@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.
- package/dist/{chunk-3HCPXPEW.js → chunk-YDM4HHQ4.js} +1783 -1421
- package/dist/evaluator-api.d.ts +12 -1
- package/dist/evaluator-api.js +52 -2
- package/dist/index.d.ts +1 -2
- package/dist/index.js +366 -3572
- package/package.json +23 -11
- package/CHANGELOG.md +0 -41
- package/examples/real-world.js +0 -66
- package/examples/validate-real-world.ts +0 -160
- package/src/__tests__/builtin-advanced.test.ts +0 -292
- package/src/__tests__/builtin-api.test.ts +0 -308
- package/src/__tests__/builtin-functions.test.ts +0 -313
- package/src/__tests__/builtin-map.test.ts +0 -129
- package/src/__tests__/builtin-promise.test.ts +0 -150
- package/src/__tests__/builtin-regexp.test.ts +0 -133
- package/src/__tests__/builtin-set.test.ts +0 -163
- package/src/__tests__/builtin-url.test.ts +0 -256
- package/src/__tests__/builtin-web.test.ts +0 -340
- package/src/__tests__/combination-scenarios.test.ts +0 -384
- package/src/__tests__/edge-cases.test.ts +0 -749
- package/src/__tests__/evaluator-loops.test.ts +0 -283
- package/src/__tests__/evaluator-nullish-coalescing.test.ts +0 -86
- package/src/__tests__/evaluator-optional-chaining.test.ts +0 -37
- package/src/__tests__/evaluator-phase2.test.ts +0 -564
- package/src/__tests__/evaluator-phase3.test.ts +0 -864
- package/src/__tests__/evaluator-refined.test.ts +0 -121
- package/src/__tests__/evaluator-string-methods.test.ts +0 -151
- package/src/__tests__/evaluator.test.ts +0 -943
- package/src/__tests__/mock-arrow-function.test.ts +0 -169
- package/src/__tests__/mock-comparison.test.ts +0 -221
- package/src/__tests__/mock-comprehensive.test.ts +0 -250
- package/src/__tests__/mock-final-integration.test.ts +0 -263
- package/src/__tests__/mock-helpers.test.ts +0 -174
- package/src/__tests__/mock-realworld.test.ts +0 -191
- package/src/__tests__/mock-rest-debug.test.ts +0 -110
- package/src/__tests__/mock-rest-edge.test.ts +0 -176
- package/src/__tests__/mock-sinon-runtime.test.ts +0 -168
- package/src/__tests__/narrowing-discriminated.test.ts +0 -35
- package/src/__tests__/narrowing-in-operator.test.ts +0 -56
- package/src/__tests__/narrowing-switch.test.ts +0 -56
- package/src/__tests__/narrowing-truthiness.test.ts +0 -52
- package/src/__tests__/narrowing.test.ts +0 -82
- package/src/__tests__/nudo-mock-syntax.test.ts +0 -245
- package/src/__tests__/realworld-patterns.test.ts +0 -430
- package/src/__tests__/syntax-sugar.test.ts +0 -345
- package/src/builtins/builtin-intl.ts +0 -17
- package/src/builtins/builtin-map.ts +0 -174
- package/src/builtins/builtin-promise.ts +0 -116
- package/src/builtins/builtin-reflect.ts +0 -30
- package/src/builtins/builtin-regexp.ts +0 -34
- package/src/builtins/builtin-set.ts +0 -131
- package/src/builtins/builtin-symbol.ts +0 -16
- package/src/builtins/builtin-url.ts +0 -58
- package/src/builtins/builtin-weak.ts +0 -22
- package/src/builtins/builtin-web.ts +0 -111
- package/src/builtins/index.ts +0 -61
- package/src/config.ts +0 -32
- package/src/env-loader.ts +0 -174
- package/src/evaluator-api.ts +0 -36
- package/src/evaluator.ts +0 -5623
- package/src/index.ts +0 -931
- package/src/narrowing.ts +0 -537
- package/src/resolve-npm.ts +0 -63
- package/tsconfig.json +0 -9
|
@@ -1,384 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { parse, extractDirectives, type CaseDirective } from "@nudojs/parser";
|
|
3
|
-
import { typeValueToString, createEnvironment } 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("Combination Scenario Tests", () => {
|
|
27
|
-
describe("Array Method Chaining", () => {
|
|
28
|
-
it("filter + map", () => {
|
|
29
|
-
const results = runTest(`
|
|
30
|
-
// @nudo:case "filter-map" ([1, 2, 3, 4, 5])
|
|
31
|
-
function process(arr) {
|
|
32
|
-
return arr
|
|
33
|
-
.filter(n => n > 2)
|
|
34
|
-
.map(n => n * 2);
|
|
35
|
-
}
|
|
36
|
-
`);
|
|
37
|
-
expect(results[0].result).toContain("[");
|
|
38
|
-
expect(results[0].result).toContain("6");
|
|
39
|
-
expect(results[0].result).toContain("8");
|
|
40
|
-
expect(results[0].result).toContain("10");
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it("map + filter", () => {
|
|
44
|
-
const results = runTest(`
|
|
45
|
-
// @nudo:case "map-filter" ([1, 2, 3, 4, 5])
|
|
46
|
-
function process(arr) {
|
|
47
|
-
return arr
|
|
48
|
-
.map(n => n * n)
|
|
49
|
-
.filter(n => n > 10);
|
|
50
|
-
}
|
|
51
|
-
`);
|
|
52
|
-
expect(results[0].result).toContain("[");
|
|
53
|
-
expect(results[0].result).toContain("16");
|
|
54
|
-
expect(results[0].result).toContain("25");
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it("filter + map + reduce", () => {
|
|
58
|
-
const results = runTest(`
|
|
59
|
-
// @nudo:case "filter-map-reduce" ([1, 2, 3, 4, 5])
|
|
60
|
-
function process(arr) {
|
|
61
|
-
return arr
|
|
62
|
-
.filter(n => n > 2)
|
|
63
|
-
.map(n => n * n)
|
|
64
|
-
.reduce((sum, n) => sum + n, 0);
|
|
65
|
-
}
|
|
66
|
-
`);
|
|
67
|
-
// Note: This is a design limitation - arrays can't be iterated
|
|
68
|
-
// The result is a union of possible values, not the accumulated value
|
|
69
|
-
expect(results[0].result).toContain("|");
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it("map + reduce", () => {
|
|
73
|
-
const results = runTest(`
|
|
74
|
-
// @nudo:case "map-reduce" ([1, 2, 3])
|
|
75
|
-
function process(arr) {
|
|
76
|
-
return arr
|
|
77
|
-
.map(n => n * 2)
|
|
78
|
-
.reduce((sum, n) => sum + n, 0);
|
|
79
|
-
}
|
|
80
|
-
`);
|
|
81
|
-
expect(results[0].result).toBe("12");
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it("filter + reduce", () => {
|
|
85
|
-
const results = runTest(`
|
|
86
|
-
// @nudo:case "filter-reduce" ([1, 2, 3, 4, 5])
|
|
87
|
-
function process(arr) {
|
|
88
|
-
return arr
|
|
89
|
-
.filter(n => n % 2 === 0)
|
|
90
|
-
.reduce((sum, n) => sum + n, 0);
|
|
91
|
-
}
|
|
92
|
-
`);
|
|
93
|
-
// Note: This is a design limitation - arrays can't be iterated
|
|
94
|
-
// The result is a union of possible values, not the accumulated value
|
|
95
|
-
expect(results[0].result).toContain("|");
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it("slice + map", () => {
|
|
99
|
-
const results = runTest(`
|
|
100
|
-
// @nudo:case "slice-map" ([10, 20, 30, 40, 50])
|
|
101
|
-
function process(arr) {
|
|
102
|
-
return arr.slice(1, 4).map(n => n / 10);
|
|
103
|
-
}
|
|
104
|
-
`);
|
|
105
|
-
expect(results[0].result).toContain("[");
|
|
106
|
-
expect(results[0].result).toContain("2");
|
|
107
|
-
expect(results[0].result).toContain("3");
|
|
108
|
-
expect(results[0].result).toContain("4");
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
describe("Promise Chaining", () => {
|
|
113
|
-
it("Promise.all with destructuring", () => {
|
|
114
|
-
const results = runTest(`
|
|
115
|
-
// @nudo:case "promise-all-destructure" ()
|
|
116
|
-
async function fetchAll() {
|
|
117
|
-
const [users, posts, comments] = await Promise.all([
|
|
118
|
-
Promise.resolve([{ id: 1, name: "Alice" }]),
|
|
119
|
-
Promise.resolve([{ id: 1, title: "Post 1" }]),
|
|
120
|
-
Promise.resolve([{ id: 1, text: "Comment 1" }])
|
|
121
|
-
]);
|
|
122
|
-
return { users, posts, comments };
|
|
123
|
-
}
|
|
124
|
-
`);
|
|
125
|
-
expect(results[0].result).toContain("Promise");
|
|
126
|
-
expect(results[0].result).toContain("users");
|
|
127
|
-
expect(results[0].result).toContain("posts");
|
|
128
|
-
expect(results[0].result).toContain("comments");
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
it("Promise.race", () => {
|
|
132
|
-
const results = runTest(`
|
|
133
|
-
// @nudo:case "promise-race" ()
|
|
134
|
-
async function race() {
|
|
135
|
-
const result = await Promise.race([
|
|
136
|
-
Promise.resolve("fast"),
|
|
137
|
-
Promise.resolve("slow")
|
|
138
|
-
]);
|
|
139
|
-
return result;
|
|
140
|
-
}
|
|
141
|
-
`);
|
|
142
|
-
expect(results[0].result).toBe('Promise<"fast" | "slow">');
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
it("sequential promises", () => {
|
|
146
|
-
const results = runTest(`
|
|
147
|
-
// @nudo:case "sequential" ()
|
|
148
|
-
async function sequential() {
|
|
149
|
-
const a = await Promise.resolve(1);
|
|
150
|
-
const b = await Promise.resolve(a + 1);
|
|
151
|
-
const c = await Promise.resolve(b + 1);
|
|
152
|
-
return [a, b, c];
|
|
153
|
-
}
|
|
154
|
-
`);
|
|
155
|
-
expect(results[0].result).toBe("Promise<[1, 2, 3]>");
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
describe("Object Operations", () => {
|
|
160
|
-
it("spread + destructure", () => {
|
|
161
|
-
const results = runTest(`
|
|
162
|
-
// @nudo:case "spread-destructure" ({ name: "Alice", age: 30 }, { age: 31, city: "NYC" })
|
|
163
|
-
function merge(a, b) {
|
|
164
|
-
const merged = { ...a, ...b };
|
|
165
|
-
const { name, age, city } = merged;
|
|
166
|
-
return { name, age, city };
|
|
167
|
-
}
|
|
168
|
-
`);
|
|
169
|
-
expect(results[0].result).toContain("name");
|
|
170
|
-
expect(results[0].result).toContain("age");
|
|
171
|
-
expect(results[0].result).toContain("city");
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
it("nested spread", () => {
|
|
175
|
-
const results = runTest(`
|
|
176
|
-
// @nudo:case "nested-spread" ({ a: { x: 1 } }, { a: { y: 2 } })
|
|
177
|
-
function merge(a, b) {
|
|
178
|
-
return { ...a, ...b };
|
|
179
|
-
}
|
|
180
|
-
`);
|
|
181
|
-
expect(results[0].result).toContain("a");
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
it("computed properties", () => {
|
|
185
|
-
const results = runTest(`
|
|
186
|
-
// @nudo:case "computed-props" ("name", "Alice")
|
|
187
|
-
function createObj(key, value) {
|
|
188
|
-
return { [key]: value };
|
|
189
|
-
}
|
|
190
|
-
`);
|
|
191
|
-
expect(results[0].result).toContain("name");
|
|
192
|
-
expect(results[0].result).toContain("Alice");
|
|
193
|
-
});
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
describe("Control Flow Combinations", () => {
|
|
197
|
-
it("if-else with early return", () => {
|
|
198
|
-
const results = runTest(`
|
|
199
|
-
// @nudo:case "early-return" (10)
|
|
200
|
-
function classify(n) {
|
|
201
|
-
if (n < 0) return "negative";
|
|
202
|
-
if (n === 0) return "zero";
|
|
203
|
-
if (n < 10) return "small";
|
|
204
|
-
if (n < 100) return "medium";
|
|
205
|
-
return "large";
|
|
206
|
-
}
|
|
207
|
-
`);
|
|
208
|
-
expect(results[0].result).toBe('"medium"');
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
it("switch with fallthrough", () => {
|
|
212
|
-
const results = runTest(`
|
|
213
|
-
// @nudo:case "switch-fallthrough" (2)
|
|
214
|
-
function getDayType(day) {
|
|
215
|
-
switch (day) {
|
|
216
|
-
case 1:
|
|
217
|
-
case 2:
|
|
218
|
-
case 3:
|
|
219
|
-
case 4:
|
|
220
|
-
case 5:
|
|
221
|
-
return "weekday";
|
|
222
|
-
case 6:
|
|
223
|
-
case 7:
|
|
224
|
-
return "weekend";
|
|
225
|
-
default:
|
|
226
|
-
return "invalid";
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
`);
|
|
230
|
-
expect(results[0].result).toBe('"weekday"');
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
it("nested conditions", () => {
|
|
234
|
-
const results = runTest(`
|
|
235
|
-
// @nudo:case "nested-conditions" ({ active: true, role: "admin" })
|
|
236
|
-
function checkAccess(user) {
|
|
237
|
-
if (user.active) {
|
|
238
|
-
if (user.role === "admin") {
|
|
239
|
-
return { access: "full", level: 3 };
|
|
240
|
-
} else if (user.role === "editor") {
|
|
241
|
-
return { access: "edit", level: 2 };
|
|
242
|
-
} else {
|
|
243
|
-
return { access: "read", level: 1 };
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
return { access: "none", level: 0 };
|
|
247
|
-
}
|
|
248
|
-
`);
|
|
249
|
-
expect(results[0].result).toContain("full");
|
|
250
|
-
expect(results[0].result).toContain("3");
|
|
251
|
-
});
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
describe("Error Handling Combinations", () => {
|
|
255
|
-
it("try-catch with fallback", () => {
|
|
256
|
-
const results = runTest(`
|
|
257
|
-
// @nudo:case "try-catch-fallback" ("valid")
|
|
258
|
-
function safeParse(str) {
|
|
259
|
-
try {
|
|
260
|
-
if (str === "valid") return { success: true, data: "parsed" };
|
|
261
|
-
throw new Error("invalid");
|
|
262
|
-
} catch (e) {
|
|
263
|
-
return { success: false, error: "parse failed" };
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
`);
|
|
267
|
-
expect(results[0].result).toContain("success");
|
|
268
|
-
expect(results[0].result).toContain("parsed");
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
it("nested try-catch", () => {
|
|
272
|
-
const results = runTest(`
|
|
273
|
-
// @nudo:case "nested-try-catch" ()
|
|
274
|
-
function nestedTry() {
|
|
275
|
-
try {
|
|
276
|
-
try {
|
|
277
|
-
return { level: "inner", success: true };
|
|
278
|
-
} catch (e) {
|
|
279
|
-
return { level: "inner", success: false };
|
|
280
|
-
}
|
|
281
|
-
} catch (e) {
|
|
282
|
-
return { level: "outer", success: false };
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
`);
|
|
286
|
-
expect(results[0].result).toContain("inner");
|
|
287
|
-
expect(results[0].result).toContain("true");
|
|
288
|
-
});
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
describe("Higher-Order Functions", () => {
|
|
292
|
-
it("function as argument", () => {
|
|
293
|
-
const results = runTest(`
|
|
294
|
-
// @nudo:case "higher-order" ([1, 2, 3])
|
|
295
|
-
function applyFn(arr, fn) {
|
|
296
|
-
return arr.map(fn);
|
|
297
|
-
}
|
|
298
|
-
`);
|
|
299
|
-
expect(results[0].result).toContain("[");
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
it("function returning function", () => {
|
|
303
|
-
const results = runTest(`
|
|
304
|
-
// @nudo:case "factory" ()
|
|
305
|
-
function createMultiplier(factor) {
|
|
306
|
-
return function(n) {
|
|
307
|
-
return n * factor;
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
`);
|
|
311
|
-
// Functions are displayed as arrow function syntax
|
|
312
|
-
expect(results[0].result).toContain("=>");
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
it("closure", () => {
|
|
316
|
-
const results = runTest(`
|
|
317
|
-
// @nudo:case "closure" ()
|
|
318
|
-
function createCounter() {
|
|
319
|
-
let count = 0;
|
|
320
|
-
return {
|
|
321
|
-
increment() { return ++count; },
|
|
322
|
-
decrement() { return --count; },
|
|
323
|
-
getCount() { return count; }
|
|
324
|
-
};
|
|
325
|
-
}
|
|
326
|
-
`);
|
|
327
|
-
expect(results[0].result).toContain("increment");
|
|
328
|
-
expect(results[0].result).toContain("decrement");
|
|
329
|
-
expect(results[0].result).toContain("getCount");
|
|
330
|
-
});
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
describe("Map/Set Operations", () => {
|
|
334
|
-
it("Map with object values", () => {
|
|
335
|
-
const results = runTest(`
|
|
336
|
-
// @nudo:case "map-objects" ()
|
|
337
|
-
function createLookup() {
|
|
338
|
-
const map = new Map();
|
|
339
|
-
map.set("alice", { name: "Alice", age: 30 });
|
|
340
|
-
map.set("bob", { name: "Bob", age: 25 });
|
|
341
|
-
return {
|
|
342
|
-
alice: map.get("alice"),
|
|
343
|
-
bob: map.get("bob"),
|
|
344
|
-
missing: map.get("charlie")
|
|
345
|
-
};
|
|
346
|
-
}
|
|
347
|
-
`);
|
|
348
|
-
expect(results[0].result).toContain("alice");
|
|
349
|
-
expect(results[0].result).toContain("bob");
|
|
350
|
-
expect(results[0].result).toContain("undefined");
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
it("Set with Array.from", () => {
|
|
354
|
-
const results = runTest(`
|
|
355
|
-
// @nudo:case "set-array-from" ([1, 2, 2, 3, 3, 3])
|
|
356
|
-
function unique(arr) {
|
|
357
|
-
const set = new Set(arr);
|
|
358
|
-
return Array.from(set);
|
|
359
|
-
}
|
|
360
|
-
`);
|
|
361
|
-
expect(results[0].result).toContain("[");
|
|
362
|
-
expect(results[0].result).toContain("1");
|
|
363
|
-
expect(results[0].result).toContain("2");
|
|
364
|
-
expect(results[0].result).toContain("3");
|
|
365
|
-
});
|
|
366
|
-
|
|
367
|
-
it("Map iteration", () => {
|
|
368
|
-
const results = runTest(`
|
|
369
|
-
// @nudo:case "map-iterate" ()
|
|
370
|
-
function mapEntries() {
|
|
371
|
-
const map = new Map();
|
|
372
|
-
map.set("a", 1);
|
|
373
|
-
map.set("b", 2);
|
|
374
|
-
const entries = [];
|
|
375
|
-
for (const [key, value] of map) {
|
|
376
|
-
entries.push([key, value]);
|
|
377
|
-
}
|
|
378
|
-
return entries;
|
|
379
|
-
}
|
|
380
|
-
`);
|
|
381
|
-
expect(results[0].result).toContain("[");
|
|
382
|
-
});
|
|
383
|
-
});
|
|
384
|
-
});
|