@computesdk/vercel 1.0.0 → 1.1.1
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 +337 -169
- package/dist/index.d.mts +21 -18
- package/dist/index.d.ts +21 -18
- package/dist/index.js +300 -193
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +301 -183
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -8
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,187 +8,254 @@ 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
|
|
|
15
|
-
|
|
16
|
-
- `VERCEL_TEAM_ID` - Your Vercel team ID
|
|
17
|
-
- `VERCEL_PROJECT_ID` - Your Vercel project ID
|
|
15
|
+
### Method 1: OIDC Token (Recommended)
|
|
18
16
|
|
|
19
|
-
|
|
17
|
+
The simplest way to authenticate. Vercel manages token expiration automatically.
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
**Development:**
|
|
20
|
+
```bash
|
|
21
|
+
vercel env pull # Downloads VERCEL_OIDC_TOKEN to .env.local
|
|
22
|
+
```
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
import { vercel } from '@computesdk/vercel';
|
|
24
|
+
**Production:** Vercel automatically provides `VERCEL_OIDC_TOKEN` in your deployment environment.
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
const sandbox = vercel();
|
|
26
|
+
### Method 2: Access Token + Team/Project IDs
|
|
28
27
|
|
|
29
|
-
|
|
30
|
-
const result = await sandbox.doExecute('console.log("Hello from Vercel!");');
|
|
31
|
-
console.log(result.stdout); // "Hello from Vercel!"
|
|
28
|
+
Alternative method using explicit credentials:
|
|
32
29
|
|
|
33
|
-
|
|
34
|
-
|
|
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
|
|
35
34
|
```
|
|
36
35
|
|
|
37
|
-
|
|
36
|
+
Get your token from [Vercel Account Tokens](https://vercel.com/account/tokens)
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
### With ComputeSDK
|
|
38
41
|
|
|
39
42
|
```typescript
|
|
43
|
+
import { compute } from 'computesdk';
|
|
40
44
|
import { vercel } from '@computesdk/vercel';
|
|
41
45
|
|
|
42
|
-
//
|
|
43
|
-
|
|
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({});
|
|
53
|
+
|
|
54
|
+
// Execute Node.js code
|
|
55
|
+
const result = await sandbox.runCode('console.log("Hello from Vercel!");');
|
|
56
|
+
console.log(result.stdout); // "Hello from Vercel!"
|
|
44
57
|
|
|
45
58
|
// Execute Python code
|
|
46
|
-
const
|
|
47
|
-
console.log(
|
|
59
|
+
const pythonResult = await sandbox.runCode('print("Hello from Python!")', 'python');
|
|
60
|
+
console.log(pythonResult.stdout); // "Hello from Python!"
|
|
48
61
|
|
|
49
|
-
|
|
62
|
+
// Clean up
|
|
63
|
+
await compute.sandbox.destroy(sandbox.sandboxId);
|
|
50
64
|
```
|
|
51
65
|
|
|
52
|
-
###
|
|
66
|
+
### Direct Usage
|
|
53
67
|
|
|
54
68
|
```typescript
|
|
55
69
|
import { vercel } from '@computesdk/vercel';
|
|
56
|
-
import { executeSandbox } from 'computesdk';
|
|
57
70
|
|
|
58
|
-
//
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
data = {
|
|
66
|
-
"timestamp": datetime.datetime.now().isoformat(),
|
|
67
|
-
"message": "Hello from Vercel Sandbox"
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
print(json.dumps(data, indent=2))
|
|
71
|
-
`
|
|
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
|
|
72
78
|
});
|
|
73
79
|
|
|
74
|
-
|
|
80
|
+
// Use with compute singleton
|
|
81
|
+
const sandbox = await compute.sandbox.create({ provider });
|
|
75
82
|
```
|
|
76
83
|
|
|
77
84
|
## Configuration
|
|
78
85
|
|
|
79
|
-
###
|
|
86
|
+
### Environment Variables
|
|
80
87
|
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
88
|
+
```bash
|
|
89
|
+
# Method 1: OIDC Token (Recommended)
|
|
90
|
+
export VERCEL_OIDC_TOKEN=your_oidc_token_here
|
|
91
|
+
|
|
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
|
|
87
96
|
```
|
|
88
97
|
|
|
89
|
-
###
|
|
98
|
+
### Configuration Options
|
|
90
99
|
|
|
91
100
|
```typescript
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
101
|
+
interface VercelConfig {
|
|
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;
|
|
112
|
+
}
|
|
96
113
|
```
|
|
97
114
|
|
|
98
115
|
## Features
|
|
99
116
|
|
|
100
|
-
|
|
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)
|
|
125
|
+
|
|
126
|
+
## API Reference
|
|
127
|
+
|
|
128
|
+
### Code Execution
|
|
129
|
+
|
|
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');
|
|
136
|
+
|
|
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');
|
|
101
143
|
|
|
102
|
-
-
|
|
103
|
-
|
|
144
|
+
// Auto-detection (based on code patterns)
|
|
145
|
+
const result = await sandbox.runCode('print("Auto-detected as Python")');
|
|
146
|
+
```
|
|
104
147
|
|
|
105
|
-
###
|
|
148
|
+
### Command Execution
|
|
106
149
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
- ✅ **Error handling** - Comprehensive error reporting
|
|
111
|
-
- ✅ **Stream support** - Real-time stdout/stderr capture
|
|
112
|
-
- ✅ **Global deployment** - Runs on Vercel's global infrastructure
|
|
150
|
+
```typescript
|
|
151
|
+
// List files
|
|
152
|
+
const result = await sandbox.runCommand('ls', ['-la']);
|
|
113
153
|
|
|
114
|
-
|
|
154
|
+
// Install packages (Node.js)
|
|
155
|
+
const result = await sandbox.runCommand('npm', ['install', 'lodash']);
|
|
115
156
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
- Memory allocation: 2048 MB per vCPU
|
|
157
|
+
// Install packages (Python)
|
|
158
|
+
const result = await sandbox.runCommand('pip', ['install', 'requests']);
|
|
119
159
|
|
|
120
|
-
|
|
160
|
+
// Run scripts
|
|
161
|
+
const result = await sandbox.runCommand('node', ['script.js']);
|
|
162
|
+
```
|
|
121
163
|
|
|
122
|
-
###
|
|
164
|
+
### Filesystem Operations
|
|
123
165
|
|
|
124
|
-
|
|
166
|
+
```typescript
|
|
167
|
+
// Write file
|
|
168
|
+
await sandbox.filesystem.writeFile('/tmp/hello.py', 'print("Hello World")');
|
|
125
169
|
|
|
126
|
-
|
|
127
|
-
|
|
170
|
+
// Read file
|
|
171
|
+
const content = await sandbox.filesystem.readFile('/tmp/hello.py');
|
|
128
172
|
|
|
129
|
-
|
|
173
|
+
// Create directory
|
|
174
|
+
await sandbox.filesystem.mkdir('/tmp/data');
|
|
130
175
|
|
|
131
|
-
|
|
176
|
+
// List directory contents
|
|
177
|
+
const files = await sandbox.filesystem.readdir('/tmp');
|
|
132
178
|
|
|
133
|
-
|
|
179
|
+
// Check if file exists
|
|
180
|
+
const exists = await sandbox.filesystem.exists('/tmp/hello.py');
|
|
134
181
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
182
|
+
// Remove file or directory
|
|
183
|
+
await sandbox.filesystem.remove('/tmp/hello.py');
|
|
184
|
+
```
|
|
138
185
|
|
|
139
|
-
|
|
186
|
+
### Sandbox Management
|
|
140
187
|
|
|
141
188
|
```typescript
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
189
|
+
// Get sandbox info
|
|
190
|
+
const info = await sandbox.getInfo();
|
|
191
|
+
console.log(info.id, info.provider, info.status);
|
|
192
|
+
|
|
193
|
+
// Get existing sandbox
|
|
194
|
+
const existing = await compute.sandbox.getById(provider, 'sandbox-id');
|
|
195
|
+
|
|
196
|
+
// Destroy sandbox
|
|
197
|
+
await compute.sandbox.destroy(provider, 'sandbox-id');
|
|
198
|
+
|
|
199
|
+
// Note: Vercel doesn't support listing all sandboxes
|
|
200
|
+
// Each sandbox is ephemeral and single-use
|
|
150
201
|
```
|
|
151
202
|
|
|
152
|
-
|
|
203
|
+
## Runtime Detection
|
|
204
|
+
|
|
205
|
+
The provider automatically detects the runtime based on code patterns:
|
|
206
|
+
|
|
207
|
+
**Python indicators:**
|
|
208
|
+
- `print(` statements
|
|
209
|
+
- `import` statements
|
|
210
|
+
- `def` function definitions
|
|
211
|
+
- Python-specific syntax (`f"`, `__`, etc.)
|
|
153
212
|
|
|
154
|
-
|
|
213
|
+
**Default:** Node.js for all other cases
|
|
155
214
|
|
|
156
|
-
|
|
215
|
+
## Error Handling
|
|
157
216
|
|
|
158
217
|
```typescript
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
region: string;
|
|
172
|
-
};
|
|
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
|
+
}
|
|
173
230
|
}
|
|
174
231
|
```
|
|
175
232
|
|
|
176
|
-
|
|
233
|
+
## Web Framework Integration
|
|
234
|
+
|
|
235
|
+
Use with web frameworks via the request handler:
|
|
177
236
|
|
|
178
|
-
|
|
237
|
+
```typescript
|
|
238
|
+
import { handleComputeRequest } from 'computesdk';
|
|
239
|
+
import { vercel } from '@computesdk/vercel';
|
|
179
240
|
|
|
180
|
-
|
|
241
|
+
export async function POST(request: Request) {
|
|
242
|
+
return handleComputeRequest({
|
|
243
|
+
request,
|
|
244
|
+
provider: vercel({ runtime: 'node' })
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
```
|
|
181
248
|
|
|
182
249
|
## Examples
|
|
183
250
|
|
|
184
251
|
### Node.js Web Server Simulation
|
|
185
252
|
|
|
186
253
|
```typescript
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
254
|
+
const sandbox = await compute.sandbox.create({
|
|
255
|
+
provider: vercel({ runtime: 'node' })
|
|
256
|
+
});
|
|
190
257
|
|
|
191
|
-
const result = await sandbox.
|
|
258
|
+
const result = await sandbox.runCode(`
|
|
192
259
|
const http = require('http');
|
|
193
260
|
const url = require('url');
|
|
194
261
|
|
|
@@ -200,7 +267,10 @@ const routes = {
|
|
|
200
267
|
{ id: 2, name: 'Bob', role: 'Designer' }
|
|
201
268
|
]
|
|
202
269
|
}),
|
|
203
|
-
'/api/health': () => ({
|
|
270
|
+
'/api/health': () => ({
|
|
271
|
+
status: 'healthy',
|
|
272
|
+
timestamp: new Date().toISOString()
|
|
273
|
+
})
|
|
204
274
|
};
|
|
205
275
|
|
|
206
276
|
// Process request
|
|
@@ -216,11 +286,11 @@ console.log(result.stdout);
|
|
|
216
286
|
### Python Data Processing
|
|
217
287
|
|
|
218
288
|
```typescript
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
289
|
+
const sandbox = await compute.sandbox.create({
|
|
290
|
+
provider: vercel({ runtime: 'python' })
|
|
291
|
+
});
|
|
222
292
|
|
|
223
|
-
const result = await sandbox.
|
|
293
|
+
const result = await sandbox.runCode(`
|
|
224
294
|
import json
|
|
225
295
|
import statistics
|
|
226
296
|
from collections import Counter
|
|
@@ -256,81 +326,179 @@ for product, revenue in sorted(product_sales.items(), key=lambda x: x[1], revers
|
|
|
256
326
|
console.log(result.stdout);
|
|
257
327
|
```
|
|
258
328
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
The provider includes comprehensive error handling:
|
|
329
|
+
### Filesystem Operations Pipeline
|
|
262
330
|
|
|
263
331
|
```typescript
|
|
264
|
-
|
|
332
|
+
const sandbox = await compute.sandbox.create({
|
|
333
|
+
provider: vercel({ runtime: 'python' })
|
|
334
|
+
});
|
|
265
335
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
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
|
|
278
349
|
}
|
|
279
|
-
}
|
|
280
|
-
```
|
|
350
|
+
};
|
|
281
351
|
|
|
282
|
-
|
|
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(`
|
|
372
|
+
import json
|
|
373
|
+
import csv
|
|
374
|
+
from collections import defaultdict
|
|
375
|
+
|
|
376
|
+
# Read configuration
|
|
377
|
+
with open('/tmp/project/config.json', 'r') as f:
|
|
378
|
+
config = json.load(f)
|
|
379
|
+
|
|
380
|
+
print(f"Running {config['project_name']} v{config['version']}")
|
|
381
|
+
|
|
382
|
+
# Read employee data
|
|
383
|
+
with open('/tmp/project/data/employees.json', 'r') as f:
|
|
384
|
+
employees = json.load(f)
|
|
385
|
+
|
|
386
|
+
# Process data - calculate department statistics
|
|
387
|
+
dept_stats = defaultdict(list)
|
|
388
|
+
for emp in employees:
|
|
389
|
+
dept_stats[emp['department']].append(emp['salary'])
|
|
390
|
+
|
|
391
|
+
# Calculate averages
|
|
392
|
+
results = []
|
|
393
|
+
for dept, salaries in dept_stats.items():
|
|
394
|
+
avg_salary = sum(salaries) / len(salaries)
|
|
395
|
+
results.append({
|
|
396
|
+
'department': dept,
|
|
397
|
+
'employee_count': len(salaries),
|
|
398
|
+
'average_salary': round(avg_salary, 2),
|
|
399
|
+
'total_salary': sum(salaries)
|
|
400
|
+
})
|
|
401
|
+
|
|
402
|
+
# Sort by average salary
|
|
403
|
+
results.sort(key=lambda x: x['average_salary'], reverse=True)
|
|
404
|
+
|
|
405
|
+
# Write results as JSON
|
|
406
|
+
with open('/tmp/project/output/department_stats.json', 'w') as f:
|
|
407
|
+
json.dump(results, f, indent=2)
|
|
408
|
+
|
|
409
|
+
# Write results as CSV
|
|
410
|
+
with open('/tmp/project/output/department_stats.csv', 'w', newline='') as f:
|
|
411
|
+
writer = csv.DictWriter(f, fieldnames=['department', 'employee_count', 'average_salary', 'total_salary'])
|
|
412
|
+
writer.writeheader()
|
|
413
|
+
writer.writerows(results)
|
|
414
|
+
|
|
415
|
+
print("Processing complete!")
|
|
416
|
+
print(f"Generated {len(results)} department statistics")
|
|
417
|
+
|
|
418
|
+
# Print summary
|
|
419
|
+
for result in results:
|
|
420
|
+
print(f"{result['department']}: {result['employee_count']} employees, avg salary ${result['average_salary']}")
|
|
421
|
+
`);
|
|
283
422
|
|
|
284
|
-
|
|
285
|
-
- Go to [Vercel Account Tokens](https://vercel.com/account/tokens)
|
|
286
|
-
- Create a new token with appropriate permissions
|
|
287
|
-
- Set as `VERCEL_TOKEN` environment variable
|
|
423
|
+
console.log('Execution Output:', result.stdout);
|
|
288
424
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
- Set as `VERCEL_TEAM_ID` and `VERCEL_PROJECT_ID`
|
|
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');
|
|
293
428
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
export VERCEL_TOKEN=your_vercel_token_here
|
|
297
|
-
export VERCEL_TEAM_ID=your_team_id_here
|
|
298
|
-
export VERCEL_PROJECT_ID=your_project_id_here
|
|
299
|
-
```
|
|
429
|
+
console.log('JSON Results:', jsonResults);
|
|
430
|
+
console.log('CSV Results:', csvResults);
|
|
300
431
|
|
|
301
|
-
|
|
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
|
+
});
|
|
438
|
+
```
|
|
302
439
|
|
|
303
|
-
|
|
440
|
+
### Package Installation and Usage
|
|
304
441
|
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
|
|
442
|
+
```typescript
|
|
443
|
+
// Node.js example with package installation
|
|
444
|
+
const sandbox = await compute.sandbox.create({
|
|
445
|
+
provider: vercel({ runtime: 'node' })
|
|
446
|
+
});
|
|
308
447
|
|
|
309
|
-
|
|
448
|
+
// Install lodash
|
|
449
|
+
const installResult = await sandbox.runCommand('npm', ['install', 'lodash']);
|
|
450
|
+
console.log('Install result:', installResult.stdout);
|
|
310
451
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
452
|
+
// Use lodash in code
|
|
453
|
+
const result = await sandbox.runCode(`
|
|
454
|
+
const _ = require('lodash');
|
|
314
455
|
|
|
315
|
-
|
|
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
|
+
];
|
|
316
461
|
|
|
317
|
-
|
|
462
|
+
// Group by city
|
|
463
|
+
const grouped = _.groupBy(data, 'city');
|
|
464
|
+
console.log('Grouped by city:', JSON.stringify(grouped, null, 2));
|
|
318
465
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
466
|
+
// Calculate average age
|
|
467
|
+
const avgAge = _.meanBy(data, 'age');
|
|
468
|
+
console.log('Average age:', avgAge);
|
|
322
469
|
|
|
323
|
-
|
|
470
|
+
// Find oldest person
|
|
471
|
+
const oldest = _.maxBy(data, 'age');
|
|
472
|
+
console.log('Oldest person:', oldest.name);
|
|
473
|
+
`);
|
|
324
474
|
|
|
325
|
-
|
|
326
|
-
npm run dev
|
|
475
|
+
console.log(result.stdout);
|
|
327
476
|
```
|
|
328
477
|
|
|
329
|
-
##
|
|
478
|
+
## Best Practices
|
|
479
|
+
|
|
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
|
|
486
|
+
|
|
487
|
+
## Limitations
|
|
330
488
|
|
|
331
|
-
|
|
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
|
|
332
495
|
|
|
333
496
|
## Support
|
|
334
497
|
|
|
335
|
-
- [
|
|
336
|
-
- [ComputeSDK
|
|
498
|
+
- [Vercel Documentation](https://vercel.com/docs)
|
|
499
|
+
- [ComputeSDK Issues](https://github.com/computesdk/computesdk/issues)
|
|
500
|
+
- [Vercel Support](https://vercel.com/support)
|
|
501
|
+
|
|
502
|
+
## License
|
|
503
|
+
|
|
504
|
+
MIT
|
package/dist/index.d.mts
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as computesdk from 'computesdk';
|
|
2
|
+
import { Runtime } from 'computesdk';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
doGetInfo(): Promise<SandboxInfo>;
|
|
4
|
+
/**
|
|
5
|
+
* Vercel-specific configuration options
|
|
6
|
+
*/
|
|
7
|
+
interface VercelConfig {
|
|
8
|
+
/** Vercel API token - if not provided, will fallback to VERCEL_TOKEN environment variable */
|
|
9
|
+
token?: string;
|
|
10
|
+
/** Vercel team ID - if not provided, will fallback to VERCEL_TEAM_ID environment variable */
|
|
11
|
+
teamId?: string;
|
|
12
|
+
/** Vercel project ID - if not provided, will fallback to VERCEL_PROJECT_ID environment variable */
|
|
13
|
+
projectId?: string;
|
|
14
|
+
/** Default runtime environment */
|
|
15
|
+
runtime?: Runtime;
|
|
16
|
+
/** Execution timeout in milliseconds */
|
|
17
|
+
timeout?: number;
|
|
18
18
|
}
|
|
19
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Create a Vercel provider instance using the factory pattern
|
|
21
|
+
*/
|
|
22
|
+
declare const vercel: (config: VercelConfig) => computesdk.Provider;
|
|
20
23
|
|
|
21
|
-
export {
|
|
24
|
+
export { type VercelConfig, vercel };
|