disk 0.7.1 → 0.8.8

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.js ADDED
@@ -0,0 +1,372 @@
1
+ // src/client.ts
2
+ import createClient from "openapi-fetch";
3
+
4
+ // src/errors.ts
5
+ var ArchilApiError = class extends Error {
6
+ status;
7
+ code;
8
+ constructor(message, status, code) {
9
+ super(message);
10
+ this.name = "ArchilApiError";
11
+ this.status = status;
12
+ this.code = code;
13
+ }
14
+ };
15
+
16
+ // src/regions.ts
17
+ var REGION_URLS = {
18
+ "aws-us-east-1": "https://control.green.us-east-1.aws.prod.archil.com",
19
+ "aws-us-west-2": "https://control.green.us-west-2.aws.prod.archil.com",
20
+ "aws-eu-west-1": "https://control.green.eu-west-1.aws.prod.archil.com",
21
+ "gcp-us-central1": "https://control.blue.us-central1.gcp.prod.archil.com"
22
+ };
23
+ function resolveBaseUrl(region) {
24
+ const url = REGION_URLS[region];
25
+ if (!url) {
26
+ throw new Error(
27
+ `Unknown region "${region}". Valid regions: ${Object.keys(REGION_URLS).join(", ")}`
28
+ );
29
+ }
30
+ return url;
31
+ }
32
+
33
+ // src/client.ts
34
+ function createApiClient(opts) {
35
+ const baseUrl = opts.baseUrl ?? resolveBaseUrl(opts.region);
36
+ return createClient({
37
+ baseUrl,
38
+ headers: {
39
+ Authorization: `key-${opts.apiKey.replace(/^key-/, "")}`
40
+ }
41
+ });
42
+ }
43
+ async function unwrap(promise) {
44
+ const { data: body, error, response } = await promise;
45
+ if (error || !body) {
46
+ const errBody = error;
47
+ throw new ArchilApiError(
48
+ errBody?.error ?? `API request failed with status ${response.status}`,
49
+ response.status
50
+ );
51
+ }
52
+ if (!body.success) {
53
+ throw new ArchilApiError(
54
+ body.error ?? "Unknown API error",
55
+ response.status
56
+ );
57
+ }
58
+ return body.data;
59
+ }
60
+ async function unwrapEmpty(promise) {
61
+ const { data: body, error, response } = await promise;
62
+ if (error || !body) {
63
+ const errBody = error;
64
+ throw new ArchilApiError(
65
+ errBody?.error ?? `API request failed with status ${response.status}`,
66
+ response.status
67
+ );
68
+ }
69
+ if (!body.success) {
70
+ throw new ArchilApiError(
71
+ body.error ?? "Unknown API error",
72
+ response.status
73
+ );
74
+ }
75
+ }
76
+
77
+ // src/disk.ts
78
+ import { createRequire } from "module";
79
+ import { pathToFileURL } from "url";
80
+ var Disk = class {
81
+ id;
82
+ name;
83
+ organization;
84
+ status;
85
+ provider;
86
+ region;
87
+ createdAt;
88
+ fsHandlerStatus;
89
+ lastAccessed;
90
+ dataSize;
91
+ monthlyUsage;
92
+ mounts;
93
+ metrics;
94
+ connectedClients;
95
+ authorizedUsers;
96
+ /** @internal */
97
+ _client;
98
+ /** @internal */
99
+ _archilRegion;
100
+ /** @internal */
101
+ constructor(data, client, archilRegion) {
102
+ this.id = data.id;
103
+ this.name = data.name;
104
+ this.organization = data.organization;
105
+ this.status = data.status;
106
+ this.provider = data.provider;
107
+ this.region = data.region;
108
+ this.createdAt = data.createdAt;
109
+ this.fsHandlerStatus = data.fsHandlerStatus;
110
+ this.lastAccessed = data.lastAccessed;
111
+ this.dataSize = data.dataSize;
112
+ this.monthlyUsage = data.monthlyUsage;
113
+ this.mounts = data.mounts;
114
+ this.metrics = data.metrics;
115
+ this.connectedClients = data.connectedClients;
116
+ this.authorizedUsers = data.authorizedUsers;
117
+ this._client = client;
118
+ this._archilRegion = archilRegion;
119
+ }
120
+ toJSON() {
121
+ return {
122
+ id: this.id,
123
+ name: this.name,
124
+ organization: this.organization,
125
+ status: this.status,
126
+ provider: this.provider,
127
+ region: this.region,
128
+ createdAt: this.createdAt,
129
+ fsHandlerStatus: this.fsHandlerStatus,
130
+ lastAccessed: this.lastAccessed,
131
+ dataSize: this.dataSize,
132
+ monthlyUsage: this.monthlyUsage,
133
+ mounts: this.mounts,
134
+ metrics: this.metrics,
135
+ connectedClients: this.connectedClients,
136
+ authorizedUsers: this.authorizedUsers
137
+ };
138
+ }
139
+ async addUser(user) {
140
+ return unwrap(
141
+ this._client.POST("/api/disks/{id}/users", {
142
+ params: { path: { id: this.id } },
143
+ body: user
144
+ })
145
+ );
146
+ }
147
+ async removeUser(userType, identifier) {
148
+ await unwrapEmpty(
149
+ this._client.DELETE("/api/disks/{id}/users/{userType}", {
150
+ params: {
151
+ path: { id: this.id, userType },
152
+ query: { identifier }
153
+ }
154
+ })
155
+ );
156
+ }
157
+ async createToken(nickname) {
158
+ const user = await unwrap(
159
+ this._client.POST("/api/disks/{id}/users", {
160
+ params: { path: { id: this.id } },
161
+ body: { type: "token", nickname }
162
+ })
163
+ );
164
+ if (!user.token || !user.identifier) {
165
+ throw new Error("Server did not return a generated token");
166
+ }
167
+ return user;
168
+ }
169
+ async removeTokenUser(identifier) {
170
+ await this.removeUser("token", identifier);
171
+ }
172
+ async delete() {
173
+ await unwrapEmpty(
174
+ this._client.DELETE("/api/disks/{id}", {
175
+ params: { path: { id: this.id } }
176
+ })
177
+ );
178
+ }
179
+ /**
180
+ * Execute a command in a container with this disk mounted.
181
+ * Blocks until the command completes and returns stdout, stderr, and exit code.
182
+ */
183
+ async exec(command) {
184
+ return unwrap(
185
+ this._client.POST("/api/disks/{id}/exec", {
186
+ params: { path: { id: this.id } },
187
+ body: { command }
188
+ })
189
+ );
190
+ }
191
+ /**
192
+ * Connect to this disk's data plane via the native ArchilClient.
193
+ *
194
+ * Requires the native module to be available (platform-specific .node binary).
195
+ */
196
+ async mount(opts) {
197
+ let ArchilClient;
198
+ try {
199
+ const base = typeof import.meta !== "undefined" && import.meta.url ? import.meta.url : pathToFileURL(__filename).href;
200
+ const nativeRequire = createRequire(base);
201
+ const native = nativeRequire("@archildata/native");
202
+ ArchilClient = native.ArchilClient;
203
+ } catch {
204
+ throw new Error(
205
+ "Native client not available. Install @archildata/native (platform-specific binary) or use ArchilClient.connect() directly."
206
+ );
207
+ }
208
+ return ArchilClient.connect({
209
+ region: this._archilRegion,
210
+ diskName: `${this.organization}/${this.name}`,
211
+ authToken: opts?.authToken,
212
+ logLevel: opts?.logLevel,
213
+ serverAddress: opts?.serverAddress,
214
+ insecure: opts?.insecure
215
+ });
216
+ }
217
+ };
218
+
219
+ // src/disks.ts
220
+ var Disks = class {
221
+ /** @internal */
222
+ _client;
223
+ /** @internal */
224
+ _region;
225
+ /** @internal */
226
+ constructor(client, region) {
227
+ this._client = client;
228
+ this._region = region;
229
+ }
230
+ async list(opts) {
231
+ const data = await unwrap(
232
+ this._client.GET("/api/disks", {
233
+ params: { query: { limit: opts?.limit, cursor: opts?.cursor } }
234
+ })
235
+ );
236
+ return data.map(
237
+ (d) => new Disk(d, this._client, this._region)
238
+ );
239
+ }
240
+ async get(id) {
241
+ const data = await unwrap(
242
+ this._client.GET("/api/disks/{id}", {
243
+ params: { path: { id } }
244
+ })
245
+ );
246
+ return new Disk(data, this._client, this._region);
247
+ }
248
+ /**
249
+ * Create a new disk with an auto-generated mount token.
250
+ *
251
+ * Returns the Disk, the one-time token (save it — it cannot be retrieved
252
+ * again), and the token identifier for later management.
253
+ */
254
+ async create(req) {
255
+ const created = await unwrap(
256
+ this._client.POST("/api/disks", { body: req })
257
+ );
258
+ const resp = created;
259
+ if (!resp.diskId) {
260
+ throw new Error("API returned success but no diskId");
261
+ }
262
+ const authorizedUsers = resp.authorizedUsers ?? [];
263
+ const tokenUser = authorizedUsers.find((u) => u.token);
264
+ const disk = await this.get(resp.diskId);
265
+ return {
266
+ disk,
267
+ token: tokenUser?.token ?? null,
268
+ tokenIdentifier: tokenUser?.identifier ?? null,
269
+ authorizedUsers
270
+ };
271
+ }
272
+ };
273
+
274
+ // src/tokens.ts
275
+ var Tokens = class {
276
+ /** @internal */
277
+ _client;
278
+ /** @internal */
279
+ constructor(client) {
280
+ this._client = client;
281
+ }
282
+ async list(opts) {
283
+ const data = await unwrap(
284
+ this._client.GET("/api/tokens", {
285
+ params: { query: { limit: opts?.limit, cursor: opts?.cursor } }
286
+ })
287
+ );
288
+ return data.tokens ?? [];
289
+ }
290
+ async create(req) {
291
+ const data = await unwrap(
292
+ this._client.POST("/api/tokens", { body: req })
293
+ );
294
+ return data;
295
+ }
296
+ async delete(id) {
297
+ await unwrapEmpty(
298
+ this._client.DELETE("/api/tokens/{id}", {
299
+ params: { path: { id } }
300
+ })
301
+ );
302
+ }
303
+ };
304
+
305
+ // src/archil.ts
306
+ var Archil = class {
307
+ disks;
308
+ tokens;
309
+ constructor(opts = {}) {
310
+ const apiKey = opts.apiKey ?? process.env.ARCHIL_API_KEY;
311
+ const region = opts.region ?? process.env.ARCHIL_REGION;
312
+ if (!apiKey) {
313
+ throw new Error("Missing API key: pass apiKey in options or set ARCHIL_API_KEY environment variable");
314
+ }
315
+ if (!region) {
316
+ throw new Error("Missing region: pass region in options or set ARCHIL_REGION environment variable");
317
+ }
318
+ const client = createApiClient({
319
+ apiKey,
320
+ region,
321
+ baseUrl: opts.baseUrl
322
+ });
323
+ this.disks = new Disks(client, region);
324
+ this.tokens = new Tokens(client);
325
+ }
326
+ };
327
+
328
+ // src/index.ts
329
+ var _options;
330
+ var _instance;
331
+ function configure(options) {
332
+ _options = options;
333
+ _instance = void 0;
334
+ }
335
+ function archil() {
336
+ if (!_instance) {
337
+ _instance = new Archil(_options);
338
+ }
339
+ return _instance;
340
+ }
341
+ function createDisk(req) {
342
+ return archil().disks.create(req);
343
+ }
344
+ function listDisks(opts) {
345
+ return archil().disks.list(opts);
346
+ }
347
+ function getDisk(id) {
348
+ return archil().disks.get(id);
349
+ }
350
+ function listApiKeys(opts) {
351
+ return archil().tokens.list(opts);
352
+ }
353
+ function createApiKey(req) {
354
+ return archil().tokens.create(req);
355
+ }
356
+ function deleteApiKey(id) {
357
+ return archil().tokens.delete(id);
358
+ }
359
+ export {
360
+ Archil,
361
+ ArchilApiError,
362
+ Disk,
363
+ Disks,
364
+ Tokens,
365
+ configure,
366
+ createApiKey,
367
+ createDisk,
368
+ deleteApiKey,
369
+ getDisk,
370
+ listApiKeys,
371
+ listDisks
372
+ };
package/package.json CHANGED
@@ -1,46 +1,50 @@
1
1
  {
2
2
  "name": "disk",
3
- "version": "0.7.1",
4
- "description": "Handle physical & virtual block devices",
5
- "author": "Jonas Hermsmeier <jhermsmeier@gmail.com> (https://jhermsmeier.de)",
6
- "license": "MIT",
7
- "keywords": [
8
- "disk",
9
- "fs",
10
- "mbr",
11
- "gpt",
12
- "partition",
13
- "filesystem",
14
- "file",
15
- "system",
16
- "blockdevice",
17
- "master boot record",
18
- "guid partition table",
19
- "hdd"
20
- ],
21
- "main": "lib/disk",
22
- "dependencies": {
23
- "debug": "^3.1.0",
24
- "gpt": "^1.0.0",
25
- "mbr": "^1.1.2"
3
+ "version": "0.8.8",
4
+ "description": "Pure-JS client and CLI for Archil disks",
5
+ "type": "module",
6
+ "main": "dist/index.cjs",
7
+ "module": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
26
15
  },
27
- "devDependencies": {
28
- "blockdevice": "^0.6.0",
29
- "mocha": "^5.1.1",
30
- "ramdisk": "^0.3.1"
16
+ "bin": {
17
+ "disk": "./dist/cli.js"
31
18
  },
19
+ "files": [
20
+ "dist",
21
+ "README.md",
22
+ "LICENSE"
23
+ ],
32
24
  "scripts": {
33
- "test": "mocha"
25
+ "generate": "openapi-typescript ../../api/controlplane/openapi.yaml -o src/generated/openapi.d.ts",
26
+ "build": "npm run generate && tsup src/index.ts --format cjs,esm --dts && tsup bin/cli.ts --format esm --outDir dist --no-splitting",
27
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
28
+ "typecheck": "npm run generate && tsc --noEmit"
34
29
  },
35
- "homepage": "https://github.com/jhermsmeier/node-disk",
36
- "repository": {
37
- "type": "git",
38
- "url": "git+https://github.com/jhermsmeier/node-disk.git"
30
+ "dependencies": {
31
+ "commander": "^14.0.3",
32
+ "openapi-fetch": "^0.13.5"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^20.19.33",
36
+ "openapi-typescript": "^7.6.1",
37
+ "tsup": "^8.4.0",
38
+ "typescript": "^5.9.3"
39
39
  },
40
- "bugs": {
41
- "url": "https://github.com/jhermsmeier/node-disk/issues"
40
+ "engines": {
41
+ "node": ">= 18"
42
42
  },
43
- "directories": {
44
- "test": "test"
45
- }
43
+ "keywords": [
44
+ "archil",
45
+ "disk",
46
+ "filesystem",
47
+ "cli"
48
+ ],
49
+ "license": "MIT"
46
50
  }