@edge-base/server 0.2.4 → 0.2.6

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.
Files changed (131) hide show
  1. package/admin-build/_app/immutable/chunks/{DILS_-VJ.js → B3CvhH3c.js} +1 -1
  2. package/admin-build/_app/immutable/chunks/BN_-k-Ck.js +1 -0
  3. package/admin-build/_app/immutable/chunks/{Dt4vL4Df.js → BYL_uBga.js} +1 -1
  4. package/admin-build/_app/immutable/chunks/{C72lTcG0.js → Bcs4KYNp.js} +1 -1
  5. package/admin-build/_app/immutable/chunks/{B8s_s9QY.js → BkZCgsc3.js} +1 -1
  6. package/admin-build/_app/immutable/chunks/{BgDzp0i0.js → BvoGcDFV.js} +1 -1
  7. package/admin-build/_app/immutable/chunks/{BME_U9TJ.js → CCUxCptE.js} +1 -1
  8. package/admin-build/_app/immutable/chunks/CLHN9MVr.js +1 -0
  9. package/admin-build/_app/immutable/chunks/{DYaCRWMA.js → CR37B8DX.js} +1 -1
  10. package/admin-build/_app/immutable/chunks/CbfX3ELZ.js +1 -0
  11. package/admin-build/_app/immutable/chunks/CjcrXziO.js +2 -0
  12. package/admin-build/_app/immutable/chunks/CrwlCAM0.js +1 -0
  13. package/admin-build/_app/immutable/chunks/{B0HRJ657.js → DOOPbWwG.js} +1 -1
  14. package/admin-build/_app/immutable/chunks/DQVP4KC-.js +1 -0
  15. package/admin-build/_app/immutable/chunks/{Dj0QUuOf.js → DdvsFblq.js} +1 -1
  16. package/admin-build/_app/immutable/chunks/DemDWbs-.js +128 -0
  17. package/admin-build/_app/immutable/chunks/{XQM1k9PM.js → DmDTovpg.js} +1 -1
  18. package/admin-build/_app/immutable/chunks/{fYEKMQ-Z.js → Ff90owjx.js} +1 -1
  19. package/admin-build/_app/immutable/chunks/{5RQRbp5q.js → LL3ulaxa.js} +1 -1
  20. package/admin-build/_app/immutable/chunks/{DBsVqhuh.js → Q3vAxeY-.js} +1 -1
  21. package/admin-build/_app/immutable/chunks/{D__dwMuW.js → SQVAC3Cv.js} +1 -1
  22. package/admin-build/_app/immutable/chunks/{Z41NK6i6.js → bguI1TeA.js} +1 -1
  23. package/admin-build/_app/immutable/chunks/{_teD5ji5.js → nlAMTi52.js} +1 -1
  24. package/admin-build/_app/immutable/chunks/{BjWZuf8W.js → qBm6xof8.js} +1 -1
  25. package/admin-build/_app/immutable/entry/{app.C8ylfBe6.js → app.CP83Ni80.js} +2 -2
  26. package/admin-build/_app/immutable/entry/start.DY6YakU0.js +1 -0
  27. package/admin-build/_app/immutable/nodes/{0.CJJ6HZbp.js → 0.DiRq7puO.js} +1 -1
  28. package/admin-build/_app/immutable/nodes/1.BFeyKLGT.js +1 -0
  29. package/admin-build/_app/immutable/nodes/10.zcee7hJx.js +1 -0
  30. package/admin-build/_app/immutable/nodes/11.BW7wLs2Y.js +1 -0
  31. package/admin-build/_app/immutable/nodes/12.CxJRlYSd.js +1 -0
  32. package/admin-build/_app/immutable/nodes/13.pp0F_5hn.js +110 -0
  33. package/admin-build/_app/immutable/nodes/14.t3AfGiGo.js +3 -0
  34. package/admin-build/_app/immutable/nodes/15.B3agc7NX.js +1 -0
  35. package/admin-build/_app/immutable/nodes/{16.D0xkPUBW.js → 16.C4uG2-i8.js} +1 -1
  36. package/admin-build/_app/immutable/nodes/{17.CebNqPeh.js → 17.CwGxi1Bn.js} +1 -1
  37. package/admin-build/_app/immutable/nodes/18.CrQyN_gU.js +1 -0
  38. package/admin-build/_app/immutable/nodes/19.NEPUOXl7.js +2 -0
  39. package/admin-build/_app/immutable/nodes/{20.DYb-q3W8.js → 20.DGHO8ipr.js} +1 -1
  40. package/admin-build/_app/immutable/nodes/21.UVKBDvp4.js +1 -0
  41. package/admin-build/_app/immutable/nodes/22.Dri5It7a.js +1 -0
  42. package/admin-build/_app/immutable/nodes/{23.BLgq21om.js → 23.BPQP_Zte.js} +2 -2
  43. package/admin-build/_app/immutable/nodes/24.D580FdSS.js +2 -0
  44. package/admin-build/_app/immutable/nodes/25.BMNPOZwF.js +2 -0
  45. package/admin-build/_app/immutable/nodes/26.XcpEcbiz.js +1 -0
  46. package/admin-build/_app/immutable/nodes/27.C1zHHcYv.js +1 -0
  47. package/admin-build/_app/immutable/nodes/28.CuKzzrY8.js +1 -0
  48. package/admin-build/_app/immutable/nodes/29.nLpBMXnM.js +1 -0
  49. package/admin-build/_app/immutable/nodes/{3.z8ut3jS-.js → 3.5G_aseoL.js} +1 -1
  50. package/admin-build/_app/immutable/nodes/30.CQC4nLoU.js +1 -0
  51. package/admin-build/_app/immutable/nodes/31.Bet8kxOK.js +1 -0
  52. package/admin-build/_app/immutable/nodes/4.nmJDYJpC.js +1 -0
  53. package/admin-build/_app/immutable/nodes/5.CnbYLG4E.js +1 -0
  54. package/admin-build/_app/immutable/nodes/6.KA01b-3y.js +1 -0
  55. package/admin-build/_app/immutable/nodes/7.CP9fkn1L.js +1 -0
  56. package/admin-build/_app/immutable/nodes/8.BTzDb---.js +1 -0
  57. package/admin-build/_app/immutable/nodes/9.DkNJg_J6.js +1 -0
  58. package/admin-build/_app/version.json +1 -1
  59. package/admin-build/index.html +7 -7
  60. package/package.json +3 -3
  61. package/src/__tests__/database-do-route-validation.test.ts +10 -7
  62. package/src/__tests__/meta-route-registration.test.ts +20 -15
  63. package/src/__tests__/push-handlers.test.ts +1 -1
  64. package/src/__tests__/room-auth-state-loss.test.ts +122 -0
  65. package/src/__tests__/room-handler-context.test.ts +4 -4
  66. package/src/__tests__/room-rate-limit-scopes.test.ts +38 -0
  67. package/src/__tests__/room-runtime-routing.test.ts +23 -0
  68. package/src/__tests__/route-parser.test.ts +6 -0
  69. package/src/__tests__/runtime-startup.test.ts +49 -0
  70. package/src/__tests__/schema.test.ts +15 -6
  71. package/src/durable-objects/database-do.ts +21 -1
  72. package/src/durable-objects/database-live-do.ts +15 -0
  73. package/src/durable-objects/room-runtime-base.ts +436 -169
  74. package/src/durable-objects/rooms-do.ts +63 -25
  75. package/src/index.ts +340 -280
  76. package/src/lib/d1-handler.ts +32 -17
  77. package/src/lib/postgres-handler.ts +24 -12
  78. package/src/lib/route-parser.ts +3 -0
  79. package/src/lib/runtime-startup.ts +53 -0
  80. package/src/lib/schemas.ts +12 -2
  81. package/src/middleware/captcha-verify.ts +16 -3
  82. package/src/middleware/error-handler.ts +1 -1
  83. package/src/middleware/rules.ts +28 -9
  84. package/src/routes/admin-auth.ts +3 -3
  85. package/src/routes/admin.ts +13 -8
  86. package/src/routes/analytics-api.ts +3 -3
  87. package/src/routes/auth.ts +1 -1
  88. package/src/routes/backup.ts +1 -1
  89. package/src/routes/d1.ts +14 -7
  90. package/src/routes/database-live.ts +13 -6
  91. package/src/routes/kv.ts +21 -10
  92. package/src/routes/oauth.ts +1 -1
  93. package/src/routes/push.ts +119 -77
  94. package/src/routes/room.ts +215 -7
  95. package/src/routes/schema-endpoint.ts +2 -2
  96. package/src/routes/sql.ts +10 -6
  97. package/src/routes/storage.ts +4 -2
  98. package/src/routes/vectorize.ts +16 -4
  99. package/admin-build/_app/immutable/chunks/BYI6CUvd.js +0 -1
  100. package/admin-build/_app/immutable/chunks/C6lpZLE2.js +0 -1
  101. package/admin-build/_app/immutable/chunks/CoI6jjbg.js +0 -2
  102. package/admin-build/_app/immutable/chunks/D5GswVnI.js +0 -128
  103. package/admin-build/_app/immutable/chunks/Dj-E9-FO.js +0 -1
  104. package/admin-build/_app/immutable/chunks/g_-Kpxu3.js +0 -1
  105. package/admin-build/_app/immutable/chunks/wCNueVYy.js +0 -1
  106. package/admin-build/_app/immutable/entry/start.CtsqDyfj.js +0 -1
  107. package/admin-build/_app/immutable/nodes/1.B4sI5cB4.js +0 -1
  108. package/admin-build/_app/immutable/nodes/10.D6hvCer6.js +0 -1
  109. package/admin-build/_app/immutable/nodes/11.Dx7b8aQ5.js +0 -1
  110. package/admin-build/_app/immutable/nodes/12.Bqmy5KIF.js +0 -1
  111. package/admin-build/_app/immutable/nodes/13.CC6KpXgS.js +0 -110
  112. package/admin-build/_app/immutable/nodes/14.yCo1Ix8E.js +0 -3
  113. package/admin-build/_app/immutable/nodes/15.co0UfPlh.js +0 -1
  114. package/admin-build/_app/immutable/nodes/18.JUoLOZxh.js +0 -1
  115. package/admin-build/_app/immutable/nodes/19.ND8kmQJe.js +0 -2
  116. package/admin-build/_app/immutable/nodes/21.cz3IN9Cc.js +0 -1
  117. package/admin-build/_app/immutable/nodes/22.UOzm8WYV.js +0 -1
  118. package/admin-build/_app/immutable/nodes/24.DN9usmUs.js +0 -2
  119. package/admin-build/_app/immutable/nodes/25.BddRfAyE.js +0 -2
  120. package/admin-build/_app/immutable/nodes/26.Dl6XHIeT.js +0 -1
  121. package/admin-build/_app/immutable/nodes/27.D0iNwALG.js +0 -1
  122. package/admin-build/_app/immutable/nodes/28.9dKQmdGi.js +0 -1
  123. package/admin-build/_app/immutable/nodes/29.wXzfJUXp.js +0 -1
  124. package/admin-build/_app/immutable/nodes/30.BtZETNsL.js +0 -1
  125. package/admin-build/_app/immutable/nodes/31.CYonj2Jh.js +0 -1
  126. package/admin-build/_app/immutable/nodes/4.COtDPQ9b.js +0 -1
  127. package/admin-build/_app/immutable/nodes/5.CTRCeIhp.js +0 -1
  128. package/admin-build/_app/immutable/nodes/6.ChHi3QkR.js +0 -1
  129. package/admin-build/_app/immutable/nodes/7.CCMtr6Ac.js +0 -1
  130. package/admin-build/_app/immutable/nodes/8.DpWJ-X_-.js +0 -1
  131. package/admin-build/_app/immutable/nodes/9.DOkvfmir.js +0 -1
@@ -1,12 +1,11 @@
1
1
  import {
2
- getRoomHooks,
3
2
  type AuthContext as SharedAuthContext,
4
3
  type RoomMemberInfo,
4
+ type RoomNamespaceConfig,
5
5
  type RoomSender,
6
6
  type RoomServerAPI,
7
7
  } from '@edge-base/shared';
8
8
  import {
9
- createCloudflareRealtimeClient,
10
9
  type CloudflareRealtimeCloseTracksRequest,
11
10
  type CloudflareRealtimeNewSessionRequest,
12
11
  type CloudflareRealtimeNewSessionResponse,
@@ -14,7 +13,6 @@ import {
14
13
  type CloudflareRealtimeTracksRequest,
15
14
  type CloudflareRealtimeTracksResponse,
16
15
  } from '../lib/cloudflare-realtime.js';
17
- import { resolveAuthContextFromToken } from '../middleware/auth.js';
18
16
  import type { Env } from '../types.js';
19
17
  import { RoomRuntimeBaseDO, type RoomWSMeta } from './room-runtime-base.js';
20
18
 
@@ -96,6 +94,17 @@ interface RoomMemberPresence {
96
94
  state: Record<string, unknown>;
97
95
  }
98
96
 
97
+ interface RoomSummaryResponse {
98
+ namespace: string;
99
+ roomId: string;
100
+ metadata: Record<string, unknown>;
101
+ occupancy: {
102
+ activeMembers: number;
103
+ activeConnections: number;
104
+ };
105
+ updatedAt: string;
106
+ }
107
+
99
108
  interface RoomMemberRealtimeSession {
100
109
  sessionId: string;
101
110
  connectionId?: string;
@@ -117,6 +126,10 @@ const MEDIA_DENIED = Symbol('rooms.media.denied');
117
126
  const WEBSOCKET_OPEN = 1;
118
127
  const CLOUDFLARE_REALTIME_KIT_MEETING_STORAGE_KEY = 'cloudflareRealtimeKitMeetingId';
119
128
 
129
+ function getRoomHooks(namespaceConfig?: RoomNamespaceConfig | null) {
130
+ return namespaceConfig?.hooks;
131
+ }
132
+
120
133
  function computeStateDelta(
121
134
  previous: Record<string, unknown>,
122
135
  next: Record<string, unknown>,
@@ -153,6 +166,10 @@ export class RoomsDO extends RoomRuntimeBaseDO {
153
166
  override async fetch(request: Request): Promise<Response> {
154
167
  const url = new URL(request.url);
155
168
 
169
+ if (url.pathname === '/summary' && request.method === 'GET') {
170
+ return this.handleSummaryGet(url);
171
+ }
172
+
156
173
  if (url.pathname === '/media/cloudflare_realtimekit/session' && request.method === 'POST') {
157
174
  return this.handleCloudflareRealtimeKitSessionCreate(request, url);
158
175
  }
@@ -182,6 +199,22 @@ export class RoomsDO extends RoomRuntimeBaseDO {
182
199
  return super.fetch(request);
183
200
  }
184
201
 
202
+ private async handleSummaryGet(url: URL): Promise<Response> {
203
+ this.hydrateRoomIdentityFromUrl(url);
204
+ const metadata = await this.getRoomMetadataSnapshot();
205
+
206
+ return this.jsonResponse<RoomSummaryResponse>(200, {
207
+ namespace: this.namespace ?? '',
208
+ roomId: this.roomId ?? '',
209
+ metadata,
210
+ occupancy: {
211
+ activeMembers: this.members.size,
212
+ activeConnections: this.joinedConnectionIds.size,
213
+ },
214
+ updatedAt: new Date().toISOString(),
215
+ });
216
+ }
217
+
185
218
  private async handleCloudflareRealtimeKitSessionCreate(request: Request, url: URL): Promise<Response> {
186
219
  try {
187
220
  const body = await this.readJsonBody<{
@@ -250,7 +283,7 @@ export class RoomsDO extends RoomRuntimeBaseDO {
250
283
  });
251
284
  }
252
285
 
253
- const client = this.buildRealtimeClient();
286
+ const client = await this.buildRealtimeClient();
254
287
  const response = await client.createSession(
255
288
  {
256
289
  sessionDescription: body.sessionDescription,
@@ -311,7 +344,7 @@ export class RoomsDO extends RoomRuntimeBaseDO {
311
344
  try {
312
345
  const body = await this.readJsonBody<{ ttl?: number }>(request);
313
346
  await this.authenticateRealtimeRequest(request, url);
314
- const client = this.buildRealtimeClient();
347
+ const client = await this.buildRealtimeClient();
315
348
  const ttl = typeof body.ttl === 'number' && Number.isFinite(body.ttl) && body.ttl > 0
316
349
  ? Math.floor(body.ttl)
317
350
  : 3600;
@@ -354,7 +387,8 @@ export class RoomsDO extends RoomRuntimeBaseDO {
354
387
  throw new Error('tracks is required');
355
388
  }
356
389
 
357
- const response = await this.buildRealtimeClient().addTracks(sessionId, {
390
+ const client = await this.buildRealtimeClient();
391
+ const response = await client.addTracks(sessionId, {
358
392
  sessionDescription: body.sessionDescription,
359
393
  tracks: body.tracks,
360
394
  autoDiscover: body.autoDiscover === true,
@@ -410,7 +444,8 @@ export class RoomsDO extends RoomRuntimeBaseDO {
410
444
  throw new Error('sessionDescription is required');
411
445
  }
412
446
 
413
- const response = await this.buildRealtimeClient().renegotiate(sessionId, {
447
+ const client = await this.buildRealtimeClient();
448
+ const response = await client.renegotiate(sessionId, {
414
449
  sessionDescription: body.sessionDescription,
415
450
  });
416
451
  this.assertRealtimeTracksResponseSuccess(response);
@@ -447,7 +482,8 @@ export class RoomsDO extends RoomRuntimeBaseDO {
447
482
  throw new Error('tracks is required');
448
483
  }
449
484
 
450
- const response = await this.buildRealtimeClient().closeTracks(sessionId, {
485
+ const client = await this.buildRealtimeClient();
486
+ const response = await client.closeTracks(sessionId, {
451
487
  sessionDescription: body.sessionDescription,
452
488
  tracks: body.tracks,
453
489
  force: body.force === true,
@@ -472,7 +508,8 @@ export class RoomsDO extends RoomRuntimeBaseDO {
472
508
  }
473
509
  }
474
510
 
475
- private buildRealtimeClient() {
511
+ private async buildRealtimeClient() {
512
+ const { createCloudflareRealtimeClient } = await import('../lib/cloudflare-realtime.js');
476
513
  return createCloudflareRealtimeClient(this.env as unknown as Env);
477
514
  }
478
515
 
@@ -633,9 +670,10 @@ export class RoomsDO extends RoomRuntimeBaseDO {
633
670
 
634
671
  const token = this.extractBearerToken(request);
635
672
  if (!token) {
636
- throw new Error('Authentication required');
673
+ throw new Error('Authentication required before the room connection could be established.');
637
674
  }
638
675
 
676
+ const { resolveAuthContextFromToken } = await import('../middleware/auth.js');
639
677
  const auth = await resolveAuthContextFromToken(this.env, token, request);
640
678
  const memberId = auth.id;
641
679
  const member = this.members.get(memberId);
@@ -758,7 +796,7 @@ export class RoomsDO extends RoomRuntimeBaseDO {
758
796
 
759
797
  const event = typeof msg.event === 'string' ? msg.event : '';
760
798
  const requestId = typeof msg.requestId === 'string' ? msg.requestId : undefined;
761
- if (!this.checkRateLimit(meta.connectionId)) {
799
+ if (!this.checkRateLimit(meta.connectionId, 'signals')) {
762
800
  this.safeSend(ws, {
763
801
  type: 'signal_error',
764
802
  event,
@@ -806,7 +844,7 @@ export class RoomsDO extends RoomRuntimeBaseDO {
806
844
 
807
845
  const operation = typeof msg.operation === 'string' ? msg.operation : '';
808
846
  const requestId = typeof msg.requestId === 'string' ? msg.requestId : undefined;
809
- if (!this.checkRateLimit(meta.connectionId)) {
847
+ if (!this.checkRateLimit(meta.connectionId, 'admin')) {
810
848
  this.safeSend(ws, {
811
849
  type: 'admin_error',
812
850
  operation,
@@ -833,7 +871,7 @@ export class RoomsDO extends RoomRuntimeBaseDO {
833
871
  const operation = this.normalizeMediaOperation(msg.operation);
834
872
  const kind = this.normalizeMediaKind(msg.kind);
835
873
  const requestId = typeof msg.requestId === 'string' ? msg.requestId : undefined;
836
- if (!this.checkRateLimit(meta.connectionId)) {
874
+ if (!this.checkRateLimit(meta.connectionId, 'media')) {
837
875
  this.safeSend(ws, {
838
876
  type: 'media_error',
839
877
  operation: operation ?? '',
@@ -1450,7 +1488,7 @@ export class RoomsDO extends RoomRuntimeBaseDO {
1450
1488
  const beforeSend = getRoomHooks(this.namespaceConfig ?? undefined)?.signals?.beforeSend;
1451
1489
  if (!beforeSend) return signal.payload;
1452
1490
 
1453
- const ctx = this.buildHandlerContext();
1491
+ const ctx = await this.buildHandlerContext();
1454
1492
  const result = await Promise.resolve(
1455
1493
  beforeSend(signal.event, signal.payload, signal.sender, signal.roomApi, ctx),
1456
1494
  );
@@ -1468,7 +1506,7 @@ export class RoomsDO extends RoomRuntimeBaseDO {
1468
1506
  if (!onSend) return;
1469
1507
 
1470
1508
  try {
1471
- const ctx = this.buildHandlerContext();
1509
+ const ctx = await this.buildHandlerContext();
1472
1510
  await Promise.resolve(onSend(event, payload, sender, roomApi, ctx));
1473
1511
  } catch (err) {
1474
1512
  console.error(`[Rooms] signal.onSend error: ${err instanceof Error ? err.message : String(err)}`);
@@ -1481,7 +1519,7 @@ export class RoomsDO extends RoomRuntimeBaseDO {
1481
1519
 
1482
1520
  try {
1483
1521
  const roomApi = this.buildRoomServerAPI();
1484
- const ctx = this.buildHandlerContext();
1522
+ const ctx = await this.buildHandlerContext();
1485
1523
  await Promise.resolve(onJoin(member, roomApi, ctx));
1486
1524
  } catch (err) {
1487
1525
  console.error(`[Rooms] members.onJoin error: ${err instanceof Error ? err.message : String(err)}`);
@@ -1497,7 +1535,7 @@ export class RoomsDO extends RoomRuntimeBaseDO {
1497
1535
 
1498
1536
  try {
1499
1537
  const roomApi = this.buildRoomServerAPI();
1500
- const ctx = this.buildHandlerContext();
1538
+ const ctx = await this.buildHandlerContext();
1501
1539
  await Promise.resolve(onLeave(member, roomApi, ctx, reason));
1502
1540
  } catch (err) {
1503
1541
  console.error(`[Rooms] members.onLeave error: ${err instanceof Error ? err.message : String(err)}`);
@@ -1513,7 +1551,7 @@ export class RoomsDO extends RoomRuntimeBaseDO {
1513
1551
 
1514
1552
  try {
1515
1553
  const roomApi = this.buildRoomServerAPI();
1516
- const ctx = this.buildHandlerContext();
1554
+ const ctx = await this.buildHandlerContext();
1517
1555
  await Promise.resolve(onStateChange(member, state, roomApi, ctx));
1518
1556
  } catch (err) {
1519
1557
  console.error(`[Rooms] members.onStateChange error: ${err instanceof Error ? err.message : String(err)}`);
@@ -1528,7 +1566,7 @@ export class RoomsDO extends RoomRuntimeBaseDO {
1528
1566
  if (!onStateChange) return;
1529
1567
 
1530
1568
  try {
1531
- const ctx = this.buildHandlerContext();
1569
+ const ctx = await this.buildHandlerContext();
1532
1570
  await Promise.resolve(onStateChange(delta, roomApi, ctx));
1533
1571
  } catch (err) {
1534
1572
  console.error(`[Rooms] state.onStateChange error: ${err instanceof Error ? err.message : String(err)}`);
@@ -1541,7 +1579,7 @@ export class RoomsDO extends RoomRuntimeBaseDO {
1541
1579
 
1542
1580
  try {
1543
1581
  const roomApi = this.buildRoomServerAPI();
1544
- const ctx = this.buildHandlerContext();
1582
+ const ctx = await this.buildHandlerContext();
1545
1583
  await Promise.resolve(onReconnect(sender, roomApi, ctx));
1546
1584
  } catch (err) {
1547
1585
  console.error(`[Rooms] session.onReconnect error: ${err instanceof Error ? err.message : String(err)}`);
@@ -1554,7 +1592,7 @@ export class RoomsDO extends RoomRuntimeBaseDO {
1554
1592
 
1555
1593
  try {
1556
1594
  const roomApi = this.buildRoomServerAPI();
1557
- const ctx = this.buildHandlerContext();
1595
+ const ctx = await this.buildHandlerContext();
1558
1596
  await Promise.resolve(onDisconnectTimeout(sender, roomApi, ctx));
1559
1597
  } catch (err) {
1560
1598
  console.error(`[Rooms] session.onDisconnectTimeout error: ${err instanceof Error ? err.message : String(err)}`);
@@ -1919,7 +1957,7 @@ export class RoomsDO extends RoomRuntimeBaseDO {
1919
1957
  return undefined;
1920
1958
  }
1921
1959
 
1922
- const ctx = this.buildHandlerContext();
1960
+ const ctx = await this.buildHandlerContext();
1923
1961
  const result = await Promise.resolve(beforePublish(kind, sender, roomApi, ctx));
1924
1962
  if (result === false) {
1925
1963
  return MEDIA_DENIED;
@@ -1936,7 +1974,7 @@ export class RoomsDO extends RoomRuntimeBaseDO {
1936
1974
  if (!onPublished) return;
1937
1975
 
1938
1976
  try {
1939
- const ctx = this.buildHandlerContext();
1977
+ const ctx = await this.buildHandlerContext();
1940
1978
  await Promise.resolve(onPublished(kind, sender, roomApi, ctx));
1941
1979
  } catch (err) {
1942
1980
  console.error(`[Rooms] media.onPublished error: ${err instanceof Error ? err.message : String(err)}`);
@@ -1952,7 +1990,7 @@ export class RoomsDO extends RoomRuntimeBaseDO {
1952
1990
  if (!onUnpublished) return;
1953
1991
 
1954
1992
  try {
1955
- const ctx = this.buildHandlerContext();
1993
+ const ctx = await this.buildHandlerContext();
1956
1994
  await Promise.resolve(onUnpublished(kind, sender, roomApi, ctx));
1957
1995
  } catch (err) {
1958
1996
  console.error(`[Rooms] media.onUnpublished error: ${err instanceof Error ? err.message : String(err)}`);
@@ -1969,7 +2007,7 @@ export class RoomsDO extends RoomRuntimeBaseDO {
1969
2007
  if (!onMuteChange) return;
1970
2008
 
1971
2009
  try {
1972
- const ctx = this.buildHandlerContext();
2010
+ const ctx = await this.buildHandlerContext();
1973
2011
  await Promise.resolve(onMuteChange(kind, sender, muted, roomApi, ctx));
1974
2012
  } catch (err) {
1975
2013
  console.error(`[Rooms] media.onMuteChange error: ${err instanceof Error ? err.message : String(err)}`);