@signe/room 1.4.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +258 -22
- package/dist/index.js +1447 -60
- package/dist/index.js.map +1 -1
- package/examples/game/app/client.tsx +2 -2
- package/examples/game/app/components/Admin.tsx +1089 -0
- package/examples/game/app/components/Room.tsx +158 -0
- package/examples/game/party/server.ts +3 -2
- package/examples/game/party/shard.ts +5 -0
- package/examples/game/partykit.json +5 -1
- package/package.json +2 -2
- package/readme.md +226 -2
- package/src/decorators.ts +34 -2
- package/src/index.ts +4 -1
- package/src/interfaces.ts +13 -0
- package/src/jwt.ts +217 -0
- package/src/mock.ts +39 -3
- package/src/server.ts +595 -79
- package/src/shard.ts +244 -0
- package/src/testing.ts +47 -6
- package/src/utils.ts +7 -0
- package/src/world.guard.ts +28 -0
- package/src/world.ts +448 -0
- package/examples/game/app/components/Counter.tsx +0 -82
package/dist/index.d.ts
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
import { Request as Request$
|
|
1
|
+
import { Request as Request$2, DurableObjectStorage, WebSocket, DurableObjectState, AnalyticsEngineDataset, VectorizeIndex, R2Bucket, KVNamespace } from '@cloudflare/workers-types';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
+
import * as _signe_reactive from '@signe/reactive';
|
|
3
4
|
|
|
4
5
|
type AssetFetcher = {
|
|
5
6
|
fetch(path: string): Promise<Response | null>;
|
|
6
7
|
};
|
|
7
8
|
type StandardRequest = globalThis.Request;
|
|
8
|
-
interface Request extends Request$
|
|
9
|
+
interface Request$1 extends Request$2 {
|
|
9
10
|
}
|
|
10
|
-
type ReturnRequest = StandardRequest | Request$
|
|
11
|
+
type ReturnRequest = StandardRequest | Request$2;
|
|
11
12
|
/** Per-party key-value storage */
|
|
12
13
|
interface Storage$1 extends DurableObjectStorage {
|
|
13
14
|
}
|
|
14
15
|
/** Connection metadata only available when the connection is made */
|
|
15
16
|
type ConnectionContext = {
|
|
16
|
-
request: Request$
|
|
17
|
+
request: Request$2;
|
|
17
18
|
};
|
|
18
19
|
type Stub = {
|
|
19
20
|
/** @deprecated Use `await socket()` instead */
|
|
@@ -151,7 +152,7 @@ type Server$1 = {
|
|
|
151
152
|
/**
|
|
152
153
|
* Called when a HTTP request is made to the room URL.
|
|
153
154
|
*/
|
|
154
|
-
onRequest?(req: Request): Response | Promise<Response>;
|
|
155
|
+
onRequest?(req: Request$1): Response | Promise<Response>;
|
|
155
156
|
/**
|
|
156
157
|
* Called when an alarm is triggered. Use Party.storage.setAlarm to set an alarm.
|
|
157
158
|
*
|
|
@@ -171,9 +172,19 @@ type ServerOptions = {
|
|
|
171
172
|
hibernate?: boolean;
|
|
172
173
|
};
|
|
173
174
|
|
|
174
|
-
type GuardFn = (sender: Connection, value: any) => boolean | Promise<boolean>;
|
|
175
|
-
type RoomGuardFn = (conn: Connection, ctx: ConnectionContext) => boolean | Promise<boolean>;
|
|
175
|
+
type GuardFn = (sender: Connection, value: any | Request$1, room: Room$1) => boolean | Promise<boolean | Response>;
|
|
176
|
+
type RoomGuardFn = (conn: Connection, ctx: ConnectionContext, room: Room$1) => boolean | Promise<boolean | Response>;
|
|
176
177
|
declare function Action(name: string, bodyValidation?: z.ZodSchema): (target: any, propertyKey: string) => void;
|
|
178
|
+
/**
|
|
179
|
+
* Request decorator for handling HTTP requests with path and method routing
|
|
180
|
+
* @param options Configuration for the HTTP request handler
|
|
181
|
+
* @param bodyValidation Optional Zod schema for request body validation
|
|
182
|
+
*/
|
|
183
|
+
interface RequestOptions {
|
|
184
|
+
path: string;
|
|
185
|
+
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS' | 'HEAD';
|
|
186
|
+
}
|
|
187
|
+
declare function Request(options: RequestOptions, bodyValidation?: z.ZodSchema): (target: any, propertyKey: string) => void;
|
|
177
188
|
interface RoomOptions {
|
|
178
189
|
path: string;
|
|
179
190
|
maxUsers?: number;
|
|
@@ -244,6 +255,8 @@ declare class Server implements Server$1 {
|
|
|
244
255
|
*/
|
|
245
256
|
get isHibernate(): boolean;
|
|
246
257
|
get roomStorage(): Storage$1;
|
|
258
|
+
send(conn: Connection, obj: any, subRoom: any): Promise<void>;
|
|
259
|
+
broadcast(obj: any, subRoom: any): void;
|
|
247
260
|
/**
|
|
248
261
|
* @method onStart
|
|
249
262
|
* @async
|
|
@@ -315,6 +328,7 @@ declare class Server implements Server$1 {
|
|
|
315
328
|
private saveSession;
|
|
316
329
|
private updateSessionConnection;
|
|
317
330
|
private deleteSession;
|
|
331
|
+
onConnectClient(conn: Connection, ctx: ConnectionContext): Promise<void>;
|
|
318
332
|
/**
|
|
319
333
|
* @method onConnect
|
|
320
334
|
* @async
|
|
@@ -332,23 +346,64 @@ declare class Server implements Server$1 {
|
|
|
332
346
|
* ```
|
|
333
347
|
*/
|
|
334
348
|
onConnect(conn: Connection, ctx: ConnectionContext): Promise<void>;
|
|
349
|
+
/**
|
|
350
|
+
* @method onConnectShard
|
|
351
|
+
* @private
|
|
352
|
+
* @param {Party.Connection} conn - The connection object for the new shard.
|
|
353
|
+
* @param {Party.ConnectionContext} ctx - The context of the shard connection.
|
|
354
|
+
* @description Handles a new shard connection, setting up the necessary state.
|
|
355
|
+
* @returns {void}
|
|
356
|
+
*/
|
|
357
|
+
onConnectShard(conn: Connection, ctx: ConnectionContext): void;
|
|
335
358
|
/**
|
|
336
359
|
* @method onMessage
|
|
337
360
|
* @async
|
|
338
|
-
* @param {string} message - The message received from a user.
|
|
361
|
+
* @param {string} message - The message received from a user or shard.
|
|
339
362
|
* @param {Party.Connection} sender - The connection object of the sender.
|
|
340
|
-
* @description Processes incoming messages
|
|
363
|
+
* @description Processes incoming messages, handling differently based on if sender is shard or client.
|
|
341
364
|
* @returns {Promise<void>}
|
|
342
|
-
*
|
|
343
|
-
* @example
|
|
344
|
-
* ```typescript
|
|
345
|
-
* server.onMessage = async (message, sender) => {
|
|
346
|
-
* await server.onMessage(message, sender);
|
|
347
|
-
* console.log("Message processed from:", sender.id);
|
|
348
|
-
* };
|
|
349
|
-
* ```
|
|
350
365
|
*/
|
|
351
366
|
onMessage(message: string, sender: Connection): Promise<void>;
|
|
367
|
+
/**
|
|
368
|
+
* @method handleShardMessage
|
|
369
|
+
* @private
|
|
370
|
+
* @async
|
|
371
|
+
* @param {string} message - The message received from a shard.
|
|
372
|
+
* @param {Party.Connection} shardConnection - The connection object of the shard.
|
|
373
|
+
* @description Processes messages from shards, extracting client information.
|
|
374
|
+
* @returns {Promise<void>}
|
|
375
|
+
*/
|
|
376
|
+
private handleShardMessage;
|
|
377
|
+
/**
|
|
378
|
+
* @method handleShardClientConnect
|
|
379
|
+
* @private
|
|
380
|
+
* @async
|
|
381
|
+
* @param {Object} message - The client connection message from a shard.
|
|
382
|
+
* @param {Party.Connection} shardConnection - The connection object of the shard.
|
|
383
|
+
* @description Handles a new client connection via a shard.
|
|
384
|
+
* @returns {Promise<void>}
|
|
385
|
+
*/
|
|
386
|
+
private handleShardClientConnect;
|
|
387
|
+
/**
|
|
388
|
+
* @method handleShardClientMessage
|
|
389
|
+
* @private
|
|
390
|
+
* @async
|
|
391
|
+
* @param {Object} message - The client message from a shard.
|
|
392
|
+
* @param {Party.Connection} shardConnection - The connection object of the shard.
|
|
393
|
+
* @description Handles a message from a client via a shard.
|
|
394
|
+
* @returns {Promise<void>}
|
|
395
|
+
*/
|
|
396
|
+
private handleShardClientMessage;
|
|
397
|
+
/**
|
|
398
|
+
* @method handleShardClientDisconnect
|
|
399
|
+
* @private
|
|
400
|
+
* @async
|
|
401
|
+
* @param {Object} message - The client disconnection message from a shard.
|
|
402
|
+
* @param {Party.Connection} shardConnection - The connection object of the shard.
|
|
403
|
+
* @description Handles a client disconnection via a shard.
|
|
404
|
+
* @returns {Promise<void>}
|
|
405
|
+
*/
|
|
406
|
+
private handleShardClientDisconnect;
|
|
352
407
|
/**
|
|
353
408
|
* @method onClose
|
|
354
409
|
* @async
|
|
@@ -367,7 +422,70 @@ declare class Server implements Server$1 {
|
|
|
367
422
|
onClose(conn: Connection): Promise<void>;
|
|
368
423
|
onAlarm(): Promise<void>;
|
|
369
424
|
onError(connection: Connection, error: Error): Promise<void>;
|
|
370
|
-
|
|
425
|
+
/**
|
|
426
|
+
* @method onRequest
|
|
427
|
+
* @async
|
|
428
|
+
* @param {Party.Request} req - The HTTP request to handle
|
|
429
|
+
* @description Handles HTTP requests, either directly from clients or forwarded by shards
|
|
430
|
+
* @returns {Promise<Response>} The response to return to the client
|
|
431
|
+
*/
|
|
432
|
+
onRequest(req: Request$1): Promise<Response>;
|
|
433
|
+
/**
|
|
434
|
+
* @method handleDirectRequest
|
|
435
|
+
* @private
|
|
436
|
+
* @async
|
|
437
|
+
* @param {Party.Request} req - The HTTP request received directly from a client
|
|
438
|
+
* @description Processes requests received directly from clients
|
|
439
|
+
* @returns {Promise<Response>} The response to return to the client
|
|
440
|
+
*/
|
|
441
|
+
private handleDirectRequest;
|
|
442
|
+
/**
|
|
443
|
+
* @method tryMatchRequestHandler
|
|
444
|
+
* @private
|
|
445
|
+
* @async
|
|
446
|
+
* @param {Party.Request} req - The HTTP request to handle
|
|
447
|
+
* @param {Object} subRoom - The room instance
|
|
448
|
+
* @description Attempts to match the request to a registered @Request handler
|
|
449
|
+
* @returns {Promise<Response | null>} The response or null if no handler matched
|
|
450
|
+
*/
|
|
451
|
+
private tryMatchRequestHandler;
|
|
452
|
+
/**
|
|
453
|
+
* @method pathMatches
|
|
454
|
+
* @private
|
|
455
|
+
* @param {string} requestPath - The path from the request
|
|
456
|
+
* @param {string} handlerPath - The path pattern from the handler
|
|
457
|
+
* @description Checks if a request path matches a handler path pattern
|
|
458
|
+
* @returns {boolean} True if the paths match
|
|
459
|
+
*/
|
|
460
|
+
private pathMatches;
|
|
461
|
+
/**
|
|
462
|
+
* @method extractPathParams
|
|
463
|
+
* @private
|
|
464
|
+
* @param {string} requestPath - The path from the request
|
|
465
|
+
* @param {string} handlerPath - The path pattern from the handler
|
|
466
|
+
* @description Extracts path parameters from the request path based on the handler pattern
|
|
467
|
+
* @returns {Object} An object containing the path parameters
|
|
468
|
+
*/
|
|
469
|
+
private extractPathParams;
|
|
470
|
+
/**
|
|
471
|
+
* @method handleShardRequest
|
|
472
|
+
* @private
|
|
473
|
+
* @async
|
|
474
|
+
* @param {Party.Request} req - The HTTP request forwarded by a shard
|
|
475
|
+
* @param {string | null} shardId - The ID of the shard that forwarded the request
|
|
476
|
+
* @description Processes requests forwarded by shards, preserving client context
|
|
477
|
+
* @returns {Promise<Response>} The response to return to the shard (which will forward it to the client)
|
|
478
|
+
*/
|
|
479
|
+
private handleShardRequest;
|
|
480
|
+
/**
|
|
481
|
+
* @method createEnhancedRequest
|
|
482
|
+
* @private
|
|
483
|
+
* @param {Party.Request} originalReq - The original request received from the shard
|
|
484
|
+
* @param {string | null} originalClientIp - The original client IP, if available
|
|
485
|
+
* @description Creates an enhanced request object that preserves the original client context
|
|
486
|
+
* @returns {Party.Request} The enhanced request object
|
|
487
|
+
*/
|
|
488
|
+
private createEnhancedRequest;
|
|
371
489
|
}
|
|
372
490
|
|
|
373
491
|
declare class Storage {
|
|
@@ -389,16 +507,24 @@ declare class MockPartyClient {
|
|
|
389
507
|
_trigger(event: any, data: any): void;
|
|
390
508
|
send(data: any): Promise<void>;
|
|
391
509
|
}
|
|
510
|
+
declare class MockContext {
|
|
511
|
+
room: MockPartyRoom;
|
|
512
|
+
parties: {
|
|
513
|
+
main: Map<string, any>;
|
|
514
|
+
};
|
|
515
|
+
constructor(room: MockPartyRoom, options?: any);
|
|
516
|
+
}
|
|
392
517
|
declare class MockPartyRoom {
|
|
393
518
|
id?: string;
|
|
394
519
|
clients: Map<string, MockPartyClient>;
|
|
395
520
|
storage: Storage;
|
|
521
|
+
context: MockContext;
|
|
396
522
|
env: {};
|
|
397
|
-
constructor(id?: string);
|
|
523
|
+
constructor(id?: string, options?: any);
|
|
398
524
|
connection(server: Server): Promise<MockPartyClient>;
|
|
399
525
|
broadcast(data: any): void;
|
|
400
526
|
getConnection(id: string): MockPartyClient;
|
|
401
|
-
getConnections():
|
|
527
|
+
getConnections(): MockConnection[];
|
|
402
528
|
clear(): void;
|
|
403
529
|
}
|
|
404
530
|
declare class MockConnection {
|
|
@@ -414,6 +540,50 @@ declare class MockConnection {
|
|
|
414
540
|
declare const ServerIo: typeof MockPartyRoom;
|
|
415
541
|
declare const ClientIo: typeof MockPartyClient;
|
|
416
542
|
|
|
543
|
+
interface PartyWebSocket {
|
|
544
|
+
send: (data: string | ArrayBufferLike | Blob | ArrayBufferView) => void;
|
|
545
|
+
addEventListener: (type: string, listener: (event: any) => void) => void;
|
|
546
|
+
close: () => void;
|
|
547
|
+
}
|
|
548
|
+
interface ShardOptions {
|
|
549
|
+
worldUrl?: string;
|
|
550
|
+
worldId?: string;
|
|
551
|
+
statsInterval?: number;
|
|
552
|
+
}
|
|
553
|
+
declare class Shard {
|
|
554
|
+
private room;
|
|
555
|
+
ws: PartyWebSocket;
|
|
556
|
+
connectionMap: Map<string, Connection<unknown>>;
|
|
557
|
+
mainServerStub: any;
|
|
558
|
+
worldUrl: string | null;
|
|
559
|
+
worldId: string;
|
|
560
|
+
lastReportedConnections: number;
|
|
561
|
+
statsInterval: number;
|
|
562
|
+
statsIntervalId: any;
|
|
563
|
+
constructor(room: Room$1);
|
|
564
|
+
onStart(): Promise<void>;
|
|
565
|
+
private startPeriodicStatsUpdates;
|
|
566
|
+
private stopPeriodicStatsUpdates;
|
|
567
|
+
onConnect(conn: Connection, ctx: ConnectionContext): void;
|
|
568
|
+
onMessage(message: string | ArrayBuffer | ArrayBufferView, sender: Connection): void;
|
|
569
|
+
onClose(conn: Connection): void;
|
|
570
|
+
updateWorldStats(): Promise<boolean>;
|
|
571
|
+
/**
|
|
572
|
+
* @method onRequest
|
|
573
|
+
* @async
|
|
574
|
+
* @param {Party.Request} req - The HTTP request to handle
|
|
575
|
+
* @description Forwards HTTP requests to the main server, preserving client context
|
|
576
|
+
* @returns {Promise<Response>} The response from the main server
|
|
577
|
+
*/
|
|
578
|
+
onRequest(req: Request$1): Promise<Response>;
|
|
579
|
+
/**
|
|
580
|
+
* @method onAlarm
|
|
581
|
+
* @async
|
|
582
|
+
* @description Executed periodically, used to perform maintenance tasks
|
|
583
|
+
*/
|
|
584
|
+
onAlarm(): Promise<void>;
|
|
585
|
+
}
|
|
586
|
+
|
|
417
587
|
/**
|
|
418
588
|
* @description Test the room with a mock server and client
|
|
419
589
|
* @param Room - The room class to test
|
|
@@ -441,10 +611,76 @@ declare const ClientIo: typeof MockPartyClient;
|
|
|
441
611
|
*/
|
|
442
612
|
declare function testRoom(Room: any, options?: {
|
|
443
613
|
hibernate?: boolean;
|
|
614
|
+
shard?: boolean;
|
|
615
|
+
env?: Record<string, string>;
|
|
444
616
|
}): Promise<{
|
|
445
|
-
server: Server;
|
|
617
|
+
server: Server | Shard;
|
|
446
618
|
room: any;
|
|
447
619
|
createClient: () => Promise<MockPartyClient>;
|
|
448
620
|
}>;
|
|
621
|
+
declare function request(room: Server, path: string, options?: {
|
|
622
|
+
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
623
|
+
body?: any;
|
|
624
|
+
headers?: Record<string, string>;
|
|
625
|
+
}): Promise<Response>;
|
|
626
|
+
|
|
627
|
+
interface RoomInterceptorPacket {
|
|
628
|
+
interceptorPacket(user: any, obj: any, conn: Connection): Promise<any> | null | any;
|
|
629
|
+
}
|
|
630
|
+
interface RoomOnJoin {
|
|
631
|
+
onJoin(user: any, conn: Connection, ctx: ConnectionContext): Promise<any> | null | any;
|
|
632
|
+
}
|
|
633
|
+
interface RoomOnLeave {
|
|
634
|
+
onLeave(user: any, conn: Connection, ctx: ConnectionContext): Promise<any> | null | any;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
type BalancingStrategy = 'round-robin' | 'least-connections' | 'random';
|
|
638
|
+
type ShardStatus = 'active' | 'maintenance' | 'draining';
|
|
639
|
+
declare class RoomConfig {
|
|
640
|
+
id: string;
|
|
641
|
+
name: _signe_reactive.WritableSignal<string>;
|
|
642
|
+
balancingStrategy: _signe_reactive.WritableSignal<BalancingStrategy>;
|
|
643
|
+
public: _signe_reactive.WritableSignal<boolean>;
|
|
644
|
+
maxPlayersPerShard: _signe_reactive.WritableSignal<number>;
|
|
645
|
+
minShards: _signe_reactive.WritableSignal<number>;
|
|
646
|
+
maxShards: _signe_reactive.WritableSignal<number>;
|
|
647
|
+
}
|
|
648
|
+
declare class ShardInfo {
|
|
649
|
+
id: string;
|
|
650
|
+
roomId: _signe_reactive.WritableSignal<string>;
|
|
651
|
+
url: _signe_reactive.WritableSignal<string>;
|
|
652
|
+
currentConnections: _signe_reactive.WritableSignal<number>;
|
|
653
|
+
maxConnections: _signe_reactive.WritableSignal<number>;
|
|
654
|
+
status: _signe_reactive.WritableSignal<ShardStatus>;
|
|
655
|
+
lastHeartbeat: _signe_reactive.WritableSignal<number>;
|
|
656
|
+
}
|
|
657
|
+
declare class WorldRoom implements RoomInterceptorPacket, RoomOnJoin {
|
|
658
|
+
private room;
|
|
659
|
+
rooms: _signe_reactive.WritableObjectSignal<Record<string, RoomConfig>>;
|
|
660
|
+
shards: _signe_reactive.WritableObjectSignal<Record<string, ShardInfo>>;
|
|
661
|
+
rrCounters: _signe_reactive.WritableObjectSignal<Record<string, number>>;
|
|
662
|
+
defaultShardUrlTemplate: _signe_reactive.WritableSignal<string>;
|
|
663
|
+
defaultMaxConnectionsPerShard: _signe_reactive.WritableSignal<number>;
|
|
664
|
+
constructor(room: Room$1);
|
|
665
|
+
onJoin(user: any, conn: Connection, ctx: ConnectionContext): Promise<void>;
|
|
666
|
+
interceptorPacket(_: any, obj: any, conn: Connection): any;
|
|
667
|
+
private cleanupInactiveShards;
|
|
668
|
+
registerRoom(req: Request$1): Promise<void>;
|
|
669
|
+
updateShardStats(req: Request$1): Promise<{
|
|
670
|
+
error: string;
|
|
671
|
+
}>;
|
|
672
|
+
scaleRoom(req: Request$1): Promise<{
|
|
673
|
+
error: string;
|
|
674
|
+
roomId?: undefined;
|
|
675
|
+
currentShardCount?: undefined;
|
|
676
|
+
} | {
|
|
677
|
+
error: string;
|
|
678
|
+
roomId: string;
|
|
679
|
+
currentShardCount: number;
|
|
680
|
+
}>;
|
|
681
|
+
connect(req: Request$1): Promise<Response>;
|
|
682
|
+
private findOptimalShard;
|
|
683
|
+
private createShard;
|
|
684
|
+
}
|
|
449
685
|
|
|
450
|
-
export { Action, ClientIo, Guard, MockConnection, Room, RoomGuard, type RoomOptions, Server, ServerIo, testRoom };
|
|
686
|
+
export { Action, ClientIo, Guard, MockConnection, Request, type RequestOptions, Room, RoomGuard, type RoomInterceptorPacket, type RoomOnJoin, type RoomOnLeave, type RoomOptions, Server, ServerIo, Shard, type ShardOptions, WorldRoom, request, testRoom };
|