@computesdk/vercel 1.0.0 → 1.1.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 +228 -3
- 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
|
@@ -10,7 +10,22 @@ npm install @computesdk/vercel
|
|
|
10
10
|
|
|
11
11
|
## Prerequisites
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Vercel provider supports two authentication methods:
|
|
14
|
+
|
|
15
|
+
### Method 1: OIDC Token (Recommended)
|
|
16
|
+
|
|
17
|
+
The simplest way to authenticate. Vercel manages token expiration automatically.
|
|
18
|
+
|
|
19
|
+
**Development:**
|
|
20
|
+
```bash
|
|
21
|
+
vercel env pull # Downloads VERCEL_OIDC_TOKEN to .env.local
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Production:** Vercel automatically provides `VERCEL_OIDC_TOKEN` in your deployment environment.
|
|
25
|
+
|
|
26
|
+
### Method 2: Access Token + Team/Project IDs
|
|
27
|
+
|
|
28
|
+
Alternative method using explicit credentials:
|
|
14
29
|
|
|
15
30
|
- `VERCEL_TOKEN` - Your Vercel access token (get from [Vercel Account Tokens](https://vercel.com/account/tokens))
|
|
16
31
|
- `VERCEL_TEAM_ID` - Your Vercel team ID
|
|
@@ -49,6 +64,23 @@ console.log(result.stdout); // "Hello from Python on Vercel!"
|
|
|
49
64
|
await sandbox.doKill();
|
|
50
65
|
```
|
|
51
66
|
|
|
67
|
+
### Sandbox Reconnection
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
import { vercel } from '@computesdk/vercel';
|
|
71
|
+
|
|
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!");');
|
|
80
|
+
|
|
81
|
+
// Both executions run in the same Vercel sandbox environment
|
|
82
|
+
```
|
|
83
|
+
|
|
52
84
|
### With ComputeSDK
|
|
53
85
|
|
|
54
86
|
```typescript
|
|
@@ -79,10 +111,13 @@ console.log(result.stdout);
|
|
|
79
111
|
### Options
|
|
80
112
|
|
|
81
113
|
```typescript
|
|
82
|
-
interface
|
|
114
|
+
interface VercelConfig {
|
|
83
115
|
runtime?: 'node' | 'python'; // Default: 'node'
|
|
84
116
|
timeout?: number; // Default: 300000 (5 minutes)
|
|
85
|
-
|
|
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)
|
|
86
121
|
}
|
|
87
122
|
```
|
|
88
123
|
|
|
@@ -179,6 +214,65 @@ Terminates the sandbox.
|
|
|
179
214
|
|
|
180
215
|
**Returns:** `Promise<void>`
|
|
181
216
|
|
|
217
|
+
### Filesystem Operations
|
|
218
|
+
|
|
219
|
+
The Vercel provider supports comprehensive filesystem operations through the `filesystem` property:
|
|
220
|
+
|
|
221
|
+
#### `sandbox.filesystem.readFile(path)`
|
|
222
|
+
|
|
223
|
+
Reads the contents of a file.
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
const content = await sandbox.filesystem.readFile('/vercel/sandbox/data.txt');
|
|
227
|
+
console.log(content);
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
#### `sandbox.filesystem.writeFile(path, content)`
|
|
231
|
+
|
|
232
|
+
Writes content to a file, creating directories as needed.
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
await sandbox.filesystem.writeFile('/vercel/sandbox/output.txt', 'Hello World!');
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
#### `sandbox.filesystem.mkdir(path)`
|
|
239
|
+
|
|
240
|
+
Creates a directory and any necessary parent directories.
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
await sandbox.filesystem.mkdir('/vercel/sandbox/project/data');
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
#### `sandbox.filesystem.readdir(path)`
|
|
247
|
+
|
|
248
|
+
Lists the contents of a directory.
|
|
249
|
+
|
|
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
|
+
```
|
|
256
|
+
|
|
257
|
+
#### `sandbox.filesystem.exists(path)`
|
|
258
|
+
|
|
259
|
+
Checks if a file or directory exists.
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
const exists = await sandbox.filesystem.exists('/vercel/sandbox/config.json');
|
|
263
|
+
if (exists) {
|
|
264
|
+
console.log('Configuration file found!');
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
#### `sandbox.filesystem.remove(path)`
|
|
269
|
+
|
|
270
|
+
Removes a file or directory.
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
await sandbox.filesystem.remove('/vercel/sandbox/temp.txt');
|
|
274
|
+
```
|
|
275
|
+
|
|
182
276
|
## Examples
|
|
183
277
|
|
|
184
278
|
### Node.js Web Server Simulation
|
|
@@ -256,6 +350,137 @@ for product, revenue in sorted(product_sales.items(), key=lambda x: x[1], revers
|
|
|
256
350
|
console.log(result.stdout);
|
|
257
351
|
```
|
|
258
352
|
|
|
353
|
+
### Filesystem Operations Example
|
|
354
|
+
|
|
355
|
+
```typescript
|
|
356
|
+
import { vercel } from '@computesdk/vercel';
|
|
357
|
+
|
|
358
|
+
const sandbox = vercel({ runtime: 'python' });
|
|
359
|
+
|
|
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 = `
|
|
398
|
+
import json
|
|
399
|
+
import csv
|
|
400
|
+
import os
|
|
401
|
+
from collections import defaultdict
|
|
402
|
+
|
|
403
|
+
# Read configuration
|
|
404
|
+
with open('/vercel/sandbox/project/config.json', 'r') as f:
|
|
405
|
+
config = json.load(f)
|
|
406
|
+
|
|
407
|
+
print(f"Running {config['project_name']} v{config['version']}")
|
|
408
|
+
|
|
409
|
+
# Read employee data
|
|
410
|
+
with open('/vercel/sandbox/project/data/employees.json', 'r') as f:
|
|
411
|
+
employees = json.load(f)
|
|
412
|
+
|
|
413
|
+
# Process data - calculate department statistics
|
|
414
|
+
dept_stats = defaultdict(list)
|
|
415
|
+
for emp in employees:
|
|
416
|
+
dept_stats[emp['department']].append(emp['salary'])
|
|
417
|
+
|
|
418
|
+
# Calculate averages
|
|
419
|
+
results = []
|
|
420
|
+
for dept, salaries in dept_stats.items():
|
|
421
|
+
avg_salary = sum(salaries) / len(salaries)
|
|
422
|
+
results.append({
|
|
423
|
+
'department': dept,
|
|
424
|
+
'employee_count': len(salaries),
|
|
425
|
+
'average_salary': round(avg_salary, 2),
|
|
426
|
+
'total_salary': sum(salaries)
|
|
427
|
+
})
|
|
428
|
+
|
|
429
|
+
# Sort by average salary
|
|
430
|
+
results.sort(key=lambda x: x['average_salary'], reverse=True)
|
|
431
|
+
|
|
432
|
+
# Write results as JSON
|
|
433
|
+
with open('/vercel/sandbox/project/output/department_stats.json', 'w') as f:
|
|
434
|
+
json.dump(results, f, indent=2)
|
|
435
|
+
|
|
436
|
+
# Write results as CSV
|
|
437
|
+
with open('/vercel/sandbox/project/output/department_stats.csv', 'w', newline='') as f:
|
|
438
|
+
writer = csv.DictWriter(f, fieldnames=['department', 'employee_count', 'average_salary', 'total_salary'])
|
|
439
|
+
writer.writeheader()
|
|
440
|
+
writer.writerows(results)
|
|
441
|
+
|
|
442
|
+
print("Processing complete!")
|
|
443
|
+
print(f"Generated {len(results)} department statistics")
|
|
444
|
+
|
|
445
|
+
# Print summary
|
|
446
|
+
for result in results:
|
|
447
|
+
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');
|
|
459
|
+
|
|
460
|
+
console.log('JSON Results:', jsonResults);
|
|
461
|
+
console.log('CSV Results:', csvResults);
|
|
462
|
+
|
|
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
|
+
});
|
|
469
|
+
|
|
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}`);
|
|
476
|
+
|
|
477
|
+
} catch (error) {
|
|
478
|
+
console.error('Pipeline failed:', error.message);
|
|
479
|
+
} finally {
|
|
480
|
+
await sandbox.doKill();
|
|
481
|
+
}
|
|
482
|
+
```
|
|
483
|
+
|
|
259
484
|
## Error Handling
|
|
260
485
|
|
|
261
486
|
The provider includes comprehensive error handling:
|
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 };
|
package/dist/index.d.ts
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 };
|