Skip to content

Commit 6771396

Browse files
authored
feat: add support for listing sandboxes (#33)
1 parent c5f262d commit 6771396

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

src/index.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,18 @@ import {
66
SandboxStartData,
77
CreateSandboxOpts,
88
VMTier,
9+
SandboxListOpts,
10+
SandboxInfo,
911
} from "./sandbox-client";
1012

11-
export { SandboxClient, SandboxStartData, CreateSandboxOpts, VMTier };
13+
export {
14+
SandboxClient,
15+
SandboxStartData,
16+
CreateSandboxOpts,
17+
VMTier,
18+
SandboxListOpts,
19+
SandboxInfo,
20+
};
1221
export * from "./sandbox";
1322

1423
export interface ClientOpts {

src/sandbox-client.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { Client } from "@hey-api/client-fetch";
44
import type { VmStartResponse, tier } from "./client";
55
import {
66
sandboxFork,
7+
sandboxList,
78
vmHibernate,
89
vmShutdown,
910
vmStart,
@@ -16,6 +17,24 @@ import { handleResponse } from "./utils/handle-response";
1617
export type SandboxPrivacy = "public" | "unlisted" | "private";
1718
export type SandboxStartData = Required<VmStartResponse>["data"];
1819

20+
export type SandboxInfo = {
21+
id: string;
22+
createdAt: Date;
23+
updatedAt: Date;
24+
title?: string;
25+
description?: string;
26+
privacy: SandboxPrivacy;
27+
tags: string[];
28+
};
29+
30+
export type SandboxListOpts = {
31+
tags?: string[];
32+
page?: number;
33+
pageSize?: number;
34+
orderBy?: "inserted_at" | "updated_at";
35+
direction?: "asc" | "desc";
36+
};
37+
1938
export const DEFAULT_SUBSCRIPTIONS = {
2039
client: {
2140
status: true,
@@ -352,6 +371,35 @@ export class SandboxClient {
352371
handleResponse(response, `Failed to hibernate sandbox ${id}`);
353372
}
354373

374+
/**
375+
* List sandboxes from the current workspace with optional filters.
376+
* Results are limited to a maximum of 50 sandboxes per request.
377+
*/
378+
async list(opts: SandboxListOpts = {}): Promise<SandboxInfo[]> {
379+
const response = await sandboxList({
380+
client: this.apiClient,
381+
query: {
382+
tags: opts.tags?.join(","),
383+
page: opts.page,
384+
page_size: opts.pageSize,
385+
order_by: opts.orderBy,
386+
direction: opts.direction,
387+
},
388+
});
389+
390+
const info = handleResponse(response, "Failed to list sandboxes");
391+
392+
return info.sandboxes.map((sandbox) => ({
393+
id: sandbox.id,
394+
createdAt: new Date(sandbox.created_at),
395+
updatedAt: new Date(sandbox.updated_at),
396+
title: sandbox.title ?? undefined,
397+
description: sandbox.description ?? undefined,
398+
privacy: privacyFromNumber(sandbox.privacy),
399+
tags: sandbox.tags,
400+
}));
401+
}
402+
355403
/**
356404
* Updates the specs that this sandbox runs on. It will dynamically scale the sandbox to the
357405
* new specs without a reboot. Be careful when scaling specs down, if the VM is using more memory
@@ -467,3 +515,16 @@ function privacyToNumber(privacy: SandboxPrivacy): number {
467515
return 2;
468516
}
469517
}
518+
519+
function privacyFromNumber(privacy: number): SandboxPrivacy {
520+
switch (privacy) {
521+
case 0:
522+
return "public";
523+
case 1:
524+
return "unlisted";
525+
case 2:
526+
return "private";
527+
}
528+
529+
throw new Error(`Invalid privacy number: ${privacy}`);
530+
}

0 commit comments

Comments
 (0)