@truenas/api-client 3.0.0 → 3.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
@@ -13015,6 +13015,33 @@ interface ContainerStopOptions$1 {
13015
13015
  timeout?: number;
13016
13016
  force: boolean;
13017
13017
  }
13018
+ /**
13019
+ * Options for deleting a container (unified interface)
13020
+ *
13021
+ * Both are optional and both default to off, matching middleware. Neither has a
13022
+ * counterpart on v25.10 — `virt.instance.delete` takes an id and nothing else —
13023
+ * so the v25.10 client cannot honour them; it says so rather than dropping them
13024
+ * quietly, because `recursive` in particular destroys data.
13025
+ */
13026
+ interface ContainerDeleteOptions$1 {
13027
+ /**
13028
+ * Stop the container first if it is not already stopped. Without it, v26+
13029
+ * refuses to delete a running or suspended container rather than tearing it
13030
+ * down underneath itself.
13031
+ */
13032
+ force?: boolean;
13033
+ /**
13034
+ * Destroy the container's dataset together with its child datasets and
13035
+ * snapshots, any clones of those snapshots wherever they live in the pool,
13036
+ * and any holds on them.
13037
+ *
13038
+ * Releasing a hold can break a replication task that depends on it, and none
13039
+ * of what this destroys is recoverable. Without it, v26+ refuses to delete a
13040
+ * container whose dataset has children or snapshots — which is the refusal
13041
+ * this option exists to override, deliberately.
13042
+ */
13043
+ recursive?: boolean;
13044
+ }
13018
13045
  /**
13019
13046
  * Options for restarting a container (unified interface)
13020
13047
  */
@@ -13058,8 +13085,14 @@ interface ContainerRestartOptions {
13058
13085
  *
13059
13086
  * To add new operations:
13060
13087
  * 1. Add the method signature here
13061
- * 2. Implement in TrueNasApiClientV2510.createOperations()
13062
- * 3. Implement in TrueNasApiClientV26.createOperations()
13088
+ * 2. Implement it in every client's `createOperations()` —
13089
+ * `TrueNasApiClientV2510`, `TrueNasApiClientV26`, `TrueNasApiClientV27`
13090
+ *
13091
+ * This list used to name only v25.10 and v26, which is how a new operation
13092
+ * would have quietly missed v27. It is not the real safety net either: adding a
13093
+ * member here fails to compile in every client that has not implemented it, and
13094
+ * that is what actually enumerates them. Keep the list current, but trust the
13095
+ * compiler.
13063
13096
  */
13064
13097
  interface OperationMappings {
13065
13098
  /**
@@ -13086,6 +13119,22 @@ interface OperationMappings {
13086
13119
  * - v26+: Emits Job updates (stop phase), then null (sync start)
13087
13120
  */
13088
13121
  containerRestart: (id: string, options: ContainerRestartOptions) => Observable<Job | null>;
13122
+ /**
13123
+ * Delete a container
13124
+ * - v25.10: `virt.instance.delete`, already a job — emits Job updates
13125
+ * - v26+: `container.delete`, made a job in v26.0.0 — emits Job updates
13126
+ *
13127
+ * A job on every supported version, so unlike `containerStart` this one does
13128
+ * not change shape across them. It is exposed here because the alternative is
13129
+ * a caller reaching for `api.call('container.delete', …)`, which is the wrong
13130
+ * verb: the method moved out of the call directory when middleware made it a
13131
+ * job, so that does not compile on v26+ and would not track the job if it did.
13132
+ *
13133
+ * `options` are honoured on v26+ only. v25.10's `virt.instance.delete` takes
13134
+ * an id and nothing else; passing them there is logged rather than silently
13135
+ * ignored, because `recursive` destroys data that cannot be recovered.
13136
+ */
13137
+ containerDelete: (id: string, options?: ContainerDeleteOptions$1) => Observable<Job | null>;
13089
13138
  }
13090
13139
 
13091
13140
  /**
@@ -27540,7 +27589,7 @@ interface CreateClientOptions {
27540
27589
  * 1. Discovers the API version (`GET /api/versions`), asking every hostname in
27541
27590
  * parallel. The first usable answer wins.
27542
27591
  * 2. Selects the matching client implementation (`v25.10.x` -> `TrueNasApiClientV2510`,
27543
- * `v26.x.y` -> `TrueNasApiClientV26`).
27592
+ * `v26.x.y` -> `TrueNasApiClientV26`, `v27.x.y` -> `TrueNasApiClientV27`).
27544
27593
  * 3. Instantiates and returns it.
27545
27594
  *
27546
27595
  * Resolves exactly once with a single client instance — dispose of it with
@@ -27608,6 +27657,7 @@ declare function createTrueNasClient<D extends ApiDirectoryShape = DefaultApiDir
27608
27657
  * - containerStart → virt.instance.start (emits Job updates)
27609
27658
  * - containerStop → virt.instance.stop (emits Job updates)
27610
27659
  * - containerRestart → virt.instance.restart (emits Job updates)
27660
+ * - containerDelete → virt.instance.delete (already a job; takes no options)
27611
27661
  */
27612
27662
  declare class TrueNasApiClientV2510 extends TrueNasApiClient<ApiDirectory$7> {
27613
27663
  /**
@@ -27645,6 +27695,7 @@ declare class TrueNasApiClientV2510 extends TrueNasApiClient<ApiDirectory$7> {
27645
27695
  * - containerStart → container.start (synchronous, emits null)
27646
27696
  * - containerStop → container.stop (emits Job updates)
27647
27697
  * - containerRestart → container.stop + container.start (emits Job, then null)
27698
+ * - containerDelete → container.delete (a job since v26.0.0; force/recursive)
27648
27699
  */
27649
27700
  declare class TrueNasApiClientV26 extends TrueNasApiClient<ApiDirectory$1> {
27650
27701
  /**
@@ -27657,6 +27708,68 @@ declare class TrueNasApiClientV26 extends TrueNasApiClient<ApiDirectory$1> {
27657
27708
  protected createOperations(): OperationMappings;
27658
27709
  }
27659
27710
 
27711
+ /**
27712
+ * TrueNAS API Client for v27.X.Y
27713
+ *
27714
+ * Handles all v27 versions (v27.0.0, v27.0.1, v27.1.2, etc.). Minor and patch
27715
+ * releases within a year are backward compatible, so one implementation covers
27716
+ * the series; breaking changes only arrive with the next year.
27717
+ *
27718
+ * That is what this class supports. What version *discovery* currently admits
27719
+ * is narrower: `MAX_SUPPORTED_VERSION` is a concrete version and the range check
27720
+ * compares patches, so today only `v27.0.0` clears it — `v27.0.1` and `v27.1.0`
27721
+ * are reported too-new and never reach this client. The effect always falls on
27722
+ * the newest series and nothing below it, which is why it has gone unnoticed:
27723
+ * raising the ceiling to v27.0.0 is what made v26.0.1 admissible in the first
27724
+ * place. Closing it means deciding how the ceiling should treat a series rather
27725
+ * than a version, which is a change to the compatibility model and not this
27726
+ * client's to make.
27727
+ *
27728
+ * To add version-specific behavior, override the factory methods:
27729
+ * - createConnection() - for connection-specific changes
27730
+ * - createApi() - for API method changes
27731
+ * - createAuthenticator() - for authentication changes
27732
+ * - createOperations() - for version-specific operation mappings
27733
+ */
27734
+
27735
+ /**
27736
+ * API client for TrueNAS API v27
27737
+ *
27738
+ * Protocol: JSON-RPC 2.0
27739
+ * WebSocket Path: /api/v27.{minor}.{patch}
27740
+ *
27741
+ * Container operations use the native container.* APIs, as v26 does:
27742
+ * - containerQuery → container.query (with response transformation)
27743
+ * - containerStart → container.start (synchronous, emits null)
27744
+ * - containerStop → container.stop (emits Job updates)
27745
+ * - containerRestart → container.stop + container.start (emits Job, then null)
27746
+ * - containerDelete → container.delete (a job since v26.0.0; force/recursive)
27747
+ *
27748
+ * Those four are currently identical to v26's, because v27 inherits all three
27749
+ * container entries the facade touches rather than re-declaring them. Asserted
27750
+ * rather than assumed, and re-runnable: the spec pins all three against v26's,
27751
+ * so the day they diverge is a failure there.
27752
+ *
27753
+ * They are written out here rather than shared with v26 because that is what
27754
+ * this repo's one-client-per-series design is for: the two are the same today
27755
+ * and are expected to diverge — middleware has no `container.restart` yet, and
27756
+ * the chained stop+start below is the workaround for its absence. Factoring the
27757
+ * bodies into a common base would couple two versions that exist in order to
27758
+ * evolve apart, and the coupling would have to be undone by whichever release
27759
+ * diverges first. The `@/generated` types are the guard against them drifting
27760
+ * silently: an entry that changes at v27 stops compiling here.
27761
+ */
27762
+ declare class TrueNasApiClientV27 extends TrueNasApiClient<ApiDirectory> {
27763
+ /**
27764
+ * Create v27-specific operation mappings
27765
+ *
27766
+ * Operations return Observable<Job | null>:
27767
+ * - Async operations emit Job updates until complete
27768
+ * - Sync operations emit null once
27769
+ */
27770
+ protected createOperations(): OperationMappings;
27771
+ }
27772
+
27660
27773
  /**
27661
27774
  * Discovers available API versions from TrueNAS systems.
27662
27775
  *
@@ -27860,4 +27973,4 @@ type ApiError = JsonRpcError | TrueNasError;
27860
27973
  */
27861
27974
  declare function getApiErrorMessage(error: unknown, fallback?: string): string;
27862
27975
 
27863
- 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 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, TrueNasAuthMechanism, type TrueNasDate, 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 };
27976
+ 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 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, 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
@@ -13015,6 +13015,33 @@ interface ContainerStopOptions$1 {
13015
13015
  timeout?: number;
13016
13016
  force: boolean;
13017
13017
  }
13018
+ /**
13019
+ * Options for deleting a container (unified interface)
13020
+ *
13021
+ * Both are optional and both default to off, matching middleware. Neither has a
13022
+ * counterpart on v25.10 — `virt.instance.delete` takes an id and nothing else —
13023
+ * so the v25.10 client cannot honour them; it says so rather than dropping them
13024
+ * quietly, because `recursive` in particular destroys data.
13025
+ */
13026
+ interface ContainerDeleteOptions$1 {
13027
+ /**
13028
+ * Stop the container first if it is not already stopped. Without it, v26+
13029
+ * refuses to delete a running or suspended container rather than tearing it
13030
+ * down underneath itself.
13031
+ */
13032
+ force?: boolean;
13033
+ /**
13034
+ * Destroy the container's dataset together with its child datasets and
13035
+ * snapshots, any clones of those snapshots wherever they live in the pool,
13036
+ * and any holds on them.
13037
+ *
13038
+ * Releasing a hold can break a replication task that depends on it, and none
13039
+ * of what this destroys is recoverable. Without it, v26+ refuses to delete a
13040
+ * container whose dataset has children or snapshots — which is the refusal
13041
+ * this option exists to override, deliberately.
13042
+ */
13043
+ recursive?: boolean;
13044
+ }
13018
13045
  /**
13019
13046
  * Options for restarting a container (unified interface)
13020
13047
  */
@@ -13058,8 +13085,14 @@ interface ContainerRestartOptions {
13058
13085
  *
13059
13086
  * To add new operations:
13060
13087
  * 1. Add the method signature here
13061
- * 2. Implement in TrueNasApiClientV2510.createOperations()
13062
- * 3. Implement in TrueNasApiClientV26.createOperations()
13088
+ * 2. Implement it in every client's `createOperations()` —
13089
+ * `TrueNasApiClientV2510`, `TrueNasApiClientV26`, `TrueNasApiClientV27`
13090
+ *
13091
+ * This list used to name only v25.10 and v26, which is how a new operation
13092
+ * would have quietly missed v27. It is not the real safety net either: adding a
13093
+ * member here fails to compile in every client that has not implemented it, and
13094
+ * that is what actually enumerates them. Keep the list current, but trust the
13095
+ * compiler.
13063
13096
  */
13064
13097
  interface OperationMappings {
13065
13098
  /**
@@ -13086,6 +13119,22 @@ interface OperationMappings {
13086
13119
  * - v26+: Emits Job updates (stop phase), then null (sync start)
13087
13120
  */
13088
13121
  containerRestart: (id: string, options: ContainerRestartOptions) => Observable<Job | null>;
13122
+ /**
13123
+ * Delete a container
13124
+ * - v25.10: `virt.instance.delete`, already a job — emits Job updates
13125
+ * - v26+: `container.delete`, made a job in v26.0.0 — emits Job updates
13126
+ *
13127
+ * A job on every supported version, so unlike `containerStart` this one does
13128
+ * not change shape across them. It is exposed here because the alternative is
13129
+ * a caller reaching for `api.call('container.delete', …)`, which is the wrong
13130
+ * verb: the method moved out of the call directory when middleware made it a
13131
+ * job, so that does not compile on v26+ and would not track the job if it did.
13132
+ *
13133
+ * `options` are honoured on v26+ only. v25.10's `virt.instance.delete` takes
13134
+ * an id and nothing else; passing them there is logged rather than silently
13135
+ * ignored, because `recursive` destroys data that cannot be recovered.
13136
+ */
13137
+ containerDelete: (id: string, options?: ContainerDeleteOptions$1) => Observable<Job | null>;
13089
13138
  }
13090
13139
 
13091
13140
  /**
@@ -27540,7 +27589,7 @@ interface CreateClientOptions {
27540
27589
  * 1. Discovers the API version (`GET /api/versions`), asking every hostname in
27541
27590
  * parallel. The first usable answer wins.
27542
27591
  * 2. Selects the matching client implementation (`v25.10.x` -> `TrueNasApiClientV2510`,
27543
- * `v26.x.y` -> `TrueNasApiClientV26`).
27592
+ * `v26.x.y` -> `TrueNasApiClientV26`, `v27.x.y` -> `TrueNasApiClientV27`).
27544
27593
  * 3. Instantiates and returns it.
27545
27594
  *
27546
27595
  * Resolves exactly once with a single client instance — dispose of it with
@@ -27608,6 +27657,7 @@ declare function createTrueNasClient<D extends ApiDirectoryShape = DefaultApiDir
27608
27657
  * - containerStart → virt.instance.start (emits Job updates)
27609
27658
  * - containerStop → virt.instance.stop (emits Job updates)
27610
27659
  * - containerRestart → virt.instance.restart (emits Job updates)
27660
+ * - containerDelete → virt.instance.delete (already a job; takes no options)
27611
27661
  */
27612
27662
  declare class TrueNasApiClientV2510 extends TrueNasApiClient<ApiDirectory$7> {
27613
27663
  /**
@@ -27645,6 +27695,7 @@ declare class TrueNasApiClientV2510 extends TrueNasApiClient<ApiDirectory$7> {
27645
27695
  * - containerStart → container.start (synchronous, emits null)
27646
27696
  * - containerStop → container.stop (emits Job updates)
27647
27697
  * - containerRestart → container.stop + container.start (emits Job, then null)
27698
+ * - containerDelete → container.delete (a job since v26.0.0; force/recursive)
27648
27699
  */
27649
27700
  declare class TrueNasApiClientV26 extends TrueNasApiClient<ApiDirectory$1> {
27650
27701
  /**
@@ -27657,6 +27708,68 @@ declare class TrueNasApiClientV26 extends TrueNasApiClient<ApiDirectory$1> {
27657
27708
  protected createOperations(): OperationMappings;
27658
27709
  }
27659
27710
 
27711
+ /**
27712
+ * TrueNAS API Client for v27.X.Y
27713
+ *
27714
+ * Handles all v27 versions (v27.0.0, v27.0.1, v27.1.2, etc.). Minor and patch
27715
+ * releases within a year are backward compatible, so one implementation covers
27716
+ * the series; breaking changes only arrive with the next year.
27717
+ *
27718
+ * That is what this class supports. What version *discovery* currently admits
27719
+ * is narrower: `MAX_SUPPORTED_VERSION` is a concrete version and the range check
27720
+ * compares patches, so today only `v27.0.0` clears it — `v27.0.1` and `v27.1.0`
27721
+ * are reported too-new and never reach this client. The effect always falls on
27722
+ * the newest series and nothing below it, which is why it has gone unnoticed:
27723
+ * raising the ceiling to v27.0.0 is what made v26.0.1 admissible in the first
27724
+ * place. Closing it means deciding how the ceiling should treat a series rather
27725
+ * than a version, which is a change to the compatibility model and not this
27726
+ * client's to make.
27727
+ *
27728
+ * To add version-specific behavior, override the factory methods:
27729
+ * - createConnection() - for connection-specific changes
27730
+ * - createApi() - for API method changes
27731
+ * - createAuthenticator() - for authentication changes
27732
+ * - createOperations() - for version-specific operation mappings
27733
+ */
27734
+
27735
+ /**
27736
+ * API client for TrueNAS API v27
27737
+ *
27738
+ * Protocol: JSON-RPC 2.0
27739
+ * WebSocket Path: /api/v27.{minor}.{patch}
27740
+ *
27741
+ * Container operations use the native container.* APIs, as v26 does:
27742
+ * - containerQuery → container.query (with response transformation)
27743
+ * - containerStart → container.start (synchronous, emits null)
27744
+ * - containerStop → container.stop (emits Job updates)
27745
+ * - containerRestart → container.stop + container.start (emits Job, then null)
27746
+ * - containerDelete → container.delete (a job since v26.0.0; force/recursive)
27747
+ *
27748
+ * Those four are currently identical to v26's, because v27 inherits all three
27749
+ * container entries the facade touches rather than re-declaring them. Asserted
27750
+ * rather than assumed, and re-runnable: the spec pins all three against v26's,
27751
+ * so the day they diverge is a failure there.
27752
+ *
27753
+ * They are written out here rather than shared with v26 because that is what
27754
+ * this repo's one-client-per-series design is for: the two are the same today
27755
+ * and are expected to diverge — middleware has no `container.restart` yet, and
27756
+ * the chained stop+start below is the workaround for its absence. Factoring the
27757
+ * bodies into a common base would couple two versions that exist in order to
27758
+ * evolve apart, and the coupling would have to be undone by whichever release
27759
+ * diverges first. The `@/generated` types are the guard against them drifting
27760
+ * silently: an entry that changes at v27 stops compiling here.
27761
+ */
27762
+ declare class TrueNasApiClientV27 extends TrueNasApiClient<ApiDirectory> {
27763
+ /**
27764
+ * Create v27-specific operation mappings
27765
+ *
27766
+ * Operations return Observable<Job | null>:
27767
+ * - Async operations emit Job updates until complete
27768
+ * - Sync operations emit null once
27769
+ */
27770
+ protected createOperations(): OperationMappings;
27771
+ }
27772
+
27660
27773
  /**
27661
27774
  * Discovers available API versions from TrueNAS systems.
27662
27775
  *
@@ -27860,4 +27973,4 @@ type ApiError = JsonRpcError | TrueNasError;
27860
27973
  */
27861
27974
  declare function getApiErrorMessage(error: unknown, fallback?: string): string;
27862
27975
 
27863
- 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 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, TrueNasAuthMechanism, type TrueNasDate, 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 };
27976
+ 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 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, 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
@@ -2892,14 +2892,23 @@ var apiVersionConfig = {
2892
2892
  /**
2893
2893
  * Maximum supported API version. Systems above it are rejected.
2894
2894
  *
2895
- * NOT derived, deliberately. This should be the newest generated version by
2896
- * the same argument as MIN, but `instantiateClientForVersion` only maps
2897
- * `25.10` and `26` a v27 system would pass the range check and then throw
2898
- * on client selection. It moves to the newest generated version once a v27
2899
- * client exists. Until then it lags on purpose, and the `satisfies` clause
2900
- * below still pins it to a version that was actually generated.
2895
+ * NOT derived, deliberately and for a different reason than it used to
2896
+ * lag. It sat at v26.0.0 while types for v27 already shipped, because
2897
+ * `CLIENT_BY_VERSION_KEY` had no `27` and a v27 system would have passed the
2898
+ * range check only to throw on client selection. `TrueNasApiClientV27` now
2899
+ * exists, so this moves up with it.
2900
+ *
2901
+ * What it must not become is `SUPPORTED_API_VERSIONS[length - 1]`, the mirror
2902
+ * of how MIN is derived. MIN is safe to derive because the oldest generated
2903
+ * version always has a client — it is the floor the clients were built from.
2904
+ * The ceiling is not symmetric: generating types for v28 does not write a v28
2905
+ * client, so deriving this would re-create the exact gap described above on
2906
+ * the next regeneration, silently. The real invariant is "the newest version
2907
+ * a client can be built for", which lives in `CLIENT_BY_VERSION_KEY`; a
2908
+ * factory test asserts the two agree, which is the check that keeps this
2909
+ * literal honest without importing the factory here.
2901
2910
  */
2902
- MAX_SUPPORTED_VERSION: "v26.0.0",
2911
+ MAX_SUPPORTED_VERSION: "v27.0.0",
2903
2912
  /**
2904
2913
  * Fallback version to use when version discovery fails due to CORS/network errors.
2905
2914
  * When /api/versions returns HTTP status 0 (CORS block, network down, etc.),
@@ -3139,7 +3148,29 @@ var TrueNasApiClientV2510 = class extends TrueNasApiClient {
3139
3148
  containerQuery: () => this.api.query("virt.instance.query", [["type", "=", "CONTAINER"]]).pipe(map((instances) => instances.map(toContainer))),
3140
3149
  containerStart: (id) => this.api.job("virt.instance.start", [id]),
3141
3150
  containerStop: (id, options) => this.api.job("virt.instance.stop", [id, options]),
3142
- containerRestart: (id, options) => this.api.job("virt.instance.restart", [id, options])
3151
+ containerRestart: (id, options) => this.api.job("virt.instance.restart", [id, options]),
3152
+ // Already a job here — `virt.instance.delete` has been one since
3153
+ // v25.10.0 — so this needs no synthesis, only the id. It takes nothing
3154
+ // else: there is no `force` and no `recursive` on this version.
3155
+ //
3156
+ // Unsupported options are reported rather than dropped. `recursive`
3157
+ // destroys child datasets, snapshots and clones irrecoverably, so a
3158
+ // caller who asked for it and silently did not get it has been told
3159
+ // something false about what just happened to their data. Reporting is
3160
+ // all this layer can do — refusing outright would make `ops.containerDelete`
3161
+ // unusable on v25.10 for the ordinary case, which is the case that works.
3162
+ containerDelete: (id, options) => {
3163
+ const unsupported = ["force", "recursive"].filter(
3164
+ (key) => options?.[key]
3165
+ );
3166
+ if (unsupported.length > 0) {
3167
+ this.logger.warn(
3168
+ "containerDelete: v25.10 has no counterpart for these options and will delete without them",
3169
+ { ignored: unsupported, id, method: "virt.instance.delete" }
3170
+ );
3171
+ }
3172
+ return this.api.job("virt.instance.delete", [id]);
3173
+ }
3143
3174
  };
3144
3175
  }
3145
3176
  };
@@ -3207,7 +3238,26 @@ var TrueNasApiClientV26 = class extends TrueNasApiClient {
3207
3238
  )
3208
3239
  )
3209
3240
  );
3210
- }
3241
+ },
3242
+ // A job since v26.0.0 — middleware made deletion long-running (it stops
3243
+ // the container when asked, tears down the libvirt domain and destroys
3244
+ // the dataset), and the generated directory moved it out of `call`
3245
+ // accordingly. `api.job` is what tracks it; `api.call` would not compile.
3246
+ //
3247
+ // Options pass straight through when given: the unified
3248
+ // `ContainerDeleteOptions` is `force`/`recursive`, exactly what the
3249
+ // generated params take.
3250
+ //
3251
+ // When they are not given the argument is *omitted* rather than passed as
3252
+ // `undefined`. `JSON.stringify` renders a trailing `undefined` array
3253
+ // element as `null`, and middleware declares `options: ContainerDeleteOptions`
3254
+ // with a model default and no `| None` — so `[id, null]` is a validation
3255
+ // error rather than "use the defaults", which is the one thing a caller
3256
+ // passing nothing is asking for.
3257
+ containerDelete: (id, options) => this.api.job(
3258
+ "container.delete",
3259
+ options ? [parseInt(id, 10), options] : [parseInt(id, 10)]
3260
+ )
3211
3261
  };
3212
3262
  }
3213
3263
  };
@@ -3222,6 +3272,87 @@ function toContainer2(container) {
3222
3272
  description
3223
3273
  };
3224
3274
  }
3275
+ var TrueNasApiClientV27 = class extends TrueNasApiClient {
3276
+ /**
3277
+ * Create v27-specific operation mappings
3278
+ *
3279
+ * Operations return Observable<Job | null>:
3280
+ * - Async operations emit Job updates until complete
3281
+ * - Sync operations emit null once
3282
+ */
3283
+ createOperations() {
3284
+ return {
3285
+ // A polymorphic `.query`, so it goes through the verb rather than
3286
+ // `call`: the directory types the raw method's response as the five-way
3287
+ // union the server may return, and the verb is what fixes it to a list.
3288
+ containerQuery: () => this.api.query("container.query").pipe(
3289
+ map((containers) => containers.map(toContainer3))
3290
+ ),
3291
+ // container.start is synchronous in v27 - emit null
3292
+ containerStart: (id) => this.api.call("container.start", [parseInt(id, 10)]).pipe(map(() => null)),
3293
+ // container.stop emits job updates
3294
+ containerStop: (id, options) => this.api.job("container.stop", [
3295
+ parseInt(id, 10),
3296
+ {
3297
+ force: options.force,
3298
+ force_after_timeout: options.force
3299
+ }
3300
+ ]),
3301
+ // v27 still has no container.restart - chain stop + start.
3302
+ // Emits Job updates during stop, then null when start completes.
3303
+ containerRestart: (id, options) => {
3304
+ const numericId = parseInt(id, 10);
3305
+ return this.api.job("container.stop", [
3306
+ numericId,
3307
+ {
3308
+ force: options.force,
3309
+ force_after_timeout: options.force
3310
+ }
3311
+ ]).pipe(
3312
+ // Collect all job updates to ensure stop fully completes
3313
+ toArray(),
3314
+ // Re-emit job updates, then call start after stop is done
3315
+ switchMap(
3316
+ (jobUpdates) => concat(
3317
+ from(jobUpdates),
3318
+ this.api.call("container.start", [numericId]).pipe(map(() => null))
3319
+ )
3320
+ )
3321
+ );
3322
+ },
3323
+ // A job since v26.0.0 — middleware made deletion long-running (it stops
3324
+ // the container when asked, tears down the libvirt domain and destroys
3325
+ // the dataset), and the generated directory moved it out of `call`
3326
+ // accordingly. `api.job` is what tracks it; `api.call` would not compile.
3327
+ //
3328
+ // Options pass straight through when given: the unified
3329
+ // `ContainerDeleteOptions` is `force`/`recursive`, exactly what the
3330
+ // generated params take.
3331
+ //
3332
+ // When they are not given the argument is *omitted* rather than passed as
3333
+ // `undefined`. `JSON.stringify` renders a trailing `undefined` array
3334
+ // element as `null`, and middleware declares `options: ContainerDeleteOptions`
3335
+ // with a model default and no `| None` — so `[id, null]` is a validation
3336
+ // error rather than "use the defaults", which is the one thing a caller
3337
+ // passing nothing is asking for.
3338
+ containerDelete: (id, options) => this.api.job(
3339
+ "container.delete",
3340
+ options ? [parseInt(id, 10), options] : [parseInt(id, 10)]
3341
+ )
3342
+ };
3343
+ }
3344
+ };
3345
+ function toContainer3(container) {
3346
+ const { description } = container;
3347
+ return {
3348
+ id: container.id.toString(),
3349
+ name: container.name,
3350
+ status: toAppState(container.status.state),
3351
+ // Optional in the generated entry, required by `Container`.
3352
+ autostart: container.autostart ?? false,
3353
+ description
3354
+ };
3355
+ }
3225
3356
 
3226
3357
  // src/errors/version-discovery.errors.ts
3227
3358
  var VersionDiscoveryError = class extends Error {
@@ -3591,7 +3722,8 @@ function selectRepresentativeFailure(failures) {
3591
3722
  }
3592
3723
  var CLIENT_BY_VERSION_KEY = {
3593
3724
  "25.10": TrueNasApiClientV2510,
3594
- "26": TrueNasApiClientV26
3725
+ "26": TrueNasApiClientV26,
3726
+ "27": TrueNasApiClientV27
3595
3727
  };
3596
3728
  function clientVersionKey(version) {
3597
3729
  if (version.year <= legacyCutoffYear) {
@@ -3637,6 +3769,6 @@ function errorMessageOrDefault(error, fallback) {
3637
3769
  return fallback;
3638
3770
  }
3639
3771
 
3640
- export { AppState, AuthError, AuthErrorCode, InvalidVersionResponseError, JobState, NoCompatibleVersionsError, SUPPORTED_API_VERSIONS, TrueNasApiClient, TrueNasApiClientV2510, TrueNasApiClientV26, TrueNasAuthMechanism, VersionCompatibility, VersionDiscovery, VersionDiscoveryError, VersionDiscoveryNetworkError, VersionDiscoveryTimeoutError, VersionEndpointNotFoundError, VersionTooNewError, VersionTooOldError, consoleLogger, createTrueNasClient, getApiErrorMessage, isJobFinished, noopLogger, v25_10_0_exports as v25_10_0, v25_10_1_exports as v25_10_1, v25_10_2_exports as v25_10_2, v25_10_3_exports as v25_10_3, v25_10_4_exports as v25_10_4, v25_10_5_exports as v25_10_5, v26_0_0_exports as v26_0_0, v27_0_0_exports as v27_0_0 };
3772
+ export { AppState, AuthError, AuthErrorCode, InvalidVersionResponseError, JobState, NoCompatibleVersionsError, SUPPORTED_API_VERSIONS, TrueNasApiClient, TrueNasApiClientV2510, TrueNasApiClientV26, TrueNasApiClientV27, TrueNasAuthMechanism, VersionCompatibility, VersionDiscovery, VersionDiscoveryError, VersionDiscoveryNetworkError, VersionDiscoveryTimeoutError, VersionEndpointNotFoundError, VersionTooNewError, VersionTooOldError, consoleLogger, createTrueNasClient, getApiErrorMessage, isJobFinished, noopLogger, v25_10_0_exports as v25_10_0, v25_10_1_exports as v25_10_1, v25_10_2_exports as v25_10_2, v25_10_3_exports as v25_10_3, v25_10_4_exports as v25_10_4, v25_10_5_exports as v25_10_5, v26_0_0_exports as v26_0_0, v27_0_0_exports as v27_0_0 };
3641
3773
  //# sourceMappingURL=index.js.map
3642
3774
  //# sourceMappingURL=index.js.map