diff --git a/packages/js-sdk/src/index.ts b/packages/js-sdk/src/index.ts index e67092a01c..9989b0adf4 100644 --- a/packages/js-sdk/src/index.ts +++ b/packages/js-sdk/src/index.ts @@ -61,6 +61,7 @@ export type { SandboxLifecycle, SandboxInfoLifecycle, SnapshotInfo, + CreateSnapshotOpts, SnapshotListOpts, SnapshotPaginator, } from './sandbox/sandboxApi' diff --git a/packages/js-sdk/src/sandbox/index.ts b/packages/js-sdk/src/sandbox/index.ts index 7384dc7af2..f8a66de55c 100644 --- a/packages/js-sdk/src/sandbox/index.ts +++ b/packages/js-sdk/src/sandbox/index.ts @@ -21,6 +21,7 @@ import { SandboxPaginator, SandboxBetaCreateOpts, SandboxApiOpts, + CreateSnapshotOpts, SnapshotListOpts, SnapshotInfo, SnapshotPaginator, @@ -614,17 +615,17 @@ export class Sandbox extends SandboxApi { * const sandbox = await Sandbox.create() * await sandbox.files.write('/app/state.json', '{"step": 1}') * - * // Create a snapshot - * const snapshot = await sandbox.createSnapshot() + * // Create a named snapshot + * const snapshot = await sandbox.createSnapshot({ name: 'my-snapshot' }) * * // Create a new sandbox from the snapshot * const newSandbox = await Sandbox.create(snapshot.snapshotId) * ``` */ - async createSnapshot(opts?: SandboxApiOpts): Promise { + async createSnapshot(opts?: CreateSnapshotOpts): Promise { return await SandboxApi.createSnapshot( this.sandboxId, - this.resolveApiOpts(opts) + { ...this.resolveApiOpts(opts), ...opts } ) } diff --git a/packages/js-sdk/src/sandbox/sandboxApi.ts b/packages/js-sdk/src/sandbox/sandboxApi.ts index f1bcf86bf2..3b446e4bee 100644 --- a/packages/js-sdk/src/sandbox/sandboxApi.ts +++ b/packages/js-sdk/src/sandbox/sandboxApi.ts @@ -248,6 +248,18 @@ export interface SandboxMetricsOpts extends SandboxApiOpts { /** * Options for listing snapshots. */ +/** + * Options for creating a snapshot. + */ +export interface CreateSnapshotOpts extends SandboxApiOpts { + /** + * Optional name for the snapshot template. + * If a snapshot template with this name already exists, + * a new build will be assigned to the existing template. + */ + name?: string +} + export interface SnapshotListOpts extends SandboxApiOpts { /** * Filter snapshots by source sandbox ID. @@ -276,6 +288,11 @@ export interface SnapshotInfo { * Can be used with Sandbox.create() to create a new sandbox from this snapshot. */ snapshotId: string + /** + * Full names of the snapshot template including team namespace and tag + * (e.g. team-slug/my-snapshot:v2). + */ + names: string[] } /** @@ -687,7 +704,7 @@ export class SandboxApi { */ static async createSnapshot( sandboxId: string, - opts?: SandboxApiOpts + opts?: CreateSnapshotOpts ): Promise { const config = new ConnectionConfig(opts) const client = new ApiClient(config) @@ -698,7 +715,9 @@ export class SandboxApi { sandboxID: sandboxId, }, }, - body: {}, + body: { + ...(opts?.name && { name: opts.name }), + }, signal: config.getSignal(opts?.requestTimeoutMs), }) @@ -713,6 +732,7 @@ export class SandboxApi { return { snapshotId: res.data!.snapshotID, + names: res.data!.names ?? [], } } @@ -1038,6 +1058,7 @@ export class SnapshotPaginator extends BasePaginator { return (res.data ?? []).map( (snapshot: components['schemas']['SnapshotInfo']) => ({ snapshotId: snapshot.snapshotID, + names: snapshot.names ?? [], }) ) }