@strapi/core 0.0.0-experimental.1e4c115f717b021ca11c139584d4519db28ba786 → 0.0.0-experimental.1f56e9319665c8cc385eb5e4178ceb6741c6d490
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.
Potentially problematic release.
This version of @strapi/core might be problematic. Click here for more details.
- package/dist/Strapi.d.ts +1 -0
- package/dist/Strapi.d.ts.map +1 -1
- package/dist/Strapi.js +23 -2
- package/dist/Strapi.js.map +1 -1
- package/dist/Strapi.mjs +23 -2
- package/dist/Strapi.mjs.map +1 -1
- package/dist/constants.d.ts +3 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +6 -0
- package/dist/constants.js.map +1 -0
- package/dist/constants.mjs +4 -0
- package/dist/constants.mjs.map +1 -0
- package/dist/core-api/controller/index.d.ts.map +1 -1
- package/dist/core-api/controller/index.js +2 -1
- package/dist/core-api/controller/index.js.map +1 -1
- package/dist/core-api/controller/index.mjs +2 -1
- package/dist/core-api/controller/index.mjs.map +1 -1
- package/dist/core-api/controller/transform.d.ts +3 -2
- package/dist/core-api/controller/transform.d.ts.map +1 -1
- package/dist/core-api/controller/transform.js +13 -3
- package/dist/core-api/controller/transform.js.map +1 -1
- package/dist/core-api/controller/transform.mjs +13 -3
- package/dist/core-api/controller/transform.mjs.map +1 -1
- package/dist/core-api/routes/index.d.ts.map +1 -1
- package/dist/core-api/routes/index.js +28 -9
- package/dist/core-api/routes/index.js.map +1 -1
- package/dist/core-api/routes/index.mjs +1 -1
- package/dist/core-api/routes/index.mjs.map +1 -1
- package/dist/core-api/routes/validation/attributes.d.ts +243 -90
- package/dist/core-api/routes/validation/attributes.d.ts.map +1 -1
- package/dist/core-api/routes/validation/attributes.js +541 -564
- package/dist/core-api/routes/validation/attributes.js.map +1 -1
- package/dist/core-api/routes/validation/attributes.mjs +505 -564
- package/dist/core-api/routes/validation/attributes.mjs.map +1 -1
- package/dist/core-api/routes/validation/common.d.ts +7 -5
- package/dist/core-api/routes/validation/common.d.ts.map +1 -1
- package/dist/core-api/routes/validation/common.js +29 -8
- package/dist/core-api/routes/validation/common.js.map +1 -1
- package/dist/core-api/routes/validation/common.mjs +6 -4
- package/dist/core-api/routes/validation/common.mjs.map +1 -1
- package/dist/core-api/routes/validation/component.d.ts +2 -10
- package/dist/core-api/routes/validation/component.d.ts.map +1 -1
- package/dist/core-api/routes/validation/component.js +3 -17
- package/dist/core-api/routes/validation/component.js.map +1 -1
- package/dist/core-api/routes/validation/component.mjs +3 -17
- package/dist/core-api/routes/validation/component.mjs.map +1 -1
- package/dist/core-api/routes/validation/constants.d.ts +6 -0
- package/dist/core-api/routes/validation/constants.d.ts.map +1 -1
- package/dist/core-api/routes/validation/constants.js +6 -1
- package/dist/core-api/routes/validation/constants.js.map +1 -1
- package/dist/core-api/routes/validation/constants.mjs +6 -1
- package/dist/core-api/routes/validation/constants.mjs.map +1 -1
- package/dist/core-api/routes/validation/content-type.d.ts +28 -71
- package/dist/core-api/routes/validation/content-type.d.ts.map +1 -1
- package/dist/core-api/routes/validation/content-type.js +67 -112
- package/dist/core-api/routes/validation/content-type.js.map +1 -1
- package/dist/core-api/routes/validation/content-type.mjs +36 -100
- package/dist/core-api/routes/validation/content-type.mjs.map +1 -1
- package/dist/core-api/routes/validation/index.d.ts +1 -1
- package/dist/core-api/routes/validation/index.d.ts.map +1 -1
- package/dist/core-api/routes/validation/mappers.d.ts +105 -0
- package/dist/core-api/routes/validation/mappers.d.ts.map +1 -0
- package/dist/core-api/routes/validation/mappers.js +273 -0
- package/dist/core-api/routes/validation/mappers.js.map +1 -0
- package/dist/core-api/routes/validation/mappers.mjs +249 -0
- package/dist/core-api/routes/validation/mappers.mjs.map +1 -0
- package/dist/core-api/routes/validation/utils.d.ts +47 -0
- package/dist/core-api/routes/validation/utils.d.ts.map +1 -0
- package/dist/core-api/routes/validation/utils.js +128 -0
- package/dist/core-api/routes/validation/utils.js.map +1 -0
- package/dist/core-api/routes/validation/utils.mjs +106 -0
- package/dist/core-api/routes/validation/utils.mjs.map +1 -0
- package/dist/domain/content-type/index.d.ts.map +1 -1
- package/dist/domain/content-type/index.js +17 -1
- package/dist/domain/content-type/index.js.map +1 -1
- package/dist/domain/content-type/index.mjs +17 -1
- package/dist/domain/content-type/index.mjs.map +1 -1
- package/dist/ee/index.d.ts +6 -0
- package/dist/ee/index.d.ts.map +1 -1
- package/dist/ee/index.js +29 -3
- package/dist/ee/index.js.map +1 -1
- package/dist/ee/index.mjs +30 -4
- package/dist/ee/index.mjs.map +1 -1
- package/dist/ee/license.d.ts +3 -1
- package/dist/ee/license.d.ts.map +1 -1
- package/dist/ee/license.js +6 -1
- package/dist/ee/license.js.map +1 -1
- package/dist/ee/license.mjs +6 -2
- package/dist/ee/license.mjs.map +1 -1
- package/dist/factories.js +1 -1
- package/dist/factories.mjs +1 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/loaders/plugins/index.js +1 -1
- package/dist/loaders/plugins/index.js.map +1 -1
- package/dist/loaders/plugins/index.mjs +1 -1
- package/dist/loaders/plugins/index.mjs.map +1 -1
- package/dist/middlewares/cors.d.ts +9 -1
- package/dist/middlewares/cors.d.ts.map +1 -1
- package/dist/middlewares/cors.js +39 -17
- package/dist/middlewares/cors.js.map +1 -1
- package/dist/middlewares/cors.mjs +39 -18
- package/dist/middlewares/cors.mjs.map +1 -1
- package/dist/migrations/first-published-at.d.ts +4 -0
- package/dist/migrations/first-published-at.d.ts.map +1 -0
- package/dist/migrations/first-published-at.js +51 -0
- package/dist/migrations/first-published-at.js.map +1 -0
- package/dist/migrations/first-published-at.mjs +49 -0
- package/dist/migrations/first-published-at.mjs.map +1 -0
- package/dist/migrations/index.d.ts.map +1 -1
- package/dist/migrations/index.js +5 -0
- package/dist/migrations/index.js.map +1 -1
- package/dist/migrations/index.mjs +5 -0
- package/dist/migrations/index.mjs.map +1 -1
- package/dist/package.json.js +17 -13
- package/dist/package.json.js.map +1 -1
- package/dist/package.json.mjs +17 -13
- package/dist/package.json.mjs.map +1 -1
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +2 -0
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/index.mjs +2 -0
- package/dist/providers/index.mjs.map +1 -1
- package/dist/providers/session-manager.d.ts +3 -0
- package/dist/providers/session-manager.d.ts.map +1 -0
- package/dist/providers/session-manager.js +23 -0
- package/dist/providers/session-manager.js.map +1 -0
- package/dist/providers/session-manager.mjs +21 -0
- package/dist/providers/session-manager.mjs.map +1 -0
- package/dist/services/content-api/index.d.ts +1 -1
- package/dist/services/content-api/index.d.ts.map +1 -1
- package/dist/services/content-api/index.js +1 -1
- package/dist/services/content-api/index.js.map +1 -1
- package/dist/services/content-api/index.mjs +2 -2
- package/dist/services/content-api/index.mjs.map +1 -1
- package/dist/services/content-source-maps.d.ts +13 -0
- package/dist/services/content-source-maps.d.ts.map +1 -0
- package/dist/services/content-source-maps.js +108 -0
- package/dist/services/content-source-maps.js.map +1 -0
- package/dist/services/content-source-maps.mjs +106 -0
- package/dist/services/content-source-maps.mjs.map +1 -0
- package/dist/services/core-store.d.ts +2 -2
- package/dist/services/core-store.d.ts.map +1 -1
- package/dist/services/core-store.js.map +1 -1
- package/dist/services/core-store.mjs.map +1 -1
- package/dist/services/document-service/components.d.ts +31 -1
- package/dist/services/document-service/components.d.ts.map +1 -1
- package/dist/services/document-service/components.js +109 -0
- package/dist/services/document-service/components.js.map +1 -1
- package/dist/services/document-service/components.mjs +107 -1
- package/dist/services/document-service/components.mjs.map +1 -1
- package/dist/services/document-service/entries.d.ts.map +1 -1
- package/dist/services/document-service/entries.js +42 -0
- package/dist/services/document-service/entries.js.map +1 -1
- package/dist/services/document-service/entries.mjs +43 -1
- package/dist/services/document-service/entries.mjs.map +1 -1
- package/dist/services/document-service/first-published-at.d.ts +7 -0
- package/dist/services/document-service/first-published-at.d.ts.map +1 -0
- package/dist/services/document-service/first-published-at.js +31 -0
- package/dist/services/document-service/first-published-at.js.map +1 -0
- package/dist/services/document-service/first-published-at.mjs +28 -0
- package/dist/services/document-service/first-published-at.mjs.map +1 -0
- package/dist/services/document-service/internationalization.d.ts +6 -1
- package/dist/services/document-service/internationalization.d.ts.map +1 -1
- package/dist/services/document-service/internationalization.js +32 -0
- package/dist/services/document-service/internationalization.js.map +1 -1
- package/dist/services/document-service/internationalization.mjs +32 -1
- package/dist/services/document-service/internationalization.mjs.map +1 -1
- package/dist/services/document-service/repository.d.ts.map +1 -1
- package/dist/services/document-service/repository.js +16 -8
- package/dist/services/document-service/repository.js.map +1 -1
- package/dist/services/document-service/repository.mjs +18 -10
- package/dist/services/document-service/repository.mjs.map +1 -1
- package/dist/services/document-service/utils/clean-component-join-table.d.ts +7 -0
- package/dist/services/document-service/utils/clean-component-join-table.d.ts.map +1 -0
- package/dist/services/document-service/utils/unidirectional-relations.d.ts +19 -2
- package/dist/services/document-service/utils/unidirectional-relations.d.ts.map +1 -1
- package/dist/services/document-service/utils/unidirectional-relations.js +21 -6
- package/dist/services/document-service/utils/unidirectional-relations.js.map +1 -1
- package/dist/services/document-service/utils/unidirectional-relations.mjs +21 -6
- package/dist/services/document-service/utils/unidirectional-relations.mjs.map +1 -1
- package/dist/services/entity-validator/index.d.ts.map +1 -1
- package/dist/services/entity-validator/index.js +9 -0
- package/dist/services/entity-validator/index.js.map +1 -1
- package/dist/services/entity-validator/index.mjs +9 -0
- package/dist/services/entity-validator/index.mjs.map +1 -1
- package/dist/services/entity-validator/validators.d.ts +1 -0
- package/dist/services/entity-validator/validators.d.ts.map +1 -1
- package/dist/services/entity-validator/validators.js +3 -0
- package/dist/services/entity-validator/validators.js.map +1 -1
- package/dist/services/entity-validator/validators.mjs +3 -0
- package/dist/services/entity-validator/validators.mjs.map +1 -1
- package/dist/services/metrics/index.d.ts +1 -1
- package/dist/services/metrics/index.d.ts.map +1 -1
- package/dist/services/metrics/index.js +11 -9
- package/dist/services/metrics/index.js.map +1 -1
- package/dist/services/metrics/index.mjs +11 -9
- package/dist/services/metrics/index.mjs.map +1 -1
- package/dist/services/metrics/middleware.d.ts +2 -1
- package/dist/services/metrics/middleware.d.ts.map +1 -1
- package/dist/services/metrics/middleware.js +2 -2
- package/dist/services/metrics/middleware.js.map +1 -1
- package/dist/services/metrics/middleware.mjs +2 -2
- package/dist/services/metrics/middleware.mjs.map +1 -1
- package/dist/services/metrics/sender.d.ts.map +1 -1
- package/dist/services/metrics/sender.js +4 -3
- package/dist/services/metrics/sender.js.map +1 -1
- package/dist/services/metrics/sender.mjs +4 -3
- package/dist/services/metrics/sender.mjs.map +1 -1
- package/dist/services/session-manager.d.ts +167 -0
- package/dist/services/session-manager.d.ts.map +1 -0
- package/dist/services/session-manager.js +529 -0
- package/dist/services/session-manager.js.map +1 -0
- package/dist/services/session-manager.mjs +526 -0
- package/dist/services/session-manager.mjs.map +1 -0
- package/dist/services/utils/conditional-fields.d.ts +3 -0
- package/dist/services/utils/conditional-fields.d.ts.map +1 -0
- package/dist/services/utils/conditional-fields.js +22 -0
- package/dist/services/utils/conditional-fields.js.map +1 -0
- package/dist/services/utils/conditional-fields.mjs +20 -0
- package/dist/services/utils/conditional-fields.mjs.map +1 -0
- package/dist/utils/fetch.d.ts +5 -1
- package/dist/utils/fetch.d.ts.map +1 -1
- package/dist/utils/fetch.js +8 -4
- package/dist/utils/fetch.js.map +1 -1
- package/dist/utils/fetch.mjs +8 -4
- package/dist/utils/fetch.mjs.map +1 -1
- package/dist/utils/transform-content-types-to-models.d.ts +197 -0
- package/dist/utils/transform-content-types-to-models.d.ts.map +1 -1
- package/package.json +17 -13
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { contentTypes } from '@strapi/utils';
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
2
|
+
import * as z from 'zod/v4';
|
|
3
|
+
import { createAttributesSchema, createAttributesInputSchema } from './mappers.mjs';
|
|
4
4
|
import { AbstractCoreRouteValidator } from './common.mjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* A validator for core content-type routes.
|
|
8
8
|
*
|
|
9
9
|
* Provides validation schemas and utilities for handling content-type-specific route validation.
|
|
10
|
+
* Extends the base AbstractRouteValidator with schema-aware validation for Strapi content types.
|
|
10
11
|
*
|
|
11
12
|
* @example
|
|
12
13
|
* ```ts
|
|
@@ -17,8 +18,8 @@ import { AbstractCoreRouteValidator } from './common.mjs';
|
|
|
17
18
|
* // Get validation schema for document
|
|
18
19
|
* const documentSchema = validator.document;
|
|
19
20
|
*
|
|
20
|
-
* // Validate query parameters
|
|
21
|
-
* const querySchema = validator.
|
|
21
|
+
* // Validate query parameters with schema awareness
|
|
22
|
+
* const querySchema = validator.queryParams(['fields', 'populate', 'sort']);
|
|
22
23
|
* ```
|
|
23
24
|
*/ class CoreContentTypeRouteValidator extends AbstractCoreRouteValidator {
|
|
24
25
|
/**
|
|
@@ -47,27 +48,20 @@ import { AbstractCoreRouteValidator } from './common.mjs';
|
|
|
47
48
|
* const docSchema = validator.document;
|
|
48
49
|
* ```
|
|
49
50
|
*/ get document() {
|
|
50
|
-
const { _scalarFields, _populatableFields } = this;
|
|
51
51
|
const entries = Object.entries({
|
|
52
|
-
..._scalarFields,
|
|
53
|
-
..._populatableFields
|
|
52
|
+
...this._scalarFields,
|
|
53
|
+
...this._populatableFields
|
|
54
54
|
});
|
|
55
|
-
const
|
|
56
|
-
// TODO: Make sure we're not leaking other fields like that
|
|
55
|
+
const sanitizedAttributes = entries// Remove passwords from the attribute list
|
|
57
56
|
.filter(([, attribute])=>![
|
|
58
57
|
'password'
|
|
59
|
-
].includes(attribute.type))
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return mapAttributeToSchema(attribute);
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
}, z.object({}));
|
|
67
|
-
return attributesSchema.extend({
|
|
58
|
+
].includes(attribute.type));
|
|
59
|
+
// Merge all attributes into a single schema
|
|
60
|
+
const attributesSchema = createAttributesSchema(sanitizedAttributes);
|
|
61
|
+
return z.object({
|
|
68
62
|
documentId: this.documentID,
|
|
69
63
|
id: z.number()
|
|
70
|
-
});
|
|
64
|
+
}).extend(attributesSchema.shape);
|
|
71
65
|
}
|
|
72
66
|
/**
|
|
73
67
|
* Generates a validation schema for an array of documents
|
|
@@ -83,31 +77,13 @@ import { AbstractCoreRouteValidator } from './common.mjs';
|
|
|
83
77
|
return z.array(this.document);
|
|
84
78
|
}
|
|
85
79
|
/**
|
|
86
|
-
*
|
|
87
|
-
|
|
88
|
-
* @returns A schema for validating field selection
|
|
89
|
-
*
|
|
90
|
-
* @example
|
|
91
|
-
* ```ts
|
|
92
|
-
* const validator = new CoreContentTypeRouteValidator(strapi, uid);
|
|
93
|
-
* const fieldsSchema = validator.queryFields;
|
|
94
|
-
* ```
|
|
95
|
-
*/ get queryFields() {
|
|
80
|
+
* Schema-aware fields validation that restricts to actual model fields
|
|
81
|
+
*/ get schemaAwareQueryFields() {
|
|
96
82
|
return this.scalarFieldsArray.readonly().describe(`The fields to return, this doesn't include populatable fields like relations, components, files, or dynamic zones`);
|
|
97
83
|
}
|
|
98
84
|
/**
|
|
99
|
-
*
|
|
100
|
-
|
|
101
|
-
* Allows wildcard (*), single field, and multiple field population.
|
|
102
|
-
*
|
|
103
|
-
* @returns A schema for validating populate parameters
|
|
104
|
-
*
|
|
105
|
-
* @example
|
|
106
|
-
* ```ts
|
|
107
|
-
* const validator = new CoreContentTypeRouteValidator(strapi, uid);
|
|
108
|
-
* const populateSchema = validator.queryPopulate;
|
|
109
|
-
* ```
|
|
110
|
-
*/ get queryPopulate() {
|
|
85
|
+
* Schema-aware populate validation that restricts to actual populatable fields
|
|
86
|
+
*/ get schemaAwareQueryPopulate() {
|
|
111
87
|
const wildcardPopulate = z.literal('*').readonly().describe('Populate all the first level relations, components, files, and dynamic zones for the entry');
|
|
112
88
|
const singleFieldPopulate = this.populatableFieldsEnum.readonly().describe('Populate a single relation, component, file, or dynamic zone');
|
|
113
89
|
const multiPopulate = this.populatableFieldsArray.describe('Populate a selection of multiple relations, components, files, or dynamic zones');
|
|
@@ -118,21 +94,8 @@ import { AbstractCoreRouteValidator } from './common.mjs';
|
|
|
118
94
|
]);
|
|
119
95
|
}
|
|
120
96
|
/**
|
|
121
|
-
*
|
|
122
|
-
|
|
123
|
-
* Allows various sorting formats including single field, multiple fields, and direction specifications
|
|
124
|
-
*
|
|
125
|
-
* @returns A schema for validating sort parameters
|
|
126
|
-
*
|
|
127
|
-
* @example
|
|
128
|
-
* ```ts
|
|
129
|
-
* const validator = new CoreContentTypeRouteValidator(strapi, uid);
|
|
130
|
-
* const sortSchema = validator.querySort;
|
|
131
|
-
* ```
|
|
132
|
-
*
|
|
133
|
-
* @remarks
|
|
134
|
-
* - Nested sorts are currently not supported
|
|
135
|
-
*/ get querySort() {
|
|
97
|
+
* Schema-aware sort validation that restricts to actual model fields
|
|
98
|
+
*/ get schemaAwareQuerySort() {
|
|
136
99
|
const orderDirection = z.enum([
|
|
137
100
|
'asc',
|
|
138
101
|
'desc'
|
|
@@ -145,8 +108,13 @@ import { AbstractCoreRouteValidator } from './common.mjs';
|
|
|
145
108
|
z.array(this.fieldRecord(orderDirection))
|
|
146
109
|
]).describe('Sort the result');
|
|
147
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* Schema-aware filters validation that restricts to actual model fields
|
|
113
|
+
*/ get schemaAwareFilters() {
|
|
114
|
+
return z.record(this.scalarFieldsEnum, z.any()).describe('Filters to apply to the query');
|
|
115
|
+
}
|
|
148
116
|
get locale() {
|
|
149
|
-
return z.string().
|
|
117
|
+
return z.string().describe('Select a locale');
|
|
150
118
|
}
|
|
151
119
|
get status() {
|
|
152
120
|
return z.enum([
|
|
@@ -154,41 +122,17 @@ import { AbstractCoreRouteValidator } from './common.mjs';
|
|
|
154
122
|
'published'
|
|
155
123
|
]).describe('Fetch documents based on their status. Default to "published" if not specified.');
|
|
156
124
|
}
|
|
157
|
-
get pagination() {
|
|
158
|
-
return z.intersection(z.object({
|
|
159
|
-
withCount: z.boolean().optional()
|
|
160
|
-
}), z.union([
|
|
161
|
-
z.object({
|
|
162
|
-
page: z.number(),
|
|
163
|
-
pageSize: z.number()
|
|
164
|
-
}).describe('Specify a page number and the number of entries per page'),
|
|
165
|
-
z.object({
|
|
166
|
-
start: z.number(),
|
|
167
|
-
limit: z.number()
|
|
168
|
-
}).describe('Specify how many entries to skip and to return')
|
|
169
|
-
])).describe('Pagination parameters');
|
|
170
|
-
}
|
|
171
|
-
get filters() {
|
|
172
|
-
return z.record(this.scalarFieldsEnum, z.any()).describe('Filters to apply to the query');
|
|
173
|
-
}
|
|
174
125
|
get data() {
|
|
175
|
-
const { _scalarFields, _populatableFields, _schema } = this;
|
|
176
126
|
const isWritableAttribute = ([attributeName])=>{
|
|
177
|
-
return contentTypes.isWritableAttribute(_schema, attributeName);
|
|
127
|
+
return contentTypes.isWritableAttribute(this._schema, attributeName);
|
|
178
128
|
};
|
|
179
129
|
const entries = Object.entries({
|
|
180
|
-
..._scalarFields,
|
|
181
|
-
..._populatableFields
|
|
130
|
+
...this._scalarFields,
|
|
131
|
+
...this._populatableFields
|
|
182
132
|
});
|
|
183
|
-
|
|
184
|
-
.filter(isWritableAttribute)
|
|
185
|
-
|
|
186
|
-
return acc.extend({
|
|
187
|
-
get [attributeName] () {
|
|
188
|
-
return mapAttributeToInputSchema(attribute);
|
|
189
|
-
}
|
|
190
|
-
});
|
|
191
|
-
}, z.object());
|
|
133
|
+
const sanitizedAttributes = entries// Remove non-writable attributes
|
|
134
|
+
.filter(isWritableAttribute);
|
|
135
|
+
return createAttributesInputSchema(sanitizedAttributes);
|
|
192
136
|
}
|
|
193
137
|
get query() {
|
|
194
138
|
return z.string();
|
|
@@ -212,14 +156,14 @@ import { AbstractCoreRouteValidator } from './common.mjs';
|
|
|
212
156
|
* @example
|
|
213
157
|
* ```ts
|
|
214
158
|
* const validator = new CoreContentTypeRouteValidator(strapi, uid);
|
|
215
|
-
* const querySchemas = validator.
|
|
159
|
+
* const querySchemas = validator.queryParams(['fields', 'populate']);
|
|
216
160
|
* ```
|
|
217
161
|
*/ queryParams(params) {
|
|
218
162
|
const map = {
|
|
219
|
-
fields: ()=>this.
|
|
220
|
-
populate: ()=>this.
|
|
221
|
-
sort: ()=>this.
|
|
222
|
-
filters: ()=>this.
|
|
163
|
+
fields: ()=>this.schemaAwareQueryFields.optional(),
|
|
164
|
+
populate: ()=>this.schemaAwareQueryPopulate.optional(),
|
|
165
|
+
sort: ()=>this.schemaAwareQuerySort.optional(),
|
|
166
|
+
filters: ()=>this.schemaAwareFilters.optional(),
|
|
223
167
|
locale: ()=>this.locale.optional(),
|
|
224
168
|
pagination: ()=>this.pagination.optional(),
|
|
225
169
|
status: ()=>this.status.optional(),
|
|
@@ -230,14 +174,6 @@ import { AbstractCoreRouteValidator } from './common.mjs';
|
|
|
230
174
|
[param]: map[param]()
|
|
231
175
|
}), {});
|
|
232
176
|
}
|
|
233
|
-
/**
|
|
234
|
-
* Creates a new instance of CoreContentTypeRouteValidator
|
|
235
|
-
*
|
|
236
|
-
* @param strapi - The Strapi instance
|
|
237
|
-
* @param uid - The content-type's unique identifier
|
|
238
|
-
*/ constructor(strapi, uid){
|
|
239
|
-
super(strapi, uid);
|
|
240
|
-
}
|
|
241
177
|
}
|
|
242
178
|
|
|
243
179
|
export { CoreContentTypeRouteValidator };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-type.mjs","sources":["../../../../src/core-api/routes/validation/content-type.ts"],"sourcesContent":["import type { Core, Schema, UID } from '@strapi/types';\n\nimport { contentTypes } from '@strapi/utils';\nimport { z } from 'zod';\n\nimport { mapAttributeToInputSchema, mapAttributeToSchema } from './attributes';\nimport { AbstractCoreRouteValidator } from './common';\n\nexport type QueryParam =\n | 'fields'\n | 'populate'\n | 'sort'\n | 'status'\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 *\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\n * const querySchema = validator.query(['fields', 'populate', 'sort']);\n * ```\n */\nexport class CoreContentTypeRouteValidator extends AbstractCoreRouteValidator<UID.ContentType> {\n /**\n * Creates a new instance of CoreContentTypeRouteValidator\n *\n * @param strapi - The Strapi instance\n * @param uid - The content-type's unique identifier\n */\n constructor(strapi: Core.Strapi, uid: UID.ContentType) {\n super(strapi, uid);\n }\n\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 { _scalarFields, _populatableFields } = this;\n\n const entries = Object.entries({ ..._scalarFields, ..._populatableFields });\n\n const attributesSchema = entries\n // Remove passwords from the attribute list\n // TODO: Make sure we're not leaking other fields like that\n .filter(([, attribute]) => !['password'].includes(attribute.type))\n // Merge all attributes into a single schema\n .reduce((acc, [attributeName, attribute]) => {\n return acc.extend({\n get [attributeName]() {\n return mapAttributeToSchema(attribute);\n },\n });\n }, z.object({}));\n\n return attributesSchema.extend({\n documentId: this.documentID,\n id: z.number(),\n });\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 * Generates a validation schema for field selection in queries\n *\n * @returns A schema for validating field selection\n *\n * @example\n * ```ts\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n * const fieldsSchema = validator.queryFields;\n * ```\n */\n get queryFields() {\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 * Generates a validation schema for populate operations.\n *\n * Allows wildcard (*), single field, and multiple field population.\n *\n * @returns A schema for validating populate parameters\n *\n * @example\n * ```ts\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n * const populateSchema = validator.queryPopulate;\n * ```\n */\n get queryPopulate() {\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 * Generates a validation schema for sorting parameters.\n *\n * Allows various sorting formats including single field, multiple fields, and direction specifications\n *\n * @returns A schema for validating sort parameters\n *\n * @example\n * ```ts\n * const validator = new CoreContentTypeRouteValidator(strapi, uid);\n * const sortSchema = validator.querySort;\n * ```\n *\n * @remarks\n * - Nested sorts are currently not supported\n */\n get querySort() {\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 get locale() {\n return z.string().optional().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 pagination() {\n return z\n .intersection(\n z.object({ withCount: z.boolean().optional() }),\n z.union([\n z\n .object({ page: z.number(), pageSize: z.number() })\n .describe('Specify a page number and the number of entries per page'),\n z\n .object({ start: z.number(), limit: z.number() })\n .describe('Specify how many entries to skip and to return'),\n ])\n )\n .describe('Pagination parameters');\n }\n\n get filters() {\n return z.record(this.scalarFieldsEnum, z.any()).describe('Filters to apply to the query');\n }\n\n get data() {\n const { _scalarFields, _populatableFields, _schema } = this;\n\n const isWritableAttribute = ([attributeName]: [string, Schema.Attribute.AnyAttribute]) => {\n return contentTypes.isWritableAttribute(_schema, attributeName);\n };\n\n const entries = Object.entries({ ..._scalarFields, ..._populatableFields });\n\n return (\n entries\n // Remove non-writable attributes\n .filter(isWritableAttribute)\n // Combine schemas\n .reduce((acc, [attributeName, attribute]) => {\n return acc.extend({\n get [attributeName]() {\n return mapAttributeToInputSchema(attribute);\n },\n });\n }, z.object())\n );\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.query(['fields', 'populate']);\n * ```\n */\n queryParams(params: QueryParam[]): Partial<Record<QueryParam, z.Schema>> {\n const map: Record<QueryParam, () => z.Schema> = {\n fields: () => this.queryFields.optional(),\n populate: () => this.queryPopulate.optional(),\n sort: () => this.querySort.optional(),\n filters: () => this.filters.optional(),\n locale: () => this.locale.optional(),\n pagination: () => this.pagination.optional(),\n status: () => this.status.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","_scalarFields","_populatableFields","entries","Object","attributesSchema","filter","attribute","includes","type","reduce","acc","attributeName","extend","mapAttributeToSchema","object","documentId","id","number","documents","array","queryFields","scalarFieldsArray","readonly","queryPopulate","wildcardPopulate","literal","singleFieldPopulate","populatableFieldsEnum","multiPopulate","populatableFieldsArray","union","querySort","orderDirection","enum","scalarFieldsEnum","fieldRecord","locale","string","optional","status","pagination","intersection","withCount","boolean","page","pageSize","start","limit","filters","record","any","data","_schema","isWritableAttribute","contentTypes","mapAttributeToInputSchema","query","body","partialBody","partial","queryParams","params","map","fields","populate","sort","_q","param","constructor","strapi","uid"],"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\nexport type QueryParam =\n | 'fields'\n | 'populate'\n | 'sort'\n | 'status'\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(sanitizedAttributes);\n\n return z\n .object({\n documentId: this.documentID,\n id: 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 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(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 _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","object","documentId","id","number","extend","shape","documents","array","schemaAwareQueryFields","scalarFieldsArray","readonly","schemaAwareQueryPopulate","wildcardPopulate","literal","singleFieldPopulate","populatableFieldsEnum","multiPopulate","populatableFieldsArray","union","schemaAwareQuerySort","orderDirection","enum","scalarFieldsEnum","fieldRecord","schemaAwareFilters","record","any","locale","string","status","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,5 +1,5 @@
|
|
|
1
1
|
export { AbstractCoreRouteValidator } from './common';
|
|
2
2
|
export { CoreContentTypeRouteValidator } from './content-type';
|
|
3
3
|
export { CoreComponentRouteValidator } from './component';
|
|
4
|
-
export { mapAttributeToSchema, mapAttributeToInputSchema } from './
|
|
4
|
+
export { createAttributesInputSchema, createAttributesSchema, mapAttributeToSchema, mapAttributeToInputSchema, } from './mappers';
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core-api/routes/validation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core-api/routes/validation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EACL,2BAA2B,EAC3B,sBAAsB,EACtB,oBAAoB,EACpB,yBAAyB,GAC1B,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview
|
|
3
|
+
* This file contains functions responsible for mapping Strapi attribute definitions to Zod schemas.
|
|
4
|
+
*/
|
|
5
|
+
import type { Schema } from '@strapi/types';
|
|
6
|
+
import * as z from 'zod/v4';
|
|
7
|
+
/**
|
|
8
|
+
* Creates a Zod schema for a collection of Strapi attributes.
|
|
9
|
+
*
|
|
10
|
+
* @param attributes - An array of tuples, where each tuple contains the attribute name and its schema definition.
|
|
11
|
+
* @returns A Zod object schema representing the combined attributes.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const myAttributes = [
|
|
16
|
+
* ['title', { type: 'string', required: true }],
|
|
17
|
+
* ['description', { type: 'text' }],
|
|
18
|
+
* ];
|
|
19
|
+
* const schema = createAttributesSchema(myAttributes);
|
|
20
|
+
* // schema will be a Zod object with 'title' and 'description' fields,
|
|
21
|
+
* // each mapped to their respective Zod schemas based on their Strapi attribute types.
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare const createAttributesSchema: (attributes: [name: string, attribute: Schema.Attribute.AnyAttribute][]) => z.ZodObject<{}, z.core.$strip>;
|
|
25
|
+
/**
|
|
26
|
+
* Creates a Zod input schema for a collection of Strapi attributes.
|
|
27
|
+
* This is typically used for validating incoming data (e.g., from API requests).
|
|
28
|
+
*
|
|
29
|
+
* @param attributes - An array of tuples, where each tuple contains the attribute name and its schema definition.
|
|
30
|
+
* @returns A Zod object schema representing the combined input attributes.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* const myInputAttributes = [
|
|
35
|
+
* ['email', { type: 'email', required: true }],
|
|
36
|
+
* ['description', { type: 'text', minLength: 8 }],
|
|
37
|
+
* ];
|
|
38
|
+
* const inputSchema = createAttributesInputSchema(myInputAttributes);
|
|
39
|
+
* // inputSchema will be a Zod object with 'email' and 'description' fields,
|
|
40
|
+
* // mapped to Zod schemas suitable for input validation.
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare const createAttributesInputSchema: (attributes: [name: string, attribute: Schema.Attribute.AnyAttribute][]) => z.ZodObject<{}, z.core.$strip>;
|
|
44
|
+
/**
|
|
45
|
+
* Maps a Strapi attribute definition to a corresponding Zod validation schema.
|
|
46
|
+
*
|
|
47
|
+
* This function handles every Strapi attribute types and converts them into
|
|
48
|
+
* appropriate Zod validation schemas.
|
|
49
|
+
*
|
|
50
|
+
* @param attribute - The Strapi attribute configuration object.
|
|
51
|
+
* @returns A Zod schema that corresponds to the input attribute's type.
|
|
52
|
+
* @throws {Error} Throws an error if an unsupported attribute type is provided.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* const stringAttribute = { type: 'string', minLength: 3 };
|
|
57
|
+
* const stringSchema = mapAttributeToSchema(stringAttribute); // Returns a Zod string schema with minLength.
|
|
58
|
+
*
|
|
59
|
+
* const booleanAttribute = { type: 'boolean', default: false };
|
|
60
|
+
* const booleanSchema = mapAttributeToSchema(booleanAttribute); // Returns a Zod boolean schema with a default.
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare const mapAttributeToSchema: (attribute: Schema.Attribute.AnyAttribute) => z.ZodTypeAny;
|
|
64
|
+
/**
|
|
65
|
+
* Maps a Strapi attribute definition to a corresponding Zod input validation schema.
|
|
66
|
+
*
|
|
67
|
+
* This function handles every Strapi attribute types and converts them into
|
|
68
|
+
* appropriate Zod validation schemas with their respective constraints.
|
|
69
|
+
*
|
|
70
|
+
* @param attribute - The Strapi attribute configuration object. Contains type information
|
|
71
|
+
* and validation rules for the attribute.
|
|
72
|
+
*
|
|
73
|
+
* @returns A Zod schema that corresponds to the input attribute's type and validation rules
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* // String attribute with constraints
|
|
78
|
+
* const stringAttribute = {
|
|
79
|
+
* type: 'string',
|
|
80
|
+
* minLength: 3,
|
|
81
|
+
* maxLength: 50,
|
|
82
|
+
* required: true
|
|
83
|
+
* };
|
|
84
|
+
* const stringSchema = mapAttributeToInputSchema(stringAttribute);
|
|
85
|
+
*
|
|
86
|
+
* // Enumeration attribute
|
|
87
|
+
* const enumAttribute = {
|
|
88
|
+
* type: 'enumeration',
|
|
89
|
+
* enum: ['draft', 'published', 'archived']
|
|
90
|
+
* };
|
|
91
|
+
* const enumSchema = mapAttributeToInputSchema(enumAttribute);
|
|
92
|
+
*
|
|
93
|
+
* // Media attribute with multiple files
|
|
94
|
+
* const mediaAttribute = {
|
|
95
|
+
* type: 'media',
|
|
96
|
+
* multiple: true
|
|
97
|
+
* };
|
|
98
|
+
* const mediaSchema = mapAttributeToInputSchema(mediaAttribute);
|
|
99
|
+
* ```
|
|
100
|
+
*
|
|
101
|
+
* @throws {Error} Throws an error if an unsupported attribute type is provided
|
|
102
|
+
*
|
|
103
|
+
*/
|
|
104
|
+
export declare const mapAttributeToInputSchema: (attribute: Schema.Attribute.AnyAttribute) => z.ZodTypeAny;
|
|
105
|
+
//# sourceMappingURL=mappers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mappers.d.ts","sourceRoot":"","sources":["../../../../src/core-api/routes/validation/mappers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAgB5B;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,sBAAsB,eACrB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,SAAS,CAAC,YAAY,CAAC,EAAE,mCASvE,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,2BAA2B,eAC1B,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,SAAS,CAAC,YAAY,CAAC,EAAE,mCASvE,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,oBAAoB,cAAe,OAAO,SAAS,CAAC,YAAY,KAAG,EAAE,UAiEjF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,eAAO,MAAM,yBAAyB,cACzB,OAAO,SAAS,CAAC,YAAY,KACvC,EAAE,UAiEJ,CAAC"}
|