sandsnap 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +287 -0
  3. package/dist/commands/delete.d.ts +9 -0
  4. package/dist/commands/delete.d.ts.map +1 -0
  5. package/dist/commands/delete.js +50 -0
  6. package/dist/commands/delete.js.map +1 -0
  7. package/dist/commands/evolve.d.ts +17 -0
  8. package/dist/commands/evolve.d.ts.map +1 -0
  9. package/dist/commands/evolve.js +228 -0
  10. package/dist/commands/evolve.js.map +1 -0
  11. package/dist/commands/list.d.ts +10 -0
  12. package/dist/commands/list.d.ts.map +1 -0
  13. package/dist/commands/list.js +47 -0
  14. package/dist/commands/list.js.map +1 -0
  15. package/dist/commands/prune.d.ts +13 -0
  16. package/dist/commands/prune.d.ts.map +1 -0
  17. package/dist/commands/prune.js +75 -0
  18. package/dist/commands/prune.js.map +1 -0
  19. package/dist/commands/run.d.ts +15 -0
  20. package/dist/commands/run.d.ts.map +1 -0
  21. package/dist/commands/run.js +132 -0
  22. package/dist/commands/run.js.map +1 -0
  23. package/dist/commands/sandboxes.d.ts +11 -0
  24. package/dist/commands/sandboxes.d.ts.map +1 -0
  25. package/dist/commands/sandboxes.js +79 -0
  26. package/dist/commands/sandboxes.js.map +1 -0
  27. package/dist/index.d.ts +3 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +83 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/lib/client.d.ts +14 -0
  32. package/dist/lib/client.d.ts.map +1 -0
  33. package/dist/lib/client.js +30 -0
  34. package/dist/lib/client.js.map +1 -0
  35. package/dist/lib/copy.d.ts +14 -0
  36. package/dist/lib/copy.d.ts.map +1 -0
  37. package/dist/lib/copy.js +91 -0
  38. package/dist/lib/copy.js.map +1 -0
  39. package/dist/lib/output.d.ts +28 -0
  40. package/dist/lib/output.d.ts.map +1 -0
  41. package/dist/lib/output.js +69 -0
  42. package/dist/lib/output.js.map +1 -0
  43. package/dist/lib/parse.d.ts +23 -0
  44. package/dist/lib/parse.d.ts.map +1 -0
  45. package/dist/lib/parse.js +58 -0
  46. package/dist/lib/parse.js.map +1 -0
  47. package/dist/lib/parse.test.d.ts +2 -0
  48. package/dist/lib/parse.test.d.ts.map +1 -0
  49. package/dist/lib/parse.test.js +139 -0
  50. package/dist/lib/parse.test.js.map +1 -0
  51. package/dist/lib/stdin.d.ts +24 -0
  52. package/dist/lib/stdin.d.ts.map +1 -0
  53. package/dist/lib/stdin.js +79 -0
  54. package/dist/lib/stdin.js.map +1 -0
  55. package/package.json +55 -0
@@ -0,0 +1,47 @@
1
+ /**
2
+ * sandboxer list - List all snapshots
3
+ */
4
+ import { getClient } from "../lib/client.js";
5
+ import { table, formatBytes } from "../lib/output.js";
6
+ export async function list(options) {
7
+ const client = getClient();
8
+ try {
9
+ const page = await client.snapshots.list();
10
+ let snapshots = page.items;
11
+ // Filter by region if specified
12
+ if (options.region) {
13
+ snapshots = snapshots.filter((s) => s.region === options.region);
14
+ }
15
+ if (options.json) {
16
+ // Snapshot class uses getters, need to extract properties manually
17
+ const data = snapshots.map((s) => ({
18
+ id: s.id,
19
+ slug: s.slug,
20
+ region: s.region,
21
+ allocatedSize: s.allocatedSize,
22
+ flattenedSize: s.flattenedSize,
23
+ isBootable: s.isBootable,
24
+ }));
25
+ console.log(JSON.stringify(data, null, 2));
26
+ return;
27
+ }
28
+ if (snapshots.length === 0) {
29
+ console.log("No snapshots found.");
30
+ return;
31
+ }
32
+ // Format as table
33
+ const headers = ["NAME", "REGION", "SIZE", "BOOTABLE"];
34
+ const rows = snapshots.map((s) => [
35
+ s.slug || s.id,
36
+ s.region,
37
+ formatBytes(s.allocatedSize || 0),
38
+ s.isBootable ? "yes" : "no",
39
+ ]);
40
+ console.log(table(headers, rows));
41
+ }
42
+ catch (err) {
43
+ console.error("Failed to list snapshots:", err);
44
+ process.exit(1);
45
+ }
46
+ }
47
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAOtD,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,OAAoB;IAC7C,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAE3B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QAC3C,IAAI,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC;QAE3B,gCAAgC;QAChC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;QACnE,CAAC;QAED,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,mEAAmE;YACnE,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACjC,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,aAAa,EAAE,CAAC,CAAC,aAAa;gBAC9B,aAAa,EAAE,CAAC,CAAC,aAAa;gBAC9B,UAAU,EAAE,CAAC,CAAC,UAAU;aACzB,CAAC,CAAC,CAAC;YACJ,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC3C,OAAO;QACT,CAAC;QAED,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;YACnC,OAAO;QACT,CAAC;QAED,kBAAkB;QAClB,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YAChC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE;YACd,CAAC,CAAC,MAAM;YACR,WAAW,CAAC,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC;YACjC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;SAC5B,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,GAAG,CAAC,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * sandboxer prune - Clean up orphaned volumes
3
+ *
4
+ * Orphaned volumes are temp volumes (tmp-*) that no longer have any
5
+ * snapshots depending on them.
6
+ */
7
+ interface PruneOptions {
8
+ force?: boolean;
9
+ dryRun?: boolean;
10
+ }
11
+ export declare function prune(options: PruneOptions): Promise<void>;
12
+ export {};
13
+ //# sourceMappingURL=prune.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prune.d.ts","sourceRoot":"","sources":["../../src/commands/prune.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,UAAU,YAAY;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA2EhE"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * sandboxer prune - Clean up orphaned volumes
3
+ *
4
+ * Orphaned volumes are temp volumes (tmp-*) that no longer have any
5
+ * snapshots depending on them.
6
+ */
7
+ import { getClient } from "../lib/client.js";
8
+ import { confirm } from "../lib/stdin.js";
9
+ import { success, error, info } from "../lib/output.js";
10
+ export async function prune(options) {
11
+ const client = getClient();
12
+ try {
13
+ // Get all volumes and snapshots
14
+ const [volumesPage, snapshotsPage] = await Promise.all([
15
+ client.volumes.list(),
16
+ client.snapshots.list(),
17
+ ]);
18
+ const volumes = volumesPage.items;
19
+ const snapshots = snapshotsPage.items;
20
+ // Build set of volume IDs that have snapshots depending on them
21
+ const volumesWithSnapshots = new Set();
22
+ for (const snap of snapshots) {
23
+ if (snap.volume?.id) {
24
+ volumesWithSnapshots.add(snap.volume.id);
25
+ }
26
+ }
27
+ // Find orphaned temp volumes (tmp-* with no snapshots)
28
+ const orphanedVolumes = volumes.filter((vol) => vol.slug.startsWith('tmp-') && !volumesWithSnapshots.has(vol.id));
29
+ if (orphanedVolumes.length === 0) {
30
+ success("No orphaned volumes to clean up.");
31
+ return;
32
+ }
33
+ console.log(`Found ${orphanedVolumes.length} orphaned volume(s):`);
34
+ for (const vol of orphanedVolumes) {
35
+ console.log(` - ${vol.slug}`);
36
+ }
37
+ if (options.dryRun) {
38
+ info("Dry run - no volumes deleted.");
39
+ return;
40
+ }
41
+ // Confirm unless --force
42
+ if (!options.force) {
43
+ const confirmed = await confirm(`Delete ${orphanedVolumes.length} orphaned volume(s)?`);
44
+ if (!confirmed) {
45
+ console.log("Aborted.");
46
+ return;
47
+ }
48
+ }
49
+ // Delete orphaned volumes
50
+ let deleted = 0;
51
+ let failed = 0;
52
+ for (const vol of orphanedVolumes) {
53
+ try {
54
+ await client.volumes.delete(vol.id);
55
+ deleted++;
56
+ info(`Deleted volume '${vol.slug}'`);
57
+ }
58
+ catch (err) {
59
+ failed++;
60
+ error(`Failed to delete '${vol.slug}': ${err}`);
61
+ }
62
+ }
63
+ if (deleted > 0) {
64
+ success(`Cleaned up ${deleted} orphaned volume(s).`);
65
+ }
66
+ if (failed > 0) {
67
+ error(`Failed to delete ${failed} volume(s).`);
68
+ }
69
+ }
70
+ catch (err) {
71
+ error(`Failed to prune: ${err}`);
72
+ process.exit(1);
73
+ }
74
+ }
75
+ //# sourceMappingURL=prune.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prune.js","sourceRoot":"","sources":["../../src/commands/prune.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * sandboxer run - Run commands in an ephemeral sandbox
3
+ */
4
+ interface RunOptions {
5
+ timeout: string;
6
+ memory: string;
7
+ region: string;
8
+ env: string[];
9
+ copy: string[];
10
+ copyOut: string[];
11
+ script?: string;
12
+ }
13
+ export declare function run(snapshot: string, options: RunOptions): Promise<void>;
14
+ export {};
15
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH,UAAU,UAAU;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAqG9E"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * sandboxer run - Run commands in an ephemeral sandbox
3
+ */
4
+ import { spawn } from "node:child_process";
5
+ import { Sandbox } from "@deno/sandbox";
6
+ import { snapshotExists } from "../lib/client.js";
7
+ import { isInteractive, readStdin, readScriptFile } from "../lib/stdin.js";
8
+ import { info, success, error, step } from "../lib/output.js";
9
+ import { copyToSandbox, copyFromSandbox } from "../lib/copy.js";
10
+ import { parseMemory, parseTimeout, parseRegion, parseEnvVars } from "../lib/parse.js";
11
+ export async function run(snapshot, options) {
12
+ // Parse and validate options
13
+ const timeout = parseTimeout(options.timeout);
14
+ const region = parseRegion(options.region);
15
+ const memory = parseMemory(options.memory);
16
+ const env = parseEnvVars(options.env);
17
+ try {
18
+ // Check if snapshot exists
19
+ const exists = await snapshotExists(snapshot);
20
+ if (!exists) {
21
+ error(`Snapshot '${snapshot}' not found. Run 'sandboxer list' to see available snapshots.`);
22
+ process.exit(1);
23
+ }
24
+ // Determine script source
25
+ let script = null;
26
+ const interactive = isInteractive();
27
+ if (options.script) {
28
+ script = await readScriptFile(options.script);
29
+ }
30
+ else if (!interactive) {
31
+ // Read from stdin (heredoc or pipe)
32
+ script = await readStdin();
33
+ }
34
+ // Boot ephemeral sandbox from snapshot
35
+ step(1, 2, `Booting sandbox from snapshot '${snapshot}'...`);
36
+ const sandbox = await Sandbox.create({
37
+ region: region,
38
+ root: snapshot,
39
+ timeout: timeout,
40
+ memory: memory,
41
+ env: Object.keys(env).length > 0 ? env : undefined,
42
+ });
43
+ info(`Sandbox ready: ${sandbox.id}`);
44
+ // Copy files into sandbox
45
+ if (options.copy.length > 0) {
46
+ await copyToSandbox(sandbox, options.copy);
47
+ }
48
+ // Setup cleanup on Ctrl+C
49
+ const cleanup = async () => {
50
+ info("\nCleaning up sandbox...");
51
+ try {
52
+ await sandbox.kill();
53
+ }
54
+ catch {
55
+ // Ignore errors during cleanup
56
+ }
57
+ };
58
+ process.on("SIGINT", async () => {
59
+ await cleanup();
60
+ process.exit(130);
61
+ });
62
+ process.on("SIGTERM", async () => {
63
+ await cleanup();
64
+ process.exit(143);
65
+ });
66
+ try {
67
+ // Execute commands
68
+ step(2, 2, script ? "Executing script..." : "Opening interactive shell...");
69
+ if (script) {
70
+ // Write script to temp file and execute
71
+ await sandbox.fs.writeTextFile("/tmp/sandsnap-script.sh", script);
72
+ try {
73
+ await sandbox.sh `bash /tmp/sandsnap-script.sh`;
74
+ }
75
+ catch (err) {
76
+ if (err && typeof err === "object" && "code" in err) {
77
+ error(`Script failed with exit code ${err.code}`);
78
+ // Still try to copy out files before exiting
79
+ if (options.copyOut.length > 0) {
80
+ await copyFromSandbox(sandbox, options.copyOut);
81
+ }
82
+ await cleanup();
83
+ process.exit(typeof err.code === "number" ? err.code : 1);
84
+ }
85
+ throw err;
86
+ }
87
+ }
88
+ else {
89
+ // Interactive mode
90
+ await openInteractiveShell(sandbox);
91
+ }
92
+ // Copy files out from sandbox
93
+ if (options.copyOut.length > 0) {
94
+ await copyFromSandbox(sandbox, options.copyOut);
95
+ }
96
+ success(script ? "Script completed successfully." : "Session ended.");
97
+ }
98
+ finally {
99
+ // Always cleanup
100
+ await cleanup();
101
+ }
102
+ }
103
+ catch (err) {
104
+ error(`Failed: ${err}`);
105
+ process.exit(1);
106
+ }
107
+ }
108
+ /**
109
+ * Open an interactive SSH shell to the sandbox
110
+ */
111
+ async function openInteractiveShell(sandbox) {
112
+ const ssh = await sandbox.exposeSsh();
113
+ info(`Connecting via SSH to ${ssh.username}@${ssh.hostname}...`);
114
+ console.log("(Type 'exit' when done)\n");
115
+ return new Promise((resolve, reject) => {
116
+ const sshProcess = spawn("ssh", [
117
+ "-o", "StrictHostKeyChecking=no",
118
+ "-o", "UserKnownHostsFile=/dev/null",
119
+ "-o", "LogLevel=ERROR",
120
+ "-t",
121
+ `${ssh.username}@${ssh.hostname}`,
122
+ ], {
123
+ stdio: "inherit",
124
+ });
125
+ sshProcess.on("close", () => {
126
+ console.log("");
127
+ resolve();
128
+ });
129
+ sshProcess.on("error", reject);
130
+ });
131
+ }
132
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * sandboxer sandboxes - List and manage running sandboxes
3
+ */
4
+ interface SandboxesOptions {
5
+ json?: boolean;
6
+ }
7
+ export declare function listSandboxes(options: SandboxesOptions): Promise<void>;
8
+ export declare function killSandbox(id: string): Promise<void>;
9
+ export declare function killAllSandboxes(): Promise<void>;
10
+ export {};
11
+ //# sourceMappingURL=sandboxes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandboxes.d.ts","sourceRoot":"","sources":["../../src/commands/sandboxes.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,UAAU,gBAAgB;IACxB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoC5E;AAED,wBAAsB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAU3D;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CA4BtD"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * sandboxer sandboxes - List and manage running sandboxes
3
+ */
4
+ import { getClient } from "../lib/client.js";
5
+ import { table, formatDate } from "../lib/output.js";
6
+ import { success, error, info } from "../lib/output.js";
7
+ export async function listSandboxes(options) {
8
+ const client = getClient();
9
+ try {
10
+ const sandboxes = await client.sandboxes.list();
11
+ if (options.json) {
12
+ const data = sandboxes.map((s) => ({
13
+ id: s.id,
14
+ region: s.region,
15
+ status: s.status,
16
+ createdAt: s.createdAt.toISOString(),
17
+ labels: s.labels,
18
+ }));
19
+ console.log(JSON.stringify(data, null, 2));
20
+ return;
21
+ }
22
+ if (sandboxes.length === 0) {
23
+ console.log("No running sandboxes.");
24
+ return;
25
+ }
26
+ const headers = ["ID", "REGION", "STATUS", "CREATED"];
27
+ const rows = sandboxes.map((s) => [
28
+ s.id,
29
+ s.region,
30
+ s.status,
31
+ formatDate(s.createdAt),
32
+ ]);
33
+ console.log(table(headers, rows));
34
+ }
35
+ catch (err) {
36
+ error(`Failed to list sandboxes: ${err}`);
37
+ process.exit(1);
38
+ }
39
+ }
40
+ export async function killSandbox(id) {
41
+ try {
42
+ const { Sandbox } = await import("@deno/sandbox");
43
+ const sandbox = await Sandbox.connect(id);
44
+ await sandbox.kill();
45
+ success(`Killed sandbox ${id}`);
46
+ }
47
+ catch (err) {
48
+ error(`Failed to kill sandbox: ${err}`);
49
+ process.exit(1);
50
+ }
51
+ }
52
+ export async function killAllSandboxes() {
53
+ const client = getClient();
54
+ try {
55
+ const allSandboxes = await client.sandboxes.list();
56
+ const sandboxes = allSandboxes.filter((s) => s.status === "running");
57
+ if (sandboxes.length === 0) {
58
+ info("No running sandboxes to kill.");
59
+ return;
60
+ }
61
+ info(`Killing ${sandboxes.length} sandbox(es)...`);
62
+ const { Sandbox } = await import("@deno/sandbox");
63
+ for (const s of sandboxes) {
64
+ try {
65
+ const sandbox = await Sandbox.connect(s.id);
66
+ await sandbox.kill();
67
+ success(`Killed ${s.id}`);
68
+ }
69
+ catch (err) {
70
+ error(`Failed to kill ${s.id}: ${err}`);
71
+ }
72
+ }
73
+ }
74
+ catch (err) {
75
+ error(`Failed: ${err}`);
76
+ process.exit(1);
77
+ }
78
+ }
79
+ //# sourceMappingURL=sandboxes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandboxes.js","sourceRoot":"","sources":["../../src/commands/sandboxes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env node
2
+ import { program } from "commander";
3
+ import { evolve } from "./commands/evolve.js";
4
+ import { run } from "./commands/run.js";
5
+ import { list } from "./commands/list.js";
6
+ import { deleteSnapshot } from "./commands/delete.js";
7
+ import { prune } from "./commands/prune.js";
8
+ import { listSandboxes, killSandbox, killAllSandboxes } from "./commands/sandboxes.js";
9
+ import { setVerbose } from "./lib/output.js";
10
+ program
11
+ .name("sandsnap")
12
+ .description("CLI for managing Deno Sandbox environments with snapshot-based workflows")
13
+ .version("0.1.0")
14
+ .option("-v, --verbose", "Show detailed progress logs")
15
+ .hook("preAction", (thisCommand) => {
16
+ const opts = thisCommand.opts();
17
+ if (opts.verbose) {
18
+ setVerbose(true);
19
+ }
20
+ });
21
+ program
22
+ .command("evolve <name>")
23
+ .description("Create a new snapshot by running commands on a base state")
24
+ .option("--from <snapshot>", "Base snapshot to evolve from (default: debian-13 base image)")
25
+ .option("--timeout <duration>", "Sandbox timeout (e.g., 10m, 30m)", "10m")
26
+ .option("--capacity <size>", "Volume capacity (e.g., 2GiB, 10GiB)", "10GiB")
27
+ .option("--memory <size>", "Sandbox memory (e.g., 1GiB, 2GiB, 4GiB)", "1280MiB")
28
+ .option("--region <region>", "Region (ord or ams)", "ord")
29
+ .option("--env <KEY=VALUE>", "Set environment variable (repeatable)", collect, [])
30
+ .option("--copy <src:dst>", "Copy file/dir from host to sandbox (repeatable)", collect, [])
31
+ .option("--script <file>", "Read commands from script file")
32
+ .option("--overwrite", "Overwrite existing snapshot with same name")
33
+ .action(evolve);
34
+ function collect(value, previous) {
35
+ return previous.concat([value]);
36
+ }
37
+ program
38
+ .command("run <snapshot>")
39
+ .description("Run commands in an ephemeral sandbox (changes discarded)")
40
+ .option("--timeout <duration>", "Sandbox timeout (e.g., 5m, 10m, session)", "session")
41
+ .option("--memory <size>", "Sandbox memory (e.g., 1GiB, 2GiB, 4GiB)", "1280MiB")
42
+ .option("--region <region>", "Region (ord or ams)", "ord")
43
+ .option("--env <KEY=VALUE>", "Set environment variable (repeatable)", collect, [])
44
+ .option("--copy <src:dst>", "Copy file/dir from host to sandbox (repeatable)", collect, [])
45
+ .option("--copy-out <src:dst>", "Copy file/dir from sandbox to host after execution (repeatable)", collect, [])
46
+ .option("--script <file>", "Read commands from script file")
47
+ .action(run);
48
+ program
49
+ .command("list")
50
+ .description("List all snapshots")
51
+ .option("--region <region>", "Filter by region")
52
+ .option("--json", "Output as JSON")
53
+ .action(list);
54
+ program
55
+ .command("delete <name>")
56
+ .description("Delete a snapshot")
57
+ .option("--force", "Skip confirmation prompt")
58
+ .action(deleteSnapshot);
59
+ program
60
+ .command("prune")
61
+ .description("Clean up orphaned temporary volumes")
62
+ .option("--force", "Skip confirmation prompt")
63
+ .option("--dry-run", "Show what would be deleted without deleting")
64
+ .action(prune);
65
+ // Sandbox management (for debugging/cleanup)
66
+ const sandboxesCmd = program
67
+ .command("sandboxes")
68
+ .description("Manage running sandboxes");
69
+ sandboxesCmd
70
+ .command("list")
71
+ .description("List running sandboxes")
72
+ .option("--json", "Output as JSON")
73
+ .action(listSandboxes);
74
+ sandboxesCmd
75
+ .command("kill <id>")
76
+ .description("Kill a running sandbox")
77
+ .action(killSandbox);
78
+ sandboxesCmd
79
+ .command("kill-all")
80
+ .description("Kill all running sandboxes")
81
+ .action(killAllSandboxes);
82
+ program.parse();
83
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Shared client instance and utilities
3
+ */
4
+ import { Client } from "@deno/sandbox";
5
+ export declare function getClient(): Client;
6
+ /**
7
+ * Check if a snapshot exists
8
+ */
9
+ export declare function snapshotExists(slug: string): Promise<boolean>;
10
+ /**
11
+ * Generate a unique temporary volume slug (max 32 chars)
12
+ */
13
+ export declare function tempVolumeSlug(): string;
14
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/lib/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAIvC,wBAAgB,SAAS,IAAI,MAAM,CAKlC;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAInE;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAMvC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Shared client instance and utilities
3
+ */
4
+ import { Client } from "@deno/sandbox";
5
+ let _client = null;
6
+ export function getClient() {
7
+ if (!_client) {
8
+ _client = new Client();
9
+ }
10
+ return _client;
11
+ }
12
+ /**
13
+ * Check if a snapshot exists
14
+ */
15
+ export async function snapshotExists(slug) {
16
+ const client = getClient();
17
+ const snapshot = await client.snapshots.get(slug);
18
+ return snapshot !== null;
19
+ }
20
+ /**
21
+ * Generate a unique temporary volume slug (max 32 chars)
22
+ */
23
+ export function tempVolumeSlug() {
24
+ // Format: tmp-{timestamp-base36}-{random}
25
+ // Keep under 32 chars
26
+ const ts = Date.now().toString(36); // ~8 chars
27
+ const rand = Math.random().toString(36).slice(2, 8); // 6 chars
28
+ return `tmp-${ts}-${rand}`; // ~18 chars
29
+ }
30
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/lib/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEvC,IAAI,OAAO,GAAkB,IAAI,CAAC;AAElC,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,GAAG,IAAI,MAAM,EAAE,CAAC;IACzB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAY;IAC/C,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClD,OAAO,QAAQ,KAAK,IAAI,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,0CAA0C;IAC1C,sBAAsB;IACtB,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW;IAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU;IAC/D,OAAO,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,YAAY;AAC1C,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * File copy utilities for sandbox operations
3
+ */
4
+ import type { Sandbox } from "@deno/sandbox";
5
+ export type { CopySpec } from "./parse.js";
6
+ /**
7
+ * Copy files from host to sandbox
8
+ */
9
+ export declare function copyToSandbox(sandbox: Sandbox, specs: string[]): Promise<void>;
10
+ /**
11
+ * Copy files from sandbox to host
12
+ */
13
+ export declare function copyFromSandbox(sandbox: Sandbox, specs: string[]): Promise<void>;
14
+ //# sourceMappingURL=copy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy.d.ts","sourceRoot":"","sources":["../../src/lib/copy.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAG7C,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C;;GAEG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,EAAE,GACd,OAAO,CAAC,IAAI,CAAC,CA0Bf;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,EAAE,GACd,OAAO,CAAC,IAAI,CAAC,CA2Df"}