@vercel/sandbox
Advanced tools
| //#region src/constants.ts | ||
| /** | ||
| * Region a sandbox runs in when none is requested. | ||
| */ | ||
| const DEFAULT_SANDBOX_REGION = "iad1"; | ||
| //#endregion | ||
| exports.DEFAULT_SANDBOX_REGION = DEFAULT_SANDBOX_REGION; | ||
| //# sourceMappingURL=constants.cjs.map |
| {"version":3,"file":"constants.cjs","names":[],"sources":["../src/constants.ts"],"sourcesContent":["export type RUNTIMES = \"node26\" | \"node24\" | \"node22\" | \"python3.13\";\n\nexport type ManagedImage =\n | \"universal\"\n | \"node:22\"\n | \"node:24\"\n | \"node:26\"\n | \"python:3.14\"\n | \"ubuntu\"\n | \"arch\";\n\n/**\n * Regions a sandbox, snapshot, or drive can live in. More regions may\n * become available, so any other region string is accepted too.\n */\nexport type SandboxRegion = \"iad1\" | \"sfo1\" | \"cle1\" | \"cdg1\" | (string & {});\n\n/**\n * Region a sandbox runs in when none is requested.\n */\nexport const DEFAULT_SANDBOX_REGION = \"iad1\";\n"],"mappings":";;;;;AAoBA,MAAa,yBAAyB"} |
| //#region src/constants.ts | ||
| /** | ||
| * Region a sandbox runs in when none is requested. | ||
| */ | ||
| const DEFAULT_SANDBOX_REGION = "iad1"; | ||
| //#endregion | ||
| export { DEFAULT_SANDBOX_REGION }; | ||
| //# sourceMappingURL=constants.js.map |
| {"version":3,"file":"constants.js","names":[],"sources":["../src/constants.ts"],"sourcesContent":["export type RUNTIMES = \"node26\" | \"node24\" | \"node22\" | \"python3.13\";\n\nexport type ManagedImage =\n | \"universal\"\n | \"node:22\"\n | \"node:24\"\n | \"node:26\"\n | \"python:3.14\"\n | \"ubuntu\"\n | \"arch\";\n\n/**\n * Regions a sandbox, snapshot, or drive can live in. More regions may\n * become available, so any other region string is accepted too.\n */\nexport type SandboxRegion = \"iad1\" | \"sfo1\" | \"cle1\" | \"cdg1\" | (string & {});\n\n/**\n * Region a sandbox runs in when none is requested.\n */\nexport const DEFAULT_SANDBOX_REGION = \"iad1\";\n"],"mappings":";;;;AAoBA,MAAa,yBAAyB"} |
@@ -107,2 +107,4 @@ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs'); | ||
| mounts: params.mounts, | ||
| region: params.region, | ||
| failoverRegions: params.failoverRegions, | ||
| ...privateParams | ||
@@ -130,2 +132,4 @@ }), | ||
| keepLastSnapshots: params.keepLastSnapshots, | ||
| region: params.region, | ||
| failoverRegions: params.failoverRegions, | ||
| ...privateParams | ||
@@ -297,2 +301,3 @@ }), | ||
| projectId: params.projectId, | ||
| region: params.region, | ||
| maxSizeBytes: params.maxSizeBytes | ||
@@ -483,3 +488,5 @@ }), | ||
| keepLastSnapshots: params.keepLastSnapshots, | ||
| currentSnapshotId: params.currentSnapshotId | ||
| currentSnapshotId: params.currentSnapshotId, | ||
| region: params.region, | ||
| failoverRegions: params.failoverRegions | ||
| }), | ||
@@ -486,0 +493,0 @@ signal: params.signal |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"api-client.cjs","names":["BaseClient","VERSION","getPrivateParams","parseOrThrow","SessionAndRoutesResponse","SandboxAndSessionResponse","toAPINetworkPolicy","z","APIError","StreamError","CommandResponse","CommandFinishedResponse","command","LogLine","InteractiveSessionResponse","EmptyResponse","FileWriter","consumeReadable","SessionsResponse","SnapshotsResponse","SnapshotTreeResponse","DrivesResponse","DriveResponse","normalizePath","json: unknown","Readable","StopSessionResponse","SessionResponse","CreateSnapshotResponse","SnapshotResponse","query: Record<string, string | undefined>","SandboxesPaginationResponse","UpdateSandboxResponse"],"sources":["../../src/api-client/api-client.ts"],"sourcesContent":["import {\n BaseClient,\n parseOrThrow,\n type Parsed,\n type RequestParams,\n} from \"./base-client.js\";\nimport {\n type CommandFinishedData,\n SessionAndRoutesResponse,\n SessionResponse,\n InteractiveSessionResponse,\n StopSessionResponse,\n SessionsResponse,\n CommandResponse,\n CommandFinishedResponse,\n EmptyResponse,\n LogLine,\n type LogOutputLine,\n SnapshotsResponse,\n SnapshotTreeResponse,\n SnapshotResponse,\n CreateSnapshotResponse,\n SandboxAndSessionResponse,\n SandboxesPaginationResponse,\n UpdateSandboxResponse,\n DrivesResponse,\n DriveResponse,\n type CommandData,\n} from \"./validators.js\";\nimport { APIError, StreamError } from \"./api-error.js\";\nimport { FileWriter } from \"./file-writer.js\";\nimport { VERSION } from \"../version.js\";\nimport { consumeReadable } from \"../utils/consume-readable.js\";\nimport { z } from \"zod\";\nimport jsonlines from \"jsonlines\";\nimport os from \"os\";\nimport { Readable } from \"stream\";\nimport { normalizePath } from \"../utils/normalizePath.js\";\nimport { getVercelOidcToken } from \"@vercel/oidc\";\nimport { NetworkPolicy } from \"../network-policy.js\";\nimport { toAPINetworkPolicy } from \"../utils/network-policy.js\";\nimport { getPrivateParams, WithPrivate } from \"../utils/types.js\";\nimport type { RUNTIMES } from \"../constants.js\";\nimport type { BaseCreateSandboxParams } from \"../sandbox.js\";\n\ninterface Claims {\n owner_id: string;\n project_id?: string;\n}\n\nfunction decodeUnverifiedToken(token: string): Claims | null {\n if (token.split(\".\").length !== 3) {\n return null;\n }\n try {\n const payload = JSON.parse(\n Buffer.from(token.split(\".\")[1], \"base64url\").toString(\"utf8\"),\n );\n if (payload.owner_id) {\n return { owner_id: payload.owner_id, project_id: payload.project_id };\n }\n return null;\n } catch {\n return null;\n }\n}\n\nexport interface WithFetchOptions {\n fetch?: typeof globalThis.fetch;\n}\n\nexport class APIClient extends BaseClient {\n private teamId: string;\n private projectId: string | undefined;\n private isJwtToken: boolean;\n\n constructor(params: {\n baseUrl?: string;\n teamId: string;\n token: string;\n fetch?: typeof globalThis.fetch;\n }) {\n super({\n baseUrl: params.baseUrl ?? \"https://vercel.com/api\",\n token: params.token,\n debug: false,\n fetch: params.fetch,\n });\n\n this.teamId = params.teamId;\n this.isJwtToken = false;\n\n const claims = decodeUnverifiedToken(params.token);\n if (claims) {\n this.isJwtToken = true;\n this.projectId = claims.project_id;\n this.teamId = claims.owner_id;\n }\n }\n\n private async ensureValidToken(): Promise<void> {\n if (!this.isJwtToken) {\n return;\n }\n\n try {\n // Use getVercelOidcToken to refresh the token with team/project scope\n const freshToken = await getVercelOidcToken({\n expirationBufferMs: 5 * 60 * 1000, // 5 minutes\n team: this.teamId,\n project: this.projectId,\n });\n\n // Update token if it changed\n if (freshToken !== this.token) {\n this.token = freshToken;\n\n const claims = decodeUnverifiedToken(freshToken);\n if (claims) {\n this.teamId = claims.owner_id;\n }\n }\n } catch {\n // Ignore refresh errors and continue with current token\n }\n }\n\n protected async request(path: string, params?: RequestParams) {\n await this.ensureValidToken();\n\n return super.request(path, {\n ...params,\n query: { teamId: this.teamId, ...params?.query },\n headers: {\n \"content-type\": \"application/json\",\n \"user-agent\": `vercel/sandbox/${VERSION} (Node.js/${process.version}; ${os.platform()}/${os.arch()})`,\n ...params?.headers,\n },\n });\n }\n\n async getSession(\n params: WithPrivate<{ sessionId: string; signal?: AbortSignal }>,\n ) {\n const privateParams = getPrivateParams(params);\n let querystring = new URLSearchParams(privateParams).toString();\n querystring = querystring ? `?${querystring}` : \"\";\n return parseOrThrow(\n SessionAndRoutesResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}${querystring}`,\n {\n signal: params.signal,\n },\n ),\n );\n }\n\n async createSandbox(\n params: WithPrivate<{\n name?: string;\n ports?: number[];\n projectId: string;\n source?:\n | {\n type: \"git\";\n url: string;\n depth?: number;\n revision?: string;\n username?: string;\n password?: string;\n }\n | { type: \"tarball\"; url: string }\n | { type: \"snapshot\"; snapshotId: string };\n timeout?: number;\n resources?: { vcpus: number };\n persistent?: boolean;\n runtime?: RUNTIMES | (string & {});\n image?: string;\n networkPolicy?: NetworkPolicy;\n env?: Record<string, string>;\n tags?: Record<string, string>;\n snapshotExpiration?: number;\n keepLastSnapshots?: {\n count: number;\n expiration?: number;\n deleteEvicted?: boolean;\n };\n mounts?: BaseCreateSandboxParams[\"mounts\"];\n signal?: AbortSignal;\n }>,\n ) {\n const privateParams = getPrivateParams(params);\n const endpoint =\n params.runtime === undefined ? \"/v3/sandboxes\" : \"/v2/sandboxes\";\n return parseOrThrow(\n SandboxAndSessionResponse,\n await this.request(endpoint, {\n method: \"POST\",\n body: JSON.stringify({\n projectId: params.projectId,\n ports: params.ports,\n source: params.source,\n timeout: params.timeout,\n resources: params.resources,\n runtime: params.runtime,\n image: params.image,\n name: params.name,\n persistent: params.persistent,\n networkPolicy: params.networkPolicy\n ? toAPINetworkPolicy(params.networkPolicy)\n : undefined,\n env: params.env,\n tags: params.tags,\n snapshotExpiration: params.snapshotExpiration,\n keepLastSnapshots: params.keepLastSnapshots,\n mounts: params.mounts,\n ...privateParams,\n }),\n signal: params.signal,\n }),\n );\n }\n\n async forkSandbox(\n params: WithPrivate<{\n sourceSandbox: string;\n projectId: string;\n name?: string;\n ports?: number[];\n timeout?: number;\n resources?: { vcpus: number };\n persistent?: boolean;\n image?: string;\n networkPolicy?: NetworkPolicy;\n env?: Record<string, string>;\n tags?: Record<string, string>;\n snapshotExpiration?: number;\n keepLastSnapshots?: {\n count: number;\n expiration?: number;\n deleteEvicted?: boolean;\n };\n signal?: AbortSignal;\n }>,\n ) {\n const privateParams = getPrivateParams(params);\n return parseOrThrow(\n SandboxAndSessionResponse,\n await this.request(\n `/v2/sandboxes/${encodeURIComponent(params.sourceSandbox)}/fork`,\n {\n method: \"POST\",\n query: { projectId: params.projectId },\n body: JSON.stringify({\n name: params.name,\n ports: params.ports,\n timeout: params.timeout,\n resources: params.resources,\n image: params.image,\n persistent: params.persistent,\n networkPolicy: params.networkPolicy\n ? toAPINetworkPolicy(params.networkPolicy)\n : undefined,\n env: params.env,\n tags: params.tags,\n snapshotExpiration: params.snapshotExpiration,\n keepLastSnapshots: params.keepLastSnapshots,\n ...privateParams,\n }),\n signal: params.signal,\n },\n ),\n );\n }\n\n async runCommand(params: {\n sessionId: string;\n cwd?: string;\n command: string;\n args: string[];\n env: Record<string, string>;\n sudo: boolean;\n wait: true;\n logs?: boolean;\n onLog?: (log: LogOutputLine) => void;\n timeout?: number;\n signal?: AbortSignal;\n }): Promise<{\n command: CommandData;\n finished: Promise<CommandFinishedData>;\n }>;\n async runCommand(params: {\n sessionId: string;\n cwd?: string;\n command: string;\n args: string[];\n env: Record<string, string>;\n sudo: boolean;\n wait?: false;\n timeout?: number;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof CommandResponse>>>;\n async runCommand(params: {\n sessionId: string;\n cwd?: string;\n command: string;\n args: string[];\n env: Record<string, string>;\n sudo: boolean;\n wait?: boolean;\n logs?: boolean;\n onLog?: (log: LogOutputLine) => void;\n timeout?: number;\n signal?: AbortSignal;\n }): Promise<\n | {\n command: CommandData;\n finished: Promise<CommandFinishedData>;\n }\n | Parsed<z.infer<typeof CommandResponse>>\n > {\n if (params.wait) {\n const response = await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/cmd`,\n {\n method: \"POST\",\n body: JSON.stringify({\n command: params.command,\n args: params.args,\n cwd: params.cwd,\n env: params.env,\n sudo: params.sudo,\n wait: true,\n logs: params.logs || undefined,\n timeout: params.timeout,\n }),\n signal: params.signal,\n },\n );\n\n if (!response.ok) {\n await parseOrThrow(z.any(), response);\n }\n\n if (response.headers.get(\"content-type\") !== \"application/x-ndjson\") {\n throw new APIError(response, {\n message: \"Expected a stream of command data\",\n sessionId: params.sessionId,\n });\n }\n\n if (response.body === null) {\n throw new APIError(response, {\n message: \"No response body\",\n sessionId: params.sessionId,\n });\n }\n\n const jsonlinesStream = jsonlines.parse();\n pipe(response.body, jsonlinesStream, { signal: params.signal }).catch(\n (err) => {\n console.error(\"Error piping command stream:\", err);\n },\n );\n\n const iterator = jsonlinesStream[Symbol.asyncIterator]();\n const commandChunk = await iterator.next();\n if (commandChunk.done) {\n throw new StreamError(\n \"stream_ended_early\",\n \"Stream ended before command data was received\",\n params.sessionId,\n );\n }\n const { command } = CommandResponse.parse(commandChunk.value);\n\n const finished = (async () => {\n while (true) {\n const chunk = await iterator.next();\n if (chunk.done) {\n throw new StreamError(\n \"stream_ended_early\",\n \"Stream ended before command finished\",\n params.sessionId,\n );\n }\n\n if (chunk.value?.command) {\n const { command } = CommandFinishedResponse.parse(chunk.value);\n return command;\n }\n\n const parsed = LogLine.parse(chunk.value);\n if (parsed.stream === \"error\") {\n throw new StreamError(\n parsed.data.code,\n parsed.data.message,\n params.sessionId,\n );\n }\n params.onLog?.(parsed);\n }\n })();\n\n return { command, finished };\n }\n\n return parseOrThrow(\n CommandResponse,\n await this.request(`/v2/sandboxes/sessions/${params.sessionId}/cmd`, {\n method: \"POST\",\n body: JSON.stringify({\n command: params.command,\n args: params.args,\n cwd: params.cwd,\n env: params.env,\n sudo: params.sudo,\n timeout: params.timeout,\n }),\n signal: params.signal,\n }),\n );\n }\n\n async getCommand(params: {\n sessionId: string;\n cmdId: string;\n wait: true;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof CommandFinishedResponse>>>;\n async getCommand(params: {\n sessionId: string;\n cmdId: string;\n wait?: boolean;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof CommandResponse>>>;\n async getCommand(params: {\n sessionId: string;\n cmdId: string;\n wait?: boolean;\n signal?: AbortSignal;\n }) {\n return params.wait\n ? parseOrThrow(\n CommandFinishedResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.cmdId}`,\n { signal: params.signal, query: { wait: \"true\" } },\n ),\n )\n : parseOrThrow(\n CommandResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.cmdId}`,\n { signal: params.signal },\n ),\n );\n }\n\n async openInteractive(params: {\n sessionId: string;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof InteractiveSessionResponse>>> {\n return parseOrThrow(\n InteractiveSessionResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/interactive`,\n {\n method: \"POST\",\n body: JSON.stringify({}),\n signal: params.signal,\n },\n ),\n );\n }\n\n async mkDir(params: {\n sessionId: string;\n path: string;\n cwd?: string;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n EmptyResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/fs/mkdir`,\n {\n method: \"POST\",\n body: JSON.stringify({ path: params.path, cwd: params.cwd }),\n signal: params.signal,\n },\n ),\n );\n }\n\n getFileWriter(params: {\n sessionId: string;\n extractDir: string;\n signal?: AbortSignal;\n }) {\n const writer = new FileWriter();\n return {\n response: (async () => {\n return this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/fs/write`,\n {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/gzip\",\n \"x-cwd\": params.extractDir,\n },\n body: await consumeReadable(writer.readable),\n signal: params.signal,\n },\n );\n })(),\n writer,\n };\n }\n\n async listSessions(params: {\n /**\n * The ID or name of the project to which the sessions belong.\n * @example \"my-project\"\n */\n projectId: string;\n /**\n * Filter sessions by sandbox name.\n */\n name?: string;\n /**\n * Maximum number of sessions to list from a request.\n * @example 10\n */\n limit?: number;\n /**\n * Cursor for pagination.\n */\n cursor?: string;\n /**\n * Sort order for results.\n */\n sortOrder?: \"asc\" | \"desc\";\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n SessionsResponse,\n await this.request(`/v2/sandboxes/sessions`, {\n query: {\n project: params.projectId,\n name: params.name,\n limit: params.limit,\n cursor: params.cursor,\n sortOrder: params.sortOrder,\n },\n method: \"GET\",\n signal: params.signal,\n }),\n );\n }\n\n async listSnapshots(params: {\n /**\n * The ID or name of the project to which the snapshots belong.\n * @example \"my-project\"\n */\n projectId: string;\n /**\n * Filter snapshots by sandbox name.\n */\n name?: string;\n /**\n * Maximum number of snapshots to list from a request.\n * @example 10\n */\n limit?: number;\n /**\n * Cursor for pagination.\n */\n cursor?: string;\n /**\n * Sort order for results.\n */\n sortOrder?: \"asc\" | \"desc\";\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n SnapshotsResponse,\n await this.request(`/v2/sandboxes/snapshots`, {\n query: {\n project: params.projectId,\n name: params.name,\n limit: params.limit,\n cursor: params.cursor,\n sortOrder: params.sortOrder,\n },\n method: \"GET\",\n signal: params.signal,\n }),\n );\n }\n\n async getSnapshotTree(params: {\n /**\n * The ID or name of the project to which the snapshots belong.\n */\n projectId: string;\n /**\n * The snapshot ID to use as the anchor for the tree traversal.\n */\n snapshotId: string;\n /**\n * Maximum number of nodes to return.\n */\n limit?: number;\n /**\n * Sort order: \"asc\" for descendants, \"desc\" for ancestors.\n */\n sortOrder?: \"asc\" | \"desc\";\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n SnapshotTreeResponse,\n await this.request(`/v2/sandboxes/snapshots/tree`, {\n query: {\n project: params.projectId,\n snapshotId: params.snapshotId,\n limit: params.limit,\n sortOrder: params.sortOrder,\n },\n method: \"GET\",\n signal: params.signal,\n }),\n );\n }\n\n async listDrives(params: {\n projectId: string;\n limit?: number;\n cursor?: string | number;\n since?: number | string;\n until?: number | string;\n sortBy?: \"createdAt\" | \"updatedAt\" | \"name\";\n sortOrder?: \"asc\" | \"desc\";\n namePrefix?: string;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n DrivesResponse,\n await this.request(`/v2/sandboxes/drives`, {\n query: {\n projectId: params.projectId,\n limit: params.limit,\n cursor: params.cursor ?? params.until,\n since: params.since,\n sortBy: params.sortBy,\n sortOrder: params.sortOrder,\n namePrefix: params.namePrefix,\n },\n method: \"GET\",\n signal: params.signal,\n }),\n );\n }\n\n async getOrCreateDrive(params: {\n projectId: string;\n name: string;\n maxSizeBytes?: number;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n DriveResponse,\n await this.request(\n `/v2/sandboxes/drives/${encodeURIComponent(params.name)}`,\n {\n method: \"POST\",\n body: JSON.stringify({\n projectId: params.projectId,\n maxSizeBytes: params.maxSizeBytes,\n }),\n signal: params.signal,\n },\n ),\n );\n }\n\n async writeFiles(params: {\n sessionId: string;\n cwd: string;\n files: {\n path: string;\n content: string | Uint8Array;\n mode?: number;\n }[];\n extractDir: string;\n signal?: AbortSignal;\n }) {\n const { writer, response } = this.getFileWriter({\n sessionId: params.sessionId,\n extractDir: params.extractDir,\n signal: params.signal,\n });\n\n for (const file of params.files) {\n await writer.addFile({\n name: normalizePath({\n filePath: file.path,\n extractDir: params.extractDir,\n cwd: params.cwd,\n }),\n content: file.content,\n mode: file.mode,\n });\n }\n\n writer.end();\n await parseOrThrow(EmptyResponse, await response);\n }\n\n async readFile(params: {\n sessionId: string;\n path: string;\n cwd?: string;\n signal?: AbortSignal;\n }): Promise<Readable | null> {\n const response = await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/fs/read`,\n {\n method: \"POST\",\n body: JSON.stringify({ path: params.path, cwd: params.cwd }),\n signal: params.signal,\n },\n );\n\n if (response.status === 404) {\n return null;\n }\n\n // The file endpoint must return the file as an octet-stream. Any other\n // content type (e.g. application/json) indicates an error payload that\n // would otherwise be piped verbatim into the destination file.\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n if (!response.ok || !contentType.includes(\"application/octet-stream\")) {\n const text = await response.text().catch(() => \"\");\n let json: unknown;\n try {\n json = JSON.parse(text || \"{}\");\n } catch {\n json = undefined;\n }\n throw new APIError(response, {\n message: `Unexpected response reading file: status ${response.status}, content-type ${contentType || \"(none)\"}`,\n json,\n text,\n });\n }\n\n if (response.body === null) {\n return null;\n }\n\n return Readable.fromWeb(response.body);\n }\n\n async killCommand(params: {\n sessionId: string;\n commandId: string;\n signal: number;\n abortSignal?: AbortSignal;\n }) {\n return parseOrThrow(\n CommandResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.commandId}/kill`,\n {\n method: \"POST\",\n body: JSON.stringify({ signal: params.signal }),\n signal: params.abortSignal,\n },\n ),\n );\n }\n\n getLogs(params: {\n sessionId: string;\n cmdId: string;\n signal?: AbortSignal;\n }): AsyncGenerator<LogOutputLine, void, void> &\n Disposable & { close(): void } {\n const self = this;\n const disposer = new AbortController();\n const signal = !params.signal\n ? disposer.signal\n : mergeSignals(params.signal, disposer.signal);\n\n const generator = (async function* () {\n const url = `/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.cmdId}/logs`;\n const response = await self.request(url, {\n method: \"GET\",\n signal,\n });\n\n if (!response.ok) {\n await parseOrThrow(z.any(), response);\n }\n\n if (response.headers.get(\"content-type\") !== \"application/x-ndjson\") {\n throw new APIError(response, {\n message: \"Expected a stream of logs\",\n sessionId: params.sessionId,\n });\n }\n\n if (response.body === null) {\n throw new APIError(response, {\n message: \"No response body\",\n sessionId: params.sessionId,\n });\n }\n\n const jsonlinesStream = jsonlines.parse();\n pipe(response.body, jsonlinesStream, { signal }).catch((err) => {\n console.error(\"Error piping logs:\", err);\n });\n\n for await (const chunk of jsonlinesStream) {\n const parsed = LogLine.parse(chunk);\n if (parsed.stream === \"error\") {\n throw new StreamError(\n parsed.data.code,\n parsed.data.message,\n params.sessionId,\n );\n }\n yield parsed;\n }\n })();\n\n return Object.assign(generator, {\n [Symbol.dispose]() {\n disposer.abort(\"Disposed\");\n },\n close: () => disposer.abort(\"Disposed\"),\n });\n }\n\n async stopSession(params: {\n sessionId: string;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof StopSessionResponse>>> {\n const url = `/v2/sandboxes/sessions/${params.sessionId}/stop`;\n return parseOrThrow(\n StopSessionResponse,\n await this.request(url, { method: \"POST\", signal: params.signal }),\n );\n }\n\n async updateNetworkPolicy(params: {\n sessionId: string;\n networkPolicy: NetworkPolicy;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof SessionResponse>>> {\n const url = `/v2/sandboxes/sessions/${params.sessionId}/network-policy`;\n return parseOrThrow(\n SessionResponse,\n await this.request(url, {\n method: \"POST\",\n body: JSON.stringify(toAPINetworkPolicy(params.networkPolicy)),\n signal: params.signal,\n }),\n );\n }\n\n async extendTimeout(params: {\n sessionId: string;\n duration: number;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof SessionResponse>>> {\n const url = `/v2/sandboxes/sessions/${params.sessionId}/extend-timeout`;\n return parseOrThrow(\n SessionResponse,\n await this.request(url, {\n method: \"POST\",\n body: JSON.stringify({ duration: params.duration }),\n signal: params.signal,\n }),\n );\n }\n\n async createSnapshot(params: {\n sessionId: string;\n expiration?: number;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof CreateSnapshotResponse>>> {\n const url = `/v2/sandboxes/sessions/${params.sessionId}/snapshot`;\n const body =\n params.expiration === undefined\n ? undefined\n : JSON.stringify({ expiration: params.expiration });\n return parseOrThrow(\n CreateSnapshotResponse,\n await this.request(url, {\n method: \"POST\",\n body,\n signal: params.signal,\n }),\n );\n }\n\n async deleteSnapshot(params: {\n snapshotId: string;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof SnapshotResponse>>> {\n const url = `/v2/sandboxes/snapshots/${params.snapshotId}`;\n return parseOrThrow(\n SnapshotResponse,\n await this.request(url, { method: \"DELETE\", signal: params.signal }),\n );\n }\n\n async getSnapshot(params: {\n snapshotId: string;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof SnapshotResponse>>> {\n const url = `/v2/sandboxes/snapshots/${params.snapshotId}`;\n return parseOrThrow(\n SnapshotResponse,\n await this.request(url, { signal: params.signal }),\n );\n }\n\n async getSandbox(\n params: WithPrivate<{\n name: string;\n projectId: string;\n resume?: boolean;\n signal?: AbortSignal;\n }>,\n ) {\n const privateParams = getPrivateParams(params);\n const query: Record<string, string | undefined> = {\n projectId: params.projectId,\n ...privateParams,\n };\n if (params.resume !== undefined) {\n query.resume = String(params.resume);\n }\n return parseOrThrow(\n SandboxAndSessionResponse,\n await this.request(`/v2/sandboxes/${encodeURIComponent(params.name)}`, {\n query,\n signal: params.signal,\n }),\n );\n }\n\n async listSandboxes(params: {\n projectId: string;\n limit?: number;\n sortBy?: \"createdAt\" | \"name\" | \"statusUpdatedAt\";\n sortOrder?: \"asc\" | \"desc\";\n namePrefix?: string;\n cursor?: string;\n tags?: Record<string, string>;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n SandboxesPaginationResponse,\n await this.request(`/v2/sandboxes`, {\n query: {\n project: params.projectId,\n limit: params.limit,\n sortBy: params.sortBy,\n sortOrder: params.sortOrder,\n namePrefix: params.namePrefix,\n cursor: params.cursor,\n tags: toTagsFilter(params.tags),\n },\n method: \"GET\",\n signal: params.signal,\n }),\n );\n }\n\n async deleteDrive(params: {\n projectId: string;\n name: string;\n signal?: AbortSignal;\n }) {\n const url = `/v2/sandboxes/drives/${encodeURIComponent(params.name)}`;\n return parseOrThrow(\n DriveResponse,\n await this.request(url, {\n method: \"DELETE\",\n query: {\n projectId: params.projectId,\n },\n signal: params.signal,\n }),\n );\n }\n\n async updateSandbox(params: {\n name: string;\n projectId: string;\n persistent?: boolean;\n resources?: { vcpus?: number; memory?: number };\n timeout?: number;\n networkPolicy?: NetworkPolicy;\n tags?: Record<string, string>;\n ports?: number[];\n snapshotExpiration?: number;\n keepLastSnapshots?: {\n count: number;\n expiration?: number;\n deleteEvicted?: boolean;\n } | null;\n currentSnapshotId?: string;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n UpdateSandboxResponse,\n await this.request(`/v2/sandboxes/${encodeURIComponent(params.name)}`, {\n method: \"PATCH\",\n query: {\n projectId: params.projectId,\n },\n body: JSON.stringify({\n persistent: params.persistent,\n resources: params.resources,\n timeout: params.timeout,\n networkPolicy: params.networkPolicy\n ? toAPINetworkPolicy(params.networkPolicy)\n : undefined,\n tags: params.tags,\n ports: params.ports,\n snapshotExpiration: params.snapshotExpiration,\n keepLastSnapshots: params.keepLastSnapshots,\n currentSnapshotId: params.currentSnapshotId,\n }),\n signal: params.signal,\n }),\n );\n }\n\n async deleteSandbox(params: {\n name: string;\n projectId: string;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n UpdateSandboxResponse,\n await this.request(`/v2/sandboxes/${encodeURIComponent(params.name)}`, {\n method: \"DELETE\",\n query: {\n projectId: params.projectId,\n },\n signal: params.signal,\n }),\n );\n }\n}\n\nasync function pipe(\n readable: ReadableStream<Uint8Array>,\n output: NodeJS.WritableStream,\n options?: { signal?: AbortSignal },\n) {\n const reader = readable.getReader();\n let aborted = false;\n\n const signal = options?.signal;\n const onAbort = () => {\n aborted = true;\n const reason =\n signal?.reason ??\n new DOMException(\"The operation was aborted.\", \"AbortError\");\n void reader.cancel(reason).catch(() => {\n // ignore cancel errors when aborting\n });\n\n if (\"destroy\" in output && typeof output.destroy === \"function\") {\n output.destroy(reason as Error);\n return;\n }\n\n output.emit(\"error\", reason);\n output.end();\n };\n\n if (signal) {\n if (signal.aborted) {\n onAbort();\n } else {\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n }\n\n try {\n while (true) {\n const read = await reader.read();\n if (read.value) {\n output.write(Buffer.from(read.value));\n }\n if (read.done) {\n break;\n }\n }\n } catch (err) {\n if (!aborted) {\n output.emit(\"error\", err);\n }\n } finally {\n signal?.removeEventListener(\"abort\", onAbort);\n if (!aborted) {\n output.end();\n }\n }\n}\n\nfunction mergeSignals(...signals: [AbortSignal, ...AbortSignal[]]) {\n const controller = new AbortController();\n const onAbort = () => {\n controller.abort();\n for (const signal of signals) {\n signal.removeEventListener(\"abort\", onAbort);\n }\n };\n for (const signal of signals) {\n if (signal.aborted) {\n controller.abort();\n break;\n }\n signal.addEventListener(\"abort\", onAbort);\n }\n return controller.signal;\n}\n\nfunction toTagsFilter(\n tags: Record<string, string> | undefined,\n): string[] | undefined {\n if (tags === undefined) return undefined;\n const entries = Object.entries(tags);\n if (entries.length === 0) return undefined;\n return entries.map(([key, value]) => `${key}:${value}`);\n}\n"],"mappings":"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"} | ||
| {"version":3,"file":"api-client.cjs","names":["BaseClient","VERSION","getPrivateParams","parseOrThrow","SessionAndRoutesResponse","SandboxAndSessionResponse","toAPINetworkPolicy","z","APIError","StreamError","CommandResponse","CommandFinishedResponse","command","LogLine","InteractiveSessionResponse","EmptyResponse","FileWriter","consumeReadable","SessionsResponse","SnapshotsResponse","SnapshotTreeResponse","DrivesResponse","DriveResponse","normalizePath","json: unknown","Readable","StopSessionResponse","SessionResponse","CreateSnapshotResponse","SnapshotResponse","query: Record<string, string | undefined>","SandboxesPaginationResponse","UpdateSandboxResponse"],"sources":["../../src/api-client/api-client.ts"],"sourcesContent":["import {\n BaseClient,\n parseOrThrow,\n type Parsed,\n type RequestParams,\n} from \"./base-client.js\";\nimport {\n type CommandFinishedData,\n SessionAndRoutesResponse,\n SessionResponse,\n InteractiveSessionResponse,\n StopSessionResponse,\n SessionsResponse,\n CommandResponse,\n CommandFinishedResponse,\n EmptyResponse,\n LogLine,\n type LogOutputLine,\n SnapshotsResponse,\n SnapshotTreeResponse,\n SnapshotResponse,\n CreateSnapshotResponse,\n SandboxAndSessionResponse,\n SandboxesPaginationResponse,\n UpdateSandboxResponse,\n DrivesResponse,\n DriveResponse,\n type CommandData,\n} from \"./validators.js\";\nimport { APIError, StreamError } from \"./api-error.js\";\nimport { FileWriter } from \"./file-writer.js\";\nimport { VERSION } from \"../version.js\";\nimport { consumeReadable } from \"../utils/consume-readable.js\";\nimport { z } from \"zod\";\nimport jsonlines from \"jsonlines\";\nimport os from \"os\";\nimport { Readable } from \"stream\";\nimport { normalizePath } from \"../utils/normalizePath.js\";\nimport { getVercelOidcToken } from \"@vercel/oidc\";\nimport { NetworkPolicy } from \"../network-policy.js\";\nimport { toAPINetworkPolicy } from \"../utils/network-policy.js\";\nimport { getPrivateParams, WithPrivate } from \"../utils/types.js\";\nimport type { RUNTIMES, SandboxRegion } from \"../constants.js\";\nimport type { BaseCreateSandboxParams } from \"../sandbox.js\";\n\ninterface Claims {\n owner_id: string;\n project_id?: string;\n}\n\nfunction decodeUnverifiedToken(token: string): Claims | null {\n if (token.split(\".\").length !== 3) {\n return null;\n }\n try {\n const payload = JSON.parse(\n Buffer.from(token.split(\".\")[1], \"base64url\").toString(\"utf8\"),\n );\n if (payload.owner_id) {\n return { owner_id: payload.owner_id, project_id: payload.project_id };\n }\n return null;\n } catch {\n return null;\n }\n}\n\nexport interface WithFetchOptions {\n fetch?: typeof globalThis.fetch;\n}\n\nexport class APIClient extends BaseClient {\n private teamId: string;\n private projectId: string | undefined;\n private isJwtToken: boolean;\n\n constructor(params: {\n baseUrl?: string;\n teamId: string;\n token: string;\n fetch?: typeof globalThis.fetch;\n }) {\n super({\n baseUrl: params.baseUrl ?? \"https://vercel.com/api\",\n token: params.token,\n debug: false,\n fetch: params.fetch,\n });\n\n this.teamId = params.teamId;\n this.isJwtToken = false;\n\n const claims = decodeUnverifiedToken(params.token);\n if (claims) {\n this.isJwtToken = true;\n this.projectId = claims.project_id;\n this.teamId = claims.owner_id;\n }\n }\n\n private async ensureValidToken(): Promise<void> {\n if (!this.isJwtToken) {\n return;\n }\n\n try {\n // Use getVercelOidcToken to refresh the token with team/project scope\n const freshToken = await getVercelOidcToken({\n expirationBufferMs: 5 * 60 * 1000, // 5 minutes\n team: this.teamId,\n project: this.projectId,\n });\n\n // Update token if it changed\n if (freshToken !== this.token) {\n this.token = freshToken;\n\n const claims = decodeUnverifiedToken(freshToken);\n if (claims) {\n this.teamId = claims.owner_id;\n }\n }\n } catch {\n // Ignore refresh errors and continue with current token\n }\n }\n\n protected async request(path: string, params?: RequestParams) {\n await this.ensureValidToken();\n\n return super.request(path, {\n ...params,\n query: { teamId: this.teamId, ...params?.query },\n headers: {\n \"content-type\": \"application/json\",\n \"user-agent\": `vercel/sandbox/${VERSION} (Node.js/${process.version}; ${os.platform()}/${os.arch()})`,\n ...params?.headers,\n },\n });\n }\n\n async getSession(\n params: WithPrivate<{ sessionId: string; signal?: AbortSignal }>,\n ) {\n const privateParams = getPrivateParams(params);\n let querystring = new URLSearchParams(privateParams).toString();\n querystring = querystring ? `?${querystring}` : \"\";\n return parseOrThrow(\n SessionAndRoutesResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}${querystring}`,\n {\n signal: params.signal,\n },\n ),\n );\n }\n\n async createSandbox(\n params: WithPrivate<{\n name?: string;\n ports?: number[];\n projectId: string;\n source?:\n | {\n type: \"git\";\n url: string;\n depth?: number;\n revision?: string;\n username?: string;\n password?: string;\n }\n | { type: \"tarball\"; url: string }\n | { type: \"snapshot\"; snapshotId: string };\n timeout?: number;\n resources?: { vcpus: number };\n persistent?: boolean;\n runtime?: RUNTIMES | (string & {});\n image?: string;\n networkPolicy?: NetworkPolicy;\n env?: Record<string, string>;\n tags?: Record<string, string>;\n snapshotExpiration?: number;\n keepLastSnapshots?: {\n count: number;\n expiration?: number;\n deleteEvicted?: boolean;\n };\n mounts?: BaseCreateSandboxParams[\"mounts\"];\n region?: SandboxRegion;\n failoverRegions?: SandboxRegion[];\n signal?: AbortSignal;\n }>,\n ) {\n const privateParams = getPrivateParams(params);\n const endpoint =\n params.runtime === undefined ? \"/v3/sandboxes\" : \"/v2/sandboxes\";\n return parseOrThrow(\n SandboxAndSessionResponse,\n await this.request(endpoint, {\n method: \"POST\",\n body: JSON.stringify({\n projectId: params.projectId,\n ports: params.ports,\n source: params.source,\n timeout: params.timeout,\n resources: params.resources,\n runtime: params.runtime,\n image: params.image,\n name: params.name,\n persistent: params.persistent,\n networkPolicy: params.networkPolicy\n ? toAPINetworkPolicy(params.networkPolicy)\n : undefined,\n env: params.env,\n tags: params.tags,\n snapshotExpiration: params.snapshotExpiration,\n keepLastSnapshots: params.keepLastSnapshots,\n mounts: params.mounts,\n region: params.region,\n failoverRegions: params.failoverRegions,\n ...privateParams,\n }),\n signal: params.signal,\n }),\n );\n }\n\n async forkSandbox(\n params: WithPrivate<{\n sourceSandbox: string;\n projectId: string;\n name?: string;\n ports?: number[];\n timeout?: number;\n resources?: { vcpus: number };\n persistent?: boolean;\n image?: string;\n networkPolicy?: NetworkPolicy;\n env?: Record<string, string>;\n tags?: Record<string, string>;\n snapshotExpiration?: number;\n keepLastSnapshots?: {\n count: number;\n expiration?: number;\n deleteEvicted?: boolean;\n };\n region?: SandboxRegion;\n failoverRegions?: SandboxRegion[];\n signal?: AbortSignal;\n }>,\n ) {\n const privateParams = getPrivateParams(params);\n return parseOrThrow(\n SandboxAndSessionResponse,\n await this.request(\n `/v2/sandboxes/${encodeURIComponent(params.sourceSandbox)}/fork`,\n {\n method: \"POST\",\n query: { projectId: params.projectId },\n body: JSON.stringify({\n name: params.name,\n ports: params.ports,\n timeout: params.timeout,\n resources: params.resources,\n image: params.image,\n persistent: params.persistent,\n networkPolicy: params.networkPolicy\n ? toAPINetworkPolicy(params.networkPolicy)\n : undefined,\n env: params.env,\n tags: params.tags,\n snapshotExpiration: params.snapshotExpiration,\n keepLastSnapshots: params.keepLastSnapshots,\n region: params.region,\n failoverRegions: params.failoverRegions,\n ...privateParams,\n }),\n signal: params.signal,\n },\n ),\n );\n }\n\n async runCommand(params: {\n sessionId: string;\n cwd?: string;\n command: string;\n args: string[];\n env: Record<string, string>;\n sudo: boolean;\n wait: true;\n logs?: boolean;\n onLog?: (log: LogOutputLine) => void;\n timeout?: number;\n signal?: AbortSignal;\n }): Promise<{\n command: CommandData;\n finished: Promise<CommandFinishedData>;\n }>;\n async runCommand(params: {\n sessionId: string;\n cwd?: string;\n command: string;\n args: string[];\n env: Record<string, string>;\n sudo: boolean;\n wait?: false;\n timeout?: number;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof CommandResponse>>>;\n async runCommand(params: {\n sessionId: string;\n cwd?: string;\n command: string;\n args: string[];\n env: Record<string, string>;\n sudo: boolean;\n wait?: boolean;\n logs?: boolean;\n onLog?: (log: LogOutputLine) => void;\n timeout?: number;\n signal?: AbortSignal;\n }): Promise<\n | {\n command: CommandData;\n finished: Promise<CommandFinishedData>;\n }\n | Parsed<z.infer<typeof CommandResponse>>\n > {\n if (params.wait) {\n const response = await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/cmd`,\n {\n method: \"POST\",\n body: JSON.stringify({\n command: params.command,\n args: params.args,\n cwd: params.cwd,\n env: params.env,\n sudo: params.sudo,\n wait: true,\n logs: params.logs || undefined,\n timeout: params.timeout,\n }),\n signal: params.signal,\n },\n );\n\n if (!response.ok) {\n await parseOrThrow(z.any(), response);\n }\n\n if (response.headers.get(\"content-type\") !== \"application/x-ndjson\") {\n throw new APIError(response, {\n message: \"Expected a stream of command data\",\n sessionId: params.sessionId,\n });\n }\n\n if (response.body === null) {\n throw new APIError(response, {\n message: \"No response body\",\n sessionId: params.sessionId,\n });\n }\n\n const jsonlinesStream = jsonlines.parse();\n pipe(response.body, jsonlinesStream, { signal: params.signal }).catch(\n (err) => {\n console.error(\"Error piping command stream:\", err);\n },\n );\n\n const iterator = jsonlinesStream[Symbol.asyncIterator]();\n const commandChunk = await iterator.next();\n if (commandChunk.done) {\n throw new StreamError(\n \"stream_ended_early\",\n \"Stream ended before command data was received\",\n params.sessionId,\n );\n }\n const { command } = CommandResponse.parse(commandChunk.value);\n\n const finished = (async () => {\n while (true) {\n const chunk = await iterator.next();\n if (chunk.done) {\n throw new StreamError(\n \"stream_ended_early\",\n \"Stream ended before command finished\",\n params.sessionId,\n );\n }\n\n if (chunk.value?.command) {\n const { command } = CommandFinishedResponse.parse(chunk.value);\n return command;\n }\n\n const parsed = LogLine.parse(chunk.value);\n if (parsed.stream === \"error\") {\n throw new StreamError(\n parsed.data.code,\n parsed.data.message,\n params.sessionId,\n );\n }\n params.onLog?.(parsed);\n }\n })();\n\n return { command, finished };\n }\n\n return parseOrThrow(\n CommandResponse,\n await this.request(`/v2/sandboxes/sessions/${params.sessionId}/cmd`, {\n method: \"POST\",\n body: JSON.stringify({\n command: params.command,\n args: params.args,\n cwd: params.cwd,\n env: params.env,\n sudo: params.sudo,\n timeout: params.timeout,\n }),\n signal: params.signal,\n }),\n );\n }\n\n async getCommand(params: {\n sessionId: string;\n cmdId: string;\n wait: true;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof CommandFinishedResponse>>>;\n async getCommand(params: {\n sessionId: string;\n cmdId: string;\n wait?: boolean;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof CommandResponse>>>;\n async getCommand(params: {\n sessionId: string;\n cmdId: string;\n wait?: boolean;\n signal?: AbortSignal;\n }) {\n return params.wait\n ? parseOrThrow(\n CommandFinishedResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.cmdId}`,\n { signal: params.signal, query: { wait: \"true\" } },\n ),\n )\n : parseOrThrow(\n CommandResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.cmdId}`,\n { signal: params.signal },\n ),\n );\n }\n\n async openInteractive(params: {\n sessionId: string;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof InteractiveSessionResponse>>> {\n return parseOrThrow(\n InteractiveSessionResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/interactive`,\n {\n method: \"POST\",\n body: JSON.stringify({}),\n signal: params.signal,\n },\n ),\n );\n }\n\n async mkDir(params: {\n sessionId: string;\n path: string;\n cwd?: string;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n EmptyResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/fs/mkdir`,\n {\n method: \"POST\",\n body: JSON.stringify({ path: params.path, cwd: params.cwd }),\n signal: params.signal,\n },\n ),\n );\n }\n\n getFileWriter(params: {\n sessionId: string;\n extractDir: string;\n signal?: AbortSignal;\n }) {\n const writer = new FileWriter();\n return {\n response: (async () => {\n return this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/fs/write`,\n {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/gzip\",\n \"x-cwd\": params.extractDir,\n },\n body: await consumeReadable(writer.readable),\n signal: params.signal,\n },\n );\n })(),\n writer,\n };\n }\n\n async listSessions(params: {\n /**\n * The ID or name of the project to which the sessions belong.\n * @example \"my-project\"\n */\n projectId: string;\n /**\n * Filter sessions by sandbox name.\n */\n name?: string;\n /**\n * Maximum number of sessions to list from a request.\n * @example 10\n */\n limit?: number;\n /**\n * Cursor for pagination.\n */\n cursor?: string;\n /**\n * Sort order for results.\n */\n sortOrder?: \"asc\" | \"desc\";\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n SessionsResponse,\n await this.request(`/v2/sandboxes/sessions`, {\n query: {\n project: params.projectId,\n name: params.name,\n limit: params.limit,\n cursor: params.cursor,\n sortOrder: params.sortOrder,\n },\n method: \"GET\",\n signal: params.signal,\n }),\n );\n }\n\n async listSnapshots(params: {\n /**\n * The ID or name of the project to which the snapshots belong.\n * @example \"my-project\"\n */\n projectId: string;\n /**\n * Filter snapshots by sandbox name.\n */\n name?: string;\n /**\n * Maximum number of snapshots to list from a request.\n * @example 10\n */\n limit?: number;\n /**\n * Cursor for pagination.\n */\n cursor?: string;\n /**\n * Sort order for results.\n */\n sortOrder?: \"asc\" | \"desc\";\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n SnapshotsResponse,\n await this.request(`/v2/sandboxes/snapshots`, {\n query: {\n project: params.projectId,\n name: params.name,\n limit: params.limit,\n cursor: params.cursor,\n sortOrder: params.sortOrder,\n },\n method: \"GET\",\n signal: params.signal,\n }),\n );\n }\n\n async getSnapshotTree(params: {\n /**\n * The ID or name of the project to which the snapshots belong.\n */\n projectId: string;\n /**\n * The snapshot ID to use as the anchor for the tree traversal.\n */\n snapshotId: string;\n /**\n * Maximum number of nodes to return.\n */\n limit?: number;\n /**\n * Sort order: \"asc\" for descendants, \"desc\" for ancestors.\n */\n sortOrder?: \"asc\" | \"desc\";\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n SnapshotTreeResponse,\n await this.request(`/v2/sandboxes/snapshots/tree`, {\n query: {\n project: params.projectId,\n snapshotId: params.snapshotId,\n limit: params.limit,\n sortOrder: params.sortOrder,\n },\n method: \"GET\",\n signal: params.signal,\n }),\n );\n }\n\n async listDrives(params: {\n projectId: string;\n limit?: number;\n cursor?: string | number;\n since?: number | string;\n until?: number | string;\n sortBy?: \"createdAt\" | \"updatedAt\" | \"name\";\n sortOrder?: \"asc\" | \"desc\";\n namePrefix?: string;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n DrivesResponse,\n await this.request(`/v2/sandboxes/drives`, {\n query: {\n projectId: params.projectId,\n limit: params.limit,\n cursor: params.cursor ?? params.until,\n since: params.since,\n sortBy: params.sortBy,\n sortOrder: params.sortOrder,\n namePrefix: params.namePrefix,\n },\n method: \"GET\",\n signal: params.signal,\n }),\n );\n }\n\n async getOrCreateDrive(params: {\n projectId: string;\n name: string;\n region?: string;\n maxSizeBytes?: number;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n DriveResponse,\n await this.request(\n `/v2/sandboxes/drives/${encodeURIComponent(params.name)}`,\n {\n method: \"POST\",\n body: JSON.stringify({\n projectId: params.projectId,\n region: params.region,\n maxSizeBytes: params.maxSizeBytes,\n }),\n signal: params.signal,\n },\n ),\n );\n }\n\n async writeFiles(params: {\n sessionId: string;\n cwd: string;\n files: {\n path: string;\n content: string | Uint8Array;\n mode?: number;\n }[];\n extractDir: string;\n signal?: AbortSignal;\n }) {\n const { writer, response } = this.getFileWriter({\n sessionId: params.sessionId,\n extractDir: params.extractDir,\n signal: params.signal,\n });\n\n for (const file of params.files) {\n await writer.addFile({\n name: normalizePath({\n filePath: file.path,\n extractDir: params.extractDir,\n cwd: params.cwd,\n }),\n content: file.content,\n mode: file.mode,\n });\n }\n\n writer.end();\n await parseOrThrow(EmptyResponse, await response);\n }\n\n async readFile(params: {\n sessionId: string;\n path: string;\n cwd?: string;\n signal?: AbortSignal;\n }): Promise<Readable | null> {\n const response = await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/fs/read`,\n {\n method: \"POST\",\n body: JSON.stringify({ path: params.path, cwd: params.cwd }),\n signal: params.signal,\n },\n );\n\n if (response.status === 404) {\n return null;\n }\n\n // The file endpoint must return the file as an octet-stream. Any other\n // content type (e.g. application/json) indicates an error payload that\n // would otherwise be piped verbatim into the destination file.\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n if (!response.ok || !contentType.includes(\"application/octet-stream\")) {\n const text = await response.text().catch(() => \"\");\n let json: unknown;\n try {\n json = JSON.parse(text || \"{}\");\n } catch {\n json = undefined;\n }\n throw new APIError(response, {\n message: `Unexpected response reading file: status ${response.status}, content-type ${contentType || \"(none)\"}`,\n json,\n text,\n });\n }\n\n if (response.body === null) {\n return null;\n }\n\n return Readable.fromWeb(response.body);\n }\n\n async killCommand(params: {\n sessionId: string;\n commandId: string;\n signal: number;\n abortSignal?: AbortSignal;\n }) {\n return parseOrThrow(\n CommandResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.commandId}/kill`,\n {\n method: \"POST\",\n body: JSON.stringify({ signal: params.signal }),\n signal: params.abortSignal,\n },\n ),\n );\n }\n\n getLogs(params: {\n sessionId: string;\n cmdId: string;\n signal?: AbortSignal;\n }): AsyncGenerator<LogOutputLine, void, void> &\n Disposable & { close(): void } {\n const self = this;\n const disposer = new AbortController();\n const signal = !params.signal\n ? disposer.signal\n : mergeSignals(params.signal, disposer.signal);\n\n const generator = (async function* () {\n const url = `/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.cmdId}/logs`;\n const response = await self.request(url, {\n method: \"GET\",\n signal,\n });\n\n if (!response.ok) {\n await parseOrThrow(z.any(), response);\n }\n\n if (response.headers.get(\"content-type\") !== \"application/x-ndjson\") {\n throw new APIError(response, {\n message: \"Expected a stream of logs\",\n sessionId: params.sessionId,\n });\n }\n\n if (response.body === null) {\n throw new APIError(response, {\n message: \"No response body\",\n sessionId: params.sessionId,\n });\n }\n\n const jsonlinesStream = jsonlines.parse();\n pipe(response.body, jsonlinesStream, { signal }).catch((err) => {\n console.error(\"Error piping logs:\", err);\n });\n\n for await (const chunk of jsonlinesStream) {\n const parsed = LogLine.parse(chunk);\n if (parsed.stream === \"error\") {\n throw new StreamError(\n parsed.data.code,\n parsed.data.message,\n params.sessionId,\n );\n }\n yield parsed;\n }\n })();\n\n return Object.assign(generator, {\n [Symbol.dispose]() {\n disposer.abort(\"Disposed\");\n },\n close: () => disposer.abort(\"Disposed\"),\n });\n }\n\n async stopSession(params: {\n sessionId: string;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof StopSessionResponse>>> {\n const url = `/v2/sandboxes/sessions/${params.sessionId}/stop`;\n return parseOrThrow(\n StopSessionResponse,\n await this.request(url, { method: \"POST\", signal: params.signal }),\n );\n }\n\n async updateNetworkPolicy(params: {\n sessionId: string;\n networkPolicy: NetworkPolicy;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof SessionResponse>>> {\n const url = `/v2/sandboxes/sessions/${params.sessionId}/network-policy`;\n return parseOrThrow(\n SessionResponse,\n await this.request(url, {\n method: \"POST\",\n body: JSON.stringify(toAPINetworkPolicy(params.networkPolicy)),\n signal: params.signal,\n }),\n );\n }\n\n async extendTimeout(params: {\n sessionId: string;\n duration: number;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof SessionResponse>>> {\n const url = `/v2/sandboxes/sessions/${params.sessionId}/extend-timeout`;\n return parseOrThrow(\n SessionResponse,\n await this.request(url, {\n method: \"POST\",\n body: JSON.stringify({ duration: params.duration }),\n signal: params.signal,\n }),\n );\n }\n\n async createSnapshot(params: {\n sessionId: string;\n expiration?: number;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof CreateSnapshotResponse>>> {\n const url = `/v2/sandboxes/sessions/${params.sessionId}/snapshot`;\n const body =\n params.expiration === undefined\n ? undefined\n : JSON.stringify({ expiration: params.expiration });\n return parseOrThrow(\n CreateSnapshotResponse,\n await this.request(url, {\n method: \"POST\",\n body,\n signal: params.signal,\n }),\n );\n }\n\n async deleteSnapshot(params: {\n snapshotId: string;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof SnapshotResponse>>> {\n const url = `/v2/sandboxes/snapshots/${params.snapshotId}`;\n return parseOrThrow(\n SnapshotResponse,\n await this.request(url, { method: \"DELETE\", signal: params.signal }),\n );\n }\n\n async getSnapshot(params: {\n snapshotId: string;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof SnapshotResponse>>> {\n const url = `/v2/sandboxes/snapshots/${params.snapshotId}`;\n return parseOrThrow(\n SnapshotResponse,\n await this.request(url, { signal: params.signal }),\n );\n }\n\n async getSandbox(\n params: WithPrivate<{\n name: string;\n projectId: string;\n resume?: boolean;\n signal?: AbortSignal;\n }>,\n ) {\n const privateParams = getPrivateParams(params);\n const query: Record<string, string | undefined> = {\n projectId: params.projectId,\n ...privateParams,\n };\n if (params.resume !== undefined) {\n query.resume = String(params.resume);\n }\n return parseOrThrow(\n SandboxAndSessionResponse,\n await this.request(`/v2/sandboxes/${encodeURIComponent(params.name)}`, {\n query,\n signal: params.signal,\n }),\n );\n }\n\n async listSandboxes(params: {\n projectId: string;\n limit?: number;\n sortBy?: \"createdAt\" | \"name\" | \"statusUpdatedAt\";\n sortOrder?: \"asc\" | \"desc\";\n namePrefix?: string;\n cursor?: string;\n tags?: Record<string, string>;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n SandboxesPaginationResponse,\n await this.request(`/v2/sandboxes`, {\n query: {\n project: params.projectId,\n limit: params.limit,\n sortBy: params.sortBy,\n sortOrder: params.sortOrder,\n namePrefix: params.namePrefix,\n cursor: params.cursor,\n tags: toTagsFilter(params.tags),\n },\n method: \"GET\",\n signal: params.signal,\n }),\n );\n }\n\n async deleteDrive(params: {\n projectId: string;\n name: string;\n signal?: AbortSignal;\n }) {\n const url = `/v2/sandboxes/drives/${encodeURIComponent(params.name)}`;\n return parseOrThrow(\n DriveResponse,\n await this.request(url, {\n method: \"DELETE\",\n query: {\n projectId: params.projectId,\n },\n signal: params.signal,\n }),\n );\n }\n\n async updateSandbox(params: {\n name: string;\n projectId: string;\n persistent?: boolean;\n resources?: { vcpus?: number; memory?: number };\n timeout?: number;\n networkPolicy?: NetworkPolicy;\n tags?: Record<string, string>;\n ports?: number[];\n snapshotExpiration?: number;\n keepLastSnapshots?: {\n count: number;\n expiration?: number;\n deleteEvicted?: boolean;\n } | null;\n currentSnapshotId?: string;\n region?: SandboxRegion;\n failoverRegions?: SandboxRegion[];\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n UpdateSandboxResponse,\n await this.request(`/v2/sandboxes/${encodeURIComponent(params.name)}`, {\n method: \"PATCH\",\n query: {\n projectId: params.projectId,\n },\n body: JSON.stringify({\n persistent: params.persistent,\n resources: params.resources,\n timeout: params.timeout,\n networkPolicy: params.networkPolicy\n ? toAPINetworkPolicy(params.networkPolicy)\n : undefined,\n tags: params.tags,\n ports: params.ports,\n snapshotExpiration: params.snapshotExpiration,\n keepLastSnapshots: params.keepLastSnapshots,\n currentSnapshotId: params.currentSnapshotId,\n region: params.region,\n failoverRegions: params.failoverRegions,\n }),\n signal: params.signal,\n }),\n );\n }\n\n async deleteSandbox(params: {\n name: string;\n projectId: string;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n UpdateSandboxResponse,\n await this.request(`/v2/sandboxes/${encodeURIComponent(params.name)}`, {\n method: \"DELETE\",\n query: {\n projectId: params.projectId,\n },\n signal: params.signal,\n }),\n );\n }\n}\n\nasync function pipe(\n readable: ReadableStream<Uint8Array>,\n output: NodeJS.WritableStream,\n options?: { signal?: AbortSignal },\n) {\n const reader = readable.getReader();\n let aborted = false;\n\n const signal = options?.signal;\n const onAbort = () => {\n aborted = true;\n const reason =\n signal?.reason ??\n new DOMException(\"The operation was aborted.\", \"AbortError\");\n void reader.cancel(reason).catch(() => {\n // ignore cancel errors when aborting\n });\n\n if (\"destroy\" in output && typeof output.destroy === \"function\") {\n output.destroy(reason as Error);\n return;\n }\n\n output.emit(\"error\", reason);\n output.end();\n };\n\n if (signal) {\n if (signal.aborted) {\n onAbort();\n } else {\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n }\n\n try {\n while (true) {\n const read = await reader.read();\n if (read.value) {\n output.write(Buffer.from(read.value));\n }\n if (read.done) {\n break;\n }\n }\n } catch (err) {\n if (!aborted) {\n output.emit(\"error\", err);\n }\n } finally {\n signal?.removeEventListener(\"abort\", onAbort);\n if (!aborted) {\n output.end();\n }\n }\n}\n\nfunction mergeSignals(...signals: [AbortSignal, ...AbortSignal[]]) {\n const controller = new AbortController();\n const onAbort = () => {\n controller.abort();\n for (const signal of signals) {\n signal.removeEventListener(\"abort\", onAbort);\n }\n };\n for (const signal of signals) {\n if (signal.aborted) {\n controller.abort();\n break;\n }\n signal.addEventListener(\"abort\", onAbort);\n }\n return controller.signal;\n}\n\nfunction toTagsFilter(\n tags: Record<string, string> | undefined,\n): string[] | undefined {\n if (tags === undefined) return undefined;\n const entries = Object.entries(tags);\n if (entries.length === 0) return undefined;\n return entries.map(([key, value]) => `${key}:${value}`);\n}\n"],"mappings":"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"} |
@@ -6,3 +6,3 @@ import { BaseClient, Parsed, RequestParams } from "./base-client.cjs"; | ||
| import { WithPrivate } from "../utils/types.cjs"; | ||
| import { RUNTIMES } from "../constants.cjs"; | ||
| import { RUNTIMES, SandboxRegion } from "../constants.cjs"; | ||
| import { BaseCreateSandboxParams } from "../sandbox.cjs"; | ||
@@ -186,2 +186,4 @@ import { z } from "zod"; | ||
| mounts?: BaseCreateSandboxParams["mounts"]; | ||
| region?: SandboxRegion; | ||
| failoverRegions?: SandboxRegion[]; | ||
| signal?: AbortSignal; | ||
@@ -197,2 +199,3 @@ }>): Promise<Parsed<{ | ||
| region?: string | undefined; | ||
| failoverRegions?: string[] | undefined; | ||
| vcpus?: number | undefined; | ||
@@ -449,2 +452,4 @@ memory?: number | undefined; | ||
| }; | ||
| region?: SandboxRegion; | ||
| failoverRegions?: SandboxRegion[]; | ||
| signal?: AbortSignal; | ||
@@ -460,2 +465,3 @@ }>): Promise<Parsed<{ | ||
| region?: string | undefined; | ||
| failoverRegions?: string[] | undefined; | ||
| vcpus?: number | undefined; | ||
@@ -925,2 +931,3 @@ memory?: number | undefined; | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -964,2 +971,3 @@ lastUsedAt?: number | undefined; | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -978,2 +986,3 @@ lastUsedAt?: number | undefined; | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -999,2 +1008,3 @@ lastUsedAt?: number | undefined; | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -1013,2 +1023,3 @@ lastUsedAt?: number | undefined; | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -1036,2 +1047,3 @@ lastUsedAt?: number | undefined; | ||
| projectId: string; | ||
| region: string; | ||
| maxSizeBytes: number; | ||
@@ -1051,2 +1063,3 @@ createdAt: number; | ||
| name: string; | ||
| region?: string; | ||
| maxSizeBytes?: number; | ||
@@ -1058,2 +1071,3 @@ signal?: AbortSignal; | ||
| projectId: string; | ||
| region: string; | ||
| maxSizeBytes: number; | ||
@@ -1148,2 +1162,3 @@ createdAt: number; | ||
| region?: string | undefined; | ||
| failoverRegions?: string[] | undefined; | ||
| vcpus?: number | undefined; | ||
@@ -1398,2 +1413,3 @@ memory?: number | undefined; | ||
| region?: string | undefined; | ||
| failoverRegions?: string[] | undefined; | ||
| vcpus?: number | undefined; | ||
@@ -1523,2 +1539,3 @@ memory?: number | undefined; | ||
| projectId: string; | ||
| region: string; | ||
| maxSizeBytes: number; | ||
@@ -1550,2 +1567,4 @@ createdAt: number; | ||
| currentSnapshotId?: string; | ||
| region?: SandboxRegion; | ||
| failoverRegions?: SandboxRegion[]; | ||
| signal?: AbortSignal; | ||
@@ -1561,2 +1580,3 @@ }): Promise<Parsed<{ | ||
| region?: string | undefined; | ||
| failoverRegions?: string[] | undefined; | ||
| vcpus?: number | undefined; | ||
@@ -1692,2 +1712,3 @@ memory?: number | undefined; | ||
| region?: string | undefined; | ||
| failoverRegions?: string[] | undefined; | ||
| vcpus?: number | undefined; | ||
@@ -1694,0 +1715,0 @@ memory?: number | undefined; |
@@ -6,3 +6,3 @@ import { BaseClient, Parsed, RequestParams } from "./base-client.js"; | ||
| import { WithPrivate } from "../utils/types.js"; | ||
| import { RUNTIMES } from "../constants.js"; | ||
| import { RUNTIMES, SandboxRegion } from "../constants.js"; | ||
| import { BaseCreateSandboxParams } from "../sandbox.js"; | ||
@@ -186,2 +186,4 @@ import { z } from "zod"; | ||
| mounts?: BaseCreateSandboxParams["mounts"]; | ||
| region?: SandboxRegion; | ||
| failoverRegions?: SandboxRegion[]; | ||
| signal?: AbortSignal; | ||
@@ -197,2 +199,3 @@ }>): Promise<Parsed<{ | ||
| region?: string | undefined; | ||
| failoverRegions?: string[] | undefined; | ||
| vcpus?: number | undefined; | ||
@@ -449,2 +452,4 @@ memory?: number | undefined; | ||
| }; | ||
| region?: SandboxRegion; | ||
| failoverRegions?: SandboxRegion[]; | ||
| signal?: AbortSignal; | ||
@@ -460,2 +465,3 @@ }>): Promise<Parsed<{ | ||
| region?: string | undefined; | ||
| failoverRegions?: string[] | undefined; | ||
| vcpus?: number | undefined; | ||
@@ -925,2 +931,3 @@ memory?: number | undefined; | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -964,2 +971,3 @@ lastUsedAt?: number | undefined; | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -978,2 +986,3 @@ lastUsedAt?: number | undefined; | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -999,2 +1008,3 @@ lastUsedAt?: number | undefined; | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -1013,2 +1023,3 @@ lastUsedAt?: number | undefined; | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -1036,2 +1047,3 @@ lastUsedAt?: number | undefined; | ||
| projectId: string; | ||
| region: string; | ||
| maxSizeBytes: number; | ||
@@ -1051,2 +1063,3 @@ createdAt: number; | ||
| name: string; | ||
| region?: string; | ||
| maxSizeBytes?: number; | ||
@@ -1058,2 +1071,3 @@ signal?: AbortSignal; | ||
| projectId: string; | ||
| region: string; | ||
| maxSizeBytes: number; | ||
@@ -1148,2 +1162,3 @@ createdAt: number; | ||
| region?: string | undefined; | ||
| failoverRegions?: string[] | undefined; | ||
| vcpus?: number | undefined; | ||
@@ -1398,2 +1413,3 @@ memory?: number | undefined; | ||
| region?: string | undefined; | ||
| failoverRegions?: string[] | undefined; | ||
| vcpus?: number | undefined; | ||
@@ -1523,2 +1539,3 @@ memory?: number | undefined; | ||
| projectId: string; | ||
| region: string; | ||
| maxSizeBytes: number; | ||
@@ -1550,2 +1567,4 @@ createdAt: number; | ||
| currentSnapshotId?: string; | ||
| region?: SandboxRegion; | ||
| failoverRegions?: SandboxRegion[]; | ||
| signal?: AbortSignal; | ||
@@ -1561,2 +1580,3 @@ }): Promise<Parsed<{ | ||
| region?: string | undefined; | ||
| failoverRegions?: string[] | undefined; | ||
| vcpus?: number | undefined; | ||
@@ -1692,2 +1712,3 @@ memory?: number | undefined; | ||
| region?: string | undefined; | ||
| failoverRegions?: string[] | undefined; | ||
| vcpus?: number | undefined; | ||
@@ -1694,0 +1715,0 @@ memory?: number | undefined; |
@@ -104,2 +104,4 @@ import { APIError, StreamError } from "./api-error.js"; | ||
| mounts: params.mounts, | ||
| region: params.region, | ||
| failoverRegions: params.failoverRegions, | ||
| ...privateParams | ||
@@ -127,2 +129,4 @@ }), | ||
| keepLastSnapshots: params.keepLastSnapshots, | ||
| region: params.region, | ||
| failoverRegions: params.failoverRegions, | ||
| ...privateParams | ||
@@ -294,2 +298,3 @@ }), | ||
| projectId: params.projectId, | ||
| region: params.region, | ||
| maxSizeBytes: params.maxSizeBytes | ||
@@ -480,3 +485,5 @@ }), | ||
| keepLastSnapshots: params.keepLastSnapshots, | ||
| currentSnapshotId: params.currentSnapshotId | ||
| currentSnapshotId: params.currentSnapshotId, | ||
| region: params.region, | ||
| failoverRegions: params.failoverRegions | ||
| }), | ||
@@ -483,0 +490,0 @@ signal: params.signal |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"api-client.js","names":["command","json: unknown","query: Record<string, string | undefined>"],"sources":["../../src/api-client/api-client.ts"],"sourcesContent":["import {\n BaseClient,\n parseOrThrow,\n type Parsed,\n type RequestParams,\n} from \"./base-client.js\";\nimport {\n type CommandFinishedData,\n SessionAndRoutesResponse,\n SessionResponse,\n InteractiveSessionResponse,\n StopSessionResponse,\n SessionsResponse,\n CommandResponse,\n CommandFinishedResponse,\n EmptyResponse,\n LogLine,\n type LogOutputLine,\n SnapshotsResponse,\n SnapshotTreeResponse,\n SnapshotResponse,\n CreateSnapshotResponse,\n SandboxAndSessionResponse,\n SandboxesPaginationResponse,\n UpdateSandboxResponse,\n DrivesResponse,\n DriveResponse,\n type CommandData,\n} from \"./validators.js\";\nimport { APIError, StreamError } from \"./api-error.js\";\nimport { FileWriter } from \"./file-writer.js\";\nimport { VERSION } from \"../version.js\";\nimport { consumeReadable } from \"../utils/consume-readable.js\";\nimport { z } from \"zod\";\nimport jsonlines from \"jsonlines\";\nimport os from \"os\";\nimport { Readable } from \"stream\";\nimport { normalizePath } from \"../utils/normalizePath.js\";\nimport { getVercelOidcToken } from \"@vercel/oidc\";\nimport { NetworkPolicy } from \"../network-policy.js\";\nimport { toAPINetworkPolicy } from \"../utils/network-policy.js\";\nimport { getPrivateParams, WithPrivate } from \"../utils/types.js\";\nimport type { RUNTIMES } from \"../constants.js\";\nimport type { BaseCreateSandboxParams } from \"../sandbox.js\";\n\ninterface Claims {\n owner_id: string;\n project_id?: string;\n}\n\nfunction decodeUnverifiedToken(token: string): Claims | null {\n if (token.split(\".\").length !== 3) {\n return null;\n }\n try {\n const payload = JSON.parse(\n Buffer.from(token.split(\".\")[1], \"base64url\").toString(\"utf8\"),\n );\n if (payload.owner_id) {\n return { owner_id: payload.owner_id, project_id: payload.project_id };\n }\n return null;\n } catch {\n return null;\n }\n}\n\nexport interface WithFetchOptions {\n fetch?: typeof globalThis.fetch;\n}\n\nexport class APIClient extends BaseClient {\n private teamId: string;\n private projectId: string | undefined;\n private isJwtToken: boolean;\n\n constructor(params: {\n baseUrl?: string;\n teamId: string;\n token: string;\n fetch?: typeof globalThis.fetch;\n }) {\n super({\n baseUrl: params.baseUrl ?? \"https://vercel.com/api\",\n token: params.token,\n debug: false,\n fetch: params.fetch,\n });\n\n this.teamId = params.teamId;\n this.isJwtToken = false;\n\n const claims = decodeUnverifiedToken(params.token);\n if (claims) {\n this.isJwtToken = true;\n this.projectId = claims.project_id;\n this.teamId = claims.owner_id;\n }\n }\n\n private async ensureValidToken(): Promise<void> {\n if (!this.isJwtToken) {\n return;\n }\n\n try {\n // Use getVercelOidcToken to refresh the token with team/project scope\n const freshToken = await getVercelOidcToken({\n expirationBufferMs: 5 * 60 * 1000, // 5 minutes\n team: this.teamId,\n project: this.projectId,\n });\n\n // Update token if it changed\n if (freshToken !== this.token) {\n this.token = freshToken;\n\n const claims = decodeUnverifiedToken(freshToken);\n if (claims) {\n this.teamId = claims.owner_id;\n }\n }\n } catch {\n // Ignore refresh errors and continue with current token\n }\n }\n\n protected async request(path: string, params?: RequestParams) {\n await this.ensureValidToken();\n\n return super.request(path, {\n ...params,\n query: { teamId: this.teamId, ...params?.query },\n headers: {\n \"content-type\": \"application/json\",\n \"user-agent\": `vercel/sandbox/${VERSION} (Node.js/${process.version}; ${os.platform()}/${os.arch()})`,\n ...params?.headers,\n },\n });\n }\n\n async getSession(\n params: WithPrivate<{ sessionId: string; signal?: AbortSignal }>,\n ) {\n const privateParams = getPrivateParams(params);\n let querystring = new URLSearchParams(privateParams).toString();\n querystring = querystring ? `?${querystring}` : \"\";\n return parseOrThrow(\n SessionAndRoutesResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}${querystring}`,\n {\n signal: params.signal,\n },\n ),\n );\n }\n\n async createSandbox(\n params: WithPrivate<{\n name?: string;\n ports?: number[];\n projectId: string;\n source?:\n | {\n type: \"git\";\n url: string;\n depth?: number;\n revision?: string;\n username?: string;\n password?: string;\n }\n | { type: \"tarball\"; url: string }\n | { type: \"snapshot\"; snapshotId: string };\n timeout?: number;\n resources?: { vcpus: number };\n persistent?: boolean;\n runtime?: RUNTIMES | (string & {});\n image?: string;\n networkPolicy?: NetworkPolicy;\n env?: Record<string, string>;\n tags?: Record<string, string>;\n snapshotExpiration?: number;\n keepLastSnapshots?: {\n count: number;\n expiration?: number;\n deleteEvicted?: boolean;\n };\n mounts?: BaseCreateSandboxParams[\"mounts\"];\n signal?: AbortSignal;\n }>,\n ) {\n const privateParams = getPrivateParams(params);\n const endpoint =\n params.runtime === undefined ? \"/v3/sandboxes\" : \"/v2/sandboxes\";\n return parseOrThrow(\n SandboxAndSessionResponse,\n await this.request(endpoint, {\n method: \"POST\",\n body: JSON.stringify({\n projectId: params.projectId,\n ports: params.ports,\n source: params.source,\n timeout: params.timeout,\n resources: params.resources,\n runtime: params.runtime,\n image: params.image,\n name: params.name,\n persistent: params.persistent,\n networkPolicy: params.networkPolicy\n ? toAPINetworkPolicy(params.networkPolicy)\n : undefined,\n env: params.env,\n tags: params.tags,\n snapshotExpiration: params.snapshotExpiration,\n keepLastSnapshots: params.keepLastSnapshots,\n mounts: params.mounts,\n ...privateParams,\n }),\n signal: params.signal,\n }),\n );\n }\n\n async forkSandbox(\n params: WithPrivate<{\n sourceSandbox: string;\n projectId: string;\n name?: string;\n ports?: number[];\n timeout?: number;\n resources?: { vcpus: number };\n persistent?: boolean;\n image?: string;\n networkPolicy?: NetworkPolicy;\n env?: Record<string, string>;\n tags?: Record<string, string>;\n snapshotExpiration?: number;\n keepLastSnapshots?: {\n count: number;\n expiration?: number;\n deleteEvicted?: boolean;\n };\n signal?: AbortSignal;\n }>,\n ) {\n const privateParams = getPrivateParams(params);\n return parseOrThrow(\n SandboxAndSessionResponse,\n await this.request(\n `/v2/sandboxes/${encodeURIComponent(params.sourceSandbox)}/fork`,\n {\n method: \"POST\",\n query: { projectId: params.projectId },\n body: JSON.stringify({\n name: params.name,\n ports: params.ports,\n timeout: params.timeout,\n resources: params.resources,\n image: params.image,\n persistent: params.persistent,\n networkPolicy: params.networkPolicy\n ? toAPINetworkPolicy(params.networkPolicy)\n : undefined,\n env: params.env,\n tags: params.tags,\n snapshotExpiration: params.snapshotExpiration,\n keepLastSnapshots: params.keepLastSnapshots,\n ...privateParams,\n }),\n signal: params.signal,\n },\n ),\n );\n }\n\n async runCommand(params: {\n sessionId: string;\n cwd?: string;\n command: string;\n args: string[];\n env: Record<string, string>;\n sudo: boolean;\n wait: true;\n logs?: boolean;\n onLog?: (log: LogOutputLine) => void;\n timeout?: number;\n signal?: AbortSignal;\n }): Promise<{\n command: CommandData;\n finished: Promise<CommandFinishedData>;\n }>;\n async runCommand(params: {\n sessionId: string;\n cwd?: string;\n command: string;\n args: string[];\n env: Record<string, string>;\n sudo: boolean;\n wait?: false;\n timeout?: number;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof CommandResponse>>>;\n async runCommand(params: {\n sessionId: string;\n cwd?: string;\n command: string;\n args: string[];\n env: Record<string, string>;\n sudo: boolean;\n wait?: boolean;\n logs?: boolean;\n onLog?: (log: LogOutputLine) => void;\n timeout?: number;\n signal?: AbortSignal;\n }): Promise<\n | {\n command: CommandData;\n finished: Promise<CommandFinishedData>;\n }\n | Parsed<z.infer<typeof CommandResponse>>\n > {\n if (params.wait) {\n const response = await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/cmd`,\n {\n method: \"POST\",\n body: JSON.stringify({\n command: params.command,\n args: params.args,\n cwd: params.cwd,\n env: params.env,\n sudo: params.sudo,\n wait: true,\n logs: params.logs || undefined,\n timeout: params.timeout,\n }),\n signal: params.signal,\n },\n );\n\n if (!response.ok) {\n await parseOrThrow(z.any(), response);\n }\n\n if (response.headers.get(\"content-type\") !== \"application/x-ndjson\") {\n throw new APIError(response, {\n message: \"Expected a stream of command data\",\n sessionId: params.sessionId,\n });\n }\n\n if (response.body === null) {\n throw new APIError(response, {\n message: \"No response body\",\n sessionId: params.sessionId,\n });\n }\n\n const jsonlinesStream = jsonlines.parse();\n pipe(response.body, jsonlinesStream, { signal: params.signal }).catch(\n (err) => {\n console.error(\"Error piping command stream:\", err);\n },\n );\n\n const iterator = jsonlinesStream[Symbol.asyncIterator]();\n const commandChunk = await iterator.next();\n if (commandChunk.done) {\n throw new StreamError(\n \"stream_ended_early\",\n \"Stream ended before command data was received\",\n params.sessionId,\n );\n }\n const { command } = CommandResponse.parse(commandChunk.value);\n\n const finished = (async () => {\n while (true) {\n const chunk = await iterator.next();\n if (chunk.done) {\n throw new StreamError(\n \"stream_ended_early\",\n \"Stream ended before command finished\",\n params.sessionId,\n );\n }\n\n if (chunk.value?.command) {\n const { command } = CommandFinishedResponse.parse(chunk.value);\n return command;\n }\n\n const parsed = LogLine.parse(chunk.value);\n if (parsed.stream === \"error\") {\n throw new StreamError(\n parsed.data.code,\n parsed.data.message,\n params.sessionId,\n );\n }\n params.onLog?.(parsed);\n }\n })();\n\n return { command, finished };\n }\n\n return parseOrThrow(\n CommandResponse,\n await this.request(`/v2/sandboxes/sessions/${params.sessionId}/cmd`, {\n method: \"POST\",\n body: JSON.stringify({\n command: params.command,\n args: params.args,\n cwd: params.cwd,\n env: params.env,\n sudo: params.sudo,\n timeout: params.timeout,\n }),\n signal: params.signal,\n }),\n );\n }\n\n async getCommand(params: {\n sessionId: string;\n cmdId: string;\n wait: true;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof CommandFinishedResponse>>>;\n async getCommand(params: {\n sessionId: string;\n cmdId: string;\n wait?: boolean;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof CommandResponse>>>;\n async getCommand(params: {\n sessionId: string;\n cmdId: string;\n wait?: boolean;\n signal?: AbortSignal;\n }) {\n return params.wait\n ? parseOrThrow(\n CommandFinishedResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.cmdId}`,\n { signal: params.signal, query: { wait: \"true\" } },\n ),\n )\n : parseOrThrow(\n CommandResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.cmdId}`,\n { signal: params.signal },\n ),\n );\n }\n\n async openInteractive(params: {\n sessionId: string;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof InteractiveSessionResponse>>> {\n return parseOrThrow(\n InteractiveSessionResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/interactive`,\n {\n method: \"POST\",\n body: JSON.stringify({}),\n signal: params.signal,\n },\n ),\n );\n }\n\n async mkDir(params: {\n sessionId: string;\n path: string;\n cwd?: string;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n EmptyResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/fs/mkdir`,\n {\n method: \"POST\",\n body: JSON.stringify({ path: params.path, cwd: params.cwd }),\n signal: params.signal,\n },\n ),\n );\n }\n\n getFileWriter(params: {\n sessionId: string;\n extractDir: string;\n signal?: AbortSignal;\n }) {\n const writer = new FileWriter();\n return {\n response: (async () => {\n return this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/fs/write`,\n {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/gzip\",\n \"x-cwd\": params.extractDir,\n },\n body: await consumeReadable(writer.readable),\n signal: params.signal,\n },\n );\n })(),\n writer,\n };\n }\n\n async listSessions(params: {\n /**\n * The ID or name of the project to which the sessions belong.\n * @example \"my-project\"\n */\n projectId: string;\n /**\n * Filter sessions by sandbox name.\n */\n name?: string;\n /**\n * Maximum number of sessions to list from a request.\n * @example 10\n */\n limit?: number;\n /**\n * Cursor for pagination.\n */\n cursor?: string;\n /**\n * Sort order for results.\n */\n sortOrder?: \"asc\" | \"desc\";\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n SessionsResponse,\n await this.request(`/v2/sandboxes/sessions`, {\n query: {\n project: params.projectId,\n name: params.name,\n limit: params.limit,\n cursor: params.cursor,\n sortOrder: params.sortOrder,\n },\n method: \"GET\",\n signal: params.signal,\n }),\n );\n }\n\n async listSnapshots(params: {\n /**\n * The ID or name of the project to which the snapshots belong.\n * @example \"my-project\"\n */\n projectId: string;\n /**\n * Filter snapshots by sandbox name.\n */\n name?: string;\n /**\n * Maximum number of snapshots to list from a request.\n * @example 10\n */\n limit?: number;\n /**\n * Cursor for pagination.\n */\n cursor?: string;\n /**\n * Sort order for results.\n */\n sortOrder?: \"asc\" | \"desc\";\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n SnapshotsResponse,\n await this.request(`/v2/sandboxes/snapshots`, {\n query: {\n project: params.projectId,\n name: params.name,\n limit: params.limit,\n cursor: params.cursor,\n sortOrder: params.sortOrder,\n },\n method: \"GET\",\n signal: params.signal,\n }),\n );\n }\n\n async getSnapshotTree(params: {\n /**\n * The ID or name of the project to which the snapshots belong.\n */\n projectId: string;\n /**\n * The snapshot ID to use as the anchor for the tree traversal.\n */\n snapshotId: string;\n /**\n * Maximum number of nodes to return.\n */\n limit?: number;\n /**\n * Sort order: \"asc\" for descendants, \"desc\" for ancestors.\n */\n sortOrder?: \"asc\" | \"desc\";\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n SnapshotTreeResponse,\n await this.request(`/v2/sandboxes/snapshots/tree`, {\n query: {\n project: params.projectId,\n snapshotId: params.snapshotId,\n limit: params.limit,\n sortOrder: params.sortOrder,\n },\n method: \"GET\",\n signal: params.signal,\n }),\n );\n }\n\n async listDrives(params: {\n projectId: string;\n limit?: number;\n cursor?: string | number;\n since?: number | string;\n until?: number | string;\n sortBy?: \"createdAt\" | \"updatedAt\" | \"name\";\n sortOrder?: \"asc\" | \"desc\";\n namePrefix?: string;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n DrivesResponse,\n await this.request(`/v2/sandboxes/drives`, {\n query: {\n projectId: params.projectId,\n limit: params.limit,\n cursor: params.cursor ?? params.until,\n since: params.since,\n sortBy: params.sortBy,\n sortOrder: params.sortOrder,\n namePrefix: params.namePrefix,\n },\n method: \"GET\",\n signal: params.signal,\n }),\n );\n }\n\n async getOrCreateDrive(params: {\n projectId: string;\n name: string;\n maxSizeBytes?: number;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n DriveResponse,\n await this.request(\n `/v2/sandboxes/drives/${encodeURIComponent(params.name)}`,\n {\n method: \"POST\",\n body: JSON.stringify({\n projectId: params.projectId,\n maxSizeBytes: params.maxSizeBytes,\n }),\n signal: params.signal,\n },\n ),\n );\n }\n\n async writeFiles(params: {\n sessionId: string;\n cwd: string;\n files: {\n path: string;\n content: string | Uint8Array;\n mode?: number;\n }[];\n extractDir: string;\n signal?: AbortSignal;\n }) {\n const { writer, response } = this.getFileWriter({\n sessionId: params.sessionId,\n extractDir: params.extractDir,\n signal: params.signal,\n });\n\n for (const file of params.files) {\n await writer.addFile({\n name: normalizePath({\n filePath: file.path,\n extractDir: params.extractDir,\n cwd: params.cwd,\n }),\n content: file.content,\n mode: file.mode,\n });\n }\n\n writer.end();\n await parseOrThrow(EmptyResponse, await response);\n }\n\n async readFile(params: {\n sessionId: string;\n path: string;\n cwd?: string;\n signal?: AbortSignal;\n }): Promise<Readable | null> {\n const response = await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/fs/read`,\n {\n method: \"POST\",\n body: JSON.stringify({ path: params.path, cwd: params.cwd }),\n signal: params.signal,\n },\n );\n\n if (response.status === 404) {\n return null;\n }\n\n // The file endpoint must return the file as an octet-stream. Any other\n // content type (e.g. application/json) indicates an error payload that\n // would otherwise be piped verbatim into the destination file.\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n if (!response.ok || !contentType.includes(\"application/octet-stream\")) {\n const text = await response.text().catch(() => \"\");\n let json: unknown;\n try {\n json = JSON.parse(text || \"{}\");\n } catch {\n json = undefined;\n }\n throw new APIError(response, {\n message: `Unexpected response reading file: status ${response.status}, content-type ${contentType || \"(none)\"}`,\n json,\n text,\n });\n }\n\n if (response.body === null) {\n return null;\n }\n\n return Readable.fromWeb(response.body);\n }\n\n async killCommand(params: {\n sessionId: string;\n commandId: string;\n signal: number;\n abortSignal?: AbortSignal;\n }) {\n return parseOrThrow(\n CommandResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.commandId}/kill`,\n {\n method: \"POST\",\n body: JSON.stringify({ signal: params.signal }),\n signal: params.abortSignal,\n },\n ),\n );\n }\n\n getLogs(params: {\n sessionId: string;\n cmdId: string;\n signal?: AbortSignal;\n }): AsyncGenerator<LogOutputLine, void, void> &\n Disposable & { close(): void } {\n const self = this;\n const disposer = new AbortController();\n const signal = !params.signal\n ? disposer.signal\n : mergeSignals(params.signal, disposer.signal);\n\n const generator = (async function* () {\n const url = `/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.cmdId}/logs`;\n const response = await self.request(url, {\n method: \"GET\",\n signal,\n });\n\n if (!response.ok) {\n await parseOrThrow(z.any(), response);\n }\n\n if (response.headers.get(\"content-type\") !== \"application/x-ndjson\") {\n throw new APIError(response, {\n message: \"Expected a stream of logs\",\n sessionId: params.sessionId,\n });\n }\n\n if (response.body === null) {\n throw new APIError(response, {\n message: \"No response body\",\n sessionId: params.sessionId,\n });\n }\n\n const jsonlinesStream = jsonlines.parse();\n pipe(response.body, jsonlinesStream, { signal }).catch((err) => {\n console.error(\"Error piping logs:\", err);\n });\n\n for await (const chunk of jsonlinesStream) {\n const parsed = LogLine.parse(chunk);\n if (parsed.stream === \"error\") {\n throw new StreamError(\n parsed.data.code,\n parsed.data.message,\n params.sessionId,\n );\n }\n yield parsed;\n }\n })();\n\n return Object.assign(generator, {\n [Symbol.dispose]() {\n disposer.abort(\"Disposed\");\n },\n close: () => disposer.abort(\"Disposed\"),\n });\n }\n\n async stopSession(params: {\n sessionId: string;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof StopSessionResponse>>> {\n const url = `/v2/sandboxes/sessions/${params.sessionId}/stop`;\n return parseOrThrow(\n StopSessionResponse,\n await this.request(url, { method: \"POST\", signal: params.signal }),\n );\n }\n\n async updateNetworkPolicy(params: {\n sessionId: string;\n networkPolicy: NetworkPolicy;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof SessionResponse>>> {\n const url = `/v2/sandboxes/sessions/${params.sessionId}/network-policy`;\n return parseOrThrow(\n SessionResponse,\n await this.request(url, {\n method: \"POST\",\n body: JSON.stringify(toAPINetworkPolicy(params.networkPolicy)),\n signal: params.signal,\n }),\n );\n }\n\n async extendTimeout(params: {\n sessionId: string;\n duration: number;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof SessionResponse>>> {\n const url = `/v2/sandboxes/sessions/${params.sessionId}/extend-timeout`;\n return parseOrThrow(\n SessionResponse,\n await this.request(url, {\n method: \"POST\",\n body: JSON.stringify({ duration: params.duration }),\n signal: params.signal,\n }),\n );\n }\n\n async createSnapshot(params: {\n sessionId: string;\n expiration?: number;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof CreateSnapshotResponse>>> {\n const url = `/v2/sandboxes/sessions/${params.sessionId}/snapshot`;\n const body =\n params.expiration === undefined\n ? undefined\n : JSON.stringify({ expiration: params.expiration });\n return parseOrThrow(\n CreateSnapshotResponse,\n await this.request(url, {\n method: \"POST\",\n body,\n signal: params.signal,\n }),\n );\n }\n\n async deleteSnapshot(params: {\n snapshotId: string;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof SnapshotResponse>>> {\n const url = `/v2/sandboxes/snapshots/${params.snapshotId}`;\n return parseOrThrow(\n SnapshotResponse,\n await this.request(url, { method: \"DELETE\", signal: params.signal }),\n );\n }\n\n async getSnapshot(params: {\n snapshotId: string;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof SnapshotResponse>>> {\n const url = `/v2/sandboxes/snapshots/${params.snapshotId}`;\n return parseOrThrow(\n SnapshotResponse,\n await this.request(url, { signal: params.signal }),\n );\n }\n\n async getSandbox(\n params: WithPrivate<{\n name: string;\n projectId: string;\n resume?: boolean;\n signal?: AbortSignal;\n }>,\n ) {\n const privateParams = getPrivateParams(params);\n const query: Record<string, string | undefined> = {\n projectId: params.projectId,\n ...privateParams,\n };\n if (params.resume !== undefined) {\n query.resume = String(params.resume);\n }\n return parseOrThrow(\n SandboxAndSessionResponse,\n await this.request(`/v2/sandboxes/${encodeURIComponent(params.name)}`, {\n query,\n signal: params.signal,\n }),\n );\n }\n\n async listSandboxes(params: {\n projectId: string;\n limit?: number;\n sortBy?: \"createdAt\" | \"name\" | \"statusUpdatedAt\";\n sortOrder?: \"asc\" | \"desc\";\n namePrefix?: string;\n cursor?: string;\n tags?: Record<string, string>;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n SandboxesPaginationResponse,\n await this.request(`/v2/sandboxes`, {\n query: {\n project: params.projectId,\n limit: params.limit,\n sortBy: params.sortBy,\n sortOrder: params.sortOrder,\n namePrefix: params.namePrefix,\n cursor: params.cursor,\n tags: toTagsFilter(params.tags),\n },\n method: \"GET\",\n signal: params.signal,\n }),\n );\n }\n\n async deleteDrive(params: {\n projectId: string;\n name: string;\n signal?: AbortSignal;\n }) {\n const url = `/v2/sandboxes/drives/${encodeURIComponent(params.name)}`;\n return parseOrThrow(\n DriveResponse,\n await this.request(url, {\n method: \"DELETE\",\n query: {\n projectId: params.projectId,\n },\n signal: params.signal,\n }),\n );\n }\n\n async updateSandbox(params: {\n name: string;\n projectId: string;\n persistent?: boolean;\n resources?: { vcpus?: number; memory?: number };\n timeout?: number;\n networkPolicy?: NetworkPolicy;\n tags?: Record<string, string>;\n ports?: number[];\n snapshotExpiration?: number;\n keepLastSnapshots?: {\n count: number;\n expiration?: number;\n deleteEvicted?: boolean;\n } | null;\n currentSnapshotId?: string;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n UpdateSandboxResponse,\n await this.request(`/v2/sandboxes/${encodeURIComponent(params.name)}`, {\n method: \"PATCH\",\n query: {\n projectId: params.projectId,\n },\n body: JSON.stringify({\n persistent: params.persistent,\n resources: params.resources,\n timeout: params.timeout,\n networkPolicy: params.networkPolicy\n ? toAPINetworkPolicy(params.networkPolicy)\n : undefined,\n tags: params.tags,\n ports: params.ports,\n snapshotExpiration: params.snapshotExpiration,\n keepLastSnapshots: params.keepLastSnapshots,\n currentSnapshotId: params.currentSnapshotId,\n }),\n signal: params.signal,\n }),\n );\n }\n\n async deleteSandbox(params: {\n name: string;\n projectId: string;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n UpdateSandboxResponse,\n await this.request(`/v2/sandboxes/${encodeURIComponent(params.name)}`, {\n method: \"DELETE\",\n query: {\n projectId: params.projectId,\n },\n signal: params.signal,\n }),\n );\n }\n}\n\nasync function pipe(\n readable: ReadableStream<Uint8Array>,\n output: NodeJS.WritableStream,\n options?: { signal?: AbortSignal },\n) {\n const reader = readable.getReader();\n let aborted = false;\n\n const signal = options?.signal;\n const onAbort = () => {\n aborted = true;\n const reason =\n signal?.reason ??\n new DOMException(\"The operation was aborted.\", \"AbortError\");\n void reader.cancel(reason).catch(() => {\n // ignore cancel errors when aborting\n });\n\n if (\"destroy\" in output && typeof output.destroy === \"function\") {\n output.destroy(reason as Error);\n return;\n }\n\n output.emit(\"error\", reason);\n output.end();\n };\n\n if (signal) {\n if (signal.aborted) {\n onAbort();\n } else {\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n }\n\n try {\n while (true) {\n const read = await reader.read();\n if (read.value) {\n output.write(Buffer.from(read.value));\n }\n if (read.done) {\n break;\n }\n }\n } catch (err) {\n if (!aborted) {\n output.emit(\"error\", err);\n }\n } finally {\n signal?.removeEventListener(\"abort\", onAbort);\n if (!aborted) {\n output.end();\n }\n }\n}\n\nfunction mergeSignals(...signals: [AbortSignal, ...AbortSignal[]]) {\n const controller = new AbortController();\n const onAbort = () => {\n controller.abort();\n for (const signal of signals) {\n signal.removeEventListener(\"abort\", onAbort);\n }\n };\n for (const signal of signals) {\n if (signal.aborted) {\n controller.abort();\n break;\n }\n signal.addEventListener(\"abort\", onAbort);\n }\n return controller.signal;\n}\n\nfunction toTagsFilter(\n tags: Record<string, string> | undefined,\n): string[] | undefined {\n if (tags === undefined) return undefined;\n const entries = Object.entries(tags);\n if (entries.length === 0) return undefined;\n return entries.map(([key, value]) => `${key}:${value}`);\n}\n"],"mappings":"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"} | ||
| {"version":3,"file":"api-client.js","names":["command","json: unknown","query: Record<string, string | undefined>"],"sources":["../../src/api-client/api-client.ts"],"sourcesContent":["import {\n BaseClient,\n parseOrThrow,\n type Parsed,\n type RequestParams,\n} from \"./base-client.js\";\nimport {\n type CommandFinishedData,\n SessionAndRoutesResponse,\n SessionResponse,\n InteractiveSessionResponse,\n StopSessionResponse,\n SessionsResponse,\n CommandResponse,\n CommandFinishedResponse,\n EmptyResponse,\n LogLine,\n type LogOutputLine,\n SnapshotsResponse,\n SnapshotTreeResponse,\n SnapshotResponse,\n CreateSnapshotResponse,\n SandboxAndSessionResponse,\n SandboxesPaginationResponse,\n UpdateSandboxResponse,\n DrivesResponse,\n DriveResponse,\n type CommandData,\n} from \"./validators.js\";\nimport { APIError, StreamError } from \"./api-error.js\";\nimport { FileWriter } from \"./file-writer.js\";\nimport { VERSION } from \"../version.js\";\nimport { consumeReadable } from \"../utils/consume-readable.js\";\nimport { z } from \"zod\";\nimport jsonlines from \"jsonlines\";\nimport os from \"os\";\nimport { Readable } from \"stream\";\nimport { normalizePath } from \"../utils/normalizePath.js\";\nimport { getVercelOidcToken } from \"@vercel/oidc\";\nimport { NetworkPolicy } from \"../network-policy.js\";\nimport { toAPINetworkPolicy } from \"../utils/network-policy.js\";\nimport { getPrivateParams, WithPrivate } from \"../utils/types.js\";\nimport type { RUNTIMES, SandboxRegion } from \"../constants.js\";\nimport type { BaseCreateSandboxParams } from \"../sandbox.js\";\n\ninterface Claims {\n owner_id: string;\n project_id?: string;\n}\n\nfunction decodeUnverifiedToken(token: string): Claims | null {\n if (token.split(\".\").length !== 3) {\n return null;\n }\n try {\n const payload = JSON.parse(\n Buffer.from(token.split(\".\")[1], \"base64url\").toString(\"utf8\"),\n );\n if (payload.owner_id) {\n return { owner_id: payload.owner_id, project_id: payload.project_id };\n }\n return null;\n } catch {\n return null;\n }\n}\n\nexport interface WithFetchOptions {\n fetch?: typeof globalThis.fetch;\n}\n\nexport class APIClient extends BaseClient {\n private teamId: string;\n private projectId: string | undefined;\n private isJwtToken: boolean;\n\n constructor(params: {\n baseUrl?: string;\n teamId: string;\n token: string;\n fetch?: typeof globalThis.fetch;\n }) {\n super({\n baseUrl: params.baseUrl ?? \"https://vercel.com/api\",\n token: params.token,\n debug: false,\n fetch: params.fetch,\n });\n\n this.teamId = params.teamId;\n this.isJwtToken = false;\n\n const claims = decodeUnverifiedToken(params.token);\n if (claims) {\n this.isJwtToken = true;\n this.projectId = claims.project_id;\n this.teamId = claims.owner_id;\n }\n }\n\n private async ensureValidToken(): Promise<void> {\n if (!this.isJwtToken) {\n return;\n }\n\n try {\n // Use getVercelOidcToken to refresh the token with team/project scope\n const freshToken = await getVercelOidcToken({\n expirationBufferMs: 5 * 60 * 1000, // 5 minutes\n team: this.teamId,\n project: this.projectId,\n });\n\n // Update token if it changed\n if (freshToken !== this.token) {\n this.token = freshToken;\n\n const claims = decodeUnverifiedToken(freshToken);\n if (claims) {\n this.teamId = claims.owner_id;\n }\n }\n } catch {\n // Ignore refresh errors and continue with current token\n }\n }\n\n protected async request(path: string, params?: RequestParams) {\n await this.ensureValidToken();\n\n return super.request(path, {\n ...params,\n query: { teamId: this.teamId, ...params?.query },\n headers: {\n \"content-type\": \"application/json\",\n \"user-agent\": `vercel/sandbox/${VERSION} (Node.js/${process.version}; ${os.platform()}/${os.arch()})`,\n ...params?.headers,\n },\n });\n }\n\n async getSession(\n params: WithPrivate<{ sessionId: string; signal?: AbortSignal }>,\n ) {\n const privateParams = getPrivateParams(params);\n let querystring = new URLSearchParams(privateParams).toString();\n querystring = querystring ? `?${querystring}` : \"\";\n return parseOrThrow(\n SessionAndRoutesResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}${querystring}`,\n {\n signal: params.signal,\n },\n ),\n );\n }\n\n async createSandbox(\n params: WithPrivate<{\n name?: string;\n ports?: number[];\n projectId: string;\n source?:\n | {\n type: \"git\";\n url: string;\n depth?: number;\n revision?: string;\n username?: string;\n password?: string;\n }\n | { type: \"tarball\"; url: string }\n | { type: \"snapshot\"; snapshotId: string };\n timeout?: number;\n resources?: { vcpus: number };\n persistent?: boolean;\n runtime?: RUNTIMES | (string & {});\n image?: string;\n networkPolicy?: NetworkPolicy;\n env?: Record<string, string>;\n tags?: Record<string, string>;\n snapshotExpiration?: number;\n keepLastSnapshots?: {\n count: number;\n expiration?: number;\n deleteEvicted?: boolean;\n };\n mounts?: BaseCreateSandboxParams[\"mounts\"];\n region?: SandboxRegion;\n failoverRegions?: SandboxRegion[];\n signal?: AbortSignal;\n }>,\n ) {\n const privateParams = getPrivateParams(params);\n const endpoint =\n params.runtime === undefined ? \"/v3/sandboxes\" : \"/v2/sandboxes\";\n return parseOrThrow(\n SandboxAndSessionResponse,\n await this.request(endpoint, {\n method: \"POST\",\n body: JSON.stringify({\n projectId: params.projectId,\n ports: params.ports,\n source: params.source,\n timeout: params.timeout,\n resources: params.resources,\n runtime: params.runtime,\n image: params.image,\n name: params.name,\n persistent: params.persistent,\n networkPolicy: params.networkPolicy\n ? toAPINetworkPolicy(params.networkPolicy)\n : undefined,\n env: params.env,\n tags: params.tags,\n snapshotExpiration: params.snapshotExpiration,\n keepLastSnapshots: params.keepLastSnapshots,\n mounts: params.mounts,\n region: params.region,\n failoverRegions: params.failoverRegions,\n ...privateParams,\n }),\n signal: params.signal,\n }),\n );\n }\n\n async forkSandbox(\n params: WithPrivate<{\n sourceSandbox: string;\n projectId: string;\n name?: string;\n ports?: number[];\n timeout?: number;\n resources?: { vcpus: number };\n persistent?: boolean;\n image?: string;\n networkPolicy?: NetworkPolicy;\n env?: Record<string, string>;\n tags?: Record<string, string>;\n snapshotExpiration?: number;\n keepLastSnapshots?: {\n count: number;\n expiration?: number;\n deleteEvicted?: boolean;\n };\n region?: SandboxRegion;\n failoverRegions?: SandboxRegion[];\n signal?: AbortSignal;\n }>,\n ) {\n const privateParams = getPrivateParams(params);\n return parseOrThrow(\n SandboxAndSessionResponse,\n await this.request(\n `/v2/sandboxes/${encodeURIComponent(params.sourceSandbox)}/fork`,\n {\n method: \"POST\",\n query: { projectId: params.projectId },\n body: JSON.stringify({\n name: params.name,\n ports: params.ports,\n timeout: params.timeout,\n resources: params.resources,\n image: params.image,\n persistent: params.persistent,\n networkPolicy: params.networkPolicy\n ? toAPINetworkPolicy(params.networkPolicy)\n : undefined,\n env: params.env,\n tags: params.tags,\n snapshotExpiration: params.snapshotExpiration,\n keepLastSnapshots: params.keepLastSnapshots,\n region: params.region,\n failoverRegions: params.failoverRegions,\n ...privateParams,\n }),\n signal: params.signal,\n },\n ),\n );\n }\n\n async runCommand(params: {\n sessionId: string;\n cwd?: string;\n command: string;\n args: string[];\n env: Record<string, string>;\n sudo: boolean;\n wait: true;\n logs?: boolean;\n onLog?: (log: LogOutputLine) => void;\n timeout?: number;\n signal?: AbortSignal;\n }): Promise<{\n command: CommandData;\n finished: Promise<CommandFinishedData>;\n }>;\n async runCommand(params: {\n sessionId: string;\n cwd?: string;\n command: string;\n args: string[];\n env: Record<string, string>;\n sudo: boolean;\n wait?: false;\n timeout?: number;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof CommandResponse>>>;\n async runCommand(params: {\n sessionId: string;\n cwd?: string;\n command: string;\n args: string[];\n env: Record<string, string>;\n sudo: boolean;\n wait?: boolean;\n logs?: boolean;\n onLog?: (log: LogOutputLine) => void;\n timeout?: number;\n signal?: AbortSignal;\n }): Promise<\n | {\n command: CommandData;\n finished: Promise<CommandFinishedData>;\n }\n | Parsed<z.infer<typeof CommandResponse>>\n > {\n if (params.wait) {\n const response = await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/cmd`,\n {\n method: \"POST\",\n body: JSON.stringify({\n command: params.command,\n args: params.args,\n cwd: params.cwd,\n env: params.env,\n sudo: params.sudo,\n wait: true,\n logs: params.logs || undefined,\n timeout: params.timeout,\n }),\n signal: params.signal,\n },\n );\n\n if (!response.ok) {\n await parseOrThrow(z.any(), response);\n }\n\n if (response.headers.get(\"content-type\") !== \"application/x-ndjson\") {\n throw new APIError(response, {\n message: \"Expected a stream of command data\",\n sessionId: params.sessionId,\n });\n }\n\n if (response.body === null) {\n throw new APIError(response, {\n message: \"No response body\",\n sessionId: params.sessionId,\n });\n }\n\n const jsonlinesStream = jsonlines.parse();\n pipe(response.body, jsonlinesStream, { signal: params.signal }).catch(\n (err) => {\n console.error(\"Error piping command stream:\", err);\n },\n );\n\n const iterator = jsonlinesStream[Symbol.asyncIterator]();\n const commandChunk = await iterator.next();\n if (commandChunk.done) {\n throw new StreamError(\n \"stream_ended_early\",\n \"Stream ended before command data was received\",\n params.sessionId,\n );\n }\n const { command } = CommandResponse.parse(commandChunk.value);\n\n const finished = (async () => {\n while (true) {\n const chunk = await iterator.next();\n if (chunk.done) {\n throw new StreamError(\n \"stream_ended_early\",\n \"Stream ended before command finished\",\n params.sessionId,\n );\n }\n\n if (chunk.value?.command) {\n const { command } = CommandFinishedResponse.parse(chunk.value);\n return command;\n }\n\n const parsed = LogLine.parse(chunk.value);\n if (parsed.stream === \"error\") {\n throw new StreamError(\n parsed.data.code,\n parsed.data.message,\n params.sessionId,\n );\n }\n params.onLog?.(parsed);\n }\n })();\n\n return { command, finished };\n }\n\n return parseOrThrow(\n CommandResponse,\n await this.request(`/v2/sandboxes/sessions/${params.sessionId}/cmd`, {\n method: \"POST\",\n body: JSON.stringify({\n command: params.command,\n args: params.args,\n cwd: params.cwd,\n env: params.env,\n sudo: params.sudo,\n timeout: params.timeout,\n }),\n signal: params.signal,\n }),\n );\n }\n\n async getCommand(params: {\n sessionId: string;\n cmdId: string;\n wait: true;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof CommandFinishedResponse>>>;\n async getCommand(params: {\n sessionId: string;\n cmdId: string;\n wait?: boolean;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof CommandResponse>>>;\n async getCommand(params: {\n sessionId: string;\n cmdId: string;\n wait?: boolean;\n signal?: AbortSignal;\n }) {\n return params.wait\n ? parseOrThrow(\n CommandFinishedResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.cmdId}`,\n { signal: params.signal, query: { wait: \"true\" } },\n ),\n )\n : parseOrThrow(\n CommandResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.cmdId}`,\n { signal: params.signal },\n ),\n );\n }\n\n async openInteractive(params: {\n sessionId: string;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof InteractiveSessionResponse>>> {\n return parseOrThrow(\n InteractiveSessionResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/interactive`,\n {\n method: \"POST\",\n body: JSON.stringify({}),\n signal: params.signal,\n },\n ),\n );\n }\n\n async mkDir(params: {\n sessionId: string;\n path: string;\n cwd?: string;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n EmptyResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/fs/mkdir`,\n {\n method: \"POST\",\n body: JSON.stringify({ path: params.path, cwd: params.cwd }),\n signal: params.signal,\n },\n ),\n );\n }\n\n getFileWriter(params: {\n sessionId: string;\n extractDir: string;\n signal?: AbortSignal;\n }) {\n const writer = new FileWriter();\n return {\n response: (async () => {\n return this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/fs/write`,\n {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/gzip\",\n \"x-cwd\": params.extractDir,\n },\n body: await consumeReadable(writer.readable),\n signal: params.signal,\n },\n );\n })(),\n writer,\n };\n }\n\n async listSessions(params: {\n /**\n * The ID or name of the project to which the sessions belong.\n * @example \"my-project\"\n */\n projectId: string;\n /**\n * Filter sessions by sandbox name.\n */\n name?: string;\n /**\n * Maximum number of sessions to list from a request.\n * @example 10\n */\n limit?: number;\n /**\n * Cursor for pagination.\n */\n cursor?: string;\n /**\n * Sort order for results.\n */\n sortOrder?: \"asc\" | \"desc\";\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n SessionsResponse,\n await this.request(`/v2/sandboxes/sessions`, {\n query: {\n project: params.projectId,\n name: params.name,\n limit: params.limit,\n cursor: params.cursor,\n sortOrder: params.sortOrder,\n },\n method: \"GET\",\n signal: params.signal,\n }),\n );\n }\n\n async listSnapshots(params: {\n /**\n * The ID or name of the project to which the snapshots belong.\n * @example \"my-project\"\n */\n projectId: string;\n /**\n * Filter snapshots by sandbox name.\n */\n name?: string;\n /**\n * Maximum number of snapshots to list from a request.\n * @example 10\n */\n limit?: number;\n /**\n * Cursor for pagination.\n */\n cursor?: string;\n /**\n * Sort order for results.\n */\n sortOrder?: \"asc\" | \"desc\";\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n SnapshotsResponse,\n await this.request(`/v2/sandboxes/snapshots`, {\n query: {\n project: params.projectId,\n name: params.name,\n limit: params.limit,\n cursor: params.cursor,\n sortOrder: params.sortOrder,\n },\n method: \"GET\",\n signal: params.signal,\n }),\n );\n }\n\n async getSnapshotTree(params: {\n /**\n * The ID or name of the project to which the snapshots belong.\n */\n projectId: string;\n /**\n * The snapshot ID to use as the anchor for the tree traversal.\n */\n snapshotId: string;\n /**\n * Maximum number of nodes to return.\n */\n limit?: number;\n /**\n * Sort order: \"asc\" for descendants, \"desc\" for ancestors.\n */\n sortOrder?: \"asc\" | \"desc\";\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n SnapshotTreeResponse,\n await this.request(`/v2/sandboxes/snapshots/tree`, {\n query: {\n project: params.projectId,\n snapshotId: params.snapshotId,\n limit: params.limit,\n sortOrder: params.sortOrder,\n },\n method: \"GET\",\n signal: params.signal,\n }),\n );\n }\n\n async listDrives(params: {\n projectId: string;\n limit?: number;\n cursor?: string | number;\n since?: number | string;\n until?: number | string;\n sortBy?: \"createdAt\" | \"updatedAt\" | \"name\";\n sortOrder?: \"asc\" | \"desc\";\n namePrefix?: string;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n DrivesResponse,\n await this.request(`/v2/sandboxes/drives`, {\n query: {\n projectId: params.projectId,\n limit: params.limit,\n cursor: params.cursor ?? params.until,\n since: params.since,\n sortBy: params.sortBy,\n sortOrder: params.sortOrder,\n namePrefix: params.namePrefix,\n },\n method: \"GET\",\n signal: params.signal,\n }),\n );\n }\n\n async getOrCreateDrive(params: {\n projectId: string;\n name: string;\n region?: string;\n maxSizeBytes?: number;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n DriveResponse,\n await this.request(\n `/v2/sandboxes/drives/${encodeURIComponent(params.name)}`,\n {\n method: \"POST\",\n body: JSON.stringify({\n projectId: params.projectId,\n region: params.region,\n maxSizeBytes: params.maxSizeBytes,\n }),\n signal: params.signal,\n },\n ),\n );\n }\n\n async writeFiles(params: {\n sessionId: string;\n cwd: string;\n files: {\n path: string;\n content: string | Uint8Array;\n mode?: number;\n }[];\n extractDir: string;\n signal?: AbortSignal;\n }) {\n const { writer, response } = this.getFileWriter({\n sessionId: params.sessionId,\n extractDir: params.extractDir,\n signal: params.signal,\n });\n\n for (const file of params.files) {\n await writer.addFile({\n name: normalizePath({\n filePath: file.path,\n extractDir: params.extractDir,\n cwd: params.cwd,\n }),\n content: file.content,\n mode: file.mode,\n });\n }\n\n writer.end();\n await parseOrThrow(EmptyResponse, await response);\n }\n\n async readFile(params: {\n sessionId: string;\n path: string;\n cwd?: string;\n signal?: AbortSignal;\n }): Promise<Readable | null> {\n const response = await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/fs/read`,\n {\n method: \"POST\",\n body: JSON.stringify({ path: params.path, cwd: params.cwd }),\n signal: params.signal,\n },\n );\n\n if (response.status === 404) {\n return null;\n }\n\n // The file endpoint must return the file as an octet-stream. Any other\n // content type (e.g. application/json) indicates an error payload that\n // would otherwise be piped verbatim into the destination file.\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n if (!response.ok || !contentType.includes(\"application/octet-stream\")) {\n const text = await response.text().catch(() => \"\");\n let json: unknown;\n try {\n json = JSON.parse(text || \"{}\");\n } catch {\n json = undefined;\n }\n throw new APIError(response, {\n message: `Unexpected response reading file: status ${response.status}, content-type ${contentType || \"(none)\"}`,\n json,\n text,\n });\n }\n\n if (response.body === null) {\n return null;\n }\n\n return Readable.fromWeb(response.body);\n }\n\n async killCommand(params: {\n sessionId: string;\n commandId: string;\n signal: number;\n abortSignal?: AbortSignal;\n }) {\n return parseOrThrow(\n CommandResponse,\n await this.request(\n `/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.commandId}/kill`,\n {\n method: \"POST\",\n body: JSON.stringify({ signal: params.signal }),\n signal: params.abortSignal,\n },\n ),\n );\n }\n\n getLogs(params: {\n sessionId: string;\n cmdId: string;\n signal?: AbortSignal;\n }): AsyncGenerator<LogOutputLine, void, void> &\n Disposable & { close(): void } {\n const self = this;\n const disposer = new AbortController();\n const signal = !params.signal\n ? disposer.signal\n : mergeSignals(params.signal, disposer.signal);\n\n const generator = (async function* () {\n const url = `/v2/sandboxes/sessions/${params.sessionId}/cmd/${params.cmdId}/logs`;\n const response = await self.request(url, {\n method: \"GET\",\n signal,\n });\n\n if (!response.ok) {\n await parseOrThrow(z.any(), response);\n }\n\n if (response.headers.get(\"content-type\") !== \"application/x-ndjson\") {\n throw new APIError(response, {\n message: \"Expected a stream of logs\",\n sessionId: params.sessionId,\n });\n }\n\n if (response.body === null) {\n throw new APIError(response, {\n message: \"No response body\",\n sessionId: params.sessionId,\n });\n }\n\n const jsonlinesStream = jsonlines.parse();\n pipe(response.body, jsonlinesStream, { signal }).catch((err) => {\n console.error(\"Error piping logs:\", err);\n });\n\n for await (const chunk of jsonlinesStream) {\n const parsed = LogLine.parse(chunk);\n if (parsed.stream === \"error\") {\n throw new StreamError(\n parsed.data.code,\n parsed.data.message,\n params.sessionId,\n );\n }\n yield parsed;\n }\n })();\n\n return Object.assign(generator, {\n [Symbol.dispose]() {\n disposer.abort(\"Disposed\");\n },\n close: () => disposer.abort(\"Disposed\"),\n });\n }\n\n async stopSession(params: {\n sessionId: string;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof StopSessionResponse>>> {\n const url = `/v2/sandboxes/sessions/${params.sessionId}/stop`;\n return parseOrThrow(\n StopSessionResponse,\n await this.request(url, { method: \"POST\", signal: params.signal }),\n );\n }\n\n async updateNetworkPolicy(params: {\n sessionId: string;\n networkPolicy: NetworkPolicy;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof SessionResponse>>> {\n const url = `/v2/sandboxes/sessions/${params.sessionId}/network-policy`;\n return parseOrThrow(\n SessionResponse,\n await this.request(url, {\n method: \"POST\",\n body: JSON.stringify(toAPINetworkPolicy(params.networkPolicy)),\n signal: params.signal,\n }),\n );\n }\n\n async extendTimeout(params: {\n sessionId: string;\n duration: number;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof SessionResponse>>> {\n const url = `/v2/sandboxes/sessions/${params.sessionId}/extend-timeout`;\n return parseOrThrow(\n SessionResponse,\n await this.request(url, {\n method: \"POST\",\n body: JSON.stringify({ duration: params.duration }),\n signal: params.signal,\n }),\n );\n }\n\n async createSnapshot(params: {\n sessionId: string;\n expiration?: number;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof CreateSnapshotResponse>>> {\n const url = `/v2/sandboxes/sessions/${params.sessionId}/snapshot`;\n const body =\n params.expiration === undefined\n ? undefined\n : JSON.stringify({ expiration: params.expiration });\n return parseOrThrow(\n CreateSnapshotResponse,\n await this.request(url, {\n method: \"POST\",\n body,\n signal: params.signal,\n }),\n );\n }\n\n async deleteSnapshot(params: {\n snapshotId: string;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof SnapshotResponse>>> {\n const url = `/v2/sandboxes/snapshots/${params.snapshotId}`;\n return parseOrThrow(\n SnapshotResponse,\n await this.request(url, { method: \"DELETE\", signal: params.signal }),\n );\n }\n\n async getSnapshot(params: {\n snapshotId: string;\n signal?: AbortSignal;\n }): Promise<Parsed<z.infer<typeof SnapshotResponse>>> {\n const url = `/v2/sandboxes/snapshots/${params.snapshotId}`;\n return parseOrThrow(\n SnapshotResponse,\n await this.request(url, { signal: params.signal }),\n );\n }\n\n async getSandbox(\n params: WithPrivate<{\n name: string;\n projectId: string;\n resume?: boolean;\n signal?: AbortSignal;\n }>,\n ) {\n const privateParams = getPrivateParams(params);\n const query: Record<string, string | undefined> = {\n projectId: params.projectId,\n ...privateParams,\n };\n if (params.resume !== undefined) {\n query.resume = String(params.resume);\n }\n return parseOrThrow(\n SandboxAndSessionResponse,\n await this.request(`/v2/sandboxes/${encodeURIComponent(params.name)}`, {\n query,\n signal: params.signal,\n }),\n );\n }\n\n async listSandboxes(params: {\n projectId: string;\n limit?: number;\n sortBy?: \"createdAt\" | \"name\" | \"statusUpdatedAt\";\n sortOrder?: \"asc\" | \"desc\";\n namePrefix?: string;\n cursor?: string;\n tags?: Record<string, string>;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n SandboxesPaginationResponse,\n await this.request(`/v2/sandboxes`, {\n query: {\n project: params.projectId,\n limit: params.limit,\n sortBy: params.sortBy,\n sortOrder: params.sortOrder,\n namePrefix: params.namePrefix,\n cursor: params.cursor,\n tags: toTagsFilter(params.tags),\n },\n method: \"GET\",\n signal: params.signal,\n }),\n );\n }\n\n async deleteDrive(params: {\n projectId: string;\n name: string;\n signal?: AbortSignal;\n }) {\n const url = `/v2/sandboxes/drives/${encodeURIComponent(params.name)}`;\n return parseOrThrow(\n DriveResponse,\n await this.request(url, {\n method: \"DELETE\",\n query: {\n projectId: params.projectId,\n },\n signal: params.signal,\n }),\n );\n }\n\n async updateSandbox(params: {\n name: string;\n projectId: string;\n persistent?: boolean;\n resources?: { vcpus?: number; memory?: number };\n timeout?: number;\n networkPolicy?: NetworkPolicy;\n tags?: Record<string, string>;\n ports?: number[];\n snapshotExpiration?: number;\n keepLastSnapshots?: {\n count: number;\n expiration?: number;\n deleteEvicted?: boolean;\n } | null;\n currentSnapshotId?: string;\n region?: SandboxRegion;\n failoverRegions?: SandboxRegion[];\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n UpdateSandboxResponse,\n await this.request(`/v2/sandboxes/${encodeURIComponent(params.name)}`, {\n method: \"PATCH\",\n query: {\n projectId: params.projectId,\n },\n body: JSON.stringify({\n persistent: params.persistent,\n resources: params.resources,\n timeout: params.timeout,\n networkPolicy: params.networkPolicy\n ? toAPINetworkPolicy(params.networkPolicy)\n : undefined,\n tags: params.tags,\n ports: params.ports,\n snapshotExpiration: params.snapshotExpiration,\n keepLastSnapshots: params.keepLastSnapshots,\n currentSnapshotId: params.currentSnapshotId,\n region: params.region,\n failoverRegions: params.failoverRegions,\n }),\n signal: params.signal,\n }),\n );\n }\n\n async deleteSandbox(params: {\n name: string;\n projectId: string;\n signal?: AbortSignal;\n }) {\n return parseOrThrow(\n UpdateSandboxResponse,\n await this.request(`/v2/sandboxes/${encodeURIComponent(params.name)}`, {\n method: \"DELETE\",\n query: {\n projectId: params.projectId,\n },\n signal: params.signal,\n }),\n );\n }\n}\n\nasync function pipe(\n readable: ReadableStream<Uint8Array>,\n output: NodeJS.WritableStream,\n options?: { signal?: AbortSignal },\n) {\n const reader = readable.getReader();\n let aborted = false;\n\n const signal = options?.signal;\n const onAbort = () => {\n aborted = true;\n const reason =\n signal?.reason ??\n new DOMException(\"The operation was aborted.\", \"AbortError\");\n void reader.cancel(reason).catch(() => {\n // ignore cancel errors when aborting\n });\n\n if (\"destroy\" in output && typeof output.destroy === \"function\") {\n output.destroy(reason as Error);\n return;\n }\n\n output.emit(\"error\", reason);\n output.end();\n };\n\n if (signal) {\n if (signal.aborted) {\n onAbort();\n } else {\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n }\n\n try {\n while (true) {\n const read = await reader.read();\n if (read.value) {\n output.write(Buffer.from(read.value));\n }\n if (read.done) {\n break;\n }\n }\n } catch (err) {\n if (!aborted) {\n output.emit(\"error\", err);\n }\n } finally {\n signal?.removeEventListener(\"abort\", onAbort);\n if (!aborted) {\n output.end();\n }\n }\n}\n\nfunction mergeSignals(...signals: [AbortSignal, ...AbortSignal[]]) {\n const controller = new AbortController();\n const onAbort = () => {\n controller.abort();\n for (const signal of signals) {\n signal.removeEventListener(\"abort\", onAbort);\n }\n };\n for (const signal of signals) {\n if (signal.aborted) {\n controller.abort();\n break;\n }\n signal.addEventListener(\"abort\", onAbort);\n }\n return controller.signal;\n}\n\nfunction toTagsFilter(\n tags: Record<string, string> | undefined,\n): string[] | undefined {\n if (tags === undefined) return undefined;\n const entries = Object.entries(tags);\n if (entries.length === 0) return undefined;\n return entries.map(([key, value]) => `${key}:${value}`);\n}\n"],"mappings":"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"} |
@@ -5,2 +5,3 @@ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs'); | ||
| const require_with_retry = require('./with-retry.cjs'); | ||
| let zod = require("zod"); | ||
| let undici = require("undici"); | ||
@@ -68,2 +69,16 @@ | ||
| /** | ||
| * The error body shape returned by the Sandbox API. Mirrors the shape the | ||
| * CLI's formatApiError parses. | ||
| */ | ||
| const ErrorResponseBody = zod.z.object({ error: zod.z.object({ message: zod.z.string() }) }); | ||
| /** | ||
| * Extract the server-provided error message from an error response body so | ||
| * it can be surfaced in APIError.message. Returns undefined for any other | ||
| * body shape. | ||
| */ | ||
| function extractServerMessage(json) { | ||
| const parsed = ErrorResponseBody.safeParse(json); | ||
| return parsed.success ? parsed.data.error.message : void 0; | ||
| } | ||
| /** | ||
| * Allows to read the response text and parse it as JSON casting to the given | ||
@@ -98,9 +113,12 @@ * type. If the response is not ok or cannot be parsed it will return error. | ||
| } | ||
| if (!response.ok) return new require_api_error.APIError(response, { | ||
| message: `Status code ${response.status} is not ok`, | ||
| json, | ||
| text, | ||
| sessionId, | ||
| sandboxName | ||
| }); | ||
| if (!response.ok) { | ||
| const serverMessage = extractServerMessage(json); | ||
| return new require_api_error.APIError(response, { | ||
| message: serverMessage ? `Status code ${response.status} is not ok: ${serverMessage}` : `Status code ${response.status} is not ok`, | ||
| json, | ||
| text, | ||
| sessionId, | ||
| sandboxName | ||
| }); | ||
| } | ||
| const validated = validator.safeParse(json); | ||
@@ -107,0 +125,0 @@ if (!validated.success) return new require_api_error.APIError(response, { |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"base-client.cjs","names":["Agent","withRetry","value","sandboxName: string | undefined","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 sessionId from a sandbox API URL.\n */\nfunction extractSessionId(url: string): string | undefined {\n const match = url.match(/\\/v2\\/sandboxes\\/sessions\\/([^/?]+)/);\n return match?.[1];\n}\n\n/**\n * Extract sandbox name from a sandbox API url.\n * Excludes known sub-paths like /sessions/ and /snapshots/.\n */\nfunction extractSandboxName(url: string): string | undefined {\n const match = url.match(/\\/v2\\/sandboxes\\/(?!sessions(?:\\/|$|\\?))(?!snapshots(?:\\/|$|\\?))([^/?]+)/);\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 sessionId = extractSessionId(response.url);\n let sandboxName: string | undefined;\n if (!sessionId) {\n sandboxName = extractSandboxName(response.url);\n }\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 sessionId,\n sandboxName\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 sessionId,\n sandboxName\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 sessionId,\n sandboxName\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 sessionId,\n sandboxName\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;;;;;;AAaX,SAAS,iBAAiB,KAAiC;AAEzD,QADc,IAAI,MAAM,sCAAsC,GAC/C;;;;;;AAOjB,SAAS,mBAAmB,KAAiC;AAE3D,QADc,IAAI,MAAM,2EAA2E,GACpF;;;;;;;;;AAUjB,eAAsB,MACpB,WACA,UAC6C;CAC7C,MAAM,YAAY,iBAAiB,SAAS,IAAI;CAChD,IAAIC;AACJ,KAAI,CAAC,UACH,eAAc,mBAAmB,SAAS,IAAI;CAGhD,MAAM,OAAO,MAAM,SAAS,MAAM,CAAC,OAAO,QAAQ;AAChD,SAAO,IAAIC,2BAAoB,UAAU;GACvC,SAAS,6BAA6B,OAAO,IAAI;GACjD;GACA;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;GACA;GACD,CAAC;;AAGJ,KAAI,CAAC,SAAS,GACZ,QAAO,IAAIA,2BAAoB,UAAU;EACvC,SAAS,eAAe,SAAS,OAAO;EAClC;EACN;EACA;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;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"} | ||
| {"version":3,"file":"base-client.cjs","names":["Agent","withRetry","value","z","sandboxName: string | undefined","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 { z, 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 sessionId from a sandbox API URL.\n */\nfunction extractSessionId(url: string): string | undefined {\n const match = url.match(/\\/v2\\/sandboxes\\/sessions\\/([^/?]+)/);\n return match?.[1];\n}\n\n/**\n * Extract sandbox name from a sandbox API url.\n * Excludes known sub-paths like /sessions/ and /snapshots/.\n */\nfunction extractSandboxName(url: string): string | undefined {\n const match = url.match(/\\/v2\\/sandboxes\\/(?!sessions(?:\\/|$|\\?))(?!snapshots(?:\\/|$|\\?))([^/?]+)/);\n return match?.[1];\n}\n\n/**\n * The error body shape returned by the Sandbox API. Mirrors the shape the\n * CLI's formatApiError parses.\n */\nconst ErrorResponseBody = z.object({\n error: z.object({\n message: z.string(),\n }),\n});\n\n/**\n * Extract the server-provided error message from an error response body so\n * it can be surfaced in APIError.message. Returns undefined for any other\n * body shape.\n */\nfunction extractServerMessage(json: unknown): string | undefined {\n const parsed = ErrorResponseBody.safeParse(json);\n return parsed.success ? parsed.data.error.message : undefined;\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 sessionId = extractSessionId(response.url);\n let sandboxName: string | undefined;\n if (!sessionId) {\n sandboxName = extractSandboxName(response.url);\n }\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 sessionId,\n sandboxName\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 sessionId,\n sandboxName\n });\n }\n\n if (!response.ok) {\n const serverMessage = extractServerMessage(json);\n return new APIError<ErrorData>(response, {\n message: serverMessage\n ? `Status code ${response.status} is not ok: ${serverMessage}`\n : `Status code ${response.status} is not ok`,\n json: json as ErrorData,\n text,\n sessionId,\n sandboxName\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 sessionId,\n sandboxName\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":"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"} |
| import { RequestOptions } from "./with-retry.js"; | ||
| import "zod"; | ||
| import { Options } from "async-retry"; | ||
| import "zod"; | ||
@@ -5,0 +5,0 @@ //#region src/api-client/base-client.d.ts |
| import { APIError } from "./api-error.js"; | ||
| import { array } from "../utils/array.js"; | ||
| import { withRetry } from "./with-retry.js"; | ||
| import { z } from "zod"; | ||
| import { Agent } from "undici"; | ||
@@ -66,2 +67,16 @@ | ||
| /** | ||
| * The error body shape returned by the Sandbox API. Mirrors the shape the | ||
| * CLI's formatApiError parses. | ||
| */ | ||
| const ErrorResponseBody = z.object({ error: z.object({ message: z.string() }) }); | ||
| /** | ||
| * Extract the server-provided error message from an error response body so | ||
| * it can be surfaced in APIError.message. Returns undefined for any other | ||
| * body shape. | ||
| */ | ||
| function extractServerMessage(json) { | ||
| const parsed = ErrorResponseBody.safeParse(json); | ||
| return parsed.success ? parsed.data.error.message : void 0; | ||
| } | ||
| /** | ||
| * Allows to read the response text and parse it as JSON casting to the given | ||
@@ -96,9 +111,12 @@ * type. If the response is not ok or cannot be parsed it will return error. | ||
| } | ||
| if (!response.ok) return new APIError(response, { | ||
| message: `Status code ${response.status} is not ok`, | ||
| json, | ||
| text, | ||
| sessionId, | ||
| sandboxName | ||
| }); | ||
| if (!response.ok) { | ||
| const serverMessage = extractServerMessage(json); | ||
| return new APIError(response, { | ||
| message: serverMessage ? `Status code ${response.status} is not ok: ${serverMessage}` : `Status code ${response.status} is not ok`, | ||
| json, | ||
| text, | ||
| sessionId, | ||
| sandboxName | ||
| }); | ||
| } | ||
| const validated = validator.safeParse(json); | ||
@@ -105,0 +123,0 @@ if (!validated.success) return new APIError(response, { |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"base-client.js","names":["value","sandboxName: string | undefined","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 sessionId from a sandbox API URL.\n */\nfunction extractSessionId(url: string): string | undefined {\n const match = url.match(/\\/v2\\/sandboxes\\/sessions\\/([^/?]+)/);\n return match?.[1];\n}\n\n/**\n * Extract sandbox name from a sandbox API url.\n * Excludes known sub-paths like /sessions/ and /snapshots/.\n */\nfunction extractSandboxName(url: string): string | undefined {\n const match = url.match(/\\/v2\\/sandboxes\\/(?!sessions(?:\\/|$|\\?))(?!snapshots(?:\\/|$|\\?))([^/?]+)/);\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 sessionId = extractSessionId(response.url);\n let sandboxName: string | undefined;\n if (!sessionId) {\n sandboxName = extractSandboxName(response.url);\n }\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 sessionId,\n sandboxName\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 sessionId,\n sandboxName\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 sessionId,\n sandboxName\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 sessionId,\n sandboxName\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;;;;;;AAaX,SAAS,iBAAiB,KAAiC;AAEzD,QADc,IAAI,MAAM,sCAAsC,GAC/C;;;;;;AAOjB,SAAS,mBAAmB,KAAiC;AAE3D,QADc,IAAI,MAAM,2EAA2E,GACpF;;;;;;;;;AAUjB,eAAsB,MACpB,WACA,UAC6C;CAC7C,MAAM,YAAY,iBAAiB,SAAS,IAAI;CAChD,IAAIC;AACJ,KAAI,CAAC,UACH,eAAc,mBAAmB,SAAS,IAAI;CAGhD,MAAM,OAAO,MAAM,SAAS,MAAM,CAAC,OAAO,QAAQ;AAChD,SAAO,IAAI,SAAoB,UAAU;GACvC,SAAS,6BAA6B,OAAO,IAAI;GACjD;GACA;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;GACA;GACD,CAAC;;AAGJ,KAAI,CAAC,SAAS,GACZ,QAAO,IAAI,SAAoB,UAAU;EACvC,SAAS,eAAe,SAAS,OAAO;EAClC;EACN;EACA;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;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"} | ||
| {"version":3,"file":"base-client.js","names":["value","sandboxName: string | undefined","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 { z, 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 sessionId from a sandbox API URL.\n */\nfunction extractSessionId(url: string): string | undefined {\n const match = url.match(/\\/v2\\/sandboxes\\/sessions\\/([^/?]+)/);\n return match?.[1];\n}\n\n/**\n * Extract sandbox name from a sandbox API url.\n * Excludes known sub-paths like /sessions/ and /snapshots/.\n */\nfunction extractSandboxName(url: string): string | undefined {\n const match = url.match(/\\/v2\\/sandboxes\\/(?!sessions(?:\\/|$|\\?))(?!snapshots(?:\\/|$|\\?))([^/?]+)/);\n return match?.[1];\n}\n\n/**\n * The error body shape returned by the Sandbox API. Mirrors the shape the\n * CLI's formatApiError parses.\n */\nconst ErrorResponseBody = z.object({\n error: z.object({\n message: z.string(),\n }),\n});\n\n/**\n * Extract the server-provided error message from an error response body so\n * it can be surfaced in APIError.message. Returns undefined for any other\n * body shape.\n */\nfunction extractServerMessage(json: unknown): string | undefined {\n const parsed = ErrorResponseBody.safeParse(json);\n return parsed.success ? parsed.data.error.message : undefined;\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 sessionId = extractSessionId(response.url);\n let sandboxName: string | undefined;\n if (!sessionId) {\n sandboxName = extractSandboxName(response.url);\n }\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 sessionId,\n sandboxName\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 sessionId,\n sandboxName\n });\n }\n\n if (!response.ok) {\n const serverMessage = extractServerMessage(json);\n return new APIError<ErrorData>(response, {\n message: serverMessage\n ? `Status code ${response.status} is not ok: ${serverMessage}`\n : `Status code ${response.status} is not ok`,\n json: json as ErrorData,\n text,\n sessionId,\n sandboxName\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 sessionId,\n sandboxName\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":"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"} |
@@ -99,2 +99,3 @@ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs'); | ||
| region: zod.z.string(), | ||
| regions: zod.z.array(zod.z.string()).optional(), | ||
| status: zod.z.enum([ | ||
@@ -178,2 +179,3 @@ "created", | ||
| projectId: zod.z.string(), | ||
| region: zod.z.string(), | ||
| maxSizeBytes: zod.z.number(), | ||
@@ -194,2 +196,3 @@ currentSessionId: zod.z.string().optional(), | ||
| region: zod.z.string().optional(), | ||
| failoverRegions: zod.z.array(zod.z.string()).optional(), | ||
| vcpus: zod.z.number().optional(), | ||
@@ -196,0 +199,0 @@ memory: zod.z.number().optional(), |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"validators.cjs","names":["z"],"sources":["../../src/api-client/validators.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport type SessionMetaData = z.infer<typeof Session>;\n\nconst RuleMatcherValidator = z.object({\n exact: z.string().optional(),\n startsWith: z.string().optional(),\n regex: z.string().optional(),\n});\n\nconst KeyValueMatcherValidator = z.object({\n key: RuleMatcherValidator.optional(),\n value: RuleMatcherValidator.optional(),\n});\n\nconst RuleMatchValidator = z.object({\n path: RuleMatcherValidator.optional(),\n method: z.array(z.string()).optional(),\n queryString: z.array(KeyValueMatcherValidator).optional(),\n headers: z.array(KeyValueMatcherValidator).optional(),\n});\n\nexport const InjectionRuleValidator = z.object({\n domain: z.string(),\n // headers are only sent in requests\n headers: z.record(z.string(), z.string()).optional(),\n // headerNames are returned in responses\n headerNames: z.array(z.string()).optional(),\n match: RuleMatchValidator.optional(),\n});\n\nexport const ForwardRuleValidator = z.object({\n domain: z.string(),\n forwardURL: z.string(),\n match: RuleMatchValidator.optional(),\n});\n\nexport const NetworkPolicyTransformValidator = z.object({\n headers: z.record(z.string(), z.string()).optional(),\n});\n\nexport const NetworkPolicyRuleValidator = z\n .object({\n match: RuleMatchValidator.optional(),\n transform: z.array(NetworkPolicyTransformValidator).optional(),\n forwardURL: z.string().optional(),\n })\n .refine(\n ({ transform, forwardURL }) =>\n transform === undefined || forwardURL === undefined,\n { message: \"transform and forwardURL cannot be used together\" },\n )\n .refine(\n ({ transform, forwardURL }) =>\n transform !== undefined || forwardURL !== undefined,\n { message: \"transform or forwardURL must be provided\" },\n );\n\nexport const V2NetworkPolicyObjectValidator = z.object({\n allow: z\n .union([\n z.array(z.string()),\n z.record(z.string(), z.array(NetworkPolicyRuleValidator)),\n ])\n .optional(),\n subnets: z\n .object({\n allow: z.array(z.string()).optional(),\n deny: z.array(z.string()).optional(),\n })\n .optional(),\n});\n\nconst NetworkPolicyModeValidator = z.union([\n z.object({ mode: z.literal(\"allow-all\") }).passthrough(),\n z.object({ mode: z.literal(\"deny-all\") }).passthrough(),\n]);\n\nconst LegacyCustomNetworkPolicyValidator = z\n .object({\n mode: z.literal(\"custom\"),\n allowedDomains: z.array(z.string()).optional(),\n allowedCIDRs: z.array(z.string()).optional(),\n deniedCIDRs: z.array(z.string()).optional(),\n injectionRules: z.array(InjectionRuleValidator).optional(),\n forwardRules: z.array(ForwardRuleValidator).optional(),\n })\n .passthrough();\n\nexport const NetworkPolicyRequestValidator = z.union([\n NetworkPolicyModeValidator,\n V2NetworkPolicyObjectValidator.passthrough(),\n]);\n\nexport const NetworkPolicyResponseValidator = z.union([\n NetworkPolicyModeValidator,\n LegacyCustomNetworkPolicyValidator,\n]);\n\nexport const Session = z.object({\n id: z.string(),\n memory: z.number(),\n vcpus: z.number(),\n region: z.string(),\n runtime: z.string().optional(),\n timeout: z.number(),\n status: z.enum([\n \"pending\",\n \"running\",\n \"stopping\",\n \"stopped\",\n \"failed\",\n \"aborted\",\n \"snapshotting\",\n ]),\n requestedAt: z.number(),\n startedAt: z.number().optional(),\n requestedStopAt: z.number().optional(),\n stoppedAt: z.number().optional(),\n abortedAt: z.number().optional(),\n duration: z.number().optional(),\n sourceSnapshotId: z.string().optional(),\n snapshottedAt: z.number().optional(),\n createdAt: z.number(),\n cwd: z.string(),\n updatedAt: z.number(),\n interactivePort: z.number().optional(),\n networkPolicy: NetworkPolicyResponseValidator.optional(),\n activeCpuDurationMs: z.number().optional(),\n networkTransfer: z\n .object({\n ingress: z.number(),\n egress: z.number(),\n })\n .optional(),\n});\n\nexport type SandboxRouteData = z.infer<typeof SandboxRoute>;\n\nexport const SandboxRoute = z.object({\n url: z.string(),\n subdomain: z.string(),\n port: z.number(),\n});\n\nexport type SnapshotMetadata = z.infer<typeof Snapshot>;\n\nexport const Snapshot = z.object({\n id: z.string(),\n sourceSessionId: z.string(),\n region: z.string(),\n status: z.enum([\"created\", \"deleted\", \"failed\"]),\n sizeBytes: z.number(),\n expiresAt: z.number().optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n lastUsedAt: z.number().optional(),\n creationMethod: z.string().optional(),\n parentId: z.string().optional(),\n});\n\nexport const CursorPagination = z.object({\n count: z.number(),\n next: z.string().nullable(),\n});\n\nexport type CommandData = z.infer<typeof Command>;\n\nexport const Command = z.object({\n id: z.string(),\n name: z.string(),\n args: z.array(z.string()),\n cwd: z.string(),\n sessionId: z.string(),\n exitCode: z.number().nullable(),\n // optional because the duration was not preserved for older commands\n durationMs: z.number().optional(),\n startedAt: z.number(),\n});\n\nconst CommandFinished = Command.extend({\n exitCode: z.number(),\n});\n\nexport const SessionResponse = z.object({\n session: Session.passthrough(),\n});\n\nexport const SessionAndRoutesResponse = SessionResponse.extend({\n routes: z.array(SandboxRoute),\n});\n\nexport type InteractiveSessionData = z.infer<typeof InteractiveSessionResponse>;\n\nexport const InteractiveSessionResponse = z.object({\n url: z.string(),\n token: z.string(),\n});\n\nexport const SessionsResponse = z.object({\n sessions: z.array(Session.passthrough()),\n pagination: CursorPagination,\n});\n\nexport const CommandResponse = z.object({\n command: Command,\n});\n\nexport type CommandFinishedData = z.infer<\n typeof CommandFinishedResponse\n>[\"command\"];\n\nexport const CommandFinishedResponse = z.object({\n command: CommandFinished,\n});\n\nexport const EmptyResponse = z.object({});\n\nconst LogLineBase = z.object({ data: z.string() });\nexport const LogLineStdout = LogLineBase.extend({\n stream: z.literal(\"stdout\"),\n});\nexport const LogLineStderr = LogLineBase.extend({\n stream: z.literal(\"stderr\"),\n});\n\nexport const LogError = z.object({\n stream: z.literal(\"error\"),\n data: z.object({\n code: z.string(),\n message: z.string(),\n }),\n});\n\nexport const LogLine = z.discriminatedUnion(\"stream\", [\n LogLineStdout,\n LogLineStderr,\n LogError,\n]);\nexport type LogLineData = z.infer<typeof LogLine>;\nexport type LogOutputLine = Exclude<LogLineData, z.infer<typeof LogError>>;\n\nexport const SnapshotsResponse = z.object({\n snapshots: z.array(Snapshot),\n pagination: CursorPagination,\n});\n\nexport const SnapshotTreeNode = z.object({\n snapshot: Snapshot,\n siblings: z.array(Snapshot),\n count: z.string(),\n});\n\nexport type SnapshotTreeNodeData = z.infer<typeof SnapshotTreeNode>;\n\nexport const SnapshotTreeResponse = z.object({\n snapshots: z.array(SnapshotTreeNode),\n anchor: SnapshotTreeNode.optional(),\n pagination: CursorPagination,\n});\n\nexport const CreateSnapshotResponse = z.object({\n snapshot: Snapshot,\n session: Session.passthrough(),\n});\n\nexport const SnapshotResponse = z.object({\n snapshot: Snapshot,\n});\n\nexport const Drive = z.object({\n name: z.string(),\n projectId: z.string(),\n maxSizeBytes: z.number(),\n currentSessionId: z.string().optional(),\n currentSandboxName: z.string().optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n});\n\nexport type DriveMetadata = z.infer<typeof Drive>;\n\nexport const DrivesResponse = z.object({\n drives: z.array(Drive),\n pagination: CursorPagination,\n});\n\nexport const DriveResponse = z.object({\n drive: Drive,\n});\n\nexport const Sandbox = z.object({\n name: z.string(),\n persistent: z.boolean(),\n region: z.string().optional(),\n vcpus: z.number().optional(),\n memory: z.number().optional(),\n runtime: z.string().optional(),\n image: z.string().optional(),\n timeout: z.number().optional(),\n networkPolicy: NetworkPolicyResponseValidator.optional(),\n totalEgressBytes: z.number().optional(),\n totalIngressBytes: z.number().optional(),\n totalActiveCpuDurationMs: z.number().optional(),\n totalDurationMs: z.number().optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n expiresAt: z.number().optional(),\n currentSessionId: z.string(),\n currentSnapshotId: z.string().optional(),\n status: Session.shape.status,\n statusUpdatedAt: z.number().optional(),\n cwd: z.string().optional(),\n tags: z.record(z.string(), z.string()).optional(),\n mounts: z\n .record(\n z.string(),\n z.object({\n drive: z.string(),\n mode: z.enum([\"read-only\", \"read-write\"]).optional(),\n }),\n )\n .optional(),\n snapshotExpiration: z.number().optional(),\n keepLastSnapshots: z\n .object({\n count: z.number(),\n expiration: z.number().optional(),\n deleteEvicted: z.boolean().optional(),\n })\n .optional(),\n});\n\nexport type SandboxMetaData = z.infer<typeof Sandbox>;\n\nexport const StopSessionResponse = z.object({\n session: Session.passthrough(),\n sandbox: Sandbox.optional(),\n snapshot: Snapshot.optional(),\n});\n\nexport const SandboxAndSessionResponse = z.object({\n sandbox: Sandbox,\n session: Session.passthrough(),\n routes: z.array(SandboxRoute),\n resumed: z.boolean().optional(),\n});\n\nexport const SandboxesPaginationResponse = z.object({\n sandboxes: z.array(Sandbox),\n pagination: CursorPagination,\n});\n\nexport const UpdateSandboxResponse = z.object({\n sandbox: Sandbox,\n routes: z.array(SandboxRoute).optional(),\n});\n"],"mappings":"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"} | ||
| {"version":3,"file":"validators.cjs","names":["z"],"sources":["../../src/api-client/validators.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport type SessionMetaData = z.infer<typeof Session>;\n\nconst RuleMatcherValidator = z.object({\n exact: z.string().optional(),\n startsWith: z.string().optional(),\n regex: z.string().optional(),\n});\n\nconst KeyValueMatcherValidator = z.object({\n key: RuleMatcherValidator.optional(),\n value: RuleMatcherValidator.optional(),\n});\n\nconst RuleMatchValidator = z.object({\n path: RuleMatcherValidator.optional(),\n method: z.array(z.string()).optional(),\n queryString: z.array(KeyValueMatcherValidator).optional(),\n headers: z.array(KeyValueMatcherValidator).optional(),\n});\n\nexport const InjectionRuleValidator = z.object({\n domain: z.string(),\n // headers are only sent in requests\n headers: z.record(z.string(), z.string()).optional(),\n // headerNames are returned in responses\n headerNames: z.array(z.string()).optional(),\n match: RuleMatchValidator.optional(),\n});\n\nexport const ForwardRuleValidator = z.object({\n domain: z.string(),\n forwardURL: z.string(),\n match: RuleMatchValidator.optional(),\n});\n\nexport const NetworkPolicyTransformValidator = z.object({\n headers: z.record(z.string(), z.string()).optional(),\n});\n\nexport const NetworkPolicyRuleValidator = z\n .object({\n match: RuleMatchValidator.optional(),\n transform: z.array(NetworkPolicyTransformValidator).optional(),\n forwardURL: z.string().optional(),\n })\n .refine(\n ({ transform, forwardURL }) =>\n transform === undefined || forwardURL === undefined,\n { message: \"transform and forwardURL cannot be used together\" },\n )\n .refine(\n ({ transform, forwardURL }) =>\n transform !== undefined || forwardURL !== undefined,\n { message: \"transform or forwardURL must be provided\" },\n );\n\nexport const V2NetworkPolicyObjectValidator = z.object({\n allow: z\n .union([\n z.array(z.string()),\n z.record(z.string(), z.array(NetworkPolicyRuleValidator)),\n ])\n .optional(),\n subnets: z\n .object({\n allow: z.array(z.string()).optional(),\n deny: z.array(z.string()).optional(),\n })\n .optional(),\n});\n\nconst NetworkPolicyModeValidator = z.union([\n z.object({ mode: z.literal(\"allow-all\") }).passthrough(),\n z.object({ mode: z.literal(\"deny-all\") }).passthrough(),\n]);\n\nconst LegacyCustomNetworkPolicyValidator = z\n .object({\n mode: z.literal(\"custom\"),\n allowedDomains: z.array(z.string()).optional(),\n allowedCIDRs: z.array(z.string()).optional(),\n deniedCIDRs: z.array(z.string()).optional(),\n injectionRules: z.array(InjectionRuleValidator).optional(),\n forwardRules: z.array(ForwardRuleValidator).optional(),\n })\n .passthrough();\n\nexport const NetworkPolicyRequestValidator = z.union([\n NetworkPolicyModeValidator,\n V2NetworkPolicyObjectValidator.passthrough(),\n]);\n\nexport const NetworkPolicyResponseValidator = z.union([\n NetworkPolicyModeValidator,\n LegacyCustomNetworkPolicyValidator,\n]);\n\nexport const Session = z.object({\n id: z.string(),\n memory: z.number(),\n vcpus: z.number(),\n region: z.string(),\n runtime: z.string().optional(),\n timeout: z.number(),\n status: z.enum([\n \"pending\",\n \"running\",\n \"stopping\",\n \"stopped\",\n \"failed\",\n \"aborted\",\n \"snapshotting\",\n ]),\n requestedAt: z.number(),\n startedAt: z.number().optional(),\n requestedStopAt: z.number().optional(),\n stoppedAt: z.number().optional(),\n abortedAt: z.number().optional(),\n duration: z.number().optional(),\n sourceSnapshotId: z.string().optional(),\n snapshottedAt: z.number().optional(),\n createdAt: z.number(),\n cwd: z.string(),\n updatedAt: z.number(),\n interactivePort: z.number().optional(),\n networkPolicy: NetworkPolicyResponseValidator.optional(),\n activeCpuDurationMs: z.number().optional(),\n networkTransfer: z\n .object({\n ingress: z.number(),\n egress: z.number(),\n })\n .optional(),\n});\n\nexport type SandboxRouteData = z.infer<typeof SandboxRoute>;\n\nexport const SandboxRoute = z.object({\n url: z.string(),\n subdomain: z.string(),\n port: z.number(),\n});\n\nexport type SnapshotMetadata = z.infer<typeof Snapshot>;\n\nexport const Snapshot = z.object({\n id: z.string(),\n sourceSessionId: z.string(),\n region: z.string(),\n regions: z.array(z.string()).optional(),\n status: z.enum([\"created\", \"deleted\", \"failed\"]),\n sizeBytes: z.number(),\n expiresAt: z.number().optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n lastUsedAt: z.number().optional(),\n creationMethod: z.string().optional(),\n parentId: z.string().optional(),\n});\n\nexport const CursorPagination = z.object({\n count: z.number(),\n next: z.string().nullable(),\n});\n\nexport type CommandData = z.infer<typeof Command>;\n\nexport const Command = z.object({\n id: z.string(),\n name: z.string(),\n args: z.array(z.string()),\n cwd: z.string(),\n sessionId: z.string(),\n exitCode: z.number().nullable(),\n // optional because the duration was not preserved for older commands\n durationMs: z.number().optional(),\n startedAt: z.number(),\n});\n\nconst CommandFinished = Command.extend({\n exitCode: z.number(),\n});\n\nexport const SessionResponse = z.object({\n session: Session.passthrough(),\n});\n\nexport const SessionAndRoutesResponse = SessionResponse.extend({\n routes: z.array(SandboxRoute),\n});\n\nexport type InteractiveSessionData = z.infer<typeof InteractiveSessionResponse>;\n\nexport const InteractiveSessionResponse = z.object({\n url: z.string(),\n token: z.string(),\n});\n\nexport const SessionsResponse = z.object({\n sessions: z.array(Session.passthrough()),\n pagination: CursorPagination,\n});\n\nexport const CommandResponse = z.object({\n command: Command,\n});\n\nexport type CommandFinishedData = z.infer<\n typeof CommandFinishedResponse\n>[\"command\"];\n\nexport const CommandFinishedResponse = z.object({\n command: CommandFinished,\n});\n\nexport const EmptyResponse = z.object({});\n\nconst LogLineBase = z.object({ data: z.string() });\nexport const LogLineStdout = LogLineBase.extend({\n stream: z.literal(\"stdout\"),\n});\nexport const LogLineStderr = LogLineBase.extend({\n stream: z.literal(\"stderr\"),\n});\n\nexport const LogError = z.object({\n stream: z.literal(\"error\"),\n data: z.object({\n code: z.string(),\n message: z.string(),\n }),\n});\n\nexport const LogLine = z.discriminatedUnion(\"stream\", [\n LogLineStdout,\n LogLineStderr,\n LogError,\n]);\nexport type LogLineData = z.infer<typeof LogLine>;\nexport type LogOutputLine = Exclude<LogLineData, z.infer<typeof LogError>>;\n\nexport const SnapshotsResponse = z.object({\n snapshots: z.array(Snapshot),\n pagination: CursorPagination,\n});\n\nexport const SnapshotTreeNode = z.object({\n snapshot: Snapshot,\n siblings: z.array(Snapshot),\n count: z.string(),\n});\n\nexport type SnapshotTreeNodeData = z.infer<typeof SnapshotTreeNode>;\n\nexport const SnapshotTreeResponse = z.object({\n snapshots: z.array(SnapshotTreeNode),\n anchor: SnapshotTreeNode.optional(),\n pagination: CursorPagination,\n});\n\nexport const CreateSnapshotResponse = z.object({\n snapshot: Snapshot,\n session: Session.passthrough(),\n});\n\nexport const SnapshotResponse = z.object({\n snapshot: Snapshot,\n});\n\nexport const Drive = z.object({\n name: z.string(),\n projectId: z.string(),\n region: z.string(),\n maxSizeBytes: z.number(),\n currentSessionId: z.string().optional(),\n currentSandboxName: z.string().optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n});\n\nexport type DriveMetadata = z.infer<typeof Drive>;\n\nexport const DrivesResponse = z.object({\n drives: z.array(Drive),\n pagination: CursorPagination,\n});\n\nexport const DriveResponse = z.object({\n drive: Drive,\n});\n\nexport const Sandbox = z.object({\n name: z.string(),\n persistent: z.boolean(),\n region: z.string().optional(),\n failoverRegions: z.array(z.string()).optional(),\n vcpus: z.number().optional(),\n memory: z.number().optional(),\n runtime: z.string().optional(),\n image: z.string().optional(),\n timeout: z.number().optional(),\n networkPolicy: NetworkPolicyResponseValidator.optional(),\n totalEgressBytes: z.number().optional(),\n totalIngressBytes: z.number().optional(),\n totalActiveCpuDurationMs: z.number().optional(),\n totalDurationMs: z.number().optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n expiresAt: z.number().optional(),\n currentSessionId: z.string(),\n currentSnapshotId: z.string().optional(),\n status: Session.shape.status,\n statusUpdatedAt: z.number().optional(),\n cwd: z.string().optional(),\n tags: z.record(z.string(), z.string()).optional(),\n mounts: z\n .record(\n z.string(),\n z.object({\n drive: z.string(),\n mode: z.enum([\"read-only\", \"read-write\"]).optional(),\n }),\n )\n .optional(),\n snapshotExpiration: z.number().optional(),\n keepLastSnapshots: z\n .object({\n count: z.number(),\n expiration: z.number().optional(),\n deleteEvicted: z.boolean().optional(),\n })\n .optional(),\n});\n\nexport type SandboxMetaData = z.infer<typeof Sandbox>;\n\nexport const StopSessionResponse = z.object({\n session: Session.passthrough(),\n sandbox: Sandbox.optional(),\n snapshot: Snapshot.optional(),\n});\n\nexport const SandboxAndSessionResponse = z.object({\n sandbox: Sandbox,\n session: Session.passthrough(),\n routes: z.array(SandboxRoute),\n resumed: z.boolean().optional(),\n});\n\nexport const SandboxesPaginationResponse = z.object({\n sandboxes: z.array(Sandbox),\n pagination: CursorPagination,\n});\n\nexport const UpdateSandboxResponse = z.object({\n sandbox: Sandbox,\n routes: z.array(SandboxRoute).optional(),\n});\n"],"mappings":"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"} |
@@ -133,2 +133,3 @@ import { z } from "zod"; | ||
| region: z.ZodString; | ||
| regions: z.ZodOptional<z.ZodArray<z.ZodString>>; | ||
| status: z.ZodEnum<{ | ||
@@ -333,2 +334,3 @@ failed: "failed"; | ||
| region: z.ZodString; | ||
| regions: z.ZodOptional<z.ZodArray<z.ZodString>>; | ||
| status: z.ZodEnum<{ | ||
@@ -351,2 +353,3 @@ failed: "failed"; | ||
| region: z.ZodString; | ||
| regions: z.ZodOptional<z.ZodArray<z.ZodString>>; | ||
| status: z.ZodEnum<{ | ||
@@ -373,2 +376,3 @@ failed: "failed"; | ||
| region: z.ZodString; | ||
| regions: z.ZodOptional<z.ZodArray<z.ZodString>>; | ||
| status: z.ZodEnum<{ | ||
@@ -510,2 +514,3 @@ failed: "failed"; | ||
| region: z.ZodString; | ||
| regions: z.ZodOptional<z.ZodArray<z.ZodString>>; | ||
| status: z.ZodEnum<{ | ||
@@ -528,2 +533,3 @@ failed: "failed"; | ||
| projectId: z.ZodString; | ||
| region: z.ZodString; | ||
| maxSizeBytes: z.ZodNumber; | ||
@@ -540,2 +546,3 @@ currentSessionId: z.ZodOptional<z.ZodString>; | ||
| region: z.ZodOptional<z.ZodString>; | ||
| failoverRegions: z.ZodOptional<z.ZodArray<z.ZodString>>; | ||
| vcpus: z.ZodOptional<z.ZodNumber>; | ||
@@ -787,2 +794,3 @@ memory: z.ZodOptional<z.ZodNumber>; | ||
| region: z.ZodOptional<z.ZodString>; | ||
| failoverRegions: z.ZodOptional<z.ZodArray<z.ZodString>>; | ||
| vcpus: z.ZodOptional<z.ZodNumber>; | ||
@@ -915,2 +923,3 @@ memory: z.ZodOptional<z.ZodNumber>; | ||
| region: z.ZodString; | ||
| regions: z.ZodOptional<z.ZodArray<z.ZodString>>; | ||
| status: z.ZodEnum<{ | ||
@@ -917,0 +926,0 @@ failed: "failed"; |
@@ -133,2 +133,3 @@ import { z } from "zod"; | ||
| region: z.ZodString; | ||
| regions: z.ZodOptional<z.ZodArray<z.ZodString>>; | ||
| status: z.ZodEnum<{ | ||
@@ -333,2 +334,3 @@ failed: "failed"; | ||
| region: z.ZodString; | ||
| regions: z.ZodOptional<z.ZodArray<z.ZodString>>; | ||
| status: z.ZodEnum<{ | ||
@@ -351,2 +353,3 @@ failed: "failed"; | ||
| region: z.ZodString; | ||
| regions: z.ZodOptional<z.ZodArray<z.ZodString>>; | ||
| status: z.ZodEnum<{ | ||
@@ -373,2 +376,3 @@ failed: "failed"; | ||
| region: z.ZodString; | ||
| regions: z.ZodOptional<z.ZodArray<z.ZodString>>; | ||
| status: z.ZodEnum<{ | ||
@@ -510,2 +514,3 @@ failed: "failed"; | ||
| region: z.ZodString; | ||
| regions: z.ZodOptional<z.ZodArray<z.ZodString>>; | ||
| status: z.ZodEnum<{ | ||
@@ -528,2 +533,3 @@ failed: "failed"; | ||
| projectId: z.ZodString; | ||
| region: z.ZodString; | ||
| maxSizeBytes: z.ZodNumber; | ||
@@ -540,2 +546,3 @@ currentSessionId: z.ZodOptional<z.ZodString>; | ||
| region: z.ZodOptional<z.ZodString>; | ||
| failoverRegions: z.ZodOptional<z.ZodArray<z.ZodString>>; | ||
| vcpus: z.ZodOptional<z.ZodNumber>; | ||
@@ -787,2 +794,3 @@ memory: z.ZodOptional<z.ZodNumber>; | ||
| region: z.ZodOptional<z.ZodString>; | ||
| failoverRegions: z.ZodOptional<z.ZodArray<z.ZodString>>; | ||
| vcpus: z.ZodOptional<z.ZodNumber>; | ||
@@ -915,2 +923,3 @@ memory: z.ZodOptional<z.ZodNumber>; | ||
| region: z.ZodString; | ||
| regions: z.ZodOptional<z.ZodArray<z.ZodString>>; | ||
| status: z.ZodEnum<{ | ||
@@ -917,0 +926,0 @@ failed: "failed"; |
@@ -98,2 +98,3 @@ import { z } from "zod"; | ||
| region: z.string(), | ||
| regions: z.array(z.string()).optional(), | ||
| status: z.enum([ | ||
@@ -177,2 +178,3 @@ "created", | ||
| projectId: z.string(), | ||
| region: z.string(), | ||
| maxSizeBytes: z.number(), | ||
@@ -193,2 +195,3 @@ currentSessionId: z.string().optional(), | ||
| region: z.string().optional(), | ||
| failoverRegions: z.array(z.string()).optional(), | ||
| vcpus: z.number().optional(), | ||
@@ -195,0 +198,0 @@ memory: z.number().optional(), |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"validators.js","names":[],"sources":["../../src/api-client/validators.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport type SessionMetaData = z.infer<typeof Session>;\n\nconst RuleMatcherValidator = z.object({\n exact: z.string().optional(),\n startsWith: z.string().optional(),\n regex: z.string().optional(),\n});\n\nconst KeyValueMatcherValidator = z.object({\n key: RuleMatcherValidator.optional(),\n value: RuleMatcherValidator.optional(),\n});\n\nconst RuleMatchValidator = z.object({\n path: RuleMatcherValidator.optional(),\n method: z.array(z.string()).optional(),\n queryString: z.array(KeyValueMatcherValidator).optional(),\n headers: z.array(KeyValueMatcherValidator).optional(),\n});\n\nexport const InjectionRuleValidator = z.object({\n domain: z.string(),\n // headers are only sent in requests\n headers: z.record(z.string(), z.string()).optional(),\n // headerNames are returned in responses\n headerNames: z.array(z.string()).optional(),\n match: RuleMatchValidator.optional(),\n});\n\nexport const ForwardRuleValidator = z.object({\n domain: z.string(),\n forwardURL: z.string(),\n match: RuleMatchValidator.optional(),\n});\n\nexport const NetworkPolicyTransformValidator = z.object({\n headers: z.record(z.string(), z.string()).optional(),\n});\n\nexport const NetworkPolicyRuleValidator = z\n .object({\n match: RuleMatchValidator.optional(),\n transform: z.array(NetworkPolicyTransformValidator).optional(),\n forwardURL: z.string().optional(),\n })\n .refine(\n ({ transform, forwardURL }) =>\n transform === undefined || forwardURL === undefined,\n { message: \"transform and forwardURL cannot be used together\" },\n )\n .refine(\n ({ transform, forwardURL }) =>\n transform !== undefined || forwardURL !== undefined,\n { message: \"transform or forwardURL must be provided\" },\n );\n\nexport const V2NetworkPolicyObjectValidator = z.object({\n allow: z\n .union([\n z.array(z.string()),\n z.record(z.string(), z.array(NetworkPolicyRuleValidator)),\n ])\n .optional(),\n subnets: z\n .object({\n allow: z.array(z.string()).optional(),\n deny: z.array(z.string()).optional(),\n })\n .optional(),\n});\n\nconst NetworkPolicyModeValidator = z.union([\n z.object({ mode: z.literal(\"allow-all\") }).passthrough(),\n z.object({ mode: z.literal(\"deny-all\") }).passthrough(),\n]);\n\nconst LegacyCustomNetworkPolicyValidator = z\n .object({\n mode: z.literal(\"custom\"),\n allowedDomains: z.array(z.string()).optional(),\n allowedCIDRs: z.array(z.string()).optional(),\n deniedCIDRs: z.array(z.string()).optional(),\n injectionRules: z.array(InjectionRuleValidator).optional(),\n forwardRules: z.array(ForwardRuleValidator).optional(),\n })\n .passthrough();\n\nexport const NetworkPolicyRequestValidator = z.union([\n NetworkPolicyModeValidator,\n V2NetworkPolicyObjectValidator.passthrough(),\n]);\n\nexport const NetworkPolicyResponseValidator = z.union([\n NetworkPolicyModeValidator,\n LegacyCustomNetworkPolicyValidator,\n]);\n\nexport const Session = z.object({\n id: z.string(),\n memory: z.number(),\n vcpus: z.number(),\n region: z.string(),\n runtime: z.string().optional(),\n timeout: z.number(),\n status: z.enum([\n \"pending\",\n \"running\",\n \"stopping\",\n \"stopped\",\n \"failed\",\n \"aborted\",\n \"snapshotting\",\n ]),\n requestedAt: z.number(),\n startedAt: z.number().optional(),\n requestedStopAt: z.number().optional(),\n stoppedAt: z.number().optional(),\n abortedAt: z.number().optional(),\n duration: z.number().optional(),\n sourceSnapshotId: z.string().optional(),\n snapshottedAt: z.number().optional(),\n createdAt: z.number(),\n cwd: z.string(),\n updatedAt: z.number(),\n interactivePort: z.number().optional(),\n networkPolicy: NetworkPolicyResponseValidator.optional(),\n activeCpuDurationMs: z.number().optional(),\n networkTransfer: z\n .object({\n ingress: z.number(),\n egress: z.number(),\n })\n .optional(),\n});\n\nexport type SandboxRouteData = z.infer<typeof SandboxRoute>;\n\nexport const SandboxRoute = z.object({\n url: z.string(),\n subdomain: z.string(),\n port: z.number(),\n});\n\nexport type SnapshotMetadata = z.infer<typeof Snapshot>;\n\nexport const Snapshot = z.object({\n id: z.string(),\n sourceSessionId: z.string(),\n region: z.string(),\n status: z.enum([\"created\", \"deleted\", \"failed\"]),\n sizeBytes: z.number(),\n expiresAt: z.number().optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n lastUsedAt: z.number().optional(),\n creationMethod: z.string().optional(),\n parentId: z.string().optional(),\n});\n\nexport const CursorPagination = z.object({\n count: z.number(),\n next: z.string().nullable(),\n});\n\nexport type CommandData = z.infer<typeof Command>;\n\nexport const Command = z.object({\n id: z.string(),\n name: z.string(),\n args: z.array(z.string()),\n cwd: z.string(),\n sessionId: z.string(),\n exitCode: z.number().nullable(),\n // optional because the duration was not preserved for older commands\n durationMs: z.number().optional(),\n startedAt: z.number(),\n});\n\nconst CommandFinished = Command.extend({\n exitCode: z.number(),\n});\n\nexport const SessionResponse = z.object({\n session: Session.passthrough(),\n});\n\nexport const SessionAndRoutesResponse = SessionResponse.extend({\n routes: z.array(SandboxRoute),\n});\n\nexport type InteractiveSessionData = z.infer<typeof InteractiveSessionResponse>;\n\nexport const InteractiveSessionResponse = z.object({\n url: z.string(),\n token: z.string(),\n});\n\nexport const SessionsResponse = z.object({\n sessions: z.array(Session.passthrough()),\n pagination: CursorPagination,\n});\n\nexport const CommandResponse = z.object({\n command: Command,\n});\n\nexport type CommandFinishedData = z.infer<\n typeof CommandFinishedResponse\n>[\"command\"];\n\nexport const CommandFinishedResponse = z.object({\n command: CommandFinished,\n});\n\nexport const EmptyResponse = z.object({});\n\nconst LogLineBase = z.object({ data: z.string() });\nexport const LogLineStdout = LogLineBase.extend({\n stream: z.literal(\"stdout\"),\n});\nexport const LogLineStderr = LogLineBase.extend({\n stream: z.literal(\"stderr\"),\n});\n\nexport const LogError = z.object({\n stream: z.literal(\"error\"),\n data: z.object({\n code: z.string(),\n message: z.string(),\n }),\n});\n\nexport const LogLine = z.discriminatedUnion(\"stream\", [\n LogLineStdout,\n LogLineStderr,\n LogError,\n]);\nexport type LogLineData = z.infer<typeof LogLine>;\nexport type LogOutputLine = Exclude<LogLineData, z.infer<typeof LogError>>;\n\nexport const SnapshotsResponse = z.object({\n snapshots: z.array(Snapshot),\n pagination: CursorPagination,\n});\n\nexport const SnapshotTreeNode = z.object({\n snapshot: Snapshot,\n siblings: z.array(Snapshot),\n count: z.string(),\n});\n\nexport type SnapshotTreeNodeData = z.infer<typeof SnapshotTreeNode>;\n\nexport const SnapshotTreeResponse = z.object({\n snapshots: z.array(SnapshotTreeNode),\n anchor: SnapshotTreeNode.optional(),\n pagination: CursorPagination,\n});\n\nexport const CreateSnapshotResponse = z.object({\n snapshot: Snapshot,\n session: Session.passthrough(),\n});\n\nexport const SnapshotResponse = z.object({\n snapshot: Snapshot,\n});\n\nexport const Drive = z.object({\n name: z.string(),\n projectId: z.string(),\n maxSizeBytes: z.number(),\n currentSessionId: z.string().optional(),\n currentSandboxName: z.string().optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n});\n\nexport type DriveMetadata = z.infer<typeof Drive>;\n\nexport const DrivesResponse = z.object({\n drives: z.array(Drive),\n pagination: CursorPagination,\n});\n\nexport const DriveResponse = z.object({\n drive: Drive,\n});\n\nexport const Sandbox = z.object({\n name: z.string(),\n persistent: z.boolean(),\n region: z.string().optional(),\n vcpus: z.number().optional(),\n memory: z.number().optional(),\n runtime: z.string().optional(),\n image: z.string().optional(),\n timeout: z.number().optional(),\n networkPolicy: NetworkPolicyResponseValidator.optional(),\n totalEgressBytes: z.number().optional(),\n totalIngressBytes: z.number().optional(),\n totalActiveCpuDurationMs: z.number().optional(),\n totalDurationMs: z.number().optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n expiresAt: z.number().optional(),\n currentSessionId: z.string(),\n currentSnapshotId: z.string().optional(),\n status: Session.shape.status,\n statusUpdatedAt: z.number().optional(),\n cwd: z.string().optional(),\n tags: z.record(z.string(), z.string()).optional(),\n mounts: z\n .record(\n z.string(),\n z.object({\n drive: z.string(),\n mode: z.enum([\"read-only\", \"read-write\"]).optional(),\n }),\n )\n .optional(),\n snapshotExpiration: z.number().optional(),\n keepLastSnapshots: z\n .object({\n count: z.number(),\n expiration: z.number().optional(),\n deleteEvicted: z.boolean().optional(),\n })\n .optional(),\n});\n\nexport type SandboxMetaData = z.infer<typeof Sandbox>;\n\nexport const StopSessionResponse = z.object({\n session: Session.passthrough(),\n sandbox: Sandbox.optional(),\n snapshot: Snapshot.optional(),\n});\n\nexport const SandboxAndSessionResponse = z.object({\n sandbox: Sandbox,\n session: Session.passthrough(),\n routes: z.array(SandboxRoute),\n resumed: z.boolean().optional(),\n});\n\nexport const SandboxesPaginationResponse = z.object({\n sandboxes: z.array(Sandbox),\n pagination: CursorPagination,\n});\n\nexport const UpdateSandboxResponse = z.object({\n sandbox: Sandbox,\n routes: z.array(SandboxRoute).optional(),\n});\n"],"mappings":"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"} | ||
| {"version":3,"file":"validators.js","names":[],"sources":["../../src/api-client/validators.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport type SessionMetaData = z.infer<typeof Session>;\n\nconst RuleMatcherValidator = z.object({\n exact: z.string().optional(),\n startsWith: z.string().optional(),\n regex: z.string().optional(),\n});\n\nconst KeyValueMatcherValidator = z.object({\n key: RuleMatcherValidator.optional(),\n value: RuleMatcherValidator.optional(),\n});\n\nconst RuleMatchValidator = z.object({\n path: RuleMatcherValidator.optional(),\n method: z.array(z.string()).optional(),\n queryString: z.array(KeyValueMatcherValidator).optional(),\n headers: z.array(KeyValueMatcherValidator).optional(),\n});\n\nexport const InjectionRuleValidator = z.object({\n domain: z.string(),\n // headers are only sent in requests\n headers: z.record(z.string(), z.string()).optional(),\n // headerNames are returned in responses\n headerNames: z.array(z.string()).optional(),\n match: RuleMatchValidator.optional(),\n});\n\nexport const ForwardRuleValidator = z.object({\n domain: z.string(),\n forwardURL: z.string(),\n match: RuleMatchValidator.optional(),\n});\n\nexport const NetworkPolicyTransformValidator = z.object({\n headers: z.record(z.string(), z.string()).optional(),\n});\n\nexport const NetworkPolicyRuleValidator = z\n .object({\n match: RuleMatchValidator.optional(),\n transform: z.array(NetworkPolicyTransformValidator).optional(),\n forwardURL: z.string().optional(),\n })\n .refine(\n ({ transform, forwardURL }) =>\n transform === undefined || forwardURL === undefined,\n { message: \"transform and forwardURL cannot be used together\" },\n )\n .refine(\n ({ transform, forwardURL }) =>\n transform !== undefined || forwardURL !== undefined,\n { message: \"transform or forwardURL must be provided\" },\n );\n\nexport const V2NetworkPolicyObjectValidator = z.object({\n allow: z\n .union([\n z.array(z.string()),\n z.record(z.string(), z.array(NetworkPolicyRuleValidator)),\n ])\n .optional(),\n subnets: z\n .object({\n allow: z.array(z.string()).optional(),\n deny: z.array(z.string()).optional(),\n })\n .optional(),\n});\n\nconst NetworkPolicyModeValidator = z.union([\n z.object({ mode: z.literal(\"allow-all\") }).passthrough(),\n z.object({ mode: z.literal(\"deny-all\") }).passthrough(),\n]);\n\nconst LegacyCustomNetworkPolicyValidator = z\n .object({\n mode: z.literal(\"custom\"),\n allowedDomains: z.array(z.string()).optional(),\n allowedCIDRs: z.array(z.string()).optional(),\n deniedCIDRs: z.array(z.string()).optional(),\n injectionRules: z.array(InjectionRuleValidator).optional(),\n forwardRules: z.array(ForwardRuleValidator).optional(),\n })\n .passthrough();\n\nexport const NetworkPolicyRequestValidator = z.union([\n NetworkPolicyModeValidator,\n V2NetworkPolicyObjectValidator.passthrough(),\n]);\n\nexport const NetworkPolicyResponseValidator = z.union([\n NetworkPolicyModeValidator,\n LegacyCustomNetworkPolicyValidator,\n]);\n\nexport const Session = z.object({\n id: z.string(),\n memory: z.number(),\n vcpus: z.number(),\n region: z.string(),\n runtime: z.string().optional(),\n timeout: z.number(),\n status: z.enum([\n \"pending\",\n \"running\",\n \"stopping\",\n \"stopped\",\n \"failed\",\n \"aborted\",\n \"snapshotting\",\n ]),\n requestedAt: z.number(),\n startedAt: z.number().optional(),\n requestedStopAt: z.number().optional(),\n stoppedAt: z.number().optional(),\n abortedAt: z.number().optional(),\n duration: z.number().optional(),\n sourceSnapshotId: z.string().optional(),\n snapshottedAt: z.number().optional(),\n createdAt: z.number(),\n cwd: z.string(),\n updatedAt: z.number(),\n interactivePort: z.number().optional(),\n networkPolicy: NetworkPolicyResponseValidator.optional(),\n activeCpuDurationMs: z.number().optional(),\n networkTransfer: z\n .object({\n ingress: z.number(),\n egress: z.number(),\n })\n .optional(),\n});\n\nexport type SandboxRouteData = z.infer<typeof SandboxRoute>;\n\nexport const SandboxRoute = z.object({\n url: z.string(),\n subdomain: z.string(),\n port: z.number(),\n});\n\nexport type SnapshotMetadata = z.infer<typeof Snapshot>;\n\nexport const Snapshot = z.object({\n id: z.string(),\n sourceSessionId: z.string(),\n region: z.string(),\n regions: z.array(z.string()).optional(),\n status: z.enum([\"created\", \"deleted\", \"failed\"]),\n sizeBytes: z.number(),\n expiresAt: z.number().optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n lastUsedAt: z.number().optional(),\n creationMethod: z.string().optional(),\n parentId: z.string().optional(),\n});\n\nexport const CursorPagination = z.object({\n count: z.number(),\n next: z.string().nullable(),\n});\n\nexport type CommandData = z.infer<typeof Command>;\n\nexport const Command = z.object({\n id: z.string(),\n name: z.string(),\n args: z.array(z.string()),\n cwd: z.string(),\n sessionId: z.string(),\n exitCode: z.number().nullable(),\n // optional because the duration was not preserved for older commands\n durationMs: z.number().optional(),\n startedAt: z.number(),\n});\n\nconst CommandFinished = Command.extend({\n exitCode: z.number(),\n});\n\nexport const SessionResponse = z.object({\n session: Session.passthrough(),\n});\n\nexport const SessionAndRoutesResponse = SessionResponse.extend({\n routes: z.array(SandboxRoute),\n});\n\nexport type InteractiveSessionData = z.infer<typeof InteractiveSessionResponse>;\n\nexport const InteractiveSessionResponse = z.object({\n url: z.string(),\n token: z.string(),\n});\n\nexport const SessionsResponse = z.object({\n sessions: z.array(Session.passthrough()),\n pagination: CursorPagination,\n});\n\nexport const CommandResponse = z.object({\n command: Command,\n});\n\nexport type CommandFinishedData = z.infer<\n typeof CommandFinishedResponse\n>[\"command\"];\n\nexport const CommandFinishedResponse = z.object({\n command: CommandFinished,\n});\n\nexport const EmptyResponse = z.object({});\n\nconst LogLineBase = z.object({ data: z.string() });\nexport const LogLineStdout = LogLineBase.extend({\n stream: z.literal(\"stdout\"),\n});\nexport const LogLineStderr = LogLineBase.extend({\n stream: z.literal(\"stderr\"),\n});\n\nexport const LogError = z.object({\n stream: z.literal(\"error\"),\n data: z.object({\n code: z.string(),\n message: z.string(),\n }),\n});\n\nexport const LogLine = z.discriminatedUnion(\"stream\", [\n LogLineStdout,\n LogLineStderr,\n LogError,\n]);\nexport type LogLineData = z.infer<typeof LogLine>;\nexport type LogOutputLine = Exclude<LogLineData, z.infer<typeof LogError>>;\n\nexport const SnapshotsResponse = z.object({\n snapshots: z.array(Snapshot),\n pagination: CursorPagination,\n});\n\nexport const SnapshotTreeNode = z.object({\n snapshot: Snapshot,\n siblings: z.array(Snapshot),\n count: z.string(),\n});\n\nexport type SnapshotTreeNodeData = z.infer<typeof SnapshotTreeNode>;\n\nexport const SnapshotTreeResponse = z.object({\n snapshots: z.array(SnapshotTreeNode),\n anchor: SnapshotTreeNode.optional(),\n pagination: CursorPagination,\n});\n\nexport const CreateSnapshotResponse = z.object({\n snapshot: Snapshot,\n session: Session.passthrough(),\n});\n\nexport const SnapshotResponse = z.object({\n snapshot: Snapshot,\n});\n\nexport const Drive = z.object({\n name: z.string(),\n projectId: z.string(),\n region: z.string(),\n maxSizeBytes: z.number(),\n currentSessionId: z.string().optional(),\n currentSandboxName: z.string().optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n});\n\nexport type DriveMetadata = z.infer<typeof Drive>;\n\nexport const DrivesResponse = z.object({\n drives: z.array(Drive),\n pagination: CursorPagination,\n});\n\nexport const DriveResponse = z.object({\n drive: Drive,\n});\n\nexport const Sandbox = z.object({\n name: z.string(),\n persistent: z.boolean(),\n region: z.string().optional(),\n failoverRegions: z.array(z.string()).optional(),\n vcpus: z.number().optional(),\n memory: z.number().optional(),\n runtime: z.string().optional(),\n image: z.string().optional(),\n timeout: z.number().optional(),\n networkPolicy: NetworkPolicyResponseValidator.optional(),\n totalEgressBytes: z.number().optional(),\n totalIngressBytes: z.number().optional(),\n totalActiveCpuDurationMs: z.number().optional(),\n totalDurationMs: z.number().optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n expiresAt: z.number().optional(),\n currentSessionId: z.string(),\n currentSnapshotId: z.string().optional(),\n status: Session.shape.status,\n statusUpdatedAt: z.number().optional(),\n cwd: z.string().optional(),\n tags: z.record(z.string(), z.string()).optional(),\n mounts: z\n .record(\n z.string(),\n z.object({\n drive: z.string(),\n mode: z.enum([\"read-only\", \"read-write\"]).optional(),\n }),\n )\n .optional(),\n snapshotExpiration: z.number().optional(),\n keepLastSnapshots: z\n .object({\n count: z.number(),\n expiration: z.number().optional(),\n deleteEvicted: z.boolean().optional(),\n })\n .optional(),\n});\n\nexport type SandboxMetaData = z.infer<typeof Sandbox>;\n\nexport const StopSessionResponse = z.object({\n session: Session.passthrough(),\n sandbox: Sandbox.optional(),\n snapshot: Snapshot.optional(),\n});\n\nexport const SandboxAndSessionResponse = z.object({\n sandbox: Sandbox,\n session: Session.passthrough(),\n routes: z.array(SandboxRoute),\n resumed: z.boolean().optional(),\n});\n\nexport const SandboxesPaginationResponse = z.object({\n sandboxes: z.array(Sandbox),\n pagination: CursorPagination,\n});\n\nexport const UpdateSandboxResponse = z.object({\n sandbox: Sandbox,\n routes: z.array(SandboxRoute).optional(),\n});\n"],"mappings":"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"} |
+10
-1
| //#region src/constants.d.ts | ||
| type RUNTIMES = "node26" | "node24" | "node22" | "python3.13"; | ||
| type ManagedImage = "universal" | "node:22" | "node:24" | "node:26" | "python:3.14" | "ubuntu" | "arch"; | ||
| /** | ||
| * Regions a sandbox, snapshot, or drive can live in. More regions may | ||
| * become available, so any other region string is accepted too. | ||
| */ | ||
| type SandboxRegion = "iad1" | "sfo1" | "cle1" | "cdg1" | (string & {}); | ||
| /** | ||
| * Region a sandbox runs in when none is requested. | ||
| */ | ||
| declare const DEFAULT_SANDBOX_REGION = "iad1"; | ||
| //#endregion | ||
| export { ManagedImage, RUNTIMES }; | ||
| export { DEFAULT_SANDBOX_REGION, ManagedImage, RUNTIMES, SandboxRegion }; | ||
| //# sourceMappingURL=constants.d.cts.map |
+10
-1
| //#region src/constants.d.ts | ||
| type RUNTIMES = "node26" | "node24" | "node22" | "python3.13"; | ||
| type ManagedImage = "universal" | "node:22" | "node:24" | "node:26" | "python:3.14" | "ubuntu" | "arch"; | ||
| /** | ||
| * Regions a sandbox, snapshot, or drive can live in. More regions may | ||
| * become available, so any other region string is accepted too. | ||
| */ | ||
| type SandboxRegion = "iad1" | "sfo1" | "cle1" | "cdg1" | (string & {}); | ||
| /** | ||
| * Region a sandbox runs in when none is requested. | ||
| */ | ||
| declare const DEFAULT_SANDBOX_REGION = "iad1"; | ||
| //#endregion | ||
| export { ManagedImage, RUNTIMES }; | ||
| export { DEFAULT_SANDBOX_REGION, ManagedImage, RUNTIMES, SandboxRegion }; | ||
| //# sourceMappingURL=constants.d.ts.map |
+8
-0
@@ -5,2 +5,3 @@ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs'); | ||
| const require_get_credentials = require('./utils/get-credentials.cjs'); | ||
| const require_constants = require('./constants.cjs'); | ||
| const require_paginator = require('./utils/paginator.cjs'); | ||
@@ -45,2 +46,8 @@ let __workflow_serde = require("@workflow/serde"); | ||
| /** | ||
| * The region where the drive data is stored. | ||
| */ | ||
| get region() { | ||
| return this.drive.region ?? require_constants.DEFAULT_SANDBOX_REGION; | ||
| } | ||
| /** | ||
| * The maximum drive size in bytes. | ||
@@ -170,2 +177,3 @@ */ | ||
| name: params.name, | ||
| region: params.region, | ||
| maxSizeBytes: params.maxSize, | ||
@@ -172,0 +180,0 @@ signal: params.signal |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"drive.cjs","names":["getCredentials","APIClient","WORKFLOW_SERIALIZE","WORKFLOW_DESERIALIZE","attachPaginator"],"sources":["../src/drive.ts"],"sourcesContent":["import { WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE } from \"@workflow/serde\";\nimport type { WithFetchOptions } from \"./api-client/api-client.js\";\nimport type { DriveMetadata } from \"./api-client/index.js\";\nimport { APIClient } from \"./api-client/index.js\";\nimport { type Credentials, getCredentials } from \"./utils/get-credentials.js\";\nimport { attachPaginator } from \"./utils/paginator.js\";\n\nexport interface SerializedDrive {\n drive: DriveMetadata;\n projectId?: string;\n}\n\n/** @inline */\ninterface GetOrCreateDriveParams {\n /**\n * The name of the drive to get or create. Must be unique within the project.\n */\n name: string;\n /**\n * Maximum drive size in bytes. If omitted, a default of 100 GiB is used.\n */\n maxSize?: number;\n /**\n * An AbortSignal to cancel the operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * A Drive is a persistent, bottomless storage that can be attached and detached to Sandboxes.\n * Drives can be mounted as read-write or read-only, at a configurable path with `Sandbox.create()`.\n *\n * Use {@link Drive.getOrCreate} to construct.\n * @hideconstructor\n */\nexport class Drive {\n private _client: APIClient | null = null;\n private drive: DriveMetadata;\n private readonly _projectId: string;\n\n /**\n * Lazily resolve credentials and construct an API client.\n * @internal\n */\n private async ensureClient(): Promise<APIClient> {\n \"use step\";\n if (this._client) return this._client;\n const credentials = await getCredentials();\n this._client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n });\n return this._client;\n }\n\n /**\n * The name of the drive.\n */\n public get name(): string {\n return this.drive.name;\n }\n\n /**\n * The project ID that owns the drive.\n */\n public get projectId(): string {\n return this._projectId;\n }\n\n /**\n * The maximum drive size in bytes.\n */\n public get maxSize(): number {\n return this.drive.maxSizeBytes;\n }\n\n /**\n * Current session ID the drive is attached to, if any.\n */\n public get currentSessionId(): string | undefined {\n return this.drive.currentSessionId;\n }\n\n /**\n * Current sandbox name the drive is attached to, if any.\n */\n public get currentSandboxName(): string | undefined {\n return this.drive.currentSandboxName;\n }\n\n /**\n * Timestamp when the drive was created.\n */\n public get createdAt(): Date {\n return new Date(this.drive.createdAt);\n }\n\n /**\n * Timestamp when the drive was last updated.\n */\n public get updatedAt(): Date {\n return new Date(this.drive.updatedAt);\n }\n\n /**\n * Serialize a Drive instance to plain data for @workflow/serde.\n *\n * @param instance - The Drive instance to serialize\n * @returns A plain object containing drive metadata\n */\n static [WORKFLOW_SERIALIZE](instance: Drive): SerializedDrive {\n return {\n drive: instance.drive,\n projectId: instance._projectId,\n };\n }\n\n /**\n * Deserialize a Drive from serialized data.\n *\n * The deserialized instance uses the serialized metadata synchronously and\n * lazily creates an API client only when methods perform API requests.\n *\n * @param data - The serialized drive data\n * @returns The reconstructed Drive instance\n */\n static [WORKFLOW_DESERIALIZE](data: SerializedDrive): Drive {\n return new Drive({\n drive: data.drive,\n projectId: data.projectId,\n });\n }\n\n constructor({\n client,\n drive,\n projectId,\n }: {\n client?: APIClient;\n drive: DriveMetadata;\n projectId?: string;\n }) {\n this._client = client ?? null;\n this.drive = drive;\n this._projectId = projectId ?? drive.projectId;\n }\n\n /**\n * Allow to get a list of drives for a team narrowed to the given params.\n * It returns both the drives and the pagination metadata to allow getting\n * the next page of results.\n *\n * The returned object is async-iterable to auto-paginate through all pages:\n *\n * ```ts\n * const result = await Drive.list({ limit: 10 });\n * for await (const drive of result) { ... }\n * // or: await result.toArray();\n * // or: for await (const page of result.pages()) { ... }\n * ```\n */\n static async list(\n params?: Partial<Parameters<APIClient[\"listDrives\"]>[0]> &\n Partial<Credentials> &\n WithFetchOptions,\n ) {\n \"use step\";\n const credentials = await getCredentials(params);\n const client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n fetch: params?.fetch,\n });\n const fetchPage = async (cursor?: string | number) => {\n const response = await client.listDrives({\n ...credentials,\n ...params,\n ...(cursor !== undefined && { cursor }),\n });\n return {\n ...response.json,\n drives: response.json.drives.map(\n (drive) =>\n new Drive({\n client,\n drive,\n projectId: credentials.projectId,\n }),\n ),\n };\n };\n const firstPage = await fetchPage(params?.cursor ?? params?.until);\n return attachPaginator(firstPage, {\n itemsKey: \"drives\",\n fetchNext: fetchPage,\n signal: params?.signal,\n });\n }\n\n /**\n * Retrieve an existing drive, or create a new one if it doesn't exists.\n *\n * @param params - Get/create parameters and optional credentials.\n * @returns A promise resolving to the {@link Drive}.\n */\n static async getOrCreate(\n params: (\n | GetOrCreateDriveParams\n | (GetOrCreateDriveParams & Credentials)\n ) &\n WithFetchOptions,\n ): Promise<Drive> {\n \"use step\";\n const credentials = await getCredentials(params);\n const client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n fetch: params.fetch,\n });\n\n const response = await client.getOrCreateDrive({\n projectId: credentials.projectId,\n name: params.name,\n maxSizeBytes: params.maxSize,\n signal: params.signal,\n });\n\n return new Drive({\n client,\n drive: response.json.drive,\n projectId: credentials.projectId,\n });\n }\n\n /**\n * Delete this drive. The drive must not be attached to any sandbox.\n * This operation is irreversible and will delete all data stored in the drive.\n *\n * @param opts - Optional parameters.\n * @param opts.signal - An AbortSignal to cancel the operation.\n * @returns A promise that resolves once the drive has been deleted.\n */\n async delete(opts?: { signal?: AbortSignal }): Promise<void> {\n \"use step\";\n const client = await this.ensureClient();\n const response = await client.deleteDrive({\n projectId: this._projectId,\n name: this.drive.name,\n signal: opts?.signal,\n });\n\n this.drive = response.json.drive;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAmCA,IAAa,QAAb,MAAa,MAAM;;;;;CASjB,MAAc,eAAmC;AAC/C;AACA,MAAI,KAAK,QAAS,QAAO,KAAK;EAC9B,MAAM,cAAc,MAAMA,wCAAgB;AAC1C,OAAK,UAAU,IAAIC,6BAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACpB,CAAC;AACF,SAAO,KAAK;;;;;CAMd,IAAW,OAAe;AACxB,SAAO,KAAK,MAAM;;;;;CAMpB,IAAW,YAAoB;AAC7B,SAAO,KAAK;;;;;CAMd,IAAW,UAAkB;AAC3B,SAAO,KAAK,MAAM;;;;;CAMpB,IAAW,mBAAuC;AAChD,SAAO,KAAK,MAAM;;;;;CAMpB,IAAW,qBAAyC;AAClD,SAAO,KAAK,MAAM;;;;;CAMpB,IAAW,YAAkB;AAC3B,SAAO,IAAI,KAAK,KAAK,MAAM,UAAU;;;;;CAMvC,IAAW,YAAkB;AAC3B,SAAO,IAAI,KAAK,KAAK,MAAM,UAAU;;;;;;;;CASvC,QAAQC,qCAAoB,UAAkC;AAC5D,SAAO;GACL,OAAO,SAAS;GAChB,WAAW,SAAS;GACrB;;;;;;;;;;;CAYH,QAAQC,uCAAsB,MAA8B;AAC1D,SAAO,IAAI,MAAM;GACf,OAAO,KAAK;GACZ,WAAW,KAAK;GACjB,CAAC;;CAGJ,YAAY,EACV,QACA,OACA,aAKC;OAzGK,UAA4B;AA0GlC,OAAK,UAAU,UAAU;AACzB,OAAK,QAAQ;AACb,OAAK,aAAa,aAAa,MAAM;;;;;;;;;;;;;;;;CAiBvC,aAAa,KACX,QAGA;AACA;EACA,MAAM,cAAc,MAAMH,uCAAe,OAAO;EAChD,MAAM,SAAS,IAAIC,6BAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACnB,OAAO,QAAQ;GAChB,CAAC;EACF,MAAM,YAAY,OAAO,WAA6B;GACpD,MAAM,WAAW,MAAM,OAAO,WAAW;IACvC,GAAG;IACH,GAAG;IACH,GAAI,WAAW,UAAa,EAAE,QAAQ;IACvC,CAAC;AACF,UAAO;IACL,GAAG,SAAS;IACZ,QAAQ,SAAS,KAAK,OAAO,KAC1B,UACC,IAAI,MAAM;KACR;KACA;KACA,WAAW,YAAY;KACxB,CAAC,CACL;IACF;;AAGH,SAAOG,kCADW,MAAM,UAAU,QAAQ,UAAU,QAAQ,MAAM,EAChC;GAChC,UAAU;GACV,WAAW;GACX,QAAQ,QAAQ;GACjB,CAAC;;;;;;;;CASJ,aAAa,YACX,QAKgB;AAChB;EACA,MAAM,cAAc,MAAMJ,uCAAe,OAAO;EAChD,MAAM,SAAS,IAAIC,6BAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACnB,OAAO,OAAO;GACf,CAAC;AASF,SAAO,IAAI,MAAM;GACf;GACA,QATe,MAAM,OAAO,iBAAiB;IAC7C,WAAW,YAAY;IACvB,MAAM,OAAO;IACb,cAAc,OAAO;IACrB,QAAQ,OAAO;IAChB,CAAC,EAIgB,KAAK;GACrB,WAAW,YAAY;GACxB,CAAC;;;;;;;;;;CAWJ,MAAM,OAAO,MAAgD;AAC3D;AAQA,OAAK,SANY,OADF,MAAM,KAAK,cAAc,EACV,YAAY;GACxC,WAAW,KAAK;GAChB,MAAM,KAAK,MAAM;GACjB,QAAQ,MAAM;GACf,CAAC,EAEoB,KAAK"} | ||
| {"version":3,"file":"drive.cjs","names":["getCredentials","APIClient","DEFAULT_SANDBOX_REGION","WORKFLOW_SERIALIZE","WORKFLOW_DESERIALIZE","attachPaginator"],"sources":["../src/drive.ts"],"sourcesContent":["import { WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE } from \"@workflow/serde\";\nimport type { WithFetchOptions } from \"./api-client/api-client.js\";\nimport type { DriveMetadata } from \"./api-client/index.js\";\nimport { APIClient } from \"./api-client/index.js\";\nimport { type Credentials, getCredentials } from \"./utils/get-credentials.js\";\nimport { attachPaginator } from \"./utils/paginator.js\";\nimport { DEFAULT_SANDBOX_REGION, type SandboxRegion } from \"./constants.js\";\n\nexport interface SerializedDrive {\n drive: DriveMetadata;\n projectId?: string;\n}\n\n/** @inline */\ninterface GetOrCreateDriveParams {\n /**\n * The name of the drive to get or create. Must be unique within the project.\n */\n name: string;\n /**\n * The region where the drive is created and stores its data. Defaults to `iad1`.\n * See the Vercel documentation for the available regions.\n */\n region?: SandboxRegion;\n /**\n * Maximum drive size in bytes. If omitted, a default of 100 GiB is used.\n */\n maxSize?: number;\n /**\n * An AbortSignal to cancel the operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * A Drive is a persistent, bottomless storage that can be attached and detached to Sandboxes.\n * Drives can be mounted as read-write or read-only, at a configurable path with `Sandbox.create()`.\n *\n * Use {@link Drive.getOrCreate} to construct.\n * @hideconstructor\n */\nexport class Drive {\n private _client: APIClient | null = null;\n private drive: DriveMetadata;\n private readonly _projectId: string;\n\n /**\n * Lazily resolve credentials and construct an API client.\n * @internal\n */\n private async ensureClient(): Promise<APIClient> {\n \"use step\";\n if (this._client) return this._client;\n const credentials = await getCredentials();\n this._client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n });\n return this._client;\n }\n\n /**\n * The name of the drive.\n */\n public get name(): string {\n return this.drive.name;\n }\n\n /**\n * The project ID that owns the drive.\n */\n public get projectId(): string {\n return this._projectId;\n }\n\n /**\n * The region where the drive data is stored.\n */\n public get region(): string {\n return this.drive.region ?? DEFAULT_SANDBOX_REGION;\n }\n\n /**\n * The maximum drive size in bytes.\n */\n public get maxSize(): number {\n return this.drive.maxSizeBytes;\n }\n\n /**\n * Current session ID the drive is attached to, if any.\n */\n public get currentSessionId(): string | undefined {\n return this.drive.currentSessionId;\n }\n\n /**\n * Current sandbox name the drive is attached to, if any.\n */\n public get currentSandboxName(): string | undefined {\n return this.drive.currentSandboxName;\n }\n\n /**\n * Timestamp when the drive was created.\n */\n public get createdAt(): Date {\n return new Date(this.drive.createdAt);\n }\n\n /**\n * Timestamp when the drive was last updated.\n */\n public get updatedAt(): Date {\n return new Date(this.drive.updatedAt);\n }\n\n /**\n * Serialize a Drive instance to plain data for @workflow/serde.\n *\n * @param instance - The Drive instance to serialize\n * @returns A plain object containing drive metadata\n */\n static [WORKFLOW_SERIALIZE](instance: Drive): SerializedDrive {\n return {\n drive: instance.drive,\n projectId: instance._projectId,\n };\n }\n\n /**\n * Deserialize a Drive from serialized data.\n *\n * The deserialized instance uses the serialized metadata synchronously and\n * lazily creates an API client only when methods perform API requests.\n *\n * @param data - The serialized drive data\n * @returns The reconstructed Drive instance\n */\n static [WORKFLOW_DESERIALIZE](data: SerializedDrive): Drive {\n return new Drive({\n drive: data.drive,\n projectId: data.projectId,\n });\n }\n\n constructor({\n client,\n drive,\n projectId,\n }: {\n client?: APIClient;\n drive: DriveMetadata;\n projectId?: string;\n }) {\n this._client = client ?? null;\n this.drive = drive;\n this._projectId = projectId ?? drive.projectId;\n }\n\n /**\n * Allow to get a list of drives for a team narrowed to the given params.\n * It returns both the drives and the pagination metadata to allow getting\n * the next page of results.\n *\n * The returned object is async-iterable to auto-paginate through all pages:\n *\n * ```ts\n * const result = await Drive.list({ limit: 10 });\n * for await (const drive of result) { ... }\n * // or: await result.toArray();\n * // or: for await (const page of result.pages()) { ... }\n * ```\n */\n static async list(\n params?: Partial<Parameters<APIClient[\"listDrives\"]>[0]> &\n Partial<Credentials> &\n WithFetchOptions,\n ) {\n \"use step\";\n const credentials = await getCredentials(params);\n const client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n fetch: params?.fetch,\n });\n const fetchPage = async (cursor?: string | number) => {\n const response = await client.listDrives({\n ...credentials,\n ...params,\n ...(cursor !== undefined && { cursor }),\n });\n return {\n ...response.json,\n drives: response.json.drives.map(\n (drive) =>\n new Drive({\n client,\n drive,\n projectId: credentials.projectId,\n }),\n ),\n };\n };\n const firstPage = await fetchPage(params?.cursor ?? params?.until);\n return attachPaginator(firstPage, {\n itemsKey: \"drives\",\n fetchNext: fetchPage,\n signal: params?.signal,\n });\n }\n\n /**\n * Retrieve an existing drive, or create a new one if it doesn't exists.\n *\n * @param params - Get/create parameters and optional credentials.\n * @returns A promise resolving to the {@link Drive}.\n */\n static async getOrCreate(\n params: (GetOrCreateDriveParams | (GetOrCreateDriveParams & Credentials)) &\n WithFetchOptions,\n ): Promise<Drive> {\n \"use step\";\n const credentials = await getCredentials(params);\n const client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n fetch: params.fetch,\n });\n\n const response = await client.getOrCreateDrive({\n projectId: credentials.projectId,\n name: params.name,\n region: params.region,\n maxSizeBytes: params.maxSize,\n signal: params.signal,\n });\n\n return new Drive({\n client,\n drive: response.json.drive,\n projectId: credentials.projectId,\n });\n }\n\n /**\n * Delete this drive. The drive must not be attached to any sandbox.\n * This operation is irreversible and will delete all data stored in the drive.\n *\n * @param opts - Optional parameters.\n * @param opts.signal - An AbortSignal to cancel the operation.\n * @returns A promise that resolves once the drive has been deleted.\n */\n async delete(opts?: { signal?: AbortSignal }): Promise<void> {\n \"use step\";\n const client = await this.ensureClient();\n const response = await client.deleteDrive({\n projectId: this._projectId,\n name: this.drive.name,\n signal: opts?.signal,\n });\n\n this.drive = response.json.drive;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAyCA,IAAa,QAAb,MAAa,MAAM;;;;;CASjB,MAAc,eAAmC;AAC/C;AACA,MAAI,KAAK,QAAS,QAAO,KAAK;EAC9B,MAAM,cAAc,MAAMA,wCAAgB;AAC1C,OAAK,UAAU,IAAIC,6BAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACpB,CAAC;AACF,SAAO,KAAK;;;;;CAMd,IAAW,OAAe;AACxB,SAAO,KAAK,MAAM;;;;;CAMpB,IAAW,YAAoB;AAC7B,SAAO,KAAK;;;;;CAMd,IAAW,SAAiB;AAC1B,SAAO,KAAK,MAAM,UAAUC;;;;;CAM9B,IAAW,UAAkB;AAC3B,SAAO,KAAK,MAAM;;;;;CAMpB,IAAW,mBAAuC;AAChD,SAAO,KAAK,MAAM;;;;;CAMpB,IAAW,qBAAyC;AAClD,SAAO,KAAK,MAAM;;;;;CAMpB,IAAW,YAAkB;AAC3B,SAAO,IAAI,KAAK,KAAK,MAAM,UAAU;;;;;CAMvC,IAAW,YAAkB;AAC3B,SAAO,IAAI,KAAK,KAAK,MAAM,UAAU;;;;;;;;CASvC,QAAQC,qCAAoB,UAAkC;AAC5D,SAAO;GACL,OAAO,SAAS;GAChB,WAAW,SAAS;GACrB;;;;;;;;;;;CAYH,QAAQC,uCAAsB,MAA8B;AAC1D,SAAO,IAAI,MAAM;GACf,OAAO,KAAK;GACZ,WAAW,KAAK;GACjB,CAAC;;CAGJ,YAAY,EACV,QACA,OACA,aAKC;OAhHK,UAA4B;AAiHlC,OAAK,UAAU,UAAU;AACzB,OAAK,QAAQ;AACb,OAAK,aAAa,aAAa,MAAM;;;;;;;;;;;;;;;;CAiBvC,aAAa,KACX,QAGA;AACA;EACA,MAAM,cAAc,MAAMJ,uCAAe,OAAO;EAChD,MAAM,SAAS,IAAIC,6BAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACnB,OAAO,QAAQ;GAChB,CAAC;EACF,MAAM,YAAY,OAAO,WAA6B;GACpD,MAAM,WAAW,MAAM,OAAO,WAAW;IACvC,GAAG;IACH,GAAG;IACH,GAAI,WAAW,UAAa,EAAE,QAAQ;IACvC,CAAC;AACF,UAAO;IACL,GAAG,SAAS;IACZ,QAAQ,SAAS,KAAK,OAAO,KAC1B,UACC,IAAI,MAAM;KACR;KACA;KACA,WAAW,YAAY;KACxB,CAAC,CACL;IACF;;AAGH,SAAOI,kCADW,MAAM,UAAU,QAAQ,UAAU,QAAQ,MAAM,EAChC;GAChC,UAAU;GACV,WAAW;GACX,QAAQ,QAAQ;GACjB,CAAC;;;;;;;;CASJ,aAAa,YACX,QAEgB;AAChB;EACA,MAAM,cAAc,MAAML,uCAAe,OAAO;EAChD,MAAM,SAAS,IAAIC,6BAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACnB,OAAO,OAAO;GACf,CAAC;AAUF,SAAO,IAAI,MAAM;GACf;GACA,QAVe,MAAM,OAAO,iBAAiB;IAC7C,WAAW,YAAY;IACvB,MAAM,OAAO;IACb,QAAQ,OAAO;IACf,cAAc,OAAO;IACrB,QAAQ,OAAO;IAChB,CAAC,EAIgB,KAAK;GACrB,WAAW,YAAY;GACxB,CAAC;;;;;;;;;;CAWJ,MAAM,OAAO,MAAgD;AAC3D;AAQA,OAAK,SANY,OADF,MAAM,KAAK,cAAc,EACV,YAAY;GACxC,WAAW,KAAK;GAChB,MAAM,KAAK,MAAM;GACjB,QAAQ,MAAM;GACf,CAAC,EAEoB,KAAK"} |
+10
-0
| import { Paginator } from "./utils/paginator.cjs"; | ||
| import { DriveMetadata } from "./api-client/validators.cjs"; | ||
| import { SandboxRegion } from "./constants.cjs"; | ||
| import { APIClient, WithFetchOptions } from "./api-client/api-client.cjs"; | ||
@@ -19,2 +20,7 @@ import { Credentials } from "./utils/get-credentials.cjs"; | ||
| /** | ||
| * The region where the drive is created and stores its data. Defaults to `iad1`. | ||
| * See the Vercel documentation for the available regions. | ||
| */ | ||
| region?: SandboxRegion; | ||
| /** | ||
| * Maximum drive size in bytes. If omitted, a default of 100 GiB is used. | ||
@@ -53,2 +59,6 @@ */ | ||
| /** | ||
| * The region where the drive data is stored. | ||
| */ | ||
| get region(): string; | ||
| /** | ||
| * The maximum drive size in bytes. | ||
@@ -55,0 +65,0 @@ */ |
+10
-0
| import { Paginator } from "./utils/paginator.js"; | ||
| import { DriveMetadata } from "./api-client/validators.js"; | ||
| import { SandboxRegion } from "./constants.js"; | ||
| import { APIClient, WithFetchOptions } from "./api-client/api-client.js"; | ||
@@ -20,2 +21,7 @@ import "./api-client/index.js"; | ||
| /** | ||
| * The region where the drive is created and stores its data. Defaults to `iad1`. | ||
| * See the Vercel documentation for the available regions. | ||
| */ | ||
| region?: SandboxRegion; | ||
| /** | ||
| * Maximum drive size in bytes. If omitted, a default of 100 GiB is used. | ||
@@ -54,2 +60,6 @@ */ | ||
| /** | ||
| * The region where the drive data is stored. | ||
| */ | ||
| get region(): string; | ||
| /** | ||
| * The maximum drive size in bytes. | ||
@@ -56,0 +66,0 @@ */ |
+8
-0
| import { APIClient } from "./api-client/api-client.js"; | ||
| import "./api-client/index.js"; | ||
| import { getCredentials } from "./utils/get-credentials.js"; | ||
| import { DEFAULT_SANDBOX_REGION } from "./constants.js"; | ||
| import { attachPaginator } from "./utils/paginator.js"; | ||
@@ -43,2 +44,8 @@ import { WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE } from "@workflow/serde"; | ||
| /** | ||
| * The region where the drive data is stored. | ||
| */ | ||
| get region() { | ||
| return this.drive.region ?? DEFAULT_SANDBOX_REGION; | ||
| } | ||
| /** | ||
| * The maximum drive size in bytes. | ||
@@ -168,2 +175,3 @@ */ | ||
| name: params.name, | ||
| region: params.region, | ||
| maxSizeBytes: params.maxSize, | ||
@@ -170,0 +178,0 @@ signal: params.signal |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"drive.js","names":[],"sources":["../src/drive.ts"],"sourcesContent":["import { WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE } from \"@workflow/serde\";\nimport type { WithFetchOptions } from \"./api-client/api-client.js\";\nimport type { DriveMetadata } from \"./api-client/index.js\";\nimport { APIClient } from \"./api-client/index.js\";\nimport { type Credentials, getCredentials } from \"./utils/get-credentials.js\";\nimport { attachPaginator } from \"./utils/paginator.js\";\n\nexport interface SerializedDrive {\n drive: DriveMetadata;\n projectId?: string;\n}\n\n/** @inline */\ninterface GetOrCreateDriveParams {\n /**\n * The name of the drive to get or create. Must be unique within the project.\n */\n name: string;\n /**\n * Maximum drive size in bytes. If omitted, a default of 100 GiB is used.\n */\n maxSize?: number;\n /**\n * An AbortSignal to cancel the operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * A Drive is a persistent, bottomless storage that can be attached and detached to Sandboxes.\n * Drives can be mounted as read-write or read-only, at a configurable path with `Sandbox.create()`.\n *\n * Use {@link Drive.getOrCreate} to construct.\n * @hideconstructor\n */\nexport class Drive {\n private _client: APIClient | null = null;\n private drive: DriveMetadata;\n private readonly _projectId: string;\n\n /**\n * Lazily resolve credentials and construct an API client.\n * @internal\n */\n private async ensureClient(): Promise<APIClient> {\n \"use step\";\n if (this._client) return this._client;\n const credentials = await getCredentials();\n this._client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n });\n return this._client;\n }\n\n /**\n * The name of the drive.\n */\n public get name(): string {\n return this.drive.name;\n }\n\n /**\n * The project ID that owns the drive.\n */\n public get projectId(): string {\n return this._projectId;\n }\n\n /**\n * The maximum drive size in bytes.\n */\n public get maxSize(): number {\n return this.drive.maxSizeBytes;\n }\n\n /**\n * Current session ID the drive is attached to, if any.\n */\n public get currentSessionId(): string | undefined {\n return this.drive.currentSessionId;\n }\n\n /**\n * Current sandbox name the drive is attached to, if any.\n */\n public get currentSandboxName(): string | undefined {\n return this.drive.currentSandboxName;\n }\n\n /**\n * Timestamp when the drive was created.\n */\n public get createdAt(): Date {\n return new Date(this.drive.createdAt);\n }\n\n /**\n * Timestamp when the drive was last updated.\n */\n public get updatedAt(): Date {\n return new Date(this.drive.updatedAt);\n }\n\n /**\n * Serialize a Drive instance to plain data for @workflow/serde.\n *\n * @param instance - The Drive instance to serialize\n * @returns A plain object containing drive metadata\n */\n static [WORKFLOW_SERIALIZE](instance: Drive): SerializedDrive {\n return {\n drive: instance.drive,\n projectId: instance._projectId,\n };\n }\n\n /**\n * Deserialize a Drive from serialized data.\n *\n * The deserialized instance uses the serialized metadata synchronously and\n * lazily creates an API client only when methods perform API requests.\n *\n * @param data - The serialized drive data\n * @returns The reconstructed Drive instance\n */\n static [WORKFLOW_DESERIALIZE](data: SerializedDrive): Drive {\n return new Drive({\n drive: data.drive,\n projectId: data.projectId,\n });\n }\n\n constructor({\n client,\n drive,\n projectId,\n }: {\n client?: APIClient;\n drive: DriveMetadata;\n projectId?: string;\n }) {\n this._client = client ?? null;\n this.drive = drive;\n this._projectId = projectId ?? drive.projectId;\n }\n\n /**\n * Allow to get a list of drives for a team narrowed to the given params.\n * It returns both the drives and the pagination metadata to allow getting\n * the next page of results.\n *\n * The returned object is async-iterable to auto-paginate through all pages:\n *\n * ```ts\n * const result = await Drive.list({ limit: 10 });\n * for await (const drive of result) { ... }\n * // or: await result.toArray();\n * // or: for await (const page of result.pages()) { ... }\n * ```\n */\n static async list(\n params?: Partial<Parameters<APIClient[\"listDrives\"]>[0]> &\n Partial<Credentials> &\n WithFetchOptions,\n ) {\n \"use step\";\n const credentials = await getCredentials(params);\n const client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n fetch: params?.fetch,\n });\n const fetchPage = async (cursor?: string | number) => {\n const response = await client.listDrives({\n ...credentials,\n ...params,\n ...(cursor !== undefined && { cursor }),\n });\n return {\n ...response.json,\n drives: response.json.drives.map(\n (drive) =>\n new Drive({\n client,\n drive,\n projectId: credentials.projectId,\n }),\n ),\n };\n };\n const firstPage = await fetchPage(params?.cursor ?? params?.until);\n return attachPaginator(firstPage, {\n itemsKey: \"drives\",\n fetchNext: fetchPage,\n signal: params?.signal,\n });\n }\n\n /**\n * Retrieve an existing drive, or create a new one if it doesn't exists.\n *\n * @param params - Get/create parameters and optional credentials.\n * @returns A promise resolving to the {@link Drive}.\n */\n static async getOrCreate(\n params: (\n | GetOrCreateDriveParams\n | (GetOrCreateDriveParams & Credentials)\n ) &\n WithFetchOptions,\n ): Promise<Drive> {\n \"use step\";\n const credentials = await getCredentials(params);\n const client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n fetch: params.fetch,\n });\n\n const response = await client.getOrCreateDrive({\n projectId: credentials.projectId,\n name: params.name,\n maxSizeBytes: params.maxSize,\n signal: params.signal,\n });\n\n return new Drive({\n client,\n drive: response.json.drive,\n projectId: credentials.projectId,\n });\n }\n\n /**\n * Delete this drive. The drive must not be attached to any sandbox.\n * This operation is irreversible and will delete all data stored in the drive.\n *\n * @param opts - Optional parameters.\n * @param opts.signal - An AbortSignal to cancel the operation.\n * @returns A promise that resolves once the drive has been deleted.\n */\n async delete(opts?: { signal?: AbortSignal }): Promise<void> {\n \"use step\";\n const client = await this.ensureClient();\n const response = await client.deleteDrive({\n projectId: this._projectId,\n name: this.drive.name,\n signal: opts?.signal,\n });\n\n this.drive = response.json.drive;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAmCA,IAAa,QAAb,MAAa,MAAM;;;;;CASjB,MAAc,eAAmC;AAC/C;AACA,MAAI,KAAK,QAAS,QAAO,KAAK;EAC9B,MAAM,cAAc,MAAM,gBAAgB;AAC1C,OAAK,UAAU,IAAI,UAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACpB,CAAC;AACF,SAAO,KAAK;;;;;CAMd,IAAW,OAAe;AACxB,SAAO,KAAK,MAAM;;;;;CAMpB,IAAW,YAAoB;AAC7B,SAAO,KAAK;;;;;CAMd,IAAW,UAAkB;AAC3B,SAAO,KAAK,MAAM;;;;;CAMpB,IAAW,mBAAuC;AAChD,SAAO,KAAK,MAAM;;;;;CAMpB,IAAW,qBAAyC;AAClD,SAAO,KAAK,MAAM;;;;;CAMpB,IAAW,YAAkB;AAC3B,SAAO,IAAI,KAAK,KAAK,MAAM,UAAU;;;;;CAMvC,IAAW,YAAkB;AAC3B,SAAO,IAAI,KAAK,KAAK,MAAM,UAAU;;;;;;;;CASvC,QAAQ,oBAAoB,UAAkC;AAC5D,SAAO;GACL,OAAO,SAAS;GAChB,WAAW,SAAS;GACrB;;;;;;;;;;;CAYH,QAAQ,sBAAsB,MAA8B;AAC1D,SAAO,IAAI,MAAM;GACf,OAAO,KAAK;GACZ,WAAW,KAAK;GACjB,CAAC;;CAGJ,YAAY,EACV,QACA,OACA,aAKC;OAzGK,UAA4B;AA0GlC,OAAK,UAAU,UAAU;AACzB,OAAK,QAAQ;AACb,OAAK,aAAa,aAAa,MAAM;;;;;;;;;;;;;;;;CAiBvC,aAAa,KACX,QAGA;AACA;EACA,MAAM,cAAc,MAAM,eAAe,OAAO;EAChD,MAAM,SAAS,IAAI,UAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACnB,OAAO,QAAQ;GAChB,CAAC;EACF,MAAM,YAAY,OAAO,WAA6B;GACpD,MAAM,WAAW,MAAM,OAAO,WAAW;IACvC,GAAG;IACH,GAAG;IACH,GAAI,WAAW,UAAa,EAAE,QAAQ;IACvC,CAAC;AACF,UAAO;IACL,GAAG,SAAS;IACZ,QAAQ,SAAS,KAAK,OAAO,KAC1B,UACC,IAAI,MAAM;KACR;KACA;KACA,WAAW,YAAY;KACxB,CAAC,CACL;IACF;;AAGH,SAAO,gBADW,MAAM,UAAU,QAAQ,UAAU,QAAQ,MAAM,EAChC;GAChC,UAAU;GACV,WAAW;GACX,QAAQ,QAAQ;GACjB,CAAC;;;;;;;;CASJ,aAAa,YACX,QAKgB;AAChB;EACA,MAAM,cAAc,MAAM,eAAe,OAAO;EAChD,MAAM,SAAS,IAAI,UAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACnB,OAAO,OAAO;GACf,CAAC;AASF,SAAO,IAAI,MAAM;GACf;GACA,QATe,MAAM,OAAO,iBAAiB;IAC7C,WAAW,YAAY;IACvB,MAAM,OAAO;IACb,cAAc,OAAO;IACrB,QAAQ,OAAO;IAChB,CAAC,EAIgB,KAAK;GACrB,WAAW,YAAY;GACxB,CAAC;;;;;;;;;;CAWJ,MAAM,OAAO,MAAgD;AAC3D;AAQA,OAAK,SANY,OADF,MAAM,KAAK,cAAc,EACV,YAAY;GACxC,WAAW,KAAK;GAChB,MAAM,KAAK,MAAM;GACjB,QAAQ,MAAM;GACf,CAAC,EAEoB,KAAK"} | ||
| {"version":3,"file":"drive.js","names":[],"sources":["../src/drive.ts"],"sourcesContent":["import { WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE } from \"@workflow/serde\";\nimport type { WithFetchOptions } from \"./api-client/api-client.js\";\nimport type { DriveMetadata } from \"./api-client/index.js\";\nimport { APIClient } from \"./api-client/index.js\";\nimport { type Credentials, getCredentials } from \"./utils/get-credentials.js\";\nimport { attachPaginator } from \"./utils/paginator.js\";\nimport { DEFAULT_SANDBOX_REGION, type SandboxRegion } from \"./constants.js\";\n\nexport interface SerializedDrive {\n drive: DriveMetadata;\n projectId?: string;\n}\n\n/** @inline */\ninterface GetOrCreateDriveParams {\n /**\n * The name of the drive to get or create. Must be unique within the project.\n */\n name: string;\n /**\n * The region where the drive is created and stores its data. Defaults to `iad1`.\n * See the Vercel documentation for the available regions.\n */\n region?: SandboxRegion;\n /**\n * Maximum drive size in bytes. If omitted, a default of 100 GiB is used.\n */\n maxSize?: number;\n /**\n * An AbortSignal to cancel the operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * A Drive is a persistent, bottomless storage that can be attached and detached to Sandboxes.\n * Drives can be mounted as read-write or read-only, at a configurable path with `Sandbox.create()`.\n *\n * Use {@link Drive.getOrCreate} to construct.\n * @hideconstructor\n */\nexport class Drive {\n private _client: APIClient | null = null;\n private drive: DriveMetadata;\n private readonly _projectId: string;\n\n /**\n * Lazily resolve credentials and construct an API client.\n * @internal\n */\n private async ensureClient(): Promise<APIClient> {\n \"use step\";\n if (this._client) return this._client;\n const credentials = await getCredentials();\n this._client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n });\n return this._client;\n }\n\n /**\n * The name of the drive.\n */\n public get name(): string {\n return this.drive.name;\n }\n\n /**\n * The project ID that owns the drive.\n */\n public get projectId(): string {\n return this._projectId;\n }\n\n /**\n * The region where the drive data is stored.\n */\n public get region(): string {\n return this.drive.region ?? DEFAULT_SANDBOX_REGION;\n }\n\n /**\n * The maximum drive size in bytes.\n */\n public get maxSize(): number {\n return this.drive.maxSizeBytes;\n }\n\n /**\n * Current session ID the drive is attached to, if any.\n */\n public get currentSessionId(): string | undefined {\n return this.drive.currentSessionId;\n }\n\n /**\n * Current sandbox name the drive is attached to, if any.\n */\n public get currentSandboxName(): string | undefined {\n return this.drive.currentSandboxName;\n }\n\n /**\n * Timestamp when the drive was created.\n */\n public get createdAt(): Date {\n return new Date(this.drive.createdAt);\n }\n\n /**\n * Timestamp when the drive was last updated.\n */\n public get updatedAt(): Date {\n return new Date(this.drive.updatedAt);\n }\n\n /**\n * Serialize a Drive instance to plain data for @workflow/serde.\n *\n * @param instance - The Drive instance to serialize\n * @returns A plain object containing drive metadata\n */\n static [WORKFLOW_SERIALIZE](instance: Drive): SerializedDrive {\n return {\n drive: instance.drive,\n projectId: instance._projectId,\n };\n }\n\n /**\n * Deserialize a Drive from serialized data.\n *\n * The deserialized instance uses the serialized metadata synchronously and\n * lazily creates an API client only when methods perform API requests.\n *\n * @param data - The serialized drive data\n * @returns The reconstructed Drive instance\n */\n static [WORKFLOW_DESERIALIZE](data: SerializedDrive): Drive {\n return new Drive({\n drive: data.drive,\n projectId: data.projectId,\n });\n }\n\n constructor({\n client,\n drive,\n projectId,\n }: {\n client?: APIClient;\n drive: DriveMetadata;\n projectId?: string;\n }) {\n this._client = client ?? null;\n this.drive = drive;\n this._projectId = projectId ?? drive.projectId;\n }\n\n /**\n * Allow to get a list of drives for a team narrowed to the given params.\n * It returns both the drives and the pagination metadata to allow getting\n * the next page of results.\n *\n * The returned object is async-iterable to auto-paginate through all pages:\n *\n * ```ts\n * const result = await Drive.list({ limit: 10 });\n * for await (const drive of result) { ... }\n * // or: await result.toArray();\n * // or: for await (const page of result.pages()) { ... }\n * ```\n */\n static async list(\n params?: Partial<Parameters<APIClient[\"listDrives\"]>[0]> &\n Partial<Credentials> &\n WithFetchOptions,\n ) {\n \"use step\";\n const credentials = await getCredentials(params);\n const client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n fetch: params?.fetch,\n });\n const fetchPage = async (cursor?: string | number) => {\n const response = await client.listDrives({\n ...credentials,\n ...params,\n ...(cursor !== undefined && { cursor }),\n });\n return {\n ...response.json,\n drives: response.json.drives.map(\n (drive) =>\n new Drive({\n client,\n drive,\n projectId: credentials.projectId,\n }),\n ),\n };\n };\n const firstPage = await fetchPage(params?.cursor ?? params?.until);\n return attachPaginator(firstPage, {\n itemsKey: \"drives\",\n fetchNext: fetchPage,\n signal: params?.signal,\n });\n }\n\n /**\n * Retrieve an existing drive, or create a new one if it doesn't exists.\n *\n * @param params - Get/create parameters and optional credentials.\n * @returns A promise resolving to the {@link Drive}.\n */\n static async getOrCreate(\n params: (GetOrCreateDriveParams | (GetOrCreateDriveParams & Credentials)) &\n WithFetchOptions,\n ): Promise<Drive> {\n \"use step\";\n const credentials = await getCredentials(params);\n const client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n fetch: params.fetch,\n });\n\n const response = await client.getOrCreateDrive({\n projectId: credentials.projectId,\n name: params.name,\n region: params.region,\n maxSizeBytes: params.maxSize,\n signal: params.signal,\n });\n\n return new Drive({\n client,\n drive: response.json.drive,\n projectId: credentials.projectId,\n });\n }\n\n /**\n * Delete this drive. The drive must not be attached to any sandbox.\n * This operation is irreversible and will delete all data stored in the drive.\n *\n * @param opts - Optional parameters.\n * @param opts.signal - An AbortSignal to cancel the operation.\n * @returns A promise that resolves once the drive has been deleted.\n */\n async delete(opts?: { signal?: AbortSignal }): Promise<void> {\n \"use step\";\n const client = await this.ensureClient();\n const response = await client.deleteDrive({\n projectId: this._projectId,\n name: this.drive.name,\n signal: opts?.signal,\n });\n\n this.drive = response.json.drive;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAyCA,IAAa,QAAb,MAAa,MAAM;;;;;CASjB,MAAc,eAAmC;AAC/C;AACA,MAAI,KAAK,QAAS,QAAO,KAAK;EAC9B,MAAM,cAAc,MAAM,gBAAgB;AAC1C,OAAK,UAAU,IAAI,UAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACpB,CAAC;AACF,SAAO,KAAK;;;;;CAMd,IAAW,OAAe;AACxB,SAAO,KAAK,MAAM;;;;;CAMpB,IAAW,YAAoB;AAC7B,SAAO,KAAK;;;;;CAMd,IAAW,SAAiB;AAC1B,SAAO,KAAK,MAAM,UAAU;;;;;CAM9B,IAAW,UAAkB;AAC3B,SAAO,KAAK,MAAM;;;;;CAMpB,IAAW,mBAAuC;AAChD,SAAO,KAAK,MAAM;;;;;CAMpB,IAAW,qBAAyC;AAClD,SAAO,KAAK,MAAM;;;;;CAMpB,IAAW,YAAkB;AAC3B,SAAO,IAAI,KAAK,KAAK,MAAM,UAAU;;;;;CAMvC,IAAW,YAAkB;AAC3B,SAAO,IAAI,KAAK,KAAK,MAAM,UAAU;;;;;;;;CASvC,QAAQ,oBAAoB,UAAkC;AAC5D,SAAO;GACL,OAAO,SAAS;GAChB,WAAW,SAAS;GACrB;;;;;;;;;;;CAYH,QAAQ,sBAAsB,MAA8B;AAC1D,SAAO,IAAI,MAAM;GACf,OAAO,KAAK;GACZ,WAAW,KAAK;GACjB,CAAC;;CAGJ,YAAY,EACV,QACA,OACA,aAKC;OAhHK,UAA4B;AAiHlC,OAAK,UAAU,UAAU;AACzB,OAAK,QAAQ;AACb,OAAK,aAAa,aAAa,MAAM;;;;;;;;;;;;;;;;CAiBvC,aAAa,KACX,QAGA;AACA;EACA,MAAM,cAAc,MAAM,eAAe,OAAO;EAChD,MAAM,SAAS,IAAI,UAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACnB,OAAO,QAAQ;GAChB,CAAC;EACF,MAAM,YAAY,OAAO,WAA6B;GACpD,MAAM,WAAW,MAAM,OAAO,WAAW;IACvC,GAAG;IACH,GAAG;IACH,GAAI,WAAW,UAAa,EAAE,QAAQ;IACvC,CAAC;AACF,UAAO;IACL,GAAG,SAAS;IACZ,QAAQ,SAAS,KAAK,OAAO,KAC1B,UACC,IAAI,MAAM;KACR;KACA;KACA,WAAW,YAAY;KACxB,CAAC,CACL;IACF;;AAGH,SAAO,gBADW,MAAM,UAAU,QAAQ,UAAU,QAAQ,MAAM,EAChC;GAChC,UAAU;GACV,WAAW;GACX,QAAQ,QAAQ;GACjB,CAAC;;;;;;;;CASJ,aAAa,YACX,QAEgB;AAChB;EACA,MAAM,cAAc,MAAM,eAAe,OAAO;EAChD,MAAM,SAAS,IAAI,UAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACnB,OAAO,OAAO;GACf,CAAC;AAUF,SAAO,IAAI,MAAM;GACf;GACA,QAVe,MAAM,OAAO,iBAAiB;IAC7C,WAAW,YAAY;IACvB,MAAM,OAAO;IACb,QAAQ,OAAO;IACf,cAAc,OAAO;IACrB,QAAQ,OAAO;IAChB,CAAC,EAIgB,KAAK;GACrB,WAAW,YAAY;GACxB,CAAC;;;;;;;;;;CAWJ,MAAM,OAAO,MAAgD;AAC3D;AAQA,OAAK,SANY,OADF,MAAM,KAAK,cAAc,EACV,YAAY;GACxC,WAAW,KAAK;GAChB,MAAM,KAAK,MAAM;GACjB,QAAQ,MAAM;GACf,CAAC,EAEoB,KAAK"} |
+2
-0
| const require_api_error = require('./api-client/api-error.cjs'); | ||
| const require_constants = require('./constants.cjs'); | ||
| const require_command = require('./command.cjs'); | ||
@@ -14,2 +15,3 @@ const require_snapshot = require('./snapshot.cjs'); | ||
| exports.CommandFinished = require_command.CommandFinished; | ||
| exports.DEFAULT_SANDBOX_REGION = require_constants.DEFAULT_SANDBOX_REGION; | ||
| exports.Drive = require_drive.Drive; | ||
@@ -16,0 +18,0 @@ exports.FileSystem = require_filesystem.FileSystem; |
+2
-1
| import { APIError, StreamError } from "./api-client/api-error.cjs"; | ||
| import { SnapshotTreeNodeData } from "./api-client/validators.cjs"; | ||
| import { NetworkPolicy, NetworkPolicyKeyValueMatcher, NetworkPolicyMatch, NetworkPolicyMatcher, NetworkPolicyRule, NetworkTransformer } from "./network-policy.cjs"; | ||
| import { DEFAULT_SANDBOX_REGION, SandboxRegion } from "./constants.cjs"; | ||
| import { Command, CommandFinished, CommandOutput, SerializedCommand, SerializedCommandFinished } from "./command.cjs"; | ||
@@ -13,2 +14,2 @@ import { SerializedSnapshot, Snapshot } from "./snapshot.cjs"; | ||
| import { InvalidRequestProxyHandler, ProxyHandler, ProxyMeta, defineSandboxProxy } from "./proxy.cjs"; | ||
| export { APIError, Command, CommandFinished, type CommandOutput, Drive, type ExecutionContext, FileSystem, type InvalidRequestProxyHandler, type NetworkPolicy, type NetworkPolicyKeyValueMatcher, type NetworkPolicyMatch, type NetworkPolicyMatcher, type NetworkPolicyRule, type NetworkTransformer, type ProxyHandler, type ProxyMeta, Sandbox, type SandboxMountMode, type SandboxMounts, SandboxUser, SandboxUserAlreadyExistsError, type SerializedCommand, type SerializedCommandFinished, type SerializedDrive, type SerializedSandbox, type SerializedSnapshot, Session, Snapshot, type SnapshotTreeNodeData, StreamError, defineSandboxProxy }; | ||
| export { APIError, Command, CommandFinished, type CommandOutput, DEFAULT_SANDBOX_REGION, Drive, type ExecutionContext, FileSystem, type InvalidRequestProxyHandler, type NetworkPolicy, type NetworkPolicyKeyValueMatcher, type NetworkPolicyMatch, type NetworkPolicyMatcher, type NetworkPolicyRule, type NetworkTransformer, type ProxyHandler, type ProxyMeta, Sandbox, type SandboxMountMode, type SandboxMounts, type SandboxRegion, SandboxUser, SandboxUserAlreadyExistsError, type SerializedCommand, type SerializedCommandFinished, type SerializedDrive, type SerializedSandbox, type SerializedSnapshot, Session, Snapshot, type SnapshotTreeNodeData, StreamError, defineSandboxProxy }; |
+2
-1
| import { APIError, StreamError } from "./api-client/api-error.js"; | ||
| import { SnapshotTreeNodeData } from "./api-client/validators.js"; | ||
| import { NetworkPolicy, NetworkPolicyKeyValueMatcher, NetworkPolicyMatch, NetworkPolicyMatcher, NetworkPolicyRule, NetworkTransformer } from "./network-policy.js"; | ||
| import { DEFAULT_SANDBOX_REGION, SandboxRegion } from "./constants.js"; | ||
| import { Command, CommandFinished, CommandOutput, SerializedCommand, SerializedCommandFinished } from "./command.js"; | ||
@@ -13,2 +14,2 @@ import { SerializedSnapshot, Snapshot } from "./snapshot.js"; | ||
| import { InvalidRequestProxyHandler, ProxyHandler, ProxyMeta, defineSandboxProxy } from "./proxy.js"; | ||
| export { APIError, Command, CommandFinished, type CommandOutput, Drive, type ExecutionContext, FileSystem, type InvalidRequestProxyHandler, type NetworkPolicy, type NetworkPolicyKeyValueMatcher, type NetworkPolicyMatch, type NetworkPolicyMatcher, type NetworkPolicyRule, type NetworkTransformer, type ProxyHandler, type ProxyMeta, Sandbox, type SandboxMountMode, type SandboxMounts, SandboxUser, SandboxUserAlreadyExistsError, type SerializedCommand, type SerializedCommandFinished, type SerializedDrive, type SerializedSandbox, type SerializedSnapshot, Session, Snapshot, type SnapshotTreeNodeData, StreamError, defineSandboxProxy }; | ||
| export { APIError, Command, CommandFinished, type CommandOutput, DEFAULT_SANDBOX_REGION, Drive, type ExecutionContext, FileSystem, type InvalidRequestProxyHandler, type NetworkPolicy, type NetworkPolicyKeyValueMatcher, type NetworkPolicyMatch, type NetworkPolicyMatcher, type NetworkPolicyRule, type NetworkTransformer, type ProxyHandler, type ProxyMeta, Sandbox, type SandboxMountMode, type SandboxMounts, type SandboxRegion, SandboxUser, SandboxUserAlreadyExistsError, type SerializedCommand, type SerializedCommandFinished, type SerializedDrive, type SerializedSandbox, type SerializedSnapshot, Session, Snapshot, type SnapshotTreeNodeData, StreamError, defineSandboxProxy }; |
+2
-1
| import { APIError, StreamError } from "./api-client/api-error.js"; | ||
| import { DEFAULT_SANDBOX_REGION } from "./constants.js"; | ||
| import { Command, CommandFinished } from "./command.js"; | ||
@@ -11,2 +12,2 @@ import { Snapshot } from "./snapshot.js"; | ||
| export { APIError, Command, CommandFinished, Drive, FileSystem, Sandbox, SandboxUser, SandboxUserAlreadyExistsError, Session, Snapshot, StreamError, defineSandboxProxy }; | ||
| export { APIError, Command, CommandFinished, DEFAULT_SANDBOX_REGION, Drive, FileSystem, Sandbox, SandboxUser, SandboxUserAlreadyExistsError, Session, Snapshot, StreamError, defineSandboxProxy }; |
+2
-1
| const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs'); | ||
| let jose = require("jose"); | ||
| let lru_cache = require("lru-cache"); | ||
@@ -12,3 +13,3 @@ //#region src/proxy.ts | ||
| const CLOCK_TOLERANCE_SECONDS = 60; | ||
| const jwksCache = /* @__PURE__ */ new Map(); | ||
| const jwksCache = new lru_cache.LRUCache({ max: 100 }); | ||
| /** | ||
@@ -15,0 +16,0 @@ * Creates a Web Handler for proxied requests from Vercel Sandboxes using the network policy `forwardURL` |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"proxy.cjs","names":["sanitizedRequest: Request","issuerUrl: URL"],"sources":["../src/proxy.ts"],"sourcesContent":["import { createRemoteJWKSet, decodeJwt, jwtVerify } from \"jose\";\n\nconst FORWARDED_HOST_HEADER = \"vercel-forwarded-host\";\nconst FORWARDED_SCHEME_HEADER = \"vercel-forwarded-scheme\";\nconst FORWARDED_PORT_HEADER = \"vercel-forwarded-port\";\nconst FORWARDED_PATH_HEADER = \"vercel-forwarded-path\";\nconst SANDBOX_OIDC_TOKEN_HEADER = \"vercel-sandbox-oidc-token\";\n\nconst VERCEL_OIDC_HOSTNAME = \"oidc.vercel.com\";\nconst CLOCK_TOLERANCE_SECONDS = 60;\n\nconst jwksCache = new Map<string, ReturnType<typeof createRemoteJWKSet>>();\n\nexport interface ProxyMeta {\n /**\n * The host of the request as received by this proxy.\n */\n host: string;\n /**\n * The ID of the team that owns the sandbox that proxied the request.\n */\n teamId: string;\n /**\n * The ID of the project that owns the sandbox that proxied the request.\n */\n projectId: string;\n /**\n * The ID of the sandbox that proxied the request.\n */\n sandboxId: string;\n /**\n * The name of the sandbox that proxied the request, when using persistent sandboxes.\n */\n sandboxName: string;\n}\n\nexport type ProxyHandler = (\n request: Request,\n meta: ProxyMeta,\n) => Response | Promise<Response>;\n\nexport type InvalidRequestProxyHandler = (\n request: Request,\n error: Error,\n) => Response | Promise<Response>;\n\n/**\n * Creates a Web Handler for proxied requests from Vercel Sandboxes using the network policy `forwardURL`\n * option. The provided `handler` is called for each valid proxied request, with the original request\n * alongside extracted metadata used to identify the source sandbox and request details.\n *\n * This function automatically verifies the OIDC token included in proxied requests to ensure the request\n * is legitimate: if invalid, the `invalidRequestHandler` is called (by default, a 403 response is returned).\n *\n * @example\n * ```ts\n * export default {\n * fetch: defineSandboxProxy(async (request, meta) => {\n * // meta contains the original host & source team/project/sandbox ids\n * console.log(meta)\n *\n * // return a custom response, or proxy upstream:\n * return await fetch(request)\n * }, (request, error) => {\n * // optional, handle any authorization error\n * return new Response(\"Forbidden\", { status: 403 })\n * })\n * }\n * ```\n *\n * @see https://vercel.com/docs/vercel-sandbox/concepts/firewall#requests-proxying\n */\nexport function defineSandboxProxy(\n handler: ProxyHandler,\n invalidRequestHandler: InvalidRequestProxyHandler = defaultInvalidRequestHandler,\n) {\n return async function sandboxProxy(request: Request): Promise<Response> {\n const headers = new Headers(request.headers);\n const host = headers.get(FORWARDED_HOST_HEADER);\n const scheme = headers.get(FORWARDED_SCHEME_HEADER);\n const port = headers.get(FORWARDED_PORT_HEADER);\n const path = headers.get(FORWARDED_PATH_HEADER);\n const oidcToken = headers.get(SANDBOX_OIDC_TOKEN_HEADER);\n\n headers.delete(FORWARDED_HOST_HEADER);\n headers.delete(FORWARDED_SCHEME_HEADER);\n headers.delete(FORWARDED_PORT_HEADER);\n headers.delete(FORWARDED_PATH_HEADER);\n headers.delete(SANDBOX_OIDC_TOKEN_HEADER);\n\n if (!host || !scheme || !port || !path || !oidcToken) {\n return invalidRequestHandler(\n request,\n new Error(\"Missing required proxy headers\"),\n );\n }\n\n let sanitizedRequest: Request;\n\n try {\n sanitizedRequest = new Request(\n getProxiedRequestUrl(scheme, host, port, path),\n {\n method: request.method,\n body: request.body,\n headers,\n duplex: \"half\",\n },\n );\n } catch {\n return invalidRequestHandler(\n new Request(request, { headers }),\n new Error(\"Invalid proxied request URL\"),\n );\n }\n\n sanitizedRequest.headers.set(\"host\", host);\n\n try {\n const originalUrl = normalizeForwardUrl(new URL(request.url), path);\n const claims = await verifyOidcToken(oidcToken, originalUrl);\n const meta = getProxyMeta(originalUrl.host, claims);\n\n return handler(sanitizedRequest, meta);\n } catch (error) {\n return invalidRequestHandler(\n sanitizedRequest,\n error instanceof Error ? error : new Error(\"Invalid OIDC token\"),\n );\n }\n };\n}\n\nfunction defaultInvalidRequestHandler(): Response {\n return new Response(\"Forbidden\", { status: 403 });\n}\n\nfunction getProxiedRequestUrl(\n scheme: string,\n host: string,\n port: string,\n path: string,\n): string {\n const origin = `${scheme}://${host}:${port}`;\n\n return path === \"/\" ? origin : `${origin}${path}`;\n}\n\nfunction normalizeForwardUrl(url: URL, forwardedPath: string): URL {\n const forwardedUrl = new URL(forwardedPath, url.origin);\n const forwardedPathname = stripTrailingPathSlash(forwardedUrl.pathname);\n const normalizedUrl = new URL(url);\n normalizedUrl.pathname = stripTrailingPathSlash(normalizedUrl.pathname);\n\n if (\n forwardedPathname !== \"/\" &&\n normalizedUrl.pathname.endsWith(forwardedPathname)\n ) {\n normalizedUrl.pathname = stripTrailingPathSlash(\n normalizedUrl.pathname.slice(0, -forwardedPathname.length),\n );\n }\n\n return normalizedUrl;\n}\n\nfunction stripTrailingPathSlash(pathname: string): string {\n return pathname.replace(/\\/+$/, \"\") || \"/\";\n}\n\nfunction getProxyMeta(\n host: string,\n claims: Record<string, unknown>,\n): ProxyMeta {\n const teamId = getClaim(claims, \"team_id\");\n const projectId = getClaim(claims, \"project_id\");\n const sandboxId = getClaim(claims, \"sandbox_id\");\n const sandboxName = getClaim(claims, \"sandbox_name\") ?? sandboxId;\n\n if (!teamId || !projectId || !sandboxId || !sandboxName) {\n throw new Error(\"Missing required claims in OIDC token\");\n }\n\n return {\n host,\n teamId,\n projectId,\n sandboxId,\n sandboxName,\n };\n}\n\nasync function verifyOidcToken(\n token: string,\n originalUrl: URL,\n): Promise<Record<string, unknown>> {\n const claims = decodeJwt(token);\n const issuer = getClaim(claims, \"iss\");\n\n if (!issuer) {\n throw new Error(\"Missing OIDC issuer\");\n }\n\n let issuerUrl: URL;\n\n try {\n issuerUrl = new URL(issuer);\n } catch {\n throw new Error(\"Invalid OIDC issuer\");\n }\n\n if (\n issuerUrl.protocol !== \"https:\" ||\n issuerUrl.hostname !== VERCEL_OIDC_HOSTNAME\n ) {\n throw new Error(\"Invalid OIDC issuer\");\n }\n\n const { payload } = await jwtVerify(token, getJwks(issuer), {\n audience: getForwardUrlAudience(originalUrl),\n algorithms: [\"RS256\"],\n clockTolerance: CLOCK_TOLERANCE_SECONDS,\n issuer,\n });\n\n return payload;\n}\n\nfunction getForwardUrlAudience(url: URL): string {\n const pathname = stripTrailingPathSlash(url.pathname);\n\n return pathname === \"/\" ? url.origin : url.origin + pathname;\n}\n\nfunction getJwks(issuer: string): ReturnType<typeof createRemoteJWKSet> {\n const cached = jwksCache.get(issuer);\n\n if (cached) {\n return cached;\n }\n\n const jwks = createRemoteJWKSet(\n new URL(`${issuer.replace(/\\/$/, \"\")}/.well-known/jwks`),\n );\n\n jwksCache.set(issuer, jwks);\n\n return jwks;\n}\n\nfunction getClaim(\n claims: Record<string, unknown>,\n name: string,\n): string | undefined {\n const value = claims[name];\n\n if (typeof value === \"string\" && value) {\n return value;\n }\n}\n"],"mappings":"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"} | ||
| {"version":3,"file":"proxy.cjs","names":["LRUCache","sanitizedRequest: Request","issuerUrl: URL"],"sources":["../src/proxy.ts"],"sourcesContent":["import { createRemoteJWKSet, decodeJwt, jwtVerify } from \"jose\";\nimport { LRUCache } from \"lru-cache\";\n\nconst FORWARDED_HOST_HEADER = \"vercel-forwarded-host\";\nconst FORWARDED_SCHEME_HEADER = \"vercel-forwarded-scheme\";\nconst FORWARDED_PORT_HEADER = \"vercel-forwarded-port\";\nconst FORWARDED_PATH_HEADER = \"vercel-forwarded-path\";\nconst SANDBOX_OIDC_TOKEN_HEADER = \"vercel-sandbox-oidc-token\";\n\nconst VERCEL_OIDC_HOSTNAME = \"oidc.vercel.com\";\nconst CLOCK_TOLERANCE_SECONDS = 60;\nconst MAX_JWKS_CACHE_SIZE = 100;\n\nconst jwksCache = new LRUCache<string, ReturnType<typeof createRemoteJWKSet>>({\n max: MAX_JWKS_CACHE_SIZE,\n});\n\nexport interface ProxyMeta {\n /**\n * The host of the request as received by this proxy.\n */\n host: string;\n /**\n * The ID of the team that owns the sandbox that proxied the request.\n */\n teamId: string;\n /**\n * The ID of the project that owns the sandbox that proxied the request.\n */\n projectId: string;\n /**\n * The ID of the sandbox that proxied the request.\n */\n sandboxId: string;\n /**\n * The name of the sandbox that proxied the request, when using persistent sandboxes.\n */\n sandboxName: string;\n}\n\nexport type ProxyHandler = (\n request: Request,\n meta: ProxyMeta,\n) => Response | Promise<Response>;\n\nexport type InvalidRequestProxyHandler = (\n request: Request,\n error: Error,\n) => Response | Promise<Response>;\n\n/**\n * Creates a Web Handler for proxied requests from Vercel Sandboxes using the network policy `forwardURL`\n * option. The provided `handler` is called for each valid proxied request, with the original request\n * alongside extracted metadata used to identify the source sandbox and request details.\n *\n * This function automatically verifies the OIDC token included in proxied requests to ensure the request\n * is legitimate: if invalid, the `invalidRequestHandler` is called (by default, a 403 response is returned).\n *\n * @example\n * ```ts\n * export default {\n * fetch: defineSandboxProxy(async (request, meta) => {\n * // meta contains the original host & source team/project/sandbox ids\n * console.log(meta)\n *\n * // return a custom response, or proxy upstream:\n * return await fetch(request)\n * }, (request, error) => {\n * // optional, handle any authorization error\n * return new Response(\"Forbidden\", { status: 403 })\n * })\n * }\n * ```\n *\n * @see https://vercel.com/docs/vercel-sandbox/concepts/firewall#requests-proxying\n */\nexport function defineSandboxProxy(\n handler: ProxyHandler,\n invalidRequestHandler: InvalidRequestProxyHandler = defaultInvalidRequestHandler,\n) {\n return async function sandboxProxy(request: Request): Promise<Response> {\n const headers = new Headers(request.headers);\n const host = headers.get(FORWARDED_HOST_HEADER);\n const scheme = headers.get(FORWARDED_SCHEME_HEADER);\n const port = headers.get(FORWARDED_PORT_HEADER);\n const path = headers.get(FORWARDED_PATH_HEADER);\n const oidcToken = headers.get(SANDBOX_OIDC_TOKEN_HEADER);\n\n headers.delete(FORWARDED_HOST_HEADER);\n headers.delete(FORWARDED_SCHEME_HEADER);\n headers.delete(FORWARDED_PORT_HEADER);\n headers.delete(FORWARDED_PATH_HEADER);\n headers.delete(SANDBOX_OIDC_TOKEN_HEADER);\n\n if (!host || !scheme || !port || !path || !oidcToken) {\n return invalidRequestHandler(\n request,\n new Error(\"Missing required proxy headers\"),\n );\n }\n\n let sanitizedRequest: Request;\n\n try {\n sanitizedRequest = new Request(\n getProxiedRequestUrl(scheme, host, port, path),\n {\n method: request.method,\n body: request.body,\n headers,\n duplex: \"half\",\n },\n );\n } catch {\n return invalidRequestHandler(\n new Request(request, { headers }),\n new Error(\"Invalid proxied request URL\"),\n );\n }\n\n sanitizedRequest.headers.set(\"host\", host);\n\n try {\n const originalUrl = normalizeForwardUrl(new URL(request.url), path);\n const claims = await verifyOidcToken(oidcToken, originalUrl);\n const meta = getProxyMeta(originalUrl.host, claims);\n\n return handler(sanitizedRequest, meta);\n } catch (error) {\n return invalidRequestHandler(\n sanitizedRequest,\n error instanceof Error ? error : new Error(\"Invalid OIDC token\"),\n );\n }\n };\n}\n\nfunction defaultInvalidRequestHandler(): Response {\n return new Response(\"Forbidden\", { status: 403 });\n}\n\nfunction getProxiedRequestUrl(\n scheme: string,\n host: string,\n port: string,\n path: string,\n): string {\n const origin = `${scheme}://${host}:${port}`;\n\n return path === \"/\" ? origin : `${origin}${path}`;\n}\n\nfunction normalizeForwardUrl(url: URL, forwardedPath: string): URL {\n const forwardedUrl = new URL(forwardedPath, url.origin);\n const forwardedPathname = stripTrailingPathSlash(forwardedUrl.pathname);\n const normalizedUrl = new URL(url);\n normalizedUrl.pathname = stripTrailingPathSlash(normalizedUrl.pathname);\n\n if (\n forwardedPathname !== \"/\" &&\n normalizedUrl.pathname.endsWith(forwardedPathname)\n ) {\n normalizedUrl.pathname = stripTrailingPathSlash(\n normalizedUrl.pathname.slice(0, -forwardedPathname.length),\n );\n }\n\n return normalizedUrl;\n}\n\nfunction stripTrailingPathSlash(pathname: string): string {\n return pathname.replace(/\\/+$/, \"\") || \"/\";\n}\n\nfunction getProxyMeta(\n host: string,\n claims: Record<string, unknown>,\n): ProxyMeta {\n const teamId = getClaim(claims, \"team_id\");\n const projectId = getClaim(claims, \"project_id\");\n const sandboxId = getClaim(claims, \"sandbox_id\");\n const sandboxName = getClaim(claims, \"sandbox_name\") ?? sandboxId;\n\n if (!teamId || !projectId || !sandboxId || !sandboxName) {\n throw new Error(\"Missing required claims in OIDC token\");\n }\n\n return {\n host,\n teamId,\n projectId,\n sandboxId,\n sandboxName,\n };\n}\n\nasync function verifyOidcToken(\n token: string,\n originalUrl: URL,\n): Promise<Record<string, unknown>> {\n const claims = decodeJwt(token);\n const issuer = getClaim(claims, \"iss\");\n\n if (!issuer) {\n throw new Error(\"Missing OIDC issuer\");\n }\n\n let issuerUrl: URL;\n\n try {\n issuerUrl = new URL(issuer);\n } catch {\n throw new Error(\"Invalid OIDC issuer\");\n }\n\n if (\n issuerUrl.protocol !== \"https:\" ||\n issuerUrl.hostname !== VERCEL_OIDC_HOSTNAME\n ) {\n throw new Error(\"Invalid OIDC issuer\");\n }\n\n const { payload } = await jwtVerify(token, getJwks(issuer), {\n audience: getForwardUrlAudience(originalUrl),\n algorithms: [\"RS256\"],\n clockTolerance: CLOCK_TOLERANCE_SECONDS,\n issuer,\n });\n\n return payload;\n}\n\nfunction getForwardUrlAudience(url: URL): string {\n const pathname = stripTrailingPathSlash(url.pathname);\n\n return pathname === \"/\" ? url.origin : url.origin + pathname;\n}\n\nfunction getJwks(issuer: string): ReturnType<typeof createRemoteJWKSet> {\n const cached = jwksCache.get(issuer);\n\n if (cached) {\n return cached;\n }\n\n const jwks = createRemoteJWKSet(\n new URL(`${issuer.replace(/\\/$/, \"\")}/.well-known/jwks`),\n );\n\n jwksCache.set(issuer, jwks);\n\n return jwks;\n}\n\nfunction getClaim(\n claims: Record<string, unknown>,\n name: string,\n): string | undefined {\n const value = claims[name];\n\n if (typeof value === \"string\" && value) {\n return value;\n }\n}\n"],"mappings":"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"} |
+2
-1
| import { createRemoteJWKSet, decodeJwt, jwtVerify } from "jose"; | ||
| import { LRUCache } from "lru-cache"; | ||
@@ -11,3 +12,3 @@ //#region src/proxy.ts | ||
| const CLOCK_TOLERANCE_SECONDS = 60; | ||
| const jwksCache = /* @__PURE__ */ new Map(); | ||
| const jwksCache = new LRUCache({ max: 100 }); | ||
| /** | ||
@@ -14,0 +15,0 @@ * Creates a Web Handler for proxied requests from Vercel Sandboxes using the network policy `forwardURL` |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"proxy.js","names":["sanitizedRequest: Request","issuerUrl: URL"],"sources":["../src/proxy.ts"],"sourcesContent":["import { createRemoteJWKSet, decodeJwt, jwtVerify } from \"jose\";\n\nconst FORWARDED_HOST_HEADER = \"vercel-forwarded-host\";\nconst FORWARDED_SCHEME_HEADER = \"vercel-forwarded-scheme\";\nconst FORWARDED_PORT_HEADER = \"vercel-forwarded-port\";\nconst FORWARDED_PATH_HEADER = \"vercel-forwarded-path\";\nconst SANDBOX_OIDC_TOKEN_HEADER = \"vercel-sandbox-oidc-token\";\n\nconst VERCEL_OIDC_HOSTNAME = \"oidc.vercel.com\";\nconst CLOCK_TOLERANCE_SECONDS = 60;\n\nconst jwksCache = new Map<string, ReturnType<typeof createRemoteJWKSet>>();\n\nexport interface ProxyMeta {\n /**\n * The host of the request as received by this proxy.\n */\n host: string;\n /**\n * The ID of the team that owns the sandbox that proxied the request.\n */\n teamId: string;\n /**\n * The ID of the project that owns the sandbox that proxied the request.\n */\n projectId: string;\n /**\n * The ID of the sandbox that proxied the request.\n */\n sandboxId: string;\n /**\n * The name of the sandbox that proxied the request, when using persistent sandboxes.\n */\n sandboxName: string;\n}\n\nexport type ProxyHandler = (\n request: Request,\n meta: ProxyMeta,\n) => Response | Promise<Response>;\n\nexport type InvalidRequestProxyHandler = (\n request: Request,\n error: Error,\n) => Response | Promise<Response>;\n\n/**\n * Creates a Web Handler for proxied requests from Vercel Sandboxes using the network policy `forwardURL`\n * option. The provided `handler` is called for each valid proxied request, with the original request\n * alongside extracted metadata used to identify the source sandbox and request details.\n *\n * This function automatically verifies the OIDC token included in proxied requests to ensure the request\n * is legitimate: if invalid, the `invalidRequestHandler` is called (by default, a 403 response is returned).\n *\n * @example\n * ```ts\n * export default {\n * fetch: defineSandboxProxy(async (request, meta) => {\n * // meta contains the original host & source team/project/sandbox ids\n * console.log(meta)\n *\n * // return a custom response, or proxy upstream:\n * return await fetch(request)\n * }, (request, error) => {\n * // optional, handle any authorization error\n * return new Response(\"Forbidden\", { status: 403 })\n * })\n * }\n * ```\n *\n * @see https://vercel.com/docs/vercel-sandbox/concepts/firewall#requests-proxying\n */\nexport function defineSandboxProxy(\n handler: ProxyHandler,\n invalidRequestHandler: InvalidRequestProxyHandler = defaultInvalidRequestHandler,\n) {\n return async function sandboxProxy(request: Request): Promise<Response> {\n const headers = new Headers(request.headers);\n const host = headers.get(FORWARDED_HOST_HEADER);\n const scheme = headers.get(FORWARDED_SCHEME_HEADER);\n const port = headers.get(FORWARDED_PORT_HEADER);\n const path = headers.get(FORWARDED_PATH_HEADER);\n const oidcToken = headers.get(SANDBOX_OIDC_TOKEN_HEADER);\n\n headers.delete(FORWARDED_HOST_HEADER);\n headers.delete(FORWARDED_SCHEME_HEADER);\n headers.delete(FORWARDED_PORT_HEADER);\n headers.delete(FORWARDED_PATH_HEADER);\n headers.delete(SANDBOX_OIDC_TOKEN_HEADER);\n\n if (!host || !scheme || !port || !path || !oidcToken) {\n return invalidRequestHandler(\n request,\n new Error(\"Missing required proxy headers\"),\n );\n }\n\n let sanitizedRequest: Request;\n\n try {\n sanitizedRequest = new Request(\n getProxiedRequestUrl(scheme, host, port, path),\n {\n method: request.method,\n body: request.body,\n headers,\n duplex: \"half\",\n },\n );\n } catch {\n return invalidRequestHandler(\n new Request(request, { headers }),\n new Error(\"Invalid proxied request URL\"),\n );\n }\n\n sanitizedRequest.headers.set(\"host\", host);\n\n try {\n const originalUrl = normalizeForwardUrl(new URL(request.url), path);\n const claims = await verifyOidcToken(oidcToken, originalUrl);\n const meta = getProxyMeta(originalUrl.host, claims);\n\n return handler(sanitizedRequest, meta);\n } catch (error) {\n return invalidRequestHandler(\n sanitizedRequest,\n error instanceof Error ? error : new Error(\"Invalid OIDC token\"),\n );\n }\n };\n}\n\nfunction defaultInvalidRequestHandler(): Response {\n return new Response(\"Forbidden\", { status: 403 });\n}\n\nfunction getProxiedRequestUrl(\n scheme: string,\n host: string,\n port: string,\n path: string,\n): string {\n const origin = `${scheme}://${host}:${port}`;\n\n return path === \"/\" ? origin : `${origin}${path}`;\n}\n\nfunction normalizeForwardUrl(url: URL, forwardedPath: string): URL {\n const forwardedUrl = new URL(forwardedPath, url.origin);\n const forwardedPathname = stripTrailingPathSlash(forwardedUrl.pathname);\n const normalizedUrl = new URL(url);\n normalizedUrl.pathname = stripTrailingPathSlash(normalizedUrl.pathname);\n\n if (\n forwardedPathname !== \"/\" &&\n normalizedUrl.pathname.endsWith(forwardedPathname)\n ) {\n normalizedUrl.pathname = stripTrailingPathSlash(\n normalizedUrl.pathname.slice(0, -forwardedPathname.length),\n );\n }\n\n return normalizedUrl;\n}\n\nfunction stripTrailingPathSlash(pathname: string): string {\n return pathname.replace(/\\/+$/, \"\") || \"/\";\n}\n\nfunction getProxyMeta(\n host: string,\n claims: Record<string, unknown>,\n): ProxyMeta {\n const teamId = getClaim(claims, \"team_id\");\n const projectId = getClaim(claims, \"project_id\");\n const sandboxId = getClaim(claims, \"sandbox_id\");\n const sandboxName = getClaim(claims, \"sandbox_name\") ?? sandboxId;\n\n if (!teamId || !projectId || !sandboxId || !sandboxName) {\n throw new Error(\"Missing required claims in OIDC token\");\n }\n\n return {\n host,\n teamId,\n projectId,\n sandboxId,\n sandboxName,\n };\n}\n\nasync function verifyOidcToken(\n token: string,\n originalUrl: URL,\n): Promise<Record<string, unknown>> {\n const claims = decodeJwt(token);\n const issuer = getClaim(claims, \"iss\");\n\n if (!issuer) {\n throw new Error(\"Missing OIDC issuer\");\n }\n\n let issuerUrl: URL;\n\n try {\n issuerUrl = new URL(issuer);\n } catch {\n throw new Error(\"Invalid OIDC issuer\");\n }\n\n if (\n issuerUrl.protocol !== \"https:\" ||\n issuerUrl.hostname !== VERCEL_OIDC_HOSTNAME\n ) {\n throw new Error(\"Invalid OIDC issuer\");\n }\n\n const { payload } = await jwtVerify(token, getJwks(issuer), {\n audience: getForwardUrlAudience(originalUrl),\n algorithms: [\"RS256\"],\n clockTolerance: CLOCK_TOLERANCE_SECONDS,\n issuer,\n });\n\n return payload;\n}\n\nfunction getForwardUrlAudience(url: URL): string {\n const pathname = stripTrailingPathSlash(url.pathname);\n\n return pathname === \"/\" ? url.origin : url.origin + pathname;\n}\n\nfunction getJwks(issuer: string): ReturnType<typeof createRemoteJWKSet> {\n const cached = jwksCache.get(issuer);\n\n if (cached) {\n return cached;\n }\n\n const jwks = createRemoteJWKSet(\n new URL(`${issuer.replace(/\\/$/, \"\")}/.well-known/jwks`),\n );\n\n jwksCache.set(issuer, jwks);\n\n return jwks;\n}\n\nfunction getClaim(\n claims: Record<string, unknown>,\n name: string,\n): string | undefined {\n const value = claims[name];\n\n if (typeof value === \"string\" && value) {\n return value;\n }\n}\n"],"mappings":"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"} | ||
| {"version":3,"file":"proxy.js","names":["sanitizedRequest: Request","issuerUrl: URL"],"sources":["../src/proxy.ts"],"sourcesContent":["import { createRemoteJWKSet, decodeJwt, jwtVerify } from \"jose\";\nimport { LRUCache } from \"lru-cache\";\n\nconst FORWARDED_HOST_HEADER = \"vercel-forwarded-host\";\nconst FORWARDED_SCHEME_HEADER = \"vercel-forwarded-scheme\";\nconst FORWARDED_PORT_HEADER = \"vercel-forwarded-port\";\nconst FORWARDED_PATH_HEADER = \"vercel-forwarded-path\";\nconst SANDBOX_OIDC_TOKEN_HEADER = \"vercel-sandbox-oidc-token\";\n\nconst VERCEL_OIDC_HOSTNAME = \"oidc.vercel.com\";\nconst CLOCK_TOLERANCE_SECONDS = 60;\nconst MAX_JWKS_CACHE_SIZE = 100;\n\nconst jwksCache = new LRUCache<string, ReturnType<typeof createRemoteJWKSet>>({\n max: MAX_JWKS_CACHE_SIZE,\n});\n\nexport interface ProxyMeta {\n /**\n * The host of the request as received by this proxy.\n */\n host: string;\n /**\n * The ID of the team that owns the sandbox that proxied the request.\n */\n teamId: string;\n /**\n * The ID of the project that owns the sandbox that proxied the request.\n */\n projectId: string;\n /**\n * The ID of the sandbox that proxied the request.\n */\n sandboxId: string;\n /**\n * The name of the sandbox that proxied the request, when using persistent sandboxes.\n */\n sandboxName: string;\n}\n\nexport type ProxyHandler = (\n request: Request,\n meta: ProxyMeta,\n) => Response | Promise<Response>;\n\nexport type InvalidRequestProxyHandler = (\n request: Request,\n error: Error,\n) => Response | Promise<Response>;\n\n/**\n * Creates a Web Handler for proxied requests from Vercel Sandboxes using the network policy `forwardURL`\n * option. The provided `handler` is called for each valid proxied request, with the original request\n * alongside extracted metadata used to identify the source sandbox and request details.\n *\n * This function automatically verifies the OIDC token included in proxied requests to ensure the request\n * is legitimate: if invalid, the `invalidRequestHandler` is called (by default, a 403 response is returned).\n *\n * @example\n * ```ts\n * export default {\n * fetch: defineSandboxProxy(async (request, meta) => {\n * // meta contains the original host & source team/project/sandbox ids\n * console.log(meta)\n *\n * // return a custom response, or proxy upstream:\n * return await fetch(request)\n * }, (request, error) => {\n * // optional, handle any authorization error\n * return new Response(\"Forbidden\", { status: 403 })\n * })\n * }\n * ```\n *\n * @see https://vercel.com/docs/vercel-sandbox/concepts/firewall#requests-proxying\n */\nexport function defineSandboxProxy(\n handler: ProxyHandler,\n invalidRequestHandler: InvalidRequestProxyHandler = defaultInvalidRequestHandler,\n) {\n return async function sandboxProxy(request: Request): Promise<Response> {\n const headers = new Headers(request.headers);\n const host = headers.get(FORWARDED_HOST_HEADER);\n const scheme = headers.get(FORWARDED_SCHEME_HEADER);\n const port = headers.get(FORWARDED_PORT_HEADER);\n const path = headers.get(FORWARDED_PATH_HEADER);\n const oidcToken = headers.get(SANDBOX_OIDC_TOKEN_HEADER);\n\n headers.delete(FORWARDED_HOST_HEADER);\n headers.delete(FORWARDED_SCHEME_HEADER);\n headers.delete(FORWARDED_PORT_HEADER);\n headers.delete(FORWARDED_PATH_HEADER);\n headers.delete(SANDBOX_OIDC_TOKEN_HEADER);\n\n if (!host || !scheme || !port || !path || !oidcToken) {\n return invalidRequestHandler(\n request,\n new Error(\"Missing required proxy headers\"),\n );\n }\n\n let sanitizedRequest: Request;\n\n try {\n sanitizedRequest = new Request(\n getProxiedRequestUrl(scheme, host, port, path),\n {\n method: request.method,\n body: request.body,\n headers,\n duplex: \"half\",\n },\n );\n } catch {\n return invalidRequestHandler(\n new Request(request, { headers }),\n new Error(\"Invalid proxied request URL\"),\n );\n }\n\n sanitizedRequest.headers.set(\"host\", host);\n\n try {\n const originalUrl = normalizeForwardUrl(new URL(request.url), path);\n const claims = await verifyOidcToken(oidcToken, originalUrl);\n const meta = getProxyMeta(originalUrl.host, claims);\n\n return handler(sanitizedRequest, meta);\n } catch (error) {\n return invalidRequestHandler(\n sanitizedRequest,\n error instanceof Error ? error : new Error(\"Invalid OIDC token\"),\n );\n }\n };\n}\n\nfunction defaultInvalidRequestHandler(): Response {\n return new Response(\"Forbidden\", { status: 403 });\n}\n\nfunction getProxiedRequestUrl(\n scheme: string,\n host: string,\n port: string,\n path: string,\n): string {\n const origin = `${scheme}://${host}:${port}`;\n\n return path === \"/\" ? origin : `${origin}${path}`;\n}\n\nfunction normalizeForwardUrl(url: URL, forwardedPath: string): URL {\n const forwardedUrl = new URL(forwardedPath, url.origin);\n const forwardedPathname = stripTrailingPathSlash(forwardedUrl.pathname);\n const normalizedUrl = new URL(url);\n normalizedUrl.pathname = stripTrailingPathSlash(normalizedUrl.pathname);\n\n if (\n forwardedPathname !== \"/\" &&\n normalizedUrl.pathname.endsWith(forwardedPathname)\n ) {\n normalizedUrl.pathname = stripTrailingPathSlash(\n normalizedUrl.pathname.slice(0, -forwardedPathname.length),\n );\n }\n\n return normalizedUrl;\n}\n\nfunction stripTrailingPathSlash(pathname: string): string {\n return pathname.replace(/\\/+$/, \"\") || \"/\";\n}\n\nfunction getProxyMeta(\n host: string,\n claims: Record<string, unknown>,\n): ProxyMeta {\n const teamId = getClaim(claims, \"team_id\");\n const projectId = getClaim(claims, \"project_id\");\n const sandboxId = getClaim(claims, \"sandbox_id\");\n const sandboxName = getClaim(claims, \"sandbox_name\") ?? sandboxId;\n\n if (!teamId || !projectId || !sandboxId || !sandboxName) {\n throw new Error(\"Missing required claims in OIDC token\");\n }\n\n return {\n host,\n teamId,\n projectId,\n sandboxId,\n sandboxName,\n };\n}\n\nasync function verifyOidcToken(\n token: string,\n originalUrl: URL,\n): Promise<Record<string, unknown>> {\n const claims = decodeJwt(token);\n const issuer = getClaim(claims, \"iss\");\n\n if (!issuer) {\n throw new Error(\"Missing OIDC issuer\");\n }\n\n let issuerUrl: URL;\n\n try {\n issuerUrl = new URL(issuer);\n } catch {\n throw new Error(\"Invalid OIDC issuer\");\n }\n\n if (\n issuerUrl.protocol !== \"https:\" ||\n issuerUrl.hostname !== VERCEL_OIDC_HOSTNAME\n ) {\n throw new Error(\"Invalid OIDC issuer\");\n }\n\n const { payload } = await jwtVerify(token, getJwks(issuer), {\n audience: getForwardUrlAudience(originalUrl),\n algorithms: [\"RS256\"],\n clockTolerance: CLOCK_TOLERANCE_SECONDS,\n issuer,\n });\n\n return payload;\n}\n\nfunction getForwardUrlAudience(url: URL): string {\n const pathname = stripTrailingPathSlash(url.pathname);\n\n return pathname === \"/\" ? url.origin : url.origin + pathname;\n}\n\nfunction getJwks(issuer: string): ReturnType<typeof createRemoteJWKSet> {\n const cached = jwksCache.get(issuer);\n\n if (cached) {\n return cached;\n }\n\n const jwks = createRemoteJWKSet(\n new URL(`${issuer.replace(/\\/$/, \"\")}/.well-known/jwks`),\n );\n\n jwksCache.set(issuer, jwks);\n\n return jwks;\n}\n\nfunction getClaim(\n claims: Record<string, unknown>,\n name: string,\n): string | undefined {\n const value = claims[name];\n\n if (typeof value === \"string\" && value) {\n return value;\n }\n}\n"],"mappings":"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"} |
+21
-2
@@ -8,2 +8,3 @@ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs'); | ||
| const require_get_credentials = require('./utils/get-credentials.cjs'); | ||
| const require_constants = require('./constants.cjs'); | ||
| const require_paginator = require('./utils/paginator.cjs'); | ||
@@ -73,8 +74,16 @@ const require_session = require('./session.cjs'); | ||
| /** | ||
| * The region this sandbox runs in. | ||
| * The region this sandbox is configured to run in. Where the running session | ||
| * actually landed is reported by {@link Session.region}. | ||
| */ | ||
| get region() { | ||
| return this.sandbox.region; | ||
| return this.sandbox.region ?? require_constants.DEFAULT_SANDBOX_REGION; | ||
| } | ||
| /** | ||
| * The additional regions this sandbox can fail over to, in order. Empty when | ||
| * it does not fail over. | ||
| */ | ||
| get failoverRegions() { | ||
| return this.sandbox.failoverRegions ?? []; | ||
| } | ||
| /** | ||
| * Number of virtual CPUs allocated. | ||
@@ -352,2 +361,4 @@ */ | ||
| keepLastSnapshots: params?.keepLastSnapshots, | ||
| region: params?.region, | ||
| failoverRegions: params?.failoverRegions, | ||
| signal: params?.signal, | ||
@@ -415,2 +426,4 @@ name: params?.name, | ||
| keepLastSnapshots: params.keepLastSnapshots, | ||
| region: params.region, | ||
| failoverRegions: params.failoverRegions, | ||
| persistent: params.persistent, | ||
@@ -1074,2 +1087,6 @@ signal: params.signal, | ||
| * | ||
| * `region` and `failoverRegions` apply to the next session; the currently | ||
| * running session keeps the region it started in. Pass an empty | ||
| * `failoverRegions` array to remove all failover regions. | ||
| * | ||
| * @param params - Fields to update. | ||
@@ -1098,2 +1115,4 @@ * @param opts - Optional abort signal. | ||
| currentSnapshotId: params.currentSnapshotId, | ||
| region: params.region, | ||
| failoverRegions: params.failoverRegions, | ||
| signal: opts?.signal | ||
@@ -1100,0 +1119,0 @@ }); |
+34
-6
@@ -5,3 +5,3 @@ import { Paginator } from "./utils/paginator.cjs"; | ||
| import { WithPrivate } from "./utils/types.cjs"; | ||
| import { ManagedImage, RUNTIMES } from "./constants.cjs"; | ||
| import { ManagedImage, RUNTIMES, SandboxRegion } from "./constants.cjs"; | ||
| import { APIClient, WithFetchOptions } from "./api-client/api-client.cjs"; | ||
@@ -52,3 +52,3 @@ import { Credentials } from "./utils/get-credentials.cjs"; | ||
| * Array of port numbers to expose from the sandbox. Sandboxes can | ||
| * expose up to 4 ports. | ||
| * expose up to 15 ports. | ||
| */ | ||
@@ -93,2 +93,12 @@ ports?: number[]; | ||
| /** | ||
| * The region to create the sandbox in. Defaults to `iad1`. | ||
| * See the Vercel documentation for the available regions. | ||
| */ | ||
| region?: SandboxRegion; | ||
| /** | ||
| * Additional regions the sandbox can fail over to. Must not include | ||
| * `region`. | ||
| */ | ||
| failoverRegions?: SandboxRegion[]; | ||
| /** | ||
| * List of drives to attach to the sandbox, keyed by the desired mount path. | ||
@@ -229,3 +239,5 @@ * The drive must be created beforehand with `Drive.getOrCreate`. | ||
| /** | ||
| * Whether to resume an existing session. Defaults to true. | ||
| * Whether to resume an existing session immediately. Defaults to false; | ||
| * a persistent sandbox still auto-resumes on the first SDK call that | ||
| * needs a running session (such as `runCommand`). | ||
| */ | ||
@@ -250,3 +262,5 @@ resume?: boolean; | ||
| /** | ||
| * Whether to resume an existing session. Defaults to true. | ||
| * Whether to resume an existing session immediately. Defaults to false; | ||
| * a persistent sandbox still auto-resumes on the first SDK call that | ||
| * needs a running session (such as `runCommand`). | ||
| */ | ||
@@ -331,6 +345,12 @@ resume?: boolean; | ||
| /** | ||
| * The region this sandbox runs in. | ||
| * The region this sandbox is configured to run in. Where the running session | ||
| * actually landed is reported by {@link Session.region}. | ||
| */ | ||
| get region(): string | undefined; | ||
| get region(): string; | ||
| /** | ||
| * The additional regions this sandbox can fail over to, in order. Empty when | ||
| * it does not fail over. | ||
| */ | ||
| get failoverRegions(): string[]; | ||
| /** | ||
| * Number of virtual CPUs allocated. | ||
@@ -470,2 +490,3 @@ */ | ||
| region?: string | undefined; | ||
| failoverRegions?: string[] | undefined; | ||
| vcpus?: number | undefined; | ||
@@ -1071,2 +1092,6 @@ memory?: number | undefined; | ||
| * | ||
| * `region` and `failoverRegions` apply to the next session; the currently | ||
| * running session keeps the region it started in. Pass an empty | ||
| * `failoverRegions` array to remove all failover regions. | ||
| * | ||
| * @param params - Fields to update. | ||
@@ -1091,2 +1116,4 @@ * @param opts - Optional abort signal. | ||
| currentSnapshotId?: string; | ||
| region?: SandboxRegion; | ||
| failoverRegions?: SandboxRegion[]; | ||
| }, opts?: { | ||
@@ -1254,2 +1281,3 @@ signal?: AbortSignal; | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -1256,0 +1284,0 @@ lastUsedAt?: number | undefined; |
+34
-6
@@ -5,3 +5,3 @@ import { Paginator } from "./utils/paginator.js"; | ||
| import { WithPrivate } from "./utils/types.js"; | ||
| import { ManagedImage, RUNTIMES } from "./constants.js"; | ||
| import { ManagedImage, RUNTIMES, SandboxRegion } from "./constants.js"; | ||
| import { APIClient, WithFetchOptions } from "./api-client/api-client.js"; | ||
@@ -53,3 +53,3 @@ import "./api-client/index.js"; | ||
| * Array of port numbers to expose from the sandbox. Sandboxes can | ||
| * expose up to 4 ports. | ||
| * expose up to 15 ports. | ||
| */ | ||
@@ -94,2 +94,12 @@ ports?: number[]; | ||
| /** | ||
| * The region to create the sandbox in. Defaults to `iad1`. | ||
| * See the Vercel documentation for the available regions. | ||
| */ | ||
| region?: SandboxRegion; | ||
| /** | ||
| * Additional regions the sandbox can fail over to. Must not include | ||
| * `region`. | ||
| */ | ||
| failoverRegions?: SandboxRegion[]; | ||
| /** | ||
| * List of drives to attach to the sandbox, keyed by the desired mount path. | ||
@@ -230,3 +240,5 @@ * The drive must be created beforehand with `Drive.getOrCreate`. | ||
| /** | ||
| * Whether to resume an existing session. Defaults to true. | ||
| * Whether to resume an existing session immediately. Defaults to false; | ||
| * a persistent sandbox still auto-resumes on the first SDK call that | ||
| * needs a running session (such as `runCommand`). | ||
| */ | ||
@@ -251,3 +263,5 @@ resume?: boolean; | ||
| /** | ||
| * Whether to resume an existing session. Defaults to true. | ||
| * Whether to resume an existing session immediately. Defaults to false; | ||
| * a persistent sandbox still auto-resumes on the first SDK call that | ||
| * needs a running session (such as `runCommand`). | ||
| */ | ||
@@ -332,6 +346,12 @@ resume?: boolean; | ||
| /** | ||
| * The region this sandbox runs in. | ||
| * The region this sandbox is configured to run in. Where the running session | ||
| * actually landed is reported by {@link Session.region}. | ||
| */ | ||
| get region(): string | undefined; | ||
| get region(): string; | ||
| /** | ||
| * The additional regions this sandbox can fail over to, in order. Empty when | ||
| * it does not fail over. | ||
| */ | ||
| get failoverRegions(): string[]; | ||
| /** | ||
| * Number of virtual CPUs allocated. | ||
@@ -471,2 +491,3 @@ */ | ||
| region?: string | undefined; | ||
| failoverRegions?: string[] | undefined; | ||
| vcpus?: number | undefined; | ||
@@ -1072,2 +1093,6 @@ memory?: number | undefined; | ||
| * | ||
| * `region` and `failoverRegions` apply to the next session; the currently | ||
| * running session keeps the region it started in. Pass an empty | ||
| * `failoverRegions` array to remove all failover regions. | ||
| * | ||
| * @param params - Fields to update. | ||
@@ -1092,2 +1117,4 @@ * @param opts - Optional abort signal. | ||
| currentSnapshotId?: string; | ||
| region?: SandboxRegion; | ||
| failoverRegions?: SandboxRegion[]; | ||
| }, opts?: { | ||
@@ -1255,2 +1282,3 @@ signal?: AbortSignal; | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -1257,0 +1285,0 @@ lastUsedAt?: number | undefined; |
+21
-2
@@ -7,2 +7,3 @@ import { APIError } from "./api-client/api-error.js"; | ||
| import { getCredentials } from "./utils/get-credentials.js"; | ||
| import { DEFAULT_SANDBOX_REGION } from "./constants.js"; | ||
| import { attachPaginator } from "./utils/paginator.js"; | ||
@@ -72,8 +73,16 @@ import { Session } from "./session.js"; | ||
| /** | ||
| * The region this sandbox runs in. | ||
| * The region this sandbox is configured to run in. Where the running session | ||
| * actually landed is reported by {@link Session.region}. | ||
| */ | ||
| get region() { | ||
| return this.sandbox.region; | ||
| return this.sandbox.region ?? DEFAULT_SANDBOX_REGION; | ||
| } | ||
| /** | ||
| * The additional regions this sandbox can fail over to, in order. Empty when | ||
| * it does not fail over. | ||
| */ | ||
| get failoverRegions() { | ||
| return this.sandbox.failoverRegions ?? []; | ||
| } | ||
| /** | ||
| * Number of virtual CPUs allocated. | ||
@@ -351,2 +360,4 @@ */ | ||
| keepLastSnapshots: params?.keepLastSnapshots, | ||
| region: params?.region, | ||
| failoverRegions: params?.failoverRegions, | ||
| signal: params?.signal, | ||
@@ -414,2 +425,4 @@ name: params?.name, | ||
| keepLastSnapshots: params.keepLastSnapshots, | ||
| region: params.region, | ||
| failoverRegions: params.failoverRegions, | ||
| persistent: params.persistent, | ||
@@ -1073,2 +1086,6 @@ signal: params.signal, | ||
| * | ||
| * `region` and `failoverRegions` apply to the next session; the currently | ||
| * running session keeps the region it started in. Pass an empty | ||
| * `failoverRegions` array to remove all failover regions. | ||
| * | ||
| * @param params - Fields to update. | ||
@@ -1097,2 +1114,4 @@ * @param opts - Optional abort signal. | ||
| currentSnapshotId: params.currentSnapshotId, | ||
| region: params.region, | ||
| failoverRegions: params.failoverRegions, | ||
| signal: opts?.signal | ||
@@ -1099,0 +1118,0 @@ }); |
@@ -45,2 +45,8 @@ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs'); | ||
| /** | ||
| * All regions where this snapshot is available. | ||
| */ | ||
| get regions() { | ||
| return this.snapshot.regions ?? [this.snapshot.region]; | ||
| } | ||
| /** | ||
| * The status of the snapshot. | ||
@@ -47,0 +53,0 @@ */ |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"snapshot.cjs","names":["getCredentials","APIClient","WORKFLOW_SERIALIZE","WORKFLOW_DESERIALIZE","attachPaginator"],"sources":["../src/snapshot.ts"],"sourcesContent":["import { WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE } from \"@workflow/serde\";\nimport type { WithFetchOptions } from \"./api-client/api-client.js\";\nimport type { SnapshotMetadata } from \"./api-client/index.js\";\nimport { APIClient } from \"./api-client/index.js\";\nimport { type Credentials, getCredentials } from \"./utils/get-credentials.js\";\nimport { attachPaginator } from \"./utils/paginator.js\";\n\nexport interface SerializedSnapshot {\n snapshot: SnapshotMetadata;\n}\n\n/** @inline */\ninterface GetSnapshotParams {\n /**\n * Unique identifier of the snapshot.\n */\n snapshotId: string;\n /**\n * An AbortSignal to cancel the operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * A Snapshot is a saved state of a Sandbox that can be used to create new Sandboxes\n *\n * Use {@link Sandbox.snapshot} or {@link Snapshot.get} to construct.\n * @hideconstructor\n */\nexport class Snapshot {\n private _client: APIClient | null = null;\n\n /**\n * Lazily resolve credentials and construct an API client.\n * This is used in step contexts where the Snapshot was deserialized\n * without a client (e.g. when crossing workflow/step boundaries).\n * @internal\n */\n private async ensureClient(): Promise<APIClient> {\n \"use step\";\n if (this._client) return this._client;\n const credentials = await getCredentials();\n this._client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n });\n return this._client;\n }\n\n /**\n * Unique ID of this snapshot.\n */\n public get snapshotId(): string {\n return this.snapshot.id;\n }\n\n /**\n * The ID of the session from which this snapshot was created.\n */\n public get sourceSessionId(): string {\n return this.snapshot.sourceSessionId;\n }\n\n /**\n * The status of the snapshot.\n */\n public get status(): SnapshotMetadata[\"status\"] {\n return this.snapshot.status;\n }\n\n /**\n * The size of the snapshot in bytes, or null if not available.\n */\n public get sizeBytes(): number {\n return this.snapshot.sizeBytes;\n }\n\n /**\n * The creation date of this snapshot.\n */\n public get createdAt(): Date {\n return new Date(this.snapshot.createdAt);\n }\n\n /**\n * When this snapshot was last updated.\n */\n public get updatedAt(): Date {\n return new Date(this.snapshot.updatedAt);\n }\n\n /**\n * The expiration date of this snapshot, or undefined if it does not expire.\n */\n public get expiresAt(): Date | undefined {\n if (this.snapshot.expiresAt === undefined) {\n return undefined;\n }\n\n return new Date(this.snapshot.expiresAt);\n }\n\n /**\n * Internal metadata about this snapshot.\n */\n private snapshot: SnapshotMetadata;\n\n /**\n * Serialize a Snapshot instance to plain data for @workflow/serde.\n *\n * @param instance - The Snapshot instance to serialize\n * @returns A plain object containing snapshot metadata\n */\n static [WORKFLOW_SERIALIZE](instance: Snapshot): SerializedSnapshot {\n return {\n snapshot: instance.snapshot,\n };\n }\n\n /**\n * Deserialize a Snapshot from serialized data.\n *\n * The deserialized instance uses the serialized metadata synchronously and\n * lazily creates an API client only when methods perform API requests.\n *\n * @param data - The serialized snapshot data\n * @returns The reconstructed Snapshot instance\n */\n static [WORKFLOW_DESERIALIZE](data: SerializedSnapshot): Snapshot {\n return new Snapshot({\n snapshot: data.snapshot,\n });\n }\n\n constructor({\n client,\n snapshot,\n }: {\n client?: APIClient;\n snapshot: SnapshotMetadata;\n }) {\n this._client = client ?? null;\n this.snapshot = snapshot;\n }\n\n /**\n * Allow to get a list of snapshots for a team narrowed to the given params.\n * It returns both the snapshots and the pagination metadata to allow getting\n * the next page of results.\n *\n * The returned object is async-iterable to auto-paginate through all pages:\n *\n * ```ts\n * const result = await Snapshot.list({ name: \"my-sandbox\" });\n * for await (const snapshot of result) { ... }\n * // or: await result.toArray();\n * // or: for await (const page of result.pages()) { ... }\n * ```\n */\n static async list(\n params?: Partial<Parameters<APIClient[\"listSnapshots\"]>[0]> &\n Partial<Credentials> &\n WithFetchOptions,\n ) {\n \"use step\";\n const credentials = await getCredentials(params);\n const client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n fetch: params?.fetch,\n });\n const fetchPage = async (cursor?: string) => {\n const response = await client.listSnapshots({\n ...credentials,\n ...params,\n ...(cursor !== undefined && { cursor }),\n });\n return response.json;\n };\n const firstPage = await fetchPage(params?.cursor);\n return attachPaginator(firstPage, {\n itemsKey: \"snapshots\",\n fetchNext: fetchPage,\n signal: params?.signal,\n });\n }\n\n /**\n * Fetch the snapshot ancestry tree anchored on a given snapshot.\n * It returns both the tree nodes and the pagination metadata to allow\n * walking the next page of results in the same direction.\n *\n * The returned object is async-iterable to auto-paginate through all pages\n * in the direction set by `sortOrder` (`\"desc\"` walks ancestors, `\"asc\"`\n * walks descendants):\n *\n * ```ts\n * const result = await Snapshot.tree({ snapshotId: \"snap_abc\", sortOrder: \"desc\" });\n * for await (const node of result) { ... }\n * // or: await result.toArray();\n * // or: for await (const page of result.pages()) { ... }\n * ```\n */\n static async tree(\n params: { snapshotId: string } &\n Partial<Parameters<APIClient[\"getSnapshotTree\"]>[0]> &\n Partial<Credentials> &\n WithFetchOptions,\n ) {\n \"use step\";\n const credentials = await getCredentials(params);\n const client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n fetch: params.fetch,\n });\n const fetchPage = async (snapshotId: string) => {\n const response = await client.getSnapshotTree({\n ...credentials,\n ...params,\n snapshotId,\n });\n return response.json;\n };\n const firstPage = await fetchPage(params.snapshotId);\n return attachPaginator(firstPage, {\n itemsKey: \"snapshots\",\n fetchNext: fetchPage,\n signal: params.signal,\n });\n }\n\n /**\n * Retrieve an existing snapshot.\n *\n * @param params - Get parameters and optional credentials.\n * @returns A promise resolving to the {@link Sandbox}.\n */\n static async get(\n params: (GetSnapshotParams | (GetSnapshotParams & Credentials)) &\n WithFetchOptions,\n ): Promise<Snapshot> {\n \"use step\";\n const credentials = await getCredentials(params);\n const client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n fetch: params.fetch,\n });\n\n const sandbox = await client.getSnapshot({\n snapshotId: params.snapshotId,\n signal: params.signal,\n });\n\n return new Snapshot({\n client,\n snapshot: sandbox.json.snapshot,\n });\n }\n\n /**\n * Delete this snapshot.\n *\n * @param opts - Optional parameters.\n * @param opts.signal - An AbortSignal to cancel the operation.\n * @returns A promise that resolves once the snapshot has been deleted.\n */\n async delete(opts?: { signal?: AbortSignal }): Promise<void> {\n \"use step\";\n const client = await this.ensureClient();\n const response = await client.deleteSnapshot({\n snapshotId: this.snapshot.id,\n signal: opts?.signal,\n });\n\n this.snapshot = response.json.snapshot;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AA6BA,IAAa,WAAb,MAAa,SAAS;;;;;;;CASpB,MAAc,eAAmC;AAC/C;AACA,MAAI,KAAK,QAAS,QAAO,KAAK;EAC9B,MAAM,cAAc,MAAMA,wCAAgB;AAC1C,OAAK,UAAU,IAAIC,6BAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACpB,CAAC;AACF,SAAO,KAAK;;;;;CAMd,IAAW,aAAqB;AAC9B,SAAO,KAAK,SAAS;;;;;CAMvB,IAAW,kBAA0B;AACnC,SAAO,KAAK,SAAS;;;;;CAMvB,IAAW,SAAqC;AAC9C,SAAO,KAAK,SAAS;;;;;CAMvB,IAAW,YAAoB;AAC7B,SAAO,KAAK,SAAS;;;;;CAMvB,IAAW,YAAkB;AAC3B,SAAO,IAAI,KAAK,KAAK,SAAS,UAAU;;;;;CAM1C,IAAW,YAAkB;AAC3B,SAAO,IAAI,KAAK,KAAK,SAAS,UAAU;;;;;CAM1C,IAAW,YAA8B;AACvC,MAAI,KAAK,SAAS,cAAc,OAC9B;AAGF,SAAO,IAAI,KAAK,KAAK,SAAS,UAAU;;;;;;;;CAc1C,QAAQC,qCAAoB,UAAwC;AAClE,SAAO,EACL,UAAU,SAAS,UACpB;;;;;;;;;;;CAYH,QAAQC,uCAAsB,MAAoC;AAChE,SAAO,IAAI,SAAS,EAClB,UAAU,KAAK,UAChB,CAAC;;CAGJ,YAAY,EACV,QACA,YAIC;OA9GK,UAA4B;AA+GlC,OAAK,UAAU,UAAU;AACzB,OAAK,WAAW;;;;;;;;;;;;;;;;CAiBlB,aAAa,KACX,QAGA;AACA;EACA,MAAM,cAAc,MAAMH,uCAAe,OAAO;EAChD,MAAM,SAAS,IAAIC,6BAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACnB,OAAO,QAAQ;GAChB,CAAC;EACF,MAAM,YAAY,OAAO,WAAoB;AAM3C,WALiB,MAAM,OAAO,cAAc;IAC1C,GAAG;IACH,GAAG;IACH,GAAI,WAAW,UAAa,EAAE,QAAQ;IACvC,CAAC,EACc;;AAGlB,SAAOG,kCADW,MAAM,UAAU,QAAQ,OAAO,EACf;GAChC,UAAU;GACV,WAAW;GACX,QAAQ,QAAQ;GACjB,CAAC;;;;;;;;;;;;;;;;;;CAmBJ,aAAa,KACX,QAIA;AACA;EACA,MAAM,cAAc,MAAMJ,uCAAe,OAAO;EAChD,MAAM,SAAS,IAAIC,6BAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACnB,OAAO,OAAO;GACf,CAAC;EACF,MAAM,YAAY,OAAO,eAAuB;AAM9C,WALiB,MAAM,OAAO,gBAAgB;IAC5C,GAAG;IACH,GAAG;IACH;IACD,CAAC,EACc;;AAGlB,SAAOG,kCADW,MAAM,UAAU,OAAO,WAAW,EAClB;GAChC,UAAU;GACV,WAAW;GACX,QAAQ,OAAO;GAChB,CAAC;;;;;;;;CASJ,aAAa,IACX,QAEmB;AACnB;EACA,MAAM,cAAc,MAAMJ,uCAAe,OAAO;EAChD,MAAM,SAAS,IAAIC,6BAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACnB,OAAO,OAAO;GACf,CAAC;AAOF,SAAO,IAAI,SAAS;GAClB;GACA,WAPc,MAAM,OAAO,YAAY;IACvC,YAAY,OAAO;IACnB,QAAQ,OAAO;IAChB,CAAC,EAIkB,KAAK;GACxB,CAAC;;;;;;;;;CAUJ,MAAM,OAAO,MAAgD;AAC3D;AAOA,OAAK,YALY,OADF,MAAM,KAAK,cAAc,EACV,eAAe;GAC3C,YAAY,KAAK,SAAS;GAC1B,QAAQ,MAAM;GACf,CAAC,EAEuB,KAAK"} | ||
| {"version":3,"file":"snapshot.cjs","names":["getCredentials","APIClient","WORKFLOW_SERIALIZE","WORKFLOW_DESERIALIZE","attachPaginator"],"sources":["../src/snapshot.ts"],"sourcesContent":["import { WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE } from \"@workflow/serde\";\nimport type { WithFetchOptions } from \"./api-client/api-client.js\";\nimport type { SnapshotMetadata } from \"./api-client/index.js\";\nimport { APIClient } from \"./api-client/index.js\";\nimport { type Credentials, getCredentials } from \"./utils/get-credentials.js\";\nimport { attachPaginator } from \"./utils/paginator.js\";\n\nexport interface SerializedSnapshot {\n snapshot: SnapshotMetadata;\n}\n\n/** @inline */\ninterface GetSnapshotParams {\n /**\n * Unique identifier of the snapshot.\n */\n snapshotId: string;\n /**\n * An AbortSignal to cancel the operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * A Snapshot is a saved state of a Sandbox that can be used to create new Sandboxes\n *\n * Use {@link Sandbox.snapshot} or {@link Snapshot.get} to construct.\n * @hideconstructor\n */\nexport class Snapshot {\n private _client: APIClient | null = null;\n\n /**\n * Lazily resolve credentials and construct an API client.\n * This is used in step contexts where the Snapshot was deserialized\n * without a client (e.g. when crossing workflow/step boundaries).\n * @internal\n */\n private async ensureClient(): Promise<APIClient> {\n \"use step\";\n if (this._client) return this._client;\n const credentials = await getCredentials();\n this._client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n });\n return this._client;\n }\n\n /**\n * Unique ID of this snapshot.\n */\n public get snapshotId(): string {\n return this.snapshot.id;\n }\n\n /**\n * The ID of the session from which this snapshot was created.\n */\n public get sourceSessionId(): string {\n return this.snapshot.sourceSessionId;\n }\n\n /**\n * All regions where this snapshot is available.\n */\n public get regions(): string[] {\n return this.snapshot.regions ?? [this.snapshot.region];\n }\n\n /**\n * The status of the snapshot.\n */\n public get status(): SnapshotMetadata[\"status\"] {\n return this.snapshot.status;\n }\n\n /**\n * The size of the snapshot in bytes, or null if not available.\n */\n public get sizeBytes(): number {\n return this.snapshot.sizeBytes;\n }\n\n /**\n * The creation date of this snapshot.\n */\n public get createdAt(): Date {\n return new Date(this.snapshot.createdAt);\n }\n\n /**\n * When this snapshot was last updated.\n */\n public get updatedAt(): Date {\n return new Date(this.snapshot.updatedAt);\n }\n\n /**\n * The expiration date of this snapshot, or undefined if it does not expire.\n */\n public get expiresAt(): Date | undefined {\n if (this.snapshot.expiresAt === undefined) {\n return undefined;\n }\n\n return new Date(this.snapshot.expiresAt);\n }\n\n /**\n * Internal metadata about this snapshot.\n */\n private snapshot: SnapshotMetadata;\n\n /**\n * Serialize a Snapshot instance to plain data for @workflow/serde.\n *\n * @param instance - The Snapshot instance to serialize\n * @returns A plain object containing snapshot metadata\n */\n static [WORKFLOW_SERIALIZE](instance: Snapshot): SerializedSnapshot {\n return {\n snapshot: instance.snapshot,\n };\n }\n\n /**\n * Deserialize a Snapshot from serialized data.\n *\n * The deserialized instance uses the serialized metadata synchronously and\n * lazily creates an API client only when methods perform API requests.\n *\n * @param data - The serialized snapshot data\n * @returns The reconstructed Snapshot instance\n */\n static [WORKFLOW_DESERIALIZE](data: SerializedSnapshot): Snapshot {\n return new Snapshot({\n snapshot: data.snapshot,\n });\n }\n\n constructor({\n client,\n snapshot,\n }: {\n client?: APIClient;\n snapshot: SnapshotMetadata;\n }) {\n this._client = client ?? null;\n this.snapshot = snapshot;\n }\n\n /**\n * Allow to get a list of snapshots for a team narrowed to the given params.\n * It returns both the snapshots and the pagination metadata to allow getting\n * the next page of results.\n *\n * The returned object is async-iterable to auto-paginate through all pages:\n *\n * ```ts\n * const result = await Snapshot.list({ name: \"my-sandbox\" });\n * for await (const snapshot of result) { ... }\n * // or: await result.toArray();\n * // or: for await (const page of result.pages()) { ... }\n * ```\n */\n static async list(\n params?: Partial<Parameters<APIClient[\"listSnapshots\"]>[0]> &\n Partial<Credentials> &\n WithFetchOptions,\n ) {\n \"use step\";\n const credentials = await getCredentials(params);\n const client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n fetch: params?.fetch,\n });\n const fetchPage = async (cursor?: string) => {\n const response = await client.listSnapshots({\n ...credentials,\n ...params,\n ...(cursor !== undefined && { cursor }),\n });\n return response.json;\n };\n const firstPage = await fetchPage(params?.cursor);\n return attachPaginator(firstPage, {\n itemsKey: \"snapshots\",\n fetchNext: fetchPage,\n signal: params?.signal,\n });\n }\n\n /**\n * Fetch the snapshot ancestry tree anchored on a given snapshot.\n * It returns both the tree nodes and the pagination metadata to allow\n * walking the next page of results in the same direction.\n *\n * The returned object is async-iterable to auto-paginate through all pages\n * in the direction set by `sortOrder` (`\"desc\"` walks ancestors, `\"asc\"`\n * walks descendants):\n *\n * ```ts\n * const result = await Snapshot.tree({ snapshotId: \"snap_abc\", sortOrder: \"desc\" });\n * for await (const node of result) { ... }\n * // or: await result.toArray();\n * // or: for await (const page of result.pages()) { ... }\n * ```\n */\n static async tree(\n params: { snapshotId: string } &\n Partial<Parameters<APIClient[\"getSnapshotTree\"]>[0]> &\n Partial<Credentials> &\n WithFetchOptions,\n ) {\n \"use step\";\n const credentials = await getCredentials(params);\n const client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n fetch: params.fetch,\n });\n const fetchPage = async (snapshotId: string) => {\n const response = await client.getSnapshotTree({\n ...credentials,\n ...params,\n snapshotId,\n });\n return response.json;\n };\n const firstPage = await fetchPage(params.snapshotId);\n return attachPaginator(firstPage, {\n itemsKey: \"snapshots\",\n fetchNext: fetchPage,\n signal: params.signal,\n });\n }\n\n /**\n * Retrieve an existing snapshot.\n *\n * @param params - Get parameters and optional credentials.\n * @returns A promise resolving to the {@link Sandbox}.\n */\n static async get(\n params: (GetSnapshotParams | (GetSnapshotParams & Credentials)) &\n WithFetchOptions,\n ): Promise<Snapshot> {\n \"use step\";\n const credentials = await getCredentials(params);\n const client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n fetch: params.fetch,\n });\n\n const sandbox = await client.getSnapshot({\n snapshotId: params.snapshotId,\n signal: params.signal,\n });\n\n return new Snapshot({\n client,\n snapshot: sandbox.json.snapshot,\n });\n }\n\n /**\n * Delete this snapshot.\n *\n * @param opts - Optional parameters.\n * @param opts.signal - An AbortSignal to cancel the operation.\n * @returns A promise that resolves once the snapshot has been deleted.\n */\n async delete(opts?: { signal?: AbortSignal }): Promise<void> {\n \"use step\";\n const client = await this.ensureClient();\n const response = await client.deleteSnapshot({\n snapshotId: this.snapshot.id,\n signal: opts?.signal,\n });\n\n this.snapshot = response.json.snapshot;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AA6BA,IAAa,WAAb,MAAa,SAAS;;;;;;;CASpB,MAAc,eAAmC;AAC/C;AACA,MAAI,KAAK,QAAS,QAAO,KAAK;EAC9B,MAAM,cAAc,MAAMA,wCAAgB;AAC1C,OAAK,UAAU,IAAIC,6BAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACpB,CAAC;AACF,SAAO,KAAK;;;;;CAMd,IAAW,aAAqB;AAC9B,SAAO,KAAK,SAAS;;;;;CAMvB,IAAW,kBAA0B;AACnC,SAAO,KAAK,SAAS;;;;;CAMvB,IAAW,UAAoB;AAC7B,SAAO,KAAK,SAAS,WAAW,CAAC,KAAK,SAAS,OAAO;;;;;CAMxD,IAAW,SAAqC;AAC9C,SAAO,KAAK,SAAS;;;;;CAMvB,IAAW,YAAoB;AAC7B,SAAO,KAAK,SAAS;;;;;CAMvB,IAAW,YAAkB;AAC3B,SAAO,IAAI,KAAK,KAAK,SAAS,UAAU;;;;;CAM1C,IAAW,YAAkB;AAC3B,SAAO,IAAI,KAAK,KAAK,SAAS,UAAU;;;;;CAM1C,IAAW,YAA8B;AACvC,MAAI,KAAK,SAAS,cAAc,OAC9B;AAGF,SAAO,IAAI,KAAK,KAAK,SAAS,UAAU;;;;;;;;CAc1C,QAAQC,qCAAoB,UAAwC;AAClE,SAAO,EACL,UAAU,SAAS,UACpB;;;;;;;;;;;CAYH,QAAQC,uCAAsB,MAAoC;AAChE,SAAO,IAAI,SAAS,EAClB,UAAU,KAAK,UAChB,CAAC;;CAGJ,YAAY,EACV,QACA,YAIC;OArHK,UAA4B;AAsHlC,OAAK,UAAU,UAAU;AACzB,OAAK,WAAW;;;;;;;;;;;;;;;;CAiBlB,aAAa,KACX,QAGA;AACA;EACA,MAAM,cAAc,MAAMH,uCAAe,OAAO;EAChD,MAAM,SAAS,IAAIC,6BAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACnB,OAAO,QAAQ;GAChB,CAAC;EACF,MAAM,YAAY,OAAO,WAAoB;AAM3C,WALiB,MAAM,OAAO,cAAc;IAC1C,GAAG;IACH,GAAG;IACH,GAAI,WAAW,UAAa,EAAE,QAAQ;IACvC,CAAC,EACc;;AAGlB,SAAOG,kCADW,MAAM,UAAU,QAAQ,OAAO,EACf;GAChC,UAAU;GACV,WAAW;GACX,QAAQ,QAAQ;GACjB,CAAC;;;;;;;;;;;;;;;;;;CAmBJ,aAAa,KACX,QAIA;AACA;EACA,MAAM,cAAc,MAAMJ,uCAAe,OAAO;EAChD,MAAM,SAAS,IAAIC,6BAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACnB,OAAO,OAAO;GACf,CAAC;EACF,MAAM,YAAY,OAAO,eAAuB;AAM9C,WALiB,MAAM,OAAO,gBAAgB;IAC5C,GAAG;IACH,GAAG;IACH;IACD,CAAC,EACc;;AAGlB,SAAOG,kCADW,MAAM,UAAU,OAAO,WAAW,EAClB;GAChC,UAAU;GACV,WAAW;GACX,QAAQ,OAAO;GAChB,CAAC;;;;;;;;CASJ,aAAa,IACX,QAEmB;AACnB;EACA,MAAM,cAAc,MAAMJ,uCAAe,OAAO;EAChD,MAAM,SAAS,IAAIC,6BAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACnB,OAAO,OAAO;GACf,CAAC;AAOF,SAAO,IAAI,SAAS;GAClB;GACA,WAPc,MAAM,OAAO,YAAY;IACvC,YAAY,OAAO;IACnB,QAAQ,OAAO;IAChB,CAAC,EAIkB,KAAK;GACxB,CAAC;;;;;;;;;CAUJ,MAAM,OAAO,MAAgD;AAC3D;AAOA,OAAK,YALY,OADF,MAAM,KAAK,cAAc,EACV,eAAe;GAC3C,YAAY,KAAK,SAAS;GAC1B,QAAQ,MAAM;GACf,CAAC,EAEuB,KAAK"} |
@@ -46,2 +46,6 @@ import { Paginator } from "./utils/paginator.cjs"; | ||
| /** | ||
| * All regions where this snapshot is available. | ||
| */ | ||
| get regions(): string[]; | ||
| /** | ||
| * The status of the snapshot. | ||
@@ -117,2 +121,3 @@ */ | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -156,2 +161,3 @@ lastUsedAt?: number | undefined; | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -170,2 +176,3 @@ lastUsedAt?: number | undefined; | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -191,2 +198,3 @@ lastUsedAt?: number | undefined; | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -205,2 +213,3 @@ lastUsedAt?: number | undefined; | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -207,0 +216,0 @@ lastUsedAt?: number | undefined; |
@@ -47,2 +47,6 @@ import { Paginator } from "./utils/paginator.js"; | ||
| /** | ||
| * All regions where this snapshot is available. | ||
| */ | ||
| get regions(): string[]; | ||
| /** | ||
| * The status of the snapshot. | ||
@@ -118,2 +122,3 @@ */ | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -157,2 +162,3 @@ lastUsedAt?: number | undefined; | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -171,2 +177,3 @@ lastUsedAt?: number | undefined; | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -192,2 +199,3 @@ lastUsedAt?: number | undefined; | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -206,2 +214,3 @@ lastUsedAt?: number | undefined; | ||
| updatedAt: number; | ||
| regions?: string[] | undefined; | ||
| expiresAt?: number | undefined; | ||
@@ -208,0 +217,0 @@ lastUsedAt?: number | undefined; |
+6
-0
@@ -44,2 +44,8 @@ import { APIClient } from "./api-client/api-client.js"; | ||
| /** | ||
| * All regions where this snapshot is available. | ||
| */ | ||
| get regions() { | ||
| return this.snapshot.regions ?? [this.snapshot.region]; | ||
| } | ||
| /** | ||
| * The status of the snapshot. | ||
@@ -46,0 +52,0 @@ */ |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"snapshot.js","names":[],"sources":["../src/snapshot.ts"],"sourcesContent":["import { WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE } from \"@workflow/serde\";\nimport type { WithFetchOptions } from \"./api-client/api-client.js\";\nimport type { SnapshotMetadata } from \"./api-client/index.js\";\nimport { APIClient } from \"./api-client/index.js\";\nimport { type Credentials, getCredentials } from \"./utils/get-credentials.js\";\nimport { attachPaginator } from \"./utils/paginator.js\";\n\nexport interface SerializedSnapshot {\n snapshot: SnapshotMetadata;\n}\n\n/** @inline */\ninterface GetSnapshotParams {\n /**\n * Unique identifier of the snapshot.\n */\n snapshotId: string;\n /**\n * An AbortSignal to cancel the operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * A Snapshot is a saved state of a Sandbox that can be used to create new Sandboxes\n *\n * Use {@link Sandbox.snapshot} or {@link Snapshot.get} to construct.\n * @hideconstructor\n */\nexport class Snapshot {\n private _client: APIClient | null = null;\n\n /**\n * Lazily resolve credentials and construct an API client.\n * This is used in step contexts where the Snapshot was deserialized\n * without a client (e.g. when crossing workflow/step boundaries).\n * @internal\n */\n private async ensureClient(): Promise<APIClient> {\n \"use step\";\n if (this._client) return this._client;\n const credentials = await getCredentials();\n this._client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n });\n return this._client;\n }\n\n /**\n * Unique ID of this snapshot.\n */\n public get snapshotId(): string {\n return this.snapshot.id;\n }\n\n /**\n * The ID of the session from which this snapshot was created.\n */\n public get sourceSessionId(): string {\n return this.snapshot.sourceSessionId;\n }\n\n /**\n * The status of the snapshot.\n */\n public get status(): SnapshotMetadata[\"status\"] {\n return this.snapshot.status;\n }\n\n /**\n * The size of the snapshot in bytes, or null if not available.\n */\n public get sizeBytes(): number {\n return this.snapshot.sizeBytes;\n }\n\n /**\n * The creation date of this snapshot.\n */\n public get createdAt(): Date {\n return new Date(this.snapshot.createdAt);\n }\n\n /**\n * When this snapshot was last updated.\n */\n public get updatedAt(): Date {\n return new Date(this.snapshot.updatedAt);\n }\n\n /**\n * The expiration date of this snapshot, or undefined if it does not expire.\n */\n public get expiresAt(): Date | undefined {\n if (this.snapshot.expiresAt === undefined) {\n return undefined;\n }\n\n return new Date(this.snapshot.expiresAt);\n }\n\n /**\n * Internal metadata about this snapshot.\n */\n private snapshot: SnapshotMetadata;\n\n /**\n * Serialize a Snapshot instance to plain data for @workflow/serde.\n *\n * @param instance - The Snapshot instance to serialize\n * @returns A plain object containing snapshot metadata\n */\n static [WORKFLOW_SERIALIZE](instance: Snapshot): SerializedSnapshot {\n return {\n snapshot: instance.snapshot,\n };\n }\n\n /**\n * Deserialize a Snapshot from serialized data.\n *\n * The deserialized instance uses the serialized metadata synchronously and\n * lazily creates an API client only when methods perform API requests.\n *\n * @param data - The serialized snapshot data\n * @returns The reconstructed Snapshot instance\n */\n static [WORKFLOW_DESERIALIZE](data: SerializedSnapshot): Snapshot {\n return new Snapshot({\n snapshot: data.snapshot,\n });\n }\n\n constructor({\n client,\n snapshot,\n }: {\n client?: APIClient;\n snapshot: SnapshotMetadata;\n }) {\n this._client = client ?? null;\n this.snapshot = snapshot;\n }\n\n /**\n * Allow to get a list of snapshots for a team narrowed to the given params.\n * It returns both the snapshots and the pagination metadata to allow getting\n * the next page of results.\n *\n * The returned object is async-iterable to auto-paginate through all pages:\n *\n * ```ts\n * const result = await Snapshot.list({ name: \"my-sandbox\" });\n * for await (const snapshot of result) { ... }\n * // or: await result.toArray();\n * // or: for await (const page of result.pages()) { ... }\n * ```\n */\n static async list(\n params?: Partial<Parameters<APIClient[\"listSnapshots\"]>[0]> &\n Partial<Credentials> &\n WithFetchOptions,\n ) {\n \"use step\";\n const credentials = await getCredentials(params);\n const client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n fetch: params?.fetch,\n });\n const fetchPage = async (cursor?: string) => {\n const response = await client.listSnapshots({\n ...credentials,\n ...params,\n ...(cursor !== undefined && { cursor }),\n });\n return response.json;\n };\n const firstPage = await fetchPage(params?.cursor);\n return attachPaginator(firstPage, {\n itemsKey: \"snapshots\",\n fetchNext: fetchPage,\n signal: params?.signal,\n });\n }\n\n /**\n * Fetch the snapshot ancestry tree anchored on a given snapshot.\n * It returns both the tree nodes and the pagination metadata to allow\n * walking the next page of results in the same direction.\n *\n * The returned object is async-iterable to auto-paginate through all pages\n * in the direction set by `sortOrder` (`\"desc\"` walks ancestors, `\"asc\"`\n * walks descendants):\n *\n * ```ts\n * const result = await Snapshot.tree({ snapshotId: \"snap_abc\", sortOrder: \"desc\" });\n * for await (const node of result) { ... }\n * // or: await result.toArray();\n * // or: for await (const page of result.pages()) { ... }\n * ```\n */\n static async tree(\n params: { snapshotId: string } &\n Partial<Parameters<APIClient[\"getSnapshotTree\"]>[0]> &\n Partial<Credentials> &\n WithFetchOptions,\n ) {\n \"use step\";\n const credentials = await getCredentials(params);\n const client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n fetch: params.fetch,\n });\n const fetchPage = async (snapshotId: string) => {\n const response = await client.getSnapshotTree({\n ...credentials,\n ...params,\n snapshotId,\n });\n return response.json;\n };\n const firstPage = await fetchPage(params.snapshotId);\n return attachPaginator(firstPage, {\n itemsKey: \"snapshots\",\n fetchNext: fetchPage,\n signal: params.signal,\n });\n }\n\n /**\n * Retrieve an existing snapshot.\n *\n * @param params - Get parameters and optional credentials.\n * @returns A promise resolving to the {@link Sandbox}.\n */\n static async get(\n params: (GetSnapshotParams | (GetSnapshotParams & Credentials)) &\n WithFetchOptions,\n ): Promise<Snapshot> {\n \"use step\";\n const credentials = await getCredentials(params);\n const client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n fetch: params.fetch,\n });\n\n const sandbox = await client.getSnapshot({\n snapshotId: params.snapshotId,\n signal: params.signal,\n });\n\n return new Snapshot({\n client,\n snapshot: sandbox.json.snapshot,\n });\n }\n\n /**\n * Delete this snapshot.\n *\n * @param opts - Optional parameters.\n * @param opts.signal - An AbortSignal to cancel the operation.\n * @returns A promise that resolves once the snapshot has been deleted.\n */\n async delete(opts?: { signal?: AbortSignal }): Promise<void> {\n \"use step\";\n const client = await this.ensureClient();\n const response = await client.deleteSnapshot({\n snapshotId: this.snapshot.id,\n signal: opts?.signal,\n });\n\n this.snapshot = response.json.snapshot;\n }\n}\n"],"mappings":";;;;;;;;;;;;;AA6BA,IAAa,WAAb,MAAa,SAAS;;;;;;;CASpB,MAAc,eAAmC;AAC/C;AACA,MAAI,KAAK,QAAS,QAAO,KAAK;EAC9B,MAAM,cAAc,MAAM,gBAAgB;AAC1C,OAAK,UAAU,IAAI,UAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACpB,CAAC;AACF,SAAO,KAAK;;;;;CAMd,IAAW,aAAqB;AAC9B,SAAO,KAAK,SAAS;;;;;CAMvB,IAAW,kBAA0B;AACnC,SAAO,KAAK,SAAS;;;;;CAMvB,IAAW,SAAqC;AAC9C,SAAO,KAAK,SAAS;;;;;CAMvB,IAAW,YAAoB;AAC7B,SAAO,KAAK,SAAS;;;;;CAMvB,IAAW,YAAkB;AAC3B,SAAO,IAAI,KAAK,KAAK,SAAS,UAAU;;;;;CAM1C,IAAW,YAAkB;AAC3B,SAAO,IAAI,KAAK,KAAK,SAAS,UAAU;;;;;CAM1C,IAAW,YAA8B;AACvC,MAAI,KAAK,SAAS,cAAc,OAC9B;AAGF,SAAO,IAAI,KAAK,KAAK,SAAS,UAAU;;;;;;;;CAc1C,QAAQ,oBAAoB,UAAwC;AAClE,SAAO,EACL,UAAU,SAAS,UACpB;;;;;;;;;;;CAYH,QAAQ,sBAAsB,MAAoC;AAChE,SAAO,IAAI,SAAS,EAClB,UAAU,KAAK,UAChB,CAAC;;CAGJ,YAAY,EACV,QACA,YAIC;OA9GK,UAA4B;AA+GlC,OAAK,UAAU,UAAU;AACzB,OAAK,WAAW;;;;;;;;;;;;;;;;CAiBlB,aAAa,KACX,QAGA;AACA;EACA,MAAM,cAAc,MAAM,eAAe,OAAO;EAChD,MAAM,SAAS,IAAI,UAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACnB,OAAO,QAAQ;GAChB,CAAC;EACF,MAAM,YAAY,OAAO,WAAoB;AAM3C,WALiB,MAAM,OAAO,cAAc;IAC1C,GAAG;IACH,GAAG;IACH,GAAI,WAAW,UAAa,EAAE,QAAQ;IACvC,CAAC,EACc;;AAGlB,SAAO,gBADW,MAAM,UAAU,QAAQ,OAAO,EACf;GAChC,UAAU;GACV,WAAW;GACX,QAAQ,QAAQ;GACjB,CAAC;;;;;;;;;;;;;;;;;;CAmBJ,aAAa,KACX,QAIA;AACA;EACA,MAAM,cAAc,MAAM,eAAe,OAAO;EAChD,MAAM,SAAS,IAAI,UAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACnB,OAAO,OAAO;GACf,CAAC;EACF,MAAM,YAAY,OAAO,eAAuB;AAM9C,WALiB,MAAM,OAAO,gBAAgB;IAC5C,GAAG;IACH,GAAG;IACH;IACD,CAAC,EACc;;AAGlB,SAAO,gBADW,MAAM,UAAU,OAAO,WAAW,EAClB;GAChC,UAAU;GACV,WAAW;GACX,QAAQ,OAAO;GAChB,CAAC;;;;;;;;CASJ,aAAa,IACX,QAEmB;AACnB;EACA,MAAM,cAAc,MAAM,eAAe,OAAO;EAChD,MAAM,SAAS,IAAI,UAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACnB,OAAO,OAAO;GACf,CAAC;AAOF,SAAO,IAAI,SAAS;GAClB;GACA,WAPc,MAAM,OAAO,YAAY;IACvC,YAAY,OAAO;IACnB,QAAQ,OAAO;IAChB,CAAC,EAIkB,KAAK;GACxB,CAAC;;;;;;;;;CAUJ,MAAM,OAAO,MAAgD;AAC3D;AAOA,OAAK,YALY,OADF,MAAM,KAAK,cAAc,EACV,eAAe;GAC3C,YAAY,KAAK,SAAS;GAC1B,QAAQ,MAAM;GACf,CAAC,EAEuB,KAAK"} | ||
| {"version":3,"file":"snapshot.js","names":[],"sources":["../src/snapshot.ts"],"sourcesContent":["import { WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE } from \"@workflow/serde\";\nimport type { WithFetchOptions } from \"./api-client/api-client.js\";\nimport type { SnapshotMetadata } from \"./api-client/index.js\";\nimport { APIClient } from \"./api-client/index.js\";\nimport { type Credentials, getCredentials } from \"./utils/get-credentials.js\";\nimport { attachPaginator } from \"./utils/paginator.js\";\n\nexport interface SerializedSnapshot {\n snapshot: SnapshotMetadata;\n}\n\n/** @inline */\ninterface GetSnapshotParams {\n /**\n * Unique identifier of the snapshot.\n */\n snapshotId: string;\n /**\n * An AbortSignal to cancel the operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * A Snapshot is a saved state of a Sandbox that can be used to create new Sandboxes\n *\n * Use {@link Sandbox.snapshot} or {@link Snapshot.get} to construct.\n * @hideconstructor\n */\nexport class Snapshot {\n private _client: APIClient | null = null;\n\n /**\n * Lazily resolve credentials and construct an API client.\n * This is used in step contexts where the Snapshot was deserialized\n * without a client (e.g. when crossing workflow/step boundaries).\n * @internal\n */\n private async ensureClient(): Promise<APIClient> {\n \"use step\";\n if (this._client) return this._client;\n const credentials = await getCredentials();\n this._client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n });\n return this._client;\n }\n\n /**\n * Unique ID of this snapshot.\n */\n public get snapshotId(): string {\n return this.snapshot.id;\n }\n\n /**\n * The ID of the session from which this snapshot was created.\n */\n public get sourceSessionId(): string {\n return this.snapshot.sourceSessionId;\n }\n\n /**\n * All regions where this snapshot is available.\n */\n public get regions(): string[] {\n return this.snapshot.regions ?? [this.snapshot.region];\n }\n\n /**\n * The status of the snapshot.\n */\n public get status(): SnapshotMetadata[\"status\"] {\n return this.snapshot.status;\n }\n\n /**\n * The size of the snapshot in bytes, or null if not available.\n */\n public get sizeBytes(): number {\n return this.snapshot.sizeBytes;\n }\n\n /**\n * The creation date of this snapshot.\n */\n public get createdAt(): Date {\n return new Date(this.snapshot.createdAt);\n }\n\n /**\n * When this snapshot was last updated.\n */\n public get updatedAt(): Date {\n return new Date(this.snapshot.updatedAt);\n }\n\n /**\n * The expiration date of this snapshot, or undefined if it does not expire.\n */\n public get expiresAt(): Date | undefined {\n if (this.snapshot.expiresAt === undefined) {\n return undefined;\n }\n\n return new Date(this.snapshot.expiresAt);\n }\n\n /**\n * Internal metadata about this snapshot.\n */\n private snapshot: SnapshotMetadata;\n\n /**\n * Serialize a Snapshot instance to plain data for @workflow/serde.\n *\n * @param instance - The Snapshot instance to serialize\n * @returns A plain object containing snapshot metadata\n */\n static [WORKFLOW_SERIALIZE](instance: Snapshot): SerializedSnapshot {\n return {\n snapshot: instance.snapshot,\n };\n }\n\n /**\n * Deserialize a Snapshot from serialized data.\n *\n * The deserialized instance uses the serialized metadata synchronously and\n * lazily creates an API client only when methods perform API requests.\n *\n * @param data - The serialized snapshot data\n * @returns The reconstructed Snapshot instance\n */\n static [WORKFLOW_DESERIALIZE](data: SerializedSnapshot): Snapshot {\n return new Snapshot({\n snapshot: data.snapshot,\n });\n }\n\n constructor({\n client,\n snapshot,\n }: {\n client?: APIClient;\n snapshot: SnapshotMetadata;\n }) {\n this._client = client ?? null;\n this.snapshot = snapshot;\n }\n\n /**\n * Allow to get a list of snapshots for a team narrowed to the given params.\n * It returns both the snapshots and the pagination metadata to allow getting\n * the next page of results.\n *\n * The returned object is async-iterable to auto-paginate through all pages:\n *\n * ```ts\n * const result = await Snapshot.list({ name: \"my-sandbox\" });\n * for await (const snapshot of result) { ... }\n * // or: await result.toArray();\n * // or: for await (const page of result.pages()) { ... }\n * ```\n */\n static async list(\n params?: Partial<Parameters<APIClient[\"listSnapshots\"]>[0]> &\n Partial<Credentials> &\n WithFetchOptions,\n ) {\n \"use step\";\n const credentials = await getCredentials(params);\n const client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n fetch: params?.fetch,\n });\n const fetchPage = async (cursor?: string) => {\n const response = await client.listSnapshots({\n ...credentials,\n ...params,\n ...(cursor !== undefined && { cursor }),\n });\n return response.json;\n };\n const firstPage = await fetchPage(params?.cursor);\n return attachPaginator(firstPage, {\n itemsKey: \"snapshots\",\n fetchNext: fetchPage,\n signal: params?.signal,\n });\n }\n\n /**\n * Fetch the snapshot ancestry tree anchored on a given snapshot.\n * It returns both the tree nodes and the pagination metadata to allow\n * walking the next page of results in the same direction.\n *\n * The returned object is async-iterable to auto-paginate through all pages\n * in the direction set by `sortOrder` (`\"desc\"` walks ancestors, `\"asc\"`\n * walks descendants):\n *\n * ```ts\n * const result = await Snapshot.tree({ snapshotId: \"snap_abc\", sortOrder: \"desc\" });\n * for await (const node of result) { ... }\n * // or: await result.toArray();\n * // or: for await (const page of result.pages()) { ... }\n * ```\n */\n static async tree(\n params: { snapshotId: string } &\n Partial<Parameters<APIClient[\"getSnapshotTree\"]>[0]> &\n Partial<Credentials> &\n WithFetchOptions,\n ) {\n \"use step\";\n const credentials = await getCredentials(params);\n const client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n fetch: params.fetch,\n });\n const fetchPage = async (snapshotId: string) => {\n const response = await client.getSnapshotTree({\n ...credentials,\n ...params,\n snapshotId,\n });\n return response.json;\n };\n const firstPage = await fetchPage(params.snapshotId);\n return attachPaginator(firstPage, {\n itemsKey: \"snapshots\",\n fetchNext: fetchPage,\n signal: params.signal,\n });\n }\n\n /**\n * Retrieve an existing snapshot.\n *\n * @param params - Get parameters and optional credentials.\n * @returns A promise resolving to the {@link Sandbox}.\n */\n static async get(\n params: (GetSnapshotParams | (GetSnapshotParams & Credentials)) &\n WithFetchOptions,\n ): Promise<Snapshot> {\n \"use step\";\n const credentials = await getCredentials(params);\n const client = new APIClient({\n teamId: credentials.teamId,\n token: credentials.token,\n fetch: params.fetch,\n });\n\n const sandbox = await client.getSnapshot({\n snapshotId: params.snapshotId,\n signal: params.signal,\n });\n\n return new Snapshot({\n client,\n snapshot: sandbox.json.snapshot,\n });\n }\n\n /**\n * Delete this snapshot.\n *\n * @param opts - Optional parameters.\n * @param opts.signal - An AbortSignal to cancel the operation.\n * @returns A promise that resolves once the snapshot has been deleted.\n */\n async delete(opts?: { signal?: AbortSignal }): Promise<void> {\n \"use step\";\n const client = await this.ensureClient();\n const response = await client.deleteSnapshot({\n snapshotId: this.snapshot.id,\n signal: opts?.signal,\n });\n\n this.snapshot = response.json.snapshot;\n }\n}\n"],"mappings":";;;;;;;;;;;;;AA6BA,IAAa,WAAb,MAAa,SAAS;;;;;;;CASpB,MAAc,eAAmC;AAC/C;AACA,MAAI,KAAK,QAAS,QAAO,KAAK;EAC9B,MAAM,cAAc,MAAM,gBAAgB;AAC1C,OAAK,UAAU,IAAI,UAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACpB,CAAC;AACF,SAAO,KAAK;;;;;CAMd,IAAW,aAAqB;AAC9B,SAAO,KAAK,SAAS;;;;;CAMvB,IAAW,kBAA0B;AACnC,SAAO,KAAK,SAAS;;;;;CAMvB,IAAW,UAAoB;AAC7B,SAAO,KAAK,SAAS,WAAW,CAAC,KAAK,SAAS,OAAO;;;;;CAMxD,IAAW,SAAqC;AAC9C,SAAO,KAAK,SAAS;;;;;CAMvB,IAAW,YAAoB;AAC7B,SAAO,KAAK,SAAS;;;;;CAMvB,IAAW,YAAkB;AAC3B,SAAO,IAAI,KAAK,KAAK,SAAS,UAAU;;;;;CAM1C,IAAW,YAAkB;AAC3B,SAAO,IAAI,KAAK,KAAK,SAAS,UAAU;;;;;CAM1C,IAAW,YAA8B;AACvC,MAAI,KAAK,SAAS,cAAc,OAC9B;AAGF,SAAO,IAAI,KAAK,KAAK,SAAS,UAAU;;;;;;;;CAc1C,QAAQ,oBAAoB,UAAwC;AAClE,SAAO,EACL,UAAU,SAAS,UACpB;;;;;;;;;;;CAYH,QAAQ,sBAAsB,MAAoC;AAChE,SAAO,IAAI,SAAS,EAClB,UAAU,KAAK,UAChB,CAAC;;CAGJ,YAAY,EACV,QACA,YAIC;OArHK,UAA4B;AAsHlC,OAAK,UAAU,UAAU;AACzB,OAAK,WAAW;;;;;;;;;;;;;;;;CAiBlB,aAAa,KACX,QAGA;AACA;EACA,MAAM,cAAc,MAAM,eAAe,OAAO;EAChD,MAAM,SAAS,IAAI,UAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACnB,OAAO,QAAQ;GAChB,CAAC;EACF,MAAM,YAAY,OAAO,WAAoB;AAM3C,WALiB,MAAM,OAAO,cAAc;IAC1C,GAAG;IACH,GAAG;IACH,GAAI,WAAW,UAAa,EAAE,QAAQ;IACvC,CAAC,EACc;;AAGlB,SAAO,gBADW,MAAM,UAAU,QAAQ,OAAO,EACf;GAChC,UAAU;GACV,WAAW;GACX,QAAQ,QAAQ;GACjB,CAAC;;;;;;;;;;;;;;;;;;CAmBJ,aAAa,KACX,QAIA;AACA;EACA,MAAM,cAAc,MAAM,eAAe,OAAO;EAChD,MAAM,SAAS,IAAI,UAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACnB,OAAO,OAAO;GACf,CAAC;EACF,MAAM,YAAY,OAAO,eAAuB;AAM9C,WALiB,MAAM,OAAO,gBAAgB;IAC5C,GAAG;IACH,GAAG;IACH;IACD,CAAC,EACc;;AAGlB,SAAO,gBADW,MAAM,UAAU,OAAO,WAAW,EAClB;GAChC,UAAU;GACV,WAAW;GACX,QAAQ,OAAO;GAChB,CAAC;;;;;;;;CASJ,aAAa,IACX,QAEmB;AACnB;EACA,MAAM,cAAc,MAAM,eAAe,OAAO;EAChD,MAAM,SAAS,IAAI,UAAU;GAC3B,QAAQ,YAAY;GACpB,OAAO,YAAY;GACnB,OAAO,OAAO;GACf,CAAC;AAOF,SAAO,IAAI,SAAS;GAClB;GACA,WAPc,MAAM,OAAO,YAAY;IACvC,YAAY,OAAO;IACnB,QAAQ,OAAO;IAChB,CAAC,EAIkB,KAAK;GACxB,CAAC;;;;;;;;;CAUJ,MAAM,OAAO,MAAgD;AAC3D;AAOA,OAAK,YALY,OADF,MAAM,KAAK,cAAc,EACV,eAAe;GAC3C,YAAY,KAAK,SAAS;GAC1B,QAAQ,MAAM;GACf,CAAC,EAEuB,KAAK"} |
+1
-1
| //#region src/version.ts | ||
| const VERSION = "3.1.0-beta.0"; | ||
| const VERSION = "3.1.0-beta.1"; | ||
@@ -5,0 +5,0 @@ //#endregion |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"version.cjs","names":[],"sources":["../src/version.ts"],"sourcesContent":["// Autogenerated by inject-version.ts\nexport const VERSION = \"3.1.0-beta.0\";\n"],"mappings":";;AACA,MAAa,UAAU"} | ||
| {"version":3,"file":"version.cjs","names":[],"sources":["../src/version.ts"],"sourcesContent":["// Autogenerated by inject-version.ts\nexport const VERSION = \"3.1.0-beta.1\";\n"],"mappings":";;AACA,MAAa,UAAU"} |
+1
-1
| //#region src/version.ts | ||
| const VERSION = "3.1.0-beta.0"; | ||
| const VERSION = "3.1.0-beta.1"; | ||
@@ -4,0 +4,0 @@ //#endregion |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"version.js","names":[],"sources":["../src/version.ts"],"sourcesContent":["// Autogenerated by inject-version.ts\nexport const VERSION = \"3.1.0-beta.0\";\n"],"mappings":";AACA,MAAa,UAAU"} | ||
| {"version":3,"file":"version.js","names":[],"sources":["../src/version.ts"],"sourcesContent":["// Autogenerated by inject-version.ts\nexport const VERSION = \"3.1.0-beta.1\";\n"],"mappings":";AACA,MAAa,UAAU"} |
+2
-1
| { | ||
| "name": "@vercel/sandbox", | ||
| "version": "3.1.0-beta.0", | ||
| "version": "3.1.0-beta.1", | ||
| "description": "Software Development Kit for Vercel Sandbox", | ||
@@ -53,2 +53,3 @@ "type": "module", | ||
| "jsonlines": "0.1.1", | ||
| "lru-cache": "^10.4.3", | ||
| "ms": "2.1.3", | ||
@@ -55,0 +56,0 @@ "picocolors": "^1.1.1", |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
1533383
1.5%217
1.88%17773
1.3%12
9.09%+ Added
+ Added