@ricsam/isolate-fetch 0.1.1 → 0.1.2

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.
@@ -1,627 +0,0 @@
1
- import { test, describe, beforeEach, afterEach } from "node:test";
2
- import assert from "node:assert";
3
- import ivm from "isolated-vm";
4
- import { setupFetch, clearAllInstanceState, type FetchHandle, type WebSocketCommand } from "./index.ts";
5
-
6
- describe("WebSocket", () => {
7
- let isolate: ivm.Isolate;
8
- let context: ivm.Context;
9
- let fetchHandle: FetchHandle;
10
-
11
- beforeEach(async () => {
12
- isolate = new ivm.Isolate();
13
- context = await isolate.createContext();
14
- clearAllInstanceState();
15
- fetchHandle = await setupFetch(context);
16
- });
17
-
18
- afterEach(() => {
19
- fetchHandle.dispose();
20
- context.release();
21
- isolate.dispose();
22
- });
23
-
24
- test("server.upgrade() returns true and sets pendingUpgrade with connectionId", async () => {
25
- context.evalSync(`
26
- serve({
27
- fetch(request, server) {
28
- const upgraded = server.upgrade(request, { data: { userId: "123" } });
29
- return new Response(upgraded ? "upgrading" : "failed", { status: upgraded ? 101 : 400 });
30
- }
31
- });
32
- `);
33
-
34
- const response = await fetchHandle.dispatchRequest(
35
- new Request("http://localhost/ws")
36
- );
37
- // Note: Status 101 is not valid for native Response, so we expose it via _originalStatus
38
- // @ts-expect-error - accessing custom property
39
- assert.strictEqual(response._originalStatus, 101);
40
-
41
- const upgrade = fetchHandle.getUpgradeRequest();
42
- assert.strictEqual(upgrade?.requested, true);
43
- assert.strictEqual(typeof upgrade?.connectionId, "string");
44
- assert.ok(upgrade?.connectionId);
45
- });
46
-
47
- test("server.upgrade() without data option", async () => {
48
- context.evalSync(`
49
- serve({
50
- fetch(request, server) {
51
- const upgraded = server.upgrade(request);
52
- return new Response(null, { status: upgraded ? 101 : 400 });
53
- }
54
- });
55
- `);
56
-
57
- const response = await fetchHandle.dispatchRequest(
58
- new Request("http://localhost/ws")
59
- );
60
- // @ts-expect-error - accessing custom property
61
- assert.strictEqual(response._originalStatus, 101);
62
-
63
- const upgrade = fetchHandle.getUpgradeRequest();
64
- assert.strictEqual(upgrade?.requested, true);
65
- assert.strictEqual(typeof upgrade?.connectionId, "string");
66
- });
67
-
68
- test("dispatchWebSocketOpen calls websocket.open handler", async () => {
69
- context.evalSync(`
70
- globalThis.openedConnections = [];
71
- serve({
72
- fetch(request, server) {
73
- server.upgrade(request, { data: { test: true } });
74
- return new Response(null, { status: 101 });
75
- },
76
- websocket: {
77
- open(ws) {
78
- globalThis.openedConnections.push(ws.data);
79
- }
80
- }
81
- });
82
- `);
83
-
84
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws"));
85
- const upgrade = fetchHandle.getUpgradeRequest();
86
- fetchHandle.dispatchWebSocketOpen(upgrade!.connectionId);
87
-
88
- const result = context.evalSync(`JSON.stringify(globalThis.openedConnections)`);
89
- const connections = JSON.parse(result as string);
90
- assert.strictEqual(connections.length, 1);
91
- assert.deepStrictEqual(connections[0], { test: true });
92
- });
93
-
94
- test("dispatchWebSocketMessage delivers messages to handler", async () => {
95
- context.evalSync(`
96
- globalThis.receivedMessages = [];
97
- serve({
98
- fetch(request, server) {
99
- server.upgrade(request);
100
- return new Response(null, { status: 101 });
101
- },
102
- websocket: {
103
- open(ws) {
104
- // Need open handler for connection to be established
105
- },
106
- message(ws, message) {
107
- globalThis.receivedMessages.push(message);
108
- }
109
- }
110
- });
111
- `);
112
-
113
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws"));
114
- const upgrade = fetchHandle.getUpgradeRequest();
115
- fetchHandle.dispatchWebSocketOpen(upgrade!.connectionId);
116
- fetchHandle.dispatchWebSocketMessage(upgrade!.connectionId, "Hello WebSocket!");
117
-
118
- const result = context.evalSync(`JSON.stringify(globalThis.receivedMessages)`);
119
- const messages = JSON.parse(result as string);
120
- assert.deepStrictEqual(messages, ["Hello WebSocket!"]);
121
- });
122
-
123
- test("dispatchWebSocketClose notifies handler with code and reason", async () => {
124
- context.evalSync(`
125
- globalThis.closeInfo = null;
126
- serve({
127
- fetch(request, server) {
128
- server.upgrade(request);
129
- return new Response(null, { status: 101 });
130
- },
131
- websocket: {
132
- open(ws) {
133
- // Need open handler for connection to be established
134
- },
135
- close(ws, code, reason) {
136
- globalThis.closeInfo = { code, reason };
137
- }
138
- }
139
- });
140
- `);
141
-
142
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws"));
143
- const upgrade = fetchHandle.getUpgradeRequest();
144
- fetchHandle.dispatchWebSocketOpen(upgrade!.connectionId);
145
- fetchHandle.dispatchWebSocketClose(upgrade!.connectionId, 1000, "Normal closure");
146
-
147
- const result = context.evalSync(`JSON.stringify(globalThis.closeInfo)`);
148
- const closeInfo = JSON.parse(result as string);
149
- assert.deepStrictEqual(closeInfo, { code: 1000, reason: "Normal closure" });
150
- });
151
-
152
- test("dispatchWebSocketError delivers error to handler", async () => {
153
- context.evalSync(`
154
- globalThis.errorInfo = null;
155
- serve({
156
- fetch(request, server) {
157
- server.upgrade(request);
158
- return new Response(null, { status: 101 });
159
- },
160
- websocket: {
161
- open(ws) {
162
- // Need open handler for connection to be established
163
- },
164
- error(ws, error) {
165
- globalThis.errorInfo = { name: error.name, message: error.message };
166
- }
167
- }
168
- });
169
- `);
170
-
171
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws"));
172
- const upgrade = fetchHandle.getUpgradeRequest();
173
- fetchHandle.dispatchWebSocketOpen(upgrade!.connectionId);
174
- fetchHandle.dispatchWebSocketError(upgrade!.connectionId, new Error("Connection lost"));
175
-
176
- const result = context.evalSync(`JSON.stringify(globalThis.errorInfo)`);
177
- const errorInfo = JSON.parse(result as string);
178
- assert.deepStrictEqual(errorInfo, { name: "Error", message: "Connection lost" });
179
- });
180
-
181
- test("ws.send() triggers onWebSocketCommand callback", async () => {
182
- context.evalSync(`
183
- serve({
184
- fetch(request, server) {
185
- server.upgrade(request);
186
- return new Response(null, { status: 101 });
187
- },
188
- websocket: {
189
- open(ws) {
190
- ws.send("Welcome!");
191
- }
192
- }
193
- });
194
- `);
195
-
196
- const commands: WebSocketCommand[] = [];
197
- fetchHandle.onWebSocketCommand((cmd) => {
198
- commands.push(cmd);
199
- });
200
-
201
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws"));
202
- const upgrade = fetchHandle.getUpgradeRequest();
203
- fetchHandle.dispatchWebSocketOpen(upgrade!.connectionId);
204
-
205
- assert.strictEqual(commands.length, 1);
206
- assert.strictEqual(commands[0].type, "message");
207
- assert.strictEqual(commands[0].connectionId, upgrade!.connectionId);
208
- assert.strictEqual(commands[0].data, "Welcome!");
209
- });
210
-
211
- test("ws.close() triggers onWebSocketCommand with close message", async () => {
212
- context.evalSync(`
213
- serve({
214
- fetch(request, server) {
215
- server.upgrade(request);
216
- return new Response(null, { status: 101 });
217
- },
218
- websocket: {
219
- open(ws) {
220
- ws.close(1000, "Goodbye");
221
- }
222
- }
223
- });
224
- `);
225
-
226
- const commands: WebSocketCommand[] = [];
227
- fetchHandle.onWebSocketCommand((cmd) => {
228
- commands.push(cmd);
229
- });
230
-
231
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws"));
232
- const upgrade = fetchHandle.getUpgradeRequest();
233
- fetchHandle.dispatchWebSocketOpen(upgrade!.connectionId);
234
-
235
- assert.strictEqual(commands.length, 1);
236
- assert.strictEqual(commands[0].type, "close");
237
- assert.strictEqual(commands[0].connectionId, upgrade!.connectionId);
238
- assert.strictEqual(commands[0].code, 1000);
239
- assert.strictEqual(commands[0].reason, "Goodbye");
240
- });
241
-
242
- test("WebSocket echo server roundtrip", async () => {
243
- context.evalSync(`
244
- serve({
245
- fetch(request, server) {
246
- server.upgrade(request);
247
- return new Response(null, { status: 101 });
248
- },
249
- websocket: {
250
- open(ws) {
251
- // Need open handler for connection to be established
252
- },
253
- message(ws, message) {
254
- ws.send("Echo: " + message);
255
- }
256
- }
257
- });
258
- `);
259
-
260
- const messages: string[] = [];
261
- fetchHandle.onWebSocketCommand((cmd) => {
262
- if (cmd.type === "message") {
263
- messages.push(cmd.data as string);
264
- }
265
- });
266
-
267
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws"));
268
- const upgrade = fetchHandle.getUpgradeRequest();
269
- fetchHandle.dispatchWebSocketOpen(upgrade!.connectionId);
270
- fetchHandle.dispatchWebSocketMessage(upgrade!.connectionId, "Hello");
271
-
272
- assert.deepStrictEqual(messages, ["Echo: Hello"]);
273
- });
274
-
275
- test("message to unknown connection is ignored", async () => {
276
- context.evalSync(`
277
- globalThis.receivedMessages = [];
278
- serve({
279
- fetch(request, server) {
280
- server.upgrade(request);
281
- return new Response(null, { status: 101 });
282
- },
283
- websocket: {
284
- open(ws) {},
285
- message(ws, message) {
286
- globalThis.receivedMessages.push(message);
287
- }
288
- }
289
- });
290
- `);
291
-
292
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws"));
293
- const upgrade = fetchHandle.getUpgradeRequest();
294
- fetchHandle.dispatchWebSocketOpen(upgrade!.connectionId);
295
-
296
- // Send to unknown connection - should not throw
297
- fetchHandle.dispatchWebSocketMessage("unknown-conn", "Hello");
298
-
299
- const result = context.evalSync(`JSON.stringify(globalThis.receivedMessages)`);
300
- const messages = JSON.parse(result as string);
301
- assert.deepStrictEqual(messages, []);
302
- });
303
-
304
- test("ws.readyState is 1 (OPEN) when connected", async () => {
305
- context.evalSync(`
306
- globalThis.readyState = null;
307
- serve({
308
- fetch(request, server) {
309
- server.upgrade(request);
310
- return new Response(null, { status: 101 });
311
- },
312
- websocket: {
313
- open(ws) {
314
- globalThis.readyState = ws.readyState;
315
- }
316
- }
317
- });
318
- `);
319
-
320
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws"));
321
- const upgrade = fetchHandle.getUpgradeRequest();
322
- fetchHandle.dispatchWebSocketOpen(upgrade!.connectionId);
323
-
324
- const result = context.evalSync(`globalThis.readyState`);
325
- assert.strictEqual(result, 1);
326
- });
327
-
328
- test("multiple connections are tracked independently", async () => {
329
- context.evalSync(`
330
- globalThis.messages = {};
331
- serve({
332
- fetch(request, server) {
333
- const match = request.url.match(/id=([^&]+)/);
334
- const id = match ? match[1] : "unknown";
335
- server.upgrade(request, { data: { id } });
336
- return new Response(null, { status: 101 });
337
- },
338
- websocket: {
339
- open(ws) {
340
- // Need open handler for connection to be established
341
- },
342
- message(ws, message) {
343
- if (!globalThis.messages[ws.data.id]) {
344
- globalThis.messages[ws.data.id] = [];
345
- }
346
- globalThis.messages[ws.data.id].push(message);
347
- }
348
- }
349
- });
350
- `);
351
-
352
- // Open two connections
353
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws?id=conn1"));
354
- const upgrade1 = fetchHandle.getUpgradeRequest();
355
- fetchHandle.dispatchWebSocketOpen(upgrade1!.connectionId);
356
-
357
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws?id=conn2"));
358
- const upgrade2 = fetchHandle.getUpgradeRequest();
359
- fetchHandle.dispatchWebSocketOpen(upgrade2!.connectionId);
360
-
361
- // Send messages to each
362
- fetchHandle.dispatchWebSocketMessage(upgrade1!.connectionId, "Message to conn1");
363
- fetchHandle.dispatchWebSocketMessage(upgrade2!.connectionId, "Message to conn2");
364
-
365
- const result = context.evalSync(`JSON.stringify(globalThis.messages)`);
366
- const messages = JSON.parse(result as string);
367
- assert.deepStrictEqual(messages, {
368
- conn1: ["Message to conn1"],
369
- conn2: ["Message to conn2"],
370
- });
371
- });
372
-
373
- test("connection is removed after close", async () => {
374
- context.evalSync(`
375
- globalThis.messageCount = 0;
376
- serve({
377
- fetch(request, server) {
378
- server.upgrade(request);
379
- return new Response(null, { status: 101 });
380
- },
381
- websocket: {
382
- open(ws) {
383
- // Need open handler for connection to be established
384
- },
385
- message(ws, message) {
386
- globalThis.messageCount++;
387
- }
388
- }
389
- });
390
- `);
391
-
392
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws"));
393
- const upgrade = fetchHandle.getUpgradeRequest();
394
- fetchHandle.dispatchWebSocketOpen(upgrade!.connectionId);
395
- fetchHandle.dispatchWebSocketMessage(upgrade!.connectionId, "Before close");
396
- fetchHandle.dispatchWebSocketClose(upgrade!.connectionId, 1000, "Normal");
397
-
398
- // Message after close should be ignored
399
- fetchHandle.dispatchWebSocketMessage(upgrade!.connectionId, "After close");
400
-
401
- const result = context.evalSync(`globalThis.messageCount`);
402
- assert.strictEqual(result, 1);
403
- });
404
-
405
- test("hasActiveConnections returns correct state", async () => {
406
- assert.strictEqual(fetchHandle.hasActiveConnections(), false);
407
-
408
- context.evalSync(`
409
- serve({
410
- fetch(request, server) {
411
- server.upgrade(request);
412
- return new Response(null, { status: 101 });
413
- },
414
- websocket: {
415
- open(ws) {}
416
- }
417
- });
418
- `);
419
-
420
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws"));
421
- const upgrade = fetchHandle.getUpgradeRequest();
422
- fetchHandle.dispatchWebSocketOpen(upgrade!.connectionId);
423
-
424
- assert.strictEqual(fetchHandle.hasActiveConnections(), true);
425
-
426
- fetchHandle.dispatchWebSocketClose(upgrade!.connectionId, 1000, "Normal");
427
-
428
- assert.strictEqual(fetchHandle.hasActiveConnections(), false);
429
- });
430
-
431
- describe("close handler data access", () => {
432
- test("close handler can access ws.data set during upgrade", async () => {
433
- context.evalSync(`
434
- globalThis.closeHandlerData = null;
435
- serve({
436
- fetch(request, server) {
437
- server.upgrade(request, { data: { userId: "user123", sessionId: "sess456" } });
438
- return new Response(null, { status: 101 });
439
- },
440
- websocket: {
441
- open(ws) {
442
- // Connection established
443
- },
444
- close(ws, code, reason) {
445
- globalThis.closeHandlerData = ws.data;
446
- }
447
- }
448
- });
449
- `);
450
-
451
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws"));
452
- const upgrade = fetchHandle.getUpgradeRequest();
453
- fetchHandle.dispatchWebSocketOpen(upgrade!.connectionId);
454
- fetchHandle.dispatchWebSocketClose(upgrade!.connectionId, 1000, "Normal");
455
-
456
- const result = context.evalSync(`JSON.stringify(globalThis.closeHandlerData)`);
457
- const data = JSON.parse(result as string);
458
- assert.deepStrictEqual(data, { userId: "user123", sessionId: "sess456" });
459
- });
460
-
461
- test("close handler can access ws.data modified during message handling", async () => {
462
- context.evalSync(`
463
- globalThis.closeHandlerData = null;
464
- serve({
465
- fetch(request, server) {
466
- server.upgrade(request, { data: {} });
467
- return new Response(null, { status: 101 });
468
- },
469
- websocket: {
470
- open(ws) {
471
- // Initial data is empty
472
- },
473
- message(ws, message) {
474
- if (message === "join:Alice") {
475
- ws.data.username = "Alice";
476
- ws.data.joinedAt = Date.now();
477
- }
478
- },
479
- close(ws, code, reason) {
480
- globalThis.closeHandlerData = ws.data;
481
- }
482
- }
483
- });
484
- `);
485
-
486
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws"));
487
- const upgrade = fetchHandle.getUpgradeRequest();
488
- fetchHandle.dispatchWebSocketOpen(upgrade!.connectionId);
489
- fetchHandle.dispatchWebSocketMessage(upgrade!.connectionId, "join:Alice");
490
- fetchHandle.dispatchWebSocketClose(upgrade!.connectionId, 1000, "Normal");
491
-
492
- const result = context.evalSync(`JSON.stringify(globalThis.closeHandlerData)`);
493
- const data = JSON.parse(result as string);
494
- assert.strictEqual(data.username, "Alice");
495
- assert.strictEqual(typeof data.joinedAt, "number");
496
- });
497
-
498
- test("close handler requires open handler for connection tracking", async () => {
499
- context.evalSync(`
500
- globalThis.closeCalled = false;
501
- serve({
502
- fetch(request, server) {
503
- server.upgrade(request, { data: { test: true } });
504
- return new Response(null, { status: 101 });
505
- },
506
- websocket: {
507
- open(ws) {
508
- // Must define open handler for connection tracking
509
- },
510
- close(ws, code, reason) {
511
- globalThis.closeCalled = true;
512
- }
513
- }
514
- });
515
- `);
516
-
517
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws"));
518
- const upgrade = fetchHandle.getUpgradeRequest();
519
- fetchHandle.dispatchWebSocketOpen(upgrade!.connectionId);
520
- fetchHandle.dispatchWebSocketClose(upgrade!.connectionId, 1000, "Normal");
521
-
522
- const result = context.evalSync(`globalThis.closeCalled`);
523
- assert.strictEqual(result, true);
524
- });
525
-
526
- test("multiple connections close handlers receive correct data", async () => {
527
- context.evalSync(`
528
- globalThis.closedUsers = [];
529
- serve({
530
- fetch(request, server) {
531
- const match = request.url.match(/user=([^&]+)/);
532
- const username = match ? match[1] : "unknown";
533
- server.upgrade(request, { data: { username } });
534
- return new Response(null, { status: 101 });
535
- },
536
- websocket: {
537
- open(ws) {
538
- // Connection established
539
- },
540
- close(ws, code, reason) {
541
- globalThis.closedUsers.push(ws.data.username);
542
- }
543
- }
544
- });
545
- `);
546
-
547
- // Open three connections
548
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws?user=Alice"));
549
- const upgrade1 = fetchHandle.getUpgradeRequest();
550
- fetchHandle.dispatchWebSocketOpen(upgrade1!.connectionId);
551
-
552
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws?user=Bob"));
553
- const upgrade2 = fetchHandle.getUpgradeRequest();
554
- fetchHandle.dispatchWebSocketOpen(upgrade2!.connectionId);
555
-
556
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws?user=Charlie"));
557
- const upgrade3 = fetchHandle.getUpgradeRequest();
558
- fetchHandle.dispatchWebSocketOpen(upgrade3!.connectionId);
559
-
560
- // Close them in different order
561
- fetchHandle.dispatchWebSocketClose(upgrade2!.connectionId, 1000, "Normal");
562
- fetchHandle.dispatchWebSocketClose(upgrade1!.connectionId, 1000, "Normal");
563
- fetchHandle.dispatchWebSocketClose(upgrade3!.connectionId, 1000, "Normal");
564
-
565
- const result = context.evalSync(`JSON.stringify(globalThis.closedUsers)`);
566
- const closedUsers = JSON.parse(result as string);
567
- assert.deepStrictEqual(closedUsers, ["Bob", "Alice", "Charlie"]);
568
- });
569
-
570
- test("close handler can broadcast to other connections", async () => {
571
- context.evalSync(`
572
- globalThis.connections = new Map();
573
- globalThis.broadcastMessages = [];
574
- serve({
575
- fetch(request, server) {
576
- const match = request.url.match(/user=([^&]+)/);
577
- const username = match ? match[1] : "unknown";
578
- server.upgrade(request, { data: { username } });
579
- return new Response(null, { status: 101 });
580
- },
581
- websocket: {
582
- open(ws) {
583
- globalThis.connections.set(ws.data.username, ws);
584
- },
585
- close(ws, code, reason) {
586
- const username = ws.data.username;
587
- globalThis.connections.delete(username);
588
- for (const [name, otherWs] of globalThis.connections) {
589
- otherWs.send("userLeft:" + username);
590
- globalThis.broadcastMessages.push({ to: name, about: username });
591
- }
592
- }
593
- }
594
- });
595
- `);
596
-
597
- const commands: WebSocketCommand[] = [];
598
- fetchHandle.onWebSocketCommand((cmd) => {
599
- commands.push(cmd);
600
- });
601
-
602
- // Open three connections
603
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws?user=Alice"));
604
- const upgrade1 = fetchHandle.getUpgradeRequest();
605
- fetchHandle.dispatchWebSocketOpen(upgrade1!.connectionId);
606
-
607
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws?user=Bob"));
608
- const upgrade2 = fetchHandle.getUpgradeRequest();
609
- fetchHandle.dispatchWebSocketOpen(upgrade2!.connectionId);
610
-
611
- await fetchHandle.dispatchRequest(new Request("http://localhost/ws?user=Charlie"));
612
- const upgrade3 = fetchHandle.getUpgradeRequest();
613
- fetchHandle.dispatchWebSocketOpen(upgrade3!.connectionId);
614
-
615
- // Bob disconnects - should broadcast to Alice and Charlie
616
- fetchHandle.dispatchWebSocketClose(upgrade2!.connectionId, 1000, "Normal");
617
-
618
- const result = context.evalSync(`JSON.stringify(globalThis.broadcastMessages)`);
619
- const broadcasts = JSON.parse(result as string);
620
-
621
- // Should have 2 broadcasts (to Alice and Charlie)
622
- assert.strictEqual(broadcasts.length, 2);
623
- assert.deepStrictEqual(broadcasts.map((b: { about: string }) => b.about), ["Bob", "Bob"]);
624
- assert.deepStrictEqual(broadcasts.map((b: { to: string }) => b.to).sort(), ["Alice", "Charlie"]);
625
- });
626
- });
627
- });
package/tsconfig.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "rootDir": "./src"
5
- },
6
- "include": ["src/**/*"],
7
- "exclude": ["node_modules", "dist", "**/*.test.ts"]
8
- }