@signe/room 2.10.0 → 3.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 (84) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/chunk-EUXUH3YW.js +15 -0
  3. package/dist/chunk-EUXUH3YW.js.map +1 -0
  4. package/dist/cloudflare/index.d.ts +71 -0
  5. package/dist/cloudflare/index.js +320 -0
  6. package/dist/cloudflare/index.js.map +1 -0
  7. package/dist/index.d.ts +87 -188
  8. package/dist/index.js +860 -114
  9. package/dist/index.js.map +1 -1
  10. package/dist/node/index.d.ts +164 -0
  11. package/dist/node/index.js +786 -0
  12. package/dist/node/index.js.map +1 -0
  13. package/dist/party-dNs-hqkq.d.ts +175 -0
  14. package/examples/cloudflare/README.md +62 -0
  15. package/examples/cloudflare/node_modules/.bin/tsc +17 -0
  16. package/examples/cloudflare/node_modules/.bin/tsserver +17 -0
  17. package/examples/cloudflare/node_modules/.bin/wrangler +17 -0
  18. package/examples/cloudflare/node_modules/.bin/wrangler2 +17 -0
  19. package/examples/cloudflare/package.json +24 -0
  20. package/examples/cloudflare/public/index.html +443 -0
  21. package/examples/cloudflare/src/index.ts +28 -0
  22. package/examples/cloudflare/src/room.ts +44 -0
  23. package/examples/cloudflare/tsconfig.json +10 -0
  24. package/examples/cloudflare/wrangler.jsonc +25 -0
  25. package/examples/node/README.md +57 -0
  26. package/examples/node/node_modules/.bin/tsc +17 -0
  27. package/examples/node/node_modules/.bin/tsserver +17 -0
  28. package/examples/node/node_modules/.bin/tsx +17 -0
  29. package/examples/node/package.json +23 -0
  30. package/examples/node/public/index.html +443 -0
  31. package/examples/node/room.ts +44 -0
  32. package/examples/node/server.sqlite.ts +52 -0
  33. package/examples/node/server.ts +51 -0
  34. package/examples/node/tsconfig.json +10 -0
  35. package/examples/node-game/README.md +66 -0
  36. package/examples/node-game/package.json +23 -0
  37. package/examples/node-game/public/index.html +705 -0
  38. package/examples/node-game/room.ts +145 -0
  39. package/examples/node-game/server.sqlite.ts +54 -0
  40. package/examples/node-game/server.ts +53 -0
  41. package/examples/node-game/tsconfig.json +10 -0
  42. package/examples/node-shard/README.md +32 -0
  43. package/examples/node-shard/dev.ts +39 -0
  44. package/examples/node-shard/package.json +24 -0
  45. package/examples/node-shard/public/index.html +777 -0
  46. package/examples/node-shard/room-server.ts +68 -0
  47. package/examples/node-shard/room.ts +105 -0
  48. package/examples/node-shard/shared.ts +6 -0
  49. package/examples/node-shard/tsconfig.json +14 -0
  50. package/examples/node-shard/world-server.ts +169 -0
  51. package/package.json +14 -5
  52. package/readme.md +418 -4
  53. package/src/cloudflare/index.ts +474 -0
  54. package/src/index.ts +2 -2
  55. package/src/jwt.ts +1 -5
  56. package/src/mock.ts +29 -7
  57. package/src/node/index.ts +1112 -0
  58. package/src/server.ts +781 -60
  59. package/src/session.guard.ts +6 -2
  60. package/src/shard.ts +91 -23
  61. package/src/storage.ts +29 -5
  62. package/src/testing.ts +4 -3
  63. package/src/types/party.ts +30 -1
  64. package/src/world.guard.ts +23 -4
  65. package/src/world.ts +121 -21
  66. package/tests/storage-restore.spec.ts +122 -0
  67. package/examples/game/.vscode/launch.json +0 -11
  68. package/examples/game/.vscode/settings.json +0 -11
  69. package/examples/game/README.md +0 -40
  70. package/examples/game/app/client.tsx +0 -15
  71. package/examples/game/app/components/Admin.tsx +0 -1089
  72. package/examples/game/app/components/Room.tsx +0 -162
  73. package/examples/game/app/styles.css +0 -31
  74. package/examples/game/package-lock.json +0 -225
  75. package/examples/game/package.json +0 -20
  76. package/examples/game/party/game.room.ts +0 -32
  77. package/examples/game/party/server.ts +0 -10
  78. package/examples/game/party/shard.ts +0 -5
  79. package/examples/game/partykit.json +0 -14
  80. package/examples/game/public/favicon.ico +0 -0
  81. package/examples/game/public/index.html +0 -27
  82. package/examples/game/public/normalize.css +0 -351
  83. package/examples/game/shared/room.schema.ts +0 -14
  84. package/examples/game/tsconfig.json +0 -109
package/dist/index.d.ts CHANGED
@@ -1,176 +1,7 @@
1
- import { Request as Request$2, DurableObjectStorage, WebSocket, DurableObjectState, AnalyticsEngineDataset, VectorizeIndex, R2Bucket, KVNamespace } from '@cloudflare/workers-types';
1
+ import { C as Connection, R as Request$1, a as Room$1, b as ConnectionContext, S as Server$1, c as Storage$1 } from './party-dNs-hqkq.js';
2
2
  import { z } from 'zod';
3
3
  import * as _signe_reactive from '@signe/reactive';
4
-
5
- type AssetFetcher = {
6
- fetch(path: string): Promise<Response | null>;
7
- };
8
- type StandardRequest = globalThis.Request;
9
- interface Request$1 extends Request$2 {
10
- }
11
- type ReturnRequest = StandardRequest | Request$2;
12
- /** Per-party key-value storage */
13
- interface Storage$1 extends DurableObjectStorage {
14
- }
15
- /** Connection metadata only available when the connection is made */
16
- type ConnectionContext = {
17
- request: Request$2;
18
- };
19
- type Stub = {
20
- /** @deprecated Use `await socket()` instead */
21
- connect: () => WebSocket;
22
- socket(pathOrInit?: string | RequestInit): Promise<WebSocket>;
23
- socket(path: string, init?: RequestInit): Promise<WebSocket>;
24
- fetch(pathOrInit?: string | RequestInit | ReturnRequest): Promise<Response>;
25
- fetch(path: string, init?: RequestInit | ReturnRequest): Promise<Response>;
26
- };
27
- /** Additional information about other resources in the current project */
28
- type Context = {
29
- /** Access other parties in this project */
30
- parties: Record<string, {
31
- get(id: string): Stub;
32
- }>;
33
- /**
34
- * A binding to the Cloudflare AI service.
35
- */
36
- ai: AI;
37
- /**
38
- * A binding to the Cloudflare Vectorize service.
39
- */
40
- vectorize: Record<string, VectorizeIndex>;
41
- /**
42
- * A binding to fetch static assets
43
- */
44
- assets: AssetFetcher;
45
- /**
46
- * Custom bindings
47
- */
48
- bindings: CustomBindings;
49
- };
50
- type AI = Record<string, never>;
51
- type ImmutablePrimitive = undefined | null | boolean | string | number;
52
- type Immutable<T> = T extends ImmutablePrimitive ? T : T extends Array<infer U> ? ImmutableArray<U> : T extends Map<infer K, infer V> ? ImmutableMap<K, V> : T extends Set<infer M> ? ImmutableSet<M> : ImmutableObject<T>;
53
- type ImmutableArray<T> = ReadonlyArray<Immutable<T>>;
54
- type ImmutableMap<K, V> = ReadonlyMap<Immutable<K>, Immutable<V>>;
55
- type ImmutableSet<T> = ReadonlySet<Immutable<T>>;
56
- type ImmutableObject<T> = {
57
- readonly [K in keyof T]: Immutable<T[K]>;
58
- };
59
- type ConnectionState<T> = ImmutableObject<T> | null;
60
- type ConnectionSetStateFn<T> = (prevState: ConnectionState<T>) => T;
61
- /** A WebSocket connected to the Room */
62
- type Connection<TState = unknown> = WebSocket & {
63
- /** Connection identifier */
64
- id: string;
65
- /** @deprecated You can access the socket properties directly on the connection*/
66
- socket: WebSocket;
67
- uri: string;
68
- /**
69
- * Arbitrary state associated with this connection.
70
- * Read-only, use Connection.setState to update the state.
71
- */
72
- state: ConnectionState<TState>;
73
- setState(state: TState | ConnectionSetStateFn<TState> | null): ConnectionState<TState>;
74
- /** @deprecated use Connection.setState instead */
75
- serializeAttachment<T = unknown>(attachment: T): void;
76
- /** @deprecated use Connection.state instead */
77
- deserializeAttachment<T = unknown>(): T | null;
78
- };
79
- type CustomBindings = {
80
- r2: Record<string, R2Bucket>;
81
- kv: Record<string, KVNamespace>;
82
- };
83
- /** Room represents a single, self-contained, long-lived session. */
84
- type Room$1 = {
85
- /** Room ID defined in the Party URL, e.g. /parties/:name/:id */
86
- id: string;
87
- /** Internal ID assigned by the platform. Use Party.id instead. */
88
- internalID: string;
89
- /** Party name defined in the Party URL, e.g. /parties/:name/:id */
90
- name: string;
91
- /** Environment variables (--var, partykit.json#vars, or .env) */
92
- env: Record<string, unknown>;
93
- /** A per-room key-value storage */
94
- storage: Storage$1;
95
- /** `blockConcurrencyWhile()` ensures no requests are delivered until */
96
- blockConcurrencyWhile: DurableObjectState["blockConcurrencyWhile"];
97
- /** Additional information about other resources in the current project */
98
- context: Context;
99
- /** @deprecated Use `room.getConnections` instead */
100
- connections: Map<string, Connection>;
101
- /** @deprecated Use `room.context.parties` instead */
102
- parties: Context["parties"];
103
- /** Send a message to all connected clients, except connection ids listed `without` */
104
- broadcast: (msg: string | ArrayBuffer | ArrayBufferView, without?: string[] | undefined) => void;
105
- /** Get a connection by connection id */
106
- getConnection<TState = unknown>(id: string): Connection<TState> | undefined;
107
- /**
108
- * Get all connections. Optionally, you can provide a tag to filter returned connections.
109
- * Use `Party.Server#getConnectionTags` to tag the connection on connect.
110
- */
111
- getConnections<TState = unknown>(tag?: string): Iterable<Connection<TState>>;
112
- /**
113
- * Cloudflare Analytics Engine dataset. Use this to log custom events and metrics.
114
- */
115
- analytics: AnalyticsEngineDataset;
116
- };
117
- type Server$1 = {
118
- /**
119
- * You can define an `options` field to customise the Party.Server behaviour.
120
- */
121
- readonly options?: ServerOptions;
122
- /**
123
- * You can tag a connection to filter them in Party#getConnections.
124
- * Each connection supports up to 9 tags, each tag max length is 256 characters.
125
- */
126
- getConnectionTags?(connection: Connection, context: ConnectionContext): string[] | Promise<string[]>;
127
- /**
128
- * Called when the server is started, before first `onConnect` or `onRequest`.
129
- * Useful for loading data from storage.
130
- *
131
- * You can use this to load data from storage and perform other asynchronous
132
- * initialization, such as retrieving data or configuration from other
133
- * services or databases.
134
- */
135
- onStart?(): void | Promise<void>;
136
- /**
137
- * Called when a new incoming WebSocket connection is opened.
138
- */
139
- onConnect?(connection: Connection, ctx: ConnectionContext): void | Promise<void>;
140
- /**
141
- * Called when a WebSocket connection receives a message from a client, or another connected party.
142
- */
143
- onMessage?(message: string | ArrayBuffer | ArrayBufferView, sender: Connection): void | Promise<void>;
144
- /**
145
- * Called when a WebSocket connection is closed by the client.
146
- */
147
- onClose?(connection: Connection): void | Promise<void>;
148
- /**
149
- * Called when a WebSocket connection is closed due to a connection error.
150
- */
151
- onError?(connection: Connection, error: Error): void | Promise<void>;
152
- /**
153
- * Called when a HTTP request is made to the room URL.
154
- */
155
- onRequest?(req: Request$1): Response | Promise<Response>;
156
- /**
157
- * Called when an alarm is triggered. Use Party.storage.setAlarm to set an alarm.
158
- *
159
- * Alarms have access to most Party resources such as storage, but not Party.id
160
- * and Party.context.parties properties. Attempting to access them will result in a
161
- * runtime error.
162
- */
163
- onAlarm?(): void | Promise<void>;
164
- };
165
- type ServerOptions = {
166
- /**
167
- * Whether the PartyKit platform should remove the server from memory
168
- * between HTTP requests and WebSocket messages.
169
- *
170
- * The default value is `false`.
171
- */
172
- hibernate?: boolean;
173
- };
4
+ import '@cloudflare/workers-types';
174
5
 
175
6
  type GuardFn = (sender: Connection, value: any | Request$1, room: Room$1) => boolean | Promise<boolean | Response>;
176
7
  type RoomGuardFn = (conn: Connection, ctx: ConnectionContext, room: Room$1) => boolean | Promise<boolean | Response>;
@@ -211,6 +42,28 @@ declare function RoomGuard(guards: RoomGuardFn[]): (target: any) => void;
211
42
  */
212
43
  declare function Guard(guards: GuardFn[]): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void;
213
44
 
45
+ type StorageRestoreContext<TSnapshot = any> = {
46
+ snapshot: TSnapshot;
47
+ room: Room$1;
48
+ server: Server;
49
+ legacy: boolean;
50
+ };
51
+ type UserStorageRestoreContext<TUser = any, TSnapshot = any> = {
52
+ userSnapshot: TSnapshot;
53
+ user: TUser | undefined;
54
+ publicId: string;
55
+ usersPropName: string;
56
+ room: Room$1;
57
+ server: Server;
58
+ legacy: boolean;
59
+ };
60
+ type SessionData = {
61
+ publicId: string;
62
+ state?: any;
63
+ created?: number;
64
+ connected?: boolean;
65
+ disconnectedAt?: number;
66
+ };
214
67
  /**
215
68
  * @class Server
216
69
  * @implements {Party.Server}
@@ -260,6 +113,26 @@ declare class Server implements Server$1 {
260
113
  */
261
114
  get isHibernate(): boolean;
262
115
  get roomStorage(): Storage$1;
116
+ private stateKey;
117
+ private sessionKey;
118
+ private sessionPublicKey;
119
+ private transferKey;
120
+ private isInternalStorageKey;
121
+ private listStorage;
122
+ private loadStatePath;
123
+ private saveStatePath;
124
+ private putStorageEntries;
125
+ private deleteStorageKeys;
126
+ private deleteStatePath;
127
+ private containsDeleteToken;
128
+ private compactStateStorage;
129
+ private createUserFromClassType;
130
+ private restoreUsersStorageSnapshot;
131
+ private restoreStorageSnapshot;
132
+ private createStorageMetrics;
133
+ private getTransferExpiryTime;
134
+ private getPrivateId;
135
+ private hasActiveSessionConnection;
263
136
  send(conn: Connection, obj: any, subRoom: any): Promise<void>;
264
137
  broadcast(obj: any, subRoom: any): void;
265
138
  /**
@@ -279,6 +152,14 @@ declare class Server implements Server$1 {
279
152
  onStart(): Promise<void>;
280
153
  runGarbageCollector(): Promise<void>;
281
154
  private garbageCollector;
155
+ private scheduleSessionGarbageCollector;
156
+ private getSessionExpiryTime;
157
+ private shouldRunSessionGarbageCollector;
158
+ private shouldRunInterval;
159
+ private repairSessionPublicIndexes;
160
+ private isTransferExpired;
161
+ private cleanupExpiredTransfers;
162
+ private expireDisconnectedSession;
282
163
  /**
283
164
  * @method createRoom
284
165
  * @private
@@ -359,12 +240,12 @@ declare class Server implements Server$1 {
359
240
  * console.log(session);
360
241
  * ```
361
242
  */
362
- getSession(privateId: string): Promise<{
363
- publicId: string;
364
- state?: any;
365
- created?: number;
366
- connected?: boolean;
367
- } | null>;
243
+ getSession(privateId: string): Promise<SessionData | null>;
244
+ private getSessionPrivateIds;
245
+ private saveSessionPrivateIds;
246
+ private addSessionToPublicIndex;
247
+ private removeSessionFromPublicIndex;
248
+ private getSessionEntryByPublicId;
368
249
  private saveSession;
369
250
  private updateSessionConnection;
370
251
  /**
@@ -397,6 +278,7 @@ declare class Server implements Server$1 {
397
278
  * ```
398
279
  */
399
280
  onConnect(conn: Connection, ctx: ConnectionContext): Promise<void>;
281
+ private isAuthorizedShardRequest;
400
282
  /**
401
283
  * @method onConnectShard
402
284
  * @private
@@ -551,10 +433,12 @@ declare class Server implements Server$1 {
551
433
 
552
434
  declare class Storage {
553
435
  private memory;
554
- put(key: any, value: any): Promise<void>;
436
+ put(key: any, value?: any): Promise<void>;
555
437
  get(key: any): Promise<any>;
556
- delete(key: any): Promise<void>;
557
- list(): Promise<Map<any, any>>;
438
+ delete(key: any): Promise<number | boolean>;
439
+ list(options?: {
440
+ prefix?: string;
441
+ }): Promise<Map<any, any>>;
558
442
  }
559
443
 
560
444
  declare class MockPartyClient {
@@ -562,7 +446,7 @@ declare class MockPartyClient {
562
446
  private events;
563
447
  id: string;
564
448
  conn: MockConnection;
565
- constructor(server: Server, id?: string);
449
+ constructor(server: Server, sessionId?: string);
566
450
  addEventListener(event: any, cb: any): void;
567
451
  removeEventListener(event: any, cb: any): void;
568
452
  _trigger(event: any, data: any): void;
@@ -591,15 +475,17 @@ declare class MockPartyRoom {
591
475
  headers?: Record<string, string>;
592
476
  }): Promise<MockPartyClient>;
593
477
  broadcast(data: any): void;
594
- getConnection(id: string): MockPartyClient;
478
+ getConnection(id: string): MockConnection;
595
479
  getConnections(): MockConnection[];
596
480
  clear(): void;
481
+ deleteConnection(id: string, connection?: MockConnection): void;
597
482
  }
598
483
  declare class MockConnection {
599
484
  client: MockPartyClient;
600
485
  server: Server;
601
486
  id: string;
602
- constructor(client: MockPartyClient);
487
+ sessionId: string;
488
+ constructor(client: MockPartyClient, sessionId: string);
603
489
  state: any;
604
490
  setState(value: any): void;
605
491
  send(data: any): void;
@@ -621,21 +507,25 @@ interface ShardOptions {
621
507
  declare class Shard {
622
508
  private room;
623
509
  ws: PartyWebSocket;
624
- connectionMap: Map<string, Connection<unknown>>;
510
+ connectionMap: Map<string, Set<Connection<unknown>>>;
625
511
  mainServerStub: any;
626
512
  worldUrl: string | null;
627
513
  worldId: string;
628
514
  lastReportedConnections: number;
629
515
  statsInterval: number;
630
516
  statsIntervalId: any;
631
- constructor(room: Room$1);
517
+ constructor(room: Room$1, options?: ShardOptions);
518
+ private getPrivateId;
519
+ private getEnvString;
520
+ private getRoomIdFromShardId;
521
+ private getWorldIdFromShardId;
632
522
  onStart(): Promise<void>;
633
523
  private startPeriodicStatsUpdates;
634
524
  private stopPeriodicStatsUpdates;
635
525
  onConnect(conn: Connection, ctx: ConnectionContext): void;
636
526
  onMessage(message: string | ArrayBuffer | ArrayBufferView, sender: Connection): void;
637
527
  onClose(conn: Connection): void;
638
- updateWorldStats(): Promise<boolean>;
528
+ updateWorldStats(force?: boolean): Promise<boolean>;
639
529
  /**
640
530
  * @method onRequest
641
531
  * @async
@@ -680,6 +570,7 @@ declare class Shard {
680
570
  declare function testRoom(Room: any, options?: {
681
571
  hibernate?: boolean;
682
572
  shard?: boolean;
573
+ id?: string;
683
574
  env?: Record<string, string>;
684
575
  parties?: Record<string, (io: any) => any>;
685
576
  partyFn?: (io: any) => any;
@@ -849,6 +740,7 @@ declare class RoomConfig {
849
740
  declare class ShardInfo {
850
741
  id: string;
851
742
  roomId: _signe_reactive.WritableSignal<string>;
743
+ worldId: _signe_reactive.WritableSignal<string>;
852
744
  url: _signe_reactive.WritableSignal<string>;
853
745
  currentConnections: _signe_reactive.WritableSignal<number>;
854
746
  maxConnections: _signe_reactive.WritableSignal<number>;
@@ -865,13 +757,20 @@ declare class WorldRoom implements RoomInterceptorPacket, RoomOnJoin {
865
757
  constructor(room: Room$1);
866
758
  onJoin(user: any, conn: Connection, ctx: ConnectionContext): Promise<void>;
867
759
  interceptorPacket(_: any, obj: any, conn: Connection): any;
760
+ private getWorldId;
761
+ private scheduleInactiveShardCleanup;
868
762
  private cleanupInactiveShards;
869
- registerRoom(req: Request$1): Promise<void>;
763
+ private removeShard;
764
+ private shouldCompleteDrain;
765
+ registerRoom(req: Request$1, res?: ServerResponse): Promise<Response>;
870
766
  updateShardStats(req: Request$1, res: ServerResponse): Promise<Response>;
871
767
  scaleRoom(req: Request$1, res: ServerResponse): Promise<Response>;
872
768
  connect(req: Request$1, res: ServerResponse): Promise<Response>;
873
769
  private findOptimalShard;
770
+ private getAvailableShards;
771
+ private canCreateShard;
874
772
  private createShard;
773
+ private ensureMinShards;
875
774
  }
876
775
 
877
776
  /**
@@ -927,4 +826,4 @@ declare function createRequireSessionGuard(storage: Storage$1): (sender: Connect
927
826
  */
928
827
  declare const requireSession: (sender: Connection, value: any, room: Room$1) => Promise<boolean>;
929
828
 
930
- export { Action, ClientIo, Guard, MockConnection, Request, type RequestOptions, Room, RoomGuard, type RoomInterceptorPacket, type RoomMethods, type RoomOnJoin, type RoomOnLeave, type RoomOptions, Server, ServerIo, ServerResponse, Shard, type ShardOptions, UnhandledAction, WorldRoom, createRequireSessionGuard, request, requireSession, testRoom, tick };
829
+ export { Action, ClientIo, Guard, MockConnection, Request, type RequestOptions, Room, RoomGuard, type RoomInterceptorPacket, type RoomMethods, type RoomOnJoin, type RoomOnLeave, type RoomOptions, Server, ServerIo, ServerResponse, Shard, type ShardOptions, type StorageRestoreContext, UnhandledAction, type UserStorageRestoreContext, WorldRoom, createRequireSessionGuard, request, requireSession, testRoom, tick };