@firtoz/socka 3.0.2 → 4.0.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 +15 -1
- package/dist/{SockaWebSocketSession-B1w7RAid.d.ts → SockaWebSocketSession-BaGvSerM.d.ts} +28 -10
- package/dist/bun/index.d.ts +6 -6
- package/dist/bun/index.js +2 -2
- package/dist/bun/index.js.map +1 -1
- package/dist/{chunk-5WQTYLIC.js → chunk-JR2GENNT.js} +2 -2
- package/dist/chunk-JR2GENNT.js.map +1 -0
- package/dist/{chunk-P3JEEOJL.js → chunk-THFUHQJ3.js} +2 -2
- package/dist/chunk-THFUHQJ3.js.map +1 -0
- package/dist/{chunk-LVVCHLNW.js → chunk-TTXY7O5P.js} +20 -4
- package/dist/chunk-TTXY7O5P.js.map +1 -0
- package/dist/client/index.d.ts +10 -10
- package/dist/client/index.js +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/do/index.d.ts +83 -18
- package/dist/do/index.js +62 -6
- package/dist/do/index.js.map +1 -1
- package/dist/hono/cloudflare-workers.d.ts +4 -4
- package/dist/hono/cloudflare-workers.js +2 -2
- package/dist/hono/cloudflare-workers.js.map +1 -1
- package/dist/hono/index.d.ts +4 -4
- package/dist/hono/index.js +2 -2
- package/dist/hono/index.js.map +1 -1
- package/dist/react/index.d.ts +13 -13
- package/dist/react/index.js +1 -1
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.d.ts +8 -8
- package/dist/server/index.js +4 -4
- package/dist/server/index.js.map +1 -1
- package/dist/{socka-report-error-CXwpAUgl.d.ts → socka-report-error-nTXJIzNb.d.ts} +32 -12
- package/docs/README.md +2 -0
- package/docs/client.md +17 -0
- package/docs/collaborative-realtime.md +61 -0
- package/docs/durable-objects.md +84 -35
- package/docs/internals.md +1 -1
- package/docs/pushes.md +32 -2
- package/docs/react-durable-objects.md +96 -0
- package/docs/recipes.md +1 -1
- package/docs/reference.md +18 -5
- package/package.json +8 -8
- package/skills/socka/core-rpc/SKILL.md +1 -1
- package/skills/socka/do-session/SKILL.md +1 -1
- package/dist/chunk-5WQTYLIC.js.map +0 -1
- package/dist/chunk-LVVCHLNW.js.map +0 -1
- package/dist/chunk-P3JEEOJL.js.map +0 -1
package/README.md
CHANGED
|
@@ -16,6 +16,20 @@
|
|
|
16
16
|
|
|
17
17
|
**npm:** [`@firtoz/socka`](https://www.npmjs.com/package/@firtoz/socka). *Socka* is the project name in prose; **install and `import` paths always use `@firtoz/socka` or `@firtoz/socka/...`**. The published artifact is **compiled ESM + `.d.ts` in `dist/`** (see `package.json` `exports`).
|
|
18
18
|
|
|
19
|
+
## Call `output` shapes (at a glance)
|
|
20
|
+
|
|
21
|
+
| Goal | In `defineSocka` `calls` |
|
|
22
|
+
|------|--------------------------|
|
|
23
|
+
| Fire-and-forget (cursors, live drafts, high frequency) | **Omit** `output` |
|
|
24
|
+
| Request/response **`await`** after the handler runs | Normal **`output`** schema |
|
|
25
|
+
| Correlated **ack** with no payload | **`output: z.void()`** |
|
|
26
|
+
|
|
27
|
+
Details: **[Client — Fire-and-forget](./docs/client.md#fire-and-forget)** · **[Reference — Optional output](./docs/reference.md#optional-output-fire-and-forget)**. For **output-less** calls, **`void send.foo(...).catch(...)`** does not observe **`serverError`**—use **`reportError`** on **`SockaSession`** / **`useSockaSession`** (see **[Client — Fire-and-forget observability](./docs/client.md#fire-and-forget-observability)**).
|
|
28
|
+
|
|
29
|
+
**React + Cloudflare Durable Objects** — **[React + Durable Objects](./docs/react-durable-objects.md)** (shared contract, **`SockaWebSocketDO`**, **`useSockaSession`**, no casts). **Canvas / whiteboard-style** contract sketch: **[Collaborative realtime](./docs/collaborative-realtime.md)**.
|
|
30
|
+
|
|
31
|
+
Hand-written types next to Zod under **`exactOptionalPropertyTypes`** can break inference—see **[Reference — TypeScript and exact optional properties](./docs/reference.md#typescript-and-exact-optional-properties)**.
|
|
32
|
+
|
|
19
33
|
## Minimal example: multi-room chat (Bun)
|
|
20
34
|
|
|
21
35
|
Join/leave and live messages use **`pushes`**; persisted lines use **`listHistory`**; who is connected uses **`listPresence`**; **`clearHistory`** wipes stored messages and **`historyCleared`** notifies the room (examples also show presence in the UI). This snippet keeps **history in memory** so it stays short—see **[chatroom-bun](../../examples/chatroom-bun)** for **SQLite**, **[chatroom-hono](../../examples/chatroom-hono)** for **file JSON**, and **[chatroom-do](../../examples/chatroom-do)** for **Durable Object SQLite**.
|
|
@@ -255,7 +269,7 @@ Pick how the socket is upgraded, then use the matching import path and guide:
|
|
|
255
269
|
|
|
256
270
|
## Documentation
|
|
257
271
|
|
|
258
|
-
Hub: **[`docs/README.md`](./docs/README.md)** (getting started, peers, lifecycle, multi-room, reference).
|
|
272
|
+
Hub: **[`docs/README.md`](./docs/README.md)** (getting started, peers, lifecycle, multi-room, reference). **React + Cloudflare DO:** **[`docs/react-durable-objects.md`](./docs/react-durable-objects.md)** · **Collaborative / canvas contracts:** **[`docs/collaborative-realtime.md`](./docs/collaborative-realtime.md)**.
|
|
259
273
|
|
|
260
274
|
**Roadmap:** [deferred ideas and future work](./roadmap.md). Agent skills: [`skills/`](./skills/).
|
|
261
275
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as SockaContractBound, y as SockaWireFormat, f as InferSockaHandlers, B as SockaReportError, h as InferSockaPushPayload } from './socka-report-error-nTXJIzNb.js';
|
|
2
2
|
|
|
3
3
|
/** Session data with no fields — `createData` may be omitted (defaults to `{}`). */
|
|
4
4
|
type EmptySockaSessionData$1 = Record<string, never>;
|
|
@@ -50,8 +50,8 @@ type SockaWebSocketCreateDataStrict<TData> = [TData] extends [
|
|
|
50
50
|
} : {
|
|
51
51
|
createData: (init: SockaStrictWebSocketInit) => TData;
|
|
52
52
|
};
|
|
53
|
-
type SockaSessionForHandlers<TContract extends
|
|
54
|
-
type SockaWebSocketSessionConfigBase<TContract extends
|
|
53
|
+
type SockaSessionForHandlers<TContract extends SockaContractBound, TData> = SockaWebSocketSession<TContract, TData>;
|
|
54
|
+
type SockaWebSocketSessionConfigBase<TContract extends SockaContractBound, TData> = {
|
|
55
55
|
contract: TContract;
|
|
56
56
|
/** Default `"json"`. Use `"msgpack"` for binary frames (must match client). */
|
|
57
57
|
wireFormat?: SockaWireFormat;
|
|
@@ -92,7 +92,7 @@ type SockaWebSocketSessionConfigBase<TContract extends SockaContract<SockaContra
|
|
|
92
92
|
* {@link SockaWebSocketSessionConfigLoose} instead. See the **Server** guide section
|
|
93
93
|
* **Strict upgrade request** in the package docs.
|
|
94
94
|
*/
|
|
95
|
-
type SockaWebSocketSessionConfig<TContract extends
|
|
95
|
+
type SockaWebSocketSessionConfig<TContract extends SockaContractBound, TData = EmptySockaSessionData$1> = SockaWebSocketSessionConfigBase<TContract, TData> & SockaWebSocketCreateDataStrict<TData>;
|
|
96
96
|
/**
|
|
97
97
|
* Configuration for {@link SockaWebSocketSession} — **loose upgrade** (opt out of strict).
|
|
98
98
|
*
|
|
@@ -110,7 +110,7 @@ type SockaWebSocketSessionConfig<TContract extends SockaContract<SockaContractCo
|
|
|
110
110
|
* If you read query params or headers from the upgrade, guard for a missing **`request`**
|
|
111
111
|
* or switch to {@link SockaWebSocketSessionConfig} and wire the real **`Request`** through.
|
|
112
112
|
*/
|
|
113
|
-
type SockaWebSocketSessionConfigLoose<TContract extends
|
|
113
|
+
type SockaWebSocketSessionConfigLoose<TContract extends SockaContractBound, TData = EmptySockaSessionData$1> = SockaWebSocketSessionConfigBase<TContract, TData> & {
|
|
114
114
|
strictUpgradeRequest: false;
|
|
115
115
|
} & SockaWebSocketCreateData<TData>;
|
|
116
116
|
/**
|
|
@@ -118,7 +118,7 @@ type SockaWebSocketSessionConfigLoose<TContract extends SockaContract<SockaContr
|
|
|
118
118
|
* This is the type accepted by {@link SockaWebSocketSession}'s constructor,
|
|
119
119
|
* **`attachSockaWebSocket`**, **`createSockaBunWebSocketHandlers`**, and Hono socka helpers.
|
|
120
120
|
*/
|
|
121
|
-
type SockaWebSocketSessionConfigUnion<TContract extends
|
|
121
|
+
type SockaWebSocketSessionConfigUnion<TContract extends SockaContractBound, TData = EmptySockaSessionData$1> = SockaWebSocketSessionConfig<TContract, TData> | SockaWebSocketSessionConfigLoose<TContract, TData>;
|
|
122
122
|
|
|
123
123
|
/** Session data with no fields — `createData` may be omitted (defaults to `{}`). */
|
|
124
124
|
type EmptySockaSessionData = Record<string, never>;
|
|
@@ -130,7 +130,7 @@ type SockaEmitCapable = {
|
|
|
130
130
|
/**
|
|
131
131
|
* Contract-typed session surface for handlers that push to clients.
|
|
132
132
|
*/
|
|
133
|
-
interface SockaPushSession<TContract extends
|
|
133
|
+
interface SockaPushSession<TContract extends SockaContractBound> {
|
|
134
134
|
emitPush<K extends keyof TContract["pushes"] & string>(name: K, body: InferSockaPushPayload<TContract, K>): Promise<void>;
|
|
135
135
|
broadcastPush<K extends keyof TContract["pushes"] & string>(name: K, body: InferSockaPushPayload<TContract, K>, excludeSelf?: boolean): Promise<void>;
|
|
136
136
|
}
|
|
@@ -141,15 +141,33 @@ interface SockaPushSession<TContract extends SockaContract<SockaContractConfig>>
|
|
|
141
141
|
* Exclusion uses the **WebSocket** identity (`self.websocket`), not the session
|
|
142
142
|
* object reference, so the same `sessions` map can hold `SockaDoSession` while
|
|
143
143
|
* `broadcastPush` runs on `this.socka` (inner {@link SockaWebSocketSession}).
|
|
144
|
+
*
|
|
145
|
+
* When there is no caller session, use {@link broadcastSockaEventToAll} or
|
|
146
|
+
* {@link broadcastContractPushToAll} instead of picking an arbitrary anchor.
|
|
144
147
|
*/
|
|
145
148
|
declare function broadcastSockaEventToPeers(sessions: Map<WebSocket, SockaEmitCapable>, self: SockaEmitCapable & {
|
|
146
149
|
readonly websocket: WebSocket;
|
|
147
150
|
}, event: string, body: unknown, excludeSelf?: boolean): void;
|
|
151
|
+
/**
|
|
152
|
+
* Broadcast a socka server event to **every** session in the map. Payload must
|
|
153
|
+
* already be contract-validated.
|
|
154
|
+
*
|
|
155
|
+
* Use when there is no originating WebSocket session (HTTP admin routes, alarms,
|
|
156
|
+
* cron). Prefer {@link broadcastContractPushToAll} so validation stays centralized.
|
|
157
|
+
*/
|
|
158
|
+
declare function broadcastSockaEventToAll(sessions: Map<WebSocket, SockaEmitCapable>, event: string, body: unknown): void;
|
|
159
|
+
/**
|
|
160
|
+
* Validate a contract push payload and broadcast it to every session in the map.
|
|
161
|
+
*
|
|
162
|
+
* Works with any session type that implements {@link SockaEmitCapable} (including
|
|
163
|
+
* {@link SockaDoSession} on Durable Objects). No-op when `sessions` is empty.
|
|
164
|
+
*/
|
|
165
|
+
declare function broadcastContractPushToAll<TContract extends SockaContractBound, K extends keyof TContract["pushes"] & string>(sessions: Map<WebSocket, SockaEmitCapable>, contract: TContract, name: K, body: InferSockaPushPayload<TContract, K>): Promise<void>;
|
|
148
166
|
/**
|
|
149
167
|
* Runtime-agnostic socka server session: standard {@link WebSocket} wire
|
|
150
168
|
* dispatch without Cloudflare Durable Object APIs.
|
|
151
169
|
*/
|
|
152
|
-
declare class SockaWebSocketSession<TContract extends
|
|
170
|
+
declare class SockaWebSocketSession<TContract extends SockaContractBound, TData = EmptySockaSessionData> implements SockaPushSession<TContract> {
|
|
153
171
|
readonly websocket: WebSocket;
|
|
154
172
|
protected readonly sessions: Map<WebSocket, SockaWebSocketSession<TContract, TData>>;
|
|
155
173
|
private readonly config;
|
|
@@ -204,6 +222,6 @@ declare class SockaWebSocketSession<TContract extends SockaContract<SockaContrac
|
|
|
204
222
|
* Invoke {@link SockaWebSocketSessionConfig.onAttached} after the session is
|
|
205
223
|
* registered in the shared map.
|
|
206
224
|
*/
|
|
207
|
-
declare function runSockaSessionOnAttached<TContract extends
|
|
225
|
+
declare function runSockaSessionOnAttached<TContract extends SockaContractBound, TData>(config: SockaWebSocketSessionConfigUnion<TContract, TData>, session: SockaWebSocketSession<TContract, TData>): void;
|
|
208
226
|
|
|
209
|
-
export { type SockaStrictWebSocketInit as S, SockaWebSocketSession as a, type SockaWebSocketSessionConfigUnion as b, type SockaWebSocketInit as c, type
|
|
227
|
+
export { type SockaStrictWebSocketInit as S, SockaWebSocketSession as a, type SockaWebSocketSessionConfigUnion as b, type SockaWebSocketInit as c, type SockaWebSocketSessionConfig as d, broadcastContractPushToAll as e, broadcastSockaEventToAll as f, broadcastSockaEventToPeers as g, type SockaEmitCapable as h, type SockaPushSession as i, type SockaWebSocketSessionConfigLoose as j, runSockaSessionOnAttached as r };
|
package/dist/bun/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ServerWebSocket } from 'bun';
|
|
2
|
-
import {
|
|
3
|
-
import { S as SockaStrictWebSocketInit, a as SockaWebSocketSession, b as SockaWebSocketSessionConfigUnion } from '../SockaWebSocketSession-
|
|
2
|
+
import { c as SockaContractBound, y as SockaWireFormat } from '../socka-report-error-nTXJIzNb.js';
|
|
3
|
+
import { S as SockaStrictWebSocketInit, a as SockaWebSocketSession, b as SockaWebSocketSessionConfigUnion } from '../SockaWebSocketSession-BaGvSerM.js';
|
|
4
4
|
import '@standard-schema/spec';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -28,11 +28,11 @@ declare function sockaBunUpgrade<TExtra extends Record<string, unknown>>(server:
|
|
|
28
28
|
data: SockaBunUpgradeData<TExtra>;
|
|
29
29
|
}) => boolean;
|
|
30
30
|
}, req: Request, data?: TExtra): boolean;
|
|
31
|
-
type SockaBunResolveScope<TContract extends
|
|
31
|
+
type SockaBunResolveScope<TContract extends SockaContractBound, TData, TWsData = undefined> = (ws: ServerWebSocket<TWsData>) => {
|
|
32
32
|
sessionMap: Map<WebSocket, SockaWebSocketSession<TContract, TData>>;
|
|
33
33
|
config: SockaWebSocketSessionConfigUnion<TContract, TData>;
|
|
34
34
|
};
|
|
35
|
-
type SockaBunWebSocketHandlers<TContract extends
|
|
35
|
+
type SockaBunWebSocketHandlers<TContract extends SockaContractBound, TData, TWsData = undefined> = {
|
|
36
36
|
sessionMap: Map<WebSocket, SockaWebSocketSession<TContract, TData>>;
|
|
37
37
|
/** Pass into `Bun.serve({ ..., websocket })`. */
|
|
38
38
|
websocket: {
|
|
@@ -53,10 +53,10 @@ type SockaBunWebSocketHandlers<TContract extends SockaContract<SockaContractConf
|
|
|
53
53
|
* `sessionMap` and `config` for that socket’s scope (e.g. from `ws.data.roomId`).
|
|
54
54
|
* The returned `sessionMap` is an empty placeholder; real maps come from `resolveScope`.
|
|
55
55
|
*/
|
|
56
|
-
declare function createSockaBunWebSocketHandlers<TContract extends
|
|
56
|
+
declare function createSockaBunWebSocketHandlers<TContract extends SockaContractBound, TData>(config: SockaWebSocketSessionConfigUnion<TContract, TData>, options?: {
|
|
57
57
|
sessionMap?: Map<WebSocket, SockaWebSocketSession<TContract, TData>>;
|
|
58
58
|
}): SockaBunWebSocketHandlers<TContract, TData, undefined>;
|
|
59
|
-
declare function createSockaBunWebSocketHandlers<TContract extends
|
|
59
|
+
declare function createSockaBunWebSocketHandlers<TContract extends SockaContractBound, TData, TWsData>(options: {
|
|
60
60
|
resolveScope: SockaBunResolveScope<TContract, TData, TWsData>;
|
|
61
61
|
}): SockaBunWebSocketHandlers<TContract, TData, TWsData>;
|
|
62
62
|
|
package/dist/bun/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { dispatchSockaInboundMessage } from '../chunk-
|
|
2
|
-
import { SockaWebSocketSession, runSockaSessionOnAttached } from '../chunk-
|
|
1
|
+
import { dispatchSockaInboundMessage } from '../chunk-JR2GENNT.js';
|
|
2
|
+
import { SockaWebSocketSession, runSockaSessionOnAttached } from '../chunk-TTXY7O5P.js';
|
|
3
3
|
import { reportSockaError } from '../chunk-IFIGKR3W.js';
|
|
4
4
|
|
|
5
5
|
// src/bun/index.ts
|
package/dist/bun/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/bun/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { ServerWebSocket } from \"bun\";\nimport type { SockaContract, SockaContractConfig } from \"../core/contract\";\nimport { reportSockaError } from \"../core/socka-report-error\";\nimport type { SockaWireFormat } from \"../core/wire-codec\";\nimport { dispatchSockaInboundMessage } from \"../server/dispatchSockaInboundMessage\";\nimport {\n\tSockaWebSocketSession,\n\trunSockaSessionOnAttached,\n\ttype SockaStrictWebSocketInit,\n\ttype SockaWebSocketSessionConfigUnion,\n} from \"../server/SockaWebSocketSession\";\n\n/**\n * Reads the upgrade {@link Request} from Bun **`ServerWebSocket.data`** when your\n * **`fetch`** handler stored it there (e.g. **`server.upgrade(req, { data: { roomId, request: req } })`**).\n *\n * Pair with the default strict upgrade on {@link SockaWebSocketSessionConfig} so\n * **`createData`** is typed with {@link SockaStrictWebSocketInit} and **`init.request`**\n * is always defined. If **`request`** is missing from **`data`**, this returns **`undefined`**\n * and the session constructor will throw — that usually means you forgot\n * to pass **`request`** on upgrade (or set **`strictUpgradeRequest: false`**).\n */\nexport function sockaBunInitFromWsData(\n\tws: ServerWebSocket<unknown>,\n): SockaStrictWebSocketInit | undefined {\n\tconst d = ws.data as Record<string, unknown> | undefined;\n\tif (d && \"request\" in d && d.request instanceof Request) {\n\t\treturn { request: d.request };\n\t}\n\treturn undefined;\n}\n\n/** `ServerWebSocket.data` shape after {@link sockaBunUpgrade}. */\nexport type SockaBunUpgradeData<TExtra> = TExtra & { request: Request };\n\n/**\n * Calls {@link Bun.Server.upgrade} with **`request: req`** merged into **`data`**, so\n * {@link sockaBunInitFromWsData} and the default strict upgrade always see the HTTP\n * upgrade request (query params, cookies path).\n */\nexport function sockaBunUpgrade<TExtra extends Record<string, unknown>>(\n\tserver: {\n\t\tupgrade: (\n\t\t\treq: Request,\n\t\t\topts: { data: SockaBunUpgradeData<TExtra> },\n\t\t) => boolean;\n\t},\n\treq: Request,\n\tdata?: TExtra,\n): boolean {\n\tconst extra = (data ?? ({} as TExtra)) as TExtra;\n\treturn server.upgrade(req, { data: { ...extra, request: req } });\n}\n\nexport type SockaBunResolveScope<\n\tTContract extends SockaContract<SockaContractConfig>,\n\tTData,\n\tTWsData = undefined,\n> = (ws: ServerWebSocket<TWsData>) => {\n\tsessionMap: Map<WebSocket, SockaWebSocketSession<TContract, TData>>;\n\tconfig: SockaWebSocketSessionConfigUnion<TContract, TData>;\n};\n\nexport type SockaBunWebSocketHandlers<\n\tTContract extends SockaContract<SockaContractConfig>,\n\tTData,\n\tTWsData = undefined,\n> = {\n\tsessionMap: Map<WebSocket, SockaWebSocketSession<TContract, TData>>;\n\t/** Pass into `Bun.serve({ ..., websocket })`. */\n\twebsocket: {\n\t\topen: (ws: ServerWebSocket<TWsData>) => void;\n\t\tmessage: (\n\t\t\tws: ServerWebSocket<TWsData>,\n\t\t\tmessage: unknown,\n\t\t) => void | Promise<void>;\n\t\tclose: (ws: ServerWebSocket<TWsData>) => void | Promise<void>;\n\t};\n\twireFormat: SockaWireFormat;\n};\n\nfunction bunHandlersFromResolveScope<\n\tTContract extends SockaContract<SockaContractConfig>,\n\tTData,\n\tTWsData,\n>(\n\tresolveScope: SockaBunResolveScope<TContract, TData, TWsData>,\n): SockaBunWebSocketHandlers<TContract, TData, TWsData> {\n\tconst websocket: SockaBunWebSocketHandlers<\n\t\tTContract,\n\t\tTData,\n\t\tTWsData\n\t>[\"websocket\"] = {\n\t\topen(ws: ServerWebSocket<TWsData>) {\n\t\t\tconst { sessionMap, config } = resolveScope(ws);\n\t\t\tconst domWs = ws as unknown as WebSocket;\n\t\t\tconst init = sockaBunInitFromWsData(ws);\n\t\t\tconst session = new SockaWebSocketSession(\n\t\t\t\tdomWs,\n\t\t\t\tsessionMap,\n\t\t\t\tconfig,\n\t\t\t\tinit,\n\t\t\t);\n\t\t\tsessionMap.set(domWs, session);\n\t\t\trunSockaSessionOnAttached(config, session);\n\t\t},\n\t\tasync message(ws: ServerWebSocket<TWsData>, message: unknown) {\n\t\t\tconst { sessionMap, config } = resolveScope(ws);\n\t\t\tconst domWs = ws as unknown as WebSocket;\n\t\t\tconst session = sessionMap.get(domWs);\n\t\t\tif (!session) return;\n\t\t\tconst wireFormat = config.wireFormat ?? \"json\";\n\t\t\ttry {\n\t\t\t\tawait dispatchSockaInboundMessage(\n\t\t\t\t\tsession,\n\t\t\t\t\twireFormat,\n\t\t\t\t\tmessage as MessageEvent[\"data\"],\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\treportSockaError(config.reportError, {\n\t\t\t\t\tkind: \"serverInboundMessage\",\n\t\t\t\t\tadapter: \"bun\",\n\t\t\t\t\terror,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\tasync close(ws: ServerWebSocket<TWsData>) {\n\t\t\tconst { sessionMap, config } = resolveScope(ws);\n\t\t\tconst domWs = ws as unknown as WebSocket;\n\t\t\tconst session = sessionMap.get(domWs);\n\t\t\ttry {\n\t\t\t\tif (session) {\n\t\t\t\t\tawait session.invokeHandleClose();\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\treportSockaError(config.reportError, {\n\t\t\t\t\tkind: \"serverHandleClose\",\n\t\t\t\t\terror,\n\t\t\t\t});\n\t\t\t} finally {\n\t\t\t\tsessionMap.delete(domWs);\n\t\t\t}\n\t\t},\n\t};\n\n\treturn {\n\t\tsessionMap: new Map(),\n\t\twebsocket,\n\t\twireFormat: \"json\",\n\t};\n}\n\nfunction bunHandlersFromConfig<\n\tTContract extends SockaContract<SockaContractConfig>,\n\tTData,\n>(\n\tconfig: SockaWebSocketSessionConfigUnion<TContract, TData>,\n\tmaybeOptions?: {\n\t\tsessionMap?: Map<WebSocket, SockaWebSocketSession<TContract, TData>>;\n\t},\n): SockaBunWebSocketHandlers<TContract, TData, undefined> {\n\tconst sessionMap =\n\t\tmaybeOptions?.sessionMap ??\n\t\tnew Map<WebSocket, SockaWebSocketSession<TContract, TData>>();\n\tconst wireFormat = config.wireFormat ?? \"json\";\n\n\tconst websocket: SockaBunWebSocketHandlers<\n\t\tTContract,\n\t\tTData,\n\t\tundefined\n\t>[\"websocket\"] = {\n\t\topen(ws: ServerWebSocket<undefined>) {\n\t\t\tconst domWs = ws as unknown as WebSocket;\n\t\t\tconst init = sockaBunInitFromWsData(ws);\n\t\t\tconst session = new SockaWebSocketSession(\n\t\t\t\tdomWs,\n\t\t\t\tsessionMap,\n\t\t\t\tconfig,\n\t\t\t\tinit,\n\t\t\t);\n\t\t\tsessionMap.set(domWs, session);\n\t\t\trunSockaSessionOnAttached(config, session);\n\t\t},\n\t\tasync message(ws: ServerWebSocket<undefined>, message: unknown) {\n\t\t\tconst domWs = ws as unknown as WebSocket;\n\t\t\tconst session = sessionMap.get(domWs);\n\t\t\tif (!session) return;\n\t\t\ttry {\n\t\t\t\tawait dispatchSockaInboundMessage(\n\t\t\t\t\tsession,\n\t\t\t\t\twireFormat,\n\t\t\t\t\tmessage as MessageEvent[\"data\"],\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\treportSockaError(config.reportError, {\n\t\t\t\t\tkind: \"serverInboundMessage\",\n\t\t\t\t\tadapter: \"bun\",\n\t\t\t\t\terror,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\tasync close(ws: ServerWebSocket<undefined>) {\n\t\t\tconst domWs = ws as unknown as WebSocket;\n\t\t\tconst session = sessionMap.get(domWs);\n\t\t\ttry {\n\t\t\t\tif (session) {\n\t\t\t\t\tawait session.invokeHandleClose();\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\treportSockaError(config.reportError, {\n\t\t\t\t\tkind: \"serverHandleClose\",\n\t\t\t\t\terror,\n\t\t\t\t});\n\t\t\t} finally {\n\t\t\t\tsessionMap.delete(domWs);\n\t\t\t}\n\t\t},\n\t};\n\n\treturn { sessionMap, websocket, wireFormat };\n}\n\n/**\n * WebSocket handlers for `Bun.serve` when using `ServerWebSocket` (no\n * `addEventListener`). Inbound frames are dispatched with the same logic as\n * `attachSockaWebSocket`.\n *\n * **Single-room:** pass a {@link SockaWebSocketSessionConfig} and optional shared `sessionMap`.\n *\n * **Multi-room:** pass `{ resolveScope }` where `resolveScope(ws)` returns the\n * `sessionMap` and `config` for that socket’s scope (e.g. from `ws.data.roomId`).\n * The returned `sessionMap` is an empty placeholder; real maps come from `resolveScope`.\n */\nexport function createSockaBunWebSocketHandlers<\n\tTContract extends SockaContract<SockaContractConfig>,\n\tTData,\n>(\n\tconfig: SockaWebSocketSessionConfigUnion<TContract, TData>,\n\toptions?: {\n\t\tsessionMap?: Map<WebSocket, SockaWebSocketSession<TContract, TData>>;\n\t},\n): SockaBunWebSocketHandlers<TContract, TData, undefined>;\n\nexport function createSockaBunWebSocketHandlers<\n\tTContract extends SockaContract<SockaContractConfig>,\n\tTData,\n\tTWsData,\n>(options: {\n\tresolveScope: SockaBunResolveScope<TContract, TData, TWsData>;\n}): SockaBunWebSocketHandlers<TContract, TData, TWsData>;\n\nexport function createSockaBunWebSocketHandlers<\n\tTContract extends SockaContract<SockaContractConfig>,\n\tTData,\n>(\n\tconfigOrOptions:\n\t\t| SockaWebSocketSessionConfigUnion<TContract, TData>\n\t\t| { resolveScope: SockaBunResolveScope<TContract, TData, unknown> },\n\tmaybeOptions?: {\n\t\tsessionMap?: Map<WebSocket, SockaWebSocketSession<TContract, TData>>;\n\t},\n):\n\t| SockaBunWebSocketHandlers<TContract, TData, undefined>\n\t| SockaBunWebSocketHandlers<TContract, TData, unknown> {\n\tconst isResolveScope =\n\t\ttypeof configOrOptions === \"object\" &&\n\t\tconfigOrOptions !== null &&\n\t\t\"resolveScope\" in configOrOptions &&\n\t\ttypeof (configOrOptions as { resolveScope: unknown }).resolveScope ===\n\t\t\t\"function\";\n\n\tif (isResolveScope) {\n\t\treturn bunHandlersFromResolveScope(\n\t\t\t(\n\t\t\t\tconfigOrOptions as {\n\t\t\t\t\tresolveScope: SockaBunResolveScope<TContract, TData, unknown>;\n\t\t\t\t}\n\t\t\t).resolveScope,\n\t\t);\n\t}\n\treturn bunHandlersFromConfig(\n\t\tconfigOrOptions as SockaWebSocketSessionConfigUnion<TContract, TData>,\n\t\tmaybeOptions,\n\t);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/bun/index.ts"],"names":[],"mappings":";;;;;AAsBO,SAAS,uBACf,EAAA,EACuC;AACvC,EAAA,MAAM,IAAI,EAAA,CAAG,IAAA;AACb,EAAA,IAAI,CAAA,IAAK,SAAA,IAAa,CAAA,IAAK,CAAA,CAAE,mBAAmB,OAAA,EAAS;AACxD,IAAA,OAAO,EAAE,OAAA,EAAS,CAAA,CAAE,OAAA,EAAQ;AAAA,EAC7B;AACA,EAAA,OAAO,MAAA;AACR;AAUO,SAAS,eAAA,CACf,MAAA,EAMA,GAAA,EACA,IAAA,EACU;AACV,EAAA,MAAM,KAAA,GAAS,QAAS,EAAC;AACzB,EAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,GAAA,EAAK,EAAE,IAAA,EAAM,EAAE,GAAG,KAAA,EAAO,OAAA,EAAS,GAAA,EAAI,EAAG,CAAA;AAChE;AA6BA,SAAS,4BAKR,YAAA,EACuD;AACvD,EAAA,MAAM,SAAA,GAIW;AAAA,IAChB,KAAK,EAAA,EAA8B;AAClC,MAAA,MAAM,EAAE,UAAA,EAAY,MAAA,EAAO,GAAI,aAAa,EAAE,CAAA;AAC9C,MAAA,MAAM,KAAA,GAAQ,EAAA;AACd,MAAA,MAAM,IAAA,GAAO,uBAAuB,EAAE,CAAA;AACtC,MAAA,MAAM,UAAU,IAAI,qBAAA;AAAA,QACnB,KAAA;AAAA,QACA,UAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA,OACD;AACA,MAAA,UAAA,CAAW,GAAA,CAAI,OAAO,OAAO,CAAA;AAC7B,MAAA,yBAAA,CAA0B,QAAQ,OAAO,CAAA;AAAA,IAC1C,CAAA;AAAA,IACA,MAAM,OAAA,CAAQ,EAAA,EAA8B,OAAA,EAAkB;AAC7D,MAAA,MAAM,EAAE,UAAA,EAAY,MAAA,EAAO,GAAI,aAAa,EAAE,CAAA;AAC9C,MAAA,MAAM,KAAA,GAAQ,EAAA;AACd,MAAA,MAAM,OAAA,GAAU,UAAA,CAAW,GAAA,CAAI,KAAK,CAAA;AACpC,MAAA,IAAI,CAAC,OAAA,EAAS;AACd,MAAA,MAAM,UAAA,GAAa,OAAO,UAAA,IAAc,MAAA;AACxC,MAAA,IAAI;AACH,QAAA,MAAM,2BAAA;AAAA,UACL,OAAA;AAAA,UACA,UAAA;AAAA,UACA;AAAA,SACD;AAAA,MACD,SAAS,KAAA,EAAO;AACf,QAAA,gBAAA,CAAiB,OAAO,WAAA,EAAa;AAAA,UACpC,IAAA,EAAM,sBAAA;AAAA,UACN,OAAA,EAAS,KAAA;AAAA,UACT;AAAA,SACA,CAAA;AAAA,MACF;AAAA,IACD,CAAA;AAAA,IACA,MAAM,MAAM,EAAA,EAA8B;AACzC,MAAA,MAAM,EAAE,UAAA,EAAY,MAAA,EAAO,GAAI,aAAa,EAAE,CAAA;AAC9C,MAAA,MAAM,KAAA,GAAQ,EAAA;AACd,MAAA,MAAM,OAAA,GAAU,UAAA,CAAW,GAAA,CAAI,KAAK,CAAA;AACpC,MAAA,IAAI;AACH,QAAA,IAAI,OAAA,EAAS;AACZ,UAAA,MAAM,QAAQ,iBAAA,EAAkB;AAAA,QACjC;AAAA,MACD,SAAS,KAAA,EAAO;AACf,QAAA,gBAAA,CAAiB,OAAO,WAAA,EAAa;AAAA,UACpC,IAAA,EAAM,mBAAA;AAAA,UACN;AAAA,SACA,CAAA;AAAA,MACF,CAAA,SAAE;AACD,QAAA,UAAA,CAAW,OAAO,KAAK,CAAA;AAAA,MACxB;AAAA,IACD;AAAA,GACD;AAEA,EAAA,OAAO;AAAA,IACN,UAAA,sBAAgB,GAAA,EAAI;AAAA,IACpB,SAAA;AAAA,IACA,UAAA,EAAY;AAAA,GACb;AACD;AAEA,SAAS,qBAAA,CACR,QACA,YAAA,EAGyD;AACzD,EAAA,MAAM,UAAA,GACL,YAAA,EAAc,UAAA,oBACd,IAAI,GAAA,EAAwD;AAC7D,EAAA,MAAM,UAAA,GAAa,OAAO,UAAA,IAAc,MAAA;AAExC,EAAA,MAAM,SAAA,GAIW;AAAA,IAChB,KAAK,EAAA,EAAgC;AACpC,MAAA,MAAM,KAAA,GAAQ,EAAA;AACd,MAAA,MAAM,IAAA,GAAO,uBAAuB,EAAE,CAAA;AACtC,MAAA,MAAM,UAAU,IAAI,qBAAA;AAAA,QACnB,KAAA;AAAA,QACA,UAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA,OACD;AACA,MAAA,UAAA,CAAW,GAAA,CAAI,OAAO,OAAO,CAAA;AAC7B,MAAA,yBAAA,CAA0B,QAAQ,OAAO,CAAA;AAAA,IAC1C,CAAA;AAAA,IACA,MAAM,OAAA,CAAQ,EAAA,EAAgC,OAAA,EAAkB;AAC/D,MAAA,MAAM,KAAA,GAAQ,EAAA;AACd,MAAA,MAAM,OAAA,GAAU,UAAA,CAAW,GAAA,CAAI,KAAK,CAAA;AACpC,MAAA,IAAI,CAAC,OAAA,EAAS;AACd,MAAA,IAAI;AACH,QAAA,MAAM,2BAAA;AAAA,UACL,OAAA;AAAA,UACA,UAAA;AAAA,UACA;AAAA,SACD;AAAA,MACD,SAAS,KAAA,EAAO;AACf,QAAA,gBAAA,CAAiB,OAAO,WAAA,EAAa;AAAA,UACpC,IAAA,EAAM,sBAAA;AAAA,UACN,OAAA,EAAS,KAAA;AAAA,UACT;AAAA,SACA,CAAA;AAAA,MACF;AAAA,IACD,CAAA;AAAA,IACA,MAAM,MAAM,EAAA,EAAgC;AAC3C,MAAA,MAAM,KAAA,GAAQ,EAAA;AACd,MAAA,MAAM,OAAA,GAAU,UAAA,CAAW,GAAA,CAAI,KAAK,CAAA;AACpC,MAAA,IAAI;AACH,QAAA,IAAI,OAAA,EAAS;AACZ,UAAA,MAAM,QAAQ,iBAAA,EAAkB;AAAA,QACjC;AAAA,MACD,SAAS,KAAA,EAAO;AACf,QAAA,gBAAA,CAAiB,OAAO,WAAA,EAAa;AAAA,UACpC,IAAA,EAAM,mBAAA;AAAA,UACN;AAAA,SACA,CAAA;AAAA,MACF,CAAA,SAAE;AACD,QAAA,UAAA,CAAW,OAAO,KAAK,CAAA;AAAA,MACxB;AAAA,IACD;AAAA,GACD;AAEA,EAAA,OAAO,EAAE,UAAA,EAAY,SAAA,EAAW,UAAA,EAAW;AAC5C;AA+BO,SAAS,+BAAA,CAIf,iBAGA,YAAA,EAKuD;AACvD,EAAA,MAAM,cAAA,GACL,OAAO,eAAA,KAAoB,QAAA,IAC3B,eAAA,KAAoB,QACpB,cAAA,IAAkB,eAAA,IAClB,OAAQ,eAAA,CAA8C,YAAA,KACrD,UAAA;AAEF,EAAA,IAAI,cAAA,EAAgB;AACnB,IAAA,OAAO,2BAAA;AAAA,MAEL,eAAA,CAGC;AAAA,KACH;AAAA,EACD;AACA,EAAA,OAAO,qBAAA;AAAA,IACN,eAAA;AAAA,IACA;AAAA,GACD;AACD","file":"index.js","sourcesContent":["import type { ServerWebSocket } from \"bun\";\nimport type { SockaContractBound } from \"../core/contract\";\nimport { reportSockaError } from \"../core/socka-report-error\";\nimport type { SockaWireFormat } from \"../core/wire-codec\";\nimport { dispatchSockaInboundMessage } from \"../server/dispatchSockaInboundMessage\";\nimport {\n\tSockaWebSocketSession,\n\trunSockaSessionOnAttached,\n\ttype SockaStrictWebSocketInit,\n\ttype SockaWebSocketSessionConfigUnion,\n} from \"../server/SockaWebSocketSession\";\n\n/**\n * Reads the upgrade {@link Request} from Bun **`ServerWebSocket.data`** when your\n * **`fetch`** handler stored it there (e.g. **`server.upgrade(req, { data: { roomId, request: req } })`**).\n *\n * Pair with the default strict upgrade on {@link SockaWebSocketSessionConfig} so\n * **`createData`** is typed with {@link SockaStrictWebSocketInit} and **`init.request`**\n * is always defined. If **`request`** is missing from **`data`**, this returns **`undefined`**\n * and the session constructor will throw — that usually means you forgot\n * to pass **`request`** on upgrade (or set **`strictUpgradeRequest: false`**).\n */\nexport function sockaBunInitFromWsData(\n\tws: ServerWebSocket<unknown>,\n): SockaStrictWebSocketInit | undefined {\n\tconst d = ws.data as Record<string, unknown> | undefined;\n\tif (d && \"request\" in d && d.request instanceof Request) {\n\t\treturn { request: d.request };\n\t}\n\treturn undefined;\n}\n\n/** `ServerWebSocket.data` shape after {@link sockaBunUpgrade}. */\nexport type SockaBunUpgradeData<TExtra> = TExtra & { request: Request };\n\n/**\n * Calls {@link Bun.Server.upgrade} with **`request: req`** merged into **`data`**, so\n * {@link sockaBunInitFromWsData} and the default strict upgrade always see the HTTP\n * upgrade request (query params, cookies path).\n */\nexport function sockaBunUpgrade<TExtra extends Record<string, unknown>>(\n\tserver: {\n\t\tupgrade: (\n\t\t\treq: Request,\n\t\t\topts: { data: SockaBunUpgradeData<TExtra> },\n\t\t) => boolean;\n\t},\n\treq: Request,\n\tdata?: TExtra,\n): boolean {\n\tconst extra = (data ?? ({} as TExtra)) as TExtra;\n\treturn server.upgrade(req, { data: { ...extra, request: req } });\n}\n\nexport type SockaBunResolveScope<\n\tTContract extends SockaContractBound,\n\tTData,\n\tTWsData = undefined,\n> = (ws: ServerWebSocket<TWsData>) => {\n\tsessionMap: Map<WebSocket, SockaWebSocketSession<TContract, TData>>;\n\tconfig: SockaWebSocketSessionConfigUnion<TContract, TData>;\n};\n\nexport type SockaBunWebSocketHandlers<\n\tTContract extends SockaContractBound,\n\tTData,\n\tTWsData = undefined,\n> = {\n\tsessionMap: Map<WebSocket, SockaWebSocketSession<TContract, TData>>;\n\t/** Pass into `Bun.serve({ ..., websocket })`. */\n\twebsocket: {\n\t\topen: (ws: ServerWebSocket<TWsData>) => void;\n\t\tmessage: (\n\t\t\tws: ServerWebSocket<TWsData>,\n\t\t\tmessage: unknown,\n\t\t) => void | Promise<void>;\n\t\tclose: (ws: ServerWebSocket<TWsData>) => void | Promise<void>;\n\t};\n\twireFormat: SockaWireFormat;\n};\n\nfunction bunHandlersFromResolveScope<\n\tTContract extends SockaContractBound,\n\tTData,\n\tTWsData,\n>(\n\tresolveScope: SockaBunResolveScope<TContract, TData, TWsData>,\n): SockaBunWebSocketHandlers<TContract, TData, TWsData> {\n\tconst websocket: SockaBunWebSocketHandlers<\n\t\tTContract,\n\t\tTData,\n\t\tTWsData\n\t>[\"websocket\"] = {\n\t\topen(ws: ServerWebSocket<TWsData>) {\n\t\t\tconst { sessionMap, config } = resolveScope(ws);\n\t\t\tconst domWs = ws as unknown as WebSocket;\n\t\t\tconst init = sockaBunInitFromWsData(ws);\n\t\t\tconst session = new SockaWebSocketSession(\n\t\t\t\tdomWs,\n\t\t\t\tsessionMap,\n\t\t\t\tconfig,\n\t\t\t\tinit,\n\t\t\t);\n\t\t\tsessionMap.set(domWs, session);\n\t\t\trunSockaSessionOnAttached(config, session);\n\t\t},\n\t\tasync message(ws: ServerWebSocket<TWsData>, message: unknown) {\n\t\t\tconst { sessionMap, config } = resolveScope(ws);\n\t\t\tconst domWs = ws as unknown as WebSocket;\n\t\t\tconst session = sessionMap.get(domWs);\n\t\t\tif (!session) return;\n\t\t\tconst wireFormat = config.wireFormat ?? \"json\";\n\t\t\ttry {\n\t\t\t\tawait dispatchSockaInboundMessage(\n\t\t\t\t\tsession,\n\t\t\t\t\twireFormat,\n\t\t\t\t\tmessage as MessageEvent[\"data\"],\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\treportSockaError(config.reportError, {\n\t\t\t\t\tkind: \"serverInboundMessage\",\n\t\t\t\t\tadapter: \"bun\",\n\t\t\t\t\terror,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\tasync close(ws: ServerWebSocket<TWsData>) {\n\t\t\tconst { sessionMap, config } = resolveScope(ws);\n\t\t\tconst domWs = ws as unknown as WebSocket;\n\t\t\tconst session = sessionMap.get(domWs);\n\t\t\ttry {\n\t\t\t\tif (session) {\n\t\t\t\t\tawait session.invokeHandleClose();\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\treportSockaError(config.reportError, {\n\t\t\t\t\tkind: \"serverHandleClose\",\n\t\t\t\t\terror,\n\t\t\t\t});\n\t\t\t} finally {\n\t\t\t\tsessionMap.delete(domWs);\n\t\t\t}\n\t\t},\n\t};\n\n\treturn {\n\t\tsessionMap: new Map(),\n\t\twebsocket,\n\t\twireFormat: \"json\",\n\t};\n}\n\nfunction bunHandlersFromConfig<TContract extends SockaContractBound, TData>(\n\tconfig: SockaWebSocketSessionConfigUnion<TContract, TData>,\n\tmaybeOptions?: {\n\t\tsessionMap?: Map<WebSocket, SockaWebSocketSession<TContract, TData>>;\n\t},\n): SockaBunWebSocketHandlers<TContract, TData, undefined> {\n\tconst sessionMap =\n\t\tmaybeOptions?.sessionMap ??\n\t\tnew Map<WebSocket, SockaWebSocketSession<TContract, TData>>();\n\tconst wireFormat = config.wireFormat ?? \"json\";\n\n\tconst websocket: SockaBunWebSocketHandlers<\n\t\tTContract,\n\t\tTData,\n\t\tundefined\n\t>[\"websocket\"] = {\n\t\topen(ws: ServerWebSocket<undefined>) {\n\t\t\tconst domWs = ws as unknown as WebSocket;\n\t\t\tconst init = sockaBunInitFromWsData(ws);\n\t\t\tconst session = new SockaWebSocketSession(\n\t\t\t\tdomWs,\n\t\t\t\tsessionMap,\n\t\t\t\tconfig,\n\t\t\t\tinit,\n\t\t\t);\n\t\t\tsessionMap.set(domWs, session);\n\t\t\trunSockaSessionOnAttached(config, session);\n\t\t},\n\t\tasync message(ws: ServerWebSocket<undefined>, message: unknown) {\n\t\t\tconst domWs = ws as unknown as WebSocket;\n\t\t\tconst session = sessionMap.get(domWs);\n\t\t\tif (!session) return;\n\t\t\ttry {\n\t\t\t\tawait dispatchSockaInboundMessage(\n\t\t\t\t\tsession,\n\t\t\t\t\twireFormat,\n\t\t\t\t\tmessage as MessageEvent[\"data\"],\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\treportSockaError(config.reportError, {\n\t\t\t\t\tkind: \"serverInboundMessage\",\n\t\t\t\t\tadapter: \"bun\",\n\t\t\t\t\terror,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\tasync close(ws: ServerWebSocket<undefined>) {\n\t\t\tconst domWs = ws as unknown as WebSocket;\n\t\t\tconst session = sessionMap.get(domWs);\n\t\t\ttry {\n\t\t\t\tif (session) {\n\t\t\t\t\tawait session.invokeHandleClose();\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\treportSockaError(config.reportError, {\n\t\t\t\t\tkind: \"serverHandleClose\",\n\t\t\t\t\terror,\n\t\t\t\t});\n\t\t\t} finally {\n\t\t\t\tsessionMap.delete(domWs);\n\t\t\t}\n\t\t},\n\t};\n\n\treturn { sessionMap, websocket, wireFormat };\n}\n\n/**\n * WebSocket handlers for `Bun.serve` when using `ServerWebSocket` (no\n * `addEventListener`). Inbound frames are dispatched with the same logic as\n * `attachSockaWebSocket`.\n *\n * **Single-room:** pass a {@link SockaWebSocketSessionConfig} and optional shared `sessionMap`.\n *\n * **Multi-room:** pass `{ resolveScope }` where `resolveScope(ws)` returns the\n * `sessionMap` and `config` for that socket’s scope (e.g. from `ws.data.roomId`).\n * The returned `sessionMap` is an empty placeholder; real maps come from `resolveScope`.\n */\nexport function createSockaBunWebSocketHandlers<\n\tTContract extends SockaContractBound,\n\tTData,\n>(\n\tconfig: SockaWebSocketSessionConfigUnion<TContract, TData>,\n\toptions?: {\n\t\tsessionMap?: Map<WebSocket, SockaWebSocketSession<TContract, TData>>;\n\t},\n): SockaBunWebSocketHandlers<TContract, TData, undefined>;\n\nexport function createSockaBunWebSocketHandlers<\n\tTContract extends SockaContractBound,\n\tTData,\n\tTWsData,\n>(options: {\n\tresolveScope: SockaBunResolveScope<TContract, TData, TWsData>;\n}): SockaBunWebSocketHandlers<TContract, TData, TWsData>;\n\nexport function createSockaBunWebSocketHandlers<\n\tTContract extends SockaContractBound,\n\tTData,\n>(\n\tconfigOrOptions:\n\t\t| SockaWebSocketSessionConfigUnion<TContract, TData>\n\t\t| { resolveScope: SockaBunResolveScope<TContract, TData, unknown> },\n\tmaybeOptions?: {\n\t\tsessionMap?: Map<WebSocket, SockaWebSocketSession<TContract, TData>>;\n\t},\n):\n\t| SockaBunWebSocketHandlers<TContract, TData, undefined>\n\t| SockaBunWebSocketHandlers<TContract, TData, unknown> {\n\tconst isResolveScope =\n\t\ttypeof configOrOptions === \"object\" &&\n\t\tconfigOrOptions !== null &&\n\t\t\"resolveScope\" in configOrOptions &&\n\t\ttypeof (configOrOptions as { resolveScope: unknown }).resolveScope ===\n\t\t\t\"function\";\n\n\tif (isResolveScope) {\n\t\treturn bunHandlersFromResolveScope(\n\t\t\t(\n\t\t\t\tconfigOrOptions as {\n\t\t\t\t\tresolveScope: SockaBunResolveScope<TContract, TData, unknown>;\n\t\t\t\t}\n\t\t\t).resolveScope,\n\t\t);\n\t}\n\treturn bunHandlersFromConfig(\n\t\tconfigOrOptions as SockaWebSocketSessionConfigUnion<TContract, TData>,\n\t\tmaybeOptions,\n\t);\n}\n"]}
|
|
@@ -42,5 +42,5 @@ async function dispatchSockaInboundMessage(session, wireFormat, data) {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
export { dispatchSockaInboundMessage };
|
|
45
|
-
//# sourceMappingURL=chunk-
|
|
46
|
-
//# sourceMappingURL=chunk-
|
|
45
|
+
//# sourceMappingURL=chunk-JR2GENNT.js.map
|
|
46
|
+
//# sourceMappingURL=chunk-JR2GENNT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server/dispatchSockaInboundMessage.ts"],"names":[],"mappings":";AAUA,eAAsB,2BAAA,CAIrB,OAAA,EACA,UAAA,EACA,IAAA,EACgB;AAChB,EAAA,IAAI,OAAO,SAAS,QAAA,EAAU;AAC7B,IAAA,MAAM,OAAA,CAAQ,iBAAiB,IAAI,CAAA;AACnC,IAAA;AAAA,EACD;AACA,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,MAAA,CAAO,QAAA,CAAS,IAAI,CAAA,EAAG;AAC3D,IAAA,IAAI,eAAe,MAAA,EAAQ;AAC1B,MAAA,MAAM,OAAA,CAAQ,gBAAA,CAAiB,IAAA,CAAK,QAAA,CAAS,MAAM,CAAC,CAAA;AACpD,MAAA;AAAA,IACD;AACA,IAAA,MAAM,QAAQ,mBAAA,CAAoB,IAAI,UAAA,CAAW,IAAI,EAAE,MAAM,CAAA;AAC7D,IAAA;AAAA,EACD;AACA,EAAA,IAAI,gBAAgB,WAAA,EAAa;AAChC,IAAA,IAAI,eAAe,MAAA,EAAQ;AAC1B,MAAA,MAAM,QAAQ,gBAAA,CAAiB,IAAI,aAAY,CAAE,MAAA,CAAO,IAAI,CAAC,CAAA;AAC7D,MAAA;AAAA,IACD;AACA,IAAA,MAAM,OAAA,CAAQ,oBAAoB,IAAI,CAAA;AACtC,IAAA;AAAA,EACD;AACA,EAAA,IAAI,gBAAgB,IAAA,EAAM;AACzB,IAAA,IAAI,eAAe,MAAA,EAAQ;AAC1B,MAAA,MAAM,OAAA,CAAQ,gBAAA,CAAiB,MAAM,IAAA,CAAK,MAAM,CAAA;AAAA,IACjD,CAAA,MAAO;AACN,MAAA,MAAM,OAAA,CAAQ,mBAAA,CAAoB,MAAM,IAAA,CAAK,aAAa,CAAA;AAAA,IAC3D;AACA,IAAA;AAAA,EACD;AACA,EAAA,IAAI,WAAA,CAAY,MAAA,CAAO,IAAI,CAAA,EAAG;AAC7B,IAAA,MAAM,CAAA,GAAI,IAAA;AACV,IAAA,MAAM,IAAA,GAAO,IAAI,UAAA,CAAW,CAAA,CAAE,QAAQ,CAAA,CAAE,UAAA,EAAY,EAAE,UAAU,CAAA;AAChE,IAAA,IAAI,eAAe,MAAA,EAAQ;AAC1B,MAAA,MAAM,QAAQ,gBAAA,CAAiB,IAAI,aAAY,CAAE,MAAA,CAAO,IAAI,CAAC,CAAA;AAC7D,MAAA;AAAA,IACD;AACA,IAAA,MAAM,IAAA,GAAO,IAAI,UAAA,CAAW,IAAA,CAAK,MAAM,CAAA;AACvC,IAAA,IAAA,CAAK,IAAI,IAAI,CAAA;AACb,IAAA,MAAM,OAAA,CAAQ,mBAAA,CAAoB,IAAA,CAAK,MAAM,CAAA;AAAA,EAC9C;AACD","file":"chunk-JR2GENNT.js","sourcesContent":["import type { SockaContractBound } from \"../core/contract\";\nimport type { SockaWireFormat } from \"../core/wire-codec\";\nimport type { SockaWebSocketSession } from \"./SockaWebSocketSession\";\n\n/**\n * Decode a WebSocket `message` payload and dispatch it to the session (same\n * behavior as the `message` handler installed by {@link attachSockaWebSocket}).\n * Use this when the runtime does not support `addEventListener` on the socket\n * (e.g. Bun {@link ServerWebSocket}) or when handling messages manually.\n */\nexport async function dispatchSockaInboundMessage<\n\tTContract extends SockaContractBound,\n\tTData,\n>(\n\tsession: SockaWebSocketSession<TContract, TData>,\n\twireFormat: SockaWireFormat,\n\tdata: MessageEvent[\"data\"],\n): Promise<void> {\n\tif (typeof data === \"string\") {\n\t\tawait session.handleRawMessage(data);\n\t\treturn;\n\t}\n\tif (typeof Buffer !== \"undefined\" && Buffer.isBuffer(data)) {\n\t\tif (wireFormat === \"json\") {\n\t\t\tawait session.handleRawMessage(data.toString(\"utf8\"));\n\t\t\treturn;\n\t\t}\n\t\tawait session.handleBinaryMessage(new Uint8Array(data).buffer);\n\t\treturn;\n\t}\n\tif (data instanceof ArrayBuffer) {\n\t\tif (wireFormat === \"json\") {\n\t\t\tawait session.handleRawMessage(new TextDecoder().decode(data));\n\t\t\treturn;\n\t\t}\n\t\tawait session.handleBinaryMessage(data);\n\t\treturn;\n\t}\n\tif (data instanceof Blob) {\n\t\tif (wireFormat === \"json\") {\n\t\t\tawait session.handleRawMessage(await data.text());\n\t\t} else {\n\t\t\tawait session.handleBinaryMessage(await data.arrayBuffer());\n\t\t}\n\t\treturn;\n\t}\n\tif (ArrayBuffer.isView(data)) {\n\t\tconst v = data;\n\t\tconst view = new Uint8Array(v.buffer, v.byteOffset, v.byteLength);\n\t\tif (wireFormat === \"json\") {\n\t\t\tawait session.handleRawMessage(new TextDecoder().decode(view));\n\t\t\treturn;\n\t\t}\n\t\tconst copy = new Uint8Array(view.length);\n\t\tcopy.set(view);\n\t\tawait session.handleBinaryMessage(copy.buffer);\n\t}\n}\n"]}
|
|
@@ -599,5 +599,5 @@ var SockaSessionBase = class {
|
|
|
599
599
|
var SockaSession = SockaSessionBase;
|
|
600
600
|
|
|
601
601
|
export { SockaSession, SockaWebSocketClient };
|
|
602
|
-
//# sourceMappingURL=chunk-
|
|
603
|
-
//# sourceMappingURL=chunk-
|
|
602
|
+
//# sourceMappingURL=chunk-THFUHQJ3.js.map
|
|
603
|
+
//# sourceMappingURL=chunk-THFUHQJ3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client/SockaWebSocketClient.ts","../src/client/SockaSession.ts"],"names":["entry"],"mappings":"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","file":"chunk-THFUHQJ3.js","sourcesContent":["import type { SockaContractBound } from \"../core/contract\";\nimport {\n\tSockaWireError,\n\tdecodeSockaWire,\n\tencodeClientRequest,\n} from \"../core/envelope\";\nimport type {\n\tSockaServerResponseFrame,\n\tSockaServerErrorFrame,\n\tSockaServerEventFrame,\n} from \"../core/envelope\";\nimport {\n\tencodeSockaWire,\n\tparseWirePayload,\n\ttype SockaWireFormat,\n} from \"../core/wire-codec\";\n\nexport interface SockaWebSocketClientOptions<\n\tTContract extends SockaContractBound,\n> {\n\tcontract: TContract;\n\t/** Default `\"json\"` (text frames). Use `\"msgpack\"` for binary `ArrayBuffer` frames. */\n\twireFormat?: SockaWireFormat;\n\turl?: string;\n\twebSocket?: WebSocket;\n\t/**\n\t * When `false`, the socket is not created until {@link SockaWebSocketClient.connect}\n\t * (or the first operation that implicitly opens, e.g. {@link SockaSession} `send`).\n\t * Default `true`.\n\t */\n\tautoConnect?: boolean;\n\tserializeJson?: (value: unknown) => string;\n\tdeserializeJson?: (raw: string) => unknown;\n\tonOpen?: (event: Event) => void;\n\tonClose?: (event: CloseEvent) => void;\n\tonError?: (event: Event) => void;\n\tonResponse?: (frame: SockaServerResponseFrame) => void;\n\tonServerError?: (frame: SockaServerErrorFrame) => void;\n\tonEvent?: (frame: SockaServerEventFrame) => void;\n\tonValidationError?: (error: Error, rawMessage: unknown) => void;\n\t/**\n\t * Automatic reconnect after an abnormal close. **Disabled by default** when\n\t * {@link webSocket} is injected (tests); enabled when using {@link url}.\n\t * Pass `false` to disable.\n\t */\n\treconnect?: false | SockaReconnectConfig;\n\t/** Fired before a reconnect attempt is scheduled (after delay is chosen). */\n\tonReconnecting?: (info: SockaReconnectingInfo) => void;\n\t/** Fired after a new socket reaches `open` following a reconnect. */\n\tonReconnected?: (info: SockaReconnectedInfo) => void;\n}\n\n/** Options for {@link SockaWebSocketClientOptions.reconnect}. */\nexport type SockaReconnectConfig = {\n\t/** Default `1000`. */\n\tinitialDelayMs?: number;\n\t/** Default `30000`. */\n\tmaxDelayMs?: number;\n\t/** 0–1 fraction of delay to randomize. Default `0.2`. */\n\tjitter?: number;\n\t/** Omit for infinite attempts. */\n\tmaxAttempts?: number;\n\t/**\n\t * When `true` (default), delay reconnect until `document` is visible again.\n\t */\n\tpauseWhenHidden?: boolean;\n};\n\nexport type SockaReconnectingInfo = {\n\tattempt: number;\n\tdelayMs: number;\n};\n\nexport type SockaReconnectedInfo = {\n\tattempt: number;\n};\n\n/** High-level connection lifecycle for UI and telemetry. */\nexport type SockaConnectionStatus =\n\t| \"idle\"\n\t| \"connecting\"\n\t| \"open\"\n\t| \"reconnecting\"\n\t| \"closed\";\n\n/**\n * Browser WebSocket client driven by a socka contract. Sends client request\n * frames and dispatches decoded server frames to callbacks.\n */\nexport class SockaWebSocketClient<TContract extends SockaContractBound> {\n\tprivate ws: WebSocket | undefined;\n\tprivate readonly opts: SockaWebSocketClientOptions<TContract>;\n\tprivate readonly wireFormat: SockaWireFormat;\n\tprivate readonly serializeJson: (value: unknown) => string;\n\tprivate readonly deserializeJson: (raw: string) => unknown;\n\tprivate readonly onResponseCb?: (frame: SockaServerResponseFrame) => void;\n\tprivate readonly onServerErrorCb?: (frame: SockaServerErrorFrame) => void;\n\tprivate readonly onEventCb?: (frame: SockaServerEventFrame) => void;\n\tprivate readonly onValidationError?: (\n\t\terror: Error,\n\t\trawMessage: unknown,\n\t) => void;\n\n\treadonly contract: TContract;\n\n\tprivate manualClose = false;\n\tprivate reconnectAttempt = 0;\n\tprivate reconnectTimer: ReturnType<typeof setTimeout> | undefined;\n\n\tprivate _status: SockaConnectionStatus;\n\tprivate readonly statusListeners = new Set<\n\t\t(status: SockaConnectionStatus) => void\n\t>();\n\n\tconstructor(options: SockaWebSocketClientOptions<TContract>) {\n\t\tthis.opts = options;\n\t\tthis.contract = options.contract;\n\t\tthis.wireFormat = options.wireFormat ?? \"json\";\n\t\tthis.serializeJson = options.serializeJson ?? JSON.stringify;\n\t\tthis.deserializeJson = options.deserializeJson ?? JSON.parse;\n\t\tthis.onResponseCb = options.onResponse;\n\t\tthis.onServerErrorCb = options.onServerError;\n\t\tthis.onEventCb = options.onEvent;\n\t\tthis.onValidationError = options.onValidationError;\n\n\t\tif (options.autoConnect !== false) {\n\t\t\tthis._status = \"connecting\";\n\t\t\tthis.attachSocket(this.createSocket());\n\t\t} else {\n\t\t\tthis._status = \"idle\";\n\t\t}\n\t}\n\n\tprivate setStatus(next: SockaConnectionStatus): void {\n\t\tif (this._status === next) return;\n\t\tthis._status = next;\n\t\tfor (const fn of this.statusListeners) {\n\t\t\tfn(next);\n\t\t}\n\t}\n\n\t/** Current connection lifecycle state. */\n\tget status(): SockaConnectionStatus {\n\t\treturn this._status;\n\t}\n\n\t/**\n\t * Subscribe to {@link status} changes. The listener is called immediately with the\n\t * current status, then on every transition. Returns an unsubscribe function.\n\t */\n\tonStatusChange(\n\t\tlistener: (status: SockaConnectionStatus) => void,\n\t): () => void {\n\t\tthis.statusListeners.add(listener);\n\t\tlistener(this._status);\n\t\treturn () => {\n\t\t\tthis.statusListeners.delete(listener);\n\t\t};\n\t}\n\n\tprivate createSocket(): WebSocket {\n\t\tif (this.opts.webSocket) {\n\t\t\treturn this.opts.webSocket;\n\t\t}\n\t\tif (this.opts.url) {\n\t\t\treturn new WebSocket(this.opts.url);\n\t\t}\n\t\tthrow new Error(\"Either 'url' or 'webSocket' must be provided\");\n\t}\n\n\tprivate attachSocket(ws: WebSocket): void {\n\t\tthis.setStatus(\"connecting\");\n\t\tthis.ws = ws;\n\t\tif (this.wireFormat === \"msgpack\") {\n\t\t\tws.binaryType = \"arraybuffer\";\n\t\t}\n\n\t\tws.addEventListener(\"open\", (event) => {\n\t\t\tconst prev = this.reconnectAttempt;\n\t\t\tthis.reconnectAttempt = 0;\n\t\t\tif (prev > 0) {\n\t\t\t\tthis.opts.onReconnected?.({ attempt: prev });\n\t\t\t}\n\t\t\tthis.setStatus(\"open\");\n\t\t\tthis.opts.onOpen?.(event);\n\t\t});\n\n\t\tws.addEventListener(\"message\", (event) => {\n\t\t\tthis.handleMessageEvent(event);\n\t\t});\n\n\t\tws.addEventListener(\"close\", (event) => {\n\t\t\tthis.opts.onClose?.(event);\n\t\t\tif (this.manualClose) {\n\t\t\t\tthis.setStatus(\"closed\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!this.getReconnectEnabled()) {\n\t\t\t\tthis.setStatus(\"closed\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst cfg = this.resolveReconnectConfig();\n\t\t\tconst maxAttempts = cfg.maxAttempts;\n\t\t\tif (maxAttempts !== undefined && this.reconnectAttempt >= maxAttempts) {\n\t\t\t\tthis.setStatus(\"closed\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.maybeScheduleReconnect();\n\t\t});\n\n\t\tws.addEventListener(\"error\", (event) => {\n\t\t\tthis.opts.onError?.(event);\n\t\t});\n\t}\n\n\tprivate getReconnectEnabled(): boolean {\n\t\tif (this.opts.reconnect === false) return false;\n\t\tif (\n\t\t\tthis.opts.webSocket !== undefined &&\n\t\t\tthis.opts.reconnect === undefined\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t\treturn this.opts.url !== undefined;\n\t}\n\n\tprivate resolveReconnectConfig(): SockaReconnectConfig {\n\t\tconst r = this.opts.reconnect;\n\t\tif (r === false) return {};\n\t\treturn r ?? {};\n\t}\n\n\tprivate computeReconnectDelayMs(\n\t\tattempt: number,\n\t\tcfg: SockaReconnectConfig,\n\t): number {\n\t\tconst initial = cfg.initialDelayMs ?? 1000;\n\t\tconst max = cfg.maxDelayMs ?? 30000;\n\t\tconst jitterRatio = cfg.jitter ?? 0.2;\n\t\tconst base = Math.min(max, initial * 2 ** Math.max(0, attempt - 1));\n\t\tconst spread = base * jitterRatio;\n\t\treturn Math.max(0, base + (Math.random() * 2 - 1) * spread);\n\t}\n\n\tprivate maybeScheduleReconnect(): void {\n\t\tif (this.manualClose) return;\n\t\tif (!this.getReconnectEnabled()) return;\n\t\tconst cfg = this.resolveReconnectConfig();\n\t\tconst maxAttempts = cfg.maxAttempts;\n\t\tif (maxAttempts !== undefined && this.reconnectAttempt >= maxAttempts) {\n\t\t\treturn;\n\t\t}\n\t\tif (\n\t\t\tcfg.pauseWhenHidden !== false &&\n\t\t\ttypeof document !== \"undefined\" &&\n\t\t\tdocument.hidden\n\t\t) {\n\t\t\tthis.setStatus(\"reconnecting\");\n\t\t\tconst onVis = (): void => {\n\t\t\t\tif (!document.hidden) {\n\t\t\t\t\tdocument.removeEventListener(\"visibilitychange\", onVis);\n\t\t\t\t\tthis.maybeScheduleReconnect();\n\t\t\t\t}\n\t\t\t};\n\t\t\tdocument.addEventListener(\"visibilitychange\", onVis);\n\t\t\treturn;\n\t\t}\n\t\tthis.reconnectAttempt += 1;\n\t\tthis.setStatus(\"reconnecting\");\n\t\tconst delayMs = this.computeReconnectDelayMs(this.reconnectAttempt, cfg);\n\t\tthis.opts.onReconnecting?.({ attempt: this.reconnectAttempt, delayMs });\n\t\tif (this.reconnectTimer !== undefined) {\n\t\t\tclearTimeout(this.reconnectTimer);\n\t\t}\n\t\tthis.reconnectTimer = setTimeout(() => {\n\t\t\tthis.reconnectTimer = undefined;\n\t\t\tif (this.manualClose) return;\n\t\t\tthis.openReplacementSocket();\n\t\t}, delayMs);\n\t}\n\n\tprivate openReplacementSocket(): void {\n\t\tif (this.manualClose) return;\n\t\tif (!this.opts.url) return;\n\t\tthis.ws = undefined;\n\t\tthis.attachSocket(this.createSocket());\n\t}\n\n\tprivate handleMessageEvent(event: MessageEvent): void {\n\t\ttry {\n\t\t\tconst fmt = this.wireFormat;\n\t\t\tlet payload: string | ArrayBuffer;\n\t\t\tif (fmt === \"json\") {\n\t\t\t\tif (typeof event.data !== \"string\") {\n\t\t\t\t\tthis.onValidationError?.(\n\t\t\t\t\t\tnew Error(\"socka: expected JSON text frame\"),\n\t\t\t\t\t\tevent.data,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tpayload = event.data;\n\t\t\t} else {\n\t\t\t\tif (!(event.data instanceof ArrayBuffer)) {\n\t\t\t\t\tthis.onValidationError?.(\n\t\t\t\t\t\tnew Error(\"socka: expected ArrayBuffer msgpack frame\"),\n\t\t\t\t\t\tevent.data,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tpayload = event.data;\n\t\t\t}\n\n\t\t\tlet parsed: unknown;\n\t\t\ttry {\n\t\t\t\tparsed = parseWirePayload(payload, fmt, this.deserializeJson);\n\t\t\t} catch (err) {\n\t\t\t\tthis.onValidationError?.(\n\t\t\t\t\terr instanceof Error ? err : new Error(String(err)),\n\t\t\t\t\tevent.data,\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet decoded: ReturnType<typeof decodeSockaWire>;\n\t\t\ttry {\n\t\t\t\tdecoded = decodeSockaWire(parsed);\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof SockaWireError) {\n\t\t\t\t\tthis.onValidationError?.(err, parsed);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t\tswitch (decoded.kind) {\n\t\t\t\tcase \"serverResponse\":\n\t\t\t\t\tthis.onResponseCb?.(decoded.frame);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"serverError\":\n\t\t\t\t\tthis.onServerErrorCb?.(decoded.frame);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"serverEvent\":\n\t\t\t\t\tthis.onEventCb?.(decoded.frame);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"clientRequest\":\n\t\t\t\t\tthis.onValidationError?.(\n\t\t\t\t\t\tnew Error(\"socka: unexpected clientRequest frame from server\"),\n\t\t\t\t\t\tparsed,\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault: {\n\t\t\t\t\tconst _exhaustive: never = decoded;\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`socka: unexpected wire decode branch ${JSON.stringify(_exhaustive)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst err = error instanceof Error ? error : new Error(String(error));\n\t\t\tthis.onValidationError?.(err, event.data);\n\t\t}\n\t}\n\n\t/**\n\t * Creates the WebSocket (when {@link SockaWebSocketClientOptions.autoConnect}\n\t * was `false`) and waits until the connection is open.\n\t */\n\tasync connect(): Promise<void> {\n\t\tif (!this.ws) {\n\t\t\tthis.attachSocket(this.createSocket());\n\t\t}\n\t\tawait this.waitForOpen();\n\t}\n\n\tsendRequest(id: string, rpc: string, body: Record<string, unknown>): void {\n\t\tif (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n\t\t\tthrow new Error(\"WebSocket is not open\");\n\t\t}\n\t\tconst frame = encodeClientRequest(id, rpc, body);\n\t\tconst encoded = encodeSockaWire(frame, this.wireFormat, this.serializeJson);\n\t\tif (typeof encoded === \"string\") {\n\t\t\tthis.ws.send(encoded);\n\t\t\treturn;\n\t\t}\n\t\tconst copy = new Uint8Array(encoded.byteLength);\n\t\tcopy.set(encoded);\n\t\tthis.ws.send(copy.buffer);\n\t}\n\n\tclose(code?: number, reason?: string): void {\n\t\tthis.manualClose = true;\n\t\tif (this.reconnectTimer !== undefined) {\n\t\t\tclearTimeout(this.reconnectTimer);\n\t\t\tthis.reconnectTimer = undefined;\n\t\t}\n\t\tthis.setStatus(\"closed\");\n\t\tthis.ws?.close(code, reason);\n\t}\n\n\tget readyState(): number {\n\t\treturn this.ws?.readyState ?? WebSocket.CONNECTING;\n\t}\n\n\tget socket(): WebSocket {\n\t\tif (!this.ws) {\n\t\t\tthrow new Error(\n\t\t\t\t\"socka: WebSocket not created yet; call connect() first or use autoConnect: true\",\n\t\t\t);\n\t\t}\n\t\treturn this.ws;\n\t}\n\n\tasync waitForOpen(): Promise<void> {\n\t\tconst ws = this.ws;\n\t\tif (!ws) {\n\t\t\tthrow new Error(\n\t\t\t\t\"socka: WebSocket not created yet; call connect() first or use autoConnect: true\",\n\t\t\t);\n\t\t}\n\t\tif (ws.readyState === WebSocket.OPEN) {\n\t\t\treturn;\n\t\t}\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst abortController = new AbortController();\n\t\t\tconst { signal } = abortController;\n\t\t\tconst cleanup = () => {\n\t\t\t\tabortController.abort();\n\t\t\t};\n\t\t\tws.addEventListener(\n\t\t\t\t\"open\",\n\t\t\t\t() => {\n\t\t\t\t\tcleanup();\n\t\t\t\t\tresolve();\n\t\t\t\t},\n\t\t\t\t{ signal },\n\t\t\t);\n\t\t\tws.addEventListener(\n\t\t\t\t\"error\",\n\t\t\t\t() => {\n\t\t\t\t\tcleanup();\n\t\t\t\t\treject(new Error(\"WebSocket connection failed\"));\n\t\t\t\t},\n\t\t\t\t{ signal },\n\t\t\t);\n\t\t});\n\t}\n}\n","import type {\n\tSockaContractBound,\n\tInferSockaSend,\n\tInferSockaPushHandlers,\n\tInferSockaPushPayload,\n} from \"../core/contract\";\nimport {\n\treportSockaError,\n\ttype SockaReportError,\n} from \"../core/socka-report-error\";\nimport { parseStandardSchema } from \"../core/validate\";\nimport { SockaError } from \"../core/socka-error\";\nimport type {\n\tSockaServerResponseFrame,\n\tSockaServerErrorFrame,\n\tSockaServerEventFrame,\n} from \"../core/envelope\";\nimport {\n\tSockaWebSocketClient,\n\ttype SockaConnectionStatus,\n\ttype SockaWebSocketClientOptions,\n} from \"./SockaWebSocketClient\";\nimport { RESERVED_SOCKA_PROCEDURE_NAMES } from \"../core/reserved-procedure-names\";\n\ntype PendingEntry = {\n\trpc: string;\n\tresolve: (value: unknown) => void;\n\treject: (error: Error) => void;\n};\n\ntype PushListenerFn = (payload: unknown) => void | Promise<void>;\n\n/** Same strings as `RESERVED_SOCKA_PROCEDURE_NAMES` (core) for O(1) lookup on `send`. */\nconst RESERVED_CALL_NAMES = new Set<string>(RESERVED_SOCKA_PROCEDURE_NAMES);\n\nexport type SockaSessionPushWaitOptions<\n\tTContract extends SockaContractBound,\n\tK extends keyof TContract[\"pushes\"] & string,\n> = {\n\tsignal?: AbortSignal;\n\ttimeoutMs?: number;\n\tpredicate?: (payload: InferSockaPushPayload<TContract, K>) => boolean;\n};\n\nexport type SockaSessionSubscribeApi<TContract extends SockaContractBound> = {\n\ton<K extends keyof TContract[\"pushes\"] & string>(\n\t\tname: K,\n\t\thandler: (\n\t\t\tpayload: InferSockaPushPayload<TContract, K>,\n\t\t) => void | Promise<void>,\n\t): void;\n\toff<K extends keyof TContract[\"pushes\"] & string>(\n\t\tname: K,\n\t\thandler: (\n\t\t\tpayload: InferSockaPushPayload<TContract, K>,\n\t\t) => void | Promise<void>,\n\t): void;\n\tonce<K extends keyof TContract[\"pushes\"] & string>(\n\t\tname: K,\n\t\thandler: (\n\t\t\tpayload: InferSockaPushPayload<TContract, K>,\n\t\t) => void | Promise<void>,\n\t): void;\n\twaitForPush<K extends keyof TContract[\"pushes\"] & string>(\n\t\tname: K,\n\t\toptions?: SockaSessionPushWaitOptions<TContract, K>,\n\t): Promise<InferSockaPushPayload<TContract, K>>;\n};\n\nfunction waitForPushAbortError(): Error {\n\tif (typeof DOMException !== \"undefined\") {\n\t\treturn new DOMException(\"waitForPush aborted\", \"AbortError\");\n\t}\n\treturn new Error(\"socka: waitForPush aborted\");\n}\n\nexport type SockaSessionOptions<TContract extends SockaContractBound> = Omit<\n\tSockaWebSocketClientOptions<TContract>,\n\t\"onResponse\" | \"onServerError\" | \"onEvent\"\n> & {\n\tonOpen?: (event: Event) => void;\n\tonClose?: (event: CloseEvent) => void;\n\tonError?: (event: Event) => void;\n\tpushHandlers?: Partial<InferSockaPushHandlers<TContract>>;\n\t/**\n\t * Optional sink for client-side push pipeline failures (listener throws,\n\t * push payload validation). Defaults to `console.error`; see\n\t * `SockaReportError` in `@firtoz/socka/core`.\n\t */\n\treportError?: (event: SockaReportError) => void;\n};\n\n/**\n * Browser WebSocket session: **`session.send`** for contract calls, **`session.subscribe`**\n * for server pushes, **`session.client`** for low-level wire access.\n */\nclass SockaSessionBase<TContract extends SockaContractBound> {\n\treadonly client: SockaWebSocketClient<TContract>;\n\treadonly send: InferSockaSend<TContract>;\n\treadonly subscribe: SockaSessionSubscribeApi<TContract>;\n\n\tprivate readonly pending = new Map<string, PendingEntry>();\n\tprivate idSeq = 0;\n\tprivate readonly pushListeners = new Map<string, Set<PushListenerFn>>();\n\tprivate readonly reportError?: (event: SockaReportError) => void;\n\n\tconstructor(options: SockaSessionOptions<TContract>) {\n\t\tconst { pushHandlers, reportError, ...clientOpts } = options;\n\t\tthis.reportError = reportError;\n\n\t\tthis.client = new SockaWebSocketClient({\n\t\t\t...clientOpts,\n\t\t\tonResponse: (frame) => this.handleResponse(frame),\n\t\t\tonServerError: (frame) => this.handleServerError(frame),\n\t\t\tonEvent: (frame) => this.handleEvent(frame),\n\t\t});\n\n\t\tthis.subscribe = this.createSubscribeApi();\n\n\t\tconst sendBag = this.buildSendMethods();\n\t\tfor (const name of Object.keys(sendBag)) {\n\t\t\tif (RESERVED_CALL_NAMES.has(name)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`socka: call name \"${name}\" is reserved on SockaSession.send; rename it in defineSocka`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tthis.send = sendBag;\n\n\t\tif (pushHandlers) {\n\t\t\tfor (const key of Object.keys(pushHandlers) as Array<\n\t\t\t\tkeyof InferSockaPushHandlers<TContract> & string\n\t\t\t>) {\n\t\t\t\tconst fn = pushHandlers[key];\n\t\t\t\tif (fn) {\n\t\t\t\t\tthis.subscribe.on(key, fn);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate createSubscribeApi(): SockaSessionSubscribeApi<TContract> {\n\t\treturn {\n\t\t\ton: (name, handler) => {\n\t\t\t\tthis.addPushListener(name, handler as PushListenerFn);\n\t\t\t},\n\t\t\toff: (name, handler) => {\n\t\t\t\tthis.removePushListener(name, handler as PushListenerFn);\n\t\t\t},\n\t\t\tonce: (name, handler) => {\n\t\t\t\tconst wrapped: PushListenerFn = (payload: unknown) => {\n\t\t\t\t\tthis.removePushListener(name, wrapped);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst result = (handler as (p: unknown) => void | Promise<void>)(\n\t\t\t\t\t\t\tpayload,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tvoid Promise.resolve(result).catch((error: unknown) => {\n\t\t\t\t\t\t\treportSockaError(this.reportError, {\n\t\t\t\t\t\t\t\tkind: \"clientEventListener\",\n\t\t\t\t\t\t\t\teventName: String(name),\n\t\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\treportSockaError(this.reportError, {\n\t\t\t\t\t\t\tkind: \"clientEventListener\",\n\t\t\t\t\t\t\teventName: String(name),\n\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tthis.addPushListener(name, wrapped);\n\t\t\t},\n\t\t\twaitForPush: (name, options) => this.waitForPushImpl(name, options),\n\t\t};\n\t}\n\n\tprivate addPushListener(name: string, handler: PushListenerFn): void {\n\t\tlet set = this.pushListeners.get(name);\n\t\tif (!set) {\n\t\t\tset = new Set();\n\t\t\tthis.pushListeners.set(name, set);\n\t\t}\n\t\tset.add(handler);\n\t}\n\n\tprivate removePushListener(name: string, handler: PushListenerFn): void {\n\t\tthis.pushListeners.get(name)?.delete(handler);\n\t}\n\n\tprivate waitForPushImpl<K extends keyof TContract[\"pushes\"] & string>(\n\t\tname: K,\n\t\toptions?: SockaSessionPushWaitOptions<TContract, K>,\n\t): Promise<InferSockaPushPayload<TContract, K>> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst signal = options?.signal;\n\t\t\tif (signal?.aborted) {\n\t\t\t\treject(waitForPushAbortError());\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst onAbort = () => {\n\t\t\t\tcleanup();\n\t\t\t\treject(waitForPushAbortError());\n\t\t\t};\n\t\t\tsignal?.addEventListener(\"abort\", onAbort);\n\n\t\t\tlet timeoutId: ReturnType<typeof setTimeout> | undefined;\n\t\t\tif (options?.timeoutMs != null) {\n\t\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\t\tcleanup();\n\t\t\t\t\treject(new Error(\"socka: waitForPush timed out\"));\n\t\t\t\t}, options.timeoutMs);\n\t\t\t}\n\n\t\t\tconst listener: PushListenerFn = (payload: unknown) => {\n\t\t\t\tif (\n\t\t\t\t\toptions?.predicate &&\n\t\t\t\t\t!options.predicate(payload as InferSockaPushPayload<TContract, K>)\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tcleanup();\n\t\t\t\tresolve(payload as InferSockaPushPayload<TContract, K>);\n\t\t\t};\n\n\t\t\tconst cleanup = () => {\n\t\t\t\tif (timeoutId !== undefined) clearTimeout(timeoutId);\n\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\tthis.removePushListener(name, listener);\n\t\t\t};\n\n\t\t\tthis.addPushListener(name, listener);\n\t\t});\n\t}\n\n\tprivate buildSendMethods(): InferSockaSend<TContract> {\n\t\tconst methods: Record<string, (input?: unknown) => Promise<unknown>> = {};\n\n\t\tfor (const name of Object.keys(this.client.contract.calls)) {\n\t\t\tconst proc = this.client.contract.calls[name];\n\t\t\tif (proc.input) {\n\t\t\t\tmethods[name] = (input: unknown) => this.call(name, input);\n\t\t\t} else {\n\t\t\t\tmethods[name] = () => this.call(name, undefined);\n\t\t\t}\n\t\t}\n\n\t\treturn methods as InferSockaSend<TContract>;\n\t}\n\n\tprivate call(callName: string, input: unknown): Promise<unknown> {\n\t\treturn (async () => {\n\t\t\tawait this.client.connect();\n\t\t\tif (this.client.readyState !== WebSocket.OPEN) {\n\t\t\t\tthrow new Error(\"WebSocket not connected\");\n\t\t\t}\n\t\t\tconst id = this.nextId(callName);\n\t\t\tconst body =\n\t\t\t\tinput !== undefined && input !== null\n\t\t\t\t\t? (input as Record<string, unknown>)\n\t\t\t\t\t: {};\n\t\t\tconst proc = this.client.contract.calls[callName];\n\t\t\tif (proc !== undefined && proc.output === undefined) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.client.sendRequest(id, callName, body);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tthrow err instanceof Error ? err : new Error(String(err));\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treturn new Promise<unknown>((resolve, reject) => {\n\t\t\t\tthis.pending.set(id, { rpc: callName, resolve, reject });\n\t\t\t\ttry {\n\t\t\t\t\tthis.client.sendRequest(id, callName, body);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tthis.pending.delete(id);\n\t\t\t\t\treject(err instanceof Error ? err : new Error(String(err)));\n\t\t\t\t}\n\t\t\t});\n\t\t})();\n\t}\n\n\tprivate handleResponse(frame: SockaServerResponseFrame): void {\n\t\tconst proc = this.client.contract.calls[frame.rpc];\n\t\tif (!proc) {\n\t\t\tconst entry = this.pending.get(frame.id);\n\t\t\tif (entry) {\n\t\t\t\tthis.pending.delete(frame.id);\n\t\t\t\tentry.reject(new SockaError(`Unknown call: ${frame.rpc}`));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (proc.output === undefined) {\n\t\t\tconst entry = this.pending.get(frame.id);\n\t\t\tif (entry) {\n\t\t\t\tthis.pending.delete(frame.id);\n\t\t\t\treportSockaError(this.reportError, {\n\t\t\t\t\tkind: \"clientUnexpectedServerResponse\",\n\t\t\t\t\trpc: frame.rpc,\n\t\t\t\t\trequestId: frame.id,\n\t\t\t\t});\n\t\t\t\tentry.reject(\n\t\t\t\t\tnew SockaError(\n\t\t\t\t\t\t\"socka: unexpected serverResponse for fire-and-forget call\",\n\t\t\t\t\t\t{ requestId: frame.id, rpc: frame.rpc },\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\treportSockaError(this.reportError, {\n\t\t\t\t\tkind: \"clientUnexpectedServerResponse\",\n\t\t\t\t\trpc: frame.rpc,\n\t\t\t\t\trequestId: frame.id,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst entry = this.pending.get(frame.id);\n\t\tif (!entry) return;\n\t\tthis.pending.delete(frame.id);\n\n\t\tvoid parseStandardSchema(proc.output, frame.body).then(\n\t\t\t(validated) => entry.resolve(validated),\n\t\t\t(err) =>\n\t\t\t\tentry.reject(err instanceof Error ? err : new Error(String(err))),\n\t\t);\n\t}\n\n\tprivate handleServerError(frame: SockaServerErrorFrame): void {\n\t\tconst entry = this.pending.get(frame.id);\n\t\tif (entry) {\n\t\t\tthis.pending.delete(frame.id);\n\t\t\tentry.reject(SockaError.fromWire(frame));\n\t\t\treturn;\n\t\t}\n\n\t\tconst err = SockaError.fromWire(frame);\n\t\tconst rpcName = frame.rpc;\n\t\tif (rpcName === undefined) {\n\t\t\treportSockaError(this.reportError, {\n\t\t\t\tkind: \"clientFireAndForgetRpcError\",\n\t\t\t\terror: err,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tconst proc = this.client.contract.calls[rpcName];\n\t\tif (proc !== undefined && proc.output === undefined) {\n\t\t\treportSockaError(this.reportError, {\n\t\t\t\tkind: \"clientFireAndForgetRpcError\",\n\t\t\t\terror: err,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\treportSockaError(this.reportError, {\n\t\t\tkind: \"clientOrphanServerError\",\n\t\t\terror: err,\n\t\t});\n\t}\n\n\tprivate handleEvent(frame: SockaServerEventFrame): void {\n\t\tconst schema = (\n\t\t\tthis.client.contract.pushes as Record<\n\t\t\t\tstring,\n\t\t\t\tParameters<typeof parseStandardSchema>[0] | undefined\n\t\t\t>\n\t\t)[frame.event];\n\t\tif (schema) {\n\t\t\tvoid parseStandardSchema(schema, frame.body).then(\n\t\t\t\t(validated) => this.dispatchValidatedPush(frame.event, validated),\n\t\t\t\t(error: unknown) =>\n\t\t\t\t\treportSockaError(this.reportError, {\n\t\t\t\t\t\tkind: \"clientEventValidation\",\n\t\t\t\t\t\teventName: frame.event,\n\t\t\t\t\t\terror,\n\t\t\t\t\t}),\n\t\t\t);\n\t\t} else {\n\t\t\tthis.dispatchValidatedPush(frame.event, frame.body);\n\t\t}\n\t}\n\n\tprivate dispatchValidatedPush(pushName: string, payload: unknown): void {\n\t\tconst set = this.pushListeners.get(pushName);\n\t\tif (!set || set.size === 0) return;\n\t\tfor (const fn of [...set]) {\n\t\t\ttry {\n\t\t\t\tconst result = fn(payload);\n\t\t\t\tvoid Promise.resolve(result).catch((error: unknown) => {\n\t\t\t\t\treportSockaError(this.reportError, {\n\t\t\t\t\t\tkind: \"clientEventListener\",\n\t\t\t\t\t\teventName: pushName,\n\t\t\t\t\t\terror,\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\treportSockaError(this.reportError, {\n\t\t\t\t\tkind: \"clientEventListener\",\n\t\t\t\t\teventName: pushName,\n\t\t\t\t\terror,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate nextId(prefix: string): string {\n\t\treturn `${prefix}-${++this.idSeq}`;\n\t}\n\n\trejectAllPending(reason: Error): void {\n\t\tfor (const [, entry] of this.pending) {\n\t\t\tentry.reject(reason);\n\t\t}\n\t\tthis.pending.clear();\n\t}\n\n\tclose(code?: number, reason?: string): void {\n\t\tthis.client.close(code, reason);\n\t}\n\n\t/** Opens the WebSocket when using {@link SockaWebSocketClientOptions.autoConnect} `false`. */\n\tconnect(): Promise<void> {\n\t\treturn this.client.connect();\n\t}\n\n\t/** Same as {@link SockaWebSocketClient.status}. */\n\tget status(): SockaConnectionStatus {\n\t\treturn this.client.status;\n\t}\n\n\t/** Same as {@link SockaWebSocketClient.onStatusChange}. */\n\tonStatusChange(\n\t\tlistener: (status: SockaConnectionStatus) => void,\n\t): () => void {\n\t\treturn this.client.onStatusChange(listener);\n\t}\n}\n\nexport type SockaSession<TContract extends SockaContractBound> =\n\tSockaSessionBase<TContract>;\n\nexport interface SockaSessionConstructor {\n\tnew <TContract extends SockaContractBound>(\n\t\toptions: SockaSessionOptions<TContract>,\n\t): SockaSession<TContract>;\n}\n\n/**\n * WebSocket session: **`session.send`** for contract calls, **`session.subscribe`** for server pushes.\n */\nexport const SockaSession: SockaSessionConstructor =\n\tSockaSessionBase as SockaSessionConstructor;\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseWirePayload, decodeSockaWire, SockaWireError, encodeServerError,
|
|
1
|
+
import { parseStandardSchema, parseWirePayload, decodeSockaWire, SockaWireError, encodeServerError, SockaError, encodeServerResponse, encodeSockaWire, encodeServerEvent, reportSockaError } from './chunk-IFIGKR3W.js';
|
|
2
2
|
import { exhaustiveGuard } from '@firtoz/maybe-error';
|
|
3
3
|
|
|
4
4
|
function isLooseUpgradeConfig(config) {
|
|
@@ -10,6 +10,22 @@ function broadcastSockaEventToPeers(sessions, self, event, body, excludeSelf = f
|
|
|
10
10
|
session.emitWireEvent(event, body);
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
|
+
function broadcastSockaEventToAll(sessions, event, body) {
|
|
14
|
+
for (const session of sessions.values()) {
|
|
15
|
+
session.emitWireEvent(event, body);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
async function broadcastContractPushToAll(sessions, contract, name, body) {
|
|
19
|
+
const schema = contract.pushes[name];
|
|
20
|
+
if (!schema) {
|
|
21
|
+
throw new Error(`socka: unknown push ${String(name)}`);
|
|
22
|
+
}
|
|
23
|
+
const validated = await parseStandardSchema(
|
|
24
|
+
schema,
|
|
25
|
+
body
|
|
26
|
+
);
|
|
27
|
+
broadcastSockaEventToAll(sessions, name, validated);
|
|
28
|
+
}
|
|
13
29
|
var SockaWebSocketSession = class {
|
|
14
30
|
constructor(websocket, sessions, config, init) {
|
|
15
31
|
this.websocket = websocket;
|
|
@@ -296,6 +312,6 @@ function runSockaSessionOnAttached(config, session) {
|
|
|
296
312
|
}
|
|
297
313
|
}
|
|
298
314
|
|
|
299
|
-
export { SockaWebSocketSession, broadcastSockaEventToPeers, runSockaSessionOnAttached };
|
|
300
|
-
//# sourceMappingURL=chunk-
|
|
301
|
-
//# sourceMappingURL=chunk-
|
|
315
|
+
export { SockaWebSocketSession, broadcastContractPushToAll, broadcastSockaEventToAll, broadcastSockaEventToPeers, runSockaSessionOnAttached };
|
|
316
|
+
//# sourceMappingURL=chunk-TTXY7O5P.js.map
|
|
317
|
+
//# sourceMappingURL=chunk-TTXY7O5P.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server/SockaWebSocketSession.ts"],"names":[],"mappings":"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","file":"chunk-TTXY7O5P.js","sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { exhaustiveGuard } from \"@firtoz/maybe-error\";\nimport type {\n\tInferSockaPushPayload,\n\tSockaContractBound,\n} from \"../core/contract\";\nimport {\n\tSockaWireError,\n\tdecodeSockaWire,\n\tencodeServerResponse,\n\tencodeServerError,\n\tencodeServerEvent,\n\ttype SockaClientRequestFrame,\n\ttype SockaWireFrame,\n} from \"../core/envelope\";\nimport {\n\tencodeSockaWire,\n\tparseWirePayload,\n\ttype SockaWireFormat,\n} from \"../core/wire-codec\";\nimport { reportSockaError } from \"../core/socka-report-error\";\nimport { parseStandardSchema } from \"../core/validate\";\nimport { SockaError } from \"../core/socka-error\";\nimport type {\n\tSockaStrictWebSocketInit,\n\tSockaWebSocketInit,\n\tSockaWebSocketSessionConfig,\n\tSockaWebSocketSessionConfigLoose,\n\tSockaWebSocketSessionConfigUnion,\n} from \"./SockaWebSocketSessionConfig\";\n\n/** Session data with no fields — `createData` may be omitted (defaults to `{}`). */\ntype EmptySockaSessionData = Record<string, never>;\n\nexport type {\n\tSockaStrictWebSocketInit,\n\tSockaWebSocketInit,\n\tSockaWebSocketSessionConfig,\n\tSockaWebSocketSessionConfigLoose,\n\tSockaWebSocketSessionConfigUnion,\n};\n\nfunction isLooseUpgradeConfig<TContract extends SockaContractBound, TData>(\n\tconfig: SockaWebSocketSessionConfigUnion<TContract, TData>,\n): config is SockaWebSocketSessionConfigLoose<TContract, TData> {\n\treturn (\n\t\t\"strictUpgradeRequest\" in config && config.strictUpgradeRequest === false\n\t);\n}\n\n/** Session that can send a wire-level server event (already validated). */\nexport type SockaEmitCapable = {\n\temitWireEvent(event: string, body: unknown): void;\n};\n\n/**\n * Contract-typed session surface for handlers that push to clients.\n */\nexport interface SockaPushSession<TContract extends SockaContractBound> {\n\temitPush<K extends keyof TContract[\"pushes\"] & string>(\n\t\tname: K,\n\t\tbody: InferSockaPushPayload<TContract, K>,\n\t): Promise<void>;\n\tbroadcastPush<K extends keyof TContract[\"pushes\"] & string>(\n\t\tname: K,\n\t\tbody: InferSockaPushPayload<TContract, K>,\n\t\texcludeSelf?: boolean,\n\t): Promise<void>;\n}\n\n/**\n * Broadcast a socka server event to every session in the map (optionally\n * excluding the caller). Payload must already be contract-validated.\n *\n * Exclusion uses the **WebSocket** identity (`self.websocket`), not the session\n * object reference, so the same `sessions` map can hold `SockaDoSession` while\n * `broadcastPush` runs on `this.socka` (inner {@link SockaWebSocketSession}).\n *\n * When there is no caller session, use {@link broadcastSockaEventToAll} or\n * {@link broadcastContractPushToAll} instead of picking an arbitrary anchor.\n */\nexport function broadcastSockaEventToPeers(\n\tsessions: Map<WebSocket, SockaEmitCapable>,\n\tself: SockaEmitCapable & { readonly websocket: WebSocket },\n\tevent: string,\n\tbody: unknown,\n\texcludeSelf = false,\n): void {\n\tfor (const [ws, session] of sessions) {\n\t\tif (excludeSelf && ws === self.websocket) continue;\n\t\tsession.emitWireEvent(event, body);\n\t}\n}\n\n/**\n * Broadcast a socka server event to **every** session in the map. Payload must\n * already be contract-validated.\n *\n * Use when there is no originating WebSocket session (HTTP admin routes, alarms,\n * cron). Prefer {@link broadcastContractPushToAll} so validation stays centralized.\n */\nexport function broadcastSockaEventToAll(\n\tsessions: Map<WebSocket, SockaEmitCapable>,\n\tevent: string,\n\tbody: unknown,\n): void {\n\tfor (const session of sessions.values()) {\n\t\tsession.emitWireEvent(event, body);\n\t}\n}\n\n/**\n * Validate a contract push payload and broadcast it to every session in the map.\n *\n * Works with any session type that implements {@link SockaEmitCapable} (including\n * {@link SockaDoSession} on Durable Objects). No-op when `sessions` is empty.\n */\nexport async function broadcastContractPushToAll<\n\tTContract extends SockaContractBound,\n\tK extends keyof TContract[\"pushes\"] & string,\n>(\n\tsessions: Map<WebSocket, SockaEmitCapable>,\n\tcontract: TContract,\n\tname: K,\n\tbody: InferSockaPushPayload<TContract, K>,\n): Promise<void> {\n\tconst schema = contract.pushes[name];\n\tif (!schema) {\n\t\tthrow new Error(`socka: unknown push ${String(name)}`);\n\t}\n\tconst validated = await parseStandardSchema(\n\t\tschema as StandardSchemaV1<unknown, InferSockaPushPayload<TContract, K>>,\n\t\tbody,\n\t);\n\tbroadcastSockaEventToAll(sessions, name, validated);\n}\n\n/**\n * Runtime-agnostic socka server session: standard {@link WebSocket} wire\n * dispatch without Cloudflare Durable Object APIs.\n */\nexport class SockaWebSocketSession<\n\tTContract extends SockaContractBound,\n\tTData = EmptySockaSessionData,\n> implements SockaPushSession<TContract>\n{\n\tprivate readonly config: SockaWebSocketSessionConfigUnion<TContract, TData>;\n\tprivate readonly wireFormat: SockaWireFormat;\n\tprivate _data!: TData;\n\n\tpublic constructor(\n\t\tpublic readonly websocket: WebSocket,\n\t\tprotected readonly sessions: Map<\n\t\t\tWebSocket,\n\t\t\tSockaWebSocketSession<TContract, TData>\n\t\t>,\n\t\tconfig: SockaWebSocketSessionConfigUnion<TContract, TData>,\n\t\tinit?: SockaWebSocketInit,\n\t) {\n\t\tthis.config = config;\n\t\tthis.wireFormat = config.wireFormat ?? \"json\";\n\t\tif (isLooseUpgradeConfig(config)) {\n\t\t\tconst createData = config.createData as\n\t\t\t\t| ((init: SockaWebSocketInit) => TData)\n\t\t\t\t| undefined;\n\t\t\tconst create = createData ?? ((_i: SockaWebSocketInit) => ({}) as TData);\n\t\t\tthis._data = create(init ?? {});\n\t\t} else {\n\t\t\tif (!init?.request) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"socka: strict upgrade (default) requires a Request on the upgrade init (e.g. Bun upgrade with `data: { …, request: req }`, or Hono default sockaInit), or use SockaWebSocketSessionConfigLoose with strictUpgradeRequest: false\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst strictInit: SockaStrictWebSocketInit = { request: init.request };\n\t\t\tif (config.createData) {\n\t\t\t\tthis._data = config.createData(strictInit);\n\t\t\t} else {\n\t\t\t\tthis._data = {} as TData;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic get data(): TData {\n\t\treturn this._data;\n\t}\n\n\t/**\n\t * Session data for every connection in the same {@link sessions} map (same room),\n\t * optionally excluding this socket.\n\t */\n\tpublic listPeers(options?: { excludeSelf?: boolean }): TData[] {\n\t\tconst out: TData[] = [];\n\t\tfor (const [ws, s] of this.sessions) {\n\t\t\tif (options?.excludeSelf && ws === this.websocket) continue;\n\t\t\tout.push(s.data);\n\t\t}\n\t\treturn out;\n\t}\n\n\t/**\n\t * Like {@link listPeers} but maps each peer {@link SockaWebSocketSession}\n\t * (e.g. when you need more than {@link #data}).\n\t */\n\tpublic listPeersWith<R>(\n\t\tmap: (session: SockaWebSocketSession<TContract, TData>) => R,\n\t\toptions?: { excludeSelf?: boolean },\n\t): R[] {\n\t\tconst out: R[] = [];\n\t\tfor (const [ws, s] of this.sessions) {\n\t\t\tif (options?.excludeSelf && ws === this.websocket) continue;\n\t\t\tout.push(map(s));\n\t\t}\n\t\treturn out;\n\t}\n\n\t/** Count of sessions in this room (same {@link sessions} map), optionally excluding self. */\n\tpublic peerCount(options?: { excludeSelf?: boolean }): number {\n\t\tlet n = 0;\n\t\tfor (const [ws] of this.sessions) {\n\t\t\tif (options?.excludeSelf && ws === this.websocket) continue;\n\t\t\tn += 1;\n\t\t}\n\t\treturn n;\n\t}\n\n\t/** Whether any peer sessions exist (optionally excluding self). */\n\tpublic hasPeers(options?: { excludeSelf?: boolean }): boolean {\n\t\treturn this.peerCount(options) > 0;\n\t}\n\n\t/**\n\t * Invokes the user {@link typeof SockaWebSocketSessionConfig.handleClose} callback.\n\t * Server adapters should call this when the WebSocket closes, **before** deleting\n\t * this session from the shared `sessions` map.\n\t */\n\tpublic async invokeHandleClose(): Promise<void> {\n\t\tawait this.config.handleClose(this);\n\t}\n\n\tpublic async handleRawMessage(rawMessage: string): Promise<void> {\n\t\tif (this.wireFormat !== \"json\") {\n\t\t\tawait this.reportValidationError(\n\t\t\t\tnew Error(\"socka: unexpected JSON frame in msgpack mode\"),\n\t\t\t\trawMessage,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tconst deserialize = this.config.deserializeJson ?? JSON.parse;\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = deserialize(rawMessage);\n\t\t} catch {\n\t\t\tawait this.reportValidationError(\n\t\t\t\tnew Error(\"socka: invalid JSON\"),\n\t\t\t\trawMessage,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tawait this.dispatchAfterParsed(parsed, rawMessage);\n\t}\n\n\tpublic async handleBinaryMessage(buffer: ArrayBuffer): Promise<void> {\n\t\tif (this.wireFormat !== \"msgpack\") {\n\t\t\tawait this.reportValidationError(\n\t\t\t\tnew Error(\"socka: unexpected binary frame in JSON mode\"),\n\t\t\t\tbuffer,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = parseWirePayload(buffer, \"msgpack\");\n\t\t} catch (err) {\n\t\t\tawait this.reportValidationError(\n\t\t\t\terr instanceof Error ? err : new Error(\"socka: msgpack decode failed\"),\n\t\t\t\tbuffer,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tawait this.dispatchAfterParsed(parsed, buffer);\n\t}\n\n\tprivate async dispatchAfterParsed(\n\t\tparsed: unknown,\n\t\toriginalWire: unknown,\n\t): Promise<void> {\n\t\tlet decoded: ReturnType<typeof decodeSockaWire>;\n\t\ttry {\n\t\t\tdecoded = decodeSockaWire(parsed);\n\t\t} catch (err) {\n\t\t\tif (err instanceof SockaWireError) {\n\t\t\t\tawait this.reportValidationError(err, originalWire);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow err;\n\t\t}\n\n\t\tswitch (decoded.kind) {\n\t\t\tcase \"clientRequest\":\n\t\t\t\tawait this.dispatchClientRequest(decoded.frame, originalWire);\n\t\t\t\treturn;\n\t\t\tcase \"serverResponse\":\n\t\t\tcase \"serverError\":\n\t\t\tcase \"serverEvent\":\n\t\t\t\tawait this.reportValidationError(\n\t\t\t\t\tnew Error(\"socka: unexpected server-originated frame from client\"),\n\t\t\t\t\tparsed,\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\tdefault:\n\t\t\t\texhaustiveGuard(decoded);\n\t\t}\n\t}\n\n\tprivate async dispatchClientRequest(\n\t\tframe: SockaClientRequestFrame,\n\t\t_originalWire: unknown,\n\t): Promise<void> {\n\t\tconst rpcName = frame.rpc;\n\t\tconst procedure = this.config.contract.calls[rpcName];\n\n\t\tif (!procedure) {\n\t\t\tconst errorFrame = encodeServerError(\n\t\t\t\tframe.id,\n\t\t\t\t`Unknown call: ${rpcName}`,\n\t\t\t\t{ rpc: rpcName },\n\t\t\t);\n\t\t\tthis.sendWireFrame(errorFrame);\n\t\t\treturn;\n\t\t}\n\n\t\tlet validatedInput: unknown;\n\t\tif (procedure.input) {\n\t\t\ttry {\n\t\t\t\tvalidatedInput = await parseStandardSchema(procedure.input, frame.body);\n\t\t\t} catch (err) {\n\t\t\t\tconst msg =\n\t\t\t\t\terr instanceof Error ? err.message : \"Input validation failed\";\n\t\t\t\tconst errorFrame = encodeServerError(frame.id, msg, {\n\t\t\t\t\trpc: rpcName,\n\t\t\t\t});\n\t\t\t\tthis.sendWireFrame(errorFrame);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tlet result: unknown;\n\t\ttry {\n\t\t\tif (procedure.input) {\n\t\t\t\tconst handler = this.config.handlers[rpcName] as (\n\t\t\t\t\tinput: unknown,\n\t\t\t\t\ts: SockaWebSocketSession<TContract, TData>,\n\t\t\t\t) => unknown | Promise<unknown>;\n\t\t\t\tresult = await handler(validatedInput, this);\n\t\t\t} else {\n\t\t\t\tconst handler = this.config.handlers[rpcName] as (\n\t\t\t\t\ts: SockaWebSocketSession<TContract, TData>,\n\t\t\t\t) => unknown | Promise<unknown>;\n\t\t\t\tresult = await handler(this);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthis.config.onHandlerError?.(err, rpcName, validatedInput, this);\n\t\t\tconst sockaErr =\n\t\t\t\terr instanceof SockaError\n\t\t\t\t\t? err\n\t\t\t\t\t: new SockaError(\n\t\t\t\t\t\t\terr instanceof Error ? err.message : \"Handler failed\",\n\t\t\t\t\t\t);\n\t\t\tconst errorFrame = encodeServerError(frame.id, sockaErr.message, {\n\t\t\t\trpc: rpcName,\n\t\t\t\tcode: sockaErr.code,\n\t\t\t\tdata: sockaErr.data,\n\t\t\t});\n\t\t\tthis.sendWireFrame(errorFrame);\n\t\t\treturn;\n\t\t}\n\n\t\tif (procedure.output === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet validatedOutput: unknown;\n\t\ttry {\n\t\t\tvalidatedOutput = await parseStandardSchema(procedure.output, result);\n\t\t} catch (err) {\n\t\t\tconst msg =\n\t\t\t\terr instanceof Error ? err.message : \"Output validation failed\";\n\t\t\tconst errorFrame = encodeServerError(frame.id, msg, { rpc: rpcName });\n\t\t\tthis.sendWireFrame(errorFrame);\n\t\t\treturn;\n\t\t}\n\n\t\tconst responseFrame = encodeServerResponse(\n\t\t\tframe.id,\n\t\t\trpcName,\n\t\t\tvalidatedOutput,\n\t\t);\n\t\tthis.sendWireFrame(responseFrame);\n\t}\n\n\tprivate encodeOutgoing(frame: SockaWireFrame): string | Uint8Array {\n\t\treturn encodeSockaWire(\n\t\t\tframe,\n\t\t\tthis.wireFormat,\n\t\t\tthis.config.serializeJson ?? JSON.stringify,\n\t\t);\n\t}\n\n\tprivate sendWireFrame(frame: SockaWireFrame): void {\n\t\tif (this.websocket.readyState !== WebSocket.OPEN) {\n\t\t\treturn;\n\t\t}\n\t\tconst encoded = this.encodeOutgoing(frame);\n\t\tif (typeof encoded === \"string\") {\n\t\t\tthis.websocket.send(encoded);\n\t\t\treturn;\n\t\t}\n\t\tconst copy = new Uint8Array(encoded.byteLength);\n\t\tcopy.set(encoded);\n\t\tthis.websocket.send(copy.buffer);\n\t}\n\n\t/**\n\t * Send a server event frame (wire). Prefer {@link emitPush} so\n\t * payloads are validated against the contract.\n\t */\n\tpublic emitWireEvent(event: string, body: unknown): void {\n\t\tconst frame = encodeServerEvent(event, body);\n\t\tthis.sendWireFrame(frame);\n\t}\n\n\tpublic async emitPush<K extends keyof TContract[\"pushes\"] & string>(\n\t\tname: K,\n\t\tbody: InferSockaPushPayload<TContract, K>,\n\t): Promise<void> {\n\t\tconst schema = this.config.contract.pushes[name];\n\t\tif (!schema) {\n\t\t\tthrow new Error(`socka: unknown push ${String(name)}`);\n\t\t}\n\t\tconst validated = await parseStandardSchema(\n\t\t\tschema as StandardSchemaV1<unknown, InferSockaPushPayload<TContract, K>>,\n\t\t\tbody,\n\t\t);\n\t\tthis.emitWireEvent(name, validated);\n\t}\n\n\tpublic async broadcastPush<K extends keyof TContract[\"pushes\"] & string>(\n\t\tname: K,\n\t\tbody: InferSockaPushPayload<TContract, K>,\n\t\texcludeSelf = false,\n\t): Promise<void> {\n\t\tconst schema = this.config.contract.pushes[name];\n\t\tif (!schema) {\n\t\t\tthrow new Error(`socka: unknown push ${String(name)}`);\n\t\t}\n\t\tconst validated = await parseStandardSchema(\n\t\t\tschema as StandardSchemaV1<unknown, InferSockaPushPayload<TContract, K>>,\n\t\t\tbody,\n\t\t);\n\t\tbroadcastSockaEventToPeers(\n\t\t\tthis.sessions,\n\t\t\tthis,\n\t\t\tname,\n\t\t\tvalidated,\n\t\t\texcludeSelf,\n\t\t);\n\t}\n\n\tprivate async reportValidationError(\n\t\terror: unknown,\n\t\toriginalMessage: unknown,\n\t): Promise<void> {\n\t\tif (this.config.onValidationError) {\n\t\t\tawait this.config.onValidationError(error, originalMessage);\n\t\t} else {\n\t\t\tconsole.error(\"socka: validation error:\", error, originalMessage);\n\t\t}\n\t}\n}\n\n/**\n * Invoke {@link SockaWebSocketSessionConfig.onAttached} after the session is\n * registered in the shared map.\n */\nexport function runSockaSessionOnAttached<\n\tTContract extends SockaContractBound,\n\tTData,\n>(\n\tconfig: SockaWebSocketSessionConfigUnion<TContract, TData>,\n\tsession: SockaWebSocketSession<TContract, TData>,\n): void {\n\tconst cb = config.onAttached;\n\tif (!cb) return;\n\ttry {\n\t\tconst result = cb(session);\n\t\tvoid Promise.resolve(result).catch((error: unknown) => {\n\t\t\treportSockaError(config.reportError, {\n\t\t\t\tkind: \"serverOnAttached\",\n\t\t\t\terror,\n\t\t\t});\n\t\t});\n\t} catch (error) {\n\t\treportSockaError(config.reportError, { kind: \"serverOnAttached\", error });\n\t}\n}\n"]}
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { c as SockaContractBound, y as SockaWireFormat, p as SockaServerResponseFrame, n as SockaServerErrorFrame, o as SockaServerEventFrame, I as InferSockaSend, h as InferSockaPushPayload, g as InferSockaPushHandlers, B as SockaReportError } from '../socka-report-error-nTXJIzNb.js';
|
|
2
|
+
export { A as reportSockaError } from '../socka-report-error-nTXJIzNb.js';
|
|
3
3
|
import '@standard-schema/spec';
|
|
4
4
|
|
|
5
|
-
interface SockaWebSocketClientOptions<TContract extends
|
|
5
|
+
interface SockaWebSocketClientOptions<TContract extends SockaContractBound> {
|
|
6
6
|
contract: TContract;
|
|
7
7
|
/** Default `"json"` (text frames). Use `"msgpack"` for binary `ArrayBuffer` frames. */
|
|
8
8
|
wireFormat?: SockaWireFormat;
|
|
@@ -62,7 +62,7 @@ type SockaConnectionStatus = "idle" | "connecting" | "open" | "reconnecting" | "
|
|
|
62
62
|
* Browser WebSocket client driven by a socka contract. Sends client request
|
|
63
63
|
* frames and dispatches decoded server frames to callbacks.
|
|
64
64
|
*/
|
|
65
|
-
declare class SockaWebSocketClient<TContract extends
|
|
65
|
+
declare class SockaWebSocketClient<TContract extends SockaContractBound> {
|
|
66
66
|
private ws;
|
|
67
67
|
private readonly opts;
|
|
68
68
|
private readonly wireFormat;
|
|
@@ -107,18 +107,18 @@ declare class SockaWebSocketClient<TContract extends SockaContract<SockaContract
|
|
|
107
107
|
waitForOpen(): Promise<void>;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
type SockaSessionPushWaitOptions<TContract extends
|
|
110
|
+
type SockaSessionPushWaitOptions<TContract extends SockaContractBound, K extends keyof TContract["pushes"] & string> = {
|
|
111
111
|
signal?: AbortSignal;
|
|
112
112
|
timeoutMs?: number;
|
|
113
113
|
predicate?: (payload: InferSockaPushPayload<TContract, K>) => boolean;
|
|
114
114
|
};
|
|
115
|
-
type SockaSessionSubscribeApi<TContract extends
|
|
115
|
+
type SockaSessionSubscribeApi<TContract extends SockaContractBound> = {
|
|
116
116
|
on<K extends keyof TContract["pushes"] & string>(name: K, handler: (payload: InferSockaPushPayload<TContract, K>) => void | Promise<void>): void;
|
|
117
117
|
off<K extends keyof TContract["pushes"] & string>(name: K, handler: (payload: InferSockaPushPayload<TContract, K>) => void | Promise<void>): void;
|
|
118
118
|
once<K extends keyof TContract["pushes"] & string>(name: K, handler: (payload: InferSockaPushPayload<TContract, K>) => void | Promise<void>): void;
|
|
119
119
|
waitForPush<K extends keyof TContract["pushes"] & string>(name: K, options?: SockaSessionPushWaitOptions<TContract, K>): Promise<InferSockaPushPayload<TContract, K>>;
|
|
120
120
|
};
|
|
121
|
-
type SockaSessionOptions<TContract extends
|
|
121
|
+
type SockaSessionOptions<TContract extends SockaContractBound> = Omit<SockaWebSocketClientOptions<TContract>, "onResponse" | "onServerError" | "onEvent"> & {
|
|
122
122
|
onOpen?: (event: Event) => void;
|
|
123
123
|
onClose?: (event: CloseEvent) => void;
|
|
124
124
|
onError?: (event: Event) => void;
|
|
@@ -134,7 +134,7 @@ type SockaSessionOptions<TContract extends SockaContract<SockaContractConfig>> =
|
|
|
134
134
|
* Browser WebSocket session: **`session.send`** for contract calls, **`session.subscribe`**
|
|
135
135
|
* for server pushes, **`session.client`** for low-level wire access.
|
|
136
136
|
*/
|
|
137
|
-
declare class SockaSessionBase<TContract extends
|
|
137
|
+
declare class SockaSessionBase<TContract extends SockaContractBound> {
|
|
138
138
|
readonly client: SockaWebSocketClient<TContract>;
|
|
139
139
|
readonly send: InferSockaSend<TContract>;
|
|
140
140
|
readonly subscribe: SockaSessionSubscribeApi<TContract>;
|
|
@@ -164,9 +164,9 @@ declare class SockaSessionBase<TContract extends SockaContract<SockaContractConf
|
|
|
164
164
|
onStatusChange(listener: (status: SockaConnectionStatus) => void): () => void;
|
|
165
165
|
}
|
|
166
166
|
interface SockaSessionConstructor {
|
|
167
|
-
new <TContract extends
|
|
167
|
+
new <TContract extends SockaContractBound>(options: SockaSessionOptions<TContract>): SockaSession<TContract>;
|
|
168
168
|
}
|
|
169
|
-
type SockaSession<TContract extends
|
|
169
|
+
type SockaSession<TContract extends SockaContractBound> = SockaSessionBase<TContract>;
|
|
170
170
|
/**
|
|
171
171
|
* WebSocket session: **`session.send`** for contract calls, **`session.subscribe`** for server pushes.
|
|
172
172
|
*/
|
package/dist/client/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { SockaSession, SockaWebSocketClient } from '../chunk-
|
|
1
|
+
export { SockaSession, SockaWebSocketClient } from '../chunk-THFUHQJ3.js';
|
|
2
2
|
import '../chunk-YMT4HAH7.js';
|
|
3
3
|
export { reportSockaError } from '../chunk-IFIGKR3W.js';
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { D as DecodedSockaWire,
|
|
1
|
+
export { D as DecodedSockaWire, f as InferSockaHandlers, g as InferSockaPushHandlers, h as InferSockaPushPayload, I as InferSockaSend, R as RESERVED_SOCKA_PROCEDURE_NAMES, i as ReservedSockaProcedureName, k as SOCKA_WIRE_VERSION, m as SockaClientRequestFrame, S as SockaContract, c as SockaContractBound, a as SockaContractConfig, b as SockaContractConfigBound, j as SockaError, e as SockaProcedureDef, B as SockaReportError, n as SockaServerErrorFrame, o as SockaServerEventFrame, p as SockaServerResponseFrame, l as SockaWireError, y as SockaWireFormat, q as SockaWireFrame, V as ValidateSockaCallKeys, r as decodeSockaWire, z as defaultReportError, d as defineSocka, s as encodeClientRequest, u as encodeServerError, v as encodeServerEvent, t as encodeServerResponse, w as encodeSockaWire, x as parseWirePayload, A as reportSockaError } from '../socka-report-error-nTXJIzNb.js';
|
|
2
2
|
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
3
3
|
|
|
4
4
|
/**
|