@strapi/utils 5.0.0-beta.0 → 5.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/async.d.ts.map +1 -1
- package/dist/content-types.d.ts +2 -1
- package/dist/content-types.d.ts.map +1 -1
- package/dist/convert-query-params.d.ts +12 -9
- package/dist/convert-query-params.d.ts.map +1 -1
- package/dist/file.d.ts +10 -4
- package/dist/file.d.ts.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1259 -1242
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1261 -1244
- package/dist/index.mjs.map +1 -1
- package/dist/policy.d.ts +1 -27
- package/dist/policy.d.ts.map +1 -1
- package/dist/sanitize/index.d.ts +23 -14
- package/dist/sanitize/index.d.ts.map +1 -1
- package/dist/sanitize/sanitizers.d.ts +10 -6
- package/dist/sanitize/sanitizers.d.ts.map +1 -1
- package/dist/traverse/factory.d.ts +3 -0
- package/dist/traverse/factory.d.ts.map +1 -1
- package/dist/traverse/index.d.ts +0 -1
- package/dist/traverse/index.d.ts.map +1 -1
- package/dist/traverse/query-populate.d.ts.map +1 -1
- package/dist/traverse-entity.d.ts +2 -0
- package/dist/traverse-entity.d.ts.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/validate/index.d.ts +21 -13
- package/dist/validate/index.d.ts.map +1 -1
- package/dist/validate/validators.d.ts +9 -5
- package/dist/validate/validators.d.ts.map +1 -1
- package/dist/validators.d.ts +2 -2
- package/dist/validators.d.ts.map +1 -1
- package/dist/zod.d.ts +3 -0
- package/dist/zod.d.ts.map +1 -0
- package/package.json +7 -6
package/dist/index.mjs
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import _$1, { kebabCase } from "lodash";
|
|
2
|
-
import { has, union, getOr, assoc, assign, cloneDeep, remove, eq, curry, isArray, isString,
|
|
3
|
-
import pMap from "p-map";
|
|
4
|
-
import { HttpError } from "http-errors";
|
|
2
|
+
import { has, union, getOr, assoc, assign, cloneDeep, remove, eq, curry, isObject, isNil, clone, isArray, isEmpty, toPath, defaults, isString, mergeAll, get, toNumber, isInteger, pick, omit, trim, pipe as pipe$1, split, map as map$1, flatten, first, identity, constant, join, merge, trimChars, trimCharsEnd, trimCharsStart, isNumber } from "lodash/fp";
|
|
5
3
|
import { randomUUID } from "crypto";
|
|
6
4
|
import { machineIdSync } from "node-machine-id";
|
|
7
5
|
import * as yup$1 from "yup";
|
|
6
|
+
import { HttpError } from "http-errors";
|
|
7
|
+
import pMap from "p-map";
|
|
8
8
|
import execa from "execa";
|
|
9
9
|
import preferredPM from "preferred-pm";
|
|
10
10
|
import { Writable } from "node:stream";
|
|
11
11
|
import slugify from "@sindresorhus/slugify";
|
|
12
|
+
import { z } from "zod";
|
|
12
13
|
function _mergeNamespaces(n, m) {
|
|
13
14
|
for (var i = 0; i < m.length; i++) {
|
|
14
15
|
const e = m[i];
|
|
@@ -333,6 +334,17 @@ const getScalarAttributes = (schema) => {
|
|
|
333
334
|
[]
|
|
334
335
|
);
|
|
335
336
|
};
|
|
337
|
+
const getRelationalAttributes = (schema) => {
|
|
338
|
+
return _$1.reduce(
|
|
339
|
+
schema.attributes,
|
|
340
|
+
(acc, attr, attrName) => {
|
|
341
|
+
if (isRelationalAttribute(attr))
|
|
342
|
+
acc.push(attrName);
|
|
343
|
+
return acc;
|
|
344
|
+
},
|
|
345
|
+
[]
|
|
346
|
+
);
|
|
347
|
+
};
|
|
336
348
|
const isTypedAttribute = (attribute, type) => {
|
|
337
349
|
return _$1.has(attribute, "type") && attribute.type === type;
|
|
338
350
|
};
|
|
@@ -349,6 +361,7 @@ const contentTypes = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.define
|
|
|
349
361
|
getNonWritableAttributes,
|
|
350
362
|
getOptions,
|
|
351
363
|
getPrivateAttributes,
|
|
364
|
+
getRelationalAttributes,
|
|
352
365
|
getScalarAttributes,
|
|
353
366
|
getTimestamps,
|
|
354
367
|
getVisibleAttributes,
|
|
@@ -516,201 +529,32 @@ const providerFactory = (options = {}) => {
|
|
|
516
529
|
}
|
|
517
530
|
};
|
|
518
531
|
};
|
|
519
|
-
|
|
520
|
-
const
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
}
|
|
526
|
-
return res;
|
|
532
|
+
const traverseEntity = async (visitor2, options, entity) => {
|
|
533
|
+
const { path = { raw: null, attribute: null }, schema, getModel } = options;
|
|
534
|
+
const traverseMorphRelationTarget = async (visitor22, path2, entry) => {
|
|
535
|
+
const targetSchema = getModel(entry.__type);
|
|
536
|
+
const traverseOptions = { schema: targetSchema, path: path2, getModel };
|
|
537
|
+
return traverseEntity(visitor22, traverseOptions, entry);
|
|
527
538
|
};
|
|
528
|
-
|
|
529
|
-
const
|
|
530
|
-
|
|
531
|
-
let acc = initialValue;
|
|
532
|
-
for (let i = 0; i < mixedArray.length; i += 1) {
|
|
533
|
-
acc = await iteratee(acc, await mixedArray[i], i);
|
|
534
|
-
}
|
|
535
|
-
return acc;
|
|
536
|
-
};
|
|
537
|
-
const async = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
538
|
-
__proto__: null,
|
|
539
|
-
map,
|
|
540
|
-
pipe,
|
|
541
|
-
reduce
|
|
542
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
543
|
-
const visitor$8 = ({ key, attribute }, { remove: remove2 }) => {
|
|
544
|
-
if (attribute?.type === "password") {
|
|
545
|
-
remove2(key);
|
|
546
|
-
}
|
|
547
|
-
};
|
|
548
|
-
const visitor$7 = ({ schema, key, attribute }, { remove: remove2 }) => {
|
|
549
|
-
if (!attribute) {
|
|
550
|
-
return;
|
|
551
|
-
}
|
|
552
|
-
const isPrivate = attribute.private === true || isPrivateAttribute(schema, key);
|
|
553
|
-
if (isPrivate) {
|
|
554
|
-
remove2(key);
|
|
555
|
-
}
|
|
556
|
-
};
|
|
557
|
-
const ACTIONS_TO_VERIFY$1 = ["find"];
|
|
558
|
-
const { CREATED_BY_ATTRIBUTE: CREATED_BY_ATTRIBUTE$1, UPDATED_BY_ATTRIBUTE: UPDATED_BY_ATTRIBUTE$1 } = constants$1;
|
|
559
|
-
const removeRestrictedRelations = (auth) => async ({ data, key, attribute, schema }, { remove: remove2, set }) => {
|
|
560
|
-
if (!attribute) {
|
|
561
|
-
return;
|
|
562
|
-
}
|
|
563
|
-
const isRelation = attribute.type === "relation";
|
|
564
|
-
if (!isRelation) {
|
|
565
|
-
return;
|
|
566
|
-
}
|
|
567
|
-
const handleMorphRelation = async () => {
|
|
568
|
-
const newMorphValue = [];
|
|
569
|
-
for (const element of data[key]) {
|
|
570
|
-
const scopes = ACTIONS_TO_VERIFY$1.map((action) => `${element.__type}.${action}`);
|
|
571
|
-
const isAllowed = await hasAccessToSomeScopes$1(scopes, auth);
|
|
572
|
-
if (isAllowed) {
|
|
573
|
-
newMorphValue.push(element);
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
if (newMorphValue.length === 0) {
|
|
577
|
-
remove2(key);
|
|
578
|
-
} else {
|
|
579
|
-
set(key, newMorphValue);
|
|
580
|
-
}
|
|
539
|
+
const traverseRelationTarget = (schema2) => async (visitor22, path2, entry) => {
|
|
540
|
+
const traverseOptions = { schema: schema2, path: path2, getModel };
|
|
541
|
+
return traverseEntity(visitor22, traverseOptions, entry);
|
|
581
542
|
};
|
|
582
|
-
const
|
|
583
|
-
const
|
|
584
|
-
const
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
543
|
+
const traverseMediaTarget = async (visitor22, path2, entry) => {
|
|
544
|
+
const targetSchemaUID = "plugin::upload.file";
|
|
545
|
+
const targetSchema = getModel(targetSchemaUID);
|
|
546
|
+
const traverseOptions = { schema: targetSchema, path: path2, getModel };
|
|
547
|
+
return traverseEntity(visitor22, traverseOptions, entry);
|
|
548
|
+
};
|
|
549
|
+
const traverseComponent = async (visitor22, path2, schema2, entry) => {
|
|
550
|
+
const traverseOptions = { schema: schema2, path: path2, getModel };
|
|
551
|
+
return traverseEntity(visitor22, traverseOptions, entry);
|
|
552
|
+
};
|
|
553
|
+
const visitDynamicZoneEntry = async (visitor22, path2, entry) => {
|
|
554
|
+
const targetSchema = getModel(entry.__component);
|
|
555
|
+
const traverseOptions = { schema: targetSchema, path: path2, getModel };
|
|
556
|
+
return traverseEntity(visitor22, traverseOptions, entry);
|
|
588
557
|
};
|
|
589
|
-
const isCreatorRelation = [CREATED_BY_ATTRIBUTE$1, UPDATED_BY_ATTRIBUTE$1].includes(key);
|
|
590
|
-
if (isMorphToRelationalAttribute(attribute)) {
|
|
591
|
-
await handleMorphRelation();
|
|
592
|
-
return;
|
|
593
|
-
}
|
|
594
|
-
if (isCreatorRelation && schema.options?.populateCreatorFields) {
|
|
595
|
-
return;
|
|
596
|
-
}
|
|
597
|
-
await handleRegularRelation();
|
|
598
|
-
};
|
|
599
|
-
const hasAccessToSomeScopes$1 = async (scopes, auth) => {
|
|
600
|
-
for (const scope of scopes) {
|
|
601
|
-
try {
|
|
602
|
-
await strapi.auth.verify(auth, { scope });
|
|
603
|
-
return true;
|
|
604
|
-
} catch {
|
|
605
|
-
continue;
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
return false;
|
|
609
|
-
};
|
|
610
|
-
const visitor$6 = ({ key, attribute }, { remove: remove2 }) => {
|
|
611
|
-
if (isMorphToRelationalAttribute(attribute)) {
|
|
612
|
-
remove2(key);
|
|
613
|
-
}
|
|
614
|
-
};
|
|
615
|
-
const visitor$5 = ({ key, attribute }, { remove: remove2 }) => {
|
|
616
|
-
if (isDynamicZoneAttribute(attribute)) {
|
|
617
|
-
remove2(key);
|
|
618
|
-
}
|
|
619
|
-
};
|
|
620
|
-
const removeDisallowedFields = (allowedFields = null) => ({ key, path: { attribute: path } }, { remove: remove2 }) => {
|
|
621
|
-
if (allowedFields === null) {
|
|
622
|
-
return;
|
|
623
|
-
}
|
|
624
|
-
if (!(isArray(allowedFields) && allowedFields.every(isString))) {
|
|
625
|
-
throw new TypeError(
|
|
626
|
-
`Expected array of strings for allowedFields but got "${typeof allowedFields}"`
|
|
627
|
-
);
|
|
628
|
-
}
|
|
629
|
-
if (isNil(path)) {
|
|
630
|
-
return;
|
|
631
|
-
}
|
|
632
|
-
const containedPaths = getContainedPaths$1(path);
|
|
633
|
-
const isPathAllowed = allowedFields.some(
|
|
634
|
-
(p) => containedPaths.includes(p) || p.startsWith(`${path}.`)
|
|
635
|
-
);
|
|
636
|
-
if (isPathAllowed) {
|
|
637
|
-
return;
|
|
638
|
-
}
|
|
639
|
-
remove2(key);
|
|
640
|
-
};
|
|
641
|
-
const getContainedPaths$1 = (path) => {
|
|
642
|
-
const parts = toPath(path);
|
|
643
|
-
return parts.reduce((acc, value, index2, list) => {
|
|
644
|
-
return [...acc, list.slice(0, index2 + 1).join(".")];
|
|
645
|
-
}, []);
|
|
646
|
-
};
|
|
647
|
-
const removeRestrictedFields = (restrictedFields = null) => ({ key, path: { attribute: path } }, { remove: remove2 }) => {
|
|
648
|
-
if (restrictedFields === null) {
|
|
649
|
-
remove2(key);
|
|
650
|
-
return;
|
|
651
|
-
}
|
|
652
|
-
if (!(isArray(restrictedFields) && restrictedFields.every(isString))) {
|
|
653
|
-
throw new TypeError(
|
|
654
|
-
`Expected array of strings for restrictedFields but got "${typeof restrictedFields}"`
|
|
655
|
-
);
|
|
656
|
-
}
|
|
657
|
-
if (restrictedFields.includes(path)) {
|
|
658
|
-
remove2(key);
|
|
659
|
-
return;
|
|
660
|
-
}
|
|
661
|
-
const isRestrictedNested = restrictedFields.some(
|
|
662
|
-
(allowedPath) => path?.toString().startsWith(`${allowedPath}.`)
|
|
663
|
-
);
|
|
664
|
-
if (isRestrictedNested) {
|
|
665
|
-
remove2(key);
|
|
666
|
-
}
|
|
667
|
-
};
|
|
668
|
-
const visitor$4 = ({ schema, key, value }, { set }) => {
|
|
669
|
-
if (key === "" && value === "*") {
|
|
670
|
-
const { attributes } = schema;
|
|
671
|
-
const newPopulateQuery = Object.entries(attributes).filter(
|
|
672
|
-
([, attribute]) => ["relation", "component", "media", "dynamiczone"].includes(attribute.type)
|
|
673
|
-
).reduce((acc, [key2]) => ({ ...acc, [key2]: true }), {});
|
|
674
|
-
set("", newPopulateQuery);
|
|
675
|
-
}
|
|
676
|
-
};
|
|
677
|
-
const visitors$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
678
|
-
__proto__: null,
|
|
679
|
-
expandWildcardPopulate: visitor$4,
|
|
680
|
-
removeDisallowedFields,
|
|
681
|
-
removeDynamicZones: visitor$5,
|
|
682
|
-
removeMorphToRelations: visitor$6,
|
|
683
|
-
removePassword: visitor$8,
|
|
684
|
-
removePrivate: visitor$7,
|
|
685
|
-
removeRestrictedFields,
|
|
686
|
-
removeRestrictedRelations
|
|
687
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
688
|
-
const traverseMorphRelationTarget = async (visitor2, path, entry) => {
|
|
689
|
-
const targetSchema = strapi.getModel(entry.__type);
|
|
690
|
-
const traverseOptions = { schema: targetSchema, path };
|
|
691
|
-
return traverseEntity(visitor2, traverseOptions, entry);
|
|
692
|
-
};
|
|
693
|
-
const traverseRelationTarget = (schema) => async (visitor2, path, entry) => {
|
|
694
|
-
const traverseOptions = { schema, path };
|
|
695
|
-
return traverseEntity(visitor2, traverseOptions, entry);
|
|
696
|
-
};
|
|
697
|
-
const traverseMediaTarget = async (visitor2, path, entry) => {
|
|
698
|
-
const targetSchemaUID = "plugin::upload.file";
|
|
699
|
-
const targetSchema = strapi.getModel(targetSchemaUID);
|
|
700
|
-
const traverseOptions = { schema: targetSchema, path };
|
|
701
|
-
return traverseEntity(visitor2, traverseOptions, entry);
|
|
702
|
-
};
|
|
703
|
-
const traverseComponent = async (visitor2, path, schema, entry) => {
|
|
704
|
-
const traverseOptions = { schema, path };
|
|
705
|
-
return traverseEntity(visitor2, traverseOptions, entry);
|
|
706
|
-
};
|
|
707
|
-
const visitDynamicZoneEntry = async (visitor2, path, entry) => {
|
|
708
|
-
const targetSchema = strapi.getModel(entry.__component);
|
|
709
|
-
const traverseOptions = { schema: targetSchema, path };
|
|
710
|
-
return traverseEntity(visitor2, traverseOptions, entry);
|
|
711
|
-
};
|
|
712
|
-
const traverseEntity = async (visitor2, options, entity) => {
|
|
713
|
-
const { path = { raw: null, attribute: null }, schema } = options;
|
|
714
558
|
if (!isObject(entity) || isNil(schema)) {
|
|
715
559
|
return entity;
|
|
716
560
|
}
|
|
@@ -734,7 +578,8 @@ const traverseEntity = async (visitor2, options, entity) => {
|
|
|
734
578
|
key,
|
|
735
579
|
value: copy[key],
|
|
736
580
|
attribute,
|
|
737
|
-
path: newPath
|
|
581
|
+
path: newPath,
|
|
582
|
+
getModel
|
|
738
583
|
};
|
|
739
584
|
await visitor2(visitorOptions, visitorUtils);
|
|
740
585
|
const value = copy[key];
|
|
@@ -743,7 +588,7 @@ const traverseEntity = async (visitor2, options, entity) => {
|
|
|
743
588
|
}
|
|
744
589
|
if (isRelationalAttribute(attribute)) {
|
|
745
590
|
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
|
746
|
-
const method = isMorphRelation ? traverseMorphRelationTarget : traverseRelationTarget(
|
|
591
|
+
const method = isMorphRelation ? traverseMorphRelationTarget : traverseRelationTarget(getModel(attribute.target));
|
|
747
592
|
if (isArray(value)) {
|
|
748
593
|
const res = new Array(value.length);
|
|
749
594
|
for (let i2 = 0; i2 < value.length; i2 += 1) {
|
|
@@ -768,7 +613,7 @@ const traverseEntity = async (visitor2, options, entity) => {
|
|
|
768
613
|
continue;
|
|
769
614
|
}
|
|
770
615
|
if (attribute.type === "component") {
|
|
771
|
-
const targetSchema =
|
|
616
|
+
const targetSchema = getModel(attribute.component);
|
|
772
617
|
if (isArray(value)) {
|
|
773
618
|
const res = new Array(value.length);
|
|
774
619
|
for (let i2 = 0; i2 < value.length; i2 += 1) {
|
|
@@ -800,80 +645,853 @@ const createVisitorUtils = ({ data }) => ({
|
|
|
800
645
|
}
|
|
801
646
|
});
|
|
802
647
|
const traverseEntity$1 = curry(traverseEntity);
|
|
803
|
-
|
|
804
|
-
const
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
648
|
+
function importDefault(modName) {
|
|
649
|
+
const mod = require(modName);
|
|
650
|
+
return mod && mod.__esModule ? mod.default : mod;
|
|
651
|
+
}
|
|
652
|
+
const machineId = () => {
|
|
653
|
+
try {
|
|
654
|
+
const deviceId = machineIdSync();
|
|
655
|
+
return deviceId;
|
|
656
|
+
} catch (error) {
|
|
657
|
+
const deviceId = randomUUID();
|
|
658
|
+
return deviceId;
|
|
659
|
+
}
|
|
660
|
+
};
|
|
661
|
+
const formatYupInnerError = (yupError) => ({
|
|
662
|
+
path: toPath(yupError.path),
|
|
663
|
+
message: yupError.message,
|
|
664
|
+
name: yupError.name
|
|
665
|
+
});
|
|
666
|
+
const formatYupErrors = (yupError) => ({
|
|
667
|
+
errors: isEmpty(yupError.inner) ? [formatYupInnerError(yupError)] : yupError.inner.map(formatYupInnerError),
|
|
668
|
+
message: yupError.message
|
|
669
|
+
});
|
|
670
|
+
class ApplicationError extends Error {
|
|
671
|
+
name;
|
|
672
|
+
details;
|
|
673
|
+
message;
|
|
674
|
+
constructor(message = "An application error occured", details = {}) {
|
|
675
|
+
super();
|
|
676
|
+
this.name = "ApplicationError";
|
|
677
|
+
this.message = message;
|
|
678
|
+
this.details = details;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
class ValidationError extends ApplicationError {
|
|
682
|
+
constructor(message, details) {
|
|
683
|
+
super(message, details);
|
|
684
|
+
this.name = "ValidationError";
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
class YupValidationError extends ValidationError {
|
|
688
|
+
constructor(yupError, message) {
|
|
689
|
+
super("Validation");
|
|
690
|
+
const { errors: errors2, message: yupMessage } = formatYupErrors(yupError);
|
|
691
|
+
this.message = message || yupMessage;
|
|
692
|
+
this.details = { errors: errors2 };
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
class PaginationError extends ApplicationError {
|
|
696
|
+
constructor(message = "Invalid pagination", details) {
|
|
697
|
+
super(message, details);
|
|
698
|
+
this.name = "PaginationError";
|
|
699
|
+
this.message = message;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
class NotFoundError extends ApplicationError {
|
|
703
|
+
constructor(message = "Entity not found", details) {
|
|
704
|
+
super(message, details);
|
|
705
|
+
this.name = "NotFoundError";
|
|
706
|
+
this.message = message;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
class ForbiddenError extends ApplicationError {
|
|
710
|
+
constructor(message = "Forbidden access", details) {
|
|
711
|
+
super(message, details);
|
|
712
|
+
this.name = "ForbiddenError";
|
|
713
|
+
this.message = message;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
class UnauthorizedError extends ApplicationError {
|
|
717
|
+
constructor(message = "Unauthorized", details) {
|
|
718
|
+
super(message, details);
|
|
719
|
+
this.name = "UnauthorizedError";
|
|
720
|
+
this.message = message;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
class RateLimitError extends ApplicationError {
|
|
724
|
+
constructor(message = "Too many requests, please try again later.", details) {
|
|
725
|
+
super(message, details);
|
|
726
|
+
this.name = "RateLimitError";
|
|
727
|
+
this.message = message;
|
|
728
|
+
this.details = details || {};
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
class PayloadTooLargeError extends ApplicationError {
|
|
732
|
+
constructor(message = "Entity too large", details) {
|
|
733
|
+
super(message, details);
|
|
734
|
+
this.name = "PayloadTooLargeError";
|
|
735
|
+
this.message = message;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
class PolicyError extends ForbiddenError {
|
|
739
|
+
constructor(message = "Policy Failed", details) {
|
|
740
|
+
super(message, details);
|
|
741
|
+
this.name = "PolicyError";
|
|
742
|
+
this.message = message;
|
|
743
|
+
this.details = details || {};
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
class NotImplementedError extends ApplicationError {
|
|
747
|
+
constructor(message = "This feature is not implemented yet", details) {
|
|
748
|
+
super(message, details);
|
|
749
|
+
this.name = "NotImplementedError";
|
|
750
|
+
this.message = message;
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
const errors = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
754
|
+
__proto__: null,
|
|
755
|
+
ApplicationError,
|
|
756
|
+
ForbiddenError,
|
|
757
|
+
HttpError,
|
|
758
|
+
NotFoundError,
|
|
759
|
+
NotImplementedError,
|
|
760
|
+
PaginationError,
|
|
761
|
+
PayloadTooLargeError,
|
|
762
|
+
PolicyError,
|
|
763
|
+
RateLimitError,
|
|
764
|
+
UnauthorizedError,
|
|
765
|
+
ValidationError,
|
|
766
|
+
YupValidationError
|
|
767
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
768
|
+
const handleYupError = (error, errorMessage) => {
|
|
769
|
+
throw new YupValidationError(error, errorMessage);
|
|
770
|
+
};
|
|
771
|
+
const defaultValidationParam = { strict: true, abortEarly: false };
|
|
772
|
+
const validateYupSchema = (schema, options = {}) => async (body, errorMessage) => {
|
|
773
|
+
try {
|
|
774
|
+
const optionsWithDefaults = defaults(defaultValidationParam, options);
|
|
775
|
+
const result = await schema.validate(body, optionsWithDefaults);
|
|
776
|
+
return result;
|
|
777
|
+
} catch (e) {
|
|
778
|
+
if (e instanceof yup$1.ValidationError) {
|
|
779
|
+
handleYupError(e, errorMessage);
|
|
780
|
+
}
|
|
781
|
+
throw e;
|
|
782
|
+
}
|
|
783
|
+
};
|
|
784
|
+
const validateYupSchemaSync = (schema, options = {}) => (body, errorMessage) => {
|
|
785
|
+
try {
|
|
786
|
+
const optionsWithDefaults = defaults(defaultValidationParam, options);
|
|
787
|
+
return schema.validateSync(body, optionsWithDefaults);
|
|
788
|
+
} catch (e) {
|
|
789
|
+
if (e instanceof yup$1.ValidationError) {
|
|
790
|
+
handleYupError(e, errorMessage);
|
|
791
|
+
}
|
|
792
|
+
throw e;
|
|
793
|
+
}
|
|
794
|
+
};
|
|
795
|
+
const GROUP_OPERATORS = ["$and", "$or"];
|
|
796
|
+
const WHERE_OPERATORS = [
|
|
797
|
+
"$not",
|
|
798
|
+
"$in",
|
|
799
|
+
"$notIn",
|
|
800
|
+
"$eq",
|
|
801
|
+
"$eqi",
|
|
802
|
+
"$ne",
|
|
803
|
+
"$nei",
|
|
804
|
+
"$gt",
|
|
805
|
+
"$gte",
|
|
806
|
+
"$lt",
|
|
807
|
+
"$lte",
|
|
808
|
+
"$null",
|
|
809
|
+
"$notNull",
|
|
810
|
+
"$between",
|
|
811
|
+
"$startsWith",
|
|
812
|
+
"$endsWith",
|
|
813
|
+
"$startsWithi",
|
|
814
|
+
"$endsWithi",
|
|
815
|
+
"$contains",
|
|
816
|
+
"$notContains",
|
|
817
|
+
"$containsi",
|
|
818
|
+
"$notContainsi",
|
|
819
|
+
// Experimental, only for internal use
|
|
820
|
+
"$jsonSupersetOf"
|
|
821
|
+
];
|
|
822
|
+
const CAST_OPERATORS = [
|
|
823
|
+
"$not",
|
|
824
|
+
"$in",
|
|
825
|
+
"$notIn",
|
|
826
|
+
"$eq",
|
|
827
|
+
"$ne",
|
|
828
|
+
"$gt",
|
|
829
|
+
"$gte",
|
|
830
|
+
"$lt",
|
|
831
|
+
"$lte",
|
|
832
|
+
"$between"
|
|
833
|
+
];
|
|
834
|
+
const ARRAY_OPERATORS = ["$in", "$notIn", "$between"];
|
|
835
|
+
const OPERATORS = {
|
|
836
|
+
where: WHERE_OPERATORS,
|
|
837
|
+
cast: CAST_OPERATORS,
|
|
838
|
+
group: GROUP_OPERATORS,
|
|
839
|
+
array: ARRAY_OPERATORS
|
|
840
|
+
};
|
|
841
|
+
const OPERATORS_LOWERCASE = Object.fromEntries(
|
|
842
|
+
Object.entries(OPERATORS).map(([key, values]) => [
|
|
843
|
+
key,
|
|
844
|
+
values.map((value) => value.toLowerCase())
|
|
845
|
+
])
|
|
846
|
+
);
|
|
847
|
+
const isObjKey = (key, obj) => {
|
|
848
|
+
return key in obj;
|
|
849
|
+
};
|
|
850
|
+
const isOperatorOfType = (type, key, ignoreCase = false) => {
|
|
851
|
+
if (ignoreCase) {
|
|
852
|
+
return OPERATORS_LOWERCASE[type]?.includes(key.toLowerCase()) ?? false;
|
|
853
|
+
}
|
|
854
|
+
if (isObjKey(type, OPERATORS)) {
|
|
855
|
+
return OPERATORS[type]?.includes(key) ?? false;
|
|
856
|
+
}
|
|
857
|
+
return false;
|
|
858
|
+
};
|
|
859
|
+
const isOperator = (key, ignoreCase = false) => {
|
|
860
|
+
return Object.keys(OPERATORS).some((type) => isOperatorOfType(type, key, ignoreCase));
|
|
861
|
+
};
|
|
862
|
+
const { ID_ATTRIBUTE: ID_ATTRIBUTE$3, DOC_ID_ATTRIBUTE: DOC_ID_ATTRIBUTE$3, PUBLISHED_AT_ATTRIBUTE } = constants$1;
|
|
863
|
+
class InvalidOrderError extends Error {
|
|
864
|
+
constructor() {
|
|
865
|
+
super();
|
|
866
|
+
this.message = "Invalid order. order can only be one of asc|desc|ASC|DESC";
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
class InvalidSortError extends Error {
|
|
870
|
+
constructor() {
|
|
871
|
+
super();
|
|
872
|
+
this.message = "Invalid sort parameter. Expected a string, an array of strings, a sort object or an array of sort objects";
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
function validateOrder(order) {
|
|
876
|
+
if (!isString(order) || !["asc", "desc"].includes(order.toLocaleLowerCase())) {
|
|
877
|
+
throw new InvalidOrderError();
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
const convertCountQueryParams = (countQuery) => {
|
|
881
|
+
return parseType({ type: "boolean", value: countQuery });
|
|
882
|
+
};
|
|
883
|
+
const convertOrderingQueryParams = (ordering) => {
|
|
884
|
+
return ordering;
|
|
885
|
+
};
|
|
886
|
+
const isPlainObject = (value) => _$1.isPlainObject(value);
|
|
887
|
+
const isStringArray$3 = (value) => isArray(value) && value.every(isString);
|
|
888
|
+
const createTransformer = ({ getModel }) => {
|
|
889
|
+
const convertSortQueryParams = (sortQuery) => {
|
|
890
|
+
if (typeof sortQuery === "string") {
|
|
891
|
+
return convertStringSortQueryParam(sortQuery);
|
|
892
|
+
}
|
|
893
|
+
if (isStringArray$3(sortQuery)) {
|
|
894
|
+
return sortQuery.flatMap((sortValue) => convertStringSortQueryParam(sortValue));
|
|
895
|
+
}
|
|
896
|
+
if (Array.isArray(sortQuery)) {
|
|
897
|
+
return sortQuery.map((sortValue) => convertNestedSortQueryParam(sortValue));
|
|
898
|
+
}
|
|
899
|
+
if (isPlainObject(sortQuery)) {
|
|
900
|
+
return convertNestedSortQueryParam(sortQuery);
|
|
901
|
+
}
|
|
902
|
+
throw new InvalidSortError();
|
|
903
|
+
};
|
|
904
|
+
const convertStringSortQueryParam = (sortQuery) => {
|
|
905
|
+
return sortQuery.split(",").map((value) => convertSingleSortQueryParam(value));
|
|
906
|
+
};
|
|
907
|
+
const convertSingleSortQueryParam = (sortQuery) => {
|
|
908
|
+
if (!sortQuery) {
|
|
909
|
+
return {};
|
|
910
|
+
}
|
|
911
|
+
if (!isString(sortQuery)) {
|
|
912
|
+
throw new Error("Invalid sort query");
|
|
913
|
+
}
|
|
914
|
+
const [field, order = "asc"] = sortQuery.split(":");
|
|
915
|
+
if (field.length === 0) {
|
|
916
|
+
throw new Error("Field cannot be empty");
|
|
917
|
+
}
|
|
918
|
+
validateOrder(order);
|
|
919
|
+
return _$1.set({}, field, order);
|
|
920
|
+
};
|
|
921
|
+
const convertNestedSortQueryParam = (sortQuery) => {
|
|
922
|
+
const transformedSort = {};
|
|
923
|
+
for (const field of Object.keys(sortQuery)) {
|
|
924
|
+
const order = sortQuery[field];
|
|
925
|
+
if (isPlainObject(order)) {
|
|
926
|
+
transformedSort[field] = convertNestedSortQueryParam(order);
|
|
927
|
+
} else if (typeof order === "string") {
|
|
928
|
+
validateOrder(order);
|
|
929
|
+
transformedSort[field] = order;
|
|
930
|
+
} else {
|
|
931
|
+
throw Error(`Invalid sort type expected object or string got ${typeof order}`);
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
return transformedSort;
|
|
935
|
+
};
|
|
936
|
+
const convertStartQueryParams = (startQuery) => {
|
|
937
|
+
const startAsANumber = _$1.toNumber(startQuery);
|
|
938
|
+
if (!_$1.isInteger(startAsANumber) || startAsANumber < 0) {
|
|
939
|
+
throw new Error(`convertStartQueryParams expected a positive integer got ${startAsANumber}`);
|
|
940
|
+
}
|
|
941
|
+
return startAsANumber;
|
|
942
|
+
};
|
|
943
|
+
const convertLimitQueryParams = (limitQuery) => {
|
|
944
|
+
const limitAsANumber = _$1.toNumber(limitQuery);
|
|
945
|
+
if (!_$1.isInteger(limitAsANumber) || limitAsANumber !== -1 && limitAsANumber < 0) {
|
|
946
|
+
throw new Error(`convertLimitQueryParams expected a positive integer got ${limitAsANumber}`);
|
|
947
|
+
}
|
|
948
|
+
if (limitAsANumber === -1) {
|
|
949
|
+
return void 0;
|
|
950
|
+
}
|
|
951
|
+
return limitAsANumber;
|
|
952
|
+
};
|
|
953
|
+
const convertPageQueryParams = (page) => {
|
|
954
|
+
const pageVal = toNumber(page);
|
|
955
|
+
if (!isInteger(pageVal) || pageVal <= 0) {
|
|
956
|
+
throw new PaginationError(
|
|
957
|
+
`Invalid 'page' parameter. Expected an integer > 0, received: ${page}`
|
|
958
|
+
);
|
|
959
|
+
}
|
|
960
|
+
return pageVal;
|
|
961
|
+
};
|
|
962
|
+
const convertPageSizeQueryParams = (pageSize, page) => {
|
|
963
|
+
const pageSizeVal = toNumber(pageSize);
|
|
964
|
+
if (!isInteger(pageSizeVal) || pageSizeVal <= 0) {
|
|
965
|
+
throw new PaginationError(
|
|
966
|
+
`Invalid 'pageSize' parameter. Expected an integer > 0, received: ${page}`
|
|
967
|
+
);
|
|
968
|
+
}
|
|
969
|
+
return pageSizeVal;
|
|
970
|
+
};
|
|
971
|
+
const validatePaginationParams = (page, pageSize, start, limit) => {
|
|
972
|
+
const isPagePagination = !isNil(page) || !isNil(pageSize);
|
|
973
|
+
const isOffsetPagination = !isNil(start) || !isNil(limit);
|
|
974
|
+
if (isPagePagination && isOffsetPagination) {
|
|
975
|
+
throw new PaginationError(
|
|
976
|
+
"Invalid pagination attributes. You cannot use page and offset pagination in the same query"
|
|
977
|
+
);
|
|
978
|
+
}
|
|
979
|
+
};
|
|
980
|
+
class InvalidPopulateError extends Error {
|
|
981
|
+
constructor() {
|
|
982
|
+
super();
|
|
983
|
+
this.message = "Invalid populate parameter. Expected a string, an array of strings, a populate object";
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
const convertPopulateQueryParams = (populate2, schema, depth = 0) => {
|
|
987
|
+
if (depth === 0 && populate2 === "*") {
|
|
988
|
+
return true;
|
|
989
|
+
}
|
|
990
|
+
if (typeof populate2 === "string") {
|
|
991
|
+
return populate2.split(",").map((value) => _$1.trim(value));
|
|
992
|
+
}
|
|
993
|
+
if (Array.isArray(populate2)) {
|
|
994
|
+
return _$1.uniq(
|
|
995
|
+
populate2.flatMap((value) => {
|
|
996
|
+
if (typeof value !== "string") {
|
|
997
|
+
throw new InvalidPopulateError();
|
|
998
|
+
}
|
|
999
|
+
return value.split(",").map((value2) => _$1.trim(value2));
|
|
1000
|
+
})
|
|
1001
|
+
);
|
|
1002
|
+
}
|
|
1003
|
+
if (_$1.isPlainObject(populate2)) {
|
|
1004
|
+
return convertPopulateObject(populate2, schema);
|
|
1005
|
+
}
|
|
1006
|
+
throw new InvalidPopulateError();
|
|
1007
|
+
};
|
|
1008
|
+
const hasFragmentPopulateDefined = (populate2) => {
|
|
1009
|
+
return typeof populate2 === "object" && "on" in populate2 && !isNil(populate2.on);
|
|
1010
|
+
};
|
|
1011
|
+
const convertPopulateObject = (populate2, schema) => {
|
|
1012
|
+
if (!schema) {
|
|
1013
|
+
return {};
|
|
1014
|
+
}
|
|
1015
|
+
const { attributes } = schema;
|
|
1016
|
+
return Object.entries(populate2).reduce((acc, [key, subPopulate]) => {
|
|
1017
|
+
if (_$1.isBoolean(subPopulate)) {
|
|
1018
|
+
return { ...acc, [key]: subPopulate };
|
|
1019
|
+
}
|
|
1020
|
+
const attribute = attributes[key];
|
|
1021
|
+
if (!attribute) {
|
|
1022
|
+
return acc;
|
|
1023
|
+
}
|
|
1024
|
+
const isAllowedAttributeForFragmentPopulate = isDynamicZoneAttribute(attribute) || isMorphToRelationalAttribute(attribute);
|
|
1025
|
+
if (isAllowedAttributeForFragmentPopulate && hasFragmentPopulateDefined(subPopulate)) {
|
|
1026
|
+
return {
|
|
1027
|
+
...acc,
|
|
1028
|
+
[key]: {
|
|
1029
|
+
on: Object.entries(subPopulate.on).reduce(
|
|
1030
|
+
(acc2, [type, typeSubPopulate]) => ({
|
|
1031
|
+
...acc2,
|
|
1032
|
+
[type]: convertNestedPopulate(typeSubPopulate, getModel(type))
|
|
1033
|
+
}),
|
|
1034
|
+
{}
|
|
1035
|
+
)
|
|
1036
|
+
}
|
|
1037
|
+
};
|
|
1038
|
+
}
|
|
1039
|
+
if (isDynamicZoneAttribute(attribute)) {
|
|
1040
|
+
const populates = attribute.components.map((uid) => getModel(uid)).map((schema2) => convertNestedPopulate(subPopulate, schema2)).map((populate22) => populate22 === true ? {} : populate22).filter((populate22) => populate22 !== false);
|
|
1041
|
+
if (isEmpty(populates)) {
|
|
1042
|
+
return acc;
|
|
1043
|
+
}
|
|
1044
|
+
return {
|
|
1045
|
+
...acc,
|
|
1046
|
+
[key]: mergeAll(populates)
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
if (isMorphToRelationalAttribute(attribute)) {
|
|
1050
|
+
return { ...acc, [key]: convertNestedPopulate(subPopulate, void 0) };
|
|
1051
|
+
}
|
|
1052
|
+
let targetSchemaUID;
|
|
1053
|
+
if (attribute.type === "relation") {
|
|
1054
|
+
targetSchemaUID = attribute.target;
|
|
1055
|
+
} else if (attribute.type === "component") {
|
|
1056
|
+
targetSchemaUID = attribute.component;
|
|
1057
|
+
} else if (attribute.type === "media") {
|
|
1058
|
+
targetSchemaUID = "plugin::upload.file";
|
|
1059
|
+
} else {
|
|
1060
|
+
return acc;
|
|
1061
|
+
}
|
|
1062
|
+
const targetSchema = getModel(targetSchemaUID);
|
|
1063
|
+
if (!targetSchema) {
|
|
1064
|
+
return acc;
|
|
1065
|
+
}
|
|
1066
|
+
const populateObject = convertNestedPopulate(subPopulate, targetSchema);
|
|
1067
|
+
if (!populateObject) {
|
|
1068
|
+
return acc;
|
|
1069
|
+
}
|
|
1070
|
+
return {
|
|
1071
|
+
...acc,
|
|
1072
|
+
[key]: populateObject
|
|
1073
|
+
};
|
|
1074
|
+
}, {});
|
|
1075
|
+
};
|
|
1076
|
+
const convertNestedPopulate = (subPopulate, schema) => {
|
|
1077
|
+
if (_$1.isString(subPopulate)) {
|
|
1078
|
+
return parseType({ type: "boolean", value: subPopulate, forceCast: true });
|
|
1079
|
+
}
|
|
1080
|
+
if (_$1.isBoolean(subPopulate)) {
|
|
1081
|
+
return subPopulate;
|
|
1082
|
+
}
|
|
1083
|
+
if (!isPlainObject(subPopulate)) {
|
|
1084
|
+
throw new Error(`Invalid nested populate. Expected '*' or an object`);
|
|
1085
|
+
}
|
|
1086
|
+
const { sort: sort2, filters: filters2, fields: fields2, populate: populate2, count, ordering, page, pageSize, start, limit } = subPopulate;
|
|
1087
|
+
const query = {};
|
|
1088
|
+
if (sort2) {
|
|
1089
|
+
query.orderBy = convertSortQueryParams(sort2);
|
|
1090
|
+
}
|
|
1091
|
+
if (filters2) {
|
|
1092
|
+
query.where = convertFiltersQueryParams(filters2, schema);
|
|
1093
|
+
}
|
|
1094
|
+
if (fields2) {
|
|
1095
|
+
query.select = convertFieldsQueryParams(fields2);
|
|
1096
|
+
}
|
|
1097
|
+
if (populate2) {
|
|
1098
|
+
query.populate = convertPopulateQueryParams(populate2, schema);
|
|
1099
|
+
}
|
|
1100
|
+
if (count) {
|
|
1101
|
+
query.count = convertCountQueryParams(count);
|
|
1102
|
+
}
|
|
1103
|
+
if (ordering) {
|
|
1104
|
+
query.ordering = convertOrderingQueryParams(ordering);
|
|
1105
|
+
}
|
|
1106
|
+
validatePaginationParams(page, pageSize, start, limit);
|
|
1107
|
+
if (!isNil(page)) {
|
|
1108
|
+
query.page = convertPageQueryParams(page);
|
|
1109
|
+
}
|
|
1110
|
+
if (!isNil(pageSize)) {
|
|
1111
|
+
query.pageSize = convertPageSizeQueryParams(pageSize, page);
|
|
1112
|
+
}
|
|
1113
|
+
if (!isNil(start)) {
|
|
1114
|
+
query.offset = convertStartQueryParams(start);
|
|
1115
|
+
}
|
|
1116
|
+
if (!isNil(limit)) {
|
|
1117
|
+
query.limit = convertLimitQueryParams(limit);
|
|
1118
|
+
}
|
|
1119
|
+
return query;
|
|
1120
|
+
};
|
|
1121
|
+
const convertFieldsQueryParams = (fields2, depth = 0) => {
|
|
1122
|
+
if (depth === 0 && fields2 === "*") {
|
|
1123
|
+
return void 0;
|
|
1124
|
+
}
|
|
1125
|
+
if (typeof fields2 === "string") {
|
|
1126
|
+
const fieldsValues = fields2.split(",").map((value) => _$1.trim(value));
|
|
1127
|
+
return _$1.uniq([ID_ATTRIBUTE$3, DOC_ID_ATTRIBUTE$3, ...fieldsValues]);
|
|
1128
|
+
}
|
|
1129
|
+
if (isStringArray$3(fields2)) {
|
|
1130
|
+
const fieldsValues = fields2.flatMap((value) => convertFieldsQueryParams(value, depth + 1)).filter((v) => !isNil(v));
|
|
1131
|
+
return _$1.uniq([ID_ATTRIBUTE$3, DOC_ID_ATTRIBUTE$3, ...fieldsValues]);
|
|
1132
|
+
}
|
|
1133
|
+
throw new Error("Invalid fields parameter. Expected a string or an array of strings");
|
|
1134
|
+
};
|
|
1135
|
+
const isValidSchemaAttribute = (key, schema) => {
|
|
1136
|
+
if ([DOC_ID_ATTRIBUTE$3, ID_ATTRIBUTE$3].includes(key)) {
|
|
1137
|
+
return true;
|
|
1138
|
+
}
|
|
1139
|
+
if (!schema) {
|
|
1140
|
+
return false;
|
|
1141
|
+
}
|
|
1142
|
+
return Object.keys(schema.attributes).includes(key);
|
|
1143
|
+
};
|
|
1144
|
+
const convertFiltersQueryParams = (filters2, schema) => {
|
|
1145
|
+
if (!isObject(filters2)) {
|
|
1146
|
+
throw new Error("The filters parameter must be an object or an array");
|
|
1147
|
+
}
|
|
1148
|
+
const filtersCopy = cloneDeep(filters2);
|
|
1149
|
+
return convertAndSanitizeFilters(filtersCopy, schema);
|
|
1150
|
+
};
|
|
1151
|
+
const convertAndSanitizeFilters = (filters2, schema) => {
|
|
1152
|
+
if (Array.isArray(filters2)) {
|
|
1153
|
+
return filters2.map((filter) => convertAndSanitizeFilters(filter, schema)).filter((filter) => !isPlainObject(filter) || !isEmpty(filter));
|
|
1154
|
+
}
|
|
1155
|
+
if (!isPlainObject(filters2)) {
|
|
1156
|
+
return filters2;
|
|
1157
|
+
}
|
|
1158
|
+
const removeOperator = (operator) => delete filters2[operator];
|
|
1159
|
+
for (const [key, value] of Object.entries(filters2)) {
|
|
1160
|
+
const attribute = get(key, schema?.attributes);
|
|
1161
|
+
const validKey = isOperator(key) || isValidSchemaAttribute(key, schema);
|
|
1162
|
+
if (!validKey) {
|
|
1163
|
+
removeOperator(key);
|
|
1164
|
+
} else if (attribute) {
|
|
1165
|
+
if (attribute.type === "relation") {
|
|
1166
|
+
filters2[key] = convertAndSanitizeFilters(value, getModel(attribute.target));
|
|
1167
|
+
} else if (attribute.type === "component") {
|
|
1168
|
+
filters2[key] = convertAndSanitizeFilters(value, getModel(attribute.component));
|
|
1169
|
+
} else if (attribute.type === "media") {
|
|
1170
|
+
filters2[key] = convertAndSanitizeFilters(value, getModel("plugin::upload.file"));
|
|
1171
|
+
} else if (attribute.type === "dynamiczone") {
|
|
1172
|
+
removeOperator(key);
|
|
1173
|
+
} else if (attribute.type === "password") {
|
|
1174
|
+
removeOperator(key);
|
|
1175
|
+
} else {
|
|
1176
|
+
filters2[key] = convertAndSanitizeFilters(value, schema);
|
|
1177
|
+
}
|
|
1178
|
+
} else if (["$null", "$notNull"].includes(key)) {
|
|
1179
|
+
filters2[key] = parseType({ type: "boolean", value: filters2[key], forceCast: true });
|
|
1180
|
+
} else if (isObject(value)) {
|
|
1181
|
+
filters2[key] = convertAndSanitizeFilters(value, schema);
|
|
1182
|
+
}
|
|
1183
|
+
if (isPlainObject(filters2[key]) && isEmpty(filters2[key])) {
|
|
1184
|
+
removeOperator(key);
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
return filters2;
|
|
1188
|
+
};
|
|
1189
|
+
const convertStatusParams = (status, query = {}) => {
|
|
1190
|
+
query.filters = ({ meta }) => {
|
|
1191
|
+
const contentType = getModel(meta.uid);
|
|
1192
|
+
if (!contentType || !hasDraftAndPublish(contentType)) {
|
|
1193
|
+
return {};
|
|
1194
|
+
}
|
|
1195
|
+
return { [PUBLISHED_AT_ATTRIBUTE]: { $null: status === "draft" } };
|
|
1196
|
+
};
|
|
1197
|
+
};
|
|
1198
|
+
const transformQueryParams = (uid, params) => {
|
|
1199
|
+
const schema = getModel(uid);
|
|
1200
|
+
const query = {};
|
|
1201
|
+
const { _q, sort: sort2, filters: filters2, fields: fields2, populate: populate2, page, pageSize, start, limit, status, ...rest } = params;
|
|
1202
|
+
if (!isNil(status)) {
|
|
1203
|
+
convertStatusParams(status, query);
|
|
1204
|
+
}
|
|
1205
|
+
if (!isNil(_q)) {
|
|
1206
|
+
query._q = _q;
|
|
1207
|
+
}
|
|
1208
|
+
if (!isNil(sort2)) {
|
|
1209
|
+
query.orderBy = convertSortQueryParams(sort2);
|
|
1210
|
+
}
|
|
1211
|
+
if (!isNil(filters2)) {
|
|
1212
|
+
query.where = convertFiltersQueryParams(filters2, schema);
|
|
1213
|
+
}
|
|
1214
|
+
if (!isNil(fields2)) {
|
|
1215
|
+
query.select = convertFieldsQueryParams(fields2);
|
|
1216
|
+
}
|
|
1217
|
+
if (!isNil(populate2)) {
|
|
1218
|
+
query.populate = convertPopulateQueryParams(populate2, schema);
|
|
1219
|
+
}
|
|
1220
|
+
validatePaginationParams(page, pageSize, start, limit);
|
|
1221
|
+
if (!isNil(page)) {
|
|
1222
|
+
query.page = convertPageQueryParams(page);
|
|
1223
|
+
}
|
|
1224
|
+
if (!isNil(pageSize)) {
|
|
1225
|
+
query.pageSize = convertPageSizeQueryParams(pageSize, page);
|
|
1226
|
+
}
|
|
1227
|
+
if (!isNil(start)) {
|
|
1228
|
+
query.offset = convertStartQueryParams(start);
|
|
1229
|
+
}
|
|
1230
|
+
if (!isNil(limit)) {
|
|
1231
|
+
query.limit = convertLimitQueryParams(limit);
|
|
1232
|
+
}
|
|
1233
|
+
return {
|
|
1234
|
+
...rest,
|
|
1235
|
+
...query
|
|
1236
|
+
};
|
|
1237
|
+
};
|
|
1238
|
+
return {
|
|
1239
|
+
private_convertSortQueryParams: convertSortQueryParams,
|
|
1240
|
+
private_convertStartQueryParams: convertStartQueryParams,
|
|
1241
|
+
private_convertLimitQueryParams: convertLimitQueryParams,
|
|
1242
|
+
private_convertPopulateQueryParams: convertPopulateQueryParams,
|
|
1243
|
+
private_convertFiltersQueryParams: convertFiltersQueryParams,
|
|
1244
|
+
private_convertFieldsQueryParams: convertFieldsQueryParams,
|
|
1245
|
+
transformQueryParams
|
|
1246
|
+
};
|
|
1247
|
+
};
|
|
1248
|
+
const convertQueryParams = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1249
|
+
__proto__: null,
|
|
1250
|
+
createTransformer
|
|
1251
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
1252
|
+
function pipe(...fns) {
|
|
1253
|
+
const [firstFn, ...fnRest] = fns;
|
|
1254
|
+
return async (...args) => {
|
|
1255
|
+
let res = await firstFn.apply(firstFn, args);
|
|
1256
|
+
for (let i = 0; i < fnRest.length; i += 1) {
|
|
1257
|
+
res = await fnRest[i](res);
|
|
1258
|
+
}
|
|
1259
|
+
return res;
|
|
1260
|
+
};
|
|
1261
|
+
}
|
|
1262
|
+
const map = curry(pMap);
|
|
1263
|
+
const reduce = (mixedArray) => async (iteratee, initialValue) => {
|
|
1264
|
+
let acc = initialValue;
|
|
1265
|
+
for (let i = 0; i < mixedArray.length; i += 1) {
|
|
1266
|
+
acc = await iteratee(acc, await mixedArray[i], i);
|
|
1267
|
+
}
|
|
1268
|
+
return acc;
|
|
1269
|
+
};
|
|
1270
|
+
const async = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1271
|
+
__proto__: null,
|
|
1272
|
+
map,
|
|
1273
|
+
pipe,
|
|
1274
|
+
reduce
|
|
1275
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
1276
|
+
const visitor$8 = ({ key, attribute }, { remove: remove2 }) => {
|
|
1277
|
+
if (attribute?.type === "password") {
|
|
1278
|
+
remove2(key);
|
|
1279
|
+
}
|
|
1280
|
+
};
|
|
1281
|
+
const visitor$7 = ({ schema, key, attribute }, { remove: remove2 }) => {
|
|
1282
|
+
if (!attribute) {
|
|
1283
|
+
return;
|
|
1284
|
+
}
|
|
1285
|
+
const isPrivate = attribute.private === true || isPrivateAttribute(schema, key);
|
|
1286
|
+
if (isPrivate) {
|
|
1287
|
+
remove2(key);
|
|
1288
|
+
}
|
|
1289
|
+
};
|
|
1290
|
+
const ACTIONS_TO_VERIFY$1 = ["find"];
|
|
1291
|
+
const { CREATED_BY_ATTRIBUTE: CREATED_BY_ATTRIBUTE$1, UPDATED_BY_ATTRIBUTE: UPDATED_BY_ATTRIBUTE$1 } = constants$1;
|
|
1292
|
+
const removeRestrictedRelations = (auth) => async ({ data, key, attribute, schema }, { remove: remove2, set }) => {
|
|
1293
|
+
if (!attribute) {
|
|
1294
|
+
return;
|
|
1295
|
+
}
|
|
1296
|
+
const isRelation = attribute.type === "relation";
|
|
1297
|
+
if (!isRelation) {
|
|
1298
|
+
return;
|
|
1299
|
+
}
|
|
1300
|
+
const handleMorphRelation = async () => {
|
|
1301
|
+
const newMorphValue = [];
|
|
1302
|
+
for (const element of data[key]) {
|
|
1303
|
+
const scopes = ACTIONS_TO_VERIFY$1.map((action) => `${element.__type}.${action}`);
|
|
1304
|
+
const isAllowed = await hasAccessToSomeScopes$1(scopes, auth);
|
|
1305
|
+
if (isAllowed) {
|
|
1306
|
+
newMorphValue.push(element);
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
if (newMorphValue.length === 0) {
|
|
1310
|
+
remove2(key);
|
|
1311
|
+
} else {
|
|
1312
|
+
set(key, newMorphValue);
|
|
1313
|
+
}
|
|
1314
|
+
};
|
|
1315
|
+
const handleRegularRelation = async () => {
|
|
1316
|
+
const scopes = ACTIONS_TO_VERIFY$1.map((action) => `${attribute.target}.${action}`);
|
|
1317
|
+
const isAllowed = await hasAccessToSomeScopes$1(scopes, auth);
|
|
1318
|
+
if (!isAllowed) {
|
|
1319
|
+
remove2(key);
|
|
1320
|
+
}
|
|
1321
|
+
};
|
|
1322
|
+
const isCreatorRelation = [CREATED_BY_ATTRIBUTE$1, UPDATED_BY_ATTRIBUTE$1].includes(key);
|
|
1323
|
+
if (isMorphToRelationalAttribute(attribute)) {
|
|
1324
|
+
await handleMorphRelation();
|
|
1325
|
+
return;
|
|
1326
|
+
}
|
|
1327
|
+
if (isCreatorRelation && schema.options?.populateCreatorFields) {
|
|
1328
|
+
return;
|
|
1329
|
+
}
|
|
1330
|
+
await handleRegularRelation();
|
|
1331
|
+
};
|
|
1332
|
+
const hasAccessToSomeScopes$1 = async (scopes, auth) => {
|
|
1333
|
+
for (const scope of scopes) {
|
|
1334
|
+
try {
|
|
1335
|
+
await strapi.auth.verify(auth, { scope });
|
|
1336
|
+
return true;
|
|
1337
|
+
} catch {
|
|
1338
|
+
continue;
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
return false;
|
|
1342
|
+
};
|
|
1343
|
+
const visitor$6 = ({ key, attribute }, { remove: remove2 }) => {
|
|
1344
|
+
if (isMorphToRelationalAttribute(attribute)) {
|
|
1345
|
+
remove2(key);
|
|
1346
|
+
}
|
|
1347
|
+
};
|
|
1348
|
+
const visitor$5 = ({ key, attribute }, { remove: remove2 }) => {
|
|
1349
|
+
if (isDynamicZoneAttribute(attribute)) {
|
|
1350
|
+
remove2(key);
|
|
1351
|
+
}
|
|
1352
|
+
};
|
|
1353
|
+
const removeDisallowedFields = (allowedFields = null) => ({ key, path: { attribute: path } }, { remove: remove2 }) => {
|
|
1354
|
+
if (allowedFields === null) {
|
|
1355
|
+
return;
|
|
1356
|
+
}
|
|
1357
|
+
if (!(isArray(allowedFields) && allowedFields.every(isString))) {
|
|
1358
|
+
throw new TypeError(
|
|
1359
|
+
`Expected array of strings for allowedFields but got "${typeof allowedFields}"`
|
|
1360
|
+
);
|
|
1361
|
+
}
|
|
1362
|
+
if (isNil(path)) {
|
|
1363
|
+
return;
|
|
1364
|
+
}
|
|
1365
|
+
const containedPaths = getContainedPaths$1(path);
|
|
1366
|
+
const isPathAllowed = allowedFields.some(
|
|
1367
|
+
(p) => containedPaths.includes(p) || p.startsWith(`${path}.`)
|
|
1368
|
+
);
|
|
1369
|
+
if (isPathAllowed) {
|
|
1370
|
+
return;
|
|
1371
|
+
}
|
|
1372
|
+
remove2(key);
|
|
1373
|
+
};
|
|
1374
|
+
const getContainedPaths$1 = (path) => {
|
|
1375
|
+
const parts = toPath(path);
|
|
1376
|
+
return parts.reduce((acc, value, index2, list) => {
|
|
1377
|
+
return [...acc, list.slice(0, index2 + 1).join(".")];
|
|
1378
|
+
}, []);
|
|
1379
|
+
};
|
|
1380
|
+
const removeRestrictedFields = (restrictedFields = null) => ({ key, path: { attribute: path } }, { remove: remove2 }) => {
|
|
1381
|
+
if (restrictedFields === null) {
|
|
1382
|
+
remove2(key);
|
|
1383
|
+
return;
|
|
1384
|
+
}
|
|
1385
|
+
if (!(isArray(restrictedFields) && restrictedFields.every(isString))) {
|
|
1386
|
+
throw new TypeError(
|
|
1387
|
+
`Expected array of strings for restrictedFields but got "${typeof restrictedFields}"`
|
|
1388
|
+
);
|
|
1389
|
+
}
|
|
1390
|
+
if (restrictedFields.includes(path)) {
|
|
1391
|
+
remove2(key);
|
|
1392
|
+
return;
|
|
1393
|
+
}
|
|
1394
|
+
const isRestrictedNested = restrictedFields.some(
|
|
1395
|
+
(allowedPath) => path?.toString().startsWith(`${allowedPath}.`)
|
|
1396
|
+
);
|
|
1397
|
+
if (isRestrictedNested) {
|
|
1398
|
+
remove2(key);
|
|
1399
|
+
}
|
|
1400
|
+
};
|
|
1401
|
+
const visitor$4 = ({ schema, key, value }, { set }) => {
|
|
1402
|
+
if (key === "" && value === "*") {
|
|
1403
|
+
const { attributes } = schema;
|
|
1404
|
+
const newPopulateQuery = Object.entries(attributes).filter(
|
|
1405
|
+
([, attribute]) => ["relation", "component", "media", "dynamiczone"].includes(attribute.type)
|
|
1406
|
+
).reduce((acc, [key2]) => ({ ...acc, [key2]: true }), {});
|
|
1407
|
+
set("", newPopulateQuery);
|
|
1408
|
+
}
|
|
1409
|
+
};
|
|
1410
|
+
const index$4 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1411
|
+
__proto__: null,
|
|
1412
|
+
expandWildcardPopulate: visitor$4,
|
|
1413
|
+
removeDisallowedFields,
|
|
1414
|
+
removeDynamicZones: visitor$5,
|
|
1415
|
+
removeMorphToRelations: visitor$6,
|
|
1416
|
+
removePassword: visitor$8,
|
|
1417
|
+
removePrivate: visitor$7,
|
|
1418
|
+
removeRestrictedFields,
|
|
1419
|
+
removeRestrictedRelations
|
|
1420
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
1421
|
+
const DEFAULT_PATH = { raw: null, attribute: null };
|
|
1422
|
+
const traverseFactory = () => {
|
|
1423
|
+
const state = {
|
|
1424
|
+
parsers: [],
|
|
1425
|
+
interceptors: [],
|
|
1426
|
+
ignore: [],
|
|
1427
|
+
handlers: {
|
|
1428
|
+
attributes: [],
|
|
1429
|
+
common: []
|
|
1430
|
+
}
|
|
1431
|
+
};
|
|
1432
|
+
const traverse = async (visitor2, options, data) => {
|
|
1433
|
+
const { path = DEFAULT_PATH, schema, getModel } = options ?? {};
|
|
1434
|
+
for (const { predicate, handler } of state.interceptors) {
|
|
1435
|
+
if (predicate(data)) {
|
|
1436
|
+
return handler(visitor2, options, data, { recurse: traverse });
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
const parser = state.parsers.find((parser2) => parser2.predicate(data))?.parser;
|
|
1440
|
+
const utils2 = parser?.(data);
|
|
1441
|
+
if (!utils2) {
|
|
1442
|
+
return data;
|
|
1443
|
+
}
|
|
1444
|
+
let out = utils2.transform(data);
|
|
1445
|
+
const keys = utils2.keys(out);
|
|
1446
|
+
for (const key of keys) {
|
|
1447
|
+
const attribute = schema?.attributes?.[key];
|
|
1448
|
+
const newPath = { ...path };
|
|
1449
|
+
newPath.raw = isNil(path.raw) ? key : `${path.raw}.${key}`;
|
|
1450
|
+
if (!isNil(attribute)) {
|
|
1451
|
+
newPath.attribute = isNil(path.attribute) ? key : `${path.attribute}.${key}`;
|
|
1452
|
+
}
|
|
1453
|
+
const visitorOptions = {
|
|
1454
|
+
key,
|
|
1455
|
+
value: utils2.get(key, out),
|
|
1456
|
+
attribute,
|
|
1457
|
+
schema,
|
|
1458
|
+
path: newPath,
|
|
1459
|
+
data: out,
|
|
1460
|
+
getModel
|
|
1461
|
+
};
|
|
1462
|
+
const transformUtils = {
|
|
1463
|
+
remove(key2) {
|
|
1464
|
+
out = utils2.remove(key2, out);
|
|
1465
|
+
},
|
|
1466
|
+
set(key2, value2) {
|
|
1467
|
+
out = utils2.set(key2, value2, out);
|
|
1468
|
+
},
|
|
1469
|
+
recurse: traverse
|
|
1470
|
+
};
|
|
1471
|
+
await visitor2(visitorOptions, pick(["remove", "set"], transformUtils));
|
|
1472
|
+
const value = utils2.get(key, out);
|
|
1473
|
+
const createContext = () => ({
|
|
1474
|
+
key,
|
|
1475
|
+
value,
|
|
1476
|
+
attribute,
|
|
1477
|
+
schema,
|
|
1478
|
+
path: newPath,
|
|
1479
|
+
data: out,
|
|
1480
|
+
visitor: visitor2,
|
|
1481
|
+
getModel
|
|
1482
|
+
});
|
|
1483
|
+
const ignoreCtx = createContext();
|
|
1484
|
+
const shouldIgnore = state.ignore.some((predicate) => predicate(ignoreCtx));
|
|
1485
|
+
if (shouldIgnore) {
|
|
1486
|
+
continue;
|
|
1487
|
+
}
|
|
1488
|
+
const handlers = [...state.handlers.common, ...state.handlers.attributes];
|
|
1489
|
+
for await (const handler of handlers) {
|
|
1490
|
+
const ctx = createContext();
|
|
1491
|
+
const pass = await handler.predicate(ctx);
|
|
1492
|
+
if (pass) {
|
|
1493
|
+
await handler.handler(ctx, pick(["recurse", "set"], transformUtils));
|
|
1494
|
+
}
|
|
877
1495
|
}
|
|
878
1496
|
}
|
|
879
1497
|
return out;
|
|
@@ -949,33 +1567,33 @@ const filters = traverseFactory().intercept(
|
|
|
949
1567
|
}
|
|
950
1568
|
})).ignore(({ value }) => isNil(value)).on(
|
|
951
1569
|
({ attribute }) => isNil(attribute),
|
|
952
|
-
async ({ key, visitor: visitor2, path, value, schema }, { set, recurse }) => {
|
|
953
|
-
set(key, await recurse(visitor2, { schema, path }, value));
|
|
1570
|
+
async ({ key, visitor: visitor2, path, value, schema, getModel }, { set, recurse }) => {
|
|
1571
|
+
set(key, await recurse(visitor2, { schema, path, getModel }, value));
|
|
954
1572
|
}
|
|
955
|
-
).onRelation(async ({ key, attribute, visitor: visitor2, path, value }, { set, recurse }) => {
|
|
1573
|
+
).onRelation(async ({ key, attribute, visitor: visitor2, path, value, getModel }, { set, recurse }) => {
|
|
956
1574
|
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
|
957
1575
|
if (isMorphRelation) {
|
|
958
1576
|
return;
|
|
959
1577
|
}
|
|
960
1578
|
const targetSchemaUID = attribute.target;
|
|
961
|
-
const targetSchema =
|
|
962
|
-
const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
|
|
1579
|
+
const targetSchema = getModel(targetSchemaUID);
|
|
1580
|
+
const newValue = await recurse(visitor2, { schema: targetSchema, path, getModel }, value);
|
|
963
1581
|
set(key, newValue);
|
|
964
|
-
}).onComponent(async ({ key, attribute, visitor: visitor2, path, value }, { set, recurse }) => {
|
|
965
|
-
const targetSchema =
|
|
966
|
-
const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
|
|
1582
|
+
}).onComponent(async ({ key, attribute, visitor: visitor2, path, value, getModel }, { set, recurse }) => {
|
|
1583
|
+
const targetSchema = getModel(attribute.component);
|
|
1584
|
+
const newValue = await recurse(visitor2, { schema: targetSchema, path, getModel }, value);
|
|
967
1585
|
set(key, newValue);
|
|
968
|
-
}).onMedia(async ({ key, visitor: visitor2, path, value }, { set, recurse }) => {
|
|
1586
|
+
}).onMedia(async ({ key, visitor: visitor2, path, value, getModel }, { set, recurse }) => {
|
|
969
1587
|
const targetSchemaUID = "plugin::upload.file";
|
|
970
|
-
const targetSchema =
|
|
971
|
-
const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
|
|
1588
|
+
const targetSchema = getModel(targetSchemaUID);
|
|
1589
|
+
const newValue = await recurse(visitor2, { schema: targetSchema, path, getModel }, value);
|
|
972
1590
|
set(key, newValue);
|
|
973
1591
|
});
|
|
974
1592
|
const traverseQueryFilters = curry(filters.traverse);
|
|
975
1593
|
const ORDERS = { asc: "asc", desc: "desc" };
|
|
976
1594
|
const ORDER_VALUES = Object.values(ORDERS);
|
|
977
1595
|
const isSortOrder = (value) => ORDER_VALUES.includes(value.toLowerCase());
|
|
978
|
-
const isStringArray$
|
|
1596
|
+
const isStringArray$2 = (value) => Array.isArray(value) && value.every(isString);
|
|
979
1597
|
const isObjectArray = (value) => Array.isArray(value) && value.every(isObject);
|
|
980
1598
|
const isNestedSorts = (value) => isString(value) && value.split(",").length > 1;
|
|
981
1599
|
const isObj$1 = (value) => isObject(value);
|
|
@@ -989,7 +1607,7 @@ const sort = traverseFactory().intercept(
|
|
|
989
1607
|
}
|
|
990
1608
|
).intercept(
|
|
991
1609
|
// Array of strings ['foo', 'foo,bar'] => map(recurse), then filter out empty items
|
|
992
|
-
isStringArray$
|
|
1610
|
+
isStringArray$2,
|
|
993
1611
|
async (visitor2, options, sort2, { recurse }) => {
|
|
994
1612
|
return Promise.all(sort2.map((nestedSort) => recurse(visitor2, options, nestedSort))).then(
|
|
995
1613
|
(res) => res.filter((nestedSort) => !isEmpty(nestedSort))
|
|
@@ -1056,23 +1674,23 @@ const sort = traverseFactory().intercept(
|
|
|
1056
1674
|
get(key, data) {
|
|
1057
1675
|
return data[key];
|
|
1058
1676
|
}
|
|
1059
|
-
})).onRelation(async ({ key, value, attribute, visitor: visitor2, path }, { set, recurse }) => {
|
|
1677
|
+
})).onRelation(async ({ key, value, attribute, visitor: visitor2, path, getModel }, { set, recurse }) => {
|
|
1060
1678
|
const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
|
|
1061
1679
|
if (isMorphRelation) {
|
|
1062
1680
|
return;
|
|
1063
1681
|
}
|
|
1064
1682
|
const targetSchemaUID = attribute.target;
|
|
1065
|
-
const targetSchema =
|
|
1066
|
-
const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
|
|
1683
|
+
const targetSchema = getModel(targetSchemaUID);
|
|
1684
|
+
const newValue = await recurse(visitor2, { schema: targetSchema, path, getModel }, value);
|
|
1067
1685
|
set(key, newValue);
|
|
1068
|
-
}).onMedia(async ({ key, path, visitor: visitor2, value }, { recurse, set }) => {
|
|
1686
|
+
}).onMedia(async ({ key, path, visitor: visitor2, value, getModel }, { recurse, set }) => {
|
|
1069
1687
|
const targetSchemaUID = "plugin::upload.file";
|
|
1070
|
-
const targetSchema =
|
|
1071
|
-
const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
|
|
1688
|
+
const targetSchema = getModel(targetSchemaUID);
|
|
1689
|
+
const newValue = await recurse(visitor2, { schema: targetSchema, path, getModel }, value);
|
|
1072
1690
|
set(key, newValue);
|
|
1073
|
-
}).onComponent(async ({ key, value, visitor: visitor2, path, attribute }, { recurse, set }) => {
|
|
1074
|
-
const targetSchema =
|
|
1075
|
-
const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
|
|
1691
|
+
}).onComponent(async ({ key, value, visitor: visitor2, path, attribute, getModel }, { recurse, set }) => {
|
|
1692
|
+
const targetSchema = getModel(attribute.component);
|
|
1693
|
+
const newValue = await recurse(visitor2, { schema: targetSchema, path, getModel }, value);
|
|
1076
1694
|
set(key, newValue);
|
|
1077
1695
|
});
|
|
1078
1696
|
const traverseQuerySort = curry(sort.traverse);
|
|
@@ -1081,9 +1699,9 @@ const isKeyword = (keyword) => {
|
|
|
1081
1699
|
return !attribute && keyword === key;
|
|
1082
1700
|
};
|
|
1083
1701
|
};
|
|
1084
|
-
const isStringArray$
|
|
1702
|
+
const isStringArray$1 = (value) => isArray(value) && value.every(isString);
|
|
1085
1703
|
const isObj = (value) => isObject(value);
|
|
1086
|
-
const populate = traverseFactory().intercept(isStringArray$
|
|
1704
|
+
const populate = traverseFactory().intercept(isStringArray$1, async (visitor2, options, populate2, { recurse }) => {
|
|
1087
1705
|
const visitedPopulate = await Promise.all(
|
|
1088
1706
|
populate2.map((nestedPopulate) => recurse(visitor2, options, nestedPopulate))
|
|
1089
1707
|
);
|
|
@@ -1160,78 +1778,86 @@ const populate = traverseFactory().intercept(isStringArray$2, async (visitor2, o
|
|
|
1160
1778
|
}).on(
|
|
1161
1779
|
// Handle recursion on populate."populate"
|
|
1162
1780
|
isKeyword("populate"),
|
|
1163
|
-
async ({ key, visitor: visitor2, path, value, schema }, { set, recurse }) => {
|
|
1164
|
-
const newValue = await recurse(visitor2, { schema, path }, value);
|
|
1781
|
+
async ({ key, visitor: visitor2, path, value, schema, getModel }, { set, recurse }) => {
|
|
1782
|
+
const newValue = await recurse(visitor2, { schema, path, getModel }, value);
|
|
1165
1783
|
set(key, newValue);
|
|
1166
1784
|
}
|
|
1167
|
-
).on(isKeyword("on"), async ({ key, visitor: visitor2, path, value }, { set, recurse }) => {
|
|
1785
|
+
).on(isKeyword("on"), async ({ key, visitor: visitor2, path, value, getModel }, { set, recurse }) => {
|
|
1168
1786
|
const newOn = {};
|
|
1169
1787
|
if (!isObj(value)) {
|
|
1170
1788
|
return;
|
|
1171
1789
|
}
|
|
1172
1790
|
for (const [uid, subPopulate] of Object.entries(value)) {
|
|
1173
|
-
const model =
|
|
1791
|
+
const model = getModel(uid);
|
|
1174
1792
|
const newPath = { ...path, raw: `${path.raw}[${uid}]` };
|
|
1175
|
-
newOn[uid] = await recurse(visitor2, { schema: model, path: newPath }, subPopulate);
|
|
1793
|
+
newOn[uid] = await recurse(visitor2, { schema: model, path: newPath, getModel }, subPopulate);
|
|
1176
1794
|
}
|
|
1177
1795
|
set(key, newOn);
|
|
1178
|
-
}).onRelation(
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
}
|
|
1182
|
-
if (isMorphToRelationalAttribute(attribute)) {
|
|
1183
|
-
if (!isObject(value) || !("on" in value && isObject(value?.on))) {
|
|
1796
|
+
}).onRelation(
|
|
1797
|
+
async ({ key, value, attribute, visitor: visitor2, path, schema, getModel }, { set, recurse }) => {
|
|
1798
|
+
if (isNil(value)) {
|
|
1184
1799
|
return;
|
|
1185
1800
|
}
|
|
1186
|
-
|
|
1187
|
-
|
|
1801
|
+
if (isMorphToRelationalAttribute(attribute)) {
|
|
1802
|
+
if (!isObject(value) || !("on" in value && isObject(value?.on))) {
|
|
1803
|
+
return;
|
|
1804
|
+
}
|
|
1805
|
+
const newValue2 = await recurse(visitor2, { schema, path, getModel }, { on: value?.on });
|
|
1806
|
+
set(key, { on: newValue2 });
|
|
1807
|
+
}
|
|
1808
|
+
const targetSchemaUID = attribute.target;
|
|
1809
|
+
const targetSchema = getModel(targetSchemaUID);
|
|
1810
|
+
const newValue = await recurse(visitor2, { schema: targetSchema, path, getModel }, value);
|
|
1811
|
+
set(key, newValue);
|
|
1188
1812
|
}
|
|
1189
|
-
|
|
1190
|
-
const targetSchema = strapi.getModel(targetSchemaUID);
|
|
1191
|
-
const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
|
|
1192
|
-
set(key, newValue);
|
|
1193
|
-
}).onMedia(async ({ key, path, visitor: visitor2, value }, { recurse, set }) => {
|
|
1813
|
+
).onMedia(async ({ key, path, visitor: visitor2, value, getModel }, { recurse, set }) => {
|
|
1194
1814
|
if (isNil(value)) {
|
|
1195
1815
|
return;
|
|
1196
1816
|
}
|
|
1197
1817
|
const targetSchemaUID = "plugin::upload.file";
|
|
1198
|
-
const targetSchema =
|
|
1199
|
-
const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
|
|
1818
|
+
const targetSchema = getModel(targetSchemaUID);
|
|
1819
|
+
const newValue = await recurse(visitor2, { schema: targetSchema, path, getModel }, value);
|
|
1200
1820
|
set(key, newValue);
|
|
1201
|
-
}).onComponent(async ({ key, value, visitor: visitor2, path, attribute }, { recurse, set }) => {
|
|
1821
|
+
}).onComponent(async ({ key, value, visitor: visitor2, path, attribute, getModel }, { recurse, set }) => {
|
|
1202
1822
|
if (isNil(value)) {
|
|
1203
1823
|
return;
|
|
1204
1824
|
}
|
|
1205
|
-
const targetSchema =
|
|
1206
|
-
const newValue = await recurse(visitor2, { schema: targetSchema, path }, value);
|
|
1825
|
+
const targetSchema = getModel(attribute.component);
|
|
1826
|
+
const newValue = await recurse(visitor2, { schema: targetSchema, path, getModel }, value);
|
|
1207
1827
|
set(key, newValue);
|
|
1208
|
-
}).onDynamicZone(
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
if (isObject(value)) {
|
|
1213
|
-
const { components } = attribute;
|
|
1214
|
-
const newValue = {};
|
|
1215
|
-
let newProperties = omit("on", value);
|
|
1216
|
-
for (const componentUID of components) {
|
|
1217
|
-
const componentSchema = strapi.getModel(componentUID);
|
|
1218
|
-
const properties = await recurse(visitor2, { schema: componentSchema, path }, value);
|
|
1219
|
-
newProperties = merge(newProperties, properties);
|
|
1828
|
+
}).onDynamicZone(
|
|
1829
|
+
async ({ key, value, attribute, schema, visitor: visitor2, path, getModel }, { set, recurse }) => {
|
|
1830
|
+
if (isNil(value)) {
|
|
1831
|
+
return;
|
|
1220
1832
|
}
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
const
|
|
1224
|
-
|
|
1833
|
+
if (isObject(value)) {
|
|
1834
|
+
const { components } = attribute;
|
|
1835
|
+
const newValue = {};
|
|
1836
|
+
let newProperties = omit("on", value);
|
|
1837
|
+
for (const componentUID of components) {
|
|
1838
|
+
const componentSchema = getModel(componentUID);
|
|
1839
|
+
const properties = await recurse(
|
|
1840
|
+
visitor2,
|
|
1841
|
+
{ schema: componentSchema, path, getModel },
|
|
1842
|
+
value
|
|
1843
|
+
);
|
|
1844
|
+
newProperties = merge(newProperties, properties);
|
|
1845
|
+
}
|
|
1846
|
+
Object.assign(newValue, newProperties);
|
|
1847
|
+
if ("on" in value && value.on) {
|
|
1848
|
+
const newOn = await recurse(visitor2, { schema, path, getModel }, { on: value.on });
|
|
1849
|
+
Object.assign(newValue, newOn);
|
|
1850
|
+
}
|
|
1851
|
+
set(key, newValue);
|
|
1852
|
+
} else {
|
|
1853
|
+
const newValue = await recurse(visitor2, { schema, path, getModel }, value);
|
|
1854
|
+
set(key, newValue);
|
|
1225
1855
|
}
|
|
1226
|
-
set(key, newValue);
|
|
1227
|
-
} else {
|
|
1228
|
-
const newValue = await recurse(visitor2, { schema, path }, value);
|
|
1229
|
-
set(key, newValue);
|
|
1230
1856
|
}
|
|
1231
|
-
|
|
1857
|
+
);
|
|
1232
1858
|
const traverseQueryPopulate = curry(populate.traverse);
|
|
1233
|
-
const isStringArray
|
|
1234
|
-
const fields = traverseFactory().intercept(isStringArray
|
|
1859
|
+
const isStringArray = (value) => isArray(value) && value.every(isString);
|
|
1860
|
+
const fields = traverseFactory().intercept(isStringArray, async (visitor2, options, fields2, { recurse }) => {
|
|
1235
1861
|
return Promise.all(fields2.map((field) => recurse(visitor2, options, field)));
|
|
1236
1862
|
}).intercept((value) => eq("*", value), constant("*")).parse(isString, () => ({
|
|
1237
1863
|
transform: trim,
|
|
@@ -1249,90 +1875,22 @@ const fields = traverseFactory().intercept(isStringArray$1, async (visitor2, opt
|
|
|
1249
1875
|
}
|
|
1250
1876
|
}));
|
|
1251
1877
|
const traverseQueryFields = curry(fields.traverse);
|
|
1252
|
-
const index$
|
|
1878
|
+
const index$3 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1253
1879
|
__proto__: null,
|
|
1254
|
-
factory: traverseFactory,
|
|
1255
1880
|
traverseQueryFields,
|
|
1256
1881
|
traverseQueryFilters,
|
|
1257
1882
|
traverseQueryPopulate,
|
|
1258
1883
|
traverseQuerySort
|
|
1259
1884
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1260
|
-
const
|
|
1261
|
-
const
|
|
1262
|
-
|
|
1263
|
-
"$in",
|
|
1264
|
-
"$notIn",
|
|
1265
|
-
"$eq",
|
|
1266
|
-
"$eqi",
|
|
1267
|
-
"$ne",
|
|
1268
|
-
"$nei",
|
|
1269
|
-
"$gt",
|
|
1270
|
-
"$gte",
|
|
1271
|
-
"$lt",
|
|
1272
|
-
"$lte",
|
|
1273
|
-
"$null",
|
|
1274
|
-
"$notNull",
|
|
1275
|
-
"$between",
|
|
1276
|
-
"$startsWith",
|
|
1277
|
-
"$endsWith",
|
|
1278
|
-
"$startsWithi",
|
|
1279
|
-
"$endsWithi",
|
|
1280
|
-
"$contains",
|
|
1281
|
-
"$notContains",
|
|
1282
|
-
"$containsi",
|
|
1283
|
-
"$notContainsi",
|
|
1284
|
-
// Experimental, only for internal use
|
|
1285
|
-
"$jsonSupersetOf"
|
|
1286
|
-
];
|
|
1287
|
-
const CAST_OPERATORS = [
|
|
1288
|
-
"$not",
|
|
1289
|
-
"$in",
|
|
1290
|
-
"$notIn",
|
|
1291
|
-
"$eq",
|
|
1292
|
-
"$ne",
|
|
1293
|
-
"$gt",
|
|
1294
|
-
"$gte",
|
|
1295
|
-
"$lt",
|
|
1296
|
-
"$lte",
|
|
1297
|
-
"$between"
|
|
1298
|
-
];
|
|
1299
|
-
const ARRAY_OPERATORS = ["$in", "$notIn", "$between"];
|
|
1300
|
-
const OPERATORS = {
|
|
1301
|
-
where: WHERE_OPERATORS,
|
|
1302
|
-
cast: CAST_OPERATORS,
|
|
1303
|
-
group: GROUP_OPERATORS,
|
|
1304
|
-
array: ARRAY_OPERATORS
|
|
1305
|
-
};
|
|
1306
|
-
const OPERATORS_LOWERCASE = Object.fromEntries(
|
|
1307
|
-
Object.entries(OPERATORS).map(([key, values]) => [
|
|
1308
|
-
key,
|
|
1309
|
-
values.map((value) => value.toLowerCase())
|
|
1310
|
-
])
|
|
1311
|
-
);
|
|
1312
|
-
const isObjKey = (key, obj) => {
|
|
1313
|
-
return key in obj;
|
|
1314
|
-
};
|
|
1315
|
-
const isOperatorOfType = (type, key, ignoreCase = false) => {
|
|
1316
|
-
if (ignoreCase) {
|
|
1317
|
-
return OPERATORS_LOWERCASE[type]?.includes(key.toLowerCase()) ?? false;
|
|
1318
|
-
}
|
|
1319
|
-
if (isObjKey(type, OPERATORS)) {
|
|
1320
|
-
return OPERATORS[type]?.includes(key) ?? false;
|
|
1321
|
-
}
|
|
1322
|
-
return false;
|
|
1323
|
-
};
|
|
1324
|
-
const isOperator = (key, ignoreCase = false) => {
|
|
1325
|
-
return Object.keys(OPERATORS).some((type) => isOperatorOfType(type, key, ignoreCase));
|
|
1326
|
-
};
|
|
1327
|
-
const { ID_ATTRIBUTE: ID_ATTRIBUTE$3, DOC_ID_ATTRIBUTE: DOC_ID_ATTRIBUTE$3 } = constants$1;
|
|
1328
|
-
const sanitizePasswords = (schema) => async (entity) => {
|
|
1329
|
-
if (!schema) {
|
|
1885
|
+
const { ID_ATTRIBUTE: ID_ATTRIBUTE$2, DOC_ID_ATTRIBUTE: DOC_ID_ATTRIBUTE$2 } = constants$1;
|
|
1886
|
+
const sanitizePasswords = (ctx) => async (entity) => {
|
|
1887
|
+
if (!ctx.schema) {
|
|
1330
1888
|
throw new Error("Missing schema in sanitizePasswords");
|
|
1331
1889
|
}
|
|
1332
|
-
return traverseEntity$1(visitor$8,
|
|
1890
|
+
return traverseEntity$1(visitor$8, ctx, entity);
|
|
1333
1891
|
};
|
|
1334
|
-
const defaultSanitizeOutput = async (
|
|
1335
|
-
if (!schema) {
|
|
1892
|
+
const defaultSanitizeOutput = async (ctx, entity) => {
|
|
1893
|
+
if (!ctx.schema) {
|
|
1336
1894
|
throw new Error("Missing schema in defaultSanitizeOutput");
|
|
1337
1895
|
}
|
|
1338
1896
|
return traverseEntity$1(
|
|
@@ -1340,139 +1898,121 @@ const defaultSanitizeOutput = async (schema, entity) => {
|
|
|
1340
1898
|
visitor$8(...args);
|
|
1341
1899
|
visitor$7(...args);
|
|
1342
1900
|
},
|
|
1343
|
-
|
|
1901
|
+
ctx,
|
|
1344
1902
|
entity
|
|
1345
1903
|
);
|
|
1346
1904
|
};
|
|
1347
|
-
const defaultSanitizeFilters = curry((
|
|
1348
|
-
if (!schema) {
|
|
1905
|
+
const defaultSanitizeFilters = curry((ctx, filters2) => {
|
|
1906
|
+
if (!ctx.schema) {
|
|
1349
1907
|
throw new Error("Missing schema in defaultSanitizeFilters");
|
|
1350
1908
|
}
|
|
1351
1909
|
return pipe(
|
|
1352
1910
|
// Remove keys that are not attributes or valid operators
|
|
1353
|
-
traverseQueryFilters(
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
},
|
|
1363
|
-
{ schema }
|
|
1364
|
-
),
|
|
1911
|
+
traverseQueryFilters(({ key, attribute }, { remove: remove2 }) => {
|
|
1912
|
+
const isAttribute = !!attribute;
|
|
1913
|
+
if ([ID_ATTRIBUTE$2, DOC_ID_ATTRIBUTE$2].includes(key)) {
|
|
1914
|
+
return;
|
|
1915
|
+
}
|
|
1916
|
+
if (!isAttribute && !isOperator(key)) {
|
|
1917
|
+
remove2(key);
|
|
1918
|
+
}
|
|
1919
|
+
}, ctx),
|
|
1365
1920
|
// Remove dynamic zones from filters
|
|
1366
|
-
traverseQueryFilters(visitor$5,
|
|
1921
|
+
traverseQueryFilters(visitor$5, ctx),
|
|
1367
1922
|
// Remove morpTo relations from filters
|
|
1368
|
-
traverseQueryFilters(visitor$6,
|
|
1923
|
+
traverseQueryFilters(visitor$6, ctx),
|
|
1369
1924
|
// Remove passwords from filters
|
|
1370
|
-
traverseQueryFilters(visitor$8,
|
|
1925
|
+
traverseQueryFilters(visitor$8, ctx),
|
|
1371
1926
|
// Remove private from filters
|
|
1372
|
-
traverseQueryFilters(visitor$7,
|
|
1927
|
+
traverseQueryFilters(visitor$7, ctx),
|
|
1373
1928
|
// Remove empty objects
|
|
1374
|
-
traverseQueryFilters(
|
|
1375
|
-
(
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
},
|
|
1380
|
-
{ schema }
|
|
1381
|
-
)
|
|
1929
|
+
traverseQueryFilters(({ key, value }, { remove: remove2 }) => {
|
|
1930
|
+
if (isObject(value) && isEmpty(value)) {
|
|
1931
|
+
remove2(key);
|
|
1932
|
+
}
|
|
1933
|
+
}, ctx)
|
|
1382
1934
|
)(filters2);
|
|
1383
1935
|
});
|
|
1384
|
-
const defaultSanitizeSort = curry((
|
|
1385
|
-
if (!schema) {
|
|
1936
|
+
const defaultSanitizeSort = curry((ctx, sort2) => {
|
|
1937
|
+
if (!ctx.schema) {
|
|
1386
1938
|
throw new Error("Missing schema in defaultSanitizeSort");
|
|
1387
1939
|
}
|
|
1388
1940
|
return pipe(
|
|
1389
1941
|
// Remove non attribute keys
|
|
1390
|
-
traverseQuerySort(
|
|
1391
|
-
(
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
},
|
|
1399
|
-
{ schema }
|
|
1400
|
-
),
|
|
1942
|
+
traverseQuerySort(({ key, attribute }, { remove: remove2 }) => {
|
|
1943
|
+
if ([ID_ATTRIBUTE$2, DOC_ID_ATTRIBUTE$2].includes(key)) {
|
|
1944
|
+
return;
|
|
1945
|
+
}
|
|
1946
|
+
if (!attribute) {
|
|
1947
|
+
remove2(key);
|
|
1948
|
+
}
|
|
1949
|
+
}, ctx),
|
|
1401
1950
|
// Remove dynamic zones from sort
|
|
1402
|
-
traverseQuerySort(visitor$5,
|
|
1951
|
+
traverseQuerySort(visitor$5, ctx),
|
|
1403
1952
|
// Remove morpTo relations from sort
|
|
1404
|
-
traverseQuerySort(visitor$6,
|
|
1953
|
+
traverseQuerySort(visitor$6, ctx),
|
|
1405
1954
|
// Remove private from sort
|
|
1406
|
-
traverseQuerySort(visitor$7,
|
|
1955
|
+
traverseQuerySort(visitor$7, ctx),
|
|
1407
1956
|
// Remove passwords from filters
|
|
1408
|
-
traverseQuerySort(visitor$8,
|
|
1957
|
+
traverseQuerySort(visitor$8, ctx),
|
|
1409
1958
|
// Remove keys for empty non-scalar values
|
|
1410
|
-
traverseQuerySort(
|
|
1411
|
-
(
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
},
|
|
1419
|
-
{ schema }
|
|
1420
|
-
)
|
|
1959
|
+
traverseQuerySort(({ key, attribute, value }, { remove: remove2 }) => {
|
|
1960
|
+
if ([ID_ATTRIBUTE$2, DOC_ID_ATTRIBUTE$2].includes(key)) {
|
|
1961
|
+
return;
|
|
1962
|
+
}
|
|
1963
|
+
if (!isScalarAttribute(attribute) && isEmpty(value)) {
|
|
1964
|
+
remove2(key);
|
|
1965
|
+
}
|
|
1966
|
+
}, ctx)
|
|
1421
1967
|
)(sort2);
|
|
1422
1968
|
});
|
|
1423
|
-
const defaultSanitizeFields = curry((
|
|
1424
|
-
if (!schema) {
|
|
1969
|
+
const defaultSanitizeFields = curry((ctx, fields2) => {
|
|
1970
|
+
if (!ctx.schema) {
|
|
1425
1971
|
throw new Error("Missing schema in defaultSanitizeFields");
|
|
1426
1972
|
}
|
|
1427
1973
|
return pipe(
|
|
1428
1974
|
// Only keep scalar attributes
|
|
1429
|
-
traverseQueryFields(
|
|
1430
|
-
(
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
},
|
|
1438
|
-
{ schema }
|
|
1439
|
-
),
|
|
1975
|
+
traverseQueryFields(({ key, attribute }, { remove: remove2 }) => {
|
|
1976
|
+
if ([ID_ATTRIBUTE$2, DOC_ID_ATTRIBUTE$2].includes(key)) {
|
|
1977
|
+
return;
|
|
1978
|
+
}
|
|
1979
|
+
if (isNil(attribute) || !isScalarAttribute(attribute)) {
|
|
1980
|
+
remove2(key);
|
|
1981
|
+
}
|
|
1982
|
+
}, ctx),
|
|
1440
1983
|
// Remove private fields
|
|
1441
|
-
traverseQueryFields(visitor$7,
|
|
1984
|
+
traverseQueryFields(visitor$7, ctx),
|
|
1442
1985
|
// Remove password fields
|
|
1443
|
-
traverseQueryFields(visitor$8,
|
|
1986
|
+
traverseQueryFields(visitor$8, ctx),
|
|
1444
1987
|
// Remove nil values from fields array
|
|
1445
1988
|
(value) => isArray(value) ? value.filter((field) => !isNil(field)) : value
|
|
1446
1989
|
)(fields2);
|
|
1447
1990
|
});
|
|
1448
|
-
const defaultSanitizePopulate = curry((
|
|
1449
|
-
if (!schema) {
|
|
1991
|
+
const defaultSanitizePopulate = curry((ctx, populate2) => {
|
|
1992
|
+
if (!ctx.schema) {
|
|
1450
1993
|
throw new Error("Missing schema in defaultSanitizePopulate");
|
|
1451
1994
|
}
|
|
1452
1995
|
return pipe(
|
|
1453
|
-
traverseQueryPopulate(visitor$4,
|
|
1454
|
-
traverseQueryPopulate(
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
},
|
|
1472
|
-
{ schema }
|
|
1473
|
-
),
|
|
1996
|
+
traverseQueryPopulate(visitor$4, ctx),
|
|
1997
|
+
traverseQueryPopulate(async ({ key, value, schema, attribute, getModel }, { set }) => {
|
|
1998
|
+
if (attribute) {
|
|
1999
|
+
return;
|
|
2000
|
+
}
|
|
2001
|
+
if (key === "sort") {
|
|
2002
|
+
set(key, await defaultSanitizeSort({ schema, getModel }, value));
|
|
2003
|
+
}
|
|
2004
|
+
if (key === "filters") {
|
|
2005
|
+
set(key, await defaultSanitizeFilters({ schema, getModel }, value));
|
|
2006
|
+
}
|
|
2007
|
+
if (key === "fields") {
|
|
2008
|
+
set(key, await defaultSanitizeFields({ schema, getModel }, value));
|
|
2009
|
+
}
|
|
2010
|
+
if (key === "populate") {
|
|
2011
|
+
set(key, await defaultSanitizePopulate({ schema, getModel }, value));
|
|
2012
|
+
}
|
|
2013
|
+
}, ctx),
|
|
1474
2014
|
// Remove private fields
|
|
1475
|
-
traverseQueryPopulate(visitor$7,
|
|
2015
|
+
traverseQueryPopulate(visitor$7, ctx)
|
|
1476
2016
|
)(populate2);
|
|
1477
2017
|
});
|
|
1478
2018
|
const sanitizers = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
@@ -1484,7 +2024,8 @@ const sanitizers = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
|
|
|
1484
2024
|
defaultSanitizeSort,
|
|
1485
2025
|
sanitizePasswords
|
|
1486
2026
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1487
|
-
const
|
|
2027
|
+
const createAPISanitizers = (opts) => {
|
|
2028
|
+
const { getModel } = opts;
|
|
1488
2029
|
const sanitizeInput = (data, schema, { auth } = {}) => {
|
|
1489
2030
|
if (!schema) {
|
|
1490
2031
|
throw new Error("Missing schema in sanitizeInput");
|
|
@@ -1498,12 +2039,14 @@ const createContentAPISanitizers = () => {
|
|
|
1498
2039
|
omit(constants$1.ID_ATTRIBUTE),
|
|
1499
2040
|
omit(constants$1.DOC_ID_ATTRIBUTE),
|
|
1500
2041
|
// Remove non-writable attributes
|
|
1501
|
-
traverseEntity$1(removeRestrictedFields(nonWritableAttributes), { schema })
|
|
2042
|
+
traverseEntity$1(removeRestrictedFields(nonWritableAttributes), { schema, getModel })
|
|
1502
2043
|
];
|
|
1503
2044
|
if (auth) {
|
|
1504
|
-
transforms.push(
|
|
2045
|
+
transforms.push(
|
|
2046
|
+
traverseEntity$1(removeRestrictedRelations(auth), { schema, getModel })
|
|
2047
|
+
);
|
|
1505
2048
|
}
|
|
1506
|
-
|
|
2049
|
+
opts?.sanitizers?.input?.forEach((sanitizer) => transforms.push(sanitizer(schema)));
|
|
1507
2050
|
return pipe(...transforms)(data);
|
|
1508
2051
|
};
|
|
1509
2052
|
const sanitizeOutput = async (data, schema, { auth } = {}) => {
|
|
@@ -1517,11 +2060,15 @@ const createContentAPISanitizers = () => {
|
|
|
1517
2060
|
}
|
|
1518
2061
|
return res;
|
|
1519
2062
|
}
|
|
1520
|
-
const transforms = [
|
|
2063
|
+
const transforms = [
|
|
2064
|
+
(data2) => defaultSanitizeOutput({ schema, getModel }, data2)
|
|
2065
|
+
];
|
|
1521
2066
|
if (auth) {
|
|
1522
|
-
transforms.push(
|
|
2067
|
+
transforms.push(
|
|
2068
|
+
traverseEntity$1(removeRestrictedRelations(auth), { schema, getModel })
|
|
2069
|
+
);
|
|
1523
2070
|
}
|
|
1524
|
-
|
|
2071
|
+
opts?.sanitizers?.output?.forEach((sanitizer) => transforms.push(sanitizer(schema)));
|
|
1525
2072
|
return pipe(...transforms)(data);
|
|
1526
2073
|
};
|
|
1527
2074
|
const sanitizeQuery = async (query, schema, { auth } = {}) => {
|
|
@@ -1551,9 +2098,11 @@ const createContentAPISanitizers = () => {
|
|
|
1551
2098
|
if (isArray(filters2)) {
|
|
1552
2099
|
return Promise.all(filters2.map((filter) => sanitizeFilters(filter, schema, { auth })));
|
|
1553
2100
|
}
|
|
1554
|
-
const transforms = [defaultSanitizeFilters(schema)];
|
|
2101
|
+
const transforms = [defaultSanitizeFilters({ schema, getModel })];
|
|
1555
2102
|
if (auth) {
|
|
1556
|
-
transforms.push(
|
|
2103
|
+
transforms.push(
|
|
2104
|
+
traverseQueryFilters(removeRestrictedRelations(auth), { schema, getModel })
|
|
2105
|
+
);
|
|
1557
2106
|
}
|
|
1558
2107
|
return pipe(...transforms)(filters2);
|
|
1559
2108
|
};
|
|
@@ -1561,9 +2110,11 @@ const createContentAPISanitizers = () => {
|
|
|
1561
2110
|
if (!schema) {
|
|
1562
2111
|
throw new Error("Missing schema in sanitizeSort");
|
|
1563
2112
|
}
|
|
1564
|
-
const transforms = [defaultSanitizeSort(schema)];
|
|
2113
|
+
const transforms = [defaultSanitizeSort({ schema, getModel })];
|
|
1565
2114
|
if (auth) {
|
|
1566
|
-
transforms.push(
|
|
2115
|
+
transforms.push(
|
|
2116
|
+
traverseQuerySort(removeRestrictedRelations(auth), { schema, getModel })
|
|
2117
|
+
);
|
|
1567
2118
|
}
|
|
1568
2119
|
return pipe(...transforms)(sort2);
|
|
1569
2120
|
};
|
|
@@ -1571,16 +2122,18 @@ const createContentAPISanitizers = () => {
|
|
|
1571
2122
|
if (!schema) {
|
|
1572
2123
|
throw new Error("Missing schema in sanitizeFields");
|
|
1573
2124
|
}
|
|
1574
|
-
const transforms = [defaultSanitizeFields(schema)];
|
|
2125
|
+
const transforms = [defaultSanitizeFields({ schema, getModel })];
|
|
1575
2126
|
return pipe(...transforms)(fields2);
|
|
1576
2127
|
};
|
|
1577
2128
|
const sanitizePopulate = (populate2, schema, { auth } = {}) => {
|
|
1578
2129
|
if (!schema) {
|
|
1579
2130
|
throw new Error("Missing schema in sanitizePopulate");
|
|
1580
2131
|
}
|
|
1581
|
-
const transforms = [defaultSanitizePopulate(schema)];
|
|
2132
|
+
const transforms = [defaultSanitizePopulate({ schema, getModel })];
|
|
1582
2133
|
if (auth) {
|
|
1583
|
-
transforms.push(
|
|
2134
|
+
transforms.push(
|
|
2135
|
+
traverseQueryPopulate(removeRestrictedRelations(auth), { schema, getModel })
|
|
2136
|
+
);
|
|
1584
2137
|
}
|
|
1585
2138
|
return pipe(...transforms)(populate2);
|
|
1586
2139
|
};
|
|
@@ -1594,118 +2147,11 @@ const createContentAPISanitizers = () => {
|
|
|
1594
2147
|
populate: sanitizePopulate
|
|
1595
2148
|
};
|
|
1596
2149
|
};
|
|
1597
|
-
const
|
|
1598
|
-
const index$1 = {
|
|
1599
|
-
contentAPI: contentAPI$1,
|
|
1600
|
-
sanitizers,
|
|
1601
|
-
visitors: visitors$1
|
|
1602
|
-
};
|
|
1603
|
-
const formatYupInnerError = (yupError) => ({
|
|
1604
|
-
path: toPath(yupError.path),
|
|
1605
|
-
message: yupError.message,
|
|
1606
|
-
name: yupError.name
|
|
1607
|
-
});
|
|
1608
|
-
const formatYupErrors = (yupError) => ({
|
|
1609
|
-
errors: isEmpty(yupError.inner) ? [formatYupInnerError(yupError)] : yupError.inner.map(formatYupInnerError),
|
|
1610
|
-
message: yupError.message
|
|
1611
|
-
});
|
|
1612
|
-
class ApplicationError extends Error {
|
|
1613
|
-
name;
|
|
1614
|
-
details;
|
|
1615
|
-
message;
|
|
1616
|
-
constructor(message = "An application error occured", details = {}) {
|
|
1617
|
-
super();
|
|
1618
|
-
this.name = "ApplicationError";
|
|
1619
|
-
this.message = message;
|
|
1620
|
-
this.details = details;
|
|
1621
|
-
}
|
|
1622
|
-
}
|
|
1623
|
-
class ValidationError extends ApplicationError {
|
|
1624
|
-
constructor(message, details) {
|
|
1625
|
-
super(message, details);
|
|
1626
|
-
this.name = "ValidationError";
|
|
1627
|
-
}
|
|
1628
|
-
}
|
|
1629
|
-
class YupValidationError extends ValidationError {
|
|
1630
|
-
constructor(yupError, message) {
|
|
1631
|
-
super("Validation");
|
|
1632
|
-
const { errors: errors2, message: yupMessage } = formatYupErrors(yupError);
|
|
1633
|
-
this.message = message || yupMessage;
|
|
1634
|
-
this.details = { errors: errors2 };
|
|
1635
|
-
}
|
|
1636
|
-
}
|
|
1637
|
-
class PaginationError extends ApplicationError {
|
|
1638
|
-
constructor(message = "Invalid pagination", details) {
|
|
1639
|
-
super(message, details);
|
|
1640
|
-
this.name = "PaginationError";
|
|
1641
|
-
this.message = message;
|
|
1642
|
-
}
|
|
1643
|
-
}
|
|
1644
|
-
class NotFoundError extends ApplicationError {
|
|
1645
|
-
constructor(message = "Entity not found", details) {
|
|
1646
|
-
super(message, details);
|
|
1647
|
-
this.name = "NotFoundError";
|
|
1648
|
-
this.message = message;
|
|
1649
|
-
}
|
|
1650
|
-
}
|
|
1651
|
-
class ForbiddenError extends ApplicationError {
|
|
1652
|
-
constructor(message = "Forbidden access", details) {
|
|
1653
|
-
super(message, details);
|
|
1654
|
-
this.name = "ForbiddenError";
|
|
1655
|
-
this.message = message;
|
|
1656
|
-
}
|
|
1657
|
-
}
|
|
1658
|
-
class UnauthorizedError extends ApplicationError {
|
|
1659
|
-
constructor(message = "Unauthorized", details) {
|
|
1660
|
-
super(message, details);
|
|
1661
|
-
this.name = "UnauthorizedError";
|
|
1662
|
-
this.message = message;
|
|
1663
|
-
}
|
|
1664
|
-
}
|
|
1665
|
-
class RateLimitError extends ApplicationError {
|
|
1666
|
-
constructor(message = "Too many requests, please try again later.", details) {
|
|
1667
|
-
super(message, details);
|
|
1668
|
-
this.name = "RateLimitError";
|
|
1669
|
-
this.message = message;
|
|
1670
|
-
this.details = details || {};
|
|
1671
|
-
}
|
|
1672
|
-
}
|
|
1673
|
-
class PayloadTooLargeError extends ApplicationError {
|
|
1674
|
-
constructor(message = "Entity too large", details) {
|
|
1675
|
-
super(message, details);
|
|
1676
|
-
this.name = "PayloadTooLargeError";
|
|
1677
|
-
this.message = message;
|
|
1678
|
-
}
|
|
1679
|
-
}
|
|
1680
|
-
class PolicyError extends ForbiddenError {
|
|
1681
|
-
constructor(message = "Policy Failed", details) {
|
|
1682
|
-
super(message, details);
|
|
1683
|
-
this.name = "PolicyError";
|
|
1684
|
-
this.message = message;
|
|
1685
|
-
this.details = details || {};
|
|
1686
|
-
}
|
|
1687
|
-
}
|
|
1688
|
-
class NotImplementedError extends ApplicationError {
|
|
1689
|
-
constructor(message = "This feature is not implemented yet", details) {
|
|
1690
|
-
super(message, details);
|
|
1691
|
-
this.name = "NotImplementedError";
|
|
1692
|
-
this.message = message;
|
|
1693
|
-
}
|
|
1694
|
-
}
|
|
1695
|
-
const errors = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2150
|
+
const index$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1696
2151
|
__proto__: null,
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
NotFoundError,
|
|
1701
|
-
NotImplementedError,
|
|
1702
|
-
PaginationError,
|
|
1703
|
-
PayloadTooLargeError,
|
|
1704
|
-
PolicyError,
|
|
1705
|
-
RateLimitError,
|
|
1706
|
-
UnauthorizedError,
|
|
1707
|
-
ValidationError,
|
|
1708
|
-
YupValidationError
|
|
2152
|
+
createAPISanitizers,
|
|
2153
|
+
sanitizers,
|
|
2154
|
+
visitors: index$4
|
|
1709
2155
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1710
2156
|
const throwInvalidParam = ({ key, path }) => {
|
|
1711
2157
|
const msg = path && path !== key ? `Invalid parameter ${key} at ${path}` : `Invalid parameter ${key}`;
|
|
@@ -1828,7 +2274,7 @@ const throwRestrictedFields = (restrictedFields = null) => ({ key, path: { attri
|
|
|
1828
2274
|
throwInvalidParam({ key, path });
|
|
1829
2275
|
}
|
|
1830
2276
|
};
|
|
1831
|
-
const
|
|
2277
|
+
const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1832
2278
|
__proto__: null,
|
|
1833
2279
|
throwDisallowedFields,
|
|
1834
2280
|
throwDynamicZones: visitor,
|
|
@@ -1838,131 +2284,152 @@ const visitors = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProp
|
|
|
1838
2284
|
throwRestrictedFields,
|
|
1839
2285
|
throwRestrictedRelations
|
|
1840
2286
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1841
|
-
const { ID_ATTRIBUTE: ID_ATTRIBUTE$
|
|
1842
|
-
const throwPasswords = (
|
|
1843
|
-
if (!schema) {
|
|
2287
|
+
const { ID_ATTRIBUTE: ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE: DOC_ID_ATTRIBUTE$1 } = constants$1;
|
|
2288
|
+
const throwPasswords = (ctx) => async (entity) => {
|
|
2289
|
+
if (!ctx.schema) {
|
|
1844
2290
|
throw new Error("Missing schema in throwPasswords");
|
|
1845
2291
|
}
|
|
1846
|
-
return traverseEntity$1(visitor$3,
|
|
2292
|
+
return traverseEntity$1(visitor$3, ctx, entity);
|
|
1847
2293
|
};
|
|
1848
|
-
const defaultValidateFilters = curry((
|
|
1849
|
-
if (!schema) {
|
|
2294
|
+
const defaultValidateFilters = curry((ctx, filters2) => {
|
|
2295
|
+
if (!ctx.schema) {
|
|
1850
2296
|
throw new Error("Missing schema in defaultValidateFilters");
|
|
1851
2297
|
}
|
|
1852
2298
|
return pipe(
|
|
1853
2299
|
// keys that are not attributes or valid operators
|
|
1854
|
-
traverseQueryFilters(
|
|
1855
|
-
(
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
},
|
|
1864
|
-
{ schema }
|
|
1865
|
-
),
|
|
2300
|
+
traverseQueryFilters(({ key, attribute, path }) => {
|
|
2301
|
+
if ([ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE$1].includes(key)) {
|
|
2302
|
+
return;
|
|
2303
|
+
}
|
|
2304
|
+
const isAttribute = !!attribute;
|
|
2305
|
+
if (!isAttribute && !isOperator(key)) {
|
|
2306
|
+
throwInvalidParam({ key, path: path.attribute });
|
|
2307
|
+
}
|
|
2308
|
+
}, ctx),
|
|
1866
2309
|
// dynamic zones from filters
|
|
1867
|
-
traverseQueryFilters(visitor,
|
|
2310
|
+
traverseQueryFilters(visitor, ctx),
|
|
1868
2311
|
// morphTo relations from filters; because you can't have deep filtering on morph relations
|
|
1869
|
-
traverseQueryFilters(visitor$1,
|
|
2312
|
+
traverseQueryFilters(visitor$1, ctx),
|
|
1870
2313
|
// passwords from filters
|
|
1871
|
-
traverseQueryFilters(visitor$3,
|
|
2314
|
+
traverseQueryFilters(visitor$3, ctx),
|
|
1872
2315
|
// private from filters
|
|
1873
|
-
traverseQueryFilters(visitor$2,
|
|
2316
|
+
traverseQueryFilters(visitor$2, ctx)
|
|
1874
2317
|
// we allow empty objects to validate and only sanitize them out, so that users may write "lazy" queries without checking their params exist
|
|
1875
2318
|
)(filters2);
|
|
1876
2319
|
});
|
|
1877
|
-
const defaultValidateSort = curry((
|
|
1878
|
-
if (!schema) {
|
|
2320
|
+
const defaultValidateSort = curry((ctx, sort2) => {
|
|
2321
|
+
if (!ctx.schema) {
|
|
1879
2322
|
throw new Error("Missing schema in defaultValidateSort");
|
|
1880
2323
|
}
|
|
1881
2324
|
return pipe(
|
|
1882
2325
|
// non attribute keys
|
|
1883
|
-
traverseQuerySort(
|
|
1884
|
-
(
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
},
|
|
1892
|
-
{ schema }
|
|
1893
|
-
),
|
|
2326
|
+
traverseQuerySort(({ key, attribute, path }) => {
|
|
2327
|
+
if ([ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE$1].includes(key)) {
|
|
2328
|
+
return;
|
|
2329
|
+
}
|
|
2330
|
+
if (!attribute) {
|
|
2331
|
+
throwInvalidParam({ key, path: path.attribute });
|
|
2332
|
+
}
|
|
2333
|
+
}, ctx),
|
|
1894
2334
|
// dynamic zones from sort
|
|
1895
|
-
traverseQuerySort(visitor,
|
|
2335
|
+
traverseQuerySort(visitor, ctx),
|
|
1896
2336
|
// morphTo relations from sort
|
|
1897
|
-
traverseQuerySort(visitor$1,
|
|
2337
|
+
traverseQuerySort(visitor$1, ctx),
|
|
1898
2338
|
// private from sort
|
|
1899
|
-
traverseQuerySort(visitor$2,
|
|
2339
|
+
traverseQuerySort(visitor$2, ctx),
|
|
1900
2340
|
// passwords from filters
|
|
1901
|
-
traverseQuerySort(visitor$3,
|
|
2341
|
+
traverseQuerySort(visitor$3, ctx),
|
|
1902
2342
|
// keys for empty non-scalar values
|
|
1903
|
-
traverseQuerySort(
|
|
1904
|
-
(
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
},
|
|
1912
|
-
{ schema }
|
|
1913
|
-
)
|
|
2343
|
+
traverseQuerySort(({ key, attribute, value, path }) => {
|
|
2344
|
+
if ([ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE$1].includes(key)) {
|
|
2345
|
+
return;
|
|
2346
|
+
}
|
|
2347
|
+
if (!isScalarAttribute(attribute) && isEmpty(value)) {
|
|
2348
|
+
throwInvalidParam({ key, path: path.attribute });
|
|
2349
|
+
}
|
|
2350
|
+
}, ctx)
|
|
1914
2351
|
)(sort2);
|
|
1915
2352
|
});
|
|
1916
|
-
const defaultValidateFields = curry((
|
|
1917
|
-
if (!schema) {
|
|
2353
|
+
const defaultValidateFields = curry((ctx, fields2) => {
|
|
2354
|
+
if (!ctx.schema) {
|
|
1918
2355
|
throw new Error("Missing schema in defaultValidateFields");
|
|
1919
2356
|
}
|
|
1920
2357
|
return pipe(
|
|
1921
2358
|
// Only allow scalar attributes
|
|
1922
|
-
traverseQueryFields(
|
|
1923
|
-
(
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
},
|
|
1931
|
-
{ schema }
|
|
1932
|
-
),
|
|
2359
|
+
traverseQueryFields(({ key, attribute, path }) => {
|
|
2360
|
+
if ([ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE$1].includes(key)) {
|
|
2361
|
+
return;
|
|
2362
|
+
}
|
|
2363
|
+
if (isNil(attribute) || !isScalarAttribute(attribute)) {
|
|
2364
|
+
throwInvalidParam({ key, path: path.attribute });
|
|
2365
|
+
}
|
|
2366
|
+
}, ctx),
|
|
1933
2367
|
// private fields
|
|
1934
|
-
traverseQueryFields(visitor$2,
|
|
2368
|
+
traverseQueryFields(visitor$2, ctx),
|
|
1935
2369
|
// password fields
|
|
1936
|
-
traverseQueryFields(visitor$3,
|
|
2370
|
+
traverseQueryFields(visitor$3, ctx)
|
|
1937
2371
|
)(fields2);
|
|
1938
2372
|
});
|
|
1939
|
-
const defaultValidatePopulate = curry((
|
|
1940
|
-
if (!schema) {
|
|
2373
|
+
const defaultValidatePopulate = curry((ctx, populate2) => {
|
|
2374
|
+
if (!ctx.schema) {
|
|
1941
2375
|
throw new Error("Missing schema in defaultValidatePopulate");
|
|
1942
2376
|
}
|
|
1943
2377
|
return pipe(
|
|
1944
|
-
traverseQueryPopulate(
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
2378
|
+
traverseQueryPopulate(async ({ key, value, schema, attribute, getModel }, { set }) => {
|
|
2379
|
+
if (attribute) {
|
|
2380
|
+
return;
|
|
2381
|
+
}
|
|
2382
|
+
if (key === "sort") {
|
|
2383
|
+
set(
|
|
2384
|
+
key,
|
|
2385
|
+
await defaultValidateSort(
|
|
2386
|
+
{
|
|
2387
|
+
schema,
|
|
2388
|
+
getModel
|
|
2389
|
+
},
|
|
2390
|
+
value
|
|
2391
|
+
)
|
|
2392
|
+
);
|
|
2393
|
+
}
|
|
2394
|
+
if (key === "filters") {
|
|
2395
|
+
set(
|
|
2396
|
+
key,
|
|
2397
|
+
await defaultValidateFilters(
|
|
2398
|
+
{
|
|
2399
|
+
schema,
|
|
2400
|
+
getModel
|
|
2401
|
+
},
|
|
2402
|
+
value
|
|
2403
|
+
)
|
|
2404
|
+
);
|
|
2405
|
+
}
|
|
2406
|
+
if (key === "fields") {
|
|
2407
|
+
set(
|
|
2408
|
+
key,
|
|
2409
|
+
await defaultValidateFields(
|
|
2410
|
+
{
|
|
2411
|
+
schema,
|
|
2412
|
+
getModel
|
|
2413
|
+
},
|
|
2414
|
+
value
|
|
2415
|
+
)
|
|
2416
|
+
);
|
|
2417
|
+
}
|
|
2418
|
+
if (key === "populate") {
|
|
2419
|
+
set(
|
|
2420
|
+
key,
|
|
2421
|
+
await defaultValidatePopulate(
|
|
2422
|
+
{
|
|
2423
|
+
schema,
|
|
2424
|
+
getModel
|
|
2425
|
+
},
|
|
2426
|
+
value
|
|
2427
|
+
)
|
|
2428
|
+
);
|
|
2429
|
+
}
|
|
2430
|
+
}, ctx),
|
|
1964
2431
|
// Remove private fields
|
|
1965
|
-
traverseQueryPopulate(visitor$2,
|
|
2432
|
+
traverseQueryPopulate(visitor$2, ctx)
|
|
1966
2433
|
)(populate2);
|
|
1967
2434
|
});
|
|
1968
2435
|
const validators = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
@@ -1973,8 +2440,9 @@ const validators = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
|
|
|
1973
2440
|
defaultValidateSort,
|
|
1974
2441
|
throwPasswords
|
|
1975
2442
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1976
|
-
const { ID_ATTRIBUTE
|
|
1977
|
-
const
|
|
2443
|
+
const { ID_ATTRIBUTE, DOC_ID_ATTRIBUTE } = constants$1;
|
|
2444
|
+
const createAPIValidators = (opts) => {
|
|
2445
|
+
const { getModel } = opts || {};
|
|
1978
2446
|
const validateInput = async (data, schema, { auth } = {}) => {
|
|
1979
2447
|
if (!schema) {
|
|
1980
2448
|
throw new Error("Missing schema in validateInput");
|
|
@@ -1987,21 +2455,26 @@ const createContentAPIValidators = () => {
|
|
|
1987
2455
|
const transforms = [
|
|
1988
2456
|
(data2) => {
|
|
1989
2457
|
if (isObject(data2)) {
|
|
1990
|
-
if (ID_ATTRIBUTE
|
|
1991
|
-
throwInvalidParam({ key: ID_ATTRIBUTE
|
|
2458
|
+
if (ID_ATTRIBUTE in data2) {
|
|
2459
|
+
throwInvalidParam({ key: ID_ATTRIBUTE });
|
|
1992
2460
|
}
|
|
1993
|
-
if (DOC_ID_ATTRIBUTE
|
|
1994
|
-
throwInvalidParam({ key: DOC_ID_ATTRIBUTE
|
|
2461
|
+
if (DOC_ID_ATTRIBUTE in data2) {
|
|
2462
|
+
throwInvalidParam({ key: DOC_ID_ATTRIBUTE });
|
|
1995
2463
|
}
|
|
1996
2464
|
}
|
|
1997
2465
|
},
|
|
1998
2466
|
// non-writable attributes
|
|
1999
|
-
traverseEntity$1(throwRestrictedFields(nonWritableAttributes), { schema })
|
|
2467
|
+
traverseEntity$1(throwRestrictedFields(nonWritableAttributes), { schema, getModel })
|
|
2000
2468
|
];
|
|
2001
2469
|
if (auth) {
|
|
2002
|
-
transforms.push(
|
|
2003
|
-
|
|
2004
|
-
|
|
2470
|
+
transforms.push(
|
|
2471
|
+
traverseEntity$1(throwRestrictedRelations(auth), {
|
|
2472
|
+
schema,
|
|
2473
|
+
getModel
|
|
2474
|
+
})
|
|
2475
|
+
);
|
|
2476
|
+
}
|
|
2477
|
+
opts?.validators?.input?.forEach((validator) => transforms.push(validator(schema)));
|
|
2005
2478
|
await pipe(...transforms)(data);
|
|
2006
2479
|
};
|
|
2007
2480
|
const validateQuery = async (query, schema, { auth } = {}) => {
|
|
@@ -2030,9 +2503,14 @@ const createContentAPIValidators = () => {
|
|
|
2030
2503
|
await Promise.all(filters2.map((filter) => validateFilters(filter, schema, { auth })));
|
|
2031
2504
|
return;
|
|
2032
2505
|
}
|
|
2033
|
-
const transforms = [defaultValidateFilters(schema)];
|
|
2506
|
+
const transforms = [defaultValidateFilters({ schema, getModel })];
|
|
2034
2507
|
if (auth) {
|
|
2035
|
-
transforms.push(
|
|
2508
|
+
transforms.push(
|
|
2509
|
+
traverseQueryFilters(throwRestrictedRelations(auth), {
|
|
2510
|
+
schema,
|
|
2511
|
+
getModel
|
|
2512
|
+
})
|
|
2513
|
+
);
|
|
2036
2514
|
}
|
|
2037
2515
|
await pipe(...transforms)(filters2);
|
|
2038
2516
|
};
|
|
@@ -2040,9 +2518,14 @@ const createContentAPIValidators = () => {
|
|
|
2040
2518
|
if (!schema) {
|
|
2041
2519
|
throw new Error("Missing schema in validateSort");
|
|
2042
2520
|
}
|
|
2043
|
-
const transforms = [defaultValidateSort(schema)];
|
|
2521
|
+
const transforms = [defaultValidateSort({ schema, getModel })];
|
|
2044
2522
|
if (auth) {
|
|
2045
|
-
transforms.push(
|
|
2523
|
+
transforms.push(
|
|
2524
|
+
traverseQuerySort(throwRestrictedRelations(auth), {
|
|
2525
|
+
schema,
|
|
2526
|
+
getModel
|
|
2527
|
+
})
|
|
2528
|
+
);
|
|
2046
2529
|
}
|
|
2047
2530
|
await pipe(...transforms)(sort2);
|
|
2048
2531
|
};
|
|
@@ -2050,16 +2533,21 @@ const createContentAPIValidators = () => {
|
|
|
2050
2533
|
if (!schema) {
|
|
2051
2534
|
throw new Error("Missing schema in validateFields");
|
|
2052
2535
|
}
|
|
2053
|
-
const transforms = [defaultValidateFields(schema)];
|
|
2536
|
+
const transforms = [defaultValidateFields({ schema, getModel })];
|
|
2054
2537
|
await pipe(...transforms)(fields2);
|
|
2055
2538
|
};
|
|
2056
2539
|
const validatePopulate = async (populate2, schema, { auth } = {}) => {
|
|
2057
2540
|
if (!schema) {
|
|
2058
2541
|
throw new Error("Missing schema in sanitizePopulate");
|
|
2059
2542
|
}
|
|
2060
|
-
const transforms = [defaultValidatePopulate(schema)];
|
|
2543
|
+
const transforms = [defaultValidatePopulate({ schema, getModel })];
|
|
2061
2544
|
if (auth) {
|
|
2062
|
-
transforms.push(
|
|
2545
|
+
transforms.push(
|
|
2546
|
+
traverseQueryPopulate(throwRestrictedRelations(auth), {
|
|
2547
|
+
schema,
|
|
2548
|
+
getModel
|
|
2549
|
+
})
|
|
2550
|
+
);
|
|
2063
2551
|
}
|
|
2064
2552
|
await pipe(...transforms)(populate2);
|
|
2065
2553
|
};
|
|
@@ -2072,436 +2560,12 @@ const createContentAPIValidators = () => {
|
|
|
2072
2560
|
populate: validatePopulate
|
|
2073
2561
|
};
|
|
2074
2562
|
};
|
|
2075
|
-
const
|
|
2076
|
-
|
|
2077
|
-
|
|
2563
|
+
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2564
|
+
__proto__: null,
|
|
2565
|
+
createAPIValidators,
|
|
2078
2566
|
validators,
|
|
2079
|
-
visitors
|
|
2080
|
-
};
|
|
2081
|
-
const { ID_ATTRIBUTE, DOC_ID_ATTRIBUTE, PUBLISHED_AT_ATTRIBUTE } = constants$1;
|
|
2082
|
-
class InvalidOrderError extends Error {
|
|
2083
|
-
constructor() {
|
|
2084
|
-
super();
|
|
2085
|
-
this.message = "Invalid order. order can only be one of asc|desc|ASC|DESC";
|
|
2086
|
-
}
|
|
2087
|
-
}
|
|
2088
|
-
class InvalidSortError extends Error {
|
|
2089
|
-
constructor() {
|
|
2090
|
-
super();
|
|
2091
|
-
this.message = "Invalid sort parameter. Expected a string, an array of strings, a sort object or an array of sort objects";
|
|
2092
|
-
}
|
|
2093
|
-
}
|
|
2094
|
-
function validateOrder(order) {
|
|
2095
|
-
if (!isString(order) || !["asc", "desc"].includes(order.toLocaleLowerCase())) {
|
|
2096
|
-
throw new InvalidOrderError();
|
|
2097
|
-
}
|
|
2098
|
-
}
|
|
2099
|
-
const convertCountQueryParams = (countQuery) => {
|
|
2100
|
-
return parseType({ type: "boolean", value: countQuery });
|
|
2101
|
-
};
|
|
2102
|
-
const convertOrderingQueryParams = (ordering) => {
|
|
2103
|
-
return ordering;
|
|
2104
|
-
};
|
|
2105
|
-
const isPlainObject = (value) => _$1.isPlainObject(value);
|
|
2106
|
-
const isStringArray = (value) => isArray(value) && value.every(isString);
|
|
2107
|
-
const convertSortQueryParams = (sortQuery) => {
|
|
2108
|
-
if (typeof sortQuery === "string") {
|
|
2109
|
-
return convertStringSortQueryParam(sortQuery);
|
|
2110
|
-
}
|
|
2111
|
-
if (isStringArray(sortQuery)) {
|
|
2112
|
-
return sortQuery.flatMap((sortValue) => convertStringSortQueryParam(sortValue));
|
|
2113
|
-
}
|
|
2114
|
-
if (Array.isArray(sortQuery)) {
|
|
2115
|
-
return sortQuery.map((sortValue) => convertNestedSortQueryParam(sortValue));
|
|
2116
|
-
}
|
|
2117
|
-
if (isPlainObject(sortQuery)) {
|
|
2118
|
-
return convertNestedSortQueryParam(sortQuery);
|
|
2119
|
-
}
|
|
2120
|
-
throw new InvalidSortError();
|
|
2121
|
-
};
|
|
2122
|
-
const convertStringSortQueryParam = (sortQuery) => {
|
|
2123
|
-
return sortQuery.split(",").map((value) => convertSingleSortQueryParam(value));
|
|
2124
|
-
};
|
|
2125
|
-
const convertSingleSortQueryParam = (sortQuery) => {
|
|
2126
|
-
if (!sortQuery) {
|
|
2127
|
-
return {};
|
|
2128
|
-
}
|
|
2129
|
-
if (!isString(sortQuery)) {
|
|
2130
|
-
throw new Error("Invalid sort query");
|
|
2131
|
-
}
|
|
2132
|
-
const [field, order = "asc"] = sortQuery.split(":");
|
|
2133
|
-
if (field.length === 0) {
|
|
2134
|
-
throw new Error("Field cannot be empty");
|
|
2135
|
-
}
|
|
2136
|
-
validateOrder(order);
|
|
2137
|
-
return _$1.set({}, field, order);
|
|
2138
|
-
};
|
|
2139
|
-
const convertNestedSortQueryParam = (sortQuery) => {
|
|
2140
|
-
const transformedSort = {};
|
|
2141
|
-
for (const field of Object.keys(sortQuery)) {
|
|
2142
|
-
const order = sortQuery[field];
|
|
2143
|
-
if (isPlainObject(order)) {
|
|
2144
|
-
transformedSort[field] = convertNestedSortQueryParam(order);
|
|
2145
|
-
} else if (typeof order === "string") {
|
|
2146
|
-
validateOrder(order);
|
|
2147
|
-
transformedSort[field] = order;
|
|
2148
|
-
} else {
|
|
2149
|
-
throw Error(`Invalid sort type expected object or string got ${typeof order}`);
|
|
2150
|
-
}
|
|
2151
|
-
}
|
|
2152
|
-
return transformedSort;
|
|
2153
|
-
};
|
|
2154
|
-
const convertStartQueryParams = (startQuery) => {
|
|
2155
|
-
const startAsANumber = _$1.toNumber(startQuery);
|
|
2156
|
-
if (!_$1.isInteger(startAsANumber) || startAsANumber < 0) {
|
|
2157
|
-
throw new Error(`convertStartQueryParams expected a positive integer got ${startAsANumber}`);
|
|
2158
|
-
}
|
|
2159
|
-
return startAsANumber;
|
|
2160
|
-
};
|
|
2161
|
-
const convertLimitQueryParams = (limitQuery) => {
|
|
2162
|
-
const limitAsANumber = _$1.toNumber(limitQuery);
|
|
2163
|
-
if (!_$1.isInteger(limitAsANumber) || limitAsANumber !== -1 && limitAsANumber < 0) {
|
|
2164
|
-
throw new Error(`convertLimitQueryParams expected a positive integer got ${limitAsANumber}`);
|
|
2165
|
-
}
|
|
2166
|
-
if (limitAsANumber === -1) {
|
|
2167
|
-
return void 0;
|
|
2168
|
-
}
|
|
2169
|
-
return limitAsANumber;
|
|
2170
|
-
};
|
|
2171
|
-
const convertPageQueryParams = (page) => {
|
|
2172
|
-
const pageVal = toNumber(page);
|
|
2173
|
-
if (!isInteger(pageVal) || pageVal <= 0) {
|
|
2174
|
-
throw new PaginationError(
|
|
2175
|
-
`Invalid 'page' parameter. Expected an integer > 0, received: ${page}`
|
|
2176
|
-
);
|
|
2177
|
-
}
|
|
2178
|
-
return pageVal;
|
|
2179
|
-
};
|
|
2180
|
-
const convertPageSizeQueryParams = (pageSize, page) => {
|
|
2181
|
-
const pageSizeVal = toNumber(pageSize);
|
|
2182
|
-
if (!isInteger(pageSizeVal) || pageSizeVal <= 0) {
|
|
2183
|
-
throw new PaginationError(
|
|
2184
|
-
`Invalid 'pageSize' parameter. Expected an integer > 0, received: ${page}`
|
|
2185
|
-
);
|
|
2186
|
-
}
|
|
2187
|
-
return pageSizeVal;
|
|
2188
|
-
};
|
|
2189
|
-
const validatePaginationParams = (page, pageSize, start, limit) => {
|
|
2190
|
-
const isPagePagination = !isNil(page) || !isNil(pageSize);
|
|
2191
|
-
const isOffsetPagination = !isNil(start) || !isNil(limit);
|
|
2192
|
-
if (isPagePagination && isOffsetPagination) {
|
|
2193
|
-
throw new PaginationError(
|
|
2194
|
-
"Invalid pagination attributes. You cannot use page and offset pagination in the same query"
|
|
2195
|
-
);
|
|
2196
|
-
}
|
|
2197
|
-
};
|
|
2198
|
-
class InvalidPopulateError extends Error {
|
|
2199
|
-
constructor() {
|
|
2200
|
-
super();
|
|
2201
|
-
this.message = "Invalid populate parameter. Expected a string, an array of strings, a populate object";
|
|
2202
|
-
}
|
|
2203
|
-
}
|
|
2204
|
-
const convertPopulateQueryParams = (populate2, schema, depth = 0) => {
|
|
2205
|
-
if (depth === 0 && populate2 === "*") {
|
|
2206
|
-
return true;
|
|
2207
|
-
}
|
|
2208
|
-
if (typeof populate2 === "string") {
|
|
2209
|
-
return populate2.split(",").map((value) => _$1.trim(value));
|
|
2210
|
-
}
|
|
2211
|
-
if (Array.isArray(populate2)) {
|
|
2212
|
-
return _$1.uniq(
|
|
2213
|
-
populate2.flatMap((value) => {
|
|
2214
|
-
if (typeof value !== "string") {
|
|
2215
|
-
throw new InvalidPopulateError();
|
|
2216
|
-
}
|
|
2217
|
-
return value.split(",").map((value2) => _$1.trim(value2));
|
|
2218
|
-
})
|
|
2219
|
-
);
|
|
2220
|
-
}
|
|
2221
|
-
if (_$1.isPlainObject(populate2)) {
|
|
2222
|
-
return convertPopulateObject(populate2, schema);
|
|
2223
|
-
}
|
|
2224
|
-
throw new InvalidPopulateError();
|
|
2225
|
-
};
|
|
2226
|
-
const hasFragmentPopulateDefined = (populate2) => {
|
|
2227
|
-
return typeof populate2 === "object" && "on" in populate2 && !isNil(populate2.on);
|
|
2228
|
-
};
|
|
2229
|
-
const convertPopulateObject = (populate2, schema) => {
|
|
2230
|
-
if (!schema) {
|
|
2231
|
-
return {};
|
|
2232
|
-
}
|
|
2233
|
-
const { attributes } = schema;
|
|
2234
|
-
return Object.entries(populate2).reduce((acc, [key, subPopulate]) => {
|
|
2235
|
-
if (_$1.isBoolean(subPopulate)) {
|
|
2236
|
-
return { ...acc, [key]: subPopulate };
|
|
2237
|
-
}
|
|
2238
|
-
const attribute = attributes[key];
|
|
2239
|
-
if (!attribute) {
|
|
2240
|
-
return acc;
|
|
2241
|
-
}
|
|
2242
|
-
const isAllowedAttributeForFragmentPopulate = isDynamicZoneAttribute(attribute) || isMorphToRelationalAttribute(attribute);
|
|
2243
|
-
if (isAllowedAttributeForFragmentPopulate && hasFragmentPopulateDefined(subPopulate)) {
|
|
2244
|
-
return {
|
|
2245
|
-
...acc,
|
|
2246
|
-
[key]: {
|
|
2247
|
-
on: Object.entries(subPopulate.on).reduce(
|
|
2248
|
-
(acc2, [type, typeSubPopulate]) => ({
|
|
2249
|
-
...acc2,
|
|
2250
|
-
[type]: convertNestedPopulate(typeSubPopulate, strapi.getModel(type))
|
|
2251
|
-
}),
|
|
2252
|
-
{}
|
|
2253
|
-
)
|
|
2254
|
-
}
|
|
2255
|
-
};
|
|
2256
|
-
}
|
|
2257
|
-
if (isDynamicZoneAttribute(attribute)) {
|
|
2258
|
-
const populates = attribute.components.map((uid) => strapi.getModel(uid)).map((schema2) => convertNestedPopulate(subPopulate, schema2)).map((populate22) => populate22 === true ? {} : populate22).filter((populate22) => populate22 !== false);
|
|
2259
|
-
if (isEmpty(populates)) {
|
|
2260
|
-
return acc;
|
|
2261
|
-
}
|
|
2262
|
-
return {
|
|
2263
|
-
...acc,
|
|
2264
|
-
[key]: mergeAll(populates)
|
|
2265
|
-
};
|
|
2266
|
-
}
|
|
2267
|
-
if (isMorphToRelationalAttribute(attribute)) {
|
|
2268
|
-
return { ...acc, [key]: convertNestedPopulate(subPopulate, void 0) };
|
|
2269
|
-
}
|
|
2270
|
-
let targetSchemaUID;
|
|
2271
|
-
if (attribute.type === "relation") {
|
|
2272
|
-
targetSchemaUID = attribute.target;
|
|
2273
|
-
} else if (attribute.type === "component") {
|
|
2274
|
-
targetSchemaUID = attribute.component;
|
|
2275
|
-
} else if (attribute.type === "media") {
|
|
2276
|
-
targetSchemaUID = "plugin::upload.file";
|
|
2277
|
-
} else {
|
|
2278
|
-
return acc;
|
|
2279
|
-
}
|
|
2280
|
-
const targetSchema = strapi.getModel(targetSchemaUID);
|
|
2281
|
-
if (!targetSchema) {
|
|
2282
|
-
return acc;
|
|
2283
|
-
}
|
|
2284
|
-
const populateObject = convertNestedPopulate(subPopulate, targetSchema);
|
|
2285
|
-
if (!populateObject) {
|
|
2286
|
-
return acc;
|
|
2287
|
-
}
|
|
2288
|
-
return {
|
|
2289
|
-
...acc,
|
|
2290
|
-
[key]: populateObject
|
|
2291
|
-
};
|
|
2292
|
-
}, {});
|
|
2293
|
-
};
|
|
2294
|
-
const convertNestedPopulate = (subPopulate, schema) => {
|
|
2295
|
-
if (_$1.isString(subPopulate)) {
|
|
2296
|
-
return parseType({ type: "boolean", value: subPopulate, forceCast: true });
|
|
2297
|
-
}
|
|
2298
|
-
if (_$1.isBoolean(subPopulate)) {
|
|
2299
|
-
return subPopulate;
|
|
2300
|
-
}
|
|
2301
|
-
if (!isPlainObject(subPopulate)) {
|
|
2302
|
-
throw new Error(`Invalid nested populate. Expected '*' or an object`);
|
|
2303
|
-
}
|
|
2304
|
-
const { sort: sort2, filters: filters2, fields: fields2, populate: populate2, count, ordering, page, pageSize, start, limit } = subPopulate;
|
|
2305
|
-
const query = {};
|
|
2306
|
-
if (sort2) {
|
|
2307
|
-
query.orderBy = convertSortQueryParams(sort2);
|
|
2308
|
-
}
|
|
2309
|
-
if (filters2) {
|
|
2310
|
-
query.where = convertFiltersQueryParams(filters2, schema);
|
|
2311
|
-
}
|
|
2312
|
-
if (fields2) {
|
|
2313
|
-
query.select = convertFieldsQueryParams(fields2);
|
|
2314
|
-
}
|
|
2315
|
-
if (populate2) {
|
|
2316
|
-
query.populate = convertPopulateQueryParams(populate2, schema);
|
|
2317
|
-
}
|
|
2318
|
-
if (count) {
|
|
2319
|
-
query.count = convertCountQueryParams(count);
|
|
2320
|
-
}
|
|
2321
|
-
if (ordering) {
|
|
2322
|
-
query.ordering = convertOrderingQueryParams(ordering);
|
|
2323
|
-
}
|
|
2324
|
-
validatePaginationParams(page, pageSize, start, limit);
|
|
2325
|
-
if (!isNil(page)) {
|
|
2326
|
-
query.page = convertPageQueryParams(page);
|
|
2327
|
-
}
|
|
2328
|
-
if (!isNil(pageSize)) {
|
|
2329
|
-
query.pageSize = convertPageSizeQueryParams(pageSize, page);
|
|
2330
|
-
}
|
|
2331
|
-
if (!isNil(start)) {
|
|
2332
|
-
query.offset = convertStartQueryParams(start);
|
|
2333
|
-
}
|
|
2334
|
-
if (!isNil(limit)) {
|
|
2335
|
-
query.limit = convertLimitQueryParams(limit);
|
|
2336
|
-
}
|
|
2337
|
-
return query;
|
|
2338
|
-
};
|
|
2339
|
-
const convertFieldsQueryParams = (fields2, depth = 0) => {
|
|
2340
|
-
if (depth === 0 && fields2 === "*") {
|
|
2341
|
-
return void 0;
|
|
2342
|
-
}
|
|
2343
|
-
if (typeof fields2 === "string") {
|
|
2344
|
-
const fieldsValues = fields2.split(",").map((value) => _$1.trim(value));
|
|
2345
|
-
return _$1.uniq([ID_ATTRIBUTE, DOC_ID_ATTRIBUTE, ...fieldsValues]);
|
|
2346
|
-
}
|
|
2347
|
-
if (isStringArray(fields2)) {
|
|
2348
|
-
const fieldsValues = fields2.flatMap((value) => convertFieldsQueryParams(value, depth + 1)).filter((v) => !isNil(v));
|
|
2349
|
-
return _$1.uniq([ID_ATTRIBUTE, DOC_ID_ATTRIBUTE, ...fieldsValues]);
|
|
2350
|
-
}
|
|
2351
|
-
throw new Error("Invalid fields parameter. Expected a string or an array of strings");
|
|
2352
|
-
};
|
|
2353
|
-
const isValidSchemaAttribute = (key, schema) => {
|
|
2354
|
-
if ([DOC_ID_ATTRIBUTE, ID_ATTRIBUTE].includes(key)) {
|
|
2355
|
-
return true;
|
|
2356
|
-
}
|
|
2357
|
-
if (!schema) {
|
|
2358
|
-
return false;
|
|
2359
|
-
}
|
|
2360
|
-
return Object.keys(schema.attributes).includes(key);
|
|
2361
|
-
};
|
|
2362
|
-
const convertFiltersQueryParams = (filters2, schema) => {
|
|
2363
|
-
if (!isObject(filters2)) {
|
|
2364
|
-
throw new Error("The filters parameter must be an object or an array");
|
|
2365
|
-
}
|
|
2366
|
-
const filtersCopy = cloneDeep(filters2);
|
|
2367
|
-
return convertAndSanitizeFilters(filtersCopy, schema);
|
|
2368
|
-
};
|
|
2369
|
-
const convertAndSanitizeFilters = (filters2, schema) => {
|
|
2370
|
-
if (Array.isArray(filters2)) {
|
|
2371
|
-
return filters2.map((filter) => convertAndSanitizeFilters(filter, schema)).filter((filter) => !isPlainObject(filter) || !isEmpty(filter));
|
|
2372
|
-
}
|
|
2373
|
-
if (!isPlainObject(filters2)) {
|
|
2374
|
-
return filters2;
|
|
2375
|
-
}
|
|
2376
|
-
const removeOperator = (operator) => delete filters2[operator];
|
|
2377
|
-
for (const [key, value] of Object.entries(filters2)) {
|
|
2378
|
-
const attribute = get(key, schema?.attributes);
|
|
2379
|
-
const validKey = isOperator(key) || isValidSchemaAttribute(key, schema);
|
|
2380
|
-
if (!validKey) {
|
|
2381
|
-
removeOperator(key);
|
|
2382
|
-
} else if (attribute) {
|
|
2383
|
-
if (attribute.type === "relation") {
|
|
2384
|
-
filters2[key] = convertAndSanitizeFilters(value, strapi.getModel(attribute.target));
|
|
2385
|
-
} else if (attribute.type === "component") {
|
|
2386
|
-
filters2[key] = convertAndSanitizeFilters(value, strapi.getModel(attribute.component));
|
|
2387
|
-
} else if (attribute.type === "media") {
|
|
2388
|
-
filters2[key] = convertAndSanitizeFilters(value, strapi.getModel("plugin::upload.file"));
|
|
2389
|
-
} else if (attribute.type === "dynamiczone") {
|
|
2390
|
-
removeOperator(key);
|
|
2391
|
-
} else if (attribute.type === "password") {
|
|
2392
|
-
removeOperator(key);
|
|
2393
|
-
} else {
|
|
2394
|
-
filters2[key] = convertAndSanitizeFilters(value, schema);
|
|
2395
|
-
}
|
|
2396
|
-
} else if (["$null", "$notNull"].includes(key)) {
|
|
2397
|
-
filters2[key] = parseType({ type: "boolean", value: filters2[key], forceCast: true });
|
|
2398
|
-
} else if (isObject(value)) {
|
|
2399
|
-
filters2[key] = convertAndSanitizeFilters(value, schema);
|
|
2400
|
-
}
|
|
2401
|
-
if (isPlainObject(filters2[key]) && isEmpty(filters2[key])) {
|
|
2402
|
-
removeOperator(key);
|
|
2403
|
-
}
|
|
2404
|
-
}
|
|
2405
|
-
return filters2;
|
|
2406
|
-
};
|
|
2407
|
-
const convertStatusParams = (status, query = {}) => {
|
|
2408
|
-
query.filters = ({ meta }) => {
|
|
2409
|
-
const contentType = strapi.contentTypes[meta.uid];
|
|
2410
|
-
if (!contentType || !hasDraftAndPublish(contentType)) {
|
|
2411
|
-
return {};
|
|
2412
|
-
}
|
|
2413
|
-
return { [PUBLISHED_AT_ATTRIBUTE]: { $null: status === "draft" } };
|
|
2414
|
-
};
|
|
2415
|
-
};
|
|
2416
|
-
const transformParamsToQuery = (uid, params) => {
|
|
2417
|
-
const schema = strapi.getModel(uid);
|
|
2418
|
-
const query = {};
|
|
2419
|
-
const { _q, sort: sort2, filters: filters2, fields: fields2, populate: populate2, page, pageSize, start, limit, status, ...rest } = params;
|
|
2420
|
-
if (!isNil(status)) {
|
|
2421
|
-
convertStatusParams(status, query);
|
|
2422
|
-
}
|
|
2423
|
-
if (!isNil(_q)) {
|
|
2424
|
-
query._q = _q;
|
|
2425
|
-
}
|
|
2426
|
-
if (!isNil(sort2)) {
|
|
2427
|
-
query.orderBy = convertSortQueryParams(sort2);
|
|
2428
|
-
}
|
|
2429
|
-
if (!isNil(filters2)) {
|
|
2430
|
-
query.where = convertFiltersQueryParams(filters2, schema);
|
|
2431
|
-
}
|
|
2432
|
-
if (!isNil(fields2)) {
|
|
2433
|
-
query.select = convertFieldsQueryParams(fields2);
|
|
2434
|
-
}
|
|
2435
|
-
if (!isNil(populate2)) {
|
|
2436
|
-
query.populate = convertPopulateQueryParams(populate2, schema);
|
|
2437
|
-
}
|
|
2438
|
-
validatePaginationParams(page, pageSize, start, limit);
|
|
2439
|
-
if (!isNil(page)) {
|
|
2440
|
-
query.page = convertPageQueryParams(page);
|
|
2441
|
-
}
|
|
2442
|
-
if (!isNil(pageSize)) {
|
|
2443
|
-
query.pageSize = convertPageSizeQueryParams(pageSize, page);
|
|
2444
|
-
}
|
|
2445
|
-
if (!isNil(start)) {
|
|
2446
|
-
query.offset = convertStartQueryParams(start);
|
|
2447
|
-
}
|
|
2448
|
-
if (!isNil(limit)) {
|
|
2449
|
-
query.limit = convertLimitQueryParams(limit);
|
|
2450
|
-
}
|
|
2451
|
-
return {
|
|
2452
|
-
...rest,
|
|
2453
|
-
...query
|
|
2454
|
-
};
|
|
2455
|
-
};
|
|
2456
|
-
const convertQueryParams = {
|
|
2457
|
-
convertSortQueryParams,
|
|
2458
|
-
convertStartQueryParams,
|
|
2459
|
-
convertLimitQueryParams,
|
|
2460
|
-
convertPopulateQueryParams,
|
|
2461
|
-
convertFiltersQueryParams,
|
|
2462
|
-
convertFieldsQueryParams,
|
|
2463
|
-
transformParamsToQuery
|
|
2464
|
-
};
|
|
2465
|
-
function importDefault(modName) {
|
|
2466
|
-
const mod = require(modName);
|
|
2467
|
-
return mod && mod.__esModule ? mod.default : mod;
|
|
2468
|
-
}
|
|
2469
|
-
const machineId = () => {
|
|
2470
|
-
try {
|
|
2471
|
-
const deviceId = machineIdSync();
|
|
2472
|
-
return deviceId;
|
|
2473
|
-
} catch (error) {
|
|
2474
|
-
const deviceId = randomUUID();
|
|
2475
|
-
return deviceId;
|
|
2476
|
-
}
|
|
2477
|
-
};
|
|
2478
|
-
const handleYupError = (error, errorMessage) => {
|
|
2479
|
-
throw new YupValidationError(error, errorMessage);
|
|
2480
|
-
};
|
|
2481
|
-
const defaultValidationParam = { strict: true, abortEarly: false };
|
|
2482
|
-
const validateYupSchema = (schema, options = {}) => async (body, errorMessage) => {
|
|
2483
|
-
try {
|
|
2484
|
-
const optionsWithDefaults = defaults(defaultValidationParam, options);
|
|
2485
|
-
const result = await schema.validate(body, optionsWithDefaults);
|
|
2486
|
-
return result;
|
|
2487
|
-
} catch (e) {
|
|
2488
|
-
if (e instanceof yup$1.ValidationError) {
|
|
2489
|
-
handleYupError(e, errorMessage);
|
|
2490
|
-
}
|
|
2491
|
-
throw e;
|
|
2492
|
-
}
|
|
2493
|
-
};
|
|
2494
|
-
const validateYupSchemaSync = (schema, options = {}) => (body, errorMessage) => {
|
|
2495
|
-
try {
|
|
2496
|
-
const optionsWithDefaults = defaults(defaultValidationParam, options);
|
|
2497
|
-
return schema.validateSync(body, optionsWithDefaults);
|
|
2498
|
-
} catch (e) {
|
|
2499
|
-
if (e instanceof yup$1.ValidationError) {
|
|
2500
|
-
handleYupError(e, errorMessage);
|
|
2501
|
-
}
|
|
2502
|
-
throw e;
|
|
2503
|
-
}
|
|
2504
|
-
};
|
|
2567
|
+
visitors: index$1
|
|
2568
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
2505
2569
|
const STRAPI_DEFAULTS = {
|
|
2506
2570
|
offset: {
|
|
2507
2571
|
start: 0,
|
|
@@ -2653,72 +2717,6 @@ const file = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty
|
|
|
2653
2717
|
streamToBuffer,
|
|
2654
2718
|
writableDiscardStream
|
|
2655
2719
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2656
|
-
const PLUGIN_PREFIX = "plugin::";
|
|
2657
|
-
const API_PREFIX = "api::";
|
|
2658
|
-
const parsePolicy = (policy2) => {
|
|
2659
|
-
if (typeof policy2 === "string") {
|
|
2660
|
-
return { policyName: policy2, config: {} };
|
|
2661
|
-
}
|
|
2662
|
-
const { name, config } = policy2;
|
|
2663
|
-
return { policyName: name, config };
|
|
2664
|
-
};
|
|
2665
|
-
const searchLocalPolicy = (policyName, policyContext) => {
|
|
2666
|
-
const { pluginName, apiName } = policyContext ?? {};
|
|
2667
|
-
if (pluginName) {
|
|
2668
|
-
return strapi.policy(`${PLUGIN_PREFIX}${pluginName}.${policyName}`);
|
|
2669
|
-
}
|
|
2670
|
-
if (apiName) {
|
|
2671
|
-
return strapi.policy(`${API_PREFIX}${apiName}.${policyName}`);
|
|
2672
|
-
}
|
|
2673
|
-
};
|
|
2674
|
-
const globalPolicy = ({ method, endpoint, controller, action, plugin }) => {
|
|
2675
|
-
return async (ctx, next) => {
|
|
2676
|
-
ctx.request.route = {
|
|
2677
|
-
endpoint: `${method} ${endpoint}`,
|
|
2678
|
-
controller: _$1.toLower(controller),
|
|
2679
|
-
action: _$1.toLower(action),
|
|
2680
|
-
verb: _$1.toLower(method),
|
|
2681
|
-
plugin
|
|
2682
|
-
};
|
|
2683
|
-
await next();
|
|
2684
|
-
};
|
|
2685
|
-
};
|
|
2686
|
-
const resolvePolicies = (config, policyContext) => {
|
|
2687
|
-
const { pluginName, apiName } = policyContext ?? {};
|
|
2688
|
-
return config.map((policyConfig) => {
|
|
2689
|
-
return {
|
|
2690
|
-
handler: getPolicy(policyConfig, { pluginName, apiName }),
|
|
2691
|
-
config: typeof policyConfig === "object" && policyConfig.config || {}
|
|
2692
|
-
};
|
|
2693
|
-
});
|
|
2694
|
-
};
|
|
2695
|
-
const findPolicy = (name, policyContext) => {
|
|
2696
|
-
const { pluginName, apiName } = policyContext ?? {};
|
|
2697
|
-
const resolvedPolicy = strapi.policy(name);
|
|
2698
|
-
if (resolvedPolicy !== void 0) {
|
|
2699
|
-
return resolvedPolicy;
|
|
2700
|
-
}
|
|
2701
|
-
const localPolicy = searchLocalPolicy(name, { pluginName, apiName });
|
|
2702
|
-
if (localPolicy !== void 0) {
|
|
2703
|
-
return localPolicy;
|
|
2704
|
-
}
|
|
2705
|
-
throw new Error(`Could not find policy "${name}"`);
|
|
2706
|
-
};
|
|
2707
|
-
const getPolicy = (policyConfig, policyContext) => {
|
|
2708
|
-
const { pluginName, apiName } = policyContext ?? {};
|
|
2709
|
-
if (typeof policyConfig === "function") {
|
|
2710
|
-
return policyConfig;
|
|
2711
|
-
}
|
|
2712
|
-
const { policyName, config } = parsePolicy(policyConfig);
|
|
2713
|
-
const policy2 = findPolicy(policyName, { pluginName, apiName });
|
|
2714
|
-
if (typeof policy2 === "function") {
|
|
2715
|
-
return policy2;
|
|
2716
|
-
}
|
|
2717
|
-
if (policy2.validator) {
|
|
2718
|
-
policy2.validator(config);
|
|
2719
|
-
}
|
|
2720
|
-
return policy2.handler;
|
|
2721
|
-
};
|
|
2722
2720
|
const createPolicy = (options) => {
|
|
2723
2721
|
const { name = "unnamed", validator, handler } = options;
|
|
2724
2722
|
const wrappedValidator = (config) => {
|
|
@@ -2750,10 +2748,7 @@ const createPolicyContext = (type, ctx) => {
|
|
|
2750
2748
|
const policy = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2751
2749
|
__proto__: null,
|
|
2752
2750
|
createPolicy,
|
|
2753
|
-
createPolicyContext
|
|
2754
|
-
get: getPolicy,
|
|
2755
|
-
globalPolicy,
|
|
2756
|
-
resolve: resolvePolicies
|
|
2751
|
+
createPolicyContext
|
|
2757
2752
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2758
2753
|
const nameToSlug = (name, options = { separator: "-" }) => slugify(name, options);
|
|
2759
2754
|
const nameToCollectionName = (name) => slugify(name, { separator: "_" });
|
|
@@ -2992,11 +2987,31 @@ const relations = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePro
|
|
|
2992
2987
|
isManyToAny,
|
|
2993
2988
|
isOneToAny
|
|
2994
2989
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2990
|
+
const validateZod = (schema) => (data) => {
|
|
2991
|
+
try {
|
|
2992
|
+
return schema.parse(data);
|
|
2993
|
+
} catch (error) {
|
|
2994
|
+
if (error instanceof z.ZodError) {
|
|
2995
|
+
const { message, errors: errors2 } = formatZodErrors(error);
|
|
2996
|
+
throw new ValidationError(message, { errors: errors2 });
|
|
2997
|
+
}
|
|
2998
|
+
throw error;
|
|
2999
|
+
}
|
|
3000
|
+
};
|
|
3001
|
+
const formatZodErrors = (zodError) => ({
|
|
3002
|
+
errors: zodError.errors.map((error) => {
|
|
3003
|
+
return {
|
|
3004
|
+
path: error.path,
|
|
3005
|
+
message: error.message,
|
|
3006
|
+
name: "ValidationError"
|
|
3007
|
+
};
|
|
3008
|
+
}),
|
|
3009
|
+
message: "Validation error"
|
|
3010
|
+
});
|
|
2995
3011
|
export {
|
|
2996
3012
|
arrays,
|
|
2997
3013
|
async,
|
|
2998
3014
|
contentTypes,
|
|
2999
|
-
convertQueryParams,
|
|
3000
3015
|
dates,
|
|
3001
3016
|
env,
|
|
3002
3017
|
errors,
|
|
@@ -3012,16 +3027,18 @@ export {
|
|
|
3012
3027
|
parseType,
|
|
3013
3028
|
policy,
|
|
3014
3029
|
providerFactory,
|
|
3030
|
+
convertQueryParams as queryParams,
|
|
3015
3031
|
relations,
|
|
3016
|
-
index$
|
|
3032
|
+
index$2 as sanitize,
|
|
3017
3033
|
setCreatorFields,
|
|
3018
3034
|
strings,
|
|
3019
3035
|
template,
|
|
3020
|
-
index$
|
|
3036
|
+
index$3 as traverse,
|
|
3021
3037
|
traverseEntity$1 as traverseEntity,
|
|
3022
3038
|
index as validate,
|
|
3023
3039
|
validateYupSchema,
|
|
3024
3040
|
validateYupSchemaSync,
|
|
3041
|
+
validateZod,
|
|
3025
3042
|
yup
|
|
3026
3043
|
};
|
|
3027
3044
|
//# sourceMappingURL=index.mjs.map
|