@geekmidas/constructs 10.0.0-alpha.125 → 10.0.0-alpha.127

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.
@@ -0,0 +1,449 @@
1
+ import { n as StandardSchemaV1 } from "./index-DdRjYhiJ.mjs";
2
+ import { c as ServicesOf, i as Declarable, r as Consumable, t as Authenticator } from "./construct-interface-ZvYQbivO.mjs";
3
+ import { n as Telemetry } from "./telemetry-BEoBn6GO.mjs";
4
+ import { ConstructName, Declaration, Dependency } from "@geekmidas/manifest";
5
+ import { Service, ServiceRecord, ServiceRegisterOptions } from "@geekmidas/services";
6
+ import { EnvironmentParser } from "@geekmidas/envkit";
7
+ import { Hono } from "hono";
8
+ import { Logger } from "@geekmidas/logger";
9
+ import { InferStandardSchema } from "@geekmidas/schema";
10
+ import { IncomingMessage, Server } from "node:http";
11
+ import { Duplex } from "node:stream";
12
+ //#region src/websocket/transport.d.ts
13
+ /**
14
+ * How a send reaches the process holding the socket.
15
+ *
16
+ * A connection id names the process it lives on — `<instance>.<n>` — so a send
17
+ * needs no registry: it is published to that instance's channel and nowhere
18
+ * else. A broadcast goes to every instance. On a stack the channels are Redis
19
+ * pub/sub, so an endpoint in another container reaches a socket the same way a
20
+ * route beside it does; in one process (a test, a single dev server) they are
21
+ * a map.
22
+ */
23
+ /** What one process is asked to do with the sockets it holds. */
24
+ type Delivery = {
25
+ kind: 'send';
26
+ ids: readonly string[];
27
+ payload: string;
28
+ } | {
29
+ kind: 'broadcast';
30
+ payload: string;
31
+ except?: readonly string[];
32
+ } | {
33
+ kind: 'close';
34
+ ids: readonly string[];
35
+ code: number;
36
+ reason: string;
37
+ };
38
+ interface WebSocketTransport {
39
+ /** Deliver to one instance, or to every instance when it is `'*'`. */
40
+ publish(instance: string, delivery: Delivery): Promise<void>;
41
+ /** Receive what is published to `instance`, and every broadcast. */
42
+ subscribe(instance: string, receive: (delivery: Delivery) => void): Promise<void>;
43
+ close(): Promise<void>;
44
+ }
45
+ /** A connection string names no transport this package knows. */
46
+ export declare class UnsupportedWebSocketTransport extends Error {
47
+ readonly connectionString: string;
48
+ constructor(connectionString: string);
49
+ }
50
+ /**
51
+ * In one process: the server and whoever sends meet in a map, keyed by the
52
+ * channel the connection string names.
53
+ */
54
+ export declare class MemoryTransport implements WebSocketTransport {
55
+ private readonly channel;
56
+ private readonly subscribed;
57
+ constructor(channel: string);
58
+ publish(instance: string, delivery: Delivery): Promise<void>;
59
+ subscribe(instance: string, receive: (delivery: Delivery) => void): Promise<void>;
60
+ close(): Promise<void>;
61
+ }
62
+ /** The subset of an ioredis client the transport uses. */
63
+ interface RedisClient {
64
+ publish(channel: string, message: string): Promise<number>;
65
+ subscribe(...channels: string[]): Promise<unknown>;
66
+ on(event: 'message', listener: (channel: string, message: string) => void): unknown;
67
+ duplicate(): RedisClient;
68
+ quit(): Promise<unknown>;
69
+ }
70
+ /**
71
+ * Over Redis pub/sub: one channel per instance and one for broadcasts, under
72
+ * a prefix that keeps two surfaces — or two projects on one Redis — apart.
73
+ * Channels are not scoped by database index, so the prefix is what does it.
74
+ *
75
+ * Publishing and subscribing take separate connections, because a connection
76
+ * that has subscribed can do nothing else.
77
+ */
78
+ export declare class RedisTransport implements WebSocketTransport {
79
+ private readonly client;
80
+ private readonly prefix;
81
+ private subscriber?;
82
+ private closed?;
83
+ constructor(client: RedisClient, prefix: string);
84
+ private channel;
85
+ publish(instance: string, delivery: Delivery): Promise<void>;
86
+ subscribe(instance: string, receive: (delivery: Delivery) => void): Promise<void>;
87
+ /** Idempotent: the server and a shutdown hook may both close it. */
88
+ close(): Promise<void>;
89
+ }
90
+ /**
91
+ * The transport a connection string names.
92
+ *
93
+ * `redis://` and `rediss://` take an optional `channel` query parameter, the
94
+ * prefix every channel is named under; `memory://<channel>` is in-process.
95
+ * Absent, the channel is `fallback` — the surface's own.
96
+ */
97
+ export declare function transportFromConnectionString(connectionString: string, fallback: string): Promise<WebSocketTransport>;
98
+ //#endregion
99
+ //#region src/websocket/publisher.d.ts
100
+ /**
101
+ * What a surface sends its sockets, by action — `WebSocketApiConfig.messages`.
102
+ */
103
+ type WebSocketMessages = Record<string, StandardSchemaV1>;
104
+ /** A surface that declares no messages: any action, any data. */
105
+ type NoMessages = Record<never, never>;
106
+ /** The actions a publisher sends: the declared ones, or any. */
107
+ type MessageAction<TMessages extends WebSocketMessages> = [keyof TMessages] extends [never] ? string : keyof TMessages & string;
108
+ /** What `action`'s data is, as its schema takes it. */
109
+ type MessageData<TMessages extends WebSocketMessages, TAction extends string> = TAction extends keyof TMessages ? StandardSchemaV1.InferInput<TMessages[TAction]> : unknown;
110
+ /** A message sent on an action the surface does not declare. */
111
+ export declare class UnknownWebSocketMessage extends Error {
112
+ readonly surface: string;
113
+ readonly action: string;
114
+ readonly declared: readonly string[];
115
+ constructor(surface: string, action: string, declared: readonly string[]);
116
+ }
117
+ /** A message whose data its action's schema refused. */
118
+ export declare class InvalidWebSocketMessage extends Error {
119
+ readonly surface: string;
120
+ readonly action: string;
121
+ readonly issues: readonly StandardSchemaV1.Issue[];
122
+ constructor(surface: string, action: string, issues: readonly StandardSchemaV1.Issue[]);
123
+ }
124
+ /**
125
+ * How anything reaches a socket — `services.realtime` in an endpoint, and
126
+ * `sockets` in a route of the surface itself.
127
+ *
128
+ * A message is `{ action, data }`, the shape a client's frames arrive in.
129
+ * Where the surface declares its messages, `action` is one of them and
130
+ * `data` is typed and checked by its schema before anything is sent; where it
131
+ * declares none, any action and any JSON value go. A message is serialised
132
+ * once, whatever the number of sockets it goes to. An id whose process has
133
+ * gone is dropped silently, as API Gateway's `postToConnection` to a closed
134
+ * connection is a no-op the sender rarely wants to handle.
135
+ */
136
+ export declare class WebSocketPublisher<TMessages extends WebSocketMessages = NoMessages> {
137
+ private readonly transport;
138
+ /**
139
+ * Delivers to this process's own sockets without a round trip through
140
+ * the transport — set on the server's own publisher.
141
+ */
142
+ private readonly local?;
143
+ /** The surface's declared messages, which every send is checked by. */
144
+ private readonly declared?;
145
+ constructor(transport: WebSocketTransport,
146
+ /**
147
+ * Delivers to this process's own sockets without a round trip through
148
+ * the transport — set on the server's own publisher.
149
+ */
150
+ local?: {
151
+ instance: string;
152
+ deliver(delivery: Delivery): void;
153
+ } | undefined,
154
+ /** The surface's declared messages, which every send is checked by. */
155
+ declared?: {
156
+ surface: string;
157
+ messages: TMessages;
158
+ } | undefined);
159
+ /** Send `action`'s message to each connection. */
160
+ send<TAction extends MessageAction<TMessages>>(ids: string | readonly string[], action: TAction, data: MessageData<TMessages, TAction>): Promise<void>;
161
+ /** Send `action`'s message to every open connection, on every process. */
162
+ broadcast<TAction extends MessageAction<TMessages>>(action: TAction, data: MessageData<TMessages, TAction>, options?: {
163
+ except?: readonly string[];
164
+ }): Promise<void>;
165
+ /** Close each connection, with a close code and reason its client sees. */
166
+ close(ids: string | readonly string[], code?: number, reason?: string): Promise<void>;
167
+ /**
168
+ * The frame, checked by the action's schema where the surface declares
169
+ * its messages.
170
+ *
171
+ * @throws {UnknownWebSocketMessage}, {InvalidWebSocketMessage}
172
+ */
173
+ private payload;
174
+ /** One delivery per process that holds any of `ids`. */
175
+ private each;
176
+ }
177
+ //#endregion
178
+ //#region src/websocket/route.d.ts
179
+ /** One open connection, as a handler sees it. */
180
+ interface Connection {
181
+ readonly id: string;
182
+ /**
183
+ * What the connect handler returned — who the connection is for, the room
184
+ * it joined. `{}` when it returned nothing.
185
+ */
186
+ readonly data: Record<string, unknown>;
187
+ }
188
+ interface BaseContext<TServices extends Service[], TMessages extends WebSocketMessages> {
189
+ services: ServiceRecord<TServices>;
190
+ logger: Logger;
191
+ /** Every socket this surface holds, on whichever process holds it. */
192
+ sockets: WebSocketPublisher<TMessages>;
193
+ }
194
+ interface ConnectContext<TServices extends Service[], TMessages extends WebSocketMessages = NoMessages> extends BaseContext<TServices, TMessages> {
195
+ connectionId: string;
196
+ headers: Headers;
197
+ query: URLSearchParams;
198
+ /**
199
+ * Whose connection it is, from the surface's `.auth()` — `null` when the
200
+ * upgrade carried no session, and when the surface names no authenticator.
201
+ * Throw an `UnauthorizedError` to refuse it.
202
+ */
203
+ session: unknown;
204
+ }
205
+ interface MessageContext<TBody, TServices extends Service[], TMessages extends WebSocketMessages = NoMessages> extends BaseContext<TServices, TMessages> {
206
+ connection: Connection;
207
+ body: TBody;
208
+ /** Send to this connection alone. */
209
+ reply(message: unknown): void;
210
+ }
211
+ interface DisconnectContext<TServices extends Service[], TMessages extends WebSocketMessages = NoMessages> extends BaseContext<TServices, TMessages> {
212
+ connection: Connection;
213
+ code: number;
214
+ reason: string;
215
+ }
216
+ /** What a frame is dispatched on: an action, or the connection's lifecycle. */
217
+ type RouteKind = 'connect' | 'disconnect' | 'message';
218
+ /**
219
+ * A handler bound to a WebSocket surface — what `realtime.route('chat.send')
220
+ * …handle()` returns, and what a file exports.
221
+ *
222
+ * Carries `surface` and `constructs` the way an endpoint does, so discovery
223
+ * records what its process reaches without knowing what a route is.
224
+ */
225
+ export declare class WebSocketRoute {
226
+ readonly kind: RouteKind;
227
+ /** The `action` it answers; `$connect` and `$disconnect` for the lifecycle. */
228
+ readonly action: string;
229
+ readonly surface: {
230
+ id: string;
231
+ };
232
+ readonly services: readonly Service[];
233
+ /** Construct ids it depends on — its edges in the manifest. */
234
+ readonly constructs: readonly string[];
235
+ readonly handler: (context: never) => unknown;
236
+ readonly schema?: StandardSchemaV1 | undefined;
237
+ readonly __IS_WEBSOCKET_ROUTE__ = true;
238
+ static isRoute(value: unknown): value is WebSocketRoute;
239
+ constructor(kind: RouteKind,
240
+ /** The `action` it answers; `$connect` and `$disconnect` for the lifecycle. */
241
+ action: string, surface: {
242
+ id: string;
243
+ }, services: readonly Service[],
244
+ /** Construct ids it depends on — its edges in the manifest. */
245
+ constructs: readonly string[], handler: (context: never) => unknown, schema?: StandardSchemaV1 | undefined);
246
+ }
247
+ /** The builder `connect()`, `disconnect()` and `route()` start. */
248
+ export declare class WebSocketRouteBuilder<TKind extends RouteKind, TSchema extends StandardSchemaV1 | undefined = undefined, TServices extends Service[] = [],
249
+ /** The surface's declared messages, which `sockets` sends. */
250
+ TMessages extends WebSocketMessages = NoMessages> {
251
+ private readonly kind;
252
+ private readonly action;
253
+ private readonly surface;
254
+ private readonly _services;
255
+ private readonly _constructs;
256
+ private readonly schema?;
257
+ constructor(kind: TKind, action: string, surface: {
258
+ id: string;
259
+ }, _services?: readonly Service[], _constructs?: readonly string[], schema?: TSchema | undefined);
260
+ /** The schema a frame's `data` must satisfy before the handler runs. */
261
+ body<S extends StandardSchemaV1>(schema: S): WebSocketRouteBuilder<TKind, S, TServices, TMessages>;
262
+ /** What the handler reaches, as `services.<id>` — per route, as an endpoint's. */
263
+ dependsOn<const T extends readonly Consumable[]>(constructs: T): WebSocketRouteBuilder<TKind, TSchema, [...TServices, ...(ServicesOf<T> extends Service[] ? ServicesOf<T> : [])], TMessages>;
264
+ /**
265
+ * The handler. A message handler's return value, when there is one, is
266
+ * sent back to the connection as the reply to that frame; a connect
267
+ * handler's is kept as the connection's `data`.
268
+ */
269
+ handle(handler: TKind extends 'connect' ? (context: ConnectContext<TServices, TMessages>) => Record<string, unknown> | undefined | Promise<Record<string, unknown> | undefined> : TKind extends 'disconnect' ? (context: DisconnectContext<TServices, TMessages>) => unknown : (context: MessageContext<TSchema extends StandardSchemaV1 ? InferStandardSchema<TSchema> : unknown, TServices, TMessages>) => unknown): WebSocketRoute;
270
+ }
271
+ //#endregion
272
+ //#region src/websocket/server.d.ts
273
+ /** Close codes a client sees. */
274
+ export declare const CLOSE: {
275
+ readonly normal: 1000;
276
+ /** The process is stopping; reconnect and land on another. */
277
+ readonly serviceRestart: 1012;
278
+ /** It stopped reading, and what was queued for it passed the limit. */
279
+ readonly tooSlow: 1013;
280
+ };
281
+ /** Two routes answer one action. */
282
+ export declare class DuplicateWebSocketRoute extends Error {
283
+ readonly surface: string;
284
+ readonly action: string;
285
+ constructor(surface: string, action: string);
286
+ }
287
+ interface WebSocketServerOptions<TMessages extends WebSocketMessages = NoMessages> {
288
+ surface: string;
289
+ /** What the surface sends its sockets — see `WebSocketApiConfig.messages`. */
290
+ messages?: TMessages;
291
+ routes: readonly WebSocketRoute[];
292
+ transport: WebSocketTransport;
293
+ envParser: EnvironmentParser<{}>;
294
+ logger: Logger;
295
+ authenticator?: Authenticator;
296
+ /**
297
+ * Origins a browser may open a socket from. A request with an `Origin`
298
+ * not in the list is refused with 403; one with none — a server, a load
299
+ * generator — is not a browser, and is let through.
300
+ */
301
+ trustedOrigins: readonly string[];
302
+ /** How often each socket is pinged; one that missed the last is dropped. */
303
+ heartbeatMs?: number;
304
+ /** The largest frame accepted, in bytes. */
305
+ maxPayload?: number;
306
+ /** Queued bytes a socket may hold before it is closed as too slow. */
307
+ maxBufferedBytes?: number;
308
+ }
309
+ export declare class WebSocketSurfaceServer<TMessages extends WebSocketMessages = NoMessages> {
310
+ private readonly wss;
311
+ private readonly options;
312
+ /** This process, as connection ids name it. */
313
+ readonly instance: string;
314
+ /** `sockets` in a route: local sends skip the transport. */
315
+ readonly publisher: WebSocketPublisher<TMessages>;
316
+ private readonly held;
317
+ private readonly routes;
318
+ private readonly lifecycle;
319
+ private readonly heartbeat;
320
+ private next;
321
+ private closing;
322
+ private constructor();
323
+ static start<TMessages extends WebSocketMessages = NoMessages>(options: WebSocketServerOptions<TMessages>): Promise<WebSocketSurfaceServer<TMessages>>;
324
+ /** How many sockets this process holds. */
325
+ get size(): number;
326
+ /** Take over `server`'s upgrades. */
327
+ attach(server: Server): void;
328
+ /** Upgrade one request, or refuse it with a status line. */
329
+ upgrade(request: IncomingMessage, socket: Duplex, head: Buffer): Promise<void>;
330
+ private open;
331
+ /** Parse, validate and run one frame. Errors go back as frames, not closes. */
332
+ private dispatch;
333
+ /** Run a handler with its services, inside a request context of its own. */
334
+ private run;
335
+ private error;
336
+ /** Write, unless the socket has stopped reading and its queue is full. */
337
+ private write;
338
+ /** What the transport, or a local publisher, asked of this process. */
339
+ private deliver;
340
+ /** Drop every socket that missed the last ping, and ping the rest. */
341
+ private beat;
342
+ /**
343
+ * Stop: refuse new upgrades, close every socket with `code` — 1012 tells
344
+ * a client to reconnect, and it lands on a process that is still up — and
345
+ * leave the transport.
346
+ */
347
+ close(code?: number, reason?: string): Promise<void>;
348
+ }
349
+ //#endregion
350
+ //#region src/websocket-api.d.ts
351
+ export interface WebSocketApiConfig<TMessages extends WebSocketMessages = NoMessages> {
352
+ /** The app that serves it, relative to the workspace root. */
353
+ path: string;
354
+ /**
355
+ * What it sends its sockets, by action — each with the schema its `data`
356
+ * is checked by before it is sent.
357
+ *
358
+ * ```ts
359
+ * messages: {
360
+ * announcement: z.object({ text: z.string() }),
361
+ * 'chat.said': z.object({ from: z.string(), text: z.string() }),
362
+ * }
363
+ * ```
364
+ *
365
+ * The publisher is typed by it — `services.realtime.broadcast(
366
+ * 'announcement', { text })` — in an endpoint and in a route's `sockets`
367
+ * alike. Absent, any action and any data go, unchecked.
368
+ */
369
+ messages?: TMessages;
370
+ /** The label it answers on. Absent, its id kebab-cased. */
371
+ subdomain?: string;
372
+ /** How many processes serve it on one machine. Default 1. */
373
+ replicas?: number;
374
+ logger?: Logger;
375
+ envParser?: EnvironmentParser<{}>;
376
+ telemetry?: Telemetry;
377
+ /** Seconds between pings; a socket that misses one is dropped. Default 30. */
378
+ heartbeat?: number;
379
+ /** The largest frame accepted, in bytes. Default 1 MiB. */
380
+ maxPayload?: number;
381
+ }
382
+ /** A replica count that is not a whole number of at least one. */
383
+ export declare class InvalidReplicaCount extends Error {
384
+ readonly id: string;
385
+ readonly replicas: number;
386
+ constructor(id: string, replicas: number);
387
+ }
388
+ export declare class WebSocketApi<TName extends string = string, TMessages extends WebSocketMessages = NoMessages> implements Declarable<TName> {
389
+ private readonly config;
390
+ /** Internal: how `.calls()` carries edges into the copy it returns. */
391
+ private readonly dependencies;
392
+ /** Internal: how `.auth()` carries the authenticator into its copy. */
393
+ readonly authenticator?: Authenticator | undefined;
394
+ readonly id: TName;
395
+ readonly keys: {
396
+ url: string;
397
+ trustedOrigins: string;
398
+ publisherConnectionString: string;
399
+ };
400
+ readonly logger: Logger;
401
+ readonly envParser: EnvironmentParser<{}>;
402
+ readonly telemetry?: Telemetry;
403
+ /**
404
+ * The surface as a dependency: `services.<id>` is its publisher, so an
405
+ * endpoint sends to a socket the way a route beside it does.
406
+ */
407
+ readonly service: Service<Uncapitalize<TName>, WebSocketPublisher<TMessages>>;
408
+ constructor(id: ConstructName<TName>, config: WebSocketApiConfig<TMessages>,
409
+ /** Internal: how `.calls()` carries edges into the copy it returns. */
410
+ dependencies?: readonly Dependency[],
411
+ /** Internal: how `.auth()` carries the authenticator into its copy. */
412
+ authenticator?: Authenticator | undefined);
413
+ /** The handler a connection's upgrade runs: refuse it, or say who it is. */
414
+ connect(): WebSocketRouteBuilder<'connect', undefined, [], TMessages>;
415
+ /** The handler a closed connection runs. */
416
+ disconnect(): WebSocketRouteBuilder<'disconnect', undefined, [], TMessages>;
417
+ /**
418
+ * The handler for frames whose `action` is `action`. `$default` answers
419
+ * any action nothing else does.
420
+ */
421
+ route(action: string): WebSocketRouteBuilder<'message', undefined, [], TMessages>;
422
+ /** What authenticates a connection — its session reaches `connect()`. */
423
+ auth(construct: Authenticator): WebSocketApi<TName, TMessages>;
424
+ /** Other surfaces this one calls. See `RestApi.calls`. */
425
+ calls(constructs: readonly Declarable[]): WebSocketApi<TName, TMessages>;
426
+ /**
427
+ * Serve it: the routes exported by `modules` that were built from this
428
+ * surface, on whatever HTTP server `attach` is handed.
429
+ *
430
+ * `app` answers plain HTTP — the generated entry puts `/health` in front
431
+ * of it — and `attach` takes over the server's upgrades. The sockets are
432
+ * closed with 1012 when the server shuts down.
433
+ */
434
+ server(options: ServiceRegisterOptions & {
435
+ modules?: readonly object[];
436
+ }): Promise<{
437
+ app: Hono;
438
+ attach(server: Server): void;
439
+ /** Close every socket with 1012, so the HTTP server can close. */
440
+ release(): Promise<void>;
441
+ server: WebSocketSurfaceServer<TMessages>;
442
+ }>;
443
+ /** The declared messages, with the surface they are checked for. */
444
+ private get declared();
445
+ declare(): Declaration[];
446
+ }
447
+ //#endregion
448
+ export type { ConnectContext, Connection, Delivery, DisconnectContext, MessageAction, MessageContext, MessageData, NoMessages, RouteKind, WebSocketMessages, WebSocketServerOptions, WebSocketTransport };
449
+ //# sourceMappingURL=websocket-api.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket-api.d.mts","names":[],"sources":["../src/websocket/transport.ts","../src/websocket/publisher.ts","../src/websocket/route.ts","../src/websocket/server.ts","../src/websocket-api.ts"],"mappings":"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"}