diff --git a/packages/twenty-server/src/engine/core-modules/record-transformer/utils/transform-rich-text-v2.util.ts b/packages/twenty-server/src/engine/core-modules/record-transformer/utils/transform-rich-text-v2.util.ts index 7d8bc4665d..02c5da32af 100644 --- a/packages/twenty-server/src/engine/core-modules/record-transformer/utils/transform-rich-text-v2.util.ts +++ b/packages/twenty-server/src/engine/core-modules/record-transformer/utils/transform-rich-text-v2.util.ts @@ -1,5 +1,3 @@ -import { Logger } from '@nestjs/common'; - import { isNonEmptyString } from '@sniptt/guards'; import { type RichTextV2Metadata, @@ -7,35 +5,30 @@ import { } from 'twenty-shared/types'; import { isDefined } from 'twenty-shared/utils'; -const logger = new Logger('TransformRichTextV2'); +// Reuse a single ServerBlockNoteEditor across all calls to avoid +// the cost of dynamic import resolution + instance creation (~90ms) on every transform. +// eslint-disable-next-line @typescript-eslint/no-explicit-any +let cachedServerBlockNoteEditor: any = null; -const calculateInputSize = (input: unknown): number => { - if (typeof input === 'string') { - return Buffer.byteLength(input, 'utf8'); - } - if (typeof input === 'object' && input !== null) { - return Buffer.byteLength(JSON.stringify(input), 'utf8'); +const getServerBlockNoteEditor = async () => { + if (!cachedServerBlockNoteEditor) { + const { ServerBlockNoteEditor } = await import('@blocknote/server-util'); + + cachedServerBlockNoteEditor = ServerBlockNoteEditor.create(); } - return 0; + return cachedServerBlockNoteEditor; }; export const transformRichTextV2Value = async ( // eslint-disable-next-line @typescript-eslint/no-explicit-any richTextValue: any, ): Promise => { - const startTime = performance.now(); - const inputSize = calculateInputSize(richTextValue); - const parsedValue = isNonEmptyString(richTextValue) ? richTextV2ValueSchema.parse(richTextValue) : richTextValue; - const afterParsingTime = performance.now(); - - const { ServerBlockNoteEditor } = await import('@blocknote/server-util'); - - const serverBlockNoteEditor = ServerBlockNoteEditor.create(); + const serverBlockNoteEditor = await getServerBlockNoteEditor(); // Patch: Handle cases where blocknote to markdown conversion fails for certain block types (custom/code blocks) // Todo : This may be resolved once the server-utils library is updated with proper conversion support - #947 @@ -51,8 +44,6 @@ export const transformRichTextV2Value = async ( convertedMarkdown = parsedValue.blocknote || null; } - const afterMarkdownConversionTime = performance.now(); - const convertedBlocknote = parsedValue.markdown ? JSON.stringify( await serverBlockNoteEditor.tryParseMarkdownToBlocks( @@ -61,12 +52,6 @@ export const transformRichTextV2Value = async ( ) : null; - const endTime = performance.now(); - - logger.debug( - `transformRichTextV2Value completed - total: ${endTime - startTime}ms, parsing: ${afterParsingTime - startTime}ms, markdown_conversion: ${afterMarkdownConversionTime - afterParsingTime}ms, blocknote_conversion: ${endTime - afterMarkdownConversionTime}ms, size: ${inputSize} bytes`, - ); - return { markdown: parsedValue.markdown || convertedMarkdown, blocknote: parsedValue.blocknote || convertedBlocknote,