@litert/typeguard 1.3.0-dev.0 → 1.4.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.
Files changed (61) hide show
  1. package/CHANGES.md +7 -1
  2. package/lib/BuiltInTypeCompiler.d.ts +1 -1
  3. package/lib/BuiltInTypeCompiler.js +4 -4
  4. package/lib/BuiltInTypeCompiler.js.map +1 -1
  5. package/lib/BuiltInTypes.d.ts +1 -1
  6. package/lib/BuiltInTypes.js +1 -1
  7. package/lib/Common.d.ts +6 -5
  8. package/lib/Common.d.ts.map +1 -1
  9. package/lib/Common.js +1 -1
  10. package/lib/Compiler.d.ts +1 -1
  11. package/lib/Compiler.d.ts.map +1 -1
  12. package/lib/Compiler.js +57 -35
  13. package/lib/Compiler.js.map +1 -1
  14. package/lib/Context.d.ts +2 -2
  15. package/lib/Context.d.ts.map +1 -1
  16. package/lib/Context.js +2 -2
  17. package/lib/Context.js.map +1 -1
  18. package/lib/FilterCompiler.d.ts +3 -3
  19. package/lib/FilterCompiler.d.ts.map +1 -1
  20. package/lib/FilterCompiler.js +4 -4
  21. package/lib/FilterCompiler.js.map +1 -1
  22. package/lib/InlineCompiler.d.ts +2 -2
  23. package/lib/InlineCompiler.d.ts.map +1 -1
  24. package/lib/InlineCompiler.js +5 -7
  25. package/lib/InlineCompiler.js.map +1 -1
  26. package/lib/Internal.d.ts +9 -4
  27. package/lib/Internal.d.ts.map +1 -1
  28. package/lib/Internal.js +45 -4
  29. package/lib/Internal.js.map +1 -1
  30. package/lib/Modifiers.d.ts +2 -1
  31. package/lib/Modifiers.d.ts.map +1 -1
  32. package/lib/Modifiers.js +3 -2
  33. package/lib/Modifiers.js.map +1 -1
  34. package/lib/index.d.ts +1 -1
  35. package/lib/index.js +1 -1
  36. package/lib/langs/JavaScript.d.ts +1 -1
  37. package/lib/langs/JavaScript.js +2 -2
  38. package/package.json +11 -13
  39. package/src/examples/quick-start.ts +5 -1
  40. package/src/lib/BuiltInTypeCompiler.ts +4 -4
  41. package/src/lib/BuiltInTypes.ts +1 -1
  42. package/src/lib/Common.ts +5 -4
  43. package/src/lib/Compiler.ts +66 -39
  44. package/src/lib/Context.ts +2 -2
  45. package/src/lib/FilterCompiler.ts +3 -3
  46. package/src/lib/InlineCompiler.ts +6 -9
  47. package/src/lib/Internal.ts +73 -4
  48. package/src/lib/Modifiers.ts +3 -1
  49. package/src/lib/index.ts +1 -1
  50. package/src/lib/langs/JavaScript.ts +2 -2
  51. package/src/test/00-all.ts +1 -1
  52. package/src/test/01-elemental-types.ts +580 -580
  53. package/src/test/02-array-and-list.ts +43 -43
  54. package/src/test/03-tuple.ts +61 -61
  55. package/src/test/04-from-string.ts +501 -501
  56. package/src/test/05-string-asserts.ts +203 -203
  57. package/src/test/06-structure.ts +71 -71
  58. package/src/test/07-modifiers.ts +297 -48
  59. package/src/test/08-map-and-dict.ts +11 -11
  60. package/src/test/09-exceptions.ts +11 -11
  61. package/src/test/abstracts.ts +57 -29
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@litert/typeguard",
3
- "version": "1.3.0-dev.0",
3
+ "version": "1.4.0",
4
4
  "description": "An easy and powerful data validation code generator by JavaScript.",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -12,7 +12,7 @@
12
12
  "clean": "rm -rf lib examples test",
13
13
  "typecheck": "tsc -p tsconfig.json --noEmit",
14
14
  "lint": "eslint --ext ts src",
15
- "prepare": "husky install"
15
+ "prepare": "husky install || echo 'skipped husky install'"
16
16
  },
17
17
  "keywords": [
18
18
  "litert",
@@ -34,18 +34,16 @@
34
34
  "types": "lib/index.d.ts",
35
35
  "typings": "lib/index.d.ts",
36
36
  "devDependencies": {
37
- "@commitlint/cli": "^17.0.3",
38
- "@commitlint/config-conventional": "^17.0.3",
39
- "@types/mocha": "^9.1.1",
40
- "@types/node": "^18.0.0",
41
- "@typescript-eslint/eslint-plugin": "^5.30.3",
42
- "@typescript-eslint/parser": "^5.30.3",
43
- "eslint": "^8.19.0",
44
- "husky": "^8.0.1",
45
- "mocha": "^10.0.0",
46
- "typescript": "^4.7.4"
37
+ "@commitlint/cli": "^17.6.5",
38
+ "@commitlint/config-conventional": "^17.6.5",
39
+ "@litert/eslint-plugin-rules": "^0.1.3",
40
+ "@types/mocha": "^10.0.1",
41
+ "@types/node": "^20.3.1",
42
+ "husky": "^8.0.3",
43
+ "mocha": "^10.2.0",
44
+ "typescript": "~5.0.0"
47
45
  },
48
46
  "engines": {
49
- "node": ">=8.0.0"
47
+ "node": ">=14.0.0"
50
48
  }
51
49
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2022 Angus Fenying <fenying@litert.org>
2
+ * Copyright 2023 Angus Fenying <fenying@litert.org>
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -170,3 +170,7 @@ executeTest(
170
170
  { 'a': '123312312', 'b': 'ccc' },
171
171
  ]
172
172
  );
173
+
174
+ console.log(tgc.compile({
175
+ rule: '@enum(1, 2, 3, "ss\\"")',
176
+ }).toString());
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2022 Angus Fenying <fenying@litert.org>
2
+ * Copyright 2023 Angus Fenying <fenying@litert.org>
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -502,7 +502,7 @@ implements I.IBuiltInTypeCompiler {
502
502
  }
503
503
  case B.STRUCT: {
504
504
 
505
- return this._lang.isStrucutre(ctx.vName, true);
505
+ return this._lang.isStructure(ctx.vName, true);
506
506
  }
507
507
  case B.NUMERIC: {
508
508
 
@@ -738,7 +738,7 @@ implements I.IBuiltInTypeCompiler {
738
738
 
739
739
  if (fromString) {
740
740
 
741
- ctx.untrap();
741
+ ctx.popUp();
742
742
 
743
743
  return this._lang.and([
744
744
  this._lang.or([
@@ -891,7 +891,7 @@ implements I.IBuiltInTypeCompiler {
891
891
 
892
892
  if (fromString) {
893
893
 
894
- ctx.untrap();
894
+ ctx.popUp();
895
895
 
896
896
  return this._lang.and([
897
897
  this._lang.or([
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2022 Angus Fenying <fenying@litert.org>
2
+ * Copyright 2023 Angus Fenying <fenying@litert.org>
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
package/src/lib/Common.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2022 Angus Fenying <fenying@litert.org>
2
+ * Copyright 2023 Angus Fenying <fenying@litert.org>
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -15,6 +15,7 @@
15
15
  */
16
16
 
17
17
  export type ITypeChecker<T> = (v: unknown, errorTraces?: string[]) => v is T;
18
+ export type IPreDefinedTypeChecker<T> = (v: unknown, ...args: any[]) => v is T;
18
19
 
19
20
  /**
20
21
  * @deprecated Use `ITypeChecker` instead.
@@ -167,7 +168,7 @@ export interface ILanguageBuilder {
167
168
  */
168
169
  modOf(a: string, b: string): string;
169
170
 
170
- literal(val: string | boolean | number): string;
171
+ literal(val: string | boolean | number | null): string;
171
172
 
172
173
  /**
173
174
  * Get the statement checking if a string expression includes a given
@@ -249,7 +250,7 @@ export interface ILanguageBuilder {
249
250
  * @param expr The expression to be checked.
250
251
  * @param positive Assert positive or negative.
251
252
  */
252
- isStrucutre(expr: string, positive: boolean): string;
253
+ isStructure(expr: string, positive: boolean): string;
253
254
 
254
255
  /**
255
256
  * Get the statement checking if an expression is an integer value.
@@ -306,7 +307,7 @@ export interface ILanguageBuilder {
306
307
  stringLength(expr: string): string;
307
308
 
308
309
  /**
309
- * Get the statement of the keys list of an dicitionary.
310
+ * Get the statement of the keys list of an dictionary.
310
311
  *
311
312
  * @param expr The expression of dictionary.
312
313
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2022 Angus Fenying <fenying@litert.org>
2
+ * Copyright 2023 Angus Fenying <fenying@litert.org>
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -215,7 +215,7 @@ class Compiler implements C.ICompiler {
215
215
  break;
216
216
  }
217
217
 
218
- throw new TypeError('Unknwn rules.');
218
+ throw new TypeError('Unknown rules.');
219
219
  }
220
220
 
221
221
  private _compileStringRule(ctx: I.IContext, rule: string): string {
@@ -313,7 +313,7 @@ class Compiler implements C.ICompiler {
313
313
  ]);
314
314
  }
315
315
 
316
- if (rule.startsWith(I.PREDEF_TYPE_SYMBOL)) {
316
+ if (rule.startsWith(I.PRE_DEF_TYPE_SYMBOL)) {
317
317
 
318
318
  return this._usePredefinedType(ctx, rule.slice(1));
319
319
  }
@@ -360,19 +360,20 @@ class Compiler implements C.ICompiler {
360
360
 
361
361
  private _usePredefinedType(
362
362
  ctx: I.IContext,
363
- typeName: string
363
+ typeExpr: string
364
364
  ): string {
365
365
 
366
- this._validateTypeName(typeName);
366
+ const expr = I.decodePreDefinedCallExpr(typeExpr);
367
367
 
368
- ctx.referredTypes[typeName] = true;
368
+ ctx.referredTypes[expr.name] = true;
369
369
 
370
370
  return this._lang.call(
371
371
  this._lang.fieldIndex(
372
372
  ctx.typeSlotName,
373
- this._lang.literal(typeName)
373
+ this._lang.literal(expr.name)
374
374
  ),
375
- ctx.vName
375
+ ctx.vName,
376
+ ...expr.args.map(i => this._lang.literal(i))
376
377
  );
377
378
  }
378
379
 
@@ -383,7 +384,7 @@ class Compiler implements C.ICompiler {
383
384
 
384
385
  const assertRule = /^:([-\w]+):/.exec(rule);
385
386
 
386
- const offset = assertRule ? assertRule[1].length + 2 : 2;
387
+ const offset = (assertRule?.[1]?.length ?? 0) + 2;
387
388
 
388
389
  switch ((assertRule?.[1]) ?? rule.slice(0, 2)) {
389
390
  case '==':
@@ -546,7 +547,7 @@ class Compiler implements C.ICompiler {
546
547
 
547
548
  if (!rules.length) {
548
549
 
549
- throw new TypeError('Unknwon type "[]".');
550
+ throw new TypeError('Unknown type "[]".');
550
551
  }
551
552
 
552
553
  /**
@@ -617,6 +618,10 @@ class Compiler implements C.ICompiler {
617
618
 
618
619
  return this._compileModifierTYPE(ctx, rules.slice(1));
619
620
  }
621
+ case M.ENUM: {
622
+
623
+ return this._compileModifierEnum(ctx, rules.slice(1));
624
+ }
620
625
  }
621
626
 
622
627
  throw new TypeError(`Unknown modifier "${rules[0]}".`);
@@ -630,7 +635,7 @@ class Compiler implements C.ICompiler {
630
635
 
631
636
  const result = this._compileModifiedRule(ctx, rules);
632
637
 
633
- ctx.untrap();
638
+ ctx.popUp();
634
639
 
635
640
  return result;
636
641
  }
@@ -645,7 +650,7 @@ class Compiler implements C.ICompiler {
645
650
 
646
651
  result.push(this._compile(ctx, r));
647
652
 
648
- ctx.untrap();
653
+ ctx.popUp();
649
654
  }
650
655
 
651
656
  return this._lang.or(result);
@@ -687,6 +692,7 @@ class Compiler implements C.ICompiler {
687
692
  [CLOSURE_PARAM],
688
693
  [CLOSURE_ARG],
689
694
  this._lang.series([
695
+ // eslint-disable-next-line @litert/rules/disable-for-each-method
690
696
  this._lang.forEach(
691
697
  CLOSURE_PARAM, vIter, ctx.vName, this._lang.ifThen(
692
698
  this._lang.not(this._compile(ctx, rules)),
@@ -698,7 +704,7 @@ class Compiler implements C.ICompiler {
698
704
  ));
699
705
  }
700
706
 
701
- ctx.untrap();
707
+ ctx.popUp();
702
708
 
703
709
  return this._lang.and(result);
704
710
  }
@@ -819,6 +825,7 @@ class Compiler implements C.ICompiler {
819
825
  [CLOSURE_PARAM],
820
826
  [CLOSURE_ARG],
821
827
  this._lang.series([
828
+ // eslint-disable-next-line @litert/rules/disable-for-each-method
822
829
  this._lang.forEach(
823
830
  CLOSURE_PARAM, vIter, ctx.vName, this._lang.ifThen(
824
831
  this._lang.not(this._compile(ctx, rules.slice(1))),
@@ -830,7 +837,7 @@ class Compiler implements C.ICompiler {
830
837
  ));
831
838
  }
832
839
 
833
- ctx.untrap();
840
+ ctx.popUp();
834
841
 
835
842
  return this._lang.and(result);
836
843
  }
@@ -946,7 +953,7 @@ class Compiler implements C.ICompiler {
946
953
  tupleLength++;
947
954
  }
948
955
 
949
- ctx.untrap();
956
+ ctx.popUp();
950
957
  }
951
958
 
952
959
  if (tupleLength >= 0) {
@@ -975,23 +982,13 @@ class Compiler implements C.ICompiler {
975
982
  return this._lang.and(result);
976
983
  }
977
984
 
978
- private _validateTypeName(name: unknown): void {
979
-
980
- if (typeof name !== 'string' || !I.RE_VALID_CUSTOM_TYPE_NAME.test(name)) {
981
-
982
- throw new TypeError(`Invalid name ${
983
- JSON.stringify(name)
984
- } for a pre-defined type.`);
985
- }
986
- }
987
-
988
985
  private _compileModifierTYPE(ctx: I.IContext, rules: any[]): string {
989
986
 
990
- this._validateTypeName(rules[0]);
987
+ I.validateTypeName(rules[0]);
991
988
 
992
989
  if (this._defTypes[rules[0]]) {
993
990
 
994
- throw new Error(`Dplicated name ${JSON.stringify(rules[0])} for a pre-defined type.`);
991
+ throw new Error(`Duplicated name ${JSON.stringify(rules[0])} for a pre-defined type.`);
995
992
  }
996
993
 
997
994
  this._defTypes[rules[0]] = this.compile({
@@ -1015,7 +1012,7 @@ class Compiler implements C.ICompiler {
1015
1012
 
1016
1013
  const ret = this._compile(ctx, rules);
1017
1014
 
1018
- ctx.untrap();
1015
+ ctx.popUp();
1019
1016
 
1020
1017
  return ret;
1021
1018
  }
@@ -1033,7 +1030,7 @@ class Compiler implements C.ICompiler {
1033
1030
 
1034
1031
  const ret = this._compile(ctx, rules);
1035
1032
 
1036
- ctx.untrap();
1033
+ ctx.popUp();
1037
1034
 
1038
1035
  return ret;
1039
1036
  }
@@ -1057,7 +1054,7 @@ class Compiler implements C.ICompiler {
1057
1054
  ctx.tracePath = `${ctx.tracePath}[${this._lang.stringTemplateVar(vKey)}]`;
1058
1055
 
1059
1056
  const result = this._lang.and([
1060
- this._lang.isStrucutre(vCArg, true),
1057
+ this._lang.isStructure(vCArg, true),
1061
1058
  this._lang.closure(
1062
1059
  [vCParam],
1063
1060
  [vCArg],
@@ -1073,11 +1070,41 @@ class Compiler implements C.ICompiler {
1073
1070
  )
1074
1071
  ]);
1075
1072
 
1076
- ctx.untrap();
1073
+ ctx.popUp();
1077
1074
 
1078
1075
  return result;
1079
1076
  }
1080
1077
 
1078
+ private _compileModifierEnum(ctx: I.IContext, rules: any[]): string {
1079
+
1080
+ if (rules.length === 0) {
1081
+
1082
+ throw new SyntaxError(`At least one enum candidate is required for $.enum`);
1083
+ }
1084
+
1085
+ const ret: string[] = [];
1086
+
1087
+ for (const r of rules) {
1088
+
1089
+ switch (typeof r) {
1090
+
1091
+ case 'string':
1092
+ case 'number':
1093
+ case 'boolean':
1094
+ ret.push(this._lang.eq(ctx.vName, this._lang.literal(r)));
1095
+ break;
1096
+ default:
1097
+ if (r === null) {
1098
+ ret.push(this._lang.eq(ctx.vName, this._lang.literal(null)));
1099
+ break;
1100
+ }
1101
+ throw new SyntaxError(`Invalid literal value ${JSON.stringify(rules)} for $.enum.`);
1102
+ }
1103
+ }
1104
+
1105
+ return this._lang.or(ret);
1106
+ }
1107
+
1081
1108
  private _compileModifierDICT(ctx: I.IContext, rules: any[]): string {
1082
1109
 
1083
1110
  if (rules.length < 2 || !Array.isArray(rules[0])) {
@@ -1094,7 +1121,7 @@ class Compiler implements C.ICompiler {
1094
1121
  rules.slice(1)
1095
1122
  ]);
1096
1123
 
1097
- const type = `${I.PREDEF_TYPE_SYMBOL}${this._lang.varName(id)}`;
1124
+ const type = `${I.PRE_DEF_TYPE_SYMBOL}${this._lang.varName(id)}`;
1098
1125
 
1099
1126
  for (const key of rules[0]) {
1100
1127
 
@@ -1119,7 +1146,7 @@ class Compiler implements C.ICompiler {
1119
1146
  const result: string[] = [
1120
1147
  this._addTraceOr(
1121
1148
  ctx,
1122
- this._lang.isStrucutre(ctx.vName, true),
1149
+ this._lang.isStructure(ctx.vName, true),
1123
1150
  '!object'
1124
1151
  )
1125
1152
  ];
@@ -1212,7 +1239,7 @@ class Compiler implements C.ICompiler {
1212
1239
  this._compile(ctx, rule)
1213
1240
  ));
1214
1241
 
1215
- ctx.untrap();
1242
+ ctx.popUp();
1216
1243
  }
1217
1244
 
1218
1245
  if (strict && keys.length) {
@@ -1247,7 +1274,7 @@ class Compiler implements C.ICompiler {
1247
1274
  }
1248
1275
 
1249
1276
  const result: string[] = [
1250
- this._lang.isStrucutre(ctx.vName, true)
1277
+ this._lang.isStructure(ctx.vName, true)
1251
1278
  ];
1252
1279
 
1253
1280
  ctx.trap();
@@ -1364,7 +1391,7 @@ class Compiler implements C.ICompiler {
1364
1391
  ));
1365
1392
  }
1366
1393
 
1367
- ctx.untrap();
1394
+ ctx.popUp();
1368
1395
  }
1369
1396
 
1370
1397
  if (keys.length) {
@@ -1389,7 +1416,7 @@ class Compiler implements C.ICompiler {
1389
1416
  ])
1390
1417
  ));
1391
1418
 
1392
- ctx.untrap();
1419
+ ctx.popUp();
1393
1420
 
1394
1421
  return this._lang.and(result);
1395
1422
  }
@@ -1411,9 +1438,9 @@ class Compiler implements C.ICompiler {
1411
1438
  */
1412
1439
  export function createCompiler(lang: C.ILanguageBuilder): C.ICompiler {
1413
1440
 
1414
- const bitc = new BuiltInTypeCompiler(lang);
1441
+ const ret = new BuiltInTypeCompiler(lang);
1415
1442
 
1416
1443
  return new Compiler(
1417
- lang, bitc, new FilterCompiler(lang, bitc)
1444
+ lang, ret, new FilterCompiler(lang, ret)
1418
1445
  );
1419
1446
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2022 Angus Fenying <fenying@litert.org>
2
+ * Copyright 2023 Angus Fenying <fenying@litert.org>
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -71,7 +71,7 @@ export class Context implements i.IContext {
71
71
  }
72
72
  }
73
73
 
74
- public untrap(): void {
74
+ public popUp(): void {
75
75
 
76
76
  const prev = this.stack.pop();
77
77
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2022 Angus Fenying <fenying@litert.org>
2
+ * Copyright 2023 Angus Fenying <fenying@litert.org>
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@ implements I.IFilterCompiler {
22
22
 
23
23
  public constructor(
24
24
  private readonly _lang: C.ILanguageBuilder,
25
- private readonly _bitc: I.IBuiltInTypeCompiler
25
+ private readonly _memCompiler: I.IBuiltInTypeCompiler
26
26
  ) {}
27
27
 
28
28
  public compile(rule: string, ctx: I.IContext): string {
@@ -51,7 +51,7 @@ implements I.IFilterCompiler {
51
51
  ret.push(this._lang.isNumber(vName, true));
52
52
  break;
53
53
  default:
54
- ret.push(this._bitc.compile(filter[0], ctx, []));
54
+ ret.push(this._memCompiler.compile(filter[0], ctx, []));
55
55
  break;
56
56
  }
57
57
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2022 Angus Fenying <fenying@litert.org>
2
+ * Copyright 2023 Angus Fenying <fenying@litert.org>
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -50,7 +50,7 @@ export interface IInlineCompiler {
50
50
  * @param name The name of the pre-defined type (without prefix `@`)
51
51
  * @param checker The checker callback of the pre-defined type.
52
52
  */
53
- addPredefinedType<T>(name: string, checker: C.ITypeChecker<T>): this;
53
+ addPredefinedType<T>(name: string, checker: C.IPreDefinedTypeChecker<T>): this;
54
54
 
55
55
  /**
56
56
  * Check if a pre-defined type is compiled.
@@ -91,12 +91,12 @@ implements IInlineCompiler {
91
91
 
92
92
  const result = this._compiler.compile(options);
93
93
 
94
- this._preapreDefinedTypes(result.referredTypes, options.stopOnEntry);
94
+ this._prepareDefinedTypes(result.referredTypes, options.stopOnEntry);
95
95
 
96
96
  return this._wrapCheckerCode(result, options.stopOnEntry);
97
97
  }
98
98
 
99
- private _preapreDefinedTypes(
99
+ private _prepareDefinedTypes(
100
100
  types: string[],
101
101
  stopOnEntry?: boolean
102
102
  ): void {
@@ -118,7 +118,7 @@ implements IInlineCompiler {
118
118
 
119
119
  this._defTypes[x] = this._wrapCheckerCode(info, stopOnEntry);
120
120
 
121
- this._preapreDefinedTypes(info.referredTypes);
121
+ this._prepareDefinedTypes(info.referredTypes);
122
122
 
123
123
  delete this._missingTypes[x];
124
124
  }
@@ -126,10 +126,7 @@ implements IInlineCompiler {
126
126
 
127
127
  public addPredefinedType(name: string, checker: C.ITypeChecker<any>): this {
128
128
 
129
- if (!I.RE_VALID_CUSTOM_TYPE_NAME.test(name)) {
130
-
131
- throw new TypeError(`Invalid name ${ JSON.stringify(name) } for a pre-defined type.`);
132
- }
129
+ I.validateTypeName(name);
133
130
 
134
131
  this._defTypes[name] = checker;
135
132
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2022 Angus Fenying <fenying@litert.org>
2
+ * Copyright 2023 Angus Fenying <fenying@litert.org>
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@ export const FILTER_PREFIX = '|';
24
24
 
25
25
  export const IMPLICIT_SYMBOL = '?';
26
26
 
27
- export const PREDEF_TYPE_SYMBOL = '@';
27
+ export const PRE_DEF_TYPE_SYMBOL = '@';
28
28
 
29
29
  export const NEGATIVE_SYMBOL = '!';
30
30
 
@@ -95,7 +95,7 @@ export interface IContext extends IContextData {
95
95
 
96
96
  trap(subjChanged?: boolean): void;
97
97
 
98
- untrap(): void;
98
+ popUp(): void;
99
99
  }
100
100
 
101
101
  export interface IFilterCompiler {
@@ -126,4 +126,73 @@ export interface IBuiltInTypeCompiler {
126
126
  isElemental(type: string): boolean;
127
127
  }
128
128
 
129
- export const RE_VALID_CUSTOM_TYPE_NAME = /^[-:.\w]+$/;
129
+ const RE_VALID_CUSTOM_TYPE_NAME = /^[-:.\w]+$/;
130
+
131
+ export interface IPreDefinedCallExpr {
132
+
133
+ name: string;
134
+
135
+ args: any[];
136
+ }
137
+
138
+ export function validateTypeName(name: string): void {
139
+
140
+ if (typeof name !== 'string' || !RE_VALID_CUSTOM_TYPE_NAME.test(name)) {
141
+
142
+ throw new TypeError(`Invalid name ${
143
+ JSON.stringify(name)
144
+ } for a pre-defined type.`);
145
+ }
146
+ }
147
+
148
+ export function decodePreDefinedCallExpr(input: string): IPreDefinedCallExpr {
149
+
150
+ let expr = input;
151
+
152
+ expr = expr.replace(/\\['"]/g, (i) => `\\u00${i.charCodeAt(1).toString(16)}`);
153
+
154
+ const r = /^([-:.\w]+)\s*(\((.*)\))?$/.exec(expr);
155
+
156
+ if (!r) {
157
+
158
+ throw new SyntaxError(`Invalid type expression: ${input}`);
159
+ }
160
+
161
+ const fn = r[1];
162
+
163
+ expr = r[3];
164
+
165
+ if (!expr) {
166
+
167
+ return { name: fn, args: [] };
168
+ }
169
+
170
+ const args = [];
171
+
172
+ while (expr) {
173
+
174
+ const m = /^\s*([-]?\d+(\.\d+)?|[-]?0x[a-fA-F0-9]+|true|false|null|"[^"]+"|'[^']+')\s*(,|$)/i.exec(expr);
175
+
176
+ if (!m) {
177
+
178
+ throw new SyntaxError(`Invalid type expression "${expr}" in "${input}"`);
179
+ }
180
+
181
+ expr = expr.slice(m[0].length);
182
+
183
+ if (m[1].startsWith("'") && m[1].endsWith("'")) {
184
+ args.push(JSON.parse(`"${m[1].slice(1, -1)}"`));
185
+ }
186
+ else if (m[1].startsWith('0x')) {
187
+ args.push(parseInt(m[1].slice(2), 16));
188
+ }
189
+ else if (m[1].startsWith('-0x')) {
190
+ args.push(-parseInt(m[1].slice(3), 16));
191
+ }
192
+ else {
193
+ args.push(JSON.parse(m[1]));
194
+ }
195
+ }
196
+
197
+ return { name: fn, args };
198
+ }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2022 Angus Fenying <fenying@litert.org>
2
+ * Copyright 2023 Angus Fenying <fenying@litert.org>
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -43,3 +43,5 @@ export const EQUAL: string = `${I.MODIFIER_PREFIX}equal`;
43
43
  export const TAG: string = `${I.MODIFIER_PREFIX}tag`;
44
44
 
45
45
  export const TYPE: string = `${I.MODIFIER_PREFIX}type`;
46
+
47
+ export const ENUM: string = `${I.MODIFIER_PREFIX}enum`;
package/src/lib/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2022 Angus Fenying <fenying@litert.org>
2
+ * Copyright 2023 Angus Fenying <fenying@litert.org>
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2022 Angus Fenying <fenying@litert.org>
2
+ * Copyright 2023 Angus Fenying <fenying@litert.org>
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -227,7 +227,7 @@ implements C.ILanguageBuilder {
227
227
  return `typeof ${vn} ${this._equal(positive)} "string"`;
228
228
  }
229
229
 
230
- public isStrucutre(vn: string, positive: boolean = true): string {
230
+ public isStructure(vn: string, positive: boolean = true): string {
231
231
 
232
232
  return positive ?
233
233
  `(typeof ${vn} === "object" && ${vn} !== null && !Array.isArray(${vn}))` :
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2022 Angus Fenying <fenying@litert.org>
2
+ * Copyright 2023 Angus Fenying <fenying@litert.org>
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.