@truenas/api-client 4.0.1 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -183,6 +183,65 @@ discovery route that resolves against whatever the appliance turned out to be.
183
183
  On the named route it cannot: the client class is picked from the version you
184
184
  stated, so `ops` is that version's mappings whether or not the server agrees.
185
185
 
186
+ `ops` is deliberately flat — `OperationMappings`, not parameterized by the
187
+ directory — so every operation is callable whether or not you pinned a version.
188
+ That is what lets an operation paper over a difference the type system would
189
+ otherwise force the caller to handle.
190
+
191
+ ```ts
192
+ // The same call on every supported version.
193
+ const sessions = await firstValueFrom(
194
+ client.ops.smbStatus({ infoLevel: 'SESSIONS' })
195
+ );
196
+
197
+ // A client count is this composed, not a second operation.
198
+ const count = await firstValueFrom(
199
+ client.ops.smbStatus({
200
+ infoLevel: 'SESSIONS',
201
+ options: { count: true },
202
+ statusOptions: { fast: true },
203
+ })
204
+ );
205
+ ```
206
+
207
+ `smbStatus` is worth singling out, because it is the first operation whose
208
+ v25.10 leg is invisible to `middlewared --dump-api`. `smb.status` is public on
209
+ v26+ and generated like any other method; on v25.10 it is the same method taking
210
+ the same four positional arguments and returning the same `list | dict | int`,
211
+ but middleware declares it `private=True`, so the dump omits it and no generated
212
+ v25.10 type mentions it. The v25.10 client therefore *asserts* the method exists
213
+ rather than reading it from the directory — a single narrow declaration admitting
214
+ one method name, one argument tuple and one return type, checked against
215
+ middleware source instead of against the dump.
216
+
217
+ Three consequences worth knowing before you reach for it.
218
+
219
+ **It needs a full-admin session on v25.10.** Being private there decides
220
+ authorization, not just documentation. `smb.status` declares no roles on
221
+ v25.10, and middleware role-registers a method only `if roles:` — so it is in no
222
+ role's allowlist, and only a **non-STIG full-admin** session, whose allowlist is
223
+ the wildcard `{ method: '*', resource: '*' }`, reaches it. A session holding
224
+ exactly `SHARING_SMB_READ` is refused with `EACCES` on v25.10 and succeeds on
225
+ v26+, where the method carries that role. Under STIG, full admin is expanded to
226
+ the union of its roles' allowlists rather than the wildcard, so it is refused on
227
+ v25.10 as well. The client does not pre-empt any of this: you get middleware's
228
+ own error, on the version where it applies.
229
+
230
+ **It logs server-side on every dispatch**, which matters if you poll it. v25.10
231
+ is in maintenance and that cost is accepted there, but it is not a pattern to
232
+ extend.
233
+
234
+ **The result is the union middleware sends** — which arm arrives is decided by
235
+ the options, not the info level — so callers narrow it themselves.
236
+
237
+ These types are deliberately not the generated ones. `SmbStatusOptions` is not
238
+ v26's `SMBStatusOptions`, and `SmbStatusResponse` is not that method's generated
239
+ response: the generated types describe one version's dump, while these describe
240
+ the contract both versions honour. They are named `Smb…` rather than `SMB…` so
241
+ the two cannot be confused at a call site — and `SmbStatusOptions` is the one
242
+ pair where the names sit closest, since it is the fourth positional argument on
243
+ both versions.
244
+
186
245
  ## Documentation
187
246
 
188
247
  The API reference is generated from the TSDoc comments in the source with
package/dist/index.cjs CHANGED
@@ -1966,6 +1966,7 @@ __export(v25_10_5_exports, {
1966
1966
  var v26_0_0_exports = {};
1967
1967
  __export(v26_0_0_exports, {
1968
1968
  ACLTemplateEntryAcltypeInput: () => ACLTemplateEntryAcltypeInput,
1969
+ Access: () => Access,
1969
1970
  Aclmode: () => Aclmode,
1970
1971
  Acltype: () => Acltype,
1971
1972
  Advpowermgmt: () => Advpowermgmt,
@@ -2049,6 +2050,8 @@ __export(v26_0_0_exports, {
2049
2050
  RsyncTaskCreateDirectionInput: () => RsyncTaskCreateDirectionInput,
2050
2051
  RsyncTaskCreateMode: () => RsyncTaskCreateMode,
2051
2052
  RsyncTaskCreateModeInput: () => RsyncTaskCreateModeInput,
2053
+ S3AccesskeyEntryStatus: () => S3AccesskeyEntryStatus,
2054
+ S3AccesskeyEntryStatusInput: () => S3AccesskeyEntryStatusInput,
2052
2055
  SMBEntryEncryption: () => SMBEntryEncryption,
2053
2056
  SMBEntryEncryptionInput: () => SMBEntryEncryptionInput,
2054
2057
  STIGType: () => STIGType,
@@ -2086,6 +2089,7 @@ __export(v26_0_0_exports, {
2086
2089
  VMWareEntryStateStateInput: () => VMWareEntryStateStateInput,
2087
2090
  VMWareMatchDatastoresWithDatasetsResultFilesystemType: () => VMWareMatchDatastoresWithDatasetsResultFilesystemType,
2088
2091
  Vendor: () => Vendor,
2092
+ Versioning: () => Versioning,
2089
2093
  Volblocksize: () => Volblocksize,
2090
2094
  When: () => When,
2091
2095
  ZfsTierRewriteJobEntryStatus: () => ZfsTierRewriteJobEntryStatus,
@@ -2094,6 +2098,12 @@ __export(v26_0_0_exports, {
2094
2098
  });
2095
2099
 
2096
2100
  // src/generated/v26_0_0/api-types.ts
2101
+ var Access = {
2102
+ Readonly: "READONLY",
2103
+ Writeonly: "WRITEONLY",
2104
+ Readwrite: "READWRITE",
2105
+ Deny: "DENY"
2106
+ };
2097
2107
  var AppContainerDetailsState = {
2098
2108
  Crashed: "crashed",
2099
2109
  Created: "created",
@@ -2170,6 +2180,25 @@ var PoolScrubAction = {
2170
2180
  Stop: "STOP",
2171
2181
  Pause: "PAUSE"
2172
2182
  };
2183
+ var S3AccesskeyEntryStatus = {
2184
+ Enabled: "ENABLED",
2185
+ Disabled: "DISABLED",
2186
+ Expired: "EXPIRED",
2187
+ UserMissing: "USER_MISSING",
2188
+ SecretLost: "SECRET_LOST"
2189
+ };
2190
+ var S3AccesskeyEntryStatusInput = {
2191
+ Enabled: "ENABLED",
2192
+ Disabled: "DISABLED",
2193
+ Expired: "EXPIRED",
2194
+ UserMissing: "USER_MISSING",
2195
+ SecretLost: "SECRET_LOST"
2196
+ };
2197
+ var Versioning = {
2198
+ Off: "OFF",
2199
+ Enabled: "ENABLED",
2200
+ Suspended: "SUSPENDED"
2201
+ };
2173
2202
  var VMWareEntryStateState = {
2174
2203
  Pending: "PENDING",
2175
2204
  Success: "SUCCESS",
@@ -2194,6 +2223,7 @@ var ZpoolScrubRunAction = {
2194
2223
  var v27_0_0_exports = {};
2195
2224
  __export(v27_0_0_exports, {
2196
2225
  ACLTemplateEntryAcltypeInput: () => ACLTemplateEntryAcltypeInput,
2226
+ Access: () => Access,
2197
2227
  Aclmode: () => Aclmode,
2198
2228
  Acltype: () => Acltype,
2199
2229
  Advpowermgmt: () => Advpowermgmt,
@@ -2277,6 +2307,8 @@ __export(v27_0_0_exports, {
2277
2307
  RsyncTaskCreateDirectionInput: () => RsyncTaskCreateDirectionInput,
2278
2308
  RsyncTaskCreateMode: () => RsyncTaskCreateMode,
2279
2309
  RsyncTaskCreateModeInput: () => RsyncTaskCreateModeInput,
2310
+ S3AccesskeyEntryStatus: () => S3AccesskeyEntryStatus,
2311
+ S3AccesskeyEntryStatusInput: () => S3AccesskeyEntryStatusInput,
2280
2312
  SMBEntryEncryption: () => SMBEntryEncryption,
2281
2313
  SMBEntryEncryptionInput: () => SMBEntryEncryptionInput,
2282
2314
  STIGType: () => STIGType,
@@ -2313,7 +2345,9 @@ __export(v27_0_0_exports, {
2313
2345
  VMWareEntryStateState: () => VMWareEntryStateState,
2314
2346
  VMWareEntryStateStateInput: () => VMWareEntryStateStateInput,
2315
2347
  VMWareMatchDatastoresWithDatasetsResultFilesystemType: () => VMWareMatchDatastoresWithDatasetsResultFilesystemType,
2348
+ VMWareMatchDatastoresWithDatasetsResultFilesystemTypeInput: () => VMWareMatchDatastoresWithDatasetsResultFilesystemTypeInput,
2316
2349
  Vendor: () => Vendor,
2350
+ Versioning: () => Versioning,
2317
2351
  Volblocksize: () => Volblocksize,
2318
2352
  When: () => When,
2319
2353
  ZfsTierRewriteJobEntryStatus: () => ZfsTierRewriteJobEntryStatus,
@@ -2329,6 +2363,10 @@ var Service2 = {
2329
2363
  Sudo: "SUDO",
2330
2364
  System: "SYSTEM"
2331
2365
  };
2366
+ var VMWareMatchDatastoresWithDatasetsResultFilesystemTypeInput = {
2367
+ Filesystem: "FILESYSTEM",
2368
+ Volume: "VOLUME"
2369
+ };
2332
2370
 
2333
2371
  // src/generated/index.ts
2334
2372
  var SUPPORTED_API_VERSIONS = [
@@ -3449,6 +3487,16 @@ function toAppState(state) {
3449
3487
  }
3450
3488
  }
3451
3489
 
3490
+ // src/utils/smb-status.utils.ts
3491
+ function toSmbStatusParams(request = {}) {
3492
+ return [
3493
+ request.infoLevel ?? "ALL",
3494
+ request.filters ?? [],
3495
+ request.options ?? {},
3496
+ request.statusOptions ?? {}
3497
+ ];
3498
+ }
3499
+
3452
3500
  // src/client/truenas-api-client-v25-10.ts
3453
3501
  var TrueNasApiClientV2510 = class extends TrueNasApiClient {
3454
3502
  /**
@@ -3488,6 +3536,42 @@ var TrueNasApiClientV2510 = class extends TrueNasApiClient {
3488
3536
  );
3489
3537
  }
3490
3538
  return this.api.job("virt.instance.delete", [id]);
3539
+ },
3540
+ // The private leg. See `PrivateSmbStatusCall` for why this is a cast and
3541
+ // not a directory lookup.
3542
+ //
3543
+ // v25.10 answers rather than refusing, for a caller with the authority.
3544
+ // Being private does not stop the method running: `ws_handler/rpc.py`
3545
+ // logs a warning for a private call over websocket and dispatches it
3546
+ // anyway — the `# FIXME: Eventually, prohibit this` above that branch is
3547
+ // still unresolved on master.
3548
+ //
3549
+ // It does decide who may run it. `smb.status` carries no `roles=` here,
3550
+ // and middleware role-registers a method only `if roles:`, so it is in no
3551
+ // role's allowlist and only the non-STIG full-admin wildcard reaches it.
3552
+ // That is documented on `OperationMappings.smbStatus`; this leg does not
3553
+ // pre-empt it. A caller without the authority gets middleware's `EACCES`,
3554
+ // which is the honest answer and the server's to give.
3555
+ //
3556
+ // The server-side warning is per dispatch, and a client count is exactly
3557
+ // the sort of thing a caller polls. Reported at debug rather than warn,
3558
+ // because nothing here is degraded or unhonoured — the request is served
3559
+ // in full — and left to the caller to weigh.
3560
+ //
3561
+ // Future tense, and for the same reason as `containerDelete` above: this
3562
+ // runs when the operation is built, and `api.call` is cold, so no request
3563
+ // has gone out yet and may never. One built observable subscribed twice
3564
+ // dispatches twice; this line is what will happen, not a record that it
3565
+ // did.
3566
+ smbStatus: (request) => {
3567
+ this.logger.debug(
3568
+ "smbStatus: smb.status is private on v25.10; each dispatch will log a warning server-side and needs a non-STIG full-admin session",
3569
+ { method: "smb.status", infoLevel: request?.infoLevel ?? "ALL" }
3570
+ );
3571
+ return this.api.call(
3572
+ "smb.status",
3573
+ toSmbStatusParams(request)
3574
+ );
3491
3575
  }
3492
3576
  };
3493
3577
  }
@@ -3575,7 +3659,16 @@ var TrueNasApiClientV26 = class extends TrueNasApiClient {
3575
3659
  containerDelete: (id, options) => this.api.job(
3576
3660
  "container.delete",
3577
3661
  options ? [parseInt(id, 10), options] : [parseInt(id, 10)]
3578
- )
3662
+ ),
3663
+ // `smb.status` is public here and gated on `SHARING_SMB_READ`, so it is
3664
+ // an ordinary `call` read straight out of the generated directory — the
3665
+ // one leg of this operation that needs no assertion about the server.
3666
+ //
3667
+ // Not a query verb: middleware returns the same `list | dict | int`
3668
+ // polymorphism a `.query` does, but the generator did not mark the entry
3669
+ // with an `entity`, so `api.query` does not accept it and the union is
3670
+ // handed to the caller to narrow.
3671
+ smbStatus: (request) => this.api.call("smb.status", toSmbStatusParams(request))
3579
3672
  };
3580
3673
  }
3581
3674
  };
@@ -3656,7 +3749,16 @@ var TrueNasApiClientV27 = class extends TrueNasApiClient {
3656
3749
  containerDelete: (id, options) => this.api.job(
3657
3750
  "container.delete",
3658
3751
  options ? [parseInt(id, 10), options] : [parseInt(id, 10)]
3659
- )
3752
+ ),
3753
+ // `smb.status` is public here and gated on `SHARING_SMB_READ`, so it is
3754
+ // an ordinary `call` read straight out of the generated directory — the
3755
+ // one leg of this operation that needs no assertion about the server.
3756
+ //
3757
+ // Not a query verb: middleware returns the same `list | dict | int`
3758
+ // polymorphism a `.query` does, but the generator did not mark the entry
3759
+ // with an `entity`, so `api.query` does not accept it and the union is
3760
+ // handed to the caller to narrow.
3761
+ smbStatus: (request) => this.api.call("smb.status", toSmbStatusParams(request))
3660
3762
  };
3661
3763
  }
3662
3764
  };