@signe/room 2.9.4 → 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 CHANGED
@@ -1,5 +1,11 @@
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
+
3
9
  ## 2.9.4
4
10
 
5
11
  ### 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, res?: ServerResponse): Promise<Response>;
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 randomValue = randomBytes?.[i] ?? Math.floor(Math.random() * 256);
83
- uuid += chars[randomValue % chars.length];
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.sessionExpiryTime ?? subRoom.constructor.sessionExpiryTime ?? 5 * 60 * 1e3;
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
- const pathname = this.normalizeRequestPath(url.pathname);
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 (!contentType.includes("application/json")) {
1432
- return res.badRequest("Content-Type must be application/json");
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
- return this.pathPatternToRegex(handlerPath).test(requestPath);
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 pathRegex = this.pathPatternToRegex(handlerPath);
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 UpdateShardStatsSchema = z2.object({
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, 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;
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 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;
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 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;
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
  }