@archildata/client 0.8.4 → 0.8.7

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
@@ -20,7 +20,7 @@ npm install @archildata/client
20
20
 
21
21
  An Archil "disk" is a filesystem that sits in front of your cloud storage. You create one by telling Archil which bucket to use. This doesn't move or copy your data — Archil reads and writes directly to your bucket.
22
22
 
23
- You also need to authorize a mount token on the disk. This is a separate credential from your API key it's what clients use to connect to the disk's data plane. Pick any string as the principal (it's just an identifier).
23
+ A mount token is automatically generated when you create a disk; it is recommended to save it.
24
24
 
25
25
  ```typescript
26
26
  import { Archil } from '@archildata/client/api';
@@ -30,25 +30,19 @@ const archil = new Archil({
30
30
  region: 'aws-us-east-1',
31
31
  });
32
32
 
33
- const MOUNT_TOKEN = 'my-secret-mount-token';
34
-
35
- const disk = await archil.disks.create({
33
+ const { disk, token } = await archil.disks.create({
36
34
  name: 'my-disk',
37
35
  mounts: [{
38
36
  type: 's3',
39
37
  bucketName: 'my-bucket',
40
38
  accessKeyId: 'AKIA...',
41
39
  secretAccessKey: '...',
42
- }],
43
- authMethods: [{
44
- type: 'token',
45
- principal: MOUNT_TOKEN,
46
- nickname: 'my-mount-token',
47
- tokenSuffix: MOUNT_TOKEN.slice(-4),
40
+ bucketPrefix: 'data/', // optional — only expose a subfolder of the bucket
48
41
  }],
49
42
  });
50
43
 
51
44
  console.log(`Created disk: ${disk.organization}/${disk.name}`);
45
+ console.log(`Mount token: ${token}`); // save this — it won't be shown again
52
46
  ```
53
47
 
54
48
  You only do this once. After that, the disk is available by name whenever you want to connect.
@@ -61,10 +55,10 @@ Install `@archildata/just-bash` to get a shell that runs against your disk:
61
55
  npm install @archildata/just-bash
62
56
  ```
63
57
 
64
- Then connect using the mount token you authorized above:
58
+ Then connect using the mount token from step 3:
65
59
 
66
60
  ```bash
67
- ARCHIL_TOKEN=my-secret-mount-token npx @archildata/just-bash aws-us-east-1 myaccount/my-disk
61
+ ARCHIL_DISK_TOKEN=<your-mount-token> npx @archildata/just-bash aws-us-east-1 myaccount/my-disk
68
62
  ```
69
63
 
70
64
  This drops you into an interactive shell. The files you see are the contents of your S3 bucket:
@@ -94,7 +88,7 @@ import { Bash } from 'just-bash';
94
88
  const client = await ArchilClient.connect({
95
89
  region: 'aws-us-east-1',
96
90
  diskName: 'myaccount/my-disk',
97
- authToken: 'my-secret-mount-token',
91
+ authToken: '<your-mount-token>',
98
92
  });
99
93
 
100
94
  // Create a filesystem adapter and a bash executor
@@ -146,7 +140,7 @@ import { ArchilClient } from '@archildata/client';
146
140
  const client = await ArchilClient.connect({
147
141
  region: 'aws-us-east-1',
148
142
  diskName: 'myaccount/my-disk',
149
- authToken: 'my-secret-mount-token',
143
+ authToken: '<your-mount-token>',
150
144
  });
151
145
  ```
152
146
 
@@ -254,17 +248,13 @@ const disks = await archil.disks.list();
254
248
  // Get a specific disk by ID
255
249
  const disk = await archil.disks.get('dsk-xxx');
256
250
 
257
- // Authorize another mount token on an existing disk
258
- const CI_TOKEN = 'ci-mount-token';
259
- await disk.addUser({
260
- type: 'token',
261
- principal: CI_TOKEN,
262
- nickname: 'ci-token',
263
- tokenSuffix: CI_TOKEN.slice(-4),
264
- });
251
+ // Add an additional mount token to an existing disk
252
+ const { token, identifier } = await disk.createToken('ci-token');
253
+ // save `token` — it's only returned once
254
+ // use `identifier` to manage or remove the token later
265
255
 
266
256
  // Remove access
267
- await disk.removeUser('token', CI_TOKEN);
257
+ await disk.removeTokenUser(identifier);
268
258
 
269
259
  // Delete a disk (this does not delete your bucket data)
270
260
  await disk.delete();
Binary file
@@ -21,8 +21,13 @@ interface paths {
21
21
  put?: never;
22
22
  /**
23
23
  * Create a new disk
24
- * @description Creates a new disk with the specified configuration. The disk will be
25
- * provisioned in the specified region with the given mounts and authentication methods.
24
+ * @description Creates a new disk with the specified configuration. A default token
25
+ * user is automatically generated and returned in the response, so the
26
+ * disk is immediately mountable. The one-time token appears in
27
+ * `authorizedUsers[].token` and cannot be retrieved again.
28
+ *
29
+ * To provide your own users instead, pass the deprecated `authMethods`
30
+ * field or call AddDiskUser after creation.
26
31
  */
27
32
  post: operations["createDisk"];
28
33
  delete?: never;
@@ -170,7 +175,10 @@ interface components {
170
175
  name: string;
171
176
  /** @description Storage mount to attach. Omit for archil-managed storage. */
172
177
  mounts?: components["schemas"]["MountConfig"][];
173
- /** @description Authentication methods for disk access */
178
+ /**
179
+ * @deprecated
180
+ * @description Deprecated. Use AddDiskUser after creation instead. When provided, suppresses the default auto-generated token user.
181
+ */
174
182
  authMethods?: components["schemas"]["DiskUser"][];
175
183
  };
176
184
  MountConfig: components["schemas"]["S3Mount"] | components["schemas"]["GCSMount"] | components["schemas"]["R2Mount"] | components["schemas"]["S3CompatibleMount"] | components["schemas"]["AzureBlobMount"];
@@ -344,9 +352,17 @@ interface components {
344
352
  * @enum {string}
345
353
  */
346
354
  type: "token";
347
- principal: string;
355
+ /**
356
+ * @deprecated
357
+ * @description Deprecated. Client-provided token. If omitted, the server generates a cryptographically secure token and returns it in the response.
358
+ */
359
+ principal?: string;
348
360
  nickname: string;
349
- tokenSuffix: string;
361
+ /**
362
+ * @deprecated
363
+ * @description Deprecated. Last 4 characters of the token. Required when principal is provided; ignored when the server generates the token.
364
+ */
365
+ tokenSuffix?: string;
350
366
  };
351
367
  AwsStsUser: {
352
368
  /**
@@ -441,6 +457,8 @@ interface components {
441
457
  bucketEndpoint?: string;
442
458
  /** @description Prefix within the bucket */
443
459
  bucketPrefix?: string;
460
+ /** @description Session identifier for IAM-authorized mounts */
461
+ sessionId?: string;
444
462
  };
445
463
  DiskMetrics: {
446
464
  /** @description Data transfer amount with unit (e.g., "1.5 GB") */
@@ -459,9 +477,17 @@ interface components {
459
477
  AuthorizedUser: {
460
478
  /** @enum {string} */
461
479
  type?: "token" | "awssts";
480
+ /**
481
+ * @deprecated
482
+ * @description Use identifier instead. Only populated for awssts type (the IAM ARN).
483
+ */
462
484
  principal?: string;
463
485
  nickname?: string;
464
486
  tokenSuffix?: string;
487
+ /** @description The generated mount token. Only present in the response when the server generates the token (i.e. principal was not provided). This value is shown exactly once and cannot be retrieved again. */
488
+ token?: string;
489
+ /** @description Stable identifier for this user, returned in creation and list responses. Use this value with DELETE /api/disks/{id}/users/{type}?identifier={identifier} to remove the user. For awssts users, this is the IAM ARN. */
490
+ identifier?: string;
465
491
  /** Format: date-time */
466
492
  createdAt?: string;
467
493
  };
@@ -482,6 +508,7 @@ interface components {
482
508
  data: {
483
509
  /** @example dsk-0123456789abcdef */
484
510
  diskId?: string;
511
+ authorizedUsers?: components["schemas"]["AuthorizedUser"][];
485
512
  };
486
513
  };
487
514
  ApiResponse_AuthorizedUser: {
@@ -746,9 +773,14 @@ interface operations {
746
773
  };
747
774
  removeDiskUser: {
748
775
  parameters: {
749
- query: {
750
- /** @description The user's principal identifier. For token type, this is the MD5 hash (hex-encoded) of the token principal. For awssts type, this is the full IAM ARN (e.g., arn:aws:iam::123456789012:role/MyRole). */
751
- principal: string;
776
+ query?: {
777
+ /** @description Identifier of the user to remove, as returned in the creation or list response. For awssts users, this is the IAM ARN. */
778
+ identifier?: string;
779
+ /**
780
+ * @deprecated
781
+ * @description Use identifier instead.
782
+ */
783
+ principal?: string;
752
784
  };
753
785
  header?: never;
754
786
  path: {
@@ -908,7 +940,12 @@ declare class Disk {
908
940
  /** @internal */
909
941
  constructor(data: DiskResponse, client: ApiClient, archilRegion: string);
910
942
  addUser(user: DiskUser): Promise<AuthorizedUser>;
911
- removeUser(userType: "token" | "awssts", principal: string): Promise<void>;
943
+ removeUser(userType: "token" | "awssts", identifier: string): Promise<void>;
944
+ createToken(nickname: string): Promise<AuthorizedUser & {
945
+ token: string;
946
+ identifier: string;
947
+ }>;
948
+ removeTokenUser(identifier: string): Promise<void>;
912
949
  delete(): Promise<void>;
913
950
  /**
914
951
  * Connect to this disk's data plane via the native ArchilClient.
@@ -922,6 +959,12 @@ interface ListDisksOptions {
922
959
  limit?: number;
923
960
  cursor?: string;
924
961
  }
962
+ interface CreateDiskResult {
963
+ disk: Disk;
964
+ token: string | null;
965
+ tokenIdentifier: string | null;
966
+ authorizedUsers: AuthorizedUser[];
967
+ }
925
968
  declare class Disks {
926
969
  /** @internal */
927
970
  private readonly _client;
@@ -932,11 +975,12 @@ declare class Disks {
932
975
  list(opts?: ListDisksOptions): Promise<Disk[]>;
933
976
  get(id: string): Promise<Disk>;
934
977
  /**
935
- * Create a new disk and return a Disk object with full details.
978
+ * Create a new disk with an auto-generated mount token.
936
979
  *
937
- * Internally calls POST /api/disks (returns diskId) then GET /api/disks/{id}.
980
+ * Returns the Disk, the one-time token (save it it cannot be retrieved
981
+ * again), and the token identifier for later management.
938
982
  */
939
- create(req: CreateDiskRequest): Promise<Disk>;
983
+ create(req: CreateDiskRequest): Promise<CreateDiskResult>;
940
984
  }
941
985
 
942
986
  interface ListTokensOptions {
@@ -956,15 +1000,17 @@ declare class Tokens {
956
1000
  }
957
1001
 
958
1002
  interface ArchilOptions {
959
- apiKey: string;
960
- region: string;
1003
+ /** API key. Falls back to ARCHIL_API_KEY env var if not provided. */
1004
+ apiKey?: string;
1005
+ /** Region. Falls back to ARCHIL_REGION env var if not provided. */
1006
+ region?: string;
961
1007
  /** Override the control plane base URL (useful for testing). */
962
1008
  baseUrl?: string;
963
1009
  }
964
1010
  declare class Archil {
965
1011
  readonly disks: Disks;
966
1012
  readonly tokens: Tokens;
967
- constructor(opts: ArchilOptions);
1013
+ constructor(opts?: ArchilOptions);
968
1014
  }
969
1015
 
970
1016
  declare class ArchilApiError extends Error {
@@ -973,4 +1019,4 @@ declare class ArchilApiError extends Error {
973
1019
  constructor(message: string, status: number, code?: string);
974
1020
  }
975
1021
 
976
- export { type ApiTokenResponse, Archil, ArchilApiError, type ArchilOptions, type AuthorizedUser, type AwsStsUser, type AzureBlobMount, type ConnectedClient, type CreateApiTokenRequest, type CreateDiskRequest, Disk, type DiskMetrics, type DiskResponse, type DiskStatus, type DiskUser, Disks, type GCSMount, type ListDisksOptions, type ListTokensOptions, type MountConfig, type MountConfigResponse, type MountOptions, type MountResponse, type R2Mount, type S3CompatibleMount, type S3Mount, type TokenUser, Tokens };
1022
+ export { type ApiTokenResponse, Archil, ArchilApiError, type ArchilOptions, type AuthorizedUser, type AwsStsUser, type AzureBlobMount, type ConnectedClient, type CreateApiTokenRequest, type CreateDiskRequest, type CreateDiskResult, Disk, type DiskMetrics, type DiskResponse, type DiskStatus, type DiskUser, Disks, type GCSMount, type ListDisksOptions, type ListTokensOptions, type MountConfig, type MountConfigResponse, type MountOptions, type MountResponse, type R2Mount, type S3CompatibleMount, type S3Mount, type TokenUser, Tokens };
@@ -21,8 +21,13 @@ interface paths {
21
21
  put?: never;
22
22
  /**
23
23
  * Create a new disk
24
- * @description Creates a new disk with the specified configuration. The disk will be
25
- * provisioned in the specified region with the given mounts and authentication methods.
24
+ * @description Creates a new disk with the specified configuration. A default token
25
+ * user is automatically generated and returned in the response, so the
26
+ * disk is immediately mountable. The one-time token appears in
27
+ * `authorizedUsers[].token` and cannot be retrieved again.
28
+ *
29
+ * To provide your own users instead, pass the deprecated `authMethods`
30
+ * field or call AddDiskUser after creation.
26
31
  */
27
32
  post: operations["createDisk"];
28
33
  delete?: never;
@@ -170,7 +175,10 @@ interface components {
170
175
  name: string;
171
176
  /** @description Storage mount to attach. Omit for archil-managed storage. */
172
177
  mounts?: components["schemas"]["MountConfig"][];
173
- /** @description Authentication methods for disk access */
178
+ /**
179
+ * @deprecated
180
+ * @description Deprecated. Use AddDiskUser after creation instead. When provided, suppresses the default auto-generated token user.
181
+ */
174
182
  authMethods?: components["schemas"]["DiskUser"][];
175
183
  };
176
184
  MountConfig: components["schemas"]["S3Mount"] | components["schemas"]["GCSMount"] | components["schemas"]["R2Mount"] | components["schemas"]["S3CompatibleMount"] | components["schemas"]["AzureBlobMount"];
@@ -344,9 +352,17 @@ interface components {
344
352
  * @enum {string}
345
353
  */
346
354
  type: "token";
347
- principal: string;
355
+ /**
356
+ * @deprecated
357
+ * @description Deprecated. Client-provided token. If omitted, the server generates a cryptographically secure token and returns it in the response.
358
+ */
359
+ principal?: string;
348
360
  nickname: string;
349
- tokenSuffix: string;
361
+ /**
362
+ * @deprecated
363
+ * @description Deprecated. Last 4 characters of the token. Required when principal is provided; ignored when the server generates the token.
364
+ */
365
+ tokenSuffix?: string;
350
366
  };
351
367
  AwsStsUser: {
352
368
  /**
@@ -441,6 +457,8 @@ interface components {
441
457
  bucketEndpoint?: string;
442
458
  /** @description Prefix within the bucket */
443
459
  bucketPrefix?: string;
460
+ /** @description Session identifier for IAM-authorized mounts */
461
+ sessionId?: string;
444
462
  };
445
463
  DiskMetrics: {
446
464
  /** @description Data transfer amount with unit (e.g., "1.5 GB") */
@@ -459,9 +477,17 @@ interface components {
459
477
  AuthorizedUser: {
460
478
  /** @enum {string} */
461
479
  type?: "token" | "awssts";
480
+ /**
481
+ * @deprecated
482
+ * @description Use identifier instead. Only populated for awssts type (the IAM ARN).
483
+ */
462
484
  principal?: string;
463
485
  nickname?: string;
464
486
  tokenSuffix?: string;
487
+ /** @description The generated mount token. Only present in the response when the server generates the token (i.e. principal was not provided). This value is shown exactly once and cannot be retrieved again. */
488
+ token?: string;
489
+ /** @description Stable identifier for this user, returned in creation and list responses. Use this value with DELETE /api/disks/{id}/users/{type}?identifier={identifier} to remove the user. For awssts users, this is the IAM ARN. */
490
+ identifier?: string;
465
491
  /** Format: date-time */
466
492
  createdAt?: string;
467
493
  };
@@ -482,6 +508,7 @@ interface components {
482
508
  data: {
483
509
  /** @example dsk-0123456789abcdef */
484
510
  diskId?: string;
511
+ authorizedUsers?: components["schemas"]["AuthorizedUser"][];
485
512
  };
486
513
  };
487
514
  ApiResponse_AuthorizedUser: {
@@ -746,9 +773,14 @@ interface operations {
746
773
  };
747
774
  removeDiskUser: {
748
775
  parameters: {
749
- query: {
750
- /** @description The user's principal identifier. For token type, this is the MD5 hash (hex-encoded) of the token principal. For awssts type, this is the full IAM ARN (e.g., arn:aws:iam::123456789012:role/MyRole). */
751
- principal: string;
776
+ query?: {
777
+ /** @description Identifier of the user to remove, as returned in the creation or list response. For awssts users, this is the IAM ARN. */
778
+ identifier?: string;
779
+ /**
780
+ * @deprecated
781
+ * @description Use identifier instead.
782
+ */
783
+ principal?: string;
752
784
  };
753
785
  header?: never;
754
786
  path: {
@@ -908,7 +940,12 @@ declare class Disk {
908
940
  /** @internal */
909
941
  constructor(data: DiskResponse, client: ApiClient, archilRegion: string);
910
942
  addUser(user: DiskUser): Promise<AuthorizedUser>;
911
- removeUser(userType: "token" | "awssts", principal: string): Promise<void>;
943
+ removeUser(userType: "token" | "awssts", identifier: string): Promise<void>;
944
+ createToken(nickname: string): Promise<AuthorizedUser & {
945
+ token: string;
946
+ identifier: string;
947
+ }>;
948
+ removeTokenUser(identifier: string): Promise<void>;
912
949
  delete(): Promise<void>;
913
950
  /**
914
951
  * Connect to this disk's data plane via the native ArchilClient.
@@ -922,6 +959,12 @@ interface ListDisksOptions {
922
959
  limit?: number;
923
960
  cursor?: string;
924
961
  }
962
+ interface CreateDiskResult {
963
+ disk: Disk;
964
+ token: string | null;
965
+ tokenIdentifier: string | null;
966
+ authorizedUsers: AuthorizedUser[];
967
+ }
925
968
  declare class Disks {
926
969
  /** @internal */
927
970
  private readonly _client;
@@ -932,11 +975,12 @@ declare class Disks {
932
975
  list(opts?: ListDisksOptions): Promise<Disk[]>;
933
976
  get(id: string): Promise<Disk>;
934
977
  /**
935
- * Create a new disk and return a Disk object with full details.
978
+ * Create a new disk with an auto-generated mount token.
936
979
  *
937
- * Internally calls POST /api/disks (returns diskId) then GET /api/disks/{id}.
980
+ * Returns the Disk, the one-time token (save it it cannot be retrieved
981
+ * again), and the token identifier for later management.
938
982
  */
939
- create(req: CreateDiskRequest): Promise<Disk>;
983
+ create(req: CreateDiskRequest): Promise<CreateDiskResult>;
940
984
  }
941
985
 
942
986
  interface ListTokensOptions {
@@ -956,15 +1000,17 @@ declare class Tokens {
956
1000
  }
957
1001
 
958
1002
  interface ArchilOptions {
959
- apiKey: string;
960
- region: string;
1003
+ /** API key. Falls back to ARCHIL_API_KEY env var if not provided. */
1004
+ apiKey?: string;
1005
+ /** Region. Falls back to ARCHIL_REGION env var if not provided. */
1006
+ region?: string;
961
1007
  /** Override the control plane base URL (useful for testing). */
962
1008
  baseUrl?: string;
963
1009
  }
964
1010
  declare class Archil {
965
1011
  readonly disks: Disks;
966
1012
  readonly tokens: Tokens;
967
- constructor(opts: ArchilOptions);
1013
+ constructor(opts?: ArchilOptions);
968
1014
  }
969
1015
 
970
1016
  declare class ArchilApiError extends Error {
@@ -973,4 +1019,4 @@ declare class ArchilApiError extends Error {
973
1019
  constructor(message: string, status: number, code?: string);
974
1020
  }
975
1021
 
976
- export { type ApiTokenResponse, Archil, ArchilApiError, type ArchilOptions, type AuthorizedUser, type AwsStsUser, type AzureBlobMount, type ConnectedClient, type CreateApiTokenRequest, type CreateDiskRequest, Disk, type DiskMetrics, type DiskResponse, type DiskStatus, type DiskUser, Disks, type GCSMount, type ListDisksOptions, type ListTokensOptions, type MountConfig, type MountConfigResponse, type MountOptions, type MountResponse, type R2Mount, type S3CompatibleMount, type S3Mount, type TokenUser, Tokens };
1022
+ export { type ApiTokenResponse, Archil, ArchilApiError, type ArchilOptions, type AuthorizedUser, type AwsStsUser, type AzureBlobMount, type ConnectedClient, type CreateApiTokenRequest, type CreateDiskRequest, type CreateDiskResult, Disk, type DiskMetrics, type DiskResponse, type DiskStatus, type DiskUser, Disks, type GCSMount, type ListDisksOptions, type ListTokensOptions, type MountConfig, type MountConfigResponse, type MountOptions, type MountResponse, type R2Mount, type S3CompatibleMount, type S3Mount, type TokenUser, Tokens };
package/dist/api/index.js CHANGED
@@ -76,7 +76,7 @@ function createApiClient(opts) {
76
76
  return (0, import_openapi_fetch.default)({
77
77
  baseUrl,
78
78
  headers: {
79
- Authorization: `key-${opts.apiKey}`
79
+ Authorization: `key-${opts.apiKey.replace(/^key-/, "")}`
80
80
  }
81
81
  });
82
82
  }
@@ -166,16 +166,31 @@ var Disk = class {
166
166
  })
167
167
  );
168
168
  }
169
- async removeUser(userType, principal) {
169
+ async removeUser(userType, identifier) {
170
170
  await unwrapEmpty(
171
171
  this._client.DELETE("/api/disks/{id}/users/{userType}", {
172
172
  params: {
173
173
  path: { id: this.id, userType },
174
- query: { principal }
174
+ query: { identifier }
175
175
  }
176
176
  })
177
177
  );
178
178
  }
179
+ async createToken(nickname) {
180
+ const user = await unwrap(
181
+ this._client.POST("/api/disks/{id}/users", {
182
+ params: { path: { id: this.id } },
183
+ body: { type: "token", nickname }
184
+ })
185
+ );
186
+ if (!user.token || !user.identifier) {
187
+ throw new Error("Server did not return a generated token");
188
+ }
189
+ return user;
190
+ }
191
+ async removeTokenUser(identifier) {
192
+ await this.removeUser("token", identifier);
193
+ }
179
194
  async delete() {
180
195
  await unwrapEmpty(
181
196
  this._client.DELETE("/api/disks/{id}", {
@@ -241,19 +256,28 @@ var Disks = class {
241
256
  return new Disk(data, this._client, this._region);
242
257
  }
243
258
  /**
244
- * Create a new disk and return a Disk object with full details.
259
+ * Create a new disk with an auto-generated mount token.
245
260
  *
246
- * Internally calls POST /api/disks (returns diskId) then GET /api/disks/{id}.
261
+ * Returns the Disk, the one-time token (save it it cannot be retrieved
262
+ * again), and the token identifier for later management.
247
263
  */
248
264
  async create(req) {
249
265
  const created = await unwrap(
250
266
  this._client.POST("/api/disks", { body: req })
251
267
  );
252
- const diskId = created.diskId;
253
- if (!diskId) {
268
+ const resp = created;
269
+ if (!resp.diskId) {
254
270
  throw new Error("API returned success but no diskId");
255
271
  }
256
- return this.get(diskId);
272
+ const authorizedUsers = resp.authorizedUsers ?? [];
273
+ const tokenUser = authorizedUsers.find((u) => u.token);
274
+ const disk = await this.get(resp.diskId);
275
+ return {
276
+ disk,
277
+ token: tokenUser?.token ?? null,
278
+ tokenIdentifier: tokenUser?.identifier ?? null,
279
+ authorizedUsers
280
+ };
257
281
  }
258
282
  };
259
283
 
@@ -292,13 +316,21 @@ var Tokens = class {
292
316
  var Archil = class {
293
317
  disks;
294
318
  tokens;
295
- constructor(opts) {
319
+ constructor(opts = {}) {
320
+ const apiKey = opts.apiKey ?? process.env.ARCHIL_API_KEY;
321
+ const region = opts.region ?? process.env.ARCHIL_REGION;
322
+ if (!apiKey) {
323
+ throw new Error("Missing API key: pass apiKey in options or set ARCHIL_API_KEY environment variable");
324
+ }
325
+ if (!region) {
326
+ throw new Error("Missing region: pass region in options or set ARCHIL_REGION environment variable");
327
+ }
296
328
  const client = createApiClient({
297
- apiKey: opts.apiKey,
298
- region: opts.region,
329
+ apiKey,
330
+ region,
299
331
  baseUrl: opts.baseUrl
300
332
  });
301
- this.disks = new Disks(client, opts.region);
333
+ this.disks = new Disks(client, region);
302
334
  this.tokens = new Tokens(client);
303
335
  }
304
336
  };
@@ -36,7 +36,7 @@ function createApiClient(opts) {
36
36
  return createClient({
37
37
  baseUrl,
38
38
  headers: {
39
- Authorization: `key-${opts.apiKey}`
39
+ Authorization: `key-${opts.apiKey.replace(/^key-/, "")}`
40
40
  }
41
41
  });
42
42
  }
@@ -125,16 +125,31 @@ var Disk = class {
125
125
  })
126
126
  );
127
127
  }
128
- async removeUser(userType, principal) {
128
+ async removeUser(userType, identifier) {
129
129
  await unwrapEmpty(
130
130
  this._client.DELETE("/api/disks/{id}/users/{userType}", {
131
131
  params: {
132
132
  path: { id: this.id, userType },
133
- query: { principal }
133
+ query: { identifier }
134
134
  }
135
135
  })
136
136
  );
137
137
  }
138
+ async createToken(nickname) {
139
+ const user = await unwrap(
140
+ this._client.POST("/api/disks/{id}/users", {
141
+ params: { path: { id: this.id } },
142
+ body: { type: "token", nickname }
143
+ })
144
+ );
145
+ if (!user.token || !user.identifier) {
146
+ throw new Error("Server did not return a generated token");
147
+ }
148
+ return user;
149
+ }
150
+ async removeTokenUser(identifier) {
151
+ await this.removeUser("token", identifier);
152
+ }
138
153
  async delete() {
139
154
  await unwrapEmpty(
140
155
  this._client.DELETE("/api/disks/{id}", {
@@ -200,19 +215,28 @@ var Disks = class {
200
215
  return new Disk(data, this._client, this._region);
201
216
  }
202
217
  /**
203
- * Create a new disk and return a Disk object with full details.
218
+ * Create a new disk with an auto-generated mount token.
204
219
  *
205
- * Internally calls POST /api/disks (returns diskId) then GET /api/disks/{id}.
220
+ * Returns the Disk, the one-time token (save it it cannot be retrieved
221
+ * again), and the token identifier for later management.
206
222
  */
207
223
  async create(req) {
208
224
  const created = await unwrap(
209
225
  this._client.POST("/api/disks", { body: req })
210
226
  );
211
- const diskId = created.diskId;
212
- if (!diskId) {
227
+ const resp = created;
228
+ if (!resp.diskId) {
213
229
  throw new Error("API returned success but no diskId");
214
230
  }
215
- return this.get(diskId);
231
+ const authorizedUsers = resp.authorizedUsers ?? [];
232
+ const tokenUser = authorizedUsers.find((u) => u.token);
233
+ const disk = await this.get(resp.diskId);
234
+ return {
235
+ disk,
236
+ token: tokenUser?.token ?? null,
237
+ tokenIdentifier: tokenUser?.identifier ?? null,
238
+ authorizedUsers
239
+ };
216
240
  }
217
241
  };
218
242
 
@@ -251,13 +275,21 @@ var Tokens = class {
251
275
  var Archil = class {
252
276
  disks;
253
277
  tokens;
254
- constructor(opts) {
278
+ constructor(opts = {}) {
279
+ const apiKey = opts.apiKey ?? process.env.ARCHIL_API_KEY;
280
+ const region = opts.region ?? process.env.ARCHIL_REGION;
281
+ if (!apiKey) {
282
+ throw new Error("Missing API key: pass apiKey in options or set ARCHIL_API_KEY environment variable");
283
+ }
284
+ if (!region) {
285
+ throw new Error("Missing region: pass region in options or set ARCHIL_REGION environment variable");
286
+ }
255
287
  const client = createApiClient({
256
- apiKey: opts.apiKey,
257
- region: opts.region,
288
+ apiKey,
289
+ region,
258
290
  baseUrl: opts.baseUrl
259
291
  });
260
- this.disks = new Disks(client, opts.region);
292
+ this.disks = new Disks(client, region);
261
293
  this.tokens = new Tokens(client);
262
294
  }
263
295
  };
package/main.mjs CHANGED
@@ -15,3 +15,4 @@ try {
15
15
  export const ArchilClient = native.ArchilClient;
16
16
  export const initLogging = native.initLogging;
17
17
  export const JsInodeType = native.JsInodeType;
18
+ export const MAXIMUM_READ_SIZE = native.MAXIMUM_READ_SIZE;
package/native.d.ts CHANGED
@@ -3,6 +3,11 @@
3
3
 
4
4
  /* auto-generated by NAPI-RS */
5
5
 
6
+ /**
7
+ * Maximum size (in bytes) of a single read request.
8
+ * Matches MAXIMUM_READ_SIZE in the Rust protocol layer (rust-common/src/network/mod.rs).
9
+ */
10
+ export declare const MAXIMUM_READ_SIZE: number
6
11
  /**
7
12
  * Initialize the Rust logger to output to stderr.
8
13
  *
package/native.js CHANGED
@@ -72,8 +72,9 @@ if (!existsSync(localPath)) {
72
72
 
73
73
  const nativeBinding = require(localPath)
74
74
 
75
- const { initLogging, ArchilClient, JsInodeType } = nativeBinding
75
+ const { initLogging, ArchilClient, JsInodeType, MAXIMUM_READ_SIZE } = nativeBinding
76
76
 
77
77
  module.exports.initLogging = initLogging
78
78
  module.exports.ArchilClient = ArchilClient
79
79
  module.exports.JsInodeType = JsInodeType
80
+ module.exports.MAXIMUM_READ_SIZE = MAXIMUM_READ_SIZE
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@archildata/client",
3
- "version": "0.8.4",
3
+ "version": "0.8.7",
4
4
  "description": "High-performance Node.js client for Archil distributed filesystem",
5
5
  "main": "main.js",
6
6
  "types": "main.d.ts",