@computesdk/vercel 1.1.0 → 1.2.0

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
@@ -1,6 +1,6 @@
1
1
  # @computesdk/vercel
2
2
 
3
- Vercel Sandbox provider for ComputeSDK - Execute Node.js and Python code in secure, isolated Vercel sandboxes.
3
+ Vercel provider for ComputeSDK - Execute Node.js and Python code in secure, isolated Vercel sandboxes.
4
4
 
5
5
  ## Installation
6
6
 
@@ -8,7 +8,7 @@ Vercel Sandbox provider for ComputeSDK - Execute Node.js and Python code in secu
8
8
  npm install @computesdk/vercel
9
9
  ```
10
10
 
11
- ## Prerequisites
11
+ ## Authentication
12
12
 
13
13
  Vercel provider supports two authentication methods:
14
14
 
@@ -27,250 +27,223 @@ vercel env pull # Downloads VERCEL_OIDC_TOKEN to .env.local
27
27
 
28
28
  Alternative method using explicit credentials:
29
29
 
30
- - `VERCEL_TOKEN` - Your Vercel access token (get from [Vercel Account Tokens](https://vercel.com/account/tokens))
31
- - `VERCEL_TEAM_ID` - Your Vercel team ID
32
- - `VERCEL_PROJECT_ID` - Your Vercel project ID
30
+ ```bash
31
+ export VERCEL_TOKEN=your_vercel_token_here
32
+ export VERCEL_TEAM_ID=your_team_id_here
33
+ export VERCEL_PROJECT_ID=your_project_id_here
34
+ ```
33
35
 
34
- ## Quick Start
36
+ Get your token from [Vercel Account Tokens](https://vercel.com/account/tokens)
35
37
 
36
- ### Basic Usage
38
+ ## Usage
39
+
40
+ ### With ComputeSDK
37
41
 
38
42
  ```typescript
43
+ import { compute } from 'computesdk';
39
44
  import { vercel } from '@computesdk/vercel';
40
45
 
41
- // Create sandbox with default Node.js runtime
42
- const sandbox = vercel();
46
+ // Set as default provider
47
+ compute.setConfig({
48
+ provider: vercel({ runtime: 'node' })
49
+ });
50
+
51
+ // Create sandbox
52
+ const sandbox = await compute.sandbox.create({});
43
53
 
44
54
  // Execute Node.js code
45
- const result = await sandbox.doExecute('console.log("Hello from Vercel!");');
55
+ const result = await sandbox.runCode('console.log("Hello from Vercel!");');
46
56
  console.log(result.stdout); // "Hello from Vercel!"
47
57
 
48
- // Clean up
49
- await sandbox.doKill();
50
- ```
51
-
52
- ### Python Runtime
53
-
54
- ```typescript
55
- import { vercel } from '@computesdk/vercel';
56
-
57
- // Create sandbox with Python runtime
58
- const sandbox = vercel({ runtime: 'python' });
59
-
60
58
  // Execute Python code
61
- const result = await sandbox.doExecute('print("Hello from Python on Vercel!")');
62
- console.log(result.stdout); // "Hello from Python on Vercel!"
59
+ const pythonResult = await sandbox.runCode('print("Hello from Python!")', 'python');
60
+ console.log(pythonResult.stdout); // "Hello from Python!"
63
61
 
64
- await sandbox.doKill();
62
+ // Clean up
63
+ await compute.sandbox.destroy(sandbox.sandboxId);
65
64
  ```
66
65
 
67
- ### Sandbox Reconnection
66
+ ### Direct Usage
68
67
 
69
68
  ```typescript
70
69
  import { vercel } from '@computesdk/vercel';
71
70
 
72
- // Create a new sandbox
73
- const sandbox1 = vercel();
74
- const result1 = await sandbox1.doExecute('console.log("First execution");');
75
- const sandboxId = sandbox1.sandboxId;
76
-
77
- // Later, reconnect to the same sandbox
78
- const sandbox2 = vercel({ sandboxId });
79
- const result2 = await sandbox2.doExecute('console.log("Reconnected!");');
71
+ // Create provider with explicit config
72
+ const provider = vercel({
73
+ token: 'your-token',
74
+ teamId: 'your-team-id',
75
+ projectId: 'your-project-id',
76
+ runtime: 'python',
77
+ timeout: 600000 // 10 minutes
78
+ });
80
79
 
81
- // Both executions run in the same Vercel sandbox environment
80
+ // Use with compute singleton
81
+ const sandbox = await compute.sandbox.create({ provider });
82
82
  ```
83
83
 
84
- ### With ComputeSDK
85
-
86
- ```typescript
87
- import { vercel } from '@computesdk/vercel';
88
- import { executeSandbox } from 'computesdk';
89
-
90
- // One-off execution
91
- const result = await executeSandbox({
92
- sandbox: vercel({ runtime: 'python' }),
93
- code: `
94
- import json
95
- import datetime
84
+ ## Configuration
96
85
 
97
- data = {
98
- "timestamp": datetime.datetime.now().isoformat(),
99
- "message": "Hello from Vercel Sandbox"
100
- }
86
+ ### Environment Variables
101
87
 
102
- print(json.dumps(data, indent=2))
103
- `
104
- });
88
+ ```bash
89
+ # Method 1: OIDC Token (Recommended)
90
+ export VERCEL_OIDC_TOKEN=your_oidc_token_here
105
91
 
106
- console.log(result.stdout);
92
+ # Method 2: Traditional
93
+ export VERCEL_TOKEN=your_vercel_token_here
94
+ export VERCEL_TEAM_ID=your_team_id_here
95
+ export VERCEL_PROJECT_ID=your_project_id_here
107
96
  ```
108
97
 
109
- ## Configuration
110
-
111
- ### Options
98
+ ### Configuration Options
112
99
 
113
100
  ```typescript
114
101
  interface VercelConfig {
115
- runtime?: 'node' | 'python'; // Default: 'node'
116
- timeout?: number; // Default: 300000 (5 minutes)
117
- sandboxId?: string; // Existing sandbox ID to reconnect to
118
- token?: string; // Vercel API token (fallback to VERCEL_TOKEN)
119
- teamId?: string; // Vercel team ID (fallback to VERCEL_TEAM_ID)
120
- projectId?: string; // Vercel project ID (fallback to VERCEL_PROJECT_ID)
102
+ /** Vercel API token - if not provided, will use VERCEL_TOKEN env var */
103
+ token?: string;
104
+ /** Vercel team ID - if not provided, will use VERCEL_TEAM_ID env var */
105
+ teamId?: string;
106
+ /** Vercel project ID - if not provided, will use VERCEL_PROJECT_ID env var */
107
+ projectId?: string;
108
+ /** Default runtime environment */
109
+ runtime?: 'node' | 'python';
110
+ /** Execution timeout in milliseconds */
111
+ timeout?: number;
121
112
  }
122
113
  ```
123
114
 
124
- ### Example with Custom Configuration
125
-
126
- ```typescript
127
- const sandbox = vercel({
128
- runtime: 'python',
129
- timeout: 600000, // 10 minutes
130
- });
131
- ```
132
-
133
115
  ## Features
134
116
 
135
- ### Supported Runtimes
136
-
137
- - **Node.js 22** (`node`) - Default runtime
138
- - **Python 3.13** (`python`) - Full Python environment
139
-
140
- ### Capabilities
141
-
142
- - **Isolated execution** - Each sandbox runs in its own secure environment
143
- - ✅ **Long-running tasks** - Up to 45 minutes execution time
144
- - ✅ **Standard libraries** - Node.js and Python standard libraries included
145
- - ✅ **Error handling** - Comprehensive error reporting
146
- - ✅ **Stream support** - Real-time stdout/stderr capture
147
- - ✅ **Global deployment** - Runs on Vercel's global infrastructure
148
-
149
- ### Limitations
150
-
151
- - Maximum execution time: 45 minutes (configurable)
152
- - Maximum 8 vCPUs per sandbox (default: 2 vCPUs)
153
- - Memory allocation: 2048 MB per vCPU
117
+ - **Code Execution** - Node.js 22 and Python 3.13 runtime support
118
+ - ✅ **Command Execution** - Run shell commands in sandbox
119
+ - **Filesystem Operations** - Full file system access via shell commands
120
+ - **Auto Runtime Detection** - Automatically detects Python vs Node.js
121
+ - ✅ **Long-running Tasks** - Up to 45 minutes execution time
122
+ - ✅ **Global Infrastructure** - Runs on Vercel's global network
123
+ - ❌ **Interactive Terminals** - Not supported by Vercel Sandbox
124
+ - **Sandbox Reconnection** - Sandboxes are ephemeral (single-use)
154
125
 
155
126
  ## API Reference
156
127
 
157
- ### `vercel(config?)`
158
-
159
- Creates a new Vercel sandbox provider.
160
-
161
- **Parameters:**
162
- - `config` (optional): Configuration object
128
+ ### Code Execution
163
129
 
164
- **Returns:** `VercelProvider` instance
165
-
166
- ### `sandbox.doExecute(code, runtime?)`
130
+ ```typescript
131
+ // Execute Node.js code
132
+ const result = await sandbox.runCode(`
133
+ const data = { message: "Hello from Node.js" };
134
+ console.log(JSON.stringify(data));
135
+ `, 'node');
167
136
 
168
- Executes code in the sandbox.
137
+ // Execute Python code
138
+ const result = await sandbox.runCode(`
139
+ import json
140
+ data = {"message": "Hello from Python"}
141
+ print(json.dumps(data))
142
+ `, 'python');
169
143
 
170
- **Parameters:**
171
- - `code`: String containing the code to execute
172
- - `runtime` (optional): Runtime to use ('node' | 'python')
144
+ // Auto-detection (based on code patterns)
145
+ const result = await sandbox.runCode('print("Auto-detected as Python")');
146
+ ```
173
147
 
174
- **Returns:** `Promise<ExecutionResult>`
148
+ ### Command Execution
175
149
 
176
150
  ```typescript
177
- interface ExecutionResult {
178
- stdout: string;
179
- stderr: string;
180
- exitCode: number;
181
- executionTime: number;
182
- sandboxId: string;
183
- provider: string;
184
- }
185
- ```
151
+ // List files
152
+ const result = await sandbox.runCommand('ls', ['-la']);
186
153
 
187
- ### `sandbox.doGetInfo()`
154
+ // Install packages (Node.js)
155
+ const result = await sandbox.runCommand('npm', ['install', 'lodash']);
188
156
 
189
- Gets information about the sandbox.
157
+ // Install packages (Python)
158
+ const result = await sandbox.runCommand('pip', ['install', 'requests']);
190
159
 
191
- **Returns:** `Promise<SandboxInfo>`
192
-
193
- ```typescript
194
- interface SandboxInfo {
195
- id: string;
196
- provider: string;
197
- runtime: string;
198
- status: 'running' | 'stopped';
199
- createdAt: Date;
200
- timeout: number;
201
- metadata: {
202
- vercelSandboxId: string;
203
- teamId: string;
204
- projectId: string;
205
- vcpus: number;
206
- region: string;
207
- };
208
- }
160
+ // Run scripts
161
+ const result = await sandbox.runCommand('node', ['script.js']);
209
162
  ```
210
163
 
211
- ### `sandbox.doKill()`
212
-
213
- Terminates the sandbox.
164
+ ### Filesystem Operations
214
165
 
215
- **Returns:** `Promise<void>`
166
+ ```typescript
167
+ // Write file
168
+ await sandbox.filesystem.writeFile('/tmp/hello.py', 'print("Hello World")');
216
169
 
217
- ### Filesystem Operations
170
+ // Read file
171
+ const content = await sandbox.filesystem.readFile('/tmp/hello.py');
218
172
 
219
- The Vercel provider supports comprehensive filesystem operations through the `filesystem` property:
173
+ // Create directory
174
+ await sandbox.filesystem.mkdir('/tmp/data');
220
175
 
221
- #### `sandbox.filesystem.readFile(path)`
176
+ // List directory contents
177
+ const files = await sandbox.filesystem.readdir('/tmp');
222
178
 
223
- Reads the contents of a file.
179
+ // Check if file exists
180
+ const exists = await sandbox.filesystem.exists('/tmp/hello.py');
224
181
 
225
- ```typescript
226
- const content = await sandbox.filesystem.readFile('/vercel/sandbox/data.txt');
227
- console.log(content);
182
+ // Remove file or directory
183
+ await sandbox.filesystem.remove('/tmp/hello.py');
228
184
  ```
229
185
 
230
- #### `sandbox.filesystem.writeFile(path, content)`
231
-
232
- Writes content to a file, creating directories as needed.
186
+ ### Sandbox Management
233
187
 
234
188
  ```typescript
235
- await sandbox.filesystem.writeFile('/vercel/sandbox/output.txt', 'Hello World!');
236
- ```
189
+ // Get sandbox info
190
+ const info = await sandbox.getInfo();
191
+ console.log(info.id, info.provider, info.status);
237
192
 
238
- #### `sandbox.filesystem.mkdir(path)`
193
+ // Get existing sandbox
194
+ const existing = await compute.sandbox.getById(provider, 'sandbox-id');
239
195
 
240
- Creates a directory and any necessary parent directories.
196
+ // Destroy sandbox
197
+ await compute.sandbox.destroy(provider, 'sandbox-id');
241
198
 
242
- ```typescript
243
- await sandbox.filesystem.mkdir('/vercel/sandbox/project/data');
199
+ // Note: Vercel doesn't support listing all sandboxes
200
+ // Each sandbox is ephemeral and single-use
244
201
  ```
245
202
 
246
- #### `sandbox.filesystem.readdir(path)`
203
+ ## Runtime Detection
247
204
 
248
- Lists the contents of a directory.
205
+ The provider automatically detects the runtime based on code patterns:
249
206
 
250
- ```typescript
251
- const entries = await sandbox.filesystem.readdir('/vercel/sandbox');
252
- entries.forEach(entry => {
253
- console.log(`${entry.name} (${entry.isDirectory ? 'directory' : 'file'}) - ${entry.size} bytes`);
254
- });
255
- ```
207
+ **Python indicators:**
208
+ - `print(` statements
209
+ - `import` statements
210
+ - `def` function definitions
211
+ - Python-specific syntax (`f"`, `__`, etc.)
256
212
 
257
- #### `sandbox.filesystem.exists(path)`
213
+ **Default:** Node.js for all other cases
258
214
 
259
- Checks if a file or directory exists.
215
+ ## Error Handling
260
216
 
261
217
  ```typescript
262
- const exists = await sandbox.filesystem.exists('/vercel/sandbox/config.json');
263
- if (exists) {
264
- console.log('Configuration file found!');
218
+ try {
219
+ const result = await sandbox.runCode('invalid code');
220
+ } catch (error) {
221
+ if (error.message.includes('Missing Vercel authentication')) {
222
+ console.error('Set VERCEL_OIDC_TOKEN or VERCEL_TOKEN environment variables');
223
+ } else if (error.message.includes('authentication failed')) {
224
+ console.error('Check your Vercel credentials');
225
+ } else if (error.message.includes('team/project configuration failed')) {
226
+ console.error('Check your VERCEL_TEAM_ID and VERCEL_PROJECT_ID');
227
+ } else if (error.message.includes('Syntax error')) {
228
+ console.error('Code has syntax errors');
229
+ }
265
230
  }
266
231
  ```
267
232
 
268
- #### `sandbox.filesystem.remove(path)`
233
+ ## Web Framework Integration
269
234
 
270
- Removes a file or directory.
235
+ Use with web frameworks via the request handler:
271
236
 
272
237
  ```typescript
273
- await sandbox.filesystem.remove('/vercel/sandbox/temp.txt');
238
+ import { handleComputeRequest } from 'computesdk';
239
+ import { vercel } from '@computesdk/vercel';
240
+
241
+ export async function POST(request: Request) {
242
+ return handleComputeRequest({
243
+ request,
244
+ provider: vercel({ runtime: 'node' })
245
+ });
246
+ }
274
247
  ```
275
248
 
276
249
  ## Examples
@@ -278,11 +251,11 @@ await sandbox.filesystem.remove('/vercel/sandbox/temp.txt');
278
251
  ### Node.js Web Server Simulation
279
252
 
280
253
  ```typescript
281
- import { vercel } from '@computesdk/vercel';
282
-
283
- const sandbox = vercel({ runtime: 'node' });
254
+ const sandbox = await compute.sandbox.create({
255
+ provider: vercel({ runtime: 'node' })
256
+ });
284
257
 
285
- const result = await sandbox.doExecute(`
258
+ const result = await sandbox.runCode(`
286
259
  const http = require('http');
287
260
  const url = require('url');
288
261
 
@@ -294,7 +267,10 @@ const routes = {
294
267
  { id: 2, name: 'Bob', role: 'Designer' }
295
268
  ]
296
269
  }),
297
- '/api/health': () => ({ status: 'healthy', timestamp: new Date().toISOString() })
270
+ '/api/health': () => ({
271
+ status: 'healthy',
272
+ timestamp: new Date().toISOString()
273
+ })
298
274
  };
299
275
 
300
276
  // Process request
@@ -310,11 +286,11 @@ console.log(result.stdout);
310
286
  ### Python Data Processing
311
287
 
312
288
  ```typescript
313
- import { vercel } from '@computesdk/vercel';
314
-
315
- const sandbox = vercel({ runtime: 'python' });
289
+ const sandbox = await compute.sandbox.create({
290
+ provider: vercel({ runtime: 'python' })
291
+ });
316
292
 
317
- const result = await sandbox.doExecute(`
293
+ const result = await sandbox.runCode(`
318
294
  import json
319
295
  import statistics
320
296
  from collections import Counter
@@ -350,64 +326,61 @@ for product, revenue in sorted(product_sales.items(), key=lambda x: x[1], revers
350
326
  console.log(result.stdout);
351
327
  ```
352
328
 
353
- ### Filesystem Operations Example
329
+ ### Filesystem Operations Pipeline
354
330
 
355
331
  ```typescript
356
- import { vercel } from '@computesdk/vercel';
332
+ const sandbox = await compute.sandbox.create({
333
+ provider: vercel({ runtime: 'python' })
334
+ });
357
335
 
358
- const sandbox = vercel({ runtime: 'python' });
336
+ // Create project structure
337
+ await sandbox.filesystem.mkdir('/tmp/project');
338
+ await sandbox.filesystem.mkdir('/tmp/project/data');
339
+ await sandbox.filesystem.mkdir('/tmp/project/output');
340
+
341
+ // Create configuration file
342
+ const config = {
343
+ project_name: "Vercel Data Pipeline",
344
+ version: "1.0.0",
345
+ settings: {
346
+ input_format: "json",
347
+ output_format: "csv",
348
+ debug: true
349
+ }
350
+ };
359
351
 
360
- // Create a complete data processing pipeline using filesystem operations
361
- try {
362
- // 1. Set up project structure
363
- await sandbox.filesystem.mkdir('/vercel/sandbox/project');
364
- await sandbox.filesystem.mkdir('/vercel/sandbox/project/data');
365
- await sandbox.filesystem.mkdir('/vercel/sandbox/project/output');
366
-
367
- // 2. Create configuration file
368
- const config = {
369
- project_name: "Vercel Data Pipeline",
370
- version: "1.0.0",
371
- settings: {
372
- input_format: "json",
373
- output_format: "csv",
374
- debug: true
375
- }
376
- };
377
-
378
- await sandbox.filesystem.writeFile(
379
- '/vercel/sandbox/project/config.json',
380
- JSON.stringify(config, null, 2)
381
- );
382
-
383
- // 3. Create sample data
384
- const sampleData = [
385
- { id: 1, name: "Alice", department: "Engineering", salary: 95000 },
386
- { id: 2, name: "Bob", department: "Marketing", salary: 75000 },
387
- { id: 3, name: "Charlie", department: "Engineering", salary: 105000 },
388
- { id: 4, name: "Diana", department: "Sales", salary: 85000 }
389
- ];
390
-
391
- await sandbox.filesystem.writeFile(
392
- '/vercel/sandbox/project/data/employees.json',
393
- JSON.stringify(sampleData, null, 2)
394
- );
395
-
396
- // 4. Create and execute data processing script
397
- const processingScript = `
352
+ await sandbox.filesystem.writeFile(
353
+ '/tmp/project/config.json',
354
+ JSON.stringify(config, null, 2)
355
+ );
356
+
357
+ // Create sample data
358
+ const sampleData = [
359
+ { id: 1, name: "Alice", department: "Engineering", salary: 95000 },
360
+ { id: 2, name: "Bob", department: "Marketing", salary: 75000 },
361
+ { id: 3, name: "Charlie", department: "Engineering", salary: 105000 },
362
+ { id: 4, name: "Diana", department: "Sales", salary: 85000 }
363
+ ];
364
+
365
+ await sandbox.filesystem.writeFile(
366
+ '/tmp/project/data/employees.json',
367
+ JSON.stringify(sampleData, null, 2)
368
+ );
369
+
370
+ // Process data
371
+ const result = await sandbox.runCode(`
398
372
  import json
399
373
  import csv
400
- import os
401
374
  from collections import defaultdict
402
375
 
403
376
  # Read configuration
404
- with open('/vercel/sandbox/project/config.json', 'r') as f:
377
+ with open('/tmp/project/config.json', 'r') as f:
405
378
  config = json.load(f)
406
379
 
407
380
  print(f"Running {config['project_name']} v{config['version']}")
408
381
 
409
382
  # Read employee data
410
- with open('/vercel/sandbox/project/data/employees.json', 'r') as f:
383
+ with open('/tmp/project/data/employees.json', 'r') as f:
411
384
  employees = json.load(f)
412
385
 
413
386
  # Process data - calculate department statistics
@@ -430,11 +403,11 @@ for dept, salaries in dept_stats.items():
430
403
  results.sort(key=lambda x: x['average_salary'], reverse=True)
431
404
 
432
405
  # Write results as JSON
433
- with open('/vercel/sandbox/project/output/department_stats.json', 'w') as f:
406
+ with open('/tmp/project/output/department_stats.json', 'w') as f:
434
407
  json.dump(results, f, indent=2)
435
408
 
436
409
  # Write results as CSV
437
- with open('/vercel/sandbox/project/output/department_stats.csv', 'w', newline='') as f:
410
+ with open('/tmp/project/output/department_stats.csv', 'w', newline='') as f:
438
411
  writer = csv.DictWriter(f, fieldnames=['department', 'employee_count', 'average_salary', 'total_salary'])
439
412
  writer.writeheader()
440
413
  writer.writerows(results)
@@ -445,117 +418,87 @@ print(f"Generated {len(results)} department statistics")
445
418
  # Print summary
446
419
  for result in results:
447
420
  print(f"{result['department']}: {result['employee_count']} employees, avg salary ${result['average_salary']}")
448
- `;
449
-
450
- await sandbox.filesystem.writeFile('/vercel/sandbox/project/process.py', processingScript);
451
-
452
- // 5. Execute the processing script
453
- const result = await sandbox.doExecute('python /vercel/sandbox/project/process.py');
454
- console.log('Execution Output:', result.stdout);
455
-
456
- // 6. Read and display results
457
- const jsonResults = await sandbox.filesystem.readFile('/vercel/sandbox/project/output/department_stats.json');
458
- const csvResults = await sandbox.filesystem.readFile('/vercel/sandbox/project/output/department_stats.csv');
421
+ `);
459
422
 
460
- console.log('JSON Results:', jsonResults);
461
- console.log('CSV Results:', csvResults);
423
+ console.log('Execution Output:', result.stdout);
462
424
 
463
- // 7. List all generated files
464
- const outputFiles = await sandbox.filesystem.readdir('/vercel/sandbox/project/output');
465
- console.log('Generated files:');
466
- outputFiles.forEach(file => {
467
- console.log(` ${file.name} (${file.size} bytes)`);
468
- });
425
+ // Read and display results
426
+ const jsonResults = await sandbox.filesystem.readFile('/tmp/project/output/department_stats.json');
427
+ const csvResults = await sandbox.filesystem.readFile('/tmp/project/output/department_stats.csv');
469
428
 
470
- // 8. Verify file existence
471
- const configExists = await sandbox.filesystem.exists('/vercel/sandbox/project/config.json');
472
- const resultsExist = await sandbox.filesystem.exists('/vercel/sandbox/project/output/department_stats.json');
473
-
474
- console.log(`Configuration file exists: ${configExists}`);
475
- console.log(`Results file exists: ${resultsExist}`);
429
+ console.log('JSON Results:', jsonResults);
430
+ console.log('CSV Results:', csvResults);
476
431
 
477
- } catch (error) {
478
- console.error('Pipeline failed:', error.message);
479
- } finally {
480
- await sandbox.doKill();
481
- }
432
+ // List all generated files
433
+ const outputFiles = await sandbox.filesystem.readdir('/tmp/project/output');
434
+ console.log('Generated files:');
435
+ outputFiles.forEach(file => {
436
+ console.log(` ${file.name} (${file.size} bytes)`);
437
+ });
482
438
  ```
483
439
 
484
- ## Error Handling
485
-
486
- The provider includes comprehensive error handling:
440
+ ### Package Installation and Usage
487
441
 
488
442
  ```typescript
489
- import { vercel } from '@computesdk/vercel';
490
-
491
- try {
492
- const sandbox = vercel();
493
- const result = await sandbox.doExecute('invalid syntax here');
494
- } catch (error) {
495
- if (error.message.includes('timeout')) {
496
- console.error('Execution timed out');
497
- } else if (error.message.includes('memory')) {
498
- console.error('Memory limit exceeded');
499
- } else if (error.message.includes('authentication')) {
500
- console.error('Check your VERCEL_TOKEN');
501
- } else {
502
- console.error('Execution failed:', error.message);
503
- }
504
- }
505
- ```
443
+ // Node.js example with package installation
444
+ const sandbox = await compute.sandbox.create({
445
+ provider: vercel({ runtime: 'node' })
446
+ });
506
447
 
507
- ## Authentication Setup
448
+ // Install lodash
449
+ const installResult = await sandbox.runCommand('npm', ['install', 'lodash']);
450
+ console.log('Install result:', installResult.stdout);
508
451
 
509
- 1. **Get Vercel Token:**
510
- - Go to [Vercel Account Tokens](https://vercel.com/account/tokens)
511
- - Create a new token with appropriate permissions
512
- - Set as `VERCEL_TOKEN` environment variable
452
+ // Use lodash in code
453
+ const result = await sandbox.runCode(`
454
+ const _ = require('lodash');
513
455
 
514
- 2. **Get Team and Project IDs:**
515
- - Find your team ID in the Vercel dashboard URL
516
- - Find your project ID in the project settings
517
- - Set as `VERCEL_TEAM_ID` and `VERCEL_PROJECT_ID`
456
+ const data = [
457
+ { name: 'Alice', age: 25, city: 'New York' },
458
+ { name: 'Bob', age: 30, city: 'San Francisco' },
459
+ { name: 'Charlie', age: 35, city: 'Chicago' }
460
+ ];
518
461
 
519
- 3. **Environment Variables:**
520
- ```bash
521
- export VERCEL_TOKEN=your_vercel_token_here
522
- export VERCEL_TEAM_ID=your_team_id_here
523
- export VERCEL_PROJECT_ID=your_project_id_here
524
- ```
462
+ // Group by city
463
+ const grouped = _.groupBy(data, 'city');
464
+ console.log('Grouped by city:', JSON.stringify(grouped, null, 2));
525
465
 
526
- ## Testing
466
+ // Calculate average age
467
+ const avgAge = _.meanBy(data, 'age');
468
+ console.log('Average age:', avgAge);
527
469
 
528
- Run the test suite:
470
+ // Find oldest person
471
+ const oldest = _.maxBy(data, 'age');
472
+ console.log('Oldest person:', oldest.name);
473
+ `);
529
474
 
530
- ```bash
531
- npm test
475
+ console.log(result.stdout);
532
476
  ```
533
477
 
534
- Run tests with coverage:
478
+ ## Best Practices
535
479
 
536
- ```bash
537
- npm run test:coverage
538
- ```
539
-
540
- ## Development
480
+ 1. **Authentication**: Use OIDC token method when possible for simpler setup
481
+ 2. **Resource Management**: Destroy sandboxes when done (they're ephemeral anyway)
482
+ 3. **Error Handling**: Use try-catch blocks for robust error handling
483
+ 4. **Timeouts**: Set appropriate timeouts for long-running tasks (up to 45 minutes)
484
+ 5. **File Organization**: Use the filesystem API to organize project files
485
+ 6. **Package Installation**: Install packages at runtime as needed
541
486
 
542
- Build the package:
487
+ ## Limitations
543
488
 
544
- ```bash
545
- npm run build
546
- ```
489
+ - **Ephemeral Sandboxes**: Each sandbox is single-use and cannot be reconnected to
490
+ - **No Sandbox Listing**: Vercel doesn't support listing all sandboxes
491
+ - **No Interactive Terminals**: Terminal operations are not supported
492
+ - **Memory Limits**: Subject to Vercel sandbox memory constraints (2048 MB per vCPU)
493
+ - **Execution Time**: Maximum 45 minutes execution time
494
+ - **Network Access**: Limited outbound network access
547
495
 
548
- Run in development mode:
496
+ ## Support
549
497
 
550
- ```bash
551
- npm run dev
552
- ```
498
+ - [Vercel Documentation](https://vercel.com/docs)
499
+ - [ComputeSDK Issues](https://github.com/computesdk/computesdk/issues)
500
+ - [Vercel Support](https://vercel.com/support)
553
501
 
554
502
  ## License
555
503
 
556
- MIT - see LICENSE file for details.
557
-
558
- ## Support
559
-
560
- - [GitHub Issues](https://github.com/computesdk/computesdk/issues)
561
- - [ComputeSDK Documentation](https://github.com/computesdk/computesdk)
504
+ MIT