@homebridge-plugins/homebridge-august 3.1.4 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/connectivity-manager.d.ts.map +1 -1
- package/dist/connectivity-manager.js +37 -18
- package/dist/connectivity-manager.js.map +1 -1
- package/dist/package.json +3 -3
- package/docs/variables/default.html +1 -1
- package/package.json +3 -3
- package/test/connectivity-manager.test.ts +84 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
## [3.1.4](https://github.com/homebridge-plugins/homebridge-august/compare/v3.1.3...v3.1.4) (2026-04-27)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **platform:** destroy August client on session refresh instead of end() ([a12f2b3](https://github.com/homebridge-plugins/homebridge-august/commit/a12f2b328263523eef3b2549383f00ce6dfbf0a1))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **lock:** wire PubNub reconnect signal into ConnectivityManager ([462b22c](https://github.com/homebridge-plugins/homebridge-august/commit/462b22c5b53e125d3ec31eceea538a74360f5760))
|
|
12
|
+
* **platform:** add ConnectivityManager (unwired) ([6377ac4](https://github.com/homebridge-plugins/homebridge-august/commit/6377ac435320aa884e82b32f25f163b2bd9fde6a))
|
|
13
|
+
* **platform:** platform-level serial poller, drop per-lock interval/retry ([aa973a4](https://github.com/homebridge-plugins/homebridge-august/commit/aa973a4e46cd4252f335a5c6988f94148cafefbf))
|
|
14
|
+
* **platform:** route pushChanges through ConnectivityManager ([41080f4](https://github.com/homebridge-plugins/homebridge-august/commit/41080f490cd71b504e22f56a80ae6e1c8c9eb016))
|
|
15
|
+
* **platform:** wire ConnectivityManager into AugustPlatform ([0ce28e3](https://github.com/homebridge-plugins/homebridge-august/commit/0ce28e359a68720ed278e17097f61262ea8705b4))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
1
19
|
## [3.1.2](https://github.com/homebridge-plugins/homebridge-august/compare/v3.1.1...v3.1.2) (2026-04-18)
|
|
2
20
|
|
|
3
21
|
### Bug Fixes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connectivity-manager.d.ts","sourceRoot":"","sources":["../src/connectivity-manager.ts"],"names":[],"mappings":"AA2CA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAEzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD,OAAO,
|
|
1
|
+
{"version":3,"file":"connectivity-manager.d.ts","sourceRoot":"","sources":["../src/connectivity-manager.ts"],"names":[],"mappings":"AA2CA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAEzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD,OAAO,MAAiE,MAAM,aAAa,CAAA;AAE3F,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,YAAY,CAAA;AAcjF,UAAU,cAAc;IACtB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,qBAAa,YAAa,SAAQ,KAAK;gBACzB,KAAK,EAAE,MAAM;CAI1B;AAED,qBAAa,mBAAmB;IAS5B,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,CAAC,eAAe;IAjBlC,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,MAAM,CAAC,CAAQ;IACvB,OAAO,CAAC,UAAU,CAAC,CAAgB;IACnC,OAAO,CAAC,YAAY,CAAI;IACxB,OAAO,CAAC,eAAe,CAAC,CAAe;IACvC,OAAO,CAAC,SAAS,CAAwE;gBAGtE,GAAG,EAAE,OAAO,EACZ,kBAAkB,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC;IAC/D;;;;;;OAMG;IACc,eAAe,GAAE,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,KAAK,IAAe;IAG7E,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B;;;;;;;;;;;;OAYG;IACG,OAAO,CAAC,CAAC,EACb,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EAClC,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAgCzB;;;;;OAKG;IACH,iBAAiB,IAAI,IAAI;IASzB,QAAQ,IAAI,iBAAiB;IAI7B;;;;;OAKG;IACH,SAAS,IAAI,MAAM,GAAG,SAAS;IAI/B;;;;OAIG;IACH,aAAa,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,iBAAiB,KAAK,IAAI,GAAG,MAAM,IAAI;IAKxF,QAAQ,IAAI,IAAI;IAUhB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,aAAa;IAqBrB,OAAO,CAAC,aAAa;YAQP,QAAQ;YA8BR,aAAa;IAkB3B,OAAO,CAAC,QAAQ;IAkDhB,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,eAAe;CAMxB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import August, { TimeoutError } from 'august-yale';
|
|
1
|
+
import August, { AbortedError, InvalidAuth, NetworkError, TimeoutError } from 'august-yale';
|
|
2
2
|
/**
|
|
3
3
|
* Backoff schedule for probes after the network is detected as broken.
|
|
4
4
|
* Capped at 5 minutes; ±10% jitter is applied at use to avoid synchronized
|
|
@@ -7,16 +7,6 @@ import August, { TimeoutError } from 'august-yale';
|
|
|
7
7
|
const BACKOFF_SCHEDULE_MS = [5_000, 10_000, 20_000, 40_000, 80_000, 160_000, 300_000];
|
|
8
8
|
/** Probe timeout — short on purpose. A healthy August API responds in <1s. */
|
|
9
9
|
const PROBE_TIMEOUT_MS = 8_000;
|
|
10
|
-
/** Network error codes that classify() treats as connectivity failures. */
|
|
11
|
-
const NETWORK_ERROR_CODES = new Set([
|
|
12
|
-
'ECONNRESET',
|
|
13
|
-
'ENETUNREACH',
|
|
14
|
-
'EHOSTUNREACH',
|
|
15
|
-
'ENOTFOUND',
|
|
16
|
-
'ECONNREFUSED',
|
|
17
|
-
'EAI_AGAIN',
|
|
18
|
-
'ETIMEDOUT',
|
|
19
|
-
]);
|
|
20
10
|
export class OfflineError extends Error {
|
|
21
11
|
constructor(label) {
|
|
22
12
|
super(`Operation skipped — connectivity is offline: ${label}`);
|
|
@@ -220,22 +210,51 @@ export class ConnectivityManager {
|
|
|
220
210
|
}
|
|
221
211
|
}
|
|
222
212
|
classify(e) {
|
|
223
|
-
|
|
224
|
-
|
|
213
|
+
// august-yale wraps every transport-level fetch failure into one of
|
|
214
|
+
// its typed exceptions before the error reaches us. We rely on those
|
|
215
|
+
// types here rather than re-implementing undici's 24-class taxonomy.
|
|
216
|
+
//
|
|
217
|
+
// - NetworkError (and its TimeoutError subclass) covers connect
|
|
218
|
+
// timeouts, socket resets, headers/body timeouts, DNS failures,
|
|
219
|
+
// TLS proxy failures, malformed responses, etc.
|
|
220
|
+
//
|
|
221
|
+
// - AbortedError reflects an in-flight request racing with our own
|
|
222
|
+
// teardown (e.g. during rebuildClient). NOT 'network': the consumer
|
|
223
|
+
// intent was to tear down, so we don't want this to drive the
|
|
224
|
+
// state machine into degraded.
|
|
225
|
+
//
|
|
226
|
+
// - InvalidAuth is august-yale's auth-failure type. Maps to 'auth'.
|
|
227
|
+
//
|
|
228
|
+
// Anything else (including programmer errors and server-answered
|
|
229
|
+
// 4xx/5xx that august-yale leaves unwrapped) is 'transient' — bubble
|
|
230
|
+
// back to the caller, don't change connectivity state.
|
|
231
|
+
if (e instanceof NetworkError) {
|
|
225
232
|
return 'network';
|
|
226
233
|
}
|
|
227
|
-
if (
|
|
228
|
-
return '
|
|
234
|
+
if (e instanceof AbortedError) {
|
|
235
|
+
return 'transient';
|
|
229
236
|
}
|
|
230
|
-
if (
|
|
237
|
+
if (e instanceof TimeoutError) {
|
|
238
|
+
// Defensive: TimeoutError is also a NetworkError so the first
|
|
239
|
+
// check should match. Kept for clarity in case of future
|
|
240
|
+
// exception hierarchy changes upstream.
|
|
231
241
|
return 'network';
|
|
232
242
|
}
|
|
233
|
-
if (
|
|
234
|
-
return '
|
|
243
|
+
if (e instanceof InvalidAuth) {
|
|
244
|
+
return 'auth';
|
|
235
245
|
}
|
|
246
|
+
// Fallback for HTTP-level errors that august-yale leaves unwrapped
|
|
247
|
+
// (e.g. server answered with a non-2xx without bare-401 semantics).
|
|
248
|
+
const err = e;
|
|
236
249
|
if (err?.statusCode === 401) {
|
|
237
250
|
return 'auth';
|
|
238
251
|
}
|
|
252
|
+
if (err?.statusCode === 502 || err?.statusCode === 503 || err?.statusCode === 504) {
|
|
253
|
+
// 5xx responses where the server is reachable but reporting an
|
|
254
|
+
// upstream issue. Treat as network — these are recoverable by
|
|
255
|
+
// waiting and retrying (matches the state-machine semantic).
|
|
256
|
+
return 'network';
|
|
257
|
+
}
|
|
239
258
|
return 'transient';
|
|
240
259
|
}
|
|
241
260
|
transitionTo(next) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connectivity-manager.js","sourceRoot":"","sources":["../src/connectivity-manager.ts"],"names":[],"mappings":"AA+CA,OAAO,MAAM,EAAE,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"connectivity-manager.js","sourceRoot":"","sources":["../src/connectivity-manager.ts"],"names":[],"mappings":"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"}
|
package/dist/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@homebridge-plugins/homebridge-august",
|
|
3
3
|
"displayName": "August",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "3.
|
|
5
|
+
"version": "3.2.0",
|
|
6
6
|
"description": "The August plugin allows you to access your August & Yale device(s) from HomeKit.",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "donavanbecker",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
64
|
"@homebridge/plugin-ui-utils": "^2.2.3",
|
|
65
|
-
"august-yale": "^1.
|
|
65
|
+
"august-yale": "^1.2.0",
|
|
66
66
|
"rxjs": "^7.8.2"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
@@ -80,4 +80,4 @@
|
|
|
80
80
|
"typescript": "^6.0.3",
|
|
81
81
|
"vitest": "^4.1.5"
|
|
82
82
|
}
|
|
83
|
-
}
|
|
83
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>default | @homebridge-plugins/homebridge-august</title><meta name="description" content="Documentation for @homebridge-plugins/homebridge-august"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">@homebridge-plugins/homebridge-august</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="" aria-current="page">default</a></li></ul><h1>Variable default</h1></div><div class="tsd-signature"><span class="tsd-kind-variable">default</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span> <span class="tsd-signature-symbol">=></span> <span class="tsd-signature-type">void</span></div><div class="tsd-type-declaration"><h4>Type Declaration</h4><ul class="tsd-parameters"><li class="tsd-parameter-signature"><ul class="tsd-signatures"><li class="tsd-signature" id="__type"><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">void</span></li><li class="tsd-description"><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">api</span>: <span class="tsd-signature-type">API</span></span></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4></li></ul></li></ul></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/homebridge-plugins/homebridge-august/blob/
|
|
1
|
+
<!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>default | @homebridge-plugins/homebridge-august</title><meta name="description" content="Documentation for @homebridge-plugins/homebridge-august"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">@homebridge-plugins/homebridge-august</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="" aria-current="page">default</a></li></ul><h1>Variable default</h1></div><div class="tsd-signature"><span class="tsd-kind-variable">default</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span> <span class="tsd-signature-symbol">=></span> <span class="tsd-signature-type">void</span></div><div class="tsd-type-declaration"><h4>Type Declaration</h4><ul class="tsd-parameters"><li class="tsd-parameter-signature"><ul class="tsd-signatures"><li class="tsd-signature" id="__type"><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">void</span></li><li class="tsd-description"><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">api</span>: <span class="tsd-signature-type">API</span></span></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4></li></ul></li></ul></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/homebridge-plugins/homebridge-august/blob/93219accdf8571330b8f3fefa029d727ddf7a6c3/src/index.ts#L26">index.ts:26</a></li></ul></aside></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">@homebridge-plugins/homebridge-august</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer></footer><div class="overlay"></div></body></html>
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@homebridge-plugins/homebridge-august",
|
|
3
3
|
"displayName": "August",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "3.
|
|
5
|
+
"version": "3.2.0",
|
|
6
6
|
"description": "The August plugin allows you to access your August & Yale device(s) from HomeKit.",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "donavanbecker",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
64
|
"@homebridge/plugin-ui-utils": "^2.2.3",
|
|
65
|
-
"august-yale": "^1.
|
|
65
|
+
"august-yale": "^1.2.0",
|
|
66
66
|
"rxjs": "^7.8.2"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
@@ -80,4 +80,4 @@
|
|
|
80
80
|
"typescript": "^6.0.3",
|
|
81
81
|
"vitest": "^4.1.5"
|
|
82
82
|
}
|
|
83
|
-
}
|
|
83
|
+
}
|
|
@@ -17,14 +17,45 @@ import { ConnectivityManager, OfflineError } from '../src/connectivity-manager.j
|
|
|
17
17
|
|
|
18
18
|
// Mock the august-yale module. We need:
|
|
19
19
|
// - August: a constructor we can instantiate, with details() and destroy()
|
|
20
|
-
// -
|
|
20
|
+
// - The full exception hierarchy that classify() now uses for routing:
|
|
21
|
+
// NetworkError, TimeoutError (subclass), AbortedError, InvalidAuth.
|
|
21
22
|
vi.mock('august-yale', () => {
|
|
22
|
-
class
|
|
23
|
-
|
|
23
|
+
class YaleApiError extends Error {
|
|
24
|
+
public originalError?: Error
|
|
25
|
+
constructor(message?: string, originalError?: Error) {
|
|
24
26
|
super(message)
|
|
27
|
+
this.name = 'YaleApiError'
|
|
28
|
+
this.originalError = originalError
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
class NetworkError extends YaleApiError {
|
|
32
|
+
public code?: string
|
|
33
|
+
constructor(message?: string, originalError?: Error, code?: string) {
|
|
34
|
+
super(message, originalError)
|
|
35
|
+
this.name = 'NetworkError'
|
|
36
|
+
this.code = code
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
class TimeoutError extends NetworkError {
|
|
40
|
+
constructor(message?: string, originalError?: Error, code?: string) {
|
|
41
|
+
super(message, originalError, code)
|
|
25
42
|
this.name = 'TimeoutError'
|
|
26
43
|
}
|
|
27
44
|
}
|
|
45
|
+
class AbortedError extends YaleApiError {
|
|
46
|
+
public code?: string
|
|
47
|
+
constructor(message?: string, originalError?: Error, code?: string) {
|
|
48
|
+
super(message, originalError)
|
|
49
|
+
this.name = 'AbortedError'
|
|
50
|
+
this.code = code
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
class InvalidAuth extends YaleApiError {
|
|
54
|
+
constructor(message?: string, originalError?: Error) {
|
|
55
|
+
super(message, originalError)
|
|
56
|
+
this.name = 'InvalidAuth'
|
|
57
|
+
}
|
|
58
|
+
}
|
|
28
59
|
// Each new August() returns a unique object so tests can assert which
|
|
29
60
|
// client is being used (initial vs. rebuilt).
|
|
30
61
|
let nextId = 0
|
|
@@ -43,7 +74,11 @@ vi.mock('august-yale', () => {
|
|
|
43
74
|
})
|
|
44
75
|
return {
|
|
45
76
|
default: MockAugust,
|
|
77
|
+
YaleApiError,
|
|
78
|
+
NetworkError,
|
|
46
79
|
TimeoutError,
|
|
80
|
+
AbortedError,
|
|
81
|
+
InvalidAuth,
|
|
47
82
|
}
|
|
48
83
|
})
|
|
49
84
|
|
|
@@ -188,23 +223,57 @@ describe('ConnectivityManager', () => {
|
|
|
188
223
|
expect(m.getState()).toBe('degraded')
|
|
189
224
|
})
|
|
190
225
|
|
|
191
|
-
it('treats
|
|
226
|
+
it('treats NetworkError as network and transitions to degraded', async () => {
|
|
227
|
+
// NetworkError covers all transport-level failures from august-yale —
|
|
228
|
+
// socket reset, DNS failure, malformed response, etc. — without us
|
|
229
|
+
// having to enumerate undici's 24 error classes.
|
|
192
230
|
const m = new ConnectivityManager(makeLog(), fakeCredentials)
|
|
193
231
|
await m.init()
|
|
194
|
-
const
|
|
195
|
-
await m.execute('test', async () => { throw
|
|
232
|
+
const { NetworkError } = await import('august-yale')
|
|
233
|
+
const result = await m.execute('test', async () => { throw new NetworkError('socket hang up', undefined, 'ECONNRESET') })
|
|
234
|
+
expect(result).toBeUndefined()
|
|
196
235
|
expect(m.getState()).toBe('degraded')
|
|
197
236
|
})
|
|
198
237
|
|
|
199
|
-
it('treats
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
238
|
+
it('treats InvalidAuth as auth and rebuilds without changing state', async () => {
|
|
239
|
+
const onClientChanged = vi.fn()
|
|
240
|
+
const m = new ConnectivityManager(makeLog(), fakeCredentials, onClientChanged)
|
|
241
|
+
await m.init()
|
|
242
|
+
expect(onClientChanged).toHaveBeenCalledTimes(1)
|
|
243
|
+
const { InvalidAuth } = await import('august-yale')
|
|
244
|
+
const result = await m.execute('test', async () => { throw new InvalidAuth('session expired') })
|
|
245
|
+
expect(result).toBeUndefined()
|
|
246
|
+
await vi.runAllTimersAsync()
|
|
247
|
+
expect(onClientChanged).toHaveBeenCalledTimes(2)
|
|
248
|
+
expect(m.getState()).toBe('healthy')
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
it('treats AbortedError as transient and does NOT change connectivity state', async () => {
|
|
252
|
+
// AbortedError reflects a request racing with our own teardown
|
|
253
|
+
// (e.g. inside rebuildClient). Treating it as 'network' would
|
|
254
|
+
// make the state machine fight itself: every rebuild produces
|
|
255
|
+
// ClientDestroyedError -> degraded -> probe -> rebuild ->
|
|
256
|
+
// ClientDestroyedError -> ...
|
|
257
|
+
const m = new ConnectivityManager(makeLog(), fakeCredentials)
|
|
258
|
+
await m.init()
|
|
259
|
+
const { AbortedError } = await import('august-yale')
|
|
260
|
+
const err = new AbortedError('client destroyed', undefined, 'UND_ERR_DESTROYED')
|
|
261
|
+
await expect(
|
|
262
|
+
m.execute('test', async () => { throw err }),
|
|
263
|
+
).rejects.toBe(err)
|
|
264
|
+
// State stays healthy — no probe scheduled.
|
|
265
|
+
expect(m.getState()).toBe('healthy')
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
it('treats 502/503/504 as network errors (HTTP-level fallback)', async () => {
|
|
269
|
+
// Most transport failures are now wrapped upstream as NetworkError,
|
|
270
|
+
// but if august-yale ever surfaces a clean HTTP 5xx response, we
|
|
271
|
+
// still want to recognize 502/503/504 as network-class and probe.
|
|
272
|
+
const m = new ConnectivityManager(makeLog(), fakeCredentials)
|
|
273
|
+
await m.init()
|
|
274
|
+
const err = Object.assign(new Error('Bad Gateway'), { statusCode: 502 })
|
|
275
|
+
await m.execute('test', async () => { throw err })
|
|
276
|
+
expect(m.getState()).toBe('degraded')
|
|
208
277
|
})
|
|
209
278
|
})
|
|
210
279
|
|