homebridge-plugin-utils 1.35.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +130 -2
- package/build/eslint-plugin/README.md +164 -0
- package/build/eslint-plugin/config.mjs +308 -0
- package/build/eslint-plugin/index.mjs +7 -0
- package/build/eslint-plugin/plugin.mjs +46 -0
- package/build/eslint-plugin/rules/blank-line-after-open-brace.mjs +137 -0
- package/build/eslint-plugin/rules/blank-line-after-open-brace.test.mjs +112 -0
- package/build/eslint-plugin/rules/comment-style.mjs +190 -0
- package/build/eslint-plugin/rules/comment-style.test.mjs +190 -0
- package/build/eslint-plugin/rules/enforce-node-protocol.mjs +114 -0
- package/build/eslint-plugin/rules/enforce-node-protocol.test.mjs +116 -0
- package/build/eslint-plugin/rules/paren-comparisons-in-logical.mjs +94 -0
- package/build/eslint-plugin/rules/paren-comparisons-in-logical.test.mjs +107 -0
- package/build/eslint-plugin/rules/split-type-imports.mjs +354 -0
- package/build/eslint-plugin/rules/split-type-imports.test.mjs +268 -0
- package/build/eslint-plugin/test-setup.mjs +21 -0
- package/build/fs-ops.mjs +184 -0
- package/build/tsconfig.json +18 -3
- package/dist/backpressure.d.ts +94 -45
- package/dist/backpressure.js +229 -93
- package/dist/backpressure.js.map +1 -1
- package/dist/cli/index.d.ts +166 -0
- package/dist/cli/index.js +551 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/clock-double.d.ts +93 -0
- package/dist/clock-double.js +141 -0
- package/dist/clock-double.js.map +1 -0
- package/dist/clock.d.ts +39 -0
- package/dist/clock.js +34 -0
- package/dist/clock.js.map +1 -0
- package/dist/disposable-stack.d.ts +59 -0
- package/dist/disposable-stack.js +155 -0
- package/dist/disposable-stack.js.map +1 -0
- package/dist/docChrome.d.ts +260 -0
- package/dist/docChrome.js +361 -0
- package/dist/docChrome.js.map +1 -0
- package/dist/eslint-plugin/config.d.mts +193 -0
- package/dist/eslint-plugin/index.d.mts +2 -0
- package/dist/eslint-plugin/plugin.d.mts +87 -0
- package/dist/eslint-plugin/rules/blank-line-after-open-brace.d.mts +19 -0
- package/dist/eslint-plugin/rules/comment-style.d.mts +15 -0
- package/dist/eslint-plugin/rules/enforce-node-protocol.d.mts +18 -0
- package/dist/eslint-plugin/rules/paren-comparisons-in-logical.d.mts +15 -0
- package/dist/eslint-plugin/rules/split-type-imports.d.mts +16 -0
- package/dist/featureOptions-docs.d.ts +96 -0
- package/dist/featureOptions-docs.js +193 -0
- package/dist/featureOptions-docs.js.map +1 -0
- package/dist/featureOptions.d.ts +674 -0
- package/dist/featureOptions.js +870 -0
- package/dist/featureOptions.js.map +1 -0
- package/dist/ffmpeg/codecs.d.ts +256 -72
- package/dist/ffmpeg/codecs.js +477 -262
- package/dist/ffmpeg/codecs.js.map +1 -1
- package/dist/ffmpeg/dgram-util.d.ts +46 -0
- package/dist/ffmpeg/dgram-util.js +38 -0
- package/dist/ffmpeg/dgram-util.js.map +1 -0
- package/dist/ffmpeg/exec.d.ts +83 -64
- package/dist/ffmpeg/exec.js +77 -86
- package/dist/ffmpeg/exec.js.map +1 -1
- package/dist/ffmpeg/fmp4.d.ts +49 -2
- package/dist/ffmpeg/fmp4.js +47 -11
- package/dist/ffmpeg/fmp4.js.map +1 -1
- package/dist/ffmpeg/hap-enums.d.ts +214 -0
- package/dist/ffmpeg/hap-enums.js +92 -0
- package/dist/ffmpeg/hap-enums.js.map +1 -0
- package/dist/ffmpeg/index.d.ts +16 -9
- package/dist/ffmpeg/index.js +6 -0
- package/dist/ffmpeg/index.js.map +1 -1
- package/dist/ffmpeg/mp4-assembler.d.ts +161 -0
- package/dist/ffmpeg/mp4-assembler.js +424 -0
- package/dist/ffmpeg/mp4-assembler.js.map +1 -0
- package/dist/ffmpeg/mp4-parser.d.ts +94 -0
- package/dist/ffmpeg/mp4-parser.js +130 -0
- package/dist/ffmpeg/mp4-parser.js.map +1 -0
- package/dist/ffmpeg/options.d.ts +62 -149
- package/dist/ffmpeg/options.js +608 -499
- package/dist/ffmpeg/options.js.map +1 -1
- package/dist/ffmpeg/process.d.ts +142 -96
- package/dist/ffmpeg/process.js +406 -278
- package/dist/ffmpeg/process.js.map +1 -1
- package/dist/ffmpeg/record.d.ts +325 -186
- package/dist/ffmpeg/record.js +418 -565
- package/dist/ffmpeg/record.js.map +1 -1
- package/dist/ffmpeg/recording-process-double.d.ts +157 -0
- package/dist/ffmpeg/recording-process-double.js +190 -0
- package/dist/ffmpeg/recording-process-double.js.map +1 -0
- package/dist/ffmpeg/rtp-parser.d.ts +70 -0
- package/dist/ffmpeg/rtp-parser.js +77 -0
- package/dist/ffmpeg/rtp-parser.js.map +1 -0
- package/dist/ffmpeg/rtp.d.ts +198 -141
- package/dist/ffmpeg/rtp.js +474 -251
- package/dist/ffmpeg/rtp.js.map +1 -1
- package/dist/ffmpeg/settings.d.ts +5 -2
- package/dist/ffmpeg/settings.js +20 -5
- package/dist/ffmpeg/settings.js.map +1 -1
- package/dist/ffmpeg/stream.d.ts +57 -107
- package/dist/ffmpeg/stream.js +121 -150
- package/dist/ffmpeg/stream.js.map +1 -1
- package/dist/formatters.d.ts +106 -0
- package/dist/formatters.js +174 -0
- package/dist/formatters.js.map +1 -0
- package/dist/homebridge-enums.d.ts +30 -0
- package/dist/homebridge-enums.js +17 -0
- package/dist/homebridge-enums.js.map +1 -0
- package/dist/index.d.ts +13 -6
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/logclient/auth.d.ts +114 -0
- package/dist/logclient/auth.js +199 -0
- package/dist/logclient/auth.js.map +1 -0
- package/dist/logclient/cli-run.d.ts +76 -0
- package/dist/logclient/cli-run.js +639 -0
- package/dist/logclient/cli-run.js.map +1 -0
- package/dist/logclient/cli.d.ts +3 -0
- package/dist/logclient/cli.js +97 -0
- package/dist/logclient/cli.js.map +1 -0
- package/dist/logclient/client.d.ts +145 -0
- package/dist/logclient/client.js +600 -0
- package/dist/logclient/client.js.map +1 -0
- package/dist/logclient/config.d.ts +173 -0
- package/dist/logclient/config.js +199 -0
- package/dist/logclient/config.js.map +1 -0
- package/dist/logclient/endpoints.d.ts +54 -0
- package/dist/logclient/endpoints.js +73 -0
- package/dist/logclient/endpoints.js.map +1 -0
- package/dist/logclient/filter.d.ts +45 -0
- package/dist/logclient/filter.js +51 -0
- package/dist/logclient/filter.js.map +1 -0
- package/dist/logclient/frame.d.ts +93 -0
- package/dist/logclient/frame.js +203 -0
- package/dist/logclient/frame.js.map +1 -0
- package/dist/logclient/index.d.ts +31 -0
- package/dist/logclient/index.js +12 -0
- package/dist/logclient/index.js.map +1 -0
- package/dist/logclient/parser.d.ts +211 -0
- package/dist/logclient/parser.js +393 -0
- package/dist/logclient/parser.js.map +1 -0
- package/dist/logclient/rest.d.ts +41 -0
- package/dist/logclient/rest.js +111 -0
- package/dist/logclient/rest.js.map +1 -0
- package/dist/logclient/settings.d.ts +15 -0
- package/dist/logclient/settings.js +64 -0
- package/dist/logclient/settings.js.map +1 -0
- package/dist/logclient/socket-double.d.ts +201 -0
- package/dist/logclient/socket-double.js +384 -0
- package/dist/logclient/socket-double.js.map +1 -0
- package/dist/logclient/socket.d.ts +257 -0
- package/dist/logclient/socket.js +620 -0
- package/dist/logclient/socket.js.map +1 -0
- package/dist/logclient/stitch.d.ts +83 -0
- package/dist/logclient/stitch.js +146 -0
- package/dist/logclient/stitch.js.map +1 -0
- package/dist/logclient/time-expression.d.ts +42 -0
- package/dist/logclient/time-expression.js +181 -0
- package/dist/logclient/time-expression.js.map +1 -0
- package/dist/logclient/time-window.d.ts +38 -0
- package/dist/logclient/time-window.js +53 -0
- package/dist/logclient/time-window.js.map +1 -0
- package/dist/logclient/types.d.ts +107 -0
- package/dist/logclient/types.js +6 -0
- package/dist/logclient/types.js.map +1 -0
- package/dist/mqttClient.d.ts +287 -0
- package/dist/mqttClient.js +433 -0
- package/dist/mqttClient.js.map +1 -0
- package/dist/service.d.ts +64 -15
- package/dist/service.js +93 -66
- package/dist/service.js.map +1 -1
- package/dist/ui/featureOptions.js +870 -0
- package/dist/ui/featureOptions.js.map +1 -0
- package/dist/ui/formatters.js +174 -0
- package/dist/ui/formatters.js.map +1 -0
- package/dist/ui/pluginConfigSession.mjs +141 -0
- package/dist/ui/webUi-featureOptions/categoryState.mjs +135 -0
- package/dist/ui/webUi-featureOptions/effects/keyboard.mjs +61 -0
- package/dist/ui/webUi-featureOptions/effects/persist.mjs +226 -0
- package/dist/ui/webUi-featureOptions/effects/theme.mjs +398 -0
- package/dist/ui/webUi-featureOptions/effects/tokens.mjs +152 -0
- package/dist/ui/webUi-featureOptions/rendering.mjs +431 -0
- package/dist/ui/webUi-featureOptions/selectors.mjs +360 -0
- package/dist/ui/webUi-featureOptions/state.mjs +319 -0
- package/dist/ui/webUi-featureOptions/store.mjs +181 -0
- package/dist/ui/webUi-featureOptions/utils.mjs +213 -0
- package/dist/ui/webUi-featureOptions/views/connectionError.mjs +152 -0
- package/dist/ui/webUi-featureOptions/views/deviceInfo.mjs +80 -0
- package/dist/ui/webUi-featureOptions/views/header.mjs +77 -0
- package/dist/ui/webUi-featureOptions/views/nav.mjs +341 -0
- package/dist/ui/webUi-featureOptions/views/options.mjs +521 -0
- package/dist/ui/webUi-featureOptions/views/search.mjs +395 -0
- package/dist/ui/webUi-featureOptions.mjs +702 -0
- package/dist/ui/webUi.mjs +225 -88
- package/dist/util.d.ts +679 -45
- package/dist/util.js +830 -77
- package/dist/util.js.map +1 -1
- package/package.json +33 -15
- package/build/eslint-rules.mjs +0 -511
- package/dist/featureoptions.d.ts +0 -264
- package/dist/featureoptions.js +0 -480
- package/dist/featureoptions.js.map +0 -1
- package/dist/mqttclient.d.ts +0 -178
- package/dist/mqttclient.js +0 -310
- package/dist/mqttclient.js.map +0 -1
- package/dist/ui/featureoptions.js +0 -480
- package/dist/ui/featureoptions.js.map +0 -1
- package/dist/ui/webUi-featureoptions.mjs +0 -3765
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import type { HomebridgePluginLogging } from "../util.ts";
|
|
2
|
+
/**
|
|
3
|
+
* A minimal WebSocket surface the {@link LogSocket} depends on, so the concrete implementation (the platform global `WebSocket`, or a test double) is an injected seam.
|
|
4
|
+
*
|
|
5
|
+
* The shape is the subset of the DOM `WebSocket` interface the socket actually uses: the four lifecycle events via `addEventListener`, `send` for outbound frames,
|
|
6
|
+
* `close` for teardown, and `readyState` (compared against {@link WEBSOCKET_OPEN}) so teardown can gate the namespace-disconnect frame on an open connection. Modeling
|
|
7
|
+
* the seam as this narrow interface rather than the full `WebSocket` keeps a test double small and makes the socket's exact dependency surface explicit.
|
|
8
|
+
*
|
|
9
|
+
* @category Log Client
|
|
10
|
+
*/
|
|
11
|
+
export interface WebSocketLike {
|
|
12
|
+
addEventListener(type: "close", listener: (event: {
|
|
13
|
+
readonly code: number;
|
|
14
|
+
}) => void): void;
|
|
15
|
+
addEventListener(type: "error", listener: (event: unknown) => void): void;
|
|
16
|
+
addEventListener(type: "message", listener: (event: {
|
|
17
|
+
readonly data: unknown;
|
|
18
|
+
}) => void): void;
|
|
19
|
+
addEventListener(type: "open", listener: () => void): void;
|
|
20
|
+
close(code?: number): void;
|
|
21
|
+
readonly readyState: number;
|
|
22
|
+
send(data: string): void;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The factory seam that constructs a {@link WebSocketLike} for a given connect URL.
|
|
26
|
+
*
|
|
27
|
+
* The production factory wraps the platform global `WebSocket`; a test substitutes a factory that returns a controllable double, so the whole socket state machine -
|
|
28
|
+
* handshake, ping/pong, reconnect, teardown - is exercised without a real network.
|
|
29
|
+
*
|
|
30
|
+
* @param url - The fully-formed `ws(s)://...` connect URL, already carrying `EIO=4`, the transport selector, and the raw token in its query string.
|
|
31
|
+
*
|
|
32
|
+
* @returns A {@link WebSocketLike} that begins connecting immediately, exactly as the platform `WebSocket` constructor does.
|
|
33
|
+
*
|
|
34
|
+
* @category Log Client
|
|
35
|
+
*/
|
|
36
|
+
export type WebSocketFactory = (url: string) => WebSocketLike;
|
|
37
|
+
/**
|
|
38
|
+
* Re-acquire a fresh raw bearer token. Invoked once per connect attempt so a reconnect after a token has expired re-authenticates from the stored credentials. The
|
|
39
|
+
* provider may reject with a permanent authentication failure, which the reconnect loop classifies terminal via {@link isPermanentAuthError}.
|
|
40
|
+
*
|
|
41
|
+
* @param signal - The connect attempt's abort signal, forwarded so a token acquisition in flight is cancelled when the attempt is aborted.
|
|
42
|
+
*
|
|
43
|
+
* @returns A promise resolving to the raw bearer token (the bare JWT, no `Bearer` prefix).
|
|
44
|
+
*
|
|
45
|
+
* @category Log Client
|
|
46
|
+
*/
|
|
47
|
+
export type TokenProvider = (signal: AbortSignal) => Promise<string>;
|
|
48
|
+
/**
|
|
49
|
+
* The numeric `readyState` value denoting an open WebSocket. The DOM `WebSocket.OPEN` constant is `1`; we name it as a module constant so the seam interface does not
|
|
50
|
+
* have to carry the static constant and teardown can gate on it without depending on the concrete class.
|
|
51
|
+
*
|
|
52
|
+
* @category Log Client
|
|
53
|
+
*/
|
|
54
|
+
export declare const WEBSOCKET_OPEN = 1;
|
|
55
|
+
/**
|
|
56
|
+
* The production {@link WebSocketFactory}: constructs the platform global `WebSocket`. A consumer holds the factory typed as the seam abstraction; a test substitutes a
|
|
57
|
+
* double. The platform `WebSocket` begins connecting on construction, which is exactly the factory contract.
|
|
58
|
+
*
|
|
59
|
+
* @param url - The connect URL.
|
|
60
|
+
*
|
|
61
|
+
* @returns A live platform `WebSocket`, typed as the {@link WebSocketLike} seam.
|
|
62
|
+
*
|
|
63
|
+
* @category Log Client
|
|
64
|
+
*/
|
|
65
|
+
export declare const webSocketFactory: WebSocketFactory;
|
|
66
|
+
/**
|
|
67
|
+
* Construction-time options for {@link LogSocket}.
|
|
68
|
+
*
|
|
69
|
+
* @property backoff - Optional override for the connect-phase backoff policy, invoked with the 1-indexed attempt about to run and returning the delay in
|
|
70
|
+
* milliseconds. Defaults to the log client's own jittered exponential curve - a `RECONNECT_BASE_MS` base doubling each attempt and
|
|
71
|
+
* capped at `RECONNECT_CAP_MS`, plus up to `JITTER_FRACTION` upward jitter. Overridden in tests with a near-zero delay so the
|
|
72
|
+
* reconnect loop runs without real waits.
|
|
73
|
+
* @property host - The hostname or IP of the homebridge-config-ui-x server.
|
|
74
|
+
* @property log - Logger for connection lifecycle and overflow diagnostics.
|
|
75
|
+
* @property port - The TCP port the server listens on. Defaults to `8581`.
|
|
76
|
+
* @property random - Injectable source of `[0, 1)` randomness for backoff jitter. Defaults to `Math.random`; pinned in tests for deterministic backoff.
|
|
77
|
+
* @property refreshable - Whether the credential backing {@link LogSocketInit.tokenProvider} can mint a fresh token on a reconnect. `true` for `password`/`noauth`
|
|
78
|
+
* credentials (each connect re-authenticates), `false` for a static `token`. When `false`, a handshake/namespace auth rejection is raised as
|
|
79
|
+
* a permanent {@link LogAuthError} so the connect-phase retry veto makes it terminal rather than retrying a token that cannot be refreshed.
|
|
80
|
+
* @property signal - Optional parent {@link AbortSignal} composed with the socket's internal controller. When the parent aborts, the socket tears down.
|
|
81
|
+
* @property stdoutHighWater - Optional high-water mark for the bounded stdout queue. Defaults to `10000`. Overflow drops the oldest lines.
|
|
82
|
+
* @property tls - When `true`, use the secure (`wss`) scheme; when `false` or omitted, plaintext (`ws`).
|
|
83
|
+
* @property tokenProvider - Re-acquires a fresh token per connect attempt. See {@link TokenProvider}.
|
|
84
|
+
* @property webSocketFactory - The factory that constructs the underlying WebSocket. Defaults to {@link webSocketFactory}.
|
|
85
|
+
*
|
|
86
|
+
* @category Log Client
|
|
87
|
+
*/
|
|
88
|
+
export interface LogSocketInit {
|
|
89
|
+
readonly backoff?: (attempt: number) => number;
|
|
90
|
+
readonly host: string;
|
|
91
|
+
readonly log: HomebridgePluginLogging;
|
|
92
|
+
readonly port?: number;
|
|
93
|
+
readonly random?: () => number;
|
|
94
|
+
readonly refreshable: boolean;
|
|
95
|
+
readonly signal?: AbortSignal;
|
|
96
|
+
readonly stdoutHighWater?: number;
|
|
97
|
+
readonly tls?: boolean;
|
|
98
|
+
readonly tokenProvider: TokenProvider;
|
|
99
|
+
readonly webSocketFactory?: WebSocketFactory;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* The log client's connect-phase reconnect backoff policy: a dev-tuned jittered exponential curve with a low ceiling.
|
|
103
|
+
*
|
|
104
|
+
* This is the single source of truth for the socket's default reconnect timing. The base delay is `RECONNECT_BASE_MS` (500 ms) and it doubles with each successive
|
|
105
|
+
* connect attempt, plateauing at the `RECONNECT_CAP_MS` ceiling (5 s) - deliberately snappier than `defaultRetryBackoff`'s 30-second ceiling, because a log-tailing
|
|
106
|
+
* dev tool should resume the tail promptly after the frequent Homebridge restarts a plugin developer does rather than back off to a half-minute lag. Up to
|
|
107
|
+
* `JITTER_FRACTION` of the computed base is added as upward jitter so a fleet of clients does not reconnect in lockstep after a shared outage.
|
|
108
|
+
*
|
|
109
|
+
* It is exported (rather than left inline in the constructor) so the bare schedule is a directly unit-testable function: with `random` pinned to `0` the curve yields the
|
|
110
|
+
* exact, deterministic 500, 1000, 2000, 4000, 5000, 5000, ... sequence. `retry` invokes the socket's backoff 1-indexed with the attempt about to run and never with
|
|
111
|
+
* `attempt === 1` (the first attempt runs immediately), so `attempt - 2` is the zero-based exponent for the second-and-later attempts.
|
|
112
|
+
*
|
|
113
|
+
* @param attempt - The 1-indexed connect attempt about to run. Called only for the second and later attempts (the first runs with no wait).
|
|
114
|
+
* @param random - Source of `[0, 1)` randomness for the jitter. Defaults to `Math.random`; pinned in tests for a deterministic schedule.
|
|
115
|
+
*
|
|
116
|
+
* @returns The delay, in milliseconds, to wait before running `attempt`.
|
|
117
|
+
*
|
|
118
|
+
* @category Log Client
|
|
119
|
+
*/
|
|
120
|
+
export declare function reconnectBackoff(attempt: number, random?: () => number): number;
|
|
121
|
+
/**
|
|
122
|
+
* The consumer-facing surface of a live-log socket: the minimal interface a client reads off a {@link LogSocket}. This is the product half of the socket
|
|
123
|
+
* dependency-inversion seam, so a client depends on this narrow interface rather than the concrete {@link LogSocket} and a test can substitute a fake that yields
|
|
124
|
+
* caller-supplied lines without standing up a WebSocket. Every member is defined on {@link LogSocket}, so the real class satisfies it by `implements` with zero runtime
|
|
125
|
+
* change.
|
|
126
|
+
*
|
|
127
|
+
* @category Log Client
|
|
128
|
+
*/
|
|
129
|
+
export interface LogSocketLike extends AsyncDisposable {
|
|
130
|
+
/**
|
|
131
|
+
* Abort the socket and tear it down. Defaults to `HbpuAbortError("shutdown")` when no reason is supplied.
|
|
132
|
+
*
|
|
133
|
+
* @param reason - Optional abort reason. Typically an {@link HbpuAbortError}.
|
|
134
|
+
*/
|
|
135
|
+
abort(reason?: unknown): void;
|
|
136
|
+
/**
|
|
137
|
+
* `true` once the socket's lifetime signal has aborted.
|
|
138
|
+
*/
|
|
139
|
+
readonly aborted: boolean;
|
|
140
|
+
/**
|
|
141
|
+
* The number of stdout lines dropped because the consumer fell behind the high-water mark. Zero in steady state.
|
|
142
|
+
*/
|
|
143
|
+
readonly droppedLines: number;
|
|
144
|
+
/**
|
|
145
|
+
* The composed abort signal representing the socket's lifetime. Aborts exactly once; the reason on `signal.reason` names the cause.
|
|
146
|
+
*/
|
|
147
|
+
readonly signal: AbortSignal;
|
|
148
|
+
/**
|
|
149
|
+
* The bounded push-to-pull stream of raw log lines the server streams over the log namespace. Terminates when the socket aborts.
|
|
150
|
+
*
|
|
151
|
+
* @returns An async generator yielding raw log lines in stream order.
|
|
152
|
+
*/
|
|
153
|
+
stdout(): AsyncGenerator<string>;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* The creational half of the socket dependency-inversion seam: build a {@link LogSocketLike} from the socket init. A client holds this factory typed as the abstraction
|
|
157
|
+
* and constructs through it, so a test can substitute a factory that returns a fake socket. The production factory is {@link logSocketFactory}, whose `create` is exactly
|
|
158
|
+
* the {@link LogSocket} constructor call, so routing construction through this seam is behavior-neutral - mirroring the `RecordingProcessFactory` precedent.
|
|
159
|
+
*
|
|
160
|
+
* @category Log Client
|
|
161
|
+
*/
|
|
162
|
+
export interface LogSocketFactory {
|
|
163
|
+
/**
|
|
164
|
+
* Construct a live-log socket for the supplied init.
|
|
165
|
+
*
|
|
166
|
+
* @param init - The socket init options. See {@link LogSocketInit}.
|
|
167
|
+
*
|
|
168
|
+
* @returns A new {@link LogSocketLike}.
|
|
169
|
+
*/
|
|
170
|
+
create(init: LogSocketInit): LogSocketLike;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* AsyncDisposable client for the live Homebridge log stream over a single Socket.IO WebSocket, with automatic reconnect, ping liveness, and a bounded push-to-pull line
|
|
174
|
+
* stream.
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
*
|
|
178
|
+
* ```ts
|
|
179
|
+
* await using socket = new LogSocket({
|
|
180
|
+
*
|
|
181
|
+
* host: "localhost",
|
|
182
|
+
* log,
|
|
183
|
+
* refreshable: true,
|
|
184
|
+
* tokenProvider: (signal) => acquireToken(credentials, { host: "localhost", port: 8581, signal }),
|
|
185
|
+
* signal: session.signal
|
|
186
|
+
* });
|
|
187
|
+
*
|
|
188
|
+
* for await (const line of socket.stdout()) {
|
|
189
|
+
*
|
|
190
|
+
* process.stdout.write(line + "\n");
|
|
191
|
+
* }
|
|
192
|
+
* ```
|
|
193
|
+
*
|
|
194
|
+
* @category Log Client
|
|
195
|
+
*/
|
|
196
|
+
export declare class LogSocket implements LogSocketLike {
|
|
197
|
+
#private;
|
|
198
|
+
/**
|
|
199
|
+
* The composed abort signal representing this socket's lifetime. Aborts exactly once - when {@link LogSocket.abort} is called, the parent signal fires, or the
|
|
200
|
+
* reconnect loop gives up on a permanent failure - and `signal.reason` names the cause.
|
|
201
|
+
*/
|
|
202
|
+
readonly signal: AbortSignal;
|
|
203
|
+
/**
|
|
204
|
+
* Construct and start a new live-log socket. The reconnect loop starts synchronously as part of construction: by the time the constructor returns, the first connect
|
|
205
|
+
* attempt is already in flight (unless the signal was pre-aborted, in which case the socket tears down immediately).
|
|
206
|
+
*
|
|
207
|
+
* @param init - Required init options. See {@link LogSocketInit}.
|
|
208
|
+
*/
|
|
209
|
+
constructor(init: LogSocketInit);
|
|
210
|
+
/**
|
|
211
|
+
* Abort the socket and tear it down. Defaults to `HbpuAbortError("shutdown")` when no reason is supplied; explicit reasons pass through unchanged.
|
|
212
|
+
*
|
|
213
|
+
* Safe to call more than once: the underlying signal aborts only once, so subsequent calls are no-ops.
|
|
214
|
+
*
|
|
215
|
+
* @param reason - Optional abort reason. Typically an {@link HbpuAbortError}.
|
|
216
|
+
*/
|
|
217
|
+
abort(reason?: unknown): void;
|
|
218
|
+
/**
|
|
219
|
+
* `AsyncDisposable` implementation. Aborts the socket (defaulting to `"shutdown"`) and awaits the reconnect loop's completion before returning, so callers using
|
|
220
|
+
* `await using` are guaranteed the connection is closed and the loop has unwound by the time the block exits.
|
|
221
|
+
*
|
|
222
|
+
* @returns A promise that resolves once the reconnect loop has fully exited.
|
|
223
|
+
*/
|
|
224
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
225
|
+
/**
|
|
226
|
+
* `true` once `this.signal` has aborted. Derived from the signal; no independent state.
|
|
227
|
+
*/
|
|
228
|
+
get aborted(): boolean;
|
|
229
|
+
/**
|
|
230
|
+
* The number of stdout lines dropped so far because the consumer fell behind the high-water mark. Zero in steady state; non-zero only after the bounded queue
|
|
231
|
+
* overflowed, which is also logged once.
|
|
232
|
+
*/
|
|
233
|
+
get droppedLines(): number;
|
|
234
|
+
/**
|
|
235
|
+
* The bounded push-to-pull stream of raw log lines (ANSI intact, terminators removed) the server streams over the log namespace's `stdout` events.
|
|
236
|
+
*
|
|
237
|
+
* The server delivers `stdout` as raw text chunks whose boundaries do not align with log lines; the socket runs each chunk through a per-session
|
|
238
|
+
* {@link LogLineSplitter}, yields complete lines here, and flushes it on each session's close so the final line is never stranded. Mirroring
|
|
239
|
+
* `Mp4SegmentAssembler.segments`, a bounded queue decouples the WebSocket producer from this consumer, and a single parked waiter blocks the consumer when the queue is
|
|
240
|
+
* empty until a line is pushed or the socket aborts. The queue survives reconnects - the same iterable keeps yielding across a drop-and-reconnect - so a consumer
|
|
241
|
+
* iterates it once for the whole socket lifetime. The stream terminates (returns) when the socket aborts; the queue is drained before it returns, so a line already
|
|
242
|
+
* staged before teardown is never lost.
|
|
243
|
+
*
|
|
244
|
+
* **Single-consumer only.** The parked-waiter slot is single-writer; iterating `stdout()` concurrently from two consumers is unsupported.
|
|
245
|
+
*
|
|
246
|
+
* @returns An async generator yielding raw log lines in stream order.
|
|
247
|
+
*/
|
|
248
|
+
stdout(): AsyncGenerator<string>;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* The production {@link LogSocketFactory}: builds the concrete WebSocket-backed {@link LogSocket}. A client holds the factory typed as the seam abstraction; a test
|
|
252
|
+
* substitutes a fake factory. `create` is exactly the {@link LogSocket} constructor call, so wiring construction through this seam is behavior-neutral.
|
|
253
|
+
*
|
|
254
|
+
* @category Log Client
|
|
255
|
+
*/
|
|
256
|
+
export declare const logSocketFactory: LogSocketFactory;
|
|
257
|
+
//# sourceMappingURL=socket.d.ts.map
|