@claxedo/workspace-relay 0.8.0 → 0.10.1

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/bun.d.ts DELETED
@@ -1,225 +0,0 @@
1
- import { type WorkspaceRelayOptions } from "./server";
2
- import { type RuntimeAccessTokenClaims } from "./auth";
3
- import { type UpstreamWebSocketConstructor } from "./upstream-websocket";
4
- /**
5
- * Bun expresses HTTP idle timeout in seconds. Runtime SSE heartbeats arrive
6
- * every 30 seconds, so this exceeds that interval while still bounding idle
7
- * unauthenticated and incomplete HTTP connections.
8
- */
9
- export declare const WORKSPACE_RELAY_IDLE_TIMEOUT_SECONDS = 45;
10
- type RelayClientWebSocketData = {
11
- kind: "client";
12
- claims: RuntimeAccessTokenClaims;
13
- upstreamUrl: string;
14
- headers: Record<string, string>;
15
- queue: Array<{
16
- payload: string | Buffer<ArrayBuffer>;
17
- queuedAt: number;
18
- }>;
19
- /** Running byte size of `queue`; reset when the queue is flushed upstream. */
20
- queuedBytes?: number;
21
- upstream?: WebSocket;
22
- upstreamOpenTimer?: ReturnType<typeof setTimeout>;
23
- trace?: RelayClientWebSocketTrace;
24
- accessCheckTimer?: ReturnType<typeof setInterval>;
25
- expiryTimer?: ReturnType<typeof setTimeout>;
26
- };
27
- type RelayClientWebSocketTrace = {
28
- acceptedAt: number;
29
- upstreamStartedAt?: number;
30
- upstreamOpenMs?: number;
31
- queuedFrames: number;
32
- maxQueuedDelayMs: number;
33
- emitted: boolean;
34
- };
35
- type RelayHostTunnelWebSocketData = {
36
- kind: "host-tunnel";
37
- hostId: string;
38
- workspaceIds: string[];
39
- /** Fence pair from the last verified Host Tunnel Token (connect or registration update); absent for tokens without one. */
40
- enrollmentId?: string;
41
- generation?: number;
42
- pending: Map<string, PendingTunnelHttpResponse>;
43
- channels: Map<string, RelayUserHostedClientWebSocket>;
44
- heartbeat?: ReturnType<typeof setInterval>;
45
- missedPongs: number;
46
- generationCheckTimer?: ReturnType<typeof setInterval>;
47
- generationCheckFailures: number;
48
- messageBuffer: string;
49
- };
50
- type RelayUserHostedClientWebSocketData = {
51
- kind: "user-hosted-client";
52
- claims: RuntimeAccessTokenClaims;
53
- hostId: string;
54
- workspaceId: string;
55
- channelId: string;
56
- path: string;
57
- relayHostToken: string;
58
- accessCheckTimer?: ReturnType<typeof setInterval>;
59
- expiryTimer?: ReturnType<typeof setTimeout>;
60
- };
61
- type RelayWebSocketData = RelayClientWebSocketData | RelayHostTunnelWebSocketData | RelayUserHostedClientWebSocketData;
62
- /** The socket type Bun hands every handler: one type carrying the data union. */
63
- type RelayWebSocket = Bun.ServerWebSocket<RelayWebSocketData>;
64
- type RelayHostTunnelWebSocket = Bun.ServerWebSocket<RelayHostTunnelWebSocketData>;
65
- type RelayUserHostedClientWebSocket = Bun.ServerWebSocket<RelayUserHostedClientWebSocketData>;
66
- type PendingTunnelHttpResponse = {
67
- controller: ReadableStreamDefaultController<Uint8Array>;
68
- stream: ReadableStream<Uint8Array>;
69
- resolve: (response: Response) => void;
70
- reject: (error: Error) => void;
71
- timeout: ReturnType<typeof setTimeout>;
72
- pendingChunks: Uint8Array[];
73
- bytesQueued: number;
74
- slowConsumerTimeout?: ReturnType<typeof setTimeout>;
75
- responseStarted: boolean;
76
- /**
77
- * The relay's own CORS headers for this request, applied to whatever the
78
- * tunnelled host answers with. The browser talks to the RELAY, so the
79
- * relay's allowlist is the one that decides what it may read — the host
80
- * behind the tunnel runs its own, unrelated policy, and passing its headers
81
- * through made a relay's configured app origin readable only when the host
82
- * happened to allow it too.
83
- */
84
- corsHeaders: (upstream: Headers) => Headers;
85
- };
86
- export type WorkspaceRelayHostTunnelOptions = {
87
- /**
88
- * Test seam replacing Host Tunnel Token verification. A boolean carries no
89
- * claims, so a tunnel admitted through it has no generation and is never
90
- * fenced.
91
- */
92
- authorizeHostTunnel?: (request: Request, input: {
93
- hostId: string;
94
- workspaceIds: string[];
95
- }) => boolean | Promise<boolean>;
96
- hostTunnelPingIntervalMs?: number;
97
- hostTunnelMaxMissedPongs?: number;
98
- /**
99
- * How often an established host tunnel's generation is re-checked against
100
- * `resolveHostGeneration`. Defaults to 30s; 0 disables the check. Because
101
- * the lookup may answer from its cache, a superseded tunnel closes within
102
- * this interval plus the lookup's cache TTL.
103
- */
104
- hostGenerationCheckIntervalMs?: number;
105
- /**
106
- * Consecutive unavailable lookups an established tunnel survives before it
107
- * is closed 1012 for the host to reconnect. Defaults to 3.
108
- */
109
- hostGenerationOutageGraceAttempts?: number;
110
- hostTunnelStateDebounceMs?: number;
111
- };
112
- export type WorkspaceRelayBackpressureOptions = {
113
- slowConsumerHighWaterMarkBytes?: number;
114
- slowConsumerTimeoutMs?: number;
115
- tunnelRequestBodyMaxBytes?: number;
116
- tunnelHttpResponseTimeoutMs?: number;
117
- directHttpTimeoutMs?: number;
118
- directHttpConcurrency?: number;
119
- upstreamWebSocketOpenTimeoutMs?: number;
120
- upstreamWebSocketPreOpenQueueMaxFrames?: number;
121
- upstreamWebSocketPreOpenQueueMaxBytes?: number;
122
- upstreamWebSocket?: UpstreamWebSocketConstructor;
123
- webSocketBufferedAmountMaxBytes?: number;
124
- };
125
- export type WorkspaceRelayBunOptions = WorkspaceRelayHostTunnelOptions & WorkspaceRelayBackpressureOptions & {
126
- /** How often established user WebSockets are re-checked for revocation. Defaults to 30s. */
127
- runtimeAccessTokenActiveCheckIntervalMs?: number;
128
- /** Clock injection used to calculate the local token-expiry deadline. */
129
- now?: () => number;
130
- };
131
- /**
132
- * Declared as function-valued properties, not methods, because every member is
133
- * a closure over the adapter's counters and is routinely handed around
134
- * detached (`metricsSources.fragmentation ?? telemetry.getFragmentationStats`).
135
- * None of them reads `this`, and the same shape is used by
136
- * `WorkspaceRelayMetricsSources` in `./server`.
137
- */
138
- export type WorkspaceRelayBunTelemetry = {
139
- getFragmentationStats: () => FragmentationStats;
140
- resetFragmentationStats: () => void;
141
- getSlowConsumerStats: () => SlowConsumerStats;
142
- resetSlowConsumerStats: () => void;
143
- };
144
- /**
145
- * Drain controller exposed by `createWorkspaceRelayBun`.
146
- *
147
- * On SIGTERM the operator (see `installShutdownDrainHandler` in main.ts)
148
- * flips `setDraining(true)`; from that point onward the relay
149
- * - returns 503 from `/health` so Fly removes the instance from routing
150
- * - rejects new HTTP requests with 503 (`relay_draining`) before doing auth
151
- * - rejects new host-tunnel WebSocket upgrades with 503
152
- * - closes active host tunnels with 1012 so host clients reconnect promptly
153
- *
154
- * `pendingCount()` reports the total number of in-flight tunnel HTTP
155
- * responses across every connected host tunnel — this is what the operator
156
- * polls via `waitForDrain(timeoutMs)` before hard-closing remaining sockets.
157
- *
158
- * Function-valued properties rather than methods, for the same reason as
159
- * `WorkspaceRelayBunTelemetry`: `isDraining` and `pendingCount` are passed
160
- * detached into `createWorkspaceRelay`, and none of them reads `this`.
161
- */
162
- export type WorkspaceRelayBunDrainController = {
163
- isDraining: () => boolean;
164
- setDraining: (value: boolean) => void;
165
- pendingCount: () => number;
166
- waitForDrain: (timeoutMs: number) => Promise<{
167
- drained: boolean;
168
- remaining: number;
169
- }>;
170
- };
171
- /**
172
- * Bytes queued in a socket's send buffer, or `undefined` if it cannot report.
173
- *
174
- * Bun spells this `getBufferedAmount()` — a method, not the browser's
175
- * `bufferedAmount` property. Reading the property on a Bun socket yields
176
- * `undefined`, and `undefined > limit` is always false, so a guard built on it
177
- * never fires.
178
- *
179
- * Fails open on a socket that cannot report, deliberately: an unguarded healthy
180
- * connection beats a guard that kills healthy connections. This is also why the
181
- * guard is not portable to `cloudflare.ts` — workerd's WebSocket exposes no
182
- * buffer depth, so bounding that path needs a protocol-level credit/ack window.
183
- */
184
- export declare const relayBufferedBytes: (socket: unknown) => number | undefined;
185
- /**
186
- * True only when the socket reports a depth over the limit. Unknown ⇒ false.
187
- *
188
- * Exported for `bun.test.ts`: a loopback peer drains faster than a test can
189
- * fill it, so the decision is asserted directly.
190
- */
191
- export declare const relayOverBackpressureLimit: (socket: unknown, limitBytes: number) => boolean;
192
- export type FragmentationStats = {
193
- fragmentsBuffered: number;
194
- oversizedClosed: number;
195
- };
196
- export type SlowConsumerStats = {
197
- overflowEvents: number;
198
- timerFired: number;
199
- droppedRequests: number;
200
- };
201
- declare function createSlowConsumerStats(): SlowConsumerStats;
202
- declare function enqueueChunkWithBackpressure(input: {
203
- ws: RelayHostTunnelWebSocket;
204
- requestId: string;
205
- entry: PendingTunnelHttpResponse;
206
- chunk: Uint8Array;
207
- slowConsumerTimeoutMs: number;
208
- slowConsumerStats: SlowConsumerStats;
209
- }): void;
210
- export declare const __slowConsumerInternalsForTest: {
211
- enqueueChunkWithBackpressure: typeof enqueueChunkWithBackpressure;
212
- createSlowConsumerStats: typeof createSlowConsumerStats;
213
- };
214
- export declare function createWorkspaceRelayBun(options: WorkspaceRelayOptions, bunOptions?: WorkspaceRelayBunOptions): {
215
- fetch: (request: Request, server: Bun.Server<RelayWebSocketData>) => Promise<Response | undefined>;
216
- websocket: {
217
- maxPayloadLength: number;
218
- message(ws: RelayWebSocket, message: string | Buffer<ArrayBuffer>): void;
219
- open(ws: RelayWebSocket): void;
220
- close(ws: RelayWebSocket, code: number, reason: string): void;
221
- };
222
- drain: WorkspaceRelayBunDrainController;
223
- telemetry: WorkspaceRelayBunTelemetry;
224
- };
225
- export {};