@signe/room 2.9.0 → 2.9.2
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/CHANGELOG.md +9 -0
- package/LICENSE +21 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +537 -678
- package/dist/index.js.map +1 -1
- package/package.json +10 -4
- package/readme.md +7 -6
- package/src/jwt.ts +1 -5
- package/src/server.ts +40 -27
- package/src/world.ts +28 -19
package/dist/index.js
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
|
-
var
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result) __defProp(target, key, result);
|
|
9
|
+
return result;
|
|
10
|
+
};
|
|
3
11
|
|
|
4
12
|
// src/decorators.ts
|
|
5
13
|
function Action(name, bodyValidation) {
|
|
@@ -13,7 +21,6 @@ function Action(name, bodyValidation) {
|
|
|
13
21
|
});
|
|
14
22
|
};
|
|
15
23
|
}
|
|
16
|
-
__name(Action, "Action");
|
|
17
24
|
function UnhandledAction() {
|
|
18
25
|
return function(target, propertyKey) {
|
|
19
26
|
target.constructor._unhandledActionMetadata = {
|
|
@@ -21,7 +28,6 @@ function UnhandledAction() {
|
|
|
21
28
|
};
|
|
22
29
|
};
|
|
23
30
|
}
|
|
24
|
-
__name(UnhandledAction, "UnhandledAction");
|
|
25
31
|
function Request2(options, bodyValidation) {
|
|
26
32
|
return function(target, propertyKey) {
|
|
27
33
|
if (!target.constructor._requestMetadata) {
|
|
@@ -38,7 +44,6 @@ function Request2(options, bodyValidation) {
|
|
|
38
44
|
});
|
|
39
45
|
};
|
|
40
46
|
}
|
|
41
|
-
__name(Request2, "Request");
|
|
42
47
|
function Room(options) {
|
|
43
48
|
return function(target) {
|
|
44
49
|
target.path = options.path;
|
|
@@ -51,46 +56,40 @@ function Room(options) {
|
|
|
51
56
|
}
|
|
52
57
|
};
|
|
53
58
|
}
|
|
54
|
-
__name(Room, "Room");
|
|
55
59
|
function RoomGuard(guards) {
|
|
56
60
|
return function(target) {
|
|
57
61
|
target["_roomGuards"] = guards;
|
|
58
62
|
};
|
|
59
63
|
}
|
|
60
|
-
__name(RoomGuard, "RoomGuard");
|
|
61
64
|
function Guard(guards) {
|
|
62
65
|
return function(target, propertyKey, descriptor) {
|
|
63
66
|
if (!target.constructor["_actionGuards"]) {
|
|
64
67
|
target.constructor["_actionGuards"] = /* @__PURE__ */ new Map();
|
|
65
68
|
}
|
|
66
69
|
if (!Array.isArray(guards)) {
|
|
67
|
-
guards = [
|
|
68
|
-
guards
|
|
69
|
-
];
|
|
70
|
+
guards = [guards];
|
|
70
71
|
}
|
|
71
72
|
target.constructor["_actionGuards"].set(propertyKey, guards);
|
|
72
73
|
};
|
|
73
74
|
}
|
|
74
|
-
__name(Guard, "Guard");
|
|
75
75
|
|
|
76
76
|
// ../sync/src/utils.ts
|
|
77
77
|
function generateShortUUID() {
|
|
78
78
|
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
79
|
+
const randomBytes = typeof globalThis.crypto?.getRandomValues === "function" ? globalThis.crypto.getRandomValues(new Uint8Array(8)) : null;
|
|
79
80
|
let uuid = "";
|
|
80
81
|
for (let i = 0; i < 8; i++) {
|
|
81
|
-
const
|
|
82
|
-
uuid += chars[
|
|
82
|
+
const randomValue = randomBytes?.[i] ?? Math.floor(Math.random() * 256);
|
|
83
|
+
uuid += chars[randomValue % chars.length];
|
|
83
84
|
}
|
|
84
85
|
return uuid;
|
|
85
86
|
}
|
|
86
|
-
__name(generateShortUUID, "generateShortUUID");
|
|
87
87
|
|
|
88
88
|
// src/storage.ts
|
|
89
89
|
var Storage = class {
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
constructor() {
|
|
91
|
+
this.memory = /* @__PURE__ */ new Map();
|
|
92
92
|
}
|
|
93
|
-
memory = /* @__PURE__ */ new Map();
|
|
94
93
|
async put(key, value) {
|
|
95
94
|
this.memory.set(key, value);
|
|
96
95
|
}
|
|
@@ -108,22 +107,27 @@ var Storage = class {
|
|
|
108
107
|
// src/server.ts
|
|
109
108
|
import { dset as dset2 } from "dset";
|
|
110
109
|
import z from "zod";
|
|
111
|
-
import {
|
|
110
|
+
import {
|
|
111
|
+
createStatesSnapshot,
|
|
112
|
+
getByPath,
|
|
113
|
+
load,
|
|
114
|
+
syncClass,
|
|
115
|
+
DELETE_TOKEN,
|
|
116
|
+
generateShortUUID as generateShortUUID2,
|
|
117
|
+
createStatesSnapshotDeep
|
|
118
|
+
} from "@signe/sync";
|
|
112
119
|
|
|
113
120
|
// src/utils.ts
|
|
114
121
|
import { dset } from "dset";
|
|
115
122
|
function isPromise(value) {
|
|
116
123
|
return value instanceof Promise;
|
|
117
124
|
}
|
|
118
|
-
__name(isPromise, "isPromise");
|
|
119
125
|
async function awaitReturn(val) {
|
|
120
126
|
return isPromise(val) ? await val : val;
|
|
121
127
|
}
|
|
122
|
-
__name(awaitReturn, "awaitReturn");
|
|
123
128
|
function isClass(obj) {
|
|
124
129
|
return typeof obj === "function" && obj.prototype && obj.prototype.constructor === obj;
|
|
125
130
|
}
|
|
126
|
-
__name(isClass, "isClass");
|
|
127
131
|
function throttle(func, wait) {
|
|
128
132
|
let timeout = null;
|
|
129
133
|
let lastArgs = null;
|
|
@@ -142,7 +146,6 @@ function throttle(func, wait) {
|
|
|
142
146
|
}
|
|
143
147
|
};
|
|
144
148
|
}
|
|
145
|
-
__name(throttle, "throttle");
|
|
146
149
|
function extractParams(pattern, str) {
|
|
147
150
|
const regexPattern = pattern.replace(/{(\w+)}/g, "(?<$1>[\\w-]+)");
|
|
148
151
|
const regex = new RegExp(`^${regexPattern}$`);
|
|
@@ -155,7 +158,6 @@ function extractParams(pattern, str) {
|
|
|
155
158
|
return null;
|
|
156
159
|
}
|
|
157
160
|
}
|
|
158
|
-
__name(extractParams, "extractParams");
|
|
159
161
|
function dremove(obj, keys) {
|
|
160
162
|
if (typeof keys === "string") {
|
|
161
163
|
keys = keys.split(".");
|
|
@@ -175,7 +177,6 @@ function dremove(obj, keys) {
|
|
|
175
177
|
delete t[k];
|
|
176
178
|
}
|
|
177
179
|
}
|
|
178
|
-
__name(dremove, "dremove");
|
|
179
180
|
function buildObject(valuesMap, allMemory) {
|
|
180
181
|
let memoryObj = {};
|
|
181
182
|
for (let path of valuesMap.keys()) {
|
|
@@ -189,33 +190,25 @@ function buildObject(valuesMap, allMemory) {
|
|
|
189
190
|
}
|
|
190
191
|
return memoryObj;
|
|
191
192
|
}
|
|
192
|
-
__name(buildObject, "buildObject");
|
|
193
193
|
function response(status, body) {
|
|
194
194
|
return new Response(JSON.stringify(body), {
|
|
195
195
|
status,
|
|
196
|
-
headers: {
|
|
197
|
-
"Content-Type": "application/json"
|
|
198
|
-
}
|
|
196
|
+
headers: { "Content-Type": "application/json" }
|
|
199
197
|
});
|
|
200
198
|
}
|
|
201
|
-
__name(response, "response");
|
|
202
199
|
|
|
203
200
|
// src/request/response.ts
|
|
204
201
|
var ServerResponse = class {
|
|
205
|
-
static {
|
|
206
|
-
__name(this, "ServerResponse");
|
|
207
|
-
}
|
|
208
|
-
interceptors;
|
|
209
|
-
statusCode = 200;
|
|
210
|
-
responseBody = {};
|
|
211
|
-
responseHeaders = {
|
|
212
|
-
"Content-Type": "application/json"
|
|
213
|
-
};
|
|
214
202
|
/**
|
|
215
203
|
* Creates a new ServerResponse instance
|
|
216
204
|
* @param interceptors Array of interceptor functions that can modify the response
|
|
217
205
|
*/
|
|
218
206
|
constructor(interceptors = []) {
|
|
207
|
+
this.statusCode = 200;
|
|
208
|
+
this.responseBody = {};
|
|
209
|
+
this.responseHeaders = {
|
|
210
|
+
"Content-Type": "application/json"
|
|
211
|
+
};
|
|
219
212
|
this.interceptors = interceptors;
|
|
220
213
|
}
|
|
221
214
|
/**
|
|
@@ -253,10 +246,7 @@ var ServerResponse = class {
|
|
|
253
246
|
* @returns this instance for chaining
|
|
254
247
|
*/
|
|
255
248
|
setHeaders(headers) {
|
|
256
|
-
this.responseHeaders = {
|
|
257
|
-
...this.responseHeaders,
|
|
258
|
-
...headers
|
|
259
|
-
};
|
|
249
|
+
this.responseHeaders = { ...this.responseHeaders, ...headers };
|
|
260
250
|
return this;
|
|
261
251
|
}
|
|
262
252
|
/**
|
|
@@ -381,9 +371,7 @@ var ServerResponse = class {
|
|
|
381
371
|
* @returns Promise<Response> The final Response object
|
|
382
372
|
*/
|
|
383
373
|
async notPermitted(message = "Not permitted") {
|
|
384
|
-
return this.status(403).json({
|
|
385
|
-
error: message
|
|
386
|
-
});
|
|
374
|
+
return this.status(403).json({ error: message });
|
|
387
375
|
}
|
|
388
376
|
/**
|
|
389
377
|
* Creates an error response with status 401
|
|
@@ -391,9 +379,7 @@ var ServerResponse = class {
|
|
|
391
379
|
* @returns Promise<Response> The final Response object
|
|
392
380
|
*/
|
|
393
381
|
async unauthorized(message = "Unauthorized") {
|
|
394
|
-
return this.status(401).json({
|
|
395
|
-
error: message
|
|
396
|
-
});
|
|
382
|
+
return this.status(401).json({ error: message });
|
|
397
383
|
}
|
|
398
384
|
/**
|
|
399
385
|
* Creates an error response with status 404
|
|
@@ -401,9 +387,7 @@ var ServerResponse = class {
|
|
|
401
387
|
* @returns Promise<Response> The final Response object
|
|
402
388
|
*/
|
|
403
389
|
async notFound(message = "Not found") {
|
|
404
|
-
return this.status(404).json({
|
|
405
|
-
error: message
|
|
406
|
-
});
|
|
390
|
+
return this.status(404).json({ error: message });
|
|
407
391
|
}
|
|
408
392
|
/**
|
|
409
393
|
* Creates an error response with status 500
|
|
@@ -411,9 +395,7 @@ var ServerResponse = class {
|
|
|
411
395
|
* @returns Promise<Response> The final Response object
|
|
412
396
|
*/
|
|
413
397
|
async serverError(message = "Internal Server Error") {
|
|
414
|
-
return this.status(500).json({
|
|
415
|
-
error: message
|
|
416
|
-
});
|
|
398
|
+
return this.status(500).json({ error: message });
|
|
417
399
|
}
|
|
418
400
|
};
|
|
419
401
|
|
|
@@ -448,11 +430,9 @@ function cors(res, options = {}) {
|
|
|
448
430
|
headers: newHeaders
|
|
449
431
|
});
|
|
450
432
|
}
|
|
451
|
-
__name(cors, "cors");
|
|
452
433
|
function createCorsInterceptor(options = {}) {
|
|
453
434
|
return (res) => cors(res, options);
|
|
454
435
|
}
|
|
455
|
-
__name(createCorsInterceptor, "createCorsInterceptor");
|
|
456
436
|
|
|
457
437
|
// src/server.ts
|
|
458
438
|
var Message = z.object({
|
|
@@ -460,37 +440,31 @@ var Message = z.object({
|
|
|
460
440
|
value: z.any()
|
|
461
441
|
});
|
|
462
442
|
var Server = class {
|
|
463
|
-
static {
|
|
464
|
-
__name(this, "Server");
|
|
465
|
-
}
|
|
466
|
-
room;
|
|
467
|
-
subRoom;
|
|
468
|
-
rooms;
|
|
469
443
|
/**
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
444
|
+
* @constructor
|
|
445
|
+
* @param {Party.Room} room - The room object representing the current game or application instance.
|
|
446
|
+
*
|
|
447
|
+
* @example
|
|
448
|
+
* ```typescript
|
|
449
|
+
* const server = new MyServer(new ServerIo("game"));
|
|
450
|
+
* ```
|
|
451
|
+
*/
|
|
478
452
|
constructor(room) {
|
|
479
453
|
this.room = room;
|
|
480
454
|
this.subRoom = null;
|
|
481
455
|
this.rooms = [];
|
|
482
456
|
}
|
|
483
457
|
/**
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
458
|
+
* @readonly
|
|
459
|
+
* @property {boolean} isHibernate - Indicates whether the server is in hibernate mode.
|
|
460
|
+
*
|
|
461
|
+
* @example
|
|
462
|
+
* ```typescript
|
|
463
|
+
* if (!server.isHibernate) {
|
|
464
|
+
* console.log("Server is active");
|
|
465
|
+
* }
|
|
466
|
+
* ```
|
|
467
|
+
*/
|
|
494
468
|
get isHibernate() {
|
|
495
469
|
return !!this["options"]?.hibernate;
|
|
496
470
|
}
|
|
@@ -514,35 +488,31 @@ var Server = class {
|
|
|
514
488
|
}
|
|
515
489
|
}
|
|
516
490
|
/**
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
491
|
+
* @method onStart
|
|
492
|
+
* @async
|
|
493
|
+
* @description Initializes the server and creates the initial room if not in hibernate mode.
|
|
494
|
+
* @returns {Promise<void>}
|
|
495
|
+
*
|
|
496
|
+
* @example
|
|
497
|
+
* ```typescript
|
|
498
|
+
* async function initServer() {
|
|
499
|
+
* await server.onStart();
|
|
500
|
+
* console.log("Server started");
|
|
501
|
+
* }
|
|
502
|
+
* ```
|
|
503
|
+
*/
|
|
530
504
|
async onStart() {
|
|
531
505
|
if (!this.isHibernate) {
|
|
532
506
|
this.subRoom = await this.createRoom();
|
|
533
507
|
}
|
|
534
508
|
}
|
|
535
509
|
async runGarbageCollector() {
|
|
536
|
-
await this.garbageCollector({
|
|
537
|
-
sessionExpiryTime: -1
|
|
538
|
-
});
|
|
510
|
+
await this.garbageCollector({ sessionExpiryTime: -1 });
|
|
539
511
|
}
|
|
540
512
|
async garbageCollector(options) {
|
|
541
513
|
const subRoom = await this.getSubRoom();
|
|
542
514
|
if (!subRoom) return;
|
|
543
|
-
const activeConnections = [
|
|
544
|
-
...this.room.getConnections()
|
|
545
|
-
];
|
|
515
|
+
const activeConnections = [...this.room.getConnections()];
|
|
546
516
|
const activePrivateIds = new Set(activeConnections.map((conn) => conn.id));
|
|
547
517
|
try {
|
|
548
518
|
const sessions = await this.room.storage.list();
|
|
@@ -577,21 +547,21 @@ var Server = class {
|
|
|
577
547
|
}
|
|
578
548
|
}
|
|
579
549
|
/**
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
550
|
+
* @method createRoom
|
|
551
|
+
* @private
|
|
552
|
+
* @async
|
|
553
|
+
* @param {CreateRoomOptions} [options={}] - Options for creating the room.
|
|
554
|
+
* @returns {Promise<Object>} The created room instance.
|
|
555
|
+
*
|
|
556
|
+
* @example
|
|
557
|
+
* ```typescript
|
|
558
|
+
* // This method is private and called internally
|
|
559
|
+
* async function internalCreateRoom() {
|
|
560
|
+
* const room = await this.createRoom({ getMemoryAll: true });
|
|
561
|
+
* console.log("Room created:", room);
|
|
562
|
+
* }
|
|
563
|
+
* ```
|
|
564
|
+
*/
|
|
595
565
|
async createRoom(options = {}) {
|
|
596
566
|
let instance;
|
|
597
567
|
let init = true;
|
|
@@ -606,7 +576,7 @@ var Server = class {
|
|
|
606
576
|
if (!instance) {
|
|
607
577
|
return null;
|
|
608
578
|
}
|
|
609
|
-
const loadMemory =
|
|
579
|
+
const loadMemory = async () => {
|
|
610
580
|
const root = await this.room.storage.get(".");
|
|
611
581
|
const memory = await this.room.storage.list();
|
|
612
582
|
const tmpObject = root || {};
|
|
@@ -620,7 +590,7 @@ var Server = class {
|
|
|
620
590
|
dset2(tmpObject, key, value);
|
|
621
591
|
}
|
|
622
592
|
load(instance, tmpObject, true);
|
|
623
|
-
}
|
|
593
|
+
};
|
|
624
594
|
instance.$memoryAll = {};
|
|
625
595
|
instance.$autoSync = instance["autoSync"] !== false;
|
|
626
596
|
instance.$pendingSync = /* @__PURE__ */ new Map();
|
|
@@ -720,7 +690,7 @@ var Server = class {
|
|
|
720
690
|
return null;
|
|
721
691
|
}
|
|
722
692
|
};
|
|
723
|
-
const syncCb =
|
|
693
|
+
const syncCb = (values) => {
|
|
724
694
|
if (options.getMemoryAll) {
|
|
725
695
|
buildObject(values, instance.$memoryAll);
|
|
726
696
|
}
|
|
@@ -736,13 +706,16 @@ var Server = class {
|
|
|
736
706
|
return;
|
|
737
707
|
}
|
|
738
708
|
const packet = buildObject(values, instance.$memoryAll);
|
|
739
|
-
this.broadcast(
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
709
|
+
this.broadcast(
|
|
710
|
+
{
|
|
711
|
+
type: "sync",
|
|
712
|
+
value: packet
|
|
713
|
+
},
|
|
714
|
+
instance
|
|
715
|
+
);
|
|
743
716
|
values.clear();
|
|
744
|
-
}
|
|
745
|
-
const persistCb =
|
|
717
|
+
};
|
|
718
|
+
const persistCb = async (values) => {
|
|
746
719
|
if (initPersist) {
|
|
747
720
|
values.clear();
|
|
748
721
|
return;
|
|
@@ -757,7 +730,7 @@ var Server = class {
|
|
|
757
730
|
}
|
|
758
731
|
}
|
|
759
732
|
values.clear();
|
|
760
|
-
}
|
|
733
|
+
};
|
|
761
734
|
syncClass(instance, {
|
|
762
735
|
onSync: instance["throttleSync"] ? throttle(syncCb, instance["throttleSync"]) : syncCb,
|
|
763
736
|
onPersist: instance["throttleStorage"] ? throttle(persistCb, instance["throttleStorage"]) : persistCb
|
|
@@ -768,21 +741,21 @@ var Server = class {
|
|
|
768
741
|
return instance;
|
|
769
742
|
}
|
|
770
743
|
/**
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
744
|
+
* @method getSubRoom
|
|
745
|
+
* @private
|
|
746
|
+
* @async
|
|
747
|
+
* @param {Object} [options={}] - Options for getting the sub-room.
|
|
748
|
+
* @returns {Promise<Object>} The sub-room instance.
|
|
749
|
+
*
|
|
750
|
+
* @example
|
|
751
|
+
* ```typescript
|
|
752
|
+
* // This method is private and called internally
|
|
753
|
+
* async function internalGetSubRoom() {
|
|
754
|
+
* const subRoom = await this.getSubRoom();
|
|
755
|
+
* console.log("Sub-room retrieved:", subRoom);
|
|
756
|
+
* }
|
|
757
|
+
* ```
|
|
758
|
+
*/
|
|
786
759
|
async getSubRoom(options = {}) {
|
|
787
760
|
let subRoom;
|
|
788
761
|
if (this.isHibernate) {
|
|
@@ -793,20 +766,20 @@ var Server = class {
|
|
|
793
766
|
return subRoom;
|
|
794
767
|
}
|
|
795
768
|
/**
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
769
|
+
* @method getUsersProperty
|
|
770
|
+
* @private
|
|
771
|
+
* @param {Object} subRoom - The sub-room instance.
|
|
772
|
+
* @returns {Object|null} The users property of the sub-room, or null if not found.
|
|
773
|
+
*
|
|
774
|
+
* @example
|
|
775
|
+
* ```typescript
|
|
776
|
+
* // This method is private and called internally
|
|
777
|
+
* function internalGetUsers(subRoom) {
|
|
778
|
+
* const users = this.getUsersProperty(subRoom);
|
|
779
|
+
* console.log("Users:", users);
|
|
780
|
+
* }
|
|
781
|
+
* ```
|
|
782
|
+
*/
|
|
810
783
|
getUsersProperty(subRoom) {
|
|
811
784
|
const meta = subRoom.constructor["_propertyMetadata"];
|
|
812
785
|
const propId = meta?.get("users");
|
|
@@ -822,12 +795,12 @@ var Server = class {
|
|
|
822
795
|
return metadata.get("users");
|
|
823
796
|
}
|
|
824
797
|
/**
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
798
|
+
* Retrieves the connection status property from a user object.
|
|
799
|
+
*
|
|
800
|
+
* @param {any} user - The user object to get the connection property from.
|
|
801
|
+
* @returns {Function|null} - The connection property signal function or null if not found.
|
|
802
|
+
* @private
|
|
803
|
+
*/
|
|
831
804
|
getUserConnectionProperty(user) {
|
|
832
805
|
if (!user) return null;
|
|
833
806
|
const metadata = user.constructor._propertyMetadata;
|
|
@@ -837,13 +810,13 @@ var Server = class {
|
|
|
837
810
|
return user[connectedPropName];
|
|
838
811
|
}
|
|
839
812
|
/**
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
813
|
+
* Updates a user's connection status in the signal.
|
|
814
|
+
*
|
|
815
|
+
* @param {any} user - The user object to update.
|
|
816
|
+
* @param {boolean} isConnected - The new connection status.
|
|
817
|
+
* @returns {boolean} - Whether the update was successful.
|
|
818
|
+
* @private
|
|
819
|
+
*/
|
|
847
820
|
updateUserConnectionStatus(user, isConnected) {
|
|
848
821
|
const connectionSignal = this.getUserConnectionProperty(user);
|
|
849
822
|
if (connectionSignal) {
|
|
@@ -853,17 +826,17 @@ var Server = class {
|
|
|
853
826
|
return false;
|
|
854
827
|
}
|
|
855
828
|
/**
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
829
|
+
* @method getSession
|
|
830
|
+
* @private
|
|
831
|
+
* @param {string} privateId - The private ID of the session.
|
|
832
|
+
* @returns {Promise<Object|null>} The session object, or null if not found.
|
|
833
|
+
*
|
|
834
|
+
* @example
|
|
835
|
+
* ```typescript
|
|
836
|
+
* const session = await server.getSession("privateId");
|
|
837
|
+
* console.log(session);
|
|
838
|
+
* ```
|
|
839
|
+
*/
|
|
867
840
|
async getSession(privateId) {
|
|
868
841
|
if (!privateId) return null;
|
|
869
842
|
try {
|
|
@@ -884,23 +857,20 @@ var Server = class {
|
|
|
884
857
|
async updateSessionConnection(privateId, connected) {
|
|
885
858
|
const session = await this.getSession(privateId);
|
|
886
859
|
if (session) {
|
|
887
|
-
await this.saveSession(privateId, {
|
|
888
|
-
...session,
|
|
889
|
-
connected
|
|
890
|
-
});
|
|
860
|
+
await this.saveSession(privateId, { ...session, connected });
|
|
891
861
|
}
|
|
892
862
|
}
|
|
893
863
|
/**
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
864
|
+
* @method deleteSession
|
|
865
|
+
* @private
|
|
866
|
+
* @param {string} privateId - The private ID of the session to delete.
|
|
867
|
+
* @returns {Promise<void>}
|
|
868
|
+
*
|
|
869
|
+
* @example
|
|
870
|
+
* ```typescript
|
|
871
|
+
* await server.deleteSession("privateId");
|
|
872
|
+
* ```
|
|
873
|
+
*/
|
|
904
874
|
async deleteSession(privateId) {
|
|
905
875
|
await this.room.storage.delete(`session:${privateId}`);
|
|
906
876
|
}
|
|
@@ -912,10 +882,8 @@ var Server = class {
|
|
|
912
882
|
conn.close();
|
|
913
883
|
return;
|
|
914
884
|
}
|
|
915
|
-
const sessionExpiryTime = subRoom.constructor.sessionExpiryTime;
|
|
916
|
-
await this.garbageCollector({
|
|
917
|
-
sessionExpiryTime
|
|
918
|
-
});
|
|
885
|
+
const sessionExpiryTime = subRoom.sessionExpiryTime ?? subRoom.constructor.sessionExpiryTime ?? 5 * 60 * 1e3;
|
|
886
|
+
await this.garbageCollector({ sessionExpiryTime });
|
|
919
887
|
const roomGuards = subRoom.constructor["_roomGuards"] || [];
|
|
920
888
|
for (const guard of roomGuards) {
|
|
921
889
|
const isAuthorized = await guard(conn, ctx, this.room);
|
|
@@ -983,21 +951,21 @@ var Server = class {
|
|
|
983
951
|
}
|
|
984
952
|
}
|
|
985
953
|
/**
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
954
|
+
* @method onConnect
|
|
955
|
+
* @async
|
|
956
|
+
* @param {Party.Connection} conn - The connection object for the new user.
|
|
957
|
+
* @param {Party.ConnectionContext} ctx - The context of the connection.
|
|
958
|
+
* @description Handles a new user connection, creates a user object, and sends initial sync data.
|
|
959
|
+
* @returns {Promise<void>}
|
|
960
|
+
*
|
|
961
|
+
* @example
|
|
962
|
+
* ```typescript
|
|
963
|
+
* server.onConnect = async (conn, ctx) => {
|
|
964
|
+
* await server.onConnect(conn, ctx);
|
|
965
|
+
* console.log("New user connected:", conn.id);
|
|
966
|
+
* };
|
|
967
|
+
* ```
|
|
968
|
+
*/
|
|
1001
969
|
async onConnect(conn, ctx) {
|
|
1002
970
|
if (ctx.request?.headers.has("x-shard-id")) {
|
|
1003
971
|
this.onConnectShard(conn, ctx);
|
|
@@ -1006,13 +974,13 @@ var Server = class {
|
|
|
1006
974
|
}
|
|
1007
975
|
}
|
|
1008
976
|
/**
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
977
|
+
* @method onConnectShard
|
|
978
|
+
* @private
|
|
979
|
+
* @param {Party.Connection} conn - The connection object for the new shard.
|
|
980
|
+
* @param {Party.ConnectionContext} ctx - The context of the shard connection.
|
|
981
|
+
* @description Handles a new shard connection, setting up the necessary state.
|
|
982
|
+
* @returns {void}
|
|
983
|
+
*/
|
|
1016
984
|
onConnectShard(conn, ctx) {
|
|
1017
985
|
const shardId = ctx.request?.headers.get("x-shard-id") || "unknown-shard";
|
|
1018
986
|
conn.setState({
|
|
@@ -1023,13 +991,13 @@ var Server = class {
|
|
|
1023
991
|
});
|
|
1024
992
|
}
|
|
1025
993
|
/**
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
994
|
+
* @method onMessage
|
|
995
|
+
* @async
|
|
996
|
+
* @param {string} message - The message received from a user or shard.
|
|
997
|
+
* @param {Party.Connection} sender - The connection object of the sender.
|
|
998
|
+
* @description Processes incoming messages, handling differently based on if sender is shard or client.
|
|
999
|
+
* @returns {Promise<void>}
|
|
1000
|
+
*/
|
|
1033
1001
|
async onMessage(message, sender) {
|
|
1034
1002
|
if (sender.state && sender.state.shard) {
|
|
1035
1003
|
await this.handleShardMessage(message, sender);
|
|
@@ -1071,12 +1039,16 @@ var Server = class {
|
|
|
1071
1039
|
}
|
|
1072
1040
|
}
|
|
1073
1041
|
if (actionName.bodyValidation) {
|
|
1074
|
-
const bodyResult = actionName.bodyValidation.safeParse(
|
|
1042
|
+
const bodyResult = actionName.bodyValidation.safeParse(
|
|
1043
|
+
result.data.value
|
|
1044
|
+
);
|
|
1075
1045
|
if (!bodyResult.success) {
|
|
1076
1046
|
return;
|
|
1077
1047
|
}
|
|
1078
1048
|
}
|
|
1079
|
-
await awaitReturn(
|
|
1049
|
+
await awaitReturn(
|
|
1050
|
+
subRoom[actionName.key](user, result.data.value, sender)
|
|
1051
|
+
);
|
|
1080
1052
|
return;
|
|
1081
1053
|
}
|
|
1082
1054
|
const unhandledAction = subRoom.constructor["_unhandledActionMetadata"];
|
|
@@ -1088,18 +1060,20 @@ var Server = class {
|
|
|
1088
1060
|
return;
|
|
1089
1061
|
}
|
|
1090
1062
|
}
|
|
1091
|
-
await awaitReturn(
|
|
1063
|
+
await awaitReturn(
|
|
1064
|
+
subRoom[unhandledAction.key](user, result.data, sender)
|
|
1065
|
+
);
|
|
1092
1066
|
}
|
|
1093
1067
|
}
|
|
1094
1068
|
/**
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1069
|
+
* @method handleShardMessage
|
|
1070
|
+
* @private
|
|
1071
|
+
* @async
|
|
1072
|
+
* @param {string} message - The message received from a shard.
|
|
1073
|
+
* @param {Party.Connection} shardConnection - The connection object of the shard.
|
|
1074
|
+
* @description Processes messages from shards, extracting client information.
|
|
1075
|
+
* @returns {Promise<void>}
|
|
1076
|
+
*/
|
|
1103
1077
|
async handleShardMessage(message, shardConnection) {
|
|
1104
1078
|
let parsedMessage;
|
|
1105
1079
|
try {
|
|
@@ -1125,14 +1099,14 @@ var Server = class {
|
|
|
1125
1099
|
}
|
|
1126
1100
|
}
|
|
1127
1101
|
/**
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1102
|
+
* @method handleShardClientConnect
|
|
1103
|
+
* @private
|
|
1104
|
+
* @async
|
|
1105
|
+
* @param {Object} message - The client connection message from a shard.
|
|
1106
|
+
* @param {Party.Connection} shardConnection - The connection object of the shard.
|
|
1107
|
+
* @description Handles a new client connection via a shard.
|
|
1108
|
+
* @returns {Promise<void>}
|
|
1109
|
+
*/
|
|
1136
1110
|
async handleShardClientConnect(message, shardConnection) {
|
|
1137
1111
|
const { privateId, requestInfo } = message;
|
|
1138
1112
|
const shardState = shardConnection.state;
|
|
@@ -1145,22 +1119,22 @@ var Server = class {
|
|
|
1145
1119
|
};
|
|
1146
1120
|
const virtualConnection = {
|
|
1147
1121
|
id: privateId,
|
|
1148
|
-
send:
|
|
1122
|
+
send: (data) => {
|
|
1149
1123
|
shardConnection.send(JSON.stringify({
|
|
1150
1124
|
targetClientId: privateId,
|
|
1151
1125
|
data
|
|
1152
1126
|
}));
|
|
1153
|
-
},
|
|
1127
|
+
},
|
|
1154
1128
|
state: {},
|
|
1155
|
-
setState:
|
|
1129
|
+
setState: (state) => {
|
|
1156
1130
|
const clients = shardState.clients;
|
|
1157
1131
|
const currentState = clients.get(privateId) || {};
|
|
1158
1132
|
const mergedState = Object.assign({}, currentState, state);
|
|
1159
1133
|
clients.set(privateId, mergedState);
|
|
1160
1134
|
virtualConnection.state = clients.get(privateId);
|
|
1161
1135
|
return virtualConnection.state;
|
|
1162
|
-
},
|
|
1163
|
-
close:
|
|
1136
|
+
},
|
|
1137
|
+
close: () => {
|
|
1164
1138
|
shardConnection.send(JSON.stringify({
|
|
1165
1139
|
type: "shard.closeClient",
|
|
1166
1140
|
privateId
|
|
@@ -1168,7 +1142,7 @@ var Server = class {
|
|
|
1168
1142
|
if (shardState.clients) {
|
|
1169
1143
|
shardState.clients.delete(privateId);
|
|
1170
1144
|
}
|
|
1171
|
-
}
|
|
1145
|
+
}
|
|
1172
1146
|
};
|
|
1173
1147
|
if (!shardState.clients.has(privateId)) {
|
|
1174
1148
|
shardState.clients.set(privateId, {});
|
|
@@ -1176,41 +1150,39 @@ var Server = class {
|
|
|
1176
1150
|
await this.onConnectClient(virtualConnection, virtualContext);
|
|
1177
1151
|
}
|
|
1178
1152
|
/**
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1153
|
+
* @method handleShardClientMessage
|
|
1154
|
+
* @private
|
|
1155
|
+
* @async
|
|
1156
|
+
* @param {Object} message - The client message from a shard.
|
|
1157
|
+
* @param {Party.Connection} shardConnection - The connection object of the shard.
|
|
1158
|
+
* @description Handles a message from a client via a shard.
|
|
1159
|
+
* @returns {Promise<void>}
|
|
1160
|
+
*/
|
|
1187
1161
|
async handleShardClientMessage(message, shardConnection) {
|
|
1188
1162
|
const { privateId, publicId, payload } = message;
|
|
1189
1163
|
const shardState = shardConnection.state;
|
|
1190
1164
|
const clients = shardState.clients;
|
|
1191
1165
|
if (!clients.has(privateId)) {
|
|
1192
1166
|
console.warn(`Received message from unknown client ${privateId}, creating virtual connection`);
|
|
1193
|
-
clients.set(privateId, {
|
|
1194
|
-
publicId
|
|
1195
|
-
});
|
|
1167
|
+
clients.set(privateId, { publicId });
|
|
1196
1168
|
}
|
|
1197
1169
|
const virtualConnection = {
|
|
1198
1170
|
id: privateId,
|
|
1199
|
-
send:
|
|
1171
|
+
send: (data) => {
|
|
1200
1172
|
shardConnection.send(JSON.stringify({
|
|
1201
1173
|
targetClientId: privateId,
|
|
1202
1174
|
data
|
|
1203
1175
|
}));
|
|
1204
|
-
},
|
|
1176
|
+
},
|
|
1205
1177
|
state: clients.get(privateId),
|
|
1206
|
-
setState:
|
|
1178
|
+
setState: (state) => {
|
|
1207
1179
|
const currentState = clients.get(privateId) || {};
|
|
1208
1180
|
const mergedState = Object.assign({}, currentState, state);
|
|
1209
1181
|
clients.set(privateId, mergedState);
|
|
1210
1182
|
virtualConnection.state = clients.get(privateId);
|
|
1211
1183
|
return virtualConnection.state;
|
|
1212
|
-
},
|
|
1213
|
-
close:
|
|
1184
|
+
},
|
|
1185
|
+
close: () => {
|
|
1214
1186
|
shardConnection.send(JSON.stringify({
|
|
1215
1187
|
type: "shard.closeClient",
|
|
1216
1188
|
privateId
|
|
@@ -1218,20 +1190,20 @@ var Server = class {
|
|
|
1218
1190
|
if (shardState.clients) {
|
|
1219
1191
|
shardState.clients.delete(privateId);
|
|
1220
1192
|
}
|
|
1221
|
-
}
|
|
1193
|
+
}
|
|
1222
1194
|
};
|
|
1223
1195
|
const payloadString = typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
1224
1196
|
await this.onMessage(payloadString, virtualConnection);
|
|
1225
1197
|
}
|
|
1226
1198
|
/**
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1199
|
+
* @method handleShardClientDisconnect
|
|
1200
|
+
* @private
|
|
1201
|
+
* @async
|
|
1202
|
+
* @param {Object} message - The client disconnection message from a shard.
|
|
1203
|
+
* @param {Party.Connection} shardConnection - The connection object of the shard.
|
|
1204
|
+
* @description Handles a client disconnection via a shard.
|
|
1205
|
+
* @returns {Promise<void>}
|
|
1206
|
+
*/
|
|
1235
1207
|
async handleShardClientDisconnect(message, shardConnection) {
|
|
1236
1208
|
const { privateId, publicId } = message;
|
|
1237
1209
|
const shardState = shardConnection.state;
|
|
@@ -1243,33 +1215,34 @@ var Server = class {
|
|
|
1243
1215
|
}
|
|
1244
1216
|
const virtualConnection = {
|
|
1245
1217
|
id: privateId,
|
|
1246
|
-
send:
|
|
1247
|
-
},
|
|
1218
|
+
send: () => {
|
|
1219
|
+
},
|
|
1220
|
+
// No-op since client is disconnecting
|
|
1248
1221
|
state: clientState,
|
|
1249
|
-
setState:
|
|
1222
|
+
setState: () => {
|
|
1250
1223
|
return {};
|
|
1251
|
-
},
|
|
1252
|
-
close:
|
|
1253
|
-
}
|
|
1224
|
+
},
|
|
1225
|
+
close: () => {
|
|
1226
|
+
}
|
|
1254
1227
|
};
|
|
1255
1228
|
await this.onClose(virtualConnection);
|
|
1256
1229
|
clients.delete(privateId);
|
|
1257
1230
|
}
|
|
1258
1231
|
/**
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1232
|
+
* @method onClose
|
|
1233
|
+
* @async
|
|
1234
|
+
* @param {Party.Connection} conn - The connection object of the disconnecting user.
|
|
1235
|
+
* @description Handles user disconnection, removing them from the room and triggering the onLeave event..
|
|
1236
|
+
* @returns {Promise<void>}
|
|
1237
|
+
*
|
|
1238
|
+
* @example
|
|
1239
|
+
* ```typescript
|
|
1240
|
+
* server.onClose = async (conn) => {
|
|
1241
|
+
* await server.onClose(conn);
|
|
1242
|
+
* console.log("User disconnected:", conn.id);
|
|
1243
|
+
* };
|
|
1244
|
+
* ```
|
|
1245
|
+
*/
|
|
1273
1246
|
async onClose(conn) {
|
|
1274
1247
|
const subRoom = await this.getSubRoom();
|
|
1275
1248
|
if (!subRoom) {
|
|
@@ -1292,9 +1265,7 @@ var Server = class {
|
|
|
1292
1265
|
if (!connectionUpdated) {
|
|
1293
1266
|
this.broadcast({
|
|
1294
1267
|
type: "user_disconnected",
|
|
1295
|
-
value: {
|
|
1296
|
-
publicId
|
|
1297
|
-
}
|
|
1268
|
+
value: { publicId }
|
|
1298
1269
|
}, subRoom);
|
|
1299
1270
|
}
|
|
1300
1271
|
}
|
|
@@ -1307,12 +1278,12 @@ var Server = class {
|
|
|
1307
1278
|
await awaitReturn(subRoom["onError"]?.(connection, error));
|
|
1308
1279
|
}
|
|
1309
1280
|
/**
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1281
|
+
* @method onRequest
|
|
1282
|
+
* @async
|
|
1283
|
+
* @param {Party.Request} req - The HTTP request to handle
|
|
1284
|
+
* @description Handles HTTP requests, either directly from clients or forwarded by shards
|
|
1285
|
+
* @returns {Promise<Response>} The response to return to the client
|
|
1286
|
+
*/
|
|
1316
1287
|
async onRequest(req) {
|
|
1317
1288
|
const isFromShard = req.headers.has("x-forwarded-by-shard");
|
|
1318
1289
|
const shardId = req.headers.get("x-shard-id");
|
|
@@ -1328,14 +1299,14 @@ var Server = class {
|
|
|
1328
1299
|
return this.handleDirectRequest(req, res);
|
|
1329
1300
|
}
|
|
1330
1301
|
/**
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1302
|
+
* @method handleSessionRestore
|
|
1303
|
+
* @private
|
|
1304
|
+
* @async
|
|
1305
|
+
* @param {Party.Request} req - The HTTP request for session restore
|
|
1306
|
+
* @param {ServerResponse} res - The response object
|
|
1307
|
+
* @description Handles session restoration from transfer data, creates session from privateId
|
|
1308
|
+
* @returns {Promise<Response>} The response to return to the client
|
|
1309
|
+
*/
|
|
1339
1310
|
async handleSessionRestore(req, res) {
|
|
1340
1311
|
try {
|
|
1341
1312
|
const transferData = await req.json();
|
|
@@ -1360,14 +1331,16 @@ var Server = class {
|
|
|
1360
1331
|
if (signal2 && usersPropName) {
|
|
1361
1332
|
const { classType } = signal2.options;
|
|
1362
1333
|
const user = isClass(classType) ? new classType() : classType();
|
|
1363
|
-
const hydratedSnapshot = await awaitReturn(
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1334
|
+
const hydratedSnapshot = await awaitReturn(
|
|
1335
|
+
subRoom["onSessionRestore"]?.({
|
|
1336
|
+
userSnapshot,
|
|
1337
|
+
user,
|
|
1338
|
+
publicId,
|
|
1339
|
+
privateId,
|
|
1340
|
+
sessionState,
|
|
1341
|
+
room: this.room
|
|
1342
|
+
})
|
|
1343
|
+
) ?? userSnapshot;
|
|
1371
1344
|
signal2()[publicId] = user;
|
|
1372
1345
|
load(user, hydratedSnapshot, true);
|
|
1373
1346
|
await this.room.storage.put(`${usersPropName}.${publicId}`, userSnapshot);
|
|
@@ -1379,22 +1352,20 @@ var Server = class {
|
|
|
1379
1352
|
publicId,
|
|
1380
1353
|
restored: true
|
|
1381
1354
|
});
|
|
1382
|
-
return res.success({
|
|
1383
|
-
transferToken
|
|
1384
|
-
});
|
|
1355
|
+
return res.success({ transferToken });
|
|
1385
1356
|
} catch (error) {
|
|
1386
1357
|
console.error("Error restoring session:", error);
|
|
1387
1358
|
return res.serverError("Failed to restore session");
|
|
1388
1359
|
}
|
|
1389
1360
|
}
|
|
1390
1361
|
/**
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1362
|
+
* @method handleDirectRequest
|
|
1363
|
+
* @private
|
|
1364
|
+
* @async
|
|
1365
|
+
* @param {Party.Request} req - The HTTP request received directly from a client
|
|
1366
|
+
* @description Processes requests received directly from clients
|
|
1367
|
+
* @returns {Promise<Response>} The response to return to the client
|
|
1368
|
+
*/
|
|
1398
1369
|
async handleDirectRequest(req, res) {
|
|
1399
1370
|
const subRoom = await this.getSubRoom();
|
|
1400
1371
|
if (!subRoom) {
|
|
@@ -1418,14 +1389,14 @@ var Server = class {
|
|
|
1418
1389
|
return res.success(legacyResponse);
|
|
1419
1390
|
}
|
|
1420
1391
|
/**
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1392
|
+
* @method tryMatchRequestHandler
|
|
1393
|
+
* @private
|
|
1394
|
+
* @async
|
|
1395
|
+
* @param {Party.Request} req - The HTTP request to handle
|
|
1396
|
+
* @param {Object} subRoom - The room instance
|
|
1397
|
+
* @description Attempts to match the request to a registered @Request handler
|
|
1398
|
+
* @returns {Promise<Response | null>} The response or null if no handler matched
|
|
1399
|
+
*/
|
|
1429
1400
|
async tryMatchRequestHandler(req, res, subRoom) {
|
|
1430
1401
|
const requestHandlers = subRoom.constructor["_requestMetadata"];
|
|
1431
1402
|
if (!requestHandlers) {
|
|
@@ -1433,8 +1404,7 @@ var Server = class {
|
|
|
1433
1404
|
}
|
|
1434
1405
|
const url = new URL(req.url);
|
|
1435
1406
|
const method = req.method;
|
|
1436
|
-
|
|
1437
|
-
pathname = "/" + pathname.split("/").slice(4).join("/");
|
|
1407
|
+
const pathname = this.normalizeRequestPath(url.pathname);
|
|
1438
1408
|
for (const [routeKey, handler] of requestHandlers.entries()) {
|
|
1439
1409
|
const firstColonIndex = routeKey.indexOf(":");
|
|
1440
1410
|
const handlerMethod = routeKey.substring(0, firstColonIndex);
|
|
@@ -1455,23 +1425,20 @@ var Server = class {
|
|
|
1455
1425
|
}
|
|
1456
1426
|
}
|
|
1457
1427
|
let bodyData = null;
|
|
1458
|
-
if (handler.bodyValidation && [
|
|
1459
|
-
"POST",
|
|
1460
|
-
"PUT",
|
|
1461
|
-
"PATCH"
|
|
1462
|
-
].includes(method)) {
|
|
1428
|
+
if (handler.bodyValidation && ["POST", "PUT", "PATCH"].includes(method)) {
|
|
1463
1429
|
try {
|
|
1464
1430
|
const contentType = req.headers.get("content-type") || "";
|
|
1465
|
-
if (contentType.includes("application/json")) {
|
|
1466
|
-
|
|
1467
|
-
const validation = handler.bodyValidation.safeParse(body);
|
|
1468
|
-
if (!validation.success) {
|
|
1469
|
-
return res.badRequest("Invalid request body", {
|
|
1470
|
-
details: validation.error
|
|
1471
|
-
});
|
|
1472
|
-
}
|
|
1473
|
-
bodyData = validation.data;
|
|
1431
|
+
if (!contentType.includes("application/json")) {
|
|
1432
|
+
return res.badRequest("Content-Type must be application/json");
|
|
1474
1433
|
}
|
|
1434
|
+
const body = await req.json();
|
|
1435
|
+
const validation = handler.bodyValidation.safeParse(body);
|
|
1436
|
+
if (!validation.success) {
|
|
1437
|
+
return res.badRequest("Invalid request body", {
|
|
1438
|
+
details: validation.error
|
|
1439
|
+
});
|
|
1440
|
+
}
|
|
1441
|
+
bodyData = validation.data;
|
|
1475
1442
|
} catch (error) {
|
|
1476
1443
|
return res.badRequest("Failed to parse request body");
|
|
1477
1444
|
}
|
|
@@ -1479,7 +1446,9 @@ var Server = class {
|
|
|
1479
1446
|
try {
|
|
1480
1447
|
req["data"] = bodyData;
|
|
1481
1448
|
req["params"] = params;
|
|
1482
|
-
const result = await awaitReturn(
|
|
1449
|
+
const result = await awaitReturn(
|
|
1450
|
+
subRoom[handler.key](req, res)
|
|
1451
|
+
);
|
|
1483
1452
|
if (result instanceof Response) {
|
|
1484
1453
|
return result;
|
|
1485
1454
|
}
|
|
@@ -1493,26 +1462,24 @@ var Server = class {
|
|
|
1493
1462
|
return null;
|
|
1494
1463
|
}
|
|
1495
1464
|
/**
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1465
|
+
* @method pathMatches
|
|
1466
|
+
* @private
|
|
1467
|
+
* @param {string} requestPath - The path from the request
|
|
1468
|
+
* @param {string} handlerPath - The path pattern from the handler
|
|
1469
|
+
* @description Checks if a request path matches a handler path pattern
|
|
1470
|
+
* @returns {boolean} True if the paths match
|
|
1471
|
+
*/
|
|
1503
1472
|
pathMatches(requestPath, handlerPath) {
|
|
1504
|
-
|
|
1505
|
-
const pathRegex = new RegExp(`^${pathRegexString}`);
|
|
1506
|
-
return pathRegex.test(requestPath);
|
|
1473
|
+
return this.pathPatternToRegex(handlerPath).test(requestPath);
|
|
1507
1474
|
}
|
|
1508
1475
|
/**
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1476
|
+
* @method extractPathParams
|
|
1477
|
+
* @private
|
|
1478
|
+
* @param {string} requestPath - The path from the request
|
|
1479
|
+
* @param {string} handlerPath - The path pattern from the handler
|
|
1480
|
+
* @description Extracts path parameters from the request path based on the handler pattern
|
|
1481
|
+
* @returns {Object} An object containing the path parameters
|
|
1482
|
+
*/
|
|
1516
1483
|
extractPathParams(requestPath, handlerPath) {
|
|
1517
1484
|
const params = {};
|
|
1518
1485
|
const paramNames = [];
|
|
@@ -1521,8 +1488,7 @@ var Server = class {
|
|
|
1521
1488
|
paramNames.push(segment.substring(1));
|
|
1522
1489
|
}
|
|
1523
1490
|
});
|
|
1524
|
-
const
|
|
1525
|
-
const pathRegex = new RegExp(`^${pathRegexString}`);
|
|
1491
|
+
const pathRegex = this.pathPatternToRegex(handlerPath);
|
|
1526
1492
|
const matches = requestPath.match(pathRegex);
|
|
1527
1493
|
if (matches && matches.length > 1) {
|
|
1528
1494
|
for (let i = 0; i < paramNames.length; i++) {
|
|
@@ -1531,15 +1497,32 @@ var Server = class {
|
|
|
1531
1497
|
}
|
|
1532
1498
|
return params;
|
|
1533
1499
|
}
|
|
1500
|
+
normalizeRequestPath(pathname) {
|
|
1501
|
+
const parts = pathname.split("/").filter(Boolean);
|
|
1502
|
+
if (parts[0] === "parties" && parts.length >= 3) {
|
|
1503
|
+
const routePath = parts.slice(3).join("/");
|
|
1504
|
+
return routePath ? `/${routePath}` : "/";
|
|
1505
|
+
}
|
|
1506
|
+
return pathname || "/";
|
|
1507
|
+
}
|
|
1508
|
+
pathPatternToRegex(handlerPath) {
|
|
1509
|
+
const segments = handlerPath.split("/").map((segment) => {
|
|
1510
|
+
if (segment.startsWith(":")) {
|
|
1511
|
+
return "([^/]+)";
|
|
1512
|
+
}
|
|
1513
|
+
return segment.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1514
|
+
});
|
|
1515
|
+
return new RegExp(`^${segments.join("/")}$`);
|
|
1516
|
+
}
|
|
1534
1517
|
/**
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1518
|
+
* @method handleShardRequest
|
|
1519
|
+
* @private
|
|
1520
|
+
* @async
|
|
1521
|
+
* @param {Party.Request} req - The HTTP request forwarded by a shard
|
|
1522
|
+
* @param {string | null} shardId - The ID of the shard that forwarded the request
|
|
1523
|
+
* @description Processes requests forwarded by shards, preserving client context
|
|
1524
|
+
* @returns {Promise<Response>} The response to return to the shard (which will forward it to the client)
|
|
1525
|
+
*/
|
|
1543
1526
|
async handleShardRequest(req, res, shardId) {
|
|
1544
1527
|
const subRoom = await this.getSubRoom();
|
|
1545
1528
|
if (!subRoom) {
|
|
@@ -1566,13 +1549,13 @@ var Server = class {
|
|
|
1566
1549
|
}
|
|
1567
1550
|
}
|
|
1568
1551
|
/**
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1552
|
+
* @method createEnhancedRequest
|
|
1553
|
+
* @private
|
|
1554
|
+
* @param {Party.Request} originalReq - The original request received from the shard
|
|
1555
|
+
* @param {string | null} originalClientIp - The original client IP, if available
|
|
1556
|
+
* @description Creates an enhanced request object that preserves the original client context
|
|
1557
|
+
* @returns {Party.Request} The enhanced request object
|
|
1558
|
+
*/
|
|
1576
1559
|
createEnhancedRequest(originalReq, originalClientIp) {
|
|
1577
1560
|
const clonedReq = originalReq.clone();
|
|
1578
1561
|
clonedReq.viaShard = true;
|
|
@@ -1585,18 +1568,6 @@ var Server = class {
|
|
|
1585
1568
|
|
|
1586
1569
|
// src/shard.ts
|
|
1587
1570
|
var Shard = class {
|
|
1588
|
-
static {
|
|
1589
|
-
__name(this, "Shard");
|
|
1590
|
-
}
|
|
1591
|
-
room;
|
|
1592
|
-
ws;
|
|
1593
|
-
connectionMap;
|
|
1594
|
-
mainServerStub;
|
|
1595
|
-
worldUrl;
|
|
1596
|
-
worldId;
|
|
1597
|
-
lastReportedConnections;
|
|
1598
|
-
statsInterval;
|
|
1599
|
-
statsIntervalId;
|
|
1600
1571
|
constructor(room) {
|
|
1601
1572
|
this.room = room;
|
|
1602
1573
|
this.connectionMap = /* @__PURE__ */ new Map();
|
|
@@ -1719,9 +1690,7 @@ var Shard = class {
|
|
|
1719
1690
|
})
|
|
1720
1691
|
});
|
|
1721
1692
|
if (!response2.ok) {
|
|
1722
|
-
const errorData = await response2.json().catch(() => ({
|
|
1723
|
-
error: "Unknown error"
|
|
1724
|
-
}));
|
|
1693
|
+
const errorData = await response2.json().catch(() => ({ error: "Unknown error" }));
|
|
1725
1694
|
console.error(`Failed to update World stats: ${response2.status} - ${errorData.error || "Unknown error"}`);
|
|
1726
1695
|
return false;
|
|
1727
1696
|
}
|
|
@@ -1733,17 +1702,15 @@ var Shard = class {
|
|
|
1733
1702
|
}
|
|
1734
1703
|
}
|
|
1735
1704
|
/**
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1705
|
+
* @method onRequest
|
|
1706
|
+
* @async
|
|
1707
|
+
* @param {Party.Request} req - The HTTP request to handle
|
|
1708
|
+
* @description Forwards HTTP requests to the main server, preserving client context
|
|
1709
|
+
* @returns {Promise<Response>} The response from the main server
|
|
1710
|
+
*/
|
|
1742
1711
|
async onRequest(req) {
|
|
1743
1712
|
if (!this.mainServerStub) {
|
|
1744
|
-
return response(503, {
|
|
1745
|
-
error: "Shard not connected to main server"
|
|
1746
|
-
});
|
|
1713
|
+
return response(503, { error: "Shard not connected to main server" });
|
|
1747
1714
|
}
|
|
1748
1715
|
try {
|
|
1749
1716
|
const url = new URL(req.url);
|
|
@@ -1771,32 +1738,28 @@ var Shard = class {
|
|
|
1771
1738
|
const response2 = await this.mainServerStub.fetch(path, requestInit);
|
|
1772
1739
|
return response2;
|
|
1773
1740
|
} catch (error) {
|
|
1774
|
-
return response(500, {
|
|
1775
|
-
error: "Error forwarding request"
|
|
1776
|
-
});
|
|
1741
|
+
return response(500, { error: "Error forwarding request" });
|
|
1777
1742
|
}
|
|
1778
1743
|
}
|
|
1779
1744
|
/**
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1745
|
+
* @method onAlarm
|
|
1746
|
+
* @async
|
|
1747
|
+
* @description Executed periodically, used to perform maintenance tasks
|
|
1748
|
+
*/
|
|
1784
1749
|
async onAlarm() {
|
|
1785
1750
|
await this.updateWorldStats();
|
|
1786
1751
|
}
|
|
1787
1752
|
};
|
|
1788
1753
|
|
|
1789
1754
|
// src/testing.ts
|
|
1790
|
-
async function testRoom(
|
|
1791
|
-
const createServer =
|
|
1755
|
+
async function testRoom(Room2, options = {}) {
|
|
1756
|
+
const createServer = (io2) => {
|
|
1792
1757
|
const server2 = new Server(io2);
|
|
1793
|
-
server2.rooms = [
|
|
1794
|
-
Room3
|
|
1795
|
-
];
|
|
1758
|
+
server2.rooms = [Room2];
|
|
1796
1759
|
return server2;
|
|
1797
|
-
}
|
|
1760
|
+
};
|
|
1798
1761
|
const isShard = options.shard || false;
|
|
1799
|
-
const io = new ServerIo(
|
|
1762
|
+
const io = new ServerIo(Room2.path, isShard ? {
|
|
1800
1763
|
parties: {
|
|
1801
1764
|
game: createServer,
|
|
1802
1765
|
...options.parties || {}
|
|
@@ -1808,9 +1771,9 @@ async function testRoom(Room3, options = {}) {
|
|
|
1808
1771
|
partyFn: options.partyFn,
|
|
1809
1772
|
env: options.env
|
|
1810
1773
|
});
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1774
|
+
Room2.prototype.throttleSync = 0;
|
|
1775
|
+
Room2.prototype.throttleStorage = 0;
|
|
1776
|
+
Room2.prototype.options = options;
|
|
1814
1777
|
let server;
|
|
1815
1778
|
if (options.shard) {
|
|
1816
1779
|
const shardServer = new Shard(io);
|
|
@@ -1835,41 +1798,31 @@ async function testRoom(Room3, options = {}) {
|
|
|
1835
1798
|
return {
|
|
1836
1799
|
server,
|
|
1837
1800
|
room: server.subRoom,
|
|
1838
|
-
createClient:
|
|
1801
|
+
createClient: async (id2, opts) => {
|
|
1839
1802
|
const client = await io.connection(server, id2, opts);
|
|
1840
1803
|
return client;
|
|
1841
|
-
},
|
|
1842
|
-
getServerUser:
|
|
1804
|
+
},
|
|
1805
|
+
getServerUser: async (client, prop = "users") => {
|
|
1843
1806
|
const privateId = client.conn.id;
|
|
1844
1807
|
const session = await server.getSession(privateId);
|
|
1845
1808
|
return server.subRoom[prop]()[session?.publicId];
|
|
1846
|
-
}
|
|
1809
|
+
}
|
|
1847
1810
|
};
|
|
1848
1811
|
}
|
|
1849
|
-
__name(testRoom, "testRoom");
|
|
1850
1812
|
async function request(room, path, options = {
|
|
1851
1813
|
method: "GET"
|
|
1852
1814
|
}) {
|
|
1853
1815
|
const url = new URL("http://localhost" + path);
|
|
1854
|
-
const
|
|
1855
|
-
const response2 = await room.onRequest(
|
|
1816
|
+
const request2 = new Request(url.toString(), options);
|
|
1817
|
+
const response2 = await room.onRequest(request2);
|
|
1856
1818
|
return response2;
|
|
1857
1819
|
}
|
|
1858
|
-
__name(request, "request");
|
|
1859
1820
|
function tick(ms = 0) {
|
|
1860
1821
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1861
1822
|
}
|
|
1862
|
-
__name(tick, "tick");
|
|
1863
1823
|
|
|
1864
1824
|
// src/mock.ts
|
|
1865
1825
|
var MockPartyClient = class {
|
|
1866
|
-
static {
|
|
1867
|
-
__name(this, "MockPartyClient");
|
|
1868
|
-
}
|
|
1869
|
-
server;
|
|
1870
|
-
events;
|
|
1871
|
-
id;
|
|
1872
|
-
conn;
|
|
1873
1826
|
constructor(server, id2) {
|
|
1874
1827
|
this.server = server;
|
|
1875
1828
|
this.events = /* @__PURE__ */ new Map();
|
|
@@ -1905,12 +1858,7 @@ var MockPartyClient = class {
|
|
|
1905
1858
|
return this.server.onMessage(JSON.stringify(data), this.conn);
|
|
1906
1859
|
}
|
|
1907
1860
|
};
|
|
1908
|
-
var MockLobby = class
|
|
1909
|
-
static {
|
|
1910
|
-
__name(this, "MockLobby");
|
|
1911
|
-
}
|
|
1912
|
-
server;
|
|
1913
|
-
lobbyId;
|
|
1861
|
+
var MockLobby = class {
|
|
1914
1862
|
constructor(server, lobbyId) {
|
|
1915
1863
|
this.server = server;
|
|
1916
1864
|
this.lobbyId = lobbyId;
|
|
@@ -1928,12 +1876,7 @@ var MockLobby = class MockLobby2 {
|
|
|
1928
1876
|
return request(this.server, baseUrl + url, options);
|
|
1929
1877
|
}
|
|
1930
1878
|
};
|
|
1931
|
-
var MockContext = class
|
|
1932
|
-
static {
|
|
1933
|
-
__name(this, "MockContext");
|
|
1934
|
-
}
|
|
1935
|
-
room;
|
|
1936
|
-
parties;
|
|
1879
|
+
var MockContext = class {
|
|
1937
1880
|
constructor(room, options = {}) {
|
|
1938
1881
|
this.room = room;
|
|
1939
1882
|
this.parties = {
|
|
@@ -1943,13 +1886,13 @@ var MockContext = class MockContext2 {
|
|
|
1943
1886
|
if (options.partyFn) {
|
|
1944
1887
|
const serverCache = /* @__PURE__ */ new Map();
|
|
1945
1888
|
this.parties.main = {
|
|
1946
|
-
get:
|
|
1889
|
+
get: async (lobbyId) => {
|
|
1947
1890
|
if (!serverCache.has(lobbyId)) {
|
|
1948
1891
|
const server = await options.partyFn(lobbyId);
|
|
1949
1892
|
serverCache.set(lobbyId, new MockLobby(server, lobbyId));
|
|
1950
1893
|
}
|
|
1951
1894
|
return serverCache.get(lobbyId);
|
|
1952
|
-
}
|
|
1895
|
+
}
|
|
1953
1896
|
};
|
|
1954
1897
|
} else {
|
|
1955
1898
|
for (let lobbyId in parties) {
|
|
@@ -1959,15 +1902,7 @@ var MockContext = class MockContext2 {
|
|
|
1959
1902
|
}
|
|
1960
1903
|
}
|
|
1961
1904
|
};
|
|
1962
|
-
var MockPartyRoom = class
|
|
1963
|
-
static {
|
|
1964
|
-
__name(this, "MockPartyRoom");
|
|
1965
|
-
}
|
|
1966
|
-
id;
|
|
1967
|
-
clients;
|
|
1968
|
-
storage;
|
|
1969
|
-
context;
|
|
1970
|
-
env;
|
|
1905
|
+
var MockPartyRoom = class {
|
|
1971
1906
|
constructor(id2, options = {}) {
|
|
1972
1907
|
this.id = id2;
|
|
1973
1908
|
this.clients = /* @__PURE__ */ new Map();
|
|
@@ -1995,9 +1930,7 @@ var MockPartyRoom = class MockPartyRoom2 {
|
|
|
1995
1930
|
...opts?.headers || {}
|
|
1996
1931
|
}
|
|
1997
1932
|
});
|
|
1998
|
-
await server.onConnect(socket.conn, {
|
|
1999
|
-
request: request2
|
|
2000
|
-
});
|
|
1933
|
+
await server.onConnect(socket.conn, { request: request2 });
|
|
2001
1934
|
this.clients.set(socket.id, socket);
|
|
2002
1935
|
return socket;
|
|
2003
1936
|
}
|
|
@@ -2017,19 +1950,12 @@ var MockPartyRoom = class MockPartyRoom2 {
|
|
|
2017
1950
|
}
|
|
2018
1951
|
};
|
|
2019
1952
|
var MockConnection = class {
|
|
2020
|
-
static {
|
|
2021
|
-
__name(this, "MockConnection");
|
|
2022
|
-
}
|
|
2023
|
-
client;
|
|
2024
|
-
server;
|
|
2025
|
-
id;
|
|
2026
1953
|
constructor(client) {
|
|
2027
1954
|
this.client = client;
|
|
2028
1955
|
this.state = {};
|
|
2029
1956
|
this.server = client.server;
|
|
2030
1957
|
this.id = client.id;
|
|
2031
1958
|
}
|
|
2032
|
-
state;
|
|
2033
1959
|
setState(value) {
|
|
2034
1960
|
this.state = value;
|
|
2035
1961
|
}
|
|
@@ -2048,17 +1974,8 @@ import { signal } from "@signe/reactive";
|
|
|
2048
1974
|
import { sync, id, persist } from "@signe/sync";
|
|
2049
1975
|
import { z as z2 } from "zod";
|
|
2050
1976
|
|
|
2051
|
-
// src/types/party.ts
|
|
2052
|
-
var party_exports = {};
|
|
2053
|
-
|
|
2054
1977
|
// src/jwt.ts
|
|
2055
1978
|
var JWTAuth = class {
|
|
2056
|
-
static {
|
|
2057
|
-
__name(this, "JWTAuth");
|
|
2058
|
-
}
|
|
2059
|
-
secret;
|
|
2060
|
-
encoder;
|
|
2061
|
-
decoder;
|
|
2062
1979
|
/**
|
|
2063
1980
|
* Constructor for the JWTAuth class
|
|
2064
1981
|
* @param {string} secret - The secret key used for signing and verifying tokens
|
|
@@ -2079,18 +1996,16 @@ var JWTAuth = class {
|
|
|
2079
1996
|
const keyData = this.encoder.encode(this.secret);
|
|
2080
1997
|
return await crypto.subtle.importKey(
|
|
2081
1998
|
"raw",
|
|
1999
|
+
// format
|
|
2082
2000
|
keyData,
|
|
2001
|
+
// key data
|
|
2083
2002
|
{
|
|
2084
2003
|
name: "HMAC",
|
|
2085
|
-
hash: {
|
|
2086
|
-
name: "SHA-256"
|
|
2087
|
-
}
|
|
2004
|
+
hash: { name: "SHA-256" }
|
|
2088
2005
|
},
|
|
2089
2006
|
false,
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
"verify"
|
|
2093
|
-
]
|
|
2007
|
+
// extractable
|
|
2008
|
+
["sign", "verify"]
|
|
2094
2009
|
// key usages
|
|
2095
2010
|
);
|
|
2096
2011
|
}
|
|
@@ -2162,9 +2077,11 @@ var JWTAuth = class {
|
|
|
2162
2077
|
const encodedPayload = this.base64UrlEncode(this.encoder.encode(JSON.stringify(fullPayload)));
|
|
2163
2078
|
const signatureBase = `${encodedHeader}.${encodedPayload}`;
|
|
2164
2079
|
const key = await this.getSecretKey();
|
|
2165
|
-
const signature = await crypto.subtle.sign(
|
|
2166
|
-
name: "HMAC"
|
|
2167
|
-
|
|
2080
|
+
const signature = await crypto.subtle.sign(
|
|
2081
|
+
{ name: "HMAC" },
|
|
2082
|
+
key,
|
|
2083
|
+
this.encoder.encode(signatureBase)
|
|
2084
|
+
);
|
|
2168
2085
|
const encodedSignature = this.base64UrlEncode(signature);
|
|
2169
2086
|
return `${signatureBase}.${encodedSignature}`;
|
|
2170
2087
|
}
|
|
@@ -2196,9 +2113,12 @@ var JWTAuth = class {
|
|
|
2196
2113
|
const key = await this.getSecretKey();
|
|
2197
2114
|
const signatureBase = `${encodedHeader}.${encodedPayload}`;
|
|
2198
2115
|
const signature = this.base64UrlDecode(encodedSignature);
|
|
2199
|
-
const isValid = await crypto.subtle.verify(
|
|
2200
|
-
name: "HMAC"
|
|
2201
|
-
|
|
2116
|
+
const isValid = await crypto.subtle.verify(
|
|
2117
|
+
{ name: "HMAC" },
|
|
2118
|
+
key,
|
|
2119
|
+
signature,
|
|
2120
|
+
this.encoder.encode(signatureBase)
|
|
2121
|
+
);
|
|
2202
2122
|
if (!isValid) {
|
|
2203
2123
|
throw new Error("Invalid signature");
|
|
2204
2124
|
}
|
|
@@ -2213,7 +2133,7 @@ var JWTAuth = class {
|
|
|
2213
2133
|
};
|
|
2214
2134
|
|
|
2215
2135
|
// src/world.guard.ts
|
|
2216
|
-
var guardManageWorld =
|
|
2136
|
+
var guardManageWorld = async (_, req, room) => {
|
|
2217
2137
|
const tokenShard = req.headers.get("x-access-shard");
|
|
2218
2138
|
if (tokenShard) {
|
|
2219
2139
|
if (tokenShard !== room.env.SHARD_SECRET) {
|
|
@@ -2236,46 +2156,22 @@ var guardManageWorld = /* @__PURE__ */ __name(async (_, req, room) => {
|
|
|
2236
2156
|
return false;
|
|
2237
2157
|
}
|
|
2238
2158
|
return true;
|
|
2239
|
-
}
|
|
2159
|
+
};
|
|
2240
2160
|
|
|
2241
2161
|
// src/world.ts
|
|
2242
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
2243
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2244
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2245
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2246
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2247
|
-
}
|
|
2248
|
-
__name(_ts_decorate, "_ts_decorate");
|
|
2249
|
-
function _ts_metadata(k, v) {
|
|
2250
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2251
|
-
}
|
|
2252
|
-
__name(_ts_metadata, "_ts_metadata");
|
|
2253
2162
|
var MAX_PLAYERS_PER_SHARD = 75;
|
|
2254
2163
|
var RoomConfigSchema = z2.object({
|
|
2255
2164
|
name: z2.string(),
|
|
2256
|
-
balancingStrategy: z2.enum([
|
|
2257
|
-
"round-robin",
|
|
2258
|
-
"least-connections",
|
|
2259
|
-
"random"
|
|
2260
|
-
]),
|
|
2165
|
+
balancingStrategy: z2.enum(["round-robin", "least-connections", "random"]),
|
|
2261
2166
|
public: z2.boolean(),
|
|
2262
2167
|
maxPlayersPerShard: z2.number().int().positive(),
|
|
2263
2168
|
minShards: z2.number().int().min(0),
|
|
2264
2169
|
maxShards: z2.number().int().positive().optional()
|
|
2265
2170
|
});
|
|
2266
|
-
var RegisterShardSchema = z2.object({
|
|
2267
|
-
shardId: z2.string(),
|
|
2268
|
-
roomId: z2.string(),
|
|
2269
|
-
url: z2.string().url(),
|
|
2270
|
-
maxConnections: z2.number().int().positive()
|
|
2271
|
-
});
|
|
2272
2171
|
var UpdateShardStatsSchema = z2.object({
|
|
2172
|
+
shardId: z2.string(),
|
|
2273
2173
|
connections: z2.number().int().min(0),
|
|
2274
|
-
status: z2.enum([
|
|
2275
|
-
"active",
|
|
2276
|
-
"maintenance",
|
|
2277
|
-
"draining"
|
|
2278
|
-
]).optional()
|
|
2174
|
+
status: z2.enum(["active", "maintenance", "draining"]).optional()
|
|
2279
2175
|
});
|
|
2280
2176
|
var ScaleRoomSchema = z2.object({
|
|
2281
2177
|
roomId: z2.string(),
|
|
@@ -2285,94 +2181,77 @@ var ScaleRoomSchema = z2.object({
|
|
|
2285
2181
|
maxConnections: z2.number().int().positive()
|
|
2286
2182
|
}).optional()
|
|
2287
2183
|
});
|
|
2288
|
-
var RoomConfig = class
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
minShards = signal(1);
|
|
2298
|
-
maxShards = signal(void 0);
|
|
2184
|
+
var RoomConfig = class {
|
|
2185
|
+
constructor() {
|
|
2186
|
+
this.name = signal("");
|
|
2187
|
+
this.balancingStrategy = signal("round-robin");
|
|
2188
|
+
this.public = signal(true);
|
|
2189
|
+
this.maxPlayersPerShard = signal(MAX_PLAYERS_PER_SHARD);
|
|
2190
|
+
this.minShards = signal(1);
|
|
2191
|
+
this.maxShards = signal(void 0);
|
|
2192
|
+
}
|
|
2299
2193
|
};
|
|
2300
|
-
|
|
2301
|
-
id()
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
_ts_decorate([
|
|
2194
|
+
__decorateClass([
|
|
2195
|
+
id()
|
|
2196
|
+
], RoomConfig.prototype, "id", 2);
|
|
2197
|
+
__decorateClass([
|
|
2305
2198
|
sync()
|
|
2306
|
-
], RoomConfig.prototype, "name",
|
|
2307
|
-
|
|
2199
|
+
], RoomConfig.prototype, "name", 2);
|
|
2200
|
+
__decorateClass([
|
|
2308
2201
|
sync()
|
|
2309
|
-
], RoomConfig.prototype, "balancingStrategy",
|
|
2310
|
-
|
|
2202
|
+
], RoomConfig.prototype, "balancingStrategy", 2);
|
|
2203
|
+
__decorateClass([
|
|
2311
2204
|
sync()
|
|
2312
|
-
], RoomConfig.prototype, "public",
|
|
2313
|
-
|
|
2205
|
+
], RoomConfig.prototype, "public", 2);
|
|
2206
|
+
__decorateClass([
|
|
2314
2207
|
sync()
|
|
2315
|
-
], RoomConfig.prototype, "maxPlayersPerShard",
|
|
2316
|
-
|
|
2208
|
+
], RoomConfig.prototype, "maxPlayersPerShard", 2);
|
|
2209
|
+
__decorateClass([
|
|
2317
2210
|
sync()
|
|
2318
|
-
], RoomConfig.prototype, "minShards",
|
|
2319
|
-
|
|
2211
|
+
], RoomConfig.prototype, "minShards", 2);
|
|
2212
|
+
__decorateClass([
|
|
2320
2213
|
sync()
|
|
2321
|
-
], RoomConfig.prototype, "maxShards",
|
|
2322
|
-
var ShardInfo = class
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
status = signal("active");
|
|
2332
|
-
lastHeartbeat = signal(0);
|
|
2214
|
+
], RoomConfig.prototype, "maxShards", 2);
|
|
2215
|
+
var ShardInfo = class {
|
|
2216
|
+
constructor() {
|
|
2217
|
+
this.roomId = signal("");
|
|
2218
|
+
this.url = signal("");
|
|
2219
|
+
this.currentConnections = signal(0);
|
|
2220
|
+
this.maxConnections = signal(MAX_PLAYERS_PER_SHARD);
|
|
2221
|
+
this.status = signal("active");
|
|
2222
|
+
this.lastHeartbeat = signal(0);
|
|
2223
|
+
}
|
|
2333
2224
|
};
|
|
2334
|
-
|
|
2335
|
-
id()
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
_ts_decorate([
|
|
2225
|
+
__decorateClass([
|
|
2226
|
+
id()
|
|
2227
|
+
], ShardInfo.prototype, "id", 2);
|
|
2228
|
+
__decorateClass([
|
|
2339
2229
|
sync()
|
|
2340
|
-
], ShardInfo.prototype, "roomId",
|
|
2341
|
-
|
|
2230
|
+
], ShardInfo.prototype, "roomId", 2);
|
|
2231
|
+
__decorateClass([
|
|
2342
2232
|
sync()
|
|
2343
|
-
], ShardInfo.prototype, "url",
|
|
2344
|
-
|
|
2233
|
+
], ShardInfo.prototype, "url", 2);
|
|
2234
|
+
__decorateClass([
|
|
2345
2235
|
sync({
|
|
2346
2236
|
persist: false
|
|
2347
2237
|
})
|
|
2348
|
-
], ShardInfo.prototype, "currentConnections",
|
|
2349
|
-
|
|
2238
|
+
], ShardInfo.prototype, "currentConnections", 2);
|
|
2239
|
+
__decorateClass([
|
|
2350
2240
|
sync()
|
|
2351
|
-
], ShardInfo.prototype, "maxConnections",
|
|
2352
|
-
|
|
2241
|
+
], ShardInfo.prototype, "maxConnections", 2);
|
|
2242
|
+
__decorateClass([
|
|
2353
2243
|
sync()
|
|
2354
|
-
], ShardInfo.prototype, "status",
|
|
2355
|
-
|
|
2244
|
+
], ShardInfo.prototype, "status", 2);
|
|
2245
|
+
__decorateClass([
|
|
2356
2246
|
sync()
|
|
2357
|
-
], ShardInfo.prototype, "lastHeartbeat",
|
|
2247
|
+
], ShardInfo.prototype, "lastHeartbeat", 2);
|
|
2358
2248
|
var WorldRoom = class {
|
|
2359
|
-
static {
|
|
2360
|
-
__name(this, "WorldRoom");
|
|
2361
|
-
}
|
|
2362
|
-
room;
|
|
2363
|
-
// Synchronized state
|
|
2364
|
-
rooms;
|
|
2365
|
-
shards;
|
|
2366
|
-
// Only persisted state (not synced to clients)
|
|
2367
|
-
rrCounters;
|
|
2368
|
-
// Configuration
|
|
2369
|
-
defaultShardUrlTemplate;
|
|
2370
|
-
defaultMaxConnectionsPerShard;
|
|
2371
2249
|
constructor(room) {
|
|
2372
2250
|
this.room = room;
|
|
2373
2251
|
this.rooms = signal({});
|
|
2374
2252
|
this.shards = signal({});
|
|
2375
2253
|
this.rrCounters = signal({});
|
|
2254
|
+
// Configuration
|
|
2376
2255
|
this.defaultShardUrlTemplate = signal("{shardId}");
|
|
2377
2256
|
this.defaultMaxConnectionsPerShard = signal(MAX_PLAYERS_PER_SHARD);
|
|
2378
2257
|
const { AUTH_JWT_SECRET, SHARD_SECRET } = this.room.env;
|
|
@@ -2410,9 +2289,14 @@ var WorldRoom = class {
|
|
|
2410
2289
|
});
|
|
2411
2290
|
setTimeout(() => this.cleanupInactiveShards(), 6e4);
|
|
2412
2291
|
}
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2292
|
+
async registerRoom(req, res) {
|
|
2293
|
+
const roomConfigResult = RoomConfigSchema.safeParse(await req.json());
|
|
2294
|
+
if (!roomConfigResult.success) {
|
|
2295
|
+
return res?.badRequest("Invalid room configuration", {
|
|
2296
|
+
details: roomConfigResult.error
|
|
2297
|
+
});
|
|
2298
|
+
}
|
|
2299
|
+
const roomConfig = roomConfigResult.data;
|
|
2416
2300
|
const roomId = roomConfig.name;
|
|
2417
2301
|
if (!this.rooms()[roomId]) {
|
|
2418
2302
|
const newRoom = new RoomConfig();
|
|
@@ -2439,7 +2323,13 @@ var WorldRoom = class {
|
|
|
2439
2323
|
}
|
|
2440
2324
|
}
|
|
2441
2325
|
async updateShardStats(req, res) {
|
|
2442
|
-
const
|
|
2326
|
+
const bodyResult = UpdateShardStatsSchema.safeParse(await req.json());
|
|
2327
|
+
if (!bodyResult.success) {
|
|
2328
|
+
return res.badRequest("Invalid shard statistics", {
|
|
2329
|
+
details: bodyResult.error
|
|
2330
|
+
});
|
|
2331
|
+
}
|
|
2332
|
+
const body = bodyResult.data;
|
|
2443
2333
|
const { shardId, connections, status } = body;
|
|
2444
2334
|
const shard = this.shards()[shardId];
|
|
2445
2335
|
if (!shard) {
|
|
@@ -2452,7 +2342,13 @@ var WorldRoom = class {
|
|
|
2452
2342
|
shard.lastHeartbeat.set(Date.now());
|
|
2453
2343
|
}
|
|
2454
2344
|
async scaleRoom(req, res) {
|
|
2455
|
-
const
|
|
2345
|
+
const dataResult = ScaleRoomSchema.safeParse(await req.json());
|
|
2346
|
+
if (!dataResult.success) {
|
|
2347
|
+
return res.badRequest("Invalid scale request", {
|
|
2348
|
+
details: dataResult.error
|
|
2349
|
+
});
|
|
2350
|
+
}
|
|
2351
|
+
const data = dataResult.data;
|
|
2456
2352
|
const { targetShardCount, shardTemplate, roomId } = data;
|
|
2457
2353
|
const room = this.rooms()[roomId];
|
|
2458
2354
|
if (!room) {
|
|
@@ -2467,14 +2363,11 @@ var WorldRoom = class {
|
|
|
2467
2363
|
});
|
|
2468
2364
|
}
|
|
2469
2365
|
if (targetShardCount < previousShardCount) {
|
|
2470
|
-
const shardsToRemove = [
|
|
2471
|
-
...roomShards
|
|
2472
|
-
].sort((a, b) => {
|
|
2366
|
+
const shardsToRemove = [...roomShards].sort((a, b) => {
|
|
2473
2367
|
if (a.status() === "draining" && b.status() !== "draining") return -1;
|
|
2474
2368
|
if (a.status() !== "draining" && b.status() === "draining") return 1;
|
|
2475
2369
|
return a.currentConnections() - b.currentConnections();
|
|
2476
2370
|
}).slice(0, previousShardCount - targetShardCount);
|
|
2477
|
-
const shardsToKeep = roomShards.filter((shard) => !shardsToRemove.some((s) => s.id === shard.id));
|
|
2478
2371
|
for (const shard of shardsToRemove) {
|
|
2479
2372
|
delete this.shards()[shard.id];
|
|
2480
2373
|
}
|
|
@@ -2483,7 +2376,11 @@ var WorldRoom = class {
|
|
|
2483
2376
|
if (targetShardCount > previousShardCount) {
|
|
2484
2377
|
const newShards = [];
|
|
2485
2378
|
for (let i = 0; i < targetShardCount - previousShardCount; i++) {
|
|
2486
|
-
const newShard = await this.createShard(
|
|
2379
|
+
const newShard = await this.createShard(
|
|
2380
|
+
roomId,
|
|
2381
|
+
shardTemplate?.urlTemplate,
|
|
2382
|
+
shardTemplate?.maxConnections
|
|
2383
|
+
);
|
|
2487
2384
|
if (newShard) {
|
|
2488
2385
|
newShards.push(newShard);
|
|
2489
2386
|
}
|
|
@@ -2525,26 +2422,22 @@ var WorldRoom = class {
|
|
|
2525
2422
|
if (!room) {
|
|
2526
2423
|
if (autoCreate) {
|
|
2527
2424
|
const mockRequest = {
|
|
2528
|
-
json:
|
|
2425
|
+
json: async () => ({
|
|
2529
2426
|
name: roomId,
|
|
2530
2427
|
balancingStrategy: "round-robin",
|
|
2531
2428
|
public: true,
|
|
2532
2429
|
maxPlayersPerShard: this.defaultMaxConnectionsPerShard(),
|
|
2533
2430
|
minShards: 1,
|
|
2534
2431
|
maxShards: void 0
|
|
2535
|
-
})
|
|
2432
|
+
})
|
|
2536
2433
|
};
|
|
2537
2434
|
await this.registerRoom(mockRequest);
|
|
2538
2435
|
room = this.rooms()[roomId];
|
|
2539
2436
|
if (!room) {
|
|
2540
|
-
return {
|
|
2541
|
-
error: `Failed to create room ${roomId}`
|
|
2542
|
-
};
|
|
2437
|
+
return { error: `Failed to create room ${roomId}` };
|
|
2543
2438
|
}
|
|
2544
2439
|
} else {
|
|
2545
|
-
return {
|
|
2546
|
-
error: `Room ${roomId} does not exist`
|
|
2547
|
-
};
|
|
2440
|
+
return { error: `Room ${roomId} does not exist` };
|
|
2548
2441
|
}
|
|
2549
2442
|
}
|
|
2550
2443
|
const roomShards = Object.values(this.shards()).filter((shard) => shard.roomId() === roomId);
|
|
@@ -2557,27 +2450,24 @@ var WorldRoom = class {
|
|
|
2557
2450
|
url: newShard.url()
|
|
2558
2451
|
};
|
|
2559
2452
|
} else {
|
|
2560
|
-
return {
|
|
2561
|
-
error: `Failed to create shard for room ${roomId}`
|
|
2562
|
-
};
|
|
2453
|
+
return { error: `Failed to create shard for room ${roomId}` };
|
|
2563
2454
|
}
|
|
2564
2455
|
} else {
|
|
2565
|
-
return {
|
|
2566
|
-
error: `No shards available for room ${roomId}`
|
|
2567
|
-
};
|
|
2456
|
+
return { error: `No shards available for room ${roomId}` };
|
|
2568
2457
|
}
|
|
2569
2458
|
}
|
|
2570
2459
|
const activeShards = roomShards.filter((shard) => shard && shard.status() === "active");
|
|
2571
2460
|
if (activeShards.length === 0) {
|
|
2572
|
-
return {
|
|
2573
|
-
error: `No active shards available for room ${roomId}`
|
|
2574
|
-
};
|
|
2461
|
+
return { error: `No active shards available for room ${roomId}` };
|
|
2575
2462
|
}
|
|
2576
2463
|
const balancingStrategy = room.balancingStrategy();
|
|
2577
2464
|
let selectedShard;
|
|
2578
2465
|
switch (balancingStrategy) {
|
|
2579
2466
|
case "least-connections":
|
|
2580
|
-
selectedShard = activeShards.reduce(
|
|
2467
|
+
selectedShard = activeShards.reduce(
|
|
2468
|
+
(min, shard) => shard.currentConnections() < min.currentConnections() ? shard : min,
|
|
2469
|
+
activeShards[0]
|
|
2470
|
+
);
|
|
2581
2471
|
break;
|
|
2582
2472
|
case "random":
|
|
2583
2473
|
selectedShard = activeShards[Math.floor(Math.random() * activeShards.length)];
|
|
@@ -2618,82 +2508,52 @@ var WorldRoom = class {
|
|
|
2618
2508
|
return newShard;
|
|
2619
2509
|
}
|
|
2620
2510
|
};
|
|
2621
|
-
|
|
2511
|
+
__decorateClass([
|
|
2622
2512
|
sync(RoomConfig)
|
|
2623
|
-
], WorldRoom.prototype, "rooms",
|
|
2624
|
-
|
|
2513
|
+
], WorldRoom.prototype, "rooms", 2);
|
|
2514
|
+
__decorateClass([
|
|
2625
2515
|
sync(ShardInfo)
|
|
2626
|
-
], WorldRoom.prototype, "shards",
|
|
2627
|
-
|
|
2516
|
+
], WorldRoom.prototype, "shards", 2);
|
|
2517
|
+
__decorateClass([
|
|
2628
2518
|
persist()
|
|
2629
|
-
], WorldRoom.prototype, "rrCounters",
|
|
2630
|
-
|
|
2519
|
+
], WorldRoom.prototype, "rrCounters", 2);
|
|
2520
|
+
__decorateClass([
|
|
2631
2521
|
Request2({
|
|
2632
2522
|
path: "register-room",
|
|
2633
2523
|
method: "POST"
|
|
2634
2524
|
}),
|
|
2635
|
-
Guard([
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
_ts_metadata("design:type", Function),
|
|
2639
|
-
_ts_metadata("design:paramtypes", [
|
|
2640
|
-
typeof party_exports === "undefined" || typeof void 0 === "undefined" ? Object : void 0
|
|
2641
|
-
]),
|
|
2642
|
-
_ts_metadata("design:returntype", Promise)
|
|
2643
|
-
], WorldRoom.prototype, "registerRoom", null);
|
|
2644
|
-
_ts_decorate([
|
|
2525
|
+
Guard([guardManageWorld])
|
|
2526
|
+
], WorldRoom.prototype, "registerRoom", 1);
|
|
2527
|
+
__decorateClass([
|
|
2645
2528
|
Request2({
|
|
2646
2529
|
path: "update-shard",
|
|
2647
2530
|
method: "POST"
|
|
2648
2531
|
}),
|
|
2649
|
-
Guard([
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
_ts_metadata("design:type", Function),
|
|
2653
|
-
_ts_metadata("design:paramtypes", [
|
|
2654
|
-
typeof party_exports === "undefined" || typeof void 0 === "undefined" ? Object : void 0,
|
|
2655
|
-
typeof ServerResponse === "undefined" ? Object : ServerResponse
|
|
2656
|
-
]),
|
|
2657
|
-
_ts_metadata("design:returntype", Promise)
|
|
2658
|
-
], WorldRoom.prototype, "updateShardStats", null);
|
|
2659
|
-
_ts_decorate([
|
|
2532
|
+
Guard([guardManageWorld])
|
|
2533
|
+
], WorldRoom.prototype, "updateShardStats", 1);
|
|
2534
|
+
__decorateClass([
|
|
2660
2535
|
Request2({
|
|
2661
2536
|
path: "scale-room",
|
|
2662
2537
|
method: "POST"
|
|
2663
2538
|
}),
|
|
2664
|
-
Guard([
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
_ts_metadata("design:type", Function),
|
|
2668
|
-
_ts_metadata("design:paramtypes", [
|
|
2669
|
-
typeof party_exports === "undefined" || typeof void 0 === "undefined" ? Object : void 0,
|
|
2670
|
-
typeof ServerResponse === "undefined" ? Object : ServerResponse
|
|
2671
|
-
]),
|
|
2672
|
-
_ts_metadata("design:returntype", Promise)
|
|
2673
|
-
], WorldRoom.prototype, "scaleRoom", null);
|
|
2674
|
-
_ts_decorate([
|
|
2539
|
+
Guard([guardManageWorld])
|
|
2540
|
+
], WorldRoom.prototype, "scaleRoom", 1);
|
|
2541
|
+
__decorateClass([
|
|
2675
2542
|
Request2({
|
|
2676
2543
|
path: "connect",
|
|
2677
2544
|
method: "POST"
|
|
2678
|
-
})
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
typeof party_exports === "undefined" || typeof void 0 === "undefined" ? Object : void 0,
|
|
2682
|
-
typeof ServerResponse === "undefined" ? Object : ServerResponse
|
|
2683
|
-
]),
|
|
2684
|
-
_ts_metadata("design:returntype", Promise)
|
|
2685
|
-
], WorldRoom.prototype, "connect", null);
|
|
2686
|
-
WorldRoom = _ts_decorate([
|
|
2545
|
+
})
|
|
2546
|
+
], WorldRoom.prototype, "connect", 1);
|
|
2547
|
+
WorldRoom = __decorateClass([
|
|
2687
2548
|
Room({
|
|
2688
2549
|
path: "world-{worldId}",
|
|
2689
2550
|
maxUsers: 100,
|
|
2551
|
+
// Limit for admin connections
|
|
2690
2552
|
throttleStorage: 2e3,
|
|
2553
|
+
// Throttle storage updates (ms)
|
|
2691
2554
|
throttleSync: 500
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
_ts_metadata("design:paramtypes", [
|
|
2695
|
-
typeof party_exports === "undefined" || typeof void 0 === "undefined" ? Object : void 0
|
|
2696
|
-
])
|
|
2555
|
+
// Throttle sync updates (ms)
|
|
2556
|
+
})
|
|
2697
2557
|
], WorldRoom);
|
|
2698
2558
|
|
|
2699
2559
|
// src/session.guard.ts
|
|
@@ -2718,8 +2578,7 @@ function createRequireSessionGuard(storage) {
|
|
|
2718
2578
|
}
|
|
2719
2579
|
};
|
|
2720
2580
|
}
|
|
2721
|
-
|
|
2722
|
-
var requireSession = /* @__PURE__ */ __name(async (sender, value, room) => {
|
|
2581
|
+
var requireSession = async (sender, value, room) => {
|
|
2723
2582
|
if (!sender || !sender.id) {
|
|
2724
2583
|
return false;
|
|
2725
2584
|
}
|
|
@@ -2737,7 +2596,7 @@ var requireSession = /* @__PURE__ */ __name(async (sender, value, room) => {
|
|
|
2737
2596
|
console.error("Error checking session in requireSession guard:", error);
|
|
2738
2597
|
return false;
|
|
2739
2598
|
}
|
|
2740
|
-
}
|
|
2599
|
+
};
|
|
2741
2600
|
export {
|
|
2742
2601
|
Action,
|
|
2743
2602
|
ClientIo,
|