phecda-core 5.2.1 → 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 +250 -116
- package/dist/index.mjs +247 -116
- 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);
|
|
@@ -293,9 +296,7 @@ function invoke(instance, key, ...params) {
|
|
|
293
296
|
const meta = getMeta(instance, k);
|
|
294
297
|
return meta.filter((item) => {
|
|
295
298
|
if (item.__NAME__) {
|
|
296
|
-
if (names.includes(item.__NAME__))
|
|
297
|
-
return false;
|
|
298
|
-
}
|
|
299
|
+
if (names.includes(item.__NAME__)) return false;
|
|
299
300
|
names.push(item.__NAME__);
|
|
300
301
|
return true;
|
|
301
302
|
} else {
|
|
@@ -303,11 +304,8 @@ function invoke(instance, key, ...params) {
|
|
|
303
304
|
}
|
|
304
305
|
});
|
|
305
306
|
}).flat().filter((item) => {
|
|
306
|
-
if (typeof item[key] === "function")
|
|
307
|
-
|
|
308
|
-
} else {
|
|
309
|
-
return false;
|
|
310
|
-
}
|
|
307
|
+
if (typeof item[key] === "function") return true;
|
|
308
|
+
else return false;
|
|
311
309
|
}).map((item) => item[key](instance, ...params))).then((res) => {
|
|
312
310
|
res.filter((item) => item.status === "rejected").forEach((item) => {
|
|
313
311
|
console.error(item.reason);
|
|
@@ -755,6 +753,70 @@ Base = _ts_decorate([
|
|
|
755
753
|
], Base);
|
|
756
754
|
|
|
757
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");
|
|
758
820
|
var _createErrorMessage = /* @__PURE__ */ __name((type, { property, meta }) => {
|
|
759
821
|
switch (type) {
|
|
760
822
|
case "const":
|
|
@@ -792,128 +854,197 @@ function isObject(value) {
|
|
|
792
854
|
return Object.prototype.toString.call(value) === "[object Object]";
|
|
793
855
|
}
|
|
794
856
|
__name(isObject, "isObject");
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
const
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
if (
|
|
821
|
-
if (
|
|
822
|
-
|
|
823
|
-
if (
|
|
824
|
-
if (nested
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
if (
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
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
|
+
});
|
|
835
896
|
}
|
|
836
897
|
}
|
|
898
|
+
} else if (nested && isPhecda(nested)) {
|
|
899
|
+
if (!isObject(value2)) return createErrMsg("object", localArgs);
|
|
837
900
|
}
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
if (
|
|
841
|
-
|
|
842
|
-
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);
|
|
843
905
|
}
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
if (
|
|
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
|
-
const ret = await item(args2);
|
|
880
|
-
if (ret) {
|
|
881
|
-
isCorrect = true;
|
|
882
|
-
break;
|
|
883
|
-
}
|
|
884
|
-
} else {
|
|
885
|
-
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)) {
|
|
886
941
|
isCorrect = true;
|
|
887
942
|
break;
|
|
888
943
|
}
|
|
889
|
-
|
|
944
|
+
}
|
|
890
945
|
}
|
|
946
|
+
if (!isCorrect) return createErrMsg("oneOf", localArgs);
|
|
891
947
|
}
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
property,
|
|
900
|
-
meta,
|
|
901
|
-
model: model2
|
|
902
|
-
};
|
|
903
|
-
for (const rule of allRules) {
|
|
904
|
-
const errMsg = await rule(args);
|
|
905
|
-
if (errMsg === true) break;
|
|
906
|
-
if (errMsg) {
|
|
907
|
-
errors.push(errMsg);
|
|
908
|
-
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;
|
|
909
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);
|
|
910
973
|
}
|
|
911
|
-
if (errors.length !== 0 && !collectErrors) break;
|
|
912
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");
|
|
913
1044
|
return errors;
|
|
914
1045
|
}
|
|
915
|
-
|
|
916
|
-
return await
|
|
1046
|
+
const rules = extractRules(model, createErrMsg, equalFn);
|
|
1047
|
+
return await validateWithRules(data, rules, collectErrors);
|
|
917
1048
|
}
|
|
918
1049
|
__name(validate, "validate");
|
|
919
1050
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -955,6 +1086,8 @@ __name(validate, "validate");
|
|
|
955
1086
|
_createErrorMessage,
|
|
956
1087
|
activeInstance,
|
|
957
1088
|
addDecoToClass,
|
|
1089
|
+
extractDataByRules,
|
|
1090
|
+
extractRules,
|
|
958
1091
|
functionToClass,
|
|
959
1092
|
get,
|
|
960
1093
|
getInject,
|
|
@@ -982,6 +1115,7 @@ __name(validate, "validate");
|
|
|
982
1115
|
setInject,
|
|
983
1116
|
setMeta,
|
|
984
1117
|
validate,
|
|
1118
|
+
validateWithRules,
|
|
985
1119
|
wait,
|
|
986
1120
|
...require("reflect-metadata")
|
|
987
1121
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -206,9 +206,7 @@ function invoke(instance, key, ...params) {
|
|
|
206
206
|
const meta = getMeta(instance, k);
|
|
207
207
|
return meta.filter((item) => {
|
|
208
208
|
if (item.__NAME__) {
|
|
209
|
-
if (names.includes(item.__NAME__))
|
|
210
|
-
return false;
|
|
211
|
-
}
|
|
209
|
+
if (names.includes(item.__NAME__)) return false;
|
|
212
210
|
names.push(item.__NAME__);
|
|
213
211
|
return true;
|
|
214
212
|
} else {
|
|
@@ -216,11 +214,8 @@ function invoke(instance, key, ...params) {
|
|
|
216
214
|
}
|
|
217
215
|
});
|
|
218
216
|
}).flat().filter((item) => {
|
|
219
|
-
if (typeof item[key] === "function")
|
|
220
|
-
|
|
221
|
-
} else {
|
|
222
|
-
return false;
|
|
223
|
-
}
|
|
217
|
+
if (typeof item[key] === "function") return true;
|
|
218
|
+
else return false;
|
|
224
219
|
}).map((item) => item[key](instance, ...params))).then((res) => {
|
|
225
220
|
res.filter((item) => item.status === "rejected").forEach((item) => {
|
|
226
221
|
console.error(item.reason);
|
|
@@ -668,6 +663,70 @@ Base = _ts_decorate([
|
|
|
668
663
|
], Base);
|
|
669
664
|
|
|
670
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");
|
|
671
730
|
var _createErrorMessage = /* @__PURE__ */ __name((type, { property, meta }) => {
|
|
672
731
|
switch (type) {
|
|
673
732
|
case "const":
|
|
@@ -705,128 +764,197 @@ function isObject(value) {
|
|
|
705
764
|
return Object.prototype.toString.call(value) === "[object Object]";
|
|
706
765
|
}
|
|
707
766
|
__name(isObject, "isObject");
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
const
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
if (
|
|
734
|
-
if (
|
|
735
|
-
|
|
736
|
-
if (
|
|
737
|
-
if (nested
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
if (
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
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
|
+
});
|
|
748
806
|
}
|
|
749
807
|
}
|
|
808
|
+
} else if (nested && isPhecda(nested)) {
|
|
809
|
+
if (!isObject(value2)) return createErrMsg("object", localArgs);
|
|
750
810
|
}
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
if (
|
|
754
|
-
|
|
755
|
-
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);
|
|
756
815
|
}
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
if (
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
const ret = await item(args2);
|
|
793
|
-
if (ret) {
|
|
794
|
-
isCorrect = true;
|
|
795
|
-
break;
|
|
796
|
-
}
|
|
797
|
-
} else {
|
|
798
|
-
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)) {
|
|
799
851
|
isCorrect = true;
|
|
800
852
|
break;
|
|
801
853
|
}
|
|
802
|
-
|
|
854
|
+
}
|
|
803
855
|
}
|
|
856
|
+
if (!isCorrect) return createErrMsg("oneOf", localArgs);
|
|
804
857
|
}
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
property,
|
|
813
|
-
meta,
|
|
814
|
-
model: model2
|
|
815
|
-
};
|
|
816
|
-
for (const rule of allRules) {
|
|
817
|
-
const errMsg = await rule(args);
|
|
818
|
-
if (errMsg === true) break;
|
|
819
|
-
if (errMsg) {
|
|
820
|
-
errors.push(errMsg);
|
|
821
|
-
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;
|
|
822
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);
|
|
823
883
|
}
|
|
824
|
-
if (errors.length !== 0 && !collectErrors) break;
|
|
825
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");
|
|
826
954
|
return errors;
|
|
827
955
|
}
|
|
828
|
-
|
|
829
|
-
return await
|
|
956
|
+
const rules = extractRules(model, createErrMsg, equalFn);
|
|
957
|
+
return await validateWithRules(data, rules, collectErrors);
|
|
830
958
|
}
|
|
831
959
|
__name(validate, "validate");
|
|
832
960
|
export {
|
|
@@ -867,6 +995,8 @@ export {
|
|
|
867
995
|
_createErrorMessage,
|
|
868
996
|
activeInstance,
|
|
869
997
|
addDecoToClass,
|
|
998
|
+
extractDataByRules,
|
|
999
|
+
extractRules,
|
|
870
1000
|
functionToClass,
|
|
871
1001
|
get,
|
|
872
1002
|
getInject,
|
|
@@ -894,5 +1024,6 @@ export {
|
|
|
894
1024
|
setInject,
|
|
895
1025
|
setMeta,
|
|
896
1026
|
validate,
|
|
1027
|
+
validateWithRules,
|
|
897
1028
|
wait
|
|
898
1029
|
};
|