From b3308736c42c6b7082cdd98d2de73a916f3e4220 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 19 Dec 2024 20:22:43 -0700 Subject: [PATCH] feat: jsdocs for generated types, by using admin.description (#9917) This makes use of admin.description to generate JSDocs for field, collection and global generated types. ![image](https://github.com/user-attachments/assets/980d825f-49a2-426d-933a-2ff3d205ea24) ![image](https://github.com/user-attachments/assets/d0b1f288-1ea1-4d80-8c05-003d59a4e41a) For the future, we should add a dedicated property to override these JSDocs. You can view the effect of this PR on our test suite generated types here: https://github.com/payloadcms/payload/pull/9917/commits/05f552bbbc9f963f5b3145528eb089f05e7c86cb --- packages/payload/src/admin/RichText.ts | 9 +- packages/payload/src/bin/generateTypes.ts | 4 +- .../payload/src/collections/config/types.ts | 2 +- packages/payload/src/fields/config/types.ts | 4 + .../queues/config/generateJobsJSONSchemas.ts | 6 +- .../src/utilities/configToJSONSchema.ts | 122 +++++++++++++++--- .../src/features/blocks/server/index.ts | 9 +- .../src/features/typesServer.ts | 22 +--- packages/richtext-lexical/src/index.ts | 2 + test/admin/payload-types.ts | 39 ++++++ test/fields/payload-types.ts | 42 ++++++ test/joins/payload-types.ts | 6 + test/live-preview/payload-types.ts | 54 ++++++++ test/localization-rtl/payload-types.ts | 2 + test/plugin-form-builder/payload-types.ts | 12 ++ test/plugin-nested-docs/payload-types.ts | 6 + test/plugin-search/payload-types.ts | 2 + test/plugin-seo/payload-types.ts | 6 + test/plugin-stripe/payload-types.ts | 6 + test/queues/payload-types.ts | 12 ++ test/uploads/payload-types.ts | 3 + 21 files changed, 323 insertions(+), 47 deletions(-) diff --git a/packages/payload/src/admin/RichText.ts b/packages/payload/src/admin/RichText.ts index 2e76967bb..9bed6b872 100644 --- a/packages/payload/src/admin/RichText.ts +++ b/packages/payload/src/admin/RichText.ts @@ -215,16 +215,11 @@ type RichTextAdapterBase< }) => void hooks?: RichTextHooks i18n?: Partial - outputSchema?: ({ - collectionIDFieldTypes, - config, - field, - interfaceNameDefinitions, - isRequired, - }: { + outputSchema?: (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. */ diff --git a/packages/payload/src/bin/generateTypes.ts b/packages/payload/src/bin/generateTypes.ts index d2d56035b..7ff5a9d13 100644 --- a/packages/payload/src/bin/generateTypes.ts +++ b/packages/payload/src/bin/generateTypes.ts @@ -1,3 +1,4 @@ +import { initI18n } from '@payloadcms/translations' import fs from 'fs' import { compile } from 'json-schema-to-typescript' @@ -19,8 +20,9 @@ export async function generateTypes( if (shouldLog) { logger.info('Compiling TS types for Collections and Globals...') } + const i18n = await initI18n({ config: config.i18n, context: 'api', language: 'en' }) - const jsonSchema = configToJSONSchema(config, config.db.defaultIDType) + const jsonSchema = 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}` diff --git a/packages/payload/src/collections/config/types.ts b/packages/payload/src/collections/config/types.ts index bd8a45427..9d6640a8c 100644 --- a/packages/payload/src/collections/config/types.ts +++ b/packages/payload/src/collections/config/types.ts @@ -329,7 +329,7 @@ export type CollectionAdminOptions = { */ defaultColumns?: string[] /** - * Custom description for collection + * Custom description for collection. This will also be used as JSDoc for the generated types */ description?: EntityDescription enableRichTextLink?: boolean diff --git a/packages/payload/src/fields/config/types.ts b/packages/payload/src/fields/config/types.ts index 1f2e1b972..fb8341747 100644 --- a/packages/payload/src/fields/config/types.ts +++ b/packages/payload/src/fields/config/types.ts @@ -280,6 +280,10 @@ type Admin = { condition?: Condition /** Extension point to add your custom data. Available in server and client. */ custom?: Record + /** + * The field description will be displayed next to the field in the admin UI. Additionally, + * we use the field description to generate JSDoc comments for the generated TypeScript types. + */ description?: Description disableBulkEdit?: boolean disabled?: boolean diff --git a/packages/payload/src/queues/config/generateJobsJSONSchemas.ts b/packages/payload/src/queues/config/generateJobsJSONSchemas.ts index e04cc4bd8..8229f87f2 100644 --- a/packages/payload/src/queues/config/generateJobsJSONSchemas.ts +++ b/packages/payload/src/queues/config/generateJobsJSONSchemas.ts @@ -1,3 +1,4 @@ +import type { I18n } from '@payloadcms/translations' import type { JSONSchema4 } from 'json-schema' import type { SanitizedConfig } from '../../config/types.js' @@ -5,7 +6,6 @@ import type { JobsConfig } from './types/index.js' import { fieldsToJSONSchema } from '../../utilities/configToJSONSchema.js' import { flattenAllFields } from '../../utilities/flattenAllFields.js' - export function generateJobsJSONSchemas( config: SanitizedConfig, jobsConfig: JobsConfig, @@ -16,6 +16,7 @@ export function generateJobsJSONSchemas( * if they have custom ID fields. */ collectionIDFieldTypes: { [key: string]: 'number' | 'string' }, + i18n?: I18n, ): { definitions?: Map properties?: { tasks: JSONSchema4 } @@ -43,6 +44,7 @@ export function generateJobsJSONSchemas( flattenAllFields({ fields: task.inputSchema }), interfaceNameDefinitions, config, + i18n, ) const fullInputJsonSchema: JSONSchema4 = { @@ -61,6 +63,7 @@ export function generateJobsJSONSchemas( flattenAllFields({ fields: task.outputSchema }), interfaceNameDefinitions, config, + i18n, ) const fullOutputJsonSchema: JSONSchema4 = { @@ -127,6 +130,7 @@ export function generateJobsJSONSchemas( flattenAllFields({ fields: workflow.inputSchema }), interfaceNameDefinitions, config, + i18n, ) const fullInputJsonSchema: JSONSchema4 = { diff --git a/packages/payload/src/utilities/configToJSONSchema.ts b/packages/payload/src/utilities/configToJSONSchema.ts index ebd1cf869..fc2a9a2b4 100644 --- a/packages/payload/src/utilities/configToJSONSchema.ts +++ b/packages/payload/src/utilities/configToJSONSchema.ts @@ -3,6 +3,8 @@ import type { JSONSchema4, JSONSchema4TypeName } from 'json-schema' import pluralize from 'pluralize' const { singular } = pluralize +import type { I18n } from '@payloadcms/translations' + import type { Auth } from '../auth/types.js' import type { SanitizedCollectionConfig } from '../collections/config/types.js' import type { SanitizedConfig } from '../config/types.js' @@ -197,6 +199,32 @@ export function withNullableJSONSchemaType( return fieldTypes } +function entityOrFieldToJsDocs({ + config, + entity, + i18n, +}: { + config: SanitizedConfig + entity: FlattenedField | SanitizedCollectionConfig | SanitizedGlobalConfig + i18n?: I18n +}): string | undefined { + let description: string | undefined = undefined + if (entity?.admin?.description) { + if (typeof entity?.admin?.description === 'string') { + description = entity?.admin?.description + } else if (typeof entity?.admin?.description === 'object') { + const defaultLocale = config?.localization ? config?.localization?.defaultLocale : undefined + if (entity?.admin?.description?.en) { + description = entity?.admin?.description?.en + } else if (entity?.admin?.description?.[defaultLocale]) { + description = entity?.admin?.description?.[defaultLocale] + } + } else if (typeof entity?.admin?.description === 'function' && i18n) { + description = entity?.admin?.description(i18n) + } + } + return description +} export function fieldsToJSONSchema( /** * Used for relationship fields, to determine whether to use a string or number type for the ID. @@ -210,6 +238,7 @@ export function fieldsToJSONSchema( */ interfaceNameDefinitions: Map, config?: SanitizedConfig, + i18n?: I18n, ): { properties: { [k: string]: JSONSchema4 @@ -226,11 +255,18 @@ export function fieldsToJSONSchema( requiredFieldNames.add(field.name) } + const fieldDescription = entityOrFieldToJsDocs({ config, entity: field, i18n }) + const baseFieldSchema: JSONSchema4 = {} + if (fieldDescription) { + baseFieldSchema.description = fieldDescription + } + let fieldSchema: JSONSchema4 switch (field.type) { case 'array': { fieldSchema = { + ...baseFieldSchema, type: withNullableJSONSchemaType('array', isRequired), items: { type: 'object', @@ -240,6 +276,7 @@ export function fieldsToJSONSchema( field.flattenedFields, interfaceNameDefinitions, config, + i18n, ), }, } @@ -260,6 +297,7 @@ export function fieldsToJSONSchema( const hasBlocks = Boolean(field.blocks.length) fieldSchema = { + ...baseFieldSchema, type: withNullableJSONSchemaType('array', isRequired), items: hasBlocks ? { @@ -269,6 +307,7 @@ export function fieldsToJSONSchema( block.flattenedFields, interfaceNameDefinitions, config, + i18n, ) const blockSchema: JSONSchema4 = { @@ -299,20 +338,27 @@ export function fieldsToJSONSchema( break } case 'checkbox': { - fieldSchema = { type: withNullableJSONSchemaType('boolean', isRequired) } + fieldSchema = { + ...baseFieldSchema, + type: withNullableJSONSchemaType('boolean', isRequired), + } break } case 'code': case 'date': case 'email': case 'textarea': { - fieldSchema = { type: withNullableJSONSchemaType('string', isRequired) } + fieldSchema = { + ...baseFieldSchema, + type: withNullableJSONSchemaType('string', isRequired), + } break } case 'group': case 'tab': { fieldSchema = { + ...baseFieldSchema, type: 'object', additionalProperties: false, ...fieldsToJSONSchema( @@ -320,21 +366,21 @@ export function fieldsToJSONSchema( field.flattenedFields, interfaceNameDefinitions, config, + i18n, ), } if (field.interfaceName) { interfaceNameDefinitions.set(field.interfaceName, fieldSchema) - fieldSchema = { - $ref: `#/definitions/${field.interfaceName}`, - } + fieldSchema = { $ref: `#/definitions/${field.interfaceName}` } } break } case 'join': { fieldSchema = { + ...baseFieldSchema, type: withNullableJSONSchemaType('object', false), additionalProperties: false, properties: { @@ -359,6 +405,7 @@ export function fieldsToJSONSchema( case 'json': { fieldSchema = field.jsonSchema?.schema || { + ...baseFieldSchema, type: ['object', 'array', 'string', 'number', 'boolean', 'null'], } break @@ -367,17 +414,22 @@ export function fieldsToJSONSchema( case 'number': { if (field.hasMany === true) { fieldSchema = { + ...baseFieldSchema, type: withNullableJSONSchemaType('array', isRequired), items: { type: 'number' }, } } else { - fieldSchema = { type: withNullableJSONSchemaType('number', isRequired) } + fieldSchema = { + ...baseFieldSchema, + type: withNullableJSONSchemaType('number', isRequired), + } } break } case 'point': { fieldSchema = { + ...baseFieldSchema, type: withNullableJSONSchemaType('array', isRequired), items: [ { @@ -394,6 +446,7 @@ export function fieldsToJSONSchema( } case 'radio': { fieldSchema = { + ...baseFieldSchema, type: withNullableJSONSchemaType('string', isRequired), enum: buildOptionEnums(field.options), } @@ -406,6 +459,7 @@ export function fieldsToJSONSchema( if (Array.isArray(field.relationTo)) { if (field.hasMany) { fieldSchema = { + ...baseFieldSchema, type: withNullableJSONSchemaType('array', isRequired), items: { oneOf: field.relationTo.map((relation) => { @@ -434,6 +488,7 @@ export function fieldsToJSONSchema( } } else { fieldSchema = { + ...baseFieldSchema, oneOf: field.relationTo.map((relation) => { return { type: withNullableJSONSchemaType('object', isRequired), @@ -460,6 +515,7 @@ export function fieldsToJSONSchema( } } else if (field.hasMany) { fieldSchema = { + ...baseFieldSchema, type: withNullableJSONSchemaType('array', isRequired), items: { oneOf: [ @@ -474,6 +530,7 @@ export function fieldsToJSONSchema( } } else { fieldSchema = { + ...baseFieldSchema, oneOf: [ { type: withNullableJSONSchemaType( @@ -481,9 +538,7 @@ export function fieldsToJSONSchema( isRequired, ), }, - { - $ref: `#/definitions/${field.relationTo}`, - }, + { $ref: `#/definitions/${field.relationTo}` }, ], } } @@ -499,16 +554,21 @@ export function fieldsToJSONSchema( throw new Error('Attempted to access unsanitized rich text editor.') } if (field.editor.outputSchema) { - fieldSchema = field.editor.outputSchema({ - collectionIDFieldTypes, - config, - field, - interfaceNameDefinitions, - isRequired, - }) + fieldSchema = { + ...baseFieldSchema, + ...field.editor.outputSchema({ + collectionIDFieldTypes, + config, + field, + i18n, + interfaceNameDefinitions, + isRequired, + }), + } } else { // Maintain backwards compatibility with existing rich text editors fieldSchema = { + ...baseFieldSchema, type: withNullableJSONSchemaType('array', isRequired), items: { type: 'object', @@ -523,6 +583,7 @@ export function fieldsToJSONSchema( if (field.hasMany) { fieldSchema = { + ...baseFieldSchema, type: withNullableJSONSchemaType('array', isRequired), items: { type: 'string', @@ -533,6 +594,7 @@ export function fieldsToJSONSchema( } } else { fieldSchema = { + ...baseFieldSchema, type: withNullableJSONSchemaType('string', isRequired), } if (optionEnums?.length) { @@ -546,11 +608,15 @@ export function fieldsToJSONSchema( case 'text': if (field.hasMany === true) { fieldSchema = { + ...baseFieldSchema, type: withNullableJSONSchemaType('array', isRequired), items: { type: 'string' }, } } else { - fieldSchema = { type: withNullableJSONSchemaType('string', isRequired) } + fieldSchema = { + ...baseFieldSchema, + type: withNullableJSONSchemaType('string', isRequired), + } } break @@ -583,6 +649,7 @@ export function entityToJSONSchema( interfaceNameDefinitions: Map, defaultIDType: 'number' | 'text', collectionIDFieldTypes?: { [key: string]: 'number' | 'string' }, + i18n?: I18n, ): JSONSchema4 { if (!collectionIDFieldTypes) { collectionIDFieldTypes = getCollectionIDFieldTypes({ config, defaultIDType }) @@ -630,7 +697,7 @@ export function entityToJSONSchema( }) } - return { + const jsonSchema: JSONSchema4 = { type: 'object', additionalProperties: false, title, @@ -639,8 +706,17 @@ export function entityToJSONSchema( entity.flattenedFields, interfaceNameDefinitions, config, + i18n, ), } + + const entityDescription = entityOrFieldToJsDocs({ config, entity, i18n }) + + if (entityDescription) { + jsonSchema.description = entityDescription + } + + return jsonSchema } export function fieldsToSelectJSONSchema({ @@ -905,6 +981,7 @@ function generateAuthOperationSchemas(collections: SanitizedCollectionConfig[]): export function configToJSONSchema( config: SanitizedConfig, defaultIDType?: 'number' | 'text', + i18n?: I18n, ): JSONSchema4 { // 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() @@ -934,6 +1011,7 @@ export function configToJSONSchema( interfaceNameDefinitions, defaultIDType, collectionIDFieldTypes, + i18n, ) const select = fieldsToSelectJSONSchema({ fields: entity.flattenedFields, @@ -968,7 +1046,13 @@ export function configToJSONSchema( ) const jobsSchemas = config.jobs - ? generateJobsJSONSchemas(config, config.jobs, interfaceNameDefinitions, collectionIDFieldTypes) + ? generateJobsJSONSchemas( + config, + config.jobs, + interfaceNameDefinitions, + collectionIDFieldTypes, + i18n, + ) : {} let jsonSchema: JSONSchema4 = { diff --git a/packages/richtext-lexical/src/features/blocks/server/index.ts b/packages/richtext-lexical/src/features/blocks/server/index.ts index e8f98c0e9..efee6709a 100644 --- a/packages/richtext-lexical/src/features/blocks/server/index.ts +++ b/packages/richtext-lexical/src/features/blocks/server/index.ts @@ -50,6 +50,7 @@ export const BlocksFeature = createServerFeature { if (!props?.blocks?.length && !props?.inlineBlocks?.length) { @@ -82,7 +83,13 @@ export const BlocksFeature = createServerFeature = { // @ts-expect-error - TODO: fix this componentImports?: Config['admin']['importMap']['generators'][0] | PayloadComponent[] generatedTypes?: { - modifyOutputSchema: ({ - collectionIDFieldTypes, - config, - currentSchema, - field, - interfaceNameDefinitions, - isRequired, - }: { + modifyOutputSchema: (args: { collectionIDFieldTypes: { [key: string]: 'number' | 'string' } config?: SanitizedConfig /** @@ -313,6 +306,7 @@ export type ServerFeature = { */ currentSchema: JSONSchema4 field: RichTextField + i18n?: I18n /** * Allows you to define new top-level interfaces that can be re-used in the output schema. */ @@ -381,14 +375,7 @@ export type SanitizedServerFeatures = { enabledFeatures: string[] generatedTypes: { modifyOutputSchemas: Array< - ({ - collectionIDFieldTypes, - config, - currentSchema, - field, - interfaceNameDefinitions, - isRequired, - }: { + (args: { collectionIDFieldTypes: { [key: string]: 'number' | 'string' } config?: SanitizedConfig /** @@ -396,6 +383,7 @@ export type SanitizedServerFeatures = { */ currentSchema: JSONSchema4 field: RichTextField + i18n?: I18n /** * Allows you to define new top-level interfaces that can be re-used in the output schema. */ diff --git a/packages/richtext-lexical/src/index.ts b/packages/richtext-lexical/src/index.ts index 055dc6c97..0fd7e98f6 100644 --- a/packages/richtext-lexical/src/index.ts +++ b/packages/richtext-lexical/src/index.ts @@ -772,6 +772,7 @@ export function lexicalEditor(props?: LexicalEditorProps): LexicalRichTextAdapte collectionIDFieldTypes, config, field, + i18n, interfaceNameDefinitions, isRequired, }) => { @@ -838,6 +839,7 @@ export function lexicalEditor(props?: LexicalEditorProps): LexicalRichTextAdapte config, currentSchema: outputSchema, field, + i18n, interfaceNameDefinitions, isRequired, }) diff --git a/test/admin/payload-types.ts b/test/admin/payload-types.ts index cca8c384a..3168c7104 100644 --- a/test/admin/payload-types.ts +++ b/test/admin/payload-types.ts @@ -125,6 +125,8 @@ export interface Upload { focalY?: number | null; } /** + * This is a custom collection description. + * * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts". */ @@ -165,6 +167,9 @@ export interface Post { defaultValueField?: string | null; relationship?: (string | null) | Post; customCell?: string | null; + /** + * This is a very long description that takes many characters to complete and hopefully will wrap instead of push the sidebar open, lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, voluptatum voluptates. Quisquam, voluptatum voluptates. + */ sidebarField?: string | null; updatedAt: string; createdAt: string; @@ -246,7 +251,13 @@ export interface CustomField { id: string; customTextServerField?: string | null; customTextClientField?: string | null; + /** + * Static field description. + */ descriptionAsString?: string | null; + /** + * Function description + */ descriptionAsFunction?: string | null; descriptionAsComponent?: string | null; customSelectField?: string | null; @@ -328,6 +339,34 @@ export interface Geo { updatedAt: string; createdAt: string; } +/** + * Description + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "customIdTab". + */ +export interface CustomIdTab { + title?: string | null; + id: string; + description?: string | null; + number?: number | null; + updatedAt: string; + createdAt: string; +} +/** + * Description + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "customIdRow". + */ +export interface CustomIdRow { + title?: string | null; + id: string; + description?: string | null; + number?: number | null; + updatedAt: string; + createdAt: string; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "disable-duplicate". diff --git a/test/fields/payload-types.ts b/test/fields/payload-types.ts index 352cc72fc..02d905d57 100644 --- a/test/fields/payload-types.ts +++ b/test/fields/payload-types.ts @@ -310,6 +310,9 @@ export interface LexicalMigrateField { export interface LexicalLocalizedField { id: string; title: string; + /** + * Non-localized field with localized block subfields + */ lexicalBlocksSubLocalized?: { root: { type: string; @@ -325,6 +328,9 @@ export interface LexicalLocalizedField { }; [k: string]: unknown; } | null; + /** + * Localized field with localized block subfields + */ lexicalBlocksLocalized?: { root: { type: string; @@ -475,6 +481,9 @@ export interface ArrayField { id?: string | null; }[] | null; + /** + * Row labels rendered as react components. + */ rowLabelAsComponent?: | { title?: string | null; @@ -589,6 +598,9 @@ export interface BlockField { } )[] | null; + /** + * The purpose of this field is to test validateExistingBlockIsIdentical works with similar blocks with group fields + */ blocksWithSimilarGroup?: | ( | { @@ -777,9 +789,18 @@ export interface TextField { id: string; text: string; hiddenTextField?: string | null; + /** + * This field should be hidden + */ adminHiddenTextField?: string | null; + /** + * This field should be disabled + */ disabledTextField?: string | null; localizedText?: string | null; + /** + * en description + */ i18nText?: string | null; defaultString?: string | null; defaultEmptyString?: string | null; @@ -900,8 +921,14 @@ export interface ConditionalLogic { userConditional?: string | null; parentGroup?: { enableParentGroupFields?: boolean | null; + /** + * Ensures we can rely on nested fields within `data`. + */ siblingField?: string | null; }; + /** + * Ensures we can rely on nested fields within `siblingsData`. + */ reliesOnParentGroup?: string | null; groupSelection?: ('group1' | 'group2') | null; group1?: { @@ -981,6 +1008,9 @@ export interface EmailField { email: string; localizedEmail?: string | null; emailWithAutocomplete?: string | null; + /** + * en description + */ i18nEmail?: string | null; defaultEmail?: string | null; defaultEmptyString?: string | null; @@ -1010,6 +1040,9 @@ export interface RadioField { */ export interface GroupField { id: string; + /** + * This is a group. + */ group: { text: string; defaultParent?: string | null; @@ -1402,6 +1435,9 @@ export interface RichTextField { [k: string]: unknown; }; lexicalCustomFields_html?: string | null; + /** + * This rich text field uses the lexical editor. + */ lexical?: { root: { type: string; @@ -1417,6 +1453,9 @@ export interface RichTextField { }; [k: string]: unknown; } | 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; richText: { [k: string]: unknown; @@ -1505,6 +1544,9 @@ export interface TabsFields2 { */ export interface TabsField { id: string; + /** + * This should not collapse despite there being many tabs pushing the main fields open. + */ sidebarField?: string | null; array: { text: string; diff --git a/test/joins/payload-types.ts b/test/joins/payload-types.ts index ab340cf24..9cd322b5e 100644 --- a/test/joins/payload-types.ts +++ b/test/joins/payload-types.ts @@ -121,6 +121,9 @@ export interface UserAuthOperations { export interface Post { id: string; title?: string | null; + /** + * Hides posts for the `filtered` join field in categories + */ isFiltered?: boolean | null; restrictedField?: string | null; upload?: (string | null) | Upload; @@ -223,6 +226,9 @@ export interface Category { docs?: (string | Post)[] | null; hasNextPage?: boolean | null; } | null; + /** + * Static Description + */ hasManyPosts?: { docs?: (string | Post)[] | null; hasNextPage?: boolean | null; diff --git a/test/live-preview/payload-types.ts b/test/live-preview/payload-types.ts index 6a9157119..1792c3981 100644 --- a/test/live-preview/payload-types.ts +++ b/test/live-preview/payload-types.ts @@ -135,6 +135,9 @@ export interface Page { } | null); url?: string | null; label: string; + /** + * Choose how the link should be rendered. + */ appearance?: ('primary' | 'secondary') | null; }; id?: string | null; @@ -169,6 +172,9 @@ export interface Page { } | null); url?: string | null; label: string; + /** + * Choose how the link should be rendered. + */ appearance?: ('default' | 'primary' | 'secondary') | null; }; id?: string | null; @@ -202,12 +208,18 @@ export interface Page { 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; @@ -367,6 +379,9 @@ export interface Post { } | null); url?: string | null; label: string; + /** + * Choose how the link should be rendered. + */ appearance?: ('primary' | 'secondary') | null; }; id?: string | null; @@ -401,6 +416,9 @@ export interface Post { } | null); url?: string | null; label: string; + /** + * Choose how the link should be rendered. + */ appearance?: ('default' | 'primary' | 'secondary') | null; }; id?: string | null; @@ -434,12 +452,18 @@ export interface Post { 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; @@ -510,6 +534,9 @@ export interface Ssr { } | null); url?: string | null; label: string; + /** + * Choose how the link should be rendered. + */ appearance?: ('primary' | 'secondary') | null; }; id?: string | null; @@ -544,6 +571,9 @@ export interface Ssr { } | null); url?: string | null; label: string; + /** + * Choose how the link should be rendered. + */ appearance?: ('default' | 'primary' | 'secondary') | null; }; id?: string | null; @@ -577,12 +607,18 @@ export interface Ssr { 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; @@ -641,6 +677,9 @@ export interface SsrAutosave { } | null); url?: string | null; label: string; + /** + * Choose how the link should be rendered. + */ appearance?: ('primary' | 'secondary') | null; }; id?: string | null; @@ -675,6 +714,9 @@ export interface SsrAutosave { } | null); url?: string | null; label: string; + /** + * Choose how the link should be rendered. + */ appearance?: ('default' | 'primary' | 'secondary') | null; }; id?: string | null; @@ -708,12 +750,18 @@ export interface SsrAutosave { 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; @@ -1345,6 +1393,9 @@ export interface Header { } | null); url?: string | null; label: string; + /** + * Choose how the link should be rendered. + */ appearance?: ('default' | 'primary' | 'secondary') | null; }; id?: string | null; @@ -1375,6 +1426,9 @@ export interface Footer { } | null); url?: string | null; label: string; + /** + * Choose how the link should be rendered. + */ appearance?: ('default' | 'primary' | 'secondary') | null; }; id?: string | null; diff --git a/test/localization-rtl/payload-types.ts b/test/localization-rtl/payload-types.ts index 98349cef5..c2fe0c179 100644 --- a/test/localization-rtl/payload-types.ts +++ b/test/localization-rtl/payload-types.ts @@ -75,6 +75,8 @@ export interface User { password?: string | null; } /** + * Description + * * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts". */ diff --git a/test/plugin-form-builder/payload-types.ts b/test/plugin-form-builder/payload-types.ts index f7088c77c..61c0be6cc 100644 --- a/test/plugin-form-builder/payload-types.ts +++ b/test/plugin-form-builder/payload-types.ts @@ -216,6 +216,9 @@ export interface Form { )[] | null; submitButtonLabel?: string | null; + /** + * 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: { @@ -240,6 +243,9 @@ export interface Form { } | null; url?: string | null; }; + /** + * Send custom emails when the form submits. Use comma separated lists to send the same email to multiple recipients. To reference a value from this form, wrap that field's name with double curly brackets, i.e. {{firstName}}. You can use a wildcard {{*}} to output all data and {{*:table}} to format it as an HTML table in the email. + */ emails?: | { emailTo?: string | null; @@ -248,6 +254,9 @@ export interface Form { replyTo?: string | null; emailFrom?: string | null; subject: string; + /** + * Enter the message that should be sent in this email. + */ message?: { root: { type: string; @@ -304,6 +313,9 @@ export interface FormSubmission { payment?: { field?: string | null; status?: string | null; + /** + * Amount in cents + */ amount?: number | null; paymentProcessor?: string | null; creditCard?: { diff --git a/test/plugin-nested-docs/payload-types.ts b/test/plugin-nested-docs/payload-types.ts index 74c6bd319..4d59cf636 100644 --- a/test/plugin-nested-docs/payload-types.ts +++ b/test/plugin-nested-docs/payload-types.ts @@ -88,6 +88,9 @@ export interface Page { export interface Category { id: string; name: string; + /** + * custom + */ categorization?: | { doc?: (string | null) | Category; @@ -97,6 +100,9 @@ export interface Category { id?: string | null; }[] | null; + /** + * custom + */ owner?: (string | null) | Category; updatedAt: string; createdAt: string; diff --git a/test/plugin-search/payload-types.ts b/test/plugin-search/payload-types.ts index 0112c21f2..6510bdc88 100644 --- a/test/plugin-search/payload-types.ts +++ b/test/plugin-search/payload-types.ts @@ -126,6 +126,8 @@ export interface CustomIds2 { createdAt: string; } /** + * This is a collection of automatically created search results. These results are used by the global site search and will be updated automatically as documents in the CMS are created or updated. + * * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "search". */ diff --git a/test/plugin-seo/payload-types.ts b/test/plugin-seo/payload-types.ts index cf758c9b5..df0bcc8ff 100644 --- a/test/plugin-seo/payload-types.ts +++ b/test/plugin-seo/payload-types.ts @@ -90,6 +90,9 @@ export interface Page { meta: { title: string; description?: string | null; + /** + * Maximum upload file size: 12MB. Recommended file size for images is <500KB. + */ image?: (string | null) | Media; ogTitle?: string | null; }; @@ -146,6 +149,9 @@ export interface PagesWithImportedField { description?: string | null; }; innerMedia?: { + /** + * Maximum upload file size: 12MB. Recommended file size for images is <500KB. + */ image?: (string | null) | Media; }; }; diff --git a/test/plugin-stripe/payload-types.ts b/test/plugin-stripe/payload-types.ts index 731c62848..24dacbf07 100644 --- a/test/plugin-stripe/payload-types.ts +++ b/test/plugin-stripe/payload-types.ts @@ -107,6 +107,9 @@ export interface User { export interface Product { id: string; name?: string | null; + /** + * All pricing information is managed in Stripe and will be reflected here. + */ price?: { stripePriceID?: string | null; stripeJSON?: string | null; @@ -123,6 +126,9 @@ export interface Product { export interface Customer { id: string; name?: string | null; + /** + * All subscriptions are managed in Stripe and will be reflected here. Use the link in the sidebar to go directly to this customer in Stripe to begin managing their subscriptions. + */ subscriptions?: | { stripeSubscriptionID?: string | null; diff --git a/test/queues/payload-types.ts b/test/queues/payload-types.ts index 876de22b6..68d2d7a77 100644 --- a/test/queues/payload-types.ts +++ b/test/queues/payload-types.ts @@ -147,6 +147,9 @@ export interface User { */ export interface PayloadJob { id: string; + /** + * Input data provided to the job + */ input?: | { [k: string]: unknown; @@ -167,7 +170,13 @@ export interface PayloadJob { | null; completedAt?: string | null; totalTried?: number | null; + /** + * If hasError is true this job will not be retried + */ hasError?: boolean | null; + /** + * If hasError is true, this is the error that caused it + */ error?: | { [k: string]: unknown; @@ -177,6 +186,9 @@ export interface PayloadJob { | number | boolean | null; + /** + * Task execution log + */ log?: | { executedAt: string; diff --git a/test/uploads/payload-types.ts b/test/uploads/payload-types.ts index 9b2f20f04..7eabf40eb 100644 --- a/test/uploads/payload-types.ts +++ b/test/uploads/payload-types.ts @@ -340,6 +340,9 @@ export interface GifResize { */ export interface FilenameCompoundIndex { id: string; + /** + * Alt text to be used for compound index + */ alt?: string | null; updatedAt: string; createdAt: string;