@strapi/utils 5.0.0-beta.1 → 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.
Files changed (37) hide show
  1. package/dist/async.d.ts +5 -11
  2. package/dist/async.d.ts.map +1 -1
  3. package/dist/content-types.d.ts +16 -6
  4. package/dist/content-types.d.ts.map +1 -1
  5. package/dist/convert-query-params.d.ts.map +1 -1
  6. package/dist/file.d.ts +0 -1
  7. package/dist/file.d.ts.map +1 -1
  8. package/dist/hooks.d.ts.map +1 -1
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +325 -154
  12. package/dist/index.js.map +1 -1
  13. package/dist/index.mjs +312 -141
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/pagination.d.ts +34 -4
  16. package/dist/pagination.d.ts.map +1 -1
  17. package/dist/parse-type.d.ts.map +1 -1
  18. package/dist/sanitize/sanitizers.d.ts +1 -1
  19. package/dist/sanitize/sanitizers.d.ts.map +1 -1
  20. package/dist/set-creator-fields.d.ts.map +1 -1
  21. package/dist/traverse/factory.d.ts +2 -4
  22. package/dist/traverse/factory.d.ts.map +1 -1
  23. package/dist/traverse/query-populate.d.ts.map +1 -1
  24. package/dist/traverse-entity.d.ts +10 -2
  25. package/dist/traverse-entity.d.ts.map +1 -1
  26. package/dist/validate/index.d.ts.map +1 -1
  27. package/dist/validate/utils.d.ts +2 -2
  28. package/dist/validate/utils.d.ts.map +1 -1
  29. package/dist/validate/visitors/index.d.ts +1 -0
  30. package/dist/validate/visitors/index.d.ts.map +1 -1
  31. package/dist/validate/visitors/throw-unrecognized-fields.d.ts +4 -0
  32. package/dist/validate/visitors/throw-unrecognized-fields.d.ts.map +1 -0
  33. package/dist/validators.d.ts +2 -2
  34. package/dist/validators.d.ts.map +1 -1
  35. package/dist/zod.d.ts +3 -0
  36. package/dist/zod.d.ts.map +1 -0
  37. package/package.json +11 -9
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const _$1 = require("lodash");
3
+ const _ = require("lodash");
4
+ const dates$1 = require("date-fns");
4
5
  const fp = require("lodash/fp");
5
6
  const crypto = require("crypto");
6
7
  const nodeMachineId = require("node-machine-id");
@@ -11,6 +12,7 @@ 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 ___default = /* @__PURE__ */ _interopDefault(_$1);
54
+ const ___namespace = /* @__PURE__ */ _interopNamespace(_);
55
+ const dates__namespace = /* @__PURE__ */ _interopNamespace(dates$1);
53
56
  const yup__namespace = /* @__PURE__ */ _interopNamespace(yup$1);
54
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 dates$1.isDate(v);
63
+ return dates__namespace.isDate(v);
63
64
  };
64
65
  const parseTime = (value) => {
65
66
  if (isDate(value)) {
66
- return dates$1.format(value, "HH:mm:ss.SSS");
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 = _.padEnd(fraction.slice(1), 3, "0");
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 dates$1.format(value, "yyyy-MM-dd");
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 = dates$1.parseISO(value);
88
- if (dates$1.isValid(date))
89
- return dates$1.format(date, "yyyy-MM-dd");
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 = dates$1.parseISO(value);
104
- if (dates$1.isValid(date))
104
+ const date = dates__namespace.parseISO(value);
105
+ if (dates__namespace.isValid(date))
105
106
  return date;
106
- const milliUnixDate = dates$1.parse(value, "T", /* @__PURE__ */ new Date());
107
- if (dates$1.isValid(milliUnixDate))
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 _.toNumber(value);
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 ___default.default.has(process.env, key) ? process.env[key] : defaultValue;
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 (!___default.default.has(process.env, key)) {
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 (!___default.default.has(process.env, key)) {
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 (!___default.default.has(process.env, key)) {
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 (!___default.default.has(process.env, key)) {
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 (!___default.default.has(process.env, key)) {
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 ___default.default.trim(___default.default.trim(v, " "), '"');
205
+ return ___namespace.default.trim(___namespace.default.trim(v, " "), '"');
205
206
  });
206
207
  },
207
208
  date(key, defaultValue) {
208
- if (!___default.default.has(process.env, key)) {
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 = ___default.default.reduce(
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 ___default.default.uniq([
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 ___default.default.difference(Object.keys(model.attributes), getNonWritableAttributes(model));
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 = ___default.default.reduce(
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 ___default.default.uniq([ID_ATTRIBUTE$4, DOC_ID_ATTRIBUTE$4, ...getTimestamps(model), ...nonVisibleAttributes]);
302
+ return ___namespace.default.uniq([ID_ATTRIBUTE$4, DOC_ID_ATTRIBUTE$4, ...getTimestamps(model), ...nonVisibleAttributes]);
302
303
  };
303
304
  const getVisibleAttributes = (model) => {
304
- return ___default.default.difference(___default.default.keys(model.attributes), getNonVisibleAttributes(model));
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) => ___default.default.assign({ draftAndPublish: false }, ___default.default.get(model, "options", {}));
310
- const hasDraftAndPublish = (model) => ___default.default.get(model, "options.draftAndPublish", false) === true;
311
- const isDraft = (data, model) => hasDraftAndPublish(model) && ___default.default.get(data, PUBLISHED_AT_ATTRIBUTE$1) === null;
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 ___default.default.union(
330
+ return ___namespace.default.union(
321
331
  getStoredPrivateAttributes(model),
322
- ___default.default.keys(___default.default.pickBy(model.attributes, (attr) => !!attr.private))
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?.type);
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?.type === "dynamiczone";
352
+ const isDynamicZoneAttribute = (attribute) => !!attribute && attribute.type === "dynamiczone";
338
353
  const isMorphToRelationalAttribute = (attribute) => {
339
- return isRelationalAttribute(attribute) && attribute?.relation?.startsWith?.("morphTo");
354
+ return !!attribute && isRelationalAttribute(attribute) && attribute.relation?.startsWith?.("morphTo");
340
355
  };
341
356
  const getComponentAttributes = (schema) => {
342
- return ___default.default.reduce(
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 ___default.default.reduce(
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 ___default.default.has(attribute, "type") && attribute.type === type;
390
+ return ___namespace.default.has(attribute, "type") && attribute.type === type;
365
391
  };
366
392
  const getContentTypeRoutePrefix = (contentType) => {
367
- return isSingleType(contentType) ? ___default.default.kebabCase(contentType.info.singularName) : ___default.default.kebabCase(contentType.info.pluralName);
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,
@@ -545,28 +577,29 @@ const providerFactory = (options = {}) => {
545
577
  };
546
578
  const traverseEntity = async (visitor2, options, entity) => {
547
579
  const { path = { raw: null, attribute: null }, schema, getModel } = options;
580
+ let parent = options.parent;
548
581
  const traverseMorphRelationTarget = async (visitor22, path2, entry) => {
549
582
  const targetSchema = getModel(entry.__type);
550
- const traverseOptions = { schema: targetSchema, path: path2, getModel };
583
+ const traverseOptions = { schema: targetSchema, path: path2, getModel, parent };
551
584
  return traverseEntity(visitor22, traverseOptions, entry);
552
585
  };
553
586
  const traverseRelationTarget = (schema2) => async (visitor22, path2, entry) => {
554
- const traverseOptions = { schema: schema2, path: path2, getModel };
587
+ const traverseOptions = { schema: schema2, path: path2, getModel, parent };
555
588
  return traverseEntity(visitor22, traverseOptions, entry);
556
589
  };
557
590
  const traverseMediaTarget = async (visitor22, path2, entry) => {
558
591
  const targetSchemaUID = "plugin::upload.file";
559
592
  const targetSchema = getModel(targetSchemaUID);
560
- const traverseOptions = { schema: targetSchema, path: path2, getModel };
593
+ const traverseOptions = { schema: targetSchema, path: path2, getModel, parent };
561
594
  return traverseEntity(visitor22, traverseOptions, entry);
562
595
  };
563
596
  const traverseComponent = async (visitor22, path2, schema2, entry) => {
564
- const traverseOptions = { schema: schema2, path: path2, getModel };
597
+ const traverseOptions = { schema: schema2, path: path2, getModel, parent };
565
598
  return traverseEntity(visitor22, traverseOptions, entry);
566
599
  };
567
600
  const visitDynamicZoneEntry = async (visitor22, path2, entry) => {
568
601
  const targetSchema = getModel(entry.__component);
569
- const traverseOptions = { schema: targetSchema, path: path2, getModel };
602
+ const traverseOptions = { schema: targetSchema, path: path2, getModel, parent };
570
603
  return traverseEntity(visitor22, traverseOptions, entry);
571
604
  };
572
605
  if (!fp.isObject(entity) || fp.isNil(schema)) {
@@ -578,9 +611,6 @@ const traverseEntity = async (visitor2, options, entity) => {
578
611
  for (let i = 0; i < keys.length; i += 1) {
579
612
  const key = keys[i];
580
613
  const attribute = schema.attributes[key];
581
- if (fp.isNil(attribute)) {
582
- continue;
583
- }
584
614
  const newPath = { ...path };
585
615
  newPath.raw = fp.isNil(path.raw) ? key : `${path.raw}.${key}`;
586
616
  if (!fp.isNil(attribute)) {
@@ -593,13 +623,15 @@ const traverseEntity = async (visitor2, options, entity) => {
593
623
  value: copy[key],
594
624
  attribute,
595
625
  path: newPath,
596
- getModel
626
+ getModel,
627
+ parent
597
628
  };
598
629
  await visitor2(visitorOptions, visitorUtils);
599
630
  const value = copy[key];
600
- if (fp.isNil(value)) {
631
+ if (fp.isNil(value) || fp.isNil(attribute)) {
601
632
  continue;
602
633
  }
634
+ parent = { schema, key, attribute, path: newPath };
603
635
  if (isRelationalAttribute(attribute)) {
604
636
  const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
605
637
  const method = isMorphRelation ? traverseMorphRelationTarget : traverseRelationTarget(getModel(attribute.target));
@@ -897,7 +929,7 @@ const convertCountQueryParams = (countQuery) => {
897
929
  const convertOrderingQueryParams = (ordering) => {
898
930
  return ordering;
899
931
  };
900
- const isPlainObject = (value) => ___default.default.isPlainObject(value);
932
+ const isPlainObject = (value) => ___namespace.default.isPlainObject(value);
901
933
  const isStringArray$3 = (value) => fp.isArray(value) && value.every(fp.isString);
902
934
  const createTransformer = ({ getModel }) => {
903
935
  const convertSortQueryParams = (sortQuery) => {
@@ -930,7 +962,7 @@ const createTransformer = ({ getModel }) => {
930
962
  throw new Error("Field cannot be empty");
931
963
  }
932
964
  validateOrder(order);
933
- return ___default.default.set({}, field, order);
965
+ return ___namespace.default.set({}, field, order);
934
966
  };
935
967
  const convertNestedSortQueryParam = (sortQuery) => {
936
968
  const transformedSort = {};
@@ -948,15 +980,15 @@ const createTransformer = ({ getModel }) => {
948
980
  return transformedSort;
949
981
  };
950
982
  const convertStartQueryParams = (startQuery) => {
951
- const startAsANumber = ___default.default.toNumber(startQuery);
952
- if (!___default.default.isInteger(startAsANumber) || startAsANumber < 0) {
983
+ const startAsANumber = ___namespace.default.toNumber(startQuery);
984
+ if (!___namespace.default.isInteger(startAsANumber) || startAsANumber < 0) {
953
985
  throw new Error(`convertStartQueryParams expected a positive integer got ${startAsANumber}`);
954
986
  }
955
987
  return startAsANumber;
956
988
  };
957
989
  const convertLimitQueryParams = (limitQuery) => {
958
- const limitAsANumber = ___default.default.toNumber(limitQuery);
959
- if (!___default.default.isInteger(limitAsANumber) || limitAsANumber !== -1 && limitAsANumber < 0) {
990
+ const limitAsANumber = ___namespace.default.toNumber(limitQuery);
991
+ if (!___namespace.default.isInteger(limitAsANumber) || limitAsANumber !== -1 && limitAsANumber < 0) {
960
992
  throw new Error(`convertLimitQueryParams expected a positive integer got ${limitAsANumber}`);
961
993
  }
962
994
  if (limitAsANumber === -1) {
@@ -1002,44 +1034,62 @@ const createTransformer = ({ getModel }) => {
1002
1034
  return true;
1003
1035
  }
1004
1036
  if (typeof populate2 === "string") {
1005
- return populate2.split(",").map((value) => ___default.default.trim(value));
1037
+ return populate2.split(",").map((value) => ___namespace.default.trim(value));
1006
1038
  }
1007
1039
  if (Array.isArray(populate2)) {
1008
- return ___default.default.uniq(
1040
+ return ___namespace.default.uniq(
1009
1041
  populate2.flatMap((value) => {
1010
1042
  if (typeof value !== "string") {
1011
1043
  throw new InvalidPopulateError();
1012
1044
  }
1013
- return value.split(",").map((value2) => ___default.default.trim(value2));
1045
+ return value.split(",").map((value2) => ___namespace.default.trim(value2));
1014
1046
  })
1015
1047
  );
1016
1048
  }
1017
- if (___default.default.isPlainObject(populate2)) {
1049
+ if (___namespace.default.isPlainObject(populate2)) {
1018
1050
  return convertPopulateObject(populate2, schema);
1019
1051
  }
1020
1052
  throw new InvalidPopulateError();
1021
1053
  };
1022
- const hasFragmentPopulateDefined = (populate2) => {
1054
+ const hasPopulateFragmentDefined = (populate2) => {
1023
1055
  return typeof populate2 === "object" && "on" in populate2 && !fp.isNil(populate2.on);
1024
1056
  };
1057
+ const hasCountDefined = (populate2) => {
1058
+ return typeof populate2 === "object" && "count" in populate2 && typeof populate2.count === "boolean";
1059
+ };
1025
1060
  const convertPopulateObject = (populate2, schema) => {
1026
1061
  if (!schema) {
1027
1062
  return {};
1028
1063
  }
1029
1064
  const { attributes } = schema;
1030
1065
  return Object.entries(populate2).reduce((acc, [key, subPopulate]) => {
1031
- if (___default.default.isBoolean(subPopulate)) {
1032
- return { ...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;
1033
1075
  }
1034
1076
  const attribute = attributes[key];
1035
1077
  if (!attribute) {
1036
1078
  return acc;
1037
1079
  }
1038
- const isAllowedAttributeForFragmentPopulate = isDynamicZoneAttribute(attribute) || isMorphToRelationalAttribute(attribute);
1039
- if (isAllowedAttributeForFragmentPopulate && hasFragmentPopulateDefined(subPopulate)) {
1040
- return {
1041
- ...acc,
1042
- [key]: {
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, {
1043
1093
  on: Object.entries(subPopulate.on).reduce(
1044
1094
  (acc2, [type, typeSubPopulate]) => ({
1045
1095
  ...acc2,
@@ -1047,21 +1097,15 @@ const createTransformer = ({ getModel }) => {
1047
1097
  }),
1048
1098
  {}
1049
1099
  )
1050
- }
1051
- };
1052
- }
1053
- if (isDynamicZoneAttribute(attribute)) {
1054
- const populates = attribute.components.map((uid) => getModel(uid)).map((schema2) => convertNestedPopulate(subPopulate, schema2)).map((populate22) => populate22 === true ? {} : populate22).filter((populate22) => populate22 !== false);
1055
- if (fp.isEmpty(populates)) {
1056
- return acc;
1100
+ });
1057
1101
  }
1058
- return {
1059
- ...acc,
1060
- [key]: fp.mergeAll(populates)
1061
- };
1102
+ if (hasCountDefined(subPopulate)) {
1103
+ Object.assign(newSubPopulate, { count: subPopulate.count });
1104
+ }
1105
+ return { ...acc, [key]: newSubPopulate };
1062
1106
  }
1063
- if (isMorphToRelationalAttribute(attribute)) {
1064
- return { ...acc, [key]: convertNestedPopulate(subPopulate, void 0) };
1107
+ if (!isMorphLikeRelationalAttribute && hasPopulateFragmentDefined(subPopulate)) {
1108
+ throw new Error(`Using fragments is not permitted to populate "${key}" in "${schema.uid}"`);
1065
1109
  }
1066
1110
  let targetSchemaUID;
1067
1111
  if (attribute.type === "relation") {
@@ -1088,10 +1132,10 @@ const createTransformer = ({ getModel }) => {
1088
1132
  }, {});
1089
1133
  };
1090
1134
  const convertNestedPopulate = (subPopulate, schema) => {
1091
- if (___default.default.isString(subPopulate)) {
1135
+ if (___namespace.default.isString(subPopulate)) {
1092
1136
  return parseType({ type: "boolean", value: subPopulate, forceCast: true });
1093
1137
  }
1094
- if (___default.default.isBoolean(subPopulate)) {
1138
+ if (___namespace.default.isBoolean(subPopulate)) {
1095
1139
  return subPopulate;
1096
1140
  }
1097
1141
  if (!isPlainObject(subPopulate)) {
@@ -1137,12 +1181,12 @@ const createTransformer = ({ getModel }) => {
1137
1181
  return void 0;
1138
1182
  }
1139
1183
  if (typeof fields2 === "string") {
1140
- const fieldsValues = fields2.split(",").map((value) => ___default.default.trim(value));
1141
- return ___default.default.uniq([ID_ATTRIBUTE$3, DOC_ID_ATTRIBUTE$3, ...fieldsValues]);
1184
+ const fieldsValues = fields2.split(",").map((value) => ___namespace.default.trim(value));
1185
+ return ___namespace.default.uniq([ID_ATTRIBUTE$3, DOC_ID_ATTRIBUTE$3, ...fieldsValues]);
1142
1186
  }
1143
1187
  if (isStringArray$3(fields2)) {
1144
1188
  const fieldsValues = fields2.flatMap((value) => convertFieldsQueryParams(value, depth + 1)).filter((v) => !fp.isNil(v));
1145
- return ___default.default.uniq([ID_ATTRIBUTE$3, DOC_ID_ATTRIBUTE$3, ...fieldsValues]);
1189
+ return ___namespace.default.uniq([ID_ATTRIBUTE$3, DOC_ID_ATTRIBUTE$3, ...fieldsValues]);
1146
1190
  }
1147
1191
  throw new Error("Invalid fields parameter. Expected a string or an array of strings");
1148
1192
  };
@@ -1817,7 +1861,8 @@ const populate = traverseFactory().intercept(isStringArray$1, async (visitor2, o
1817
1861
  return;
1818
1862
  }
1819
1863
  const newValue2 = await recurse(visitor2, { schema, path, getModel }, { on: value?.on });
1820
- set(key, { on: newValue2 });
1864
+ set(key, newValue2);
1865
+ return;
1821
1866
  }
1822
1867
  const targetSchemaUID = attribute.target;
1823
1868
  const targetSchema = getModel(targetSchemaUID);
@@ -1839,36 +1884,15 @@ const populate = traverseFactory().intercept(isStringArray$1, async (visitor2, o
1839
1884
  const targetSchema = getModel(attribute.component);
1840
1885
  const newValue = await recurse(visitor2, { schema: targetSchema, path, getModel }, value);
1841
1886
  set(key, newValue);
1842
- }).onDynamicZone(
1843
- async ({ key, value, attribute, schema, visitor: visitor2, path, getModel }, { set, recurse }) => {
1844
- if (fp.isNil(value)) {
1845
- return;
1846
- }
1847
- if (fp.isObject(value)) {
1848
- const { components } = attribute;
1849
- const newValue = {};
1850
- let newProperties = fp.omit("on", value);
1851
- for (const componentUID of components) {
1852
- const componentSchema = getModel(componentUID);
1853
- const properties = await recurse(
1854
- visitor2,
1855
- { schema: componentSchema, path, getModel },
1856
- value
1857
- );
1858
- newProperties = fp.merge(newProperties, properties);
1859
- }
1860
- Object.assign(newValue, newProperties);
1861
- if ("on" in value && value.on) {
1862
- const newOn = await recurse(visitor2, { schema, path, getModel }, { on: value.on });
1863
- Object.assign(newValue, newOn);
1864
- }
1865
- set(key, newValue);
1866
- } else {
1867
- const newValue = await recurse(visitor2, { schema, path, getModel }, value);
1868
- set(key, newValue);
1869
- }
1887
+ }).onDynamicZone(async ({ key, value, schema, visitor: visitor2, path, getModel }, { set, recurse }) => {
1888
+ if (fp.isNil(value) || !fp.isObject(value)) {
1889
+ return;
1870
1890
  }
1871
- );
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
+ });
1872
1896
  const traverseQueryPopulate = fp.curry(populate.traverse);
1873
1897
  const isStringArray = (value) => fp.isArray(value) && value.every(fp.isString);
1874
1898
  const fields = traverseFactory().intercept(isStringArray, async (visitor2, options, fields2, { recurse }) => {
@@ -2167,13 +2191,16 @@ const index$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
2167
2191
  sanitizers,
2168
2192
  visitors: index$4
2169
2193
  }, Symbol.toStringTag, { value: "Module" }));
2170
- const throwInvalidParam = ({ key, path }) => {
2171
- const msg = path && path !== key ? `Invalid parameter ${key} at ${path}` : `Invalid parameter ${key}`;
2172
- 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
+ });
2173
2200
  };
2174
2201
  const visitor$3 = ({ key, attribute, path }) => {
2175
2202
  if (attribute?.type === "password") {
2176
- throwInvalidParam({ key, path: path.attribute });
2203
+ throwInvalidKey({ key, path: path.attribute });
2177
2204
  }
2178
2205
  };
2179
2206
  const visitor$2 = ({ schema, key, attribute, path }) => {
@@ -2182,7 +2209,7 @@ const visitor$2 = ({ schema, key, attribute, path }) => {
2182
2209
  }
2183
2210
  const isPrivate = attribute.private === true || isPrivateAttribute(schema, key);
2184
2211
  if (isPrivate) {
2185
- throwInvalidParam({ key, path: path.attribute });
2212
+ throwInvalidKey({ key, path: path.attribute });
2186
2213
  }
2187
2214
  };
2188
2215
  const ACTIONS_TO_VERIFY = ["find"];
@@ -2200,7 +2227,7 @@ const throwRestrictedRelations = (auth) => async ({ data, key, attribute, schema
2200
2227
  const scopes = ACTIONS_TO_VERIFY.map((action) => `${element.__type}.${action}`);
2201
2228
  const isAllowed = await hasAccessToSomeScopes(scopes, auth);
2202
2229
  if (!isAllowed) {
2203
- throwInvalidParam({ key, path: path.attribute });
2230
+ throwInvalidKey({ key, path: path.attribute });
2204
2231
  }
2205
2232
  }
2206
2233
  };
@@ -2208,7 +2235,7 @@ const throwRestrictedRelations = (auth) => async ({ data, key, attribute, schema
2208
2235
  const scopes = ACTIONS_TO_VERIFY.map((action) => `${attribute.target}.${action}`);
2209
2236
  const isAllowed = await hasAccessToSomeScopes(scopes, auth);
2210
2237
  if (!isAllowed) {
2211
- throwInvalidParam({ key, path: path.attribute });
2238
+ throwInvalidKey({ key, path: path.attribute });
2212
2239
  }
2213
2240
  };
2214
2241
  const isCreatorRelation = [CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE].includes(key);
@@ -2234,12 +2261,12 @@ const hasAccessToSomeScopes = async (scopes, auth) => {
2234
2261
  };
2235
2262
  const visitor$1 = ({ key, attribute, path }) => {
2236
2263
  if (isMorphToRelationalAttribute(attribute)) {
2237
- throwInvalidParam({ key, path: path.attribute });
2264
+ throwInvalidKey({ key, path: path.attribute });
2238
2265
  }
2239
2266
  };
2240
2267
  const visitor = ({ key, attribute, path }) => {
2241
2268
  if (isDynamicZoneAttribute(attribute)) {
2242
- throwInvalidParam({ key, path: path.attribute });
2269
+ throwInvalidKey({ key, path: path.attribute });
2243
2270
  }
2244
2271
  };
2245
2272
  const throwDisallowedFields = (allowedFields = null) => ({ key, path: { attribute: path } }) => {
@@ -2261,7 +2288,7 @@ const throwDisallowedFields = (allowedFields = null) => ({ key, path: { attribut
2261
2288
  if (isPathAllowed) {
2262
2289
  return;
2263
2290
  }
2264
- throwInvalidParam({ key, path });
2291
+ throwInvalidKey({ key, path });
2265
2292
  };
2266
2293
  const getContainedPaths = (path) => {
2267
2294
  const parts = fp.toPath(path);
@@ -2271,7 +2298,7 @@ const getContainedPaths = (path) => {
2271
2298
  };
2272
2299
  const throwRestrictedFields = (restrictedFields = null) => ({ key, path: { attribute: path } }) => {
2273
2300
  if (restrictedFields === null) {
2274
- throwInvalidParam({ key, path });
2301
+ throwInvalidKey({ key, path });
2275
2302
  }
2276
2303
  if (!(fp.isArray(restrictedFields) && restrictedFields.every(fp.isString))) {
2277
2304
  throw new TypeError(
@@ -2279,14 +2306,44 @@ const throwRestrictedFields = (restrictedFields = null) => ({ key, path: { attri
2279
2306
  );
2280
2307
  }
2281
2308
  if (restrictedFields.includes(path)) {
2282
- throwInvalidParam({ key, path });
2309
+ throwInvalidKey({ key, path });
2283
2310
  }
2284
2311
  const isRestrictedNested = restrictedFields.some(
2285
2312
  (allowedPath) => path?.toString().startsWith(`${allowedPath}.`)
2286
2313
  );
2287
2314
  if (isRestrictedNested) {
2288
- throwInvalidParam({ key, path });
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;
2289
2345
  }
2346
+ throwInvalidKey({ key, path: attribute });
2290
2347
  };
2291
2348
  const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2292
2349
  __proto__: null,
@@ -2296,7 +2353,8 @@ const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
2296
2353
  throwPassword: visitor$3,
2297
2354
  throwPrivate: visitor$2,
2298
2355
  throwRestrictedFields,
2299
- throwRestrictedRelations
2356
+ throwRestrictedRelations,
2357
+ throwUnrecognizedFields
2300
2358
  }, Symbol.toStringTag, { value: "Module" }));
2301
2359
  const { ID_ATTRIBUTE: ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE: DOC_ID_ATTRIBUTE$1 } = constants$1;
2302
2360
  const throwPasswords = (ctx) => async (entity) => {
@@ -2317,7 +2375,7 @@ const defaultValidateFilters = fp.curry((ctx, filters2) => {
2317
2375
  }
2318
2376
  const isAttribute = !!attribute;
2319
2377
  if (!isAttribute && !isOperator(key)) {
2320
- throwInvalidParam({ key, path: path.attribute });
2378
+ throwInvalidKey({ key, path: path.attribute });
2321
2379
  }
2322
2380
  }, ctx),
2323
2381
  // dynamic zones from filters
@@ -2342,7 +2400,7 @@ const defaultValidateSort = fp.curry((ctx, sort2) => {
2342
2400
  return;
2343
2401
  }
2344
2402
  if (!attribute) {
2345
- throwInvalidParam({ key, path: path.attribute });
2403
+ throwInvalidKey({ key, path: path.attribute });
2346
2404
  }
2347
2405
  }, ctx),
2348
2406
  // dynamic zones from sort
@@ -2359,7 +2417,7 @@ const defaultValidateSort = fp.curry((ctx, sort2) => {
2359
2417
  return;
2360
2418
  }
2361
2419
  if (!isScalarAttribute(attribute) && fp.isEmpty(value)) {
2362
- throwInvalidParam({ key, path: path.attribute });
2420
+ throwInvalidKey({ key, path: path.attribute });
2363
2421
  }
2364
2422
  }, ctx)
2365
2423
  )(sort2);
@@ -2375,7 +2433,7 @@ const defaultValidateFields = fp.curry((ctx, fields2) => {
2375
2433
  return;
2376
2434
  }
2377
2435
  if (fp.isNil(attribute) || !isScalarAttribute(attribute)) {
2378
- throwInvalidParam({ key, path: path.attribute });
2436
+ throwInvalidKey({ key, path: path.attribute });
2379
2437
  }
2380
2438
  }, ctx),
2381
2439
  // private fields
@@ -2470,15 +2528,18 @@ const createAPIValidators = (opts) => {
2470
2528
  (data2) => {
2471
2529
  if (fp.isObject(data2)) {
2472
2530
  if (ID_ATTRIBUTE in data2) {
2473
- throwInvalidParam({ key: ID_ATTRIBUTE });
2531
+ throwInvalidKey({ key: ID_ATTRIBUTE });
2474
2532
  }
2475
2533
  if (DOC_ID_ATTRIBUTE in data2) {
2476
- throwInvalidParam({ key: DOC_ID_ATTRIBUTE });
2534
+ throwInvalidKey({ key: DOC_ID_ATTRIBUTE });
2477
2535
  }
2478
2536
  }
2537
+ return data2;
2479
2538
  },
2480
2539
  // non-writable attributes
2481
- traverseEntity$1(throwRestrictedFields(nonWritableAttributes), { schema, getModel })
2540
+ traverseEntity$1(throwRestrictedFields(nonWritableAttributes), { schema, getModel }),
2541
+ // unrecognized attributes
2542
+ traverseEntity$1(throwUnrecognizedFields, { schema, getModel })
2482
2543
  ];
2483
2544
  if (auth) {
2484
2545
  transforms.push(
@@ -2489,7 +2550,14 @@ const createAPIValidators = (opts) => {
2489
2550
  );
2490
2551
  }
2491
2552
  opts?.validators?.input?.forEach((validator) => transforms.push(validator(schema)));
2492
- await pipe(...transforms)(data);
2553
+ try {
2554
+ await pipe(...transforms)(data);
2555
+ } catch (e) {
2556
+ if (e instanceof ValidationError) {
2557
+ e.details.source = "body";
2558
+ }
2559
+ throw e;
2560
+ }
2493
2561
  };
2494
2562
  const validateQuery = async (query, schema, { auth } = {}) => {
2495
2563
  if (!schema) {
@@ -2526,7 +2594,15 @@ const createAPIValidators = (opts) => {
2526
2594
  })
2527
2595
  );
2528
2596
  }
2529
- await pipe(...transforms)(filters2);
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;
2605
+ }
2530
2606
  };
2531
2607
  const validateSort = async (sort2, schema, { auth } = {}) => {
2532
2608
  if (!schema) {
@@ -2541,14 +2617,30 @@ const createAPIValidators = (opts) => {
2541
2617
  })
2542
2618
  );
2543
2619
  }
2544
- await pipe(...transforms)(sort2);
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;
2628
+ }
2545
2629
  };
2546
2630
  const validateFields = async (fields2, schema) => {
2547
2631
  if (!schema) {
2548
2632
  throw new Error("Missing schema in validateFields");
2549
2633
  }
2550
2634
  const transforms = [defaultValidateFields({ schema, getModel })];
2551
- await pipe(...transforms)(fields2);
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
+ }
2552
2644
  };
2553
2645
  const validatePopulate = async (populate2, schema, { auth } = {}) => {
2554
2646
  if (!schema) {
@@ -2563,7 +2655,15 @@ const createAPIValidators = (opts) => {
2563
2655
  })
2564
2656
  );
2565
2657
  }
2566
- await pipe(...transforms)(populate2);
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;
2666
+ }
2567
2667
  };
2568
2668
  return {
2569
2669
  input: validateInput,
@@ -2647,8 +2747,57 @@ const withDefaultPagination = (args, { defaults = {}, maxLimit = -1 } = {}) => {
2647
2747
  );
2648
2748
  return replacePaginationAttributes(args);
2649
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
+ };
2650
2797
  const pagination = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2651
2798
  __proto__: null,
2799
+ transformOffsetPaginationInfo,
2800
+ transformPagedPaginationInfo,
2652
2801
  withDefaultPagination
2653
2802
  }, Symbol.toStringTag, { value: "Module" }));
2654
2803
  const SUPPORTED_PACKAGE_MANAGERS = ["npm", "yarn"];
@@ -2772,9 +2921,9 @@ const toRegressedEnumValue = (value) => slugify__default.default(value, {
2772
2921
  separator: "_"
2773
2922
  });
2774
2923
  const getCommonPath = (...paths) => {
2775
- const [segments, ...otherSegments] = paths.map((it) => ___default.default.split(it, "/"));
2776
- return ___default.default.join(
2777
- ___default.default.takeWhile(segments, (str, index2) => otherSegments.every((it) => it[index2] === str)),
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)),
2778
2927
  "/"
2779
2928
  );
2780
2929
  };
@@ -2796,7 +2945,7 @@ const joinBy = (joint, ...args) => {
2796
2945
  return url + joint + trim(path);
2797
2946
  }, "");
2798
2947
  };
2799
- const toKebabCase = (value) => _$1.kebabCase(value);
2948
+ const toKebabCase = (value) => _.kebabCase(value);
2800
2949
  const strings = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2801
2950
  __proto__: null,
2802
2951
  getCommonPath,
@@ -2816,9 +2965,9 @@ const arrays = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
2816
2965
  __proto__: null,
2817
2966
  includesString
2818
2967
  }, Symbol.toStringTag, { value: "Module" }));
2819
- const keysDeep = (obj, path = []) => !___default.default.isObject(obj) ? [path.join(".")] : ___default.default.reduce(
2968
+ const keysDeep = (obj, path = []) => !___namespace.default.isObject(obj) ? [path.join(".")] : ___namespace.default.reduce(
2820
2969
  obj,
2821
- (acc, next, key) => ___default.default.concat(acc, keysDeep(next, [...path, key])),
2970
+ (acc, next, key) => ___namespace.default.concat(acc, keysDeep(next, [...path, key])),
2822
2971
  []
2823
2972
  );
2824
2973
  const objects = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
@@ -2882,8 +3031,8 @@ function printValue(value, quoteStrings) {
2882
3031
  );
2883
3032
  }
2884
3033
  const strapiID = () => new StrapiIDSchema();
2885
- const isNotNilTest = (value) => !___default.default.isNil(value);
2886
- const isNotNullTest = (value) => !___default.default.isNull(value);
3034
+ const isNotNilTest = (value) => !___namespace.default.isNil(value);
3035
+ const isNotNullTest = (value) => !___namespace.default.isNull(value);
2887
3036
  yup__namespace.addMethod(yup__namespace.mixed, "notNil", function isNotNill(msg = "${path} must be defined.") {
2888
3037
  return this.test("defined", msg, isNotNilTest);
2889
3038
  });
@@ -2894,7 +3043,7 @@ yup__namespace.addMethod(yup__namespace.mixed, "isFunction", function isFunction
2894
3043
  return this.test(
2895
3044
  "is a function",
2896
3045
  message,
2897
- (value) => ___default.default.isUndefined(value) || ___default.default.isFunction(value)
3046
+ (value) => ___namespace.default.isUndefined(value) || ___namespace.default.isFunction(value)
2898
3047
  );
2899
3048
  });
2900
3049
  yup__namespace.addMethod(
@@ -2926,7 +3075,7 @@ yup__namespace.addMethod(
2926
3075
  return this.test(
2927
3076
  "only contains functions",
2928
3077
  message,
2929
- (value) => ___default.default.isUndefined(value) || value && Object.values(value).every(___default.default.isFunction)
3078
+ (value) => ___namespace.default.isUndefined(value) || value && Object.values(value).every(___namespace.default.isFunction)
2930
3079
  );
2931
3080
  }
2932
3081
  );
@@ -3001,6 +3150,27 @@ const relations = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePro
3001
3150
  isManyToAny,
3002
3151
  isOneToAny
3003
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
+ });
3004
3174
  exports.arrays = arrays;
3005
3175
  exports.async = async;
3006
3176
  exports.contentTypes = contentTypes;
@@ -3030,5 +3200,6 @@ exports.traverseEntity = traverseEntity$1;
3030
3200
  exports.validate = index;
3031
3201
  exports.validateYupSchema = validateYupSchema;
3032
3202
  exports.validateYupSchemaSync = validateYupSchemaSync;
3203
+ exports.validateZod = validateZod;
3033
3204
  exports.yup = yup;
3034
3205
  //# sourceMappingURL=index.js.map