@strapi/utils 5.0.0-rc.8 → 5.0.0

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/index.js CHANGED
@@ -544,16 +544,6 @@ const providerFactory = (options = {}) => {
544
544
  get(key) {
545
545
  return state.registry.get(key);
546
546
  },
547
- getWhere(filters2 = {}) {
548
- const items = this.values();
549
- const filtersEntries = Object.entries(filters2);
550
- if (filtersEntries.length === 0) {
551
- return items;
552
- }
553
- return items.filter((item) => {
554
- return filtersEntries.every(([key, value]) => item[key] === value);
555
- });
556
- },
557
547
  values() {
558
548
  return Array.from(state.registry.values());
559
549
  },
@@ -1345,6 +1335,32 @@ const visitor$7 = ({ schema, key, attribute }, { remove }) => {
1345
1335
  remove(key);
1346
1336
  }
1347
1337
  };
1338
+ const MANY_RELATIONS = ["oneToMany", "manyToMany"];
1339
+ const getRelationalFields = (contentType) => {
1340
+ return Object.keys(contentType.attributes).filter((attributeName) => {
1341
+ return contentType.attributes[attributeName].type === "relation";
1342
+ });
1343
+ };
1344
+ const isOneToAny = (attribute) => isRelationalAttribute(attribute) && ["oneToOne", "oneToMany"].includes(attribute.relation);
1345
+ const isManyToAny = (attribute) => isRelationalAttribute(attribute) && ["manyToMany", "manyToOne"].includes(attribute.relation);
1346
+ const isAnyToOne = (attribute) => isRelationalAttribute(attribute) && ["oneToOne", "manyToOne"].includes(attribute.relation);
1347
+ const isAnyToMany = (attribute) => isRelationalAttribute(attribute) && ["oneToMany", "manyToMany"].includes(attribute.relation);
1348
+ const constants = {
1349
+ MANY_RELATIONS
1350
+ };
1351
+ const VALID_RELATION_ORDERING_KEYS = {
1352
+ strict: fp.isBoolean
1353
+ };
1354
+ const relations = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1355
+ __proto__: null,
1356
+ VALID_RELATION_ORDERING_KEYS,
1357
+ constants,
1358
+ getRelationalFields,
1359
+ isAnyToMany,
1360
+ isAnyToOne,
1361
+ isManyToAny,
1362
+ isOneToAny
1363
+ }, Symbol.toStringTag, { value: "Module" }));
1348
1364
  const ACTIONS_TO_VERIFY$1 = ["find"];
1349
1365
  const { CREATED_BY_ATTRIBUTE: CREATED_BY_ATTRIBUTE$1, UPDATED_BY_ATTRIBUTE: UPDATED_BY_ATTRIBUTE$1 } = constants$1;
1350
1366
  const removeRestrictedRelations = (auth) => async ({ data, key, attribute, schema }, { remove, set }) => {
@@ -1356,19 +1372,57 @@ const removeRestrictedRelations = (auth) => async ({ data, key, attribute, schem
1356
1372
  return;
1357
1373
  }
1358
1374
  const handleMorphRelation = async () => {
1359
- const newMorphValue = [];
1360
- for (const element of data[key]) {
1375
+ const elements = data[key];
1376
+ if ("connect" in elements || "set" in elements || "disconnect" in elements) {
1377
+ const newValue = {};
1378
+ const connect = await handleMorphElements(elements.connect || []);
1379
+ const relSet = await handleMorphElements(elements.set || []);
1380
+ const disconnect = await handleMorphElements(elements.disconnect || []);
1381
+ if (connect.length > 0) {
1382
+ newValue.connect = connect;
1383
+ }
1384
+ if (relSet.length > 0) {
1385
+ newValue.set = relSet;
1386
+ }
1387
+ if (disconnect.length > 0) {
1388
+ newValue.disconnect = disconnect;
1389
+ }
1390
+ if ("options" in elements && typeof elements.options === "object" && elements.options !== null) {
1391
+ const filteredOptions = {};
1392
+ Object.keys(elements.options).forEach((key2) => {
1393
+ const validator = VALID_RELATION_ORDERING_KEYS[key2];
1394
+ if (validator && validator(elements.options[key2])) {
1395
+ filteredOptions[key2] = elements.options[key2];
1396
+ }
1397
+ });
1398
+ newValue.options = filteredOptions;
1399
+ }
1400
+ set(key, newValue);
1401
+ } else {
1402
+ const newMorphValue = await handleMorphElements(elements);
1403
+ if (newMorphValue.length === 0) {
1404
+ remove(key);
1405
+ } else {
1406
+ set(key, newMorphValue);
1407
+ }
1408
+ }
1409
+ };
1410
+ const handleMorphElements = async (elements) => {
1411
+ const allowedElements = [];
1412
+ if (!fp.isArray(elements)) {
1413
+ return allowedElements;
1414
+ }
1415
+ for (const element of elements) {
1416
+ if (!fp.isObject(element) || !("__type" in element)) {
1417
+ continue;
1418
+ }
1361
1419
  const scopes = ACTIONS_TO_VERIFY$1.map((action) => `${element.__type}.${action}`);
1362
1420
  const isAllowed = await hasAccessToSomeScopes$1(scopes, auth);
1363
1421
  if (isAllowed) {
1364
- newMorphValue.push(element);
1422
+ allowedElements.push(element);
1365
1423
  }
1366
1424
  }
1367
- if (newMorphValue.length === 0) {
1368
- remove(key);
1369
- } else {
1370
- set(key, newMorphValue);
1371
- }
1425
+ return allowedElements;
1372
1426
  };
1373
1427
  const handleRegularRelation = async () => {
1374
1428
  const scopes = ACTIONS_TO_VERIFY$1.map((action) => `${attribute.target}.${action}`);
@@ -1894,10 +1948,17 @@ const populate = traverseFactory().intercept(isStringArray$1, async (visitor2, o
1894
1948
  }
1895
1949
  });
1896
1950
  const traverseQueryPopulate = fp.curry(populate.traverse);
1897
- const isStringArray = (value) => fp.isArray(value) && value.every(fp.isString);
1951
+ const isStringArray = (value) => {
1952
+ return fp.isArray(value) && value.every(fp.isString);
1953
+ };
1898
1954
  const fields = traverseFactory().intercept(isStringArray, async (visitor2, options, fields2, { recurse }) => {
1899
1955
  return Promise.all(fields2.map((field) => recurse(visitor2, options, field)));
1900
- }).intercept((value) => fp.eq("*", value), fp.constant("*")).parse(fp.isString, () => ({
1956
+ }).intercept(
1957
+ (value) => fp.isString(value) && value.includes(","),
1958
+ (visitor2, options, fields2, { recurse }) => {
1959
+ return Promise.all(fields2.split(",").map((field) => recurse(visitor2, options, field)));
1960
+ }
1961
+ ).intercept((value) => fp.eq("*", value), fp.constant("*")).parse(fp.isString, () => ({
1901
1962
  transform: fp.trim,
1902
1963
  remove(key, data) {
1903
1964
  return data === key ? void 0 : data;
@@ -2198,6 +2259,15 @@ const throwInvalidKey = ({ key, path }) => {
2198
2259
  path
2199
2260
  });
2200
2261
  };
2262
+ const asyncCurry = (fn) => {
2263
+ const curried = (...args) => {
2264
+ if (args.length >= fn.length) {
2265
+ return fn(...args);
2266
+ }
2267
+ return (...moreArgs) => curried(...args, ...moreArgs);
2268
+ };
2269
+ return curried;
2270
+ };
2201
2271
  const visitor$3 = ({ key, attribute, path }) => {
2202
2272
  if (attribute?.type === "password") {
2203
2273
  throwInvalidKey({ key, path: path.attribute });
@@ -2223,7 +2293,40 @@ const throwRestrictedRelations = (auth) => async ({ data, key, attribute, schema
2223
2293
  return;
2224
2294
  }
2225
2295
  const handleMorphRelation = async () => {
2226
- for (const element of data[key]) {
2296
+ const elements = data[key];
2297
+ if ("connect" in elements || "set" in elements || "disconnect" in elements || "options" in elements) {
2298
+ await handleMorphElements(elements.connect || []);
2299
+ await handleMorphElements(elements.set || []);
2300
+ await handleMorphElements(elements.disconnect || []);
2301
+ if ("options" in elements) {
2302
+ if (elements.options === null || elements.options === void 0) {
2303
+ return;
2304
+ }
2305
+ if (typeof elements.options !== "object") {
2306
+ throwInvalidKey({ key, path: path.attribute });
2307
+ }
2308
+ const optionKeys = Object.keys(elements.options);
2309
+ for (const key2 of optionKeys) {
2310
+ if (!(key2 in VALID_RELATION_ORDERING_KEYS)) {
2311
+ throwInvalidKey({ key: key2, path: path.attribute });
2312
+ }
2313
+ if (!VALID_RELATION_ORDERING_KEYS[key2](elements.options[key2])) {
2314
+ throwInvalidKey({ key: key2, path: path.attribute });
2315
+ }
2316
+ }
2317
+ }
2318
+ } else {
2319
+ await handleMorphElements(elements);
2320
+ }
2321
+ };
2322
+ const handleMorphElements = async (elements) => {
2323
+ if (!fp.isArray(elements)) {
2324
+ throwInvalidKey({ key, path: path.attribute });
2325
+ }
2326
+ for (const element of elements) {
2327
+ if (!fp.isObject(element) || !("__type" in element)) {
2328
+ throwInvalidKey({ key, path: path.attribute });
2329
+ }
2227
2330
  const scopes = ACTIONS_TO_VERIFY.map((action) => `${element.__type}.${action}`);
2228
2331
  const isAllowed = await hasAccessToSomeScopes(scopes, auth);
2229
2332
  if (!isAllowed) {
@@ -2363,154 +2466,294 @@ const throwPasswords = (ctx) => async (entity) => {
2363
2466
  }
2364
2467
  return traverseEntity$1(visitor$3, ctx, entity);
2365
2468
  };
2366
- const defaultValidateFilters = fp.curry((ctx, filters2) => {
2367
- if (!ctx.schema) {
2368
- throw new Error("Missing schema in defaultValidateFilters");
2469
+ const FILTER_TRAVERSALS = [
2470
+ "nonAttributesOperators",
2471
+ "dynamicZones",
2472
+ "morphRelations",
2473
+ "passwords",
2474
+ "private"
2475
+ ];
2476
+ const validateFilters = asyncCurry(
2477
+ async (ctx, filters2, include) => {
2478
+ if (!ctx.schema) {
2479
+ throw new Error("Missing schema in defaultValidateFilters");
2480
+ }
2481
+ const functionsToApply = [];
2482
+ if (include.includes("nonAttributesOperators")) {
2483
+ functionsToApply.push(
2484
+ traverseQueryFilters(({ key, attribute, path }) => {
2485
+ if ([ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE$1].includes(key)) {
2486
+ return;
2487
+ }
2488
+ const isAttribute = !!attribute;
2489
+ if (!isAttribute && !isOperator(key)) {
2490
+ throwInvalidKey({ key, path: path.attribute });
2491
+ }
2492
+ }, ctx)
2493
+ );
2494
+ }
2495
+ if (include.includes("dynamicZones")) {
2496
+ functionsToApply.push(traverseQueryFilters(visitor, ctx));
2497
+ }
2498
+ if (include.includes("morphRelations")) {
2499
+ functionsToApply.push(traverseQueryFilters(visitor$1, ctx));
2500
+ }
2501
+ if (include.includes("passwords")) {
2502
+ functionsToApply.push(traverseQueryFilters(visitor$3, ctx));
2503
+ }
2504
+ if (include.includes("private")) {
2505
+ functionsToApply.push(traverseQueryFilters(visitor$2, ctx));
2506
+ }
2507
+ if (functionsToApply.length === 0) {
2508
+ return filters2;
2509
+ }
2510
+ return pipe(...functionsToApply)(filters2);
2369
2511
  }
2370
- return pipe(
2371
- // keys that are not attributes or valid operators
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),
2381
- // dynamic zones from filters
2382
- traverseQueryFilters(visitor, ctx),
2383
- // morphTo relations from filters; because you can't have deep filtering on morph relations
2384
- traverseQueryFilters(visitor$1, ctx),
2385
- // passwords from filters
2386
- traverseQueryFilters(visitor$3, ctx),
2387
- // private from filters
2388
- traverseQueryFilters(visitor$2, ctx)
2389
- // we allow empty objects to validate and only sanitize them out, so that users may write "lazy" queries without checking their params exist
2390
- )(filters2);
2512
+ );
2513
+ const defaultValidateFilters = asyncCurry(async (ctx, filters2) => {
2514
+ return validateFilters(ctx, filters2, FILTER_TRAVERSALS);
2391
2515
  });
2392
- const defaultValidateSort = fp.curry((ctx, sort2) => {
2393
- if (!ctx.schema) {
2394
- throw new Error("Missing schema in defaultValidateSort");
2516
+ const SORT_TRAVERSALS = [
2517
+ "nonAttributesOperators",
2518
+ "dynamicZones",
2519
+ "morphRelations",
2520
+ "passwords",
2521
+ "private",
2522
+ "nonScalarEmptyKeys"
2523
+ ];
2524
+ const validateSort = asyncCurry(
2525
+ async (ctx, sort2, include) => {
2526
+ if (!ctx.schema) {
2527
+ throw new Error("Missing schema in defaultValidateSort");
2528
+ }
2529
+ const functionsToApply = [];
2530
+ if (include.includes("nonAttributesOperators")) {
2531
+ functionsToApply.push(
2532
+ traverseQuerySort(({ key, attribute, path }) => {
2533
+ if ([ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE$1].includes(key)) {
2534
+ return;
2535
+ }
2536
+ if (!attribute) {
2537
+ throwInvalidKey({ key, path: path.attribute });
2538
+ }
2539
+ }, ctx)
2540
+ );
2541
+ }
2542
+ if (include.includes("dynamicZones")) {
2543
+ functionsToApply.push(traverseQuerySort(visitor, ctx));
2544
+ }
2545
+ if (include.includes("morphRelations")) {
2546
+ functionsToApply.push(traverseQuerySort(visitor$1, ctx));
2547
+ }
2548
+ if (include.includes("passwords")) {
2549
+ functionsToApply.push(traverseQuerySort(visitor$3, ctx));
2550
+ }
2551
+ if (include.includes("private")) {
2552
+ functionsToApply.push(traverseQuerySort(visitor$2, ctx));
2553
+ }
2554
+ if (include.includes("nonScalarEmptyKeys")) {
2555
+ functionsToApply.push(
2556
+ traverseQuerySort(({ key, attribute, value, path }) => {
2557
+ if ([ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE$1].includes(key)) {
2558
+ return;
2559
+ }
2560
+ if (!isScalarAttribute(attribute) && fp.isEmpty(value)) {
2561
+ throwInvalidKey({ key, path: path.attribute });
2562
+ }
2563
+ }, ctx)
2564
+ );
2565
+ }
2566
+ if (functionsToApply.length === 0) {
2567
+ return sort2;
2568
+ }
2569
+ return pipe(...functionsToApply)(sort2);
2395
2570
  }
2396
- return pipe(
2397
- // non attribute keys
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),
2406
- // dynamic zones from sort
2407
- traverseQuerySort(visitor, ctx),
2408
- // morphTo relations from sort
2409
- traverseQuerySort(visitor$1, ctx),
2410
- // private from sort
2411
- traverseQuerySort(visitor$2, ctx),
2412
- // passwords from filters
2413
- traverseQuerySort(visitor$3, ctx),
2414
- // keys for empty non-scalar values
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)
2423
- )(sort2);
2571
+ );
2572
+ const defaultValidateSort = asyncCurry(async (ctx, sort2) => {
2573
+ return validateSort(ctx, sort2, SORT_TRAVERSALS);
2424
2574
  });
2425
- const defaultValidateFields = fp.curry((ctx, fields2) => {
2426
- if (!ctx.schema) {
2427
- throw new Error("Missing schema in defaultValidateFields");
2575
+ const FIELDS_TRAVERSALS = ["scalarAttributes", "privateFields", "passwordFields"];
2576
+ const validateFields = asyncCurry(
2577
+ async (ctx, fields2, include) => {
2578
+ if (!ctx.schema) {
2579
+ throw new Error("Missing schema in defaultValidateFields");
2580
+ }
2581
+ const functionsToApply = [];
2582
+ if (include.includes("scalarAttributes")) {
2583
+ functionsToApply.push(
2584
+ traverseQueryFields(({ key, attribute, path }) => {
2585
+ if ([ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE$1].includes(key)) {
2586
+ return;
2587
+ }
2588
+ if (fp.isNil(attribute) || !isScalarAttribute(attribute)) {
2589
+ throwInvalidKey({ key, path: path.attribute });
2590
+ }
2591
+ }, ctx)
2592
+ );
2593
+ }
2594
+ if (include.includes("privateFields")) {
2595
+ functionsToApply.push(traverseQueryFields(visitor$2, ctx));
2596
+ }
2597
+ if (include.includes("passwordFields")) {
2598
+ functionsToApply.push(traverseQueryFields(visitor$3, ctx));
2599
+ }
2600
+ if (functionsToApply.length === 0) {
2601
+ return fields2;
2602
+ }
2603
+ return pipe(...functionsToApply)(fields2);
2428
2604
  }
2429
- return pipe(
2430
- // Only allow scalar attributes
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),
2439
- // private fields
2440
- traverseQueryFields(visitor$2, ctx),
2441
- // password fields
2442
- traverseQueryFields(visitor$3, ctx)
2443
- )(fields2);
2605
+ );
2606
+ const defaultValidateFields = asyncCurry(async (ctx, fields2) => {
2607
+ return validateFields(ctx, fields2, FIELDS_TRAVERSALS);
2444
2608
  });
2445
- const defaultValidatePopulate = fp.curry((ctx, populate2) => {
2609
+ const POPULATE_TRAVERSALS = ["nonAttributesOperators", "private"];
2610
+ const validatePopulate = asyncCurry(
2611
+ async (ctx, populate2, includes) => {
2612
+ if (!ctx.schema) {
2613
+ throw new Error("Missing schema in defaultValidatePopulate");
2614
+ }
2615
+ const functionsToApply = [];
2616
+ functionsToApply.push(
2617
+ traverseQueryPopulate(async ({ key, path, value, schema, attribute, getModel }, { set }) => {
2618
+ if (attribute) {
2619
+ const isPopulatableAttribute = ["relation", "dynamiczone", "component", "media"].includes(
2620
+ attribute.type
2621
+ );
2622
+ if (!isPopulatableAttribute) {
2623
+ throwInvalidKey({ key, path: path.raw });
2624
+ }
2625
+ return;
2626
+ }
2627
+ if (key === "on") {
2628
+ if (!fp.isObject(value)) {
2629
+ return throwInvalidKey({ key, path: path.raw });
2630
+ }
2631
+ const targets = Object.keys(value);
2632
+ for (const target of targets) {
2633
+ const model = getModel(target);
2634
+ if (!model) {
2635
+ throwInvalidKey({ key: target, path: `${path.raw}.${target}` });
2636
+ }
2637
+ }
2638
+ return;
2639
+ }
2640
+ if (key === "" && value === "*") {
2641
+ return;
2642
+ }
2643
+ if (key === "count") {
2644
+ try {
2645
+ parseType({ type: "boolean", value });
2646
+ return;
2647
+ } catch {
2648
+ throwInvalidKey({ key, path: path.attribute });
2649
+ }
2650
+ }
2651
+ try {
2652
+ parseType({ type: "boolean", value: key });
2653
+ return;
2654
+ } catch {
2655
+ }
2656
+ if (key === "sort") {
2657
+ set(
2658
+ key,
2659
+ await validateSort(
2660
+ {
2661
+ schema,
2662
+ getModel
2663
+ },
2664
+ value,
2665
+ // pass the sort value
2666
+ includes?.sort || SORT_TRAVERSALS
2667
+ )
2668
+ );
2669
+ return;
2670
+ }
2671
+ if (key === "filters") {
2672
+ set(
2673
+ key,
2674
+ await validateFilters(
2675
+ {
2676
+ schema,
2677
+ getModel
2678
+ },
2679
+ value,
2680
+ // pass the filters value
2681
+ includes?.filters || FILTER_TRAVERSALS
2682
+ )
2683
+ );
2684
+ return;
2685
+ }
2686
+ if (key === "fields") {
2687
+ set(
2688
+ key,
2689
+ await validateFields(
2690
+ {
2691
+ schema,
2692
+ getModel
2693
+ },
2694
+ value,
2695
+ // pass the fields value
2696
+ includes?.fields || FIELDS_TRAVERSALS
2697
+ )
2698
+ );
2699
+ return;
2700
+ }
2701
+ if (key === "populate") {
2702
+ set(
2703
+ key,
2704
+ await validatePopulate(
2705
+ {
2706
+ schema,
2707
+ getModel
2708
+ },
2709
+ value,
2710
+ // pass the nested populate value
2711
+ includes
2712
+ // pass down the same includes object
2713
+ )
2714
+ );
2715
+ return;
2716
+ }
2717
+ if (includes?.populate?.includes("nonAttributesOperators")) {
2718
+ throwInvalidKey({ key, path: path.attribute });
2719
+ }
2720
+ }, ctx)
2721
+ );
2722
+ if (includes?.populate?.includes("private")) {
2723
+ functionsToApply.push(traverseQueryPopulate(visitor$2, ctx));
2724
+ }
2725
+ if (functionsToApply.length === 0) {
2726
+ return populate2;
2727
+ }
2728
+ return pipe(...functionsToApply)(populate2);
2729
+ }
2730
+ );
2731
+ const defaultValidatePopulate = asyncCurry(async (ctx, populate2) => {
2446
2732
  if (!ctx.schema) {
2447
2733
  throw new Error("Missing schema in defaultValidatePopulate");
2448
2734
  }
2449
- return pipe(
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),
2503
- // Remove private fields
2504
- traverseQueryPopulate(visitor$2, ctx)
2505
- )(populate2);
2735
+ return validatePopulate(ctx, populate2, {
2736
+ filters: FILTER_TRAVERSALS,
2737
+ sort: SORT_TRAVERSALS,
2738
+ fields: FIELDS_TRAVERSALS,
2739
+ populate: POPULATE_TRAVERSALS
2740
+ });
2506
2741
  });
2507
2742
  const validators = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2508
2743
  __proto__: null,
2744
+ FIELDS_TRAVERSALS,
2745
+ FILTER_TRAVERSALS,
2746
+ POPULATE_TRAVERSALS,
2747
+ SORT_TRAVERSALS,
2509
2748
  defaultValidateFields,
2510
2749
  defaultValidateFilters,
2511
2750
  defaultValidatePopulate,
2512
2751
  defaultValidateSort,
2513
- throwPasswords
2752
+ throwPasswords,
2753
+ validateFields,
2754
+ validateFilters,
2755
+ validatePopulate,
2756
+ validateSort
2514
2757
  }, Symbol.toStringTag, { value: "Module" }));
2515
2758
  const { ID_ATTRIBUTE, DOC_ID_ATTRIBUTE } = constants$1;
2516
2759
  const createAPIValidators = (opts) => {
@@ -2565,24 +2808,24 @@ const createAPIValidators = (opts) => {
2565
2808
  }
2566
2809
  const { filters: filters2, sort: sort2, fields: fields2, populate: populate2 } = query;
2567
2810
  if (filters2) {
2568
- await validateFilters(filters2, schema, { auth });
2811
+ await validateFilters2(filters2, schema, { auth });
2569
2812
  }
2570
2813
  if (sort2) {
2571
- await validateSort(sort2, schema, { auth });
2814
+ await validateSort2(sort2, schema, { auth });
2572
2815
  }
2573
2816
  if (fields2) {
2574
- await validateFields(fields2, schema);
2817
+ await validateFields2(fields2, schema);
2575
2818
  }
2576
2819
  if (populate2 && populate2 !== "*") {
2577
- await validatePopulate(populate2, schema);
2820
+ await validatePopulate2(populate2, schema);
2578
2821
  }
2579
2822
  };
2580
- const validateFilters = async (filters2, schema, { auth } = {}) => {
2823
+ const validateFilters2 = async (filters2, schema, { auth } = {}) => {
2581
2824
  if (!schema) {
2582
2825
  throw new Error("Missing schema in validateFilters");
2583
2826
  }
2584
2827
  if (fp.isArray(filters2)) {
2585
- await Promise.all(filters2.map((filter) => validateFilters(filter, schema, { auth })));
2828
+ await Promise.all(filters2.map((filter) => validateFilters2(filter, schema, { auth })));
2586
2829
  return;
2587
2830
  }
2588
2831
  const transforms = [defaultValidateFilters({ schema, getModel })];
@@ -2604,7 +2847,7 @@ const createAPIValidators = (opts) => {
2604
2847
  throw e;
2605
2848
  }
2606
2849
  };
2607
- const validateSort = async (sort2, schema, { auth } = {}) => {
2850
+ const validateSort2 = async (sort2, schema, { auth } = {}) => {
2608
2851
  if (!schema) {
2609
2852
  throw new Error("Missing schema in validateSort");
2610
2853
  }
@@ -2627,7 +2870,7 @@ const createAPIValidators = (opts) => {
2627
2870
  throw e;
2628
2871
  }
2629
2872
  };
2630
- const validateFields = async (fields2, schema) => {
2873
+ const validateFields2 = async (fields2, schema) => {
2631
2874
  if (!schema) {
2632
2875
  throw new Error("Missing schema in validateFields");
2633
2876
  }
@@ -2642,7 +2885,7 @@ const createAPIValidators = (opts) => {
2642
2885
  throw e;
2643
2886
  }
2644
2887
  };
2645
- const validatePopulate = async (populate2, schema, { auth } = {}) => {
2888
+ const validatePopulate2 = async (populate2, schema, { auth } = {}) => {
2646
2889
  if (!schema) {
2647
2890
  throw new Error("Missing schema in sanitizePopulate");
2648
2891
  }
@@ -2668,10 +2911,10 @@ const createAPIValidators = (opts) => {
2668
2911
  return {
2669
2912
  input: validateInput,
2670
2913
  query: validateQuery,
2671
- filters: validateFilters,
2672
- sort: validateSort,
2673
- fields: validateFields,
2674
- populate: validatePopulate
2914
+ filters: validateFilters2,
2915
+ sort: validateSort2,
2916
+ fields: validateFields2,
2917
+ populate: validatePopulate2
2675
2918
  };
2676
2919
  };
2677
2920
  const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
@@ -3128,28 +3371,6 @@ const yup = /* @__PURE__ */ _mergeNamespaces({
3128
3371
  StrapiIDSchema,
3129
3372
  strapiID
3130
3373
  }, [yup__namespace]);
3131
- const MANY_RELATIONS = ["oneToMany", "manyToMany"];
3132
- const getRelationalFields = (contentType) => {
3133
- return Object.keys(contentType.attributes).filter((attributeName) => {
3134
- return contentType.attributes[attributeName].type === "relation";
3135
- });
3136
- };
3137
- const isOneToAny = (attribute) => isRelationalAttribute(attribute) && ["oneToOne", "oneToMany"].includes(attribute.relation);
3138
- const isManyToAny = (attribute) => isRelationalAttribute(attribute) && ["manyToMany", "manyToOne"].includes(attribute.relation);
3139
- const isAnyToOne = (attribute) => isRelationalAttribute(attribute) && ["oneToOne", "manyToOne"].includes(attribute.relation);
3140
- const isAnyToMany = (attribute) => isRelationalAttribute(attribute) && ["oneToMany", "manyToMany"].includes(attribute.relation);
3141
- const constants = {
3142
- MANY_RELATIONS
3143
- };
3144
- const relations = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
3145
- __proto__: null,
3146
- constants,
3147
- getRelationalFields,
3148
- isAnyToMany,
3149
- isAnyToOne,
3150
- isManyToAny,
3151
- isOneToAny
3152
- }, Symbol.toStringTag, { value: "Module" }));
3153
3374
  const validateZod = (schema) => (data) => {
3154
3375
  try {
3155
3376
  return schema.parse(data);