@exedev/sdk 0.0.6 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Bold Software, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -2,8 +2,6 @@
2
2
 
3
3
  Official JavaScript/TypeScript SDK for the [exe.dev](https://exe.dev) HTTPS API.
4
4
 
5
- ## Install
6
-
7
5
  ```sh
8
6
  npm install @exedev/sdk
9
7
  ```
@@ -14,71 +12,155 @@ npm install @exedev/sdk
14
12
  import exedev from "@exedev/sdk";
15
13
 
16
14
  const exe = exedev({ token: process.env.EXE_TOKEN! });
15
+ const vm = await exe.new({ name: "my-vm", image: "ubuntu:24.04", tag: ["dev"] });
16
+ // new waits for SSH by default. No create-then-ssh retry loop is needed.
17
+ try {
18
+ console.log(vm.name, vm.httpsUrl);
19
+ const result = await vm.ssh("uname -a");
20
+ console.log(result.exitCode, result.stdout, result.stderr);
21
+ await vm.shareAdd("friend@example.com", { message: "have a look" });
22
+ } finally {
23
+ await vm.rm();
24
+ }
25
+ ```
26
+
27
+ ## Client and VM API
28
+
29
+ `exedev({ token, baseURL?, fetch? })` creates a client. `baseURL` defaults to
30
+ `https://exe.dev`; `fetch` defaults to the global implementation. Named imports
31
+ of `exedev`, `ExedevClient`, and `VM` are also available.
32
+
33
+ - `exe.new(options?)` creates a VM and returns a `VM` object.
34
+ - `exe.ls(nameOrPattern?, options?)` returns `VM[]`.
35
+ - `exe.vm(name)` references an existing VM without making a request.
36
+ - `vm.refresh(options?)` refreshes its metadata and returns the same object.
37
+ - `vm.ssh(command, options?)` runs a shell command on that VM.
38
+ - `vm.cp({ name?, ...options })` copies it and returns a new `VM` object.
39
+ - Lifecycle and VM-scoped commands are methods on the VM: `vm.rm()`,
40
+ `vm.pause()`, `vm.resume()`, `vm.restart()`, `vm.rename(newName)`,
41
+ `vm.resize(options)`, `vm.stat(options)`, `vm.tag(tags)`, `vm.comment(text)`,
42
+ `vm.shareShow()`, `vm.sharePort(port)`, and the other generated VM commands.
43
+ - Account commands remain on the client: `exe.whoami()`, `exe.sshKeyList()`,
44
+ `exe.integrationsList()`, `exe.billingPlan()`, etc.
45
+
46
+ There is no parallel raw-command API or client-level `ssh`, `cp`, or `rm`.
47
+ Options for generated commands retain CLI flag names (for example,
48
+ `{ "no-email": true }`); each method carries the server's help text.
49
+ Methods with known JSON responses reject malformed JSON; other account/VM
50
+ commands may return JSON or text and are typed as `unknown`.
51
+
52
+ `vm.name` is the current name. `vm.httpsUrl`, `vm.sshDest`, and `vm.tags` expose
53
+ common metadata. `vm.info` is a read-only snapshot with `status`, `region`,
54
+ `comment`, `createdAt`, and `setupError` when available. A reference from
55
+ `exe.vm(name)` initially knows only its name. Copies do not invent a web URL;
56
+ call `refresh()` to fetch it. A successful `rename()` updates the same object
57
+ and invalidates old destinations; other references do not automatically change.
58
+
59
+ ## Readiness and cancellation
60
+
61
+ `new`, `cp`, `restart`, and `resume` wait for SSH by default. Pass
62
+ `{ waitUntil: "created" }` to return without probing, including when the token
63
+ has no `ssh` permission. `vm.waitUntilReady({ timeoutMs?, signal? })` explicitly
64
+ waits later. The default readiness deadline is 60 seconds **after** creation or
65
+ the lifecycle operation returns, including probe requests and backoff.
66
+
67
+ Readiness runs only the harmless command `true`, retrying transient connection
68
+ failures. It does not wait for application servers or setup scripts, and it
69
+ never retries a user command or the creation request.
70
+
71
+ If waiting fails, `VMReadyError.vm` gives you the VM for inspection or cleanup;
72
+ it is not automatically deleted. All operations accept an `AbortSignal`.
73
+ Caller cancellation preserves `signal.reason`, including during streaming and
74
+ callbacks, rather than wrapping it in another error. An aborted creation may
75
+ still have created a VM; use an explicit name or `ls()` to recover it.
76
+
77
+ ## Running commands
78
+
79
+ `vm.ssh()` resolves to `{ exitCode, stdout, stderr, stdoutBytes, stderrBytes,
80
+ captured }`. A nonzero exit code is a result, not an exception. Byte arrays
81
+ preserve binary output; strings are decoded as UTF-8. The command is a shell
82
+ script: quote any untrusted values you interpolate into it.
17
83
 
18
- // List all VMs
19
- const vms = await exe.ls();
20
- console.log(vms);
84
+ ```ts
85
+ await vm.ssh("make", {
86
+ capture: false,
87
+ onStdout: (chunk) => { process.stdout.write(chunk); },
88
+ onStderr: (chunk) => { process.stderr.write(chunk); },
89
+ });
90
+ ```
21
91
 
22
- // Get your identity
23
- const me = await exe.whoami();
24
- console.log(me.email);
92
+ Callbacks are awaited serially, with incremental UTF-8 decoding per stream.
93
+ Their cross-stream order is approximate. Throwing from a callback cancels the
94
+ response and rejects with that error.
25
95
 
26
- // Create a VM
27
- await exe.new("my-vm", { region: "lon" });
96
+ Output is captured by default, with an **8 MiB combined limit** on stdout and
97
+ stderr. Change it with `maxOutputBytes`; exceeding it cancels the response and
98
+ throws `SSHStreamError` with code `output_limit`. Set `capture: false` for
99
+ bounded-memory streaming of arbitrarily long output: callbacks still receive
100
+ it, but result/error output is empty and `captured` is false. The capture limit
101
+ is ignored in this mode. Invalid or oversized NDJSON frames are always rejected.
28
102
 
29
- // Get VM details
30
- const info = await exe.stat("my-vm");
31
- console.log(info);
103
+ ## Errors
32
104
 
33
- // Run any command
34
- const result = await exe.exec("help");
35
- console.log(result.body);
105
+ - `ExeAPIError`: `operation` and HTTP `status`. The message, stack, and ordinary
106
+ serialization omit request arguments and server response bodies. Explicitly
107
+ call `error.details().body` for diagnostics; this may contain secrets.
108
+ - `ExeProtocolError`: an incompatible response, including malformed JSON or a
109
+ server that does not support NDJSON SSH output.
110
+ - `SSHStreamError`: interrupted/invalid output or a capture limit. `code` is
111
+ `interrupted`, `protocol`, or `output_limit`; getters provide captured partial
112
+ output. The exit status is unknown. `details()` exposes opt-in server diagnostics.
113
+ - `VMReadyError`: readiness failed; `vm` and `cause` are available.
36
114
 
37
- // Delete a VM
38
- await exe.rm("my-vm");
39
- ```
115
+ Errors do not establish that an operation never ran. Do not blindly retry a
116
+ mutation or remote command after a transport failure.
40
117
 
41
118
  ## Authentication
42
119
 
43
- Generate an API token via SSH:
120
+ Generate a token via SSH:
44
121
 
45
122
  ```sh
46
- ssh exe.dev token
123
+ ssh exe.dev ssh-key generate-api-key --label=my-app --exp=30d --cmds="new,ls,ssh,rm"
47
124
  ```
48
125
 
49
- See the [HTTPS API docs](https://exe.dev/docs/https-api) for full details on
50
- authentication, token permissions, and scoping.
126
+ See the [HTTPS API docs](https://exe.dev/docs/https-api) for permissions and scoping.
51
127
 
52
- ## API
128
+ ## Development
53
129
 
54
- ### `exedev(options)`
130
+ **All of `src/` is generated.** Edit `cmd/gensdkjs` and its TypeScript templates
131
+ in the exe.dev repository, then run `go run ./cmd/gensdkjs` there. Copy the
132
+ outputs into this checkout and test:
55
133
 
56
- | Option | Type | Required | Default |
57
- | --------- | ------ | -------- | ------------------- |
58
- | `token` | string | Yes | |
59
- | `baseURL` | string | No | `https://exe.dev` |
134
+ ```sh
135
+ npm install
136
+ npm run sync-commands -- ../exe
137
+ npm test
138
+ ```
60
139
 
61
- ### Methods
140
+ `npm test` builds the package, checks the public TypeScript API, and runs unit
141
+ and live integration tests. Live tests require a tag-scoped token and create,
142
+ copy, execute commands on, restart, rename, and delete their own test VMs.
143
+ They read `$EXE_TOKEN`, or `$EXE_TOKEN_FILE` (a bare token or JSON containing
144
+ `token`), or `~/.config/exedev/sdk-test-token`. The expected tag is `sdk-test`
145
+ (override with `$EXE_TEST_TAG`). To create a test token:
62
146
 
63
- | Method | Description |
64
- | --- | --- |
65
- | `exec(command)` | Run any command (raw) |
66
- | `ls()` | List VMs |
67
- | `whoami()` | Get authenticated user |
68
- | `stat(vmName)` | Get VM details |
69
- | `new(name, options?)` | Create a VM |
70
- | `rm(vmName)` | Delete a VM |
71
- | `restart(vmName)` | Restart a VM |
72
- | `rename(oldName, newName)` | Rename a VM |
73
- | `sshKeyList()` | List SSH keys |
74
- | `shareShow(vmName)` | Show sharing settings |
147
+ ```sh
148
+ ssh exe.dev 'ssh-key generate-api-key --label=sdk-test --tag=sdk-test --exp=30d --cmds="ls,new,whoami,stat,rm,restart,rename,cp,ssh,ssh-key list,share show" --json'
149
+ ```
75
150
 
76
- All methods accept an optional `{ signal: AbortSignal }` as the last argument for cancellation.
151
+ Set `EXE_SKIP_INTEGRATION=1` to run without live access. Set
152
+ `EXE_SKIP_SSH_INTEGRATION=1` to exercise only the live control plane when the
153
+ server has not yet deployed NDJSON SSH support; this explicitly skips live SSH
154
+ and readiness assertions, not the corresponding unit tests. The full live
155
+ suite requires that protocol and does not silently fall back to raw SSH output.
77
156
 
78
- ### Named import
157
+ The generator's Go tests check regeneration and command grammar assumptions.
158
+ Server-side wire-contract tests exercise creation, listing, copying, and SSH.
159
+ To run the generated SDK end-to-end against the local Go HTTP/SSH fixture:
79
160
 
80
- ```ts
81
- import { exedev } from "@exedev/sdk";
161
+ ```sh
162
+ # In the exe.dev checkout, with this SDK's npm dependencies installed:
163
+ EXE_SDK_JS_DIR=/absolute/path/to/exe-sdk-js go test ./execore -run TestSDKJSHTTP
82
164
  ```
83
165
 
84
166
  ## License
package/dist/client.d.ts CHANGED
@@ -1,64 +1,69 @@
1
- import type { VM, WhoamiResponse, StatResponse } from "./types.js";
1
+ import type { Arg, CallOptions, FlagKind } from "./commands.gen.js";
2
2
  export interface ExedevOptions {
3
- /** Bearer token (exe0.* or exe1.*). */
3
+ /** API bearer token. */
4
4
  token: string;
5
- /** Base URL for the API. Defaults to "https://exe.dev". */
5
+ /** Defaults to https://exe.dev. */
6
6
  baseURL?: string;
7
+ /** Defaults to global fetch. */
8
+ fetch?: typeof fetch;
7
9
  }
8
- export interface ExecOptions {
9
- /** AbortSignal for cancellation. */
10
- signal?: AbortSignal;
10
+ export interface SSHOptions extends CallOptions {
11
+ /** Awaited serially as UTF-8 output arrives. Throwing cancels the response. */
12
+ onStdout?: (data: string) => void | Promise<void>;
13
+ onStderr?: (data: string) => void | Promise<void>;
14
+ /** Retain output in the result/error. Set false for bounded-memory streaming. Default true. */
15
+ capture?: boolean;
16
+ /** Maximum combined captured bytes. Default 8 MiB. Ignored with capture: false. */
17
+ maxOutputBytes?: number;
11
18
  }
12
- export interface ExecResult {
13
- /** HTTP status code. */
14
- status: number;
15
- /** Raw response body. */
16
- body: string;
17
- /** Whether the request succeeded (2xx). */
18
- ok: boolean;
19
+ export interface SSHResult {
20
+ readonly exitCode: number;
21
+ readonly captured: boolean;
22
+ readonly stdout: string;
23
+ readonly stderr: string;
24
+ readonly stdoutBytes: Uint8Array;
25
+ readonly stderrBytes: Uint8Array;
19
26
  }
20
- export interface ExedevClient {
21
- /** Execute a raw command against the exe.dev API. */
22
- exec(command: string, opts?: ExecOptions): Promise<ExecResult>;
23
- /** List all VMs. */
24
- ls(opts?: ExecOptions): Promise<VM[]>;
25
- /** Get the authenticated user's identity. */
26
- whoami(opts?: ExecOptions): Promise<WhoamiResponse>;
27
- /** Get detailed status of a VM. */
28
- stat(vmName: string, opts?: ExecOptions): Promise<StatResponse>;
29
- /** Create a new VM. Returns the VM name. */
30
- "new"(name: string, options?: {
31
- region?: string;
32
- }, opts?: ExecOptions): Promise<string>;
33
- /** Delete a VM. */
34
- rm(vmName: string, opts?: ExecOptions): Promise<void>;
35
- /** Restart a VM. */
36
- restart(vmName: string, opts?: ExecOptions): Promise<void>;
37
- /** Rename a VM. */
38
- rename(oldName: string, newName: string, opts?: ExecOptions): Promise<void>;
39
- /** List SSH keys. */
40
- sshKeyList(opts?: ExecOptions): Promise<string>;
41
- /** Show sharing settings for a VM. */
42
- shareShow(vmName: string, opts?: ExecOptions): Promise<string>;
43
- }
44
- /**
45
- * Create an exe.dev API client.
46
- *
47
- * @example
48
- * ```ts
49
- * import exedev from "@exedev/sdk";
50
- *
51
- * const exe = exedev({ token: process.env.EXE_TOKEN! });
52
- * const vms = await exe.ls();
53
- * console.log(vms);
54
- * ```
55
- */
56
- export default function exedev(opts: ExedevOptions): ExedevClient;
57
- /** Error thrown when the exe.dev API returns a non-2xx status. */
27
+ /** API rejection. Neither requests nor response bodies appear in default logging. */
58
28
  export declare class ExeAPIError extends Error {
59
- readonly command: string;
29
+ #private;
30
+ readonly operation: string;
60
31
  readonly status: number;
61
- readonly body: string;
62
- constructor(command: string, status: number, body: string);
32
+ constructor(operation: string, status: number, body: string);
33
+ /** Opt-in server diagnostics; may contain secrets. Does not establish whether an operation ran. */
34
+ details(): {
35
+ body: string;
36
+ };
37
+ }
38
+ export declare class ExeProtocolError extends Error {
39
+ readonly operation: string;
40
+ constructor(operation: string);
41
+ }
42
+ /** The command's exit status is unknown; captured output is only a prefix. Do not blindly retry. */
43
+ export declare class SSHStreamError extends Error {
44
+ #private;
45
+ readonly code: "interrupted" | "protocol" | "output_limit";
46
+ readonly captured: boolean;
47
+ constructor(code: "interrupted" | "protocol" | "output_limit", captured: boolean, stdout: Uint8Array, stderr: Uint8Array, detail?: string);
48
+ get stdoutBytes(): Uint8Array;
49
+ get stderrBytes(): Uint8Array;
50
+ get stdout(): string;
51
+ get stderr(): string;
52
+ /** Opt-in server diagnostics; may contain secrets. */
53
+ details(): {
54
+ message?: string;
55
+ };
56
+ }
57
+ /** Internal transport, deliberately not exported from the package entry point. */
58
+ export declare class Transport {
59
+ #private;
60
+ constructor(opts: ExedevOptions);
61
+ call(path: string, args: readonly Arg[], options: CallOptions | undefined, flags: Readonly<Record<string, FlagKind>>, json?: boolean): Promise<any>;
62
+ ssh(vm: string, command: string, options?: SSHOptions): Promise<SSHResult>;
63
63
  }
64
+ export declare function commandLine(path: string, args: readonly Arg[], options: CallOptions | undefined, flags: Readonly<Record<string, FlagKind>>): string;
65
+ export declare function quote(s: string): string;
66
+ /** Stop waiting for an uncooperative fetch/body/callback when the caller cancels. */
67
+ export declare function abortable<T>(promise: Promise<T>, signal?: AbortSignal): Promise<T>;
68
+ export declare function delay(ms: number, signal: AbortSignal): Promise<void>;
64
69
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAkB,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEnF,MAAM,WAAW,aAAa;IAC5B,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,oCAAoC;IACpC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,wBAAwB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,EAAE,EAAE,OAAO,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/D,oBAAoB;IACpB,EAAE,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IACtC,6CAA6C;IAC7C,MAAM,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACpD,mCAAmC;IACnC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAChE,4CAA4C;IAC5C,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACxF,mBAAmB;IACnB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,oBAAoB;IACpB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,mBAAmB;IACnB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,qBAAqB;IACrB,UAAU,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD,sCAAsC;IACtC,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAChE;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,YAAY,CA8GhE;AAED,kEAAkE;AAClE,qBAAa,WAAY,SAAQ,KAAK;IACpC,SAAgB,OAAO,EAAE,MAAM,CAAC;IAChC,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,IAAI,EAAE,MAAM,CAAC;gBAEjB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;CAO1D"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}