@machine0/sdk 0.1.1 → 0.2.1

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 CHANGED
@@ -58,6 +58,7 @@ Notes:
58
58
  - Lifecycle mutations (`start`, `stop`, `reboot`, `suspend`, `destroy`) are asynchronous on the server — they return `{success: true}` immediately and the machine transitions through states (`STARTING`, `STOPPING`, …). Poll `get()` to observe progress.
59
59
  - `machines.create` responds before the image join exists, so the created machine lacks `image`/`distribution` — call `get()` if you need them right away.
60
60
  - `sshKeys.create({type: "MANAGED", name})` returns the plaintext `privateKey` — store it. (Managed keys are retrievable later through the CLI's `machine0 keys get <name> --download`; this SDK deliberately never requests the private key after creation.)
61
+ - `get()`, `getByName()` and `update()` return the machine's creation-time environment variables as `env` (`{}` when it has none, `null` if they could not be read) — with their values, so don't log whole responses. `list()` never includes them.
61
62
  - All date fields are ISO-8601 strings.
62
63
 
63
64
  ## Options
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ActionResult, Image, ImageDetail, Machine, MachineCreated, MachineCreateInput, MachineDetail, MachineMetrics, MachineMetricsRange, MachineUpdateInput, SshKey, SshKeyCreated, SshKeyCreatedManaged, SshKeyCreateInput, SshKeyWithFile } from "./types.js";
1
+ import type { ActionResult, ImageDetail, ImageListItem, Machine, MachineCreated, MachineCreateInput, MachineDetail, MachineMetrics, MachineMetricsRange, MachineUpdateInput, SshKey, SshKeyCreated, SshKeyCreatedManaged, SshKeyCreateInput, SshKeyWithFile } from "./types.js";
2
2
  export interface Machine0ClientOptions {
3
3
  /** machine0 API key (dashboard → Account → API Tokens, https://app.machine0.io/account/tokens). Sent as the `x-api-key` header. */
4
4
  apiKey: string;
@@ -51,7 +51,7 @@ export declare function createClient(options: Machine0ClientOptions): {
51
51
  }) => Promise<MachineMetrics>;
52
52
  };
53
53
  images: {
54
- list: () => Promise<Image[]>;
54
+ list: () => Promise<ImageListItem[]>;
55
55
  get: (input: {
56
56
  id: string;
57
57
  }) => Promise<ImageDetail>;
package/dist/types.d.ts CHANGED
@@ -9,12 +9,21 @@
9
9
  export type Open<T extends string> = T | (string & {});
10
10
  export type MachineStatus = "DESTROYED" | "CREATING" | "RUNNING" | "STARTING" | "STOPPING" | "STOPPED" | "RESTARTING" | "ERRORED" | "SUSPENDING" | "SUSPENDED" | "UNAVAILABLE" | "ORDERED";
11
11
  export type MachineSize = "small" | "medium" | "large" | "xl" | "xxl" | "large-nvme" | "xl-nvme" | "xxl-nvme" | "xl-premium" | "xxl-premium" | "xxxl" | "4xl" | "5xl" | "6xl" | "gpu-4000ada-1" | "gpu-l40s-1" | "gpu-6000ada-1" | "gpu-mi300x-1" | "gpu-h100-1" | "gpu-h200-1" | "gpu-mi300x-8" | "gpu-h100-8" | "gpu-h200-8";
12
- export type MachineRegion = "us-east" | "us-west" | "uk" | "eu" | "asia";
12
+ /** Datacenter slugs (region IS the datacenter since the region flip). */
13
+ export type MachineRegion = "nyc3" | "sfo3" | "lon1" | "ams3" | "sgp1" | "tor1" | "nyc2" | "atl1" | "fra1";
14
+ /**
15
+ * Legacy region aliases still accepted on input, normalized server-side to
16
+ * their historical primary datacenter (us/us-east→nyc3, us-west→sfo3,
17
+ * uk→lon1, eu→ams3, asia→sgp1).
18
+ */
19
+ export type LegacyMachineRegion = "us" | "us-east" | "us-west" | "uk" | "eu" | "asia";
13
20
  export type Distribution = "ubuntu" | "nixos";
14
21
  export type ImageStatus = "DESTROYED" | "CREATING" | "READY" | "TRANSFERRING" | "ERRORED";
15
22
  export type ImageType = "USER" | "SYSTEM";
16
23
  export type SshKeyType = "MANAGED" | "PUBLIC";
17
24
  export type MachineMetricsRange = "1h" | "24h" | "7d";
25
+ /** Idle-detection action: what the server does after sustained inactivity. */
26
+ export type MachineOnIdleAction = "suspend" | "destroy" | "none";
18
27
  /** Machine as returned by `machines.list`. */
19
28
  export interface Machine {
20
29
  id: string;
@@ -35,6 +44,10 @@ export interface Machine {
35
44
  totalCost: number | null;
36
45
  pricePerHour: number | null;
37
46
  metricsEnabled: boolean;
47
+ /** Idle-detection action; `"none"` = disabled. */
48
+ onIdle: Open<MachineOnIdleAction>;
49
+ /** Sustained-inactivity window (minutes) before `onIdle` fires. */
50
+ idleTimeoutMinutes: number;
38
51
  /**
39
52
  * Standing-order deadline (`machine0 order`): set while the machine is an
40
53
  * ORDERED (or expired) order, cleared once the order fills. Null for
@@ -48,7 +61,17 @@ export interface Machine {
48
61
  * `distribution` are absent — fetch the machine (`machines.get`) if you need
49
62
  * them immediately after creation.
50
63
  */
51
- export type MachineCreated = Omit<Machine, "image" | "distribution">;
64
+ export type MachineCreated = Omit<Machine, "image" | "distribution"> & {
65
+ /**
66
+ * Whether a supplied `env` map was applied: `true` when `env` was passed and
67
+ * honored, `false` when no `env` was passed. Always present on a server that
68
+ * supports env overrides. A server that predates env support OMITS this field
69
+ * entirely (and silently creates the VM without the variables), so after
70
+ * passing `env` you can distinguish an applied override from an old server
71
+ * with `"envApplied" in created`.
72
+ */
73
+ envApplied: boolean;
74
+ };
52
75
  /** Machine as returned by `machines.get`, `machines.getByName` and `machines.update`. */
53
76
  export interface MachineDetail {
54
77
  id: string;
@@ -69,6 +92,10 @@ export interface MachineDetail {
69
92
  defaultSSHUsername: string | null;
70
93
  sshClientInitialCommand: string | null;
71
94
  metricsEnabled: boolean;
95
+ /** See {@link Machine.onIdle}. */
96
+ onIdle: Open<MachineOnIdleAction>;
97
+ /** See {@link Machine.idleTimeoutMinutes}. */
98
+ idleTimeoutMinutes: number;
72
99
  distribution: Open<Distribution>;
73
100
  /** SSH key the machine was created with (null if since destroyed). */
74
101
  key: {
@@ -85,6 +112,14 @@ export interface MachineDetail {
85
112
  statusExplanation: string | null;
86
113
  /** See {@link Machine.orderExpiresAt}. */
87
114
  orderExpiresAt: string | null;
115
+ /**
116
+ * The environment variables the machine was created with
117
+ * ({@link MachineCreateInput.env}) — its own variables only, not those it
118
+ * inherits from a profile. `{}` when it was created without any; `null` when
119
+ * they are stored but could not be read. Treat the values as secrets: don't
120
+ * log a whole `MachineDetail`.
121
+ */
122
+ env: Record<string, string> | null;
88
123
  }
89
124
  export interface DiskMount {
90
125
  diskName: string;
@@ -93,14 +128,39 @@ export interface DiskMount {
93
128
  export interface MachineCreateInput {
94
129
  name: string;
95
130
  size: MachineSize;
96
- /** `"us"` is a legacy alias for `"us-east"` accepted by the API. */
97
- region: MachineRegion | "us";
131
+ /** Legacy aliases ("us-east", "eu", …) are accepted and normalized. */
132
+ region: MachineRegion | LegacyMachineRegion;
98
133
  imageName: string;
99
134
  sshKeyId?: string;
100
135
  imageVersion?: number;
101
136
  profileName?: string;
102
137
  mounts?: DiskMount[];
103
138
  metricsEnabled?: boolean;
139
+ /**
140
+ * Suspend or destroy the machine after sustained inactivity. Enabling
141
+ * (`"suspend"`/`"destroy"`) force-enables `metricsEnabled` and requires a
142
+ * managed SSH key.
143
+ *
144
+ * Requires a server that supports idle detection: an older server silently
145
+ * ignores this field (the machine is created WITHOUT the policy) and omits
146
+ * `onIdle`/`idleTimeoutMinutes` from responses. Published SDK versions
147
+ * always trail the production server, so this only matters against
148
+ * self-hosted/stale deployments — check `machine.onIdle !== undefined`
149
+ * after creating if you depend on the policy.
150
+ */
151
+ onIdle?: MachineOnIdleAction;
152
+ /** Minutes of inactivity before `onIdle` fires (10-2880; default 30). */
153
+ idleTimeoutMinutes?: number;
154
+ /**
155
+ * Environment variables set on the VM at creation, keyed by name. They
156
+ * override the chosen profile's variables on name collision and are applied
157
+ * on every provision/resume. Immutable after creation.
158
+ *
159
+ * Requires a server that supports machine env overrides: an older server
160
+ * silently ignores this field (the VM is created WITHOUT the variables, and
161
+ * with a `profileName` collision the profile's value is used instead).
162
+ */
163
+ env?: Record<string, string>;
104
164
  }
105
165
  export interface MachineUpdateInput {
106
166
  id: string;
@@ -108,6 +168,10 @@ export interface MachineUpdateInput {
108
168
  defaultSSHUsername?: string;
109
169
  sshClientInitialCommand?: string;
110
170
  metricsEnabled?: boolean;
171
+ /** See {@link MachineCreateInput.onIdle}. */
172
+ onIdle?: MachineOnIdleAction;
173
+ /** See {@link MachineCreateInput.idleTimeoutMinutes}. */
174
+ idleTimeoutMinutes?: number;
111
175
  }
112
176
  /** Returned by machine lifecycle mutations (start/stop/reboot/suspend/destroy). */
113
177
  export interface ActionResult {
@@ -144,12 +208,33 @@ export interface Image {
144
208
  minDiskGb: number | null;
145
209
  regions: string[];
146
210
  gpuOnly: boolean;
211
+ /**
212
+ * Branch-tracking source identity (github `--flake` builds). All null on
213
+ * non-tracked images. When set, pushes to `gitRepo`@`gitBranch` rebuild
214
+ * the image and auto-promote the new version.
215
+ */
216
+ gitRepo: string | null;
217
+ gitBranch: string | null;
218
+ flakeDir: string | null;
219
+ nixProfile: string | null;
147
220
  createdAt: string;
148
221
  updatedAt: string;
149
222
  ageMinutes: number;
150
223
  totalCost: number | null;
151
224
  pricePerHour: number | null;
152
225
  }
226
+ /**
227
+ * Image as returned by `images.list` — adds the latest failed-build error of
228
+ * the image's current draft (owner/admin-visible only; null otherwise or
229
+ * when the latest build succeeded).
230
+ */
231
+ export interface ImageListItem extends Image {
232
+ latestVersionError: {
233
+ version: number;
234
+ message: string;
235
+ at: string | null;
236
+ } | null;
237
+ }
153
238
  /** Image as returned by `images.get`. */
154
239
  export interface ImageDetail extends Image {
155
240
  versionSnapshotStorageCost: number | null;
@@ -189,10 +274,11 @@ export interface SshKeyCreated extends SshKeyWithFile {
189
274
  export interface SshKeyCreatedManaged extends SshKeyWithFile {
190
275
  privateKey: string;
191
276
  }
192
- export declare const MACHINE_KEYS: readonly ["id", "name", "url", "status", "ip", "size", "region", "provider", "createdAt", "firstStartedAt", "destroyedAt", "image", "distribution", "ageMinutes", "totalCost", "pricePerHour", "metricsEnabled", "orderExpiresAt"];
193
- export declare const MACHINE_CREATED_KEYS: readonly ["id", "name", "url", "status", "ip", "size", "region", "provider", "createdAt", "firstStartedAt", "destroyedAt", "ageMinutes", "totalCost", "pricePerHour", "metricsEnabled", "orderExpiresAt"];
194
- export declare const MACHINE_DETAIL_KEYS: readonly ["id", "name", "url", "status", "ip", "size", "vcpu", "ram", "disk", "region", "provider", "createdAt", "firstStartedAt", "image", "imageVersion", "defaultSSHUsername", "sshClientInitialCommand", "metricsEnabled", "distribution", "key", "ageMinutes", "totalCost", "pricePerHour", "mountPaths", "statusExplanation", "orderExpiresAt"];
195
- export declare const IMAGE_KEYS: readonly ["id", "name", "description", "distribution", "type", "status", "provider", "sizeGb", "minDiskGb", "regions", "gpuOnly", "createdAt", "updatedAt", "ageMinutes", "totalCost", "pricePerHour"];
196
- export declare const IMAGE_DETAIL_KEYS: readonly ["id", "name", "description", "distribution", "type", "status", "provider", "sizeGb", "minDiskGb", "regions", "gpuOnly", "createdAt", "updatedAt", "ageMinutes", "totalCost", "pricePerHour", "versionSnapshotStorageCost"];
277
+ export declare const MACHINE_KEYS: readonly ["id", "name", "url", "status", "ip", "size", "region", "provider", "createdAt", "firstStartedAt", "destroyedAt", "image", "distribution", "ageMinutes", "totalCost", "pricePerHour", "metricsEnabled", "onIdle", "idleTimeoutMinutes", "orderExpiresAt"];
278
+ export declare const MACHINE_CREATED_KEYS: readonly ["id", "name", "url", "status", "ip", "size", "region", "provider", "createdAt", "firstStartedAt", "destroyedAt", "ageMinutes", "totalCost", "pricePerHour", "metricsEnabled", "onIdle", "idleTimeoutMinutes", "orderExpiresAt", "envApplied"];
279
+ export declare const MACHINE_DETAIL_KEYS: readonly ["id", "name", "url", "status", "ip", "size", "vcpu", "ram", "disk", "region", "provider", "createdAt", "firstStartedAt", "image", "imageVersion", "defaultSSHUsername", "sshClientInitialCommand", "metricsEnabled", "onIdle", "idleTimeoutMinutes", "distribution", "key", "ageMinutes", "totalCost", "pricePerHour", "mountPaths", "statusExplanation", "orderExpiresAt", "env"];
280
+ export declare const IMAGE_KEYS: readonly ["id", "name", "description", "distribution", "type", "status", "provider", "sizeGb", "minDiskGb", "regions", "gpuOnly", "gitRepo", "gitBranch", "flakeDir", "nixProfile", "createdAt", "updatedAt", "ageMinutes", "totalCost", "pricePerHour"];
281
+ export declare const IMAGE_LIST_KEYS: readonly ["id", "name", "description", "distribution", "type", "status", "provider", "sizeGb", "minDiskGb", "regions", "gpuOnly", "gitRepo", "gitBranch", "flakeDir", "nixProfile", "createdAt", "updatedAt", "ageMinutes", "totalCost", "pricePerHour", "latestVersionError"];
282
+ export declare const IMAGE_DETAIL_KEYS: readonly ["id", "name", "description", "distribution", "type", "status", "provider", "sizeGb", "minDiskGb", "regions", "gpuOnly", "gitRepo", "gitBranch", "flakeDir", "nixProfile", "createdAt", "updatedAt", "ageMinutes", "totalCost", "pricePerHour", "versionSnapshotStorageCost"];
197
283
  export declare const SSH_KEY_KEYS: readonly ["id", "name", "type", "publicKey", "isDefault", "createdAt"];
198
284
  export declare const SSH_KEY_WITH_FILE_KEYS: readonly ["id", "name", "type", "publicKey", "isDefault", "createdAt", "fileName"];
package/dist/types.js CHANGED
@@ -35,6 +35,8 @@ export const MACHINE_KEYS = [
35
35
  "totalCost",
36
36
  "pricePerHour",
37
37
  "metricsEnabled",
38
+ "onIdle",
39
+ "idleTimeoutMinutes",
38
40
  "orderExpiresAt",
39
41
  ];
40
42
  export const MACHINE_CREATED_KEYS = [
@@ -53,7 +55,10 @@ export const MACHINE_CREATED_KEYS = [
53
55
  "totalCost",
54
56
  "pricePerHour",
55
57
  "metricsEnabled",
58
+ "onIdle",
59
+ "idleTimeoutMinutes",
56
60
  "orderExpiresAt",
61
+ "envApplied",
57
62
  ];
58
63
  export const MACHINE_DETAIL_KEYS = [
59
64
  "id",
@@ -74,6 +79,8 @@ export const MACHINE_DETAIL_KEYS = [
74
79
  "defaultSSHUsername",
75
80
  "sshClientInitialCommand",
76
81
  "metricsEnabled",
82
+ "onIdle",
83
+ "idleTimeoutMinutes",
77
84
  "distribution",
78
85
  "key",
79
86
  "ageMinutes",
@@ -82,7 +89,10 @@ export const MACHINE_DETAIL_KEYS = [
82
89
  "mountPaths",
83
90
  "statusExplanation",
84
91
  "orderExpiresAt",
92
+ "env",
85
93
  ];
94
+ // The shared Image keys — valid against BOTH images.list rows and images.get
95
+ // (kept stable for existing consumers indexing either shape).
86
96
  export const IMAGE_KEYS = [
87
97
  "id",
88
98
  "name",
@@ -95,12 +105,21 @@ export const IMAGE_KEYS = [
95
105
  "minDiskGb",
96
106
  "regions",
97
107
  "gpuOnly",
108
+ "gitRepo",
109
+ "gitBranch",
110
+ "flakeDir",
111
+ "nixProfile",
98
112
  "createdAt",
99
113
  "updatedAt",
100
114
  "ageMinutes",
101
115
  "totalCost",
102
116
  "pricePerHour",
103
117
  ];
118
+ // List rows additionally carry the computed latestVersionError; get does not.
119
+ export const IMAGE_LIST_KEYS = [
120
+ ...IMAGE_KEYS,
121
+ "latestVersionError",
122
+ ];
104
123
  export const IMAGE_DETAIL_KEYS = [
105
124
  ...IMAGE_KEYS,
106
125
  "versionSnapshotStorageCost",
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "0.1.1";
1
+ export declare const SDK_VERSION = "0.2.1";
package/dist/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  // Must match the "version" field in package.json — version.test.ts enforces
2
2
  // the sync, and the deploy-sdk workflow compares this constant (imported from
3
3
  // the built dist under plain Node) against package.json before publishing.
4
- export const SDK_VERSION = "0.1.1";
4
+ export const SDK_VERSION = "0.2.1";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@machine0/sdk",
3
- "version": "0.1.1",
3
+ "version": "0.2.1",
4
4
  "description": "Typed Node.js/TypeScript SDK for the machine0 API. Zero dependencies, fetch-based.",
5
5
  "homepage": "https://machine0.io",
6
6
  "author": "Barnaby Malet <barnaby@machine0.io>",