@firtoz/websocket-do 10.0.0 → 13.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 +68 -61
- package/dist/BaseSession.d.ts +41 -0
- package/dist/BaseSession.js +5 -0
- package/dist/BaseSession.js.map +1 -0
- package/dist/BaseWebSocketDO.d.ts +42 -0
- package/dist/BaseWebSocketDO.js +4 -0
- package/dist/BaseWebSocketDO.js.map +1 -0
- package/dist/StandardSchemaSession.d.ts +41 -0
- package/dist/StandardSchemaSession.js +8 -0
- package/dist/StandardSchemaSession.js.map +1 -0
- package/dist/StandardSchemaWebSocketClient.d.ts +45 -0
- package/dist/StandardSchemaWebSocketClient.js +5 -0
- package/dist/StandardSchemaWebSocketClient.js.map +1 -0
- package/dist/StandardSchemaWebSocketDO.d.ts +28 -0
- package/dist/StandardSchemaWebSocketDO.js +5 -0
- package/dist/StandardSchemaWebSocketDO.js.map +1 -0
- package/dist/WebsocketWrapper.d.ts +9 -0
- package/dist/WebsocketWrapper.js +4 -0
- package/dist/WebsocketWrapper.js.map +1 -0
- package/dist/chunk-3C77OSOD.js +54 -0
- package/dist/chunk-3C77OSOD.js.map +1 -0
- package/dist/chunk-3LWVEY3R.js +130 -0
- package/dist/chunk-3LWVEY3R.js.map +1 -0
- package/dist/chunk-53MFRNQS.js +153 -0
- package/dist/chunk-53MFRNQS.js.map +1 -0
- package/dist/chunk-CAX4POIL.js +13 -0
- package/dist/chunk-CAX4POIL.js.map +1 -0
- package/dist/chunk-KCPOB32E.js +20 -0
- package/dist/chunk-KCPOB32E.js.map +1 -0
- package/dist/chunk-NOUFNU2O.js +10 -0
- package/dist/chunk-NOUFNU2O.js.map +1 -0
- package/dist/chunk-QMGIRIHJ.js +18 -0
- package/dist/chunk-QMGIRIHJ.js.map +1 -0
- package/dist/chunk-ULGH6X42.js +23 -0
- package/dist/chunk-ULGH6X42.js.map +1 -0
- package/dist/chunk-WJIQBI6I.js +35 -0
- package/dist/chunk-WJIQBI6I.js.map +1 -0
- package/dist/chunk-XFB6C3NZ.js +134 -0
- package/dist/chunk-XFB6C3NZ.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/parseStandardSchema.d.ts +9 -0
- package/dist/parseStandardSchema.js +4 -0
- package/dist/parseStandardSchema.js.map +1 -0
- package/dist/standardSchemaMsgpack.d.ts +8 -0
- package/dist/standardSchemaMsgpack.js +5 -0
- package/dist/standardSchemaMsgpack.js.map +1 -0
- package/dist/standardSchemaRpc.d.ts +30 -0
- package/dist/standardSchemaRpc.js +6 -0
- package/dist/standardSchemaRpc.js.map +1 -0
- package/dist/standardSchemaRpcReact.d.ts +27 -0
- package/dist/standardSchemaRpcReact.js +54 -0
- package/dist/standardSchemaRpcReact.js.map +1 -0
- package/package.json +36 -18
- package/src/BaseSession.ts +15 -5
- package/src/{ZodSession.ts → StandardSchemaSession.ts} +71 -70
- package/src/{ZodWebSocketClient.ts → StandardSchemaWebSocketClient.ts} +30 -50
- package/src/{ZodWebSocketDO.ts → StandardSchemaWebSocketDO.ts} +29 -22
- package/src/index.ts +15 -12
- package/src/parseStandardSchema.ts +17 -0
- package/src/standardSchemaMsgpack.ts +17 -0
- package/src/standardSchemaRpc.ts +83 -0
- package/src/standardSchemaRpcReact.ts +107 -0
- package/src/zodMsgpack.ts +0 -13
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { WebsocketWrapper } from './chunk-KCPOB32E.js';
|
|
2
|
+
|
|
3
|
+
// src/BaseSession.ts
|
|
4
|
+
var BaseSession = class {
|
|
5
|
+
constructor(websocket, sessions, handlers) {
|
|
6
|
+
this.websocket = websocket;
|
|
7
|
+
this.sessions = sessions;
|
|
8
|
+
this.wrapper = new WebsocketWrapper(websocket);
|
|
9
|
+
this.handlers = handlers;
|
|
10
|
+
}
|
|
11
|
+
get data() {
|
|
12
|
+
return this._data;
|
|
13
|
+
}
|
|
14
|
+
set data(data) {
|
|
15
|
+
this._data = data;
|
|
16
|
+
}
|
|
17
|
+
startFresh(ctx) {
|
|
18
|
+
this.data = this.handlers.createData !== void 0 ? this.handlers.createData(ctx) : {};
|
|
19
|
+
this.wrapper.serializeAttachment(this.data);
|
|
20
|
+
}
|
|
21
|
+
resume() {
|
|
22
|
+
const existingData = this.wrapper.deserializeAttachment();
|
|
23
|
+
if (existingData) {
|
|
24
|
+
this.data = existingData;
|
|
25
|
+
} else {
|
|
26
|
+
throw new Error("No data to resume");
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
update() {
|
|
30
|
+
this.wrapper.serializeAttachment(this.data);
|
|
31
|
+
}
|
|
32
|
+
broadcast(message, excludeSelf = false) {
|
|
33
|
+
for (const session of this.sessions.values()) {
|
|
34
|
+
if (excludeSelf && session === this) continue;
|
|
35
|
+
session.send(message);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
send(message) {
|
|
39
|
+
this.wrapper.send(message);
|
|
40
|
+
}
|
|
41
|
+
async handleMessage(message) {
|
|
42
|
+
return this.handlers.handleMessage(message);
|
|
43
|
+
}
|
|
44
|
+
async handleBufferMessage(message) {
|
|
45
|
+
return this.handlers.handleBufferMessage(message);
|
|
46
|
+
}
|
|
47
|
+
async handleClose() {
|
|
48
|
+
return this.handlers.handleClose(this);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export { BaseSession };
|
|
53
|
+
//# sourceMappingURL=chunk-3C77OSOD.js.map
|
|
54
|
+
//# sourceMappingURL=chunk-3C77OSOD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/BaseSession.ts"],"names":[],"mappings":";;;AAwEO,IAAM,cAAN,MAKL;AAAA,EAmBD,WAAA,CACQ,SAAA,EACG,QAAA,EAIV,QAAA,EACC;AANM,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AACG,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAMV,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,gBAAA,CAAwC,SAAS,CAAA;AACpE,IAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAAA,EACjB;AAAA,EA1BA,IAAW,IAAA,GAAc;AACxB,IAAA,OAAO,IAAA,CAAK,KAAA;AAAA,EACb;AAAA,EAEA,IAAY,KAAK,IAAA,EAAa;AAC7B,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AAAA,EACd;AAAA,EAsBO,WAAW,GAAA,EAAkC;AACnD,IAAA,IAAA,CAAK,IAAA,GACJ,IAAA,CAAK,QAAA,CAAS,UAAA,KAAe,MAAA,GAC1B,KAAK,QAAA,CAAS,UAAA,CAAW,GAAG,CAAA,GAC3B,EAAC;AACN,IAAA,IAAA,CAAK,OAAA,CAAQ,mBAAA,CAAoB,IAAA,CAAK,IAAI,CAAA;AAAA,EAC3C;AAAA,EAEO,MAAA,GAAS;AACf,IAAA,MAAM,YAAA,GAAe,IAAA,CAAK,OAAA,CAAQ,qBAAA,EAAsB;AACxD,IAAA,IAAI,YAAA,EAAc;AACjB,MAAA,IAAA,CAAK,IAAA,GAAO,YAAA;AAAA,IACb,CAAA,MAAO;AACN,MAAA,MAAM,IAAI,MAAM,mBAAmB,CAAA;AAAA,IACpC;AAAA,EACD;AAAA,EAEO,MAAA,GAAS;AACf,IAAA,IAAA,CAAK,OAAA,CAAQ,mBAAA,CAAoB,IAAA,CAAK,IAAI,CAAA;AAAA,EAC3C;AAAA,EAEO,SAAA,CAAU,OAAA,EAAyB,WAAA,GAAc,KAAA,EAAO;AAC9D,IAAA,KAAA,MAAW,OAAA,IAAW,IAAA,CAAK,QAAA,CAAS,MAAA,EAAO,EAAG;AAC7C,MAAA,IAAI,WAAA,IAAe,YAAY,IAAA,EAAM;AACrC,MAAA,OAAA,CAAQ,KAAK,OAAO,CAAA;AAAA,IACrB;AAAA,EACD;AAAA,EAEO,KAAK,OAAA,EAAyB;AACpC,IAAA,IAAA,CAAK,OAAA,CAAQ,KAAK,OAAO,CAAA;AAAA,EAC1B;AAAA,EAEA,MAAM,cAAc,OAAA,EAAwC;AAC3D,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,aAAA,CAAc,OAAO,CAAA;AAAA,EAC3C;AAAA,EAEA,MAAM,oBAAoB,OAAA,EAAqC;AAC9D,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,mBAAA,CAAoB,OAAO,CAAA;AAAA,EACjD;AAAA,EAEA,MAAM,WAAA,GAA6B;AAClC,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,WAAA,CAAY,IAAI,CAAA;AAAA,EACtC;AACD","file":"chunk-3C77OSOD.js","sourcesContent":["import type { Context } from \"hono\";\nimport { WebsocketWrapper } from \"./WebsocketWrapper\";\n\n// biome-ignore lint/suspicious/noExplicitAny: We are using any on purpose to allow any type of session.\nexport type SessionData<TSession extends BaseSession<any, any, any, any>> =\n\tTSession extends BaseSession<\n\t\tinfer TData,\n\t\tinfer _TServerMessage,\n\t\tinfer _TClientMessage,\n\t\tinfer _TEnv\n\t>\n\t\t? TData\n\t\t: never;\n\nexport type SessionClientMessage<\n\t// biome-ignore lint/suspicious/noExplicitAny: We are using any on purpose to allow any type of session.\n\tTSession extends BaseSession<any, any, any, any>,\n> =\n\tTSession extends BaseSession<\n\t\tinfer _TData,\n\t\tinfer _TServerMessage,\n\t\tinfer TClientMessage,\n\t\tinfer _TEnv\n\t>\n\t\t? TClientMessage\n\t\t: never;\n\nexport type SessionServerMessage<\n\t// biome-ignore lint/suspicious/noExplicitAny: We are using any on purpose to allow any type of session.\n\tTSession extends BaseSession<any, any, any, any>,\n> =\n\tTSession extends BaseSession<\n\t\tinfer _TData,\n\t\tinfer TServerMessage,\n\t\tinfer _TClientMessage,\n\t\tinfer _TEnv\n\t>\n\t\t? TServerMessage\n\t\t: never;\n\nexport type SessionEnv<\n\t// biome-ignore lint/suspicious/noExplicitAny: We are using any on purpose to allow any type of session.\n\tTSession extends BaseSession<any, any, any, any>,\n> =\n\tTSession extends BaseSession<\n\t\tinfer _TData,\n\t\tinfer _TServerMessage,\n\t\tinfer _TClientMessage,\n\t\tinfer TEnv extends Cloudflare.Env\n\t>\n\t\t? TEnv\n\t\t: never;\n\nexport type BaseSessionHandlers<\n\tTData,\n\tTServerMessage,\n\tTClientMessage,\n\tTEnv extends object = Cloudflare.Env,\n> = {\n\t/**\n\t * Per-connection state. If omitted, `startFresh` initializes `data` as `{}`\n\t * (use empty `TData`, e.g. `Record<string, never>`).\n\t */\n\tcreateData?: (ctx: Context<{ Bindings: TEnv }>) => TData;\n\thandleMessage: (message: TClientMessage) => Promise<void>;\n\thandleBufferMessage: (message: ArrayBuffer) => Promise<void>;\n\t/** Called when this connection closes; `session` is this {@link BaseSession} instance. */\n\thandleClose: (\n\t\tsession: BaseSession<TData, TServerMessage, TClientMessage, TEnv>,\n\t) => Promise<void>;\n};\n\nexport class BaseSession<\n\tTData,\n\tTServerMessage,\n\tTClientMessage,\n\tTEnv extends object = Cloudflare.Env,\n> {\n\tprivate _data!: TData;\n\n\tpublic get data(): TData {\n\t\treturn this._data;\n\t}\n\n\tprivate set data(data: TData) {\n\t\tthis._data = data;\n\t}\n\n\tprivate readonly wrapper: WebsocketWrapper<TData, TServerMessage>;\n\tprotected readonly handlers: BaseSessionHandlers<\n\t\tTData,\n\t\tTServerMessage,\n\t\tTClientMessage,\n\t\tTEnv\n\t>;\n\n\tconstructor(\n\t\tpublic websocket: WebSocket,\n\t\tprotected sessions: Map<\n\t\t\tWebSocket,\n\t\t\tBaseSession<TData, TServerMessage, TClientMessage, TEnv>\n\t\t>,\n\t\thandlers: BaseSessionHandlers<TData, TServerMessage, TClientMessage, TEnv>,\n\t) {\n\t\tthis.wrapper = new WebsocketWrapper<TData, TServerMessage>(websocket);\n\t\tthis.handlers = handlers;\n\t}\n\n\tpublic startFresh(ctx: Context<{ Bindings: TEnv }>) {\n\t\tthis.data =\n\t\t\tthis.handlers.createData !== undefined\n\t\t\t\t? this.handlers.createData(ctx)\n\t\t\t\t: ({} as TData);\n\t\tthis.wrapper.serializeAttachment(this.data);\n\t}\n\n\tpublic resume() {\n\t\tconst existingData = this.wrapper.deserializeAttachment();\n\t\tif (existingData) {\n\t\t\tthis.data = existingData;\n\t\t} else {\n\t\t\tthrow new Error(\"No data to resume\");\n\t\t}\n\t}\n\n\tpublic update() {\n\t\tthis.wrapper.serializeAttachment(this.data);\n\t}\n\n\tpublic broadcast(message: TServerMessage, excludeSelf = false) {\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tif (excludeSelf && session === this) continue;\n\t\t\tsession.send(message);\n\t\t}\n\t}\n\n\tpublic send(message: TServerMessage) {\n\t\tthis.wrapper.send(message);\n\t}\n\n\tasync handleMessage(message: TClientMessage): Promise<void> {\n\t\treturn this.handlers.handleMessage(message);\n\t}\n\n\tasync handleBufferMessage(message: ArrayBuffer): Promise<void> {\n\t\treturn this.handlers.handleBufferMessage(message);\n\t}\n\n\tasync handleClose(): Promise<void> {\n\t\treturn this.handlers.handleClose(this);\n\t}\n}\n"]}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { parseStandardSchema } from './chunk-CAX4POIL.js';
|
|
2
|
+
import { unpack, pack } from 'msgpackr';
|
|
3
|
+
|
|
4
|
+
var StandardSchemaWebSocketClient = class {
|
|
5
|
+
constructor(options) {
|
|
6
|
+
this.clientSchema = options.clientSchema;
|
|
7
|
+
this.serverSchema = options.serverSchema;
|
|
8
|
+
this.serializeJson = options.serializeJson ?? JSON.stringify;
|
|
9
|
+
this.deserializeJson = options.deserializeJson ?? JSON.parse;
|
|
10
|
+
this.enableBufferMessages = options.enableBufferMessages ?? false;
|
|
11
|
+
this.onMessageCallback = options.onMessage;
|
|
12
|
+
this.onValidationError = options.onValidationError;
|
|
13
|
+
if (options.webSocket) {
|
|
14
|
+
this.ws = options.webSocket;
|
|
15
|
+
} else if (options.url) {
|
|
16
|
+
this.ws = new WebSocket(options.url);
|
|
17
|
+
} else {
|
|
18
|
+
throw new Error("Either 'url' or 'webSocket' must be provided");
|
|
19
|
+
}
|
|
20
|
+
if (this.enableBufferMessages) {
|
|
21
|
+
this.ws.binaryType = "arraybuffer";
|
|
22
|
+
}
|
|
23
|
+
this.ws.addEventListener("open", (event) => {
|
|
24
|
+
options.onOpen?.(event);
|
|
25
|
+
});
|
|
26
|
+
this.ws.addEventListener("message", (event) => {
|
|
27
|
+
void this.handleMessageEvent(event);
|
|
28
|
+
});
|
|
29
|
+
this.ws.addEventListener("close", (event) => {
|
|
30
|
+
options.onClose?.(event);
|
|
31
|
+
});
|
|
32
|
+
this.ws.addEventListener("error", (event) => {
|
|
33
|
+
options.onError?.(event);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
async handleMessageEvent(event) {
|
|
37
|
+
try {
|
|
38
|
+
let parsedMessage;
|
|
39
|
+
if (this.enableBufferMessages) {
|
|
40
|
+
if (!(event.data instanceof ArrayBuffer)) {
|
|
41
|
+
console.error(
|
|
42
|
+
"Expected ArrayBuffer but received:",
|
|
43
|
+
typeof event.data
|
|
44
|
+
);
|
|
45
|
+
this.onValidationError?.(
|
|
46
|
+
new Error("Expected ArrayBuffer in buffer mode"),
|
|
47
|
+
event.data
|
|
48
|
+
);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const unpacked = unpack(new Uint8Array(event.data));
|
|
52
|
+
parsedMessage = await parseStandardSchema(this.serverSchema, unpacked);
|
|
53
|
+
} else {
|
|
54
|
+
if (typeof event.data !== "string") {
|
|
55
|
+
console.error("Expected string but received:", typeof event.data);
|
|
56
|
+
this.onValidationError?.(
|
|
57
|
+
new Error("Expected string in JSON mode"),
|
|
58
|
+
event.data
|
|
59
|
+
);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const parsed = this.deserializeJson(event.data);
|
|
63
|
+
parsedMessage = await parseStandardSchema(this.serverSchema, parsed);
|
|
64
|
+
}
|
|
65
|
+
this.onMessageCallback?.(parsedMessage);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error("Failed to process message:", error);
|
|
68
|
+
this.onValidationError?.(
|
|
69
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
70
|
+
event.data
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Send a message (automatically encodes based on mode).
|
|
76
|
+
*/
|
|
77
|
+
async send(message) {
|
|
78
|
+
const validatedMessage = await parseStandardSchema(
|
|
79
|
+
this.clientSchema,
|
|
80
|
+
message
|
|
81
|
+
);
|
|
82
|
+
if (this.enableBufferMessages) {
|
|
83
|
+
const packed = pack(validatedMessage);
|
|
84
|
+
this.ws.send(new Uint8Array(packed));
|
|
85
|
+
} else {
|
|
86
|
+
this.ws.send(this.serializeJson(validatedMessage));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
close(code, reason) {
|
|
90
|
+
this.ws.close(code, reason);
|
|
91
|
+
}
|
|
92
|
+
get readyState() {
|
|
93
|
+
return this.ws.readyState;
|
|
94
|
+
}
|
|
95
|
+
get socket() {
|
|
96
|
+
return this.ws;
|
|
97
|
+
}
|
|
98
|
+
async waitForOpen() {
|
|
99
|
+
if (this.ws.readyState === WebSocket.OPEN) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
return new Promise((resolve, reject) => {
|
|
103
|
+
const abortController = new AbortController();
|
|
104
|
+
const { signal } = abortController;
|
|
105
|
+
const cleanup = () => {
|
|
106
|
+
abortController.abort();
|
|
107
|
+
};
|
|
108
|
+
this.ws.addEventListener(
|
|
109
|
+
"open",
|
|
110
|
+
() => {
|
|
111
|
+
cleanup();
|
|
112
|
+
resolve();
|
|
113
|
+
},
|
|
114
|
+
{ signal }
|
|
115
|
+
);
|
|
116
|
+
this.ws.addEventListener(
|
|
117
|
+
"error",
|
|
118
|
+
() => {
|
|
119
|
+
cleanup();
|
|
120
|
+
reject(new Error("WebSocket connection failed"));
|
|
121
|
+
},
|
|
122
|
+
{ signal }
|
|
123
|
+
);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export { StandardSchemaWebSocketClient };
|
|
129
|
+
//# sourceMappingURL=chunk-3LWVEY3R.js.map
|
|
130
|
+
//# sourceMappingURL=chunk-3LWVEY3R.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/StandardSchemaWebSocketClient.ts"],"names":[],"mappings":"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","file":"chunk-3LWVEY3R.js","sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { pack, unpack } from \"msgpackr\";\nimport { parseStandardSchema } from \"./parseStandardSchema\";\n\nexport interface StandardSchemaWebSocketClientOptions<\n\tTClientMessage,\n\tTServerMessage,\n> {\n\t/**\n\t * URL to connect to (required if webSocket not provided)\n\t */\n\turl?: string;\n\t/**\n\t * Existing WebSocket to wrap (alternative to url)\n\t * Useful when getting a WebSocket from honoDoFetcher\n\t */\n\twebSocket?: WebSocket;\n\tclientSchema: StandardSchemaV1<unknown, TClientMessage>;\n\tserverSchema: StandardSchemaV1<unknown, TServerMessage>;\n\tserializeJson?: (value: unknown) => string;\n\tdeserializeJson?: (raw: string) => unknown;\n\tenableBufferMessages?: boolean;\n\tonMessage?: (message: TServerMessage) => void;\n\tonOpen?: (event: Event) => void;\n\tonClose?: (event: CloseEvent) => void;\n\tonError?: (event: Event) => void;\n\tonValidationError?: (error: Error, rawMessage: unknown) => void;\n}\n\nexport class StandardSchemaWebSocketClient<TClientMessage, TServerMessage> {\n\tprivate ws: WebSocket;\n\tprivate readonly clientSchema: StandardSchemaV1<unknown, TClientMessage>;\n\tprivate readonly serverSchema: StandardSchemaV1<unknown, TServerMessage>;\n\tprivate readonly serializeJson: (value: unknown) => string;\n\tprivate readonly deserializeJson: (raw: string) => unknown;\n\tprivate readonly enableBufferMessages: boolean;\n\tprivate readonly onMessageCallback?: (message: TServerMessage) => void;\n\tprivate readonly onValidationError?: (\n\t\terror: Error,\n\t\trawMessage: unknown,\n\t) => void;\n\n\tconstructor(\n\t\toptions: StandardSchemaWebSocketClientOptions<\n\t\t\tTClientMessage,\n\t\t\tTServerMessage\n\t\t>,\n\t) {\n\t\tthis.clientSchema = options.clientSchema;\n\t\tthis.serverSchema = options.serverSchema;\n\t\tthis.serializeJson = options.serializeJson ?? JSON.stringify;\n\t\tthis.deserializeJson = options.deserializeJson ?? JSON.parse;\n\t\tthis.enableBufferMessages = options.enableBufferMessages ?? false;\n\t\tthis.onMessageCallback = options.onMessage;\n\t\tthis.onValidationError = options.onValidationError;\n\n\t\tif (options.webSocket) {\n\t\t\tthis.ws = options.webSocket;\n\t\t} else if (options.url) {\n\t\t\tthis.ws = new WebSocket(options.url);\n\t\t} else {\n\t\t\tthrow new Error(\"Either 'url' or 'webSocket' must be provided\");\n\t\t}\n\n\t\tif (this.enableBufferMessages) {\n\t\t\tthis.ws.binaryType = \"arraybuffer\";\n\t\t}\n\n\t\tthis.ws.addEventListener(\"open\", (event) => {\n\t\t\toptions.onOpen?.(event);\n\t\t});\n\n\t\tthis.ws.addEventListener(\"message\", (event) => {\n\t\t\tvoid this.handleMessageEvent(event);\n\t\t});\n\n\t\tthis.ws.addEventListener(\"close\", (event) => {\n\t\t\toptions.onClose?.(event);\n\t\t});\n\n\t\tthis.ws.addEventListener(\"error\", (event) => {\n\t\t\toptions.onError?.(event);\n\t\t});\n\t}\n\n\tprivate async handleMessageEvent(event: MessageEvent): Promise<void> {\n\t\ttry {\n\t\t\tlet parsedMessage: TServerMessage;\n\n\t\t\tif (this.enableBufferMessages) {\n\t\t\t\tif (!(event.data instanceof ArrayBuffer)) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\"Expected ArrayBuffer but received:\",\n\t\t\t\t\t\ttypeof event.data,\n\t\t\t\t\t);\n\t\t\t\t\tthis.onValidationError?.(\n\t\t\t\t\t\tnew Error(\"Expected ArrayBuffer in buffer mode\"),\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\n\t\t\t\tconst unpacked = unpack(new Uint8Array(event.data));\n\t\t\t\tparsedMessage = await parseStandardSchema(this.serverSchema, unpacked);\n\t\t\t} else {\n\t\t\t\tif (typeof event.data !== \"string\") {\n\t\t\t\t\tconsole.error(\"Expected string but received:\", typeof event.data);\n\t\t\t\t\tthis.onValidationError?.(\n\t\t\t\t\t\tnew Error(\"Expected string in JSON mode\"),\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\n\t\t\t\tconst parsed = this.deserializeJson(event.data);\n\t\t\t\tparsedMessage = await parseStandardSchema(this.serverSchema, parsed);\n\t\t\t}\n\n\t\t\tthis.onMessageCallback?.(parsedMessage);\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Failed to process message:\", error);\n\t\t\tthis.onValidationError?.(\n\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t\tevent.data,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Send a message (automatically encodes based on mode).\n\t */\n\tasync send(message: TClientMessage): Promise<void> {\n\t\tconst validatedMessage = await parseStandardSchema(\n\t\t\tthis.clientSchema,\n\t\t\tmessage,\n\t\t);\n\n\t\tif (this.enableBufferMessages) {\n\t\t\tconst packed = pack(validatedMessage);\n\t\t\tthis.ws.send(new Uint8Array(packed));\n\t\t} else {\n\t\t\tthis.ws.send(this.serializeJson(validatedMessage));\n\t\t}\n\t}\n\n\tclose(code?: number, reason?: string): void {\n\t\tthis.ws.close(code, reason);\n\t}\n\n\tget readyState(): number {\n\t\treturn this.ws.readyState;\n\t}\n\n\tget socket(): WebSocket {\n\t\treturn this.ws;\n\t}\n\n\tasync waitForOpen(): Promise<void> {\n\t\tif (this.ws.readyState === WebSocket.OPEN) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst abortController = new AbortController();\n\t\t\tconst { signal } = abortController;\n\n\t\t\tconst cleanup = () => {\n\t\t\t\tabortController.abort();\n\t\t\t};\n\n\t\t\tthis.ws.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\n\t\t\tthis.ws.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"]}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { standardSchemaMsgpack } from './chunk-QMGIRIHJ.js';
|
|
2
|
+
import { BaseSession } from './chunk-3C77OSOD.js';
|
|
3
|
+
import { parseStandardSchema } from './chunk-CAX4POIL.js';
|
|
4
|
+
|
|
5
|
+
// src/StandardSchemaSession.ts
|
|
6
|
+
var StandardSchemaSession = class _StandardSchemaSession extends BaseSession {
|
|
7
|
+
constructor(websocket, sessions, options, schemaHandlers) {
|
|
8
|
+
super(websocket, sessions, {
|
|
9
|
+
createData: schemaHandlers.createData,
|
|
10
|
+
handleMessage: async (message) => {
|
|
11
|
+
return this._internalHandleMessage(message);
|
|
12
|
+
},
|
|
13
|
+
handleBufferMessage: async (message) => {
|
|
14
|
+
return this._internalHandleBufferMessage(message);
|
|
15
|
+
},
|
|
16
|
+
handleClose: async (session) => {
|
|
17
|
+
return schemaHandlers.handleClose(
|
|
18
|
+
session
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
this.options = options;
|
|
23
|
+
this.schemaHandlers = schemaHandlers;
|
|
24
|
+
this.clientCodec = standardSchemaMsgpack(options.clientSchema);
|
|
25
|
+
this.serverCodec = standardSchemaMsgpack(options.serverSchema);
|
|
26
|
+
this.enableBufferMessages = options.enableBufferMessages ?? false;
|
|
27
|
+
}
|
|
28
|
+
async handleRawMessage(rawMessage) {
|
|
29
|
+
if (this.enableBufferMessages) {
|
|
30
|
+
console.error(
|
|
31
|
+
"String messages not allowed when buffer messages are enabled"
|
|
32
|
+
);
|
|
33
|
+
await this.sendProtocolError(
|
|
34
|
+
"String messages are not allowed. Please use buffer messages."
|
|
35
|
+
);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const parsed = this.deserializeJson(rawMessage);
|
|
40
|
+
const validatedMessage = await parseStandardSchema(
|
|
41
|
+
this.options.clientSchema,
|
|
42
|
+
parsed
|
|
43
|
+
);
|
|
44
|
+
await this.schemaHandlers.handleValidatedMessage(validatedMessage);
|
|
45
|
+
} catch (error) {
|
|
46
|
+
console.error("Invalid client message received:", error);
|
|
47
|
+
await this._internalHandleValidationError(error, rawMessage);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async _internalHandleMessage(message) {
|
|
51
|
+
if (this.enableBufferMessages) {
|
|
52
|
+
console.error(
|
|
53
|
+
"String messages not allowed when buffer messages are enabled"
|
|
54
|
+
);
|
|
55
|
+
await this.sendProtocolError(
|
|
56
|
+
"String messages are not allowed. Please use buffer messages."
|
|
57
|
+
);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
const validatedMessage = await parseStandardSchema(
|
|
62
|
+
this.options.clientSchema,
|
|
63
|
+
message
|
|
64
|
+
);
|
|
65
|
+
await this.schemaHandlers.handleValidatedMessage(validatedMessage);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error("Invalid client message received:", error);
|
|
68
|
+
await this._internalHandleValidationError(error, message);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async _internalHandleBufferMessage(buffer) {
|
|
72
|
+
if (!this.enableBufferMessages) {
|
|
73
|
+
console.error(
|
|
74
|
+
"Buffer messages not allowed when buffer messages are disabled"
|
|
75
|
+
);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
const bytes = new Uint8Array(buffer);
|
|
80
|
+
const decodedMessage = await this.clientCodec.decode(bytes);
|
|
81
|
+
await this.schemaHandlers.handleValidatedMessage(decodedMessage);
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.error("Failed to decode buffer message:", error);
|
|
84
|
+
await this._internalHandleValidationError(error, buffer);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async _internalHandleValidationError(error, originalMessage) {
|
|
88
|
+
if (this.schemaHandlers.handleValidationError) {
|
|
89
|
+
await this.schemaHandlers.handleValidationError(error, originalMessage);
|
|
90
|
+
} else {
|
|
91
|
+
console.error(
|
|
92
|
+
"Validation error:",
|
|
93
|
+
error,
|
|
94
|
+
"Original message:",
|
|
95
|
+
originalMessage
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
send(message) {
|
|
100
|
+
if (this.enableBufferMessages) {
|
|
101
|
+
void this.sendBufferAsync(message).catch((error) => {
|
|
102
|
+
console.error("Failed to encode buffer message:", error);
|
|
103
|
+
});
|
|
104
|
+
} else {
|
|
105
|
+
void this.sendJsonAsync(message).catch((error) => {
|
|
106
|
+
console.error("Invalid server message to send:", error);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async sendJsonAsync(message) {
|
|
111
|
+
const validatedMessage = await parseStandardSchema(
|
|
112
|
+
this.options.serverSchema,
|
|
113
|
+
message
|
|
114
|
+
);
|
|
115
|
+
if (this.websocket.readyState !== WebSocket.OPEN) return;
|
|
116
|
+
this.websocket.send(this.serializeJson(validatedMessage));
|
|
117
|
+
}
|
|
118
|
+
async sendBufferAsync(message) {
|
|
119
|
+
const encodedMessage = await this.serverCodec.encode(message);
|
|
120
|
+
if (this.websocket.readyState !== WebSocket.OPEN) return;
|
|
121
|
+
this.websocket.send(encodedMessage);
|
|
122
|
+
}
|
|
123
|
+
async sendProtocolError(errorMessage) {
|
|
124
|
+
try {
|
|
125
|
+
if (this.options.sendProtocolError) {
|
|
126
|
+
await this.options.sendProtocolError(this.websocket, errorMessage);
|
|
127
|
+
} else {
|
|
128
|
+
if (this.websocket.readyState !== WebSocket.OPEN) return;
|
|
129
|
+
this.websocket.send(this.serializeJson({ error: errorMessage }));
|
|
130
|
+
}
|
|
131
|
+
} catch (error) {
|
|
132
|
+
console.error("Failed to send protocol error:", error);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
serializeJson(value) {
|
|
136
|
+
return this.options.serializeJson ? this.options.serializeJson(value) : JSON.stringify(value);
|
|
137
|
+
}
|
|
138
|
+
deserializeJson(raw) {
|
|
139
|
+
return this.options.deserializeJson ? this.options.deserializeJson(raw) : JSON.parse(raw);
|
|
140
|
+
}
|
|
141
|
+
broadcast(message, excludeSelf = false) {
|
|
142
|
+
for (const session of this.sessions.values()) {
|
|
143
|
+
if (excludeSelf && session === this) continue;
|
|
144
|
+
if (session instanceof _StandardSchemaSession) {
|
|
145
|
+
session.send(message);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
export { StandardSchemaSession };
|
|
152
|
+
//# sourceMappingURL=chunk-53MFRNQS.js.map
|
|
153
|
+
//# sourceMappingURL=chunk-53MFRNQS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/StandardSchemaSession.ts"],"names":[],"mappings":"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","file":"chunk-53MFRNQS.js","sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type { Context } from \"hono\";\nimport { BaseSession } from \"./BaseSession\";\nimport { parseStandardSchema } from \"./parseStandardSchema\";\nimport { standardSchemaMsgpack } from \"./standardSchemaMsgpack\";\n\nexport type StandardSchemaSessionOptions<TClientMessage, TServerMessage> = {\n\tclientSchema: StandardSchemaV1<unknown, TClientMessage>;\n\tserverSchema: StandardSchemaV1<unknown, TServerMessage>;\n\tserializeJson?: (value: unknown) => string;\n\tdeserializeJson?: (raw: string) => unknown;\n\tenableBufferMessages?: boolean;\n\tsendProtocolError?: (\n\t\twebsocket: WebSocket,\n\t\terrorMessage: string,\n\t) => Promise<void>;\n};\n\nexport type StandardSchemaSessionHandlers<\n\tTData,\n\tTServerMessage,\n\tTClientMessage,\n\tTEnv extends object,\n> = {\n\tcreateData: (ctx: Context<{ Bindings: TEnv }>) => TData;\n\thandleValidatedMessage: (message: TClientMessage) => Promise<void>;\n\thandleValidationError?: (\n\t\terror: unknown,\n\t\toriginalMessage: unknown,\n\t) => Promise<void>;\n\thandleClose: (\n\t\tsession: StandardSchemaSession<TData, TServerMessage, TClientMessage, TEnv>,\n\t) => Promise<void>;\n};\n\nexport class StandardSchemaSession<\n\tTData,\n\tTServerMessage,\n\tTClientMessage,\n\tTEnv extends object = Cloudflare.Env,\n> extends BaseSession<TData, TServerMessage, TClientMessage, TEnv> {\n\tprivate readonly clientCodec: ReturnType<\n\t\ttypeof standardSchemaMsgpack<TClientMessage>\n\t>;\n\tprivate readonly serverCodec: ReturnType<\n\t\ttypeof standardSchemaMsgpack<TServerMessage>\n\t>;\n\tprotected readonly enableBufferMessages: boolean;\n\n\tconstructor(\n\t\twebsocket: WebSocket,\n\t\tsessions: Map<\n\t\t\tWebSocket,\n\t\t\tStandardSchemaSession<TData, TServerMessage, TClientMessage, TEnv>\n\t\t>,\n\t\tprivate readonly options: StandardSchemaSessionOptions<\n\t\t\tTClientMessage,\n\t\t\tTServerMessage\n\t\t>,\n\t\tprivate readonly schemaHandlers: StandardSchemaSessionHandlers<\n\t\t\tTData,\n\t\t\tTServerMessage,\n\t\t\tTClientMessage,\n\t\t\tTEnv\n\t\t>,\n\t) {\n\t\tsuper(websocket, sessions, {\n\t\t\tcreateData: schemaHandlers.createData,\n\t\t\thandleMessage: async (message) => {\n\t\t\t\treturn this._internalHandleMessage(message);\n\t\t\t},\n\t\t\thandleBufferMessage: async (message) => {\n\t\t\t\treturn this._internalHandleBufferMessage(message);\n\t\t\t},\n\t\t\thandleClose: async (\n\t\t\t\tsession: BaseSession<TData, TServerMessage, TClientMessage, TEnv>,\n\t\t\t) => {\n\t\t\t\treturn schemaHandlers.handleClose(\n\t\t\t\t\tsession as StandardSchemaSession<\n\t\t\t\t\t\tTData,\n\t\t\t\t\t\tTServerMessage,\n\t\t\t\t\t\tTClientMessage,\n\t\t\t\t\t\tTEnv\n\t\t\t\t\t>,\n\t\t\t\t);\n\t\t\t},\n\t\t});\n\n\t\tthis.clientCodec = standardSchemaMsgpack(options.clientSchema);\n\t\tthis.serverCodec = standardSchemaMsgpack(options.serverSchema);\n\t\tthis.enableBufferMessages = options.enableBufferMessages ?? false;\n\t}\n\n\tpublic async handleRawMessage(rawMessage: string): Promise<void> {\n\t\tif (this.enableBufferMessages) {\n\t\t\tconsole.error(\n\t\t\t\t\"String messages not allowed when buffer messages are enabled\",\n\t\t\t);\n\t\t\tawait this.sendProtocolError(\n\t\t\t\t\"String messages are not allowed. Please use buffer messages.\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst parsed = this.deserializeJson(rawMessage);\n\t\t\tconst validatedMessage = await parseStandardSchema(\n\t\t\t\tthis.options.clientSchema,\n\t\t\t\tparsed,\n\t\t\t);\n\t\t\tawait this.schemaHandlers.handleValidatedMessage(validatedMessage);\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Invalid client message received:\", error);\n\t\t\tawait this._internalHandleValidationError(error, rawMessage);\n\t\t}\n\t}\n\n\tprivate async _internalHandleMessage(message: TClientMessage): Promise<void> {\n\t\tif (this.enableBufferMessages) {\n\t\t\tconsole.error(\n\t\t\t\t\"String messages not allowed when buffer messages are enabled\",\n\t\t\t);\n\t\t\tawait this.sendProtocolError(\n\t\t\t\t\"String messages are not allowed. Please use buffer messages.\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst validatedMessage = await parseStandardSchema(\n\t\t\t\tthis.options.clientSchema,\n\t\t\t\tmessage,\n\t\t\t);\n\t\t\tawait this.schemaHandlers.handleValidatedMessage(validatedMessage);\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Invalid client message received:\", error);\n\t\t\tawait this._internalHandleValidationError(error, message);\n\t\t}\n\t}\n\n\tprivate async _internalHandleBufferMessage(\n\t\tbuffer: ArrayBuffer,\n\t): Promise<void> {\n\t\tif (!this.enableBufferMessages) {\n\t\t\tconsole.error(\n\t\t\t\t\"Buffer messages not allowed when buffer messages are disabled\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst bytes = new Uint8Array(buffer);\n\t\t\tconst decodedMessage = await this.clientCodec.decode(bytes);\n\t\t\tawait this.schemaHandlers.handleValidatedMessage(decodedMessage);\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Failed to decode buffer message:\", error);\n\t\t\tawait this._internalHandleValidationError(error, buffer);\n\t\t}\n\t}\n\n\tprivate async _internalHandleValidationError(\n\t\terror: unknown,\n\t\toriginalMessage: unknown,\n\t): Promise<void> {\n\t\tif (this.schemaHandlers.handleValidationError) {\n\t\t\tawait this.schemaHandlers.handleValidationError(error, originalMessage);\n\t\t} else {\n\t\t\tconsole.error(\n\t\t\t\t\"Validation error:\",\n\t\t\t\terror,\n\t\t\t\t\"Original message:\",\n\t\t\t\toriginalMessage,\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic send(message: TServerMessage): void {\n\t\tif (this.enableBufferMessages) {\n\t\t\tvoid this.sendBufferAsync(message).catch((error: unknown) => {\n\t\t\t\tconsole.error(\"Failed to encode buffer message:\", error);\n\t\t\t});\n\t\t} else {\n\t\t\tvoid this.sendJsonAsync(message).catch((error: unknown) => {\n\t\t\t\tconsole.error(\"Invalid server message to send:\", error);\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async sendJsonAsync(message: TServerMessage): Promise<void> {\n\t\tconst validatedMessage = await parseStandardSchema(\n\t\t\tthis.options.serverSchema,\n\t\t\tmessage,\n\t\t);\n\t\tif (this.websocket.readyState !== WebSocket.OPEN) return;\n\t\tthis.websocket.send(this.serializeJson(validatedMessage));\n\t}\n\n\tprivate async sendBufferAsync(message: TServerMessage): Promise<void> {\n\t\tconst encodedMessage = await this.serverCodec.encode(message);\n\t\tif (this.websocket.readyState !== WebSocket.OPEN) return;\n\t\tthis.websocket.send(encodedMessage);\n\t}\n\n\tprivate async sendProtocolError(errorMessage: string): Promise<void> {\n\t\ttry {\n\t\t\tif (this.options.sendProtocolError) {\n\t\t\t\tawait this.options.sendProtocolError(this.websocket, errorMessage);\n\t\t\t} else {\n\t\t\t\tif (this.websocket.readyState !== WebSocket.OPEN) return;\n\t\t\t\tthis.websocket.send(this.serializeJson({ error: errorMessage }));\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Failed to send protocol error:\", error);\n\t\t}\n\t}\n\n\tprivate serializeJson(value: unknown): string {\n\t\treturn this.options.serializeJson\n\t\t\t? this.options.serializeJson(value)\n\t\t\t: JSON.stringify(value);\n\t}\n\n\tprivate deserializeJson(raw: string): unknown {\n\t\treturn this.options.deserializeJson\n\t\t\t? this.options.deserializeJson(raw)\n\t\t\t: JSON.parse(raw);\n\t}\n\n\tpublic broadcast(message: TServerMessage, excludeSelf = false): void {\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tif (excludeSelf && session === this) continue;\n\t\t\tif (session instanceof StandardSchemaSession) {\n\t\t\t\tsession.send(message);\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// src/parseStandardSchema.ts
|
|
2
|
+
async function parseStandardSchema(schema, value) {
|
|
3
|
+
const result = await schema["~standard"].validate(value);
|
|
4
|
+
if (result.issues) {
|
|
5
|
+
const messages = result.issues.map((issue) => issue.message).join("; ");
|
|
6
|
+
throw new Error(messages || "Validation failed");
|
|
7
|
+
}
|
|
8
|
+
return result.value;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { parseStandardSchema };
|
|
12
|
+
//# sourceMappingURL=chunk-CAX4POIL.js.map
|
|
13
|
+
//# sourceMappingURL=chunk-CAX4POIL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/parseStandardSchema.ts"],"names":[],"mappings":";AAMA,eAAsB,mBAAA,CACrB,QACA,KAAA,EACa;AACb,EAAA,MAAM,SAAS,MAAM,MAAA,CAAO,WAAW,CAAA,CAAE,SAAS,KAAK,CAAA;AACvD,EAAA,IAAI,OAAO,MAAA,EAAQ;AAClB,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,MAAA,CAAO,GAAA,CAAI,CAAC,UAAU,KAAA,CAAM,OAAO,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA;AACtE,IAAA,MAAM,IAAI,KAAA,CAAM,QAAA,IAAY,mBAAmB,CAAA;AAAA,EAChD;AACA,EAAA,OAAO,MAAA,CAAO,KAAA;AACf","file":"chunk-CAX4POIL.js","sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\n/**\n * Validates {@link value} with a Standard Schema v1 schema and returns the output,\n * or throws an {@link Error} whose message aggregates issue messages.\n */\nexport async function parseStandardSchema<T>(\n\tschema: StandardSchemaV1<unknown, T>,\n\tvalue: unknown,\n): Promise<T> {\n\tconst result = await schema[\"~standard\"].validate(value);\n\tif (result.issues) {\n\t\tconst messages = result.issues.map((issue) => issue.message).join(\"; \");\n\t\tthrow new Error(messages || \"Validation failed\");\n\t}\n\treturn result.value;\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// src/WebsocketWrapper.ts
|
|
2
|
+
var WebsocketWrapper = class {
|
|
3
|
+
constructor(webSocket) {
|
|
4
|
+
this.webSocket = webSocket;
|
|
5
|
+
}
|
|
6
|
+
send(message) {
|
|
7
|
+
if (this.webSocket.readyState !== WebSocket.OPEN) return;
|
|
8
|
+
this.webSocket.send(JSON.stringify(message));
|
|
9
|
+
}
|
|
10
|
+
deserializeAttachment() {
|
|
11
|
+
return this.webSocket.deserializeAttachment();
|
|
12
|
+
}
|
|
13
|
+
serializeAttachment(attachment) {
|
|
14
|
+
this.webSocket.serializeAttachment(attachment);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export { WebsocketWrapper };
|
|
19
|
+
//# sourceMappingURL=chunk-KCPOB32E.js.map
|
|
20
|
+
//# sourceMappingURL=chunk-KCPOB32E.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/WebsocketWrapper.ts"],"names":[],"mappings":";AAAO,IAAM,mBAAN,MAA8C;AAAA,EAC7C,YAAmB,SAAA,EAAsB;AAAtB,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AAAA,EAAuB;AAAA,EAE1C,KAAK,OAAA,EAAmB;AAC9B,IAAA,IAAI,IAAA,CAAK,SAAA,CAAU,UAAA,KAAe,SAAA,CAAU,IAAA,EAAM;AAClD,IAAA,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,IAAA,CAAK,SAAA,CAAU,OAAO,CAAC,CAAA;AAAA,EAC5C;AAAA,EAEO,qBAAA,GAAwB;AAC9B,IAAA,OAAO,IAAA,CAAK,UAAU,qBAAA,EAAsB;AAAA,EAC7C;AAAA,EAEO,oBAAoB,UAAA,EAAyB;AACnD,IAAA,IAAA,CAAK,SAAA,CAAU,oBAAoB,UAAU,CAAA;AAAA,EAC9C;AACD","file":"chunk-KCPOB32E.js","sourcesContent":["export class WebsocketWrapper<TAttachment, TMessage> {\n\tpublic constructor(public webSocket: WebSocket) {}\n\n\tpublic send(message: TMessage) {\n\t\tif (this.webSocket.readyState !== WebSocket.OPEN) return;\n\t\tthis.webSocket.send(JSON.stringify(message));\n\t}\n\n\tpublic deserializeAttachment() {\n\t\treturn this.webSocket.deserializeAttachment() as TAttachment;\n\t}\n\n\tpublic serializeAttachment(attachment: TAttachment) {\n\t\tthis.webSocket.serializeAttachment(attachment);\n\t}\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
var __typeError = (msg) => {
|
|
2
|
+
throw TypeError(msg);
|
|
3
|
+
};
|
|
4
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
5
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
6
|
+
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
7
|
+
|
|
8
|
+
export { __privateAdd, __privateMethod };
|
|
9
|
+
//# sourceMappingURL=chunk-NOUFNU2O.js.map
|
|
10
|
+
//# sourceMappingURL=chunk-NOUFNU2O.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-NOUFNU2O.js"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { parseStandardSchema } from './chunk-CAX4POIL.js';
|
|
2
|
+
import { unpack, pack } from 'msgpackr';
|
|
3
|
+
|
|
4
|
+
var standardSchemaMsgpack = (schema) => ({
|
|
5
|
+
async encode(value) {
|
|
6
|
+
const validated = await parseStandardSchema(schema, value);
|
|
7
|
+
const packed = pack(validated);
|
|
8
|
+
return new Uint8Array(packed);
|
|
9
|
+
},
|
|
10
|
+
async decode(bytes) {
|
|
11
|
+
const unpacked = unpack(bytes);
|
|
12
|
+
return parseStandardSchema(schema, unpacked);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export { standardSchemaMsgpack };
|
|
17
|
+
//# sourceMappingURL=chunk-QMGIRIHJ.js.map
|
|
18
|
+
//# sourceMappingURL=chunk-QMGIRIHJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/standardSchemaMsgpack.ts"],"names":[],"mappings":";;;AAIO,IAAM,qBAAA,GAAwB,CACpC,MAAA,MACK;AAAA,EACL,MAAM,OAAO,KAAA,EAA+B;AAC3C,IAAA,MAAM,SAAA,GAAY,MAAM,mBAAA,CAAoB,MAAA,EAAQ,KAAK,CAAA;AACzD,IAAA,MAAM,MAAA,GAAS,KAAK,SAAS,CAAA;AAC7B,IAAA,OAAO,IAAI,WAAW,MAAM,CAAA;AAAA,EAC7B,CAAA;AAAA,EACA,MAAM,OAAO,KAAA,EAA+B;AAC3C,IAAA,MAAM,QAAA,GAAW,OAAO,KAAK,CAAA;AAC7B,IAAA,OAAO,mBAAA,CAAoB,QAAQ,QAAQ,CAAA;AAAA,EAC5C;AACD,CAAA","file":"chunk-QMGIRIHJ.js","sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { pack, unpack } from \"msgpackr\";\nimport { parseStandardSchema } from \"./parseStandardSchema\";\n\nexport const standardSchemaMsgpack = <T>(\n\tschema: StandardSchemaV1<unknown, T>,\n) => ({\n\tasync encode(value: T): Promise<Uint8Array> {\n\t\tconst validated = await parseStandardSchema(schema, value);\n\t\tconst packed = pack(validated);\n\t\treturn new Uint8Array(packed);\n\t},\n\tasync decode(bytes: Uint8Array): Promise<T> {\n\t\tconst unpacked = unpack(bytes);\n\t\treturn parseStandardSchema(schema, unpacked);\n\t},\n});\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { BaseWebSocketDO } from './chunk-XFB6C3NZ.js';
|
|
2
|
+
|
|
3
|
+
// src/StandardSchemaWebSocketDO.ts
|
|
4
|
+
var StandardSchemaWebSocketDO = class extends BaseWebSocketDO {
|
|
5
|
+
constructor(ctx, env, options) {
|
|
6
|
+
super(ctx, env, {
|
|
7
|
+
createSession: (ctx2, websocket) => {
|
|
8
|
+
const schemaOptions = typeof options.standardSchemaSessionOptions === "function" ? options.standardSchemaSessionOptions(ctx2, websocket) : options.standardSchemaSessionOptions;
|
|
9
|
+
return options.createStandardSchemaSession(
|
|
10
|
+
ctx2,
|
|
11
|
+
websocket,
|
|
12
|
+
schemaOptions
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
this.standardSchemaSessionOptions = options.standardSchemaSessionOptions;
|
|
17
|
+
this.createStandardSchemaSessionFn = options.createStandardSchemaSession;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export { StandardSchemaWebSocketDO };
|
|
22
|
+
//# sourceMappingURL=chunk-ULGH6X42.js.map
|
|
23
|
+
//# sourceMappingURL=chunk-ULGH6X42.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/StandardSchemaWebSocketDO.ts"],"names":["ctx"],"mappings":";;;AA0CO,IAAe,yBAAA,GAAf,cAQG,eAAA,CAAgC;AAAA,EAYzC,WAAA,CACC,GAAA,EACA,GAAA,EACA,OAAA,EAMC;AACD,IAAA,KAAA,CAAM,KAAK,GAAA,EAAK;AAAA,MACf,aAAA,EAAe,CAACA,IAAAA,EAAK,SAAA,KAAc;AAClC,QAAA,MAAM,aAAA,GACL,OAAO,OAAA,CAAQ,4BAAA,KAAiC,UAAA,GAC7C,QAAQ,4BAAA,CAA6BA,IAAAA,EAAK,SAAS,CAAA,GACnD,OAAA,CAAQ,4BAAA;AAEZ,QAAA,OAAO,OAAA,CAAQ,2BAAA;AAAA,UACdA,IAAAA;AAAA,UACA,SAAA;AAAA,UACA;AAAA,SACD;AAAA,MACD;AAAA,KACA,CAAA;AACD,IAAA,IAAA,CAAK,+BAA+B,OAAA,CAAQ,4BAAA;AAC5C,IAAA,IAAA,CAAK,gCAAgC,OAAA,CAAQ,2BAAA;AAAA,EAC9C;AACD","file":"chunk-ULGH6X42.js","sourcesContent":["import type { Context } from \"hono\";\nimport type {\n\tSessionClientMessage,\n\tSessionEnv,\n\tSessionServerMessage,\n} from \"./BaseSession\";\nimport { BaseWebSocketDO } from \"./BaseWebSocketDO\";\nimport type {\n\tStandardSchemaSession,\n\tStandardSchemaSessionOptions,\n} from \"./StandardSchemaSession\";\n\nexport type StandardSchemaSessionOptionsOrFactory<\n\tTClientMessage,\n\tTServerMessage,\n\tTEnv extends Cloudflare.Env = Cloudflare.Env,\n> =\n\t| StandardSchemaSessionOptions<TClientMessage, TServerMessage>\n\t| ((\n\t\t\tctx: Context<{ Bindings: TEnv }> | undefined,\n\t\t\twebsocket: WebSocket,\n\t ) => StandardSchemaSessionOptions<TClientMessage, TServerMessage>);\n\nexport type StandardSchemaWebSocketDOOptions<\n\t// biome-ignore lint/suspicious/noExplicitAny: We are using any on purpose to allow any type of session.\n\tTSession extends StandardSchemaSession<any, any, any, any>,\n\tTClientMessage,\n\tTServerMessage,\n\tTEnv extends SessionEnv<TSession>,\n> = {\n\tstandardSchemaSessionOptions: StandardSchemaSessionOptionsOrFactory<\n\t\tTClientMessage,\n\t\tTServerMessage,\n\t\tTEnv\n\t>;\n\tcreateStandardSchemaSession: (\n\t\tctx: Context<{ Bindings: TEnv }> | undefined,\n\t\twebsocket: WebSocket,\n\t\toptions: StandardSchemaSessionOptions<TClientMessage, TServerMessage>,\n\t) => TSession | Promise<TSession>;\n};\n\nexport abstract class StandardSchemaWebSocketDO<\n\t// biome-ignore lint/suspicious/noExplicitAny: We are using any on purpose to allow any type of session.\n\tTSession extends StandardSchemaSession<any, any, any, any>,\n\tTClientMessage extends\n\t\tSessionClientMessage<TSession> = SessionClientMessage<TSession>,\n\tTServerMessage extends\n\t\tSessionServerMessage<TSession> = SessionServerMessage<TSession>,\n\tTEnv extends SessionEnv<TSession> = SessionEnv<TSession>,\n> extends BaseWebSocketDO<TSession, TEnv> {\n\tprotected readonly standardSchemaSessionOptions: StandardSchemaSessionOptionsOrFactory<\n\t\tTClientMessage,\n\t\tTServerMessage,\n\t\tTEnv\n\t>;\n\tprotected readonly createStandardSchemaSessionFn: (\n\t\tctx: Context<{ Bindings: TEnv }> | undefined,\n\t\twebsocket: WebSocket,\n\t\toptions: StandardSchemaSessionOptions<TClientMessage, TServerMessage>,\n\t) => TSession | Promise<TSession>;\n\n\tconstructor(\n\t\tctx: DurableObjectState,\n\t\tenv: TEnv,\n\t\toptions: StandardSchemaWebSocketDOOptions<\n\t\t\tTSession,\n\t\t\tTClientMessage,\n\t\t\tTServerMessage,\n\t\t\tTEnv\n\t\t>,\n\t) {\n\t\tsuper(ctx, env, {\n\t\t\tcreateSession: (ctx, websocket) => {\n\t\t\t\tconst schemaOptions =\n\t\t\t\t\ttypeof options.standardSchemaSessionOptions === \"function\"\n\t\t\t\t\t\t? options.standardSchemaSessionOptions(ctx, websocket)\n\t\t\t\t\t\t: options.standardSchemaSessionOptions;\n\n\t\t\t\treturn options.createStandardSchemaSession(\n\t\t\t\t\tctx,\n\t\t\t\t\twebsocket,\n\t\t\t\t\tschemaOptions,\n\t\t\t\t);\n\t\t\t},\n\t\t});\n\t\tthis.standardSchemaSessionOptions = options.standardSchemaSessionOptions;\n\t\tthis.createStandardSchemaSessionFn = options.createStandardSchemaSession;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { StandardSchemaWebSocketClient } from './chunk-3LWVEY3R.js';
|
|
2
|
+
|
|
3
|
+
// src/standardSchemaRpc.ts
|
|
4
|
+
var StandardSchemaWebSocketRpcSession = class {
|
|
5
|
+
constructor(options) {
|
|
6
|
+
this.pending = /* @__PURE__ */ new Map();
|
|
7
|
+
this.idSeq = 0;
|
|
8
|
+
const { onMessage, ...clientOptions } = options;
|
|
9
|
+
this.client = new StandardSchemaWebSocketClient({
|
|
10
|
+
...clientOptions,
|
|
11
|
+
onMessage: (message) => {
|
|
12
|
+
onMessage(message, this);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
nextId(prefix) {
|
|
17
|
+
return `${prefix}-${++this.idSeq}`;
|
|
18
|
+
}
|
|
19
|
+
rejectAllPending(reason) {
|
|
20
|
+
for (const [, pending] of this.pending) {
|
|
21
|
+
pending.reject(reason);
|
|
22
|
+
}
|
|
23
|
+
this.pending.clear();
|
|
24
|
+
}
|
|
25
|
+
close(code, reason) {
|
|
26
|
+
this.client.close(code, reason);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
function createStandardSchemaWebSocketRpcSession(options) {
|
|
30
|
+
return new StandardSchemaWebSocketRpcSession(options);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export { StandardSchemaWebSocketRpcSession, createStandardSchemaWebSocketRpcSession };
|
|
34
|
+
//# sourceMappingURL=chunk-WJIQBI6I.js.map
|
|
35
|
+
//# sourceMappingURL=chunk-WJIQBI6I.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/standardSchemaRpc.ts"],"names":[],"mappings":";;;AA6BO,IAAM,oCAAN,MAIL;AAAA,EAKD,YACC,OAAA,EAKC;AAVF,IAAA,IAAA,CAAS,OAAA,uBAAc,GAAA,EAAsB;AAE7C,IAAA,IAAA,CAAQ,KAAA,GAAQ,CAAA;AASf,IAAA,MAAM,EAAE,SAAA,EAAW,GAAG,aAAA,EAAc,GAAI,OAAA;AACxC,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,6BAAA,CAA8B;AAAA,MAC/C,GAAG,aAAA;AAAA,MACH,SAAA,EAAW,CAAC,OAAA,KAAY;AACvB,QAAA,SAAA,CAAU,SAAS,IAAI,CAAA;AAAA,MACxB;AAAA,KACA,CAAA;AAAA,EACF;AAAA,EAEA,OAAO,MAAA,EAAwB;AAC9B,IAAA,OAAO,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,EAAE,KAAK,KAAK,CAAA,CAAA;AAAA,EACjC;AAAA,EAEA,iBAAiB,MAAA,EAAqB;AACrC,IAAA,KAAA,MAAW,GAAG,OAAO,CAAA,IAAK,KAAK,OAAA,EAAS;AACvC,MAAA,OAAA,CAAQ,OAAO,MAAM,CAAA;AAAA,IACtB;AACA,IAAA,IAAA,CAAK,QAAQ,KAAA,EAAM;AAAA,EACpB;AAAA,EAEA,KAAA,CAAM,MAAe,MAAA,EAAuB;AAC3C,IAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,IAAA,EAAM,MAAM,CAAA;AAAA,EAC/B;AACD;AAEO,SAAS,wCAKf,OAAA,EAKsE;AACtE,EAAA,OAAO,IAAI,kCAAkC,OAAO,CAAA;AACrD","file":"chunk-WJIQBI6I.js","sourcesContent":["import {\n\ttype StandardSchemaWebSocketClientOptions,\n\tStandardSchemaWebSocketClient,\n} from \"./StandardSchemaWebSocketClient\";\n\nexport type StandardSchemaWebSocketRpcSessionConstructorOptions<\n\tTClientMsg,\n\tTServerMsg,\n\tTPending extends { reject: (error: Error) => void },\n> = Omit<\n\tStandardSchemaWebSocketClientOptions<TClientMsg, TServerMsg>,\n\t\"onMessage\"\n> & {\n\tonMessage: (\n\t\tmessage: TServerMsg,\n\t\tsession: StandardSchemaWebSocketRpcSession<\n\t\t\tTClientMsg,\n\t\t\tTServerMsg,\n\t\t\tTPending\n\t\t>,\n\t) => void;\n};\n\n/**\n * WebSocket client session with a pending map for request/response RPC and a\n * monotonic id helper. Wire formats stay in your Standard Schema schemas; you dispatch\n * {@link TServerMsg} in `onMessage` (typically with `switch` + `exhaustiveGuard`)\n * and resolve/reject entries in {@link pending}.\n */\nexport class StandardSchemaWebSocketRpcSession<\n\tTClientMsg,\n\tTServerMsg,\n\tTPending extends { reject: (error: Error) => void },\n> {\n\treadonly pending = new Map<string, TPending>();\n\treadonly client: StandardSchemaWebSocketClient<TClientMsg, TServerMsg>;\n\tprivate idSeq = 0;\n\n\tconstructor(\n\t\toptions: StandardSchemaWebSocketRpcSessionConstructorOptions<\n\t\t\tTClientMsg,\n\t\t\tTServerMsg,\n\t\t\tTPending\n\t\t>,\n\t) {\n\t\tconst { onMessage, ...clientOptions } = options;\n\t\tthis.client = new StandardSchemaWebSocketClient({\n\t\t\t...clientOptions,\n\t\t\tonMessage: (message) => {\n\t\t\t\tonMessage(message, this);\n\t\t\t},\n\t\t});\n\t}\n\n\tnextId(prefix: string): string {\n\t\treturn `${prefix}-${++this.idSeq}`;\n\t}\n\n\trejectAllPending(reason: Error): void {\n\t\tfor (const [, pending] of this.pending) {\n\t\t\tpending.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\nexport function createStandardSchemaWebSocketRpcSession<\n\tTClientMsg,\n\tTServerMsg,\n\tTPending extends { reject: (error: Error) => void },\n>(\n\toptions: StandardSchemaWebSocketRpcSessionConstructorOptions<\n\t\tTClientMsg,\n\t\tTServerMsg,\n\t\tTPending\n\t>,\n): StandardSchemaWebSocketRpcSession<TClientMsg, TServerMsg, TPending> {\n\treturn new StandardSchemaWebSocketRpcSession(options);\n}\n"]}
|