@exedev/sdk 0.1.0 → 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/README.md +124 -61
- package/dist/client.d.ts +56 -46
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +288 -103
- package/dist/client.js.map +1 -1
- package/dist/commands.gen.d.ts +328 -292
- package/dist/commands.gen.d.ts.map +1 -1
- package/dist/commands.gen.js +778 -511
- package/dist/commands.gen.js.map +1 -1
- package/dist/index.d.ts +8 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +28 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
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,91 +12,156 @@ npm install @exedev/sdk
|
|
|
14
12
|
import exedev from "@exedev/sdk";
|
|
15
13
|
|
|
16
14
|
const exe = exedev({ token: process.env.EXE_TOKEN! });
|
|
17
|
-
|
|
18
|
-
// Every exe.dev command is a method. Positional arguments are parameters;
|
|
19
|
-
// flags go in an options object, spelled as on the command line.
|
|
20
15
|
const vm = await exe.new({ name: "my-vm", image: "ubuntu:24.04", tag: ["dev"] });
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
await
|
|
25
|
-
|
|
26
|
-
await
|
|
27
|
-
|
|
28
|
-
await
|
|
29
|
-
|
|
30
|
-
// Run a raw command line.
|
|
31
|
-
const result = await exe.exec("help");
|
|
32
|
-
console.log(result.body);
|
|
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
|
+
}
|
|
33
25
|
```
|
|
34
26
|
|
|
35
|
-
##
|
|
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.
|
|
36
83
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
+
});
|
|
41
90
|
```
|
|
42
91
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
## API
|
|
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.
|
|
47
95
|
|
|
48
|
-
|
|
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.
|
|
49
102
|
|
|
50
|
-
|
|
51
|
-
| --------- | ------ | -------- | ------------------- |
|
|
52
|
-
| `token` | string | Yes | |
|
|
53
|
-
| `baseURL` | string | No | `https://exe.dev` |
|
|
54
|
-
| `fetch` | function | No | global `fetch` |
|
|
103
|
+
## Errors
|
|
55
104
|
|
|
56
|
-
|
|
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.
|
|
57
114
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
`team settings auto-join` is `teamSettingsAutoJoin`. Each method's doc comment
|
|
61
|
-
is the command's own help text, so `help <command>` and your editor agree.
|
|
115
|
+
Errors do not establish that an operation never ran. Do not blindly retry a
|
|
116
|
+
mutation or remote command after a transport failure.
|
|
62
117
|
|
|
63
|
-
|
|
64
|
-
`CommandResults` (`src/types.ts`) and `unknown` otherwise. They reject with
|
|
65
|
-
`ExeAPIError` (`status`, `command`, `body`) when a command fails. Every
|
|
66
|
-
options object accepts `signal` (an `AbortSignal`) for cancellation.
|
|
67
|
-
|
|
68
|
-
The command methods live in `src/commands.gen.ts`, which is generated from the
|
|
69
|
-
exe.dev command tree; don't edit it by hand. To pick up new commands, run
|
|
70
|
-
`npm run sync-commands -- path/to/exe` (default `../exe`) with an up-to-date
|
|
71
|
-
checkout of the exe.dev repository, then `npm test`.
|
|
118
|
+
## Authentication
|
|
72
119
|
|
|
73
|
-
|
|
120
|
+
Generate a token via SSH:
|
|
74
121
|
|
|
75
|
-
```
|
|
76
|
-
|
|
122
|
+
```sh
|
|
123
|
+
ssh exe.dev ssh-key generate-api-key --label=my-app --exp=30d --cmds="new,ls,ssh,rm"
|
|
77
124
|
```
|
|
78
125
|
|
|
126
|
+
See the [HTTPS API docs](https://exe.dev/docs/https-api) for permissions and scoping.
|
|
127
|
+
|
|
79
128
|
## Development
|
|
80
129
|
|
|
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:
|
|
133
|
+
|
|
81
134
|
```sh
|
|
82
135
|
npm install
|
|
136
|
+
npm run sync-commands -- ../exe
|
|
83
137
|
npm test
|
|
84
138
|
```
|
|
85
139
|
|
|
86
|
-
`npm test` builds the package,
|
|
87
|
-
|
|
88
|
-
restart, rename and delete
|
|
89
|
-
|
|
90
|
-
`
|
|
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:
|
|
91
146
|
|
|
92
147
|
```sh
|
|
93
|
-
|
|
94
|
-
ssh exe.dev 'ssh-key generate-api-key --label=sdk-test --tag=sdk-test --exp=30d --cmds="help,ls,new,whoami,stat,rm,restart,rename,ssh-key list,share show" --json' \
|
|
95
|
-
| jq -r .token > ~/.config/exedev/sdk-test-token
|
|
96
|
-
chmod 600 ~/.config/exedev/sdk-test-token
|
|
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'
|
|
97
149
|
```
|
|
98
150
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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.
|
|
156
|
+
|
|
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:
|
|
160
|
+
|
|
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
|
|
164
|
+
```
|
|
102
165
|
|
|
103
166
|
## License
|
|
104
167
|
|
package/dist/client.d.ts
CHANGED
|
@@ -1,59 +1,69 @@
|
|
|
1
|
-
import { Commands } from "./commands.gen.js";
|
|
2
1
|
import type { Arg, CallOptions, FlagKind } from "./commands.gen.js";
|
|
3
2
|
export interface ExedevOptions {
|
|
4
|
-
/**
|
|
3
|
+
/** API bearer token. */
|
|
5
4
|
token: string;
|
|
6
|
-
/**
|
|
5
|
+
/** Defaults to https://exe.dev. */
|
|
7
6
|
baseURL?: string;
|
|
8
|
-
/**
|
|
7
|
+
/** Defaults to global fetch. */
|
|
9
8
|
fetch?: typeof fetch;
|
|
10
9
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
ok: boolean;
|
|
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;
|
|
20
18
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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;
|
|
26
|
+
}
|
|
27
|
+
/** API rejection. Neither requests nor response bodies appear in default logging. */
|
|
28
|
+
export declare class ExeAPIError extends Error {
|
|
29
|
+
#private;
|
|
30
|
+
readonly operation: string;
|
|
31
|
+
readonly status: number;
|
|
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 {
|
|
29
59
|
#private;
|
|
30
60
|
constructor(opts: ExedevOptions);
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
protected run(path: string, args: readonly Arg[], options: CallOptions | undefined, flags: Readonly<Record<string, FlagKind>>): Promise<any>;
|
|
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>;
|
|
34
63
|
}
|
|
35
|
-
/**
|
|
36
|
-
* Create an exe.dev API client.
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* ```ts
|
|
40
|
-
* import exedev from "@exedev/sdk";
|
|
41
|
-
*
|
|
42
|
-
* const exe = exedev({ token: process.env.EXE_TOKEN! });
|
|
43
|
-
* const { vms } = await exe.ls();
|
|
44
|
-
* console.log(vms);
|
|
45
|
-
* ```
|
|
46
|
-
*/
|
|
47
|
-
export default function exedev(opts: ExedevOptions): ExedevClient;
|
|
48
|
-
/** Builds the command line for a generated command method. */
|
|
49
64
|
export declare function commandLine(path: string, args: readonly Arg[], options: CallOptions | undefined, flags: Readonly<Record<string, FlagKind>>): string;
|
|
50
|
-
/** Quotes s for the exe.dev command-line parser (POSIX shell rules). */
|
|
51
65
|
export declare function quote(s: string): string;
|
|
52
|
-
/**
|
|
53
|
-
export declare
|
|
54
|
-
|
|
55
|
-
readonly status: number;
|
|
56
|
-
readonly body: string;
|
|
57
|
-
constructor(command: string, status: number, body: string);
|
|
58
|
-
}
|
|
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>;
|
|
59
69
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|