@vercel/sandbox 2.0.0-beta.11 → 2.0.0-beta.12

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.
Files changed (196) hide show
  1. package/README.md +8 -0
  2. package/dist/_virtual/rolldown_runtime.cjs +29 -0
  3. package/dist/api-client/api-client.cjs +456 -0
  4. package/dist/api-client/api-client.cjs.map +1 -0
  5. package/dist/api-client/api-client.d.cts +788 -0
  6. package/dist/api-client/api-client.d.ts +782 -777
  7. package/dist/api-client/api-client.js +445 -471
  8. package/dist/api-client/api-client.js.map +1 -1
  9. package/dist/api-client/api-error.cjs +32 -0
  10. package/dist/api-client/api-error.cjs.map +1 -0
  11. package/dist/api-client/api-error.d.cts +29 -0
  12. package/dist/api-client/api-error.d.ts +21 -18
  13. package/dist/api-client/api-error.js +28 -33
  14. package/dist/api-client/api-error.js.map +1 -1
  15. package/dist/api-client/base-client.cjs +125 -0
  16. package/dist/api-client/base-client.cjs.map +1 -0
  17. package/dist/api-client/base-client.d.cts +38 -0
  18. package/dist/api-client/base-client.d.ts +31 -36
  19. package/dist/api-client/base-client.js +110 -130
  20. package/dist/api-client/base-client.js.map +1 -1
  21. package/dist/api-client/file-writer.cjs +62 -0
  22. package/dist/api-client/file-writer.cjs.map +1 -0
  23. package/dist/api-client/file-writer.d.cts +66 -0
  24. package/dist/api-client/file-writer.d.ts +56 -52
  25. package/dist/api-client/file-writer.js +57 -61
  26. package/dist/api-client/file-writer.js.map +1 -1
  27. package/dist/api-client/index.cjs +2 -0
  28. package/dist/api-client/index.d.ts +2 -2
  29. package/dist/api-client/index.js +4 -21
  30. package/dist/api-client/validators.cjs +181 -0
  31. package/dist/api-client/validators.cjs.map +1 -0
  32. package/dist/api-client/validators.d.cts +1469 -0
  33. package/dist/api-client/validators.d.ts +1282 -3699
  34. package/dist/api-client/validators.js +154 -170
  35. package/dist/api-client/validators.js.map +1 -1
  36. package/dist/api-client/with-retry.cjs +89 -0
  37. package/dist/api-client/with-retry.cjs.map +1 -0
  38. package/dist/api-client/with-retry.d.cts +10 -0
  39. package/dist/api-client/with-retry.d.ts +9 -13
  40. package/dist/api-client/with-retry.js +81 -102
  41. package/dist/api-client/with-retry.js.map +1 -1
  42. package/dist/auth/api.cjs +29 -0
  43. package/dist/auth/api.cjs.map +1 -0
  44. package/dist/auth/api.js +26 -25
  45. package/dist/auth/api.js.map +1 -1
  46. package/dist/auth/error.cjs +13 -0
  47. package/dist/auth/error.cjs.map +1 -0
  48. package/dist/auth/error.js +11 -11
  49. package/dist/auth/error.js.map +1 -1
  50. package/dist/auth/file.cjs +64 -0
  51. package/dist/auth/file.cjs.map +1 -0
  52. package/dist/auth/file.d.cts +26 -0
  53. package/dist/auth/file.d.ts +19 -15
  54. package/dist/auth/file.js +49 -64
  55. package/dist/auth/file.js.map +1 -1
  56. package/dist/auth/index.cjs +12 -0
  57. package/dist/auth/index.d.cts +5 -0
  58. package/dist/auth/index.d.ts +5 -6
  59. package/dist/auth/index.js +6 -27
  60. package/dist/auth/linked-project.cjs +38 -0
  61. package/dist/auth/linked-project.cjs.map +1 -0
  62. package/dist/auth/linked-project.js +30 -64
  63. package/dist/auth/linked-project.js.map +1 -1
  64. package/dist/auth/oauth.cjs +205 -0
  65. package/dist/auth/oauth.cjs.map +1 -0
  66. package/dist/auth/oauth.d.cts +135 -0
  67. package/dist/auth/oauth.d.ts +113 -109
  68. package/dist/auth/oauth.js +185 -252
  69. package/dist/auth/oauth.js.map +1 -1
  70. package/dist/auth/poll-for-token.cjs +82 -0
  71. package/dist/auth/poll-for-token.cjs.map +1 -0
  72. package/dist/auth/poll-for-token.d.cts +28 -0
  73. package/dist/auth/poll-for-token.d.ts +23 -15
  74. package/dist/auth/poll-for-token.js +79 -64
  75. package/dist/auth/poll-for-token.js.map +1 -1
  76. package/dist/auth/project.cjs +80 -0
  77. package/dist/auth/project.cjs.map +1 -0
  78. package/dist/auth/project.d.cts +44 -0
  79. package/dist/auth/project.d.ts +12 -8
  80. package/dist/auth/project.js +70 -72
  81. package/dist/auth/project.js.map +1 -1
  82. package/dist/auth/zod.cjs +22 -0
  83. package/dist/auth/zod.cjs.map +1 -0
  84. package/dist/auth/zod.js +18 -17
  85. package/dist/auth/zod.js.map +1 -1
  86. package/dist/command.cjs +328 -0
  87. package/dist/command.cjs.map +1 -0
  88. package/dist/command.d.cts +289 -0
  89. package/dist/command.d.ts +265 -171
  90. package/dist/command.js +323 -226
  91. package/dist/command.js.map +1 -1
  92. package/dist/constants.d.cts +5 -0
  93. package/dist/constants.d.ts +5 -1
  94. package/dist/index.cjs +13 -0
  95. package/dist/index.d.cts +7 -0
  96. package/dist/index.d.ts +7 -6
  97. package/dist/index.js +7 -17
  98. package/dist/network-policy.d.cts +100 -0
  99. package/dist/network-policy.d.ts +32 -28
  100. package/dist/sandbox.cjs +688 -0
  101. package/dist/sandbox.cjs.map +1 -0
  102. package/dist/sandbox.d.cts +780 -0
  103. package/dist/sandbox.d.ts +767 -711
  104. package/dist/sandbox.js +678 -615
  105. package/dist/sandbox.js.map +1 -1
  106. package/dist/session.cjs +520 -0
  107. package/dist/session.cjs.map +1 -0
  108. package/dist/session.d.cts +406 -0
  109. package/dist/session.d.ts +398 -367
  110. package/dist/session.js +517 -505
  111. package/dist/session.js.map +1 -1
  112. package/dist/snapshot.cjs +116 -0
  113. package/dist/snapshot.cjs.map +1 -0
  114. package/dist/snapshot.d.cts +107 -0
  115. package/dist/snapshot.d.ts +98 -91
  116. package/dist/snapshot.js +114 -115
  117. package/dist/snapshot.js.map +1 -1
  118. package/dist/utils/array.cjs +17 -0
  119. package/dist/utils/array.cjs.map +1 -0
  120. package/dist/utils/array.js +12 -15
  121. package/dist/utils/array.js.map +1 -1
  122. package/dist/utils/consume-readable.cjs +18 -0
  123. package/dist/utils/consume-readable.cjs.map +1 -0
  124. package/dist/utils/consume-readable.js +13 -12
  125. package/dist/utils/consume-readable.js.map +1 -1
  126. package/dist/utils/decode-base64-url.cjs +15 -0
  127. package/dist/utils/decode-base64-url.cjs.map +1 -0
  128. package/dist/utils/decode-base64-url.js +10 -9
  129. package/dist/utils/decode-base64-url.js.map +1 -1
  130. package/dist/utils/dev-credentials.cjs +142 -0
  131. package/dist/utils/dev-credentials.cjs.map +1 -0
  132. package/dist/utils/dev-credentials.js +126 -184
  133. package/dist/utils/dev-credentials.js.map +1 -1
  134. package/dist/utils/get-credentials.cjs +123 -0
  135. package/dist/utils/get-credentials.cjs.map +1 -0
  136. package/dist/utils/get-credentials.d.cts +21 -0
  137. package/dist/utils/get-credentials.d.ts +19 -61
  138. package/dist/utils/get-credentials.js +106 -140
  139. package/dist/utils/get-credentials.js.map +1 -1
  140. package/dist/utils/log.cjs +25 -0
  141. package/dist/utils/log.cjs.map +1 -0
  142. package/dist/utils/log.js +15 -17
  143. package/dist/utils/log.js.map +1 -1
  144. package/dist/utils/network-policy.cjs +65 -0
  145. package/dist/utils/network-policy.cjs.map +1 -0
  146. package/dist/utils/network-policy.js +58 -77
  147. package/dist/utils/network-policy.js.map +1 -1
  148. package/dist/utils/normalizePath.cjs +27 -0
  149. package/dist/utils/normalizePath.cjs.map +1 -0
  150. package/dist/utils/normalizePath.js +21 -28
  151. package/dist/utils/normalizePath.js.map +1 -1
  152. package/dist/utils/resolveSignal.cjs +20 -0
  153. package/dist/utils/resolveSignal.cjs.map +1 -0
  154. package/dist/utils/resolveSignal.d.cts +15 -0
  155. package/dist/utils/resolveSignal.d.ts +12 -10
  156. package/dist/utils/resolveSignal.js +14 -17
  157. package/dist/utils/resolveSignal.js.map +1 -1
  158. package/dist/utils/sandbox-snapshot.cjs +14 -0
  159. package/dist/utils/sandbox-snapshot.cjs.map +1 -0
  160. package/dist/utils/sandbox-snapshot.d.cts +10 -0
  161. package/dist/utils/sandbox-snapshot.d.ts +11 -0
  162. package/dist/utils/sandbox-snapshot.js +14 -0
  163. package/dist/utils/sandbox-snapshot.js.map +1 -0
  164. package/dist/utils/types.cjs +13 -0
  165. package/dist/utils/types.cjs.map +1 -0
  166. package/dist/utils/types.d.cts +11 -0
  167. package/dist/utils/types.d.ts +5 -7
  168. package/dist/utils/types.js +8 -8
  169. package/dist/utils/types.js.map +1 -1
  170. package/dist/version.cjs +7 -0
  171. package/dist/version.cjs.map +1 -0
  172. package/dist/version.js +5 -5
  173. package/dist/version.js.map +1 -1
  174. package/package.json +23 -3
  175. package/dist/api-client/index.js.map +0 -1
  176. package/dist/auth/api.d.ts +0 -6
  177. package/dist/auth/error.d.ts +0 -11
  178. package/dist/auth/index.js.map +0 -1
  179. package/dist/auth/linked-project.d.ts +0 -10
  180. package/dist/auth/zod.d.ts +0 -5
  181. package/dist/constants.js +0 -3
  182. package/dist/constants.js.map +0 -1
  183. package/dist/index.js.map +0 -1
  184. package/dist/network-policy.js +0 -3
  185. package/dist/network-policy.js.map +0 -1
  186. package/dist/utils/array.d.ts +0 -9
  187. package/dist/utils/consume-readable.d.ts +0 -5
  188. package/dist/utils/convert-sandbox.d.ts +0 -6
  189. package/dist/utils/convert-sandbox.js +0 -14
  190. package/dist/utils/convert-sandbox.js.map +0 -1
  191. package/dist/utils/decode-base64-url.d.ts +0 -7
  192. package/dist/utils/dev-credentials.d.ts +0 -37
  193. package/dist/utils/log.d.ts +0 -2
  194. package/dist/utils/network-policy.d.ts +0 -7
  195. package/dist/utils/normalizePath.d.ts +0 -17
  196. package/dist/version.d.ts +0 -1
@@ -1,479 +1,453 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.APIClient = void 0;
7
- const base_client_1 = require("./base-client");
8
- const validators_1 = require("./validators");
9
- const api_error_1 = require("./api-error");
10
- const file_writer_1 = require("./file-writer");
11
- const version_1 = require("../version");
12
- const consume_readable_1 = require("../utils/consume-readable");
13
- const zod_1 = require("zod");
14
- const jsonlines_1 = __importDefault(require("jsonlines"));
15
- const os_1 = __importDefault(require("os"));
16
- const stream_1 = require("stream");
17
- const normalizePath_1 = require("../utils/normalizePath");
18
- const oidc_1 = require("@vercel/oidc");
19
- const network_policy_1 = require("../utils/network-policy");
20
- const types_1 = require("../utils/types");
21
- const promises_1 = require("node:timers/promises");
1
+ import { APIError, StreamError } from "./api-error.js";
2
+ import { BaseClient, parseOrThrow } from "./base-client.js";
3
+ import { CommandFinishedResponse, CommandResponse, CreateSnapshotResponse, EmptyResponse, LogLine, SandboxAndSessionResponse, SandboxesPaginationResponse, SessionAndRoutesResponse, SessionResponse, SessionsResponse, SnapshotResponse, SnapshotsResponse, UpdateSandboxResponse } from "./validators.js";
4
+ import { FileWriter } from "./file-writer.js";
5
+ import { VERSION } from "../version.js";
6
+ import { consumeReadable } from "../utils/consume-readable.js";
7
+ import { normalizePath } from "../utils/normalizePath.js";
8
+ import { toAPINetworkPolicy } from "../utils/network-policy.js";
9
+ import { getPrivateParams } from "../utils/types.js";
10
+ import { setTimeout } from "node:timers/promises";
11
+ import { z } from "zod";
12
+ import { Readable } from "stream";
13
+ import jsonlines from "jsonlines";
14
+ import os from "os";
15
+ import { getVercelOidcToken } from "@vercel/oidc";
16
+
17
+ //#region src/api-client/api-client.ts
22
18
  function decodeUnverifiedToken(token) {
23
- if (token.split(".").length !== 3) {
24
- return null;
25
- }
26
- try {
27
- const payload = JSON.parse(Buffer.from(token.split(".")[1], "base64url").toString("utf8"));
28
- if (payload.owner_id) {
29
- return { owner_id: payload.owner_id, project_id: payload.project_id };
30
- }
31
- return null;
32
- }
33
- catch {
34
- return null;
35
- }
36
- }
37
- class APIClient extends base_client_1.BaseClient {
38
- constructor(params) {
39
- super({
40
- baseUrl: params.baseUrl ?? "https://vercel.com/api",
41
- token: params.token,
42
- debug: false,
43
- fetch: params.fetch,
44
- });
45
- this.teamId = params.teamId;
46
- this.isJwtToken = false;
47
- const claims = decodeUnverifiedToken(params.token);
48
- if (claims) {
49
- this.isJwtToken = true;
50
- this.projectId = claims.project_id;
51
- this.teamId = claims.owner_id;
52
- }
53
- }
54
- async ensureValidToken() {
55
- if (!this.isJwtToken) {
56
- return;
57
- }
58
- try {
59
- // Use getVercelOidcToken to refresh the token with team/project scope
60
- const freshToken = await (0, oidc_1.getVercelOidcToken)({
61
- expirationBufferMs: 5 * 60 * 1000, // 5 minutes
62
- team: this.teamId,
63
- project: this.projectId,
64
- });
65
- // Update token if it changed
66
- if (freshToken !== this.token) {
67
- this.token = freshToken;
68
- const claims = decodeUnverifiedToken(freshToken);
69
- if (claims) {
70
- this.teamId = claims.owner_id;
71
- }
72
- }
73
- }
74
- catch {
75
- // Ignore refresh errors and continue with current token
76
- }
77
- }
78
- async request(path, params) {
79
- await this.ensureValidToken();
80
- return super.request(path, {
81
- ...params,
82
- query: { teamId: this.teamId, ...params?.query },
83
- headers: {
84
- "content-type": "application/json",
85
- "user-agent": `vercel/sandbox/${version_1.VERSION} (Node.js/${process.version}; ${os_1.default.platform()}/${os_1.default.arch()})`,
86
- ...params?.headers,
87
- },
88
- });
89
- }
90
- async getSession(params) {
91
- const privateParams = (0, types_1.getPrivateParams)(params);
92
- let querystring = new URLSearchParams(privateParams).toString();
93
- querystring = querystring ? `?${querystring}` : "";
94
- return (0, base_client_1.parseOrThrow)(validators_1.SessionAndRoutesResponse, await this.request(`/v2/sandboxes/sessions/${params.sessionId}${querystring}`, {
95
- signal: params.signal,
96
- }));
97
- }
98
- async createSandbox(params) {
99
- const privateParams = (0, types_1.getPrivateParams)(params);
100
- return (0, base_client_1.parseOrThrow)(validators_1.SandboxAndSessionResponse, await this.request("/v2/sandboxes", {
101
- method: "POST",
102
- body: JSON.stringify({
103
- projectId: params.projectId,
104
- ports: params.ports,
105
- source: params.source,
106
- timeout: params.timeout,
107
- resources: params.resources,
108
- runtime: params.runtime,
109
- name: params.name,
110
- persistent: params.persistent,
111
- networkPolicy: params.networkPolicy
112
- ? (0, network_policy_1.toAPINetworkPolicy)(params.networkPolicy)
113
- : undefined,
114
- env: params.env,
115
- tags: params.tags,
116
- snapshotExpiration: params.snapshotExpiration,
117
- ...privateParams,
118
- }),
119
- signal: params.signal,
120
- }));
121
- }
122
- async runCommand(params) {
123
- if (params.wait) {
124
- const response = await this.request(`/v2/sandboxes/sessions/${params.sessionId}/cmd`, {
125
- method: "POST",
126
- body: JSON.stringify({
127
- command: params.command,
128
- args: params.args,
129
- cwd: params.cwd,
130
- env: params.env,
131
- sudo: params.sudo,
132
- wait: true,
133
- }),
134
- signal: params.signal,
135
- });
136
- if (!response.ok) {
137
- await (0, base_client_1.parseOrThrow)(zod_1.z.any(), response);
138
- }
139
- if (response.headers.get("content-type") !== "application/x-ndjson") {
140
- throw new api_error_1.APIError(response, {
141
- message: "Expected a stream of command data",
142
- sessionId: params.sessionId,
143
- });
144
- }
145
- if (response.body === null) {
146
- throw new api_error_1.APIError(response, {
147
- message: "No response body",
148
- sessionId: params.sessionId,
149
- });
150
- }
151
- const jsonlinesStream = jsonlines_1.default.parse();
152
- pipe(response.body, jsonlinesStream).catch((err) => {
153
- console.error("Error piping command stream:", err);
154
- });
155
- const iterator = jsonlinesStream[Symbol.asyncIterator]();
156
- const commandChunk = await iterator.next();
157
- const { command } = validators_1.CommandResponse.parse(commandChunk.value);
158
- const finished = (async () => {
159
- const finishedChunk = await iterator.next();
160
- const { command } = validators_1.CommandFinishedResponse.parse(finishedChunk.value);
161
- return command;
162
- })();
163
- return { command, finished };
164
- }
165
- return (0, base_client_1.parseOrThrow)(validators_1.CommandResponse, await this.request(`/v2/sandboxes/sessions/${params.sessionId}/cmd`, {
166
- method: "POST",
167
- body: JSON.stringify({
168
- command: params.command,
169
- args: params.args,
170
- cwd: params.cwd,
171
- env: params.env,
172
- sudo: params.sudo,
173
- }),
174
- signal: params.signal,
175
- }));
176
- }
177
- async getCommand(params) {
178
- return params.wait
179
- ? (0, base_client_1.parseOrThrow)(validators_1.CommandFinishedResponse, await this.request(`/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.cmdId}`, { signal: params.signal, query: { wait: "true" } }))
180
- : (0, base_client_1.parseOrThrow)(validators_1.CommandResponse, await this.request(`/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.cmdId}`, { signal: params.signal }));
181
- }
182
- async mkDir(params) {
183
- return (0, base_client_1.parseOrThrow)(validators_1.EmptyResponse, await this.request(`/v2/sandboxes/sessions/${params.sessionId}/fs/mkdir`, {
184
- method: "POST",
185
- body: JSON.stringify({ path: params.path, cwd: params.cwd }),
186
- signal: params.signal,
187
- }));
188
- }
189
- getFileWriter(params) {
190
- const writer = new file_writer_1.FileWriter();
191
- return {
192
- response: (async () => {
193
- return this.request(`/v2/sandboxes/sessions/${params.sessionId}/fs/write`, {
194
- method: "POST",
195
- headers: {
196
- "content-type": "application/gzip",
197
- "x-cwd": params.extractDir,
198
- },
199
- body: await (0, consume_readable_1.consumeReadable)(writer.readable),
200
- signal: params.signal,
201
- });
202
- })(),
203
- writer,
204
- };
205
- }
206
- async listSessions(params) {
207
- return (0, base_client_1.parseOrThrow)(validators_1.SessionsResponse, await this.request(`/v2/sandboxes/sessions`, {
208
- query: {
209
- project: params.projectId,
210
- name: params.name,
211
- limit: params.limit,
212
- cursor: params.cursor,
213
- sortOrder: params.sortOrder,
214
- },
215
- method: "GET",
216
- signal: params.signal,
217
- }));
218
- }
219
- async listSnapshots(params) {
220
- return (0, base_client_1.parseOrThrow)(validators_1.SnapshotsResponse, await this.request(`/v2/sandboxes/snapshots`, {
221
- query: {
222
- project: params.projectId,
223
- name: params.name,
224
- limit: params.limit,
225
- cursor: params.cursor,
226
- sortOrder: params.sortOrder,
227
- },
228
- method: "GET",
229
- signal: params.signal,
230
- }));
231
- }
232
- async writeFiles(params) {
233
- const { writer, response } = this.getFileWriter({
234
- sessionId: params.sessionId,
235
- extractDir: params.extractDir,
236
- signal: params.signal,
237
- });
238
- for (const file of params.files) {
239
- await writer.addFile({
240
- name: (0, normalizePath_1.normalizePath)({
241
- filePath: file.path,
242
- extractDir: params.extractDir,
243
- cwd: params.cwd,
244
- }),
245
- content: file.content,
246
- mode: file.mode,
247
- });
248
- }
249
- writer.end();
250
- await (0, base_client_1.parseOrThrow)(validators_1.EmptyResponse, await response);
251
- }
252
- async readFile(params) {
253
- const response = await this.request(`/v2/sandboxes/sessions/${params.sessionId}/fs/read`, {
254
- method: "POST",
255
- body: JSON.stringify({ path: params.path, cwd: params.cwd }),
256
- signal: params.signal,
257
- });
258
- if (response.status === 404) {
259
- return null;
260
- }
261
- if (!response.ok) {
262
- await (0, base_client_1.parseOrThrow)(zod_1.z.any(), response);
263
- }
264
- if (response.body === null) {
265
- return null;
266
- }
267
- return stream_1.Readable.fromWeb(response.body);
268
- }
269
- async killCommand(params) {
270
- return (0, base_client_1.parseOrThrow)(validators_1.CommandResponse, await this.request(`/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.commandId}/kill`, {
271
- method: "POST",
272
- body: JSON.stringify({ signal: params.signal }),
273
- signal: params.abortSignal,
274
- }));
275
- }
276
- getLogs(params) {
277
- const self = this;
278
- const disposer = new AbortController();
279
- const signal = !params.signal
280
- ? disposer.signal
281
- : mergeSignals(params.signal, disposer.signal);
282
- const generator = (async function* () {
283
- const url = `/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.cmdId}/logs`;
284
- const response = await self.request(url, {
285
- method: "GET",
286
- signal,
287
- });
288
- if (!response.ok) {
289
- await (0, base_client_1.parseOrThrow)(zod_1.z.any(), response);
290
- }
291
- if (response.headers.get("content-type") !== "application/x-ndjson") {
292
- throw new api_error_1.APIError(response, {
293
- message: "Expected a stream of logs",
294
- sessionId: params.sessionId,
295
- });
296
- }
297
- if (response.body === null) {
298
- throw new api_error_1.APIError(response, {
299
- message: "No response body",
300
- sessionId: params.sessionId,
301
- });
302
- }
303
- const jsonlinesStream = jsonlines_1.default.parse();
304
- pipe(response.body, jsonlinesStream).catch((err) => {
305
- console.error("Error piping logs:", err);
306
- });
307
- for await (const chunk of jsonlinesStream) {
308
- const parsed = validators_1.LogLine.parse(chunk);
309
- if (parsed.stream === "error") {
310
- throw new api_error_1.StreamError(parsed.data.code, parsed.data.message, params.sessionId);
311
- }
312
- yield parsed;
313
- }
314
- })();
315
- return Object.assign(generator, {
316
- [Symbol.dispose]() {
317
- disposer.abort("Disposed");
318
- },
319
- close: () => disposer.abort("Disposed"),
320
- });
321
- }
322
- async stopSession(params) {
323
- const url = `/v2/sandboxes/sessions/${params.sessionId}/stop`;
324
- const response = await (0, base_client_1.parseOrThrow)(validators_1.SessionResponse, await this.request(url, { method: "POST", signal: params.signal }));
325
- if (params.blocking) {
326
- let session = response.json.session;
327
- while (session.status !== "stopped" && session.status !== "failed" && session.status !== "aborted") {
328
- await (0, promises_1.setTimeout)(500, undefined, { signal: params.signal });
329
- const poll = await this.getSession({
330
- sessionId: params.sessionId,
331
- signal: params.signal,
332
- });
333
- session = poll.json.session;
334
- response.json.session = session;
335
- }
336
- }
337
- return response;
338
- }
339
- async updateNetworkPolicy(params) {
340
- const url = `/v2/sandboxes/sessions/${params.sessionId}/network-policy`;
341
- return (0, base_client_1.parseOrThrow)(validators_1.SessionResponse, await this.request(url, {
342
- method: "POST",
343
- body: JSON.stringify((0, network_policy_1.toAPINetworkPolicy)(params.networkPolicy)),
344
- signal: params.signal,
345
- }));
346
- }
347
- async extendTimeout(params) {
348
- const url = `/v2/sandboxes/sessions/${params.sessionId}/extend-timeout`;
349
- return (0, base_client_1.parseOrThrow)(validators_1.SessionResponse, await this.request(url, {
350
- method: "POST",
351
- body: JSON.stringify({ duration: params.duration }),
352
- signal: params.signal,
353
- }));
354
- }
355
- async createSnapshot(params) {
356
- const url = `/v2/sandboxes/sessions/${params.sessionId}/snapshot`;
357
- const body = params.expiration === undefined
358
- ? undefined
359
- : JSON.stringify({ expiration: params.expiration });
360
- return (0, base_client_1.parseOrThrow)(validators_1.CreateSnapshotResponse, await this.request(url, {
361
- method: "POST",
362
- body,
363
- signal: params.signal,
364
- }));
365
- }
366
- async deleteSnapshot(params) {
367
- const url = `/v2/sandboxes/snapshots/${params.snapshotId}`;
368
- return (0, base_client_1.parseOrThrow)(validators_1.SnapshotResponse, await this.request(url, { method: "DELETE", signal: params.signal }));
369
- }
370
- async getSnapshot(params) {
371
- const url = `/v2/sandboxes/snapshots/${params.snapshotId}`;
372
- return (0, base_client_1.parseOrThrow)(validators_1.SnapshotResponse, await this.request(url, { signal: params.signal }));
373
- }
374
- async getSandbox(params) {
375
- const privateParams = (0, types_1.getPrivateParams)(params);
376
- const query = {
377
- projectId: params.projectId,
378
- ...privateParams,
379
- };
380
- if (params.resume !== undefined) {
381
- query.resume = String(params.resume);
382
- }
383
- return (0, base_client_1.parseOrThrow)(validators_1.SandboxAndSessionResponse, await this.request(`/v2/sandboxes/${encodeURIComponent(params.name)}`, {
384
- query,
385
- signal: params.signal,
386
- }));
387
- }
388
- async listSandboxes(params) {
389
- return (0, base_client_1.parseOrThrow)(validators_1.SandboxesPaginationResponse, await this.request(`/v2/sandboxes`, {
390
- query: {
391
- project: params.projectId,
392
- limit: params.limit,
393
- sortBy: params.sortBy,
394
- sortOrder: params.sortOrder,
395
- namePrefix: params.namePrefix,
396
- cursor: params.cursor,
397
- tags: toTagsFilter(params.tags),
398
- },
399
- method: "GET",
400
- signal: params.signal,
401
- }));
402
- }
403
- async updateSandbox(params) {
404
- return (0, base_client_1.parseOrThrow)(validators_1.UpdateSandboxResponse, await this.request(`/v2/sandboxes/${encodeURIComponent(params.name)}`, {
405
- method: "PATCH",
406
- query: {
407
- projectId: params.projectId,
408
- },
409
- body: JSON.stringify({
410
- persistent: params.persistent,
411
- resources: params.resources,
412
- runtime: params.runtime,
413
- timeout: params.timeout,
414
- networkPolicy: params.networkPolicy
415
- ? (0, network_policy_1.toAPINetworkPolicy)(params.networkPolicy)
416
- : undefined,
417
- tags: params.tags,
418
- snapshotExpiration: params.snapshotExpiration,
419
- }),
420
- signal: params.signal,
421
- }));
422
- }
423
- async deleteSandbox(params) {
424
- return (0, base_client_1.parseOrThrow)(validators_1.UpdateSandboxResponse, await this.request(`/v2/sandboxes/${encodeURIComponent(params.name)}`, {
425
- method: "DELETE",
426
- query: {
427
- projectId: params.projectId,
428
- },
429
- signal: params.signal,
430
- }));
431
- }
19
+ if (token.split(".").length !== 3) return null;
20
+ try {
21
+ const payload = JSON.parse(Buffer.from(token.split(".")[1], "base64url").toString("utf8"));
22
+ if (payload.owner_id) return {
23
+ owner_id: payload.owner_id,
24
+ project_id: payload.project_id
25
+ };
26
+ return null;
27
+ } catch {
28
+ return null;
29
+ }
432
30
  }
433
- exports.APIClient = APIClient;
434
- async function pipe(readable, output) {
435
- const reader = readable.getReader();
436
- try {
437
- while (true) {
438
- const read = await reader.read();
439
- if (read.value) {
440
- output.write(Buffer.from(read.value));
441
- }
442
- if (read.done) {
443
- break;
444
- }
445
- }
446
- }
447
- catch (err) {
448
- output.emit("error", err);
449
- }
450
- finally {
451
- output.end();
452
- }
31
+ var APIClient = class extends BaseClient {
32
+ constructor(params) {
33
+ super({
34
+ baseUrl: params.baseUrl ?? "https://vercel.com/api",
35
+ token: params.token,
36
+ debug: false,
37
+ fetch: params.fetch
38
+ });
39
+ this.teamId = params.teamId;
40
+ this.isJwtToken = false;
41
+ const claims = decodeUnverifiedToken(params.token);
42
+ if (claims) {
43
+ this.isJwtToken = true;
44
+ this.projectId = claims.project_id;
45
+ this.teamId = claims.owner_id;
46
+ }
47
+ }
48
+ async ensureValidToken() {
49
+ if (!this.isJwtToken) return;
50
+ try {
51
+ const freshToken = await getVercelOidcToken({
52
+ expirationBufferMs: 300 * 1e3,
53
+ team: this.teamId,
54
+ project: this.projectId
55
+ });
56
+ if (freshToken !== this.token) {
57
+ this.token = freshToken;
58
+ const claims = decodeUnverifiedToken(freshToken);
59
+ if (claims) this.teamId = claims.owner_id;
60
+ }
61
+ } catch {}
62
+ }
63
+ async request(path, params) {
64
+ await this.ensureValidToken();
65
+ return super.request(path, {
66
+ ...params,
67
+ query: {
68
+ teamId: this.teamId,
69
+ ...params?.query
70
+ },
71
+ headers: {
72
+ "content-type": "application/json",
73
+ "user-agent": `vercel/sandbox/${VERSION} (Node.js/${process.version}; ${os.platform()}/${os.arch()})`,
74
+ ...params?.headers
75
+ }
76
+ });
77
+ }
78
+ async getSession(params) {
79
+ const privateParams = getPrivateParams(params);
80
+ let querystring = new URLSearchParams(privateParams).toString();
81
+ querystring = querystring ? `?${querystring}` : "";
82
+ return parseOrThrow(SessionAndRoutesResponse, await this.request(`/v2/sandboxes/sessions/${params.sessionId}${querystring}`, { signal: params.signal }));
83
+ }
84
+ async createSandbox(params) {
85
+ const privateParams = getPrivateParams(params);
86
+ return parseOrThrow(SandboxAndSessionResponse, await this.request("/v2/sandboxes", {
87
+ method: "POST",
88
+ body: JSON.stringify({
89
+ projectId: params.projectId,
90
+ ports: params.ports,
91
+ source: params.source,
92
+ timeout: params.timeout,
93
+ resources: params.resources,
94
+ runtime: params.runtime,
95
+ name: params.name,
96
+ persistent: params.persistent,
97
+ networkPolicy: params.networkPolicy ? toAPINetworkPolicy(params.networkPolicy) : void 0,
98
+ env: params.env,
99
+ tags: params.tags,
100
+ snapshotExpiration: params.snapshotExpiration,
101
+ ...privateParams
102
+ }),
103
+ signal: params.signal
104
+ }));
105
+ }
106
+ async runCommand(params) {
107
+ if (params.wait) {
108
+ const response = await this.request(`/v2/sandboxes/sessions/${params.sessionId}/cmd`, {
109
+ method: "POST",
110
+ body: JSON.stringify({
111
+ command: params.command,
112
+ args: params.args,
113
+ cwd: params.cwd,
114
+ env: params.env,
115
+ sudo: params.sudo,
116
+ wait: true
117
+ }),
118
+ signal: params.signal
119
+ });
120
+ if (!response.ok) await parseOrThrow(z.any(), response);
121
+ if (response.headers.get("content-type") !== "application/x-ndjson") throw new APIError(response, {
122
+ message: "Expected a stream of command data",
123
+ sessionId: params.sessionId
124
+ });
125
+ if (response.body === null) throw new APIError(response, {
126
+ message: "No response body",
127
+ sessionId: params.sessionId
128
+ });
129
+ const jsonlinesStream = jsonlines.parse();
130
+ pipe(response.body, jsonlinesStream, { signal: params.signal }).catch((err) => {
131
+ console.error("Error piping command stream:", err);
132
+ });
133
+ const iterator = jsonlinesStream[Symbol.asyncIterator]();
134
+ const commandChunk = await iterator.next();
135
+ if (commandChunk.done) throw new StreamError("stream_ended_early", "Stream ended before command data was received", params.sessionId);
136
+ const { command } = CommandResponse.parse(commandChunk.value);
137
+ return {
138
+ command,
139
+ finished: (async () => {
140
+ const finishedChunk = await iterator.next();
141
+ if (finishedChunk.done) throw new StreamError("stream_ended_early", "Stream ended before command finished", params.sessionId);
142
+ const { command: command$1 } = CommandFinishedResponse.parse(finishedChunk.value);
143
+ return command$1;
144
+ })()
145
+ };
146
+ }
147
+ return parseOrThrow(CommandResponse, await this.request(`/v2/sandboxes/sessions/${params.sessionId}/cmd`, {
148
+ method: "POST",
149
+ body: JSON.stringify({
150
+ command: params.command,
151
+ args: params.args,
152
+ cwd: params.cwd,
153
+ env: params.env,
154
+ sudo: params.sudo
155
+ }),
156
+ signal: params.signal
157
+ }));
158
+ }
159
+ async getCommand(params) {
160
+ return params.wait ? parseOrThrow(CommandFinishedResponse, await this.request(`/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.cmdId}`, {
161
+ signal: params.signal,
162
+ query: { wait: "true" }
163
+ })) : parseOrThrow(CommandResponse, await this.request(`/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.cmdId}`, { signal: params.signal }));
164
+ }
165
+ async mkDir(params) {
166
+ return parseOrThrow(EmptyResponse, await this.request(`/v2/sandboxes/sessions/${params.sessionId}/fs/mkdir`, {
167
+ method: "POST",
168
+ body: JSON.stringify({
169
+ path: params.path,
170
+ cwd: params.cwd
171
+ }),
172
+ signal: params.signal
173
+ }));
174
+ }
175
+ getFileWriter(params) {
176
+ const writer = new FileWriter();
177
+ return {
178
+ response: (async () => {
179
+ return this.request(`/v2/sandboxes/sessions/${params.sessionId}/fs/write`, {
180
+ method: "POST",
181
+ headers: {
182
+ "content-type": "application/gzip",
183
+ "x-cwd": params.extractDir
184
+ },
185
+ body: await consumeReadable(writer.readable),
186
+ signal: params.signal
187
+ });
188
+ })(),
189
+ writer
190
+ };
191
+ }
192
+ async listSessions(params) {
193
+ return parseOrThrow(SessionsResponse, await this.request(`/v2/sandboxes/sessions`, {
194
+ query: {
195
+ project: params.projectId,
196
+ name: params.name,
197
+ limit: params.limit,
198
+ cursor: params.cursor,
199
+ sortOrder: params.sortOrder
200
+ },
201
+ method: "GET",
202
+ signal: params.signal
203
+ }));
204
+ }
205
+ async listSnapshots(params) {
206
+ return parseOrThrow(SnapshotsResponse, await this.request(`/v2/sandboxes/snapshots`, {
207
+ query: {
208
+ project: params.projectId,
209
+ name: params.name,
210
+ limit: params.limit,
211
+ cursor: params.cursor,
212
+ sortOrder: params.sortOrder
213
+ },
214
+ method: "GET",
215
+ signal: params.signal
216
+ }));
217
+ }
218
+ async writeFiles(params) {
219
+ const { writer, response } = this.getFileWriter({
220
+ sessionId: params.sessionId,
221
+ extractDir: params.extractDir,
222
+ signal: params.signal
223
+ });
224
+ for (const file of params.files) await writer.addFile({
225
+ name: normalizePath({
226
+ filePath: file.path,
227
+ extractDir: params.extractDir,
228
+ cwd: params.cwd
229
+ }),
230
+ content: file.content,
231
+ mode: file.mode
232
+ });
233
+ writer.end();
234
+ await parseOrThrow(EmptyResponse, await response);
235
+ }
236
+ async readFile(params) {
237
+ const response = await this.request(`/v2/sandboxes/sessions/${params.sessionId}/fs/read`, {
238
+ method: "POST",
239
+ body: JSON.stringify({
240
+ path: params.path,
241
+ cwd: params.cwd
242
+ }),
243
+ signal: params.signal
244
+ });
245
+ if (response.status === 404) return null;
246
+ if (!response.ok) await parseOrThrow(z.any(), response);
247
+ if (response.body === null) return null;
248
+ return Readable.fromWeb(response.body);
249
+ }
250
+ async killCommand(params) {
251
+ return parseOrThrow(CommandResponse, await this.request(`/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.commandId}/kill`, {
252
+ method: "POST",
253
+ body: JSON.stringify({ signal: params.signal }),
254
+ signal: params.abortSignal
255
+ }));
256
+ }
257
+ getLogs(params) {
258
+ const self = this;
259
+ const disposer = new AbortController();
260
+ const signal = !params.signal ? disposer.signal : mergeSignals(params.signal, disposer.signal);
261
+ const generator = (async function* () {
262
+ const url = `/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.cmdId}/logs`;
263
+ const response = await self.request(url, {
264
+ method: "GET",
265
+ signal
266
+ });
267
+ if (!response.ok) await parseOrThrow(z.any(), response);
268
+ if (response.headers.get("content-type") !== "application/x-ndjson") throw new APIError(response, {
269
+ message: "Expected a stream of logs",
270
+ sessionId: params.sessionId
271
+ });
272
+ if (response.body === null) throw new APIError(response, {
273
+ message: "No response body",
274
+ sessionId: params.sessionId
275
+ });
276
+ const jsonlinesStream = jsonlines.parse();
277
+ pipe(response.body, jsonlinesStream, { signal }).catch((err) => {
278
+ console.error("Error piping logs:", err);
279
+ });
280
+ for await (const chunk of jsonlinesStream) {
281
+ const parsed = LogLine.parse(chunk);
282
+ if (parsed.stream === "error") throw new StreamError(parsed.data.code, parsed.data.message, params.sessionId);
283
+ yield parsed;
284
+ }
285
+ })();
286
+ return Object.assign(generator, {
287
+ [Symbol.dispose]() {
288
+ disposer.abort("Disposed");
289
+ },
290
+ close: () => disposer.abort("Disposed")
291
+ });
292
+ }
293
+ async stopSession(params) {
294
+ const url = `/v2/sandboxes/sessions/${params.sessionId}/stop`;
295
+ const response = await parseOrThrow(SessionResponse, await this.request(url, {
296
+ method: "POST",
297
+ signal: params.signal
298
+ }));
299
+ if (params.blocking) {
300
+ let session = response.json.session;
301
+ while (session.status !== "stopped" && session.status !== "failed" && session.status !== "aborted") {
302
+ await setTimeout(500, void 0, { signal: params.signal });
303
+ session = (await this.getSession({
304
+ sessionId: params.sessionId,
305
+ signal: params.signal
306
+ })).json.session;
307
+ response.json.session = session;
308
+ }
309
+ }
310
+ return response;
311
+ }
312
+ async updateNetworkPolicy(params) {
313
+ const url = `/v2/sandboxes/sessions/${params.sessionId}/network-policy`;
314
+ return parseOrThrow(SessionResponse, await this.request(url, {
315
+ method: "POST",
316
+ body: JSON.stringify(toAPINetworkPolicy(params.networkPolicy)),
317
+ signal: params.signal
318
+ }));
319
+ }
320
+ async extendTimeout(params) {
321
+ const url = `/v2/sandboxes/sessions/${params.sessionId}/extend-timeout`;
322
+ return parseOrThrow(SessionResponse, await this.request(url, {
323
+ method: "POST",
324
+ body: JSON.stringify({ duration: params.duration }),
325
+ signal: params.signal
326
+ }));
327
+ }
328
+ async createSnapshot(params) {
329
+ const url = `/v2/sandboxes/sessions/${params.sessionId}/snapshot`;
330
+ const body = params.expiration === void 0 ? void 0 : JSON.stringify({ expiration: params.expiration });
331
+ return parseOrThrow(CreateSnapshotResponse, await this.request(url, {
332
+ method: "POST",
333
+ body,
334
+ signal: params.signal
335
+ }));
336
+ }
337
+ async deleteSnapshot(params) {
338
+ const url = `/v2/sandboxes/snapshots/${params.snapshotId}`;
339
+ return parseOrThrow(SnapshotResponse, await this.request(url, {
340
+ method: "DELETE",
341
+ signal: params.signal
342
+ }));
343
+ }
344
+ async getSnapshot(params) {
345
+ const url = `/v2/sandboxes/snapshots/${params.snapshotId}`;
346
+ return parseOrThrow(SnapshotResponse, await this.request(url, { signal: params.signal }));
347
+ }
348
+ async getSandbox(params) {
349
+ const privateParams = getPrivateParams(params);
350
+ const query = {
351
+ projectId: params.projectId,
352
+ ...privateParams
353
+ };
354
+ if (params.resume !== void 0) query.resume = String(params.resume);
355
+ return parseOrThrow(SandboxAndSessionResponse, await this.request(`/v2/sandboxes/${encodeURIComponent(params.name)}`, {
356
+ query,
357
+ signal: params.signal
358
+ }));
359
+ }
360
+ async listSandboxes(params) {
361
+ return parseOrThrow(SandboxesPaginationResponse, await this.request(`/v2/sandboxes`, {
362
+ query: {
363
+ project: params.projectId,
364
+ limit: params.limit,
365
+ sortBy: params.sortBy,
366
+ sortOrder: params.sortOrder,
367
+ namePrefix: params.namePrefix,
368
+ cursor: params.cursor,
369
+ tags: toTagsFilter(params.tags)
370
+ },
371
+ method: "GET",
372
+ signal: params.signal
373
+ }));
374
+ }
375
+ async updateSandbox(params) {
376
+ return parseOrThrow(UpdateSandboxResponse, await this.request(`/v2/sandboxes/${encodeURIComponent(params.name)}`, {
377
+ method: "PATCH",
378
+ query: { projectId: params.projectId },
379
+ body: JSON.stringify({
380
+ persistent: params.persistent,
381
+ resources: params.resources,
382
+ runtime: params.runtime,
383
+ timeout: params.timeout,
384
+ networkPolicy: params.networkPolicy ? toAPINetworkPolicy(params.networkPolicy) : void 0,
385
+ tags: params.tags,
386
+ snapshotExpiration: params.snapshotExpiration
387
+ }),
388
+ signal: params.signal
389
+ }));
390
+ }
391
+ async deleteSandbox(params) {
392
+ return parseOrThrow(UpdateSandboxResponse, await this.request(`/v2/sandboxes/${encodeURIComponent(params.name)}`, {
393
+ method: "DELETE",
394
+ query: { projectId: params.projectId },
395
+ signal: params.signal
396
+ }));
397
+ }
398
+ };
399
+ async function pipe(readable, output, options) {
400
+ const reader = readable.getReader();
401
+ let aborted = false;
402
+ const signal = options?.signal;
403
+ const onAbort = () => {
404
+ aborted = true;
405
+ const reason = signal?.reason ?? new DOMException("The operation was aborted.", "AbortError");
406
+ reader.cancel(reason).catch(() => {});
407
+ if ("destroy" in output && typeof output.destroy === "function") {
408
+ output.destroy(reason);
409
+ return;
410
+ }
411
+ output.emit("error", reason);
412
+ output.end();
413
+ };
414
+ if (signal) if (signal.aborted) onAbort();
415
+ else signal.addEventListener("abort", onAbort, { once: true });
416
+ try {
417
+ while (true) {
418
+ const read = await reader.read();
419
+ if (read.value) output.write(Buffer.from(read.value));
420
+ if (read.done) break;
421
+ }
422
+ } catch (err) {
423
+ if (!aborted) output.emit("error", err);
424
+ } finally {
425
+ signal?.removeEventListener("abort", onAbort);
426
+ if (!aborted) output.end();
427
+ }
453
428
  }
454
429
  function mergeSignals(...signals) {
455
- const controller = new AbortController();
456
- const onAbort = () => {
457
- controller.abort();
458
- for (const signal of signals) {
459
- signal.removeEventListener("abort", onAbort);
460
- }
461
- };
462
- for (const signal of signals) {
463
- if (signal.aborted) {
464
- controller.abort();
465
- break;
466
- }
467
- signal.addEventListener("abort", onAbort);
468
- }
469
- return controller.signal;
430
+ const controller = new AbortController();
431
+ const onAbort = () => {
432
+ controller.abort();
433
+ for (const signal of signals) signal.removeEventListener("abort", onAbort);
434
+ };
435
+ for (const signal of signals) {
436
+ if (signal.aborted) {
437
+ controller.abort();
438
+ break;
439
+ }
440
+ signal.addEventListener("abort", onAbort);
441
+ }
442
+ return controller.signal;
470
443
  }
471
444
  function toTagsFilter(tags) {
472
- if (tags === undefined)
473
- return undefined;
474
- const entries = Object.entries(tags);
475
- if (entries.length === 0)
476
- return undefined;
477
- return entries.map(([key, value]) => `${key}:${value}`);
445
+ if (tags === void 0) return void 0;
446
+ const entries = Object.entries(tags);
447
+ if (entries.length === 0) return void 0;
448
+ return entries.map(([key, value]) => `${key}:${value}`);
478
449
  }
450
+
451
+ //#endregion
452
+ export { APIClient };
479
453
  //# sourceMappingURL=api-client.js.map