@atscript/typescript 0.1.39 → 0.1.41

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/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <p align="center">
2
- <img src="https://atscript.moost.org/logo.svg" alt="Atscript" width="120" />
2
+ <img src="https://atscript.dev/logo.svg" alt="Atscript" width="120" />
3
3
  </p>
4
4
 
5
5
  <h1 align="center">@atscript/typescript</h1>
@@ -9,7 +9,7 @@
9
9
  </p>
10
10
 
11
11
  <p align="center">
12
- <a href="https://atscript.moost.org">Documentation</a> · <a href="https://atscript.moost.org/packages/typescript/">TypeScript Guide</a>
12
+ <a href="https://atscript.dev">Documentation</a> · <a href="https://atscript.dev/packages/typescript/">TypeScript Guide</a>
13
13
  </p>
14
14
 
15
15
  ---
@@ -60,8 +60,8 @@ npx atscript-typescript-skill --global # Install globally
60
60
 
61
61
  ## Documentation
62
62
 
63
- - [TypeScript Guide](https://atscript.moost.org/packages/typescript/)
64
- - [Full Documentation](https://atscript.moost.org)
63
+ - [TypeScript Guide](https://atscript.dev/packages/typescript/)
64
+ - [Full Documentation](https://atscript.dev)
65
65
 
66
66
  ## License
67
67
 
package/dist/cli.cjs CHANGED
@@ -688,27 +688,26 @@ else obj[key] = value;
688
688
  }
689
689
  const regexCache = new Map();
690
690
  var Validator = class {
691
- isLimitExceeded() {
692
- if (this.stackErrors.length > 0) {
693
- const top = this.stackErrors[this.stackErrors.length - 1];
694
- return top !== null && top.length >= this.opts.errorLimit;
695
- }
696
- return this.errors.length >= this.opts.errorLimit;
691
+ buildPath() {
692
+ if (this.depth <= 0) return "";
693
+ let path$4 = this.pathSegments[0];
694
+ for (let i = 1; i < this.depth; i++) path$4 += `.${this.pathSegments[i]}`;
695
+ return path$4;
697
696
  }
698
697
  push(name) {
699
- this.stackPath.push(name);
698
+ this.pathSegments[this.depth] = name;
699
+ this.depth++;
700
700
  this.stackErrors.push(null);
701
- this.cachedPath = this.stackPath.length <= 1 ? "" : this.stackPath[1] + (this.stackPath.length > 2 ? "." + this.stackPath.slice(2).join(".") : "");
702
701
  }
703
702
  pop(saveErrors) {
704
- this.stackPath.pop();
703
+ this.depth--;
705
704
  const popped = this.stackErrors.pop();
706
705
  if (saveErrors && popped !== null && popped !== undefined && popped.length > 0) for (const err of popped) this.error(err.message, err.path, err.details);
707
- this.cachedPath = this.stackPath.length <= 1 ? "" : this.stackPath[1] + (this.stackPath.length > 2 ? "." + this.stackPath.slice(2).join(".") : "");
708
706
  return popped;
709
707
  }
710
708
  clear() {
711
709
  this.stackErrors[this.stackErrors.length - 1] = null;
710
+ if (this.limitExceeded) this.limitExceeded = false;
712
711
  }
713
712
  error(message, path$4, details) {
714
713
  let errors = this.stackErrors[this.stackErrors.length - 1];
@@ -717,11 +716,12 @@ var Validator = class {
717
716
  this.stackErrors[this.stackErrors.length - 1] = errors;
718
717
  } else errors = this.errors;
719
718
  const error = {
720
- path: path$4 || this.cachedPath,
719
+ path: path$4 || this.buildPath(),
721
720
  message
722
721
  };
723
722
  if (details?.length) error.details = details;
724
723
  errors.push(error);
724
+ if (errors.length >= this.opts.errorLimit) this.limitExceeded = true;
725
725
  }
726
726
  throw() {
727
727
  throw new ValidatorError(this.errors);
@@ -738,12 +738,11 @@ var Validator = class {
738
738
  * @throws {ValidatorError} When validation fails and `safe` is not `true`.
739
739
  */ validate(value, safe, context) {
740
740
  this.errors = [];
741
- this.stackErrors = [];
742
- this.stackPath = [""];
743
- this.cachedPath = "";
741
+ this.stackErrors.length = 0;
742
+ this.depth = 0;
743
+ this.limitExceeded = false;
744
744
  this.context = context;
745
745
  const passed = this.validateSafe(this.def, value);
746
- this.pop(!passed);
747
746
  this.context = undefined;
748
747
  if (!passed) {
749
748
  if (safe) return false;
@@ -752,18 +751,17 @@ var Validator = class {
752
751
  return true;
753
752
  }
754
753
  validateSafe(def, value) {
755
- if (this.isLimitExceeded()) return false;
756
- if (!isAnnotatedType(def)) throw new Error("Can not validate not-annotated type");
757
- if (typeof this.opts.replace === "function") def = this.opts.replace(def, this.cachedPath);
754
+ if (this.limitExceeded) return false;
755
+ if (this.hasReplace) def = this.opts.replace(def, this.buildPath());
758
756
  if (def.optional && (value === undefined || value === null)) return true;
759
- for (const plugin of this.opts.plugins) {
757
+ if (this.hasPlugins) for (const plugin of this.opts.plugins) {
760
758
  const result = plugin(this, def, value);
761
759
  if (result === false || result === true) return result;
762
760
  }
763
761
  return this.validateAnnotatedType(def, value);
764
762
  }
765
763
  get path() {
766
- return this.cachedPath;
764
+ return this.buildPath();
767
765
  }
768
766
  validateAnnotatedType(def, value) {
769
767
  switch (def.type.kind) {
@@ -780,21 +778,21 @@ var Validator = class {
780
778
  }
781
779
  }
782
780
  validateUnion(def, value) {
783
- let i = 0;
784
- const popped = [];
785
- for (const item of def.type.items) {
786
- this.push(`[${item.type.kind || item.type.designType}(${i})]`);
781
+ const items = def.type.items;
782
+ let details;
783
+ for (const item of items) {
784
+ this.stackErrors.push(null);
787
785
  if (this.validateSafe(item, value)) {
788
- this.pop(false);
786
+ this.stackErrors.pop();
789
787
  return true;
790
788
  }
791
- const errors = this.pop(false);
792
- if (errors) popped.push(...errors);
793
- i++;
789
+ const branchErrors = this.stackErrors.pop();
790
+ if (this.limitExceeded) this.limitExceeded = false;
791
+ if (branchErrors) if (details) for (const err of branchErrors) details.push(err);
792
+ else details = branchErrors;
794
793
  }
795
- this.clear();
796
- const expected = def.type.items.map((item, i$1) => `[${item.type.kind || item.type.designType}(${i$1})]`).join(", ");
797
- this.error(`Value does not match any of the allowed types: ${expected}`, undefined, popped);
794
+ const expected = items.map((item, i) => `[${item.type.kind || item.type.designType}(${i})]`).join(", ");
795
+ this.error(`Value does not match any of the allowed types: ${expected}`, undefined, details);
798
796
  return false;
799
797
  }
800
798
  validateIntersection(def, value) {
@@ -872,7 +870,7 @@ var Validator = class {
872
870
  if (!this.validateSafe(def.type.of, item)) {
873
871
  passed = false;
874
872
  this.pop(true);
875
- if (this.isLimitExceeded()) return false;
873
+ if (this.limitExceeded) return false;
876
874
  } else this.pop(false);
877
875
  i++;
878
876
  }
@@ -884,67 +882,72 @@ var Validator = class {
884
882
  return false;
885
883
  }
886
884
  let passed = true;
887
- const valueKeys = new Set(Object.keys(value));
888
- const typeKeys = new Set();
885
+ let keysToStrip;
889
886
  let skipList;
890
887
  if (this.opts.skipList) {
891
- const path$4 = this.stackPath.length > 1 ? `${this.cachedPath}.` : "";
888
+ const path$4 = this.depth > 0 ? `${this.buildPath()}.` : "";
892
889
  for (const item of this.opts.skipList) if (item.startsWith(path$4)) {
893
890
  const key = item.slice(path$4.length);
894
891
  if (!skipList) skipList = new Set();
895
892
  skipList.add(key);
896
- valueKeys.delete(key);
897
893
  }
898
894
  }
899
895
  let partialFunctionMatched = false;
900
- if (typeof this.opts.partial === "function") partialFunctionMatched = this.opts.partial(def, this.cachedPath);
896
+ if (typeof this.opts.partial === "function") partialFunctionMatched = this.opts.partial(def, this.buildPath());
901
897
  for (const [key, item] of def.type.props.entries()) {
902
898
  if (skipList && skipList.has(key) || isPhantomType(item)) continue;
903
- typeKeys.add(key);
904
899
  if (value[key] === undefined) {
905
- if (partialFunctionMatched || this.opts.partial === "deep" || this.opts.partial === true && this.stackPath.length <= 1) continue;
900
+ if (partialFunctionMatched || this.opts.partial === "deep" || this.opts.partial === true && this.depth === 0) continue;
906
901
  }
907
902
  this.push(key);
908
903
  if (this.validateSafe(item, value[key])) this.pop(false);
909
904
  else {
910
905
  passed = false;
911
906
  this.pop(true);
912
- if (this.isLimitExceeded()) return false;
913
- }
914
- }
915
- for (const key of valueKeys)
916
- /** matched patterns for unknown keys */ if (!typeKeys.has(key)) {
917
- const matched = [];
918
- for (const { pattern, def: propDef } of def.type.propsPatterns) if (pattern.test(key)) matched.push({
919
- pattern,
920
- def: propDef
921
- });
922
- if (matched.length > 0) {
923
- this.push(key);
924
- let keyPassed = false;
925
- for (const { def: propDef } of matched) {
926
- if (this.validateSafe(propDef, value[key])) {
927
- keyPassed = true;
928
- break;
907
+ if (this.limitExceeded) return false;
908
+ }
909
+ }
910
+ const hasPatterns = def.type.propsPatterns.length > 0;
911
+ if (this.opts.unknownProps !== "ignore" || hasPatterns) {
912
+ const keys = Object.keys(value);
913
+ for (const key of keys) {
914
+ if (skipList && skipList.has(key)) continue;
915
+ const knownProp = def.type.props.get(key);
916
+ if (knownProp && !isPhantomType(knownProp)) continue;
917
+ const matched = [];
918
+ for (const { pattern, def: propDef } of def.type.propsPatterns) if (pattern.test(key)) matched.push({
919
+ pattern,
920
+ def: propDef
921
+ });
922
+ if (matched.length > 0) {
923
+ this.push(key);
924
+ let keyPassed = false;
925
+ for (const { def: propDef } of matched) {
926
+ if (this.validateSafe(propDef, value[key])) {
927
+ keyPassed = true;
928
+ break;
929
+ }
930
+ this.clear();
929
931
  }
930
- this.clear();
931
- }
932
- if (!keyPassed) {
933
- this.validateSafe(matched[0].def, value[key]);
934
- this.pop(true);
935
- passed = false;
936
- if (this.isLimitExceeded()) return false;
937
- } else this.pop(false);
938
- } else if (this.opts.unknownProps !== "ignore") {
939
- if (this.opts.unknownProps === "error") {
932
+ if (!keyPassed) {
933
+ this.validateSafe(matched[0].def, value[key]);
934
+ this.pop(true);
935
+ passed = false;
936
+ if (this.limitExceeded) return false;
937
+ } else this.pop(false);
938
+ } else if (this.opts.unknownProps === "error") {
940
939
  this.push(key);
941
940
  this.error(`Unexpected property`);
942
941
  this.pop(true);
943
- if (this.isLimitExceeded()) return false;
942
+ if (this.limitExceeded) return false;
944
943
  passed = false;
945
- } else if (this.opts.unknownProps === "strip") delete value[key];
944
+ } else if (this.opts.unknownProps === "strip") {
945
+ if (!keysToStrip) keysToStrip = [];
946
+ keysToStrip.push(key);
947
+ }
946
948
  }
947
949
  }
950
+ if (passed && keysToStrip) for (const key of keysToStrip) delete value[key];
948
951
  return passed;
949
952
  }
950
953
  validatePrimitive(def, value) {
@@ -1008,6 +1011,7 @@ else {
1008
1011
  }
1009
1012
  }
1010
1013
  validateString(def, value) {
1014
+ if (def.metadata.size === 0) return true;
1011
1015
  const filled = def.metadata.get("meta.required");
1012
1016
  if (filled) {
1013
1017
  if (value.trim().length === 0) {
@@ -1051,6 +1055,7 @@ else {
1051
1055
  return true;
1052
1056
  }
1053
1057
  validateNumber(def, value) {
1058
+ if (def.metadata.size === 0) return true;
1054
1059
  const int = def.metadata.get("expect.int");
1055
1060
  if (int && value % 1 !== 0) {
1056
1061
  const message = typeof int === "object" && int.message ? int.message : `Expected integer, got ${value}`;
@@ -1078,6 +1083,7 @@ else {
1078
1083
  return true;
1079
1084
  }
1080
1085
  validateBoolean(def, value) {
1086
+ if (def.metadata.size === 0) return true;
1081
1087
  const filled = def.metadata.get("meta.required");
1082
1088
  if (filled) {
1083
1089
  if (value !== true) {
@@ -1091,16 +1097,20 @@ else {
1091
1097
  constructor(def, opts) {
1092
1098
  _define_property$4(this, "def", void 0);
1093
1099
  _define_property$4(this, "opts", void 0);
1100
+ _define_property$4(this, "hasPlugins", void 0);
1101
+ _define_property$4(this, "hasReplace", void 0);
1094
1102
  /** Validation errors collected during the last {@link validate} call. */ _define_property$4(this, "errors", void 0);
1095
1103
  _define_property$4(this, "stackErrors", void 0);
1096
- _define_property$4(this, "stackPath", void 0);
1097
- _define_property$4(this, "cachedPath", void 0);
1104
+ _define_property$4(this, "pathSegments", void 0);
1105
+ _define_property$4(this, "depth", void 0);
1106
+ _define_property$4(this, "limitExceeded", void 0);
1098
1107
  _define_property$4(this, "context", void 0);
1099
1108
  this.def = def;
1100
1109
  this.errors = [];
1101
1110
  this.stackErrors = [];
1102
- this.stackPath = [];
1103
- this.cachedPath = "";
1111
+ this.pathSegments = [];
1112
+ this.depth = 0;
1113
+ this.limitExceeded = false;
1104
1114
  this.opts = {
1105
1115
  partial: false,
1106
1116
  unknownProps: "error",
@@ -1108,6 +1118,8 @@ else {
1108
1118
  ...opts,
1109
1119
  plugins: opts?.plugins || []
1110
1120
  };
1121
+ this.hasPlugins = this.opts.plugins.length > 0;
1122
+ this.hasReplace = typeof this.opts.replace === "function";
1111
1123
  }
1112
1124
  };
1113
1125
  var ValidatorError = class extends Error {
@@ -2426,7 +2438,7 @@ const BANNER = DYE_COLORS.cyan(`
2426
2438
  const PLAN_HEADER = [
2427
2439
  "",
2428
2440
  DYE_COLORS.bold("╔══════════════════════════════════════╗"),
2429
- DYE_COLORS.bold("║ Schema Sync Plan ║"),
2441
+ DYE_COLORS.bold("║ Schema Sync Plan ║"),
2430
2442
  DYE_COLORS.bold("╚══════════════════════════════════════╝"),
2431
2443
  ""
2432
2444
  ];
package/dist/index.cjs CHANGED
@@ -23,7 +23,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
23
  }) : target, mod));
24
24
 
25
25
  //#endregion
26
- const require_json_schema = require('./json-schema-B55uxKNQ.cjs');
26
+ const require_json_schema = require('./json-schema-CE9SaXaN.cjs');
27
27
  const path = __toESM(require("path"));
28
28
  const __atscript_core = __toESM(require("@atscript/core"));
29
29
 
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { buildJsonSchema, defineAnnotatedType } from "./json-schema-DaFltW4t.mjs";
1
+ import { buildJsonSchema, defineAnnotatedType } from "./json-schema-CpCjWo9b.mjs";
2
2
  import path from "path";
3
3
  import { DEFAULT_FORMAT, flattenInterfaceNode, hasNavPropAnnotation, isArray, isConst, isGroup, isInterface, isPrimitive, isQueryLogical, isRef, isStructure } from "@atscript/core";
4
4
 
@@ -13,27 +13,26 @@ else obj[key] = value;
13
13
  }
14
14
  const regexCache = new Map();
15
15
  var Validator = class {
16
- isLimitExceeded() {
17
- if (this.stackErrors.length > 0) {
18
- const top = this.stackErrors[this.stackErrors.length - 1];
19
- return top !== null && top.length >= this.opts.errorLimit;
20
- }
21
- return this.errors.length >= this.opts.errorLimit;
16
+ buildPath() {
17
+ if (this.depth <= 0) return "";
18
+ let path = this.pathSegments[0];
19
+ for (let i = 1; i < this.depth; i++) path += `.${this.pathSegments[i]}`;
20
+ return path;
22
21
  }
23
22
  push(name) {
24
- this.stackPath.push(name);
23
+ this.pathSegments[this.depth] = name;
24
+ this.depth++;
25
25
  this.stackErrors.push(null);
26
- this.cachedPath = this.stackPath.length <= 1 ? "" : this.stackPath[1] + (this.stackPath.length > 2 ? "." + this.stackPath.slice(2).join(".") : "");
27
26
  }
28
27
  pop(saveErrors) {
29
- this.stackPath.pop();
28
+ this.depth--;
30
29
  const popped = this.stackErrors.pop();
31
30
  if (saveErrors && popped !== null && popped !== undefined && popped.length > 0) for (const err of popped) this.error(err.message, err.path, err.details);
32
- this.cachedPath = this.stackPath.length <= 1 ? "" : this.stackPath[1] + (this.stackPath.length > 2 ? "." + this.stackPath.slice(2).join(".") : "");
33
31
  return popped;
34
32
  }
35
33
  clear() {
36
34
  this.stackErrors[this.stackErrors.length - 1] = null;
35
+ if (this.limitExceeded) this.limitExceeded = false;
37
36
  }
38
37
  error(message, path, details) {
39
38
  let errors = this.stackErrors[this.stackErrors.length - 1];
@@ -42,11 +41,12 @@ var Validator = class {
42
41
  this.stackErrors[this.stackErrors.length - 1] = errors;
43
42
  } else errors = this.errors;
44
43
  const error = {
45
- path: path || this.cachedPath,
44
+ path: path || this.buildPath(),
46
45
  message
47
46
  };
48
47
  if (details?.length) error.details = details;
49
48
  errors.push(error);
49
+ if (errors.length >= this.opts.errorLimit) this.limitExceeded = true;
50
50
  }
51
51
  throw() {
52
52
  throw new ValidatorError(this.errors);
@@ -63,12 +63,11 @@ var Validator = class {
63
63
  * @throws {ValidatorError} When validation fails and `safe` is not `true`.
64
64
  */ validate(value, safe, context) {
65
65
  this.errors = [];
66
- this.stackErrors = [];
67
- this.stackPath = [""];
68
- this.cachedPath = "";
66
+ this.stackErrors.length = 0;
67
+ this.depth = 0;
68
+ this.limitExceeded = false;
69
69
  this.context = context;
70
70
  const passed = this.validateSafe(this.def, value);
71
- this.pop(!passed);
72
71
  this.context = undefined;
73
72
  if (!passed) {
74
73
  if (safe) return false;
@@ -77,18 +76,17 @@ var Validator = class {
77
76
  return true;
78
77
  }
79
78
  validateSafe(def, value) {
80
- if (this.isLimitExceeded()) return false;
81
- if (!isAnnotatedType(def)) throw new Error("Can not validate not-annotated type");
82
- if (typeof this.opts.replace === "function") def = this.opts.replace(def, this.cachedPath);
79
+ if (this.limitExceeded) return false;
80
+ if (this.hasReplace) def = this.opts.replace(def, this.buildPath());
83
81
  if (def.optional && (value === undefined || value === null)) return true;
84
- for (const plugin of this.opts.plugins) {
82
+ if (this.hasPlugins) for (const plugin of this.opts.plugins) {
85
83
  const result = plugin(this, def, value);
86
84
  if (result === false || result === true) return result;
87
85
  }
88
86
  return this.validateAnnotatedType(def, value);
89
87
  }
90
88
  get path() {
91
- return this.cachedPath;
89
+ return this.buildPath();
92
90
  }
93
91
  validateAnnotatedType(def, value) {
94
92
  switch (def.type.kind) {
@@ -105,21 +103,21 @@ var Validator = class {
105
103
  }
106
104
  }
107
105
  validateUnion(def, value) {
108
- let i = 0;
109
- const popped = [];
110
- for (const item of def.type.items) {
111
- this.push(`[${item.type.kind || item.type.designType}(${i})]`);
106
+ const items = def.type.items;
107
+ let details;
108
+ for (const item of items) {
109
+ this.stackErrors.push(null);
112
110
  if (this.validateSafe(item, value)) {
113
- this.pop(false);
111
+ this.stackErrors.pop();
114
112
  return true;
115
113
  }
116
- const errors = this.pop(false);
117
- if (errors) popped.push(...errors);
118
- i++;
114
+ const branchErrors = this.stackErrors.pop();
115
+ if (this.limitExceeded) this.limitExceeded = false;
116
+ if (branchErrors) if (details) for (const err of branchErrors) details.push(err);
117
+ else details = branchErrors;
119
118
  }
120
- this.clear();
121
- const expected = def.type.items.map((item, i$1) => `[${item.type.kind || item.type.designType}(${i$1})]`).join(", ");
122
- this.error(`Value does not match any of the allowed types: ${expected}`, undefined, popped);
119
+ const expected = items.map((item, i) => `[${item.type.kind || item.type.designType}(${i})]`).join(", ");
120
+ this.error(`Value does not match any of the allowed types: ${expected}`, undefined, details);
123
121
  return false;
124
122
  }
125
123
  validateIntersection(def, value) {
@@ -197,7 +195,7 @@ var Validator = class {
197
195
  if (!this.validateSafe(def.type.of, item)) {
198
196
  passed = false;
199
197
  this.pop(true);
200
- if (this.isLimitExceeded()) return false;
198
+ if (this.limitExceeded) return false;
201
199
  } else this.pop(false);
202
200
  i++;
203
201
  }
@@ -209,67 +207,72 @@ var Validator = class {
209
207
  return false;
210
208
  }
211
209
  let passed = true;
212
- const valueKeys = new Set(Object.keys(value));
213
- const typeKeys = new Set();
210
+ let keysToStrip;
214
211
  let skipList;
215
212
  if (this.opts.skipList) {
216
- const path = this.stackPath.length > 1 ? `${this.cachedPath}.` : "";
213
+ const path = this.depth > 0 ? `${this.buildPath()}.` : "";
217
214
  for (const item of this.opts.skipList) if (item.startsWith(path)) {
218
215
  const key = item.slice(path.length);
219
216
  if (!skipList) skipList = new Set();
220
217
  skipList.add(key);
221
- valueKeys.delete(key);
222
218
  }
223
219
  }
224
220
  let partialFunctionMatched = false;
225
- if (typeof this.opts.partial === "function") partialFunctionMatched = this.opts.partial(def, this.cachedPath);
221
+ if (typeof this.opts.partial === "function") partialFunctionMatched = this.opts.partial(def, this.buildPath());
226
222
  for (const [key, item] of def.type.props.entries()) {
227
223
  if (skipList && skipList.has(key) || isPhantomType(item)) continue;
228
- typeKeys.add(key);
229
224
  if (value[key] === undefined) {
230
- if (partialFunctionMatched || this.opts.partial === "deep" || this.opts.partial === true && this.stackPath.length <= 1) continue;
225
+ if (partialFunctionMatched || this.opts.partial === "deep" || this.opts.partial === true && this.depth === 0) continue;
231
226
  }
232
227
  this.push(key);
233
228
  if (this.validateSafe(item, value[key])) this.pop(false);
234
229
  else {
235
230
  passed = false;
236
231
  this.pop(true);
237
- if (this.isLimitExceeded()) return false;
232
+ if (this.limitExceeded) return false;
238
233
  }
239
234
  }
240
- for (const key of valueKeys)
241
- /** matched patterns for unknown keys */ if (!typeKeys.has(key)) {
242
- const matched = [];
243
- for (const { pattern, def: propDef } of def.type.propsPatterns) if (pattern.test(key)) matched.push({
244
- pattern,
245
- def: propDef
246
- });
247
- if (matched.length > 0) {
248
- this.push(key);
249
- let keyPassed = false;
250
- for (const { def: propDef } of matched) {
251
- if (this.validateSafe(propDef, value[key])) {
252
- keyPassed = true;
253
- break;
235
+ const hasPatterns = def.type.propsPatterns.length > 0;
236
+ if (this.opts.unknownProps !== "ignore" || hasPatterns) {
237
+ const keys = Object.keys(value);
238
+ for (const key of keys) {
239
+ if (skipList && skipList.has(key)) continue;
240
+ const knownProp = def.type.props.get(key);
241
+ if (knownProp && !isPhantomType(knownProp)) continue;
242
+ const matched = [];
243
+ for (const { pattern, def: propDef } of def.type.propsPatterns) if (pattern.test(key)) matched.push({
244
+ pattern,
245
+ def: propDef
246
+ });
247
+ if (matched.length > 0) {
248
+ this.push(key);
249
+ let keyPassed = false;
250
+ for (const { def: propDef } of matched) {
251
+ if (this.validateSafe(propDef, value[key])) {
252
+ keyPassed = true;
253
+ break;
254
+ }
255
+ this.clear();
254
256
  }
255
- this.clear();
256
- }
257
- if (!keyPassed) {
258
- this.validateSafe(matched[0].def, value[key]);
259
- this.pop(true);
260
- passed = false;
261
- if (this.isLimitExceeded()) return false;
262
- } else this.pop(false);
263
- } else if (this.opts.unknownProps !== "ignore") {
264
- if (this.opts.unknownProps === "error") {
257
+ if (!keyPassed) {
258
+ this.validateSafe(matched[0].def, value[key]);
259
+ this.pop(true);
260
+ passed = false;
261
+ if (this.limitExceeded) return false;
262
+ } else this.pop(false);
263
+ } else if (this.opts.unknownProps === "error") {
265
264
  this.push(key);
266
265
  this.error(`Unexpected property`);
267
266
  this.pop(true);
268
- if (this.isLimitExceeded()) return false;
267
+ if (this.limitExceeded) return false;
269
268
  passed = false;
270
- } else if (this.opts.unknownProps === "strip") delete value[key];
269
+ } else if (this.opts.unknownProps === "strip") {
270
+ if (!keysToStrip) keysToStrip = [];
271
+ keysToStrip.push(key);
272
+ }
271
273
  }
272
274
  }
275
+ if (passed && keysToStrip) for (const key of keysToStrip) delete value[key];
273
276
  return passed;
274
277
  }
275
278
  validatePrimitive(def, value) {
@@ -333,6 +336,7 @@ else {
333
336
  }
334
337
  }
335
338
  validateString(def, value) {
339
+ if (def.metadata.size === 0) return true;
336
340
  const filled = def.metadata.get("meta.required");
337
341
  if (filled) {
338
342
  if (value.trim().length === 0) {
@@ -376,6 +380,7 @@ else {
376
380
  return true;
377
381
  }
378
382
  validateNumber(def, value) {
383
+ if (def.metadata.size === 0) return true;
379
384
  const int = def.metadata.get("expect.int");
380
385
  if (int && value % 1 !== 0) {
381
386
  const message = typeof int === "object" && int.message ? int.message : `Expected integer, got ${value}`;
@@ -403,6 +408,7 @@ else {
403
408
  return true;
404
409
  }
405
410
  validateBoolean(def, value) {
411
+ if (def.metadata.size === 0) return true;
406
412
  const filled = def.metadata.get("meta.required");
407
413
  if (filled) {
408
414
  if (value !== true) {
@@ -416,16 +422,20 @@ else {
416
422
  constructor(def, opts) {
417
423
  _define_property(this, "def", void 0);
418
424
  _define_property(this, "opts", void 0);
425
+ _define_property(this, "hasPlugins", void 0);
426
+ _define_property(this, "hasReplace", void 0);
419
427
  /** Validation errors collected during the last {@link validate} call. */ _define_property(this, "errors", void 0);
420
428
  _define_property(this, "stackErrors", void 0);
421
- _define_property(this, "stackPath", void 0);
422
- _define_property(this, "cachedPath", void 0);
429
+ _define_property(this, "pathSegments", void 0);
430
+ _define_property(this, "depth", void 0);
431
+ _define_property(this, "limitExceeded", void 0);
423
432
  _define_property(this, "context", void 0);
424
433
  this.def = def;
425
434
  this.errors = [];
426
435
  this.stackErrors = [];
427
- this.stackPath = [];
428
- this.cachedPath = "";
436
+ this.pathSegments = [];
437
+ this.depth = 0;
438
+ this.limitExceeded = false;
429
439
  this.opts = {
430
440
  partial: false,
431
441
  unknownProps: "error",
@@ -433,6 +443,8 @@ else {
433
443
  ...opts,
434
444
  plugins: opts?.plugins || []
435
445
  };
446
+ this.hasPlugins = this.opts.plugins.length > 0;
447
+ this.hasReplace = typeof this.opts.replace === "function";
436
448
  }
437
449
  };
438
450
  var ValidatorError = class extends Error {
@@ -12,27 +12,26 @@ else obj[key] = value;
12
12
  }
13
13
  const regexCache = new Map();
14
14
  var Validator = class {
15
- isLimitExceeded() {
16
- if (this.stackErrors.length > 0) {
17
- const top = this.stackErrors[this.stackErrors.length - 1];
18
- return top !== null && top.length >= this.opts.errorLimit;
19
- }
20
- return this.errors.length >= this.opts.errorLimit;
15
+ buildPath() {
16
+ if (this.depth <= 0) return "";
17
+ let path = this.pathSegments[0];
18
+ for (let i = 1; i < this.depth; i++) path += `.${this.pathSegments[i]}`;
19
+ return path;
21
20
  }
22
21
  push(name) {
23
- this.stackPath.push(name);
22
+ this.pathSegments[this.depth] = name;
23
+ this.depth++;
24
24
  this.stackErrors.push(null);
25
- this.cachedPath = this.stackPath.length <= 1 ? "" : this.stackPath[1] + (this.stackPath.length > 2 ? "." + this.stackPath.slice(2).join(".") : "");
26
25
  }
27
26
  pop(saveErrors) {
28
- this.stackPath.pop();
27
+ this.depth--;
29
28
  const popped = this.stackErrors.pop();
30
29
  if (saveErrors && popped !== null && popped !== undefined && popped.length > 0) for (const err of popped) this.error(err.message, err.path, err.details);
31
- this.cachedPath = this.stackPath.length <= 1 ? "" : this.stackPath[1] + (this.stackPath.length > 2 ? "." + this.stackPath.slice(2).join(".") : "");
32
30
  return popped;
33
31
  }
34
32
  clear() {
35
33
  this.stackErrors[this.stackErrors.length - 1] = null;
34
+ if (this.limitExceeded) this.limitExceeded = false;
36
35
  }
37
36
  error(message, path, details) {
38
37
  let errors = this.stackErrors[this.stackErrors.length - 1];
@@ -41,11 +40,12 @@ var Validator = class {
41
40
  this.stackErrors[this.stackErrors.length - 1] = errors;
42
41
  } else errors = this.errors;
43
42
  const error = {
44
- path: path || this.cachedPath,
43
+ path: path || this.buildPath(),
45
44
  message
46
45
  };
47
46
  if (details?.length) error.details = details;
48
47
  errors.push(error);
48
+ if (errors.length >= this.opts.errorLimit) this.limitExceeded = true;
49
49
  }
50
50
  throw() {
51
51
  throw new ValidatorError(this.errors);
@@ -62,12 +62,11 @@ var Validator = class {
62
62
  * @throws {ValidatorError} When validation fails and `safe` is not `true`.
63
63
  */ validate(value, safe, context) {
64
64
  this.errors = [];
65
- this.stackErrors = [];
66
- this.stackPath = [""];
67
- this.cachedPath = "";
65
+ this.stackErrors.length = 0;
66
+ this.depth = 0;
67
+ this.limitExceeded = false;
68
68
  this.context = context;
69
69
  const passed = this.validateSafe(this.def, value);
70
- this.pop(!passed);
71
70
  this.context = undefined;
72
71
  if (!passed) {
73
72
  if (safe) return false;
@@ -76,18 +75,17 @@ var Validator = class {
76
75
  return true;
77
76
  }
78
77
  validateSafe(def, value) {
79
- if (this.isLimitExceeded()) return false;
80
- if (!isAnnotatedType(def)) throw new Error("Can not validate not-annotated type");
81
- if (typeof this.opts.replace === "function") def = this.opts.replace(def, this.cachedPath);
78
+ if (this.limitExceeded) return false;
79
+ if (this.hasReplace) def = this.opts.replace(def, this.buildPath());
82
80
  if (def.optional && (value === undefined || value === null)) return true;
83
- for (const plugin of this.opts.plugins) {
81
+ if (this.hasPlugins) for (const plugin of this.opts.plugins) {
84
82
  const result = plugin(this, def, value);
85
83
  if (result === false || result === true) return result;
86
84
  }
87
85
  return this.validateAnnotatedType(def, value);
88
86
  }
89
87
  get path() {
90
- return this.cachedPath;
88
+ return this.buildPath();
91
89
  }
92
90
  validateAnnotatedType(def, value) {
93
91
  switch (def.type.kind) {
@@ -104,21 +102,21 @@ var Validator = class {
104
102
  }
105
103
  }
106
104
  validateUnion(def, value) {
107
- let i = 0;
108
- const popped = [];
109
- for (const item of def.type.items) {
110
- this.push(`[${item.type.kind || item.type.designType}(${i})]`);
105
+ const items = def.type.items;
106
+ let details;
107
+ for (const item of items) {
108
+ this.stackErrors.push(null);
111
109
  if (this.validateSafe(item, value)) {
112
- this.pop(false);
110
+ this.stackErrors.pop();
113
111
  return true;
114
112
  }
115
- const errors = this.pop(false);
116
- if (errors) popped.push(...errors);
117
- i++;
113
+ const branchErrors = this.stackErrors.pop();
114
+ if (this.limitExceeded) this.limitExceeded = false;
115
+ if (branchErrors) if (details) for (const err of branchErrors) details.push(err);
116
+ else details = branchErrors;
118
117
  }
119
- this.clear();
120
- const expected = def.type.items.map((item, i$1) => `[${item.type.kind || item.type.designType}(${i$1})]`).join(", ");
121
- this.error(`Value does not match any of the allowed types: ${expected}`, undefined, popped);
118
+ const expected = items.map((item, i) => `[${item.type.kind || item.type.designType}(${i})]`).join(", ");
119
+ this.error(`Value does not match any of the allowed types: ${expected}`, undefined, details);
122
120
  return false;
123
121
  }
124
122
  validateIntersection(def, value) {
@@ -196,7 +194,7 @@ var Validator = class {
196
194
  if (!this.validateSafe(def.type.of, item)) {
197
195
  passed = false;
198
196
  this.pop(true);
199
- if (this.isLimitExceeded()) return false;
197
+ if (this.limitExceeded) return false;
200
198
  } else this.pop(false);
201
199
  i++;
202
200
  }
@@ -208,67 +206,72 @@ var Validator = class {
208
206
  return false;
209
207
  }
210
208
  let passed = true;
211
- const valueKeys = new Set(Object.keys(value));
212
- const typeKeys = new Set();
209
+ let keysToStrip;
213
210
  let skipList;
214
211
  if (this.opts.skipList) {
215
- const path = this.stackPath.length > 1 ? `${this.cachedPath}.` : "";
212
+ const path = this.depth > 0 ? `${this.buildPath()}.` : "";
216
213
  for (const item of this.opts.skipList) if (item.startsWith(path)) {
217
214
  const key = item.slice(path.length);
218
215
  if (!skipList) skipList = new Set();
219
216
  skipList.add(key);
220
- valueKeys.delete(key);
221
217
  }
222
218
  }
223
219
  let partialFunctionMatched = false;
224
- if (typeof this.opts.partial === "function") partialFunctionMatched = this.opts.partial(def, this.cachedPath);
220
+ if (typeof this.opts.partial === "function") partialFunctionMatched = this.opts.partial(def, this.buildPath());
225
221
  for (const [key, item] of def.type.props.entries()) {
226
222
  if (skipList && skipList.has(key) || isPhantomType(item)) continue;
227
- typeKeys.add(key);
228
223
  if (value[key] === undefined) {
229
- if (partialFunctionMatched || this.opts.partial === "deep" || this.opts.partial === true && this.stackPath.length <= 1) continue;
224
+ if (partialFunctionMatched || this.opts.partial === "deep" || this.opts.partial === true && this.depth === 0) continue;
230
225
  }
231
226
  this.push(key);
232
227
  if (this.validateSafe(item, value[key])) this.pop(false);
233
228
  else {
234
229
  passed = false;
235
230
  this.pop(true);
236
- if (this.isLimitExceeded()) return false;
237
- }
238
- }
239
- for (const key of valueKeys)
240
- /** matched patterns for unknown keys */ if (!typeKeys.has(key)) {
241
- const matched = [];
242
- for (const { pattern, def: propDef } of def.type.propsPatterns) if (pattern.test(key)) matched.push({
243
- pattern,
244
- def: propDef
245
- });
246
- if (matched.length > 0) {
247
- this.push(key);
248
- let keyPassed = false;
249
- for (const { def: propDef } of matched) {
250
- if (this.validateSafe(propDef, value[key])) {
251
- keyPassed = true;
252
- break;
231
+ if (this.limitExceeded) return false;
232
+ }
233
+ }
234
+ const hasPatterns = def.type.propsPatterns.length > 0;
235
+ if (this.opts.unknownProps !== "ignore" || hasPatterns) {
236
+ const keys = Object.keys(value);
237
+ for (const key of keys) {
238
+ if (skipList && skipList.has(key)) continue;
239
+ const knownProp = def.type.props.get(key);
240
+ if (knownProp && !isPhantomType(knownProp)) continue;
241
+ const matched = [];
242
+ for (const { pattern, def: propDef } of def.type.propsPatterns) if (pattern.test(key)) matched.push({
243
+ pattern,
244
+ def: propDef
245
+ });
246
+ if (matched.length > 0) {
247
+ this.push(key);
248
+ let keyPassed = false;
249
+ for (const { def: propDef } of matched) {
250
+ if (this.validateSafe(propDef, value[key])) {
251
+ keyPassed = true;
252
+ break;
253
+ }
254
+ this.clear();
253
255
  }
254
- this.clear();
255
- }
256
- if (!keyPassed) {
257
- this.validateSafe(matched[0].def, value[key]);
258
- this.pop(true);
259
- passed = false;
260
- if (this.isLimitExceeded()) return false;
261
- } else this.pop(false);
262
- } else if (this.opts.unknownProps !== "ignore") {
263
- if (this.opts.unknownProps === "error") {
256
+ if (!keyPassed) {
257
+ this.validateSafe(matched[0].def, value[key]);
258
+ this.pop(true);
259
+ passed = false;
260
+ if (this.limitExceeded) return false;
261
+ } else this.pop(false);
262
+ } else if (this.opts.unknownProps === "error") {
264
263
  this.push(key);
265
264
  this.error(`Unexpected property`);
266
265
  this.pop(true);
267
- if (this.isLimitExceeded()) return false;
266
+ if (this.limitExceeded) return false;
268
267
  passed = false;
269
- } else if (this.opts.unknownProps === "strip") delete value[key];
268
+ } else if (this.opts.unknownProps === "strip") {
269
+ if (!keysToStrip) keysToStrip = [];
270
+ keysToStrip.push(key);
271
+ }
270
272
  }
271
273
  }
274
+ if (passed && keysToStrip) for (const key of keysToStrip) delete value[key];
272
275
  return passed;
273
276
  }
274
277
  validatePrimitive(def, value) {
@@ -332,6 +335,7 @@ else {
332
335
  }
333
336
  }
334
337
  validateString(def, value) {
338
+ if (def.metadata.size === 0) return true;
335
339
  const filled = def.metadata.get("meta.required");
336
340
  if (filled) {
337
341
  if (value.trim().length === 0) {
@@ -375,6 +379,7 @@ else {
375
379
  return true;
376
380
  }
377
381
  validateNumber(def, value) {
382
+ if (def.metadata.size === 0) return true;
378
383
  const int = def.metadata.get("expect.int");
379
384
  if (int && value % 1 !== 0) {
380
385
  const message = typeof int === "object" && int.message ? int.message : `Expected integer, got ${value}`;
@@ -402,6 +407,7 @@ else {
402
407
  return true;
403
408
  }
404
409
  validateBoolean(def, value) {
410
+ if (def.metadata.size === 0) return true;
405
411
  const filled = def.metadata.get("meta.required");
406
412
  if (filled) {
407
413
  if (value !== true) {
@@ -415,16 +421,20 @@ else {
415
421
  constructor(def, opts) {
416
422
  _define_property(this, "def", void 0);
417
423
  _define_property(this, "opts", void 0);
424
+ _define_property(this, "hasPlugins", void 0);
425
+ _define_property(this, "hasReplace", void 0);
418
426
  /** Validation errors collected during the last {@link validate} call. */ _define_property(this, "errors", void 0);
419
427
  _define_property(this, "stackErrors", void 0);
420
- _define_property(this, "stackPath", void 0);
421
- _define_property(this, "cachedPath", void 0);
428
+ _define_property(this, "pathSegments", void 0);
429
+ _define_property(this, "depth", void 0);
430
+ _define_property(this, "limitExceeded", void 0);
422
431
  _define_property(this, "context", void 0);
423
432
  this.def = def;
424
433
  this.errors = [];
425
434
  this.stackErrors = [];
426
- this.stackPath = [];
427
- this.cachedPath = "";
435
+ this.pathSegments = [];
436
+ this.depth = 0;
437
+ this.limitExceeded = false;
428
438
  this.opts = {
429
439
  partial: false,
430
440
  unknownProps: "error",
@@ -432,6 +442,8 @@ else {
432
442
  ...opts,
433
443
  plugins: opts?.plugins || []
434
444
  };
445
+ this.hasPlugins = this.opts.plugins.length > 0;
446
+ this.hasReplace = typeof this.opts.replace === "function";
435
447
  }
436
448
  };
437
449
  var ValidatorError = class extends Error {
package/dist/utils.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- const require_json_schema = require('./json-schema-B55uxKNQ.cjs');
2
+ const require_json_schema = require('./json-schema-CE9SaXaN.cjs');
3
3
 
4
4
  //#region packages/typescript/src/runtime/default-value.ts
5
5
  /**
package/dist/utils.d.ts CHANGED
@@ -51,14 +51,17 @@ interface TValidatorPluginContext {
51
51
  declare class Validator<T extends TAtscriptAnnotatedType = TAtscriptAnnotatedType, DataType = TAtscriptDataType<T>> {
52
52
  protected readonly def: T;
53
53
  protected opts: TValidatorOptions;
54
+ protected hasPlugins: boolean;
55
+ protected hasReplace: boolean;
54
56
  constructor(def: T, opts?: Partial<TValidatorOptions>);
55
57
  /** Validation errors collected during the last {@link validate} call. */
56
58
  errors: TError[];
57
59
  protected stackErrors: Array<TError[] | null>;
58
- protected stackPath: string[];
59
- protected cachedPath: string;
60
+ protected pathSegments: string[];
61
+ protected depth: number;
62
+ protected limitExceeded: boolean;
60
63
  protected context: unknown;
61
- protected isLimitExceeded(): boolean;
64
+ protected buildPath(): string;
62
65
  protected push(name: string): void;
63
66
  protected pop(saveErrors: boolean): TError[] | null | undefined;
64
67
  protected clear(): void;
package/dist/utils.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { Validator, ValidatorError, annotate, buildJsonSchema, cloneRefProp, createAnnotatedTypeNode, defineAnnotatedType, forAnnotatedType, fromJsonSchema, isAnnotatedType, isAnnotatedTypeOfPrimitive, isPhantomType, mergeJsonSchemas } from "./json-schema-DaFltW4t.mjs";
1
+ import { Validator, ValidatorError, annotate, buildJsonSchema, cloneRefProp, createAnnotatedTypeNode, defineAnnotatedType, forAnnotatedType, fromJsonSchema, isAnnotatedType, isAnnotatedTypeOfPrimitive, isPhantomType, mergeJsonSchemas } from "./json-schema-CpCjWo9b.mjs";
2
2
 
3
3
  //#region packages/typescript/src/runtime/default-value.ts
4
4
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atscript/typescript",
3
- "version": "0.1.39",
3
+ "version": "0.1.41",
4
4
  "description": "Atscript: typescript-gen support.",
5
5
  "keywords": [
6
6
  "annotations",
@@ -61,11 +61,12 @@
61
61
  "moost": "^0.6.2"
62
62
  },
63
63
  "devDependencies": {
64
- "vitest": "3.2.4"
64
+ "vitest": "3.2.4",
65
+ "@atscript/db": "^0.1.41"
65
66
  },
66
67
  "peerDependencies": {
67
- "@atscript/core": "^0.1.39",
68
- "@atscript/db": "^0.1.39"
68
+ "@atscript/db": "^0.1.41",
69
+ "@atscript/core": "^0.1.41"
69
70
  },
70
71
  "peerDependenciesMeta": {
71
72
  "@atscript/db": {