@strapi/utils 5.0.0-beta.6 → 5.0.0-beta.7

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.
@@ -28,6 +28,13 @@ declare const getOptions: (model: Model) => {
28
28
  });
29
29
  declare const hasDraftAndPublish: (model: Model) => boolean;
30
30
  declare const isDraft: <T extends object>(data: T, model: Model) => boolean;
31
+ declare const isSchema: (data: unknown) => data is Model;
32
+ declare const isComponentSchema: (data: unknown) => data is Model & {
33
+ modelType: 'component';
34
+ };
35
+ declare const isContentTypeSchema: (data: unknown) => data is Model & {
36
+ modelType: 'contentType';
37
+ };
31
38
  declare const isSingleType: ({ kind }: {
32
39
  kind?: string | undefined;
33
40
  }) => boolean;
@@ -37,12 +44,13 @@ declare const isCollectionType: ({ kind }: {
37
44
  declare const isKind: (kind: Kind) => (model: Model) => boolean;
38
45
  declare const getPrivateAttributes: (model: Model) => string[];
39
46
  declare const isPrivateAttribute: (model: Model, attributeName: string) => boolean;
40
- declare const isScalarAttribute: (attribute: Attribute) => boolean;
41
- declare const isMediaAttribute: (attribute: Attribute) => boolean;
42
- declare const isRelationalAttribute: (attribute: Attribute) => attribute is RelationalAttribute;
47
+ declare const isScalarAttribute: (attribute?: Attribute) => boolean | undefined;
48
+ declare const isMediaAttribute: (attribute?: Attribute) => boolean;
49
+ declare const isRelationalAttribute: (attribute?: Attribute) => attribute is RelationalAttribute;
50
+ declare const hasRelationReordering: (attribute?: Attribute) => boolean;
43
51
  declare const isComponentAttribute: (attribute: Attribute) => attribute is ComponentAttribute | DynamicZoneAttribute;
44
- declare const isDynamicZoneAttribute: (attribute: Attribute) => attribute is DynamicZoneAttribute;
45
- declare const isMorphToRelationalAttribute: (attribute: Attribute) => boolean;
52
+ declare const isDynamicZoneAttribute: (attribute?: Attribute) => attribute is DynamicZoneAttribute;
53
+ declare const isMorphToRelationalAttribute: (attribute?: Attribute) => boolean;
46
54
  declare const getComponentAttributes: (schema: Model) => string[];
47
55
  declare const getScalarAttributes: (schema: Model) => string[];
48
56
  declare const getRelationalAttributes: (schema: Model) => string[];
@@ -58,5 +66,5 @@ declare const isTypedAttribute: (attribute: Attribute, type: string) => boolean;
58
66
  * @returns {string}
59
67
  */
60
68
  declare const getContentTypeRoutePrefix: (contentType: WithRequired<Model, 'info'>) => string;
61
- export { isScalarAttribute, isMediaAttribute, isRelationalAttribute, isComponentAttribute, isDynamicZoneAttribute, isMorphToRelationalAttribute, isTypedAttribute, getPrivateAttributes, isPrivateAttribute, constants, getNonWritableAttributes, getComponentAttributes, getScalarAttributes, getRelationalAttributes, getWritableAttributes, isWritableAttribute, getNonVisibleAttributes, getVisibleAttributes, getTimestamps, getCreatorFields, isVisibleAttribute, getOptions, isDraft, hasDraftAndPublish, isSingleType, isCollectionType, isKind, getContentTypeRoutePrefix, };
69
+ export { isSchema, isContentTypeSchema, isComponentSchema, isScalarAttribute, isMediaAttribute, isRelationalAttribute, hasRelationReordering, isComponentAttribute, isDynamicZoneAttribute, isMorphToRelationalAttribute, isTypedAttribute, getPrivateAttributes, isPrivateAttribute, constants, getNonWritableAttributes, getComponentAttributes, getScalarAttributes, getRelationalAttributes, getWritableAttributes, isWritableAttribute, getNonVisibleAttributes, getVisibleAttributes, getTimestamps, getCreatorFields, isVisibleAttribute, getOptions, isDraft, hasDraftAndPublish, isSingleType, isCollectionType, isKind, getContentTypeRoutePrefix, };
62
70
  //# sourceMappingURL=content-types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"content-types.d.ts","sourceRoot":"","sources":["../src/content-types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,KAAK,EACL,IAAI,EACJ,SAAS,EACT,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,YAAY,EACb,MAAM,SAAS,CAAC;AAejB,QAAA,MAAM,SAAS;;;;;;;;;;CAUd,CAAC;AAEF,QAAA,MAAM,aAAa,UAAW,KAAK,aAYlC,CAAC;AAEF,QAAA,MAAM,gBAAgB,UAAW,KAAK,aAYrC,CAAC;AAEF,QAAA,MAAM,wBAAwB,UAAW,KAAK,aAe7C,CAAC;AAEF,QAAA,MAAM,qBAAqB,UAAW,KAAK,aAI1C,CAAC;AAEF,QAAA,MAAM,mBAAmB,UAAW,KAAK,iBAAiB,MAAM,YAE/D,CAAC;AAEF,QAAA,MAAM,uBAAuB,UAAW,KAAK,aAQ5C,CAAC;AAEF,QAAA,MAAM,oBAAoB,UAAW,KAAK,aAEzC,CAAC;AAEF,QAAA,MAAM,kBAAkB,UAAW,KAAK,iBAAiB,MAAM,YAE9D,CAAC;AAEF,QAAA,MAAM,UAAU,UAAW,KAAK;;;;;;;EACmC,CAAC;AAEpE,QAAA,MAAM,kBAAkB,UAAW,KAAK,YACiB,CAAC;AAE1D,QAAA,MAAM,OAAO,2BAA4B,CAAC,SAAS,KAAK,YACmB,CAAC;AAE5E,QAAA,MAAM,YAAY;;aAAuD,CAAC;AAC1E,QAAA,MAAM,gBAAgB;;aAA2D,CAAC;AAClF,QAAA,MAAM,MAAM,SAAU,IAAI,aAAa,KAAK,YAAwB,CAAC;AAQrE,QAAA,MAAM,oBAAoB,UAAW,KAAK,aAKzC,CAAC;AAEF,QAAA,MAAM,kBAAkB,UAAW,KAAK,iBAAiB,MAAM,YAK9D,CAAC;AAEF,QAAA,MAAM,iBAAiB,cAAe,SAAS,YAE9C,CAAC;AACF,QAAA,MAAM,gBAAgB,cAAe,SAAS,YAAgC,CAAC;AAC/E,QAAA,MAAM,qBAAqB,cAAe,SAAS,qCACnB,CAAC;AAEjC,QAAA,MAAM,oBAAoB,cACb,SAAS,2DAEkC,CAAC;AAEzD,QAAA,MAAM,sBAAsB,cAAe,SAAS,sCACjB,CAAC;AACpC,QAAA,MAAM,4BAA4B,cAAe,SAAS,YAEzD,CAAC;AAEF,QAAA,MAAM,sBAAsB,WAAY,KAAK,aAS5C,CAAC;AAEF,QAAA,MAAM,mBAAmB,WAAY,KAAK,aASzC,CAAC;AAEF,QAAA,MAAM,uBAAuB,WAAY,KAAK,aAS7C,CAAC;AAEF;;;;GAIG;AACH,QAAA,MAAM,gBAAgB,cAAe,SAAS,QAAQ,MAAM,YAE3D,CAAC;AAEF;;;;GAIG;AACH,QAAA,MAAM,yBAAyB,gBAAiB,aAAa,KAAK,EAAE,MAAM,CAAC,WAI1E,CAAC;AAEF,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,EACtB,4BAA4B,EAC5B,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,SAAS,EACT,wBAAwB,EACxB,sBAAsB,EACtB,mBAAmB,EACnB,uBAAuB,EACvB,qBAAqB,EACrB,mBAAmB,EACnB,uBAAuB,EACvB,oBAAoB,EACpB,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,UAAU,EACV,OAAO,EACP,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EAChB,MAAM,EACN,yBAAyB,GAC1B,CAAC"}
1
+ {"version":3,"file":"content-types.d.ts","sourceRoot":"","sources":["../src/content-types.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -310,6 +310,15 @@ const isVisibleAttribute = (model, attributeName) => {
310
310
  const getOptions = (model) => ___namespace.default.assign({ draftAndPublish: false }, ___namespace.default.get(model, "options", {}));
311
311
  const hasDraftAndPublish = (model) => ___namespace.default.get(model, "options.draftAndPublish", false) === true;
312
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
+ };
313
322
  const isSingleType = ({ kind = COLLECTION_TYPE }) => kind === SINGLE_TYPE;
314
323
  const isCollectionType = ({ kind = COLLECTION_TYPE }) => kind === COLLECTION_TYPE;
315
324
  const isKind = (kind) => (model) => model.kind === kind;
@@ -330,14 +339,16 @@ const isPrivateAttribute = (model, attributeName) => {
330
339
  return getStoredPrivateAttributes(model).includes(attributeName);
331
340
  };
332
341
  const isScalarAttribute = (attribute) => {
333
- return !["media", "component", "relation", "dynamiczone"].includes(attribute?.type);
342
+ return attribute && !["media", "component", "relation", "dynamiczone"].includes(attribute.type);
334
343
  };
335
344
  const isMediaAttribute = (attribute) => attribute?.type === "media";
336
345
  const isRelationalAttribute = (attribute) => attribute?.type === "relation";
346
+ const HAS_RELATION_REORDERING = ["manyToMany", "manyToOne", "oneToMany"];
347
+ const hasRelationReordering = (attribute) => isRelationalAttribute(attribute) && HAS_RELATION_REORDERING.includes(attribute.relation);
337
348
  const isComponentAttribute = (attribute) => ["component", "dynamiczone"].includes(attribute?.type);
338
- const isDynamicZoneAttribute = (attribute) => attribute?.type === "dynamiczone";
349
+ const isDynamicZoneAttribute = (attribute) => !!attribute && attribute.type === "dynamiczone";
339
350
  const isMorphToRelationalAttribute = (attribute) => {
340
- return isRelationalAttribute(attribute) && attribute?.relation?.startsWith?.("morphTo");
351
+ return !!attribute && isRelationalAttribute(attribute) && attribute.relation?.startsWith?.("morphTo");
341
352
  };
342
353
  const getComponentAttributes = (schema) => {
343
354
  return ___namespace.default.reduce(
@@ -394,8 +405,11 @@ const contentTypes = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.define
394
405
  getVisibleAttributes,
395
406
  getWritableAttributes,
396
407
  hasDraftAndPublish,
408
+ hasRelationReordering,
397
409
  isCollectionType,
398
410
  isComponentAttribute,
411
+ isComponentSchema,
412
+ isContentTypeSchema,
399
413
  isDraft,
400
414
  isDynamicZoneAttribute,
401
415
  isKind,
@@ -404,6 +418,7 @@ const contentTypes = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.define
404
418
  isPrivateAttribute,
405
419
  isRelationalAttribute,
406
420
  isScalarAttribute,
421
+ isSchema,
407
422
  isSingleType,
408
423
  isTypedAttribute,
409
424
  isVisibleAttribute,
@@ -558,28 +573,29 @@ const providerFactory = (options = {}) => {
558
573
  };
559
574
  const traverseEntity = async (visitor2, options, entity) => {
560
575
  const { path = { raw: null, attribute: null }, schema, getModel } = options;
576
+ let parent = options.parent;
561
577
  const traverseMorphRelationTarget = async (visitor22, path2, entry) => {
562
578
  const targetSchema = getModel(entry.__type);
563
- const traverseOptions = { schema: targetSchema, path: path2, getModel };
579
+ const traverseOptions = { schema: targetSchema, path: path2, getModel, parent };
564
580
  return traverseEntity(visitor22, traverseOptions, entry);
565
581
  };
566
582
  const traverseRelationTarget = (schema2) => async (visitor22, path2, entry) => {
567
- const traverseOptions = { schema: schema2, path: path2, getModel };
583
+ const traverseOptions = { schema: schema2, path: path2, getModel, parent };
568
584
  return traverseEntity(visitor22, traverseOptions, entry);
569
585
  };
570
586
  const traverseMediaTarget = async (visitor22, path2, entry) => {
571
587
  const targetSchemaUID = "plugin::upload.file";
572
588
  const targetSchema = getModel(targetSchemaUID);
573
- const traverseOptions = { schema: targetSchema, path: path2, getModel };
589
+ const traverseOptions = { schema: targetSchema, path: path2, getModel, parent };
574
590
  return traverseEntity(visitor22, traverseOptions, entry);
575
591
  };
576
592
  const traverseComponent = async (visitor22, path2, schema2, entry) => {
577
- const traverseOptions = { schema: schema2, path: path2, getModel };
593
+ const traverseOptions = { schema: schema2, path: path2, getModel, parent };
578
594
  return traverseEntity(visitor22, traverseOptions, entry);
579
595
  };
580
596
  const visitDynamicZoneEntry = async (visitor22, path2, entry) => {
581
597
  const targetSchema = getModel(entry.__component);
582
- const traverseOptions = { schema: targetSchema, path: path2, getModel };
598
+ const traverseOptions = { schema: targetSchema, path: path2, getModel, parent };
583
599
  return traverseEntity(visitor22, traverseOptions, entry);
584
600
  };
585
601
  if (!fp.isObject(entity) || fp.isNil(schema)) {
@@ -591,9 +607,6 @@ const traverseEntity = async (visitor2, options, entity) => {
591
607
  for (let i = 0; i < keys.length; i += 1) {
592
608
  const key = keys[i];
593
609
  const attribute = schema.attributes[key];
594
- if (fp.isNil(attribute)) {
595
- continue;
596
- }
597
610
  const newPath = { ...path };
598
611
  newPath.raw = fp.isNil(path.raw) ? key : `${path.raw}.${key}`;
599
612
  if (!fp.isNil(attribute)) {
@@ -606,13 +619,15 @@ const traverseEntity = async (visitor2, options, entity) => {
606
619
  value: copy[key],
607
620
  attribute,
608
621
  path: newPath,
609
- getModel
622
+ getModel,
623
+ parent
610
624
  };
611
625
  await visitor2(visitorOptions, visitorUtils);
612
626
  const value = copy[key];
613
- if (fp.isNil(value)) {
627
+ if (fp.isNil(value) || fp.isNil(attribute)) {
614
628
  continue;
615
629
  }
630
+ parent = { schema, key, attribute, path: newPath };
616
631
  if (isRelationalAttribute(attribute)) {
617
632
  const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
618
633
  const method = isMorphRelation ? traverseMorphRelationTarget : traverseRelationTarget(getModel(attribute.target));
@@ -2180,13 +2195,16 @@ const index$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
2180
2195
  sanitizers,
2181
2196
  visitors: index$4
2182
2197
  }, Symbol.toStringTag, { value: "Module" }));
2183
- const throwInvalidParam = ({ key, path }) => {
2184
- const msg = path && path !== key ? `Invalid parameter ${key} at ${path}` : `Invalid parameter ${key}`;
2185
- throw new ValidationError(msg);
2198
+ const throwInvalidKey = ({ key, path }) => {
2199
+ const msg = path && path !== key ? `Invalid key ${key} at ${path}` : `Invalid key ${key}`;
2200
+ throw new ValidationError(msg, {
2201
+ key,
2202
+ path
2203
+ });
2186
2204
  };
2187
2205
  const visitor$3 = ({ key, attribute, path }) => {
2188
2206
  if (attribute?.type === "password") {
2189
- throwInvalidParam({ key, path: path.attribute });
2207
+ throwInvalidKey({ key, path: path.attribute });
2190
2208
  }
2191
2209
  };
2192
2210
  const visitor$2 = ({ schema, key, attribute, path }) => {
@@ -2195,7 +2213,7 @@ const visitor$2 = ({ schema, key, attribute, path }) => {
2195
2213
  }
2196
2214
  const isPrivate = attribute.private === true || isPrivateAttribute(schema, key);
2197
2215
  if (isPrivate) {
2198
- throwInvalidParam({ key, path: path.attribute });
2216
+ throwInvalidKey({ key, path: path.attribute });
2199
2217
  }
2200
2218
  };
2201
2219
  const ACTIONS_TO_VERIFY = ["find"];
@@ -2213,7 +2231,7 @@ const throwRestrictedRelations = (auth) => async ({ data, key, attribute, schema
2213
2231
  const scopes = ACTIONS_TO_VERIFY.map((action) => `${element.__type}.${action}`);
2214
2232
  const isAllowed = await hasAccessToSomeScopes(scopes, auth);
2215
2233
  if (!isAllowed) {
2216
- throwInvalidParam({ key, path: path.attribute });
2234
+ throwInvalidKey({ key, path: path.attribute });
2217
2235
  }
2218
2236
  }
2219
2237
  };
@@ -2221,7 +2239,7 @@ const throwRestrictedRelations = (auth) => async ({ data, key, attribute, schema
2221
2239
  const scopes = ACTIONS_TO_VERIFY.map((action) => `${attribute.target}.${action}`);
2222
2240
  const isAllowed = await hasAccessToSomeScopes(scopes, auth);
2223
2241
  if (!isAllowed) {
2224
- throwInvalidParam({ key, path: path.attribute });
2242
+ throwInvalidKey({ key, path: path.attribute });
2225
2243
  }
2226
2244
  };
2227
2245
  const isCreatorRelation = [CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE].includes(key);
@@ -2247,12 +2265,12 @@ const hasAccessToSomeScopes = async (scopes, auth) => {
2247
2265
  };
2248
2266
  const visitor$1 = ({ key, attribute, path }) => {
2249
2267
  if (isMorphToRelationalAttribute(attribute)) {
2250
- throwInvalidParam({ key, path: path.attribute });
2268
+ throwInvalidKey({ key, path: path.attribute });
2251
2269
  }
2252
2270
  };
2253
2271
  const visitor = ({ key, attribute, path }) => {
2254
2272
  if (isDynamicZoneAttribute(attribute)) {
2255
- throwInvalidParam({ key, path: path.attribute });
2273
+ throwInvalidKey({ key, path: path.attribute });
2256
2274
  }
2257
2275
  };
2258
2276
  const throwDisallowedFields = (allowedFields = null) => ({ key, path: { attribute: path } }) => {
@@ -2274,7 +2292,7 @@ const throwDisallowedFields = (allowedFields = null) => ({ key, path: { attribut
2274
2292
  if (isPathAllowed) {
2275
2293
  return;
2276
2294
  }
2277
- throwInvalidParam({ key, path });
2295
+ throwInvalidKey({ key, path });
2278
2296
  };
2279
2297
  const getContainedPaths = (path) => {
2280
2298
  const parts = fp.toPath(path);
@@ -2284,7 +2302,7 @@ const getContainedPaths = (path) => {
2284
2302
  };
2285
2303
  const throwRestrictedFields = (restrictedFields = null) => ({ key, path: { attribute: path } }) => {
2286
2304
  if (restrictedFields === null) {
2287
- throwInvalidParam({ key, path });
2305
+ throwInvalidKey({ key, path });
2288
2306
  }
2289
2307
  if (!(fp.isArray(restrictedFields) && restrictedFields.every(fp.isString))) {
2290
2308
  throw new TypeError(
@@ -2292,15 +2310,45 @@ const throwRestrictedFields = (restrictedFields = null) => ({ key, path: { attri
2292
2310
  );
2293
2311
  }
2294
2312
  if (restrictedFields.includes(path)) {
2295
- throwInvalidParam({ key, path });
2313
+ throwInvalidKey({ key, path });
2296
2314
  }
2297
2315
  const isRestrictedNested = restrictedFields.some(
2298
2316
  (allowedPath) => path?.toString().startsWith(`${allowedPath}.`)
2299
2317
  );
2300
2318
  if (isRestrictedNested) {
2301
- throwInvalidParam({ key, path });
2319
+ throwInvalidKey({ key, path });
2302
2320
  }
2303
2321
  };
2322
+ const ID_FIELDS = [constants$1.DOC_ID_ATTRIBUTE, constants$1.DOC_ID_ATTRIBUTE];
2323
+ const ALLOWED_ROOT_LEVEL_FIELDS = [...ID_FIELDS];
2324
+ const MORPH_TO_ALLOWED_FIELDS = ["__type"];
2325
+ const DYNAMIC_ZONE_ALLOWED_FIELDS = ["__component"];
2326
+ const RELATION_REORDERING_FIELDS = ["connect", "disconnect", "set", "options"];
2327
+ const throwUnrecognizedFields = ({ key, attribute, path, schema, parent }) => {
2328
+ if (attribute) {
2329
+ return;
2330
+ }
2331
+ if (path.attribute === null) {
2332
+ if (ALLOWED_ROOT_LEVEL_FIELDS.includes(key)) {
2333
+ return;
2334
+ }
2335
+ return throwInvalidKey({ key, path: attribute });
2336
+ }
2337
+ if (isMorphToRelationalAttribute(parent?.attribute) && MORPH_TO_ALLOWED_FIELDS.includes(key)) {
2338
+ return;
2339
+ }
2340
+ if (isComponentSchema(schema) && isDynamicZoneAttribute(parent?.attribute) && DYNAMIC_ZONE_ALLOWED_FIELDS.includes(key)) {
2341
+ return;
2342
+ }
2343
+ if (hasRelationReordering(parent?.attribute) && RELATION_REORDERING_FIELDS.includes(key)) {
2344
+ return;
2345
+ }
2346
+ const canUseID = isRelationalAttribute(parent?.attribute) || isMediaAttribute(parent?.attribute);
2347
+ if (canUseID && !ID_FIELDS.includes(key)) {
2348
+ return;
2349
+ }
2350
+ throwInvalidKey({ key, path: attribute });
2351
+ };
2304
2352
  const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2305
2353
  __proto__: null,
2306
2354
  throwDisallowedFields,
@@ -2309,7 +2357,8 @@ const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
2309
2357
  throwPassword: visitor$3,
2310
2358
  throwPrivate: visitor$2,
2311
2359
  throwRestrictedFields,
2312
- throwRestrictedRelations
2360
+ throwRestrictedRelations,
2361
+ throwUnrecognizedFields
2313
2362
  }, Symbol.toStringTag, { value: "Module" }));
2314
2363
  const { ID_ATTRIBUTE: ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE: DOC_ID_ATTRIBUTE$1 } = constants$1;
2315
2364
  const throwPasswords = (ctx) => async (entity) => {
@@ -2330,7 +2379,7 @@ const defaultValidateFilters = fp.curry((ctx, filters2) => {
2330
2379
  }
2331
2380
  const isAttribute = !!attribute;
2332
2381
  if (!isAttribute && !isOperator(key)) {
2333
- throwInvalidParam({ key, path: path.attribute });
2382
+ throwInvalidKey({ key, path: path.attribute });
2334
2383
  }
2335
2384
  }, ctx),
2336
2385
  // dynamic zones from filters
@@ -2355,7 +2404,7 @@ const defaultValidateSort = fp.curry((ctx, sort2) => {
2355
2404
  return;
2356
2405
  }
2357
2406
  if (!attribute) {
2358
- throwInvalidParam({ key, path: path.attribute });
2407
+ throwInvalidKey({ key, path: path.attribute });
2359
2408
  }
2360
2409
  }, ctx),
2361
2410
  // dynamic zones from sort
@@ -2372,7 +2421,7 @@ const defaultValidateSort = fp.curry((ctx, sort2) => {
2372
2421
  return;
2373
2422
  }
2374
2423
  if (!isScalarAttribute(attribute) && fp.isEmpty(value)) {
2375
- throwInvalidParam({ key, path: path.attribute });
2424
+ throwInvalidKey({ key, path: path.attribute });
2376
2425
  }
2377
2426
  }, ctx)
2378
2427
  )(sort2);
@@ -2388,7 +2437,7 @@ const defaultValidateFields = fp.curry((ctx, fields2) => {
2388
2437
  return;
2389
2438
  }
2390
2439
  if (fp.isNil(attribute) || !isScalarAttribute(attribute)) {
2391
- throwInvalidParam({ key, path: path.attribute });
2440
+ throwInvalidKey({ key, path: path.attribute });
2392
2441
  }
2393
2442
  }, ctx),
2394
2443
  // private fields
@@ -2483,15 +2532,18 @@ const createAPIValidators = (opts) => {
2483
2532
  (data2) => {
2484
2533
  if (fp.isObject(data2)) {
2485
2534
  if (ID_ATTRIBUTE in data2) {
2486
- throwInvalidParam({ key: ID_ATTRIBUTE });
2535
+ throwInvalidKey({ key: ID_ATTRIBUTE });
2487
2536
  }
2488
2537
  if (DOC_ID_ATTRIBUTE in data2) {
2489
- throwInvalidParam({ key: DOC_ID_ATTRIBUTE });
2538
+ throwInvalidKey({ key: DOC_ID_ATTRIBUTE });
2490
2539
  }
2491
2540
  }
2541
+ return data2;
2492
2542
  },
2493
2543
  // non-writable attributes
2494
- traverseEntity$1(throwRestrictedFields(nonWritableAttributes), { schema, getModel })
2544
+ traverseEntity$1(throwRestrictedFields(nonWritableAttributes), { schema, getModel }),
2545
+ // unrecognized attributes
2546
+ traverseEntity$1(throwUnrecognizedFields, { schema, getModel })
2495
2547
  ];
2496
2548
  if (auth) {
2497
2549
  transforms.push(
@@ -2502,7 +2554,14 @@ const createAPIValidators = (opts) => {
2502
2554
  );
2503
2555
  }
2504
2556
  opts?.validators?.input?.forEach((validator) => transforms.push(validator(schema)));
2505
- await pipe(...transforms)(data);
2557
+ try {
2558
+ await pipe(...transforms)(data);
2559
+ } catch (e) {
2560
+ if (e instanceof ValidationError) {
2561
+ e.details.source = "body";
2562
+ }
2563
+ throw e;
2564
+ }
2506
2565
  };
2507
2566
  const validateQuery = async (query, schema, { auth } = {}) => {
2508
2567
  if (!schema) {
@@ -2539,7 +2598,15 @@ const createAPIValidators = (opts) => {
2539
2598
  })
2540
2599
  );
2541
2600
  }
2542
- await pipe(...transforms)(filters2);
2601
+ try {
2602
+ await pipe(...transforms)(filters2);
2603
+ } catch (e) {
2604
+ if (e instanceof ValidationError) {
2605
+ e.details.source = "query";
2606
+ e.details.param = "filters";
2607
+ }
2608
+ throw e;
2609
+ }
2543
2610
  };
2544
2611
  const validateSort = async (sort2, schema, { auth } = {}) => {
2545
2612
  if (!schema) {
@@ -2554,14 +2621,30 @@ const createAPIValidators = (opts) => {
2554
2621
  })
2555
2622
  );
2556
2623
  }
2557
- await pipe(...transforms)(sort2);
2624
+ try {
2625
+ await pipe(...transforms)(sort2);
2626
+ } catch (e) {
2627
+ if (e instanceof ValidationError) {
2628
+ e.details.source = "query";
2629
+ e.details.param = "sort";
2630
+ }
2631
+ throw e;
2632
+ }
2558
2633
  };
2559
2634
  const validateFields = async (fields2, schema) => {
2560
2635
  if (!schema) {
2561
2636
  throw new Error("Missing schema in validateFields");
2562
2637
  }
2563
2638
  const transforms = [defaultValidateFields({ schema, getModel })];
2564
- await pipe(...transforms)(fields2);
2639
+ try {
2640
+ await pipe(...transforms)(fields2);
2641
+ } catch (e) {
2642
+ if (e instanceof ValidationError) {
2643
+ e.details.source = "query";
2644
+ e.details.param = "fields";
2645
+ }
2646
+ throw e;
2647
+ }
2565
2648
  };
2566
2649
  const validatePopulate = async (populate2, schema, { auth } = {}) => {
2567
2650
  if (!schema) {
@@ -2576,7 +2659,15 @@ const createAPIValidators = (opts) => {
2576
2659
  })
2577
2660
  );
2578
2661
  }
2579
- await pipe(...transforms)(populate2);
2662
+ try {
2663
+ await pipe(...transforms)(populate2);
2664
+ } catch (e) {
2665
+ if (e instanceof ValidationError) {
2666
+ e.details.source = "query";
2667
+ e.details.param = "populate";
2668
+ }
2669
+ throw e;
2670
+ }
2580
2671
  };
2581
2672
  return {
2582
2673
  input: validateInput,
@@ -2660,8 +2751,57 @@ const withDefaultPagination = (args, { defaults = {}, maxLimit = -1 } = {}) => {
2660
2751
  );
2661
2752
  return replacePaginationAttributes(args);
2662
2753
  };
2754
+ const transformPagedPaginationInfo = (paginationInfo, total) => {
2755
+ if (!fp.isNil(paginationInfo.page)) {
2756
+ const page = paginationInfo.page;
2757
+ const pageSize = paginationInfo.pageSize ?? total;
2758
+ return {
2759
+ page,
2760
+ pageSize,
2761
+ pageCount: pageSize > 0 ? Math.ceil(total / pageSize) : 0,
2762
+ total
2763
+ };
2764
+ }
2765
+ if (!fp.isNil(paginationInfo.start)) {
2766
+ const start = paginationInfo.start;
2767
+ const limit = paginationInfo.limit ?? total;
2768
+ return {
2769
+ page: Math.floor(start / limit) + 1,
2770
+ pageSize: limit,
2771
+ pageCount: limit > 0 ? Math.ceil(total / limit) : 0,
2772
+ total
2773
+ };
2774
+ }
2775
+ return {
2776
+ ...paginationInfo,
2777
+ page: 1,
2778
+ pageSize: 10,
2779
+ pageCount: 1,
2780
+ total
2781
+ };
2782
+ };
2783
+ const transformOffsetPaginationInfo = (paginationInfo, total) => {
2784
+ if (!fp.isNil(paginationInfo.page)) {
2785
+ const limit = paginationInfo.pageSize ?? total;
2786
+ const start = (paginationInfo.page - 1) * limit;
2787
+ return { start, limit, total };
2788
+ }
2789
+ if (!fp.isNil(paginationInfo.start)) {
2790
+ const start = paginationInfo.start;
2791
+ const limit = paginationInfo.limit ?? total;
2792
+ return { start, limit, total };
2793
+ }
2794
+ return {
2795
+ ...paginationInfo,
2796
+ start: 0,
2797
+ limit: 10,
2798
+ total
2799
+ };
2800
+ };
2663
2801
  const pagination = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2664
2802
  __proto__: null,
2803
+ transformOffsetPaginationInfo,
2804
+ transformPagedPaginationInfo,
2665
2805
  withDefaultPagination
2666
2806
  }, Symbol.toStringTag, { value: "Module" }));
2667
2807
  const SUPPORTED_PACKAGE_MANAGERS = ["npm", "yarn"];