fix(richtext-lexical): migrate scripts not working due to migration hooks running during migrate script

This commit is contained in:
Alessio Gravili
2024-08-21 16:43:56 -04:00
parent af0105ced5
commit d894ac75f0
5 changed files with 38 additions and 31 deletions

View File

@@ -18,6 +18,7 @@ IMPORTANT: This will overwrite all slate data. We recommend doing the following
1. Take a backup of your entire database. If anything goes wrong and you do not have a backup, you are on your own and will not receive any support. 1. Take a backup of your entire database. If anything goes wrong and you do not have a backup, you are on your own and will not receive any support.
2. Make every richText field a lexical editor. This script will only convert lexical richText fields with old Slate data 2. Make every richText field a lexical editor. This script will only convert lexical richText fields with old Slate data
3. Add the SlateToLexicalFeature (as seen below) first, and test it out by loading up the Admin Panel, to see if the migrator works as expected. You might have to build some custom converters for some fields first in order to convert custom Slate nodes. The SlateToLexicalFeature is where the converters are stored. Only fields with this feature added will be migrated. 3. Add the SlateToLexicalFeature (as seen below) first, and test it out by loading up the Admin Panel, to see if the migrator works as expected. You might have to build some custom converters for some fields first in order to convert custom Slate nodes. The SlateToLexicalFeature is where the converters are stored. Only fields with this feature added will be migrated.
4. If this works as expected, add the `disableHooks: true` prop everywhere you're initializing `SlateToLexicalFeature`. Example: `SlateToLexicalFeature({ disableHooks: true })`. Once you did that, you're ready to run the migration script.
```ts ```ts
import { migrateSlateToLexical } from '@payloadcms/richtext-lexical/migrate' import { migrateSlateToLexical } from '@payloadcms/richtext-lexical/migrate'

View File

@@ -47,7 +47,7 @@ export function convertLexicalPluginNodesToLexical({
parentNodeType: string parentNodeType: string
quiet?: boolean quiet?: boolean
}): SerializedLexicalNode[] { }): SerializedLexicalNode[] {
if (!lexicalPluginNodes?.length) { if (!lexicalPluginNodes?.length || !converters?.length) {
return [] return []
} }
const unknownConverter = converters.find((converter) => converter.nodeTypes.includes('unknown')) const unknownConverter = converters.find((converter) => converter.nodeTypes.includes('unknown'))

View File

@@ -13,6 +13,7 @@ export type LexicalPluginToLexicalFeatureProps = {
defaultConverters: LexicalPluginNodeConverter[] defaultConverters: LexicalPluginNodeConverter[]
}) => LexicalPluginNodeConverter[]) }) => LexicalPluginNodeConverter[])
| LexicalPluginNodeConverter[] | LexicalPluginNodeConverter[]
disableHooks?: boolean
quiet?: boolean quiet?: boolean
} }
@@ -37,23 +38,25 @@ export const LexicalPluginToLexicalFeature =
return { return {
ClientFeature: '@payloadcms/richtext-lexical/client#LexicalPluginToLexicalFeatureClient', ClientFeature: '@payloadcms/richtext-lexical/client#LexicalPluginToLexicalFeatureClient',
hooks: { hooks: props.disableHooks
afterRead: [ ? undefined
({ value }) => { : {
if (!value || !('jsonContent' in value)) { afterRead: [
// incomingEditorState null or not from Lexical Plugin ({ value }) => {
return value if (!value || !('jsonContent' in value)) {
} // incomingEditorState null or not from Lexical Plugin
return value
}
// Lexical Plugin => convert to lexical // Lexical Plugin => convert to lexical
return convertLexicalPluginToLexical({ return convertLexicalPluginToLexical({
converters: props.converters as LexicalPluginNodeConverter[], converters: props.converters as LexicalPluginNodeConverter[],
lexicalPluginData: value as PayloadPluginLexicalData, lexicalPluginData: value as PayloadPluginLexicalData,
quiet: props?.quiet, quiet: props?.quiet,
}) })
},
],
}, },
],
},
nodes: [ nodes: [
{ {
node: UnknownConvertedNode, node: UnknownConvertedNode,

View File

@@ -47,7 +47,7 @@ export function convertSlateNodesToLexical({
parentNodeType: string parentNodeType: string
slateNodes: SlateNode[] slateNodes: SlateNode[]
}): SerializedLexicalNode[] { }): SerializedLexicalNode[] {
if (!converters?.length) { if (!converters?.length || !slateNodes?.length) {
return [] return []
} }
const unknownConverter = converters.find((converter) => converter.nodeTypes.includes('unknown')) const unknownConverter = converters.find((converter) => converter.nodeTypes.includes('unknown'))

View File

@@ -9,6 +9,7 @@ export type SlateToLexicalFeatureProps = {
converters?: converters?:
| (({ defaultConverters }: { defaultConverters: SlateNodeConverter[] }) => SlateNodeConverter[]) | (({ defaultConverters }: { defaultConverters: SlateNodeConverter[] }) => SlateNodeConverter[])
| SlateNodeConverter[] | SlateNodeConverter[]
disableHooks?: boolean
} }
export const SlateToLexicalFeature = createServerFeature< export const SlateToLexicalFeature = createServerFeature<
@@ -35,22 +36,24 @@ export const SlateToLexicalFeature = createServerFeature<
return { return {
ClientFeature: '@payloadcms/richtext-lexical/client#SlateToLexicalFeatureClient', ClientFeature: '@payloadcms/richtext-lexical/client#SlateToLexicalFeatureClient',
hooks: { hooks: props.disableHooks
afterRead: [ ? undefined
({ value }) => { : {
if (!value || !Array.isArray(value) || 'root' in value) { afterRead: [
// incomingEditorState null or not from Slate ({ value }) => {
return value if (!value || !Array.isArray(value) || 'root' in value) {
} // incomingEditorState null or not from Slate
return value
}
// Slate => convert to lexical // Slate => convert to lexical
return convertSlateToLexical({ return convertSlateToLexical({
converters: props.converters as SlateNodeConverter[], converters: props.converters as SlateNodeConverter[],
slateData: value, slateData: value,
}) })
},
],
}, },
],
},
nodes: [ nodes: [
{ {
node: UnknownConvertedNode, node: UnknownConvertedNode,