@folsom/fuse 0.0.1 → 0.4.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/dist/index.d.ts CHANGED
@@ -51,8 +51,22 @@ interface Spec {
51
51
  cpus?: number;
52
52
  ram_mb?: number;
53
53
  storage_gb?: number;
54
+ gpus?: number;
55
+ gpu_kind?: string;
54
56
  region?: string;
55
57
  max_runtime_seconds?: number;
58
+ image?: string;
59
+ }
60
+ /** ExposeSpec requests that a guest port be published at boot. */
61
+ interface ExposeSpec {
62
+ port: number;
63
+ as?: string;
64
+ }
65
+ /** Endpoint is a published port with its externally reachable URL. */
66
+ interface Endpoint {
67
+ as?: string;
68
+ url: string;
69
+ port: number;
56
70
  }
57
71
  /** CreateRequest is the body for environments.create. */
58
72
  interface CreateRequest {
@@ -63,6 +77,7 @@ interface CreateRequest {
63
77
  startup_script?: string;
64
78
  gateway_url?: string;
65
79
  gateway_token?: string;
80
+ expose?: ExposeSpec[];
66
81
  }
67
82
  /** EnvironmentInfo is the server's view of a single microVM. */
68
83
  interface EnvironmentInfo {
@@ -75,6 +90,42 @@ interface EnvironmentInfo {
75
90
  created_at: string;
76
91
  updated_at: string;
77
92
  error?: string;
93
+ endpoints?: Endpoint[];
94
+ }
95
+ /** ForkOptions is the optional body for environments.fork. */
96
+ interface ForkOptions {
97
+ reuse_snapshot_id?: string;
98
+ comment?: string;
99
+ }
100
+ /** ExecRequest is the body for environments.exec. Exactly one of cmd or shell must be set. */
101
+ interface ExecRequest {
102
+ /**
103
+ * The argv to run in the guest, e.g. ["ls", "-l"]. Argv needs no quoting
104
+ * rules and cannot be turned into an injection by interpolating a value, so
105
+ * prefer it.
106
+ */
107
+ cmd?: string[];
108
+ /**
109
+ * Runs the string under `sh -lc`. Use it only for what argv cannot express:
110
+ * pipelines, redirects, and globs.
111
+ */
112
+ shell?: string;
113
+ /**
114
+ * Bounds the command inside the guest. Zero or unset takes the server
115
+ * default; the server clamps anything above its ceiling.
116
+ */
117
+ timeout_ms?: number;
118
+ }
119
+ /**
120
+ * ExecResult is the outcome of a guest command.
121
+ *
122
+ * A non-zero exit_code is a successful call: the command ran and failed. Only a
123
+ * thrown error means the command could not be run at all.
124
+ */
125
+ interface ExecResult {
126
+ exit_code: number;
127
+ stdout: string;
128
+ stderr: string;
78
129
  }
79
130
  /**
80
131
  * Event is one item from environments.events. It matches the server's SSE
@@ -132,6 +183,8 @@ interface HostCapacity {
132
183
  ram_mb: number;
133
184
  storage_gb: number;
134
185
  vm_count: number;
186
+ gpus?: number;
187
+ gpu_kind?: string;
135
188
  }
136
189
  /** RegisterHostRequest is the body for hosts.register. */
137
190
  interface RegisterHostRequest {
@@ -139,6 +192,7 @@ interface RegisterHostRequest {
139
192
  url: string;
140
193
  token?: string;
141
194
  region?: string;
195
+ backend?: string;
142
196
  capacity?: HostCapacity;
143
197
  }
144
198
  /** Host is the server's view of a registered host. */
@@ -147,11 +201,15 @@ interface Host {
147
201
  url: string;
148
202
  region?: string;
149
203
  state: string;
204
+ backend?: string;
150
205
  capacity: HostCapacity;
151
206
  allocated: HostCapacity;
152
207
  last_seen: string;
153
208
  created_at: string;
154
209
  updated_at: string;
210
+ /** Non-fatal registration notices (e.g. declared capacity exceeding the
211
+ * probed value). Only ever populated on the response to hosts.register. */
212
+ warnings?: string[];
155
213
  }
156
214
  /**
157
215
  * APIKey is a key's metadata. The raw secret appears only in
@@ -200,6 +258,22 @@ declare class EnvironmentsService {
200
258
  get(vmId: string, opts?: CallOptions): Promise<EnvironmentInfo>;
201
259
  /** Provision a new environment. Blocks until running or creation fails. */
202
260
  create(body: CreateRequest, opts?: CallOptions): Promise<EnvironmentInfo>;
261
+ /** Fork an environment into a new one; returns the new environment. */
262
+ fork(vmId: string, body?: ForkOptions, opts?: CallOptions): Promise<EnvironmentInfo>;
263
+ /**
264
+ * Run a command inside a running environment's guest and return its exit code
265
+ * with stdout and stderr kept separate.
266
+ *
267
+ * A non-zero exit_code is resolved, not thrown: the command ran and failed.
268
+ * A thrown error means the command could not be run at all.
269
+ *
270
+ * Exec requires the master token.
271
+ *
272
+ * @example
273
+ * const out = await client.environments.exec(id, { cmd: ["ls", "-l"] });
274
+ * if (out.exit_code !== 0) console.error(out.stderr);
275
+ */
276
+ exec(vmId: string, body: ExecRequest, opts?: CallOptions): Promise<ExecResult>;
203
277
  /** Gracefully drain an environment; returns the updated environment. */
204
278
  drain(vmId: string, opts?: CallOptions): Promise<EnvironmentInfo>;
205
279
  /** Rotate the per-VM credentials and push them to the guest. */
@@ -314,7 +388,7 @@ declare class FuseClient {
314
388
  constructor(options: FuseClientOptions);
315
389
  }
316
390
 
317
- declare const VERSION = "0.0.1";
391
+ declare const VERSION = "0.4.0";
318
392
 
319
393
  /** Stable, machine-readable error codes returned by the server. */
320
394
  declare const ErrorCode: {
@@ -363,4 +437,4 @@ declare function isInvalidArgument(err: unknown): boolean;
363
437
  /** isUnavailable reports whether err is an unavailable api error. */
364
438
  declare function isUnavailable(err: unknown): boolean;
365
439
 
366
- export { type APIKey, ApiKeysService, type CallOptions, type CreateRequest, type CreatedAPIKey, type EnvironmentInfo, EnvironmentsService, ErrorCode, type Event, type FetchLike, FuseApiError, type FuseApiErrorInit, FuseClient, type FuseClientOptions, FuseError, type Host, type HostCapacity, HostsService, type ListEnvironmentsOptions, type ListSnapshotsOptions, type RegisterHostRequest, type Snapshot, type SnapshotExport, type SnapshotRequest, SnapshotsService, type Spec, State, VERSION, isConflict, isFuseApiError, isInvalidArgument, isNotFound, isTerminalState, isUnauthorized, isUnavailable };
440
+ export { type APIKey, ApiKeysService, type CallOptions, type CreateRequest, type CreatedAPIKey, type Endpoint, type EnvironmentInfo, EnvironmentsService, ErrorCode, type Event, type ExecRequest, type ExecResult, type ExposeSpec, type FetchLike, type ForkOptions, FuseApiError, type FuseApiErrorInit, FuseClient, type FuseClientOptions, FuseError, type Host, type HostCapacity, HostsService, type ListEnvironmentsOptions, type ListSnapshotsOptions, type RegisterHostRequest, type Snapshot, type SnapshotExport, type SnapshotRequest, SnapshotsService, type Spec, State, VERSION, isConflict, isFuseApiError, isInvalidArgument, isNotFound, isTerminalState, isUnauthorized, isUnavailable };
package/dist/index.js CHANGED
@@ -385,6 +385,44 @@ var EnvironmentsService = class {
385
385
  signal: opts.signal
386
386
  });
387
387
  }
388
+ /** Fork an environment into a new one; returns the new environment. */
389
+ async fork(vmId, body = {}, opts = {}) {
390
+ requireArg(vmId, "vm id");
391
+ return this.t.json(
392
+ "POST",
393
+ `/v1/environments/${encodeURIComponent(vmId)}`,
394
+ { query: { action: "fork" }, body, signal: opts.signal }
395
+ );
396
+ }
397
+ /**
398
+ * Run a command inside a running environment's guest and return its exit code
399
+ * with stdout and stderr kept separate.
400
+ *
401
+ * A non-zero exit_code is resolved, not thrown: the command ran and failed.
402
+ * A thrown error means the command could not be run at all.
403
+ *
404
+ * Exec requires the master token.
405
+ *
406
+ * @example
407
+ * const out = await client.environments.exec(id, { cmd: ["ls", "-l"] });
408
+ * if (out.exit_code !== 0) console.error(out.stderr);
409
+ */
410
+ async exec(vmId, body, opts = {}) {
411
+ requireArg(vmId, "vm id");
412
+ const hasCmd = (body.cmd?.length ?? 0) > 0;
413
+ const hasShell = (body.shell ?? "") !== "";
414
+ if (!hasCmd && !hasShell) {
415
+ throw new FuseError("one of cmd or shell is required");
416
+ }
417
+ if (hasCmd && hasShell) {
418
+ throw new FuseError("cmd and shell are mutually exclusive");
419
+ }
420
+ return this.t.json(
421
+ "POST",
422
+ `/v1/environments/${encodeURIComponent(vmId)}`,
423
+ { query: { action: "exec" }, body, signal: opts.signal }
424
+ );
425
+ }
388
426
  /** Gracefully drain an environment; returns the updated environment. */
389
427
  async drain(vmId, opts = {}) {
390
428
  requireArg(vmId, "vm id");
@@ -560,7 +598,7 @@ var ApiKeysService = class {
560
598
  };
561
599
 
562
600
  // src/version.ts
563
- var VERSION = "0.0.1";
601
+ var VERSION = "0.4.0";
564
602
 
565
603
  // src/client.ts
566
604
  var FuseClient = class {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/transport.ts","../src/validate.ts","../src/types.ts","../src/events.ts","../src/environments.ts","../src/snapshots.ts","../src/hosts.ts","../src/apiKeys.ts","../src/version.ts","../src/client.ts"],"names":["REQUEST_ID_HEADER"],"mappings":"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","file":"index.js","sourcesContent":["// Error types for the Fuse SDK, mirroring sdks/go/errors.go: a structured\n// FuseApiError for non-2xx responses plus code-checking helpers, and a\n// FuseError for transport/configuration failures.\n\nconst REQUEST_ID_HEADER = \"X-Request-ID\";\n\n/** Stable, machine-readable error codes returned by the server. */\nexport const ErrorCode = {\n NotFound: \"not_found\",\n Conflict: \"conflict\",\n InvalidArgument: \"invalid_argument\",\n Unavailable: \"unavailable\",\n Internal: \"internal\",\n Unauthorized: \"unauthorized\",\n} as const;\n\nexport type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];\n\nconst STATUS_TEXT: Record<number, string> = {\n 400: \"bad request\",\n 401: \"unauthorized\",\n 403: \"forbidden\",\n 404: \"not found\",\n 409: \"conflict\",\n 500: \"internal server error\",\n 502: \"bad gateway\",\n 503: \"service unavailable\",\n};\n\nfunction statusText(status: number): string {\n return STATUS_TEXT[status] ?? `status ${status}`;\n}\n\nexport interface FuseApiErrorInit {\n status: number;\n code?: string;\n message?: string;\n details?: Record<string, string>;\n requestId?: string;\n body?: string;\n}\n\nfunction formatMessage(init: FuseApiErrorInit): string {\n const parts: string[] = [`status=${init.status}`];\n if (init.code) parts.push(`code=${init.code}`);\n if (init.message) parts.push(init.message);\n else parts.push(statusText(init.status));\n if (init.requestId) parts.push(`request_id=${init.requestId}`);\n return \"fuse api error: \" + parts.join(\", \");\n}\n\n/** FuseApiError is a non-2xx response from the server. */\nexport class FuseApiError extends Error {\n readonly status: number;\n readonly code: string;\n readonly details?: Record<string, string>;\n readonly requestId?: string;\n /** Raw response body, when available. */\n readonly body?: string;\n\n constructor(init: FuseApiErrorInit) {\n super(formatMessage(init));\n this.name = \"FuseApiError\";\n this.status = init.status;\n this.code = init.code ?? \"\";\n this.details = init.details;\n this.requestId = init.requestId;\n this.body = init.body;\n // Restore the prototype chain so `instanceof` works after transpilation.\n Object.setPrototypeOf(this, FuseApiError.prototype);\n }\n}\n\n/** FuseError is a transport, configuration, or decoding failure (not an API error). */\nexport class FuseError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"FuseError\";\n Object.setPrototypeOf(this, FuseError.prototype);\n }\n}\n\n/** isFuseApiError is a type guard for FuseApiError. */\nexport function isFuseApiError(err: unknown): err is FuseApiError {\n return err instanceof FuseApiError;\n}\n\nfunction hasCode(err: unknown, code: string): boolean {\n return isFuseApiError(err) && err.code === code;\n}\n\n/** isNotFound reports whether err is a not_found api error. */\nexport function isNotFound(err: unknown): boolean {\n return hasCode(err, ErrorCode.NotFound);\n}\n\n/** isConflict reports whether err is a conflict api error. */\nexport function isConflict(err: unknown): boolean {\n return hasCode(err, ErrorCode.Conflict);\n}\n\n/** isUnauthorized reports whether err is an unauthorized api error. */\nexport function isUnauthorized(err: unknown): boolean {\n return hasCode(err, ErrorCode.Unauthorized);\n}\n\n/** isInvalidArgument reports whether err is an invalid_argument api error. */\nexport function isInvalidArgument(err: unknown): boolean {\n return hasCode(err, ErrorCode.InvalidArgument);\n}\n\n/** isUnavailable reports whether err is an unavailable api error. */\nexport function isUnavailable(err: unknown): boolean {\n return hasCode(err, ErrorCode.Unavailable);\n}\n\ninterface ErrorEnvelope {\n error?: {\n code?: string;\n message?: string;\n details?: Record<string, string>;\n };\n}\n\nfunction parseApiError(\n status: number,\n requestId: string | undefined,\n body: string,\n): FuseApiError {\n if (body) {\n try {\n const env = JSON.parse(body) as ErrorEnvelope;\n const e = env?.error;\n if (e && (e.code || e.message)) {\n return new FuseApiError({\n status,\n code: e.code,\n message: e.message,\n details: e.details,\n requestId,\n body,\n });\n }\n } catch {\n // fall through to the status-text error below\n }\n }\n return new FuseApiError({ status, message: statusText(status), requestId, body });\n}\n\n/**\n * errorFromResponse builds a FuseApiError from a non-2xx Response, parsing the\n * `{\"error\":{code,message,details}}` envelope and reading the X-Request-ID\n * response header for correlation.\n */\nexport async function errorFromResponse(res: Response): Promise<FuseApiError> {\n const requestId = res.headers.get(REQUEST_ID_HEADER) ?? undefined;\n let body = \"\";\n try {\n body = await res.text();\n } catch (err) {\n return new FuseApiError({\n status: res.status,\n message: `read error body: ${String(err)}`,\n requestId,\n });\n }\n return parseApiError(res.status, requestId, body);\n}\n","// The transport layer: builds requests (URL, headers, auth, X-Request-ID,\n// JSON body), applies an optional client-default timeout, executes fetch, and\n// turns non-2xx responses into FuseApiError. Mirrors the transport in\n// sdks/go/environments.go. SSE streams use stream() which deliberately applies\n// no timeout (the Go SDK uses a separate Timeout:0 client for events).\n\nimport { FuseError, errorFromResponse } from \"./errors.js\";\n\nconst REQUEST_ID_HEADER = \"X-Request-ID\";\n\n/** A minimal fetch signature, satisfied by the global fetch and most polyfills. */\nexport type FetchLike = (input: string | URL, init?: RequestInit) => Promise<Response>;\n\n/** Per-call options accepted by every service method. */\nexport interface CallOptions {\n /** Abort the request (and, for events, the stream). */\n signal?: AbortSignal;\n}\n\nexport interface TransportConfig {\n baseUrl: string;\n token?: string;\n fetch?: FetchLike;\n userAgent?: string;\n requestId?: () => string;\n timeoutMs?: number;\n headers?: Record<string, string>;\n}\n\ntype Query = Record<string, string | undefined>;\n\ninterface RequestSpec {\n query?: Query;\n body?: unknown;\n signal?: AbortSignal;\n}\n\n/** Combine zero or more AbortSignals into one, without relying on AbortSignal.any (Node 20+). */\nfunction combineSignals(signals: Array<AbortSignal | undefined>): {\n signal?: AbortSignal;\n cleanup: () => void;\n} {\n const active = signals.filter((s): s is AbortSignal => s != null);\n if (active.length === 0) return { cleanup: () => {} };\n if (active.length === 1) return { signal: active[0], cleanup: () => {} };\n\n const controller = new AbortController();\n const onAbort = (event: Event) => {\n const target = event.target as AbortSignal;\n controller.abort(target.reason);\n cleanup();\n };\n const cleanup = () => {\n for (const s of active) s.removeEventListener(\"abort\", onAbort);\n };\n for (const s of active) {\n if (s.aborted) {\n controller.abort(s.reason);\n cleanup();\n return { signal: controller.signal, cleanup: () => {} };\n }\n s.addEventListener(\"abort\", onAbort);\n }\n return { signal: controller.signal, cleanup };\n}\n\nexport class Transport {\n private readonly baseUrl: URL;\n private readonly token?: string;\n private readonly fetchImpl: FetchLike;\n private readonly userAgent?: string;\n private readonly requestId?: () => string;\n private readonly timeoutMs?: number;\n private readonly defaultHeaders?: Record<string, string>;\n\n constructor(cfg: TransportConfig) {\n if (!cfg.baseUrl) {\n throw new FuseError(\"base url is required\");\n }\n let parsed: URL;\n try {\n parsed = new URL(cfg.baseUrl);\n } catch {\n throw new FuseError(\"base url is invalid\");\n }\n this.baseUrl = parsed;\n this.token = cfg.token;\n this.userAgent = cfg.userAgent;\n this.requestId = cfg.requestId;\n this.timeoutMs = cfg.timeoutMs;\n this.defaultHeaders = cfg.headers;\n\n const provided = cfg.fetch;\n if (provided) {\n this.fetchImpl = provided;\n } else if (typeof globalThis.fetch === \"function\") {\n this.fetchImpl = globalThis.fetch.bind(globalThis) as FetchLike;\n } else {\n throw new FuseError(\n \"global fetch is not available; pass a fetch implementation via the `fetch` option (Node 18+ required)\",\n );\n }\n }\n\n /** Perform a request and decode a JSON response body. */\n async json<T>(method: string, path: string, spec: RequestSpec = {}): Promise<T> {\n const { signal: combined, cleanup } = this.withTimeout(spec.signal);\n try {\n const res = await this.execute(method, path, spec, combined);\n if (!res.ok) throw await errorFromResponse(res);\n return await this.decodeJson<T>(res);\n } finally {\n cleanup();\n }\n }\n\n /** Perform a request that returns no body (e.g. 204 actions). */\n async noContent(method: string, path: string, spec: RequestSpec = {}): Promise<void> {\n const { signal: combined, cleanup } = this.withTimeout(spec.signal);\n try {\n const res = await this.execute(method, path, spec, combined);\n if (!res.ok) throw await errorFromResponse(res);\n // Release the connection even if the server sent a body.\n await res.body?.cancel().catch(() => {});\n } finally {\n cleanup();\n }\n }\n\n /**\n * Open a long-lived stream (SSE). Applies NO timeout — only the caller's\n * signal cancels it — and checks the status eagerly so connect-time errors\n * (404/401/...) surface as a FuseApiError before any iteration.\n */\n async stream(\n path: string,\n query: Query | undefined,\n signal?: AbortSignal,\n ): Promise<Response> {\n const res = await this.execute(\n \"GET\",\n path,\n { query, signal },\n signal,\n \"text/event-stream\",\n );\n if (!res.ok) throw await errorFromResponse(res);\n return res;\n }\n\n private async execute(\n method: string,\n path: string,\n spec: RequestSpec,\n signal: AbortSignal | undefined,\n accept?: string,\n ): Promise<Response> {\n const url = this.buildUrl(path, spec.query);\n const hasBody = spec.body !== undefined && spec.body !== null;\n const headers = this.buildHeaders(hasBody, accept);\n const init: RequestInit = { method, headers };\n if (hasBody) init.body = JSON.stringify(spec.body);\n if (signal) init.signal = signal;\n\n try {\n return await this.fetchImpl(url, init);\n } catch (err) {\n // A caller- or timeout-initiated abort propagates as-is; everything else\n // is wrapped so consumers get a consistent FuseError with a cause.\n if (signal?.aborted) throw err;\n throw new FuseError(`request failed: ${method} ${url}`, { cause: err });\n }\n }\n\n private buildUrl(path: string, query?: Query): string {\n const p = path.startsWith(\"/\") ? path : \"/\" + path;\n const u = new URL(p, this.baseUrl);\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined && value !== \"\") u.searchParams.set(key, value);\n }\n }\n return u.toString();\n }\n\n private buildHeaders(hasBody: boolean, accept?: string): Record<string, string> {\n const headers: Record<string, string> = { ...(this.defaultHeaders ?? {}) };\n if (hasBody) headers[\"Content-Type\"] = \"application/json\";\n if (this.token) headers[\"Authorization\"] = `Bearer ${this.token}`;\n if (this.userAgent) headers[\"User-Agent\"] = this.userAgent;\n if (this.requestId) {\n const id = this.requestId();\n if (id) headers[REQUEST_ID_HEADER] = id;\n }\n if (accept) headers[\"Accept\"] = accept;\n return headers;\n }\n\n private async decodeJson<T>(res: Response): Promise<T> {\n const text = await res.text();\n if (!text) return undefined as T;\n try {\n return JSON.parse(text) as T;\n } catch (err) {\n throw new FuseError(\"decode response body\", { cause: err });\n }\n }\n\n private withTimeout(callerSignal?: AbortSignal): {\n signal?: AbortSignal;\n cleanup: () => void;\n } {\n const signals: Array<AbortSignal | undefined> = [callerSignal];\n if (this.timeoutMs && this.timeoutMs > 0) {\n signals.push(AbortSignal.timeout(this.timeoutMs));\n }\n return combineSignals(signals);\n }\n}\n","import { FuseError } from \"./errors.js\";\n\n/**\n * requireArg throws a FuseError when a required path argument is missing,\n * mirroring the Go SDK's \"<thing> is required\" guards.\n */\nexport function requireArg(value: string | undefined | null, name: string): string {\n if (!value) {\n throw new FuseError(`${name} is required`);\n }\n return value;\n}\n","// Wire types for the Fuse API. Field names match the JSON sent on the wire\n// (snake_case), so request/response bodies pass through JSON.stringify /\n// JSON.parse untouched — a faithful 1:1 mirror of the Go SDK's struct tags\n// (see sdks/go/types.go). List *options* (see each service) use camelCase\n// keys and are translated to snake_case query params by the service.\n\n/** Spec is the hardware/runtime spec for a microVM. */\nexport interface Spec {\n cpus?: number;\n ram_mb?: number;\n storage_gb?: number;\n region?: string;\n max_runtime_seconds?: number;\n}\n\n/** CreateRequest is the body for environments.create. */\nexport interface CreateRequest {\n task_id: string;\n spec?: Spec;\n manifest_inline?: string;\n secrets?: Record<string, string>;\n startup_script?: string;\n gateway_url?: string;\n gateway_token?: string;\n}\n\n/** EnvironmentInfo is the server's view of a single microVM. */\nexport interface EnvironmentInfo {\n id: string;\n state: string;\n task_id: string;\n host_id?: string;\n url: string;\n spec: Spec;\n created_at: string;\n updated_at: string;\n error?: string;\n}\n\n/**\n * Event is one item from environments.events. It matches the server's SSE\n * wire payload. Stream-level failures are thrown from the async iterator\n * rather than delivered as an in-band event.\n */\nexport interface Event {\n id: string;\n /** Event kind. v1 only emits \"state\". */\n event: string;\n vm_id: string;\n state: string;\n url?: string;\n error?: string;\n updated_at: string;\n}\n\n/** SnapshotRequest is the optional body for snapshots.create. */\nexport interface SnapshotRequest {\n comment?: string;\n mode?: string;\n retention_seconds?: number;\n metadata?: Record<string, string>;\n export_ref?: string;\n export_status?: string;\n}\n\n/** SnapshotExport is an optional exported snapshot artifact. */\nexport interface SnapshotExport {\n destination: string;\n status?: string;\n requested_at?: string;\n updated_at?: string;\n last_error?: string;\n}\n\n/** Snapshot is a persisted snapshot record. */\nexport interface Snapshot {\n id: string;\n vm_id: string;\n task_id?: string;\n tenant_id?: string;\n parent_snapshot_id?: string;\n mode?: string;\n state?: string;\n comment?: string;\n size_bytes?: number;\n created_at: string;\n updated_at?: string;\n retention_until?: string;\n last_error?: string;\n export_ref?: string;\n exports?: SnapshotExport[];\n}\n\n/** HostCapacity is a host's resource envelope. */\nexport interface HostCapacity {\n cpus: number;\n ram_mb: number;\n storage_gb: number;\n vm_count: number;\n}\n\n/** RegisterHostRequest is the body for hosts.register. */\nexport interface RegisterHostRequest {\n id: string;\n url: string;\n token?: string;\n region?: string;\n capacity?: HostCapacity;\n}\n\n/** Host is the server's view of a registered host. */\nexport interface Host {\n id: string;\n url: string;\n region?: string;\n state: string;\n capacity: HostCapacity;\n allocated: HostCapacity;\n last_seen: string;\n created_at: string;\n updated_at: string;\n}\n\n/**\n * APIKey is a key's metadata. The raw secret appears only in\n * CreatedAPIKey.key, returned once at creation.\n */\nexport interface APIKey {\n id: string;\n label?: string;\n created_at: string;\n last_used_at?: string;\n revoked_at?: string;\n}\n\n/**\n * CreatedAPIKey is returned by apiKeys.create. `key` is the raw secret and is\n * unrecoverable after this response.\n */\nexport interface CreatedAPIKey extends APIKey {\n key: string;\n}\n\n/** Lifecycle states for EnvironmentInfo.state and Event.state. */\nexport const State = {\n Provisioning: \"provisioning\",\n Running: \"running\",\n Draining: \"draining\",\n Destroying: \"destroying\",\n Destroyed: \"destroyed\",\n Failed: \"failed\",\n} as const;\n\nexport type State = (typeof State)[keyof typeof State];\n\n/** isTerminalState reports whether state is a terminal lifecycle state. */\nexport function isTerminalState(state: string): boolean {\n return state === State.Destroyed || state === State.Failed;\n}\n","// SSE event streaming, porting the state machine in sdks/go/events.go to an\n// async iterator. The stream is opened (and its status checked) eagerly; the\n// returned AsyncIterable yields each Event and ends after a terminal-state\n// event (destroyed/failed) or on clean EOF. Stream-level failures are thrown\n// from the iterator. Caller abort is treated as normal termination.\n\nimport type { Transport } from \"./transport.js\";\nimport { FuseError } from \"./errors.js\";\nimport { type Event, isTerminalState } from \"./types.js\";\n\nconst DATA_PREFIX = \"data:\";\n\n/** Open the SSE stream for an environment and return an async-iterable of events. */\nexport async function streamEvents(\n t: Transport,\n vmId: string,\n signal?: AbortSignal,\n): Promise<AsyncIterable<Event>> {\n const path = `/v1/environments/${encodeURIComponent(vmId)}/events`;\n const res = await t.stream(path, undefined, signal);\n return parseEventStream(res, signal);\n}\n\nfunction parseEventStream(res: Response, signal?: AbortSignal): AsyncIterable<Event> {\n return {\n async *[Symbol.asyncIterator](): AsyncGenerator<Event> {\n const body = res.body;\n if (!body) return;\n\n const reader = body.getReader();\n const decoder = new TextDecoder(\"utf-8\");\n let buffer = \"\";\n let data = \"\";\n let hasData = false;\n\n try {\n while (true) {\n let chunk;\n try {\n chunk = await reader.read();\n } catch (err) {\n // Caller-initiated abort is a clean end, not an error.\n if (signal?.aborted) return;\n throw new FuseError(\"event stream read failed\", { cause: err });\n }\n if (chunk.done) {\n // Clean EOF with no terminal state: just end (matches Go).\n return;\n }\n\n buffer += decoder.decode(chunk.value, { stream: true });\n\n let nl: number;\n while ((nl = buffer.indexOf(\"\\n\")) >= 0) {\n let line = buffer.slice(0, nl);\n buffer = buffer.slice(nl + 1);\n if (line.endsWith(\"\\r\")) line = line.slice(0, -1); // tolerate CRLF\n\n if (line === \"\") {\n // Blank line terminates the current event.\n if (!hasData) continue;\n const payload = data;\n data = \"\";\n hasData = false;\n\n let event: Event;\n try {\n event = JSON.parse(payload) as Event;\n } catch (err) {\n throw new FuseError(\"decode event\", { cause: err });\n }\n yield event;\n if (isTerminalState(event.state)) return;\n } else if (line.startsWith(\":\")) {\n // Comment / keepalive line — skip.\n continue;\n } else if (line.startsWith(DATA_PREFIX)) {\n // Strip the prefix and a single optional leading space; multiple\n // data: lines concatenate without a separator (matches server).\n let p = line.slice(DATA_PREFIX.length);\n if (p.startsWith(\" \")) p = p.slice(1);\n data += p;\n hasData = true;\n }\n // Other fields (id:, event:, ...) are ignored.\n }\n }\n } finally {\n // Release the underlying socket if the consumer breaks early.\n try {\n await reader.cancel();\n } catch {\n // ignore\n }\n }\n },\n };\n}\n","import type { CallOptions, Transport } from \"./transport.js\";\nimport type { CreateRequest, EnvironmentInfo, Event } from \"./types.js\";\nimport { requireArg } from \"./validate.js\";\nimport { streamEvents } from \"./events.js\";\n\n/** Filters for environments.list. */\nexport interface ListEnvironmentsOptions {\n taskId?: string;\n state?: string;\n hostId?: string;\n}\n\ninterface EnvironmentList {\n environments: EnvironmentInfo[];\n}\n\n/** EnvironmentsService manages microVM lifecycle. */\nexport class EnvironmentsService {\n constructor(private readonly t: Transport) {}\n\n /** List tracked environments, optionally filtered. */\n async list(\n options: ListEnvironmentsOptions = {},\n opts: CallOptions = {},\n ): Promise<EnvironmentInfo[]> {\n const out = await this.t.json<EnvironmentList>(\"GET\", \"/v1/environments\", {\n query: { task_id: options.taskId, state: options.state, host_id: options.hostId },\n signal: opts.signal,\n });\n return out.environments ?? [];\n }\n\n /** Fetch a single environment by VM id. */\n async get(vmId: string, opts: CallOptions = {}): Promise<EnvironmentInfo> {\n requireArg(vmId, \"vm id\");\n return this.t.json<EnvironmentInfo>(\n \"GET\",\n `/v1/environments/${encodeURIComponent(vmId)}`,\n { signal: opts.signal },\n );\n }\n\n /** Provision a new environment. Blocks until running or creation fails. */\n async create(body: CreateRequest, opts: CallOptions = {}): Promise<EnvironmentInfo> {\n return this.t.json<EnvironmentInfo>(\"POST\", \"/v1/environments\", {\n body,\n signal: opts.signal,\n });\n }\n\n /** Gracefully drain an environment; returns the updated environment. */\n async drain(vmId: string, opts: CallOptions = {}): Promise<EnvironmentInfo> {\n requireArg(vmId, \"vm id\");\n return this.t.json<EnvironmentInfo>(\n \"POST\",\n `/v1/environments/${encodeURIComponent(vmId)}`,\n { query: { action: \"drain\" }, signal: opts.signal },\n );\n }\n\n /** Rotate the per-VM credentials and push them to the guest. */\n async rotateToken(vmId: string, opts: CallOptions = {}): Promise<void> {\n requireArg(vmId, \"vm id\");\n await this.t.noContent(\"POST\", `/v1/environments/${encodeURIComponent(vmId)}`, {\n query: { action: \"rotate-token\" },\n signal: opts.signal,\n });\n }\n\n /** Forcefully destroy an environment. Idempotent. */\n async destroy(vmId: string, opts: CallOptions = {}): Promise<void> {\n requireArg(vmId, \"vm id\");\n await this.t.noContent(\"DELETE\", `/v1/environments/${encodeURIComponent(vmId)}`, {\n signal: opts.signal,\n });\n }\n\n /**\n * Open the SSE event stream for an environment. The returned promise rejects\n * with a FuseApiError on a connect-time failure (e.g. not_found); on success\n * it resolves to an AsyncIterable that yields each Event and ends after a\n * terminal-state event. Pass `opts.signal` to cancel; there is no built-in\n * timeout on the stream.\n *\n * @example\n * for await (const ev of await client.environments.events(id)) {\n * console.log(ev.state);\n * }\n */\n async events(vmId: string, opts: CallOptions = {}): Promise<AsyncIterable<Event>> {\n requireArg(vmId, \"vm id\");\n return streamEvents(this.t, vmId, opts.signal);\n }\n}\n","import type { CallOptions, Transport } from \"./transport.js\";\nimport type { Snapshot, SnapshotRequest } from \"./types.js\";\nimport { requireArg } from \"./validate.js\";\n\n/** Filters for snapshots.list. */\nexport interface ListSnapshotsOptions {\n vmId?: string;\n taskId?: string;\n tenantId?: string;\n state?: string;\n}\n\ninterface SnapshotList {\n snapshots: Snapshot[];\n}\n\n/** SnapshotsService manages microVM snapshots. */\nexport class SnapshotsService {\n constructor(private readonly t: Transport) {}\n\n /** Create a snapshot of a running environment. */\n async create(\n vmId: string,\n body: SnapshotRequest = {},\n opts: CallOptions = {},\n ): Promise<Snapshot> {\n requireArg(vmId, \"vm id\");\n return this.t.json<Snapshot>(\n \"POST\",\n `/v1/environments/${encodeURIComponent(vmId)}/snapshots`,\n { body, signal: opts.signal },\n );\n }\n\n /** List snapshots, optionally filtered. */\n async list(\n options: ListSnapshotsOptions = {},\n opts: CallOptions = {},\n ): Promise<Snapshot[]> {\n const out = await this.t.json<SnapshotList>(\"GET\", \"/v1/snapshots\", {\n query: {\n vm_id: options.vmId,\n task_id: options.taskId,\n tenant_id: options.tenantId,\n state: options.state,\n },\n signal: opts.signal,\n });\n return out.snapshots ?? [];\n }\n\n /** Fetch a single snapshot by id. */\n async get(snapshotId: string, opts: CallOptions = {}): Promise<Snapshot> {\n requireArg(snapshotId, \"snapshot id\");\n return this.t.json<Snapshot>(\n \"GET\",\n `/v1/snapshots/${encodeURIComponent(snapshotId)}`,\n { signal: opts.signal },\n );\n }\n\n /** Delete a snapshot. Idempotent; the snapshot must be a leaf. */\n async delete(snapshotId: string, opts: CallOptions = {}): Promise<void> {\n requireArg(snapshotId, \"snapshot id\");\n await this.t.noContent(\"DELETE\", `/v1/snapshots/${encodeURIComponent(snapshotId)}`, {\n signal: opts.signal,\n });\n }\n\n /** Restore an environment from a snapshot. */\n async restore(snapshotId: string, opts: CallOptions = {}): Promise<void> {\n requireArg(snapshotId, \"snapshot id\");\n await this.t.noContent(\"POST\", `/v1/snapshots/${encodeURIComponent(snapshotId)}`, {\n query: { action: \"restore\" },\n signal: opts.signal,\n });\n }\n}\n","import type { CallOptions, Transport } from \"./transport.js\";\nimport type { Host, RegisterHostRequest } from \"./types.js\";\nimport { requireArg } from \"./validate.js\";\n\ninterface HostList {\n hosts: Host[];\n}\n\n/** HostsService manages registered Firecracker hosts. */\nexport class HostsService {\n constructor(private readonly t: Transport) {}\n\n /** Register (or re-register) a host. Idempotent on id. */\n async register(body: RegisterHostRequest, opts: CallOptions = {}): Promise<Host> {\n return this.t.json<Host>(\"POST\", \"/v1/hosts\", { body, signal: opts.signal });\n }\n\n /** List registered hosts. */\n async list(opts: CallOptions = {}): Promise<Host[]> {\n const out = await this.t.json<HostList>(\"GET\", \"/v1/hosts\", { signal: opts.signal });\n return out.hosts ?? [];\n }\n\n /** Fetch a single host by id. */\n async get(hostId: string, opts: CallOptions = {}): Promise<Host> {\n requireArg(hostId, \"host id\");\n return this.t.json<Host>(\"GET\", `/v1/hosts/${encodeURIComponent(hostId)}`, {\n signal: opts.signal,\n });\n }\n\n /** Mark a host unschedulable; existing VMs keep running. */\n async cordon(hostId: string, opts: CallOptions = {}): Promise<void> {\n await this.action(hostId, \"cordon\", opts);\n }\n\n /** Return a cordoned host to active scheduling. */\n async uncordon(hostId: string, opts: CallOptions = {}): Promise<void> {\n await this.action(hostId, \"uncordon\", opts);\n }\n\n /** Remove a host. The host must have no running VMs. */\n async deregister(hostId: string, opts: CallOptions = {}): Promise<void> {\n requireArg(hostId, \"host id\");\n await this.t.noContent(\"DELETE\", `/v1/hosts/${encodeURIComponent(hostId)}`, {\n signal: opts.signal,\n });\n }\n\n private async action(hostId: string, action: string, opts: CallOptions): Promise<void> {\n requireArg(hostId, \"host id\");\n await this.t.noContent(\"POST\", `/v1/hosts/${encodeURIComponent(hostId)}`, {\n query: { action },\n signal: opts.signal,\n });\n }\n}\n","import type { CallOptions, Transport } from \"./transport.js\";\nimport type { APIKey, CreatedAPIKey } from \"./types.js\";\nimport { requireArg } from \"./validate.js\";\n\ninterface APIKeyList {\n api_keys: APIKey[];\n}\n\n/**\n * ApiKeysService manages revocable API keys. These endpoints require the\n * master token; the server enforces this.\n */\nexport class ApiKeysService {\n constructor(private readonly t: Transport) {}\n\n /**\n * Issue a new API key. The raw secret is returned once in `key` and is\n * unrecoverable afterward.\n */\n async create(label?: string, opts: CallOptions = {}): Promise<CreatedAPIKey> {\n return this.t.json<CreatedAPIKey>(\"POST\", \"/v1/api-keys\", {\n body: label ? { label } : {},\n signal: opts.signal,\n });\n }\n\n /** List API key metadata. */\n async list(opts: CallOptions = {}): Promise<APIKey[]> {\n const out = await this.t.json<APIKeyList>(\"GET\", \"/v1/api-keys\", {\n signal: opts.signal,\n });\n return out.api_keys ?? [];\n }\n\n /** Revoke the API key with the given id. */\n async revoke(id: string, opts: CallOptions = {}): Promise<void> {\n requireArg(id, \"id\");\n await this.t.noContent(\"DELETE\", `/v1/api-keys/${encodeURIComponent(id)}`, {\n signal: opts.signal,\n });\n }\n}\n","// generated by scripts/gen-version.mjs. do not edit.\nexport const VERSION = \"0.0.1\";\n","import { Transport, type FetchLike } from \"./transport.js\";\nimport { EnvironmentsService } from \"./environments.js\";\nimport { SnapshotsService } from \"./snapshots.js\";\nimport { HostsService } from \"./hosts.js\";\nimport { ApiKeysService } from \"./apiKeys.js\";\nimport { VERSION } from \"./version.js\";\n\n/** Options for constructing a FuseClient. */\nexport interface FuseClientOptions {\n /** Base URL of the Fuse control plane, e.g. \"https://fuse.example.com\". Required. */\n baseUrl: string;\n /** Bearer token (master token or an API key). Omit for unauthenticated endpoints. */\n token?: string;\n /** Custom fetch implementation. Defaults to the global fetch (Node 18+). */\n fetch?: FetchLike;\n /** User-Agent header. Defaults to \"fuse-ts/<version>\". Ignored by browsers. */\n userAgent?: string;\n /** Generator for the X-Request-ID header, called once per request. Empty results are omitted. */\n requestId?: () => string;\n /** Default per-request timeout in milliseconds. Does NOT apply to events() streams. */\n timeoutMs?: number;\n /** Extra default headers merged into every request. */\n headers?: Record<string, string>;\n}\n\n/**\n * FuseClient is the entry point for the Fuse API. It groups the resource\n * services that share a single transport.\n *\n * @example\n * const client = new FuseClient({ baseUrl: \"https://fuse.example.com\", token });\n * const env = await client.environments.create({ task_id: \"task-1\" });\n */\nexport class FuseClient {\n readonly environments: EnvironmentsService;\n readonly snapshots: SnapshotsService;\n readonly hosts: HostsService;\n readonly apiKeys: ApiKeysService;\n\n constructor(options: FuseClientOptions) {\n const transport = new Transport({\n baseUrl: options.baseUrl,\n token: options.token,\n fetch: options.fetch,\n userAgent: options.userAgent ?? `fuse-ts/${VERSION}`,\n requestId: options.requestId,\n timeoutMs: options.timeoutMs,\n headers: options.headers,\n });\n this.environments = new EnvironmentsService(transport);\n this.snapshots = new SnapshotsService(transport);\n this.hosts = new HostsService(transport);\n this.apiKeys = new ApiKeysService(transport);\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/transport.ts","../src/validate.ts","../src/types.ts","../src/events.ts","../src/environments.ts","../src/snapshots.ts","../src/hosts.ts","../src/apiKeys.ts","../src/version.ts","../src/client.ts"],"names":["REQUEST_ID_HEADER"],"mappings":"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","file":"index.js","sourcesContent":["// Error types for the Fuse SDK, mirroring sdks/go/errors.go: a structured\n// FuseApiError for non-2xx responses plus code-checking helpers, and a\n// FuseError for transport/configuration failures.\n\nconst REQUEST_ID_HEADER = \"X-Request-ID\";\n\n/** Stable, machine-readable error codes returned by the server. */\nexport const ErrorCode = {\n NotFound: \"not_found\",\n Conflict: \"conflict\",\n InvalidArgument: \"invalid_argument\",\n Unavailable: \"unavailable\",\n Internal: \"internal\",\n Unauthorized: \"unauthorized\",\n} as const;\n\nexport type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];\n\nconst STATUS_TEXT: Record<number, string> = {\n 400: \"bad request\",\n 401: \"unauthorized\",\n 403: \"forbidden\",\n 404: \"not found\",\n 409: \"conflict\",\n 500: \"internal server error\",\n 502: \"bad gateway\",\n 503: \"service unavailable\",\n};\n\nfunction statusText(status: number): string {\n return STATUS_TEXT[status] ?? `status ${status}`;\n}\n\nexport interface FuseApiErrorInit {\n status: number;\n code?: string;\n message?: string;\n details?: Record<string, string>;\n requestId?: string;\n body?: string;\n}\n\nfunction formatMessage(init: FuseApiErrorInit): string {\n const parts: string[] = [`status=${init.status}`];\n if (init.code) parts.push(`code=${init.code}`);\n if (init.message) parts.push(init.message);\n else parts.push(statusText(init.status));\n if (init.requestId) parts.push(`request_id=${init.requestId}`);\n return \"fuse api error: \" + parts.join(\", \");\n}\n\n/** FuseApiError is a non-2xx response from the server. */\nexport class FuseApiError extends Error {\n readonly status: number;\n readonly code: string;\n readonly details?: Record<string, string>;\n readonly requestId?: string;\n /** Raw response body, when available. */\n readonly body?: string;\n\n constructor(init: FuseApiErrorInit) {\n super(formatMessage(init));\n this.name = \"FuseApiError\";\n this.status = init.status;\n this.code = init.code ?? \"\";\n this.details = init.details;\n this.requestId = init.requestId;\n this.body = init.body;\n // Restore the prototype chain so `instanceof` works after transpilation.\n Object.setPrototypeOf(this, FuseApiError.prototype);\n }\n}\n\n/** FuseError is a transport, configuration, or decoding failure (not an API error). */\nexport class FuseError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"FuseError\";\n Object.setPrototypeOf(this, FuseError.prototype);\n }\n}\n\n/** isFuseApiError is a type guard for FuseApiError. */\nexport function isFuseApiError(err: unknown): err is FuseApiError {\n return err instanceof FuseApiError;\n}\n\nfunction hasCode(err: unknown, code: string): boolean {\n return isFuseApiError(err) && err.code === code;\n}\n\n/** isNotFound reports whether err is a not_found api error. */\nexport function isNotFound(err: unknown): boolean {\n return hasCode(err, ErrorCode.NotFound);\n}\n\n/** isConflict reports whether err is a conflict api error. */\nexport function isConflict(err: unknown): boolean {\n return hasCode(err, ErrorCode.Conflict);\n}\n\n/** isUnauthorized reports whether err is an unauthorized api error. */\nexport function isUnauthorized(err: unknown): boolean {\n return hasCode(err, ErrorCode.Unauthorized);\n}\n\n/** isInvalidArgument reports whether err is an invalid_argument api error. */\nexport function isInvalidArgument(err: unknown): boolean {\n return hasCode(err, ErrorCode.InvalidArgument);\n}\n\n/** isUnavailable reports whether err is an unavailable api error. */\nexport function isUnavailable(err: unknown): boolean {\n return hasCode(err, ErrorCode.Unavailable);\n}\n\ninterface ErrorEnvelope {\n error?: {\n code?: string;\n message?: string;\n details?: Record<string, string>;\n };\n}\n\nfunction parseApiError(\n status: number,\n requestId: string | undefined,\n body: string,\n): FuseApiError {\n if (body) {\n try {\n const env = JSON.parse(body) as ErrorEnvelope;\n const e = env?.error;\n if (e && (e.code || e.message)) {\n return new FuseApiError({\n status,\n code: e.code,\n message: e.message,\n details: e.details,\n requestId,\n body,\n });\n }\n } catch {\n // fall through to the status-text error below\n }\n }\n return new FuseApiError({ status, message: statusText(status), requestId, body });\n}\n\n/**\n * errorFromResponse builds a FuseApiError from a non-2xx Response, parsing the\n * `{\"error\":{code,message,details}}` envelope and reading the X-Request-ID\n * response header for correlation.\n */\nexport async function errorFromResponse(res: Response): Promise<FuseApiError> {\n const requestId = res.headers.get(REQUEST_ID_HEADER) ?? undefined;\n let body = \"\";\n try {\n body = await res.text();\n } catch (err) {\n return new FuseApiError({\n status: res.status,\n message: `read error body: ${String(err)}`,\n requestId,\n });\n }\n return parseApiError(res.status, requestId, body);\n}\n","// The transport layer: builds requests (URL, headers, auth, X-Request-ID,\n// JSON body), applies an optional client-default timeout, executes fetch, and\n// turns non-2xx responses into FuseApiError. Mirrors the transport in\n// sdks/go/environments.go. SSE streams use stream() which deliberately applies\n// no timeout (the Go SDK uses a separate Timeout:0 client for events).\n\nimport { FuseError, errorFromResponse } from \"./errors.js\";\n\nconst REQUEST_ID_HEADER = \"X-Request-ID\";\n\n/** A minimal fetch signature, satisfied by the global fetch and most polyfills. */\nexport type FetchLike = (input: string | URL, init?: RequestInit) => Promise<Response>;\n\n/** Per-call options accepted by every service method. */\nexport interface CallOptions {\n /** Abort the request (and, for events, the stream). */\n signal?: AbortSignal;\n}\n\nexport interface TransportConfig {\n baseUrl: string;\n token?: string;\n fetch?: FetchLike;\n userAgent?: string;\n requestId?: () => string;\n timeoutMs?: number;\n headers?: Record<string, string>;\n}\n\ntype Query = Record<string, string | undefined>;\n\ninterface RequestSpec {\n query?: Query;\n body?: unknown;\n signal?: AbortSignal;\n}\n\n/** Combine zero or more AbortSignals into one, without relying on AbortSignal.any (Node 20+). */\nfunction combineSignals(signals: Array<AbortSignal | undefined>): {\n signal?: AbortSignal;\n cleanup: () => void;\n} {\n const active = signals.filter((s): s is AbortSignal => s != null);\n if (active.length === 0) return { cleanup: () => {} };\n if (active.length === 1) return { signal: active[0], cleanup: () => {} };\n\n const controller = new AbortController();\n const onAbort = (event: Event) => {\n const target = event.target as AbortSignal;\n controller.abort(target.reason);\n cleanup();\n };\n const cleanup = () => {\n for (const s of active) s.removeEventListener(\"abort\", onAbort);\n };\n for (const s of active) {\n if (s.aborted) {\n controller.abort(s.reason);\n cleanup();\n return { signal: controller.signal, cleanup: () => {} };\n }\n s.addEventListener(\"abort\", onAbort);\n }\n return { signal: controller.signal, cleanup };\n}\n\nexport class Transport {\n private readonly baseUrl: URL;\n private readonly token?: string;\n private readonly fetchImpl: FetchLike;\n private readonly userAgent?: string;\n private readonly requestId?: () => string;\n private readonly timeoutMs?: number;\n private readonly defaultHeaders?: Record<string, string>;\n\n constructor(cfg: TransportConfig) {\n if (!cfg.baseUrl) {\n throw new FuseError(\"base url is required\");\n }\n let parsed: URL;\n try {\n parsed = new URL(cfg.baseUrl);\n } catch {\n throw new FuseError(\"base url is invalid\");\n }\n this.baseUrl = parsed;\n this.token = cfg.token;\n this.userAgent = cfg.userAgent;\n this.requestId = cfg.requestId;\n this.timeoutMs = cfg.timeoutMs;\n this.defaultHeaders = cfg.headers;\n\n const provided = cfg.fetch;\n if (provided) {\n this.fetchImpl = provided;\n } else if (typeof globalThis.fetch === \"function\") {\n this.fetchImpl = globalThis.fetch.bind(globalThis) as FetchLike;\n } else {\n throw new FuseError(\n \"global fetch is not available; pass a fetch implementation via the `fetch` option (Node 18+ required)\",\n );\n }\n }\n\n /** Perform a request and decode a JSON response body. */\n async json<T>(method: string, path: string, spec: RequestSpec = {}): Promise<T> {\n const { signal: combined, cleanup } = this.withTimeout(spec.signal);\n try {\n const res = await this.execute(method, path, spec, combined);\n if (!res.ok) throw await errorFromResponse(res);\n return await this.decodeJson<T>(res);\n } finally {\n cleanup();\n }\n }\n\n /** Perform a request that returns no body (e.g. 204 actions). */\n async noContent(method: string, path: string, spec: RequestSpec = {}): Promise<void> {\n const { signal: combined, cleanup } = this.withTimeout(spec.signal);\n try {\n const res = await this.execute(method, path, spec, combined);\n if (!res.ok) throw await errorFromResponse(res);\n // Release the connection even if the server sent a body.\n await res.body?.cancel().catch(() => {});\n } finally {\n cleanup();\n }\n }\n\n /**\n * Open a long-lived stream (SSE). Applies NO timeout — only the caller's\n * signal cancels it — and checks the status eagerly so connect-time errors\n * (404/401/...) surface as a FuseApiError before any iteration.\n */\n async stream(\n path: string,\n query: Query | undefined,\n signal?: AbortSignal,\n ): Promise<Response> {\n const res = await this.execute(\n \"GET\",\n path,\n { query, signal },\n signal,\n \"text/event-stream\",\n );\n if (!res.ok) throw await errorFromResponse(res);\n return res;\n }\n\n private async execute(\n method: string,\n path: string,\n spec: RequestSpec,\n signal: AbortSignal | undefined,\n accept?: string,\n ): Promise<Response> {\n const url = this.buildUrl(path, spec.query);\n const hasBody = spec.body !== undefined && spec.body !== null;\n const headers = this.buildHeaders(hasBody, accept);\n const init: RequestInit = { method, headers };\n if (hasBody) init.body = JSON.stringify(spec.body);\n if (signal) init.signal = signal;\n\n try {\n return await this.fetchImpl(url, init);\n } catch (err) {\n // A caller- or timeout-initiated abort propagates as-is; everything else\n // is wrapped so consumers get a consistent FuseError with a cause.\n if (signal?.aborted) throw err;\n throw new FuseError(`request failed: ${method} ${url}`, { cause: err });\n }\n }\n\n private buildUrl(path: string, query?: Query): string {\n const p = path.startsWith(\"/\") ? path : \"/\" + path;\n const u = new URL(p, this.baseUrl);\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined && value !== \"\") u.searchParams.set(key, value);\n }\n }\n return u.toString();\n }\n\n private buildHeaders(hasBody: boolean, accept?: string): Record<string, string> {\n const headers: Record<string, string> = { ...(this.defaultHeaders ?? {}) };\n if (hasBody) headers[\"Content-Type\"] = \"application/json\";\n if (this.token) headers[\"Authorization\"] = `Bearer ${this.token}`;\n if (this.userAgent) headers[\"User-Agent\"] = this.userAgent;\n if (this.requestId) {\n const id = this.requestId();\n if (id) headers[REQUEST_ID_HEADER] = id;\n }\n if (accept) headers[\"Accept\"] = accept;\n return headers;\n }\n\n private async decodeJson<T>(res: Response): Promise<T> {\n const text = await res.text();\n if (!text) return undefined as T;\n try {\n return JSON.parse(text) as T;\n } catch (err) {\n throw new FuseError(\"decode response body\", { cause: err });\n }\n }\n\n private withTimeout(callerSignal?: AbortSignal): {\n signal?: AbortSignal;\n cleanup: () => void;\n } {\n const signals: Array<AbortSignal | undefined> = [callerSignal];\n if (this.timeoutMs && this.timeoutMs > 0) {\n signals.push(AbortSignal.timeout(this.timeoutMs));\n }\n return combineSignals(signals);\n }\n}\n","import { FuseError } from \"./errors.js\";\n\n/**\n * requireArg throws a FuseError when a required path argument is missing,\n * mirroring the Go SDK's \"<thing> is required\" guards.\n */\nexport function requireArg(value: string | undefined | null, name: string): string {\n if (!value) {\n throw new FuseError(`${name} is required`);\n }\n return value;\n}\n","// Wire types for the Fuse API. Field names match the JSON sent on the wire\n// (snake_case), so request/response bodies pass through JSON.stringify /\n// JSON.parse untouched — a faithful 1:1 mirror of the Go SDK's struct tags\n// (see sdks/go/types.go). List *options* (see each service) use camelCase\n// keys and are translated to snake_case query params by the service.\n\n/** Spec is the hardware/runtime spec for a microVM. */\nexport interface Spec {\n cpus?: number;\n ram_mb?: number;\n storage_gb?: number;\n gpus?: number;\n gpu_kind?: string;\n region?: string;\n max_runtime_seconds?: number;\n image?: string;\n}\n\n/** ExposeSpec requests that a guest port be published at boot. */\nexport interface ExposeSpec {\n port: number;\n as?: string;\n}\n\n/** Endpoint is a published port with its externally reachable URL. */\nexport interface Endpoint {\n as?: string;\n url: string;\n port: number;\n}\n\n/** CreateRequest is the body for environments.create. */\nexport interface CreateRequest {\n task_id: string;\n spec?: Spec;\n manifest_inline?: string;\n secrets?: Record<string, string>;\n startup_script?: string;\n gateway_url?: string;\n gateway_token?: string;\n expose?: ExposeSpec[];\n}\n\n/** EnvironmentInfo is the server's view of a single microVM. */\nexport interface EnvironmentInfo {\n id: string;\n state: string;\n task_id: string;\n host_id?: string;\n url: string;\n spec: Spec;\n created_at: string;\n updated_at: string;\n error?: string;\n endpoints?: Endpoint[];\n}\n\n/** ForkOptions is the optional body for environments.fork. */\nexport interface ForkOptions {\n reuse_snapshot_id?: string;\n comment?: string;\n}\n\n/** ExecRequest is the body for environments.exec. Exactly one of cmd or shell must be set. */\nexport interface ExecRequest {\n /**\n * The argv to run in the guest, e.g. [\"ls\", \"-l\"]. Argv needs no quoting\n * rules and cannot be turned into an injection by interpolating a value, so\n * prefer it.\n */\n cmd?: string[];\n\n /**\n * Runs the string under `sh -lc`. Use it only for what argv cannot express:\n * pipelines, redirects, and globs.\n */\n shell?: string;\n\n /**\n * Bounds the command inside the guest. Zero or unset takes the server\n * default; the server clamps anything above its ceiling.\n */\n timeout_ms?: number;\n}\n\n/**\n * ExecResult is the outcome of a guest command.\n *\n * A non-zero exit_code is a successful call: the command ran and failed. Only a\n * thrown error means the command could not be run at all.\n */\nexport interface ExecResult {\n exit_code: number;\n stdout: string;\n stderr: string;\n}\n\n/**\n * Event is one item from environments.events. It matches the server's SSE\n * wire payload. Stream-level failures are thrown from the async iterator\n * rather than delivered as an in-band event.\n */\nexport interface Event {\n id: string;\n /** Event kind. v1 only emits \"state\". */\n event: string;\n vm_id: string;\n state: string;\n url?: string;\n error?: string;\n updated_at: string;\n}\n\n/** SnapshotRequest is the optional body for snapshots.create. */\nexport interface SnapshotRequest {\n comment?: string;\n mode?: string;\n retention_seconds?: number;\n metadata?: Record<string, string>;\n export_ref?: string;\n export_status?: string;\n}\n\n/** SnapshotExport is an optional exported snapshot artifact. */\nexport interface SnapshotExport {\n destination: string;\n status?: string;\n requested_at?: string;\n updated_at?: string;\n last_error?: string;\n}\n\n/** Snapshot is a persisted snapshot record. */\nexport interface Snapshot {\n id: string;\n vm_id: string;\n task_id?: string;\n tenant_id?: string;\n parent_snapshot_id?: string;\n mode?: string;\n state?: string;\n comment?: string;\n size_bytes?: number;\n created_at: string;\n updated_at?: string;\n retention_until?: string;\n last_error?: string;\n export_ref?: string;\n exports?: SnapshotExport[];\n}\n\n/** HostCapacity is a host's resource envelope. */\nexport interface HostCapacity {\n cpus: number;\n ram_mb: number;\n storage_gb: number;\n vm_count: number;\n gpus?: number;\n gpu_kind?: string;\n}\n\n/** RegisterHostRequest is the body for hosts.register. */\nexport interface RegisterHostRequest {\n id: string;\n url: string;\n token?: string;\n region?: string;\n backend?: string;\n capacity?: HostCapacity;\n}\n\n/** Host is the server's view of a registered host. */\nexport interface Host {\n id: string;\n url: string;\n region?: string;\n state: string;\n backend?: string;\n capacity: HostCapacity;\n allocated: HostCapacity;\n last_seen: string;\n created_at: string;\n updated_at: string;\n /** Non-fatal registration notices (e.g. declared capacity exceeding the\n * probed value). Only ever populated on the response to hosts.register. */\n warnings?: string[];\n}\n\n/**\n * APIKey is a key's metadata. The raw secret appears only in\n * CreatedAPIKey.key, returned once at creation.\n */\nexport interface APIKey {\n id: string;\n label?: string;\n created_at: string;\n last_used_at?: string;\n revoked_at?: string;\n}\n\n/**\n * CreatedAPIKey is returned by apiKeys.create. `key` is the raw secret and is\n * unrecoverable after this response.\n */\nexport interface CreatedAPIKey extends APIKey {\n key: string;\n}\n\n/** Lifecycle states for EnvironmentInfo.state and Event.state. */\nexport const State = {\n Provisioning: \"provisioning\",\n Running: \"running\",\n Draining: \"draining\",\n Destroying: \"destroying\",\n Destroyed: \"destroyed\",\n Failed: \"failed\",\n} as const;\n\nexport type State = (typeof State)[keyof typeof State];\n\n/** isTerminalState reports whether state is a terminal lifecycle state. */\nexport function isTerminalState(state: string): boolean {\n return state === State.Destroyed || state === State.Failed;\n}\n","// SSE event streaming, porting the state machine in sdks/go/events.go to an\n// async iterator. The stream is opened (and its status checked) eagerly; the\n// returned AsyncIterable yields each Event and ends after a terminal-state\n// event (destroyed/failed) or on clean EOF. Stream-level failures are thrown\n// from the iterator. Caller abort is treated as normal termination.\n\nimport type { Transport } from \"./transport.js\";\nimport { FuseError } from \"./errors.js\";\nimport { type Event, isTerminalState } from \"./types.js\";\n\nconst DATA_PREFIX = \"data:\";\n\n/** Open the SSE stream for an environment and return an async-iterable of events. */\nexport async function streamEvents(\n t: Transport,\n vmId: string,\n signal?: AbortSignal,\n): Promise<AsyncIterable<Event>> {\n const path = `/v1/environments/${encodeURIComponent(vmId)}/events`;\n const res = await t.stream(path, undefined, signal);\n return parseEventStream(res, signal);\n}\n\nfunction parseEventStream(res: Response, signal?: AbortSignal): AsyncIterable<Event> {\n return {\n async *[Symbol.asyncIterator](): AsyncGenerator<Event> {\n const body = res.body;\n if (!body) return;\n\n const reader = body.getReader();\n const decoder = new TextDecoder(\"utf-8\");\n let buffer = \"\";\n let data = \"\";\n let hasData = false;\n\n try {\n while (true) {\n let chunk;\n try {\n chunk = await reader.read();\n } catch (err) {\n // Caller-initiated abort is a clean end, not an error.\n if (signal?.aborted) return;\n throw new FuseError(\"event stream read failed\", { cause: err });\n }\n if (chunk.done) {\n // Clean EOF with no terminal state: just end (matches Go).\n return;\n }\n\n buffer += decoder.decode(chunk.value, { stream: true });\n\n let nl: number;\n while ((nl = buffer.indexOf(\"\\n\")) >= 0) {\n let line = buffer.slice(0, nl);\n buffer = buffer.slice(nl + 1);\n if (line.endsWith(\"\\r\")) line = line.slice(0, -1); // tolerate CRLF\n\n if (line === \"\") {\n // Blank line terminates the current event.\n if (!hasData) continue;\n const payload = data;\n data = \"\";\n hasData = false;\n\n let event: Event;\n try {\n event = JSON.parse(payload) as Event;\n } catch (err) {\n throw new FuseError(\"decode event\", { cause: err });\n }\n yield event;\n if (isTerminalState(event.state)) return;\n } else if (line.startsWith(\":\")) {\n // Comment / keepalive line — skip.\n continue;\n } else if (line.startsWith(DATA_PREFIX)) {\n // Strip the prefix and a single optional leading space; multiple\n // data: lines concatenate without a separator (matches server).\n let p = line.slice(DATA_PREFIX.length);\n if (p.startsWith(\" \")) p = p.slice(1);\n data += p;\n hasData = true;\n }\n // Other fields (id:, event:, ...) are ignored.\n }\n }\n } finally {\n // Release the underlying socket if the consumer breaks early.\n try {\n await reader.cancel();\n } catch {\n // ignore\n }\n }\n },\n };\n}\n","import type { CallOptions, Transport } from \"./transport.js\";\nimport type {\n CreateRequest,\n EnvironmentInfo,\n Event,\n ExecRequest,\n ExecResult,\n ForkOptions,\n} from \"./types.js\";\nimport { FuseError } from \"./errors.js\";\nimport { requireArg } from \"./validate.js\";\nimport { streamEvents } from \"./events.js\";\n\n/** Filters for environments.list. */\nexport interface ListEnvironmentsOptions {\n taskId?: string;\n state?: string;\n hostId?: string;\n}\n\ninterface EnvironmentList {\n environments: EnvironmentInfo[];\n}\n\n/** EnvironmentsService manages microVM lifecycle. */\nexport class EnvironmentsService {\n constructor(private readonly t: Transport) {}\n\n /** List tracked environments, optionally filtered. */\n async list(\n options: ListEnvironmentsOptions = {},\n opts: CallOptions = {},\n ): Promise<EnvironmentInfo[]> {\n const out = await this.t.json<EnvironmentList>(\"GET\", \"/v1/environments\", {\n query: { task_id: options.taskId, state: options.state, host_id: options.hostId },\n signal: opts.signal,\n });\n return out.environments ?? [];\n }\n\n /** Fetch a single environment by VM id. */\n async get(vmId: string, opts: CallOptions = {}): Promise<EnvironmentInfo> {\n requireArg(vmId, \"vm id\");\n return this.t.json<EnvironmentInfo>(\n \"GET\",\n `/v1/environments/${encodeURIComponent(vmId)}`,\n { signal: opts.signal },\n );\n }\n\n /** Provision a new environment. Blocks until running or creation fails. */\n async create(body: CreateRequest, opts: CallOptions = {}): Promise<EnvironmentInfo> {\n return this.t.json<EnvironmentInfo>(\"POST\", \"/v1/environments\", {\n body,\n signal: opts.signal,\n });\n }\n\n /** Fork an environment into a new one; returns the new environment. */\n async fork(\n vmId: string,\n body: ForkOptions = {},\n opts: CallOptions = {},\n ): Promise<EnvironmentInfo> {\n requireArg(vmId, \"vm id\");\n return this.t.json<EnvironmentInfo>(\n \"POST\",\n `/v1/environments/${encodeURIComponent(vmId)}`,\n { query: { action: \"fork\" }, body, signal: opts.signal },\n );\n }\n\n /**\n * Run a command inside a running environment's guest and return its exit code\n * with stdout and stderr kept separate.\n *\n * A non-zero exit_code is resolved, not thrown: the command ran and failed.\n * A thrown error means the command could not be run at all.\n *\n * Exec requires the master token.\n *\n * @example\n * const out = await client.environments.exec(id, { cmd: [\"ls\", \"-l\"] });\n * if (out.exit_code !== 0) console.error(out.stderr);\n */\n async exec(\n vmId: string,\n body: ExecRequest,\n opts: CallOptions = {},\n ): Promise<ExecResult> {\n requireArg(vmId, \"vm id\");\n const hasCmd = (body.cmd?.length ?? 0) > 0;\n const hasShell = (body.shell ?? \"\") !== \"\";\n if (!hasCmd && !hasShell) {\n throw new FuseError(\"one of cmd or shell is required\");\n }\n if (hasCmd && hasShell) {\n throw new FuseError(\"cmd and shell are mutually exclusive\");\n }\n return this.t.json<ExecResult>(\n \"POST\",\n `/v1/environments/${encodeURIComponent(vmId)}`,\n { query: { action: \"exec\" }, body, signal: opts.signal },\n );\n }\n\n /** Gracefully drain an environment; returns the updated environment. */\n async drain(vmId: string, opts: CallOptions = {}): Promise<EnvironmentInfo> {\n requireArg(vmId, \"vm id\");\n return this.t.json<EnvironmentInfo>(\n \"POST\",\n `/v1/environments/${encodeURIComponent(vmId)}`,\n { query: { action: \"drain\" }, signal: opts.signal },\n );\n }\n\n /** Rotate the per-VM credentials and push them to the guest. */\n async rotateToken(vmId: string, opts: CallOptions = {}): Promise<void> {\n requireArg(vmId, \"vm id\");\n await this.t.noContent(\"POST\", `/v1/environments/${encodeURIComponent(vmId)}`, {\n query: { action: \"rotate-token\" },\n signal: opts.signal,\n });\n }\n\n /** Forcefully destroy an environment. Idempotent. */\n async destroy(vmId: string, opts: CallOptions = {}): Promise<void> {\n requireArg(vmId, \"vm id\");\n await this.t.noContent(\"DELETE\", `/v1/environments/${encodeURIComponent(vmId)}`, {\n signal: opts.signal,\n });\n }\n\n /**\n * Open the SSE event stream for an environment. The returned promise rejects\n * with a FuseApiError on a connect-time failure (e.g. not_found); on success\n * it resolves to an AsyncIterable that yields each Event and ends after a\n * terminal-state event. Pass `opts.signal` to cancel; there is no built-in\n * timeout on the stream.\n *\n * @example\n * for await (const ev of await client.environments.events(id)) {\n * console.log(ev.state);\n * }\n */\n async events(vmId: string, opts: CallOptions = {}): Promise<AsyncIterable<Event>> {\n requireArg(vmId, \"vm id\");\n return streamEvents(this.t, vmId, opts.signal);\n }\n}\n","import type { CallOptions, Transport } from \"./transport.js\";\nimport type { Snapshot, SnapshotRequest } from \"./types.js\";\nimport { requireArg } from \"./validate.js\";\n\n/** Filters for snapshots.list. */\nexport interface ListSnapshotsOptions {\n vmId?: string;\n taskId?: string;\n tenantId?: string;\n state?: string;\n}\n\ninterface SnapshotList {\n snapshots: Snapshot[];\n}\n\n/** SnapshotsService manages microVM snapshots. */\nexport class SnapshotsService {\n constructor(private readonly t: Transport) {}\n\n /** Create a snapshot of a running environment. */\n async create(\n vmId: string,\n body: SnapshotRequest = {},\n opts: CallOptions = {},\n ): Promise<Snapshot> {\n requireArg(vmId, \"vm id\");\n return this.t.json<Snapshot>(\n \"POST\",\n `/v1/environments/${encodeURIComponent(vmId)}/snapshots`,\n { body, signal: opts.signal },\n );\n }\n\n /** List snapshots, optionally filtered. */\n async list(\n options: ListSnapshotsOptions = {},\n opts: CallOptions = {},\n ): Promise<Snapshot[]> {\n const out = await this.t.json<SnapshotList>(\"GET\", \"/v1/snapshots\", {\n query: {\n vm_id: options.vmId,\n task_id: options.taskId,\n tenant_id: options.tenantId,\n state: options.state,\n },\n signal: opts.signal,\n });\n return out.snapshots ?? [];\n }\n\n /** Fetch a single snapshot by id. */\n async get(snapshotId: string, opts: CallOptions = {}): Promise<Snapshot> {\n requireArg(snapshotId, \"snapshot id\");\n return this.t.json<Snapshot>(\n \"GET\",\n `/v1/snapshots/${encodeURIComponent(snapshotId)}`,\n { signal: opts.signal },\n );\n }\n\n /** Delete a snapshot. Idempotent; the snapshot must be a leaf. */\n async delete(snapshotId: string, opts: CallOptions = {}): Promise<void> {\n requireArg(snapshotId, \"snapshot id\");\n await this.t.noContent(\"DELETE\", `/v1/snapshots/${encodeURIComponent(snapshotId)}`, {\n signal: opts.signal,\n });\n }\n\n /** Restore an environment from a snapshot. */\n async restore(snapshotId: string, opts: CallOptions = {}): Promise<void> {\n requireArg(snapshotId, \"snapshot id\");\n await this.t.noContent(\"POST\", `/v1/snapshots/${encodeURIComponent(snapshotId)}`, {\n query: { action: \"restore\" },\n signal: opts.signal,\n });\n }\n}\n","import type { CallOptions, Transport } from \"./transport.js\";\nimport type { Host, RegisterHostRequest } from \"./types.js\";\nimport { requireArg } from \"./validate.js\";\n\ninterface HostList {\n hosts: Host[];\n}\n\n/** HostsService manages registered Firecracker hosts. */\nexport class HostsService {\n constructor(private readonly t: Transport) {}\n\n /** Register (or re-register) a host. Idempotent on id. */\n async register(body: RegisterHostRequest, opts: CallOptions = {}): Promise<Host> {\n return this.t.json<Host>(\"POST\", \"/v1/hosts\", { body, signal: opts.signal });\n }\n\n /** List registered hosts. */\n async list(opts: CallOptions = {}): Promise<Host[]> {\n const out = await this.t.json<HostList>(\"GET\", \"/v1/hosts\", { signal: opts.signal });\n return out.hosts ?? [];\n }\n\n /** Fetch a single host by id. */\n async get(hostId: string, opts: CallOptions = {}): Promise<Host> {\n requireArg(hostId, \"host id\");\n return this.t.json<Host>(\"GET\", `/v1/hosts/${encodeURIComponent(hostId)}`, {\n signal: opts.signal,\n });\n }\n\n /** Mark a host unschedulable; existing VMs keep running. */\n async cordon(hostId: string, opts: CallOptions = {}): Promise<void> {\n await this.action(hostId, \"cordon\", opts);\n }\n\n /** Return a cordoned host to active scheduling. */\n async uncordon(hostId: string, opts: CallOptions = {}): Promise<void> {\n await this.action(hostId, \"uncordon\", opts);\n }\n\n /** Remove a host. The host must have no running VMs. */\n async deregister(hostId: string, opts: CallOptions = {}): Promise<void> {\n requireArg(hostId, \"host id\");\n await this.t.noContent(\"DELETE\", `/v1/hosts/${encodeURIComponent(hostId)}`, {\n signal: opts.signal,\n });\n }\n\n private async action(hostId: string, action: string, opts: CallOptions): Promise<void> {\n requireArg(hostId, \"host id\");\n await this.t.noContent(\"POST\", `/v1/hosts/${encodeURIComponent(hostId)}`, {\n query: { action },\n signal: opts.signal,\n });\n }\n}\n","import type { CallOptions, Transport } from \"./transport.js\";\nimport type { APIKey, CreatedAPIKey } from \"./types.js\";\nimport { requireArg } from \"./validate.js\";\n\ninterface APIKeyList {\n api_keys: APIKey[];\n}\n\n/**\n * ApiKeysService manages revocable API keys. These endpoints require the\n * master token; the server enforces this.\n */\nexport class ApiKeysService {\n constructor(private readonly t: Transport) {}\n\n /**\n * Issue a new API key. The raw secret is returned once in `key` and is\n * unrecoverable afterward.\n */\n async create(label?: string, opts: CallOptions = {}): Promise<CreatedAPIKey> {\n return this.t.json<CreatedAPIKey>(\"POST\", \"/v1/api-keys\", {\n body: label ? { label } : {},\n signal: opts.signal,\n });\n }\n\n /** List API key metadata. */\n async list(opts: CallOptions = {}): Promise<APIKey[]> {\n const out = await this.t.json<APIKeyList>(\"GET\", \"/v1/api-keys\", {\n signal: opts.signal,\n });\n return out.api_keys ?? [];\n }\n\n /** Revoke the API key with the given id. */\n async revoke(id: string, opts: CallOptions = {}): Promise<void> {\n requireArg(id, \"id\");\n await this.t.noContent(\"DELETE\", `/v1/api-keys/${encodeURIComponent(id)}`, {\n signal: opts.signal,\n });\n }\n}\n","// generated by scripts/gen-version.mjs. do not edit.\nexport const VERSION = \"0.4.0\";\n","import { Transport, type FetchLike } from \"./transport.js\";\nimport { EnvironmentsService } from \"./environments.js\";\nimport { SnapshotsService } from \"./snapshots.js\";\nimport { HostsService } from \"./hosts.js\";\nimport { ApiKeysService } from \"./apiKeys.js\";\nimport { VERSION } from \"./version.js\";\n\n/** Options for constructing a FuseClient. */\nexport interface FuseClientOptions {\n /** Base URL of the Fuse control plane, e.g. \"https://fuse.example.com\". Required. */\n baseUrl: string;\n /** Bearer token (master token or an API key). Omit for unauthenticated endpoints. */\n token?: string;\n /** Custom fetch implementation. Defaults to the global fetch (Node 18+). */\n fetch?: FetchLike;\n /** User-Agent header. Defaults to \"fuse-ts/<version>\". Ignored by browsers. */\n userAgent?: string;\n /** Generator for the X-Request-ID header, called once per request. Empty results are omitted. */\n requestId?: () => string;\n /** Default per-request timeout in milliseconds. Does NOT apply to events() streams. */\n timeoutMs?: number;\n /** Extra default headers merged into every request. */\n headers?: Record<string, string>;\n}\n\n/**\n * FuseClient is the entry point for the Fuse API. It groups the resource\n * services that share a single transport.\n *\n * @example\n * const client = new FuseClient({ baseUrl: \"https://fuse.example.com\", token });\n * const env = await client.environments.create({ task_id: \"task-1\" });\n */\nexport class FuseClient {\n readonly environments: EnvironmentsService;\n readonly snapshots: SnapshotsService;\n readonly hosts: HostsService;\n readonly apiKeys: ApiKeysService;\n\n constructor(options: FuseClientOptions) {\n const transport = new Transport({\n baseUrl: options.baseUrl,\n token: options.token,\n fetch: options.fetch,\n userAgent: options.userAgent ?? `fuse-ts/${VERSION}`,\n requestId: options.requestId,\n timeoutMs: options.timeoutMs,\n headers: options.headers,\n });\n this.environments = new EnvironmentsService(transport);\n this.snapshots = new SnapshotsService(transport);\n this.hosts = new HostsService(transport);\n this.apiKeys = new ApiKeysService(transport);\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@folsom/fuse",
3
- "version": "0.0.1",
3
+ "version": "0.4.0",
4
4
  "description": "TypeScript SDK for the Fuse microVM control plane",
5
5
  "license": "MIT",
6
6
  "author": "andrewn6",