From d894ac75f0526c9eced6ec0173858dd5b87f0a86 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Wed, 21 Aug 2024 16:43:56 -0400 Subject: [PATCH] fix(richtext-lexical): migrate scripts not working due to migration hooks running during migrate script --- docs/lexical/migration.mdx | 1 + .../lexicalPluginToLexical/converter/index.ts | 2 +- .../lexicalPluginToLexical/feature.server.ts | 33 ++++++++++--------- .../slateToLexical/converter/index.ts | 2 +- .../slateToLexical/feature.server.ts | 31 +++++++++-------- 5 files changed, 38 insertions(+), 31 deletions(-) diff --git a/docs/lexical/migration.mdx b/docs/lexical/migration.mdx index 880e19af7..8e0b5841c 100644 --- a/docs/lexical/migration.mdx +++ b/docs/lexical/migration.mdx @@ -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. 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. +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 import { migrateSlateToLexical } from '@payloadcms/richtext-lexical/migrate' diff --git a/packages/richtext-lexical/src/features/migrations/lexicalPluginToLexical/converter/index.ts b/packages/richtext-lexical/src/features/migrations/lexicalPluginToLexical/converter/index.ts index e17d5d4db..59081b24d 100644 --- a/packages/richtext-lexical/src/features/migrations/lexicalPluginToLexical/converter/index.ts +++ b/packages/richtext-lexical/src/features/migrations/lexicalPluginToLexical/converter/index.ts @@ -47,7 +47,7 @@ export function convertLexicalPluginNodesToLexical({ parentNodeType: string quiet?: boolean }): SerializedLexicalNode[] { - if (!lexicalPluginNodes?.length) { + if (!lexicalPluginNodes?.length || !converters?.length) { return [] } const unknownConverter = converters.find((converter) => converter.nodeTypes.includes('unknown')) diff --git a/packages/richtext-lexical/src/features/migrations/lexicalPluginToLexical/feature.server.ts b/packages/richtext-lexical/src/features/migrations/lexicalPluginToLexical/feature.server.ts index 07d5bbd89..fcdbcb003 100644 --- a/packages/richtext-lexical/src/features/migrations/lexicalPluginToLexical/feature.server.ts +++ b/packages/richtext-lexical/src/features/migrations/lexicalPluginToLexical/feature.server.ts @@ -13,6 +13,7 @@ export type LexicalPluginToLexicalFeatureProps = { defaultConverters: LexicalPluginNodeConverter[] }) => LexicalPluginNodeConverter[]) | LexicalPluginNodeConverter[] + disableHooks?: boolean quiet?: boolean } @@ -37,23 +38,25 @@ export const LexicalPluginToLexicalFeature = return { ClientFeature: '@payloadcms/richtext-lexical/client#LexicalPluginToLexicalFeatureClient', - hooks: { - afterRead: [ - ({ value }) => { - if (!value || !('jsonContent' in value)) { - // incomingEditorState null or not from Lexical Plugin - return value - } + hooks: props.disableHooks + ? undefined + : { + afterRead: [ + ({ value }) => { + if (!value || !('jsonContent' in value)) { + // incomingEditorState null or not from Lexical Plugin + return value + } - // Lexical Plugin => convert to lexical - return convertLexicalPluginToLexical({ - converters: props.converters as LexicalPluginNodeConverter[], - lexicalPluginData: value as PayloadPluginLexicalData, - quiet: props?.quiet, - }) + // Lexical Plugin => convert to lexical + return convertLexicalPluginToLexical({ + converters: props.converters as LexicalPluginNodeConverter[], + lexicalPluginData: value as PayloadPluginLexicalData, + quiet: props?.quiet, + }) + }, + ], }, - ], - }, nodes: [ { node: UnknownConvertedNode, diff --git a/packages/richtext-lexical/src/features/migrations/slateToLexical/converter/index.ts b/packages/richtext-lexical/src/features/migrations/slateToLexical/converter/index.ts index 13f4d729a..f55cee5b6 100644 --- a/packages/richtext-lexical/src/features/migrations/slateToLexical/converter/index.ts +++ b/packages/richtext-lexical/src/features/migrations/slateToLexical/converter/index.ts @@ -47,7 +47,7 @@ export function convertSlateNodesToLexical({ parentNodeType: string slateNodes: SlateNode[] }): SerializedLexicalNode[] { - if (!converters?.length) { + if (!converters?.length || !slateNodes?.length) { return [] } const unknownConverter = converters.find((converter) => converter.nodeTypes.includes('unknown')) diff --git a/packages/richtext-lexical/src/features/migrations/slateToLexical/feature.server.ts b/packages/richtext-lexical/src/features/migrations/slateToLexical/feature.server.ts index 422b36881..99711d985 100644 --- a/packages/richtext-lexical/src/features/migrations/slateToLexical/feature.server.ts +++ b/packages/richtext-lexical/src/features/migrations/slateToLexical/feature.server.ts @@ -9,6 +9,7 @@ export type SlateToLexicalFeatureProps = { converters?: | (({ defaultConverters }: { defaultConverters: SlateNodeConverter[] }) => SlateNodeConverter[]) | SlateNodeConverter[] + disableHooks?: boolean } export const SlateToLexicalFeature = createServerFeature< @@ -35,22 +36,24 @@ export const SlateToLexicalFeature = createServerFeature< return { ClientFeature: '@payloadcms/richtext-lexical/client#SlateToLexicalFeatureClient', - hooks: { - afterRead: [ - ({ value }) => { - if (!value || !Array.isArray(value) || 'root' in value) { - // incomingEditorState null or not from Slate - return value - } + hooks: props.disableHooks + ? undefined + : { + afterRead: [ + ({ value }) => { + if (!value || !Array.isArray(value) || 'root' in value) { + // incomingEditorState null or not from Slate + return value + } - // Slate => convert to lexical - return convertSlateToLexical({ - converters: props.converters as SlateNodeConverter[], - slateData: value, - }) + // Slate => convert to lexical + return convertSlateToLexical({ + converters: props.converters as SlateNodeConverter[], + slateData: value, + }) + }, + ], }, - ], - }, nodes: [ { node: UnknownConvertedNode,