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