DocsIntegrating PuckData Migration

Data Migration

Version migrating

Puck follows semantic versioning. Major releases may introduce breaking changes for your Data payload.

Puck provides the migrate helper method to help migrate legacy data payloads to the latest data model, transforming any deprecated properties to their latest counterparts as described by the Data API reference.

import { migrate } from "@measured/puck";
 
migrate(legacyData);

Breaking changes to props

Renaming or removing the props passed to your components are considered breaking changes. Any existing Data payloads that reference these props will be unable to render.

There are two strategies for dealing with this:

  1. Retaining backwards-compatible props
  2. Implementing a prop migration

Retaining backwards-compatibility

The easiest way to avoid breaking changes is to implement your prop changes in a backwards compatible manor:

const config = {
  HeadingBlock: ({ title, heading }) => <h1>{heading || title}</h1>,
};

Implementing a prop migration

It will often be preferrable to update the underlying Data payload. Puck provides the transformProps utility method to conveniently transform the props for a given component throughout the payload.

import { transformProps } from "@measured/puck";
 
const config = {
  // Renamed `title` prop to `heading`
  HeadingBlock: ({ heading }) => <h1>{heading}</h1>,
};
 
const data = {
  content: [
    // HeadingBlock references the legacy `title` prop
    { type: "HeadingBlock", props: { title: "Hello, world" } },
  ],
};
 
const updatedData = transformProps(data, {
  // Map `heading` to the legacy `title` prop
  HeadingBlock: ({ title, ...props }) => ({ heading: title, ...props }),
});
 
console.log(updatedData);
// { content: [{ type: "HeadingBlock", props: { heading: "Hello, world" } }] };

You may choose to run this transform every time you render your content, or perform a batch operation against your database.

Example showing data being updated before rendering
import { Puck, Render, transformProps } from "@measured/puck";
 
const transforms = {
  HeadingBlock: ({ title, ...props }) => ({ heading: title, ...props }),
};
 
export const MyEditor = ({ data, config }) => (
  <Puck data={transformProps(data, transforms)} config={config} />
);
 
export const MyPage = ({ data, config }) => (
  <Render data={transformProps(data, transforms)} config={config} />
);

Further reading