rivetkit 2.0.22-rc.1 → 2.0.22

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 (124) hide show
  1. package/dist/schemas/actor-persist/v2.ts +259 -0
  2. package/dist/tsup/{chunk-LCQDY73V.cjs → chunk-2GJILCGQ.cjs} +3 -3
  3. package/dist/tsup/{chunk-LCQDY73V.cjs.map → chunk-2GJILCGQ.cjs.map} +1 -1
  4. package/dist/tsup/{chunk-JN6GPVFY.js → chunk-2K2LR56Q.js} +3 -3
  5. package/dist/tsup/{chunk-EEXX243L.js → chunk-2WVCZCJL.js} +6 -6
  6. package/dist/tsup/{chunk-FETQGZN4.js → chunk-3BJJSSTM.js} +272 -89
  7. package/dist/tsup/chunk-3BJJSSTM.js.map +1 -0
  8. package/dist/tsup/{chunk-ZZYMCYAY.cjs → chunk-3LFMVAJV.cjs} +14 -14
  9. package/dist/tsup/{chunk-ZZYMCYAY.cjs.map → chunk-3LFMVAJV.cjs.map} +1 -1
  10. package/dist/tsup/{chunk-NDLOG2JH.js → chunk-6YQKMAMV.js} +2 -2
  11. package/dist/tsup/{chunk-C2U6KGOG.cjs → chunk-AR4S2QJ7.cjs} +3 -3
  12. package/dist/tsup/{chunk-C2U6KGOG.cjs.map → chunk-AR4S2QJ7.cjs.map} +1 -1
  13. package/dist/tsup/{chunk-PELXJCJS.cjs → chunk-B4QZKOMH.cjs} +8 -8
  14. package/dist/tsup/{chunk-PELXJCJS.cjs.map → chunk-B4QZKOMH.cjs.map} +1 -1
  15. package/dist/tsup/{chunk-5EB77IQ2.cjs → chunk-CYA35VI3.cjs} +6 -6
  16. package/dist/tsup/{chunk-5EB77IQ2.cjs.map → chunk-CYA35VI3.cjs.map} +1 -1
  17. package/dist/tsup/{chunk-UBCUW7HD.js → chunk-D7AA2DK5.js} +2 -2
  18. package/dist/tsup/{chunk-I7EJWHYV.js → chunk-EBSGEDD3.js} +51 -47
  19. package/dist/tsup/chunk-EBSGEDD3.js.map +1 -0
  20. package/dist/tsup/{chunk-R6XOZKMU.cjs → chunk-HSO2H2SB.cjs} +467 -284
  21. package/dist/tsup/chunk-HSO2H2SB.cjs.map +1 -0
  22. package/dist/tsup/{chunk-VJLGVVGP.cjs → chunk-HZ4ZM3FL.cjs} +31 -12
  23. package/dist/tsup/chunk-HZ4ZM3FL.cjs.map +1 -0
  24. package/dist/tsup/{chunk-7FEMVD3D.cjs → chunk-LMZSOCYD.cjs} +12 -12
  25. package/dist/tsup/{chunk-7FEMVD3D.cjs.map → chunk-LMZSOCYD.cjs.map} +1 -1
  26. package/dist/tsup/{chunk-ZVEDMBFT.js → chunk-PBFLG45S.js} +3 -3
  27. package/dist/tsup/{chunk-GJPOIJHZ.js → chunk-ST6FGRCH.js} +26 -7
  28. package/dist/tsup/chunk-ST6FGRCH.js.map +1 -0
  29. package/dist/tsup/{chunk-BIOPK7IB.cjs → chunk-TI72NLP3.cjs} +71 -67
  30. package/dist/tsup/chunk-TI72NLP3.cjs.map +1 -0
  31. package/dist/tsup/{chunk-RPI45FGS.js → chunk-TQ4OAC2G.js} +2 -2
  32. package/dist/tsup/{chunk-4B25D5OW.js → chunk-UB4OHFDW.js} +385 -104
  33. package/dist/tsup/chunk-UB4OHFDW.js.map +1 -0
  34. package/dist/tsup/{chunk-6Z3YA6QR.cjs → chunk-V6C34TVH.cjs} +35 -15
  35. package/dist/tsup/chunk-V6C34TVH.cjs.map +1 -0
  36. package/dist/tsup/{chunk-OAB7ECAB.cjs → chunk-WVUAO2F7.cjs} +558 -277
  37. package/dist/tsup/chunk-WVUAO2F7.cjs.map +1 -0
  38. package/dist/tsup/{chunk-JKNDUKFI.js → chunk-WWAZJHTS.js} +36 -16
  39. package/dist/tsup/chunk-WWAZJHTS.js.map +1 -0
  40. package/dist/tsup/client/mod.cjs +9 -9
  41. package/dist/tsup/client/mod.d.cts +2 -2
  42. package/dist/tsup/client/mod.d.ts +2 -2
  43. package/dist/tsup/client/mod.js +8 -8
  44. package/dist/tsup/common/log.cjs +3 -3
  45. package/dist/tsup/common/log.js +2 -2
  46. package/dist/tsup/common/websocket.cjs +4 -4
  47. package/dist/tsup/common/websocket.js +3 -3
  48. package/dist/tsup/{conn-Clu655RU.d.ts → conn-BYXlxnh0.d.ts} +111 -102
  49. package/dist/tsup/{conn-lUvFLo_q.d.cts → conn-BiazosE_.d.cts} +111 -102
  50. package/dist/tsup/driver-helpers/mod.cjs +5 -5
  51. package/dist/tsup/driver-helpers/mod.d.cts +1 -1
  52. package/dist/tsup/driver-helpers/mod.d.ts +1 -1
  53. package/dist/tsup/driver-helpers/mod.js +4 -4
  54. package/dist/tsup/driver-test-suite/mod.cjs +71 -71
  55. package/dist/tsup/driver-test-suite/mod.d.cts +1 -1
  56. package/dist/tsup/driver-test-suite/mod.d.ts +1 -1
  57. package/dist/tsup/driver-test-suite/mod.js +11 -11
  58. package/dist/tsup/inspector/mod.cjs +6 -6
  59. package/dist/tsup/inspector/mod.d.cts +2 -2
  60. package/dist/tsup/inspector/mod.d.ts +2 -2
  61. package/dist/tsup/inspector/mod.js +5 -5
  62. package/dist/tsup/mod.cjs +10 -10
  63. package/dist/tsup/mod.d.cts +3 -3
  64. package/dist/tsup/mod.d.ts +3 -3
  65. package/dist/tsup/mod.js +9 -9
  66. package/dist/tsup/test/mod.cjs +11 -11
  67. package/dist/tsup/test/mod.d.cts +1 -1
  68. package/dist/tsup/test/mod.d.ts +1 -1
  69. package/dist/tsup/test/mod.js +10 -10
  70. package/dist/tsup/utils.cjs +8 -2
  71. package/dist/tsup/utils.cjs.map +1 -1
  72. package/dist/tsup/utils.d.cts +8 -1
  73. package/dist/tsup/utils.d.ts +8 -1
  74. package/dist/tsup/utils.js +7 -1
  75. package/package.json +5 -4
  76. package/src/actor/config.ts +10 -0
  77. package/src/actor/conn-drivers.ts +43 -1
  78. package/src/actor/conn-socket.ts +1 -1
  79. package/src/actor/conn.ts +22 -2
  80. package/src/actor/context.ts +1 -1
  81. package/src/actor/driver.ts +13 -2
  82. package/src/actor/instance.ts +248 -57
  83. package/src/actor/persisted.ts +7 -0
  84. package/src/actor/router-endpoints.ts +67 -45
  85. package/src/actor/router.ts +25 -17
  86. package/src/client/actor-conn.ts +9 -5
  87. package/src/common/cors.ts +57 -0
  88. package/src/common/log.ts +26 -5
  89. package/src/common/utils.ts +5 -9
  90. package/src/common/websocket-interface.ts +10 -0
  91. package/src/driver-helpers/utils.ts +1 -0
  92. package/src/drivers/engine/actor-driver.ts +261 -14
  93. package/src/drivers/engine/config.ts +2 -4
  94. package/src/drivers/file-system/actor.ts +3 -2
  95. package/src/drivers/file-system/global-state.ts +1 -1
  96. package/src/drivers/file-system/manager.ts +3 -0
  97. package/src/engine-process/mod.ts +22 -4
  98. package/src/inspector/config.ts +0 -45
  99. package/src/manager/gateway.ts +45 -32
  100. package/src/manager/hono-websocket-adapter.ts +31 -3
  101. package/src/manager/router.ts +11 -17
  102. package/src/registry/run-config.ts +2 -8
  103. package/src/remote-manager-driver/actor-http-client.ts +5 -8
  104. package/src/remote-manager-driver/actor-websocket-client.ts +2 -14
  105. package/src/remote-manager-driver/mod.ts +0 -1
  106. package/src/schemas/actor-persist/mod.ts +1 -1
  107. package/src/schemas/actor-persist/versioned.ts +22 -10
  108. package/src/utils.ts +26 -0
  109. package/dist/tsup/chunk-4B25D5OW.js.map +0 -1
  110. package/dist/tsup/chunk-6Z3YA6QR.cjs.map +0 -1
  111. package/dist/tsup/chunk-BIOPK7IB.cjs.map +0 -1
  112. package/dist/tsup/chunk-FETQGZN4.js.map +0 -1
  113. package/dist/tsup/chunk-GJPOIJHZ.js.map +0 -1
  114. package/dist/tsup/chunk-I7EJWHYV.js.map +0 -1
  115. package/dist/tsup/chunk-JKNDUKFI.js.map +0 -1
  116. package/dist/tsup/chunk-OAB7ECAB.cjs.map +0 -1
  117. package/dist/tsup/chunk-R6XOZKMU.cjs.map +0 -1
  118. package/dist/tsup/chunk-VJLGVVGP.cjs.map +0 -1
  119. /package/dist/tsup/{chunk-JN6GPVFY.js.map → chunk-2K2LR56Q.js.map} +0 -0
  120. /package/dist/tsup/{chunk-EEXX243L.js.map → chunk-2WVCZCJL.js.map} +0 -0
  121. /package/dist/tsup/{chunk-NDLOG2JH.js.map → chunk-6YQKMAMV.js.map} +0 -0
  122. /package/dist/tsup/{chunk-UBCUW7HD.js.map → chunk-D7AA2DK5.js.map} +0 -0
  123. /package/dist/tsup/{chunk-ZVEDMBFT.js.map → chunk-PBFLG45S.js.map} +0 -0
  124. /package/dist/tsup/{chunk-RPI45FGS.js.map → chunk-TQ4OAC2G.js.map} +0 -0
@@ -7,12 +7,12 @@ import { ActionContext } from "@/actor/action";
7
7
  import type { AnyConn } from "@/actor/conn";
8
8
  import {
9
9
  generateConnId,
10
- generateConnSocketId,
10
+ generateConnRequestId,
11
11
  generateConnToken,
12
12
  } from "@/actor/conn";
13
13
  import { ConnDriverKind } from "@/actor/conn-drivers";
14
14
  import * as errors from "@/actor/errors";
15
- import type { AnyActorInstance } from "@/actor/instance";
15
+ import { type AnyActorInstance, PERSIST_SYMBOL } from "@/actor/instance";
16
16
  import type { InputData } from "@/actor/protocol/serde";
17
17
  import { type Encoding, EncodingSchema } from "@/actor/protocol/serde";
18
18
  import {
@@ -38,7 +38,11 @@ import {
38
38
  deserializeWithEncoding,
39
39
  serializeWithEncoding,
40
40
  } from "@/serde";
41
- import { bufferToArrayBuffer, promiseWithResolvers } from "@/utils";
41
+ import {
42
+ arrayBuffersEqual,
43
+ bufferToArrayBuffer,
44
+ promiseWithResolvers,
45
+ } from "@/utils";
42
46
  import type { ActorDriver } from "./driver";
43
47
  import { loggerWithoutContext } from "./log";
44
48
  import { parseMessage } from "./protocol/old";
@@ -111,8 +115,9 @@ export async function handleWebSocketConnect(
111
115
  actorId: string,
112
116
  encoding: Encoding,
113
117
  parameters: unknown,
114
- connId?: string,
115
- connToken?: string,
118
+ requestId: string,
119
+ connId: string | undefined,
120
+ connToken: string | undefined,
116
121
  ): Promise<UpgradeWebSocketArgs> {
117
122
  const exposeInternalError = req
118
123
  ? getRequestExposeInternalError(req)
@@ -157,7 +162,9 @@ export async function handleWebSocketConnect(
157
162
 
158
163
  // Promise used to wait for the websocket close in `disconnect`
159
164
  const closePromise = promiseWithResolvers<void>();
160
- const socketId = generateConnSocketId();
165
+
166
+ // Track connection outside of scope for cleanup
167
+ let createdConn: AnyConn | undefined;
161
168
 
162
169
  return {
163
170
  onOpen: (_evt: any, ws: WSContext) => {
@@ -179,7 +186,7 @@ export async function handleWebSocketConnect(
179
186
 
180
187
  conn = await actor.createConn(
181
188
  {
182
- socketId,
189
+ requestId: requestId,
183
190
  driverState: {
184
191
  [ConnDriverKind.WEBSOCKET]: {
185
192
  encoding,
@@ -194,6 +201,9 @@ export async function handleWebSocketConnect(
194
201
  connToken,
195
202
  );
196
203
 
204
+ // Store connection so we can clean on close
205
+ createdConn = conn;
206
+
197
207
  // Unblock other handlers
198
208
  handlersResolve({ conn, actor, connId: conn.id });
199
209
  } catch (error) {
@@ -294,20 +304,13 @@ export async function handleWebSocketConnect(
294
304
  // https://github.com/cloudflare/workerd/issues/2569
295
305
  ws.close(1000, "hack_force_close");
296
306
 
297
- // Handle cleanup asynchronously
298
- handlersPromise
299
- .then(({ conn, actor }) => {
307
+ // Wait for actor.createConn to finish before removing the connection
308
+ handlersPromise.finally(() => {
309
+ if (createdConn) {
300
310
  const wasClean = event.wasClean || event.code === 1000;
301
- actor.__connDisconnected(conn, wasClean, socketId);
302
- })
303
- .catch((error) => {
304
- deconstructError(
305
- error,
306
- actor.rLog,
307
- { wsEvent: "close" },
308
- exposeInternalError,
309
- );
310
- });
311
+ actor.__connDisconnected(createdConn, wasClean, requestId);
312
+ }
313
+ });
311
314
  },
312
315
  onError: (_error: unknown) => {
313
316
  try {
@@ -338,7 +341,7 @@ export async function handleSseConnect(
338
341
 
339
342
  const encoding = getRequestEncoding(c.req);
340
343
  const parameters = getRequestConnParams(c.req);
341
- const socketId = generateConnSocketId();
344
+ const requestId = generateConnRequestId();
342
345
 
343
346
  // Check for reconnection parameters
344
347
  const connId = c.req.header(HEADER_CONN_ID);
@@ -361,7 +364,7 @@ export async function handleSseConnect(
361
364
 
362
365
  conn = await actor.createConn(
363
366
  {
364
- socketId,
367
+ requestId: requestId,
365
368
  driverState: {
366
369
  [ConnDriverKind.SSE]: {
367
370
  encoding,
@@ -392,7 +395,7 @@ export async function handleSseConnect(
392
395
 
393
396
  // Cleanup
394
397
  if (conn) {
395
- actor.__connDisconnected(conn, false, socketId);
398
+ actor.__connDisconnected(conn, false, requestId);
396
399
  }
397
400
 
398
401
  abortResolver.resolve(undefined);
@@ -431,7 +434,7 @@ export async function handleSseConnect(
431
434
 
432
435
  // Cleanup on error
433
436
  if (conn && actor !== undefined) {
434
- actor.__connDisconnected(conn, false, socketId);
437
+ actor.__connDisconnected(conn, false, requestId);
435
438
  }
436
439
 
437
440
  // Close the stream on error
@@ -461,7 +464,7 @@ export async function handleAction(
461
464
  HTTP_ACTION_REQUEST_VERSIONED,
462
465
  );
463
466
  const actionArgs = cbor.decode(new Uint8Array(request.args));
464
- const socketId = generateConnSocketId();
467
+ const requestId = generateConnRequestId();
465
468
 
466
469
  // Invoke the action
467
470
  let actor: AnyActorInstance | undefined;
@@ -475,7 +478,7 @@ export async function handleAction(
475
478
  // Create conn
476
479
  conn = await actor.createConn(
477
480
  {
478
- socketId,
481
+ requestId: requestId,
479
482
  driverState: { [ConnDriverKind.HTTP]: {} },
480
483
  },
481
484
  parameters,
@@ -488,7 +491,7 @@ export async function handleAction(
488
491
  } finally {
489
492
  if (conn) {
490
493
  // HTTP connections don't have persistent sockets, so no socket ID needed
491
- actor?.__connDisconnected(conn, true, socketId);
494
+ actor?.__connDisconnected(conn, true, requestId);
492
495
  }
493
496
  }
494
497
 
@@ -595,38 +598,38 @@ export async function handleRawWebSocketHandler(
595
598
 
596
599
  // Return WebSocket event handlers
597
600
  return {
598
- onOpen: (_evt: any, ws: any) => {
601
+ onOpen: (evt: any, ws: any) => {
602
+ // Extract rivetRequestId provided by engine runner
603
+ const rivetRequestId = evt?.rivetRequestId;
604
+ const isHibernatable =
605
+ actor[PERSIST_SYMBOL].hibernatableWebSocket.findIndex((ws) =>
606
+ arrayBuffersEqual(ws.requestId, rivetRequestId),
607
+ ) !== -1;
608
+
599
609
  // Wrap the Hono WebSocket in our adapter
600
- const adapter = new HonoWebSocketAdapter(ws);
610
+ const adapter = new HonoWebSocketAdapter(
611
+ ws,
612
+ rivetRequestId,
613
+ isHibernatable,
614
+ );
601
615
 
602
616
  // Store adapter reference on the WebSocket for event handlers
603
617
  (ws as any).__adapter = adapter;
604
618
 
605
- // Extract the path after prefix and preserve query parameters
606
- // Use URL API for cleaner parsing
607
- const url = new URL(path, "http://actor");
608
- const pathname =
609
- url.pathname.replace(/^\/raw\/websocket\/?/, "") || "/";
610
- const normalizedPath =
611
- (pathname.startsWith("/") ? pathname : "/" + pathname) +
612
- url.search;
613
-
619
+ const newPath = truncateRawWebSocketPathPrefix(path);
614
620
  let newRequest: Request;
615
621
  if (req) {
616
- newRequest = new Request(`http://actor${normalizedPath}`, req);
622
+ newRequest = new Request(`http://actor${newPath}`, req);
617
623
  } else {
618
- newRequest = new Request(`http://actor${normalizedPath}`, {
624
+ newRequest = new Request(`http://actor${newPath}`, {
619
625
  method: "GET",
620
626
  });
621
627
  }
622
628
 
623
629
  actor.rLog.debug({
624
630
  msg: "rewriting websocket url",
625
- from: path,
626
- to: newRequest.url,
627
- pathname: url.pathname,
628
- search: url.search,
629
- normalizedPath,
631
+ fromPath: path,
632
+ toUrl: newRequest.url,
630
633
  });
631
634
 
632
635
  // Call the actor's onWebSocket handler with the adapted WebSocket
@@ -711,3 +714,22 @@ export function getRequestConnParams(req: HonoRequest): unknown {
711
714
  );
712
715
  }
713
716
  }
717
+
718
+ /**
719
+ * Truncase the PATH_RAW_WEBSOCKET_PREFIX path prefix in order to pass a clean
720
+ * path to the onWebSocket handler.
721
+ *
722
+ * Example:
723
+ * - `/raw/websocket/foo` -> `/foo`
724
+ * - `/raw/websocket` -> `/`
725
+ */
726
+ export function truncateRawWebSocketPathPrefix(path: string): string {
727
+ // Extract the path after prefix and preserve query parameters
728
+ // Use URL API for cleaner parsing
729
+ const url = new URL(path, "http://actor");
730
+ const pathname = url.pathname.replace(/^\/raw\/websocket\/?/, "") || "/";
731
+ const normalizedPath =
732
+ (pathname.startsWith("/") ? pathname : "/" + pathname) + url.search;
733
+
734
+ return normalizedPath;
735
+ }
@@ -1,5 +1,4 @@
1
1
  import { Hono, type Context as HonoContext } from "hono";
2
- import { cors } from "hono/cors";
3
2
  import invariant from "invariant";
4
3
  import { EncodingSchema } from "@/actor/protocol/serde";
5
4
  import {
@@ -42,6 +41,7 @@ import {
42
41
  } from "@/inspector/actor";
43
42
  import { isInspectorEnabled, secureInspector } from "@/inspector/utils";
44
43
  import type { RunnerConfig } from "@/registry/run-config";
44
+ import { generateConnRequestId } from "./conn";
45
45
  import { ConnDriverKind } from "./conn-drivers";
46
46
  import type { ActorDriver } from "./driver";
47
47
  import { InternalError } from "./errors";
@@ -77,6 +77,17 @@ export function createActorRouter(
77
77
 
78
78
  router.use("*", loggerMiddleware(loggerWithoutContext()));
79
79
 
80
+ // Track all HTTP requests to prevent actor from sleeping during active requests
81
+ router.use("*", async (c, next) => {
82
+ const actor = await actorDriver.loadActor(c.env.actorId);
83
+ actor.__beginHonoHttpRequest();
84
+ try {
85
+ await next();
86
+ } finally {
87
+ actor.__endHonoHttpRequest();
88
+ }
89
+ });
90
+
80
91
  router.get("/", (c) => {
81
92
  return c.text(
82
93
  "This is an RivetKit actor.\n\nLearn more at https://rivetkit.org",
@@ -175,6 +186,7 @@ export function createActorRouter(
175
186
  c.env.actorId,
176
187
  encoding,
177
188
  connParams,
189
+ generateConnRequestId(),
178
190
  connIdRaw,
179
191
  connTokenRaw,
180
192
  );
@@ -307,22 +319,18 @@ export function createActorRouter(
307
319
  new Hono<
308
320
  ActorInspectorRouterEnv & { Bindings: ActorRouterBindings }
309
321
  >()
310
- .use(
311
- cors(runConfig.inspector.cors),
312
- secureInspector(runConfig),
313
- async (c, next) => {
314
- const inspector = (
315
- await actorDriver.loadActor(c.env.actorId)
316
- ).inspector;
317
- invariant(
318
- inspector,
319
- "inspector not supported on this platform",
320
- );
321
-
322
- c.set("inspector", inspector);
323
- return next();
324
- },
325
- )
322
+ .use(secureInspector(runConfig), async (c, next) => {
323
+ const inspector = (
324
+ await actorDriver.loadActor(c.env.actorId)
325
+ ).inspector;
326
+ invariant(
327
+ inspector,
328
+ "inspector not supported on this platform",
329
+ );
330
+
331
+ c.set("inspector", inspector);
332
+ return next();
333
+ })
326
334
  .route("/", createActorInspectorRouter()),
327
335
  );
328
336
  }
@@ -563,17 +563,21 @@ enc
563
563
  // TODO: Handle queue
564
564
  // TODO: Reconnect with backoff
565
565
 
566
- // Reject open promise
567
- if (this.#onOpenPromise) {
568
- this.#onOpenPromise.reject(new Error("Closed"));
569
- }
570
-
571
566
  // We can't use `event instanceof CloseEvent` because it's not defined in NodeJS
572
567
  //
573
568
  // These properties will be undefined
574
569
  const closeEvent = event as CloseEvent;
575
570
  const wasClean = closeEvent.wasClean;
576
571
 
572
+ // Reject open promise
573
+ if (this.#onOpenPromise) {
574
+ this.#onOpenPromise.reject(
575
+ new Error(
576
+ `websocket closed with code ${closeEvent.code}: ${closeEvent.reason}`,
577
+ ),
578
+ );
579
+ }
580
+
577
581
  logger().info({
578
582
  msg: "socket closed",
579
583
  code: closeEvent.code,
@@ -0,0 +1,57 @@
1
+ import type { MiddlewareHandler } from "hono";
2
+
3
+ /**
4
+ * Simple CORS middleware that matches the gateway behavior.
5
+ *
6
+ * - Echoes back the Origin header from the request
7
+ * - Echoes back the Access-Control-Request-Headers from preflight
8
+ * - Supports credentials
9
+ * - Allows common HTTP methods
10
+ * - Caches preflight for 24 hours
11
+ * - Adds Vary header to prevent cache poisoning
12
+ */
13
+ export const cors = (): MiddlewareHandler => {
14
+ return async (c, next) => {
15
+ // Extract origin from request
16
+ const origin = c.req.header("origin") || "*";
17
+
18
+ // Handle preflight OPTIONS request
19
+ if (c.req.method === "OPTIONS") {
20
+ const requestHeaders =
21
+ c.req.header("access-control-request-headers") || "*";
22
+
23
+ c.header("access-control-allow-origin", origin);
24
+ c.header("access-control-allow-credentials", "true");
25
+ c.header(
26
+ "access-control-allow-methods",
27
+ "GET, POST, PUT, DELETE, OPTIONS, PATCH",
28
+ );
29
+ c.header("access-control-allow-headers", requestHeaders);
30
+ c.header("access-control-expose-headers", "*");
31
+ c.header("access-control-max-age", "86400");
32
+
33
+ // Add Vary header to prevent cache poisoning when echoing origin
34
+ if (origin !== "*") {
35
+ c.header("vary", "Origin");
36
+ }
37
+
38
+ // Remove content headers from preflight response
39
+ c.res.headers.delete("content-length");
40
+ c.res.headers.delete("content-type");
41
+
42
+ return c.body(null, 204);
43
+ }
44
+
45
+ await next();
46
+
47
+ // Add CORS headers to actual request
48
+ c.header("access-control-allow-origin", origin);
49
+ c.header("access-control-allow-credentials", "true");
50
+ c.header("access-control-expose-headers", "*");
51
+
52
+ // Add Vary header to prevent cache poisoning when echoing origin
53
+ if (origin !== "*") {
54
+ c.header("vary", "Origin");
55
+ }
56
+ };
57
+ };
package/src/common/log.ts CHANGED
@@ -146,7 +146,7 @@ export async function configureDefaultLogger(
146
146
  },
147
147
  },
148
148
  hooks: {
149
- logMethod(inputArgs, _method, level) {
149
+ logMethod(inputArgs, method, level) {
150
150
  // TODO: This is a hack to not implement our own transport target. We can get better perf if we have our own transport target.
151
151
 
152
152
  const levelMap: Record<number, string> = {
@@ -162,20 +162,41 @@ export async function configureDefaultLogger(
162
162
  getEnvUniversal("LOG_TIMESTAMP") === "1"
163
163
  ? Date.now()
164
164
  : undefined;
165
+
166
+ // Get bindings from the logger instance (child logger fields)
167
+ const bindings = (this as any).bindings?.() || {};
168
+
165
169
  // TODO: This can be simplified in logfmt.ts
166
170
  if (inputArgs.length >= 2) {
167
171
  const [objOrMsg, msg] = inputArgs;
168
172
  if (typeof objOrMsg === "object" && objOrMsg !== null) {
169
- customWrite(levelName, { ...objOrMsg, msg, time });
173
+ customWrite(levelName, {
174
+ ...bindings,
175
+ ...objOrMsg,
176
+ msg,
177
+ time,
178
+ });
170
179
  } else {
171
- customWrite(levelName, { msg: String(objOrMsg), time });
180
+ customWrite(levelName, {
181
+ ...bindings,
182
+ msg: String(objOrMsg),
183
+ time,
184
+ });
172
185
  }
173
186
  } else if (inputArgs.length === 1) {
174
187
  const [objOrMsg] = inputArgs;
175
188
  if (typeof objOrMsg === "object" && objOrMsg !== null) {
176
- customWrite(levelName, { ...objOrMsg, time });
189
+ customWrite(levelName, {
190
+ ...bindings,
191
+ ...objOrMsg,
192
+ time,
193
+ });
177
194
  } else {
178
- customWrite(levelName, { msg: String(objOrMsg), time });
195
+ customWrite(levelName, {
196
+ ...bindings,
197
+ msg: String(objOrMsg),
198
+ time,
199
+ });
179
200
  }
180
201
  }
181
202
  },
@@ -1,7 +1,7 @@
1
1
  import type { Next } from "hono";
2
2
  import type { ContentfulStatusCode } from "hono/utils/http-status";
3
3
  import * as errors from "@/actor/errors";
4
- import { getEnvUniversal } from "@/utils";
4
+ import { EXTRA_ERROR_LOG, getEnvUniversal, VERSION } from "@/utils";
5
5
  import type { Logger } from "./log";
6
6
 
7
7
  export function assertUnreachable(x: never): never {
@@ -228,8 +228,7 @@ export function deconstructError(
228
228
  group,
229
229
  code,
230
230
  message,
231
- issues: "https://github.com/rivet-dev/rivetkit/issues",
232
- support: "https://rivet.dev/discord",
231
+ ...EXTRA_ERROR_LOG,
233
232
  ...extraLog,
234
233
  });
235
234
  } else if (exposeInternalError) {
@@ -246,8 +245,7 @@ export function deconstructError(
246
245
  group,
247
246
  code,
248
247
  message,
249
- issues: "https://github.com/rivet-dev/rivetkit/issues",
250
- support: "https://rivet.dev/discord",
248
+ ...EXTRA_ERROR_LOG,
251
249
  ...extraLog,
252
250
  });
253
251
  } else {
@@ -262,8 +260,7 @@ export function deconstructError(
262
260
  group,
263
261
  code,
264
262
  message,
265
- issues: "https://github.com/rivet-dev/rivetkit/issues",
266
- support: "https://rivet.dev/discord",
263
+ ...EXTRA_ERROR_LOG,
267
264
  ...extraLog,
268
265
  });
269
266
  }
@@ -281,8 +278,7 @@ export function deconstructError(
281
278
  msg: "internal error",
282
279
  error: getErrorMessage(error),
283
280
  stack: (error as Error)?.stack,
284
- issues: "https://github.com/rivet-dev/rivetkit/issues",
285
- support: "https://rivet.dev/discord",
281
+ ...EXTRA_ERROR_LOG,
286
282
  ...extraLog,
287
283
  });
288
284
  }
@@ -3,10 +3,20 @@ export interface RivetEvent {
3
3
  type: string;
4
4
  target?: any;
5
5
  currentTarget?: any;
6
+ /**
7
+ * @experimental
8
+ * Request ID for hibernatable websockets (provided by engine runner)
9
+ **/
10
+ rivetRequestId?: ArrayBuffer;
6
11
  }
7
12
 
8
13
  export interface RivetMessageEvent extends RivetEvent {
9
14
  data: any;
15
+ /**
16
+ * @experimental
17
+ * Message index for hibernatable websockets (provided by engine runner)
18
+ **/
19
+ rivetMessageIndex?: number;
10
20
  }
11
21
 
12
22
  export interface RivetCloseEvent extends RivetEvent {
@@ -15,6 +15,7 @@ export function serializeEmptyPersistData(
15
15
  state: bufferToArrayBuffer(cbor.encode(undefined)),
16
16
  connections: [],
17
17
  scheduledEvents: [],
18
+ hibernatableWebSocket: [],
18
19
  };
19
20
  return PERSISTED_ACTOR_VERSIONED.serializeWithEmbeddedVersion(persistData);
20
21
  }