@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/dist/index.mjs
CHANGED
|
@@ -1,202 +1,320 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import { Sandbox } from "@vercel/sandbox";
|
|
3
|
-
import
|
|
4
|
-
var
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
this.runtime = config.runtime || "node";
|
|
33
|
-
}
|
|
34
|
-
async ensureSandbox() {
|
|
35
|
-
if (this.sandbox) {
|
|
36
|
-
return this.sandbox;
|
|
37
|
-
}
|
|
38
|
-
try {
|
|
39
|
-
const runtimeImage = this.runtime === "node" ? "node22" : "python3.13";
|
|
40
|
-
this.sandbox = await Sandbox.create({
|
|
41
|
-
runtime: runtimeImage,
|
|
42
|
-
timeout: ms(`${this.timeout}ms`),
|
|
43
|
-
resources: { vcpus: 2 }
|
|
44
|
-
// Default to 2 vCPUs
|
|
45
|
-
});
|
|
46
|
-
return this.sandbox;
|
|
47
|
-
} catch (error) {
|
|
48
|
-
if (error instanceof Error) {
|
|
49
|
-
if (error.message.includes("unauthorized") || error.message.includes("token")) {
|
|
50
|
-
throw new Error(
|
|
51
|
-
`Vercel authentication failed. Please check your VERCEL_TOKEN environment variable. Get your token from https://vercel.com/account/tokens`
|
|
52
|
-
);
|
|
2
|
+
import { Sandbox as VercelSandbox } from "@vercel/sandbox";
|
|
3
|
+
import { createProvider } from "computesdk";
|
|
4
|
+
var vercel = createProvider({
|
|
5
|
+
name: "vercel",
|
|
6
|
+
methods: {
|
|
7
|
+
sandbox: {
|
|
8
|
+
// Collection operations (map to compute.sandbox.*)
|
|
9
|
+
create: async (config, options) => {
|
|
10
|
+
const oidcToken = typeof process !== "undefined" && process.env?.VERCEL_OIDC_TOKEN;
|
|
11
|
+
const token = config.token || typeof process !== "undefined" && process.env?.VERCEL_TOKEN || "";
|
|
12
|
+
const teamId = config.teamId || typeof process !== "undefined" && process.env?.VERCEL_TEAM_ID || "";
|
|
13
|
+
const projectId = config.projectId || typeof process !== "undefined" && process.env?.VERCEL_PROJECT_ID || "";
|
|
14
|
+
if (!oidcToken && (!token || !teamId || !projectId)) {
|
|
15
|
+
if (!oidcToken && !token) {
|
|
16
|
+
throw new Error(
|
|
17
|
+
`Missing Vercel authentication. Either:
|
|
18
|
+
1. Use OIDC token: Run 'vercel env pull' to get VERCEL_OIDC_TOKEN, or
|
|
19
|
+
2. Use traditional method: Provide 'token' in config or set VERCEL_TOKEN environment variable. Get your token from https://vercel.com/account/tokens`
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
if (!oidcToken && !teamId) {
|
|
23
|
+
throw new Error(
|
|
24
|
+
`Missing Vercel team ID. Provide 'teamId' in config or set VERCEL_TEAM_ID environment variable.`
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
if (!oidcToken && !projectId) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
`Missing Vercel project ID. Provide 'projectId' in config or set VERCEL_PROJECT_ID environment variable.`
|
|
30
|
+
);
|
|
31
|
+
}
|
|
53
32
|
}
|
|
54
|
-
|
|
33
|
+
const runtime = options?.runtime || config.runtime || "node";
|
|
34
|
+
const timeout = config.timeout || 3e5;
|
|
35
|
+
try {
|
|
36
|
+
let sandbox;
|
|
37
|
+
if (options?.sandboxId) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
`Vercel provider does not support reconnecting to existing sandboxes. Vercel sandboxes are ephemeral and must be created fresh each time.`
|
|
40
|
+
);
|
|
41
|
+
} else {
|
|
42
|
+
if (oidcToken) {
|
|
43
|
+
sandbox = await VercelSandbox.create();
|
|
44
|
+
} else {
|
|
45
|
+
sandbox = await VercelSandbox.create({
|
|
46
|
+
token,
|
|
47
|
+
teamId,
|
|
48
|
+
projectId
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
sandbox,
|
|
54
|
+
sandboxId: sandbox.sandboxId
|
|
55
|
+
};
|
|
56
|
+
} catch (error) {
|
|
57
|
+
if (error instanceof Error) {
|
|
58
|
+
if (error.message.includes("unauthorized") || error.message.includes("token")) {
|
|
59
|
+
throw new Error(
|
|
60
|
+
`Vercel authentication failed. Please check your VERCEL_TOKEN environment variable. Get your token from https://vercel.com/account/tokens`
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
if (error.message.includes("team") || error.message.includes("project")) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
`Vercel team/project configuration failed. Please check your VERCEL_TEAM_ID and VERCEL_PROJECT_ID environment variables.`
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
55
69
|
throw new Error(
|
|
56
|
-
`
|
|
70
|
+
`Failed to create Vercel sandbox: ${error instanceof Error ? error.message : String(error)}`
|
|
57
71
|
);
|
|
58
72
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
73
|
+
},
|
|
74
|
+
getById: async (config, sandboxId) => {
|
|
75
|
+
const oidcToken = typeof process !== "undefined" && process.env?.VERCEL_OIDC_TOKEN;
|
|
76
|
+
try {
|
|
77
|
+
let sandbox;
|
|
78
|
+
if (oidcToken) {
|
|
79
|
+
sandbox = await VercelSandbox.get({ sandboxId });
|
|
80
|
+
} else {
|
|
81
|
+
const token = config.token || process.env.VERCEL_TOKEN;
|
|
82
|
+
const teamId = config.teamId || process.env.VERCEL_TEAM_ID;
|
|
83
|
+
const projectId = config.projectId || process.env.VERCEL_PROJECT_ID;
|
|
84
|
+
sandbox = await VercelSandbox.get({
|
|
85
|
+
sandboxId,
|
|
86
|
+
token,
|
|
87
|
+
teamId,
|
|
88
|
+
projectId
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
sandbox,
|
|
93
|
+
sandboxId
|
|
94
|
+
};
|
|
95
|
+
} catch (error) {
|
|
96
|
+
return null;
|
|
63
97
|
}
|
|
64
|
-
|
|
98
|
+
},
|
|
99
|
+
list: async (_config) => {
|
|
100
|
+
throw new Error(
|
|
101
|
+
`Vercel provider does not support listing sandboxes. Vercel sandboxes are ephemeral and designed for single-use execution. Consider using a provider with persistent sandbox management like E2B.`
|
|
102
|
+
);
|
|
103
|
+
},
|
|
104
|
+
destroy: async (config, sandboxId) => {
|
|
105
|
+
const oidcToken = typeof process !== "undefined" && process.env?.VERCEL_OIDC_TOKEN;
|
|
106
|
+
try {
|
|
107
|
+
let sandbox;
|
|
108
|
+
if (oidcToken) {
|
|
109
|
+
sandbox = await VercelSandbox.get({ sandboxId });
|
|
110
|
+
} else {
|
|
111
|
+
const token = config.token || process.env.VERCEL_TOKEN;
|
|
112
|
+
const teamId = config.teamId || process.env.VERCEL_TEAM_ID;
|
|
113
|
+
const projectId = config.projectId || process.env.VERCEL_PROJECT_ID;
|
|
114
|
+
sandbox = await VercelSandbox.get({
|
|
115
|
+
sandboxId,
|
|
116
|
+
token,
|
|
117
|
+
teamId,
|
|
118
|
+
projectId
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
await sandbox.stop();
|
|
122
|
+
} catch (error) {
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
// Instance operations (map to individual Sandbox methods)
|
|
126
|
+
runCode: async (sandbox, code, runtime, config) => {
|
|
127
|
+
const startTime = Date.now();
|
|
128
|
+
try {
|
|
129
|
+
const effectiveRuntime = runtime || config?.runtime || // Strong Python indicators
|
|
130
|
+
(code.includes("print(") || code.includes("import ") || code.includes("def ") || code.includes("sys.") || code.includes("json.") || code.includes("__") || code.includes('f"') || code.includes("f'") ? "python" : "node");
|
|
131
|
+
const encoded = Buffer.from(code).toString("base64");
|
|
132
|
+
let command;
|
|
133
|
+
if (effectiveRuntime === "python") {
|
|
134
|
+
command = await sandbox.runCommand("sh", ["-c", `echo "${encoded}" | base64 -d | python3`]);
|
|
135
|
+
} else {
|
|
136
|
+
command = await sandbox.runCommand("sh", ["-c", `echo "${encoded}" | base64 -d | node`]);
|
|
137
|
+
}
|
|
138
|
+
const finishedCommand = await command.wait();
|
|
139
|
+
let stdout = "";
|
|
140
|
+
let stderr = "";
|
|
141
|
+
for await (const log of finishedCommand.logs()) {
|
|
142
|
+
if (log.stream === "stdout") {
|
|
143
|
+
stdout += log.data;
|
|
144
|
+
} else if (log.stream === "stderr") {
|
|
145
|
+
stderr += log.data;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (finishedCommand.exitCode !== 0 && stderr) {
|
|
149
|
+
if (stderr.includes("SyntaxError") || stderr.includes("invalid syntax") || stderr.includes("Unexpected token") || stderr.includes("Unexpected identifier")) {
|
|
150
|
+
throw new Error(`Syntax error: ${stderr.trim()}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
stdout,
|
|
155
|
+
stderr,
|
|
156
|
+
exitCode: finishedCommand.exitCode,
|
|
157
|
+
executionTime: Date.now() - startTime,
|
|
158
|
+
sandboxId: sandbox.sandboxId,
|
|
159
|
+
provider: "vercel"
|
|
160
|
+
};
|
|
161
|
+
} catch (error) {
|
|
162
|
+
if (error instanceof Error && error.message.includes("Syntax error")) {
|
|
163
|
+
throw error;
|
|
164
|
+
}
|
|
65
165
|
throw new Error(
|
|
66
|
-
`Vercel
|
|
166
|
+
`Vercel execution failed: ${error instanceof Error ? error.message : String(error)}`
|
|
67
167
|
);
|
|
68
168
|
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if (result.stdout) {
|
|
103
|
-
result.stdout.on("data", (data) => {
|
|
104
|
-
stdout += data.toString();
|
|
105
|
-
});
|
|
106
|
-
result.stdout.on("end", resolve);
|
|
107
|
-
} else {
|
|
108
|
-
resolve();
|
|
169
|
+
},
|
|
170
|
+
runCommand: async (sandbox, command, args = []) => {
|
|
171
|
+
const startTime = Date.now();
|
|
172
|
+
try {
|
|
173
|
+
const cmd = await sandbox.runCommand(command, args);
|
|
174
|
+
const finishedCommand = await cmd.wait();
|
|
175
|
+
let stdout = "";
|
|
176
|
+
let stderr = "";
|
|
177
|
+
for await (const log of finishedCommand.logs()) {
|
|
178
|
+
if (log.stream === "stdout") {
|
|
179
|
+
stdout += log.data;
|
|
180
|
+
} else if (log.stream === "stderr") {
|
|
181
|
+
stderr += log.data;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
stdout,
|
|
186
|
+
stderr,
|
|
187
|
+
exitCode: finishedCommand.exitCode,
|
|
188
|
+
executionTime: Date.now() - startTime,
|
|
189
|
+
sandboxId: sandbox.sandboxId,
|
|
190
|
+
provider: "vercel"
|
|
191
|
+
};
|
|
192
|
+
} catch (error) {
|
|
193
|
+
return {
|
|
194
|
+
stdout: "",
|
|
195
|
+
stderr: error instanceof Error ? error.message : String(error),
|
|
196
|
+
exitCode: 127,
|
|
197
|
+
// Standard "command not found" exit code
|
|
198
|
+
executionTime: Date.now() - startTime,
|
|
199
|
+
sandboxId: sandbox.sandboxId,
|
|
200
|
+
provider: "vercel"
|
|
201
|
+
};
|
|
109
202
|
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
203
|
+
},
|
|
204
|
+
getInfo: async (sandbox) => {
|
|
205
|
+
return {
|
|
206
|
+
id: "vercel-unknown",
|
|
207
|
+
provider: "vercel",
|
|
208
|
+
runtime: "node",
|
|
209
|
+
// Vercel default
|
|
210
|
+
status: "running",
|
|
211
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
212
|
+
timeout: 3e5,
|
|
213
|
+
metadata: {
|
|
214
|
+
vercelSandboxId: "vercel-unknown"
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
},
|
|
218
|
+
// Optional filesystem methods - Vercel has shell-based filesystem support
|
|
219
|
+
filesystem: {
|
|
220
|
+
readFile: async (sandbox, path) => {
|
|
221
|
+
const cmd = await sandbox.runCommand("cat", [path]);
|
|
222
|
+
const finishedCommand = await cmd.wait();
|
|
223
|
+
if (finishedCommand.exitCode !== 0) {
|
|
224
|
+
let stderr = "";
|
|
225
|
+
for await (const log of finishedCommand.logs()) {
|
|
226
|
+
if (log.stream === "stderr") {
|
|
227
|
+
stderr += log.data;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
throw new Error(`Failed to read file ${path}: ${stderr}`);
|
|
231
|
+
}
|
|
232
|
+
let content = "";
|
|
233
|
+
for await (const log of finishedCommand.logs()) {
|
|
234
|
+
if (log.stream === "stdout") {
|
|
235
|
+
content += log.data;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return content.replace(/\n$/, "");
|
|
239
|
+
},
|
|
240
|
+
writeFile: async (sandbox, path, content) => {
|
|
241
|
+
const cmd = await sandbox.runCommand("sh", ["-c", `echo ${JSON.stringify(content)} > ${JSON.stringify(path)}`]);
|
|
242
|
+
const finishedCommand = await cmd.wait();
|
|
243
|
+
if (finishedCommand.exitCode !== 0) {
|
|
244
|
+
let stderr = "";
|
|
245
|
+
for await (const log of finishedCommand.logs()) {
|
|
246
|
+
if (log.stream === "stderr") {
|
|
247
|
+
stderr += log.data;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
throw new Error(`Failed to write file ${path}: ${stderr}`);
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
mkdir: async (sandbox, path) => {
|
|
254
|
+
const cmd = await sandbox.runCommand("mkdir", ["-p", path]);
|
|
255
|
+
const finishedCommand = await cmd.wait();
|
|
256
|
+
if (finishedCommand.exitCode !== 0) {
|
|
257
|
+
let stderr = "";
|
|
258
|
+
for await (const log of finishedCommand.logs()) {
|
|
259
|
+
if (log.stream === "stderr") {
|
|
260
|
+
stderr += log.data;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
throw new Error(`Failed to create directory ${path}: ${stderr}`);
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
readdir: async (sandbox, path) => {
|
|
267
|
+
const cmd = await sandbox.runCommand("ls", ["-la", path]);
|
|
268
|
+
const finishedCommand = await cmd.wait();
|
|
269
|
+
let stdout = "";
|
|
270
|
+
let stderr = "";
|
|
271
|
+
for await (const log of finishedCommand.logs()) {
|
|
272
|
+
if (log.stream === "stdout") {
|
|
273
|
+
stdout += log.data;
|
|
274
|
+
} else if (log.stream === "stderr") {
|
|
275
|
+
stderr += log.data;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (finishedCommand.exitCode !== 0) {
|
|
279
|
+
throw new Error(`Failed to list directory ${path}: ${stderr}`);
|
|
280
|
+
}
|
|
281
|
+
const lines = (stdout || "").split("\n").filter((line) => line.trim() && !line.startsWith("total"));
|
|
282
|
+
return lines.map((line) => {
|
|
283
|
+
const parts = line.trim().split(/\s+/);
|
|
284
|
+
const name = parts[parts.length - 1];
|
|
285
|
+
const isDirectory = line.startsWith("d");
|
|
286
|
+
return {
|
|
287
|
+
name,
|
|
288
|
+
path: `${path}/${name}`,
|
|
289
|
+
isDirectory,
|
|
290
|
+
size: parseInt(parts[4]) || 0,
|
|
291
|
+
lastModified: /* @__PURE__ */ new Date()
|
|
292
|
+
};
|
|
115
293
|
});
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
sandboxId: this.sandboxId,
|
|
135
|
-
provider: this.provider
|
|
136
|
-
};
|
|
137
|
-
} catch (error) {
|
|
138
|
-
if (error instanceof Error) {
|
|
139
|
-
if (error.message.includes("timeout")) {
|
|
140
|
-
throw new Error(
|
|
141
|
-
`Vercel execution timeout (${this.timeout}ms). Consider increasing the timeout or optimizing your code.`
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
if (error.message.includes("memory") || error.message.includes("Memory")) {
|
|
145
|
-
throw new Error(
|
|
146
|
-
`Vercel execution failed due to memory limits. Consider optimizing your code or using smaller data sets.`
|
|
147
|
-
);
|
|
294
|
+
},
|
|
295
|
+
exists: async (sandbox, path) => {
|
|
296
|
+
const cmd = await sandbox.runCommand("test", ["-e", path]);
|
|
297
|
+
const finishedCommand = await cmd.wait();
|
|
298
|
+
return finishedCommand.exitCode === 0;
|
|
299
|
+
},
|
|
300
|
+
remove: async (sandbox, path) => {
|
|
301
|
+
const cmd = await sandbox.runCommand("rm", ["-rf", path]);
|
|
302
|
+
const finishedCommand = await cmd.wait();
|
|
303
|
+
if (finishedCommand.exitCode !== 0) {
|
|
304
|
+
let stderr = "";
|
|
305
|
+
for await (const log of finishedCommand.logs()) {
|
|
306
|
+
if (log.stream === "stderr") {
|
|
307
|
+
stderr += log.data;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
throw new Error(`Failed to remove ${path}: ${stderr}`);
|
|
311
|
+
}
|
|
148
312
|
}
|
|
149
313
|
}
|
|
150
|
-
throw new Error(
|
|
151
|
-
`Vercel execution failed: ${error instanceof Error ? error.message : String(error)}`
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
async doKill() {
|
|
156
|
-
if (!this.sandbox) {
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
try {
|
|
160
|
-
await this.sandbox.stop();
|
|
161
|
-
this.sandbox = null;
|
|
162
|
-
} catch (error) {
|
|
163
|
-
throw new Error(
|
|
164
|
-
`Failed to kill Vercel sandbox: ${error instanceof Error ? error.message : String(error)}`
|
|
165
|
-
);
|
|
166
314
|
}
|
|
167
315
|
}
|
|
168
|
-
|
|
169
|
-
await this.ensureSandbox();
|
|
170
|
-
return {
|
|
171
|
-
id: this.sandboxId,
|
|
172
|
-
provider: this.provider,
|
|
173
|
-
runtime: this.runtime,
|
|
174
|
-
status: this.sandbox ? "running" : "stopped",
|
|
175
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
176
|
-
timeout: this.timeout,
|
|
177
|
-
metadata: {
|
|
178
|
-
vercelSandboxId: this.sandboxId,
|
|
179
|
-
teamId: this.teamId,
|
|
180
|
-
projectId: this.projectId,
|
|
181
|
-
vcpus: 2,
|
|
182
|
-
// Default vCPUs
|
|
183
|
-
region: "global"
|
|
184
|
-
// Vercel sandboxes can run globally
|
|
185
|
-
}
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
};
|
|
189
|
-
function vercel(config) {
|
|
190
|
-
const fullConfig = {
|
|
191
|
-
provider: "vercel",
|
|
192
|
-
runtime: "node",
|
|
193
|
-
timeout: 3e5,
|
|
194
|
-
...config
|
|
195
|
-
};
|
|
196
|
-
return new VercelProvider(fullConfig);
|
|
197
|
-
}
|
|
316
|
+
});
|
|
198
317
|
export {
|
|
199
|
-
VercelProvider,
|
|
200
318
|
vercel
|
|
201
319
|
};
|
|
202
320
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { Sandbox } from '@vercel/sandbox';\nimport ms from 'ms';\nimport type {\n ComputeSpecification,\n ExecutionResult,\n Runtime,\n SandboxInfo,\n SandboxConfig\n} from 'computesdk';\n\nexport class VercelProvider implements ComputeSpecification {\n public readonly specificationVersion = 'v1' as const;\n public readonly provider = 'vercel';\n public readonly sandboxId: string;\n\n private sandbox: any = null;\n private readonly token: string;\n private readonly teamId: string;\n private readonly projectId: string;\n private readonly runtime: Runtime;\n private readonly timeout: number;\n\n constructor(config: SandboxConfig) {\n this.sandboxId = `vercel-${Date.now()}-${Math.random().toString(36).substring(7)}`;\n this.timeout = config.timeout || 300000;\n\n // Get authentication from environment\n this.token = process.env.VERCEL_TOKEN || '';\n this.teamId = process.env.VERCEL_TEAM_ID || '';\n this.projectId = process.env.VERCEL_PROJECT_ID || '';\n\n if (!this.token) {\n throw new Error(\n `Missing Vercel token. Set VERCEL_TOKEN environment variable. Get your token from https://vercel.com/account/tokens`\n );\n }\n\n if (!this.teamId) {\n throw new Error(\n `Missing Vercel team ID. Set VERCEL_TEAM_ID environment variable.`\n );\n }\n\n if (!this.projectId) {\n throw new Error(\n `Missing Vercel project ID. Set VERCEL_PROJECT_ID environment variable.`\n );\n }\n\n // Validate runtime - Vercel supports Node.js and Python\n if (config.runtime && !['node', 'python'].includes(config.runtime)) {\n throw new Error('Vercel provider only supports Node.js and Python runtimes');\n }\n\n this.runtime = config.runtime || 'node';\n }\n\n private async ensureSandbox(): Promise<any> {\n if (this.sandbox) {\n return this.sandbox;\n }\n\n try {\n // Create Vercel Sandbox with appropriate runtime\n const runtimeImage = this.runtime === 'node' ? 'node22' : 'python3.13';\n\n this.sandbox = await Sandbox.create({\n runtime: runtimeImage,\n timeout: ms(`${this.timeout}ms`),\n resources: { vcpus: 2 }, // Default to 2 vCPUs\n });\n\n return this.sandbox;\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes('unauthorized') || error.message.includes('token')) {\n throw new Error(\n `Vercel authentication failed. Please check your VERCEL_TOKEN environment variable. Get your token from https://vercel.com/account/tokens`\n );\n }\n if (error.message.includes('team') || error.message.includes('project')) {\n throw new Error(\n `Vercel team/project configuration error. Please check your VERCEL_TEAM_ID and VERCEL_PROJECT_ID environment variables.`\n );\n }\n if (error.message.includes('Memory limit exceeded')) {\n throw new Error(\n `Vercel execution failed due to memory limits. Consider optimizing your code or using smaller data sets.`\n );\n }\n if (error.message.includes('quota') || error.message.includes('limit')) {\n throw new Error(\n `Vercel quota exceeded. Please check your usage in the Vercel dashboard.`\n );\n }\n }\n throw new Error(\n `Failed to initialize Vercel sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n async doExecute(code: string, runtime?: Runtime): Promise<ExecutionResult> {\n // Validate runtime\n if (runtime && !['node', 'python'].includes(runtime)) {\n throw new Error('Vercel provider only supports Node.js and Python runtimes');\n }\n\n const startTime = Date.now();\n const actualRuntime = runtime || this.runtime;\n\n try {\n const sandbox = await this.ensureSandbox();\n\n // Execute code based on runtime\n let command: string;\n let args: string[] = [];\n\n if (actualRuntime === 'node') {\n // For Node.js, use node -e to execute code directly\n command = 'node';\n args = ['-e', code];\n } else if (actualRuntime === 'python') {\n // For Python, use python -c to execute code directly\n command = 'python';\n args = ['-c', code];\n } else {\n throw new Error(`Unsupported runtime: ${actualRuntime}`);\n }\n\n // Execute the command in the sandbox\n const result = await sandbox.runCommand({\n cmd: command,\n args: args,\n });\n\n // Collect stdout and stderr streams\n let stdout = '';\n let stderr = '';\n let exitCode = 0;\n\n // Set up stream listeners\n const stdoutPromise = new Promise<void>((resolve) => {\n if (result.stdout) {\n result.stdout.on('data', (data: Buffer) => {\n stdout += data.toString();\n });\n result.stdout.on('end', resolve);\n } else {\n resolve();\n }\n });\n\n const stderrPromise = new Promise<void>((resolve) => {\n if (result.stderr) {\n result.stderr.on('data', (data: Buffer) => {\n stderr += data.toString();\n });\n result.stderr.on('end', resolve);\n } else {\n resolve();\n }\n });\n\n // Wait for the process to complete\n const exitPromise = new Promise<number>((resolve, reject) => {\n result.on('exit', (code: number) => {\n exitCode = code;\n resolve(code);\n });\n result.on('error', reject);\n });\n\n // Wait for all streams to complete\n await Promise.all([stdoutPromise, stderrPromise, exitPromise]);\n\n return {\n stdout: stdout.trim(),\n stderr: stderr.trim(),\n exitCode: exitCode,\n executionTime: Date.now() - startTime,\n sandboxId: this.sandboxId,\n provider: this.provider\n };\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes('timeout')) {\n throw new Error(\n `Vercel execution timeout (${this.timeout}ms). Consider increasing the timeout or optimizing your code.`\n );\n }\n if (error.message.includes('memory') || error.message.includes('Memory')) {\n throw new Error(\n `Vercel execution failed due to memory limits. Consider optimizing your code or using smaller data sets.`\n );\n }\n }\n throw new Error(\n `Vercel execution failed: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n async doKill(): Promise<void> {\n if (!this.sandbox) {\n return;\n }\n\n try {\n await this.sandbox.stop();\n this.sandbox = null;\n } catch (error) {\n throw new Error(\n `Failed to kill Vercel sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n async doGetInfo(): Promise<SandboxInfo> {\n await this.ensureSandbox();\n\n return {\n id: this.sandboxId,\n provider: this.provider,\n runtime: this.runtime,\n status: this.sandbox ? 'running' : 'stopped',\n createdAt: new Date(),\n timeout: this.timeout,\n metadata: {\n vercelSandboxId: this.sandboxId,\n teamId: this.teamId,\n projectId: this.projectId,\n vcpus: 2, // Default vCPUs\n region: 'global' // Vercel sandboxes can run globally\n }\n };\n }\n}\n\nexport function vercel(config?: Partial<SandboxConfig>): VercelProvider {\n const fullConfig: SandboxConfig = {\n provider: 'vercel',\n runtime: 'node',\n timeout: 300000,\n ...config\n };\n\n return new VercelProvider(fullConfig);\n}\n"],"mappings":"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","names":["code"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Vercel Provider - Factory-based Implementation\n * \n * Demonstrates the new createProvider() factory pattern with ~50 lines\n * instead of the original ~350 lines of boilerplate.\n */\n\nimport { Sandbox as VercelSandbox } from '@vercel/sandbox';\nimport { createProvider } from 'computesdk';\nimport type { Runtime, ExecutionResult, SandboxInfo, CreateSandboxOptions, FileEntry } from 'computesdk';\n\n/**\n * Vercel-specific configuration options\n */\nexport interface VercelConfig {\n /** Vercel API token - if not provided, will fallback to VERCEL_TOKEN environment variable */\n token?: string;\n /** Vercel team ID - if not provided, will fallback to VERCEL_TEAM_ID environment variable */\n teamId?: string;\n /** Vercel project ID - if not provided, will fallback to VERCEL_PROJECT_ID environment variable */\n projectId?: string;\n /** Default runtime environment */\n runtime?: Runtime;\n /** Execution timeout in milliseconds */\n timeout?: number;\n}\n\n\n\n/**\n * Create a Vercel provider instance using the factory pattern\n */\nexport const vercel = createProvider<VercelSandbox, VercelConfig>({\n name: 'vercel',\n methods: {\n sandbox: {\n // Collection operations (map to compute.sandbox.*)\n create: async (config: VercelConfig, options?: CreateSandboxOptions) => {\n // Check for OIDC token first (recommended method)\n const oidcToken = typeof process !== 'undefined' && process.env?.VERCEL_OIDC_TOKEN;\n \n // Fall back to traditional method (token + teamId + projectId)\n const token = config.token || (typeof process !== 'undefined' && process.env?.VERCEL_TOKEN) || '';\n const teamId = config.teamId || (typeof process !== 'undefined' && process.env?.VERCEL_TEAM_ID) || '';\n const projectId = config.projectId || (typeof process !== 'undefined' && process.env?.VERCEL_PROJECT_ID) || '';\n \n // Validate authentication - either OIDC token OR traditional method\n if (!oidcToken && (!token || !teamId || !projectId)) {\n if (!oidcToken && !token) {\n throw new Error(\n `Missing Vercel authentication. Either:\\n` +\n `1. Use OIDC token: Run 'vercel env pull' to get VERCEL_OIDC_TOKEN, or\\n` +\n `2. Use traditional method: Provide 'token' in config or set VERCEL_TOKEN environment variable. Get your token from https://vercel.com/account/tokens`\n );\n }\n if (!oidcToken && !teamId) {\n throw new Error(\n `Missing Vercel team ID. Provide 'teamId' in config or set VERCEL_TEAM_ID environment variable.`\n );\n }\n if (!oidcToken && !projectId) {\n throw new Error(\n `Missing Vercel project ID. Provide 'projectId' in config or set VERCEL_PROJECT_ID environment variable.`\n );\n }\n }\n\n const runtime = options?.runtime || config.runtime || 'node';\n const timeout = config.timeout || 300000;\n\n try {\n let sandbox: VercelSandbox;\n\n if (options?.sandboxId) {\n // Vercel doesn't support reconnecting to existing sandboxes\n // Each sandbox is ephemeral and must be created fresh\n throw new Error(\n `Vercel provider does not support reconnecting to existing sandboxes. Vercel sandboxes are ephemeral and must be created fresh each time.`\n );\n } else {\n // Create new Vercel sandbox using the appropriate authentication method\n if (oidcToken) {\n // Use OIDC token method (simpler, recommended)\n sandbox = await VercelSandbox.create();\n } else {\n // Use traditional method (token + teamId + projectId)\n sandbox = await VercelSandbox.create({\n token,\n teamId,\n projectId,\n });\n }\n }\n\n return {\n sandbox,\n sandboxId: sandbox.sandboxId\n };\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes('unauthorized') || error.message.includes('token')) {\n throw new Error(\n `Vercel authentication failed. Please check your VERCEL_TOKEN environment variable. Get your token from https://vercel.com/account/tokens`\n );\n }\n if (error.message.includes('team') || error.message.includes('project')) {\n throw new Error(\n `Vercel team/project configuration failed. Please check your VERCEL_TEAM_ID and VERCEL_PROJECT_ID environment variables.`\n );\n }\n }\n throw new Error(\n `Failed to create Vercel sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n getById: async (config: VercelConfig, sandboxId: string) => {\n // Check for OIDC token first (recommended method)\n const oidcToken = typeof process !== 'undefined' && process.env?.VERCEL_OIDC_TOKEN;\n \n try {\n let sandbox: VercelSandbox;\n \n if (oidcToken) {\n // Use OIDC token method\n sandbox = await VercelSandbox.get({ sandboxId });\n } else {\n // Use traditional method\n const token = config.token || process.env.VERCEL_TOKEN!;\n const teamId = config.teamId || process.env.VERCEL_TEAM_ID!;\n const projectId = config.projectId || process.env.VERCEL_PROJECT_ID!;\n \n sandbox = await VercelSandbox.get({\n sandboxId,\n token,\n teamId,\n projectId,\n });\n }\n \n return {\n sandbox,\n sandboxId\n };\n } catch (error) {\n // Sandbox doesn't exist or can't be accessed\n return null;\n }\n },\n\n list: async (_config: VercelConfig) => {\n throw new Error(\n `Vercel provider does not support listing sandboxes. Vercel sandboxes are ephemeral and designed for single-use execution. Consider using a provider with persistent sandbox management like E2B.`\n );\n },\n\n destroy: async (config: VercelConfig, sandboxId: string) => {\n // Check for OIDC token first (recommended method)\n const oidcToken = typeof process !== 'undefined' && process.env?.VERCEL_OIDC_TOKEN;\n \n try {\n let sandbox: VercelSandbox;\n \n if (oidcToken) {\n // Use OIDC token method\n sandbox = await VercelSandbox.get({ sandboxId });\n } else {\n // Use traditional method\n const token = config.token || process.env.VERCEL_TOKEN!;\n const teamId = config.teamId || process.env.VERCEL_TEAM_ID!;\n const projectId = config.projectId || process.env.VERCEL_PROJECT_ID!;\n \n sandbox = await VercelSandbox.get({\n sandboxId,\n token,\n teamId,\n projectId,\n });\n }\n \n await sandbox.stop();\n } catch (error) {\n // Sandbox might already be destroyed or doesn't exist\n // This is acceptable for destroy operations\n }\n },\n\n // Instance operations (map to individual Sandbox methods)\n runCode: async (sandbox: VercelSandbox, code: string, runtime?: Runtime, config?: VercelConfig): Promise<ExecutionResult> => {\n const startTime = Date.now();\n \n try {\n // Auto-detect runtime if not specified\n const effectiveRuntime = runtime || config?.runtime || (\n // Strong Python indicators\n code.includes('print(') || \n code.includes('import ') ||\n code.includes('def ') ||\n code.includes('sys.') ||\n code.includes('json.') ||\n code.includes('__') ||\n code.includes('f\"') ||\n code.includes(\"f'\")\n ? 'python'\n // Default to Node.js for all other cases (including ambiguous)\n : 'node'\n );\n \n // Use base64 encoding for both runtimes for reliability and consistency\n const encoded = Buffer.from(code).toString('base64');\n let command;\n \n if (effectiveRuntime === 'python') {\n // Execute Python code with base64 encoding\n command = await sandbox.runCommand('sh', ['-c', `echo \"${encoded}\" | base64 -d | python3`]);\n } else {\n // Execute Node.js code with base64 encoding\n command = await sandbox.runCommand('sh', ['-c', `echo \"${encoded}\" | base64 -d | node`]);\n }\n\n // Wait for command to complete and get exit code\n const finishedCommand = await command.wait();\n\n // Use single logs() iteration to avoid \"multiple consumers\" warning\n let stdout = '';\n let stderr = '';\n \n // Single iteration through logs to collect both stdout and stderr\n for await (const log of finishedCommand.logs()) {\n if (log.stream === 'stdout') {\n stdout += log.data;\n } else if (log.stream === 'stderr') {\n stderr += log.data;\n }\n }\n\n // Check for syntax errors and throw them (similar to E2B behavior)\n if (finishedCommand.exitCode !== 0 && stderr) {\n // Check for common syntax error patterns\n if (stderr.includes('SyntaxError') || \n stderr.includes('invalid syntax') ||\n stderr.includes('Unexpected token') ||\n stderr.includes('Unexpected identifier')) {\n throw new Error(`Syntax error: ${stderr.trim()}`);\n }\n }\n\n return {\n stdout,\n stderr,\n exitCode: finishedCommand.exitCode,\n executionTime: Date.now() - startTime,\n sandboxId: sandbox.sandboxId,\n provider: 'vercel'\n };\n } catch (error) {\n // Re-throw syntax errors\n if (error instanceof Error && error.message.includes('Syntax error')) {\n throw error;\n }\n throw new Error(\n `Vercel execution failed: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n runCommand: async (sandbox: VercelSandbox, command: string, args: string[] = []): Promise<ExecutionResult> => {\n const startTime = Date.now();\n\n try {\n const cmd = await sandbox.runCommand(command, args);\n \n // Wait for command to complete and get exit code\n const finishedCommand = await cmd.wait();\n\n // Use logs() iterator to avoid \"multiple consumers\" warning\n let stdout = '';\n let stderr = '';\n \n for await (const log of finishedCommand.logs()) {\n if (log.stream === 'stdout') {\n stdout += log.data;\n } else if (log.stream === 'stderr') {\n stderr += log.data;\n }\n }\n\n return {\n stdout,\n stderr,\n exitCode: finishedCommand.exitCode,\n executionTime: Date.now() - startTime,\n sandboxId: sandbox.sandboxId,\n provider: 'vercel'\n };\n } catch (error) {\n // For command execution, return error result instead of throwing\n // This handles cases like \"command not found\" where Vercel API returns 400\n return {\n stdout: '',\n stderr: error instanceof Error ? error.message : String(error),\n exitCode: 127, // Standard \"command not found\" exit code\n executionTime: Date.now() - startTime,\n sandboxId: sandbox.sandboxId,\n provider: 'vercel'\n };\n }\n },\n\n getInfo: async (sandbox: VercelSandbox): Promise<SandboxInfo> => {\n return {\n id: 'vercel-unknown',\n provider: 'vercel',\n runtime: 'node', // Vercel default\n status: 'running',\n createdAt: new Date(),\n timeout: 300000,\n metadata: {\n vercelSandboxId: 'vercel-unknown'\n }\n };\n },\n\n // Optional filesystem methods - Vercel has shell-based filesystem support\n filesystem: {\n readFile: async (sandbox: VercelSandbox, path: string): Promise<string> => {\n const cmd = await sandbox.runCommand('cat', [path]);\n const finishedCommand = await cmd.wait();\n \n if (finishedCommand.exitCode !== 0) {\n let stderr = '';\n for await (const log of finishedCommand.logs()) {\n if (log.stream === 'stderr') {\n stderr += log.data;\n }\n }\n throw new Error(`Failed to read file ${path}: ${stderr}`);\n }\n \n let content = '';\n for await (const log of finishedCommand.logs()) {\n if (log.stream === 'stdout') {\n content += log.data;\n }\n }\n // Trim trailing newline that cat command adds\n return content.replace(/\\n$/, '');\n },\n\n writeFile: async (sandbox: VercelSandbox, path: string, content: string): Promise<void> => {\n const cmd = await sandbox.runCommand('sh', ['-c', `echo ${JSON.stringify(content)} > ${JSON.stringify(path)}`]);\n const finishedCommand = await cmd.wait();\n \n if (finishedCommand.exitCode !== 0) {\n let stderr = '';\n for await (const log of finishedCommand.logs()) {\n if (log.stream === 'stderr') {\n stderr += log.data;\n }\n }\n throw new Error(`Failed to write file ${path}: ${stderr}`);\n }\n },\n\n mkdir: async (sandbox: VercelSandbox, path: string): Promise<void> => {\n const cmd = await sandbox.runCommand('mkdir', ['-p', path]);\n const finishedCommand = await cmd.wait();\n \n if (finishedCommand.exitCode !== 0) {\n let stderr = '';\n for await (const log of finishedCommand.logs()) {\n if (log.stream === 'stderr') {\n stderr += log.data;\n }\n }\n throw new Error(`Failed to create directory ${path}: ${stderr}`);\n }\n },\n\n readdir: async (sandbox: VercelSandbox, path: string): Promise<FileEntry[]> => {\n const cmd = await sandbox.runCommand('ls', ['-la', path]);\n const finishedCommand = await cmd.wait();\n \n let stdout = '';\n let stderr = '';\n \n // Single iteration through logs to collect both stdout and stderr\n for await (const log of finishedCommand.logs()) {\n if (log.stream === 'stdout') {\n stdout += log.data;\n } else if (log.stream === 'stderr') {\n stderr += log.data;\n }\n }\n \n if (finishedCommand.exitCode !== 0) {\n throw new Error(`Failed to list directory ${path}: ${stderr}`);\n }\n \n const lines = (stdout || '').split('\\n').filter((line: string) => line.trim() && !line.startsWith('total'));\n \n return lines.map((line: string) => {\n const parts = line.trim().split(/\\s+/);\n const name = parts[parts.length - 1];\n const isDirectory = line.startsWith('d');\n \n return {\n name,\n path: `${path}/${name}`,\n isDirectory,\n size: parseInt(parts[4]) || 0,\n lastModified: new Date()\n };\n });\n },\n\n exists: async (sandbox: VercelSandbox, path: string): Promise<boolean> => {\n const cmd = await sandbox.runCommand('test', ['-e', path]);\n const finishedCommand = await cmd.wait();\n return finishedCommand.exitCode === 0; // Exit code 0 means file exists\n },\n\n remove: async (sandbox: VercelSandbox, path: string): Promise<void> => {\n const cmd = await sandbox.runCommand('rm', ['-rf', path]);\n const finishedCommand = await cmd.wait();\n \n if (finishedCommand.exitCode !== 0) {\n let stderr = '';\n for await (const log of finishedCommand.logs()) {\n if (log.stream === 'stderr') {\n stderr += log.data;\n }\n }\n throw new Error(`Failed to remove ${path}: ${stderr}`);\n }\n }\n }\n }\n }\n});"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@computesdk/vercel",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Vercel Sandbox provider for ComputeSDK",
|
|
5
5
|
"author": "Garrison",
|
|
6
6
|
"license": "MIT",
|
|
@@ -19,10 +19,8 @@
|
|
|
19
19
|
],
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@vercel/sandbox": "^0.0.13",
|
|
22
|
-
"ms": "^2.1.3"
|
|
23
|
-
|
|
24
|
-
"peerDependencies": {
|
|
25
|
-
"computesdk": "1.0.0"
|
|
22
|
+
"ms": "^2.1.3",
|
|
23
|
+
"computesdk": "1.1.0"
|
|
26
24
|
},
|
|
27
25
|
"keywords": [
|
|
28
26
|
"vercel",
|
|
@@ -50,13 +48,14 @@
|
|
|
50
48
|
"rimraf": "^5.0.0",
|
|
51
49
|
"tsup": "^8.0.0",
|
|
52
50
|
"typescript": "^5.0.0",
|
|
53
|
-
"vitest": "^1.0.0"
|
|
51
|
+
"vitest": "^1.0.0",
|
|
52
|
+
"@computesdk/test-utils": "1.1.0"
|
|
54
53
|
},
|
|
55
54
|
"scripts": {
|
|
56
55
|
"build": "tsup",
|
|
57
56
|
"dev": "tsup --watch",
|
|
58
|
-
"test": "vitest",
|
|
57
|
+
"test": "vitest run",
|
|
59
58
|
"typecheck": "tsc --noEmit",
|
|
60
|
-
"lint": "eslint
|
|
59
|
+
"lint": "eslint"
|
|
61
60
|
}
|
|
62
61
|
}
|