@nudojs/cli 0.2.1 → 0.3.1

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 (64) hide show
  1. package/dist/{chunk-3HCPXPEW.js → chunk-YDM4HHQ4.js} +1783 -1421
  2. package/dist/evaluator-api.d.ts +12 -1
  3. package/dist/evaluator-api.js +52 -2
  4. package/dist/index.d.ts +1 -2
  5. package/dist/index.js +366 -3572
  6. package/package.json +23 -11
  7. package/CHANGELOG.md +0 -41
  8. package/examples/real-world.js +0 -66
  9. package/examples/validate-real-world.ts +0 -160
  10. package/src/__tests__/builtin-advanced.test.ts +0 -292
  11. package/src/__tests__/builtin-api.test.ts +0 -308
  12. package/src/__tests__/builtin-functions.test.ts +0 -313
  13. package/src/__tests__/builtin-map.test.ts +0 -129
  14. package/src/__tests__/builtin-promise.test.ts +0 -150
  15. package/src/__tests__/builtin-regexp.test.ts +0 -133
  16. package/src/__tests__/builtin-set.test.ts +0 -163
  17. package/src/__tests__/builtin-url.test.ts +0 -256
  18. package/src/__tests__/builtin-web.test.ts +0 -340
  19. package/src/__tests__/combination-scenarios.test.ts +0 -384
  20. package/src/__tests__/edge-cases.test.ts +0 -749
  21. package/src/__tests__/evaluator-loops.test.ts +0 -283
  22. package/src/__tests__/evaluator-nullish-coalescing.test.ts +0 -86
  23. package/src/__tests__/evaluator-optional-chaining.test.ts +0 -37
  24. package/src/__tests__/evaluator-phase2.test.ts +0 -564
  25. package/src/__tests__/evaluator-phase3.test.ts +0 -864
  26. package/src/__tests__/evaluator-refined.test.ts +0 -121
  27. package/src/__tests__/evaluator-string-methods.test.ts +0 -151
  28. package/src/__tests__/evaluator.test.ts +0 -943
  29. package/src/__tests__/mock-arrow-function.test.ts +0 -169
  30. package/src/__tests__/mock-comparison.test.ts +0 -221
  31. package/src/__tests__/mock-comprehensive.test.ts +0 -250
  32. package/src/__tests__/mock-final-integration.test.ts +0 -263
  33. package/src/__tests__/mock-helpers.test.ts +0 -174
  34. package/src/__tests__/mock-realworld.test.ts +0 -191
  35. package/src/__tests__/mock-rest-debug.test.ts +0 -110
  36. package/src/__tests__/mock-rest-edge.test.ts +0 -176
  37. package/src/__tests__/mock-sinon-runtime.test.ts +0 -168
  38. package/src/__tests__/narrowing-discriminated.test.ts +0 -35
  39. package/src/__tests__/narrowing-in-operator.test.ts +0 -56
  40. package/src/__tests__/narrowing-switch.test.ts +0 -56
  41. package/src/__tests__/narrowing-truthiness.test.ts +0 -52
  42. package/src/__tests__/narrowing.test.ts +0 -82
  43. package/src/__tests__/nudo-mock-syntax.test.ts +0 -245
  44. package/src/__tests__/realworld-patterns.test.ts +0 -430
  45. package/src/__tests__/syntax-sugar.test.ts +0 -345
  46. package/src/builtins/builtin-intl.ts +0 -17
  47. package/src/builtins/builtin-map.ts +0 -174
  48. package/src/builtins/builtin-promise.ts +0 -116
  49. package/src/builtins/builtin-reflect.ts +0 -30
  50. package/src/builtins/builtin-regexp.ts +0 -34
  51. package/src/builtins/builtin-set.ts +0 -131
  52. package/src/builtins/builtin-symbol.ts +0 -16
  53. package/src/builtins/builtin-url.ts +0 -58
  54. package/src/builtins/builtin-weak.ts +0 -22
  55. package/src/builtins/builtin-web.ts +0 -111
  56. package/src/builtins/index.ts +0 -61
  57. package/src/config.ts +0 -32
  58. package/src/env-loader.ts +0 -174
  59. package/src/evaluator-api.ts +0 -36
  60. package/src/evaluator.ts +0 -5623
  61. package/src/index.ts +0 -931
  62. package/src/narrowing.ts +0 -537
  63. package/src/resolve-npm.ts +0 -63
  64. 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
- });