@truenas/api-client 4.0.1 → 4.0.2

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.cts CHANGED
@@ -14509,6 +14509,103 @@ interface ContainerRestartOptions {
14509
14509
  force: boolean;
14510
14510
  }
14511
14511
 
14512
+ /**
14513
+ * Types for the version-agnostic `ops.smbStatus` operation.
14514
+ *
14515
+ * `smb.status` is one method with two different standings. On v26+ it is a
14516
+ * public, role-gated endpoint (`SHARING_SMB_READ`) and appears in the generated
14517
+ * directory. On v25.10 it is declared `private=True`, so `--dump-api` never
14518
+ * emitted it and no generated v25.10 type describes it — but the method is
14519
+ * there, under the same name, taking the same four positional arguments and
14520
+ * returning the same union. These types describe that shared wire contract
14521
+ * once, so the operation can present a single shape on every version.
14522
+ *
14523
+ * They are deliberately *not* re-exports of the generated v26 types. Those
14524
+ * describe one version's dump; this describes the contract both versions
14525
+ * happen to honour, and the two are only equal for as long as they stay equal.
14526
+ */
14527
+ /**
14528
+ * The kind of status being asked for.
14529
+ *
14530
+ * Neither version offers a seventh, but for two different reasons. v25.10
14531
+ * carries a legacy `AUTH_LOG` in its enum and its implementation — it routes to
14532
+ * `audit.query` rather than to `smbstatus` — while its own argument model
14533
+ * refuses it: the `Literal` there lists exactly these six. It is unreachable
14534
+ * even from middleware's own internal calls, because `api_method` validates
14535
+ * every invocation. v26+ does not have it at all; the level was deleted rather
14536
+ * than left dormant.
14537
+ */
14538
+ type SmbStatusInfoLevel = 'ALL' | 'SESSIONS' | 'SHARES' | 'LOCKS' | 'BYTERANGE' | 'NOTIFICATIONS';
14539
+ /**
14540
+ * Server-side options for the status query itself.
14541
+ *
14542
+ * Field names are snake_case because this object is passed to middleware
14543
+ * verbatim; it is the wire shape, not a translation of it.
14544
+ *
14545
+ * Every field is optional here, matching the generated v26 type. Middleware
14546
+ * defaults them on both versions — `verbose` and `resolve_uids` to true,
14547
+ * `fast` to false, the two `restrict_*` to empty strings.
14548
+ */
14549
+ interface SmbStatusOptions {
14550
+ verbose?: boolean;
14551
+ fast?: boolean;
14552
+ restrict_user?: string;
14553
+ restrict_session?: string;
14554
+ resolve_uids?: boolean;
14555
+ }
14556
+ /**
14557
+ * Rows returned by `smb.status` are not modelled by either version.
14558
+ *
14559
+ * The middleware result model is `list[dict] | dict | int` on both, and the
14560
+ * dump reproduces that as a `Record<string, unknown>` — the shape genuinely
14561
+ * varies with `info_level`, and neither version declares the per-level
14562
+ * structures. Callers narrow it themselves.
14563
+ */
14564
+ type SmbStatusRow = Record<string, unknown>;
14565
+ /**
14566
+ * What `smb.status` may return.
14567
+ *
14568
+ * The three arms are not interchangeable and which one arrives is decided by
14569
+ * the options, not by the info level: `{ count: true }` gives the number,
14570
+ * `{ get: true }` a single row, anything else the list. This is the same
14571
+ * polymorphism the query verbs exist to resolve, but `smb.status` is not a
14572
+ * `.query` method — the generator did not mark it with an `entity` — so the
14573
+ * union is returned as-is and the caller narrows.
14574
+ */
14575
+ type SmbStatusResponse = SmbStatusRow[] | SmbStatusRow | number;
14576
+ /**
14577
+ * Arguments for {@link OperationMappings.smbStatus}.
14578
+ *
14579
+ * A single object rather than four positional parameters: the wire form is
14580
+ * positional and every argument is optional, so a caller wanting only
14581
+ * `statusOptions` — the fourth — would otherwise have to pass three
14582
+ * placeholder arguments to reach it. The operation maps this back onto the
14583
+ * positional array.
14584
+ */
14585
+ interface SmbStatusRequest {
14586
+ /** Defaults to `ALL` on both versions. */
14587
+ infoLevel?: SmbStatusInfoLevel;
14588
+ /**
14589
+ * Query filters applied to the rows.
14590
+ *
14591
+ * Both versions special-case a lone `uid` or `session_id` equality filter,
14592
+ * turning it into the corresponding `restrict_*` status option instead of
14593
+ * filtering after the fact.
14594
+ *
14595
+ * That *overwrites* the status option rather than combining with it. Passing
14596
+ * `filters: [['uid', '=', 1000]]` together with
14597
+ * `statusOptions: { restrict_user: 'bob' }` sends both, and middleware
14598
+ * discards `'bob'`. This is middleware's behaviour on both versions, carried
14599
+ * through unchanged — but the two look like they compose and do not, so do
14600
+ * not set both.
14601
+ */
14602
+ filters?: QueryFilters<SmbStatusRow>;
14603
+ /** Query options. `{ count: true }` is what makes the result a number. */
14604
+ options?: QueryOptions<SmbStatusRow>;
14605
+ /** Options for the status command itself. */
14606
+ statusOptions?: SmbStatusOptions;
14607
+ }
14608
+
14512
14609
  /**
14513
14610
  * OperationMappings Interface
14514
14611
  *
@@ -14594,6 +14691,64 @@ interface OperationMappings {
14594
14691
  * ignored, because `recursive` destroys data that cannot be recovered.
14595
14692
  */
14596
14693
  containerDelete: (id: string, options?: ContainerDeleteOptions$1) => Observable<Job | null>;
14694
+ /**
14695
+ * Read SMB server status — sessions, shares, locks, notifications.
14696
+ *
14697
+ * - v25.10: `smb.status`, which is declared `private=True` there
14698
+ * - v26+: `smb.status`, public and gated on the `SHARING_SMB_READ` role
14699
+ *
14700
+ * The same method under the same name on both, taking the same four
14701
+ * positional arguments and returning the same `list | dict | int` union. That
14702
+ * is why this reads as one operation rather than a v26 feature with a v25.10
14703
+ * excuse, and why v25.10 returns real data instead of throwing.
14704
+ *
14705
+ * **The two versions are not equally reachable, though.** Being private on
14706
+ * v25.10 is not only a statement about documentation — it decides
14707
+ * authorization too, and this is the one respect in which the operation
14708
+ * cannot present a single face:
14709
+ *
14710
+ * - **v26+** declares `roles=['SHARING_SMB_READ']`, so any session holding
14711
+ * that role may call it.
14712
+ * - **v25.10** declares no roles at all. Middleware registers a method with
14713
+ * the role manager only `if roles:`, so `smb.status` is in no role's
14714
+ * allowlist, and `authorize('CALL', 'smb.status')` fails for a role-scoped
14715
+ * session with `Not authorized` (`EACCES`). A session holding exactly
14716
+ * `SHARING_SMB_READ` — the role that works on v26+ — is refused on v25.10.
14717
+ * - What does reach it is a **non-STIG full-admin** session, whose allowlist
14718
+ * is the wildcard `{ method: '*', resource: '*' }`. Under STIG, full admin
14719
+ * is expanded to the union of its roles' allowlists instead of the
14720
+ * wildcard, and `smb.status` is in none of them — so STIG full admin is
14721
+ * refused on v25.10 as well.
14722
+ *
14723
+ * Nothing here pre-empts that. The operation does not inspect the session or
14724
+ * refuse ahead of the server; a caller lacking the authority gets
14725
+ * middleware's own error, on the version where it applies.
14726
+ *
14727
+ * It is the first operation whose v25.10 leg is invisible to `--dump-api`: no
14728
+ * generated v25.10 type describes `smb.status`, because the dump omits
14729
+ * private methods. The v25.10 client therefore asserts the method's existence
14730
+ * rather than reading it from the directory, and that assertion is checked
14731
+ * against middleware source, not against the dump. See
14732
+ * `TrueNasApiClientV2510.createOperations`.
14733
+ *
14734
+ * Calling a private method logs a warning server-side on every invocation.
14735
+ * That is accepted for v25.10, which is in maintenance; it is not a pattern
14736
+ * to extend to versions still taking features.
14737
+ *
14738
+ * A client count is this composed rather than given its own operation, since
14739
+ * it is the same endpoint with different options:
14740
+ *
14741
+ * ```typescript
14742
+ * truenas.ops
14743
+ * .smbStatus({
14744
+ * infoLevel: 'SESSIONS',
14745
+ * options: { count: true },
14746
+ * statusOptions: { fast: true },
14747
+ * })
14748
+ * .subscribe((count) => console.log(count as number));
14749
+ * ```
14750
+ */
14751
+ smbStatus: (request?: SmbStatusRequest) => Observable<SmbStatusResponse>;
14597
14752
  }
14598
14753
 
14599
14754
  /**
@@ -30590,6 +30745,12 @@ declare function createTrueNasClient<D extends ApiDirectoryShape = DefaultApiDir
30590
30745
  * - containerStop → virt.instance.stop (emits Job updates)
30591
30746
  * - containerRestart → virt.instance.restart (emits Job updates)
30592
30747
  * - containerDelete → virt.instance.delete (already a job; takes no options)
30748
+ *
30749
+ * SMB operations:
30750
+ * - smbStatus → smb.status, which is declared `private=True` on this version
30751
+ * and so is absent from the generated directory. See `PrivateSmbStatusCall`
30752
+ * for how it is reached and why that is a cast, and `OperationMappings` for
30753
+ * the authorization difference being private carries with it here.
30593
30754
  */
30594
30755
  declare class TrueNasApiClientV2510 extends TrueNasApiClient<ApiDirectory$7> {
30595
30756
  /**
@@ -30628,6 +30789,9 @@ declare class TrueNasApiClientV2510 extends TrueNasApiClient<ApiDirectory$7> {
30628
30789
  * - containerStop → container.stop (emits Job updates)
30629
30790
  * - containerRestart → container.stop + container.start (emits Job, then null)
30630
30791
  * - containerDelete → container.delete (a job since v26.0.0; force/recursive)
30792
+ *
30793
+ * SMB operations:
30794
+ * - smbStatus → smb.status, public here and gated on `SHARING_SMB_READ`
30631
30795
  */
30632
30796
  declare class TrueNasApiClientV26 extends TrueNasApiClient<ApiDirectory$1> {
30633
30797
  /**
@@ -30677,10 +30841,26 @@ declare class TrueNasApiClientV26 extends TrueNasApiClient<ApiDirectory$1> {
30677
30841
  * - containerRestart → container.stop + container.start (emits Job, then null)
30678
30842
  * - containerDelete → container.delete (a job since v26.0.0; force/recursive)
30679
30843
  *
30680
- * Those four are currently identical to v26's, because v27 inherits all three
30681
- * container entries the facade touches rather than re-declaring them. Asserted
30682
- * rather than assumed, and re-runnable: the spec pins all three against v26's,
30683
- * so the day they diverge is a failure there.
30844
+ * SMB operations:
30845
+ * - smbStatus → smb.status, public and gated on `SHARING_SMB_READ`, as v26.
30846
+ * v27 inherits the entry rather than re-declaring it.
30847
+ *
30848
+ * All five container operations are currently identical to v26's, because v27
30849
+ * inherits the container entries the facade touches rather than re-declaring
30850
+ * them. Five operations, four entries — `containerRestart` has none of its own,
30851
+ * being `container.stop` then `container.start`. Asserted rather than assumed,
30852
+ * and re-runnable: the spec pins all four entries — `container.query`,
30853
+ * `.start`, `.stop`, `.delete` — against v26's, so the day they diverge is a
30854
+ * failure there.
30855
+ *
30856
+ * `smbStatus` is not among them. Its v27 entry is inherited from v26 too, but
30857
+ * nothing pins it the way the container entries are pinned. `tsc` is a partial
30858
+ * stand-in and worth stating precisely: this leg reads the method out of the
30859
+ * directory, so a v27 entry that *narrowed* the arguments or widened the
30860
+ * response past `SmbStatusResponse` would stop compiling here. The reverse
30861
+ * would not. A widened `info_level` or a narrowed response still compiles, and
30862
+ * the operation would go on advertising the stale union. Add an `Identical<>`
30863
+ * assertion beside the container ones if that matters.
30684
30864
  *
30685
30865
  * They are written out here rather than shared with v26 because that is what
30686
30866
  * this repo's one-client-per-series design is for: the two are the same today
@@ -30688,8 +30868,9 @@ declare class TrueNasApiClientV26 extends TrueNasApiClient<ApiDirectory$1> {
30688
30868
  * the chained stop+start below is the workaround for its absence. Factoring the
30689
30869
  * bodies into a common base would couple two versions that exist in order to
30690
30870
  * evolve apart, and the coupling would have to be undone by whichever release
30691
- * diverges first. The `@/generated` types are the guard against them drifting
30692
- * silently: an entry that changes at v27 stops compiling here.
30871
+ * diverges first. The `@/generated` types are what guard against them drifting
30872
+ * silently — though only as far as the paragraph above says: a directory change
30873
+ * this code cannot absorb stops compiling here, and one it can absorb does not.
30693
30874
  */
30694
30875
  declare class TrueNasApiClientV27 extends TrueNasApiClient<ApiDirectory> {
30695
30876
  /**
@@ -30942,4 +31123,4 @@ type ApiError = JsonRpcError | TrueNasError;
30942
31123
  */
30943
31124
  declare function getApiErrorMessage(error: unknown, fallback?: string): string;
30944
31125
 
30945
- export { type ApiCallDirectory$7 as ApiCallDirectoryV25_10_0, type ApiCallDirectory$6 as ApiCallDirectoryV25_10_1, type ApiCallDirectory$5 as ApiCallDirectoryV25_10_2, type ApiCallDirectory$4 as ApiCallDirectoryV25_10_3, type ApiCallDirectory$3 as ApiCallDirectoryV25_10_4, type ApiCallDirectory$2 as ApiCallDirectoryV25_10_5, type ApiCallDirectory$1 as ApiCallDirectoryV26_0_0, type ApiCallDirectory as ApiCallDirectoryV27_0_0, type ApiDirectoryByVersion, type ApiDirectoryShape, type ApiDirectory$7 as ApiDirectoryV25_10_0, type ApiDirectory$6 as ApiDirectoryV25_10_1, type ApiDirectory$5 as ApiDirectoryV25_10_2, type ApiDirectory$4 as ApiDirectoryV25_10_3, type ApiDirectory$3 as ApiDirectoryV25_10_4, type ApiDirectory$2 as ApiDirectoryV25_10_5, type ApiDirectory$1 as ApiDirectoryV26_0_0, type ApiDirectory as ApiDirectoryV27_0_0, type ApiError, type ApiEventDirectory$7 as ApiEventDirectoryV25_10_0, type ApiEventDirectory$6 as ApiEventDirectoryV25_10_1, type ApiEventDirectory$5 as ApiEventDirectoryV25_10_2, type ApiEventDirectory$4 as ApiEventDirectoryV25_10_3, type ApiEventDirectory$3 as ApiEventDirectoryV25_10_4, type ApiEventDirectory$2 as ApiEventDirectoryV25_10_5, type ApiEventDirectory$1 as ApiEventDirectoryV26_0_0, type ApiEventDirectory as ApiEventDirectoryV27_0_0, type ApiJobDirectory$7 as ApiJobDirectoryV25_10_0, type ApiJobDirectory$6 as ApiJobDirectoryV25_10_1, type ApiJobDirectory$5 as ApiJobDirectoryV25_10_2, type ApiJobDirectory$4 as ApiJobDirectoryV25_10_3, type ApiJobDirectory$3 as ApiJobDirectoryV25_10_4, type ApiJobDirectory$2 as ApiJobDirectoryV25_10_5, type ApiJobDirectory$1 as ApiJobDirectoryV26_0_0, type ApiJobDirectory as ApiJobDirectoryV27_0_0, type ApiKeyCreate, type ApiVersion, type ApiVersionResponse, AppState, type ApplianceProtocol, type ArgsOf, AuthError, AuthErrorCode, type AuthResponse, type BaseApiDirectory, type CallMethod, type CallParams, type CallResponse, type Container, type CreateClientOptions, type DefaultApiDirectory, type EventKind, type EventName, type EventUnion, InvalidVersionResponseError, type Job, type JobMethod, type JobParams, type JobProgress, type JobResult, JobState, type Logger, NoCompatibleVersionsError, type OperationMappings, type QueryDirectory, type QueryEntity, type QueryListOptions, type QueryMethod, type QuerySingleOptions, SUPPORTED_API_VERSIONS, type SupportedApiVersion, TrueNasApiClient, TrueNasApiClientV2510, TrueNasApiClientV26, TrueNasApiClientV27, TrueNasAuthMechanism, type TrueNasDate, UserRole, type UserRoleName, VersionCompatibility, VersionDiscovery, VersionDiscoveryError, VersionDiscoveryNetworkError, VersionDiscoveryTimeoutError, VersionEndpointNotFoundError, VersionTooNewError, VersionTooOldError, consoleLogger, createTrueNasClient, getApiErrorMessage, isJobFinished, noopLogger, index$7 as v25_10_0, index$6 as v25_10_1, index$5 as v25_10_2, index$4 as v25_10_3, index$3 as v25_10_4, index$2 as v25_10_5, index$1 as v26_0_0, index as v27_0_0 };
31126
+ export { type ApiCallDirectory$7 as ApiCallDirectoryV25_10_0, type ApiCallDirectory$6 as ApiCallDirectoryV25_10_1, type ApiCallDirectory$5 as ApiCallDirectoryV25_10_2, type ApiCallDirectory$4 as ApiCallDirectoryV25_10_3, type ApiCallDirectory$3 as ApiCallDirectoryV25_10_4, type ApiCallDirectory$2 as ApiCallDirectoryV25_10_5, type ApiCallDirectory$1 as ApiCallDirectoryV26_0_0, type ApiCallDirectory as ApiCallDirectoryV27_0_0, type ApiDirectoryByVersion, type ApiDirectoryShape, type ApiDirectory$7 as ApiDirectoryV25_10_0, type ApiDirectory$6 as ApiDirectoryV25_10_1, type ApiDirectory$5 as ApiDirectoryV25_10_2, type ApiDirectory$4 as ApiDirectoryV25_10_3, type ApiDirectory$3 as ApiDirectoryV25_10_4, type ApiDirectory$2 as ApiDirectoryV25_10_5, type ApiDirectory$1 as ApiDirectoryV26_0_0, type ApiDirectory as ApiDirectoryV27_0_0, type ApiError, type ApiEventDirectory$7 as ApiEventDirectoryV25_10_0, type ApiEventDirectory$6 as ApiEventDirectoryV25_10_1, type ApiEventDirectory$5 as ApiEventDirectoryV25_10_2, type ApiEventDirectory$4 as ApiEventDirectoryV25_10_3, type ApiEventDirectory$3 as ApiEventDirectoryV25_10_4, type ApiEventDirectory$2 as ApiEventDirectoryV25_10_5, type ApiEventDirectory$1 as ApiEventDirectoryV26_0_0, type ApiEventDirectory as ApiEventDirectoryV27_0_0, type ApiJobDirectory$7 as ApiJobDirectoryV25_10_0, type ApiJobDirectory$6 as ApiJobDirectoryV25_10_1, type ApiJobDirectory$5 as ApiJobDirectoryV25_10_2, type ApiJobDirectory$4 as ApiJobDirectoryV25_10_3, type ApiJobDirectory$3 as ApiJobDirectoryV25_10_4, type ApiJobDirectory$2 as ApiJobDirectoryV25_10_5, type ApiJobDirectory$1 as ApiJobDirectoryV26_0_0, type ApiJobDirectory as ApiJobDirectoryV27_0_0, type ApiKeyCreate, type ApiVersion, type ApiVersionResponse, AppState, type ApplianceProtocol, type ArgsOf, AuthError, AuthErrorCode, type AuthResponse, type BaseApiDirectory, type CallMethod, type CallParams, type CallResponse, type Container, type CreateClientOptions, type DefaultApiDirectory, type EventKind, type EventName, type EventUnion, InvalidVersionResponseError, type Job, type JobMethod, type JobParams, type JobProgress, type JobResult, JobState, type Logger, NoCompatibleVersionsError, type OperationMappings, type QueryDirectory, type QueryEntity, type QueryListOptions, type QueryMethod, type QuerySingleOptions, SUPPORTED_API_VERSIONS, type SmbStatusInfoLevel, type SmbStatusOptions, type SmbStatusRequest, type SmbStatusResponse, type SmbStatusRow, type SupportedApiVersion, TrueNasApiClient, TrueNasApiClientV2510, TrueNasApiClientV26, TrueNasApiClientV27, TrueNasAuthMechanism, type TrueNasDate, UserRole, type UserRoleName, VersionCompatibility, VersionDiscovery, VersionDiscoveryError, VersionDiscoveryNetworkError, VersionDiscoveryTimeoutError, VersionEndpointNotFoundError, VersionTooNewError, VersionTooOldError, consoleLogger, createTrueNasClient, getApiErrorMessage, isJobFinished, noopLogger, index$7 as v25_10_0, index$6 as v25_10_1, index$5 as v25_10_2, index$4 as v25_10_3, index$3 as v25_10_4, index$2 as v25_10_5, index$1 as v26_0_0, index as v27_0_0 };
package/dist/index.d.ts CHANGED
@@ -14509,6 +14509,103 @@ interface ContainerRestartOptions {
14509
14509
  force: boolean;
14510
14510
  }
14511
14511
 
14512
+ /**
14513
+ * Types for the version-agnostic `ops.smbStatus` operation.
14514
+ *
14515
+ * `smb.status` is one method with two different standings. On v26+ it is a
14516
+ * public, role-gated endpoint (`SHARING_SMB_READ`) and appears in the generated
14517
+ * directory. On v25.10 it is declared `private=True`, so `--dump-api` never
14518
+ * emitted it and no generated v25.10 type describes it — but the method is
14519
+ * there, under the same name, taking the same four positional arguments and
14520
+ * returning the same union. These types describe that shared wire contract
14521
+ * once, so the operation can present a single shape on every version.
14522
+ *
14523
+ * They are deliberately *not* re-exports of the generated v26 types. Those
14524
+ * describe one version's dump; this describes the contract both versions
14525
+ * happen to honour, and the two are only equal for as long as they stay equal.
14526
+ */
14527
+ /**
14528
+ * The kind of status being asked for.
14529
+ *
14530
+ * Neither version offers a seventh, but for two different reasons. v25.10
14531
+ * carries a legacy `AUTH_LOG` in its enum and its implementation — it routes to
14532
+ * `audit.query` rather than to `smbstatus` — while its own argument model
14533
+ * refuses it: the `Literal` there lists exactly these six. It is unreachable
14534
+ * even from middleware's own internal calls, because `api_method` validates
14535
+ * every invocation. v26+ does not have it at all; the level was deleted rather
14536
+ * than left dormant.
14537
+ */
14538
+ type SmbStatusInfoLevel = 'ALL' | 'SESSIONS' | 'SHARES' | 'LOCKS' | 'BYTERANGE' | 'NOTIFICATIONS';
14539
+ /**
14540
+ * Server-side options for the status query itself.
14541
+ *
14542
+ * Field names are snake_case because this object is passed to middleware
14543
+ * verbatim; it is the wire shape, not a translation of it.
14544
+ *
14545
+ * Every field is optional here, matching the generated v26 type. Middleware
14546
+ * defaults them on both versions — `verbose` and `resolve_uids` to true,
14547
+ * `fast` to false, the two `restrict_*` to empty strings.
14548
+ */
14549
+ interface SmbStatusOptions {
14550
+ verbose?: boolean;
14551
+ fast?: boolean;
14552
+ restrict_user?: string;
14553
+ restrict_session?: string;
14554
+ resolve_uids?: boolean;
14555
+ }
14556
+ /**
14557
+ * Rows returned by `smb.status` are not modelled by either version.
14558
+ *
14559
+ * The middleware result model is `list[dict] | dict | int` on both, and the
14560
+ * dump reproduces that as a `Record<string, unknown>` — the shape genuinely
14561
+ * varies with `info_level`, and neither version declares the per-level
14562
+ * structures. Callers narrow it themselves.
14563
+ */
14564
+ type SmbStatusRow = Record<string, unknown>;
14565
+ /**
14566
+ * What `smb.status` may return.
14567
+ *
14568
+ * The three arms are not interchangeable and which one arrives is decided by
14569
+ * the options, not by the info level: `{ count: true }` gives the number,
14570
+ * `{ get: true }` a single row, anything else the list. This is the same
14571
+ * polymorphism the query verbs exist to resolve, but `smb.status` is not a
14572
+ * `.query` method — the generator did not mark it with an `entity` — so the
14573
+ * union is returned as-is and the caller narrows.
14574
+ */
14575
+ type SmbStatusResponse = SmbStatusRow[] | SmbStatusRow | number;
14576
+ /**
14577
+ * Arguments for {@link OperationMappings.smbStatus}.
14578
+ *
14579
+ * A single object rather than four positional parameters: the wire form is
14580
+ * positional and every argument is optional, so a caller wanting only
14581
+ * `statusOptions` — the fourth — would otherwise have to pass three
14582
+ * placeholder arguments to reach it. The operation maps this back onto the
14583
+ * positional array.
14584
+ */
14585
+ interface SmbStatusRequest {
14586
+ /** Defaults to `ALL` on both versions. */
14587
+ infoLevel?: SmbStatusInfoLevel;
14588
+ /**
14589
+ * Query filters applied to the rows.
14590
+ *
14591
+ * Both versions special-case a lone `uid` or `session_id` equality filter,
14592
+ * turning it into the corresponding `restrict_*` status option instead of
14593
+ * filtering after the fact.
14594
+ *
14595
+ * That *overwrites* the status option rather than combining with it. Passing
14596
+ * `filters: [['uid', '=', 1000]]` together with
14597
+ * `statusOptions: { restrict_user: 'bob' }` sends both, and middleware
14598
+ * discards `'bob'`. This is middleware's behaviour on both versions, carried
14599
+ * through unchanged — but the two look like they compose and do not, so do
14600
+ * not set both.
14601
+ */
14602
+ filters?: QueryFilters<SmbStatusRow>;
14603
+ /** Query options. `{ count: true }` is what makes the result a number. */
14604
+ options?: QueryOptions<SmbStatusRow>;
14605
+ /** Options for the status command itself. */
14606
+ statusOptions?: SmbStatusOptions;
14607
+ }
14608
+
14512
14609
  /**
14513
14610
  * OperationMappings Interface
14514
14611
  *
@@ -14594,6 +14691,64 @@ interface OperationMappings {
14594
14691
  * ignored, because `recursive` destroys data that cannot be recovered.
14595
14692
  */
14596
14693
  containerDelete: (id: string, options?: ContainerDeleteOptions$1) => Observable<Job | null>;
14694
+ /**
14695
+ * Read SMB server status — sessions, shares, locks, notifications.
14696
+ *
14697
+ * - v25.10: `smb.status`, which is declared `private=True` there
14698
+ * - v26+: `smb.status`, public and gated on the `SHARING_SMB_READ` role
14699
+ *
14700
+ * The same method under the same name on both, taking the same four
14701
+ * positional arguments and returning the same `list | dict | int` union. That
14702
+ * is why this reads as one operation rather than a v26 feature with a v25.10
14703
+ * excuse, and why v25.10 returns real data instead of throwing.
14704
+ *
14705
+ * **The two versions are not equally reachable, though.** Being private on
14706
+ * v25.10 is not only a statement about documentation — it decides
14707
+ * authorization too, and this is the one respect in which the operation
14708
+ * cannot present a single face:
14709
+ *
14710
+ * - **v26+** declares `roles=['SHARING_SMB_READ']`, so any session holding
14711
+ * that role may call it.
14712
+ * - **v25.10** declares no roles at all. Middleware registers a method with
14713
+ * the role manager only `if roles:`, so `smb.status` is in no role's
14714
+ * allowlist, and `authorize('CALL', 'smb.status')` fails for a role-scoped
14715
+ * session with `Not authorized` (`EACCES`). A session holding exactly
14716
+ * `SHARING_SMB_READ` — the role that works on v26+ — is refused on v25.10.
14717
+ * - What does reach it is a **non-STIG full-admin** session, whose allowlist
14718
+ * is the wildcard `{ method: '*', resource: '*' }`. Under STIG, full admin
14719
+ * is expanded to the union of its roles' allowlists instead of the
14720
+ * wildcard, and `smb.status` is in none of them — so STIG full admin is
14721
+ * refused on v25.10 as well.
14722
+ *
14723
+ * Nothing here pre-empts that. The operation does not inspect the session or
14724
+ * refuse ahead of the server; a caller lacking the authority gets
14725
+ * middleware's own error, on the version where it applies.
14726
+ *
14727
+ * It is the first operation whose v25.10 leg is invisible to `--dump-api`: no
14728
+ * generated v25.10 type describes `smb.status`, because the dump omits
14729
+ * private methods. The v25.10 client therefore asserts the method's existence
14730
+ * rather than reading it from the directory, and that assertion is checked
14731
+ * against middleware source, not against the dump. See
14732
+ * `TrueNasApiClientV2510.createOperations`.
14733
+ *
14734
+ * Calling a private method logs a warning server-side on every invocation.
14735
+ * That is accepted for v25.10, which is in maintenance; it is not a pattern
14736
+ * to extend to versions still taking features.
14737
+ *
14738
+ * A client count is this composed rather than given its own operation, since
14739
+ * it is the same endpoint with different options:
14740
+ *
14741
+ * ```typescript
14742
+ * truenas.ops
14743
+ * .smbStatus({
14744
+ * infoLevel: 'SESSIONS',
14745
+ * options: { count: true },
14746
+ * statusOptions: { fast: true },
14747
+ * })
14748
+ * .subscribe((count) => console.log(count as number));
14749
+ * ```
14750
+ */
14751
+ smbStatus: (request?: SmbStatusRequest) => Observable<SmbStatusResponse>;
14597
14752
  }
14598
14753
 
14599
14754
  /**
@@ -30590,6 +30745,12 @@ declare function createTrueNasClient<D extends ApiDirectoryShape = DefaultApiDir
30590
30745
  * - containerStop → virt.instance.stop (emits Job updates)
30591
30746
  * - containerRestart → virt.instance.restart (emits Job updates)
30592
30747
  * - containerDelete → virt.instance.delete (already a job; takes no options)
30748
+ *
30749
+ * SMB operations:
30750
+ * - smbStatus → smb.status, which is declared `private=True` on this version
30751
+ * and so is absent from the generated directory. See `PrivateSmbStatusCall`
30752
+ * for how it is reached and why that is a cast, and `OperationMappings` for
30753
+ * the authorization difference being private carries with it here.
30593
30754
  */
30594
30755
  declare class TrueNasApiClientV2510 extends TrueNasApiClient<ApiDirectory$7> {
30595
30756
  /**
@@ -30628,6 +30789,9 @@ declare class TrueNasApiClientV2510 extends TrueNasApiClient<ApiDirectory$7> {
30628
30789
  * - containerStop → container.stop (emits Job updates)
30629
30790
  * - containerRestart → container.stop + container.start (emits Job, then null)
30630
30791
  * - containerDelete → container.delete (a job since v26.0.0; force/recursive)
30792
+ *
30793
+ * SMB operations:
30794
+ * - smbStatus → smb.status, public here and gated on `SHARING_SMB_READ`
30631
30795
  */
30632
30796
  declare class TrueNasApiClientV26 extends TrueNasApiClient<ApiDirectory$1> {
30633
30797
  /**
@@ -30677,10 +30841,26 @@ declare class TrueNasApiClientV26 extends TrueNasApiClient<ApiDirectory$1> {
30677
30841
  * - containerRestart → container.stop + container.start (emits Job, then null)
30678
30842
  * - containerDelete → container.delete (a job since v26.0.0; force/recursive)
30679
30843
  *
30680
- * Those four are currently identical to v26's, because v27 inherits all three
30681
- * container entries the facade touches rather than re-declaring them. Asserted
30682
- * rather than assumed, and re-runnable: the spec pins all three against v26's,
30683
- * so the day they diverge is a failure there.
30844
+ * SMB operations:
30845
+ * - smbStatus → smb.status, public and gated on `SHARING_SMB_READ`, as v26.
30846
+ * v27 inherits the entry rather than re-declaring it.
30847
+ *
30848
+ * All five container operations are currently identical to v26's, because v27
30849
+ * inherits the container entries the facade touches rather than re-declaring
30850
+ * them. Five operations, four entries — `containerRestart` has none of its own,
30851
+ * being `container.stop` then `container.start`. Asserted rather than assumed,
30852
+ * and re-runnable: the spec pins all four entries — `container.query`,
30853
+ * `.start`, `.stop`, `.delete` — against v26's, so the day they diverge is a
30854
+ * failure there.
30855
+ *
30856
+ * `smbStatus` is not among them. Its v27 entry is inherited from v26 too, but
30857
+ * nothing pins it the way the container entries are pinned. `tsc` is a partial
30858
+ * stand-in and worth stating precisely: this leg reads the method out of the
30859
+ * directory, so a v27 entry that *narrowed* the arguments or widened the
30860
+ * response past `SmbStatusResponse` would stop compiling here. The reverse
30861
+ * would not. A widened `info_level` or a narrowed response still compiles, and
30862
+ * the operation would go on advertising the stale union. Add an `Identical<>`
30863
+ * assertion beside the container ones if that matters.
30684
30864
  *
30685
30865
  * They are written out here rather than shared with v26 because that is what
30686
30866
  * this repo's one-client-per-series design is for: the two are the same today
@@ -30688,8 +30868,9 @@ declare class TrueNasApiClientV26 extends TrueNasApiClient<ApiDirectory$1> {
30688
30868
  * the chained stop+start below is the workaround for its absence. Factoring the
30689
30869
  * bodies into a common base would couple two versions that exist in order to
30690
30870
  * evolve apart, and the coupling would have to be undone by whichever release
30691
- * diverges first. The `@/generated` types are the guard against them drifting
30692
- * silently: an entry that changes at v27 stops compiling here.
30871
+ * diverges first. The `@/generated` types are what guard against them drifting
30872
+ * silently — though only as far as the paragraph above says: a directory change
30873
+ * this code cannot absorb stops compiling here, and one it can absorb does not.
30693
30874
  */
30694
30875
  declare class TrueNasApiClientV27 extends TrueNasApiClient<ApiDirectory> {
30695
30876
  /**
@@ -30942,4 +31123,4 @@ type ApiError = JsonRpcError | TrueNasError;
30942
31123
  */
30943
31124
  declare function getApiErrorMessage(error: unknown, fallback?: string): string;
30944
31125
 
30945
- export { type ApiCallDirectory$7 as ApiCallDirectoryV25_10_0, type ApiCallDirectory$6 as ApiCallDirectoryV25_10_1, type ApiCallDirectory$5 as ApiCallDirectoryV25_10_2, type ApiCallDirectory$4 as ApiCallDirectoryV25_10_3, type ApiCallDirectory$3 as ApiCallDirectoryV25_10_4, type ApiCallDirectory$2 as ApiCallDirectoryV25_10_5, type ApiCallDirectory$1 as ApiCallDirectoryV26_0_0, type ApiCallDirectory as ApiCallDirectoryV27_0_0, type ApiDirectoryByVersion, type ApiDirectoryShape, type ApiDirectory$7 as ApiDirectoryV25_10_0, type ApiDirectory$6 as ApiDirectoryV25_10_1, type ApiDirectory$5 as ApiDirectoryV25_10_2, type ApiDirectory$4 as ApiDirectoryV25_10_3, type ApiDirectory$3 as ApiDirectoryV25_10_4, type ApiDirectory$2 as ApiDirectoryV25_10_5, type ApiDirectory$1 as ApiDirectoryV26_0_0, type ApiDirectory as ApiDirectoryV27_0_0, type ApiError, type ApiEventDirectory$7 as ApiEventDirectoryV25_10_0, type ApiEventDirectory$6 as ApiEventDirectoryV25_10_1, type ApiEventDirectory$5 as ApiEventDirectoryV25_10_2, type ApiEventDirectory$4 as ApiEventDirectoryV25_10_3, type ApiEventDirectory$3 as ApiEventDirectoryV25_10_4, type ApiEventDirectory$2 as ApiEventDirectoryV25_10_5, type ApiEventDirectory$1 as ApiEventDirectoryV26_0_0, type ApiEventDirectory as ApiEventDirectoryV27_0_0, type ApiJobDirectory$7 as ApiJobDirectoryV25_10_0, type ApiJobDirectory$6 as ApiJobDirectoryV25_10_1, type ApiJobDirectory$5 as ApiJobDirectoryV25_10_2, type ApiJobDirectory$4 as ApiJobDirectoryV25_10_3, type ApiJobDirectory$3 as ApiJobDirectoryV25_10_4, type ApiJobDirectory$2 as ApiJobDirectoryV25_10_5, type ApiJobDirectory$1 as ApiJobDirectoryV26_0_0, type ApiJobDirectory as ApiJobDirectoryV27_0_0, type ApiKeyCreate, type ApiVersion, type ApiVersionResponse, AppState, type ApplianceProtocol, type ArgsOf, AuthError, AuthErrorCode, type AuthResponse, type BaseApiDirectory, type CallMethod, type CallParams, type CallResponse, type Container, type CreateClientOptions, type DefaultApiDirectory, type EventKind, type EventName, type EventUnion, InvalidVersionResponseError, type Job, type JobMethod, type JobParams, type JobProgress, type JobResult, JobState, type Logger, NoCompatibleVersionsError, type OperationMappings, type QueryDirectory, type QueryEntity, type QueryListOptions, type QueryMethod, type QuerySingleOptions, SUPPORTED_API_VERSIONS, type SupportedApiVersion, TrueNasApiClient, TrueNasApiClientV2510, TrueNasApiClientV26, TrueNasApiClientV27, TrueNasAuthMechanism, type TrueNasDate, UserRole, type UserRoleName, VersionCompatibility, VersionDiscovery, VersionDiscoveryError, VersionDiscoveryNetworkError, VersionDiscoveryTimeoutError, VersionEndpointNotFoundError, VersionTooNewError, VersionTooOldError, consoleLogger, createTrueNasClient, getApiErrorMessage, isJobFinished, noopLogger, index$7 as v25_10_0, index$6 as v25_10_1, index$5 as v25_10_2, index$4 as v25_10_3, index$3 as v25_10_4, index$2 as v25_10_5, index$1 as v26_0_0, index as v27_0_0 };
31126
+ export { type ApiCallDirectory$7 as ApiCallDirectoryV25_10_0, type ApiCallDirectory$6 as ApiCallDirectoryV25_10_1, type ApiCallDirectory$5 as ApiCallDirectoryV25_10_2, type ApiCallDirectory$4 as ApiCallDirectoryV25_10_3, type ApiCallDirectory$3 as ApiCallDirectoryV25_10_4, type ApiCallDirectory$2 as ApiCallDirectoryV25_10_5, type ApiCallDirectory$1 as ApiCallDirectoryV26_0_0, type ApiCallDirectory as ApiCallDirectoryV27_0_0, type ApiDirectoryByVersion, type ApiDirectoryShape, type ApiDirectory$7 as ApiDirectoryV25_10_0, type ApiDirectory$6 as ApiDirectoryV25_10_1, type ApiDirectory$5 as ApiDirectoryV25_10_2, type ApiDirectory$4 as ApiDirectoryV25_10_3, type ApiDirectory$3 as ApiDirectoryV25_10_4, type ApiDirectory$2 as ApiDirectoryV25_10_5, type ApiDirectory$1 as ApiDirectoryV26_0_0, type ApiDirectory as ApiDirectoryV27_0_0, type ApiError, type ApiEventDirectory$7 as ApiEventDirectoryV25_10_0, type ApiEventDirectory$6 as ApiEventDirectoryV25_10_1, type ApiEventDirectory$5 as ApiEventDirectoryV25_10_2, type ApiEventDirectory$4 as ApiEventDirectoryV25_10_3, type ApiEventDirectory$3 as ApiEventDirectoryV25_10_4, type ApiEventDirectory$2 as ApiEventDirectoryV25_10_5, type ApiEventDirectory$1 as ApiEventDirectoryV26_0_0, type ApiEventDirectory as ApiEventDirectoryV27_0_0, type ApiJobDirectory$7 as ApiJobDirectoryV25_10_0, type ApiJobDirectory$6 as ApiJobDirectoryV25_10_1, type ApiJobDirectory$5 as ApiJobDirectoryV25_10_2, type ApiJobDirectory$4 as ApiJobDirectoryV25_10_3, type ApiJobDirectory$3 as ApiJobDirectoryV25_10_4, type ApiJobDirectory$2 as ApiJobDirectoryV25_10_5, type ApiJobDirectory$1 as ApiJobDirectoryV26_0_0, type ApiJobDirectory as ApiJobDirectoryV27_0_0, type ApiKeyCreate, type ApiVersion, type ApiVersionResponse, AppState, type ApplianceProtocol, type ArgsOf, AuthError, AuthErrorCode, type AuthResponse, type BaseApiDirectory, type CallMethod, type CallParams, type CallResponse, type Container, type CreateClientOptions, type DefaultApiDirectory, type EventKind, type EventName, type EventUnion, InvalidVersionResponseError, type Job, type JobMethod, type JobParams, type JobProgress, type JobResult, JobState, type Logger, NoCompatibleVersionsError, type OperationMappings, type QueryDirectory, type QueryEntity, type QueryListOptions, type QueryMethod, type QuerySingleOptions, SUPPORTED_API_VERSIONS, type SmbStatusInfoLevel, type SmbStatusOptions, type SmbStatusRequest, type SmbStatusResponse, type SmbStatusRow, type SupportedApiVersion, TrueNasApiClient, TrueNasApiClientV2510, TrueNasApiClientV26, TrueNasApiClientV27, TrueNasAuthMechanism, type TrueNasDate, UserRole, type UserRoleName, VersionCompatibility, VersionDiscovery, VersionDiscoveryError, VersionDiscoveryNetworkError, VersionDiscoveryTimeoutError, VersionEndpointNotFoundError, VersionTooNewError, VersionTooOldError, consoleLogger, createTrueNasClient, getApiErrorMessage, isJobFinished, noopLogger, index$7 as v25_10_0, index$6 as v25_10_1, index$5 as v25_10_2, index$4 as v25_10_3, index$3 as v25_10_4, index$2 as v25_10_5, index$1 as v26_0_0, index as v27_0_0 };
package/dist/index.js CHANGED
@@ -3447,6 +3447,16 @@ function toAppState(state) {
3447
3447
  }
3448
3448
  }
3449
3449
 
3450
+ // src/utils/smb-status.utils.ts
3451
+ function toSmbStatusParams(request = {}) {
3452
+ return [
3453
+ request.infoLevel ?? "ALL",
3454
+ request.filters ?? [],
3455
+ request.options ?? {},
3456
+ request.statusOptions ?? {}
3457
+ ];
3458
+ }
3459
+
3450
3460
  // src/client/truenas-api-client-v25-10.ts
3451
3461
  var TrueNasApiClientV2510 = class extends TrueNasApiClient {
3452
3462
  /**
@@ -3486,6 +3496,42 @@ var TrueNasApiClientV2510 = class extends TrueNasApiClient {
3486
3496
  );
3487
3497
  }
3488
3498
  return this.api.job("virt.instance.delete", [id]);
3499
+ },
3500
+ // The private leg. See `PrivateSmbStatusCall` for why this is a cast and
3501
+ // not a directory lookup.
3502
+ //
3503
+ // v25.10 answers rather than refusing, for a caller with the authority.
3504
+ // Being private does not stop the method running: `ws_handler/rpc.py`
3505
+ // logs a warning for a private call over websocket and dispatches it
3506
+ // anyway — the `# FIXME: Eventually, prohibit this` above that branch is
3507
+ // still unresolved on master.
3508
+ //
3509
+ // It does decide who may run it. `smb.status` carries no `roles=` here,
3510
+ // and middleware role-registers a method only `if roles:`, so it is in no
3511
+ // role's allowlist and only the non-STIG full-admin wildcard reaches it.
3512
+ // That is documented on `OperationMappings.smbStatus`; this leg does not
3513
+ // pre-empt it. A caller without the authority gets middleware's `EACCES`,
3514
+ // which is the honest answer and the server's to give.
3515
+ //
3516
+ // The server-side warning is per dispatch, and a client count is exactly
3517
+ // the sort of thing a caller polls. Reported at debug rather than warn,
3518
+ // because nothing here is degraded or unhonoured — the request is served
3519
+ // in full — and left to the caller to weigh.
3520
+ //
3521
+ // Future tense, and for the same reason as `containerDelete` above: this
3522
+ // runs when the operation is built, and `api.call` is cold, so no request
3523
+ // has gone out yet and may never. One built observable subscribed twice
3524
+ // dispatches twice; this line is what will happen, not a record that it
3525
+ // did.
3526
+ smbStatus: (request) => {
3527
+ this.logger.debug(
3528
+ "smbStatus: smb.status is private on v25.10; each dispatch will log a warning server-side and needs a non-STIG full-admin session",
3529
+ { method: "smb.status", infoLevel: request?.infoLevel ?? "ALL" }
3530
+ );
3531
+ return this.api.call(
3532
+ "smb.status",
3533
+ toSmbStatusParams(request)
3534
+ );
3489
3535
  }
3490
3536
  };
3491
3537
  }
@@ -3573,7 +3619,16 @@ var TrueNasApiClientV26 = class extends TrueNasApiClient {
3573
3619
  containerDelete: (id, options) => this.api.job(
3574
3620
  "container.delete",
3575
3621
  options ? [parseInt(id, 10), options] : [parseInt(id, 10)]
3576
- )
3622
+ ),
3623
+ // `smb.status` is public here and gated on `SHARING_SMB_READ`, so it is
3624
+ // an ordinary `call` read straight out of the generated directory — the
3625
+ // one leg of this operation that needs no assertion about the server.
3626
+ //
3627
+ // Not a query verb: middleware returns the same `list | dict | int`
3628
+ // polymorphism a `.query` does, but the generator did not mark the entry
3629
+ // with an `entity`, so `api.query` does not accept it and the union is
3630
+ // handed to the caller to narrow.
3631
+ smbStatus: (request) => this.api.call("smb.status", toSmbStatusParams(request))
3577
3632
  };
3578
3633
  }
3579
3634
  };
@@ -3654,7 +3709,16 @@ var TrueNasApiClientV27 = class extends TrueNasApiClient {
3654
3709
  containerDelete: (id, options) => this.api.job(
3655
3710
  "container.delete",
3656
3711
  options ? [parseInt(id, 10), options] : [parseInt(id, 10)]
3657
- )
3712
+ ),
3713
+ // `smb.status` is public here and gated on `SHARING_SMB_READ`, so it is
3714
+ // an ordinary `call` read straight out of the generated directory — the
3715
+ // one leg of this operation that needs no assertion about the server.
3716
+ //
3717
+ // Not a query verb: middleware returns the same `list | dict | int`
3718
+ // polymorphism a `.query` does, but the generator did not mark the entry
3719
+ // with an `entity`, so `api.query` does not accept it and the union is
3720
+ // handed to the caller to narrow.
3721
+ smbStatus: (request) => this.api.call("smb.status", toSmbStatusParams(request))
3658
3722
  };
3659
3723
  }
3660
3724
  };