@signe/room 2.8.3 → 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 +9 -2
- package/dist/index.js +570 -692
- package/dist/index.js.map +1 -1
- package/package.json +10 -4
- package/readme.md +55 -6
- package/src/decorators.ts +13 -1
- package/src/jwt.ts +1 -5
- package/src/server.ts +79 -52
- 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,13 @@ function Action(name, bodyValidation) {
|
|
|
13
21
|
});
|
|
14
22
|
};
|
|
15
23
|
}
|
|
16
|
-
|
|
24
|
+
function UnhandledAction() {
|
|
25
|
+
return function(target, propertyKey) {
|
|
26
|
+
target.constructor._unhandledActionMetadata = {
|
|
27
|
+
key: propertyKey
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
}
|
|
17
31
|
function Request2(options, bodyValidation) {
|
|
18
32
|
return function(target, propertyKey) {
|
|
19
33
|
if (!target.constructor._requestMetadata) {
|
|
@@ -30,7 +44,6 @@ function Request2(options, bodyValidation) {
|
|
|
30
44
|
});
|
|
31
45
|
};
|
|
32
46
|
}
|
|
33
|
-
__name(Request2, "Request");
|
|
34
47
|
function Room(options) {
|
|
35
48
|
return function(target) {
|
|
36
49
|
target.path = options.path;
|
|
@@ -43,46 +56,40 @@ function Room(options) {
|
|
|
43
56
|
}
|
|
44
57
|
};
|
|
45
58
|
}
|
|
46
|
-
__name(Room, "Room");
|
|
47
59
|
function RoomGuard(guards) {
|
|
48
60
|
return function(target) {
|
|
49
61
|
target["_roomGuards"] = guards;
|
|
50
62
|
};
|
|
51
63
|
}
|
|
52
|
-
__name(RoomGuard, "RoomGuard");
|
|
53
64
|
function Guard(guards) {
|
|
54
65
|
return function(target, propertyKey, descriptor) {
|
|
55
66
|
if (!target.constructor["_actionGuards"]) {
|
|
56
67
|
target.constructor["_actionGuards"] = /* @__PURE__ */ new Map();
|
|
57
68
|
}
|
|
58
69
|
if (!Array.isArray(guards)) {
|
|
59
|
-
guards = [
|
|
60
|
-
guards
|
|
61
|
-
];
|
|
70
|
+
guards = [guards];
|
|
62
71
|
}
|
|
63
72
|
target.constructor["_actionGuards"].set(propertyKey, guards);
|
|
64
73
|
};
|
|
65
74
|
}
|
|
66
|
-
__name(Guard, "Guard");
|
|
67
75
|
|
|
68
76
|
// ../sync/src/utils.ts
|
|
69
77
|
function generateShortUUID() {
|
|
70
78
|
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
79
|
+
const randomBytes = typeof globalThis.crypto?.getRandomValues === "function" ? globalThis.crypto.getRandomValues(new Uint8Array(8)) : null;
|
|
71
80
|
let uuid = "";
|
|
72
81
|
for (let i = 0; i < 8; i++) {
|
|
73
|
-
const
|
|
74
|
-
uuid += chars[
|
|
82
|
+
const randomValue = randomBytes?.[i] ?? Math.floor(Math.random() * 256);
|
|
83
|
+
uuid += chars[randomValue % chars.length];
|
|
75
84
|
}
|
|
76
85
|
return uuid;
|
|
77
86
|
}
|
|
78
|
-
__name(generateShortUUID, "generateShortUUID");
|
|
79
87
|
|
|
80
88
|
// src/storage.ts
|
|
81
89
|
var Storage = class {
|
|
82
|
-
|
|
83
|
-
|
|
90
|
+
constructor() {
|
|
91
|
+
this.memory = /* @__PURE__ */ new Map();
|
|
84
92
|
}
|
|
85
|
-
memory = /* @__PURE__ */ new Map();
|
|
86
93
|
async put(key, value) {
|
|
87
94
|
this.memory.set(key, value);
|
|
88
95
|
}
|
|
@@ -100,22 +107,27 @@ var Storage = class {
|
|
|
100
107
|
// src/server.ts
|
|
101
108
|
import { dset as dset2 } from "dset";
|
|
102
109
|
import z from "zod";
|
|
103
|
-
import {
|
|
110
|
+
import {
|
|
111
|
+
createStatesSnapshot,
|
|
112
|
+
getByPath,
|
|
113
|
+
load,
|
|
114
|
+
syncClass,
|
|
115
|
+
DELETE_TOKEN,
|
|
116
|
+
generateShortUUID as generateShortUUID2,
|
|
117
|
+
createStatesSnapshotDeep
|
|
118
|
+
} from "@signe/sync";
|
|
104
119
|
|
|
105
120
|
// src/utils.ts
|
|
106
121
|
import { dset } from "dset";
|
|
107
122
|
function isPromise(value) {
|
|
108
123
|
return value instanceof Promise;
|
|
109
124
|
}
|
|
110
|
-
__name(isPromise, "isPromise");
|
|
111
125
|
async function awaitReturn(val) {
|
|
112
126
|
return isPromise(val) ? await val : val;
|
|
113
127
|
}
|
|
114
|
-
__name(awaitReturn, "awaitReturn");
|
|
115
128
|
function isClass(obj) {
|
|
116
129
|
return typeof obj === "function" && obj.prototype && obj.prototype.constructor === obj;
|
|
117
130
|
}
|
|
118
|
-
__name(isClass, "isClass");
|
|
119
131
|
function throttle(func, wait) {
|
|
120
132
|
let timeout = null;
|
|
121
133
|
let lastArgs = null;
|
|
@@ -134,7 +146,6 @@ function throttle(func, wait) {
|
|
|
134
146
|
}
|
|
135
147
|
};
|
|
136
148
|
}
|
|
137
|
-
__name(throttle, "throttle");
|
|
138
149
|
function extractParams(pattern, str) {
|
|
139
150
|
const regexPattern = pattern.replace(/{(\w+)}/g, "(?<$1>[\\w-]+)");
|
|
140
151
|
const regex = new RegExp(`^${regexPattern}$`);
|
|
@@ -147,7 +158,6 @@ function extractParams(pattern, str) {
|
|
|
147
158
|
return null;
|
|
148
159
|
}
|
|
149
160
|
}
|
|
150
|
-
__name(extractParams, "extractParams");
|
|
151
161
|
function dremove(obj, keys) {
|
|
152
162
|
if (typeof keys === "string") {
|
|
153
163
|
keys = keys.split(".");
|
|
@@ -167,7 +177,6 @@ function dremove(obj, keys) {
|
|
|
167
177
|
delete t[k];
|
|
168
178
|
}
|
|
169
179
|
}
|
|
170
|
-
__name(dremove, "dremove");
|
|
171
180
|
function buildObject(valuesMap, allMemory) {
|
|
172
181
|
let memoryObj = {};
|
|
173
182
|
for (let path of valuesMap.keys()) {
|
|
@@ -181,33 +190,25 @@ function buildObject(valuesMap, allMemory) {
|
|
|
181
190
|
}
|
|
182
191
|
return memoryObj;
|
|
183
192
|
}
|
|
184
|
-
__name(buildObject, "buildObject");
|
|
185
193
|
function response(status, body) {
|
|
186
194
|
return new Response(JSON.stringify(body), {
|
|
187
195
|
status,
|
|
188
|
-
headers: {
|
|
189
|
-
"Content-Type": "application/json"
|
|
190
|
-
}
|
|
196
|
+
headers: { "Content-Type": "application/json" }
|
|
191
197
|
});
|
|
192
198
|
}
|
|
193
|
-
__name(response, "response");
|
|
194
199
|
|
|
195
200
|
// src/request/response.ts
|
|
196
201
|
var ServerResponse = class {
|
|
197
|
-
static {
|
|
198
|
-
__name(this, "ServerResponse");
|
|
199
|
-
}
|
|
200
|
-
interceptors;
|
|
201
|
-
statusCode = 200;
|
|
202
|
-
responseBody = {};
|
|
203
|
-
responseHeaders = {
|
|
204
|
-
"Content-Type": "application/json"
|
|
205
|
-
};
|
|
206
202
|
/**
|
|
207
203
|
* Creates a new ServerResponse instance
|
|
208
204
|
* @param interceptors Array of interceptor functions that can modify the response
|
|
209
205
|
*/
|
|
210
206
|
constructor(interceptors = []) {
|
|
207
|
+
this.statusCode = 200;
|
|
208
|
+
this.responseBody = {};
|
|
209
|
+
this.responseHeaders = {
|
|
210
|
+
"Content-Type": "application/json"
|
|
211
|
+
};
|
|
211
212
|
this.interceptors = interceptors;
|
|
212
213
|
}
|
|
213
214
|
/**
|
|
@@ -245,10 +246,7 @@ var ServerResponse = class {
|
|
|
245
246
|
* @returns this instance for chaining
|
|
246
247
|
*/
|
|
247
248
|
setHeaders(headers) {
|
|
248
|
-
this.responseHeaders = {
|
|
249
|
-
...this.responseHeaders,
|
|
250
|
-
...headers
|
|
251
|
-
};
|
|
249
|
+
this.responseHeaders = { ...this.responseHeaders, ...headers };
|
|
252
250
|
return this;
|
|
253
251
|
}
|
|
254
252
|
/**
|
|
@@ -373,9 +371,7 @@ var ServerResponse = class {
|
|
|
373
371
|
* @returns Promise<Response> The final Response object
|
|
374
372
|
*/
|
|
375
373
|
async notPermitted(message = "Not permitted") {
|
|
376
|
-
return this.status(403).json({
|
|
377
|
-
error: message
|
|
378
|
-
});
|
|
374
|
+
return this.status(403).json({ error: message });
|
|
379
375
|
}
|
|
380
376
|
/**
|
|
381
377
|
* Creates an error response with status 401
|
|
@@ -383,9 +379,7 @@ var ServerResponse = class {
|
|
|
383
379
|
* @returns Promise<Response> The final Response object
|
|
384
380
|
*/
|
|
385
381
|
async unauthorized(message = "Unauthorized") {
|
|
386
|
-
return this.status(401).json({
|
|
387
|
-
error: message
|
|
388
|
-
});
|
|
382
|
+
return this.status(401).json({ error: message });
|
|
389
383
|
}
|
|
390
384
|
/**
|
|
391
385
|
* Creates an error response with status 404
|
|
@@ -393,9 +387,7 @@ var ServerResponse = class {
|
|
|
393
387
|
* @returns Promise<Response> The final Response object
|
|
394
388
|
*/
|
|
395
389
|
async notFound(message = "Not found") {
|
|
396
|
-
return this.status(404).json({
|
|
397
|
-
error: message
|
|
398
|
-
});
|
|
390
|
+
return this.status(404).json({ error: message });
|
|
399
391
|
}
|
|
400
392
|
/**
|
|
401
393
|
* Creates an error response with status 500
|
|
@@ -403,9 +395,7 @@ var ServerResponse = class {
|
|
|
403
395
|
* @returns Promise<Response> The final Response object
|
|
404
396
|
*/
|
|
405
397
|
async serverError(message = "Internal Server Error") {
|
|
406
|
-
return this.status(500).json({
|
|
407
|
-
error: message
|
|
408
|
-
});
|
|
398
|
+
return this.status(500).json({ error: message });
|
|
409
399
|
}
|
|
410
400
|
};
|
|
411
401
|
|
|
@@ -440,11 +430,9 @@ function cors(res, options = {}) {
|
|
|
440
430
|
headers: newHeaders
|
|
441
431
|
});
|
|
442
432
|
}
|
|
443
|
-
__name(cors, "cors");
|
|
444
433
|
function createCorsInterceptor(options = {}) {
|
|
445
434
|
return (res) => cors(res, options);
|
|
446
435
|
}
|
|
447
|
-
__name(createCorsInterceptor, "createCorsInterceptor");
|
|
448
436
|
|
|
449
437
|
// src/server.ts
|
|
450
438
|
var Message = z.object({
|
|
@@ -452,37 +440,31 @@ var Message = z.object({
|
|
|
452
440
|
value: z.any()
|
|
453
441
|
});
|
|
454
442
|
var Server = class {
|
|
455
|
-
static {
|
|
456
|
-
__name(this, "Server");
|
|
457
|
-
}
|
|
458
|
-
room;
|
|
459
|
-
subRoom;
|
|
460
|
-
rooms;
|
|
461
443
|
/**
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
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
|
+
*/
|
|
470
452
|
constructor(room) {
|
|
471
453
|
this.room = room;
|
|
472
454
|
this.subRoom = null;
|
|
473
455
|
this.rooms = [];
|
|
474
456
|
}
|
|
475
457
|
/**
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
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
|
+
*/
|
|
486
468
|
get isHibernate() {
|
|
487
469
|
return !!this["options"]?.hibernate;
|
|
488
470
|
}
|
|
@@ -506,35 +488,31 @@ var Server = class {
|
|
|
506
488
|
}
|
|
507
489
|
}
|
|
508
490
|
/**
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
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
|
+
*/
|
|
522
504
|
async onStart() {
|
|
523
505
|
if (!this.isHibernate) {
|
|
524
506
|
this.subRoom = await this.createRoom();
|
|
525
507
|
}
|
|
526
508
|
}
|
|
527
509
|
async runGarbageCollector() {
|
|
528
|
-
await this.garbageCollector({
|
|
529
|
-
sessionExpiryTime: -1
|
|
530
|
-
});
|
|
510
|
+
await this.garbageCollector({ sessionExpiryTime: -1 });
|
|
531
511
|
}
|
|
532
512
|
async garbageCollector(options) {
|
|
533
513
|
const subRoom = await this.getSubRoom();
|
|
534
514
|
if (!subRoom) return;
|
|
535
|
-
const activeConnections = [
|
|
536
|
-
...this.room.getConnections()
|
|
537
|
-
];
|
|
515
|
+
const activeConnections = [...this.room.getConnections()];
|
|
538
516
|
const activePrivateIds = new Set(activeConnections.map((conn) => conn.id));
|
|
539
517
|
try {
|
|
540
518
|
const sessions = await this.room.storage.list();
|
|
@@ -569,21 +547,21 @@ var Server = class {
|
|
|
569
547
|
}
|
|
570
548
|
}
|
|
571
549
|
/**
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
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
|
+
*/
|
|
587
565
|
async createRoom(options = {}) {
|
|
588
566
|
let instance;
|
|
589
567
|
let init = true;
|
|
@@ -598,7 +576,7 @@ var Server = class {
|
|
|
598
576
|
if (!instance) {
|
|
599
577
|
return null;
|
|
600
578
|
}
|
|
601
|
-
const loadMemory =
|
|
579
|
+
const loadMemory = async () => {
|
|
602
580
|
const root = await this.room.storage.get(".");
|
|
603
581
|
const memory = await this.room.storage.list();
|
|
604
582
|
const tmpObject = root || {};
|
|
@@ -612,7 +590,7 @@ var Server = class {
|
|
|
612
590
|
dset2(tmpObject, key, value);
|
|
613
591
|
}
|
|
614
592
|
load(instance, tmpObject, true);
|
|
615
|
-
}
|
|
593
|
+
};
|
|
616
594
|
instance.$memoryAll = {};
|
|
617
595
|
instance.$autoSync = instance["autoSync"] !== false;
|
|
618
596
|
instance.$pendingSync = /* @__PURE__ */ new Map();
|
|
@@ -712,7 +690,7 @@ var Server = class {
|
|
|
712
690
|
return null;
|
|
713
691
|
}
|
|
714
692
|
};
|
|
715
|
-
const syncCb =
|
|
693
|
+
const syncCb = (values) => {
|
|
716
694
|
if (options.getMemoryAll) {
|
|
717
695
|
buildObject(values, instance.$memoryAll);
|
|
718
696
|
}
|
|
@@ -728,13 +706,16 @@ var Server = class {
|
|
|
728
706
|
return;
|
|
729
707
|
}
|
|
730
708
|
const packet = buildObject(values, instance.$memoryAll);
|
|
731
|
-
this.broadcast(
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
709
|
+
this.broadcast(
|
|
710
|
+
{
|
|
711
|
+
type: "sync",
|
|
712
|
+
value: packet
|
|
713
|
+
},
|
|
714
|
+
instance
|
|
715
|
+
);
|
|
735
716
|
values.clear();
|
|
736
|
-
}
|
|
737
|
-
const persistCb =
|
|
717
|
+
};
|
|
718
|
+
const persistCb = async (values) => {
|
|
738
719
|
if (initPersist) {
|
|
739
720
|
values.clear();
|
|
740
721
|
return;
|
|
@@ -749,7 +730,7 @@ var Server = class {
|
|
|
749
730
|
}
|
|
750
731
|
}
|
|
751
732
|
values.clear();
|
|
752
|
-
}
|
|
733
|
+
};
|
|
753
734
|
syncClass(instance, {
|
|
754
735
|
onSync: instance["throttleSync"] ? throttle(syncCb, instance["throttleSync"]) : syncCb,
|
|
755
736
|
onPersist: instance["throttleStorage"] ? throttle(persistCb, instance["throttleStorage"]) : persistCb
|
|
@@ -760,21 +741,21 @@ var Server = class {
|
|
|
760
741
|
return instance;
|
|
761
742
|
}
|
|
762
743
|
/**
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
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
|
+
*/
|
|
778
759
|
async getSubRoom(options = {}) {
|
|
779
760
|
let subRoom;
|
|
780
761
|
if (this.isHibernate) {
|
|
@@ -785,20 +766,20 @@ var Server = class {
|
|
|
785
766
|
return subRoom;
|
|
786
767
|
}
|
|
787
768
|
/**
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
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
|
+
*/
|
|
802
783
|
getUsersProperty(subRoom) {
|
|
803
784
|
const meta = subRoom.constructor["_propertyMetadata"];
|
|
804
785
|
const propId = meta?.get("users");
|
|
@@ -814,12 +795,12 @@ var Server = class {
|
|
|
814
795
|
return metadata.get("users");
|
|
815
796
|
}
|
|
816
797
|
/**
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
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
|
+
*/
|
|
823
804
|
getUserConnectionProperty(user) {
|
|
824
805
|
if (!user) return null;
|
|
825
806
|
const metadata = user.constructor._propertyMetadata;
|
|
@@ -829,13 +810,13 @@ var Server = class {
|
|
|
829
810
|
return user[connectedPropName];
|
|
830
811
|
}
|
|
831
812
|
/**
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
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
|
+
*/
|
|
839
820
|
updateUserConnectionStatus(user, isConnected) {
|
|
840
821
|
const connectionSignal = this.getUserConnectionProperty(user);
|
|
841
822
|
if (connectionSignal) {
|
|
@@ -845,17 +826,17 @@ var Server = class {
|
|
|
845
826
|
return false;
|
|
846
827
|
}
|
|
847
828
|
/**
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
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
|
+
*/
|
|
859
840
|
async getSession(privateId) {
|
|
860
841
|
if (!privateId) return null;
|
|
861
842
|
try {
|
|
@@ -876,23 +857,20 @@ var Server = class {
|
|
|
876
857
|
async updateSessionConnection(privateId, connected) {
|
|
877
858
|
const session = await this.getSession(privateId);
|
|
878
859
|
if (session) {
|
|
879
|
-
await this.saveSession(privateId, {
|
|
880
|
-
...session,
|
|
881
|
-
connected
|
|
882
|
-
});
|
|
860
|
+
await this.saveSession(privateId, { ...session, connected });
|
|
883
861
|
}
|
|
884
862
|
}
|
|
885
863
|
/**
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
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
|
+
*/
|
|
896
874
|
async deleteSession(privateId) {
|
|
897
875
|
await this.room.storage.delete(`session:${privateId}`);
|
|
898
876
|
}
|
|
@@ -904,10 +882,8 @@ var Server = class {
|
|
|
904
882
|
conn.close();
|
|
905
883
|
return;
|
|
906
884
|
}
|
|
907
|
-
const sessionExpiryTime = subRoom.constructor.sessionExpiryTime;
|
|
908
|
-
await this.garbageCollector({
|
|
909
|
-
sessionExpiryTime
|
|
910
|
-
});
|
|
885
|
+
const sessionExpiryTime = subRoom.sessionExpiryTime ?? subRoom.constructor.sessionExpiryTime ?? 5 * 60 * 1e3;
|
|
886
|
+
await this.garbageCollector({ sessionExpiryTime });
|
|
911
887
|
const roomGuards = subRoom.constructor["_roomGuards"] || [];
|
|
912
888
|
for (const guard of roomGuards) {
|
|
913
889
|
const isAuthorized = await guard(conn, ctx, this.room);
|
|
@@ -975,21 +951,21 @@ var Server = class {
|
|
|
975
951
|
}
|
|
976
952
|
}
|
|
977
953
|
/**
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
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
|
+
*/
|
|
993
969
|
async onConnect(conn, ctx) {
|
|
994
970
|
if (ctx.request?.headers.has("x-shard-id")) {
|
|
995
971
|
this.onConnectShard(conn, ctx);
|
|
@@ -998,13 +974,13 @@ var Server = class {
|
|
|
998
974
|
}
|
|
999
975
|
}
|
|
1000
976
|
/**
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
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
|
+
*/
|
|
1008
984
|
onConnectShard(conn, ctx) {
|
|
1009
985
|
const shardId = ctx.request?.headers.get("x-shard-id") || "unknown-shard";
|
|
1010
986
|
conn.setState({
|
|
@@ -1015,13 +991,13 @@ var Server = class {
|
|
|
1015
991
|
});
|
|
1016
992
|
}
|
|
1017
993
|
/**
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
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
|
+
*/
|
|
1025
1001
|
async onMessage(message, sender) {
|
|
1026
1002
|
if (sender.state && sender.state.shard) {
|
|
1027
1003
|
await this.handleShardMessage(message, sender);
|
|
@@ -1050,38 +1026,54 @@ var Server = class {
|
|
|
1050
1026
|
}
|
|
1051
1027
|
}
|
|
1052
1028
|
const actions = subRoom.constructor["_actionMetadata"];
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
return;
|
|
1064
|
-
}
|
|
1029
|
+
const signal2 = this.getUsersProperty(subRoom);
|
|
1030
|
+
const { publicId } = sender.state;
|
|
1031
|
+
const user = signal2?.()[publicId];
|
|
1032
|
+
const actionName = actions?.get(result.data.action);
|
|
1033
|
+
if (actionName) {
|
|
1034
|
+
const guards = subRoom.constructor["_actionGuards"]?.get(actionName.key) || [];
|
|
1035
|
+
for (const guard of guards) {
|
|
1036
|
+
const isAuthorized = await guard(sender, result.data.value, this.room);
|
|
1037
|
+
if (!isAuthorized) {
|
|
1038
|
+
return;
|
|
1065
1039
|
}
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1040
|
+
}
|
|
1041
|
+
if (actionName.bodyValidation) {
|
|
1042
|
+
const bodyResult = actionName.bodyValidation.safeParse(
|
|
1043
|
+
result.data.value
|
|
1044
|
+
);
|
|
1045
|
+
if (!bodyResult.success) {
|
|
1046
|
+
return;
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
await awaitReturn(
|
|
1050
|
+
subRoom[actionName.key](user, result.data.value, sender)
|
|
1051
|
+
);
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1054
|
+
const unhandledAction = subRoom.constructor["_unhandledActionMetadata"];
|
|
1055
|
+
if (unhandledAction) {
|
|
1056
|
+
const guards = subRoom.constructor["_actionGuards"]?.get(unhandledAction.key) || [];
|
|
1057
|
+
for (const guard of guards) {
|
|
1058
|
+
const isAuthorized = await guard(sender, result.data, this.room);
|
|
1059
|
+
if (!isAuthorized) {
|
|
1060
|
+
return;
|
|
1071
1061
|
}
|
|
1072
|
-
await awaitReturn(subRoom[actionName.key](user, result.data.value, sender));
|
|
1073
1062
|
}
|
|
1063
|
+
await awaitReturn(
|
|
1064
|
+
subRoom[unhandledAction.key](user, result.data, sender)
|
|
1065
|
+
);
|
|
1074
1066
|
}
|
|
1075
1067
|
}
|
|
1076
1068
|
/**
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
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
|
+
*/
|
|
1085
1077
|
async handleShardMessage(message, shardConnection) {
|
|
1086
1078
|
let parsedMessage;
|
|
1087
1079
|
try {
|
|
@@ -1107,14 +1099,14 @@ var Server = class {
|
|
|
1107
1099
|
}
|
|
1108
1100
|
}
|
|
1109
1101
|
/**
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
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
|
+
*/
|
|
1118
1110
|
async handleShardClientConnect(message, shardConnection) {
|
|
1119
1111
|
const { privateId, requestInfo } = message;
|
|
1120
1112
|
const shardState = shardConnection.state;
|
|
@@ -1127,22 +1119,22 @@ var Server = class {
|
|
|
1127
1119
|
};
|
|
1128
1120
|
const virtualConnection = {
|
|
1129
1121
|
id: privateId,
|
|
1130
|
-
send:
|
|
1122
|
+
send: (data) => {
|
|
1131
1123
|
shardConnection.send(JSON.stringify({
|
|
1132
1124
|
targetClientId: privateId,
|
|
1133
1125
|
data
|
|
1134
1126
|
}));
|
|
1135
|
-
},
|
|
1127
|
+
},
|
|
1136
1128
|
state: {},
|
|
1137
|
-
setState:
|
|
1129
|
+
setState: (state) => {
|
|
1138
1130
|
const clients = shardState.clients;
|
|
1139
1131
|
const currentState = clients.get(privateId) || {};
|
|
1140
1132
|
const mergedState = Object.assign({}, currentState, state);
|
|
1141
1133
|
clients.set(privateId, mergedState);
|
|
1142
1134
|
virtualConnection.state = clients.get(privateId);
|
|
1143
1135
|
return virtualConnection.state;
|
|
1144
|
-
},
|
|
1145
|
-
close:
|
|
1136
|
+
},
|
|
1137
|
+
close: () => {
|
|
1146
1138
|
shardConnection.send(JSON.stringify({
|
|
1147
1139
|
type: "shard.closeClient",
|
|
1148
1140
|
privateId
|
|
@@ -1150,7 +1142,7 @@ var Server = class {
|
|
|
1150
1142
|
if (shardState.clients) {
|
|
1151
1143
|
shardState.clients.delete(privateId);
|
|
1152
1144
|
}
|
|
1153
|
-
}
|
|
1145
|
+
}
|
|
1154
1146
|
};
|
|
1155
1147
|
if (!shardState.clients.has(privateId)) {
|
|
1156
1148
|
shardState.clients.set(privateId, {});
|
|
@@ -1158,41 +1150,39 @@ var Server = class {
|
|
|
1158
1150
|
await this.onConnectClient(virtualConnection, virtualContext);
|
|
1159
1151
|
}
|
|
1160
1152
|
/**
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
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
|
+
*/
|
|
1169
1161
|
async handleShardClientMessage(message, shardConnection) {
|
|
1170
1162
|
const { privateId, publicId, payload } = message;
|
|
1171
1163
|
const shardState = shardConnection.state;
|
|
1172
1164
|
const clients = shardState.clients;
|
|
1173
1165
|
if (!clients.has(privateId)) {
|
|
1174
1166
|
console.warn(`Received message from unknown client ${privateId}, creating virtual connection`);
|
|
1175
|
-
clients.set(privateId, {
|
|
1176
|
-
publicId
|
|
1177
|
-
});
|
|
1167
|
+
clients.set(privateId, { publicId });
|
|
1178
1168
|
}
|
|
1179
1169
|
const virtualConnection = {
|
|
1180
1170
|
id: privateId,
|
|
1181
|
-
send:
|
|
1171
|
+
send: (data) => {
|
|
1182
1172
|
shardConnection.send(JSON.stringify({
|
|
1183
1173
|
targetClientId: privateId,
|
|
1184
1174
|
data
|
|
1185
1175
|
}));
|
|
1186
|
-
},
|
|
1176
|
+
},
|
|
1187
1177
|
state: clients.get(privateId),
|
|
1188
|
-
setState:
|
|
1178
|
+
setState: (state) => {
|
|
1189
1179
|
const currentState = clients.get(privateId) || {};
|
|
1190
1180
|
const mergedState = Object.assign({}, currentState, state);
|
|
1191
1181
|
clients.set(privateId, mergedState);
|
|
1192
1182
|
virtualConnection.state = clients.get(privateId);
|
|
1193
1183
|
return virtualConnection.state;
|
|
1194
|
-
},
|
|
1195
|
-
close:
|
|
1184
|
+
},
|
|
1185
|
+
close: () => {
|
|
1196
1186
|
shardConnection.send(JSON.stringify({
|
|
1197
1187
|
type: "shard.closeClient",
|
|
1198
1188
|
privateId
|
|
@@ -1200,20 +1190,20 @@ var Server = class {
|
|
|
1200
1190
|
if (shardState.clients) {
|
|
1201
1191
|
shardState.clients.delete(privateId);
|
|
1202
1192
|
}
|
|
1203
|
-
}
|
|
1193
|
+
}
|
|
1204
1194
|
};
|
|
1205
1195
|
const payloadString = typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
1206
1196
|
await this.onMessage(payloadString, virtualConnection);
|
|
1207
1197
|
}
|
|
1208
1198
|
/**
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
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
|
+
*/
|
|
1217
1207
|
async handleShardClientDisconnect(message, shardConnection) {
|
|
1218
1208
|
const { privateId, publicId } = message;
|
|
1219
1209
|
const shardState = shardConnection.state;
|
|
@@ -1225,33 +1215,34 @@ var Server = class {
|
|
|
1225
1215
|
}
|
|
1226
1216
|
const virtualConnection = {
|
|
1227
1217
|
id: privateId,
|
|
1228
|
-
send:
|
|
1229
|
-
},
|
|
1218
|
+
send: () => {
|
|
1219
|
+
},
|
|
1220
|
+
// No-op since client is disconnecting
|
|
1230
1221
|
state: clientState,
|
|
1231
|
-
setState:
|
|
1222
|
+
setState: () => {
|
|
1232
1223
|
return {};
|
|
1233
|
-
},
|
|
1234
|
-
close:
|
|
1235
|
-
}
|
|
1224
|
+
},
|
|
1225
|
+
close: () => {
|
|
1226
|
+
}
|
|
1236
1227
|
};
|
|
1237
1228
|
await this.onClose(virtualConnection);
|
|
1238
1229
|
clients.delete(privateId);
|
|
1239
1230
|
}
|
|
1240
1231
|
/**
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
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
|
+
*/
|
|
1255
1246
|
async onClose(conn) {
|
|
1256
1247
|
const subRoom = await this.getSubRoom();
|
|
1257
1248
|
if (!subRoom) {
|
|
@@ -1274,9 +1265,7 @@ var Server = class {
|
|
|
1274
1265
|
if (!connectionUpdated) {
|
|
1275
1266
|
this.broadcast({
|
|
1276
1267
|
type: "user_disconnected",
|
|
1277
|
-
value: {
|
|
1278
|
-
publicId
|
|
1279
|
-
}
|
|
1268
|
+
value: { publicId }
|
|
1280
1269
|
}, subRoom);
|
|
1281
1270
|
}
|
|
1282
1271
|
}
|
|
@@ -1289,12 +1278,12 @@ var Server = class {
|
|
|
1289
1278
|
await awaitReturn(subRoom["onError"]?.(connection, error));
|
|
1290
1279
|
}
|
|
1291
1280
|
/**
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
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
|
+
*/
|
|
1298
1287
|
async onRequest(req) {
|
|
1299
1288
|
const isFromShard = req.headers.has("x-forwarded-by-shard");
|
|
1300
1289
|
const shardId = req.headers.get("x-shard-id");
|
|
@@ -1310,14 +1299,14 @@ var Server = class {
|
|
|
1310
1299
|
return this.handleDirectRequest(req, res);
|
|
1311
1300
|
}
|
|
1312
1301
|
/**
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
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
|
+
*/
|
|
1321
1310
|
async handleSessionRestore(req, res) {
|
|
1322
1311
|
try {
|
|
1323
1312
|
const transferData = await req.json();
|
|
@@ -1342,14 +1331,16 @@ var Server = class {
|
|
|
1342
1331
|
if (signal2 && usersPropName) {
|
|
1343
1332
|
const { classType } = signal2.options;
|
|
1344
1333
|
const user = isClass(classType) ? new classType() : classType();
|
|
1345
|
-
const hydratedSnapshot = await awaitReturn(
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
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;
|
|
1353
1344
|
signal2()[publicId] = user;
|
|
1354
1345
|
load(user, hydratedSnapshot, true);
|
|
1355
1346
|
await this.room.storage.put(`${usersPropName}.${publicId}`, userSnapshot);
|
|
@@ -1361,22 +1352,20 @@ var Server = class {
|
|
|
1361
1352
|
publicId,
|
|
1362
1353
|
restored: true
|
|
1363
1354
|
});
|
|
1364
|
-
return res.success({
|
|
1365
|
-
transferToken
|
|
1366
|
-
});
|
|
1355
|
+
return res.success({ transferToken });
|
|
1367
1356
|
} catch (error) {
|
|
1368
1357
|
console.error("Error restoring session:", error);
|
|
1369
1358
|
return res.serverError("Failed to restore session");
|
|
1370
1359
|
}
|
|
1371
1360
|
}
|
|
1372
1361
|
/**
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
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
|
+
*/
|
|
1380
1369
|
async handleDirectRequest(req, res) {
|
|
1381
1370
|
const subRoom = await this.getSubRoom();
|
|
1382
1371
|
if (!subRoom) {
|
|
@@ -1400,14 +1389,14 @@ var Server = class {
|
|
|
1400
1389
|
return res.success(legacyResponse);
|
|
1401
1390
|
}
|
|
1402
1391
|
/**
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
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
|
+
*/
|
|
1411
1400
|
async tryMatchRequestHandler(req, res, subRoom) {
|
|
1412
1401
|
const requestHandlers = subRoom.constructor["_requestMetadata"];
|
|
1413
1402
|
if (!requestHandlers) {
|
|
@@ -1415,8 +1404,7 @@ var Server = class {
|
|
|
1415
1404
|
}
|
|
1416
1405
|
const url = new URL(req.url);
|
|
1417
1406
|
const method = req.method;
|
|
1418
|
-
|
|
1419
|
-
pathname = "/" + pathname.split("/").slice(4).join("/");
|
|
1407
|
+
const pathname = this.normalizeRequestPath(url.pathname);
|
|
1420
1408
|
for (const [routeKey, handler] of requestHandlers.entries()) {
|
|
1421
1409
|
const firstColonIndex = routeKey.indexOf(":");
|
|
1422
1410
|
const handlerMethod = routeKey.substring(0, firstColonIndex);
|
|
@@ -1437,23 +1425,20 @@ var Server = class {
|
|
|
1437
1425
|
}
|
|
1438
1426
|
}
|
|
1439
1427
|
let bodyData = null;
|
|
1440
|
-
if (handler.bodyValidation && [
|
|
1441
|
-
"POST",
|
|
1442
|
-
"PUT",
|
|
1443
|
-
"PATCH"
|
|
1444
|
-
].includes(method)) {
|
|
1428
|
+
if (handler.bodyValidation && ["POST", "PUT", "PATCH"].includes(method)) {
|
|
1445
1429
|
try {
|
|
1446
1430
|
const contentType = req.headers.get("content-type") || "";
|
|
1447
|
-
if (contentType.includes("application/json")) {
|
|
1448
|
-
|
|
1449
|
-
const validation = handler.bodyValidation.safeParse(body);
|
|
1450
|
-
if (!validation.success) {
|
|
1451
|
-
return res.badRequest("Invalid request body", {
|
|
1452
|
-
details: validation.error
|
|
1453
|
-
});
|
|
1454
|
-
}
|
|
1455
|
-
bodyData = validation.data;
|
|
1431
|
+
if (!contentType.includes("application/json")) {
|
|
1432
|
+
return res.badRequest("Content-Type must be application/json");
|
|
1456
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;
|
|
1457
1442
|
} catch (error) {
|
|
1458
1443
|
return res.badRequest("Failed to parse request body");
|
|
1459
1444
|
}
|
|
@@ -1461,7 +1446,9 @@ var Server = class {
|
|
|
1461
1446
|
try {
|
|
1462
1447
|
req["data"] = bodyData;
|
|
1463
1448
|
req["params"] = params;
|
|
1464
|
-
const result = await awaitReturn(
|
|
1449
|
+
const result = await awaitReturn(
|
|
1450
|
+
subRoom[handler.key](req, res)
|
|
1451
|
+
);
|
|
1465
1452
|
if (result instanceof Response) {
|
|
1466
1453
|
return result;
|
|
1467
1454
|
}
|
|
@@ -1475,26 +1462,24 @@ var Server = class {
|
|
|
1475
1462
|
return null;
|
|
1476
1463
|
}
|
|
1477
1464
|
/**
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
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
|
+
*/
|
|
1485
1472
|
pathMatches(requestPath, handlerPath) {
|
|
1486
|
-
|
|
1487
|
-
const pathRegex = new RegExp(`^${pathRegexString}`);
|
|
1488
|
-
return pathRegex.test(requestPath);
|
|
1473
|
+
return this.pathPatternToRegex(handlerPath).test(requestPath);
|
|
1489
1474
|
}
|
|
1490
1475
|
/**
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
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
|
+
*/
|
|
1498
1483
|
extractPathParams(requestPath, handlerPath) {
|
|
1499
1484
|
const params = {};
|
|
1500
1485
|
const paramNames = [];
|
|
@@ -1503,8 +1488,7 @@ var Server = class {
|
|
|
1503
1488
|
paramNames.push(segment.substring(1));
|
|
1504
1489
|
}
|
|
1505
1490
|
});
|
|
1506
|
-
const
|
|
1507
|
-
const pathRegex = new RegExp(`^${pathRegexString}`);
|
|
1491
|
+
const pathRegex = this.pathPatternToRegex(handlerPath);
|
|
1508
1492
|
const matches = requestPath.match(pathRegex);
|
|
1509
1493
|
if (matches && matches.length > 1) {
|
|
1510
1494
|
for (let i = 0; i < paramNames.length; i++) {
|
|
@@ -1513,15 +1497,32 @@ var Server = class {
|
|
|
1513
1497
|
}
|
|
1514
1498
|
return params;
|
|
1515
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
|
+
}
|
|
1516
1517
|
/**
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
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
|
+
*/
|
|
1525
1526
|
async handleShardRequest(req, res, shardId) {
|
|
1526
1527
|
const subRoom = await this.getSubRoom();
|
|
1527
1528
|
if (!subRoom) {
|
|
@@ -1548,13 +1549,13 @@ var Server = class {
|
|
|
1548
1549
|
}
|
|
1549
1550
|
}
|
|
1550
1551
|
/**
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
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
|
+
*/
|
|
1558
1559
|
createEnhancedRequest(originalReq, originalClientIp) {
|
|
1559
1560
|
const clonedReq = originalReq.clone();
|
|
1560
1561
|
clonedReq.viaShard = true;
|
|
@@ -1567,18 +1568,6 @@ var Server = class {
|
|
|
1567
1568
|
|
|
1568
1569
|
// src/shard.ts
|
|
1569
1570
|
var Shard = class {
|
|
1570
|
-
static {
|
|
1571
|
-
__name(this, "Shard");
|
|
1572
|
-
}
|
|
1573
|
-
room;
|
|
1574
|
-
ws;
|
|
1575
|
-
connectionMap;
|
|
1576
|
-
mainServerStub;
|
|
1577
|
-
worldUrl;
|
|
1578
|
-
worldId;
|
|
1579
|
-
lastReportedConnections;
|
|
1580
|
-
statsInterval;
|
|
1581
|
-
statsIntervalId;
|
|
1582
1571
|
constructor(room) {
|
|
1583
1572
|
this.room = room;
|
|
1584
1573
|
this.connectionMap = /* @__PURE__ */ new Map();
|
|
@@ -1701,9 +1690,7 @@ var Shard = class {
|
|
|
1701
1690
|
})
|
|
1702
1691
|
});
|
|
1703
1692
|
if (!response2.ok) {
|
|
1704
|
-
const errorData = await response2.json().catch(() => ({
|
|
1705
|
-
error: "Unknown error"
|
|
1706
|
-
}));
|
|
1693
|
+
const errorData = await response2.json().catch(() => ({ error: "Unknown error" }));
|
|
1707
1694
|
console.error(`Failed to update World stats: ${response2.status} - ${errorData.error || "Unknown error"}`);
|
|
1708
1695
|
return false;
|
|
1709
1696
|
}
|
|
@@ -1715,17 +1702,15 @@ var Shard = class {
|
|
|
1715
1702
|
}
|
|
1716
1703
|
}
|
|
1717
1704
|
/**
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
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
|
+
*/
|
|
1724
1711
|
async onRequest(req) {
|
|
1725
1712
|
if (!this.mainServerStub) {
|
|
1726
|
-
return response(503, {
|
|
1727
|
-
error: "Shard not connected to main server"
|
|
1728
|
-
});
|
|
1713
|
+
return response(503, { error: "Shard not connected to main server" });
|
|
1729
1714
|
}
|
|
1730
1715
|
try {
|
|
1731
1716
|
const url = new URL(req.url);
|
|
@@ -1753,32 +1738,28 @@ var Shard = class {
|
|
|
1753
1738
|
const response2 = await this.mainServerStub.fetch(path, requestInit);
|
|
1754
1739
|
return response2;
|
|
1755
1740
|
} catch (error) {
|
|
1756
|
-
return response(500, {
|
|
1757
|
-
error: "Error forwarding request"
|
|
1758
|
-
});
|
|
1741
|
+
return response(500, { error: "Error forwarding request" });
|
|
1759
1742
|
}
|
|
1760
1743
|
}
|
|
1761
1744
|
/**
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1745
|
+
* @method onAlarm
|
|
1746
|
+
* @async
|
|
1747
|
+
* @description Executed periodically, used to perform maintenance tasks
|
|
1748
|
+
*/
|
|
1766
1749
|
async onAlarm() {
|
|
1767
1750
|
await this.updateWorldStats();
|
|
1768
1751
|
}
|
|
1769
1752
|
};
|
|
1770
1753
|
|
|
1771
1754
|
// src/testing.ts
|
|
1772
|
-
async function testRoom(
|
|
1773
|
-
const createServer =
|
|
1755
|
+
async function testRoom(Room2, options = {}) {
|
|
1756
|
+
const createServer = (io2) => {
|
|
1774
1757
|
const server2 = new Server(io2);
|
|
1775
|
-
server2.rooms = [
|
|
1776
|
-
Room3
|
|
1777
|
-
];
|
|
1758
|
+
server2.rooms = [Room2];
|
|
1778
1759
|
return server2;
|
|
1779
|
-
}
|
|
1760
|
+
};
|
|
1780
1761
|
const isShard = options.shard || false;
|
|
1781
|
-
const io = new ServerIo(
|
|
1762
|
+
const io = new ServerIo(Room2.path, isShard ? {
|
|
1782
1763
|
parties: {
|
|
1783
1764
|
game: createServer,
|
|
1784
1765
|
...options.parties || {}
|
|
@@ -1790,9 +1771,9 @@ async function testRoom(Room3, options = {}) {
|
|
|
1790
1771
|
partyFn: options.partyFn,
|
|
1791
1772
|
env: options.env
|
|
1792
1773
|
});
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1774
|
+
Room2.prototype.throttleSync = 0;
|
|
1775
|
+
Room2.prototype.throttleStorage = 0;
|
|
1776
|
+
Room2.prototype.options = options;
|
|
1796
1777
|
let server;
|
|
1797
1778
|
if (options.shard) {
|
|
1798
1779
|
const shardServer = new Shard(io);
|
|
@@ -1817,41 +1798,31 @@ async function testRoom(Room3, options = {}) {
|
|
|
1817
1798
|
return {
|
|
1818
1799
|
server,
|
|
1819
1800
|
room: server.subRoom,
|
|
1820
|
-
createClient:
|
|
1801
|
+
createClient: async (id2, opts) => {
|
|
1821
1802
|
const client = await io.connection(server, id2, opts);
|
|
1822
1803
|
return client;
|
|
1823
|
-
},
|
|
1824
|
-
getServerUser:
|
|
1804
|
+
},
|
|
1805
|
+
getServerUser: async (client, prop = "users") => {
|
|
1825
1806
|
const privateId = client.conn.id;
|
|
1826
1807
|
const session = await server.getSession(privateId);
|
|
1827
1808
|
return server.subRoom[prop]()[session?.publicId];
|
|
1828
|
-
}
|
|
1809
|
+
}
|
|
1829
1810
|
};
|
|
1830
1811
|
}
|
|
1831
|
-
__name(testRoom, "testRoom");
|
|
1832
1812
|
async function request(room, path, options = {
|
|
1833
1813
|
method: "GET"
|
|
1834
1814
|
}) {
|
|
1835
1815
|
const url = new URL("http://localhost" + path);
|
|
1836
|
-
const
|
|
1837
|
-
const response2 = await room.onRequest(
|
|
1816
|
+
const request2 = new Request(url.toString(), options);
|
|
1817
|
+
const response2 = await room.onRequest(request2);
|
|
1838
1818
|
return response2;
|
|
1839
1819
|
}
|
|
1840
|
-
__name(request, "request");
|
|
1841
1820
|
function tick(ms = 0) {
|
|
1842
1821
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1843
1822
|
}
|
|
1844
|
-
__name(tick, "tick");
|
|
1845
1823
|
|
|
1846
1824
|
// src/mock.ts
|
|
1847
1825
|
var MockPartyClient = class {
|
|
1848
|
-
static {
|
|
1849
|
-
__name(this, "MockPartyClient");
|
|
1850
|
-
}
|
|
1851
|
-
server;
|
|
1852
|
-
events;
|
|
1853
|
-
id;
|
|
1854
|
-
conn;
|
|
1855
1826
|
constructor(server, id2) {
|
|
1856
1827
|
this.server = server;
|
|
1857
1828
|
this.events = /* @__PURE__ */ new Map();
|
|
@@ -1887,12 +1858,7 @@ var MockPartyClient = class {
|
|
|
1887
1858
|
return this.server.onMessage(JSON.stringify(data), this.conn);
|
|
1888
1859
|
}
|
|
1889
1860
|
};
|
|
1890
|
-
var MockLobby = class
|
|
1891
|
-
static {
|
|
1892
|
-
__name(this, "MockLobby");
|
|
1893
|
-
}
|
|
1894
|
-
server;
|
|
1895
|
-
lobbyId;
|
|
1861
|
+
var MockLobby = class {
|
|
1896
1862
|
constructor(server, lobbyId) {
|
|
1897
1863
|
this.server = server;
|
|
1898
1864
|
this.lobbyId = lobbyId;
|
|
@@ -1910,12 +1876,7 @@ var MockLobby = class MockLobby2 {
|
|
|
1910
1876
|
return request(this.server, baseUrl + url, options);
|
|
1911
1877
|
}
|
|
1912
1878
|
};
|
|
1913
|
-
var MockContext = class
|
|
1914
|
-
static {
|
|
1915
|
-
__name(this, "MockContext");
|
|
1916
|
-
}
|
|
1917
|
-
room;
|
|
1918
|
-
parties;
|
|
1879
|
+
var MockContext = class {
|
|
1919
1880
|
constructor(room, options = {}) {
|
|
1920
1881
|
this.room = room;
|
|
1921
1882
|
this.parties = {
|
|
@@ -1925,13 +1886,13 @@ var MockContext = class MockContext2 {
|
|
|
1925
1886
|
if (options.partyFn) {
|
|
1926
1887
|
const serverCache = /* @__PURE__ */ new Map();
|
|
1927
1888
|
this.parties.main = {
|
|
1928
|
-
get:
|
|
1889
|
+
get: async (lobbyId) => {
|
|
1929
1890
|
if (!serverCache.has(lobbyId)) {
|
|
1930
1891
|
const server = await options.partyFn(lobbyId);
|
|
1931
1892
|
serverCache.set(lobbyId, new MockLobby(server, lobbyId));
|
|
1932
1893
|
}
|
|
1933
1894
|
return serverCache.get(lobbyId);
|
|
1934
|
-
}
|
|
1895
|
+
}
|
|
1935
1896
|
};
|
|
1936
1897
|
} else {
|
|
1937
1898
|
for (let lobbyId in parties) {
|
|
@@ -1941,15 +1902,7 @@ var MockContext = class MockContext2 {
|
|
|
1941
1902
|
}
|
|
1942
1903
|
}
|
|
1943
1904
|
};
|
|
1944
|
-
var MockPartyRoom = class
|
|
1945
|
-
static {
|
|
1946
|
-
__name(this, "MockPartyRoom");
|
|
1947
|
-
}
|
|
1948
|
-
id;
|
|
1949
|
-
clients;
|
|
1950
|
-
storage;
|
|
1951
|
-
context;
|
|
1952
|
-
env;
|
|
1905
|
+
var MockPartyRoom = class {
|
|
1953
1906
|
constructor(id2, options = {}) {
|
|
1954
1907
|
this.id = id2;
|
|
1955
1908
|
this.clients = /* @__PURE__ */ new Map();
|
|
@@ -1977,9 +1930,7 @@ var MockPartyRoom = class MockPartyRoom2 {
|
|
|
1977
1930
|
...opts?.headers || {}
|
|
1978
1931
|
}
|
|
1979
1932
|
});
|
|
1980
|
-
await server.onConnect(socket.conn, {
|
|
1981
|
-
request: request2
|
|
1982
|
-
});
|
|
1933
|
+
await server.onConnect(socket.conn, { request: request2 });
|
|
1983
1934
|
this.clients.set(socket.id, socket);
|
|
1984
1935
|
return socket;
|
|
1985
1936
|
}
|
|
@@ -1999,19 +1950,12 @@ var MockPartyRoom = class MockPartyRoom2 {
|
|
|
1999
1950
|
}
|
|
2000
1951
|
};
|
|
2001
1952
|
var MockConnection = class {
|
|
2002
|
-
static {
|
|
2003
|
-
__name(this, "MockConnection");
|
|
2004
|
-
}
|
|
2005
|
-
client;
|
|
2006
|
-
server;
|
|
2007
|
-
id;
|
|
2008
1953
|
constructor(client) {
|
|
2009
1954
|
this.client = client;
|
|
2010
1955
|
this.state = {};
|
|
2011
1956
|
this.server = client.server;
|
|
2012
1957
|
this.id = client.id;
|
|
2013
1958
|
}
|
|
2014
|
-
state;
|
|
2015
1959
|
setState(value) {
|
|
2016
1960
|
this.state = value;
|
|
2017
1961
|
}
|
|
@@ -2030,17 +1974,8 @@ import { signal } from "@signe/reactive";
|
|
|
2030
1974
|
import { sync, id, persist } from "@signe/sync";
|
|
2031
1975
|
import { z as z2 } from "zod";
|
|
2032
1976
|
|
|
2033
|
-
// src/types/party.ts
|
|
2034
|
-
var party_exports = {};
|
|
2035
|
-
|
|
2036
1977
|
// src/jwt.ts
|
|
2037
1978
|
var JWTAuth = class {
|
|
2038
|
-
static {
|
|
2039
|
-
__name(this, "JWTAuth");
|
|
2040
|
-
}
|
|
2041
|
-
secret;
|
|
2042
|
-
encoder;
|
|
2043
|
-
decoder;
|
|
2044
1979
|
/**
|
|
2045
1980
|
* Constructor for the JWTAuth class
|
|
2046
1981
|
* @param {string} secret - The secret key used for signing and verifying tokens
|
|
@@ -2061,18 +1996,16 @@ var JWTAuth = class {
|
|
|
2061
1996
|
const keyData = this.encoder.encode(this.secret);
|
|
2062
1997
|
return await crypto.subtle.importKey(
|
|
2063
1998
|
"raw",
|
|
1999
|
+
// format
|
|
2064
2000
|
keyData,
|
|
2001
|
+
// key data
|
|
2065
2002
|
{
|
|
2066
2003
|
name: "HMAC",
|
|
2067
|
-
hash: {
|
|
2068
|
-
name: "SHA-256"
|
|
2069
|
-
}
|
|
2004
|
+
hash: { name: "SHA-256" }
|
|
2070
2005
|
},
|
|
2071
2006
|
false,
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
"verify"
|
|
2075
|
-
]
|
|
2007
|
+
// extractable
|
|
2008
|
+
["sign", "verify"]
|
|
2076
2009
|
// key usages
|
|
2077
2010
|
);
|
|
2078
2011
|
}
|
|
@@ -2144,9 +2077,11 @@ var JWTAuth = class {
|
|
|
2144
2077
|
const encodedPayload = this.base64UrlEncode(this.encoder.encode(JSON.stringify(fullPayload)));
|
|
2145
2078
|
const signatureBase = `${encodedHeader}.${encodedPayload}`;
|
|
2146
2079
|
const key = await this.getSecretKey();
|
|
2147
|
-
const signature = await crypto.subtle.sign(
|
|
2148
|
-
name: "HMAC"
|
|
2149
|
-
|
|
2080
|
+
const signature = await crypto.subtle.sign(
|
|
2081
|
+
{ name: "HMAC" },
|
|
2082
|
+
key,
|
|
2083
|
+
this.encoder.encode(signatureBase)
|
|
2084
|
+
);
|
|
2150
2085
|
const encodedSignature = this.base64UrlEncode(signature);
|
|
2151
2086
|
return `${signatureBase}.${encodedSignature}`;
|
|
2152
2087
|
}
|
|
@@ -2178,9 +2113,12 @@ var JWTAuth = class {
|
|
|
2178
2113
|
const key = await this.getSecretKey();
|
|
2179
2114
|
const signatureBase = `${encodedHeader}.${encodedPayload}`;
|
|
2180
2115
|
const signature = this.base64UrlDecode(encodedSignature);
|
|
2181
|
-
const isValid = await crypto.subtle.verify(
|
|
2182
|
-
name: "HMAC"
|
|
2183
|
-
|
|
2116
|
+
const isValid = await crypto.subtle.verify(
|
|
2117
|
+
{ name: "HMAC" },
|
|
2118
|
+
key,
|
|
2119
|
+
signature,
|
|
2120
|
+
this.encoder.encode(signatureBase)
|
|
2121
|
+
);
|
|
2184
2122
|
if (!isValid) {
|
|
2185
2123
|
throw new Error("Invalid signature");
|
|
2186
2124
|
}
|
|
@@ -2195,7 +2133,7 @@ var JWTAuth = class {
|
|
|
2195
2133
|
};
|
|
2196
2134
|
|
|
2197
2135
|
// src/world.guard.ts
|
|
2198
|
-
var guardManageWorld =
|
|
2136
|
+
var guardManageWorld = async (_, req, room) => {
|
|
2199
2137
|
const tokenShard = req.headers.get("x-access-shard");
|
|
2200
2138
|
if (tokenShard) {
|
|
2201
2139
|
if (tokenShard !== room.env.SHARD_SECRET) {
|
|
@@ -2218,46 +2156,22 @@ var guardManageWorld = /* @__PURE__ */ __name(async (_, req, room) => {
|
|
|
2218
2156
|
return false;
|
|
2219
2157
|
}
|
|
2220
2158
|
return true;
|
|
2221
|
-
}
|
|
2159
|
+
};
|
|
2222
2160
|
|
|
2223
2161
|
// src/world.ts
|
|
2224
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
2225
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2226
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2227
|
-
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;
|
|
2228
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2229
|
-
}
|
|
2230
|
-
__name(_ts_decorate, "_ts_decorate");
|
|
2231
|
-
function _ts_metadata(k, v) {
|
|
2232
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2233
|
-
}
|
|
2234
|
-
__name(_ts_metadata, "_ts_metadata");
|
|
2235
2162
|
var MAX_PLAYERS_PER_SHARD = 75;
|
|
2236
2163
|
var RoomConfigSchema = z2.object({
|
|
2237
2164
|
name: z2.string(),
|
|
2238
|
-
balancingStrategy: z2.enum([
|
|
2239
|
-
"round-robin",
|
|
2240
|
-
"least-connections",
|
|
2241
|
-
"random"
|
|
2242
|
-
]),
|
|
2165
|
+
balancingStrategy: z2.enum(["round-robin", "least-connections", "random"]),
|
|
2243
2166
|
public: z2.boolean(),
|
|
2244
2167
|
maxPlayersPerShard: z2.number().int().positive(),
|
|
2245
2168
|
minShards: z2.number().int().min(0),
|
|
2246
2169
|
maxShards: z2.number().int().positive().optional()
|
|
2247
2170
|
});
|
|
2248
|
-
var RegisterShardSchema = z2.object({
|
|
2249
|
-
shardId: z2.string(),
|
|
2250
|
-
roomId: z2.string(),
|
|
2251
|
-
url: z2.string().url(),
|
|
2252
|
-
maxConnections: z2.number().int().positive()
|
|
2253
|
-
});
|
|
2254
2171
|
var UpdateShardStatsSchema = z2.object({
|
|
2172
|
+
shardId: z2.string(),
|
|
2255
2173
|
connections: z2.number().int().min(0),
|
|
2256
|
-
status: z2.enum([
|
|
2257
|
-
"active",
|
|
2258
|
-
"maintenance",
|
|
2259
|
-
"draining"
|
|
2260
|
-
]).optional()
|
|
2174
|
+
status: z2.enum(["active", "maintenance", "draining"]).optional()
|
|
2261
2175
|
});
|
|
2262
2176
|
var ScaleRoomSchema = z2.object({
|
|
2263
2177
|
roomId: z2.string(),
|
|
@@ -2267,94 +2181,77 @@ var ScaleRoomSchema = z2.object({
|
|
|
2267
2181
|
maxConnections: z2.number().int().positive()
|
|
2268
2182
|
}).optional()
|
|
2269
2183
|
});
|
|
2270
|
-
var RoomConfig = class
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
minShards = signal(1);
|
|
2280
|
-
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
|
+
}
|
|
2281
2193
|
};
|
|
2282
|
-
|
|
2283
|
-
id()
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
_ts_decorate([
|
|
2194
|
+
__decorateClass([
|
|
2195
|
+
id()
|
|
2196
|
+
], RoomConfig.prototype, "id", 2);
|
|
2197
|
+
__decorateClass([
|
|
2287
2198
|
sync()
|
|
2288
|
-
], RoomConfig.prototype, "name",
|
|
2289
|
-
|
|
2199
|
+
], RoomConfig.prototype, "name", 2);
|
|
2200
|
+
__decorateClass([
|
|
2290
2201
|
sync()
|
|
2291
|
-
], RoomConfig.prototype, "balancingStrategy",
|
|
2292
|
-
|
|
2202
|
+
], RoomConfig.prototype, "balancingStrategy", 2);
|
|
2203
|
+
__decorateClass([
|
|
2293
2204
|
sync()
|
|
2294
|
-
], RoomConfig.prototype, "public",
|
|
2295
|
-
|
|
2205
|
+
], RoomConfig.prototype, "public", 2);
|
|
2206
|
+
__decorateClass([
|
|
2296
2207
|
sync()
|
|
2297
|
-
], RoomConfig.prototype, "maxPlayersPerShard",
|
|
2298
|
-
|
|
2208
|
+
], RoomConfig.prototype, "maxPlayersPerShard", 2);
|
|
2209
|
+
__decorateClass([
|
|
2299
2210
|
sync()
|
|
2300
|
-
], RoomConfig.prototype, "minShards",
|
|
2301
|
-
|
|
2211
|
+
], RoomConfig.prototype, "minShards", 2);
|
|
2212
|
+
__decorateClass([
|
|
2302
2213
|
sync()
|
|
2303
|
-
], RoomConfig.prototype, "maxShards",
|
|
2304
|
-
var ShardInfo = class
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
status = signal("active");
|
|
2314
|
-
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
|
+
}
|
|
2315
2224
|
};
|
|
2316
|
-
|
|
2317
|
-
id()
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
_ts_decorate([
|
|
2225
|
+
__decorateClass([
|
|
2226
|
+
id()
|
|
2227
|
+
], ShardInfo.prototype, "id", 2);
|
|
2228
|
+
__decorateClass([
|
|
2321
2229
|
sync()
|
|
2322
|
-
], ShardInfo.prototype, "roomId",
|
|
2323
|
-
|
|
2230
|
+
], ShardInfo.prototype, "roomId", 2);
|
|
2231
|
+
__decorateClass([
|
|
2324
2232
|
sync()
|
|
2325
|
-
], ShardInfo.prototype, "url",
|
|
2326
|
-
|
|
2233
|
+
], ShardInfo.prototype, "url", 2);
|
|
2234
|
+
__decorateClass([
|
|
2327
2235
|
sync({
|
|
2328
2236
|
persist: false
|
|
2329
2237
|
})
|
|
2330
|
-
], ShardInfo.prototype, "currentConnections",
|
|
2331
|
-
|
|
2238
|
+
], ShardInfo.prototype, "currentConnections", 2);
|
|
2239
|
+
__decorateClass([
|
|
2332
2240
|
sync()
|
|
2333
|
-
], ShardInfo.prototype, "maxConnections",
|
|
2334
|
-
|
|
2241
|
+
], ShardInfo.prototype, "maxConnections", 2);
|
|
2242
|
+
__decorateClass([
|
|
2335
2243
|
sync()
|
|
2336
|
-
], ShardInfo.prototype, "status",
|
|
2337
|
-
|
|
2244
|
+
], ShardInfo.prototype, "status", 2);
|
|
2245
|
+
__decorateClass([
|
|
2338
2246
|
sync()
|
|
2339
|
-
], ShardInfo.prototype, "lastHeartbeat",
|
|
2247
|
+
], ShardInfo.prototype, "lastHeartbeat", 2);
|
|
2340
2248
|
var WorldRoom = class {
|
|
2341
|
-
static {
|
|
2342
|
-
__name(this, "WorldRoom");
|
|
2343
|
-
}
|
|
2344
|
-
room;
|
|
2345
|
-
// Synchronized state
|
|
2346
|
-
rooms;
|
|
2347
|
-
shards;
|
|
2348
|
-
// Only persisted state (not synced to clients)
|
|
2349
|
-
rrCounters;
|
|
2350
|
-
// Configuration
|
|
2351
|
-
defaultShardUrlTemplate;
|
|
2352
|
-
defaultMaxConnectionsPerShard;
|
|
2353
2249
|
constructor(room) {
|
|
2354
2250
|
this.room = room;
|
|
2355
2251
|
this.rooms = signal({});
|
|
2356
2252
|
this.shards = signal({});
|
|
2357
2253
|
this.rrCounters = signal({});
|
|
2254
|
+
// Configuration
|
|
2358
2255
|
this.defaultShardUrlTemplate = signal("{shardId}");
|
|
2359
2256
|
this.defaultMaxConnectionsPerShard = signal(MAX_PLAYERS_PER_SHARD);
|
|
2360
2257
|
const { AUTH_JWT_SECRET, SHARD_SECRET } = this.room.env;
|
|
@@ -2392,9 +2289,14 @@ var WorldRoom = class {
|
|
|
2392
2289
|
});
|
|
2393
2290
|
setTimeout(() => this.cleanupInactiveShards(), 6e4);
|
|
2394
2291
|
}
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
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;
|
|
2398
2300
|
const roomId = roomConfig.name;
|
|
2399
2301
|
if (!this.rooms()[roomId]) {
|
|
2400
2302
|
const newRoom = new RoomConfig();
|
|
@@ -2421,7 +2323,13 @@ var WorldRoom = class {
|
|
|
2421
2323
|
}
|
|
2422
2324
|
}
|
|
2423
2325
|
async updateShardStats(req, res) {
|
|
2424
|
-
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;
|
|
2425
2333
|
const { shardId, connections, status } = body;
|
|
2426
2334
|
const shard = this.shards()[shardId];
|
|
2427
2335
|
if (!shard) {
|
|
@@ -2434,7 +2342,13 @@ var WorldRoom = class {
|
|
|
2434
2342
|
shard.lastHeartbeat.set(Date.now());
|
|
2435
2343
|
}
|
|
2436
2344
|
async scaleRoom(req, res) {
|
|
2437
|
-
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;
|
|
2438
2352
|
const { targetShardCount, shardTemplate, roomId } = data;
|
|
2439
2353
|
const room = this.rooms()[roomId];
|
|
2440
2354
|
if (!room) {
|
|
@@ -2449,14 +2363,11 @@ var WorldRoom = class {
|
|
|
2449
2363
|
});
|
|
2450
2364
|
}
|
|
2451
2365
|
if (targetShardCount < previousShardCount) {
|
|
2452
|
-
const shardsToRemove = [
|
|
2453
|
-
...roomShards
|
|
2454
|
-
].sort((a, b) => {
|
|
2366
|
+
const shardsToRemove = [...roomShards].sort((a, b) => {
|
|
2455
2367
|
if (a.status() === "draining" && b.status() !== "draining") return -1;
|
|
2456
2368
|
if (a.status() !== "draining" && b.status() === "draining") return 1;
|
|
2457
2369
|
return a.currentConnections() - b.currentConnections();
|
|
2458
2370
|
}).slice(0, previousShardCount - targetShardCount);
|
|
2459
|
-
const shardsToKeep = roomShards.filter((shard) => !shardsToRemove.some((s) => s.id === shard.id));
|
|
2460
2371
|
for (const shard of shardsToRemove) {
|
|
2461
2372
|
delete this.shards()[shard.id];
|
|
2462
2373
|
}
|
|
@@ -2465,7 +2376,11 @@ var WorldRoom = class {
|
|
|
2465
2376
|
if (targetShardCount > previousShardCount) {
|
|
2466
2377
|
const newShards = [];
|
|
2467
2378
|
for (let i = 0; i < targetShardCount - previousShardCount; i++) {
|
|
2468
|
-
const newShard = await this.createShard(
|
|
2379
|
+
const newShard = await this.createShard(
|
|
2380
|
+
roomId,
|
|
2381
|
+
shardTemplate?.urlTemplate,
|
|
2382
|
+
shardTemplate?.maxConnections
|
|
2383
|
+
);
|
|
2469
2384
|
if (newShard) {
|
|
2470
2385
|
newShards.push(newShard);
|
|
2471
2386
|
}
|
|
@@ -2507,26 +2422,22 @@ var WorldRoom = class {
|
|
|
2507
2422
|
if (!room) {
|
|
2508
2423
|
if (autoCreate) {
|
|
2509
2424
|
const mockRequest = {
|
|
2510
|
-
json:
|
|
2425
|
+
json: async () => ({
|
|
2511
2426
|
name: roomId,
|
|
2512
2427
|
balancingStrategy: "round-robin",
|
|
2513
2428
|
public: true,
|
|
2514
2429
|
maxPlayersPerShard: this.defaultMaxConnectionsPerShard(),
|
|
2515
2430
|
minShards: 1,
|
|
2516
2431
|
maxShards: void 0
|
|
2517
|
-
})
|
|
2432
|
+
})
|
|
2518
2433
|
};
|
|
2519
2434
|
await this.registerRoom(mockRequest);
|
|
2520
2435
|
room = this.rooms()[roomId];
|
|
2521
2436
|
if (!room) {
|
|
2522
|
-
return {
|
|
2523
|
-
error: `Failed to create room ${roomId}`
|
|
2524
|
-
};
|
|
2437
|
+
return { error: `Failed to create room ${roomId}` };
|
|
2525
2438
|
}
|
|
2526
2439
|
} else {
|
|
2527
|
-
return {
|
|
2528
|
-
error: `Room ${roomId} does not exist`
|
|
2529
|
-
};
|
|
2440
|
+
return { error: `Room ${roomId} does not exist` };
|
|
2530
2441
|
}
|
|
2531
2442
|
}
|
|
2532
2443
|
const roomShards = Object.values(this.shards()).filter((shard) => shard.roomId() === roomId);
|
|
@@ -2539,27 +2450,24 @@ var WorldRoom = class {
|
|
|
2539
2450
|
url: newShard.url()
|
|
2540
2451
|
};
|
|
2541
2452
|
} else {
|
|
2542
|
-
return {
|
|
2543
|
-
error: `Failed to create shard for room ${roomId}`
|
|
2544
|
-
};
|
|
2453
|
+
return { error: `Failed to create shard for room ${roomId}` };
|
|
2545
2454
|
}
|
|
2546
2455
|
} else {
|
|
2547
|
-
return {
|
|
2548
|
-
error: `No shards available for room ${roomId}`
|
|
2549
|
-
};
|
|
2456
|
+
return { error: `No shards available for room ${roomId}` };
|
|
2550
2457
|
}
|
|
2551
2458
|
}
|
|
2552
2459
|
const activeShards = roomShards.filter((shard) => shard && shard.status() === "active");
|
|
2553
2460
|
if (activeShards.length === 0) {
|
|
2554
|
-
return {
|
|
2555
|
-
error: `No active shards available for room ${roomId}`
|
|
2556
|
-
};
|
|
2461
|
+
return { error: `No active shards available for room ${roomId}` };
|
|
2557
2462
|
}
|
|
2558
2463
|
const balancingStrategy = room.balancingStrategy();
|
|
2559
2464
|
let selectedShard;
|
|
2560
2465
|
switch (balancingStrategy) {
|
|
2561
2466
|
case "least-connections":
|
|
2562
|
-
selectedShard = activeShards.reduce(
|
|
2467
|
+
selectedShard = activeShards.reduce(
|
|
2468
|
+
(min, shard) => shard.currentConnections() < min.currentConnections() ? shard : min,
|
|
2469
|
+
activeShards[0]
|
|
2470
|
+
);
|
|
2563
2471
|
break;
|
|
2564
2472
|
case "random":
|
|
2565
2473
|
selectedShard = activeShards[Math.floor(Math.random() * activeShards.length)];
|
|
@@ -2600,82 +2508,52 @@ var WorldRoom = class {
|
|
|
2600
2508
|
return newShard;
|
|
2601
2509
|
}
|
|
2602
2510
|
};
|
|
2603
|
-
|
|
2511
|
+
__decorateClass([
|
|
2604
2512
|
sync(RoomConfig)
|
|
2605
|
-
], WorldRoom.prototype, "rooms",
|
|
2606
|
-
|
|
2513
|
+
], WorldRoom.prototype, "rooms", 2);
|
|
2514
|
+
__decorateClass([
|
|
2607
2515
|
sync(ShardInfo)
|
|
2608
|
-
], WorldRoom.prototype, "shards",
|
|
2609
|
-
|
|
2516
|
+
], WorldRoom.prototype, "shards", 2);
|
|
2517
|
+
__decorateClass([
|
|
2610
2518
|
persist()
|
|
2611
|
-
], WorldRoom.prototype, "rrCounters",
|
|
2612
|
-
|
|
2519
|
+
], WorldRoom.prototype, "rrCounters", 2);
|
|
2520
|
+
__decorateClass([
|
|
2613
2521
|
Request2({
|
|
2614
2522
|
path: "register-room",
|
|
2615
2523
|
method: "POST"
|
|
2616
2524
|
}),
|
|
2617
|
-
Guard([
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
_ts_metadata("design:type", Function),
|
|
2621
|
-
_ts_metadata("design:paramtypes", [
|
|
2622
|
-
typeof party_exports === "undefined" || typeof void 0 === "undefined" ? Object : void 0
|
|
2623
|
-
]),
|
|
2624
|
-
_ts_metadata("design:returntype", Promise)
|
|
2625
|
-
], WorldRoom.prototype, "registerRoom", null);
|
|
2626
|
-
_ts_decorate([
|
|
2525
|
+
Guard([guardManageWorld])
|
|
2526
|
+
], WorldRoom.prototype, "registerRoom", 1);
|
|
2527
|
+
__decorateClass([
|
|
2627
2528
|
Request2({
|
|
2628
2529
|
path: "update-shard",
|
|
2629
2530
|
method: "POST"
|
|
2630
2531
|
}),
|
|
2631
|
-
Guard([
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
_ts_metadata("design:type", Function),
|
|
2635
|
-
_ts_metadata("design:paramtypes", [
|
|
2636
|
-
typeof party_exports === "undefined" || typeof void 0 === "undefined" ? Object : void 0,
|
|
2637
|
-
typeof ServerResponse === "undefined" ? Object : ServerResponse
|
|
2638
|
-
]),
|
|
2639
|
-
_ts_metadata("design:returntype", Promise)
|
|
2640
|
-
], WorldRoom.prototype, "updateShardStats", null);
|
|
2641
|
-
_ts_decorate([
|
|
2532
|
+
Guard([guardManageWorld])
|
|
2533
|
+
], WorldRoom.prototype, "updateShardStats", 1);
|
|
2534
|
+
__decorateClass([
|
|
2642
2535
|
Request2({
|
|
2643
2536
|
path: "scale-room",
|
|
2644
2537
|
method: "POST"
|
|
2645
2538
|
}),
|
|
2646
|
-
Guard([
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
_ts_metadata("design:type", Function),
|
|
2650
|
-
_ts_metadata("design:paramtypes", [
|
|
2651
|
-
typeof party_exports === "undefined" || typeof void 0 === "undefined" ? Object : void 0,
|
|
2652
|
-
typeof ServerResponse === "undefined" ? Object : ServerResponse
|
|
2653
|
-
]),
|
|
2654
|
-
_ts_metadata("design:returntype", Promise)
|
|
2655
|
-
], WorldRoom.prototype, "scaleRoom", null);
|
|
2656
|
-
_ts_decorate([
|
|
2539
|
+
Guard([guardManageWorld])
|
|
2540
|
+
], WorldRoom.prototype, "scaleRoom", 1);
|
|
2541
|
+
__decorateClass([
|
|
2657
2542
|
Request2({
|
|
2658
2543
|
path: "connect",
|
|
2659
2544
|
method: "POST"
|
|
2660
|
-
})
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
typeof party_exports === "undefined" || typeof void 0 === "undefined" ? Object : void 0,
|
|
2664
|
-
typeof ServerResponse === "undefined" ? Object : ServerResponse
|
|
2665
|
-
]),
|
|
2666
|
-
_ts_metadata("design:returntype", Promise)
|
|
2667
|
-
], WorldRoom.prototype, "connect", null);
|
|
2668
|
-
WorldRoom = _ts_decorate([
|
|
2545
|
+
})
|
|
2546
|
+
], WorldRoom.prototype, "connect", 1);
|
|
2547
|
+
WorldRoom = __decorateClass([
|
|
2669
2548
|
Room({
|
|
2670
2549
|
path: "world-{worldId}",
|
|
2671
2550
|
maxUsers: 100,
|
|
2551
|
+
// Limit for admin connections
|
|
2672
2552
|
throttleStorage: 2e3,
|
|
2553
|
+
// Throttle storage updates (ms)
|
|
2673
2554
|
throttleSync: 500
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
_ts_metadata("design:paramtypes", [
|
|
2677
|
-
typeof party_exports === "undefined" || typeof void 0 === "undefined" ? Object : void 0
|
|
2678
|
-
])
|
|
2555
|
+
// Throttle sync updates (ms)
|
|
2556
|
+
})
|
|
2679
2557
|
], WorldRoom);
|
|
2680
2558
|
|
|
2681
2559
|
// src/session.guard.ts
|
|
@@ -2700,8 +2578,7 @@ function createRequireSessionGuard(storage) {
|
|
|
2700
2578
|
}
|
|
2701
2579
|
};
|
|
2702
2580
|
}
|
|
2703
|
-
|
|
2704
|
-
var requireSession = /* @__PURE__ */ __name(async (sender, value, room) => {
|
|
2581
|
+
var requireSession = async (sender, value, room) => {
|
|
2705
2582
|
if (!sender || !sender.id) {
|
|
2706
2583
|
return false;
|
|
2707
2584
|
}
|
|
@@ -2719,7 +2596,7 @@ var requireSession = /* @__PURE__ */ __name(async (sender, value, room) => {
|
|
|
2719
2596
|
console.error("Error checking session in requireSession guard:", error);
|
|
2720
2597
|
return false;
|
|
2721
2598
|
}
|
|
2722
|
-
}
|
|
2599
|
+
};
|
|
2723
2600
|
export {
|
|
2724
2601
|
Action,
|
|
2725
2602
|
ClientIo,
|
|
@@ -2732,6 +2609,7 @@ export {
|
|
|
2732
2609
|
ServerIo,
|
|
2733
2610
|
ServerResponse,
|
|
2734
2611
|
Shard,
|
|
2612
|
+
UnhandledAction,
|
|
2735
2613
|
WorldRoom,
|
|
2736
2614
|
createRequireSessionGuard,
|
|
2737
2615
|
request,
|