@strapi/utils 5.0.0-beta.0 → 5.0.0-beta.10
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/async.d.ts +5 -11
- package/dist/async.d.ts.map +1 -1
- package/dist/content-types.d.ts +16 -6
- package/dist/content-types.d.ts.map +1 -1
- package/dist/convert-query-params.d.ts +12 -9
- package/dist/convert-query-params.d.ts.map +1 -1
- package/dist/file.d.ts +9 -4
- package/dist/file.d.ts.map +1 -1
- package/dist/hooks.d.ts.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1507 -1354
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1499 -1346
- package/dist/index.mjs.map +1 -1
- package/dist/pagination.d.ts +34 -4
- package/dist/pagination.d.ts.map +1 -1
- package/dist/parse-type.d.ts.map +1 -1
- package/dist/policy.d.ts +1 -27
- package/dist/policy.d.ts.map +1 -1
- package/dist/sanitize/index.d.ts +23 -14
- package/dist/sanitize/index.d.ts.map +1 -1
- package/dist/sanitize/sanitizers.d.ts +10 -6
- package/dist/sanitize/sanitizers.d.ts.map +1 -1
- package/dist/set-creator-fields.d.ts.map +1 -1
- package/dist/traverse/factory.d.ts +5 -4
- package/dist/traverse/factory.d.ts.map +1 -1
- package/dist/traverse/index.d.ts +0 -1
- package/dist/traverse/index.d.ts.map +1 -1
- package/dist/traverse/query-populate.d.ts.map +1 -1
- package/dist/traverse-entity.d.ts +12 -2
- package/dist/traverse-entity.d.ts.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/validate/index.d.ts +21 -13
- package/dist/validate/index.d.ts.map +1 -1
- package/dist/validate/utils.d.ts +2 -2
- package/dist/validate/utils.d.ts.map +1 -1
- package/dist/validate/validators.d.ts +9 -5
- package/dist/validate/validators.d.ts.map +1 -1
- package/dist/validate/visitors/index.d.ts +1 -0
- package/dist/validate/visitors/index.d.ts.map +1 -1
- package/dist/validate/visitors/throw-unrecognized-fields.d.ts +4 -0
- package/dist/validate/visitors/throw-unrecognized-fields.d.ts.map +1 -0
- package/dist/validators.d.ts +2 -2
- package/dist/validators.d.ts.map +1 -1
- package/dist/zod.d.ts +3 -0
- package/dist/zod.d.ts.map +1 -0
- package/package.json +11 -9
package/dist/index.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const _
|
|
3
|
+
const _ = require("lodash");
|
|
4
|
+
const dates$1 = require("date-fns");
|
|
4
5
|
const fp = require("lodash/fp");
|
|
5
|
-
const pMap = require("p-map");
|
|
6
|
-
const httpErrors = require("http-errors");
|
|
7
6
|
const crypto = require("crypto");
|
|
8
7
|
const nodeMachineId = require("node-machine-id");
|
|
9
8
|
const yup$1 = require("yup");
|
|
9
|
+
const httpErrors = require("http-errors");
|
|
10
|
+
const pMap = require("p-map");
|
|
10
11
|
const execa = require("execa");
|
|
11
12
|
const preferredPM = require("preferred-pm");
|
|
12
13
|
const node_stream = require("node:stream");
|
|
13
14
|
const slugify = require("@sindresorhus/slugify");
|
|
15
|
+
const zod = require("zod");
|
|
14
16
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
15
17
|
function _interopNamespace(e) {
|
|
16
18
|
if (e && e.__esModule)
|
|
@@ -49,21 +51,20 @@ function _mergeNamespaces(n, m) {
|
|
|
49
51
|
}
|
|
50
52
|
return Object.freeze(Object.defineProperty(n, Symbol.toStringTag, { value: "Module" }));
|
|
51
53
|
}
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
+
const ___namespace = /* @__PURE__ */ _interopNamespace(_);
|
|
55
|
+
const dates__namespace = /* @__PURE__ */ _interopNamespace(dates$1);
|
|
54
56
|
const yup__namespace = /* @__PURE__ */ _interopNamespace(yup$1);
|
|
57
|
+
const pMap__default = /* @__PURE__ */ _interopDefault(pMap);
|
|
55
58
|
const execa__default = /* @__PURE__ */ _interopDefault(execa);
|
|
56
59
|
const preferredPM__default = /* @__PURE__ */ _interopDefault(preferredPM);
|
|
57
60
|
const slugify__default = /* @__PURE__ */ _interopDefault(slugify);
|
|
58
|
-
const _ = require("lodash");
|
|
59
|
-
const dates$1 = require("date-fns");
|
|
60
61
|
const timeRegex = /^(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]{1,3})?$/;
|
|
61
62
|
const isDate = (v) => {
|
|
62
|
-
return
|
|
63
|
+
return dates__namespace.isDate(v);
|
|
63
64
|
};
|
|
64
65
|
const parseTime = (value) => {
|
|
65
66
|
if (isDate(value)) {
|
|
66
|
-
return
|
|
67
|
+
return dates__namespace.format(value, "HH:mm:ss.SSS");
|
|
67
68
|
}
|
|
68
69
|
if (typeof value !== "string") {
|
|
69
70
|
throw new Error(`Expected a string, got a ${typeof value}`);
|
|
@@ -73,20 +74,20 @@ const parseTime = (value) => {
|
|
|
73
74
|
throw new Error("Invalid time format, expected HH:mm:ss.SSS");
|
|
74
75
|
}
|
|
75
76
|
const [, hours, minutes, seconds, fraction = ".000"] = result;
|
|
76
|
-
const fractionPart =
|
|
77
|
+
const fractionPart = ___namespace.padEnd(fraction.slice(1), 3, "0");
|
|
77
78
|
return `${hours}:${minutes}:${seconds}.${fractionPart}`;
|
|
78
79
|
};
|
|
79
80
|
const parseDate = (value) => {
|
|
80
81
|
if (isDate(value)) {
|
|
81
|
-
return
|
|
82
|
+
return dates__namespace.format(value, "yyyy-MM-dd");
|
|
82
83
|
}
|
|
83
84
|
if (typeof value !== "string") {
|
|
84
85
|
throw new Error(`Expected a string, got a ${typeof value}`);
|
|
85
86
|
}
|
|
86
87
|
try {
|
|
87
|
-
const date =
|
|
88
|
-
if (
|
|
89
|
-
return
|
|
88
|
+
const date = dates__namespace.parseISO(value);
|
|
89
|
+
if (dates__namespace.isValid(date))
|
|
90
|
+
return dates__namespace.format(date, "yyyy-MM-dd");
|
|
90
91
|
throw new Error(`Invalid format, expected an ISO compatible date`);
|
|
91
92
|
} catch (error) {
|
|
92
93
|
throw new Error(`Invalid format, expected an ISO compatible date`);
|
|
@@ -100,11 +101,11 @@ const parseDateTimeOrTimestamp = (value) => {
|
|
|
100
101
|
throw new Error(`Expected a string, got a ${typeof value}`);
|
|
101
102
|
}
|
|
102
103
|
try {
|
|
103
|
-
const date =
|
|
104
|
-
if (
|
|
104
|
+
const date = dates__namespace.parseISO(value);
|
|
105
|
+
if (dates__namespace.isValid(date))
|
|
105
106
|
return date;
|
|
106
|
-
const milliUnixDate =
|
|
107
|
-
if (
|
|
107
|
+
const milliUnixDate = dates__namespace.parse(value, "T", /* @__PURE__ */ new Date());
|
|
108
|
+
if (dates__namespace.isValid(milliUnixDate))
|
|
108
109
|
return milliUnixDate;
|
|
109
110
|
throw new Error(`Invalid format, expected a timestamp or an ISO date`);
|
|
110
111
|
} catch (error) {
|
|
@@ -138,7 +139,7 @@ const parseType = (options) => {
|
|
|
138
139
|
case "biginteger":
|
|
139
140
|
case "float":
|
|
140
141
|
case "decimal": {
|
|
141
|
-
return
|
|
142
|
+
return ___namespace.toNumber(value);
|
|
142
143
|
}
|
|
143
144
|
case "time": {
|
|
144
145
|
return parseTime(value);
|
|
@@ -155,32 +156,32 @@ const parseType = (options) => {
|
|
|
155
156
|
}
|
|
156
157
|
};
|
|
157
158
|
function envFn(key, defaultValue) {
|
|
158
|
-
return
|
|
159
|
+
return ___namespace.default.has(process.env, key) ? process.env[key] : defaultValue;
|
|
159
160
|
}
|
|
160
161
|
function getKey(key) {
|
|
161
162
|
return process.env[key] ?? "";
|
|
162
163
|
}
|
|
163
164
|
const utils = {
|
|
164
165
|
int(key, defaultValue) {
|
|
165
|
-
if (!
|
|
166
|
+
if (!___namespace.default.has(process.env, key)) {
|
|
166
167
|
return defaultValue;
|
|
167
168
|
}
|
|
168
169
|
return parseInt(getKey(key), 10);
|
|
169
170
|
},
|
|
170
171
|
float(key, defaultValue) {
|
|
171
|
-
if (!
|
|
172
|
+
if (!___namespace.default.has(process.env, key)) {
|
|
172
173
|
return defaultValue;
|
|
173
174
|
}
|
|
174
175
|
return parseFloat(getKey(key));
|
|
175
176
|
},
|
|
176
177
|
bool(key, defaultValue) {
|
|
177
|
-
if (!
|
|
178
|
+
if (!___namespace.default.has(process.env, key)) {
|
|
178
179
|
return defaultValue;
|
|
179
180
|
}
|
|
180
181
|
return getKey(key) === "true";
|
|
181
182
|
},
|
|
182
183
|
json(key, defaultValue) {
|
|
183
|
-
if (!
|
|
184
|
+
if (!___namespace.default.has(process.env, key)) {
|
|
184
185
|
return defaultValue;
|
|
185
186
|
}
|
|
186
187
|
try {
|
|
@@ -193,7 +194,7 @@ const utils = {
|
|
|
193
194
|
}
|
|
194
195
|
},
|
|
195
196
|
array(key, defaultValue) {
|
|
196
|
-
if (!
|
|
197
|
+
if (!___namespace.default.has(process.env, key)) {
|
|
197
198
|
return defaultValue;
|
|
198
199
|
}
|
|
199
200
|
let value = getKey(key);
|
|
@@ -201,11 +202,11 @@ const utils = {
|
|
|
201
202
|
value = value.substring(1, value.length - 1);
|
|
202
203
|
}
|
|
203
204
|
return value.split(",").map((v) => {
|
|
204
|
-
return
|
|
205
|
+
return ___namespace.default.trim(___namespace.default.trim(v, " "), '"');
|
|
205
206
|
});
|
|
206
207
|
},
|
|
207
208
|
date(key, defaultValue) {
|
|
208
|
-
if (!
|
|
209
|
+
if (!___namespace.default.has(process.env, key)) {
|
|
209
210
|
return defaultValue;
|
|
210
211
|
}
|
|
211
212
|
return new Date(getKey(key));
|
|
@@ -272,12 +273,12 @@ const getCreatorFields = (model) => {
|
|
|
272
273
|
const getNonWritableAttributes = (model) => {
|
|
273
274
|
if (!model)
|
|
274
275
|
return [];
|
|
275
|
-
const nonWritableAttributes =
|
|
276
|
+
const nonWritableAttributes = ___namespace.default.reduce(
|
|
276
277
|
model.attributes,
|
|
277
278
|
(acc, attr, attrName) => attr.writable === false ? acc.concat(attrName) : acc,
|
|
278
279
|
[]
|
|
279
280
|
);
|
|
280
|
-
return
|
|
281
|
+
return ___namespace.default.uniq([
|
|
281
282
|
ID_ATTRIBUTE$4,
|
|
282
283
|
DOC_ID_ATTRIBUTE$4,
|
|
283
284
|
...getTimestamps(model),
|
|
@@ -287,28 +288,37 @@ const getNonWritableAttributes = (model) => {
|
|
|
287
288
|
const getWritableAttributes = (model) => {
|
|
288
289
|
if (!model)
|
|
289
290
|
return [];
|
|
290
|
-
return
|
|
291
|
+
return ___namespace.default.difference(Object.keys(model.attributes), getNonWritableAttributes(model));
|
|
291
292
|
};
|
|
292
293
|
const isWritableAttribute = (model, attributeName) => {
|
|
293
294
|
return getWritableAttributes(model).includes(attributeName);
|
|
294
295
|
};
|
|
295
296
|
const getNonVisibleAttributes = (model) => {
|
|
296
|
-
const nonVisibleAttributes =
|
|
297
|
+
const nonVisibleAttributes = ___namespace.default.reduce(
|
|
297
298
|
model.attributes,
|
|
298
299
|
(acc, attr, attrName) => attr.visible === false ? acc.concat(attrName) : acc,
|
|
299
300
|
[]
|
|
300
301
|
);
|
|
301
|
-
return
|
|
302
|
+
return ___namespace.default.uniq([ID_ATTRIBUTE$4, DOC_ID_ATTRIBUTE$4, ...getTimestamps(model), ...nonVisibleAttributes]);
|
|
302
303
|
};
|
|
303
304
|
const getVisibleAttributes = (model) => {
|
|
304
|
-
return
|
|
305
|
+
return ___namespace.default.difference(___namespace.default.keys(model.attributes), getNonVisibleAttributes(model));
|
|
305
306
|
};
|
|
306
307
|
const isVisibleAttribute = (model, attributeName) => {
|
|
307
308
|
return getVisibleAttributes(model).includes(attributeName);
|
|
308
309
|
};
|
|
309
|
-
const getOptions = (model) =>
|
|
310
|
-
const hasDraftAndPublish = (model) =>
|
|
311
|
-
const isDraft = (data, model) => hasDraftAndPublish(model) &&
|
|
310
|
+
const getOptions = (model) => ___namespace.default.assign({ draftAndPublish: false }, ___namespace.default.get(model, "options", {}));
|
|
311
|
+
const hasDraftAndPublish = (model) => ___namespace.default.get(model, "options.draftAndPublish", false) === true;
|
|
312
|
+
const isDraft = (data, model) => hasDraftAndPublish(model) && ___namespace.default.get(data, PUBLISHED_AT_ATTRIBUTE$1) === null;
|
|
313
|
+
const isSchema = (data) => {
|
|
314
|
+
return typeof data === "object" && data !== null && "modelType" in data && typeof data.modelType === "string" && ["component", "contentType"].includes(data.modelType);
|
|
315
|
+
};
|
|
316
|
+
const isComponentSchema = (data) => {
|
|
317
|
+
return isSchema(data) && data.modelType === "component";
|
|
318
|
+
};
|
|
319
|
+
const isContentTypeSchema = (data) => {
|
|
320
|
+
return isSchema(data) && data.modelType === "contentType";
|
|
321
|
+
};
|
|
312
322
|
const isSingleType = ({ kind = COLLECTION_TYPE }) => kind === SINGLE_TYPE;
|
|
313
323
|
const isCollectionType = ({ kind = COLLECTION_TYPE }) => kind === COLLECTION_TYPE;
|
|
314
324
|
const isKind = (kind) => (model) => model.kind === kind;
|
|
@@ -317,9 +327,9 @@ const getStoredPrivateAttributes = (model) => fp.union(
|
|
|
317
327
|
fp.getOr([], "options.privateAttributes", model)
|
|
318
328
|
);
|
|
319
329
|
const getPrivateAttributes = (model) => {
|
|
320
|
-
return
|
|
330
|
+
return ___namespace.default.union(
|
|
321
331
|
getStoredPrivateAttributes(model),
|
|
322
|
-
|
|
332
|
+
___namespace.default.keys(___namespace.default.pickBy(model.attributes, (attr) => !!attr.private))
|
|
323
333
|
);
|
|
324
334
|
};
|
|
325
335
|
const isPrivateAttribute = (model, attributeName) => {
|
|
@@ -329,17 +339,22 @@ const isPrivateAttribute = (model, attributeName) => {
|
|
|
329
339
|
return getStoredPrivateAttributes(model).includes(attributeName);
|
|
330
340
|
};
|
|
331
341
|
const isScalarAttribute = (attribute) => {
|
|
332
|
-
return !["media", "component", "relation", "dynamiczone"].includes(attribute
|
|
342
|
+
return attribute && !["media", "component", "relation", "dynamiczone"].includes(attribute.type);
|
|
343
|
+
};
|
|
344
|
+
const getDoesAttributeRequireValidation = (attribute) => {
|
|
345
|
+
return attribute.required || attribute.unique || Object.prototype.hasOwnProperty.call(attribute, "max") || Object.prototype.hasOwnProperty.call(attribute, "min") || Object.prototype.hasOwnProperty.call(attribute, "maxLength") || Object.prototype.hasOwnProperty.call(attribute, "minLength");
|
|
333
346
|
};
|
|
334
347
|
const isMediaAttribute = (attribute) => attribute?.type === "media";
|
|
335
348
|
const isRelationalAttribute = (attribute) => attribute?.type === "relation";
|
|
349
|
+
const HAS_RELATION_REORDERING = ["manyToMany", "manyToOne", "oneToMany"];
|
|
350
|
+
const hasRelationReordering = (attribute) => isRelationalAttribute(attribute) && HAS_RELATION_REORDERING.includes(attribute.relation);
|
|
336
351
|
const isComponentAttribute = (attribute) => ["component", "dynamiczone"].includes(attribute?.type);
|
|
337
|
-
const isDynamicZoneAttribute = (attribute) => attribute
|
|
352
|
+
const isDynamicZoneAttribute = (attribute) => !!attribute && attribute.type === "dynamiczone";
|
|
338
353
|
const isMorphToRelationalAttribute = (attribute) => {
|
|
339
|
-
return isRelationalAttribute(attribute) && attribute
|
|
354
|
+
return !!attribute && isRelationalAttribute(attribute) && attribute.relation?.startsWith?.("morphTo");
|
|
340
355
|
};
|
|
341
356
|
const getComponentAttributes = (schema) => {
|
|
342
|
-
return
|
|
357
|
+
return ___namespace.default.reduce(
|
|
343
358
|
schema.attributes,
|
|
344
359
|
(acc, attr, attrName) => {
|
|
345
360
|
if (isComponentAttribute(attr))
|
|
@@ -350,7 +365,7 @@ const getComponentAttributes = (schema) => {
|
|
|
350
365
|
);
|
|
351
366
|
};
|
|
352
367
|
const getScalarAttributes = (schema) => {
|
|
353
|
-
return
|
|
368
|
+
return ___namespace.default.reduce(
|
|
354
369
|
schema.attributes,
|
|
355
370
|
(acc, attr, attrName) => {
|
|
356
371
|
if (isScalarAttribute(attr))
|
|
@@ -360,11 +375,22 @@ const getScalarAttributes = (schema) => {
|
|
|
360
375
|
[]
|
|
361
376
|
);
|
|
362
377
|
};
|
|
378
|
+
const getRelationalAttributes = (schema) => {
|
|
379
|
+
return ___namespace.default.reduce(
|
|
380
|
+
schema.attributes,
|
|
381
|
+
(acc, attr, attrName) => {
|
|
382
|
+
if (isRelationalAttribute(attr))
|
|
383
|
+
acc.push(attrName);
|
|
384
|
+
return acc;
|
|
385
|
+
},
|
|
386
|
+
[]
|
|
387
|
+
);
|
|
388
|
+
};
|
|
363
389
|
const isTypedAttribute = (attribute, type) => {
|
|
364
|
-
return
|
|
390
|
+
return ___namespace.default.has(attribute, "type") && attribute.type === type;
|
|
365
391
|
};
|
|
366
392
|
const getContentTypeRoutePrefix = (contentType) => {
|
|
367
|
-
return isSingleType(contentType) ?
|
|
393
|
+
return isSingleType(contentType) ? ___namespace.default.kebabCase(contentType.info.singularName) : ___namespace.default.kebabCase(contentType.info.pluralName);
|
|
368
394
|
};
|
|
369
395
|
const contentTypes = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
370
396
|
__proto__: null,
|
|
@@ -372,17 +398,22 @@ const contentTypes = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.define
|
|
|
372
398
|
getComponentAttributes,
|
|
373
399
|
getContentTypeRoutePrefix,
|
|
374
400
|
getCreatorFields,
|
|
401
|
+
getDoesAttributeRequireValidation,
|
|
375
402
|
getNonVisibleAttributes,
|
|
376
403
|
getNonWritableAttributes,
|
|
377
404
|
getOptions,
|
|
378
405
|
getPrivateAttributes,
|
|
406
|
+
getRelationalAttributes,
|
|
379
407
|
getScalarAttributes,
|
|
380
408
|
getTimestamps,
|
|
381
409
|
getVisibleAttributes,
|
|
382
410
|
getWritableAttributes,
|
|
383
411
|
hasDraftAndPublish,
|
|
412
|
+
hasRelationReordering,
|
|
384
413
|
isCollectionType,
|
|
385
414
|
isComponentAttribute,
|
|
415
|
+
isComponentSchema,
|
|
416
|
+
isContentTypeSchema,
|
|
386
417
|
isDraft,
|
|
387
418
|
isDynamicZoneAttribute,
|
|
388
419
|
isKind,
|
|
@@ -391,6 +422,7 @@ const contentTypes = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.define
|
|
|
391
422
|
isPrivateAttribute,
|
|
392
423
|
isRelationalAttribute,
|
|
393
424
|
isScalarAttribute,
|
|
425
|
+
isSchema,
|
|
394
426
|
isSingleType,
|
|
395
427
|
isTypedAttribute,
|
|
396
428
|
isVisibleAttribute,
|
|
@@ -543,201 +575,33 @@ const providerFactory = (options = {}) => {
|
|
|
543
575
|
}
|
|
544
576
|
};
|
|
545
577
|
};
|
|
546
|
-
|
|
547
|
-
const
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
return res;
|
|
578
|
+
const traverseEntity = async (visitor2, options, entity) => {
|
|
579
|
+
const { path = { raw: null, attribute: null }, schema, getModel } = options;
|
|
580
|
+
let parent = options.parent;
|
|
581
|
+
const traverseMorphRelationTarget = async (visitor22, path2, entry) => {
|
|
582
|
+
const targetSchema = getModel(entry.__type);
|
|
583
|
+
const traverseOptions = { schema: targetSchema, path: path2, getModel, parent };
|
|
584
|
+
return traverseEntity(visitor22, traverseOptions, entry);
|
|
554
585
|
};
|
|
555
|
-
|
|
556
|
-
const
|
|
557
|
-
|
|
558
|
-
let acc = initialValue;
|
|
559
|
-
for (let i = 0; i < mixedArray.length; i += 1) {
|
|
560
|
-
acc = await iteratee(acc, await mixedArray[i], i);
|
|
561
|
-
}
|
|
562
|
-
return acc;
|
|
563
|
-
};
|
|
564
|
-
const async = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
565
|
-
__proto__: null,
|
|
566
|
-
map,
|
|
567
|
-
pipe,
|
|
568
|
-
reduce
|
|
569
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
570
|
-
const visitor$8 = ({ key, attribute }, { remove }) => {
|
|
571
|
-
if (attribute?.type === "password") {
|
|
572
|
-
remove(key);
|
|
573
|
-
}
|
|
574
|
-
};
|
|
575
|
-
const visitor$7 = ({ schema, key, attribute }, { remove }) => {
|
|
576
|
-
if (!attribute) {
|
|
577
|
-
return;
|
|
578
|
-
}
|
|
579
|
-
const isPrivate = attribute.private === true || isPrivateAttribute(schema, key);
|
|
580
|
-
if (isPrivate) {
|
|
581
|
-
remove(key);
|
|
582
|
-
}
|
|
583
|
-
};
|
|
584
|
-
const ACTIONS_TO_VERIFY$1 = ["find"];
|
|
585
|
-
const { CREATED_BY_ATTRIBUTE: CREATED_BY_ATTRIBUTE$1, UPDATED_BY_ATTRIBUTE: UPDATED_BY_ATTRIBUTE$1 } = constants$1;
|
|
586
|
-
const removeRestrictedRelations = (auth) => async ({ data, key, attribute, schema }, { remove, set }) => {
|
|
587
|
-
if (!attribute) {
|
|
588
|
-
return;
|
|
589
|
-
}
|
|
590
|
-
const isRelation = attribute.type === "relation";
|
|
591
|
-
if (!isRelation) {
|
|
592
|
-
return;
|
|
593
|
-
}
|
|
594
|
-
const handleMorphRelation = async () => {
|
|
595
|
-
const newMorphValue = [];
|
|
596
|
-
for (const element of data[key]) {
|
|
597
|
-
const scopes = ACTIONS_TO_VERIFY$1.map((action) => `${element.__type}.${action}`);
|
|
598
|
-
const isAllowed = await hasAccessToSomeScopes$1(scopes, auth);
|
|
599
|
-
if (isAllowed) {
|
|
600
|
-
newMorphValue.push(element);
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
if (newMorphValue.length === 0) {
|
|
604
|
-
remove(key);
|
|
605
|
-
} else {
|
|
606
|
-
set(key, newMorphValue);
|
|
607
|
-
}
|
|
586
|
+
const traverseRelationTarget = (schema2) => async (visitor22, path2, entry) => {
|
|
587
|
+
const traverseOptions = { schema: schema2, path: path2, getModel, parent };
|
|
588
|
+
return traverseEntity(visitor22, traverseOptions, entry);
|
|
608
589
|
};
|
|
609
|
-
const
|
|
610
|
-
const
|
|
611
|
-
const
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
590
|
+
const traverseMediaTarget = async (visitor22, path2, entry) => {
|
|
591
|
+
const targetSchemaUID = "plugin::upload.file";
|
|
592
|
+
const targetSchema = getModel(targetSchemaUID);
|
|
593
|
+
const traverseOptions = { schema: targetSchema, path: path2, getModel, parent };
|
|
594
|
+
return traverseEntity(visitor22, traverseOptions, entry);
|
|
595
|
+
};
|
|
596
|
+
const traverseComponent = async (visitor22, path2, schema2, entry) => {
|
|
597
|
+
const traverseOptions = { schema: schema2, path: path2, getModel, parent };
|
|
598
|
+
return traverseEntity(visitor22, traverseOptions, entry);
|
|
599
|
+
};
|
|
600
|
+
const visitDynamicZoneEntry = async (visitor22, path2, entry) => {
|
|
601
|
+
const targetSchema = getModel(entry.__component);
|
|
602
|
+
const traverseOptions = { schema: targetSchema, path: path2, getModel, parent };
|
|
603
|
+
return traverseEntity(visitor22, traverseOptions, entry);
|
|
615
604
|
};
|
|
616
|
-
const isCreatorRelation = [CREATED_BY_ATTRIBUTE$1, UPDATED_BY_ATTRIBUTE$1].includes(key);
|
|
617
|
-
if (isMorphToRelationalAttribute(attribute)) {
|
|
618
|
-
await handleMorphRelation();
|
|
619
|
-
return;
|
|
620
|
-
}
|
|
621
|
-
if (isCreatorRelation && schema.options?.populateCreatorFields) {
|
|
622
|
-
return;
|
|
623
|
-
}
|
|
624
|
-
await handleRegularRelation();
|
|
625
|
-
};
|
|
626
|
-
const hasAccessToSomeScopes$1 = async (scopes, auth) => {
|
|
627
|
-
for (const scope of scopes) {
|
|
628
|
-
try {
|
|
629
|
-
await strapi.auth.verify(auth, { scope });
|
|
630
|
-
return true;
|
|
631
|
-
} catch {
|
|
632
|
-
continue;
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
return false;
|
|
636
|
-
};
|
|
637
|
-
const visitor$6 = ({ key, attribute }, { remove }) => {
|
|
638
|
-
if (isMorphToRelationalAttribute(attribute)) {
|
|
639
|
-
remove(key);
|
|
640
|
-
}
|
|
641
|
-
};
|
|
642
|
-
const visitor$5 = ({ key, attribute }, { remove }) => {
|
|
643
|
-
if (isDynamicZoneAttribute(attribute)) {
|
|
644
|
-
remove(key);
|
|
645
|
-
}
|
|
646
|
-
};
|
|
647
|
-
const removeDisallowedFields = (allowedFields = null) => ({ key, path: { attribute: path } }, { remove }) => {
|
|
648
|
-
if (allowedFields === null) {
|
|
649
|
-
return;
|
|
650
|
-
}
|
|
651
|
-
if (!(fp.isArray(allowedFields) && allowedFields.every(fp.isString))) {
|
|
652
|
-
throw new TypeError(
|
|
653
|
-
`Expected array of strings for allowedFields but got "${typeof allowedFields}"`
|
|
654
|
-
);
|
|
655
|
-
}
|
|
656
|
-
if (fp.isNil(path)) {
|
|
657
|
-
return;
|
|
658
|
-
}
|
|
659
|
-
const containedPaths = getContainedPaths$1(path);
|
|
660
|
-
const isPathAllowed = allowedFields.some(
|
|
661
|
-
(p) => containedPaths.includes(p) || p.startsWith(`${path}.`)
|
|
662
|
-
);
|
|
663
|
-
if (isPathAllowed) {
|
|
664
|
-
return;
|
|
665
|
-
}
|
|
666
|
-
remove(key);
|
|
667
|
-
};
|
|
668
|
-
const getContainedPaths$1 = (path) => {
|
|
669
|
-
const parts = fp.toPath(path);
|
|
670
|
-
return parts.reduce((acc, value, index2, list) => {
|
|
671
|
-
return [...acc, list.slice(0, index2 + 1).join(".")];
|
|
672
|
-
}, []);
|
|
673
|
-
};
|
|
674
|
-
const removeRestrictedFields = (restrictedFields = null) => ({ key, path: { attribute: path } }, { remove }) => {
|
|
675
|
-
if (restrictedFields === null) {
|
|
676
|
-
remove(key);
|
|
677
|
-
return;
|
|
678
|
-
}
|
|
679
|
-
if (!(fp.isArray(restrictedFields) && restrictedFields.every(fp.isString))) {
|
|
680
|
-
throw new TypeError(
|
|
681
|
-
`Expected array of strings for restrictedFields but got "${typeof restrictedFields}"`
|
|
682
|
-
);
|
|
683
|
-
}
|
|
684
|
-
if (restrictedFields.includes(path)) {
|
|
685
|
-
remove(key);
|
|
686
|
-
return;
|
|
687
|
-
}
|
|
688
|
-
const isRestrictedNested = restrictedFields.some(
|
|
689
|
-
(allowedPath) => path?.toString().startsWith(`${allowedPath}.`)
|
|
690
|
-
);
|
|
691
|
-
if (isRestrictedNested) {
|
|
692
|
-
remove(key);
|
|
693
|
-
}
|
|
694
|
-
};
|
|
695
|
-
const visitor$4 = ({ schema, key, value }, { set }) => {
|
|
696
|
-
if (key === "" && value === "*") {
|
|
697
|
-
const { attributes } = schema;
|
|
698
|
-
const newPopulateQuery = Object.entries(attributes).filter(
|
|
699
|
-
([, attribute]) => ["relation", "component", "media", "dynamiczone"].includes(attribute.type)
|
|
700
|
-
).reduce((acc, [key2]) => ({ ...acc, [key2]: true }), {});
|
|
701
|
-
set("", newPopulateQuery);
|
|
702
|
-
}
|
|
703
|
-
};
|
|
704
|
-
const visitors$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
705
|
-
__proto__: null,
|
|
706
|
-
expandWildcardPopulate: visitor$4,
|
|
707
|
-
removeDisallowedFields,
|
|
708
|
-
removeDynamicZones: visitor$5,
|
|
709
|
-
removeMorphToRelations: visitor$6,
|
|
710
|
-
removePassword: visitor$8,
|
|
711
|
-
removePrivate: visitor$7,
|
|
712
|
-
removeRestrictedFields,
|
|
713
|
-
removeRestrictedRelations
|
|
714
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
715
|
-
const traverseMorphRelationTarget = async (visitor2, path, entry) => {
|
|
716
|
-
const targetSchema = strapi.getModel(entry.__type);
|
|
717
|
-
const traverseOptions = { schema: targetSchema, path };
|
|
718
|
-
return traverseEntity(visitor2, traverseOptions, entry);
|
|
719
|
-
};
|
|
720
|
-
const traverseRelationTarget = (schema) => async (visitor2, path, entry) => {
|
|
721
|
-
const traverseOptions = { schema, path };
|
|
722
|
-
return traverseEntity(visitor2, traverseOptions, entry);
|
|
723
|
-
};
|
|
724
|
-
const traverseMediaTarget = async (visitor2, path, entry) => {
|
|
725
|
-
const targetSchemaUID = "plugin::upload.file";
|
|
726
|
-
const targetSchema = strapi.getModel(targetSchemaUID);
|
|
727
|
-
const traverseOptions = { schema: targetSchema, path };
|
|
728
|
-
return traverseEntity(visitor2, traverseOptions, entry);
|
|
729
|
-
};
|
|
730
|
-
const traverseComponent = async (visitor2, path, schema, entry) => {
|
|
731
|
-
const traverseOptions = { schema, path };
|
|
732
|
-
return traverseEntity(visitor2, traverseOptions, entry);
|
|
733
|
-
};
|
|
734
|
-
const visitDynamicZoneEntry = async (visitor2, path, entry) => {
|
|
735
|
-
const targetSchema = strapi.getModel(entry.__component);
|
|
736
|
-
const traverseOptions = { schema: targetSchema, path };
|
|
737
|
-
return traverseEntity(visitor2, traverseOptions, entry);
|
|
738
|
-
};
|
|
739
|
-
const traverseEntity = async (visitor2, options, entity) => {
|
|
740
|
-
const { path = { raw: null, attribute: null }, schema } = options;
|
|
741
605
|
if (!fp.isObject(entity) || fp.isNil(schema)) {
|
|
742
606
|
return entity;
|
|
743
607
|
}
|
|
@@ -747,9 +611,6 @@ const traverseEntity = async (visitor2, options, entity) => {
|
|
|
747
611
|
for (let i = 0; i < keys.length; i += 1) {
|
|
748
612
|
const key = keys[i];
|
|
749
613
|
const attribute = schema.attributes[key];
|
|
750
|
-
if (fp.isNil(attribute)) {
|
|
751
|
-
continue;
|
|
752
|
-
}
|
|
753
614
|
const newPath = { ...path };
|
|
754
615
|
newPath.raw = fp.isNil(path.raw) ? key : `${path.raw}.${key}`;
|
|
755
616
|
if (!fp.isNil(attribute)) {
|
|
@@ -761,16 +622,19 @@ const traverseEntity = async (visitor2, options, entity) => {
|
|
|
761
622
|
key,
|
|
762
623
|
value: copy[key],
|
|
763
624
|
attribute,
|
|
764
|
-
path: newPath
|
|
625
|
+
path: newPath,
|
|
626
|
+
getModel,
|
|
627
|
+
parent
|
|
765
628
|
};
|
|
766
629
|
await visitor2(visitorOptions, visitorUtils);
|
|
767
630
|
const value = copy[key];
|
|
768
|
-
if (fp.isNil(value)) {
|
|
631
|
+
if (fp.isNil(value) || fp.isNil(attribute)) {
|
|
769
632
|
continue;
|
|
770
633
|
}
|
|
634
|
+
parent = { schema, key, attribute, path: newPath };
|
|
771
635
|
if (isRelationalAttribute(attribute)) {
|
|
772
636
|
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
|
773
|
-
const method = isMorphRelation ? traverseMorphRelationTarget : traverseRelationTarget(
|
|
637
|
+
const method = isMorphRelation ? traverseMorphRelationTarget : traverseRelationTarget(getModel(attribute.target));
|
|
774
638
|
if (fp.isArray(value)) {
|
|
775
639
|
const res = new Array(value.length);
|
|
776
640
|
for (let i2 = 0; i2 < value.length; i2 += 1) {
|
|
@@ -795,7 +659,7 @@ const traverseEntity = async (visitor2, options, entity) => {
|
|
|
795
659
|
continue;
|
|
796
660
|
}
|
|
797
661
|
if (attribute.type === "component") {
|
|
798
|
-
const targetSchema =
|
|
662
|
+
const targetSchema = getModel(attribute.component);
|
|
799
663
|
if (fp.isArray(value)) {
|
|
800
664
|
const res = new Array(value.length);
|
|
801
665
|
for (let i2 = 0; i2 < value.length; i2 += 1) {
|
|
@@ -827,68 +691,853 @@ const createVisitorUtils = ({ data }) => ({
|
|
|
827
691
|
}
|
|
828
692
|
});
|
|
829
693
|
const traverseEntity$1 = fp.curry(traverseEntity);
|
|
830
|
-
|
|
831
|
-
const
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
694
|
+
function importDefault(modName) {
|
|
695
|
+
const mod = require(modName);
|
|
696
|
+
return mod && mod.__esModule ? mod.default : mod;
|
|
697
|
+
}
|
|
698
|
+
const machineId = () => {
|
|
699
|
+
try {
|
|
700
|
+
const deviceId = nodeMachineId.machineIdSync();
|
|
701
|
+
return deviceId;
|
|
702
|
+
} catch (error) {
|
|
703
|
+
const deviceId = crypto.randomUUID();
|
|
704
|
+
return deviceId;
|
|
705
|
+
}
|
|
706
|
+
};
|
|
707
|
+
const formatYupInnerError = (yupError) => ({
|
|
708
|
+
path: fp.toPath(yupError.path),
|
|
709
|
+
message: yupError.message,
|
|
710
|
+
name: yupError.name
|
|
711
|
+
});
|
|
712
|
+
const formatYupErrors = (yupError) => ({
|
|
713
|
+
errors: fp.isEmpty(yupError.inner) ? [formatYupInnerError(yupError)] : yupError.inner.map(formatYupInnerError),
|
|
714
|
+
message: yupError.message
|
|
715
|
+
});
|
|
716
|
+
class ApplicationError extends Error {
|
|
717
|
+
name;
|
|
718
|
+
details;
|
|
719
|
+
message;
|
|
720
|
+
constructor(message = "An application error occured", details = {}) {
|
|
721
|
+
super();
|
|
722
|
+
this.name = "ApplicationError";
|
|
723
|
+
this.message = message;
|
|
724
|
+
this.details = details;
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
class ValidationError extends ApplicationError {
|
|
728
|
+
constructor(message, details) {
|
|
729
|
+
super(message, details);
|
|
730
|
+
this.name = "ValidationError";
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
class YupValidationError extends ValidationError {
|
|
734
|
+
constructor(yupError, message) {
|
|
735
|
+
super("Validation");
|
|
736
|
+
const { errors: errors2, message: yupMessage } = formatYupErrors(yupError);
|
|
737
|
+
this.message = message || yupMessage;
|
|
738
|
+
this.details = { errors: errors2 };
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
class PaginationError extends ApplicationError {
|
|
742
|
+
constructor(message = "Invalid pagination", details) {
|
|
743
|
+
super(message, details);
|
|
744
|
+
this.name = "PaginationError";
|
|
745
|
+
this.message = message;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
class NotFoundError extends ApplicationError {
|
|
749
|
+
constructor(message = "Entity not found", details) {
|
|
750
|
+
super(message, details);
|
|
751
|
+
this.name = "NotFoundError";
|
|
752
|
+
this.message = message;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
class ForbiddenError extends ApplicationError {
|
|
756
|
+
constructor(message = "Forbidden access", details) {
|
|
757
|
+
super(message, details);
|
|
758
|
+
this.name = "ForbiddenError";
|
|
759
|
+
this.message = message;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
class UnauthorizedError extends ApplicationError {
|
|
763
|
+
constructor(message = "Unauthorized", details) {
|
|
764
|
+
super(message, details);
|
|
765
|
+
this.name = "UnauthorizedError";
|
|
766
|
+
this.message = message;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
class RateLimitError extends ApplicationError {
|
|
770
|
+
constructor(message = "Too many requests, please try again later.", details) {
|
|
771
|
+
super(message, details);
|
|
772
|
+
this.name = "RateLimitError";
|
|
773
|
+
this.message = message;
|
|
774
|
+
this.details = details || {};
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
class PayloadTooLargeError extends ApplicationError {
|
|
778
|
+
constructor(message = "Entity too large", details) {
|
|
779
|
+
super(message, details);
|
|
780
|
+
this.name = "PayloadTooLargeError";
|
|
781
|
+
this.message = message;
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
class PolicyError extends ForbiddenError {
|
|
785
|
+
constructor(message = "Policy Failed", details) {
|
|
786
|
+
super(message, details);
|
|
787
|
+
this.name = "PolicyError";
|
|
788
|
+
this.message = message;
|
|
789
|
+
this.details = details || {};
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
class NotImplementedError extends ApplicationError {
|
|
793
|
+
constructor(message = "This feature is not implemented yet", details) {
|
|
794
|
+
super(message, details);
|
|
795
|
+
this.name = "NotImplementedError";
|
|
796
|
+
this.message = message;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
const errors = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
800
|
+
__proto__: null,
|
|
801
|
+
ApplicationError,
|
|
802
|
+
ForbiddenError,
|
|
803
|
+
HttpError: httpErrors.HttpError,
|
|
804
|
+
NotFoundError,
|
|
805
|
+
NotImplementedError,
|
|
806
|
+
PaginationError,
|
|
807
|
+
PayloadTooLargeError,
|
|
808
|
+
PolicyError,
|
|
809
|
+
RateLimitError,
|
|
810
|
+
UnauthorizedError,
|
|
811
|
+
ValidationError,
|
|
812
|
+
YupValidationError
|
|
813
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
814
|
+
const handleYupError = (error, errorMessage) => {
|
|
815
|
+
throw new YupValidationError(error, errorMessage);
|
|
816
|
+
};
|
|
817
|
+
const defaultValidationParam = { strict: true, abortEarly: false };
|
|
818
|
+
const validateYupSchema = (schema, options = {}) => async (body, errorMessage) => {
|
|
819
|
+
try {
|
|
820
|
+
const optionsWithDefaults = fp.defaults(defaultValidationParam, options);
|
|
821
|
+
const result = await schema.validate(body, optionsWithDefaults);
|
|
822
|
+
return result;
|
|
823
|
+
} catch (e) {
|
|
824
|
+
if (e instanceof yup__namespace.ValidationError) {
|
|
825
|
+
handleYupError(e, errorMessage);
|
|
826
|
+
}
|
|
827
|
+
throw e;
|
|
828
|
+
}
|
|
829
|
+
};
|
|
830
|
+
const validateYupSchemaSync = (schema, options = {}) => (body, errorMessage) => {
|
|
831
|
+
try {
|
|
832
|
+
const optionsWithDefaults = fp.defaults(defaultValidationParam, options);
|
|
833
|
+
return schema.validateSync(body, optionsWithDefaults);
|
|
834
|
+
} catch (e) {
|
|
835
|
+
if (e instanceof yup__namespace.ValidationError) {
|
|
836
|
+
handleYupError(e, errorMessage);
|
|
837
|
+
}
|
|
838
|
+
throw e;
|
|
839
|
+
}
|
|
840
|
+
};
|
|
841
|
+
const GROUP_OPERATORS = ["$and", "$or"];
|
|
842
|
+
const WHERE_OPERATORS = [
|
|
843
|
+
"$not",
|
|
844
|
+
"$in",
|
|
845
|
+
"$notIn",
|
|
846
|
+
"$eq",
|
|
847
|
+
"$eqi",
|
|
848
|
+
"$ne",
|
|
849
|
+
"$nei",
|
|
850
|
+
"$gt",
|
|
851
|
+
"$gte",
|
|
852
|
+
"$lt",
|
|
853
|
+
"$lte",
|
|
854
|
+
"$null",
|
|
855
|
+
"$notNull",
|
|
856
|
+
"$between",
|
|
857
|
+
"$startsWith",
|
|
858
|
+
"$endsWith",
|
|
859
|
+
"$startsWithi",
|
|
860
|
+
"$endsWithi",
|
|
861
|
+
"$contains",
|
|
862
|
+
"$notContains",
|
|
863
|
+
"$containsi",
|
|
864
|
+
"$notContainsi",
|
|
865
|
+
// Experimental, only for internal use
|
|
866
|
+
"$jsonSupersetOf"
|
|
867
|
+
];
|
|
868
|
+
const CAST_OPERATORS = [
|
|
869
|
+
"$not",
|
|
870
|
+
"$in",
|
|
871
|
+
"$notIn",
|
|
872
|
+
"$eq",
|
|
873
|
+
"$ne",
|
|
874
|
+
"$gt",
|
|
875
|
+
"$gte",
|
|
876
|
+
"$lt",
|
|
877
|
+
"$lte",
|
|
878
|
+
"$between"
|
|
879
|
+
];
|
|
880
|
+
const ARRAY_OPERATORS = ["$in", "$notIn", "$between"];
|
|
881
|
+
const OPERATORS = {
|
|
882
|
+
where: WHERE_OPERATORS,
|
|
883
|
+
cast: CAST_OPERATORS,
|
|
884
|
+
group: GROUP_OPERATORS,
|
|
885
|
+
array: ARRAY_OPERATORS
|
|
886
|
+
};
|
|
887
|
+
const OPERATORS_LOWERCASE = Object.fromEntries(
|
|
888
|
+
Object.entries(OPERATORS).map(([key, values]) => [
|
|
889
|
+
key,
|
|
890
|
+
values.map((value) => value.toLowerCase())
|
|
891
|
+
])
|
|
892
|
+
);
|
|
893
|
+
const isObjKey = (key, obj) => {
|
|
894
|
+
return key in obj;
|
|
895
|
+
};
|
|
896
|
+
const isOperatorOfType = (type, key, ignoreCase = false) => {
|
|
897
|
+
if (ignoreCase) {
|
|
898
|
+
return OPERATORS_LOWERCASE[type]?.includes(key.toLowerCase()) ?? false;
|
|
899
|
+
}
|
|
900
|
+
if (isObjKey(type, OPERATORS)) {
|
|
901
|
+
return OPERATORS[type]?.includes(key) ?? false;
|
|
902
|
+
}
|
|
903
|
+
return false;
|
|
904
|
+
};
|
|
905
|
+
const isOperator = (key, ignoreCase = false) => {
|
|
906
|
+
return Object.keys(OPERATORS).some((type) => isOperatorOfType(type, key, ignoreCase));
|
|
907
|
+
};
|
|
908
|
+
const { ID_ATTRIBUTE: ID_ATTRIBUTE$3, DOC_ID_ATTRIBUTE: DOC_ID_ATTRIBUTE$3, PUBLISHED_AT_ATTRIBUTE } = constants$1;
|
|
909
|
+
class InvalidOrderError extends Error {
|
|
910
|
+
constructor() {
|
|
911
|
+
super();
|
|
912
|
+
this.message = "Invalid order. order can only be one of asc|desc|ASC|DESC";
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
class InvalidSortError extends Error {
|
|
916
|
+
constructor() {
|
|
917
|
+
super();
|
|
918
|
+
this.message = "Invalid sort parameter. Expected a string, an array of strings, a sort object or an array of sort objects";
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
function validateOrder(order) {
|
|
922
|
+
if (!fp.isString(order) || !["asc", "desc"].includes(order.toLocaleLowerCase())) {
|
|
923
|
+
throw new InvalidOrderError();
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
const convertCountQueryParams = (countQuery) => {
|
|
927
|
+
return parseType({ type: "boolean", value: countQuery });
|
|
928
|
+
};
|
|
929
|
+
const convertOrderingQueryParams = (ordering) => {
|
|
930
|
+
return ordering;
|
|
931
|
+
};
|
|
932
|
+
const isPlainObject = (value) => ___namespace.default.isPlainObject(value);
|
|
933
|
+
const isStringArray$3 = (value) => fp.isArray(value) && value.every(fp.isString);
|
|
934
|
+
const createTransformer = ({ getModel }) => {
|
|
935
|
+
const convertSortQueryParams = (sortQuery) => {
|
|
936
|
+
if (typeof sortQuery === "string") {
|
|
937
|
+
return convertStringSortQueryParam(sortQuery);
|
|
938
|
+
}
|
|
939
|
+
if (isStringArray$3(sortQuery)) {
|
|
940
|
+
return sortQuery.flatMap((sortValue) => convertStringSortQueryParam(sortValue));
|
|
941
|
+
}
|
|
942
|
+
if (Array.isArray(sortQuery)) {
|
|
943
|
+
return sortQuery.map((sortValue) => convertNestedSortQueryParam(sortValue));
|
|
944
|
+
}
|
|
945
|
+
if (isPlainObject(sortQuery)) {
|
|
946
|
+
return convertNestedSortQueryParam(sortQuery);
|
|
947
|
+
}
|
|
948
|
+
throw new InvalidSortError();
|
|
949
|
+
};
|
|
950
|
+
const convertStringSortQueryParam = (sortQuery) => {
|
|
951
|
+
return sortQuery.split(",").map((value) => convertSingleSortQueryParam(value));
|
|
952
|
+
};
|
|
953
|
+
const convertSingleSortQueryParam = (sortQuery) => {
|
|
954
|
+
if (!sortQuery) {
|
|
955
|
+
return {};
|
|
956
|
+
}
|
|
957
|
+
if (!fp.isString(sortQuery)) {
|
|
958
|
+
throw new Error("Invalid sort query");
|
|
959
|
+
}
|
|
960
|
+
const [field, order = "asc"] = sortQuery.split(":");
|
|
961
|
+
if (field.length === 0) {
|
|
962
|
+
throw new Error("Field cannot be empty");
|
|
963
|
+
}
|
|
964
|
+
validateOrder(order);
|
|
965
|
+
return ___namespace.default.set({}, field, order);
|
|
966
|
+
};
|
|
967
|
+
const convertNestedSortQueryParam = (sortQuery) => {
|
|
968
|
+
const transformedSort = {};
|
|
969
|
+
for (const field of Object.keys(sortQuery)) {
|
|
970
|
+
const order = sortQuery[field];
|
|
971
|
+
if (isPlainObject(order)) {
|
|
972
|
+
transformedSort[field] = convertNestedSortQueryParam(order);
|
|
973
|
+
} else if (typeof order === "string") {
|
|
974
|
+
validateOrder(order);
|
|
975
|
+
transformedSort[field] = order;
|
|
976
|
+
} else {
|
|
977
|
+
throw Error(`Invalid sort type expected object or string got ${typeof order}`);
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
return transformedSort;
|
|
981
|
+
};
|
|
982
|
+
const convertStartQueryParams = (startQuery) => {
|
|
983
|
+
const startAsANumber = ___namespace.default.toNumber(startQuery);
|
|
984
|
+
if (!___namespace.default.isInteger(startAsANumber) || startAsANumber < 0) {
|
|
985
|
+
throw new Error(`convertStartQueryParams expected a positive integer got ${startAsANumber}`);
|
|
986
|
+
}
|
|
987
|
+
return startAsANumber;
|
|
988
|
+
};
|
|
989
|
+
const convertLimitQueryParams = (limitQuery) => {
|
|
990
|
+
const limitAsANumber = ___namespace.default.toNumber(limitQuery);
|
|
991
|
+
if (!___namespace.default.isInteger(limitAsANumber) || limitAsANumber !== -1 && limitAsANumber < 0) {
|
|
992
|
+
throw new Error(`convertLimitQueryParams expected a positive integer got ${limitAsANumber}`);
|
|
993
|
+
}
|
|
994
|
+
if (limitAsANumber === -1) {
|
|
995
|
+
return void 0;
|
|
996
|
+
}
|
|
997
|
+
return limitAsANumber;
|
|
998
|
+
};
|
|
999
|
+
const convertPageQueryParams = (page) => {
|
|
1000
|
+
const pageVal = fp.toNumber(page);
|
|
1001
|
+
if (!fp.isInteger(pageVal) || pageVal <= 0) {
|
|
1002
|
+
throw new PaginationError(
|
|
1003
|
+
`Invalid 'page' parameter. Expected an integer > 0, received: ${page}`
|
|
1004
|
+
);
|
|
1005
|
+
}
|
|
1006
|
+
return pageVal;
|
|
1007
|
+
};
|
|
1008
|
+
const convertPageSizeQueryParams = (pageSize, page) => {
|
|
1009
|
+
const pageSizeVal = fp.toNumber(pageSize);
|
|
1010
|
+
if (!fp.isInteger(pageSizeVal) || pageSizeVal <= 0) {
|
|
1011
|
+
throw new PaginationError(
|
|
1012
|
+
`Invalid 'pageSize' parameter. Expected an integer > 0, received: ${page}`
|
|
1013
|
+
);
|
|
1014
|
+
}
|
|
1015
|
+
return pageSizeVal;
|
|
1016
|
+
};
|
|
1017
|
+
const validatePaginationParams = (page, pageSize, start, limit) => {
|
|
1018
|
+
const isPagePagination = !fp.isNil(page) || !fp.isNil(pageSize);
|
|
1019
|
+
const isOffsetPagination = !fp.isNil(start) || !fp.isNil(limit);
|
|
1020
|
+
if (isPagePagination && isOffsetPagination) {
|
|
1021
|
+
throw new PaginationError(
|
|
1022
|
+
"Invalid pagination attributes. You cannot use page and offset pagination in the same query"
|
|
1023
|
+
);
|
|
1024
|
+
}
|
|
1025
|
+
};
|
|
1026
|
+
class InvalidPopulateError extends Error {
|
|
1027
|
+
constructor() {
|
|
1028
|
+
super();
|
|
1029
|
+
this.message = "Invalid populate parameter. Expected a string, an array of strings, a populate object";
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
const convertPopulateQueryParams = (populate2, schema, depth = 0) => {
|
|
1033
|
+
if (depth === 0 && populate2 === "*") {
|
|
1034
|
+
return true;
|
|
1035
|
+
}
|
|
1036
|
+
if (typeof populate2 === "string") {
|
|
1037
|
+
return populate2.split(",").map((value) => ___namespace.default.trim(value));
|
|
1038
|
+
}
|
|
1039
|
+
if (Array.isArray(populate2)) {
|
|
1040
|
+
return ___namespace.default.uniq(
|
|
1041
|
+
populate2.flatMap((value) => {
|
|
1042
|
+
if (typeof value !== "string") {
|
|
1043
|
+
throw new InvalidPopulateError();
|
|
1044
|
+
}
|
|
1045
|
+
return value.split(",").map((value2) => ___namespace.default.trim(value2));
|
|
1046
|
+
})
|
|
1047
|
+
);
|
|
1048
|
+
}
|
|
1049
|
+
if (___namespace.default.isPlainObject(populate2)) {
|
|
1050
|
+
return convertPopulateObject(populate2, schema);
|
|
1051
|
+
}
|
|
1052
|
+
throw new InvalidPopulateError();
|
|
1053
|
+
};
|
|
1054
|
+
const hasPopulateFragmentDefined = (populate2) => {
|
|
1055
|
+
return typeof populate2 === "object" && "on" in populate2 && !fp.isNil(populate2.on);
|
|
1056
|
+
};
|
|
1057
|
+
const hasCountDefined = (populate2) => {
|
|
1058
|
+
return typeof populate2 === "object" && "count" in populate2 && typeof populate2.count === "boolean";
|
|
1059
|
+
};
|
|
1060
|
+
const convertPopulateObject = (populate2, schema) => {
|
|
1061
|
+
if (!schema) {
|
|
1062
|
+
return {};
|
|
1063
|
+
}
|
|
1064
|
+
const { attributes } = schema;
|
|
1065
|
+
return Object.entries(populate2).reduce((acc, [key, subPopulate]) => {
|
|
1066
|
+
if (___namespace.default.isString(subPopulate)) {
|
|
1067
|
+
try {
|
|
1068
|
+
const subPopulateAsBoolean = parseType({ type: "boolean", value: subPopulate });
|
|
1069
|
+
return subPopulateAsBoolean === true ? { ...acc, [key]: true } : acc;
|
|
1070
|
+
} catch {
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
if (___namespace.default.isBoolean(subPopulate)) {
|
|
1074
|
+
return subPopulate === true ? { ...acc, [key]: true } : acc;
|
|
1075
|
+
}
|
|
1076
|
+
const attribute = attributes[key];
|
|
1077
|
+
if (!attribute) {
|
|
1078
|
+
return acc;
|
|
1079
|
+
}
|
|
1080
|
+
const isMorphLikeRelationalAttribute = isDynamicZoneAttribute(attribute) || isMorphToRelationalAttribute(attribute);
|
|
1081
|
+
if (isMorphLikeRelationalAttribute) {
|
|
1082
|
+
const hasInvalidProperties = Object.keys(subPopulate).some(
|
|
1083
|
+
(key2) => !["on", "count"].includes(key2)
|
|
1084
|
+
);
|
|
1085
|
+
if (hasInvalidProperties) {
|
|
1086
|
+
throw new Error(
|
|
1087
|
+
`Invalid nested populate for ${schema.info?.singularName}.${key} (${schema.uid}). Expected a fragment ("on") or "count" but found ${JSON.stringify(subPopulate)}`
|
|
1088
|
+
);
|
|
1089
|
+
}
|
|
1090
|
+
const newSubPopulate = {};
|
|
1091
|
+
if (hasPopulateFragmentDefined(subPopulate)) {
|
|
1092
|
+
Object.assign(newSubPopulate, {
|
|
1093
|
+
on: Object.entries(subPopulate.on).reduce(
|
|
1094
|
+
(acc2, [type, typeSubPopulate]) => ({
|
|
1095
|
+
...acc2,
|
|
1096
|
+
[type]: convertNestedPopulate(typeSubPopulate, getModel(type))
|
|
1097
|
+
}),
|
|
1098
|
+
{}
|
|
1099
|
+
)
|
|
1100
|
+
});
|
|
1101
|
+
}
|
|
1102
|
+
if (hasCountDefined(subPopulate)) {
|
|
1103
|
+
Object.assign(newSubPopulate, { count: subPopulate.count });
|
|
1104
|
+
}
|
|
1105
|
+
return { ...acc, [key]: newSubPopulate };
|
|
1106
|
+
}
|
|
1107
|
+
if (!isMorphLikeRelationalAttribute && hasPopulateFragmentDefined(subPopulate)) {
|
|
1108
|
+
throw new Error(`Using fragments is not permitted to populate "${key}" in "${schema.uid}"`);
|
|
1109
|
+
}
|
|
1110
|
+
let targetSchemaUID;
|
|
1111
|
+
if (attribute.type === "relation") {
|
|
1112
|
+
targetSchemaUID = attribute.target;
|
|
1113
|
+
} else if (attribute.type === "component") {
|
|
1114
|
+
targetSchemaUID = attribute.component;
|
|
1115
|
+
} else if (attribute.type === "media") {
|
|
1116
|
+
targetSchemaUID = "plugin::upload.file";
|
|
1117
|
+
} else {
|
|
1118
|
+
return acc;
|
|
1119
|
+
}
|
|
1120
|
+
const targetSchema = getModel(targetSchemaUID);
|
|
1121
|
+
if (!targetSchema) {
|
|
1122
|
+
return acc;
|
|
1123
|
+
}
|
|
1124
|
+
const populateObject = convertNestedPopulate(subPopulate, targetSchema);
|
|
1125
|
+
if (!populateObject) {
|
|
1126
|
+
return acc;
|
|
1127
|
+
}
|
|
1128
|
+
return {
|
|
1129
|
+
...acc,
|
|
1130
|
+
[key]: populateObject
|
|
1131
|
+
};
|
|
1132
|
+
}, {});
|
|
1133
|
+
};
|
|
1134
|
+
const convertNestedPopulate = (subPopulate, schema) => {
|
|
1135
|
+
if (___namespace.default.isString(subPopulate)) {
|
|
1136
|
+
return parseType({ type: "boolean", value: subPopulate, forceCast: true });
|
|
1137
|
+
}
|
|
1138
|
+
if (___namespace.default.isBoolean(subPopulate)) {
|
|
1139
|
+
return subPopulate;
|
|
1140
|
+
}
|
|
1141
|
+
if (!isPlainObject(subPopulate)) {
|
|
1142
|
+
throw new Error(`Invalid nested populate. Expected '*' or an object`);
|
|
1143
|
+
}
|
|
1144
|
+
const { sort: sort2, filters: filters2, fields: fields2, populate: populate2, count, ordering, page, pageSize, start, limit } = subPopulate;
|
|
1145
|
+
const query = {};
|
|
1146
|
+
if (sort2) {
|
|
1147
|
+
query.orderBy = convertSortQueryParams(sort2);
|
|
1148
|
+
}
|
|
1149
|
+
if (filters2) {
|
|
1150
|
+
query.where = convertFiltersQueryParams(filters2, schema);
|
|
1151
|
+
}
|
|
1152
|
+
if (fields2) {
|
|
1153
|
+
query.select = convertFieldsQueryParams(fields2);
|
|
1154
|
+
}
|
|
1155
|
+
if (populate2) {
|
|
1156
|
+
query.populate = convertPopulateQueryParams(populate2, schema);
|
|
1157
|
+
}
|
|
1158
|
+
if (count) {
|
|
1159
|
+
query.count = convertCountQueryParams(count);
|
|
1160
|
+
}
|
|
1161
|
+
if (ordering) {
|
|
1162
|
+
query.ordering = convertOrderingQueryParams(ordering);
|
|
1163
|
+
}
|
|
1164
|
+
validatePaginationParams(page, pageSize, start, limit);
|
|
1165
|
+
if (!fp.isNil(page)) {
|
|
1166
|
+
query.page = convertPageQueryParams(page);
|
|
1167
|
+
}
|
|
1168
|
+
if (!fp.isNil(pageSize)) {
|
|
1169
|
+
query.pageSize = convertPageSizeQueryParams(pageSize, page);
|
|
1170
|
+
}
|
|
1171
|
+
if (!fp.isNil(start)) {
|
|
1172
|
+
query.offset = convertStartQueryParams(start);
|
|
1173
|
+
}
|
|
1174
|
+
if (!fp.isNil(limit)) {
|
|
1175
|
+
query.limit = convertLimitQueryParams(limit);
|
|
1176
|
+
}
|
|
1177
|
+
return query;
|
|
1178
|
+
};
|
|
1179
|
+
const convertFieldsQueryParams = (fields2, depth = 0) => {
|
|
1180
|
+
if (depth === 0 && fields2 === "*") {
|
|
1181
|
+
return void 0;
|
|
1182
|
+
}
|
|
1183
|
+
if (typeof fields2 === "string") {
|
|
1184
|
+
const fieldsValues = fields2.split(",").map((value) => ___namespace.default.trim(value));
|
|
1185
|
+
return ___namespace.default.uniq([ID_ATTRIBUTE$3, DOC_ID_ATTRIBUTE$3, ...fieldsValues]);
|
|
1186
|
+
}
|
|
1187
|
+
if (isStringArray$3(fields2)) {
|
|
1188
|
+
const fieldsValues = fields2.flatMap((value) => convertFieldsQueryParams(value, depth + 1)).filter((v) => !fp.isNil(v));
|
|
1189
|
+
return ___namespace.default.uniq([ID_ATTRIBUTE$3, DOC_ID_ATTRIBUTE$3, ...fieldsValues]);
|
|
1190
|
+
}
|
|
1191
|
+
throw new Error("Invalid fields parameter. Expected a string or an array of strings");
|
|
1192
|
+
};
|
|
1193
|
+
const isValidSchemaAttribute = (key, schema) => {
|
|
1194
|
+
if ([DOC_ID_ATTRIBUTE$3, ID_ATTRIBUTE$3].includes(key)) {
|
|
1195
|
+
return true;
|
|
1196
|
+
}
|
|
1197
|
+
if (!schema) {
|
|
1198
|
+
return false;
|
|
1199
|
+
}
|
|
1200
|
+
return Object.keys(schema.attributes).includes(key);
|
|
1201
|
+
};
|
|
1202
|
+
const convertFiltersQueryParams = (filters2, schema) => {
|
|
1203
|
+
if (!fp.isObject(filters2)) {
|
|
1204
|
+
throw new Error("The filters parameter must be an object or an array");
|
|
1205
|
+
}
|
|
1206
|
+
const filtersCopy = fp.cloneDeep(filters2);
|
|
1207
|
+
return convertAndSanitizeFilters(filtersCopy, schema);
|
|
1208
|
+
};
|
|
1209
|
+
const convertAndSanitizeFilters = (filters2, schema) => {
|
|
1210
|
+
if (Array.isArray(filters2)) {
|
|
1211
|
+
return filters2.map((filter) => convertAndSanitizeFilters(filter, schema)).filter((filter) => !isPlainObject(filter) || !fp.isEmpty(filter));
|
|
1212
|
+
}
|
|
1213
|
+
if (!isPlainObject(filters2)) {
|
|
1214
|
+
return filters2;
|
|
1215
|
+
}
|
|
1216
|
+
const removeOperator = (operator) => delete filters2[operator];
|
|
1217
|
+
for (const [key, value] of Object.entries(filters2)) {
|
|
1218
|
+
const attribute = fp.get(key, schema?.attributes);
|
|
1219
|
+
const validKey = isOperator(key) || isValidSchemaAttribute(key, schema);
|
|
1220
|
+
if (!validKey) {
|
|
1221
|
+
removeOperator(key);
|
|
1222
|
+
} else if (attribute) {
|
|
1223
|
+
if (attribute.type === "relation") {
|
|
1224
|
+
filters2[key] = convertAndSanitizeFilters(value, getModel(attribute.target));
|
|
1225
|
+
} else if (attribute.type === "component") {
|
|
1226
|
+
filters2[key] = convertAndSanitizeFilters(value, getModel(attribute.component));
|
|
1227
|
+
} else if (attribute.type === "media") {
|
|
1228
|
+
filters2[key] = convertAndSanitizeFilters(value, getModel("plugin::upload.file"));
|
|
1229
|
+
} else if (attribute.type === "dynamiczone") {
|
|
1230
|
+
removeOperator(key);
|
|
1231
|
+
} else if (attribute.type === "password") {
|
|
1232
|
+
removeOperator(key);
|
|
1233
|
+
} else {
|
|
1234
|
+
filters2[key] = convertAndSanitizeFilters(value, schema);
|
|
1235
|
+
}
|
|
1236
|
+
} else if (["$null", "$notNull"].includes(key)) {
|
|
1237
|
+
filters2[key] = parseType({ type: "boolean", value: filters2[key], forceCast: true });
|
|
1238
|
+
} else if (fp.isObject(value)) {
|
|
1239
|
+
filters2[key] = convertAndSanitizeFilters(value, schema);
|
|
1240
|
+
}
|
|
1241
|
+
if (isPlainObject(filters2[key]) && fp.isEmpty(filters2[key])) {
|
|
1242
|
+
removeOperator(key);
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
return filters2;
|
|
1246
|
+
};
|
|
1247
|
+
const convertStatusParams = (status, query = {}) => {
|
|
1248
|
+
query.filters = ({ meta }) => {
|
|
1249
|
+
const contentType = getModel(meta.uid);
|
|
1250
|
+
if (!contentType || !hasDraftAndPublish(contentType)) {
|
|
1251
|
+
return {};
|
|
1252
|
+
}
|
|
1253
|
+
return { [PUBLISHED_AT_ATTRIBUTE]: { $null: status === "draft" } };
|
|
1254
|
+
};
|
|
1255
|
+
};
|
|
1256
|
+
const transformQueryParams = (uid, params) => {
|
|
1257
|
+
const schema = getModel(uid);
|
|
1258
|
+
const query = {};
|
|
1259
|
+
const { _q, sort: sort2, filters: filters2, fields: fields2, populate: populate2, page, pageSize, start, limit, status, ...rest } = params;
|
|
1260
|
+
if (!fp.isNil(status)) {
|
|
1261
|
+
convertStatusParams(status, query);
|
|
1262
|
+
}
|
|
1263
|
+
if (!fp.isNil(_q)) {
|
|
1264
|
+
query._q = _q;
|
|
1265
|
+
}
|
|
1266
|
+
if (!fp.isNil(sort2)) {
|
|
1267
|
+
query.orderBy = convertSortQueryParams(sort2);
|
|
1268
|
+
}
|
|
1269
|
+
if (!fp.isNil(filters2)) {
|
|
1270
|
+
query.where = convertFiltersQueryParams(filters2, schema);
|
|
1271
|
+
}
|
|
1272
|
+
if (!fp.isNil(fields2)) {
|
|
1273
|
+
query.select = convertFieldsQueryParams(fields2);
|
|
1274
|
+
}
|
|
1275
|
+
if (!fp.isNil(populate2)) {
|
|
1276
|
+
query.populate = convertPopulateQueryParams(populate2, schema);
|
|
1277
|
+
}
|
|
1278
|
+
validatePaginationParams(page, pageSize, start, limit);
|
|
1279
|
+
if (!fp.isNil(page)) {
|
|
1280
|
+
query.page = convertPageQueryParams(page);
|
|
1281
|
+
}
|
|
1282
|
+
if (!fp.isNil(pageSize)) {
|
|
1283
|
+
query.pageSize = convertPageSizeQueryParams(pageSize, page);
|
|
1284
|
+
}
|
|
1285
|
+
if (!fp.isNil(start)) {
|
|
1286
|
+
query.offset = convertStartQueryParams(start);
|
|
1287
|
+
}
|
|
1288
|
+
if (!fp.isNil(limit)) {
|
|
1289
|
+
query.limit = convertLimitQueryParams(limit);
|
|
1290
|
+
}
|
|
1291
|
+
return {
|
|
1292
|
+
...rest,
|
|
1293
|
+
...query
|
|
1294
|
+
};
|
|
1295
|
+
};
|
|
1296
|
+
return {
|
|
1297
|
+
private_convertSortQueryParams: convertSortQueryParams,
|
|
1298
|
+
private_convertStartQueryParams: convertStartQueryParams,
|
|
1299
|
+
private_convertLimitQueryParams: convertLimitQueryParams,
|
|
1300
|
+
private_convertPopulateQueryParams: convertPopulateQueryParams,
|
|
1301
|
+
private_convertFiltersQueryParams: convertFiltersQueryParams,
|
|
1302
|
+
private_convertFieldsQueryParams: convertFieldsQueryParams,
|
|
1303
|
+
transformQueryParams
|
|
1304
|
+
};
|
|
1305
|
+
};
|
|
1306
|
+
const convertQueryParams = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1307
|
+
__proto__: null,
|
|
1308
|
+
createTransformer
|
|
1309
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
1310
|
+
function pipe(...fns) {
|
|
1311
|
+
const [firstFn, ...fnRest] = fns;
|
|
1312
|
+
return async (...args) => {
|
|
1313
|
+
let res = await firstFn.apply(firstFn, args);
|
|
1314
|
+
for (let i = 0; i < fnRest.length; i += 1) {
|
|
1315
|
+
res = await fnRest[i](res);
|
|
1316
|
+
}
|
|
1317
|
+
return res;
|
|
1318
|
+
};
|
|
1319
|
+
}
|
|
1320
|
+
const map = fp.curry(pMap__default.default);
|
|
1321
|
+
const reduce = (mixedArray) => async (iteratee, initialValue) => {
|
|
1322
|
+
let acc = initialValue;
|
|
1323
|
+
for (let i = 0; i < mixedArray.length; i += 1) {
|
|
1324
|
+
acc = await iteratee(acc, await mixedArray[i], i);
|
|
1325
|
+
}
|
|
1326
|
+
return acc;
|
|
1327
|
+
};
|
|
1328
|
+
const async = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1329
|
+
__proto__: null,
|
|
1330
|
+
map,
|
|
1331
|
+
pipe,
|
|
1332
|
+
reduce
|
|
1333
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
1334
|
+
const visitor$8 = ({ key, attribute }, { remove }) => {
|
|
1335
|
+
if (attribute?.type === "password") {
|
|
1336
|
+
remove(key);
|
|
1337
|
+
}
|
|
1338
|
+
};
|
|
1339
|
+
const visitor$7 = ({ schema, key, attribute }, { remove }) => {
|
|
1340
|
+
if (!attribute) {
|
|
1341
|
+
return;
|
|
1342
|
+
}
|
|
1343
|
+
const isPrivate = attribute.private === true || isPrivateAttribute(schema, key);
|
|
1344
|
+
if (isPrivate) {
|
|
1345
|
+
remove(key);
|
|
1346
|
+
}
|
|
1347
|
+
};
|
|
1348
|
+
const ACTIONS_TO_VERIFY$1 = ["find"];
|
|
1349
|
+
const { CREATED_BY_ATTRIBUTE: CREATED_BY_ATTRIBUTE$1, UPDATED_BY_ATTRIBUTE: UPDATED_BY_ATTRIBUTE$1 } = constants$1;
|
|
1350
|
+
const removeRestrictedRelations = (auth) => async ({ data, key, attribute, schema }, { remove, set }) => {
|
|
1351
|
+
if (!attribute) {
|
|
1352
|
+
return;
|
|
1353
|
+
}
|
|
1354
|
+
const isRelation = attribute.type === "relation";
|
|
1355
|
+
if (!isRelation) {
|
|
1356
|
+
return;
|
|
1357
|
+
}
|
|
1358
|
+
const handleMorphRelation = async () => {
|
|
1359
|
+
const newMorphValue = [];
|
|
1360
|
+
for (const element of data[key]) {
|
|
1361
|
+
const scopes = ACTIONS_TO_VERIFY$1.map((action) => `${element.__type}.${action}`);
|
|
1362
|
+
const isAllowed = await hasAccessToSomeScopes$1(scopes, auth);
|
|
1363
|
+
if (isAllowed) {
|
|
1364
|
+
newMorphValue.push(element);
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
if (newMorphValue.length === 0) {
|
|
1368
|
+
remove(key);
|
|
1369
|
+
} else {
|
|
1370
|
+
set(key, newMorphValue);
|
|
1371
|
+
}
|
|
1372
|
+
};
|
|
1373
|
+
const handleRegularRelation = async () => {
|
|
1374
|
+
const scopes = ACTIONS_TO_VERIFY$1.map((action) => `${attribute.target}.${action}`);
|
|
1375
|
+
const isAllowed = await hasAccessToSomeScopes$1(scopes, auth);
|
|
1376
|
+
if (!isAllowed) {
|
|
1377
|
+
remove(key);
|
|
1378
|
+
}
|
|
1379
|
+
};
|
|
1380
|
+
const isCreatorRelation = [CREATED_BY_ATTRIBUTE$1, UPDATED_BY_ATTRIBUTE$1].includes(key);
|
|
1381
|
+
if (isMorphToRelationalAttribute(attribute)) {
|
|
1382
|
+
await handleMorphRelation();
|
|
1383
|
+
return;
|
|
1384
|
+
}
|
|
1385
|
+
if (isCreatorRelation && schema.options?.populateCreatorFields) {
|
|
1386
|
+
return;
|
|
1387
|
+
}
|
|
1388
|
+
await handleRegularRelation();
|
|
1389
|
+
};
|
|
1390
|
+
const hasAccessToSomeScopes$1 = async (scopes, auth) => {
|
|
1391
|
+
for (const scope of scopes) {
|
|
1392
|
+
try {
|
|
1393
|
+
await strapi.auth.verify(auth, { scope });
|
|
1394
|
+
return true;
|
|
1395
|
+
} catch {
|
|
1396
|
+
continue;
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
return false;
|
|
1400
|
+
};
|
|
1401
|
+
const visitor$6 = ({ key, attribute }, { remove }) => {
|
|
1402
|
+
if (isMorphToRelationalAttribute(attribute)) {
|
|
1403
|
+
remove(key);
|
|
1404
|
+
}
|
|
1405
|
+
};
|
|
1406
|
+
const visitor$5 = ({ key, attribute }, { remove }) => {
|
|
1407
|
+
if (isDynamicZoneAttribute(attribute)) {
|
|
1408
|
+
remove(key);
|
|
1409
|
+
}
|
|
1410
|
+
};
|
|
1411
|
+
const removeDisallowedFields = (allowedFields = null) => ({ key, path: { attribute: path } }, { remove }) => {
|
|
1412
|
+
if (allowedFields === null) {
|
|
1413
|
+
return;
|
|
1414
|
+
}
|
|
1415
|
+
if (!(fp.isArray(allowedFields) && allowedFields.every(fp.isString))) {
|
|
1416
|
+
throw new TypeError(
|
|
1417
|
+
`Expected array of strings for allowedFields but got "${typeof allowedFields}"`
|
|
1418
|
+
);
|
|
1419
|
+
}
|
|
1420
|
+
if (fp.isNil(path)) {
|
|
1421
|
+
return;
|
|
1422
|
+
}
|
|
1423
|
+
const containedPaths = getContainedPaths$1(path);
|
|
1424
|
+
const isPathAllowed = allowedFields.some(
|
|
1425
|
+
(p) => containedPaths.includes(p) || p.startsWith(`${path}.`)
|
|
1426
|
+
);
|
|
1427
|
+
if (isPathAllowed) {
|
|
1428
|
+
return;
|
|
1429
|
+
}
|
|
1430
|
+
remove(key);
|
|
1431
|
+
};
|
|
1432
|
+
const getContainedPaths$1 = (path) => {
|
|
1433
|
+
const parts = fp.toPath(path);
|
|
1434
|
+
return parts.reduce((acc, value, index2, list) => {
|
|
1435
|
+
return [...acc, list.slice(0, index2 + 1).join(".")];
|
|
1436
|
+
}, []);
|
|
1437
|
+
};
|
|
1438
|
+
const removeRestrictedFields = (restrictedFields = null) => ({ key, path: { attribute: path } }, { remove }) => {
|
|
1439
|
+
if (restrictedFields === null) {
|
|
1440
|
+
remove(key);
|
|
1441
|
+
return;
|
|
1442
|
+
}
|
|
1443
|
+
if (!(fp.isArray(restrictedFields) && restrictedFields.every(fp.isString))) {
|
|
1444
|
+
throw new TypeError(
|
|
1445
|
+
`Expected array of strings for restrictedFields but got "${typeof restrictedFields}"`
|
|
1446
|
+
);
|
|
1447
|
+
}
|
|
1448
|
+
if (restrictedFields.includes(path)) {
|
|
1449
|
+
remove(key);
|
|
1450
|
+
return;
|
|
1451
|
+
}
|
|
1452
|
+
const isRestrictedNested = restrictedFields.some(
|
|
1453
|
+
(allowedPath) => path?.toString().startsWith(`${allowedPath}.`)
|
|
1454
|
+
);
|
|
1455
|
+
if (isRestrictedNested) {
|
|
1456
|
+
remove(key);
|
|
1457
|
+
}
|
|
1458
|
+
};
|
|
1459
|
+
const visitor$4 = ({ schema, key, value }, { set }) => {
|
|
1460
|
+
if (key === "" && value === "*") {
|
|
1461
|
+
const { attributes } = schema;
|
|
1462
|
+
const newPopulateQuery = Object.entries(attributes).filter(
|
|
1463
|
+
([, attribute]) => ["relation", "component", "media", "dynamiczone"].includes(attribute.type)
|
|
1464
|
+
).reduce((acc, [key2]) => ({ ...acc, [key2]: true }), {});
|
|
1465
|
+
set("", newPopulateQuery);
|
|
1466
|
+
}
|
|
1467
|
+
};
|
|
1468
|
+
const index$4 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1469
|
+
__proto__: null,
|
|
1470
|
+
expandWildcardPopulate: visitor$4,
|
|
1471
|
+
removeDisallowedFields,
|
|
1472
|
+
removeDynamicZones: visitor$5,
|
|
1473
|
+
removeMorphToRelations: visitor$6,
|
|
1474
|
+
removePassword: visitor$8,
|
|
1475
|
+
removePrivate: visitor$7,
|
|
1476
|
+
removeRestrictedFields,
|
|
1477
|
+
removeRestrictedRelations
|
|
1478
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
1479
|
+
const DEFAULT_PATH = { raw: null, attribute: null };
|
|
1480
|
+
const traverseFactory = () => {
|
|
1481
|
+
const state = {
|
|
1482
|
+
parsers: [],
|
|
1483
|
+
interceptors: [],
|
|
1484
|
+
ignore: [],
|
|
1485
|
+
handlers: {
|
|
1486
|
+
attributes: [],
|
|
1487
|
+
common: []
|
|
1488
|
+
}
|
|
1489
|
+
};
|
|
1490
|
+
const traverse = async (visitor2, options, data) => {
|
|
1491
|
+
const { path = DEFAULT_PATH, schema, getModel } = options ?? {};
|
|
1492
|
+
for (const { predicate, handler } of state.interceptors) {
|
|
1493
|
+
if (predicate(data)) {
|
|
1494
|
+
return handler(visitor2, options, data, { recurse: traverse });
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
const parser = state.parsers.find((parser2) => parser2.predicate(data))?.parser;
|
|
1498
|
+
const utils2 = parser?.(data);
|
|
1499
|
+
if (!utils2) {
|
|
1500
|
+
return data;
|
|
1501
|
+
}
|
|
1502
|
+
let out = utils2.transform(data);
|
|
1503
|
+
const keys = utils2.keys(out);
|
|
1504
|
+
for (const key of keys) {
|
|
1505
|
+
const attribute = schema?.attributes?.[key];
|
|
1506
|
+
const newPath = { ...path };
|
|
1507
|
+
newPath.raw = fp.isNil(path.raw) ? key : `${path.raw}.${key}`;
|
|
1508
|
+
if (!fp.isNil(attribute)) {
|
|
1509
|
+
newPath.attribute = fp.isNil(path.attribute) ? key : `${path.attribute}.${key}`;
|
|
1510
|
+
}
|
|
1511
|
+
const visitorOptions = {
|
|
1512
|
+
key,
|
|
1513
|
+
value: utils2.get(key, out),
|
|
1514
|
+
attribute,
|
|
1515
|
+
schema,
|
|
1516
|
+
path: newPath,
|
|
1517
|
+
data: out,
|
|
1518
|
+
getModel
|
|
1519
|
+
};
|
|
1520
|
+
const transformUtils = {
|
|
1521
|
+
remove(key2) {
|
|
1522
|
+
out = utils2.remove(key2, out);
|
|
1523
|
+
},
|
|
1524
|
+
set(key2, value2) {
|
|
1525
|
+
out = utils2.set(key2, value2, out);
|
|
1526
|
+
},
|
|
1527
|
+
recurse: traverse
|
|
1528
|
+
};
|
|
1529
|
+
await visitor2(visitorOptions, fp.pick(["remove", "set"], transformUtils));
|
|
1530
|
+
const value = utils2.get(key, out);
|
|
1531
|
+
const createContext = () => ({
|
|
1532
|
+
key,
|
|
1533
|
+
value,
|
|
1534
|
+
attribute,
|
|
1535
|
+
schema,
|
|
1536
|
+
path: newPath,
|
|
1537
|
+
data: out,
|
|
1538
|
+
visitor: visitor2,
|
|
1539
|
+
getModel
|
|
1540
|
+
});
|
|
892
1541
|
const ignoreCtx = createContext();
|
|
893
1542
|
const shouldIgnore = state.ignore.some((predicate) => predicate(ignoreCtx));
|
|
894
1543
|
if (shouldIgnore) {
|
|
@@ -976,33 +1625,33 @@ const filters = traverseFactory().intercept(
|
|
|
976
1625
|
}
|
|
977
1626
|
})).ignore(({ value }) => fp.isNil(value)).on(
|
|
978
1627
|
({ attribute }) => fp.isNil(attribute),
|
|
979
|
-
async ({ key, visitor: visitor2, path, value, schema }, { set, recurse }) => {
|
|
980
|
-
set(key, await recurse(visitor2, { schema, path }, value));
|
|
1628
|
+
async ({ key, visitor: visitor2, path, value, schema, getModel }, { set, recurse }) => {
|
|
1629
|
+
set(key, await recurse(visitor2, { schema, path, getModel }, value));
|
|
981
1630
|
}
|
|
982
|
-
).onRelation(async ({ key, attribute, visitor: visitor2, path, value }, { set, recurse }) => {
|
|
1631
|
+
).onRelation(async ({ key, attribute, visitor: visitor2, path, value, getModel }, { set, recurse }) => {
|
|
983
1632
|
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
|
984
1633
|
if (isMorphRelation) {
|
|
985
1634
|
return;
|
|
986
1635
|
}
|
|
987
1636
|
const targetSchemaUID = attribute.target;
|
|
988
|
-
const targetSchema =
|
|
989
|
-
const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
|
|
1637
|
+
const targetSchema = getModel(targetSchemaUID);
|
|
1638
|
+
const newValue = await recurse(visitor2, { schema: targetSchema, path, getModel }, value);
|
|
990
1639
|
set(key, newValue);
|
|
991
|
-
}).onComponent(async ({ key, attribute, visitor: visitor2, path, value }, { set, recurse }) => {
|
|
992
|
-
const targetSchema =
|
|
993
|
-
const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
|
|
1640
|
+
}).onComponent(async ({ key, attribute, visitor: visitor2, path, value, getModel }, { set, recurse }) => {
|
|
1641
|
+
const targetSchema = getModel(attribute.component);
|
|
1642
|
+
const newValue = await recurse(visitor2, { schema: targetSchema, path, getModel }, value);
|
|
994
1643
|
set(key, newValue);
|
|
995
|
-
}).onMedia(async ({ key, visitor: visitor2, path, value }, { set, recurse }) => {
|
|
1644
|
+
}).onMedia(async ({ key, visitor: visitor2, path, value, getModel }, { set, recurse }) => {
|
|
996
1645
|
const targetSchemaUID = "plugin::upload.file";
|
|
997
|
-
const targetSchema =
|
|
998
|
-
const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
|
|
1646
|
+
const targetSchema = getModel(targetSchemaUID);
|
|
1647
|
+
const newValue = await recurse(visitor2, { schema: targetSchema, path, getModel }, value);
|
|
999
1648
|
set(key, newValue);
|
|
1000
1649
|
});
|
|
1001
1650
|
const traverseQueryFilters = fp.curry(filters.traverse);
|
|
1002
1651
|
const ORDERS = { asc: "asc", desc: "desc" };
|
|
1003
1652
|
const ORDER_VALUES = Object.values(ORDERS);
|
|
1004
1653
|
const isSortOrder = (value) => ORDER_VALUES.includes(value.toLowerCase());
|
|
1005
|
-
const isStringArray$
|
|
1654
|
+
const isStringArray$2 = (value) => Array.isArray(value) && value.every(fp.isString);
|
|
1006
1655
|
const isObjectArray = (value) => Array.isArray(value) && value.every(fp.isObject);
|
|
1007
1656
|
const isNestedSorts = (value) => fp.isString(value) && value.split(",").length > 1;
|
|
1008
1657
|
const isObj$1 = (value) => fp.isObject(value);
|
|
@@ -1016,7 +1665,7 @@ const sort = traverseFactory().intercept(
|
|
|
1016
1665
|
}
|
|
1017
1666
|
).intercept(
|
|
1018
1667
|
// Array of strings ['foo', 'foo,bar'] => map(recurse), then filter out empty items
|
|
1019
|
-
isStringArray$
|
|
1668
|
+
isStringArray$2,
|
|
1020
1669
|
async (visitor2, options, sort2, { recurse }) => {
|
|
1021
1670
|
return Promise.all(sort2.map((nestedSort) => recurse(visitor2, options, nestedSort))).then(
|
|
1022
1671
|
(res) => res.filter((nestedSort) => !fp.isEmpty(nestedSort))
|
|
@@ -1083,23 +1732,23 @@ const sort = traverseFactory().intercept(
|
|
|
1083
1732
|
get(key, data) {
|
|
1084
1733
|
return data[key];
|
|
1085
1734
|
}
|
|
1086
|
-
})).onRelation(async ({ key, value, attribute, visitor: visitor2, path }, { set, recurse }) => {
|
|
1735
|
+
})).onRelation(async ({ key, value, attribute, visitor: visitor2, path, getModel }, { set, recurse }) => {
|
|
1087
1736
|
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
|
1088
1737
|
if (isMorphRelation) {
|
|
1089
1738
|
return;
|
|
1090
1739
|
}
|
|
1091
1740
|
const targetSchemaUID = attribute.target;
|
|
1092
|
-
const targetSchema =
|
|
1093
|
-
const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
|
|
1741
|
+
const targetSchema = getModel(targetSchemaUID);
|
|
1742
|
+
const newValue = await recurse(visitor2, { schema: targetSchema, path, getModel }, value);
|
|
1094
1743
|
set(key, newValue);
|
|
1095
|
-
}).onMedia(async ({ key, path, visitor: visitor2, value }, { recurse, set }) => {
|
|
1744
|
+
}).onMedia(async ({ key, path, visitor: visitor2, value, getModel }, { recurse, set }) => {
|
|
1096
1745
|
const targetSchemaUID = "plugin::upload.file";
|
|
1097
|
-
const targetSchema =
|
|
1098
|
-
const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
|
|
1746
|
+
const targetSchema = getModel(targetSchemaUID);
|
|
1747
|
+
const newValue = await recurse(visitor2, { schema: targetSchema, path, getModel }, value);
|
|
1099
1748
|
set(key, newValue);
|
|
1100
|
-
}).onComponent(async ({ key, value, visitor: visitor2, path, attribute }, { recurse, set }) => {
|
|
1101
|
-
const targetSchema =
|
|
1102
|
-
const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
|
|
1749
|
+
}).onComponent(async ({ key, value, visitor: visitor2, path, attribute, getModel }, { recurse, set }) => {
|
|
1750
|
+
const targetSchema = getModel(attribute.component);
|
|
1751
|
+
const newValue = await recurse(visitor2, { schema: targetSchema, path, getModel }, value);
|
|
1103
1752
|
set(key, newValue);
|
|
1104
1753
|
});
|
|
1105
1754
|
const traverseQuerySort = fp.curry(sort.traverse);
|
|
@@ -1108,9 +1757,9 @@ const isKeyword = (keyword) => {
|
|
|
1108
1757
|
return !attribute && keyword === key;
|
|
1109
1758
|
};
|
|
1110
1759
|
};
|
|
1111
|
-
const isStringArray$
|
|
1760
|
+
const isStringArray$1 = (value) => fp.isArray(value) && value.every(fp.isString);
|
|
1112
1761
|
const isObj = (value) => fp.isObject(value);
|
|
1113
|
-
const populate = traverseFactory().intercept(isStringArray$
|
|
1762
|
+
const populate = traverseFactory().intercept(isStringArray$1, async (visitor2, options, populate2, { recurse }) => {
|
|
1114
1763
|
const visitedPopulate = await Promise.all(
|
|
1115
1764
|
populate2.map((nestedPopulate) => recurse(visitor2, options, nestedPopulate))
|
|
1116
1765
|
);
|
|
@@ -1186,180 +1835,100 @@ const populate = traverseFactory().intercept(isStringArray$2, async (visitor2, o
|
|
|
1186
1835
|
return ["sort", "filters", "fields"].includes(key) && !attribute;
|
|
1187
1836
|
}).on(
|
|
1188
1837
|
// Handle recursion on populate."populate"
|
|
1189
|
-
isKeyword("populate"),
|
|
1190
|
-
async ({ key, visitor: visitor2, path, value, schema }, { set, recurse }) => {
|
|
1191
|
-
const newValue = await recurse(visitor2, { schema, path }, value);
|
|
1192
|
-
set(key, newValue);
|
|
1193
|
-
}
|
|
1194
|
-
).on(isKeyword("on"), async ({ key, visitor: visitor2, path, value }, { set, recurse }) => {
|
|
1195
|
-
const newOn = {};
|
|
1196
|
-
if (!isObj(value)) {
|
|
1197
|
-
return;
|
|
1198
|
-
}
|
|
1199
|
-
for (const [uid, subPopulate] of Object.entries(value)) {
|
|
1200
|
-
const model = strapi.getModel(uid);
|
|
1201
|
-
const newPath = { ...path, raw: `${path.raw}[${uid}]` };
|
|
1202
|
-
newOn[uid] = await recurse(visitor2, { schema: model, path: newPath }, subPopulate);
|
|
1203
|
-
}
|
|
1204
|
-
set(key, newOn);
|
|
1205
|
-
}).onRelation(async ({ key, value, attribute, visitor: visitor2, path, schema }, { set, recurse }) => {
|
|
1206
|
-
if (fp.isNil(value)) {
|
|
1207
|
-
return;
|
|
1208
|
-
}
|
|
1209
|
-
if (isMorphToRelationalAttribute(attribute)) {
|
|
1210
|
-
if (!fp.isObject(value) || !("on" in value && fp.isObject(value?.on))) {
|
|
1211
|
-
return;
|
|
1212
|
-
}
|
|
1213
|
-
const newValue2 = await recurse(visitor2, { schema, path }, { on: value?.on });
|
|
1214
|
-
set(key, { on: newValue2 });
|
|
1215
|
-
}
|
|
1216
|
-
const targetSchemaUID = attribute.target;
|
|
1217
|
-
const targetSchema = strapi.getModel(targetSchemaUID);
|
|
1218
|
-
const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
|
|
1219
|
-
set(key, newValue);
|
|
1220
|
-
}).onMedia(async ({ key, path, visitor: visitor2, value }, { recurse, set }) => {
|
|
1221
|
-
if (fp.isNil(value)) {
|
|
1222
|
-
return;
|
|
1223
|
-
}
|
|
1224
|
-
const targetSchemaUID = "plugin::upload.file";
|
|
1225
|
-
const targetSchema = strapi.getModel(targetSchemaUID);
|
|
1226
|
-
const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
|
|
1227
|
-
set(key, newValue);
|
|
1228
|
-
}).onComponent(async ({ key, value, visitor: visitor2, path, attribute }, { recurse, set }) => {
|
|
1229
|
-
if (fp.isNil(value)) {
|
|
1230
|
-
return;
|
|
1231
|
-
}
|
|
1232
|
-
const targetSchema = strapi.getModel(attribute.component);
|
|
1233
|
-
const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
|
|
1234
|
-
set(key, newValue);
|
|
1235
|
-
}).onDynamicZone(async ({ key, value, attribute, schema, visitor: visitor2, path }, { set, recurse }) => {
|
|
1236
|
-
if (fp.isNil(value)) {
|
|
1237
|
-
return;
|
|
1238
|
-
}
|
|
1239
|
-
if (fp.isObject(value)) {
|
|
1240
|
-
const { components } = attribute;
|
|
1241
|
-
const newValue = {};
|
|
1242
|
-
let newProperties = fp.omit("on", value);
|
|
1243
|
-
for (const componentUID of components) {
|
|
1244
|
-
const componentSchema = strapi.getModel(componentUID);
|
|
1245
|
-
const properties = await recurse(visitor2, { schema: componentSchema, path }, value);
|
|
1246
|
-
newProperties = fp.merge(newProperties, properties);
|
|
1247
|
-
}
|
|
1248
|
-
Object.assign(newValue, newProperties);
|
|
1249
|
-
if ("on" in value && value.on) {
|
|
1250
|
-
const newOn = await recurse(visitor2, { schema, path }, { on: value.on });
|
|
1251
|
-
Object.assign(newValue, newOn);
|
|
1252
|
-
}
|
|
1253
|
-
set(key, newValue);
|
|
1254
|
-
} else {
|
|
1255
|
-
const newValue = await recurse(visitor2, { schema, path }, value);
|
|
1256
|
-
set(key, newValue);
|
|
1257
|
-
}
|
|
1258
|
-
});
|
|
1259
|
-
const traverseQueryPopulate = fp.curry(populate.traverse);
|
|
1260
|
-
const isStringArray$1 = (value) => fp.isArray(value) && value.every(fp.isString);
|
|
1261
|
-
const fields = traverseFactory().intercept(isStringArray$1, async (visitor2, options, fields2, { recurse }) => {
|
|
1262
|
-
return Promise.all(fields2.map((field) => recurse(visitor2, options, field)));
|
|
1263
|
-
}).intercept((value) => fp.eq("*", value), fp.constant("*")).parse(fp.isString, () => ({
|
|
1264
|
-
transform: fp.trim,
|
|
1265
|
-
remove(key, data) {
|
|
1266
|
-
return data === key ? void 0 : data;
|
|
1267
|
-
},
|
|
1268
|
-
set(_key, _value, data) {
|
|
1269
|
-
return data;
|
|
1270
|
-
},
|
|
1271
|
-
keys(data) {
|
|
1272
|
-
return [data];
|
|
1273
|
-
},
|
|
1274
|
-
get(key, data) {
|
|
1275
|
-
return key === data ? data : void 0;
|
|
1276
|
-
}
|
|
1277
|
-
}));
|
|
1278
|
-
const traverseQueryFields = fp.curry(fields.traverse);
|
|
1279
|
-
const index$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1280
|
-
__proto__: null,
|
|
1281
|
-
factory: traverseFactory,
|
|
1282
|
-
traverseQueryFields,
|
|
1283
|
-
traverseQueryFilters,
|
|
1284
|
-
traverseQueryPopulate,
|
|
1285
|
-
traverseQuerySort
|
|
1286
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
1287
|
-
const GROUP_OPERATORS = ["$and", "$or"];
|
|
1288
|
-
const WHERE_OPERATORS = [
|
|
1289
|
-
"$not",
|
|
1290
|
-
"$in",
|
|
1291
|
-
"$notIn",
|
|
1292
|
-
"$eq",
|
|
1293
|
-
"$eqi",
|
|
1294
|
-
"$ne",
|
|
1295
|
-
"$nei",
|
|
1296
|
-
"$gt",
|
|
1297
|
-
"$gte",
|
|
1298
|
-
"$lt",
|
|
1299
|
-
"$lte",
|
|
1300
|
-
"$null",
|
|
1301
|
-
"$notNull",
|
|
1302
|
-
"$between",
|
|
1303
|
-
"$startsWith",
|
|
1304
|
-
"$endsWith",
|
|
1305
|
-
"$startsWithi",
|
|
1306
|
-
"$endsWithi",
|
|
1307
|
-
"$contains",
|
|
1308
|
-
"$notContains",
|
|
1309
|
-
"$containsi",
|
|
1310
|
-
"$notContainsi",
|
|
1311
|
-
// Experimental, only for internal use
|
|
1312
|
-
"$jsonSupersetOf"
|
|
1313
|
-
];
|
|
1314
|
-
const CAST_OPERATORS = [
|
|
1315
|
-
"$not",
|
|
1316
|
-
"$in",
|
|
1317
|
-
"$notIn",
|
|
1318
|
-
"$eq",
|
|
1319
|
-
"$ne",
|
|
1320
|
-
"$gt",
|
|
1321
|
-
"$gte",
|
|
1322
|
-
"$lt",
|
|
1323
|
-
"$lte",
|
|
1324
|
-
"$between"
|
|
1325
|
-
];
|
|
1326
|
-
const ARRAY_OPERATORS = ["$in", "$notIn", "$between"];
|
|
1327
|
-
const OPERATORS = {
|
|
1328
|
-
where: WHERE_OPERATORS,
|
|
1329
|
-
cast: CAST_OPERATORS,
|
|
1330
|
-
group: GROUP_OPERATORS,
|
|
1331
|
-
array: ARRAY_OPERATORS
|
|
1332
|
-
};
|
|
1333
|
-
const OPERATORS_LOWERCASE = Object.fromEntries(
|
|
1334
|
-
Object.entries(OPERATORS).map(([key, values]) => [
|
|
1335
|
-
key,
|
|
1336
|
-
values.map((value) => value.toLowerCase())
|
|
1337
|
-
])
|
|
1338
|
-
);
|
|
1339
|
-
const isObjKey = (key, obj) => {
|
|
1340
|
-
return key in obj;
|
|
1341
|
-
};
|
|
1342
|
-
const isOperatorOfType = (type, key, ignoreCase = false) => {
|
|
1343
|
-
if (ignoreCase) {
|
|
1344
|
-
return OPERATORS_LOWERCASE[type]?.includes(key.toLowerCase()) ?? false;
|
|
1838
|
+
isKeyword("populate"),
|
|
1839
|
+
async ({ key, visitor: visitor2, path, value, schema, getModel }, { set, recurse }) => {
|
|
1840
|
+
const newValue = await recurse(visitor2, { schema, path, getModel }, value);
|
|
1841
|
+
set(key, newValue);
|
|
1345
1842
|
}
|
|
1346
|
-
|
|
1347
|
-
|
|
1843
|
+
).on(isKeyword("on"), async ({ key, visitor: visitor2, path, value, getModel }, { set, recurse }) => {
|
|
1844
|
+
const newOn = {};
|
|
1845
|
+
if (!isObj(value)) {
|
|
1846
|
+
return;
|
|
1348
1847
|
}
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
const
|
|
1352
|
-
|
|
1353
|
-
}
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1848
|
+
for (const [uid, subPopulate] of Object.entries(value)) {
|
|
1849
|
+
const model = getModel(uid);
|
|
1850
|
+
const newPath = { ...path, raw: `${path.raw}[${uid}]` };
|
|
1851
|
+
newOn[uid] = await recurse(visitor2, { schema: model, path: newPath, getModel }, subPopulate);
|
|
1852
|
+
}
|
|
1853
|
+
set(key, newOn);
|
|
1854
|
+
}).onRelation(
|
|
1855
|
+
async ({ key, value, attribute, visitor: visitor2, path, schema, getModel }, { set, recurse }) => {
|
|
1856
|
+
if (fp.isNil(value)) {
|
|
1857
|
+
return;
|
|
1858
|
+
}
|
|
1859
|
+
if (isMorphToRelationalAttribute(attribute)) {
|
|
1860
|
+
if (!fp.isObject(value) || !("on" in value && fp.isObject(value?.on))) {
|
|
1861
|
+
return;
|
|
1862
|
+
}
|
|
1863
|
+
const newValue2 = await recurse(visitor2, { schema, path, getModel }, { on: value?.on });
|
|
1864
|
+
set(key, newValue2);
|
|
1865
|
+
return;
|
|
1866
|
+
}
|
|
1867
|
+
const targetSchemaUID = attribute.target;
|
|
1868
|
+
const targetSchema = getModel(targetSchemaUID);
|
|
1869
|
+
const newValue = await recurse(visitor2, { schema: targetSchema, path, getModel }, value);
|
|
1870
|
+
set(key, newValue);
|
|
1871
|
+
}
|
|
1872
|
+
).onMedia(async ({ key, path, visitor: visitor2, value, getModel }, { recurse, set }) => {
|
|
1873
|
+
if (fp.isNil(value)) {
|
|
1874
|
+
return;
|
|
1875
|
+
}
|
|
1876
|
+
const targetSchemaUID = "plugin::upload.file";
|
|
1877
|
+
const targetSchema = getModel(targetSchemaUID);
|
|
1878
|
+
const newValue = await recurse(visitor2, { schema: targetSchema, path, getModel }, value);
|
|
1879
|
+
set(key, newValue);
|
|
1880
|
+
}).onComponent(async ({ key, value, visitor: visitor2, path, attribute, getModel }, { recurse, set }) => {
|
|
1881
|
+
if (fp.isNil(value)) {
|
|
1882
|
+
return;
|
|
1883
|
+
}
|
|
1884
|
+
const targetSchema = getModel(attribute.component);
|
|
1885
|
+
const newValue = await recurse(visitor2, { schema: targetSchema, path, getModel }, value);
|
|
1886
|
+
set(key, newValue);
|
|
1887
|
+
}).onDynamicZone(async ({ key, value, schema, visitor: visitor2, path, getModel }, { set, recurse }) => {
|
|
1888
|
+
if (fp.isNil(value) || !fp.isObject(value)) {
|
|
1889
|
+
return;
|
|
1890
|
+
}
|
|
1891
|
+
if ("on" in value && value.on) {
|
|
1892
|
+
const newOn = await recurse(visitor2, { schema, path, getModel }, { on: value.on });
|
|
1893
|
+
set(key, newOn);
|
|
1894
|
+
}
|
|
1895
|
+
});
|
|
1896
|
+
const traverseQueryPopulate = fp.curry(populate.traverse);
|
|
1897
|
+
const isStringArray = (value) => fp.isArray(value) && value.every(fp.isString);
|
|
1898
|
+
const fields = traverseFactory().intercept(isStringArray, async (visitor2, options, fields2, { recurse }) => {
|
|
1899
|
+
return Promise.all(fields2.map((field) => recurse(visitor2, options, field)));
|
|
1900
|
+
}).intercept((value) => fp.eq("*", value), fp.constant("*")).parse(fp.isString, () => ({
|
|
1901
|
+
transform: fp.trim,
|
|
1902
|
+
remove(key, data) {
|
|
1903
|
+
return data === key ? void 0 : data;
|
|
1904
|
+
},
|
|
1905
|
+
set(_key, _value, data) {
|
|
1906
|
+
return data;
|
|
1907
|
+
},
|
|
1908
|
+
keys(data) {
|
|
1909
|
+
return [data];
|
|
1910
|
+
},
|
|
1911
|
+
get(key, data) {
|
|
1912
|
+
return key === data ? data : void 0;
|
|
1913
|
+
}
|
|
1914
|
+
}));
|
|
1915
|
+
const traverseQueryFields = fp.curry(fields.traverse);
|
|
1916
|
+
const index$3 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1917
|
+
__proto__: null,
|
|
1918
|
+
traverseQueryFields,
|
|
1919
|
+
traverseQueryFilters,
|
|
1920
|
+
traverseQueryPopulate,
|
|
1921
|
+
traverseQuerySort
|
|
1922
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
1923
|
+
const { ID_ATTRIBUTE: ID_ATTRIBUTE$2, DOC_ID_ATTRIBUTE: DOC_ID_ATTRIBUTE$2 } = constants$1;
|
|
1924
|
+
const sanitizePasswords = (ctx) => async (entity) => {
|
|
1925
|
+
if (!ctx.schema) {
|
|
1357
1926
|
throw new Error("Missing schema in sanitizePasswords");
|
|
1358
1927
|
}
|
|
1359
|
-
return traverseEntity$1(visitor$8,
|
|
1928
|
+
return traverseEntity$1(visitor$8, ctx, entity);
|
|
1360
1929
|
};
|
|
1361
|
-
const defaultSanitizeOutput = async (
|
|
1362
|
-
if (!schema) {
|
|
1930
|
+
const defaultSanitizeOutput = async (ctx, entity) => {
|
|
1931
|
+
if (!ctx.schema) {
|
|
1363
1932
|
throw new Error("Missing schema in defaultSanitizeOutput");
|
|
1364
1933
|
}
|
|
1365
1934
|
return traverseEntity$1(
|
|
@@ -1367,139 +1936,121 @@ const defaultSanitizeOutput = async (schema, entity) => {
|
|
|
1367
1936
|
visitor$8(...args);
|
|
1368
1937
|
visitor$7(...args);
|
|
1369
1938
|
},
|
|
1370
|
-
|
|
1939
|
+
ctx,
|
|
1371
1940
|
entity
|
|
1372
1941
|
);
|
|
1373
1942
|
};
|
|
1374
|
-
const defaultSanitizeFilters = fp.curry((
|
|
1375
|
-
if (!schema) {
|
|
1943
|
+
const defaultSanitizeFilters = fp.curry((ctx, filters2) => {
|
|
1944
|
+
if (!ctx.schema) {
|
|
1376
1945
|
throw new Error("Missing schema in defaultSanitizeFilters");
|
|
1377
1946
|
}
|
|
1378
1947
|
return pipe(
|
|
1379
1948
|
// Remove keys that are not attributes or valid operators
|
|
1380
|
-
traverseQueryFilters(
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
},
|
|
1390
|
-
{ schema }
|
|
1391
|
-
),
|
|
1949
|
+
traverseQueryFilters(({ key, attribute }, { remove }) => {
|
|
1950
|
+
const isAttribute = !!attribute;
|
|
1951
|
+
if ([ID_ATTRIBUTE$2, DOC_ID_ATTRIBUTE$2].includes(key)) {
|
|
1952
|
+
return;
|
|
1953
|
+
}
|
|
1954
|
+
if (!isAttribute && !isOperator(key)) {
|
|
1955
|
+
remove(key);
|
|
1956
|
+
}
|
|
1957
|
+
}, ctx),
|
|
1392
1958
|
// Remove dynamic zones from filters
|
|
1393
|
-
traverseQueryFilters(visitor$5,
|
|
1959
|
+
traverseQueryFilters(visitor$5, ctx),
|
|
1394
1960
|
// Remove morpTo relations from filters
|
|
1395
|
-
traverseQueryFilters(visitor$6,
|
|
1961
|
+
traverseQueryFilters(visitor$6, ctx),
|
|
1396
1962
|
// Remove passwords from filters
|
|
1397
|
-
traverseQueryFilters(visitor$8,
|
|
1963
|
+
traverseQueryFilters(visitor$8, ctx),
|
|
1398
1964
|
// Remove private from filters
|
|
1399
|
-
traverseQueryFilters(visitor$7,
|
|
1965
|
+
traverseQueryFilters(visitor$7, ctx),
|
|
1400
1966
|
// Remove empty objects
|
|
1401
|
-
traverseQueryFilters(
|
|
1402
|
-
(
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
},
|
|
1407
|
-
{ schema }
|
|
1408
|
-
)
|
|
1967
|
+
traverseQueryFilters(({ key, value }, { remove }) => {
|
|
1968
|
+
if (fp.isObject(value) && fp.isEmpty(value)) {
|
|
1969
|
+
remove(key);
|
|
1970
|
+
}
|
|
1971
|
+
}, ctx)
|
|
1409
1972
|
)(filters2);
|
|
1410
1973
|
});
|
|
1411
|
-
const defaultSanitizeSort = fp.curry((
|
|
1412
|
-
if (!schema) {
|
|
1974
|
+
const defaultSanitizeSort = fp.curry((ctx, sort2) => {
|
|
1975
|
+
if (!ctx.schema) {
|
|
1413
1976
|
throw new Error("Missing schema in defaultSanitizeSort");
|
|
1414
1977
|
}
|
|
1415
1978
|
return pipe(
|
|
1416
1979
|
// Remove non attribute keys
|
|
1417
|
-
traverseQuerySort(
|
|
1418
|
-
(
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
},
|
|
1426
|
-
{ schema }
|
|
1427
|
-
),
|
|
1980
|
+
traverseQuerySort(({ key, attribute }, { remove }) => {
|
|
1981
|
+
if ([ID_ATTRIBUTE$2, DOC_ID_ATTRIBUTE$2].includes(key)) {
|
|
1982
|
+
return;
|
|
1983
|
+
}
|
|
1984
|
+
if (!attribute) {
|
|
1985
|
+
remove(key);
|
|
1986
|
+
}
|
|
1987
|
+
}, ctx),
|
|
1428
1988
|
// Remove dynamic zones from sort
|
|
1429
|
-
traverseQuerySort(visitor$5,
|
|
1989
|
+
traverseQuerySort(visitor$5, ctx),
|
|
1430
1990
|
// Remove morpTo relations from sort
|
|
1431
|
-
traverseQuerySort(visitor$6,
|
|
1991
|
+
traverseQuerySort(visitor$6, ctx),
|
|
1432
1992
|
// Remove private from sort
|
|
1433
|
-
traverseQuerySort(visitor$7,
|
|
1993
|
+
traverseQuerySort(visitor$7, ctx),
|
|
1434
1994
|
// Remove passwords from filters
|
|
1435
|
-
traverseQuerySort(visitor$8,
|
|
1995
|
+
traverseQuerySort(visitor$8, ctx),
|
|
1436
1996
|
// Remove keys for empty non-scalar values
|
|
1437
|
-
traverseQuerySort(
|
|
1438
|
-
(
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
},
|
|
1446
|
-
{ schema }
|
|
1447
|
-
)
|
|
1997
|
+
traverseQuerySort(({ key, attribute, value }, { remove }) => {
|
|
1998
|
+
if ([ID_ATTRIBUTE$2, DOC_ID_ATTRIBUTE$2].includes(key)) {
|
|
1999
|
+
return;
|
|
2000
|
+
}
|
|
2001
|
+
if (!isScalarAttribute(attribute) && fp.isEmpty(value)) {
|
|
2002
|
+
remove(key);
|
|
2003
|
+
}
|
|
2004
|
+
}, ctx)
|
|
1448
2005
|
)(sort2);
|
|
1449
2006
|
});
|
|
1450
|
-
const defaultSanitizeFields = fp.curry((
|
|
1451
|
-
if (!schema) {
|
|
2007
|
+
const defaultSanitizeFields = fp.curry((ctx, fields2) => {
|
|
2008
|
+
if (!ctx.schema) {
|
|
1452
2009
|
throw new Error("Missing schema in defaultSanitizeFields");
|
|
1453
2010
|
}
|
|
1454
2011
|
return pipe(
|
|
1455
2012
|
// Only keep scalar attributes
|
|
1456
|
-
traverseQueryFields(
|
|
1457
|
-
(
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
},
|
|
1465
|
-
{ schema }
|
|
1466
|
-
),
|
|
2013
|
+
traverseQueryFields(({ key, attribute }, { remove }) => {
|
|
2014
|
+
if ([ID_ATTRIBUTE$2, DOC_ID_ATTRIBUTE$2].includes(key)) {
|
|
2015
|
+
return;
|
|
2016
|
+
}
|
|
2017
|
+
if (fp.isNil(attribute) || !isScalarAttribute(attribute)) {
|
|
2018
|
+
remove(key);
|
|
2019
|
+
}
|
|
2020
|
+
}, ctx),
|
|
1467
2021
|
// Remove private fields
|
|
1468
|
-
traverseQueryFields(visitor$7,
|
|
2022
|
+
traverseQueryFields(visitor$7, ctx),
|
|
1469
2023
|
// Remove password fields
|
|
1470
|
-
traverseQueryFields(visitor$8,
|
|
2024
|
+
traverseQueryFields(visitor$8, ctx),
|
|
1471
2025
|
// Remove nil values from fields array
|
|
1472
2026
|
(value) => fp.isArray(value) ? value.filter((field) => !fp.isNil(field)) : value
|
|
1473
2027
|
)(fields2);
|
|
1474
2028
|
});
|
|
1475
|
-
const defaultSanitizePopulate = fp.curry((
|
|
1476
|
-
if (!schema) {
|
|
2029
|
+
const defaultSanitizePopulate = fp.curry((ctx, populate2) => {
|
|
2030
|
+
if (!ctx.schema) {
|
|
1477
2031
|
throw new Error("Missing schema in defaultSanitizePopulate");
|
|
1478
2032
|
}
|
|
1479
2033
|
return pipe(
|
|
1480
|
-
traverseQueryPopulate(visitor$4,
|
|
1481
|
-
traverseQueryPopulate(
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
},
|
|
1499
|
-
{ schema }
|
|
1500
|
-
),
|
|
2034
|
+
traverseQueryPopulate(visitor$4, ctx),
|
|
2035
|
+
traverseQueryPopulate(async ({ key, value, schema, attribute, getModel }, { set }) => {
|
|
2036
|
+
if (attribute) {
|
|
2037
|
+
return;
|
|
2038
|
+
}
|
|
2039
|
+
if (key === "sort") {
|
|
2040
|
+
set(key, await defaultSanitizeSort({ schema, getModel }, value));
|
|
2041
|
+
}
|
|
2042
|
+
if (key === "filters") {
|
|
2043
|
+
set(key, await defaultSanitizeFilters({ schema, getModel }, value));
|
|
2044
|
+
}
|
|
2045
|
+
if (key === "fields") {
|
|
2046
|
+
set(key, await defaultSanitizeFields({ schema, getModel }, value));
|
|
2047
|
+
}
|
|
2048
|
+
if (key === "populate") {
|
|
2049
|
+
set(key, await defaultSanitizePopulate({ schema, getModel }, value));
|
|
2050
|
+
}
|
|
2051
|
+
}, ctx),
|
|
1501
2052
|
// Remove private fields
|
|
1502
|
-
traverseQueryPopulate(visitor$7,
|
|
2053
|
+
traverseQueryPopulate(visitor$7, ctx)
|
|
1503
2054
|
)(populate2);
|
|
1504
2055
|
});
|
|
1505
2056
|
const sanitizers = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
@@ -1511,7 +2062,8 @@ const sanitizers = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
|
|
|
1511
2062
|
defaultSanitizeSort,
|
|
1512
2063
|
sanitizePasswords
|
|
1513
2064
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1514
|
-
const
|
|
2065
|
+
const createAPISanitizers = (opts) => {
|
|
2066
|
+
const { getModel } = opts;
|
|
1515
2067
|
const sanitizeInput = (data, schema, { auth } = {}) => {
|
|
1516
2068
|
if (!schema) {
|
|
1517
2069
|
throw new Error("Missing schema in sanitizeInput");
|
|
@@ -1525,12 +2077,14 @@ const createContentAPISanitizers = () => {
|
|
|
1525
2077
|
fp.omit(constants$1.ID_ATTRIBUTE),
|
|
1526
2078
|
fp.omit(constants$1.DOC_ID_ATTRIBUTE),
|
|
1527
2079
|
// Remove non-writable attributes
|
|
1528
|
-
traverseEntity$1(removeRestrictedFields(nonWritableAttributes), { schema })
|
|
2080
|
+
traverseEntity$1(removeRestrictedFields(nonWritableAttributes), { schema, getModel })
|
|
1529
2081
|
];
|
|
1530
2082
|
if (auth) {
|
|
1531
|
-
transforms.push(
|
|
2083
|
+
transforms.push(
|
|
2084
|
+
traverseEntity$1(removeRestrictedRelations(auth), { schema, getModel })
|
|
2085
|
+
);
|
|
1532
2086
|
}
|
|
1533
|
-
|
|
2087
|
+
opts?.sanitizers?.input?.forEach((sanitizer) => transforms.push(sanitizer(schema)));
|
|
1534
2088
|
return pipe(...transforms)(data);
|
|
1535
2089
|
};
|
|
1536
2090
|
const sanitizeOutput = async (data, schema, { auth } = {}) => {
|
|
@@ -1544,11 +2098,15 @@ const createContentAPISanitizers = () => {
|
|
|
1544
2098
|
}
|
|
1545
2099
|
return res;
|
|
1546
2100
|
}
|
|
1547
|
-
const transforms = [
|
|
2101
|
+
const transforms = [
|
|
2102
|
+
(data2) => defaultSanitizeOutput({ schema, getModel }, data2)
|
|
2103
|
+
];
|
|
1548
2104
|
if (auth) {
|
|
1549
|
-
transforms.push(
|
|
2105
|
+
transforms.push(
|
|
2106
|
+
traverseEntity$1(removeRestrictedRelations(auth), { schema, getModel })
|
|
2107
|
+
);
|
|
1550
2108
|
}
|
|
1551
|
-
|
|
2109
|
+
opts?.sanitizers?.output?.forEach((sanitizer) => transforms.push(sanitizer(schema)));
|
|
1552
2110
|
return pipe(...transforms)(data);
|
|
1553
2111
|
};
|
|
1554
2112
|
const sanitizeQuery = async (query, schema, { auth } = {}) => {
|
|
@@ -1578,9 +2136,11 @@ const createContentAPISanitizers = () => {
|
|
|
1578
2136
|
if (fp.isArray(filters2)) {
|
|
1579
2137
|
return Promise.all(filters2.map((filter) => sanitizeFilters(filter, schema, { auth })));
|
|
1580
2138
|
}
|
|
1581
|
-
const transforms = [defaultSanitizeFilters(schema)];
|
|
2139
|
+
const transforms = [defaultSanitizeFilters({ schema, getModel })];
|
|
1582
2140
|
if (auth) {
|
|
1583
|
-
transforms.push(
|
|
2141
|
+
transforms.push(
|
|
2142
|
+
traverseQueryFilters(removeRestrictedRelations(auth), { schema, getModel })
|
|
2143
|
+
);
|
|
1584
2144
|
}
|
|
1585
2145
|
return pipe(...transforms)(filters2);
|
|
1586
2146
|
};
|
|
@@ -1588,9 +2148,11 @@ const createContentAPISanitizers = () => {
|
|
|
1588
2148
|
if (!schema) {
|
|
1589
2149
|
throw new Error("Missing schema in sanitizeSort");
|
|
1590
2150
|
}
|
|
1591
|
-
const transforms = [defaultSanitizeSort(schema)];
|
|
2151
|
+
const transforms = [defaultSanitizeSort({ schema, getModel })];
|
|
1592
2152
|
if (auth) {
|
|
1593
|
-
transforms.push(
|
|
2153
|
+
transforms.push(
|
|
2154
|
+
traverseQuerySort(removeRestrictedRelations(auth), { schema, getModel })
|
|
2155
|
+
);
|
|
1594
2156
|
}
|
|
1595
2157
|
return pipe(...transforms)(sort2);
|
|
1596
2158
|
};
|
|
@@ -1598,16 +2160,18 @@ const createContentAPISanitizers = () => {
|
|
|
1598
2160
|
if (!schema) {
|
|
1599
2161
|
throw new Error("Missing schema in sanitizeFields");
|
|
1600
2162
|
}
|
|
1601
|
-
const transforms = [defaultSanitizeFields(schema)];
|
|
2163
|
+
const transforms = [defaultSanitizeFields({ schema, getModel })];
|
|
1602
2164
|
return pipe(...transforms)(fields2);
|
|
1603
2165
|
};
|
|
1604
2166
|
const sanitizePopulate = (populate2, schema, { auth } = {}) => {
|
|
1605
2167
|
if (!schema) {
|
|
1606
2168
|
throw new Error("Missing schema in sanitizePopulate");
|
|
1607
2169
|
}
|
|
1608
|
-
const transforms = [defaultSanitizePopulate(schema)];
|
|
2170
|
+
const transforms = [defaultSanitizePopulate({ schema, getModel })];
|
|
1609
2171
|
if (auth) {
|
|
1610
|
-
transforms.push(
|
|
2172
|
+
transforms.push(
|
|
2173
|
+
traverseQueryPopulate(removeRestrictedRelations(auth), { schema, getModel })
|
|
2174
|
+
);
|
|
1611
2175
|
}
|
|
1612
2176
|
return pipe(...transforms)(populate2);
|
|
1613
2177
|
};
|
|
@@ -1621,126 +2185,22 @@ const createContentAPISanitizers = () => {
|
|
|
1621
2185
|
populate: sanitizePopulate
|
|
1622
2186
|
};
|
|
1623
2187
|
};
|
|
1624
|
-
const
|
|
1625
|
-
const index$1 = {
|
|
1626
|
-
contentAPI: contentAPI$1,
|
|
1627
|
-
sanitizers,
|
|
1628
|
-
visitors: visitors$1
|
|
1629
|
-
};
|
|
1630
|
-
const formatYupInnerError = (yupError) => ({
|
|
1631
|
-
path: fp.toPath(yupError.path),
|
|
1632
|
-
message: yupError.message,
|
|
1633
|
-
name: yupError.name
|
|
1634
|
-
});
|
|
1635
|
-
const formatYupErrors = (yupError) => ({
|
|
1636
|
-
errors: fp.isEmpty(yupError.inner) ? [formatYupInnerError(yupError)] : yupError.inner.map(formatYupInnerError),
|
|
1637
|
-
message: yupError.message
|
|
1638
|
-
});
|
|
1639
|
-
class ApplicationError extends Error {
|
|
1640
|
-
name;
|
|
1641
|
-
details;
|
|
1642
|
-
message;
|
|
1643
|
-
constructor(message = "An application error occured", details = {}) {
|
|
1644
|
-
super();
|
|
1645
|
-
this.name = "ApplicationError";
|
|
1646
|
-
this.message = message;
|
|
1647
|
-
this.details = details;
|
|
1648
|
-
}
|
|
1649
|
-
}
|
|
1650
|
-
class ValidationError extends ApplicationError {
|
|
1651
|
-
constructor(message, details) {
|
|
1652
|
-
super(message, details);
|
|
1653
|
-
this.name = "ValidationError";
|
|
1654
|
-
}
|
|
1655
|
-
}
|
|
1656
|
-
class YupValidationError extends ValidationError {
|
|
1657
|
-
constructor(yupError, message) {
|
|
1658
|
-
super("Validation");
|
|
1659
|
-
const { errors: errors2, message: yupMessage } = formatYupErrors(yupError);
|
|
1660
|
-
this.message = message || yupMessage;
|
|
1661
|
-
this.details = { errors: errors2 };
|
|
1662
|
-
}
|
|
1663
|
-
}
|
|
1664
|
-
class PaginationError extends ApplicationError {
|
|
1665
|
-
constructor(message = "Invalid pagination", details) {
|
|
1666
|
-
super(message, details);
|
|
1667
|
-
this.name = "PaginationError";
|
|
1668
|
-
this.message = message;
|
|
1669
|
-
}
|
|
1670
|
-
}
|
|
1671
|
-
class NotFoundError extends ApplicationError {
|
|
1672
|
-
constructor(message = "Entity not found", details) {
|
|
1673
|
-
super(message, details);
|
|
1674
|
-
this.name = "NotFoundError";
|
|
1675
|
-
this.message = message;
|
|
1676
|
-
}
|
|
1677
|
-
}
|
|
1678
|
-
class ForbiddenError extends ApplicationError {
|
|
1679
|
-
constructor(message = "Forbidden access", details) {
|
|
1680
|
-
super(message, details);
|
|
1681
|
-
this.name = "ForbiddenError";
|
|
1682
|
-
this.message = message;
|
|
1683
|
-
}
|
|
1684
|
-
}
|
|
1685
|
-
class UnauthorizedError extends ApplicationError {
|
|
1686
|
-
constructor(message = "Unauthorized", details) {
|
|
1687
|
-
super(message, details);
|
|
1688
|
-
this.name = "UnauthorizedError";
|
|
1689
|
-
this.message = message;
|
|
1690
|
-
}
|
|
1691
|
-
}
|
|
1692
|
-
class RateLimitError extends ApplicationError {
|
|
1693
|
-
constructor(message = "Too many requests, please try again later.", details) {
|
|
1694
|
-
super(message, details);
|
|
1695
|
-
this.name = "RateLimitError";
|
|
1696
|
-
this.message = message;
|
|
1697
|
-
this.details = details || {};
|
|
1698
|
-
}
|
|
1699
|
-
}
|
|
1700
|
-
class PayloadTooLargeError extends ApplicationError {
|
|
1701
|
-
constructor(message = "Entity too large", details) {
|
|
1702
|
-
super(message, details);
|
|
1703
|
-
this.name = "PayloadTooLargeError";
|
|
1704
|
-
this.message = message;
|
|
1705
|
-
}
|
|
1706
|
-
}
|
|
1707
|
-
class PolicyError extends ForbiddenError {
|
|
1708
|
-
constructor(message = "Policy Failed", details) {
|
|
1709
|
-
super(message, details);
|
|
1710
|
-
this.name = "PolicyError";
|
|
1711
|
-
this.message = message;
|
|
1712
|
-
this.details = details || {};
|
|
1713
|
-
}
|
|
1714
|
-
}
|
|
1715
|
-
class NotImplementedError extends ApplicationError {
|
|
1716
|
-
constructor(message = "This feature is not implemented yet", details) {
|
|
1717
|
-
super(message, details);
|
|
1718
|
-
this.name = "NotImplementedError";
|
|
1719
|
-
this.message = message;
|
|
1720
|
-
}
|
|
1721
|
-
}
|
|
1722
|
-
const errors = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2188
|
+
const index$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1723
2189
|
__proto__: null,
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
NotFoundError,
|
|
1728
|
-
NotImplementedError,
|
|
1729
|
-
PaginationError,
|
|
1730
|
-
PayloadTooLargeError,
|
|
1731
|
-
PolicyError,
|
|
1732
|
-
RateLimitError,
|
|
1733
|
-
UnauthorizedError,
|
|
1734
|
-
ValidationError,
|
|
1735
|
-
YupValidationError
|
|
2190
|
+
createAPISanitizers,
|
|
2191
|
+
sanitizers,
|
|
2192
|
+
visitors: index$4
|
|
1736
2193
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1737
|
-
const
|
|
1738
|
-
const msg = path && path !== key ? `Invalid
|
|
1739
|
-
throw new ValidationError(msg
|
|
2194
|
+
const throwInvalidKey = ({ key, path }) => {
|
|
2195
|
+
const msg = path && path !== key ? `Invalid key ${key} at ${path}` : `Invalid key ${key}`;
|
|
2196
|
+
throw new ValidationError(msg, {
|
|
2197
|
+
key,
|
|
2198
|
+
path
|
|
2199
|
+
});
|
|
1740
2200
|
};
|
|
1741
2201
|
const visitor$3 = ({ key, attribute, path }) => {
|
|
1742
2202
|
if (attribute?.type === "password") {
|
|
1743
|
-
|
|
2203
|
+
throwInvalidKey({ key, path: path.attribute });
|
|
1744
2204
|
}
|
|
1745
2205
|
};
|
|
1746
2206
|
const visitor$2 = ({ schema, key, attribute, path }) => {
|
|
@@ -1749,7 +2209,7 @@ const visitor$2 = ({ schema, key, attribute, path }) => {
|
|
|
1749
2209
|
}
|
|
1750
2210
|
const isPrivate = attribute.private === true || isPrivateAttribute(schema, key);
|
|
1751
2211
|
if (isPrivate) {
|
|
1752
|
-
|
|
2212
|
+
throwInvalidKey({ key, path: path.attribute });
|
|
1753
2213
|
}
|
|
1754
2214
|
};
|
|
1755
2215
|
const ACTIONS_TO_VERIFY = ["find"];
|
|
@@ -1767,7 +2227,7 @@ const throwRestrictedRelations = (auth) => async ({ data, key, attribute, schema
|
|
|
1767
2227
|
const scopes = ACTIONS_TO_VERIFY.map((action) => `${element.__type}.${action}`);
|
|
1768
2228
|
const isAllowed = await hasAccessToSomeScopes(scopes, auth);
|
|
1769
2229
|
if (!isAllowed) {
|
|
1770
|
-
|
|
2230
|
+
throwInvalidKey({ key, path: path.attribute });
|
|
1771
2231
|
}
|
|
1772
2232
|
}
|
|
1773
2233
|
};
|
|
@@ -1775,7 +2235,7 @@ const throwRestrictedRelations = (auth) => async ({ data, key, attribute, schema
|
|
|
1775
2235
|
const scopes = ACTIONS_TO_VERIFY.map((action) => `${attribute.target}.${action}`);
|
|
1776
2236
|
const isAllowed = await hasAccessToSomeScopes(scopes, auth);
|
|
1777
2237
|
if (!isAllowed) {
|
|
1778
|
-
|
|
2238
|
+
throwInvalidKey({ key, path: path.attribute });
|
|
1779
2239
|
}
|
|
1780
2240
|
};
|
|
1781
2241
|
const isCreatorRelation = [CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE].includes(key);
|
|
@@ -1801,12 +2261,12 @@ const hasAccessToSomeScopes = async (scopes, auth) => {
|
|
|
1801
2261
|
};
|
|
1802
2262
|
const visitor$1 = ({ key, attribute, path }) => {
|
|
1803
2263
|
if (isMorphToRelationalAttribute(attribute)) {
|
|
1804
|
-
|
|
2264
|
+
throwInvalidKey({ key, path: path.attribute });
|
|
1805
2265
|
}
|
|
1806
2266
|
};
|
|
1807
2267
|
const visitor = ({ key, attribute, path }) => {
|
|
1808
2268
|
if (isDynamicZoneAttribute(attribute)) {
|
|
1809
|
-
|
|
2269
|
+
throwInvalidKey({ key, path: path.attribute });
|
|
1810
2270
|
}
|
|
1811
2271
|
};
|
|
1812
2272
|
const throwDisallowedFields = (allowedFields = null) => ({ key, path: { attribute: path } }) => {
|
|
@@ -1828,7 +2288,7 @@ const throwDisallowedFields = (allowedFields = null) => ({ key, path: { attribut
|
|
|
1828
2288
|
if (isPathAllowed) {
|
|
1829
2289
|
return;
|
|
1830
2290
|
}
|
|
1831
|
-
|
|
2291
|
+
throwInvalidKey({ key, path });
|
|
1832
2292
|
};
|
|
1833
2293
|
const getContainedPaths = (path) => {
|
|
1834
2294
|
const parts = fp.toPath(path);
|
|
@@ -1838,7 +2298,7 @@ const getContainedPaths = (path) => {
|
|
|
1838
2298
|
};
|
|
1839
2299
|
const throwRestrictedFields = (restrictedFields = null) => ({ key, path: { attribute: path } }) => {
|
|
1840
2300
|
if (restrictedFields === null) {
|
|
1841
|
-
|
|
2301
|
+
throwInvalidKey({ key, path });
|
|
1842
2302
|
}
|
|
1843
2303
|
if (!(fp.isArray(restrictedFields) && restrictedFields.every(fp.isString))) {
|
|
1844
2304
|
throw new TypeError(
|
|
@@ -1846,16 +2306,46 @@ const throwRestrictedFields = (restrictedFields = null) => ({ key, path: { attri
|
|
|
1846
2306
|
);
|
|
1847
2307
|
}
|
|
1848
2308
|
if (restrictedFields.includes(path)) {
|
|
1849
|
-
|
|
2309
|
+
throwInvalidKey({ key, path });
|
|
1850
2310
|
}
|
|
1851
2311
|
const isRestrictedNested = restrictedFields.some(
|
|
1852
2312
|
(allowedPath) => path?.toString().startsWith(`${allowedPath}.`)
|
|
1853
2313
|
);
|
|
1854
2314
|
if (isRestrictedNested) {
|
|
1855
|
-
|
|
2315
|
+
throwInvalidKey({ key, path });
|
|
2316
|
+
}
|
|
2317
|
+
};
|
|
2318
|
+
const ID_FIELDS = [constants$1.DOC_ID_ATTRIBUTE, constants$1.DOC_ID_ATTRIBUTE];
|
|
2319
|
+
const ALLOWED_ROOT_LEVEL_FIELDS = [...ID_FIELDS];
|
|
2320
|
+
const MORPH_TO_ALLOWED_FIELDS = ["__type"];
|
|
2321
|
+
const DYNAMIC_ZONE_ALLOWED_FIELDS = ["__component"];
|
|
2322
|
+
const RELATION_REORDERING_FIELDS = ["connect", "disconnect", "set", "options"];
|
|
2323
|
+
const throwUnrecognizedFields = ({ key, attribute, path, schema, parent }) => {
|
|
2324
|
+
if (attribute) {
|
|
2325
|
+
return;
|
|
2326
|
+
}
|
|
2327
|
+
if (path.attribute === null) {
|
|
2328
|
+
if (ALLOWED_ROOT_LEVEL_FIELDS.includes(key)) {
|
|
2329
|
+
return;
|
|
2330
|
+
}
|
|
2331
|
+
return throwInvalidKey({ key, path: attribute });
|
|
2332
|
+
}
|
|
2333
|
+
if (isMorphToRelationalAttribute(parent?.attribute) && MORPH_TO_ALLOWED_FIELDS.includes(key)) {
|
|
2334
|
+
return;
|
|
2335
|
+
}
|
|
2336
|
+
if (isComponentSchema(schema) && isDynamicZoneAttribute(parent?.attribute) && DYNAMIC_ZONE_ALLOWED_FIELDS.includes(key)) {
|
|
2337
|
+
return;
|
|
2338
|
+
}
|
|
2339
|
+
if (hasRelationReordering(parent?.attribute) && RELATION_REORDERING_FIELDS.includes(key)) {
|
|
2340
|
+
return;
|
|
2341
|
+
}
|
|
2342
|
+
const canUseID = isRelationalAttribute(parent?.attribute) || isMediaAttribute(parent?.attribute);
|
|
2343
|
+
if (canUseID && !ID_FIELDS.includes(key)) {
|
|
2344
|
+
return;
|
|
1856
2345
|
}
|
|
2346
|
+
throwInvalidKey({ key, path: attribute });
|
|
1857
2347
|
};
|
|
1858
|
-
const
|
|
2348
|
+
const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1859
2349
|
__proto__: null,
|
|
1860
2350
|
throwDisallowedFields,
|
|
1861
2351
|
throwDynamicZones: visitor,
|
|
@@ -1863,133 +2353,155 @@ const visitors = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProp
|
|
|
1863
2353
|
throwPassword: visitor$3,
|
|
1864
2354
|
throwPrivate: visitor$2,
|
|
1865
2355
|
throwRestrictedFields,
|
|
1866
|
-
throwRestrictedRelations
|
|
2356
|
+
throwRestrictedRelations,
|
|
2357
|
+
throwUnrecognizedFields
|
|
1867
2358
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1868
|
-
const { ID_ATTRIBUTE: ID_ATTRIBUTE$
|
|
1869
|
-
const throwPasswords = (
|
|
1870
|
-
if (!schema) {
|
|
2359
|
+
const { ID_ATTRIBUTE: ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE: DOC_ID_ATTRIBUTE$1 } = constants$1;
|
|
2360
|
+
const throwPasswords = (ctx) => async (entity) => {
|
|
2361
|
+
if (!ctx.schema) {
|
|
1871
2362
|
throw new Error("Missing schema in throwPasswords");
|
|
1872
2363
|
}
|
|
1873
|
-
return traverseEntity$1(visitor$3,
|
|
2364
|
+
return traverseEntity$1(visitor$3, ctx, entity);
|
|
1874
2365
|
};
|
|
1875
|
-
const defaultValidateFilters = fp.curry((
|
|
1876
|
-
if (!schema) {
|
|
2366
|
+
const defaultValidateFilters = fp.curry((ctx, filters2) => {
|
|
2367
|
+
if (!ctx.schema) {
|
|
1877
2368
|
throw new Error("Missing schema in defaultValidateFilters");
|
|
1878
2369
|
}
|
|
1879
2370
|
return pipe(
|
|
1880
2371
|
// keys that are not attributes or valid operators
|
|
1881
|
-
traverseQueryFilters(
|
|
1882
|
-
(
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
},
|
|
1891
|
-
{ schema }
|
|
1892
|
-
),
|
|
2372
|
+
traverseQueryFilters(({ key, attribute, path }) => {
|
|
2373
|
+
if ([ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE$1].includes(key)) {
|
|
2374
|
+
return;
|
|
2375
|
+
}
|
|
2376
|
+
const isAttribute = !!attribute;
|
|
2377
|
+
if (!isAttribute && !isOperator(key)) {
|
|
2378
|
+
throwInvalidKey({ key, path: path.attribute });
|
|
2379
|
+
}
|
|
2380
|
+
}, ctx),
|
|
1893
2381
|
// dynamic zones from filters
|
|
1894
|
-
traverseQueryFilters(visitor,
|
|
2382
|
+
traverseQueryFilters(visitor, ctx),
|
|
1895
2383
|
// morphTo relations from filters; because you can't have deep filtering on morph relations
|
|
1896
|
-
traverseQueryFilters(visitor$1,
|
|
2384
|
+
traverseQueryFilters(visitor$1, ctx),
|
|
1897
2385
|
// passwords from filters
|
|
1898
|
-
traverseQueryFilters(visitor$3,
|
|
2386
|
+
traverseQueryFilters(visitor$3, ctx),
|
|
1899
2387
|
// private from filters
|
|
1900
|
-
traverseQueryFilters(visitor$2,
|
|
2388
|
+
traverseQueryFilters(visitor$2, ctx)
|
|
1901
2389
|
// we allow empty objects to validate and only sanitize them out, so that users may write "lazy" queries without checking their params exist
|
|
1902
2390
|
)(filters2);
|
|
1903
2391
|
});
|
|
1904
|
-
const defaultValidateSort = fp.curry((
|
|
1905
|
-
if (!schema) {
|
|
2392
|
+
const defaultValidateSort = fp.curry((ctx, sort2) => {
|
|
2393
|
+
if (!ctx.schema) {
|
|
1906
2394
|
throw new Error("Missing schema in defaultValidateSort");
|
|
1907
2395
|
}
|
|
1908
2396
|
return pipe(
|
|
1909
2397
|
// non attribute keys
|
|
1910
|
-
traverseQuerySort(
|
|
1911
|
-
(
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
},
|
|
1919
|
-
{ schema }
|
|
1920
|
-
),
|
|
2398
|
+
traverseQuerySort(({ key, attribute, path }) => {
|
|
2399
|
+
if ([ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE$1].includes(key)) {
|
|
2400
|
+
return;
|
|
2401
|
+
}
|
|
2402
|
+
if (!attribute) {
|
|
2403
|
+
throwInvalidKey({ key, path: path.attribute });
|
|
2404
|
+
}
|
|
2405
|
+
}, ctx),
|
|
1921
2406
|
// dynamic zones from sort
|
|
1922
|
-
traverseQuerySort(visitor,
|
|
2407
|
+
traverseQuerySort(visitor, ctx),
|
|
1923
2408
|
// morphTo relations from sort
|
|
1924
|
-
traverseQuerySort(visitor$1,
|
|
2409
|
+
traverseQuerySort(visitor$1, ctx),
|
|
1925
2410
|
// private from sort
|
|
1926
|
-
traverseQuerySort(visitor$2,
|
|
2411
|
+
traverseQuerySort(visitor$2, ctx),
|
|
1927
2412
|
// passwords from filters
|
|
1928
|
-
traverseQuerySort(visitor$3,
|
|
2413
|
+
traverseQuerySort(visitor$3, ctx),
|
|
1929
2414
|
// keys for empty non-scalar values
|
|
1930
|
-
traverseQuerySort(
|
|
1931
|
-
(
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
},
|
|
1939
|
-
{ schema }
|
|
1940
|
-
)
|
|
2415
|
+
traverseQuerySort(({ key, attribute, value, path }) => {
|
|
2416
|
+
if ([ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE$1].includes(key)) {
|
|
2417
|
+
return;
|
|
2418
|
+
}
|
|
2419
|
+
if (!isScalarAttribute(attribute) && fp.isEmpty(value)) {
|
|
2420
|
+
throwInvalidKey({ key, path: path.attribute });
|
|
2421
|
+
}
|
|
2422
|
+
}, ctx)
|
|
1941
2423
|
)(sort2);
|
|
1942
2424
|
});
|
|
1943
|
-
const defaultValidateFields = fp.curry((
|
|
1944
|
-
if (!schema) {
|
|
2425
|
+
const defaultValidateFields = fp.curry((ctx, fields2) => {
|
|
2426
|
+
if (!ctx.schema) {
|
|
1945
2427
|
throw new Error("Missing schema in defaultValidateFields");
|
|
1946
2428
|
}
|
|
1947
2429
|
return pipe(
|
|
1948
2430
|
// Only allow scalar attributes
|
|
1949
|
-
traverseQueryFields(
|
|
1950
|
-
(
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
},
|
|
1958
|
-
{ schema }
|
|
1959
|
-
),
|
|
2431
|
+
traverseQueryFields(({ key, attribute, path }) => {
|
|
2432
|
+
if ([ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE$1].includes(key)) {
|
|
2433
|
+
return;
|
|
2434
|
+
}
|
|
2435
|
+
if (fp.isNil(attribute) || !isScalarAttribute(attribute)) {
|
|
2436
|
+
throwInvalidKey({ key, path: path.attribute });
|
|
2437
|
+
}
|
|
2438
|
+
}, ctx),
|
|
1960
2439
|
// private fields
|
|
1961
|
-
traverseQueryFields(visitor$2,
|
|
2440
|
+
traverseQueryFields(visitor$2, ctx),
|
|
1962
2441
|
// password fields
|
|
1963
|
-
traverseQueryFields(visitor$3,
|
|
2442
|
+
traverseQueryFields(visitor$3, ctx)
|
|
1964
2443
|
)(fields2);
|
|
1965
2444
|
});
|
|
1966
|
-
const defaultValidatePopulate = fp.curry((
|
|
1967
|
-
if (!schema) {
|
|
2445
|
+
const defaultValidatePopulate = fp.curry((ctx, populate2) => {
|
|
2446
|
+
if (!ctx.schema) {
|
|
1968
2447
|
throw new Error("Missing schema in defaultValidatePopulate");
|
|
1969
2448
|
}
|
|
1970
2449
|
return pipe(
|
|
1971
|
-
traverseQueryPopulate(
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
2450
|
+
traverseQueryPopulate(async ({ key, value, schema, attribute, getModel }, { set }) => {
|
|
2451
|
+
if (attribute) {
|
|
2452
|
+
return;
|
|
2453
|
+
}
|
|
2454
|
+
if (key === "sort") {
|
|
2455
|
+
set(
|
|
2456
|
+
key,
|
|
2457
|
+
await defaultValidateSort(
|
|
2458
|
+
{
|
|
2459
|
+
schema,
|
|
2460
|
+
getModel
|
|
2461
|
+
},
|
|
2462
|
+
value
|
|
2463
|
+
)
|
|
2464
|
+
);
|
|
2465
|
+
}
|
|
2466
|
+
if (key === "filters") {
|
|
2467
|
+
set(
|
|
2468
|
+
key,
|
|
2469
|
+
await defaultValidateFilters(
|
|
2470
|
+
{
|
|
2471
|
+
schema,
|
|
2472
|
+
getModel
|
|
2473
|
+
},
|
|
2474
|
+
value
|
|
2475
|
+
)
|
|
2476
|
+
);
|
|
2477
|
+
}
|
|
2478
|
+
if (key === "fields") {
|
|
2479
|
+
set(
|
|
2480
|
+
key,
|
|
2481
|
+
await defaultValidateFields(
|
|
2482
|
+
{
|
|
2483
|
+
schema,
|
|
2484
|
+
getModel
|
|
2485
|
+
},
|
|
2486
|
+
value
|
|
2487
|
+
)
|
|
2488
|
+
);
|
|
2489
|
+
}
|
|
2490
|
+
if (key === "populate") {
|
|
2491
|
+
set(
|
|
2492
|
+
key,
|
|
2493
|
+
await defaultValidatePopulate(
|
|
2494
|
+
{
|
|
2495
|
+
schema,
|
|
2496
|
+
getModel
|
|
2497
|
+
},
|
|
2498
|
+
value
|
|
2499
|
+
)
|
|
2500
|
+
);
|
|
2501
|
+
}
|
|
2502
|
+
}, ctx),
|
|
1991
2503
|
// Remove private fields
|
|
1992
|
-
traverseQueryPopulate(visitor$2,
|
|
2504
|
+
traverseQueryPopulate(visitor$2, ctx)
|
|
1993
2505
|
)(populate2);
|
|
1994
2506
|
});
|
|
1995
2507
|
const validators = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
@@ -2000,8 +2512,9 @@ const validators = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
|
|
|
2000
2512
|
defaultValidateSort,
|
|
2001
2513
|
throwPasswords
|
|
2002
2514
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2003
|
-
const { ID_ATTRIBUTE
|
|
2004
|
-
const
|
|
2515
|
+
const { ID_ATTRIBUTE, DOC_ID_ATTRIBUTE } = constants$1;
|
|
2516
|
+
const createAPIValidators = (opts) => {
|
|
2517
|
+
const { getModel } = opts || {};
|
|
2005
2518
|
const validateInput = async (data, schema, { auth } = {}) => {
|
|
2006
2519
|
if (!schema) {
|
|
2007
2520
|
throw new Error("Missing schema in validateInput");
|
|
@@ -2014,22 +2527,37 @@ const createContentAPIValidators = () => {
|
|
|
2014
2527
|
const transforms = [
|
|
2015
2528
|
(data2) => {
|
|
2016
2529
|
if (fp.isObject(data2)) {
|
|
2017
|
-
if (ID_ATTRIBUTE
|
|
2018
|
-
|
|
2530
|
+
if (ID_ATTRIBUTE in data2) {
|
|
2531
|
+
throwInvalidKey({ key: ID_ATTRIBUTE });
|
|
2019
2532
|
}
|
|
2020
|
-
if (DOC_ID_ATTRIBUTE
|
|
2021
|
-
|
|
2533
|
+
if (DOC_ID_ATTRIBUTE in data2) {
|
|
2534
|
+
throwInvalidKey({ key: DOC_ID_ATTRIBUTE });
|
|
2022
2535
|
}
|
|
2023
2536
|
}
|
|
2537
|
+
return data2;
|
|
2024
2538
|
},
|
|
2025
2539
|
// non-writable attributes
|
|
2026
|
-
traverseEntity$1(throwRestrictedFields(nonWritableAttributes), { schema })
|
|
2540
|
+
traverseEntity$1(throwRestrictedFields(nonWritableAttributes), { schema, getModel }),
|
|
2541
|
+
// unrecognized attributes
|
|
2542
|
+
traverseEntity$1(throwUnrecognizedFields, { schema, getModel })
|
|
2027
2543
|
];
|
|
2028
2544
|
if (auth) {
|
|
2029
|
-
transforms.push(
|
|
2545
|
+
transforms.push(
|
|
2546
|
+
traverseEntity$1(throwRestrictedRelations(auth), {
|
|
2547
|
+
schema,
|
|
2548
|
+
getModel
|
|
2549
|
+
})
|
|
2550
|
+
);
|
|
2551
|
+
}
|
|
2552
|
+
opts?.validators?.input?.forEach((validator) => transforms.push(validator(schema)));
|
|
2553
|
+
try {
|
|
2554
|
+
await pipe(...transforms)(data);
|
|
2555
|
+
} catch (e) {
|
|
2556
|
+
if (e instanceof ValidationError) {
|
|
2557
|
+
e.details.source = "body";
|
|
2558
|
+
}
|
|
2559
|
+
throw e;
|
|
2030
2560
|
}
|
|
2031
|
-
strapi.validators.get("content-api.input").forEach((validator) => transforms.push(validator(schema)));
|
|
2032
|
-
await pipe(...transforms)(data);
|
|
2033
2561
|
};
|
|
2034
2562
|
const validateQuery = async (query, schema, { auth } = {}) => {
|
|
2035
2563
|
if (!schema) {
|
|
@@ -2057,38 +2585,85 @@ const createContentAPIValidators = () => {
|
|
|
2057
2585
|
await Promise.all(filters2.map((filter) => validateFilters(filter, schema, { auth })));
|
|
2058
2586
|
return;
|
|
2059
2587
|
}
|
|
2060
|
-
const transforms = [defaultValidateFilters(schema)];
|
|
2588
|
+
const transforms = [defaultValidateFilters({ schema, getModel })];
|
|
2061
2589
|
if (auth) {
|
|
2062
|
-
transforms.push(
|
|
2590
|
+
transforms.push(
|
|
2591
|
+
traverseQueryFilters(throwRestrictedRelations(auth), {
|
|
2592
|
+
schema,
|
|
2593
|
+
getModel
|
|
2594
|
+
})
|
|
2595
|
+
);
|
|
2596
|
+
}
|
|
2597
|
+
try {
|
|
2598
|
+
await pipe(...transforms)(filters2);
|
|
2599
|
+
} catch (e) {
|
|
2600
|
+
if (e instanceof ValidationError) {
|
|
2601
|
+
e.details.source = "query";
|
|
2602
|
+
e.details.param = "filters";
|
|
2603
|
+
}
|
|
2604
|
+
throw e;
|
|
2063
2605
|
}
|
|
2064
|
-
await pipe(...transforms)(filters2);
|
|
2065
2606
|
};
|
|
2066
2607
|
const validateSort = async (sort2, schema, { auth } = {}) => {
|
|
2067
2608
|
if (!schema) {
|
|
2068
2609
|
throw new Error("Missing schema in validateSort");
|
|
2069
2610
|
}
|
|
2070
|
-
const transforms = [defaultValidateSort(schema)];
|
|
2611
|
+
const transforms = [defaultValidateSort({ schema, getModel })];
|
|
2071
2612
|
if (auth) {
|
|
2072
|
-
transforms.push(
|
|
2613
|
+
transforms.push(
|
|
2614
|
+
traverseQuerySort(throwRestrictedRelations(auth), {
|
|
2615
|
+
schema,
|
|
2616
|
+
getModel
|
|
2617
|
+
})
|
|
2618
|
+
);
|
|
2619
|
+
}
|
|
2620
|
+
try {
|
|
2621
|
+
await pipe(...transforms)(sort2);
|
|
2622
|
+
} catch (e) {
|
|
2623
|
+
if (e instanceof ValidationError) {
|
|
2624
|
+
e.details.source = "query";
|
|
2625
|
+
e.details.param = "sort";
|
|
2626
|
+
}
|
|
2627
|
+
throw e;
|
|
2073
2628
|
}
|
|
2074
|
-
await pipe(...transforms)(sort2);
|
|
2075
2629
|
};
|
|
2076
2630
|
const validateFields = async (fields2, schema) => {
|
|
2077
2631
|
if (!schema) {
|
|
2078
2632
|
throw new Error("Missing schema in validateFields");
|
|
2079
2633
|
}
|
|
2080
|
-
const transforms = [defaultValidateFields(schema)];
|
|
2081
|
-
|
|
2634
|
+
const transforms = [defaultValidateFields({ schema, getModel })];
|
|
2635
|
+
try {
|
|
2636
|
+
await pipe(...transforms)(fields2);
|
|
2637
|
+
} catch (e) {
|
|
2638
|
+
if (e instanceof ValidationError) {
|
|
2639
|
+
e.details.source = "query";
|
|
2640
|
+
e.details.param = "fields";
|
|
2641
|
+
}
|
|
2642
|
+
throw e;
|
|
2643
|
+
}
|
|
2082
2644
|
};
|
|
2083
2645
|
const validatePopulate = async (populate2, schema, { auth } = {}) => {
|
|
2084
2646
|
if (!schema) {
|
|
2085
2647
|
throw new Error("Missing schema in sanitizePopulate");
|
|
2086
2648
|
}
|
|
2087
|
-
const transforms = [defaultValidatePopulate(schema)];
|
|
2649
|
+
const transforms = [defaultValidatePopulate({ schema, getModel })];
|
|
2088
2650
|
if (auth) {
|
|
2089
|
-
transforms.push(
|
|
2651
|
+
transforms.push(
|
|
2652
|
+
traverseQueryPopulate(throwRestrictedRelations(auth), {
|
|
2653
|
+
schema,
|
|
2654
|
+
getModel
|
|
2655
|
+
})
|
|
2656
|
+
);
|
|
2657
|
+
}
|
|
2658
|
+
try {
|
|
2659
|
+
await pipe(...transforms)(populate2);
|
|
2660
|
+
} catch (e) {
|
|
2661
|
+
if (e instanceof ValidationError) {
|
|
2662
|
+
e.details.source = "query";
|
|
2663
|
+
e.details.param = "populate";
|
|
2664
|
+
}
|
|
2665
|
+
throw e;
|
|
2090
2666
|
}
|
|
2091
|
-
await pipe(...transforms)(populate2);
|
|
2092
2667
|
};
|
|
2093
2668
|
return {
|
|
2094
2669
|
input: validateInput,
|
|
@@ -2099,436 +2674,12 @@ const createContentAPIValidators = () => {
|
|
|
2099
2674
|
populate: validatePopulate
|
|
2100
2675
|
};
|
|
2101
2676
|
};
|
|
2102
|
-
const
|
|
2103
|
-
|
|
2104
|
-
|
|
2677
|
+
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2678
|
+
__proto__: null,
|
|
2679
|
+
createAPIValidators,
|
|
2105
2680
|
validators,
|
|
2106
|
-
visitors
|
|
2107
|
-
};
|
|
2108
|
-
const { ID_ATTRIBUTE, DOC_ID_ATTRIBUTE, PUBLISHED_AT_ATTRIBUTE } = constants$1;
|
|
2109
|
-
class InvalidOrderError extends Error {
|
|
2110
|
-
constructor() {
|
|
2111
|
-
super();
|
|
2112
|
-
this.message = "Invalid order. order can only be one of asc|desc|ASC|DESC";
|
|
2113
|
-
}
|
|
2114
|
-
}
|
|
2115
|
-
class InvalidSortError extends Error {
|
|
2116
|
-
constructor() {
|
|
2117
|
-
super();
|
|
2118
|
-
this.message = "Invalid sort parameter. Expected a string, an array of strings, a sort object or an array of sort objects";
|
|
2119
|
-
}
|
|
2120
|
-
}
|
|
2121
|
-
function validateOrder(order) {
|
|
2122
|
-
if (!fp.isString(order) || !["asc", "desc"].includes(order.toLocaleLowerCase())) {
|
|
2123
|
-
throw new InvalidOrderError();
|
|
2124
|
-
}
|
|
2125
|
-
}
|
|
2126
|
-
const convertCountQueryParams = (countQuery) => {
|
|
2127
|
-
return parseType({ type: "boolean", value: countQuery });
|
|
2128
|
-
};
|
|
2129
|
-
const convertOrderingQueryParams = (ordering) => {
|
|
2130
|
-
return ordering;
|
|
2131
|
-
};
|
|
2132
|
-
const isPlainObject = (value) => ___default.default.isPlainObject(value);
|
|
2133
|
-
const isStringArray = (value) => fp.isArray(value) && value.every(fp.isString);
|
|
2134
|
-
const convertSortQueryParams = (sortQuery) => {
|
|
2135
|
-
if (typeof sortQuery === "string") {
|
|
2136
|
-
return convertStringSortQueryParam(sortQuery);
|
|
2137
|
-
}
|
|
2138
|
-
if (isStringArray(sortQuery)) {
|
|
2139
|
-
return sortQuery.flatMap((sortValue) => convertStringSortQueryParam(sortValue));
|
|
2140
|
-
}
|
|
2141
|
-
if (Array.isArray(sortQuery)) {
|
|
2142
|
-
return sortQuery.map((sortValue) => convertNestedSortQueryParam(sortValue));
|
|
2143
|
-
}
|
|
2144
|
-
if (isPlainObject(sortQuery)) {
|
|
2145
|
-
return convertNestedSortQueryParam(sortQuery);
|
|
2146
|
-
}
|
|
2147
|
-
throw new InvalidSortError();
|
|
2148
|
-
};
|
|
2149
|
-
const convertStringSortQueryParam = (sortQuery) => {
|
|
2150
|
-
return sortQuery.split(",").map((value) => convertSingleSortQueryParam(value));
|
|
2151
|
-
};
|
|
2152
|
-
const convertSingleSortQueryParam = (sortQuery) => {
|
|
2153
|
-
if (!sortQuery) {
|
|
2154
|
-
return {};
|
|
2155
|
-
}
|
|
2156
|
-
if (!fp.isString(sortQuery)) {
|
|
2157
|
-
throw new Error("Invalid sort query");
|
|
2158
|
-
}
|
|
2159
|
-
const [field, order = "asc"] = sortQuery.split(":");
|
|
2160
|
-
if (field.length === 0) {
|
|
2161
|
-
throw new Error("Field cannot be empty");
|
|
2162
|
-
}
|
|
2163
|
-
validateOrder(order);
|
|
2164
|
-
return ___default.default.set({}, field, order);
|
|
2165
|
-
};
|
|
2166
|
-
const convertNestedSortQueryParam = (sortQuery) => {
|
|
2167
|
-
const transformedSort = {};
|
|
2168
|
-
for (const field of Object.keys(sortQuery)) {
|
|
2169
|
-
const order = sortQuery[field];
|
|
2170
|
-
if (isPlainObject(order)) {
|
|
2171
|
-
transformedSort[field] = convertNestedSortQueryParam(order);
|
|
2172
|
-
} else if (typeof order === "string") {
|
|
2173
|
-
validateOrder(order);
|
|
2174
|
-
transformedSort[field] = order;
|
|
2175
|
-
} else {
|
|
2176
|
-
throw Error(`Invalid sort type expected object or string got ${typeof order}`);
|
|
2177
|
-
}
|
|
2178
|
-
}
|
|
2179
|
-
return transformedSort;
|
|
2180
|
-
};
|
|
2181
|
-
const convertStartQueryParams = (startQuery) => {
|
|
2182
|
-
const startAsANumber = ___default.default.toNumber(startQuery);
|
|
2183
|
-
if (!___default.default.isInteger(startAsANumber) || startAsANumber < 0) {
|
|
2184
|
-
throw new Error(`convertStartQueryParams expected a positive integer got ${startAsANumber}`);
|
|
2185
|
-
}
|
|
2186
|
-
return startAsANumber;
|
|
2187
|
-
};
|
|
2188
|
-
const convertLimitQueryParams = (limitQuery) => {
|
|
2189
|
-
const limitAsANumber = ___default.default.toNumber(limitQuery);
|
|
2190
|
-
if (!___default.default.isInteger(limitAsANumber) || limitAsANumber !== -1 && limitAsANumber < 0) {
|
|
2191
|
-
throw new Error(`convertLimitQueryParams expected a positive integer got ${limitAsANumber}`);
|
|
2192
|
-
}
|
|
2193
|
-
if (limitAsANumber === -1) {
|
|
2194
|
-
return void 0;
|
|
2195
|
-
}
|
|
2196
|
-
return limitAsANumber;
|
|
2197
|
-
};
|
|
2198
|
-
const convertPageQueryParams = (page) => {
|
|
2199
|
-
const pageVal = fp.toNumber(page);
|
|
2200
|
-
if (!fp.isInteger(pageVal) || pageVal <= 0) {
|
|
2201
|
-
throw new PaginationError(
|
|
2202
|
-
`Invalid 'page' parameter. Expected an integer > 0, received: ${page}`
|
|
2203
|
-
);
|
|
2204
|
-
}
|
|
2205
|
-
return pageVal;
|
|
2206
|
-
};
|
|
2207
|
-
const convertPageSizeQueryParams = (pageSize, page) => {
|
|
2208
|
-
const pageSizeVal = fp.toNumber(pageSize);
|
|
2209
|
-
if (!fp.isInteger(pageSizeVal) || pageSizeVal <= 0) {
|
|
2210
|
-
throw new PaginationError(
|
|
2211
|
-
`Invalid 'pageSize' parameter. Expected an integer > 0, received: ${page}`
|
|
2212
|
-
);
|
|
2213
|
-
}
|
|
2214
|
-
return pageSizeVal;
|
|
2215
|
-
};
|
|
2216
|
-
const validatePaginationParams = (page, pageSize, start, limit) => {
|
|
2217
|
-
const isPagePagination = !fp.isNil(page) || !fp.isNil(pageSize);
|
|
2218
|
-
const isOffsetPagination = !fp.isNil(start) || !fp.isNil(limit);
|
|
2219
|
-
if (isPagePagination && isOffsetPagination) {
|
|
2220
|
-
throw new PaginationError(
|
|
2221
|
-
"Invalid pagination attributes. You cannot use page and offset pagination in the same query"
|
|
2222
|
-
);
|
|
2223
|
-
}
|
|
2224
|
-
};
|
|
2225
|
-
class InvalidPopulateError extends Error {
|
|
2226
|
-
constructor() {
|
|
2227
|
-
super();
|
|
2228
|
-
this.message = "Invalid populate parameter. Expected a string, an array of strings, a populate object";
|
|
2229
|
-
}
|
|
2230
|
-
}
|
|
2231
|
-
const convertPopulateQueryParams = (populate2, schema, depth = 0) => {
|
|
2232
|
-
if (depth === 0 && populate2 === "*") {
|
|
2233
|
-
return true;
|
|
2234
|
-
}
|
|
2235
|
-
if (typeof populate2 === "string") {
|
|
2236
|
-
return populate2.split(",").map((value) => ___default.default.trim(value));
|
|
2237
|
-
}
|
|
2238
|
-
if (Array.isArray(populate2)) {
|
|
2239
|
-
return ___default.default.uniq(
|
|
2240
|
-
populate2.flatMap((value) => {
|
|
2241
|
-
if (typeof value !== "string") {
|
|
2242
|
-
throw new InvalidPopulateError();
|
|
2243
|
-
}
|
|
2244
|
-
return value.split(",").map((value2) => ___default.default.trim(value2));
|
|
2245
|
-
})
|
|
2246
|
-
);
|
|
2247
|
-
}
|
|
2248
|
-
if (___default.default.isPlainObject(populate2)) {
|
|
2249
|
-
return convertPopulateObject(populate2, schema);
|
|
2250
|
-
}
|
|
2251
|
-
throw new InvalidPopulateError();
|
|
2252
|
-
};
|
|
2253
|
-
const hasFragmentPopulateDefined = (populate2) => {
|
|
2254
|
-
return typeof populate2 === "object" && "on" in populate2 && !fp.isNil(populate2.on);
|
|
2255
|
-
};
|
|
2256
|
-
const convertPopulateObject = (populate2, schema) => {
|
|
2257
|
-
if (!schema) {
|
|
2258
|
-
return {};
|
|
2259
|
-
}
|
|
2260
|
-
const { attributes } = schema;
|
|
2261
|
-
return Object.entries(populate2).reduce((acc, [key, subPopulate]) => {
|
|
2262
|
-
if (___default.default.isBoolean(subPopulate)) {
|
|
2263
|
-
return { ...acc, [key]: subPopulate };
|
|
2264
|
-
}
|
|
2265
|
-
const attribute = attributes[key];
|
|
2266
|
-
if (!attribute) {
|
|
2267
|
-
return acc;
|
|
2268
|
-
}
|
|
2269
|
-
const isAllowedAttributeForFragmentPopulate = isDynamicZoneAttribute(attribute) || isMorphToRelationalAttribute(attribute);
|
|
2270
|
-
if (isAllowedAttributeForFragmentPopulate && hasFragmentPopulateDefined(subPopulate)) {
|
|
2271
|
-
return {
|
|
2272
|
-
...acc,
|
|
2273
|
-
[key]: {
|
|
2274
|
-
on: Object.entries(subPopulate.on).reduce(
|
|
2275
|
-
(acc2, [type, typeSubPopulate]) => ({
|
|
2276
|
-
...acc2,
|
|
2277
|
-
[type]: convertNestedPopulate(typeSubPopulate, strapi.getModel(type))
|
|
2278
|
-
}),
|
|
2279
|
-
{}
|
|
2280
|
-
)
|
|
2281
|
-
}
|
|
2282
|
-
};
|
|
2283
|
-
}
|
|
2284
|
-
if (isDynamicZoneAttribute(attribute)) {
|
|
2285
|
-
const populates = attribute.components.map((uid) => strapi.getModel(uid)).map((schema2) => convertNestedPopulate(subPopulate, schema2)).map((populate22) => populate22 === true ? {} : populate22).filter((populate22) => populate22 !== false);
|
|
2286
|
-
if (fp.isEmpty(populates)) {
|
|
2287
|
-
return acc;
|
|
2288
|
-
}
|
|
2289
|
-
return {
|
|
2290
|
-
...acc,
|
|
2291
|
-
[key]: fp.mergeAll(populates)
|
|
2292
|
-
};
|
|
2293
|
-
}
|
|
2294
|
-
if (isMorphToRelationalAttribute(attribute)) {
|
|
2295
|
-
return { ...acc, [key]: convertNestedPopulate(subPopulate, void 0) };
|
|
2296
|
-
}
|
|
2297
|
-
let targetSchemaUID;
|
|
2298
|
-
if (attribute.type === "relation") {
|
|
2299
|
-
targetSchemaUID = attribute.target;
|
|
2300
|
-
} else if (attribute.type === "component") {
|
|
2301
|
-
targetSchemaUID = attribute.component;
|
|
2302
|
-
} else if (attribute.type === "media") {
|
|
2303
|
-
targetSchemaUID = "plugin::upload.file";
|
|
2304
|
-
} else {
|
|
2305
|
-
return acc;
|
|
2306
|
-
}
|
|
2307
|
-
const targetSchema = strapi.getModel(targetSchemaUID);
|
|
2308
|
-
if (!targetSchema) {
|
|
2309
|
-
return acc;
|
|
2310
|
-
}
|
|
2311
|
-
const populateObject = convertNestedPopulate(subPopulate, targetSchema);
|
|
2312
|
-
if (!populateObject) {
|
|
2313
|
-
return acc;
|
|
2314
|
-
}
|
|
2315
|
-
return {
|
|
2316
|
-
...acc,
|
|
2317
|
-
[key]: populateObject
|
|
2318
|
-
};
|
|
2319
|
-
}, {});
|
|
2320
|
-
};
|
|
2321
|
-
const convertNestedPopulate = (subPopulate, schema) => {
|
|
2322
|
-
if (___default.default.isString(subPopulate)) {
|
|
2323
|
-
return parseType({ type: "boolean", value: subPopulate, forceCast: true });
|
|
2324
|
-
}
|
|
2325
|
-
if (___default.default.isBoolean(subPopulate)) {
|
|
2326
|
-
return subPopulate;
|
|
2327
|
-
}
|
|
2328
|
-
if (!isPlainObject(subPopulate)) {
|
|
2329
|
-
throw new Error(`Invalid nested populate. Expected '*' or an object`);
|
|
2330
|
-
}
|
|
2331
|
-
const { sort: sort2, filters: filters2, fields: fields2, populate: populate2, count, ordering, page, pageSize, start, limit } = subPopulate;
|
|
2332
|
-
const query = {};
|
|
2333
|
-
if (sort2) {
|
|
2334
|
-
query.orderBy = convertSortQueryParams(sort2);
|
|
2335
|
-
}
|
|
2336
|
-
if (filters2) {
|
|
2337
|
-
query.where = convertFiltersQueryParams(filters2, schema);
|
|
2338
|
-
}
|
|
2339
|
-
if (fields2) {
|
|
2340
|
-
query.select = convertFieldsQueryParams(fields2);
|
|
2341
|
-
}
|
|
2342
|
-
if (populate2) {
|
|
2343
|
-
query.populate = convertPopulateQueryParams(populate2, schema);
|
|
2344
|
-
}
|
|
2345
|
-
if (count) {
|
|
2346
|
-
query.count = convertCountQueryParams(count);
|
|
2347
|
-
}
|
|
2348
|
-
if (ordering) {
|
|
2349
|
-
query.ordering = convertOrderingQueryParams(ordering);
|
|
2350
|
-
}
|
|
2351
|
-
validatePaginationParams(page, pageSize, start, limit);
|
|
2352
|
-
if (!fp.isNil(page)) {
|
|
2353
|
-
query.page = convertPageQueryParams(page);
|
|
2354
|
-
}
|
|
2355
|
-
if (!fp.isNil(pageSize)) {
|
|
2356
|
-
query.pageSize = convertPageSizeQueryParams(pageSize, page);
|
|
2357
|
-
}
|
|
2358
|
-
if (!fp.isNil(start)) {
|
|
2359
|
-
query.offset = convertStartQueryParams(start);
|
|
2360
|
-
}
|
|
2361
|
-
if (!fp.isNil(limit)) {
|
|
2362
|
-
query.limit = convertLimitQueryParams(limit);
|
|
2363
|
-
}
|
|
2364
|
-
return query;
|
|
2365
|
-
};
|
|
2366
|
-
const convertFieldsQueryParams = (fields2, depth = 0) => {
|
|
2367
|
-
if (depth === 0 && fields2 === "*") {
|
|
2368
|
-
return void 0;
|
|
2369
|
-
}
|
|
2370
|
-
if (typeof fields2 === "string") {
|
|
2371
|
-
const fieldsValues = fields2.split(",").map((value) => ___default.default.trim(value));
|
|
2372
|
-
return ___default.default.uniq([ID_ATTRIBUTE, DOC_ID_ATTRIBUTE, ...fieldsValues]);
|
|
2373
|
-
}
|
|
2374
|
-
if (isStringArray(fields2)) {
|
|
2375
|
-
const fieldsValues = fields2.flatMap((value) => convertFieldsQueryParams(value, depth + 1)).filter((v) => !fp.isNil(v));
|
|
2376
|
-
return ___default.default.uniq([ID_ATTRIBUTE, DOC_ID_ATTRIBUTE, ...fieldsValues]);
|
|
2377
|
-
}
|
|
2378
|
-
throw new Error("Invalid fields parameter. Expected a string or an array of strings");
|
|
2379
|
-
};
|
|
2380
|
-
const isValidSchemaAttribute = (key, schema) => {
|
|
2381
|
-
if ([DOC_ID_ATTRIBUTE, ID_ATTRIBUTE].includes(key)) {
|
|
2382
|
-
return true;
|
|
2383
|
-
}
|
|
2384
|
-
if (!schema) {
|
|
2385
|
-
return false;
|
|
2386
|
-
}
|
|
2387
|
-
return Object.keys(schema.attributes).includes(key);
|
|
2388
|
-
};
|
|
2389
|
-
const convertFiltersQueryParams = (filters2, schema) => {
|
|
2390
|
-
if (!fp.isObject(filters2)) {
|
|
2391
|
-
throw new Error("The filters parameter must be an object or an array");
|
|
2392
|
-
}
|
|
2393
|
-
const filtersCopy = fp.cloneDeep(filters2);
|
|
2394
|
-
return convertAndSanitizeFilters(filtersCopy, schema);
|
|
2395
|
-
};
|
|
2396
|
-
const convertAndSanitizeFilters = (filters2, schema) => {
|
|
2397
|
-
if (Array.isArray(filters2)) {
|
|
2398
|
-
return filters2.map((filter) => convertAndSanitizeFilters(filter, schema)).filter((filter) => !isPlainObject(filter) || !fp.isEmpty(filter));
|
|
2399
|
-
}
|
|
2400
|
-
if (!isPlainObject(filters2)) {
|
|
2401
|
-
return filters2;
|
|
2402
|
-
}
|
|
2403
|
-
const removeOperator = (operator) => delete filters2[operator];
|
|
2404
|
-
for (const [key, value] of Object.entries(filters2)) {
|
|
2405
|
-
const attribute = fp.get(key, schema?.attributes);
|
|
2406
|
-
const validKey = isOperator(key) || isValidSchemaAttribute(key, schema);
|
|
2407
|
-
if (!validKey) {
|
|
2408
|
-
removeOperator(key);
|
|
2409
|
-
} else if (attribute) {
|
|
2410
|
-
if (attribute.type === "relation") {
|
|
2411
|
-
filters2[key] = convertAndSanitizeFilters(value, strapi.getModel(attribute.target));
|
|
2412
|
-
} else if (attribute.type === "component") {
|
|
2413
|
-
filters2[key] = convertAndSanitizeFilters(value, strapi.getModel(attribute.component));
|
|
2414
|
-
} else if (attribute.type === "media") {
|
|
2415
|
-
filters2[key] = convertAndSanitizeFilters(value, strapi.getModel("plugin::upload.file"));
|
|
2416
|
-
} else if (attribute.type === "dynamiczone") {
|
|
2417
|
-
removeOperator(key);
|
|
2418
|
-
} else if (attribute.type === "password") {
|
|
2419
|
-
removeOperator(key);
|
|
2420
|
-
} else {
|
|
2421
|
-
filters2[key] = convertAndSanitizeFilters(value, schema);
|
|
2422
|
-
}
|
|
2423
|
-
} else if (["$null", "$notNull"].includes(key)) {
|
|
2424
|
-
filters2[key] = parseType({ type: "boolean", value: filters2[key], forceCast: true });
|
|
2425
|
-
} else if (fp.isObject(value)) {
|
|
2426
|
-
filters2[key] = convertAndSanitizeFilters(value, schema);
|
|
2427
|
-
}
|
|
2428
|
-
if (isPlainObject(filters2[key]) && fp.isEmpty(filters2[key])) {
|
|
2429
|
-
removeOperator(key);
|
|
2430
|
-
}
|
|
2431
|
-
}
|
|
2432
|
-
return filters2;
|
|
2433
|
-
};
|
|
2434
|
-
const convertStatusParams = (status, query = {}) => {
|
|
2435
|
-
query.filters = ({ meta }) => {
|
|
2436
|
-
const contentType = strapi.contentTypes[meta.uid];
|
|
2437
|
-
if (!contentType || !hasDraftAndPublish(contentType)) {
|
|
2438
|
-
return {};
|
|
2439
|
-
}
|
|
2440
|
-
return { [PUBLISHED_AT_ATTRIBUTE]: { $null: status === "draft" } };
|
|
2441
|
-
};
|
|
2442
|
-
};
|
|
2443
|
-
const transformParamsToQuery = (uid, params) => {
|
|
2444
|
-
const schema = strapi.getModel(uid);
|
|
2445
|
-
const query = {};
|
|
2446
|
-
const { _q, sort: sort2, filters: filters2, fields: fields2, populate: populate2, page, pageSize, start, limit, status, ...rest } = params;
|
|
2447
|
-
if (!fp.isNil(status)) {
|
|
2448
|
-
convertStatusParams(status, query);
|
|
2449
|
-
}
|
|
2450
|
-
if (!fp.isNil(_q)) {
|
|
2451
|
-
query._q = _q;
|
|
2452
|
-
}
|
|
2453
|
-
if (!fp.isNil(sort2)) {
|
|
2454
|
-
query.orderBy = convertSortQueryParams(sort2);
|
|
2455
|
-
}
|
|
2456
|
-
if (!fp.isNil(filters2)) {
|
|
2457
|
-
query.where = convertFiltersQueryParams(filters2, schema);
|
|
2458
|
-
}
|
|
2459
|
-
if (!fp.isNil(fields2)) {
|
|
2460
|
-
query.select = convertFieldsQueryParams(fields2);
|
|
2461
|
-
}
|
|
2462
|
-
if (!fp.isNil(populate2)) {
|
|
2463
|
-
query.populate = convertPopulateQueryParams(populate2, schema);
|
|
2464
|
-
}
|
|
2465
|
-
validatePaginationParams(page, pageSize, start, limit);
|
|
2466
|
-
if (!fp.isNil(page)) {
|
|
2467
|
-
query.page = convertPageQueryParams(page);
|
|
2468
|
-
}
|
|
2469
|
-
if (!fp.isNil(pageSize)) {
|
|
2470
|
-
query.pageSize = convertPageSizeQueryParams(pageSize, page);
|
|
2471
|
-
}
|
|
2472
|
-
if (!fp.isNil(start)) {
|
|
2473
|
-
query.offset = convertStartQueryParams(start);
|
|
2474
|
-
}
|
|
2475
|
-
if (!fp.isNil(limit)) {
|
|
2476
|
-
query.limit = convertLimitQueryParams(limit);
|
|
2477
|
-
}
|
|
2478
|
-
return {
|
|
2479
|
-
...rest,
|
|
2480
|
-
...query
|
|
2481
|
-
};
|
|
2482
|
-
};
|
|
2483
|
-
const convertQueryParams = {
|
|
2484
|
-
convertSortQueryParams,
|
|
2485
|
-
convertStartQueryParams,
|
|
2486
|
-
convertLimitQueryParams,
|
|
2487
|
-
convertPopulateQueryParams,
|
|
2488
|
-
convertFiltersQueryParams,
|
|
2489
|
-
convertFieldsQueryParams,
|
|
2490
|
-
transformParamsToQuery
|
|
2491
|
-
};
|
|
2492
|
-
function importDefault(modName) {
|
|
2493
|
-
const mod = require(modName);
|
|
2494
|
-
return mod && mod.__esModule ? mod.default : mod;
|
|
2495
|
-
}
|
|
2496
|
-
const machineId = () => {
|
|
2497
|
-
try {
|
|
2498
|
-
const deviceId = nodeMachineId.machineIdSync();
|
|
2499
|
-
return deviceId;
|
|
2500
|
-
} catch (error) {
|
|
2501
|
-
const deviceId = crypto.randomUUID();
|
|
2502
|
-
return deviceId;
|
|
2503
|
-
}
|
|
2504
|
-
};
|
|
2505
|
-
const handleYupError = (error, errorMessage) => {
|
|
2506
|
-
throw new YupValidationError(error, errorMessage);
|
|
2507
|
-
};
|
|
2508
|
-
const defaultValidationParam = { strict: true, abortEarly: false };
|
|
2509
|
-
const validateYupSchema = (schema, options = {}) => async (body, errorMessage) => {
|
|
2510
|
-
try {
|
|
2511
|
-
const optionsWithDefaults = fp.defaults(defaultValidationParam, options);
|
|
2512
|
-
const result = await schema.validate(body, optionsWithDefaults);
|
|
2513
|
-
return result;
|
|
2514
|
-
} catch (e) {
|
|
2515
|
-
if (e instanceof yup__namespace.ValidationError) {
|
|
2516
|
-
handleYupError(e, errorMessage);
|
|
2517
|
-
}
|
|
2518
|
-
throw e;
|
|
2519
|
-
}
|
|
2520
|
-
};
|
|
2521
|
-
const validateYupSchemaSync = (schema, options = {}) => (body, errorMessage) => {
|
|
2522
|
-
try {
|
|
2523
|
-
const optionsWithDefaults = fp.defaults(defaultValidationParam, options);
|
|
2524
|
-
return schema.validateSync(body, optionsWithDefaults);
|
|
2525
|
-
} catch (e) {
|
|
2526
|
-
if (e instanceof yup__namespace.ValidationError) {
|
|
2527
|
-
handleYupError(e, errorMessage);
|
|
2528
|
-
}
|
|
2529
|
-
throw e;
|
|
2530
|
-
}
|
|
2531
|
-
};
|
|
2681
|
+
visitors: index$1
|
|
2682
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
2532
2683
|
const STRAPI_DEFAULTS = {
|
|
2533
2684
|
offset: {
|
|
2534
2685
|
start: 0,
|
|
@@ -2596,8 +2747,57 @@ const withDefaultPagination = (args, { defaults = {}, maxLimit = -1 } = {}) => {
|
|
|
2596
2747
|
);
|
|
2597
2748
|
return replacePaginationAttributes(args);
|
|
2598
2749
|
};
|
|
2750
|
+
const transformPagedPaginationInfo = (paginationInfo, total) => {
|
|
2751
|
+
if (!fp.isNil(paginationInfo.page)) {
|
|
2752
|
+
const page = paginationInfo.page;
|
|
2753
|
+
const pageSize = paginationInfo.pageSize ?? total;
|
|
2754
|
+
return {
|
|
2755
|
+
page,
|
|
2756
|
+
pageSize,
|
|
2757
|
+
pageCount: pageSize > 0 ? Math.ceil(total / pageSize) : 0,
|
|
2758
|
+
total
|
|
2759
|
+
};
|
|
2760
|
+
}
|
|
2761
|
+
if (!fp.isNil(paginationInfo.start)) {
|
|
2762
|
+
const start = paginationInfo.start;
|
|
2763
|
+
const limit = paginationInfo.limit ?? total;
|
|
2764
|
+
return {
|
|
2765
|
+
page: Math.floor(start / limit) + 1,
|
|
2766
|
+
pageSize: limit,
|
|
2767
|
+
pageCount: limit > 0 ? Math.ceil(total / limit) : 0,
|
|
2768
|
+
total
|
|
2769
|
+
};
|
|
2770
|
+
}
|
|
2771
|
+
return {
|
|
2772
|
+
...paginationInfo,
|
|
2773
|
+
page: 1,
|
|
2774
|
+
pageSize: 10,
|
|
2775
|
+
pageCount: 1,
|
|
2776
|
+
total
|
|
2777
|
+
};
|
|
2778
|
+
};
|
|
2779
|
+
const transformOffsetPaginationInfo = (paginationInfo, total) => {
|
|
2780
|
+
if (!fp.isNil(paginationInfo.page)) {
|
|
2781
|
+
const limit = paginationInfo.pageSize ?? total;
|
|
2782
|
+
const start = (paginationInfo.page - 1) * limit;
|
|
2783
|
+
return { start, limit, total };
|
|
2784
|
+
}
|
|
2785
|
+
if (!fp.isNil(paginationInfo.start)) {
|
|
2786
|
+
const start = paginationInfo.start;
|
|
2787
|
+
const limit = paginationInfo.limit ?? total;
|
|
2788
|
+
return { start, limit, total };
|
|
2789
|
+
}
|
|
2790
|
+
return {
|
|
2791
|
+
...paginationInfo,
|
|
2792
|
+
start: 0,
|
|
2793
|
+
limit: 10,
|
|
2794
|
+
total
|
|
2795
|
+
};
|
|
2796
|
+
};
|
|
2599
2797
|
const pagination = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2600
2798
|
__proto__: null,
|
|
2799
|
+
transformOffsetPaginationInfo,
|
|
2800
|
+
transformPagedPaginationInfo,
|
|
2601
2801
|
withDefaultPagination
|
|
2602
2802
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2603
2803
|
const SUPPORTED_PACKAGE_MANAGERS = ["npm", "yarn"];
|
|
@@ -2680,72 +2880,6 @@ const file = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty
|
|
|
2680
2880
|
streamToBuffer,
|
|
2681
2881
|
writableDiscardStream
|
|
2682
2882
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2683
|
-
const PLUGIN_PREFIX = "plugin::";
|
|
2684
|
-
const API_PREFIX = "api::";
|
|
2685
|
-
const parsePolicy = (policy2) => {
|
|
2686
|
-
if (typeof policy2 === "string") {
|
|
2687
|
-
return { policyName: policy2, config: {} };
|
|
2688
|
-
}
|
|
2689
|
-
const { name, config } = policy2;
|
|
2690
|
-
return { policyName: name, config };
|
|
2691
|
-
};
|
|
2692
|
-
const searchLocalPolicy = (policyName, policyContext) => {
|
|
2693
|
-
const { pluginName, apiName } = policyContext ?? {};
|
|
2694
|
-
if (pluginName) {
|
|
2695
|
-
return strapi.policy(`${PLUGIN_PREFIX}${pluginName}.${policyName}`);
|
|
2696
|
-
}
|
|
2697
|
-
if (apiName) {
|
|
2698
|
-
return strapi.policy(`${API_PREFIX}${apiName}.${policyName}`);
|
|
2699
|
-
}
|
|
2700
|
-
};
|
|
2701
|
-
const globalPolicy = ({ method, endpoint, controller, action, plugin }) => {
|
|
2702
|
-
return async (ctx, next) => {
|
|
2703
|
-
ctx.request.route = {
|
|
2704
|
-
endpoint: `${method} ${endpoint}`,
|
|
2705
|
-
controller: ___default.default.toLower(controller),
|
|
2706
|
-
action: ___default.default.toLower(action),
|
|
2707
|
-
verb: ___default.default.toLower(method),
|
|
2708
|
-
plugin
|
|
2709
|
-
};
|
|
2710
|
-
await next();
|
|
2711
|
-
};
|
|
2712
|
-
};
|
|
2713
|
-
const resolvePolicies = (config, policyContext) => {
|
|
2714
|
-
const { pluginName, apiName } = policyContext ?? {};
|
|
2715
|
-
return config.map((policyConfig) => {
|
|
2716
|
-
return {
|
|
2717
|
-
handler: getPolicy(policyConfig, { pluginName, apiName }),
|
|
2718
|
-
config: typeof policyConfig === "object" && policyConfig.config || {}
|
|
2719
|
-
};
|
|
2720
|
-
});
|
|
2721
|
-
};
|
|
2722
|
-
const findPolicy = (name, policyContext) => {
|
|
2723
|
-
const { pluginName, apiName } = policyContext ?? {};
|
|
2724
|
-
const resolvedPolicy = strapi.policy(name);
|
|
2725
|
-
if (resolvedPolicy !== void 0) {
|
|
2726
|
-
return resolvedPolicy;
|
|
2727
|
-
}
|
|
2728
|
-
const localPolicy = searchLocalPolicy(name, { pluginName, apiName });
|
|
2729
|
-
if (localPolicy !== void 0) {
|
|
2730
|
-
return localPolicy;
|
|
2731
|
-
}
|
|
2732
|
-
throw new Error(`Could not find policy "${name}"`);
|
|
2733
|
-
};
|
|
2734
|
-
const getPolicy = (policyConfig, policyContext) => {
|
|
2735
|
-
const { pluginName, apiName } = policyContext ?? {};
|
|
2736
|
-
if (typeof policyConfig === "function") {
|
|
2737
|
-
return policyConfig;
|
|
2738
|
-
}
|
|
2739
|
-
const { policyName, config } = parsePolicy(policyConfig);
|
|
2740
|
-
const policy2 = findPolicy(policyName, { pluginName, apiName });
|
|
2741
|
-
if (typeof policy2 === "function") {
|
|
2742
|
-
return policy2;
|
|
2743
|
-
}
|
|
2744
|
-
if (policy2.validator) {
|
|
2745
|
-
policy2.validator(config);
|
|
2746
|
-
}
|
|
2747
|
-
return policy2.handler;
|
|
2748
|
-
};
|
|
2749
2883
|
const createPolicy = (options) => {
|
|
2750
2884
|
const { name = "unnamed", validator, handler } = options;
|
|
2751
2885
|
const wrappedValidator = (config) => {
|
|
@@ -2777,10 +2911,7 @@ const createPolicyContext = (type, ctx) => {
|
|
|
2777
2911
|
const policy = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2778
2912
|
__proto__: null,
|
|
2779
2913
|
createPolicy,
|
|
2780
|
-
createPolicyContext
|
|
2781
|
-
get: getPolicy,
|
|
2782
|
-
globalPolicy,
|
|
2783
|
-
resolve: resolvePolicies
|
|
2914
|
+
createPolicyContext
|
|
2784
2915
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2785
2916
|
const nameToSlug = (name, options = { separator: "-" }) => slugify__default.default(name, options);
|
|
2786
2917
|
const nameToCollectionName = (name) => slugify__default.default(name, { separator: "_" });
|
|
@@ -2790,9 +2921,9 @@ const toRegressedEnumValue = (value) => slugify__default.default(value, {
|
|
|
2790
2921
|
separator: "_"
|
|
2791
2922
|
});
|
|
2792
2923
|
const getCommonPath = (...paths) => {
|
|
2793
|
-
const [segments, ...otherSegments] = paths.map((it) =>
|
|
2794
|
-
return
|
|
2795
|
-
|
|
2924
|
+
const [segments, ...otherSegments] = paths.map((it) => ___namespace.default.split(it, "/"));
|
|
2925
|
+
return ___namespace.default.join(
|
|
2926
|
+
___namespace.default.takeWhile(segments, (str, index2) => otherSegments.every((it) => it[index2] === str)),
|
|
2796
2927
|
"/"
|
|
2797
2928
|
);
|
|
2798
2929
|
};
|
|
@@ -2814,7 +2945,7 @@ const joinBy = (joint, ...args) => {
|
|
|
2814
2945
|
return url + joint + trim(path);
|
|
2815
2946
|
}, "");
|
|
2816
2947
|
};
|
|
2817
|
-
const toKebabCase = (value) => _
|
|
2948
|
+
const toKebabCase = (value) => _.kebabCase(value);
|
|
2818
2949
|
const strings = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2819
2950
|
__proto__: null,
|
|
2820
2951
|
getCommonPath,
|
|
@@ -2834,9 +2965,9 @@ const arrays = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
|
|
|
2834
2965
|
__proto__: null,
|
|
2835
2966
|
includesString
|
|
2836
2967
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2837
|
-
const keysDeep = (obj, path = []) => !
|
|
2968
|
+
const keysDeep = (obj, path = []) => !___namespace.default.isObject(obj) ? [path.join(".")] : ___namespace.default.reduce(
|
|
2838
2969
|
obj,
|
|
2839
|
-
(acc, next, key) =>
|
|
2970
|
+
(acc, next, key) => ___namespace.default.concat(acc, keysDeep(next, [...path, key])),
|
|
2840
2971
|
[]
|
|
2841
2972
|
);
|
|
2842
2973
|
const objects = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
@@ -2900,8 +3031,8 @@ function printValue(value, quoteStrings) {
|
|
|
2900
3031
|
);
|
|
2901
3032
|
}
|
|
2902
3033
|
const strapiID = () => new StrapiIDSchema();
|
|
2903
|
-
const isNotNilTest = (value) => !
|
|
2904
|
-
const isNotNullTest = (value) => !
|
|
3034
|
+
const isNotNilTest = (value) => !___namespace.default.isNil(value);
|
|
3035
|
+
const isNotNullTest = (value) => !___namespace.default.isNull(value);
|
|
2905
3036
|
yup__namespace.addMethod(yup__namespace.mixed, "notNil", function isNotNill(msg = "${path} must be defined.") {
|
|
2906
3037
|
return this.test("defined", msg, isNotNilTest);
|
|
2907
3038
|
});
|
|
@@ -2912,7 +3043,7 @@ yup__namespace.addMethod(yup__namespace.mixed, "isFunction", function isFunction
|
|
|
2912
3043
|
return this.test(
|
|
2913
3044
|
"is a function",
|
|
2914
3045
|
message,
|
|
2915
|
-
(value) =>
|
|
3046
|
+
(value) => ___namespace.default.isUndefined(value) || ___namespace.default.isFunction(value)
|
|
2916
3047
|
);
|
|
2917
3048
|
});
|
|
2918
3049
|
yup__namespace.addMethod(
|
|
@@ -2944,7 +3075,7 @@ yup__namespace.addMethod(
|
|
|
2944
3075
|
return this.test(
|
|
2945
3076
|
"only contains functions",
|
|
2946
3077
|
message,
|
|
2947
|
-
(value) =>
|
|
3078
|
+
(value) => ___namespace.default.isUndefined(value) || value && Object.values(value).every(___namespace.default.isFunction)
|
|
2948
3079
|
);
|
|
2949
3080
|
}
|
|
2950
3081
|
);
|
|
@@ -3019,10 +3150,30 @@ const relations = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePro
|
|
|
3019
3150
|
isManyToAny,
|
|
3020
3151
|
isOneToAny
|
|
3021
3152
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
3153
|
+
const validateZod = (schema) => (data) => {
|
|
3154
|
+
try {
|
|
3155
|
+
return schema.parse(data);
|
|
3156
|
+
} catch (error) {
|
|
3157
|
+
if (error instanceof zod.z.ZodError) {
|
|
3158
|
+
const { message, errors: errors2 } = formatZodErrors(error);
|
|
3159
|
+
throw new ValidationError(message, { errors: errors2 });
|
|
3160
|
+
}
|
|
3161
|
+
throw error;
|
|
3162
|
+
}
|
|
3163
|
+
};
|
|
3164
|
+
const formatZodErrors = (zodError) => ({
|
|
3165
|
+
errors: zodError.errors.map((error) => {
|
|
3166
|
+
return {
|
|
3167
|
+
path: error.path,
|
|
3168
|
+
message: error.message,
|
|
3169
|
+
name: "ValidationError"
|
|
3170
|
+
};
|
|
3171
|
+
}),
|
|
3172
|
+
message: "Validation error"
|
|
3173
|
+
});
|
|
3022
3174
|
exports.arrays = arrays;
|
|
3023
3175
|
exports.async = async;
|
|
3024
3176
|
exports.contentTypes = contentTypes;
|
|
3025
|
-
exports.convertQueryParams = convertQueryParams;
|
|
3026
3177
|
exports.dates = dates;
|
|
3027
3178
|
exports.env = env;
|
|
3028
3179
|
exports.errors = errors;
|
|
@@ -3038,15 +3189,17 @@ exports.pagination = pagination;
|
|
|
3038
3189
|
exports.parseType = parseType;
|
|
3039
3190
|
exports.policy = policy;
|
|
3040
3191
|
exports.providerFactory = providerFactory;
|
|
3192
|
+
exports.queryParams = convertQueryParams;
|
|
3041
3193
|
exports.relations = relations;
|
|
3042
|
-
exports.sanitize = index$
|
|
3194
|
+
exports.sanitize = index$2;
|
|
3043
3195
|
exports.setCreatorFields = setCreatorFields;
|
|
3044
3196
|
exports.strings = strings;
|
|
3045
3197
|
exports.template = template;
|
|
3046
|
-
exports.traverse = index$
|
|
3198
|
+
exports.traverse = index$3;
|
|
3047
3199
|
exports.traverseEntity = traverseEntity$1;
|
|
3048
3200
|
exports.validate = index;
|
|
3049
3201
|
exports.validateYupSchema = validateYupSchema;
|
|
3050
3202
|
exports.validateYupSchemaSync = validateYupSchemaSync;
|
|
3203
|
+
exports.validateZod = validateZod;
|
|
3051
3204
|
exports.yup = yup;
|
|
3052
3205
|
//# sourceMappingURL=index.js.map
|