From 7bfaee864a0f920c03e1f501a6ce71a4534c4d07 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Sat, 23 May 2026 17:38:47 -0700 Subject: [PATCH 01/56] cleanup!: extract hooks and schema types out of lexical index.ts, rename outputSchema to jsonSchema --- packages/payload/src/admin/RichText.ts | 2 +- .../src/utilities/configToJSONSchema.ts | 4 +- .../richtext-lexical/src/cell/rscEntry.tsx | 2 +- .../src/exports/react/index.ts | 2 +- .../src/features/blockquote/server/index.ts | 2 +- .../blocks/client/component/index.tsx | 2 +- .../blocks/client/componentInline/index.tsx | 2 +- .../blocks/client/nodes/BlocksNode.tsx | 2 +- .../blocks/client/nodes/InlineBlocksNode.tsx | 2 +- .../src/features/blocks/server/index.ts | 2 +- .../blocks/server/nodes/BlocksNode.tsx | 2 +- .../blocks/server/nodes/InlineBlocksNode.tsx | 2 +- .../converters/htmlToLexical/index.ts | 2 +- .../async/converters/blockquote.ts | 2 +- .../lexicalToHtml/async/converters/heading.ts | 2 +- .../async/converters/horizontalRule.ts | 2 +- .../async/converters/linebreak.ts | 2 +- .../lexicalToHtml/async/converters/link.ts | 2 +- .../lexicalToHtml/async/converters/list.ts | 2 +- .../async/converters/paragraph.ts | 2 +- .../lexicalToHtml/async/converters/tab.ts | 2 +- .../lexicalToHtml/async/converters/table.ts | 2 +- .../lexicalToHtml/async/converters/text.ts | 2 +- .../lexicalToHtml/async/converters/upload.ts | 2 +- .../lexicalToHtml/async/defaultConverters.ts | 2 +- .../converters/lexicalToHtml/async/types.ts | 2 +- .../shared/findConverterForNode.ts | 2 +- .../sync/converters/blockquote.ts | 2 +- .../lexicalToHtml/sync/converters/heading.ts | 2 +- .../sync/converters/horizontalRule.ts | 2 +- .../sync/converters/linebreak.ts | 2 +- .../lexicalToHtml/sync/converters/link.ts | 2 +- .../lexicalToHtml/sync/converters/list.ts | 2 +- .../sync/converters/paragraph.ts | 2 +- .../lexicalToHtml/sync/converters/tab.ts | 2 +- .../lexicalToHtml/sync/converters/table.ts | 2 +- .../lexicalToHtml/sync/converters/text.ts | 2 +- .../lexicalToHtml/sync/converters/upload.ts | 2 +- .../lexicalToHtml/sync/defaultConverters.ts | 2 +- .../converters/lexicalToHtml/sync/types.ts | 2 +- .../lexicalToJSX/Component/index.tsx | 4 +- .../converter/converters/blockquote.tsx | 2 +- .../converter/converters/heading.tsx | 2 +- .../converter/converters/horizontalRule.tsx | 2 +- .../converter/converters/linebreak.tsx | 2 +- .../converter/converters/link.tsx | 2 +- .../converter/converters/list.tsx | 2 +- .../converter/converters/paragraph.tsx | 2 +- .../lexicalToJSX/converter/converters/tab.tsx | 2 +- .../converter/converters/table.tsx | 2 +- .../converter/converters/text.tsx | 2 +- .../converter/converters/upload.tsx | 2 +- .../converter/defaultConverters.ts | 2 +- .../lexicalToJSX/converter/index.tsx | 4 +- .../lexicalToJSX/converter/types.ts | 2 +- .../convertLexicalToPlaintext.spec.ts | 2 +- .../shared/findConverterForNode.ts | 2 +- .../lexicalToPlaintext/sync/types.ts | 2 +- .../converters/markdownToLexical/index.ts | 2 +- .../experimental_table/server/index.ts | 2 +- .../src/features/heading/server/index.ts | 2 +- .../server/nodes/HorizontalRuleNode.tsx | 2 +- .../src/features/link/nodes/types.ts | 2 +- .../src/features/lists/plugin/index.tsx | 2 +- .../server/nodes/RelationshipNode.tsx | 2 +- .../src/features/toolbars/types.ts | 2 +- .../src/features/typesClient.ts | 2 +- .../src/features/typesServer.ts | 6 +- .../upload/server/nodes/UploadNode.tsx | 2 +- .../src/field/Diff/converters/link.ts | 2 +- .../field/Diff/converters/listitem/index.tsx | 2 +- .../Diff/converters/relationship/index.tsx | 2 +- .../field/Diff/converters/unknown/index.tsx | 2 +- .../field/Diff/converters/upload/index.tsx | 2 +- .../richtext-lexical/src/field/Diff/index.tsx | 2 +- packages/richtext-lexical/src/field/Field.tsx | 2 +- .../src/field/RenderLexical/index.tsx | 4 +- .../src/field/RichTextViewProvider.tsx | 2 +- packages/richtext-lexical/src/field/index.tsx | 2 +- .../richtext-lexical/src/field/rscEntry.tsx | 2 +- packages/richtext-lexical/src/hooks.ts | 631 +++++++++++++++ packages/richtext-lexical/src/index.ts | 736 +----------------- .../src/lexical/LexicalProvider.tsx | 2 +- .../config/client/EditorConfigProvider.tsx | 2 +- .../src/lexical/config/client/loader.ts | 2 +- .../src/lexical/config/client/sanitize.ts | 2 +- .../src/lexical/config/server/sanitize.ts | 6 +- .../src/lexical/config/types.ts | 2 +- .../src/lexical/nodes/index.ts | 2 +- .../LexicalTypeaheadMenuPlugin/types.ts | 2 +- .../populateLexicalPopulationPromises.ts | 2 +- .../src/{types.ts => types/index.ts} | 16 +- .../src/{ => types}/nodeTypes.ts | 20 +- packages/richtext-lexical/src/types/schema.ts | 90 +++ .../src/utilities/buildEditorState.ts | 6 +- .../src/utilities/buildInitialState.ts | 2 +- .../src/utilities/createClientFeature.ts | 2 +- .../src/utilities/editorConfigFactory.ts | 2 +- .../src/utilities/generateImportMap.tsx | 2 +- .../src/utilities/initLexicalFeatures.ts | 2 +- .../upgradeDocumentFieldsRecursively.ts | 2 +- 101 files changed, 863 insertions(+), 842 deletions(-) create mode 100644 packages/richtext-lexical/src/hooks.ts rename packages/richtext-lexical/src/{types.ts => types/index.ts} (96%) rename packages/richtext-lexical/src/{ => types}/nodeTypes.ts (86%) create mode 100644 packages/richtext-lexical/src/types/schema.ts diff --git a/packages/payload/src/admin/RichText.ts b/packages/payload/src/admin/RichText.ts index d139dc2000f..9c318d3e667 100644 --- a/packages/payload/src/admin/RichText.ts +++ b/packages/payload/src/admin/RichText.ts @@ -249,7 +249,7 @@ type RichTextAdapterBase< * `json-schema-to-typescript` which is used to generate types for this richtext field * payload-types.ts) */ - outputSchema?: (args: { + jsonSchema?: (args: { collectionIDFieldTypes: { [key: string]: 'number' | 'string' } config?: SanitizedConfig field: RichTextField diff --git a/packages/payload/src/utilities/configToJSONSchema.ts b/packages/payload/src/utilities/configToJSONSchema.ts index 7234a9615b6..5de17f5094d 100644 --- a/packages/payload/src/utilities/configToJSONSchema.ts +++ b/packages/payload/src/utilities/configToJSONSchema.ts @@ -734,10 +734,10 @@ export function fieldsToJSONSchema( if (typeof field.editor === 'function') { throw new Error('Attempted to access unsanitized rich text editor.') } - if (field.editor.outputSchema) { + if (field.editor.jsonSchema) { fieldSchema = { ...baseFieldSchema, - ...field.editor.outputSchema({ + ...field.editor.jsonSchema({ collectionIDFieldTypes, config, field, diff --git a/packages/richtext-lexical/src/cell/rscEntry.tsx b/packages/richtext-lexical/src/cell/rscEntry.tsx index 5e705961727..76a750b28c5 100644 --- a/packages/richtext-lexical/src/cell/rscEntry.tsx +++ b/packages/richtext-lexical/src/cell/rscEntry.tsx @@ -5,7 +5,7 @@ import { Link } from '@payloadcms/ui' import { formatAdminURL } from 'payload/shared' import React from 'react' -import type { LexicalRichTextCellProps } from '../types.js' +import type { LexicalRichTextCellProps } from '../types/index.js' function recurseEditorState( editorState: SerializedLexicalNode[], diff --git a/packages/richtext-lexical/src/exports/react/index.ts b/packages/richtext-lexical/src/exports/react/index.ts index 33f18285ac7..adac7c487fc 100644 --- a/packages/richtext-lexical/src/exports/react/index.ts +++ b/packages/richtext-lexical/src/exports/react/index.ts @@ -32,4 +32,4 @@ export type { ViewMapBlockComponentProps, ViewMapBlockEditorProps, ViewMapBlockJSXConverterProps, -} from '../../types.js' +} from '../../types/index.js' diff --git a/packages/richtext-lexical/src/features/blockquote/server/index.ts b/packages/richtext-lexical/src/features/blockquote/server/index.ts index 9b68d6489a6..add401d88e8 100644 --- a/packages/richtext-lexical/src/features/blockquote/server/index.ts +++ b/packages/richtext-lexical/src/features/blockquote/server/index.ts @@ -3,7 +3,7 @@ import type { SerializedLexicalNode } from 'lexical' import { QuoteNode } from '@lexical/rich-text' -import type { StronglyTypedElementNode } from '../../../nodeTypes.js' +import type { StronglyTypedElementNode } from '../../../types/nodeTypes.js' import { createServerFeature } from '../../../utilities/createServerFeature.js' import { createNode } from '../../typeUtilities.js' diff --git a/packages/richtext-lexical/src/features/blocks/client/component/index.tsx b/packages/richtext-lexical/src/features/blocks/client/component/index.tsx index 7fe472c942f..43143e8ab51 100644 --- a/packages/richtext-lexical/src/features/blocks/client/component/index.tsx +++ b/packages/richtext-lexical/src/features/blocks/client/component/index.tsx @@ -39,7 +39,7 @@ import { deepCopyObjectSimpleWithoutReactComponents, reduceFieldsToValues } from import React, { useCallback, useEffect, useMemo, useRef } from 'react' import { v4 as uuid } from 'uuid' -import type { ViewMapBlockComponentProps } from '../../../../types.js' +import type { ViewMapBlockComponentProps } from '../../../../types/index.js' import type { BlockFields } from '../../server/nodes/BlocksNode.js' import './index.css' diff --git a/packages/richtext-lexical/src/features/blocks/client/componentInline/index.tsx b/packages/richtext-lexical/src/features/blocks/client/componentInline/index.tsx index 32c75435641..c63047f856e 100644 --- a/packages/richtext-lexical/src/features/blocks/client/componentInline/index.tsx +++ b/packages/richtext-lexical/src/features/blocks/client/componentInline/index.tsx @@ -30,7 +30,7 @@ import { deepCopyObjectSimpleWithoutReactComponents, reduceFieldsToValues } from import React, { createContext, useCallback, useEffect, useMemo, useRef } from 'react' import { v4 as uuid } from 'uuid' -import type { ViewMapInlineBlockComponentProps } from '../../../../types.js' +import type { ViewMapInlineBlockComponentProps } from '../../../../types/index.js' import type { InlineBlockFields } from '../../server/nodes/InlineBlocksNode.js' import type { BlockComponentProps } from '../component/index.js' diff --git a/packages/richtext-lexical/src/features/blocks/client/nodes/BlocksNode.tsx b/packages/richtext-lexical/src/features/blocks/client/nodes/BlocksNode.tsx index fb591515c95..85a64ae15f5 100644 --- a/packages/richtext-lexical/src/features/blocks/client/nodes/BlocksNode.tsx +++ b/packages/richtext-lexical/src/features/blocks/client/nodes/BlocksNode.tsx @@ -8,7 +8,7 @@ import { } from 'lexical' import React, { type JSX } from 'react' -import type { ViewMapBlockComponentProps } from '../../../../types.js' +import type { ViewMapBlockComponentProps } from '../../../../types/index.js' import type { BlockFieldsOptionalID, SerializedBlockNode } from '../../server/nodes/BlocksNode.js' import { ServerBlockNode } from '../../server/nodes/BlocksNode.js' diff --git a/packages/richtext-lexical/src/features/blocks/client/nodes/InlineBlocksNode.tsx b/packages/richtext-lexical/src/features/blocks/client/nodes/InlineBlocksNode.tsx index 7a82c54b738..ec32fb10d0f 100644 --- a/packages/richtext-lexical/src/features/blocks/client/nodes/InlineBlocksNode.tsx +++ b/packages/richtext-lexical/src/features/blocks/client/nodes/InlineBlocksNode.tsx @@ -8,7 +8,7 @@ import { } from 'lexical' import React, { type JSX } from 'react' -import type { ViewMapInlineBlockComponentProps } from '../../../../types.js' +import type { ViewMapInlineBlockComponentProps } from '../../../../types/index.js' import type { InlineBlockFields, SerializedInlineBlockNode, diff --git a/packages/richtext-lexical/src/features/blocks/server/index.ts b/packages/richtext-lexical/src/features/blocks/server/index.ts index effc4975f6e..6f3ddab845b 100644 --- a/packages/richtext-lexical/src/features/blocks/server/index.ts +++ b/packages/richtext-lexical/src/features/blocks/server/index.ts @@ -88,7 +88,7 @@ export const BlocksFeature = createServerFeature = { /** Block form data */ diff --git a/packages/richtext-lexical/src/features/blocks/server/nodes/InlineBlocksNode.tsx b/packages/richtext-lexical/src/features/blocks/server/nodes/InlineBlocksNode.tsx index c2587f7e911..5611562100e 100644 --- a/packages/richtext-lexical/src/features/blocks/server/nodes/InlineBlocksNode.tsx +++ b/packages/richtext-lexical/src/features/blocks/server/nodes/InlineBlocksNode.tsx @@ -15,7 +15,7 @@ import { addClassNamesToElement } from '@lexical/utils' import ObjectID from 'bson-objectid' import { $applyNodeReplacement, DecoratorNode } from 'lexical' -import type { StronglyTypedLeafNode } from '../../../../nodeTypes.js' +import type { StronglyTypedLeafNode } from '../../../../types/nodeTypes.js' export type InlineBlockFields = { blockType: string diff --git a/packages/richtext-lexical/src/features/converters/htmlToLexical/index.ts b/packages/richtext-lexical/src/features/converters/htmlToLexical/index.ts index cbafa7d41f7..115b7276d8b 100644 --- a/packages/richtext-lexical/src/features/converters/htmlToLexical/index.ts +++ b/packages/richtext-lexical/src/features/converters/htmlToLexical/index.ts @@ -2,7 +2,7 @@ import { createHeadlessEditor } from '@lexical/headless' import { $getRoot, $getSelection, type SerializedLexicalNode } from 'lexical' import type { SanitizedServerEditorConfig } from '../../../lexical/config/types.js' -import type { DefaultNodeTypes, TypedEditorState } from '../../../nodeTypes.js' +import type { DefaultNodeTypes, TypedEditorState } from '../../../types/nodeTypes.js' import { getEnabledNodes } from '../../../lexical/nodes/index.js' import { $generateNodesFromDOM } from '../../../lexical-proxy/@lexical-html.js' diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/blockquote.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/blockquote.ts index 4c012504100..bbb5243adbe 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/blockquote.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/blockquote.ts @@ -1,4 +1,4 @@ -import type { SerializedQuoteNode } from '../../../../../nodeTypes.js' +import type { SerializedQuoteNode } from '../../../../../types/nodeTypes.js' import type { HTMLConvertersAsync } from '../types.js' export const BlockquoteHTMLConverterAsync: HTMLConvertersAsync = { diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/heading.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/heading.ts index f0fcc8d0b49..876f046cfc2 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/heading.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/heading.ts @@ -1,4 +1,4 @@ -import type { SerializedHeadingNode } from '../../../../../nodeTypes.js' +import type { SerializedHeadingNode } from '../../../../../types/nodeTypes.js' import type { HTMLConvertersAsync } from '../types.js' const ALLOWED_HEADING_TAGS = new Set(['h1', 'h2', 'h3', 'h4', 'h5', 'h6']) diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/horizontalRule.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/horizontalRule.ts index 5d3c96c34ae..8c71a10bf4d 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/horizontalRule.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/horizontalRule.ts @@ -1,4 +1,4 @@ -import type { SerializedHorizontalRuleNode } from '../../../../../nodeTypes.js' +import type { SerializedHorizontalRuleNode } from '../../../../../types/nodeTypes.js' import type { HTMLConvertersAsync } from '../types.js' export const HorizontalRuleHTMLConverterAsync: HTMLConvertersAsync = { horizontalrule: '
', diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/linebreak.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/linebreak.ts index 148b4cbad22..ca020646212 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/linebreak.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/linebreak.ts @@ -1,4 +1,4 @@ -import type { SerializedLineBreakNode } from '../../../../../nodeTypes.js' +import type { SerializedLineBreakNode } from '../../../../../types/nodeTypes.js' import type { HTMLConvertersAsync } from '../types.js' export const LinebreakHTMLConverterAsync: HTMLConvertersAsync = { diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/link.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/link.ts index 584795d2caa..e897ad1c2c5 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/link.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/link.ts @@ -1,7 +1,7 @@ import escapeHTML from 'escape-html' import { sanitizeUrl } from 'payload/shared' -import type { SerializedAutoLinkNode, SerializedLinkNode } from '../../../../../nodeTypes.js' +import type { SerializedAutoLinkNode, SerializedLinkNode } from '../../../../../types/nodeTypes.js' import type { HTMLConvertersAsync, HTMLPopulateFn } from '../types.js' export const LinkHTMLConverterAsync: (args: { diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/list.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/list.ts index b441dd5d3eb..e6de2ef2360 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/list.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/list.ts @@ -1,6 +1,6 @@ import { v4 as uuidv4 } from 'uuid' -import type { SerializedListItemNode, SerializedListNode } from '../../../../../nodeTypes.js' +import type { SerializedListItemNode, SerializedListNode } from '../../../../../types/nodeTypes.js' import type { HTMLConvertersAsync } from '../types.js' const ALLOWED_LIST_TAGS = new Set(['ol', 'ul']) diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/paragraph.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/paragraph.ts index 8db85b674bc..0beea8314de 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/paragraph.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/paragraph.ts @@ -1,4 +1,4 @@ -import type { SerializedParagraphNode } from '../../../../../nodeTypes.js' +import type { SerializedParagraphNode } from '../../../../../types/nodeTypes.js' import type { HTMLConvertersAsync } from '../types.js' export const ParagraphHTMLConverterAsync: HTMLConvertersAsync = { diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/tab.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/tab.ts index 1c68e9a747d..d026974dfb2 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/tab.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/tab.ts @@ -1,4 +1,4 @@ -import type { SerializedTabNode } from '../../../../../nodeTypes.js' +import type { SerializedTabNode } from '../../../../../types/nodeTypes.js' import type { HTMLConvertersAsync } from '../types.js' export const TabHTMLConverterAsync: HTMLConvertersAsync = { diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/table.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/table.ts index b7210b17314..f69d1697bbd 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/table.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/table.ts @@ -2,7 +2,7 @@ import type { SerializedTableCellNode, SerializedTableNode, SerializedTableRowNode, -} from '../../../../../nodeTypes.js' +} from '../../../../../types/nodeTypes.js' import type { HTMLConvertersAsync } from '../types.js' import { isSafeCssColor } from '../../shared/cssColors.js' diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/text.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/text.ts index 1f60da4a496..ee0f3a736e1 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/text.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/text.ts @@ -1,6 +1,6 @@ import escapeHTML from 'escape-html' -import type { SerializedTextNode } from '../../../../../nodeTypes.js' +import type { SerializedTextNode } from '../../../../../types/nodeTypes.js' import type { HTMLConvertersAsync } from '../types.js' import { NodeFormat } from '../../../../../lexical/utils/nodeFormat.js' diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/upload.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/upload.ts index 2d749a809a1..c1f0f0af52f 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/upload.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/upload.ts @@ -2,7 +2,7 @@ import type { FileData, FileSize, TypeWithID } from 'payload' import escapeHTML from 'escape-html' -import type { SerializedUploadNode } from '../../../../../nodeTypes.js' +import type { SerializedUploadNode } from '../../../../../types/nodeTypes.js' import type { UploadDataImproved } from '../../../../upload/server/nodes/UploadNode.js' import type { HTMLConvertersAsync } from '../types.js' diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/defaultConverters.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/defaultConverters.ts index 2ff3650dcb8..97357b8b667 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/defaultConverters.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/defaultConverters.ts @@ -1,4 +1,4 @@ -import type { DefaultNodeTypes } from '../../../../nodeTypes.js' +import type { DefaultNodeTypes } from '../../../../types/nodeTypes.js' import type { HTMLConvertersAsync } from './types.js' import { BlockquoteHTMLConverterAsync } from './converters/blockquote.js' diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/types.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/types.ts index 8a9fafd972f..dccb32a1a45 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/types.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/types.ts @@ -5,7 +5,7 @@ import type { DefaultNodeTypes, SerializedBlockNode, SerializedInlineBlockNode, -} from '../../../../nodeTypes.js' +} from '../../../../types/nodeTypes.js' import type { SerializedLexicalNodeWithParent } from '../shared/types.js' export type HTMLPopulateArguments = { collectionSlug: string diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/shared/findConverterForNode.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/shared/findConverterForNode.ts index ebc1e793cd4..7c33c3b4d95 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/shared/findConverterForNode.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/shared/findConverterForNode.ts @@ -1,7 +1,7 @@ /* eslint-disable no-console */ import type { SerializedLexicalNode } from 'lexical' -import type { SerializedBlockNode, SerializedInlineBlockNode } from '../../../../nodeTypes.js' +import type { SerializedBlockNode, SerializedInlineBlockNode } from '../../../../types/nodeTypes.js' import type { HTMLConverterAsync, HTMLConvertersAsync } from '../async/types.js' import type { HTMLConverter, HTMLConverters } from '../sync/types.js' import type { ProvidedCSS } from './types.js' diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/blockquote.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/blockquote.ts index 56b69844d95..18b8309cad1 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/blockquote.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/blockquote.ts @@ -1,4 +1,4 @@ -import type { SerializedQuoteNode } from '../../../../../nodeTypes.js' +import type { SerializedQuoteNode } from '../../../../../types/nodeTypes.js' import type { HTMLConverters } from '../types.js' export const BlockquoteHTMLConverter: HTMLConverters = { diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/heading.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/heading.ts index edd42cd4654..fda01585220 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/heading.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/heading.ts @@ -1,4 +1,4 @@ -import type { SerializedHeadingNode } from '../../../../../nodeTypes.js' +import type { SerializedHeadingNode } from '../../../../../types/nodeTypes.js' import type { HTMLConverters } from '../types.js' const ALLOWED_HEADING_TAGS = new Set(['h1', 'h2', 'h3', 'h4', 'h5', 'h6']) diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/horizontalRule.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/horizontalRule.ts index eb0c3788b26..8d39d78edb6 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/horizontalRule.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/horizontalRule.ts @@ -1,4 +1,4 @@ -import type { SerializedHorizontalRuleNode } from '../../../../../nodeTypes.js' +import type { SerializedHorizontalRuleNode } from '../../../../../types/nodeTypes.js' import type { HTMLConverters } from '../types.js' export const HorizontalRuleHTMLConverter: HTMLConverters = { horizontalrule: '
', diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/linebreak.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/linebreak.ts index 76dc5b80fec..0fe9dabbd67 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/linebreak.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/linebreak.ts @@ -1,4 +1,4 @@ -import type { SerializedLineBreakNode } from '../../../../../nodeTypes.js' +import type { SerializedLineBreakNode } from '../../../../../types/nodeTypes.js' import type { HTMLConverters } from '../types.js' export const LinebreakHTMLConverter: HTMLConverters = { diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/link.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/link.ts index b7c323f400a..2e73535a2db 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/link.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/link.ts @@ -1,7 +1,7 @@ import escapeHTML from 'escape-html' import { sanitizeUrl } from 'payload/shared' -import type { SerializedAutoLinkNode, SerializedLinkNode } from '../../../../../nodeTypes.js' +import type { SerializedAutoLinkNode, SerializedLinkNode } from '../../../../../types/nodeTypes.js' import type { HTMLConverters } from '../types.js' export const LinkHTMLConverter: (args: { diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/list.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/list.ts index bfb1077dacb..c2fc97fc7a7 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/list.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/list.ts @@ -1,6 +1,6 @@ import { v4 as uuidv4 } from 'uuid' -import type { SerializedListItemNode, SerializedListNode } from '../../../../../nodeTypes.js' +import type { SerializedListItemNode, SerializedListNode } from '../../../../../types/nodeTypes.js' import type { HTMLConverters } from '../types.js' const ALLOWED_LIST_TAGS = new Set(['ol', 'ul']) diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/paragraph.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/paragraph.ts index 1065e692048..b57037681e5 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/paragraph.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/paragraph.ts @@ -1,4 +1,4 @@ -import type { SerializedParagraphNode } from '../../../../../nodeTypes.js' +import type { SerializedParagraphNode } from '../../../../../types/nodeTypes.js' import type { HTMLConverters } from '../types.js' export const ParagraphHTMLConverter: HTMLConverters = { diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/tab.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/tab.ts index da70ac94197..b808c7bd242 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/tab.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/tab.ts @@ -1,4 +1,4 @@ -import type { SerializedTabNode } from '../../../../../nodeTypes.js' +import type { SerializedTabNode } from '../../../../../types/nodeTypes.js' import type { HTMLConverters } from '../types.js' export const TabHTMLConverter: HTMLConverters = { diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/table.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/table.ts index 7c4518b9785..5351e9515d6 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/table.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/table.ts @@ -2,7 +2,7 @@ import type { SerializedTableCellNode, SerializedTableNode, SerializedTableRowNode, -} from '../../../../../nodeTypes.js' +} from '../../../../../types/nodeTypes.js' import type { HTMLConverters } from '../types.js' import { isSafeCssColor } from '../../shared/cssColors.js' diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/text.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/text.ts index 3c40c608820..fc6bcf2c358 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/text.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/text.ts @@ -1,6 +1,6 @@ import escapeHTML from 'escape-html' -import type { SerializedTextNode } from '../../../../../nodeTypes.js' +import type { SerializedTextNode } from '../../../../../types/nodeTypes.js' import type { HTMLConverters } from '../types.js' import { NodeFormat } from '../../../../../lexical/utils/nodeFormat.js' diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/upload.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/upload.ts index f38ca1d1192..8381cf5eb4a 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/upload.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/upload.ts @@ -2,7 +2,7 @@ import type { FileData, FileSize, TypeWithID } from 'payload' import escapeHTML from 'escape-html' -import type { SerializedUploadNode } from '../../../../../nodeTypes.js' +import type { SerializedUploadNode } from '../../../../../types/nodeTypes.js' import type { UploadDataImproved } from '../../../../upload/server/nodes/UploadNode.js' import type { HTMLConverters } from '../types.js' diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/defaultConverters.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/defaultConverters.ts index d9f1913ea35..e65dd832e39 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/defaultConverters.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/defaultConverters.ts @@ -1,4 +1,4 @@ -import type { DefaultNodeTypes } from '../../../../nodeTypes.js' +import type { DefaultNodeTypes } from '../../../../types/nodeTypes.js' import type { HTMLConverters } from './types.js' import { BlockquoteHTMLConverter } from './converters/blockquote.js' diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/types.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/types.ts index 0cca0c2bc4a..e5f1926402d 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/types.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/types.ts @@ -4,7 +4,7 @@ import type { DefaultNodeTypes, SerializedBlockNode, SerializedInlineBlockNode, -} from '../../../../nodeTypes.js' +} from '../../../../types/nodeTypes.js' import type { SerializedLexicalNodeWithParent } from '../shared/types.js' export type HTMLConverter = diff --git a/packages/richtext-lexical/src/features/converters/lexicalToJSX/Component/index.tsx b/packages/richtext-lexical/src/features/converters/lexicalToJSX/Component/index.tsx index 09c2499eb59..d94e60460fe 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToJSX/Component/index.tsx +++ b/packages/richtext-lexical/src/features/converters/lexicalToJSX/Component/index.tsx @@ -1,11 +1,11 @@ import React from 'react' +import type { SerializedNodeBase } from '../../../../types/index.js' import type { DefaultNodeTypes, SerializedBlockNode, SerializedInlineBlockNode, -} from '../../../../nodeTypes.js' -import type { SerializedNodeBase } from '../../../../types.js' +} from '../../../../types/nodeTypes.js' import type { JSXConverters } from '../converter/types.js' import { defaultJSXConverters } from '../converter/defaultConverters.js' diff --git a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/blockquote.tsx b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/blockquote.tsx index 2440195c625..cbdc6dcddc7 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/blockquote.tsx +++ b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/blockquote.tsx @@ -1,4 +1,4 @@ -import type { SerializedQuoteNode } from '../../../../../nodeTypes.js' +import type { SerializedQuoteNode } from '../../../../../types/nodeTypes.js' import type { JSXConverters } from '../types.js' export const BlockquoteJSXConverter: JSXConverters = { diff --git a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/heading.tsx b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/heading.tsx index a9f62892345..f4fbdb380df 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/heading.tsx +++ b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/heading.tsx @@ -1,4 +1,4 @@ -import type { SerializedHeadingNode } from '../../../../../nodeTypes.js' +import type { SerializedHeadingNode } from '../../../../../types/nodeTypes.js' import type { JSXConverters } from '../types.js' export const HeadingJSXConverter: JSXConverters = { diff --git a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/horizontalRule.tsx b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/horizontalRule.tsx index 7370a08ac36..2d331c29693 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/horizontalRule.tsx +++ b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/horizontalRule.tsx @@ -1,4 +1,4 @@ -import type { SerializedHorizontalRuleNode } from '../../../../../nodeTypes.js' +import type { SerializedHorizontalRuleNode } from '../../../../../types/nodeTypes.js' import type { JSXConverters } from '../types.js' export const HorizontalRuleJSXConverter: JSXConverters = { horizontalrule:
, diff --git a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/linebreak.tsx b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/linebreak.tsx index 1261ca5bff2..f06f1e78b54 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/linebreak.tsx +++ b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/linebreak.tsx @@ -1,4 +1,4 @@ -import type { SerializedLineBreakNode } from '../../../../../nodeTypes.js' +import type { SerializedLineBreakNode } from '../../../../../types/nodeTypes.js' import type { JSXConverters } from '../types.js' export const LinebreakJSXConverter: JSXConverters = { diff --git a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/link.tsx b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/link.tsx index 6c8fe655303..840f560d02d 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/link.tsx +++ b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/link.tsx @@ -1,4 +1,4 @@ -import type { SerializedAutoLinkNode, SerializedLinkNode } from '../../../../../nodeTypes.js' +import type { SerializedAutoLinkNode, SerializedLinkNode } from '../../../../../types/nodeTypes.js' import type { JSXConverters } from '../types.js' export const LinkJSXConverter: (args: { diff --git a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/list.tsx b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/list.tsx index 7c538a959c1..98b56a3ebef 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/list.tsx +++ b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/list.tsx @@ -1,6 +1,6 @@ import { v4 as uuidv4 } from 'uuid' -import type { SerializedListItemNode, SerializedListNode } from '../../../../../nodeTypes.js' +import type { SerializedListItemNode, SerializedListNode } from '../../../../../types/nodeTypes.js' import type { JSXConverters } from '../types.js' export const ListJSXConverter: JSXConverters = { diff --git a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/paragraph.tsx b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/paragraph.tsx index 1b7814cd563..4071a664a7d 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/paragraph.tsx +++ b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/paragraph.tsx @@ -1,4 +1,4 @@ -import type { SerializedParagraphNode } from '../../../../../nodeTypes.js' +import type { SerializedParagraphNode } from '../../../../../types/nodeTypes.js' import type { JSXConverters } from '../types.js' export const ParagraphJSXConverter: JSXConverters = { diff --git a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/tab.tsx b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/tab.tsx index ccc70b4824e..4b8f6c0a275 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/tab.tsx +++ b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/tab.tsx @@ -1,4 +1,4 @@ -import type { SerializedTabNode } from '../../../../../nodeTypes.js' +import type { SerializedTabNode } from '../../../../../types/nodeTypes.js' import type { JSXConverters } from '../types.js' export const TabJSXConverter: JSXConverters = { diff --git a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/table.tsx b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/table.tsx index 6c3ebc50b35..763b4b1d5c0 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/table.tsx +++ b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/table.tsx @@ -2,7 +2,7 @@ import type { SerializedTableCellNode, SerializedTableNode, SerializedTableRowNode, -} from '../../../../../nodeTypes.js' +} from '../../../../../types/nodeTypes.js' import type { JSXConverters } from '../types.js' export const TableJSXConverter: JSXConverters< diff --git a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/text.tsx b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/text.tsx index 4dfe7a2a4ef..6ceea223bb9 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/text.tsx +++ b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/text.tsx @@ -1,6 +1,6 @@ import React from 'react' -import type { SerializedTextNode } from '../../../../../nodeTypes.js' +import type { SerializedTextNode } from '../../../../../types/nodeTypes.js' import type { JSXConverters } from '../types.js' import { NodeFormat } from '../../../../../lexical/utils/nodeFormat.js' diff --git a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/upload.tsx b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/upload.tsx index 2a9bc7e0e67..6a3070ade10 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/upload.tsx +++ b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/upload.tsx @@ -1,6 +1,6 @@ import type { FileData, FileSize, TypeWithID } from 'payload' -import type { SerializedUploadNode } from '../../../../../nodeTypes.js' +import type { SerializedUploadNode } from '../../../../../types/nodeTypes.js' import type { UploadDataImproved } from '../../../../upload/server/nodes/UploadNode.js' import type { JSXConverters } from '../types.js' diff --git a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/defaultConverters.ts b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/defaultConverters.ts index f00439be97c..96481003a97 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/defaultConverters.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/defaultConverters.ts @@ -1,4 +1,4 @@ -import type { DefaultNodeTypes } from '../../../../nodeTypes.js' +import type { DefaultNodeTypes } from '../../../../types/nodeTypes.js' import type { JSXConverters } from './types.js' import { BlockquoteJSXConverter } from './converters/blockquote.js' diff --git a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/index.tsx b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/index.tsx index d75bb3f3826..cf94b67d8b6 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/index.tsx +++ b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/index.tsx @@ -3,14 +3,14 @@ import type { SerializedEditorState, SerializedLexicalNode } from 'lexical' import React from 'react' -import type { SerializedBlockNode, SerializedInlineBlockNode } from '../../../../nodeTypes.js' import type { LexicalEditorNodeMap, NodeMapBlockValue, NodeMapValue, SerializedNodeBase, ViewMapBlockJSXConverterProps, -} from '../../../../types.js' +} from '../../../../types/index.js' +import type { SerializedBlockNode, SerializedInlineBlockNode } from '../../../../types/nodeTypes.js' import type { JSXConverter, JSXConverters, SerializedLexicalNodeWithParent } from './types.js' import { hasText } from '../../../../validate/hasText.js' diff --git a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/types.ts b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/types.ts index c06016f4855..61304833d1b 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/types.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/types.ts @@ -4,7 +4,7 @@ import type { DefaultNodeTypes, SerializedBlockNode, SerializedInlineBlockNode, -} from '../../../../nodeTypes.js' +} from '../../../../types/nodeTypes.js' export type JSXConverterArgs< TNode extends { [key: string]: any; type?: string } = SerializedLexicalNode, diff --git a/packages/richtext-lexical/src/features/converters/lexicalToPlaintext/convertLexicalToPlaintext.spec.ts b/packages/richtext-lexical/src/features/converters/lexicalToPlaintext/convertLexicalToPlaintext.spec.ts index 0c27342a514..6395cf7a994 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToPlaintext/convertLexicalToPlaintext.spec.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToPlaintext/convertLexicalToPlaintext.spec.ts @@ -12,7 +12,7 @@ import type { SerializedTableRowNode, SerializedTableNode, SerializedTableCellNode, -} from '../../../nodeTypes.js' +} from '../../../types/nodeTypes.js' import { convertLexicalToPlaintext } from './sync/index.js' function textNode(text: string, bold?: boolean): SerializedTextNode { diff --git a/packages/richtext-lexical/src/features/converters/lexicalToPlaintext/shared/findConverterForNode.ts b/packages/richtext-lexical/src/features/converters/lexicalToPlaintext/shared/findConverterForNode.ts index 1db49a65bb2..122b1075ce2 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToPlaintext/shared/findConverterForNode.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToPlaintext/shared/findConverterForNode.ts @@ -1,6 +1,6 @@ import type { SerializedLexicalNode } from 'lexical' -import type { SerializedBlockNode, SerializedInlineBlockNode } from '../../../../nodeTypes.js' +import type { SerializedBlockNode, SerializedInlineBlockNode } from '../../../../types/nodeTypes.js' import type { PlaintextConverter, PlaintextConverters } from '../sync/types.js' export function findConverterForNode< diff --git a/packages/richtext-lexical/src/features/converters/lexicalToPlaintext/sync/types.ts b/packages/richtext-lexical/src/features/converters/lexicalToPlaintext/sync/types.ts index 5f80af25ec7..b8bf5c21cae 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToPlaintext/sync/types.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToPlaintext/sync/types.ts @@ -4,7 +4,7 @@ import type { DefaultNodeTypes, SerializedBlockNode, SerializedInlineBlockNode, -} from '../../../../nodeTypes.js' +} from '../../../../types/nodeTypes.js' import type { SerializedLexicalNodeWithParent } from '../shared/types.js' export type PlaintextConverter< diff --git a/packages/richtext-lexical/src/features/converters/markdownToLexical/index.ts b/packages/richtext-lexical/src/features/converters/markdownToLexical/index.ts index 11803803b42..c0945e5b800 100644 --- a/packages/richtext-lexical/src/features/converters/markdownToLexical/index.ts +++ b/packages/richtext-lexical/src/features/converters/markdownToLexical/index.ts @@ -3,7 +3,7 @@ import type { SerializedLexicalNode } from 'lexical' import { createHeadlessEditor } from '@lexical/headless' import type { SanitizedServerEditorConfig } from '../../../lexical/config/types.js' -import type { DefaultNodeTypes, TypedEditorState } from '../../../nodeTypes.js' +import type { DefaultNodeTypes, TypedEditorState } from '../../../types/nodeTypes.js' import { getEnabledNodes } from '../../../lexical/nodes/index.js' import { $convertFromMarkdownString } from '../../../packages/@lexical/markdown/index.js' diff --git a/packages/richtext-lexical/src/features/experimental_table/server/index.ts b/packages/richtext-lexical/src/features/experimental_table/server/index.ts index 2cea887538f..316a2cf402b 100644 --- a/packages/richtext-lexical/src/features/experimental_table/server/index.ts +++ b/packages/richtext-lexical/src/features/experimental_table/server/index.ts @@ -9,7 +9,7 @@ import type { Config, Field, FieldSchemaMap } from 'payload' import { TableCellNode, TableNode, TableRowNode } from '@lexical/table' import { sanitizeFields } from 'payload' -import type { StronglyTypedElementNode } from '../../../nodeTypes.js' +import type { StronglyTypedElementNode } from '../../../types/nodeTypes.js' import { createServerFeature } from '../../../utilities/createServerFeature.js' import { createNode } from '../../typeUtilities.js' diff --git a/packages/richtext-lexical/src/features/heading/server/index.ts b/packages/richtext-lexical/src/features/heading/server/index.ts index 0e226f4131e..209c25ea187 100644 --- a/packages/richtext-lexical/src/features/heading/server/index.ts +++ b/packages/richtext-lexical/src/features/heading/server/index.ts @@ -6,7 +6,7 @@ import type { SerializedLexicalNode } from 'lexical' import { HeadingNode } from '@lexical/rich-text' -import type { StronglyTypedElementNode } from '../../../nodeTypes.js' +import type { StronglyTypedElementNode } from '../../../types/nodeTypes.js' import { createServerFeature } from '../../../utilities/createServerFeature.js' import { createNode } from '../../typeUtilities.js' diff --git a/packages/richtext-lexical/src/features/horizontalRule/server/nodes/HorizontalRuleNode.tsx b/packages/richtext-lexical/src/features/horizontalRule/server/nodes/HorizontalRuleNode.tsx index ef7f37ea0e4..569dc8cd3df 100644 --- a/packages/richtext-lexical/src/features/horizontalRule/server/nodes/HorizontalRuleNode.tsx +++ b/packages/richtext-lexical/src/features/horizontalRule/server/nodes/HorizontalRuleNode.tsx @@ -12,7 +12,7 @@ import type * as React from 'react' import { addClassNamesToElement } from '@lexical/utils' import { $applyNodeReplacement, createCommand, DecoratorNode } from 'lexical' -import type { StronglyTypedLeafNode } from '../../../../nodeTypes.js' +import type { StronglyTypedLeafNode } from '../../../../types/nodeTypes.js' /** * Serialized representation of a horizontal rule node. Serialized = converted to JSON. This is what is stored in the database / in the lexical editor state. diff --git a/packages/richtext-lexical/src/features/link/nodes/types.ts b/packages/richtext-lexical/src/features/link/nodes/types.ts index b3113cab7b3..94f39223481 100644 --- a/packages/richtext-lexical/src/features/link/nodes/types.ts +++ b/packages/richtext-lexical/src/features/link/nodes/types.ts @@ -1,7 +1,7 @@ import type { SerializedElementNode, SerializedLexicalNode } from 'lexical' import type { DefaultDocumentIDType, JsonValue } from 'payload' -import type { StronglyTypedElementNode } from '../../../nodeTypes.js' +import type { StronglyTypedElementNode } from '../../../types/nodeTypes.js' export type LinkFields = { [key: string]: JsonValue diff --git a/packages/richtext-lexical/src/features/lists/plugin/index.tsx b/packages/richtext-lexical/src/features/lists/plugin/index.tsx index 96e59f21459..34b947e7035 100644 --- a/packages/richtext-lexical/src/features/lists/plugin/index.tsx +++ b/packages/richtext-lexical/src/features/lists/plugin/index.tsx @@ -8,7 +8,7 @@ import type { SerializedLexicalNode } from 'lexical' import { ListPlugin } from '@lexical/react/LexicalListPlugin.js' import React from 'react' -import type { StronglyTypedElementNode } from '../../../nodeTypes.js' +import type { StronglyTypedElementNode } from '../../../types/nodeTypes.js' import type { PluginComponent } from '../../typesClient.js' export type SerializedListItemNode = { diff --git a/packages/richtext-lexical/src/features/relationship/server/nodes/RelationshipNode.tsx b/packages/richtext-lexical/src/features/relationship/server/nodes/RelationshipNode.tsx index 808aaf93589..12c1c39bda9 100644 --- a/packages/richtext-lexical/src/features/relationship/server/nodes/RelationshipNode.tsx +++ b/packages/richtext-lexical/src/features/relationship/server/nodes/RelationshipNode.tsx @@ -16,7 +16,7 @@ import { type NodeKey, } from 'lexical' -import type { StronglyTypedLeafNode } from '../../../../nodeTypes.js' +import type { StronglyTypedLeafNode } from '../../../../types/nodeTypes.js' export type RelationshipData = { [TCollectionSlug in CollectionSlug]: { diff --git a/packages/richtext-lexical/src/features/toolbars/types.ts b/packages/richtext-lexical/src/features/toolbars/types.ts index 0fb3b716a60..d6d93e41612 100644 --- a/packages/richtext-lexical/src/features/toolbars/types.ts +++ b/packages/richtext-lexical/src/features/toolbars/types.ts @@ -3,7 +3,7 @@ import type { BaseSelection, LexicalEditor } from 'lexical' import type React from 'react' import type { EditorConfigContextType } from '../../lexical/config/client/EditorConfigProvider.js' -import type { FeatureClientSchemaMap } from '../../types.js' +import type { FeatureClientSchemaMap } from '../../types/index.js' export type ToolbarGroup = ToolbarButtonsGroup | ToolbarDropdownGroup diff --git a/packages/richtext-lexical/src/features/typesClient.ts b/packages/richtext-lexical/src/features/typesClient.ts index 569ab1971a0..e856637be58 100644 --- a/packages/richtext-lexical/src/features/typesClient.ts +++ b/packages/richtext-lexical/src/features/typesClient.ts @@ -12,7 +12,7 @@ import type { JSX } from 'react' import type { ClientEditorConfig } from '../lexical/config/types.js' import type { SlashMenuGroup } from '../lexical/plugins/SlashMenu/LexicalTypeaheadMenuPlugin/types.js' import type { Transformer } from '../packages/@lexical/markdown/index.js' -import type { FeatureClientSchemaMap } from '../types.js' +import type { FeatureClientSchemaMap } from '../types/index.js' import type { ToolbarGroup } from './toolbars/types.js' export type FeatureProviderProviderClient< diff --git a/packages/richtext-lexical/src/features/typesServer.ts b/packages/richtext-lexical/src/features/typesServer.ts index 4f3eb1a2fa2..f42afa9829f 100644 --- a/packages/richtext-lexical/src/features/typesServer.ts +++ b/packages/richtext-lexical/src/features/typesServer.ts @@ -27,7 +27,7 @@ import type { import type { ServerEditorConfig } from '../lexical/config/types.js' import type { Transformer } from '../packages/@lexical/markdown/index.js' -import type { LexicalRichTextField } from '../types.js' +import type { LexicalRichTextField } from '../types/index.js' import type { BaseClientFeatureProps } from './typesClient.js' export type PopulationPromise = (args: { @@ -285,7 +285,7 @@ export type ServerFeature = { | ImportMapGenerators[0] | PayloadComponent[] generatedTypes?: { - modifyOutputSchema: (args: { + modifyJSONSchema: (args: { collectionIDFieldTypes: { [key: string]: 'number' | 'string' } config?: SanitizedConfig /** @@ -357,7 +357,7 @@ export type SanitizedServerFeatures = { /** The keys of all enabled features */ enabledFeatures: string[] generatedTypes: { - modifyOutputSchemas: Array< + modifyJSONSchemas: Array< (args: { collectionIDFieldTypes: { [key: string]: 'number' | 'string' } config?: SanitizedConfig diff --git a/packages/richtext-lexical/src/features/upload/server/nodes/UploadNode.tsx b/packages/richtext-lexical/src/features/upload/server/nodes/UploadNode.tsx index f302340a8db..113a8defc63 100644 --- a/packages/richtext-lexical/src/features/upload/server/nodes/UploadNode.tsx +++ b/packages/richtext-lexical/src/features/upload/server/nodes/UploadNode.tsx @@ -21,7 +21,7 @@ import { addClassNamesToElement } from '@lexical/utils' import ObjectID from 'bson-objectid' import { $applyNodeReplacement } from 'lexical' -import type { StronglyTypedLeafNode } from '../../../../nodeTypes.js' +import type { StronglyTypedLeafNode } from '../../../../types/nodeTypes.js' import { $convertUploadElement } from './conversions.js' diff --git a/packages/richtext-lexical/src/field/Diff/converters/link.ts b/packages/richtext-lexical/src/field/Diff/converters/link.ts index d46ed3285bc..58d392ccbd7 100644 --- a/packages/richtext-lexical/src/field/Diff/converters/link.ts +++ b/packages/richtext-lexical/src/field/Diff/converters/link.ts @@ -6,7 +6,7 @@ import type { HTMLConvertersAsync, HTMLPopulateFn, } from '../../../features/converters/lexicalToHtml/async/types.js' -import type { SerializedAutoLinkNode, SerializedLinkNode } from '../../../nodeTypes.js' +import type { SerializedAutoLinkNode, SerializedLinkNode } from '../../../types/nodeTypes.js' export const LinkDiffHTMLConverterAsync: (args: { internalDocToHref?: (args: { diff --git a/packages/richtext-lexical/src/field/Diff/converters/listitem/index.tsx b/packages/richtext-lexical/src/field/Diff/converters/listitem/index.tsx index ca0c4a577b1..11aabfbc415 100644 --- a/packages/richtext-lexical/src/field/Diff/converters/listitem/index.tsx +++ b/packages/richtext-lexical/src/field/Diff/converters/listitem/index.tsx @@ -1,7 +1,7 @@ import { CheckIcon } from '@payloadcms/ui/rsc' import type { HTMLConvertersAsync } from '../../../../features/converters/lexicalToHtml/async/types.js' -import type { SerializedListItemNode } from '../../../../nodeTypes.js' +import type { SerializedListItemNode } from '../../../../types/nodeTypes.js' import './index.css' diff --git a/packages/richtext-lexical/src/field/Diff/converters/relationship/index.tsx b/packages/richtext-lexical/src/field/Diff/converters/relationship/index.tsx index 9ea381d91c8..4d3d5ddcb69 100644 --- a/packages/richtext-lexical/src/field/Diff/converters/relationship/index.tsx +++ b/packages/richtext-lexical/src/field/Diff/converters/relationship/index.tsx @@ -7,7 +7,7 @@ import './index.css' import { formatAdminURL } from 'payload/shared' import type { HTMLConvertersAsync } from '../../../../features/converters/lexicalToHtml/async/types.js' -import type { SerializedRelationshipNode } from '../../../../nodeTypes.js' +import type { SerializedRelationshipNode } from '../../../../types/nodeTypes.js' const baseClass = 'lexical-relationship-diff' diff --git a/packages/richtext-lexical/src/field/Diff/converters/unknown/index.tsx b/packages/richtext-lexical/src/field/Diff/converters/unknown/index.tsx index 789f4a011aa..2f3d69e3492 100644 --- a/packages/richtext-lexical/src/field/Diff/converters/unknown/index.tsx +++ b/packages/richtext-lexical/src/field/Diff/converters/unknown/index.tsx @@ -8,7 +8,7 @@ import './index.css' import { createHash } from 'crypto' import type { HTMLConvertersAsync } from '../../../../features/converters/lexicalToHtml/async/types.js' -import type { SerializedBlockNode } from '../../../../nodeTypes.js' +import type { SerializedBlockNode } from '../../../../types/nodeTypes.js' const baseClass = 'lexical-unknown-diff' diff --git a/packages/richtext-lexical/src/field/Diff/converters/upload/index.tsx b/packages/richtext-lexical/src/field/Diff/converters/upload/index.tsx index 687d6c5a8d6..126fd8616d1 100644 --- a/packages/richtext-lexical/src/field/Diff/converters/upload/index.tsx +++ b/packages/richtext-lexical/src/field/Diff/converters/upload/index.tsx @@ -11,7 +11,7 @@ import React from 'react' import type { HTMLConvertersAsync } from '../../../../features/converters/lexicalToHtml/async/types.js' import type { UploadDataImproved } from '../../../../features/upload/server/nodes/UploadNode.js' -import type { SerializedUploadNode } from '../../../../nodeTypes.js' +import type { SerializedUploadNode } from '../../../../types/nodeTypes.js' const baseClass = 'lexical-upload-diff' diff --git a/packages/richtext-lexical/src/field/Diff/index.tsx b/packages/richtext-lexical/src/field/Diff/index.tsx index 7bea2ead8bd..0df77cef5f0 100644 --- a/packages/richtext-lexical/src/field/Diff/index.tsx +++ b/packages/richtext-lexical/src/field/Diff/index.tsx @@ -13,7 +13,7 @@ import type { HTMLConvertersFunctionAsync, HTMLPopulateFn, } from '../../features/converters/lexicalToHtml/async/types.js' -import type { SerializedLinkNode } from '../../nodeTypes.js' +import type { SerializedLinkNode } from '../../types/nodeTypes.js' import { convertLexicalToHTMLAsync } from '../../features/converters/lexicalToHtml/async/index.js' import { getPayloadPopulateFn } from '../../features/converters/utilities/payloadPopulateFn.js' diff --git a/packages/richtext-lexical/src/field/Field.tsx b/packages/richtext-lexical/src/field/Field.tsx index 46f689a5385..580cc1a4d8d 100644 --- a/packages/richtext-lexical/src/field/Field.tsx +++ b/packages/richtext-lexical/src/field/Field.tsx @@ -27,7 +27,7 @@ import '../lexical/theme/EditorTheme.css' import './bundled.css' import './index.css' -import type { LexicalRichTextFieldProps } from '../types.js' +import type { LexicalRichTextFieldProps } from '../types/index.js' import { LexicalProvider } from '../lexical/LexicalProvider.js' import { useRunDeprioritized } from '../utilities/useRunDeprioritized.js' diff --git a/packages/richtext-lexical/src/field/RenderLexical/index.tsx b/packages/richtext-lexical/src/field/RenderLexical/index.tsx index 5793e678d59..99d3b6e473f 100644 --- a/packages/richtext-lexical/src/field/RenderLexical/index.tsx +++ b/packages/richtext-lexical/src/field/RenderLexical/index.tsx @@ -13,8 +13,8 @@ import { } from '@payloadcms/ui' import React, { useCallback, useEffect, useRef } from 'react' -import type { DefaultTypedEditorState } from '../../nodeTypes.js' -import type { LexicalRichTextField } from '../../types.js' +import type { LexicalRichTextField } from '../../types/index.js' +import type { DefaultTypedEditorState } from '../../types/nodeTypes.js' /** * Utility to render a lexical editor on the client. diff --git a/packages/richtext-lexical/src/field/RichTextViewProvider.tsx b/packages/richtext-lexical/src/field/RichTextViewProvider.tsx index a20db6bc9f0..7f250fdf7d9 100644 --- a/packages/richtext-lexical/src/field/RichTextViewProvider.tsx +++ b/packages/richtext-lexical/src/field/RichTextViewProvider.tsx @@ -2,7 +2,7 @@ import { useControllableState } from '@payloadcms/ui' import React, { createContext, use, useMemo } from 'react' -import type { LexicalEditorNodeMap, LexicalEditorViewMap } from '../types.js' +import type { LexicalEditorNodeMap, LexicalEditorViewMap } from '../types/index.js' /** * Context for managing richtext editor view state and inheritance. diff --git a/packages/richtext-lexical/src/field/index.tsx b/packages/richtext-lexical/src/field/index.tsx index 661a5ae5740..d97d74311d1 100644 --- a/packages/richtext-lexical/src/field/index.tsx +++ b/packages/richtext-lexical/src/field/index.tsx @@ -8,7 +8,7 @@ import React, { lazy, Suspense, useEffect, useState } from 'react' import type { FeatureProviderClient } from '../features/typesClient.js' import type { SanitizedClientEditorConfig } from '../lexical/config/types.js' -import type { LexicalFieldAdminClientProps, LexicalRichTextFieldProps } from '../types.js' +import type { LexicalFieldAdminClientProps, LexicalRichTextFieldProps } from '../types/index.js' import { defaultEditorLexicalConfig } from '../lexical/config/client/default.js' import { loadClientFeatures } from '../lexical/config/client/loader.js' diff --git a/packages/richtext-lexical/src/field/rscEntry.tsx b/packages/richtext-lexical/src/field/rscEntry.tsx index 67f9aa2675d..9189277bfaa 100644 --- a/packages/richtext-lexical/src/field/rscEntry.tsx +++ b/packages/richtext-lexical/src/field/rscEntry.tsx @@ -18,7 +18,7 @@ import type { LexicalEditorViewMap, LexicalFieldAdminClientProps, LexicalRichTextFieldProps, -} from '../types.js' +} from '../types/index.js' // eslint-disable-next-line payload/no-imports-from-exports-dir import { RichTextField } from '../exports/client/index.js' diff --git a/packages/richtext-lexical/src/hooks.ts b/packages/richtext-lexical/src/hooks.ts new file mode 100644 index 00000000000..f834dbd61fe --- /dev/null +++ b/packages/richtext-lexical/src/hooks.ts @@ -0,0 +1,631 @@ +import type { SerializedEditorState, SerializedLexicalNode } from 'lexical' + +import { + afterChangeTraverseFields, + afterReadTraverseFields, + beforeChangeTraverseFields, + beforeValidateTraverseFields, + type RichTextHooks, +} from 'payload' + +import type { SanitizedServerEditorConfig } from './lexical/config/types.js' + +import { recurseNodeTree } from './utilities/recurseNodeTree.js' + +export const getLexicalHooks: (args: { + editorConfig: SanitizedServerEditorConfig +}) => RichTextHooks = ({ editorConfig }) => { + return { + afterChange: [ + async (args) => { + const { + collection, + context: _context, + data, + field, + global, + indexPath, + operation, + originalDoc, + parentIsLocalized, + path, + previousDoc, + previousValue, + req, + schemaPath, + } = args + + let { value } = args + if (editorConfig?.features?.hooks?.afterChange?.length) { + for (const hook of editorConfig.features.hooks.afterChange) { + value = await hook(args) + } + } + if ( + !editorConfig.features.nodeHooks?.afterChange?.size && + !editorConfig.features.getSubFields?.size + ) { + return value + } + // TO-DO: We should not use context, as it is intended for external use only + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const context: any = _context + const nodeIDMap: { + [key: string]: SerializedLexicalNode + } = {} + + const previousNodeIDMap: { + [key: string]: SerializedLexicalNode + } = {} + + /** + * Get the originalNodeIDMap from the beforeValidate hook, which is always run before this hook. + */ + const originalNodeIDMap: { + [key: string]: SerializedLexicalNode + } = context?.internal?.richText?.[path.join('.')]?.originalNodeIDMap + + if (!originalNodeIDMap || !Object.keys(originalNodeIDMap).length || !value) { + return value + } + + recurseNodeTree({ + nodeIDMap, + nodes: (value as SerializedEditorState)?.root?.children ?? [], + }) + + recurseNodeTree({ + nodeIDMap: previousNodeIDMap, + nodes: (previousValue as SerializedEditorState)?.root?.children ?? [], + }) + + // eslint-disable-next-line prefer-const + for (let [id, node] of Object.entries(nodeIDMap)) { + const afterChangeHooks = editorConfig.features.nodeHooks?.afterChange + const afterChangeHooksForNode = afterChangeHooks?.get(node.type) + if (afterChangeHooksForNode) { + for (const hook of afterChangeHooksForNode) { + if (!originalNodeIDMap[id]) { + console.warn( + '(afterChange) No original node found for node with id', + id, + 'node:', + node, + 'path', + path.join('.'), + ) + continue + } + node = await hook({ + context, + node, + operation, + originalNode: originalNodeIDMap[id], + parentRichTextFieldPath: path, + parentRichTextFieldSchemaPath: schemaPath, + + previousNode: previousNodeIDMap[id]!, + req, + }) + } + } + const subFieldFn = editorConfig.features.getSubFields?.get(node.type) + const subFieldDataFn = editorConfig.features.getSubFieldsData?.get(node.type) + + if (subFieldFn && subFieldDataFn) { + const subFields = subFieldFn({ node, req }) + const nodeSiblingData = subFieldDataFn({ node, req }) ?? {} + + const nodeSiblingDoc = subFieldDataFn({ node: originalNodeIDMap[id]!, req }) ?? {} + const nodePreviousSiblingDoc = + subFieldDataFn({ node: previousNodeIDMap[id]!, req }) ?? {} + + if (subFields?.length) { + await afterChangeTraverseFields({ + blockData: nodeSiblingData, + collection, + context, + data: data ?? {}, + doc: originalDoc, + fields: subFields, + global, + operation, + parentIndexPath: indexPath.join('-'), + parentIsLocalized: parentIsLocalized || field.localized || false, + parentPath: path.join('.'), + parentSchemaPath: schemaPath.join('.'), + previousDoc, + previousSiblingDoc: { ...nodePreviousSiblingDoc }, + req, + siblingData: nodeSiblingData || {}, + siblingDoc: { ...nodeSiblingDoc }, + }) + } + } + } + return value + }, + ], + afterRead: [ + /** + * afterRead hooks do not receive the originalNode. Thus, they can run on all nodes, not just nodes with an ID. + */ + async (args) => { + const { + collection, + context: context, + currentDepth, + depth, + draft, + fallbackLocale, + field, + fieldPromises, + findMany, + flattenLocales, + global, + indexPath, + locale, + originalDoc, + overrideAccess, + parentIsLocalized, + path, + populate, + populationPromises, + req, + schemaPath, + showHiddenFields, + triggerAccessControl, + triggerHooks, + } = args + + let { value } = args + + if (editorConfig?.features?.hooks?.afterRead?.length) { + for (const hook of editorConfig.features.hooks.afterRead) { + value = await hook(args) + } + } + + if ( + !editorConfig.features.nodeHooks?.afterRead?.size && + !editorConfig.features.getSubFields?.size + ) { + return value + } + const flattenedNodes: SerializedLexicalNode[] = [] + + recurseNodeTree({ + flattenedNodes, + nodes: (value as SerializedEditorState)?.root?.children ?? [], + }) + + for (let node of flattenedNodes) { + const afterReadHooks = editorConfig.features.nodeHooks?.afterRead + const afterReadHooksForNode = afterReadHooks?.get(node.type) + if (afterReadHooksForNode) { + for (const hook of afterReadHooksForNode) { + node = await hook({ + context, + currentDepth: currentDepth!, + depth: depth!, + draft: draft!, + fallbackLocale: fallbackLocale!, + fieldPromises: fieldPromises!, + findMany: findMany!, + flattenLocales: flattenLocales!, + locale: locale!, + node, + overrideAccess: overrideAccess!, + parentRichTextFieldPath: path, + parentRichTextFieldSchemaPath: schemaPath, + populateArg: populate, + populationPromises: populationPromises!, + req, + showHiddenFields: showHiddenFields!, + triggerAccessControl: triggerAccessControl!, + triggerHooks: triggerHooks!, + }) + } + } + const subFieldFn = editorConfig.features.getSubFields?.get(node.type) + const subFieldDataFn = editorConfig.features.getSubFieldsData?.get(node.type) + + if (subFieldFn && subFieldDataFn) { + const subFields = subFieldFn({ node, req }) + const nodeSiblingData = subFieldDataFn({ node, req }) ?? {} + + if (subFields?.length) { + afterReadTraverseFields({ + blockData: nodeSiblingData, + collection, + context, + currentDepth: currentDepth!, + depth: depth!, + doc: originalDoc, + draft: draft!, + fallbackLocale: fallbackLocale!, + fieldPromises: fieldPromises!, + fields: subFields, + findMany: findMany!, + flattenLocales: flattenLocales!, + global, + locale: locale!, + overrideAccess: overrideAccess!, + parentIndexPath: indexPath.join('-'), + parentIsLocalized: parentIsLocalized || field.localized || false, + parentPath: path.join('.'), + parentSchemaPath: schemaPath.join('.'), + populate, + populationPromises: populationPromises!, + req, + showHiddenFields: showHiddenFields!, + siblingDoc: nodeSiblingData, + triggerAccessControl, + triggerHooks, + }) + } + } + } + + return value + }, + ], + beforeChange: [ + async (args) => { + const { + collection, + context: _context, + data, + docWithLocales, + errors, + field, + fieldLabelPath, + global, + indexPath, + mergeLocaleActions, + operation, + originalDoc, + overrideAccess, + parentIsLocalized, + path, + previousValue, + req, + schemaPath, + siblingData, + siblingDocWithLocales, + skipValidation, + } = args + + let { value } = args + + if (editorConfig?.features?.hooks?.beforeChange?.length) { + for (const hook of editorConfig.features.hooks.beforeChange) { + value = await hook(args) + } + } + + if ( + !editorConfig.features.nodeHooks?.beforeChange?.size && + !editorConfig.features.getSubFields?.size + ) { + return value + } + + // TO-DO: We should not use context, as it is intended for external use only + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const context: any = _context + const nodeIDMap: { + [key: string]: SerializedLexicalNode + } = {} + + /** + * Get the originalNodeIDMap from the beforeValidate hook, which is always run before this hook. + */ + const originalNodeIDMap: { + [key: string]: SerializedLexicalNode + } = context?.internal?.richText?.[path.join('.')]?.originalNodeIDMap + + if (!originalNodeIDMap || !Object.keys(originalNodeIDMap).length || !value) { + return value + } + + const previousNodeIDMap: { + [key: string]: SerializedLexicalNode + } = {} + + const originalNodeWithLocalesIDMap: { + [key: string]: SerializedLexicalNode + } = {} + + recurseNodeTree({ + nodeIDMap, + nodes: (value as SerializedEditorState)?.root?.children ?? [], + }) + + recurseNodeTree({ + nodeIDMap: previousNodeIDMap, + nodes: (previousValue as SerializedEditorState)?.root?.children ?? [], + }) + if (field.name && siblingDocWithLocales?.[field.name]) { + recurseNodeTree({ + nodeIDMap: originalNodeWithLocalesIDMap, + nodes: + (siblingDocWithLocales[field.name] as SerializedEditorState)?.root?.children ?? [], + }) + } + + // eslint-disable-next-line prefer-const + for (let [id, node] of Object.entries(nodeIDMap)) { + const beforeChangeHooks = editorConfig.features.nodeHooks?.beforeChange + const beforeChangeHooksForNode = beforeChangeHooks?.get(node.type) + if (beforeChangeHooksForNode) { + for (const hook of beforeChangeHooksForNode) { + if (!originalNodeIDMap[id]) { + console.warn( + '(beforeChange) No original node found for node with id', + id, + 'node:', + node, + 'path', + path.join('.'), + ) + continue + } + node = await hook({ + context, + errors: errors!, + mergeLocaleActions: mergeLocaleActions!, + node, + operation: operation!, + originalNode: originalNodeIDMap[id], + originalNodeWithLocales: originalNodeWithLocalesIDMap[id], + parentRichTextFieldPath: path, + parentRichTextFieldSchemaPath: schemaPath, + previousNode: previousNodeIDMap[id]!, + req, + skipValidation: skipValidation!, + }) + } + } + + const subFieldFn = editorConfig.features.getSubFields?.get(node.type) + const subFieldDataFn = editorConfig.features.getSubFieldsData?.get(node.type) + + if (subFieldFn && subFieldDataFn) { + const subFields = subFieldFn({ node, req }) + const nodeSiblingData = subFieldDataFn({ node, req }) ?? {} + const nodeSiblingDocWithLocales = + subFieldDataFn({ + node: originalNodeWithLocalesIDMap[id]!, + req, + }) ?? {} + const nodePreviousSiblingDoc = + subFieldDataFn({ node: previousNodeIDMap[id]!, req }) ?? {} + + if (subFields?.length) { + await beforeChangeTraverseFields({ + id, + blockData: nodeSiblingData, + collection, + context, + data: data ?? {}, + doc: originalDoc ?? {}, + docWithLocales: docWithLocales ?? {}, + errors: errors!, + fieldLabelPath, + fields: subFields, + global, + mergeLocaleActions: mergeLocaleActions!, + operation: operation!, + overrideAccess, + parentIndexPath: indexPath.join('-'), + parentIsLocalized: parentIsLocalized || field.localized || false, + parentPath: path.join('.'), + parentSchemaPath: schemaPath.join('.'), + req, + siblingData: nodeSiblingData, + siblingDoc: nodePreviousSiblingDoc, + siblingDocWithLocales: nodeSiblingDocWithLocales ?? {}, + skipValidation, + }) + } + } + } + + /** + * within the beforeChange hook, id's may be re-generated. + * Example: + * 1. Seed data contains IDs for block feature blocks. + * 2. Those are used in beforeValidate + * 3. in beforeChange, those IDs are regenerated, because you cannot provide IDs during document creation. See baseIDField beforeChange hook for reasoning + * 4. Thus, in order for all post-beforeChange hooks to receive the correct ID, we need to update the originalNodeIDMap with the new ID's, by regenerating the nodeIDMap. + * The reason this is not generated for every hook, is to save on performance. We know we only really have to generate it in beforeValidate, which is the first hook, + * and in beforeChange, which is where modifications to the provided IDs can occur. + */ + const newOriginalNodeIDMap: { + [key: string]: SerializedLexicalNode + } = {} + + const previousOriginalValue = siblingData[field.name!] + + recurseNodeTree({ + nodeIDMap: newOriginalNodeIDMap, + nodes: (previousOriginalValue as SerializedEditorState)?.root?.children ?? [], + }) + + if (!context.internal) { + // Add to context, for other hooks to use + context.internal = {} + } + if (!context.internal.richText) { + context.internal.richText = {} + } + context.internal.richText[path.join('.')] = { + originalNodeIDMap: newOriginalNodeIDMap, + } + + return value + }, + ], + beforeValidate: [ + async (args) => { + const { + collection, + context, + data, + field, + global, + indexPath, + operation, + originalDoc, + overrideAccess, + parentIsLocalized, + path, + previousValue, + req, + schemaPath, + } = args + + let { value } = args + if (editorConfig?.features?.hooks?.beforeValidate?.length) { + for (const hook of editorConfig.features.hooks.beforeValidate) { + value = await hook(args) + } + } + + // return value if there are NO hooks + if ( + !editorConfig.features.nodeHooks?.beforeValidate?.size && + !editorConfig.features.nodeHooks?.afterChange?.size && + !editorConfig.features.nodeHooks?.beforeChange?.size && + !editorConfig.features.getSubFields?.size + ) { + return value + } + + /** + * beforeValidate is the first field hook which runs. This is where we can create the node map, which can then be used in the other hooks. + * + */ + + /** + * flattenedNodes contains all nodes in the editor, in the order they appear in the editor. They will be used for the following hooks: + * - afterRead + * + * The other hooks require nodes to have IDs, which is why those are ran only from the nodeIDMap. They require IDs because they have both doc/siblingDoc and data/siblingData, and + * thus require a reliable way to match new node data to old node data. Given that node positions can change in between hooks, this is only reliably possible for nodes which are saved with + * an ID. + */ + //const flattenedNodes: SerializedLexicalNode[] = [] + + /** + * Only nodes with id's (so, nodes with hooks added to them) will be added to the nodeIDMap. They will be used for the following hooks: + * - afterChange + * - beforeChange + * - beforeValidate + * + * Other hooks are handled by the flattenedNodes. All nodes in the nodeIDMap are part of flattenedNodes. + */ + + const originalNodeIDMap: { + [key: string]: SerializedLexicalNode + } = {} + + recurseNodeTree({ + nodeIDMap: originalNodeIDMap, + nodes: (previousValue as SerializedEditorState)?.root?.children ?? [], + }) + + if (!context.internal) { + // Add to context, for other hooks to use + context.internal = {} + } + if (!(context as any).internal.richText) { + ;(context as any).internal.richText = {} + } + ;(context as any).internal.richText[path.join('.')] = { + originalNodeIDMap, + } + + /** + * Now that the maps for all hooks are set up, we can run the validate hook + */ + if (!editorConfig.features.nodeHooks?.beforeValidate?.size) { + return value + } + const nodeIDMap: { + [key: string]: SerializedLexicalNode + } = {} + recurseNodeTree({ + //flattenedNodes, + nodeIDMap, + nodes: (value as SerializedEditorState)?.root?.children ?? [], + }) + + // eslint-disable-next-line prefer-const + for (let [id, node] of Object.entries(nodeIDMap)) { + const beforeValidateHooks = editorConfig.features.nodeHooks.beforeValidate + const beforeValidateHooksForNode = beforeValidateHooks?.get(node.type) + if (beforeValidateHooksForNode) { + for (const hook of beforeValidateHooksForNode) { + if (!originalNodeIDMap[id]) { + console.warn( + '(beforeValidate) No original node found for node with id', + id, + 'node:', + node, + 'path', + path.join('.'), + ) + continue + } + node = await hook({ + context, + node, + operation, + originalNode: originalNodeIDMap[id], + overrideAccess: overrideAccess!, + parentRichTextFieldPath: path, + parentRichTextFieldSchemaPath: schemaPath, + req, + }) + } + } + const subFieldFn = editorConfig.features.getSubFields?.get(node.type) + const subFieldDataFn = editorConfig.features.getSubFieldsData?.get(node.type) + + if (subFieldFn && subFieldDataFn) { + const subFields = subFieldFn({ node, req }) + const nodeSiblingData = subFieldDataFn({ node, req }) ?? {} + + const nodeSiblingDoc = subFieldDataFn({ node: originalNodeIDMap[id]!, req }) ?? {} + + if (subFields?.length) { + await beforeValidateTraverseFields({ + id, + blockData: nodeSiblingData, + collection, + context, + data, + doc: originalDoc, + fields: subFields, + global, + operation, + overrideAccess: overrideAccess!, + parentIndexPath: indexPath.join('-'), + parentIsLocalized: parentIsLocalized || field.localized || false, + parentPath: path.join('.'), + parentSchemaPath: schemaPath.join('.'), + req, + siblingData: nodeSiblingData, + siblingDoc: nodeSiblingDoc, + }) + } + } + } + + return value + }, + ], + } +} diff --git a/packages/richtext-lexical/src/index.ts b/packages/richtext-lexical/src/index.ts index 368bf0673da..57e6e0129ee 100644 --- a/packages/richtext-lexical/src/index.ts +++ b/packages/richtext-lexical/src/index.ts @@ -1,29 +1,24 @@ import type { GenericLanguages, GenericTranslationsObject } from '@payloadcms/translations' -import type { JSONSchema4 } from 'json-schema' -import type { SerializedEditorState, SerializedLexicalNode } from 'lexical' -import { - afterChangeTraverseFields, - afterReadTraverseFields, - beforeChangeTraverseFields, - beforeValidateTraverseFields, - checkDependencies, - deepMergeSimple, - withNullableJSONSchemaType, -} from 'payload' +import { checkDependencies, deepMergeSimple } from 'payload' import type { FeatureProviderServer, ResolvedServerFeatureMap } from './features/typesServer.js' import type { SanitizedServerEditorConfig } from './lexical/config/types.js' -import type { AdapterProps, LexicalEditorProps, LexicalRichTextAdapterProvider } from './types.js' +import type { + AdapterProps, + LexicalEditorProps, + LexicalRichTextAdapterProvider, +} from './types/index.js' +import { getLexicalHooks } from './hooks.js' import { i18n } from './i18n.js' import { defaultEditorFeatures } from './lexical/config/server/default.js' import { populateLexicalPopulationPromises } from './populateGraphQL/populateLexicalPopulationPromises.js' +import { getFieldToJSONSchema } from './types/schema.js' import { featuresInputToEditorConfig } from './utilities/editorConfigFactory.js' import { getGenerateImportMap } from './utilities/generateImportMap.js' import { getGenerateSchemaMap } from './utilities/generateSchemaMap.js' import { getDefaultSanitizedEditorConfig } from './utilities/getDefaultSanitizedEditorConfig.js' -import { recurseNodeTree } from './utilities/recurseNodeTree.js' import { richTextValidateHOC } from './validate/index.js' let checkedDependencies = false @@ -163,709 +158,10 @@ export function lexicalEditor(args?: LexicalEditorProps): LexicalRichTextAdapter }) } }, - hooks: { - afterChange: [ - async (args) => { - const { - collection, - context: _context, - data, - field, - global, - indexPath, - operation, - originalDoc, - parentIsLocalized, - path, - previousDoc, - previousValue, - req, - schemaPath, - } = args - - let { value } = args - if (finalSanitizedEditorConfig?.features?.hooks?.afterChange?.length) { - for (const hook of finalSanitizedEditorConfig.features.hooks.afterChange) { - value = await hook(args) - } - } - if ( - !finalSanitizedEditorConfig.features.nodeHooks?.afterChange?.size && - !finalSanitizedEditorConfig.features.getSubFields?.size - ) { - return value - } - // TO-DO: We should not use context, as it is intended for external use only - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const context: any = _context - const nodeIDMap: { - [key: string]: SerializedLexicalNode - } = {} - - const previousNodeIDMap: { - [key: string]: SerializedLexicalNode - } = {} - - /** - * Get the originalNodeIDMap from the beforeValidate hook, which is always run before this hook. - */ - const originalNodeIDMap: { - [key: string]: SerializedLexicalNode - } = context?.internal?.richText?.[path.join('.')]?.originalNodeIDMap - - if (!originalNodeIDMap || !Object.keys(originalNodeIDMap).length || !value) { - return value - } - - recurseNodeTree({ - nodeIDMap, - nodes: (value as SerializedEditorState)?.root?.children ?? [], - }) - - recurseNodeTree({ - nodeIDMap: previousNodeIDMap, - nodes: (previousValue as SerializedEditorState)?.root?.children ?? [], - }) - - // eslint-disable-next-line prefer-const - for (let [id, node] of Object.entries(nodeIDMap)) { - const afterChangeHooks = finalSanitizedEditorConfig.features.nodeHooks?.afterChange - const afterChangeHooksForNode = afterChangeHooks?.get(node.type) - if (afterChangeHooksForNode) { - for (const hook of afterChangeHooksForNode) { - if (!originalNodeIDMap[id]) { - console.warn( - '(afterChange) No original node found for node with id', - id, - 'node:', - node, - 'path', - path.join('.'), - ) - continue - } - node = await hook({ - context, - node, - operation, - originalNode: originalNodeIDMap[id], - parentRichTextFieldPath: path, - parentRichTextFieldSchemaPath: schemaPath, - - previousNode: previousNodeIDMap[id]!, - req, - }) - } - } - const subFieldFn = finalSanitizedEditorConfig.features.getSubFields?.get(node.type) - const subFieldDataFn = finalSanitizedEditorConfig.features.getSubFieldsData?.get( - node.type, - ) - - if (subFieldFn && subFieldDataFn) { - const subFields = subFieldFn({ node, req }) - const nodeSiblingData = subFieldDataFn({ node, req }) ?? {} - - const nodeSiblingDoc = subFieldDataFn({ node: originalNodeIDMap[id]!, req }) ?? {} - const nodePreviousSiblingDoc = - subFieldDataFn({ node: previousNodeIDMap[id]!, req }) ?? {} - - if (subFields?.length) { - await afterChangeTraverseFields({ - blockData: nodeSiblingData, - collection, - context, - data: data ?? {}, - doc: originalDoc, - fields: subFields, - global, - operation, - parentIndexPath: indexPath.join('-'), - parentIsLocalized: parentIsLocalized || field.localized || false, - parentPath: path.join('.'), - parentSchemaPath: schemaPath.join('.'), - previousDoc, - previousSiblingDoc: { ...nodePreviousSiblingDoc }, - req, - siblingData: nodeSiblingData || {}, - siblingDoc: { ...nodeSiblingDoc }, - }) - } - } - } - return value - }, - ], - afterRead: [ - /** - * afterRead hooks do not receive the originalNode. Thus, they can run on all nodes, not just nodes with an ID. - */ - async (args) => { - const { - collection, - context: context, - currentDepth, - depth, - draft, - fallbackLocale, - field, - fieldPromises, - findMany, - flattenLocales, - global, - indexPath, - locale, - originalDoc, - overrideAccess, - parentIsLocalized, - path, - populate, - populationPromises, - req, - schemaPath, - showHiddenFields, - triggerAccessControl, - triggerHooks, - } = args - - let { value } = args - - if (finalSanitizedEditorConfig?.features?.hooks?.afterRead?.length) { - for (const hook of finalSanitizedEditorConfig.features.hooks.afterRead) { - value = await hook(args) - } - } - - if ( - !finalSanitizedEditorConfig.features.nodeHooks?.afterRead?.size && - !finalSanitizedEditorConfig.features.getSubFields?.size - ) { - return value - } - const flattenedNodes: SerializedLexicalNode[] = [] - - recurseNodeTree({ - flattenedNodes, - nodes: (value as SerializedEditorState)?.root?.children ?? [], - }) - - for (let node of flattenedNodes) { - const afterReadHooks = finalSanitizedEditorConfig.features.nodeHooks?.afterRead - const afterReadHooksForNode = afterReadHooks?.get(node.type) - if (afterReadHooksForNode) { - for (const hook of afterReadHooksForNode) { - node = await hook({ - context, - currentDepth: currentDepth!, - depth: depth!, - draft: draft!, - fallbackLocale: fallbackLocale!, - fieldPromises: fieldPromises!, - findMany: findMany!, - flattenLocales: flattenLocales!, - locale: locale!, - node, - overrideAccess: overrideAccess!, - parentRichTextFieldPath: path, - parentRichTextFieldSchemaPath: schemaPath, - populateArg: populate, - populationPromises: populationPromises!, - req, - showHiddenFields: showHiddenFields!, - triggerAccessControl: triggerAccessControl!, - triggerHooks: triggerHooks!, - }) - } - } - const subFieldFn = finalSanitizedEditorConfig.features.getSubFields?.get(node.type) - const subFieldDataFn = finalSanitizedEditorConfig.features.getSubFieldsData?.get( - node.type, - ) - - if (subFieldFn && subFieldDataFn) { - const subFields = subFieldFn({ node, req }) - const nodeSiblingData = subFieldDataFn({ node, req }) ?? {} - - if (subFields?.length) { - afterReadTraverseFields({ - blockData: nodeSiblingData, - collection, - context, - currentDepth: currentDepth!, - depth: depth!, - doc: originalDoc, - draft: draft!, - fallbackLocale: fallbackLocale!, - fieldPromises: fieldPromises!, - fields: subFields, - findMany: findMany!, - flattenLocales: flattenLocales!, - global, - locale: locale!, - overrideAccess: overrideAccess!, - parentIndexPath: indexPath.join('-'), - parentIsLocalized: parentIsLocalized || field.localized || false, - parentPath: path.join('.'), - parentSchemaPath: schemaPath.join('.'), - populate, - populationPromises: populationPromises!, - req, - showHiddenFields: showHiddenFields!, - siblingDoc: nodeSiblingData, - triggerAccessControl, - triggerHooks, - }) - } - } - } - - return value - }, - ], - beforeChange: [ - async (args) => { - const { - collection, - context: _context, - data, - docWithLocales, - errors, - field, - fieldLabelPath, - global, - indexPath, - mergeLocaleActions, - operation, - originalDoc, - overrideAccess, - parentIsLocalized, - path, - previousValue, - req, - schemaPath, - siblingData, - siblingDocWithLocales, - skipValidation, - } = args - - let { value } = args - - if (finalSanitizedEditorConfig?.features?.hooks?.beforeChange?.length) { - for (const hook of finalSanitizedEditorConfig.features.hooks.beforeChange) { - value = await hook(args) - } - } - - if ( - !finalSanitizedEditorConfig.features.nodeHooks?.beforeChange?.size && - !finalSanitizedEditorConfig.features.getSubFields?.size - ) { - return value - } - - // TO-DO: We should not use context, as it is intended for external use only - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const context: any = _context - const nodeIDMap: { - [key: string]: SerializedLexicalNode - } = {} - - /** - * Get the originalNodeIDMap from the beforeValidate hook, which is always run before this hook. - */ - const originalNodeIDMap: { - [key: string]: SerializedLexicalNode - } = context?.internal?.richText?.[path.join('.')]?.originalNodeIDMap - - if (!originalNodeIDMap || !Object.keys(originalNodeIDMap).length || !value) { - return value - } - - const previousNodeIDMap: { - [key: string]: SerializedLexicalNode - } = {} - - const originalNodeWithLocalesIDMap: { - [key: string]: SerializedLexicalNode - } = {} - - recurseNodeTree({ - nodeIDMap, - nodes: (value as SerializedEditorState)?.root?.children ?? [], - }) - - recurseNodeTree({ - nodeIDMap: previousNodeIDMap, - nodes: (previousValue as SerializedEditorState)?.root?.children ?? [], - }) - if (field.name && siblingDocWithLocales?.[field.name]) { - recurseNodeTree({ - nodeIDMap: originalNodeWithLocalesIDMap, - nodes: - (siblingDocWithLocales[field.name] as SerializedEditorState)?.root?.children ?? - [], - }) - } - - // eslint-disable-next-line prefer-const - for (let [id, node] of Object.entries(nodeIDMap)) { - const beforeChangeHooks = finalSanitizedEditorConfig.features.nodeHooks?.beforeChange - const beforeChangeHooksForNode = beforeChangeHooks?.get(node.type) - if (beforeChangeHooksForNode) { - for (const hook of beforeChangeHooksForNode) { - if (!originalNodeIDMap[id]) { - console.warn( - '(beforeChange) No original node found for node with id', - id, - 'node:', - node, - 'path', - path.join('.'), - ) - continue - } - node = await hook({ - context, - errors: errors!, - mergeLocaleActions: mergeLocaleActions!, - node, - operation: operation!, - originalNode: originalNodeIDMap[id], - originalNodeWithLocales: originalNodeWithLocalesIDMap[id], - parentRichTextFieldPath: path, - parentRichTextFieldSchemaPath: schemaPath, - previousNode: previousNodeIDMap[id]!, - req, - skipValidation: skipValidation!, - }) - } - } - - const subFieldFn = finalSanitizedEditorConfig.features.getSubFields?.get(node.type) - const subFieldDataFn = finalSanitizedEditorConfig.features.getSubFieldsData?.get( - node.type, - ) - - if (subFieldFn && subFieldDataFn) { - const subFields = subFieldFn({ node, req }) - const nodeSiblingData = subFieldDataFn({ node, req }) ?? {} - const nodeSiblingDocWithLocales = - subFieldDataFn({ - node: originalNodeWithLocalesIDMap[id]!, - req, - }) ?? {} - const nodePreviousSiblingDoc = - subFieldDataFn({ node: previousNodeIDMap[id]!, req }) ?? {} - - if (subFields?.length) { - await beforeChangeTraverseFields({ - id, - blockData: nodeSiblingData, - collection, - context, - data: data ?? {}, - doc: originalDoc ?? {}, - docWithLocales: docWithLocales ?? {}, - errors: errors!, - fieldLabelPath, - fields: subFields, - global, - mergeLocaleActions: mergeLocaleActions!, - operation: operation!, - overrideAccess, - parentIndexPath: indexPath.join('-'), - parentIsLocalized: parentIsLocalized || field.localized || false, - parentPath: path.join('.'), - parentSchemaPath: schemaPath.join('.'), - req, - siblingData: nodeSiblingData, - siblingDoc: nodePreviousSiblingDoc, - siblingDocWithLocales: nodeSiblingDocWithLocales ?? {}, - skipValidation, - }) - } - } - } - - /** - * within the beforeChange hook, id's may be re-generated. - * Example: - * 1. Seed data contains IDs for block feature blocks. - * 2. Those are used in beforeValidate - * 3. in beforeChange, those IDs are regenerated, because you cannot provide IDs during document creation. See baseIDField beforeChange hook for reasoning - * 4. Thus, in order for all post-beforeChange hooks to receive the correct ID, we need to update the originalNodeIDMap with the new ID's, by regenerating the nodeIDMap. - * The reason this is not generated for every hook, is to save on performance. We know we only really have to generate it in beforeValidate, which is the first hook, - * and in beforeChange, which is where modifications to the provided IDs can occur. - */ - const newOriginalNodeIDMap: { - [key: string]: SerializedLexicalNode - } = {} - - const previousOriginalValue = siblingData[field.name!] - - recurseNodeTree({ - nodeIDMap: newOriginalNodeIDMap, - nodes: (previousOriginalValue as SerializedEditorState)?.root?.children ?? [], - }) - - if (!context.internal) { - // Add to context, for other hooks to use - context.internal = {} - } - if (!context.internal.richText) { - context.internal.richText = {} - } - context.internal.richText[path.join('.')] = { - originalNodeIDMap: newOriginalNodeIDMap, - } - - return value - }, - ], - beforeValidate: [ - async (args) => { - const { - collection, - context, - data, - field, - global, - indexPath, - operation, - originalDoc, - overrideAccess, - parentIsLocalized, - path, - previousValue, - req, - schemaPath, - } = args - - let { value } = args - if (finalSanitizedEditorConfig?.features?.hooks?.beforeValidate?.length) { - for (const hook of finalSanitizedEditorConfig.features.hooks.beforeValidate) { - value = await hook(args) - } - } - - // return value if there are NO hooks - if ( - !finalSanitizedEditorConfig.features.nodeHooks?.beforeValidate?.size && - !finalSanitizedEditorConfig.features.nodeHooks?.afterChange?.size && - !finalSanitizedEditorConfig.features.nodeHooks?.beforeChange?.size && - !finalSanitizedEditorConfig.features.getSubFields?.size - ) { - return value - } - - /** - * beforeValidate is the first field hook which runs. This is where we can create the node map, which can then be used in the other hooks. - * - */ - - /** - * flattenedNodes contains all nodes in the editor, in the order they appear in the editor. They will be used for the following hooks: - * - afterRead - * - * The other hooks require nodes to have IDs, which is why those are ran only from the nodeIDMap. They require IDs because they have both doc/siblingDoc and data/siblingData, and - * thus require a reliable way to match new node data to old node data. Given that node positions can change in between hooks, this is only reliably possible for nodes which are saved with - * an ID. - */ - //const flattenedNodes: SerializedLexicalNode[] = [] - - /** - * Only nodes with id's (so, nodes with hooks added to them) will be added to the nodeIDMap. They will be used for the following hooks: - * - afterChange - * - beforeChange - * - beforeValidate - * - * Other hooks are handled by the flattenedNodes. All nodes in the nodeIDMap are part of flattenedNodes. - */ - - const originalNodeIDMap: { - [key: string]: SerializedLexicalNode - } = {} - - recurseNodeTree({ - nodeIDMap: originalNodeIDMap, - nodes: (previousValue as SerializedEditorState)?.root?.children ?? [], - }) - - if (!context.internal) { - // Add to context, for other hooks to use - context.internal = {} - } - if (!(context as any).internal.richText) { - ;(context as any).internal.richText = {} - } - ;(context as any).internal.richText[path.join('.')] = { - originalNodeIDMap, - } - - /** - * Now that the maps for all hooks are set up, we can run the validate hook - */ - if (!finalSanitizedEditorConfig.features.nodeHooks?.beforeValidate?.size) { - return value - } - const nodeIDMap: { - [key: string]: SerializedLexicalNode - } = {} - recurseNodeTree({ - //flattenedNodes, - nodeIDMap, - nodes: (value as SerializedEditorState)?.root?.children ?? [], - }) - - // eslint-disable-next-line prefer-const - for (let [id, node] of Object.entries(nodeIDMap)) { - const beforeValidateHooks = - finalSanitizedEditorConfig.features.nodeHooks.beforeValidate - const beforeValidateHooksForNode = beforeValidateHooks?.get(node.type) - if (beforeValidateHooksForNode) { - for (const hook of beforeValidateHooksForNode) { - if (!originalNodeIDMap[id]) { - console.warn( - '(beforeValidate) No original node found for node with id', - id, - 'node:', - node, - 'path', - path.join('.'), - ) - continue - } - node = await hook({ - context, - node, - operation, - originalNode: originalNodeIDMap[id], - overrideAccess: overrideAccess!, - parentRichTextFieldPath: path, - parentRichTextFieldSchemaPath: schemaPath, - req, - }) - } - } - const subFieldFn = finalSanitizedEditorConfig.features.getSubFields?.get(node.type) - const subFieldDataFn = finalSanitizedEditorConfig.features.getSubFieldsData?.get( - node.type, - ) - - if (subFieldFn && subFieldDataFn) { - const subFields = subFieldFn({ node, req }) - const nodeSiblingData = subFieldDataFn({ node, req }) ?? {} - - const nodeSiblingDoc = subFieldDataFn({ node: originalNodeIDMap[id]!, req }) ?? {} - - if (subFields?.length) { - await beforeValidateTraverseFields({ - id, - blockData: nodeSiblingData, - collection, - context, - data, - doc: originalDoc, - fields: subFields, - global, - operation, - overrideAccess: overrideAccess!, - parentIndexPath: indexPath.join('-'), - parentIsLocalized: parentIsLocalized || field.localized || false, - parentPath: path.join('.'), - parentSchemaPath: schemaPath.join('.'), - req, - siblingData: nodeSiblingData, - siblingDoc: nodeSiblingDoc, - }) - } - } - } - - return value - }, - ], - }, - outputSchema: ({ - collectionIDFieldTypes, - config, - field, - i18n, - interfaceNameDefinitions, - isRequired, - }) => { - let outputSchema: JSONSchema4 = { - // This schema matches the SerializedEditorState type so far, that it's possible to cast SerializedEditorState to this schema without any errors. - // In the future, we should - // 1) allow recursive children - // 2) Pass in all the different types for every node added to the editorconfig. This can be done with refs in the schema. - type: withNullableJSONSchemaType('object', isRequired), - properties: { - root: { - type: 'object', - additionalProperties: false, - properties: { - type: { - type: 'string', - }, - children: { - type: 'array', - items: { - type: 'object', - additionalProperties: true, - properties: { - type: { - type: 'string', - tsType: 'any', - }, - version: { - type: 'integer', - }, - }, - required: ['type', 'version'], - }, - }, - direction: { - oneOf: [ - { - enum: ['ltr', 'rtl'], - }, - { - type: 'null', - }, - ], - }, - format: { - type: 'string', - enum: ['left', 'start', 'center', 'right', 'end', 'justify', ''], // ElementFormatType, since the root node is an element - }, - indent: { - type: 'integer', - }, - version: { - type: 'integer', - }, - }, - required: ['children', 'direction', 'format', 'indent', 'type', 'version'], - }, - }, - required: ['root'], - } - for (const modifyOutputSchema of finalSanitizedEditorConfig.features.generatedTypes - .modifyOutputSchemas) { - outputSchema = modifyOutputSchema({ - collectionIDFieldTypes, - config, - currentSchema: outputSchema, - field, - i18n, - interfaceNameDefinitions, - isRequired, - }) - } - - return outputSchema - }, + hooks: getLexicalHooks({ + editorConfig: finalSanitizedEditorConfig, + }), + jsonSchema: getFieldToJSONSchema({ editorConfig: finalSanitizedEditorConfig }), validate: richTextValidateHOC({ editorConfig: finalSanitizedEditorConfig, }), @@ -1047,12 +343,10 @@ export { export { sanitizeUrl, validateUrl } from './lexical/utils/url.js' -export type * from './nodeTypes.js' - export { $convertFromMarkdownString } from './packages/@lexical/markdown/index.js' + export { defaultRichTextValue } from './populateGraphQL/defaultValue.js' export { populate } from './populateGraphQL/populate.js' - export type { ClientFeaturesMap, LexicalEditorNodeMap, @@ -1063,7 +357,9 @@ export type { NodeMapValue, SerializedNodeBase, ViewMapBlockComponentProps, -} from './types.js' +} from './types/index.js' + +export type * from './types/nodeTypes.js' export { buildDefaultEditorState, buildEditorState } from './utilities/buildEditorState.js' export { createServerFeature } from './utilities/createServerFeature.js' diff --git a/packages/richtext-lexical/src/lexical/LexicalProvider.tsx b/packages/richtext-lexical/src/lexical/LexicalProvider.tsx index 71289109d9f..38321563971 100644 --- a/packages/richtext-lexical/src/lexical/LexicalProvider.tsx +++ b/packages/richtext-lexical/src/lexical/LexicalProvider.tsx @@ -7,7 +7,7 @@ import { useEditDepth } from '@payloadcms/ui' import * as React from 'react' import { useMemo } from 'react' -import type { LexicalRichTextFieldProps } from '../types.js' +import type { LexicalRichTextFieldProps } from '../types/index.js' import type { SanitizedClientEditorConfig } from './config/types.js' import { useRichTextView } from '../field/RichTextViewProvider.js' diff --git a/packages/richtext-lexical/src/lexical/config/client/EditorConfigProvider.tsx b/packages/richtext-lexical/src/lexical/config/client/EditorConfigProvider.tsx index fecef560b35..6512223044c 100644 --- a/packages/richtext-lexical/src/lexical/config/client/EditorConfigProvider.tsx +++ b/packages/richtext-lexical/src/lexical/config/client/EditorConfigProvider.tsx @@ -9,7 +9,7 @@ import * as React from 'react' import { createContext, use, useMemo, useRef, useState } from 'react' import type { InlineBlockNode } from '../../../features/blocks/client/nodes/InlineBlocksNode.js' -import type { LexicalRichTextFieldProps } from '../../../types.js' +import type { LexicalRichTextFieldProps } from '../../../types/index.js' import type { SanitizedClientEditorConfig } from '../types.js' // Should always produce a 20 character pseudo-random string diff --git a/packages/richtext-lexical/src/lexical/config/client/loader.ts b/packages/richtext-lexical/src/lexical/config/client/loader.ts index f732c117810..6c95964e7ad 100644 --- a/packages/richtext-lexical/src/lexical/config/client/loader.ts +++ b/packages/richtext-lexical/src/lexical/config/client/loader.ts @@ -7,7 +7,7 @@ import type { ResolvedClientFeature, ResolvedClientFeatureMap, } from '../../../features/typesClient.js' -import type { FeatureClientSchemaMap } from '../../../types.js' +import type { FeatureClientSchemaMap } from '../../../types/index.js' import type { ClientEditorConfig } from '../types.js' /** diff --git a/packages/richtext-lexical/src/lexical/config/client/sanitize.ts b/packages/richtext-lexical/src/lexical/config/client/sanitize.ts index eb3a0da2faa..639b4b47f11 100644 --- a/packages/richtext-lexical/src/lexical/config/client/sanitize.ts +++ b/packages/richtext-lexical/src/lexical/config/client/sanitize.ts @@ -9,7 +9,7 @@ import type { ResolvedClientFeatureMap, SanitizedClientFeatures, } from '../../../features/typesClient.js' -import type { LexicalFieldAdminClientProps } from '../../../types.js' +import type { LexicalFieldAdminClientProps } from '../../../types/index.js' import type { SanitizedClientEditorConfig } from '../types.js' export const sanitizeClientFeatures = ( diff --git a/packages/richtext-lexical/src/lexical/config/server/sanitize.ts b/packages/richtext-lexical/src/lexical/config/server/sanitize.ts index 86d4aaeebde..baeb8560edc 100644 --- a/packages/richtext-lexical/src/lexical/config/server/sanitize.ts +++ b/packages/richtext-lexical/src/lexical/config/server/sanitize.ts @@ -14,7 +14,7 @@ export const sanitizeServerFeatures = ( const sanitized: SanitizedServerFeatures = { enabledFeatures: [], generatedTypes: { - modifyOutputSchemas: [], + modifyJSONSchemas: [], }, getSubFields: new Map(), getSubFieldsData: new Map(), @@ -43,8 +43,8 @@ export const sanitizeServerFeatures = ( } features.forEach((feature) => { - if (feature?.generatedTypes?.modifyOutputSchema) { - sanitized.generatedTypes.modifyOutputSchemas.push(feature.generatedTypes.modifyOutputSchema) + if (feature?.generatedTypes?.modifyJSONSchema) { + sanitized.generatedTypes.modifyJSONSchemas.push(feature.generatedTypes.modifyJSONSchema) } if (feature?.hooks?.beforeValidate?.length) { diff --git a/packages/richtext-lexical/src/lexical/config/types.ts b/packages/richtext-lexical/src/lexical/config/types.ts index 47fbad931e7..1f0138a1202 100644 --- a/packages/richtext-lexical/src/lexical/config/types.ts +++ b/packages/richtext-lexical/src/lexical/config/types.ts @@ -10,7 +10,7 @@ import type { ResolvedServerFeatureMap, SanitizedServerFeatures, } from '../../features/typesServer.js' -import type { LexicalFieldAdminClientProps } from '../../types.js' +import type { LexicalFieldAdminClientProps } from '../../types/index.js' export type ServerEditorConfig = { features: FeatureProviderServer[] diff --git a/packages/richtext-lexical/src/lexical/nodes/index.ts b/packages/richtext-lexical/src/lexical/nodes/index.ts index b7c05bf7e86..c5da4f04633 100644 --- a/packages/richtext-lexical/src/lexical/nodes/index.ts +++ b/packages/richtext-lexical/src/lexical/nodes/index.ts @@ -16,7 +16,7 @@ import type { NodeMapBlockValue, NodeMapInlineBlockValue, NodeMapValue, -} from '../../types.js' +} from '../../types/index.js' import type { SanitizedClientEditorConfig, SanitizedServerEditorConfig } from '../config/types.js' // Store view definitions for each editor and node type diff --git a/packages/richtext-lexical/src/lexical/plugins/SlashMenu/LexicalTypeaheadMenuPlugin/types.ts b/packages/richtext-lexical/src/lexical/plugins/SlashMenu/LexicalTypeaheadMenuPlugin/types.ts index 6d8b7045d31..b0f41fb9080 100644 --- a/packages/richtext-lexical/src/lexical/plugins/SlashMenu/LexicalTypeaheadMenuPlugin/types.ts +++ b/packages/richtext-lexical/src/lexical/plugins/SlashMenu/LexicalTypeaheadMenuPlugin/types.ts @@ -3,7 +3,7 @@ import type { LexicalEditor, Spread } from 'lexical' import type React from 'react' import type { RefObject } from 'react' -import type { FeatureClientSchemaMap } from '../../../../types.js' +import type { FeatureClientSchemaMap } from '../../../../types/index.js' export type SlashMenuItem = { /** The icon which is rendered in your slash menu item. */ diff --git a/packages/richtext-lexical/src/populateGraphQL/populateLexicalPopulationPromises.ts b/packages/richtext-lexical/src/populateGraphQL/populateLexicalPopulationPromises.ts index 73a6c30cdfe..595abc37c10 100644 --- a/packages/richtext-lexical/src/populateGraphQL/populateLexicalPopulationPromises.ts +++ b/packages/richtext-lexical/src/populateGraphQL/populateLexicalPopulationPromises.ts @@ -2,7 +2,7 @@ import type { SerializedEditorState } from 'lexical' import type { RichTextAdapter } from 'payload' import type { PopulationPromise } from '../features/typesServer.js' -import type { AdapterProps } from '../types.js' +import type { AdapterProps } from '../types/index.js' import { recurseNodes } from '../utilities/forEachNodeRecursively.js' diff --git a/packages/richtext-lexical/src/types.ts b/packages/richtext-lexical/src/types/index.ts similarity index 96% rename from packages/richtext-lexical/src/types.ts rename to packages/richtext-lexical/src/types/index.ts index 722a4bbbbf5..115feac1ee2 100644 --- a/packages/richtext-lexical/src/types.ts +++ b/packages/richtext-lexical/src/types/index.ts @@ -21,27 +21,27 @@ import type { StaticLabel, } from 'payload' -import type { BlockComponentContextType } from './features/blocks/client/component/BlockContent.js' +import type { BlockComponentContextType } from '../features/blocks/client/component/BlockContent.js' export type { BlockComponentContextType } -import type { BlockComponentProps } from './features/blocks/client/component/index.js' -import type { InlineBlockComponentContextType } from './features/blocks/client/componentInline/index.js' +import type { BlockComponentProps } from '../features/blocks/client/component/index.js' +import type { InlineBlockComponentContextType } from '../features/blocks/client/componentInline/index.js' import type { JSXConverterArgs, JSXConverters, SerializedLexicalNodeWithParent, -} from './features/converters/lexicalToJSX/converter/types.js' +} from '../features/converters/lexicalToJSX/converter/types.js' import type { BaseClientFeatureProps, FeatureProviderProviderClient, -} from './features/typesClient.js' -import type { FeatureProviderServer } from './features/typesServer.js' -import type { SanitizedServerEditorConfig } from './lexical/config/types.js' +} from '../features/typesClient.js' +import type { FeatureProviderServer } from '../features/typesServer.js' +import type { SanitizedServerEditorConfig } from '../lexical/config/types.js' +import type { InitialLexicalFormState } from '../utilities/buildInitialState.js' import type { DefaultNodeTypes, SerializedBlockNode, SerializedInlineBlockNode, } from './nodeTypes.js' -import type { InitialLexicalFormState } from './utilities/buildInitialState.js' /** * Base constraint for serialized Lexical node types. diff --git a/packages/richtext-lexical/src/nodeTypes.ts b/packages/richtext-lexical/src/types/nodeTypes.ts similarity index 86% rename from packages/richtext-lexical/src/nodeTypes.ts rename to packages/richtext-lexical/src/types/nodeTypes.ts index ae38f9ede32..f41d45782a8 100644 --- a/packages/richtext-lexical/src/nodeTypes.ts +++ b/packages/richtext-lexical/src/types/nodeTypes.ts @@ -7,20 +7,20 @@ import type { SerializedLexicalNode, } from 'lexical' -import type { SerializedQuoteNode } from './features/blockquote/server/index.js' -import type { SerializedBlockNode } from './features/blocks/server/nodes/BlocksNode.js' -import type { SerializedInlineBlockNode } from './features/blocks/server/nodes/InlineBlocksNode.js' +import type { SerializedQuoteNode } from '../features/blockquote/server/index.js' +import type { SerializedBlockNode } from '../features/blocks/server/nodes/BlocksNode.js' +import type { SerializedInlineBlockNode } from '../features/blocks/server/nodes/InlineBlocksNode.js' import type { SerializedTableCellNode, SerializedTableNode, SerializedTableRowNode, -} from './features/experimental_table/server/index.js' -import type { SerializedHeadingNode } from './features/heading/server/index.js' -import type { SerializedHorizontalRuleNode } from './features/horizontalRule/server/nodes/HorizontalRuleNode.js' -import type { SerializedAutoLinkNode, SerializedLinkNode } from './features/link/nodes/types.js' -import type { SerializedListItemNode, SerializedListNode } from './features/lists/plugin/index.js' -import type { SerializedRelationshipNode } from './features/relationship/server/nodes/RelationshipNode.js' -import type { SerializedUploadNode } from './features/upload/server/nodes/UploadNode.js' +} from '../features/experimental_table/server/index.js' +import type { SerializedHeadingNode } from '../features/heading/server/index.js' +import type { SerializedHorizontalRuleNode } from '../features/horizontalRule/server/nodes/HorizontalRuleNode.js' +import type { SerializedAutoLinkNode, SerializedLinkNode } from '../features/link/nodes/types.js' +import type { SerializedListItemNode, SerializedListNode } from '../features/lists/plugin/index.js' +import type { SerializedRelationshipNode } from '../features/relationship/server/nodes/RelationshipNode.js' +import type { SerializedUploadNode } from '../features/upload/server/nodes/UploadNode.js' /** * Helper type to create strongly typed serialized nodes with flexible children types. diff --git a/packages/richtext-lexical/src/types/schema.ts b/packages/richtext-lexical/src/types/schema.ts new file mode 100644 index 00000000000..49b261a3b40 --- /dev/null +++ b/packages/richtext-lexical/src/types/schema.ts @@ -0,0 +1,90 @@ +import type { JSONSchema4 } from 'json-schema' + +import { withNullableJSONSchemaType } from 'payload' + +import type { SanitizedServerEditorConfig } from '../lexical/config/types.js' +import type { LexicalRichTextAdapter } from './index.js' + +export const getFieldToJSONSchema: (args: { + editorConfig: SanitizedServerEditorConfig +}) => LexicalRichTextAdapter['jsonSchema'] = ({ editorConfig }) => { + return ({ + collectionIDFieldTypes, + config, + field, + i18n, + interfaceNameDefinitions, + isRequired, + }) => { + let jsonSchema: JSONSchema4 = { + // This schema matches the SerializedEditorState type so far, that it's possible to cast SerializedEditorState to this schema without any errors. + // In the future, we should + // 1) allow recursive children + // 2) Pass in all the different types for every node added to the editorconfig. This can be done with refs in the schema. + type: withNullableJSONSchemaType('object', isRequired), + properties: { + root: { + type: 'object', + additionalProperties: false, + properties: { + type: { + type: 'string', + }, + children: { + type: 'array', + items: { + type: 'object', + additionalProperties: true, + properties: { + type: { + type: 'string', + tsType: 'any', + }, + version: { + type: 'integer', + }, + }, + required: ['type', 'version'], + }, + }, + direction: { + oneOf: [ + { + enum: ['ltr', 'rtl'], + }, + { + type: 'null', + }, + ], + }, + format: { + type: 'string', + enum: ['left', 'start', 'center', 'right', 'end', 'justify', ''], // ElementFormatType, since the root node is an element + }, + indent: { + type: 'integer', + }, + version: { + type: 'integer', + }, + }, + required: ['children', 'direction', 'format', 'indent', 'type', 'version'], + }, + }, + required: ['root'], + } + for (const modifyJSONSchema of editorConfig.features.generatedTypes.modifyJSONSchemas) { + jsonSchema = modifyJSONSchema({ + collectionIDFieldTypes, + config, + currentSchema: jsonSchema, + field, + i18n, + interfaceNameDefinitions, + isRequired, + }) + } + + return jsonSchema + } +} diff --git a/packages/richtext-lexical/src/utilities/buildEditorState.ts b/packages/richtext-lexical/src/utilities/buildEditorState.ts index 141b0c8c064..3abc8e868e5 100644 --- a/packages/richtext-lexical/src/utilities/buildEditorState.ts +++ b/packages/richtext-lexical/src/utilities/buildEditorState.ts @@ -1,6 +1,10 @@ import type { SerializedLexicalNode } from 'lexical' -import type { DefaultNodeTypes, DefaultTypedEditorState, TypedEditorState } from '../nodeTypes.js' +import type { + DefaultNodeTypes, + DefaultTypedEditorState, + TypedEditorState, +} from '../types/nodeTypes.js' /** * Helper to build lexical editor state JSON from text and/or nodes. diff --git a/packages/richtext-lexical/src/utilities/buildInitialState.ts b/packages/richtext-lexical/src/utilities/buildInitialState.ts index 37ee5498a0a..220cfacfb9b 100644 --- a/packages/richtext-lexical/src/utilities/buildInitialState.ts +++ b/packages/richtext-lexical/src/utilities/buildInitialState.ts @@ -12,7 +12,7 @@ import type { import { fieldSchemasToFormState } from '@payloadcms/ui/forms/fieldSchemasToFormState' -import type { SerializedBlockNode } from '../nodeTypes.js' +import type { SerializedBlockNode } from '../types/nodeTypes.js' export type InitialLexicalFormState = { [nodeID: string]: { diff --git a/packages/richtext-lexical/src/utilities/createClientFeature.ts b/packages/richtext-lexical/src/utilities/createClientFeature.ts index f0204ceed46..a454c344f81 100644 --- a/packages/richtext-lexical/src/utilities/createClientFeature.ts +++ b/packages/richtext-lexical/src/utilities/createClientFeature.ts @@ -9,7 +9,7 @@ import type { ResolvedClientFeatureMap, } from '../features/typesClient.js' import type { ClientEditorConfig } from '../lexical/config/types.js' -import type { FeatureClientSchemaMap } from '../types.js' +import type { FeatureClientSchemaMap } from '../types/index.js' export type CreateClientFeatureArgs = | ((props: { diff --git a/packages/richtext-lexical/src/utilities/editorConfigFactory.ts b/packages/richtext-lexical/src/utilities/editorConfigFactory.ts index 921ff8a523d..d3ddccb6a98 100644 --- a/packages/richtext-lexical/src/utilities/editorConfigFactory.ts +++ b/packages/richtext-lexical/src/utilities/editorConfigFactory.ts @@ -7,7 +7,7 @@ import type { FeaturesInput, LexicalRichTextAdapter, LexicalRichTextAdapterProvider, -} from '../types.js' +} from '../types/index.js' import { defaultEditorConfig, defaultEditorFeatures } from '../lexical/config/server/default.js' import { loadFeatures } from '../lexical/config/server/loader.js' diff --git a/packages/richtext-lexical/src/utilities/generateImportMap.tsx b/packages/richtext-lexical/src/utilities/generateImportMap.tsx index f5a4869d9b9..7cd500d8225 100644 --- a/packages/richtext-lexical/src/utilities/generateImportMap.tsx +++ b/packages/richtext-lexical/src/utilities/generateImportMap.tsx @@ -3,7 +3,7 @@ import type { RichTextAdapter } from 'payload' import { genImportMapIterateFields } from 'payload' import type { ResolvedServerFeatureMap } from '../features/typesServer.js' -import type { LexicalEditorProps } from '../types.js' +import type { LexicalEditorProps } from '../types/index.js' export const getGenerateImportMap = (args: { diff --git a/packages/richtext-lexical/src/utilities/initLexicalFeatures.ts b/packages/richtext-lexical/src/utilities/initLexicalFeatures.ts index b595bf94d79..5c79a90fe00 100644 --- a/packages/richtext-lexical/src/utilities/initLexicalFeatures.ts +++ b/packages/richtext-lexical/src/utilities/initLexicalFeatures.ts @@ -8,7 +8,7 @@ import type { FeatureProviderProviderClient, } from '../features/typesClient.js' import type { SanitizedServerEditorConfig } from '../lexical/config/types.js' -import type { FeatureClientSchemaMap, LexicalRichTextFieldProps } from '../types.js' +import type { FeatureClientSchemaMap, LexicalRichTextFieldProps } from '../types/index.js' type Args = { clientFieldSchemaMap: ClientFieldSchemaMap fieldSchemaMap: FieldSchemaMap diff --git a/packages/richtext-lexical/src/utilities/upgradeLexicalData/upgradeDocumentFieldsRecursively.ts b/packages/richtext-lexical/src/utilities/upgradeLexicalData/upgradeDocumentFieldsRecursively.ts index a3253742ac0..cd17dc196a9 100644 --- a/packages/richtext-lexical/src/utilities/upgradeLexicalData/upgradeDocumentFieldsRecursively.ts +++ b/packages/richtext-lexical/src/utilities/upgradeLexicalData/upgradeDocumentFieldsRecursively.ts @@ -4,7 +4,7 @@ import type { Field, FlattenedBlock, Payload } from 'payload' import { createHeadlessEditor } from '@lexical/headless' import { fieldAffectsData, fieldHasSubFields, fieldIsArrayType, tabHasName } from 'payload/shared' -import type { LexicalRichTextAdapter } from '../../types.js' +import type { LexicalRichTextAdapter } from '../../types/index.js' import { getEnabledNodes } from '../../lexical/nodes/index.js' From e254a3017cb74b94bcd44e6601c7086ef8b931a3 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Wed, 27 May 2026 00:42:04 -0700 Subject: [PATCH 02/56] feat: typeStringDefinitions property in configtojsonschema --- packages/payload/src/admin/RichText.ts | 21 ++- packages/payload/src/bin/generateTypes.ts | 11 +- .../queues/config/generateJobsJSONSchemas.ts | 28 ++-- .../src/utilities/configToJSONSchema.spec.ts | 16 +- .../src/utilities/configToJSONSchema.ts | 149 +++++++++++------- 5 files changed, 136 insertions(+), 89 deletions(-) diff --git a/packages/payload/src/admin/RichText.ts b/packages/payload/src/admin/RichText.ts index 9c318d3e667..4e5f92491e4 100644 --- a/packages/payload/src/admin/RichText.ts +++ b/packages/payload/src/admin/RichText.ts @@ -14,6 +14,7 @@ import type { import type { SanitizedGlobalConfig } from '../globals/config/types.js' import type { RequestContext, TypedFallbackLocale } from '../index.js' import type { JsonObject, PayloadRequest, PopulateType } from '../types/index.js' +import type { FieldsToJSONSchemaArgs } from '../utilities/configToJSONSchema.js' import type { RichTextFieldClientProps, RichTextFieldServerProps } from './fields/RichText.js' import type { FieldDiffClientProps, FieldDiffServerProps, FieldSchemaMap } from './types.js' @@ -249,17 +250,15 @@ type RichTextAdapterBase< * `json-schema-to-typescript` which is used to generate types for this richtext field * payload-types.ts) */ - jsonSchema?: (args: { - collectionIDFieldTypes: { [key: string]: 'number' | 'string' } - config?: SanitizedConfig - field: RichTextField - i18n?: I18n - /** - * Allows you to define new top-level interfaces that can be re-used in the output schema. - */ - interfaceNameDefinitions: Map - isRequired: boolean - }) => JSONSchema4 + jsonSchema?: ( + args: Pick< + FieldsToJSONSchemaArgs, + 'collectionIDFieldTypes' | 'config' | 'i18n' | 'interfaceNameDefinitions' | 'typeStringDefinitions' + > & { + field: RichTextField + isRequired: boolean + }, + ) => JSONSchema4 /** * Provide validation function for the richText field. This function is run the same way * as other field validation functions. diff --git a/packages/payload/src/bin/generateTypes.ts b/packages/payload/src/bin/generateTypes.ts index 1eff65acccf..82c3ecc32bb 100644 --- a/packages/payload/src/bin/generateTypes.ts +++ b/packages/payload/src/bin/generateTypes.ts @@ -29,7 +29,11 @@ export async function generateTypes( const i18n = await initI18n({ config: config.i18n, context: 'api', language }) - const jsonSchema = configToJSONSchema(config, config.db.defaultIDType, i18n) + const { jsonSchema, typeStringDefinitions } = configToJSONSchema( + config, + config.db.defaultIDType, + i18n, + ) const declare = `declare module 'payload' {\n export interface GeneratedTypes extends Config {}\n}` const declareWithTSIgnoreError = `declare module 'payload' {\n // @ts-ignore \n export interface GeneratedTypes extends Config {}\n}` @@ -50,6 +54,11 @@ export async function generateTypes( compiled = addSelectGenericsToGeneratedTypes({ compiledGeneratedTypes: compiled }) + if (typeStringDefinitions.size > 0) { + const block = [...typeStringDefinitions.values()].join('\n\n') + compiled = `${compiled.trimEnd()}\n\n${block}\n` + } + if (config.typescript.postProcess?.length) { for (const fn of config.typescript.postProcess) { compiled = fn({ compiledTypes: compiled, config }) diff --git a/packages/payload/src/queues/config/generateJobsJSONSchemas.ts b/packages/payload/src/queues/config/generateJobsJSONSchemas.ts index 97286cd6fa6..6855dfb2de2 100644 --- a/packages/payload/src/queues/config/generateJobsJSONSchemas.ts +++ b/packages/payload/src/queues/config/generateJobsJSONSchemas.ts @@ -16,6 +16,7 @@ export function generateJobsJSONSchemas( * if they have custom ID fields. */ collectionIDFieldTypes: { [key: string]: 'number' | 'string' }, + typeStringDefinitions: Map, i18n?: I18n, ): { definitions?: Map @@ -39,13 +40,14 @@ export function generateJobsJSONSchemas( required: [], } if (task?.inputSchema?.length) { - const inputJsonSchema = fieldsToJSONSchema( + const inputJsonSchema = fieldsToJSONSchema({ collectionIDFieldTypes, - flattenAllFields({ fields: task.inputSchema }), - interfaceNameDefinitions, config, + fields: flattenAllFields({ fields: task.inputSchema }), i18n, - ) + interfaceNameDefinitions, + typeStringDefinitions, + }) const fullInputJsonSchema: JSONSchema4 = { type: 'object', @@ -58,13 +60,14 @@ export function generateJobsJSONSchemas( ;(fullTaskJsonSchema.required as string[]).push('input') } if (task?.outputSchema?.length) { - const outputJsonSchema = fieldsToJSONSchema( + const outputJsonSchema = fieldsToJSONSchema({ collectionIDFieldTypes, - flattenAllFields({ fields: task.outputSchema }), - interfaceNameDefinitions, config, + fields: flattenAllFields({ fields: task.outputSchema }), i18n, - ) + interfaceNameDefinitions, + typeStringDefinitions, + }) const fullOutputJsonSchema: JSONSchema4 = { type: 'object', @@ -125,13 +128,14 @@ export function generateJobsJSONSchemas( } if (workflow?.inputSchema?.length) { - const inputJsonSchema = fieldsToJSONSchema( + const inputJsonSchema = fieldsToJSONSchema({ collectionIDFieldTypes, - flattenAllFields({ fields: workflow.inputSchema }), - interfaceNameDefinitions, config, + fields: flattenAllFields({ fields: workflow.inputSchema }), i18n, - ) + interfaceNameDefinitions, + typeStringDefinitions, + }) const fullInputJsonSchema: JSONSchema4 = { type: 'object', diff --git a/packages/payload/src/utilities/configToJSONSchema.spec.ts b/packages/payload/src/utilities/configToJSONSchema.spec.ts index 582a24e0b74..0cae8ca2bc6 100644 --- a/packages/payload/src/utilities/configToJSONSchema.spec.ts +++ b/packages/payload/src/utilities/configToJSONSchema.spec.ts @@ -33,7 +33,7 @@ describe('configToJSONSchema', () => { } const sanitizedConfig = await sanitizeConfig(config) - const schema = configToJSONSchema(sanitizedConfig, 'text') + const { jsonSchema: schema } = configToJSONSchema(sanitizedConfig, 'text') expect(schema?.definitions?.test).toStrictEqual({ type: 'object', @@ -120,7 +120,7 @@ describe('configToJSONSchema', () => { } const sanitizedConfig = await sanitizeConfig(config) - const schema = configToJSONSchema(sanitizedConfig, 'text') + const { jsonSchema: schema } = configToJSONSchema(sanitizedConfig, 'text') expect(schema?.definitions?.test).toStrictEqual({ type: 'object', @@ -244,7 +244,7 @@ describe('configToJSONSchema', () => { } const sanitizedConfig = await sanitizeConfig(config) - const schema = configToJSONSchema(sanitizedConfig, 'text') + const { jsonSchema: schema } = configToJSONSchema(sanitizedConfig, 'text') expect(schema?.definitions?.test).toStrictEqual({ type: 'object', @@ -319,7 +319,7 @@ describe('configToJSONSchema', () => { } const sanitizedConfig = await sanitizeConfig(config as Config) - const schema = configToJSONSchema(sanitizedConfig, 'text') + const { jsonSchema: schema } = configToJSONSchema(sanitizedConfig, 'text') expect(schema?.definitions?.test).toStrictEqual({ type: 'object', @@ -386,7 +386,7 @@ describe('configToJSONSchema', () => { )?.editor, ).toBe('object') - const schema = configToJSONSchema(sanitizedConfig, 'text') + const { jsonSchema: schema } = configToJSONSchema(sanitizedConfig, 'text') const expectedBlockSchema = { type: 'object', @@ -452,7 +452,7 @@ describe('configToJSONSchema', () => { } const sanitizedConfig = await sanitizeConfig(config) - const schema = configToJSONSchema(sanitizedConfig, 'text') + const { jsonSchema: schema } = configToJSONSchema(sanitizedConfig, 'text') // @ts-expect-error expect(schema.definitions.test.properties.title.required).toStrictEqual(false) @@ -490,13 +490,13 @@ describe('configToJSONSchema', () => { const sanitizedConfig = await sanitizeConfig(config) // Without forceInlineBlocks: blocks field uses $ref - const schemaDefault = configToJSONSchema(sanitizedConfig, 'text') + const { jsonSchema: schemaDefault } = configToJSONSchema(sanitizedConfig, 'text') const arrItemsDefault = schemaDefault.definitions!.test.properties!.arr.items as JSONSchema4 const arrBlocksDefault = (arrItemsDefault.properties!.blocks.items as JSONSchema4).oneOf![0] expect(arrBlocksDefault).toStrictEqual({ $ref: '#/definitions/MyBlock' }) // With forceInlineBlocks: blocks field is inlined, no $ref - const schemaInline = configToJSONSchema(sanitizedConfig, 'text', undefined, { + const { jsonSchema: schemaInline } = configToJSONSchema(sanitizedConfig, 'text', undefined, { forceInlineBlocks: true, }) const arrItemsInline = schemaInline.definitions!.test.properties!.arr.items as JSONSchema4 diff --git a/packages/payload/src/utilities/configToJSONSchema.ts b/packages/payload/src/utilities/configToJSONSchema.ts index 5de17f5094d..ecc74282ee6 100644 --- a/packages/payload/src/utilities/configToJSONSchema.ts +++ b/packages/payload/src/utilities/configToJSONSchema.ts @@ -155,15 +155,17 @@ function getAllowedWidgetWidths({ function generateWidgetSchemas({ collectionIDFieldTypes, config, + forceInlineBlocks, i18n, interfaceNameDefinitions, - opts = {}, + typeStringDefinitions, }: { collectionIDFieldTypes: { [key: string]: 'number' | 'string' } config: SanitizedConfig + forceInlineBlocks?: boolean i18n?: I18n interfaceNameDefinitions: Map - opts?: ConfigToJSONSchemaOptions + typeStringDefinitions: Map }): { definitions: Record schema: JSONSchema4 @@ -181,14 +183,15 @@ function generateWidgetSchemas({ let dataSchema: JSONSchema4 if (widget.fields?.length) { - const widgetFieldSchemas = fieldsToJSONSchema( + const widgetFieldSchemas = fieldsToJSONSchema({ collectionIDFieldTypes, - flattenAllFields({ fields: widget.fields }), - interfaceNameDefinitions, config, + fields: flattenAllFields({ fields: widget.fields }), + forceInlineBlocks, i18n, - opts, - ) + interfaceNameDefinitions, + typeStringDefinitions, + }) dataSchema = { type: 'object', @@ -350,22 +353,41 @@ type ConfigToJSONSchemaOptions = { forceInlineBlocks?: boolean } -export function fieldsToJSONSchema( +export type FieldsToJSONSchemaArgs = { /** - * Used for relationship fields, to determine whether to use a string or number type for the ID. - * While there is a default ID field type set by the db adapter, they can differ on a collection-level - * if they have custom ID fields. + * Used for relationship fields, to determine whether to use a string or + * number type for the ID. While there is a default ID field type set by + * the db adapter, they can differ on a collection-level if they have + * custom ID fields. */ - collectionIDFieldTypes: { [key: string]: 'number' | 'string' }, - fields: FlattenedField[], + collectionIDFieldTypes: { [key: string]: 'number' | 'string' } + config?: SanitizedConfig + fields: FlattenedField[] /** - * Allows you to define new top-level interfaces that can be re-used in the output schema. + * If true, blocks are inlined into each `block` field instead of being + * lifted to a top-level definition. Used by the MCP plugin. */ - interfaceNameDefinitions: Map, - config?: SanitizedConfig, - i18n?: I18n, - opts: ConfigToJSONSchemaOptions = {}, -): { + forceInlineBlocks?: boolean + i18n?: I18n + /** Allows you to define new top-level interfaces that can be re-used in the output schema. */ + interfaceNameDefinitions: Map + /** + * Allows you to append raw TS source to `payload-types.ts`. Keys are used + * for de-duplication - identical keys overwrite, so the same string written + * from many fields ends up emitted once. + */ + typeStringDefinitions: Map +} + +export function fieldsToJSONSchema({ + collectionIDFieldTypes, + config, + fields, + forceInlineBlocks, + i18n, + interfaceNameDefinitions, + typeStringDefinitions, +}: FieldsToJSONSchemaArgs): { properties: { [k: string]: JSONSchema4 } @@ -394,14 +416,15 @@ export function fieldsToJSONSchema( items: { type: 'object', additionalProperties: false, - ...fieldsToJSONSchema( + ...fieldsToJSONSchema({ collectionIDFieldTypes, - field.flattenedFields, - interfaceNameDefinitions, config, + fields: field.flattenedFields, + forceInlineBlocks, i18n, - opts, - ), + interfaceNameDefinitions, + typeStringDefinitions, + }), }, } @@ -435,7 +458,7 @@ export function fieldsToJSONSchema( return {} } - if (!opts.forceInlineBlocks) { + if (!forceInlineBlocks) { return { $ref: `#/definitions/${resolvedBlock.interfaceName ?? resolvedBlock.slug}`, } @@ -443,14 +466,15 @@ export function fieldsToJSONSchema( block = resolvedBlock } - const blockFieldSchemas = fieldsToJSONSchema( + const blockFieldSchemas = fieldsToJSONSchema({ collectionIDFieldTypes, - block.flattenedFields, - interfaceNameDefinitions, config, + fields: block.flattenedFields, + forceInlineBlocks, i18n, - opts, - ) + interfaceNameDefinitions, + typeStringDefinitions, + }) const blockSchema: JSONSchema4 = { type: 'object', @@ -464,7 +488,7 @@ export function fieldsToJSONSchema( required: ['blockType', ...blockFieldSchemas.required], } - if (!opts.forceInlineBlocks && block.interfaceName) { + if (!forceInlineBlocks && block.interfaceName) { interfaceNameDefinitions.set(block.interfaceName, blockSchema) return { @@ -503,14 +527,15 @@ export function fieldsToJSONSchema( ...baseFieldSchema, type: 'object', additionalProperties: false, - ...fieldsToJSONSchema( + ...fieldsToJSONSchema({ collectionIDFieldTypes, - field.flattenedFields, - interfaceNameDefinitions, config, + fields: field.flattenedFields, + forceInlineBlocks, i18n, - opts, - ), + interfaceNameDefinitions, + typeStringDefinitions, + }), } if (field.interfaceName) { @@ -744,6 +769,7 @@ export function fieldsToJSONSchema( i18n, interfaceNameDefinitions, isRequired, + typeStringDefinitions, }), } } else { @@ -819,14 +845,15 @@ export function fieldsToJSONSchema( ...baseFieldSchema, type: 'object', additionalProperties: false, - ...fieldsToJSONSchema( + ...fieldsToJSONSchema({ collectionIDFieldTypes, - field.flattenedFields, - interfaceNameDefinitions, config, + fields: field.flattenedFields, + forceInlineBlocks, i18n, - opts, - ), + interfaceNameDefinitions, + typeStringDefinitions, + }), } if (field.interfaceName) { @@ -883,9 +910,10 @@ export function entityToJSONSchema( entity: SanitizedCollectionConfig | SanitizedGlobalConfig, interfaceNameDefinitions: Map, defaultIDType: 'number' | 'text', + typeStringDefinitions: Map, collectionIDFieldTypes?: { [key: string]: 'number' | 'string' }, i18n?: I18n, - opts: ConfigToJSONSchemaOptions = {}, + forceInlineBlocks?: boolean, ): JSONSchema4 { if (!collectionIDFieldTypes) { collectionIDFieldTypes = getCollectionIDFieldTypes({ config, defaultIDType }) @@ -940,14 +968,15 @@ export function entityToJSONSchema( const isAuthCollection = 'auth' in entity && entity.auth - const fieldsSchema = fieldsToJSONSchema( + const fieldsSchema = fieldsToJSONSchema({ collectionIDFieldTypes, - mutableFields, - interfaceNameDefinitions, config, + fields: mutableFields, + forceInlineBlocks, i18n, - opts, - ) + interfaceNameDefinitions, + typeStringDefinitions, + }) // Add collection property to auth collections if (isAuthCollection) { @@ -1260,10 +1289,12 @@ export function configToJSONSchema( config: SanitizedConfig, defaultIDType?: 'number' | 'text', i18n?: I18n, - opts: ConfigToJSONSchemaOptions = {}, -): JSONSchema4 { + { forceInlineBlocks }: ConfigToJSONSchemaOptions = {}, +): { jsonSchema: JSONSchema4; typeStringDefinitions: Map } { // a mutable Map to store custom top-level `interfaceName` types. Fields with an `interfaceName` property will be moved to the top-level definitions here const interfaceNameDefinitions: Map = new Map() + // a mutable Map for raw TS source to be appended to `payload-types.ts`. + const typeStringDefinitions: Map = new Map() // Used for relationship fields, to determine whether to use a string or number type for the ID. const collectionIDFieldTypes = getCollectionIDFieldTypes({ @@ -1292,9 +1323,10 @@ export function configToJSONSchema( entity, interfaceNameDefinitions, defaultIDType!, + typeStringDefinitions, collectionIDFieldTypes, i18n, - opts, + forceInlineBlocks, ) const select = fieldsToSelectJSONSchema({ config, @@ -1323,9 +1355,10 @@ export function configToJSONSchema( const widgetSchemas = generateWidgetSchemas({ collectionIDFieldTypes, config, + forceInlineBlocks, i18n, interfaceNameDefinitions, - opts, + typeStringDefinitions, }) const authOperationDefinitions = [...config.collections] @@ -1344,6 +1377,7 @@ export function configToJSONSchema( config.jobs, interfaceNameDefinitions, collectionIDFieldTypes, + typeStringDefinitions, i18n, ) : {} @@ -1356,14 +1390,15 @@ export function configToJSONSchema( } if (config?.blocks?.length) { for (const block of config.blocks) { - const blockFieldSchemas = fieldsToJSONSchema( + const blockFieldSchemas = fieldsToJSONSchema({ collectionIDFieldTypes, - block.flattenedFields, - interfaceNameDefinitions, config, + fields: block.flattenedFields, + forceInlineBlocks, i18n, - opts, - ) + interfaceNameDefinitions, + typeStringDefinitions, + }) const blockSchema: JSONSchema4 = { type: 'object', @@ -1459,5 +1494,5 @@ export function configToJSONSchema( } } - return jsonSchema + return { jsonSchema, typeStringDefinitions } } From c07ec8803d4b5734441438dd80c5a55012a69e58 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Wed, 27 May 2026 00:42:38 -0700 Subject: [PATCH 03/56] breakage --- packages/plugin-mcp/src/mcp/getMcpHandler.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/plugin-mcp/src/mcp/getMcpHandler.ts b/packages/plugin-mcp/src/mcp/getMcpHandler.ts index c03981b7690..08cdd7a4530 100644 --- a/packages/plugin-mcp/src/mcp/getMcpHandler.ts +++ b/packages/plugin-mcp/src/mcp/getMcpHandler.ts @@ -49,9 +49,14 @@ export const getMCPHandler = ( req: PayloadRequest, ) => { const { payload } = req - const configSchema = configToJSONSchema(payload.config, payload.db.defaultIDType, req.i18n, { - forceInlineBlocks: true, - }) + const { jsonSchema: configSchema } = configToJSONSchema( + payload.config, + payload.db.defaultIDType, + req.i18n, + { + forceInlineBlocks: true, + }, + ) // Handler wrapper that injects req before the _extra argument const wrapHandler = (handler: (...args: any[]) => any) => { From d77a30c56304a62eaf856d8fce119acf04205a1d Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Wed, 27 May 2026 00:55:06 -0700 Subject: [PATCH 04/56] export type --- packages/payload/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/payload/src/index.ts b/packages/payload/src/index.ts index 4daa5d612e2..8c62b7185c9 100644 --- a/packages/payload/src/index.ts +++ b/packages/payload/src/index.ts @@ -1840,6 +1840,7 @@ export { commitTransaction } from './utilities/commitTransaction.js' export { configToJSONSchema, entityToJSONSchema, + type FieldsToJSONSchemaArgs, fieldsToJSONSchema, withNullableJSONSchemaType, } from './utilities/configToJSONSchema.js' From 8ea07bea6f1e4c0a4c9c4b66f2c91f35b804ca3c Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Wed, 27 May 2026 22:17:59 -0700 Subject: [PATCH 05/56] make typeStringDefinitions a set --- packages/payload/src/bin/generateTypes.ts | 2 +- .../queues/config/generateJobsJSONSchemas.ts | 2 +- .../src/utilities/configToJSONSchema.ts | 18 +++++++++--------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/payload/src/bin/generateTypes.ts b/packages/payload/src/bin/generateTypes.ts index 82c3ecc32bb..764f2b40898 100644 --- a/packages/payload/src/bin/generateTypes.ts +++ b/packages/payload/src/bin/generateTypes.ts @@ -55,7 +55,7 @@ export async function generateTypes( compiled = addSelectGenericsToGeneratedTypes({ compiledGeneratedTypes: compiled }) if (typeStringDefinitions.size > 0) { - const block = [...typeStringDefinitions.values()].join('\n\n') + const block = [...typeStringDefinitions].join('\n\n') compiled = `${compiled.trimEnd()}\n\n${block}\n` } diff --git a/packages/payload/src/queues/config/generateJobsJSONSchemas.ts b/packages/payload/src/queues/config/generateJobsJSONSchemas.ts index 6855dfb2de2..00f5d28b1f4 100644 --- a/packages/payload/src/queues/config/generateJobsJSONSchemas.ts +++ b/packages/payload/src/queues/config/generateJobsJSONSchemas.ts @@ -16,7 +16,7 @@ export function generateJobsJSONSchemas( * if they have custom ID fields. */ collectionIDFieldTypes: { [key: string]: 'number' | 'string' }, - typeStringDefinitions: Map, + typeStringDefinitions: Set, i18n?: I18n, ): { definitions?: Map diff --git a/packages/payload/src/utilities/configToJSONSchema.ts b/packages/payload/src/utilities/configToJSONSchema.ts index ecc74282ee6..1e59191b015 100644 --- a/packages/payload/src/utilities/configToJSONSchema.ts +++ b/packages/payload/src/utilities/configToJSONSchema.ts @@ -165,7 +165,7 @@ function generateWidgetSchemas({ forceInlineBlocks?: boolean i18n?: I18n interfaceNameDefinitions: Map - typeStringDefinitions: Map + typeStringDefinitions: Set }): { definitions: Record schema: JSONSchema4 @@ -372,11 +372,11 @@ export type FieldsToJSONSchemaArgs = { /** Allows you to define new top-level interfaces that can be re-used in the output schema. */ interfaceNameDefinitions: Map /** - * Allows you to append raw TS source to `payload-types.ts`. Keys are used - * for de-duplication - identical keys overwrite, so the same string written - * from many fields ends up emitted once. + * Allows you to append raw TS source to `payload-types.ts`. Identical + * strings de-dupe naturally, so the same helper written from many fields + * ends up emitted once. */ - typeStringDefinitions: Map + typeStringDefinitions: Set } export function fieldsToJSONSchema({ @@ -910,7 +910,7 @@ export function entityToJSONSchema( entity: SanitizedCollectionConfig | SanitizedGlobalConfig, interfaceNameDefinitions: Map, defaultIDType: 'number' | 'text', - typeStringDefinitions: Map, + typeStringDefinitions: Set, collectionIDFieldTypes?: { [key: string]: 'number' | 'string' }, i18n?: I18n, forceInlineBlocks?: boolean, @@ -1290,11 +1290,11 @@ export function configToJSONSchema( defaultIDType?: 'number' | 'text', i18n?: I18n, { forceInlineBlocks }: ConfigToJSONSchemaOptions = {}, -): { jsonSchema: JSONSchema4; typeStringDefinitions: Map } { +): { jsonSchema: JSONSchema4; typeStringDefinitions: Set } { // a mutable Map to store custom top-level `interfaceName` types. Fields with an `interfaceName` property will be moved to the top-level definitions here const interfaceNameDefinitions: Map = new Map() - // a mutable Map for raw TS source to be appended to `payload-types.ts`. - const typeStringDefinitions: Map = new Map() + // a mutable Set for raw TS source to be appended to `payload-types.ts`. + const typeStringDefinitions: Set = new Set() // Used for relationship fields, to determine whether to use a string or number type for the ID. const collectionIDFieldTypes = getCollectionIDFieldTypes({ From bb6c5f277ede7ff480a8a05b7220297ef92c1b9e Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Wed, 27 May 2026 22:28:42 -0700 Subject: [PATCH 06/56] feat: type-safe lexical schemas --- .../src/features/blockquote/server/index.ts | 10 +- .../src/features/blockquote/server/schema.ts | 24 +++ .../src/features/blocks/server/index.ts | 63 +++--- .../blocks/server/nodes/BlocksNode.tsx | 28 +-- .../blocks/server/nodes/InlineBlocksNode.tsx | 15 +- .../src/features/blocks/server/schema.ts | 179 ++++++++++++++++++ .../experimental_table/server/index.ts | 26 +-- .../experimental_table/server/schema.ts | 93 +++++++++ .../src/features/heading/server/index.ts | 13 +- .../src/features/heading/server/schema.ts | 45 +++++ .../features/horizontalRule/server/index.ts | 4 + .../server/nodes/HorizontalRuleNode.tsx | 12 +- .../features/horizontalRule/server/schema.ts | 28 +++ .../src/features/link/nodes/types.ts | 38 +--- .../src/features/link/server/index.ts | 10 +- .../src/features/link/server/schema.ts | 135 +++++++++++++ .../features/lists/checklist/server/index.ts | 3 + .../lists/orderedList/server/index.ts | 3 + .../src/features/lists/plugin/index.tsx | 17 +- .../src/features/lists/shared/schema.ts | 68 +++++++ .../lists/unorderedList/server/index.ts | 3 + .../client/utils/useEnabledRelationships.tsx | 57 ++---- .../src/features/relationship/server/index.ts | 4 + .../server/nodes/RelationshipNode.tsx | 16 +- .../features/relationship/server/schema.ts | 82 ++++++++ .../filterEnabledRelationshipCollections.ts | 59 ++++++ .../src/features/typesServer.ts | 27 +++ .../src/features/upload/server/index.ts | 15 +- .../upload/server/nodes/UploadNode.tsx | 75 +------- .../src/features/upload/server/schema.ts | 143 ++++++++++++++ .../src/lexical/config/server/sanitize.ts | 11 ++ .../src/types/builtInNodes.ts | 176 +++++++++++++++++ .../src/types/jsonSchemaHelpers.ts | 54 ++++++ .../richtext-lexical/src/types/nodeTypes.ts | 65 +++---- packages/richtext-lexical/src/types/schema.ts | 131 +++++++------ 35 files changed, 1364 insertions(+), 368 deletions(-) create mode 100644 packages/richtext-lexical/src/features/blockquote/server/schema.ts create mode 100644 packages/richtext-lexical/src/features/blocks/server/schema.ts create mode 100644 packages/richtext-lexical/src/features/experimental_table/server/schema.ts create mode 100644 packages/richtext-lexical/src/features/heading/server/schema.ts create mode 100644 packages/richtext-lexical/src/features/horizontalRule/server/schema.ts create mode 100644 packages/richtext-lexical/src/features/link/server/schema.ts create mode 100644 packages/richtext-lexical/src/features/lists/shared/schema.ts create mode 100644 packages/richtext-lexical/src/features/relationship/server/schema.ts create mode 100644 packages/richtext-lexical/src/features/relationship/shared/filterEnabledRelationshipCollections.ts create mode 100644 packages/richtext-lexical/src/features/upload/server/schema.ts create mode 100644 packages/richtext-lexical/src/types/builtInNodes.ts create mode 100644 packages/richtext-lexical/src/types/jsonSchemaHelpers.ts diff --git a/packages/richtext-lexical/src/features/blockquote/server/index.ts b/packages/richtext-lexical/src/features/blockquote/server/index.ts index add401d88e8..dfc86763ea4 100644 --- a/packages/richtext-lexical/src/features/blockquote/server/index.ts +++ b/packages/richtext-lexical/src/features/blockquote/server/index.ts @@ -1,17 +1,12 @@ -import type { SerializedQuoteNode as _SerializedQuoteNode } from '@lexical/rich-text' -import type { SerializedLexicalNode } from 'lexical' - import { QuoteNode } from '@lexical/rich-text' -import type { StronglyTypedElementNode } from '../../../types/nodeTypes.js' - import { createServerFeature } from '../../../utilities/createServerFeature.js' import { createNode } from '../../typeUtilities.js' import { MarkdownTransformer } from '../markdownTransformer.js' import { i18n } from './i18n.js' +import { quoteNodeJSONSchema } from './schema.js' -export type SerializedQuoteNode = - StronglyTypedElementNode<_SerializedQuoteNode, 'quote', T> +export type { SerializedQuoteNode } from './schema.js' export const BlockquoteFeature = createServerFeature({ feature: { @@ -21,6 +16,7 @@ export const BlockquoteFeature = createServerFeature({ markdownTransformers: [MarkdownTransformer], nodes: [ createNode({ + jsonSchema: quoteNodeJSONSchema, node: QuoteNode, }), ], diff --git a/packages/richtext-lexical/src/features/blockquote/server/schema.ts b/packages/richtext-lexical/src/features/blockquote/server/schema.ts new file mode 100644 index 00000000000..123995574f2 --- /dev/null +++ b/packages/richtext-lexical/src/features/blockquote/server/schema.ts @@ -0,0 +1,24 @@ +import type { SerializedQuoteNode as _SerializedQuoteNode } from '@lexical/rich-text' +import type { SerializedLexicalNode } from 'lexical' + +import type { StronglyTypedElementNode } from '../../../types/nodeTypes.js' +import type { JSONSchemaFn } from '../../typesServer.js' + +export type SerializedQuoteNode = + StronglyTypedElementNode<_SerializedQuoteNode, 'quote', TChildren> + +const SERIALIZED_QUOTE_NODE_TS = `export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +}` + +export const quoteNodeJSONSchema: JSONSchemaFn = ({ + elementNodeSchema, + nodeUnionName, + typeStringDefinitions, +}) => { + typeStringDefinitions.add(SERIALIZED_QUOTE_NODE_TS) + return elementNodeSchema({ + nodeType: 'quote', + tsType: `SerializedQuoteNode<${nodeUnionName}>`, + }) +} diff --git a/packages/richtext-lexical/src/features/blocks/server/index.ts b/packages/richtext-lexical/src/features/blocks/server/index.ts index 6f3ddab845b..7f355984e53 100644 --- a/packages/richtext-lexical/src/features/blocks/server/index.ts +++ b/packages/richtext-lexical/src/features/blocks/server/index.ts @@ -11,6 +11,8 @@ import type { import { fieldsToJSONSchema, flattenAllFields, sanitizeFields } from 'payload' +import type { NodeWithHooks } from '../../typesServer.js' + import { applyBaseFilterToFields } from '../../../utilities/applyBaseFilterToFields.js' import { createServerFeature } from '../../../utilities/createServerFeature.js' import { createNode } from '../../typeUtilities.js' @@ -19,8 +21,17 @@ import { i18n } from './i18n.js' import { getBlockMarkdownTransformers } from './markdown/markdownTransformer.js' import { ServerBlockNode } from './nodes/BlocksNode.js' import { ServerInlineBlockNode } from './nodes/InlineBlocksNode.js' +import { createBlockNodeJSONSchema, createInlineBlockNodeJSONSchema } from './schema.js' import { blockValidationHOC } from './validate.js' +export type { + BlockFields, + BlockFieldsOptionalID, + InlineBlockFields, + SerializedBlockNode, + SerializedInlineBlockNode, +} from './schema.js' + export type BlocksFeatureProps = { blocks?: (Block | BlockSlug)[] | Block[] inlineBlocks?: (Block | BlockSlug)[] | Block[] @@ -95,6 +106,7 @@ export const BlocksFeature = createServerFeature { if (!blockConfigs?.length && !inlineBlockConfigs?.length) { return currentSchema @@ -130,13 +142,14 @@ export const BlocksFeature = createServerFeature { if (!node) { - if (blockConfigs?.length) { - return [ - { - name: 'lexical_blocks', - type: 'blocks', - blocks: blockConfigs, - }, - ] - } - return [] + return [ + { + name: 'lexical_blocks', + type: 'blocks', + blocks: blockConfigs, + }, + ] } const blockType = node.fields.blockType - - const block = blockConfigs?.find((block) => block.slug === blockType) + const block = blockConfigs.find((block) => block.slug === blockType) return block?.fields }, getSubFieldsData: ({ node }) => { @@ -244,24 +254,21 @@ export const BlocksFeature = createServerFeature { if (!node) { - if (inlineBlockConfigs?.length) { - return [ - { - name: 'lexical_inline_blocks', - type: 'blocks', - blocks: inlineBlockConfigs, - }, - ] - } - return [] + return [ + { + name: 'lexical_inline_blocks', + type: 'blocks', + blocks: inlineBlockConfigs, + }, + ] } const blockType = node.fields.blockType - - const block = inlineBlockConfigs?.find((block) => block.slug === blockType) + const block = inlineBlockConfigs.find((block) => block.slug === blockType) return block?.fields }, getSubFieldsData: ({ node }) => { diff --git a/packages/richtext-lexical/src/features/blocks/server/nodes/BlocksNode.tsx b/packages/richtext-lexical/src/features/blocks/server/nodes/BlocksNode.tsx index a6b8101a84a..aa59493434e 100644 --- a/packages/richtext-lexical/src/features/blocks/server/nodes/BlocksNode.tsx +++ b/packages/richtext-lexical/src/features/blocks/server/nodes/BlocksNode.tsx @@ -1,5 +1,3 @@ -import type { SerializedDecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode.js' -import type { JsonObject } from 'payload' import type { JSX } from 'react' import { DecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode.js' @@ -16,25 +14,15 @@ import { type NodeKey, } from 'lexical' -import type { StronglyTypedLeafNode } from '../../../../types/nodeTypes.js' +import type { BlockFields, BlockFieldsOptionalID, SerializedBlockNode } from '../schema.js' -type BaseBlockFields = { - /** Block form data */ - blockName: string - blockType: string -} & TBlockFields - -export type BlockFields = { - id: string -} & BaseBlockFields - -export type BlockFieldsOptionalID = { - id?: string -} & BaseBlockFields - -export type SerializedBlockNode = { - fields: BlockFields -} & StronglyTypedLeafNode +// Re-export the runtime types from the colocated schema module so existing +// imports of this path keep working. +export type { + BlockFields, + BlockFieldsOptionalID, + SerializedBlockNode, +} from '../schema.js' export class ServerBlockNode extends DecoratorBlockNode { __cacheBuster: number diff --git a/packages/richtext-lexical/src/features/blocks/server/nodes/InlineBlocksNode.tsx b/packages/richtext-lexical/src/features/blocks/server/nodes/InlineBlocksNode.tsx index 5611562100e..282527bbfc8 100644 --- a/packages/richtext-lexical/src/features/blocks/server/nodes/InlineBlocksNode.tsx +++ b/packages/richtext-lexical/src/features/blocks/server/nodes/InlineBlocksNode.tsx @@ -5,9 +5,7 @@ import type { LexicalEditor, LexicalNode, NodeKey, - SerializedLexicalNode, } from 'lexical' -import type { JsonObject } from 'payload' import type React from 'react' import type { JSX } from 'react' @@ -15,16 +13,11 @@ import { addClassNamesToElement } from '@lexical/utils' import ObjectID from 'bson-objectid' import { $applyNodeReplacement, DecoratorNode } from 'lexical' -import type { StronglyTypedLeafNode } from '../../../../types/nodeTypes.js' +import type { InlineBlockFields, SerializedInlineBlockNode } from '../schema.js' -export type InlineBlockFields = { - blockType: string - id: string -} & TInlineBlockFields - -export type SerializedInlineBlockNode = { - fields: InlineBlockFields -} & StronglyTypedLeafNode +// Re-export the runtime types from the colocated schema module so existing +// imports of this path keep working. +export type { InlineBlockFields, SerializedInlineBlockNode } from '../schema.js' export class ServerInlineBlockNode extends DecoratorNode { __cacheBuster: number diff --git a/packages/richtext-lexical/src/features/blocks/server/schema.ts b/packages/richtext-lexical/src/features/blocks/server/schema.ts new file mode 100644 index 00000000000..13af760bd3a --- /dev/null +++ b/packages/richtext-lexical/src/features/blocks/server/schema.ts @@ -0,0 +1,179 @@ +import type { SerializedDecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode.js' +import type { JSONSchema4 } from 'json-schema' +import type { SerializedLexicalNode } from 'lexical' +import type { Block, JsonObject } from 'payload' + +import { fieldsToJSONSchema, flattenAllFields } from 'payload' + +import type { StronglyTypedLeafNode } from '../../../types/nodeTypes.js' +import type { JSONSchemaArgs, JSONSchemaFn } from '../../typesServer.js' + +import { formatSchema } from '../../../types/jsonSchemaHelpers.js' + +type BaseBlockFields = { + blockName: string + blockType: string +} & TFields + +export type BlockFields = { + id: string +} & BaseBlockFields + +export type BlockFieldsOptionalID = { + id?: string +} & BaseBlockFields + +export type InlineBlockFields = { + blockType: string + id: string +} & TFields + +export type SerializedBlockNode = { + fields: BlockFields +} & StronglyTypedLeafNode + +export type SerializedInlineBlockNode = { + fields: InlineBlockFields +} & StronglyTypedLeafNode + +const BLOCK_NODES_TS = `export type SerializedBlockNode = { + type: 'block'; + format: LexicalElementFormat; + version: number; + fields: { id: string; blockName: string | null } & Omit; +}; +export type SerializedInlineBlockNode = { + type: 'inlineBlock'; + version: number; + fields: { id: string } & Omit; +};` + +/** + * Per-block `fields` schema. Strips Payload's auto-added `id`/`blockName` + * (every block carries those as base fields) and re-adds them with strict + * runtime types — required, non-null `id`; required `blockName: string | null` + * (omitted for inline blocks). + * + * Blocks with `interfaceName` are emitted as top-level `$ref` definitions. + */ +const buildBlockVariantSchema = ( + block: Block, + args: JSONSchemaArgs, + { isInlineBlock }: { isInlineBlock: boolean }, +): JSONSchema4 => { + const flattened = flattenAllFields({ fields: block.fields }) + const userFieldsSchema = args.config + ? fieldsToJSONSchema({ + collectionIDFieldTypes: args.collectionIDFieldTypes, + config: args.config, + fields: flattened, + i18n: args.i18n, + interfaceNameDefinitions: args.interfaceNameDefinitions, + typeStringDefinitions: args.typeStringDefinitions, + }) + : { properties: {}, required: [] } + + const { + id: _stripId, + blockName: _stripBlockName, + ...userOnlyProperties + } = (userFieldsSchema.properties ?? {}) as { [k: string]: JSONSchema4 } + const userOnlyRequired = (userFieldsSchema.required ?? []).filter( + (r) => r !== 'id' && r !== 'blockName', + ) + + const properties: { [k: string]: JSONSchema4 } = { + id: { type: 'string' }, + blockType: { type: 'string', const: block.slug }, + ...userOnlyProperties, + } + const required = ['id', 'blockType', ...userOnlyRequired] + + if (!isInlineBlock) { + properties.blockName = { type: ['string', 'null'] } + required.push('blockName') + } + + const variantSchema: JSONSchema4 = { + type: 'object', + additionalProperties: false, + properties, + required, + } + + if (block.interfaceName) { + args.interfaceNameDefinitions.set(block.interfaceName, variantSchema) + return { $ref: `#/definitions/${block.interfaceName}` } + } + + return variantSchema +} + +export const createBlockNodeJSONSchema = + (blockConfigs: Block[]): JSONSchemaFn => + (args) => { + args.typeStringDefinitions.add(BLOCK_NODES_TS) + const variants = blockConfigs.map((block) => + buildBlockVariantSchema(block, args, { isInlineBlock: false }), + ) + + const fieldsSchema: JSONSchema4 = + variants.length === 0 + ? { type: 'object', additionalProperties: true } + : variants.length === 1 + ? variants[0]! + : { oneOf: variants } + + const allHaveInterfaceName = + blockConfigs.length > 0 && blockConfigs.every((b) => Boolean(b.interfaceName)) + const tsType = allHaveInterfaceName + ? `SerializedBlockNode<${blockConfigs.map((b) => b.interfaceName!).join(' | ')}>` + : undefined + + return { + type: 'object', + additionalProperties: false, + ...(tsType ? { tsType } : {}), + properties: { + type: { type: 'string', const: 'block' }, + fields: fieldsSchema, + format: formatSchema, + version: { type: 'integer' }, + }, + required: ['fields', 'format', 'type', 'version'], + } + } + +export const createInlineBlockNodeJSONSchema = + (inlineBlockConfigs: Block[]): JSONSchemaFn => + (args) => { + args.typeStringDefinitions.add(BLOCK_NODES_TS) + const variants = inlineBlockConfigs.map((block) => + buildBlockVariantSchema(block, args, { isInlineBlock: true }), + ) + + const fieldsSchema: JSONSchema4 = + variants.length === 0 + ? { type: 'object', additionalProperties: true } + : variants.length === 1 + ? variants[0]! + : { oneOf: variants } + + const allHaveInterfaceName = + inlineBlockConfigs.length > 0 && inlineBlockConfigs.every((b) => Boolean(b.interfaceName)) + const tsType = allHaveInterfaceName + ? `SerializedInlineBlockNode<${inlineBlockConfigs.map((b) => b.interfaceName!).join(' | ')}>` + : undefined + + return { + type: 'object', + additionalProperties: false, + ...(tsType ? { tsType } : {}), + properties: { + type: { type: 'string', const: 'inlineBlock' }, + fields: fieldsSchema, + version: { type: 'integer' }, + }, + required: ['fields', 'type', 'version'], + } + } diff --git a/packages/richtext-lexical/src/features/experimental_table/server/index.ts b/packages/richtext-lexical/src/features/experimental_table/server/index.ts index 316a2cf402b..2836e6853df 100644 --- a/packages/richtext-lexical/src/features/experimental_table/server/index.ts +++ b/packages/richtext-lexical/src/features/experimental_table/server/index.ts @@ -1,19 +1,18 @@ -import type { - SerializedTableCellNode as _SerializedTableCellNode, - SerializedTableNode as _SerializedTableNode, - SerializedTableRowNode as _SerializedTableRowNode, -} from '@lexical/table' -import type { SerializedLexicalNode } from 'lexical' import type { Config, Field, FieldSchemaMap } from 'payload' import { TableCellNode, TableNode, TableRowNode } from '@lexical/table' import { sanitizeFields } from 'payload' -import type { StronglyTypedElementNode } from '../../../types/nodeTypes.js' - import { createServerFeature } from '../../../utilities/createServerFeature.js' import { createNode } from '../../typeUtilities.js' import { TableMarkdownTransformer } from '../markdownTransformer.js' +import { tableCellNodeJSONSchema, tableNodeJSONSchema, tableRowNodeJSONSchema } from './schema.js' + +export type { + SerializedTableCellNode, + SerializedTableNode, + SerializedTableRowNode, +} from './schema.js' const fields: Field[] = [ { @@ -30,14 +29,6 @@ const fields: Field[] = [ }, ] -export type SerializedTableCellNode = - StronglyTypedElementNode<_SerializedTableCellNode, 'tablecell', T> - -export type SerializedTableNode = - StronglyTypedElementNode<_SerializedTableNode, 'table', T> - -export type SerializedTableRowNode = - StronglyTypedElementNode<_SerializedTableRowNode, 'tablerow', T> export const EXPERIMENTAL_TableFeature = createServerFeature({ feature: async ({ config, isRoot, parentIsLocalized }) => { const validRelationships = config.collections.map((c) => c.slug) || [] @@ -63,12 +54,15 @@ export const EXPERIMENTAL_TableFeature = createServerFeature({ markdownTransformers: [TableMarkdownTransformer], nodes: [ createNode({ + jsonSchema: tableNodeJSONSchema, node: TableNode, }), createNode({ + jsonSchema: tableCellNodeJSONSchema, node: TableCellNode, }), createNode({ + jsonSchema: tableRowNodeJSONSchema, node: TableRowNode, }), ], diff --git a/packages/richtext-lexical/src/features/experimental_table/server/schema.ts b/packages/richtext-lexical/src/features/experimental_table/server/schema.ts new file mode 100644 index 00000000000..b25dbc3ca6f --- /dev/null +++ b/packages/richtext-lexical/src/features/experimental_table/server/schema.ts @@ -0,0 +1,93 @@ +import type { + SerializedTableCellNode as _SerializedTableCellNode, + SerializedTableNode as _SerializedTableNode, + SerializedTableRowNode as _SerializedTableRowNode, +} from '@lexical/table' +import type { SerializedLexicalNode } from 'lexical' + +import type { StronglyTypedElementNode } from '../../../types/nodeTypes.js' +import type { JSONSchemaFn } from '../../typesServer.js' + +export type SerializedTableCellNode< + TChildren extends SerializedLexicalNode = SerializedLexicalNode, +> = StronglyTypedElementNode<_SerializedTableCellNode, 'tablecell', TChildren> + +export type SerializedTableNode = + StronglyTypedElementNode<_SerializedTableNode, 'table', TChildren> + +export type SerializedTableRowNode< + TChildren extends SerializedLexicalNode = SerializedLexicalNode, +> = StronglyTypedElementNode<_SerializedTableRowNode, 'tablerow', TChildren> + +const TABLE_NODES_TS = `export interface SerializedTableNode extends SerializedLexicalElementBase { + type: 'table'; + colWidths?: number[]; + frozenColumnCount?: number; + frozenRowCount?: number; + rowStriping?: boolean; +} +export interface SerializedTableRowNode extends SerializedLexicalElementBase { + type: 'tablerow'; + height?: number; +} +export interface SerializedTableCellNode extends SerializedLexicalElementBase { + type: 'tablecell'; + backgroundColor?: string | null; + colSpan?: number; + headerState: number; + rowSpan?: number; + verticalAlign?: string; + width?: number; +}` + +export const tableNodeJSONSchema: JSONSchemaFn = ({ + elementNodeSchema, + nodeUnionName, + typeStringDefinitions, +}) => { + typeStringDefinitions.add(TABLE_NODES_TS) + return elementNodeSchema({ + nodeType: 'table', + properties: { + colWidths: { type: 'array', items: { type: 'number' } }, + frozenColumnCount: { type: 'integer' }, + frozenRowCount: { type: 'integer' }, + rowStriping: { type: 'boolean' }, + }, + tsType: `SerializedTableNode<${nodeUnionName}>`, + }) +} + +export const tableCellNodeJSONSchema: JSONSchemaFn = ({ + elementNodeSchema, + nodeUnionName, + typeStringDefinitions, +}) => { + typeStringDefinitions.add(TABLE_NODES_TS) + return elementNodeSchema({ + nodeType: 'tablecell', + properties: { + backgroundColor: { oneOf: [{ type: 'string' }, { type: 'null' }] }, + colSpan: { type: 'integer' }, + headerState: { type: 'integer' }, + rowSpan: { type: 'integer' }, + verticalAlign: { type: 'string' }, + width: { type: 'integer' }, + }, + required: ['headerState'], + tsType: `SerializedTableCellNode<${nodeUnionName}>`, + }) +} + +export const tableRowNodeJSONSchema: JSONSchemaFn = ({ + elementNodeSchema, + nodeUnionName, + typeStringDefinitions, +}) => { + typeStringDefinitions.add(TABLE_NODES_TS) + return elementNodeSchema({ + nodeType: 'tablerow', + properties: { height: { type: 'integer' } }, + tsType: `SerializedTableRowNode<${nodeUnionName}>`, + }) +} diff --git a/packages/richtext-lexical/src/features/heading/server/index.ts b/packages/richtext-lexical/src/features/heading/server/index.ts index 209c25ea187..3b75d0e41a2 100644 --- a/packages/richtext-lexical/src/features/heading/server/index.ts +++ b/packages/richtext-lexical/src/features/heading/server/index.ts @@ -1,20 +1,14 @@ -import type { - SerializedHeadingNode as _SerializedHeadingNode, - HeadingTagType, -} from '@lexical/rich-text' -import type { SerializedLexicalNode } from 'lexical' +import type { HeadingTagType } from '@lexical/rich-text' import { HeadingNode } from '@lexical/rich-text' -import type { StronglyTypedElementNode } from '../../../types/nodeTypes.js' - import { createServerFeature } from '../../../utilities/createServerFeature.js' import { createNode } from '../../typeUtilities.js' import { MarkdownTransformer } from '../markdownTransformer.js' import { i18n } from './i18n.js' +import { createHeadingJSONSchema } from './schema.js' -export type SerializedHeadingNode = - StronglyTypedElementNode<_SerializedHeadingNode, 'heading', T> +export type { SerializedHeadingNode } from './schema.js' export type HeadingFeatureProps = { enabledHeadingSizes?: HeadingTagType[] @@ -42,6 +36,7 @@ export const HeadingFeature = createServerFeature< enabledHeadingSizes.length > 0 ? [MarkdownTransformer(enabledHeadingSizes)] : [], nodes: [ createNode({ + jsonSchema: createHeadingJSONSchema(enabledHeadingSizes), node: HeadingNode, }), ], diff --git a/packages/richtext-lexical/src/features/heading/server/schema.ts b/packages/richtext-lexical/src/features/heading/server/schema.ts new file mode 100644 index 00000000000..eae8b6a49b8 --- /dev/null +++ b/packages/richtext-lexical/src/features/heading/server/schema.ts @@ -0,0 +1,45 @@ +import type { + SerializedHeadingNode as _SerializedHeadingNode, + HeadingTagType, +} from '@lexical/rich-text' +import type { SerializedLexicalNode } from 'lexical' + +import type { StronglyTypedElementNode } from '../../../types/nodeTypes.js' +import type { JSONSchemaFn } from '../../typesServer.js' + +export type SerializedHeadingNode< + TChildren extends SerializedLexicalNode = SerializedLexicalNode, + TTag extends HeadingTagType = HeadingTagType, +> = { tag: TTag } & StronglyTypedElementNode<_SerializedHeadingNode, 'heading', TChildren> + +const ALL_HEADING_TAGS: HeadingTagType[] = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] + +const SERIALIZED_HEADING_NODE_TS = `export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +}` + +export const createHeadingJSONSchema = + (enabledHeadingSizes: HeadingTagType[]): JSONSchemaFn => + ({ elementNodeSchema, nodeUnionName, typeStringDefinitions }) => { + typeStringDefinitions.add(SERIALIZED_HEADING_NODE_TS) + // Skip the second generic arg when every tag is enabled — the helper + // type's default already covers all six. + const isAllTags = + enabledHeadingSizes.length === ALL_HEADING_TAGS.length && + ALL_HEADING_TAGS.every((tag) => enabledHeadingSizes.includes(tag)) + const tagUnion = enabledHeadingSizes.map((tag) => `'${tag}'`).join(' | ') + const tsType = isAllTags + ? `SerializedHeadingNode<${nodeUnionName}>` + : `SerializedHeadingNode<${nodeUnionName}, ${tagUnion}>` + + return elementNodeSchema({ + nodeType: 'heading', + properties: { tag: { type: 'string', enum: enabledHeadingSizes } }, + required: ['tag'], + tsType, + }) + } diff --git a/packages/richtext-lexical/src/features/horizontalRule/server/index.ts b/packages/richtext-lexical/src/features/horizontalRule/server/index.ts index 2a4971613e0..8b0ae37cdf6 100644 --- a/packages/richtext-lexical/src/features/horizontalRule/server/index.ts +++ b/packages/richtext-lexical/src/features/horizontalRule/server/index.ts @@ -3,6 +3,9 @@ import { createNode } from '../../typeUtilities.js' import { i18n } from './i18n.js' import { MarkdownTransformer } from './markdownTransformer.js' import { HorizontalRuleServerNode } from './nodes/HorizontalRuleNode.js' +import { horizontalRuleNodeJSONSchema } from './schema.js' + +export type { SerializedHorizontalRuleNode } from './schema.js' export const HorizontalRuleFeature = createServerFeature({ feature: { @@ -11,6 +14,7 @@ export const HorizontalRuleFeature = createServerFeature({ markdownTransformers: [MarkdownTransformer], nodes: [ createNode({ + jsonSchema: horizontalRuleNodeJSONSchema, node: HorizontalRuleServerNode, }), ], diff --git a/packages/richtext-lexical/src/features/horizontalRule/server/nodes/HorizontalRuleNode.tsx b/packages/richtext-lexical/src/features/horizontalRule/server/nodes/HorizontalRuleNode.tsx index 569dc8cd3df..6fff022ccff 100644 --- a/packages/richtext-lexical/src/features/horizontalRule/server/nodes/HorizontalRuleNode.tsx +++ b/packages/richtext-lexical/src/features/horizontalRule/server/nodes/HorizontalRuleNode.tsx @@ -12,15 +12,11 @@ import type * as React from 'react' import { addClassNamesToElement } from '@lexical/utils' import { $applyNodeReplacement, createCommand, DecoratorNode } from 'lexical' -import type { StronglyTypedLeafNode } from '../../../../types/nodeTypes.js' +import type { SerializedHorizontalRuleNode } from '../schema.js' -/** - * Serialized representation of a horizontal rule node. Serialized = converted to JSON. This is what is stored in the database / in the lexical editor state. - */ -export type SerializedHorizontalRuleNode = StronglyTypedLeafNode< - SerializedLexicalNode, - 'horizontalrule' -> +// Re-export the runtime type from the colocated schema module so existing +// imports of this path keep working. +export type { SerializedHorizontalRuleNode } from '../schema.js' export const INSERT_HORIZONTAL_RULE_COMMAND: LexicalCommand = createCommand( 'INSERT_HORIZONTAL_RULE_COMMAND', diff --git a/packages/richtext-lexical/src/features/horizontalRule/server/schema.ts b/packages/richtext-lexical/src/features/horizontalRule/server/schema.ts new file mode 100644 index 00000000000..6b5beb162eb --- /dev/null +++ b/packages/richtext-lexical/src/features/horizontalRule/server/schema.ts @@ -0,0 +1,28 @@ +import type { SerializedLexicalNode } from 'lexical' + +import type { StronglyTypedLeafNode } from '../../../types/nodeTypes.js' +import type { JSONSchemaFn } from '../../typesServer.js' + +export type SerializedHorizontalRuleNode = StronglyTypedLeafNode< + SerializedLexicalNode, + 'horizontalrule' +> + +const SERIALIZED_HORIZONTAL_RULE_NODE_TS = `export interface SerializedHorizontalRuleNode { + type: 'horizontalrule'; + version: number; +}` + +export const horizontalRuleNodeJSONSchema: JSONSchemaFn = ({ typeStringDefinitions }) => { + typeStringDefinitions.add(SERIALIZED_HORIZONTAL_RULE_NODE_TS) + return { + type: 'object', + additionalProperties: false, + properties: { + type: { type: 'string', const: 'horizontalrule' }, + version: { type: 'integer' }, + }, + required: ['type', 'version'], + tsType: 'SerializedHorizontalRuleNode', + } +} diff --git a/packages/richtext-lexical/src/features/link/nodes/types.ts b/packages/richtext-lexical/src/features/link/nodes/types.ts index 94f39223481..d62fcd82b00 100644 --- a/packages/richtext-lexical/src/features/link/nodes/types.ts +++ b/packages/richtext-lexical/src/features/link/nodes/types.ts @@ -1,33 +1,5 @@ -import type { SerializedElementNode, SerializedLexicalNode } from 'lexical' -import type { DefaultDocumentIDType, JsonValue } from 'payload' - -import type { StronglyTypedElementNode } from '../../../types/nodeTypes.js' - -export type LinkFields = { - [key: string]: JsonValue - doc?: { - relationTo: string - value: - | { - // Actual doc data, populated in afterRead hook - [key: string]: JsonValue - id: DefaultDocumentIDType - } - | DefaultDocumentIDType - } | null - linkType: 'custom' | 'internal' - newTab: boolean - url?: string -} - -export type SerializedLinkNode = { - fields: LinkFields - /** - * @todo make required in 4.0 and type AutoLinkNode differently - */ - id?: string // optional if AutoLinkNode -} & StronglyTypedElementNode - -export type SerializedAutoLinkNode = { - fields: LinkFields -} & StronglyTypedElementNode +// Re-export the runtime types from the colocated schema module so existing +// imports of this path keep working. The canonical definitions live in +// `../server/schema.ts` next to the JSON Schema builders and the inlined- +// into-payload-types TS source string. +export type { LinkFields, SerializedAutoLinkNode, SerializedLinkNode } from '../server/schema.js' diff --git a/packages/richtext-lexical/src/features/link/server/index.ts b/packages/richtext-lexical/src/features/link/server/index.ts index 7db1a7853d7..7f9a5efe15b 100644 --- a/packages/richtext-lexical/src/features/link/server/index.ts +++ b/packages/richtext-lexical/src/features/link/server/index.ts @@ -11,7 +11,6 @@ import { sanitizeFields } from 'payload' import type { NodeWithHooks } from '../../typesServer.js' import type { ClientProps } from '../client/index.js' -import type { SerializedLinkNode } from '../nodes/types.js' import { createServerFeature } from '../../../utilities/createServerFeature.js' import { createNode } from '../../typeUtilities.js' @@ -20,9 +19,16 @@ import { AutoLinkNode } from '../nodes/AutoLinkNode.js' import { LinkNode } from '../nodes/LinkNode.js' import { linkPopulationPromiseHOC } from './graphQLPopulationPromise.js' import { i18n } from './i18n.js' +import { + createAutoLinkNodeJSONSchema, + createLinkNodeJSONSchema, + type SerializedLinkNode, +} from './schema.js' import { transformExtraFields } from './transformExtraFields.js' import { linkValidation } from './validate.js' +export type { LinkFields, SerializedAutoLinkNode, SerializedLinkNode } from './schema.js' + export type ExclusiveLinkCollectionsProps = | { /** @@ -170,6 +176,7 @@ export const LinkFeature = createServerFeature< props?.disableAutoLinks === true ? null : createNode({ + jsonSchema: createAutoLinkNodeJSONSchema(sanitizedFieldsWithoutText), node: AutoLinkNode, // Since AutoLinkNodes are just internal links, they need no hooks or graphQL population promises validations: [linkValidation(props, sanitizedFieldsWithoutText)], @@ -182,6 +189,7 @@ export const LinkFeature = createServerFeature< return node?.fields }, graphQLPopulationPromises: [linkPopulationPromiseHOC(props)], + jsonSchema: createLinkNodeJSONSchema(sanitizedFieldsWithoutText), node: LinkNode, validations: [linkValidation(props, sanitizedFieldsWithoutText)], }), diff --git a/packages/richtext-lexical/src/features/link/server/schema.ts b/packages/richtext-lexical/src/features/link/server/schema.ts new file mode 100644 index 00000000000..c96701dd3b1 --- /dev/null +++ b/packages/richtext-lexical/src/features/link/server/schema.ts @@ -0,0 +1,135 @@ +import type { JSONSchema4 } from 'json-schema' +import type { SerializedElementNode, SerializedLexicalNode } from 'lexical' +import type { DefaultDocumentIDType, Field, JsonValue } from 'payload' + +import { fieldsToJSONSchema, flattenAllFields } from 'payload' + +import type { StronglyTypedElementNode } from '../../../types/nodeTypes.js' +import type { JSONSchemaArgs, JSONSchemaFn } from '../../typesServer.js' + +export type LinkFields = { + [key: string]: JsonValue + doc?: { + relationTo: string + value: + | { + // Actual doc data, populated in afterRead hook + [key: string]: JsonValue + id: DefaultDocumentIDType + } + | DefaultDocumentIDType + } | null + linkType: 'custom' | 'internal' + newTab: boolean + url?: string +} + +export type SerializedLinkNode = { + fields: LinkFields + /** @todo make required in 4.0 and type AutoLinkNode differently */ + id?: string +} & StronglyTypedElementNode + +export type SerializedAutoLinkNode< + TChildren extends SerializedLexicalNode = SerializedLexicalNode, +> = { + fields: LinkFields +} & StronglyTypedElementNode + +const LINK_NODES_TS = `export interface LexicalLinkFields { + doc?: { relationTo: string; value: string | number } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; + [k: string]: unknown; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +}` + +const buildLinkFieldsJSONSchema = ( + sanitizedFieldsWithoutText: Field[], + { + collectionIDFieldTypes, + config, + i18n, + interfaceNameDefinitions, + typeStringDefinitions, + }: JSONSchemaArgs, +): JSONSchema4 => { + const flattenedExtraFields = flattenAllFields({ fields: sanitizedFieldsWithoutText }) + const userFieldsSchema = + flattenedExtraFields.length > 0 && config + ? fieldsToJSONSchema({ + collectionIDFieldTypes, + config, + fields: flattenedExtraFields, + i18n, + interfaceNameDefinitions, + typeStringDefinitions, + }) + : { properties: {}, required: [] } + + return { + type: 'object', + additionalProperties: false, + properties: { + ...userFieldsSchema.properties, + doc: { + oneOf: [ + { + type: 'object', + additionalProperties: false, + properties: { + relationTo: { type: 'string' }, + value: { oneOf: [{ type: 'string' }, { type: 'number' }] }, + }, + required: ['relationTo', 'value'], + }, + { type: 'null' }, + ], + }, + linkType: { type: 'string', enum: ['custom', 'internal'] }, + newTab: { type: 'boolean' }, + url: { type: 'string' }, + }, + required: ['linkType', 'newTab', ...userFieldsSchema.required], + } +} + +export const createLinkNodeJSONSchema = + (sanitizedFieldsWithoutText: Field[]): JSONSchemaFn => + (args) => { + const { elementNodeSchema, nodeUnionName, typeStringDefinitions } = args + typeStringDefinitions.add(LINK_NODES_TS) + return elementNodeSchema({ + nodeType: 'link', + properties: { + id: { type: 'string' }, + fields: buildLinkFieldsJSONSchema(sanitizedFieldsWithoutText, args), + }, + required: ['fields'], + tsType: `SerializedLinkNode<${nodeUnionName}>`, + }) + } + +export const createAutoLinkNodeJSONSchema = + (sanitizedFieldsWithoutText: Field[]): JSONSchemaFn => + (args) => { + const { elementNodeSchema, nodeUnionName, typeStringDefinitions } = args + typeStringDefinitions.add(LINK_NODES_TS) + return elementNodeSchema({ + nodeType: 'autolink', + properties: { + fields: buildLinkFieldsJSONSchema(sanitizedFieldsWithoutText, args), + }, + required: ['fields'], + tsType: `SerializedAutoLinkNode<${nodeUnionName}>`, + }) + } diff --git a/packages/richtext-lexical/src/features/lists/checklist/server/index.ts b/packages/richtext-lexical/src/features/lists/checklist/server/index.ts index e78713e7f58..97bf9672af3 100644 --- a/packages/richtext-lexical/src/features/lists/checklist/server/index.ts +++ b/packages/richtext-lexical/src/features/lists/checklist/server/index.ts @@ -2,6 +2,7 @@ import { ListItemNode, ListNode } from '@lexical/list' import { createServerFeature } from '../../../../utilities/createServerFeature.js' import { createNode } from '../../../typeUtilities.js' +import { listItemNodeJSONSchema, listNodeJSONSchema } from '../../shared/schema.js' import { shouldRegisterListBaseNodes } from '../../shared/shouldRegisterListBaseNodes.js' import { CHECK_LIST } from '../markdownTransformers.js' import { i18n } from './i18n.js' @@ -15,9 +16,11 @@ export const ChecklistFeature = createServerFeature({ nodes: shouldRegisterListBaseNodes('checklist', featureProviderMap) ? [ createNode({ + jsonSchema: listNodeJSONSchema, node: ListNode, }), createNode({ + jsonSchema: listItemNodeJSONSchema, node: ListItemNode, }), ] diff --git a/packages/richtext-lexical/src/features/lists/orderedList/server/index.ts b/packages/richtext-lexical/src/features/lists/orderedList/server/index.ts index 9d84bb38cba..d801d546f82 100644 --- a/packages/richtext-lexical/src/features/lists/orderedList/server/index.ts +++ b/packages/richtext-lexical/src/features/lists/orderedList/server/index.ts @@ -2,6 +2,7 @@ import { ListItemNode, ListNode } from '@lexical/list' import { createServerFeature } from '../../../../utilities/createServerFeature.js' import { createNode } from '../../../typeUtilities.js' +import { listItemNodeJSONSchema, listNodeJSONSchema } from '../../shared/schema.js' import { shouldRegisterListBaseNodes } from '../../shared/shouldRegisterListBaseNodes.js' import { ORDERED_LIST } from '../markdownTransformer.js' import { i18n } from './i18n.js' @@ -15,9 +16,11 @@ export const OrderedListFeature = createServerFeature({ nodes: shouldRegisterListBaseNodes('ordered', featureProviderMap) ? [ createNode({ + jsonSchema: listNodeJSONSchema, node: ListNode, }), createNode({ + jsonSchema: listItemNodeJSONSchema, node: ListItemNode, }), ] diff --git a/packages/richtext-lexical/src/features/lists/plugin/index.tsx b/packages/richtext-lexical/src/features/lists/plugin/index.tsx index 34b947e7035..6d2b4ce62e0 100644 --- a/packages/richtext-lexical/src/features/lists/plugin/index.tsx +++ b/packages/richtext-lexical/src/features/lists/plugin/index.tsx @@ -1,23 +1,12 @@ 'use client' -import type { - SerializedListItemNode as _SerializedListItemNode, - SerializedListNode as _SerializedListNode, -} from '@lexical/list' -import type { SerializedLexicalNode } from 'lexical' - import { ListPlugin } from '@lexical/react/LexicalListPlugin.js' import React from 'react' -import type { StronglyTypedElementNode } from '../../../types/nodeTypes.js' import type { PluginComponent } from '../../typesClient.js' -export type SerializedListItemNode = { - checked?: boolean -} & StronglyTypedElementNode<_SerializedListItemNode, 'listitem', T> - -export type SerializedListNode = { - checked?: boolean -} & StronglyTypedElementNode<_SerializedListNode, 'list', T> +// Re-export the runtime types from the colocated schema module so existing +// imports from this client entry keep working. +export type { SerializedListItemNode, SerializedListNode } from '../shared/schema.js' export const LexicalListPlugin: PluginComponent = () => { return diff --git a/packages/richtext-lexical/src/features/lists/shared/schema.ts b/packages/richtext-lexical/src/features/lists/shared/schema.ts new file mode 100644 index 00000000000..d7ff0a3c83a --- /dev/null +++ b/packages/richtext-lexical/src/features/lists/shared/schema.ts @@ -0,0 +1,68 @@ +import type { + SerializedListItemNode as _SerializedListItemNode, + SerializedListNode as _SerializedListNode, +} from '@lexical/list' +import type { SerializedLexicalNode } from 'lexical' + +import type { StronglyTypedElementNode } from '../../../types/nodeTypes.js' +import type { JSONSchemaFn } from '../../typesServer.js' + +export type SerializedListItemNode< + TChildren extends SerializedLexicalNode = SerializedLexicalNode, +> = { + checked?: boolean +} & StronglyTypedElementNode<_SerializedListItemNode, 'listitem', TChildren> + +export type SerializedListNode = { + checked?: boolean +} & StronglyTypedElementNode<_SerializedListNode, 'list', TChildren> + +const SERIALIZED_LIST_NODE_TS = `export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +}` + +const SERIALIZED_LIST_ITEM_NODE_TS = `export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +}` + +export const listNodeJSONSchema: JSONSchemaFn = ({ + elementNodeSchema, + nodeUnionName, + typeStringDefinitions, +}) => { + typeStringDefinitions.add(SERIALIZED_LIST_NODE_TS) + return elementNodeSchema({ + nodeType: 'list', + properties: { + checked: { type: 'boolean' }, + listType: { type: 'string', enum: ['number', 'bullet', 'check'] }, + start: { type: 'integer' }, + tag: { type: 'string', enum: ['ul', 'ol'] }, + }, + required: ['listType', 'start', 'tag'], + tsType: `SerializedListNode<${nodeUnionName}>`, + }) +} + +export const listItemNodeJSONSchema: JSONSchemaFn = ({ + elementNodeSchema, + nodeUnionName, + typeStringDefinitions, +}) => { + typeStringDefinitions.add(SERIALIZED_LIST_ITEM_NODE_TS) + return elementNodeSchema({ + nodeType: 'listitem', + properties: { + checked: { type: 'boolean' }, + value: { type: 'integer' }, + }, + required: ['value'], + tsType: `SerializedListItemNode<${nodeUnionName}>`, + }) +} diff --git a/packages/richtext-lexical/src/features/lists/unorderedList/server/index.ts b/packages/richtext-lexical/src/features/lists/unorderedList/server/index.ts index 2abd9d39e14..7006fb70b5e 100644 --- a/packages/richtext-lexical/src/features/lists/unorderedList/server/index.ts +++ b/packages/richtext-lexical/src/features/lists/unorderedList/server/index.ts @@ -2,6 +2,7 @@ import { ListItemNode, ListNode } from '@lexical/list' import { createServerFeature } from '../../../../utilities/createServerFeature.js' import { createNode } from '../../../typeUtilities.js' +import { listItemNodeJSONSchema, listNodeJSONSchema } from '../../shared/schema.js' import { UNORDERED_LIST } from '../markdownTransformer.js' import { i18n } from './i18n.js' @@ -12,9 +13,11 @@ export const UnorderedListFeature = createServerFeature({ markdownTransformers: [UNORDERED_LIST], nodes: [ createNode({ + jsonSchema: listNodeJSONSchema, node: ListNode, }), createNode({ + jsonSchema: listItemNodeJSONSchema, node: ListItemNode, }), ], diff --git a/packages/richtext-lexical/src/features/relationship/client/utils/useEnabledRelationships.tsx b/packages/richtext-lexical/src/features/relationship/client/utils/useEnabledRelationships.tsx index fbd1ecb3728..4fdda166162 100644 --- a/packages/richtext-lexical/src/features/relationship/client/utils/useEnabledRelationships.tsx +++ b/packages/richtext-lexical/src/features/relationship/client/utils/useEnabledRelationships.tsx @@ -4,6 +4,8 @@ import type { ClientCollectionConfig, CollectionSlug } from 'payload' import { useConfig, useEntityVisibility } from '@payloadcms/ui' import * as React from 'react' +import { filterEnabledRelationshipCollections } from '../../shared/filterEnabledRelationshipCollections.js' + type UseEnabledRelationshipsOptions = { collectionSlugsBlacklist?: string[] collectionSlugsWhitelist?: string[] @@ -24,51 +26,16 @@ export const useEnabledRelationships = ( } = useConfig() const { visibleEntities } = useEntityVisibility() - const result = React.useMemo(() => { - const enabledCollectionSlugs: string[] = [] - const enabledCollections: ClientCollectionConfig[] = [] - const whitelistSet = collectionSlugsWhitelist ? new Set(collectionSlugsWhitelist) : null - const blacklistSet = collectionSlugsBlacklist ? new Set(collectionSlugsBlacklist) : null - - for (const collection of collections) { - const { - slug, - admin: { enableRichTextRelationship }, - upload, - } = collection - - // Check visibility - if (!visibleEntities?.collections.includes(slug)) { - continue - } - - // Check rich text relationship and upload settings - if (uploads) { - if (!enableRichTextRelationship || !upload) { - continue - } - } else { - if (upload || !enableRichTextRelationship) { - continue - } - } - - // Check whitelist (if provided, only include slugs in the whitelist) - if (whitelistSet && !whitelistSet.has(slug)) { - continue - } - - // Check blacklist (if provided, exclude slugs in the blacklist) - if (blacklistSet && blacklistSet.has(slug)) { - continue - } - - enabledCollectionSlugs.push(slug) - enabledCollections.push(collection) + return React.useMemo(() => { + const enabledCollections = filterEnabledRelationshipCollections(collections, { + disabledCollections: collectionSlugsBlacklist, + enabledCollections: collectionSlugsWhitelist, + uploads, + visibleSlugs: visibleEntities?.collections, + }) + return { + enabledCollections, + enabledCollectionSlugs: enabledCollections.map((c) => c.slug), } - - return { enabledCollections, enabledCollectionSlugs } }, [collections, visibleEntities, uploads, collectionSlugsWhitelist, collectionSlugsBlacklist]) - - return result } diff --git a/packages/richtext-lexical/src/features/relationship/server/index.ts b/packages/richtext-lexical/src/features/relationship/server/index.ts index 5e18901e99d..572b95c439c 100644 --- a/packages/richtext-lexical/src/features/relationship/server/index.ts +++ b/packages/richtext-lexical/src/features/relationship/server/index.ts @@ -6,6 +6,9 @@ import { createNode } from '../../typeUtilities.js' import { relationshipPopulationPromiseHOC } from './graphQLPopulationPromise.js' import { i18n } from './i18n.js' import { RelationshipServerNode } from './nodes/RelationshipNode.js' +import { createRelationshipNodeJSONSchema } from './schema.js' + +export type { RelationshipData, SerializedRelationshipNode } from './schema.js' export type ExclusiveRelationshipFeatureProps = | { @@ -101,6 +104,7 @@ export const RelationshipFeature = createServerFeature< }, ], }, + jsonSchema: createRelationshipNodeJSONSchema(props), node: RelationshipServerNode, }), ], diff --git a/packages/richtext-lexical/src/features/relationship/server/nodes/RelationshipNode.tsx b/packages/richtext-lexical/src/features/relationship/server/nodes/RelationshipNode.tsx index 12c1c39bda9..6aef96bc2c1 100644 --- a/packages/richtext-lexical/src/features/relationship/server/nodes/RelationshipNode.tsx +++ b/packages/richtext-lexical/src/features/relationship/server/nodes/RelationshipNode.tsx @@ -1,5 +1,3 @@ -import type { SerializedDecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode.js' -import type { CollectionSlug, DataFromCollectionSlug } from 'payload' import type { JSX } from 'react' import { DecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode.js' @@ -16,17 +14,11 @@ import { type NodeKey, } from 'lexical' -import type { StronglyTypedLeafNode } from '../../../../types/nodeTypes.js' +import type { RelationshipData, SerializedRelationshipNode } from '../schema.js' -export type RelationshipData = { - [TCollectionSlug in CollectionSlug]: { - relationTo: TCollectionSlug - value: DataFromCollectionSlug | number | string - } -}[CollectionSlug] - -export type SerializedRelationshipNode = RelationshipData & - StronglyTypedLeafNode +// Re-export the runtime data types from the colocated schema module so +// existing imports of this path keep working. +export type { RelationshipData, SerializedRelationshipNode } from '../schema.js' function $relationshipElementToServerNode(domNode: HTMLDivElement): DOMConversionOutput | null { const id = domNode.getAttribute('data-lexical-relationship-id') diff --git a/packages/richtext-lexical/src/features/relationship/server/schema.ts b/packages/richtext-lexical/src/features/relationship/server/schema.ts new file mode 100644 index 00000000000..71635cb641a --- /dev/null +++ b/packages/richtext-lexical/src/features/relationship/server/schema.ts @@ -0,0 +1,82 @@ +import type { SerializedDecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode.js' +import type { JSONSchema4 } from 'json-schema' +import type { CollectionSlug, DataFromCollectionSlug } from 'payload' + +import type { StronglyTypedLeafNode } from '../../../types/nodeTypes.js' +import type { JSONSchemaFn } from '../../typesServer.js' +import type { RelationshipFeatureProps } from './index.js' + +import { formatSchema } from '../../../types/jsonSchemaHelpers.js' +import { filterEnabledRelationshipCollections } from '../shared/filterEnabledRelationshipCollections.js' + +export type RelationshipData = { + [TCollectionSlug in CollectionSlug]: { + relationTo: TCollectionSlug + value: DataFromCollectionSlug | number | string + } +}[CollectionSlug] + +export type SerializedRelationshipNode = RelationshipData & + StronglyTypedLeafNode + +const SERIALIZED_RELATIONSHIP_NODE_TS = `export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: Config['collections'][TSlug] | (Config['collections'][TSlug] extends { id: infer TID } ? TID : never); + }; +}[TSlugs];` + +export const createRelationshipNodeJSONSchema = + (props: RelationshipFeatureProps | undefined): JSONSchemaFn => + ({ collectionIDFieldTypes, config, typeStringDefinitions }) => { + typeStringDefinitions.add(SERIALIZED_RELATIONSHIP_NODE_TS) + const enabledCollections = config?.collections + ? filterEnabledRelationshipCollections(config.collections, { + disabledCollections: props?.disabledCollections, + enabledCollections: props?.enabledCollections, + uploads: false, + }) + : [] + + const variants: JSONSchema4[] = enabledCollections.map((collection) => { + const slug = collection.slug + const idType: 'number' | 'string' = collectionIDFieldTypes[slug] ?? 'string' + return { + type: 'object', + additionalProperties: false, + properties: { + type: { type: 'string', const: 'relationship' }, + format: formatSchema, + relationTo: { type: 'string', const: slug }, + value: { + oneOf: [{ type: idType }, { $ref: `#/definitions/${slug}` }], + }, + version: { type: 'integer' }, + }, + required: ['format', 'relationTo', 'type', 'value', 'version'], + } + }) + + let schema: JSONSchema4 + if (variants.length === 0) { + schema = { + type: 'object', + additionalProperties: true, + properties: { + type: { type: 'string', const: 'relationship' }, + version: { type: 'integer' }, + }, + required: ['type', 'version'], + } + } else { + const slugUnion = enabledCollections.map((c) => `'${c.slug}'`).join(' | ') + const baseSchema: JSONSchema4 = variants.length === 1 ? variants[0]! : { oneOf: variants } + schema = { ...baseSchema, tsType: `SerializedRelationshipNode<${slugUnion}>` } + } + + return schema + } diff --git a/packages/richtext-lexical/src/features/relationship/shared/filterEnabledRelationshipCollections.ts b/packages/richtext-lexical/src/features/relationship/shared/filterEnabledRelationshipCollections.ts new file mode 100644 index 00000000000..4c091e9508c --- /dev/null +++ b/packages/richtext-lexical/src/features/relationship/shared/filterEnabledRelationshipCollections.ts @@ -0,0 +1,59 @@ +type CollectionLike = { + admin?: { + enableRichTextRelationship?: boolean + } + slug: string + upload?: unknown +} + +export type FilterEnabledRelationshipCollectionsOptions = { + /** `disabledCollections` feature prop — slug blacklist. */ + disabledCollections?: readonly string[] + /** `enabledCollections` feature prop — slug whitelist. */ + enabledCollections?: readonly string[] + /** When `true`, only upload-enabled collections; when `false`, only non-upload ones. */ + uploads: boolean + /** + * Slugs the current user can see, supplied by the client at runtime. + * Server-side type generation passes `undefined` to skip the check. + */ + visibleSlugs?: readonly string[] +} + +export const filterEnabledRelationshipCollections = ( + collections: readonly TCollection[], + { + disabledCollections, + enabledCollections, + uploads, + visibleSlugs, + }: FilterEnabledRelationshipCollectionsOptions, +): TCollection[] => { + const whitelistSet = enabledCollections?.length ? new Set(enabledCollections) : null + const blacklistSet = disabledCollections?.length ? new Set(disabledCollections) : null + + return collections.filter((collection) => { + const { slug, admin, upload } = collection + + if (visibleSlugs && !visibleSlugs.includes(slug)) { + return false + } + + if (uploads) { + if (!admin?.enableRichTextRelationship || !upload) { + return false + } + } else if (upload || !admin?.enableRichTextRelationship) { + return false + } + + if (whitelistSet && !whitelistSet.has(slug)) { + return false + } + if (blacklistSet && blacklistSet.has(slug)) { + return false + } + + return true + }) +} diff --git a/packages/richtext-lexical/src/features/typesServer.ts b/packages/richtext-lexical/src/features/typesServer.ts index f42afa9829f..58758ea2985 100644 --- a/packages/richtext-lexical/src/features/typesServer.ts +++ b/packages/richtext-lexical/src/features/typesServer.ts @@ -10,6 +10,7 @@ import type { import type { Field, FieldSchemaMap, + FieldsToJSONSchemaArgs, ImportMapGenerators, JsonObject, PayloadComponent, @@ -28,6 +29,7 @@ import type { import type { ServerEditorConfig } from '../lexical/config/types.js' import type { Transformer } from '../packages/@lexical/markdown/index.js' import type { LexicalRichTextField } from '../types/index.js' +import type { ElementNodeSchemaFn } from '../types/jsonSchemaHelpers.js' import type { BaseClientFeatureProps } from './typesClient.js' export type PopulationPromise = (args: { @@ -216,6 +218,23 @@ export type BeforeValidateNodeHook = ( args: BaseNodeHookArgs & BeforeValidateNodeHookArgs, ) => Promise | T +/** Arguments passed to each node's `jsonSchema` function. */ +export type JSONSchemaArgs = { + elementNodeSchema: ElementNodeSchemaFn + field: LexicalRichTextField + /** TS name of the node union - use in `tsType` annotations. */ + nodeUnionName: string +} & Pick< + FieldsToJSONSchemaArgs, + | 'collectionIDFieldTypes' + | 'config' + | 'i18n' + | 'interfaceNameDefinitions' + | 'typeStringDefinitions' +> + +export type JSONSchemaFn = (args: JSONSchemaArgs) => JSONSchema4 + // Define the node with hooks that use the node's exportJSON return type export type NodeWithHooks = { /** @@ -256,6 +275,12 @@ export type NodeWithHooks = { BeforeValidateNodeHook['exportJSON']>> > } + /** + * Returns the JSON Schema for this node, plus optional standalone TS + * source for helper types its `tsType` annotations reference. Nodes + * without this function are omitted from the strictly-typed union. + */ + jsonSchema?: JSONSchemaFn /** * The actual lexical node needs to be provided here. This also supports [lexical node replacements](https://lexical.dev/docs/concepts/node-replacement). */ @@ -299,6 +324,7 @@ export type ServerFeature = { */ interfaceNameDefinitions: Map isRequired: boolean + typeStringDefinitions: Set }) => JSONSchema4 } generateSchemaMap?: (args: { @@ -372,6 +398,7 @@ export type SanitizedServerFeatures = { */ interfaceNameDefinitions: Map isRequired: boolean + typeStringDefinitions: Set }) => JSONSchema4 > } diff --git a/packages/richtext-lexical/src/features/upload/server/index.ts b/packages/richtext-lexical/src/features/upload/server/index.ts index 2f95eb73b32..10c7e5fbf92 100644 --- a/packages/richtext-lexical/src/features/upload/server/index.ts +++ b/packages/richtext-lexical/src/features/upload/server/index.ts @@ -11,8 +11,16 @@ import { uploadPopulationPromiseHOC } from './graphQLPopulationPromise.js' import { i18n } from './i18n.js' import { UploadMarkdownTransformer } from './markdownTransformer.js' import { UploadServerNode } from './nodes/UploadNode.js' +import { createUploadNodeJSONSchema } from './schema.js' import { uploadValidation } from './validate.js' +export type { + Internal_UploadData, + SerializedUploadNode, + UploadData, + UploadDataImproved, +} from './schema.js' + export type ExclusiveUploadFeatureProps = | { /** @@ -166,8 +174,10 @@ export const UploadFeature = createServerFeature< if (!collection) { return node } - // @ts-expect-error - Fix in Payload v4 - const id = node?.value?.id || node?.value // for backwards-compatibility + const id = + typeof node?.value === 'object' && node.value !== null && 'id' in node.value + ? node.value.id + : node?.value // for backwards-compatibility const populateDepth = props?.maxDepth !== undefined && props?.maxDepth < depth ? props?.maxDepth : depth @@ -193,6 +203,7 @@ export const UploadFeature = createServerFeature< }, ], }, + jsonSchema: createUploadNodeJSONSchema(props), node: UploadServerNode, validations: [uploadValidation(props)], }), diff --git a/packages/richtext-lexical/src/features/upload/server/nodes/UploadNode.tsx b/packages/richtext-lexical/src/features/upload/server/nodes/UploadNode.tsx index 113a8defc63..ef408ec5c1a 100644 --- a/packages/richtext-lexical/src/features/upload/server/nodes/UploadNode.tsx +++ b/packages/richtext-lexical/src/features/upload/server/nodes/UploadNode.tsx @@ -1,4 +1,3 @@ -import type { SerializedDecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode.js' import type { DOMConversionMap, DOMExportOutput, @@ -7,13 +6,6 @@ import type { LexicalNode, NodeKey, } from 'lexical' -import type { - CollectionSlug, - DataFromCollectionSlug, - JsonObject, - TypedUploadCollection, - UploadCollectionSlug, -} from 'payload' import type { JSX } from 'react' import { DecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode.js' @@ -21,66 +13,19 @@ import { addClassNamesToElement } from '@lexical/utils' import ObjectID from 'bson-objectid' import { $applyNodeReplacement } from 'lexical' -import type { StronglyTypedLeafNode } from '../../../../types/nodeTypes.js' +import type { Internal_UploadData, SerializedUploadNode, UploadData } from '../schema.js' import { $convertUploadElement } from './conversions.js' -export type UploadData = { - [TCollectionSlug in CollectionSlug]: { - fields: TUploadExtraFieldsData - /** - * Every lexical node that has sub-fields needs to have a unique ID. This is the ID of this upload node, not the ID of the linked upload document - */ - id: string - relationTo: TCollectionSlug - /** - * Value can be just the document ID, or the full, populated document - */ - value: DataFromCollectionSlug | number | string - } -}[CollectionSlug] - -/** - * Internal use only - UploadData type that can contain a pending state - * @internal - */ -export type Internal_UploadData = { - pending?: { - /** - * ID that corresponds to the bulk upload form ID - */ - formID: string - /** - * src value of the image dom element - */ - src: string - } -} & UploadData - -/** - * UploadDataImproved is a more precise type, and will replace UploadData in Payload v4. - * This type is for internal use only as it will be deprecated in the future. - * @internal - * - * @todo Replace UploadData with UploadDataImproved in 4.0 - */ -export type UploadDataImproved = { - [TCollectionSlug in UploadCollectionSlug]: { - fields: TUploadExtraFieldsData - /** - * Every lexical node that has sub-fields needs to have a unique ID. This is the ID of this upload node, not the ID of the linked upload document - */ - id: string - relationTo: TCollectionSlug - /** - * Value can be just the document ID, or the full, populated document - */ - value: number | string | TypedUploadCollection[TCollectionSlug] - } -}[UploadCollectionSlug] - -export type SerializedUploadNode = StronglyTypedLeafNode & - UploadData +// Re-export the runtime data types from the colocated schema module so +// existing imports of this path keep working. Canonical definitions live in +// `../schema.ts` next to the JSON Schema builder + inlined TS source string. +export type { + Internal_UploadData, + SerializedUploadNode, + UploadData, + UploadDataImproved, +} from '../schema.js' export class UploadServerNode extends DecoratorBlockNode { __data: UploadData diff --git a/packages/richtext-lexical/src/features/upload/server/schema.ts b/packages/richtext-lexical/src/features/upload/server/schema.ts new file mode 100644 index 00000000000..d37b7a32796 --- /dev/null +++ b/packages/richtext-lexical/src/features/upload/server/schema.ts @@ -0,0 +1,143 @@ +import type { SerializedDecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode.js' +import type { JSONSchema4 } from 'json-schema' +import type { + CollectionSlug, + DataFromCollectionSlug, + JsonObject, + TypedUploadCollection, + UploadCollectionSlug, +} from 'payload' + +import { fieldsToJSONSchema, flattenAllFields } from 'payload' + +import type { StronglyTypedLeafNode } from '../../../types/nodeTypes.js' +import type { JSONSchemaFn } from '../../typesServer.js' +import type { UploadFeatureProps } from './index.js' + +import { formatSchema } from '../../../types/jsonSchemaHelpers.js' +import { filterEnabledRelationshipCollections } from '../../relationship/shared/filterEnabledRelationshipCollections.js' + +export type UploadData = { + [TCollectionSlug in CollectionSlug]: { + fields: TFields + /** ID of this upload node — NOT the linked document's ID. */ + id: string + relationTo: TCollectionSlug + /** Either the document ID or the full populated document. */ + value: DataFromCollectionSlug | number | string + } +}[CollectionSlug] + +/** @internal Adds a pending state to `UploadData`. */ +export type Internal_UploadData = { + pending?: { + /** Bulk upload form ID. */ + formID: string + /** `src` of the image DOM element. */ + src: string + } +} & UploadData + +/** + * More precise variant of {@link UploadData}. Replaces `UploadData` in v4. + * @internal + * @todo Replace UploadData with UploadDataImproved in 4.0 + */ +export type UploadDataImproved = { + [TCollectionSlug in UploadCollectionSlug]: { + fields: TFields + id: string + relationTo: TCollectionSlug + value: number | string | TypedUploadCollection[TCollectionSlug] + } +}[UploadCollectionSlug] + +export type SerializedUploadNode = StronglyTypedLeafNode & + UploadData + +const SERIALIZED_UPLOAD_NODE_TS = `export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: { [k: string]: unknown }; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: Config['collections'][TSlug] | (Config['collections'][TSlug] extends { id: infer TID } ? TID : never); + }; +}[TSlugs];` + +export const createUploadNodeJSONSchema = + (props: undefined | UploadFeatureProps): JSONSchemaFn => + ({ collectionIDFieldTypes, config, i18n, interfaceNameDefinitions, typeStringDefinitions }) => { + typeStringDefinitions.add(SERIALIZED_UPLOAD_NODE_TS) + const enabledCollections = config?.collections + ? filterEnabledRelationshipCollections(config.collections, { + disabledCollections: props?.disabledCollections, + enabledCollections: props?.enabledCollections, + uploads: true, + }) + : [] + + const collectionVariants: JSONSchema4[] = enabledCollections.map((collection) => { + const slug = collection.slug + const idType: 'number' | 'string' = collectionIDFieldTypes[slug] ?? 'string' + const extraFields = props?.collections?.[slug]?.fields ?? [] + const flattenedExtra = flattenAllFields({ fields: extraFields }) + const extraFieldsSchema = + flattenedExtra.length > 0 && config + ? fieldsToJSONSchema({ + collectionIDFieldTypes, + config, + fields: flattenedExtra, + i18n, + interfaceNameDefinitions, + typeStringDefinitions, + }) + : { properties: {}, required: [] } + + return { + type: 'object', + additionalProperties: false, + properties: { + id: { type: 'string' }, + type: { type: 'string', const: 'upload' }, + fields: { + type: 'object', + additionalProperties: false, + properties: extraFieldsSchema.properties, + required: extraFieldsSchema.required, + }, + format: formatSchema, + relationTo: { type: 'string', const: slug }, + value: { + oneOf: [{ type: idType }, { $ref: `#/definitions/${slug}` }], + }, + version: { type: 'integer' }, + }, + required: ['fields', 'format', 'id', 'relationTo', 'type', 'value', 'version'], + } + }) + + let schema: JSONSchema4 + if (collectionVariants.length === 0) { + // Fallback when no enabled upload collections. + schema = { + type: 'object', + additionalProperties: true, + properties: { + type: { type: 'string', const: 'upload' }, + version: { type: 'integer' }, + }, + required: ['type', 'version'], + } + } else { + const slugUnion = enabledCollections.map((c) => `'${c.slug}'`).join(' | ') + const baseSchema: JSONSchema4 = + collectionVariants.length === 1 ? collectionVariants[0]! : { oneOf: collectionVariants } + schema = { ...baseSchema, tsType: `SerializedUploadNode<${slugUnion}>` } + } + + return schema + } diff --git a/packages/richtext-lexical/src/lexical/config/server/sanitize.ts b/packages/richtext-lexical/src/lexical/config/server/sanitize.ts index baeb8560edc..3191631ec12 100644 --- a/packages/richtext-lexical/src/lexical/config/server/sanitize.ts +++ b/packages/richtext-lexical/src/lexical/config/server/sanitize.ts @@ -79,6 +79,17 @@ export const sanitizeServerFeatures = ( if (feature.nodes?.length) { // Do not concat here. We need to keep the object reference of sanitized.nodes so that function markdown transformers of features automatically get the updated nodes for (const node of feature.nodes) { + const nodeType = 'with' in node.node ? node.node.replace.getType() : node.node.getType() + const alreadyRegistered = sanitized.nodes.some((existing) => { + const existingType = + 'with' in existing.node ? existing.node.replace.getType() : existing.node.getType() + return existingType === nodeType + }) + if (alreadyRegistered) { + throw new Error( + `Lexical editor config: node type "${nodeType}" was registered more than once (feature "${feature.key}"). Each lexical node type may only be registered by a single feature.`, + ) + } sanitized.nodes.push(node) } feature.nodes.forEach((node) => { diff --git a/packages/richtext-lexical/src/types/builtInNodes.ts b/packages/richtext-lexical/src/types/builtInNodes.ts new file mode 100644 index 00000000000..d1566baad6d --- /dev/null +++ b/packages/richtext-lexical/src/types/builtInNodes.ts @@ -0,0 +1,176 @@ +import type { JSONSchema4 } from 'json-schema' + +import { withNullableJSONSchemaType } from 'payload' + +import type { JSONSchemaFn } from '../features/typesServer.js' + +/** + * Cross-cutting Lexical types shared by every element node. Inlined into + * `payload-types.ts`. Per-node helpers (text, tab, linebreak, paragraph, + * the field wrapper, and feature-supplied nodes) live with their respective + * schemas and are added to `typeStringDefinitions` on demand. + */ +export const CORE_LEXICAL_TYPE_STRING = `/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +}` + +/** + * Built-in Lexical node schemas (always present regardless of feature config). + * Co-located with the TS source they reference — each `JSONSchemaFn` adds + * its helper interface(s) to `typeStringDefinitions` and returns the JSON + * schema for that node. + */ + +const LEXICAL_TEXT_MODE_TS = `export type LexicalTextMode = 'normal' | 'token' | 'segmented';` + +const SERIALIZED_TEXT_NODE_TS = `export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +}` + +const SERIALIZED_TAB_NODE_TS = `export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +}` + +const SERIALIZED_LINE_BREAK_NODE_TS = `export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +}` + +const SERIALIZED_PARAGRAPH_NODE_TS = `export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +}` + +const textModeSchema: JSONSchema4 = { + type: 'string', + enum: ['normal', 'token', 'segmented'], + tsType: 'LexicalTextMode', +} + +export const textNodeJSONSchema: JSONSchemaFn = ({ typeStringDefinitions }) => { + typeStringDefinitions.add(LEXICAL_TEXT_MODE_TS) + typeStringDefinitions.add(SERIALIZED_TEXT_NODE_TS) + return { + type: 'object', + additionalProperties: false, + properties: { + type: { type: 'string', const: 'text' }, + detail: { type: 'integer' }, + format: { type: 'integer' }, + mode: textModeSchema, + style: { type: 'string' }, + text: { type: 'string' }, + version: { type: 'integer' }, + }, + required: ['detail', 'format', 'mode', 'style', 'text', 'type', 'version'], + tsType: 'SerializedTextNode', + } +} + +export const tabNodeJSONSchema: JSONSchemaFn = ({ typeStringDefinitions }) => { + typeStringDefinitions.add(LEXICAL_TEXT_MODE_TS) + typeStringDefinitions.add(SERIALIZED_TAB_NODE_TS) + return { + type: 'object', + additionalProperties: false, + properties: { + type: { type: 'string', const: 'tab' }, + detail: { type: 'integer' }, + format: { type: 'integer' }, + mode: textModeSchema, + style: { type: 'string' }, + text: { type: 'string' }, + version: { type: 'integer' }, + }, + required: ['detail', 'format', 'mode', 'style', 'text', 'type', 'version'], + tsType: 'SerializedTabNode', + } +} + +export const lineBreakNodeJSONSchema: JSONSchemaFn = ({ typeStringDefinitions }) => { + typeStringDefinitions.add(SERIALIZED_LINE_BREAK_NODE_TS) + return { + type: 'object', + additionalProperties: false, + properties: { + type: { type: 'string', const: 'linebreak' }, + version: { type: 'integer' }, + }, + required: ['type', 'version'], + tsType: 'SerializedLineBreakNode', + } +} + +export const paragraphNodeJSONSchema: JSONSchemaFn = ({ + elementNodeSchema, + nodeUnionName, + typeStringDefinitions, +}) => { + typeStringDefinitions.add(SERIALIZED_PARAGRAPH_NODE_TS) + return elementNodeSchema({ + nodeType: 'paragraph', + properties: { + textFormat: { type: 'integer' }, + textStyle: { type: 'string' }, + }, + required: ['textFormat', 'textStyle'], + tsType: `SerializedParagraphNode<${nodeUnionName}>`, + }) +} + +const ROOT_NODE_TS = `/** Shape of a Lexical \`richText\` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +}` + +export const rootNodeJSONSchema: JSONSchemaFn = ({ + elementNodeSchema, + field, + nodeUnionName, + typeStringDefinitions, +}) => { + typeStringDefinitions.add(ROOT_NODE_TS) + return { + type: withNullableJSONSchemaType('object', !!field.required), + additionalProperties: false, + properties: { + root: elementNodeSchema({ + nodeType: 'root', + }), + }, + required: ['root'], + tsType: field.required + ? `LexicalRichText<${nodeUnionName}>` + : `LexicalRichText<${nodeUnionName}> | null`, + } +} diff --git a/packages/richtext-lexical/src/types/jsonSchemaHelpers.ts b/packages/richtext-lexical/src/types/jsonSchemaHelpers.ts new file mode 100644 index 00000000000..062071c64db --- /dev/null +++ b/packages/richtext-lexical/src/types/jsonSchemaHelpers.ts @@ -0,0 +1,54 @@ +import type { JSONSchema4 } from 'json-schema' + +/** `format` property shared by every element node (Lexical `ElementFormatType`). */ +export const formatSchema: JSONSchema4 = { + type: 'string', + enum: ['left', 'start', 'center', 'right', 'end', 'justify', ''], + tsType: 'LexicalElementFormat', +} + +/** `direction` property shared by every element node. */ +export const directionSchema: JSONSchema4 = { + oneOf: [{ type: 'string', enum: ['ltr', 'rtl'] }, { type: 'null' }], + tsType: 'LexicalElementDirection', +} + +type ElementNodeSchemaOptions = { + nodeType: string + properties?: { [k: string]: JSONSchema4 } + required?: string[] + /** TS helper-type expression — emitted verbatim by json-schema-to-typescript. */ + tsType?: string +} + +/** + * Builds the JSON Schema for a Lexical element node - merges the shared + * element-base shape (children/direction/format/indent/version) with the + * node-specific bits a feature provides. + */ +export const elementNodeSchema = ({ + nodeType, + nodeUnionRef, + properties = {}, + required = [], + tsType, +}: { nodeUnionRef: JSONSchema4 } & ElementNodeSchemaOptions): JSONSchema4 => ({ + type: 'object', + additionalProperties: false, + properties: { + type: { type: 'string', const: nodeType }, + children: { type: 'array', items: nodeUnionRef }, + direction: directionSchema, + format: formatSchema, + indent: { type: 'integer' }, + version: { type: 'integer' }, + ...properties, + }, + required: ['children', 'direction', 'format', 'indent', 'type', 'version', ...required], + ...(tsType ? { tsType } : {}), +}) + +/** + * `elementNodeSchema` HOC type, so that features don't have to pass `nodeUnionRef` every time. + */ +export type ElementNodeSchemaFn = (opts: ElementNodeSchemaOptions) => JSONSchema4 diff --git a/packages/richtext-lexical/src/types/nodeTypes.ts b/packages/richtext-lexical/src/types/nodeTypes.ts index f41d45782a8..bd8b85538f0 100644 --- a/packages/richtext-lexical/src/types/nodeTypes.ts +++ b/packages/richtext-lexical/src/types/nodeTypes.ts @@ -22,14 +22,7 @@ import type { SerializedListItemNode, SerializedListNode } from '../features/lis import type { SerializedRelationshipNode } from '../features/relationship/server/nodes/RelationshipNode.js' import type { SerializedUploadNode } from '../features/upload/server/nodes/UploadNode.js' -/** - * Helper type to create strongly typed serialized nodes with flexible children types. - * Omits 'children' and 'type' from the base node type and redeclares them with proper typing. - * - * @param TBase - The base Lexical node type (e.g., _SerializedHeadingNode) - * @param TType - The node type string (e.g., 'heading') - * @param TChildren - The type for children (defaults to SerializedLexicalNode) - */ +/** Strongly-typed serialized element node with `children` and `type` re-declared. */ export type StronglyTypedElementNode< TBase, TType extends string, @@ -39,13 +32,7 @@ export type StronglyTypedElementNode< type: TType } & Omit -/** - * Helper type to create strongly typed leaf nodes (nodes without children). - * Omits 'children' and 'type' from the base node type and redeclares 'type' with a literal. - * - * @param TBase - The base Lexical node type (e.g., _SerializedTextNode) - * @param TType - The node type string (e.g., 'text') - */ +/** Strongly-typed serialized leaf node — no `children`, `type` re-declared. */ export type StronglyTypedLeafNode = { type: TType } & Omit @@ -67,9 +54,11 @@ export type { SerializedUploadNode, } -export type SerializedParagraphNode = { +export type SerializedParagraphNode< + TChildren extends SerializedLexicalNode = SerializedLexicalNode, +> = { textFormat: number -} & StronglyTypedElementNode +} & StronglyTypedElementNode export type SerializedTextNode = StronglyTypedLeafNode<_SerializedTextNode, 'text'> @@ -78,40 +67,34 @@ export type SerializedTabNode = StronglyTypedLeafNode<_SerializedTabNode, 'tab'> export type SerializedLineBreakNode = StronglyTypedLeafNode<_SerializedLineBreakNode, 'linebreak'> /** - * Recursively adds typed children to nodes up to a specified depth. - * - * Key behaviors: - * - `T extends any`: Distributive - processes each union member individually - * - `OriginalUnion`: Preserves full union so nested children accept all node types, not just parent's type. If we just used `T`, the type would be narrowed to the parent's type and the children would only consist of the parent's type. - * - `'children' extends keyof T`: Only adds children to container nodes; respects leaf nodes that use `Omit<_, 'children'>` - * - `Depth`: Limits recursion to prevent infinite types (default: 4 levels) + * Recursively adds typed children to nodes up to `TDepth` levels (default 4). + * Distributive over `TNode`; `TOriginalNode` preserves the full union so + * nested children accept all node types, not just the parent's. * - * @internal - this type may change or be removed in a minor release + * @internal — may change or be removed in a minor release. */ export type RecursiveNodes< - T extends SerializedLexicalNode, - Depth extends number = 4, - OriginalUnion extends SerializedLexicalNode = T, + TNode extends SerializedLexicalNode, + TDepth extends number = 4, + TOriginalNode extends SerializedLexicalNode = TNode, // eslint-disable-next-line @typescript-eslint/no-explicit-any -> = T extends any // Make distributive over unions - ? Depth extends 0 - ? T - : 'children' extends keyof T - ? { children?: RecursiveNodes, OriginalUnion>[] } & T - : T // Skip leaf nodes +> = TNode extends any + ? TDepth extends 0 + ? TNode + : 'children' extends keyof TNode + ? { children?: RecursiveNodes, TOriginalNode>[] } & TNode + : TNode : never -/** Decrements depth: 4→3, 3→2, 2→1, 1→0, 0→0 */ -type DecrementDepth = [0, 0, 1, 2, 3, 4][N] +/** 4→3, 3→2, 2→1, 1→0, 0→0 */ +type DecrementDepth = [0, 0, 1, 2, 3, 4][TN] /** - * Alternative type to `SerializedEditorState` that automatically types your nodes - * more strictly, narrowing down nodes based on the `type` without having to manually - * type-cast. + * `SerializedEditorState` with nodes narrowed by `type`. No type-casting needed. */ -export type TypedEditorState = { +export type TypedEditorState = { [k: string]: unknown -} & SerializedEditorState> +} & SerializedEditorState> /** * All node types included by default in a lexical editor without configuration. diff --git a/packages/richtext-lexical/src/types/schema.ts b/packages/richtext-lexical/src/types/schema.ts index 49b261a3b40..b66f51d5f27 100644 --- a/packages/richtext-lexical/src/types/schema.ts +++ b/packages/richtext-lexical/src/types/schema.ts @@ -1,10 +1,33 @@ import type { JSONSchema4 } from 'json-schema' -import { withNullableJSONSchemaType } from 'payload' +import { createHash } from 'crypto' +import type { JSONSchemaArgs } from '../features/typesServer.js' import type { SanitizedServerEditorConfig } from '../lexical/config/types.js' import type { LexicalRichTextAdapter } from './index.js' +import { + CORE_LEXICAL_TYPE_STRING, + lineBreakNodeJSONSchema, + paragraphNodeJSONSchema, + rootNodeJSONSchema, + tabNodeJSONSchema, + textNodeJSONSchema, +} from './builtInNodes.js' +import { elementNodeSchema } from './jsonSchemaHelpers.js' + +/** + * A placeholder string that will be replaced with the real union name later. + * Union = a union of all possible node types for this richtext field. + * + * We need to replace this *later*, because we're using a hadsh of the schema (like `LexicalNodes_AB12CD34`). + * We cannot calculate the hash until we've built the whole schema, but we can't build the whole schema + * until we have the hash as a name for the union - chicken-and-egg problem. + * + * We need to hash the actual schema to benefit from deduplication of two identical lexical fields. + */ +const NODE_UNION_NAME_PLACEHOLDER = '__LEXICAL_NODE_UNION_NAME__' + export const getFieldToJSONSchema: (args: { editorConfig: SanitizedServerEditorConfig }) => LexicalRichTextAdapter['jsonSchema'] = ({ editorConfig }) => { @@ -15,64 +38,59 @@ export const getFieldToJSONSchema: (args: { i18n, interfaceNameDefinitions, isRequired, + typeStringDefinitions, }) => { - let jsonSchema: JSONSchema4 = { - // This schema matches the SerializedEditorState type so far, that it's possible to cast SerializedEditorState to this schema without any errors. - // In the future, we should - // 1) allow recursive children - // 2) Pass in all the different types for every node added to the editorconfig. This can be done with refs in the schema. - type: withNullableJSONSchemaType('object', isRequired), - properties: { - root: { - type: 'object', - additionalProperties: false, - properties: { - type: { - type: 'string', - }, - children: { - type: 'array', - items: { - type: 'object', - additionalProperties: true, - properties: { - type: { - type: 'string', - tsType: 'any', - }, - version: { - type: 'integer', - }, - }, - required: ['type', 'version'], - }, - }, - direction: { - oneOf: [ - { - enum: ['ltr', 'rtl'], - }, - { - type: 'null', - }, - ], - }, - format: { - type: 'string', - enum: ['left', 'start', 'center', 'right', 'end', 'justify', ''], // ElementFormatType, since the root node is an element - }, - indent: { - type: 'integer', - }, - version: { - type: 'integer', - }, + // Step 1: build the schema for every node type allowed in this field. + + typeStringDefinitions.add(CORE_LEXICAL_TYPE_STRING) + + const nodeJsonSchemaArgs: JSONSchemaArgs = { + collectionIDFieldTypes, + config, + // Each element node needs its children typed using the union node type recursively + elementNodeSchema: (args) => + elementNodeSchema({ + ...args, + nodeUnionRef: { + $ref: `#/definitions/${NODE_UNION_NAME_PLACEHOLDER}`, }, - required: ['children', 'direction', 'format', 'indent', 'type', 'version'], - }, - }, - required: ['root'], + }), + field, + i18n, + interfaceNameDefinitions, + nodeUnionName: NODE_UNION_NAME_PLACEHOLDER, + typeStringDefinitions, } + + const nodeSchemas: JSONSchema4[] = [ + // Add built-in node schemas + textNodeJSONSchema(nodeJsonSchemaArgs), + tabNodeJSONSchema(nodeJsonSchemaArgs), + lineBreakNodeJSONSchema(nodeJsonSchemaArgs), + paragraphNodeJSONSchema(nodeJsonSchemaArgs), + // Add feature node schemas + ...editorConfig.features.nodes + .filter((node) => node.jsonSchema) + .map((node) => node.jsonSchema!(nodeJsonSchemaArgs)), + ] + const rootSchemaWithPlaceholder = rootNodeJSONSchema(nodeJsonSchemaArgs) + + // Step 2: get the final node union name, then replace the placeholder + // in both the union members and the root node. + // + // See JSDocs for `NODE_UNION_NAME_PLACEHOLDER` for why we use a placeholder and hashing. + const nodeUnionJson = JSON.stringify({ oneOf: nodeSchemas }) + + const hash = createHash('sha256').update(nodeUnionJson).digest('hex').slice(0, 8).toUpperCase() + const nodeUnionName = `LexicalNodes_${hash}` + + const replacePlaceholder = (schemaString: string) => + JSON.parse(schemaString.replaceAll(NODE_UNION_NAME_PLACEHOLDER, nodeUnionName)) as JSONSchema4 + + interfaceNameDefinitions.set(nodeUnionName, replacePlaceholder(nodeUnionJson)) + + let jsonSchema = replacePlaceholder(JSON.stringify(rootSchemaWithPlaceholder)) + for (const modifyJSONSchema of editorConfig.features.generatedTypes.modifyJSONSchemas) { jsonSchema = modifyJSONSchema({ collectionIDFieldTypes, @@ -82,6 +100,7 @@ export const getFieldToJSONSchema: (args: { i18n, interfaceNameDefinitions, isRequired, + typeStringDefinitions, }) } From f119fbef1f7cb95ac7f430ad7479381838ccc446 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Wed, 27 May 2026 22:28:56 -0700 Subject: [PATCH 07/56] types --- test/lexical/payload-types.ts | 2780 +++++++++++++++++++++++++-------- 1 file changed, 2165 insertions(+), 615 deletions(-) diff --git a/test/lexical/payload-types.ts b/test/lexical/payload-types.ts index 7ce00b650ca..679a32db1b2 100644 --- a/test/lexical/payload-types.ts +++ b/test/lexical/payload-types.ts @@ -60,6 +60,814 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_0BDB72B5". + */ +export type LexicalNodes_0BDB72B5 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedHorizontalRuleNode + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_2CC3BC57". + */ +export type LexicalNodes_2CC3BC57 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | { + type: 'block'; + fields: + | { + id: string; + blockType: 'benchBlock1'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock2'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock3'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock4'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock5'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock6'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock7'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock8'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock9'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock10'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock11'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock12'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock13'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock14'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock15'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock16'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock17'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock18'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock19'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock20'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock21'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock22'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock23'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock24'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock25'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock26'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock27'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock28'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock29'; + title?: string | null; + content?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'benchBlock30'; + title?: string | null; + content?: string | null; + blockName: string | null; + }; + format: LexicalElementFormat; + version: number; + } + | SerializedHorizontalRuleNode + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_A1CCBEB0". + */ +export type LexicalNodes_A1CCBEB0 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | { + type: 'block'; + fields: + | { + id: string; + blockType: 'Code'; + language?: + | ( + | 'abap' + | 'apex' + | 'azcli' + | 'bat' + | 'bicep' + | 'cameligo' + | 'clojure' + | 'coffee' + | 'cpp' + | 'csharp' + | 'csp' + | 'css' + | 'cypher' + | 'dart' + | 'dockerfile' + | 'ecl' + | 'elixir' + | 'flow9' + | 'freemarker2' + | 'fsharp' + | 'go' + | 'graphql' + | 'handlebars' + | 'hcl' + | 'html' + | 'ini' + | 'java' + | 'javascript' + | 'julia' + | 'kotlin' + | 'less' + | 'lexon' + | 'liquid' + | 'lua' + | 'm3' + | 'markdown' + | 'mdx' + | 'mips' + | 'msdax' + | 'mysql' + | 'objective-c' + | 'pascal' + | 'pascaligo' + | 'perl' + | 'pgsql' + | 'php' + | 'pla' + | 'plaintext' + | 'postiats' + | 'powerquery' + | 'powershell' + | 'protobuf' + | 'pug' + | 'python' + | 'qsharp' + | 'r' + | 'razor' + | 'redis' + | 'redshift' + | 'restructuredtext' + | 'ruby' + | 'rust' + | 'sb' + | 'scala' + | 'scheme' + | 'scss' + | 'shell' + | 'solidity' + | 'sophia' + | 'sparql' + | 'sql' + | 'st' + | 'swift' + | 'systemverilog' + | 'tcl' + | 'twig' + | 'typescript' + | 'typespec' + | 'vb' + | 'wgsl' + | 'xml' + | 'yaml' + ) + | null; + code?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'PayloadCode'; + language?: ('js' | 'ts' | 'json' | 'plaintext') | null; + code?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'myBlock'; + someText?: string | null; + blockName: string | null; + }; + format: LexicalElementFormat; + version: number; + } + | { + type: 'inlineBlock'; + fields: + | { + id: string; + blockType: 'myInlineBlock'; + someText?: string | null; + } + | InlineBlockWithSelect + | { + id: string; + blockType: 'inlineBlockWithRelationship'; + relationship?: (string | null) | TextField; + }; + version: number; + } + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode + | SerializedHorizontalRuleNode + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_47BA6198". + */ +export type LexicalNodes_47BA6198 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedAutoLinkNode + | SerializedLinkNode + | { + type: 'block'; + fields: { + id: string; + blockType: 'textBlock'; + blockTitle?: string | null; + blockName: string | null; + }; + format: LexicalElementFormat; + version: number; + } + | SerializedHorizontalRuleNode + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_31F9EDCE". + */ +export type LexicalNodes_31F9EDCE = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedHorizontalRuleNode + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_54DD9B10". + */ +export type LexicalNodes_54DD9B10 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedListNode + | SerializedListItemNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_CF729D18". + */ +export type LexicalNodes_CF729D18 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedHeadingNode + | SerializedHorizontalRuleNode + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_9A21BAAC". + */ +export type LexicalNodes_9A21BAAC = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | { + type: 'block'; + fields: { + id: string; + blockType: 'myBlock'; + someText?: string | null; + someTextRequired: string; + radios?: ('option1' | 'option2' | 'option3') | null; + blockName: string | null; + }; + format: LexicalElementFormat; + version: number; + } + | SerializedHeadingNode + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + >; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_A5916376". + */ +export type LexicalNodes_A5916376 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | { + type: 'block'; + fields: { + id: string; + blockType: 'lexicalAndUploadBlock'; + subRichTextField?: LexicalRichText | null; + subUploadField?: (string | null) | Upload; + blockName: string | null; + }; + format: LexicalElementFormat; + version: number; + } + | SerializedHorizontalRuleNode + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "BlockColumns". @@ -76,6 +884,1158 @@ export type BlockColumns = id?: string | null; }[] | null; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_BC3A19C3". + */ +export type LexicalNodes_BC3A19C3 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedHeadingNode + | { + type: 'block'; + fields: + | { + id: string; + blockType: 'richTextBlock'; + richTextField?: LexicalRichText | null; + blockName: string | null; + } + | { + id: string; + blockType: 'textRequired'; + text: string; + blockName: string | null; + } + | { + id: string; + blockType: 'uploadAndRichText'; + upload: string | Upload; + richText?: LexicalRichText | null; + blockName: string | null; + } + | { + id: string; + blockType: 'select'; + select?: ('option1' | 'option2' | 'option3' | 'option4' | 'option5') | null; + blockName: string | null; + } + | { + id: string; + blockType: 'relationshipBlock'; + rel: string | Upload; + blockName: string | null; + } + | { + id: string; + blockType: 'relationshipHasManyBlock'; + rel: ( + | { + relationTo: 'text-fields'; + value: string | TextField; + } + | { + relationTo: 'uploads'; + value: string | Upload; + } + )[]; + blockName: string | null; + } + | { + id: string; + blockType: 'subBlockLexical'; + subBlocksLexical?: + | ( + | { + richText: LexicalRichText; + id?: string | null; + blockName?: string | null; + blockType: 'contentBlock'; + } + | { + content: string; + id?: string | null; + blockName?: string | null; + blockType: 'textArea'; + } + | { + select?: ('option1' | 'option2' | 'option3' | 'option4' | 'option5') | null; + id?: string | null; + blockName?: string | null; + blockType: 'select'; + } + )[] + | null; + blockName: string | null; + } + | LexicalBlocksRadioButtonsBlock + | { + id: string; + blockType: 'conditionalLayout'; + layout: '1' | '2' | '3'; + columns?: BlockColumns; + columns2?: BlockColumns; + columns3?: BlockColumns; + blockName: string | null; + }; + format: LexicalElementFormat; + version: number; + }; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_F9A19CBA". + */ +export type LexicalNodes_F9A19CBA = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode + | { + type: 'block'; + fields: + | { + id: string; + blockType: 'validationBlock'; + text?: string | null; + group?: { + groupText?: string | null; + textDependsOnDocData?: string | null; + textDependsOnSiblingData?: string | null; + textDependsOnBlockData?: string | null; + }; + blockName: string | null; + } + | { + id: string; + blockType: 'filterOptionsBlock'; + text?: string | null; + group?: { + groupText?: string | null; + dependsOnDocData?: (string | null) | TextField; + dependsOnSiblingData?: (string | null) | TextField; + dependsOnBlockData?: (string | null) | TextField; + }; + blockName: string | null; + } + | { + id: string; + blockType: 'asyncHooksBlock'; + test1?: string | null; + test2?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'richTextBlock'; + richTextField?: LexicalRichText | null; + blockName: string | null; + } + | { + id: string; + blockType: 'textRequired'; + text: string; + blockName: string | null; + } + | { + id: string; + blockType: 'uploadAndRichText'; + upload: string | Upload; + richText?: LexicalRichText | null; + blockName: string | null; + } + | { + id: string; + blockType: 'select'; + select?: ('option1' | 'option2' | 'option3' | 'option4' | 'option5') | null; + blockName: string | null; + } + | { + id: string; + blockType: 'relationshipBlock'; + rel: string | Upload; + blockName: string | null; + } + | { + id: string; + blockType: 'relationshipHasManyBlock'; + rel: ( + | { + relationTo: 'text-fields'; + value: string | TextField; + } + | { + relationTo: 'uploads'; + value: string | Upload; + } + )[]; + blockName: string | null; + } + | { + id: string; + blockType: 'subBlockLexical'; + subBlocksLexical?: + | ( + | { + richText: LexicalRichText; + id?: string | null; + blockName?: string | null; + blockType: 'contentBlock'; + } + | { + content: string; + id?: string | null; + blockName?: string | null; + blockType: 'textArea'; + } + | { + select?: ('option1' | 'option2' | 'option3' | 'option4' | 'option5') | null; + id?: string | null; + blockName?: string | null; + blockType: 'select'; + } + )[] + | null; + blockName: string | null; + } + | LexicalBlocksRadioButtonsBlock + | { + id: string; + blockType: 'conditionalLayout'; + layout: '1' | '2' | '3'; + columns?: BlockColumns; + columns2?: BlockColumns; + columns3?: BlockColumns; + blockName: string | null; + } + | { + id: string; + blockType: 'tabBlock'; + tab1?: { + text1?: string | null; + }; + tab2?: { + text2?: string | null; + }; + blockName: string | null; + } + | { + id: string; + blockType: 'code'; + code?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'noBlockName'; + text?: string | null; + blockName: string | null; + } + | { + id: string; + blockType: 'myBlock'; + key?: ('value1' | 'value2' | 'value3') | null; + blockName: string | null; + } + | { + id: string; + blockType: 'myBlockWithLabel'; + key?: ('value1' | 'value2' | 'value3') | null; + blockName: string | null; + } + | { + id: string; + blockType: 'myBlockWithBlock'; + key?: ('value1' | 'value2' | 'value3') | null; + blockName: string | null; + } + | { + id: string; + blockType: 'BlockRSC'; + key?: ('value1' | 'value2' | 'value3') | null; + blockName: string | null; + } + | { + id: string; + blockType: 'myBlockWithBlockAndLabel'; + key?: ('value1' | 'value2' | 'value3') | null; + blockName: string | null; + }; + format: LexicalElementFormat; + version: number; + } + | { + type: 'inlineBlock'; + fields: + | AvatarGroupBlock + | { + id: string; + blockType: 'myInlineBlock'; + key?: ('value1' | 'value2' | 'value3') | null; + } + | { + id: string; + blockType: 'myInlineBlockWithLabel'; + key?: ('value1' | 'value2' | 'value3') | null; + } + | { + id: string; + blockType: 'myInlineBlockWithBlock'; + key?: ('value1' | 'value2' | 'value3') | null; + } + | { + id: string; + blockType: 'myInlineBlockWithBlockAndLabel'; + key?: ('value1' | 'value2' | 'value3') | null; + }; + version: number; + } + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedHorizontalRuleNode + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_B1C82968". + */ +export type LexicalNodes_B1C82968 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedHorizontalRuleNode + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_00CACBE2". + */ +export type LexicalNodes_00CACBE2 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedHorizontalRuleNode + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_FEC9EC0C". + */ +export type LexicalNodes_FEC9EC0C = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedHorizontalRuleNode + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_9C90CA3A". + */ +export type LexicalNodes_9C90CA3A = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedHorizontalRuleNode + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_91C7C52E". + */ +export type LexicalNodes_91C7C52E = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | { + type: 'block'; + fields: { + id: string; + blockType: 'blockLexicalLocalized'; + textLocalized?: string | null; + counter?: number | null; + rel?: (string | null) | LexicalLocalizedField; + blockName: string | null; + }; + format: LexicalElementFormat; + version: number; + } + | SerializedHorizontalRuleNode + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_BE60F591". + */ +export type LexicalNodes_BE60F591 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | { + type: 'block'; + fields: { + id: string; + blockType: 'blockLexicalLocalized2'; + textLocalized?: string | null; + rel?: (string | null) | LexicalLocalizedField; + blockName: string | null; + }; + format: LexicalElementFormat; + version: number; + } + | SerializedHorizontalRuleNode + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_C3F54E23". + */ +export type LexicalNodes_C3F54E23 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedUploadNode<'uploads' | 'uploads2'>; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_9F698A1B". + */ +export type LexicalNodes_9F698A1B = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | { + type: 'block'; + fields: { + id: string; + blockType: 'blockInLexical'; + /** + * Some Description + */ + lexicalInBlock: LexicalRichText; + blockName: string | null; + }; + format: LexicalElementFormat; + version: number; + }; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_FCD30BF2". + */ +export type LexicalNodes_FCD30BF2 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | { + type: 'inlineBlock'; + fields: { + id: string; + blockType: 'inlineBlockInLexical'; + text?: string | null; + }; + version: number; + }; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_7084D4A1". + */ +export type LexicalNodes_7084D4A1 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | { + type: 'block'; + fields: { + id: string; + blockType: 'blockWithRichText'; + nestedRichText?: LexicalRichText | null; + blockName: string | null; + }; + format: LexicalElementFormat; + version: number; + }; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_807731E1". + */ +export type LexicalNodes_807731E1 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedHorizontalRuleNode + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_BF713F1F". + */ +export type LexicalNodes_BF713F1F = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedUploadNode<'uploads'> + | SerializedRelationshipNode<'array-fields'> + | SerializedHorizontalRuleNode + | SerializedQuoteNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_476F32D1". + */ +export type LexicalNodes_476F32D1 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedHorizontalRuleNode + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedQuoteNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_0C3E1A7F". + */ +export type LexicalNodes_0C3E1A7F = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedUploadNode<'uploads2'> + | SerializedHorizontalRuleNode + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_DB0E1578". + */ +export type LexicalNodes_DB0E1578 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | { + type: 'block'; + fields: { + id: string; + blockType: 'blockWithBlockRef'; + nestedBlocks?: NestedBlock[] | null; + blockName: string | null; + }; + format: LexicalElementFormat; + version: number; + } + | SerializedHorizontalRuleNode + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_F35D58EB". + */ +export type LexicalNodes_F35D58EB = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | { + type: 'block'; + fields: + | { + id: string; + blockType: 'textRequired'; + text: string; + blockName: string | null; + } + | { + id: string; + blockType: 'uploadAndRichText'; + upload: string | Upload; + richText?: LexicalRichText | null; + blockName: string | null; + } + | { + id: string; + blockType: 'select'; + select?: ('option1' | 'option2' | 'option3' | 'option4' | 'option5') | null; + blockName: string | null; + } + | { + id: string; + blockType: 'relationshipBlock'; + rel: string | Upload; + blockName: string | null; + }; + format: LexicalElementFormat; + version: number; + } + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedHorizontalRuleNode + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_51E914D8". + */ +export type LexicalNodes_51E914D8 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode + | { + type: 'block'; + fields: { + id: string; + blockType: 'myBlock'; + someText?: string | null; + someTextRequired: string; + radios?: ('option1' | 'option2' | 'option3') | null; + blockName: string | null; + }; + format: LexicalElementFormat; + version: number; + } + | SerializedHeadingNode + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + >; export interface Config { auth: { @@ -224,21 +2184,7 @@ export interface BlockWithBlockRef { */ export interface LexicalBenchmark { id: string; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -248,21 +2194,7 @@ export interface LexicalBenchmark { */ export interface LexicalFullyFeatured { id: string; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -275,21 +2207,7 @@ export interface LexicalAutosave { title?: string | null; cta?: | { - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; id?: string | null; }[] | null; @@ -303,21 +2221,7 @@ export interface LexicalAutosave { */ export interface LexicalLinkFeature { id: string; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -327,21 +2231,7 @@ export interface LexicalLinkFeature { */ export interface LexicalListsFeature { id: string; - onlyOrderedList?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + onlyOrderedList?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -351,21 +2241,7 @@ export interface LexicalListsFeature { */ export interface LexicalHeadingFeature { id: string; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -375,21 +2251,7 @@ export interface LexicalHeadingFeature { */ export interface LexicalJsxConverter { id: string; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -400,57 +2262,15 @@ export interface LexicalJsxConverter { export interface LexicalField { id: string; title: string; - lexicalRootEditor?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + lexicalRootEditor?: LexicalRichText | null; /** * A simple lexical field */ - lexicalSimple?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + lexicalSimple?: LexicalRichText | null; /** * Should not be rendered */ - lexicalWithBlocks: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - }; + lexicalWithBlocks: LexicalRichText; lexicalWithBlocks_markdown?: string | null; updatedAt: string; createdAt: string; @@ -461,36 +2281,8 @@ export interface LexicalField { */ export interface LexicalView { id: string; - customDefaultView?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - vanillaView?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + customDefaultView?: LexicalRichText | null; + vanillaView?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -500,21 +2292,7 @@ export interface LexicalView { */ export interface LexicalViewsFrontend { id: string; - customFrontendViews?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + customFrontendViews?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -525,21 +2303,7 @@ export interface LexicalViewsFrontend { export interface LexicalViewsProvider { id: string; viewProviderWrapper?: { - richTextField?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richTextField?: LexicalRichText | null; }; updatedAt: string; createdAt: string; @@ -551,21 +2315,7 @@ export interface LexicalViewsProvider { export interface LexicalViewsProviderDefault { id: string; defaultViewWrapper?: { - richTextField?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richTextField?: LexicalRichText | null; }; updatedAt: string; createdAt: string; @@ -577,21 +2327,7 @@ export interface LexicalViewsProviderDefault { export interface LexicalViewsProviderFallback { id: string; fallbackViewWrapper?: { - richTextField?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richTextField?: LexicalRichText | null; }; updatedAt: string; createdAt: string; @@ -602,21 +2338,7 @@ export interface LexicalViewsProviderFallback { */ export interface LexicalViewsNested { id: string; - parentRichText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + parentRichText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -630,39 +2352,11 @@ export interface LexicalLocalizedField { /** * Non-localized field with localized block subfields */ - lexicalBlocksSubLocalized?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + lexicalBlocksSubLocalized?: LexicalRichText | null; /** * Localized field with localized block subfields */ - lexicalBlocksLocalized?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + lexicalBlocksLocalized?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -672,36 +2366,8 @@ export interface LexicalLocalizedField { */ export interface LexicalObjectReferenceBug { id: string; - lexicalDefault?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - lexicalEditor?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + lexicalDefault?: LexicalRichText | null; + lexicalEditor?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -711,38 +2377,10 @@ export interface LexicalObjectReferenceBug { */ export interface LexicalInBlock { id: string; - content?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + content?: LexicalRichText | null; blocks?: | { - lexical?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + lexical?: LexicalRichText | null; id?: string | null; blockName?: string | null; blockType: 'lexicalInBlock2'; @@ -757,21 +2395,7 @@ export interface LexicalInBlock { */ export interface LexicalAutosaveBlock { id: string; - content?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + content?: LexicalRichText | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -783,21 +2407,7 @@ export interface LexicalAutosaveBlock { export interface LexicalAccessControl { id: string; title?: string | null; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -807,66 +2417,10 @@ export interface LexicalAccessControl { */ export interface LexicalRelationshipField { id: string; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - richText2?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - richText3?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - richTextLocalized?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; + richText2?: LexicalRichText | null; + richText3?: LexicalRichText | null; + richTextLocalized?: LexicalRichText | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -877,21 +2431,7 @@ export interface LexicalRelationshipField { */ export interface Collision { id: string; - collision?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + collision?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -902,21 +2442,7 @@ export interface Collision { export interface LexicalNestedBlock { id: string; title: string; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -927,40 +2453,12 @@ export interface LexicalNestedBlock { export interface RichTextField { id: string; title: string; - lexicalCustomFields: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - }; + lexicalCustomFields: LexicalRichText; lexicalCustomFields_html?: string | null; /** * This rich text field uses the lexical editor. */ - lexical?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + lexical?: LexicalRichText | null; /** * This select field is rendered here to ensure its options dropdown renders above the rich text toolbar. */ @@ -1200,21 +2698,7 @@ export interface OnDemandOutsideForm { | number | boolean | null; - hiddenAnchor?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + hiddenAnchor?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1225,21 +2709,7 @@ export interface OnDemandOutsideForm { export interface LexicalCustomCell { id: string; title: string; - richTextField?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richTextField?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2007,38 +3477,10 @@ export interface PayloadMigrationsSelect { export interface TabsWithRichText { id: string; tab1?: { - rt1?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + rt1?: LexicalRichText | null; }; tab2?: { - rt2?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + rt2?: LexicalRichText | null; }; updatedAt?: string | null; createdAt?: string | null; @@ -2124,21 +3566,7 @@ export interface ViewsTestBlock { export interface BannerBlock { type: 'normal' | 'important'; title: string; - content?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + content?: LexicalRichText | null; id?: string | null; blockName?: string | null; blockType: 'banner'; @@ -2149,21 +3577,7 @@ export interface BannerBlock { */ export interface ContentBlock { title: string; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; id?: string | null; blockName?: string | null; blockType: 'content-block'; @@ -2175,21 +3589,7 @@ export interface ContentBlock { export interface ProviderBannerBlock { type: 'normal' | 'important'; title: string; - content?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + content?: LexicalRichText | null; id?: string | null; blockName?: string | null; blockType: 'banner'; @@ -2200,21 +3600,7 @@ export interface ProviderBannerBlock { */ export interface NestedContentBlock { label: string; - nestedRichText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + nestedRichText?: LexicalRichText | null; id?: string | null; blockName?: string | null; blockType: 'nested-content'; @@ -2227,6 +3613,170 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export interface SerializedHorizontalRuleNode { + type: 'horizontalrule'; + version: number; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: { [k: string]: unknown }; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: Config['collections'][TSlug] | (Config['collections'][TSlug] extends { id: infer TID } ? TID : never); + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: Config['collections'][TSlug] | (Config['collections'][TSlug] extends { id: infer TID } ? TID : never); + }; +}[TSlugs]; + +export interface LexicalLinkFields { + doc?: { relationTo: string; value: string | number } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; + [k: string]: unknown; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + +export type SerializedBlockNode = { + type: 'block'; + format: LexicalElementFormat; + version: number; + fields: { id: string; blockName: string | null } & Omit; +}; +export type SerializedInlineBlockNode = { + type: 'inlineBlock'; + version: number; + fields: { id: string } & Omit; +}; + +export interface SerializedTableNode extends SerializedLexicalElementBase { + type: 'table'; + colWidths?: number[]; + frozenColumnCount?: number; + frozenRowCount?: number; + rowStriping?: boolean; +} +export interface SerializedTableRowNode extends SerializedLexicalElementBase { + type: 'tablerow'; + height?: number; +} +export interface SerializedTableCellNode extends SerializedLexicalElementBase { + type: 'tablecell'; + backgroundColor?: string | null; + colSpan?: number; + headerState: number; + rowSpan?: number; + verticalAlign?: string; + width?: number; +} + declare module 'payload' { // @ts-ignore From ed64fbbf9765e6908c6c48082422009b8e2f1b12 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 28 May 2026 05:46:27 +0000 Subject: [PATCH 08/56] feat!: remove now-unused modifyJSONSchemas lexical feature property --- .../src/features/blocks/server/index.ts | 62 +-- .../src/features/typesServer.ts | 40 +- .../src/lexical/config/server/sanitize.ts | 7 - packages/richtext-lexical/src/types/schema.ts | 18 +- test/lexical/payload-types.ts | 498 +++++++++++------- 5 files changed, 311 insertions(+), 314 deletions(-) diff --git a/packages/richtext-lexical/src/features/blocks/server/index.ts b/packages/richtext-lexical/src/features/blocks/server/index.ts index 7f355984e53..2972e2ba9dd 100644 --- a/packages/richtext-lexical/src/features/blocks/server/index.ts +++ b/packages/richtext-lexical/src/features/blocks/server/index.ts @@ -4,14 +4,11 @@ import type { BlockSlug, Config, FieldSchemaMap, - FlattenedBlocksField, UIFieldClientProps, UIFieldServerProps, } from 'payload' -import { fieldsToJSONSchema, flattenAllFields, sanitizeFields } from 'payload' - -import type { NodeWithHooks } from '../../typesServer.js' +import { sanitizeFields } from 'payload' import { applyBaseFilterToFields } from '../../../utilities/applyBaseFilterToFields.js' import { createServerFeature } from '../../../utilities/createServerFeature.js' @@ -98,63 +95,6 @@ export const BlocksFeature = createServerFeature { - if (!blockConfigs?.length && !inlineBlockConfigs?.length) { - return currentSchema - } - - const fields: FlattenedBlocksField[] = [] - - if (blockConfigs?.length) { - fields.push({ - name: field?.name + '_lexical_blocks', - type: 'blocks', - blocks: blockConfigs.map((block) => { - return { - ...block, - flattenedFields: flattenAllFields({ fields: block.fields }), - } - }), - }) - } - if (inlineBlockConfigs?.length) { - fields.push({ - name: field?.name + '_lexical_inline_blocks', - type: 'blocks', - blocks: inlineBlockConfigs.map((block) => { - return { - ...block, - flattenedFields: flattenAllFields({ fields: block.fields }), - } - }), - }) - } - - if (fields.length) { - // This is only done so that interfaceNameDefinitions sets those block's interfaceNames. - // we don't actually use the JSON Schema itself in the generated types yet. - fieldsToJSONSchema({ - collectionIDFieldTypes, - config, - fields, - i18n, - interfaceNameDefinitions, - typeStringDefinitions, - }) - } - - return currentSchema - }, - }, generateSchemaMap: ({ config }) => { /** * Add sub-fields to the schemaMap. E.g. if you have an array field as part of the block, and it runs addRow, it will request these diff --git a/packages/richtext-lexical/src/features/typesServer.ts b/packages/richtext-lexical/src/features/typesServer.ts index 58758ea2985..b6afb6c31ad 100644 --- a/packages/richtext-lexical/src/features/typesServer.ts +++ b/packages/richtext-lexical/src/features/typesServer.ts @@ -1,4 +1,4 @@ -import type { GenericLanguages, I18n, I18nClient } from '@payloadcms/translations' +import type { GenericLanguages, I18nClient } from '@payloadcms/translations' import type { JSONSchema4 } from 'json-schema' import type { Klass, @@ -309,24 +309,6 @@ export type ServerFeature = { } | ImportMapGenerators[0] | PayloadComponent[] - generatedTypes?: { - modifyJSONSchema: (args: { - collectionIDFieldTypes: { [key: string]: 'number' | 'string' } - config?: SanitizedConfig - /** - * Current schema which will be modified by this function. - */ - currentSchema: JSONSchema4 - field: LexicalRichTextField - i18n?: I18n - /** - * Allows you to define new top-level interfaces that can be re-used in the output schema. - */ - interfaceNameDefinitions: Map - isRequired: boolean - typeStringDefinitions: Set - }) => JSONSchema4 - } generateSchemaMap?: (args: { config: SanitizedConfig field: RichTextField @@ -382,26 +364,6 @@ export type ServerFeatureProviderMap = Map - isRequired: boolean - typeStringDefinitions: Set - }) => JSONSchema4 - > - } /** The node types mapped to their hooks */ getSubFields?: Map< diff --git a/packages/richtext-lexical/src/lexical/config/server/sanitize.ts b/packages/richtext-lexical/src/lexical/config/server/sanitize.ts index 3191631ec12..4579000728d 100644 --- a/packages/richtext-lexical/src/lexical/config/server/sanitize.ts +++ b/packages/richtext-lexical/src/lexical/config/server/sanitize.ts @@ -13,9 +13,6 @@ export const sanitizeServerFeatures = ( ): SanitizedServerFeatures => { const sanitized: SanitizedServerFeatures = { enabledFeatures: [], - generatedTypes: { - modifyJSONSchemas: [], - }, getSubFields: new Map(), getSubFieldsData: new Map(), graphQLPopulationPromises: new Map(), @@ -43,10 +40,6 @@ export const sanitizeServerFeatures = ( } features.forEach((feature) => { - if (feature?.generatedTypes?.modifyJSONSchema) { - sanitized.generatedTypes.modifyJSONSchemas.push(feature.generatedTypes.modifyJSONSchema) - } - if (feature?.hooks?.beforeValidate?.length) { sanitized.hooks.beforeValidate = sanitized.hooks.beforeValidate?.concat( feature.hooks.beforeValidate, diff --git a/packages/richtext-lexical/src/types/schema.ts b/packages/richtext-lexical/src/types/schema.ts index b66f51d5f27..e6637a3e1cf 100644 --- a/packages/richtext-lexical/src/types/schema.ts +++ b/packages/richtext-lexical/src/types/schema.ts @@ -37,7 +37,6 @@ export const getFieldToJSONSchema: (args: { field, i18n, interfaceNameDefinitions, - isRequired, typeStringDefinitions, }) => { // Step 1: build the schema for every node type allowed in this field. @@ -89,21 +88,6 @@ export const getFieldToJSONSchema: (args: { interfaceNameDefinitions.set(nodeUnionName, replacePlaceholder(nodeUnionJson)) - let jsonSchema = replacePlaceholder(JSON.stringify(rootSchemaWithPlaceholder)) - - for (const modifyJSONSchema of editorConfig.features.generatedTypes.modifyJSONSchemas) { - jsonSchema = modifyJSONSchema({ - collectionIDFieldTypes, - config, - currentSchema: jsonSchema, - field, - i18n, - interfaceNameDefinitions, - isRequired, - typeStringDefinitions, - }) - } - - return jsonSchema + return replacePlaceholder(JSON.stringify(rootSchemaWithPlaceholder)) } } diff --git a/test/lexical/payload-types.ts b/test/lexical/payload-types.ts index 679a32db1b2..47873b32f0d 100644 --- a/test/lexical/payload-types.ts +++ b/test/lexical/payload-types.ts @@ -114,13 +114,13 @@ export type LexicalNodes_0BDB72B5 = | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_2CC3BC57". + * via the `definition` "LexicalNodes_ED984320". */ -export type LexicalNodes_2CC3BC57 = +export type LexicalNodes_ED984320 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | { type: 'block'; fields: @@ -337,9 +337,16 @@ export type LexicalNodes_2CC3BC57 = format: LexicalElementFormat; version: number; } + | { + type: 'inlineBlock'; + fields: { + [k: string]: unknown; + }; + version: number; + } | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -375,11 +382,11 @@ export type LexicalNodes_2CC3BC57 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "LexicalNodes_A1CCBEB0". @@ -564,15 +571,15 @@ export type LexicalNodes_A1CCBEB0 = | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_47BA6198". + * via the `definition` "LexicalNodes_B1B9B3BD". */ -export type LexicalNodes_47BA6198 = +export type LexicalNodes_B1B9B3BD = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedParagraphNode + | SerializedAutoLinkNode + | SerializedLinkNode | { type: 'block'; fields: { @@ -584,9 +591,16 @@ export type LexicalNodes_47BA6198 = format: LexicalElementFormat; version: number; } + | { + type: 'inlineBlock'; + fields: { + [k: string]: unknown; + }; + version: number; + } | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -622,9 +636,9 @@ export type LexicalNodes_47BA6198 = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "LexicalNodes_31F9EDCE". @@ -742,13 +756,13 @@ export type LexicalNodes_CF729D18 = | SerializedListItemNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_9A21BAAC". + * via the `definition` "LexicalNodes_C06ABAD2". */ -export type LexicalNodes_9A21BAAC = +export type LexicalNodes_C06ABAD2 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | { type: 'block'; fields: { @@ -762,13 +776,20 @@ export type LexicalNodes_9A21BAAC = format: LexicalElementFormat; version: number; } - | SerializedHeadingNode + | { + type: 'inlineBlock'; + fields: { + [k: string]: unknown; + }; + version: number; + } + | SerializedHeadingNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedListNode - | SerializedListItemNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -806,13 +827,13 @@ export type LexicalNodes_9A21BAAC = >; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_A5916376". + * via the `definition` "LexicalNodes_58B95BE3". */ -export type LexicalNodes_A5916376 = +export type LexicalNodes_58B95BE3 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | { type: 'block'; fields: { @@ -825,9 +846,16 @@ export type LexicalNodes_A5916376 = format: LexicalElementFormat; version: number; } + | { + type: 'inlineBlock'; + fields: { + [k: string]: unknown; + }; + version: number; + } | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -863,11 +891,11 @@ export type LexicalNodes_A5916376 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "BlockColumns". @@ -886,21 +914,21 @@ export type BlockColumns = | null; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_BC3A19C3". + * via the `definition` "LexicalNodes_8A55385E". */ -export type LexicalNodes_BC3A19C3 = +export type LexicalNodes_8A55385E = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedHeadingNode + | SerializedParagraphNode + | SerializedHeadingNode | { type: 'block'; fields: | { id: string; blockType: 'richTextBlock'; - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; blockName: string | null; } | { @@ -982,19 +1010,26 @@ export type LexicalNodes_BC3A19C3 = }; format: LexicalElementFormat; version: number; + } + | { + type: 'inlineBlock'; + fields: { + [k: string]: unknown; + }; + version: number; }; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_F9A19CBA". + * via the `definition` "LexicalNodes_1AC423EA". */ -export type LexicalNodes_F9A19CBA = +export type LexicalNodes_1AC423EA = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode + | SerializedParagraphNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode | { type: 'block'; fields: @@ -1032,7 +1067,7 @@ export type LexicalNodes_F9A19CBA = | { id: string; blockType: 'richTextBlock'; - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; blockName: string | null; } | { @@ -1195,10 +1230,10 @@ export type LexicalNodes_F9A19CBA = version: number; } | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1234,22 +1269,29 @@ export type LexicalNodes_F9A19CBA = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_B1C82968". + * via the `definition` "LexicalNodes_44B4C4A7". */ -export type LexicalNodes_B1C82968 = +export type LexicalNodes_44B4C4A7 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode + | { + type: 'inlineBlock'; + fields: { + [k: string]: unknown; + }; + version: number; + } | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1285,24 +1327,31 @@ export type LexicalNodes_B1C82968 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_00CACBE2". + * via the `definition` "LexicalNodes_E02E9941". */ -export type LexicalNodes_00CACBE2 = +export type LexicalNodes_E02E9941 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode + | { + type: 'inlineBlock'; + fields: { + [k: string]: unknown; + }; + version: number; + } | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1338,24 +1387,31 @@ export type LexicalNodes_00CACBE2 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_FEC9EC0C". + * via the `definition` "LexicalNodes_25DBE01C". */ -export type LexicalNodes_FEC9EC0C = +export type LexicalNodes_25DBE01C = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode + | { + type: 'inlineBlock'; + fields: { + [k: string]: unknown; + }; + version: number; + } | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1391,24 +1447,31 @@ export type LexicalNodes_FEC9EC0C = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_9C90CA3A". + * via the `definition` "LexicalNodes_23E2AA22". */ -export type LexicalNodes_9C90CA3A = +export type LexicalNodes_23E2AA22 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode + | { + type: 'inlineBlock'; + fields: { + [k: string]: unknown; + }; + version: number; + } | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1444,20 +1507,20 @@ export type LexicalNodes_9C90CA3A = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_91C7C52E". + * via the `definition` "LexicalNodes_A9FDE2F6". */ -export type LexicalNodes_91C7C52E = +export type LexicalNodes_A9FDE2F6 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | { type: 'block'; fields: { @@ -1471,9 +1534,16 @@ export type LexicalNodes_91C7C52E = format: LexicalElementFormat; version: number; } + | { + type: 'inlineBlock'; + fields: { + [k: string]: unknown; + }; + version: number; + } | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1509,20 +1579,20 @@ export type LexicalNodes_91C7C52E = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_BE60F591". + * via the `definition` "LexicalNodes_1E9F5E16". */ -export type LexicalNodes_BE60F591 = +export type LexicalNodes_1E9F5E16 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | { type: 'block'; fields: { @@ -1535,9 +1605,16 @@ export type LexicalNodes_BE60F591 = format: LexicalElementFormat; version: number; } + | { + type: 'inlineBlock'; + fields: { + [k: string]: unknown; + }; + version: number; + } | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1573,11 +1650,11 @@ export type LexicalNodes_BE60F591 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "LexicalNodes_C3F54E23". @@ -1590,13 +1667,13 @@ export type LexicalNodes_C3F54E23 = | SerializedUploadNode<'uploads' | 'uploads2'>; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_9F698A1B". + * via the `definition` "LexicalNodes_0E309CFF". */ -export type LexicalNodes_9F698A1B = +export type LexicalNodes_0E309CFF = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | { type: 'block'; fields: { @@ -1610,16 +1687,31 @@ export type LexicalNodes_9F698A1B = }; format: LexicalElementFormat; version: number; + } + | { + type: 'inlineBlock'; + fields: { + [k: string]: unknown; + }; + version: number; }; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_FCD30BF2". + * via the `definition` "LexicalNodes_61405AB6". */ -export type LexicalNodes_FCD30BF2 = +export type LexicalNodes_61405AB6 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode + | { + type: 'block'; + fields: { + [k: string]: unknown; + }; + format: LexicalElementFormat; + version: number; + } | { type: 'inlineBlock'; fields: { @@ -1631,13 +1723,13 @@ export type LexicalNodes_FCD30BF2 = }; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_7084D4A1". + * via the `definition` "LexicalNodes_047C3A1A". */ -export type LexicalNodes_7084D4A1 = +export type LexicalNodes_047C3A1A = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | { type: 'block'; fields: { @@ -1648,6 +1740,13 @@ export type LexicalNodes_7084D4A1 = }; format: LexicalElementFormat; version: number; + } + | { + type: 'inlineBlock'; + fields: { + [k: string]: unknown; + }; + version: number; }; /** * This interface was referenced by `Config`'s JSON-Schema @@ -1825,13 +1924,13 @@ export type LexicalNodes_0C3E1A7F = | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_DB0E1578". + * via the `definition` "LexicalNodes_8C92C54E". */ -export type LexicalNodes_DB0E1578 = +export type LexicalNodes_8C92C54E = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | { type: 'block'; fields: { @@ -1843,9 +1942,16 @@ export type LexicalNodes_DB0E1578 = format: LexicalElementFormat; version: number; } + | { + type: 'inlineBlock'; + fields: { + [k: string]: unknown; + }; + version: number; + } | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1881,20 +1987,20 @@ export type LexicalNodes_DB0E1578 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_F35D58EB". + * via the `definition` "LexicalNodes_D4CB7FDD". */ -export type LexicalNodes_F35D58EB = +export type LexicalNodes_D4CB7FDD = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | { type: 'block'; fields: @@ -1926,11 +2032,18 @@ export type LexicalNodes_F35D58EB = format: LexicalElementFormat; version: number; } + | { + type: 'inlineBlock'; + fields: { + [k: string]: unknown; + }; + version: number; + } | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1966,21 +2079,21 @@ export type LexicalNodes_F35D58EB = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_51E914D8". + * via the `definition` "LexicalNodes_557405F9". */ -export type LexicalNodes_51E914D8 = +export type LexicalNodes_557405F9 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode + | SerializedParagraphNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode | { type: 'block'; fields: { @@ -1994,13 +2107,20 @@ export type LexicalNodes_51E914D8 = format: LexicalElementFormat; version: number; } - | SerializedHeadingNode + | { + type: 'inlineBlock'; + fields: { + [k: string]: unknown; + }; + version: number; + } + | SerializedHeadingNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedListNode - | SerializedListItemNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -2184,7 +2304,7 @@ export interface BlockWithBlockRef { */ export interface LexicalBenchmark { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2207,7 +2327,7 @@ export interface LexicalAutosave { title?: string | null; cta?: | { - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; id?: string | null; }[] | null; @@ -2262,15 +2382,15 @@ export interface LexicalJsxConverter { export interface LexicalField { id: string; title: string; - lexicalRootEditor?: LexicalRichText | null; + lexicalRootEditor?: LexicalRichText | null; /** * A simple lexical field */ - lexicalSimple?: LexicalRichText | null; + lexicalSimple?: LexicalRichText | null; /** * Should not be rendered */ - lexicalWithBlocks: LexicalRichText; + lexicalWithBlocks: LexicalRichText; lexicalWithBlocks_markdown?: string | null; updatedAt: string; createdAt: string; @@ -2281,8 +2401,8 @@ export interface LexicalField { */ export interface LexicalView { id: string; - customDefaultView?: LexicalRichText | null; - vanillaView?: LexicalRichText | null; + customDefaultView?: LexicalRichText | null; + vanillaView?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2292,7 +2412,7 @@ export interface LexicalView { */ export interface LexicalViewsFrontend { id: string; - customFrontendViews?: LexicalRichText | null; + customFrontendViews?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2303,7 +2423,7 @@ export interface LexicalViewsFrontend { export interface LexicalViewsProvider { id: string; viewProviderWrapper?: { - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; }; updatedAt: string; createdAt: string; @@ -2338,7 +2458,7 @@ export interface LexicalViewsProviderFallback { */ export interface LexicalViewsNested { id: string; - parentRichText?: LexicalRichText | null; + parentRichText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2352,11 +2472,11 @@ export interface LexicalLocalizedField { /** * Non-localized field with localized block subfields */ - lexicalBlocksSubLocalized?: LexicalRichText | null; + lexicalBlocksSubLocalized?: LexicalRichText | null; /** * Localized field with localized block subfields */ - lexicalBlocksLocalized?: LexicalRichText | null; + lexicalBlocksLocalized?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2366,7 +2486,7 @@ export interface LexicalLocalizedField { */ export interface LexicalObjectReferenceBug { id: string; - lexicalDefault?: LexicalRichText | null; + lexicalDefault?: LexicalRichText | null; lexicalEditor?: LexicalRichText | null; updatedAt: string; createdAt: string; @@ -2377,10 +2497,10 @@ export interface LexicalObjectReferenceBug { */ export interface LexicalInBlock { id: string; - content?: LexicalRichText | null; + content?: LexicalRichText | null; blocks?: | { - lexical?: LexicalRichText | null; + lexical?: LexicalRichText | null; id?: string | null; blockName?: string | null; blockType: 'lexicalInBlock2'; @@ -2395,7 +2515,7 @@ export interface LexicalInBlock { */ export interface LexicalAutosaveBlock { id: string; - content?: LexicalRichText | null; + content?: LexicalRichText | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -2442,7 +2562,7 @@ export interface Collision { export interface LexicalNestedBlock { id: string; title: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2453,7 +2573,7 @@ export interface LexicalNestedBlock { export interface RichTextField { id: string; title: string; - lexicalCustomFields: LexicalRichText; + lexicalCustomFields: LexicalRichText; lexicalCustomFields_html?: string | null; /** * This rich text field uses the lexical editor. @@ -2698,7 +2818,7 @@ export interface OnDemandOutsideForm { | number | boolean | null; - hiddenAnchor?: LexicalRichText | null; + hiddenAnchor?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -3519,91 +3639,89 @@ export interface CollectionsWidget { * via the `definition` "InlineBlockWithSelect". */ export interface InlineBlockWithSelect { - styles?: ('opt1' | 'opt2')[] | null; - id?: string | null; - blockName?: string | null; + id: string; blockType: 'inlineBlockWithSelect'; + styles?: ('opt1' | 'opt2')[] | null; } /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "LexicalBlocksRadioButtonsBlock". */ export interface LexicalBlocksRadioButtonsBlock { - radioButtons?: ('option1' | 'option2' | 'option3') | null; - id?: string | null; - blockName?: string | null; + id: string; blockType: 'radioButtons'; + radioButtons?: ('option1' | 'option2' | 'option3') | null; + blockName: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "AvatarGroupBlock". */ export interface AvatarGroupBlock { + id: string; + blockType: 'AvatarGroup'; avatars?: | { image?: (string | null) | Upload; id?: string | null; }[] | null; - id?: string | null; - blockName?: string | null; - blockType: 'AvatarGroup'; } /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "ViewsTestBlock". */ export interface ViewsTestBlock { - text?: string | null; - id?: string | null; - blockName?: string | null; + id: string; blockType: 'viewsTestBlock'; + text?: string | null; + blockName: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "BannerBlock". */ export interface BannerBlock { + id: string; + blockType: 'banner'; type: 'normal' | 'important'; title: string; content?: LexicalRichText | null; - id?: string | null; - blockName?: string | null; - blockType: 'banner'; + blockName: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "ContentBlock". */ export interface ContentBlock { + id: string; + blockType: 'content-block'; title: string; richText?: LexicalRichText | null; - id?: string | null; - blockName?: string | null; - blockType: 'content-block'; + blockName: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "ProviderBannerBlock". */ export interface ProviderBannerBlock { + id: string; + blockType: 'banner'; type: 'normal' | 'important'; title: string; content?: LexicalRichText | null; - id?: string | null; - blockName?: string | null; - blockType: 'banner'; + blockName: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "NestedContentBlock". */ export interface NestedContentBlock { + id: string; + blockType: 'nested-content'; label: string; nestedRichText?: LexicalRichText | null; - id?: string | null; - blockName?: string | null; - blockType: 'nested-content'; + blockName: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema From 4460089524a45493ad0a7bf29b8ca283ff93f79c Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 28 May 2026 05:52:49 +0000 Subject: [PATCH 09/56] feat!: rename typescriptSchema => jsonSchema --- docs/fields/array.mdx | 44 ++++++++-------- docs/fields/blocks.mdx | 40 +++++++------- docs/fields/checkbox.mdx | 34 ++++++------ docs/fields/code.mdx | 40 +++++++------- docs/fields/date.mdx | 36 ++++++------- docs/fields/email.mdx | 36 ++++++------- docs/fields/group.mdx | 34 ++++++------ docs/fields/join.mdx | 34 ++++++------ docs/fields/json.mdx | 38 +++++++------- docs/fields/number.mdx | 46 ++++++++-------- docs/fields/point.mdx | 36 ++++++------- docs/fields/radio.mdx | 40 +++++++------- docs/fields/relationship.mdx | 50 +++++++++--------- docs/fields/rich-text.mdx | 34 ++++++------ docs/fields/select.mdx | 48 ++++++++--------- docs/fields/text.mdx | 46 ++++++++-------- docs/fields/textarea.mdx | 40 +++++++------- docs/fields/upload.mdx | 52 +++++++++---------- packages/payload/src/fields/config/client.ts | 4 +- packages/payload/src/fields/config/types.ts | 35 ++++--------- .../src/utilities/configToJSONSchema.spec.ts | 4 +- .../src/utilities/configToJSONSchema.ts | 4 +- test/types/config.ts | 2 +- 23 files changed, 382 insertions(+), 395 deletions(-) diff --git a/docs/fields/array.mdx b/docs/fields/array.mdx index a11d2b80302..255e55da36b 100644 --- a/docs/fields/array.mdx +++ b/docs/fields/array.mdx @@ -39,28 +39,28 @@ export const MyArrayField: Field = { ## Config Options -| Option | Description | -| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | -| **`label`** | Text used as the heading in the [Admin Panel](../admin/overview) or an object with keys for each language. Auto-generated from name if not defined. | -| **`fields`** \* | Array of field types to correspond to each row of the Array. | -| **`validate`** | Provide a custom validation function that will be executed on both the [Admin Panel](../admin/overview) and the backend. [More details](/docs/fields/overview#validation). | -| **`minRows`** | A number for the fewest allowed items during validation when a value is present. | -| **`maxRows`** | A number for the most allowed items during validation when a value is present. | -| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | -| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | -| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | -| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | -| **`defaultValue`** | Provide an array of row data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | -| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. If enabled, a separate, localized set of all data within this Array will be kept, so there is no need to specify each nested field as `localized`. | -| **`required`** | Require this field to have a value. | -| **`labels`** | Customize the row labels appearing in the Admin dashboard. | -| **`admin`** | Admin-specific configuration. [More details](#admin-options). | -| **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). | -| **`dbName`** | Custom table name for the field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. | -| **`typescriptSchema`** | Override field type generation with providing a JSON schema | -| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/overview#string-path-virtual-fields). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | +| Option | Description | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | +| **`label`** | Text used as the heading in the [Admin Panel](../admin/overview) or an object with keys for each language. Auto-generated from name if not defined. | +| **`fields`** \* | Array of field types to correspond to each row of the Array. | +| **`validate`** | Provide a custom validation function that will be executed on both the [Admin Panel](../admin/overview) and the backend. [More details](/docs/fields/overview#validation). | +| **`minRows`** | A number for the fewest allowed items during validation when a value is present. | +| **`maxRows`** | A number for the most allowed items during validation when a value is present. | +| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | +| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | +| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | +| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | +| **`defaultValue`** | Provide an array of row data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | +| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. If enabled, a separate, localized set of all data within this Array will be kept, so there is no need to specify each nested field as `localized`. | +| **`required`** | Require this field to have a value. | +| **`labels`** | Customize the row labels appearing in the Admin dashboard. | +| **`admin`** | Admin-specific configuration. [More details](#admin-options). | +| **`custom`** | Extension point for adding custom data (e.g. for plugins) | +| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). | +| **`dbName`** | Custom table name for the field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. | +| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/overview#string-path-virtual-fields). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/blocks.mdx b/docs/fields/blocks.mdx index bb4db41866c..8c329017795 100644 --- a/docs/fields/blocks.mdx +++ b/docs/fields/blocks.mdx @@ -42,26 +42,26 @@ This page is divided into two parts: first, the settings of the Blocks Field, an ### Block Config Options -| Option | Description | -| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | -| **`label`** | Text used as the heading in the Admin Panel or an object with keys for each language. Auto-generated from name if not defined. | -| **`blocks`** \* | Array of [block configs](/docs/fields/blocks#config-options) to be made available to this field. | -| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | -| **`minRows`** | A number for the fewest allowed items during validation when a value is present. | -| **`maxRows`** | A number for the most allowed items during validation when a value is present. | -| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | -| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | -| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | -| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API response or the Admin Panel. | -| **`defaultValue`** | Provide an array of block data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | -| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. If enabled, a separate, localized set of all data within this field will be kept, so there is no need to specify each nested field as `localized`. | -| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | -| **`labels`** | Customize the block row labels appearing in the Admin dashboard. | -| **`admin`** | Admin-specific configuration. [More details](#admin-options). | -| **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`typescriptSchema`** | Override field type generation with providing a JSON schema | -| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/overview#string-path-virtual-fields). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | +| Option | Description | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | +| **`label`** | Text used as the heading in the Admin Panel or an object with keys for each language. Auto-generated from name if not defined. | +| **`blocks`** \* | Array of [block configs](/docs/fields/blocks#config-options) to be made available to this field. | +| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | +| **`minRows`** | A number for the fewest allowed items during validation when a value is present. | +| **`maxRows`** | A number for the most allowed items during validation when a value is present. | +| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | +| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | +| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | +| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API response or the Admin Panel. | +| **`defaultValue`** | Provide an array of block data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | +| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. If enabled, a separate, localized set of all data within this field will be kept, so there is no need to specify each nested field as `localized`. | +| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | +| **`labels`** | Customize the block row labels appearing in the Admin dashboard. | +| **`admin`** | Admin-specific configuration. [More details](#admin-options). | +| **`custom`** | Extension point for adding custom data (e.g. for plugins) | +| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/overview#string-path-virtual-fields). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/checkbox.mdx b/docs/fields/checkbox.mdx index 95c7a04d92c..b56a37534f8 100644 --- a/docs/fields/checkbox.mdx +++ b/docs/fields/checkbox.mdx @@ -28,23 +28,23 @@ export const MyCheckboxField: Field = { ## Config Options -| Option | Description | -| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | -| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | -| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | -| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | -| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | -| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | -| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | -| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | -| **`defaultValue`** | Provide data to be used for this field's default value, will default to false if field is also `required`. [More details](/docs/fields/overview#default-values). | -| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | -| **`required`** | Require this field to have a value. | -| **`admin`** | Admin-specific configuration. [More details](./overview#admin-options). | -| **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`typescriptSchema`** | Override field type generation with providing a JSON schema | -| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | +| Option | Description | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | +| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | +| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | +| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | +| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | +| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | +| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | +| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | +| **`defaultValue`** | Provide data to be used for this field's default value, will default to false if field is also `required`. [More details](/docs/fields/overview#default-values). | +| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | +| **`required`** | Require this field to have a value. | +| **`admin`** | Admin-specific configuration. [More details](./overview#admin-options). | +| **`custom`** | Extension point for adding custom data (e.g. for plugins) | +| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/code.mdx b/docs/fields/code.mdx index 2b984a37465..5cc6e495e1b 100644 --- a/docs/fields/code.mdx +++ b/docs/fields/code.mdx @@ -29,26 +29,26 @@ export const MyBlocksField: Field = { ## Config Options -| Option | Description | -| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | -| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | -| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | -| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | -| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. | -| **`maxLength`** | Used by the default validation function to ensure values are of a maximum character length. | -| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | -| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | -| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | -| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | -| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | -| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | -| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | -| **`required`** | Require this field to have a value. | -| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-options). | -| **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`typescriptSchema`** | Override field type generation with providing a JSON schema | -| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | +| Option | Description | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | +| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | +| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | +| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | +| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. | +| **`maxLength`** | Used by the default validation function to ensure values are of a maximum character length. | +| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | +| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | +| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | +| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | +| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | +| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | +| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | +| **`required`** | Require this field to have a value. | +| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-options). | +| **`custom`** | Extension point for adding custom data (e.g. for plugins) | +| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/date.mdx b/docs/fields/date.mdx index 3a1568fd3d9..feb7b1e5920 100644 --- a/docs/fields/date.mdx +++ b/docs/fields/date.mdx @@ -28,24 +28,24 @@ export const MyDateField: Field = { ## Config Options -| Option | Description | -| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | -| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | -| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | -| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | -| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | -| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | -| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | -| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | -| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | -| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | -| **`required`** | Require this field to have a value. | -| **`admin`** | Admin-specific configuration. [More details](#admin-options). | -| **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`timezone`** \* | Set to `true` to enable timezone selection on this field. [More details](#timezones). | -| **`typescriptSchema`** | Override field type generation with providing a JSON schema | -| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | +| Option | Description | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | +| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | +| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | +| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | +| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | +| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | +| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | +| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | +| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | +| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | +| **`required`** | Require this field to have a value. | +| **`admin`** | Admin-specific configuration. [More details](#admin-options). | +| **`custom`** | Extension point for adding custom data (e.g. for plugins) | +| **`timezone`** \* | Set to `true` to enable timezone selection on this field. [More details](#timezones). | +| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/email.mdx b/docs/fields/email.mdx index 7b68e56cc84..41e47b6a4aa 100644 --- a/docs/fields/email.mdx +++ b/docs/fields/email.mdx @@ -28,24 +28,24 @@ export const MyEmailField: Field = { ## Config Options -| Option | Description | -| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | -| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | -| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | -| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | -| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | -| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | -| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | -| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | -| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | -| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | -| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | -| **`required`** | Require this field to have a value. | -| **`admin`** | Admin-specific configuration. [More details](#admin-options). | -| **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`typescriptSchema`** | Override field type generation with providing a JSON schema | -| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | +| Option | Description | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | +| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | +| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | +| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | +| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | +| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | +| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | +| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | +| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | +| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | +| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | +| **`required`** | Require this field to have a value. | +| **`admin`** | Admin-specific configuration. [More details](#admin-options). | +| **`custom`** | Extension point for adding custom data (e.g. for plugins) | +| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/group.mdx b/docs/fields/group.mdx index 693be20ca2c..81f3fcfbc1f 100644 --- a/docs/fields/group.mdx +++ b/docs/fields/group.mdx @@ -33,23 +33,23 @@ export const MyGroupField: Field = { ## Config Options -| Option | Description | -| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`name`** | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | -| **`fields`** \* | Array of field types to nest within this Group. | -| **`label`** | Used as a heading in the Admin Panel and to name the generated GraphQL type. Defaults to the field name, if defined. | -| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | -| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | -| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | -| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | -| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | -| **`defaultValue`** | Provide an object of data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | -| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. If enabled, a separate, localized set of all data within this Group will be kept, so there is no need to specify each nested field as `localized`. | -| **`admin`** | Admin-specific configuration. [More details](#admin-options). | -| **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). | -| **`typescriptSchema`** | Override field type generation with providing a JSON schema | -| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | +| Option | Description | +| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`name`** | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | +| **`fields`** \* | Array of field types to nest within this Group. | +| **`label`** | Used as a heading in the Admin Panel and to name the generated GraphQL type. Defaults to the field name, if defined. | +| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | +| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | +| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | +| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | +| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | +| **`defaultValue`** | Provide an object of data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | +| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. If enabled, a separate, localized set of all data within this Group will be kept, so there is no need to specify each nested field as `localized`. | +| **`admin`** | Admin-specific configuration. [More details](#admin-options). | +| **`custom`** | Extension point for adding custom data (e.g. for plugins) | +| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). | +| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/join.mdx b/docs/fields/join.mdx index cf6e90f1906..584d1269ab3 100644 --- a/docs/fields/join.mdx +++ b/docs/fields/join.mdx @@ -133,23 +133,23 @@ powerful Admin UI. ## Config Options -| Option | Description | -| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`name`** \* | To be used as the property name when retrieved from the database. [More details](./overview#field-names). | -| **`collection`** \* | The `slug`s having the relationship field or an array of collection slugs. | -| **`on`** \* | The name of the relationship or upload field that relates to the collection document. Use dot notation for nested paths, like 'myGroup.relationName'. If `collection` is an array, this field must exist for all specified collections | -| **`orderable`** | If true, enables custom ordering and joined documents can be reordered via drag and drop. Uses [fractional indexing](../configuration/collections#fractional-indexing) for efficient reordering. | -| **`where`** | A `Where` query to hide related documents from appearing. Will be merged with any `where` specified in the request. | -| **`maxDepth`** | Default is 1, Sets a maximum population depth for this field, regardless of the remaining depth when this field is reached. [Max Depth](../queries/depth#max-depth). | -| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | -| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | -| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | -| **`defaultLimit`** | The number of documents to return. Set to 0 to return all related documents. | -| **`defaultSort`** | The field name used to specify the order the joined documents are returned. | -| **`admin`** | Admin-specific configuration. [More details](#admin-config-options). | -| **`custom`** | Extension point for adding custom data (e.g. for plugins). | -| **`typescriptSchema`** | Override field type generation with providing a JSON schema. | -| **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) | +| Option | Description | +| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`name`** \* | To be used as the property name when retrieved from the database. [More details](./overview#field-names). | +| **`collection`** \* | The `slug`s having the relationship field or an array of collection slugs. | +| **`on`** \* | The name of the relationship or upload field that relates to the collection document. Use dot notation for nested paths, like 'myGroup.relationName'. If `collection` is an array, this field must exist for all specified collections | +| **`orderable`** | If true, enables custom ordering and joined documents can be reordered via drag and drop. Uses [fractional indexing](../configuration/collections#fractional-indexing) for efficient reordering. | +| **`where`** | A `Where` query to hide related documents from appearing. Will be merged with any `where` specified in the request. | +| **`maxDepth`** | Default is 1, Sets a maximum population depth for this field, regardless of the remaining depth when this field is reached. [Max Depth](../queries/depth#max-depth). | +| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | +| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | +| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | +| **`defaultLimit`** | The number of documents to return. Set to 0 to return all related documents. | +| **`defaultSort`** | The field name used to specify the order the joined documents are returned. | +| **`admin`** | Admin-specific configuration. [More details](#admin-config-options). | +| **`custom`** | Extension point for adding custom data (e.g. for plugins). | +| **`jsonSchema`** | Override field json schema used for type generation and mcp validation. | +| **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/json.mdx b/docs/fields/json.mdx index a487f2bf877..3284fc8b1e8 100644 --- a/docs/fields/json.mdx +++ b/docs/fields/json.mdx @@ -29,25 +29,25 @@ export const MyJSONField: Field = { ## Config Options -| Option | Description | -| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | -| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | -| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | -| **`index`** | Build an [index](/docs/database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | -| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | -| **`jsonSchema`** | Provide a JSON schema that will be used for validation. [JSON schemas](https://json-schema.org/learn/getting-started-step-by-step) | -| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | -| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | -| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | -| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | -| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | -| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | -| **`required`** | Require this field to have a value. | -| **`admin`** | Admin-specific configuration. [More details](#admin-options). | -| **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`typescriptSchema`** | Override field type generation with providing a JSON schema | -| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | +| Option | Description | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | +| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | +| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | +| **`index`** | Build an [index](/docs/database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | +| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | +| **`jsonSchema`** | Provide a JSON schema that will be used for validation. [JSON schemas](https://json-schema.org/learn/getting-started-step-by-step) | +| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | +| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | +| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | +| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | +| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | +| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | +| **`required`** | Require this field to have a value. | +| **`admin`** | Admin-specific configuration. [More details](#admin-options). | +| **`custom`** | Extension point for adding custom data (e.g. for plugins) | +| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/number.mdx b/docs/fields/number.mdx index d996be306b1..1b1401c7fd7 100644 --- a/docs/fields/number.mdx +++ b/docs/fields/number.mdx @@ -28,29 +28,29 @@ export const MyNumberField: Field = { ## Config Options -| Option | Description | -| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | -| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | -| **`min`** | Minimum value accepted. Used in the default `validation` function. | -| **`max`** | Maximum value accepted. Used in the default `validation` function. | -| **`hasMany`** | Makes this field an ordered array of numbers instead of just a single number. | -| **`minRows`** | Minimum number of numbers in the numbers array, if `hasMany` is set to true. | -| **`maxRows`** | Maximum number of numbers in the numbers array, if `hasMany` is set to true. | -| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | -| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | -| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | -| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | -| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | -| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | -| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | -| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | -| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | -| **`required`** | Require this field to have a value. | -| **`admin`** | Admin-specific configuration. [More details](#admin-options). | -| **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`typescriptSchema`** | Override field type generation with providing a JSON schema | -| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | +| Option | Description | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | +| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | +| **`min`** | Minimum value accepted. Used in the default `validation` function. | +| **`max`** | Maximum value accepted. Used in the default `validation` function. | +| **`hasMany`** | Makes this field an ordered array of numbers instead of just a single number. | +| **`minRows`** | Minimum number of numbers in the numbers array, if `hasMany` is set to true. | +| **`maxRows`** | Maximum number of numbers in the numbers array, if `hasMany` is set to true. | +| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | +| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | +| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | +| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | +| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | +| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | +| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | +| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | +| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | +| **`required`** | Require this field to have a value. | +| **`admin`** | Admin-specific configuration. [More details](#admin-options). | +| **`custom`** | Extension point for adding custom data (e.g. for plugins) | +| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/point.mdx b/docs/fields/point.mdx index 61bdb69739d..011d07d9c36 100644 --- a/docs/fields/point.mdx +++ b/docs/fields/point.mdx @@ -32,24 +32,24 @@ export const MyPointField: Field = { ## Config -| Option | Description | -| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | -| **`label`** | Used as a field label in the Admin Panel and to name the generated GraphQL type. | -| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | -| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. To support location queries, point index defaults to `2dsphere`, to disable the index set to `false`. | -| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | -| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | -| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | -| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | -| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | -| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | -| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | -| **`required`** | Require this field to have a value. | -| **`admin`** | Admin-specific configuration. [More details](./overview#admin-options). | -| **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`typescriptSchema`** | Override field type generation with providing a JSON schema | -| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | +| Option | Description | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | +| **`label`** | Used as a field label in the Admin Panel and to name the generated GraphQL type. | +| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | +| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. To support location queries, point index defaults to `2dsphere`, to disable the index set to `false`. | +| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | +| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | +| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | +| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | +| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | +| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | +| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | +| **`required`** | Require this field to have a value. | +| **`admin`** | Admin-specific configuration. [More details](./overview#admin-options). | +| **`custom`** | Extension point for adding custom data (e.g. for plugins) | +| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/radio.mdx b/docs/fields/radio.mdx index 88038346efb..b4c96fb6d83 100644 --- a/docs/fields/radio.mdx +++ b/docs/fields/radio.mdx @@ -33,26 +33,26 @@ export const MyRadioField: Field = { ## Config Options -| Option | Description | -| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | -| **`options`** \* | Array of options to allow the field to store. Can either be an array of strings, or an array of objects containing a `label` string and a `value` string. | -| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | -| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | -| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | -| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | -| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | -| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | -| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | -| **`defaultValue`** | Provide data to be used for this field's default value. The default value must exist within provided values in `options`. [More details](/docs/fields/overview#default-values). | -| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | -| **`required`** | Require this field to have a value. | -| **`admin`** | Admin-specific configuration. [More details](#admin-options). | -| **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`enumName`** | Custom enum name for this field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. | -| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). | -| **`typescriptSchema`** | Override field type generation with providing a JSON schema | -| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | +| Option | Description | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | +| **`options`** \* | Array of options to allow the field to store. Can either be an array of strings, or an array of objects containing a `label` string and a `value` string. | +| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | +| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | +| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | +| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | +| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | +| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | +| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | +| **`defaultValue`** | Provide data to be used for this field's default value. The default value must exist within provided values in `options`. [More details](/docs/fields/overview#default-values). | +| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | +| **`required`** | Require this field to have a value. | +| **`admin`** | Admin-specific configuration. [More details](#admin-options). | +| **`custom`** | Extension point for adding custom data (e.g. for plugins) | +| **`enumName`** | Custom enum name for this field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. | +| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). | +| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/relationship.mdx b/docs/fields/relationship.mdx index 86d6f3e4047..028a3e46106 100644 --- a/docs/fields/relationship.mdx +++ b/docs/fields/relationship.mdx @@ -37,31 +37,31 @@ export const MyRelationshipField: Field = { ## Config Options -| Option | Description | -| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | -| **`relationTo`** \* | Provide one or many collection `slug`s to be able to assign relationships to. | -| **`filterOptions`** | A query to filter which options appear in the UI and validate against. [More details](#filtering-relationship-options). | -| **`hasMany`** | Boolean when, if set to `true`, allows this field to have many relations instead of only one. | -| **`minRows`** | A number for the fewest allowed items during validation when a value is present. Used with `hasMany`. | -| **`maxRows`** | A number for the most allowed items during validation when a value is present. Used with `hasMany`. | -| **`maxDepth`** | Sets a maximum population depth for this field, regardless of the remaining depth when this field is reached. [Max Depth](/docs/queries/depth#max-depth) | -| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | -| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | -| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | -| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | -| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | -| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | -| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | -| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | -| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | -| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | -| **`required`** | Require this field to have a value. | -| **`admin`** | Admin-specific configuration. [More details](#admin-options). | -| **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`typescriptSchema`** | Override field type generation with providing a JSON schema | -| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to link the field with a relationship. See [Virtual Field Configuration](/docs/fields/overview#virtual-field-configuration) | -| **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) | +| Option | Description | +| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | +| **`relationTo`** \* | Provide one or many collection `slug`s to be able to assign relationships to. | +| **`filterOptions`** | A query to filter which options appear in the UI and validate against. [More details](#filtering-relationship-options). | +| **`hasMany`** | Boolean when, if set to `true`, allows this field to have many relations instead of only one. | +| **`minRows`** | A number for the fewest allowed items during validation when a value is present. Used with `hasMany`. | +| **`maxRows`** | A number for the most allowed items during validation when a value is present. Used with `hasMany`. | +| **`maxDepth`** | Sets a maximum population depth for this field, regardless of the remaining depth when this field is reached. [Max Depth](/docs/queries/depth#max-depth) | +| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | +| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | +| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | +| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | +| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | +| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | +| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | +| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | +| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | +| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | +| **`required`** | Require this field to have a value. | +| **`admin`** | Admin-specific configuration. [More details](#admin-options). | +| **`custom`** | Extension point for adding custom data (e.g. for plugins) | +| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to link the field with a relationship. See [Virtual Field Configuration](/docs/fields/overview#virtual-field-configuration) | +| **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/rich-text.mdx b/docs/fields/rich-text.mdx index 7acf1380a60..4b9937e81d7 100644 --- a/docs/fields/rich-text.mdx +++ b/docs/fields/rich-text.mdx @@ -19,23 +19,23 @@ Instead, you can invest your time and effort into learning the underlying open-s ## Config Options -| Option | Description | -| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](./overview#field-names). | -| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | -| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](./overview#validation). | -| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](../authentication/overview), include its data in the user JWT. | -| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | -| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | -| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | -| **`defaultValue`** | Provide data to be used for this field's default value. [More details](./overview#default-values). | -| **`localized`** | Enable localization for this field. Requires [localization to be enabled](../configuration/localization) in the Base config. | -| **`required`** | Require this field to have a value. | -| **`admin`** | Admin-specific configuration. [More details](#admin-options). | -| **`editor`** | Customize or override the rich text editor. [More details](../rich-text/overview). | -| **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`typescriptSchema`** | Override field type generation with providing a JSON schema | -| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | +| Option | Description | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](./overview#field-names). | +| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | +| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](./overview#validation). | +| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](../authentication/overview), include its data in the user JWT. | +| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | +| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | +| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | +| **`defaultValue`** | Provide data to be used for this field's default value. [More details](./overview#default-values). | +| **`localized`** | Enable localization for this field. Requires [localization to be enabled](../configuration/localization) in the Base config. | +| **`required`** | Require this field to have a value. | +| **`admin`** | Admin-specific configuration. [More details](#admin-options). | +| **`editor`** | Customize or override the rich text editor. [More details](../rich-text/overview). | +| **`custom`** | Extension point for adding custom data (e.g. for plugins) | +| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | \*_ An asterisk denotes that a property is required._ diff --git a/docs/fields/select.mdx b/docs/fields/select.mdx index de3aa247f31..9220be9f56c 100644 --- a/docs/fields/select.mdx +++ b/docs/fields/select.mdx @@ -33,30 +33,30 @@ export const MySelectField: Field = { ## Config Options -| Option | Description | -| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | -| **`options`** \* | Array of options to allow the field to store. Can either be an array of strings, or an array of objects containing a `label` string and a `value` string. | -| **`hasMany`** | Boolean when, if set to `true`, allows this field to have many selections instead of only one. | -| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | -| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | -| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | -| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | -| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | -| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | -| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | -| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | -| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | -| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | -| **`required`** | Require this field to have a value. | -| **`admin`** | Admin-specific configuration. See the [default field admin config](/docs/fields/overview#admin-options) for more details. | -| **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`enumName`** | Custom enum name for this field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. | -| **`dbName`** | Custom table name (if `hasMany` set to `true`) for this field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. | -| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). | -| **`filterOptions`** | Dynamically filter which options are available based on the user, data, etc. [More details](#filteroptions) | -| **`typescriptSchema`** | Override field type generation with providing a JSON schema | -| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | +| Option | Description | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | +| **`options`** \* | Array of options to allow the field to store. Can either be an array of strings, or an array of objects containing a `label` string and a `value` string. | +| **`hasMany`** | Boolean when, if set to `true`, allows this field to have many selections instead of only one. | +| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | +| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | +| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | +| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | +| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | +| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | +| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | +| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | +| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | +| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | +| **`required`** | Require this field to have a value. | +| **`admin`** | Admin-specific configuration. See the [default field admin config](/docs/fields/overview#admin-options) for more details. | +| **`custom`** | Extension point for adding custom data (e.g. for plugins) | +| **`enumName`** | Custom enum name for this field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. | +| **`dbName`** | Custom table name (if `hasMany` set to `true`) for this field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. | +| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). | +| **`filterOptions`** | Dynamically filter which options are available based on the user, data, etc. [More details](#filteroptions) | +| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/text.mdx b/docs/fields/text.mdx index 746360f7a17..98af0369d7e 100644 --- a/docs/fields/text.mdx +++ b/docs/fields/text.mdx @@ -28,29 +28,29 @@ export const MyTextField: Field = { ## Config Options -| Option | Description | -| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | -| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | -| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | -| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. | -| **`maxLength`** | Used by the default validation function to ensure values are of a maximum character length. | -| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | -| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | -| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | -| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | -| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | -| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | -| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | -| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | -| **`required`** | Require this field to have a value. | -| **`admin`** | Admin-specific configuration. [More details](#admin-options). | -| **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`hasMany`** | Makes this field an ordered array of text instead of just a single text. | -| **`minRows`** | Minimum number of texts in the array, if `hasMany` is set to true. | -| **`maxRows`** | Maximum number of texts in the array, if `hasMany` is set to true. | -| **`typescriptSchema`** | Override field type generation with providing a JSON schema | -| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | +| Option | Description | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | +| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | +| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | +| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. | +| **`maxLength`** | Used by the default validation function to ensure values are of a maximum character length. | +| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | +| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | +| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | +| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | +| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | +| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | +| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | +| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | +| **`required`** | Require this field to have a value. | +| **`admin`** | Admin-specific configuration. [More details](#admin-options). | +| **`custom`** | Extension point for adding custom data (e.g. for plugins) | +| **`hasMany`** | Makes this field an ordered array of text instead of just a single text. | +| **`minRows`** | Minimum number of texts in the array, if `hasMany` is set to true. | +| **`maxRows`** | Maximum number of texts in the array, if `hasMany` is set to true. | +| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/textarea.mdx b/docs/fields/textarea.mdx index 50b65e7896b..62367c174fc 100644 --- a/docs/fields/textarea.mdx +++ b/docs/fields/textarea.mdx @@ -28,26 +28,26 @@ export const MyTextareaField: Field = { ## Config Options -| Option | Description | -| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | -| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | -| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | -| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. | -| **`maxLength`** | Used by the default validation function to ensure values are of a maximum character length. | -| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | -| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | -| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | -| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | -| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | -| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | -| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | -| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | -| **`required`** | Require this field to have a value. | -| **`admin`** | Admin-specific configuration. [More details](#admin-options). | -| **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`typescriptSchema`** | Override field type generation with providing a JSON schema | -| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | +| Option | Description | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | +| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | +| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | +| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. | +| **`maxLength`** | Used by the default validation function to ensure values are of a maximum character length. | +| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | +| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | +| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | +| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | +| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | +| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | +| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | +| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | +| **`required`** | Require this field to have a value. | +| **`admin`** | Admin-specific configuration. [More details](#admin-options). | +| **`custom`** | Extension point for adding custom data (e.g. for plugins) | +| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/upload.mdx b/docs/fields/upload.mdx index 06113a0026a..13bdc7c18f6 100644 --- a/docs/fields/upload.mdx +++ b/docs/fields/upload.mdx @@ -44,32 +44,32 @@ export const MyUploadField: Field = { ## Config Options -| Option | Description | -| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | -| **`relationTo`** \* | Provide a single collection `slug` or an array of slugs to allow this field to accept a relation to. **Note: the related collections must be configured to support Uploads.** | -| **`filterOptions`** | A query to filter which options appear in the UI and validate against. [More details](#filtering-upload-options). | -| **`hasMany`** | Boolean which, if set to true, allows this field to have many relations instead of only one. | -| **`minRows`** | A number for the fewest allowed items during validation when a value is present. Used with hasMany. | -| **`maxRows`** | A number for the most allowed items during validation when a value is present. Used with hasMany. | -| **`maxDepth`** | Sets a number limit on iterations of related documents to populate when queried. [Depth](../queries/depth) | -| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | -| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | -| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | -| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | -| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | -| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | -| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | -| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | -| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | -| **`displayPreview`** | Enable displaying preview of the uploaded file. Overrides related Collection's `displayPreview` option. [More details](/docs/upload/overview#collection-upload-options). | -| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | -| **`required`** | Require this field to have a value. | -| **`admin`** | Admin-specific configuration. [Admin Options](./overview#admin-options). | -| **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`typescriptSchema`** | Override field type generation with providing a JSON schema | -| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | -| **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) | +| Option | Description | +| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More details](/docs/fields/overview#field-names). | +| **`relationTo`** \* | Provide a single collection `slug` or an array of slugs to allow this field to accept a relation to. **Note: the related collections must be configured to support Uploads.** | +| **`filterOptions`** | A query to filter which options appear in the UI and validate against. [More details](#filtering-upload-options). | +| **`hasMany`** | Boolean which, if set to true, allows this field to have many relations instead of only one. | +| **`minRows`** | A number for the fewest allowed items during validation when a value is present. Used with hasMany. | +| **`maxRows`** | A number for the most allowed items during validation when a value is present. Used with hasMany. | +| **`maxDepth`** | Sets a number limit on iterations of related documents to populate when queried. [Depth](../queries/depth) | +| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. | +| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. This creates a database-level unique index on the field's path. [More details](/docs/database/indexes#unique-fields). | +| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More details](/docs/fields/overview#validation). | +| **`index`** | Build an [index](../database/indexes) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. | +| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. | +| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). | +| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). | +| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. | +| **`defaultValue`** | Provide data to be used for this field's default value. [More details](/docs/fields/overview#default-values). | +| **`displayPreview`** | Enable displaying preview of the uploaded file. Overrides related Collection's `displayPreview` option. [More details](/docs/upload/overview#collection-upload-options). | +| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. | +| **`required`** | Require this field to have a value. | +| **`admin`** | Admin-specific configuration. [Admin Options](./overview#admin-options). | +| **`custom`** | Extension point for adding custom data (e.g. for plugins) | +| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | +| **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) | _\* An asterisk denotes that a property is required._ diff --git a/packages/payload/src/fields/config/client.ts b/packages/payload/src/fields/config/client.ts index b675ad27549..552b01581a0 100644 --- a/packages/payload/src/fields/config/client.ts +++ b/packages/payload/src/fields/config/client.ts @@ -39,8 +39,8 @@ export type ServerOnlyFieldProperties = | 'enumName' // can be a function | 'filterOptions' // This is a `relationship`, `upload`, and `select` only property | 'graphQL' + | 'jsonSchema' | 'label' - | 'typescriptSchema' | 'validate' | keyof Pick @@ -58,7 +58,7 @@ const serverOnlyFieldProperties: Partial[] = [ 'filterOptions', // This is a `relationship`, `upload`, and `select` only property 'editor', // This is a `richText` only property 'custom', - 'typescriptSchema', + 'jsonSchema', 'dbName', // can be a function 'enumName', // can be a function 'graphQL', // client does not need graphQL diff --git a/packages/payload/src/fields/config/types.ts b/packages/payload/src/fields/config/types.ts index 3ef4c8f50b8..ac12dabf555 100644 --- a/packages/payload/src/fields/config/types.ts +++ b/packages/payload/src/fields/config/types.ts @@ -504,6 +504,12 @@ export interface FieldBase { beforeValidate?: FieldHook[] } index?: boolean + /** + * Allows you to modify the base JSON schema that is generated for this field. + * This JSON schema will be used to generate the TypeScript interface of this field, and to + * validate the field's value in the MCP plugin. + */ + jsonSchema?: Array<(args: { jsonSchema: JSONSchema4 }) => JSONSchema4> label?: false | LabelFunction | StaticLabel localized?: boolean /** @@ -515,11 +521,6 @@ export interface FieldBase { name: string required?: boolean saveToJWT?: boolean | string - /** - * Allows you to modify the base JSON schema that is generated during generate:types for this field. - * This JSON schema will be used to generate the TypeScript interface of this field. - */ - typescriptSchema?: Array<(args: { jsonSchema: JSONSchema4 }) => JSONSchema4> unique?: boolean validate?: Validate /** @@ -530,27 +531,13 @@ export interface FieldBase { virtual?: boolean | string } -export interface FieldBaseClient { +export interface FieldBaseClient + extends Pick< + FieldBase, + 'hidden' | 'index' | 'jsonSchema' | 'localized' | 'name' | 'required' | 'saveToJWT' | 'unique' + > { admin?: AdminClient - hidden?: boolean - index?: boolean label?: StaticLabel - localized?: boolean - /** - * The name of the field. Must be alphanumeric and cannot contain ' . ' - * - * Must not be one of reserved field names: ['__v', 'salt', 'hash', 'file'] - * @link https://payloadcms.com/docs/fields/overview#field-names - */ - name: string - required?: boolean - saveToJWT?: boolean | string - /** - * Allows you to modify the base JSON schema that is generated during generate:types for this field. - * This JSON schema will be used to generate the TypeScript interface of this field. - */ - typescriptSchema?: Array<(args: { jsonSchema: JSONSchema4 }) => JSONSchema4> - unique?: boolean } export type NumberField = { diff --git a/packages/payload/src/utilities/configToJSONSchema.spec.ts b/packages/payload/src/utilities/configToJSONSchema.spec.ts index 0cae8ca2bc6..eca9932d35c 100644 --- a/packages/payload/src/utilities/configToJSONSchema.spec.ts +++ b/packages/payload/src/utilities/configToJSONSchema.spec.ts @@ -301,7 +301,7 @@ describe('configToJSONSchema', () => { { name: 'withCustom', type: 'text', - typescriptSchema: [() => customSchema], + jsonSchema: [() => customSchema], }, { name: 'jsonWithSchema', @@ -438,7 +438,7 @@ describe('configToJSONSchema', () => { type: 'text', required: true, defaultValue: 'test', - typescriptSchema: [ + jsonSchema: [ () => ({ type: 'string', required: false, diff --git a/packages/payload/src/utilities/configToJSONSchema.ts b/packages/payload/src/utilities/configToJSONSchema.ts index 1e59191b015..65762311c80 100644 --- a/packages/payload/src/utilities/configToJSONSchema.ts +++ b/packages/payload/src/utilities/configToJSONSchema.ts @@ -884,8 +884,8 @@ export function fieldsToJSONSchema({ } } - if ('typescriptSchema' in field && field?.typescriptSchema?.length) { - for (const schema of field.typescriptSchema) { + if ('jsonSchema' in field && field?.jsonSchema?.length) { + for (const schema of field.jsonSchema) { fieldSchema = schema({ jsonSchema: fieldSchema! }) } } diff --git a/test/types/config.ts b/test/types/config.ts index 6704440ff06..d55fcad17d3 100644 --- a/test/types/config.ts +++ b/test/types/config.ts @@ -82,7 +82,7 @@ export default buildConfigWithDefaults({ { name: 'externalType', type: 'text', - typescriptSchema: [ + jsonSchema: [ () => ({ $ref: './test/types/schemas/custom-type.json', }), From 370039cc0bfa4bfe42777c2477f1a6b071f6adc6 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 28 May 2026 06:54:08 +0000 Subject: [PATCH 10/56] docs: capitalisation --- docs/fields/array.mdx | 2 +- docs/fields/blocks.mdx | 2 +- docs/fields/checkbox.mdx | 2 +- docs/fields/code.mdx | 2 +- docs/fields/date.mdx | 2 +- docs/fields/email.mdx | 2 +- docs/fields/group.mdx | 2 +- docs/fields/join.mdx | 2 +- docs/fields/json.mdx | 2 +- docs/fields/number.mdx | 2 +- docs/fields/point.mdx | 2 +- docs/fields/radio.mdx | 2 +- docs/fields/relationship.mdx | 2 +- docs/fields/rich-text.mdx | 2 +- docs/fields/select.mdx | 2 +- docs/fields/text.mdx | 2 +- docs/fields/textarea.mdx | 2 +- docs/fields/upload.mdx | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/fields/array.mdx b/docs/fields/array.mdx index 255e55da36b..4960330d553 100644 --- a/docs/fields/array.mdx +++ b/docs/fields/array.mdx @@ -59,7 +59,7 @@ export const MyArrayField: Field = { | **`custom`** | Extension point for adding custom data (e.g. for plugins) | | **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). | | **`dbName`** | Custom table name for the field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. | -| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`jsonSchema`** | Override field JSON Schema used for type generation and MCP validation | | **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/overview#string-path-virtual-fields). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/blocks.mdx b/docs/fields/blocks.mdx index 8c329017795..077b1862cd7 100644 --- a/docs/fields/blocks.mdx +++ b/docs/fields/blocks.mdx @@ -60,7 +60,7 @@ This page is divided into two parts: first, the settings of the Blocks Field, an | **`labels`** | Customize the block row labels appearing in the Admin dashboard. | | **`admin`** | Admin-specific configuration. [More details](#admin-options). | | **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`jsonSchema`** | Override field JSON Schema used for type generation and MCP validation | | **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/overview#string-path-virtual-fields). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/checkbox.mdx b/docs/fields/checkbox.mdx index b56a37534f8..fd140dacc38 100644 --- a/docs/fields/checkbox.mdx +++ b/docs/fields/checkbox.mdx @@ -43,7 +43,7 @@ export const MyCheckboxField: Field = { | **`required`** | Require this field to have a value. | | **`admin`** | Admin-specific configuration. [More details](./overview#admin-options). | | **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`jsonSchema`** | Override field JSON Schema used for type generation and MCP validation | | **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/code.mdx b/docs/fields/code.mdx index 5cc6e495e1b..325de4aeffa 100644 --- a/docs/fields/code.mdx +++ b/docs/fields/code.mdx @@ -47,7 +47,7 @@ export const MyBlocksField: Field = { | **`required`** | Require this field to have a value. | | **`admin`** | Admin-specific configuration. See below for [more detail](#admin-options). | | **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`jsonSchema`** | Override field JSON Schema used for type generation and MCP validation | | **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/date.mdx b/docs/fields/date.mdx index feb7b1e5920..388b7c158af 100644 --- a/docs/fields/date.mdx +++ b/docs/fields/date.mdx @@ -44,7 +44,7 @@ export const MyDateField: Field = { | **`admin`** | Admin-specific configuration. [More details](#admin-options). | | **`custom`** | Extension point for adding custom data (e.g. for plugins) | | **`timezone`** \* | Set to `true` to enable timezone selection on this field. [More details](#timezones). | -| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`jsonSchema`** | Override field JSON Schema used for type generation and MCP validation | | **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/email.mdx b/docs/fields/email.mdx index 41e47b6a4aa..cabaecde58a 100644 --- a/docs/fields/email.mdx +++ b/docs/fields/email.mdx @@ -44,7 +44,7 @@ export const MyEmailField: Field = { | **`required`** | Require this field to have a value. | | **`admin`** | Admin-specific configuration. [More details](#admin-options). | | **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`jsonSchema`** | Override field JSON Schema used for type generation and MCP validation | | **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/group.mdx b/docs/fields/group.mdx index 81f3fcfbc1f..7dadfa15eb5 100644 --- a/docs/fields/group.mdx +++ b/docs/fields/group.mdx @@ -48,7 +48,7 @@ export const MyGroupField: Field = { | **`admin`** | Admin-specific configuration. [More details](#admin-options). | | **`custom`** | Extension point for adding custom data (e.g. for plugins) | | **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). | -| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`jsonSchema`** | Override field JSON Schema used for type generation and MCP validation | | **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/join.mdx b/docs/fields/join.mdx index 584d1269ab3..16b048c8205 100644 --- a/docs/fields/join.mdx +++ b/docs/fields/join.mdx @@ -148,7 +148,7 @@ powerful Admin UI. | **`defaultSort`** | The field name used to specify the order the joined documents are returned. | | **`admin`** | Admin-specific configuration. [More details](#admin-config-options). | | **`custom`** | Extension point for adding custom data (e.g. for plugins). | -| **`jsonSchema`** | Override field json schema used for type generation and mcp validation. | +| **`jsonSchema`** | Override field JSON Schema used for type generation and MCP validation. | | **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/json.mdx b/docs/fields/json.mdx index 3284fc8b1e8..6d4cba3692f 100644 --- a/docs/fields/json.mdx +++ b/docs/fields/json.mdx @@ -46,7 +46,7 @@ export const MyJSONField: Field = { | **`required`** | Require this field to have a value. | | **`admin`** | Admin-specific configuration. [More details](#admin-options). | | **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`jsonSchema`** | Override field JSON Schema used for type generation and MCP validation | | **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/number.mdx b/docs/fields/number.mdx index 1b1401c7fd7..3eeb37af7b5 100644 --- a/docs/fields/number.mdx +++ b/docs/fields/number.mdx @@ -49,7 +49,7 @@ export const MyNumberField: Field = { | **`required`** | Require this field to have a value. | | **`admin`** | Admin-specific configuration. [More details](#admin-options). | | **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`jsonSchema`** | Override field JSON Schema used for type generation and MCP validation | | **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/point.mdx b/docs/fields/point.mdx index 011d07d9c36..dd5d1746964 100644 --- a/docs/fields/point.mdx +++ b/docs/fields/point.mdx @@ -48,7 +48,7 @@ export const MyPointField: Field = { | **`required`** | Require this field to have a value. | | **`admin`** | Admin-specific configuration. [More details](./overview#admin-options). | | **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`jsonSchema`** | Override field JSON Schema used for type generation and MCP validation | | **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/radio.mdx b/docs/fields/radio.mdx index b4c96fb6d83..fb3c3388c26 100644 --- a/docs/fields/radio.mdx +++ b/docs/fields/radio.mdx @@ -51,7 +51,7 @@ export const MyRadioField: Field = { | **`custom`** | Extension point for adding custom data (e.g. for plugins) | | **`enumName`** | Custom enum name for this field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. | | **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). | -| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`jsonSchema`** | Override field JSON Schema used for type generation and MCP validation | | **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/relationship.mdx b/docs/fields/relationship.mdx index 028a3e46106..99ff6c2197c 100644 --- a/docs/fields/relationship.mdx +++ b/docs/fields/relationship.mdx @@ -59,7 +59,7 @@ export const MyRelationshipField: Field = { | **`required`** | Require this field to have a value. | | **`admin`** | Admin-specific configuration. [More details](#admin-options). | | **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`jsonSchema`** | Override field JSON Schema used for type generation and MCP validation | | **`virtual`** | Provide `true` to disable field in the database, or provide a string path to link the field with a relationship. See [Virtual Field Configuration](/docs/fields/overview#virtual-field-configuration) | | **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) | diff --git a/docs/fields/rich-text.mdx b/docs/fields/rich-text.mdx index 4b9937e81d7..1a61cd8568d 100644 --- a/docs/fields/rich-text.mdx +++ b/docs/fields/rich-text.mdx @@ -34,7 +34,7 @@ Instead, you can invest your time and effort into learning the underlying open-s | **`admin`** | Admin-specific configuration. [More details](#admin-options). | | **`editor`** | Customize or override the rich text editor. [More details](../rich-text/overview). | | **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`jsonSchema`** | Override field JSON Schema used for type generation and MCP validation | | **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | \*_ An asterisk denotes that a property is required._ diff --git a/docs/fields/select.mdx b/docs/fields/select.mdx index 9220be9f56c..7adacda2e3a 100644 --- a/docs/fields/select.mdx +++ b/docs/fields/select.mdx @@ -55,7 +55,7 @@ export const MySelectField: Field = { | **`dbName`** | Custom table name (if `hasMany` set to `true`) for this field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. | | **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). | | **`filterOptions`** | Dynamically filter which options are available based on the user, data, etc. [More details](#filteroptions) | -| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`jsonSchema`** | Override field JSON Schema used for type generation and MCP validation | | **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/text.mdx b/docs/fields/text.mdx index 98af0369d7e..6a7f052d0a9 100644 --- a/docs/fields/text.mdx +++ b/docs/fields/text.mdx @@ -49,7 +49,7 @@ export const MyTextField: Field = { | **`hasMany`** | Makes this field an ordered array of text instead of just a single text. | | **`minRows`** | Minimum number of texts in the array, if `hasMany` is set to true. | | **`maxRows`** | Maximum number of texts in the array, if `hasMany` is set to true. | -| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`jsonSchema`** | Override field JSON Schema used for type generation and MCP validation | | **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/textarea.mdx b/docs/fields/textarea.mdx index 62367c174fc..bde28b433ec 100644 --- a/docs/fields/textarea.mdx +++ b/docs/fields/textarea.mdx @@ -46,7 +46,7 @@ export const MyTextareaField: Field = { | **`required`** | Require this field to have a value. | | **`admin`** | Admin-specific configuration. [More details](#admin-options). | | **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`jsonSchema`** | Override field JSON Schema used for type generation and MCP validation | | **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | _\* An asterisk denotes that a property is required._ diff --git a/docs/fields/upload.mdx b/docs/fields/upload.mdx index 13bdc7c18f6..e5331f2c7f2 100644 --- a/docs/fields/upload.mdx +++ b/docs/fields/upload.mdx @@ -67,7 +67,7 @@ export const MyUploadField: Field = { | **`required`** | Require this field to have a value. | | **`admin`** | Admin-specific configuration. [Admin Options](./overview#admin-options). | | **`custom`** | Extension point for adding custom data (e.g. for plugins) | -| **`jsonSchema`** | Override field json schema used for type generation and mcp validation | +| **`jsonSchema`** | Override field JSON Schema used for type generation and MCP validation | | **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) | | **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) | From cd440b878ec3d63aa91021104804cee4e042a8ec Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 28 May 2026 06:56:37 +0000 Subject: [PATCH 11/56] remove re-exports, improve variable names --- .../blocks/client/component/index.tsx | 2 +- .../blocks/client/componentInline/index.tsx | 2 +- .../blocks/client/nodes/BlocksNode.tsx | 2 +- .../blocks/client/nodes/InlineBlocksNode.tsx | 5 +-- .../features/blocks/client/plugin/index.tsx | 2 +- .../blocks/server/graphQLPopulationPromise.ts | 3 +- .../src/features/blocks/server/index.ts | 6 +++ .../blocks/server/nodes/BlocksNode.tsx | 8 ---- .../blocks/server/nodes/InlineBlocksNode.tsx | 4 -- .../src/features/blocks/server/schema.ts | 40 +++++++++---------- .../src/features/blocks/server/validate.ts | 3 +- .../lexicalToHtml/async/converters/upload.ts | 2 +- .../lexicalToHtml/sync/converters/upload.ts | 2 +- .../converter/converters/upload.tsx | 2 +- .../client/nodes/HorizontalRuleNode.tsx | 2 +- .../server/nodes/HorizontalRuleNode.tsx | 4 -- .../src/features/link/nodes/types.ts | 5 --- .../src/features/lists/plugin/index.tsx | 4 -- .../components/RelationshipComponent.tsx | 2 +- .../relationship/client/plugins/index.tsx | 2 +- .../server/graphQLPopulationPromise.ts | 2 +- .../server/nodes/RelationshipNode.tsx | 4 -- .../upload/client/component/index.tsx | 2 +- .../upload/client/nodes/UploadNode.tsx | 6 +-- .../features/upload/client/plugin/index.tsx | 2 +- .../upload/server/graphQLPopulationPromise.ts | 2 +- packages/richtext-lexical/src/index.ts | 16 ++++---- 27 files changed, 51 insertions(+), 85 deletions(-) delete mode 100644 packages/richtext-lexical/src/features/link/nodes/types.ts diff --git a/packages/richtext-lexical/src/features/blocks/client/component/index.tsx b/packages/richtext-lexical/src/features/blocks/client/component/index.tsx index 43143e8ab51..58081e140a3 100644 --- a/packages/richtext-lexical/src/features/blocks/client/component/index.tsx +++ b/packages/richtext-lexical/src/features/blocks/client/component/index.tsx @@ -40,7 +40,7 @@ import React, { useCallback, useEffect, useMemo, useRef } from 'react' import { v4 as uuid } from 'uuid' import type { ViewMapBlockComponentProps } from '../../../../types/index.js' -import type { BlockFields } from '../../server/nodes/BlocksNode.js' +import type { BlockFields } from '../../server/schema.js' import './index.css' import { useEditorConfigContext } from '../../../../lexical/config/client/EditorConfigProvider.js' diff --git a/packages/richtext-lexical/src/features/blocks/client/componentInline/index.tsx b/packages/richtext-lexical/src/features/blocks/client/componentInline/index.tsx index c63047f856e..c6cf10a026e 100644 --- a/packages/richtext-lexical/src/features/blocks/client/componentInline/index.tsx +++ b/packages/richtext-lexical/src/features/blocks/client/componentInline/index.tsx @@ -31,7 +31,7 @@ import React, { createContext, useCallback, useEffect, useMemo, useRef } from 'r import { v4 as uuid } from 'uuid' import type { ViewMapInlineBlockComponentProps } from '../../../../types/index.js' -import type { InlineBlockFields } from '../../server/nodes/InlineBlocksNode.js' +import type { InlineBlockFields } from '../../server/schema.js' import type { BlockComponentProps } from '../component/index.js' import { useEditorConfigContext } from '../../../../lexical/config/client/EditorConfigProvider.js' diff --git a/packages/richtext-lexical/src/features/blocks/client/nodes/BlocksNode.tsx b/packages/richtext-lexical/src/features/blocks/client/nodes/BlocksNode.tsx index 85a64ae15f5..e597338e268 100644 --- a/packages/richtext-lexical/src/features/blocks/client/nodes/BlocksNode.tsx +++ b/packages/richtext-lexical/src/features/blocks/client/nodes/BlocksNode.tsx @@ -9,7 +9,7 @@ import { import React, { type JSX } from 'react' import type { ViewMapBlockComponentProps } from '../../../../types/index.js' -import type { BlockFieldsOptionalID, SerializedBlockNode } from '../../server/nodes/BlocksNode.js' +import type { BlockFieldsOptionalID, SerializedBlockNode } from '../../server/schema.js' import { ServerBlockNode } from '../../server/nodes/BlocksNode.js' import { BlockComponent } from '../component/index.js' diff --git a/packages/richtext-lexical/src/features/blocks/client/nodes/InlineBlocksNode.tsx b/packages/richtext-lexical/src/features/blocks/client/nodes/InlineBlocksNode.tsx index ec32fb10d0f..9fcfda9399c 100644 --- a/packages/richtext-lexical/src/features/blocks/client/nodes/InlineBlocksNode.tsx +++ b/packages/richtext-lexical/src/features/blocks/client/nodes/InlineBlocksNode.tsx @@ -9,10 +9,7 @@ import { import React, { type JSX } from 'react' import type { ViewMapInlineBlockComponentProps } from '../../../../types/index.js' -import type { - InlineBlockFields, - SerializedInlineBlockNode, -} from '../../server/nodes/InlineBlocksNode.js' +import type { InlineBlockFields, SerializedInlineBlockNode } from '../../server/schema.js' import { ServerInlineBlockNode } from '../../server/nodes/InlineBlocksNode.js' diff --git a/packages/richtext-lexical/src/features/blocks/client/plugin/index.tsx b/packages/richtext-lexical/src/features/blocks/client/plugin/index.tsx index fa9539852ec..97533dc61f7 100644 --- a/packages/richtext-lexical/src/features/blocks/client/plugin/index.tsx +++ b/packages/richtext-lexical/src/features/blocks/client/plugin/index.tsx @@ -17,7 +17,7 @@ import { import { useEffect, useState } from 'react' import type { PluginComponent } from '../../../typesClient.js' -import type { BlockFields, BlockFieldsOptionalID } from '../../server/nodes/BlocksNode.js' +import type { BlockFields, BlockFieldsOptionalID } from '../../server/schema.js' import { useEditorConfigContext } from '../../../../lexical/config/client/EditorConfigProvider.js' import { useLexicalDrawer } from '../../../../utilities/fieldsDrawer/useLexicalDrawer.js' diff --git a/packages/richtext-lexical/src/features/blocks/server/graphQLPopulationPromise.ts b/packages/richtext-lexical/src/features/blocks/server/graphQLPopulationPromise.ts index b8456e3b25c..363a8e6af26 100644 --- a/packages/richtext-lexical/src/features/blocks/server/graphQLPopulationPromise.ts +++ b/packages/richtext-lexical/src/features/blocks/server/graphQLPopulationPromise.ts @@ -1,8 +1,7 @@ import type { Block } from 'payload' import type { PopulationPromise } from '../../typesServer.js' -import type { SerializedInlineBlockNode } from '../server/nodes/InlineBlocksNode.js' -import type { SerializedBlockNode } from './nodes/BlocksNode.js' +import type { SerializedBlockNode, SerializedInlineBlockNode } from './schema.js' import { recursivelyPopulateFieldsForGraphQL } from '../../../populateGraphQL/recursivelyPopulateFieldsForGraphQL.js' diff --git a/packages/richtext-lexical/src/features/blocks/server/index.ts b/packages/richtext-lexical/src/features/blocks/server/index.ts index 2972e2ba9dd..7d10c7321f8 100644 --- a/packages/richtext-lexical/src/features/blocks/server/index.ts +++ b/packages/richtext-lexical/src/features/blocks/server/index.ts @@ -173,6 +173,9 @@ export const BlocksFeature = createServerFeature { if (!node) { + if (!blockConfigs.length) { + return [] + } return [ { name: 'lexical_blocks', @@ -198,6 +201,9 @@ export const BlocksFeature = createServerFeature { if (!node) { + if (!inlineBlockConfigs.length) { + return [] + } return [ { name: 'lexical_inline_blocks', diff --git a/packages/richtext-lexical/src/features/blocks/server/nodes/BlocksNode.tsx b/packages/richtext-lexical/src/features/blocks/server/nodes/BlocksNode.tsx index aa59493434e..307a09f5ab6 100644 --- a/packages/richtext-lexical/src/features/blocks/server/nodes/BlocksNode.tsx +++ b/packages/richtext-lexical/src/features/blocks/server/nodes/BlocksNode.tsx @@ -16,14 +16,6 @@ import { import type { BlockFields, BlockFieldsOptionalID, SerializedBlockNode } from '../schema.js' -// Re-export the runtime types from the colocated schema module so existing -// imports of this path keep working. -export type { - BlockFields, - BlockFieldsOptionalID, - SerializedBlockNode, -} from '../schema.js' - export class ServerBlockNode extends DecoratorBlockNode { __cacheBuster: number __fields: BlockFields diff --git a/packages/richtext-lexical/src/features/blocks/server/nodes/InlineBlocksNode.tsx b/packages/richtext-lexical/src/features/blocks/server/nodes/InlineBlocksNode.tsx index 282527bbfc8..ccab69d6794 100644 --- a/packages/richtext-lexical/src/features/blocks/server/nodes/InlineBlocksNode.tsx +++ b/packages/richtext-lexical/src/features/blocks/server/nodes/InlineBlocksNode.tsx @@ -15,10 +15,6 @@ import { $applyNodeReplacement, DecoratorNode } from 'lexical' import type { InlineBlockFields, SerializedInlineBlockNode } from '../schema.js' -// Re-export the runtime types from the colocated schema module so existing -// imports of this path keep working. -export type { InlineBlockFields, SerializedInlineBlockNode } from '../schema.js' - export class ServerInlineBlockNode extends DecoratorNode { __cacheBuster: number __fields: InlineBlockFields diff --git a/packages/richtext-lexical/src/features/blocks/server/schema.ts b/packages/richtext-lexical/src/features/blocks/server/schema.ts index 13af760bd3a..eca31c13e36 100644 --- a/packages/richtext-lexical/src/features/blocks/server/schema.ts +++ b/packages/richtext-lexical/src/features/blocks/server/schema.ts @@ -49,14 +49,14 @@ export type SerializedInlineBlockNode = { };` /** - * Per-block `fields` schema. Strips Payload's auto-added `id`/`blockName` - * (every block carries those as base fields) and re-adds them with strict - * runtime types — required, non-null `id`; required `blockName: string | null` - * (omitted for inline blocks). + * JSON Schema for the `fields:` payload of one (inline) block. Strips + * Payload's auto-added `id`/`blockName` (every block carries those as base + * fields) and re-adds them with strict runtime types — required, non-null + * `id`; required `blockName: string | null` (omitted for inline blocks). * * Blocks with `interfaceName` are emitted as top-level `$ref` definitions. */ -const buildBlockVariantSchema = ( +const buildBlockFieldsSchema = ( block: Block, args: JSONSchemaArgs, { isInlineBlock }: { isInlineBlock: boolean }, @@ -94,7 +94,7 @@ const buildBlockVariantSchema = ( required.push('blockName') } - const variantSchema: JSONSchema4 = { + const fieldsSchema: JSONSchema4 = { type: 'object', additionalProperties: false, properties, @@ -102,27 +102,27 @@ const buildBlockVariantSchema = ( } if (block.interfaceName) { - args.interfaceNameDefinitions.set(block.interfaceName, variantSchema) + args.interfaceNameDefinitions.set(block.interfaceName, fieldsSchema) return { $ref: `#/definitions/${block.interfaceName}` } } - return variantSchema + return fieldsSchema } export const createBlockNodeJSONSchema = (blockConfigs: Block[]): JSONSchemaFn => (args) => { args.typeStringDefinitions.add(BLOCK_NODES_TS) - const variants = blockConfigs.map((block) => - buildBlockVariantSchema(block, args, { isInlineBlock: false }), + const blockFieldsSchemas = blockConfigs.map((block) => + buildBlockFieldsSchema(block, args, { isInlineBlock: false }), ) const fieldsSchema: JSONSchema4 = - variants.length === 0 + blockFieldsSchemas.length === 0 ? { type: 'object', additionalProperties: true } - : variants.length === 1 - ? variants[0]! - : { oneOf: variants } + : blockFieldsSchemas.length === 1 + ? blockFieldsSchemas[0]! + : { oneOf: blockFieldsSchemas } const allHaveInterfaceName = blockConfigs.length > 0 && blockConfigs.every((b) => Boolean(b.interfaceName)) @@ -148,16 +148,16 @@ export const createInlineBlockNodeJSONSchema = (inlineBlockConfigs: Block[]): JSONSchemaFn => (args) => { args.typeStringDefinitions.add(BLOCK_NODES_TS) - const variants = inlineBlockConfigs.map((block) => - buildBlockVariantSchema(block, args, { isInlineBlock: true }), + const blockFieldsSchemas = inlineBlockConfigs.map((block) => + buildBlockFieldsSchema(block, args, { isInlineBlock: true }), ) const fieldsSchema: JSONSchema4 = - variants.length === 0 + blockFieldsSchemas.length === 0 ? { type: 'object', additionalProperties: true } - : variants.length === 1 - ? variants[0]! - : { oneOf: variants } + : blockFieldsSchemas.length === 1 + ? blockFieldsSchemas[0]! + : { oneOf: blockFieldsSchemas } const allHaveInterfaceName = inlineBlockConfigs.length > 0 && inlineBlockConfigs.every((b) => Boolean(b.interfaceName)) diff --git a/packages/richtext-lexical/src/features/blocks/server/validate.ts b/packages/richtext-lexical/src/features/blocks/server/validate.ts index 7adc71cee59..acfd6f2eef5 100644 --- a/packages/richtext-lexical/src/features/blocks/server/validate.ts +++ b/packages/richtext-lexical/src/features/blocks/server/validate.ts @@ -3,8 +3,7 @@ import type { Block } from 'payload' import { fieldSchemasToFormState } from '@payloadcms/ui/forms/fieldSchemasToFormState' import type { NodeValidation } from '../../typesServer.js' -import type { BlockFields, SerializedBlockNode } from './nodes/BlocksNode.js' -import type { SerializedInlineBlockNode } from './nodes/InlineBlocksNode.js' +import type { BlockFields, SerializedBlockNode, SerializedInlineBlockNode } from './schema.js' /** * Runs validation for blocks. This function will determine if the rich text field itself is valid. It does not handle diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/upload.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/upload.ts index c1f0f0af52f..75ed09ff54b 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/upload.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/converters/upload.ts @@ -3,7 +3,7 @@ import type { FileData, FileSize, TypeWithID } from 'payload' import escapeHTML from 'escape-html' import type { SerializedUploadNode } from '../../../../../types/nodeTypes.js' -import type { UploadDataImproved } from '../../../../upload/server/nodes/UploadNode.js' +import type { UploadDataImproved } from '../../../../upload/server/schema.js' import type { HTMLConvertersAsync } from '../types.js' export const UploadHTMLConverterAsync: HTMLConvertersAsync = { diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/upload.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/upload.ts index 8381cf5eb4a..d63b8807ed4 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/upload.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/converters/upload.ts @@ -3,7 +3,7 @@ import type { FileData, FileSize, TypeWithID } from 'payload' import escapeHTML from 'escape-html' import type { SerializedUploadNode } from '../../../../../types/nodeTypes.js' -import type { UploadDataImproved } from '../../../../upload/server/nodes/UploadNode.js' +import type { UploadDataImproved } from '../../../../upload/server/schema.js' import type { HTMLConverters } from '../types.js' export const UploadHTMLConverter: HTMLConverters = { diff --git a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/upload.tsx b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/upload.tsx index 6a3070ade10..d9ba171cce9 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/upload.tsx +++ b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/converters/upload.tsx @@ -1,7 +1,7 @@ import type { FileData, FileSize, TypeWithID } from 'payload' import type { SerializedUploadNode } from '../../../../../types/nodeTypes.js' -import type { UploadDataImproved } from '../../../../upload/server/nodes/UploadNode.js' +import type { UploadDataImproved } from '../../../../upload/server/schema.js' import type { JSXConverters } from '../types.js' export const UploadJSXConverter: JSXConverters = { diff --git a/packages/richtext-lexical/src/features/horizontalRule/client/nodes/HorizontalRuleNode.tsx b/packages/richtext-lexical/src/features/horizontalRule/client/nodes/HorizontalRuleNode.tsx index 38da131c67a..1abdb18afa0 100644 --- a/packages/richtext-lexical/src/features/horizontalRule/client/nodes/HorizontalRuleNode.tsx +++ b/packages/richtext-lexical/src/features/horizontalRule/client/nodes/HorizontalRuleNode.tsx @@ -4,7 +4,7 @@ import type { DOMConversionOutput, LexicalNode, SerializedLexicalNode } from 'le import { $applyNodeReplacement } from 'lexical' import * as React from 'react' -import type { SerializedHorizontalRuleNode } from '../../server/nodes/HorizontalRuleNode.js' +import type { SerializedHorizontalRuleNode } from '../../server/schema.js' import { HorizontalRuleServerNode } from '../../server/nodes/HorizontalRuleNode.js' diff --git a/packages/richtext-lexical/src/features/horizontalRule/server/nodes/HorizontalRuleNode.tsx b/packages/richtext-lexical/src/features/horizontalRule/server/nodes/HorizontalRuleNode.tsx index 6fff022ccff..24924823951 100644 --- a/packages/richtext-lexical/src/features/horizontalRule/server/nodes/HorizontalRuleNode.tsx +++ b/packages/richtext-lexical/src/features/horizontalRule/server/nodes/HorizontalRuleNode.tsx @@ -14,10 +14,6 @@ import { $applyNodeReplacement, createCommand, DecoratorNode } from 'lexical' import type { SerializedHorizontalRuleNode } from '../schema.js' -// Re-export the runtime type from the colocated schema module so existing -// imports of this path keep working. -export type { SerializedHorizontalRuleNode } from '../schema.js' - export const INSERT_HORIZONTAL_RULE_COMMAND: LexicalCommand = createCommand( 'INSERT_HORIZONTAL_RULE_COMMAND', ) diff --git a/packages/richtext-lexical/src/features/link/nodes/types.ts b/packages/richtext-lexical/src/features/link/nodes/types.ts deleted file mode 100644 index d62fcd82b00..00000000000 --- a/packages/richtext-lexical/src/features/link/nodes/types.ts +++ /dev/null @@ -1,5 +0,0 @@ -// Re-export the runtime types from the colocated schema module so existing -// imports of this path keep working. The canonical definitions live in -// `../server/schema.ts` next to the JSON Schema builders and the inlined- -// into-payload-types TS source string. -export type { LinkFields, SerializedAutoLinkNode, SerializedLinkNode } from '../server/schema.js' diff --git a/packages/richtext-lexical/src/features/lists/plugin/index.tsx b/packages/richtext-lexical/src/features/lists/plugin/index.tsx index 6d2b4ce62e0..217cec47fd0 100644 --- a/packages/richtext-lexical/src/features/lists/plugin/index.tsx +++ b/packages/richtext-lexical/src/features/lists/plugin/index.tsx @@ -4,10 +4,6 @@ import React from 'react' import type { PluginComponent } from '../../typesClient.js' -// Re-export the runtime types from the colocated schema module so existing -// imports from this client entry keep working. -export type { SerializedListItemNode, SerializedListNode } from '../shared/schema.js' - export const LexicalListPlugin: PluginComponent = () => { return } diff --git a/packages/richtext-lexical/src/features/relationship/client/components/RelationshipComponent.tsx b/packages/richtext-lexical/src/features/relationship/client/components/RelationshipComponent.tsx index ae795c9fc83..9bab2fd15fe 100644 --- a/packages/richtext-lexical/src/features/relationship/client/components/RelationshipComponent.tsx +++ b/packages/richtext-lexical/src/features/relationship/client/components/RelationshipComponent.tsx @@ -9,7 +9,7 @@ import { $getNodeByKey, $getSelection, $isNodeSelection, $isRangeSelection } fro import { formatAdminURL } from 'payload/shared' import React, { useCallback, useEffect, useReducer, useRef, useState } from 'react' -import type { RelationshipData } from '../../server/nodes/RelationshipNode.js' +import type { RelationshipData } from '../../server/schema.js' import './index.css' import { useLexicalDocumentDrawer } from '../../../../utilities/fieldsDrawer/useLexicalDocumentDrawer.js' diff --git a/packages/richtext-lexical/src/features/relationship/client/plugins/index.tsx b/packages/richtext-lexical/src/features/relationship/client/plugins/index.tsx index 2d57651244d..be8ffa41147 100644 --- a/packages/richtext-lexical/src/features/relationship/client/plugins/index.tsx +++ b/packages/richtext-lexical/src/features/relationship/client/plugins/index.tsx @@ -15,7 +15,7 @@ import { useEffect } from 'react' import type { PluginComponent } from '../../../typesClient.js' import type { RelationshipFeatureProps } from '../../server/index.js' -import type { RelationshipData } from '../../server/nodes/RelationshipNode.js' +import type { RelationshipData } from '../../server/schema.js' import { RelationshipDrawer } from '../drawer/index.js' import { $createRelationshipNode, RelationshipNode } from '../nodes/RelationshipNode.js' diff --git a/packages/richtext-lexical/src/features/relationship/server/graphQLPopulationPromise.ts b/packages/richtext-lexical/src/features/relationship/server/graphQLPopulationPromise.ts index 0fc428b625a..1c7a9a96c8b 100644 --- a/packages/richtext-lexical/src/features/relationship/server/graphQLPopulationPromise.ts +++ b/packages/richtext-lexical/src/features/relationship/server/graphQLPopulationPromise.ts @@ -1,6 +1,6 @@ import type { PopulationPromise } from '../../typesServer.js' import type { RelationshipFeatureProps } from './index.js' -import type { SerializedRelationshipNode } from './nodes/RelationshipNode.js' +import type { SerializedRelationshipNode } from './schema.js' import { populate } from '../../../populateGraphQL/populate.js' diff --git a/packages/richtext-lexical/src/features/relationship/server/nodes/RelationshipNode.tsx b/packages/richtext-lexical/src/features/relationship/server/nodes/RelationshipNode.tsx index 6aef96bc2c1..24079acc357 100644 --- a/packages/richtext-lexical/src/features/relationship/server/nodes/RelationshipNode.tsx +++ b/packages/richtext-lexical/src/features/relationship/server/nodes/RelationshipNode.tsx @@ -16,10 +16,6 @@ import { import type { RelationshipData, SerializedRelationshipNode } from '../schema.js' -// Re-export the runtime data types from the colocated schema module so -// existing imports of this path keep working. -export type { RelationshipData, SerializedRelationshipNode } from '../schema.js' - function $relationshipElementToServerNode(domNode: HTMLDivElement): DOMConversionOutput | null { const id = domNode.getAttribute('data-lexical-relationship-id') const relationTo = domNode.getAttribute('data-lexical-relationship-relationTo') diff --git a/packages/richtext-lexical/src/features/upload/client/component/index.tsx b/packages/richtext-lexical/src/features/upload/client/component/index.tsx index 5db1cf7eccc..e0c152213e7 100644 --- a/packages/richtext-lexical/src/features/upload/client/component/index.tsx +++ b/packages/richtext-lexical/src/features/upload/client/component/index.tsx @@ -25,7 +25,7 @@ import { formatAdminURL, isImage } from 'payload/shared' import React, { useCallback, useEffect, useId, useReducer, useRef, useState } from 'react' import type { BaseClientFeatureProps } from '../../../typesClient.js' -import type { UploadData } from '../../server/nodes/UploadNode.js' +import type { UploadData } from '../../server/schema.js' import type { UploadFeaturePropsClient } from '../index.js' import type { UploadNode } from '../nodes/UploadNode.js' diff --git a/packages/richtext-lexical/src/features/upload/client/nodes/UploadNode.tsx b/packages/richtext-lexical/src/features/upload/client/nodes/UploadNode.tsx index aa3323e5869..bf2df98a8af 100644 --- a/packages/richtext-lexical/src/features/upload/client/nodes/UploadNode.tsx +++ b/packages/richtext-lexical/src/features/upload/client/nodes/UploadNode.tsx @@ -6,11 +6,7 @@ import ObjectID from 'bson-objectid' import { $applyNodeReplacement } from 'lexical' import * as React from 'react' -import type { - Internal_UploadData, - SerializedUploadNode, - UploadData, -} from '../../server/nodes/UploadNode.js' +import type { Internal_UploadData, SerializedUploadNode, UploadData } from '../../server/schema.js' import { $convertUploadElement } from '../../server/nodes/conversions.js' import { UploadServerNode } from '../../server/nodes/UploadNode.js' diff --git a/packages/richtext-lexical/src/features/upload/client/plugin/index.tsx b/packages/richtext-lexical/src/features/upload/client/plugin/index.tsx index 691473acafa..cfd3f4d7644 100644 --- a/packages/richtext-lexical/src/features/upload/client/plugin/index.tsx +++ b/packages/richtext-lexical/src/features/upload/client/plugin/index.tsx @@ -23,7 +23,7 @@ import { import React, { useEffect } from 'react' import type { PluginComponent } from '../../../typesClient.js' -import type { Internal_UploadData, UploadData } from '../../server/nodes/UploadNode.js' +import type { Internal_UploadData, UploadData } from '../../server/schema.js' import type { UploadFeaturePropsClient } from '../index.js' import { useEnabledRelationships } from '../../../relationship/client/utils/useEnabledRelationships.js' diff --git a/packages/richtext-lexical/src/features/upload/server/graphQLPopulationPromise.ts b/packages/richtext-lexical/src/features/upload/server/graphQLPopulationPromise.ts index 65d61a96ddf..854e24f4a16 100644 --- a/packages/richtext-lexical/src/features/upload/server/graphQLPopulationPromise.ts +++ b/packages/richtext-lexical/src/features/upload/server/graphQLPopulationPromise.ts @@ -1,6 +1,6 @@ import type { PopulationPromise } from '../../typesServer.js' import type { UploadFeatureProps } from './index.js' -import type { SerializedUploadNode } from './nodes/UploadNode.js' +import type { SerializedUploadNode } from './schema.js' import { populate } from '../../../populateGraphQL/populate.js' import { recursivelyPopulateFieldsForGraphQL } from '../../../populateGraphQL/recursivelyPopulateFieldsForGraphQL.js' diff --git a/packages/richtext-lexical/src/index.ts b/packages/richtext-lexical/src/index.ts index 57e6e0129ee..d5f13570e27 100644 --- a/packages/richtext-lexical/src/index.ts +++ b/packages/richtext-lexical/src/index.ts @@ -188,17 +188,16 @@ export type { export { $createServerBlockNode, $isServerBlockNode, - type BlockFields, ServerBlockNode, } from './features/blocks/server/nodes/BlocksNode.js' - export { $createServerInlineBlockNode, $isServerInlineBlockNode, - type InlineBlockFields, ServerInlineBlockNode, } from './features/blocks/server/nodes/InlineBlocksNode.js' +export type { BlockFields, InlineBlockFields } from './features/blocks/server/schema.js' + export { convertHTMLToLexical } from './features/converters/htmlToLexical/index.js' export { lexicalHTMLField } from './features/converters/lexicalToHtml/async/field/index.js' @@ -231,8 +230,8 @@ export { } from './features/link/nodes/AutoLinkNode.js' export { $createLinkNode, $isLinkNode, LinkNode } from './features/link/nodes/LinkNode.js' -export type { LinkFields } from './features/link/nodes/types.js' export { LinkFeature, type LinkFeatureServerProps } from './features/link/server/index.js' +export type { LinkFields } from './features/link/server/schema.js' export { ChecklistFeature } from './features/lists/checklist/server/index.js' export { OrderedListFeature } from './features/lists/orderedList/server/index.js' @@ -246,10 +245,8 @@ export { type RelationshipFeatureProps, } from './features/relationship/server/index.js' -export { - type RelationshipData, - RelationshipServerNode, -} from './features/relationship/server/nodes/RelationshipNode.js' +export { RelationshipServerNode } from './features/relationship/server/nodes/RelationshipNode.js' +export type { RelationshipData } from './features/relationship/server/schema.js' export { defaultColors } from './features/textState/defaultColors.js' export { TextStateFeature } from './features/textState/feature.server.js' @@ -298,7 +295,8 @@ export { createNode } from './features/typeUtilities.js' // Only useful in featu export { UploadFeature } from './features/upload/server/index.js' export type { UploadFeatureProps } from './features/upload/server/index.js' -export { type UploadData, UploadServerNode } from './features/upload/server/nodes/UploadNode.js' +export { UploadServerNode } from './features/upload/server/nodes/UploadNode.js' +export type { UploadData } from './features/upload/server/schema.js' export type { EditorConfigContextType } from './lexical/config/client/EditorConfigProvider.js' export { From 282e697e201a0822ef06977ad5ae550bed84f3d8 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 28 May 2026 07:08:53 +0000 Subject: [PATCH 12/56] fix invalid tag schema generation --- .../src/features/heading/server/schema.ts | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/richtext-lexical/src/features/heading/server/schema.ts b/packages/richtext-lexical/src/features/heading/server/schema.ts index eae8b6a49b8..1f9e7f599f8 100644 --- a/packages/richtext-lexical/src/features/heading/server/schema.ts +++ b/packages/richtext-lexical/src/features/heading/server/schema.ts @@ -2,6 +2,7 @@ import type { SerializedHeadingNode as _SerializedHeadingNode, HeadingTagType, } from '@lexical/rich-text' +import type { JSONSchema4 } from 'json-schema' import type { SerializedLexicalNode } from 'lexical' import type { StronglyTypedElementNode } from '../../../types/nodeTypes.js' @@ -26,11 +27,17 @@ export const createHeadingJSONSchema = (enabledHeadingSizes: HeadingTagType[]): JSONSchemaFn => ({ elementNodeSchema, nodeUnionName, typeStringDefinitions }) => { typeStringDefinitions.add(SERIALIZED_HEADING_NODE_TS) - // Skip the second generic arg when every tag is enabled — the helper - // type's default already covers all six. + // Empty array means the user disabled every heading size. Treat the same + // as "no tag constraint" rather than emitting an invalid `` generic + // and an unsatisfiable `enum: []`. const isAllTags = - enabledHeadingSizes.length === ALL_HEADING_TAGS.length && - ALL_HEADING_TAGS.every((tag) => enabledHeadingSizes.includes(tag)) + enabledHeadingSizes.length === 0 || + (enabledHeadingSizes.length === ALL_HEADING_TAGS.length && + ALL_HEADING_TAGS.every((tag) => enabledHeadingSizes.includes(tag))) + const tagSchema: JSONSchema4 = + enabledHeadingSizes.length === 0 + ? { type: 'string' } + : { type: 'string', enum: enabledHeadingSizes } const tagUnion = enabledHeadingSizes.map((tag) => `'${tag}'`).join(' | ') const tsType = isAllTags ? `SerializedHeadingNode<${nodeUnionName}>` @@ -38,7 +45,7 @@ export const createHeadingJSONSchema = return elementNodeSchema({ nodeType: 'heading', - properties: { tag: { type: 'string', enum: enabledHeadingSizes } }, + properties: { tag: tagSchema }, required: ['tag'], tsType, }) From a1a82308563b5fae5c22e2b5a19722cc4e56cd0b Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 28 May 2026 16:53:24 +0000 Subject: [PATCH 13/56] remove re-exports --- .../src/features/upload/server/nodes/UploadNode.tsx | 10 ---------- .../src/features/upload/server/nodes/conversions.ts | 3 ++- .../src/features/upload/server/validate.ts | 2 +- .../src/field/Diff/converters/upload/index.tsx | 2 +- .../src/lexical/config/server/sanitize.ts | 5 +---- 5 files changed, 5 insertions(+), 17 deletions(-) diff --git a/packages/richtext-lexical/src/features/upload/server/nodes/UploadNode.tsx b/packages/richtext-lexical/src/features/upload/server/nodes/UploadNode.tsx index ef408ec5c1a..ec4e2efaf88 100644 --- a/packages/richtext-lexical/src/features/upload/server/nodes/UploadNode.tsx +++ b/packages/richtext-lexical/src/features/upload/server/nodes/UploadNode.tsx @@ -17,16 +17,6 @@ import type { Internal_UploadData, SerializedUploadNode, UploadData } from '../s import { $convertUploadElement } from './conversions.js' -// Re-export the runtime data types from the colocated schema module so -// existing imports of this path keep working. Canonical definitions live in -// `../schema.ts` next to the JSON Schema builder + inlined TS source string. -export type { - Internal_UploadData, - SerializedUploadNode, - UploadData, - UploadDataImproved, -} from '../schema.js' - export class UploadServerNode extends DecoratorBlockNode { __data: UploadData diff --git a/packages/richtext-lexical/src/features/upload/server/nodes/conversions.ts b/packages/richtext-lexical/src/features/upload/server/nodes/conversions.ts index b3fa4330b54..f0cb83e04ff 100644 --- a/packages/richtext-lexical/src/features/upload/server/nodes/conversions.ts +++ b/packages/richtext-lexical/src/features/upload/server/nodes/conversions.ts @@ -5,7 +5,8 @@ import type { DOMConversionOutput } from 'lexical' import ObjectID from 'bson-objectid' import type { $createUploadNode } from '../../client/nodes/UploadNode.js' -import type { $createUploadServerNode, Internal_UploadData } from './UploadNode.js' +import type { Internal_UploadData } from '../schema.js' +import type { $createUploadServerNode } from './UploadNode.js' export function isGoogleDocCheckboxImg(img: HTMLImageElement): boolean { return ( diff --git a/packages/richtext-lexical/src/features/upload/server/validate.ts b/packages/richtext-lexical/src/features/upload/server/validate.ts index ac475d1acb8..211edca0279 100644 --- a/packages/richtext-lexical/src/features/upload/server/validate.ts +++ b/packages/richtext-lexical/src/features/upload/server/validate.ts @@ -3,7 +3,7 @@ import { isValidID } from 'payload' import type { NodeValidation } from '../../typesServer.js' import type { UploadFeatureProps } from './index.js' -import type { SerializedUploadNode } from './nodes/UploadNode.js' +import type { SerializedUploadNode } from './schema.js' export const uploadValidation = ( props: UploadFeatureProps, diff --git a/packages/richtext-lexical/src/field/Diff/converters/upload/index.tsx b/packages/richtext-lexical/src/field/Diff/converters/upload/index.tsx index 126fd8616d1..b36655edd96 100644 --- a/packages/richtext-lexical/src/field/Diff/converters/upload/index.tsx +++ b/packages/richtext-lexical/src/field/Diff/converters/upload/index.tsx @@ -10,7 +10,7 @@ import { formatFilesize } from 'payload/shared' import React from 'react' import type { HTMLConvertersAsync } from '../../../../features/converters/lexicalToHtml/async/types.js' -import type { UploadDataImproved } from '../../../../features/upload/server/nodes/UploadNode.js' +import type { UploadDataImproved } from '../../../../features/upload/server/schema.js' import type { SerializedUploadNode } from '../../../../types/nodeTypes.js' const baseClass = 'lexical-upload-diff' diff --git a/packages/richtext-lexical/src/lexical/config/server/sanitize.ts b/packages/richtext-lexical/src/lexical/config/server/sanitize.ts index 4579000728d..f6481d3dd4c 100644 --- a/packages/richtext-lexical/src/lexical/config/server/sanitize.ts +++ b/packages/richtext-lexical/src/lexical/config/server/sanitize.ts @@ -84,9 +84,6 @@ export const sanitizeServerFeatures = ( ) } sanitized.nodes.push(node) - } - feature.nodes.forEach((node) => { - const nodeType = 'with' in node.node ? node.node.replace.getType() : node.node.getType() // TODO: Idk if this works for node replacements if (node?.graphQLPopulationPromises?.length) { sanitized.graphQLPopulationPromises.set(nodeType, node.graphQLPopulationPromises) } @@ -111,7 +108,7 @@ export const sanitizeServerFeatures = ( if (node?.getSubFieldsData) { sanitized.getSubFieldsData?.set(nodeType, node.getSubFieldsData) } - }) + } } if (feature.markdownTransformers?.length) { From 287a80c6d00c3c600ef98a9bef90e8e6949a30a9 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 28 May 2026 19:50:06 +0000 Subject: [PATCH 14/56] feat!: always generate block interface --- docs/fields/blocks.mdx | 18 +++++++------- docs/typescript/generating-types.mdx | 4 +++- packages/payload/src/fields/config/types.ts | 14 +++++++---- .../src/utilities/configToJSONSchema.ts | 24 +++++++++++++------ 4 files changed, 39 insertions(+), 21 deletions(-) diff --git a/docs/fields/blocks.mdx b/docs/fields/blocks.mdx index 077b1862cd7..a855556c6ed 100644 --- a/docs/fields/blocks.mdx +++ b/docs/fields/blocks.mdx @@ -194,15 +194,15 @@ Blocks are defined as separate configs of their own. trivializes their reusability. -| Option | Description | -| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`slug`** \* | Identifier for this block type. Will be saved on each block as the `blockType` property. | -| **`fields`** \* | Array of fields to be stored in this block. | -| **`labels`** | Customize the block labels that appear in the Admin dashboard. Auto-generated from slug if not defined. Alternatively you can use `admin.components.Label` for greater control. | -| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). | -| **`graphQL.singularName`** | Text to use for the GraphQL schema name. Auto-generated from slug if not defined. NOTE: this is set for deprecation, prefer `interfaceName`. | -| **`dbName`** | Custom table name for this block type when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from slug if not defined. | -| **`custom`** | Extension point for adding custom data (e.g. for plugins) | +| Option | Description | +| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **`slug`** \* | Identifier for this block type. Will be saved on each block as the `blockType` property. | +| **`fields`** \* | Array of fields to be stored in this block. | +| **`labels`** | Customize the block labels that appear in the Admin dashboard. Auto-generated from slug if not defined. Alternatively you can use `admin.components.Label` for greater control. | +| **`interfaceName`** | Override the name of the auto-generated top-level [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). Blocks always get an interface — defaults to a PascalCase form of the slug. | +| **`graphQL.singularName`** | Text to use for the GraphQL schema name. Auto-generated from slug if not defined. NOTE: this is set for deprecation, prefer `interfaceName`. | +| **`dbName`** | Custom table name for this block type when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from slug if not defined. | +| **`custom`** | Extension point for adding custom data (e.g. for plugins) | _\* An asterisk denotes that a property is required._ diff --git a/docs/typescript/generating-types.mdx b/docs/typescript/generating-types.mdx index c3eb6bbc491..ded2d9c3e8a 100644 --- a/docs/typescript/generating-types.mdx +++ b/docs/typescript/generating-types.mdx @@ -186,7 +186,9 @@ export interface Post { ## Custom Field Interfaces -For `array`, `block`, `group` and named `tab` fields, you can generate top level reusable interfaces. The following group field config: +`array`, `group` and named `tab` fields generate a top-level interface only when you set `interfaceName` on them. `block` fields always generate a top-level interface — `interfaceName` on a block is an **override** of the auto-derived name (which is a PascalCase form of the slug: `'content-block'` → `ContentBlock`). + +The following group field config: ```ts { diff --git a/packages/payload/src/fields/config/types.ts b/packages/payload/src/fields/config/types.ts index ac12dabf555..5a76d8e9cdd 100644 --- a/packages/payload/src/fields/config/types.ts +++ b/packages/payload/src/fields/config/types.ts @@ -1509,11 +1509,17 @@ export type Block = { * @deprecated Use `admin.images` instead. Preferred aspect ratio of the image is 3:2. */ imageURL?: string - /** Customize generated GraphQL and Typescript schema names. - * The slug is used by default. + /** + * Override the name of the top-level TypeScript interface and GraphQL + * type generated for this block. Blocks **always** generate a top-level + * interface — by default it's a PascalCase form of the slug + * (`'content-block'` → `ContentBlock`). Set this to take control of the + * generated name (useful for disambiguating slug-PascalCase collisions + * or referencing the type elsewhere under a name of your choosing). * - * This is useful if you would like to generate a top level type to share amongst collections/fields. - * **Note**: Top level types can collide, ensure they are unique amongst collections, arrays, groups, blocks, tabs. + * **Note**: Top-level types share a namespace with collections, arrays, + * groups, tabs, and other blocks — set an explicit `interfaceName` to + * resolve any collisions. */ interfaceName?: string jsx?: BlockJSX diff --git a/packages/payload/src/utilities/configToJSONSchema.ts b/packages/payload/src/utilities/configToJSONSchema.ts index 65762311c80..3032000959b 100644 --- a/packages/payload/src/utilities/configToJSONSchema.ts +++ b/packages/payload/src/utilities/configToJSONSchema.ts @@ -11,7 +11,7 @@ import { MissingEditorProp } from '../errors/MissingEditorProp.js' import { fieldAffectsData } from '../fields/config/types.js' import { generateJobsJSONSchemas } from '../queues/config/generateJobsJSONSchemas.js' import { flattenAllFields } from './flattenAllFields.js' -import { formatNames } from './formatLabels.js' +import { formatNames, toWords } from './formatLabels.js' import { getCollectionIDFieldTypes } from './getCollectionIDFieldTypes.js' import { optionsAreEqual } from './optionsAreEqual.js' @@ -460,7 +460,7 @@ export function fieldsToJSONSchema({ if (!forceInlineBlocks) { return { - $ref: `#/definitions/${resolvedBlock.interfaceName ?? resolvedBlock.slug}`, + $ref: `#/definitions/${resolvedBlock.interfaceName ?? toWords(resolvedBlock.slug, true)}`, } } @@ -488,11 +488,15 @@ export function fieldsToJSONSchema({ required: ['blockType', ...blockFieldSchemas.required], } - if (!forceInlineBlocks && block.interfaceName) { - interfaceNameDefinitions.set(block.interfaceName, blockSchema) + if (!forceInlineBlocks) { + // Always register the block as a top-level definition, + // using the user's `interfaceName` override if set or a + // PascalCase fallback derived from the slug. + const interfaceName = block.interfaceName ?? toWords(block.slug, true) + interfaceNameDefinitions.set(interfaceName, blockSchema) return { - $ref: `#/definitions/${block.interfaceName}`, + $ref: `#/definitions/${interfaceName}`, } } @@ -1291,7 +1295,11 @@ export function configToJSONSchema( i18n?: I18n, { forceInlineBlocks }: ConfigToJSONSchemaOptions = {}, ): { jsonSchema: JSONSchema4; typeStringDefinitions: Set } { - // a mutable Map to store custom top-level `interfaceName` types. Fields with an `interfaceName` property will be moved to the top-level definitions here + // a mutable Map of top-level definitions in the generated JSON Schema. + // - `array`/`group`/named-`tab` fields are registered here when they set + // `interfaceName` (otherwise they stay inline). + // - `block` configs always register here, keyed by `block.interfaceName` + // if set, otherwise a PascalCase form of the slug via `toWords`. const interfaceNameDefinitions: Map = new Map() // a mutable Set for raw TS source to be appended to `payload-types.ts`. const typeStringDefinitions: Set = new Set() @@ -1412,7 +1420,9 @@ export function configToJSONSchema( required: ['blockType', ...blockFieldSchemas.required], } - const interfaceName = block.interfaceName ?? block.slug + // `block.interfaceName` is treated as an override of the auto-derived + // PascalCase name. Without it, blocks still get a top-level interface. + const interfaceName = block.interfaceName ?? toWords(block.slug, true) interfaceNameDefinitions.set(interfaceName, blockSchema) blocksDefinition.properties![block.slug] = { From d65e29bd2dd70c30c4dddbfc194c5e236c02c8c0 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 28 May 2026 20:13:44 +0000 Subject: [PATCH 15/56] fix: consistent schemas and internal types --- .../src/features/blockquote/server/schema.ts | 11 +- .../src/features/blocks/server/schema.ts | 73 +- .../experimental_table/server/schema.ts | 41 +- .../src/features/heading/server/schema.ts | 15 +- .../features/horizontalRule/server/schema.ts | 12 +- .../src/features/link/server/schema.ts | 98 +- .../src/features/lists/shared/schema.ts | 25 +- .../features/relationship/server/schema.ts | 18 +- .../src/features/upload/server/schema.ts | 25 +- .../src/types/builtInNodes.ts | 12 +- .../richtext-lexical/src/types/nodeTypes.ts | 192 +- packages/richtext-lexical/src/types/schema.ts | 30 +- test/lexical/payload-types.ts | 2512 ++++++++--------- 13 files changed, 1599 insertions(+), 1465 deletions(-) diff --git a/packages/richtext-lexical/src/features/blockquote/server/schema.ts b/packages/richtext-lexical/src/features/blockquote/server/schema.ts index 123995574f2..be2c914866b 100644 --- a/packages/richtext-lexical/src/features/blockquote/server/schema.ts +++ b/packages/richtext-lexical/src/features/blockquote/server/schema.ts @@ -1,12 +1,15 @@ -import type { SerializedQuoteNode as _SerializedQuoteNode } from '@lexical/rich-text' import type { SerializedLexicalNode } from 'lexical' -import type { StronglyTypedElementNode } from '../../../types/nodeTypes.js' +import type { SerializedLexicalElementBase } from '../../../types/nodeTypes.js' import type { JSONSchemaFn } from '../../typesServer.js' -export type SerializedQuoteNode = - StronglyTypedElementNode<_SerializedQuoteNode, 'quote', TChildren> +export interface SerializedQuoteNode< + TChildren extends SerializedLexicalNode = SerializedLexicalNode, +> extends SerializedLexicalElementBase { + type: 'quote' +} +/** MUST stay byte-for-byte in sync with the runtime `SerializedQuoteNode` declared above. */ const SERIALIZED_QUOTE_NODE_TS = `export interface SerializedQuoteNode extends SerializedLexicalElementBase { type: 'quote'; }` diff --git a/packages/richtext-lexical/src/features/blocks/server/schema.ts b/packages/richtext-lexical/src/features/blocks/server/schema.ts index eca31c13e36..9ddbe4dedf6 100644 --- a/packages/richtext-lexical/src/features/blocks/server/schema.ts +++ b/packages/richtext-lexical/src/features/blocks/server/schema.ts @@ -1,11 +1,9 @@ -import type { SerializedDecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode.js' import type { JSONSchema4 } from 'json-schema' -import type { SerializedLexicalNode } from 'lexical' import type { Block, JsonObject } from 'payload' -import { fieldsToJSONSchema, flattenAllFields } from 'payload' +import { fieldsToJSONSchema, flattenAllFields, toWords } from 'payload' -import type { StronglyTypedLeafNode } from '../../../types/nodeTypes.js' +import type { LexicalElementFormat } from '../../../types/nodeTypes.js' import type { JSONSchemaArgs, JSONSchemaFn } from '../../typesServer.js' import { formatSchema } from '../../../types/jsonSchemaHelpers.js' @@ -28,14 +26,25 @@ export type InlineBlockFields = { id: string } & TFields -export type SerializedBlockNode = { - fields: BlockFields -} & StronglyTypedLeafNode +export type SerializedBlockNode = { + fields: { blockName: null | string; id: string } & Omit + format: LexicalElementFormat + type: 'block' + version: number +} -export type SerializedInlineBlockNode = { - fields: InlineBlockFields -} & StronglyTypedLeafNode +export type SerializedInlineBlockNode< + TFields extends { blockType: string } = { blockType: string }, +> = { + fields: { id: string } & Omit + type: 'inlineBlock' + version: number +} +/** + * MUST stay byte-for-byte in sync with the runtime `SerializedBlockNode` and + * `SerializedInlineBlockNode` declared above. + */ const BLOCK_NODES_TS = `export type SerializedBlockNode = { type: 'block'; format: LexicalElementFormat; @@ -48,13 +57,14 @@ export type SerializedInlineBlockNode = { fields: { id: string } & Omit; };` +/** Block `interfaceName` if set, otherwise a PascalCase form of the slug. */ +const blockFieldsInterfaceName = (block: Block) => block.interfaceName ?? toWords(block.slug, true) + /** - * JSON Schema for the `fields:` payload of one (inline) block. Strips - * Payload's auto-added `id`/`blockName` (every block carries those as base - * fields) and re-adds them with strict runtime types — required, non-null - * `id`; required `blockName: string | null` (omitted for inline blocks). - * - * Blocks with `interfaceName` are emitted as top-level `$ref` definitions. + * JSON Schema for one block's `fields:` payload. Strips Payload's auto-added + * `id`/`blockName` and re-adds them with strict runtime types: required + * non-null `id`, required `blockName: string | null` (omitted for inline + * blocks). Always registers as a top-level `$ref`. */ const buildBlockFieldsSchema = ( block: Block, @@ -101,12 +111,9 @@ const buildBlockFieldsSchema = ( required, } - if (block.interfaceName) { - args.interfaceNameDefinitions.set(block.interfaceName, fieldsSchema) - return { $ref: `#/definitions/${block.interfaceName}` } - } - - return fieldsSchema + const definitionName = blockFieldsInterfaceName(block) + args.interfaceNameDefinitions.set(definitionName, fieldsSchema) + return { $ref: `#/definitions/${definitionName}` } } export const createBlockNodeJSONSchema = @@ -124,16 +131,14 @@ export const createBlockNodeJSONSchema = ? blockFieldsSchemas[0]! : { oneOf: blockFieldsSchemas } - const allHaveInterfaceName = - blockConfigs.length > 0 && blockConfigs.every((b) => Boolean(b.interfaceName)) - const tsType = allHaveInterfaceName - ? `SerializedBlockNode<${blockConfigs.map((b) => b.interfaceName!).join(' | ')}>` - : undefined + const tsType = + blockConfigs.length > 0 + ? `SerializedBlockNode<${blockConfigs.map((b) => blockFieldsInterfaceName(b)).join(' | ')}>` + : `SerializedBlockNode<{ blockType: string }>` return { type: 'object', additionalProperties: false, - ...(tsType ? { tsType } : {}), properties: { type: { type: 'string', const: 'block' }, fields: fieldsSchema, @@ -141,6 +146,7 @@ export const createBlockNodeJSONSchema = version: { type: 'integer' }, }, required: ['fields', 'format', 'type', 'version'], + tsType, } } @@ -159,21 +165,20 @@ export const createInlineBlockNodeJSONSchema = ? blockFieldsSchemas[0]! : { oneOf: blockFieldsSchemas } - const allHaveInterfaceName = - inlineBlockConfigs.length > 0 && inlineBlockConfigs.every((b) => Boolean(b.interfaceName)) - const tsType = allHaveInterfaceName - ? `SerializedInlineBlockNode<${inlineBlockConfigs.map((b) => b.interfaceName!).join(' | ')}>` - : undefined + const tsType = + inlineBlockConfigs.length > 0 + ? `SerializedInlineBlockNode<${inlineBlockConfigs.map((b) => blockFieldsInterfaceName(b)).join(' | ')}>` + : `SerializedInlineBlockNode<{ blockType: string }>` return { type: 'object', additionalProperties: false, - ...(tsType ? { tsType } : {}), properties: { type: { type: 'string', const: 'inlineBlock' }, fields: fieldsSchema, version: { type: 'integer' }, }, required: ['fields', 'type', 'version'], + tsType, } } diff --git a/packages/richtext-lexical/src/features/experimental_table/server/schema.ts b/packages/richtext-lexical/src/features/experimental_table/server/schema.ts index b25dbc3ca6f..2f157bb000d 100644 --- a/packages/richtext-lexical/src/features/experimental_table/server/schema.ts +++ b/packages/richtext-lexical/src/features/experimental_table/server/schema.ts @@ -1,24 +1,41 @@ -import type { - SerializedTableCellNode as _SerializedTableCellNode, - SerializedTableNode as _SerializedTableNode, - SerializedTableRowNode as _SerializedTableRowNode, -} from '@lexical/table' import type { SerializedLexicalNode } from 'lexical' -import type { StronglyTypedElementNode } from '../../../types/nodeTypes.js' +import type { SerializedLexicalElementBase } from '../../../types/nodeTypes.js' import type { JSONSchemaFn } from '../../typesServer.js' -export type SerializedTableCellNode< +export interface SerializedTableCellNode< TChildren extends SerializedLexicalNode = SerializedLexicalNode, -> = StronglyTypedElementNode<_SerializedTableCellNode, 'tablecell', TChildren> +> extends SerializedLexicalElementBase { + backgroundColor?: null | string + colSpan?: number + headerState: number + rowSpan?: number + type: 'tablecell' + verticalAlign?: string + width?: number +} -export type SerializedTableNode = - StronglyTypedElementNode<_SerializedTableNode, 'table', TChildren> +export interface SerializedTableNode< + TChildren extends SerializedLexicalNode = SerializedLexicalNode, +> extends SerializedLexicalElementBase { + colWidths?: number[] + frozenColumnCount?: number + frozenRowCount?: number + rowStriping?: boolean + type: 'table' +} -export type SerializedTableRowNode< +export interface SerializedTableRowNode< TChildren extends SerializedLexicalNode = SerializedLexicalNode, -> = StronglyTypedElementNode<_SerializedTableRowNode, 'tablerow', TChildren> +> extends SerializedLexicalElementBase { + height?: number + type: 'tablerow' +} +/** + * MUST stay byte-for-byte in sync with the runtime `SerializedTableNode`, + * `SerializedTableRowNode`, and `SerializedTableCellNode` declared above. + */ const TABLE_NODES_TS = `export interface SerializedTableNode extends SerializedLexicalElementBase { type: 'table'; colWidths?: number[]; diff --git a/packages/richtext-lexical/src/features/heading/server/schema.ts b/packages/richtext-lexical/src/features/heading/server/schema.ts index 1f9e7f599f8..368536643af 100644 --- a/packages/richtext-lexical/src/features/heading/server/schema.ts +++ b/packages/richtext-lexical/src/features/heading/server/schema.ts @@ -1,20 +1,21 @@ -import type { - SerializedHeadingNode as _SerializedHeadingNode, - HeadingTagType, -} from '@lexical/rich-text' +import type { HeadingTagType } from '@lexical/rich-text' import type { JSONSchema4 } from 'json-schema' import type { SerializedLexicalNode } from 'lexical' -import type { StronglyTypedElementNode } from '../../../types/nodeTypes.js' +import type { SerializedLexicalElementBase } from '../../../types/nodeTypes.js' import type { JSONSchemaFn } from '../../typesServer.js' -export type SerializedHeadingNode< +export interface SerializedHeadingNode< TChildren extends SerializedLexicalNode = SerializedLexicalNode, TTag extends HeadingTagType = HeadingTagType, -> = { tag: TTag } & StronglyTypedElementNode<_SerializedHeadingNode, 'heading', TChildren> +> extends SerializedLexicalElementBase { + tag: TTag + type: 'heading' +} const ALL_HEADING_TAGS: HeadingTagType[] = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] +/** MUST stay byte-for-byte in sync with the runtime `SerializedHeadingNode` declared above. */ const SERIALIZED_HEADING_NODE_TS = `export interface SerializedHeadingNode< TChildren, TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', diff --git a/packages/richtext-lexical/src/features/horizontalRule/server/schema.ts b/packages/richtext-lexical/src/features/horizontalRule/server/schema.ts index 6b5beb162eb..28b67ec132e 100644 --- a/packages/richtext-lexical/src/features/horizontalRule/server/schema.ts +++ b/packages/richtext-lexical/src/features/horizontalRule/server/schema.ts @@ -1,13 +1,11 @@ -import type { SerializedLexicalNode } from 'lexical' - -import type { StronglyTypedLeafNode } from '../../../types/nodeTypes.js' import type { JSONSchemaFn } from '../../typesServer.js' -export type SerializedHorizontalRuleNode = StronglyTypedLeafNode< - SerializedLexicalNode, - 'horizontalrule' -> +export interface SerializedHorizontalRuleNode { + type: 'horizontalrule' + version: number +} +/** MUST stay byte-for-byte in sync with the runtime `SerializedHorizontalRuleNode` declared above. */ const SERIALIZED_HORIZONTAL_RULE_NODE_TS = `export interface SerializedHorizontalRuleNode { type: 'horizontalrule'; version: number; diff --git a/packages/richtext-lexical/src/features/link/server/schema.ts b/packages/richtext-lexical/src/features/link/server/schema.ts index c96701dd3b1..885a94b9824 100644 --- a/packages/richtext-lexical/src/features/link/server/schema.ts +++ b/packages/richtext-lexical/src/features/link/server/schema.ts @@ -1,47 +1,56 @@ import type { JSONSchema4 } from 'json-schema' -import type { SerializedElementNode, SerializedLexicalNode } from 'lexical' -import type { DefaultDocumentIDType, Field, JsonValue } from 'payload' +import type { SerializedLexicalNode } from 'lexical' +import type { DefaultDocumentIDType, Field } from 'payload' import { fieldsToJSONSchema, flattenAllFields } from 'payload' -import type { StronglyTypedElementNode } from '../../../types/nodeTypes.js' +import type { SerializedLexicalElementBase } from '../../../types/nodeTypes.js' import type { JSONSchemaArgs, JSONSchemaFn } from '../../typesServer.js' export type LinkFields = { - [key: string]: JsonValue + /** Custom fields added via `LinkFeature`'s `fields` prop. */ + [k: string]: unknown doc?: { relationTo: string - value: - | { - // Actual doc data, populated in afterRead hook - [key: string]: JsonValue - id: DefaultDocumentIDType - } - | DefaultDocumentIDType + /** Document ID, or the full doc when populated by the afterRead hook. */ + value: { [k: string]: unknown; id: DefaultDocumentIDType } | DefaultDocumentIDType } | null linkType: 'custom' | 'internal' newTab: boolean url?: string } -export type SerializedLinkNode = { - fields: LinkFields +export interface SerializedLinkNode< + TChildren extends SerializedLexicalNode = SerializedLexicalNode, + TFields = LinkFields, +> extends SerializedLexicalElementBase { + fields: TFields /** @todo make required in 4.0 and type AutoLinkNode differently */ id?: string -} & StronglyTypedElementNode + type: 'link' +} -export type SerializedAutoLinkNode< +export interface SerializedAutoLinkNode< TChildren extends SerializedLexicalNode = SerializedLexicalNode, -> = { - fields: LinkFields -} & StronglyTypedElementNode + TFields = LinkFields, +> extends SerializedLexicalElementBase { + fields: TFields + type: 'autolink' +} +/** + * MUST stay byte-for-byte in sync with the runtime `LinkFields`, `SerializedLinkNode`, + * and `SerializedAutoLinkNode` declared above. + */ const LINK_NODES_TS = `export interface LexicalLinkFields { - doc?: { relationTo: string; value: string | number } | null; + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; linkType: 'custom' | 'internal'; newTab: boolean; url?: string; - [k: string]: unknown; } export interface SerializedLinkNode extends SerializedLexicalElementBase { type: 'link'; @@ -88,7 +97,19 @@ const buildLinkFieldsJSONSchema = ( additionalProperties: false, properties: { relationTo: { type: 'string' }, - value: { oneOf: [{ type: 'string' }, { type: 'number' }] }, + value: { + oneOf: [ + { type: 'string' }, + { type: 'number' }, + // Populated form (afterRead inflates `value` into the doc). + { + type: 'object', + additionalProperties: true, + properties: { id: { type: ['string', 'number'] } }, + required: ['id'], + }, + ], + }, }, required: ['relationTo', 'value'], }, @@ -103,19 +124,45 @@ const buildLinkFieldsJSONSchema = ( } } +/** Fields auto-attached by `LinkFeature` (see `transformExtraFields`). */ +const STANDARD_LINK_FIELD_NAMES = new Set(['doc', 'linkType', 'newTab', 'url']) + +/** + * With custom link fields, emit a per-editor `LexicalLinkFields_` + * interface so the link node picks up their real shape. Without any, + * reuse the default `LexicalLinkFields` for cross-alias assignability. + */ +const resolveLinkFieldsRef = ( + sanitizedFieldsWithoutText: Field[], + args: JSONSchemaArgs, +): { fieldsRef: JSONSchema4; fieldsTypeName: string } => { + const fieldsSchema = buildLinkFieldsJSONSchema(sanitizedFieldsWithoutText, args) + const hasUserExtras = sanitizedFieldsWithoutText.some( + (field) => 'name' in field && !STANDARD_LINK_FIELD_NAMES.has(field.name), + ) + if (!hasUserExtras) { + return { fieldsRef: fieldsSchema, fieldsTypeName: 'LexicalLinkFields' } + } + const editorHash = args.nodeUnionName.replace(/^LexicalNodes_/, '') + const fieldsTypeName = `LexicalLinkFields_${editorHash}` + args.interfaceNameDefinitions.set(fieldsTypeName, fieldsSchema) + return { fieldsRef: { $ref: `#/definitions/${fieldsTypeName}` }, fieldsTypeName } +} + export const createLinkNodeJSONSchema = (sanitizedFieldsWithoutText: Field[]): JSONSchemaFn => (args) => { const { elementNodeSchema, nodeUnionName, typeStringDefinitions } = args typeStringDefinitions.add(LINK_NODES_TS) + const { fieldsRef, fieldsTypeName } = resolveLinkFieldsRef(sanitizedFieldsWithoutText, args) return elementNodeSchema({ nodeType: 'link', properties: { id: { type: 'string' }, - fields: buildLinkFieldsJSONSchema(sanitizedFieldsWithoutText, args), + fields: fieldsRef, }, required: ['fields'], - tsType: `SerializedLinkNode<${nodeUnionName}>`, + tsType: `SerializedLinkNode<${nodeUnionName}, ${fieldsTypeName}>`, }) } @@ -124,12 +171,13 @@ export const createAutoLinkNodeJSONSchema = (args) => { const { elementNodeSchema, nodeUnionName, typeStringDefinitions } = args typeStringDefinitions.add(LINK_NODES_TS) + const { fieldsRef, fieldsTypeName } = resolveLinkFieldsRef(sanitizedFieldsWithoutText, args) return elementNodeSchema({ nodeType: 'autolink', properties: { - fields: buildLinkFieldsJSONSchema(sanitizedFieldsWithoutText, args), + fields: fieldsRef, }, required: ['fields'], - tsType: `SerializedAutoLinkNode<${nodeUnionName}>`, + tsType: `SerializedAutoLinkNode<${nodeUnionName}, ${fieldsTypeName}>`, }) } diff --git a/packages/richtext-lexical/src/features/lists/shared/schema.ts b/packages/richtext-lexical/src/features/lists/shared/schema.ts index d7ff0a3c83a..b4da179efaf 100644 --- a/packages/richtext-lexical/src/features/lists/shared/schema.ts +++ b/packages/richtext-lexical/src/features/lists/shared/schema.ts @@ -1,22 +1,26 @@ -import type { - SerializedListItemNode as _SerializedListItemNode, - SerializedListNode as _SerializedListNode, -} from '@lexical/list' import type { SerializedLexicalNode } from 'lexical' -import type { StronglyTypedElementNode } from '../../../types/nodeTypes.js' +import type { SerializedLexicalElementBase } from '../../../types/nodeTypes.js' import type { JSONSchemaFn } from '../../typesServer.js' -export type SerializedListItemNode< +export interface SerializedListItemNode< TChildren extends SerializedLexicalNode = SerializedLexicalNode, -> = { +> extends SerializedLexicalElementBase { checked?: boolean -} & StronglyTypedElementNode<_SerializedListItemNode, 'listitem', TChildren> + type: 'listitem' + value: number +} -export type SerializedListNode = { +export interface SerializedListNode + extends SerializedLexicalElementBase { checked?: boolean -} & StronglyTypedElementNode<_SerializedListNode, 'list', TChildren> + listType: 'bullet' | 'check' | 'number' + start: number + tag: 'ol' | 'ul' + type: 'list' +} +/** MUST stay byte-for-byte in sync with the runtime `SerializedListNode` declared above. */ const SERIALIZED_LIST_NODE_TS = `export interface SerializedListNode extends SerializedLexicalElementBase { type: 'list'; checked?: boolean; @@ -25,6 +29,7 @@ const SERIALIZED_LIST_NODE_TS = `export interface SerializedListNode tag: 'ul' | 'ol'; }` +/** MUST stay byte-for-byte in sync with the runtime `SerializedListItemNode` declared above. */ const SERIALIZED_LIST_ITEM_NODE_TS = `export interface SerializedListItemNode extends SerializedLexicalElementBase { type: 'listitem'; checked?: boolean; diff --git a/packages/richtext-lexical/src/features/relationship/server/schema.ts b/packages/richtext-lexical/src/features/relationship/server/schema.ts index 71635cb641a..2d0b941c12b 100644 --- a/packages/richtext-lexical/src/features/relationship/server/schema.ts +++ b/packages/richtext-lexical/src/features/relationship/server/schema.ts @@ -1,8 +1,7 @@ -import type { SerializedDecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode.js' import type { JSONSchema4 } from 'json-schema' import type { CollectionSlug, DataFromCollectionSlug } from 'payload' -import type { StronglyTypedLeafNode } from '../../../types/nodeTypes.js' +import type { LexicalElementFormat } from '../../../types/nodeTypes.js' import type { JSONSchemaFn } from '../../typesServer.js' import type { RelationshipFeatureProps } from './index.js' @@ -16,9 +15,18 @@ export type RelationshipData = { } }[CollectionSlug] -export type SerializedRelationshipNode = RelationshipData & - StronglyTypedLeafNode +export type SerializedRelationshipNode = { + [TSlug in TSlugs]: { + relationTo: TSlug + value: DataFromCollectionSlug | number | string + } +}[TSlugs] & { + format: LexicalElementFormat + type: 'relationship' + version: number +} +/** MUST stay byte-for-byte in sync with the runtime `SerializedRelationshipNode` declared above. */ const SERIALIZED_RELATIONSHIP_NODE_TS = `export type SerializedRelationshipNode = { type: 'relationship'; format: LexicalElementFormat; @@ -26,7 +34,7 @@ const SERIALIZED_RELATIONSHIP_NODE_TS = `export type SerializedRelationshipNode< } & { [TSlug in TSlugs]: { relationTo: TSlug; - value: Config['collections'][TSlug] | (Config['collections'][TSlug] extends { id: infer TID } ? TID : never); + value: number | string | Config['collections'][TSlug]; }; }[TSlugs];` diff --git a/packages/richtext-lexical/src/features/upload/server/schema.ts b/packages/richtext-lexical/src/features/upload/server/schema.ts index d37b7a32796..0008b4e4593 100644 --- a/packages/richtext-lexical/src/features/upload/server/schema.ts +++ b/packages/richtext-lexical/src/features/upload/server/schema.ts @@ -1,7 +1,5 @@ -import type { SerializedDecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode.js' import type { JSONSchema4 } from 'json-schema' import type { - CollectionSlug, DataFromCollectionSlug, JsonObject, TypedUploadCollection, @@ -10,7 +8,7 @@ import type { import { fieldsToJSONSchema, flattenAllFields } from 'payload' -import type { StronglyTypedLeafNode } from '../../../types/nodeTypes.js' +import type { LexicalElementFormat } from '../../../types/nodeTypes.js' import type { JSONSchemaFn } from '../../typesServer.js' import type { UploadFeatureProps } from './index.js' @@ -18,7 +16,7 @@ import { formatSchema } from '../../../types/jsonSchemaHelpers.js' import { filterEnabledRelationshipCollections } from '../../relationship/shared/filterEnabledRelationshipCollections.js' export type UploadData = { - [TCollectionSlug in CollectionSlug]: { + [TCollectionSlug in UploadCollectionSlug]: { fields: TFields /** ID of this upload node — NOT the linked document's ID. */ id: string @@ -26,7 +24,7 @@ export type UploadData = { /** Either the document ID or the full populated document. */ value: DataFromCollectionSlug | number | string } -}[CollectionSlug] +}[UploadCollectionSlug] /** @internal Adds a pending state to `UploadData`. */ export type Internal_UploadData = { @@ -52,9 +50,20 @@ export type UploadDataImproved = { } }[UploadCollectionSlug] -export type SerializedUploadNode = StronglyTypedLeafNode & - UploadData +export type SerializedUploadNode = { + [TSlug in TSlugs]: { + relationTo: TSlug + value: DataFromCollectionSlug | number | string + } +}[TSlugs] & { + fields: { [k: string]: unknown } + format: LexicalElementFormat + id: string + type: 'upload' + version: number +} +/** MUST stay byte-for-byte in sync with the runtime `SerializedUploadNode` declared above. */ const SERIALIZED_UPLOAD_NODE_TS = `export type SerializedUploadNode = { type: 'upload'; format: LexicalElementFormat; @@ -64,7 +73,7 @@ const SERIALIZED_UPLOAD_NODE_TS = `export type SerializedUploadNode { * schema for that node. */ +/** MUST stay byte-for-byte in sync with `LexicalTextMode` in `types/nodeTypes.ts`. */ const LEXICAL_TEXT_MODE_TS = `export type LexicalTextMode = 'normal' | 'token' | 'segmented';` +/** MUST stay byte-for-byte in sync with `SerializedTextNode` in `types/nodeTypes.ts`. */ const SERIALIZED_TEXT_NODE_TS = `export interface SerializedTextNode { type: 'text'; detail: number; @@ -43,6 +45,7 @@ const SERIALIZED_TEXT_NODE_TS = `export interface SerializedTextNode { version: number; }` +/** MUST stay byte-for-byte in sync with `SerializedTabNode` in `types/nodeTypes.ts`. */ const SERIALIZED_TAB_NODE_TS = `export interface SerializedTabNode { type: 'tab'; detail: number; @@ -53,11 +56,13 @@ const SERIALIZED_TAB_NODE_TS = `export interface SerializedTabNode { version: number; }` +/** MUST stay byte-for-byte in sync with `SerializedLineBreakNode` in `types/nodeTypes.ts`. */ const SERIALIZED_LINE_BREAK_NODE_TS = `export interface SerializedLineBreakNode { type: 'linebreak'; version: number; }` +/** MUST stay byte-for-byte in sync with `SerializedParagraphNode` in `types/nodeTypes.ts`. */ const SERIALIZED_PARAGRAPH_NODE_TS = `export interface SerializedParagraphNode extends SerializedLexicalElementBase { type: 'paragraph'; textFormat: number; @@ -141,6 +146,7 @@ export const paragraphNodeJSONSchema: JSONSchemaFn = ({ }) } +/** MUST stay byte-for-byte in sync with `LexicalRichText` in `types/nodeTypes.ts`. */ const ROOT_NODE_TS = `/** Shape of a Lexical \`richText\` field. */ export interface LexicalRichText { root: { diff --git a/packages/richtext-lexical/src/types/nodeTypes.ts b/packages/richtext-lexical/src/types/nodeTypes.ts index bd8b85538f0..ed7d96cd97d 100644 --- a/packages/richtext-lexical/src/types/nodeTypes.ts +++ b/packages/richtext-lexical/src/types/nodeTypes.ts @@ -1,41 +1,85 @@ -import type { - SerializedLineBreakNode as _SerializedLineBreakNode, - SerializedTabNode as _SerializedTabNode, - SerializedTextNode as _SerializedTextNode, - SerializedEditorState, - SerializedElementNode, - SerializedLexicalNode, -} from 'lexical' +import type { SerializedLexicalNode } from 'lexical' -import type { SerializedQuoteNode } from '../features/blockquote/server/index.js' -import type { SerializedBlockNode } from '../features/blocks/server/nodes/BlocksNode.js' -import type { SerializedInlineBlockNode } from '../features/blocks/server/nodes/InlineBlocksNode.js' +import type { SerializedQuoteNode } from '../features/blockquote/server/schema.js' +import type { + SerializedBlockNode, + SerializedInlineBlockNode, +} from '../features/blocks/server/schema.js' import type { SerializedTableCellNode, SerializedTableNode, SerializedTableRowNode, -} from '../features/experimental_table/server/index.js' -import type { SerializedHeadingNode } from '../features/heading/server/index.js' -import type { SerializedHorizontalRuleNode } from '../features/horizontalRule/server/nodes/HorizontalRuleNode.js' -import type { SerializedAutoLinkNode, SerializedLinkNode } from '../features/link/nodes/types.js' -import type { SerializedListItemNode, SerializedListNode } from '../features/lists/plugin/index.js' -import type { SerializedRelationshipNode } from '../features/relationship/server/nodes/RelationshipNode.js' -import type { SerializedUploadNode } from '../features/upload/server/nodes/UploadNode.js' +} from '../features/experimental_table/server/schema.js' +import type { SerializedHeadingNode } from '../features/heading/server/schema.js' +import type { SerializedHorizontalRuleNode } from '../features/horizontalRule/server/schema.js' +import type { SerializedAutoLinkNode, SerializedLinkNode } from '../features/link/server/schema.js' +import type { SerializedListItemNode, SerializedListNode } from '../features/lists/shared/schema.js' +import type { SerializedRelationshipNode } from '../features/relationship/server/schema.js' +import type { SerializedUploadNode } from '../features/upload/server/schema.js' + +// The declarations below must stay byte-for-byte aligned with the TS source +// strings Payload appends to `payload-types.ts` — twins live in +// `types/builtInNodes.ts` and per-feature `schema.ts`. -/** Strongly-typed serialized element node with `children` and `type` re-declared. */ -export type StronglyTypedElementNode< - TBase, - TType extends string, - TChildren extends SerializedLexicalNode = SerializedLexicalNode, -> = { +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = '' | 'center' | 'end' | 'justify' | 'left' | 'right' | 'start' +export type LexicalElementDirection = ('ltr' | 'rtl') | null + +export interface SerializedLexicalElementBase { children: TChildren[] - type: TType -} & Omit + direction: LexicalElementDirection + format: LexicalElementFormat + indent: number + textFormat?: number + textStyle?: string + version: number +} -/** Strongly-typed serialized leaf node — no `children`, `type` re-declared. */ -export type StronglyTypedLeafNode = { - type: TType -} & Omit +export type LexicalTextMode = 'normal' | 'segmented' | 'token' + +export interface SerializedTextNode { + detail: number + format: number + mode: LexicalTextMode + style: string + text: string + type: 'text' + version: number +} + +export interface SerializedTabNode { + detail: number + format: number + mode: LexicalTextMode + style: string + text: string + type: 'tab' + version: number +} + +export interface SerializedLineBreakNode { + type: 'linebreak' + version: number +} + +export interface SerializedParagraphNode + extends SerializedLexicalElementBase { + textFormat: number + textStyle: string + type: 'paragraph' +} + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[] + direction: LexicalElementDirection + format: LexicalElementFormat + indent: number + type: 'root' + version: number + } +} export type { SerializedAutoLinkNode, @@ -54,70 +98,58 @@ export type { SerializedUploadNode, } -export type SerializedParagraphNode< - TChildren extends SerializedLexicalNode = SerializedLexicalNode, -> = { - textFormat: number -} & StronglyTypedElementNode - -export type SerializedTextNode = StronglyTypedLeafNode<_SerializedTextNode, 'text'> - -export type SerializedTabNode = StronglyTypedLeafNode<_SerializedTabNode, 'tab'> - -export type SerializedLineBreakNode = StronglyTypedLeafNode<_SerializedLineBreakNode, 'linebreak'> - -/** - * Recursively adds typed children to nodes up to `TDepth` levels (default 4). - * Distributive over `TNode`; `TOriginalNode` preserves the full union so - * nested children accept all node types, not just the parent's. - * - * @internal — may change or be removed in a minor release. - */ -export type RecursiveNodes< - TNode extends SerializedLexicalNode, - TDepth extends number = 4, - TOriginalNode extends SerializedLexicalNode = TNode, - // eslint-disable-next-line @typescript-eslint/no-explicit-any -> = TNode extends any - ? TDepth extends 0 - ? TNode - : 'children' extends keyof TNode - ? { children?: RecursiveNodes, TOriginalNode>[] } & TNode - : TNode - : never - -/** 4→3, 3→2, 2→1, 1→0, 0→0 */ -type DecrementDepth = [0, 0, 1, 2, 3, 4][TN] +/** `SerializedEditorState` with nodes narrowed by `type`. No type-casting needed. */ +export type TypedEditorState = + LexicalRichText /** - * `SerializedEditorState` with nodes narrowed by `type`. No type-casting needed. + * All node types included by default in a lexical editor. Self-recursive — + * each element node's `children` is `DefaultNodeTypes` again, no depth limit. + * To compose your own union including the defaults, see {@link DefaultNodeTypesOf}. */ -export type TypedEditorState = { - [k: string]: unknown -} & SerializedEditorState> +export type DefaultNodeTypes = + | SerializedAutoLinkNode + //| SerializedBlockNode // Not included by default + | SerializedHeadingNode + | SerializedHorizontalRuleNode + | SerializedLineBreakNode + | SerializedLinkNode + | SerializedListItemNode + | SerializedListNode + | SerializedParagraphNode + | SerializedQuoteNode + | SerializedRelationshipNode + | SerializedTabNode + | SerializedTextNode + | SerializedUploadNode /** - * All node types included by default in a lexical editor without configuration. + * Default node types, parameterised by the union to use for element children. + * Use to mix custom nodes with the defaults: + * + * ```ts + * type MyNodes = DefaultNodeTypesOf | SerializedBlockNode + * ``` */ -export type DefaultNodeTypes = - | SerializedAutoLinkNode - //| SerializedBlockNode // Not included by default - | SerializedHeadingNode +export type DefaultNodeTypesOf = + | SerializedAutoLinkNode + | SerializedHeadingNode | SerializedHorizontalRuleNode | SerializedLineBreakNode - | SerializedLinkNode - | SerializedListItemNode - | SerializedListNode - | SerializedParagraphNode - | SerializedQuoteNode + | SerializedLinkNode + | SerializedListItemNode + | SerializedListNode + | SerializedParagraphNode + | SerializedQuoteNode | SerializedRelationshipNode | SerializedTabNode | SerializedTextNode | SerializedUploadNode /** - * Like `TypedEditorState` but includes all default node types. - * You can pass *additional* node types as a generic parameter. + * Like `TypedEditorState` but includes all default node types. Pass extra + * node types as a generic to union them at the top level; for nodes that + * should also nest inside default containers, use {@link DefaultNodeTypesOf}. */ export type DefaultTypedEditorState< TAdditionalNodeTypes extends null | SerializedLexicalNode = null, diff --git a/packages/richtext-lexical/src/types/schema.ts b/packages/richtext-lexical/src/types/schema.ts index e6637a3e1cf..c2500b8ee62 100644 --- a/packages/richtext-lexical/src/types/schema.ts +++ b/packages/richtext-lexical/src/types/schema.ts @@ -17,16 +17,13 @@ import { import { elementNodeSchema } from './jsonSchemaHelpers.js' /** - * A placeholder string that will be replaced with the real union name later. - * Union = a union of all possible node types for this richtext field. - * - * We need to replace this *later*, because we're using a hadsh of the schema (like `LexicalNodes_AB12CD34`). - * We cannot calculate the hash until we've built the whole schema, but we can't build the whole schema - * until we have the hash as a name for the union - chicken-and-egg problem. - * - * We need to hash the actual schema to benefit from deduplication of two identical lexical fields. + * The node-union name is a hash of its own schema (so identical editors dedupe). + * Since the schema references the union name, we use a placeholder during build + * and substitute the real hash once everything's assembled. Features can derive + * sibling names (e.g. `LexicalLinkFields_`) using the bare hash placeholder. */ -const NODE_UNION_NAME_PLACEHOLDER = '__LEXICAL_NODE_UNION_NAME__' +const NODE_UNION_HASH_PLACEHOLDER = '__LEXICAL_NODE_UNION_HASH__' +const NODE_UNION_NAME_PLACEHOLDER = `LexicalNodes_${NODE_UNION_HASH_PLACEHOLDER}` export const getFieldToJSONSchema: (args: { editorConfig: SanitizedServerEditorConfig @@ -83,8 +80,21 @@ export const getFieldToJSONSchema: (args: { const hash = createHash('sha256').update(nodeUnionJson).digest('hex').slice(0, 8).toUpperCase() const nodeUnionName = `LexicalNodes_${hash}` + // Replacing the hash resolves the union name and any feature-derived + // sibling names in one pass. const replacePlaceholder = (schemaString: string) => - JSON.parse(schemaString.replaceAll(NODE_UNION_NAME_PLACEHOLDER, nodeUnionName)) as JSONSchema4 + JSON.parse(schemaString.replaceAll(NODE_UNION_HASH_PLACEHOLDER, hash)) as JSONSchema4 + + // Resolve placeholders left in feature-registered definitions so Map keys + // and `$ref` targets line up. + for (const [oldKey, schema] of [...interfaceNameDefinitions.entries()]) { + const newKey = oldKey.replaceAll(NODE_UNION_HASH_PLACEHOLDER, hash) + const resolvedSchema = replacePlaceholder(JSON.stringify(schema)) + if (newKey !== oldKey) { + interfaceNameDefinitions.delete(oldKey) + } + interfaceNameDefinitions.set(newKey, resolvedSchema) + } interfaceNameDefinitions.set(nodeUnionName, replacePlaceholder(nodeUnionJson)) diff --git a/test/lexical/payload-types.ts b/test/lexical/payload-types.ts index 47873b32f0d..de593491155 100644 --- a/test/lexical/payload-types.ts +++ b/test/lexical/payload-types.ts @@ -62,16 +62,16 @@ export type SupportedTimezones = | 'Pacific/Fiji'; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_0BDB72B5". + * via the `definition` "LexicalNodes_698362B2". */ -export type LexicalNodes_0BDB72B5 = +export type LexicalNodes_698362B2 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -107,246 +107,56 @@ export type LexicalNodes_0BDB72B5 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_ED984320". + * via the `definition` "LexicalNodes_D0888BA2". */ -export type LexicalNodes_ED984320 = +export type LexicalNodes_D0888BA2 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | { - type: 'block'; - fields: - | { - id: string; - blockType: 'benchBlock1'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock2'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock3'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock4'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock5'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock6'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock7'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock8'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock9'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock10'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock11'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock12'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock13'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock14'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock15'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock16'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock17'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock18'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock19'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock20'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock21'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock22'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock23'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock24'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock25'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock26'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock27'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock28'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock29'; - title?: string | null; - content?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'benchBlock30'; - title?: string | null; - content?: string | null; - blockName: string | null; - }; - format: LexicalElementFormat; - version: number; - } - | { - type: 'inlineBlock'; - fields: { - [k: string]: unknown; - }; - version: number; - } + | SerializedParagraphNode + | SerializedBlockNode< + | BenchBlock1 + | BenchBlock2 + | BenchBlock3 + | BenchBlock4 + | BenchBlock5 + | BenchBlock6 + | BenchBlock7 + | BenchBlock8 + | BenchBlock9 + | BenchBlock10 + | BenchBlock11 + | BenchBlock12 + | BenchBlock13 + | BenchBlock14 + | BenchBlock15 + | BenchBlock16 + | BenchBlock17 + | BenchBlock18 + | BenchBlock19 + | BenchBlock20 + | BenchBlock21 + | BenchBlock22 + | BenchBlock23 + | BenchBlock24 + | BenchBlock25 + | BenchBlock26 + | BenchBlock27 + | BenchBlock28 + | BenchBlock29 + | BenchBlock30 + > + | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -382,153 +192,28 @@ export type LexicalNodes_ED984320 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_A1CCBEB0". + * via the `definition` "LexicalNodes_75C842AC". */ -export type LexicalNodes_A1CCBEB0 = +export type LexicalNodes_75C842AC = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | { - type: 'block'; - fields: - | { - id: string; - blockType: 'Code'; - language?: - | ( - | 'abap' - | 'apex' - | 'azcli' - | 'bat' - | 'bicep' - | 'cameligo' - | 'clojure' - | 'coffee' - | 'cpp' - | 'csharp' - | 'csp' - | 'css' - | 'cypher' - | 'dart' - | 'dockerfile' - | 'ecl' - | 'elixir' - | 'flow9' - | 'freemarker2' - | 'fsharp' - | 'go' - | 'graphql' - | 'handlebars' - | 'hcl' - | 'html' - | 'ini' - | 'java' - | 'javascript' - | 'julia' - | 'kotlin' - | 'less' - | 'lexon' - | 'liquid' - | 'lua' - | 'm3' - | 'markdown' - | 'mdx' - | 'mips' - | 'msdax' - | 'mysql' - | 'objective-c' - | 'pascal' - | 'pascaligo' - | 'perl' - | 'pgsql' - | 'php' - | 'pla' - | 'plaintext' - | 'postiats' - | 'powerquery' - | 'powershell' - | 'protobuf' - | 'pug' - | 'python' - | 'qsharp' - | 'r' - | 'razor' - | 'redis' - | 'redshift' - | 'restructuredtext' - | 'ruby' - | 'rust' - | 'sb' - | 'scala' - | 'scheme' - | 'scss' - | 'shell' - | 'solidity' - | 'sophia' - | 'sparql' - | 'sql' - | 'st' - | 'swift' - | 'systemverilog' - | 'tcl' - | 'twig' - | 'typescript' - | 'typespec' - | 'vb' - | 'wgsl' - | 'xml' - | 'yaml' - ) - | null; - code?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'PayloadCode'; - language?: ('js' | 'ts' | 'json' | 'plaintext') | null; - code?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'myBlock'; - someText?: string | null; - blockName: string | null; - }; - format: LexicalElementFormat; - version: number; - } - | { - type: 'inlineBlock'; - fields: - | { - id: string; - blockType: 'myInlineBlock'; - someText?: string | null; - } - | InlineBlockWithSelect - | { - id: string; - blockType: 'inlineBlockWithRelationship'; - relationship?: (string | null) | TextField; - }; - version: number; - } - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -564,43 +249,27 @@ export type LexicalNodes_A1CCBEB0 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_B1B9B3BD". + * via the `definition` "LexicalNodes_BF66DC01". */ -export type LexicalNodes_B1B9B3BD = +export type LexicalNodes_BF66DC01 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedAutoLinkNode - | SerializedLinkNode - | { - type: 'block'; - fields: { - id: string; - blockType: 'textBlock'; - blockTitle?: string | null; - blockName: string | null; - }; - format: LexicalElementFormat; - version: number; - } - | { - type: 'inlineBlock'; - fields: { - [k: string]: unknown; - }; - version: number; - } + | SerializedParagraphNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -636,23 +305,23 @@ export type LexicalNodes_B1B9B3BD = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_31F9EDCE". + * via the `definition` "LexicalNodes_EDD2E236". */ -export type LexicalNodes_31F9EDCE = +export type LexicalNodes_EDD2E236 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedParagraphNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -688,33 +357,33 @@ export type LexicalNodes_31F9EDCE = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_54DD9B10". + * via the `definition` "LexicalNodes_4DAB3018". */ -export type LexicalNodes_54DD9B10 = +export type LexicalNodes_4DAB3018 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedListNode - | SerializedListItemNode; + | SerializedParagraphNode + | SerializedListNode + | SerializedListItemNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_CF729D18". + * via the `definition` "LexicalNodes_5B50F90F". */ -export type LexicalNodes_CF729D18 = +export type LexicalNodes_5B50F90F = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedHeadingNode + | SerializedParagraphNode + | SerializedHeadingNode | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -750,46 +419,28 @@ export type LexicalNodes_CF729D18 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_C06ABAD2". + * via the `definition` "LexicalNodes_52F22C78". */ -export type LexicalNodes_C06ABAD2 = +export type LexicalNodes_52F22C78 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | { - type: 'block'; - fields: { - id: string; - blockType: 'myBlock'; - someText?: string | null; - someTextRequired: string; - radios?: ('option1' | 'option2' | 'option3') | null; - blockName: string | null; - }; - format: LexicalElementFormat; - version: number; - } - | { - type: 'inlineBlock'; - fields: { - [k: string]: unknown; - }; - version: number; - } - | SerializedHeadingNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> + | SerializedHeadingNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedListNode - | SerializedListItemNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -827,35 +478,18 @@ export type LexicalNodes_C06ABAD2 = >; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_58B95BE3". + * via the `definition` "LexicalNodes_5065BF69". */ -export type LexicalNodes_58B95BE3 = +export type LexicalNodes_5065BF69 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | { - type: 'block'; - fields: { - id: string; - blockType: 'lexicalAndUploadBlock'; - subRichTextField?: LexicalRichText | null; - subUploadField?: (string | null) | Upload; - blockName: string | null; - }; - format: LexicalElementFormat; - version: number; - } - | { - type: 'inlineBlock'; - fields: { - [k: string]: unknown; - }; - version: number; - } + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -891,11 +525,11 @@ export type LexicalNodes_58B95BE3 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "BlockColumns". @@ -914,326 +548,72 @@ export type BlockColumns = | null; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_8A55385E". + * via the `definition` "LexicalNodes_9E9D615A". */ -export type LexicalNodes_8A55385E = +export type LexicalNodes_9E9D615A = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedHeadingNode - | { - type: 'block'; - fields: - | { - id: string; - blockType: 'richTextBlock'; - richTextField?: LexicalRichText | null; - blockName: string | null; - } - | { - id: string; - blockType: 'textRequired'; - text: string; - blockName: string | null; - } - | { - id: string; - blockType: 'uploadAndRichText'; - upload: string | Upload; - richText?: LexicalRichText | null; - blockName: string | null; - } - | { - id: string; - blockType: 'select'; - select?: ('option1' | 'option2' | 'option3' | 'option4' | 'option5') | null; - blockName: string | null; - } - | { - id: string; - blockType: 'relationshipBlock'; - rel: string | Upload; - blockName: string | null; - } - | { - id: string; - blockType: 'relationshipHasManyBlock'; - rel: ( - | { - relationTo: 'text-fields'; - value: string | TextField; - } - | { - relationTo: 'uploads'; - value: string | Upload; - } - )[]; - blockName: string | null; - } - | { - id: string; - blockType: 'subBlockLexical'; - subBlocksLexical?: - | ( - | { - richText: LexicalRichText; - id?: string | null; - blockName?: string | null; - blockType: 'contentBlock'; - } - | { - content: string; - id?: string | null; - blockName?: string | null; - blockType: 'textArea'; - } - | { - select?: ('option1' | 'option2' | 'option3' | 'option4' | 'option5') | null; - id?: string | null; - blockName?: string | null; - blockType: 'select'; - } - )[] - | null; - blockName: string | null; - } - | LexicalBlocksRadioButtonsBlock - | { - id: string; - blockType: 'conditionalLayout'; - layout: '1' | '2' | '3'; - columns?: BlockColumns; - columns2?: BlockColumns; - columns3?: BlockColumns; - blockName: string | null; - }; - format: LexicalElementFormat; - version: number; - } - | { - type: 'inlineBlock'; - fields: { - [k: string]: unknown; - }; - version: number; - }; + | SerializedParagraphNode + | SerializedHeadingNode + | SerializedBlockNode< + | RichTextBlock + | TextRequired + | UploadAndRichText + | Select + | RelationshipBlock + | RelationshipHasManyBlock + | SubBlockLexical + | LexicalBlocksRadioButtonsBlock + | ConditionalLayout + > + | SerializedInlineBlockNode<{blockType: string}>; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_1AC423EA". + * via the `definition` "LexicalNodes_096444F4". */ -export type LexicalNodes_1AC423EA = +export type LexicalNodes_096444F4 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode - | { - type: 'block'; - fields: - | { - id: string; - blockType: 'validationBlock'; - text?: string | null; - group?: { - groupText?: string | null; - textDependsOnDocData?: string | null; - textDependsOnSiblingData?: string | null; - textDependsOnBlockData?: string | null; - }; - blockName: string | null; - } - | { - id: string; - blockType: 'filterOptionsBlock'; - text?: string | null; - group?: { - groupText?: string | null; - dependsOnDocData?: (string | null) | TextField; - dependsOnSiblingData?: (string | null) | TextField; - dependsOnBlockData?: (string | null) | TextField; - }; - blockName: string | null; - } - | { - id: string; - blockType: 'asyncHooksBlock'; - test1?: string | null; - test2?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'richTextBlock'; - richTextField?: LexicalRichText | null; - blockName: string | null; - } - | { - id: string; - blockType: 'textRequired'; - text: string; - blockName: string | null; - } - | { - id: string; - blockType: 'uploadAndRichText'; - upload: string | Upload; - richText?: LexicalRichText | null; - blockName: string | null; - } - | { - id: string; - blockType: 'select'; - select?: ('option1' | 'option2' | 'option3' | 'option4' | 'option5') | null; - blockName: string | null; - } - | { - id: string; - blockType: 'relationshipBlock'; - rel: string | Upload; - blockName: string | null; - } - | { - id: string; - blockType: 'relationshipHasManyBlock'; - rel: ( - | { - relationTo: 'text-fields'; - value: string | TextField; - } - | { - relationTo: 'uploads'; - value: string | Upload; - } - )[]; - blockName: string | null; - } - | { - id: string; - blockType: 'subBlockLexical'; - subBlocksLexical?: - | ( - | { - richText: LexicalRichText; - id?: string | null; - blockName?: string | null; - blockType: 'contentBlock'; - } - | { - content: string; - id?: string | null; - blockName?: string | null; - blockType: 'textArea'; - } - | { - select?: ('option1' | 'option2' | 'option3' | 'option4' | 'option5') | null; - id?: string | null; - blockName?: string | null; - blockType: 'select'; - } - )[] - | null; - blockName: string | null; - } - | LexicalBlocksRadioButtonsBlock - | { - id: string; - blockType: 'conditionalLayout'; - layout: '1' | '2' | '3'; - columns?: BlockColumns; - columns2?: BlockColumns; - columns3?: BlockColumns; - blockName: string | null; - } - | { - id: string; - blockType: 'tabBlock'; - tab1?: { - text1?: string | null; - }; - tab2?: { - text2?: string | null; - }; - blockName: string | null; - } - | { - id: string; - blockType: 'code'; - code?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'noBlockName'; - text?: string | null; - blockName: string | null; - } - | { - id: string; - blockType: 'myBlock'; - key?: ('value1' | 'value2' | 'value3') | null; - blockName: string | null; - } - | { - id: string; - blockType: 'myBlockWithLabel'; - key?: ('value1' | 'value2' | 'value3') | null; - blockName: string | null; - } - | { - id: string; - blockType: 'myBlockWithBlock'; - key?: ('value1' | 'value2' | 'value3') | null; - blockName: string | null; - } - | { - id: string; - blockType: 'BlockRSC'; - key?: ('value1' | 'value2' | 'value3') | null; - blockName: string | null; - } - | { - id: string; - blockType: 'myBlockWithBlockAndLabel'; - key?: ('value1' | 'value2' | 'value3') | null; - blockName: string | null; - }; - format: LexicalElementFormat; - version: number; - } - | { - type: 'inlineBlock'; - fields: - | AvatarGroupBlock - | { - id: string; - blockType: 'myInlineBlock'; - key?: ('value1' | 'value2' | 'value3') | null; - } - | { - id: string; - blockType: 'myInlineBlockWithLabel'; - key?: ('value1' | 'value2' | 'value3') | null; - } - | { - id: string; - blockType: 'myInlineBlockWithBlock'; - key?: ('value1' | 'value2' | 'value3') | null; - } - | { - id: string; - blockType: 'myInlineBlockWithBlockAndLabel'; - key?: ('value1' | 'value2' | 'value3') | null; - }; - version: number; - } + | SerializedParagraphNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode + | SerializedBlockNode< + | ValidationBlock + | FilterOptionsBlock + | AsyncHooksBlock + | RichTextBlock + | TextRequired + | UploadAndRichText + | Select + | RelationshipBlock + | RelationshipHasManyBlock + | SubBlockLexical + | LexicalBlocksRadioButtonsBlock + | ConditionalLayout + | TabBlock + | Code + | NoBlockName + | MyBlock + | MyBlockWithLabel + | MyBlockWithBlock + | BlockRSC + | MyBlockWithBlockAndLabel + > + | SerializedInlineBlockNode< + | AvatarGroupBlock + | MyInlineBlock + | MyInlineBlockWithLabel + | MyInlineBlockWithBlock + | MyInlineBlockWithBlockAndLabel + > | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1269,29 +649,23 @@ export type LexicalNodes_1AC423EA = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_44B4C4A7". + * via the `definition` "LexicalNodes_1F1774B7". */ -export type LexicalNodes_44B4C4A7 = +export type LexicalNodes_1F1774B7 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode - | { - type: 'inlineBlock'; - fields: { - [k: string]: unknown; - }; - version: number; - } + | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1327,31 +701,25 @@ export type LexicalNodes_44B4C4A7 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_E02E9941". + * via the `definition` "LexicalNodes_50F31288". */ -export type LexicalNodes_E02E9941 = +export type LexicalNodes_50F31288 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode - | { - type: 'inlineBlock'; - fields: { - [k: string]: unknown; - }; - version: number; - } + | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1387,31 +755,25 @@ export type LexicalNodes_E02E9941 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_25DBE01C". + * via the `definition` "LexicalNodes_30BF6BFA". */ -export type LexicalNodes_25DBE01C = +export type LexicalNodes_30BF6BFA = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode - | { - type: 'inlineBlock'; - fields: { - [k: string]: unknown; - }; - version: number; - } + | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1447,31 +809,25 @@ export type LexicalNodes_25DBE01C = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_23E2AA22". + * via the `definition` "LexicalNodes_5DF9547D". */ -export type LexicalNodes_23E2AA22 = +export type LexicalNodes_5DF9547D = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode - | { - type: 'inlineBlock'; - fields: { - [k: string]: unknown; - }; - version: number; - } + | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1507,43 +863,25 @@ export type LexicalNodes_23E2AA22 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_A9FDE2F6". + * via the `definition` "LexicalNodes_0517F0E7". */ -export type LexicalNodes_A9FDE2F6 = +export type LexicalNodes_0517F0E7 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | { - type: 'block'; - fields: { - id: string; - blockType: 'blockLexicalLocalized'; - textLocalized?: string | null; - counter?: number | null; - rel?: (string | null) | LexicalLocalizedField; - blockName: string | null; - }; - format: LexicalElementFormat; - version: number; - } - | { - type: 'inlineBlock'; - fields: { - [k: string]: unknown; - }; - version: number; - } + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1579,42 +917,25 @@ export type LexicalNodes_A9FDE2F6 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_1E9F5E16". + * via the `definition` "LexicalNodes_4A786712". */ -export type LexicalNodes_1E9F5E16 = +export type LexicalNodes_4A786712 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | { - type: 'block'; - fields: { - id: string; - blockType: 'blockLexicalLocalized2'; - textLocalized?: string | null; - rel?: (string | null) | LexicalLocalizedField; - blockName: string | null; - }; - format: LexicalElementFormat; - version: number; - } - | { - type: 'inlineBlock'; - fields: { - [k: string]: unknown; - }; - version: number; - } + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1650,183 +971,81 @@ export type LexicalNodes_1E9F5E16 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_C3F54E23". + * via the `definition` "LexicalNodes_8D432583". */ -export type LexicalNodes_C3F54E23 = +export type LexicalNodes_8D432583 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedUploadNode<'uploads' | 'uploads2'>; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_0E309CFF". + * via the `definition` "LexicalNodes_6E495D8E". */ -export type LexicalNodes_0E309CFF = +export type LexicalNodes_6E495D8E = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | { - type: 'block'; - fields: { - id: string; - blockType: 'blockInLexical'; - /** - * Some Description - */ - lexicalInBlock: LexicalRichText; - blockName: string | null; - }; - format: LexicalElementFormat; - version: number; - } - | { - type: 'inlineBlock'; - fields: { - [k: string]: unknown; - }; - version: number; - }; -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_61405AB6". - */ -export type LexicalNodes_61405AB6 = - | SerializedTextNode - | SerializedTabNode - | SerializedLineBreakNode - | SerializedParagraphNode - | { - type: 'block'; - fields: { - [k: string]: unknown; - }; - format: LexicalElementFormat; - version: number; - } - | { - type: 'inlineBlock'; - fields: { - id: string; - blockType: 'inlineBlockInLexical'; - text?: string | null; - }; - version: number; - }; + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}>; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_047C3A1A". + * via the `definition` "LexicalNodes_463BB3B6". */ -export type LexicalNodes_047C3A1A = +export type LexicalNodes_463BB3B6 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | { - type: 'block'; - fields: { - id: string; - blockType: 'blockWithRichText'; - nestedRichText?: LexicalRichText | null; - blockName: string | null; - }; - format: LexicalElementFormat; - version: number; - } - | { - type: 'inlineBlock'; - fields: { - [k: string]: unknown; - }; - version: number; - }; + | SerializedParagraphNode + | SerializedBlockNode<{blockType: string}> + | SerializedInlineBlockNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_807731E1". + * via the `definition` "LexicalNodes_6339F04B". */ -export type LexicalNodes_807731E1 = +export type LexicalNodes_6339F04B = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedHorizontalRuleNode - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedRelationshipNode< - | 'lexical-benchmark' - | 'lexical-fully-featured' - | 'lexical-autosave' - | 'lexical-link-feature' - | 'lexical-lists-features' - | 'lexical-heading-feature' - | 'lexical-jsx-converter' - | 'lexical-fields' - | 'lexical-views' - | 'lexical-views-frontend' - | 'lexical-views-provider' - | 'lexical-views-provider-default' - | 'lexical-views-provider-fallback' - | 'lexical-views-nested' - | 'lexical-localized-fields' - | 'lexicalObjectReferenceBug' - | 'LexicalInBlock' - | 'lexical-autosave-block' - | 'lexical-access-control' - | 'lexical-relationship-fields' - | 'collision' - | 'lexical-nested-blocks' - | 'rich-text-fields' - | 'text-fields' - | 'array-fields' - | 'OnDemandForm' - | 'OnDemandOutsideForm' - | 'lexical-custom-cell' - | 'payload-kv' - | 'users' - | 'payload-locked-documents' - | 'payload-preferences' - | 'payload-migrations' - > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}>; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_BF713F1F". + * via the `definition` "LexicalNodes_A23F00F3". */ -export type LexicalNodes_BF713F1F = +export type LexicalNodes_A23F00F3 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedUploadNode<'uploads'> | SerializedRelationshipNode<'array-fields'> | SerializedHorizontalRuleNode - | SerializedQuoteNode - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedQuoteNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_476F32D1". + * via the `definition` "LexicalNodes_DD92D6E8". */ -export type LexicalNodes_476F32D1 = +export type LexicalNodes_DD92D6E8 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1864,24 +1083,24 @@ export type LexicalNodes_476F32D1 = > | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedQuoteNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_0C3E1A7F". + * via the `definition` "LexicalNodes_C390D5EC". */ -export type LexicalNodes_0C3E1A7F = +export type LexicalNodes_C390D5EC = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedUploadNode<'uploads2'> | SerializedHorizontalRuleNode - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1917,41 +1136,25 @@ export type LexicalNodes_0C3E1A7F = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_8C92C54E". + * via the `definition` "LexicalNodes_B294A98F". */ -export type LexicalNodes_8C92C54E = +export type LexicalNodes_B294A98F = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | { - type: 'block'; - fields: { - id: string; - blockType: 'blockWithBlockRef'; - nestedBlocks?: NestedBlock[] | null; - blockName: string | null; - }; - format: LexicalElementFormat; - version: number; - } - | { - type: 'inlineBlock'; - fields: { - [k: string]: unknown; - }; - version: number; - } + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1987,63 +1190,27 @@ export type LexicalNodes_8C92C54E = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_D4CB7FDD". + * via the `definition` "LexicalNodes_C0F97F48". */ -export type LexicalNodes_D4CB7FDD = +export type LexicalNodes_C0F97F48 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | { - type: 'block'; - fields: - | { - id: string; - blockType: 'textRequired'; - text: string; - blockName: string | null; - } - | { - id: string; - blockType: 'uploadAndRichText'; - upload: string | Upload; - richText?: LexicalRichText | null; - blockName: string | null; - } - | { - id: string; - blockType: 'select'; - select?: ('option1' | 'option2' | 'option3' | 'option4' | 'option5') | null; - blockName: string | null; - } - | { - id: string; - blockType: 'relationshipBlock'; - rel: string | Upload; - blockName: string | null; - }; - format: LexicalElementFormat; - version: number; - } - | { - type: 'inlineBlock'; - fields: { - [k: string]: unknown; - }; - version: number; - } + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -2079,48 +1246,30 @@ export type LexicalNodes_D4CB7FDD = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_557405F9". + * via the `definition` "LexicalNodes_4CE78AC7". */ -export type LexicalNodes_557405F9 = +export type LexicalNodes_4CE78AC7 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode - | { - type: 'block'; - fields: { - id: string; - blockType: 'myBlock'; - someText?: string | null; - someTextRequired: string; - radios?: ('option1' | 'option2' | 'option3') | null; - blockName: string | null; - }; - format: LexicalElementFormat; - version: number; - } - | { - type: 'inlineBlock'; - fields: { - [k: string]: unknown; - }; - version: number; - } - | SerializedHeadingNode + | SerializedParagraphNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> + | SerializedHeadingNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedListNode - | SerializedListItemNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -2280,7 +1429,7 @@ export interface UserAuthOperations { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "nestedBlock". + * via the `definition` "NestedBlock". */ export interface NestedBlock { text?: string | null; @@ -2290,7 +1439,7 @@ export interface NestedBlock { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "blockWithBlockRef". + * via the `definition` "BlockWithBlockRef". */ export interface BlockWithBlockRef { nestedBlocks?: NestedBlock[] | null; @@ -2304,7 +1453,7 @@ export interface BlockWithBlockRef { */ export interface LexicalBenchmark { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2314,7 +1463,7 @@ export interface LexicalBenchmark { */ export interface LexicalFullyFeatured { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2327,7 +1476,7 @@ export interface LexicalAutosave { title?: string | null; cta?: | { - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; id?: string | null; }[] | null; @@ -2341,7 +1490,7 @@ export interface LexicalAutosave { */ export interface LexicalLinkFeature { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2351,7 +1500,7 @@ export interface LexicalLinkFeature { */ export interface LexicalListsFeature { id: string; - onlyOrderedList?: LexicalRichText | null; + onlyOrderedList?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2361,7 +1510,7 @@ export interface LexicalListsFeature { */ export interface LexicalHeadingFeature { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2371,7 +1520,7 @@ export interface LexicalHeadingFeature { */ export interface LexicalJsxConverter { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2382,15 +1531,15 @@ export interface LexicalJsxConverter { export interface LexicalField { id: string; title: string; - lexicalRootEditor?: LexicalRichText | null; + lexicalRootEditor?: LexicalRichText | null; /** * A simple lexical field */ - lexicalSimple?: LexicalRichText | null; + lexicalSimple?: LexicalRichText | null; /** * Should not be rendered */ - lexicalWithBlocks: LexicalRichText; + lexicalWithBlocks: LexicalRichText; lexicalWithBlocks_markdown?: string | null; updatedAt: string; createdAt: string; @@ -2401,8 +1550,8 @@ export interface LexicalField { */ export interface LexicalView { id: string; - customDefaultView?: LexicalRichText | null; - vanillaView?: LexicalRichText | null; + customDefaultView?: LexicalRichText | null; + vanillaView?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2412,7 +1561,7 @@ export interface LexicalView { */ export interface LexicalViewsFrontend { id: string; - customFrontendViews?: LexicalRichText | null; + customFrontendViews?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2423,7 +1572,7 @@ export interface LexicalViewsFrontend { export interface LexicalViewsProvider { id: string; viewProviderWrapper?: { - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; }; updatedAt: string; createdAt: string; @@ -2435,7 +1584,7 @@ export interface LexicalViewsProvider { export interface LexicalViewsProviderDefault { id: string; defaultViewWrapper?: { - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; }; updatedAt: string; createdAt: string; @@ -2447,7 +1596,7 @@ export interface LexicalViewsProviderDefault { export interface LexicalViewsProviderFallback { id: string; fallbackViewWrapper?: { - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; }; updatedAt: string; createdAt: string; @@ -2458,7 +1607,7 @@ export interface LexicalViewsProviderFallback { */ export interface LexicalViewsNested { id: string; - parentRichText?: LexicalRichText | null; + parentRichText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2472,11 +1621,11 @@ export interface LexicalLocalizedField { /** * Non-localized field with localized block subfields */ - lexicalBlocksSubLocalized?: LexicalRichText | null; + lexicalBlocksSubLocalized?: LexicalRichText | null; /** * Localized field with localized block subfields */ - lexicalBlocksLocalized?: LexicalRichText | null; + lexicalBlocksLocalized?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2486,8 +1635,8 @@ export interface LexicalLocalizedField { */ export interface LexicalObjectReferenceBug { id: string; - lexicalDefault?: LexicalRichText | null; - lexicalEditor?: LexicalRichText | null; + lexicalDefault?: LexicalRichText | null; + lexicalEditor?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2497,25 +1646,28 @@ export interface LexicalObjectReferenceBug { */ export interface LexicalInBlock { id: string; - content?: LexicalRichText | null; - blocks?: - | { - lexical?: LexicalRichText | null; - id?: string | null; - blockName?: string | null; - blockType: 'lexicalInBlock2'; - }[] - | null; + content?: LexicalRichText | null; + blocks?: LexicalInBlock2[] | null; updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalInBlock2". + */ +export interface LexicalInBlock2 { + lexical?: LexicalRichText | null; + id?: string | null; + blockName?: string | null; + blockType: 'lexicalInBlock2'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "lexical-autosave-block". */ export interface LexicalAutosaveBlock { id: string; - content?: LexicalRichText | null; + content?: LexicalRichText | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -2527,7 +1679,7 @@ export interface LexicalAutosaveBlock { export interface LexicalAccessControl { id: string; title?: string | null; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2537,10 +1689,10 @@ export interface LexicalAccessControl { */ export interface LexicalRelationshipField { id: string; - richText?: LexicalRichText | null; - richText2?: LexicalRichText | null; - richText3?: LexicalRichText | null; - richTextLocalized?: LexicalRichText | null; + richText?: LexicalRichText | null; + richText2?: LexicalRichText | null; + richText3?: LexicalRichText | null; + richTextLocalized?: LexicalRichText | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -2551,7 +1703,7 @@ export interface LexicalRelationshipField { */ export interface Collision { id: string; - collision?: LexicalRichText | null; + collision?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2562,7 +1714,7 @@ export interface Collision { export interface LexicalNestedBlock { id: string; title: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2573,27 +1725,30 @@ export interface LexicalNestedBlock { export interface RichTextField { id: string; title: string; - lexicalCustomFields: LexicalRichText; + lexicalCustomFields: LexicalRichText; lexicalCustomFields_html?: string | null; /** * This rich text field uses the lexical editor. */ - lexical?: LexicalRichText | null; + lexical?: LexicalRichText | null; /** * This select field is rendered here to ensure its options dropdown renders above the rich text toolbar. */ selectHasMany?: ('one' | 'two' | 'three' | 'four' | 'five' | 'six')[] | null; - blocks?: - | { - text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'textBlock'; - }[] - | null; + blocks?: TextBlock[] | null; updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TextBlock". + */ +export interface TextBlock { + text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'textBlock'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "text-fields". @@ -2635,17 +1790,20 @@ export interface TextField { id?: string | null; }[] | null; - blocks?: - | { - texts?: string[] | null; - id?: string | null; - blockName?: string | null; - blockType: 'blockWithText'; - }[] - | null; + blocks?: BlockWithText[] | null; updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockWithText". + */ +export interface BlockWithText { + texts?: string[] | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockWithText'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "uploads". @@ -2818,7 +1976,7 @@ export interface OnDemandOutsideForm { | number | boolean | null; - hiddenAnchor?: LexicalRichText | null; + hiddenAnchor?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2829,7 +1987,7 @@ export interface OnDemandOutsideForm { export interface LexicalCustomCell { id: string; title: string; - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -3597,10 +2755,10 @@ export interface PayloadMigrationsSelect { export interface TabsWithRichText { id: string; tab1?: { - rt1?: LexicalRichText | null; + rt1?: LexicalRichText | null; }; tab2?: { - rt2?: LexicalRichText | null; + rt2?: LexicalRichText | null; }; updatedAt?: string | null; createdAt?: string | null; @@ -3636,21 +2794,715 @@ export interface CollectionsWidget { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "InlineBlockWithSelect". + * via the `definition` "BenchBlock1". */ -export interface InlineBlockWithSelect { +export interface BenchBlock1 { id: string; - blockType: 'inlineBlockWithSelect'; - styles?: ('opt1' | 'opt2')[] | null; + blockType: 'benchBlock1'; + title?: string | null; + content?: string | null; + blockName: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalBlocksRadioButtonsBlock". + * via the `definition` "BenchBlock2". */ -export interface LexicalBlocksRadioButtonsBlock { +export interface BenchBlock2 { id: string; - blockType: 'radioButtons'; - radioButtons?: ('option1' | 'option2' | 'option3') | null; + blockType: 'benchBlock2'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock3". + */ +export interface BenchBlock3 { + id: string; + blockType: 'benchBlock3'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock4". + */ +export interface BenchBlock4 { + id: string; + blockType: 'benchBlock4'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock5". + */ +export interface BenchBlock5 { + id: string; + blockType: 'benchBlock5'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock6". + */ +export interface BenchBlock6 { + id: string; + blockType: 'benchBlock6'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock7". + */ +export interface BenchBlock7 { + id: string; + blockType: 'benchBlock7'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock8". + */ +export interface BenchBlock8 { + id: string; + blockType: 'benchBlock8'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock9". + */ +export interface BenchBlock9 { + id: string; + blockType: 'benchBlock9'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock10". + */ +export interface BenchBlock10 { + id: string; + blockType: 'benchBlock10'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock11". + */ +export interface BenchBlock11 { + id: string; + blockType: 'benchBlock11'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock12". + */ +export interface BenchBlock12 { + id: string; + blockType: 'benchBlock12'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock13". + */ +export interface BenchBlock13 { + id: string; + blockType: 'benchBlock13'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock14". + */ +export interface BenchBlock14 { + id: string; + blockType: 'benchBlock14'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock15". + */ +export interface BenchBlock15 { + id: string; + blockType: 'benchBlock15'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock16". + */ +export interface BenchBlock16 { + id: string; + blockType: 'benchBlock16'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock17". + */ +export interface BenchBlock17 { + id: string; + blockType: 'benchBlock17'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock18". + */ +export interface BenchBlock18 { + id: string; + blockType: 'benchBlock18'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock19". + */ +export interface BenchBlock19 { + id: string; + blockType: 'benchBlock19'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock20". + */ +export interface BenchBlock20 { + id: string; + blockType: 'benchBlock20'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock21". + */ +export interface BenchBlock21 { + id: string; + blockType: 'benchBlock21'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock22". + */ +export interface BenchBlock22 { + id: string; + blockType: 'benchBlock22'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock23". + */ +export interface BenchBlock23 { + id: string; + blockType: 'benchBlock23'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock24". + */ +export interface BenchBlock24 { + id: string; + blockType: 'benchBlock24'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock25". + */ +export interface BenchBlock25 { + id: string; + blockType: 'benchBlock25'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock26". + */ +export interface BenchBlock26 { + id: string; + blockType: 'benchBlock26'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock27". + */ +export interface BenchBlock27 { + id: string; + blockType: 'benchBlock27'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock28". + */ +export interface BenchBlock28 { + id: string; + blockType: 'benchBlock28'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock29". + */ +export interface BenchBlock29 { + id: string; + blockType: 'benchBlock29'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BenchBlock30". + */ +export interface BenchBlock30 { + id: string; + blockType: 'benchBlock30'; + title?: string | null; + content?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Code". + */ +export interface Code { + id: string; + blockType: 'code'; + code?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "PayloadCode". + */ +export interface PayloadCode { + id: string; + blockType: 'PayloadCode'; + language?: ('js' | 'ts' | 'json' | 'plaintext') | null; + code?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock". + */ +export interface MyBlock { + id: string; + blockType: 'myBlock'; + someText?: string | null; + someTextRequired: string; + radios?: ('option1' | 'option2' | 'option3') | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyInlineBlock". + */ +export interface MyInlineBlock { + id: string; + blockType: 'myInlineBlock'; + key?: ('value1' | 'value2' | 'value3') | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "InlineBlockWithSelect". + */ +export interface InlineBlockWithSelect { + id: string; + blockType: 'inlineBlockWithSelect'; + styles?: ('opt1' | 'opt2')[] | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "InlineBlockWithRelationship". + */ +export interface InlineBlockWithRelationship { + id: string; + blockType: 'inlineBlockWithRelationship'; + relationship?: (string | null) | TextField; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LinkBlock". + */ +export interface LinkBlock { + relationshipInLink?: (string | null) | TextField; + id?: string | null; + blockName?: string | null; + blockType: 'linkBlock'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_BF66DC01". + */ +export interface LexicalLinkFields_BF66DC01 { + linkBlocks?: LinkBlock[] | null; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_EDD2E236". + */ +export interface LexicalLinkFields_EDD2E236 { + linkType: 'custom' | 'internal'; + url?: string; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + newTab: boolean; + blocks?: Block[] | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Block". + */ +export interface Block { + text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'block'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_52F22C78". + */ +export interface LexicalLinkFields_52F22C78 { + linkType: 'custom' | 'internal'; + url?: string; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + newTab: boolean; + description?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalAndUploadBlock". + */ +export interface LexicalAndUploadBlock { + id: string; + blockType: 'lexicalAndUploadBlock'; + subRichTextField?: LexicalRichText | null; + subUploadField?: (string | null) | Upload; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "RichTextBlock". + */ +export interface RichTextBlock { + id: string; + blockType: 'richTextBlock'; + richTextField?: LexicalRichText | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TextRequired". + */ +export interface TextRequired { + id: string; + blockType: 'textRequired'; + text: string; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "UploadAndRichText". + */ +export interface UploadAndRichText { + id: string; + blockType: 'uploadAndRichText'; + upload: string | Upload; + richText?: LexicalRichText | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Select". + */ +export interface Select { + id: string; + blockType: 'select'; + select?: ('option1' | 'option2' | 'option3' | 'option4' | 'option5') | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "RelationshipBlock". + */ +export interface RelationshipBlock { + id: string; + blockType: 'relationshipBlock'; + rel: string | Upload; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "RelationshipHasManyBlock". + */ +export interface RelationshipHasManyBlock { + id: string; + blockType: 'relationshipHasManyBlock'; + rel: ( + | { + relationTo: 'text-fields'; + value: string | TextField; + } + | { + relationTo: 'uploads'; + value: string | Upload; + } + )[]; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "ContentBlock". + */ +export interface ContentBlock { + id: string; + blockType: 'content-block'; + title: string; + richText?: LexicalRichText | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TextArea". + */ +export interface TextArea { + content: string; + id?: string | null; + blockName?: string | null; + blockType: 'textArea'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "SubBlockLexical". + */ +export interface SubBlockLexical { + id: string; + blockType: 'subBlockLexical'; + subBlocksLexical?: (ContentBlock | TextArea | Select)[] | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalBlocksRadioButtonsBlock". + */ +export interface LexicalBlocksRadioButtonsBlock { + id: string; + blockType: 'radioButtons'; + radioButtons?: ('option1' | 'option2' | 'option3') | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "ConditionalLayout". + */ +export interface ConditionalLayout { + id: string; + blockType: 'conditionalLayout'; + layout: '1' | '2' | '3'; + columns?: BlockColumns; + columns2?: BlockColumns; + columns3?: BlockColumns; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "ValidationBlock". + */ +export interface ValidationBlock { + id: string; + blockType: 'validationBlock'; + text?: string | null; + group?: { + groupText?: string | null; + textDependsOnDocData?: string | null; + textDependsOnSiblingData?: string | null; + textDependsOnBlockData?: string | null; + }; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "FilterOptionsBlock". + */ +export interface FilterOptionsBlock { + id: string; + blockType: 'filterOptionsBlock'; + text?: string | null; + group?: { + groupText?: string | null; + dependsOnDocData?: (string | null) | TextField; + dependsOnSiblingData?: (string | null) | TextField; + dependsOnBlockData?: (string | null) | TextField; + }; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "AsyncHooksBlock". + */ +export interface AsyncHooksBlock { + id: string; + blockType: 'asyncHooksBlock'; + test1?: string | null; + test2?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TabBlock". + */ +export interface TabBlock { + id: string; + blockType: 'tabBlock'; + tab1?: { + text1?: string | null; + }; + tab2?: { + text2?: string | null; + }; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "NoBlockName". + */ +export interface NoBlockName { + id: string; + blockType: 'noBlockName'; + text?: string | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlockWithLabel". + */ +export interface MyBlockWithLabel { + id: string; + blockType: 'myBlockWithLabel'; + key?: ('value1' | 'value2' | 'value3') | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlockWithBlock". + */ +export interface MyBlockWithBlock { + id: string; + blockType: 'myBlockWithBlock'; + key?: ('value1' | 'value2' | 'value3') | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockRSC". + */ +export interface BlockRSC { + id: string; + blockType: 'BlockRSC'; + key?: ('value1' | 'value2' | 'value3') | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlockWithBlockAndLabel". + */ +export interface MyBlockWithBlockAndLabel { + id: string; + blockType: 'myBlockWithBlockAndLabel'; + key?: ('value1' | 'value2' | 'value3') | null; blockName: string | null; } /** @@ -3667,6 +3519,56 @@ export interface AvatarGroupBlock { }[] | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyInlineBlockWithLabel". + */ +export interface MyInlineBlockWithLabel { + id: string; + blockType: 'myInlineBlockWithLabel'; + key?: ('value1' | 'value2' | 'value3') | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyInlineBlockWithBlock". + */ +export interface MyInlineBlockWithBlock { + id: string; + blockType: 'myInlineBlockWithBlock'; + key?: ('value1' | 'value2' | 'value3') | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyInlineBlockWithBlockAndLabel". + */ +export interface MyInlineBlockWithBlockAndLabel { + id: string; + blockType: 'myInlineBlockWithBlockAndLabel'; + key?: ('value1' | 'value2' | 'value3') | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_096444F4". + */ +export interface LexicalLinkFields_096444F4 { + linkType: 'custom' | 'internal'; + url?: string; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + newTab: boolean; + /** + * The rel attribute defines the relationship between a linked resource and the current document. This is a custom link field. + */ + rel?: ('noopener' | 'noreferrer' | 'nofollow')[] | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "ViewsTestBlock". @@ -3686,18 +3588,7 @@ export interface BannerBlock { blockType: 'banner'; type: 'normal' | 'important'; title: string; - content?: LexicalRichText | null; - blockName: string | null; -} -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "ContentBlock". - */ -export interface ContentBlock { - id: string; - blockType: 'content-block'; - title: string; - richText?: LexicalRichText | null; + content?: LexicalRichText | null; blockName: string | null; } /** @@ -3709,7 +3600,7 @@ export interface ProviderBannerBlock { blockType: 'banner'; type: 'normal' | 'important'; title: string; - content?: LexicalRichText | null; + content?: LexicalRichText | null; blockName: string | null; } /** @@ -3720,9 +3611,107 @@ export interface NestedContentBlock { id: string; blockType: 'nested-content'; label: string; - nestedRichText?: LexicalRichText | null; + nestedRichText?: LexicalRichText | null; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockLexicalLocalized". + */ +export interface BlockLexicalLocalized { + id: string; + blockType: 'blockLexicalLocalized'; + textLocalized?: string | null; + counter?: number | null; + rel?: (string | null) | LexicalLocalizedField; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockLexicalLocalized2". + */ +export interface BlockLexicalLocalized2 { + id: string; + blockType: 'blockLexicalLocalized2'; + textLocalized?: string | null; + rel?: (string | null) | LexicalLocalizedField; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockInLexical". + */ +export interface BlockInLexical { + id: string; + blockType: 'blockInLexical'; + /** + * Some Description + */ + lexicalInBlock: LexicalRichText; + blockName: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "InlineBlockInLexical". + */ +export interface InlineBlockInLexical { + id: string; + blockType: 'inlineBlockInLexical'; + text?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockWithRichText". + */ +export interface BlockWithRichText { + id: string; + blockType: 'blockWithRichText'; + nestedRichText?: LexicalRichText | null; blockName: string | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_C0F97F48". + */ +export interface LexicalLinkFields_C0F97F48 { + linkType: 'custom' | 'internal'; + url?: string; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + newTab: boolean; + /** + * The rel attribute defines the relationship between a linked resource and the current document. This is a custom link field. + */ + rel?: ('noopener' | 'noreferrer' | 'nofollow')[] | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_4CE78AC7". + */ +export interface LexicalLinkFields_4CE78AC7 { + linkType: 'custom' | 'internal'; + url?: string; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + newTab: boolean; + description?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". @@ -3792,7 +3781,7 @@ export type SerializedUploadNode = { } & { [TSlug in TSlugs]: { relationTo: TSlug; - value: Config['collections'][TSlug] | (Config['collections'][TSlug] extends { id: infer TID } ? TID : never); + value: number | string | Config['collections'][TSlug]; }; }[TSlugs]; @@ -3807,16 +3796,19 @@ export type SerializedRelationshipNode extends SerializedLexicalElementBase { type: 'link'; From 59b07cfaa215c7427f59b18c18cc9ddbb881c89f Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 28 May 2026 21:07:16 +0000 Subject: [PATCH 16/56] v4 migration docs --- docs/migration-guide/v4.mdx | 145 ++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) diff --git a/docs/migration-guide/v4.mdx b/docs/migration-guide/v4.mdx index 4ea68268c3c..e8aeebeca25 100644 --- a/docs/migration-guide/v4.mdx +++ b/docs/migration-guide/v4.mdx @@ -329,6 +329,151 @@ The deprecated `HTMLConverterFeature`, `lexicalHTML`, and the per-node `converte Custom nodes that define `converters.html` should export their converters instead. +### Field `typescriptSchema` renamed to `jsonSchema` + +`typescriptSchema` accepted JSON Schema, not TypeScript, so the name lied. Renamed to `jsonSchema`. Same shape, same array of transforms. The underlying schema is now also consumed by the MCP plugin for runtime validation, not just type generation. + +```diff + { + name: 'tags', + type: 'json', +- typescriptSchema: [() => ({ type: 'array', items: { type: 'string' } })], ++ jsonSchema: [() => ({ type: 'array', items: { type: 'string' } })], + } +``` + +### RichText adapter `outputSchema` renamed to `jsonSchema` + +Same story on the editor side. The arguments object also gains `typeStringDefinitions: Set` — a sink for raw TS source appended to `payload-types.ts`. + +```diff + myAdapter: RichTextAdapter = { +- outputSchema: ({ collectionIDFieldTypes, config, field, i18n, interfaceNameDefinitions, isRequired }) => { ++ jsonSchema: ({ collectionIDFieldTypes, config, field, i18n, interfaceNameDefinitions, isRequired, typeStringDefinitions }) => { + // return JSONSchema4 + }, + } +``` + +`@payloadcms/richtext-lexical` is updated. Only third-party adapters need attention. + +### `configToJSONSchema` returns `{ jsonSchema, typeStringDefinitions }` + +`configToJSONSchema` (from `payload`) used to return a `JSONSchema4` directly. It now returns an object with the schema plus the TS-source sink. Destructure to pull the schema out. + +```diff +- const schema = configToJSONSchema(sanitizedConfig, 'text') ++ const { jsonSchema: schema, typeStringDefinitions } = configToJSONSchema(sanitizedConfig, 'text') +``` + +If you run your own type generation, append `[...typeStringDefinitions].join('\n\n')` to the compiled output. Otherwise ignore it. + +### `fieldsToJSONSchema` switched to object arguments + +`fieldsToJSONSchema` used to take 6 positional arguments. It now takes one object. The new shape also requires `typeStringDefinitions`, and `forceInlineBlocks` is a top-level sibling instead of nested under `opts`. + +```diff +- fieldsToJSONSchema( +- collectionIDFieldTypes, +- fields, +- interfaceNameDefinitions, +- config, +- i18n, +- { forceInlineBlocks: true }, +- ) ++ fieldsToJSONSchema({ ++ collectionIDFieldTypes, ++ config, ++ fields, ++ forceInlineBlocks: true, ++ i18n, ++ interfaceNameDefinitions, ++ typeStringDefinitions, ++ }) +``` + +### `entityToJSONSchema` gained a required `typeStringDefinitions` argument + +Inserted at position 5 (between `defaultIDType` and `collectionIDFieldTypes`). The old `opts: ConfigToJSONSchemaOptions` is replaced by an optional positional `forceInlineBlocks?: boolean` at the end. + +```diff + entityToJSONSchema( + config, + entity, + interfaceNameDefinitions, + defaultIDType, ++ typeStringDefinitions, + collectionIDFieldTypes, + i18n, +- { forceInlineBlocks: true }, ++ true, + ) +``` + +### Lexical: `modifyOutputSchema` is gone + +`generatedTypes.modifyOutputSchema` on lexical features (and `modifyOutputSchemas`) is removed. Features now contribute per-node JSON Schemas via `createNode({ jsonSchema, node })` instead of mutating a whole-field schema after the fact. The editor composes per-node schemas into the field's union automatically. + +If you wrote a custom feature that overrode `modifyOutputSchema`, move per-node generation into `createNode({ jsonSchema: ... })`: + +```diff + export const MyFeature = createServerFeature({ + feature: () => ({ +- generatedTypes: { +- modifyOutputSchema: ({ currentSchema, interfaceNameDefinitions }) => { +- // ... mutate currentSchema or interfaceNameDefinitions ... +- return currentSchema +- }, +- }, + nodes: [ + createNode({ + node: MyNode, ++ jsonSchema: ({ elementNodeSchema, nodeUnionName, typeStringDefinitions }) => { ++ typeStringDefinitions.add(`export interface SerializedMyNode { type: 'my'; /* ... */ }`) ++ return elementNodeSchema({ ++ nodeType: 'my', ++ tsType: `SerializedMyNode<${nodeUnionName}>`, ++ }) ++ }, + }), + ], + }), + }) +``` + +Nodes without a `jsonSchema` function fall back to `{ [k: string]: unknown }`, so omitting it is safe — just looser. + +### Lexical: duplicate node registration throws + +`sanitizeServerFeatures` now rejects features that register a node type already present in the editor (matched on `getType()`, or on the replacement target for `LexicalNodeReplacement`). The old behaviour silently let the last write win. + +The built-in lists features coordinate registration through `shouldRegisterListBaseNodes`, so the default editor is unaffected. Custom features that re-registered an existing node to swap in a subclass should use lexical's `LexicalNodeReplacement` shape: + +```diff + createNode({ +- node: MyExtendedHeadingNode, ++ node: { replace: HeadingNode, with: (node) => new MyExtendedHeadingNode(node.__tag) }, + }) +``` + +### Every block now auto-generates a top-level TypeScript interface + +Before, a block's fields only became a top-level interface in `payload-types.ts` if you set `interfaceName` on the block. Without it, the fields were inlined wherever the block appeared in your types. + +Now **every block always emits a top-level interface**. The name comes from the slug, converted to PascalCase (`'content-block'` → `ContentBlock`, `'richTextBlock'` → `RichTextBlock`). `interfaceName` still works, but it's now an _override_ for that default name rather than the switch that enables generation. + +The same rule applies to lexical block nodes — they now emit as `SerializedBlockNode<…>` / `SerializedInlineBlockNode<…>` referencing the per-block interface, instead of inlining a `{ [k: string]: unknown }` shape. + +If a block's auto-derived name collides with another type in your generated file (a collection, an array's `interfaceName`, etc.), set `interfaceName` on the block to disambiguate. + +### Lexical: generated `payload-types.ts` shape changed + +`richText` fields backed by `lexicalEditor` used to emit a permissive `{ [k: string]: unknown }` per field. They now emit a discriminated union of strict per-node interfaces (`SerializedTextNode`, `SerializedParagraphNode`, `SerializedHeadingNode`, `SerializedBlockNode`, etc.) under a hash-named alias like `LexicalNodes_AB12CD34`. + +Block nodes always come through as `SerializedBlockNode` / `SerializedInlineBlockNode` referencing the per-block interface (see the `block.interfaceName` change above). Their auto-added `id`/`blockName` tighten from `id?: string | null` / `blockName?: string | null` to `id: string` / `blockName: string | null` to match what's actually stored. + +Code that imported field types from `payload-types.ts` and cast through `unknown` may now type-check tighter and surface real bugs. + ### Jobs: `jobs.depth` and `jobs.runHooks` have been removed ([#16414](https://github.com/payloadcms/payload/pull/16414)) The deprecated `jobs.depth` and `jobs.runHooks` config options have been removed. Job operations now always use direct database calls with depth `0`. From 30dfd9d3deeb20dbd4ab9552b1a629a59eae6da8 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 28 May 2026 21:21:56 +0000 Subject: [PATCH 17/56] type tests --- test/types/payload-types.ts | 221 +++++++++++++++++++++++++++++++++--- test/types/types.spec.ts | 180 +++++++++++++++++++++++++---- 2 files changed, 366 insertions(+), 35 deletions(-) diff --git a/test/types/payload-types.ts b/test/types/payload-types.ts index 01b340a3bed..3024b7de65c 100644 --- a/test/types/payload-types.ts +++ b/test/types/payload-types.ts @@ -73,6 +73,34 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_A21938DB". + */ +export type LexicalNodes_A21938DB = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedHorizontalRuleNode + | SerializedUploadNode<'media'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'posts' + | 'pages' + | 'pages-categories' + | 'draft-posts' + | 'payload-kv' + | 'users' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; export interface Config { auth: { @@ -84,6 +112,7 @@ export interface Config { pages: Page; 'pages-categories': PagesCategory; 'draft-posts': DraftPost; + media: Media; 'payload-kv': PayloadKv; users: User; 'payload-locked-documents': PayloadLockedDocument; @@ -100,6 +129,7 @@ export interface Config { pages: PagesSelect | PagesSelect; 'pages-categories': PagesCategoriesSelect | PagesCategoriesSelect; 'draft-posts': DraftPostsSelect | DraftPostsSelect; + media: MediaSelect | MediaSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; @@ -154,21 +184,7 @@ export interface UserAuthOperations { export interface Post { id: string; text?: string | null; - richText: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - }; + richText: LexicalRichText; title?: string | null; selectField: MySelectOptions; insideUnnamedGroup?: string | null; @@ -222,6 +238,25 @@ export interface DraftPost { createdAt: string; _status?: ('draft' | 'published') | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "media". + */ +export interface Media { + id: string; + alt?: string | null; + updatedAt: string; + createdAt: string; + url?: string | null; + thumbnailURL?: string | null; + filename?: string | null; + mimeType?: string | null; + filesize?: number | null; + width?: number | null; + height?: number | null; + focalX?: number | null; + focalY?: number | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -287,6 +322,10 @@ export interface PayloadLockedDocument { relationTo: 'draft-posts'; value: string | DraftPost; } | null) + | ({ + relationTo: 'media'; + value: string | Media; + } | null) | ({ relationTo: 'users'; value: string | User; @@ -384,6 +423,24 @@ export interface DraftPostsSelect { createdAt?: T; _status?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "media_select". + */ +export interface MediaSelect { + alt?: T; + updatedAt?: T; + createdAt?: T; + url?: T; + thumbnailURL?: T; + filename?: T; + mimeType?: T; + filesize?: T; + width?: T; + height?: T; + focalX?: T; + focalY?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -506,6 +563,140 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export interface SerializedHorizontalRuleNode { + type: 'horizontalrule'; + version: number; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: { [k: string]: unknown }; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + declare module 'payload' { // @ts-ignore diff --git a/test/types/types.spec.ts b/test/types/types.spec.ts index e0ed8fa1100..5ea18c78293 100644 --- a/test/types/types.spec.ts +++ b/test/types/types.spec.ts @@ -19,10 +19,20 @@ import { buildEditorState, type DefaultNodeTypes, type DefaultTypedEditorState, - type RecursiveNodes, + type SerializedAutoLinkNode, type SerializedBlockNode, type SerializedHeadingNode, + type SerializedHorizontalRuleNode, + type SerializedLineBreakNode, + type SerializedLinkNode, + type SerializedListItemNode, + type SerializedListNode, + type SerializedParagraphNode, + type SerializedQuoteNode, + type SerializedRelationshipNode, + type SerializedTabNode, type SerializedTextNode, + type SerializedUploadNode, type TypedEditorState, } from '@payloadcms/richtext-lexical' import { PayloadSDK } from '@payloadcms/sdk' @@ -30,6 +40,20 @@ import payload from 'payload' import { describe, expect, test } from 'tstyche' import type { + SerializedAutoLinkNode as GenAutoLink, + SerializedHeadingNode as GenHeading, + SerializedHorizontalRuleNode as GenHR, + SerializedLineBreakNode as GenLB, + SerializedListItemNode as GenLI, + SerializedLinkNode as GenLink, + SerializedListNode as GenList, + LexicalNodes_A21938DB as GenNodeUnion, + SerializedParagraphNode as GenParagraph, + SerializedQuoteNode as GenQuote, + SerializedRelationshipNode as GenRelationship, + SerializedTabNode as GenTab, + SerializedTextNode as GenText, + SerializedUploadNode as GenUpload, Config as LocalConfig, Menu, MyRadioOptions, @@ -458,7 +482,7 @@ describe('Types testing', () => { }) test('ensure linebreak nodes cannot have children even when nested', () => { - // This test verifies that RecursiveNodes doesn't add children to leaf nodes + // This test verifies that the self-recursive `DefaultNodeTypes` union doesn't add children to leaf nodes type RootChildren = DefaultTypedEditorState['root']['children'][number] // At top level @@ -508,7 +532,7 @@ describe('Types testing', () => { }) test('accepts complete heading node as part of DefaultNodeTypes if heading node is explicitly typed', () => { - const headingNode: SerializedHeadingNode> = { + const headingNode: SerializedHeadingNode = { type: 'heading', children: [ { @@ -543,7 +567,7 @@ describe('Types testing', () => { }) test('accepts complete heading node as part of nested children within DefaultNodeTypes if heading node is explicitly typed', () => { - const headingNode: SerializedHeadingNode> = { + const headingNode: SerializedHeadingNode = { type: 'heading', children: [ { @@ -574,6 +598,7 @@ describe('Types testing', () => { format: 'left', indent: 0, textFormat: 0, + textStyle: '', version: 0, }, ], @@ -622,6 +647,7 @@ describe('Types testing', () => { format: 'left', indent: 0, textFormat: 0, + textStyle: '', version: 0, }, { @@ -646,6 +672,7 @@ describe('Types testing', () => { format: 'left', indent: 0, textFormat: 0, + textStyle: '', version: 0, }, ], @@ -938,6 +965,107 @@ describe('Types testing', () => { expect(result).type.toBe>() }) }) + + describe('generated <-> runtime per-node compatibility', () => { + // Per-node assertions pinpoint which node differs when the whole-tree + // assertions above fail. + + test('SerializedTextNode: generated <-> runtime', () => { + expect().type.toBeAssignableWith() + expect().type.toBeAssignableWith() + }) + + test('SerializedTabNode: generated <-> runtime', () => { + expect().type.toBeAssignableWith() + expect().type.toBeAssignableWith() + }) + + test('SerializedLineBreakNode: generated <-> runtime', () => { + expect().type.toBeAssignableWith() + expect().type.toBeAssignableWith() + }) + + test('SerializedHorizontalRuleNode: generated <-> runtime', () => { + expect().type.toBeAssignableWith() + expect().type.toBeAssignableWith() + }) + + test('SerializedParagraphNode: generated <-> runtime', () => { + expect>().type.toBeAssignableWith< + SerializedParagraphNode + >() + expect>().type.toBeAssignableWith< + GenParagraph + >() + }) + + test('SerializedHeadingNode: generated <-> runtime', () => { + expect>().type.toBeAssignableWith< + SerializedHeadingNode + >() + expect>().type.toBeAssignableWith< + GenHeading + >() + }) + + test('SerializedQuoteNode: generated <-> runtime', () => { + expect>().type.toBeAssignableWith< + SerializedQuoteNode + >() + expect>().type.toBeAssignableWith< + GenQuote + >() + }) + + test('SerializedListNode: generated <-> runtime', () => { + expect>().type.toBeAssignableWith>() + expect>().type.toBeAssignableWith>() + }) + + test('SerializedListItemNode: generated <-> runtime', () => { + expect>().type.toBeAssignableWith< + SerializedListItemNode + >() + expect>().type.toBeAssignableWith< + GenLI + >() + }) + + test('SerializedLinkNode: generated <-> runtime', () => { + expect>().type.toBeAssignableWith>() + expect>().type.toBeAssignableWith>() + }) + + test('SerializedAutoLinkNode: generated <-> runtime', () => { + expect>().type.toBeAssignableWith< + SerializedAutoLinkNode + >() + expect>().type.toBeAssignableWith< + GenAutoLink + >() + }) + + test('SerializedRelationshipNode: generated <-> runtime', () => { + type Slugs = keyof LocalConfig['collections'] + expect>().type.toBeAssignableWith() + expect().type.toBeAssignableWith>() + }) + + test('SerializedUploadNode: generated <-> runtime', () => { + // No upload collections in this config — the generated node falls back + // to `{ type: 'upload', version: number, [k]: unknown }`. + type GenUploadInUnion = Extract + expect().type.toBeAssignableWith() + expect().type.toBeAssignableWith() + }) + + test('LexicalRichText.root: generated <-> runtime', () => { + type Gen = Post['richText']['root'] + type Run = DefaultTypedEditorState['root'] + expect().type.toBeAssignableWith() + expect().type.toBeAssignableWith() + }) + }) }) describe('sdk', () => { @@ -949,6 +1077,7 @@ describe('Types testing', () => { const _sdk = new PayloadSDK({ baseURL: '' }) expect[0]['collection']>().type.toBe< | 'draft-posts' + | 'media' | 'pages' | 'pages-categories' | 'payload-kv' @@ -965,6 +1094,7 @@ describe('Types testing', () => { // ensure collection property of sdk.create has posts in the union type expect[0]['collection']>().type.toBe< | 'draft-posts' + | 'media' | 'pages' | 'pages-categories' | 'payload-kv' @@ -983,7 +1113,14 @@ describe('Types testing', () => { data: { radioField: 'option-1', richText: { - root: { type: '', children: [], direction: null, format: '', indent: 0, version: 0 }, + root: { + type: 'root', + children: [], + direction: null, + format: '', + indent: 0, + version: 0, + }, }, selectField: 'option-1', title: 'Test Post', @@ -1001,7 +1138,14 @@ describe('Types testing', () => { invalidProperty: 'should error', radioField: 'option-1', richText: { - root: { type: '', children: [], direction: null, format: '', indent: 0, version: 0 }, + root: { + type: 'root', + children: [], + direction: null, + format: '', + indent: 0, + version: 0, + }, }, selectField: 'option-1', title: 'Test Post', @@ -1266,20 +1410,21 @@ describe('Types testing', () => { test('update with draft:true on draft-enabled collection should work', () => { expect( - payload.update({ collection: 'draft-posts', id: 1, data: { title: 'Test' }, draft: true }), + payload.update({ + collection: 'draft-posts', + id: 1, + data: { title: 'Test' }, + draft: true, + }), ).type.not.toRaiseError() }) test('duplicate with draft:true on non-draft collection should error', () => { - expect( - payload.duplicate({ collection: 'pages', id: 1, draft: true }), - ).type.toRaiseError() + expect(payload.duplicate({ collection: 'pages', id: 1, draft: true })).type.toRaiseError() }) test('duplicate with draft:false on non-draft collection should error', () => { - expect( - payload.duplicate({ collection: 'pages', id: 1, draft: false }), - ).type.toRaiseError() + expect(payload.duplicate({ collection: 'pages', id: 1, draft: false })).type.toRaiseError() }) test('duplicate with draft:true on draft-enabled collection should work', () => { @@ -1301,15 +1446,11 @@ describe('Types testing', () => { }) test('global update with draft:true on non-draft global should error', () => { - expect( - payload.updateGlobal({ slug: 'menu', data: {}, draft: true }), - ).type.toRaiseError() + expect(payload.updateGlobal({ slug: 'menu', data: {}, draft: true })).type.toRaiseError() }) test('global update with draft:false on non-draft global should error', () => { - expect( - payload.updateGlobal({ slug: 'menu', data: {}, draft: false }), - ).type.toRaiseError() + expect(payload.updateGlobal({ slug: 'menu', data: {}, draft: false })).type.toRaiseError() }) test('global update with draft:true on draft-enabled global should work', () => { @@ -1318,6 +1459,5 @@ describe('Types testing', () => { ).type.not.toRaiseError() }) }) - }) }) From f5120c1351c2ee6d10493d4077d39e7764dff6ee Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Fri, 29 May 2026 07:02:38 +0000 Subject: [PATCH 18/56] fix imports --- packages/richtext-lexical/src/features/link/client/index.tsx | 2 +- .../src/features/link/client/plugins/autoLink/index.tsx | 2 +- .../client/plugins/floatingLinkEditor/LinkEditor/index.tsx | 2 +- .../features/link/client/plugins/floatingLinkEditor/types.ts | 2 +- .../src/features/link/client/plugins/link/index.tsx | 2 +- .../src/features/link/markdownTransformer.spec.ts | 2 +- .../src/features/link/markdownTransformer.ts | 2 +- .../richtext-lexical/src/features/link/nodes/AutoLinkNode.ts | 2 +- .../richtext-lexical/src/features/link/nodes/LinkNode.ts | 2 +- .../richtext-lexical/src/features/link/server/baseFields.ts | 2 +- .../src/features/link/server/graphQLPopulationPromise.ts | 2 +- .../richtext-lexical/src/features/link/server/validate.ts | 2 +- .../features/relationship/client/nodes/RelationshipNode.tsx | 5 +---- packages/richtext-lexical/src/types/index.ts | 2 +- 14 files changed, 14 insertions(+), 17 deletions(-) diff --git a/packages/richtext-lexical/src/features/link/client/index.tsx b/packages/richtext-lexical/src/features/link/client/index.tsx index 2200c2d20b1..a3d56e51ea7 100644 --- a/packages/richtext-lexical/src/features/link/client/index.tsx +++ b/packages/richtext-lexical/src/features/link/client/index.tsx @@ -7,8 +7,8 @@ import { $getSelection, $isRangeSelection } from 'lexical' import type { ToolbarGroup } from '../../toolbars/types.js' import type { ClientFeature } from '../../typesClient.js' -import type { LinkFields } from '../nodes/types.js' import type { ExclusiveLinkCollectionsProps } from '../server/index.js' +import type { LinkFields } from '../server/schema.js' import { LinkIcon } from '../../../lexical/ui/icons/Link/index.js' import { getSelectedNode } from '../../../lexical/utils/getSelectedNode.js' diff --git a/packages/richtext-lexical/src/features/link/client/plugins/autoLink/index.tsx b/packages/richtext-lexical/src/features/link/client/plugins/autoLink/index.tsx index a5707f715ac..ae5d52eccb1 100644 --- a/packages/richtext-lexical/src/features/link/client/plugins/autoLink/index.tsx +++ b/packages/richtext-lexical/src/features/link/client/plugins/autoLink/index.tsx @@ -16,7 +16,7 @@ import { import { useEffect } from 'react' import type { PluginComponent } from '../../../../typesClient.js' -import type { LinkFields } from '../../../nodes/types.js' +import type { LinkFields } from '../../../server/schema.js' import type { ClientProps } from '../../index.js' import { $createAutoLinkNode, $isAutoLinkNode, AutoLinkNode } from '../../../nodes/AutoLinkNode.js' diff --git a/packages/richtext-lexical/src/features/link/client/plugins/floatingLinkEditor/LinkEditor/index.tsx b/packages/richtext-lexical/src/features/link/client/plugins/floatingLinkEditor/LinkEditor/index.tsx index 6de99d08c38..7d5da578675 100644 --- a/packages/richtext-lexical/src/features/link/client/plugins/floatingLinkEditor/LinkEditor/index.tsx +++ b/packages/richtext-lexical/src/features/link/client/plugins/floatingLinkEditor/LinkEditor/index.tsx @@ -30,7 +30,7 @@ import { formatAdminURL } from 'payload/shared' import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react' import type { LinkNode } from '../../../../nodes/LinkNode.js' -import type { LinkFields } from '../../../../nodes/types.js' +import type { LinkFields } from '../../../../server/schema.js' import type { LinkPayload } from '../types.js' import { useEditorConfigContext } from '../../../../../../lexical/config/client/EditorConfigProvider.js' diff --git a/packages/richtext-lexical/src/features/link/client/plugins/floatingLinkEditor/types.ts b/packages/richtext-lexical/src/features/link/client/plugins/floatingLinkEditor/types.ts index 3eed9d04020..c1648a30925 100644 --- a/packages/richtext-lexical/src/features/link/client/plugins/floatingLinkEditor/types.ts +++ b/packages/richtext-lexical/src/features/link/client/plugins/floatingLinkEditor/types.ts @@ -1,6 +1,6 @@ import type { LexicalNode } from 'lexical' -import type { LinkFields } from '../../../nodes/types.js' +import type { LinkFields } from '../../../server/schema.js' /** * The payload of a link node diff --git a/packages/richtext-lexical/src/features/link/client/plugins/link/index.tsx b/packages/richtext-lexical/src/features/link/client/plugins/link/index.tsx index da4a144d6cf..86ec0219b58 100644 --- a/packages/richtext-lexical/src/features/link/client/plugins/link/index.tsx +++ b/packages/richtext-lexical/src/features/link/client/plugins/link/index.tsx @@ -11,7 +11,7 @@ import { import { useEffect } from 'react' import type { PluginComponent } from '../../../../typesClient.js' -import type { LinkFields } from '../../../nodes/types.js' +import type { LinkFields } from '../../../server/schema.js' import type { ClientProps } from '../../index.js' import type { LinkPayload } from '../floatingLinkEditor/types.js' diff --git a/packages/richtext-lexical/src/features/link/markdownTransformer.spec.ts b/packages/richtext-lexical/src/features/link/markdownTransformer.spec.ts index eb467936b46..6f0b5cb56f5 100644 --- a/packages/richtext-lexical/src/features/link/markdownTransformer.spec.ts +++ b/packages/richtext-lexical/src/features/link/markdownTransformer.spec.ts @@ -5,7 +5,7 @@ import { describe, expect, it } from 'vitest' import { $convertToMarkdownString } from '../../packages/@lexical/markdown/index.js' import { AutoLinkNode } from './nodes/AutoLinkNode.js' import { $createLinkNode, LinkNode } from './nodes/LinkNode.js' -import type { SerializedLinkNode } from './nodes/types.js' +import type { SerializedLinkNode } from './server/schema.js' import { LinkMarkdownTransformer, createLinkMarkdownTransformer } from './markdownTransformer.js' function createEditor() { diff --git a/packages/richtext-lexical/src/features/link/markdownTransformer.ts b/packages/richtext-lexical/src/features/link/markdownTransformer.ts index 6527536dd9d..1f7d50b513e 100644 --- a/packages/richtext-lexical/src/features/link/markdownTransformer.ts +++ b/packages/richtext-lexical/src/features/link/markdownTransformer.ts @@ -9,7 +9,7 @@ import { $createTextNode, $isTextNode } from 'lexical' import type { TextMatchTransformer } from '../../packages/@lexical/markdown/MarkdownTransformers.js' -import type { SerializedLinkNode } from './nodes/types.js' +import type { SerializedLinkNode } from './server/schema.js' import { sanitizeUrl } from '../../lexical/utils/url.js' import { $createLinkNode, $isLinkNode, LinkNode } from './nodes/LinkNode.js' diff --git a/packages/richtext-lexical/src/features/link/nodes/AutoLinkNode.ts b/packages/richtext-lexical/src/features/link/nodes/AutoLinkNode.ts index 05fc40ce287..194dd9e9d11 100644 --- a/packages/richtext-lexical/src/features/link/nodes/AutoLinkNode.ts +++ b/packages/richtext-lexical/src/features/link/nodes/AutoLinkNode.ts @@ -2,7 +2,7 @@ import type { ElementNode, LexicalNode, LexicalUpdateJSON, RangeSelection } from import { $applyNodeReplacement, $isElementNode } from 'lexical' -import type { LinkFields, SerializedAutoLinkNode } from './types.js' +import type { LinkFields, SerializedAutoLinkNode } from '../server/schema.js' import { LinkNode } from './LinkNode.js' diff --git a/packages/richtext-lexical/src/features/link/nodes/LinkNode.ts b/packages/richtext-lexical/src/features/link/nodes/LinkNode.ts index 80cca82a486..7f3e2962bac 100644 --- a/packages/richtext-lexical/src/features/link/nodes/LinkNode.ts +++ b/packages/richtext-lexical/src/features/link/nodes/LinkNode.ts @@ -24,7 +24,7 @@ import { } from 'lexical' import type { LinkPayload } from '../client/plugins/floatingLinkEditor/types.js' -import type { LinkFields, SerializedLinkNode } from './types.js' +import type { LinkFields, SerializedLinkNode } from '../server/schema.js' const SUPPORTED_URL_PROTOCOLS = new Set(['http:', 'https:', 'mailto:', 'sms:', 'tel:']) diff --git a/packages/richtext-lexical/src/features/link/server/baseFields.ts b/packages/richtext-lexical/src/features/link/server/baseFields.ts index 8ce0ec596ae..0a78199b4de 100644 --- a/packages/richtext-lexical/src/features/link/server/baseFields.ts +++ b/packages/richtext-lexical/src/features/link/server/baseFields.ts @@ -8,7 +8,7 @@ import type { TypedUser, } from 'payload' -import type { LinkFields } from '../nodes/types.js' +import type { LinkFields } from './schema.js' import { validateUrl, validateUrlMinimal } from '../../../lexical/utils/url.js' diff --git a/packages/richtext-lexical/src/features/link/server/graphQLPopulationPromise.ts b/packages/richtext-lexical/src/features/link/server/graphQLPopulationPromise.ts index 1b1d66d523d..625f3e35b52 100644 --- a/packages/richtext-lexical/src/features/link/server/graphQLPopulationPromise.ts +++ b/packages/richtext-lexical/src/features/link/server/graphQLPopulationPromise.ts @@ -1,6 +1,6 @@ import type { PopulationPromise } from '../../typesServer.js' -import type { SerializedLinkNode } from '../nodes/types.js' import type { LinkFeatureServerProps } from './index.js' +import type { SerializedLinkNode } from './schema.js' import { recursivelyPopulateFieldsForGraphQL } from '../../../populateGraphQL/recursivelyPopulateFieldsForGraphQL.js' diff --git a/packages/richtext-lexical/src/features/link/server/validate.ts b/packages/richtext-lexical/src/features/link/server/validate.ts index 452334676bd..e66dcdf8674 100644 --- a/packages/richtext-lexical/src/features/link/server/validate.ts +++ b/packages/richtext-lexical/src/features/link/server/validate.ts @@ -3,8 +3,8 @@ import type { Field } from 'payload' import { fieldSchemasToFormState } from '@payloadcms/ui/forms/fieldSchemasToFormState' import type { NodeValidation } from '../../typesServer.js' -import type { SerializedAutoLinkNode, SerializedLinkNode } from '../nodes/types.js' import type { LinkFeatureServerProps } from './index.js' +import type { SerializedAutoLinkNode, SerializedLinkNode } from './schema.js' export const linkValidation = ( props: LinkFeatureServerProps, diff --git a/packages/richtext-lexical/src/features/relationship/client/nodes/RelationshipNode.tsx b/packages/richtext-lexical/src/features/relationship/client/nodes/RelationshipNode.tsx index 92f2a02ae9d..505c0a5d953 100644 --- a/packages/richtext-lexical/src/features/relationship/client/nodes/RelationshipNode.tsx +++ b/packages/richtext-lexical/src/features/relationship/client/nodes/RelationshipNode.tsx @@ -11,10 +11,7 @@ import { } from 'lexical' import * as React from 'react' -import type { - RelationshipData, - SerializedRelationshipNode, -} from '../../server/nodes/RelationshipNode.js' +import type { RelationshipData, SerializedRelationshipNode } from '../../server/schema.js' import { RelationshipServerNode } from '../../server/nodes/RelationshipNode.js' diff --git a/packages/richtext-lexical/src/types/index.ts b/packages/richtext-lexical/src/types/index.ts index 115feac1ee2..e962577435b 100644 --- a/packages/richtext-lexical/src/types/index.ts +++ b/packages/richtext-lexical/src/types/index.ts @@ -48,7 +48,7 @@ import type { * Used as the generic constraint for node map types. * Extends the base SerializedLexicalNode with optional type for flexibility. */ -export type SerializedNodeBase = { [key: string]: unknown; type?: string } +export type SerializedNodeBase = { type?: string } export type LexicalFieldAdminProps = { /** From 7d7149ad2d7668c9a175bcd7724f58a77d053fa4 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Tue, 2 Jun 2026 17:08:24 +0000 Subject: [PATCH 19/56] fix build --- .../src/features/blocks/server/schema.ts | 2 +- .../features/converters/lexicalToHtml/async/types.ts | 2 +- .../features/converters/lexicalToHtml/sync/types.ts | 2 +- .../converters/lexicalToJSX/Component/index.tsx | 4 ++-- .../src/features/link/nodes/AutoLinkNode.ts | 11 +++++++++-- .../src/features/link/nodes/LinkNode.ts | 4 +++- 6 files changed, 17 insertions(+), 8 deletions(-) diff --git a/packages/richtext-lexical/src/features/blocks/server/schema.ts b/packages/richtext-lexical/src/features/blocks/server/schema.ts index 9ddbe4dedf6..b3679e21743 100644 --- a/packages/richtext-lexical/src/features/blocks/server/schema.ts +++ b/packages/richtext-lexical/src/features/blocks/server/schema.ts @@ -9,7 +9,7 @@ import type { JSONSchemaArgs, JSONSchemaFn } from '../../typesServer.js' import { formatSchema } from '../../../types/jsonSchemaHelpers.js' type BaseBlockFields = { - blockName: string + blockName?: null | string blockType: string } & TFields diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/types.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/types.ts index dccb32a1a45..9fce30d88ce 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/types.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/async/types.ts @@ -89,6 +89,6 @@ export type HTMLConvertersAsync< export type HTMLConvertersFunctionAsync< T extends { [key: string]: any; type?: string } = | DefaultNodeTypes - | SerializedBlockNode<{ blockName?: null | string }> + | SerializedBlockNode<{ blockName?: null | string; blockType: string }> | SerializedInlineBlockNode<{ blockName?: null | string; blockType: string }>, > = (args: { defaultConverters: HTMLConvertersAsync }) => HTMLConvertersAsync diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/types.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/types.ts index e5f1926402d..48b1ccd1b9e 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/types.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/sync/types.ts @@ -77,6 +77,6 @@ export type HTMLConverters< export type HTMLConvertersFunction< T extends { [key: string]: any; type?: string } = | DefaultNodeTypes - | SerializedBlockNode<{ blockName?: null | string }> + | SerializedBlockNode<{ blockName?: null | string; blockType: string }> | SerializedInlineBlockNode<{ blockName?: null | string; blockType: string }>, > = (args: { defaultConverters: HTMLConverters }) => HTMLConverters diff --git a/packages/richtext-lexical/src/features/converters/lexicalToJSX/Component/index.tsx b/packages/richtext-lexical/src/features/converters/lexicalToJSX/Component/index.tsx index d94e60460fe..8eef57bae96 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToJSX/Component/index.tsx +++ b/packages/richtext-lexical/src/features/converters/lexicalToJSX/Component/index.tsx @@ -14,8 +14,8 @@ import { convertLexicalToJSX, type ConvertLexicalToJSXArgs } from '../converter/ export type JSXConvertersFunction< T extends SerializedNodeBase = | DefaultNodeTypes - | SerializedBlockNode<{ blockName?: null | string }> - | SerializedInlineBlockNode<{ blockName?: null | string }>, + | SerializedBlockNode<{ blockName?: null | string; blockType: string }> + | SerializedInlineBlockNode<{ blockName?: null | string; blockType: string }>, > = (args: { defaultConverters: JSXConverters }) => JSXConverters type RichTextProps = { diff --git a/packages/richtext-lexical/src/features/link/nodes/AutoLinkNode.ts b/packages/richtext-lexical/src/features/link/nodes/AutoLinkNode.ts index 194dd9e9d11..292ebb242be 100644 --- a/packages/richtext-lexical/src/features/link/nodes/AutoLinkNode.ts +++ b/packages/richtext-lexical/src/features/link/nodes/AutoLinkNode.ts @@ -1,4 +1,10 @@ -import type { ElementNode, LexicalNode, LexicalUpdateJSON, RangeSelection } from 'lexical' +import type { + ElementNode, + LexicalNode, + LexicalUpdateJSON, + RangeSelection, + SerializedElementNode, +} from 'lexical' import { $applyNodeReplacement, $isElementNode } from 'lexical' @@ -65,7 +71,8 @@ export class AutoLinkNode extends LinkNode { return null } - override updateFromJSON(serializedNode: LexicalUpdateJSON): this { + override updateFromJSON(_serializedNode: LexicalUpdateJSON): this { + const serializedNode = _serializedNode as unknown as SerializedAutoLinkNode return super.updateFromJSON(serializedNode).setFields(serializedNode.fields) } } diff --git a/packages/richtext-lexical/src/features/link/nodes/LinkNode.ts b/packages/richtext-lexical/src/features/link/nodes/LinkNode.ts index 7f3e2962bac..23854e55528 100644 --- a/packages/richtext-lexical/src/features/link/nodes/LinkNode.ts +++ b/packages/richtext-lexical/src/features/link/nodes/LinkNode.ts @@ -9,6 +9,7 @@ import type { LexicalUpdateJSON, NodeKey, RangeSelection, + SerializedElementNode, } from 'lexical' import { addClassNamesToElement, isHTMLAnchorElement } from '@lexical/utils' @@ -244,7 +245,8 @@ export class LinkNode extends ElementNode { return false } - override updateFromJSON(serializedNode: LexicalUpdateJSON): this { + override updateFromJSON(_serializedNode: LexicalUpdateJSON): this { + const serializedNode = _serializedNode as unknown as SerializedLinkNode return super .updateFromJSON(serializedNode) .setFields(serializedNode.fields) From 4c1f454f2b80f08916d3f7f9f08307f54f0263c7 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Tue, 2 Jun 2026 17:21:08 +0000 Subject: [PATCH 20/56] matching blockName schema --- .../src/features/blocks/server/schema.ts | 7 +- test/lexical/payload-types.ts | 862 ++++++++++-------- 2 files changed, 491 insertions(+), 378 deletions(-) diff --git a/packages/richtext-lexical/src/features/blocks/server/schema.ts b/packages/richtext-lexical/src/features/blocks/server/schema.ts index b3679e21743..d8b222f6a08 100644 --- a/packages/richtext-lexical/src/features/blocks/server/schema.ts +++ b/packages/richtext-lexical/src/features/blocks/server/schema.ts @@ -27,7 +27,7 @@ export type InlineBlockFields = { } & TFields export type SerializedBlockNode = { - fields: { blockName: null | string; id: string } & Omit + fields: { blockName?: string | null; id: string } & Omit format: LexicalElementFormat type: 'block' version: number @@ -49,7 +49,7 @@ const BLOCK_NODES_TS = `export type SerializedBlockNode; + fields: { id: string; blockName?: string | null } & Omit; }; export type SerializedInlineBlockNode = { type: 'inlineBlock'; @@ -63,7 +63,7 @@ const blockFieldsInterfaceName = (block: Block) => block.interfaceName ?? toWord /** * JSON Schema for one block's `fields:` payload. Strips Payload's auto-added * `id`/`blockName` and re-adds them with strict runtime types: required - * non-null `id`, required `blockName: string | null` (omitted for inline + * non-null `id`, optional `blockName?: string | null` (omitted for inline * blocks). Always registers as a top-level `$ref`. */ const buildBlockFieldsSchema = ( @@ -101,7 +101,6 @@ const buildBlockFieldsSchema = ( if (!isInlineBlock) { properties.blockName = { type: ['string', 'null'] } - required.push('blockName') } const fieldsSchema: JSONSchema4 = { diff --git a/test/lexical/payload-types.ts b/test/lexical/payload-types.ts index de593491155..1af3963477d 100644 --- a/test/lexical/payload-types.ts +++ b/test/lexical/payload-types.ts @@ -62,16 +62,16 @@ export type SupportedTimezones = | 'Pacific/Fiji'; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_698362B2". + * via the `definition` "LexicalNodes_32EA6B4A". */ -export type LexicalNodes_698362B2 = +export type LexicalNodes_32EA6B4A = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -101,26 +101,27 @@ export type LexicalNodes_698362B2 = | 'OnDemandForm' | 'OnDemandOutsideForm' | 'lexical-custom-cell' - | 'payload-kv' | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' | 'payload-locked-documents' | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_D0888BA2". + * via the `definition` "LexicalNodes_FF120C72". */ -export type LexicalNodes_D0888BA2 = +export type LexicalNodes_FF120C72 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode< | BenchBlock1 | BenchBlock2 @@ -156,7 +157,7 @@ export type LexicalNodes_D0888BA2 = | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -186,34 +187,35 @@ export type LexicalNodes_D0888BA2 = | 'OnDemandForm' | 'OnDemandOutsideForm' | 'lexical-custom-cell' - | 'payload-kv' | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' | 'payload-locked-documents' | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_75C842AC". + * via the `definition` "LexicalNodes_F9A96ED9". */ -export type LexicalNodes_75C842AC = +export type LexicalNodes_F9A96ED9 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -243,33 +245,34 @@ export type LexicalNodes_75C842AC = | 'OnDemandForm' | 'OnDemandOutsideForm' | 'lexical-custom-cell' - | 'payload-kv' | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' | 'payload-locked-documents' | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_BF66DC01". + * via the `definition` "LexicalNodes_26E8B07E". */ -export type LexicalNodes_BF66DC01 = +export type LexicalNodes_26E8B07E = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedParagraphNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -299,29 +302,30 @@ export type LexicalNodes_BF66DC01 = | 'OnDemandForm' | 'OnDemandOutsideForm' | 'lexical-custom-cell' - | 'payload-kv' | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' | 'payload-locked-documents' | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_EDD2E236". + * via the `definition` "LexicalNodes_6F823331". */ -export type LexicalNodes_EDD2E236 = +export type LexicalNodes_6F823331 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedParagraphNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -351,15 +355,16 @@ export type LexicalNodes_EDD2E236 = | 'OnDemandForm' | 'OnDemandOutsideForm' | 'lexical-custom-cell' - | 'payload-kv' | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' | 'payload-locked-documents' | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "LexicalNodes_4DAB3018". @@ -373,17 +378,17 @@ export type LexicalNodes_4DAB3018 = | SerializedListItemNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_5B50F90F". + * via the `definition` "LexicalNodes_652244A4". */ -export type LexicalNodes_5B50F90F = +export type LexicalNodes_652244A4 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedHeadingNode + | SerializedParagraphNode + | SerializedHeadingNode | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -413,34 +418,35 @@ export type LexicalNodes_5B50F90F = | 'OnDemandForm' | 'OnDemandOutsideForm' | 'lexical-custom-cell' - | 'payload-kv' | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' | 'payload-locked-documents' | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_52F22C78". + * via the `definition` "LexicalNodes_4E96E670". */ -export type LexicalNodes_52F22C78 = +export type LexicalNodes_4E96E670 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> - | SerializedHeadingNode + | SerializedHeadingNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedListNode - | SerializedListItemNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -470,26 +476,27 @@ export type LexicalNodes_52F22C78 = | 'OnDemandForm' | 'OnDemandOutsideForm' | 'lexical-custom-cell' - | 'payload-kv' | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' | 'payload-locked-documents' | 'payload-preferences' | 'payload-migrations' >; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_5065BF69". + * via the `definition` "LexicalNodes_F25D27D9". */ -export type LexicalNodes_5065BF69 = +export type LexicalNodes_F25D27D9 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -519,17 +526,18 @@ export type LexicalNodes_5065BF69 = | 'OnDemandForm' | 'OnDemandOutsideForm' | 'lexical-custom-cell' - | 'payload-kv' | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' | 'payload-locked-documents' | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "BlockColumns". @@ -548,14 +556,14 @@ export type BlockColumns = | null; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_9E9D615A". + * via the `definition` "LexicalNodes_5BC162BC". */ -export type LexicalNodes_9E9D615A = +export type LexicalNodes_5BC162BC = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedHeadingNode + | SerializedParagraphNode + | SerializedHeadingNode | SerializedBlockNode< | RichTextBlock | TextRequired @@ -570,16 +578,16 @@ export type LexicalNodes_9E9D615A = | SerializedInlineBlockNode<{blockType: string}>; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_096444F4". + * via the `definition` "LexicalNodes_2792F11B". */ -export type LexicalNodes_096444F4 = +export type LexicalNodes_2792F11B = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode + | SerializedParagraphNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode | SerializedBlockNode< | ValidationBlock | FilterOptionsBlock @@ -610,10 +618,10 @@ export type LexicalNodes_096444F4 = | MyInlineBlockWithBlockAndLabel > | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -643,29 +651,30 @@ export type LexicalNodes_096444F4 = | 'OnDemandForm' | 'OnDemandOutsideForm' | 'lexical-custom-cell' - | 'payload-kv' | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' | 'payload-locked-documents' | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_1F1774B7". + * via the `definition` "LexicalNodes_423CFDD8". */ -export type LexicalNodes_1F1774B7 = +export type LexicalNodes_423CFDD8 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -695,31 +704,32 @@ export type LexicalNodes_1F1774B7 = | 'OnDemandForm' | 'OnDemandOutsideForm' | 'lexical-custom-cell' - | 'payload-kv' | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' | 'payload-locked-documents' | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_50F31288". + * via the `definition` "LexicalNodes_B33E6EC4". */ -export type LexicalNodes_50F31288 = +export type LexicalNodes_B33E6EC4 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -749,31 +759,32 @@ export type LexicalNodes_50F31288 = | 'OnDemandForm' | 'OnDemandOutsideForm' | 'lexical-custom-cell' - | 'payload-kv' | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' | 'payload-locked-documents' | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_30BF6BFA". + * via the `definition` "LexicalNodes_816689F6". */ -export type LexicalNodes_30BF6BFA = +export type LexicalNodes_816689F6 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -803,31 +814,32 @@ export type LexicalNodes_30BF6BFA = | 'OnDemandForm' | 'OnDemandOutsideForm' | 'lexical-custom-cell' - | 'payload-kv' | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' | 'payload-locked-documents' | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_5DF9547D". + * via the `definition` "LexicalNodes_846D8E24". */ -export type LexicalNodes_5DF9547D = +export type LexicalNodes_846D8E24 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -857,31 +869,32 @@ export type LexicalNodes_5DF9547D = | 'OnDemandForm' | 'OnDemandOutsideForm' | 'lexical-custom-cell' - | 'payload-kv' | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' | 'payload-locked-documents' | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_0517F0E7". + * via the `definition` "LexicalNodes_1889F581". */ -export type LexicalNodes_0517F0E7 = +export type LexicalNodes_1889F581 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -911,31 +924,32 @@ export type LexicalNodes_0517F0E7 = | 'OnDemandForm' | 'OnDemandOutsideForm' | 'lexical-custom-cell' - | 'payload-kv' | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' | 'payload-locked-documents' | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_4A786712". + * via the `definition` "LexicalNodes_634B98CF". */ -export type LexicalNodes_4A786712 = +export type LexicalNodes_634B98CF = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -965,17 +979,18 @@ export type LexicalNodes_4A786712 = | 'OnDemandForm' | 'OnDemandOutsideForm' | 'lexical-custom-cell' - | 'payload-kv' | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' | 'payload-locked-documents' | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "LexicalNodes_8D432583". @@ -988,35 +1003,35 @@ export type LexicalNodes_8D432583 = | SerializedUploadNode<'uploads' | 'uploads2'>; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_6E495D8E". + * via the `definition` "LexicalNodes_68F73700". */ -export type LexicalNodes_6E495D8E = +export type LexicalNodes_68F73700 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}>; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_463BB3B6". + * via the `definition` "LexicalNodes_AD8137E5". */ -export type LexicalNodes_463BB3B6 = +export type LexicalNodes_AD8137E5 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode<{blockType: string}> | SerializedInlineBlockNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_6339F04B". + * via the `definition` "LexicalNodes_7EAD8D74". */ -export type LexicalNodes_6339F04B = +export type LexicalNodes_7EAD8D74 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}>; /** @@ -1039,13 +1054,13 @@ export type LexicalNodes_A23F00F3 = | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_DD92D6E8". + * via the `definition` "LexicalNodes_D05D701F". */ -export type LexicalNodes_DD92D6E8 = +export type LexicalNodes_D05D701F = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1075,32 +1090,33 @@ export type LexicalNodes_DD92D6E8 = | 'OnDemandForm' | 'OnDemandOutsideForm' | 'lexical-custom-cell' - | 'payload-kv' | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' | 'payload-locked-documents' | 'payload-preferences' | 'payload-migrations' > | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedQuoteNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_C390D5EC". + * via the `definition` "LexicalNodes_F2570347". */ -export type LexicalNodes_C390D5EC = +export type LexicalNodes_F2570347 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedUploadNode<'uploads2'> | SerializedHorizontalRuleNode - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1130,31 +1146,32 @@ export type LexicalNodes_C390D5EC = | 'OnDemandForm' | 'OnDemandOutsideForm' | 'lexical-custom-cell' - | 'payload-kv' | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' | 'payload-locked-documents' | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_B294A98F". + * via the `definition` "LexicalNodes_A4F423C0". */ -export type LexicalNodes_B294A98F = +export type LexicalNodes_A4F423C0 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1184,33 +1201,34 @@ export type LexicalNodes_B294A98F = | 'OnDemandForm' | 'OnDemandOutsideForm' | 'lexical-custom-cell' - | 'payload-kv' | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' | 'payload-locked-documents' | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_C0F97F48". + * via the `definition` "LexicalNodes_D654DD6A". */ -export type LexicalNodes_C0F97F48 = +export type LexicalNodes_D654DD6A = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1240,36 +1258,37 @@ export type LexicalNodes_C0F97F48 = | 'OnDemandForm' | 'OnDemandOutsideForm' | 'lexical-custom-cell' - | 'payload-kv' | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' | 'payload-locked-documents' | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_4CE78AC7". + * via the `definition` "LexicalNodes_A0A0A55E". */ -export type LexicalNodes_4CE78AC7 = +export type LexicalNodes_A0A0A55E = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode + | SerializedParagraphNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> - | SerializedHeadingNode + | SerializedHeadingNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedListNode - | SerializedListItemNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1299,8 +1318,9 @@ export type LexicalNodes_4CE78AC7 = | 'OnDemandForm' | 'OnDemandOutsideForm' | 'lexical-custom-cell' - | 'payload-kv' | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' | 'payload-locked-documents' | 'payload-preferences' | 'payload-migrations' @@ -1309,6 +1329,7 @@ export type LexicalNodes_4CE78AC7 = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: { nestedBlock: NestedBlock; @@ -1345,8 +1366,9 @@ export interface Config { OnDemandForm: OnDemandForm; OnDemandOutsideForm: OnDemandOutsideForm; 'lexical-custom-cell': LexicalCustomCell; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -1383,8 +1405,9 @@ export interface Config { OnDemandForm: OnDemandFormSelect | OnDemandFormSelect; OnDemandOutsideForm: OnDemandOutsideFormSelect | OnDemandOutsideFormSelect; 'lexical-custom-cell': LexicalCustomCellSelect | LexicalCustomCellSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -1403,7 +1426,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -1427,6 +1450,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "NestedBlock". @@ -1453,7 +1494,7 @@ export interface BlockWithBlockRef { */ export interface LexicalBenchmark { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1463,7 +1504,7 @@ export interface LexicalBenchmark { */ export interface LexicalFullyFeatured { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1476,7 +1517,7 @@ export interface LexicalAutosave { title?: string | null; cta?: | { - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; id?: string | null; }[] | null; @@ -1490,7 +1531,7 @@ export interface LexicalAutosave { */ export interface LexicalLinkFeature { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1510,7 +1551,7 @@ export interface LexicalListsFeature { */ export interface LexicalHeadingFeature { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1520,7 +1561,7 @@ export interface LexicalHeadingFeature { */ export interface LexicalJsxConverter { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1531,15 +1572,15 @@ export interface LexicalJsxConverter { export interface LexicalField { id: string; title: string; - lexicalRootEditor?: LexicalRichText | null; + lexicalRootEditor?: LexicalRichText | null; /** * A simple lexical field */ - lexicalSimple?: LexicalRichText | null; + lexicalSimple?: LexicalRichText | null; /** * Should not be rendered */ - lexicalWithBlocks: LexicalRichText; + lexicalWithBlocks: LexicalRichText; lexicalWithBlocks_markdown?: string | null; updatedAt: string; createdAt: string; @@ -1550,8 +1591,8 @@ export interface LexicalField { */ export interface LexicalView { id: string; - customDefaultView?: LexicalRichText | null; - vanillaView?: LexicalRichText | null; + customDefaultView?: LexicalRichText | null; + vanillaView?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1561,7 +1602,7 @@ export interface LexicalView { */ export interface LexicalViewsFrontend { id: string; - customFrontendViews?: LexicalRichText | null; + customFrontendViews?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1572,7 +1613,7 @@ export interface LexicalViewsFrontend { export interface LexicalViewsProvider { id: string; viewProviderWrapper?: { - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; }; updatedAt: string; createdAt: string; @@ -1584,7 +1625,7 @@ export interface LexicalViewsProvider { export interface LexicalViewsProviderDefault { id: string; defaultViewWrapper?: { - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; }; updatedAt: string; createdAt: string; @@ -1596,7 +1637,7 @@ export interface LexicalViewsProviderDefault { export interface LexicalViewsProviderFallback { id: string; fallbackViewWrapper?: { - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; }; updatedAt: string; createdAt: string; @@ -1607,7 +1648,7 @@ export interface LexicalViewsProviderFallback { */ export interface LexicalViewsNested { id: string; - parentRichText?: LexicalRichText | null; + parentRichText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1621,11 +1662,11 @@ export interface LexicalLocalizedField { /** * Non-localized field with localized block subfields */ - lexicalBlocksSubLocalized?: LexicalRichText | null; + lexicalBlocksSubLocalized?: LexicalRichText | null; /** * Localized field with localized block subfields */ - lexicalBlocksLocalized?: LexicalRichText | null; + lexicalBlocksLocalized?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1635,7 +1676,7 @@ export interface LexicalLocalizedField { */ export interface LexicalObjectReferenceBug { id: string; - lexicalDefault?: LexicalRichText | null; + lexicalDefault?: LexicalRichText | null; lexicalEditor?: LexicalRichText | null; updatedAt: string; createdAt: string; @@ -1646,7 +1687,7 @@ export interface LexicalObjectReferenceBug { */ export interface LexicalInBlock { id: string; - content?: LexicalRichText | null; + content?: LexicalRichText | null; blocks?: LexicalInBlock2[] | null; updatedAt: string; createdAt: string; @@ -1656,7 +1697,7 @@ export interface LexicalInBlock { * via the `definition` "LexicalInBlock2". */ export interface LexicalInBlock2 { - lexical?: LexicalRichText | null; + lexical?: LexicalRichText | null; id?: string | null; blockName?: string | null; blockType: 'lexicalInBlock2'; @@ -1667,7 +1708,7 @@ export interface LexicalInBlock2 { */ export interface LexicalAutosaveBlock { id: string; - content?: LexicalRichText | null; + content?: LexicalRichText | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -1679,7 +1720,7 @@ export interface LexicalAutosaveBlock { export interface LexicalAccessControl { id: string; title?: string | null; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1690,8 +1731,8 @@ export interface LexicalAccessControl { export interface LexicalRelationshipField { id: string; richText?: LexicalRichText | null; - richText2?: LexicalRichText | null; - richText3?: LexicalRichText | null; + richText2?: LexicalRichText | null; + richText3?: LexicalRichText | null; richTextLocalized?: LexicalRichText | null; updatedAt: string; createdAt: string; @@ -1703,7 +1744,7 @@ export interface LexicalRelationshipField { */ export interface Collision { id: string; - collision?: LexicalRichText | null; + collision?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1714,7 +1755,7 @@ export interface Collision { export interface LexicalNestedBlock { id: string; title: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1725,12 +1766,12 @@ export interface LexicalNestedBlock { export interface RichTextField { id: string; title: string; - lexicalCustomFields: LexicalRichText; + lexicalCustomFields: LexicalRichText; lexicalCustomFields_html?: string | null; /** * This rich text field uses the lexical editor. */ - lexical?: LexicalRichText | null; + lexical?: LexicalRichText | null; /** * This select field is rendered here to ensure its options dropdown renders above the rich text toolbar. */ @@ -1976,7 +2017,7 @@ export interface OnDemandOutsideForm { | number | boolean | null; - hiddenAnchor?: LexicalRichText | null; + hiddenAnchor?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1987,27 +2028,10 @@ export interface OnDemandOutsideForm { export interface LexicalCustomCell { id: string; title: string; - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -2033,6 +2057,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -2163,12 +2247,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -2178,10 +2271,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -2686,14 +2784,6 @@ export interface LexicalCustomCellSelect { updatedAt?: T; createdAt?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -2716,6 +2806,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -2755,10 +2869,10 @@ export interface PayloadMigrationsSelect { export interface TabsWithRichText { id: string; tab1?: { - rt1?: LexicalRichText | null; + rt1?: LexicalRichText | null; }; tab2?: { - rt2?: LexicalRichText | null; + rt2?: LexicalRichText | null; }; updatedAt?: string | null; createdAt?: string | null; @@ -2801,7 +2915,7 @@ export interface BenchBlock1 { blockType: 'benchBlock1'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -2812,7 +2926,7 @@ export interface BenchBlock2 { blockType: 'benchBlock2'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -2823,7 +2937,7 @@ export interface BenchBlock3 { blockType: 'benchBlock3'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -2834,7 +2948,7 @@ export interface BenchBlock4 { blockType: 'benchBlock4'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -2845,7 +2959,7 @@ export interface BenchBlock5 { blockType: 'benchBlock5'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -2856,7 +2970,7 @@ export interface BenchBlock6 { blockType: 'benchBlock6'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -2867,7 +2981,7 @@ export interface BenchBlock7 { blockType: 'benchBlock7'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -2878,7 +2992,7 @@ export interface BenchBlock8 { blockType: 'benchBlock8'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -2889,7 +3003,7 @@ export interface BenchBlock9 { blockType: 'benchBlock9'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -2900,7 +3014,7 @@ export interface BenchBlock10 { blockType: 'benchBlock10'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -2911,7 +3025,7 @@ export interface BenchBlock11 { blockType: 'benchBlock11'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -2922,7 +3036,7 @@ export interface BenchBlock12 { blockType: 'benchBlock12'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -2933,7 +3047,7 @@ export interface BenchBlock13 { blockType: 'benchBlock13'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -2944,7 +3058,7 @@ export interface BenchBlock14 { blockType: 'benchBlock14'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -2955,7 +3069,7 @@ export interface BenchBlock15 { blockType: 'benchBlock15'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -2966,7 +3080,7 @@ export interface BenchBlock16 { blockType: 'benchBlock16'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -2977,7 +3091,7 @@ export interface BenchBlock17 { blockType: 'benchBlock17'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -2988,7 +3102,7 @@ export interface BenchBlock18 { blockType: 'benchBlock18'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -2999,7 +3113,7 @@ export interface BenchBlock19 { blockType: 'benchBlock19'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3010,7 +3124,7 @@ export interface BenchBlock20 { blockType: 'benchBlock20'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3021,7 +3135,7 @@ export interface BenchBlock21 { blockType: 'benchBlock21'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3032,7 +3146,7 @@ export interface BenchBlock22 { blockType: 'benchBlock22'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3043,7 +3157,7 @@ export interface BenchBlock23 { blockType: 'benchBlock23'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3054,7 +3168,7 @@ export interface BenchBlock24 { blockType: 'benchBlock24'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3065,7 +3179,7 @@ export interface BenchBlock25 { blockType: 'benchBlock25'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3076,7 +3190,7 @@ export interface BenchBlock26 { blockType: 'benchBlock26'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3087,7 +3201,7 @@ export interface BenchBlock27 { blockType: 'benchBlock27'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3098,7 +3212,7 @@ export interface BenchBlock28 { blockType: 'benchBlock28'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3109,7 +3223,7 @@ export interface BenchBlock29 { blockType: 'benchBlock29'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3120,7 +3234,7 @@ export interface BenchBlock30 { blockType: 'benchBlock30'; title?: string | null; content?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3130,7 +3244,7 @@ export interface Code { id: string; blockType: 'code'; code?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3141,7 +3255,7 @@ export interface PayloadCode { blockType: 'PayloadCode'; language?: ('js' | 'ts' | 'json' | 'plaintext') | null; code?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3153,7 +3267,7 @@ export interface MyBlock { someText?: string | null; someTextRequired: string; radios?: ('option1' | 'option2' | 'option3') | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3194,9 +3308,9 @@ export interface LinkBlock { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_BF66DC01". + * via the `definition` "LexicalLinkFields_26E8B07E". */ -export interface LexicalLinkFields_BF66DC01 { +export interface LexicalLinkFields_26E8B07E { linkBlocks?: LinkBlock[] | null; doc?: { relationTo: string; @@ -3214,9 +3328,9 @@ export interface LexicalLinkFields_BF66DC01 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_EDD2E236". + * via the `definition` "LexicalLinkFields_6F823331". */ -export interface LexicalLinkFields_EDD2E236 { +export interface LexicalLinkFields_6F823331 { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3244,9 +3358,9 @@ export interface Block { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_52F22C78". + * via the `definition` "LexicalLinkFields_4E96E670". */ -export interface LexicalLinkFields_52F22C78 { +export interface LexicalLinkFields_4E96E670 { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3269,9 +3383,9 @@ export interface LexicalLinkFields_52F22C78 { export interface LexicalAndUploadBlock { id: string; blockType: 'lexicalAndUploadBlock'; - subRichTextField?: LexicalRichText | null; + subRichTextField?: LexicalRichText | null; subUploadField?: (string | null) | Upload; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3280,8 +3394,8 @@ export interface LexicalAndUploadBlock { export interface RichTextBlock { id: string; blockType: 'richTextBlock'; - richTextField?: LexicalRichText | null; - blockName: string | null; + richTextField?: LexicalRichText | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3291,7 +3405,7 @@ export interface TextRequired { id: string; blockType: 'textRequired'; text: string; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3301,8 +3415,8 @@ export interface UploadAndRichText { id: string; blockType: 'uploadAndRichText'; upload: string | Upload; - richText?: LexicalRichText | null; - blockName: string | null; + richText?: LexicalRichText | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3312,7 +3426,7 @@ export interface Select { id: string; blockType: 'select'; select?: ('option1' | 'option2' | 'option3' | 'option4' | 'option5') | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3322,7 +3436,7 @@ export interface RelationshipBlock { id: string; blockType: 'relationshipBlock'; rel: string | Upload; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3341,7 +3455,7 @@ export interface RelationshipHasManyBlock { value: string | Upload; } )[]; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3351,8 +3465,8 @@ export interface ContentBlock { id: string; blockType: 'content-block'; title: string; - richText?: LexicalRichText | null; - blockName: string | null; + richText?: LexicalRichText | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3372,7 +3486,7 @@ export interface SubBlockLexical { id: string; blockType: 'subBlockLexical'; subBlocksLexical?: (ContentBlock | TextArea | Select)[] | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3382,7 +3496,7 @@ export interface LexicalBlocksRadioButtonsBlock { id: string; blockType: 'radioButtons'; radioButtons?: ('option1' | 'option2' | 'option3') | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3395,7 +3509,7 @@ export interface ConditionalLayout { columns?: BlockColumns; columns2?: BlockColumns; columns3?: BlockColumns; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3411,7 +3525,7 @@ export interface ValidationBlock { textDependsOnSiblingData?: string | null; textDependsOnBlockData?: string | null; }; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3427,7 +3541,7 @@ export interface FilterOptionsBlock { dependsOnSiblingData?: (string | null) | TextField; dependsOnBlockData?: (string | null) | TextField; }; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3438,7 +3552,7 @@ export interface AsyncHooksBlock { blockType: 'asyncHooksBlock'; test1?: string | null; test2?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3453,7 +3567,7 @@ export interface TabBlock { tab2?: { text2?: string | null; }; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3463,7 +3577,7 @@ export interface NoBlockName { id: string; blockType: 'noBlockName'; text?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3473,7 +3587,7 @@ export interface MyBlockWithLabel { id: string; blockType: 'myBlockWithLabel'; key?: ('value1' | 'value2' | 'value3') | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3483,7 +3597,7 @@ export interface MyBlockWithBlock { id: string; blockType: 'myBlockWithBlock'; key?: ('value1' | 'value2' | 'value3') | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3493,7 +3607,7 @@ export interface BlockRSC { id: string; blockType: 'BlockRSC'; key?: ('value1' | 'value2' | 'value3') | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3503,7 +3617,7 @@ export interface MyBlockWithBlockAndLabel { id: string; blockType: 'myBlockWithBlockAndLabel'; key?: ('value1' | 'value2' | 'value3') | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3548,9 +3662,9 @@ export interface MyInlineBlockWithBlockAndLabel { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_096444F4". + * via the `definition` "LexicalLinkFields_2792F11B". */ -export interface LexicalLinkFields_096444F4 { +export interface LexicalLinkFields_2792F11B { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3577,7 +3691,7 @@ export interface ViewsTestBlock { id: string; blockType: 'viewsTestBlock'; text?: string | null; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3588,8 +3702,8 @@ export interface BannerBlock { blockType: 'banner'; type: 'normal' | 'important'; title: string; - content?: LexicalRichText | null; - blockName: string | null; + content?: LexicalRichText | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3600,8 +3714,8 @@ export interface ProviderBannerBlock { blockType: 'banner'; type: 'normal' | 'important'; title: string; - content?: LexicalRichText | null; - blockName: string | null; + content?: LexicalRichText | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3611,8 +3725,8 @@ export interface NestedContentBlock { id: string; blockType: 'nested-content'; label: string; - nestedRichText?: LexicalRichText | null; - blockName: string | null; + nestedRichText?: LexicalRichText | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3624,7 +3738,7 @@ export interface BlockLexicalLocalized { textLocalized?: string | null; counter?: number | null; rel?: (string | null) | LexicalLocalizedField; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3635,7 +3749,7 @@ export interface BlockLexicalLocalized2 { blockType: 'blockLexicalLocalized2'; textLocalized?: string | null; rel?: (string | null) | LexicalLocalizedField; - blockName: string | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3647,8 +3761,8 @@ export interface BlockInLexical { /** * Some Description */ - lexicalInBlock: LexicalRichText; - blockName: string | null; + lexicalInBlock: LexicalRichText; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3666,14 +3780,14 @@ export interface InlineBlockInLexical { export interface BlockWithRichText { id: string; blockType: 'blockWithRichText'; - nestedRichText?: LexicalRichText | null; - blockName: string | null; + nestedRichText?: LexicalRichText | null; + blockName?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_C0F97F48". + * via the `definition` "LexicalLinkFields_D654DD6A". */ -export interface LexicalLinkFields_C0F97F48 { +export interface LexicalLinkFields_D654DD6A { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3694,9 +3808,9 @@ export interface LexicalLinkFields_C0F97F48 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_4CE78AC7". + * via the `definition` "LexicalLinkFields_A0A0A55E". */ -export interface LexicalLinkFields_4CE78AC7 { +export interface LexicalLinkFields_A0A0A55E { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3858,7 +3972,7 @@ export type SerializedBlockNode = { type: 'block'; format: LexicalElementFormat; version: number; - fields: { id: string; blockName: string | null } & Omit; + fields: { id: string; blockName?: string | null } & Omit; }; export type SerializedInlineBlockNode = { type: 'inlineBlock'; From 3b9df2f5d39c2820ff30d8f42a259900282f2f65 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Tue, 2 Jun 2026 18:05:03 +0000 Subject: [PATCH 21/56] fix build --- packages/payload/src/fields/config/types.ts | 8 ++++---- .../blocks/client/markdown/markdownTransformer.ts | 8 ++++---- .../blocks/server/markdown/markdownTransformer.ts | 8 ++++---- packages/richtext-lexical/src/types/nodeTypes.ts | 5 +++-- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/packages/payload/src/fields/config/types.ts b/packages/payload/src/fields/config/types.ts index d6297930090..a73db0f6ec6 100644 --- a/packages/payload/src/fields/config/types.ts +++ b/packages/payload/src/fields/config/types.ts @@ -4,7 +4,7 @@ import type { EditorProps } from '@monaco-editor/react' import type { JSONSchema4 } from 'json-schema' import type { CSSProperties } from 'react' import type React from 'react' -import type { DeepUndefinable, MarkRequired } from 'ts-essentials' +import type { DeepUndefinable, MarkOptional, MarkRequired } from 'ts-essentials' import type { JoinFieldClientProps, @@ -1371,8 +1371,8 @@ export type RadioFieldClient = { type BlockFields = { [key: string]: any - blockName?: string - blockType?: string + blockName?: null | string + blockType: string } export type BlockJSX = { @@ -1430,7 +1430,7 @@ export type BlockJSX = { markdownToLexical: (props: { markdown: string }) => Record openMatch?: RegExpMatchArray props: Record - }) => BlockFields | false + }) => false | MarkOptional } export type Block = { diff --git a/packages/richtext-lexical/src/features/blocks/client/markdown/markdownTransformer.ts b/packages/richtext-lexical/src/features/blocks/client/markdown/markdownTransformer.ts index e7925f974a1..c22db995f2f 100644 --- a/packages/richtext-lexical/src/features/blocks/client/markdown/markdownTransformer.ts +++ b/packages/richtext-lexical/src/features/blocks/client/markdown/markdownTransformer.ts @@ -337,9 +337,9 @@ function getMarkdownTransformerForBlock( } const node = $createBlockNode({ - blockType: block.slug, ...blockFields, - } as any) + blockType: block.slug, + }) if (node) { // Now handle beforeStartLine and afterEndLine. If those are not empty, we need to add them as text nodes before and after the block node. @@ -421,9 +421,9 @@ function getMarkdownTransformerForBlock( } const node = $createBlockNode({ - blockType: block.slug, ...blockFields, - } as any) + blockType: block.slug, + }) if (node) { rootNode.append(node) diff --git a/packages/richtext-lexical/src/features/blocks/server/markdown/markdownTransformer.ts b/packages/richtext-lexical/src/features/blocks/server/markdown/markdownTransformer.ts index bdc5c09573f..654f336d536 100644 --- a/packages/richtext-lexical/src/features/blocks/server/markdown/markdownTransformer.ts +++ b/packages/richtext-lexical/src/features/blocks/server/markdown/markdownTransformer.ts @@ -366,9 +366,9 @@ function getMarkdownTransformerForBlock( } const node = $createServerBlockNode({ - blockType: block.slug, ...blockFields, - } as any) + blockType: block.slug, + }) if (node) { // Now handle beforeStartLine and afterEndLine. If those are not empty, we need to add them as text nodes before and after the block node. @@ -455,9 +455,9 @@ function getMarkdownTransformerForBlock( } const node = $createServerBlockNode({ - blockType: block.slug, ...blockFields, - } as any) + blockType: block.slug, + }) if (node) { rootNode.append(node) diff --git a/packages/richtext-lexical/src/types/nodeTypes.ts b/packages/richtext-lexical/src/types/nodeTypes.ts index ed7d96cd97d..79644303641 100644 --- a/packages/richtext-lexical/src/types/nodeTypes.ts +++ b/packages/richtext-lexical/src/types/nodeTypes.ts @@ -62,8 +62,9 @@ export interface SerializedLineBreakNode { version: number } -export interface SerializedParagraphNode - extends SerializedLexicalElementBase { +export interface SerializedParagraphNode< + TChildren extends SerializedLexicalNode = SerializedLexicalNode, +> extends SerializedLexicalElementBase { textFormat: number textStyle: string type: 'paragraph' From b72b277ed3e3430b0e61806b40385e65e44c8bd0 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Tue, 2 Jun 2026 18:46:54 +0000 Subject: [PATCH 22/56] chore: add more isolated failing test --- test/types/types.spec.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/types/types.spec.ts b/test/types/types.spec.ts index 5ea18c78293..415183f63c9 100644 --- a/test/types/types.spec.ts +++ b/test/types/types.spec.ts @@ -382,6 +382,23 @@ describe('Types testing', () => { expect().type.toBeAssignableWith() }) + test('ensure a relationship node targeting an upload-enabled collection is assignable to the generated node union', () => { + /** + * Minimal reproduction of the single thing that breaks the whole-tree + * assertion above. The generated union contains BOTH a relationship node + * and an upload node, and both can carry `relationTo: 'media'` (since + * `media` is the upload-enabled collection). TypeScript's discriminated- + * union matcher keys on `relationTo`, misroutes the relationship node to + * the upload member (which requires `id`/`fields`), and never retries the + * actual relationship member — so the assignment fails. + * + * Control: the same node targeting a non-upload slug (e.g. 'posts') has no + * colliding upload member and assigns cleanly. + */ + expect().type.toBeAssignableWith>() + expect().type.toBeAssignableWith>() + }) + test('ensure type property in editorState.root.children.push() is correctly typed as union of all node types', () => { const _editorState: DefaultTypedEditorState = null as unknown as DefaultTypedEditorState From 765fd02bb765d98320896c6447a105a99c074604 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Tue, 2 Jun 2026 23:36:37 +0000 Subject: [PATCH 23/56] chore: generated types --- test/types/payload-types.ts | 234 ++++++++++++++++++++++-------------- 1 file changed, 145 insertions(+), 89 deletions(-) diff --git a/test/types/payload-types.ts b/test/types/payload-types.ts index 3024b7de65c..5bb8793c0d3 100644 --- a/test/types/payload-types.ts +++ b/test/types/payload-types.ts @@ -75,36 +75,42 @@ export type SupportedTimezones = | 'Pacific/Fiji'; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_A21938DB". + * via the `definition` "LexicalNodes_2201AD62". */ -export type LexicalNodes_A21938DB = +export type LexicalNodes_2201AD62 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedHorizontalRuleNode - | SerializedUploadNode<'media'> - | SerializedQuoteNode + | { + type: 'upload'; + version: number; + [k: string]: unknown; + } + | SerializedQuoteNode | SerializedRelationshipNode< | 'posts' | 'pages' | 'pages-categories' | 'draft-posts' - | 'payload-kv' | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' | 'payload-locked-documents' | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -112,9 +118,9 @@ export interface Config { pages: Page; 'pages-categories': PagesCategory; 'draft-posts': DraftPost; - media: Media; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -129,9 +135,9 @@ export interface Config { pages: PagesSelect | PagesSelect; 'pages-categories': PagesCategoriesSelect | PagesCategoriesSelect; 'draft-posts': DraftPostsSelect | DraftPostsSelect; - media: MediaSelect | MediaSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -153,7 +159,7 @@ export interface Config { collections: CollectionsWidget; }; strictDraftTypes: true; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -177,6 +183,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts". @@ -184,7 +208,7 @@ export interface UserAuthOperations { export interface Post { id: string; text?: string | null; - richText: LexicalRichText; + richText: LexicalRichText; title?: string | null; selectField: MySelectOptions; insideUnnamedGroup?: string | null; @@ -240,31 +264,57 @@ export interface DraftPost { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "media". + * via the `definition` "users". */ -export interface Media { +export interface User { id: string; - alt?: string | null; updatedAt: string; createdAt: string; - url?: string | null; - thumbnailURL?: string | null; - filename?: string | null; - mimeType?: string | null; - filesize?: number | null; - width?: number | null; - height?: number | null; - focalX?: number | null; - focalY?: number | null; + email: string; + resetPasswordToken?: string | null; + resetPasswordExpiration?: string | null; + salt?: string | null; + hash?: string | null; + loginAttempts?: number | null; + lockUntil?: string | null; + sessions?: + | { + id: string; + createdAt?: string | null; + expiresAt: string; + }[] + | null; + password?: string | null; + collection: 'users'; } /** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". + * via the `definition` "payload-mcp-api-keys". */ -export interface PayloadKv { +export interface PayloadMcpApiKey { id: string; - key: string; - data: + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: | { [k: string]: unknown; } @@ -273,31 +323,29 @@ export interface PayloadKv { | number | boolean | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "users". + * via the `definition` "payload-kv". */ -export interface User { +export interface PayloadKv { id: string; - updatedAt: string; - createdAt: string; - email: string; - resetPasswordToken?: string | null; - resetPasswordExpiration?: string | null; - salt?: string | null; - hash?: string | null; - loginAttempts?: number | null; - lockUntil?: string | null; - sessions?: + key: string; + data: | { - id: string; - createdAt?: string | null; - expiresAt: string; - }[] + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean | null; - password?: string | null; - collection: 'users'; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -322,19 +370,24 @@ export interface PayloadLockedDocument { relationTo: 'draft-posts'; value: string | DraftPost; } | null) - | ({ - relationTo: 'media'; - value: string | Media; - } | null) | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -344,10 +397,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -423,32 +481,6 @@ export interface DraftPostsSelect { createdAt?: T; _status?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "media_select". - */ -export interface MediaSelect { - alt?: T; - updatedAt?: T; - createdAt?: T; - url?: T; - thumbnailURL?: T; - filename?: T; - mimeType?: T; - filesize?: T; - width?: T; - height?: T; - focalX?: T; - focalY?: T; -} -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -471,6 +503,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". From 5106d957ff7a170767cb2f0c26ec4bc01b699e3b Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Tue, 2 Jun 2026 23:39:43 +0000 Subject: [PATCH 24/56] fix import --- test/types/types.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/types/types.spec.ts b/test/types/types.spec.ts index 415183f63c9..920195d6dc2 100644 --- a/test/types/types.spec.ts +++ b/test/types/types.spec.ts @@ -47,7 +47,7 @@ import type { SerializedListItemNode as GenLI, SerializedLinkNode as GenLink, SerializedListNode as GenList, - LexicalNodes_A21938DB as GenNodeUnion, + LexicalNodes_2201AD62 as GenNodeUnion, SerializedParagraphNode as GenParagraph, SerializedQuoteNode as GenQuote, SerializedRelationshipNode as GenRelationship, From 20b46960dd5836ee69ef79bb356634c615398efb Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Wed, 3 Jun 2026 00:38:37 +0000 Subject: [PATCH 25/56] remove invalid written type tests --- test/types/types.spec.ts | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/test/types/types.spec.ts b/test/types/types.spec.ts index 9818c71dfd8..aa9f5579a37 100644 --- a/test/types/types.spec.ts +++ b/test/types/types.spec.ts @@ -377,23 +377,6 @@ describe('Types testing', () => { expect().type.toBeAssignableWith() }) - test('ensure a relationship node targeting an upload-enabled collection is assignable to the generated node union', () => { - /** - * Minimal reproduction of the single thing that breaks the whole-tree - * assertion above. The generated union contains BOTH a relationship node - * and an upload node, and both can carry `relationTo: 'media'` (since - * `media` is the upload-enabled collection). TypeScript's discriminated- - * union matcher keys on `relationTo`, misroutes the relationship node to - * the upload member (which requires `id`/`fields`), and never retries the - * actual relationship member — so the assignment fails. - * - * Control: the same node targeting a non-upload slug (e.g. 'posts') has no - * colliding upload member and assigns cleanly. - */ - expect().type.toBeAssignableWith>() - expect().type.toBeAssignableWith>() - }) - test('ensure type property in editorState.root.children.push() is correctly typed as union of all node types', () => { const _editorState: DefaultTypedEditorState = null as unknown as DefaultTypedEditorState @@ -1085,7 +1068,6 @@ describe('Types testing', () => { const _sdk = new PayloadSDK({ baseURL: '' }) expect[0]['collection']>().type.toBe< | 'draft-posts' - | 'media' | 'pages' | 'pages-categories' | 'payload-kv' @@ -1103,7 +1085,6 @@ describe('Types testing', () => { // ensure collection property of sdk.create has posts in the union type expect[0]['collection']>().type.toBe< | 'draft-posts' - | 'media' | 'pages' | 'pages-categories' | 'payload-kv' From bdc4483b7eeb0a26ee3a594cdb67209508d31312 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Wed, 3 Jun 2026 02:32:35 +0000 Subject: [PATCH 26/56] fix: exclude upload collection slugs in SerializedRelationshipNode --- .../features/relationship/server/schema.ts | 13 ++++- test/lexical/payload-types.ts | 54 +++++++++++++++---- 2 files changed, 56 insertions(+), 11 deletions(-) diff --git a/packages/richtext-lexical/src/features/relationship/server/schema.ts b/packages/richtext-lexical/src/features/relationship/server/schema.ts index 2d0b941c12b..3a5a37c3167 100644 --- a/packages/richtext-lexical/src/features/relationship/server/schema.ts +++ b/packages/richtext-lexical/src/features/relationship/server/schema.ts @@ -1,5 +1,5 @@ import type { JSONSchema4 } from 'json-schema' -import type { CollectionSlug, DataFromCollectionSlug } from 'payload' +import type { CollectionSlug, DataFromCollectionSlug, UploadCollectionSlug } from 'payload' import type { LexicalElementFormat } from '../../../types/nodeTypes.js' import type { JSONSchemaFn } from '../../typesServer.js' @@ -15,7 +15,16 @@ export type RelationshipData = { } }[CollectionSlug] -export type SerializedRelationshipNode = { +/** + * Exclude upload collection slugs. This matches runtime behavior, as well as the json schema. + */ +export type NonUploadCollectionSlug = [Exclude] extends [ + never, +] + ? CollectionSlug + : Exclude + +export type SerializedRelationshipNode = { [TSlug in TSlugs]: { relationTo: TSlug value: DataFromCollectionSlug | number | string diff --git a/test/lexical/payload-types.ts b/test/lexical/payload-types.ts index 1af3963477d..9d5f3320f95 100644 --- a/test/lexical/payload-types.ts +++ b/test/lexical/payload-types.ts @@ -1333,7 +1333,7 @@ export interface Config { }; blocks: { nestedBlock: NestedBlock; - blockWithBlockRef: BlockWithBlockRef; + blockWithBlockRef: BlockWithBlockRef_338FAE2E; }; collections: { 'lexical-benchmark': LexicalBenchmark; @@ -1479,10 +1479,12 @@ export interface NestedBlock { blockType: 'nestedBlock'; } /** + * Multiple blocks resolve to the `BlockWithBlockRef` interface with different fields, so a content hash is appended to keep the generated types stable and unambiguous. Set a unique `interfaceName` on the block to choose the name yourself. See https://payloadcms.com/docs/typescript/generating-types#block-interface-name-collisions + * * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "BlockWithBlockRef". + * via the `definition` "BlockWithBlockRef_338FAE2E". */ -export interface BlockWithBlockRef { +export interface BlockWithBlockRef_338FAE2E { nestedBlocks?: NestedBlock[] | null; id?: string | null; blockName?: string | null; @@ -1776,15 +1778,17 @@ export interface RichTextField { * This select field is rendered here to ensure its options dropdown renders above the rich text toolbar. */ selectHasMany?: ('one' | 'two' | 'three' | 'four' | 'five' | 'six')[] | null; - blocks?: TextBlock[] | null; + blocks?: TextBlock_9A4C1CB0[] | null; updatedAt: string; createdAt: string; } /** + * Multiple blocks resolve to the `TextBlock` interface with different fields, so a content hash is appended to keep the generated types stable and unambiguous. Set a unique `interfaceName` on the block to choose the name yourself. See https://payloadcms.com/docs/typescript/generating-types#block-interface-name-collisions + * * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "TextBlock". + * via the `definition` "TextBlock_9A4C1CB0". */ -export interface TextBlock { +export interface TextBlock_9A4C1CB0 { text?: string | null; id?: string | null; blockName?: string | null; @@ -3306,6 +3310,16 @@ export interface LinkBlock { blockName?: string | null; blockType: 'linkBlock'; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TextBlock". + */ +export interface TextBlock { + id: string; + blockType: 'textBlock'; + blockTitle?: string | null; + blockName?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "LexicalLinkFields_26E8B07E". @@ -3478,6 +3492,18 @@ export interface TextArea { blockName?: string | null; blockType: 'textArea'; } +/** + * Multiple blocks resolve to the `Select` interface with different fields, so a content hash is appended to keep the generated types stable and unambiguous. Set a unique `interfaceName` on the block to choose the name yourself. See https://payloadcms.com/docs/typescript/generating-types#block-interface-name-collisions + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Select_FE424990". + */ +export interface Select_FE424990 { + select?: ('option1' | 'option2' | 'option3' | 'option4' | 'option5') | null; + id?: string | null; + blockName?: string | null; + blockType: 'select'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "SubBlockLexical". @@ -3485,7 +3511,7 @@ export interface TextArea { export interface SubBlockLexical { id: string; blockType: 'subBlockLexical'; - subBlocksLexical?: (ContentBlock | TextArea | Select)[] | null; + subBlocksLexical?: (ContentBlock | TextArea | Select_FE424990)[] | null; blockName?: string | null; } /** @@ -3783,6 +3809,16 @@ export interface BlockWithRichText { nestedRichText?: LexicalRichText | null; blockName?: string | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockWithBlockRef". + */ +export interface BlockWithBlockRef { + id: string; + blockType: 'blockWithBlockRef'; + nestedBlocks?: NestedBlock[] | null; + blockName?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "LexicalLinkFields_D654DD6A". @@ -4003,6 +4039,6 @@ export interface SerializedTableCellNode extends SerializedLexicalEle declare module 'payload' { - // @ts-ignore + // @ts-ignore export interface GeneratedTypes extends Config {} -} \ No newline at end of file +} From 5f0cd13910def8034076d5eb544c5225b49e8b94 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Wed, 3 Jun 2026 03:03:37 +0000 Subject: [PATCH 27/56] fix type tests --- test/types/config.ts | 10 ++++++ test/types/payload-types.ts | 69 +++++++++++++++++++++++++++++-------- test/types/types.spec.ts | 18 +++++----- 3 files changed, 74 insertions(+), 23 deletions(-) diff --git a/test/types/config.ts b/test/types/config.ts index d55fcad17d3..de1902761ee 100644 --- a/test/types/config.ts +++ b/test/types/config.ts @@ -137,6 +137,16 @@ export default buildConfigWithDefaults({ }, ], }, + { + slug: 'media', + upload: true, + fields: [ + { + type: 'text', + name: 'alt', + }, + ], + }, ], admin: { importMap: { diff --git a/test/types/payload-types.ts b/test/types/payload-types.ts index 5bb8793c0d3..b39d80430e7 100644 --- a/test/types/payload-types.ts +++ b/test/types/payload-types.ts @@ -75,20 +75,16 @@ export type SupportedTimezones = | 'Pacific/Fiji'; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_2201AD62". + * via the `definition` "LexicalNodes_99AE542E". */ -export type LexicalNodes_2201AD62 = +export type LexicalNodes_99AE542E = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedHorizontalRuleNode - | { - type: 'upload'; - version: number; - [k: string]: unknown; - } - | SerializedQuoteNode + | SerializedUploadNode<'media'> + | SerializedQuoteNode | SerializedRelationshipNode< | 'posts' | 'pages' @@ -101,11 +97,11 @@ export type LexicalNodes_2201AD62 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; export interface Config { auth: { @@ -118,6 +114,7 @@ export interface Config { pages: Page; 'pages-categories': PagesCategory; 'draft-posts': DraftPost; + media: Media; users: User; 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; @@ -135,6 +132,7 @@ export interface Config { pages: PagesSelect | PagesSelect; 'pages-categories': PagesCategoriesSelect | PagesCategoriesSelect; 'draft-posts': DraftPostsSelect | DraftPostsSelect; + media: MediaSelect | MediaSelect; users: UsersSelect | UsersSelect; 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; @@ -208,7 +206,7 @@ export interface PayloadMcpApiKeyAuthOperations { export interface Post { id: string; text?: string | null; - richText: LexicalRichText; + richText: LexicalRichText; title?: string | null; selectField: MySelectOptions; insideUnnamedGroup?: string | null; @@ -262,6 +260,25 @@ export interface DraftPost { createdAt: string; _status?: ('draft' | 'published') | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "media". + */ +export interface Media { + id: string; + alt?: string | null; + updatedAt: string; + createdAt: string; + url?: string | null; + thumbnailURL?: string | null; + filename?: string | null; + mimeType?: string | null; + filesize?: number | null; + width?: number | null; + height?: number | null; + focalX?: number | null; + focalY?: number | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -370,6 +387,10 @@ export interface PayloadLockedDocument { relationTo: 'draft-posts'; value: string | DraftPost; } | null) + | ({ + relationTo: 'media'; + value: string | Media; + } | null) | ({ relationTo: 'users'; value: string | User; @@ -481,6 +502,24 @@ export interface DraftPostsSelect { createdAt?: T; _status?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "media_select". + */ +export interface MediaSelect { + alt?: T; + updatedAt?: T; + createdAt?: T; + url?: T; + thumbnailURL?: T; + filename?: T; + mimeType?: T; + filesize?: T; + width?: T; + height?: T; + focalX?: T; + focalY?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". diff --git a/test/types/types.spec.ts b/test/types/types.spec.ts index aa9f5579a37..fe275bfc441 100644 --- a/test/types/types.spec.ts +++ b/test/types/types.spec.ts @@ -47,13 +47,11 @@ import type { SerializedListItemNode as GenLI, SerializedLinkNode as GenLink, SerializedListNode as GenList, - LexicalNodes_2201AD62 as GenNodeUnion, + LexicalNodes_99AE542E as GenNodeUnion, SerializedParagraphNode as GenParagraph, SerializedQuoteNode as GenQuote, - SerializedRelationshipNode as GenRelationship, SerializedTabNode as GenTab, SerializedTextNode as GenText, - SerializedUploadNode as GenUpload, Config as LocalConfig, Menu, MyRadioOptions, @@ -1037,14 +1035,16 @@ describe('Types testing', () => { }) test('SerializedRelationshipNode: generated <-> runtime', () => { - type Slugs = keyof LocalConfig['collections'] - expect>().type.toBeAssignableWith() - expect().type.toBeAssignableWith>() + // The relationship node excludes upload collections, so compare against the + // relationship member as it actually appears in the generated union. + type GenRelationshipInUnion = Extract + expect().type.toBeAssignableWith() + expect().type.toBeAssignableWith() }) test('SerializedUploadNode: generated <-> runtime', () => { - // No upload collections in this config — the generated node falls back - // to `{ type: 'upload', version: number, [k]: unknown }`. + // `media` is the upload-enabled collection, so both sides resolve to + // `SerializedUploadNode<'media'>`. type GenUploadInUnion = Extract expect().type.toBeAssignableWith() expect().type.toBeAssignableWith() @@ -1068,6 +1068,7 @@ describe('Types testing', () => { const _sdk = new PayloadSDK({ baseURL: '' }) expect[0]['collection']>().type.toBe< | 'draft-posts' + | 'media' | 'pages' | 'pages-categories' | 'payload-kv' @@ -1085,6 +1086,7 @@ describe('Types testing', () => { // ensure collection property of sdk.create has posts in the union type expect[0]['collection']>().type.toBe< | 'draft-posts' + | 'media' | 'pages' | 'pages-categories' | 'payload-kv' From 8e6fbad4601b1e6cfd91fdc40929edb3a0e69237 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Wed, 3 Jun 2026 04:22:46 +0000 Subject: [PATCH 28/56] fix collision --- packages/payload/src/index.ts | 1 + .../src/utilities/configToJSONSchema.ts | 2 +- .../src/features/blocks/server/schema.ts | 44 ++-- test/lexical/lexical.int.spec.ts | 54 +++- test/lexical/payload-types.ts | 237 ++++++++++++++---- 5 files changed, 260 insertions(+), 78 deletions(-) diff --git a/packages/payload/src/index.ts b/packages/payload/src/index.ts index 461ba3824ec..7ab6a99d54a 100644 --- a/packages/payload/src/index.ts +++ b/packages/payload/src/index.ts @@ -1844,6 +1844,7 @@ export { entityToJSONSchema, type FieldsToJSONSchemaArgs, fieldsToJSONSchema, + registerBlockInterface, withNullableJSONSchemaType, } from './utilities/configToJSONSchema.js' export { createArrayFromCommaDelineated } from './utilities/createArrayFromCommaDelineated.js' diff --git a/packages/payload/src/utilities/configToJSONSchema.ts b/packages/payload/src/utilities/configToJSONSchema.ts index c347598cbb5..eebab58dc75 100644 --- a/packages/payload/src/utilities/configToJSONSchema.ts +++ b/packages/payload/src/utilities/configToJSONSchema.ts @@ -1284,7 +1284,7 @@ const hashBlockSchema = (schema: JSONSchema4): string => * block already uses that name, this one gets a content-hash suffix (`Hero_3F2A1B0C`) so the * two don't overwrite each other. Registering the same block shape again reuses its name. */ -function registerBlockInterface( +export function registerBlockInterface( block: { interfaceName?: string; slug: string }, blockSchema: JSONSchema4, interfaceNameDefinitions: Map, diff --git a/packages/richtext-lexical/src/features/blocks/server/schema.ts b/packages/richtext-lexical/src/features/blocks/server/schema.ts index d8b222f6a08..bdc7a1118f2 100644 --- a/packages/richtext-lexical/src/features/blocks/server/schema.ts +++ b/packages/richtext-lexical/src/features/blocks/server/schema.ts @@ -1,7 +1,7 @@ import type { JSONSchema4 } from 'json-schema' import type { Block, JsonObject } from 'payload' -import { fieldsToJSONSchema, flattenAllFields, toWords } from 'payload' +import { fieldsToJSONSchema, flattenAllFields, registerBlockInterface } from 'payload' import type { LexicalElementFormat } from '../../../types/nodeTypes.js' import type { JSONSchemaArgs, JSONSchemaFn } from '../../typesServer.js' @@ -27,7 +27,7 @@ export type InlineBlockFields = { } & TFields export type SerializedBlockNode = { - fields: { blockName?: string | null; id: string } & Omit + fields: { blockName?: null | string; id: string } & Omit format: LexicalElementFormat type: 'block' version: number @@ -57,20 +57,18 @@ export type SerializedInlineBlockNode = { fields: { id: string } & Omit; };` -/** Block `interfaceName` if set, otherwise a PascalCase form of the slug. */ -const blockFieldsInterfaceName = (block: Block) => block.interfaceName ?? toWords(block.slug, true) - /** * JSON Schema for one block's `fields:` payload. Strips Payload's auto-added * `id`/`blockName` and re-adds them with strict runtime types: required * non-null `id`, optional `blockName?: string | null` (omitted for inline - * blocks). Always registers as a top-level `$ref`. + * blocks). Registers the interface through `registerBlockInterface` (shared with + * payload core) and returns its collision-safe name. */ const buildBlockFieldsSchema = ( block: Block, args: JSONSchemaArgs, { isInlineBlock }: { isInlineBlock: boolean }, -): JSONSchema4 => { +): string => { const flattened = flattenAllFields({ fields: block.fields }) const userFieldsSchema = args.config ? fieldsToJSONSchema({ @@ -110,29 +108,27 @@ const buildBlockFieldsSchema = ( required, } - const definitionName = blockFieldsInterfaceName(block) - args.interfaceNameDefinitions.set(definitionName, fieldsSchema) - return { $ref: `#/definitions/${definitionName}` } + return registerBlockInterface(block, fieldsSchema, args.interfaceNameDefinitions) } export const createBlockNodeJSONSchema = (blockConfigs: Block[]): JSONSchemaFn => (args) => { args.typeStringDefinitions.add(BLOCK_NODES_TS) - const blockFieldsSchemas = blockConfigs.map((block) => + const definitionNames = blockConfigs.map((block) => buildBlockFieldsSchema(block, args, { isInlineBlock: false }), ) const fieldsSchema: JSONSchema4 = - blockFieldsSchemas.length === 0 + definitionNames.length === 0 ? { type: 'object', additionalProperties: true } - : blockFieldsSchemas.length === 1 - ? blockFieldsSchemas[0]! - : { oneOf: blockFieldsSchemas } + : definitionNames.length === 1 + ? { $ref: `#/definitions/${definitionNames[0]!}` } + : { oneOf: definitionNames.map((name) => ({ $ref: `#/definitions/${name}` })) } const tsType = - blockConfigs.length > 0 - ? `SerializedBlockNode<${blockConfigs.map((b) => blockFieldsInterfaceName(b)).join(' | ')}>` + definitionNames.length > 0 + ? `SerializedBlockNode<${definitionNames.join(' | ')}>` : `SerializedBlockNode<{ blockType: string }>` return { @@ -153,20 +149,20 @@ export const createInlineBlockNodeJSONSchema = (inlineBlockConfigs: Block[]): JSONSchemaFn => (args) => { args.typeStringDefinitions.add(BLOCK_NODES_TS) - const blockFieldsSchemas = inlineBlockConfigs.map((block) => + const definitionNames = inlineBlockConfigs.map((block) => buildBlockFieldsSchema(block, args, { isInlineBlock: true }), ) const fieldsSchema: JSONSchema4 = - blockFieldsSchemas.length === 0 + definitionNames.length === 0 ? { type: 'object', additionalProperties: true } - : blockFieldsSchemas.length === 1 - ? blockFieldsSchemas[0]! - : { oneOf: blockFieldsSchemas } + : definitionNames.length === 1 + ? { $ref: `#/definitions/${definitionNames[0]!}` } + : { oneOf: definitionNames.map((name) => ({ $ref: `#/definitions/${name}` })) } const tsType = - inlineBlockConfigs.length > 0 - ? `SerializedInlineBlockNode<${inlineBlockConfigs.map((b) => blockFieldsInterfaceName(b)).join(' | ')}>` + definitionNames.length > 0 + ? `SerializedInlineBlockNode<${definitionNames.join(' | ')}>` : `SerializedInlineBlockNode<{ blockType: string }>` return { diff --git a/test/lexical/lexical.int.spec.ts b/test/lexical/lexical.int.spec.ts index 46ab104d0a4..a4279acfe53 100644 --- a/test/lexical/lexical.int.spec.ts +++ b/test/lexical/lexical.int.spec.ts @@ -2,17 +2,20 @@ import type { SerializedEditorState, SerializedParagraphNode, } from '@payloadcms/richtext-lexical/lexical' -import type { PaginatedDocs, Payload } from 'payload' +import type { Config, PaginatedDocs, Payload } from 'payload' import { + BlocksFeature, buildEditorState, type DefaultNodeTypes, + lexicalEditor, type SerializedBlockNode, type SerializedLinkNode, type SerializedRelationshipNode, type SerializedUploadNode, } from '@payloadcms/richtext-lexical' import path from 'path' +import { configToJSONSchema, sanitizeConfig } from 'payload' import { sanitizeUrl } from 'payload/shared' import { fileURLToPath } from 'url' import { beforeAll, beforeEach, describe, expect, it as vitestIt } from 'vitest' @@ -1267,3 +1270,52 @@ describe('Lexical', () => { }) }) }) + +describe('Lexical block interface generation', () => { + // A lexical block's interface is named after its slug (PascalCase) or its `interfaceName`. + // When two differently-shaped blocks resolve to the same name, each must get its own + // interface — the first keeps the clean name, the second gets a content-hash suffix — so + // neither is silently mistyped. This mirrors payload core's `registerBlockInterface`. + vitestIt( + 'content-hashes a colliding lexical block instead of silently overwriting it', + async () => { + const heroEditor = (fieldName: string, fieldType: 'number' | 'text') => + lexicalEditor({ + features: [ + BlocksFeature({ + blocks: [{ slug: 'hero', fields: [{ name: fieldName, type: fieldType }] }], + }), + ], + }) + + // Two richText fields each define a `hero` block with DIFFERENT fields, so both + // resolve to the `Hero` interface name. + const config = { + collections: [ + { + slug: 'collisionTest', + fields: [ + { name: 'rt1', type: 'richText', editor: heroEditor('title', 'text') }, + { name: 'rt2', type: 'richText', editor: heroEditor('subtitle', 'number') }, + ], + }, + ], + } as unknown as Config + + const sanitizedConfig = await sanitizeConfig(config) + const { jsonSchema } = configToJSONSchema(sanitizedConfig, 'text') + const defs = jsonSchema.definitions! + + // Each differently-shaped `hero` gets its own interface (one clean, one hashed). + const heroNames = Object.keys(defs).filter((k) => /^Hero(_[0-9A-F]{8})?$/.test(k)) + expect(heroNames).toHaveLength(2) + + // ...and they carry distinct field shapes (not a silent overwrite). + const shapeOf = (name: string): string => + Object.keys((defs[name] as { properties: Record }).properties) + .sort() + .join(',') + expect(shapeOf(heroNames[0]!)).not.toBe(shapeOf(heroNames[1]!)) + }, + ) +}) diff --git a/test/lexical/payload-types.ts b/test/lexical/payload-types.ts index 9d5f3320f95..a03e4ad601f 100644 --- a/test/lexical/payload-types.ts +++ b/test/lexical/payload-types.ts @@ -431,22 +431,22 @@ export type LexicalNodes_652244A4 = | SerializedListItemNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_4E96E670". + * via the `definition` "LexicalNodes_62661AA4". */ -export type LexicalNodes_4E96E670 = +export type LexicalNodes_62661AA4 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedBlockNode + | SerializedParagraphNode + | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> - | SerializedHeadingNode + | SerializedHeadingNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedListNode - | SerializedListItemNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -578,16 +578,16 @@ export type LexicalNodes_5BC162BC = | SerializedInlineBlockNode<{blockType: string}>; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_2792F11B". + * via the `definition` "LexicalNodes_ACA183EB". */ -export type LexicalNodes_2792F11B = +export type LexicalNodes_ACA183EB = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode + | SerializedParagraphNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode | SerializedBlockNode< | ValidationBlock | FilterOptionsBlock @@ -602,9 +602,9 @@ export type LexicalNodes_2792F11B = | LexicalBlocksRadioButtonsBlock | ConditionalLayout | TabBlock - | Code + | Code_5DA82017 | NoBlockName - | MyBlock + | MyBlock_0B02E2CC | MyBlockWithLabel | MyBlockWithBlock | BlockRSC @@ -612,16 +612,16 @@ export type LexicalNodes_2792F11B = > | SerializedInlineBlockNode< | AvatarGroupBlock - | MyInlineBlock + | MyInlineBlock_FAB42262 | MyInlineBlockWithLabel | MyInlineBlockWithBlock | MyInlineBlockWithBlockAndLabel > | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -658,9 +658,9 @@ export type LexicalNodes_2792F11B = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "LexicalNodes_423CFDD8". @@ -1270,25 +1270,25 @@ export type LexicalNodes_D654DD6A = | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_A0A0A55E". + * via the `definition` "LexicalNodes_2A841A08". */ -export type LexicalNodes_A0A0A55E = +export type LexicalNodes_2A841A08 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode - | SerializedBlockNode + | SerializedParagraphNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode + | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> - | SerializedHeadingNode + | SerializedHeadingNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedListNode - | SerializedListItemNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1574,7 +1574,7 @@ export interface LexicalJsxConverter { export interface LexicalField { id: string; title: string; - lexicalRootEditor?: LexicalRichText | null; + lexicalRootEditor?: LexicalRichText | null; /** * A simple lexical field */ @@ -1582,7 +1582,7 @@ export interface LexicalField { /** * Should not be rendered */ - lexicalWithBlocks: LexicalRichText; + lexicalWithBlocks: LexicalRichText; lexicalWithBlocks_markdown?: string | null; updatedAt: string; createdAt: string; @@ -1678,7 +1678,7 @@ export interface LexicalLocalizedField { */ export interface LexicalObjectReferenceBug { id: string; - lexicalDefault?: LexicalRichText | null; + lexicalDefault?: LexicalRichText | null; lexicalEditor?: LexicalRichText | null; updatedAt: string; createdAt: string; @@ -2021,7 +2021,7 @@ export interface OnDemandOutsideForm { | number | boolean | null; - hiddenAnchor?: LexicalRichText | null; + hiddenAnchor?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -3246,7 +3246,93 @@ export interface BenchBlock30 { */ export interface Code { id: string; - blockType: 'code'; + blockType: 'Code'; + language?: + | ( + | 'abap' + | 'apex' + | 'azcli' + | 'bat' + | 'bicep' + | 'cameligo' + | 'clojure' + | 'coffee' + | 'cpp' + | 'csharp' + | 'csp' + | 'css' + | 'cypher' + | 'dart' + | 'dockerfile' + | 'ecl' + | 'elixir' + | 'flow9' + | 'freemarker2' + | 'fsharp' + | 'go' + | 'graphql' + | 'handlebars' + | 'hcl' + | 'html' + | 'ini' + | 'java' + | 'javascript' + | 'julia' + | 'kotlin' + | 'less' + | 'lexon' + | 'liquid' + | 'lua' + | 'm3' + | 'markdown' + | 'mdx' + | 'mips' + | 'msdax' + | 'mysql' + | 'objective-c' + | 'pascal' + | 'pascaligo' + | 'perl' + | 'pgsql' + | 'php' + | 'pla' + | 'plaintext' + | 'postiats' + | 'powerquery' + | 'powershell' + | 'protobuf' + | 'pug' + | 'python' + | 'qsharp' + | 'r' + | 'razor' + | 'redis' + | 'redshift' + | 'restructuredtext' + | 'ruby' + | 'rust' + | 'sb' + | 'scala' + | 'scheme' + | 'scss' + | 'shell' + | 'solidity' + | 'sophia' + | 'sparql' + | 'sql' + | 'st' + | 'swift' + | 'systemverilog' + | 'tcl' + | 'twig' + | 'typescript' + | 'typespec' + | 'vb' + | 'wgsl' + | 'xml' + | 'yaml' + ) + | null; code?: string | null; blockName?: string | null; } @@ -3269,8 +3355,6 @@ export interface MyBlock { id: string; blockType: 'myBlock'; someText?: string | null; - someTextRequired: string; - radios?: ('option1' | 'option2' | 'option3') | null; blockName?: string | null; } /** @@ -3280,7 +3364,7 @@ export interface MyBlock { export interface MyInlineBlock { id: string; blockType: 'myInlineBlock'; - key?: ('value1' | 'value2' | 'value3') | null; + someText?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3370,11 +3454,25 @@ export interface Block { blockName?: string | null; blockType: 'block'; } +/** + * Multiple blocks resolve to the `MyBlock` interface with different fields, so a content hash is appended to keep the generated types stable and unambiguous. Set a unique `interfaceName` on the block to choose the name yourself. See https://payloadcms.com/docs/typescript/generating-types#block-interface-name-collisions + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock_89EF3EA7". + */ +export interface MyBlock_89EF3EA7 { + id: string; + blockType: 'myBlock'; + someText?: string | null; + someTextRequired: string; + radios?: ('option1' | 'option2' | 'option3') | null; + blockName?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_4E96E670". + * via the `definition` "LexicalLinkFields_62661AA4". */ -export interface LexicalLinkFields_4E96E670 { +export interface LexicalLinkFields_62661AA4 { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3595,6 +3693,18 @@ export interface TabBlock { }; blockName?: string | null; } +/** + * Multiple blocks resolve to the `Code` interface with different fields, so a content hash is appended to keep the generated types stable and unambiguous. Set a unique `interfaceName` on the block to choose the name yourself. See https://payloadcms.com/docs/typescript/generating-types#block-interface-name-collisions + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Code_5DA82017". + */ +export interface Code_5DA82017 { + id: string; + blockType: 'code'; + code?: string | null; + blockName?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "NoBlockName". @@ -3605,6 +3715,18 @@ export interface NoBlockName { text?: string | null; blockName?: string | null; } +/** + * Multiple blocks resolve to the `MyBlock` interface with different fields, so a content hash is appended to keep the generated types stable and unambiguous. Set a unique `interfaceName` on the block to choose the name yourself. See https://payloadcms.com/docs/typescript/generating-types#block-interface-name-collisions + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock_0B02E2CC". + */ +export interface MyBlock_0B02E2CC { + id: string; + blockType: 'myBlock'; + key?: ('value1' | 'value2' | 'value3') | null; + blockName?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "MyBlockWithLabel". @@ -3659,6 +3781,17 @@ export interface AvatarGroupBlock { }[] | null; } +/** + * Multiple blocks resolve to the `MyInlineBlock` interface with different fields, so a content hash is appended to keep the generated types stable and unambiguous. Set a unique `interfaceName` on the block to choose the name yourself. See https://payloadcms.com/docs/typescript/generating-types#block-interface-name-collisions + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyInlineBlock_FAB42262". + */ +export interface MyInlineBlock_FAB42262 { + id: string; + blockType: 'myInlineBlock'; + key?: ('value1' | 'value2' | 'value3') | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "MyInlineBlockWithLabel". @@ -3688,9 +3821,9 @@ export interface MyInlineBlockWithBlockAndLabel { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_2792F11B". + * via the `definition` "LexicalLinkFields_ACA183EB". */ -export interface LexicalLinkFields_2792F11B { +export interface LexicalLinkFields_ACA183EB { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3844,9 +3977,9 @@ export interface LexicalLinkFields_D654DD6A { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_A0A0A55E". + * via the `definition` "LexicalLinkFields_2A841A08". */ -export interface LexicalLinkFields_A0A0A55E { +export interface LexicalLinkFields_2A841A08 { linkType: 'custom' | 'internal'; url?: string; doc?: { From 15ea5e88441e1740a137ec377057a5de9a2c6a87 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Wed, 3 Jun 2026 04:24:02 +0000 Subject: [PATCH 29/56] lint --- packages/payload/src/admin/RichText.ts | 14 +++++++++----- .../collections/operations/local/duplicate.ts | 7 +++++-- .../src/collections/operations/local/find.ts | 18 ++++++++++-------- .../collections/operations/local/findByID.ts | 5 +---- .../operations/local/findVersionByID.ts | 9 +++------ .../operations/local/findVersions.ts | 9 +++------ .../operations/local/restoreVersion.ts | 9 +++------ .../src/globals/operations/local/findOne.ts | 12 ++++++------ .../src/globals/operations/local/update.ts | 7 +++++-- packages/payload/src/index.ts | 2 +- 10 files changed, 46 insertions(+), 46 deletions(-) diff --git a/packages/payload/src/admin/RichText.ts b/packages/payload/src/admin/RichText.ts index 4e5f92491e4..54825b26ec5 100644 --- a/packages/payload/src/admin/RichText.ts +++ b/packages/payload/src/admin/RichText.ts @@ -251,13 +251,17 @@ type RichTextAdapterBase< * payload-types.ts) */ jsonSchema?: ( - args: Pick< - FieldsToJSONSchemaArgs, - 'collectionIDFieldTypes' | 'config' | 'i18n' | 'interfaceNameDefinitions' | 'typeStringDefinitions' - > & { + args: { field: RichTextField isRequired: boolean - }, + } & Pick< + FieldsToJSONSchemaArgs, + | 'collectionIDFieldTypes' + | 'config' + | 'i18n' + | 'interfaceNameDefinitions' + | 'typeStringDefinitions' + >, ) => JSONSchema4 /** * Provide validation function for the richText field. This function is run the same way diff --git a/packages/payload/src/collections/operations/local/duplicate.ts b/packages/payload/src/collections/operations/local/duplicate.ts index bb2cf260357..8572edaae8a 100644 --- a/packages/payload/src/collections/operations/local/duplicate.ts +++ b/packages/payload/src/collections/operations/local/duplicate.ts @@ -89,8 +89,11 @@ type BaseOptions = { user?: Document } & Pick, 'select'> -export type Options = - BaseOptions & DraftFlagFromCollectionSlug +export type Options = BaseOptions< + TSlug, + TSelect +> & + DraftFlagFromCollectionSlug export async function duplicateLocal< TSlug extends CollectionSlug, diff --git a/packages/payload/src/collections/operations/local/find.ts b/packages/payload/src/collections/operations/local/find.ts index 6688ad21bfc..bf63ddabae5 100644 --- a/packages/payload/src/collections/operations/local/find.ts +++ b/packages/payload/src/collections/operations/local/find.ts @@ -20,10 +20,7 @@ import type { Where, } from '../../../types/index.js' import type { CreateLocalReqOptions } from '../../../utilities/createLocalReq.js' -import type { - DraftFlagFromCollectionSlug, - SelectFromCollectionSlug, -} from '../../config/types.js' +import type { DraftFlagFromCollectionSlug, SelectFromCollectionSlug } from '../../config/types.js' import { APIError } from '../../../errors/index.js' import { createLocalReq } from '../../../utilities/createLocalReq.js' @@ -180,12 +177,17 @@ type BaseFindOptions = where?: Where } -export type Options = - BaseFindOptions & DraftFlagFromCollectionSlug +export type Options = BaseFindOptions< + TSlug, + TSelect +> & + DraftFlagFromCollectionSlug // Backward compatibility export -export type FindOptions = - Options +export type FindOptions = Options< + TSlug, + TSelect +> export async function findLocal< TSlug extends CollectionSlug, diff --git a/packages/payload/src/collections/operations/local/findByID.ts b/packages/payload/src/collections/operations/local/findByID.ts index 7788002c780..1ca4eec413c 100644 --- a/packages/payload/src/collections/operations/local/findByID.ts +++ b/packages/payload/src/collections/operations/local/findByID.ts @@ -16,10 +16,7 @@ import type { TransformCollectionWithSelect, } from '../../../types/index.js' import type { CreateLocalReqOptions } from '../../../utilities/createLocalReq.js' -import type { - DraftFlagFromCollectionSlug, - SelectFromCollectionSlug, -} from '../../config/types.js' +import type { DraftFlagFromCollectionSlug, SelectFromCollectionSlug } from '../../config/types.js' import { APIError } from '../../../errors/index.js' import { createLocalReq } from '../../../utilities/createLocalReq.js' diff --git a/packages/payload/src/collections/operations/local/findVersionByID.ts b/packages/payload/src/collections/operations/local/findVersionByID.ts index d8aeb6a9924..5e1f4420245 100644 --- a/packages/payload/src/collections/operations/local/findVersionByID.ts +++ b/packages/payload/src/collections/operations/local/findVersionByID.ts @@ -8,10 +8,7 @@ import type { import type { Document, PayloadRequest, PopulateType, SelectType } from '../../../types/index.js' import type { CreateLocalReqOptions } from '../../../utilities/createLocalReq.js' import type { TypeWithVersion } from '../../../versions/types.js' -import type { - DataFromCollectionSlug, - DraftFlagFromCollectionSlug, -} from '../../config/types.js' +import type { DataFromCollectionSlug, DraftFlagFromCollectionSlug } from '../../config/types.js' import { APIError } from '../../../errors/index.js' import { createLocalReq } from '../../../utilities/createLocalReq.js' @@ -86,8 +83,8 @@ type BaseOptions = { user?: Document } & Pick, 'select'> -export type Options = - BaseOptions & DraftFlagFromCollectionSlug +export type Options = BaseOptions & + DraftFlagFromCollectionSlug export async function findVersionByIDLocal( payload: Payload, diff --git a/packages/payload/src/collections/operations/local/findVersions.ts b/packages/payload/src/collections/operations/local/findVersions.ts index 23090cebb6d..9ff18dc84ea 100644 --- a/packages/payload/src/collections/operations/local/findVersions.ts +++ b/packages/payload/src/collections/operations/local/findVersions.ts @@ -16,10 +16,7 @@ import type { } from '../../../types/index.js' import type { CreateLocalReqOptions } from '../../../utilities/createLocalReq.js' import type { TypeWithVersion } from '../../../versions/types.js' -import type { - DataFromCollectionSlug, - DraftFlagFromCollectionSlug, -} from '../../config/types.js' +import type { DataFromCollectionSlug, DraftFlagFromCollectionSlug } from '../../config/types.js' import { APIError } from '../../../errors/index.js' import { createLocalReq } from '../../../utilities/createLocalReq.js' @@ -111,8 +108,8 @@ type BaseOptions = { where?: Where } & Pick, 'select'> -export type Options = - BaseOptions & DraftFlagFromCollectionSlug +export type Options = BaseOptions & + DraftFlagFromCollectionSlug export async function findVersionsLocal( payload: Payload, diff --git a/packages/payload/src/collections/operations/local/restoreVersion.ts b/packages/payload/src/collections/operations/local/restoreVersion.ts index 7e78128bb07..3e9def9cae2 100644 --- a/packages/payload/src/collections/operations/local/restoreVersion.ts +++ b/packages/payload/src/collections/operations/local/restoreVersion.ts @@ -7,10 +7,7 @@ import type { } from '../../../index.js' import type { Document, PayloadRequest, PopulateType, SelectType } from '../../../types/index.js' import type { CreateLocalReqOptions } from '../../../utilities/createLocalReq.js' -import type { - DataFromCollectionSlug, - DraftFlagFromCollectionSlug, -} from '../../config/types.js' +import type { DataFromCollectionSlug, DraftFlagFromCollectionSlug } from '../../config/types.js' import { APIError } from '../../../errors/index.js' import { createLocalReq } from '../../../utilities/createLocalReq.js' @@ -71,8 +68,8 @@ type BaseOptions = { user?: Document } & Pick, 'select'> -export type Options = - BaseOptions & DraftFlagFromCollectionSlug +export type Options = BaseOptions & + DraftFlagFromCollectionSlug export async function restoreVersionLocal( payload: Payload, diff --git a/packages/payload/src/globals/operations/local/findOne.ts b/packages/payload/src/globals/operations/local/findOne.ts index 70bd720ad5c..2ed4d944951 100644 --- a/packages/payload/src/globals/operations/local/findOne.ts +++ b/packages/payload/src/globals/operations/local/findOne.ts @@ -14,10 +14,7 @@ import type { TransformGlobalWithSelect, } from '../../../types/index.js' import type { CreateLocalReqOptions } from '../../../utilities/createLocalReq.js' -import type { - DraftFlagFromGlobalSlug, - SelectFromGlobalSlug, -} from '../../config/types.js' +import type { DraftFlagFromGlobalSlug, SelectFromGlobalSlug } from '../../config/types.js' import { APIError } from '../../../errors/index.js' import { createLocalReq } from '../../../utilities/createLocalReq.js' @@ -92,8 +89,11 @@ type BaseFindOneOptions = } & Pick, 'select'> & Pick -export type Options = - BaseFindOneOptions & DraftFlagFromGlobalSlug +export type Options = BaseFindOneOptions< + TSlug, + TSelect +> & + DraftFlagFromGlobalSlug export async function findOneGlobalLocal< TSlug extends GlobalSlug, diff --git a/packages/payload/src/globals/operations/local/update.ts b/packages/payload/src/globals/operations/local/update.ts index b6b8053201f..850c6677139 100644 --- a/packages/payload/src/globals/operations/local/update.ts +++ b/packages/payload/src/globals/operations/local/update.ts @@ -101,8 +101,11 @@ type BaseOptions = { user?: Document } & Pick, 'select'> -export type Options = - BaseOptions & DraftFlagFromGlobalSlug +export type Options = BaseOptions< + TSlug, + TSelect +> & + DraftFlagFromGlobalSlug export async function updateGlobalLocal< TSlug extends GlobalSlug, diff --git a/packages/payload/src/index.ts b/packages/payload/src/index.ts index 7ab6a99d54a..432bd5ce2fe 100644 --- a/packages/payload/src/index.ts +++ b/packages/payload/src/index.ts @@ -1842,8 +1842,8 @@ export { commitTransaction } from './utilities/commitTransaction.js' export { configToJSONSchema, entityToJSONSchema, - type FieldsToJSONSchemaArgs, fieldsToJSONSchema, + type FieldsToJSONSchemaArgs, registerBlockInterface, withNullableJSONSchemaType, } from './utilities/configToJSONSchema.js' From 58fd9eefd39a4f3780148714c96100e2d3e2e47d Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Wed, 3 Jun 2026 04:46:40 +0000 Subject: [PATCH 30/56] docs: update v4 breaking changes guide --- docs/migration-guide/v4.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/migration-guide/v4.mdx b/docs/migration-guide/v4.mdx index 09e68f14d09..8416165cf1b 100644 --- a/docs/migration-guide/v4.mdx +++ b/docs/migration-guide/v4.mdx @@ -562,7 +562,7 @@ When two **different** blocks resolve to the same auto-derived name (same slug, `richText` fields backed by `lexicalEditor` used to emit a permissive `{ [k: string]: unknown }` per field. They now emit a discriminated union of strict per-node interfaces (`SerializedTextNode`, `SerializedParagraphNode`, `SerializedHeadingNode`, `SerializedBlockNode`, etc.) under a hash-named alias like `LexicalNodes_AB12CD34`. -Block nodes always come through as `SerializedBlockNode` / `SerializedInlineBlockNode` referencing the per-block interface (see the `block.interfaceName` change above). Their auto-added `id`/`blockName` tighten from `id?: string | null` / `blockName?: string | null` to `id: string` / `blockName: string | null` to match what's actually stored. +Block nodes come through as `SerializedBlockNode` / `SerializedInlineBlockNode` referencing the per-block interface (see the `block.interfaceName` change above). The auto-added `id` is now required (`id: string`), since a stored lexical block always has one. Code that imported field types from `payload-types.ts` and cast through `unknown` may now type-check tighter and surface real bugs. From cb02871efd3fee2edfa9d1961315c5f58662091d Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Wed, 3 Jun 2026 05:36:10 +0000 Subject: [PATCH 31/56] declare $schema --- packages/payload/src/utilities/configToJSONSchema.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/payload/src/utilities/configToJSONSchema.ts b/packages/payload/src/utilities/configToJSONSchema.ts index eebab58dc75..36a8f5fd8f3 100644 --- a/packages/payload/src/utilities/configToJSONSchema.ts +++ b/packages/payload/src/utilities/configToJSONSchema.ts @@ -1456,6 +1456,7 @@ export function configToJSONSchema( } let jsonSchema: JSONSchema4 = { + $schema: 'http://json-schema.org/draft-07/schema#', additionalProperties: false, definitions: { supportedTimezones: timezoneDefinitions, From f57cf358aedae390f27adb67c87637739e3107d7 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Wed, 3 Jun 2026 07:19:16 +0000 Subject: [PATCH 32/56] fix: ensure the json schema we pass to the mcp server is self-contained and does not contain dangling references to definitions we don't pass to it --- packages/payload/src/index.ts | 1 + .../src/utilities/configToJSONSchema.spec.ts | 64 +++++++++++++++++- .../src/utilities/configToJSONSchema.ts | 67 +++++++++++++++++++ packages/plugin-mcp/src/mcp/buildMcpServer.ts | 33 +++++---- .../simplifyRelationshipFields.ts | 11 +++ test/lexical/payload-types.ts | 4 +- 6 files changed, 163 insertions(+), 17 deletions(-) diff --git a/packages/payload/src/index.ts b/packages/payload/src/index.ts index 432bd5ce2fe..851dda655df 100644 --- a/packages/payload/src/index.ts +++ b/packages/payload/src/index.ts @@ -1842,6 +1842,7 @@ export { commitTransaction } from './utilities/commitTransaction.js' export { configToJSONSchema, entityToJSONSchema, + entityToStandaloneJSONSchema, fieldsToJSONSchema, type FieldsToJSONSchemaArgs, registerBlockInterface, diff --git a/packages/payload/src/utilities/configToJSONSchema.spec.ts b/packages/payload/src/utilities/configToJSONSchema.spec.ts index 9156b1083fd..715ffbbb6f1 100644 --- a/packages/payload/src/utilities/configToJSONSchema.spec.ts +++ b/packages/payload/src/utilities/configToJSONSchema.spec.ts @@ -4,7 +4,7 @@ import { describe, it, expect } from 'vitest' import type { Config } from '../config/types.js' import { sanitizeConfig } from '../config/sanitize.js' -import { configToJSONSchema } from './configToJSONSchema.js' +import { configToJSONSchema, entityToStandaloneJSONSchema } from './configToJSONSchema.js' import type { Block, BlocksField, RichTextField } from '../fields/config/types.js' describe('configToJSONSchema', () => { @@ -543,4 +543,66 @@ describe('configToJSONSchema', () => { expect(grpBlocksInline).not.toHaveProperty('$ref') expect(grpBlocksInline.properties?.blockType).toStrictEqual({ const: 'myBlock' }) }) + + it('entityToStandaloneJSONSchema bundles only the definitions an entity references', async () => { + const sharedBlock: Block = { + slug: 'sharedBlock', + interfaceName: 'SharedBlock', + fields: [{ name: 'title', type: 'text' }], + } + + // @ts-expect-error partial config + const config: Config = { + admin: { + timezones: { + supportedTimezones: [ + { label: 'UTC', value: 'UTC' }, + { label: 'New York', value: 'America/New_York' }, + ], + }, + }, + blocks: [sharedBlock], + collections: [ + { + slug: 'with-refs', + fields: [ + { name: 'layout', type: 'blocks', blockReferences: ['sharedBlock'], blocks: [] }, + { name: 'when', type: 'date', timezone: true }, + ], + timestamps: false, + }, + { + slug: 'other', + fields: [{ name: 'title', type: 'text' }], + timestamps: false, + }, + ], + } + + const sanitizedConfig = await sanitizeConfig(config) + const entity = sanitizedConfig.collections.find( + (collection) => collection.slug === 'with-refs', + )! + + const schema = entityToStandaloneJSONSchema({ + config: sanitizedConfig, + defaultIDType: 'text', + entity, + }) + + // Has its own $schema, so it resolves on its own. + expect(schema.$schema).toBe('http://json-schema.org/draft-07/schema#') + + // The block reference is resolved inline, so it can't dangle. + const layoutItems = (schema.properties?.layout as JSONSchema4)?.items as JSONSchema4 + const inlinedBlock = (layoutItems?.oneOf?.[0] ?? {}) as JSONSchema4 + expect(inlinedBlock.properties?.blockType).toStrictEqual({ const: 'sharedBlock' }) + expect(inlinedBlock.properties?.title).toBeDefined() + + // A timezone field pulls in supportedTimezones from the root config. + expect(schema.definitions?.supportedTimezones).toBeDefined() + + // Doesn't pull in unrelated collections. + expect(schema.definitions?.other).toBeUndefined() + }) }) diff --git a/packages/payload/src/utilities/configToJSONSchema.ts b/packages/payload/src/utilities/configToJSONSchema.ts index 36a8f5fd8f3..245880f151d 100644 --- a/packages/payload/src/utilities/configToJSONSchema.ts +++ b/packages/payload/src/utilities/configToJSONSchema.ts @@ -995,6 +995,72 @@ export function entityToJSONSchema( return jsonSchema } +/** + * Like {@link entityToJSONSchema}, but returns a standalone schema for one collection or global: + * the entity plus only the `definitions` it actually uses, so it resolves on its own rather than + * as part of the whole config schema. + * + * Relationship/upload `$ref`s to other collections are left in place - the caller handles those. + */ +export function entityToStandaloneJSONSchema({ + config, + defaultIDType, + entity, + i18n, +}: { + config: SanitizedConfig + defaultIDType: 'number' | 'text' + entity: SanitizedCollectionConfig | SanitizedGlobalConfig + i18n?: I18n +}): JSONSchema4 { + const definitions = new Map() + + // entityToJSONSchema fills `definitions` with everything the fields reference (node unions, blocks). + const schema = entityToJSONSchema( + config, + entity, + definitions, + defaultIDType, + new Set(), + undefined, + i18n, + true, // forceInlineBlocks + ) + + // Timezone fields `$ref` supportedTimezones, which lives on the root config schema, so add it here. + const supportedTimezones = config.admin?.timezones?.supportedTimezones + if ( + supportedTimezones?.length && + schemaHasRef([schema, ...definitions.values()], '#/definitions/supportedTimezones') + ) { + definitions.set('supportedTimezones', timezonesToJSONSchema(supportedTimezones)) + } + + return { + $schema: 'http://json-schema.org/draft-07/schema#', + ...schema, + definitions: Object.fromEntries(definitions), + } +} + +/** + * Recursive function that returns true if + * `node` has a `$ref` to `ref` somewhere inside it. + * */ +function schemaHasRef(node: unknown, ref: string): boolean { + if (Array.isArray(node)) { + return node.some((child) => schemaHasRef(child, ref)) + } + if (node && typeof node === 'object') { + const obj = node as Record + if (obj.$ref === ref) { + return true + } + return Object.values(obj).some((value) => schemaHasRef(value, ref)) + } + return false +} + export function fieldsToSelectJSONSchema({ config, fields, @@ -1456,6 +1522,7 @@ export function configToJSONSchema( } let jsonSchema: JSONSchema4 = { + // draft-07 so consumers resolve `#/definitions/...` refs (the default assumes 2020-12 / `$defs`) $schema: 'http://json-schema.org/draft-07/schema#', additionalProperties: false, definitions: { diff --git a/packages/plugin-mcp/src/mcp/buildMcpServer.ts b/packages/plugin-mcp/src/mcp/buildMcpServer.ts index 677839d895d..83dc2117ceb 100644 --- a/packages/plugin-mcp/src/mcp/buildMcpServer.ts +++ b/packages/plugin-mcp/src/mcp/buildMcpServer.ts @@ -1,5 +1,5 @@ import { McpServer, type ServerContext } from '@modelcontextprotocol/server' -import { APIError, configToJSONSchema, type PayloadRequest } from 'payload' +import { APIError, entityToStandaloneJSONSchema, type PayloadRequest } from 'payload' import type { AuthorizedMCP, @@ -64,13 +64,6 @@ export const buildMcpServer = ({ return rest } - const { jsonSchema: configSchema } = configToJSONSchema( - req.payload.config, - req.payload.db.defaultIDType, - req.i18n, - { forceInlineBlocks: true }, - ) as { jsonSchema: JsonSchemaType; typeStringDefinitions: Set } - try { for (const item of authorizedMCP.items) { switch (item.type) { @@ -79,15 +72,20 @@ export const buildMcpServer = ({ const name = wireName(item.key, item.collectionSlug) let inputSchema = tool.input if (typeof inputSchema === 'function') { - const raw = configSchema.definitions?.[item.collectionSlug] - if (!raw) { + const collection = req.payload.collections[item.collectionSlug]?.config + if (!collection) { throw new APIError( `Collection schema not found for slug: ${item.collectionSlug}`, 500, ) } const collectionSchema = removeVirtualFieldsFromSchema( - JSON.parse(JSON.stringify(raw)) as JsonSchemaType, + entityToStandaloneJSONSchema({ + config: req.payload.config, + defaultIDType: req.payload.db.defaultIDType, + entity: collection, + i18n: req.i18n, + }) as unknown as JsonSchemaType, getCollectionVirtualFieldNames(req.payload.config, item.collectionSlug), ) inputSchema = inputSchema({ collectionSchema }) @@ -118,12 +116,19 @@ export const buildMcpServer = ({ const name = wireName(item.key, item.globalSlug) let inputSchema = tool.input if (typeof inputSchema === 'function') { - const raw = configSchema.definitions?.[item.globalSlug] - if (!raw) { + const globalEntity = req.payload.config.globals.find( + (globalConfig) => globalConfig.slug === item.globalSlug, + ) + if (!globalEntity) { throw new APIError(`Global schema not found for slug: ${item.globalSlug}`, 500) } const globalSchema = removeVirtualFieldsFromSchema( - JSON.parse(JSON.stringify(raw)) as JsonSchemaType, + entityToStandaloneJSONSchema({ + config: req.payload.config, + defaultIDType: req.payload.db.defaultIDType, + entity: globalEntity, + i18n: req.i18n, + }) as unknown as JsonSchemaType, getGlobalVirtualFieldNames(req.payload.config, item.globalSlug), ) diff --git a/packages/plugin-mcp/src/utils/schemaConversion/simplifyRelationshipFields.ts b/packages/plugin-mcp/src/utils/schemaConversion/simplifyRelationshipFields.ts index 5ddf8e4e7f6..3d3d107fe7b 100644 --- a/packages/plugin-mcp/src/utils/schemaConversion/simplifyRelationshipFields.ts +++ b/packages/plugin-mcp/src/utils/schemaConversion/simplifyRelationshipFields.ts @@ -66,5 +66,16 @@ export function simplifyRelationshipFields(schema: JsonSchemaType): JsonSchemaTy processed.items = simplifyRelationshipFields(processed.items) } + // Also walk `definitions`: lexical node unions and blocks live there, and their relationship + // fields point at collections that aren't bundled. Simplifying them drops those refs to IDs. + if (processed.definitions && typeof processed.definitions === 'object') { + processed.definitions = Object.fromEntries( + Object.entries(processed.definitions).map(([key, value]) => [ + key, + typeof value === 'object' ? simplifyRelationshipFields(value) : value, + ]), + ) + } + return processed } diff --git a/test/lexical/payload-types.ts b/test/lexical/payload-types.ts index a03e4ad601f..3fb6b4f4a35 100644 --- a/test/lexical/payload-types.ts +++ b/test/lexical/payload-types.ts @@ -4172,6 +4172,6 @@ export interface SerializedTableCellNode extends SerializedLexicalEle declare module 'payload' { - // @ts-ignore + // @ts-ignore export interface GeneratedTypes extends Config {} -} +} \ No newline at end of file From ff4fd4bffd20c27d2ad53c2ba1104d6e1d9d570a Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Wed, 3 Jun 2026 08:08:42 +0000 Subject: [PATCH 33/56] breaking changes doc --- docs/migration-guide/v4.mdx | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/docs/migration-guide/v4.mdx b/docs/migration-guide/v4.mdx index 8416165cf1b..5899e5e4c24 100644 --- a/docs/migration-guide/v4.mdx +++ b/docs/migration-guide/v4.mdx @@ -502,17 +502,17 @@ Inserted at position 5 (between `defaultIDType` and `collectionIDFieldTypes`). T ) ``` -### Lexical: `modifyOutputSchema` is gone +### Lexical: `modifyJSONSchema` is gone -`generatedTypes.modifyOutputSchema` on lexical features (and `modifyOutputSchemas`) is removed. Features now contribute per-node JSON Schemas via `createNode({ jsonSchema, node })` instead of mutating a whole-field schema after the fact. The editor composes per-node schemas into the field's union automatically. +`generatedTypes.modifyJSONSchema` on lexical features (and the sanitized `modifyJSONSchemas` array) is removed. Features now contribute per-node JSON Schemas via `createNode({ jsonSchema, node })` instead of mutating a whole-field schema after the fact. The editor composes per-node schemas into the field's union automatically. -If you wrote a custom feature that overrode `modifyOutputSchema`, move per-node generation into `createNode({ jsonSchema: ... })`: +If you wrote a custom feature that overrode `modifyJSONSchema`, move per-node generation into `createNode({ jsonSchema: ... })`: ```diff export const MyFeature = createServerFeature({ feature: () => ({ - generatedTypes: { -- modifyOutputSchema: ({ currentSchema, interfaceNameDefinitions }) => { +- modifyJSONSchema: ({ currentSchema, interfaceNameDefinitions }) => { - // ... mutate currentSchema or interfaceNameDefinitions ... - return currentSchema - }, @@ -566,6 +566,27 @@ Block nodes come through as `SerializedBlockNode` / `SerializedInlineBl Code that imported field types from `payload-types.ts` and cast through `unknown` may now type-check tighter and surface real bugs. +The hand-written `TypedEditorState` / `DefaultTypedEditorState` helpers (used to type rich text in converters, custom renderers, and so on) got stricter to match. `TypedEditorState` dropped the `{ [k: string]: unknown }` at the editor-state root, and a node's `children` are now the real node union at any depth — they used to fall back to the loose `SerializedLexicalNode`. Runtime data is unchanged, but narrow by `node.type` where you read nested nodes loosely. + +Element nodes are now generic over their `children`, and you pass the node union into them yourself (previously `TypedEditorState` did this for you via an internal `RecursiveNodes` helper): + +```diff + import type { + SerializedParagraphNode, + SerializedTextNode, + TypedEditorState, + } from '@payloadcms/richtext-lexical' + +- type MyNodes = SerializedParagraphNode | SerializedTextNode ++ type MyNodes = SerializedParagraphNode | SerializedTextNode + + function renderRichText(state: TypedEditorState) { + // ... + } +``` + +`SerializedTextNode` is a leaf, so it stays bare. For the built-in nodes plus a few of your own, `DefaultNodeTypesOf` threads the union for you (`type MyNodes = DefaultNodeTypesOf | SerializedBlockNode`), and `DefaultTypedEditorState` with only built-in nodes needs no change. + ### Jobs: `jobs.depth` and `jobs.runHooks` have been removed ([#16414](https://github.com/payloadcms/payload/pull/16414)) The deprecated `jobs.depth` and `jobs.runHooks` config options have been removed. Job operations now always use direct database calls with depth `0`. From f6e71a27ea38970ab875db25123a9defc2e34b5d Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Wed, 3 Jun 2026 09:04:07 +0000 Subject: [PATCH 34/56] feat: add description properties to schema to help the llm --- .../experimental_table/server/schema.ts | 10 +- .../features/relationship/server/schema.ts | 8 +- .../src/features/upload/server/schema.ts | 8 +- .../src/types/builtInNodes.ts | 19 +- .../src/types/jsonSchemaHelpers.ts | 9 +- test/lexical/payload-types.ts | 558 +++++++++--------- test/types/payload-types.ts | 20 +- test/types/types.spec.ts | 2 +- 8 files changed, 329 insertions(+), 305 deletions(-) diff --git a/packages/richtext-lexical/src/features/experimental_table/server/schema.ts b/packages/richtext-lexical/src/features/experimental_table/server/schema.ts index 2f157bb000d..4d65eae65d1 100644 --- a/packages/richtext-lexical/src/features/experimental_table/server/schema.ts +++ b/packages/richtext-lexical/src/features/experimental_table/server/schema.ts @@ -85,9 +85,13 @@ export const tableCellNodeJSONSchema: JSONSchemaFn = ({ nodeType: 'tablecell', properties: { backgroundColor: { oneOf: [{ type: 'string' }, { type: 'null' }] }, - colSpan: { type: 'integer' }, - headerState: { type: 'integer' }, - rowSpan: { type: 'integer' }, + colSpan: { type: 'integer', description: 'How many columns this cell spans (default 1).' }, + headerState: { + type: 'integer', + description: + 'Header bitmask: 0 = normal cell, 1 = row header, 2 = column header, 3 = both.', + }, + rowSpan: { type: 'integer', description: 'How many rows this cell spans (default 1).' }, verticalAlign: { type: 'string' }, width: { type: 'integer' }, }, diff --git a/packages/richtext-lexical/src/features/relationship/server/schema.ts b/packages/richtext-lexical/src/features/relationship/server/schema.ts index 3a5a37c3167..8c475fbddff 100644 --- a/packages/richtext-lexical/src/features/relationship/server/schema.ts +++ b/packages/richtext-lexical/src/features/relationship/server/schema.ts @@ -5,7 +5,7 @@ import type { LexicalElementFormat } from '../../../types/nodeTypes.js' import type { JSONSchemaFn } from '../../typesServer.js' import type { RelationshipFeatureProps } from './index.js' -import { formatSchema } from '../../../types/jsonSchemaHelpers.js' +import { formatSchema, versionSchema } from '../../../types/jsonSchemaHelpers.js' import { filterEnabledRelationshipCollections } from '../shared/filterEnabledRelationshipCollections.js' export type RelationshipData = { @@ -70,9 +70,11 @@ export const createRelationshipNodeJSONSchema = format: formatSchema, relationTo: { type: 'string', const: slug }, value: { + description: + 'The related document by ID (string or number). Populated to the full document when read at depth > 0.', oneOf: [{ type: idType }, { $ref: `#/definitions/${slug}` }], }, - version: { type: 'integer' }, + version: versionSchema, }, required: ['format', 'relationTo', 'type', 'value', 'version'], } @@ -85,7 +87,7 @@ export const createRelationshipNodeJSONSchema = additionalProperties: true, properties: { type: { type: 'string', const: 'relationship' }, - version: { type: 'integer' }, + version: versionSchema, }, required: ['type', 'version'], } diff --git a/packages/richtext-lexical/src/features/upload/server/schema.ts b/packages/richtext-lexical/src/features/upload/server/schema.ts index 0008b4e4593..8fbabe3b4f3 100644 --- a/packages/richtext-lexical/src/features/upload/server/schema.ts +++ b/packages/richtext-lexical/src/features/upload/server/schema.ts @@ -12,7 +12,7 @@ import type { LexicalElementFormat } from '../../../types/nodeTypes.js' import type { JSONSchemaFn } from '../../typesServer.js' import type { UploadFeatureProps } from './index.js' -import { formatSchema } from '../../../types/jsonSchemaHelpers.js' +import { formatSchema, versionSchema } from '../../../types/jsonSchemaHelpers.js' import { filterEnabledRelationshipCollections } from '../../relationship/shared/filterEnabledRelationshipCollections.js' export type UploadData = { @@ -121,9 +121,11 @@ export const createUploadNodeJSONSchema = format: formatSchema, relationTo: { type: 'string', const: slug }, value: { + description: + 'The uploaded file by ID (string or number). Populated to the full upload document when read at depth > 0.', oneOf: [{ type: idType }, { $ref: `#/definitions/${slug}` }], }, - version: { type: 'integer' }, + version: versionSchema, }, required: ['fields', 'format', 'id', 'relationTo', 'type', 'value', 'version'], } @@ -137,7 +139,7 @@ export const createUploadNodeJSONSchema = additionalProperties: true, properties: { type: { type: 'string', const: 'upload' }, - version: { type: 'integer' }, + version: versionSchema, }, required: ['type', 'version'], } diff --git a/packages/richtext-lexical/src/types/builtInNodes.ts b/packages/richtext-lexical/src/types/builtInNodes.ts index fddce8bfb19..8e99e9ae3b5 100644 --- a/packages/richtext-lexical/src/types/builtInNodes.ts +++ b/packages/richtext-lexical/src/types/builtInNodes.ts @@ -4,6 +4,8 @@ import { withNullableJSONSchemaType } from 'payload' import type { JSONSchemaFn } from '../features/typesServer.js' +import { versionSchema } from './jsonSchemaHelpers.js' + /** * Cross-cutting Lexical types shared by every element node. Inlined into * `payload-types.ts`. Must stay byte-for-byte in sync with the runtime twins @@ -75,6 +77,13 @@ const textModeSchema: JSONSchema4 = { tsType: 'LexicalTextMode', } +/** Text-node `format` bitmask (Lexical text-format flags). */ +const textFormatSchema: JSONSchema4 = { + type: 'integer', + description: + 'Active text formats as a bitmask, OR-ed together (0 = none): bold=1, italic=2, strikethrough=4, underline=8, code=16, subscript=32, superscript=64, highlight=128, lowercase=256, uppercase=512. e.g. bold + italic = 3.', +} + export const textNodeJSONSchema: JSONSchemaFn = ({ typeStringDefinitions }) => { typeStringDefinitions.add(LEXICAL_TEXT_MODE_TS) typeStringDefinitions.add(SERIALIZED_TEXT_NODE_TS) @@ -84,11 +93,11 @@ export const textNodeJSONSchema: JSONSchemaFn = ({ typeStringDefinitions }) => { properties: { type: { type: 'string', const: 'text' }, detail: { type: 'integer' }, - format: { type: 'integer' }, + format: textFormatSchema, mode: textModeSchema, style: { type: 'string' }, text: { type: 'string' }, - version: { type: 'integer' }, + version: versionSchema, }, required: ['detail', 'format', 'mode', 'style', 'text', 'type', 'version'], tsType: 'SerializedTextNode', @@ -104,11 +113,11 @@ export const tabNodeJSONSchema: JSONSchemaFn = ({ typeStringDefinitions }) => { properties: { type: { type: 'string', const: 'tab' }, detail: { type: 'integer' }, - format: { type: 'integer' }, + format: textFormatSchema, mode: textModeSchema, style: { type: 'string' }, text: { type: 'string' }, - version: { type: 'integer' }, + version: versionSchema, }, required: ['detail', 'format', 'mode', 'style', 'text', 'type', 'version'], tsType: 'SerializedTabNode', @@ -122,7 +131,7 @@ export const lineBreakNodeJSONSchema: JSONSchemaFn = ({ typeStringDefinitions }) additionalProperties: false, properties: { type: { type: 'string', const: 'linebreak' }, - version: { type: 'integer' }, + version: versionSchema, }, required: ['type', 'version'], tsType: 'SerializedLineBreakNode', diff --git a/packages/richtext-lexical/src/types/jsonSchemaHelpers.ts b/packages/richtext-lexical/src/types/jsonSchemaHelpers.ts index 062071c64db..10ff65f7415 100644 --- a/packages/richtext-lexical/src/types/jsonSchemaHelpers.ts +++ b/packages/richtext-lexical/src/types/jsonSchemaHelpers.ts @@ -3,6 +3,7 @@ import type { JSONSchema4 } from 'json-schema' /** `format` property shared by every element node (Lexical `ElementFormatType`). */ export const formatSchema: JSONSchema4 = { type: 'string', + description: 'How this element is aligned. Empty string means no explicit alignment.', enum: ['left', 'start', 'center', 'right', 'end', 'justify', ''], tsType: 'LexicalElementFormat', } @@ -13,6 +14,12 @@ export const directionSchema: JSONSchema4 = { tsType: 'LexicalElementDirection', } +/** `version` property shared by every Lexical node. */ +export const versionSchema: JSONSchema4 = { + type: 'integer', + description: "Lexical's internal serialization version for this node type.", +} + type ElementNodeSchemaOptions = { nodeType: string properties?: { [k: string]: JSONSchema4 } @@ -41,7 +48,7 @@ export const elementNodeSchema = ({ direction: directionSchema, format: formatSchema, indent: { type: 'integer' }, - version: { type: 'integer' }, + version: versionSchema, ...properties, }, required: ['children', 'direction', 'format', 'indent', 'type', 'version', ...required], diff --git a/test/lexical/payload-types.ts b/test/lexical/payload-types.ts index 3fb6b4f4a35..0205a729212 100644 --- a/test/lexical/payload-types.ts +++ b/test/lexical/payload-types.ts @@ -62,16 +62,16 @@ export type SupportedTimezones = | 'Pacific/Fiji'; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_32EA6B4A". + * via the `definition` "LexicalNodes_27B63E33". */ -export type LexicalNodes_32EA6B4A = +export type LexicalNodes_27B63E33 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -108,20 +108,20 @@ export type LexicalNodes_32EA6B4A = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_FF120C72". + * via the `definition` "LexicalNodes_D85009C7". */ -export type LexicalNodes_FF120C72 = +export type LexicalNodes_D85009C7 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode< | BenchBlock1 | BenchBlock2 @@ -157,7 +157,7 @@ export type LexicalNodes_FF120C72 = | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -194,28 +194,28 @@ export type LexicalNodes_FF120C72 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_F9A96ED9". + * via the `definition` "LexicalNodes_A572658A". */ -export type LexicalNodes_F9A96ED9 = +export type LexicalNodes_A572658A = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -252,27 +252,27 @@ export type LexicalNodes_F9A96ED9 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_26E8B07E". + * via the `definition` "LexicalNodes_B1F8D64B". */ -export type LexicalNodes_26E8B07E = +export type LexicalNodes_B1F8D64B = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedParagraphNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -309,23 +309,23 @@ export type LexicalNodes_26E8B07E = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_6F823331". + * via the `definition` "LexicalNodes_E600437B". */ -export type LexicalNodes_6F823331 = +export type LexicalNodes_E600437B = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedParagraphNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -362,33 +362,33 @@ export type LexicalNodes_6F823331 = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_4DAB3018". + * via the `definition` "LexicalNodes_B06100BA". */ -export type LexicalNodes_4DAB3018 = +export type LexicalNodes_B06100BA = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedListNode - | SerializedListItemNode; + | SerializedParagraphNode + | SerializedListNode + | SerializedListItemNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_652244A4". + * via the `definition` "LexicalNodes_652B8F46". */ -export type LexicalNodes_652244A4 = +export type LexicalNodes_652B8F46 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedHeadingNode + | SerializedParagraphNode + | SerializedHeadingNode | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -425,28 +425,28 @@ export type LexicalNodes_652244A4 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_62661AA4". + * via the `definition` "LexicalNodes_361E9E69". */ -export type LexicalNodes_62661AA4 = +export type LexicalNodes_361E9E69 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> - | SerializedHeadingNode + | SerializedHeadingNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedListNode - | SerializedListItemNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -485,18 +485,18 @@ export type LexicalNodes_62661AA4 = >; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_F25D27D9". + * via the `definition` "LexicalNodes_E600EF15". */ -export type LexicalNodes_F25D27D9 = +export type LexicalNodes_E600EF15 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -533,11 +533,11 @@ export type LexicalNodes_F25D27D9 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "BlockColumns". @@ -556,14 +556,14 @@ export type BlockColumns = | null; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_5BC162BC". + * via the `definition` "LexicalNodes_188B197D". */ -export type LexicalNodes_5BC162BC = +export type LexicalNodes_188B197D = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedHeadingNode + | SerializedParagraphNode + | SerializedHeadingNode | SerializedBlockNode< | RichTextBlock | TextRequired @@ -578,16 +578,16 @@ export type LexicalNodes_5BC162BC = | SerializedInlineBlockNode<{blockType: string}>; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_ACA183EB". + * via the `definition` "LexicalNodes_2FE228E9". */ -export type LexicalNodes_ACA183EB = +export type LexicalNodes_2FE228E9 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode + | SerializedParagraphNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode | SerializedBlockNode< | ValidationBlock | FilterOptionsBlock @@ -618,10 +618,10 @@ export type LexicalNodes_ACA183EB = | MyInlineBlockWithBlockAndLabel > | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -658,23 +658,23 @@ export type LexicalNodes_ACA183EB = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_423CFDD8". + * via the `definition` "LexicalNodes_E2F7CFB3". */ -export type LexicalNodes_423CFDD8 = +export type LexicalNodes_E2F7CFB3 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -711,25 +711,25 @@ export type LexicalNodes_423CFDD8 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_B33E6EC4". + * via the `definition` "LexicalNodes_15D85A4C". */ -export type LexicalNodes_B33E6EC4 = +export type LexicalNodes_15D85A4C = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -766,25 +766,25 @@ export type LexicalNodes_B33E6EC4 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_816689F6". + * via the `definition` "LexicalNodes_B73866D0". */ -export type LexicalNodes_816689F6 = +export type LexicalNodes_B73866D0 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -821,25 +821,25 @@ export type LexicalNodes_816689F6 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_846D8E24". + * via the `definition` "LexicalNodes_B864F712". */ -export type LexicalNodes_846D8E24 = +export type LexicalNodes_B864F712 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -876,25 +876,25 @@ export type LexicalNodes_846D8E24 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_1889F581". + * via the `definition` "LexicalNodes_04808660". */ -export type LexicalNodes_1889F581 = +export type LexicalNodes_04808660 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -931,25 +931,25 @@ export type LexicalNodes_1889F581 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_634B98CF". + * via the `definition` "LexicalNodes_998D58F7". */ -export type LexicalNodes_634B98CF = +export type LexicalNodes_998D58F7 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -986,81 +986,81 @@ export type LexicalNodes_634B98CF = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_8D432583". + * via the `definition` "LexicalNodes_55712B26". */ -export type LexicalNodes_8D432583 = +export type LexicalNodes_55712B26 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedUploadNode<'uploads' | 'uploads2'>; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_68F73700". + * via the `definition` "LexicalNodes_3A6F021F". */ -export type LexicalNodes_68F73700 = +export type LexicalNodes_3A6F021F = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}>; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_AD8137E5". + * via the `definition` "LexicalNodes_D39B65B3". */ -export type LexicalNodes_AD8137E5 = +export type LexicalNodes_D39B65B3 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode<{blockType: string}> | SerializedInlineBlockNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_7EAD8D74". + * via the `definition` "LexicalNodes_A52479CF". */ -export type LexicalNodes_7EAD8D74 = +export type LexicalNodes_A52479CF = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}>; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_A23F00F3". + * via the `definition` "LexicalNodes_BCA20638". */ -export type LexicalNodes_A23F00F3 = +export type LexicalNodes_BCA20638 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedUploadNode<'uploads'> | SerializedRelationshipNode<'array-fields'> | SerializedHorizontalRuleNode - | SerializedQuoteNode - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedQuoteNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_D05D701F". + * via the `definition` "LexicalNodes_24EBD3C5". */ -export type LexicalNodes_D05D701F = +export type LexicalNodes_24EBD3C5 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1099,24 +1099,24 @@ export type LexicalNodes_D05D701F = > | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedQuoteNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_F2570347". + * via the `definition` "LexicalNodes_25924F55". */ -export type LexicalNodes_F2570347 = +export type LexicalNodes_25924F55 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedUploadNode<'uploads2'> | SerializedHorizontalRuleNode - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1153,25 +1153,25 @@ export type LexicalNodes_F2570347 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_A4F423C0". + * via the `definition` "LexicalNodes_52C5E759". */ -export type LexicalNodes_A4F423C0 = +export type LexicalNodes_52C5E759 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1208,27 +1208,27 @@ export type LexicalNodes_A4F423C0 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_D654DD6A". + * via the `definition` "LexicalNodes_3A8AD1F5". */ -export type LexicalNodes_D654DD6A = +export type LexicalNodes_3A8AD1F5 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1265,30 +1265,30 @@ export type LexicalNodes_D654DD6A = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_2A841A08". + * via the `definition` "LexicalNodes_172DC8C8". */ -export type LexicalNodes_2A841A08 = +export type LexicalNodes_172DC8C8 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode + | SerializedParagraphNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> - | SerializedHeadingNode + | SerializedHeadingNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedListNode - | SerializedListItemNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1496,7 +1496,7 @@ export interface BlockWithBlockRef_338FAE2E { */ export interface LexicalBenchmark { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1506,7 +1506,7 @@ export interface LexicalBenchmark { */ export interface LexicalFullyFeatured { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1519,7 +1519,7 @@ export interface LexicalAutosave { title?: string | null; cta?: | { - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; id?: string | null; }[] | null; @@ -1533,7 +1533,7 @@ export interface LexicalAutosave { */ export interface LexicalLinkFeature { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1543,7 +1543,7 @@ export interface LexicalLinkFeature { */ export interface LexicalListsFeature { id: string; - onlyOrderedList?: LexicalRichText | null; + onlyOrderedList?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1553,7 +1553,7 @@ export interface LexicalListsFeature { */ export interface LexicalHeadingFeature { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1563,7 +1563,7 @@ export interface LexicalHeadingFeature { */ export interface LexicalJsxConverter { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1574,15 +1574,15 @@ export interface LexicalJsxConverter { export interface LexicalField { id: string; title: string; - lexicalRootEditor?: LexicalRichText | null; + lexicalRootEditor?: LexicalRichText | null; /** * A simple lexical field */ - lexicalSimple?: LexicalRichText | null; + lexicalSimple?: LexicalRichText | null; /** * Should not be rendered */ - lexicalWithBlocks: LexicalRichText; + lexicalWithBlocks: LexicalRichText; lexicalWithBlocks_markdown?: string | null; updatedAt: string; createdAt: string; @@ -1593,8 +1593,8 @@ export interface LexicalField { */ export interface LexicalView { id: string; - customDefaultView?: LexicalRichText | null; - vanillaView?: LexicalRichText | null; + customDefaultView?: LexicalRichText | null; + vanillaView?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1604,7 +1604,7 @@ export interface LexicalView { */ export interface LexicalViewsFrontend { id: string; - customFrontendViews?: LexicalRichText | null; + customFrontendViews?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1615,7 +1615,7 @@ export interface LexicalViewsFrontend { export interface LexicalViewsProvider { id: string; viewProviderWrapper?: { - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; }; updatedAt: string; createdAt: string; @@ -1627,7 +1627,7 @@ export interface LexicalViewsProvider { export interface LexicalViewsProviderDefault { id: string; defaultViewWrapper?: { - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; }; updatedAt: string; createdAt: string; @@ -1639,7 +1639,7 @@ export interface LexicalViewsProviderDefault { export interface LexicalViewsProviderFallback { id: string; fallbackViewWrapper?: { - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; }; updatedAt: string; createdAt: string; @@ -1650,7 +1650,7 @@ export interface LexicalViewsProviderFallback { */ export interface LexicalViewsNested { id: string; - parentRichText?: LexicalRichText | null; + parentRichText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1664,11 +1664,11 @@ export interface LexicalLocalizedField { /** * Non-localized field with localized block subfields */ - lexicalBlocksSubLocalized?: LexicalRichText | null; + lexicalBlocksSubLocalized?: LexicalRichText | null; /** * Localized field with localized block subfields */ - lexicalBlocksLocalized?: LexicalRichText | null; + lexicalBlocksLocalized?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1678,8 +1678,8 @@ export interface LexicalLocalizedField { */ export interface LexicalObjectReferenceBug { id: string; - lexicalDefault?: LexicalRichText | null; - lexicalEditor?: LexicalRichText | null; + lexicalDefault?: LexicalRichText | null; + lexicalEditor?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1689,7 +1689,7 @@ export interface LexicalObjectReferenceBug { */ export interface LexicalInBlock { id: string; - content?: LexicalRichText | null; + content?: LexicalRichText | null; blocks?: LexicalInBlock2[] | null; updatedAt: string; createdAt: string; @@ -1699,7 +1699,7 @@ export interface LexicalInBlock { * via the `definition` "LexicalInBlock2". */ export interface LexicalInBlock2 { - lexical?: LexicalRichText | null; + lexical?: LexicalRichText | null; id?: string | null; blockName?: string | null; blockType: 'lexicalInBlock2'; @@ -1710,7 +1710,7 @@ export interface LexicalInBlock2 { */ export interface LexicalAutosaveBlock { id: string; - content?: LexicalRichText | null; + content?: LexicalRichText | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -1722,7 +1722,7 @@ export interface LexicalAutosaveBlock { export interface LexicalAccessControl { id: string; title?: string | null; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1732,10 +1732,10 @@ export interface LexicalAccessControl { */ export interface LexicalRelationshipField { id: string; - richText?: LexicalRichText | null; - richText2?: LexicalRichText | null; - richText3?: LexicalRichText | null; - richTextLocalized?: LexicalRichText | null; + richText?: LexicalRichText | null; + richText2?: LexicalRichText | null; + richText3?: LexicalRichText | null; + richTextLocalized?: LexicalRichText | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -1746,7 +1746,7 @@ export interface LexicalRelationshipField { */ export interface Collision { id: string; - collision?: LexicalRichText | null; + collision?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1757,7 +1757,7 @@ export interface Collision { export interface LexicalNestedBlock { id: string; title: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1768,12 +1768,12 @@ export interface LexicalNestedBlock { export interface RichTextField { id: string; title: string; - lexicalCustomFields: LexicalRichText; + lexicalCustomFields: LexicalRichText; lexicalCustomFields_html?: string | null; /** * This rich text field uses the lexical editor. */ - lexical?: LexicalRichText | null; + lexical?: LexicalRichText | null; /** * This select field is rendered here to ensure its options dropdown renders above the rich text toolbar. */ @@ -2021,7 +2021,7 @@ export interface OnDemandOutsideForm { | number | boolean | null; - hiddenAnchor?: LexicalRichText | null; + hiddenAnchor?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2032,7 +2032,7 @@ export interface OnDemandOutsideForm { export interface LexicalCustomCell { id: string; title: string; - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2873,10 +2873,10 @@ export interface PayloadMigrationsSelect { export interface TabsWithRichText { id: string; tab1?: { - rt1?: LexicalRichText | null; + rt1?: LexicalRichText | null; }; tab2?: { - rt2?: LexicalRichText | null; + rt2?: LexicalRichText | null; }; updatedAt?: string | null; createdAt?: string | null; @@ -3406,9 +3406,9 @@ export interface TextBlock { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_26E8B07E". + * via the `definition` "LexicalLinkFields_B1F8D64B". */ -export interface LexicalLinkFields_26E8B07E { +export interface LexicalLinkFields_B1F8D64B { linkBlocks?: LinkBlock[] | null; doc?: { relationTo: string; @@ -3426,9 +3426,9 @@ export interface LexicalLinkFields_26E8B07E { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_6F823331". + * via the `definition` "LexicalLinkFields_E600437B". */ -export interface LexicalLinkFields_6F823331 { +export interface LexicalLinkFields_E600437B { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3470,9 +3470,9 @@ export interface MyBlock_89EF3EA7 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_62661AA4". + * via the `definition` "LexicalLinkFields_361E9E69". */ -export interface LexicalLinkFields_62661AA4 { +export interface LexicalLinkFields_361E9E69 { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3495,7 +3495,7 @@ export interface LexicalLinkFields_62661AA4 { export interface LexicalAndUploadBlock { id: string; blockType: 'lexicalAndUploadBlock'; - subRichTextField?: LexicalRichText | null; + subRichTextField?: LexicalRichText | null; subUploadField?: (string | null) | Upload; blockName?: string | null; } @@ -3506,7 +3506,7 @@ export interface LexicalAndUploadBlock { export interface RichTextBlock { id: string; blockType: 'richTextBlock'; - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; blockName?: string | null; } /** @@ -3527,7 +3527,7 @@ export interface UploadAndRichText { id: string; blockType: 'uploadAndRichText'; upload: string | Upload; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; blockName?: string | null; } /** @@ -3577,7 +3577,7 @@ export interface ContentBlock { id: string; blockType: 'content-block'; title: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; blockName?: string | null; } /** @@ -3821,9 +3821,9 @@ export interface MyInlineBlockWithBlockAndLabel { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_ACA183EB". + * via the `definition` "LexicalLinkFields_2FE228E9". */ -export interface LexicalLinkFields_ACA183EB { +export interface LexicalLinkFields_2FE228E9 { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3861,7 +3861,7 @@ export interface BannerBlock { blockType: 'banner'; type: 'normal' | 'important'; title: string; - content?: LexicalRichText | null; + content?: LexicalRichText | null; blockName?: string | null; } /** @@ -3873,7 +3873,7 @@ export interface ProviderBannerBlock { blockType: 'banner'; type: 'normal' | 'important'; title: string; - content?: LexicalRichText | null; + content?: LexicalRichText | null; blockName?: string | null; } /** @@ -3884,7 +3884,7 @@ export interface NestedContentBlock { id: string; blockType: 'nested-content'; label: string; - nestedRichText?: LexicalRichText | null; + nestedRichText?: LexicalRichText | null; blockName?: string | null; } /** @@ -3920,7 +3920,7 @@ export interface BlockInLexical { /** * Some Description */ - lexicalInBlock: LexicalRichText; + lexicalInBlock: LexicalRichText; blockName?: string | null; } /** @@ -3939,7 +3939,7 @@ export interface InlineBlockInLexical { export interface BlockWithRichText { id: string; blockType: 'blockWithRichText'; - nestedRichText?: LexicalRichText | null; + nestedRichText?: LexicalRichText | null; blockName?: string | null; } /** @@ -3954,9 +3954,9 @@ export interface BlockWithBlockRef { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_D654DD6A". + * via the `definition` "LexicalLinkFields_3A8AD1F5". */ -export interface LexicalLinkFields_D654DD6A { +export interface LexicalLinkFields_3A8AD1F5 { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3977,9 +3977,9 @@ export interface LexicalLinkFields_D654DD6A { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_2A841A08". + * via the `definition` "LexicalLinkFields_172DC8C8". */ -export interface LexicalLinkFields_2A841A08 { +export interface LexicalLinkFields_172DC8C8 { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -4172,6 +4172,6 @@ export interface SerializedTableCellNode extends SerializedLexicalEle declare module 'payload' { - // @ts-ignore + // @ts-ignore export interface GeneratedTypes extends Config {} -} \ No newline at end of file +} diff --git a/test/types/payload-types.ts b/test/types/payload-types.ts index b39d80430e7..bbf48cab025 100644 --- a/test/types/payload-types.ts +++ b/test/types/payload-types.ts @@ -75,16 +75,16 @@ export type SupportedTimezones = | 'Pacific/Fiji'; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_99AE542E". + * via the `definition` "LexicalNodes_F6A92CF8". */ -export type LexicalNodes_99AE542E = +export type LexicalNodes_F6A92CF8 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedHorizontalRuleNode | SerializedUploadNode<'media'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'posts' | 'pages' @@ -97,11 +97,11 @@ export type LexicalNodes_99AE542E = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; export interface Config { auth: { @@ -206,7 +206,7 @@ export interface PayloadMcpApiKeyAuthOperations { export interface Post { id: string; text?: string | null; - richText: LexicalRichText; + richText: LexicalRichText; title?: string | null; selectField: MySelectOptions; insideUnnamedGroup?: string | null; diff --git a/test/types/types.spec.ts b/test/types/types.spec.ts index fe275bfc441..bb03b3e0e77 100644 --- a/test/types/types.spec.ts +++ b/test/types/types.spec.ts @@ -47,7 +47,7 @@ import type { SerializedListItemNode as GenLI, SerializedLinkNode as GenLink, SerializedListNode as GenList, - LexicalNodes_99AE542E as GenNodeUnion, + LexicalNodes_F6A92CF8 as GenNodeUnion, SerializedParagraphNode as GenParagraph, SerializedQuoteNode as GenQuote, SerializedTabNode as GenTab, From f8b19e2dd528cafa8c9f4e28b47ca26aa3e68383 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Wed, 3 Jun 2026 22:14:46 +0000 Subject: [PATCH 35/56] fix: json schema for tab nodes was to weak --- packages/richtext-lexical/src/types/builtInNodes.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/richtext-lexical/src/types/builtInNodes.ts b/packages/richtext-lexical/src/types/builtInNodes.ts index 8e99e9ae3b5..32357661093 100644 --- a/packages/richtext-lexical/src/types/builtInNodes.ts +++ b/packages/richtext-lexical/src/types/builtInNodes.ts @@ -112,11 +112,13 @@ export const tabNodeJSONSchema: JSONSchemaFn = ({ typeStringDefinitions }) => { additionalProperties: false, properties: { type: { type: 'string', const: 'tab' }, - detail: { type: 'integer' }, + // A tab node is fully fixed: Lexical marks it unmergeable (`detail` = IS_UNMERGEABLE = 2) and + // its text is a single tab. Any other `detail` makes `TabNode.setDetail` throw on load. + detail: { const: 2, description: 'Always 2 (Lexical IS_UNMERGEABLE); other values throw.' }, format: textFormatSchema, mode: textModeSchema, style: { type: 'string' }, - text: { type: 'string' }, + text: { const: '\t', description: 'Always a single tab character.' }, version: versionSchema, }, required: ['detail', 'format', 'mode', 'style', 'text', 'type', 'version'], From 7b58398e1d7b7c3fd83fe500ccacebe9cb56c297 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 4 Jun 2026 04:21:59 +0000 Subject: [PATCH 36/56] fix: link schema had duplicative required strings --- packages/richtext-lexical/src/features/link/server/schema.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/richtext-lexical/src/features/link/server/schema.ts b/packages/richtext-lexical/src/features/link/server/schema.ts index 885a94b9824..ebfbb8340e5 100644 --- a/packages/richtext-lexical/src/features/link/server/schema.ts +++ b/packages/richtext-lexical/src/features/link/server/schema.ts @@ -120,7 +120,9 @@ const buildLinkFieldsJSONSchema = ( newTab: { type: 'boolean' }, url: { type: 'string' }, }, - required: ['linkType', 'newTab', ...userFieldsSchema.required], + // `linkType`/`newTab` are already in `userFieldsSchema.required`; use Set to dedupe, + // so `required` stays unique (draft 2020-12 enforces `uniqueItems`). + required: [...new Set(['linkType', 'newTab', ...userFieldsSchema.required])], } } From ee58abcfc4aba767e910c2cec916d2d70e850f1b Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 4 Jun 2026 05:05:45 +0000 Subject: [PATCH 37/56] feat: single relationship field description so that relationTo is defined --- .../simplifyRelationshipFields.ts | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/packages/plugin-mcp/src/utils/schemaConversion/simplifyRelationshipFields.ts b/packages/plugin-mcp/src/utils/schemaConversion/simplifyRelationshipFields.ts index 3d3d107fe7b..6e28602908c 100644 --- a/packages/plugin-mcp/src/utils/schemaConversion/simplifyRelationshipFields.ts +++ b/packages/plugin-mcp/src/utils/schemaConversion/simplifyRelationshipFields.ts @@ -1,21 +1,11 @@ import type { JsonSchemaType } from '../../types.js' /** - * Recursively processes JSON schema properties to simplify relationship fields - * and convert `oneOf` constructs into MCP-friendly schemas. + * Recursively simplifies relationship fields for MCP create/update input. We only need to accept + * IDs (string/number), not populated objects, so `$ref` options pointing at full entity definitions + * are dropped from `oneOf` unions. A lone remaining option is unwrapped; multiple become `anyOf`. * - * For create/update validation we only need to accept IDs (string/number), - * not populated objects. `$ref` options pointing to full entity definitions - * are removed entirely from `oneOf` unions. When a single option remains the - * `oneOf` is unwrapped; otherwise it is converted to `anyOf`. - * - * This matters because `json-schema-to-zod` converts `oneOf` into a strict - * `z.any().superRefine(...)` validator whose base type is `z.any()`, causing - * `zodToJsonSchema` to emit `{}` and losing all type information in the MCP - * tool input schema. `anyOf` instead produces a clean `z.union([...])`. - * - * NOTE: This function must operate on a cloned schema to avoid mutating - * the original JSON schema used for tool listing. + * NOTE: operates on a clone per level so the original schema (reused for tool listing) isn't mutated. */ export function simplifyRelationshipFields(schema: JsonSchemaType): JsonSchemaType { if (!schema || typeof schema !== 'object') { @@ -39,10 +29,17 @@ export function simplifyRelationshipFields(schema: JsonSchemaType): JsonSchemaTy if (nonRefOptions.length === 1) { const single = nonRefOptions[0]! + // A single-target relationship collapses to a bare ID; note the target collection(s) in a description. + const refSlugs = processed.oneOf + .filter((option) => option && typeof option === 'object' && '$ref' in option) + .map((option) => String((option as { $ref: string }).$ref).replace('#/definitions/', '')) delete processed.oneOf if (typeof single === 'object') { Object.assign(processed, single) } + if (refSlugs.length > 0 && !processed.description) { + processed.description = `The ID of the related "${refSlugs.join('" or "')}" document.` + } } else if (nonRefOptions.length > 1) { delete processed.oneOf processed.anyOf = nonRefOptions From e891e3aa25d095b6d79c525adcecdea169acb1ad Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 4 Jun 2026 05:42:01 +0000 Subject: [PATCH 38/56] fix type tests --- test/types/types.spec.ts | 56 ++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/test/types/types.spec.ts b/test/types/types.spec.ts index fc17d606774..0a140974fbd 100644 --- a/test/types/types.spec.ts +++ b/test/types/types.spec.ts @@ -960,76 +960,76 @@ describe('Types testing', () => { // assertions above fail. test('SerializedTextNode: generated <-> runtime', () => { - expect().type.toBeAssignableWith() - expect().type.toBeAssignableWith() + expect().type.toBeAssignableFrom() + expect().type.toBeAssignableFrom() }) test('SerializedTabNode: generated <-> runtime', () => { - expect().type.toBeAssignableWith() - expect().type.toBeAssignableWith() + expect().type.toBeAssignableFrom() + expect().type.toBeAssignableFrom() }) test('SerializedLineBreakNode: generated <-> runtime', () => { - expect().type.toBeAssignableWith() - expect().type.toBeAssignableWith() + expect().type.toBeAssignableFrom() + expect().type.toBeAssignableFrom() }) test('SerializedHorizontalRuleNode: generated <-> runtime', () => { - expect().type.toBeAssignableWith() - expect().type.toBeAssignableWith() + expect().type.toBeAssignableFrom() + expect().type.toBeAssignableFrom() }) test('SerializedParagraphNode: generated <-> runtime', () => { - expect>().type.toBeAssignableWith< + expect>().type.toBeAssignableFrom< SerializedParagraphNode >() - expect>().type.toBeAssignableWith< + expect>().type.toBeAssignableFrom< GenParagraph >() }) test('SerializedHeadingNode: generated <-> runtime', () => { - expect>().type.toBeAssignableWith< + expect>().type.toBeAssignableFrom< SerializedHeadingNode >() - expect>().type.toBeAssignableWith< + expect>().type.toBeAssignableFrom< GenHeading >() }) test('SerializedQuoteNode: generated <-> runtime', () => { - expect>().type.toBeAssignableWith< + expect>().type.toBeAssignableFrom< SerializedQuoteNode >() - expect>().type.toBeAssignableWith< + expect>().type.toBeAssignableFrom< GenQuote >() }) test('SerializedListNode: generated <-> runtime', () => { - expect>().type.toBeAssignableWith>() - expect>().type.toBeAssignableWith>() + expect>().type.toBeAssignableFrom>() + expect>().type.toBeAssignableFrom>() }) test('SerializedListItemNode: generated <-> runtime', () => { - expect>().type.toBeAssignableWith< + expect>().type.toBeAssignableFrom< SerializedListItemNode >() - expect>().type.toBeAssignableWith< + expect>().type.toBeAssignableFrom< GenLI >() }) test('SerializedLinkNode: generated <-> runtime', () => { - expect>().type.toBeAssignableWith>() - expect>().type.toBeAssignableWith>() + expect>().type.toBeAssignableFrom>() + expect>().type.toBeAssignableFrom>() }) test('SerializedAutoLinkNode: generated <-> runtime', () => { - expect>().type.toBeAssignableWith< + expect>().type.toBeAssignableFrom< SerializedAutoLinkNode >() - expect>().type.toBeAssignableWith< + expect>().type.toBeAssignableFrom< GenAutoLink >() }) @@ -1038,23 +1038,23 @@ describe('Types testing', () => { // The relationship node excludes upload collections, so compare against the // relationship member as it actually appears in the generated union. type GenRelationshipInUnion = Extract - expect().type.toBeAssignableWith() - expect().type.toBeAssignableWith() + expect().type.toBeAssignableFrom() + expect().type.toBeAssignableFrom() }) test('SerializedUploadNode: generated <-> runtime', () => { // `media` is the upload-enabled collection, so both sides resolve to // `SerializedUploadNode<'media'>`. type GenUploadInUnion = Extract - expect().type.toBeAssignableWith() - expect().type.toBeAssignableWith() + expect().type.toBeAssignableFrom() + expect().type.toBeAssignableFrom() }) test('LexicalRichText.root: generated <-> runtime', () => { type Gen = Post['richText']['root'] type Run = DefaultTypedEditorState['root'] - expect().type.toBeAssignableWith() - expect().type.toBeAssignableWith() + expect().type.toBeAssignableFrom() + expect().type.toBeAssignableFrom() }) }) }) From 6119ef4276eb9b777ff31978a767b285bee718f3 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 4 Jun 2026 16:19:17 +0000 Subject: [PATCH 39/56] migrate definitions => $defs merge conflicts --- .../payload/src/utilities/configToJSONSchema.spec.ts | 6 +++--- packages/payload/src/utilities/configToJSONSchema.ts | 8 ++++---- .../schemaConversion/simplifyRelationshipFields.ts | 10 +++++----- .../src/features/blocks/server/schema.ts | 8 ++++---- .../src/features/link/server/schema.ts | 2 +- .../src/features/relationship/server/schema.ts | 2 +- .../src/features/upload/server/schema.ts | 2 +- packages/richtext-lexical/src/types/schema.ts | 7 +++++-- test/lexical/lexical.int.spec.ts | 2 +- 9 files changed, 25 insertions(+), 22 deletions(-) diff --git a/packages/payload/src/utilities/configToJSONSchema.spec.ts b/packages/payload/src/utilities/configToJSONSchema.spec.ts index 3c2de2e4fc1..bee323acdb8 100644 --- a/packages/payload/src/utilities/configToJSONSchema.spec.ts +++ b/packages/payload/src/utilities/configToJSONSchema.spec.ts @@ -591,7 +591,7 @@ describe('configToJSONSchema', () => { }) // Has its own $schema, so it resolves on its own. - expect(schema.$schema).toBe('http://json-schema.org/draft-07/schema#') + expect(schema.$schema).toBe('https://json-schema.org/draft/2020-12/schema') // The block reference is resolved inline, so it can't dangle. const layoutItems = (schema.properties?.layout as JSONSchema4)?.items as JSONSchema4 @@ -600,9 +600,9 @@ describe('configToJSONSchema', () => { expect(inlinedBlock.properties?.title).toBeDefined() // A timezone field pulls in supportedTimezones from the root config. - expect(schema.definitions?.supportedTimezones).toBeDefined() + expect(schema.$defs?.supportedTimezones).toBeDefined() // Doesn't pull in unrelated collections. - expect(schema.definitions?.other).toBeUndefined() + expect(schema.$defs?.other).toBeUndefined() }) }) diff --git a/packages/payload/src/utilities/configToJSONSchema.ts b/packages/payload/src/utilities/configToJSONSchema.ts index 7b69efc01f6..6f6a4a317bc 100644 --- a/packages/payload/src/utilities/configToJSONSchema.ts +++ b/packages/payload/src/utilities/configToJSONSchema.ts @@ -997,7 +997,7 @@ export function entityToJSONSchema( /** * Like {@link entityToJSONSchema}, but returns a standalone schema for one collection or global: - * the entity plus only the `definitions` it actually uses, so it resolves on its own rather than + * the entity plus only the `$defs` it actually uses, so it resolves on its own rather than * as part of the whole config schema. * * Relationship/upload `$ref`s to other collections are left in place - the caller handles those. @@ -1031,15 +1031,15 @@ export function entityToStandaloneJSONSchema({ const supportedTimezones = config.admin?.timezones?.supportedTimezones if ( supportedTimezones?.length && - schemaHasRef([schema, ...definitions.values()], '#/definitions/supportedTimezones') + schemaHasRef([schema, ...definitions.values()], '#/$defs/supportedTimezones') ) { definitions.set('supportedTimezones', timezonesToJSONSchema(supportedTimezones)) } return { - $schema: 'http://json-schema.org/draft-07/schema#', + $schema: 'https://json-schema.org/draft/2020-12/schema', ...schema, - definitions: Object.fromEntries(definitions), + $defs: Object.fromEntries(definitions), } } diff --git a/packages/plugin-mcp/src/utils/schemaConversion/simplifyRelationshipFields.ts b/packages/plugin-mcp/src/utils/schemaConversion/simplifyRelationshipFields.ts index 6e28602908c..9b96124a2a5 100644 --- a/packages/plugin-mcp/src/utils/schemaConversion/simplifyRelationshipFields.ts +++ b/packages/plugin-mcp/src/utils/schemaConversion/simplifyRelationshipFields.ts @@ -32,7 +32,7 @@ export function simplifyRelationshipFields(schema: JsonSchemaType): JsonSchemaTy // A single-target relationship collapses to a bare ID; note the target collection(s) in a description. const refSlugs = processed.oneOf .filter((option) => option && typeof option === 'object' && '$ref' in option) - .map((option) => String((option as { $ref: string }).$ref).replace('#/definitions/', '')) + .map((option) => String((option as { $ref: string }).$ref).replace('#/$defs/', '')) delete processed.oneOf if (typeof single === 'object') { Object.assign(processed, single) @@ -63,11 +63,11 @@ export function simplifyRelationshipFields(schema: JsonSchemaType): JsonSchemaTy processed.items = simplifyRelationshipFields(processed.items) } - // Also walk `definitions`: lexical node unions and blocks live there, and their relationship + // Also walk `$defs`: lexical node unions and blocks live there, and their relationship // fields point at collections that aren't bundled. Simplifying them drops those refs to IDs. - if (processed.definitions && typeof processed.definitions === 'object') { - processed.definitions = Object.fromEntries( - Object.entries(processed.definitions).map(([key, value]) => [ + if (processed.$defs && typeof processed.$defs === 'object') { + processed.$defs = Object.fromEntries( + Object.entries(processed.$defs).map(([key, value]) => [ key, typeof value === 'object' ? simplifyRelationshipFields(value) : value, ]), diff --git a/packages/richtext-lexical/src/features/blocks/server/schema.ts b/packages/richtext-lexical/src/features/blocks/server/schema.ts index bdc7a1118f2..1381d9de7a2 100644 --- a/packages/richtext-lexical/src/features/blocks/server/schema.ts +++ b/packages/richtext-lexical/src/features/blocks/server/schema.ts @@ -123,8 +123,8 @@ export const createBlockNodeJSONSchema = definitionNames.length === 0 ? { type: 'object', additionalProperties: true } : definitionNames.length === 1 - ? { $ref: `#/definitions/${definitionNames[0]!}` } - : { oneOf: definitionNames.map((name) => ({ $ref: `#/definitions/${name}` })) } + ? { $ref: `#/$defs/${definitionNames[0]!}` } + : { oneOf: definitionNames.map((name) => ({ $ref: `#/$defs/${name}` })) } const tsType = definitionNames.length > 0 @@ -157,8 +157,8 @@ export const createInlineBlockNodeJSONSchema = definitionNames.length === 0 ? { type: 'object', additionalProperties: true } : definitionNames.length === 1 - ? { $ref: `#/definitions/${definitionNames[0]!}` } - : { oneOf: definitionNames.map((name) => ({ $ref: `#/definitions/${name}` })) } + ? { $ref: `#/$defs/${definitionNames[0]!}` } + : { oneOf: definitionNames.map((name) => ({ $ref: `#/$defs/${name}` })) } const tsType = definitionNames.length > 0 diff --git a/packages/richtext-lexical/src/features/link/server/schema.ts b/packages/richtext-lexical/src/features/link/server/schema.ts index ebfbb8340e5..4e95c2c8e12 100644 --- a/packages/richtext-lexical/src/features/link/server/schema.ts +++ b/packages/richtext-lexical/src/features/link/server/schema.ts @@ -148,7 +148,7 @@ const resolveLinkFieldsRef = ( const editorHash = args.nodeUnionName.replace(/^LexicalNodes_/, '') const fieldsTypeName = `LexicalLinkFields_${editorHash}` args.interfaceNameDefinitions.set(fieldsTypeName, fieldsSchema) - return { fieldsRef: { $ref: `#/definitions/${fieldsTypeName}` }, fieldsTypeName } + return { fieldsRef: { $ref: `#/$defs/${fieldsTypeName}` }, fieldsTypeName } } export const createLinkNodeJSONSchema = diff --git a/packages/richtext-lexical/src/features/relationship/server/schema.ts b/packages/richtext-lexical/src/features/relationship/server/schema.ts index 8c475fbddff..2da931c2ce7 100644 --- a/packages/richtext-lexical/src/features/relationship/server/schema.ts +++ b/packages/richtext-lexical/src/features/relationship/server/schema.ts @@ -72,7 +72,7 @@ export const createRelationshipNodeJSONSchema = value: { description: 'The related document by ID (string or number). Populated to the full document when read at depth > 0.', - oneOf: [{ type: idType }, { $ref: `#/definitions/${slug}` }], + oneOf: [{ type: idType }, { $ref: `#/$defs/${slug}` }], }, version: versionSchema, }, diff --git a/packages/richtext-lexical/src/features/upload/server/schema.ts b/packages/richtext-lexical/src/features/upload/server/schema.ts index 8fbabe3b4f3..4702bac3b34 100644 --- a/packages/richtext-lexical/src/features/upload/server/schema.ts +++ b/packages/richtext-lexical/src/features/upload/server/schema.ts @@ -123,7 +123,7 @@ export const createUploadNodeJSONSchema = value: { description: 'The uploaded file by ID (string or number). Populated to the full upload document when read at depth > 0.', - oneOf: [{ type: idType }, { $ref: `#/definitions/${slug}` }], + oneOf: [{ type: idType }, { $ref: `#/$defs/${slug}` }], }, version: versionSchema, }, diff --git a/packages/richtext-lexical/src/types/schema.ts b/packages/richtext-lexical/src/types/schema.ts index c2500b8ee62..50397b65d0c 100644 --- a/packages/richtext-lexical/src/types/schema.ts +++ b/packages/richtext-lexical/src/types/schema.ts @@ -48,7 +48,7 @@ export const getFieldToJSONSchema: (args: { elementNodeSchema({ ...args, nodeUnionRef: { - $ref: `#/definitions/${NODE_UNION_NAME_PLACEHOLDER}`, + $ref: `#/$defs/${NODE_UNION_NAME_PLACEHOLDER}`, }, }), field, @@ -77,7 +77,10 @@ export const getFieldToJSONSchema: (args: { // See JSDocs for `NODE_UNION_NAME_PLACEHOLDER` for why we use a placeholder and hashing. const nodeUnionJson = JSON.stringify({ oneOf: nodeSchemas }) - const hash = createHash('sha256').update(nodeUnionJson).digest('hex').slice(0, 8).toUpperCase() + // Hash a ref-style-agnostic form so switching draft-07 `definitions` → 2020-12 `$defs` doesn't + // shift every `LexicalNodes_` (the hash only disambiguates editors, not ref syntax). + const hashInput = nodeUnionJson.replaceAll('#/$defs/', '#/definitions/') + const hash = createHash('sha256').update(hashInput).digest('hex').slice(0, 8).toUpperCase() const nodeUnionName = `LexicalNodes_${hash}` // Replacing the hash resolves the union name and any feature-derived diff --git a/test/lexical/lexical.int.spec.ts b/test/lexical/lexical.int.spec.ts index a4279acfe53..eae4d1b26a5 100644 --- a/test/lexical/lexical.int.spec.ts +++ b/test/lexical/lexical.int.spec.ts @@ -1304,7 +1304,7 @@ describe('Lexical block interface generation', () => { const sanitizedConfig = await sanitizeConfig(config) const { jsonSchema } = configToJSONSchema(sanitizedConfig, 'text') - const defs = jsonSchema.definitions! + const defs = jsonSchema.$defs! // Each differently-shaped `hero` gets its own interface (one clean, one hashed). const heroNames = Object.keys(defs).filter((k) => /^Hero(_[0-9A-F]{8})?$/.test(k)) From 628218e326a7dd8cd162fee2fbbb242c5dad0ed3 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 4 Jun 2026 16:28:41 +0000 Subject: [PATCH 40/56] fix type tests import, remove unnecessary replaceAll --- packages/richtext-lexical/src/types/schema.ts | 5 +- test/lexical/payload-types.ts | 564 +++++++++--------- test/types/payload-types.ts | 20 +- test/types/types.spec.ts | 2 +- 4 files changed, 294 insertions(+), 297 deletions(-) diff --git a/packages/richtext-lexical/src/types/schema.ts b/packages/richtext-lexical/src/types/schema.ts index 50397b65d0c..a33bb89654e 100644 --- a/packages/richtext-lexical/src/types/schema.ts +++ b/packages/richtext-lexical/src/types/schema.ts @@ -77,10 +77,7 @@ export const getFieldToJSONSchema: (args: { // See JSDocs for `NODE_UNION_NAME_PLACEHOLDER` for why we use a placeholder and hashing. const nodeUnionJson = JSON.stringify({ oneOf: nodeSchemas }) - // Hash a ref-style-agnostic form so switching draft-07 `definitions` → 2020-12 `$defs` doesn't - // shift every `LexicalNodes_` (the hash only disambiguates editors, not ref syntax). - const hashInput = nodeUnionJson.replaceAll('#/$defs/', '#/definitions/') - const hash = createHash('sha256').update(hashInput).digest('hex').slice(0, 8).toUpperCase() + const hash = createHash('sha256').update(nodeUnionJson).digest('hex').slice(0, 8).toUpperCase() const nodeUnionName = `LexicalNodes_${hash}` // Replacing the hash resolves the union name and any feature-derived diff --git a/test/lexical/payload-types.ts b/test/lexical/payload-types.ts index 0205a729212..97452706c28 100644 --- a/test/lexical/payload-types.ts +++ b/test/lexical/payload-types.ts @@ -62,16 +62,16 @@ export type SupportedTimezones = | 'Pacific/Fiji'; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_27B63E33". + * via the `definition` "LexicalNodes_29DEEC7D". */ -export type LexicalNodes_27B63E33 = +export type LexicalNodes_29DEEC7D = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -108,20 +108,20 @@ export type LexicalNodes_27B63E33 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_D85009C7". + * via the `definition` "LexicalNodes_C9EBCCB8". */ -export type LexicalNodes_D85009C7 = +export type LexicalNodes_C9EBCCB8 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode< | BenchBlock1 | BenchBlock2 @@ -157,7 +157,7 @@ export type LexicalNodes_D85009C7 = | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -194,28 +194,28 @@ export type LexicalNodes_D85009C7 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_A572658A". + * via the `definition` "LexicalNodes_29A2F1FE". */ -export type LexicalNodes_A572658A = +export type LexicalNodes_29A2F1FE = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -252,27 +252,27 @@ export type LexicalNodes_A572658A = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_B1F8D64B". + * via the `definition` "LexicalNodes_4D64798E". */ -export type LexicalNodes_B1F8D64B = +export type LexicalNodes_4D64798E = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedParagraphNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -309,23 +309,23 @@ export type LexicalNodes_B1F8D64B = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_E600437B". + * via the `definition` "LexicalNodes_9CB8FCB8". */ -export type LexicalNodes_E600437B = +export type LexicalNodes_9CB8FCB8 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedParagraphNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -362,33 +362,33 @@ export type LexicalNodes_E600437B = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_B06100BA". + * via the `definition` "LexicalNodes_2C2D92D6". */ -export type LexicalNodes_B06100BA = +export type LexicalNodes_2C2D92D6 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedListNode - | SerializedListItemNode; + | SerializedParagraphNode + | SerializedListNode + | SerializedListItemNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_652B8F46". + * via the `definition` "LexicalNodes_1DE931C3". */ -export type LexicalNodes_652B8F46 = +export type LexicalNodes_1DE931C3 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedHeadingNode + | SerializedParagraphNode + | SerializedHeadingNode | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -425,28 +425,28 @@ export type LexicalNodes_652B8F46 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_361E9E69". + * via the `definition` "LexicalNodes_A8D383AF". */ -export type LexicalNodes_361E9E69 = +export type LexicalNodes_A8D383AF = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> - | SerializedHeadingNode + | SerializedHeadingNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedListNode - | SerializedListItemNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -485,18 +485,18 @@ export type LexicalNodes_361E9E69 = >; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_E600EF15". + * via the `definition` "LexicalNodes_48D9D1B0". */ -export type LexicalNodes_E600EF15 = +export type LexicalNodes_48D9D1B0 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -533,11 +533,11 @@ export type LexicalNodes_E600EF15 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "BlockColumns". @@ -556,14 +556,14 @@ export type BlockColumns = | null; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_188B197D". + * via the `definition` "LexicalNodes_2EF528CD". */ -export type LexicalNodes_188B197D = +export type LexicalNodes_2EF528CD = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedHeadingNode + | SerializedParagraphNode + | SerializedHeadingNode | SerializedBlockNode< | RichTextBlock | TextRequired @@ -578,16 +578,16 @@ export type LexicalNodes_188B197D = | SerializedInlineBlockNode<{blockType: string}>; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_2FE228E9". + * via the `definition` "LexicalNodes_CB922BFF". */ -export type LexicalNodes_2FE228E9 = +export type LexicalNodes_CB922BFF = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode + | SerializedParagraphNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode | SerializedBlockNode< | ValidationBlock | FilterOptionsBlock @@ -618,10 +618,10 @@ export type LexicalNodes_2FE228E9 = | MyInlineBlockWithBlockAndLabel > | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -658,23 +658,23 @@ export type LexicalNodes_2FE228E9 = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_E2F7CFB3". + * via the `definition` "LexicalNodes_BE093052". */ -export type LexicalNodes_E2F7CFB3 = +export type LexicalNodes_BE093052 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -711,25 +711,25 @@ export type LexicalNodes_E2F7CFB3 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_15D85A4C". + * via the `definition` "LexicalNodes_68573818". */ -export type LexicalNodes_15D85A4C = +export type LexicalNodes_68573818 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -766,25 +766,25 @@ export type LexicalNodes_15D85A4C = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_B73866D0". + * via the `definition` "LexicalNodes_623E3672". */ -export type LexicalNodes_B73866D0 = +export type LexicalNodes_623E3672 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -821,25 +821,25 @@ export type LexicalNodes_B73866D0 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_B864F712". + * via the `definition` "LexicalNodes_2E7BE0FA". */ -export type LexicalNodes_B864F712 = +export type LexicalNodes_2E7BE0FA = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -876,25 +876,25 @@ export type LexicalNodes_B864F712 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_04808660". + * via the `definition` "LexicalNodes_67B1150A". */ -export type LexicalNodes_04808660 = +export type LexicalNodes_67B1150A = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -931,25 +931,25 @@ export type LexicalNodes_04808660 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_998D58F7". + * via the `definition` "LexicalNodes_3DA3D872". */ -export type LexicalNodes_998D58F7 = +export type LexicalNodes_3DA3D872 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -986,81 +986,81 @@ export type LexicalNodes_998D58F7 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_55712B26". + * via the `definition` "LexicalNodes_295A68C8". */ -export type LexicalNodes_55712B26 = +export type LexicalNodes_295A68C8 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedUploadNode<'uploads' | 'uploads2'>; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_3A6F021F". + * via the `definition` "LexicalNodes_245E32E8". */ -export type LexicalNodes_3A6F021F = +export type LexicalNodes_245E32E8 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}>; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_D39B65B3". + * via the `definition` "LexicalNodes_C91787A6". */ -export type LexicalNodes_D39B65B3 = +export type LexicalNodes_C91787A6 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode<{blockType: string}> | SerializedInlineBlockNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_A52479CF". + * via the `definition` "LexicalNodes_703DA597". */ -export type LexicalNodes_A52479CF = +export type LexicalNodes_703DA597 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}>; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_BCA20638". + * via the `definition` "LexicalNodes_86068B65". */ -export type LexicalNodes_BCA20638 = +export type LexicalNodes_86068B65 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedUploadNode<'uploads'> | SerializedRelationshipNode<'array-fields'> | SerializedHorizontalRuleNode - | SerializedQuoteNode - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedQuoteNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_24EBD3C5". + * via the `definition` "LexicalNodes_1A4AEB92". */ -export type LexicalNodes_24EBD3C5 = +export type LexicalNodes_1A4AEB92 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1099,24 +1099,24 @@ export type LexicalNodes_24EBD3C5 = > | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedQuoteNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_25924F55". + * via the `definition` "LexicalNodes_54186730". */ -export type LexicalNodes_25924F55 = +export type LexicalNodes_54186730 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedUploadNode<'uploads2'> | SerializedHorizontalRuleNode - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1153,25 +1153,25 @@ export type LexicalNodes_25924F55 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_52C5E759". + * via the `definition` "LexicalNodes_6DEEAAB8". */ -export type LexicalNodes_52C5E759 = +export type LexicalNodes_6DEEAAB8 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1208,27 +1208,27 @@ export type LexicalNodes_52C5E759 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_3A8AD1F5". + * via the `definition` "LexicalNodes_99E59AA4". */ -export type LexicalNodes_3A8AD1F5 = +export type LexicalNodes_99E59AA4 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1265,30 +1265,30 @@ export type LexicalNodes_3A8AD1F5 = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_172DC8C8". + * via the `definition` "LexicalNodes_D5461E96". */ -export type LexicalNodes_172DC8C8 = +export type LexicalNodes_D5461E96 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode + | SerializedParagraphNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> - | SerializedHeadingNode + | SerializedHeadingNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedListNode - | SerializedListItemNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1333,7 +1333,7 @@ export interface Config { }; blocks: { nestedBlock: NestedBlock; - blockWithBlockRef: BlockWithBlockRef_338FAE2E; + blockWithBlockRef: BlockWithBlockRef_DBAB1AB1; }; collections: { 'lexical-benchmark': LexicalBenchmark; @@ -1482,9 +1482,9 @@ export interface NestedBlock { * Multiple blocks resolve to the `BlockWithBlockRef` interface with different fields, so a content hash is appended to keep the generated types stable and unambiguous. Set a unique `interfaceName` on the block to choose the name yourself. See https://payloadcms.com/docs/typescript/generating-types#block-interface-name-collisions * * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "BlockWithBlockRef_338FAE2E". + * via the `definition` "BlockWithBlockRef_DBAB1AB1". */ -export interface BlockWithBlockRef_338FAE2E { +export interface BlockWithBlockRef_DBAB1AB1 { nestedBlocks?: NestedBlock[] | null; id?: string | null; blockName?: string | null; @@ -1496,7 +1496,7 @@ export interface BlockWithBlockRef_338FAE2E { */ export interface LexicalBenchmark { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1506,7 +1506,7 @@ export interface LexicalBenchmark { */ export interface LexicalFullyFeatured { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1519,7 +1519,7 @@ export interface LexicalAutosave { title?: string | null; cta?: | { - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; id?: string | null; }[] | null; @@ -1533,7 +1533,7 @@ export interface LexicalAutosave { */ export interface LexicalLinkFeature { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1543,7 +1543,7 @@ export interface LexicalLinkFeature { */ export interface LexicalListsFeature { id: string; - onlyOrderedList?: LexicalRichText | null; + onlyOrderedList?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1553,7 +1553,7 @@ export interface LexicalListsFeature { */ export interface LexicalHeadingFeature { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1563,7 +1563,7 @@ export interface LexicalHeadingFeature { */ export interface LexicalJsxConverter { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1574,15 +1574,15 @@ export interface LexicalJsxConverter { export interface LexicalField { id: string; title: string; - lexicalRootEditor?: LexicalRichText | null; + lexicalRootEditor?: LexicalRichText | null; /** * A simple lexical field */ - lexicalSimple?: LexicalRichText | null; + lexicalSimple?: LexicalRichText | null; /** * Should not be rendered */ - lexicalWithBlocks: LexicalRichText; + lexicalWithBlocks: LexicalRichText; lexicalWithBlocks_markdown?: string | null; updatedAt: string; createdAt: string; @@ -1593,8 +1593,8 @@ export interface LexicalField { */ export interface LexicalView { id: string; - customDefaultView?: LexicalRichText | null; - vanillaView?: LexicalRichText | null; + customDefaultView?: LexicalRichText | null; + vanillaView?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1604,7 +1604,7 @@ export interface LexicalView { */ export interface LexicalViewsFrontend { id: string; - customFrontendViews?: LexicalRichText | null; + customFrontendViews?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1615,7 +1615,7 @@ export interface LexicalViewsFrontend { export interface LexicalViewsProvider { id: string; viewProviderWrapper?: { - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; }; updatedAt: string; createdAt: string; @@ -1627,7 +1627,7 @@ export interface LexicalViewsProvider { export interface LexicalViewsProviderDefault { id: string; defaultViewWrapper?: { - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; }; updatedAt: string; createdAt: string; @@ -1639,7 +1639,7 @@ export interface LexicalViewsProviderDefault { export interface LexicalViewsProviderFallback { id: string; fallbackViewWrapper?: { - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; }; updatedAt: string; createdAt: string; @@ -1650,7 +1650,7 @@ export interface LexicalViewsProviderFallback { */ export interface LexicalViewsNested { id: string; - parentRichText?: LexicalRichText | null; + parentRichText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1664,11 +1664,11 @@ export interface LexicalLocalizedField { /** * Non-localized field with localized block subfields */ - lexicalBlocksSubLocalized?: LexicalRichText | null; + lexicalBlocksSubLocalized?: LexicalRichText | null; /** * Localized field with localized block subfields */ - lexicalBlocksLocalized?: LexicalRichText | null; + lexicalBlocksLocalized?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1678,8 +1678,8 @@ export interface LexicalLocalizedField { */ export interface LexicalObjectReferenceBug { id: string; - lexicalDefault?: LexicalRichText | null; - lexicalEditor?: LexicalRichText | null; + lexicalDefault?: LexicalRichText | null; + lexicalEditor?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1689,7 +1689,7 @@ export interface LexicalObjectReferenceBug { */ export interface LexicalInBlock { id: string; - content?: LexicalRichText | null; + content?: LexicalRichText | null; blocks?: LexicalInBlock2[] | null; updatedAt: string; createdAt: string; @@ -1699,7 +1699,7 @@ export interface LexicalInBlock { * via the `definition` "LexicalInBlock2". */ export interface LexicalInBlock2 { - lexical?: LexicalRichText | null; + lexical?: LexicalRichText | null; id?: string | null; blockName?: string | null; blockType: 'lexicalInBlock2'; @@ -1710,7 +1710,7 @@ export interface LexicalInBlock2 { */ export interface LexicalAutosaveBlock { id: string; - content?: LexicalRichText | null; + content?: LexicalRichText | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -1722,7 +1722,7 @@ export interface LexicalAutosaveBlock { export interface LexicalAccessControl { id: string; title?: string | null; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1732,10 +1732,10 @@ export interface LexicalAccessControl { */ export interface LexicalRelationshipField { id: string; - richText?: LexicalRichText | null; - richText2?: LexicalRichText | null; - richText3?: LexicalRichText | null; - richTextLocalized?: LexicalRichText | null; + richText?: LexicalRichText | null; + richText2?: LexicalRichText | null; + richText3?: LexicalRichText | null; + richTextLocalized?: LexicalRichText | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -1746,7 +1746,7 @@ export interface LexicalRelationshipField { */ export interface Collision { id: string; - collision?: LexicalRichText | null; + collision?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1757,7 +1757,7 @@ export interface Collision { export interface LexicalNestedBlock { id: string; title: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1768,12 +1768,12 @@ export interface LexicalNestedBlock { export interface RichTextField { id: string; title: string; - lexicalCustomFields: LexicalRichText; + lexicalCustomFields: LexicalRichText; lexicalCustomFields_html?: string | null; /** * This rich text field uses the lexical editor. */ - lexical?: LexicalRichText | null; + lexical?: LexicalRichText | null; /** * This select field is rendered here to ensure its options dropdown renders above the rich text toolbar. */ @@ -2021,7 +2021,7 @@ export interface OnDemandOutsideForm { | number | boolean | null; - hiddenAnchor?: LexicalRichText | null; + hiddenAnchor?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2032,7 +2032,7 @@ export interface OnDemandOutsideForm { export interface LexicalCustomCell { id: string; title: string; - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2873,10 +2873,10 @@ export interface PayloadMigrationsSelect { export interface TabsWithRichText { id: string; tab1?: { - rt1?: LexicalRichText | null; + rt1?: LexicalRichText | null; }; tab2?: { - rt2?: LexicalRichText | null; + rt2?: LexicalRichText | null; }; updatedAt?: string | null; createdAt?: string | null; @@ -3406,9 +3406,9 @@ export interface TextBlock { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_B1F8D64B". + * via the `definition` "LexicalLinkFields_4D64798E". */ -export interface LexicalLinkFields_B1F8D64B { +export interface LexicalLinkFields_4D64798E { linkBlocks?: LinkBlock[] | null; doc?: { relationTo: string; @@ -3426,9 +3426,9 @@ export interface LexicalLinkFields_B1F8D64B { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_E600437B". + * via the `definition` "LexicalLinkFields_9CB8FCB8". */ -export interface LexicalLinkFields_E600437B { +export interface LexicalLinkFields_9CB8FCB8 { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3470,9 +3470,9 @@ export interface MyBlock_89EF3EA7 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_361E9E69". + * via the `definition` "LexicalLinkFields_A8D383AF". */ -export interface LexicalLinkFields_361E9E69 { +export interface LexicalLinkFields_A8D383AF { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3495,7 +3495,7 @@ export interface LexicalLinkFields_361E9E69 { export interface LexicalAndUploadBlock { id: string; blockType: 'lexicalAndUploadBlock'; - subRichTextField?: LexicalRichText | null; + subRichTextField?: LexicalRichText | null; subUploadField?: (string | null) | Upload; blockName?: string | null; } @@ -3506,7 +3506,7 @@ export interface LexicalAndUploadBlock { export interface RichTextBlock { id: string; blockType: 'richTextBlock'; - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; blockName?: string | null; } /** @@ -3527,7 +3527,7 @@ export interface UploadAndRichText { id: string; blockType: 'uploadAndRichText'; upload: string | Upload; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; blockName?: string | null; } /** @@ -3577,7 +3577,7 @@ export interface ContentBlock { id: string; blockType: 'content-block'; title: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; blockName?: string | null; } /** @@ -3821,9 +3821,9 @@ export interface MyInlineBlockWithBlockAndLabel { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_2FE228E9". + * via the `definition` "LexicalLinkFields_CB922BFF". */ -export interface LexicalLinkFields_2FE228E9 { +export interface LexicalLinkFields_CB922BFF { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3861,7 +3861,7 @@ export interface BannerBlock { blockType: 'banner'; type: 'normal' | 'important'; title: string; - content?: LexicalRichText | null; + content?: LexicalRichText | null; blockName?: string | null; } /** @@ -3873,7 +3873,7 @@ export interface ProviderBannerBlock { blockType: 'banner'; type: 'normal' | 'important'; title: string; - content?: LexicalRichText | null; + content?: LexicalRichText | null; blockName?: string | null; } /** @@ -3884,7 +3884,7 @@ export interface NestedContentBlock { id: string; blockType: 'nested-content'; label: string; - nestedRichText?: LexicalRichText | null; + nestedRichText?: LexicalRichText | null; blockName?: string | null; } /** @@ -3920,7 +3920,7 @@ export interface BlockInLexical { /** * Some Description */ - lexicalInBlock: LexicalRichText; + lexicalInBlock: LexicalRichText; blockName?: string | null; } /** @@ -3939,7 +3939,7 @@ export interface InlineBlockInLexical { export interface BlockWithRichText { id: string; blockType: 'blockWithRichText'; - nestedRichText?: LexicalRichText | null; + nestedRichText?: LexicalRichText | null; blockName?: string | null; } /** @@ -3954,9 +3954,9 @@ export interface BlockWithBlockRef { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_3A8AD1F5". + * via the `definition` "LexicalLinkFields_99E59AA4". */ -export interface LexicalLinkFields_3A8AD1F5 { +export interface LexicalLinkFields_99E59AA4 { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3977,9 +3977,9 @@ export interface LexicalLinkFields_3A8AD1F5 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_172DC8C8". + * via the `definition` "LexicalLinkFields_D5461E96". */ -export interface LexicalLinkFields_172DC8C8 { +export interface LexicalLinkFields_D5461E96 { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -4172,6 +4172,6 @@ export interface SerializedTableCellNode extends SerializedLexicalEle declare module 'payload' { - // @ts-ignore + // @ts-ignore export interface GeneratedTypes extends Config {} -} +} \ No newline at end of file diff --git a/test/types/payload-types.ts b/test/types/payload-types.ts index bbf48cab025..610dd77771d 100644 --- a/test/types/payload-types.ts +++ b/test/types/payload-types.ts @@ -75,16 +75,16 @@ export type SupportedTimezones = | 'Pacific/Fiji'; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_F6A92CF8". + * via the `definition` "LexicalNodes_BFE38E95". */ -export type LexicalNodes_F6A92CF8 = +export type LexicalNodes_BFE38E95 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedHorizontalRuleNode | SerializedUploadNode<'media'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'posts' | 'pages' @@ -97,11 +97,11 @@ export type LexicalNodes_F6A92CF8 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; export interface Config { auth: { @@ -206,7 +206,7 @@ export interface PayloadMcpApiKeyAuthOperations { export interface Post { id: string; text?: string | null; - richText: LexicalRichText; + richText: LexicalRichText; title?: string | null; selectField: MySelectOptions; insideUnnamedGroup?: string | null; diff --git a/test/types/types.spec.ts b/test/types/types.spec.ts index 0a140974fbd..a00c9dd7006 100644 --- a/test/types/types.spec.ts +++ b/test/types/types.spec.ts @@ -47,7 +47,7 @@ import type { SerializedListItemNode as GenLI, SerializedLinkNode as GenLink, SerializedListNode as GenList, - LexicalNodes_F6A92CF8 as GenNodeUnion, + LexicalNodes_BFE38E95 as GenNodeUnion, SerializedParagraphNode as GenParagraph, SerializedQuoteNode as GenQuote, SerializedTabNode as GenTab, From 7c40bac80ef786c8402435d58f32e7b2494c06c6 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 4 Jun 2026 16:40:00 +0000 Subject: [PATCH 41/56] test that generated types are assignable to converters --- test/types/types.spec.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/types/types.spec.ts b/test/types/types.spec.ts index a00c9dd7006..2d3711d7673 100644 --- a/test/types/types.spec.ts +++ b/test/types/types.spec.ts @@ -1,3 +1,4 @@ +import type { SerializedEditorState } from '@payloadcms/richtext-lexical/lexical' import type { BulkOperationResult, CollectionSlug, @@ -35,6 +36,7 @@ import { type SerializedUploadNode, type TypedEditorState, } from '@payloadcms/richtext-lexical' +import { convertLexicalToPlaintext } from '@payloadcms/richtext-lexical/plaintext' import { PayloadSDK } from '@payloadcms/sdk' import payload from 'payload' import { describe, expect, test } from 'tstyche' @@ -375,6 +377,19 @@ describe('Types testing', () => { expect().type.toBeAssignableFrom() }) + test('ensure generated richText types can be assigned to SerializedEditorState (what converters consume)', () => { + // Every lexical converter (convertLexicalToHTML, convertLexicalToPlaintext, ...) accepts + // `data: SerializedEditorState`, so data straight from the local API must be assignable to it. + type GeneratedRichTextType = Post['richText'] + + expect().type.toBeAssignableFrom() + + // ...and the converter must accept the generated type directly, with no cast. + expect(convertLexicalToPlaintext).type.toBeCallableWith({ + data: null as unknown as GeneratedRichTextType, + }) + }) + test('ensure type property in editorState.root.children.push() is correctly typed as union of all node types', () => { const _editorState: DefaultTypedEditorState = null as unknown as DefaultTypedEditorState From 8d4cf82f82572c8a9aa4defdd8ccc63413641942 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 4 Jun 2026 18:00:57 +0000 Subject: [PATCH 42/56] feat: make it easier to use buildEditorState with generated types --- .../richtext-lexical/src/types/nodeTypes.ts | 9 +++++ .../src/utilities/buildEditorState.ts | 28 +++++++++++++--- test/lexical/seed.ts | 33 +++++++++++++++---- test/types/types.spec.ts | 27 +++++++++++++++ 4 files changed, 86 insertions(+), 11 deletions(-) diff --git a/packages/richtext-lexical/src/types/nodeTypes.ts b/packages/richtext-lexical/src/types/nodeTypes.ts index 79644303641..78da217ad58 100644 --- a/packages/richtext-lexical/src/types/nodeTypes.ts +++ b/packages/richtext-lexical/src/types/nodeTypes.ts @@ -103,6 +103,15 @@ export type { export type TypedEditorState = LexicalRichText +/** + * The node union of a generated `richText` field. Pass the field type — e.g. + * `RichTextNodes` — to type an individual node you build for that editor (for + * example a single block, or a `.map()` of nodes). To build a whole editor state, prefer passing + * the field type straight to {@link buildEditorState}. + */ +export type RichTextNodes = + NonNullable extends LexicalRichText ? TNode : never + /** * All node types included by default in a lexical editor. Self-recursive — * each element node's `children` is `DefaultNodeTypes` again, no depth limit. diff --git a/packages/richtext-lexical/src/utilities/buildEditorState.ts b/packages/richtext-lexical/src/utilities/buildEditorState.ts index 3abc8e868e5..97dcf4cc562 100644 --- a/packages/richtext-lexical/src/utilities/buildEditorState.ts +++ b/packages/richtext-lexical/src/utilities/buildEditorState.ts @@ -6,6 +6,15 @@ import type { TypedEditorState, } from '../types/nodeTypes.js' +/** + * The node union to build with. Accepts either a node union directly (e.g. `DefaultNodeTypes`) or a + * generated `richText` field type (e.g. `Post['richText']`), whose nodes are extracted automatically. + */ +type BuildNodes = + NonNullable extends TypedEditorState + ? TNode + : Extract, SerializedLexicalNode> + /** * Helper to build lexical editor state JSON from text and/or nodes. * @@ -42,14 +51,25 @@ import type { * ], * }) * ``` + * + * @example + * + * passing a generated `richText` field type — the result is exactly that field's type: + * + * ```ts + * post.richText = buildEditorState({ text: 'Hello world' }) + * ``` */ -export function buildEditorState({ +export function buildEditorState< + T extends null | SerializedLexicalNode | TypedEditorState | undefined = + DefaultNodeTypes, +>({ nodes, text, }: { - nodes?: TypedEditorState['root']['children'] + nodes?: TypedEditorState>['root']['children'] text?: string -}): TypedEditorState { +}): TypedEditorState> { const editorJSON: DefaultTypedEditorState = { root: { type: 'root', @@ -103,7 +123,7 @@ export function buildEditorState({ }) } - return editorJSON as TypedEditorState + return editorJSON as TypedEditorState> } /** diff --git a/test/lexical/seed.ts b/test/lexical/seed.ts index 07e4550d037..cd6ea5de27d 100644 --- a/test/lexical/seed.ts +++ b/test/lexical/seed.ts @@ -22,11 +22,20 @@ import { // import type { Payload } from 'payload' -import { buildEditorState, type DefaultNodeTypes } from '@payloadcms/richtext-lexical' +import { + buildEditorState, + type DefaultNodeTypes, + type RichTextNodes, +} from '@payloadcms/richtext-lexical' import { getFileByPath } from 'payload' import type { LexicalViewsNodes } from './collections/LexicalViews/index.js' import type { LexicalViewsFrontendNodes } from './collections/LexicalViewsFrontend/index.js' +import type { + LexicalBenchmark, + LexicalInBlock2, + LexicalRelationshipField, +} from './payload-types.js' import { seedDB } from '../__helpers/shared/clearAndSeed/seed.js' import { devUser } from '../credentials.js' @@ -421,11 +430,18 @@ export const seed = async (_payload: Payload) => { await _payload.create({ collection: lexicalRelationshipFieldsSlug, data: { - richText: buildEditorState({ text: 'English text' }), + richText: buildEditorState({ text: 'English text' }), }, depth: 0, }) + // The 2nd child is the localized block — narrow to a node that carries `fields` to reuse its id. + const localizedBlock = lexicalLocalizedDoc1.lexicalBlocksSubLocalized?.root.children[1] + const localizedBlockID = + localizedBlock && 'fields' in localizedBlock && typeof localizedBlock.fields.id === 'string' + ? localizedBlock.fields.id + : undefined + await _payload.update({ id: lexicalLocalizedDoc1.id, collection: lexicalLocalizedFieldsSlug, @@ -434,7 +450,7 @@ export const seed = async (_payload: Payload) => { lexicalBlocksSubLocalized: generateLexicalLocalizedRichText( 'Shared text', 'Spanish text in block', - (lexicalLocalizedDoc1?.lexicalBlocksSubLocalized?.root?.children[1]?.fields as any).id, + localizedBlockID, ) as any, title: 'Localized Lexical es', }, @@ -499,7 +515,10 @@ export const seed = async (_payload: Payload) => { locale: 'es', }) - const getInlineBlock = () => ({ + const getInlineBlock = (): Extract< + RichTextNodes, + { type: 'inlineBlock' } + > => ({ type: 'inlineBlock', fields: { id: Math.random().toString(36).substring(2, 15), @@ -516,12 +535,12 @@ export const seed = async (_payload: Payload) => { { blockName: '1', blockType: 'lexicalInBlock2', - lexical: buildEditorState({ text: '1' }), + lexical: buildEditorState({ text: '1' }), }, { blockName: '2', blockType: 'lexicalInBlock2', - lexical: buildEditorState({ text: '2' }), + lexical: buildEditorState({ text: '2' }), }, { id: '67e1af0b78de3228e23ef1d5', @@ -656,7 +675,7 @@ export const seed = async (_payload: Payload) => { blockName: '', blockType: `benchBlock${i + 1}`, }, - })) + })) as Extract, { type: 'block' }>[] await _payload.create({ collection: lexicalBenchmarkSlug, diff --git a/test/types/types.spec.ts b/test/types/types.spec.ts index 2d3711d7673..ccb6b32eb80 100644 --- a/test/types/types.spec.ts +++ b/test/types/types.spec.ts @@ -772,6 +772,33 @@ describe('Types testing', () => { expect(result).type.toBeAssignableTo() }) + test('buildEditorState accepts a generated field type directly and returns exactly it', () => { + // The ergonomic path for users with generated types: pass the field type, no node extraction. + const result = buildEditorState({ text: 'hello' }) + expect(result).type.toBe() + }) + + test('buildEditorState with a generated field type directly narrows `nodes` to the field — a registered node type is accepted', () => { + // `horizontalrule` is part of this editor, so calling with it is valid. + expect(buildEditorState).type.toBeCallableWith({ + nodes: [{ type: 'horizontalrule', version: 1 }], + }) + }) + + test('buildEditorState with a generated field type directly narrows `nodes` to the field — an unregistered node type errors', () => { + // `block` is not enabled on this editor, so calling with it is rejected. + expect(buildEditorState).type.not.toBeCallableWith({ + nodes: [ + { + type: 'block', + fields: { id: 'x', blockName: '', blockType: 'whatever' }, + format: '', + version: 1, + }, + ], + }) + }) + test('buildEditorState allows pushing typed nodes to children', () => { const result = buildEditorState({ text: 'hello' }) result.root.children.push({ From 34826f76ad851ffffa69b7c0ca248f7230d35c6d Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 4 Jun 2026 18:02:15 +0000 Subject: [PATCH 43/56] docs --- docs/rich-text/overview.mdx | 47 +++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/docs/rich-text/overview.mdx b/docs/rich-text/overview.mdx index 7b763821e7c..a558a525885 100644 --- a/docs/rich-text/overview.mdx +++ b/docs/rich-text/overview.mdx @@ -140,7 +140,9 @@ You can find more information about creating your own feature in our [building c Every single piece of saved data is 100% fully typed within lexical. It provides a type for every single node, which can be imported from `@payloadcms/richtext-lexical` - each type is prefixed with `Serialized`, e.g., `SerializedUploadNode`. -To fully type the entire editor JSON, you can use our `TypedEditorState` helper type, which accepts a union of all possible node types as a generic. We don't provide a type that already contains all possible node types because they depend on which features you have enabled in your editor. Here is an example: +If you have [generated types](#automatic-type-generation), each `richText` field is already fully typed - reference it directly (e.g. `Post['richText']`) instead of assembling a union by hand. + +To type editor state without generated types, use our `TypedEditorState` helper type, which accepts a union of all possible node types as a generic. We don't provide a type that already contains all possible node types because they depend on which features you have enabled in your editor. Here is an example: ```ts import type { @@ -253,7 +255,48 @@ Make sure to only use types exported from `@payloadcms/richtext-lexical`, not fr ### Automatic type generation -Lexical does not generate accurate type definitions for your richText fields for you yet - this will be improved in the future. Currently, it only outputs the rough shape of the editor JSON, which you can enhance using type assertions. +When you [generate types](../typescript/generating-types), every `richText` field gets an accurate, fully-typed definition based on the exact features enabled on _that_ editor. Each field's nodes are narrowed to what the editor actually allows - including your custom blocks and the specific collections its relationship and upload nodes can point to. + +You can reference a field's editor state type straight from your generated types - no manual `TypedEditorState` union, no type assertions: + +```ts +import type { Post } from './payload-types' + +// Fully typed and narrowed to this editor's nodes - use it wherever you need the field's type +type PostRichText = Post['richText'] +``` + +This data is also directly assignable to the `SerializedEditorState` that every [converter](./converting-html) accepts, so you can pass it straight through: + +```ts +import { convertLexicalToHTML } from '@payloadcms/richtext-lexical/html' + +const html = convertLexicalToHTML({ data: post.richText }) +``` + +### Building editor state + +Use the `buildEditorState` helper to construct editor state JSON from text and/or nodes. Pass your generated field type as the generic and the result is exactly that field's type - with the `nodes` you pass checked against that editor's allowed nodes: + +```ts +import { buildEditorState } from '@payloadcms/richtext-lexical' + +import type { Post } from './payload-types' + +post.richText = buildEditorState({ text: 'Hello world' }) +``` + +If you don't have a generated type, you can pass a node union instead (e.g. `buildEditorState({ text: 'Hello world' })`). + +To type an individual node you build by hand (for example a single block, or a `.map()` of nodes), use the `RichTextNodes` helper to pull a field's node union out of its generated type: + +```ts +import type { RichTextNodes } from '@payloadcms/richtext-lexical' + +import type { Post } from './payload-types' + +type PostNode = RichTextNodes +``` ## Admin customization From 0500a45d313892d8c7e88d3ed0cf841cd791639a Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 4 Jun 2026 18:26:52 +0000 Subject: [PATCH 44/56] update incorrect migration docs --- docs/migration-guide/v4.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/migration-guide/v4.mdx b/docs/migration-guide/v4.mdx index ed631e36beb..81486196a39 100644 --- a/docs/migration-guide/v4.mdx +++ b/docs/migration-guide/v4.mdx @@ -533,7 +533,7 @@ If you wrote a custom feature that overrode `modifyJSONSchema`, move per-node ge }) ``` -Nodes without a `jsonSchema` function fall back to `{ [k: string]: unknown }`, so omitting it is safe — just looser. +Nodes without a `jsonSchema` function are omitted from the generated node union entirely — they're filtered out, with no fallback shape. Define `jsonSchema` for every custom node you want reflected in the types; otherwise that node won't appear in the field's generated type, and editor state containing it won't be assignable to it. ### Lexical: duplicate node registration throws From 398799a36501dade73b4f9d50c7e85dac7c564e8 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 4 Jun 2026 18:29:28 +0000 Subject: [PATCH 45/56] fix: two identical lexical fields with differing link node fields generate the same, conflicting generated type --- packages/richtext-lexical/src/types/schema.ts | 15 +++++- test/lexical/lexical.int.spec.ts | 49 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/packages/richtext-lexical/src/types/schema.ts b/packages/richtext-lexical/src/types/schema.ts index a33bb89654e..0a5f04c82ba 100644 --- a/packages/richtext-lexical/src/types/schema.ts +++ b/packages/richtext-lexical/src/types/schema.ts @@ -77,7 +77,20 @@ export const getFieldToJSONSchema: (args: { // See JSDocs for `NODE_UNION_NAME_PLACEHOLDER` for why we use a placeholder and hashing. const nodeUnionJson = JSON.stringify({ oneOf: nodeSchemas }) - const hash = createHash('sha256').update(nodeUnionJson).digest('hex').slice(0, 8).toUpperCase() + // Features can register per-editor definitions during node-schema build (e.g. a link node's + // custom `LexicalLinkFields_`), keyed by the not-yet-resolved hash placeholder. The node + // union only `$ref`s them, so their content isn't in `nodeUnionJson` - two editors with the same + // nodes but different feature config (e.g. different custom link fields) would otherwise hash + // identically and overwrite each other's definition. To avoid that, include that content into the hash too. + const pendingDefinitions = [...interfaceNameDefinitions.entries()] + .filter(([key]) => key.includes(NODE_UNION_HASH_PLACEHOLDER)) + .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)) + + const hashInput = pendingDefinitions.length + ? JSON.stringify({ definitions: pendingDefinitions, oneOf: nodeSchemas }) + : nodeUnionJson + + const hash = createHash('sha256').update(hashInput).digest('hex').slice(0, 8).toUpperCase() const nodeUnionName = `LexicalNodes_${hash}` // Replacing the hash resolves the union name and any feature-derived diff --git a/test/lexical/lexical.int.spec.ts b/test/lexical/lexical.int.spec.ts index eae4d1b26a5..2d2e9181527 100644 --- a/test/lexical/lexical.int.spec.ts +++ b/test/lexical/lexical.int.spec.ts @@ -9,6 +9,7 @@ import { buildEditorState, type DefaultNodeTypes, lexicalEditor, + LinkFeature, type SerializedBlockNode, type SerializedLinkNode, type SerializedRelationshipNode, @@ -1319,3 +1320,51 @@ describe('Lexical block interface generation', () => { }, ) }) + +describe('Lexical link fields interface generation', () => { + // The node-union name is a content hash of the editor's nodes. A link node only carries a `$ref` + // to its `LexicalLinkFields_` interface, whose *content* lives separately — so two editors + // with identical nodes but different custom LinkFeature fields must not hash the same, or one + // `LexicalLinkFields_` would overwrite the other and mistype a field. + vitestIt( + 'gives editors with identical nodes but different custom link fields distinct interfaces', + async () => { + const linkEditor = (fieldName: string) => + lexicalEditor({ + features: [ + LinkFeature({ + fields: ({ defaultFields }) => [...defaultFields, { name: fieldName, type: 'text' }], + }), + ], + }) + + // Two richText fields with the same nodes, differing only in their custom link field. + const config = { + collections: [ + { + slug: 'linkCollisionTest', + fields: [ + { name: 'rt1', type: 'richText', editor: linkEditor('label') }, + { name: 'rt2', type: 'richText', editor: linkEditor('trackingId') }, + ], + }, + ], + } as unknown as Config + + const sanitizedConfig = await sanitizeConfig(config) + const { jsonSchema } = configToJSONSchema(sanitizedConfig, 'text') + const defs = jsonSchema.$defs! + + // Each editor gets its own custom-link-fields interface (not a single shared, overwritten one). + const linkFieldsNames = Object.keys(defs).filter((k) => + /^LexicalLinkFields_[0-9A-F]{8}$/.test(k), + ) + expect(linkFieldsNames).toHaveLength(2) + + // ...and each carries its own custom field (`label` vs `trackingId`), not a silent overwrite. + const propsOf = (name: string): string[] => + Object.keys((defs[name] as { properties: Record }).properties).sort() + expect(propsOf(linkFieldsNames[0]!)).not.toEqual(propsOf(linkFieldsNames[1]!)) + }, + ) +}) From 5f595dfdda2c6679d5c567fa0e339083350e035b Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 4 Jun 2026 18:31:32 +0000 Subject: [PATCH 46/56] fix: two identical interfaceName properties can generate the same conflicting type, overriding each other. Now, they are subject to the same hashing mechanism as auto-generated ones --- .../src/utilities/configToJSONSchema.spec.ts | 68 +++++++++++++++++++ .../src/utilities/configToJSONSchema.ts | 13 ++-- 2 files changed, 75 insertions(+), 6 deletions(-) diff --git a/packages/payload/src/utilities/configToJSONSchema.spec.ts b/packages/payload/src/utilities/configToJSONSchema.spec.ts index bee323acdb8..c53fa578f06 100644 --- a/packages/payload/src/utilities/configToJSONSchema.spec.ts +++ b/packages/payload/src/utilities/configToJSONSchema.spec.ts @@ -459,6 +459,74 @@ describe('configToJSONSchema', () => { expect(schema?.$defs?.SharedBlock).toStrictEqual(expectedBlockSchema) }) + it('content-hashes a colliding explicit interfaceName instead of overwriting it', async () => { + // Two different blocks both set `interfaceName: 'Hero'` - each must keep its own definition. + const config: Config = { + collections: [ + { + slug: 'test', + fields: [ + { + name: 'blocksField', + type: 'blocks', + blocks: [ + { slug: 'blockA', fields: [{ name: 'title', type: 'text' }], interfaceName: 'Hero' }, + { + slug: 'blockB', + fields: [{ name: 'subtitle', type: 'number' }], + interfaceName: 'Hero', + }, + ], + }, + ], + timestamps: false, + }, + ], + } as unknown as Config + + const sanitizedConfig = await sanitizeConfig(config) + const { jsonSchema } = configToJSONSchema(sanitizedConfig, 'text') + const defs = jsonSchema.$defs! + + // Each differently-shaped block keeps its own interface (one clean, one hash-suffixed). + const heroNames = Object.keys(defs).filter((k) => /^Hero(_[0-9A-F]{8})?$/.test(k)) + expect(heroNames).toHaveLength(2) + + // ...and they carry distinct field shapes (not a silent overwrite). + const shapeOf = (name: string): string => + Object.keys((defs[name] as { properties: Record }).properties) + .sort() + .join(',') + expect(shapeOf(heroNames[0]!)).not.toBe(shapeOf(heroNames[1]!)) + }) + + it('reuses one definition when the same block is registered more than once', async () => { + // Reusing one block across fields registers an identical schema each time, so it dedupes. + const heroBlock = { + slug: 'hero', + fields: [{ name: 'title', type: 'text' }], + interfaceName: 'Hero', + } + const config: Config = { + collections: [ + { + slug: 'test', + fields: [ + { name: 'a', type: 'blocks', blocks: [heroBlock] }, + { name: 'b', type: 'blocks', blocks: [heroBlock] }, + ], + timestamps: false, + }, + ], + } as unknown as Config + + const sanitizedConfig = await sanitizeConfig(config) + const { jsonSchema } = configToJSONSchema(sanitizedConfig, 'text') + + const heroNames = Object.keys(jsonSchema.$defs!).filter((k) => /^Hero(_[0-9A-F]{8})?$/.test(k)) + expect(heroNames).toEqual(['Hero']) + }) + it('should allow overriding required to false', async () => { // @ts-expect-error const config: Config = { diff --git a/packages/payload/src/utilities/configToJSONSchema.ts b/packages/payload/src/utilities/configToJSONSchema.ts index 6f6a4a317bc..14d87ff310d 100644 --- a/packages/payload/src/utilities/configToJSONSchema.ts +++ b/packages/payload/src/utilities/configToJSONSchema.ts @@ -1346,9 +1346,10 @@ const hashBlockSchema = (schema: JSONSchema4): string => /** * Registers a block's schema as a top-level definition and returns its name. * - * The name is the block's `interfaceName`, or a PascalCase form of its slug. If a different - * block already uses that name, this one gets a content-hash suffix (`Hero_3F2A1B0C`) so the - * two don't overwrite each other. Registering the same block shape again reuses its name. + * The name is the block's `interfaceName`, or a PascalCase form of its slug. If a different block + * already uses that name - whether it was auto-generated or an explicit `interfaceName` - this one + * gets a content-hash suffix (`Hero_3F2A1B0C`) so the two don't overwrite each other. Registering + * the same block shape again reuses its name. */ export function registerBlockInterface( block: { interfaceName?: string; slug: string }, @@ -1358,8 +1359,8 @@ export function registerBlockInterface( const baseName = block.interfaceName ?? toWords(block.slug, true) const existing = interfaceNameDefinitions.get(baseName) - // Use the clean name if it is free, or if the block sets an explicit interfaceName. - if (!existing || block.interfaceName) { + // The name is free - claim it. + if (!existing) { interfaceNameDefinitions.set(baseName, blockSchema) return baseName } @@ -1371,7 +1372,7 @@ export function registerBlockInterface( return baseName } - // A different block already owns the clean name. Disambiguate this one with its hash. + // A different block already owns the name. Disambiguate this one with its hash. blockSchema.description = `Multiple blocks resolve to the \`${baseName}\` interface with different fields, so a content hash is appended to keep the generated types stable and unambiguous. Set a unique \`interfaceName\` on the block to choose the name yourself. See https://payloadcms.com/docs/typescript/generating-types#block-interface-name-collisions` const uniqueName = `${baseName}_${hash}` From 52306b782435a099674726d7bc29b83ffba2aa65 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 4 Jun 2026 18:31:51 +0000 Subject: [PATCH 47/56] types --- test/lexical/payload-types.ts | 297 ++++++++++++++++++++----------- test/plugin-mcp/payload-types.ts | 22 +-- 2 files changed, 202 insertions(+), 117 deletions(-) diff --git a/test/lexical/payload-types.ts b/test/lexical/payload-types.ts index 97452706c28..4435a393272 100644 --- a/test/lexical/payload-types.ts +++ b/test/lexical/payload-types.ts @@ -259,20 +259,20 @@ export type LexicalNodes_29A2F1FE = | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_4D64798E". + * via the `definition` "LexicalNodes_E05AD439". */ -export type LexicalNodes_4D64798E = +export type LexicalNodes_E05AD439 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedParagraphNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -309,23 +309,23 @@ export type LexicalNodes_4D64798E = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_9CB8FCB8". + * via the `definition` "LexicalNodes_533C9B9B". */ -export type LexicalNodes_9CB8FCB8 = +export type LexicalNodes_533C9B9B = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedParagraphNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -362,9 +362,9 @@ export type LexicalNodes_9CB8FCB8 = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "LexicalNodes_2C2D92D6". @@ -431,22 +431,22 @@ export type LexicalNodes_1DE931C3 = | SerializedListItemNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_A8D383AF". + * via the `definition` "LexicalNodes_3F819CB3". */ -export type LexicalNodes_A8D383AF = +export type LexicalNodes_3F819CB3 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> - | SerializedHeadingNode + | SerializedHeadingNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedListNode - | SerializedListItemNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -578,16 +578,16 @@ export type LexicalNodes_2EF528CD = | SerializedInlineBlockNode<{blockType: string}>; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_CB922BFF". + * via the `definition` "LexicalNodes_66D9025B". */ -export type LexicalNodes_CB922BFF = +export type LexicalNodes_66D9025B = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode + | SerializedParagraphNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode | SerializedBlockNode< | ValidationBlock | FilterOptionsBlock @@ -618,10 +618,10 @@ export type LexicalNodes_CB922BFF = | MyInlineBlockWithBlockAndLabel > | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -658,9 +658,9 @@ export type LexicalNodes_CB922BFF = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "LexicalNodes_BE093052". @@ -773,18 +773,18 @@ export type LexicalNodes_68573818 = | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_623E3672". + * via the `definition` "LexicalNodes_63106233". */ -export type LexicalNodes_623E3672 = +export type LexicalNodes_63106233 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedBlockNode + | SerializedParagraphNode + | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -821,11 +821,11 @@ export type LexicalNodes_623E3672 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "LexicalNodes_2E7BE0FA". @@ -1034,6 +1034,59 @@ export type LexicalNodes_703DA597 = | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}>; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_3D210EC6". + */ +export type LexicalNodes_3D210EC6 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedHorizontalRuleNode + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'lexical-benchmark' + | 'lexical-fully-featured' + | 'lexical-autosave' + | 'lexical-link-feature' + | 'lexical-lists-features' + | 'lexical-heading-feature' + | 'lexical-jsx-converter' + | 'lexical-fields' + | 'lexical-views' + | 'lexical-views-frontend' + | 'lexical-views-provider' + | 'lexical-views-provider-default' + | 'lexical-views-provider-fallback' + | 'lexical-views-nested' + | 'lexical-localized-fields' + | 'lexicalObjectReferenceBug' + | 'LexicalInBlock' + | 'lexical-autosave-block' + | 'lexical-access-control' + | 'lexical-relationship-fields' + | 'collision' + | 'lexical-nested-blocks' + | 'rich-text-fields' + | 'text-fields' + | 'array-fields' + | 'OnDemandForm' + | 'OnDemandOutsideForm' + | 'lexical-custom-cell' + | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "LexicalNodes_86068B65". @@ -1215,20 +1268,20 @@ export type LexicalNodes_6DEEAAB8 = | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_99E59AA4". + * via the `definition` "LexicalNodes_8B8AF2BD". */ -export type LexicalNodes_99E59AA4 = +export type LexicalNodes_8B8AF2BD = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1265,30 +1318,30 @@ export type LexicalNodes_99E59AA4 = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_D5461E96". + * via the `definition` "LexicalNodes_0B0D3C8D". */ -export type LexicalNodes_D5461E96 = +export type LexicalNodes_0B0D3C8D = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode + | SerializedParagraphNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> - | SerializedHeadingNode + | SerializedHeadingNode | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedListNode - | SerializedListItemNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1519,7 +1572,7 @@ export interface LexicalAutosave { title?: string | null; cta?: | { - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; id?: string | null; }[] | null; @@ -1533,7 +1586,7 @@ export interface LexicalAutosave { */ export interface LexicalLinkFeature { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1574,7 +1627,7 @@ export interface LexicalJsxConverter { export interface LexicalField { id: string; title: string; - lexicalRootEditor?: LexicalRichText | null; + lexicalRootEditor?: LexicalRichText | null; /** * A simple lexical field */ @@ -1582,7 +1635,7 @@ export interface LexicalField { /** * Should not be rendered */ - lexicalWithBlocks: LexicalRichText; + lexicalWithBlocks: LexicalRichText; lexicalWithBlocks_markdown?: string | null; updatedAt: string; createdAt: string; @@ -1615,7 +1668,7 @@ export interface LexicalViewsFrontend { export interface LexicalViewsProvider { id: string; viewProviderWrapper?: { - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; }; updatedAt: string; createdAt: string; @@ -1678,7 +1731,7 @@ export interface LexicalLocalizedField { */ export interface LexicalObjectReferenceBug { id: string; - lexicalDefault?: LexicalRichText | null; + lexicalDefault?: LexicalRichText | null; lexicalEditor?: LexicalRichText | null; updatedAt: string; createdAt: string; @@ -1722,7 +1775,7 @@ export interface LexicalAutosaveBlock { export interface LexicalAccessControl { id: string; title?: string | null; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1768,7 +1821,7 @@ export interface LexicalNestedBlock { export interface RichTextField { id: string; title: string; - lexicalCustomFields: LexicalRichText; + lexicalCustomFields: LexicalRichText; lexicalCustomFields_html?: string | null; /** * This rich text field uses the lexical editor. @@ -2021,7 +2074,7 @@ export interface OnDemandOutsideForm { | number | boolean | null; - hiddenAnchor?: LexicalRichText | null; + hiddenAnchor?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -3406,9 +3459,9 @@ export interface TextBlock { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_4D64798E". + * via the `definition` "LexicalLinkFields_E05AD439". */ -export interface LexicalLinkFields_4D64798E { +export interface LexicalLinkFields_E05AD439 { linkBlocks?: LinkBlock[] | null; doc?: { relationTo: string; @@ -3426,9 +3479,9 @@ export interface LexicalLinkFields_4D64798E { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_9CB8FCB8". + * via the `definition` "LexicalLinkFields_533C9B9B". */ -export interface LexicalLinkFields_9CB8FCB8 { +export interface LexicalLinkFields_533C9B9B { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3442,17 +3495,7 @@ export interface LexicalLinkFields_9CB8FCB8 { }; } | null; newTab: boolean; - blocks?: Block[] | null; -} -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "Block". - */ -export interface Block { - text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'block'; + someText?: string | null; } /** * Multiple blocks resolve to the `MyBlock` interface with different fields, so a content hash is appended to keep the generated types stable and unambiguous. Set a unique `interfaceName` on the block to choose the name yourself. See https://payloadcms.com/docs/typescript/generating-types#block-interface-name-collisions @@ -3470,9 +3513,9 @@ export interface MyBlock_89EF3EA7 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_A8D383AF". + * via the `definition` "LexicalLinkFields_3F819CB3". */ -export interface LexicalLinkFields_A8D383AF { +export interface LexicalLinkFields_3F819CB3 { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3574,11 +3617,10 @@ export interface RelationshipHasManyBlock { * via the `definition` "ContentBlock". */ export interface ContentBlock { - id: string; - blockType: 'content-block'; - title: string; - richText?: LexicalRichText | null; + richText: LexicalRichText; + id?: string | null; blockName?: string | null; + blockType: 'contentBlock'; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -3821,9 +3863,9 @@ export interface MyInlineBlockWithBlockAndLabel { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_CB922BFF". + * via the `definition` "LexicalLinkFields_66D9025B". */ -export interface LexicalLinkFields_CB922BFF { +export interface LexicalLinkFields_66D9025B { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3864,6 +3906,19 @@ export interface BannerBlock { content?: LexicalRichText | null; blockName?: string | null; } +/** + * Multiple blocks resolve to the `ContentBlock` interface with different fields, so a content hash is appended to keep the generated types stable and unambiguous. Set a unique `interfaceName` on the block to choose the name yourself. See https://payloadcms.com/docs/typescript/generating-types#block-interface-name-collisions + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "ContentBlock_A3B1CF88". + */ +export interface ContentBlock_A3B1CF88 { + id: string; + blockType: 'content-block'; + title: string; + richText?: LexicalRichText | null; + blockName?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "ProviderBannerBlock". @@ -3942,6 +3997,36 @@ export interface BlockWithRichText { nestedRichText?: LexicalRichText | null; blockName?: string | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Block". + */ +export interface Block { + text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'block'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_3D210EC6". + */ +export interface LexicalLinkFields_3D210EC6 { + linkType: 'custom' | 'internal'; + url?: string; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + newTab: boolean; + blocks?: Block[] | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "BlockWithBlockRef". @@ -3954,9 +4039,9 @@ export interface BlockWithBlockRef { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_99E59AA4". + * via the `definition` "LexicalLinkFields_8B8AF2BD". */ -export interface LexicalLinkFields_99E59AA4 { +export interface LexicalLinkFields_8B8AF2BD { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3977,9 +4062,9 @@ export interface LexicalLinkFields_99E59AA4 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_D5461E96". + * via the `definition` "LexicalLinkFields_0B0D3C8D". */ -export interface LexicalLinkFields_D5461E96 { +export interface LexicalLinkFields_0B0D3C8D { linkType: 'custom' | 'internal'; url?: string; doc?: { diff --git a/test/plugin-mcp/payload-types.ts b/test/plugin-mcp/payload-types.ts index 0cbbbbb297a..8b665d1fb93 100644 --- a/test/plugin-mcp/payload-types.ts +++ b/test/plugin-mcp/payload-types.ts @@ -318,17 +318,7 @@ export interface ReturnedResource { export interface Page { id: string; title: string; - layout?: - | ( - | HeroBlock - | { - body?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'textContent'; - } - )[] - | null; + layout?: (HeroBlock | TextContent)[] | null; updatedAt: string; createdAt: string; } @@ -343,6 +333,16 @@ export interface HeroBlock { blockName?: string | null; blockType: 'hero'; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TextContent". + */ +export interface TextContent { + body?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'textContent'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "field-types". From 8a5a0559ad39cb5a5df957a0de19d2349fa4237c Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 4 Jun 2026 18:58:18 +0000 Subject: [PATCH 48/56] fix: simplifyRelationshipFields incorrectly converting oneOf to anyOf --- .../prepareCollectionSchema.spec.ts | 102 ++++++++++++++++++ .../simplifyRelationshipFields.ts | 3 +- 2 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 packages/plugin-mcp/src/utils/schemaConversion/prepareCollectionSchema.spec.ts diff --git a/packages/plugin-mcp/src/utils/schemaConversion/prepareCollectionSchema.spec.ts b/packages/plugin-mcp/src/utils/schemaConversion/prepareCollectionSchema.spec.ts new file mode 100644 index 00000000000..72ebfe5e763 --- /dev/null +++ b/packages/plugin-mcp/src/utils/schemaConversion/prepareCollectionSchema.spec.ts @@ -0,0 +1,102 @@ +import { describe, expect, it } from 'vitest' + +import type { JsonSchemaType } from '../../types.js' + +import { prepareCollectionSchema } from './prepareCollectionSchema.js' + +describe('prepareCollectionSchema', () => { + it('keeps a Lexical node union strict (oneOf) while simplifying relationship values to IDs', () => { + // Shaped like the schema the MCP server prepares for a collection with a Lexical richText field: + // a `$defs` node union (a `oneOf` of node shapes) where a relationship node's `value` is either + // an ID or a `$ref` to the populated related collection. + const standalone: JsonSchemaType = { + type: 'object', + $defs: { + LexicalNodes_ABCDEF12: { + oneOf: [ + { + type: 'object', + additionalProperties: false, + properties: { type: { const: 'paragraph' } }, + required: ['type'], + }, + { + type: 'object', + additionalProperties: false, + properties: { + type: { const: 'relationship' }, + value: { oneOf: [{ type: 'string' }, { $ref: '#/$defs/posts' }] }, + }, + required: ['type'], + }, + ], + }, + posts: { + type: 'object', + additionalProperties: false, + properties: { id: { type: 'string' }, title: { type: 'string' } }, + }, + }, + properties: { + id: { type: 'string' }, + content: { + type: 'object', + properties: { + root: { + type: 'object', + properties: { + children: { type: 'array', items: { $ref: '#/$defs/LexicalNodes_ABCDEF12' } }, + }, + }, + }, + }, + }, + } + + expect(prepareCollectionSchema(standalone)).toStrictEqual({ + type: 'object', + $defs: { + // The node union stays a strict discriminated `oneOf` - not loosened to `anyOf`... + LexicalNodes_ABCDEF12: { + oneOf: [ + { + type: 'object', + additionalProperties: false, + properties: { type: { const: 'paragraph' } }, + required: ['type'], + }, + { + type: 'object', + additionalProperties: false, + properties: { + type: { const: 'relationship' }, + // ...while the relationship `value` is simplified to a bare ID (the populated-doc `$ref` is dropped). + value: { type: 'string', description: 'The ID of the related "posts" document.' }, + }, + required: ['type'], + }, + ], + }, + posts: { + type: 'object', + additionalProperties: false, + properties: { id: { type: 'string' }, title: { type: 'string' } }, + }, + }, + properties: { + // `id` is dropped - it's a Payload-managed field MCP clients never set. + content: { + type: 'object', + properties: { + root: { + type: 'object', + properties: { + children: { type: 'array', items: { $ref: '#/$defs/LexicalNodes_ABCDEF12' } }, + }, + }, + }, + }, + }, + }) + }) +}) diff --git a/packages/plugin-mcp/src/utils/schemaConversion/simplifyRelationshipFields.ts b/packages/plugin-mcp/src/utils/schemaConversion/simplifyRelationshipFields.ts index 9b96124a2a5..eea1aaec07c 100644 --- a/packages/plugin-mcp/src/utils/schemaConversion/simplifyRelationshipFields.ts +++ b/packages/plugin-mcp/src/utils/schemaConversion/simplifyRelationshipFields.ts @@ -45,8 +45,7 @@ export function simplifyRelationshipFields(schema: JsonSchemaType): JsonSchemaTy processed.anyOf = nonRefOptions } } else { - processed.anyOf = processed.oneOf.map(recurse) - delete processed.oneOf + processed.oneOf = processed.oneOf.map(recurse) } } From 3862e6b480d63f60a1d7e9ed3fc4d887d08e067f Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 4 Jun 2026 19:24:04 +0000 Subject: [PATCH 49/56] fix: mismatch: SerializedUploadNode schema had extra fields strongly typed, internal and generated types typed them as { [k: string]: unknown } --- packages/payload/src/bin/generateTypes.ts | 9 ++- .../src/features/upload/server/schema.ts | 42 ++++++++--- test/lexical/lexical.int.spec.ts | 42 +++++++++++ test/lexical/payload-types.ts | 69 ++++++++++--------- test/types/payload-types.ts | 4 +- 5 files changed, 120 insertions(+), 46 deletions(-) diff --git a/packages/payload/src/bin/generateTypes.ts b/packages/payload/src/bin/generateTypes.ts index 764f2b40898..59b0992748d 100644 --- a/packages/payload/src/bin/generateTypes.ts +++ b/packages/payload/src/bin/generateTypes.ts @@ -12,8 +12,8 @@ import { getLogger } from '../utilities/logger.js' export async function generateTypes( config: SanitizedConfig, - options?: { log: boolean }, -): Promise { + options?: { log?: boolean; returnString?: boolean }, +): Promise { const logger = getLogger('payload', 'sync') const outputFile = process.env.PAYLOAD_TS_OUTPUT_PATH || config.typescript.outputFile @@ -73,6 +73,11 @@ export async function generateTypes( } } + // Return the generated types instead of writing them to disk. + if (options?.returnString) { + return compiled + } + // Diff the compiled types against the existing types file try { const existingTypes = await fs.readFile(outputFile, 'utf-8') diff --git a/packages/richtext-lexical/src/features/upload/server/schema.ts b/packages/richtext-lexical/src/features/upload/server/schema.ts index 4702bac3b34..57f267c7be3 100644 --- a/packages/richtext-lexical/src/features/upload/server/schema.ts +++ b/packages/richtext-lexical/src/features/upload/server/schema.ts @@ -6,6 +6,7 @@ import type { UploadCollectionSlug, } from 'payload' +import { createHash } from 'crypto' import { fieldsToJSONSchema, flattenAllFields } from 'payload' import type { LexicalElementFormat } from '../../../types/nodeTypes.js' @@ -50,13 +51,16 @@ export type UploadDataImproved = { } }[UploadCollectionSlug] -export type SerializedUploadNode = { +export type SerializedUploadNode< + TSlugs extends UploadCollectionSlug = UploadCollectionSlug, + TFields = { [k: string]: unknown }, +> = { [TSlug in TSlugs]: { relationTo: TSlug value: DataFromCollectionSlug | number | string } }[TSlugs] & { - fields: { [k: string]: unknown } + fields: TFields format: LexicalElementFormat id: string type: 'upload' @@ -64,12 +68,12 @@ export type SerializedUploadNode = { +const SERIALIZED_UPLOAD_NODE_TS = `export type SerializedUploadNode = { type: 'upload'; format: LexicalElementFormat; id: string; version: number; - fields: { [k: string]: unknown }; + fields: TFields; } & { [TSlug in TSlugs]: { relationTo: TSlug; @@ -77,6 +81,9 @@ const SERIALIZED_UPLOAD_NODE_TS = `export type SerializedUploadNode + createHash('sha256').update(JSON.stringify(schema)).digest('hex').slice(0, 8).toUpperCase() + export const createUploadNodeJSONSchema = (props: undefined | UploadFeatureProps): JSONSchemaFn => ({ collectionIDFieldTypes, config, i18n, interfaceNameDefinitions, typeStringDefinitions }) => { @@ -89,6 +96,10 @@ export const createUploadNodeJSONSchema = }) : [] + // Configured extra fields are registered as their own interface and referenced here, so the + // generated TypeScript keeps them - the node-level `tsType` would otherwise erase `fields` to + // `{ [k: string]: unknown }`. Mirrors how LinkFeature handles custom link fields. + const fieldsTypeNames = new Set() const collectionVariants: JSONSchema4[] = enabledCollections.map((collection) => { const slug = collection.slug const idType: 'number' | 'string' = collectionIDFieldTypes[slug] ?? 'string' @@ -106,18 +117,26 @@ export const createUploadNodeJSONSchema = }) : { properties: {}, required: [] } + let fieldsSchema: JSONSchema4 = { + type: 'object', + additionalProperties: false, + properties: extraFieldsSchema.properties, + required: extraFieldsSchema.required, + } + if (flattenedExtra.length > 0) { + const fieldsTypeName = `LexicalUploadFields_${hashUploadFields(fieldsSchema)}` + interfaceNameDefinitions.set(fieldsTypeName, fieldsSchema) + fieldsTypeNames.add(fieldsTypeName) + fieldsSchema = { $ref: `#/$defs/${fieldsTypeName}` } + } + return { type: 'object', additionalProperties: false, properties: { id: { type: 'string' }, type: { type: 'string', const: 'upload' }, - fields: { - type: 'object', - additionalProperties: false, - properties: extraFieldsSchema.properties, - required: extraFieldsSchema.required, - }, + fields: fieldsSchema, format: formatSchema, relationTo: { type: 'string', const: slug }, value: { @@ -147,7 +166,8 @@ export const createUploadNodeJSONSchema = const slugUnion = enabledCollections.map((c) => `'${c.slug}'`).join(' | ') const baseSchema: JSONSchema4 = collectionVariants.length === 1 ? collectionVariants[0]! : { oneOf: collectionVariants } - schema = { ...baseSchema, tsType: `SerializedUploadNode<${slugUnion}>` } + const fieldsType = fieldsTypeNames.size > 0 ? `, ${[...fieldsTypeNames].join(' | ')}` : '' + schema = { ...baseSchema, tsType: `SerializedUploadNode<${slugUnion}${fieldsType}>` } } return schema diff --git a/test/lexical/lexical.int.spec.ts b/test/lexical/lexical.int.spec.ts index 2d2e9181527..bc76e0eba06 100644 --- a/test/lexical/lexical.int.spec.ts +++ b/test/lexical/lexical.int.spec.ts @@ -14,9 +14,11 @@ import { type SerializedLinkNode, type SerializedRelationshipNode, type SerializedUploadNode, + UploadFeature, } from '@payloadcms/richtext-lexical' import path from 'path' import { configToJSONSchema, sanitizeConfig } from 'payload' +import { generateTypes } from 'payload/node' import { sanitizeUrl } from 'payload/shared' import { fileURLToPath } from 'url' import { beforeAll, beforeEach, describe, expect, it as vitestIt } from 'vitest' @@ -1368,3 +1370,43 @@ describe('Lexical link fields interface generation', () => { }, ) }) + +describe('Lexical upload node type generation', () => { + // The upload node's JSON Schema validates configured extra fields strictly, so the generated + // TypeScript must expose them too - not erase them to `{ [k: string]: unknown }`. + vitestIt('reflects UploadFeature extra fields in the generated upload node type', async () => { + const config = { + collections: [ + { slug: 'media', fields: [], upload: true }, + { + slug: 'articles', + fields: [ + { + name: 'content', + type: 'richText', + editor: lexicalEditor({ + features: [ + UploadFeature({ + collections: { media: { fields: [{ name: 'caption', type: 'text' }] } }, + }), + ], + }), + }, + ], + }, + ], + } as unknown as Config + + const sanitizedConfig = await sanitizeConfig(config) + // `generateTypes` only needs the ID type - avoid standing up a DB adapter. + ;(sanitizedConfig as unknown as { db: { defaultIDType: string } }).db = { + defaultIDType: 'text', + } + + const generatedTypes = await generateTypes(sanitizedConfig, { log: false, returnString: true }) + + // The configured `caption` upload field must survive into the generated upload node type, + // not be erased to `{ [k: string]: unknown }`. + expect(generatedTypes).toContain('caption') + }) +}) diff --git a/test/lexical/payload-types.ts b/test/lexical/payload-types.ts index 4435a393272..eac96373539 100644 --- a/test/lexical/payload-types.ts +++ b/test/lexical/payload-types.ts @@ -578,16 +578,16 @@ export type LexicalNodes_2EF528CD = | SerializedInlineBlockNode<{blockType: string}>; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_66D9025B". + * via the `definition` "LexicalNodes_556D3D48". */ -export type LexicalNodes_66D9025B = +export type LexicalNodes_556D3D48 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode + | SerializedParagraphNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode | SerializedBlockNode< | ValidationBlock | FilterOptionsBlock @@ -617,11 +617,11 @@ export type LexicalNodes_66D9025B = | MyInlineBlockWithBlock | MyInlineBlockWithBlockAndLabel > - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedUploadNode<'uploads' | 'uploads2', LexicalUploadFields_5F1A55C0> + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -658,9 +658,9 @@ export type LexicalNodes_66D9025B = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "LexicalNodes_BE093052". @@ -1268,20 +1268,20 @@ export type LexicalNodes_6DEEAAB8 = | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_8B8AF2BD". + * via the `definition` "LexicalNodes_A8AEB0F1". */ -export type LexicalNodes_8B8AF2BD = +export type LexicalNodes_A8AEB0F1 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedUploadNode<'uploads' | 'uploads2', LexicalUploadFields_5F1A55C0> + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1318,9 +1318,9 @@ export type LexicalNodes_8B8AF2BD = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "LexicalNodes_0B0D3C8D". @@ -1635,7 +1635,7 @@ export interface LexicalField { /** * Should not be rendered */ - lexicalWithBlocks: LexicalRichText; + lexicalWithBlocks: LexicalRichText; lexicalWithBlocks_markdown?: string | null; updatedAt: string; createdAt: string; @@ -1821,7 +1821,7 @@ export interface LexicalNestedBlock { export interface RichTextField { id: string; title: string; - lexicalCustomFields: LexicalRichText; + lexicalCustomFields: LexicalRichText; lexicalCustomFields_html?: string | null; /** * This rich text field uses the lexical editor. @@ -3863,9 +3863,16 @@ export interface MyInlineBlockWithBlockAndLabel { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_66D9025B". + * via the `definition` "LexicalUploadFields_5F1A55C0". */ -export interface LexicalLinkFields_66D9025B { +export interface LexicalUploadFields_5F1A55C0 { + caption?: LexicalRichText | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_556D3D48". + */ +export interface LexicalLinkFields_556D3D48 { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -4039,9 +4046,9 @@ export interface BlockWithBlockRef { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_8B8AF2BD". + * via the `definition` "LexicalLinkFields_A8AEB0F1". */ -export interface LexicalLinkFields_8B8AF2BD { +export interface LexicalLinkFields_A8AEB0F1 { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -4140,12 +4147,12 @@ export interface SerializedHorizontalRuleNode { version: number; } -export type SerializedUploadNode = { +export type SerializedUploadNode = { type: 'upload'; format: LexicalElementFormat; id: string; version: number; - fields: { [k: string]: unknown }; + fields: TFields; } & { [TSlug in TSlugs]: { relationTo: TSlug; diff --git a/test/types/payload-types.ts b/test/types/payload-types.ts index 610dd77771d..20d951cdd89 100644 --- a/test/types/payload-types.ts +++ b/test/types/payload-types.ts @@ -710,12 +710,12 @@ export interface SerializedHorizontalRuleNode { version: number; } -export type SerializedUploadNode = { +export type SerializedUploadNode = { type: 'upload'; format: LexicalElementFormat; id: string; version: number; - fields: { [k: string]: unknown }; + fields: TFields; } & { [TSlug in TSlugs]: { relationTo: TSlug; From 7bc940c9db8f1234917762da06b133d24c1de861 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 4 Jun 2026 20:46:28 +0000 Subject: [PATCH 50/56] add $schema property to geberated json schema --- packages/payload/src/utilities/configToJSONSchema.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/payload/src/utilities/configToJSONSchema.ts b/packages/payload/src/utilities/configToJSONSchema.ts index 14d87ff310d..3f18e5a2150 100644 --- a/packages/payload/src/utilities/configToJSONSchema.ts +++ b/packages/payload/src/utilities/configToJSONSchema.ts @@ -1530,6 +1530,7 @@ export function configToJSONSchema( ...Object.fromEntries(interfaceNameDefinitions), ...authOperationDefinitions, }, + $schema: 'https://json-schema.org/draft/2020-12/schema', additionalProperties: false, // These properties here will be very simple, as all the complexity is in the definitions. These are just the properties for the top-level `Config` type type: 'object', From 8e6246fa06a2bc818840cbef56202fe7d90b5b21 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Fri, 5 Jun 2026 00:18:32 +0000 Subject: [PATCH 51/56] perf: ensure json schema for data does not go through zod, which produces 40% bigger json schema and drops descriptions --- .../src/mcp/builtin/collections/createTool.ts | 74 ++++++------- .../src/mcp/builtin/collections/updateTool.ts | 103 +++++++++--------- .../src/mcp/builtin/globals/updateTool.ts | 68 ++++++------ .../utils/schemaConversion/buildToolInput.ts | 68 ++++++++++++ 4 files changed, 194 insertions(+), 119 deletions(-) create mode 100644 packages/plugin-mcp/src/utils/schemaConversion/buildToolInput.ts diff --git a/packages/plugin-mcp/src/mcp/builtin/collections/createTool.ts b/packages/plugin-mcp/src/mcp/builtin/collections/createTool.ts index 879430754e1..896ff600033 100644 --- a/packages/plugin-mcp/src/mcp/builtin/collections/createTool.ts +++ b/packages/plugin-mcp/src/mcp/builtin/collections/createTool.ts @@ -9,7 +9,8 @@ import { stripVirtualFields, } from '../../../utils/getVirtualFieldNames.js' import { localAPIDefaults } from '../../../utils/localAPIDefaults.js' -import { prepareCollectionSchema } from '../../../utils/schemaConversion/prepareCollectionSchema.js' +import { buildToolInput } from '../../../utils/schemaConversion/buildToolInput.js' +import { sanitizeEntitySchema } from '../../../utils/schemaConversion/sanitizeEntitySchema.js' import { transformPointDataToPayload } from '../../../utils/transformPointDataToPayload.js' const DEFAULT_DESCRIPTION = 'Create a document in a collection.' @@ -17,41 +18,40 @@ const DEFAULT_DESCRIPTION = 'Create a document in a collection.' export const createCollectionTool = defineCollectionTool({ description: DEFAULT_DESCRIPTION, input: ({ collectionSchema }) => - z.object({ - data: z - .fromJSONSchema( - prepareCollectionSchema(collectionSchema) as unknown as z.core.JSONSchema.JSONSchema, - ) - .describe('The document fields to create'), - depth: z - .number() - .int() - .min(0) - .max(10) - .describe('How many levels deep to populate relationships in response') - .optional() - .default(0), - draft: z - .boolean() - .describe('Whether to create the document as a draft') - .optional() - .default(false), - fallbackLocale: z - .string() - .describe('Optional: fallback locale code to use when requested locale is not available') - .optional(), - locale: z - .string() - .describe( - 'Optional: locale code to create the document in (e.g., "en", "es"). Defaults to the default locale', - ) - .optional(), - select: z - .string() - .describe( - 'Optional: define exactly which fields you\'d like to create (JSON), e.g., \'{"title": "My Post"}\'', - ) - .optional(), + buildToolInput({ + controls: { + depth: z + .number() + .int() + .min(0) + .max(10) + .describe('How many levels deep to populate relationships in response') + .optional() + .default(0), + draft: z + .boolean() + .describe('Whether to create the document as a draft') + .optional() + .default(false), + fallbackLocale: z + .string() + .describe('Optional: fallback locale code to use when requested locale is not available') + .optional(), + locale: z + .string() + .describe( + 'Optional: locale code to create the document in (e.g., "en", "es"). Defaults to the default locale', + ) + .optional(), + select: z + .string() + .describe( + 'Optional: define exactly which fields you\'d like to create (JSON), e.g., \'{"title": "My Post"}\'', + ) + .optional(), + }, + dataDescription: 'The document fields to create', + dataSchema: sanitizeEntitySchema(collectionSchema), }), }).handler(async ({ authorizedMCP, collectionSlug, input, req }) => { const payload = req.payload @@ -64,7 +64,7 @@ export const createCollectionTool = defineCollectionTool({ ) try { - let parsedData = transformPointDataToPayload(data as Record) + let parsedData = transformPointDataToPayload(data) const virtualFieldNames = getCollectionVirtualFieldNames(payload.config, collectionSlug) parsedData = stripVirtualFields(parsedData, virtualFieldNames) diff --git a/packages/plugin-mcp/src/mcp/builtin/collections/updateTool.ts b/packages/plugin-mcp/src/mcp/builtin/collections/updateTool.ts index 34684755de6..4c5ee8e1d05 100644 --- a/packages/plugin-mcp/src/mcp/builtin/collections/updateTool.ts +++ b/packages/plugin-mcp/src/mcp/builtin/collections/updateTool.ts @@ -9,7 +9,8 @@ import { stripVirtualFields, } from '../../../utils/getVirtualFieldNames.js' import { localAPIDefaults } from '../../../utils/localAPIDefaults.js' -import { prepareCollectionSchema } from '../../../utils/schemaConversion/prepareCollectionSchema.js' +import { buildToolInput } from '../../../utils/schemaConversion/buildToolInput.js' +import { sanitizeEntitySchema } from '../../../utils/schemaConversion/sanitizeEntitySchema.js' import { transformPointDataToPayload } from '../../../utils/transformPointDataToPayload.js' const DEFAULT_DESCRIPTION = 'Update documents in a collection by ID or where clause.' @@ -17,7 +18,7 @@ const DEFAULT_DESCRIPTION = 'Update documents in a collection by ID or where cla export const updateCollectionTool = defineCollectionTool({ description: DEFAULT_DESCRIPTION, input: ({ collectionSchema }) => { - const partialSchema = prepareCollectionSchema(collectionSchema) + const partialSchema = sanitizeEntitySchema(collectionSchema) // Collection updates do not require all required fields to be passed => delete .required. // @@ -25,52 +26,56 @@ export const updateCollectionTool = defineCollectionTool({ // data: DeepPartial> delete partialSchema.required - return z.object({ - id: z.union([z.string(), z.number()]).describe('The ID of the document to update').optional(), - data: z - .fromJSONSchema(partialSchema as unknown as z.core.JSONSchema.JSONSchema) - .describe('The fields to update'), - depth: z - .number() - .describe('How many levels deep to populate relationships') - .optional() - .default(0), - draft: z - .boolean() - .describe('Whether to update the document as a draft') - .optional() - .default(false), - fallbackLocale: z - .string() - .describe('Optional: fallback locale code to use when requested locale is not available') - .optional(), - filePath: z.string().describe('File path for file uploads').optional(), - locale: z - .string() - .describe( - 'Optional: locale code to update the document in (e.g., "en", "es"). Defaults to the default locale', - ) - .optional(), - overrideLock: z - .boolean() - .describe('Whether to override document locks') - .optional() - .default(true), - overwriteExistingFiles: z - .boolean() - .describe('Whether to overwrite existing files') - .optional() - .default(false), - select: z - .string() - .describe( - 'Optional: define exactly which fields you\'d like to return in the response (JSON), e.g., \'{"title": "My Post"}\'', - ) - .optional(), - where: z - .string() - .describe('JSON string for where clause to update multiple documents') - .optional(), + return buildToolInput({ + controls: { + id: z + .union([z.string(), z.number()]) + .describe('The ID of the document to update') + .optional(), + depth: z + .number() + .describe('How many levels deep to populate relationships') + .optional() + .default(0), + draft: z + .boolean() + .describe('Whether to update the document as a draft') + .optional() + .default(false), + fallbackLocale: z + .string() + .describe('Optional: fallback locale code to use when requested locale is not available') + .optional(), + filePath: z.string().describe('File path for file uploads').optional(), + locale: z + .string() + .describe( + 'Optional: locale code to update the document in (e.g., "en", "es"). Defaults to the default locale', + ) + .optional(), + overrideLock: z + .boolean() + .describe('Whether to override document locks') + .optional() + .default(true), + overwriteExistingFiles: z + .boolean() + .describe('Whether to overwrite existing files') + .optional() + .default(false), + select: z + .string() + .describe( + 'Optional: define exactly which fields you\'d like to return in the response (JSON), e.g., \'{"title": "My Post"}\'', + ) + .optional(), + where: z + .string() + .describe('JSON string for where clause to update multiple documents') + .optional(), + }, + dataDescription: 'The fields to update', + dataSchema: partialSchema, }) }, }).handler(async ({ authorizedMCP, collectionSlug, input, req }) => { @@ -102,7 +107,7 @@ export const updateCollectionTool = defineCollectionTool({ } } - let parsedData = transformPointDataToPayload(data as Record) + let parsedData = transformPointDataToPayload(data) const virtualFieldNames = getCollectionVirtualFieldNames(payload.config, collectionSlug) parsedData = stripVirtualFields(parsedData, virtualFieldNames) diff --git a/packages/plugin-mcp/src/mcp/builtin/globals/updateTool.ts b/packages/plugin-mcp/src/mcp/builtin/globals/updateTool.ts index b4dbee14493..ae90fda7cb7 100644 --- a/packages/plugin-mcp/src/mcp/builtin/globals/updateTool.ts +++ b/packages/plugin-mcp/src/mcp/builtin/globals/updateTool.ts @@ -9,50 +9,52 @@ import { stripVirtualFields, } from '../../../utils/getVirtualFieldNames.js' import { localAPIDefaults } from '../../../utils/localAPIDefaults.js' -import { prepareCollectionSchema } from '../../../utils/schemaConversion/prepareCollectionSchema.js' +import { buildToolInput } from '../../../utils/schemaConversion/buildToolInput.js' +import { sanitizeEntitySchema } from '../../../utils/schemaConversion/sanitizeEntitySchema.js' const DEFAULT_DESCRIPTION = 'Update a Payload global singleton configuration.' export const updateGlobalTool = defineGlobalTool({ description: DEFAULT_DESCRIPTION, input: ({ globalSchema }) => { - const partialSchema = prepareCollectionSchema(globalSchema) + const partialSchema = sanitizeEntitySchema(globalSchema) // Global updates do not require all required fields to be passed => delete .required. // // Local API equivalent: packages/payload/src/global/operations/local/update.ts#BaseOptions#data: // data: DeepPartial, 'id'>> delete partialSchema.required - return z.object({ - data: z - .fromJSONSchema(partialSchema as unknown as z.core.JSONSchema.JSONSchema) - .describe('The fields to update'), - depth: z - .number() - .describe('Optional: Depth of relationships to populate') - .optional() - .default(0), - draft: z - .boolean() - .describe('Optional: Whether to save as draft (default: false)') - .optional() - .default(false), - fallbackLocale: z - .string() - .describe('Optional: fallback locale code to use when requested locale is not available') - .optional(), - locale: z - .string() - .describe( - 'Optional: locale code to update data in (e.g., "en", "es"). Use "all" to update all locales for localized fields', - ) - .optional(), - select: z - .string() - .describe( - 'Optional: define exactly which fields you\'d like to return in the response (JSON), e.g., \'{"siteName": "My Site"}\'', - ) - .optional(), + return buildToolInput({ + controls: { + depth: z + .number() + .describe('Optional: Depth of relationships to populate') + .optional() + .default(0), + draft: z + .boolean() + .describe('Optional: Whether to save as draft (default: false)') + .optional() + .default(false), + fallbackLocale: z + .string() + .describe('Optional: fallback locale code to use when requested locale is not available') + .optional(), + locale: z + .string() + .describe( + 'Optional: locale code to update data in (e.g., "en", "es"). Use "all" to update all locales for localized fields', + ) + .optional(), + select: z + .string() + .describe( + 'Optional: define exactly which fields you\'d like to return in the response (JSON), e.g., \'{"siteName": "My Site"}\'', + ) + .optional(), + }, + dataDescription: 'The fields to update', + dataSchema: partialSchema, }) }, }).handler(async ({ authorizedMCP, globalSlug, input, req }) => { @@ -67,7 +69,7 @@ export const updateGlobalTool = defineGlobalTool({ try { const virtualFieldNames = getGlobalVirtualFieldNames(payload.config, globalSlug) - const parsedData = stripVirtualFields(data as Record, virtualFieldNames) + const parsedData = stripVirtualFields(data, virtualFieldNames) let selectClause: SelectType | undefined if (select) { diff --git a/packages/plugin-mcp/src/utils/schemaConversion/buildToolInput.ts b/packages/plugin-mcp/src/utils/schemaConversion/buildToolInput.ts new file mode 100644 index 00000000000..cd73dbac40d --- /dev/null +++ b/packages/plugin-mcp/src/utils/schemaConversion/buildToolInput.ts @@ -0,0 +1,68 @@ +import type { StandardSchemaWithJSON } from '@modelcontextprotocol/server' + +import { z } from 'zod' + +import type { JsonSchemaType } from '../../types.js' + +/** + * Builds a create/update tool's `input`: a `data` field (the document's fields) plus controls like + * `depth` and `draft`. Using just `z.fromJSONSchema(ourJSONSchema)` has a few problems which are mitigated + * in this function. z.fromJSONSchema is both bigger and lossier (≈40% larger on the lexical schema). + * Each example below is `what we publish` => `what a plain zod round-trip would publish instead`. + * + * @example + * Bigger - zod inlines shared defs instead of keeping our `$ref`s (and adds junk integer bounds), so a + * reused def is duplicated at every use: + * `{ $ref: '#/$defs/author' }` => `{ type: 'object', properties: { id, name }, additionalProperties: false }` + * + * @example + * Lossier - zod drops the `description` on `enum`/`const` fields: + * `{ enum: ['draft', 'published'], description: 'Publish state' }` → `{ enum: ['draft', 'published'] }` + */ +export const buildToolInput = ({ + controls, + dataDescription, + dataSchema, +}: { + /** Tool options alongside `data` (depth, draft, where, …) as plain zod - inferred into `input`. */ + controls: TControls + dataDescription: string + dataSchema: JsonSchemaType +}) => { + // `sanitizeEntitySchema` already emits draft 2020-12 with `$defs`, which is what zod's `fromJSONSchema` + // and MCP clients both expect. Drop only the root `$schema` keyword, redundant once it's a sub-schema. + const { $schema: _schema, ...entitySchema } = dataSchema as Record + + const schema = z.object({ + data: z.fromJSONSchema(entitySchema as unknown as z.core.JSONSchema.JSONSchema), + ...controls, + }) + const standard = (schema as unknown as StandardSchemaWithJSON)['~standard'] + + return { + '~standard': { + ...standard, + jsonSchema: { + ...standard.jsonSchema, + input: (options) => { + // Start from zod's JSON Schema for the whole input, then replace its lossy `data` schema with + // the sanitized entity schema. The entity's `$defs` move to the root so the `$ref`s resolve. + const generated = standard.jsonSchema.input(options) + const { $defs, ...entityBody } = entitySchema + ;(generated.properties as Record).data = { + ...entityBody, + description: dataDescription, + } + if ($defs) { + generated.$defs = $defs as object + } else { + delete generated.$defs + } + return generated + }, + }, + }, + } as StandardSchemaWithJSON< + { data: Record } & Omit, 'data'> + > +} From a2ef4a4220facaddd52617fa3743b3a06b1d1d3f Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Fri, 5 Jun 2026 06:17:26 +0000 Subject: [PATCH 52/56] perf: minimize json schema size --- .../prepareCollectionSchema.ts | 39 -- ...a.spec.ts => sanitizeEntitySchema.spec.ts} | 13 +- .../schemaConversion/sanitizeEntitySchema.ts | 529 ++++++++++++++++++ .../schemaConversion/sanitizeJsonSchema.ts | 62 -- .../simplifyRelationshipFields.ts | 77 --- .../schemaConversion/transformPointFields.ts | 56 -- test/plugin-mcp/int.spec.ts | 182 ++++-- 7 files changed, 684 insertions(+), 274 deletions(-) delete mode 100644 packages/plugin-mcp/src/utils/schemaConversion/prepareCollectionSchema.ts rename packages/plugin-mcp/src/utils/schemaConversion/{prepareCollectionSchema.spec.ts => sanitizeEntitySchema.spec.ts} (89%) create mode 100644 packages/plugin-mcp/src/utils/schemaConversion/sanitizeEntitySchema.ts delete mode 100644 packages/plugin-mcp/src/utils/schemaConversion/sanitizeJsonSchema.ts delete mode 100644 packages/plugin-mcp/src/utils/schemaConversion/simplifyRelationshipFields.ts delete mode 100644 packages/plugin-mcp/src/utils/schemaConversion/transformPointFields.ts diff --git a/packages/plugin-mcp/src/utils/schemaConversion/prepareCollectionSchema.ts b/packages/plugin-mcp/src/utils/schemaConversion/prepareCollectionSchema.ts deleted file mode 100644 index 31d8fc26f6b..00000000000 --- a/packages/plugin-mcp/src/utils/schemaConversion/prepareCollectionSchema.ts +++ /dev/null @@ -1,39 +0,0 @@ -import type { JsonSchemaType } from '../../types.js' - -import { sanitizeJsonSchema } from './sanitizeJsonSchema.js' -import { simplifyRelationshipFields } from './simplifyRelationshipFields.js' -import { transformPointFieldsForMCP } from './transformPointFields.js' - -/** - * Fields Payload manages automatically — clients should never be required to provide - * them. Stripped from `required` and `properties` so they don't appear in tool - * inputs. - */ -const PAYLOAD_MANAGED_FIELDS = new Set(['_status', 'createdAt', 'id', 'updatedAt']) - -/** - * Sanitizes Payload's auto-generated collection JSON Schema so it can be safely - * fed into the MCP server's `fromJsonSchema()` adapter (no zod intermediate step). - */ -export const prepareCollectionSchema = (schema: JsonSchemaType): JsonSchemaType => { - // Clone to avoid mutating the original schema (used elsewhere for tool listing) - const schemaClone = JSON.parse(JSON.stringify(schema)) as JsonSchemaType - - const sanitized = sanitizeJsonSchema(schemaClone) - const pointTransformed = transformPointFieldsForMCP(sanitized) - const simplified = simplifyRelationshipFields(pointTransformed) - - if (simplified.properties) { - for (const field of PAYLOAD_MANAGED_FIELDS) { - delete simplified.properties[field] - } - } - if (Array.isArray(simplified.required)) { - simplified.required = simplified.required.filter((name) => !PAYLOAD_MANAGED_FIELDS.has(name)) - if (simplified.required.length === 0) { - delete simplified.required - } - } - - return simplified -} diff --git a/packages/plugin-mcp/src/utils/schemaConversion/prepareCollectionSchema.spec.ts b/packages/plugin-mcp/src/utils/schemaConversion/sanitizeEntitySchema.spec.ts similarity index 89% rename from packages/plugin-mcp/src/utils/schemaConversion/prepareCollectionSchema.spec.ts rename to packages/plugin-mcp/src/utils/schemaConversion/sanitizeEntitySchema.spec.ts index 72ebfe5e763..6dec979c4e3 100644 --- a/packages/plugin-mcp/src/utils/schemaConversion/prepareCollectionSchema.spec.ts +++ b/packages/plugin-mcp/src/utils/schemaConversion/sanitizeEntitySchema.spec.ts @@ -2,9 +2,9 @@ import { describe, expect, it } from 'vitest' import type { JsonSchemaType } from '../../types.js' -import { prepareCollectionSchema } from './prepareCollectionSchema.js' +import { sanitizeEntitySchema } from './sanitizeEntitySchema.js' -describe('prepareCollectionSchema', () => { +describe('sanitizeEntitySchema', () => { it('keeps a Lexical node union strict (oneOf) while simplifying relationship values to IDs', () => { // Shaped like the schema the MCP server prepares for a collection with a Lexical richText field: // a `$defs` node union (a `oneOf` of node shapes) where a relationship node's `value` is either @@ -53,11 +53,12 @@ describe('prepareCollectionSchema', () => { }, } - expect(prepareCollectionSchema(standalone)).toStrictEqual({ + expect(sanitizeEntitySchema(standalone)).toStrictEqual({ type: 'object', $defs: { - // The node union stays a strict discriminated `oneOf` - not loosened to `anyOf`... - LexicalNodes_ABCDEF12: { + // The node union is renamed to a short, readable `node`, and stays a strict discriminated + // `oneOf` - not loosened to `anyOf`... + node: { oneOf: [ { type: 'object', @@ -91,7 +92,7 @@ describe('prepareCollectionSchema', () => { root: { type: 'object', properties: { - children: { type: 'array', items: { $ref: '#/$defs/LexicalNodes_ABCDEF12' } }, + children: { type: 'array', items: { $ref: '#/$defs/node' } }, }, }, }, diff --git a/packages/plugin-mcp/src/utils/schemaConversion/sanitizeEntitySchema.ts b/packages/plugin-mcp/src/utils/schemaConversion/sanitizeEntitySchema.ts new file mode 100644 index 00000000000..2f0c699053b --- /dev/null +++ b/packages/plugin-mcp/src/utils/schemaConversion/sanitizeEntitySchema.ts @@ -0,0 +1,529 @@ +import type { JsonSchemaType } from '../../types.js' + +/** + * Turns the JSON Schema that Payload generates for a collection or global into the input schema for + * an MCP create/update tool. In short, it: + * + * - drops fields a client can't set (`id`, `createdAt`, the draft `_status`, …), + * - rewrites Payload-specific field shapes (points, relationships) into plain JSON the model can fill, + * - and shrinks the result so it's cheaper for the model to read, + * + * while keeping every node valid JSON Schema draft 2020-12. Each step below is tagged with why it runs - + * **Correctness** (valid input the API accepts), **Size** (equivalence-preserving shrink), or **LLM + * ergonomics** (easier for the model to read/fill) - and carries a before/after example on its definition. + */ +export const sanitizeEntitySchema = (schema: JsonSchemaType): JsonSchemaType => { + // Work on a copy — the caller reuses the original schema elsewhere (e.g. when listing tools). + let result = structuredClone(schema) + + // Correctness — drop the fields a client can't set (id, createdAt, updatedAt, draft _status) + collapse nullable types. + result = removeManagedFields(result) + + // LLM ergonomics — rewrite point fields from a `[number, number]` tuple into a `{ longitude, latitude }` object. + result = pointFieldsToObjects(result) + + // Correctness — a relationship value can be an ID or a populated doc; on input only the ID is valid, so keep that. + result = relationshipsToIds(result) + + // Size — strip inert type-gen leftovers that only bloat the schema (`tsType`, block-collision notes). + result = removeTypeGenArtifacts(result) + + // Size — where a `const` already pins a value, the sibling `type` is redundant; remove it. + result = dropRedundantConstType(result) + + // Size — fold per-collection relationship/upload variants (identical but for `relationTo`) into one `enum`. + result = mergeConstDiscriminatedUnions(result) + + // Size — pull any subschema that appears more than once into a single shared `$defs` entry. + result = deduplicateIntoDefinitions(result) + + // LLM ergonomics — give `$defs` short, readable names (`Code`, `paragraph`, `node`) so the `$ref`s read nicely. + result = shortenDefinitionNames(result) + + return result +} + +/** + * Rebuilds a schema bottom-up, calling `visit` on each node after its children. Shared by the + * transforms that need to touch every node in the tree. + */ +const mapNodes = (node: unknown, visit: (node: JsonSchemaType) => JsonSchemaType): unknown => { + if (Array.isArray(node)) { + return node.map((child) => mapNodes(child, visit)) + } + if (!node || typeof node !== 'object') { + return node + } + const out: Record = {} + for (const [key, value] of Object.entries(node)) { + out[key] = mapNodes(value, visit) + } + return visit(out as JsonSchemaType) +} + +// Payload sets these on every document, so an MCP client never provides them when creating/updating. +const PAYLOAD_MANAGED_FIELDS = new Set(['_status', 'createdAt', 'id', 'updatedAt']) + +/** + * **Correctness.** Removes the fields a client can't set on create/update - `id`, `createdAt`, `updatedAt`, and the draft + * `_status` - from every field object's `properties` and `required` (recursing into nested objects and + * array items). Along the way it also collapses optional array/object types via {@link collapseNullableType}. + * + * @example + * { properties: { id: { type: 'string' }, tags: { type: ['array', 'null'], items: {} } }, required: ['id', 'tags'] } + * → { properties: { tags: { type: 'array', items: {} } }, required: ['tags'] } + */ +const removeManagedFields = (schema: JsonSchemaType): JsonSchemaType => { + if (schema.properties && typeof schema.properties === 'object') { + for (const field of PAYLOAD_MANAGED_FIELDS) { + delete schema.properties[field] + } + for (const key of Object.keys(schema.properties)) { + const prop = schema.properties[key] as JsonSchemaType + if (!prop || typeof prop !== 'object') { + continue + } + const isRequired = Array.isArray(schema.required) && schema.required.includes(key) + collapseNullableType(prop, isRequired) + if (prop.properties) { + removeManagedFields(prop) + } + if (prop.items && typeof prop.items === 'object' && !Array.isArray(prop.items)) { + removeManagedFields(prop.items) + } + } + } + + if (Array.isArray(schema.required)) { + schema.required = schema.required.filter((name) => !PAYLOAD_MANAGED_FIELDS.has(name)) + if (schema.required.length === 0) { + delete schema.required + } + } + + return schema +} + +/** + * Drops the `'null'` from an optional array/object type (`['array', 'null']` → `'array'`, likewise + * `'object'`). Payload marks a field optional by unioning its type with `'null'`, but a create/update + * tool already conveys "optional" through the `required` list - the client just omits the field - so the + * `'null'` is redundant here. Dropping it shows the model a plain `type: 'array'` instead of implying it + * should send a literal `null`. + * + * We never touch the `required` list, so this can't change whether a field is required. And we skip fields + * that ARE required (`isRequired`): there a `'null'` is a value the field genuinely accepts, not optionality + * encoding. Nullable scalars (`['string', 'null']`) are also left alone - they read fine as `string | null`. + * + * @example + * optional { type: ['array', 'null'] } → { type: 'array' } (still optional, just no longer null-valued) + * required { type: ['array', 'null'] } → unchanged + * { type: ['string', 'null'] } → unchanged + */ +const collapseNullableType = (schema: JsonSchemaType, isRequired: boolean): void => { + if (isRequired || !Array.isArray(schema.type)) { + return + } + const nonNullTypes = schema.type.filter((t) => t !== 'null') + if (nonNullTypes.length === 1 && (nonNullTypes[0] === 'array' || nonNullTypes[0] === 'object')) { + schema.type = nonNullTypes[0] + } +} + +/** + * **LLM ergonomics.** Rewrites a point field (stored as a two-number tuple) into a `{ longitude, latitude }` object, which + * is far easier for the model to fill in than a positional array. This is input-only and lossless: the + * create/update handler converts the object back to the `[longitude, latitude]` tuple Payload stores, + * via `transformPointDataToPayload`. + * + * @example + * { type: 'array', items: [{ type: 'number' }, { type: 'number' }] } + * → { type: 'object', properties: { longitude: { type: 'number' }, latitude: { type: 'number' } }, required: ['longitude', 'latitude'] } + */ +const pointFieldsToObjects = (schema: JsonSchemaType): JsonSchemaType => { + if (!schema || typeof schema !== 'object') { + return schema + } + + const transformed = { ...schema } + + if (transformed.properties && typeof transformed.properties === 'object') { + transformed.properties = Object.fromEntries( + Object.entries(transformed.properties).map(([key, value]) => { + if (!value || typeof value !== 'object') { + return [key, value] + } + const isArrayType = + value.type === 'array' || (Array.isArray(value.type) && value.type.includes('array')) + const isPointField = + isArrayType && + Array.isArray(value.items) && + value.items.length === 2 && + value.items.every((item) => item && typeof item === 'object' && item.type === 'number') + + if (isPointField) { + const isNullable = Array.isArray(value.type) && value.type.includes('null') + return [ + key, + { + type: isNullable ? ['object', 'null'] : 'object', + description: value.description || 'Geographic coordinates (longitude, latitude)', + properties: { + latitude: { type: 'number', description: 'Latitude coordinate' }, + longitude: { type: 'number', description: 'Longitude coordinate' }, + }, + required: ['longitude', 'latitude'], + }, + ] + } + + return [key, pointFieldsToObjects(value)] + }), + ) + } + + if ( + transformed.items && + typeof transformed.items === 'object' && + !Array.isArray(transformed.items) + ) { + transformed.items = pointFieldsToObjects(transformed.items) + } + + return transformed +} + +/** + * **Correctness.** Reduces relationship/upload fields to the IDs a client actually sends. Payload types the value as + * "an ID or the full related document" - but the populated-document form only appears in read responses; + * on create/update you always reference a relationship by its ID. So we drop that `$ref` option, leaving + * the bare ID. A single remaining target collapses inline (with a description naming the target + * collection); several targets become an `anyOf` of IDs. + * + * @example + * { oneOf: [{ type: 'string' }, { $ref: '#/$defs/posts' }] } + * → { type: 'string', description: 'The ID of the related "posts" document.' } + */ +const relationshipsToIds = (schema: JsonSchemaType): JsonSchemaType => { + if (!schema || typeof schema !== 'object') { + return schema + } + + const processed = { ...schema } + + if (Array.isArray(processed.oneOf)) { + const isRelatedDocRef = (option: unknown): option is { $ref: string } => + !!option && typeof option === 'object' && '$ref' in option + + if (processed.oneOf.some(isRelatedDocRef)) { + // A relationship value is "an ID, or the populated related document". Keep the ID option(s) and + // drop the `$ref`s to the related collections, since a client only ever sends the ID. + const idOptions = processed.oneOf + .filter((option) => !isRelatedDocRef(option)) + .map((option) => (typeof option === 'object' ? relationshipsToIds(option) : option)) + const targetCollections = processed.oneOf + .filter(isRelatedDocRef) + .map((option) => option.$ref.replace('#/$defs/', '')) + + if (idOptions.length === 1) { + delete processed.oneOf + Object.assign(processed, idOptions[0]) + if (targetCollections.length > 0 && !processed.description) { + processed.description = `The ID of the related "${targetCollections.join('" or "')}" document.` + } + } else if (idOptions.length > 1) { + delete processed.oneOf + processed.anyOf = idOptions + } + } else { + processed.oneOf = processed.oneOf.map((option) => + typeof option === 'object' ? relationshipsToIds(option) : option, + ) + } + } + + if (processed.properties && typeof processed.properties === 'object') { + processed.properties = Object.fromEntries( + Object.entries(processed.properties).map(([key, value]) => [ + key, + typeof value === 'object' ? relationshipsToIds(value) : value, + ]), + ) + } + + if (processed.items && typeof processed.items === 'object' && !Array.isArray(processed.items)) { + processed.items = relationshipsToIds(processed.items) + } + + // Lexical node unions and blocks live under `$defs` and have their own relationship fields, so walk + // those too — otherwise their `$ref`s would dangle once we don't bundle the related collections. + if (processed.$defs && typeof processed.$defs === 'object') { + processed.$defs = Object.fromEntries( + Object.entries(processed.$defs).map(([key, value]) => [ + key, + typeof value === 'object' ? relationshipsToIds(value) : value, + ]), + ) + } + + return processed +} + +/** + * **Size.** Strips type-generation leftovers that bloat the schema without helping the model: the `tsType` + * hint (a `json-schema-to-typescript` extension; JSON Schema validators just ignore it, they don't reject it) + * and the block-interface-collision note Payload adds to some block descriptions (the + * `block-interface-name-collisions` docs link set in `registerBlockInterface`, see configToJSONSchema.ts). + * Both are inert here - removing them only shrinks the schema (and spares the model irrelevant noise). + * + * @example + * { type: 'object', tsType: 'SerializedBlockNode', description: 'see …#block-interface-name-collisions' } + * → { type: 'object' } + */ +const removeTypeGenArtifacts = (schema: JsonSchemaType): JsonSchemaType => + mapNodes(schema, (node) => { + delete (node as { tsType?: unknown }).tsType + const { description } = node as { description?: string } + if ( + typeof description === 'string' && + description.includes('block-interface-name-collisions') + ) { + delete (node as { description?: unknown }).description + } + return node + }) as JsonSchemaType + +/** + * **Size.** Removes `type` whenever a `const` sits next to it — the constant already fixes the value. + * + * @example + * { type: 'string', const: 'paragraph' } → { const: 'paragraph' } + */ +const dropRedundantConstType = (schema: JsonSchemaType): JsonSchemaType => + mapNodes(schema, (node) => { + if ('const' in node && 'type' in node) { + delete (node as { type?: unknown }).type + } + return node + }) as JsonSchemaType + +/** + * **Size.** Merges the members of a `oneOf`/`anyOf` that are identical except for one `const`-valued property + * into a single member with that property as an `enum`. Since the members differ only by that one + * constant, the `enum` form accepts exactly the same values - it's just smaller. This folds the + * per-collection relationship and upload variants, which differ only in their `relationTo` constant. + * + * @example + * { oneOf: [ + * { properties: { relationTo: { const: 'posts' }, value: { type: 'string' } } }, + * { properties: { relationTo: { const: 'pages' }, value: { type: 'string' } } }, + * ] } + * → { properties: { relationTo: { enum: ['posts', 'pages'] }, value: { type: 'string' } } } + */ +const mergeConstDiscriminatedUnions = (schema: JsonSchemaType): JsonSchemaType => + mapNodes(schema, (node) => { + for (const keyword of ['oneOf', 'anyOf'] as const) { + const members = node[keyword] + if (Array.isArray(members) && members.length > 1) { + const merged = mergeMembersByConst(members) + if (merged) { + delete node[keyword] + Object.assign(node, merged) + } + } + } + return node + }) as JsonSchemaType + +/** Returns the merged member for {@link mergeConstDiscriminatedUnions}, or `null` if they can't merge. */ +const mergeMembersByConst = (members: Array): JsonSchemaType | null => { + const objects = members.filter( + (member): member is JsonSchemaType => + typeof member === 'object' && member !== null && typeof member.properties === 'object', + ) + if (objects.length < 2 || objects.length !== members.length) { + return null + } + + for (const discriminator of Object.keys(objects[0]!.properties!)) { + // Each member must pin this property to a `const`... + const constValues: unknown[] = [] + const everyMemberPinsConst = objects.every((member) => { + const prop = member.properties![discriminator] + if (prop && typeof prop === 'object' && 'const' in prop) { + constValues.push(prop.const) + return true + } + return false + }) + if (!everyMemberPinsConst) { + continue + } + + // ...and be otherwise identical (compare each member with the discriminator removed). + const fingerprintWithoutDiscriminator = (member: JsonSchemaType): string => { + const { [discriminator]: _discriminator, ...otherProperties } = member.properties! + return JSON.stringify({ ...member, properties: otherProperties }) + } + if (new Set(objects.map(fingerprintWithoutDiscriminator)).size !== 1) { + continue + } + + const uniqueConstValues = [...new Set(constValues)] + if (uniqueConstValues.length < 2) { + continue + } + + // Replace the per-member `const` with a single `enum` of every value. + const merged = structuredClone(objects[0]!) + const discriminatorProp = merged.properties![discriminator] + if (discriminatorProp && typeof discriminatorProp === 'object') { + delete discriminatorProp.const + discriminatorProp.enum = uniqueConstValues as NonNullable + } + return merged + } + return null +} + +// A `$ref` costs ~30 characters once names are shortened, so sharing a subschema only pays off when +// it's larger than that and appears more than once. +const MIN_SHARED_SIZE = 64 + +/** A subschema worth sharing: a standalone object/union/described schema, not a `$ref` or a primitive. */ +const isShareable = (node: unknown): node is Record => { + if (!node || typeof node !== 'object' || Array.isArray(node) || '$ref' in node) { + return false + } + const schema = node as JsonSchemaType + return ( + Array.isArray(schema.oneOf) || + Array.isArray(schema.anyOf) || + Boolean(schema.properties) || + Boolean(schema.items) || + typeof schema.description === 'string' + ) +} + +/** + * **Size.** Replaces any subschema that appears more than once with a single shared `$defs` entry referenced by + * `$ref`. Lossless — only the serialized size shrinks. A collection with several rich-text fields, for + * example, inlines the same large lexical node schema once per field; this collapses them into one. + * + * @example + * { properties: { billing: address, shipping: address } } + * → { properties: { billing: { $ref: '#/$defs/shared_0' }, shipping: { $ref: '#/$defs/shared_0' } }, $defs: { shared_0: address } } + */ +const deduplicateIntoDefinitions = (schema: JsonSchemaType): JsonSchemaType => { + // Count how often each shareable subschema appears, keyed by its serialized form. + const counts = new Map() + const count = (node: unknown): void => { + if (isShareable(node)) { + const key = JSON.stringify(node) + if (key.length >= MIN_SHARED_SIZE) { + counts.set(key, (counts.get(key) ?? 0) + 1) + } + } + if (Array.isArray(node)) { + node.forEach(count) + } else if (node && typeof node === 'object') { + Object.values(node).forEach(count) + } + } + count(schema) + + if (![...counts.values()].some((n) => n >= 2)) { + return schema + } + + // Replace each subschema seen 2+ times with a `$ref`. The first time we meet one it becomes a shared + // entry; we never descend into a stored entry, so shared entries never reference one another. + const sharedEntries: Record = {} + const nameByKey = new Map() + const share = (node: unknown): unknown => { + if (isShareable(node)) { + const key = JSON.stringify(node) + if ((counts.get(key) ?? 0) >= 2) { + let name = nameByKey.get(key) + if (!name) { + name = `shared_${nameByKey.size}` + nameByKey.set(key, name) + sharedEntries[name] = node as JsonSchemaType + } + return { $ref: `#/$defs/${name}` } + } + } + if (Array.isArray(node)) { + return node.map(share) + } + if (node && typeof node === 'object') { + return Object.fromEntries( + Object.entries(node).map(([childKey, value]) => [childKey, share(value)]), + ) + } + return node + } + + const result = share(schema) as JsonSchemaType + result.$defs = { ...result.$defs, ...sharedEntries } + return result +} + +/** + * **LLM ergonomics.** Renames `$defs` entries to short, readable names so the `$ref`s stay legible to the model: a block's + * `blockType` (`Code`), a node's `type` (`paragraph`), `node` for a rich-text node union, otherwise the + * generated name with its disambiguating hash dropped. A numeric suffix keeps collisions unique. + * + * @example + * { properties: { body: { $ref: '#/$defs/LexicalNodes_9FBEC708' } }, $defs: { LexicalNodes_9FBEC708: {} } } + * → { properties: { body: { $ref: '#/$defs/node' } }, $defs: { node: {} } } + */ +const shortenDefinitionNames = (schema: JsonSchemaType): JsonSchemaType => { + const definitions = schema.$defs + if (!definitions || Object.keys(definitions).length === 0) { + return schema + } + + const shortNameFor = (name: string, definition: boolean | JsonSchemaType): string => { + const properties = (typeof definition === 'object' && definition.properties) || {} + const constString = (key: string): string | undefined => { + const prop = properties[key] + return prop && typeof prop === 'object' && typeof prop.const === 'string' + ? prop.const + : undefined + } + const members = + typeof definition === 'object' ? (definition.anyOf ?? definition.oneOf) : undefined + const isNodeUnion = + Array.isArray(members) && + members.some((m) => typeof m === 'object' && Boolean(m.$ref || m.properties?.type)) + return ( + constString('blockType') ?? + constString('type') ?? + (isNodeUnion ? 'node' : undefined) ?? + name.replace(/_[0-9A-F]{6,}$/i, '') + ) + } + + const prefix = '#/$defs/' + const usedNames = new Map() + const rename = new Map() + for (const [name, definition] of Object.entries(definitions)) { + const shortName = shortNameFor(name, definition) + const used = usedNames.get(shortName) ?? 0 + usedNames.set(shortName, used + 1) + rename.set(name, used === 0 ? shortName : `${shortName}${used + 1}`) + } + + const result = mapNodes(schema, (node) => { + if (typeof node.$ref === 'string' && node.$ref.startsWith(prefix)) { + const name = node.$ref.slice(prefix.length) + node.$ref = `${prefix}${rename.get(name) ?? name}` + } + return node + }) as JsonSchemaType + result.$defs = Object.fromEntries( + Object.entries(result.$defs!).map(([name, body]) => [rename.get(name) ?? name, body]), + ) + return result +} diff --git a/packages/plugin-mcp/src/utils/schemaConversion/sanitizeJsonSchema.ts b/packages/plugin-mcp/src/utils/schemaConversion/sanitizeJsonSchema.ts deleted file mode 100644 index 7a4579b0816..00000000000 --- a/packages/plugin-mcp/src/utils/schemaConversion/sanitizeJsonSchema.ts +++ /dev/null @@ -1,62 +0,0 @@ -import type { JsonSchemaType } from '../../types.js' - -/** - * Removes internal Payload properties (id, createdAt, updatedAt) from a - * JSON Schema so they don't appear in the generated Zod validation schema. - * Also strips `id` from the `required` array when present. - * - * Additionally normalizes nullable type arrays (e.g. `['array', 'null']` → - * `'array'`) throughout the schema tree. Without this, `json-schema-to-zod` - * emits a Zod union which the MCP SDK serialises back as `anyOf`, stripping - * the concrete `type` from the output and breaking schema introspection. - */ -export function sanitizeJsonSchema(schema: JsonSchemaType): JsonSchemaType { - delete schema?.properties?.id - delete schema?.properties?.createdAt - delete schema?.properties?.updatedAt - - if (Array.isArray(schema.required)) { - schema.required = schema.required.filter((field) => field !== 'id') - if (schema.required.length === 0) { - delete schema.required - } - } - - if (schema.properties && typeof schema.properties === 'object') { - for (const key of Object.keys(schema.properties)) { - const prop = schema.properties[key] as JsonSchemaType - if (!prop || typeof prop !== 'object') { - continue - } - normalizeNullableType(prop) - if (prop.properties) { - sanitizeJsonSchema(prop) - } - if (prop.items && typeof prop.items === 'object' && !Array.isArray(prop.items)) { - sanitizeJsonSchema(prop.items) - } - } - } - - return schema -} - -/** - * Strips `'null'` from a `type` array only when the remaining type is a - * complex structural type (`array` or `object`). - * - * Simple scalar types (`string`, `number`, `boolean`) are intentionally - * preserved as `['string', 'null']` so that the MCP SDK serialises them as a - * compact inline `type` array. Complex types however cause `zodToJsonSchema` - * to emit `anyOf: [{ type: 'array', items: ... }, { type: 'null' }]`, which - * has no top-level `type` property and breaks schema introspection by clients. - */ -function normalizeNullableType(schema: JsonSchemaType): void { - if (!Array.isArray(schema.type)) { - return - } - const nonNullTypes = schema.type.filter((t) => t !== 'null') - if (nonNullTypes.length === 1 && (nonNullTypes[0] === 'array' || nonNullTypes[0] === 'object')) { - schema.type = nonNullTypes[0] - } -} diff --git a/packages/plugin-mcp/src/utils/schemaConversion/simplifyRelationshipFields.ts b/packages/plugin-mcp/src/utils/schemaConversion/simplifyRelationshipFields.ts deleted file mode 100644 index eea1aaec07c..00000000000 --- a/packages/plugin-mcp/src/utils/schemaConversion/simplifyRelationshipFields.ts +++ /dev/null @@ -1,77 +0,0 @@ -import type { JsonSchemaType } from '../../types.js' - -/** - * Recursively simplifies relationship fields for MCP create/update input. We only need to accept - * IDs (string/number), not populated objects, so `$ref` options pointing at full entity definitions - * are dropped from `oneOf` unions. A lone remaining option is unwrapped; multiple become `anyOf`. - * - * NOTE: operates on a clone per level so the original schema (reused for tool listing) isn't mutated. - */ -export function simplifyRelationshipFields(schema: JsonSchemaType): JsonSchemaType { - if (!schema || typeof schema !== 'object') { - return schema - } - - const processed = { ...schema } - - if (Array.isArray(processed.oneOf)) { - const hasRef = processed.oneOf.some( - (option) => option && typeof option === 'object' && '$ref' in option, - ) - - const recurse = (option: boolean | JsonSchemaType): boolean | JsonSchemaType => - typeof option === 'object' ? simplifyRelationshipFields(option) : option - - if (hasRef) { - const nonRefOptions = processed.oneOf - .filter((option) => !(option && typeof option === 'object' && '$ref' in option)) - .map(recurse) - - if (nonRefOptions.length === 1) { - const single = nonRefOptions[0]! - // A single-target relationship collapses to a bare ID; note the target collection(s) in a description. - const refSlugs = processed.oneOf - .filter((option) => option && typeof option === 'object' && '$ref' in option) - .map((option) => String((option as { $ref: string }).$ref).replace('#/$defs/', '')) - delete processed.oneOf - if (typeof single === 'object') { - Object.assign(processed, single) - } - if (refSlugs.length > 0 && !processed.description) { - processed.description = `The ID of the related "${refSlugs.join('" or "')}" document.` - } - } else if (nonRefOptions.length > 1) { - delete processed.oneOf - processed.anyOf = nonRefOptions - } - } else { - processed.oneOf = processed.oneOf.map(recurse) - } - } - - if (processed.properties && typeof processed.properties === 'object') { - processed.properties = Object.fromEntries( - Object.entries(processed.properties).map(([key, value]) => [ - key, - typeof value === 'object' ? simplifyRelationshipFields(value) : value, - ]), - ) - } - - if (processed.items && typeof processed.items === 'object' && !Array.isArray(processed.items)) { - processed.items = simplifyRelationshipFields(processed.items) - } - - // Also walk `$defs`: lexical node unions and blocks live there, and their relationship - // fields point at collections that aren't bundled. Simplifying them drops those refs to IDs. - if (processed.$defs && typeof processed.$defs === 'object') { - processed.$defs = Object.fromEntries( - Object.entries(processed.$defs).map(([key, value]) => [ - key, - typeof value === 'object' ? simplifyRelationshipFields(value) : value, - ]), - ) - } - - return processed -} diff --git a/packages/plugin-mcp/src/utils/schemaConversion/transformPointFields.ts b/packages/plugin-mcp/src/utils/schemaConversion/transformPointFields.ts deleted file mode 100644 index edefeececa9..00000000000 --- a/packages/plugin-mcp/src/utils/schemaConversion/transformPointFields.ts +++ /dev/null @@ -1,56 +0,0 @@ -import type { JsonSchemaType } from '../../types.js' - -export function transformPointFieldsForMCP(schema: JsonSchemaType): JsonSchemaType { - if (!schema || typeof schema !== 'object') { - return schema - } - - const transformed = { ...schema } - - if (transformed.properties && typeof transformed.properties === 'object') { - transformed.properties = Object.fromEntries( - Object.entries(transformed.properties).map(([key, value]) => { - if (!value || typeof value !== 'object') { - return [key, value] - } - const isArrayType = - value.type === 'array' || (Array.isArray(value.type) && value.type.includes('array')) - - if ( - isArrayType && - Array.isArray(value.items) && - value.items.length === 2 && - value.items.every((item) => item && typeof item === 'object' && item.type === 'number') - ) { - // Transform to object format - const isNullable = Array.isArray(value.type) && value.type.includes('null') - - return [ - key, - { - type: isNullable ? ['object', 'null'] : 'object', - description: value.description || 'Geographic coordinates (longitude, latitude)', - properties: { - latitude: { type: 'number', description: 'Latitude coordinate' }, - longitude: { type: 'number', description: 'Longitude coordinate' }, - }, - required: ['longitude', 'latitude'], - }, - ] - } - - return [key, transformPointFieldsForMCP(value)] - }), - ) - } - - if ( - transformed.items && - typeof transformed.items === 'object' && - !Array.isArray(transformed.items) - ) { - transformed.items = transformPointFieldsForMCP(transformed.items) - } - - return transformed -} diff --git a/test/plugin-mcp/int.spec.ts b/test/plugin-mcp/int.spec.ts index 4804bb5104e..9d206de1647 100644 --- a/test/plugin-mcp/int.spec.ts +++ b/test/plugin-mcp/int.spec.ts @@ -4,6 +4,50 @@ import { afterEach, describe, expect } from 'vitest' import { getToolDoc, getToolText } from './helpers/mcpClient.js' import { getApiKey, it, payload, restClient, userId } from './helpers/mcpFixtures.js' +/** + * Reports JSON Schema draft 2020-12 violations in a tool's `input_schema + */ +function draft2020Violations(schema: unknown, rootPath: string): string[] { + const errors: string[] = [] + const walk = (node: any, jsonPath: string): void => { + if (Array.isArray(node)) { + node.forEach((child, index) => walk(child, `${jsonPath}/${index}`)) + return + } + if (!node || typeof node !== 'object') { + return + } + if (typeof node.$schema === 'string' && !node.$schema.includes('2020-12')) { + errors.push(`${jsonPath}: non-2020-12 $schema "${node.$schema}"`) + } + if ('definitions' in node) { + errors.push(`${jsonPath}: draft-07 "definitions" (2020-12 uses "$defs")`) + } + if (typeof node.$ref === 'string' && node.$ref.startsWith('#/definitions/')) { + errors.push(`${jsonPath}: $ref into draft-07 "definitions"`) + } + if (Array.isArray(node.required) && new Set(node.required).size !== node.required.length) { + errors.push(`${jsonPath}: duplicate "required" entries [${node.required.join(', ')}]`) + } + if ( + Array.isArray(node.type) && + (node.type.length === 0 || new Set(node.type).size !== node.type.length) + ) { + errors.push(`${jsonPath}: invalid "type" array [${node.type.join(', ')}]`) + } + for (const keyword of ['allOf', 'anyOf', 'oneOf']) { + if (keyword in node && (!Array.isArray(node[keyword]) || node[keyword].length === 0)) { + errors.push(`${jsonPath}: empty "${keyword}"`) + } + } + for (const [key, value] of Object.entries(node)) { + walk(value, `${jsonPath}/${key}`) + } + } + walk(schema, rootPath) + return errors +} + describe('@payloadcms/plugin-mcp', () => { it('should ping', async ({ mcp }) => { const apiKey = await getApiKey() @@ -187,6 +231,22 @@ describe('@payloadcms/plugin-mcp', () => { expect(diceRoll.inputSchema.properties.sides.maximum).toBe(1000) }) + it('should expose only tool input schemas that are valid JSON Schema draft 2020-12', async ({ + mcp, + }) => { + const apiKey = await getApiKey() + const toolsResponse = await mcp.listTools({ apiKey }) + const tools = toolsResponse.result.tools as Array<{ inputSchema?: object; name: string }> + + // MCP clients validate each input_schema against the strict 2020-12 meta-schema. The SDK's own validator is + // lenient (it only compiles), so lint for what the meta-schema enforces. + const invalid = tools.flatMap((tool) => + tool.inputSchema ? draft2020Violations(tool.inputSchema, tool.name) : [], + ) + + expect(invalid).toEqual([]) + }) + it('should list tools injected by other plugins via slug and options', async ({ mcp }) => { const apiKey = await getApiKey() const toolsResponse = await mcp.listTools({ apiKey }) @@ -229,7 +289,9 @@ describe('@payloadcms/plugin-mcp', () => { expect(promptsResponse.result.prompts).toHaveLength(1) expect(promptsResponse.result.prompts[0].name).toBe('echo') expect(promptsResponse.result.prompts[0].title).toBe('Echo Prompt') - expect(promptsResponse.result.prompts[0].description).toBe('Creates a prompt to process a message') + expect(promptsResponse.result.prompts[0].description).toBe( + 'Creates a prompt to process a message', + ) expect(promptsResponse.result.prompts[0].arguments).toBeDefined() expect(promptsResponse.result.prompts[0].arguments).toHaveLength(1) expect(promptsResponse.result.prompts[0].arguments[0].name).toBe('message') @@ -245,7 +307,9 @@ describe('@payloadcms/plugin-mcp', () => { expect(toolsResponse.result.tools).toBeDefined() // The global's description (from plugin config) overrides the built-in tool description - const findGlobalTool = toolsResponse.result.tools.find((t: any) => t.name === 'findSiteSettings') + const findGlobalTool = toolsResponse.result.tools.find( + (t: any) => t.name === 'findSiteSettings', + ) expect(findGlobalTool).toBeDefined() expect(findGlobalTool.description).toContain('Site-wide configuration settings.') expect(findGlobalTool.inputSchema.properties.select).toBeDefined() @@ -254,7 +318,9 @@ describe('@payloadcms/plugin-mcp', () => { "Optional: define exactly which fields you'd like to return in the response (JSON), e.g., '{\"title\": true}'", ) - const updateGlobalTool = toolsResponse.result.tools.find((t: any) => t.name === 'updateSiteSettings') + const updateGlobalTool = toolsResponse.result.tools.find( + (t: any) => t.name === 'updateSiteSettings', + ) expect(updateGlobalTool).toBeDefined() expect(updateGlobalTool.description).toContain('Site-wide configuration settings.') expect(updateGlobalTool.inputSchema.properties.select).toBeDefined() @@ -264,7 +330,9 @@ describe('@payloadcms/plugin-mcp', () => { ) }) - it('should list updatePosts when API key permits update and include select schema', async ({ mcp }) => { + it('should list updatePosts when API key permits update and include select schema', async ({ + mcp, + }) => { const apiKey = await getApiKey({ enableUpdate: true }) const toolsResponse = await mcp.listTools({ apiKey }) @@ -296,7 +364,9 @@ describe('@payloadcms/plugin-mcp', () => { expect(promptResponse.result).toBeDefined() expect(promptResponse.result.messages).toHaveLength(2) expect(promptResponse.result.messages[0].content.type).toBe('text') - expect(promptResponse.result.messages[0].content.text).toContain('This prompt was sent: Hello, world!') + expect(promptResponse.result.messages[0].content.text).toContain( + 'This prompt was sent: Hello, world!', + ) expect(promptResponse.result.messages[1].content.type).toBe('text') expect(promptResponse.result.messages[1].content.text).toContain( `This prompt was sent by userId: ${userId}`, @@ -335,7 +405,9 @@ describe('@payloadcms/plugin-mcp', () => { expect(resourceResponse.result.contents).toHaveLength(2) expect(resourceResponse.result.contents[0].uri).toBe('data://app') expect(resourceResponse.result.contents[0].text).toContain('My special data.') - expect(resourceResponse.result.contents[1].text).toContain(`This was requested by user: ${userId}`) + expect(resourceResponse.result.contents[1].text).toContain( + `This was requested by user: ${userId}`, + ) const { docs } = await payload.find({ collection: 'returned-resources', @@ -368,7 +440,9 @@ describe('@payloadcms/plugin-mcp', () => { expect(resourceResponse.result.contents).toHaveLength(2) expect(resourceResponse.result.contents[0].uri).toBe('data://app/1') expect(resourceResponse.result.contents[0].text).toContain('My special data for ID: 1') - expect(resourceResponse.result.contents[1].text).toContain(`This was requested by user: ${userId}`) + expect(resourceResponse.result.contents[1].text).toContain( + `This was requested by user: ${userId}`, + ) const { docs } = await payload.find({ collection: 'returned-resources', @@ -718,7 +792,9 @@ describe('@payloadcms/plugin-mcp', () => { ) expect(callResponse.result.content[0].text).toContain('Deleted document:') expect(callResponse.result.content[0].text).toContain('```json') - expect(callResponse.result.content[0].text).toContain('"content":"Content for test post to delete."') + expect(callResponse.result.content[0].text).toContain( + '"content":"Content for test post to delete."', + ) }) it('should handle point fields with object format in createPosts', async ({ mcp }) => { @@ -1095,7 +1171,9 @@ describe('@payloadcms/plugin-mcp', () => { expect(callResponse.result).toBeDefined() expect(callResponse.result.content).toBeDefined() expect(callResponse.result.content[0].type).toBe('text') - expect(callResponse.result.content[0].text).toContain('Global "site-settings" updated successfully') + expect(callResponse.result.content[0].text).toContain( + 'Global "site-settings" updated successfully', + ) }) it('should update site-settings global with select', async ({ mcp }) => { @@ -1135,7 +1213,9 @@ describe('@payloadcms/plugin-mcp', () => { createdIDs.length = 0 }) - it('should return minified JSON without newlines or indentation in resource responses', async ({ mcp }) => { + it('should return minified JSON without newlines or indentation in resource responses', async ({ + mcp, + }) => { const doc = await payload.create({ collection: 'posts', data: { @@ -1268,7 +1348,9 @@ describe('@payloadcms/plugin-mcp', () => { expect(callResponse.result).toBeDefined() expect(callResponse.result.content[0].text).toContain('Document created successfully') expect(callResponse.result.content[0].text).toContain('"title":"Hello World"') - expect(callResponse.result.content[0].text).toContain('"content":"This is my first post in English"') + expect(callResponse.result.content[0].text).toContain( + '"content":"This is my first post in English"', + ) }) it('should update post to add translation', async ({ mcp }) => { @@ -1458,7 +1540,9 @@ describe('@payloadcms/plugin-mcp', () => { const toolsResponse = await mcp.listTools({ apiKey }) expect(toolsResponse.result.tools).toBeDefined() - const createTool = toolsResponse.result.tools.find((t: any) => t.name === 'createFieldTypes') + const createTool = toolsResponse.result.tools.find( + (t: any) => t.name === 'createFieldTypes', + ) expect(createTool).toBeDefined() const inputProps = createTool.inputSchema.properties.data.properties @@ -1468,7 +1552,9 @@ describe('@payloadcms/plugin-mcp', () => { it('should include group field as nested object in create tool schema', async ({ mcp }) => { const apiKey = await getFieldTypesApiKey() const toolsResponse = await mcp.listTools({ apiKey }) - const createTool = toolsResponse.result.tools.find((t: any) => t.name === 'createFieldTypes') + const createTool = toolsResponse.result.tools.find( + (t: any) => t.name === 'createFieldTypes', + ) const inputProps = createTool.inputSchema.properties.data.properties expect(inputProps.groupField).toBeDefined() @@ -1478,35 +1564,47 @@ describe('@payloadcms/plugin-mcp', () => { expect(inputProps.groupField.properties.groupNumber).toBeDefined() }) - it('should include collapsible children as top-level fields in create tool schema', async ({ mcp }) => { + it('should include collapsible children as top-level fields in create tool schema', async ({ + mcp, + }) => { const apiKey = await getFieldTypesApiKey() const toolsResponse = await mcp.listTools({ apiKey }) - const createTool = toolsResponse.result.tools.find((t: any) => t.name === 'createFieldTypes') + const createTool = toolsResponse.result.tools.find( + (t: any) => t.name === 'createFieldTypes', + ) const inputProps = createTool.inputSchema.properties.data.properties // Children of collapsible appear at the top level, not under a `collapsible` key expect(inputProps.collapsibleText).toBeDefined() - // Nullable text fields render as anyOf: [string, null] - expect(inputProps.collapsibleText.anyOf).toBeDefined() - expect(inputProps.collapsibleText.anyOf.some((t: any) => t.type === 'string')).toBe(true) + // Nullable text fields render as a type array: ['string', 'null'] + expect(inputProps.collapsibleText.type).toContain('string') + expect(inputProps.collapsibleText.type).toContain('null') }) - it('should include row children as top-level fields in create tool schema', async ({ mcp }) => { + it('should include row children as top-level fields in create tool schema', async ({ + mcp, + }) => { const apiKey = await getFieldTypesApiKey() const toolsResponse = await mcp.listTools({ apiKey }) - const createTool = toolsResponse.result.tools.find((t: any) => t.name === 'createFieldTypes') + const createTool = toolsResponse.result.tools.find( + (t: any) => t.name === 'createFieldTypes', + ) const inputProps = createTool.inputSchema.properties.data.properties // Children of row appear at the top level, not under a `row` key expect(inputProps.rowText).toBeDefined() - expect(inputProps.rowText.anyOf).toBeDefined() - expect(inputProps.rowText.anyOf.some((t: any) => t.type === 'string')).toBe(true) + expect(inputProps.rowText.type).toContain('string') + expect(inputProps.rowText.type).toContain('null') }) - it('should include named tab as nested object and unnamed tab children at top level in create tool schema', async ({ mcp }) => { + it('should include named tab as nested object and unnamed tab children at top level in create tool schema', async ({ + mcp, + }) => { const apiKey = await getFieldTypesApiKey() const toolsResponse = await mcp.listTools({ apiKey }) - const createTool = toolsResponse.result.tools.find((t: any) => t.name === 'createFieldTypes') + const createTool = toolsResponse.result.tools.find( + (t: any) => t.name === 'createFieldTypes', + ) const inputProps = createTool.inputSchema.properties.data.properties // Named tab appears as a nested object @@ -1517,14 +1615,16 @@ describe('@payloadcms/plugin-mcp', () => { // Unnamed tab children appear at the top level expect(inputProps.unnamedTabText).toBeDefined() - expect(inputProps.unnamedTabText.anyOf).toBeDefined() - expect(inputProps.unnamedTabText.anyOf.some((t: any) => t.type === 'string')).toBe(true) + expect(inputProps.unnamedTabText.type).toContain('string') + expect(inputProps.unnamedTabText.type).toContain('null') }) it('should include select field with enum values in create tool schema', async ({ mcp }) => { const apiKey = await getFieldTypesApiKey() const toolsResponse = await mcp.listTools({ apiKey }) - const createTool = toolsResponse.result.tools.find((t: any) => t.name === 'createFieldTypes') + const createTool = toolsResponse.result.tools.find( + (t: any) => t.name === 'createFieldTypes', + ) const inputProps = createTool.inputSchema.properties.data.properties expect(inputProps.selectField).toBeDefined() @@ -1537,7 +1637,9 @@ describe('@payloadcms/plugin-mcp', () => { it('should include radio field with enum values in create tool schema', async ({ mcp }) => { const apiKey = await getFieldTypesApiKey() const toolsResponse = await mcp.listTools({ apiKey }) - const createTool = toolsResponse.result.tools.find((t: any) => t.name === 'createFieldTypes') + const createTool = toolsResponse.result.tools.find( + (t: any) => t.name === 'createFieldTypes', + ) const inputProps = createTool.inputSchema.properties.data.properties expect(inputProps.radioField).toBeDefined() @@ -1550,7 +1652,9 @@ describe('@payloadcms/plugin-mcp', () => { it('should include array field with item schema in create tool schema', async ({ mcp }) => { const apiKey = await getFieldTypesApiKey() const toolsResponse = await mcp.listTools({ apiKey }) - const createTool = toolsResponse.result.tools.find((t: any) => t.name === 'createFieldTypes') + const createTool = toolsResponse.result.tools.find( + (t: any) => t.name === 'createFieldTypes', + ) const inputProps = createTool.inputSchema.properties.data.properties expect(inputProps.arrayField).toBeDefined() @@ -1563,7 +1667,9 @@ describe('@payloadcms/plugin-mcp', () => { }) describe('Create + round-trip', () => { - it('should create and find document with atomic data fields (text, textarea, number, email, checkbox)', async ({ mcp }) => { + it('should create and find document with atomic data fields (text, textarea, number, email, checkbox)', async ({ + mcp, + }) => { const apiKey = await getFieldTypesApiKey(false, true) const callResponse = await mcp.callTool({ apiKey, @@ -1747,7 +1853,9 @@ describe('@payloadcms/plugin-mcp', () => { createdFieldTypeIds.push(doc.id) }) - it('should create document with tabs fields (named tab as object, unnamed tab children at top level)', async ({ mcp }) => { + it('should create document with tabs fields (named tab as object, unnamed tab children at top level)', async ({ + mcp, + }) => { const apiKey = await getFieldTypesApiKey(false, true) const callResponse = await mcp.callTool({ apiKey, @@ -1870,7 +1978,9 @@ describe('@payloadcms/plugin-mcp', () => { expect(doc.groupField.groupNumber).toBe(100) }) - it('should update document with collapsible field (children at top level)', async ({ mcp }) => { + it('should update document with collapsible field (children at top level)', async ({ + mcp, + }) => { const created = await (payload as any).create({ collection: 'field-types', data: { @@ -1938,7 +2048,9 @@ describe('@payloadcms/plugin-mcp', () => { }) describe('Display field safety', () => { - it('should create document with ui field present without errors and ui field absent from response', async ({ mcp }) => { + it('should create document with ui field present without errors and ui field absent from response', async ({ + mcp, + }) => { const apiKey = await getFieldTypesApiKey(false, true) // Create a doc without passing any `uiField` value (it has no stored data) @@ -1964,7 +2076,9 @@ describe('@payloadcms/plugin-mcp', () => { createdFieldTypeIds.push(doc.id) }) - it('should create and find document with all structural layout fields populated', async ({ mcp }) => { + it('should create and find document with all structural layout fields populated', async ({ + mcp, + }) => { const apiKey = await getFieldTypesApiKey(false, true) const callResponse = await mcp.callTool({ apiKey, From 043c36ef62a3eae44e7b94bb157fae404fc5a211 Mon Sep 17 00:00:00 2001 From: German Jablonski <43938777+GermanJablo@users.noreply.github.com> Date: Fri, 5 Jun 2026 11:25:17 +0100 Subject: [PATCH 53/56] test: regenerate payload types (#16878) I thought it would be useful to include the generated test payload types in this PR so we can see the full impact of the rich text type-generation changes. ## Summary - Regenerated payload types across the test suites with `pnpm dev:generate-types`. - Includes the generated `test/uuid-v7/payload-types.ts` file that the script now produces. ## Test plan - Ran `pnpm dev:generate-types`. --- test/_community/payload-types.ts | 176 ++- test/a11y/payload-types.ts | 166 ++- test/access-control/payload-types.ts | 710 ++++++--- test/admin-bar/payload-types.ts | 179 ++- test/admin-root/payload-types.ts | 179 ++- test/admin/payload-types.ts | 265 +++- test/array-update/payload-types.ts | 179 ++- test/auth-basic/payload-types.ts | 186 ++- test/auth/payload-types.ts | 336 ++++- test/benchmark-blocks/payload-types.ts | 1556 ++++++++++++-------- test/bulk-edit/payload-types.ts | 185 ++- test/collections-graphql/payload-types.ts | 125 +- test/collections-rest/payload-types.ts | 179 ++- test/config/payload-types.ts | 192 ++- test/custom-graphql/payload-types.ts | 186 ++- test/dashboard/payload-types.ts | 132 +- test/database/payload-types.ts | 726 ++++++--- test/dataloader/payload-types.ts | 336 ++++- test/email-nodemailer/payload-types.ts | 186 ++- test/email-resend/payload-types.ts | 186 ++- test/email/payload-types.ts | 179 ++- test/endpoints/payload-types.ts | 179 ++- test/evals/payload-types.ts | 181 ++- test/field-error-states/payload-types.ts | 506 +++++-- test/field-paths/payload-types.ts | 190 ++- test/field-perf/payload-types.ts | 429 +++++- test/fields-relationship/payload-types.ts | 166 ++- test/fields/payload-types.ts | 990 ++++++++----- test/folders/payload-types.ts | 166 ++- test/form-state/payload-types.ts | 203 ++- test/globals/payload-types.ts | 186 ++- test/graphql-schema-gen/payload-types.ts | 179 ++- test/graphql/payload-types.ts | 177 ++- test/hierarchy/payload-types.ts | 166 ++- test/hooks/payload-types.ts | 411 +++++- test/i18n/payload-types.ts | 166 ++- test/joins/payload-types.ts | 131 +- test/kv/payload-types.ts | 186 ++- test/lexical-mdx/payload-types.ts | 517 ++++++- test/live-preview/payload-types.ts | 1394 +++++++----------- test/localization-rtl/payload-types.ts | 346 ++++- test/localization/payload-types.ts | 713 ++++++--- test/locked-documents/payload-types.ts | 357 ++++- test/login-with-username/payload-types.ts | 107 +- test/migrations-cli/payload-types.ts | 186 ++- test/nested-fields/payload-types.ts | 282 ++-- test/payload-cloud/payload-types.ts | 168 ++- test/plugin-cloud-storage/payload-types.ts | 112 +- test/plugin-ecommerce/payload-types.ts | 112 +- test/plugin-form-builder/payload-types.ts | 701 ++++++--- test/plugin-import-export/payload-types.ts | 506 +++++-- test/plugin-multi-tenant/payload-types.ts | 319 +++- test/plugin-nested-docs/payload-types.ts | 125 +- test/plugin-redirects/payload-types.ts | 125 +- test/plugin-search/payload-types.ts | 125 +- test/plugin-sentry/payload-types.ts | 125 +- test/plugin-seo/payload-types.ts | 336 ++++- test/plugin-stripe/payload-types.ts | 107 +- test/plugins/payload-types.ts | 125 +- test/query-presets/payload-types.ts | 112 +- test/queues/payload-types.ts | 356 ++++- test/relationships/payload-types.ts | 210 ++- test/sdk/payload-types.ts | 127 +- test/select/payload-types.ts | 531 +++++-- test/server-functions/payload-types.ts | 186 ++- test/server-url/payload-types.ts | 186 ++- test/sort/payload-types.ts | 166 ++- test/storage-azure/payload-types.ts | 112 +- test/storage-gcs/payload-types.ts | 125 +- test/storage-r2/payload-types.ts | 125 +- test/storage-s3/payload-types.ts | 125 +- test/storage-uploadthing/payload-types.ts | 127 +- test/storage-vercel-blob/payload-types.ts | 269 +++- test/tags/payload-types.ts | 166 ++- test/trash/payload-types.ts | 112 +- test/uploads/payload-types.ts | 470 +++++- test/uuid-v7/payload-types.ts | 373 +++++ test/v4/payload-types.ts | 1165 ++++++++++++--- test/versions/payload-types.ts | 440 ++++-- 79 files changed, 18173 insertions(+), 5354 deletions(-) create mode 100644 test/uuid-v7/payload-types.ts diff --git a/test/_community/payload-types.ts b/test/_community/payload-types.ts index 835827c20d7..36768493879 100644 --- a/test/_community/payload-types.ts +++ b/test/_community/payload-types.ts @@ -60,6 +60,32 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_00871687". + */ +export type LexicalNodes_00871687 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedHorizontalRuleNode + | SerializedUploadNode<'media'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'posts' + | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; export interface Config { auth: { @@ -151,21 +177,7 @@ export interface PayloadMcpApiKeyAuthOperations { export interface Post { id: string; title?: string | null; - content?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + content?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -550,6 +562,140 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export interface SerializedHorizontalRuleNode { + type: 'horizontalrule'; + version: number; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + declare module 'payload' { // @ts-ignore diff --git a/test/a11y/payload-types.ts b/test/a11y/payload-types.ts index 4d1b256f6b3..3d3875685b1 100644 --- a/test/a11y/payload-types.ts +++ b/test/a11y/payload-types.ts @@ -64,13 +64,15 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { posts: Post; media: Media; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -79,8 +81,9 @@ export interface Config { collectionsSelect: { posts: PostsSelect | PostsSelect; media: MediaSelect | MediaSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -99,7 +102,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -123,6 +126,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts". @@ -181,23 +202,6 @@ export interface Media { }; }; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -223,6 +227,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -241,12 +305,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -256,10 +329,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -345,14 +423,6 @@ export interface MediaSelect { }; }; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -375,6 +445,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". diff --git a/test/access-control/payload-types.ts b/test/access-control/payload-types.ts index c4cb5b4fc08..da3aad832da 100644 --- a/test/access-control/payload-types.ts +++ b/test/access-control/payload-types.ts @@ -60,12 +60,140 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_0219D497". + */ +export type LexicalNodes_0219D497 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> + | SerializedHeadingNode + | { + type: 'upload'; + /** + * Lexical's internal serialization version for this node type. + */ + version: number; + [k: string]: unknown; + } + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedRelationshipNode< + | 'users' + | 'public-users' + | 'posts' + | 'unrestricted' + | 'relation-restricted' + | 'fully-restricted' + | 'read-only-collection' + | 'user-restricted-collection' + | 'can-create-not-update-collection' + | 'restricted-versions' + | 'restricted-versions-admin-panel' + | 'sibling-data' + | 'rely-on-request-headers' + | 'doc-level-access' + | 'hidden-fields' + | 'hidden-access' + | 'hidden-access-count' + | 'fields-and-top-access' + | 'blocks-field-access' + | 'disabled' + | 'rich-text' + | 'regression1' + | 'regression2' + | 'hooks' + | 'auth-collection' + | 'read-restricted' + | 'differentiated-trash' + | 'restricted-trash' + | 'field-restricted-update-based-on-data' + | 'where-cache-same' + | 'where-cache-unique' + | 'async-parent' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + >; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_3CC4B7D0". + */ +export type LexicalNodes_3CC4B7D0 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedHorizontalRuleNode + | { + type: 'upload'; + /** + * Lexical's internal serialization version for this node type. + */ + version: number; + [k: string]: unknown; + } + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'users' + | 'public-users' + | 'posts' + | 'unrestricted' + | 'relation-restricted' + | 'fully-restricted' + | 'read-only-collection' + | 'user-restricted-collection' + | 'can-create-not-update-collection' + | 'restricted-versions' + | 'restricted-versions-admin-panel' + | 'sibling-data' + | 'rely-on-request-headers' + | 'doc-level-access' + | 'hidden-fields' + | 'hidden-access' + | 'hidden-access-count' + | 'fields-and-top-access' + | 'blocks-field-access' + | 'disabled' + | 'rich-text' + | 'regression1' + | 'regression2' + | 'hooks' + | 'auth-collection' + | 'read-restricted' + | 'differentiated-trash' + | 'restricted-trash' + | 'field-restricted-update-based-on-data' + | 'where-cache-same' + | 'where-cache-unique' + | 'async-parent' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; export interface Config { auth: { users: UserAuthOperations; 'public-users': PublicUserAuthOperations; 'auth-collection': AuthCollectionAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: { titleblock: Titleblock; @@ -103,6 +231,7 @@ export interface Config { 'where-cache-same': WhereCacheSame; 'where-cache-unique': WhereCacheUnique; 'async-parent': AsyncParent; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -142,6 +271,7 @@ export interface Config { 'where-cache-same': WhereCacheSameSelect | WhereCacheSameSelect; 'where-cache-unique': WhereCacheUniqueSelect | WhereCacheUniqueSelect; 'async-parent': AsyncParentSelect | AsyncParentSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -169,7 +299,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User | PublicUser | AuthCollection; + user: User | PublicUser | AuthCollection | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -229,9 +359,27 @@ export interface AuthCollectionAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "titleblock". + * via the `definition` "Titleblock". */ export interface Titleblock { title?: string | null; @@ -495,41 +643,50 @@ export interface FieldsAndTopAccess { export interface BlocksFieldAccess { id: string; title: string; - editableBlocks?: - | { - title?: string | null; - content?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'testBlock'; - }[] - | null; - readOnlyBlocks?: - | { - title?: string | null; - content?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'testBlock2'; - }[] - | null; + editableBlocks?: TestBlock[] | null; + readOnlyBlocks?: TestBlock2[] | null; editableBlockRefs?: Titleblock[] | null; readOnlyBlockRefs?: Titleblock[] | null; tabReadOnlyTest?: { - tabReadOnlyBlocks?: - | { - title?: string | null; - content?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'testBlock3'; - }[] - | null; + tabReadOnlyBlocks?: TestBlock3[] | null; tabReadOnlyBlockRefs?: Titleblock[] | null; }; updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TestBlock". + */ +export interface TestBlock { + title?: string | null; + content?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'testBlock'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TestBlock2". + */ +export interface TestBlock2 { + title?: string | null; + content?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'testBlock2'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TestBlock3". + */ +export interface TestBlock3 { + title?: string | null; + content?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'testBlock3'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "disabled". @@ -558,31 +715,20 @@ export interface Disabled { */ export interface RichText { id: string; - blocks?: - | { - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - id?: string | null; - blockName?: string | null; - blockType: 'richText'; - }[] - | null; + blocks?: RichText1[] | null; updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "RichText". + */ +export interface RichText1 { + richText?: LexicalRichText | null; + id?: string | null; + blockName?: string | null; + blockType: 'richText'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "regression1". @@ -590,164 +736,63 @@ export interface RichText { export interface Regression1 { id: string; group1?: { - richText1?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText1?: LexicalRichText | null; text?: string | null; }; tab1?: { - richText2?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - blocks2?: - | { - richText3?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - id?: string | null; - blockName?: string | null; - blockType: 'myBlock'; - }[] - | null; + richText2?: LexicalRichText | null; + blocks2?: MyBlock_C0B6048C[] | null; }; - richText4?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - blocks3?: - | { - richText5?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - id?: string | null; - blockName?: string | null; - blockType: 'myBlock2'; - }[] - | null; + richText4?: LexicalRichText | null; + blocks3?: MyBlock2[] | null; array?: | { - art?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + art?: LexicalRichText | null; id?: string | null; }[] | null; arrayWithAccessFalse?: | { - richText6?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - id?: string | null; - }[] - | null; - blocks?: - | { - richText7?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText6?: LexicalRichText | null; id?: string | null; - blockName?: string | null; - blockType: 'myBlock3'; }[] | null; + blocks?: MyBlock3[] | null; updatedAt: string; createdAt: string; } +/** + * Multiple blocks resolve to the `MyBlock` interface with different fields, so a content hash is appended to keep the generated types stable and unambiguous. Set a unique `interfaceName` on the block to choose the name yourself. See https://payloadcms.com/docs/typescript/generating-types#block-interface-name-collisions + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock_C0B6048C". + */ +export interface MyBlock_C0B6048C { + richText3?: LexicalRichText | null; + id?: string | null; + blockName?: string | null; + blockType: 'myBlock'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock2". + */ +export interface MyBlock2 { + richText5?: LexicalRichText | null; + id?: string | null; + blockName?: string | null; + blockType: 'myBlock2'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock3". + */ +export interface MyBlock3 { + richText7?: LexicalRichText | null; + id?: string | null; + blockName?: string | null; + blockType: 'myBlock3'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "regression2". @@ -755,40 +800,12 @@ export interface Regression1 { export interface Regression2 { id: string; group?: { - richText1?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText1?: LexicalRichText | null; text?: string | null; }; array?: | { - richText2?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText2?: LexicalRichText | null; id?: string | null; }[] | null; @@ -971,6 +988,49 @@ export interface AsyncParent { updatedAt: string; createdAt: string; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -1122,6 +1182,10 @@ export interface PayloadLockedDocument { | ({ relationTo: 'async-parent'; value: string | AsyncParent; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; user: @@ -1136,6 +1200,10 @@ export interface PayloadLockedDocument { | { relationTo: 'auth-collection'; value: string | AuthCollection; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; }; updatedAt: string; createdAt: string; @@ -1158,6 +1226,10 @@ export interface PayloadPreference { | { relationTo: 'auth-collection'; value: string | AuthCollection; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; }; key?: string | null; value?: @@ -1781,6 +1853,22 @@ export interface AsyncParentSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -1929,6 +2017,38 @@ export interface CollectionsWidget { }; width: 'full'; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock". + */ +export interface MyBlock { + id: string; + blockType: 'myBlock'; + someText?: string | null; + someTextRequired: string; + radios?: ('option1' | 'option2' | 'option3') | null; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_0219D497". + */ +export interface LexicalLinkFields_0219D497 { + linkType: 'custom' | 'internal'; + url?: string; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + newTab: boolean; + description?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". @@ -1937,6 +2057,152 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export type SerializedBlockNode = { + type: 'block'; + format: LexicalElementFormat; + version: number; + fields: { id: string; blockName?: string | null } & Omit; +}; +export type SerializedInlineBlockNode = { + type: 'inlineBlock'; + version: number; + fields: { id: string } & Omit; +}; + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + +export interface SerializedHorizontalRuleNode { + type: 'horizontalrule'; + version: number; +} + declare module 'payload' { // @ts-ignore diff --git a/test/admin-bar/payload-types.ts b/test/admin-bar/payload-types.ts index d9e8308f3b9..2c7dbc22b18 100644 --- a/test/admin-bar/payload-types.ts +++ b/test/admin-bar/payload-types.ts @@ -64,13 +64,15 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { posts: Post; media: Media; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -79,8 +81,9 @@ export interface Config { collectionsSelect: { posts: PostsSelect | PostsSelect; media: MediaSelect | MediaSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -92,7 +95,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -116,6 +122,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts". @@ -171,23 +195,6 @@ export interface Media { }; }; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -213,6 +220,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -231,12 +298,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -246,10 +322,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -335,14 +416,6 @@ export interface MediaSelect { }; }; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -365,6 +438,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -397,6 +494,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/admin-root/payload-types.ts b/test/admin-root/payload-types.ts index 5823bcc2f9c..86cc8c46852 100644 --- a/test/admin-root/payload-types.ts +++ b/test/admin-root/payload-types.ts @@ -64,12 +64,14 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { posts: Post; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -77,8 +79,9 @@ export interface Config { collectionsJoins: {}; collectionsSelect: { posts: PostsSelect | PostsSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -94,7 +97,10 @@ export interface Config { menu: MenuSelect | MenuSelect; }; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -118,6 +124,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts". @@ -129,23 +153,6 @@ export interface Post { createdAt: string; _status?: ('draft' | 'published') | null; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -171,6 +178,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -185,12 +252,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -200,10 +276,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -238,14 +319,6 @@ export interface PostsSelect { createdAt?: T; _status?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -268,6 +341,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -320,6 +417,16 @@ export interface MenuSelect { createdAt?: T; globalType?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/admin/payload-types.ts b/test/admin/payload-types.ts index fcee0aebe76..1503ea699a7 100644 --- a/test/admin/payload-types.ts +++ b/test/admin/payload-types.ts @@ -60,10 +60,59 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_7DB35FFD". + */ +export type LexicalNodes_7DB35FFD = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedRelationshipNode< + | 'posts' + | 'users' + | 'hidden-collection' + | 'not-in-view-collection' + | 'collection-no-api-view' + | 'custom-document-controls' + | 'custom-views-one' + | 'custom-views-two' + | 'custom-collection-view' + | 'reorder-tabs' + | 'custom-fields' + | 'group-one-collection-ones' + | 'group-one-collection-twos' + | 'group-two-collection-ones' + | 'group-two-collection-twos' + | 'geo' + | 'array' + | 'disable-duplicate' + | 'disable-copy-to-locale' + | 'edit-menu-items' + | 'format-doc-url' + | 'base-list-filters' + | 'with300documents' + | 'with-list-drawer' + | 'placeholder' + | 'use-as-title-group-field' + | 'disable-bulk-edit' + | 'custom-list-drawer' + | 'list-view-select-api' + | 'virtuals' + | 'no-timestamps' + | 'localized' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + >; export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -101,6 +150,7 @@ export interface Config { virtuals: Virtual; 'no-timestamps': NoTimestamp; localized: Localized; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -142,6 +192,7 @@ export interface Config { virtuals: VirtualsSelect | VirtualsSelect; 'no-timestamps': NoTimestampsSelect | NoTimestampsSelect; localized: LocalizedSelect | LocalizedSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -179,7 +230,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -203,6 +254,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "uploads". @@ -262,21 +331,7 @@ export interface Post { title?: string | null; description?: string | null; number?: number | null; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; someTextField?: string | null; namedGroup?: { someTextField?: string | null; @@ -444,14 +499,7 @@ export interface CustomField { id?: string | null; }[] | null; - blocksFieldWithBeforeAfterInputs?: - | { - textField?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'blockFields'; - }[] - | null; + blocksFieldWithBeforeAfterInputs?: BlockFields[] | null; text?: string | null; groupFieldWithBeforeAfterInputs?: { textOne?: string | null; @@ -461,6 +509,16 @@ export interface CustomField { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockFields". + */ +export interface BlockFields { + textField?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockFields'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "group-one-collection-ones". @@ -693,6 +751,49 @@ export interface Localized { createdAt: string; _status?: ('draft' | 'published') | null; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -852,12 +953,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'localized'; value: string | Localized; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -867,10 +977,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -1342,6 +1457,22 @@ export interface LocalizedSelect { createdAt?: T; _status?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -1604,6 +1735,76 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + declare module 'payload' { // @ts-ignore diff --git a/test/array-update/payload-types.ts b/test/array-update/payload-types.ts index 6b30bbe4413..0d36fe71eb5 100644 --- a/test/array-update/payload-types.ts +++ b/test/array-update/payload-types.ts @@ -64,12 +64,14 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { arrays: Array; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -77,8 +79,9 @@ export interface Config { collectionsJoins: {}; collectionsSelect: { arrays: ArraysSelect | ArraysSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -90,7 +93,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -114,6 +120,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "arrays". @@ -137,23 +161,6 @@ export interface Array { updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -179,6 +186,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -193,12 +260,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -208,10 +284,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -258,14 +339,6 @@ export interface ArraysSelect { updatedAt?: T; createdAt?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -288,6 +361,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -320,6 +417,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/auth-basic/payload-types.ts b/test/auth-basic/payload-types.ts index cb0d502bdc9..883393fc3c6 100644 --- a/test/auth-basic/payload-types.ts +++ b/test/auth-basic/payload-types.ts @@ -64,19 +64,22 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; }; collectionsJoins: {}; collectionsSelect: { - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -88,7 +91,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -112,22 +118,23 @@ export interface UserAuthOperations { password: string; }; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -154,21 +161,91 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". */ export interface PayloadLockedDocument { id: string; - document?: { - relationTo: 'users'; - value: string | User; - } | null; + document?: + | ({ + relationTo: 'users'; + value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -178,10 +255,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -206,14 +288,6 @@ export interface PayloadMigration { updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -236,6 +310,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -268,6 +366,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/auth/payload-types.ts b/test/auth/payload-types.ts index 39b40bc48bb..3709ea29f5b 100644 --- a/test/auth/payload-types.ts +++ b/test/auth/payload-types.ts @@ -60,6 +60,45 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_8518094C". + */ +export type LexicalNodes_8518094C = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> + | SerializedHeadingNode + | { + type: 'upload'; + /** + * Lexical's internal serialization version for this node type. + */ + version: number; + [k: string]: unknown; + } + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedRelationshipNode< + | 'users' + | 'partial-disable-local-strategies' + | 'disable-local-strategy-password' + | 'api-keys' + | 'public-users' + | 'relationsCollection' + | 'api-keys-with-field-read-access' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + >; export interface Config { auth: { @@ -69,6 +108,7 @@ export interface Config { 'api-keys': ApiKeyAuthOperations; 'public-users': PublicUserAuthOperations; 'api-keys-with-field-read-access': ApiKeysWithFieldReadAccessAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -79,6 +119,7 @@ export interface Config { 'public-users': PublicUser; relationsCollection: RelationsCollection; 'api-keys-with-field-read-access': ApiKeysWithFieldReadAccess; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -93,6 +134,7 @@ export interface Config { 'public-users': PublicUsersSelect | PublicUsersSelect; relationsCollection: RelationsCollectionSelect | RelationsCollectionSelect; 'api-keys-with-field-read-access': ApiKeysWithFieldReadAccessSelect | ApiKeysWithFieldReadAccessSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -105,13 +147,17 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; + widgets: { + collections: CollectionsWidget; + }; user: | User | PartialDisableLocalStrategy | DisableLocalStrategyPassword | ApiKey | PublicUser - | ApiKeysWithFieldReadAccess; + | ApiKeysWithFieldReadAccess + | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -225,6 +271,24 @@ export interface ApiKeysWithFieldReadAccessAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -240,21 +304,7 @@ export interface User { }[] | null; namedSaveToJWT?: string | null; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; group?: { liftedSaveToJWT?: string | null; }; @@ -395,6 +445,49 @@ export interface ApiKeysWithFieldReadAccess { apiKeyIndex?: string | null; collection: 'api-keys-with-field-read-access'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -446,6 +539,10 @@ export interface PayloadLockedDocument { | ({ relationTo: 'api-keys-with-field-read-access'; value: string | ApiKeysWithFieldReadAccess; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; user: @@ -472,6 +569,10 @@ export interface PayloadLockedDocument { | { relationTo: 'api-keys-with-field-read-access'; value: string | ApiKeysWithFieldReadAccess; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; }; updatedAt: string; createdAt: string; @@ -506,6 +607,10 @@ export interface PayloadPreference { | { relationTo: 'api-keys-with-field-read-access'; value: string | ApiKeysWithFieldReadAccess; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; }; key?: string | null; value?: @@ -679,6 +784,22 @@ export interface ApiKeysWithFieldReadAccessSelect { apiKey?: T; apiKeyIndex?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -719,6 +840,48 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock". + */ +export interface MyBlock { + id: string; + blockType: 'myBlock'; + someText?: string | null; + someTextRequired: string; + radios?: ('option1' | 'option2' | 'option3') | null; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_8518094C". + */ +export interface LexicalLinkFields_8518094C { + linkType: 'custom' | 'internal'; + url?: string; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + newTab: boolean; + description?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". @@ -727,6 +890,147 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export type SerializedBlockNode = { + type: 'block'; + format: LexicalElementFormat; + version: number; + fields: { id: string; blockName?: string | null } & Omit; +}; +export type SerializedInlineBlockNode = { + type: 'inlineBlock'; + version: number; + fields: { id: string } & Omit; +}; + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + declare module 'payload' { // @ts-ignore diff --git a/test/benchmark-blocks/payload-types.ts b/test/benchmark-blocks/payload-types.ts index 9c7f1d83441..a7e122a27f4 100644 --- a/test/benchmark-blocks/payload-types.ts +++ b/test/benchmark-blocks/payload-types.ts @@ -60,10 +60,38 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_9626C4EE". + */ +export type LexicalNodes_9626C4EE = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedHorizontalRuleNode + | SerializedUploadNode<'media'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'posts' + | 'pages' + | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: { block_0: Block_0; @@ -671,8 +699,9 @@ export interface Config { posts: Post; pages: Page; media: Media; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -682,8 +711,9 @@ export interface Config { posts: PostsSelect | PostsSelect; pages: PagesSelect | PagesSelect; media: MediaSelect | MediaSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -695,7 +725,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -719,9 +752,27 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_0". + * via the `definition` "Block_0". */ export interface Block_0 { field1?: string | null; @@ -734,7 +785,7 @@ export interface Block_0 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_1". + * via the `definition` "Block_1". */ export interface Block_1 { field1?: string | null; @@ -747,7 +798,7 @@ export interface Block_1 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_2". + * via the `definition` "Block_2". */ export interface Block_2 { field1?: string | null; @@ -760,7 +811,7 @@ export interface Block_2 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_3". + * via the `definition` "Block_3". */ export interface Block_3 { field1?: string | null; @@ -773,7 +824,7 @@ export interface Block_3 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_4". + * via the `definition` "Block_4". */ export interface Block_4 { field1?: string | null; @@ -786,7 +837,7 @@ export interface Block_4 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_5". + * via the `definition` "Block_5". */ export interface Block_5 { field1?: string | null; @@ -799,7 +850,7 @@ export interface Block_5 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_6". + * via the `definition` "Block_6". */ export interface Block_6 { field1?: string | null; @@ -812,7 +863,7 @@ export interface Block_6 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_7". + * via the `definition` "Block_7". */ export interface Block_7 { field1?: string | null; @@ -825,7 +876,7 @@ export interface Block_7 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_8". + * via the `definition` "Block_8". */ export interface Block_8 { field1?: string | null; @@ -838,7 +889,7 @@ export interface Block_8 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_9". + * via the `definition` "Block_9". */ export interface Block_9 { field1?: string | null; @@ -851,7 +902,7 @@ export interface Block_9 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_10". + * via the `definition` "Block_10". */ export interface Block_10 { field1?: string | null; @@ -864,7 +915,7 @@ export interface Block_10 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_11". + * via the `definition` "Block_11". */ export interface Block_11 { field1?: string | null; @@ -877,7 +928,7 @@ export interface Block_11 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_12". + * via the `definition` "Block_12". */ export interface Block_12 { field1?: string | null; @@ -890,7 +941,7 @@ export interface Block_12 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_13". + * via the `definition` "Block_13". */ export interface Block_13 { field1?: string | null; @@ -903,7 +954,7 @@ export interface Block_13 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_14". + * via the `definition` "Block_14". */ export interface Block_14 { field1?: string | null; @@ -916,7 +967,7 @@ export interface Block_14 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_15". + * via the `definition` "Block_15". */ export interface Block_15 { field1?: string | null; @@ -929,7 +980,7 @@ export interface Block_15 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_16". + * via the `definition` "Block_16". */ export interface Block_16 { field1?: string | null; @@ -942,7 +993,7 @@ export interface Block_16 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_17". + * via the `definition` "Block_17". */ export interface Block_17 { field1?: string | null; @@ -955,7 +1006,7 @@ export interface Block_17 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_18". + * via the `definition` "Block_18". */ export interface Block_18 { field1?: string | null; @@ -968,7 +1019,7 @@ export interface Block_18 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_19". + * via the `definition` "Block_19". */ export interface Block_19 { field1?: string | null; @@ -981,7 +1032,7 @@ export interface Block_19 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_20". + * via the `definition` "Block_20". */ export interface Block_20 { field1?: string | null; @@ -994,7 +1045,7 @@ export interface Block_20 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_21". + * via the `definition` "Block_21". */ export interface Block_21 { field1?: string | null; @@ -1007,7 +1058,7 @@ export interface Block_21 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_22". + * via the `definition` "Block_22". */ export interface Block_22 { field1?: string | null; @@ -1020,7 +1071,7 @@ export interface Block_22 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_23". + * via the `definition` "Block_23". */ export interface Block_23 { field1?: string | null; @@ -1033,7 +1084,7 @@ export interface Block_23 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_24". + * via the `definition` "Block_24". */ export interface Block_24 { field1?: string | null; @@ -1046,7 +1097,7 @@ export interface Block_24 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_25". + * via the `definition` "Block_25". */ export interface Block_25 { field1?: string | null; @@ -1059,7 +1110,7 @@ export interface Block_25 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_26". + * via the `definition` "Block_26". */ export interface Block_26 { field1?: string | null; @@ -1072,7 +1123,7 @@ export interface Block_26 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_27". + * via the `definition` "Block_27". */ export interface Block_27 { field1?: string | null; @@ -1085,7 +1136,7 @@ export interface Block_27 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_28". + * via the `definition` "Block_28". */ export interface Block_28 { field1?: string | null; @@ -1098,7 +1149,7 @@ export interface Block_28 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_29". + * via the `definition` "Block_29". */ export interface Block_29 { field1?: string | null; @@ -1111,7 +1162,7 @@ export interface Block_29 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_30". + * via the `definition` "Block_30". */ export interface Block_30 { field1?: string | null; @@ -1124,7 +1175,7 @@ export interface Block_30 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_31". + * via the `definition` "Block_31". */ export interface Block_31 { field1?: string | null; @@ -1137,7 +1188,7 @@ export interface Block_31 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_32". + * via the `definition` "Block_32". */ export interface Block_32 { field1?: string | null; @@ -1150,7 +1201,7 @@ export interface Block_32 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_33". + * via the `definition` "Block_33". */ export interface Block_33 { field1?: string | null; @@ -1163,7 +1214,7 @@ export interface Block_33 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_34". + * via the `definition` "Block_34". */ export interface Block_34 { field1?: string | null; @@ -1176,7 +1227,7 @@ export interface Block_34 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_35". + * via the `definition` "Block_35". */ export interface Block_35 { field1?: string | null; @@ -1189,7 +1240,7 @@ export interface Block_35 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_36". + * via the `definition` "Block_36". */ export interface Block_36 { field1?: string | null; @@ -1202,7 +1253,7 @@ export interface Block_36 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_37". + * via the `definition` "Block_37". */ export interface Block_37 { field1?: string | null; @@ -1215,7 +1266,7 @@ export interface Block_37 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_38". + * via the `definition` "Block_38". */ export interface Block_38 { field1?: string | null; @@ -1228,7 +1279,7 @@ export interface Block_38 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_39". + * via the `definition` "Block_39". */ export interface Block_39 { field1?: string | null; @@ -1241,7 +1292,7 @@ export interface Block_39 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_40". + * via the `definition` "Block_40". */ export interface Block_40 { field1?: string | null; @@ -1254,7 +1305,7 @@ export interface Block_40 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_41". + * via the `definition` "Block_41". */ export interface Block_41 { field1?: string | null; @@ -1267,7 +1318,7 @@ export interface Block_41 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_42". + * via the `definition` "Block_42". */ export interface Block_42 { field1?: string | null; @@ -1280,7 +1331,7 @@ export interface Block_42 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_43". + * via the `definition` "Block_43". */ export interface Block_43 { field1?: string | null; @@ -1293,7 +1344,7 @@ export interface Block_43 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_44". + * via the `definition` "Block_44". */ export interface Block_44 { field1?: string | null; @@ -1306,7 +1357,7 @@ export interface Block_44 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_45". + * via the `definition` "Block_45". */ export interface Block_45 { field1?: string | null; @@ -1319,7 +1370,7 @@ export interface Block_45 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_46". + * via the `definition` "Block_46". */ export interface Block_46 { field1?: string | null; @@ -1332,7 +1383,7 @@ export interface Block_46 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_47". + * via the `definition` "Block_47". */ export interface Block_47 { field1?: string | null; @@ -1345,7 +1396,7 @@ export interface Block_47 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_48". + * via the `definition` "Block_48". */ export interface Block_48 { field1?: string | null; @@ -1358,7 +1409,7 @@ export interface Block_48 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_49". + * via the `definition` "Block_49". */ export interface Block_49 { field1?: string | null; @@ -1371,7 +1422,7 @@ export interface Block_49 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_50". + * via the `definition` "Block_50". */ export interface Block_50 { field1?: string | null; @@ -1384,7 +1435,7 @@ export interface Block_50 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_51". + * via the `definition` "Block_51". */ export interface Block_51 { field1?: string | null; @@ -1397,7 +1448,7 @@ export interface Block_51 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_52". + * via the `definition` "Block_52". */ export interface Block_52 { field1?: string | null; @@ -1410,7 +1461,7 @@ export interface Block_52 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_53". + * via the `definition` "Block_53". */ export interface Block_53 { field1?: string | null; @@ -1423,7 +1474,7 @@ export interface Block_53 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_54". + * via the `definition` "Block_54". */ export interface Block_54 { field1?: string | null; @@ -1436,7 +1487,7 @@ export interface Block_54 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_55". + * via the `definition` "Block_55". */ export interface Block_55 { field1?: string | null; @@ -1449,7 +1500,7 @@ export interface Block_55 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_56". + * via the `definition` "Block_56". */ export interface Block_56 { field1?: string | null; @@ -1462,7 +1513,7 @@ export interface Block_56 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_57". + * via the `definition` "Block_57". */ export interface Block_57 { field1?: string | null; @@ -1475,7 +1526,7 @@ export interface Block_57 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_58". + * via the `definition` "Block_58". */ export interface Block_58 { field1?: string | null; @@ -1488,7 +1539,7 @@ export interface Block_58 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_59". + * via the `definition` "Block_59". */ export interface Block_59 { field1?: string | null; @@ -1501,7 +1552,7 @@ export interface Block_59 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_60". + * via the `definition` "Block_60". */ export interface Block_60 { field1?: string | null; @@ -1514,7 +1565,7 @@ export interface Block_60 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_61". + * via the `definition` "Block_61". */ export interface Block_61 { field1?: string | null; @@ -1527,7 +1578,7 @@ export interface Block_61 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_62". + * via the `definition` "Block_62". */ export interface Block_62 { field1?: string | null; @@ -1540,7 +1591,7 @@ export interface Block_62 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_63". + * via the `definition` "Block_63". */ export interface Block_63 { field1?: string | null; @@ -1553,7 +1604,7 @@ export interface Block_63 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_64". + * via the `definition` "Block_64". */ export interface Block_64 { field1?: string | null; @@ -1566,7 +1617,7 @@ export interface Block_64 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_65". + * via the `definition` "Block_65". */ export interface Block_65 { field1?: string | null; @@ -1579,7 +1630,7 @@ export interface Block_65 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_66". + * via the `definition` "Block_66". */ export interface Block_66 { field1?: string | null; @@ -1592,7 +1643,7 @@ export interface Block_66 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_67". + * via the `definition` "Block_67". */ export interface Block_67 { field1?: string | null; @@ -1605,7 +1656,7 @@ export interface Block_67 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_68". + * via the `definition` "Block_68". */ export interface Block_68 { field1?: string | null; @@ -1618,7 +1669,7 @@ export interface Block_68 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_69". + * via the `definition` "Block_69". */ export interface Block_69 { field1?: string | null; @@ -1631,7 +1682,7 @@ export interface Block_69 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_70". + * via the `definition` "Block_70". */ export interface Block_70 { field1?: string | null; @@ -1644,7 +1695,7 @@ export interface Block_70 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_71". + * via the `definition` "Block_71". */ export interface Block_71 { field1?: string | null; @@ -1657,7 +1708,7 @@ export interface Block_71 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_72". + * via the `definition` "Block_72". */ export interface Block_72 { field1?: string | null; @@ -1670,7 +1721,7 @@ export interface Block_72 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_73". + * via the `definition` "Block_73". */ export interface Block_73 { field1?: string | null; @@ -1683,7 +1734,7 @@ export interface Block_73 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_74". + * via the `definition` "Block_74". */ export interface Block_74 { field1?: string | null; @@ -1696,7 +1747,7 @@ export interface Block_74 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_75". + * via the `definition` "Block_75". */ export interface Block_75 { field1?: string | null; @@ -1709,7 +1760,7 @@ export interface Block_75 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_76". + * via the `definition` "Block_76". */ export interface Block_76 { field1?: string | null; @@ -1722,7 +1773,7 @@ export interface Block_76 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_77". + * via the `definition` "Block_77". */ export interface Block_77 { field1?: string | null; @@ -1735,7 +1786,7 @@ export interface Block_77 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_78". + * via the `definition` "Block_78". */ export interface Block_78 { field1?: string | null; @@ -1748,7 +1799,7 @@ export interface Block_78 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_79". + * via the `definition` "Block_79". */ export interface Block_79 { field1?: string | null; @@ -1761,7 +1812,7 @@ export interface Block_79 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_80". + * via the `definition` "Block_80". */ export interface Block_80 { field1?: string | null; @@ -1774,7 +1825,7 @@ export interface Block_80 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_81". + * via the `definition` "Block_81". */ export interface Block_81 { field1?: string | null; @@ -1787,7 +1838,7 @@ export interface Block_81 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_82". + * via the `definition` "Block_82". */ export interface Block_82 { field1?: string | null; @@ -1800,7 +1851,7 @@ export interface Block_82 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_83". + * via the `definition` "Block_83". */ export interface Block_83 { field1?: string | null; @@ -1813,7 +1864,7 @@ export interface Block_83 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_84". + * via the `definition` "Block_84". */ export interface Block_84 { field1?: string | null; @@ -1826,7 +1877,7 @@ export interface Block_84 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_85". + * via the `definition` "Block_85". */ export interface Block_85 { field1?: string | null; @@ -1839,7 +1890,7 @@ export interface Block_85 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_86". + * via the `definition` "Block_86". */ export interface Block_86 { field1?: string | null; @@ -1852,7 +1903,7 @@ export interface Block_86 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_87". + * via the `definition` "Block_87". */ export interface Block_87 { field1?: string | null; @@ -1865,7 +1916,7 @@ export interface Block_87 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_88". + * via the `definition` "Block_88". */ export interface Block_88 { field1?: string | null; @@ -1878,7 +1929,7 @@ export interface Block_88 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_89". + * via the `definition` "Block_89". */ export interface Block_89 { field1?: string | null; @@ -1891,7 +1942,7 @@ export interface Block_89 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_90". + * via the `definition` "Block_90". */ export interface Block_90 { field1?: string | null; @@ -1904,7 +1955,7 @@ export interface Block_90 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_91". + * via the `definition` "Block_91". */ export interface Block_91 { field1?: string | null; @@ -1917,7 +1968,7 @@ export interface Block_91 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_92". + * via the `definition` "Block_92". */ export interface Block_92 { field1?: string | null; @@ -1930,7 +1981,7 @@ export interface Block_92 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_93". + * via the `definition` "Block_93". */ export interface Block_93 { field1?: string | null; @@ -1943,7 +1994,7 @@ export interface Block_93 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_94". + * via the `definition` "Block_94". */ export interface Block_94 { field1?: string | null; @@ -1956,7 +2007,7 @@ export interface Block_94 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_95". + * via the `definition` "Block_95". */ export interface Block_95 { field1?: string | null; @@ -1969,7 +2020,7 @@ export interface Block_95 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_96". + * via the `definition` "Block_96". */ export interface Block_96 { field1?: string | null; @@ -1982,7 +2033,7 @@ export interface Block_96 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_97". + * via the `definition` "Block_97". */ export interface Block_97 { field1?: string | null; @@ -1995,7 +2046,7 @@ export interface Block_97 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_98". + * via the `definition` "Block_98". */ export interface Block_98 { field1?: string | null; @@ -2008,7 +2059,7 @@ export interface Block_98 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_99". + * via the `definition` "Block_99". */ export interface Block_99 { field1?: string | null; @@ -2021,7 +2072,7 @@ export interface Block_99 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_100". + * via the `definition` "Block_100". */ export interface Block_100 { field1?: string | null; @@ -2034,7 +2085,7 @@ export interface Block_100 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_101". + * via the `definition` "Block_101". */ export interface Block_101 { field1?: string | null; @@ -2047,7 +2098,7 @@ export interface Block_101 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_102". + * via the `definition` "Block_102". */ export interface Block_102 { field1?: string | null; @@ -2060,7 +2111,7 @@ export interface Block_102 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_103". + * via the `definition` "Block_103". */ export interface Block_103 { field1?: string | null; @@ -2073,7 +2124,7 @@ export interface Block_103 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_104". + * via the `definition` "Block_104". */ export interface Block_104 { field1?: string | null; @@ -2086,7 +2137,7 @@ export interface Block_104 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_105". + * via the `definition` "Block_105". */ export interface Block_105 { field1?: string | null; @@ -2099,7 +2150,7 @@ export interface Block_105 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_106". + * via the `definition` "Block_106". */ export interface Block_106 { field1?: string | null; @@ -2112,7 +2163,7 @@ export interface Block_106 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_107". + * via the `definition` "Block_107". */ export interface Block_107 { field1?: string | null; @@ -2125,7 +2176,7 @@ export interface Block_107 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_108". + * via the `definition` "Block_108". */ export interface Block_108 { field1?: string | null; @@ -2138,7 +2189,7 @@ export interface Block_108 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_109". + * via the `definition` "Block_109". */ export interface Block_109 { field1?: string | null; @@ -2151,7 +2202,7 @@ export interface Block_109 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_110". + * via the `definition` "Block_110". */ export interface Block_110 { field1?: string | null; @@ -2164,7 +2215,7 @@ export interface Block_110 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_111". + * via the `definition` "Block_111". */ export interface Block_111 { field1?: string | null; @@ -2177,7 +2228,7 @@ export interface Block_111 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_112". + * via the `definition` "Block_112". */ export interface Block_112 { field1?: string | null; @@ -2190,7 +2241,7 @@ export interface Block_112 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_113". + * via the `definition` "Block_113". */ export interface Block_113 { field1?: string | null; @@ -2203,7 +2254,7 @@ export interface Block_113 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_114". + * via the `definition` "Block_114". */ export interface Block_114 { field1?: string | null; @@ -2216,7 +2267,7 @@ export interface Block_114 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_115". + * via the `definition` "Block_115". */ export interface Block_115 { field1?: string | null; @@ -2229,7 +2280,7 @@ export interface Block_115 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_116". + * via the `definition` "Block_116". */ export interface Block_116 { field1?: string | null; @@ -2242,7 +2293,7 @@ export interface Block_116 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_117". + * via the `definition` "Block_117". */ export interface Block_117 { field1?: string | null; @@ -2255,7 +2306,7 @@ export interface Block_117 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_118". + * via the `definition` "Block_118". */ export interface Block_118 { field1?: string | null; @@ -2268,7 +2319,7 @@ export interface Block_118 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_119". + * via the `definition` "Block_119". */ export interface Block_119 { field1?: string | null; @@ -2281,7 +2332,7 @@ export interface Block_119 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_120". + * via the `definition` "Block_120". */ export interface Block_120 { field1?: string | null; @@ -2294,7 +2345,7 @@ export interface Block_120 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_121". + * via the `definition` "Block_121". */ export interface Block_121 { field1?: string | null; @@ -2307,7 +2358,7 @@ export interface Block_121 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_122". + * via the `definition` "Block_122". */ export interface Block_122 { field1?: string | null; @@ -2320,7 +2371,7 @@ export interface Block_122 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_123". + * via the `definition` "Block_123". */ export interface Block_123 { field1?: string | null; @@ -2333,7 +2384,7 @@ export interface Block_123 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_124". + * via the `definition` "Block_124". */ export interface Block_124 { field1?: string | null; @@ -2346,7 +2397,7 @@ export interface Block_124 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_125". + * via the `definition` "Block_125". */ export interface Block_125 { field1?: string | null; @@ -2359,7 +2410,7 @@ export interface Block_125 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_126". + * via the `definition` "Block_126". */ export interface Block_126 { field1?: string | null; @@ -2372,7 +2423,7 @@ export interface Block_126 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_127". + * via the `definition` "Block_127". */ export interface Block_127 { field1?: string | null; @@ -2385,7 +2436,7 @@ export interface Block_127 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_128". + * via the `definition` "Block_128". */ export interface Block_128 { field1?: string | null; @@ -2398,7 +2449,7 @@ export interface Block_128 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_129". + * via the `definition` "Block_129". */ export interface Block_129 { field1?: string | null; @@ -2411,7 +2462,7 @@ export interface Block_129 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_130". + * via the `definition` "Block_130". */ export interface Block_130 { field1?: string | null; @@ -2424,7 +2475,7 @@ export interface Block_130 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_131". + * via the `definition` "Block_131". */ export interface Block_131 { field1?: string | null; @@ -2437,7 +2488,7 @@ export interface Block_131 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_132". + * via the `definition` "Block_132". */ export interface Block_132 { field1?: string | null; @@ -2450,7 +2501,7 @@ export interface Block_132 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_133". + * via the `definition` "Block_133". */ export interface Block_133 { field1?: string | null; @@ -2463,7 +2514,7 @@ export interface Block_133 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_134". + * via the `definition` "Block_134". */ export interface Block_134 { field1?: string | null; @@ -2476,7 +2527,7 @@ export interface Block_134 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_135". + * via the `definition` "Block_135". */ export interface Block_135 { field1?: string | null; @@ -2489,7 +2540,7 @@ export interface Block_135 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_136". + * via the `definition` "Block_136". */ export interface Block_136 { field1?: string | null; @@ -2502,7 +2553,7 @@ export interface Block_136 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_137". + * via the `definition` "Block_137". */ export interface Block_137 { field1?: string | null; @@ -2515,7 +2566,7 @@ export interface Block_137 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_138". + * via the `definition` "Block_138". */ export interface Block_138 { field1?: string | null; @@ -2528,7 +2579,7 @@ export interface Block_138 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_139". + * via the `definition` "Block_139". */ export interface Block_139 { field1?: string | null; @@ -2541,7 +2592,7 @@ export interface Block_139 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_140". + * via the `definition` "Block_140". */ export interface Block_140 { field1?: string | null; @@ -2554,7 +2605,7 @@ export interface Block_140 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_141". + * via the `definition` "Block_141". */ export interface Block_141 { field1?: string | null; @@ -2567,7 +2618,7 @@ export interface Block_141 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_142". + * via the `definition` "Block_142". */ export interface Block_142 { field1?: string | null; @@ -2580,7 +2631,7 @@ export interface Block_142 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_143". + * via the `definition` "Block_143". */ export interface Block_143 { field1?: string | null; @@ -2593,7 +2644,7 @@ export interface Block_143 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_144". + * via the `definition` "Block_144". */ export interface Block_144 { field1?: string | null; @@ -2606,7 +2657,7 @@ export interface Block_144 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_145". + * via the `definition` "Block_145". */ export interface Block_145 { field1?: string | null; @@ -2619,7 +2670,7 @@ export interface Block_145 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_146". + * via the `definition` "Block_146". */ export interface Block_146 { field1?: string | null; @@ -2632,7 +2683,7 @@ export interface Block_146 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_147". + * via the `definition` "Block_147". */ export interface Block_147 { field1?: string | null; @@ -2645,7 +2696,7 @@ export interface Block_147 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_148". + * via the `definition` "Block_148". */ export interface Block_148 { field1?: string | null; @@ -2658,7 +2709,7 @@ export interface Block_148 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_149". + * via the `definition` "Block_149". */ export interface Block_149 { field1?: string | null; @@ -2671,7 +2722,7 @@ export interface Block_149 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_150". + * via the `definition` "Block_150". */ export interface Block_150 { field1?: string | null; @@ -2684,7 +2735,7 @@ export interface Block_150 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_151". + * via the `definition` "Block_151". */ export interface Block_151 { field1?: string | null; @@ -2697,7 +2748,7 @@ export interface Block_151 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_152". + * via the `definition` "Block_152". */ export interface Block_152 { field1?: string | null; @@ -2710,7 +2761,7 @@ export interface Block_152 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_153". + * via the `definition` "Block_153". */ export interface Block_153 { field1?: string | null; @@ -2723,7 +2774,7 @@ export interface Block_153 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_154". + * via the `definition` "Block_154". */ export interface Block_154 { field1?: string | null; @@ -2736,7 +2787,7 @@ export interface Block_154 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_155". + * via the `definition` "Block_155". */ export interface Block_155 { field1?: string | null; @@ -2749,7 +2800,7 @@ export interface Block_155 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_156". + * via the `definition` "Block_156". */ export interface Block_156 { field1?: string | null; @@ -2762,7 +2813,7 @@ export interface Block_156 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_157". + * via the `definition` "Block_157". */ export interface Block_157 { field1?: string | null; @@ -2775,7 +2826,7 @@ export interface Block_157 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_158". + * via the `definition` "Block_158". */ export interface Block_158 { field1?: string | null; @@ -2788,7 +2839,7 @@ export interface Block_158 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_159". + * via the `definition` "Block_159". */ export interface Block_159 { field1?: string | null; @@ -2801,7 +2852,7 @@ export interface Block_159 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_160". + * via the `definition` "Block_160". */ export interface Block_160 { field1?: string | null; @@ -2814,7 +2865,7 @@ export interface Block_160 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_161". + * via the `definition` "Block_161". */ export interface Block_161 { field1?: string | null; @@ -2827,7 +2878,7 @@ export interface Block_161 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_162". + * via the `definition` "Block_162". */ export interface Block_162 { field1?: string | null; @@ -2840,7 +2891,7 @@ export interface Block_162 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_163". + * via the `definition` "Block_163". */ export interface Block_163 { field1?: string | null; @@ -2853,7 +2904,7 @@ export interface Block_163 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_164". + * via the `definition` "Block_164". */ export interface Block_164 { field1?: string | null; @@ -2866,7 +2917,7 @@ export interface Block_164 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_165". + * via the `definition` "Block_165". */ export interface Block_165 { field1?: string | null; @@ -2879,7 +2930,7 @@ export interface Block_165 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_166". + * via the `definition` "Block_166". */ export interface Block_166 { field1?: string | null; @@ -2892,7 +2943,7 @@ export interface Block_166 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_167". + * via the `definition` "Block_167". */ export interface Block_167 { field1?: string | null; @@ -2905,7 +2956,7 @@ export interface Block_167 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_168". + * via the `definition` "Block_168". */ export interface Block_168 { field1?: string | null; @@ -2918,7 +2969,7 @@ export interface Block_168 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_169". + * via the `definition` "Block_169". */ export interface Block_169 { field1?: string | null; @@ -2931,7 +2982,7 @@ export interface Block_169 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_170". + * via the `definition` "Block_170". */ export interface Block_170 { field1?: string | null; @@ -2944,7 +2995,7 @@ export interface Block_170 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_171". + * via the `definition` "Block_171". */ export interface Block_171 { field1?: string | null; @@ -2957,7 +3008,7 @@ export interface Block_171 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_172". + * via the `definition` "Block_172". */ export interface Block_172 { field1?: string | null; @@ -2970,7 +3021,7 @@ export interface Block_172 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_173". + * via the `definition` "Block_173". */ export interface Block_173 { field1?: string | null; @@ -2983,7 +3034,7 @@ export interface Block_173 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_174". + * via the `definition` "Block_174". */ export interface Block_174 { field1?: string | null; @@ -2996,7 +3047,7 @@ export interface Block_174 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_175". + * via the `definition` "Block_175". */ export interface Block_175 { field1?: string | null; @@ -3009,7 +3060,7 @@ export interface Block_175 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_176". + * via the `definition` "Block_176". */ export interface Block_176 { field1?: string | null; @@ -3022,7 +3073,7 @@ export interface Block_176 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_177". + * via the `definition` "Block_177". */ export interface Block_177 { field1?: string | null; @@ -3035,7 +3086,7 @@ export interface Block_177 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_178". + * via the `definition` "Block_178". */ export interface Block_178 { field1?: string | null; @@ -3048,7 +3099,7 @@ export interface Block_178 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_179". + * via the `definition` "Block_179". */ export interface Block_179 { field1?: string | null; @@ -3061,7 +3112,7 @@ export interface Block_179 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_180". + * via the `definition` "Block_180". */ export interface Block_180 { field1?: string | null; @@ -3074,7 +3125,7 @@ export interface Block_180 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_181". + * via the `definition` "Block_181". */ export interface Block_181 { field1?: string | null; @@ -3087,7 +3138,7 @@ export interface Block_181 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_182". + * via the `definition` "Block_182". */ export interface Block_182 { field1?: string | null; @@ -3100,7 +3151,7 @@ export interface Block_182 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_183". + * via the `definition` "Block_183". */ export interface Block_183 { field1?: string | null; @@ -3113,7 +3164,7 @@ export interface Block_183 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_184". + * via the `definition` "Block_184". */ export interface Block_184 { field1?: string | null; @@ -3126,7 +3177,7 @@ export interface Block_184 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_185". + * via the `definition` "Block_185". */ export interface Block_185 { field1?: string | null; @@ -3139,7 +3190,7 @@ export interface Block_185 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_186". + * via the `definition` "Block_186". */ export interface Block_186 { field1?: string | null; @@ -3152,7 +3203,7 @@ export interface Block_186 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_187". + * via the `definition` "Block_187". */ export interface Block_187 { field1?: string | null; @@ -3165,7 +3216,7 @@ export interface Block_187 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_188". + * via the `definition` "Block_188". */ export interface Block_188 { field1?: string | null; @@ -3178,7 +3229,7 @@ export interface Block_188 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_189". + * via the `definition` "Block_189". */ export interface Block_189 { field1?: string | null; @@ -3191,7 +3242,7 @@ export interface Block_189 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_190". + * via the `definition` "Block_190". */ export interface Block_190 { field1?: string | null; @@ -3204,7 +3255,7 @@ export interface Block_190 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_191". + * via the `definition` "Block_191". */ export interface Block_191 { field1?: string | null; @@ -3217,7 +3268,7 @@ export interface Block_191 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_192". + * via the `definition` "Block_192". */ export interface Block_192 { field1?: string | null; @@ -3230,7 +3281,7 @@ export interface Block_192 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_193". + * via the `definition` "Block_193". */ export interface Block_193 { field1?: string | null; @@ -3243,7 +3294,7 @@ export interface Block_193 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_194". + * via the `definition` "Block_194". */ export interface Block_194 { field1?: string | null; @@ -3256,7 +3307,7 @@ export interface Block_194 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_195". + * via the `definition` "Block_195". */ export interface Block_195 { field1?: string | null; @@ -3269,7 +3320,7 @@ export interface Block_195 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_196". + * via the `definition` "Block_196". */ export interface Block_196 { field1?: string | null; @@ -3282,7 +3333,7 @@ export interface Block_196 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_197". + * via the `definition` "Block_197". */ export interface Block_197 { field1?: string | null; @@ -3295,7 +3346,7 @@ export interface Block_197 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_198". + * via the `definition` "Block_198". */ export interface Block_198 { field1?: string | null; @@ -3308,7 +3359,7 @@ export interface Block_198 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_199". + * via the `definition` "Block_199". */ export interface Block_199 { field1?: string | null; @@ -3321,7 +3372,7 @@ export interface Block_199 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_200". + * via the `definition` "Block_200". */ export interface Block_200 { field1?: string | null; @@ -3334,7 +3385,7 @@ export interface Block_200 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_201". + * via the `definition` "Block_201". */ export interface Block_201 { field1?: string | null; @@ -3347,7 +3398,7 @@ export interface Block_201 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_202". + * via the `definition` "Block_202". */ export interface Block_202 { field1?: string | null; @@ -3360,7 +3411,7 @@ export interface Block_202 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_203". + * via the `definition` "Block_203". */ export interface Block_203 { field1?: string | null; @@ -3373,7 +3424,7 @@ export interface Block_203 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_204". + * via the `definition` "Block_204". */ export interface Block_204 { field1?: string | null; @@ -3386,7 +3437,7 @@ export interface Block_204 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_205". + * via the `definition` "Block_205". */ export interface Block_205 { field1?: string | null; @@ -3399,7 +3450,7 @@ export interface Block_205 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_206". + * via the `definition` "Block_206". */ export interface Block_206 { field1?: string | null; @@ -3412,7 +3463,7 @@ export interface Block_206 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_207". + * via the `definition` "Block_207". */ export interface Block_207 { field1?: string | null; @@ -3425,7 +3476,7 @@ export interface Block_207 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_208". + * via the `definition` "Block_208". */ export interface Block_208 { field1?: string | null; @@ -3438,7 +3489,7 @@ export interface Block_208 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_209". + * via the `definition` "Block_209". */ export interface Block_209 { field1?: string | null; @@ -3451,7 +3502,7 @@ export interface Block_209 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_210". + * via the `definition` "Block_210". */ export interface Block_210 { field1?: string | null; @@ -3464,7 +3515,7 @@ export interface Block_210 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_211". + * via the `definition` "Block_211". */ export interface Block_211 { field1?: string | null; @@ -3477,7 +3528,7 @@ export interface Block_211 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_212". + * via the `definition` "Block_212". */ export interface Block_212 { field1?: string | null; @@ -3490,7 +3541,7 @@ export interface Block_212 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_213". + * via the `definition` "Block_213". */ export interface Block_213 { field1?: string | null; @@ -3503,7 +3554,7 @@ export interface Block_213 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_214". + * via the `definition` "Block_214". */ export interface Block_214 { field1?: string | null; @@ -3516,7 +3567,7 @@ export interface Block_214 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_215". + * via the `definition` "Block_215". */ export interface Block_215 { field1?: string | null; @@ -3529,7 +3580,7 @@ export interface Block_215 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_216". + * via the `definition` "Block_216". */ export interface Block_216 { field1?: string | null; @@ -3542,7 +3593,7 @@ export interface Block_216 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_217". + * via the `definition` "Block_217". */ export interface Block_217 { field1?: string | null; @@ -3555,7 +3606,7 @@ export interface Block_217 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_218". + * via the `definition` "Block_218". */ export interface Block_218 { field1?: string | null; @@ -3568,7 +3619,7 @@ export interface Block_218 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_219". + * via the `definition` "Block_219". */ export interface Block_219 { field1?: string | null; @@ -3581,7 +3632,7 @@ export interface Block_219 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_220". + * via the `definition` "Block_220". */ export interface Block_220 { field1?: string | null; @@ -3594,7 +3645,7 @@ export interface Block_220 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_221". + * via the `definition` "Block_221". */ export interface Block_221 { field1?: string | null; @@ -3607,7 +3658,7 @@ export interface Block_221 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_222". + * via the `definition` "Block_222". */ export interface Block_222 { field1?: string | null; @@ -3620,7 +3671,7 @@ export interface Block_222 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_223". + * via the `definition` "Block_223". */ export interface Block_223 { field1?: string | null; @@ -3633,7 +3684,7 @@ export interface Block_223 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_224". + * via the `definition` "Block_224". */ export interface Block_224 { field1?: string | null; @@ -3646,7 +3697,7 @@ export interface Block_224 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_225". + * via the `definition` "Block_225". */ export interface Block_225 { field1?: string | null; @@ -3659,7 +3710,7 @@ export interface Block_225 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_226". + * via the `definition` "Block_226". */ export interface Block_226 { field1?: string | null; @@ -3672,7 +3723,7 @@ export interface Block_226 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_227". + * via the `definition` "Block_227". */ export interface Block_227 { field1?: string | null; @@ -3685,7 +3736,7 @@ export interface Block_227 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_228". + * via the `definition` "Block_228". */ export interface Block_228 { field1?: string | null; @@ -3698,7 +3749,7 @@ export interface Block_228 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_229". + * via the `definition` "Block_229". */ export interface Block_229 { field1?: string | null; @@ -3711,7 +3762,7 @@ export interface Block_229 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_230". + * via the `definition` "Block_230". */ export interface Block_230 { field1?: string | null; @@ -3724,7 +3775,7 @@ export interface Block_230 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_231". + * via the `definition` "Block_231". */ export interface Block_231 { field1?: string | null; @@ -3737,7 +3788,7 @@ export interface Block_231 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_232". + * via the `definition` "Block_232". */ export interface Block_232 { field1?: string | null; @@ -3750,7 +3801,7 @@ export interface Block_232 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_233". + * via the `definition` "Block_233". */ export interface Block_233 { field1?: string | null; @@ -3763,7 +3814,7 @@ export interface Block_233 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_234". + * via the `definition` "Block_234". */ export interface Block_234 { field1?: string | null; @@ -3776,7 +3827,7 @@ export interface Block_234 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_235". + * via the `definition` "Block_235". */ export interface Block_235 { field1?: string | null; @@ -3789,7 +3840,7 @@ export interface Block_235 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_236". + * via the `definition` "Block_236". */ export interface Block_236 { field1?: string | null; @@ -3802,7 +3853,7 @@ export interface Block_236 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_237". + * via the `definition` "Block_237". */ export interface Block_237 { field1?: string | null; @@ -3815,7 +3866,7 @@ export interface Block_237 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_238". + * via the `definition` "Block_238". */ export interface Block_238 { field1?: string | null; @@ -3828,7 +3879,7 @@ export interface Block_238 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_239". + * via the `definition` "Block_239". */ export interface Block_239 { field1?: string | null; @@ -3841,7 +3892,7 @@ export interface Block_239 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_240". + * via the `definition` "Block_240". */ export interface Block_240 { field1?: string | null; @@ -3854,7 +3905,7 @@ export interface Block_240 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_241". + * via the `definition` "Block_241". */ export interface Block_241 { field1?: string | null; @@ -3867,7 +3918,7 @@ export interface Block_241 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_242". + * via the `definition` "Block_242". */ export interface Block_242 { field1?: string | null; @@ -3880,7 +3931,7 @@ export interface Block_242 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_243". + * via the `definition` "Block_243". */ export interface Block_243 { field1?: string | null; @@ -3893,7 +3944,7 @@ export interface Block_243 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_244". + * via the `definition` "Block_244". */ export interface Block_244 { field1?: string | null; @@ -3906,7 +3957,7 @@ export interface Block_244 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_245". + * via the `definition` "Block_245". */ export interface Block_245 { field1?: string | null; @@ -3919,7 +3970,7 @@ export interface Block_245 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_246". + * via the `definition` "Block_246". */ export interface Block_246 { field1?: string | null; @@ -3932,7 +3983,7 @@ export interface Block_246 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_247". + * via the `definition` "Block_247". */ export interface Block_247 { field1?: string | null; @@ -3945,7 +3996,7 @@ export interface Block_247 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_248". + * via the `definition` "Block_248". */ export interface Block_248 { field1?: string | null; @@ -3958,7 +4009,7 @@ export interface Block_248 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_249". + * via the `definition` "Block_249". */ export interface Block_249 { field1?: string | null; @@ -3971,7 +4022,7 @@ export interface Block_249 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_250". + * via the `definition` "Block_250". */ export interface Block_250 { field1?: string | null; @@ -3984,7 +4035,7 @@ export interface Block_250 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_251". + * via the `definition` "Block_251". */ export interface Block_251 { field1?: string | null; @@ -3997,7 +4048,7 @@ export interface Block_251 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_252". + * via the `definition` "Block_252". */ export interface Block_252 { field1?: string | null; @@ -4010,7 +4061,7 @@ export interface Block_252 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_253". + * via the `definition` "Block_253". */ export interface Block_253 { field1?: string | null; @@ -4023,7 +4074,7 @@ export interface Block_253 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_254". + * via the `definition` "Block_254". */ export interface Block_254 { field1?: string | null; @@ -4036,7 +4087,7 @@ export interface Block_254 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_255". + * via the `definition` "Block_255". */ export interface Block_255 { field1?: string | null; @@ -4049,7 +4100,7 @@ export interface Block_255 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_256". + * via the `definition` "Block_256". */ export interface Block_256 { field1?: string | null; @@ -4062,7 +4113,7 @@ export interface Block_256 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_257". + * via the `definition` "Block_257". */ export interface Block_257 { field1?: string | null; @@ -4075,7 +4126,7 @@ export interface Block_257 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_258". + * via the `definition` "Block_258". */ export interface Block_258 { field1?: string | null; @@ -4088,7 +4139,7 @@ export interface Block_258 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_259". + * via the `definition` "Block_259". */ export interface Block_259 { field1?: string | null; @@ -4101,7 +4152,7 @@ export interface Block_259 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_260". + * via the `definition` "Block_260". */ export interface Block_260 { field1?: string | null; @@ -4114,7 +4165,7 @@ export interface Block_260 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_261". + * via the `definition` "Block_261". */ export interface Block_261 { field1?: string | null; @@ -4127,7 +4178,7 @@ export interface Block_261 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_262". + * via the `definition` "Block_262". */ export interface Block_262 { field1?: string | null; @@ -4140,7 +4191,7 @@ export interface Block_262 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_263". + * via the `definition` "Block_263". */ export interface Block_263 { field1?: string | null; @@ -4153,7 +4204,7 @@ export interface Block_263 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_264". + * via the `definition` "Block_264". */ export interface Block_264 { field1?: string | null; @@ -4166,7 +4217,7 @@ export interface Block_264 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_265". + * via the `definition` "Block_265". */ export interface Block_265 { field1?: string | null; @@ -4179,7 +4230,7 @@ export interface Block_265 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_266". + * via the `definition` "Block_266". */ export interface Block_266 { field1?: string | null; @@ -4192,7 +4243,7 @@ export interface Block_266 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_267". + * via the `definition` "Block_267". */ export interface Block_267 { field1?: string | null; @@ -4205,7 +4256,7 @@ export interface Block_267 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_268". + * via the `definition` "Block_268". */ export interface Block_268 { field1?: string | null; @@ -4218,7 +4269,7 @@ export interface Block_268 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_269". + * via the `definition` "Block_269". */ export interface Block_269 { field1?: string | null; @@ -4231,7 +4282,7 @@ export interface Block_269 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_270". + * via the `definition` "Block_270". */ export interface Block_270 { field1?: string | null; @@ -4244,7 +4295,7 @@ export interface Block_270 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_271". + * via the `definition` "Block_271". */ export interface Block_271 { field1?: string | null; @@ -4257,7 +4308,7 @@ export interface Block_271 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_272". + * via the `definition` "Block_272". */ export interface Block_272 { field1?: string | null; @@ -4270,7 +4321,7 @@ export interface Block_272 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_273". + * via the `definition` "Block_273". */ export interface Block_273 { field1?: string | null; @@ -4283,7 +4334,7 @@ export interface Block_273 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_274". + * via the `definition` "Block_274". */ export interface Block_274 { field1?: string | null; @@ -4296,7 +4347,7 @@ export interface Block_274 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_275". + * via the `definition` "Block_275". */ export interface Block_275 { field1?: string | null; @@ -4309,7 +4360,7 @@ export interface Block_275 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_276". + * via the `definition` "Block_276". */ export interface Block_276 { field1?: string | null; @@ -4322,7 +4373,7 @@ export interface Block_276 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_277". + * via the `definition` "Block_277". */ export interface Block_277 { field1?: string | null; @@ -4335,7 +4386,7 @@ export interface Block_277 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_278". + * via the `definition` "Block_278". */ export interface Block_278 { field1?: string | null; @@ -4348,7 +4399,7 @@ export interface Block_278 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_279". + * via the `definition` "Block_279". */ export interface Block_279 { field1?: string | null; @@ -4361,7 +4412,7 @@ export interface Block_279 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_280". + * via the `definition` "Block_280". */ export interface Block_280 { field1?: string | null; @@ -4374,7 +4425,7 @@ export interface Block_280 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_281". + * via the `definition` "Block_281". */ export interface Block_281 { field1?: string | null; @@ -4387,7 +4438,7 @@ export interface Block_281 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_282". + * via the `definition` "Block_282". */ export interface Block_282 { field1?: string | null; @@ -4400,7 +4451,7 @@ export interface Block_282 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_283". + * via the `definition` "Block_283". */ export interface Block_283 { field1?: string | null; @@ -4413,7 +4464,7 @@ export interface Block_283 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_284". + * via the `definition` "Block_284". */ export interface Block_284 { field1?: string | null; @@ -4426,7 +4477,7 @@ export interface Block_284 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_285". + * via the `definition` "Block_285". */ export interface Block_285 { field1?: string | null; @@ -4439,7 +4490,7 @@ export interface Block_285 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_286". + * via the `definition` "Block_286". */ export interface Block_286 { field1?: string | null; @@ -4452,7 +4503,7 @@ export interface Block_286 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_287". + * via the `definition` "Block_287". */ export interface Block_287 { field1?: string | null; @@ -4465,7 +4516,7 @@ export interface Block_287 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_288". + * via the `definition` "Block_288". */ export interface Block_288 { field1?: string | null; @@ -4478,7 +4529,7 @@ export interface Block_288 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_289". + * via the `definition` "Block_289". */ export interface Block_289 { field1?: string | null; @@ -4491,7 +4542,7 @@ export interface Block_289 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_290". + * via the `definition` "Block_290". */ export interface Block_290 { field1?: string | null; @@ -4504,7 +4555,7 @@ export interface Block_290 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_291". + * via the `definition` "Block_291". */ export interface Block_291 { field1?: string | null; @@ -4517,7 +4568,7 @@ export interface Block_291 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_292". + * via the `definition` "Block_292". */ export interface Block_292 { field1?: string | null; @@ -4530,7 +4581,7 @@ export interface Block_292 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_293". + * via the `definition` "Block_293". */ export interface Block_293 { field1?: string | null; @@ -4543,7 +4594,7 @@ export interface Block_293 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_294". + * via the `definition` "Block_294". */ export interface Block_294 { field1?: string | null; @@ -4556,7 +4607,7 @@ export interface Block_294 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_295". + * via the `definition` "Block_295". */ export interface Block_295 { field1?: string | null; @@ -4569,7 +4620,7 @@ export interface Block_295 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_296". + * via the `definition` "Block_296". */ export interface Block_296 { field1?: string | null; @@ -4582,7 +4633,7 @@ export interface Block_296 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_297". + * via the `definition` "Block_297". */ export interface Block_297 { field1?: string | null; @@ -4595,7 +4646,7 @@ export interface Block_297 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_298". + * via the `definition` "Block_298". */ export interface Block_298 { field1?: string | null; @@ -4608,7 +4659,7 @@ export interface Block_298 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_299". + * via the `definition` "Block_299". */ export interface Block_299 { field1?: string | null; @@ -4621,7 +4672,7 @@ export interface Block_299 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_300". + * via the `definition` "Block_300". */ export interface Block_300 { field1?: string | null; @@ -4634,7 +4685,7 @@ export interface Block_300 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_301". + * via the `definition` "Block_301". */ export interface Block_301 { field1?: string | null; @@ -4647,7 +4698,7 @@ export interface Block_301 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_302". + * via the `definition` "Block_302". */ export interface Block_302 { field1?: string | null; @@ -4660,7 +4711,7 @@ export interface Block_302 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_303". + * via the `definition` "Block_303". */ export interface Block_303 { field1?: string | null; @@ -4673,7 +4724,7 @@ export interface Block_303 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_304". + * via the `definition` "Block_304". */ export interface Block_304 { field1?: string | null; @@ -4686,7 +4737,7 @@ export interface Block_304 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_305". + * via the `definition` "Block_305". */ export interface Block_305 { field1?: string | null; @@ -4699,7 +4750,7 @@ export interface Block_305 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_306". + * via the `definition` "Block_306". */ export interface Block_306 { field1?: string | null; @@ -4712,7 +4763,7 @@ export interface Block_306 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_307". + * via the `definition` "Block_307". */ export interface Block_307 { field1?: string | null; @@ -4725,7 +4776,7 @@ export interface Block_307 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_308". + * via the `definition` "Block_308". */ export interface Block_308 { field1?: string | null; @@ -4738,7 +4789,7 @@ export interface Block_308 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_309". + * via the `definition` "Block_309". */ export interface Block_309 { field1?: string | null; @@ -4751,7 +4802,7 @@ export interface Block_309 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_310". + * via the `definition` "Block_310". */ export interface Block_310 { field1?: string | null; @@ -4764,7 +4815,7 @@ export interface Block_310 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_311". + * via the `definition` "Block_311". */ export interface Block_311 { field1?: string | null; @@ -4777,7 +4828,7 @@ export interface Block_311 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_312". + * via the `definition` "Block_312". */ export interface Block_312 { field1?: string | null; @@ -4790,7 +4841,7 @@ export interface Block_312 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_313". + * via the `definition` "Block_313". */ export interface Block_313 { field1?: string | null; @@ -4803,7 +4854,7 @@ export interface Block_313 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_314". + * via the `definition` "Block_314". */ export interface Block_314 { field1?: string | null; @@ -4816,7 +4867,7 @@ export interface Block_314 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_315". + * via the `definition` "Block_315". */ export interface Block_315 { field1?: string | null; @@ -4829,7 +4880,7 @@ export interface Block_315 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_316". + * via the `definition` "Block_316". */ export interface Block_316 { field1?: string | null; @@ -4842,7 +4893,7 @@ export interface Block_316 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_317". + * via the `definition` "Block_317". */ export interface Block_317 { field1?: string | null; @@ -4855,7 +4906,7 @@ export interface Block_317 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_318". + * via the `definition` "Block_318". */ export interface Block_318 { field1?: string | null; @@ -4868,7 +4919,7 @@ export interface Block_318 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_319". + * via the `definition` "Block_319". */ export interface Block_319 { field1?: string | null; @@ -4881,7 +4932,7 @@ export interface Block_319 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_320". + * via the `definition` "Block_320". */ export interface Block_320 { field1?: string | null; @@ -4894,7 +4945,7 @@ export interface Block_320 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_321". + * via the `definition` "Block_321". */ export interface Block_321 { field1?: string | null; @@ -4907,7 +4958,7 @@ export interface Block_321 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_322". + * via the `definition` "Block_322". */ export interface Block_322 { field1?: string | null; @@ -4920,7 +4971,7 @@ export interface Block_322 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_323". + * via the `definition` "Block_323". */ export interface Block_323 { field1?: string | null; @@ -4933,7 +4984,7 @@ export interface Block_323 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_324". + * via the `definition` "Block_324". */ export interface Block_324 { field1?: string | null; @@ -4946,7 +4997,7 @@ export interface Block_324 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_325". + * via the `definition` "Block_325". */ export interface Block_325 { field1?: string | null; @@ -4959,7 +5010,7 @@ export interface Block_325 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_326". + * via the `definition` "Block_326". */ export interface Block_326 { field1?: string | null; @@ -4972,7 +5023,7 @@ export interface Block_326 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_327". + * via the `definition` "Block_327". */ export interface Block_327 { field1?: string | null; @@ -4985,7 +5036,7 @@ export interface Block_327 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_328". + * via the `definition` "Block_328". */ export interface Block_328 { field1?: string | null; @@ -4998,7 +5049,7 @@ export interface Block_328 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_329". + * via the `definition` "Block_329". */ export interface Block_329 { field1?: string | null; @@ -5011,7 +5062,7 @@ export interface Block_329 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_330". + * via the `definition` "Block_330". */ export interface Block_330 { field1?: string | null; @@ -5024,7 +5075,7 @@ export interface Block_330 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_331". + * via the `definition` "Block_331". */ export interface Block_331 { field1?: string | null; @@ -5037,7 +5088,7 @@ export interface Block_331 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_332". + * via the `definition` "Block_332". */ export interface Block_332 { field1?: string | null; @@ -5050,7 +5101,7 @@ export interface Block_332 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_333". + * via the `definition` "Block_333". */ export interface Block_333 { field1?: string | null; @@ -5063,7 +5114,7 @@ export interface Block_333 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_334". + * via the `definition` "Block_334". */ export interface Block_334 { field1?: string | null; @@ -5076,7 +5127,7 @@ export interface Block_334 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_335". + * via the `definition` "Block_335". */ export interface Block_335 { field1?: string | null; @@ -5089,7 +5140,7 @@ export interface Block_335 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_336". + * via the `definition` "Block_336". */ export interface Block_336 { field1?: string | null; @@ -5102,7 +5153,7 @@ export interface Block_336 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_337". + * via the `definition` "Block_337". */ export interface Block_337 { field1?: string | null; @@ -5115,7 +5166,7 @@ export interface Block_337 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_338". + * via the `definition` "Block_338". */ export interface Block_338 { field1?: string | null; @@ -5128,7 +5179,7 @@ export interface Block_338 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_339". + * via the `definition` "Block_339". */ export interface Block_339 { field1?: string | null; @@ -5141,7 +5192,7 @@ export interface Block_339 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_340". + * via the `definition` "Block_340". */ export interface Block_340 { field1?: string | null; @@ -5154,7 +5205,7 @@ export interface Block_340 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_341". + * via the `definition` "Block_341". */ export interface Block_341 { field1?: string | null; @@ -5167,7 +5218,7 @@ export interface Block_341 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_342". + * via the `definition` "Block_342". */ export interface Block_342 { field1?: string | null; @@ -5180,7 +5231,7 @@ export interface Block_342 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_343". + * via the `definition` "Block_343". */ export interface Block_343 { field1?: string | null; @@ -5193,7 +5244,7 @@ export interface Block_343 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_344". + * via the `definition` "Block_344". */ export interface Block_344 { field1?: string | null; @@ -5206,7 +5257,7 @@ export interface Block_344 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_345". + * via the `definition` "Block_345". */ export interface Block_345 { field1?: string | null; @@ -5219,7 +5270,7 @@ export interface Block_345 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_346". + * via the `definition` "Block_346". */ export interface Block_346 { field1?: string | null; @@ -5232,7 +5283,7 @@ export interface Block_346 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_347". + * via the `definition` "Block_347". */ export interface Block_347 { field1?: string | null; @@ -5245,7 +5296,7 @@ export interface Block_347 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_348". + * via the `definition` "Block_348". */ export interface Block_348 { field1?: string | null; @@ -5258,7 +5309,7 @@ export interface Block_348 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_349". + * via the `definition` "Block_349". */ export interface Block_349 { field1?: string | null; @@ -5271,7 +5322,7 @@ export interface Block_349 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_350". + * via the `definition` "Block_350". */ export interface Block_350 { field1?: string | null; @@ -5284,7 +5335,7 @@ export interface Block_350 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_351". + * via the `definition` "Block_351". */ export interface Block_351 { field1?: string | null; @@ -5297,7 +5348,7 @@ export interface Block_351 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_352". + * via the `definition` "Block_352". */ export interface Block_352 { field1?: string | null; @@ -5310,7 +5361,7 @@ export interface Block_352 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_353". + * via the `definition` "Block_353". */ export interface Block_353 { field1?: string | null; @@ -5323,7 +5374,7 @@ export interface Block_353 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_354". + * via the `definition` "Block_354". */ export interface Block_354 { field1?: string | null; @@ -5336,7 +5387,7 @@ export interface Block_354 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_355". + * via the `definition` "Block_355". */ export interface Block_355 { field1?: string | null; @@ -5349,7 +5400,7 @@ export interface Block_355 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_356". + * via the `definition` "Block_356". */ export interface Block_356 { field1?: string | null; @@ -5362,7 +5413,7 @@ export interface Block_356 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_357". + * via the `definition` "Block_357". */ export interface Block_357 { field1?: string | null; @@ -5375,7 +5426,7 @@ export interface Block_357 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_358". + * via the `definition` "Block_358". */ export interface Block_358 { field1?: string | null; @@ -5388,7 +5439,7 @@ export interface Block_358 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_359". + * via the `definition` "Block_359". */ export interface Block_359 { field1?: string | null; @@ -5401,7 +5452,7 @@ export interface Block_359 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_360". + * via the `definition` "Block_360". */ export interface Block_360 { field1?: string | null; @@ -5414,7 +5465,7 @@ export interface Block_360 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_361". + * via the `definition` "Block_361". */ export interface Block_361 { field1?: string | null; @@ -5427,7 +5478,7 @@ export interface Block_361 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_362". + * via the `definition` "Block_362". */ export interface Block_362 { field1?: string | null; @@ -5440,7 +5491,7 @@ export interface Block_362 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_363". + * via the `definition` "Block_363". */ export interface Block_363 { field1?: string | null; @@ -5453,7 +5504,7 @@ export interface Block_363 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_364". + * via the `definition` "Block_364". */ export interface Block_364 { field1?: string | null; @@ -5466,7 +5517,7 @@ export interface Block_364 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_365". + * via the `definition` "Block_365". */ export interface Block_365 { field1?: string | null; @@ -5479,7 +5530,7 @@ export interface Block_365 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_366". + * via the `definition` "Block_366". */ export interface Block_366 { field1?: string | null; @@ -5492,7 +5543,7 @@ export interface Block_366 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_367". + * via the `definition` "Block_367". */ export interface Block_367 { field1?: string | null; @@ -5505,7 +5556,7 @@ export interface Block_367 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_368". + * via the `definition` "Block_368". */ export interface Block_368 { field1?: string | null; @@ -5518,7 +5569,7 @@ export interface Block_368 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_369". + * via the `definition` "Block_369". */ export interface Block_369 { field1?: string | null; @@ -5531,7 +5582,7 @@ export interface Block_369 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_370". + * via the `definition` "Block_370". */ export interface Block_370 { field1?: string | null; @@ -5544,7 +5595,7 @@ export interface Block_370 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_371". + * via the `definition` "Block_371". */ export interface Block_371 { field1?: string | null; @@ -5557,7 +5608,7 @@ export interface Block_371 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_372". + * via the `definition` "Block_372". */ export interface Block_372 { field1?: string | null; @@ -5570,7 +5621,7 @@ export interface Block_372 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_373". + * via the `definition` "Block_373". */ export interface Block_373 { field1?: string | null; @@ -5583,7 +5634,7 @@ export interface Block_373 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_374". + * via the `definition` "Block_374". */ export interface Block_374 { field1?: string | null; @@ -5596,7 +5647,7 @@ export interface Block_374 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_375". + * via the `definition` "Block_375". */ export interface Block_375 { field1?: string | null; @@ -5609,7 +5660,7 @@ export interface Block_375 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_376". + * via the `definition` "Block_376". */ export interface Block_376 { field1?: string | null; @@ -5622,7 +5673,7 @@ export interface Block_376 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_377". + * via the `definition` "Block_377". */ export interface Block_377 { field1?: string | null; @@ -5635,7 +5686,7 @@ export interface Block_377 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_378". + * via the `definition` "Block_378". */ export interface Block_378 { field1?: string | null; @@ -5648,7 +5699,7 @@ export interface Block_378 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_379". + * via the `definition` "Block_379". */ export interface Block_379 { field1?: string | null; @@ -5661,7 +5712,7 @@ export interface Block_379 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_380". + * via the `definition` "Block_380". */ export interface Block_380 { field1?: string | null; @@ -5674,7 +5725,7 @@ export interface Block_380 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_381". + * via the `definition` "Block_381". */ export interface Block_381 { field1?: string | null; @@ -5687,7 +5738,7 @@ export interface Block_381 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_382". + * via the `definition` "Block_382". */ export interface Block_382 { field1?: string | null; @@ -5700,7 +5751,7 @@ export interface Block_382 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_383". + * via the `definition` "Block_383". */ export interface Block_383 { field1?: string | null; @@ -5713,7 +5764,7 @@ export interface Block_383 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_384". + * via the `definition` "Block_384". */ export interface Block_384 { field1?: string | null; @@ -5726,7 +5777,7 @@ export interface Block_384 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_385". + * via the `definition` "Block_385". */ export interface Block_385 { field1?: string | null; @@ -5739,7 +5790,7 @@ export interface Block_385 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_386". + * via the `definition` "Block_386". */ export interface Block_386 { field1?: string | null; @@ -5752,7 +5803,7 @@ export interface Block_386 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_387". + * via the `definition` "Block_387". */ export interface Block_387 { field1?: string | null; @@ -5765,7 +5816,7 @@ export interface Block_387 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_388". + * via the `definition` "Block_388". */ export interface Block_388 { field1?: string | null; @@ -5778,7 +5829,7 @@ export interface Block_388 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_389". + * via the `definition` "Block_389". */ export interface Block_389 { field1?: string | null; @@ -5791,7 +5842,7 @@ export interface Block_389 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_390". + * via the `definition` "Block_390". */ export interface Block_390 { field1?: string | null; @@ -5804,7 +5855,7 @@ export interface Block_390 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_391". + * via the `definition` "Block_391". */ export interface Block_391 { field1?: string | null; @@ -5817,7 +5868,7 @@ export interface Block_391 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_392". + * via the `definition` "Block_392". */ export interface Block_392 { field1?: string | null; @@ -5830,7 +5881,7 @@ export interface Block_392 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_393". + * via the `definition` "Block_393". */ export interface Block_393 { field1?: string | null; @@ -5843,7 +5894,7 @@ export interface Block_393 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_394". + * via the `definition` "Block_394". */ export interface Block_394 { field1?: string | null; @@ -5856,7 +5907,7 @@ export interface Block_394 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_395". + * via the `definition` "Block_395". */ export interface Block_395 { field1?: string | null; @@ -5869,7 +5920,7 @@ export interface Block_395 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_396". + * via the `definition` "Block_396". */ export interface Block_396 { field1?: string | null; @@ -5882,7 +5933,7 @@ export interface Block_396 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_397". + * via the `definition` "Block_397". */ export interface Block_397 { field1?: string | null; @@ -5895,7 +5946,7 @@ export interface Block_397 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_398". + * via the `definition` "Block_398". */ export interface Block_398 { field1?: string | null; @@ -5908,7 +5959,7 @@ export interface Block_398 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_399". + * via the `definition` "Block_399". */ export interface Block_399 { field1?: string | null; @@ -5921,7 +5972,7 @@ export interface Block_399 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_400". + * via the `definition` "Block_400". */ export interface Block_400 { field1?: string | null; @@ -5934,7 +5985,7 @@ export interface Block_400 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_401". + * via the `definition` "Block_401". */ export interface Block_401 { field1?: string | null; @@ -5947,7 +5998,7 @@ export interface Block_401 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_402". + * via the `definition` "Block_402". */ export interface Block_402 { field1?: string | null; @@ -5960,7 +6011,7 @@ export interface Block_402 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_403". + * via the `definition` "Block_403". */ export interface Block_403 { field1?: string | null; @@ -5973,7 +6024,7 @@ export interface Block_403 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_404". + * via the `definition` "Block_404". */ export interface Block_404 { field1?: string | null; @@ -5986,7 +6037,7 @@ export interface Block_404 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_405". + * via the `definition` "Block_405". */ export interface Block_405 { field1?: string | null; @@ -5999,7 +6050,7 @@ export interface Block_405 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_406". + * via the `definition` "Block_406". */ export interface Block_406 { field1?: string | null; @@ -6012,7 +6063,7 @@ export interface Block_406 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_407". + * via the `definition` "Block_407". */ export interface Block_407 { field1?: string | null; @@ -6025,7 +6076,7 @@ export interface Block_407 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_408". + * via the `definition` "Block_408". */ export interface Block_408 { field1?: string | null; @@ -6038,7 +6089,7 @@ export interface Block_408 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_409". + * via the `definition` "Block_409". */ export interface Block_409 { field1?: string | null; @@ -6051,7 +6102,7 @@ export interface Block_409 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_410". + * via the `definition` "Block_410". */ export interface Block_410 { field1?: string | null; @@ -6064,7 +6115,7 @@ export interface Block_410 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_411". + * via the `definition` "Block_411". */ export interface Block_411 { field1?: string | null; @@ -6077,7 +6128,7 @@ export interface Block_411 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_412". + * via the `definition` "Block_412". */ export interface Block_412 { field1?: string | null; @@ -6090,7 +6141,7 @@ export interface Block_412 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_413". + * via the `definition` "Block_413". */ export interface Block_413 { field1?: string | null; @@ -6103,7 +6154,7 @@ export interface Block_413 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_414". + * via the `definition` "Block_414". */ export interface Block_414 { field1?: string | null; @@ -6116,7 +6167,7 @@ export interface Block_414 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_415". + * via the `definition` "Block_415". */ export interface Block_415 { field1?: string | null; @@ -6129,7 +6180,7 @@ export interface Block_415 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_416". + * via the `definition` "Block_416". */ export interface Block_416 { field1?: string | null; @@ -6142,7 +6193,7 @@ export interface Block_416 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_417". + * via the `definition` "Block_417". */ export interface Block_417 { field1?: string | null; @@ -6155,7 +6206,7 @@ export interface Block_417 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_418". + * via the `definition` "Block_418". */ export interface Block_418 { field1?: string | null; @@ -6168,7 +6219,7 @@ export interface Block_418 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_419". + * via the `definition` "Block_419". */ export interface Block_419 { field1?: string | null; @@ -6181,7 +6232,7 @@ export interface Block_419 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_420". + * via the `definition` "Block_420". */ export interface Block_420 { field1?: string | null; @@ -6194,7 +6245,7 @@ export interface Block_420 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_421". + * via the `definition` "Block_421". */ export interface Block_421 { field1?: string | null; @@ -6207,7 +6258,7 @@ export interface Block_421 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_422". + * via the `definition` "Block_422". */ export interface Block_422 { field1?: string | null; @@ -6220,7 +6271,7 @@ export interface Block_422 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_423". + * via the `definition` "Block_423". */ export interface Block_423 { field1?: string | null; @@ -6233,7 +6284,7 @@ export interface Block_423 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_424". + * via the `definition` "Block_424". */ export interface Block_424 { field1?: string | null; @@ -6246,7 +6297,7 @@ export interface Block_424 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_425". + * via the `definition` "Block_425". */ export interface Block_425 { field1?: string | null; @@ -6259,7 +6310,7 @@ export interface Block_425 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_426". + * via the `definition` "Block_426". */ export interface Block_426 { field1?: string | null; @@ -6272,7 +6323,7 @@ export interface Block_426 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_427". + * via the `definition` "Block_427". */ export interface Block_427 { field1?: string | null; @@ -6285,7 +6336,7 @@ export interface Block_427 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_428". + * via the `definition` "Block_428". */ export interface Block_428 { field1?: string | null; @@ -6298,7 +6349,7 @@ export interface Block_428 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_429". + * via the `definition` "Block_429". */ export interface Block_429 { field1?: string | null; @@ -6311,7 +6362,7 @@ export interface Block_429 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_430". + * via the `definition` "Block_430". */ export interface Block_430 { field1?: string | null; @@ -6324,7 +6375,7 @@ export interface Block_430 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_431". + * via the `definition` "Block_431". */ export interface Block_431 { field1?: string | null; @@ -6337,7 +6388,7 @@ export interface Block_431 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_432". + * via the `definition` "Block_432". */ export interface Block_432 { field1?: string | null; @@ -6350,7 +6401,7 @@ export interface Block_432 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_433". + * via the `definition` "Block_433". */ export interface Block_433 { field1?: string | null; @@ -6363,7 +6414,7 @@ export interface Block_433 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_434". + * via the `definition` "Block_434". */ export interface Block_434 { field1?: string | null; @@ -6376,7 +6427,7 @@ export interface Block_434 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_435". + * via the `definition` "Block_435". */ export interface Block_435 { field1?: string | null; @@ -6389,7 +6440,7 @@ export interface Block_435 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_436". + * via the `definition` "Block_436". */ export interface Block_436 { field1?: string | null; @@ -6402,7 +6453,7 @@ export interface Block_436 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_437". + * via the `definition` "Block_437". */ export interface Block_437 { field1?: string | null; @@ -6415,7 +6466,7 @@ export interface Block_437 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_438". + * via the `definition` "Block_438". */ export interface Block_438 { field1?: string | null; @@ -6428,7 +6479,7 @@ export interface Block_438 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_439". + * via the `definition` "Block_439". */ export interface Block_439 { field1?: string | null; @@ -6441,7 +6492,7 @@ export interface Block_439 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_440". + * via the `definition` "Block_440". */ export interface Block_440 { field1?: string | null; @@ -6454,7 +6505,7 @@ export interface Block_440 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_441". + * via the `definition` "Block_441". */ export interface Block_441 { field1?: string | null; @@ -6467,7 +6518,7 @@ export interface Block_441 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_442". + * via the `definition` "Block_442". */ export interface Block_442 { field1?: string | null; @@ -6480,7 +6531,7 @@ export interface Block_442 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_443". + * via the `definition` "Block_443". */ export interface Block_443 { field1?: string | null; @@ -6493,7 +6544,7 @@ export interface Block_443 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_444". + * via the `definition` "Block_444". */ export interface Block_444 { field1?: string | null; @@ -6506,7 +6557,7 @@ export interface Block_444 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_445". + * via the `definition` "Block_445". */ export interface Block_445 { field1?: string | null; @@ -6519,7 +6570,7 @@ export interface Block_445 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_446". + * via the `definition` "Block_446". */ export interface Block_446 { field1?: string | null; @@ -6532,7 +6583,7 @@ export interface Block_446 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_447". + * via the `definition` "Block_447". */ export interface Block_447 { field1?: string | null; @@ -6545,7 +6596,7 @@ export interface Block_447 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_448". + * via the `definition` "Block_448". */ export interface Block_448 { field1?: string | null; @@ -6558,7 +6609,7 @@ export interface Block_448 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_449". + * via the `definition` "Block_449". */ export interface Block_449 { field1?: string | null; @@ -6571,7 +6622,7 @@ export interface Block_449 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_450". + * via the `definition` "Block_450". */ export interface Block_450 { field1?: string | null; @@ -6584,7 +6635,7 @@ export interface Block_450 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_451". + * via the `definition` "Block_451". */ export interface Block_451 { field1?: string | null; @@ -6597,7 +6648,7 @@ export interface Block_451 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_452". + * via the `definition` "Block_452". */ export interface Block_452 { field1?: string | null; @@ -6610,7 +6661,7 @@ export interface Block_452 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_453". + * via the `definition` "Block_453". */ export interface Block_453 { field1?: string | null; @@ -6623,7 +6674,7 @@ export interface Block_453 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_454". + * via the `definition` "Block_454". */ export interface Block_454 { field1?: string | null; @@ -6636,7 +6687,7 @@ export interface Block_454 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_455". + * via the `definition` "Block_455". */ export interface Block_455 { field1?: string | null; @@ -6649,7 +6700,7 @@ export interface Block_455 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_456". + * via the `definition` "Block_456". */ export interface Block_456 { field1?: string | null; @@ -6662,7 +6713,7 @@ export interface Block_456 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_457". + * via the `definition` "Block_457". */ export interface Block_457 { field1?: string | null; @@ -6675,7 +6726,7 @@ export interface Block_457 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_458". + * via the `definition` "Block_458". */ export interface Block_458 { field1?: string | null; @@ -6688,7 +6739,7 @@ export interface Block_458 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_459". + * via the `definition` "Block_459". */ export interface Block_459 { field1?: string | null; @@ -6701,7 +6752,7 @@ export interface Block_459 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_460". + * via the `definition` "Block_460". */ export interface Block_460 { field1?: string | null; @@ -6714,7 +6765,7 @@ export interface Block_460 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_461". + * via the `definition` "Block_461". */ export interface Block_461 { field1?: string | null; @@ -6727,7 +6778,7 @@ export interface Block_461 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_462". + * via the `definition` "Block_462". */ export interface Block_462 { field1?: string | null; @@ -6740,7 +6791,7 @@ export interface Block_462 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_463". + * via the `definition` "Block_463". */ export interface Block_463 { field1?: string | null; @@ -6753,7 +6804,7 @@ export interface Block_463 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_464". + * via the `definition` "Block_464". */ export interface Block_464 { field1?: string | null; @@ -6766,7 +6817,7 @@ export interface Block_464 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_465". + * via the `definition` "Block_465". */ export interface Block_465 { field1?: string | null; @@ -6779,7 +6830,7 @@ export interface Block_465 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_466". + * via the `definition` "Block_466". */ export interface Block_466 { field1?: string | null; @@ -6792,7 +6843,7 @@ export interface Block_466 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_467". + * via the `definition` "Block_467". */ export interface Block_467 { field1?: string | null; @@ -6805,7 +6856,7 @@ export interface Block_467 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_468". + * via the `definition` "Block_468". */ export interface Block_468 { field1?: string | null; @@ -6818,7 +6869,7 @@ export interface Block_468 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_469". + * via the `definition` "Block_469". */ export interface Block_469 { field1?: string | null; @@ -6831,7 +6882,7 @@ export interface Block_469 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_470". + * via the `definition` "Block_470". */ export interface Block_470 { field1?: string | null; @@ -6844,7 +6895,7 @@ export interface Block_470 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_471". + * via the `definition` "Block_471". */ export interface Block_471 { field1?: string | null; @@ -6857,7 +6908,7 @@ export interface Block_471 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_472". + * via the `definition` "Block_472". */ export interface Block_472 { field1?: string | null; @@ -6870,7 +6921,7 @@ export interface Block_472 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_473". + * via the `definition` "Block_473". */ export interface Block_473 { field1?: string | null; @@ -6883,7 +6934,7 @@ export interface Block_473 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_474". + * via the `definition` "Block_474". */ export interface Block_474 { field1?: string | null; @@ -6896,7 +6947,7 @@ export interface Block_474 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_475". + * via the `definition` "Block_475". */ export interface Block_475 { field1?: string | null; @@ -6909,7 +6960,7 @@ export interface Block_475 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_476". + * via the `definition` "Block_476". */ export interface Block_476 { field1?: string | null; @@ -6922,7 +6973,7 @@ export interface Block_476 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_477". + * via the `definition` "Block_477". */ export interface Block_477 { field1?: string | null; @@ -6935,7 +6986,7 @@ export interface Block_477 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_478". + * via the `definition` "Block_478". */ export interface Block_478 { field1?: string | null; @@ -6948,7 +6999,7 @@ export interface Block_478 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_479". + * via the `definition` "Block_479". */ export interface Block_479 { field1?: string | null; @@ -6961,7 +7012,7 @@ export interface Block_479 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_480". + * via the `definition` "Block_480". */ export interface Block_480 { field1?: string | null; @@ -6974,7 +7025,7 @@ export interface Block_480 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_481". + * via the `definition` "Block_481". */ export interface Block_481 { field1?: string | null; @@ -6987,7 +7038,7 @@ export interface Block_481 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_482". + * via the `definition` "Block_482". */ export interface Block_482 { field1?: string | null; @@ -7000,7 +7051,7 @@ export interface Block_482 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_483". + * via the `definition` "Block_483". */ export interface Block_483 { field1?: string | null; @@ -7013,7 +7064,7 @@ export interface Block_483 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_484". + * via the `definition` "Block_484". */ export interface Block_484 { field1?: string | null; @@ -7026,7 +7077,7 @@ export interface Block_484 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_485". + * via the `definition` "Block_485". */ export interface Block_485 { field1?: string | null; @@ -7039,7 +7090,7 @@ export interface Block_485 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_486". + * via the `definition` "Block_486". */ export interface Block_486 { field1?: string | null; @@ -7052,7 +7103,7 @@ export interface Block_486 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_487". + * via the `definition` "Block_487". */ export interface Block_487 { field1?: string | null; @@ -7065,7 +7116,7 @@ export interface Block_487 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_488". + * via the `definition` "Block_488". */ export interface Block_488 { field1?: string | null; @@ -7078,7 +7129,7 @@ export interface Block_488 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_489". + * via the `definition` "Block_489". */ export interface Block_489 { field1?: string | null; @@ -7091,7 +7142,7 @@ export interface Block_489 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_490". + * via the `definition` "Block_490". */ export interface Block_490 { field1?: string | null; @@ -7104,7 +7155,7 @@ export interface Block_490 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_491". + * via the `definition` "Block_491". */ export interface Block_491 { field1?: string | null; @@ -7117,7 +7168,7 @@ export interface Block_491 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_492". + * via the `definition` "Block_492". */ export interface Block_492 { field1?: string | null; @@ -7130,7 +7181,7 @@ export interface Block_492 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_493". + * via the `definition` "Block_493". */ export interface Block_493 { field1?: string | null; @@ -7143,7 +7194,7 @@ export interface Block_493 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_494". + * via the `definition` "Block_494". */ export interface Block_494 { field1?: string | null; @@ -7156,7 +7207,7 @@ export interface Block_494 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_495". + * via the `definition` "Block_495". */ export interface Block_495 { field1?: string | null; @@ -7169,7 +7220,7 @@ export interface Block_495 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_496". + * via the `definition` "Block_496". */ export interface Block_496 { field1?: string | null; @@ -7182,7 +7233,7 @@ export interface Block_496 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_497". + * via the `definition` "Block_497". */ export interface Block_497 { field1?: string | null; @@ -7195,7 +7246,7 @@ export interface Block_497 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_498". + * via the `definition` "Block_498". */ export interface Block_498 { field1?: string | null; @@ -7208,7 +7259,7 @@ export interface Block_498 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_499". + * via the `definition` "Block_499". */ export interface Block_499 { field1?: string | null; @@ -7221,7 +7272,7 @@ export interface Block_499 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_500". + * via the `definition` "Block_500". */ export interface Block_500 { field1?: string | null; @@ -7234,7 +7285,7 @@ export interface Block_500 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_501". + * via the `definition` "Block_501". */ export interface Block_501 { field1?: string | null; @@ -7247,7 +7298,7 @@ export interface Block_501 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_502". + * via the `definition` "Block_502". */ export interface Block_502 { field1?: string | null; @@ -7260,7 +7311,7 @@ export interface Block_502 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_503". + * via the `definition` "Block_503". */ export interface Block_503 { field1?: string | null; @@ -7273,7 +7324,7 @@ export interface Block_503 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_504". + * via the `definition` "Block_504". */ export interface Block_504 { field1?: string | null; @@ -7286,7 +7337,7 @@ export interface Block_504 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_505". + * via the `definition` "Block_505". */ export interface Block_505 { field1?: string | null; @@ -7299,7 +7350,7 @@ export interface Block_505 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_506". + * via the `definition` "Block_506". */ export interface Block_506 { field1?: string | null; @@ -7312,7 +7363,7 @@ export interface Block_506 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_507". + * via the `definition` "Block_507". */ export interface Block_507 { field1?: string | null; @@ -7325,7 +7376,7 @@ export interface Block_507 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_508". + * via the `definition` "Block_508". */ export interface Block_508 { field1?: string | null; @@ -7338,7 +7389,7 @@ export interface Block_508 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_509". + * via the `definition` "Block_509". */ export interface Block_509 { field1?: string | null; @@ -7351,7 +7402,7 @@ export interface Block_509 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_510". + * via the `definition` "Block_510". */ export interface Block_510 { field1?: string | null; @@ -7364,7 +7415,7 @@ export interface Block_510 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_511". + * via the `definition` "Block_511". */ export interface Block_511 { field1?: string | null; @@ -7377,7 +7428,7 @@ export interface Block_511 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_512". + * via the `definition` "Block_512". */ export interface Block_512 { field1?: string | null; @@ -7390,7 +7441,7 @@ export interface Block_512 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_513". + * via the `definition` "Block_513". */ export interface Block_513 { field1?: string | null; @@ -7403,7 +7454,7 @@ export interface Block_513 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_514". + * via the `definition` "Block_514". */ export interface Block_514 { field1?: string | null; @@ -7416,7 +7467,7 @@ export interface Block_514 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_515". + * via the `definition` "Block_515". */ export interface Block_515 { field1?: string | null; @@ -7429,7 +7480,7 @@ export interface Block_515 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_516". + * via the `definition` "Block_516". */ export interface Block_516 { field1?: string | null; @@ -7442,7 +7493,7 @@ export interface Block_516 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_517". + * via the `definition` "Block_517". */ export interface Block_517 { field1?: string | null; @@ -7455,7 +7506,7 @@ export interface Block_517 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_518". + * via the `definition` "Block_518". */ export interface Block_518 { field1?: string | null; @@ -7468,7 +7519,7 @@ export interface Block_518 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_519". + * via the `definition` "Block_519". */ export interface Block_519 { field1?: string | null; @@ -7481,7 +7532,7 @@ export interface Block_519 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_520". + * via the `definition` "Block_520". */ export interface Block_520 { field1?: string | null; @@ -7494,7 +7545,7 @@ export interface Block_520 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_521". + * via the `definition` "Block_521". */ export interface Block_521 { field1?: string | null; @@ -7507,7 +7558,7 @@ export interface Block_521 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_522". + * via the `definition` "Block_522". */ export interface Block_522 { field1?: string | null; @@ -7520,7 +7571,7 @@ export interface Block_522 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_523". + * via the `definition` "Block_523". */ export interface Block_523 { field1?: string | null; @@ -7533,7 +7584,7 @@ export interface Block_523 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_524". + * via the `definition` "Block_524". */ export interface Block_524 { field1?: string | null; @@ -7546,7 +7597,7 @@ export interface Block_524 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_525". + * via the `definition` "Block_525". */ export interface Block_525 { field1?: string | null; @@ -7559,7 +7610,7 @@ export interface Block_525 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_526". + * via the `definition` "Block_526". */ export interface Block_526 { field1?: string | null; @@ -7572,7 +7623,7 @@ export interface Block_526 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_527". + * via the `definition` "Block_527". */ export interface Block_527 { field1?: string | null; @@ -7585,7 +7636,7 @@ export interface Block_527 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_528". + * via the `definition` "Block_528". */ export interface Block_528 { field1?: string | null; @@ -7598,7 +7649,7 @@ export interface Block_528 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_529". + * via the `definition` "Block_529". */ export interface Block_529 { field1?: string | null; @@ -7611,7 +7662,7 @@ export interface Block_529 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_530". + * via the `definition` "Block_530". */ export interface Block_530 { field1?: string | null; @@ -7624,7 +7675,7 @@ export interface Block_530 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_531". + * via the `definition` "Block_531". */ export interface Block_531 { field1?: string | null; @@ -7637,7 +7688,7 @@ export interface Block_531 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_532". + * via the `definition` "Block_532". */ export interface Block_532 { field1?: string | null; @@ -7650,7 +7701,7 @@ export interface Block_532 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_533". + * via the `definition` "Block_533". */ export interface Block_533 { field1?: string | null; @@ -7663,7 +7714,7 @@ export interface Block_533 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_534". + * via the `definition` "Block_534". */ export interface Block_534 { field1?: string | null; @@ -7676,7 +7727,7 @@ export interface Block_534 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_535". + * via the `definition` "Block_535". */ export interface Block_535 { field1?: string | null; @@ -7689,7 +7740,7 @@ export interface Block_535 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_536". + * via the `definition` "Block_536". */ export interface Block_536 { field1?: string | null; @@ -7702,7 +7753,7 @@ export interface Block_536 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_537". + * via the `definition` "Block_537". */ export interface Block_537 { field1?: string | null; @@ -7715,7 +7766,7 @@ export interface Block_537 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_538". + * via the `definition` "Block_538". */ export interface Block_538 { field1?: string | null; @@ -7728,7 +7779,7 @@ export interface Block_538 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_539". + * via the `definition` "Block_539". */ export interface Block_539 { field1?: string | null; @@ -7741,7 +7792,7 @@ export interface Block_539 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_540". + * via the `definition` "Block_540". */ export interface Block_540 { field1?: string | null; @@ -7754,7 +7805,7 @@ export interface Block_540 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_541". + * via the `definition` "Block_541". */ export interface Block_541 { field1?: string | null; @@ -7767,7 +7818,7 @@ export interface Block_541 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_542". + * via the `definition` "Block_542". */ export interface Block_542 { field1?: string | null; @@ -7780,7 +7831,7 @@ export interface Block_542 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_543". + * via the `definition` "Block_543". */ export interface Block_543 { field1?: string | null; @@ -7793,7 +7844,7 @@ export interface Block_543 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_544". + * via the `definition` "Block_544". */ export interface Block_544 { field1?: string | null; @@ -7806,7 +7857,7 @@ export interface Block_544 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_545". + * via the `definition` "Block_545". */ export interface Block_545 { field1?: string | null; @@ -7819,7 +7870,7 @@ export interface Block_545 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_546". + * via the `definition` "Block_546". */ export interface Block_546 { field1?: string | null; @@ -7832,7 +7883,7 @@ export interface Block_546 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_547". + * via the `definition` "Block_547". */ export interface Block_547 { field1?: string | null; @@ -7845,7 +7896,7 @@ export interface Block_547 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_548". + * via the `definition` "Block_548". */ export interface Block_548 { field1?: string | null; @@ -7858,7 +7909,7 @@ export interface Block_548 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_549". + * via the `definition` "Block_549". */ export interface Block_549 { field1?: string | null; @@ -7871,7 +7922,7 @@ export interface Block_549 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_550". + * via the `definition` "Block_550". */ export interface Block_550 { field1?: string | null; @@ -7884,7 +7935,7 @@ export interface Block_550 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_551". + * via the `definition` "Block_551". */ export interface Block_551 { field1?: string | null; @@ -7897,7 +7948,7 @@ export interface Block_551 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_552". + * via the `definition` "Block_552". */ export interface Block_552 { field1?: string | null; @@ -7910,7 +7961,7 @@ export interface Block_552 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_553". + * via the `definition` "Block_553". */ export interface Block_553 { field1?: string | null; @@ -7923,7 +7974,7 @@ export interface Block_553 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_554". + * via the `definition` "Block_554". */ export interface Block_554 { field1?: string | null; @@ -7936,7 +7987,7 @@ export interface Block_554 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_555". + * via the `definition` "Block_555". */ export interface Block_555 { field1?: string | null; @@ -7949,7 +8000,7 @@ export interface Block_555 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_556". + * via the `definition` "Block_556". */ export interface Block_556 { field1?: string | null; @@ -7962,7 +8013,7 @@ export interface Block_556 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_557". + * via the `definition` "Block_557". */ export interface Block_557 { field1?: string | null; @@ -7975,7 +8026,7 @@ export interface Block_557 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_558". + * via the `definition` "Block_558". */ export interface Block_558 { field1?: string | null; @@ -7988,7 +8039,7 @@ export interface Block_558 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_559". + * via the `definition` "Block_559". */ export interface Block_559 { field1?: string | null; @@ -8001,7 +8052,7 @@ export interface Block_559 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_560". + * via the `definition` "Block_560". */ export interface Block_560 { field1?: string | null; @@ -8014,7 +8065,7 @@ export interface Block_560 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_561". + * via the `definition` "Block_561". */ export interface Block_561 { field1?: string | null; @@ -8027,7 +8078,7 @@ export interface Block_561 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_562". + * via the `definition` "Block_562". */ export interface Block_562 { field1?: string | null; @@ -8040,7 +8091,7 @@ export interface Block_562 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_563". + * via the `definition` "Block_563". */ export interface Block_563 { field1?: string | null; @@ -8053,7 +8104,7 @@ export interface Block_563 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_564". + * via the `definition` "Block_564". */ export interface Block_564 { field1?: string | null; @@ -8066,7 +8117,7 @@ export interface Block_564 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_565". + * via the `definition` "Block_565". */ export interface Block_565 { field1?: string | null; @@ -8079,7 +8130,7 @@ export interface Block_565 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_566". + * via the `definition` "Block_566". */ export interface Block_566 { field1?: string | null; @@ -8092,7 +8143,7 @@ export interface Block_566 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_567". + * via the `definition` "Block_567". */ export interface Block_567 { field1?: string | null; @@ -8105,7 +8156,7 @@ export interface Block_567 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_568". + * via the `definition` "Block_568". */ export interface Block_568 { field1?: string | null; @@ -8118,7 +8169,7 @@ export interface Block_568 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_569". + * via the `definition` "Block_569". */ export interface Block_569 { field1?: string | null; @@ -8131,7 +8182,7 @@ export interface Block_569 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_570". + * via the `definition` "Block_570". */ export interface Block_570 { field1?: string | null; @@ -8144,7 +8195,7 @@ export interface Block_570 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_571". + * via the `definition` "Block_571". */ export interface Block_571 { field1?: string | null; @@ -8157,7 +8208,7 @@ export interface Block_571 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_572". + * via the `definition` "Block_572". */ export interface Block_572 { field1?: string | null; @@ -8170,7 +8221,7 @@ export interface Block_572 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_573". + * via the `definition` "Block_573". */ export interface Block_573 { field1?: string | null; @@ -8183,7 +8234,7 @@ export interface Block_573 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_574". + * via the `definition` "Block_574". */ export interface Block_574 { field1?: string | null; @@ -8196,7 +8247,7 @@ export interface Block_574 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_575". + * via the `definition` "Block_575". */ export interface Block_575 { field1?: string | null; @@ -8209,7 +8260,7 @@ export interface Block_575 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_576". + * via the `definition` "Block_576". */ export interface Block_576 { field1?: string | null; @@ -8222,7 +8273,7 @@ export interface Block_576 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_577". + * via the `definition` "Block_577". */ export interface Block_577 { field1?: string | null; @@ -8235,7 +8286,7 @@ export interface Block_577 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_578". + * via the `definition` "Block_578". */ export interface Block_578 { field1?: string | null; @@ -8248,7 +8299,7 @@ export interface Block_578 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_579". + * via the `definition` "Block_579". */ export interface Block_579 { field1?: string | null; @@ -8261,7 +8312,7 @@ export interface Block_579 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_580". + * via the `definition` "Block_580". */ export interface Block_580 { field1?: string | null; @@ -8274,7 +8325,7 @@ export interface Block_580 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_581". + * via the `definition` "Block_581". */ export interface Block_581 { field1?: string | null; @@ -8287,7 +8338,7 @@ export interface Block_581 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_582". + * via the `definition` "Block_582". */ export interface Block_582 { field1?: string | null; @@ -8300,7 +8351,7 @@ export interface Block_582 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_583". + * via the `definition` "Block_583". */ export interface Block_583 { field1?: string | null; @@ -8313,7 +8364,7 @@ export interface Block_583 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_584". + * via the `definition` "Block_584". */ export interface Block_584 { field1?: string | null; @@ -8326,7 +8377,7 @@ export interface Block_584 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_585". + * via the `definition` "Block_585". */ export interface Block_585 { field1?: string | null; @@ -8339,7 +8390,7 @@ export interface Block_585 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_586". + * via the `definition` "Block_586". */ export interface Block_586 { field1?: string | null; @@ -8352,7 +8403,7 @@ export interface Block_586 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_587". + * via the `definition` "Block_587". */ export interface Block_587 { field1?: string | null; @@ -8365,7 +8416,7 @@ export interface Block_587 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_588". + * via the `definition` "Block_588". */ export interface Block_588 { field1?: string | null; @@ -8378,7 +8429,7 @@ export interface Block_588 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_589". + * via the `definition` "Block_589". */ export interface Block_589 { field1?: string | null; @@ -8391,7 +8442,7 @@ export interface Block_589 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_590". + * via the `definition` "Block_590". */ export interface Block_590 { field1?: string | null; @@ -8404,7 +8455,7 @@ export interface Block_590 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_591". + * via the `definition` "Block_591". */ export interface Block_591 { field1?: string | null; @@ -8417,7 +8468,7 @@ export interface Block_591 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_592". + * via the `definition` "Block_592". */ export interface Block_592 { field1?: string | null; @@ -8430,7 +8481,7 @@ export interface Block_592 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_593". + * via the `definition` "Block_593". */ export interface Block_593 { field1?: string | null; @@ -8443,7 +8494,7 @@ export interface Block_593 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_594". + * via the `definition` "Block_594". */ export interface Block_594 { field1?: string | null; @@ -8456,7 +8507,7 @@ export interface Block_594 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_595". + * via the `definition` "Block_595". */ export interface Block_595 { field1?: string | null; @@ -8469,7 +8520,7 @@ export interface Block_595 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_596". + * via the `definition` "Block_596". */ export interface Block_596 { field1?: string | null; @@ -8482,7 +8533,7 @@ export interface Block_596 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_597". + * via the `definition` "Block_597". */ export interface Block_597 { field1?: string | null; @@ -8495,7 +8546,7 @@ export interface Block_597 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_598". + * via the `definition` "Block_598". */ export interface Block_598 { field1?: string | null; @@ -8508,7 +8559,7 @@ export interface Block_598 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "block_599". + * via the `definition` "Block_599". */ export interface Block_599 { field1?: string | null; @@ -8526,21 +8577,7 @@ export interface Block_599 { export interface Post { id: string; title?: string | null; - content?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + content?: LexicalRichText | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -34998,23 +35035,6 @@ export interface Media { }; }; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -35040,6 +35060,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -35062,12 +35142,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -35077,10 +35166,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -35775,14 +35869,6 @@ export interface MediaSelect { }; }; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -35805,6 +35891,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -35837,6 +35947,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". @@ -35845,6 +35965,140 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export interface SerializedHorizontalRuleNode { + type: 'horizontalrule'; + version: number; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + declare module 'payload' { // @ts-ignore diff --git a/test/bulk-edit/payload-types.ts b/test/bulk-edit/payload-types.ts index 805706aacb5..9a3e4078e3c 100644 --- a/test/bulk-edit/payload-types.ts +++ b/test/bulk-edit/payload-types.ts @@ -64,13 +64,15 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { posts: Post; tabs: Tab; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -79,8 +81,9 @@ export interface Config { collectionsSelect: { posts: PostsSelect | PostsSelect; tabs: TabsSelect | TabsSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -95,7 +98,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -119,6 +122,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts". @@ -149,20 +170,23 @@ export interface Post { id?: string | null; }[] | null; - blocks?: - | { - textFieldForBlock?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'textBlock'; - }[] - | null; + blocks?: TextBlock[] | null; noRead?: string | null; noUpdate?: string | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TextBlock". + */ +export interface TextBlock { + textFieldForBlock?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'textBlock'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "tabs". @@ -185,23 +209,6 @@ export interface Tab { updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -227,6 +234,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -245,12 +312,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -260,10 +336,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -361,14 +442,6 @@ export interface TabsSelect { updatedAt?: T; createdAt?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -391,6 +464,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". diff --git a/test/collections-graphql/payload-types.ts b/test/collections-graphql/payload-types.ts index 23a5fd5521e..d47e79d7eb6 100644 --- a/test/collections-graphql/payload-types.ts +++ b/test/collections-graphql/payload-types.ts @@ -64,6 +64,7 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -80,6 +81,7 @@ export interface Config { 'cyclical-relationship': CyclicalRelationship; media: Media; sort: Sort; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -100,6 +102,7 @@ export interface Config { 'cyclical-relationship': CyclicalRelationshipSelect | CyclicalRelationshipSelect; media: MediaSelect | MediaSelect; sort: SortSelect | SortSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -112,7 +115,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: 'en' | 'es'; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -136,6 +142,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -348,6 +372,49 @@ export interface Sort { updatedAt: string; createdAt: string; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -423,12 +490,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'sort'; value: string | Sort; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -438,10 +514,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -655,6 +736,22 @@ export interface SortSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -695,6 +792,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/collections-rest/payload-types.ts b/test/collections-rest/payload-types.ts index 87b712cc7fc..653ec6820a4 100644 --- a/test/collections-rest/payload-types.ts +++ b/test/collections-rest/payload-types.ts @@ -64,6 +64,7 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -77,8 +78,9 @@ export interface Config { endpoints: Endpoint; 'disabled-bulk-edit-docs': DisabledBulkEditDoc; 'large-documents': LargeDocument; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -95,8 +97,9 @@ export interface Config { endpoints: EndpointsSelect | EndpointsSelect; 'disabled-bulk-edit-docs': DisabledBulkEditDocsSelect | DisabledBulkEditDocsSelect; 'large-documents': LargeDocumentsSelect | LargeDocumentsSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -108,7 +111,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -132,6 +138,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts". @@ -277,23 +301,6 @@ export interface LargeDocument { updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -319,6 +326,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -369,12 +436,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -384,10 +460,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -532,14 +613,6 @@ export interface LargeDocumentsSelect { updatedAt?: T; createdAt?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -562,6 +635,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -594,6 +691,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/config/payload-types.ts b/test/config/payload-types.ts index b2818247cbb..fe7ff33cc36 100644 --- a/test/config/payload-types.ts +++ b/test/config/payload-types.ts @@ -64,12 +64,14 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { pages: Page; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -77,8 +79,9 @@ export interface Config { collectionsJoins: {}; collectionsSelect: { pages: PagesSelect | PagesSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -94,7 +97,10 @@ export interface Config { 'my-global': MyGlobalSelect | MyGlobalSelect; }; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -118,6 +124,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "pages". @@ -125,34 +149,20 @@ export interface UserAuthOperations { export interface Page { id: string; title?: string | null; - myBlocks?: - | { - blockOneField?: string | null; - blockTwoField?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'blockOne'; - }[] - | null; + myBlocks?: BlockOne[] | null; updatedAt: string; createdAt: string; } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". + * via the `definition` "BlockOne". */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; +export interface BlockOne { + blockOneField?: string | null; + blockTwoField?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockOne'; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -179,6 +189,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -193,12 +263,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -208,10 +287,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -257,14 +341,6 @@ export interface PagesSelect { updatedAt?: T; createdAt?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -287,6 +363,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -339,6 +439,16 @@ export interface MyGlobalSelect { createdAt?: T; globalType?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/custom-graphql/payload-types.ts b/test/custom-graphql/payload-types.ts index cb0d502bdc9..883393fc3c6 100644 --- a/test/custom-graphql/payload-types.ts +++ b/test/custom-graphql/payload-types.ts @@ -64,19 +64,22 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; }; collectionsJoins: {}; collectionsSelect: { - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -88,7 +91,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -112,22 +118,23 @@ export interface UserAuthOperations { password: string; }; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -154,21 +161,91 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". */ export interface PayloadLockedDocument { id: string; - document?: { - relationTo: 'users'; - value: string | User; - } | null; + document?: + | ({ + relationTo: 'users'; + value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -178,10 +255,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -206,14 +288,6 @@ export interface PayloadMigration { updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -236,6 +310,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -268,6 +366,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/dashboard/payload-types.ts b/test/dashboard/payload-types.ts index 4261f4fd15f..16200eeec4f 100644 --- a/test/dashboard/payload-types.ts +++ b/test/dashboard/payload-types.ts @@ -64,14 +64,16 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { tickets: Ticket; revenue: Revenue; events: Event; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -81,8 +83,9 @@ export interface Config { tickets: TicketsSelect | TicketsSelect; revenue: RevenueSelect | RevenueSelect; events: EventsSelect | EventsSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -102,7 +105,7 @@ export interface Config { configurable: ConfigurableWidget; collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -126,6 +129,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "tickets". @@ -196,6 +217,49 @@ export interface Event { updatedAt: string; createdAt: string; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -235,12 +299,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -250,10 +323,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -320,14 +398,6 @@ export interface EventsSelect { updatedAt?: T; createdAt?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -350,6 +420,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". diff --git a/test/database/payload-types.ts b/test/database/payload-types.ts index 56675a59f52..9244aeb16b1 100644 --- a/test/database/payload-types.ts +++ b/test/database/payload-types.ts @@ -60,10 +60,70 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_9E6341C8". + */ +export type LexicalNodes_9E6341C8 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> + | SerializedHeadingNode + | { + type: 'upload'; + /** + * Lexical's internal serialization version for this node type. + */ + version: number; + [k: string]: unknown; + } + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedRelationshipNode< + | 'noTimeStamps' + | 'categories' + | 'simple' + | 'simple-localized' + | 'categories-custom-id' + | 'posts' + | 'error-on-unnamed-fields' + | 'default-values' + | 'relation-a' + | 'relation-b' + | 'pg-migrations' + | 'custom-schema' + | 'places' + | 'virtual-relations' + | 'fields-persistance' + | 'custom-ids' + | 'fake-custom-ids' + | 'relationships-migration' + | 'compound-indexes' + | 'aliases' + | 'blocks-docs' + | 'unique-fields' + | 'select-has-many' + | 'virtual-linked-tenants' + | 'virtual-linked-roles' + | 'virtual-linked-projects' + | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + >; export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -93,8 +153,9 @@ export interface Config { 'virtual-linked-tenants': VirtualLinkedTenant; 'virtual-linked-roles': VirtualLinkedRole; 'virtual-linked-projects': VirtualLinkedProject; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -131,14 +192,15 @@ export interface Config { 'virtual-linked-tenants': VirtualLinkedTenantsSelect | VirtualLinkedTenantsSelect; 'virtual-linked-roles': VirtualLinkedRolesSelect | VirtualLinkedRolesSelect; 'virtual-linked-projects': VirtualLinkedProjectsSelect | VirtualLinkedProjectsSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; }; db: { - defaultIDType: number; + defaultIDType: string; }; fallbackLocale: ('false' | 'none' | 'null') | false | null | ('en' | 'es' | 'uk') | ('en' | 'es' | 'uk')[]; globals: { @@ -159,7 +221,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -183,12 +245,30 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "noTimeStamps". */ export interface NoTimeStamp { - id: number; + id: string; title?: string | null; } /** @@ -196,12 +276,12 @@ export interface NoTimeStamp { * via the `definition` "categories". */ export interface Category { - id: number; + id: string; title?: string | null; - simple?: (number | null) | Simple; + simple?: (string | null) | Simple; hideout?: { camera1?: { - time1Image?: (number | null) | Post; + time1Image?: (string | null) | Post; }; }; updatedAt: string; @@ -213,7 +293,7 @@ export interface Category { * via the `definition` "simple". */ export interface Simple { - id: number; + id: string; text?: string | null; number?: number | null; updatedAt: string; @@ -224,9 +304,9 @@ export interface Simple { * via the `definition` "posts". */ export interface Post { - id: number; + id: string; title: string; - category?: (number | null) | Category; + category?: (string | null) | Category; categoryID?: | { [k: string]: unknown; @@ -238,16 +318,16 @@ export interface Post { | null; categoryTitle?: string | null; categorySimpleText?: string | null; - categories?: (number | Category)[] | null; + categories?: (string | Category)[] | null; categoriesCustomID?: (number | CategoriesCustomId)[] | null; categoryPoly?: { relationTo: 'categories'; - value: number | Category; + value: string | Category; } | null; categoryPolyMany?: | { relationTo: 'categories'; - value: number | Category; + value: string | Category; }[] | null; categoryCustomID?: (number | null) | CategoriesCustomId; @@ -255,11 +335,11 @@ export interface Post { | ( | { relationTo: 'categories'; - value: number | Category; + value: string | Category; } | { relationTo: 'simple'; - value: number | Simple; + value: string | Simple; } )[] | null; @@ -267,11 +347,11 @@ export interface Post { | ( | { relationTo: 'categories'; - value: number | Category; + value: string | Category; } | { relationTo: 'simple'; - value: number | Simple; + value: string | Simple; } )[] | null; @@ -281,31 +361,17 @@ export interface Post { numberDefault?: number | null; numbersHasMany?: number[] | null; publishDate?: string | null; - blocks?: - | { - nested?: - | { - nested?: unknown[] | null; - id?: string | null; - blockName?: string | null; - blockType: 'block-fourth'; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'block-third'; - }[] - | null; + blocks?: BlockThird[] | null; testNestedGroup?: { nestedLocalizedPolymorphicRelation?: | ( | { relationTo: 'categories'; - value: number | Category; + value: string | Category; } | { relationTo: 'simple'; - value: number | Simple; + value: string | Simple; } )[] | null; @@ -335,14 +401,7 @@ export interface Post { id?: string | null; }[] | null; - blocksWithIDs?: - | { - text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'block-first'; - }[] - | null; + blocksWithIDs?: BlockFirst[] | null; group?: { text?: string | null; }; @@ -362,12 +421,42 @@ export interface CategoriesCustomId { createdAt: string; _status?: ('draft' | 'published') | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockThird". + */ +export interface BlockThird { + nested?: BlockFourth[] | null; + id?: string | null; + blockName?: string | null; + blockType: 'block-third'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockFourth". + */ +export interface BlockFourth { + nested?: unknown[] | null; + id?: string | null; + blockName?: string | null; + blockType: 'block-fourth'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockFirst". + */ +export interface BlockFirst { + text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'block-first'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "simple-localized". */ export interface SimpleLocalized { - id: number; + id: string; text?: string | null; number?: number | null; updatedAt: string; @@ -378,7 +467,7 @@ export interface SimpleLocalized { * via the `definition` "error-on-unnamed-fields". */ export interface ErrorOnUnnamedField { - id: number; + id: string; groupWithinUnnamedTab: { text: string; }; @@ -390,7 +479,7 @@ export interface ErrorOnUnnamedField { * via the `definition` "default-values". */ export interface DefaultValue { - id: number; + id: string; title?: string | null; defaultValue?: string | null; array?: @@ -417,23 +506,9 @@ export interface DefaultValue { * via the `definition` "relation-a". */ export interface RelationA { - id: number; + id: string; title?: string | null; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -442,24 +517,10 @@ export interface RelationA { * via the `definition` "relation-b". */ export interface RelationB { - id: number; + id: string; title?: string | null; - relationship?: (number | null) | RelationA; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + relationship?: (string | null) | RelationA; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -468,14 +529,14 @@ export interface RelationB { * via the `definition` "pg-migrations". */ export interface PgMigration { - id: number; - relation1?: (number | null) | RelationA; + id: string; + relation1?: (string | null) | RelationA; myArray?: | { - relation2?: (number | null) | RelationB; + relation2?: (string | null) | RelationB; mySubArray?: | { - relation3?: (number | null) | RelationB; + relation3?: (string | null) | RelationB; id?: string | null; }[] | null; @@ -483,29 +544,34 @@ export interface PgMigration { }[] | null; myGroup?: { - relation4?: (number | null) | RelationB; + relation4?: (string | null) | RelationB; }; - myBlocks?: - | { - relation5?: (number | null) | RelationA; - relation6?: (number | null) | RelationB; - id?: string | null; - blockName?: string | null; - blockType: 'myBlock'; - }[] - | null; + myBlocks?: MyBlock_0C4AEB7D[] | null; updatedAt: string; createdAt: string; } +/** + * Multiple blocks resolve to the `MyBlock` interface with different fields, so a content hash is appended to keep the generated types stable and unambiguous. Set a unique `interfaceName` on the block to choose the name yourself. See https://payloadcms.com/docs/typescript/generating-types#block-interface-name-collisions + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock_0C4AEB7D". + */ +export interface MyBlock_0C4AEB7D { + relation5?: (string | null) | RelationA; + relation6?: (string | null) | RelationB; + id?: string | null; + blockName?: string | null; + blockType: 'myBlock'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "custom-schema". */ export interface CustomSchema { - id: number; + id: string; text?: string | null; localizedText?: string | null; - relationship?: (number | RelationA)[] | null; + relationship?: (string | RelationA)[] | null; select?: ('a' | 'b' | 'c')[] | null; radio?: ('a' | 'b' | 'c') | null; array?: @@ -515,25 +581,28 @@ export interface CustomSchema { id?: string | null; }[] | null; - blocks?: - | { - text?: string | null; - localizedText?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'block-second'; - }[] - | null; + blocks?: BlockSecond[] | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockSecond". + */ +export interface BlockSecond { + text?: string | null; + localizedText?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'block-second'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "places". */ export interface Place { - id: number; + id: string; country?: string | null; city?: string | null; updatedAt: string; @@ -544,7 +613,7 @@ export interface Place { * via the `definition` "virtual-relations". */ export interface VirtualRelation { - id: number; + id: string; postTitle?: string | null; postsTitles?: string[] | null; postCategoriesTitles?: string[] | null; @@ -570,8 +639,8 @@ export interface VirtualRelation { | boolean | null; postLocalized?: string | null; - post?: (number | null) | Post; - posts?: (number | Post)[] | null; + post?: (string | null) | Post; + posts?: (string | Post)[] | null; customID?: (string | null) | CustomId; customIDValue?: string | null; updatedAt: string; @@ -594,7 +663,7 @@ export interface CustomId { * via the `definition` "fields-persistance". */ export interface FieldsPersistance { - id: number; + id: string; text?: string | null; textHooked?: string | null; array?: @@ -605,24 +674,27 @@ export interface FieldsPersistance { textWithinRow?: string | null; textWithinCollapsible?: string | null; textWithinTabs?: string | null; - blockWithVirtual?: - | { - text?: string | null; - virtualField?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'blockWithVirtual'; - }[] - | null; + blockWithVirtual?: BlockWithVirtual[] | null; updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockWithVirtual". + */ +export interface BlockWithVirtual { + text?: string | null; + virtualField?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockWithVirtual'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "fake-custom-ids". */ export interface FakeCustomId { - id: number; + id: string; title?: string | null; group?: { id?: string | null; @@ -638,11 +710,11 @@ export interface FakeCustomId { * via the `definition` "relationships-migration". */ export interface RelationshipsMigration { - id: number; - relationship?: (number | null) | DefaultValue; + id: string; + relationship?: (string | null) | DefaultValue; relationship_2?: { relationTo: 'default-values'; - value: number | DefaultValue; + value: string | DefaultValue; } | null; updatedAt: string; createdAt: string; @@ -652,7 +724,7 @@ export interface RelationshipsMigration { * via the `definition` "compound-indexes". */ export interface CompoundIndex { - id: number; + id: string; one?: string | null; two?: string | null; three?: string | null; @@ -667,7 +739,7 @@ export interface CompoundIndex { * via the `definition` "aliases". */ export interface Alias { - id: number; + id: string; thisIsALongFieldNameThatCanCauseAPostgresErrorEvenThoughWeSetAShorterDBName?: | { nestedArray?: @@ -687,32 +759,28 @@ export interface Alias { * via the `definition` "blocks-docs". */ export interface BlocksDoc { - id: number; - testBlocksLocalized?: - | { - text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'cta'; - }[] - | null; - testBlocks?: - | { - text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'cta'; - }[] - | null; + id: string; + testBlocksLocalized?: Cta[] | null; + testBlocks?: Cta[] | null; updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Cta". + */ +export interface Cta { + text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'cta'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "unique-fields". */ export interface UniqueField { - id: number; + id: string; slugField?: string | null; updatedAt: string; createdAt: string; @@ -764,29 +832,12 @@ export interface VirtualLinkedProject { updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: number; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". */ export interface User { - id: number; + id: string; updatedAt: string; createdAt: string; email: string; @@ -806,28 +857,88 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". */ export interface PayloadLockedDocument { - id: number; + id: string; document?: | ({ relationTo: 'noTimeStamps'; - value: number | NoTimeStamp; + value: string | NoTimeStamp; } | null) | ({ relationTo: 'categories'; - value: number | Category; + value: string | Category; } | null) | ({ relationTo: 'simple'; - value: number | Simple; + value: string | Simple; } | null) | ({ relationTo: 'simple-localized'; - value: number | SimpleLocalized; + value: string | SimpleLocalized; } | null) | ({ relationTo: 'categories-custom-id'; @@ -835,43 +946,43 @@ export interface PayloadLockedDocument { } | null) | ({ relationTo: 'posts'; - value: number | Post; + value: string | Post; } | null) | ({ relationTo: 'error-on-unnamed-fields'; - value: number | ErrorOnUnnamedField; + value: string | ErrorOnUnnamedField; } | null) | ({ relationTo: 'default-values'; - value: number | DefaultValue; + value: string | DefaultValue; } | null) | ({ relationTo: 'relation-a'; - value: number | RelationA; + value: string | RelationA; } | null) | ({ relationTo: 'relation-b'; - value: number | RelationB; + value: string | RelationB; } | null) | ({ relationTo: 'pg-migrations'; - value: number | PgMigration; + value: string | PgMigration; } | null) | ({ relationTo: 'custom-schema'; - value: number | CustomSchema; + value: string | CustomSchema; } | null) | ({ relationTo: 'places'; - value: number | Place; + value: string | Place; } | null) | ({ relationTo: 'virtual-relations'; - value: number | VirtualRelation; + value: string | VirtualRelation; } | null) | ({ relationTo: 'fields-persistance'; - value: number | FieldsPersistance; + value: string | FieldsPersistance; } | null) | ({ relationTo: 'custom-ids'; @@ -879,27 +990,27 @@ export interface PayloadLockedDocument { } | null) | ({ relationTo: 'fake-custom-ids'; - value: number | FakeCustomId; + value: string | FakeCustomId; } | null) | ({ relationTo: 'relationships-migration'; - value: number | RelationshipsMigration; + value: string | RelationshipsMigration; } | null) | ({ relationTo: 'compound-indexes'; - value: number | CompoundIndex; + value: string | CompoundIndex; } | null) | ({ relationTo: 'aliases'; - value: number | Alias; + value: string | Alias; } | null) | ({ relationTo: 'blocks-docs'; - value: number | BlocksDoc; + value: string | BlocksDoc; } | null) | ({ relationTo: 'unique-fields'; - value: number | UniqueField; + value: string | UniqueField; } | null) | ({ relationTo: 'select-has-many'; @@ -919,13 +1030,22 @@ export interface PayloadLockedDocument { } | null) | ({ relationTo: 'users'; - value: number | User; + value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: number | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -934,11 +1054,16 @@ export interface PayloadLockedDocument { * via the `definition` "payload-preferences". */ export interface PayloadPreference { - id: number; - user: { - relationTo: 'users'; - value: number | User; - }; + id: string; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -957,7 +1082,7 @@ export interface PayloadPreference { * via the `definition` "payload-migrations". */ export interface PayloadMigration { - id: number; + id: string; name?: string | null; batch?: number | null; updatedAt: string; @@ -1468,14 +1593,6 @@ export interface VirtualLinkedProjectsSelect { updatedAt?: T; createdAt?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -1498,6 +1615,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -1535,7 +1676,7 @@ export interface PayloadMigrationsSelect { * via the `definition` "header". */ export interface Header { - id: number; + id: string; itemsLvl1?: | { label?: string | null; @@ -1568,7 +1709,7 @@ export interface Header { * via the `definition` "global". */ export interface Global { - id: number; + id: string; text?: string | null; updatedAt?: string | null; createdAt?: string | null; @@ -1578,7 +1719,7 @@ export interface Global { * via the `definition` "global-2". */ export interface Global2 { - id: number; + id: string; text?: string | null; updatedAt?: string | null; createdAt?: string | null; @@ -1588,7 +1729,7 @@ export interface Global2 { * via the `definition` "global-3". */ export interface Global3 { - id: number; + id: string; text?: string | null; updatedAt?: string | null; createdAt?: string | null; @@ -1598,9 +1739,9 @@ export interface Global3 { * via the `definition` "virtual-relation-global". */ export interface VirtualRelationGlobal { - id: number; + id: string; postTitle?: string | null; - post?: (number | null) | Post; + post?: (string | null) | Post; updatedAt?: string | null; createdAt?: string | null; } @@ -1688,6 +1829,38 @@ export interface CollectionsWidget { }; width: 'full'; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock". + */ +export interface MyBlock { + id: string; + blockType: 'myBlock'; + someText?: string | null; + someTextRequired: string; + radios?: ('option1' | 'option2' | 'option3') | null; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_9E6341C8". + */ +export interface LexicalLinkFields_9E6341C8 { + linkType: 'custom' | 'internal'; + url?: string; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + newTab: boolean; + description?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". @@ -1696,6 +1869,147 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export type SerializedBlockNode = { + type: 'block'; + format: LexicalElementFormat; + version: number; + fields: { id: string; blockName?: string | null } & Omit; +}; +export type SerializedInlineBlockNode = { + type: 'inlineBlock'; + version: number; + fields: { id: string } & Omit; +}; + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + declare module 'payload' { // @ts-ignore diff --git a/test/dataloader/payload-types.ts b/test/dataloader/payload-types.ts index 68ab216f9c8..2d2df79dbba 100644 --- a/test/dataloader/payload-types.ts +++ b/test/dataloader/payload-types.ts @@ -60,10 +60,49 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_5AC9F469". + */ +export type LexicalNodes_5AC9F469 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedHorizontalRuleNode + | { + type: 'upload'; + /** + * Lexical's internal serialization version for this node type. + */ + version: number; + [k: string]: unknown; + } + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'posts' + | 'relation-a' + | 'relation-b' + | 'shops' + | 'items' + | 'itemTags' + | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -73,8 +112,9 @@ export interface Config { shops: Shop; items: Item; itemTags: ItemTag; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -87,8 +127,9 @@ export interface Config { shops: ShopsSelect | ShopsSelect; items: ItemsSelect | ItemsSelect; itemTags: ItemTagsSelect | ItemTagsSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -103,7 +144,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -127,6 +168,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts". @@ -170,21 +229,7 @@ export interface User { export interface RelationA { id: string; relationship?: (string | null) | RelationB; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -195,21 +240,7 @@ export interface RelationA { export interface RelationB { id: string; relationship?: (string | null) | RelationA; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -245,6 +276,49 @@ export interface ItemTag { updatedAt: string; createdAt: string; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -296,12 +370,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -311,10 +394,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -398,14 +486,6 @@ export interface ItemTagsSelect { updatedAt?: T; createdAt?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -428,6 +508,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -478,6 +582,140 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export interface SerializedHorizontalRuleNode { + type: 'horizontalrule'; + version: number; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + declare module 'payload' { // @ts-ignore diff --git a/test/email-nodemailer/payload-types.ts b/test/email-nodemailer/payload-types.ts index cb0d502bdc9..883393fc3c6 100644 --- a/test/email-nodemailer/payload-types.ts +++ b/test/email-nodemailer/payload-types.ts @@ -64,19 +64,22 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; }; collectionsJoins: {}; collectionsSelect: { - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -88,7 +91,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -112,22 +118,23 @@ export interface UserAuthOperations { password: string; }; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -154,21 +161,91 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". */ export interface PayloadLockedDocument { id: string; - document?: { - relationTo: 'users'; - value: string | User; - } | null; + document?: + | ({ + relationTo: 'users'; + value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -178,10 +255,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -206,14 +288,6 @@ export interface PayloadMigration { updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -236,6 +310,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -268,6 +366,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/email-resend/payload-types.ts b/test/email-resend/payload-types.ts index cb0d502bdc9..883393fc3c6 100644 --- a/test/email-resend/payload-types.ts +++ b/test/email-resend/payload-types.ts @@ -64,19 +64,22 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; }; collectionsJoins: {}; collectionsSelect: { - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -88,7 +91,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -112,22 +118,23 @@ export interface UserAuthOperations { password: string; }; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -154,21 +161,91 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". */ export interface PayloadLockedDocument { id: string; - document?: { - relationTo: 'users'; - value: string | User; - } | null; + document?: + | ({ + relationTo: 'users'; + value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -178,10 +255,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -206,14 +288,6 @@ export interface PayloadMigration { updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -236,6 +310,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -268,6 +366,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/email/payload-types.ts b/test/email/payload-types.ts index 54430164500..70e033c86b6 100644 --- a/test/email/payload-types.ts +++ b/test/email/payload-types.ts @@ -64,13 +64,15 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { posts: Post; media: Media; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -79,8 +81,9 @@ export interface Config { collectionsSelect: { posts: PostsSelect | PostsSelect; media: MediaSelect | MediaSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -96,7 +99,10 @@ export interface Config { menu: MenuSelect | MenuSelect; }; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -120,6 +126,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts". @@ -176,23 +200,6 @@ export interface Media { }; }; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -218,6 +225,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -236,12 +303,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -251,10 +327,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -341,14 +422,6 @@ export interface MediaSelect { }; }; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -371,6 +444,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -423,6 +520,16 @@ export interface MenuSelect { createdAt?: T; globalType?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/endpoints/payload-types.ts b/test/endpoints/payload-types.ts index abaf13684f9..51a904adc48 100644 --- a/test/endpoints/payload-types.ts +++ b/test/endpoints/payload-types.ts @@ -64,13 +64,15 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { endpoints: Endpoint; 'no-endpoints': NoEndpoint; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -79,8 +81,9 @@ export interface Config { collectionsSelect: { endpoints: EndpointsSelect | EndpointsSelect; 'no-endpoints': NoEndpointsSelect | NoEndpointsSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -98,7 +101,10 @@ export interface Config { 'global-no-endpoints': GlobalNoEndpointsSelect | GlobalNoEndpointsSelect; }; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -122,6 +128,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "endpoints". @@ -142,23 +166,6 @@ export interface NoEndpoint { updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -184,6 +191,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -202,12 +269,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -217,10 +293,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -263,14 +344,6 @@ export interface NoEndpointsSelect { updatedAt?: T; createdAt?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -293,6 +366,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -363,6 +460,16 @@ export interface GlobalNoEndpointsSelect { createdAt?: T; globalType?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/evals/payload-types.ts b/test/evals/payload-types.ts index c5e54204810..883393fc3c6 100644 --- a/test/evals/payload-types.ts +++ b/test/evals/payload-types.ts @@ -64,25 +64,28 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; }; collectionsJoins: {}; collectionsSelect: { - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; }; db: { - defaultIDType: number; + defaultIDType: string; }; fallbackLocale: null; globals: {}; @@ -91,7 +94,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -115,29 +118,30 @@ export interface UserAuthOperations { password: string; }; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: number; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; } /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". */ export interface User { - id: number; + id: string; updatedAt: string; createdAt: string; email: string; @@ -157,21 +161,91 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". */ export interface PayloadLockedDocument { id: string; - document?: { - relationTo: 'users'; - value: string | User; - } | null; + document?: + | ({ + relationTo: 'users'; + value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: number | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -180,11 +254,16 @@ export interface PayloadLockedDocument { * via the `definition` "payload-preferences". */ export interface PayloadPreference { - id: number; - user: { - relationTo: 'users'; - value: number | User; - }; + id: string; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -203,20 +282,12 @@ export interface PayloadPreference { * via the `definition` "payload-migrations". */ export interface PayloadMigration { - id: number; + id: string; name?: string | null; batch?: number | null; updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -239,6 +310,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". diff --git a/test/field-error-states/payload-types.ts b/test/field-error-states/payload-types.ts index 92a7c30edcf..79b03caf154 100644 --- a/test/field-error-states/payload-types.ts +++ b/test/field-error-states/payload-types.ts @@ -60,10 +60,43 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_11A876F6". + */ +export type LexicalNodes_11A876F6 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> + | SerializedHeadingNode + | SerializedUploadNode<'uploads'> + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedRelationshipNode< + | 'error-fields' + | 'validate-drafts-on' + | 'validate-drafts-off' + | 'validate-drafts-on-autosave' + | 'prev-value' + | 'prev-value-relation' + | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + >; export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -74,8 +107,9 @@ export interface Config { 'validate-drafts-on-autosave': ValidateDraftsOnAutosave; 'prev-value': PrevValue; 'prev-value-relation': PrevValueRelation; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -89,8 +123,9 @@ export interface Config { 'validate-drafts-on-autosave': ValidateDraftsOnAutosaveSelect | ValidateDraftsOnAutosaveSelect; 'prev-value': PrevValueSelect | PrevValueSelect; 'prev-value-relation': PrevValueRelationSelect | PrevValueRelationSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -106,9 +141,10 @@ export interface Config { 'global-validate-drafts-on': GlobalValidateDraftsOnSelect | GlobalValidateDraftsOnSelect; }; locale: null; - user: User & { - collection: 'users'; + widgets: { + collections: CollectionsWidget; }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -132,6 +168,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "error-fields". @@ -178,21 +232,7 @@ export interface ErrorField { point: [number, number]; radio: 'mint' | 'dark_gray'; relationship: string | User; - richtext: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - }; + richtext: LexicalRichText; select: 'mint' | 'dark_gray'; upload: string | Upload; text: string; @@ -231,21 +271,7 @@ export interface ErrorField { point: [number, number]; radio: 'mint' | 'dark_gray'; relationship: string | User; - richtext: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - }; + richtext: LexicalRichText; select: 'mint' | 'dark_gray'; upload: string | Upload; text: string; @@ -263,65 +289,7 @@ export interface ErrorField { arrayText: string; id?: string | null; }[]; - layout?: - | { - tabText: string; - text: string; - array?: - | { - requiredArrayText: string; - arrayText?: string | null; - group: { - text: string; - number: number; - date: string; - checkbox: boolean; - }; - code: string; - json: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; - email: string; - /** - * @minItems 2 - * @maxItems 2 - */ - point: [number, number]; - radio: 'mint' | 'dark_gray'; - relationship: string | User; - richtext: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - }; - select: 'mint' | 'dark_gray'; - upload: string | Upload; - text: string; - textarea: string; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'block1'; - }[] - | null; + layout?: Block1[] | null; group: { text: string; }; @@ -351,6 +319,7 @@ export interface User { }[] | null; password?: string | null; + collection: 'users'; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -360,21 +329,7 @@ export interface Upload { id: string; text?: string | null; media?: (string | null) | Upload; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; url?: string | null; @@ -387,6 +342,53 @@ export interface Upload { focalX?: number | null; focalY?: number | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Block1". + */ +export interface Block1 { + tabText: string; + text: string; + array?: + | { + requiredArrayText: string; + arrayText?: string | null; + group: { + text: string; + number: number; + date: string; + checkbox: boolean; + }; + code: string; + json: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + email: string; + /** + * @minItems 2 + * @maxItems 2 + */ + point: [number, number]; + radio: 'mint' | 'dark_gray'; + relationship: string | User; + richtext: LexicalRichText; + select: 'mint' | 'dark_gray'; + upload: string | Upload; + text: string; + textarea: string; + id?: string | null; + }[] + | null; + id?: string | null; + blockName?: string | null; + blockType: 'block1'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "validate-drafts-on". @@ -465,6 +467,49 @@ export interface PrevValueRelation { updatedAt: string; createdAt: string; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -520,12 +565,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -535,10 +589,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -776,14 +835,6 @@ export interface PrevValueRelationSelect { updatedAt?: T; createdAt?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -806,6 +857,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -866,6 +941,48 @@ export interface GlobalValidateDraftsOnSelect { createdAt?: T; globalType?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock". + */ +export interface MyBlock { + id: string; + blockType: 'myBlock'; + someText?: string | null; + someTextRequired: string; + radios?: ('option1' | 'option2' | 'option3') | null; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_11A876F6". + */ +export interface LexicalLinkFields_11A876F6 { + linkType: 'custom' | 'internal'; + url?: string; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + newTab: boolean; + description?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". @@ -874,6 +991,147 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export type SerializedBlockNode = { + type: 'block'; + format: LexicalElementFormat; + version: number; + fields: { id: string; blockName?: string | null } & Omit; +}; +export type SerializedInlineBlockNode = { + type: 'inlineBlock'; + version: number; + fields: { id: string } & Omit; +}; + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + declare module 'payload' { // @ts-ignore diff --git a/test/field-paths/payload-types.ts b/test/field-paths/payload-types.ts index 2e74a8193b4..06758d0eb2c 100644 --- a/test/field-paths/payload-types.ts +++ b/test/field-paths/payload-types.ts @@ -64,12 +64,14 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { 'field-paths': FieldPath; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -77,8 +79,9 @@ export interface Config { collectionsJoins: {}; collectionsSelect: { 'field-paths': FieldPathsSelect | FieldPathsSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -90,7 +93,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -114,6 +120,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "field-paths". @@ -145,14 +169,7 @@ export interface FieldPath { fieldWithinNamedTabWithinCollapsible?: string | null; }; textFieldInUnnamedGroup?: string | null; - blocks?: - | { - textInCollapsibleInCollapsibleBlock?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'CollapsibleBlock'; - }[] - | null; + blocks?: CollapsibleBlock[] | null; topLevelNamedField_beforeValidate_FieldPaths?: | { [k: string]: unknown; @@ -591,20 +608,13 @@ export interface FieldPath { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". + * via the `definition` "CollapsibleBlock". */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; +export interface CollapsibleBlock { + textInCollapsibleInCollapsibleBlock?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'CollapsibleBlock'; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -631,6 +641,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -645,12 +715,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -660,10 +739,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -785,14 +869,6 @@ export interface FieldPathsSelect { createdAt?: T; _status?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -815,6 +891,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -847,6 +947,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/field-perf/payload-types.ts b/test/field-perf/payload-types.ts index 6291b70bb52..c40a8545bb0 100644 --- a/test/field-perf/payload-types.ts +++ b/test/field-perf/payload-types.ts @@ -60,16 +60,52 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_60491765". + */ +export type LexicalNodes_60491765 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> + | SerializedHeadingNode + | { + type: 'upload'; + /** + * Lexical's internal serialization version for this node type. + */ + version: number; + [k: string]: unknown; + } + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedRelationshipNode< + | 'blocks-collection' + | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + >; export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { 'blocks-collection': BlocksCollection; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -77,8 +113,9 @@ export interface Config { collectionsJoins: {}; collectionsSelect: { 'blocks-collection': BlocksCollectionSelect | BlocksCollectionSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -90,7 +127,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -114,62 +154,52 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "blocks-collection". */ export interface BlocksCollection { id: string; - layout?: - | { - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - field1?: string | null; - field2?: string | null; - field3?: string | null; - field4?: string | null; - field5?: string | null; - field6?: string | null; - field7?: string | null; - field8?: string | null; - field9?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'content'; - }[] - | null; + layout?: Content[] | null; updatedAt: string; createdAt: string; } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". + * via the `definition` "Content". */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; +export interface Content { + richText?: LexicalRichText | null; + field1?: string | null; + field2?: string | null; + field3?: string | null; + field4?: string | null; + field5?: string | null; + field6?: string | null; + field7?: string | null; + field8?: string | null; + field9?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'content'; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -196,6 +226,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -210,12 +300,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -225,10 +324,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -281,14 +385,6 @@ export interface BlocksCollectionSelect { updatedAt?: T; createdAt?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -311,6 +407,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -343,6 +463,48 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock". + */ +export interface MyBlock { + id: string; + blockType: 'myBlock'; + someText?: string | null; + someTextRequired: string; + radios?: ('option1' | 'option2' | 'option3') | null; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_60491765". + */ +export interface LexicalLinkFields_60491765 { + linkType: 'custom' | 'internal'; + url?: string; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + newTab: boolean; + description?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". @@ -351,6 +513,147 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export type SerializedBlockNode = { + type: 'block'; + format: LexicalElementFormat; + version: number; + fields: { id: string; blockName?: string | null } & Omit; +}; +export type SerializedInlineBlockNode = { + type: 'inlineBlock'; + version: number; + fields: { id: string } & Omit; +}; + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + declare module 'payload' { // @ts-ignore diff --git a/test/fields-relationship/payload-types.ts b/test/fields-relationship/payload-types.ts index ff45feab375..ea7b823db36 100644 --- a/test/fields-relationship/payload-types.ts +++ b/test/fields-relationship/payload-types.ts @@ -64,6 +64,7 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -81,8 +82,9 @@ export interface Config { podcasts: Podcast; 'mixed-media': MixedMedia; 'versioned-relationship-field': VersionedRelationshipField; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -103,8 +105,9 @@ export interface Config { podcasts: PodcastsSelect | PodcastsSelect; 'mixed-media': MixedMediaSelect | MixedMediaSelect; 'versioned-relationship-field': VersionedRelationshipFieldSelect | VersionedRelationshipFieldSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -119,7 +122,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -143,6 +146,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "fields-relationship". @@ -386,23 +407,6 @@ export interface VersionedRelationshipField { createdAt: string; _status?: ('draft' | 'published') | null; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -428,6 +432,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -494,12 +558,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -509,10 +582,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -693,14 +771,6 @@ export interface VersionedRelationshipFieldSelect { createdAt?: T; _status?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -723,6 +793,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". diff --git a/test/fields/payload-types.ts b/test/fields/payload-types.ts index c18a99c5687..7e278b6e69f 100644 --- a/test/fields/payload-types.ts +++ b/test/fields/payload-types.ts @@ -62,6 +62,121 @@ export type SupportedTimezones = | 'Pacific/Fiji' | 'America/Monterrey' | 'UTC'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_E99B774E". + */ +export type LexicalNodes_E99B774E = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> + | SerializedHeadingNode + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedRelationshipNode< + | 'users' + | 'select-versions-fields' + | 'array-fields' + | 'block-fields' + | 'checkbox-fields' + | 'code-fields' + | 'collapsible-fields' + | 'conditional-logic' + | 'custom-id' + | 'custom-id-nested' + | 'custom-tab-id' + | 'custom-row-id' + | 'date-fields' + | 'email-fields' + | 'radio-fields' + | 'group-fields' + | 'row-fields' + | 'indexed-fields' + | 'json-fields' + | 'number-fields' + | 'point-fields' + | 'relationship-fields' + | 'select-fields' + | 'slug-fields' + | 'tabs-fields-2' + | 'tabs-fields' + | 'text-fields' + | 'textarea-fields' + | 'uploads-multi' + | 'uploads-poly' + | 'uploads-multi-poly' + | 'uploads-restricted' + | 'ui-fields' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + >; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_A9A5E3FC". + */ +export type LexicalNodes_A9A5E3FC = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedHorizontalRuleNode + | SerializedUploadNode<'uploads' | 'uploads2'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'users' + | 'select-versions-fields' + | 'array-fields' + | 'block-fields' + | 'checkbox-fields' + | 'code-fields' + | 'collapsible-fields' + | 'conditional-logic' + | 'custom-id' + | 'custom-id-nested' + | 'custom-tab-id' + | 'custom-row-id' + | 'date-fields' + | 'email-fields' + | 'radio-fields' + | 'group-fields' + | 'row-fields' + | 'indexed-fields' + | 'json-fields' + | 'number-fields' + | 'point-fields' + | 'relationship-fields' + | 'select-fields' + | 'slug-fields' + | 'tabs-fields-2' + | 'tabs-fields' + | 'text-fields' + | 'textarea-fields' + | 'uploads-multi' + | 'uploads-poly' + | 'uploads-multi-poly' + | 'uploads-restricted' + | 'ui-fields' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; export interface Config { auth: { @@ -224,7 +339,7 @@ export interface ConfigBlockTest { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "localizedTextReference". + * via the `definition` "LocalizedTextReference". */ export interface LocalizedTextReference { text?: string | null; @@ -234,7 +349,7 @@ export interface LocalizedTextReference { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "localizedTextReference2". + * via the `definition` "LocalizedTextReference2". */ export interface LocalizedTextReference2 { text?: string | null; @@ -281,18 +396,21 @@ export interface SelectVersionsField { id?: string | null; }[] | null; - blocks?: - | { - hasManyBlocks?: ('a' | 'b' | 'c')[] | null; - id?: string | null; - blockName?: string | null; - blockType: 'block'; - }[] - | null; + blocks?: Block[] | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Block". + */ +export interface Block { + hasManyBlocks?: ('a' | 'b' | 'c')[] | null; + id?: string | null; + blockName?: string | null; + blockType: 'block'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "array-fields". @@ -304,21 +422,7 @@ export interface ArrayField { text: string; anotherText?: string | null; localizedText?: string | null; - richTextField?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richTextField?: LexicalRichText | null; subArray?: | { text?: string | null; @@ -450,127 +554,17 @@ export interface BlockField { | LocalizedSubBlocksBlock | LocalizedTabsBlock )[]; - i18nBlocks?: - | { - text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'textInI18nBlock'; - }[] - | null; - blocksWithLocalizedArray?: - | { - array?: - | { - text?: string | null; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'localizedArray'; - }[] - | null; - blocksWithSimilarConfigs?: - | ( - | { - items?: - | { - title: string; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'block-a'; - } - | { - items?: - | { - title2: string; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'block-b'; - } - | { - group?: { - text?: string | null; - }; - id?: string | null; - blockName?: string | null; - blockType: 'group-block'; - } - )[] - | null; + i18nBlocks?: TextInI18NBlock[] | null; + blocksWithLocalizedArray?: LocalizedArray[] | null; + blocksWithSimilarConfigs?: (BlockA | BlockB | GroupBlock)[] | null; /** * The purpose of this field is to test validateExistingBlockIsIdentical works with similar blocks with group fields */ - blocksWithSimilarGroup?: - | ( - | { - group?: { - text?: string | null; - }; - id?: string | null; - blockName?: string | null; - blockType: 'group-block'; - } - | { - items?: - | { - title2: string; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'block-b'; - } - )[] - | null; - blocksWithMinRows?: - | { - blockTitle?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'blockWithMinRows'; - }[] - | null; - customBlocks?: - | ( - | { - block1Title?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'block-1'; - } - | { - block2Title?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'block-2'; - } - )[] - | null; - relationshipBlocks?: - | { - relationship?: (string | null) | TextField; - id?: string | null; - blockName?: string | null; - blockType: 'relationships'; - }[] - | null; - blockWithLabels?: - | { - text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'text'; - }[] - | null; + blocksWithSimilarGroup?: (GroupBlock | BlockB)[] | null; + blocksWithMinRows?: BlockWithMinRows[] | null; + customBlocks?: (Block1 | Block2)[] | null; + relationshipBlocks?: Relationships[] | null; + blockWithLabels?: Text[] | null; deduplicatedBlocks?: ConfigBlockTest[] | null; deduplicatedBlocks2?: ConfigBlockTest[] | null; localizedReferencesLocalizedBlock?: LocalizedTextReference[] | null; @@ -578,90 +572,14 @@ export interface BlockField { /** * The purpose of this field is to test Block groups. */ - groupedBlocks?: - | ( - | { - text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'blockWithGroupOne'; - } - | { - text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'blockWithGroupTwo'; - } - | { - text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'blockWithLocalizedGroup'; - } - | { - text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'blockWithoutGroup'; - } - )[] - | null; - readOnly?: - | { - title?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'readOnlyBlock'; - }[] - | null; + groupedBlocks?: (BlockWithGroupOne | BlockWithGroupTwo | BlockWithLocalizedGroup | BlockWithoutGroup)[] | null; + readOnly?: ReadOnlyBlock[] | null; /** * Change the value of this field to change the enabled blocks of the blocksWithDynamicFilterOptions field. If it's empty, all blocks are enabled. */ enabledBlocks?: string | null; - blocksWithDynamicFilterOptions?: - | ( - | { - block1Text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'blockOne'; - } - | { - block2Text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'blockTwo'; - } - | { - block3Text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'blockThree'; - } - )[] - | null; - blocksWithFilterOptions?: - | ( - | { - block1Text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'blockFour'; - } - | { - block2Text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'blockFive'; - } - | { - block3Text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'blockSix'; - } - )[] - | null; + blocksWithDynamicFilterOptions?: (BlockOne | BlockTwo | BlockThree)[] | null; + blocksWithFilterOptions?: (BlockFour | BlockFive | BlockSix)[] | null; updatedAt: string; createdAt: string; } @@ -671,21 +589,7 @@ export interface BlockField { */ export interface ContentBlock { text: string; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; id?: string | null; blockName?: string | null; blockType: 'content'; @@ -725,21 +629,21 @@ export interface NumberBlock { * via the `definition` "SubBlocksBlock". */ export interface SubBlocksBlock { - subBlocks?: - | ( - | { - text: string; - id?: string | null; - blockName?: string | null; - blockType: 'textRequired'; - } - | NumberBlock - )[] - | null; + subBlocks?: (TextRequired | NumberBlock)[] | null; id?: string | null; blockName?: string | null; blockType: 'subBlocks'; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TextRequired". + */ +export interface TextRequired { + text: string; + id?: string | null; + blockName?: string | null; + blockType: 'textRequired'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "TabsBlock". @@ -757,21 +661,7 @@ export interface TabsBlock { */ export interface LocalizedContentBlock { text: string; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; id?: string | null; blockName?: string | null; blockType: 'localizedContent'; @@ -811,17 +701,7 @@ export interface LocalizedNumberBlock { * via the `definition` "localizedSubBlocksBlock". */ export interface LocalizedSubBlocksBlock { - subBlocks?: - | ( - | { - text: string; - id?: string | null; - blockName?: string | null; - blockType: 'textRequired'; - } - | NumberBlock - )[] - | null; + subBlocks?: (TextRequired | NumberBlock)[] | null; id?: string | null; blockName?: string | null; blockType: 'localizedSubBlocks'; @@ -837,6 +717,113 @@ export interface LocalizedTabsBlock { blockName?: string | null; blockType: 'localizedTabs'; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TextInI18nBlock". + */ +export interface TextInI18NBlock { + text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'textInI18nBlock'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LocalizedArray". + */ +export interface LocalizedArray { + array?: + | { + text?: string | null; + id?: string | null; + }[] + | null; + id?: string | null; + blockName?: string | null; + blockType: 'localizedArray'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockA". + */ +export interface BlockA { + items?: + | { + title: string; + id?: string | null; + }[] + | null; + id?: string | null; + blockName?: string | null; + blockType: 'block-a'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockB". + */ +export interface BlockB { + items?: + | { + title2: string; + id?: string | null; + }[] + | null; + id?: string | null; + blockName?: string | null; + blockType: 'block-b'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "GroupBlock". + */ +export interface GroupBlock { + group?: { + text?: string | null; + }; + id?: string | null; + blockName?: string | null; + blockType: 'group-block'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockWithMinRows". + */ +export interface BlockWithMinRows { + blockTitle?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockWithMinRows'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Block1". + */ +export interface Block1 { + block1Title?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'block-1'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Block2". + */ +export interface Block2 { + block2Title?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'block-2'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Relationships". + */ +export interface Relationships { + relationship?: (string | null) | TextField; + id?: string | null; + blockName?: string | null; + blockType: 'relationships'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "text-fields". @@ -880,17 +867,140 @@ export interface TextField { id?: string | null; }[] | null; - blocks?: - | { - texts?: string[] | null; - id?: string | null; - blockName?: string | null; - blockType: 'blockWithText'; - }[] - | null; + blocks?: BlockWithText[] | null; updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockWithText". + */ +export interface BlockWithText { + texts?: string[] | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockWithText'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Text". + */ +export interface Text { + text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'text'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockWithGroupOne". + */ +export interface BlockWithGroupOne { + text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockWithGroupOne'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockWithGroupTwo". + */ +export interface BlockWithGroupTwo { + text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockWithGroupTwo'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockWithLocalizedGroup". + */ +export interface BlockWithLocalizedGroup { + text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockWithLocalizedGroup'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockWithoutGroup". + */ +export interface BlockWithoutGroup { + text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockWithoutGroup'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "ReadOnlyBlock". + */ +export interface ReadOnlyBlock { + title?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'readOnlyBlock'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockOne". + */ +export interface BlockOne { + block1Text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockOne'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockTwo". + */ +export interface BlockTwo { + block2Text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockTwo'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockThree". + */ +export interface BlockThree { + block3Text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockThree'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockFour". + */ +export interface BlockFour { + block1Text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockFour'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockFive". + */ +export interface BlockFive { + block2Text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockFive'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockSix". + */ +export interface BlockSix { + block3Text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockSix'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "checkbox-fields". @@ -965,21 +1075,7 @@ export interface ConditionalLogic { customFieldWithHOC?: string | null; customClientFieldWithCondition?: string | null; customServerFieldWithCondition?: string | null; - conditionalRichText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + conditionalRichText?: LexicalRichText | null; userConditional?: string | null; parentGroup?: { enableParentGroupFields?: boolean | null; @@ -1007,24 +1103,8 @@ export interface ConditionalLogic { id?: string | null; }[] | null; - blocksWithConditionalField?: - | { - text?: string | null; - textWithCondition?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'blockWithConditionalField'; - }[] - | null; - blocksWithRadioCondition?: - | { - radioTrigger?: ('show' | 'hide') | null; - conditionalTextField?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'blockWithRadioCondition'; - }[] - | null; + blocksWithConditionalField?: BlockWithConditionalField[] | null; + blocksWithRadioCondition?: BlockWithRadioCondition[] | null; enableTabs?: boolean | null; conditionalTabsField1?: string | null; conditionalTabsField2?: string | null; @@ -1049,6 +1129,28 @@ export interface ConditionalLogic { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockWithConditionalField". + */ +export interface BlockWithConditionalField { + text?: string | null; + textWithCondition?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockWithConditionalField'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockWithRadioCondition". + */ +export interface BlockWithRadioCondition { + radioTrigger?: ('show' | 'hide') | null; + conditionalTextField?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockWithRadioCondition'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "custom-id". @@ -1116,15 +1218,7 @@ export interface DateField { dayAndTimeWithTimezoneRequired_tz: SupportedTimezones; dayAndTimeWithTimezoneReadOnly?: string | null; dayAndTimeWithTimezoneReadOnly_tz?: SupportedTimezones; - timezoneBlocks?: - | { - dayAndTime?: string | null; - dayAndTime_tz?: SupportedTimezones; - id?: string | null; - blockName?: string | null; - blockType: 'dateBlock'; - }[] - | null; + timezoneBlocks?: DateBlock[] | null; timezoneArray?: | { dayAndTime?: string | null; @@ -1153,6 +1247,17 @@ export interface DateField { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "DateBlock". + */ +export interface DateBlock { + dayAndTime?: string | null; + dayAndTime_tz?: SupportedTimezones; + id?: string | null; + blockName?: string | null; + blockType: 'dateBlock'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "email-fields". @@ -1321,22 +1426,8 @@ export interface RowField { no_set_width_within_row_b?: string | null; no_set_width_within_row_c?: string | null; field_20_percent_width_within_row_d?: string | null; - leftColumn?: - | { - leftText?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'leftTextBlock'; - }[] - | null; - rightColumn?: - | { - rightText?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'rightTextBlock'; - }[] - | null; + leftColumn?: LeftTextBlock[] | null; + rightColumn?: RightTextBlock[] | null; arrayLeftColumn?: | { leftArrayChild?: string | null; @@ -1352,6 +1443,26 @@ export interface RowField { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LeftTextBlock". + */ +export interface LeftTextBlock { + leftText?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'leftTextBlock'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "RightTextBlock". + */ +export interface RightTextBlock { + rightText?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'rightTextBlock'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "indexed-fields". @@ -1476,17 +1587,20 @@ export interface NumberField { id?: string | null; }[] | null; - blocks?: - | { - numbers?: number[] | null; - id?: string | null; - blockName?: string | null; - blockType: 'blockWithNumber'; - }[] - | null; + blocks?: BlockWithNumber[] | null; updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockWithNumber". + */ +export interface BlockWithNumber { + numbers?: number[] | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockWithNumber'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "point-fields". @@ -3868,6 +3982,38 @@ export interface CollectionsWidget { }; width: 'full'; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock". + */ +export interface MyBlock { + id: string; + blockType: 'myBlock'; + someText?: string | null; + someTextRequired: string; + radios?: ('option1' | 'option2' | 'option3') | null; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_E99B774E". + */ +export interface LexicalLinkFields_E99B774E { + linkType: 'custom' | 'internal'; + url?: string; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + newTab: boolean; + description?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". @@ -3876,6 +4022,152 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export type SerializedBlockNode = { + type: 'block'; + format: LexicalElementFormat; + version: number; + fields: { id: string; blockName?: string | null } & Omit; +}; +export type SerializedInlineBlockNode = { + type: 'inlineBlock'; + version: number; + fields: { id: string } & Omit; +}; + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + +export interface SerializedHorizontalRuleNode { + type: 'horizontalrule'; + version: number; +} + declare module 'payload' { // @ts-ignore diff --git a/test/folders/payload-types.ts b/test/folders/payload-types.ts index 07f0e62af93..0b5f30c5d68 100644 --- a/test/folders/payload-types.ts +++ b/test/folders/payload-types.ts @@ -64,6 +64,7 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -71,8 +72,9 @@ export interface Config { posts: Post; media: Media; 'translated-labels': TranslatedLabel; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -87,8 +89,9 @@ export interface Config { posts: PostsSelect | PostsSelect; media: MediaSelect | MediaSelect; 'translated-labels': TranslatedLabelsSelect | TranslatedLabelsSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -107,7 +110,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -131,6 +134,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-folders". @@ -212,23 +233,6 @@ export interface TranslatedLabel { updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -254,6 +258,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -280,12 +344,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -295,10 +368,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -379,14 +457,6 @@ export interface TranslatedLabelsSelect { updatedAt?: T; createdAt?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -409,6 +479,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". diff --git a/test/form-state/payload-types.ts b/test/form-state/payload-types.ts index fc00236b29a..70c9002fdeb 100644 --- a/test/form-state/payload-types.ts +++ b/test/form-state/payload-types.ts @@ -64,14 +64,16 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { posts: Post; 'autosave-posts': AutosavePost; conditions: Condition; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -81,8 +83,9 @@ export interface Config { posts: PostsSelect | PostsSelect; 'autosave-posts': AutosavePostsSelect | AutosavePostsSelect; conditions: ConditionsSelect | ConditionsSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -97,7 +100,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -121,6 +124,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts". @@ -134,22 +155,7 @@ export interface Post { * This field should only validate on submit. Try typing "Not allowed" and submitting the form. */ validateUsingEvent?: string | null; - blocks?: - | ( - | { - text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'text'; - } - | { - number?: number | null; - id?: string | null; - blockName?: string | null; - blockType: 'number'; - } - )[] - | null; + blocks?: (Text | Number)[] | null; array?: | { customTextField?: string | null; @@ -177,6 +183,26 @@ export interface Post { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Text". + */ +export interface Text { + text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'text'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Number". + */ +export interface Number { + number?: number | null; + id?: string | null; + blockName?: string | null; + blockType: 'number'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "autosave-posts". @@ -200,23 +226,6 @@ export interface Condition { updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -242,6 +251,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -264,12 +333,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -279,10 +357,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -381,14 +464,6 @@ export interface ConditionsSelect { updatedAt?: T; createdAt?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -411,6 +486,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". diff --git a/test/globals/payload-types.ts b/test/globals/payload-types.ts index 28933bd2cdc..b07cea2ee2d 100644 --- a/test/globals/payload-types.ts +++ b/test/globals/payload-types.ts @@ -64,19 +64,22 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; }; collectionsJoins: {}; collectionsSelect: { - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -100,7 +103,10 @@ export interface Config { 'without-graphql': WithoutGraphqlSelect | WithoutGraphqlSelect; }; locale: 'en' | 'es'; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -124,22 +130,23 @@ export interface UserAuthOperations { password: string; }; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -166,21 +173,91 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". */ export interface PayloadLockedDocument { id: string; - document?: { - relationTo: 'users'; - value: string | User; - } | null; + document?: + | ({ + relationTo: 'users'; + value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -190,10 +267,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -218,14 +300,6 @@ export interface PayloadMigration { updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -248,6 +322,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -408,6 +506,16 @@ export interface WithoutGraphqlSelect { createdAt?: T; globalType?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/graphql-schema-gen/payload-types.ts b/test/graphql-schema-gen/payload-types.ts index 74ce2a6aa5f..58f9de21176 100644 --- a/test/graphql-schema-gen/payload-types.ts +++ b/test/graphql-schema-gen/payload-types.ts @@ -75,14 +75,16 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { collection1: Collection1; collection2: Collection2; 'no-graphql': NoGraphql; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -92,8 +94,9 @@ export interface Config { collection1: Collection1Select | Collection1Select; collection2: Collection2Select | Collection2Select; 'no-graphql': NoGraphqlSelect | NoGraphqlSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -105,7 +108,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -129,6 +135,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "collection1". @@ -198,23 +222,6 @@ export interface NoGraphql { updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -240,6 +247,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -262,12 +329,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -277,10 +353,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -385,14 +466,6 @@ export interface NoGraphqlSelect { updatedAt?: T; createdAt?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -415,6 +488,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -447,6 +544,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/graphql/payload-types.ts b/test/graphql/payload-types.ts index 996899e32f7..3a215569278 100644 --- a/test/graphql/payload-types.ts +++ b/test/graphql/payload-types.ts @@ -64,12 +64,14 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { posts: Post; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -77,8 +79,9 @@ export interface Config { collectionsJoins: {}; collectionsSelect: { posts: PostsSelect | PostsSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -97,7 +100,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -121,6 +124,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts". @@ -130,33 +151,19 @@ export interface Post { title?: string | null; 'hyphenated-name'?: string | null; relationToSelf?: (string | null) | Post; - contentBlockField?: - | { - text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'content'; - }[] - | null; + contentBlockField?: Content[] | null; updatedAt: string; createdAt: string; } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". + * via the `definition` "Content". */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; +export interface Content { + text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'content'; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -183,6 +190,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -197,12 +264,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -212,10 +288,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -262,14 +343,6 @@ export interface PostsSelect { updatedAt?: T; createdAt?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -292,6 +365,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". diff --git a/test/hierarchy/payload-types.ts b/test/hierarchy/payload-types.ts index 66de7b56e49..8b4af7eed82 100644 --- a/test/hierarchy/payload-types.ts +++ b/test/hierarchy/payload-types.ts @@ -64,6 +64,7 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -74,8 +75,9 @@ export interface Config { pages: Page; products: Product; regions: Region; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -89,8 +91,9 @@ export interface Config { pages: PagesSelect | PagesSelect; products: ProductsSelect | ProductsSelect; regions: RegionsSelect | RegionsSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -105,7 +108,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -129,6 +132,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "categories". @@ -228,23 +249,6 @@ export interface Region { _h_slugPath?: string | null; _h_titlePath?: string | null; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -270,6 +274,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -308,12 +372,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -323,10 +396,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -443,14 +521,6 @@ export interface RegionsSelect { _h_slugPath?: T; _h_titlePath?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -473,6 +543,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". diff --git a/test/hooks/payload-types.ts b/test/hooks/payload-types.ts index 228e023094a..9fc2c9e80b9 100644 --- a/test/hooks/payload-types.ts +++ b/test/hooks/payload-types.ts @@ -60,10 +60,62 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_6C4CCB8D". + */ +export type LexicalNodes_6C4CCB8D = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> + | SerializedHorizontalRuleNode + | { + type: 'upload'; + /** + * Lexical's internal serialization version for this node type. + */ + version: number; + [k: string]: unknown; + } + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'beforeOperation' + | 'before-change-hooks' + | 'before-validate' + | 'afterOperation' + | 'context-hooks' + | 'transforms' + | 'hooks' + | 'nested-after-read-hooks' + | 'nested-after-change-hooks' + | 'chaining-hooks' + | 'relations' + | 'hooks-users' + | 'data-hooks' + | 'before-delete-hooks' + | 'before-delete-2-hooks' + | 'value-hooks' + | 'after-read' + | 'override-access-hooks' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; export interface Config { auth: { 'hooks-users': HooksUserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -84,6 +136,8 @@ export interface Config { 'before-delete-2-hooks': BeforeDelete2Hook; 'value-hooks': ValueHook; 'after-read': AfterRead; + 'override-access-hooks': OverrideAccessHook; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -108,6 +162,8 @@ export interface Config { 'before-delete-2-hooks': BeforeDelete2HooksSelect | BeforeDelete2HooksSelect; 'value-hooks': ValueHooksSelect | ValueHooksSelect; 'after-read': AfterReadSelect | AfterReadSelect; + 'override-access-hooks': OverrideAccessHooksSelect | OverrideAccessHooksSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -124,7 +180,10 @@ export interface Config { 'data-hooks-global': DataHooksGlobalSelect | DataHooksGlobalSelect; }; locale: null; - user: HooksUser; + widgets: { + collections: CollectionsWidget; + }; + user: HooksUser | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -148,6 +207,24 @@ export interface HooksUserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "beforeOperation". @@ -286,21 +363,7 @@ export interface NestedAfterChangeHook { }[] | null; }; - lexical?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + lexical?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -399,6 +462,63 @@ export interface AfterRead { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "override-access-hooks". + */ +export interface OverrideAccessHook { + id: string; + title?: string | null; + beforeReadCalled?: boolean | null; + beforeReadOverrideAccess?: boolean | null; + afterReadCalled?: boolean | null; + afterReadOverrideAccess?: boolean | null; + updatedAt: string; + createdAt: string; +} +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | HooksUser; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -490,12 +610,25 @@ export interface PayloadLockedDocument { | ({ relationTo: 'after-read'; value: string | AfterRead; + } | null) + | ({ + relationTo: 'override-access-hooks'; + value: string | OverrideAccessHook; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'hooks-users'; - value: string | HooksUser; - }; + user: + | { + relationTo: 'hooks-users'; + value: string | HooksUser; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -505,10 +638,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'hooks-users'; - value: string | HooksUser; - }; + user: + | { + relationTo: 'hooks-users'; + value: string | HooksUser; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -749,6 +887,35 @@ export interface AfterReadSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "override-access-hooks_select". + */ +export interface OverrideAccessHooksSelect { + title?: T; + beforeReadCalled?: T; + beforeReadOverrideAccess?: T; + afterReadCalled?: T; + afterReadOverrideAccess?: T; + updatedAt?: T; + createdAt?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -817,6 +984,56 @@ export interface DataHooksGlobalSelect { createdAt?: T; globalType?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "NestedLinkBlock". + */ +export interface NestedLinkBlock { + nestedRelationship?: (string | null) | Relation; + id?: string | null; + blockName?: string | null; + blockType: 'nestedLinkBlock'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "NestedBlock". + */ +export interface NestedBlock { + id: string; + blockType: 'nestedBlock'; + nestedAfterChange?: string | null; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_6C4CCB8D". + */ +export interface LexicalLinkFields_6C4CCB8D { + linkBlocks?: NestedLinkBlock[] | null; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". @@ -825,6 +1042,152 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export type SerializedBlockNode = { + type: 'block'; + format: LexicalElementFormat; + version: number; + fields: { id: string; blockName?: string | null } & Omit; +}; +export type SerializedInlineBlockNode = { + type: 'inlineBlock'; + version: number; + fields: { id: string } & Omit; +}; + +export interface SerializedHorizontalRuleNode { + type: 'horizontalrule'; + version: number; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + declare module 'payload' { // @ts-ignore diff --git a/test/i18n/payload-types.ts b/test/i18n/payload-types.ts index 649178bce73..8755da48386 100644 --- a/test/i18n/payload-types.ts +++ b/test/i18n/payload-types.ts @@ -64,12 +64,14 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { collection1: Collection1; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -77,8 +79,9 @@ export interface Config { collectionsJoins: {}; collectionsSelect: { collection1: Collection1Select | Collection1Select; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -97,7 +100,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -121,6 +124,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "collection1". @@ -136,23 +157,6 @@ export interface Collection1 { updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -178,6 +182,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -192,12 +256,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -207,10 +280,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -249,14 +327,6 @@ export interface Collection1Select { updatedAt?: T; createdAt?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -279,6 +349,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". diff --git a/test/joins/payload-types.ts b/test/joins/payload-types.ts index 97cf7723015..e95d1c4dc2a 100644 --- a/test/joins/payload-types.ts +++ b/test/joins/payload-types.ts @@ -64,6 +64,7 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -93,6 +94,7 @@ export interface Config { 'example-posts': ExamplePost; folderPoly1: FolderPoly1; folderPoly2: FolderPoly2; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -184,6 +186,7 @@ export interface Config { 'example-posts': ExamplePostsSelect | ExamplePostsSelect; folderPoly1: FolderPoly1Select | FolderPoly1Select; folderPoly2: FolderPoly2Select | FolderPoly2Select; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -199,7 +202,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -223,6 +226,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -335,14 +356,7 @@ export interface Post { id?: string | null; }[] | null; - blocks?: - | { - category?: (string | null) | Category; - id?: string | null; - blockName?: string | null; - blockType: 'block'; - }[] - | null; + blocks?: Block[] | null; first?: { tabText?: string | null; }; @@ -570,6 +584,16 @@ export interface Singular { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Block". + */ +export interface Block { + category?: (string | null) | Category; + id?: string | null; + blockName?: string | null; + blockType: 'block'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "self-joins". @@ -837,6 +861,49 @@ export interface FolderPoly2 { updatedAt: string; createdAt: string; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -964,12 +1031,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'folderPoly2'; value: string | FolderPoly2; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -979,10 +1055,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -1380,6 +1461,22 @@ export interface FolderPoly2Select { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". diff --git a/test/kv/payload-types.ts b/test/kv/payload-types.ts index cb0d502bdc9..883393fc3c6 100644 --- a/test/kv/payload-types.ts +++ b/test/kv/payload-types.ts @@ -64,19 +64,22 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; }; collectionsJoins: {}; collectionsSelect: { - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -88,7 +91,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -112,22 +118,23 @@ export interface UserAuthOperations { password: string; }; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -154,21 +161,91 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". */ export interface PayloadLockedDocument { id: string; - document?: { - relationTo: 'users'; - value: string | User; - } | null; + document?: + | ({ + relationTo: 'users'; + value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -178,10 +255,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -206,14 +288,6 @@ export interface PayloadMigration { updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -236,6 +310,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -268,6 +366,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/lexical-mdx/payload-types.ts b/test/lexical-mdx/payload-types.ts index bf183788fe5..ccf15959bdd 100644 --- a/test/lexical-mdx/payload-types.ts +++ b/test/lexical-mdx/payload-types.ts @@ -60,18 +60,81 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_D0137BA6". + */ +export type LexicalNodes_D0137BA6 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode<{blockType: string}> + | SerializedInlineBlockNode + | SerializedHorizontalRuleNode + | SerializedUploadNode<'media'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'posts' + | 'simple' + | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_E1F445FF". + */ +export type LexicalNodes_E1F445FF = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode + | SerializedHorizontalRuleNode + | SerializedUploadNode<'media'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'posts' + | 'simple' + | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { posts: Post; simple: Simple; media: Media; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -81,8 +144,9 @@ export interface Config { posts: PostsSelect | PostsSelect; simple: SimpleSelect | SimpleSelect; media: MediaSelect | MediaSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -94,7 +158,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -118,6 +185,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts". @@ -132,36 +217,8 @@ export interface Post { id?: string | null; }[] | null; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - richTextUnconverted?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; + richTextUnconverted?: LexicalRichText | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -220,23 +277,6 @@ export interface Media { }; }; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -262,6 +302,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -284,12 +384,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -299,10 +408,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -406,14 +520,6 @@ export interface MediaSelect { }; }; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -436,6 +542,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -468,11 +598,97 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "InlineCode". + */ +export interface InlineCode { + id: string; + blockType: 'InlineCode'; + code?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Banner". + */ +export interface Banner { + id: string; + blockType: 'Banner'; + type?: ('success' | 'info' | 'warning') | null; + content?: LexicalRichText | null; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Code". + */ +export interface Code { + id: string; + blockType: 'Code'; + language?: ('ts' | 'plaintext' | 'tsx' | 'js' | 'jsx') | null; + code?: string | null; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "PackageInstallOptions". + */ +export interface PackageInstallOptions { + id: string; + blockType: 'PackageInstallOptions'; + packageId?: string | null; + global?: boolean | null; + someObject?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + update?: boolean | null; + uniqueId?: string | null; + someNestedObject?: string | null; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TextContainerNoTrim". + */ +export interface TextContainerNoTrim { + id: string; + blockType: 'TextContainerNoTrim'; + text?: string | null; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TextContainer". + */ +export interface TextContainer { + id: string; + blockType: 'TextContainer'; + text?: string | null; + blockName?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "RestExamplesBlock". */ export interface RestExamplesBlock { + id: string; + blockType: 'restExamples'; data?: | { operation?: string | null; @@ -504,9 +720,7 @@ export interface RestExamplesBlock { id?: string | null; }[] | null; - id?: string | null; blockName?: string | null; - blockType: 'restExamples'; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -516,6 +730,173 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export type SerializedBlockNode = { + type: 'block'; + format: LexicalElementFormat; + version: number; + fields: { id: string; blockName?: string | null } & Omit; +}; +export type SerializedInlineBlockNode = { + type: 'inlineBlock'; + version: number; + fields: { id: string } & Omit; +}; + +export interface SerializedHorizontalRuleNode { + type: 'horizontalrule'; + version: number; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + +export interface SerializedTableNode extends SerializedLexicalElementBase { + type: 'table'; + colWidths?: number[]; + frozenColumnCount?: number; + frozenRowCount?: number; + rowStriping?: boolean; +} +export interface SerializedTableRowNode extends SerializedLexicalElementBase { + type: 'tablerow'; + height?: number; +} +export interface SerializedTableCellNode extends SerializedLexicalElementBase { + type: 'tablecell'; + backgroundColor?: string | null; + colSpan?: number; + headerState: number; + rowSpan?: number; + verticalAlign?: string; + width?: number; +} + declare module 'payload' { // @ts-ignore diff --git a/test/live-preview/payload-types.ts b/test/live-preview/payload-types.ts index a0c25dddf68..738f43d9de9 100644 --- a/test/live-preview/payload-types.ts +++ b/test/live-preview/payload-types.ts @@ -60,10 +60,119 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_A6D73F5A". + */ +export type LexicalNodes_A6D73F5A = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedHorizontalRuleNode + | SerializedUploadNode<'media'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'users' + | 'pages' + | 'posts' + | 'ssr' + | 'ssr-autosave' + | 'tenants' + | 'categories' + | 'collection-level-config' + | 'static-url' + | 'custom-live-preview' + | 'conditional-url' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_AB3326D2". + */ +export type LexicalNodes_AB3326D2 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> + | SerializedHorizontalRuleNode + | SerializedUploadNode<'media'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'users' + | 'pages' + | 'posts' + | 'ssr' + | 'ssr-autosave' + | 'tenants' + | 'categories' + | 'collection-level-config' + | 'static-url' + | 'custom-live-preview' + | 'conditional-url' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_918BCD54". + */ +export type LexicalNodes_918BCD54 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> + | SerializedHeadingNode + | SerializedUploadNode<'media', LexicalUploadFields_1AB4670B> + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedRelationshipNode< + | 'users' + | 'pages' + | 'posts' + | 'ssr' + | 'ssr-autosave' + | 'tenants' + | 'categories' + | 'collection-level-config' + | 'static-url' + | 'custom-live-preview' + | 'conditional-url' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + >; export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: { mediaBlock: MediaBlock; @@ -81,6 +190,7 @@ export interface Config { 'static-url': StaticUrl; 'custom-live-preview': CustomLivePreview; 'conditional-url': ConditionalUrl; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -100,6 +210,7 @@ export interface Config { 'static-url': StaticUrlSelect | StaticUrlSelect; 'custom-live-preview': CustomLivePreviewSelect | CustomLivePreviewSelect; 'conditional-url': ConditionalUrlSelect | ConditionalUrlSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -121,7 +232,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -145,9 +256,27 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "mediaBlock". + * via the `definition` "MediaBlock". */ export interface MediaBlock { invertBackground?: boolean | null; @@ -214,206 +343,18 @@ export interface Page { title: string; hero: { type: 'none' | 'highImpact' | 'lowImpact'; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; media?: (string | null) | Media; }; - layout?: - | ( - | { - invertBackground?: boolean | null; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - links?: - | { - link: { - type?: ('reference' | 'custom') | null; - newTab?: boolean | null; - reference?: - | ({ - relationTo: 'posts'; - value: string | Post; - } | null) - | ({ - relationTo: 'pages'; - value: string | Page; - } | null); - url?: string | null; - label: string; - /** - * Choose how the link should be rendered. - */ - appearance?: ('primary' | 'secondary') | null; - }; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'cta'; - } - | { - invertBackground?: boolean | null; - columns?: - | { - size?: ('oneThird' | 'half' | 'twoThirds' | 'full') | null; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - enableLink?: boolean | null; - link?: { - type?: ('reference' | 'custom') | null; - newTab?: boolean | null; - reference?: - | ({ - relationTo: 'posts'; - value: string | Post; - } | null) - | ({ - relationTo: 'pages'; - value: string | Page; - } | null); - url?: string | null; - label: string; - /** - * Choose how the link should be rendered. - */ - appearance?: ('default' | 'primary' | 'secondary') | null; - }; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'content'; - } - | { - invertBackground?: boolean | null; - position?: ('default' | 'fullscreen') | null; - media: string | Media; - id?: string | null; - blockName?: string | null; - blockType: 'mediaBlock'; - } - | { - introContent?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - populateBy?: ('collection' | 'selection') | null; - relationTo?: 'posts' | null; - categories?: (string | Category)[] | null; - limit?: number | null; - selectedDocs?: - | { - relationTo: 'posts'; - value: string | Post; - }[] - | null; - /** - * This field is auto-populated after-read - */ - populatedDocs?: - | { - relationTo: 'posts'; - value: string | Post; - }[] - | null; - /** - * This field is auto-populated after-read - */ - populatedDocsTotal?: number | null; - id?: string | null; - blockName?: string | null; - blockType: 'archive'; - } - )[] - | null; + layout?: (Cta | Content | MediaBlock | Archive)[] | null; /** * A number field for visual comparison with toolbar size inputs */ testNumber?: number | null; localizedTitle?: string | null; relationToLocalized?: (string | null) | Post; - richTextLexical?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - richTextLexicalLocalized?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richTextLexical?: LexicalRichText | null; + richTextLexicalLocalized?: LexicalRichText | null; relationshipAsUpload?: (string | null) | Media; relationshipMonoHasOne?: (string | null) | Post; relationshipMonoHasMany?: (string | Post)[] | null; @@ -430,21 +371,7 @@ export interface Page { arrayOfRelationships?: | { uploadInArray?: (string | null) | Media; - richTextInArray?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richTextInArray?: LexicalRichText | null; relationshipInArrayMonoHasOne?: (string | null) | Post; relationshipInArrayMonoHasMany?: (string | Post)[] | null; relationshipInArrayPolyHasOne?: { @@ -482,6 +409,41 @@ export interface Tenant { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Cta". + */ +export interface Cta { + invertBackground?: boolean | null; + richText?: LexicalRichText | null; + links?: + | { + link: { + type?: ('reference' | 'custom') | null; + newTab?: boolean | null; + reference?: + | ({ + relationTo: 'posts'; + value: string | Post; + } | null) + | ({ + relationTo: 'pages'; + value: string | Page; + } | null); + url?: string | null; + label: string; + /** + * Choose how the link should be rendered. + */ + appearance?: ('primary' | 'secondary') | null; + }; + id?: string | null; + }[] + | null; + id?: string | null; + blockName?: string | null; + blockType: 'cta'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts". @@ -493,170 +455,10 @@ export interface Post { title: string; hero: { type: 'none' | 'highImpact' | 'lowImpact'; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; media?: (string | null) | Media; }; - layout?: - | ( - | { - invertBackground?: boolean | null; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - links?: - | { - link: { - type?: ('reference' | 'custom') | null; - newTab?: boolean | null; - reference?: - | ({ - relationTo: 'posts'; - value: string | Post; - } | null) - | ({ - relationTo: 'pages'; - value: string | Page; - } | null); - url?: string | null; - label: string; - /** - * Choose how the link should be rendered. - */ - appearance?: ('primary' | 'secondary') | null; - }; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'cta'; - } - | { - invertBackground?: boolean | null; - columns?: - | { - size?: ('oneThird' | 'half' | 'twoThirds' | 'full') | null; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - enableLink?: boolean | null; - link?: { - type?: ('reference' | 'custom') | null; - newTab?: boolean | null; - reference?: - | ({ - relationTo: 'posts'; - value: string | Post; - } | null) - | ({ - relationTo: 'pages'; - value: string | Page; - } | null); - url?: string | null; - label: string; - /** - * Choose how the link should be rendered. - */ - appearance?: ('default' | 'primary' | 'secondary') | null; - }; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'content'; - } - | { - invertBackground?: boolean | null; - position?: ('default' | 'fullscreen') | null; - media: string | Media; - id?: string | null; - blockName?: string | null; - blockType: 'mediaBlock'; - } - | { - introContent?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - populateBy?: ('collection' | 'selection') | null; - relationTo?: 'posts' | null; - categories?: (string | Category)[] | null; - limit?: number | null; - selectedDocs?: - | { - relationTo: 'posts'; - value: string | Post; - }[] - | null; - /** - * This field is auto-populated after-read - */ - populatedDocs?: - | { - relationTo: 'posts'; - value: string | Post; - }[] - | null; - /** - * This field is auto-populated after-read - */ - populatedDocsTotal?: number | null; - id?: string | null; - blockName?: string | null; - blockType: 'archive'; - } - )[] - | null; + layout?: (Cta | Content | MediaBlock | Archive)[] | null; relatedPosts?: (string | Post)[] | null; localizedTitle?: string | null; meta?: { @@ -668,6 +470,76 @@ export interface Post { createdAt: string; deletedAt?: string | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Content". + */ +export interface Content { + invertBackground?: boolean | null; + columns?: + | { + size?: ('oneThird' | 'half' | 'twoThirds' | 'full') | null; + richText?: LexicalRichText | null; + enableLink?: boolean | null; + link?: { + type?: ('reference' | 'custom') | null; + newTab?: boolean | null; + reference?: + | ({ + relationTo: 'posts'; + value: string | Post; + } | null) + | ({ + relationTo: 'pages'; + value: string | Page; + } | null); + url?: string | null; + label: string; + /** + * Choose how the link should be rendered. + */ + appearance?: ('default' | 'primary' | 'secondary') | null; + }; + id?: string | null; + }[] + | null; + id?: string | null; + blockName?: string | null; + blockType: 'content'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Archive". + */ +export interface Archive { + introContent?: LexicalRichText | null; + populateBy?: ('collection' | 'selection') | null; + relationTo?: 'posts' | null; + categories?: (string | Category)[] | null; + limit?: number | null; + selectedDocs?: + | { + relationTo: 'posts'; + value: string | Post; + }[] + | null; + /** + * This field is auto-populated after-read + */ + populatedDocs?: + | { + relationTo: 'posts'; + value: string | Post; + }[] + | null; + /** + * This field is auto-populated after-read + */ + populatedDocsTotal?: number | null; + id?: string | null; + blockName?: string | null; + blockType: 'archive'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "categories". @@ -691,170 +563,10 @@ export interface Ssr { title: string; hero: { type: 'none' | 'highImpact' | 'lowImpact'; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; media?: (string | null) | Media; }; - layout?: - | ( - | { - invertBackground?: boolean | null; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - links?: - | { - link: { - type?: ('reference' | 'custom') | null; - newTab?: boolean | null; - reference?: - | ({ - relationTo: 'posts'; - value: string | Post; - } | null) - | ({ - relationTo: 'pages'; - value: string | Page; - } | null); - url?: string | null; - label: string; - /** - * Choose how the link should be rendered. - */ - appearance?: ('primary' | 'secondary') | null; - }; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'cta'; - } - | { - invertBackground?: boolean | null; - columns?: - | { - size?: ('oneThird' | 'half' | 'twoThirds' | 'full') | null; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - enableLink?: boolean | null; - link?: { - type?: ('reference' | 'custom') | null; - newTab?: boolean | null; - reference?: - | ({ - relationTo: 'posts'; - value: string | Post; - } | null) - | ({ - relationTo: 'pages'; - value: string | Page; - } | null); - url?: string | null; - label: string; - /** - * Choose how the link should be rendered. - */ - appearance?: ('default' | 'primary' | 'secondary') | null; - }; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'content'; - } - | { - invertBackground?: boolean | null; - position?: ('default' | 'fullscreen') | null; - media: string | Media; - id?: string | null; - blockName?: string | null; - blockType: 'mediaBlock'; - } - | { - introContent?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - populateBy?: ('collection' | 'selection') | null; - relationTo?: 'posts' | null; - categories?: (string | Category)[] | null; - limit?: number | null; - selectedDocs?: - | { - relationTo: 'posts'; - value: string | Post; - }[] - | null; - /** - * This field is auto-populated after-read - */ - populatedDocs?: - | { - relationTo: 'posts'; - value: string | Post; - }[] - | null; - /** - * This field is auto-populated after-read - */ - populatedDocsTotal?: number | null; - id?: string | null; - blockName?: string | null; - blockType: 'archive'; - } - )[] - | null; + layout?: (Cta | Content | MediaBlock | Archive)[] | null; meta?: { title?: string | null; description?: string | null; @@ -876,170 +588,10 @@ export interface SsrAutosave { title: string; hero: { type: 'none' | 'highImpact' | 'lowImpact'; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; media?: (string | null) | Media; }; - layout?: - | ( - | { - invertBackground?: boolean | null; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - links?: - | { - link: { - type?: ('reference' | 'custom') | null; - newTab?: boolean | null; - reference?: - | ({ - relationTo: 'posts'; - value: string | Post; - } | null) - | ({ - relationTo: 'pages'; - value: string | Page; - } | null); - url?: string | null; - label: string; - /** - * Choose how the link should be rendered. - */ - appearance?: ('primary' | 'secondary') | null; - }; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'cta'; - } - | { - invertBackground?: boolean | null; - columns?: - | { - size?: ('oneThird' | 'half' | 'twoThirds' | 'full') | null; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - enableLink?: boolean | null; - link?: { - type?: ('reference' | 'custom') | null; - newTab?: boolean | null; - reference?: - | ({ - relationTo: 'posts'; - value: string | Post; - } | null) - | ({ - relationTo: 'pages'; - value: string | Page; - } | null); - url?: string | null; - label: string; - /** - * Choose how the link should be rendered. - */ - appearance?: ('default' | 'primary' | 'secondary') | null; - }; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'content'; - } - | { - invertBackground?: boolean | null; - position?: ('default' | 'fullscreen') | null; - media: string | Media; - id?: string | null; - blockName?: string | null; - blockType: 'mediaBlock'; - } - | { - introContent?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - populateBy?: ('collection' | 'selection') | null; - relationTo?: 'posts' | null; - categories?: (string | Category)[] | null; - limit?: number | null; - selectedDocs?: - | { - relationTo: 'posts'; - value: string | Post; - }[] - | null; - /** - * This field is auto-populated after-read - */ - populatedDocs?: - | { - relationTo: 'posts'; - value: string | Post; - }[] - | null; - /** - * This field is auto-populated after-read - */ - populatedDocsTotal?: number | null; - id?: string | null; - blockName?: string | null; - blockType: 'archive'; - } - )[] - | null; + layout?: (Cta | Content | MediaBlock | Archive)[] | null; meta?: { title?: string | null; description?: string | null; @@ -1082,170 +634,10 @@ export interface CustomLivePreview { title: string; hero: { type: 'none' | 'highImpact' | 'lowImpact'; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; media?: (string | null) | Media; }; - layout?: - | ( - | { - invertBackground?: boolean | null; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - links?: - | { - link: { - type?: ('reference' | 'custom') | null; - newTab?: boolean | null; - reference?: - | ({ - relationTo: 'posts'; - value: string | Post; - } | null) - | ({ - relationTo: 'pages'; - value: string | Page; - } | null); - url?: string | null; - label: string; - /** - * Choose how the link should be rendered. - */ - appearance?: ('primary' | 'secondary') | null; - }; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'cta'; - } - | { - invertBackground?: boolean | null; - columns?: - | { - size?: ('oneThird' | 'half' | 'twoThirds' | 'full') | null; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - enableLink?: boolean | null; - link?: { - type?: ('reference' | 'custom') | null; - newTab?: boolean | null; - reference?: - | ({ - relationTo: 'posts'; - value: string | Post; - } | null) - | ({ - relationTo: 'pages'; - value: string | Page; - } | null); - url?: string | null; - label: string; - /** - * Choose how the link should be rendered. - */ - appearance?: ('default' | 'primary' | 'secondary') | null; - }; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'content'; - } - | { - invertBackground?: boolean | null; - position?: ('default' | 'fullscreen') | null; - media: string | Media; - id?: string | null; - blockName?: string | null; - blockType: 'mediaBlock'; - } - | { - introContent?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - populateBy?: ('collection' | 'selection') | null; - relationTo?: 'posts' | null; - categories?: (string | Category)[] | null; - limit?: number | null; - selectedDocs?: - | { - relationTo: 'posts'; - value: string | Post; - }[] - | null; - /** - * This field is auto-populated after-read - */ - populatedDocs?: - | { - relationTo: 'posts'; - value: string | Post; - }[] - | null; - /** - * This field is auto-populated after-read - */ - populatedDocsTotal?: number | null; - id?: string | null; - blockName?: string | null; - blockType: 'archive'; - } - )[] - | null; + layout?: (Cta | Content | MediaBlock | Archive)[] | null; meta?: { title?: string | null; description?: string | null; @@ -1265,6 +657,49 @@ export interface ConditionalUrl { updatedAt: string; createdAt: string; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -1336,12 +771,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'conditional-url'; value: string | ConditionalUrl; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -1351,10 +795,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -1996,6 +1445,22 @@ export interface ConditionalUrlSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -2160,6 +1625,59 @@ export interface CollectionsWidget { }; width: 'full'; } +/** + * Multiple blocks resolve to the `MediaBlock` interface with different fields, so a content hash is appended to keep the generated types stable and unambiguous. Set a unique `interfaceName` on the block to choose the name yourself. See https://payloadcms.com/docs/typescript/generating-types#block-interface-name-collisions + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MediaBlock_1EDC4A89". + */ +export interface MediaBlock_1EDC4A89 { + id: string; + blockType: 'mediaBlock'; + invertBackground?: boolean | null; + position?: ('default' | 'fullscreen') | null; + media: string | Media; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock". + */ +export interface MyBlock { + id: string; + blockType: 'myBlock'; + someText?: string | null; + someTextRequired: string; + radios?: ('option1' | 'option2' | 'option3') | null; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalUploadFields_1AB4670B". + */ +export interface LexicalUploadFields_1AB4670B { + alt?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_918BCD54". + */ +export interface LexicalLinkFields_918BCD54 { + linkType: 'custom' | 'internal'; + url?: string; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + newTab: boolean; + description?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". @@ -2168,6 +1686,152 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export interface SerializedHorizontalRuleNode { + type: 'horizontalrule'; + version: number; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + +export type SerializedBlockNode = { + type: 'block'; + format: LexicalElementFormat; + version: number; + fields: { id: string; blockName?: string | null } & Omit; +}; +export type SerializedInlineBlockNode = { + type: 'inlineBlock'; + version: number; + fields: { id: string } & Omit; +}; + declare module 'payload' { // @ts-ignore diff --git a/test/localization-rtl/payload-types.ts b/test/localization-rtl/payload-types.ts index 2aa3fc94e16..43c7f566871 100644 --- a/test/localization-rtl/payload-types.ts +++ b/test/localization-rtl/payload-types.ts @@ -60,15 +60,51 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_2C59E551". + */ +export type LexicalNodes_2C59E551 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> + | SerializedHeadingNode + | { + type: 'upload'; + /** + * Lexical's internal serialization version for this node type. + */ + version: number; + [k: string]: unknown; + } + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedRelationshipNode< + | 'users' + | 'posts' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + >; export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { users: User; posts: Post; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -78,6 +114,7 @@ export interface Config { collectionsSelect: { users: UsersSelect | UsersSelect; posts: PostsSelect | PostsSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -90,7 +127,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: 'en' | 'ar'; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -114,6 +154,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -149,23 +207,52 @@ export interface Post { id: string; title?: string | null; description?: string | null; - content?: { - root: { - type: string; - children: { - type: any; - version: number; + content?: LexicalRichText | null; + updatedAt: string; + createdAt: string; +} +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + } + | unknown[] + | string + | number + | boolean + | null; updatedAt: string; createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -198,12 +285,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'posts'; value: string | Post; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -213,10 +309,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -274,6 +375,22 @@ export interface PostsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -314,6 +431,48 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock". + */ +export interface MyBlock { + id: string; + blockType: 'myBlock'; + someText?: string | null; + someTextRequired: string; + radios?: ('option1' | 'option2' | 'option3') | null; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_2C59E551". + */ +export interface LexicalLinkFields_2C59E551 { + linkType: 'custom' | 'internal'; + url?: string; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + newTab: boolean; + description?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". @@ -322,6 +481,147 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export type SerializedBlockNode = { + type: 'block'; + format: LexicalElementFormat; + version: number; + fields: { id: string; blockName?: string | null } & Omit; +}; +export type SerializedInlineBlockNode = { + type: 'inlineBlock'; + version: number; + fields: { id: string } & Omit; +}; + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + declare module 'payload' { // @ts-ignore diff --git a/test/localization/payload-types.ts b/test/localization/payload-types.ts index 8c1b04b3ae6..8371139f6d7 100644 --- a/test/localization/payload-types.ts +++ b/test/localization/payload-types.ts @@ -60,10 +60,65 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_B43B745B". + */ +export type LexicalNodes_B43B745B = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedHorizontalRuleNode + | { + type: 'upload'; + /** + * Lexical's internal serialization version for this node type. + */ + version: number; + [k: string]: unknown; + } + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'richText' + | 'blocks-fields' + | 'nested-arrays' + | 'nested-field-tables' + | 'localized-drafts' + | 'localized-date-fields' + | 'all-fields-localized' + | 'users' + | 'localized-posts' + | 'no-localized-fields' + | 'array-fields' + | 'localized-required' + | 'with-localized-relationship' + | 'relationship-localized' + | 'cannot-create-default-locale' + | 'locale-restricted' + | 'nested' + | 'groups' + | 'tabs' + | 'localized-sort' + | 'blocks-same-name' + | 'localized-within-localized' + | 'array-with-fallback-fields' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -90,6 +145,7 @@ export interface Config { 'blocks-same-name': BlocksSameName; 'localized-within-localized': LocalizedWithinLocalized; 'array-with-fallback-fields': ArrayWithFallbackField; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -120,6 +176,7 @@ export interface Config { 'blocks-same-name': BlocksSameNameSelect | BlocksSameNameSelect; 'localized-within-localized': LocalizedWithinLocalizedSelect | LocalizedWithinLocalizedSelect; 'array-with-fallback-fields': ArrayWithFallbackFieldsSelect | ArrayWithFallbackFieldsSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -148,7 +205,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -172,27 +229,31 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "richText". */ export interface RichText { id: string; - lexical?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + lexical?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -203,41 +264,50 @@ export interface RichText { export interface BlocksField { id: string; title?: string | null; - tabContent?: - | { - text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'blockInsideTab'; - }[] - | null; - content?: + tabContent?: BlockInsideTab[] | null; + content?: BlockInsideBlock[] | null; + updatedAt: string; + createdAt: string; + _status?: ('draft' | 'published') | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockInsideTab". + */ +export interface BlockInsideTab { + text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockInsideTab'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockInsideBlock". + */ +export interface BlockInsideBlock { + text?: string | null; + content?: TextBlock[] | null; + array?: | { - text?: string | null; - content?: - | { - text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'textBlock'; - }[] - | null; - array?: - | { - link?: { - label?: string | null; - }; - id?: string | null; - }[] - | null; + link?: { + label?: string | null; + }; id?: string | null; - blockName?: string | null; - blockType: 'blockInsideBlock'; }[] | null; - updatedAt: string; - createdAt: string; - _status?: ('draft' | 'published') | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockInsideBlock'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TextBlock". + */ +export interface TextBlock { + text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'textBlock'; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -247,17 +317,7 @@ export interface NestedArray { id: string; arrayWithBlocks?: | { - blocksWithinArray?: - | { - relationWithinBlock?: (string | null) | LocalizedPost; - myGroup?: { - text?: string | null; - }; - id?: string | null; - blockName?: string | null; - blockType: 'someBlock'; - }[] - | null; + blocksWithinArray?: SomeBlock[] | null; id?: string | null; }[] | null; @@ -271,6 +331,19 @@ export interface NestedArray { createdAt: string; _status?: ('draft' | 'published') | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "SomeBlock". + */ +export interface SomeBlock { + relationWithinBlock?: (string | null) | LocalizedPost; + myGroup?: { + text?: string | null; + }; + id?: string | null; + blockName?: string | null; + blockType: 'someBlock'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "localized-posts". @@ -314,35 +387,41 @@ export interface NestedFieldTable { id?: string | null; }[] | null; - blocks?: + blocks?: Block[] | null; + updatedAt: string; + createdAt: string; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Block". + */ +export interface Block { + nestedBlocks?: Content[] | null; + array?: | { - nestedBlocks?: - | { - relation?: { - relationTo: 'localized-posts'; - value: string | LocalizedPost; - } | null; - id?: string | null; - blockName?: string | null; - blockType: 'content'; - }[] - | null; - array?: - | { - relation?: { - relationTo: 'localized-posts'; - value: string | LocalizedPost; - } | null; - id?: string | null; - }[] - | null; + relation?: { + relationTo: 'localized-posts'; + value: string | LocalizedPost; + } | null; id?: string | null; - blockName?: string | null; - blockType: 'block'; }[] | null; - updatedAt: string; - createdAt: string; + id?: string | null; + blockName?: string | null; + blockType: 'block'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Content". + */ +export interface Content { + relation?: { + relationTo: 'localized-posts'; + value: string | LocalizedPost; + } | null; + id?: string | null; + blockName?: string | null; + blockType: 'content'; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -411,27 +490,7 @@ export interface AllFieldsLocalized { id?: string | null; }[] | null; - localizedBlocks?: - | ( - | { - text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'localizedTextBlock'; - } - | { - nestedArray?: - | { - item?: string | null; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'nestedBlock'; - } - )[] - | null; + localizedBlocks?: (LocalizedTextBlock | NestedBlock)[] | null; localizedTab?: { tabText?: string | null; }; @@ -459,6 +518,31 @@ export interface AllFieldsLocalized { createdAt: string; _status?: ('draft' | 'published') | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LocalizedTextBlock". + */ +export interface LocalizedTextBlock { + text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'localizedTextBlock'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "NestedBlock". + */ +export interface NestedBlock { + nestedArray?: + | { + item?: string | null; + id?: string | null; + }[] + | null; + id?: string | null; + blockName?: string | null; + blockType: 'nestedBlock'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -526,42 +610,7 @@ export interface LocalizedRequired { title: string; seoTitle?: string | null; nav: { - layout: ( - | { - text?: string | null; - nestedArray?: - | { - text?: string | null; - l2?: - | { - l3?: - | { - l4?: - | { - superNestedText?: string | null; - id?: string | null; - }[] - | null; - id?: string | null; - }[] - | null; - id?: string | null; - }[] - | null; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'text'; - } - | { - number?: number | null; - id?: string | null; - blockName?: string | null; - blockType: 'number'; - } - )[]; + layout: (Text | Number)[]; }; myTab?: { text?: string | null; @@ -578,6 +627,48 @@ export interface LocalizedRequired { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Text". + */ +export interface Text { + text?: string | null; + nestedArray?: + | { + text?: string | null; + l2?: + | { + l3?: + | { + l4?: + | { + superNestedText?: string | null; + id?: string | null; + }[] + | null; + id?: string | null; + }[] + | null; + id?: string | null; + }[] + | null; + id?: string | null; + }[] + | null; + id?: string | null; + blockName?: string | null; + blockType: 'text'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Number". + */ +export interface Number { + number?: number | null; + id?: string | null; + blockName?: string | null; + blockType: 'number'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "with-localized-relationship". @@ -674,21 +765,7 @@ export interface LocaleRestricted { */ export interface Nested { id: string; - blocks?: - | { - someText?: string | null; - array?: - | { - text?: string | null; - textNotLocalized?: string | null; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'block'; - }[] - | null; + blocks?: Block_8612C35D[] | null; topLevelArray?: | { localizedText?: string | null; @@ -705,6 +782,25 @@ export interface Nested { updatedAt: string; createdAt: string; } +/** + * Multiple blocks resolve to the `Block` interface with different fields, so a content hash is appended to keep the generated types stable and unambiguous. Set a unique `interfaceName` on the block to choose the name yourself. See https://payloadcms.com/docs/typescript/generating-types#block-interface-name-collisions + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Block_8612C35D". + */ +export interface Block_8612C35D { + someText?: string | null; + array?: + | { + text?: string | null; + textNotLocalized?: string | null; + id?: string | null; + }[] + | null; + id?: string | null; + blockName?: string | null; + blockType: 'block'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "groups". @@ -727,18 +823,21 @@ export interface Group { id?: string | null; }[] | null; - blocks?: - | { - title?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'first'; - }[] - | null; + blocks?: First[] | null; }; updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "First". + */ +export interface First { + title?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'first'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "tabs". @@ -767,14 +866,7 @@ export interface Tab { id?: string | null; }[] | null; - blocks?: - | { - title?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'first'; - }[] - | null; + blocks?: First[] | null; }; updatedAt: string; createdAt: string; @@ -796,25 +888,30 @@ export interface LocalizedSort { */ export interface BlocksSameName { id: string; - blocks?: - | ( - | { - title?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'block_first'; - } - | { - title?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'block_second'; - } - )[] - | null; + blocks?: (BlockFirst | BlockSecond)[] | null; updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Block_first". + */ +export interface BlockFirst { + title?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'block_first'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Block_second". + */ +export interface BlockSecond { + title?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'block_second'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "localized-within-localized". @@ -830,20 +927,23 @@ export interface LocalizedWithinLocalized { id?: string | null; }[] | null; - myBlocks?: - | { - shouldNotBeLocalized?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'myBlock'; - }[] - | null; + myBlocks?: MyBlock[] | null; myGroup?: { shouldNotBeLocalized?: string | null; }; updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock". + */ +export interface MyBlock { + shouldNotBeLocalized?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'myBlock'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "array-with-fallback-fields". @@ -863,6 +963,49 @@ export interface ArrayWithFallbackField { updatedAt: string; createdAt: string; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -978,12 +1121,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'array-with-fallback-fields'; value: string | ArrayWithFallbackField; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -993,10 +1145,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -1705,6 +1862,22 @@ export interface ArrayWithFallbackFieldsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -1835,6 +2008,140 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export interface SerializedHorizontalRuleNode { + type: 'horizontalrule'; + version: number; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + declare module 'payload' { // @ts-ignore diff --git a/test/locked-documents/payload-types.ts b/test/locked-documents/payload-types.ts index 6618a60f276..6ece63bf474 100644 --- a/test/locked-documents/payload-types.ts +++ b/test/locked-documents/payload-types.ts @@ -60,10 +60,51 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_2ACC7E17". + */ +export type LexicalNodes_2ACC7E17 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> + | SerializedHeadingNode + | { + type: 'upload'; + /** + * Lexical's internal serialization version for this node type. + */ + version: number; + [k: string]: unknown; + } + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedRelationshipNode< + | 'autosave' + | 'pages' + | 'posts' + | 'server-components' + | 'simple' + | 'simple-with-versions' + | 'tests' + | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + >; export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -75,6 +116,7 @@ export interface Config { 'simple-with-versions': SimpleWithVersion; tests: Test; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -90,6 +132,7 @@ export interface Config { 'simple-with-versions': SimpleWithVersionsSelect | SimpleWithVersionsSelect; tests: TestsSelect | TestsSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -115,7 +158,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -139,6 +182,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "autosave". @@ -169,21 +230,7 @@ export interface Page { export interface Post { id: string; text?: string | null; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; documentLoaded?: string | null; updatedAt: string; createdAt: string; @@ -196,21 +243,7 @@ export interface Post { export interface ServerComponent { id: string; customTextServer?: string | null; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -275,6 +308,49 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -326,12 +402,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -341,10 +426,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -467,6 +557,22 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -601,6 +707,38 @@ export interface CollectionsWidget { }; width: 'full'; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock". + */ +export interface MyBlock { + id: string; + blockType: 'myBlock'; + someText?: string | null; + someTextRequired: string; + radios?: ('option1' | 'option2' | 'option3') | null; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_2ACC7E17". + */ +export interface LexicalLinkFields_2ACC7E17 { + linkType: 'custom' | 'internal'; + url?: string; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + newTab: boolean; + description?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". @@ -609,6 +747,147 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export type SerializedBlockNode = { + type: 'block'; + format: LexicalElementFormat; + version: number; + fields: { id: string; blockName?: string | null } & Omit; +}; +export type SerializedInlineBlockNode = { + type: 'inlineBlock'; + version: number; + fields: { id: string } & Omit; +}; + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + declare module 'payload' { // @ts-ignore diff --git a/test/login-with-username/payload-types.ts b/test/login-with-username/payload-types.ts index 1c73c744e0d..b04fcfa54e9 100644 --- a/test/login-with-username/payload-types.ts +++ b/test/login-with-username/payload-types.ts @@ -66,12 +66,14 @@ export interface Config { users: UserAuthOperations; 'login-with-either': LoginWithEitherAuthOperations; 'require-email': RequireEmailAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { users: User; 'login-with-either': LoginWithEither; 'require-email': RequireEmail; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -82,6 +84,7 @@ export interface Config { users: UsersSelect | UsersSelect; 'login-with-either': LoginWithEitherSelect | LoginWithEitherSelect; 'require-email': RequireEmailSelect | RequireEmailSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -94,7 +97,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User | LoginWithEither | RequireEmail; + widgets: { + collections: CollectionsWidget; + }; + user: User | LoginWithEither | RequireEmail | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -163,6 +169,24 @@ export interface RequireEmailAuthOperations { username: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -241,6 +265,49 @@ export interface RequireEmail { password?: string | null; collection: 'require-email'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -276,6 +343,10 @@ export interface PayloadLockedDocument { | ({ relationTo: 'require-email'; value: string | RequireEmail; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; user: @@ -290,6 +361,10 @@ export interface PayloadLockedDocument { | { relationTo: 'require-email'; value: string | RequireEmail; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; }; updatedAt: string; createdAt: string; @@ -312,6 +387,10 @@ export interface PayloadPreference { | { relationTo: 'require-email'; value: string | RequireEmail; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; }; key?: string | null; value?: @@ -406,6 +485,22 @@ export interface RequireEmailSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -446,6 +541,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/migrations-cli/payload-types.ts b/test/migrations-cli/payload-types.ts index cb0d502bdc9..883393fc3c6 100644 --- a/test/migrations-cli/payload-types.ts +++ b/test/migrations-cli/payload-types.ts @@ -64,19 +64,22 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; }; collectionsJoins: {}; collectionsSelect: { - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -88,7 +91,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -112,22 +118,23 @@ export interface UserAuthOperations { password: string; }; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -154,21 +161,91 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". */ export interface PayloadLockedDocument { id: string; - document?: { - relationTo: 'users'; - value: string | User; - } | null; + document?: + | ({ + relationTo: 'users'; + value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -178,10 +255,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -206,14 +288,6 @@ export interface PayloadMigration { updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -236,6 +310,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -268,6 +366,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/nested-fields/payload-types.ts b/test/nested-fields/payload-types.ts index fb76169c336..c3e7a665305 100644 --- a/test/nested-fields/payload-types.ts +++ b/test/nested-fields/payload-types.ts @@ -64,12 +64,14 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { 'nested-fields': NestedField; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -77,8 +79,9 @@ export interface Config { collectionsJoins: {}; collectionsSelect: { 'nested-fields': NestedFieldsSelect | NestedFieldsSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -90,7 +93,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -114,6 +120,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "nested-fields". @@ -124,98 +148,64 @@ export interface NestedField { | { group?: { namedTab?: { - blocks?: - | { - text?: string | null; - blockArray?: - | { - arrayText?: string | null; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'blockWithFields'; - }[] - | null; + blocks?: BlockWithFields[] | null; }; }; id?: string | null; }[] | null; tab1?: { - layout?: - | ( - | { - items?: - | { - title: string; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'block-1'; - } - | { - items?: - | { - title2: string; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'block-2'; - } - )[] - | null; + layout?: (Block1 | Block2)[] | null; }; - blocksWithSimilarConfigs?: - | ( - | { - items?: - | { - title: string; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'block-1'; - } - | { - items?: - | { - title2: string; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'block-2'; - } - )[] - | null; + blocksWithSimilarConfigs?: (Block1 | Block2)[] | null; updatedAt: string; createdAt: string; } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". + * via the `definition` "BlockWithFields". */ -export interface PayloadKv { - id: string; - key: string; - data: +export interface BlockWithFields { + text?: string | null; + blockArray?: | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean + arrayText?: string | null; + id?: string | null; + }[] + | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockWithFields'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Block1". + */ +export interface Block1 { + items?: + | { + title: string; + id?: string | null; + }[] | null; + id?: string | null; + blockName?: string | null; + blockType: 'block-1'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Block2". + */ +export interface Block2 { + items?: + | { + title2: string; + id?: string | null; + }[] + | null; + id?: string | null; + blockName?: string | null; + blockType: 'block-2'; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -242,6 +232,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -256,12 +306,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -271,10 +330,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -397,14 +461,6 @@ export interface NestedFieldsSelect { updatedAt?: T; createdAt?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -427,6 +483,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -459,6 +539,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/payload-cloud/payload-types.ts b/test/payload-cloud/payload-types.ts index 8c84b737fb4..0b82c30fa7a 100644 --- a/test/payload-cloud/payload-types.ts +++ b/test/payload-cloud/payload-types.ts @@ -64,11 +64,14 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { + documents: Document; media: Media; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -76,8 +79,10 @@ export interface Config { }; collectionsJoins: {}; collectionsSelect: { + documents: DocumentsSelect | DocumentsSelect; media: MediaSelect | MediaSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -90,7 +95,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -114,6 +122,43 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "documents". + */ +export interface Document { + id: string; + title?: string | null; + updatedAt: string; + createdAt: string; + url?: string | null; + thumbnailURL?: string | null; + filename?: string | null; + mimeType?: string | null; + filesize?: number | null; + width?: number | null; + height?: number | null; + focalX?: number | null; + focalY?: number | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "media". @@ -176,6 +221,49 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -200,6 +288,10 @@ export interface PayloadKv { export interface PayloadLockedDocument { id: string; document?: + | ({ + relationTo: 'documents'; + value: string | Document; + } | null) | ({ relationTo: 'media'; value: string | Media; @@ -207,12 +299,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -222,10 +323,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -250,6 +356,24 @@ export interface PayloadMigration { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "documents_select". + */ +export interface DocumentsSelect { + title?: T; + updatedAt?: T; + createdAt?: T; + url?: T; + thumbnailURL?: T; + filename?: T; + mimeType?: T; + filesize?: T; + width?: T; + height?: T; + focalX?: T; + focalY?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "media_select". @@ -314,6 +438,22 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -354,6 +494,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/plugin-cloud-storage/payload-types.ts b/test/plugin-cloud-storage/payload-types.ts index 9bd52c6f37b..cd498968e2d 100644 --- a/test/plugin-cloud-storage/payload-types.ts +++ b/test/plugin-cloud-storage/payload-types.ts @@ -64,6 +64,7 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -77,6 +78,7 @@ export interface Config { 'restricted-media': RestrictedMedia; 'test-metadata': TestMetadatum; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -94,6 +96,7 @@ export interface Config { 'restricted-media': RestrictedMediaSelect | RestrictedMediaSelect; 'test-metadata': TestMetadataSelect | TestMetadataSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -109,7 +112,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -133,6 +136,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "media". @@ -382,6 +403,49 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -445,12 +509,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -460,10 +533,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -735,6 +813,22 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". diff --git a/test/plugin-ecommerce/payload-types.ts b/test/plugin-ecommerce/payload-types.ts index 462137d50b6..24e49575b55 100644 --- a/test/plugin-ecommerce/payload-types.ts +++ b/test/plugin-ecommerce/payload-types.ts @@ -69,6 +69,7 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -82,6 +83,7 @@ export interface Config { carts: Cart; orders: Order; transactions: Transaction; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -106,6 +108,7 @@ export interface Config { carts: CartsSelect | CartsSelect; orders: OrdersSelect | OrdersSelect; transactions: TransactionsSelect | TransactionsSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -121,7 +124,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -161,6 +164,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -449,6 +470,49 @@ export interface Transaction { updatedAt: string; createdAt: string; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -512,12 +576,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'transactions'; value: string | Transaction; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -527,10 +600,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -783,6 +861,22 @@ export interface TransactionsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". diff --git a/test/plugin-form-builder/payload-types.ts b/test/plugin-form-builder/payload-types.ts index a01564f7a60..f66c04fe96c 100644 --- a/test/plugin-form-builder/payload-types.ts +++ b/test/plugin-form-builder/payload-types.ts @@ -60,10 +60,37 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_2AAF05BF". + */ +export type LexicalNodes_2AAF05BF = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedHorizontalRuleNode + | SerializedUploadNode<'media' | 'documents'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'pages' + | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -73,6 +100,7 @@ export interface Config { documents: Document; forms: Form; 'form-submissions': FormSubmission; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -86,6 +114,7 @@ export interface Config { documents: DocumentsSelect | DocumentsSelect; forms: FormsSelect | FormsSelect; 'form-submissions': FormSubmissionsSelect | FormSubmissionsSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -101,7 +130,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -125,6 +154,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "pages". @@ -146,179 +193,19 @@ export interface Form { title: string; fields?: | ( - | { - name: string; - label?: string | null; - width?: number | null; - required?: boolean | null; - defaultValue?: boolean | null; - id?: string | null; - blockName?: string | null; - blockType: 'checkbox'; - } - | { - name: string; - label?: string | null; - width?: number | null; - required?: boolean | null; - id?: string | null; - blockName?: string | null; - blockType: 'country'; - } - | { - name: string; - label?: string | null; - width?: number | null; - required?: boolean | null; - id?: string | null; - blockName?: string | null; - blockType: 'email'; - } - | { - message?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - id?: string | null; - blockName?: string | null; - blockType: 'message'; - } - | { - name: string; - label?: string | null; - width?: number | null; - defaultValue?: number | null; - required?: boolean | null; - id?: string | null; - blockName?: string | null; - blockType: 'number'; - } - | { - name: string; - label?: string | null; - width?: number | null; - basePrice?: number | null; - priceConditions?: - | { - fieldToUse?: string | null; - condition?: ('hasValue' | 'equals' | 'notEquals') | null; - valueForCondition?: string | null; - operator?: ('add' | 'subtract' | 'multiply' | 'divide') | null; - valueType?: ('static' | 'valueOfField') | null; - valueForOperator?: string | null; - id?: string | null; - }[] - | null; - required?: boolean | null; - id?: string | null; - blockName?: string | null; - blockType: 'payment'; - } - | { - name: string; - label?: string | null; - width?: number | null; - defaultValue?: string | null; - placeholder?: string | null; - options?: - | { - label: string; - value: string; - id?: string | null; - }[] - | null; - required?: boolean | null; - id?: string | null; - blockName?: string | null; - blockType: 'select'; - } - | { - name: string; - label?: string | null; - width?: number | null; - required?: boolean | null; - id?: string | null; - blockName?: string | null; - blockType: 'state'; - } - | { - name: string; - label?: string | null; - width?: number | null; - defaultValue?: string | null; - required?: boolean | null; - id?: string | null; - blockName?: string | null; - blockType: 'text'; - } - | { - name: string; - label?: string | null; - width?: number | null; - defaultValue?: string | null; - required?: boolean | null; - id?: string | null; - blockName?: string | null; - blockType: 'textarea'; - } - | { - name: string; - label?: string | null; - /** - * Select which upload collection to store files in - */ - uploadCollection: 'media' | 'documents'; - /** - * Restrict allowed file types (e.g., image/*, application/pdf). Leave empty to allow all types. - */ - mimeTypes?: - | { - mimeType: string; - id?: string | null; - }[] - | null; - width?: number | null; - /** - * Maximum file size in bytes. Leave empty for no limit. - */ - maxFileSize?: number | null; - required?: boolean | null; - multiple?: boolean | null; - id?: string | null; - blockName?: string | null; - blockType: 'upload'; - } - | { - value?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'color'; - } - | { - name: string; - label?: string | null; - width?: number | null; - required?: boolean | null; - /** - * This is a date field - */ - defaultValue?: string | null; - defaultValue_tz?: SupportedTimezones; - id?: string | null; - blockName?: string | null; - blockType: 'date'; - } + | Checkbox + | Country + | Email + | Message + | Number + | Payment + | Select + | State + | Text + | Textarea + | Upload + | Color + | Date )[] | null; submitButtonLabel?: string | null; @@ -326,21 +213,7 @@ export interface Form { * Choose whether to display an on-page message or redirect to a different page after they submit the form. */ confirmationType?: ('message' | 'redirect') | null; - confirmationMessage?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + confirmationMessage?: LexicalRichText; redirect?: { type?: ('reference' | 'custom') | null; reference?: { @@ -363,21 +236,7 @@ export interface Form { /** * Enter the message that should be sent in this email. */ - message?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + message?: LexicalRichText | null; id?: string | null; }[] | null; @@ -385,6 +244,217 @@ export interface Form { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Checkbox". + */ +export interface Checkbox { + name: string; + label?: string | null; + width?: number | null; + required?: boolean | null; + defaultValue?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'checkbox'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Country". + */ +export interface Country { + name: string; + label?: string | null; + width?: number | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'country'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Email". + */ +export interface Email { + name: string; + label?: string | null; + width?: number | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'email'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Message". + */ +export interface Message { + message?: LexicalRichText | null; + id?: string | null; + blockName?: string | null; + blockType: 'message'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Number". + */ +export interface Number { + name: string; + label?: string | null; + width?: number | null; + defaultValue?: number | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'number'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Payment". + */ +export interface Payment { + name: string; + label?: string | null; + width?: number | null; + basePrice?: number | null; + priceConditions?: + | { + fieldToUse?: string | null; + condition?: ('hasValue' | 'equals' | 'notEquals') | null; + valueForCondition?: string | null; + operator?: ('add' | 'subtract' | 'multiply' | 'divide') | null; + valueType?: ('static' | 'valueOfField') | null; + valueForOperator?: string | null; + id?: string | null; + }[] + | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'payment'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Select". + */ +export interface Select { + name: string; + label?: string | null; + width?: number | null; + defaultValue?: string | null; + placeholder?: string | null; + options?: + | { + label: string; + value: string; + id?: string | null; + }[] + | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'select'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "State". + */ +export interface State { + name: string; + label?: string | null; + width?: number | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'state'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Text". + */ +export interface Text { + name: string; + label?: string | null; + width?: number | null; + defaultValue?: string | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'text'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Textarea". + */ +export interface Textarea { + name: string; + label?: string | null; + width?: number | null; + defaultValue?: string | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'textarea'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Upload". + */ +export interface Upload { + name: string; + label?: string | null; + /** + * Select which upload collection to store files in + */ + uploadCollection: 'media' | 'documents'; + /** + * Restrict allowed file types (e.g., image/*, application/pdf). Leave empty to allow all types. + */ + mimeTypes?: + | { + mimeType: string; + id?: string | null; + }[] + | null; + width?: number | null; + /** + * Maximum file size in bytes. Leave empty for no limit. + */ + maxFileSize?: number | null; + required?: boolean | null; + multiple?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'upload'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Color". + */ +export interface Color { + value?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'color'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Date". + */ +export interface Date { + name: string; + label?: string | null; + width?: number | null; + required?: boolean | null; + /** + * This is a date field + */ + defaultValue?: string | null; + defaultValue_tz?: SupportedTimezones; + id?: string | null; + blockName?: string | null; + blockType: 'date'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -497,6 +567,49 @@ export interface FormSubmission { updatedAt: string; createdAt: string; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -544,12 +657,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'form-submissions'; value: string | FormSubmission; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -559,10 +681,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -892,6 +1019,22 @@ export interface FormSubmissionsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -950,6 +1093,140 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export interface SerializedHorizontalRuleNode { + type: 'horizontalrule'; + version: number; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + declare module 'payload' { // @ts-ignore diff --git a/test/plugin-import-export/payload-types.ts b/test/plugin-import-export/payload-types.ts index 3f30d3a883a..bf0c34ab138 100644 --- a/test/plugin-import-export/payload-types.ts +++ b/test/plugin-import-export/payload-types.ts @@ -61,10 +61,67 @@ export type SupportedTimezones = | 'Pacific/Auckland' | 'Pacific/Fiji' | 'UTC'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_8C0174C1". + */ +export type LexicalNodes_8C0174C1 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> + | SerializedHeadingNode + | SerializedUploadNode< + | 'media' + | 'exports' + | 'posts-export' + | 'posts-no-jobs-queue-export' + | 'posts-with-s3-export' + | 'posts-with-limits-export' + | 'posts-with-hooks-export' + | 'posts-with-field-hooks-export' + | 'posts-with-column-map-export' + | 'imports' + | 'posts-import' + | 'posts-with-s3-import' + | 'posts-with-limits-import' + | 'posts-with-hooks-import' + | 'posts-with-field-hooks-import' + | 'posts-with-column-map-import', + LexicalUploadFields_1AB4670B + > + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedRelationshipNode< + | 'users' + | 'pages' + | 'posts' + | 'posts-exports-only' + | 'posts-imports-only' + | 'posts-no-jobs-queue' + | 'posts-with-limits' + | 'posts-with-s3' + | 'posts-with-hooks' + | 'posts-with-field-hooks' + | 'posts-with-column-map' + | 'custom-id-pages' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-jobs' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + >; export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -96,6 +153,7 @@ export interface Config { 'posts-with-hooks-import': PostsWithHooksImport; 'posts-with-field-hooks-import': PostsWithFieldHooksImport; 'posts-with-column-map-import': PostsWithColumnMapImport; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-jobs': PayloadJob; 'payload-locked-documents': PayloadLockedDocument; @@ -132,6 +190,7 @@ export interface Config { 'posts-with-hooks-import': PostsWithHooksImportSelect | PostsWithHooksImportSelect; 'posts-with-field-hooks-import': PostsWithFieldHooksImportSelect | PostsWithFieldHooksImportSelect; 'posts-with-column-map-import': PostsWithColumnMapImportSelect | PostsWithColumnMapImportSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-jobs': PayloadJobsSelect | PayloadJobsSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; @@ -153,7 +212,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: { createCollectionExport: TaskCreateCollectionExport; @@ -184,6 +243,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -249,36 +326,7 @@ export interface Page { id?: string | null; }[] | null; - blocks?: - | ( - | { - title?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'hero'; - } - | { - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - id?: string | null; - blockName?: string | null; - blockType: 'content'; - } - )[] - | null; + blocks?: (Hero | Content)[] | null; author?: (string | null) | User; virtualRelationship?: string | null; virtual?: string | null; @@ -292,21 +340,7 @@ export interface Page { | number | boolean | null; - richTextField?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richTextField?: LexicalRichText | null; relationship?: (string | null) | User; excerpt?: string | null; /** @@ -359,6 +393,26 @@ export interface Page { createdAt: string; _status?: ('draft' | 'published') | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Hero". + */ +export interface Hero { + title?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'hero'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Content". + */ +export interface Content { + richText?: LexicalRichText | null; + id?: string | null; + blockName?: string | null; + blockType: 'content'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts". @@ -366,21 +420,7 @@ export interface Page { export interface Post { id: string; title: string; - content?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + content?: LexicalRichText | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -411,21 +451,7 @@ export interface Media { export interface PostsExportsOnly { id: string; title: string; - content?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + content?: LexicalRichText | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -437,21 +463,7 @@ export interface PostsExportsOnly { export interface PostsImportsOnly { id: string; title: string; - content?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + content?: LexicalRichText | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -463,21 +475,7 @@ export interface PostsImportsOnly { export interface PostsNoJobsQueue { id: string; title: string; - content?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + content?: LexicalRichText | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -534,24 +532,13 @@ export interface PostsWithFieldHook { deepField?: string | null; }; }; - legacyToCSV?: string | null; - legacyToCSVArgs?: string | null; - legacyFromCSV?: string | null; - legacyFromCSVArgs?: string | null; items?: | { note?: string | null; id?: string | null; }[] | null; - content?: - | { - body?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'textBlock'; - }[] - | null; + content?: TextBlock[] | null; mayCrash?: string | null; rowField?: string | null; collapsibleField?: string | null; @@ -562,6 +549,16 @@ export interface PostsWithFieldHook { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TextBlock". + */ +export interface TextBlock { + body?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'textBlock'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts-with-column-map". @@ -1148,6 +1145,49 @@ export interface PostsWithColumnMapImport { focalX?: number | null; focalY?: number | null; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -1315,12 +1355,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'custom-id-pages'; value: string | CustomIdPage; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -1330,10 +1379,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -1563,10 +1617,6 @@ export interface PostsWithFieldHooksSelect { deepField?: T; }; }; - legacyToCSV?: T; - legacyToCSVArgs?: T; - legacyFromCSV?: T; - legacyFromCSVArgs?: T; items?: | T | { @@ -2078,6 +2128,22 @@ export interface PostsWithColumnMapImportSelect { focalX?: T; focalY?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -2237,6 +2303,45 @@ export interface TaskCreateCollectionImport { }; output?: unknown; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock". + */ +export interface MyBlock { + id: string; + blockType: 'myBlock'; + someText?: string | null; + someTextRequired: string; + radios?: ('option1' | 'option2' | 'option3') | null; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalUploadFields_1AB4670B". + */ +export interface LexicalUploadFields_1AB4670B { + alt?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_8C0174C1". + */ +export interface LexicalLinkFields_8C0174C1 { + linkType: 'custom' | 'internal'; + url?: string; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + newTab: boolean; + description?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". @@ -2245,6 +2350,147 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export type SerializedBlockNode = { + type: 'block'; + format: LexicalElementFormat; + version: number; + fields: { id: string; blockName?: string | null } & Omit; +}; +export type SerializedInlineBlockNode = { + type: 'inlineBlock'; + version: number; + fields: { id: string } & Omit; +}; + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + declare module 'payload' { // @ts-ignore diff --git a/test/plugin-multi-tenant/payload-types.ts b/test/plugin-multi-tenant/payload-types.ts index aa7c9dcc463..01616ffc2bf 100644 --- a/test/plugin-multi-tenant/payload-types.ts +++ b/test/plugin-multi-tenant/payload-types.ts @@ -60,10 +60,46 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_177EA583". + */ +export type LexicalNodes_177EA583 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> + | SerializedHorizontalRuleNode + | SerializedUploadNode<'media'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'tenants' + | 'users' + | 'food-items' + | 'food-menu' + | 'autosave-global' + | 'relationships' + | 'multi-tenant-posts' + | 'notTenanted' + | 'folders' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -77,6 +113,7 @@ export interface Config { media: Media; notTenanted: NotTenanted; folders: Folder; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -98,6 +135,7 @@ export interface Config { media: MediaSelect | MediaSelect; notTenanted: NotTenantedSelect | NotTenantedSelect; folders: FoldersSelect | FoldersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -113,7 +151,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -137,6 +175,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "tenants". @@ -197,21 +253,7 @@ export interface FoodItem { tenant?: (string | null) | Tenant; name: string; localizedName?: string | null; - content?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + content?: LexicalRichText | null; polymorphicRelationship?: | ({ relationTo: 'relationships'; @@ -332,6 +374,49 @@ export interface Media { focalX?: number | null; focalY?: number | null; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -395,12 +480,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'folders'; value: string | Folder; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -410,10 +504,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -588,6 +687,22 @@ export interface FoldersSelect { _h_slugPath?: T; _h_titlePath?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -638,6 +753,16 @@ export interface CollectionsWidget { }; width: 'full'; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BlockWithRelationship". + */ +export interface BlockWithRelationship { + id: string; + blockType: 'block-with-relationship'; + relationship?: (string | null) | FoodMenu; + blockName?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". @@ -646,6 +771,152 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export type SerializedBlockNode = { + type: 'block'; + format: LexicalElementFormat; + version: number; + fields: { id: string; blockName?: string | null } & Omit; +}; +export type SerializedInlineBlockNode = { + type: 'inlineBlock'; + version: number; + fields: { id: string } & Omit; +}; + +export interface SerializedHorizontalRuleNode { + type: 'horizontalrule'; + version: number; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + declare module 'payload' { // @ts-ignore diff --git a/test/plugin-nested-docs/payload-types.ts b/test/plugin-nested-docs/payload-types.ts index 774a05e5af8..a78f0237fdd 100644 --- a/test/plugin-nested-docs/payload-types.ts +++ b/test/plugin-nested-docs/payload-types.ts @@ -64,12 +64,14 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { pages: Page; categories: Category; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -80,6 +82,7 @@ export interface Config { pages: PagesSelect | PagesSelect; categories: CategoriesSelect | CategoriesSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -92,7 +95,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: 'en' | 'es' | 'de'; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -116,6 +122,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "pages". @@ -189,6 +213,49 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -224,12 +291,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -239,10 +315,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -329,6 +410,22 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -369,6 +466,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/plugin-redirects/payload-types.ts b/test/plugin-redirects/payload-types.ts index 1214fc3dfeb..0d04ade3291 100644 --- a/test/plugin-redirects/payload-types.ts +++ b/test/plugin-redirects/payload-types.ts @@ -64,12 +64,14 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { users: User; pages: Page; redirects: Redirect; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -80,6 +82,7 @@ export interface Config { users: UsersSelect | UsersSelect; pages: PagesSelect | PagesSelect; redirects: RedirectsSelect | RedirectsSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -92,7 +95,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: 'en' | 'es' | 'de'; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -116,6 +122,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -173,6 +197,49 @@ export interface Redirect { updatedAt: string; createdAt: string; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -208,12 +275,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'redirects'; value: string | Redirect; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -223,10 +299,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -302,6 +383,22 @@ export interface RedirectsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -342,6 +439,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/plugin-search/payload-types.ts b/test/plugin-search/payload-types.ts index 8b710d80a8f..b4805a76570 100644 --- a/test/plugin-search/payload-types.ts +++ b/test/plugin-search/payload-types.ts @@ -64,6 +64,7 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -74,6 +75,7 @@ export interface Config { 'custom-ids-2': CustomIds2; 'filtered-locales': FilteredLocale; search: Search; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -88,6 +90,7 @@ export interface Config { 'custom-ids-2': CustomIds2Select | CustomIds2Select; 'filtered-locales': FilteredLocalesSelect | FilteredLocalesSelect; search: SearchSelect | SearchSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -100,7 +103,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: 'en' | 'es' | 'de'; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -124,6 +130,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -240,6 +264,49 @@ export interface Search { updatedAt: string; createdAt: string; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -291,12 +358,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'search'; value: string | Search; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -306,10 +382,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -422,6 +503,22 @@ export interface SearchSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -462,6 +559,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/plugin-sentry/payload-types.ts b/test/plugin-sentry/payload-types.ts index f01124cbbfe..b3bb2d6d47f 100644 --- a/test/plugin-sentry/payload-types.ts +++ b/test/plugin-sentry/payload-types.ts @@ -64,11 +64,13 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { posts: Post; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -78,6 +80,7 @@ export interface Config { collectionsSelect: { posts: PostsSelect | PostsSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -90,7 +93,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -114,6 +120,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts". @@ -149,6 +173,49 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -180,12 +247,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -195,10 +271,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -254,6 +335,22 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -294,6 +391,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/plugin-seo/payload-types.ts b/test/plugin-seo/payload-types.ts index 1c5533367a4..b5b1f776323 100644 --- a/test/plugin-seo/payload-types.ts +++ b/test/plugin-seo/payload-types.ts @@ -60,10 +60,39 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_619DC837". + */ +export type LexicalNodes_619DC837 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> + | SerializedHeadingNode + | SerializedUploadNode<'media', LexicalUploadFields_1AB4670B> + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedRelationshipNode< + | 'users' + | 'pages' + | 'pagesWithImportedFields' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + >; export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -71,6 +100,7 @@ export interface Config { pages: Page; media: Media; pagesWithImportedFields: PagesWithImportedField; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -82,6 +112,7 @@ export interface Config { pages: PagesSelect | PagesSelect; media: MediaSelect | MediaSelect; pagesWithImportedFields: PagesWithImportedFieldsSelect | PagesWithImportedFieldsSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -97,7 +128,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -121,6 +152,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -176,21 +225,7 @@ export interface Page { export interface Media { id: string; media?: (string | null) | Media; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; url?: string | null; @@ -228,6 +263,49 @@ export interface PagesWithImportedField { createdAt: string; _status?: ('draft' | 'published') | null; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -267,12 +345,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'pagesWithImportedFields'; value: string | PagesWithImportedField; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -282,10 +369,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -399,6 +491,22 @@ export interface PagesWithImportedFieldsSelect { createdAt?: T; _status?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -449,6 +557,45 @@ export interface CollectionsWidget { }; width: 'full'; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock". + */ +export interface MyBlock { + id: string; + blockType: 'myBlock'; + someText?: string | null; + someTextRequired: string; + radios?: ('option1' | 'option2' | 'option3') | null; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalUploadFields_1AB4670B". + */ +export interface LexicalUploadFields_1AB4670B { + alt?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_619DC837". + */ +export interface LexicalLinkFields_619DC837 { + linkType: 'custom' | 'internal'; + url?: string; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + newTab: boolean; + description?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". @@ -457,6 +604,147 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export type SerializedBlockNode = { + type: 'block'; + format: LexicalElementFormat; + version: number; + fields: { id: string; blockName?: string | null } & Omit; +}; +export type SerializedInlineBlockNode = { + type: 'inlineBlock'; + version: number; + fields: { id: string } & Omit; +}; + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + declare module 'payload' { // @ts-ignore diff --git a/test/plugin-stripe/payload-types.ts b/test/plugin-stripe/payload-types.ts index dddc1944834..c7c912e69ca 100644 --- a/test/plugin-stripe/payload-types.ts +++ b/test/plugin-stripe/payload-types.ts @@ -65,12 +65,14 @@ export interface Config { auth: { users: UserAuthOperations; customers: CustomerAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { users: User; products: Product; customers: Customer; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -81,6 +83,7 @@ export interface Config { users: UsersSelect | UsersSelect; products: ProductsSelect | ProductsSelect; customers: CustomersSelect | CustomersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -93,7 +96,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: 'en' | 'es' | 'de'; - user: User | Customer; + widgets: { + collections: CollectionsWidget; + }; + user: User | Customer | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -135,6 +141,24 @@ export interface CustomerAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -225,6 +249,49 @@ export interface Customer { password?: string | null; collection: 'customers'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -260,6 +327,10 @@ export interface PayloadLockedDocument { | ({ relationTo: 'customers'; value: string | Customer; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; user: @@ -270,6 +341,10 @@ export interface PayloadLockedDocument { | { relationTo: 'customers'; value: string | Customer; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; }; updatedAt: string; createdAt: string; @@ -288,6 +363,10 @@ export interface PayloadPreference { | { relationTo: 'customers'; value: string | Customer; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; }; key?: string | null; value?: @@ -390,6 +469,22 @@ export interface CustomersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -430,6 +525,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/plugins/payload-types.ts b/test/plugins/payload-types.ts index 3fe672c8ac6..57f5fda6664 100644 --- a/test/plugins/payload-types.ts +++ b/test/plugins/payload-types.ts @@ -64,11 +64,13 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { users: User; pages: Page; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -78,6 +80,7 @@ export interface Config { collectionsSelect: { users: UsersSelect | UsersSelect; pages: PagesSelect | PagesSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -90,7 +93,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -114,6 +120,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -149,6 +173,49 @@ export interface Page { updatedAt: string; createdAt: string; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -180,12 +247,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'pages'; value: string | Page; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -195,10 +271,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -254,6 +335,22 @@ export interface PagesSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -294,6 +391,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/query-presets/payload-types.ts b/test/query-presets/payload-types.ts index e76244c32b6..7333ee6d365 100644 --- a/test/query-presets/payload-types.ts +++ b/test/query-presets/payload-types.ts @@ -64,6 +64,7 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -71,6 +72,7 @@ export interface Config { posts: Post; users: User; 'default-columns': DefaultColumn; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -83,6 +85,7 @@ export interface Config { posts: PostsSelect | PostsSelect; users: UsersSelect | UsersSelect; 'default-columns': DefaultColumnsSelect | DefaultColumnsSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -99,7 +102,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -123,6 +126,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "pages". @@ -188,6 +209,49 @@ export interface DefaultColumn { updatedAt: string; createdAt: string; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -219,12 +283,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'default-columns'; value: string | DefaultColumn; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -234,10 +307,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -372,6 +450,22 @@ export interface DefaultColumnsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". diff --git a/test/queues/payload-types.ts b/test/queues/payload-types.ts index de3f616303f..d681a210dfd 100644 --- a/test/queues/payload-types.ts +++ b/test/queues/payload-types.ts @@ -60,17 +60,54 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_0E9BF36D". + */ +export type LexicalNodes_0E9BF36D = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedHorizontalRuleNode + | { + type: 'upload'; + /** + * Lexical's internal serialization version for this node type. + */ + version: number; + [k: string]: unknown; + } + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'posts' + | 'simple' + | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-jobs' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { posts: Post; simple: Simple; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-jobs': PayloadJob; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -80,8 +117,9 @@ export interface Config { collectionsSelect: { posts: PostsSelect | PostsSelect; simple: SimpleSelect | SimpleSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-jobs': PayloadJobsSelect | PayloadJobsSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -97,7 +135,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: { UpdatePost: MyUpdatePostType; @@ -164,6 +202,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts". @@ -171,21 +227,7 @@ export interface UserAuthOperations { export interface Post { id: string; title: string; - content?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + content?: LexicalRichText | null; jobStep1Ran?: string | null; jobStep2Ran?: string | null; updatedAt: string; @@ -201,23 +243,6 @@ export interface Simple { updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -243,6 +268,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-jobs". @@ -413,12 +498,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -428,10 +522,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -477,14 +576,6 @@ export interface SimpleSelect { updatedAt?: T; createdAt?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -507,6 +598,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-jobs_select". @@ -678,7 +793,6 @@ export interface TaskThrowError { input?: unknown; output?: unknown; } - /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "TaskDoNothingTask". @@ -948,8 +1062,142 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export interface SerializedHorizontalRuleNode { + type: 'horizontalrule'; + version: number; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + declare module 'payload' { - // @ts-ignore + // @ts-ignore export interface GeneratedTypes extends Config {} -} +} \ No newline at end of file diff --git a/test/relationships/payload-types.ts b/test/relationships/payload-types.ts index 3289bff7e43..e6abcfe3b14 100644 --- a/test/relationships/payload-types.ts +++ b/test/relationships/payload-types.ts @@ -64,6 +64,7 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -87,9 +88,10 @@ export interface Config { 'deep-nested': DeepNested; relations: Relation1; items: Item; - blocks: Block; - 'payload-kv': PayloadKv; + blocks: Block1; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -121,8 +123,9 @@ export interface Config { relations: RelationsSelect | RelationsSelect; items: ItemsSelect | ItemsSelect; blocks: BlocksSelect | BlocksSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -134,7 +137,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: 'en' | 'de'; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -158,6 +164,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts". @@ -168,14 +192,7 @@ export interface Post { description?: string | null; number?: number | null; relationField?: (string | null) | Relation; - blocks?: - | { - relationField?: (string | null) | Relation; - id?: string | null; - blockName?: string | null; - blockType: 'block'; - }[] - | null; + blocks?: Block[] | null; defaultAccessRelation?: (string | null) | StrictAccess; chainedRelation?: (string | null) | Chained; maxDepthRelation?: (string | null) | Relation; @@ -196,6 +213,16 @@ export interface Relation { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Block". + */ +export interface Block { + relationField?: (string | null) | Relation; + id?: string | null; + blockName?: string | null; + blockType: 'block'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "strict-access". @@ -449,20 +476,23 @@ export interface ObjectWrite { export interface DeepNested { id: string; content?: { - blocks?: - | { - meta?: { - movie?: (string | null) | Movie; - }; - id?: string | null; - blockName?: string | null; - blockType: 'testBlock'; - }[] - | null; + blocks?: TestBlock[] | null; }; updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TestBlock". + */ +export interface TestBlock { + meta?: { + movie?: (string | null) | Movie; + }; + id?: string | null; + blockName?: string | null; + blockType: 'testBlock'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "relations". @@ -495,19 +525,65 @@ export interface Item { * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "blocks". */ -export interface Block { +export interface Block1 { id: string; - blocks?: + blocks?: Some[] | null; + updatedAt: string; + createdAt: string; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Some". + */ +export interface Some { + director?: (string | null) | Director; + directors?: (string | Director)[] | null; + id?: string | null; + blockName?: string | null; + blockType: 'some'; +} +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: | { - director?: (string | null) | Director; - directors?: (string | Director)[] | null; - id?: string | null; - blockName?: string | null; - blockType: 'some'; - }[] + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean | null; updatedAt: string; createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -615,17 +691,26 @@ export interface PayloadLockedDocument { } | null) | ({ relationTo: 'blocks'; - value: string | Block; + value: string | Block1; } | null) | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -635,10 +720,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -937,14 +1027,6 @@ export interface BlocksSelect { updatedAt?: T; createdAt?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -967,6 +1049,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -999,6 +1105,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/sdk/payload-types.ts b/test/sdk/payload-types.ts index c1504b2b7b4..3eb19c0abff 100644 --- a/test/sdk/payload-types.ts +++ b/test/sdk/payload-types.ts @@ -64,6 +64,7 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -71,6 +72,7 @@ export interface Config { posts: Post; emails: Email; media: Media; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -82,6 +84,7 @@ export interface Config { posts: PostsSelect | PostsSelect; emails: EmailsSelect | EmailsSelect; media: MediaSelect | MediaSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -98,7 +101,10 @@ export interface Config { global: GlobalSelect | GlobalSelect; }; locale: 'en' | 'es' | 'de'; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -122,6 +128,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -162,6 +186,7 @@ export interface Post { }; updatedAt: string; createdAt: string; + deletedAt?: string | null; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -192,6 +217,49 @@ export interface Media { focalX?: number | null; focalY?: number | null; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -231,12 +299,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'media'; value: string | Media; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -246,10 +323,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -312,6 +394,7 @@ export interface PostsSelect { }; updatedAt?: T; createdAt?: T; + deletedAt?: T; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -340,6 +423,22 @@ export interface MediaSelect { focalX?: T; focalY?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -400,6 +499,16 @@ export interface GlobalSelect { createdAt?: T; globalType?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/select/payload-types.ts b/test/select/payload-types.ts index 47d57e8e816..06f3afac87e 100644 --- a/test/select/payload-types.ts +++ b/test/select/payload-types.ts @@ -60,10 +60,46 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_AE9E55AF". + */ +export type LexicalNodes_AE9E55AF = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedHorizontalRuleNode + | SerializedUploadNode<'upload'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'posts' + | 'localized-posts' + | 'versioned-posts' + | 'deep-posts' + | 'pages' + | 'points' + | 'force-select' + | 'rels' + | 'relationships-blocks' + | 'custom-ids' + | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + > + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -79,6 +115,7 @@ export interface Config { 'relationships-blocks': RelationshipsBlock; 'custom-ids': CustomId; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -98,6 +135,7 @@ export interface Config { 'relationships-blocks': RelationshipsBlocksSelect | RelationshipsBlocksSelect; 'custom-ids': CustomIdsSelect | CustomIdsSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -119,7 +157,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -143,6 +181,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts". @@ -164,24 +220,7 @@ export interface Post { id?: string | null; }[] | null; - blocks?: - | ( - | { - text?: string | null; - introText?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'intro'; - } - | { - text?: string | null; - ctaText?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'cta'; - } - )[] - | null; + blocks?: (Intro | Cta)[] | null; tab?: { text?: string | null; number?: number | null; @@ -204,6 +243,28 @@ export interface Post { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Intro". + */ +export interface Intro { + text?: string | null; + introText?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'intro'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Cta". + */ +export interface Cta { + text?: string | null; + ctaText?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'cta'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "rels". @@ -264,45 +325,33 @@ export interface LocalizedPost { id?: string | null; }[] | null; - blocks?: - | ( - | { - text?: string | null; - introText?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'intro'; - } - | { - text?: string | null; - ctaText?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'cta'; - } - )[] - | null; - blocksSecond?: - | ( - | { - text?: string | null; - firstText?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'first'; - } - | { - text?: string | null; - secondText?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'second'; - } - )[] - | null; + blocks?: (Intro | Cta)[] | null; + blocksSecond?: (First | Second)[] | null; updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "First". + */ +export interface First { + text?: string | null; + firstText?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'first'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Second". + */ +export interface Second { + text?: string | null; + secondText?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'second'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "versioned-posts". @@ -317,18 +366,21 @@ export interface VersionedPost { id?: string | null; }[] | null; - blocks?: - | { - text?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'test'; - }[] - | null; + blocks?: Test[] | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Test". + */ +export interface Test { + text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'test'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "deep-posts". @@ -345,15 +397,7 @@ export interface DeepPost { id?: string | null; }[] | null; - blocks?: - | { - text?: string | null; - number?: number | null; - id?: string | null; - blockName?: string | null; - blockType: 'block'; - }[] - | null; + blocks?: Block[] | null; }; arrayTop?: | { @@ -371,6 +415,17 @@ export interface DeepPost { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Block". + */ +export interface Block { + text?: string | null; + number?: number | null; + id?: string | null; + blockName?: string | null; + blockType: 'block'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "pages". @@ -378,44 +433,7 @@ export interface DeepPost { export interface Page { id: string; relatedPage?: (string | null) | Page; - content?: - | { - title: string; - link: { - docPoly?: { - relationTo: 'pages'; - value: string | Page; - } | null; - doc?: (string | null) | Page; - docMany?: (string | Page)[] | null; - docHasManyPoly?: - | { - relationTo: 'pages'; - value: string | Page; - }[] - | null; - label: string; - }; - richTextLexical?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - id?: string | null; - blockName?: string | null; - blockType: 'introduction'; - }[] - | null; + content?: Introduction[] | null; slug: string; additional?: string | null; array?: @@ -425,18 +443,47 @@ export interface Page { id?: string | null; }[] | null; - blocks?: - | { - title?: string | null; - other?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'some'; - }[] - | null; + blocks?: Some[] | null; updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Introduction". + */ +export interface Introduction { + title: string; + link: { + docPoly?: { + relationTo: 'pages'; + value: string | Page; + } | null; + doc?: (string | null) | Page; + docMany?: (string | Page)[] | null; + docHasManyPoly?: + | { + relationTo: 'pages'; + value: string | Page; + }[] + | null; + label: string; + }; + richTextLexical?: LexicalRichText | null; + id?: string | null; + blockName?: string | null; + blockType: 'introduction'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Some". + */ +export interface Some { + title?: string | null; + other?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'some'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "points". @@ -470,18 +517,23 @@ export interface ForceSelect { */ export interface RelationshipsBlock { id: string; - blocks?: - | { - hasMany?: (string | Rel)[] | null; - hasOne?: (string | null) | Rel; - id?: string | null; - blockName?: string | null; - blockType: 'block'; - }[] - | null; + blocks?: Block_421D958C[] | null; updatedAt: string; createdAt: string; } +/** + * Multiple blocks resolve to the `Block` interface with different fields, so a content hash is appended to keep the generated types stable and unambiguous. Set a unique `interfaceName` on the block to choose the name yourself. See https://payloadcms.com/docs/typescript/generating-types#block-interface-name-collisions + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Block_421D958C". + */ +export interface Block_421D958C { + hasMany?: (string | Rel)[] | null; + hasOne?: (string | null) | Rel; + id?: string | null; + blockName?: string | null; + blockType: 'block'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "custom-ids". @@ -519,6 +571,49 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -590,12 +685,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -605,10 +709,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -997,6 +1106,22 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -1101,6 +1226,140 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export interface SerializedHorizontalRuleNode { + type: 'horizontalrule'; + version: number; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + declare module 'payload' { // @ts-ignore diff --git a/test/server-functions/payload-types.ts b/test/server-functions/payload-types.ts index cb0d502bdc9..883393fc3c6 100644 --- a/test/server-functions/payload-types.ts +++ b/test/server-functions/payload-types.ts @@ -64,19 +64,22 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; }; collectionsJoins: {}; collectionsSelect: { - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -88,7 +91,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -112,22 +118,23 @@ export interface UserAuthOperations { password: string; }; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -154,21 +161,91 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". */ export interface PayloadLockedDocument { id: string; - document?: { - relationTo: 'users'; - value: string | User; - } | null; + document?: + | ({ + relationTo: 'users'; + value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -178,10 +255,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -206,14 +288,6 @@ export interface PayloadMigration { updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -236,6 +310,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -268,6 +366,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/server-url/payload-types.ts b/test/server-url/payload-types.ts index cb0d502bdc9..883393fc3c6 100644 --- a/test/server-url/payload-types.ts +++ b/test/server-url/payload-types.ts @@ -64,19 +64,22 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; }; collectionsJoins: {}; collectionsSelect: { - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -88,7 +91,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -112,22 +118,23 @@ export interface UserAuthOperations { password: string; }; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -154,21 +161,91 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". */ export interface PayloadLockedDocument { id: string; - document?: { - relationTo: 'users'; - value: string | User; - } | null; + document?: + | ({ + relationTo: 'users'; + value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -178,10 +255,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -206,14 +288,6 @@ export interface PayloadMigration { updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -236,6 +310,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -268,6 +366,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/sort/payload-types.ts b/test/sort/payload-types.ts index 24e3f7fabf0..8bc25a9b30a 100644 --- a/test/sort/payload-types.ts +++ b/test/sort/payload-types.ts @@ -64,6 +64,7 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -74,8 +75,9 @@ export interface Config { localized: Localized; orderable: Orderable; 'orderable-join': OrderableJoin; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -96,8 +98,9 @@ export interface Config { localized: LocalizedSelect | LocalizedSelect; orderable: OrderableSelect | OrderableSelect; 'orderable-join': OrderableJoinSelect | OrderableJoinSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -112,7 +115,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -136,6 +139,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts". @@ -251,23 +272,6 @@ export interface OrderableJoin { updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -293,6 +297,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -331,12 +395,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -346,10 +419,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -472,14 +550,6 @@ export interface OrderableJoinSelect { updatedAt?: T; createdAt?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -502,6 +572,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". diff --git a/test/storage-azure/payload-types.ts b/test/storage-azure/payload-types.ts index 16263ece575..4ebf77d4373 100644 --- a/test/storage-azure/payload-types.ts +++ b/test/storage-azure/payload-types.ts @@ -64,12 +64,14 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { media: Media; 'media-with-prefix': MediaWithPrefix; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -80,6 +82,7 @@ export interface Config { media: MediaSelect | MediaSelect; 'media-with-prefix': MediaWithPrefixSelect | MediaWithPrefixSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -95,7 +98,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -119,6 +122,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "media". @@ -200,6 +221,49 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -235,12 +299,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -250,10 +323,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -360,6 +438,22 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". diff --git a/test/storage-gcs/payload-types.ts b/test/storage-gcs/payload-types.ts index f56882571c1..4ebf77d4373 100644 --- a/test/storage-gcs/payload-types.ts +++ b/test/storage-gcs/payload-types.ts @@ -64,12 +64,14 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { media: Media; 'media-with-prefix': MediaWithPrefix; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -80,6 +82,7 @@ export interface Config { media: MediaSelect | MediaSelect; 'media-with-prefix': MediaWithPrefixSelect | MediaWithPrefixSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -92,7 +95,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -116,6 +122,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "media". @@ -197,6 +221,49 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -232,12 +299,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -247,10 +323,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -357,6 +438,22 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -397,6 +494,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/storage-r2/payload-types.ts b/test/storage-r2/payload-types.ts index ed74d876c5f..1582c05bd50 100644 --- a/test/storage-r2/payload-types.ts +++ b/test/storage-r2/payload-types.ts @@ -64,6 +64,7 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -71,6 +72,7 @@ export interface Config { 'media-with-prefix': MediaWithPrefix; 'media-client': MediaClient; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -82,6 +84,7 @@ export interface Config { 'media-with-prefix': MediaWithPrefixSelect | MediaWithPrefixSelect; 'media-client': MediaClientSelect | MediaClientSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -94,7 +97,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -118,6 +124,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "media". @@ -236,6 +260,49 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -275,12 +342,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -290,10 +366,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -442,6 +523,22 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -482,6 +579,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/storage-s3/payload-types.ts b/test/storage-s3/payload-types.ts index 2874996f399..8d805c2ad57 100644 --- a/test/storage-s3/payload-types.ts +++ b/test/storage-s3/payload-types.ts @@ -64,6 +64,7 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -74,6 +75,7 @@ export interface Config { 'media-with-prefix': MediaWithPrefix; 'media-with-signed-downloads': MediaWithSignedDownload; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -88,6 +90,7 @@ export interface Config { 'media-with-prefix': MediaWithPrefixSelect | MediaWithPrefixSelect; 'media-with-signed-downloads': MediaWithSignedDownloadsSelect | MediaWithSignedDownloadsSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -100,7 +103,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -124,6 +130,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "media". @@ -292,6 +316,49 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -343,12 +410,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -358,10 +434,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -555,6 +636,22 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -595,6 +692,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/storage-uploadthing/payload-types.ts b/test/storage-uploadthing/payload-types.ts index 1ab2a1ab929..744f628a92f 100644 --- a/test/storage-uploadthing/payload-types.ts +++ b/test/storage-uploadthing/payload-types.ts @@ -64,12 +64,14 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { media: Media; 'media-with-prefix': MediaWithPrefix; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -80,6 +82,7 @@ export interface Config { media: MediaSelect | MediaSelect; 'media-with-prefix': MediaWithPrefixSelect | MediaWithPrefixSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -92,7 +95,10 @@ export interface Config { globals: {}; globalsSelect: {}; locale: null; - user: User; + widgets: { + collections: CollectionsWidget; + }; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -116,6 +122,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "media". @@ -124,6 +148,7 @@ export interface Media { id: string; alt?: string | null; _key?: string | null; + prefix?: string | null; updatedAt: string; createdAt: string; url?: string | null; @@ -199,6 +224,49 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -234,12 +302,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -249,10 +326,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -284,6 +366,7 @@ export interface PayloadMigration { export interface MediaSelect { alt?: T; _key?: T; + prefix?: T; updatedAt?: T; createdAt?: T; url?: T; @@ -361,6 +444,22 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". @@ -401,6 +500,16 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/test/storage-vercel-blob/payload-types.ts b/test/storage-vercel-blob/payload-types.ts index 16263ece575..863739eee6f 100644 --- a/test/storage-vercel-blob/payload-types.ts +++ b/test/storage-vercel-blob/payload-types.ts @@ -64,12 +64,17 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { media: Media; + 'media-with-always-insert-fields': MediaWithAlwaysInsertField; + 'media-with-direct-access': MediaWithDirectAccess; + 'media-with-dynamic-prefix': MediaWithDynamicPrefix; 'media-with-prefix': MediaWithPrefix; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -78,8 +83,12 @@ export interface Config { collectionsJoins: {}; collectionsSelect: { media: MediaSelect | MediaSelect; + 'media-with-always-insert-fields': MediaWithAlwaysInsertFieldsSelect | MediaWithAlwaysInsertFieldsSelect; + 'media-with-direct-access': MediaWithDirectAccessSelect | MediaWithDirectAccessSelect; + 'media-with-dynamic-prefix': MediaWithDynamicPrefixSelect | MediaWithDynamicPrefixSelect; 'media-with-prefix': MediaWithPrefixSelect | MediaWithPrefixSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -95,7 +104,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -119,6 +128,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "media". @@ -156,6 +183,75 @@ export interface Media { }; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "media-with-always-insert-fields". + */ +export interface MediaWithAlwaysInsertField { + id: string; + alt?: string | null; + prefix?: string | null; + updatedAt: string; + createdAt: string; + url?: string | null; + thumbnailURL?: string | null; + filename?: string | null; + mimeType?: string | null; + filesize?: number | null; + width?: number | null; + height?: number | null; + focalX?: number | null; + focalY?: number | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "media-with-direct-access". + */ +export interface MediaWithDirectAccess { + id: string; + alt?: string | null; + updatedAt: string; + createdAt: string; + url?: string | null; + thumbnailURL?: string | null; + filename?: string | null; + mimeType?: string | null; + filesize?: number | null; + width?: number | null; + height?: number | null; + focalX?: number | null; + focalY?: number | null; + sizes?: { + thumbnail?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + }; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "media-with-dynamic-prefix". + */ +export interface MediaWithDynamicPrefix { + id: string; + tenant: string; + prefix?: string | null; + updatedAt: string; + createdAt: string; + url?: string | null; + thumbnailURL?: string | null; + filename?: string | null; + mimeType?: string | null; + filesize?: number | null; + width?: number | null; + height?: number | null; + focalX?: number | null; + focalY?: number | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "media-with-prefix". @@ -200,6 +296,49 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -228,6 +367,18 @@ export interface PayloadLockedDocument { relationTo: 'media'; value: string | Media; } | null) + | ({ + relationTo: 'media-with-always-insert-fields'; + value: string | MediaWithAlwaysInsertField; + } | null) + | ({ + relationTo: 'media-with-direct-access'; + value: string | MediaWithDirectAccess; + } | null) + | ({ + relationTo: 'media-with-dynamic-prefix'; + value: string | MediaWithDynamicPrefix; + } | null) | ({ relationTo: 'media-with-prefix'; value: string | MediaWithPrefix; @@ -235,12 +386,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -250,10 +410,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -320,6 +485,76 @@ export interface MediaSelect { }; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "media-with-always-insert-fields_select". + */ +export interface MediaWithAlwaysInsertFieldsSelect { + alt?: T; + prefix?: T; + updatedAt?: T; + createdAt?: T; + url?: T; + thumbnailURL?: T; + filename?: T; + mimeType?: T; + filesize?: T; + width?: T; + height?: T; + focalX?: T; + focalY?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "media-with-direct-access_select". + */ +export interface MediaWithDirectAccessSelect { + alt?: T; + updatedAt?: T; + createdAt?: T; + url?: T; + thumbnailURL?: T; + filename?: T; + mimeType?: T; + filesize?: T; + width?: T; + height?: T; + focalX?: T; + focalY?: T; + sizes?: + | T + | { + thumbnail?: + | T + | { + url?: T; + width?: T; + height?: T; + mimeType?: T; + filesize?: T; + filename?: T; + }; + }; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "media-with-dynamic-prefix_select". + */ +export interface MediaWithDynamicPrefixSelect { + tenant?: T; + prefix?: T; + updatedAt?: T; + createdAt?: T; + url?: T; + thumbnailURL?: T; + filename?: T; + mimeType?: T; + filesize?: T; + width?: T; + height?: T; + focalX?: T; + focalY?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "media-with-prefix_select". @@ -360,6 +595,22 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". diff --git a/test/tags/payload-types.ts b/test/tags/payload-types.ts index b03134e87d6..571e8427bac 100644 --- a/test/tags/payload-types.ts +++ b/test/tags/payload-types.ts @@ -64,6 +64,7 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -72,8 +73,9 @@ export interface Config { pages: Page; media: Media; tags: Tag; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -85,8 +87,9 @@ export interface Config { pages: PagesSelect | PagesSelect; media: MediaSelect | MediaSelect; tags: TagsSelect | TagsSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -101,7 +104,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -125,6 +128,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "categories". @@ -196,23 +217,6 @@ export interface Media { focalX?: number | null; focalY?: number | null; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -238,6 +242,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -268,12 +332,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -283,10 +356,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -377,14 +455,6 @@ export interface TagsSelect { _h_slugPath?: T; _h_titlePath?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -407,6 +477,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". diff --git a/test/trash/payload-types.ts b/test/trash/payload-types.ts index 0a25a30ab29..1f5ab3865d5 100644 --- a/test/trash/payload-types.ts +++ b/test/trash/payload-types.ts @@ -64,6 +64,7 @@ export type SupportedTimezones = export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -72,6 +73,7 @@ export interface Config { 'restricted-collection': RestrictedCollection; 'differentiated-trash-collection': DifferentiatedTrashCollection; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -84,6 +86,7 @@ export interface Config { 'restricted-collection': RestrictedCollectionSelect | RestrictedCollectionSelect; 'differentiated-trash-collection': DifferentiatedTrashCollectionSelect | DifferentiatedTrashCollectionSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -99,7 +102,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -123,6 +126,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "pages". @@ -201,6 +222,49 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". @@ -244,12 +308,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -259,10 +332,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -358,6 +436,22 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". diff --git a/test/uploads/payload-types.ts b/test/uploads/payload-types.ts index 436c932e3b2..f78c61dd824 100644 --- a/test/uploads/payload-types.ts +++ b/test/uploads/payload-types.ts @@ -60,10 +60,98 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_C5C3B369". + */ +export type LexicalNodes_C5C3B369 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> + | SerializedHeadingNode + | SerializedUploadNode< + | 'gif-resize' + | 'filename-compound-index' + | 'no-image-sizes' + | 'object-fit' + | 'with-meta-data' + | 'without-meta-data' + | 'with-only-jpeg-meta-data' + | 'crop-only' + | 'focal-only' + | 'image-sizes-only' + | 'focal-no-sizes' + | 'media' + | 'allow-list-media' + | 'skip-safe-fetch-media' + | 'skip-safe-fetch-header-filter' + | 'skip-allow-list-safe-fetch-media' + | 'restrict-file-types' + | 'no-restrict-file-types' + | 'no-restrict-file-mime-types' + | 'pdf-only' + | 'restricted-mime-types' + | 'animated-type-media' + | 'enlarge' + | 'without-enlarge' + | 'reduce' + | 'media-trim' + | 'custom-file-name-media' + | 'unstored-media' + | 'externally-served-media' + | 'uploads-1' + | 'admin-thumbnail-function' + | 'admin-thumbnail-with-search-queries' + | 'admin-thumbnail-size' + | 'admin-upload-control' + | 'no-files-required' + | 'optional-file' + | 'required-file' + | 'versions' + | 'custom-upload-field' + | 'media-with-relation-preview' + | 'media-without-cache-tags' + | 'media-without-relation-preview' + | 'hide-file-input-on-create' + | 'three-dimensional' + | 'constructor-options' + | 'bulk-uploads' + | 'bulk-uploads-hook-error' + | 'file-mime-type' + | 'svg-only' + | 'media-without-delete-access' + | 'media-with-image-size-admin-props' + | 'prefix-media', + LexicalUploadFields_1AB4670B + > + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedRelationshipNode< + | 'relation' + | 'audio' + | 'relation-to-no-files-required' + | 'relation-preview' + | 'best-fit' + | 'list-view-preview' + | 'simple-relationship' + | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + >; export interface Config { auth: { users: UserAuthOperations; + 'payload-mcp-api-keys': PayloadMcpApiKeyAuthOperations; }; blocks: {}; collections: { @@ -128,8 +216,9 @@ export interface Config { 'media-without-delete-access': MediaWithoutDeleteAccess; 'media-with-image-size-admin-props': MediaWithImageSizeAdminProp; 'prefix-media': PrefixMedia; - 'payload-kv': PayloadKv; users: User; + 'payload-mcp-api-keys': PayloadMcpApiKey; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -197,8 +286,9 @@ export interface Config { 'media-without-delete-access': MediaWithoutDeleteAccessSelect | MediaWithoutDeleteAccessSelect; 'media-with-image-size-admin-props': MediaWithImageSizeAdminPropsSelect | MediaWithImageSizeAdminPropsSelect; 'prefix-media': PrefixMediaSelect | PrefixMediaSelect; - 'payload-kv': PayloadKvSelect | PayloadKvSelect; users: UsersSelect | UsersSelect; + 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -213,7 +303,7 @@ export interface Config { widgets: { collections: CollectionsWidget; }; - user: User; + user: User | PayloadMcpApiKey; jobs: { tasks: unknown; workflows: unknown; @@ -237,6 +327,24 @@ export interface UserAuthOperations { password: string; }; } +export interface PayloadMcpApiKeyAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "relation". @@ -247,15 +355,7 @@ export interface Relation { versionedImage?: (string | null) | Version; hideFileInputOnCreate?: (string | null) | HideFileInputOnCreate; hasManyImage?: (string | Media)[] | null; - blocks?: - | { - media: string | Media; - relatedMedia?: (string | Media)[] | null; - id?: string | null; - blockName?: string | null; - blockType: 'localizedMediaBlock'; - }[] - | null; + blocks?: LocalizedMediaBlock[] | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -449,6 +549,17 @@ export interface HideFileInputOnCreate { focalX?: number | null; focalY?: number | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LocalizedMediaBlock". + */ +export interface LocalizedMediaBlock { + media: string | Media; + relatedMedia?: (string | Media)[] | null; + id?: string | null; + blockName?: string | null; + blockType: 'localizedMediaBlock'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "audio". @@ -1301,21 +1412,7 @@ export interface Uploads1 { singleUpload?: (string | null) | Uploads2; hasManyThumbnailUpload?: (string | AdminThumbnailSize)[] | null; singleThumbnailUpload?: (string | null) | AdminThumbnailSize; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; url?: string | null; @@ -1851,23 +1948,6 @@ export interface PrefixMedia { focalX?: number | null; focalY?: number | null; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv". - */ -export interface PayloadKv { - id: string; - key: string; - data: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -1893,6 +1973,66 @@ export interface User { password?: string | null; collection: 'users'; } +/** + * API keys control which collections, resources, tools, and prompts MCP clients can access + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys". + */ +export interface PayloadMcpApiKey { + id: string; + /** + * The user that the API key is associated with. + */ + user: string | User; + /** + * A useful label for the API key. + */ + label?: string | null; + /** + * The purpose of the API key. + */ + description?: string | null; + /** + * When checked, this key bypasses Payload access control on every operation it performs. Leave unchecked unless you have a specific reason. + */ + overrideAccess?: boolean | null; + /** + * Access for this API key — uncheck to revoke individual tools. + */ + access?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; + enableAPIKey?: boolean | null; + apiKey?: string | null; + apiKeyIndex?: string | null; + collection: 'payload-mcp-api-keys'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -2147,12 +2287,21 @@ export interface PayloadLockedDocument { | ({ relationTo: 'users'; value: string | User; + } | null) + | ({ + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; } | null); globalSlug?: string | null; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; updatedAt: string; createdAt: string; } @@ -2162,10 +2311,15 @@ export interface PayloadLockedDocument { */ export interface PayloadPreference { id: string; - user: { - relationTo: 'users'; - value: string | User; - }; + user: + | { + relationTo: 'users'; + value: string | User; + } + | { + relationTo: 'payload-mcp-api-keys'; + value: string | PayloadMcpApiKey; + }; key?: string | null; value?: | { @@ -3878,14 +4032,6 @@ export interface PrefixMediaSelect { focalX?: T; focalY?: T; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "payload-kv_select". - */ -export interface PayloadKvSelect { - key?: T; - data?: T; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -3908,6 +4054,30 @@ export interface UsersSelect { expiresAt?: T; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-mcp-api-keys_select". + */ +export interface PayloadMcpApiKeysSelect { + user?: T; + label?: T; + description?: T; + overrideAccess?: T; + access?: T; + updatedAt?: T; + createdAt?: T; + enableAPIKey?: T; + apiKey?: T; + apiKeyIndex?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". @@ -3950,6 +4120,45 @@ export interface CollectionsWidget { }; width: 'full'; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock". + */ +export interface MyBlock { + id: string; + blockType: 'myBlock'; + someText?: string | null; + someTextRequired: string; + radios?: ('option1' | 'option2' | 'option3') | null; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalUploadFields_1AB4670B". + */ +export interface LexicalUploadFields_1AB4670B { + alt?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_C5C3B369". + */ +export interface LexicalLinkFields_C5C3B369 { + linkType: 'custom' | 'internal'; + url?: string; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + newTab: boolean; + description?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". @@ -3958,6 +4167,147 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export type SerializedBlockNode = { + type: 'block'; + format: LexicalElementFormat; + version: number; + fields: { id: string; blockName?: string | null } & Omit; +}; +export type SerializedInlineBlockNode = { + type: 'inlineBlock'; + version: number; + fields: { id: string } & Omit; +}; + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + declare module 'payload' { // @ts-ignore diff --git a/test/uuid-v7/payload-types.ts b/test/uuid-v7/payload-types.ts new file mode 100644 index 00000000000..ea29d3c412c --- /dev/null +++ b/test/uuid-v7/payload-types.ts @@ -0,0 +1,373 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * This file was automatically generated by Payload. + * DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config, + * and re-run `payload generate:types` to regenerate this file. + */ + +/** + * Supported timezones in IANA format. + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "supportedTimezones". + */ +export type SupportedTimezones = + | 'Pacific/Midway' + | 'Pacific/Niue' + | 'Pacific/Honolulu' + | 'Pacific/Rarotonga' + | 'America/Anchorage' + | 'Pacific/Gambier' + | 'America/Los_Angeles' + | 'America/Tijuana' + | 'America/Denver' + | 'America/Phoenix' + | 'America/Chicago' + | 'America/Guatemala' + | 'America/New_York' + | 'America/Bogota' + | 'America/Caracas' + | 'America/Santiago' + | 'America/Buenos_Aires' + | 'America/Sao_Paulo' + | 'Atlantic/South_Georgia' + | 'Atlantic/Azores' + | 'Atlantic/Cape_Verde' + | 'Europe/London' + | 'Europe/Berlin' + | 'Africa/Lagos' + | 'Europe/Athens' + | 'Africa/Cairo' + | 'Europe/Moscow' + | 'Asia/Riyadh' + | 'Asia/Dubai' + | 'Asia/Baku' + | 'Asia/Karachi' + | 'Asia/Tashkent' + | 'Asia/Calcutta' + | 'Asia/Dhaka' + | 'Asia/Almaty' + | 'Asia/Jakarta' + | 'Asia/Bangkok' + | 'Asia/Shanghai' + | 'Asia/Singapore' + | 'Asia/Tokyo' + | 'Asia/Seoul' + | 'Australia/Brisbane' + | 'Australia/Sydney' + | 'Pacific/Guam' + | 'Pacific/Noumea' + | 'Pacific/Auckland' + | 'Pacific/Fiji'; + +export interface Config { + auth: { + users: UserAuthOperations; + }; + blocks: {}; + collections: { + posts: Post; + categories: Category; + articles: Article; + 'payload-kv': PayloadKv; + users: User; + 'payload-locked-documents': PayloadLockedDocument; + 'payload-preferences': PayloadPreference; + 'payload-migrations': PayloadMigration; + }; + collectionsJoins: {}; + collectionsSelect: { + posts: PostsSelect | PostsSelect; + categories: CategoriesSelect | CategoriesSelect; + articles: ArticlesSelect | ArticlesSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; + users: UsersSelect | UsersSelect; + 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; + 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; + 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; + }; + db: { + defaultIDType: string; + }; + fallbackLocale: null; + globals: {}; + globalsSelect: {}; + locale: null; + widgets: { + collections: CollectionsWidget; + }; + user: User; + jobs: { + tasks: unknown; + workflows: unknown; + }; +} +export interface UserAuthOperations { + forgotPassword: { + email: string; + password: string; + }; + login: { + email: string; + password: string; + }; + registerFirstUser: { + email: string; + password: string; + }; + unlock: { + email: string; + password: string; + }; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "posts". + */ +export interface Post { + id: string; + title?: string | null; + updatedAt: string; + createdAt: string; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "categories". + */ +export interface Category { + id: string; + name?: string | null; + updatedAt: string; + createdAt: string; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "articles". + */ +export interface Article { + id: string; + title?: string | null; + category?: (string | null) | Category; + updatedAt: string; + createdAt: string; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "users". + */ +export interface User { + id: string; + updatedAt: string; + createdAt: string; + email: string; + resetPasswordToken?: string | null; + resetPasswordExpiration?: string | null; + salt?: string | null; + hash?: string | null; + loginAttempts?: number | null; + lockUntil?: string | null; + sessions?: + | { + id: string; + createdAt?: string | null; + expiresAt: string; + }[] + | null; + password?: string | null; + collection: 'users'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-locked-documents". + */ +export interface PayloadLockedDocument { + id: string; + document?: + | ({ + relationTo: 'posts'; + value: string | Post; + } | null) + | ({ + relationTo: 'categories'; + value: string | Category; + } | null) + | ({ + relationTo: 'articles'; + value: string | Article; + } | null) + | ({ + relationTo: 'users'; + value: string | User; + } | null); + globalSlug?: string | null; + user: { + relationTo: 'users'; + value: string | User; + }; + updatedAt: string; + createdAt: string; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-preferences". + */ +export interface PayloadPreference { + id: string; + user: { + relationTo: 'users'; + value: string | User; + }; + key?: string | null; + value?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + updatedAt: string; + createdAt: string; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-migrations". + */ +export interface PayloadMigration { + id: string; + name?: string | null; + batch?: number | null; + updatedAt: string; + createdAt: string; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "posts_select". + */ +export interface PostsSelect { + title?: T; + updatedAt?: T; + createdAt?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "categories_select". + */ +export interface CategoriesSelect { + name?: T; + updatedAt?: T; + createdAt?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "articles_select". + */ +export interface ArticlesSelect { + title?: T; + category?: T; + updatedAt?: T; + createdAt?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "users_select". + */ +export interface UsersSelect { + updatedAt?: T; + createdAt?: T; + email?: T; + resetPasswordToken?: T; + resetPasswordExpiration?: T; + salt?: T; + hash?: T; + loginAttempts?: T; + lockUntil?: T; + sessions?: + | T + | { + id?: T; + createdAt?: T; + expiresAt?: T; + }; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-locked-documents_select". + */ +export interface PayloadLockedDocumentsSelect { + document?: T; + globalSlug?: T; + user?: T; + updatedAt?: T; + createdAt?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-preferences_select". + */ +export interface PayloadPreferencesSelect { + user?: T; + key?: T; + value?: T; + updatedAt?: T; + createdAt?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-migrations_select". + */ +export interface PayloadMigrationsSelect { + name?: T; + batch?: T; + updatedAt?: T; + createdAt?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "collections_widget". + */ +export interface CollectionsWidget { + data?: { + [k: string]: unknown; + }; + width: 'full'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "auth". + */ +export interface Auth { + [k: string]: unknown; +} + + +declare module 'payload' { + export interface GeneratedTypes extends Config {} +} \ No newline at end of file diff --git a/test/v4/payload-types.ts b/test/v4/payload-types.ts index 7d27ee65b3a..261a2dc1009 100644 --- a/test/v4/payload-types.ts +++ b/test/v4/payload-types.ts @@ -60,6 +60,406 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_E6CA934E". + */ +export type LexicalNodes_E6CA934E = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode + | SerializedUploadNode<'uploads', LexicalUploadFields_7C90EEAC> + | SerializedHorizontalRuleNode + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'users' + | 'doc-controls' + | 'orderable' + | 'search-bar-test' + | 'talks' + | 'unauthorized-test' + | 'array-fields' + | 'blocks-fields' + | 'checkbox-fields' + | 'code-fields' + | 'collapsible-fields' + | 'date-fields' + | 'email-fields' + | 'group-fields' + | 'join-fields' + | 'join-posts' + | 'json-fields' + | 'number-fields' + | 'password-fields' + | 'point-fields' + | 'radio-fields' + | 'relationship-fields' + | 'rich-text-fields' + | 'row-fields' + | 'select-fields' + | 'slug-fields' + | 'tabs-fields' + | 'text-fields' + | 'textarea-fields' + | 'folders' + | 'folder-items' + | 'tags' + | 'tag-items' + | 'rubbish' + | 'rubbish-with-drafts' + | 'upload-fields' + | 'autosave' + | 'versions-diff' + | 'draft-versions' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-jobs' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + | 'payload-query-presets' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_AA0E78C0". + */ +export type LexicalNodes_AA0E78C0 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> + | SerializedHeadingNode + | SerializedUploadNode<'uploads'> + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedRelationshipNode< + | 'users' + | 'doc-controls' + | 'orderable' + | 'search-bar-test' + | 'talks' + | 'unauthorized-test' + | 'array-fields' + | 'blocks-fields' + | 'checkbox-fields' + | 'code-fields' + | 'collapsible-fields' + | 'date-fields' + | 'email-fields' + | 'group-fields' + | 'join-fields' + | 'join-posts' + | 'json-fields' + | 'number-fields' + | 'password-fields' + | 'point-fields' + | 'radio-fields' + | 'relationship-fields' + | 'rich-text-fields' + | 'row-fields' + | 'select-fields' + | 'slug-fields' + | 'tabs-fields' + | 'text-fields' + | 'textarea-fields' + | 'folders' + | 'folder-items' + | 'tags' + | 'tag-items' + | 'rubbish' + | 'rubbish-with-drafts' + | 'upload-fields' + | 'autosave' + | 'versions-diff' + | 'draft-versions' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-jobs' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + | 'payload-query-presets' + >; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_D5ECE514". + */ +export type LexicalNodes_D5ECE514 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode + | SerializedUploadNode<'uploads', LexicalUploadFields_76339D00> + | SerializedHorizontalRuleNode + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'users' + | 'doc-controls' + | 'orderable' + | 'search-bar-test' + | 'talks' + | 'unauthorized-test' + | 'array-fields' + | 'blocks-fields' + | 'checkbox-fields' + | 'code-fields' + | 'collapsible-fields' + | 'date-fields' + | 'email-fields' + | 'group-fields' + | 'join-fields' + | 'join-posts' + | 'json-fields' + | 'number-fields' + | 'password-fields' + | 'point-fields' + | 'radio-fields' + | 'relationship-fields' + | 'rich-text-fields' + | 'row-fields' + | 'select-fields' + | 'slug-fields' + | 'tabs-fields' + | 'text-fields' + | 'textarea-fields' + | 'folders' + | 'folder-items' + | 'tags' + | 'tag-items' + | 'rubbish' + | 'rubbish-with-drafts' + | 'upload-fields' + | 'autosave' + | 'versions-diff' + | 'draft-versions' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-jobs' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + | 'payload-query-presets' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_B722CE44". + */ +export type LexicalNodes_B722CE44 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode + | SerializedHorizontalRuleNode + | SerializedUploadNode<'uploads'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'users' + | 'doc-controls' + | 'orderable' + | 'search-bar-test' + | 'talks' + | 'unauthorized-test' + | 'array-fields' + | 'blocks-fields' + | 'checkbox-fields' + | 'code-fields' + | 'collapsible-fields' + | 'date-fields' + | 'email-fields' + | 'group-fields' + | 'join-fields' + | 'join-posts' + | 'json-fields' + | 'number-fields' + | 'password-fields' + | 'point-fields' + | 'radio-fields' + | 'relationship-fields' + | 'rich-text-fields' + | 'row-fields' + | 'select-fields' + | 'slug-fields' + | 'tabs-fields' + | 'text-fields' + | 'textarea-fields' + | 'folders' + | 'folder-items' + | 'tags' + | 'tag-items' + | 'rubbish' + | 'rubbish-with-drafts' + | 'upload-fields' + | 'autosave' + | 'versions-diff' + | 'draft-versions' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-jobs' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + | 'payload-query-presets' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_5D52C4F6". + */ +export type LexicalNodes_5D52C4F6 = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> + | SerializedHorizontalRuleNode + | SerializedUploadNode<'uploads'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'users' + | 'doc-controls' + | 'orderable' + | 'search-bar-test' + | 'talks' + | 'unauthorized-test' + | 'array-fields' + | 'blocks-fields' + | 'checkbox-fields' + | 'code-fields' + | 'collapsible-fields' + | 'date-fields' + | 'email-fields' + | 'group-fields' + | 'join-fields' + | 'join-posts' + | 'json-fields' + | 'number-fields' + | 'password-fields' + | 'point-fields' + | 'radio-fields' + | 'relationship-fields' + | 'rich-text-fields' + | 'row-fields' + | 'select-fields' + | 'slug-fields' + | 'tabs-fields' + | 'text-fields' + | 'textarea-fields' + | 'folders' + | 'folder-items' + | 'tags' + | 'tag-items' + | 'rubbish' + | 'rubbish-with-drafts' + | 'upload-fields' + | 'autosave' + | 'versions-diff' + | 'draft-versions' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-jobs' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + | 'payload-query-presets' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_B87BCF4E". + */ +export type LexicalNodes_B87BCF4E = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedHorizontalRuleNode + | SerializedUploadNode<'uploads'> + | SerializedQuoteNode + | SerializedRelationshipNode< + | 'users' + | 'doc-controls' + | 'orderable' + | 'search-bar-test' + | 'talks' + | 'unauthorized-test' + | 'array-fields' + | 'blocks-fields' + | 'checkbox-fields' + | 'code-fields' + | 'collapsible-fields' + | 'date-fields' + | 'email-fields' + | 'group-fields' + | 'join-fields' + | 'join-posts' + | 'json-fields' + | 'number-fields' + | 'password-fields' + | 'point-fields' + | 'radio-fields' + | 'relationship-fields' + | 'rich-text-fields' + | 'row-fields' + | 'select-fields' + | 'slug-fields' + | 'tabs-fields' + | 'text-fields' + | 'textarea-fields' + | 'folders' + | 'folder-items' + | 'tags' + | 'tag-items' + | 'rubbish' + | 'rubbish-with-drafts' + | 'upload-fields' + | 'autosave' + | 'versions-diff' + | 'draft-versions' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-jobs' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + | 'payload-query-presets' + > + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; export interface Config { auth: { @@ -339,11 +739,7 @@ export interface Talk { * One-paragraph teaser shown in listings. */ shortDescription?: string | null; - abstract?: - | { - [k: string]: unknown; - }[] - | null; + abstract?: LexicalRichText | null; track?: ('frontend' | 'backend' | 'devops' | 'design' | 'ai-ml' | 'workshop') | null; /** * Total runtime in minutes. @@ -391,55 +787,7 @@ export interface Talk { id?: string | null; }[] | null; - sections?: - | ( - | { - eyebrow?: string | null; - heading: string; - subheading?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'talk-hero'; - } - | { - quote: string; - attribution?: string | null; - role?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'talk-quote'; - } - | { - label: string; - url: string; - style?: ('primary' | 'secondary' | 'ghost') | null; - id?: string | null; - blockName?: string | null; - blockType: 'talk-cta'; - } - | { - image: string | Upload; - caption?: string | null; - align?: ('left' | 'center' | 'right') | null; - id?: string | null; - blockName?: string | null; - blockType: 'talk-image'; - } - | { - heading?: string | null; - items?: - | { - question: string; - answer: string; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'talk-qa'; - } - )[] - | null; + sections?: (TalkHero | TalkQuote | TalkCta | TalkImage | TalkQa)[] | null; /** * Links to slides, recording, docs, code. */ @@ -532,6 +880,71 @@ export interface Upload { focalX?: number | null; focalY?: number | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TalkHero". + */ +export interface TalkHero { + eyebrow?: string | null; + heading: string; + subheading?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'talk-hero'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TalkQuote". + */ +export interface TalkQuote { + quote: string; + attribution?: string | null; + role?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'talk-quote'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TalkCta". + */ +export interface TalkCta { + label: string; + url: string; + style?: ('primary' | 'secondary' | 'ghost') | null; + id?: string | null; + blockName?: string | null; + blockType: 'talk-cta'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TalkImage". + */ +export interface TalkImage { + image: string | Upload; + caption?: string | null; + align?: ('left' | 'center' | 'right') | null; + id?: string | null; + blockName?: string | null; + blockType: 'talk-image'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TalkQa". + */ +export interface TalkQa { + heading?: string | null; + items?: + | { + question: string; + answer: string; + id?: string | null; + }[] + | null; + id?: string | null; + blockName?: string | null; + blockType: 'talk-qa'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "tags". @@ -627,113 +1040,127 @@ export interface BlocksField { * A block field with multiple block types. */ multipleBlockTypes?: - | ( - | { - text: string; - id?: string | null; - blockName?: string | null; - blockType: 'test-block'; - } - | { - heading: string; - subheading?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'hero-block'; - } - | { - label: string; - url?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'call-to-action-block'; - } - | { - caption?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'image-block'; - } - | { - quote: string; - author?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'quote-block'; - } - | { - heading?: string | null; - body?: string | null; - link?: string | null; - footnote?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'content-block'; - } - | { - title?: string | null; - firstName?: string | null; - lastName?: string | null; - email?: string | null; - message?: string | null; - terms?: boolean | null; - id?: string | null; - blockName?: string | null; - blockType: 'form-block'; - } - )[] - | null; - blocksWithRequiredField?: - | { - text: string; - id?: string | null; - blockName?: string | null; - blockType: 'test-block-required'; - }[] - | null; - blocksWithMinRows?: - | { - text: string; - id?: string | null; - blockName?: string | null; - blockType: 'test-block'; - }[] - | null; - readOnlyBlocks?: - | { - text: string; - id?: string | null; - blockName?: string | null; - blockType: 'test-block'; - }[] - | null; - nestedBlocksField?: - | { - outerText?: string | null; - nestedBlocks?: - | ( - | { - innerText?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'inner-block'; - } - | { - text: string; - id?: string | null; - blockName?: string | null; - blockType: 'test-block'; - } - )[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'outer-block'; - }[] + | (TestBlock | HeroBlock | CallToActionBlock | ImageBlock | QuoteBlock | ContentBlock | FormBlock)[] | null; + blocksWithRequiredField?: TestBlockRequired[] | null; + blocksWithMinRows?: TestBlock[] | null; + readOnlyBlocks?: TestBlock[] | null; + nestedBlocksField?: OuterBlock[] | null; updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TestBlock". + */ +export interface TestBlock { + text: string; + id?: string | null; + blockName?: string | null; + blockType: 'test-block'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "HeroBlock". + */ +export interface HeroBlock { + heading: string; + subheading?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'hero-block'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "CallToActionBlock". + */ +export interface CallToActionBlock { + label: string; + url?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'call-to-action-block'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "ImageBlock". + */ +export interface ImageBlock { + caption?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'image-block'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "QuoteBlock". + */ +export interface QuoteBlock { + quote: string; + author?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'quote-block'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "ContentBlock". + */ +export interface ContentBlock { + heading?: string | null; + body?: string | null; + link?: string | null; + footnote?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'content-block'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "FormBlock". + */ +export interface FormBlock { + title?: string | null; + firstName?: string | null; + lastName?: string | null; + email?: string | null; + message?: string | null; + terms?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'form-block'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TestBlockRequired". + */ +export interface TestBlockRequired { + text: string; + id?: string | null; + blockName?: string | null; + blockType: 'test-block-required'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "OuterBlock". + */ +export interface OuterBlock { + outerText?: string | null; + nestedBlocks?: (InnerBlock | TestBlock)[] | null; + id?: string | null; + blockName?: string | null; + blockType: 'outer-block'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "InnerBlock". + */ +export interface InnerBlock { + innerText?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'inner-block'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "checkbox-fields". @@ -1200,31 +1627,11 @@ export interface TextField { */ export interface RichTextField { id: string; - content?: - | { - [k: string]: unknown; - }[] - | null; - table?: - | { - [k: string]: unknown; - }[] - | null; - code?: - | { - [k: string]: unknown; - }[] - | null; - typography?: - | { - [k: string]: unknown; - }[] - | null; - lists?: - | { - [k: string]: unknown; - }[] - | null; + content?: LexicalRichText | null; + table?: LexicalRichText | null; + code?: LexicalRichText | null; + typography?: LexicalRichText | null; + lists?: LexicalRichText | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -1362,11 +1769,7 @@ export interface SlugField { export interface TabsField { id: string; title?: string | null; - postContent?: - | { - [k: string]: unknown; - }[] - | null; + postContent?: LexicalRichText | null; featuredImage: string; metaTitle?: string | null; metaDescription?: string | null; @@ -1509,22 +1912,7 @@ export interface VersionsDiff { id?: string | null; }[] | null; - blocks?: - | ( - | { - blockText?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'textBlock'; - } - | { - blockNumber?: number | null; - id?: string | null; - blockName?: string | null; - blockType: 'numberBlock'; - } - )[] - | null; + blocks?: (TextBlock | NumberBlock)[] | null; checkbox?: boolean | null; code?: string | null; date?: string | null; @@ -1563,6 +1951,26 @@ export interface VersionsDiff { createdAt: string; _status?: ('draft' | 'published') | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TextBlock". + */ +export interface TextBlock { + blockText?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'textBlock'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "NumberBlock". + */ +export interface NumberBlock { + blockNumber?: number | null; + id?: string | null; + blockName?: string | null; + blockType: 'numberBlock'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "draft-versions". @@ -3081,6 +3489,190 @@ export interface TaskSchedulePublish { }; output?: unknown; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Callout". + */ +export interface Callout { + id: string; + blockType: 'callout'; + style?: ('info' | 'warning' | 'success' | 'error') | null; + body: string; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Kbd". + */ +export interface Kbd { + id: string; + blockType: 'kbd'; + keys: string; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalUploadFields_7C90EEAC". + */ +export interface LexicalUploadFields_7C90EEAC { + caption?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock". + */ +export interface MyBlock { + id: string; + blockType: 'myBlock'; + someText?: string | null; + someTextRequired: string; + radios?: ('option1' | 'option2' | 'option3') | null; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_AA0E78C0". + */ +export interface LexicalLinkFields_AA0E78C0 { + linkType: 'custom' | 'internal'; + url?: string; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + newTab: boolean; + description?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Banner". + */ +export interface Banner { + id: string; + blockType: 'banner'; + style?: ('info' | 'warning' | 'error' | 'success') | null; + content?: LexicalRichText | null; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Highlight". + */ +export interface Highlight { + id: string; + blockType: 'highlight'; + text?: string | null; + color?: ('yellow' | 'green' | 'blue' | 'pink') | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalUploadFields_76339D00". + */ +export interface LexicalUploadFields_76339D00 { + caption?: LexicalRichText | null; + altText?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Code". + */ +export interface Code { + id: string; + blockType: 'Code'; + language?: + | ( + | 'abap' + | 'apex' + | 'azcli' + | 'bat' + | 'bicep' + | 'cameligo' + | 'clojure' + | 'coffee' + | 'cpp' + | 'csharp' + | 'csp' + | 'css' + | 'cypher' + | 'dart' + | 'dockerfile' + | 'ecl' + | 'elixir' + | 'flow9' + | 'freemarker2' + | 'fsharp' + | 'go' + | 'graphql' + | 'handlebars' + | 'hcl' + | 'html' + | 'ini' + | 'java' + | 'javascript' + | 'julia' + | 'kotlin' + | 'less' + | 'lexon' + | 'liquid' + | 'lua' + | 'm3' + | 'markdown' + | 'mdx' + | 'mips' + | 'msdax' + | 'mysql' + | 'objective-c' + | 'pascal' + | 'pascaligo' + | 'perl' + | 'pgsql' + | 'php' + | 'pla' + | 'plaintext' + | 'postiats' + | 'powerquery' + | 'powershell' + | 'protobuf' + | 'pug' + | 'python' + | 'qsharp' + | 'r' + | 'razor' + | 'redis' + | 'redshift' + | 'restructuredtext' + | 'ruby' + | 'rust' + | 'sb' + | 'scala' + | 'scheme' + | 'scss' + | 'shell' + | 'solidity' + | 'sophia' + | 'sparql' + | 'sql' + | 'st' + | 'swift' + | 'systemverilog' + | 'tcl' + | 'twig' + | 'typescript' + | 'typespec' + | 'vb' + | 'wgsl' + | 'xml' + | 'yaml' + ) + | null; + code?: string | null; + blockName?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". @@ -3089,6 +3681,173 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export type SerializedBlockNode = { + type: 'block'; + format: LexicalElementFormat; + version: number; + fields: { id: string; blockName?: string | null } & Omit; +}; +export type SerializedInlineBlockNode = { + type: 'inlineBlock'; + version: number; + fields: { id: string } & Omit; +}; + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedHorizontalRuleNode { + type: 'horizontalrule'; + version: number; +} + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + +export interface SerializedTableNode extends SerializedLexicalElementBase { + type: 'table'; + colWidths?: number[]; + frozenColumnCount?: number; + frozenRowCount?: number; + rowStriping?: boolean; +} +export interface SerializedTableRowNode extends SerializedLexicalElementBase { + type: 'tablerow'; + height?: number; +} +export interface SerializedTableCellNode extends SerializedLexicalElementBase { + type: 'tablecell'; + backgroundColor?: string | null; + colSpan?: number; + headerState: number; + rowSpan?: number; + verticalAlign?: string; + width?: number; +} + declare module 'payload' { // @ts-ignore diff --git a/test/versions/payload-types.ts b/test/versions/payload-types.ts index b4385476b0b..128e7cc2525 100644 --- a/test/versions/payload-types.ts +++ b/test/versions/payload-types.ts @@ -60,6 +60,51 @@ export type SupportedTimezones = | 'Pacific/Noumea' | 'Pacific/Auckland' | 'Pacific/Fiji'; +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalNodes_985FB45B". + */ +export type LexicalNodes_985FB45B = + | SerializedTextNode + | SerializedTabNode + | SerializedLineBreakNode + | SerializedParagraphNode + | SerializedBlockNode + | SerializedInlineBlockNode<{blockType: string}> + | SerializedHeadingNode + | SerializedUploadNode<'draft-with-upload' | 'media' | 'media2', LexicalUploadFields_1AB4670B> + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedRelationshipNode< + | 'disable-publish' + | 'posts' + | 'autosave-posts' + | 'autosave-with-draft-button-posts' + | 'autosave-multi-select-posts' + | 'autosave-with-validate-posts' + | 'draft-posts' + | 'drafts-no-read-versions' + | 'draft-with-max-posts' + | 'draft-posts-with-change-hook' + | 'drafts-with-custom-unpublish' + | 'draft-with-validate-posts' + | 'error-on-unpublish' + | 'localized-posts' + | 'version-posts' + | 'custom-ids' + | 'diff' + | 'text' + | 'users' + | 'payload-mcp-api-keys' + | 'payload-kv' + | 'payload-jobs' + | 'payload-locked-documents' + | 'payload-preferences' + | 'payload-migrations' + >; export interface Config { auth: { @@ -238,11 +283,7 @@ export interface AutosavePost { title: string; relationship?: (string | null) | Post; computedTitle?: string | null; - richText?: - | { - [k: string]: unknown; - }[] - | null; + richText?: LexicalRichText | null; json?: | { [k: string]: unknown; @@ -284,21 +325,24 @@ export interface DraftPost { description: string; radio?: 'test' | null; select?: ('test1' | 'test2')[] | null; - blocksField?: - | { - text?: string | null; - localized?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'block'; - }[] - | null; + blocksField?: Block[] | null; relation?: (string | null) | DraftPost; restrictedToUpdate?: boolean | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Block". + */ +export interface Block { + text?: string | null; + localized?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'block'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "autosave-with-draft-button-posts". @@ -355,15 +399,7 @@ export interface DraftWithMaxPost { description: string; radio?: 'test' | null; select?: ('test1' | 'test2')[] | null; - blocksField?: - | { - text?: string | null; - localized?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'block'; - }[] - | null; + blocksField?: Block[] | null; relation?: (string | null) | DraftWithMaxPost; updatedAt: string; createdAt: string; @@ -422,31 +458,38 @@ export interface LocalizedPost { id: string; text?: string | null; description?: string | null; - blocks?: - | ( - | { - array?: - | { - relationship?: (string | null) | Post; - id?: string | null; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'block'; - } - | { - blockText?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'localizedTextBlock'; - } - )[] - | null; + blocks?: (Block_DBD0B346 | LocalizedTextBlock)[] | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; } +/** + * Multiple blocks resolve to the `Block` interface with different fields, so a content hash is appended to keep the generated types stable and unambiguous. Set a unique `interfaceName` on the block to choose the name yourself. See https://payloadcms.com/docs/typescript/generating-types#block-interface-name-collisions + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "Block_DBD0B346". + */ +export interface Block_DBD0B346 { + array?: + | { + relationship?: (string | null) | Post; + id?: string | null; + }[] + | null; + id?: string | null; + blockName?: string | null; + blockType: 'block'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LocalizedTextBlock". + */ +export interface LocalizedTextBlock { + blockText?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'localizedTextBlock'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "custom-ids". @@ -475,56 +518,7 @@ export interface Diff { id?: string | null; }[] | null; - blocks?: - | ( - | { - title?: string | null; - relatedItem?: { - relationTo: 'text'; - value: string | Text; - } | null; - id?: string | null; - blockName?: string | null; - blockType: 'SingleRelationshipBlock'; - } - | { - title?: string | null; - relatedItem?: - | { - relationTo: 'text'; - value: string | Text; - }[] - | null; - id?: string | null; - blockName?: string | null; - blockType: 'ManyRelationshipBlock'; - } - | { - textInBlock?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'TextBlock'; - } - | { - textInCollapsibleInCollapsibleBlock?: string | null; - textInRowInCollapsibleBlock?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'CollapsibleBlock'; - } - | { - namedTab1InBlock?: { - textInNamedTab1InBlock?: string | null; - }; - textInUnnamedTab2InBlock?: string | null; - textInUnnamedTab2InBlockAccessFalse?: string | null; - textInRowInUnnamedTab2InBlock?: string | null; - id?: string | null; - blockName?: string | null; - blockType: 'TabsBlock'; - } - )[] - | null; + blocks?: (SingleRelationshipBlock | ManyRelationshipBlock | TextBlock | CollapsibleBlock | TabsBlock)[] | null; checkbox?: boolean | null; code?: string | null; textInCollapsible?: string | null; @@ -587,16 +581,8 @@ export interface Diff { )[] | null; zeroDepthRelationship?: (string | null) | User; - richtext?: - | { - [k: string]: unknown; - }[] - | null; - richtextWithCustomDiff?: - | { - [k: string]: unknown; - }[] - | null; + richtext?: LexicalRichText | null; + richtextWithCustomDiff?: LexicalRichText | null; textInRow?: string | null; textCannotRead?: string | null; select?: ('option1' | 'option2') | null; @@ -616,6 +602,20 @@ export interface Diff { createdAt: string; _status?: ('draft' | 'published') | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "SingleRelationshipBlock". + */ +export interface SingleRelationshipBlock { + title?: string | null; + relatedItem?: { + relationTo: 'text'; + value: string | Text; + } | null; + id?: string | null; + blockName?: string | null; + blockType: 'SingleRelationshipBlock'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "text". @@ -626,6 +626,58 @@ export interface Text { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "ManyRelationshipBlock". + */ +export interface ManyRelationshipBlock { + title?: string | null; + relatedItem?: + | { + relationTo: 'text'; + value: string | Text; + }[] + | null; + id?: string | null; + blockName?: string | null; + blockType: 'ManyRelationshipBlock'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TextBlock". + */ +export interface TextBlock { + textInBlock?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'TextBlock'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "CollapsibleBlock". + */ +export interface CollapsibleBlock { + textInCollapsibleInCollapsibleBlock?: string | null; + textInRowInCollapsibleBlock?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'CollapsibleBlock'; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "TabsBlock". + */ +export interface TabsBlock { + namedTab1InBlock?: { + textInNamedTab1InBlock?: string | null; + }; + textInUnnamedTab2InBlock?: string | null; + textInUnnamedTab2InBlockAccessFalse?: string | null; + textInRowInUnnamedTab2InBlock?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'TabsBlock'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -1760,6 +1812,45 @@ export interface TaskSchedulePublish { }; output?: unknown; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "MyBlock". + */ +export interface MyBlock { + id: string; + blockType: 'myBlock'; + someText?: string | null; + someTextRequired: string; + radios?: ('option1' | 'option2' | 'option3') | null; + blockName?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalUploadFields_1AB4670B". + */ +export interface LexicalUploadFields_1AB4670B { + alt?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalLinkFields_985FB45B". + */ +export interface LexicalLinkFields_985FB45B { + linkType: 'custom' | 'internal'; + url?: string; + doc?: { + relationTo: string; + value: + | string + | number + | { + id: string | number; + [k: string]: unknown; + }; + } | null; + newTab: boolean; + description?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". @@ -1768,6 +1859,147 @@ export interface Auth { [k: string]: unknown; } +/** @internal Core Lexical types — see @payloadcms/richtext-lexical. */ +export type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; +export type LexicalElementDirection = ('ltr' | 'rtl') | null; + +export interface SerializedLexicalElementBase { + children: TChildren[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + textFormat?: number; + textStyle?: string; + version: number; +} + +export type LexicalTextMode = 'normal' | 'token' | 'segmented'; + +export interface SerializedTextNode { + type: 'text'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedTabNode { + type: 'tab'; + detail: number; + format: number; + mode: LexicalTextMode; + style: string; + text: string; + version: number; +} + +export interface SerializedLineBreakNode { + type: 'linebreak'; + version: number; +} + +export interface SerializedParagraphNode extends SerializedLexicalElementBase { + type: 'paragraph'; + textFormat: number; + textStyle: string; +} + +export type SerializedBlockNode = { + type: 'block'; + format: LexicalElementFormat; + version: number; + fields: { id: string; blockName?: string | null } & Omit; +}; +export type SerializedInlineBlockNode = { + type: 'inlineBlock'; + version: number; + fields: { id: string } & Omit; +}; + +export interface SerializedHeadingNode< + TChildren, + TTag extends 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', +> extends SerializedLexicalElementBase { + type: 'heading'; + tag: TTag; +} + +export type SerializedUploadNode = { + type: 'upload'; + format: LexicalElementFormat; + id: string; + version: number; + fields: TFields; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +export interface SerializedQuoteNode extends SerializedLexicalElementBase { + type: 'quote'; +} + +export interface SerializedListNode extends SerializedLexicalElementBase { + type: 'list'; + checked?: boolean; + listType: 'number' | 'bullet' | 'check'; + start: number; + tag: 'ul' | 'ol'; +} + +export interface SerializedListItemNode extends SerializedLexicalElementBase { + type: 'listitem'; + checked?: boolean; + value: number; +} + +export interface LexicalLinkFields { + [k: string]: unknown; + doc?: { + relationTo: string; + value: Config['db']['defaultIDType'] | { [k: string]: unknown; id: Config['db']['defaultIDType'] }; + } | null; + linkType: 'custom' | 'internal'; + newTab: boolean; + url?: string; +} +export interface SerializedLinkNode extends SerializedLexicalElementBase { + type: 'link'; + fields: TFields; + id?: string; +} +export interface SerializedAutoLinkNode extends SerializedLexicalElementBase { + type: 'autolink'; + fields: TFields; +} + +export type SerializedRelationshipNode = { + type: 'relationship'; + format: LexicalElementFormat; + version: number; +} & { + [TSlug in TSlugs]: { + relationTo: TSlug; + value: number | string | Config['collections'][TSlug]; + }; +}[TSlugs]; + +/** Shape of a Lexical `richText` field. */ +export interface LexicalRichText { + root: { + children: TNode[]; + direction: LexicalElementDirection; + format: LexicalElementFormat; + indent: number; + type: 'root'; + version: number; + }; +} + declare module 'payload' { // @ts-ignore From 8934ed15e9764bb7f579ede4b995577fe6749173 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Fri, 5 Jun 2026 16:46:51 +0000 Subject: [PATCH 54/56] fix uploadnode types with 2+ upload collections and differing custom fields --- .../src/features/upload/server/schema.ts | 20 +- test/types/config.ts | 32 +++- test/types/payload-types.ts | 92 +++++++-- test/types/types.spec.ts | 175 ++++++++++++++---- 4 files changed, 262 insertions(+), 57 deletions(-) diff --git a/packages/richtext-lexical/src/features/upload/server/schema.ts b/packages/richtext-lexical/src/features/upload/server/schema.ts index 57f267c7be3..3df315aad52 100644 --- a/packages/richtext-lexical/src/features/upload/server/schema.ts +++ b/packages/richtext-lexical/src/features/upload/server/schema.ts @@ -99,7 +99,11 @@ export const createUploadNodeJSONSchema = // Configured extra fields are registered as their own interface and referenced here, so the // generated TypeScript keeps them - the node-level `tsType` would otherwise erase `fields` to // `{ [k: string]: unknown }`. Mirrors how LinkFeature handles custom link fields. - const fieldsTypeNames = new Set() + // + // Each collection gets its own `SerializedUploadNode<'slug', Fields>` instantiation so the + // generated union correctly pairs each `relationTo` with its own fields type. A single + // `SerializedUploadNode<'a' | 'b', AFields | BFields>` would lose that pairing. + const perCollectionTsTypes: string[] = [] const collectionVariants: JSONSchema4[] = enabledCollections.map((collection) => { const slug = collection.slug const idType: 'number' | 'string' = collectionIDFieldTypes[slug] ?? 'string' @@ -123,13 +127,19 @@ export const createUploadNodeJSONSchema = properties: extraFieldsSchema.properties, required: extraFieldsSchema.required, } + let fieldsTypeName: string | undefined if (flattenedExtra.length > 0) { - const fieldsTypeName = `LexicalUploadFields_${hashUploadFields(fieldsSchema)}` + fieldsTypeName = `LexicalUploadFields_${hashUploadFields(fieldsSchema)}` interfaceNameDefinitions.set(fieldsTypeName, fieldsSchema) - fieldsTypeNames.add(fieldsTypeName) fieldsSchema = { $ref: `#/$defs/${fieldsTypeName}` } } + perCollectionTsTypes.push( + fieldsTypeName + ? `SerializedUploadNode<'${slug}', ${fieldsTypeName}>` + : `SerializedUploadNode<'${slug}'>`, + ) + return { type: 'object', additionalProperties: false, @@ -163,11 +173,9 @@ export const createUploadNodeJSONSchema = required: ['type', 'version'], } } else { - const slugUnion = enabledCollections.map((c) => `'${c.slug}'`).join(' | ') const baseSchema: JSONSchema4 = collectionVariants.length === 1 ? collectionVariants[0]! : { oneOf: collectionVariants } - const fieldsType = fieldsTypeNames.size > 0 ? `, ${[...fieldsTypeNames].join(' | ')}` : '' - schema = { ...baseSchema, tsType: `SerializedUploadNode<${slugUnion}${fieldsType}>` } + schema = { ...baseSchema, tsType: perCollectionTsTypes.join(' | ') } } return schema diff --git a/test/types/config.ts b/test/types/config.ts index de1902761ee..a47d631be73 100644 --- a/test/types/config.ts +++ b/test/types/config.ts @@ -1,4 +1,4 @@ -import { lexicalEditor } from '@payloadcms/richtext-lexical' +import { lexicalEditor, UploadFeature } from '@payloadcms/richtext-lexical' import { fileURLToPath } from 'node:url' import path from 'path' @@ -147,13 +147,37 @@ export default buildConfigWithDefaults({ }, ], }, + { + slug: 'gallery', + upload: true, + fields: [ + { + type: 'text', + name: 'title', + }, + ], + }, ], admin: { importMap: { baseDir: path.resolve(dirname), }, }, - editor: lexicalEditor({}), + editor: lexicalEditor({ + features: ({ defaultFeatures }) => [ + ...defaultFeatures.filter((f) => f.key !== 'upload'), + UploadFeature({ + collections: { + media: { + fields: [{ name: 'caption', type: 'text' }], + }, + gallery: { + fields: [{ name: 'altText', type: 'text', required: true }], + }, + }, + }), + ], + }), globals: [ { slug: 'menu', @@ -163,6 +187,10 @@ export default buildConfigWithDefaults({ type: 'text', name: 'text', }, + { + type: 'richText', + name: 'richText', + }, ], }, { diff --git a/test/types/payload-types.ts b/test/types/payload-types.ts index 20d951cdd89..b34795d9ee0 100644 --- a/test/types/payload-types.ts +++ b/test/types/payload-types.ts @@ -75,16 +75,17 @@ export type SupportedTimezones = | 'Pacific/Fiji'; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_BFE38E95". + * via the `definition` "LexicalNodes_4CE595A9". */ -export type LexicalNodes_BFE38E95 = +export type LexicalNodes_4CE595A9 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode + | SerializedUploadNode<'media', LexicalUploadFields_7C90EEAC> + | SerializedUploadNode<'gallery', LexicalUploadFields_9521FA4A> | SerializedHorizontalRuleNode - | SerializedUploadNode<'media'> - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'posts' | 'pages' @@ -97,11 +98,11 @@ export type LexicalNodes_BFE38E95 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; export interface Config { auth: { @@ -115,6 +116,7 @@ export interface Config { 'pages-categories': PagesCategory; 'draft-posts': DraftPost; media: Media; + gallery: Gallery; users: User; 'payload-mcp-api-keys': PayloadMcpApiKey; 'payload-kv': PayloadKv; @@ -133,6 +135,7 @@ export interface Config { 'pages-categories': PagesCategoriesSelect | PagesCategoriesSelect; 'draft-posts': DraftPostsSelect | DraftPostsSelect; media: MediaSelect | MediaSelect; + gallery: GallerySelect | GallerySelect; users: UsersSelect | UsersSelect; 'payload-mcp-api-keys': PayloadMcpApiKeysSelect | PayloadMcpApiKeysSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; @@ -206,7 +209,7 @@ export interface PayloadMcpApiKeyAuthOperations { export interface Post { id: string; text?: string | null; - richText: LexicalRichText; + richText: LexicalRichText; title?: string | null; selectField: MySelectOptions; insideUnnamedGroup?: string | null; @@ -279,6 +282,25 @@ export interface Media { focalX?: number | null; focalY?: number | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "gallery". + */ +export interface Gallery { + id: string; + title?: string | null; + updatedAt: string; + createdAt: string; + url?: string | null; + thumbnailURL?: string | null; + filename?: string | null; + mimeType?: string | null; + filesize?: number | null; + width?: number | null; + height?: number | null; + focalX?: number | null; + focalY?: number | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -391,6 +413,10 @@ export interface PayloadLockedDocument { relationTo: 'media'; value: string | Media; } | null) + | ({ + relationTo: 'gallery'; + value: string | Gallery; + } | null) | ({ relationTo: 'users'; value: string | User; @@ -520,6 +546,24 @@ export interface MediaSelect { focalX?: T; focalY?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "gallery_select". + */ +export interface GallerySelect { + title?: T; + updatedAt?: T; + createdAt?: T; + url?: T; + thumbnailURL?: T; + filename?: T; + mimeType?: T; + filesize?: T; + width?: T; + height?: T; + focalX?: T; + focalY?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". @@ -605,6 +649,7 @@ export interface PayloadMigrationsSelect { export interface Menu { id: string; text?: string | null; + richText?: LexicalRichText | null; updatedAt?: string | null; createdAt?: string | null; } @@ -625,6 +670,7 @@ export interface Setting { */ export interface MenuSelect { text?: T; + richText?: T; updatedAt?: T; createdAt?: T; globalType?: T; @@ -650,6 +696,20 @@ export interface CollectionsWidget { }; width: 'full'; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalUploadFields_7C90EEAC". + */ +export interface LexicalUploadFields_7C90EEAC { + caption?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "LexicalUploadFields_9521FA4A". + */ +export interface LexicalUploadFields_9521FA4A { + altText: string; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". @@ -705,11 +765,6 @@ export interface SerializedParagraphNode extends SerializedLexicalEle textStyle: string; } -export interface SerializedHorizontalRuleNode { - type: 'horizontalrule'; - version: number; -} - export type SerializedUploadNode = { type: 'upload'; format: LexicalElementFormat; @@ -723,6 +778,11 @@ export type SerializedUploadNode extends SerializedLexicalElementBase { type: 'quote'; } diff --git a/test/types/types.spec.ts b/test/types/types.spec.ts index ccb6b32eb80..a44f3f7d268 100644 --- a/test/types/types.spec.ts +++ b/test/types/types.spec.ts @@ -49,12 +49,14 @@ import type { SerializedListItemNode as GenLI, SerializedLinkNode as GenLink, SerializedListNode as GenList, - LexicalNodes_BFE38E95 as GenNodeUnion, + LexicalNodes_4CE595A9 as GenNodeUnion, SerializedParagraphNode as GenParagraph, SerializedQuoteNode as GenQuote, SerializedTabNode as GenTab, SerializedTextNode as GenText, Config as LocalConfig, + LexicalUploadFields_7C90EEAC as MediaUploadFields, + LexicalUploadFields_9521FA4A as GalleryUploadFields, Menu, MyRadioOptions, MySelectOptions, @@ -355,26 +357,20 @@ describe('Types testing', () => { } }) - test('ensure generated richText types can be assigned to DefaultTypedEditorState type', () => { - // If there is a function that expects DefaultTypedEditorState, you should be able to assign the generated type to it - // This ensures that data can be passed directly form the payload local API to a function that expects DefaultTypedEditorState - type GeneratedRichTextType = Post['richText'] - - expect().type.toBeAssignableFrom() - }) - - test('ensure DefaultTypedEditorState type can be assigned to GeneratedRichTextType type', () => { - /** - * Example: - * - * const mySeedData: RequiredDataFromCollectionSlug<'posts'> = { - * title: 'hello', - * richText: buildEditorState({text: 'hello'}) // <= DefaultTypedEditorState - * } - */ + test('ensure generated richText types can be assigned to DefaultTypedEditorState when no custom upload fields exist', () => { + // When no UploadFeature extra fields are configured, the generated type and DefaultTypedEditorState + // are bidirectionally assignable. With per-collection upload fields (as in this config), the generated + // type has narrower upload field types, so they diverge. In that case, use `buildEditorState()` + // instead of `buildEditorState()`. + // + // This test intentionally documents the divergence when custom upload fields are configured. type GeneratedRichTextType = Post['richText'] - expect().type.toBeAssignableFrom() + // The generated type and DefaultTypedEditorState are NOT bidirectionally assignable when custom + // upload fields narrow the node union. buildEditorState is the correct path. + expect().type.toBeAssignableFrom< + ReturnType> + >() }) test('ensure generated richText types can be assigned to SerializedEditorState (what converters consume)', () => { @@ -766,10 +762,9 @@ describe('Types testing', () => { expect(result.root.children[0]!.type).type.toBe<'block' | _Hardcoded_DefaultNodeTypes>() }) - test('buildEditorState result can be assigned to Post richText field', () => { - const result = buildEditorState({ text: 'hello' }) - type GeneratedRichTextType = Post['richText'] - expect(result).type.toBeAssignableTo() + test('buildEditorState with generated field type can be assigned to Post richText field', () => { + const result = buildEditorState({ text: 'hello' }) + expect(result).type.toBeAssignableTo() }) test('buildEditorState accepts a generated field type directly and returns exactly it', () => { @@ -1084,19 +1079,39 @@ describe('Types testing', () => { expect().type.toBeAssignableFrom() }) - test('SerializedUploadNode: generated <-> runtime', () => { - // `media` is the upload-enabled collection, so both sides resolve to - // `SerializedUploadNode<'media'>`. + test('SerializedUploadNode: generated narrows correctly per collection', () => { + // With per-collection upload fields, the generated type is a discriminated union of + // per-collection variants rather than one SerializedUploadNode with unioned generics. type GenUploadInUnion = Extract - expect().type.toBeAssignableFrom() - expect().type.toBeAssignableFrom() + type MediaVariant = Extract + type GalleryVariant = Extract + + expect().type.toHaveProperty('fields') + expect().type.toHaveProperty('fields') + + expect().type.toBe<'media'>() + expect().type.toBe<'gallery'>() }) - test('LexicalRichText.root: generated <-> runtime', () => { - type Gen = Post['richText']['root'] - type Run = DefaultTypedEditorState['root'] - expect().type.toBeAssignableFrom() - expect().type.toBeAssignableFrom() + test('SerializedUploadNode: discriminated fields per collection', () => { + type GenUpload = Extract + + type MediaUpload = Extract + type GalleryUpload = Extract + + expect().type.toBe() + expect().type.toBe() + + expect().type.toHaveProperty('caption') + expect().type.toHaveProperty('altText') + + expect().type.not.toHaveProperty('altText') + expect().type.not.toHaveProperty('caption') + }) + + test('LexicalRichText.root: generated root children are typed as the generated node union', () => { + type GenChild = Post['richText']['root']['children'][number] + expect().type.toBe() }) }) }) @@ -1110,6 +1125,7 @@ describe('Types testing', () => { const _sdk = new PayloadSDK({ baseURL: '' }) expect[0]['collection']>().type.toBe< | 'draft-posts' + | 'gallery' | 'media' | 'pages' | 'pages-categories' @@ -1128,6 +1144,7 @@ describe('Types testing', () => { // ensure collection property of sdk.create has posts in the union type expect[0]['collection']>().type.toBe< | 'draft-posts' + | 'gallery' | 'media' | 'pages' | 'pages-categories' @@ -1221,6 +1238,98 @@ describe('Types testing', () => { }) }) + describe('richText enforcement in local API and SDK', () => { + test('payload.create accepts buildEditorState output as richText', () => { + expect( + payload.create({ + collection: 'posts', + data: { + radioField: 'option-1', + richText: buildEditorState({ text: 'hello' }), + selectField: 'option-1', + }, + }), + ).type.not.toRaiseError() + }) + + test('payload.create accepts inline richText with correct node structure', () => { + expect( + payload.create({ + collection: 'posts', + data: { + radioField: 'option-1', + richText: { + root: { + type: 'root', + children: [ + { + type: 'paragraph', + children: [{ type: 'text', detail: 0, format: 0, mode: 'normal', style: '', text: 'hello', version: 1 }], + direction: null, + format: '', + indent: 0, + textFormat: 0, + textStyle: '', + version: 1, + }, + ], + direction: null, + format: '', + indent: 0, + version: 1, + }, + }, + selectField: 'option-1', + }, + }), + ).type.not.toRaiseError() + }) + + test('payload.update accepts richText via buildEditorState', () => { + expect( + payload.update({ + id: 1, + collection: 'posts', + data: { + richText: buildEditorState({ text: 'updated' }), + }, + }), + ).type.not.toRaiseError() + }) + + test('payload.updateGlobal accepts richText via buildEditorState', () => { + expect( + payload.updateGlobal({ + slug: 'menu', + data: { + richText: buildEditorState({ text: 'nav content' }), + }, + }), + ).type.not.toRaiseError() + }) + + test('SDK create accepts buildEditorState output as richText', () => { + const _sdk = new PayloadSDK({ baseURL: '' }) + + expect( + _sdk.create({ + collection: 'posts', + data: { + radioField: 'option-1', + richText: buildEditorState({ text: 'hello' }), + selectField: 'option-1', + }, + }), + ).type.not.toRaiseError() + }) + + test('convertLexicalToPlaintext accepts generated richText directly', () => { + const _post = null as unknown as Post + + expect(convertLexicalToPlaintext({ data: _post.richText })).type.not.toRaiseError() + }) + }) + describe('strictDraftTypes flag', () => { describe('query operations', () => { test('draft find query returns optional required fields when flag is enabled', async () => { From ef3f8048bc69d8a27c4be59412a047c328e1737f Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Fri, 5 Jun 2026 09:53:03 -0700 Subject: [PATCH 55/56] regen types --- test/admin/payload-types.ts | 4 +- test/fields/payload-types.ts | 58 ++- test/lexical/payload-types.ts | 565 +++++++++++---------- test/plugin-form-builder/payload-types.ts | 27 +- test/plugin-import-export/payload-types.ts | 69 ++- test/uploads/payload-types.ts | 131 +++-- test/versions/payload-types.ts | 32 +- 7 files changed, 453 insertions(+), 433 deletions(-) diff --git a/test/admin/payload-types.ts b/test/admin/payload-types.ts index f00e12786ed..1503ea699a7 100644 --- a/test/admin/payload-types.ts +++ b/test/admin/payload-types.ts @@ -1807,6 +1807,6 @@ export interface LexicalRichText { declare module 'payload' { - // @ts-ignore + // @ts-ignore export interface GeneratedTypes extends Config {} -} +} \ No newline at end of file diff --git a/test/fields/payload-types.ts b/test/fields/payload-types.ts index f395cadf21f..594bb6591da 100644 --- a/test/fields/payload-types.ts +++ b/test/fields/payload-types.ts @@ -64,22 +64,23 @@ export type SupportedTimezones = | 'UTC'; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_E99B774E". + * via the `definition` "LexicalNodes_E074AD98". */ -export type LexicalNodes_E99B774E = +export type LexicalNodes_E074AD98 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> - | SerializedHeadingNode - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedListNode - | SerializedListItemNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedHeadingNode + | SerializedUploadNode<'uploads'> + | SerializedUploadNode<'uploads2'> + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedRelationshipNode< | 'users' | 'select-versions-fields' @@ -122,16 +123,17 @@ export type LexicalNodes_E99B774E = >; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_A9A5E3FC". + * via the `definition` "LexicalNodes_313DC238". */ -export type LexicalNodes_A9A5E3FC = +export type LexicalNodes_313DC238 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedHorizontalRuleNode - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedUploadNode<'uploads'> + | SerializedUploadNode<'uploads2'> + | SerializedQuoteNode | SerializedRelationshipNode< | 'users' | 'select-versions-fields' @@ -172,11 +174,11 @@ export type LexicalNodes_A9A5E3FC = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; export interface Config { auth: { @@ -422,7 +424,7 @@ export interface ArrayField { text: string; anotherText?: string | null; localizedText?: string | null; - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; subArray?: | { text?: string | null; @@ -589,7 +591,7 @@ export interface BlockField { */ export interface ContentBlock { text: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; id?: string | null; blockName?: string | null; blockType: 'content'; @@ -661,7 +663,7 @@ export interface TabsBlock { */ export interface LocalizedContentBlock { text: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; id?: string | null; blockName?: string | null; blockType: 'localizedContent'; @@ -1075,7 +1077,7 @@ export interface ConditionalLogic { customFieldWithHOC?: string | null; customClientFieldWithCondition?: string | null; customServerFieldWithCondition?: string | null; - conditionalRichText?: LexicalRichText | null; + conditionalRichText?: LexicalRichText | null; userConditional?: string | null; parentGroup?: { enableParentGroupFields?: boolean | null; @@ -3996,9 +3998,9 @@ export interface MyBlock { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_E99B774E". + * via the `definition` "LexicalLinkFields_E074AD98". */ -export interface LexicalLinkFields_E99B774E { +export interface LexicalLinkFields_E074AD98 { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -4170,6 +4172,6 @@ export interface SerializedHorizontalRuleNode { declare module 'payload' { - // @ts-ignore + // @ts-ignore export interface GeneratedTypes extends Config {} -} +} \ No newline at end of file diff --git a/test/lexical/payload-types.ts b/test/lexical/payload-types.ts index eac96373539..9e38bb790cd 100644 --- a/test/lexical/payload-types.ts +++ b/test/lexical/payload-types.ts @@ -62,16 +62,17 @@ export type SupportedTimezones = | 'Pacific/Fiji'; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_29DEEC7D". + * via the `definition` "LexicalNodes_5AC12460". */ -export type LexicalNodes_29DEEC7D = +export type LexicalNodes_5AC12460 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedHorizontalRuleNode - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedUploadNode<'uploads'> + | SerializedUploadNode<'uploads2'> + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -108,20 +109,20 @@ export type LexicalNodes_29DEEC7D = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_C9EBCCB8". + * via the `definition` "LexicalNodes_51C70DFC". */ -export type LexicalNodes_C9EBCCB8 = +export type LexicalNodes_51C70DFC = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode< | BenchBlock1 | BenchBlock2 @@ -156,8 +157,9 @@ export type LexicalNodes_C9EBCCB8 = > | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedUploadNode<'uploads'> + | SerializedUploadNode<'uploads2'> + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -194,28 +196,29 @@ export type LexicalNodes_C9EBCCB8 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_29A2F1FE". + * via the `definition` "LexicalNodes_4189F979". */ -export type LexicalNodes_29A2F1FE = +export type LexicalNodes_4189F979 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode | SerializedHorizontalRuleNode - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedUploadNode<'uploads'> + | SerializedUploadNode<'uploads2'> + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -252,27 +255,28 @@ export type LexicalNodes_29A2F1FE = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_E05AD439". + * via the `definition` "LexicalNodes_D1C84E9E". */ -export type LexicalNodes_E05AD439 = +export type LexicalNodes_D1C84E9E = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedParagraphNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedUploadNode<'uploads'> + | SerializedUploadNode<'uploads2'> + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -309,23 +313,24 @@ export type LexicalNodes_E05AD439 = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_533C9B9B". + * via the `definition` "LexicalNodes_C4CC3409". */ -export type LexicalNodes_533C9B9B = +export type LexicalNodes_C4CC3409 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedParagraphNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedUploadNode<'uploads'> + | SerializedUploadNode<'uploads2'> + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -362,9 +367,9 @@ export type LexicalNodes_533C9B9B = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "LexicalNodes_2C2D92D6". @@ -378,17 +383,18 @@ export type LexicalNodes_2C2D92D6 = | SerializedListItemNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_1DE931C3". + * via the `definition` "LexicalNodes_02CE3078". */ -export type LexicalNodes_1DE931C3 = +export type LexicalNodes_02CE3078 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedHeadingNode + | SerializedParagraphNode + | SerializedHeadingNode | SerializedHorizontalRuleNode - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedUploadNode<'uploads'> + | SerializedUploadNode<'uploads2'> + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -425,28 +431,29 @@ export type LexicalNodes_1DE931C3 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_3F819CB3". + * via the `definition` "LexicalNodes_27C59130". */ -export type LexicalNodes_3F819CB3 = +export type LexicalNodes_27C59130 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> - | SerializedHeadingNode - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedListNode - | SerializedListItemNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedHeadingNode + | SerializedUploadNode<'uploads'> + | SerializedUploadNode<'uploads2'> + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -485,18 +492,19 @@ export type LexicalNodes_3F819CB3 = >; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_48D9D1B0". + * via the `definition` "LexicalNodes_903D3919". */ -export type LexicalNodes_48D9D1B0 = +export type LexicalNodes_903D3919 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedUploadNode<'uploads'> + | SerializedUploadNode<'uploads2'> + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -533,11 +541,11 @@ export type LexicalNodes_48D9D1B0 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "BlockColumns". @@ -578,16 +586,16 @@ export type LexicalNodes_2EF528CD = | SerializedInlineBlockNode<{blockType: string}>; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_556D3D48". + * via the `definition` "LexicalNodes_80D343B4". */ -export type LexicalNodes_556D3D48 = +export type LexicalNodes_80D343B4 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode + | SerializedParagraphNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode | SerializedBlockNode< | ValidationBlock | FilterOptionsBlock @@ -617,11 +625,12 @@ export type LexicalNodes_556D3D48 = | MyInlineBlockWithBlock | MyInlineBlockWithBlockAndLabel > - | SerializedUploadNode<'uploads' | 'uploads2', LexicalUploadFields_5F1A55C0> - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedUploadNode<'uploads', LexicalUploadFields_224D209A> + | SerializedUploadNode<'uploads2'> + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -658,23 +667,24 @@ export type LexicalNodes_556D3D48 = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_BE093052". + * via the `definition` "LexicalNodes_6A840C50". */ -export type LexicalNodes_BE093052 = +export type LexicalNodes_6A840C50 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedUploadNode<'uploads'> + | SerializedUploadNode<'uploads2'> + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -711,25 +721,26 @@ export type LexicalNodes_BE093052 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_68573818". + * via the `definition` "LexicalNodes_93C8E7A2". */ -export type LexicalNodes_68573818 = +export type LexicalNodes_93C8E7A2 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedUploadNode<'uploads'> + | SerializedUploadNode<'uploads2'> + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -766,25 +777,26 @@ export type LexicalNodes_68573818 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_63106233". + * via the `definition` "LexicalNodes_BD5C150F". */ -export type LexicalNodes_63106233 = +export type LexicalNodes_BD5C150F = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedBlockNode + | SerializedParagraphNode + | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedUploadNode<'uploads'> + | SerializedUploadNode<'uploads2'> + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -821,25 +833,26 @@ export type LexicalNodes_63106233 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_2E7BE0FA". + * via the `definition` "LexicalNodes_192D873F". */ -export type LexicalNodes_2E7BE0FA = +export type LexicalNodes_192D873F = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedUploadNode<'uploads'> + | SerializedUploadNode<'uploads2'> + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -876,25 +889,26 @@ export type LexicalNodes_2E7BE0FA = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_67B1150A". + * via the `definition` "LexicalNodes_D31F0167". */ -export type LexicalNodes_67B1150A = +export type LexicalNodes_D31F0167 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedUploadNode<'uploads'> + | SerializedUploadNode<'uploads2'> + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -931,25 +945,26 @@ export type LexicalNodes_67B1150A = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_3DA3D872". + * via the `definition` "LexicalNodes_E46FF336". */ -export type LexicalNodes_3DA3D872 = +export type LexicalNodes_E46FF336 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedUploadNode<'uploads'> + | SerializedUploadNode<'uploads2'> + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -986,21 +1001,22 @@ export type LexicalNodes_3DA3D872 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_295A68C8". + * via the `definition` "LexicalNodes_2A14730B". */ -export type LexicalNodes_295A68C8 = +export type LexicalNodes_2A14730B = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedUploadNode<'uploads' | 'uploads2'>; + | SerializedParagraphNode + | SerializedUploadNode<'uploads'> + | SerializedUploadNode<'uploads2'>; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "LexicalNodes_245E32E8". @@ -1036,18 +1052,19 @@ export type LexicalNodes_703DA597 = | SerializedInlineBlockNode<{blockType: string}>; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_3D210EC6". + * via the `definition` "LexicalNodes_AFD89559". */ -export type LexicalNodes_3D210EC6 = +export type LexicalNodes_AFD89559 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedParagraphNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedUploadNode<'uploads'> + | SerializedUploadNode<'uploads2'> + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1084,9 +1101,9 @@ export type LexicalNodes_3D210EC6 = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "LexicalNodes_86068B65". @@ -1107,13 +1124,13 @@ export type LexicalNodes_86068B65 = | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_1A4AEB92". + * via the `definition` "LexicalNodes_419CE8C9". */ -export type LexicalNodes_1A4AEB92 = +export type LexicalNodes_419CE8C9 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1151,13 +1168,14 @@ export type LexicalNodes_1A4AEB92 = | 'payload-migrations' > | SerializedHorizontalRuleNode - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedUploadNode<'uploads'> + | SerializedUploadNode<'uploads2'> + | SerializedQuoteNode + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "LexicalNodes_54186730". @@ -1213,18 +1231,19 @@ export type LexicalNodes_54186730 = | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_6DEEAAB8". + * via the `definition` "LexicalNodes_806A786F". */ -export type LexicalNodes_6DEEAAB8 = +export type LexicalNodes_806A786F = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> | SerializedHorizontalRuleNode - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode + | SerializedUploadNode<'uploads'> + | SerializedUploadNode<'uploads2'> + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1261,27 +1280,28 @@ export type LexicalNodes_6DEEAAB8 = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_A8AEB0F1". + * via the `definition` "LexicalNodes_5F0B8784". */ -export type LexicalNodes_A8AEB0F1 = +export type LexicalNodes_5F0B8784 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> - | SerializedUploadNode<'uploads' | 'uploads2', LexicalUploadFields_5F1A55C0> - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedUploadNode<'uploads', LexicalUploadFields_224D209A> + | SerializedUploadNode<'uploads2'> + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedHorizontalRuleNode - | SerializedQuoteNode + | SerializedQuoteNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1318,30 +1338,31 @@ export type LexicalNodes_A8AEB0F1 = | 'payload-preferences' | 'payload-migrations' > - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_0B0D3C8D". + * via the `definition` "LexicalNodes_FFF6D80A". */ -export type LexicalNodes_0B0D3C8D = +export type LexicalNodes_FFF6D80A = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode - | SerializedTableNode - | SerializedTableCellNode - | SerializedTableRowNode + | SerializedParagraphNode + | SerializedTableNode + | SerializedTableCellNode + | SerializedTableRowNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> - | SerializedHeadingNode - | SerializedUploadNode<'uploads' | 'uploads2'> - | SerializedQuoteNode - | SerializedListNode - | SerializedListItemNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedHeadingNode + | SerializedUploadNode<'uploads'> + | SerializedUploadNode<'uploads2'> + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedRelationshipNode< | 'lexical-benchmark' | 'lexical-fully-featured' @@ -1549,7 +1570,7 @@ export interface BlockWithBlockRef_DBAB1AB1 { */ export interface LexicalBenchmark { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1559,7 +1580,7 @@ export interface LexicalBenchmark { */ export interface LexicalFullyFeatured { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1572,7 +1593,7 @@ export interface LexicalAutosave { title?: string | null; cta?: | { - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; id?: string | null; }[] | null; @@ -1586,7 +1607,7 @@ export interface LexicalAutosave { */ export interface LexicalLinkFeature { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1606,7 +1627,7 @@ export interface LexicalListsFeature { */ export interface LexicalHeadingFeature { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1616,7 +1637,7 @@ export interface LexicalHeadingFeature { */ export interface LexicalJsxConverter { id: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1627,7 +1648,7 @@ export interface LexicalJsxConverter { export interface LexicalField { id: string; title: string; - lexicalRootEditor?: LexicalRichText | null; + lexicalRootEditor?: LexicalRichText | null; /** * A simple lexical field */ @@ -1635,7 +1656,7 @@ export interface LexicalField { /** * Should not be rendered */ - lexicalWithBlocks: LexicalRichText; + lexicalWithBlocks: LexicalRichText; lexicalWithBlocks_markdown?: string | null; updatedAt: string; createdAt: string; @@ -1646,8 +1667,8 @@ export interface LexicalField { */ export interface LexicalView { id: string; - customDefaultView?: LexicalRichText | null; - vanillaView?: LexicalRichText | null; + customDefaultView?: LexicalRichText | null; + vanillaView?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1657,7 +1678,7 @@ export interface LexicalView { */ export interface LexicalViewsFrontend { id: string; - customFrontendViews?: LexicalRichText | null; + customFrontendViews?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1668,7 +1689,7 @@ export interface LexicalViewsFrontend { export interface LexicalViewsProvider { id: string; viewProviderWrapper?: { - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; }; updatedAt: string; createdAt: string; @@ -1680,7 +1701,7 @@ export interface LexicalViewsProvider { export interface LexicalViewsProviderDefault { id: string; defaultViewWrapper?: { - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; }; updatedAt: string; createdAt: string; @@ -1692,7 +1713,7 @@ export interface LexicalViewsProviderDefault { export interface LexicalViewsProviderFallback { id: string; fallbackViewWrapper?: { - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; }; updatedAt: string; createdAt: string; @@ -1703,7 +1724,7 @@ export interface LexicalViewsProviderFallback { */ export interface LexicalViewsNested { id: string; - parentRichText?: LexicalRichText | null; + parentRichText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1717,11 +1738,11 @@ export interface LexicalLocalizedField { /** * Non-localized field with localized block subfields */ - lexicalBlocksSubLocalized?: LexicalRichText | null; + lexicalBlocksSubLocalized?: LexicalRichText | null; /** * Localized field with localized block subfields */ - lexicalBlocksLocalized?: LexicalRichText | null; + lexicalBlocksLocalized?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1731,8 +1752,8 @@ export interface LexicalLocalizedField { */ export interface LexicalObjectReferenceBug { id: string; - lexicalDefault?: LexicalRichText | null; - lexicalEditor?: LexicalRichText | null; + lexicalDefault?: LexicalRichText | null; + lexicalEditor?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1775,7 +1796,7 @@ export interface LexicalAutosaveBlock { export interface LexicalAccessControl { id: string; title?: string | null; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1786,7 +1807,7 @@ export interface LexicalAccessControl { export interface LexicalRelationshipField { id: string; richText?: LexicalRichText | null; - richText2?: LexicalRichText | null; + richText2?: LexicalRichText | null; richText3?: LexicalRichText | null; richTextLocalized?: LexicalRichText | null; updatedAt: string; @@ -1799,7 +1820,7 @@ export interface LexicalRelationshipField { */ export interface Collision { id: string; - collision?: LexicalRichText | null; + collision?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1810,7 +1831,7 @@ export interface Collision { export interface LexicalNestedBlock { id: string; title: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -1821,12 +1842,12 @@ export interface LexicalNestedBlock { export interface RichTextField { id: string; title: string; - lexicalCustomFields: LexicalRichText; + lexicalCustomFields: LexicalRichText; lexicalCustomFields_html?: string | null; /** * This rich text field uses the lexical editor. */ - lexical?: LexicalRichText | null; + lexical?: LexicalRichText | null; /** * This select field is rendered here to ensure its options dropdown renders above the rich text toolbar. */ @@ -2074,7 +2095,7 @@ export interface OnDemandOutsideForm { | number | boolean | null; - hiddenAnchor?: LexicalRichText | null; + hiddenAnchor?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2085,7 +2106,7 @@ export interface OnDemandOutsideForm { export interface LexicalCustomCell { id: string; title: string; - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; updatedAt: string; createdAt: string; } @@ -2926,10 +2947,10 @@ export interface PayloadMigrationsSelect { export interface TabsWithRichText { id: string; tab1?: { - rt1?: LexicalRichText | null; + rt1?: LexicalRichText | null; }; tab2?: { - rt2?: LexicalRichText | null; + rt2?: LexicalRichText | null; }; updatedAt?: string | null; createdAt?: string | null; @@ -3459,9 +3480,9 @@ export interface TextBlock { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_E05AD439". + * via the `definition` "LexicalLinkFields_D1C84E9E". */ -export interface LexicalLinkFields_E05AD439 { +export interface LexicalLinkFields_D1C84E9E { linkBlocks?: LinkBlock[] | null; doc?: { relationTo: string; @@ -3479,9 +3500,9 @@ export interface LexicalLinkFields_E05AD439 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_533C9B9B". + * via the `definition` "LexicalLinkFields_C4CC3409". */ -export interface LexicalLinkFields_533C9B9B { +export interface LexicalLinkFields_C4CC3409 { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3513,9 +3534,9 @@ export interface MyBlock_89EF3EA7 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_3F819CB3". + * via the `definition` "LexicalLinkFields_27C59130". */ -export interface LexicalLinkFields_3F819CB3 { +export interface LexicalLinkFields_27C59130 { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3538,7 +3559,7 @@ export interface LexicalLinkFields_3F819CB3 { export interface LexicalAndUploadBlock { id: string; blockType: 'lexicalAndUploadBlock'; - subRichTextField?: LexicalRichText | null; + subRichTextField?: LexicalRichText | null; subUploadField?: (string | null) | Upload; blockName?: string | null; } @@ -3549,7 +3570,7 @@ export interface LexicalAndUploadBlock { export interface RichTextBlock { id: string; blockType: 'richTextBlock'; - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; blockName?: string | null; } /** @@ -3570,7 +3591,7 @@ export interface UploadAndRichText { id: string; blockType: 'uploadAndRichText'; upload: string | Upload; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; blockName?: string | null; } /** @@ -3617,7 +3638,7 @@ export interface RelationshipHasManyBlock { * via the `definition` "ContentBlock". */ export interface ContentBlock { - richText: LexicalRichText; + richText: LexicalRichText; id?: string | null; blockName?: string | null; blockType: 'contentBlock'; @@ -3863,16 +3884,16 @@ export interface MyInlineBlockWithBlockAndLabel { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalUploadFields_5F1A55C0". + * via the `definition` "LexicalUploadFields_224D209A". */ -export interface LexicalUploadFields_5F1A55C0 { - caption?: LexicalRichText | null; +export interface LexicalUploadFields_224D209A { + caption?: LexicalRichText | null; } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_556D3D48". + * via the `definition` "LexicalLinkFields_80D343B4". */ -export interface LexicalLinkFields_556D3D48 { +export interface LexicalLinkFields_80D343B4 { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -3910,20 +3931,20 @@ export interface BannerBlock { blockType: 'banner'; type: 'normal' | 'important'; title: string; - content?: LexicalRichText | null; + content?: LexicalRichText | null; blockName?: string | null; } /** * Multiple blocks resolve to the `ContentBlock` interface with different fields, so a content hash is appended to keep the generated types stable and unambiguous. Set a unique `interfaceName` on the block to choose the name yourself. See https://payloadcms.com/docs/typescript/generating-types#block-interface-name-collisions * * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "ContentBlock_A3B1CF88". + * via the `definition` "ContentBlock_8653F325". */ -export interface ContentBlock_A3B1CF88 { +export interface ContentBlock_8653F325 { id: string; blockType: 'content-block'; title: string; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; blockName?: string | null; } /** @@ -3935,7 +3956,7 @@ export interface ProviderBannerBlock { blockType: 'banner'; type: 'normal' | 'important'; title: string; - content?: LexicalRichText | null; + content?: LexicalRichText | null; blockName?: string | null; } /** @@ -3946,7 +3967,7 @@ export interface NestedContentBlock { id: string; blockType: 'nested-content'; label: string; - nestedRichText?: LexicalRichText | null; + nestedRichText?: LexicalRichText | null; blockName?: string | null; } /** @@ -3982,7 +4003,7 @@ export interface BlockInLexical { /** * Some Description */ - lexicalInBlock: LexicalRichText; + lexicalInBlock: LexicalRichText; blockName?: string | null; } /** @@ -4001,7 +4022,7 @@ export interface InlineBlockInLexical { export interface BlockWithRichText { id: string; blockType: 'blockWithRichText'; - nestedRichText?: LexicalRichText | null; + nestedRichText?: LexicalRichText | null; blockName?: string | null; } /** @@ -4016,9 +4037,9 @@ export interface Block { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_3D210EC6". + * via the `definition` "LexicalLinkFields_AFD89559". */ -export interface LexicalLinkFields_3D210EC6 { +export interface LexicalLinkFields_AFD89559 { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -4046,9 +4067,9 @@ export interface BlockWithBlockRef { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_A8AEB0F1". + * via the `definition` "LexicalLinkFields_5F0B8784". */ -export interface LexicalLinkFields_A8AEB0F1 { +export interface LexicalLinkFields_5F0B8784 { linkType: 'custom' | 'internal'; url?: string; doc?: { @@ -4069,9 +4090,9 @@ export interface LexicalLinkFields_A8AEB0F1 { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_0B0D3C8D". + * via the `definition` "LexicalLinkFields_FFF6D80A". */ -export interface LexicalLinkFields_0B0D3C8D { +export interface LexicalLinkFields_FFF6D80A { linkType: 'custom' | 'internal'; url?: string; doc?: { diff --git a/test/plugin-form-builder/payload-types.ts b/test/plugin-form-builder/payload-types.ts index f66c04fe96c..5572f66cf37 100644 --- a/test/plugin-form-builder/payload-types.ts +++ b/test/plugin-form-builder/payload-types.ts @@ -62,16 +62,17 @@ export type SupportedTimezones = | 'Pacific/Fiji'; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_2AAF05BF". + * via the `definition` "LexicalNodes_47A9529B". */ -export type LexicalNodes_2AAF05BF = +export type LexicalNodes_47A9529B = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedHorizontalRuleNode - | SerializedUploadNode<'media' | 'documents'> - | SerializedQuoteNode + | SerializedUploadNode<'media'> + | SerializedUploadNode<'documents'> + | SerializedQuoteNode | SerializedRelationshipNode< | 'pages' | 'users' @@ -81,11 +82,11 @@ export type LexicalNodes_2AAF05BF = | 'payload-preferences' | 'payload-migrations' > - | SerializedAutoLinkNode - | SerializedLinkNode - | SerializedListNode - | SerializedListItemNode - | SerializedHeadingNode; + | SerializedAutoLinkNode + | SerializedLinkNode + | SerializedListNode + | SerializedListItemNode + | SerializedHeadingNode; export interface Config { auth: { @@ -213,7 +214,7 @@ export interface Form { * Choose whether to display an on-page message or redirect to a different page after they submit the form. */ confirmationType?: ('message' | 'redirect') | null; - confirmationMessage?: LexicalRichText; + confirmationMessage?: LexicalRichText; redirect?: { type?: ('reference' | 'custom') | null; reference?: { @@ -236,7 +237,7 @@ export interface Form { /** * Enter the message that should be sent in this email. */ - message?: LexicalRichText | null; + message?: LexicalRichText | null; id?: string | null; }[] | null; @@ -289,7 +290,7 @@ export interface Email { * via the `definition` "Message". */ export interface Message { - message?: LexicalRichText | null; + message?: LexicalRichText | null; id?: string | null; blockName?: string | null; blockType: 'message'; diff --git a/test/plugin-import-export/payload-types.ts b/test/plugin-import-export/payload-types.ts index bf0c34ab138..26fcd488ee0 100644 --- a/test/plugin-import-export/payload-types.ts +++ b/test/plugin-import-export/payload-types.ts @@ -63,40 +63,37 @@ export type SupportedTimezones = | 'UTC'; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_8C0174C1". + * via the `definition` "LexicalNodes_A2D343B3". */ -export type LexicalNodes_8C0174C1 = +export type LexicalNodes_A2D343B3 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> - | SerializedHeadingNode - | SerializedUploadNode< - | 'media' - | 'exports' - | 'posts-export' - | 'posts-no-jobs-queue-export' - | 'posts-with-s3-export' - | 'posts-with-limits-export' - | 'posts-with-hooks-export' - | 'posts-with-field-hooks-export' - | 'posts-with-column-map-export' - | 'imports' - | 'posts-import' - | 'posts-with-s3-import' - | 'posts-with-limits-import' - | 'posts-with-hooks-import' - | 'posts-with-field-hooks-import' - | 'posts-with-column-map-import', - LexicalUploadFields_1AB4670B - > - | SerializedQuoteNode - | SerializedListNode - | SerializedListItemNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedHeadingNode + | SerializedUploadNode<'media', LexicalUploadFields_1AB4670B> + | SerializedUploadNode<'exports'> + | SerializedUploadNode<'posts-export'> + | SerializedUploadNode<'posts-no-jobs-queue-export'> + | SerializedUploadNode<'posts-with-s3-export'> + | SerializedUploadNode<'posts-with-limits-export'> + | SerializedUploadNode<'posts-with-hooks-export'> + | SerializedUploadNode<'posts-with-field-hooks-export'> + | SerializedUploadNode<'posts-with-column-map-export'> + | SerializedUploadNode<'imports'> + | SerializedUploadNode<'posts-import'> + | SerializedUploadNode<'posts-with-s3-import'> + | SerializedUploadNode<'posts-with-limits-import'> + | SerializedUploadNode<'posts-with-hooks-import'> + | SerializedUploadNode<'posts-with-field-hooks-import'> + | SerializedUploadNode<'posts-with-column-map-import'> + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedRelationshipNode< | 'users' | 'pages' @@ -340,7 +337,7 @@ export interface Page { | number | boolean | null; - richTextField?: LexicalRichText | null; + richTextField?: LexicalRichText | null; relationship?: (string | null) | User; excerpt?: string | null; /** @@ -408,7 +405,7 @@ export interface Hero { * via the `definition` "Content". */ export interface Content { - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; id?: string | null; blockName?: string | null; blockType: 'content'; @@ -420,7 +417,7 @@ export interface Content { export interface Post { id: string; title: string; - content?: LexicalRichText | null; + content?: LexicalRichText | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -451,7 +448,7 @@ export interface Media { export interface PostsExportsOnly { id: string; title: string; - content?: LexicalRichText | null; + content?: LexicalRichText | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -463,7 +460,7 @@ export interface PostsExportsOnly { export interface PostsImportsOnly { id: string; title: string; - content?: LexicalRichText | null; + content?: LexicalRichText | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -475,7 +472,7 @@ export interface PostsImportsOnly { export interface PostsNoJobsQueue { id: string; title: string; - content?: LexicalRichText | null; + content?: LexicalRichText | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -2324,9 +2321,9 @@ export interface LexicalUploadFields_1AB4670B { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_8C0174C1". + * via the `definition` "LexicalLinkFields_A2D343B3". */ -export interface LexicalLinkFields_8C0174C1 { +export interface LexicalLinkFields_A2D343B3 { linkType: 'custom' | 'internal'; url?: string; doc?: { diff --git a/test/uploads/payload-types.ts b/test/uploads/payload-types.ts index f78c61dd824..df527e1a9f7 100644 --- a/test/uploads/payload-types.ts +++ b/test/uploads/payload-types.ts @@ -62,76 +62,73 @@ export type SupportedTimezones = | 'Pacific/Fiji'; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_C5C3B369". + * via the `definition` "LexicalNodes_ED428AB9". */ -export type LexicalNodes_C5C3B369 = +export type LexicalNodes_ED428AB9 = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> - | SerializedHeadingNode - | SerializedUploadNode< - | 'gif-resize' - | 'filename-compound-index' - | 'no-image-sizes' - | 'object-fit' - | 'with-meta-data' - | 'without-meta-data' - | 'with-only-jpeg-meta-data' - | 'crop-only' - | 'focal-only' - | 'image-sizes-only' - | 'focal-no-sizes' - | 'media' - | 'allow-list-media' - | 'skip-safe-fetch-media' - | 'skip-safe-fetch-header-filter' - | 'skip-allow-list-safe-fetch-media' - | 'restrict-file-types' - | 'no-restrict-file-types' - | 'no-restrict-file-mime-types' - | 'pdf-only' - | 'restricted-mime-types' - | 'animated-type-media' - | 'enlarge' - | 'without-enlarge' - | 'reduce' - | 'media-trim' - | 'custom-file-name-media' - | 'unstored-media' - | 'externally-served-media' - | 'uploads-1' - | 'admin-thumbnail-function' - | 'admin-thumbnail-with-search-queries' - | 'admin-thumbnail-size' - | 'admin-upload-control' - | 'no-files-required' - | 'optional-file' - | 'required-file' - | 'versions' - | 'custom-upload-field' - | 'media-with-relation-preview' - | 'media-without-cache-tags' - | 'media-without-relation-preview' - | 'hide-file-input-on-create' - | 'three-dimensional' - | 'constructor-options' - | 'bulk-uploads' - | 'bulk-uploads-hook-error' - | 'file-mime-type' - | 'svg-only' - | 'media-without-delete-access' - | 'media-with-image-size-admin-props' - | 'prefix-media', - LexicalUploadFields_1AB4670B - > - | SerializedQuoteNode - | SerializedListNode - | SerializedListItemNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedHeadingNode + | SerializedUploadNode<'gif-resize'> + | SerializedUploadNode<'filename-compound-index'> + | SerializedUploadNode<'no-image-sizes'> + | SerializedUploadNode<'object-fit'> + | SerializedUploadNode<'with-meta-data'> + | SerializedUploadNode<'without-meta-data'> + | SerializedUploadNode<'with-only-jpeg-meta-data'> + | SerializedUploadNode<'crop-only'> + | SerializedUploadNode<'focal-only'> + | SerializedUploadNode<'image-sizes-only'> + | SerializedUploadNode<'focal-no-sizes'> + | SerializedUploadNode<'media', LexicalUploadFields_1AB4670B> + | SerializedUploadNode<'allow-list-media'> + | SerializedUploadNode<'skip-safe-fetch-media'> + | SerializedUploadNode<'skip-safe-fetch-header-filter'> + | SerializedUploadNode<'skip-allow-list-safe-fetch-media'> + | SerializedUploadNode<'restrict-file-types'> + | SerializedUploadNode<'no-restrict-file-types'> + | SerializedUploadNode<'no-restrict-file-mime-types'> + | SerializedUploadNode<'pdf-only'> + | SerializedUploadNode<'restricted-mime-types'> + | SerializedUploadNode<'animated-type-media'> + | SerializedUploadNode<'enlarge'> + | SerializedUploadNode<'without-enlarge'> + | SerializedUploadNode<'reduce'> + | SerializedUploadNode<'media-trim'> + | SerializedUploadNode<'custom-file-name-media'> + | SerializedUploadNode<'unstored-media'> + | SerializedUploadNode<'externally-served-media'> + | SerializedUploadNode<'uploads-1'> + | SerializedUploadNode<'admin-thumbnail-function'> + | SerializedUploadNode<'admin-thumbnail-with-search-queries'> + | SerializedUploadNode<'admin-thumbnail-size'> + | SerializedUploadNode<'admin-upload-control'> + | SerializedUploadNode<'no-files-required'> + | SerializedUploadNode<'optional-file'> + | SerializedUploadNode<'required-file'> + | SerializedUploadNode<'versions'> + | SerializedUploadNode<'custom-upload-field'> + | SerializedUploadNode<'media-with-relation-preview'> + | SerializedUploadNode<'media-without-cache-tags'> + | SerializedUploadNode<'media-without-relation-preview'> + | SerializedUploadNode<'hide-file-input-on-create'> + | SerializedUploadNode<'three-dimensional'> + | SerializedUploadNode<'constructor-options'> + | SerializedUploadNode<'bulk-uploads'> + | SerializedUploadNode<'bulk-uploads-hook-error'> + | SerializedUploadNode<'file-mime-type'> + | SerializedUploadNode<'svg-only'> + | SerializedUploadNode<'media-without-delete-access'> + | SerializedUploadNode<'media-with-image-size-admin-props'> + | SerializedUploadNode<'prefix-media'> + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedRelationshipNode< | 'relation' | 'audio' @@ -1412,7 +1409,7 @@ export interface Uploads1 { singleUpload?: (string | null) | Uploads2; hasManyThumbnailUpload?: (string | AdminThumbnailSize)[] | null; singleThumbnailUpload?: (string | null) | AdminThumbnailSize; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; updatedAt: string; createdAt: string; url?: string | null; @@ -4141,9 +4138,9 @@ export interface LexicalUploadFields_1AB4670B { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_C5C3B369". + * via the `definition` "LexicalLinkFields_ED428AB9". */ -export interface LexicalLinkFields_C5C3B369 { +export interface LexicalLinkFields_ED428AB9 { linkType: 'custom' | 'internal'; url?: string; doc?: { diff --git a/test/versions/payload-types.ts b/test/versions/payload-types.ts index 128e7cc2525..c1ed43967db 100644 --- a/test/versions/payload-types.ts +++ b/test/versions/payload-types.ts @@ -62,22 +62,24 @@ export type SupportedTimezones = | 'Pacific/Fiji'; /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalNodes_985FB45B". + * via the `definition` "LexicalNodes_CD4D3FCC". */ -export type LexicalNodes_985FB45B = +export type LexicalNodes_CD4D3FCC = | SerializedTextNode | SerializedTabNode | SerializedLineBreakNode - | SerializedParagraphNode + | SerializedParagraphNode | SerializedBlockNode | SerializedInlineBlockNode<{blockType: string}> - | SerializedHeadingNode - | SerializedUploadNode<'draft-with-upload' | 'media' | 'media2', LexicalUploadFields_1AB4670B> - | SerializedQuoteNode - | SerializedListNode - | SerializedListItemNode - | SerializedAutoLinkNode - | SerializedLinkNode + | SerializedHeadingNode + | SerializedUploadNode<'draft-with-upload'> + | SerializedUploadNode<'media', LexicalUploadFields_1AB4670B> + | SerializedUploadNode<'media2'> + | SerializedQuoteNode + | SerializedListNode + | SerializedListItemNode + | SerializedAutoLinkNode + | SerializedLinkNode | SerializedRelationshipNode< | 'disable-publish' | 'posts' @@ -283,7 +285,7 @@ export interface AutosavePost { title: string; relationship?: (string | null) | Post; computedTitle?: string | null; - richText?: LexicalRichText | null; + richText?: LexicalRichText | null; json?: | { [k: string]: unknown; @@ -581,8 +583,8 @@ export interface Diff { )[] | null; zeroDepthRelationship?: (string | null) | User; - richtext?: LexicalRichText | null; - richtextWithCustomDiff?: LexicalRichText | null; + richtext?: LexicalRichText | null; + richtextWithCustomDiff?: LexicalRichText | null; textInRow?: string | null; textCannotRead?: string | null; select?: ('option1' | 'option2') | null; @@ -1833,9 +1835,9 @@ export interface LexicalUploadFields_1AB4670B { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "LexicalLinkFields_985FB45B". + * via the `definition` "LexicalLinkFields_CD4D3FCC". */ -export interface LexicalLinkFields_985FB45B { +export interface LexicalLinkFields_CD4D3FCC { linkType: 'custom' | 'internal'; url?: string; doc?: { From d96698e5fa5a4b698e33ea5cad7e47979b3c3deb Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Fri, 5 Jun 2026 10:01:18 -0700 Subject: [PATCH 56/56] fix unit tests that paul broke --- .../payload/src/utilities/configToJSONSchema.spec.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/payload/src/utilities/configToJSONSchema.spec.ts b/packages/payload/src/utilities/configToJSONSchema.spec.ts index a0a31e67f17..62df138118c 100644 --- a/packages/payload/src/utilities/configToJSONSchema.spec.ts +++ b/packages/payload/src/utilities/configToJSONSchema.spec.ts @@ -477,7 +477,11 @@ describe('configToJSONSchema', () => { name: 'blocksField', type: 'blocks', blocks: [ - { slug: 'blockA', fields: [{ name: 'title', type: 'text' }], interfaceName: 'Hero' }, + { + slug: 'blockA', + fields: [{ name: 'title', type: 'text' }], + interfaceName: 'Hero', + }, { slug: 'blockB', fields: [{ name: 'subtitle', type: 'number' }], @@ -487,6 +491,7 @@ describe('configToJSONSchema', () => { }, ], timestamps: false, + versions: false, }, ], } as unknown as Config @@ -523,6 +528,7 @@ describe('configToJSONSchema', () => { { name: 'b', type: 'blocks', blocks: [heroBlock] }, ], timestamps: false, + versions: false, }, ], } as unknown as Config @@ -647,11 +653,13 @@ describe('configToJSONSchema', () => { { name: 'when', type: 'date', timezone: true }, ], timestamps: false, + versions: false, }, { slug: 'other', fields: [{ name: 'title', type: 'text' }], timestamps: false, + versions: false, }, ], }