@vercel/sandbox 1.9.3 → 1.10.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/dist/api-client/api-client.d.cts +25 -25
- package/dist/api-client/api-client.d.ts +25 -25
- package/dist/api-client/base-client.cjs +2 -1
- package/dist/api-client/base-client.cjs.map +1 -1
- package/dist/api-client/base-client.js +2 -1
- package/dist/api-client/base-client.js.map +1 -1
- package/dist/api-client/validators.d.cts +102 -102
- package/dist/api-client/validators.d.ts +102 -102
- package/dist/auth/file.d.cts +3 -3
- package/dist/auth/file.d.ts +3 -3
- package/dist/auth/index.cjs +0 -1
- package/dist/auth/index.d.cts +2 -2
- package/dist/auth/index.d.ts +2 -2
- package/dist/auth/index.js +2 -2
- package/dist/auth/project.cjs +124 -26
- package/dist/auth/project.cjs.map +1 -1
- package/dist/auth/project.d.cts +9 -13
- package/dist/auth/project.d.ts +9 -13
- package/dist/auth/project.js +125 -26
- package/dist/auth/project.js.map +1 -1
- package/dist/filesystem.cjs +499 -0
- package/dist/filesystem.cjs.map +1 -0
- package/dist/filesystem.d.cts +258 -0
- package/dist/filesystem.d.ts +258 -0
- package/dist/filesystem.js +497 -0
- package/dist/filesystem.js.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/sandbox.cjs +2 -0
- package/dist/sandbox.cjs.map +1 -1
- package/dist/sandbox.d.cts +20 -9
- package/dist/sandbox.d.ts +20 -9
- package/dist/sandbox.js +2 -0
- package/dist/sandbox.js.map +1 -1
- package/dist/snapshot.cjs +39 -5
- package/dist/snapshot.cjs.map +1 -1
- package/dist/snapshot.d.cts +36 -14
- package/dist/snapshot.d.ts +36 -14
- package/dist/snapshot.js +38 -5
- package/dist/snapshot.js.map +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
|
@@ -28,17 +28,17 @@ declare class APIClient extends BaseClient {
|
|
|
28
28
|
signal?: AbortSignal;
|
|
29
29
|
}>): Promise<Parsed<{
|
|
30
30
|
sandbox: {
|
|
31
|
-
status: "aborted" | "
|
|
31
|
+
status: "aborted" | "failed" | "pending" | "running" | "stopping" | "stopped" | "snapshotting";
|
|
32
32
|
id: string;
|
|
33
|
+
region: string;
|
|
34
|
+
createdAt: number;
|
|
35
|
+
updatedAt: number;
|
|
33
36
|
memory: number;
|
|
34
37
|
vcpus: number;
|
|
35
|
-
region: string;
|
|
36
38
|
runtime: string;
|
|
37
39
|
timeout: number;
|
|
38
40
|
requestedAt: number;
|
|
39
|
-
createdAt: number;
|
|
40
41
|
cwd: string;
|
|
41
|
-
updatedAt: number;
|
|
42
42
|
startedAt?: number | undefined;
|
|
43
43
|
requestedStopAt?: number | undefined;
|
|
44
44
|
stoppedAt?: number | undefined;
|
|
@@ -109,17 +109,17 @@ declare class APIClient extends BaseClient {
|
|
|
109
109
|
signal?: AbortSignal;
|
|
110
110
|
}>): Promise<Parsed<{
|
|
111
111
|
sandbox: {
|
|
112
|
-
status: "aborted" | "
|
|
112
|
+
status: "aborted" | "failed" | "pending" | "running" | "stopping" | "stopped" | "snapshotting";
|
|
113
113
|
id: string;
|
|
114
|
+
region: string;
|
|
115
|
+
createdAt: number;
|
|
116
|
+
updatedAt: number;
|
|
114
117
|
memory: number;
|
|
115
118
|
vcpus: number;
|
|
116
|
-
region: string;
|
|
117
119
|
runtime: string;
|
|
118
120
|
timeout: number;
|
|
119
121
|
requestedAt: number;
|
|
120
|
-
createdAt: number;
|
|
121
122
|
cwd: string;
|
|
122
|
-
updatedAt: number;
|
|
123
123
|
startedAt?: number | undefined;
|
|
124
124
|
requestedStopAt?: number | undefined;
|
|
125
125
|
stoppedAt?: number | undefined;
|
|
@@ -235,18 +235,23 @@ declare class APIClient extends BaseClient {
|
|
|
235
235
|
until?: number | Date;
|
|
236
236
|
signal?: AbortSignal;
|
|
237
237
|
}): Promise<Parsed<{
|
|
238
|
+
pagination: {
|
|
239
|
+
count: number;
|
|
240
|
+
next: number | null;
|
|
241
|
+
prev: number | null;
|
|
242
|
+
};
|
|
238
243
|
sandboxes: {
|
|
239
|
-
status: "aborted" | "
|
|
244
|
+
status: "aborted" | "failed" | "pending" | "running" | "stopping" | "stopped" | "snapshotting";
|
|
240
245
|
id: string;
|
|
246
|
+
region: string;
|
|
247
|
+
createdAt: number;
|
|
248
|
+
updatedAt: number;
|
|
241
249
|
memory: number;
|
|
242
250
|
vcpus: number;
|
|
243
|
-
region: string;
|
|
244
251
|
runtime: string;
|
|
245
252
|
timeout: number;
|
|
246
253
|
requestedAt: number;
|
|
247
|
-
createdAt: number;
|
|
248
254
|
cwd: string;
|
|
249
|
-
updatedAt: number;
|
|
250
255
|
startedAt?: number | undefined;
|
|
251
256
|
requestedStopAt?: number | undefined;
|
|
252
257
|
stoppedAt?: number | undefined;
|
|
@@ -284,11 +289,6 @@ declare class APIClient extends BaseClient {
|
|
|
284
289
|
egress: number;
|
|
285
290
|
} | undefined;
|
|
286
291
|
}[];
|
|
287
|
-
pagination: {
|
|
288
|
-
count: number;
|
|
289
|
-
next: number | null;
|
|
290
|
-
prev: number | null;
|
|
291
|
-
};
|
|
292
292
|
}>>;
|
|
293
293
|
listSnapshots(params: {
|
|
294
294
|
/**
|
|
@@ -313,21 +313,21 @@ declare class APIClient extends BaseClient {
|
|
|
313
313
|
until?: number | Date;
|
|
314
314
|
signal?: AbortSignal;
|
|
315
315
|
}): Promise<Parsed<{
|
|
316
|
-
pagination: {
|
|
317
|
-
count: number;
|
|
318
|
-
next: number | null;
|
|
319
|
-
prev: number | null;
|
|
320
|
-
};
|
|
321
316
|
snapshots: {
|
|
322
|
-
status: "
|
|
317
|
+
status: "created" | "deleted" | "failed";
|
|
323
318
|
id: string;
|
|
319
|
+
sourceSandboxId: string;
|
|
324
320
|
region: string;
|
|
321
|
+
sizeBytes: number;
|
|
325
322
|
createdAt: number;
|
|
326
323
|
updatedAt: number;
|
|
327
|
-
sourceSandboxId: string;
|
|
328
|
-
sizeBytes: number;
|
|
329
324
|
expiresAt?: number | undefined;
|
|
330
325
|
}[];
|
|
326
|
+
pagination: {
|
|
327
|
+
count: number;
|
|
328
|
+
next: number | null;
|
|
329
|
+
prev: number | null;
|
|
330
|
+
};
|
|
331
331
|
}>>;
|
|
332
332
|
writeFiles(params: {
|
|
333
333
|
sandboxId: string;
|
|
@@ -28,17 +28,17 @@ declare class APIClient extends BaseClient {
|
|
|
28
28
|
signal?: AbortSignal;
|
|
29
29
|
}>): Promise<Parsed<{
|
|
30
30
|
sandbox: {
|
|
31
|
-
status: "aborted" | "
|
|
31
|
+
status: "aborted" | "failed" | "pending" | "running" | "stopping" | "stopped" | "snapshotting";
|
|
32
32
|
id: string;
|
|
33
|
+
region: string;
|
|
34
|
+
createdAt: number;
|
|
35
|
+
updatedAt: number;
|
|
33
36
|
memory: number;
|
|
34
37
|
vcpus: number;
|
|
35
|
-
region: string;
|
|
36
38
|
runtime: string;
|
|
37
39
|
timeout: number;
|
|
38
40
|
requestedAt: number;
|
|
39
|
-
createdAt: number;
|
|
40
41
|
cwd: string;
|
|
41
|
-
updatedAt: number;
|
|
42
42
|
startedAt?: number | undefined;
|
|
43
43
|
requestedStopAt?: number | undefined;
|
|
44
44
|
stoppedAt?: number | undefined;
|
|
@@ -109,17 +109,17 @@ declare class APIClient extends BaseClient {
|
|
|
109
109
|
signal?: AbortSignal;
|
|
110
110
|
}>): Promise<Parsed<{
|
|
111
111
|
sandbox: {
|
|
112
|
-
status: "aborted" | "
|
|
112
|
+
status: "aborted" | "failed" | "pending" | "running" | "stopping" | "stopped" | "snapshotting";
|
|
113
113
|
id: string;
|
|
114
|
+
region: string;
|
|
115
|
+
createdAt: number;
|
|
116
|
+
updatedAt: number;
|
|
114
117
|
memory: number;
|
|
115
118
|
vcpus: number;
|
|
116
|
-
region: string;
|
|
117
119
|
runtime: string;
|
|
118
120
|
timeout: number;
|
|
119
121
|
requestedAt: number;
|
|
120
|
-
createdAt: number;
|
|
121
122
|
cwd: string;
|
|
122
|
-
updatedAt: number;
|
|
123
123
|
startedAt?: number | undefined;
|
|
124
124
|
requestedStopAt?: number | undefined;
|
|
125
125
|
stoppedAt?: number | undefined;
|
|
@@ -235,18 +235,23 @@ declare class APIClient extends BaseClient {
|
|
|
235
235
|
until?: number | Date;
|
|
236
236
|
signal?: AbortSignal;
|
|
237
237
|
}): Promise<Parsed<{
|
|
238
|
+
pagination: {
|
|
239
|
+
count: number;
|
|
240
|
+
next: number | null;
|
|
241
|
+
prev: number | null;
|
|
242
|
+
};
|
|
238
243
|
sandboxes: {
|
|
239
|
-
status: "aborted" | "
|
|
244
|
+
status: "aborted" | "failed" | "pending" | "running" | "stopping" | "stopped" | "snapshotting";
|
|
240
245
|
id: string;
|
|
246
|
+
region: string;
|
|
247
|
+
createdAt: number;
|
|
248
|
+
updatedAt: number;
|
|
241
249
|
memory: number;
|
|
242
250
|
vcpus: number;
|
|
243
|
-
region: string;
|
|
244
251
|
runtime: string;
|
|
245
252
|
timeout: number;
|
|
246
253
|
requestedAt: number;
|
|
247
|
-
createdAt: number;
|
|
248
254
|
cwd: string;
|
|
249
|
-
updatedAt: number;
|
|
250
255
|
startedAt?: number | undefined;
|
|
251
256
|
requestedStopAt?: number | undefined;
|
|
252
257
|
stoppedAt?: number | undefined;
|
|
@@ -284,11 +289,6 @@ declare class APIClient extends BaseClient {
|
|
|
284
289
|
egress: number;
|
|
285
290
|
} | undefined;
|
|
286
291
|
}[];
|
|
287
|
-
pagination: {
|
|
288
|
-
count: number;
|
|
289
|
-
next: number | null;
|
|
290
|
-
prev: number | null;
|
|
291
|
-
};
|
|
292
292
|
}>>;
|
|
293
293
|
listSnapshots(params: {
|
|
294
294
|
/**
|
|
@@ -313,21 +313,21 @@ declare class APIClient extends BaseClient {
|
|
|
313
313
|
until?: number | Date;
|
|
314
314
|
signal?: AbortSignal;
|
|
315
315
|
}): Promise<Parsed<{
|
|
316
|
-
pagination: {
|
|
317
|
-
count: number;
|
|
318
|
-
next: number | null;
|
|
319
|
-
prev: number | null;
|
|
320
|
-
};
|
|
321
316
|
snapshots: {
|
|
322
|
-
status: "
|
|
317
|
+
status: "created" | "deleted" | "failed";
|
|
323
318
|
id: string;
|
|
319
|
+
sourceSandboxId: string;
|
|
324
320
|
region: string;
|
|
321
|
+
sizeBytes: number;
|
|
325
322
|
createdAt: number;
|
|
326
323
|
updatedAt: number;
|
|
327
|
-
sourceSandboxId: string;
|
|
328
|
-
sizeBytes: number;
|
|
329
324
|
expiresAt?: number | undefined;
|
|
330
325
|
}[];
|
|
326
|
+
pagination: {
|
|
327
|
+
count: number;
|
|
328
|
+
next: number | null;
|
|
329
|
+
prev: number | null;
|
|
330
|
+
};
|
|
331
331
|
}>>;
|
|
332
332
|
writeFiles(params: {
|
|
333
333
|
sandboxId: string;
|
|
@@ -5,6 +5,7 @@ const require_with_retry = require('./with-retry.cjs');
|
|
|
5
5
|
let undici = require("undici");
|
|
6
6
|
|
|
7
7
|
//#region src/api-client/base-client.ts
|
|
8
|
+
const DEFAULT_AGENT = new undici.Agent({ bodyTimeout: 0 });
|
|
8
9
|
/**
|
|
9
10
|
* A base API client that provides a convenience wrapper for fetching where
|
|
10
11
|
* we can pass query parameters as an object, support retries, debugging
|
|
@@ -16,7 +17,7 @@ var BaseClient = class {
|
|
|
16
17
|
this.baseUrl = params.baseUrl;
|
|
17
18
|
this.debug = params.debug ?? process.env.DEBUG_FETCH === "true";
|
|
18
19
|
this.token = params.token;
|
|
19
|
-
this.agent =
|
|
20
|
+
this.agent = DEFAULT_AGENT;
|
|
20
21
|
}
|
|
21
22
|
async request(path, opts) {
|
|
22
23
|
const url = new URL(`${this.baseUrl}${path}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-client.cjs","names":["
|
|
1
|
+
{"version":3,"file":"base-client.cjs","names":["Agent","withRetry","value","APIError","json: Data | ErrorData"],"sources":["../../src/api-client/base-client.ts"],"sourcesContent":["import type { Options as RetryOptions } from \"async-retry\";\nimport { APIError } from \"./api-error.js\";\nimport { ZodType } from \"zod\";\nimport { array } from \"../utils/array.js\";\nimport { withRetry, type RequestOptions } from \"./with-retry.js\";\nimport { Agent } from \"undici\";\n\nexport interface RequestParams extends RequestInit {\n headers?: Record<string, string>;\n method?: string;\n onRetry?(error: any, options: RequestOptions): void;\n query?: Record<string, number | string | null | undefined | string[]>;\n retry?: Partial<RetryOptions>;\n}\n\nconst DEFAULT_AGENT = new Agent({\n bodyTimeout: 0, // disable body timeout to allow long logs streaming\n});\n\n/**\n * A base API client that provides a convenience wrapper for fetching where\n * we can pass query parameters as an object, support retries, debugging\n * and automatic authorization.\n */\nexport class BaseClient {\n protected token?: string;\n private fetch: ReturnType<typeof withRetry<RequestInit>>;\n private debug: boolean;\n private baseUrl: string;\n private agent: Agent;\n\n constructor(params: {\n debug?: boolean;\n baseUrl: string;\n token?: string;\n fetch?: typeof globalThis.fetch;\n }) {\n this.fetch = withRetry(params.fetch ?? globalThis.fetch);\n this.baseUrl = params.baseUrl;\n this.debug = params.debug ?? process.env.DEBUG_FETCH === \"true\";\n this.token = params.token;\n this.agent = DEFAULT_AGENT;\n }\n\n protected async request(path: string, opts?: RequestParams) {\n const url = new URL(`${this.baseUrl}${path}`);\n if (opts?.query) {\n for (const [key, value] of Object.entries(opts.query)) {\n array(value).forEach((value) => {\n url.searchParams.append(key, value.toString());\n });\n }\n }\n\n const start = Date.now();\n const response = await this.fetch(url.toString(), {\n ...opts,\n body: opts?.body,\n method: opts?.method || \"GET\",\n headers: this.token\n ? { Authorization: `Bearer ${this.token}`, ...opts?.headers }\n : opts?.headers,\n // @ts-expect-error Node.js' and undici's Agent have different types\n dispatcher: this.agent,\n signal: opts?.signal,\n });\n\n if (this.debug) {\n const duration = Date.now() - start;\n console.log(`[API] ${url} (${response.status}) ${duration}ms`);\n if (response.status === 429) {\n const retry = parseInt(response.headers.get(\"Retry-After\") ?? \"\", 10);\n const hours = Math.floor(retry / 60 / 60);\n const minutes = Math.floor(retry / 60) % 60;\n const seconds = retry % 60;\n console.warn(\n `[API] ${url} Rate Limited, Retry After ${hours}h ${minutes}m ${seconds}s`,\n );\n }\n }\n\n return response;\n }\n}\n\nexport interface Parsed<Data> {\n response: Response;\n text: string;\n json: Data;\n}\n\n/**\n * Extract sandboxId from a sandbox API URL.\n * URLs follow the pattern: /v1/sandboxes/{sandboxId}/...\n */\nfunction extractSandboxId(url: string): string | undefined {\n const match = url.match(/\\/v1\\/sandboxes\\/([^/?]+)/);\n return match?.[1];\n}\n\n/**\n * Allows to read the response text and parse it as JSON casting to the given\n * type. If the response is not ok or cannot be parsed it will return error.\n *\n * @param response Response to parse.\n * @returns Parsed response or error.\n */\nexport async function parse<Data, ErrorData>(\n validator: ZodType<Data>,\n response: Response,\n): Promise<Parsed<Data> | APIError<ErrorData>> {\n const sandboxId = extractSandboxId(response.url);\n\n const text = await response.text().catch((err) => {\n return new APIError<ErrorData>(response, {\n message: `Can't read response text: ${String(err)}`,\n sandboxId,\n });\n });\n\n if (typeof text !== \"string\") {\n return text;\n }\n\n let json: Data | ErrorData;\n\n try {\n json = JSON.parse(text || \"{}\");\n } catch (error) {\n return new APIError<ErrorData>(response, {\n message: `Can't parse JSON: ${String(error)}`,\n text,\n sandboxId,\n });\n }\n\n if (!response.ok) {\n return new APIError<ErrorData>(response, {\n message: `Status code ${response.status} is not ok`,\n json: json as ErrorData,\n text,\n sandboxId,\n });\n }\n\n const validated = validator.safeParse(json);\n if (!validated.success) {\n return new APIError<ErrorData>(response, {\n message: `Response JSON is not valid: ${validated.error}`,\n json: json as ErrorData,\n text,\n sandboxId,\n });\n }\n\n return {\n json: validated.data,\n response,\n text,\n };\n}\n\nexport async function parseOrThrow<Data, ErrorData>(\n validator: ZodType<Data>,\n response: Response,\n): Promise<Parsed<Data>> {\n const result = await parse<Data, ErrorData>(validator, response);\n if (result instanceof APIError) {\n throw result;\n }\n\n return result;\n}\n"],"mappings":";;;;;;;AAeA,MAAM,gBAAgB,IAAIA,aAAM,EAC9B,aAAa,GACd,CAAC;;;;;;AAOF,IAAa,aAAb,MAAwB;CAOtB,YAAY,QAKT;AACD,OAAK,QAAQC,6BAAU,OAAO,SAAS,WAAW,MAAM;AACxD,OAAK,UAAU,OAAO;AACtB,OAAK,QAAQ,OAAO,SAAS,QAAQ,IAAI,gBAAgB;AACzD,OAAK,QAAQ,OAAO;AACpB,OAAK,QAAQ;;CAGf,MAAgB,QAAQ,MAAc,MAAsB;EAC1D,MAAM,MAAM,IAAI,IAAI,GAAG,KAAK,UAAU,OAAO;AAC7C,MAAI,MAAM,MACR,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,MAAM,CACnD,qBAAM,MAAM,CAAC,SAAS,YAAU;AAC9B,OAAI,aAAa,OAAO,KAAKC,QAAM,UAAU,CAAC;IAC9C;EAIN,MAAM,QAAQ,KAAK,KAAK;EACxB,MAAM,WAAW,MAAM,KAAK,MAAM,IAAI,UAAU,EAAE;GAChD,GAAG;GACH,MAAM,MAAM;GACZ,QAAQ,MAAM,UAAU;GACxB,SAAS,KAAK,QACV;IAAE,eAAe,UAAU,KAAK;IAAS,GAAG,MAAM;IAAS,GAC3D,MAAM;GAEV,YAAY,KAAK;GACjB,QAAQ,MAAM;GACf,CAAC;AAEF,MAAI,KAAK,OAAO;GACd,MAAM,WAAW,KAAK,KAAK,GAAG;AAC9B,WAAQ,IAAI,SAAS,IAAI,IAAI,SAAS,OAAO,IAAI,SAAS,IAAI;AAC9D,OAAI,SAAS,WAAW,KAAK;IAC3B,MAAM,QAAQ,SAAS,SAAS,QAAQ,IAAI,cAAc,IAAI,IAAI,GAAG;IACrE,MAAM,QAAQ,KAAK,MAAM,QAAQ,KAAK,GAAG;IACzC,MAAM,UAAU,KAAK,MAAM,QAAQ,GAAG,GAAG;IACzC,MAAM,UAAU,QAAQ;AACxB,YAAQ,KACN,SAAS,IAAI,6BAA6B,MAAM,IAAI,QAAQ,IAAI,QAAQ,GACzE;;;AAIL,SAAO;;;;;;;AAcX,SAAS,iBAAiB,KAAiC;AAEzD,QADc,IAAI,MAAM,4BAA4B,GACrC;;;;;;;;;AAUjB,eAAsB,MACpB,WACA,UAC6C;CAC7C,MAAM,YAAY,iBAAiB,SAAS,IAAI;CAEhD,MAAM,OAAO,MAAM,SAAS,MAAM,CAAC,OAAO,QAAQ;AAChD,SAAO,IAAIC,2BAAoB,UAAU;GACvC,SAAS,6BAA6B,OAAO,IAAI;GACjD;GACD,CAAC;GACF;AAEF,KAAI,OAAO,SAAS,SAClB,QAAO;CAGT,IAAIC;AAEJ,KAAI;AACF,SAAO,KAAK,MAAM,QAAQ,KAAK;UACxB,OAAO;AACd,SAAO,IAAID,2BAAoB,UAAU;GACvC,SAAS,qBAAqB,OAAO,MAAM;GAC3C;GACA;GACD,CAAC;;AAGJ,KAAI,CAAC,SAAS,GACZ,QAAO,IAAIA,2BAAoB,UAAU;EACvC,SAAS,eAAe,SAAS,OAAO;EAClC;EACN;EACA;EACD,CAAC;CAGJ,MAAM,YAAY,UAAU,UAAU,KAAK;AAC3C,KAAI,CAAC,UAAU,QACb,QAAO,IAAIA,2BAAoB,UAAU;EACvC,SAAS,+BAA+B,UAAU;EAC5C;EACN;EACA;EACD,CAAC;AAGJ,QAAO;EACL,MAAM,UAAU;EAChB;EACA;EACD;;AAGH,eAAsB,aACpB,WACA,UACuB;CACvB,MAAM,SAAS,MAAM,MAAuB,WAAW,SAAS;AAChE,KAAI,kBAAkBA,2BACpB,OAAM;AAGR,QAAO"}
|
|
@@ -4,6 +4,7 @@ import { withRetry } from "./with-retry.js";
|
|
|
4
4
|
import { Agent } from "undici";
|
|
5
5
|
|
|
6
6
|
//#region src/api-client/base-client.ts
|
|
7
|
+
const DEFAULT_AGENT = new Agent({ bodyTimeout: 0 });
|
|
7
8
|
/**
|
|
8
9
|
* A base API client that provides a convenience wrapper for fetching where
|
|
9
10
|
* we can pass query parameters as an object, support retries, debugging
|
|
@@ -15,7 +16,7 @@ var BaseClient = class {
|
|
|
15
16
|
this.baseUrl = params.baseUrl;
|
|
16
17
|
this.debug = params.debug ?? process.env.DEBUG_FETCH === "true";
|
|
17
18
|
this.token = params.token;
|
|
18
|
-
this.agent =
|
|
19
|
+
this.agent = DEFAULT_AGENT;
|
|
19
20
|
}
|
|
20
21
|
async request(path, opts) {
|
|
21
22
|
const url = new URL(`${this.baseUrl}${path}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-client.js","names":["value","json: Data | ErrorData"],"sources":["../../src/api-client/base-client.ts"],"sourcesContent":["import type { Options as RetryOptions } from \"async-retry\";\nimport { APIError } from \"./api-error.js\";\nimport { ZodType } from \"zod\";\nimport { array } from \"../utils/array.js\";\nimport { withRetry, type RequestOptions } from \"./with-retry.js\";\nimport { Agent } from \"undici\";\n\nexport interface RequestParams extends RequestInit {\n headers?: Record<string, string>;\n method?: string;\n onRetry?(error: any, options: RequestOptions): void;\n query?: Record<string, number | string | null | undefined | string[]>;\n retry?: Partial<RetryOptions>;\n}\n\n/**\n * A base API client that provides a convenience wrapper for fetching where\n * we can pass query parameters as an object, support retries, debugging\n * and automatic authorization.\n */\nexport class BaseClient {\n protected token?: string;\n private fetch: ReturnType<typeof withRetry<RequestInit>>;\n private debug: boolean;\n private baseUrl: string;\n private agent: Agent;\n\n constructor(params: {\n debug?: boolean;\n baseUrl: string;\n token?: string;\n fetch?: typeof globalThis.fetch;\n }) {\n this.fetch = withRetry(params.fetch ?? globalThis.fetch);\n this.baseUrl = params.baseUrl;\n this.debug = params.debug ?? process.env.DEBUG_FETCH === \"true\";\n this.token = params.token;\n this.agent =
|
|
1
|
+
{"version":3,"file":"base-client.js","names":["value","json: Data | ErrorData"],"sources":["../../src/api-client/base-client.ts"],"sourcesContent":["import type { Options as RetryOptions } from \"async-retry\";\nimport { APIError } from \"./api-error.js\";\nimport { ZodType } from \"zod\";\nimport { array } from \"../utils/array.js\";\nimport { withRetry, type RequestOptions } from \"./with-retry.js\";\nimport { Agent } from \"undici\";\n\nexport interface RequestParams extends RequestInit {\n headers?: Record<string, string>;\n method?: string;\n onRetry?(error: any, options: RequestOptions): void;\n query?: Record<string, number | string | null | undefined | string[]>;\n retry?: Partial<RetryOptions>;\n}\n\nconst DEFAULT_AGENT = new Agent({\n bodyTimeout: 0, // disable body timeout to allow long logs streaming\n});\n\n/**\n * A base API client that provides a convenience wrapper for fetching where\n * we can pass query parameters as an object, support retries, debugging\n * and automatic authorization.\n */\nexport class BaseClient {\n protected token?: string;\n private fetch: ReturnType<typeof withRetry<RequestInit>>;\n private debug: boolean;\n private baseUrl: string;\n private agent: Agent;\n\n constructor(params: {\n debug?: boolean;\n baseUrl: string;\n token?: string;\n fetch?: typeof globalThis.fetch;\n }) {\n this.fetch = withRetry(params.fetch ?? globalThis.fetch);\n this.baseUrl = params.baseUrl;\n this.debug = params.debug ?? process.env.DEBUG_FETCH === \"true\";\n this.token = params.token;\n this.agent = DEFAULT_AGENT;\n }\n\n protected async request(path: string, opts?: RequestParams) {\n const url = new URL(`${this.baseUrl}${path}`);\n if (opts?.query) {\n for (const [key, value] of Object.entries(opts.query)) {\n array(value).forEach((value) => {\n url.searchParams.append(key, value.toString());\n });\n }\n }\n\n const start = Date.now();\n const response = await this.fetch(url.toString(), {\n ...opts,\n body: opts?.body,\n method: opts?.method || \"GET\",\n headers: this.token\n ? { Authorization: `Bearer ${this.token}`, ...opts?.headers }\n : opts?.headers,\n // @ts-expect-error Node.js' and undici's Agent have different types\n dispatcher: this.agent,\n signal: opts?.signal,\n });\n\n if (this.debug) {\n const duration = Date.now() - start;\n console.log(`[API] ${url} (${response.status}) ${duration}ms`);\n if (response.status === 429) {\n const retry = parseInt(response.headers.get(\"Retry-After\") ?? \"\", 10);\n const hours = Math.floor(retry / 60 / 60);\n const minutes = Math.floor(retry / 60) % 60;\n const seconds = retry % 60;\n console.warn(\n `[API] ${url} Rate Limited, Retry After ${hours}h ${minutes}m ${seconds}s`,\n );\n }\n }\n\n return response;\n }\n}\n\nexport interface Parsed<Data> {\n response: Response;\n text: string;\n json: Data;\n}\n\n/**\n * Extract sandboxId from a sandbox API URL.\n * URLs follow the pattern: /v1/sandboxes/{sandboxId}/...\n */\nfunction extractSandboxId(url: string): string | undefined {\n const match = url.match(/\\/v1\\/sandboxes\\/([^/?]+)/);\n return match?.[1];\n}\n\n/**\n * Allows to read the response text and parse it as JSON casting to the given\n * type. If the response is not ok or cannot be parsed it will return error.\n *\n * @param response Response to parse.\n * @returns Parsed response or error.\n */\nexport async function parse<Data, ErrorData>(\n validator: ZodType<Data>,\n response: Response,\n): Promise<Parsed<Data> | APIError<ErrorData>> {\n const sandboxId = extractSandboxId(response.url);\n\n const text = await response.text().catch((err) => {\n return new APIError<ErrorData>(response, {\n message: `Can't read response text: ${String(err)}`,\n sandboxId,\n });\n });\n\n if (typeof text !== \"string\") {\n return text;\n }\n\n let json: Data | ErrorData;\n\n try {\n json = JSON.parse(text || \"{}\");\n } catch (error) {\n return new APIError<ErrorData>(response, {\n message: `Can't parse JSON: ${String(error)}`,\n text,\n sandboxId,\n });\n }\n\n if (!response.ok) {\n return new APIError<ErrorData>(response, {\n message: `Status code ${response.status} is not ok`,\n json: json as ErrorData,\n text,\n sandboxId,\n });\n }\n\n const validated = validator.safeParse(json);\n if (!validated.success) {\n return new APIError<ErrorData>(response, {\n message: `Response JSON is not valid: ${validated.error}`,\n json: json as ErrorData,\n text,\n sandboxId,\n });\n }\n\n return {\n json: validated.data,\n response,\n text,\n };\n}\n\nexport async function parseOrThrow<Data, ErrorData>(\n validator: ZodType<Data>,\n response: Response,\n): Promise<Parsed<Data>> {\n const result = await parse<Data, ErrorData>(validator, response);\n if (result instanceof APIError) {\n throw result;\n }\n\n return result;\n}\n"],"mappings":";;;;;;AAeA,MAAM,gBAAgB,IAAI,MAAM,EAC9B,aAAa,GACd,CAAC;;;;;;AAOF,IAAa,aAAb,MAAwB;CAOtB,YAAY,QAKT;AACD,OAAK,QAAQ,UAAU,OAAO,SAAS,WAAW,MAAM;AACxD,OAAK,UAAU,OAAO;AACtB,OAAK,QAAQ,OAAO,SAAS,QAAQ,IAAI,gBAAgB;AACzD,OAAK,QAAQ,OAAO;AACpB,OAAK,QAAQ;;CAGf,MAAgB,QAAQ,MAAc,MAAsB;EAC1D,MAAM,MAAM,IAAI,IAAI,GAAG,KAAK,UAAU,OAAO;AAC7C,MAAI,MAAM,MACR,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,MAAM,CACnD,OAAM,MAAM,CAAC,SAAS,YAAU;AAC9B,OAAI,aAAa,OAAO,KAAKA,QAAM,UAAU,CAAC;IAC9C;EAIN,MAAM,QAAQ,KAAK,KAAK;EACxB,MAAM,WAAW,MAAM,KAAK,MAAM,IAAI,UAAU,EAAE;GAChD,GAAG;GACH,MAAM,MAAM;GACZ,QAAQ,MAAM,UAAU;GACxB,SAAS,KAAK,QACV;IAAE,eAAe,UAAU,KAAK;IAAS,GAAG,MAAM;IAAS,GAC3D,MAAM;GAEV,YAAY,KAAK;GACjB,QAAQ,MAAM;GACf,CAAC;AAEF,MAAI,KAAK,OAAO;GACd,MAAM,WAAW,KAAK,KAAK,GAAG;AAC9B,WAAQ,IAAI,SAAS,IAAI,IAAI,SAAS,OAAO,IAAI,SAAS,IAAI;AAC9D,OAAI,SAAS,WAAW,KAAK;IAC3B,MAAM,QAAQ,SAAS,SAAS,QAAQ,IAAI,cAAc,IAAI,IAAI,GAAG;IACrE,MAAM,QAAQ,KAAK,MAAM,QAAQ,KAAK,GAAG;IACzC,MAAM,UAAU,KAAK,MAAM,QAAQ,GAAG,GAAG;IACzC,MAAM,UAAU,QAAQ;AACxB,YAAQ,KACN,SAAS,IAAI,6BAA6B,MAAM,IAAI,QAAQ,IAAI,QAAQ,GACzE;;;AAIL,SAAO;;;;;;;AAcX,SAAS,iBAAiB,KAAiC;AAEzD,QADc,IAAI,MAAM,4BAA4B,GACrC;;;;;;;;;AAUjB,eAAsB,MACpB,WACA,UAC6C;CAC7C,MAAM,YAAY,iBAAiB,SAAS,IAAI;CAEhD,MAAM,OAAO,MAAM,SAAS,MAAM,CAAC,OAAO,QAAQ;AAChD,SAAO,IAAI,SAAoB,UAAU;GACvC,SAAS,6BAA6B,OAAO,IAAI;GACjD;GACD,CAAC;GACF;AAEF,KAAI,OAAO,SAAS,SAClB,QAAO;CAGT,IAAIC;AAEJ,KAAI;AACF,SAAO,KAAK,MAAM,QAAQ,KAAK;UACxB,OAAO;AACd,SAAO,IAAI,SAAoB,UAAU;GACvC,SAAS,qBAAqB,OAAO,MAAM;GAC3C;GACA;GACD,CAAC;;AAGJ,KAAI,CAAC,SAAS,GACZ,QAAO,IAAI,SAAoB,UAAU;EACvC,SAAS,eAAe,SAAS,OAAO;EAClC;EACN;EACA;EACD,CAAC;CAGJ,MAAM,YAAY,UAAU,UAAU,KAAK;AAC3C,KAAI,CAAC,UAAU,QACb,QAAO,IAAI,SAAoB,UAAU;EACvC,SAAS,+BAA+B,UAAU;EAC5C;EACN;EACA;EACD,CAAC;AAGJ,QAAO;EACL,MAAM,UAAU;EAChB;EACA;EACD;;AAGH,eAAsB,aACpB,WACA,UACuB;CACvB,MAAM,SAAS,MAAM,MAAuB,WAAW,SAAS;AAChE,KAAI,kBAAkB,SACpB,OAAM;AAGR,QAAO"}
|