@cloudflare/sandbox 0.0.0-1a42464 โ†’ 0.0.0-1be7d53

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/README.md CHANGED
@@ -17,6 +17,10 @@
17
17
  - [Basic Setup](#basic-setup)
18
18
  - [๐Ÿ“š API Reference](#api-reference)
19
19
  - [Core Methods](#core-methods)
20
+ - [๐Ÿงช Code Interpreter](#code-interpreter)
21
+ - [Code Execution](#code-execution)
22
+ - [Rich Outputs](#rich-outputs)
23
+ - [Output Formats](#output-formats)
20
24
  - [๐ŸŒ Port Forwarding](#port-forwarding)
21
25
  - [Utility Methods](#utility-methods)
22
26
  - [๐Ÿ’ก Examples](#examples)
@@ -24,6 +28,7 @@
24
28
  - [Build and Test Code](#build-and-test-code)
25
29
  - [Interactive Development Environment](#interactive-development-environment)
26
30
  - [Expose Services with Preview URLs](#expose-services-with-preview-urls)
31
+ - [Data Analysis with Code Interpreter](#data-analysis-with-code-interpreter)
27
32
  - [๐Ÿ—๏ธ Architecture](#architecture)
28
33
  - [๐Ÿ› ๏ธ Advanced Usage](#advanced-usage)
29
34
  - [AsyncIterable Streaming Support](#asynciterable-streaming-support)
@@ -45,11 +50,15 @@ The Cloudflare Sandbox SDK enables you to run isolated code environments directl
45
50
  - **๐Ÿ”’ Secure Isolation**: Each sandbox runs in its own container with full process isolation
46
51
  - **โšก Edge-Native**: Runs on Cloudflare's global network for low latency worldwide
47
52
  - **๐Ÿ“ File System Access**: Read, write, and manage files within the sandbox
53
+ - **๐Ÿ–ผ๏ธ Binary File Support**: Automatic MIME type detection and base64 encoding for images, PDFs, and other binary files
48
54
  - **๐Ÿ”ง Command Execution**: Run any command or process inside the container
49
55
  - **๐ŸŒ Preview URLs**: Expose services running in your sandbox via public URLs
50
56
  - **๐Ÿ”„ Git Integration**: Clone repositories directly into sandboxes
51
- - **๐Ÿš€ Streaming Support**: Real-time output streaming for long-running commands
57
+ - **๐Ÿš€ Streaming Support**: Real-time output streaming for long-running commands and file transfers
52
58
  - **๐ŸŽฎ Session Management**: Maintain state across multiple operations
59
+ - **๐Ÿงช Code Interpreter**: Execute Python and JavaScript with rich outputs (charts, tables, formatted data)
60
+ - **๐Ÿ“Š Multi-Language Support**: Persistent execution contexts for Python and JavaScript/TypeScript
61
+ - **๐ŸŽจ Rich MIME Types**: Automatic processing of images, HTML, charts, and structured data
53
62
 
54
63
  <h2 id="quick-start">๐Ÿš€ Quick Start</h2>
55
64
 
@@ -64,12 +73,10 @@ npm install @cloudflare/sandbox
64
73
  1. **Create a Dockerfile** (temporary requirement, will be removed in future releases):
65
74
 
66
75
  ```dockerfile
67
- FROM docker.io/cloudflare/sandbox:0.1.2
76
+ FROM docker.io/cloudflare/sandbox:0.3.6
68
77
 
78
+ # Expose the ports you want to expose
69
79
  EXPOSE 3000
70
-
71
- # Run the same command as the original image
72
- CMD ["bun", "index.ts"]
73
80
  ```
74
81
 
75
82
  2. **Configure wrangler.json**:
@@ -83,7 +90,7 @@ CMD ["bun", "index.ts"]
83
90
  {
84
91
  "class_name": "Sandbox",
85
92
  "image": "./Dockerfile",
86
- "max_instances": 1
93
+ "max_instances": 20
87
94
  }
88
95
  ],
89
96
  "durable_objects": {
@@ -178,16 +185,62 @@ for await (const log of parseSSEStream<LogEvent>(logStream)) {
178
185
  Write content to a file.
179
186
 
180
187
  ```typescript
181
- await sandbox.writeFile("/app.js", "console.log('Hello!');");
188
+ await sandbox.writeFile("/workspace/app.js", "console.log('Hello!');");
182
189
  ```
183
190
 
184
191
  #### `readFile(path, options?)`
185
192
 
186
- Read a file from the sandbox.
193
+ Read a file from the sandbox with automatic binary detection.
187
194
 
188
195
  ```typescript
196
+ // Read text files
189
197
  const file = await sandbox.readFile("/package.json");
190
- console.log(file.content);
198
+ console.log(file.content); // UTF-8 text content
199
+
200
+ // Read binary files - automatically detected and base64 encoded
201
+ const image = await sandbox.readFile("/workspace/chart.png");
202
+ console.log(image.mimeType); // "image/png"
203
+ console.log(image.isBinary); // true
204
+ console.log(image.encoding); // "base64"
205
+ console.log(image.size); // File size in bytes
206
+
207
+ // Use the base64 content directly in data URLs
208
+ const dataUrl = `data:${image.mimeType};base64,${image.content}`;
209
+ ```
210
+
211
+ #### `readFileStream(path)`
212
+
213
+ Stream large files efficiently with automatic chunking and encoding.
214
+
215
+ ```typescript
216
+ import { streamFile, collectFile } from '@cloudflare/sandbox';
217
+
218
+ // Stream a large file
219
+ const stream = await sandbox.readFileStream("/large-video.mp4");
220
+
221
+ // Option 1: Process chunks as they arrive
222
+ for await (const chunk of streamFile(stream)) {
223
+ if (chunk instanceof Uint8Array) {
224
+ // Binary chunk - already decoded from base64
225
+ console.log(`Received ${chunk.byteLength} bytes`);
226
+ // Process binary data...
227
+ } else {
228
+ // Text chunk
229
+ console.log('Text:', chunk);
230
+ }
231
+ }
232
+
233
+ // Option 2: Collect entire file into memory
234
+ const { content, metadata } = await collectFile(stream);
235
+ console.log(`MIME: ${metadata.mimeType}, Size: ${metadata.size} bytes`);
236
+
237
+ if (content instanceof Uint8Array) {
238
+ // Binary file - ready to save or process
239
+ await writeToStorage(content);
240
+ } else {
241
+ // Text file
242
+ console.log('Content:', content);
243
+ }
191
244
  ```
192
245
 
193
246
  #### `gitCheckout(repoUrl, options?)`
@@ -235,7 +288,8 @@ console.log(result.stdout); // "production"
235
288
  #### File System Methods
236
289
 
237
290
  - `writeFile(path, content, options?)` - Write content to a file
238
- - `readFile(path, options?)` - Read a file from the sandbox
291
+ - `readFile(path, options?)` - Read a file with automatic binary detection and base64 encoding
292
+ - `readFileStream(path)` - Stream large files efficiently with chunking
239
293
  - `mkdir(path, options?)` - Create a directory
240
294
  - `deleteFile(path)` - Delete a file
241
295
  - `renameFile(oldPath, newPath)` - Rename a file
@@ -248,6 +302,131 @@ console.log(result.stdout); // "production"
248
302
  - `unexposePort(port)` - Remove port exposure
249
303
  - `getExposedPorts()` - List all exposed ports with their URLs
250
304
 
305
+ #### Session Methods
306
+
307
+ - `createSession(options)` - Create an isolated execution session
308
+ - `name`: Session identifier
309
+ - `env`: Environment variables for this session
310
+ - `cwd`: Working directory
311
+ - `isolation`: Enable PID namespace isolation (requires CAP_SYS_ADMIN)
312
+
313
+ <h2 id="code-interpreter">๐Ÿงช Code Interpreter</h2>
314
+
315
+ The Sandbox SDK includes powerful code interpreter capabilities, allowing you to execute Python and JavaScript code with rich outputs including charts, tables, and formatted data.
316
+
317
+ ### Code Execution
318
+
319
+ #### `createCodeContext(options?)`
320
+
321
+ Creates a new code execution context with persistent state.
322
+
323
+ ```typescript
324
+ // Create a Python context
325
+ const pythonCtx = await sandbox.createCodeContext({ language: 'python' });
326
+
327
+ // Create a JavaScript context
328
+ const jsCtx = await sandbox.createCodeContext({ language: 'javascript' });
329
+ ```
330
+
331
+ **Options:**
332
+ - `language`: Programming language (`'python'` | `'javascript'` | `'typescript'`)
333
+ - `cwd`: Working directory (default: `/workspace`)
334
+ - `envVars`: Environment variables for the context
335
+
336
+ #### `runCode(code, options?)`
337
+
338
+ Executes code with optional streaming callbacks.
339
+
340
+ ```typescript
341
+ // Simple execution
342
+ const execution = await sandbox.runCode('print("Hello World")', {
343
+ context: pythonCtx
344
+ });
345
+
346
+ // With streaming callbacks
347
+ await sandbox.runCode(`
348
+ for i in range(5):
349
+ print(f"Step {i}")
350
+ time.sleep(1)
351
+ `, {
352
+ context: pythonCtx,
353
+ onStdout: (output) => console.log('Real-time:', output.text),
354
+ onResult: (result) => console.log('Result:', result)
355
+ });
356
+ ```
357
+
358
+ **Options:**
359
+ - `context`: Context to run the code in
360
+ - `language`: Language if no context provided
361
+ - `onStdout`: Callback for stdout output
362
+ - `onStderr`: Callback for stderr output
363
+ - `onResult`: Callback for execution results
364
+ - `onError`: Callback for errors
365
+
366
+ #### `runCodeStream(code, options?)`
367
+
368
+ Returns a streaming response for real-time processing.
369
+
370
+ ```typescript
371
+ const stream = await sandbox.runCodeStream('import time; [print(i) for i in range(10)]');
372
+ // Process the stream as needed
373
+ ```
374
+
375
+ ### Rich Outputs
376
+
377
+ The code interpreter automatically detects and processes various output types:
378
+
379
+ ```typescript
380
+ // Data visualization
381
+ const execution = await sandbox.runCode(`
382
+ import matplotlib.pyplot as plt
383
+ import numpy as np
384
+
385
+ x = np.linspace(0, 10, 100)
386
+ y = np.sin(x)
387
+ plt.plot(x, y)
388
+ plt.title('Sine Wave')
389
+ plt.show()
390
+ `, {
391
+ context: pythonCtx,
392
+ onResult: (result) => {
393
+ if (result.png) {
394
+ // Base64 encoded PNG image
395
+ console.log('Chart generated!');
396
+ }
397
+ }
398
+ });
399
+
400
+ // HTML tables with pandas
401
+ const tableExecution = await sandbox.runCode(`
402
+ import pandas as pd
403
+ df = pd.DataFrame({
404
+ 'name': ['Alice', 'Bob', 'Charlie'],
405
+ 'score': [92, 88, 95]
406
+ })
407
+ df
408
+ `, { context: pythonCtx });
409
+
410
+ // Access HTML table in execution.results[0].html
411
+ ```
412
+
413
+ ### Output Formats
414
+
415
+ Results can include multiple formats:
416
+ - `text`: Plain text representation
417
+ - `html`: HTML (often pandas DataFrames)
418
+ - `png`/`jpeg`: Base64 encoded images
419
+ - `svg`: Vector graphics
420
+ - `json`: Structured data
421
+ - `chart`: Parsed chart information
422
+
423
+ Check available formats with `result.formats()`.
424
+
425
+ #### Additional Code Interpreter Methods
426
+
427
+ - `listCodeContexts()` - List all active code contexts
428
+ - `deleteCodeContext(contextId)` - Delete a specific context
429
+
251
430
  <h2 id="port-forwarding">๐ŸŒ Port Forwarding</h2>
252
431
 
253
432
  The SDK automatically handles preview URL routing for exposed ports. Just add one line to your worker:
@@ -284,7 +463,7 @@ The SDK handles:
284
463
 
285
464
  ```dockerfile
286
465
  # In your Dockerfile (only needed for local dev)
287
- FROM oven/bun:latest
466
+ FROM docker.io/cloudflare/sandbox:0.1.3
288
467
 
289
468
  # Expose the ports you'll be using
290
469
  EXPOSE 3000 # For a web server
@@ -316,7 +495,7 @@ const sandbox = getSandbox(env.Sandbox, "node-app");
316
495
 
317
496
  // Write a simple Express server
318
497
  await sandbox.writeFile(
319
- "/app.js",
498
+ "/workspace/app.js",
320
499
  `
321
500
  const express = require('express');
322
501
  const app = express();
@@ -406,14 +585,100 @@ console.log(`Service available at: ${preview.url}`);
406
585
  // See the example in examples/basic/src/index.ts for the routing implementation.
407
586
  ```
408
587
 
588
+ ### Data Analysis with Code Interpreter
589
+
590
+ ```typescript
591
+ const sandbox = getSandbox(env.Sandbox, "analysis");
592
+
593
+ // Create a Python context for data analysis
594
+ const pythonCtx = await sandbox.createCodeContext({ language: 'python' });
595
+
596
+ // Load and analyze data
597
+ const analysis = await sandbox.runCode(`
598
+ import pandas as pd
599
+ import matplotlib.pyplot as plt
600
+
601
+ # Create sample data
602
+ data = {
603
+ 'Month': ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
604
+ 'Sales': [10000, 12000, 15000, 14000, 18000],
605
+ 'Profit': [2000, 2500, 3200, 2800, 4000]
606
+ }
607
+ df = pd.DataFrame(data)
608
+
609
+ # Display summary statistics
610
+ print("Sales Summary:")
611
+ print(df.describe())
612
+
613
+ # Create visualization
614
+ plt.figure(figsize=(10, 6))
615
+ plt.subplot(1, 2, 1)
616
+ plt.bar(df['Month'], df['Sales'])
617
+ plt.title('Monthly Sales')
618
+ plt.xlabel('Month')
619
+ plt.ylabel('Sales ($)')
620
+
621
+ plt.subplot(1, 2, 2)
622
+ plt.plot(df['Month'], df['Profit'], marker='o', color='green')
623
+ plt.title('Monthly Profit')
624
+ plt.xlabel('Month')
625
+ plt.ylabel('Profit ($)')
626
+
627
+ plt.tight_layout()
628
+ plt.show()
629
+
630
+ # Return the data as JSON
631
+ df.to_dict('records')
632
+ `, {
633
+ context: pythonCtx,
634
+ onResult: (result) => {
635
+ if (result.png) {
636
+ // Handle the chart image
637
+ console.log('Chart generated:', result.png.substring(0, 50) + '...');
638
+ }
639
+ if (result.json) {
640
+ // Handle the structured data
641
+ console.log('Data:', result.json);
642
+ }
643
+ }
644
+ });
645
+
646
+ // Multi-language workflow: Process in Python, analyze in JavaScript
647
+ await sandbox.runCode(`
648
+ # Save processed data
649
+ df.to_json('/tmp/sales_data.json', orient='records')
650
+ `, { context: pythonCtx });
651
+
652
+ const jsCtx = await sandbox.createCodeContext({ language: 'javascript' });
653
+ const jsAnalysis = await sandbox.runCode(`
654
+ const fs = require('fs');
655
+ const data = JSON.parse(fs.readFileSync('/tmp/sales_data.json', 'utf8'));
656
+
657
+ // Calculate growth rate
658
+ const growth = data.map((curr, idx) => {
659
+ if (idx === 0) return { ...curr, growth: 0 };
660
+ const prev = data[idx - 1];
661
+ return {
662
+ ...curr,
663
+ growth: ((curr.Sales - prev.Sales) / prev.Sales * 100).toFixed(2) + '%'
664
+ };
665
+ });
666
+
667
+ console.log('Growth Analysis:', growth);
668
+ growth;
669
+ `, { context: jsCtx });
670
+ ```
671
+
409
672
  <h2 id="architecture">๐Ÿ—๏ธ Architecture</h2>
410
673
 
411
674
  The SDK leverages Cloudflare's infrastructure:
412
675
 
413
676
  - **Durable Objects**: Manages sandbox lifecycle and state
414
- - **Containers**: Provides isolated execution environments
677
+ - **Containers**: Provides isolated execution environments with Jupyter kernels
415
678
  - **Workers**: Handles HTTP routing and API interface
416
679
  - **Edge Network**: Enables global distribution and low latency
680
+ - **Jupyter Integration**: Python (IPython) and JavaScript (TSLab) kernels for code execution
681
+ - **MIME Processing**: Automatic detection and handling of rich output formats
417
682
 
418
683
  <h2 id="advanced-usage">๐Ÿ› ๏ธ Advanced Usage</h2>
419
684
 
@@ -448,10 +713,15 @@ for await (const event of parseSSEStream<ExecEvent>(stream)) {
448
713
 
449
714
  The SDK exports utilities for working with Server-Sent Event streams:
450
715
 
716
+ **Command Execution:**
451
717
  - **`parseSSEStream<T>(stream)`** - Convert ReadableStream to typed AsyncIterable
452
718
  - **`responseToAsyncIterable<T>(response)`** - Convert SSE Response to AsyncIterable
453
719
  - **`asyncIterableToSSEStream<T>(iterable)`** - Convert AsyncIterable back to SSE stream
454
720
 
721
+ **File Streaming:**
722
+ - **`streamFile(stream, signal?)`** - Convert file SSE stream to AsyncIterable with automatic base64 decoding
723
+ - **`collectFile(stream, signal?)`** - Collect entire file from stream into memory
724
+
455
725
  #### Advanced Streaming Examples
456
726
 
457
727
  **CI/CD Build System:**
@@ -494,17 +764,71 @@ for await (const log of parseSSEStream<LogEvent>(logStream)) {
494
764
 
495
765
  ### Session Management
496
766
 
497
- Maintain context across commands:
767
+ The SDK provides two approaches for managing execution context:
768
+
769
+ #### Implicit Sessions (Recommended)
770
+
771
+ Each sandbox maintains its own persistent session automatically:
772
+
773
+ ```typescript
774
+ const sandbox = getSandbox(env.Sandbox, "my-app");
775
+
776
+ // These commands share state (pwd, env vars, etc.)
777
+ await sandbox.exec("cd /app");
778
+ await sandbox.exec("pwd"); // Output: /app
779
+ await sandbox.exec("export MY_VAR=hello");
780
+ await sandbox.exec("echo $MY_VAR"); // Output: hello
781
+ ```
782
+
783
+ #### Explicit Sessions for Advanced Use Cases
784
+
785
+ Create isolated execution contexts within the same sandbox:
498
786
 
499
787
  ```typescript
500
- const sessionId = crypto.randomUUID();
788
+ const sandbox = getSandbox(env.Sandbox, "multi-env");
789
+
790
+ // Create independent sessions with different environments
791
+ const buildSession = await sandbox.createSession({
792
+ name: "build",
793
+ env: { NODE_ENV: "production" },
794
+ cwd: "/build"
795
+ });
501
796
 
502
- // Commands in the same session share working directory
503
- await sandbox.exec("cd /app", { sessionId });
504
- await sandbox.exec("npm install", { sessionId });
505
- const app = await sandbox.startProcess("npm start", { sessionId });
797
+ const testSession = await sandbox.createSession({
798
+ name: "test",
799
+ env: { NODE_ENV: "test" },
800
+ cwd: "/test"
801
+ });
802
+
803
+ // Run commands in parallel with different contexts
804
+ await Promise.all([
805
+ buildSession.exec("npm run build"),
806
+ testSession.exec("npm test")
807
+ ]);
506
808
  ```
507
809
 
810
+ #### Security with AI Agents
811
+
812
+ When using AI coding agents, separate development from execution:
813
+
814
+ ```typescript
815
+ // Phase 1: AI agent writes code (with API keys)
816
+ const devSession = await sandbox.createSession({
817
+ name: "ai-development",
818
+ env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY }
819
+ });
820
+ await devSession.exec('opencode "build a web server"');
821
+
822
+ // Phase 2: Run the generated code (without API keys)
823
+ const appSession = await sandbox.createSession({
824
+ name: "app-runtime",
825
+ env: { PORT: "3000" } // Only app-specific vars
826
+ });
827
+ await appSession.exec("node server.js");
828
+ ```
829
+
830
+ > **Best Practice**: Keep AI agent credentials separate from your application runtime to prevent accidental exposure of API keys.
831
+
508
832
  <h2 id="debugging">๐Ÿ” Debugging</h2>
509
833
 
510
834
  Enable verbose logging:
@@ -523,6 +847,9 @@ sandbox.client.onCommandComplete = (success, code) =>
523
847
  - Maximum container runtime is limited by Durable Object constraints
524
848
  - WebSocket support for preview URLs coming soon
525
849
  - Some system calls may be restricted in the container environment
850
+ - Code interpreter has no internet access (sandbox restriction)
851
+ - Some Python/JavaScript packages may not be pre-installed
852
+ - Resource limits apply to code execution (CPU, memory)
526
853
 
527
854
  <h2 id="contributing">๐Ÿค Contributing</h2>
528
855
 
@@ -536,11 +863,21 @@ cd sandbox-sdk
536
863
  # Install dependencies
537
864
  npm install
538
865
 
866
+ # Install Bun (if not already installed)
867
+ # Visit https://bun.sh for installation instructions
868
+ curl -fsSL https://bun.sh/install | bash
869
+
870
+ # Install container dependencies (required for TypeScript checking)
871
+ cd packages/sandbox/container_src && bun install && cd -
872
+
539
873
  # Run tests
540
874
  npm test
541
875
 
542
876
  # Build the project
543
877
  npm run build
878
+
879
+ # Run type checking and linting
880
+ npm run check
544
881
  ```
545
882
 
546
883
  <h2 id="license">๐Ÿ“„ License</h2>
@@ -0,0 +1,76 @@
1
+ {
2
+ "lockfileVersion": 1,
3
+ "workspaces": {
4
+ "": {
5
+ "name": "sandbox-server",
6
+ "dependencies": {
7
+ "esbuild": "^0.21.5",
8
+ "uuid": "^9.0.1",
9
+ },
10
+ "devDependencies": {
11
+ "@types/node": "^20.0.0",
12
+ "@types/uuid": "^9.0.7",
13
+ "typescript": "^5.3.0",
14
+ },
15
+ },
16
+ },
17
+ "packages": {
18
+ "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
19
+
20
+ "@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="],
21
+
22
+ "@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="],
23
+
24
+ "@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="],
25
+
26
+ "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="],
27
+
28
+ "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="],
29
+
30
+ "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="],
31
+
32
+ "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="],
33
+
34
+ "@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="],
35
+
36
+ "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="],
37
+
38
+ "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="],
39
+
40
+ "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="],
41
+
42
+ "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="],
43
+
44
+ "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="],
45
+
46
+ "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="],
47
+
48
+ "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="],
49
+
50
+ "@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="],
51
+
52
+ "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="],
53
+
54
+ "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="],
55
+
56
+ "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="],
57
+
58
+ "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="],
59
+
60
+ "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="],
61
+
62
+ "@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="],
63
+
64
+ "@types/node": ["@types/node@20.19.16", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-VS6TTONVdgwJwtJr7U+ghEjpfmQdqehLLpg/iMYGOd1+ilaFjdBJwFuPggJ4EAYPDCzWfDUHoIxyVnu+tOWVuQ=="],
65
+
66
+ "@types/uuid": ["@types/uuid@9.0.8", "", {}, "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA=="],
67
+
68
+ "esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="],
69
+
70
+ "typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="],
71
+
72
+ "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
73
+
74
+ "uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="],
75
+ }
76
+ }