@firtoz/websocket-do 12.0.0 → 13.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +5 -1
  2. package/dist/BaseSession.d.ts +41 -0
  3. package/dist/BaseSession.js +5 -0
  4. package/dist/BaseSession.js.map +1 -0
  5. package/dist/BaseWebSocketDO.d.ts +42 -0
  6. package/dist/BaseWebSocketDO.js +4 -0
  7. package/dist/BaseWebSocketDO.js.map +1 -0
  8. package/dist/StandardSchemaSession.d.ts +41 -0
  9. package/dist/StandardSchemaSession.js +8 -0
  10. package/dist/StandardSchemaSession.js.map +1 -0
  11. package/dist/StandardSchemaWebSocketClient.d.ts +45 -0
  12. package/dist/StandardSchemaWebSocketClient.js +5 -0
  13. package/dist/StandardSchemaWebSocketClient.js.map +1 -0
  14. package/dist/StandardSchemaWebSocketDO.d.ts +28 -0
  15. package/dist/StandardSchemaWebSocketDO.js +5 -0
  16. package/dist/StandardSchemaWebSocketDO.js.map +1 -0
  17. package/dist/WebsocketWrapper.d.ts +9 -0
  18. package/dist/WebsocketWrapper.js +4 -0
  19. package/dist/WebsocketWrapper.js.map +1 -0
  20. package/dist/chunk-3C77OSOD.js +54 -0
  21. package/dist/chunk-3C77OSOD.js.map +1 -0
  22. package/dist/chunk-3LWVEY3R.js +130 -0
  23. package/dist/chunk-3LWVEY3R.js.map +1 -0
  24. package/dist/chunk-53MFRNQS.js +153 -0
  25. package/dist/chunk-53MFRNQS.js.map +1 -0
  26. package/dist/chunk-CAX4POIL.js +13 -0
  27. package/dist/chunk-CAX4POIL.js.map +1 -0
  28. package/dist/chunk-KCPOB32E.js +20 -0
  29. package/dist/chunk-KCPOB32E.js.map +1 -0
  30. package/dist/chunk-NOUFNU2O.js +10 -0
  31. package/dist/chunk-NOUFNU2O.js.map +1 -0
  32. package/dist/chunk-QMGIRIHJ.js +18 -0
  33. package/dist/chunk-QMGIRIHJ.js.map +1 -0
  34. package/dist/chunk-ULGH6X42.js +23 -0
  35. package/dist/chunk-ULGH6X42.js.map +1 -0
  36. package/dist/chunk-WJIQBI6I.js +35 -0
  37. package/dist/chunk-WJIQBI6I.js.map +1 -0
  38. package/dist/chunk-XFB6C3NZ.js +134 -0
  39. package/dist/chunk-XFB6C3NZ.js.map +1 -0
  40. package/dist/index.d.ts +14 -0
  41. package/dist/index.js +11 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/parseStandardSchema.d.ts +9 -0
  44. package/dist/parseStandardSchema.js +4 -0
  45. package/dist/parseStandardSchema.js.map +1 -0
  46. package/dist/standardSchemaMsgpack.d.ts +8 -0
  47. package/dist/standardSchemaMsgpack.js +5 -0
  48. package/dist/standardSchemaMsgpack.js.map +1 -0
  49. package/dist/standardSchemaRpc.d.ts +30 -0
  50. package/dist/standardSchemaRpc.js +6 -0
  51. package/dist/standardSchemaRpc.js.map +1 -0
  52. package/dist/standardSchemaRpcReact.d.ts +27 -0
  53. package/dist/standardSchemaRpcReact.js +54 -0
  54. package/dist/standardSchemaRpcReact.js.map +1 -0
  55. package/package.json +24 -22
@@ -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"]}
@@ -0,0 +1,134 @@
1
+ import { __privateAdd, __privateMethod } from './chunk-NOUFNU2O.js';
2
+ import { DurableObject } from 'cloudflare:workers';
3
+ import { Hono } from 'hono';
4
+
5
+ var _BaseWebSocketDO_instances, handleClose_fn;
6
+ var BaseWebSocketDO = class extends DurableObject {
7
+ constructor(ctx, env, options) {
8
+ super(ctx, env);
9
+ this.options = options;
10
+ __privateAdd(this, _BaseWebSocketDO_instances);
11
+ this.sessions = /* @__PURE__ */ new Map();
12
+ this.ctx.blockConcurrencyWhile(async () => {
13
+ const websockets = this.ctx.getWebSockets();
14
+ await Promise.all(
15
+ websockets.map(async (websocket) => {
16
+ try {
17
+ const session = await options.createSession(void 0, websocket);
18
+ session.resume();
19
+ this.sessions.set(websocket, session);
20
+ } catch (error) {
21
+ console.error(`Error during session setup: ${error}`);
22
+ await this.webSocketError(websocket, error);
23
+ }
24
+ })
25
+ );
26
+ });
27
+ }
28
+ getBaseApp() {
29
+ return new Hono().get(
30
+ "/websocket",
31
+ async (ctx) => {
32
+ const { req } = ctx;
33
+ if (req.header("Upgrade") !== "websocket") {
34
+ console.error("Expected websocket");
35
+ return ctx.text("Expected websocket", 400);
36
+ }
37
+ const [client, server] = Object.values(new WebSocketPair());
38
+ try {
39
+ await this.handleSession(ctx, server);
40
+ return new Response(null, { status: 101, webSocket: client });
41
+ } catch (error) {
42
+ console.error(error);
43
+ client.accept();
44
+ client.send(
45
+ JSON.stringify({
46
+ error: "Uncaught exception during session setup."
47
+ })
48
+ );
49
+ client.close(1011, "Uncaught exception during session setup.");
50
+ return new Response(null, { status: 101, webSocket: client });
51
+ }
52
+ }
53
+ );
54
+ }
55
+ async handleSession(ctx, ws) {
56
+ this.ctx.acceptWebSocket(ws);
57
+ try {
58
+ const session = await this.options.createSession(ctx, ws);
59
+ session.startFresh(ctx);
60
+ this.sessions.set(ws, session);
61
+ } catch (error) {
62
+ console.error(`Error during session setup: ${error}`);
63
+ await this.webSocketError(ws, error);
64
+ }
65
+ }
66
+ async webSocketMessage(ws, message) {
67
+ const session = this.sessions.get(ws);
68
+ if (!session) return;
69
+ try {
70
+ if (message instanceof ArrayBuffer) {
71
+ await session.handleBufferMessage(message);
72
+ return;
73
+ }
74
+ const rawMessageSession = session;
75
+ if (rawMessageSession.handleRawMessage) {
76
+ await rawMessageSession.handleRawMessage(message);
77
+ return;
78
+ }
79
+ const parsed = JSON.parse(message);
80
+ await session.handleMessage(parsed);
81
+ } catch (error) {
82
+ console.error(`Error during session message: ${error}`);
83
+ }
84
+ }
85
+ async webSocketClose(ws, _code, _reason, _wasClean) {
86
+ const session = this.sessions.get(ws);
87
+ if (!session) return;
88
+ try {
89
+ await __privateMethod(this, _BaseWebSocketDO_instances, handleClose_fn).call(this, session);
90
+ } catch (error) {
91
+ console.error(`Error during session close: ${error}`);
92
+ } finally {
93
+ if (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CLOSING) {
94
+ ws.close(1e3, "Normal closure");
95
+ }
96
+ }
97
+ }
98
+ async webSocketError(ws, error) {
99
+ const session = this.sessions.get(ws);
100
+ if (!session) {
101
+ if (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CLOSING) {
102
+ ws.close(1011, "Error during session setup.");
103
+ }
104
+ return;
105
+ }
106
+ console.error(`Error for session: ${error}`);
107
+ try {
108
+ await __privateMethod(this, _BaseWebSocketDO_instances, handleClose_fn).call(this, session);
109
+ } catch (error2) {
110
+ console.error(`Error during session close: ${error2}`);
111
+ } finally {
112
+ if (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CLOSING) {
113
+ ws.close(1011, "Error during session.");
114
+ }
115
+ }
116
+ }
117
+ fetch(request) {
118
+ return this.app.fetch(request, this.env);
119
+ }
120
+ };
121
+ _BaseWebSocketDO_instances = new WeakSet();
122
+ handleClose_fn = async function(session) {
123
+ try {
124
+ await session.handleClose();
125
+ } catch (error) {
126
+ console.error(`Error during session close: ${error}`);
127
+ } finally {
128
+ this.sessions.delete(session.websocket);
129
+ }
130
+ };
131
+
132
+ export { BaseWebSocketDO };
133
+ //# sourceMappingURL=chunk-XFB6C3NZ.js.map
134
+ //# sourceMappingURL=chunk-XFB6C3NZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/BaseWebSocketDO.ts"],"names":["error"],"mappings":"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","file":"chunk-XFB6C3NZ.js","sourcesContent":["import { DurableObject } from \"cloudflare:workers\";\nimport type { DOWithHonoApp } from \"@firtoz/hono-fetcher/honoDoFetcher\";\nimport { type Context, Hono } from \"hono\";\nimport type {\n\tBaseSession,\n\tSessionClientMessage,\n\tSessionEnv,\n} from \"./BaseSession\";\n\nexport type BaseWebSocketDOOptions<\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\tTEnv extends SessionEnv<TSession>,\n> = {\n\tcreateSession: (\n\t\tctx: Context<{ Bindings: TEnv }> | undefined,\n\t\twebsocket: WebSocket,\n\t) => TSession | Promise<TSession>;\n};\n\nexport abstract class BaseWebSocketDO<\n\t\t// biome-ignore lint/suspicious/noExplicitAny: We are using any on purpose to allow any type of session.\n\t\tTSession extends BaseSession<any, any, any, any> = BaseSession<\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: We are using any on purpose to allow any type of session.\n\t\t\tany,\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: We are using any on purpose to allow any type of session.\n\t\t\tany,\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: We are using any on purpose to allow any type of session.\n\t\t\tany,\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: We are using any on purpose to allow any type of session.\n\t\t\tany\n\t\t>,\n\t\tTEnv extends SessionEnv<TSession> = SessionEnv<TSession>,\n\t>\n\textends DurableObject<TEnv>\n\timplements DOWithHonoApp\n{\n\tprotected readonly sessions = new Map<WebSocket, TSession>();\n\tabstract readonly app: Hono<{ Bindings: TEnv }>;\n\n\tconstructor(\n\t\tctx: DurableObjectState,\n\t\tenv: TEnv,\n\t\tprivate readonly options: BaseWebSocketDOOptions<TSession, TEnv>,\n\t) {\n\t\tsuper(ctx, env);\n\n\t\tthis.ctx.blockConcurrencyWhile(async () => {\n\t\t\tconst websockets = this.ctx.getWebSockets();\n\t\t\tawait Promise.all(\n\t\t\t\twebsockets.map(async (websocket) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// For resumed sessions, we don't have a Hono context\n\t\t\t\t\t\t// Pass undefined and let implementers handle it\n\t\t\t\t\t\tconst session = await options.createSession(undefined, websocket);\n\t\t\t\t\t\tsession.resume();\n\t\t\t\t\t\tthis.sessions.set(websocket, session);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconsole.error(`Error during session setup: ${error}`);\n\t\t\t\t\t\tawait this.webSocketError(websocket, error);\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t);\n\t\t});\n\t}\n\n\tprotected getBaseApp() {\n\t\treturn new Hono<{ Bindings: TEnv }>().get(\n\t\t\t\"/websocket\",\n\t\t\tasync (ctx): Promise<Response> => {\n\t\t\t\tconst { req } = ctx;\n\t\t\t\tif (req.header(\"Upgrade\") !== \"websocket\") {\n\t\t\t\t\tconsole.error(\"Expected websocket\");\n\t\t\t\t\treturn ctx.text(\"Expected websocket\", 400);\n\t\t\t\t}\n\n\t\t\t\tconst [client, server] = Object.values(new WebSocketPair()) as [\n\t\t\t\t\tWebSocket,\n\t\t\t\t\tWebSocket,\n\t\t\t\t];\n\n\t\t\t\ttry {\n\t\t\t\t\tawait this.handleSession(ctx, server);\n\t\t\t\t\treturn new Response(null, { status: 101, webSocket: client });\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error(error);\n\t\t\t\t\tclient.accept();\n\t\t\t\t\tclient.send(\n\t\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\t\terror: \"Uncaught exception during session setup.\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\tclient.close(1011, \"Uncaught exception during session setup.\");\n\t\t\t\t\treturn new Response(null, { status: 101, webSocket: client });\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\t}\n\n\tasync handleSession(\n\t\tctx: Context<{ Bindings: TEnv }>,\n\t\tws: WebSocket,\n\t): Promise<void> {\n\t\tthis.ctx.acceptWebSocket(ws);\n\t\ttry {\n\t\t\tconst session = await this.options.createSession(ctx, ws);\n\t\t\tsession.startFresh(ctx);\n\t\t\tthis.sessions.set(ws, session);\n\t\t} catch (error) {\n\t\t\tconsole.error(`Error during session setup: ${error}`);\n\t\t\tawait this.webSocketError(ws, error);\n\t\t}\n\t}\n\n\toverride async webSocketMessage(\n\t\tws: WebSocket,\n\t\tmessage: string | ArrayBuffer,\n\t): Promise<void> {\n\t\tconst session = this.sessions.get(ws);\n\t\tif (!session) return;\n\n\t\ttry {\n\t\t\tif (message instanceof ArrayBuffer) {\n\t\t\t\tawait session.handleBufferMessage(message);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst rawMessageSession = session as BaseSession<\n\t\t\t\tunknown,\n\t\t\t\tunknown,\n\t\t\t\tunknown,\n\t\t\t\tTEnv\n\t\t\t> & {\n\t\t\t\thandleRawMessage?: (rawMessage: string) => Promise<void>;\n\t\t\t};\n\t\t\tif (rawMessageSession.handleRawMessage) {\n\t\t\t\tawait rawMessageSession.handleRawMessage(message);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst parsed = JSON.parse(message) as SessionClientMessage<TSession>;\n\t\t\tawait session.handleMessage(parsed);\n\t\t} catch (error) {\n\t\t\tconsole.error(`Error during session message: ${error}`);\n\t\t\t// Let the implementer decide how to handle errors in their session implementation\n\t\t\t// The session can optionally implement error handling that closes the connection if needed\n\t\t}\n\t}\n\n\toverride async webSocketClose(\n\t\tws: WebSocket,\n\t\t_code: number,\n\t\t_reason: string,\n\t\t_wasClean: boolean,\n\t) {\n\t\tconst session = this.sessions.get(ws);\n\t\tif (!session) return;\n\n\t\ttry {\n\t\t\tawait this.#handleClose(session);\n\t\t} catch (error) {\n\t\t\tconsole.error(`Error during session close: ${error}`);\n\t\t} finally {\n\t\t\t// Call close() for both OPEN and CLOSING states\n\t\t\t// For CLOSING, this can help ensure the WebSocket fully transitions to CLOSED\n\t\t\tif (\n\t\t\t\tws.readyState === WebSocket.OPEN ||\n\t\t\t\tws.readyState === WebSocket.CLOSING\n\t\t\t) {\n\t\t\t\tws.close(1000, \"Normal closure\");\n\t\t\t}\n\t\t}\n\t}\n\n\toverride async webSocketError(ws: WebSocket, error: unknown) {\n\t\tconst session = this.sessions.get(ws);\n\t\tif (!session) {\n\t\t\t// Call close() for both OPEN and CLOSING states\n\t\t\tif (\n\t\t\t\tws.readyState === WebSocket.OPEN ||\n\t\t\t\tws.readyState === WebSocket.CLOSING\n\t\t\t) {\n\t\t\t\tws.close(1011, \"Error during session setup.\");\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconsole.error(`Error for session: ${error}`);\n\t\ttry {\n\t\t\tawait this.#handleClose(session);\n\t\t} catch (error) {\n\t\t\tconsole.error(`Error during session close: ${error}`);\n\t\t} finally {\n\t\t\t// Call close() for both OPEN and CLOSING states\n\t\t\tif (\n\t\t\t\tws.readyState === WebSocket.OPEN ||\n\t\t\t\tws.readyState === WebSocket.CLOSING\n\t\t\t) {\n\t\t\t\tws.close(1011, \"Error during session.\");\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #handleClose(session: TSession) {\n\t\ttry {\n\t\t\tawait session.handleClose();\n\t\t} catch (error) {\n\t\t\tconsole.error(`Error during session close: ${error}`);\n\t\t} finally {\n\t\t\tthis.sessions.delete(session.websocket);\n\t\t}\n\t}\n\n\toverride fetch(request: Request): Response | Promise<Response> {\n\t\treturn this.app.fetch(request, this.env);\n\t}\n}\n"]}
@@ -0,0 +1,14 @@
1
+ export { BaseSession, BaseSessionHandlers, SessionClientMessage, SessionEnv, SessionServerMessage } from './BaseSession.js';
2
+ export { BaseWebSocketDO, BaseWebSocketDOOptions } from './BaseWebSocketDO.js';
3
+ export { WebsocketWrapper } from './WebsocketWrapper.js';
4
+ export { StandardSchemaSession, StandardSchemaSessionHandlers, StandardSchemaSessionOptions } from './StandardSchemaSession.js';
5
+ export { StandardSchemaWebSocketClient, StandardSchemaWebSocketClientOptions } from './StandardSchemaWebSocketClient.js';
6
+ export { StandardSchemaSessionOptionsOrFactory, StandardSchemaWebSocketDO, StandardSchemaWebSocketDOOptions } from './StandardSchemaWebSocketDO.js';
7
+ export { parseStandardSchema } from './parseStandardSchema.js';
8
+ export { standardSchemaMsgpack } from './standardSchemaMsgpack.js';
9
+ import 'hono';
10
+ import 'hono/hono-base';
11
+ import 'hono/utils/http-status';
12
+ import 'cloudflare:workers';
13
+ import '@firtoz/hono-fetcher/honoDoFetcher';
14
+ import '@standard-schema/spec';
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ export { StandardSchemaSession } from './chunk-53MFRNQS.js';
2
+ export { standardSchemaMsgpack } from './chunk-QMGIRIHJ.js';
3
+ export { BaseSession } from './chunk-3C77OSOD.js';
4
+ export { StandardSchemaWebSocketClient } from './chunk-3LWVEY3R.js';
5
+ export { StandardSchemaWebSocketDO } from './chunk-ULGH6X42.js';
6
+ export { BaseWebSocketDO } from './chunk-XFB6C3NZ.js';
7
+ export { WebsocketWrapper } from './chunk-KCPOB32E.js';
8
+ export { parseStandardSchema } from './chunk-CAX4POIL.js';
9
+ import './chunk-NOUFNU2O.js';
10
+ //# sourceMappingURL=index.js.map
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,9 @@
1
+ import { StandardSchemaV1 } from '@standard-schema/spec';
2
+
3
+ /**
4
+ * Validates {@link value} with a Standard Schema v1 schema and returns the output,
5
+ * or throws an {@link Error} whose message aggregates issue messages.
6
+ */
7
+ declare function parseStandardSchema<T>(schema: StandardSchemaV1<unknown, T>, value: unknown): Promise<T>;
8
+
9
+ export { parseStandardSchema };
@@ -0,0 +1,4 @@
1
+ export { parseStandardSchema } from './chunk-CAX4POIL.js';
2
+ import './chunk-NOUFNU2O.js';
3
+ //# sourceMappingURL=parseStandardSchema.js.map
4
+ //# sourceMappingURL=parseStandardSchema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"parseStandardSchema.js"}
@@ -0,0 +1,8 @@
1
+ import { StandardSchemaV1 } from '@standard-schema/spec';
2
+
3
+ declare const standardSchemaMsgpack: <T>(schema: StandardSchemaV1<unknown, T>) => {
4
+ encode(value: T): Promise<Uint8Array>;
5
+ decode(bytes: Uint8Array): Promise<T>;
6
+ };
7
+
8
+ export { standardSchemaMsgpack };
@@ -0,0 +1,5 @@
1
+ export { standardSchemaMsgpack } from './chunk-QMGIRIHJ.js';
2
+ import './chunk-CAX4POIL.js';
3
+ import './chunk-NOUFNU2O.js';
4
+ //# sourceMappingURL=standardSchemaMsgpack.js.map
5
+ //# sourceMappingURL=standardSchemaMsgpack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"standardSchemaMsgpack.js"}
@@ -0,0 +1,30 @@
1
+ import { StandardSchemaWebSocketClientOptions, StandardSchemaWebSocketClient } from './StandardSchemaWebSocketClient.js';
2
+ import '@standard-schema/spec';
3
+
4
+ type StandardSchemaWebSocketRpcSessionConstructorOptions<TClientMsg, TServerMsg, TPending extends {
5
+ reject: (error: Error) => void;
6
+ }> = Omit<StandardSchemaWebSocketClientOptions<TClientMsg, TServerMsg>, "onMessage"> & {
7
+ onMessage: (message: TServerMsg, session: StandardSchemaWebSocketRpcSession<TClientMsg, TServerMsg, TPending>) => void;
8
+ };
9
+ /**
10
+ * WebSocket client session with a pending map for request/response RPC and a
11
+ * monotonic id helper. Wire formats stay in your Standard Schema schemas; you dispatch
12
+ * {@link TServerMsg} in `onMessage` (typically with `switch` + `exhaustiveGuard`)
13
+ * and resolve/reject entries in {@link pending}.
14
+ */
15
+ declare class StandardSchemaWebSocketRpcSession<TClientMsg, TServerMsg, TPending extends {
16
+ reject: (error: Error) => void;
17
+ }> {
18
+ readonly pending: Map<string, TPending>;
19
+ readonly client: StandardSchemaWebSocketClient<TClientMsg, TServerMsg>;
20
+ private idSeq;
21
+ constructor(options: StandardSchemaWebSocketRpcSessionConstructorOptions<TClientMsg, TServerMsg, TPending>);
22
+ nextId(prefix: string): string;
23
+ rejectAllPending(reason: Error): void;
24
+ close(code?: number, reason?: string): void;
25
+ }
26
+ declare function createStandardSchemaWebSocketRpcSession<TClientMsg, TServerMsg, TPending extends {
27
+ reject: (error: Error) => void;
28
+ }>(options: StandardSchemaWebSocketRpcSessionConstructorOptions<TClientMsg, TServerMsg, TPending>): StandardSchemaWebSocketRpcSession<TClientMsg, TServerMsg, TPending>;
29
+
30
+ export { StandardSchemaWebSocketRpcSession, type StandardSchemaWebSocketRpcSessionConstructorOptions, createStandardSchemaWebSocketRpcSession };
@@ -0,0 +1,6 @@
1
+ export { StandardSchemaWebSocketRpcSession, createStandardSchemaWebSocketRpcSession } from './chunk-WJIQBI6I.js';
2
+ import './chunk-3LWVEY3R.js';
3
+ import './chunk-CAX4POIL.js';
4
+ import './chunk-NOUFNU2O.js';
5
+ //# sourceMappingURL=standardSchemaRpc.js.map
6
+ //# sourceMappingURL=standardSchemaRpc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"standardSchemaRpc.js"}