@truenas/api-client 3.0.6 → 3.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -12476,6 +12476,14 @@ interface ActiveConnection {
12476
12476
  }
12477
12477
  interface ConnectionError extends Error {
12478
12478
  hostname?: string;
12479
+ /** The WebSocket close code, when the failure came from a close rather than a timeout. */
12480
+ closeCode?: number;
12481
+ /**
12482
+ * The server's own reason text, verbatim. `message` is this client's rendering
12483
+ * of the code and loses what the appliance actually said — for a policy close
12484
+ * that is the difference between "policy violation" and which policy.
12485
+ */
12486
+ closeReason?: string;
12479
12487
  }
12480
12488
  type Connection = ActiveConnection & {
12481
12489
  state: 'active';
@@ -12568,6 +12576,11 @@ declare class TrueNasConnection {
12568
12576
  /**
12569
12577
  * enables or disables the connection gate. the app calls this when its `SystemState`
12570
12578
  * changes (mapping `SystemState.Active -> true`, everything else -> `false`).
12579
+ *
12580
+ * This is also how a caller asks for another attempt after the appliance has
12581
+ * refused the client — nothing reconnects on its own from there. The gate is
12582
+ * `distinctUntilChanged`, so re-asserting `true` while it is already `true`
12583
+ * does nothing: the round trip through `false` is what asks again.
12571
12584
  */
12572
12585
  setEnabled(enabled: boolean): void;
12573
12586
  /**
package/dist/index.d.ts CHANGED
@@ -12476,6 +12476,14 @@ interface ActiveConnection {
12476
12476
  }
12477
12477
  interface ConnectionError extends Error {
12478
12478
  hostname?: string;
12479
+ /** The WebSocket close code, when the failure came from a close rather than a timeout. */
12480
+ closeCode?: number;
12481
+ /**
12482
+ * The server's own reason text, verbatim. `message` is this client's rendering
12483
+ * of the code and loses what the appliance actually said — for a policy close
12484
+ * that is the difference between "policy violation" and which policy.
12485
+ */
12486
+ closeReason?: string;
12479
12487
  }
12480
12488
  type Connection = ActiveConnection & {
12481
12489
  state: 'active';
@@ -12568,6 +12576,11 @@ declare class TrueNasConnection {
12568
12576
  /**
12569
12577
  * enables or disables the connection gate. the app calls this when its `SystemState`
12570
12578
  * changes (mapping `SystemState.Active -> true`, everything else -> `false`).
12579
+ *
12580
+ * This is also how a caller asks for another attempt after the appliance has
12581
+ * refused the client — nothing reconnects on its own from there. The gate is
12582
+ * `distinctUntilChanged`, so re-asserting `true` while it is already `true`
12583
+ * does nothing: the round trip through `false` is what asks again.
12571
12584
  */
12572
12585
  setEnabled(enabled: boolean): void;
12573
12586
  /**
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { map, toArray, switchMap, concat, from, defer, throwError, firstValueFrom, BehaviorSubject, Subject, distinctUntilChanged, of, filter, take, catchError as catchError$1, retry, startWith, shareReplay as shareReplay$1, takeUntil, EMPTY, combineLatest, interval, Observable, timeout, timer, race, tap, share, finalize, merge, takeWhile } from 'rxjs';
1
+ import { map, toArray, switchMap, concat, from, defer, throwError, firstValueFrom, BehaviorSubject, Subject, distinctUntilChanged, catchError as catchError$1, of, filter, take, retry, startWith, shareReplay as shareReplay$1, takeUntil, EMPTY, combineLatest, interval, Observable, timeout, timer, race, tap, share, finalize, merge, takeWhile } from 'rxjs';
2
2
  import { webSocket } from 'rxjs/webSocket';
3
3
  import { map as map$1, catchError, shareReplay } from 'rxjs/operators';
4
4
 
@@ -2834,6 +2834,7 @@ var noopLogger = {
2834
2834
  };
2835
2835
 
2836
2836
  // src/utils/truenas-connection.utils.ts
2837
+ var policyViolationCloseCode = 1008;
2837
2838
  function isHttpStatusError(reason) {
2838
2839
  return ["404", "502", "503"].some((code) => reason.includes(code));
2839
2840
  }
@@ -2942,7 +2943,25 @@ var TrueNasConnection = class {
2942
2943
  switchMap((enabled) => {
2943
2944
  if (enabled) {
2944
2945
  return this.connect().pipe(
2945
- map((conn) => makeActiveConnection(conn.ws, conn.hostname))
2946
+ map((conn) => makeActiveConnection(conn.ws, conn.hostname)),
2947
+ // A refusal becomes a value here rather than an error, so it never
2948
+ // reaches the `retry` below and nothing reconnects on its own.
2949
+ //
2950
+ // Handled at this depth on purpose: letting it out completes the
2951
+ // pipeline and unsubscribes `enabledChange$`, and `setEnabled` is the
2952
+ // documented way an app asks for another attempt once the network
2953
+ // changes. Not retrying is a statement about what this client does on
2954
+ // its own; it is not a reason to refuse the caller asking again.
2955
+ catchError$1(
2956
+ (err) => isTerminalClose(err) ? of(
2957
+ makeConnectionError(
2958
+ err.message,
2959
+ err.hostname,
2960
+ err.closeCode,
2961
+ err.closeReason
2962
+ )
2963
+ ) : throwError(() => err)
2964
+ )
2946
2965
  );
2947
2966
  }
2948
2967
  return of(closedConnection);
@@ -2968,7 +2987,14 @@ var TrueNasConnection = class {
2968
2987
  catchError$1((err) => {
2969
2988
  this.logger.error("All connections failed - retrying", { message: err?.message, hostname: err?.hostname });
2970
2989
  return concat(
2971
- of(makeConnectionError(err.message, err.hostname)),
2990
+ of(
2991
+ makeConnectionError(
2992
+ err.message,
2993
+ err.hostname,
2994
+ err.closeCode,
2995
+ err.closeReason
2996
+ )
2997
+ ),
2972
2998
  // since this error will immediately get caught by `retry` there's no reason to build a real error.
2973
2999
  throwError(() => null)
2974
3000
  );
@@ -3077,6 +3103,11 @@ var TrueNasConnection = class {
3077
3103
  /**
3078
3104
  * enables or disables the connection gate. the app calls this when its `SystemState`
3079
3105
  * changes (mapping `SystemState.Active -> true`, everything else -> `false`).
3106
+ *
3107
+ * This is also how a caller asks for another attempt after the appliance has
3108
+ * refused the client — nothing reconnects on its own from there. The gate is
3109
+ * `distinctUntilChanged`, so re-asserting `true` while it is already `true`
3110
+ * does nothing: the round trip through `false` is what asks again.
3080
3111
  */
3081
3112
  setEnabled(enabled) {
3082
3113
  this.enabled$.next(enabled);
@@ -3134,7 +3165,9 @@ var TrueNasConnection = class {
3134
3165
  errorMessage = getWebSocketError(event.code);
3135
3166
  }
3136
3167
  this.connectionAttempts.next(this.connectionAttempts.value + 1);
3137
- subscriber.error(makeConnectionError(errorMessage, hostname));
3168
+ subscriber.error(
3169
+ makeConnectionError(errorMessage, hostname, event.code, reason)
3170
+ );
3138
3171
  }
3139
3172
  }
3140
3173
  });
@@ -3184,12 +3217,15 @@ var makeActiveConnection = (ws, hostname) => ({
3184
3217
  hostname,
3185
3218
  state: "active"
3186
3219
  });
3187
- var makeConnectionError = (message, hostname) => ({
3220
+ var makeConnectionError = (message, hostname, closeCode, closeReason) => ({
3188
3221
  name: "ConnectionError",
3189
3222
  message,
3190
3223
  hostname,
3224
+ closeCode,
3225
+ closeReason,
3191
3226
  state: "error"
3192
3227
  });
3228
+ var isTerminalClose = (err) => err?.closeCode === policyViolationCloseCode;
3193
3229
  var closedConnection = { state: "closed" };
3194
3230
 
3195
3231
  // src/client/truenas-api-client.ts