phecda-core 5.2.0 → 5.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +11 -2
- package/dist/index.d.ts +11 -2
- package/dist/index.js +255 -118
- package/dist/index.mjs +252 -118
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -144,6 +144,15 @@ declare abstract class Base {
|
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
declare const _createErrorMessage: (type: string, { property, meta }: RuleArgs) => string;
|
|
147
|
-
|
|
147
|
+
interface ExtractedRule {
|
|
148
|
+
property: string;
|
|
149
|
+
designType: any;
|
|
150
|
+
mergedMeta: any;
|
|
151
|
+
validate: (value: any) => Promise<string | undefined>;
|
|
152
|
+
}
|
|
153
|
+
declare function extractRules(model: Construct, createErrMsg?: (type: string, { property, meta }: RuleArgs) => string, equalFn?: (a: any, b: any) => boolean, parentPath?: string): ExtractedRule[];
|
|
154
|
+
declare function extractDataByRules(data: any, rules: ExtractedRule[]): any;
|
|
155
|
+
declare function validateWithRules(data: any, rules: ExtractedRule[], collectErrors?: boolean): Promise<string[]>;
|
|
156
|
+
declare function validate(model: Construct, data: any, collectErrors?: boolean, createErrMsg?: (type: string, { property, meta }: RuleArgs) => string, equalFn?: (a: any, b: any) => boolean): Promise<string[]>;
|
|
148
157
|
|
|
149
|
-
export { type AbConstruct, Assign, Base, CLEAR_KEY, type ClassValue, Clear, Const, type Construct, DataMap, Doc, Effect, Empty, Enum, Err, type Events, Expose, Global, If, Init, Inject, type InjectData, Injectable, Isolate, Max, Min, type NameSpace, Nested, OneOf, Optional, PHECDA_KEY, type Phecda, Pipeline, Provide, Required, Rule, type RuleArgs, SHARE_KEY, Storage, type StorageParam, Tag, Unique, Unmount, Watcher, type WatcherParam, _createErrorMessage, activeInstance, addDecoToClass, functionToClass, get, getInject, getMergedMeta, getMeta, getMetaKey, getMetaParams, getOwnMeta, getOwnMetaKey, getOwnMetaParams, getPhecdaFromTarget, getTag, init, invoke, invokeInit, invokeUnmount, isAsyncFunc, isPhecda, objectToClass, omit, override, partial, pick, set, setInject, setMeta, validate, wait };
|
|
158
|
+
export { type AbConstruct, Assign, Base, CLEAR_KEY, type ClassValue, Clear, Const, type Construct, DataMap, Doc, Effect, Empty, Enum, Err, type Events, Expose, type ExtractedRule, Global, If, Init, Inject, type InjectData, Injectable, Isolate, Max, Min, type NameSpace, Nested, OneOf, Optional, PHECDA_KEY, type Phecda, Pipeline, Provide, Required, Rule, type RuleArgs, SHARE_KEY, Storage, type StorageParam, Tag, Unique, Unmount, Watcher, type WatcherParam, _createErrorMessage, activeInstance, addDecoToClass, extractDataByRules, extractRules, functionToClass, get, getInject, getMergedMeta, getMeta, getMetaKey, getMetaParams, getOwnMeta, getOwnMetaKey, getOwnMetaParams, getPhecdaFromTarget, getTag, init, invoke, invokeInit, invokeUnmount, isAsyncFunc, isPhecda, objectToClass, omit, override, partial, pick, set, setInject, setMeta, validate, validateWithRules, wait };
|
package/dist/index.d.ts
CHANGED
|
@@ -144,6 +144,15 @@ declare abstract class Base {
|
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
declare const _createErrorMessage: (type: string, { property, meta }: RuleArgs) => string;
|
|
147
|
-
|
|
147
|
+
interface ExtractedRule {
|
|
148
|
+
property: string;
|
|
149
|
+
designType: any;
|
|
150
|
+
mergedMeta: any;
|
|
151
|
+
validate: (value: any) => Promise<string | undefined>;
|
|
152
|
+
}
|
|
153
|
+
declare function extractRules(model: Construct, createErrMsg?: (type: string, { property, meta }: RuleArgs) => string, equalFn?: (a: any, b: any) => boolean, parentPath?: string): ExtractedRule[];
|
|
154
|
+
declare function extractDataByRules(data: any, rules: ExtractedRule[]): any;
|
|
155
|
+
declare function validateWithRules(data: any, rules: ExtractedRule[], collectErrors?: boolean): Promise<string[]>;
|
|
156
|
+
declare function validate(model: Construct, data: any, collectErrors?: boolean, createErrMsg?: (type: string, { property, meta }: RuleArgs) => string, equalFn?: (a: any, b: any) => boolean): Promise<string[]>;
|
|
148
157
|
|
|
149
|
-
export { type AbConstruct, Assign, Base, CLEAR_KEY, type ClassValue, Clear, Const, type Construct, DataMap, Doc, Effect, Empty, Enum, Err, type Events, Expose, Global, If, Init, Inject, type InjectData, Injectable, Isolate, Max, Min, type NameSpace, Nested, OneOf, Optional, PHECDA_KEY, type Phecda, Pipeline, Provide, Required, Rule, type RuleArgs, SHARE_KEY, Storage, type StorageParam, Tag, Unique, Unmount, Watcher, type WatcherParam, _createErrorMessage, activeInstance, addDecoToClass, functionToClass, get, getInject, getMergedMeta, getMeta, getMetaKey, getMetaParams, getOwnMeta, getOwnMetaKey, getOwnMetaParams, getPhecdaFromTarget, getTag, init, invoke, invokeInit, invokeUnmount, isAsyncFunc, isPhecda, objectToClass, omit, override, partial, pick, set, setInject, setMeta, validate, wait };
|
|
158
|
+
export { type AbConstruct, Assign, Base, CLEAR_KEY, type ClassValue, Clear, Const, type Construct, DataMap, Doc, Effect, Empty, Enum, Err, type Events, Expose, type ExtractedRule, Global, If, Init, Inject, type InjectData, Injectable, Isolate, Max, Min, type NameSpace, Nested, OneOf, Optional, PHECDA_KEY, type Phecda, Pipeline, Provide, Required, Rule, type RuleArgs, SHARE_KEY, Storage, type StorageParam, Tag, Unique, Unmount, Watcher, type WatcherParam, _createErrorMessage, activeInstance, addDecoToClass, extractDataByRules, extractRules, functionToClass, get, getInject, getMergedMeta, getMeta, getMetaKey, getMetaParams, getOwnMeta, getOwnMetaKey, getOwnMetaParams, getPhecdaFromTarget, getTag, init, invoke, invokeInit, invokeUnmount, isAsyncFunc, isPhecda, objectToClass, omit, override, partial, pick, set, setInject, setMeta, validate, validateWithRules, wait };
|
package/dist/index.js
CHANGED
|
@@ -59,6 +59,8 @@ __export(index_exports, {
|
|
|
59
59
|
_createErrorMessage: () => _createErrorMessage,
|
|
60
60
|
activeInstance: () => activeInstance,
|
|
61
61
|
addDecoToClass: () => addDecoToClass,
|
|
62
|
+
extractDataByRules: () => extractDataByRules,
|
|
63
|
+
extractRules: () => extractRules,
|
|
62
64
|
functionToClass: () => functionToClass,
|
|
63
65
|
get: () => get,
|
|
64
66
|
getInject: () => getInject,
|
|
@@ -86,6 +88,7 @@ __export(index_exports, {
|
|
|
86
88
|
setInject: () => setInject,
|
|
87
89
|
setMeta: () => setMeta,
|
|
88
90
|
validate: () => validate,
|
|
91
|
+
validateWithRules: () => validateWithRules,
|
|
89
92
|
wait: () => wait
|
|
90
93
|
});
|
|
91
94
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -288,23 +291,21 @@ function isAsyncFunc(fn) {
|
|
|
288
291
|
__name(isAsyncFunc, "isAsyncFunc");
|
|
289
292
|
function invoke(instance, key, ...params) {
|
|
290
293
|
const metaKeys = getMetaKey(instance);
|
|
291
|
-
const names = [];
|
|
292
294
|
return Promise.allSettled(metaKeys.map((k) => {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
295
|
+
const names = [];
|
|
296
|
+
const meta = getMeta(instance, k);
|
|
297
|
+
return meta.filter((item) => {
|
|
296
298
|
if (item.__NAME__) {
|
|
297
|
-
if (names.includes(item.__NAME__))
|
|
298
|
-
return false;
|
|
299
|
-
}
|
|
299
|
+
if (names.includes(item.__NAME__)) return false;
|
|
300
300
|
names.push(item.__NAME__);
|
|
301
301
|
return true;
|
|
302
302
|
} else {
|
|
303
303
|
return true;
|
|
304
304
|
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
|
|
305
|
+
});
|
|
306
|
+
}).flat().filter((item) => {
|
|
307
|
+
if (typeof item[key] === "function") return true;
|
|
308
|
+
else return false;
|
|
308
309
|
}).map((item) => item[key](instance, ...params))).then((res) => {
|
|
309
310
|
res.filter((item) => item.status === "rejected").forEach((item) => {
|
|
310
311
|
console.error(item.reason);
|
|
@@ -752,6 +753,70 @@ Base = _ts_decorate([
|
|
|
752
753
|
], Base);
|
|
753
754
|
|
|
754
755
|
// src/validate.ts
|
|
756
|
+
function parsePath(path) {
|
|
757
|
+
if (!path) return [];
|
|
758
|
+
return path.split(".").flatMap((token) => {
|
|
759
|
+
if (!token) return [];
|
|
760
|
+
if (token.endsWith("[]")) return [
|
|
761
|
+
token.slice(0, -2),
|
|
762
|
+
"[]"
|
|
763
|
+
];
|
|
764
|
+
return [
|
|
765
|
+
token
|
|
766
|
+
];
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
__name(parsePath, "parsePath");
|
|
770
|
+
function collectConcretePathsByTokens(data, tokens) {
|
|
771
|
+
if (!tokens.length) return [
|
|
772
|
+
{
|
|
773
|
+
keys: [],
|
|
774
|
+
value: data
|
|
775
|
+
}
|
|
776
|
+
];
|
|
777
|
+
const walk = /* @__PURE__ */ __name((node, tokenIndex, keys) => {
|
|
778
|
+
if (tokenIndex >= tokens.length) return [
|
|
779
|
+
{
|
|
780
|
+
keys,
|
|
781
|
+
value: node
|
|
782
|
+
}
|
|
783
|
+
];
|
|
784
|
+
const token = tokens[tokenIndex];
|
|
785
|
+
if (token === "[]") {
|
|
786
|
+
if (!Array.isArray(node)) return [];
|
|
787
|
+
return node.flatMap((item, idx) => walk(item, tokenIndex + 1, [
|
|
788
|
+
...keys,
|
|
789
|
+
idx
|
|
790
|
+
]));
|
|
791
|
+
}
|
|
792
|
+
if (node === null || node === void 0) return [];
|
|
793
|
+
const nodeType = typeof node;
|
|
794
|
+
if (nodeType !== "object" && nodeType !== "function") return [];
|
|
795
|
+
return walk(node[token], tokenIndex + 1, [
|
|
796
|
+
...keys,
|
|
797
|
+
token
|
|
798
|
+
]);
|
|
799
|
+
}, "walk");
|
|
800
|
+
return walk(data, 0, []);
|
|
801
|
+
}
|
|
802
|
+
__name(collectConcretePathsByTokens, "collectConcretePathsByTokens");
|
|
803
|
+
function setByConcreteKeys(target, keys, value) {
|
|
804
|
+
if (!keys.length) return value;
|
|
805
|
+
let node = target;
|
|
806
|
+
for (let i = 0; i < keys.length; i++) {
|
|
807
|
+
const key = keys[i];
|
|
808
|
+
const isLast = i === keys.length - 1;
|
|
809
|
+
if (isLast) {
|
|
810
|
+
node[key] = value;
|
|
811
|
+
break;
|
|
812
|
+
}
|
|
813
|
+
const nextKey = keys[i + 1];
|
|
814
|
+
if (node[key] === void 0) node[key] = typeof nextKey === "number" ? [] : {};
|
|
815
|
+
node = node[key];
|
|
816
|
+
}
|
|
817
|
+
return target;
|
|
818
|
+
}
|
|
819
|
+
__name(setByConcreteKeys, "setByConcreteKeys");
|
|
755
820
|
var _createErrorMessage = /* @__PURE__ */ __name((type, { property, meta }) => {
|
|
756
821
|
switch (type) {
|
|
757
822
|
case "const":
|
|
@@ -789,128 +854,197 @@ function isObject(value) {
|
|
|
789
854
|
return Object.prototype.toString.call(value) === "[object Object]";
|
|
790
855
|
}
|
|
791
856
|
__name(isObject, "isObject");
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
const
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
if (
|
|
818
|
-
if (
|
|
819
|
-
|
|
820
|
-
if (
|
|
821
|
-
if (nested
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
if (
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
break;
|
|
857
|
+
function extractRules(model, createErrMsg = _createErrorMessage, equalFn = (a, b) => a === b, parentPath = "") {
|
|
858
|
+
const mergedRuleMap = /* @__PURE__ */ new Map();
|
|
859
|
+
const collect = /* @__PURE__ */ __name((currentModel, currentPath) => {
|
|
860
|
+
for (const key of getMetaKey(currentModel)) {
|
|
861
|
+
const mergedMeta = getMergedMeta(currentModel, key);
|
|
862
|
+
const baseProperty = key === SHARE_KEY ? "" : key;
|
|
863
|
+
const property = baseProperty && currentPath ? `${currentPath}.${baseProperty}` : baseProperty || currentPath;
|
|
864
|
+
const designType = baseProperty === "" ? currentModel : Reflect.getMetadata("design:type", currentModel.prototype, key);
|
|
865
|
+
const ruleRunner = /* @__PURE__ */ __name(async (value) => {
|
|
866
|
+
const { rules = [], nested, oneOf, min, max, enum: enumMap, required } = mergedMeta;
|
|
867
|
+
const args = {
|
|
868
|
+
value,
|
|
869
|
+
property,
|
|
870
|
+
meta: mergedMeta,
|
|
871
|
+
model: currentModel
|
|
872
|
+
};
|
|
873
|
+
const allRules = [
|
|
874
|
+
async (localArgs) => {
|
|
875
|
+
const { value: value2 } = localArgs;
|
|
876
|
+
if ("const" in mergedMeta) {
|
|
877
|
+
if (!equalFn(value2, mergedMeta.const)) return createErrMsg("const", localArgs);
|
|
878
|
+
}
|
|
879
|
+
if (required === false && value2 === void 0) return true;
|
|
880
|
+
if (required !== false && value2 === void 0) return createErrMsg("required", localArgs);
|
|
881
|
+
if (designType === String && typeof value2 !== "string") return createErrMsg("string", localArgs);
|
|
882
|
+
if (designType === Number && typeof value2 !== "number") return createErrMsg("number", localArgs);
|
|
883
|
+
if (designType === Boolean && typeof value2 !== "boolean") return createErrMsg("boolean", localArgs);
|
|
884
|
+
if (designType === Array) {
|
|
885
|
+
if (!Array.isArray(value2)) return createErrMsg("array", localArgs);
|
|
886
|
+
if (!nested) return;
|
|
887
|
+
for (const i in value2) {
|
|
888
|
+
if (nested === String && typeof value2[i] !== "string") return createErrMsg("stringArray", localArgs);
|
|
889
|
+
if (nested === Number && typeof value2[i] !== "number") return createErrMsg("numberArray", localArgs);
|
|
890
|
+
if (nested === Boolean && typeof value2[i] !== "boolean") return createErrMsg("booleanArray", localArgs);
|
|
891
|
+
if (isPhecda(nested)) {
|
|
892
|
+
if (!isObject(value2[i])) return createErrMsg("object", {
|
|
893
|
+
...localArgs,
|
|
894
|
+
arrayIndex: i
|
|
895
|
+
});
|
|
832
896
|
}
|
|
833
897
|
}
|
|
898
|
+
} else if (nested && isPhecda(nested)) {
|
|
899
|
+
if (!isObject(value2)) return createErrMsg("object", localArgs);
|
|
834
900
|
}
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
if (
|
|
838
|
-
|
|
839
|
-
if (errs.length) errors.push(errs[0]);
|
|
901
|
+
if (min) {
|
|
902
|
+
if (typeof value2 === "number" && value2 < min) return createErrMsg("min", localArgs);
|
|
903
|
+
if (typeof value2 === "string" && value2.length < min) return createErrMsg("min", localArgs);
|
|
904
|
+
if (Array.isArray(value2) && value2.length < min) return createErrMsg("min", localArgs);
|
|
840
905
|
}
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
if (
|
|
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
|
-
const ret = await item(args2);
|
|
877
|
-
if (ret) {
|
|
878
|
-
isCorrect = true;
|
|
879
|
-
break;
|
|
880
|
-
}
|
|
881
|
-
} else {
|
|
882
|
-
if (equalFn(value2, item)) {
|
|
906
|
+
if (max) {
|
|
907
|
+
if (typeof value2 === "number" && value2 > max) return createErrMsg("max", localArgs);
|
|
908
|
+
if (typeof value2 === "string" && value2.length > max) return createErrMsg("max", localArgs);
|
|
909
|
+
if (Array.isArray(value2) && value2.length > max) return createErrMsg("max", localArgs);
|
|
910
|
+
}
|
|
911
|
+
if (enumMap) {
|
|
912
|
+
if (!Object.values(enumMap).includes(value2)) return createErrMsg("enum", localArgs);
|
|
913
|
+
}
|
|
914
|
+
if (oneOf) {
|
|
915
|
+
let isCorrect = false;
|
|
916
|
+
for (const item of oneOf) {
|
|
917
|
+
switch (item) {
|
|
918
|
+
case String:
|
|
919
|
+
if (typeof value2 === "string") isCorrect = true;
|
|
920
|
+
break;
|
|
921
|
+
case Number:
|
|
922
|
+
if (typeof value2 === "number") isCorrect = true;
|
|
923
|
+
break;
|
|
924
|
+
case Boolean:
|
|
925
|
+
if (typeof value2 === "boolean") isCorrect = true;
|
|
926
|
+
break;
|
|
927
|
+
default:
|
|
928
|
+
if (isPhecda(item)) {
|
|
929
|
+
const errs = await validate(item, value2);
|
|
930
|
+
if (!errs.length) {
|
|
931
|
+
isCorrect = true;
|
|
932
|
+
break;
|
|
933
|
+
}
|
|
934
|
+
} else if (typeof item === "function") {
|
|
935
|
+
const ret = await item(localArgs);
|
|
936
|
+
if (ret) {
|
|
937
|
+
isCorrect = true;
|
|
938
|
+
break;
|
|
939
|
+
}
|
|
940
|
+
} else if (equalFn(value2, item)) {
|
|
883
941
|
isCorrect = true;
|
|
884
942
|
break;
|
|
885
943
|
}
|
|
886
|
-
|
|
944
|
+
}
|
|
887
945
|
}
|
|
946
|
+
if (!isCorrect) return createErrMsg("oneOf", localArgs);
|
|
888
947
|
}
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
property,
|
|
897
|
-
meta,
|
|
898
|
-
model: model2
|
|
899
|
-
};
|
|
900
|
-
for (const rule of allRules) {
|
|
901
|
-
const errMsg = await rule(args);
|
|
902
|
-
if (errMsg === true) break;
|
|
903
|
-
if (errMsg) {
|
|
904
|
-
errors.push(errMsg);
|
|
905
|
-
break;
|
|
948
|
+
},
|
|
949
|
+
...rules
|
|
950
|
+
];
|
|
951
|
+
for (const rule of allRules) {
|
|
952
|
+
const errMsg = await rule(args);
|
|
953
|
+
if (errMsg === true) return;
|
|
954
|
+
if (errMsg) return errMsg;
|
|
906
955
|
}
|
|
956
|
+
}, "ruleRunner");
|
|
957
|
+
const current = mergedRuleMap.get(property);
|
|
958
|
+
if (!current) {
|
|
959
|
+
mergedRuleMap.set(property, {
|
|
960
|
+
property,
|
|
961
|
+
designType,
|
|
962
|
+
mergedMeta,
|
|
963
|
+
validators: [
|
|
964
|
+
ruleRunner
|
|
965
|
+
]
|
|
966
|
+
});
|
|
967
|
+
} else {
|
|
968
|
+
current.validators.push(ruleRunner);
|
|
969
|
+
}
|
|
970
|
+
if (mergedMeta.nested && isPhecda(mergedMeta.nested)) {
|
|
971
|
+
const nestedPath = designType === Array ? `${property}[]` : property;
|
|
972
|
+
collect(mergedMeta.nested, nestedPath);
|
|
907
973
|
}
|
|
908
|
-
if (errors.length !== 0 && !collectErrors) break;
|
|
909
974
|
}
|
|
975
|
+
}, "collect");
|
|
976
|
+
collect(model, parentPath);
|
|
977
|
+
return [
|
|
978
|
+
...mergedRuleMap.values()
|
|
979
|
+
].map((item) => ({
|
|
980
|
+
property: item.property,
|
|
981
|
+
designType: item.designType,
|
|
982
|
+
mergedMeta: item.mergedMeta,
|
|
983
|
+
validate: /* @__PURE__ */ __name(async (value) => {
|
|
984
|
+
for (const validator of item.validators) {
|
|
985
|
+
const err = await validator(value);
|
|
986
|
+
if (err) return err;
|
|
987
|
+
}
|
|
988
|
+
}, "validate")
|
|
989
|
+
}));
|
|
990
|
+
}
|
|
991
|
+
__name(extractRules, "extractRules");
|
|
992
|
+
function extractDataByRules(data, rules) {
|
|
993
|
+
let transformed = {};
|
|
994
|
+
const projectContainerOnly = /* @__PURE__ */ __name((value, rule) => {
|
|
995
|
+
const nested = rule.mergedMeta?.nested;
|
|
996
|
+
if (!nested || !isPhecda(nested)) return value;
|
|
997
|
+
if (rule.designType === Array) return Array.isArray(value) ? [] : value;
|
|
998
|
+
return isObject(value) ? {} : value;
|
|
999
|
+
}, "projectContainerOnly");
|
|
1000
|
+
for (const rule of rules) {
|
|
1001
|
+
if (!rule.property) continue;
|
|
1002
|
+
const tokens = parsePath(rule.property);
|
|
1003
|
+
const concreteValues = collectConcretePathsByTokens(data, tokens);
|
|
1004
|
+
for (const concrete of concreteValues) {
|
|
1005
|
+
const projectedValue = projectContainerOnly(concrete.value, rule);
|
|
1006
|
+
transformed = setByConcreteKeys(transformed, concrete.keys, projectedValue);
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
return transformed;
|
|
1010
|
+
}
|
|
1011
|
+
__name(extractDataByRules, "extractDataByRules");
|
|
1012
|
+
async function validateWithRules(data, rules, collectErrors = false) {
|
|
1013
|
+
const errors = [];
|
|
1014
|
+
for (const rule of rules) {
|
|
1015
|
+
if (!rule.property) {
|
|
1016
|
+
const err = await rule.validate(data);
|
|
1017
|
+
if (err) {
|
|
1018
|
+
errors.push(err);
|
|
1019
|
+
if (!collectErrors) break;
|
|
1020
|
+
}
|
|
1021
|
+
continue;
|
|
1022
|
+
}
|
|
1023
|
+
const tokens = parsePath(rule.property);
|
|
1024
|
+
const values = collectConcretePathsByTokens(data, tokens).map((v) => v.value);
|
|
1025
|
+
const targetValues = values.length ? values : tokens.length === 1 ? [
|
|
1026
|
+
void 0
|
|
1027
|
+
] : [];
|
|
1028
|
+
for (const value of targetValues) {
|
|
1029
|
+
const err = await rule.validate(value);
|
|
1030
|
+
if (err) {
|
|
1031
|
+
errors.push(err);
|
|
1032
|
+
break;
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
if (errors.length && !collectErrors) break;
|
|
1036
|
+
}
|
|
1037
|
+
return errors;
|
|
1038
|
+
}
|
|
1039
|
+
__name(validateWithRules, "validateWithRules");
|
|
1040
|
+
async function validate(model, data, collectErrors = false, createErrMsg = _createErrorMessage, equalFn = (a, b) => a === b) {
|
|
1041
|
+
const errors = [];
|
|
1042
|
+
if (!isObject(data)) {
|
|
1043
|
+
errors.push("data must be an object");
|
|
910
1044
|
return errors;
|
|
911
1045
|
}
|
|
912
|
-
|
|
913
|
-
return await
|
|
1046
|
+
const rules = extractRules(model, createErrMsg, equalFn);
|
|
1047
|
+
return await validateWithRules(data, rules, collectErrors);
|
|
914
1048
|
}
|
|
915
1049
|
__name(validate, "validate");
|
|
916
1050
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -952,6 +1086,8 @@ __name(validate, "validate");
|
|
|
952
1086
|
_createErrorMessage,
|
|
953
1087
|
activeInstance,
|
|
954
1088
|
addDecoToClass,
|
|
1089
|
+
extractDataByRules,
|
|
1090
|
+
extractRules,
|
|
955
1091
|
functionToClass,
|
|
956
1092
|
get,
|
|
957
1093
|
getInject,
|
|
@@ -979,6 +1115,7 @@ __name(validate, "validate");
|
|
|
979
1115
|
setInject,
|
|
980
1116
|
setMeta,
|
|
981
1117
|
validate,
|
|
1118
|
+
validateWithRules,
|
|
982
1119
|
wait,
|
|
983
1120
|
...require("reflect-metadata")
|
|
984
1121
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -201,23 +201,21 @@ function isAsyncFunc(fn) {
|
|
|
201
201
|
__name(isAsyncFunc, "isAsyncFunc");
|
|
202
202
|
function invoke(instance, key, ...params) {
|
|
203
203
|
const metaKeys = getMetaKey(instance);
|
|
204
|
-
const names = [];
|
|
205
204
|
return Promise.allSettled(metaKeys.map((k) => {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
205
|
+
const names = [];
|
|
206
|
+
const meta = getMeta(instance, k);
|
|
207
|
+
return meta.filter((item) => {
|
|
209
208
|
if (item.__NAME__) {
|
|
210
|
-
if (names.includes(item.__NAME__))
|
|
211
|
-
return false;
|
|
212
|
-
}
|
|
209
|
+
if (names.includes(item.__NAME__)) return false;
|
|
213
210
|
names.push(item.__NAME__);
|
|
214
211
|
return true;
|
|
215
212
|
} else {
|
|
216
213
|
return true;
|
|
217
214
|
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
|
|
215
|
+
});
|
|
216
|
+
}).flat().filter((item) => {
|
|
217
|
+
if (typeof item[key] === "function") return true;
|
|
218
|
+
else return false;
|
|
221
219
|
}).map((item) => item[key](instance, ...params))).then((res) => {
|
|
222
220
|
res.filter((item) => item.status === "rejected").forEach((item) => {
|
|
223
221
|
console.error(item.reason);
|
|
@@ -665,6 +663,70 @@ Base = _ts_decorate([
|
|
|
665
663
|
], Base);
|
|
666
664
|
|
|
667
665
|
// src/validate.ts
|
|
666
|
+
function parsePath(path) {
|
|
667
|
+
if (!path) return [];
|
|
668
|
+
return path.split(".").flatMap((token) => {
|
|
669
|
+
if (!token) return [];
|
|
670
|
+
if (token.endsWith("[]")) return [
|
|
671
|
+
token.slice(0, -2),
|
|
672
|
+
"[]"
|
|
673
|
+
];
|
|
674
|
+
return [
|
|
675
|
+
token
|
|
676
|
+
];
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
__name(parsePath, "parsePath");
|
|
680
|
+
function collectConcretePathsByTokens(data, tokens) {
|
|
681
|
+
if (!tokens.length) return [
|
|
682
|
+
{
|
|
683
|
+
keys: [],
|
|
684
|
+
value: data
|
|
685
|
+
}
|
|
686
|
+
];
|
|
687
|
+
const walk = /* @__PURE__ */ __name((node, tokenIndex, keys) => {
|
|
688
|
+
if (tokenIndex >= tokens.length) return [
|
|
689
|
+
{
|
|
690
|
+
keys,
|
|
691
|
+
value: node
|
|
692
|
+
}
|
|
693
|
+
];
|
|
694
|
+
const token = tokens[tokenIndex];
|
|
695
|
+
if (token === "[]") {
|
|
696
|
+
if (!Array.isArray(node)) return [];
|
|
697
|
+
return node.flatMap((item, idx) => walk(item, tokenIndex + 1, [
|
|
698
|
+
...keys,
|
|
699
|
+
idx
|
|
700
|
+
]));
|
|
701
|
+
}
|
|
702
|
+
if (node === null || node === void 0) return [];
|
|
703
|
+
const nodeType = typeof node;
|
|
704
|
+
if (nodeType !== "object" && nodeType !== "function") return [];
|
|
705
|
+
return walk(node[token], tokenIndex + 1, [
|
|
706
|
+
...keys,
|
|
707
|
+
token
|
|
708
|
+
]);
|
|
709
|
+
}, "walk");
|
|
710
|
+
return walk(data, 0, []);
|
|
711
|
+
}
|
|
712
|
+
__name(collectConcretePathsByTokens, "collectConcretePathsByTokens");
|
|
713
|
+
function setByConcreteKeys(target, keys, value) {
|
|
714
|
+
if (!keys.length) return value;
|
|
715
|
+
let node = target;
|
|
716
|
+
for (let i = 0; i < keys.length; i++) {
|
|
717
|
+
const key = keys[i];
|
|
718
|
+
const isLast = i === keys.length - 1;
|
|
719
|
+
if (isLast) {
|
|
720
|
+
node[key] = value;
|
|
721
|
+
break;
|
|
722
|
+
}
|
|
723
|
+
const nextKey = keys[i + 1];
|
|
724
|
+
if (node[key] === void 0) node[key] = typeof nextKey === "number" ? [] : {};
|
|
725
|
+
node = node[key];
|
|
726
|
+
}
|
|
727
|
+
return target;
|
|
728
|
+
}
|
|
729
|
+
__name(setByConcreteKeys, "setByConcreteKeys");
|
|
668
730
|
var _createErrorMessage = /* @__PURE__ */ __name((type, { property, meta }) => {
|
|
669
731
|
switch (type) {
|
|
670
732
|
case "const":
|
|
@@ -702,128 +764,197 @@ function isObject(value) {
|
|
|
702
764
|
return Object.prototype.toString.call(value) === "[object Object]";
|
|
703
765
|
}
|
|
704
766
|
__name(isObject, "isObject");
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
const
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
if (
|
|
731
|
-
if (
|
|
732
|
-
|
|
733
|
-
if (
|
|
734
|
-
if (nested
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
if (
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
break;
|
|
767
|
+
function extractRules(model, createErrMsg = _createErrorMessage, equalFn = (a, b) => a === b, parentPath = "") {
|
|
768
|
+
const mergedRuleMap = /* @__PURE__ */ new Map();
|
|
769
|
+
const collect = /* @__PURE__ */ __name((currentModel, currentPath) => {
|
|
770
|
+
for (const key of getMetaKey(currentModel)) {
|
|
771
|
+
const mergedMeta = getMergedMeta(currentModel, key);
|
|
772
|
+
const baseProperty = key === SHARE_KEY ? "" : key;
|
|
773
|
+
const property = baseProperty && currentPath ? `${currentPath}.${baseProperty}` : baseProperty || currentPath;
|
|
774
|
+
const designType = baseProperty === "" ? currentModel : Reflect.getMetadata("design:type", currentModel.prototype, key);
|
|
775
|
+
const ruleRunner = /* @__PURE__ */ __name(async (value) => {
|
|
776
|
+
const { rules = [], nested, oneOf, min, max, enum: enumMap, required } = mergedMeta;
|
|
777
|
+
const args = {
|
|
778
|
+
value,
|
|
779
|
+
property,
|
|
780
|
+
meta: mergedMeta,
|
|
781
|
+
model: currentModel
|
|
782
|
+
};
|
|
783
|
+
const allRules = [
|
|
784
|
+
async (localArgs) => {
|
|
785
|
+
const { value: value2 } = localArgs;
|
|
786
|
+
if ("const" in mergedMeta) {
|
|
787
|
+
if (!equalFn(value2, mergedMeta.const)) return createErrMsg("const", localArgs);
|
|
788
|
+
}
|
|
789
|
+
if (required === false && value2 === void 0) return true;
|
|
790
|
+
if (required !== false && value2 === void 0) return createErrMsg("required", localArgs);
|
|
791
|
+
if (designType === String && typeof value2 !== "string") return createErrMsg("string", localArgs);
|
|
792
|
+
if (designType === Number && typeof value2 !== "number") return createErrMsg("number", localArgs);
|
|
793
|
+
if (designType === Boolean && typeof value2 !== "boolean") return createErrMsg("boolean", localArgs);
|
|
794
|
+
if (designType === Array) {
|
|
795
|
+
if (!Array.isArray(value2)) return createErrMsg("array", localArgs);
|
|
796
|
+
if (!nested) return;
|
|
797
|
+
for (const i in value2) {
|
|
798
|
+
if (nested === String && typeof value2[i] !== "string") return createErrMsg("stringArray", localArgs);
|
|
799
|
+
if (nested === Number && typeof value2[i] !== "number") return createErrMsg("numberArray", localArgs);
|
|
800
|
+
if (nested === Boolean && typeof value2[i] !== "boolean") return createErrMsg("booleanArray", localArgs);
|
|
801
|
+
if (isPhecda(nested)) {
|
|
802
|
+
if (!isObject(value2[i])) return createErrMsg("object", {
|
|
803
|
+
...localArgs,
|
|
804
|
+
arrayIndex: i
|
|
805
|
+
});
|
|
745
806
|
}
|
|
746
807
|
}
|
|
808
|
+
} else if (nested && isPhecda(nested)) {
|
|
809
|
+
if (!isObject(value2)) return createErrMsg("object", localArgs);
|
|
747
810
|
}
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
if (
|
|
751
|
-
|
|
752
|
-
if (errs.length) errors.push(errs[0]);
|
|
811
|
+
if (min) {
|
|
812
|
+
if (typeof value2 === "number" && value2 < min) return createErrMsg("min", localArgs);
|
|
813
|
+
if (typeof value2 === "string" && value2.length < min) return createErrMsg("min", localArgs);
|
|
814
|
+
if (Array.isArray(value2) && value2.length < min) return createErrMsg("min", localArgs);
|
|
753
815
|
}
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
if (
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
const ret = await item(args2);
|
|
790
|
-
if (ret) {
|
|
791
|
-
isCorrect = true;
|
|
792
|
-
break;
|
|
793
|
-
}
|
|
794
|
-
} else {
|
|
795
|
-
if (equalFn(value2, item)) {
|
|
816
|
+
if (max) {
|
|
817
|
+
if (typeof value2 === "number" && value2 > max) return createErrMsg("max", localArgs);
|
|
818
|
+
if (typeof value2 === "string" && value2.length > max) return createErrMsg("max", localArgs);
|
|
819
|
+
if (Array.isArray(value2) && value2.length > max) return createErrMsg("max", localArgs);
|
|
820
|
+
}
|
|
821
|
+
if (enumMap) {
|
|
822
|
+
if (!Object.values(enumMap).includes(value2)) return createErrMsg("enum", localArgs);
|
|
823
|
+
}
|
|
824
|
+
if (oneOf) {
|
|
825
|
+
let isCorrect = false;
|
|
826
|
+
for (const item of oneOf) {
|
|
827
|
+
switch (item) {
|
|
828
|
+
case String:
|
|
829
|
+
if (typeof value2 === "string") isCorrect = true;
|
|
830
|
+
break;
|
|
831
|
+
case Number:
|
|
832
|
+
if (typeof value2 === "number") isCorrect = true;
|
|
833
|
+
break;
|
|
834
|
+
case Boolean:
|
|
835
|
+
if (typeof value2 === "boolean") isCorrect = true;
|
|
836
|
+
break;
|
|
837
|
+
default:
|
|
838
|
+
if (isPhecda(item)) {
|
|
839
|
+
const errs = await validate(item, value2);
|
|
840
|
+
if (!errs.length) {
|
|
841
|
+
isCorrect = true;
|
|
842
|
+
break;
|
|
843
|
+
}
|
|
844
|
+
} else if (typeof item === "function") {
|
|
845
|
+
const ret = await item(localArgs);
|
|
846
|
+
if (ret) {
|
|
847
|
+
isCorrect = true;
|
|
848
|
+
break;
|
|
849
|
+
}
|
|
850
|
+
} else if (equalFn(value2, item)) {
|
|
796
851
|
isCorrect = true;
|
|
797
852
|
break;
|
|
798
853
|
}
|
|
799
|
-
|
|
854
|
+
}
|
|
800
855
|
}
|
|
856
|
+
if (!isCorrect) return createErrMsg("oneOf", localArgs);
|
|
801
857
|
}
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
property,
|
|
810
|
-
meta,
|
|
811
|
-
model: model2
|
|
812
|
-
};
|
|
813
|
-
for (const rule of allRules) {
|
|
814
|
-
const errMsg = await rule(args);
|
|
815
|
-
if (errMsg === true) break;
|
|
816
|
-
if (errMsg) {
|
|
817
|
-
errors.push(errMsg);
|
|
818
|
-
break;
|
|
858
|
+
},
|
|
859
|
+
...rules
|
|
860
|
+
];
|
|
861
|
+
for (const rule of allRules) {
|
|
862
|
+
const errMsg = await rule(args);
|
|
863
|
+
if (errMsg === true) return;
|
|
864
|
+
if (errMsg) return errMsg;
|
|
819
865
|
}
|
|
866
|
+
}, "ruleRunner");
|
|
867
|
+
const current = mergedRuleMap.get(property);
|
|
868
|
+
if (!current) {
|
|
869
|
+
mergedRuleMap.set(property, {
|
|
870
|
+
property,
|
|
871
|
+
designType,
|
|
872
|
+
mergedMeta,
|
|
873
|
+
validators: [
|
|
874
|
+
ruleRunner
|
|
875
|
+
]
|
|
876
|
+
});
|
|
877
|
+
} else {
|
|
878
|
+
current.validators.push(ruleRunner);
|
|
879
|
+
}
|
|
880
|
+
if (mergedMeta.nested && isPhecda(mergedMeta.nested)) {
|
|
881
|
+
const nestedPath = designType === Array ? `${property}[]` : property;
|
|
882
|
+
collect(mergedMeta.nested, nestedPath);
|
|
820
883
|
}
|
|
821
|
-
if (errors.length !== 0 && !collectErrors) break;
|
|
822
884
|
}
|
|
885
|
+
}, "collect");
|
|
886
|
+
collect(model, parentPath);
|
|
887
|
+
return [
|
|
888
|
+
...mergedRuleMap.values()
|
|
889
|
+
].map((item) => ({
|
|
890
|
+
property: item.property,
|
|
891
|
+
designType: item.designType,
|
|
892
|
+
mergedMeta: item.mergedMeta,
|
|
893
|
+
validate: /* @__PURE__ */ __name(async (value) => {
|
|
894
|
+
for (const validator of item.validators) {
|
|
895
|
+
const err = await validator(value);
|
|
896
|
+
if (err) return err;
|
|
897
|
+
}
|
|
898
|
+
}, "validate")
|
|
899
|
+
}));
|
|
900
|
+
}
|
|
901
|
+
__name(extractRules, "extractRules");
|
|
902
|
+
function extractDataByRules(data, rules) {
|
|
903
|
+
let transformed = {};
|
|
904
|
+
const projectContainerOnly = /* @__PURE__ */ __name((value, rule) => {
|
|
905
|
+
const nested = rule.mergedMeta?.nested;
|
|
906
|
+
if (!nested || !isPhecda(nested)) return value;
|
|
907
|
+
if (rule.designType === Array) return Array.isArray(value) ? [] : value;
|
|
908
|
+
return isObject(value) ? {} : value;
|
|
909
|
+
}, "projectContainerOnly");
|
|
910
|
+
for (const rule of rules) {
|
|
911
|
+
if (!rule.property) continue;
|
|
912
|
+
const tokens = parsePath(rule.property);
|
|
913
|
+
const concreteValues = collectConcretePathsByTokens(data, tokens);
|
|
914
|
+
for (const concrete of concreteValues) {
|
|
915
|
+
const projectedValue = projectContainerOnly(concrete.value, rule);
|
|
916
|
+
transformed = setByConcreteKeys(transformed, concrete.keys, projectedValue);
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
return transformed;
|
|
920
|
+
}
|
|
921
|
+
__name(extractDataByRules, "extractDataByRules");
|
|
922
|
+
async function validateWithRules(data, rules, collectErrors = false) {
|
|
923
|
+
const errors = [];
|
|
924
|
+
for (const rule of rules) {
|
|
925
|
+
if (!rule.property) {
|
|
926
|
+
const err = await rule.validate(data);
|
|
927
|
+
if (err) {
|
|
928
|
+
errors.push(err);
|
|
929
|
+
if (!collectErrors) break;
|
|
930
|
+
}
|
|
931
|
+
continue;
|
|
932
|
+
}
|
|
933
|
+
const tokens = parsePath(rule.property);
|
|
934
|
+
const values = collectConcretePathsByTokens(data, tokens).map((v) => v.value);
|
|
935
|
+
const targetValues = values.length ? values : tokens.length === 1 ? [
|
|
936
|
+
void 0
|
|
937
|
+
] : [];
|
|
938
|
+
for (const value of targetValues) {
|
|
939
|
+
const err = await rule.validate(value);
|
|
940
|
+
if (err) {
|
|
941
|
+
errors.push(err);
|
|
942
|
+
break;
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
if (errors.length && !collectErrors) break;
|
|
946
|
+
}
|
|
947
|
+
return errors;
|
|
948
|
+
}
|
|
949
|
+
__name(validateWithRules, "validateWithRules");
|
|
950
|
+
async function validate(model, data, collectErrors = false, createErrMsg = _createErrorMessage, equalFn = (a, b) => a === b) {
|
|
951
|
+
const errors = [];
|
|
952
|
+
if (!isObject(data)) {
|
|
953
|
+
errors.push("data must be an object");
|
|
823
954
|
return errors;
|
|
824
955
|
}
|
|
825
|
-
|
|
826
|
-
return await
|
|
956
|
+
const rules = extractRules(model, createErrMsg, equalFn);
|
|
957
|
+
return await validateWithRules(data, rules, collectErrors);
|
|
827
958
|
}
|
|
828
959
|
__name(validate, "validate");
|
|
829
960
|
export {
|
|
@@ -864,6 +995,8 @@ export {
|
|
|
864
995
|
_createErrorMessage,
|
|
865
996
|
activeInstance,
|
|
866
997
|
addDecoToClass,
|
|
998
|
+
extractDataByRules,
|
|
999
|
+
extractRules,
|
|
867
1000
|
functionToClass,
|
|
868
1001
|
get,
|
|
869
1002
|
getInject,
|
|
@@ -891,5 +1024,6 @@ export {
|
|
|
891
1024
|
setInject,
|
|
892
1025
|
setMeta,
|
|
893
1026
|
validate,
|
|
1027
|
+
validateWithRules,
|
|
894
1028
|
wait
|
|
895
1029
|
};
|