@nudojs/cli 0.2.1 → 0.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.
Files changed (58) hide show
  1. package/package.json +12 -7
  2. package/src/abs-route.ts +273 -0
  3. package/src/builtins/builtin-prototype.ts +279 -0
  4. package/src/builtins/builtin-static.ts +260 -0
  5. package/src/eval-binary.ts +113 -0
  6. package/src/evaluator-api.ts +3 -0
  7. package/src/evaluator.ts +174 -633
  8. package/src/index.ts +373 -270
  9. package/src/narrowing.ts +7 -0
  10. package/src/phi-from-test.ts +42 -0
  11. package/src/run-test.ts +92 -0
  12. package/src/term-registry.ts +96 -0
  13. package/CHANGELOG.md +0 -41
  14. package/dist/chunk-3HCPXPEW.js +0 -5286
  15. package/dist/evaluator-api.d.ts +0 -151
  16. package/dist/evaluator-api.js +0 -214
  17. package/dist/index.d.ts +0 -2
  18. package/dist/index.js +0 -4035
  19. package/examples/real-world.js +0 -66
  20. package/examples/validate-real-world.ts +0 -160
  21. package/src/__tests__/builtin-advanced.test.ts +0 -292
  22. package/src/__tests__/builtin-api.test.ts +0 -308
  23. package/src/__tests__/builtin-functions.test.ts +0 -313
  24. package/src/__tests__/builtin-map.test.ts +0 -129
  25. package/src/__tests__/builtin-promise.test.ts +0 -150
  26. package/src/__tests__/builtin-regexp.test.ts +0 -133
  27. package/src/__tests__/builtin-set.test.ts +0 -163
  28. package/src/__tests__/builtin-url.test.ts +0 -256
  29. package/src/__tests__/builtin-web.test.ts +0 -340
  30. package/src/__tests__/combination-scenarios.test.ts +0 -384
  31. package/src/__tests__/edge-cases.test.ts +0 -749
  32. package/src/__tests__/evaluator-loops.test.ts +0 -283
  33. package/src/__tests__/evaluator-nullish-coalescing.test.ts +0 -86
  34. package/src/__tests__/evaluator-optional-chaining.test.ts +0 -37
  35. package/src/__tests__/evaluator-phase2.test.ts +0 -564
  36. package/src/__tests__/evaluator-phase3.test.ts +0 -864
  37. package/src/__tests__/evaluator-refined.test.ts +0 -121
  38. package/src/__tests__/evaluator-string-methods.test.ts +0 -151
  39. package/src/__tests__/evaluator.test.ts +0 -943
  40. package/src/__tests__/mock-arrow-function.test.ts +0 -169
  41. package/src/__tests__/mock-comparison.test.ts +0 -221
  42. package/src/__tests__/mock-comprehensive.test.ts +0 -250
  43. package/src/__tests__/mock-final-integration.test.ts +0 -263
  44. package/src/__tests__/mock-helpers.test.ts +0 -174
  45. package/src/__tests__/mock-realworld.test.ts +0 -191
  46. package/src/__tests__/mock-rest-debug.test.ts +0 -110
  47. package/src/__tests__/mock-rest-edge.test.ts +0 -176
  48. package/src/__tests__/mock-sinon-runtime.test.ts +0 -168
  49. package/src/__tests__/narrowing-discriminated.test.ts +0 -35
  50. package/src/__tests__/narrowing-in-operator.test.ts +0 -56
  51. package/src/__tests__/narrowing-switch.test.ts +0 -56
  52. package/src/__tests__/narrowing-truthiness.test.ts +0 -52
  53. package/src/__tests__/narrowing.test.ts +0 -82
  54. package/src/__tests__/nudo-mock-syntax.test.ts +0 -245
  55. package/src/__tests__/realworld-patterns.test.ts +0 -430
  56. package/src/__tests__/syntax-sugar.test.ts +0 -345
  57. package/src/builtins/index.ts +0 -61
  58. package/tsconfig.json +0 -9
@@ -1,129 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { parse, extractDirectives, type CaseDirective } from "@nudojs/parser";
3
- import { typeValueToString, createEnvironment, T } from "@nudojs/core";
4
- import { evaluateFunctionFull } from "../evaluator.js";
5
-
6
- function runTest(source: string): { name: string; caseName: string; result: string }[] {
7
- const ast = parse(source);
8
- const directives = extractDirectives(ast);
9
- const env = createEnvironment();
10
- const results: { name: string; caseName: string; result: string }[] = [];
11
-
12
- for (const fn of directives) {
13
- const caseDirectives = fn.directives.filter((d): d is CaseDirective => d.kind === "case");
14
- for (const dir of caseDirectives) {
15
- const result = evaluateFunctionFull(fn.node, dir.args, env);
16
- results.push({ name: fn.name, caseName: dir.name, result: typeValueToString(result.value) });
17
- }
18
- }
19
- return results;
20
- }
21
-
22
- describe("Built-in Map API", () => {
23
- it("new Map() should create a Map instance", () => {
24
- const results = runTest(`
25
- // @nudo:case "new-map" ()
26
- function fn() {
27
- const m = new Map();
28
- return m;
29
- }
30
- `);
31
- expect(results[0].result).toContain("Map");
32
- });
33
-
34
- it("Map.get() should return V | undefined (unknown when V is unknown)", () => {
35
- const results = runTest(`
36
- // @nudo:case "get" ()
37
- function fn() {
38
- const m = new Map();
39
- return m.get("key");
40
- }
41
- `);
42
- // When V is unknown, unknown | undefined simplifies to unknown
43
- expect(results[0].result).toBe("unknown");
44
- });
45
-
46
- it("Map.has() should return boolean", () => {
47
- const results = runTest(`
48
- // @nudo:case "has" ()
49
- function fn() {
50
- const m = new Map();
51
- return m.has("key");
52
- }
53
- `);
54
- expect(results[0].result).toBe("boolean");
55
- });
56
-
57
- it("Map.size should return number", () => {
58
- const results = runTest(`
59
- // @nudo:case "size" ()
60
- function fn() {
61
- const m = new Map();
62
- return m.size;
63
- }
64
- `);
65
- expect(results[0].result).toBe("number");
66
- });
67
-
68
- it("arrow function case argument works as Array.map callback", () => {
69
- const results = runTest(`
70
- // @nudo:case "double" ([1, 2, 3], (a) => a * 2)
71
- function doubleAll(items, cb) {
72
- return items.map(cb);
73
- }
74
- `);
75
- expect(results[0].result).toBe("[2, 4, 6]");
76
- });
77
-
78
- it("Map.get() hits literal keys recorded at construction", () => {
79
- const results = runTest(`
80
- // @nudo:case "lookup-table" ()
81
- function fn() {
82
- const typeMap = new Map([['[object Map]', 1], ['[object Set]', 2]]);
83
- return [typeMap.get('[object Set]'), typeMap.get('[object Object]')];
84
- }
85
- `);
86
- // Precise hit returns the stored value; miss returns undefined
87
- expect(results[0].result).toBe("[2, undefined]");
88
- });
89
-
90
- it("Map.get() tracks keys stored via set()", () => {
91
- const results = runTest(`
92
- // @nudo:case "seen-cache" ()
93
- function fn() {
94
- const seen = new Map();
95
- seen.set('obj', 'clone');
96
- return seen.get('obj');
97
- }
98
- `);
99
- expect(results[0].result).toBe('"clone"');
100
- });
101
-
102
- it("Map.has() decides literally for recorded keys", () => {
103
- const results = runTest(`
104
- // @nudo:case "has-literal" ()
105
- function fn() {
106
- const m = new Map([['a', 1]]);
107
- return m.has('a');
108
- }
109
- `);
110
- expect(results[0].result).toBe("true");
111
- });
112
-
113
- it("for-of on a Map instance iterates [key, value] tuples", () => {
114
- const results = runTest(`
115
- // @nudo:case "forof-entries" ()
116
- function fn() {
117
- const m = new Map([['a', 1], ['b', 2]]);
118
- const keys = [];
119
- const values = [];
120
- for (const [k, v] of m) {
121
- keys.push(k);
122
- values.push(v);
123
- }
124
- return [keys, values];
125
- }
126
- `);
127
- expect(results[0].result).toBe('[["a", "b"], [1, 2]]');
128
- });
129
- });
@@ -1,150 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { parse, extractDirectives, type CaseDirective } from "@nudojs/parser";
3
- import { typeValueToString, createEnvironment, T } from "@nudojs/core";
4
- import { evaluateFunctionFull } from "../evaluator.js";
5
-
6
- function runTest(source: string): { name: string; caseName: string; result: string }[] {
7
- const ast = parse(source);
8
- const directives = extractDirectives(ast);
9
- const env = createEnvironment();
10
- const results: { name: string; caseName: string; result: string }[] = [];
11
-
12
- for (const fn of directives) {
13
- const caseDirectives = fn.directives.filter((d): d is CaseDirective => d.kind === "case");
14
- for (const dir of caseDirectives) {
15
- const result = evaluateFunctionFull(fn.node, dir.args, env);
16
- results.push({
17
- name: fn.name,
18
- caseName: dir.name,
19
- result: typeValueToString(result.value),
20
- });
21
- }
22
- }
23
- return results;
24
- }
25
-
26
- describe("Built-in Promise API", () => {
27
- it("Promise.resolve(v) should return Promise<T>", () => {
28
- const results = runTest(`
29
- // @nudo:case "resolve" (42)
30
- function fn(x) {
31
- return Promise.resolve(x);
32
- }
33
- `);
34
- expect(results[0].result).toBe("Promise<42>");
35
- });
36
-
37
- it("Promise.reject(v) should return Promise<never>", () => {
38
- const results = runTest(`
39
- // @nudo:case "reject" ()
40
- function fn() {
41
- return Promise.reject(new Error("fail"));
42
- }
43
- `);
44
- expect(results[0].result).toBe("Promise<never>");
45
- });
46
-
47
- it("Promise.all([...]) should return Promise<[T1, T2]> (tuple)", () => {
48
- const results = runTest(`
49
- // @nudo:case "all" ()
50
- function fn() {
51
- return Promise.all([Promise.resolve(1), Promise.resolve(2)]);
52
- }
53
- `);
54
- expect(results[0].result).toBe("Promise<[1, 2]>");
55
- });
56
-
57
- it("Promise.race([...]) should return Promise<T>", () => {
58
- const results = runTest(`
59
- // @nudo:case "race" ()
60
- function fn() {
61
- return Promise.race([Promise.resolve("a"), Promise.resolve("b")]);
62
- }
63
- `);
64
- expect(results[0].result).toContain("Promise");
65
- });
66
-
67
- it(".then() should return Promise<T>", () => {
68
- const results = runTest(`
69
- // @nudo:case "then" ()
70
- function fn() {
71
- return Promise.resolve(42).then(x => x);
72
- }
73
- `);
74
- expect(results[0].result).toContain("Promise");
75
- });
76
-
77
- it("new Promise with resolve inside setTimeout callback should resolve via static site scan", () => {
78
- const results = runTest(`
79
- // @nudo:case "ctor-async-site" ()
80
- function fn() {
81
- return new Promise((resolve) => {
82
- setTimeout(() => resolve('x'), 1);
83
- });
84
- }
85
- `);
86
- expect(results[0].result).toBe('Promise<"x">');
87
- });
88
-
89
- it("new Promise with direct synchronous resolve should return Promise<42>", () => {
90
- const results = runTest(`
91
- // @nudo:case "ctor-sync" ()
92
- function fn() {
93
- return new Promise((resolve) => resolve(42));
94
- }
95
- `);
96
- expect(results[0].result).toBe("Promise<42>");
97
- });
98
-
99
- it("new Promise with never-resolving executor should return Promise<never>", () => {
100
- const results = runTest(`
101
- // @nudo:case "ctor-never" ()
102
- function fn() {
103
- return new Promise(() => {});
104
- }
105
- `);
106
- expect(results[0].result).toBe("Promise<never>");
107
- });
108
-
109
- it("new Promise with non-function executor should return Promise<unknown>", () => {
110
- const results = runTest(`
111
- // @nudo:case "ctor-nonfn" ()
112
- function fn(x) {
113
- return new Promise(x);
114
- }
115
- `);
116
- expect(results[0].result).toBe("Promise<unknown>");
117
- });
118
-
119
- it("new Promise should evaluate resolve argument in the executor closure scope", () => {
120
- const results = runTest(`
121
- // @nudo:case "ctor-outer-value" (7)
122
- function fn(returnValue) {
123
- return new Promise((resolve) => {
124
- setTimeout(() => resolve(returnValue), 1);
125
- });
126
- }
127
- `);
128
- expect(results[0].result).toBe("Promise<7>");
129
- });
130
-
131
- it(".then(cb) end-to-end should propagate the callback's return type", () => {
132
- const results = runTest(`
133
- // @nudo:case "then-chain" (7)
134
- function fn(v) {
135
- return Promise.resolve(v).then(x => [x, x]);
136
- }
137
- `);
138
- expect(results[0].result).toBe("Promise<[7, 7]>");
139
- });
140
-
141
- it("new Promise result should chain through .then", () => {
142
- const results = runTest(`
143
- // @nudo:case "ctor-then" ()
144
- function fn() {
145
- return new Promise((resolve) => resolve('done')).then(x => x);
146
- }
147
- `);
148
- expect(results[0].result).toBe('Promise<"done">');
149
- });
150
- });
@@ -1,133 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { parse, extractDirectives, type CaseDirective } from "@nudojs/parser";
3
- import { typeValueToString, createEnvironment, T } from "@nudojs/core";
4
- import { evaluateFunctionFull } from "../evaluator.js";
5
-
6
- function runTest(source: string): { name: string; caseName: string; result: string }[] {
7
- const ast = parse(source);
8
- const directives = extractDirectives(ast);
9
- const env = createEnvironment();
10
- const results: { name: string; caseName: string; result: string }[] = [];
11
-
12
- for (const fn of directives) {
13
- const caseDirectives = fn.directives.filter((d): d is CaseDirective => d.kind === "case");
14
- for (const dir of caseDirectives) {
15
- const result = evaluateFunctionFull(fn.node, dir.args, env);
16
- results.push({ name: fn.name, caseName: dir.name, result: typeValueToString(result.value) });
17
- }
18
- }
19
- return results;
20
- }
21
-
22
- describe("Built-in RegExp API", () => {
23
- it("RegExp literal should create a RegExp instance", () => {
24
- const results = runTest(`
25
- // @nudo:case "regexp-literal" ()
26
- function fn() {
27
- const re = /abc/gi;
28
- return re;
29
- }
30
- `);
31
- expect(results[0].result).toContain("RegExp");
32
- });
33
-
34
- it("new RegExp() should create a RegExp instance", () => {
35
- const results = runTest(`
36
- // @nudo:case "new-regexp" ()
37
- function fn() {
38
- const re = new RegExp("abc");
39
- return re;
40
- }
41
- `);
42
- expect(results[0].result).toContain("RegExp");
43
- });
44
-
45
- it("RegExp.test() should return boolean", () => {
46
- const results = runTest(`
47
- // @nudo:case "test" ()
48
- function fn() {
49
- const re = /abc/;
50
- return re.test("abcdef");
51
- }
52
- `);
53
- expect(results[0].result).toBe("boolean");
54
- });
55
-
56
- it("RegExp.source should return string", () => {
57
- const results = runTest(`
58
- // @nudo:case "source" ()
59
- function fn() {
60
- const re = /abc/gi;
61
- return re.source;
62
- }
63
- `);
64
- expect(results[0].result).toBe("string");
65
- });
66
-
67
- it("RegExp.flags should return string", () => {
68
- const results = runTest(`
69
- // @nudo:case "flags" ()
70
- function fn() {
71
- const re = /abc/gi;
72
- return re.flags;
73
- }
74
- `);
75
- expect(results[0].result).toBe("string");
76
- });
77
-
78
- it("RegExp.global should return boolean", () => {
79
- const results = runTest(`
80
- // @nudo:case "global" ()
81
- function fn() {
82
- const re = /abc/g;
83
- return re.global;
84
- }
85
- `);
86
- expect(results[0].result).toBe("boolean");
87
- });
88
-
89
- it("RegExp.ignoreCase should return boolean", () => {
90
- const results = runTest(`
91
- // @nudo:case "ignoreCase" ()
92
- function fn() {
93
- const re = /abc/i;
94
- return re.ignoreCase;
95
- }
96
- `);
97
- expect(results[0].result).toBe("boolean");
98
- });
99
-
100
- it("RegExp.multiline should return boolean", () => {
101
- const results = runTest(`
102
- // @nudo:case "multiline" ()
103
- function fn() {
104
- const re = /abc/m;
105
- return re.multiline;
106
- }
107
- `);
108
- expect(results[0].result).toBe("boolean");
109
- });
110
-
111
- it("RegExp.exec() should return union of null and object", () => {
112
- const results = runTest(`
113
- // @nudo:case "exec" ()
114
- function fn() {
115
- const re = /abc/;
116
- return re.exec("abcdef");
117
- }
118
- `);
119
- expect(results[0].result).toContain("null");
120
- expect(results[0].result).toContain("{}");
121
- });
122
-
123
- it("RegExp.toString() should return string", () => {
124
- const results = runTest(`
125
- // @nudo:case "toString" ()
126
- function fn() {
127
- const re = /abc/gi;
128
- return re.toString();
129
- }
130
- `);
131
- expect(results[0].result).toBe("string");
132
- });
133
- });
@@ -1,163 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { parse, extractDirectives, type CaseDirective } from "@nudojs/parser";
3
- import { typeValueToString, createEnvironment, T } from "@nudojs/core";
4
- import { evaluateFunctionFull } from "../evaluator.js";
5
-
6
- function runTest(source: string): { name: string; caseName: string; result: string }[] {
7
- const ast = parse(source);
8
- const directives = extractDirectives(ast);
9
- const env = createEnvironment();
10
- const results: { name: string; caseName: string; result: string }[] = [];
11
-
12
- for (const fn of directives) {
13
- const caseDirectives = fn.directives.filter((d): d is CaseDirective => d.kind === "case");
14
- for (const dir of caseDirectives) {
15
- const result = evaluateFunctionFull(fn.node, dir.args, env);
16
- results.push({ name: fn.name, caseName: dir.name, result: typeValueToString(result.value) });
17
- }
18
- }
19
- return results;
20
- }
21
-
22
- describe("Built-in Set API", () => {
23
- it("new Set() should create a Set instance", () => {
24
- const results = runTest(`
25
- // @nudo:case "new-set" ()
26
- function fn() {
27
- const s = new Set();
28
- return s;
29
- }
30
- `);
31
- expect(results[0].result).toContain("Set");
32
- });
33
-
34
- it("Set.has() should return boolean", () => {
35
- const results = runTest(`
36
- // @nudo:case "has" ()
37
- function fn() {
38
- const s = new Set();
39
- return s.has("key");
40
- }
41
- `);
42
- expect(results[0].result).toBe("boolean");
43
- });
44
-
45
- it("Set.size should return number", () => {
46
- const results = runTest(`
47
- // @nudo:case "size" ()
48
- function fn() {
49
- const s = new Set();
50
- return s.size;
51
- }
52
- `);
53
- expect(results[0].result).toBe("number");
54
- });
55
-
56
- it("Set.add() should return the Set instance", () => {
57
- const results = runTest(`
58
- // @nudo:case "add" ()
59
- function fn() {
60
- const s = new Set();
61
- return s.add(42);
62
- }
63
- `);
64
- expect(results[0].result).toContain("Set");
65
- });
66
-
67
- it("new Set([1, 2, 3]) should infer element type", () => {
68
- const results = runTest(`
69
- // @nudo:case "from-array" ()
70
- function fn() {
71
- const s = new Set([1, 2, 3]);
72
- return s;
73
- }
74
- `);
75
- expect(results[0].result).toContain("Set");
76
- });
77
-
78
- it("Set.delete() should return boolean", () => {
79
- const results = runTest(`
80
- // @nudo:case "delete" ()
81
- function fn() {
82
- const s = new Set();
83
- return s.delete("key");
84
- }
85
- `);
86
- expect(results[0].result).toBe("boolean");
87
- });
88
-
89
- it("Set.clear() should return undefined", () => {
90
- const results = runTest(`
91
- // @nudo:case "clear" ()
92
- function fn() {
93
- const s = new Set();
94
- return s.clear();
95
- }
96
- `);
97
- expect(results[0].result).toBe("undefined");
98
- });
99
-
100
- it("Set.has() decides literally for recorded values", () => {
101
- const results = runTest(`
102
- // @nudo:case "has-literal" ()
103
- function fn() {
104
- const s = new Set(['a', 'b']);
105
- return [s.has('a'), s.has('z')];
106
- }
107
- `);
108
- expect(results[0].result).toBe("[true, false]");
109
- });
110
-
111
- it("Set.has() decides prototype singletons by identity", () => {
112
- const results = runTest(`
113
- // @nudo:case "has-proto" ()
114
- function fn() {
115
- const protoHack = new Set([Map.prototype, Set.prototype]);
116
- return protoHack.has(Object.prototype);
117
- }
118
- `);
119
- expect(results[0].result).toBe("false");
120
- });
121
-
122
- it("for-of on a Set instance iterates its recorded values", () => {
123
- const results = runTest(`
124
- // @nudo:case "forof-values" ()
125
- function fn() {
126
- const s = new Set([1, 2]);
127
- const out = [];
128
- for (const v of s) {
129
- out.push(v);
130
- }
131
- return out;
132
- }
133
- `);
134
- expect(results[0].result).toBe("[1, 2]");
135
- });
136
-
137
- it("Set.prototype.values.call(s) iterates like s.values()", () => {
138
- const results = runTest(`
139
- // @nudo:case "proto-values-call" ()
140
- function fn() {
141
- const s = new Set([1, 2]);
142
- const out = [];
143
- for (const v of Set.prototype.values.call(s)) {
144
- out.push(v);
145
- }
146
- return out;
147
- }
148
- `);
149
- expect(results[0].result).toBe("[1, 2]");
150
- });
151
-
152
- it("Set.delete() decides literally against recorded values and size stays number", () => {
153
- const results = runTest(`
154
- // @nudo:case "delete-literal" ()
155
- function fn() {
156
- const s = new Set([1, 2, 3]);
157
- const hit = s.delete(2);
158
- return [hit, s.size];
159
- }
160
- `);
161
- expect(results[0].result).toBe("[true, number]");
162
- });
163
- });