@strapi/core 5.52.1 → 5.52.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Strapi.d.ts +1 -0
- package/dist/Strapi.d.ts.map +1 -1
- package/dist/Strapi.js +5 -1
- package/dist/Strapi.js.map +1 -1
- package/dist/Strapi.mjs +5 -1
- package/dist/Strapi.mjs.map +1 -1
- package/dist/core-api/routes/validation/common.d.ts +3 -3
- package/dist/core-api/routes/validation/common.js +3 -3
- package/dist/core-api/routes/validation/common.js.map +1 -1
- package/dist/core-api/routes/validation/common.mjs +3 -3
- package/dist/core-api/routes/validation/common.mjs.map +1 -1
- package/dist/core-api/routes/validation/content-type.d.ts +3 -3
- package/dist/core-api/routes/validation/content-type.d.ts.map +1 -1
- package/dist/core-api/routes/validation/content-type.js +1 -1
- package/dist/core-api/routes/validation/content-type.js.map +1 -1
- package/dist/core-api/routes/validation/content-type.mjs +1 -1
- package/dist/core-api/routes/validation/content-type.mjs.map +1 -1
- package/dist/core-api/routes/validation/schema-registry.d.ts +21 -0
- package/dist/core-api/routes/validation/schema-registry.d.ts.map +1 -0
- package/dist/core-api/routes/validation/schema-registry.js +99 -0
- package/dist/core-api/routes/validation/schema-registry.js.map +1 -0
- package/dist/core-api/routes/validation/schema-registry.mjs +77 -0
- package/dist/core-api/routes/validation/schema-registry.mjs.map +1 -0
- package/dist/core-api/routes/validation/utils.d.ts +6 -6
- package/dist/core-api/routes/validation/utils.d.ts.map +1 -1
- package/dist/core-api/routes/validation/utils.js +34 -34
- package/dist/core-api/routes/validation/utils.js.map +1 -1
- package/dist/core-api/routes/validation/utils.mjs +34 -34
- package/dist/core-api/routes/validation/utils.mjs.map +1 -1
- package/dist/loaders/plugins/get-enabled-plugins.d.ts.map +1 -1
- package/dist/loaders/plugins/get-enabled-plugins.js +2 -7
- package/dist/loaders/plugins/get-enabled-plugins.js.map +1 -1
- package/dist/loaders/plugins/get-enabled-plugins.mjs +2 -3
- package/dist/loaders/plugins/get-enabled-plugins.mjs.map +1 -1
- package/dist/loaders/plugins/get-user-plugins-config.d.ts +6 -1
- package/dist/loaders/plugins/get-user-plugins-config.d.ts.map +1 -1
- package/dist/loaders/plugins/get-user-plugins-config.js.map +1 -1
- package/dist/loaders/plugins/get-user-plugins-config.mjs.map +1 -1
- package/dist/migrations/database/5.0.0-discard-drafts.d.ts.map +1 -1
- package/dist/migrations/database/5.0.0-discard-drafts.js +4 -0
- package/dist/migrations/database/5.0.0-discard-drafts.js.map +1 -1
- package/dist/migrations/database/5.0.0-discard-drafts.mjs +4 -0
- package/dist/migrations/database/5.0.0-discard-drafts.mjs.map +1 -1
- package/dist/migrations/database/serialize-json-columns.d.ts +12 -0
- package/dist/migrations/database/serialize-json-columns.d.ts.map +1 -0
- package/dist/migrations/database/serialize-json-columns.js +35 -0
- package/dist/migrations/database/serialize-json-columns.js.map +1 -0
- package/dist/migrations/database/serialize-json-columns.mjs +33 -0
- package/dist/migrations/database/serialize-json-columns.mjs.map +1 -0
- package/dist/package.json.js +14 -14
- package/dist/package.json.mjs +14 -14
- package/dist/services/content-api/index.d.ts.map +1 -1
- package/dist/services/content-api/index.js +33 -41
- package/dist/services/content-api/index.js.map +1 -1
- package/dist/services/content-api/index.mjs +33 -38
- package/dist/services/content-api/index.mjs.map +1 -1
- package/dist/services/content-api/permissions/index.js +2 -2
- package/dist/services/content-api/permissions/index.js.map +1 -1
- package/dist/services/content-api/permissions/index.mjs +2 -2
- package/dist/services/content-api/permissions/index.mjs.map +1 -1
- package/dist/services/fs.js +1 -1
- package/dist/services/fs.js.map +1 -1
- package/dist/services/fs.mjs +1 -1
- package/dist/services/fs.mjs.map +1 -1
- package/dist/services/server/register-routes.js +7 -7
- package/dist/services/server/register-routes.js.map +1 -1
- package/dist/services/server/register-routes.mjs +7 -7
- package/dist/services/server/register-routes.mjs.map +1 -1
- package/dist/services/session-manager.d.ts.map +1 -1
- package/dist/services/session-manager.js +9 -9
- package/dist/services/session-manager.js.map +1 -1
- package/dist/services/session-manager.mjs +9 -9
- package/dist/services/session-manager.mjs.map +1 -1
- package/dist/utils/zod.d.ts +23 -0
- package/dist/utils/zod.d.ts.map +1 -0
- package/dist/utils/zod.js +46 -0
- package/dist/utils/zod.js.map +1 -0
- package/dist/utils/zod.mjs +43 -0
- package/dist/utils/zod.mjs.map +1 -0
- package/package.json +14 -14
|
@@ -90,15 +90,15 @@ export declare class CoreContentTypeRouteValidator extends AbstractCoreRouteVali
|
|
|
90
90
|
[x: string]: string;
|
|
91
91
|
}>>, z.ZodRecord<z.ZodEnum<{
|
|
92
92
|
[x: string]: string;
|
|
93
|
-
}
|
|
93
|
+
}> & z.core.$partial, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>, z.ZodArray<z.ZodRecord<z.ZodEnum<{
|
|
94
94
|
[x: string]: string;
|
|
95
|
-
}
|
|
95
|
+
}> & z.core.$partial, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>>]>;
|
|
96
96
|
/**
|
|
97
97
|
* Schema-aware filters validation that restricts to actual model fields
|
|
98
98
|
*/
|
|
99
99
|
protected get schemaAwareFilters(): z.ZodRecord<z.ZodEnum<{
|
|
100
100
|
[x: string]: string;
|
|
101
|
-
}
|
|
101
|
+
}> & z.core.$partial, z.ZodAny>;
|
|
102
102
|
get locale(): z.ZodString;
|
|
103
103
|
get status(): z.ZodEnum<{
|
|
104
104
|
draft: "draft";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-type.d.ts","sourceRoot":"","sources":["../../../../src/core-api/routes/validation/content-type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAU,GAAG,EAAE,MAAM,eAAe,CAAC;AAGjD,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAI5B,OAAO,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAC;AAEtD,mGAAmG;AACnG,MAAM,MAAM,UAAU,GAClB,QAAQ,GACR,UAAU,GACV,MAAM,GACN,QAAQ,GACR,mBAAmB,GACnB,qBAAqB,GACrB,QAAQ,GACR,YAAY,GACZ,SAAS,GACT,IAAI,CAAC;AAET;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,6BAA8B,SAAQ,0BAA0B,CAAC,GAAG,CAAC,WAAW,CAAC;IAC5F;;;;;;;;;;OAUG;IACH,IAAI,UAAU,cAEb;IAED;;;;;;;;;;;;OAYG;IACH,IAAI,QAAQ;;;sBAgBX;IAED;;;;;;;;;;OAUG;IACH,IAAI,SAAS;;;uBAEZ;IAED;;OAEG;IACH,SAAS,KAAK,sBAAsB;;SAMnC;IAED;;OAEG;IACH,SAAS,KAAK,wBAAwB;;;;UAiBrC;IAED;;OAEG;IACH,SAAS,KAAK,oBAAoB;;;;;;;;
|
|
1
|
+
{"version":3,"file":"content-type.d.ts","sourceRoot":"","sources":["../../../../src/core-api/routes/validation/content-type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAU,GAAG,EAAE,MAAM,eAAe,CAAC;AAGjD,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAI5B,OAAO,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAC;AAEtD,mGAAmG;AACnG,MAAM,MAAM,UAAU,GAClB,QAAQ,GACR,UAAU,GACV,MAAM,GACN,QAAQ,GACR,mBAAmB,GACnB,qBAAqB,GACrB,QAAQ,GACR,YAAY,GACZ,SAAS,GACT,IAAI,CAAC;AAET;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,6BAA8B,SAAQ,0BAA0B,CAAC,GAAG,CAAC,WAAW,CAAC;IAC5F;;;;;;;;;;OAUG;IACH,IAAI,UAAU,cAEb;IAED;;;;;;;;;;;;OAYG;IACH,IAAI,QAAQ;;;sBAgBX;IAED;;;;;;;;;;OAUG;IACH,IAAI,SAAS;;;uBAEZ;IAED;;OAEG;IACH,SAAS,KAAK,sBAAsB;;SAMnC;IAED;;OAEG;IACH,SAAS,KAAK,wBAAwB;;;;UAiBrC;IAED;;OAEG;IACH,SAAS,KAAK,oBAAoB;;;;;;;;sGAYjC;IAED;;OAEG;IACH,SAAS,KAAK,kBAAkB;;oCAI/B;IAED,IAAI,MAAM,gBAET;IAED,IAAI,MAAM;;;OAIT;IAED,IAAI,iBAAiB;;;;;;;;;OAepB;IAED,mGAAmG;IACnG,IAAI,mBAAmB;;;SAMtB;IAED,IAAI,IAAI,mCAYP;IAED,IAAI,KAAK,gBAER;IAED,IAAI,IAAI;;sBAEP;IAED,IAAI,WAAW;;sBAEd;IAED;;;;;;;;;;;OAWG;IACH,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;CAmBzE"}
|
|
@@ -136,7 +136,7 @@ var z__namespace = /*#__PURE__*/_interopNamespace(z);
|
|
|
136
136
|
/**
|
|
137
137
|
* Schema-aware filters validation that restricts to actual model fields
|
|
138
138
|
*/ get schemaAwareFilters() {
|
|
139
|
-
return z__namespace.
|
|
139
|
+
return z__namespace.partialRecord(this.scalarFieldsEnum, z__namespace.any()).describe('Filters to apply to the query');
|
|
140
140
|
}
|
|
141
141
|
get locale() {
|
|
142
142
|
return z__namespace.string().describe('Select a locale');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-type.js","sources":["../../../../src/core-api/routes/validation/content-type.ts"],"sourcesContent":["import type { Schema, UID } from '@strapi/types';\n\nimport { contentTypes } from '@strapi/utils';\nimport * as z from 'zod/v4';\n\n// eslint-disable-next-line import/no-cycle\nimport { createAttributesInputSchema, createAttributesSchema } from './mappers';\nimport { AbstractCoreRouteValidator } from './common';\n\n/** REST query param names. `hasPublishedVersion` is deprecated in favor of `publicationFilter`. */\nexport type QueryParam =\n | 'fields'\n | 'populate'\n | 'sort'\n | 'status'\n | 'publicationFilter'\n | 'hasPublishedVersion'\n | 'locale'\n | 'pagination'\n | 'filters'\n | '_q';\n\n/**\n * A validator for core content-type routes.\n *\n * Provides validation schemas and utilities for handling content-type-specific route validation.\n * Extends the base AbstractRouteValidator with schema-aware validation for Strapi content types.\n *\n * @example\n * ```ts\n * const strapi = // ... strapi instance\n * const uid = 'api::article.article'\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n *\n * // Get validation schema for document\n * const documentSchema = validator.document;\n *\n * // Validate query parameters with schema awareness\n * const querySchema = validator.queryParams(['fields', 'populate', 'sort']);\n * ```\n */\nexport class CoreContentTypeRouteValidator extends AbstractCoreRouteValidator<UID.ContentType> {\n /**\n * Generates a validation schema for document IDs\n *\n * @returns A schema that validates UUIDs\n *\n * @example\n * ```ts\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n * const idSchema = validator.documentID;\n * ```\n */\n get documentID() {\n return z.uuid().describe('The document ID, represented by a UUID');\n }\n\n /**\n * Generates a comprehensive validation schema for a single document.\n *\n * Combines scalar fields and populatable fields into a single schema.\n *\n * @returns A schema for validating complete documents\n *\n * @example\n * ```ts\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n * const docSchema = validator.document;\n * ```\n */\n get document() {\n const entries = Object.entries({ ...this._scalarFields, ...this._populatableFields });\n\n const sanitizedAttributes = entries\n // Remove passwords from the attribute list\n .filter(([, attribute]) => !['password'].includes(attribute.type));\n\n // Merge all attributes into a single schema\n const attributesSchema = createAttributesSchema(this._strapi, sanitizedAttributes);\n\n return z\n .object({\n documentId: this.documentID,\n id: z.union([z.string(), z.number()]),\n })\n .extend(attributesSchema.shape);\n }\n\n /**\n * Generates a validation schema for an array of documents\n *\n * @returns A schema for validating arrays of documents\n *\n * @example\n * ```ts\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n * const docsSchema = validator.documents;\n * ```\n */\n get documents() {\n return z.array(this.document);\n }\n\n /**\n * Schema-aware fields validation that restricts to actual model fields\n */\n protected get schemaAwareQueryFields() {\n return this.scalarFieldsArray\n .readonly()\n .describe(\n `The fields to return, this doesn't include populatable fields like relations, components, files, or dynamic zones`\n );\n }\n\n /**\n * Schema-aware populate validation that restricts to actual populatable fields\n */\n protected get schemaAwareQueryPopulate() {\n const wildcardPopulate = z\n .literal('*')\n .readonly()\n .describe(\n 'Populate all the first level relations, components, files, and dynamic zones for the entry'\n );\n\n const singleFieldPopulate = this.populatableFieldsEnum\n .readonly()\n .describe('Populate a single relation, component, file, or dynamic zone');\n\n const multiPopulate = this.populatableFieldsArray.describe(\n 'Populate a selection of multiple relations, components, files, or dynamic zones'\n );\n\n return z.union([wildcardPopulate, singleFieldPopulate, multiPopulate]);\n }\n\n /**\n * Schema-aware sort validation that restricts to actual model fields\n */\n protected get schemaAwareQuerySort() {\n const orderDirection = z.enum(['asc', 'desc']);\n\n // TODO: Handle nested sorts but very low priority, very little usage\n return z\n .union([\n this.scalarFieldsEnum, // 'name' | 'title'\n this.scalarFieldsArray, // ['name', 'title']\n this.fieldRecord(orderDirection), // { name: 'desc' } | { title: 'asc' }\n z.array(this.fieldRecord(orderDirection)), // [{ name: 'desc'}, { title: 'asc' }]\n ])\n .describe('Sort the result');\n }\n\n /**\n * Schema-aware filters validation that restricts to actual model fields\n */\n protected get schemaAwareFilters() {\n return z.record(this.scalarFieldsEnum, z.any()).describe('Filters to apply to the query');\n }\n\n get locale() {\n return z.string().describe('Select a locale');\n }\n\n get status() {\n return z\n .enum(['draft', 'published'])\n .describe('Fetch documents based on their status. Default to \"published\" if not specified.');\n }\n\n get publicationFilter() {\n return z\n .enum([\n 'never-published',\n 'has-published-version',\n 'modified',\n 'unmodified',\n 'never-published-document',\n 'has-published-version-document',\n 'published-without-draft',\n 'published-with-draft',\n ])\n .describe(\n 'Derived publication cohort: pair-scoped (per documentId+locale), document-scoped variants (-document), or published-slice diagnostics (published-without-draft / published-with-draft)'\n );\n }\n\n /** @deprecated Use `publicationFilter` instead (`never-published`, `has-published-version`, …). */\n get hasPublishedVersion() {\n return z\n .union([z.boolean(), z.enum(['true', 'false'])])\n .describe(\n '[Deprecated: prefer publicationFilter] Filter documents by whether they have a published version. Use with status=draft to find documents that have never been published'\n );\n }\n\n get data() {\n const isWritableAttribute = ([attributeName]: [string, Schema.Attribute.AnyAttribute]) => {\n return contentTypes.isWritableAttribute(this._schema, attributeName);\n };\n\n const entries = Object.entries({ ...this._scalarFields, ...this._populatableFields });\n\n const sanitizedAttributes = entries\n // Remove non-writable attributes\n .filter(isWritableAttribute);\n\n return createAttributesInputSchema(this._strapi, sanitizedAttributes);\n }\n\n get query() {\n return z.string();\n }\n\n get body() {\n return z.object({ data: this.data });\n }\n\n get partialBody() {\n return z.object({ data: this.data.partial() });\n }\n\n /**\n * Creates validation schemas for query parameters\n *\n * @param params - Array of query parameters to validate ('fields', 'populate', 'sort', ...)\n * @returns Object containing validation schemas for requested parameters\n *\n * @example\n * ```ts\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n * const querySchemas = validator.queryParams(['fields', 'populate']);\n * ```\n */\n queryParams(params: QueryParam[]): Partial<Record<QueryParam, z.Schema>> {\n const map: Record<QueryParam, () => z.Schema> = {\n fields: () => this.schemaAwareQueryFields.optional(),\n populate: () => this.schemaAwareQueryPopulate.optional(),\n sort: () => this.schemaAwareQuerySort.optional(),\n filters: () => this.schemaAwareFilters.optional(),\n locale: () => this.locale.optional(),\n pagination: () => this.pagination.optional(),\n status: () => this.status.optional(),\n publicationFilter: () => this.publicationFilter.optional(),\n hasPublishedVersion: () => this.hasPublishedVersion.optional(),\n _q: () => this.query.optional(),\n } as const;\n\n return params.reduce(\n (acc, param) => ({ ...acc, [param]: map[param]() }),\n {} as Partial<Record<QueryParam, z.Schema>>\n );\n }\n}\n"],"names":["CoreContentTypeRouteValidator","AbstractCoreRouteValidator","documentID","z","uuid","describe","document","entries","Object","_scalarFields","_populatableFields","sanitizedAttributes","filter","attribute","includes","type","attributesSchema","createAttributesSchema","_strapi","object","documentId","id","union","string","number","extend","shape","documents","array","schemaAwareQueryFields","scalarFieldsArray","readonly","schemaAwareQueryPopulate","wildcardPopulate","literal","singleFieldPopulate","populatableFieldsEnum","multiPopulate","populatableFieldsArray","schemaAwareQuerySort","orderDirection","enum","scalarFieldsEnum","fieldRecord","schemaAwareFilters","record","any","locale","status","publicationFilter","hasPublishedVersion","boolean","data","isWritableAttribute","attributeName","contentTypes","_schema","createAttributesInputSchema","query","body","partialBody","partial","queryParams","params","map","fields","optional","populate","sort","filters","pagination","_q","reduce","acc","param"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"content-type.js","sources":["../../../../src/core-api/routes/validation/content-type.ts"],"sourcesContent":["import type { Schema, UID } from '@strapi/types';\n\nimport { contentTypes } from '@strapi/utils';\nimport * as z from 'zod/v4';\n\n// eslint-disable-next-line import/no-cycle\nimport { createAttributesInputSchema, createAttributesSchema } from './mappers';\nimport { AbstractCoreRouteValidator } from './common';\n\n/** REST query param names. `hasPublishedVersion` is deprecated in favor of `publicationFilter`. */\nexport type QueryParam =\n | 'fields'\n | 'populate'\n | 'sort'\n | 'status'\n | 'publicationFilter'\n | 'hasPublishedVersion'\n | 'locale'\n | 'pagination'\n | 'filters'\n | '_q';\n\n/**\n * A validator for core content-type routes.\n *\n * Provides validation schemas and utilities for handling content-type-specific route validation.\n * Extends the base AbstractRouteValidator with schema-aware validation for Strapi content types.\n *\n * @example\n * ```ts\n * const strapi = // ... strapi instance\n * const uid = 'api::article.article'\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n *\n * // Get validation schema for document\n * const documentSchema = validator.document;\n *\n * // Validate query parameters with schema awareness\n * const querySchema = validator.queryParams(['fields', 'populate', 'sort']);\n * ```\n */\nexport class CoreContentTypeRouteValidator extends AbstractCoreRouteValidator<UID.ContentType> {\n /**\n * Generates a validation schema for document IDs\n *\n * @returns A schema that validates UUIDs\n *\n * @example\n * ```ts\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n * const idSchema = validator.documentID;\n * ```\n */\n get documentID() {\n return z.uuid().describe('The document ID, represented by a UUID');\n }\n\n /**\n * Generates a comprehensive validation schema for a single document.\n *\n * Combines scalar fields and populatable fields into a single schema.\n *\n * @returns A schema for validating complete documents\n *\n * @example\n * ```ts\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n * const docSchema = validator.document;\n * ```\n */\n get document() {\n const entries = Object.entries({ ...this._scalarFields, ...this._populatableFields });\n\n const sanitizedAttributes = entries\n // Remove passwords from the attribute list\n .filter(([, attribute]) => !['password'].includes(attribute.type));\n\n // Merge all attributes into a single schema\n const attributesSchema = createAttributesSchema(this._strapi, sanitizedAttributes);\n\n return z\n .object({\n documentId: this.documentID,\n id: z.union([z.string(), z.number()]),\n })\n .extend(attributesSchema.shape);\n }\n\n /**\n * Generates a validation schema for an array of documents\n *\n * @returns A schema for validating arrays of documents\n *\n * @example\n * ```ts\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n * const docsSchema = validator.documents;\n * ```\n */\n get documents() {\n return z.array(this.document);\n }\n\n /**\n * Schema-aware fields validation that restricts to actual model fields\n */\n protected get schemaAwareQueryFields() {\n return this.scalarFieldsArray\n .readonly()\n .describe(\n `The fields to return, this doesn't include populatable fields like relations, components, files, or dynamic zones`\n );\n }\n\n /**\n * Schema-aware populate validation that restricts to actual populatable fields\n */\n protected get schemaAwareQueryPopulate() {\n const wildcardPopulate = z\n .literal('*')\n .readonly()\n .describe(\n 'Populate all the first level relations, components, files, and dynamic zones for the entry'\n );\n\n const singleFieldPopulate = this.populatableFieldsEnum\n .readonly()\n .describe('Populate a single relation, component, file, or dynamic zone');\n\n const multiPopulate = this.populatableFieldsArray.describe(\n 'Populate a selection of multiple relations, components, files, or dynamic zones'\n );\n\n return z.union([wildcardPopulate, singleFieldPopulate, multiPopulate]);\n }\n\n /**\n * Schema-aware sort validation that restricts to actual model fields\n */\n protected get schemaAwareQuerySort() {\n const orderDirection = z.enum(['asc', 'desc']);\n\n // TODO: Handle nested sorts but very low priority, very little usage\n return z\n .union([\n this.scalarFieldsEnum, // 'name' | 'title'\n this.scalarFieldsArray, // ['name', 'title']\n this.fieldRecord(orderDirection), // { name: 'desc' } | { title: 'asc' }\n z.array(this.fieldRecord(orderDirection)), // [{ name: 'desc'}, { title: 'asc' }]\n ])\n .describe('Sort the result');\n }\n\n /**\n * Schema-aware filters validation that restricts to actual model fields\n */\n protected get schemaAwareFilters() {\n return z\n .partialRecord(this.scalarFieldsEnum, z.any())\n .describe('Filters to apply to the query');\n }\n\n get locale() {\n return z.string().describe('Select a locale');\n }\n\n get status() {\n return z\n .enum(['draft', 'published'])\n .describe('Fetch documents based on their status. Default to \"published\" if not specified.');\n }\n\n get publicationFilter() {\n return z\n .enum([\n 'never-published',\n 'has-published-version',\n 'modified',\n 'unmodified',\n 'never-published-document',\n 'has-published-version-document',\n 'published-without-draft',\n 'published-with-draft',\n ])\n .describe(\n 'Derived publication cohort: pair-scoped (per documentId+locale), document-scoped variants (-document), or published-slice diagnostics (published-without-draft / published-with-draft)'\n );\n }\n\n /** @deprecated Use `publicationFilter` instead (`never-published`, `has-published-version`, …). */\n get hasPublishedVersion() {\n return z\n .union([z.boolean(), z.enum(['true', 'false'])])\n .describe(\n '[Deprecated: prefer publicationFilter] Filter documents by whether they have a published version. Use with status=draft to find documents that have never been published'\n );\n }\n\n get data() {\n const isWritableAttribute = ([attributeName]: [string, Schema.Attribute.AnyAttribute]) => {\n return contentTypes.isWritableAttribute(this._schema, attributeName);\n };\n\n const entries = Object.entries({ ...this._scalarFields, ...this._populatableFields });\n\n const sanitizedAttributes = entries\n // Remove non-writable attributes\n .filter(isWritableAttribute);\n\n return createAttributesInputSchema(this._strapi, sanitizedAttributes);\n }\n\n get query() {\n return z.string();\n }\n\n get body() {\n return z.object({ data: this.data });\n }\n\n get partialBody() {\n return z.object({ data: this.data.partial() });\n }\n\n /**\n * Creates validation schemas for query parameters\n *\n * @param params - Array of query parameters to validate ('fields', 'populate', 'sort', ...)\n * @returns Object containing validation schemas for requested parameters\n *\n * @example\n * ```ts\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n * const querySchemas = validator.queryParams(['fields', 'populate']);\n * ```\n */\n queryParams(params: QueryParam[]): Partial<Record<QueryParam, z.Schema>> {\n const map: Record<QueryParam, () => z.Schema> = {\n fields: () => this.schemaAwareQueryFields.optional(),\n populate: () => this.schemaAwareQueryPopulate.optional(),\n sort: () => this.schemaAwareQuerySort.optional(),\n filters: () => this.schemaAwareFilters.optional(),\n locale: () => this.locale.optional(),\n pagination: () => this.pagination.optional(),\n status: () => this.status.optional(),\n publicationFilter: () => this.publicationFilter.optional(),\n hasPublishedVersion: () => this.hasPublishedVersion.optional(),\n _q: () => this.query.optional(),\n } as const;\n\n return params.reduce(\n (acc, param) => ({ ...acc, [param]: map[param]() }),\n {} as Partial<Record<QueryParam, z.Schema>>\n );\n }\n}\n"],"names":["CoreContentTypeRouteValidator","AbstractCoreRouteValidator","documentID","z","uuid","describe","document","entries","Object","_scalarFields","_populatableFields","sanitizedAttributes","filter","attribute","includes","type","attributesSchema","createAttributesSchema","_strapi","object","documentId","id","union","string","number","extend","shape","documents","array","schemaAwareQueryFields","scalarFieldsArray","readonly","schemaAwareQueryPopulate","wildcardPopulate","literal","singleFieldPopulate","populatableFieldsEnum","multiPopulate","populatableFieldsArray","schemaAwareQuerySort","orderDirection","enum","scalarFieldsEnum","fieldRecord","schemaAwareFilters","partialRecord","any","locale","status","publicationFilter","hasPublishedVersion","boolean","data","isWritableAttribute","attributeName","contentTypes","_schema","createAttributesInputSchema","query","body","partialBody","partial","queryParams","params","map","fields","optional","populate","sort","filters","pagination","_q","reduce","acc","param"],"mappings":"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"}
|
|
@@ -114,7 +114,7 @@ import { AbstractCoreRouteValidator } from './common.mjs';
|
|
|
114
114
|
/**
|
|
115
115
|
* Schema-aware filters validation that restricts to actual model fields
|
|
116
116
|
*/ get schemaAwareFilters() {
|
|
117
|
-
return z.
|
|
117
|
+
return z.partialRecord(this.scalarFieldsEnum, z.any()).describe('Filters to apply to the query');
|
|
118
118
|
}
|
|
119
119
|
get locale() {
|
|
120
120
|
return z.string().describe('Select a locale');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-type.mjs","sources":["../../../../src/core-api/routes/validation/content-type.ts"],"sourcesContent":["import type { Schema, UID } from '@strapi/types';\n\nimport { contentTypes } from '@strapi/utils';\nimport * as z from 'zod/v4';\n\n// eslint-disable-next-line import/no-cycle\nimport { createAttributesInputSchema, createAttributesSchema } from './mappers';\nimport { AbstractCoreRouteValidator } from './common';\n\n/** REST query param names. `hasPublishedVersion` is deprecated in favor of `publicationFilter`. */\nexport type QueryParam =\n | 'fields'\n | 'populate'\n | 'sort'\n | 'status'\n | 'publicationFilter'\n | 'hasPublishedVersion'\n | 'locale'\n | 'pagination'\n | 'filters'\n | '_q';\n\n/**\n * A validator for core content-type routes.\n *\n * Provides validation schemas and utilities for handling content-type-specific route validation.\n * Extends the base AbstractRouteValidator with schema-aware validation for Strapi content types.\n *\n * @example\n * ```ts\n * const strapi = // ... strapi instance\n * const uid = 'api::article.article'\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n *\n * // Get validation schema for document\n * const documentSchema = validator.document;\n *\n * // Validate query parameters with schema awareness\n * const querySchema = validator.queryParams(['fields', 'populate', 'sort']);\n * ```\n */\nexport class CoreContentTypeRouteValidator extends AbstractCoreRouteValidator<UID.ContentType> {\n /**\n * Generates a validation schema for document IDs\n *\n * @returns A schema that validates UUIDs\n *\n * @example\n * ```ts\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n * const idSchema = validator.documentID;\n * ```\n */\n get documentID() {\n return z.uuid().describe('The document ID, represented by a UUID');\n }\n\n /**\n * Generates a comprehensive validation schema for a single document.\n *\n * Combines scalar fields and populatable fields into a single schema.\n *\n * @returns A schema for validating complete documents\n *\n * @example\n * ```ts\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n * const docSchema = validator.document;\n * ```\n */\n get document() {\n const entries = Object.entries({ ...this._scalarFields, ...this._populatableFields });\n\n const sanitizedAttributes = entries\n // Remove passwords from the attribute list\n .filter(([, attribute]) => !['password'].includes(attribute.type));\n\n // Merge all attributes into a single schema\n const attributesSchema = createAttributesSchema(this._strapi, sanitizedAttributes);\n\n return z\n .object({\n documentId: this.documentID,\n id: z.union([z.string(), z.number()]),\n })\n .extend(attributesSchema.shape);\n }\n\n /**\n * Generates a validation schema for an array of documents\n *\n * @returns A schema for validating arrays of documents\n *\n * @example\n * ```ts\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n * const docsSchema = validator.documents;\n * ```\n */\n get documents() {\n return z.array(this.document);\n }\n\n /**\n * Schema-aware fields validation that restricts to actual model fields\n */\n protected get schemaAwareQueryFields() {\n return this.scalarFieldsArray\n .readonly()\n .describe(\n `The fields to return, this doesn't include populatable fields like relations, components, files, or dynamic zones`\n );\n }\n\n /**\n * Schema-aware populate validation that restricts to actual populatable fields\n */\n protected get schemaAwareQueryPopulate() {\n const wildcardPopulate = z\n .literal('*')\n .readonly()\n .describe(\n 'Populate all the first level relations, components, files, and dynamic zones for the entry'\n );\n\n const singleFieldPopulate = this.populatableFieldsEnum\n .readonly()\n .describe('Populate a single relation, component, file, or dynamic zone');\n\n const multiPopulate = this.populatableFieldsArray.describe(\n 'Populate a selection of multiple relations, components, files, or dynamic zones'\n );\n\n return z.union([wildcardPopulate, singleFieldPopulate, multiPopulate]);\n }\n\n /**\n * Schema-aware sort validation that restricts to actual model fields\n */\n protected get schemaAwareQuerySort() {\n const orderDirection = z.enum(['asc', 'desc']);\n\n // TODO: Handle nested sorts but very low priority, very little usage\n return z\n .union([\n this.scalarFieldsEnum, // 'name' | 'title'\n this.scalarFieldsArray, // ['name', 'title']\n this.fieldRecord(orderDirection), // { name: 'desc' } | { title: 'asc' }\n z.array(this.fieldRecord(orderDirection)), // [{ name: 'desc'}, { title: 'asc' }]\n ])\n .describe('Sort the result');\n }\n\n /**\n * Schema-aware filters validation that restricts to actual model fields\n */\n protected get schemaAwareFilters() {\n return z.record(this.scalarFieldsEnum, z.any()).describe('Filters to apply to the query');\n }\n\n get locale() {\n return z.string().describe('Select a locale');\n }\n\n get status() {\n return z\n .enum(['draft', 'published'])\n .describe('Fetch documents based on their status. Default to \"published\" if not specified.');\n }\n\n get publicationFilter() {\n return z\n .enum([\n 'never-published',\n 'has-published-version',\n 'modified',\n 'unmodified',\n 'never-published-document',\n 'has-published-version-document',\n 'published-without-draft',\n 'published-with-draft',\n ])\n .describe(\n 'Derived publication cohort: pair-scoped (per documentId+locale), document-scoped variants (-document), or published-slice diagnostics (published-without-draft / published-with-draft)'\n );\n }\n\n /** @deprecated Use `publicationFilter` instead (`never-published`, `has-published-version`, …). */\n get hasPublishedVersion() {\n return z\n .union([z.boolean(), z.enum(['true', 'false'])])\n .describe(\n '[Deprecated: prefer publicationFilter] Filter documents by whether they have a published version. Use with status=draft to find documents that have never been published'\n );\n }\n\n get data() {\n const isWritableAttribute = ([attributeName]: [string, Schema.Attribute.AnyAttribute]) => {\n return contentTypes.isWritableAttribute(this._schema, attributeName);\n };\n\n const entries = Object.entries({ ...this._scalarFields, ...this._populatableFields });\n\n const sanitizedAttributes = entries\n // Remove non-writable attributes\n .filter(isWritableAttribute);\n\n return createAttributesInputSchema(this._strapi, sanitizedAttributes);\n }\n\n get query() {\n return z.string();\n }\n\n get body() {\n return z.object({ data: this.data });\n }\n\n get partialBody() {\n return z.object({ data: this.data.partial() });\n }\n\n /**\n * Creates validation schemas for query parameters\n *\n * @param params - Array of query parameters to validate ('fields', 'populate', 'sort', ...)\n * @returns Object containing validation schemas for requested parameters\n *\n * @example\n * ```ts\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n * const querySchemas = validator.queryParams(['fields', 'populate']);\n * ```\n */\n queryParams(params: QueryParam[]): Partial<Record<QueryParam, z.Schema>> {\n const map: Record<QueryParam, () => z.Schema> = {\n fields: () => this.schemaAwareQueryFields.optional(),\n populate: () => this.schemaAwareQueryPopulate.optional(),\n sort: () => this.schemaAwareQuerySort.optional(),\n filters: () => this.schemaAwareFilters.optional(),\n locale: () => this.locale.optional(),\n pagination: () => this.pagination.optional(),\n status: () => this.status.optional(),\n publicationFilter: () => this.publicationFilter.optional(),\n hasPublishedVersion: () => this.hasPublishedVersion.optional(),\n _q: () => this.query.optional(),\n } as const;\n\n return params.reduce(\n (acc, param) => ({ ...acc, [param]: map[param]() }),\n {} as Partial<Record<QueryParam, z.Schema>>\n );\n }\n}\n"],"names":["CoreContentTypeRouteValidator","AbstractCoreRouteValidator","documentID","z","uuid","describe","document","entries","Object","_scalarFields","_populatableFields","sanitizedAttributes","filter","attribute","includes","type","attributesSchema","createAttributesSchema","_strapi","object","documentId","id","union","string","number","extend","shape","documents","array","schemaAwareQueryFields","scalarFieldsArray","readonly","schemaAwareQueryPopulate","wildcardPopulate","literal","singleFieldPopulate","populatableFieldsEnum","multiPopulate","populatableFieldsArray","schemaAwareQuerySort","orderDirection","enum","scalarFieldsEnum","fieldRecord","schemaAwareFilters","record","any","locale","status","publicationFilter","hasPublishedVersion","boolean","data","isWritableAttribute","attributeName","contentTypes","_schema","createAttributesInputSchema","query","body","partialBody","partial","queryParams","params","map","fields","optional","populate","sort","filters","pagination","_q","reduce","acc","param"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"content-type.mjs","sources":["../../../../src/core-api/routes/validation/content-type.ts"],"sourcesContent":["import type { Schema, UID } from '@strapi/types';\n\nimport { contentTypes } from '@strapi/utils';\nimport * as z from 'zod/v4';\n\n// eslint-disable-next-line import/no-cycle\nimport { createAttributesInputSchema, createAttributesSchema } from './mappers';\nimport { AbstractCoreRouteValidator } from './common';\n\n/** REST query param names. `hasPublishedVersion` is deprecated in favor of `publicationFilter`. */\nexport type QueryParam =\n | 'fields'\n | 'populate'\n | 'sort'\n | 'status'\n | 'publicationFilter'\n | 'hasPublishedVersion'\n | 'locale'\n | 'pagination'\n | 'filters'\n | '_q';\n\n/**\n * A validator for core content-type routes.\n *\n * Provides validation schemas and utilities for handling content-type-specific route validation.\n * Extends the base AbstractRouteValidator with schema-aware validation for Strapi content types.\n *\n * @example\n * ```ts\n * const strapi = // ... strapi instance\n * const uid = 'api::article.article'\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n *\n * // Get validation schema for document\n * const documentSchema = validator.document;\n *\n * // Validate query parameters with schema awareness\n * const querySchema = validator.queryParams(['fields', 'populate', 'sort']);\n * ```\n */\nexport class CoreContentTypeRouteValidator extends AbstractCoreRouteValidator<UID.ContentType> {\n /**\n * Generates a validation schema for document IDs\n *\n * @returns A schema that validates UUIDs\n *\n * @example\n * ```ts\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n * const idSchema = validator.documentID;\n * ```\n */\n get documentID() {\n return z.uuid().describe('The document ID, represented by a UUID');\n }\n\n /**\n * Generates a comprehensive validation schema for a single document.\n *\n * Combines scalar fields and populatable fields into a single schema.\n *\n * @returns A schema for validating complete documents\n *\n * @example\n * ```ts\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n * const docSchema = validator.document;\n * ```\n */\n get document() {\n const entries = Object.entries({ ...this._scalarFields, ...this._populatableFields });\n\n const sanitizedAttributes = entries\n // Remove passwords from the attribute list\n .filter(([, attribute]) => !['password'].includes(attribute.type));\n\n // Merge all attributes into a single schema\n const attributesSchema = createAttributesSchema(this._strapi, sanitizedAttributes);\n\n return z\n .object({\n documentId: this.documentID,\n id: z.union([z.string(), z.number()]),\n })\n .extend(attributesSchema.shape);\n }\n\n /**\n * Generates a validation schema for an array of documents\n *\n * @returns A schema for validating arrays of documents\n *\n * @example\n * ```ts\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n * const docsSchema = validator.documents;\n * ```\n */\n get documents() {\n return z.array(this.document);\n }\n\n /**\n * Schema-aware fields validation that restricts to actual model fields\n */\n protected get schemaAwareQueryFields() {\n return this.scalarFieldsArray\n .readonly()\n .describe(\n `The fields to return, this doesn't include populatable fields like relations, components, files, or dynamic zones`\n );\n }\n\n /**\n * Schema-aware populate validation that restricts to actual populatable fields\n */\n protected get schemaAwareQueryPopulate() {\n const wildcardPopulate = z\n .literal('*')\n .readonly()\n .describe(\n 'Populate all the first level relations, components, files, and dynamic zones for the entry'\n );\n\n const singleFieldPopulate = this.populatableFieldsEnum\n .readonly()\n .describe('Populate a single relation, component, file, or dynamic zone');\n\n const multiPopulate = this.populatableFieldsArray.describe(\n 'Populate a selection of multiple relations, components, files, or dynamic zones'\n );\n\n return z.union([wildcardPopulate, singleFieldPopulate, multiPopulate]);\n }\n\n /**\n * Schema-aware sort validation that restricts to actual model fields\n */\n protected get schemaAwareQuerySort() {\n const orderDirection = z.enum(['asc', 'desc']);\n\n // TODO: Handle nested sorts but very low priority, very little usage\n return z\n .union([\n this.scalarFieldsEnum, // 'name' | 'title'\n this.scalarFieldsArray, // ['name', 'title']\n this.fieldRecord(orderDirection), // { name: 'desc' } | { title: 'asc' }\n z.array(this.fieldRecord(orderDirection)), // [{ name: 'desc'}, { title: 'asc' }]\n ])\n .describe('Sort the result');\n }\n\n /**\n * Schema-aware filters validation that restricts to actual model fields\n */\n protected get schemaAwareFilters() {\n return z\n .partialRecord(this.scalarFieldsEnum, z.any())\n .describe('Filters to apply to the query');\n }\n\n get locale() {\n return z.string().describe('Select a locale');\n }\n\n get status() {\n return z\n .enum(['draft', 'published'])\n .describe('Fetch documents based on their status. Default to \"published\" if not specified.');\n }\n\n get publicationFilter() {\n return z\n .enum([\n 'never-published',\n 'has-published-version',\n 'modified',\n 'unmodified',\n 'never-published-document',\n 'has-published-version-document',\n 'published-without-draft',\n 'published-with-draft',\n ])\n .describe(\n 'Derived publication cohort: pair-scoped (per documentId+locale), document-scoped variants (-document), or published-slice diagnostics (published-without-draft / published-with-draft)'\n );\n }\n\n /** @deprecated Use `publicationFilter` instead (`never-published`, `has-published-version`, …). */\n get hasPublishedVersion() {\n return z\n .union([z.boolean(), z.enum(['true', 'false'])])\n .describe(\n '[Deprecated: prefer publicationFilter] Filter documents by whether they have a published version. Use with status=draft to find documents that have never been published'\n );\n }\n\n get data() {\n const isWritableAttribute = ([attributeName]: [string, Schema.Attribute.AnyAttribute]) => {\n return contentTypes.isWritableAttribute(this._schema, attributeName);\n };\n\n const entries = Object.entries({ ...this._scalarFields, ...this._populatableFields });\n\n const sanitizedAttributes = entries\n // Remove non-writable attributes\n .filter(isWritableAttribute);\n\n return createAttributesInputSchema(this._strapi, sanitizedAttributes);\n }\n\n get query() {\n return z.string();\n }\n\n get body() {\n return z.object({ data: this.data });\n }\n\n get partialBody() {\n return z.object({ data: this.data.partial() });\n }\n\n /**\n * Creates validation schemas for query parameters\n *\n * @param params - Array of query parameters to validate ('fields', 'populate', 'sort', ...)\n * @returns Object containing validation schemas for requested parameters\n *\n * @example\n * ```ts\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n * const querySchemas = validator.queryParams(['fields', 'populate']);\n * ```\n */\n queryParams(params: QueryParam[]): Partial<Record<QueryParam, z.Schema>> {\n const map: Record<QueryParam, () => z.Schema> = {\n fields: () => this.schemaAwareQueryFields.optional(),\n populate: () => this.schemaAwareQueryPopulate.optional(),\n sort: () => this.schemaAwareQuerySort.optional(),\n filters: () => this.schemaAwareFilters.optional(),\n locale: () => this.locale.optional(),\n pagination: () => this.pagination.optional(),\n status: () => this.status.optional(),\n publicationFilter: () => this.publicationFilter.optional(),\n hasPublishedVersion: () => this.hasPublishedVersion.optional(),\n _q: () => this.query.optional(),\n } as const;\n\n return params.reduce(\n (acc, param) => ({ ...acc, [param]: map[param]() }),\n {} as Partial<Record<QueryParam, z.Schema>>\n );\n }\n}\n"],"names":["CoreContentTypeRouteValidator","AbstractCoreRouteValidator","documentID","z","uuid","describe","document","entries","Object","_scalarFields","_populatableFields","sanitizedAttributes","filter","attribute","includes","type","attributesSchema","createAttributesSchema","_strapi","object","documentId","id","union","string","number","extend","shape","documents","array","schemaAwareQueryFields","scalarFieldsArray","readonly","schemaAwareQueryPopulate","wildcardPopulate","literal","singleFieldPopulate","populatableFieldsEnum","multiPopulate","populatableFieldsArray","schemaAwareQuerySort","orderDirection","enum","scalarFieldsEnum","fieldRecord","schemaAwareFilters","partialRecord","any","locale","status","publicationFilter","hasPublishedVersion","boolean","data","isWritableAttribute","attributeName","contentTypes","_schema","createAttributesInputSchema","query","body","partialBody","partial","queryParams","params","map","fields","optional","populate","sort","filters","pagination","_q","reduce","acc","param"],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as z from 'zod/v4';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a per-application store of named Zod schemas for content-API validation.
|
|
4
|
+
*
|
|
5
|
+
* An owned Zod registry is kept in sync with the ID map so schema identity is
|
|
6
|
+
* preserved during construction. The map is the source of truth for lookup and
|
|
7
|
+
* iteration; OpenAPI conversion must copy `entries()` into a conversion-local
|
|
8
|
+
* registry rather than reading the live Zod registry.
|
|
9
|
+
*/
|
|
10
|
+
export declare const createContentAPISchemaRegistry: () => {
|
|
11
|
+
set: (id: string, schema: z.ZodType) => void;
|
|
12
|
+
get: (id: string) => z.ZodType | undefined;
|
|
13
|
+
getOrDefer: (id: string) => z.ZodType | undefined;
|
|
14
|
+
has: (id: string) => boolean;
|
|
15
|
+
startPending: (id: string) => void;
|
|
16
|
+
finishPending: (id: string) => void;
|
|
17
|
+
entries: () => Iterable<[string, z.ZodType]>;
|
|
18
|
+
remove: (id: string) => boolean;
|
|
19
|
+
clear: () => void;
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=schema-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-registry.d.ts","sourceRoot":"","sources":["../../../../src/core-api/routes/validation/schema-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAQ5B;;;;;;;GAOG;AACH,eAAO,MAAM,8BAA8B;cAqBxB,MAAM,UAAU,CAAC,CAAC,OAAO,KAAG,IAAI;cAdhC,MAAM,KAAG,CAAC,CAAC,OAAO,GAAG,SAAS;qBA4BvB,MAAM,KAAG,CAAC,CAAC,OAAO,GAAG,SAAS;cAFrC,MAAM,KAAG,OAAO;uBAUP,MAAM,KAAG,IAAI;wBAIZ,MAAM,KAAG,IAAI;mBAIpB,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;iBAE7B,MAAM,KAAG,OAAO;iBAWlB,IAAI;CAiBvB,CAAC"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var z = require('zod/v4');
|
|
4
|
+
|
|
5
|
+
function _interopNamespace(e) {
|
|
6
|
+
if (e && e.__esModule) return e;
|
|
7
|
+
var n = Object.create(null);
|
|
8
|
+
if (e) {
|
|
9
|
+
Object.keys(e).forEach(function (k) {
|
|
10
|
+
if (k !== 'default') {
|
|
11
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
12
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () { return e[k]; }
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
n.default = e;
|
|
20
|
+
return Object.freeze(n);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
var z__namespace = /*#__PURE__*/_interopNamespace(z);
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Creates a per-application store of named Zod schemas for content-API validation.
|
|
27
|
+
*
|
|
28
|
+
* An owned Zod registry is kept in sync with the ID map so schema identity is
|
|
29
|
+
* preserved during construction. The map is the source of truth for lookup and
|
|
30
|
+
* iteration; OpenAPI conversion must copy `entries()` into a conversion-local
|
|
31
|
+
* registry rather than reading the live Zod registry.
|
|
32
|
+
*/ const createContentAPISchemaRegistry = ()=>{
|
|
33
|
+
const store = {
|
|
34
|
+
registry: z__namespace.registry(),
|
|
35
|
+
schemas: new Map(),
|
|
36
|
+
pending: new Set()
|
|
37
|
+
};
|
|
38
|
+
const get = (id)=>store.schemas.get(id);
|
|
39
|
+
const getRequired = (id)=>{
|
|
40
|
+
const schema = get(id);
|
|
41
|
+
if (schema === undefined) {
|
|
42
|
+
throw new Error(`Content-API schema "${id}" was not registered`);
|
|
43
|
+
}
|
|
44
|
+
return schema;
|
|
45
|
+
};
|
|
46
|
+
const isPending = (id)=>store.pending.has(id);
|
|
47
|
+
const set = (id, schema)=>{
|
|
48
|
+
const existingSchema = store.schemas.get(id);
|
|
49
|
+
if (existingSchema !== undefined) {
|
|
50
|
+
store.registry.remove(existingSchema);
|
|
51
|
+
store.schemas.delete(id);
|
|
52
|
+
}
|
|
53
|
+
store.registry.add(schema, {
|
|
54
|
+
id
|
|
55
|
+
});
|
|
56
|
+
store.schemas.set(id, schema);
|
|
57
|
+
};
|
|
58
|
+
const has = (id)=>store.schemas.has(id);
|
|
59
|
+
const getOrDefer = (id)=>{
|
|
60
|
+
if (isPending(id) === true) {
|
|
61
|
+
return z__namespace.lazy(()=>getRequired(id));
|
|
62
|
+
}
|
|
63
|
+
return get(id);
|
|
64
|
+
};
|
|
65
|
+
const startPending = (id)=>{
|
|
66
|
+
store.pending.add(id);
|
|
67
|
+
};
|
|
68
|
+
const finishPending = (id)=>{
|
|
69
|
+
store.pending.delete(id);
|
|
70
|
+
};
|
|
71
|
+
const entries = ()=>store.schemas.entries();
|
|
72
|
+
const remove = (id)=>{
|
|
73
|
+
const schema = store.schemas.get(id);
|
|
74
|
+
if (schema === undefined) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
store.registry.remove(schema);
|
|
78
|
+
return store.schemas.delete(id);
|
|
79
|
+
};
|
|
80
|
+
const clear = ()=>{
|
|
81
|
+
store.registry.clear();
|
|
82
|
+
store.schemas.clear();
|
|
83
|
+
store.pending.clear();
|
|
84
|
+
};
|
|
85
|
+
return {
|
|
86
|
+
set,
|
|
87
|
+
get,
|
|
88
|
+
getOrDefer,
|
|
89
|
+
has,
|
|
90
|
+
startPending,
|
|
91
|
+
finishPending,
|
|
92
|
+
entries,
|
|
93
|
+
remove,
|
|
94
|
+
clear
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
exports.createContentAPISchemaRegistry = createContentAPISchemaRegistry;
|
|
99
|
+
//# sourceMappingURL=schema-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-registry.js","sources":["../../../../src/core-api/routes/validation/schema-registry.ts"],"sourcesContent":["import * as z from 'zod/v4';\n\ntype SchemaRegistryStore = {\n registry: ReturnType<typeof z.registry<z.core.GlobalMeta>>;\n schemas: Map<string, z.ZodType>;\n pending: Set<string>;\n};\n\n/**\n * Creates a per-application store of named Zod schemas for content-API validation.\n *\n * An owned Zod registry is kept in sync with the ID map so schema identity is\n * preserved during construction. The map is the source of truth for lookup and\n * iteration; OpenAPI conversion must copy `entries()` into a conversion-local\n * registry rather than reading the live Zod registry.\n */\nexport const createContentAPISchemaRegistry = () => {\n const store: SchemaRegistryStore = {\n registry: z.registry<z.core.GlobalMeta>(),\n schemas: new Map<string, z.ZodType>(),\n pending: new Set<string>(),\n };\n\n const get = (id: string): z.ZodType | undefined => store.schemas.get(id);\n\n const getRequired = (id: string): z.ZodType => {\n const schema = get(id);\n\n if (schema === undefined) {\n throw new Error(`Content-API schema \"${id}\" was not registered`);\n }\n\n return schema;\n };\n\n const isPending = (id: string): boolean => store.pending.has(id);\n\n const set = (id: string, schema: z.ZodType): void => {\n const existingSchema = store.schemas.get(id);\n\n if (existingSchema !== undefined) {\n store.registry.remove(existingSchema);\n store.schemas.delete(id);\n }\n\n store.registry.add(schema, { id });\n store.schemas.set(id, schema);\n };\n\n const has = (id: string): boolean => store.schemas.has(id);\n\n const getOrDefer = (id: string): z.ZodType | undefined => {\n if (isPending(id) === true) {\n return z.lazy(() => getRequired(id));\n }\n\n return get(id);\n };\n\n const startPending = (id: string): void => {\n store.pending.add(id);\n };\n\n const finishPending = (id: string): void => {\n store.pending.delete(id);\n };\n\n const entries = (): Iterable<[string, z.ZodType]> => store.schemas.entries();\n\n const remove = (id: string): boolean => {\n const schema = store.schemas.get(id);\n\n if (schema === undefined) {\n return false;\n }\n\n store.registry.remove(schema);\n return store.schemas.delete(id);\n };\n\n const clear = (): void => {\n store.registry.clear();\n store.schemas.clear();\n store.pending.clear();\n };\n\n return {\n set,\n get,\n getOrDefer,\n has,\n startPending,\n finishPending,\n entries,\n remove,\n clear,\n };\n};\n"],"names":["createContentAPISchemaRegistry","store","registry","z","schemas","Map","pending","Set","get","id","getRequired","schema","undefined","Error","isPending","has","set","existingSchema","remove","delete","add","getOrDefer","lazy","startPending","finishPending","entries","clear"],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import * as z from 'zod/v4';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Creates a per-application store of named Zod schemas for content-API validation.
|
|
5
|
+
*
|
|
6
|
+
* An owned Zod registry is kept in sync with the ID map so schema identity is
|
|
7
|
+
* preserved during construction. The map is the source of truth for lookup and
|
|
8
|
+
* iteration; OpenAPI conversion must copy `entries()` into a conversion-local
|
|
9
|
+
* registry rather than reading the live Zod registry.
|
|
10
|
+
*/ const createContentAPISchemaRegistry = ()=>{
|
|
11
|
+
const store = {
|
|
12
|
+
registry: z.registry(),
|
|
13
|
+
schemas: new Map(),
|
|
14
|
+
pending: new Set()
|
|
15
|
+
};
|
|
16
|
+
const get = (id)=>store.schemas.get(id);
|
|
17
|
+
const getRequired = (id)=>{
|
|
18
|
+
const schema = get(id);
|
|
19
|
+
if (schema === undefined) {
|
|
20
|
+
throw new Error(`Content-API schema "${id}" was not registered`);
|
|
21
|
+
}
|
|
22
|
+
return schema;
|
|
23
|
+
};
|
|
24
|
+
const isPending = (id)=>store.pending.has(id);
|
|
25
|
+
const set = (id, schema)=>{
|
|
26
|
+
const existingSchema = store.schemas.get(id);
|
|
27
|
+
if (existingSchema !== undefined) {
|
|
28
|
+
store.registry.remove(existingSchema);
|
|
29
|
+
store.schemas.delete(id);
|
|
30
|
+
}
|
|
31
|
+
store.registry.add(schema, {
|
|
32
|
+
id
|
|
33
|
+
});
|
|
34
|
+
store.schemas.set(id, schema);
|
|
35
|
+
};
|
|
36
|
+
const has = (id)=>store.schemas.has(id);
|
|
37
|
+
const getOrDefer = (id)=>{
|
|
38
|
+
if (isPending(id) === true) {
|
|
39
|
+
return z.lazy(()=>getRequired(id));
|
|
40
|
+
}
|
|
41
|
+
return get(id);
|
|
42
|
+
};
|
|
43
|
+
const startPending = (id)=>{
|
|
44
|
+
store.pending.add(id);
|
|
45
|
+
};
|
|
46
|
+
const finishPending = (id)=>{
|
|
47
|
+
store.pending.delete(id);
|
|
48
|
+
};
|
|
49
|
+
const entries = ()=>store.schemas.entries();
|
|
50
|
+
const remove = (id)=>{
|
|
51
|
+
const schema = store.schemas.get(id);
|
|
52
|
+
if (schema === undefined) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
store.registry.remove(schema);
|
|
56
|
+
return store.schemas.delete(id);
|
|
57
|
+
};
|
|
58
|
+
const clear = ()=>{
|
|
59
|
+
store.registry.clear();
|
|
60
|
+
store.schemas.clear();
|
|
61
|
+
store.pending.clear();
|
|
62
|
+
};
|
|
63
|
+
return {
|
|
64
|
+
set,
|
|
65
|
+
get,
|
|
66
|
+
getOrDefer,
|
|
67
|
+
has,
|
|
68
|
+
startPending,
|
|
69
|
+
finishPending,
|
|
70
|
+
entries,
|
|
71
|
+
remove,
|
|
72
|
+
clear
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export { createContentAPISchemaRegistry };
|
|
77
|
+
//# sourceMappingURL=schema-registry.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-registry.mjs","sources":["../../../../src/core-api/routes/validation/schema-registry.ts"],"sourcesContent":["import * as z from 'zod/v4';\n\ntype SchemaRegistryStore = {\n registry: ReturnType<typeof z.registry<z.core.GlobalMeta>>;\n schemas: Map<string, z.ZodType>;\n pending: Set<string>;\n};\n\n/**\n * Creates a per-application store of named Zod schemas for content-API validation.\n *\n * An owned Zod registry is kept in sync with the ID map so schema identity is\n * preserved during construction. The map is the source of truth for lookup and\n * iteration; OpenAPI conversion must copy `entries()` into a conversion-local\n * registry rather than reading the live Zod registry.\n */\nexport const createContentAPISchemaRegistry = () => {\n const store: SchemaRegistryStore = {\n registry: z.registry<z.core.GlobalMeta>(),\n schemas: new Map<string, z.ZodType>(),\n pending: new Set<string>(),\n };\n\n const get = (id: string): z.ZodType | undefined => store.schemas.get(id);\n\n const getRequired = (id: string): z.ZodType => {\n const schema = get(id);\n\n if (schema === undefined) {\n throw new Error(`Content-API schema \"${id}\" was not registered`);\n }\n\n return schema;\n };\n\n const isPending = (id: string): boolean => store.pending.has(id);\n\n const set = (id: string, schema: z.ZodType): void => {\n const existingSchema = store.schemas.get(id);\n\n if (existingSchema !== undefined) {\n store.registry.remove(existingSchema);\n store.schemas.delete(id);\n }\n\n store.registry.add(schema, { id });\n store.schemas.set(id, schema);\n };\n\n const has = (id: string): boolean => store.schemas.has(id);\n\n const getOrDefer = (id: string): z.ZodType | undefined => {\n if (isPending(id) === true) {\n return z.lazy(() => getRequired(id));\n }\n\n return get(id);\n };\n\n const startPending = (id: string): void => {\n store.pending.add(id);\n };\n\n const finishPending = (id: string): void => {\n store.pending.delete(id);\n };\n\n const entries = (): Iterable<[string, z.ZodType]> => store.schemas.entries();\n\n const remove = (id: string): boolean => {\n const schema = store.schemas.get(id);\n\n if (schema === undefined) {\n return false;\n }\n\n store.registry.remove(schema);\n return store.schemas.delete(id);\n };\n\n const clear = (): void => {\n store.registry.clear();\n store.schemas.clear();\n store.pending.clear();\n };\n\n return {\n set,\n get,\n getOrDefer,\n has,\n startPending,\n finishPending,\n entries,\n remove,\n clear,\n };\n};\n"],"names":["createContentAPISchemaRegistry","store","registry","z","schemas","Map","pending","Set","get","id","getRequired","schema","undefined","Error","isPending","has","set","existingSchema","remove","delete","add","getOrDefer","lazy","startPending","finishPending","entries","clear"],"mappings":"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"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { Core, Internal } from '@strapi/types';
|
|
2
2
|
import * as z from 'zod/v4';
|
|
3
3
|
/**
|
|
4
|
-
* Safely adds or updates a schema in
|
|
4
|
+
* Safely adds or updates a schema in Strapi's owned OpenAPI registry.
|
|
5
5
|
*
|
|
6
6
|
* If a schema with the given `id` already exists, it will be removed before adding the new one.
|
|
7
7
|
*
|
|
8
8
|
* This is useful for hot-reloading or preventing issues with cyclical dependencies.
|
|
9
9
|
*
|
|
10
|
-
* @param id - The unique identifier for the schema in
|
|
10
|
+
* @param id - The unique identifier for the schema in Strapi's registry.
|
|
11
11
|
* @param schema - The Zod schema to register.
|
|
12
12
|
* @example
|
|
13
13
|
* ```typescript
|
|
@@ -16,16 +16,16 @@ import * as z from 'zod/v4';
|
|
|
16
16
|
*/
|
|
17
17
|
export declare const safeGlobalRegistrySet: (strapi: Core.Strapi, id: Internal.UID.Schema, schema: z.ZodType) => void;
|
|
18
18
|
/**
|
|
19
|
-
* Safely creates and registers a Zod schema in
|
|
19
|
+
* Safely creates and registers a Zod schema in Strapi's owned OpenAPI registry, particularly useful for handling cyclical data structures.
|
|
20
20
|
*
|
|
21
|
-
* If a schema with the given `id` already exists in
|
|
21
|
+
* If a schema with the given `id` already exists in Strapi's registry, it returns the existing schema.
|
|
22
22
|
*
|
|
23
23
|
* Otherwise, it registers a temporary `z.any()` schema, calls the provided `callback` to create the actual schema,
|
|
24
24
|
* and then replaces the temporary schema with the actual one in the registry.
|
|
25
25
|
*
|
|
26
26
|
* This prevents infinite loops in cases of cyclical dependencies.
|
|
27
27
|
*
|
|
28
|
-
* @param id - The unique identifier for the schema in
|
|
28
|
+
* @param id - The unique identifier for the schema in Strapi's registry.
|
|
29
29
|
* @param callback - A function that returns the Zod schema to be created and registered.
|
|
30
30
|
* @returns The created or retrieved Zod schema.
|
|
31
31
|
* @example
|
|
@@ -43,5 +43,5 @@ export declare const safeGlobalRegistrySet: (strapi: Core.Strapi, id: Internal.U
|
|
|
43
43
|
* );
|
|
44
44
|
* ```
|
|
45
45
|
*/
|
|
46
|
-
export declare const safeSchemaCreation: (strapi: Core.Strapi, id: Internal.UID.Schema, callback: () => z.ZodType) => z.
|
|
46
|
+
export declare const safeSchemaCreation: (strapi: Core.Strapi, id: Internal.UID.Schema, callback: () => z.ZodType) => z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
|
|
47
47
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/core-api/routes/validation/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/core-api/routes/validation/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAM5B;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,qBAAqB,GAChC,QAAQ,IAAI,CAAC,MAAM,EACnB,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,EACvB,QAAQ,CAAC,CAAC,OAAO,SAmBlB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,IAAI,CAAC,MAAM,EACnB,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,EACvB,UAAU,MAAM,CAAC,CAAC,OAAO,4EA8D1B,CAAC"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var strapiUtils = require('@strapi/utils');
|
|
4
4
|
var z = require('zod/v4');
|
|
5
|
+
var zod = require('../../../utils/zod.js');
|
|
5
6
|
|
|
6
7
|
function _interopNamespace(e) {
|
|
7
8
|
if (e && e.__esModule) return e;
|
|
@@ -25,13 +26,13 @@ var z__namespace = /*#__PURE__*/_interopNamespace(z);
|
|
|
25
26
|
|
|
26
27
|
// Schema generation happens on-demand when schemas don't exist in the registry
|
|
27
28
|
/**
|
|
28
|
-
* Safely adds or updates a schema in
|
|
29
|
+
* Safely adds or updates a schema in Strapi's owned OpenAPI registry.
|
|
29
30
|
*
|
|
30
31
|
* If a schema with the given `id` already exists, it will be removed before adding the new one.
|
|
31
32
|
*
|
|
32
33
|
* This is useful for hot-reloading or preventing issues with cyclical dependencies.
|
|
33
34
|
*
|
|
34
|
-
* @param id - The unique identifier for the schema in
|
|
35
|
+
* @param id - The unique identifier for the schema in Strapi's registry.
|
|
35
36
|
* @param schema - The Zod schema to register.
|
|
36
37
|
* @example
|
|
37
38
|
* ```typescript
|
|
@@ -39,33 +40,27 @@ var z__namespace = /*#__PURE__*/_interopNamespace(z);
|
|
|
39
40
|
* ```
|
|
40
41
|
*/ const safeGlobalRegistrySet = (strapi, id, schema)=>{
|
|
41
42
|
try {
|
|
42
|
-
const { _idmap: idMap } = z__namespace.globalRegistry;
|
|
43
43
|
const transformedId = strapiUtils.transformUidToValidOpenApiName(id);
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
strapi.log.debug(`${isReplacing ? 'Replacing' : 'Registering'} schema ${transformedId} in global registry`);
|
|
50
|
-
z__namespace.globalRegistry.add(schema, {
|
|
51
|
-
id: transformedId
|
|
52
|
-
});
|
|
44
|
+
const schemaStore = strapi.contentAPISchemaRegistry;
|
|
45
|
+
const isReplacing = schemaStore.has(transformedId);
|
|
46
|
+
strapi.log.debug(`${isReplacing ? 'Replacing' : 'Registering'} schema ${transformedId} in Strapi registry`);
|
|
47
|
+
schemaStore.set(transformedId, schema);
|
|
53
48
|
} catch (error) {
|
|
54
|
-
strapi.log.error(`Schema registration failed: Failed to register schema ${id} in
|
|
49
|
+
strapi.log.error(`Schema registration failed: Failed to register schema ${id} in Strapi registry`);
|
|
55
50
|
throw error;
|
|
56
51
|
}
|
|
57
52
|
};
|
|
58
53
|
/**
|
|
59
|
-
* Safely creates and registers a Zod schema in
|
|
54
|
+
* Safely creates and registers a Zod schema in Strapi's owned OpenAPI registry, particularly useful for handling cyclical data structures.
|
|
60
55
|
*
|
|
61
|
-
* If a schema with the given `id` already exists in
|
|
56
|
+
* If a schema with the given `id` already exists in Strapi's registry, it returns the existing schema.
|
|
62
57
|
*
|
|
63
58
|
* Otherwise, it registers a temporary `z.any()` schema, calls the provided `callback` to create the actual schema,
|
|
64
59
|
* and then replaces the temporary schema with the actual one in the registry.
|
|
65
60
|
*
|
|
66
61
|
* This prevents infinite loops in cases of cyclical dependencies.
|
|
67
62
|
*
|
|
68
|
-
* @param id - The unique identifier for the schema in
|
|
63
|
+
* @param id - The unique identifier for the schema in Strapi's registry.
|
|
69
64
|
* @param callback - A function that returns the Zod schema to be created and registered.
|
|
70
65
|
* @returns The created or retrieved Zod schema.
|
|
71
66
|
* @example
|
|
@@ -84,13 +79,12 @@ var z__namespace = /*#__PURE__*/_interopNamespace(z);
|
|
|
84
79
|
* ```
|
|
85
80
|
*/ const safeSchemaCreation = (strapi, id, callback)=>{
|
|
86
81
|
try {
|
|
87
|
-
const { _idmap: idMap } = z__namespace.globalRegistry;
|
|
88
82
|
const transformedId = strapiUtils.transformUidToValidOpenApiName(id);
|
|
83
|
+
const schemaStore = strapi.contentAPISchemaRegistry;
|
|
89
84
|
// Return existing schema if already registered
|
|
90
|
-
const
|
|
91
|
-
if (
|
|
92
|
-
|
|
93
|
-
return mapItem;
|
|
85
|
+
const existingSchema = schemaStore.getOrDefer(transformedId);
|
|
86
|
+
if (existingSchema !== undefined) {
|
|
87
|
+
return existingSchema;
|
|
94
88
|
}
|
|
95
89
|
strapi.log.debug(`Schema ${transformedId} not found in registry, generating new schema`);
|
|
96
90
|
// Determine if this is a built-in schema or user content
|
|
@@ -101,20 +95,26 @@ var z__namespace = /*#__PURE__*/_interopNamespace(z);
|
|
|
101
95
|
const schemaName = transformedId.replace('Document', '').replace('Entry', '').replace(/([A-Z])/g, ' $1').trim();
|
|
102
96
|
strapi.log.debug(`📝 Generating validation schema for "${schemaName}"`);
|
|
103
97
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
98
|
+
schemaStore.startPending(transformedId);
|
|
99
|
+
try {
|
|
100
|
+
// Temporary any placeholder before replacing with the actual schema type
|
|
101
|
+
// Used to prevent infinite loops in cyclical data structures
|
|
102
|
+
safeGlobalRegistrySet(strapi, id, z__namespace.any());
|
|
103
|
+
// Generate the actual schema using the callback
|
|
104
|
+
const schema = callback();
|
|
105
|
+
// Replace the placeholder with the real schema
|
|
106
|
+
safeGlobalRegistrySet(strapi, id, schema);
|
|
107
|
+
// Show completion for user content only
|
|
108
|
+
if (!isBuiltInSchema) {
|
|
109
|
+
const inspection = zod.inspectZodSchema(schema);
|
|
110
|
+
const fieldCount = inspection.type === 'object' ? Object.keys(inspection.shape).length : 0;
|
|
111
|
+
const schemaName = transformedId.replace('Document', '').replace('Entry', '').replace(/([A-Z])/g, ' $1').trim();
|
|
112
|
+
strapi.log.debug(` ✅ "${schemaName}" schema created with ${fieldCount} fields`);
|
|
113
|
+
}
|
|
114
|
+
return schema;
|
|
115
|
+
} finally{
|
|
116
|
+
schemaStore.finishPending(transformedId);
|
|
116
117
|
}
|
|
117
|
-
return schema;
|
|
118
118
|
} catch (error) {
|
|
119
119
|
strapi.log.error(`Schema creation failed: Failed to create schema ${id}`);
|
|
120
120
|
throw error;
|