@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 +258 -315
- package/dist/index.d.mts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +55 -150
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +55 -150
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @computesdk/vercel
|
|
2
2
|
|
|
3
|
-
Vercel
|
|
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
|
-
##
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
|
|
36
|
+
Get your token from [Vercel Account Tokens](https://vercel.com/account/tokens)
|
|
35
37
|
|
|
36
|
-
|
|
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
|
-
//
|
|
42
|
-
|
|
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.
|
|
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
|
|
62
|
-
console.log(
|
|
59
|
+
const pythonResult = await sandbox.runCode('print("Hello from Python!")', 'python');
|
|
60
|
+
console.log(pythonResult.stdout); // "Hello from Python!"
|
|
63
61
|
|
|
64
|
-
|
|
62
|
+
// Clean up
|
|
63
|
+
await compute.sandbox.destroy(sandbox.sandboxId);
|
|
65
64
|
```
|
|
66
65
|
|
|
67
|
-
###
|
|
66
|
+
### Direct Usage
|
|
68
67
|
|
|
69
68
|
```typescript
|
|
70
69
|
import { vercel } from '@computesdk/vercel';
|
|
71
70
|
|
|
72
|
-
// Create
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
-
//
|
|
80
|
+
// Use with compute singleton
|
|
81
|
+
const sandbox = await compute.sandbox.create({ provider });
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
|
|
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
|
-
|
|
98
|
-
"timestamp": datetime.datetime.now().isoformat(),
|
|
99
|
-
"message": "Hello from Vercel Sandbox"
|
|
100
|
-
}
|
|
86
|
+
### Environment Variables
|
|
101
87
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
88
|
+
```bash
|
|
89
|
+
# Method 1: OIDC Token (Recommended)
|
|
90
|
+
export VERCEL_OIDC_TOKEN=your_oidc_token_here
|
|
105
91
|
|
|
106
|
-
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
### Options
|
|
98
|
+
### Configuration Options
|
|
112
99
|
|
|
113
100
|
```typescript
|
|
114
101
|
interface VercelConfig {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
projectId?: string;
|
|
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
|
-
|
|
136
|
-
|
|
137
|
-
- **
|
|
138
|
-
- **
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
-
|
|
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
|
-
###
|
|
158
|
-
|
|
159
|
-
Creates a new Vercel sandbox provider.
|
|
160
|
-
|
|
161
|
-
**Parameters:**
|
|
162
|
-
- `config` (optional): Configuration object
|
|
128
|
+
### Code Execution
|
|
163
129
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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
|
-
|
|
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
|
-
|
|
171
|
-
|
|
172
|
-
|
|
144
|
+
// Auto-detection (based on code patterns)
|
|
145
|
+
const result = await sandbox.runCode('print("Auto-detected as Python")');
|
|
146
|
+
```
|
|
173
147
|
|
|
174
|
-
|
|
148
|
+
### Command Execution
|
|
175
149
|
|
|
176
150
|
```typescript
|
|
177
|
-
|
|
178
|
-
|
|
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
|
-
|
|
154
|
+
// Install packages (Node.js)
|
|
155
|
+
const result = await sandbox.runCommand('npm', ['install', 'lodash']);
|
|
188
156
|
|
|
189
|
-
|
|
157
|
+
// Install packages (Python)
|
|
158
|
+
const result = await sandbox.runCommand('pip', ['install', 'requests']);
|
|
190
159
|
|
|
191
|
-
|
|
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
|
-
###
|
|
212
|
-
|
|
213
|
-
Terminates the sandbox.
|
|
164
|
+
### Filesystem Operations
|
|
214
165
|
|
|
215
|
-
|
|
166
|
+
```typescript
|
|
167
|
+
// Write file
|
|
168
|
+
await sandbox.filesystem.writeFile('/tmp/hello.py', 'print("Hello World")');
|
|
216
169
|
|
|
217
|
-
|
|
170
|
+
// Read file
|
|
171
|
+
const content = await sandbox.filesystem.readFile('/tmp/hello.py');
|
|
218
172
|
|
|
219
|
-
|
|
173
|
+
// Create directory
|
|
174
|
+
await sandbox.filesystem.mkdir('/tmp/data');
|
|
220
175
|
|
|
221
|
-
|
|
176
|
+
// List directory contents
|
|
177
|
+
const files = await sandbox.filesystem.readdir('/tmp');
|
|
222
178
|
|
|
223
|
-
|
|
179
|
+
// Check if file exists
|
|
180
|
+
const exists = await sandbox.filesystem.exists('/tmp/hello.py');
|
|
224
181
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
console.log(content);
|
|
182
|
+
// Remove file or directory
|
|
183
|
+
await sandbox.filesystem.remove('/tmp/hello.py');
|
|
228
184
|
```
|
|
229
185
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
Writes content to a file, creating directories as needed.
|
|
186
|
+
### Sandbox Management
|
|
233
187
|
|
|
234
188
|
```typescript
|
|
235
|
-
|
|
236
|
-
|
|
189
|
+
// Get sandbox info
|
|
190
|
+
const info = await sandbox.getInfo();
|
|
191
|
+
console.log(info.id, info.provider, info.status);
|
|
237
192
|
|
|
238
|
-
|
|
193
|
+
// Get existing sandbox
|
|
194
|
+
const existing = await compute.sandbox.getById(provider, 'sandbox-id');
|
|
239
195
|
|
|
240
|
-
|
|
196
|
+
// Destroy sandbox
|
|
197
|
+
await compute.sandbox.destroy(provider, 'sandbox-id');
|
|
241
198
|
|
|
242
|
-
|
|
243
|
-
|
|
199
|
+
// Note: Vercel doesn't support listing all sandboxes
|
|
200
|
+
// Each sandbox is ephemeral and single-use
|
|
244
201
|
```
|
|
245
202
|
|
|
246
|
-
|
|
203
|
+
## Runtime Detection
|
|
247
204
|
|
|
248
|
-
|
|
205
|
+
The provider automatically detects the runtime based on code patterns:
|
|
249
206
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
```
|
|
207
|
+
**Python indicators:**
|
|
208
|
+
- `print(` statements
|
|
209
|
+
- `import` statements
|
|
210
|
+
- `def` function definitions
|
|
211
|
+
- Python-specific syntax (`f"`, `__`, etc.)
|
|
256
212
|
|
|
257
|
-
|
|
213
|
+
**Default:** Node.js for all other cases
|
|
258
214
|
|
|
259
|
-
|
|
215
|
+
## Error Handling
|
|
260
216
|
|
|
261
217
|
```typescript
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
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
|
-
|
|
233
|
+
## Web Framework Integration
|
|
269
234
|
|
|
270
|
-
|
|
235
|
+
Use with web frameworks via the request handler:
|
|
271
236
|
|
|
272
237
|
```typescript
|
|
273
|
-
|
|
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
|
-
|
|
282
|
-
|
|
283
|
-
|
|
254
|
+
const sandbox = await compute.sandbox.create({
|
|
255
|
+
provider: vercel({ runtime: 'node' })
|
|
256
|
+
});
|
|
284
257
|
|
|
285
|
-
const result = await sandbox.
|
|
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': () => ({
|
|
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
|
-
|
|
314
|
-
|
|
315
|
-
|
|
289
|
+
const sandbox = await compute.sandbox.create({
|
|
290
|
+
provider: vercel({ runtime: 'python' })
|
|
291
|
+
});
|
|
316
292
|
|
|
317
|
-
const result = await sandbox.
|
|
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
|
|
329
|
+
### Filesystem Operations Pipeline
|
|
354
330
|
|
|
355
331
|
```typescript
|
|
356
|
-
|
|
332
|
+
const sandbox = await compute.sandbox.create({
|
|
333
|
+
provider: vercel({ runtime: 'python' })
|
|
334
|
+
});
|
|
357
335
|
|
|
358
|
-
|
|
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
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
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('/
|
|
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('/
|
|
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('/
|
|
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('/
|
|
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
|
-
|
|
461
|
-
console.log('CSV Results:', csvResults);
|
|
423
|
+
console.log('Execution Output:', result.stdout);
|
|
462
424
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
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
|
-
|
|
471
|
-
|
|
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
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
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
|
-
|
|
485
|
-
|
|
486
|
-
The provider includes comprehensive error handling:
|
|
440
|
+
### Package Installation and Usage
|
|
487
441
|
|
|
488
442
|
```typescript
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
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
|
-
|
|
448
|
+
// Install lodash
|
|
449
|
+
const installResult = await sandbox.runCommand('npm', ['install', 'lodash']);
|
|
450
|
+
console.log('Install result:', installResult.stdout);
|
|
508
451
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
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
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
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
|
-
|
|
520
|
-
|
|
521
|
-
|
|
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
|
-
|
|
466
|
+
// Calculate average age
|
|
467
|
+
const avgAge = _.meanBy(data, 'age');
|
|
468
|
+
console.log('Average age:', avgAge);
|
|
527
469
|
|
|
528
|
-
|
|
470
|
+
// Find oldest person
|
|
471
|
+
const oldest = _.maxBy(data, 'age');
|
|
472
|
+
console.log('Oldest person:', oldest.name);
|
|
473
|
+
`);
|
|
529
474
|
|
|
530
|
-
|
|
531
|
-
npm test
|
|
475
|
+
console.log(result.stdout);
|
|
532
476
|
```
|
|
533
477
|
|
|
534
|
-
|
|
478
|
+
## Best Practices
|
|
535
479
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
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
|
-
|
|
487
|
+
## Limitations
|
|
543
488
|
|
|
544
|
-
|
|
545
|
-
|
|
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
|
-
|
|
496
|
+
## Support
|
|
549
497
|
|
|
550
|
-
|
|
551
|
-
|
|
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
|
|
557
|
-
|
|
558
|
-
## Support
|
|
559
|
-
|
|
560
|
-
- [GitHub Issues](https://github.com/computesdk/computesdk/issues)
|
|
561
|
-
- [ComputeSDK Documentation](https://github.com/computesdk/computesdk)
|
|
504
|
+
MIT
|