@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.
Files changed (65) hide show
  1. package/README.md +68 -61
  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 +36 -18
  56. package/src/BaseSession.ts +15 -5
  57. package/src/{ZodSession.ts → StandardSchemaSession.ts} +71 -70
  58. package/src/{ZodWebSocketClient.ts → StandardSchemaWebSocketClient.ts} +30 -50
  59. package/src/{ZodWebSocketDO.ts → StandardSchemaWebSocketDO.ts} +29 -22
  60. package/src/index.ts +15 -12
  61. package/src/parseStandardSchema.ts +17 -0
  62. package/src/standardSchemaMsgpack.ts +17 -0
  63. package/src/standardSchemaRpc.ts +83 -0
  64. package/src/standardSchemaRpcReact.ts +107 -0
  65. package/src/zodMsgpack.ts +0 -13
package/README.md CHANGED
@@ -4,14 +4,18 @@
4
4
  [![npm downloads](https://img.shields.io/npm/dm/%40firtoz%2Fwebsocket-do.svg)](https://www.npmjs.com/package/@firtoz/websocket-do)
5
5
  [![license](https://img.shields.io/npm/l/%40firtoz%2Fwebsocket-do.svg)](https://github.com/firtoz/fullstack-toolkit/blob/main/LICENSE)
6
6
 
7
- Type-safe WebSocket session management for Cloudflare Durable Objects with Hono integration.
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
8
+ [![Cloudflare](https://img.shields.io/badge/Cloudflare-Durable_Objects-F38020?logo=cloudflare&logoColor=white)](https://developers.cloudflare.com/durable-objects/)
9
+ [![Hono](https://img.shields.io/badge/Hono-E36002?logo=hono&logoColor=white)](https://hono.dev)
10
+
11
+ **WebSocket sessions on Durable Objects** — Standard Schema message validation, broadcasting, and Hono integration.
8
12
 
9
13
  > **⚠️ Early WIP Notice:** This package is in very early development and is **not production-ready**. It is TypeScript-only and may have breaking changes. While I (the maintainer) have limited time, I'm open to PRs for features, bug fixes, or additional support (like JS builds). Please feel free to try it out and contribute! See [CONTRIBUTING.md](../../CONTRIBUTING.md) for details.
10
14
 
11
15
  ## Features
12
16
 
13
17
  - 🔒 **Type-safe** - Full TypeScript support with generic types for messages and session data
14
- - ✨ **Zod Validation** - Runtime message validation with `ZodWebSocketClient` and `ZodSession`
18
+ - ✨ **Standard Schema validation** - Runtime message validation with `StandardSchemaWebSocketClient` and `StandardSchemaSession` (Zod, Valibot, ArkType, …)
15
19
  - 🌐 **WebSocket Management** - Built on Cloudflare Durable Objects for stateful WebSocket connections
16
20
  - 🎯 **Session-based** - Abstract session class for easy implementation of custom WebSocket logic
17
21
  - 🔄 **State Persistence** - Automatic serialization/deserialization of session data
@@ -34,10 +38,7 @@ This package requires the following peer dependencies:
34
38
  bun add hono @firtoz/hono-fetcher
35
39
  ```
36
40
 
37
- **For Zod validation features** (ZodWebSocketClient, ZodSession):
38
- ```bash
39
- bun add zod msgpackr
40
- ```
41
+ **For schemas:** use any [Standard Schema v1](https://standardschema.dev/) library (e.g. Zod, Valibot). **`msgpackr`** is a normal dependency of this package (buffer / msgpack mode); you do not add it separately unless your bundler needs it hoisted.
41
42
 
42
43
  For TypeScript support, use `wrangler types` to generate accurate types from your `wrangler.jsonc`:
43
44
 
@@ -101,8 +102,8 @@ const chatSessionHandlers: BaseSessionHandlers<
101
102
  // Handle binary messages if needed
102
103
  },
103
104
 
104
- handleClose: async () => {
105
- console.log('Session closed');
105
+ handleClose: async (session) => {
106
+ console.log('Session closed', session.data);
106
107
  },
107
108
  };
108
109
 
@@ -140,8 +141,8 @@ class ChatSession extends BaseSession<
140
141
  handleBufferMessage: async (message) => {
141
142
  // Handle binary messages if needed
142
143
  },
143
- handleClose: async () => {
144
- console.log(`Session closed for user ${this.data.userId}`);
144
+ handleClose: async (session) => {
145
+ console.log(`Session closed for user ${session.data.userId}`);
145
146
  },
146
147
  });
147
148
  }
@@ -214,13 +215,13 @@ export default {
214
215
  };
215
216
  ```
216
217
 
217
- ## ZodWebSocketClient (Type-Safe Client)
218
+ ## StandardSchemaWebSocketClient (Type-Safe Client)
218
219
 
219
- `ZodWebSocketClient` provides a type-safe WebSocket client with automatic Zod validation for both incoming and outgoing messages.
220
+ `StandardSchemaWebSocketClient` provides a type-safe WebSocket client with automatic validation (Standard Schema v1) for both incoming and outgoing messages.
220
221
 
221
222
  ### Features
222
223
 
223
- - ✅ **Automatic validation** - All messages validated with Zod schemas
224
+ - ✅ **Automatic validation** - All messages validated with your Standard Schema–compatible schemas
224
225
  - 🎯 **Full type inference** - TypeScript types automatically inferred from schemas
225
226
  - 📦 **Dual mode** - Supports both JSON and msgpack (buffer) serialization
226
227
  - 🔗 **DO Integration** - Works seamlessly with `honoDoFetcher` WebSocket connections
@@ -229,7 +230,7 @@ export default {
229
230
  ### Basic Usage
230
231
 
231
232
  ```typescript
232
- import { ZodWebSocketClient } from '@firtoz/websocket-do';
233
+ import { StandardSchemaWebSocketClient } from '@firtoz/websocket-do';
233
234
  import { z } from 'zod';
234
235
 
235
236
  // Define your message schemas
@@ -249,8 +250,8 @@ type ServerMessage = z.infer<typeof ServerMessageSchema>;
249
250
  // Create WebSocket connection (regular or via honoDoFetcher)
250
251
  const ws = new WebSocket('wss://example.com/chat');
251
252
 
252
- // Wrap with ZodWebSocketClient
253
- const client = new ZodWebSocketClient({
253
+ // Wrap with StandardSchemaWebSocketClient
254
+ const client = new StandardSchemaWebSocketClient({
254
255
  webSocket: ws, // Can also use 'url' instead
255
256
  clientSchema: ClientMessageSchema,
256
257
  serverSchema: ServerMessageSchema,
@@ -272,7 +273,7 @@ Perfect for connecting to Durable Objects:
272
273
 
273
274
  ```typescript
274
275
  import { honoDoFetcherWithName } from '@firtoz/hono-fetcher';
275
- import { ZodWebSocketClient } from '@firtoz/websocket-do';
276
+ import { StandardSchemaWebSocketClient } from '@firtoz/websocket-do';
276
277
 
277
278
  // 1. Connect to DO via honoDoFetcher
278
279
  const api = honoDoFetcherWithName(env.CHAT_ROOM, 'room-1');
@@ -281,8 +282,8 @@ const wsResp = await api.websocket({
281
282
  config: { autoAccept: false }, // Let client control acceptance
282
283
  });
283
284
 
284
- // 2. Wrap with ZodWebSocketClient for type safety!
285
- const client = new ZodWebSocketClient({
285
+ // 2. Wrap with StandardSchemaWebSocketClient for type safety!
286
+ const client = new StandardSchemaWebSocketClient({
286
287
  webSocket: wsResp.webSocket,
287
288
  clientSchema: ClientMessageSchema,
288
289
  serverSchema: ServerMessageSchema,
@@ -307,7 +308,7 @@ client.send({ type: 'chat', text: 'Hello from typed client!' });
307
308
  For better performance and smaller payloads, use buffer mode with msgpack:
308
309
 
309
310
  ```typescript
310
- const client = new ZodWebSocketClient({
311
+ const client = new StandardSchemaWebSocketClient({
311
312
  webSocket: ws,
312
313
  clientSchema: ClientMessageSchema,
313
314
  serverSchema: ServerMessageSchema,
@@ -327,14 +328,16 @@ client.send({ type: 'chat', text: 'Efficient binary message!' });
327
328
  #### Constructor Options
328
329
 
329
330
  ```typescript
330
- interface ZodWebSocketClientOptions<TClientMessage, TServerMessage> {
331
+ import type { StandardSchemaV1 } from "@standard-schema/spec";
332
+
333
+ interface StandardSchemaWebSocketClientOptions<TClientMessage, TServerMessage> {
331
334
  // Connection (provide one)
332
335
  url?: string; // Create new WebSocket
333
336
  webSocket?: WebSocket; // Use existing WebSocket (e.g., from honoDoFetcher)
334
337
 
335
338
  // Schemas (required)
336
- clientSchema: z.ZodType<TClientMessage>;
337
- serverSchema: z.ZodType<TServerMessage>;
339
+ clientSchema: StandardSchemaV1<unknown, TClientMessage>;
340
+ serverSchema: StandardSchemaV1<unknown, TServerMessage>;
338
341
 
339
342
  // Serialization
340
343
  enableBufferMessages?: boolean; // Use msgpack instead of JSON (default: false)
@@ -350,18 +353,18 @@ interface ZodWebSocketClientOptions<TClientMessage, TServerMessage> {
350
353
 
351
354
  #### Methods
352
355
 
353
- - `send(message: TClientMessage): void` - Send a validated message
356
+ - `send(message: TClientMessage): Promise<void>` - Send a validated message (async Standard Schema validation)
354
357
  - `close(code?: number, reason?: string): void` - Close the connection
355
358
  - `waitForOpen(): Promise<void>` - Wait for connection to open
356
359
 
357
- ## ZodSession (Validated Sessions)
360
+ ## StandardSchemaSession (Validated Sessions)
358
361
 
359
- `ZodSession` extends `BaseSession` with automatic Zod validation for incoming messages.
362
+ `StandardSchemaSession` extends `BaseSession` with automatic validation for incoming messages.
360
363
 
361
364
  ### Basic Usage
362
365
 
363
366
  ```typescript
364
- import { ZodSession } from '@firtoz/websocket-do';
367
+ import { StandardSchemaSession } from '@firtoz/websocket-do';
365
368
  import { z } from 'zod';
366
369
 
367
370
  // Define schemas
@@ -384,7 +387,7 @@ interface SessionData {
384
387
  }
385
388
 
386
389
  // Implement validated session
387
- class ChatSession extends ZodSession<
390
+ class ChatSession extends StandardSchemaSession<
388
391
  SessionData,
389
392
  ServerMessage,
390
393
  ClientMessage,
@@ -393,7 +396,7 @@ class ChatSession extends ZodSession<
393
396
  constructor(
394
397
  websocket: WebSocket,
395
398
  sessions: Map<WebSocket, ChatSession>,
396
- options: ZodSessionOptions<ClientMessage, ServerMessage>
399
+ options: StandardSchemaSessionOptions<ClientMessage, ServerMessage>
397
400
  ) {
398
401
  super(websocket, sessions, options, {
399
402
  createData: (ctx) => ({ name: 'Anonymous' }),
@@ -417,18 +420,18 @@ class ChatSession extends ZodSession<
417
420
  }
418
421
  },
419
422
 
420
- handleClose: async () => {
421
- console.log(`${this.data.name} disconnected`);
423
+ handleClose: async (session) => {
424
+ console.log(`${session.data.name} disconnected`);
422
425
  },
423
426
  });
424
427
  }
425
428
  }
426
429
  ```
427
430
 
428
- ### Buffer Mode with ZodSession
431
+ ### Buffer Mode with StandardSchemaSession
429
432
 
430
433
  ```typescript
431
- class ChatSession extends ZodSession<...> {
434
+ class ChatSession extends StandardSchemaSession<...> {
432
435
  constructor(
433
436
  websocket: WebSocket,
434
437
  sessions: Map<WebSocket, ChatSession>
@@ -443,8 +446,8 @@ class ChatSession extends ZodSession<...> {
443
446
  // Messages automatically decoded from msgpack
444
447
  // Handle validated message
445
448
  },
446
- handleClose: async () => {
447
- console.log('Session closed');
449
+ handleClose: async (session) => {
450
+ console.log('Session closed', session.data);
448
451
  },
449
452
  });
450
453
  }
@@ -521,13 +524,17 @@ constructor(
521
524
 
522
525
  ```typescript
523
526
  type BaseSessionHandlers<TData, TServerMessage, TClientMessage, TEnv> = {
524
- createData: (ctx: Context<{ Bindings: TEnv }>) => TData;
527
+ createData?: (ctx: Context<{ Bindings: TEnv }>) => TData;
525
528
  handleMessage: (message: TClientMessage) => Promise<void>;
526
529
  handleBufferMessage: (message: ArrayBuffer) => Promise<void>;
527
- handleClose: () => Promise<void>;
530
+ handleClose: (
531
+ session: BaseSession<TData, TServerMessage, TClientMessage, TEnv>,
532
+ ) => Promise<void>;
528
533
  };
529
534
  ```
530
535
 
536
+ If `createData` is omitted, `startFresh` sets `data` to `{}` (use an empty `TData` such as `Record<string, never>`).
537
+
531
538
  #### Methods
532
539
 
533
540
  - `send(message: TServerMessage): void`
@@ -537,7 +544,7 @@ type BaseSessionHandlers<TData, TServerMessage, TClientMessage, TEnv> = {
537
544
  - Send message to all connected sessions
538
545
 
539
546
  - `startFresh(ctx: Context): void`
540
- - Initialize new session (called automatically)
547
+ - Initialize new session (called automatically). Uses `createData` when provided; otherwise `{}`.
541
548
 
542
549
  - `resume(): void`
543
550
  - Resume existing session after hibernation (called automatically)
@@ -635,8 +642,8 @@ class GameSession extends BaseSession<GameData, ServerMsg, ClientMsg, Env> {
635
642
  // Handle buffer messages if needed
636
643
  },
637
644
 
638
- handleClose: async () => {
639
- console.log('Game session closed');
645
+ handleClose: async (session) => {
646
+ console.log('Game session closed', session.data);
640
647
  },
641
648
  });
642
649
  }
@@ -678,8 +685,8 @@ class MySession extends BaseSession<...> {
678
685
  // Handle buffer messages
679
686
  },
680
687
 
681
- handleClose: async () => {
682
- console.log('Session closed');
688
+ handleClose: async (session) => {
689
+ console.log('Session closed', session.data);
683
690
  },
684
691
  });
685
692
  }
@@ -693,22 +700,22 @@ This package exports the following:
693
700
  ### Classes
694
701
  - `BaseWebSocketDO` - Base class for WebSocket Durable Objects (composition-based)
695
702
  - `BaseSession` - Concrete session class with handler injection
696
- - `ZodWebSocketClient` - Type-safe WebSocket client with Zod validation
697
- - `ZodSession` - Concrete session class with Zod validation and handler injection
698
- - `ZodWebSocketDO` - Base class for WebSocket DOs with Zod validation
703
+ - `StandardSchemaWebSocketClient` - Type-safe WebSocket client with Standard Schema validation
704
+ - `StandardSchemaSession` - Concrete session class with validation and handler injection
705
+ - `StandardSchemaWebSocketDO` - Base class for WebSocket DOs with Standard Schema sessions
699
706
  - `WebsocketWrapper` - Low-level WebSocket wrapper with typed attachments
700
707
 
701
708
  ### Types
702
709
  - `BaseSessionHandlers` - Handler interface for `BaseSession`
703
710
  - `BaseWebSocketDOOptions` - Options interface for `BaseWebSocketDO`
704
- - `ZodSessionHandlers` - Handler interface for `ZodSession`
705
- - `ZodSessionOptions` - Options interface for `ZodSession`
706
- - `ZodSessionOptionsOrFactory` - Options or factory function for `ZodSession`
707
- - `ZodWebSocketDOOptions` - Options interface for `ZodWebSocketDO`
708
- - `ZodWebSocketClientOptions` - Options interface for `ZodWebSocketClient`
711
+ - `StandardSchemaSessionHandlers` - Handler interface for `StandardSchemaSession`
712
+ - `StandardSchemaSessionOptions` - Options interface for `StandardSchemaSession`
713
+ - `StandardSchemaSessionOptionsOrFactory` - Options or factory function for `StandardSchemaSession`
714
+ - `StandardSchemaWebSocketDOOptions` - Options interface for `StandardSchemaWebSocketDO`
715
+ - `StandardSchemaWebSocketClientOptions` - Options interface for `StandardSchemaWebSocketClient`
709
716
 
710
717
  ### Utilities
711
- - `zodMsgpack` - Msgpack encode/decode with Zod validation
718
+ - `standardSchemaMsgpack` - Msgpack encode/decode with Standard Schema validation
712
719
 
713
720
  ## Complete Example
714
721
 
@@ -734,7 +741,7 @@ export type ClientMessage = z.infer<typeof ClientMessageSchema>;
734
741
  export type ServerMessage = z.infer<typeof ServerMessageSchema>;
735
742
 
736
743
  // do.ts - Server-side (Durable Object)
737
- import { BaseWebSocketDO, ZodSession, type ZodSessionOptions } from '@firtoz/websocket-do';
744
+ import { BaseWebSocketDO, StandardSchemaSession, type StandardSchemaSessionOptions } from '@firtoz/websocket-do';
738
745
  import { ClientMessageSchema, ServerMessageSchema } from './schemas';
739
746
 
740
747
  interface SessionData {
@@ -742,11 +749,11 @@ interface SessionData {
742
749
  joinedAt: number;
743
750
  }
744
751
 
745
- class ChatSession extends ZodSession<SessionData, ServerMessage, ClientMessage, Env> {
752
+ class ChatSession extends StandardSchemaSession<SessionData, ServerMessage, ClientMessage, Env> {
746
753
  constructor(
747
754
  websocket: WebSocket,
748
755
  sessions: Map<WebSocket, ChatSession>,
749
- options: ZodSessionOptions<ClientMessage, ServerMessage>
756
+ options: StandardSchemaSessionOptions<ClientMessage, ServerMessage>
750
757
  ) {
751
758
  super(websocket, sessions, options, {
752
759
  createData: () => ({
@@ -775,8 +782,8 @@ class ChatSession extends ZodSession<SessionData, ServerMessage, ClientMessage,
775
782
  }
776
783
  },
777
784
 
778
- handleClose: async () => {
779
- console.log(`${this.data.name} disconnected`);
785
+ handleClose: async (session) => {
786
+ console.log(`${session.data.name} disconnected`);
780
787
  },
781
788
  });
782
789
  }
@@ -806,7 +813,7 @@ export class ChatRoomDO extends BaseWebSocketDO<ChatSession, Env> {
806
813
  }
807
814
 
808
815
  // client.ts - Client-side
809
- import { ZodWebSocketClient } from '@firtoz/websocket-do';
816
+ import { StandardSchemaWebSocketClient } from '@firtoz/websocket-do';
810
817
  import { honoDoFetcherWithName } from '@firtoz/hono-fetcher';
811
818
  import { ClientMessageSchema, ServerMessageSchema } from './schemas';
812
819
 
@@ -818,8 +825,8 @@ async function connectToChat(env: Env, roomName: string) {
818
825
  config: { autoAccept: false },
819
826
  });
820
827
 
821
- // 2. Wrap with ZodWebSocketClient
822
- const client = new ZodWebSocketClient({
828
+ // 2. Wrap with StandardSchemaWebSocketClient
829
+ const client = new StandardSchemaWebSocketClient({
823
830
  webSocket: wsResp.webSocket,
824
831
  clientSchema: ClientMessageSchema,
825
832
  serverSchema: ServerMessageSchema,
@@ -868,8 +875,8 @@ This package includes comprehensive integration tests in a separate test package
868
875
  - ✅ Real-time WebSocket message exchange
869
876
  - ✅ WebSocket session management
870
877
  - ✅ Type-safe DO client integration
871
- - ✅ Zod validation in both JSON and msgpack modes
872
- - ✅ Integration between honoDoFetcher and ZodWebSocketClient
878
+ - ✅ Standard Schema validation in both JSON and msgpack modes
879
+ - ✅ Integration between honoDoFetcher and StandardSchemaWebSocketClient
873
880
 
874
881
  For detailed information about testing capabilities, example implementations, comprehensive test coverage, and setup instructions, see the [websocket-do-test](../../tests/websocket-do-test/) package.
875
882
 
@@ -0,0 +1,41 @@
1
+ import { Context } from 'hono';
2
+
3
+ type SessionData<TSession extends BaseSession<any, any, any, any>> = TSession extends BaseSession<infer TData, infer _TServerMessage, infer _TClientMessage, infer _TEnv> ? TData : never;
4
+ type SessionClientMessage<TSession extends BaseSession<any, any, any, any>> = TSession extends BaseSession<infer _TData, infer _TServerMessage, infer TClientMessage, infer _TEnv> ? TClientMessage : never;
5
+ type SessionServerMessage<TSession extends BaseSession<any, any, any, any>> = TSession extends BaseSession<infer _TData, infer TServerMessage, infer _TClientMessage, infer _TEnv> ? TServerMessage : never;
6
+ type SessionEnv<TSession extends BaseSession<any, any, any, any>> = TSession extends BaseSession<infer _TData, infer _TServerMessage, infer _TClientMessage, infer TEnv extends Cloudflare.Env> ? TEnv : never;
7
+ type BaseSessionHandlers<TData, TServerMessage, TClientMessage, TEnv extends object = Cloudflare.Env> = {
8
+ /**
9
+ * Per-connection state. If omitted, `startFresh` initializes `data` as `{}`
10
+ * (use empty `TData`, e.g. `Record<string, never>`).
11
+ */
12
+ createData?: (ctx: Context<{
13
+ Bindings: TEnv;
14
+ }>) => TData;
15
+ handleMessage: (message: TClientMessage) => Promise<void>;
16
+ handleBufferMessage: (message: ArrayBuffer) => Promise<void>;
17
+ /** Called when this connection closes; `session` is this {@link BaseSession} instance. */
18
+ handleClose: (session: BaseSession<TData, TServerMessage, TClientMessage, TEnv>) => Promise<void>;
19
+ };
20
+ declare class BaseSession<TData, TServerMessage, TClientMessage, TEnv extends object = Cloudflare.Env> {
21
+ websocket: WebSocket;
22
+ protected sessions: Map<WebSocket, BaseSession<TData, TServerMessage, TClientMessage, TEnv>>;
23
+ private _data;
24
+ get data(): TData;
25
+ private set data(value);
26
+ private readonly wrapper;
27
+ protected readonly handlers: BaseSessionHandlers<TData, TServerMessage, TClientMessage, TEnv>;
28
+ constructor(websocket: WebSocket, sessions: Map<WebSocket, BaseSession<TData, TServerMessage, TClientMessage, TEnv>>, handlers: BaseSessionHandlers<TData, TServerMessage, TClientMessage, TEnv>);
29
+ startFresh(ctx: Context<{
30
+ Bindings: TEnv;
31
+ }>): void;
32
+ resume(): void;
33
+ update(): void;
34
+ broadcast(message: TServerMessage, excludeSelf?: boolean): void;
35
+ send(message: TServerMessage): void;
36
+ handleMessage(message: TClientMessage): Promise<void>;
37
+ handleBufferMessage(message: ArrayBuffer): Promise<void>;
38
+ handleClose(): Promise<void>;
39
+ }
40
+
41
+ export { BaseSession, type BaseSessionHandlers, type SessionClientMessage, type SessionData, type SessionEnv, type SessionServerMessage };
@@ -0,0 +1,5 @@
1
+ export { BaseSession } from './chunk-3C77OSOD.js';
2
+ import './chunk-KCPOB32E.js';
3
+ import './chunk-NOUFNU2O.js';
4
+ //# sourceMappingURL=BaseSession.js.map
5
+ //# sourceMappingURL=BaseSession.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"BaseSession.js"}
@@ -0,0 +1,42 @@
1
+ import * as hono_hono_base from 'hono/hono-base';
2
+ import * as hono_utils_http_status from 'hono/utils/http-status';
3
+ import { DurableObject } from 'cloudflare:workers';
4
+ import { DOWithHonoApp } from '@firtoz/hono-fetcher/honoDoFetcher';
5
+ import { Context, Hono } from 'hono';
6
+ import { BaseSession, SessionEnv } from './BaseSession.js';
7
+
8
+ type BaseWebSocketDOOptions<TSession extends BaseSession<any, any, any, any>, TEnv extends SessionEnv<TSession>> = {
9
+ createSession: (ctx: Context<{
10
+ Bindings: TEnv;
11
+ }> | undefined, websocket: WebSocket) => TSession | Promise<TSession>;
12
+ };
13
+ declare abstract class BaseWebSocketDO<TSession extends BaseSession<any, any, any, any> = BaseSession<any, any, any, any>, TEnv extends SessionEnv<TSession> = SessionEnv<TSession>> extends DurableObject<TEnv> implements DOWithHonoApp {
14
+ #private;
15
+ private readonly options;
16
+ protected readonly sessions: Map<WebSocket, TSession>;
17
+ abstract readonly app: Hono<{
18
+ Bindings: TEnv;
19
+ }>;
20
+ constructor(ctx: DurableObjectState, env: TEnv, options: BaseWebSocketDOOptions<TSession, TEnv>);
21
+ protected getBaseApp(): hono_hono_base.HonoBase<{
22
+ Bindings: TEnv;
23
+ }, {
24
+ "/websocket": {
25
+ $get: {
26
+ input: {};
27
+ output: {};
28
+ outputFormat: string;
29
+ status: hono_utils_http_status.StatusCode;
30
+ };
31
+ };
32
+ }, "/", "/websocket">;
33
+ handleSession(ctx: Context<{
34
+ Bindings: TEnv;
35
+ }>, ws: WebSocket): Promise<void>;
36
+ webSocketMessage(ws: WebSocket, message: string | ArrayBuffer): Promise<void>;
37
+ webSocketClose(ws: WebSocket, _code: number, _reason: string, _wasClean: boolean): Promise<void>;
38
+ webSocketError(ws: WebSocket, error: unknown): Promise<void>;
39
+ fetch(request: Request): Response | Promise<Response>;
40
+ }
41
+
42
+ export { BaseWebSocketDO, type BaseWebSocketDOOptions };
@@ -0,0 +1,4 @@
1
+ export { BaseWebSocketDO } from './chunk-XFB6C3NZ.js';
2
+ import './chunk-NOUFNU2O.js';
3
+ //# sourceMappingURL=BaseWebSocketDO.js.map
4
+ //# sourceMappingURL=BaseWebSocketDO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"BaseWebSocketDO.js"}
@@ -0,0 +1,41 @@
1
+ import { StandardSchemaV1 } from '@standard-schema/spec';
2
+ import { Context } from 'hono';
3
+ import { BaseSession } from './BaseSession.js';
4
+
5
+ type StandardSchemaSessionOptions<TClientMessage, TServerMessage> = {
6
+ clientSchema: StandardSchemaV1<unknown, TClientMessage>;
7
+ serverSchema: StandardSchemaV1<unknown, TServerMessage>;
8
+ serializeJson?: (value: unknown) => string;
9
+ deserializeJson?: (raw: string) => unknown;
10
+ enableBufferMessages?: boolean;
11
+ sendProtocolError?: (websocket: WebSocket, errorMessage: string) => Promise<void>;
12
+ };
13
+ type StandardSchemaSessionHandlers<TData, TServerMessage, TClientMessage, TEnv extends object> = {
14
+ createData: (ctx: Context<{
15
+ Bindings: TEnv;
16
+ }>) => TData;
17
+ handleValidatedMessage: (message: TClientMessage) => Promise<void>;
18
+ handleValidationError?: (error: unknown, originalMessage: unknown) => Promise<void>;
19
+ handleClose: (session: StandardSchemaSession<TData, TServerMessage, TClientMessage, TEnv>) => Promise<void>;
20
+ };
21
+ declare class StandardSchemaSession<TData, TServerMessage, TClientMessage, TEnv extends object = Cloudflare.Env> extends BaseSession<TData, TServerMessage, TClientMessage, TEnv> {
22
+ private readonly options;
23
+ private readonly schemaHandlers;
24
+ private readonly clientCodec;
25
+ private readonly serverCodec;
26
+ protected readonly enableBufferMessages: boolean;
27
+ constructor(websocket: WebSocket, sessions: Map<WebSocket, StandardSchemaSession<TData, TServerMessage, TClientMessage, TEnv>>, options: StandardSchemaSessionOptions<TClientMessage, TServerMessage>, schemaHandlers: StandardSchemaSessionHandlers<TData, TServerMessage, TClientMessage, TEnv>);
28
+ handleRawMessage(rawMessage: string): Promise<void>;
29
+ private _internalHandleMessage;
30
+ private _internalHandleBufferMessage;
31
+ private _internalHandleValidationError;
32
+ send(message: TServerMessage): void;
33
+ private sendJsonAsync;
34
+ private sendBufferAsync;
35
+ private sendProtocolError;
36
+ private serializeJson;
37
+ private deserializeJson;
38
+ broadcast(message: TServerMessage, excludeSelf?: boolean): void;
39
+ }
40
+
41
+ export { StandardSchemaSession, type StandardSchemaSessionHandlers, type StandardSchemaSessionOptions };
@@ -0,0 +1,8 @@
1
+ export { StandardSchemaSession } from './chunk-53MFRNQS.js';
2
+ import './chunk-QMGIRIHJ.js';
3
+ import './chunk-3C77OSOD.js';
4
+ import './chunk-KCPOB32E.js';
5
+ import './chunk-CAX4POIL.js';
6
+ import './chunk-NOUFNU2O.js';
7
+ //# sourceMappingURL=StandardSchemaSession.js.map
8
+ //# sourceMappingURL=StandardSchemaSession.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"StandardSchemaSession.js"}
@@ -0,0 +1,45 @@
1
+ import { StandardSchemaV1 } from '@standard-schema/spec';
2
+
3
+ interface StandardSchemaWebSocketClientOptions<TClientMessage, TServerMessage> {
4
+ /**
5
+ * URL to connect to (required if webSocket not provided)
6
+ */
7
+ url?: string;
8
+ /**
9
+ * Existing WebSocket to wrap (alternative to url)
10
+ * Useful when getting a WebSocket from honoDoFetcher
11
+ */
12
+ webSocket?: WebSocket;
13
+ clientSchema: StandardSchemaV1<unknown, TClientMessage>;
14
+ serverSchema: StandardSchemaV1<unknown, TServerMessage>;
15
+ serializeJson?: (value: unknown) => string;
16
+ deserializeJson?: (raw: string) => unknown;
17
+ enableBufferMessages?: boolean;
18
+ onMessage?: (message: TServerMessage) => void;
19
+ onOpen?: (event: Event) => void;
20
+ onClose?: (event: CloseEvent) => void;
21
+ onError?: (event: Event) => void;
22
+ onValidationError?: (error: Error, rawMessage: unknown) => void;
23
+ }
24
+ declare class StandardSchemaWebSocketClient<TClientMessage, TServerMessage> {
25
+ private ws;
26
+ private readonly clientSchema;
27
+ private readonly serverSchema;
28
+ private readonly serializeJson;
29
+ private readonly deserializeJson;
30
+ private readonly enableBufferMessages;
31
+ private readonly onMessageCallback?;
32
+ private readonly onValidationError?;
33
+ constructor(options: StandardSchemaWebSocketClientOptions<TClientMessage, TServerMessage>);
34
+ private handleMessageEvent;
35
+ /**
36
+ * Send a message (automatically encodes based on mode).
37
+ */
38
+ send(message: TClientMessage): Promise<void>;
39
+ close(code?: number, reason?: string): void;
40
+ get readyState(): number;
41
+ get socket(): WebSocket;
42
+ waitForOpen(): Promise<void>;
43
+ }
44
+
45
+ export { StandardSchemaWebSocketClient, type StandardSchemaWebSocketClientOptions };
@@ -0,0 +1,5 @@
1
+ export { StandardSchemaWebSocketClient } from './chunk-3LWVEY3R.js';
2
+ import './chunk-CAX4POIL.js';
3
+ import './chunk-NOUFNU2O.js';
4
+ //# sourceMappingURL=StandardSchemaWebSocketClient.js.map
5
+ //# sourceMappingURL=StandardSchemaWebSocketClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"StandardSchemaWebSocketClient.js"}
@@ -0,0 +1,28 @@
1
+ import { Context } from 'hono';
2
+ import { SessionEnv, SessionClientMessage, SessionServerMessage } from './BaseSession.js';
3
+ import { BaseWebSocketDO } from './BaseWebSocketDO.js';
4
+ import { StandardSchemaSessionOptions, StandardSchemaSession } from './StandardSchemaSession.js';
5
+ import 'hono/hono-base';
6
+ import 'hono/utils/http-status';
7
+ import 'cloudflare:workers';
8
+ import '@firtoz/hono-fetcher/honoDoFetcher';
9
+ import '@standard-schema/spec';
10
+
11
+ type StandardSchemaSessionOptionsOrFactory<TClientMessage, TServerMessage, TEnv extends Cloudflare.Env = Cloudflare.Env> = StandardSchemaSessionOptions<TClientMessage, TServerMessage> | ((ctx: Context<{
12
+ Bindings: TEnv;
13
+ }> | undefined, websocket: WebSocket) => StandardSchemaSessionOptions<TClientMessage, TServerMessage>);
14
+ type StandardSchemaWebSocketDOOptions<TSession extends StandardSchemaSession<any, any, any, any>, TClientMessage, TServerMessage, TEnv extends SessionEnv<TSession>> = {
15
+ standardSchemaSessionOptions: StandardSchemaSessionOptionsOrFactory<TClientMessage, TServerMessage, TEnv>;
16
+ createStandardSchemaSession: (ctx: Context<{
17
+ Bindings: TEnv;
18
+ }> | undefined, websocket: WebSocket, options: StandardSchemaSessionOptions<TClientMessage, TServerMessage>) => TSession | Promise<TSession>;
19
+ };
20
+ declare abstract class StandardSchemaWebSocketDO<TSession extends StandardSchemaSession<any, any, any, any>, TClientMessage extends SessionClientMessage<TSession> = SessionClientMessage<TSession>, TServerMessage extends SessionServerMessage<TSession> = SessionServerMessage<TSession>, TEnv extends SessionEnv<TSession> = SessionEnv<TSession>> extends BaseWebSocketDO<TSession, TEnv> {
21
+ protected readonly standardSchemaSessionOptions: StandardSchemaSessionOptionsOrFactory<TClientMessage, TServerMessage, TEnv>;
22
+ protected readonly createStandardSchemaSessionFn: (ctx: Context<{
23
+ Bindings: TEnv;
24
+ }> | undefined, websocket: WebSocket, options: StandardSchemaSessionOptions<TClientMessage, TServerMessage>) => TSession | Promise<TSession>;
25
+ constructor(ctx: DurableObjectState, env: TEnv, options: StandardSchemaWebSocketDOOptions<TSession, TClientMessage, TServerMessage, TEnv>);
26
+ }
27
+
28
+ export { type StandardSchemaSessionOptionsOrFactory, StandardSchemaWebSocketDO, type StandardSchemaWebSocketDOOptions };
@@ -0,0 +1,5 @@
1
+ export { StandardSchemaWebSocketDO } from './chunk-ULGH6X42.js';
2
+ import './chunk-XFB6C3NZ.js';
3
+ import './chunk-NOUFNU2O.js';
4
+ //# sourceMappingURL=StandardSchemaWebSocketDO.js.map
5
+ //# sourceMappingURL=StandardSchemaWebSocketDO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"StandardSchemaWebSocketDO.js"}
@@ -0,0 +1,9 @@
1
+ declare class WebsocketWrapper<TAttachment, TMessage> {
2
+ webSocket: WebSocket;
3
+ constructor(webSocket: WebSocket);
4
+ send(message: TMessage): void;
5
+ deserializeAttachment(): TAttachment;
6
+ serializeAttachment(attachment: TAttachment): void;
7
+ }
8
+
9
+ export { WebsocketWrapper };
@@ -0,0 +1,4 @@
1
+ export { WebsocketWrapper } from './chunk-KCPOB32E.js';
2
+ import './chunk-NOUFNU2O.js';
3
+ //# sourceMappingURL=WebsocketWrapper.js.map
4
+ //# sourceMappingURL=WebsocketWrapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"WebsocketWrapper.js"}