@signe/room 2.9.3 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/index.d.ts +1 -3
- package/dist/index.js +32 -57
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/readme.md +6 -7
- package/src/jwt.ts +5 -1
- package/src/server.ts +27 -40
- package/src/world.ts +70 -79
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @signe/room
|
|
2
2
|
|
|
3
|
+
## 2.10.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Reset the package line to the 2.9.0 runtime baseline for the 2.10 release.
|
|
8
|
+
|
|
9
|
+
## 2.9.4
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [35643c0]
|
|
14
|
+
- @signe/sync@2.9.4
|
|
15
|
+
|
|
3
16
|
## 2.9.3
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -528,8 +528,6 @@ declare class Server implements Server$1 {
|
|
|
528
528
|
* @returns {Object} An object containing the path parameters
|
|
529
529
|
*/
|
|
530
530
|
private extractPathParams;
|
|
531
|
-
private normalizeRequestPath;
|
|
532
|
-
private pathPatternToRegex;
|
|
533
531
|
/**
|
|
534
532
|
* @method handleShardRequest
|
|
535
533
|
* @private
|
|
@@ -868,7 +866,7 @@ declare class WorldRoom implements RoomInterceptorPacket, RoomOnJoin {
|
|
|
868
866
|
onJoin(user: any, conn: Connection, ctx: ConnectionContext): Promise<void>;
|
|
869
867
|
interceptorPacket(_: any, obj: any, conn: Connection): any;
|
|
870
868
|
private cleanupInactiveShards;
|
|
871
|
-
registerRoom(req: Request$1
|
|
869
|
+
registerRoom(req: Request$1): Promise<void>;
|
|
872
870
|
updateShardStats(req: Request$1, res: ServerResponse): Promise<Response>;
|
|
873
871
|
scaleRoom(req: Request$1, res: ServerResponse): Promise<Response>;
|
|
874
872
|
connect(req: Request$1, res: ServerResponse): Promise<Response>;
|
package/dist/index.js
CHANGED
|
@@ -76,11 +76,10 @@ function Guard(guards) {
|
|
|
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;
|
|
80
79
|
let uuid = "";
|
|
81
80
|
for (let i = 0; i < 8; i++) {
|
|
82
|
-
const
|
|
83
|
-
uuid += chars[
|
|
81
|
+
const randomIndex = Math.floor(Math.random() * chars.length);
|
|
82
|
+
uuid += chars[randomIndex];
|
|
84
83
|
}
|
|
85
84
|
return uuid;
|
|
86
85
|
}
|
|
@@ -882,7 +881,7 @@ var Server = class {
|
|
|
882
881
|
conn.close();
|
|
883
882
|
return;
|
|
884
883
|
}
|
|
885
|
-
const sessionExpiryTime = subRoom.
|
|
884
|
+
const sessionExpiryTime = subRoom.constructor.sessionExpiryTime;
|
|
886
885
|
await this.garbageCollector({ sessionExpiryTime });
|
|
887
886
|
const roomGuards = subRoom.constructor["_roomGuards"] || [];
|
|
888
887
|
for (const guard of roomGuards) {
|
|
@@ -1404,7 +1403,8 @@ var Server = class {
|
|
|
1404
1403
|
}
|
|
1405
1404
|
const url = new URL(req.url);
|
|
1406
1405
|
const method = req.method;
|
|
1407
|
-
|
|
1406
|
+
let pathname = url.pathname;
|
|
1407
|
+
pathname = "/" + pathname.split("/").slice(4).join("/");
|
|
1408
1408
|
for (const [routeKey, handler] of requestHandlers.entries()) {
|
|
1409
1409
|
const firstColonIndex = routeKey.indexOf(":");
|
|
1410
1410
|
const handlerMethod = routeKey.substring(0, firstColonIndex);
|
|
@@ -1428,17 +1428,16 @@ var Server = class {
|
|
|
1428
1428
|
if (handler.bodyValidation && ["POST", "PUT", "PATCH"].includes(method)) {
|
|
1429
1429
|
try {
|
|
1430
1430
|
const contentType = req.headers.get("content-type") || "";
|
|
1431
|
-
if (
|
|
1432
|
-
|
|
1431
|
+
if (contentType.includes("application/json")) {
|
|
1432
|
+
const body = await req.json();
|
|
1433
|
+
const validation = handler.bodyValidation.safeParse(body);
|
|
1434
|
+
if (!validation.success) {
|
|
1435
|
+
return res.badRequest("Invalid request body", {
|
|
1436
|
+
details: validation.error
|
|
1437
|
+
});
|
|
1438
|
+
}
|
|
1439
|
+
bodyData = validation.data;
|
|
1433
1440
|
}
|
|
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;
|
|
1442
1441
|
} catch (error) {
|
|
1443
1442
|
return res.badRequest("Failed to parse request body");
|
|
1444
1443
|
}
|
|
@@ -1470,7 +1469,9 @@ var Server = class {
|
|
|
1470
1469
|
* @returns {boolean} True if the paths match
|
|
1471
1470
|
*/
|
|
1472
1471
|
pathMatches(requestPath, handlerPath) {
|
|
1473
|
-
|
|
1472
|
+
const pathRegexString = handlerPath.replace(/\//g, "\\/").replace(/:([^\/]+)/g, "([^/]+)");
|
|
1473
|
+
const pathRegex = new RegExp(`^${pathRegexString}`);
|
|
1474
|
+
return pathRegex.test(requestPath);
|
|
1474
1475
|
}
|
|
1475
1476
|
/**
|
|
1476
1477
|
* @method extractPathParams
|
|
@@ -1488,7 +1489,8 @@ var Server = class {
|
|
|
1488
1489
|
paramNames.push(segment.substring(1));
|
|
1489
1490
|
}
|
|
1490
1491
|
});
|
|
1491
|
-
const
|
|
1492
|
+
const pathRegexString = handlerPath.replace(/\//g, "\\/").replace(/:([^\/]+)/g, "([^/]+)");
|
|
1493
|
+
const pathRegex = new RegExp(`^${pathRegexString}`);
|
|
1492
1494
|
const matches = requestPath.match(pathRegex);
|
|
1493
1495
|
if (matches && matches.length > 1) {
|
|
1494
1496
|
for (let i = 0; i < paramNames.length; i++) {
|
|
@@ -1497,23 +1499,6 @@ var Server = class {
|
|
|
1497
1499
|
}
|
|
1498
1500
|
return params;
|
|
1499
1501
|
}
|
|
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
|
-
}
|
|
1517
1502
|
/**
|
|
1518
1503
|
* @method handleShardRequest
|
|
1519
1504
|
* @private
|
|
@@ -2168,8 +2153,13 @@ var RoomConfigSchema = z2.object({
|
|
|
2168
2153
|
minShards: z2.number().int().min(0),
|
|
2169
2154
|
maxShards: z2.number().int().positive().optional()
|
|
2170
2155
|
});
|
|
2171
|
-
var
|
|
2156
|
+
var RegisterShardSchema = z2.object({
|
|
2172
2157
|
shardId: z2.string(),
|
|
2158
|
+
roomId: z2.string(),
|
|
2159
|
+
url: z2.string().url(),
|
|
2160
|
+
maxConnections: z2.number().int().positive()
|
|
2161
|
+
});
|
|
2162
|
+
var UpdateShardStatsSchema = z2.object({
|
|
2173
2163
|
connections: z2.number().int().min(0),
|
|
2174
2164
|
status: z2.enum(["active", "maintenance", "draining"]).optional()
|
|
2175
2165
|
});
|
|
@@ -2289,14 +2279,8 @@ var WorldRoom = class {
|
|
|
2289
2279
|
});
|
|
2290
2280
|
setTimeout(() => this.cleanupInactiveShards(), 6e4);
|
|
2291
2281
|
}
|
|
2292
|
-
async registerRoom(req
|
|
2293
|
-
const
|
|
2294
|
-
if (!roomConfigResult.success) {
|
|
2295
|
-
return res?.badRequest("Invalid room configuration", {
|
|
2296
|
-
details: roomConfigResult.error
|
|
2297
|
-
});
|
|
2298
|
-
}
|
|
2299
|
-
const roomConfig = roomConfigResult.data;
|
|
2282
|
+
async registerRoom(req) {
|
|
2283
|
+
const roomConfig = await req.json();
|
|
2300
2284
|
const roomId = roomConfig.name;
|
|
2301
2285
|
if (!this.rooms()[roomId]) {
|
|
2302
2286
|
const newRoom = new RoomConfig();
|
|
@@ -2323,13 +2307,7 @@ var WorldRoom = class {
|
|
|
2323
2307
|
}
|
|
2324
2308
|
}
|
|
2325
2309
|
async updateShardStats(req, res) {
|
|
2326
|
-
const
|
|
2327
|
-
if (!bodyResult.success) {
|
|
2328
|
-
return res.badRequest("Invalid shard statistics", {
|
|
2329
|
-
details: bodyResult.error
|
|
2330
|
-
});
|
|
2331
|
-
}
|
|
2332
|
-
const body = bodyResult.data;
|
|
2310
|
+
const body = await req.json();
|
|
2333
2311
|
const { shardId, connections, status } = body;
|
|
2334
2312
|
const shard = this.shards()[shardId];
|
|
2335
2313
|
if (!shard) {
|
|
@@ -2342,13 +2320,7 @@ var WorldRoom = class {
|
|
|
2342
2320
|
shard.lastHeartbeat.set(Date.now());
|
|
2343
2321
|
}
|
|
2344
2322
|
async scaleRoom(req, res) {
|
|
2345
|
-
const
|
|
2346
|
-
if (!dataResult.success) {
|
|
2347
|
-
return res.badRequest("Invalid scale request", {
|
|
2348
|
-
details: dataResult.error
|
|
2349
|
-
});
|
|
2350
|
-
}
|
|
2351
|
-
const data = dataResult.data;
|
|
2323
|
+
const data = await req.json();
|
|
2352
2324
|
const { targetShardCount, shardTemplate, roomId } = data;
|
|
2353
2325
|
const room = this.rooms()[roomId];
|
|
2354
2326
|
if (!room) {
|
|
@@ -2368,6 +2340,9 @@ var WorldRoom = class {
|
|
|
2368
2340
|
if (a.status() !== "draining" && b.status() === "draining") return 1;
|
|
2369
2341
|
return a.currentConnections() - b.currentConnections();
|
|
2370
2342
|
}).slice(0, previousShardCount - targetShardCount);
|
|
2343
|
+
const shardsToKeep = roomShards.filter(
|
|
2344
|
+
(shard) => !shardsToRemove.some((s) => s.id === shard.id)
|
|
2345
|
+
);
|
|
2371
2346
|
for (const shard of shardsToRemove) {
|
|
2372
2347
|
delete this.shards()[shard.id];
|
|
2373
2348
|
}
|