@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 +409 -188
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +410 -189
- package/dist/index.mjs.map +1 -1
- package/dist/provider-factory.d.ts +7 -8
- package/dist/provider-factory.d.ts.map +1 -1
- package/dist/relations.d.ts +3 -0
- package/dist/relations.d.ts.map +1 -1
- package/dist/sanitize/visitors/remove-restricted-relations.d.ts.map +1 -1
- package/dist/traverse/factory.d.ts +1 -1
- package/dist/traverse/query-fields.d.ts.map +1 -1
- package/dist/traverse/query-populate.d.ts.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/validate/utils.d.ts +1 -0
- package/dist/validate/utils.d.ts.map +1 -1
- package/dist/validate/validators.d.ts +19 -7
- package/dist/validate/validators.d.ts.map +1 -1
- package/dist/validate/visitors/throw-restricted-relations.d.ts.map +1 -1
- package/package.json +4 -4
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
|
|
1360
|
-
|
|
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
|
-
|
|
1422
|
+
allowedElements.push(element);
|
|
1365
1423
|
}
|
|
1366
1424
|
}
|
|
1367
|
-
|
|
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) =>
|
|
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(
|
|
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
|
-
|
|
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
|
|
2367
|
-
|
|
2368
|
-
|
|
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
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
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
|
|
2393
|
-
|
|
2394
|
-
|
|
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
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
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
|
|
2426
|
-
|
|
2427
|
-
|
|
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
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
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
|
|
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
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
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
|
|
2811
|
+
await validateFilters2(filters2, schema, { auth });
|
|
2569
2812
|
}
|
|
2570
2813
|
if (sort2) {
|
|
2571
|
-
await
|
|
2814
|
+
await validateSort2(sort2, schema, { auth });
|
|
2572
2815
|
}
|
|
2573
2816
|
if (fields2) {
|
|
2574
|
-
await
|
|
2817
|
+
await validateFields2(fields2, schema);
|
|
2575
2818
|
}
|
|
2576
2819
|
if (populate2 && populate2 !== "*") {
|
|
2577
|
-
await
|
|
2820
|
+
await validatePopulate2(populate2, schema);
|
|
2578
2821
|
}
|
|
2579
2822
|
};
|
|
2580
|
-
const
|
|
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) =>
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
2672
|
-
sort:
|
|
2673
|
-
fields:
|
|
2674
|
-
populate:
|
|
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);
|