ai-evaluate 2.1.6 → 2.1.8

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 (100) hide show
  1. package/README.md +90 -3
  2. package/dist/capnweb-bundle.d.ts +10 -0
  3. package/dist/capnweb-bundle.d.ts.map +1 -0
  4. package/dist/capnweb-bundle.js +2596 -0
  5. package/dist/capnweb-bundle.js.map +1 -0
  6. package/dist/evaluate.d.ts +1 -1
  7. package/dist/evaluate.d.ts.map +1 -1
  8. package/dist/evaluate.js +186 -7
  9. package/dist/evaluate.js.map +1 -1
  10. package/dist/index.d.ts +2 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +1 -0
  13. package/dist/index.js.map +1 -1
  14. package/dist/miniflare-pool.d.ts +109 -0
  15. package/dist/miniflare-pool.d.ts.map +1 -0
  16. package/dist/miniflare-pool.js +308 -0
  17. package/dist/miniflare-pool.js.map +1 -0
  18. package/dist/node.d.ts.map +1 -1
  19. package/dist/node.js +42 -10
  20. package/dist/node.js.map +1 -1
  21. package/dist/shared.d.ts +66 -0
  22. package/dist/shared.d.ts.map +1 -0
  23. package/dist/shared.js +169 -0
  24. package/dist/shared.js.map +1 -0
  25. package/dist/type-guards.d.ts +21 -0
  26. package/dist/type-guards.d.ts.map +1 -0
  27. package/dist/type-guards.js +216 -0
  28. package/dist/type-guards.js.map +1 -0
  29. package/dist/types.d.ts +17 -2
  30. package/dist/types.d.ts.map +1 -1
  31. package/dist/validation.d.ts +26 -0
  32. package/dist/validation.d.ts.map +1 -0
  33. package/dist/validation.js +104 -0
  34. package/dist/validation.js.map +1 -0
  35. package/dist/worker-template/code-transforms.d.ts +9 -0
  36. package/dist/worker-template/code-transforms.d.ts.map +1 -0
  37. package/dist/worker-template/code-transforms.js +28 -0
  38. package/dist/worker-template/code-transforms.js.map +1 -0
  39. package/{src/worker-template.d.ts → dist/worker-template/core.d.ts} +7 -15
  40. package/dist/worker-template/core.d.ts.map +1 -0
  41. package/dist/worker-template/core.js +502 -0
  42. package/dist/worker-template/core.js.map +1 -0
  43. package/dist/worker-template/helpers.d.ts +14 -0
  44. package/dist/worker-template/helpers.d.ts.map +1 -0
  45. package/dist/worker-template/helpers.js +79 -0
  46. package/dist/worker-template/helpers.js.map +1 -0
  47. package/dist/worker-template/index.d.ts +14 -0
  48. package/dist/worker-template/index.d.ts.map +1 -0
  49. package/dist/worker-template/index.js +19 -0
  50. package/dist/worker-template/index.js.map +1 -0
  51. package/dist/worker-template/sdk-generator.d.ts +17 -0
  52. package/dist/worker-template/sdk-generator.d.ts.map +1 -0
  53. package/{src/worker-template.js → dist/worker-template/sdk-generator.js} +377 -1506
  54. package/dist/worker-template/sdk-generator.js.map +1 -0
  55. package/dist/worker-template/test-generator.d.ts +16 -0
  56. package/dist/worker-template/test-generator.d.ts.map +1 -0
  57. package/dist/worker-template/test-generator.js +357 -0
  58. package/dist/worker-template/test-generator.js.map +1 -0
  59. package/dist/worker-template.d.ts +2 -2
  60. package/dist/worker-template.d.ts.map +1 -1
  61. package/dist/worker-template.js +64 -31
  62. package/dist/worker-template.js.map +1 -1
  63. package/example/package.json +7 -3
  64. package/example/src/index.ts +194 -40
  65. package/example/wrangler.jsonc +18 -2
  66. package/package.json +1 -3
  67. package/src/capnweb-bundle.ts +2596 -0
  68. package/src/evaluate.ts +216 -7
  69. package/src/index.ts +3 -1
  70. package/src/miniflare-pool.ts +395 -0
  71. package/src/node.ts +56 -11
  72. package/src/shared.ts +186 -0
  73. package/src/type-guards.ts +323 -0
  74. package/src/types.ts +18 -2
  75. package/src/validation.ts +120 -0
  76. package/src/worker-template/code-transforms.ts +32 -0
  77. package/src/worker-template/core.ts +557 -0
  78. package/src/worker-template/helpers.ts +90 -0
  79. package/src/worker-template/index.ts +23 -0
  80. package/src/{worker-template.ts → worker-template/sdk-generator.ts} +322 -1566
  81. package/src/worker-template/test-generator.ts +358 -0
  82. package/test/miniflare-pool.test.ts +246 -0
  83. package/test/node.test.ts +467 -0
  84. package/test/security.test.ts +1009 -0
  85. package/test/shared.test.ts +105 -0
  86. package/test/type-guards.test.ts +303 -0
  87. package/test/validation.test.ts +240 -0
  88. package/test/worker-template.test.ts +21 -19
  89. package/src/evaluate.js +0 -187
  90. package/src/index.js +0 -10
  91. package/src/node.d.ts +0 -17
  92. package/src/node.d.ts.map +0 -1
  93. package/src/node.js +0 -168
  94. package/src/node.js.map +0 -1
  95. package/src/types.d.ts +0 -172
  96. package/src/types.d.ts.map +0 -1
  97. package/src/types.js +0 -4
  98. package/src/types.js.map +0 -1
  99. package/src/worker-template.d.ts.map +0 -1
  100. package/src/worker-template.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk-generator.js","sourceRoot":"","sources":["../../src/worker-template/sdk-generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Test framework embedding for worker templates
3
+ *
4
+ * Generates the embedded test framework code used in dev mode
5
+ * (vitest-compatible API without external dependencies)
6
+ */
7
+ /**
8
+ * Generate the embedded test framework code
9
+ * This creates a vitest-compatible testing API that runs in the sandbox
10
+ */
11
+ export declare function generateTestFrameworkCode(): string;
12
+ /**
13
+ * Generate the test runner code that executes pending tests
14
+ */
15
+ export declare function generateTestRunnerCode(): string;
16
+ //# sourceMappingURL=test-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-generator.d.ts","sourceRoot":"","sources":["../../src/worker-template/test-generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CA0RlD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CA2D/C"}
@@ -0,0 +1,357 @@
1
+ /**
2
+ * Test framework embedding for worker templates
3
+ *
4
+ * Generates the embedded test framework code used in dev mode
5
+ * (vitest-compatible API without external dependencies)
6
+ */
7
+ /**
8
+ * Generate the embedded test framework code
9
+ * This creates a vitest-compatible testing API that runs in the sandbox
10
+ */
11
+ export function generateTestFrameworkCode() {
12
+ return `
13
+ // Test framework (vitest-compatible API)
14
+ let currentDescribe = '';
15
+ let beforeEachFns = [];
16
+ let afterEachFns = [];
17
+
18
+ const describe = (name, fn) => {
19
+ const prev = currentDescribe;
20
+ const prevBeforeEach = [...beforeEachFns];
21
+ const prevAfterEach = [...afterEachFns];
22
+ currentDescribe = currentDescribe ? currentDescribe + ' > ' + name : name;
23
+ try { fn(); } finally {
24
+ currentDescribe = prev;
25
+ beforeEachFns = prevBeforeEach;
26
+ afterEachFns = prevAfterEach;
27
+ }
28
+ };
29
+
30
+ // Hooks
31
+ const beforeEach = (fn) => { beforeEachFns.push(fn); };
32
+ const afterEach = (fn) => { afterEachFns.push(fn); };
33
+
34
+ const it = (name, fn) => {
35
+ const fullName = currentDescribe ? currentDescribe + ' > ' + name : name;
36
+ const hooks = { before: [...beforeEachFns], after: [...afterEachFns] };
37
+ pendingTests.push({ name: fullName, fn, hooks });
38
+ };
39
+ const test = it;
40
+
41
+ it.skip = (name, fn) => {
42
+ const fullName = currentDescribe ? currentDescribe + ' > ' + name : name;
43
+ pendingTests.push({ name: fullName, fn: null, skip: true });
44
+ };
45
+ test.skip = it.skip;
46
+
47
+ it.only = (name, fn) => {
48
+ const fullName = currentDescribe ? currentDescribe + ' > ' + name : name;
49
+ const hooks = { before: [...beforeEachFns], after: [...afterEachFns] };
50
+ pendingTests.push({ name: fullName, fn, hooks, only: true });
51
+ };
52
+ test.only = it.only;
53
+
54
+ // Deep equality check
55
+ const deepEqual = (a, b) => {
56
+ if (a === b) return true;
57
+ if (a == null || b == null) return false;
58
+ if (typeof a !== typeof b) return false;
59
+ if (typeof a !== 'object') return false;
60
+ if (Array.isArray(a) !== Array.isArray(b)) return false;
61
+ if (Array.isArray(a)) {
62
+ if (a.length !== b.length) return false;
63
+ return a.every((v, i) => deepEqual(v, b[i]));
64
+ }
65
+ const keysA = Object.keys(a);
66
+ const keysB = Object.keys(b);
67
+ if (keysA.length !== keysB.length) return false;
68
+ return keysA.every(k => deepEqual(a[k], b[k]));
69
+ };
70
+
71
+ // Expect implementation with vitest-compatible matchers
72
+ const expect = (actual) => {
73
+ const matchers = {
74
+ toBe: (expected) => {
75
+ if (actual !== expected) {
76
+ throw new Error(\`Expected \${JSON.stringify(expected)} but got \${JSON.stringify(actual)}\`);
77
+ }
78
+ },
79
+ toEqual: (expected) => {
80
+ if (!deepEqual(actual, expected)) {
81
+ throw new Error(\`Expected \${JSON.stringify(expected)} but got \${JSON.stringify(actual)}\`);
82
+ }
83
+ },
84
+ toStrictEqual: (expected) => {
85
+ if (!deepEqual(actual, expected)) {
86
+ throw new Error(\`Expected \${JSON.stringify(expected)} but got \${JSON.stringify(actual)}\`);
87
+ }
88
+ },
89
+ toBeTruthy: () => {
90
+ if (!actual) throw new Error(\`Expected truthy but got \${JSON.stringify(actual)}\`);
91
+ },
92
+ toBeFalsy: () => {
93
+ if (actual) throw new Error(\`Expected falsy but got \${JSON.stringify(actual)}\`);
94
+ },
95
+ toBeNull: () => {
96
+ if (actual !== null) throw new Error(\`Expected null but got \${JSON.stringify(actual)}\`);
97
+ },
98
+ toBeUndefined: () => {
99
+ if (actual !== undefined) throw new Error(\`Expected undefined but got \${JSON.stringify(actual)}\`);
100
+ },
101
+ toBeDefined: () => {
102
+ if (actual === undefined) throw new Error('Expected defined but got undefined');
103
+ },
104
+ toBeNaN: () => {
105
+ if (!Number.isNaN(actual)) throw new Error(\`Expected NaN but got \${actual}\`);
106
+ },
107
+ toContain: (item) => {
108
+ if (Array.isArray(actual)) {
109
+ if (!actual.includes(item)) throw new Error(\`Expected array to contain \${JSON.stringify(item)}\`);
110
+ } else if (typeof actual === 'string') {
111
+ if (!actual.includes(item)) throw new Error(\`Expected string to contain "\${item}"\`);
112
+ } else {
113
+ throw new Error('toContain only works on arrays and strings');
114
+ }
115
+ },
116
+ toContainEqual: (item) => {
117
+ if (!Array.isArray(actual)) throw new Error('toContainEqual only works on arrays');
118
+ if (!actual.some(v => deepEqual(v, item))) {
119
+ throw new Error(\`Expected array to contain \${JSON.stringify(item)}\`);
120
+ }
121
+ },
122
+ toHaveLength: (length) => {
123
+ if (actual?.length !== length) {
124
+ throw new Error(\`Expected length \${length} but got \${actual?.length}\`);
125
+ }
126
+ },
127
+ toHaveProperty: function(path, value) {
128
+ const parts = typeof path === 'string' ? path.split('.') : [path];
129
+ let obj = actual;
130
+ for (const part of parts) {
131
+ if (obj == null || !(part in obj)) {
132
+ throw new Error(\`Expected object to have property "\${path}"\`);
133
+ }
134
+ obj = obj[part];
135
+ }
136
+ if (arguments.length > 1 && !deepEqual(obj, value)) {
137
+ throw new Error(\`Expected property "\${path}" to be \${JSON.stringify(value)} but got \${JSON.stringify(obj)}\`);
138
+ }
139
+ },
140
+ toMatchObject: (expected) => {
141
+ if (typeof actual !== 'object' || actual === null) {
142
+ throw new Error('toMatchObject expects an object');
143
+ }
144
+ for (const key of Object.keys(expected)) {
145
+ if (!deepEqual(actual[key], expected[key])) {
146
+ throw new Error(\`Expected property "\${key}" to be \${JSON.stringify(expected[key])} but got \${JSON.stringify(actual[key])}\`);
147
+ }
148
+ }
149
+ },
150
+ toThrow: (expected) => {
151
+ if (typeof actual !== 'function') throw new Error('toThrow expects a function');
152
+ let threw = false;
153
+ let error;
154
+ try {
155
+ actual();
156
+ } catch (e) {
157
+ threw = true;
158
+ error = e;
159
+ }
160
+ if (!threw) throw new Error('Expected function to throw');
161
+ if (expected !== undefined) {
162
+ if (typeof expected === 'string' && !error.message.includes(expected)) {
163
+ throw new Error(\`Expected error message to contain "\${expected}" but got "\${error.message}"\`);
164
+ }
165
+ if (expected instanceof RegExp && !expected.test(error.message)) {
166
+ throw new Error(\`Expected error message to match \${expected} but got "\${error.message}"\`);
167
+ }
168
+ if (typeof expected === 'function' && !(error instanceof expected)) {
169
+ throw new Error(\`Expected error to be instance of \${expected.name}\`);
170
+ }
171
+ }
172
+ },
173
+ toBeGreaterThan: (n) => {
174
+ if (!(actual > n)) throw new Error(\`Expected \${actual} to be greater than \${n}\`);
175
+ },
176
+ toBeLessThan: (n) => {
177
+ if (!(actual < n)) throw new Error(\`Expected \${actual} to be less than \${n}\`);
178
+ },
179
+ toBeGreaterThanOrEqual: (n) => {
180
+ if (!(actual >= n)) throw new Error(\`Expected \${actual} to be >= \${n}\`);
181
+ },
182
+ toBeLessThanOrEqual: (n) => {
183
+ if (!(actual <= n)) throw new Error(\`Expected \${actual} to be <= \${n}\`);
184
+ },
185
+ toBeCloseTo: (n, digits = 2) => {
186
+ const diff = Math.abs(actual - n);
187
+ const threshold = Math.pow(10, -digits) / 2;
188
+ if (diff > threshold) {
189
+ throw new Error(\`Expected \${actual} to be close to \${n}\`);
190
+ }
191
+ },
192
+ toMatch: (pattern) => {
193
+ if (typeof actual !== 'string') throw new Error('toMatch expects a string');
194
+ const regex = typeof pattern === 'string' ? new RegExp(pattern) : pattern;
195
+ if (!regex.test(actual)) {
196
+ throw new Error(\`Expected "\${actual}" to match \${pattern}\`);
197
+ }
198
+ },
199
+ toBeInstanceOf: (cls) => {
200
+ if (!(actual instanceof cls)) {
201
+ throw new Error(\`Expected instance of \${cls.name}\`);
202
+ }
203
+ },
204
+ toBeTypeOf: (type) => {
205
+ if (typeof actual !== type) {
206
+ throw new Error(\`Expected typeof to be "\${type}" but got "\${typeof actual}"\`);
207
+ }
208
+ },
209
+ };
210
+
211
+ matchers.not = {
212
+ toBe: (expected) => {
213
+ if (actual === expected) throw new Error(\`Expected not \${JSON.stringify(expected)}\`);
214
+ },
215
+ toEqual: (expected) => {
216
+ if (deepEqual(actual, expected)) {
217
+ throw new Error(\`Expected not equal to \${JSON.stringify(expected)}\`);
218
+ }
219
+ },
220
+ toBeTruthy: () => {
221
+ if (actual) throw new Error('Expected not truthy');
222
+ },
223
+ toBeFalsy: () => {
224
+ if (!actual) throw new Error('Expected not falsy');
225
+ },
226
+ toBeNull: () => {
227
+ if (actual === null) throw new Error('Expected not null');
228
+ },
229
+ toBeUndefined: () => {
230
+ if (actual === undefined) throw new Error('Expected not undefined');
231
+ },
232
+ toBeDefined: () => {
233
+ if (actual !== undefined) throw new Error('Expected undefined');
234
+ },
235
+ toContain: (item) => {
236
+ if (Array.isArray(actual) && actual.includes(item)) {
237
+ throw new Error(\`Expected array not to contain \${JSON.stringify(item)}\`);
238
+ }
239
+ if (typeof actual === 'string' && actual.includes(item)) {
240
+ throw new Error(\`Expected string not to contain "\${item}"\`);
241
+ }
242
+ },
243
+ toHaveProperty: (path) => {
244
+ const parts = typeof path === 'string' ? path.split('.') : [path];
245
+ let obj = actual;
246
+ try {
247
+ for (const part of parts) {
248
+ if (obj == null || !(part in obj)) return;
249
+ obj = obj[part];
250
+ }
251
+ throw new Error(\`Expected object not to have property "\${path}"\`);
252
+ } catch {}
253
+ },
254
+ toThrow: () => {
255
+ if (typeof actual !== 'function') throw new Error('toThrow expects a function');
256
+ try {
257
+ actual();
258
+ } catch (e) {
259
+ throw new Error('Expected function not to throw');
260
+ }
261
+ },
262
+ toMatch: (pattern) => {
263
+ if (typeof actual !== 'string') throw new Error('toMatch expects a string');
264
+ const regex = typeof pattern === 'string' ? new RegExp(pattern) : pattern;
265
+ if (regex.test(actual)) {
266
+ throw new Error(\`Expected "\${actual}" not to match \${pattern}\`);
267
+ }
268
+ },
269
+ };
270
+
271
+ matchers.resolves = new Proxy({}, {
272
+ get: (_, prop) => async (...args) => {
273
+ const resolved = await actual;
274
+ return expect(resolved)[prop](...args);
275
+ }
276
+ });
277
+
278
+ matchers.rejects = new Proxy({}, {
279
+ get: (_, prop) => async (...args) => {
280
+ try {
281
+ await actual;
282
+ throw new Error('Expected promise to reject');
283
+ } catch (e) {
284
+ if (e.message === 'Expected promise to reject') throw e;
285
+ return expect(e)[prop](...args);
286
+ }
287
+ }
288
+ });
289
+
290
+ return matchers;
291
+ };
292
+ `;
293
+ }
294
+ /**
295
+ * Generate the test runner code that executes pending tests
296
+ */
297
+ export function generateTestRunnerCode() {
298
+ return `
299
+ // Run all pending tests
300
+ const testStart = Date.now();
301
+ const hasOnly = pendingTests.some(t => t.only);
302
+ const testsToRun = hasOnly ? pendingTests.filter(t => t.only || t.skip) : pendingTests;
303
+
304
+ for (const { name, fn, hooks, skip } of testsToRun) {
305
+ testResults.total++;
306
+
307
+ if (skip) {
308
+ testResults.skipped++;
309
+ testResults.tests.push({ name, passed: true, skipped: true, duration: 0 });
310
+ continue;
311
+ }
312
+
313
+ const start = Date.now();
314
+ try {
315
+ // Run beforeEach hooks
316
+ if (hooks?.before) {
317
+ for (const hook of hooks.before) {
318
+ const hookResult = hook();
319
+ if (hookResult && typeof hookResult.then === 'function') {
320
+ await hookResult;
321
+ }
322
+ }
323
+ }
324
+
325
+ // Run the test
326
+ const result = fn();
327
+ if (result && typeof result.then === 'function') {
328
+ await result;
329
+ }
330
+
331
+ // Run afterEach hooks
332
+ if (hooks?.after) {
333
+ for (const hook of hooks.after) {
334
+ const hookResult = hook();
335
+ if (hookResult && typeof hookResult.then === 'function') {
336
+ await hookResult;
337
+ }
338
+ }
339
+ }
340
+
341
+ testResults.passed++;
342
+ testResults.tests.push({ name, passed: true, duration: Date.now() - start });
343
+ } catch (e) {
344
+ testResults.failed++;
345
+ testResults.tests.push({
346
+ name,
347
+ passed: false,
348
+ error: e.message || String(e),
349
+ duration: Date.now() - start
350
+ });
351
+ }
352
+ }
353
+
354
+ testResults.duration = Date.now() - testStart;
355
+ `;
356
+ }
357
+ //# sourceMappingURL=test-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-generator.js","sourceRoot":"","sources":["../../src/worker-template/test-generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,MAAM,UAAU,yBAAyB;IACvC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwRR,CAAA;AACD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB;IACpC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyDR,CAAA;AACD,CAAC"}
@@ -13,7 +13,7 @@
13
13
  * - POST /rpc or WebSocket upgrade - capnweb RPC to module exports
14
14
  * - GET / - Return info about available exports
15
15
  */
16
- import type { SDKConfig } from './types.js';
16
+ import type { SDKConfig, FetchConfig } from './types.js';
17
17
  /**
18
18
  * Generate worker code for production (uses RPC to ai-tests)
19
19
  */
@@ -36,6 +36,6 @@ export declare function generateDevWorkerCode(options: {
36
36
  script?: string | undefined;
37
37
  sdk?: SDKConfig | boolean | undefined;
38
38
  imports?: string[] | undefined;
39
- fetch?: null | undefined;
39
+ fetch?: null | FetchConfig | undefined;
40
40
  }): string;
41
41
  //# sourceMappingURL=worker-template.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"worker-template.d.ts","sourceRoot":"","sources":["../src/worker-template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AA03F3C;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,GAAG,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAA;IACrC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;CAC/B,GAAG,MAAM,CAgPT;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE;IAC7C,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,GAAG,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAA;IACrC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;IAC9B,KAAK,CAAC,EAAE,IAAI,GAAG,SAAS,CAAA;CACzB,GAAG,MAAM,CA4hBT"}
1
+ {"version":3,"file":"worker-template.d.ts","sourceRoot":"","sources":["../src/worker-template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AA23FxD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,GAAG,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAA;IACrC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;CAC/B,GAAG,MAAM,CAoQT;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE;IAC7C,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,GAAG,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAA;IACrC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;IAC9B,KAAK,CAAC,EAAE,IAAI,GAAG,WAAW,GAAG,SAAS,CAAA;CACvC,GAAG,MAAM,CAikBT"}
@@ -13,6 +13,7 @@
13
13
  * - POST /rpc or WebSocket upgrade - capnweb RPC to module exports
14
14
  * - GET / - Return info about available exports
15
15
  */
16
+ import { generateDomainCheckCode } from './shared.js';
16
17
  /**
17
18
  * Generate SDK code for injection into sandbox
18
19
  *
@@ -2919,7 +2920,8 @@ function wrapScriptForReturn(script) {
2919
2920
  return script;
2920
2921
  const lastLine = lastLineRaw.trim();
2921
2922
  // If last line is an expression (not a declaration, control flow, or throw)
2922
- if (lastLine && !/^\s*(const|let|var|if|for|while|switch|try|class|function|return|throw)\b/.test(lastLine)) {
2923
+ if (lastLine &&
2924
+ !/^\s*(const|let|var|if|for|while|switch|try|class|function|return|throw)\b/.test(lastLine)) {
2923
2925
  lines[lines.length - 1] = `return ${lastLine.replace(/;?\s*$/, '')}`;
2924
2926
  return lines.join('\n');
2925
2927
  }
@@ -2930,7 +2932,7 @@ function wrapScriptForReturn(script) {
2930
2932
  */
2931
2933
  export function generateWorkerCode(options) {
2932
2934
  const { module: rawModule = '', tests = '', script: rawScript = '', sdk, imports = [] } = options;
2933
- const sdkConfig = sdk === true ? {} : (sdk || null);
2935
+ const sdkConfig = sdk === true ? {} : sdk || null;
2934
2936
  const module = rawModule ? transformModuleCode(rawModule) : '';
2935
2937
  const script = rawScript ? wrapScriptForReturn(rawScript) : '';
2936
2938
  const exportNames = getExportNames(rawModule);
@@ -2938,7 +2940,7 @@ export function generateWorkerCode(options) {
2938
2940
  const hoistedImports = imports.length > 0 ? imports.join('\n') + '\n' : '';
2939
2941
  return `
2940
2942
  // Sandbox Worker Entry Point
2941
- import { RpcTarget, newWorkersRpcResponse } from 'capnweb';
2943
+ import { RpcTarget, newWorkersRpcResponse } from 'capnweb.js';
2942
2944
  ${hoistedImports}
2943
2945
  const logs = [];
2944
2946
 
@@ -2968,20 +2970,24 @@ console.debug = captureConsole('debug');
2968
2970
  // Module exports object - exports become top-level variables
2969
2971
  const exports = {};
2970
2972
 
2971
- ${module ? `
2973
+ ${module
2974
+ ? `
2972
2975
  // Execute module code
2973
2976
  try {
2974
2977
  ${module}
2975
2978
  } catch (e) {
2976
2979
  console.error('Module error:', e.message);
2977
2980
  }
2978
- ` : '// No module code provided'}
2981
+ `
2982
+ : '// No module code provided'}
2979
2983
 
2980
2984
  // Expose all exports as top-level variables for tests and scripts
2981
2985
  // This allows: export const add = (a, b) => a + b; then later: add(1, 2)
2982
- ${rawModule ? `
2986
+ ${rawModule
2987
+ ? `
2983
2988
  const { ${exportNames} } = exports;
2984
- `.trim() : ''}
2989
+ `.trim()
2990
+ : ''}
2985
2991
 
2986
2992
  // ============================================================
2987
2993
  // RPC SERVER - Expose exports via capnweb
@@ -3121,17 +3127,20 @@ export default {
3121
3127
  // USER TEST CODE (embedded at generation time)
3122
3128
  // ============================================================
3123
3129
 
3124
- ${tests ? `
3130
+ ${tests
3131
+ ? `
3125
3132
  // Register tests
3126
3133
  try {
3127
3134
  ${tests}
3128
3135
  } catch (e) {
3129
3136
  console.error('Test registration error:', e.message);
3130
3137
  }
3131
- ` : '// No test code provided'}
3138
+ `
3139
+ : '// No test code provided'}
3132
3140
 
3133
3141
  // Execute user script
3134
- ${script ? `
3142
+ ${script
3143
+ ? `
3135
3144
  try {
3136
3145
  scriptResult = await (async () => {
3137
3146
  ${script}
@@ -3140,17 +3149,20 @@ ${script}
3140
3149
  console.error('Script error:', e.message);
3141
3150
  scriptError = e.message;
3142
3151
  }
3143
- ` : '// No script code provided'}
3152
+ `
3153
+ : '// No script code provided'}
3144
3154
 
3145
3155
  // Run tests if any were registered
3146
- ${tests ? `
3156
+ ${tests
3157
+ ? `
3147
3158
  try {
3148
3159
  testResults = await testService.run();
3149
3160
  } catch (e) {
3150
3161
  console.error('Test run error:', e.message);
3151
3162
  testResults = { total: 0, passed: 0, failed: 1, skipped: 0, tests: [], duration: 0, error: e.message };
3152
3163
  }
3153
- ` : ''}
3164
+ `
3165
+ : ''}
3154
3166
 
3155
3167
  const hasTests = ${tests ? 'true' : 'false'};
3156
3168
  const success = scriptError === null && (!hasTests || (testResults && testResults.failed === 0));
@@ -3174,14 +3186,33 @@ ${script}
3174
3186
  * avoiding the need for RPC service bindings in local development.
3175
3187
  */
3176
3188
  export function generateDevWorkerCode(options) {
3177
- const { module: rawModule = '', tests = '', script: rawScript = '', sdk, imports = [], fetch: fetchOption } = options;
3178
- const sdkConfig = sdk === true ? {} : (sdk || null);
3189
+ const { module: rawModule = '', tests = '', script: rawScript = '', sdk, imports = [], fetch: fetchOption, } = options;
3190
+ const sdkConfig = sdk === true ? {} : sdk || null;
3179
3191
  const module = rawModule ? transformModuleCode(rawModule) : '';
3180
3192
  const script = rawScript ? wrapScriptForReturn(rawScript) : '';
3181
3193
  const exportNames = getExportNames(rawModule);
3182
- const blockFetch = fetchOption === null;
3194
+ // Determine fetch handling mode
3195
+ // - null or { mode: 'block' } -> block all network
3196
+ // - { mode: 'allowlist', allowedDomains: [...] } -> domain filtering
3197
+ // - undefined or { mode: 'allow' } -> allow all (no wrapper needed)
3198
+ const blockFetch = fetchOption === null || (fetchOption && fetchOption.mode === 'block');
3199
+ const useAllowlist = fetchOption && fetchOption.mode === 'allowlist' && fetchOption.allowedDomains;
3183
3200
  // Hoisted imports (from MDX test files) - placed at true module top level
3184
3201
  const hoistedImports = imports.length > 0 ? imports.join('\n') + '\n' : '';
3202
+ // Generate fetch control code based on mode
3203
+ let fetchControlCode = '';
3204
+ if (blockFetch) {
3205
+ fetchControlCode = `
3206
+ // Block fetch when fetch: null or mode: 'block' is specified
3207
+ const __originalFetch__ = globalThis.fetch;
3208
+ globalThis.fetch = async (...args) => {
3209
+ throw new Error('Network access blocked: fetch is disabled in this sandbox');
3210
+ };
3211
+ `;
3212
+ }
3213
+ else if (useAllowlist) {
3214
+ fetchControlCode = generateDomainCheckCode(fetchOption.allowedDomains);
3215
+ }
3185
3216
  return `
3186
3217
  // Sandbox Worker Entry Point (Dev Mode - embedded test framework)
3187
3218
  ${hoistedImports}
@@ -3189,13 +3220,7 @@ const logs = [];
3189
3220
  const testResults = { total: 0, passed: 0, failed: 0, skipped: 0, tests: [], duration: 0 };
3190
3221
  const pendingTests = [];
3191
3222
 
3192
- ${blockFetch ? `
3193
- // Block fetch when fetch: null is specified
3194
- const __originalFetch__ = globalThis.fetch;
3195
- globalThis.fetch = async (...args) => {
3196
- throw new Error('Network access blocked: fetch is disabled in this sandbox');
3197
- };
3198
- ` : ''}
3223
+ ${fetchControlCode}
3199
3224
 
3200
3225
  ${sdkConfig ? generateShouldCode() : ''}
3201
3226
 
@@ -3503,32 +3528,38 @@ const expect = (actual) => {
3503
3528
  // Module exports object - exports become top-level variables
3504
3529
  const exports = {};
3505
3530
 
3506
- ${module ? `
3531
+ ${module
3532
+ ? `
3507
3533
  // Execute module code
3508
3534
  try {
3509
3535
  ${module}
3510
3536
  } catch (e) {
3511
3537
  console.error('Module error:', e.message);
3512
3538
  }
3513
- ` : '// No module code provided'}
3539
+ `
3540
+ : '// No module code provided'}
3514
3541
 
3515
3542
  // Expose all exports as top-level variables for tests and scripts
3516
3543
  // This allows: export const add = (a, b) => a + b; then later: add(1, 2)
3517
- ${rawModule ? `
3544
+ ${rawModule
3545
+ ? `
3518
3546
  const { ${exportNames} } = exports;
3519
- `.trim() : ''}
3547
+ `.trim()
3548
+ : ''}
3520
3549
 
3521
3550
  // ============================================================
3522
3551
  // USER TEST CODE (embedded at generation time)
3523
3552
  // ============================================================
3524
- ${tests ? `
3553
+ ${tests
3554
+ ? `
3525
3555
  // Register tests
3526
3556
  try {
3527
3557
  ${tests}
3528
3558
  } catch (e) {
3529
3559
  console.error('Test registration error:', e.message);
3530
3560
  }
3531
- ` : '// No test code provided'}
3561
+ `
3562
+ : '// No test code provided'}
3532
3563
 
3533
3564
  // ============================================================
3534
3565
  // SIMPLE RPC HANDLER (dev mode - no capnweb dependency)
@@ -3629,7 +3660,8 @@ export default {
3629
3660
  let scriptError = null;
3630
3661
 
3631
3662
  // Execute user script
3632
- ${script ? `
3663
+ ${script
3664
+ ? `
3633
3665
  try {
3634
3666
  scriptResult = await (async () => {
3635
3667
  ${script}
@@ -3638,7 +3670,8 @@ ${script}
3638
3670
  console.error('Script error:', e.message);
3639
3671
  scriptError = e.message;
3640
3672
  }
3641
- ` : '// No script code provided'}
3673
+ `
3674
+ : '// No script code provided'}
3642
3675
 
3643
3676
  // Run all pending tests
3644
3677
  const testStart = Date.now();