rivetkit 2.3.0-rc.7 → 2.3.0-rc.9

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 (122) hide show
  1. package/dist/browser/client.d.ts +8 -37
  2. package/dist/browser/client.js +34 -64
  3. package/dist/browser/client.js.map +1 -1
  4. package/dist/browser/inspector/client.js +3 -4
  5. package/dist/browser/inspector/client.js.map +1 -1
  6. package/dist/tsup/actor/errors.cjs +2 -2
  7. package/dist/tsup/actor/errors.js +1 -1
  8. package/dist/tsup/agent-os/index.cjs +5 -7
  9. package/dist/tsup/agent-os/index.cjs.map +1 -1
  10. package/dist/tsup/agent-os/index.d.cts +5 -26
  11. package/dist/tsup/agent-os/index.d.ts +5 -26
  12. package/dist/tsup/agent-os/index.js +5 -7
  13. package/dist/tsup/agent-os/index.js.map +1 -1
  14. package/dist/tsup/{chunk-55E7IR6D.cjs → chunk-4CGA6QJO.cjs} +4 -4
  15. package/dist/tsup/{chunk-55E7IR6D.cjs.map → chunk-4CGA6QJO.cjs.map} +1 -1
  16. package/dist/tsup/{chunk-G5HUSWP4.cjs → chunk-4WPEZBK4.cjs} +8 -8
  17. package/dist/tsup/{chunk-G5HUSWP4.cjs.map → chunk-4WPEZBK4.cjs.map} +1 -1
  18. package/dist/tsup/{chunk-2H4ISA4Y.cjs → chunk-CPA4Y3RG.cjs} +10 -10
  19. package/dist/tsup/chunk-CPA4Y3RG.cjs.map +1 -0
  20. package/dist/tsup/{chunk-VJ4Y4WBT.js → chunk-F3Q5BFQ6.js} +34 -10
  21. package/dist/tsup/chunk-F3Q5BFQ6.js.map +1 -0
  22. package/dist/tsup/{chunk-ZGPX6KAH.cjs → chunk-GVTOE34S.cjs} +193 -169
  23. package/dist/tsup/chunk-GVTOE34S.cjs.map +1 -0
  24. package/dist/tsup/{chunk-4DJMFOSU.js → chunk-H37XQU3I.js} +2 -2
  25. package/dist/tsup/{chunk-CMV6N5OX.js → chunk-H7P7WR2Y.js} +3 -3
  26. package/dist/tsup/{chunk-TMLOKTRB.js → chunk-KIWH5H3K.js} +3 -3
  27. package/dist/tsup/chunk-KIWH5H3K.js.map +1 -0
  28. package/dist/tsup/{chunk-52TPEKEC.js → chunk-KJTA3ATT.js} +2 -2
  29. package/dist/tsup/{chunk-SJLPZEA3.cjs → chunk-MALSPBAF.cjs} +3 -3
  30. package/dist/tsup/{chunk-SJLPZEA3.cjs.map → chunk-MALSPBAF.cjs.map} +1 -1
  31. package/dist/tsup/{chunk-VFIY6GWO.js → chunk-MMMEZM5J.js} +4 -4
  32. package/dist/tsup/chunk-MMMEZM5J.js.map +1 -0
  33. package/dist/tsup/{chunk-63WNTDRC.cjs → chunk-QAZLM4WT.cjs} +3 -3
  34. package/dist/tsup/{chunk-63WNTDRC.cjs.map → chunk-QAZLM4WT.cjs.map} +1 -1
  35. package/dist/tsup/{chunk-D5G75T7J.js → chunk-T6YVRM4K.js} +1 -3
  36. package/dist/tsup/chunk-T6YVRM4K.js.map +1 -0
  37. package/dist/tsup/{chunk-FEOG44WH.cjs → chunk-VJFRBJVQ.cjs} +9 -137
  38. package/dist/tsup/chunk-VJFRBJVQ.cjs.map +1 -0
  39. package/dist/tsup/{chunk-HERL2VQ2.js → chunk-VRCIXJRN.js} +5 -7
  40. package/dist/tsup/chunk-VRCIXJRN.js.map +1 -0
  41. package/dist/tsup/{chunk-4LTY5TOO.js → chunk-W7EYSYVI.js} +4 -132
  42. package/dist/tsup/chunk-W7EYSYVI.js.map +1 -0
  43. package/dist/tsup/{chunk-SRNOPUC6.cjs → chunk-WQ4HNA4W.cjs} +2 -4
  44. package/dist/tsup/chunk-WQ4HNA4W.cjs.map +1 -0
  45. package/dist/tsup/{chunk-X6HIFXNK.cjs → chunk-Y5NSCZA2.cjs} +12 -14
  46. package/dist/tsup/chunk-Y5NSCZA2.cjs.map +1 -0
  47. package/dist/tsup/client/mod.cjs +7 -7
  48. package/dist/tsup/client/mod.d.cts +2 -2
  49. package/dist/tsup/client/mod.d.ts +2 -2
  50. package/dist/tsup/client/mod.js +6 -6
  51. package/dist/tsup/common/log.cjs +3 -3
  52. package/dist/tsup/common/log.js +2 -2
  53. package/dist/tsup/common/websocket.cjs +4 -4
  54. package/dist/tsup/common/websocket.js +3 -3
  55. package/dist/tsup/{config-Ak1lv4gF.d.ts → config-0Ta55UV0.d.ts} +6 -27
  56. package/dist/tsup/{config-DU_xj4qZ.d.cts → config-Ca8dN4cS.d.cts} +6 -27
  57. package/dist/tsup/{context-DAAp4Lpg.d.ts → context-B_IWbWne.d.ts} +1 -1
  58. package/dist/tsup/{context-Dt_L55q8.d.cts → context-CUrQ9MHc.d.cts} +1 -1
  59. package/dist/tsup/inspector/mod.cjs +6 -6
  60. package/dist/tsup/inspector/mod.js +5 -5
  61. package/dist/tsup/mod.cjs +355 -482
  62. package/dist/tsup/mod.cjs.map +1 -1
  63. package/dist/tsup/mod.d.cts +3 -3
  64. package/dist/tsup/mod.d.ts +3 -3
  65. package/dist/tsup/mod.js +276 -403
  66. package/dist/tsup/mod.js.map +1 -1
  67. package/dist/tsup/test/mod.cjs +10 -10
  68. package/dist/tsup/test/mod.d.cts +1 -1
  69. package/dist/tsup/test/mod.d.ts +1 -1
  70. package/dist/tsup/test/mod.js +6 -6
  71. package/dist/tsup/utils.cjs +3 -3
  72. package/dist/tsup/utils.js +2 -2
  73. package/dist/tsup/workflow/mod.cjs +16 -41
  74. package/dist/tsup/workflow/mod.cjs.map +1 -1
  75. package/dist/tsup/workflow/mod.d.cts +3 -3
  76. package/dist/tsup/workflow/mod.d.ts +3 -3
  77. package/dist/tsup/workflow/mod.js +10 -35
  78. package/dist/tsup/workflow/mod.js.map +1 -1
  79. package/package.json +10 -11
  80. package/src/actor/config.ts +0 -3
  81. package/src/actor/errors.ts +2 -2
  82. package/src/agent-os/actor/session.ts +2 -2
  83. package/src/client/actor-conn.ts +34 -6
  84. package/src/client/actor-handle.ts +1 -2
  85. package/src/client/queue.ts +1 -2
  86. package/src/client/utils.ts +1 -0
  87. package/src/common/encoding.ts +5 -243
  88. package/src/common/inline-websocket-adapter.ts +12 -12
  89. package/src/common/log.ts +0 -1
  90. package/src/common/router.ts +2 -2
  91. package/src/common/utils.ts +148 -0
  92. package/src/drivers/engine/actor-driver.ts +11 -11
  93. package/src/engine-client/actor-websocket-client.ts +1 -2
  94. package/src/engine-client/mod.ts +2 -3
  95. package/src/registry/index.ts +109 -46
  96. package/src/registry/napi-runtime.ts +34 -11
  97. package/src/registry/native.ts +162 -205
  98. package/src/registry/runtime.ts +12 -5
  99. package/src/registry/wasm-runtime.ts +13 -2
  100. package/src/serde.ts +2 -2
  101. package/src/workflow/context.ts +5 -32
  102. package/src/workflow/inspector.ts +1 -2
  103. package/dist/tsup/chunk-2H4ISA4Y.cjs.map +0 -1
  104. package/dist/tsup/chunk-4LTY5TOO.js.map +0 -1
  105. package/dist/tsup/chunk-D5G75T7J.js.map +0 -1
  106. package/dist/tsup/chunk-FEOG44WH.cjs.map +0 -1
  107. package/dist/tsup/chunk-HERL2VQ2.js.map +0 -1
  108. package/dist/tsup/chunk-SRNOPUC6.cjs.map +0 -1
  109. package/dist/tsup/chunk-TMLOKTRB.js.map +0 -1
  110. package/dist/tsup/chunk-VFIY6GWO.js.map +0 -1
  111. package/dist/tsup/chunk-VJ4Y4WBT.js.map +0 -1
  112. package/dist/tsup/chunk-X6HIFXNK.cjs.map +0 -1
  113. package/dist/tsup/chunk-ZGPX6KAH.cjs.map +0 -1
  114. package/dist/tsup/process-metrics-NW754INA.js +0 -118
  115. package/dist/tsup/process-metrics-NW754INA.js.map +0 -1
  116. package/dist/tsup/process-metrics-TYAGKCEJ.cjs +0 -118
  117. package/dist/tsup/process-metrics-TYAGKCEJ.cjs.map +0 -1
  118. package/src/registry/process-metrics.ts +0 -183
  119. package/src/registry/write-through-proxy.ts +0 -40
  120. /package/dist/tsup/{chunk-4DJMFOSU.js.map → chunk-H37XQU3I.js.map} +0 -0
  121. /package/dist/tsup/{chunk-CMV6N5OX.js.map → chunk-H7P7WR2Y.js.map} +0 -0
  122. /package/dist/tsup/{chunk-52TPEKEC.js.map → chunk-KJTA3ATT.js.map} +0 -0
package/dist/tsup/mod.js CHANGED
@@ -2,14 +2,13 @@ import {
2
2
  ACTOR_CONTEXT_INTERNAL_SYMBOL,
3
3
  ActorConfigSchema,
4
4
  CONN_STATE_MANAGER_SYMBOL,
5
- RAW_STATE_SYMBOL,
6
5
  getRunFunction,
7
6
  getRunInspectorConfig,
8
7
  getRunMetadata
9
- } from "./chunk-D5G75T7J.js";
8
+ } from "./chunk-T6YVRM4K.js";
10
9
  import {
11
10
  decodeWorkflowHistoryTransport
12
- } from "./chunk-52TPEKEC.js";
11
+ } from "./chunk-KJTA3ATT.js";
13
12
  import {
14
13
  ALLOWED_PUBLIC_HEADERS,
15
14
  HEADER_CONN_PARAMS,
@@ -19,7 +18,7 @@ import {
19
18
  getDatacenters,
20
19
  tryParseEndpoint,
21
20
  updateRunnerConfig
22
- } from "./chunk-VJ4Y4WBT.js";
21
+ } from "./chunk-F3Q5BFQ6.js";
23
22
  import {
24
23
  KEYS,
25
24
  makePrefixedKey,
@@ -29,18 +28,16 @@ import {
29
28
  workflowStoragePrefix
30
29
  } from "./chunk-3YY5S6TV.js";
31
30
  import {
32
- assertJsonCompatValue,
33
31
  decodeCborCompat,
34
32
  decodeCborJsonCompat,
35
33
  encodeCborCompat
36
- } from "./chunk-4LTY5TOO.js";
34
+ } from "./chunk-W7EYSYVI.js";
37
35
  import "./chunk-PCBNKI2J.js";
38
- import "./chunk-4DJMFOSU.js";
36
+ import "./chunk-H37XQU3I.js";
39
37
  import {
40
38
  LogLevelSchema,
41
39
  VERSION,
42
40
  deconstructError,
43
- detectRuntime,
44
41
  getEnvUniversal,
45
42
  getLogger,
46
43
  getNodeEnv,
@@ -60,7 +57,7 @@ import {
60
57
  noopNext,
61
58
  stringifyError,
62
59
  toUint8Array
63
- } from "./chunk-HERL2VQ2.js";
60
+ } from "./chunk-VRCIXJRN.js";
64
61
  import {
65
62
  INTERNAL_ERROR_CODE,
66
63
  RivetError,
@@ -71,7 +68,7 @@ import {
71
68
  isRivetErrorLike,
72
69
  toRivetError,
73
70
  unsupportedFeature
74
- } from "./chunk-TMLOKTRB.js";
71
+ } from "./chunk-KIWH5H3K.js";
75
72
 
76
73
  // src/actor/log.ts
77
74
  function loggerWithoutContext() {
@@ -317,24 +314,24 @@ var InlineWebSocketAdapter = class {
317
314
  this.#close(1011, "Internal error during initialization");
318
315
  }
319
316
  }
320
- #handleError(error) {
321
- console.error("INLINE_WEBSOCKET_ADAPTER_ERROR", error);
317
+ #handleError(err) {
318
+ console.error("INLINE_WEBSOCKET_ADAPTER_ERROR", err);
322
319
  logger().error({
323
320
  msg: "error in websocket",
324
- error,
325
- errorMessage: error instanceof Error ? error.message : String(error),
326
- stack: error instanceof Error ? error.stack : void 0
321
+ error: err,
322
+ errorMessage: err instanceof Error ? err.message : String(err),
323
+ stack: err instanceof Error ? err.stack : void 0
327
324
  });
328
325
  try {
329
- this.#handler.onError(error, this.#wsContext);
330
- } catch (error2) {
326
+ this.#handler.onError(err, this.#wsContext);
327
+ } catch (handlerErr) {
331
328
  logger().error({
332
329
  msg: "error in onError handler",
333
- error: error2
330
+ error: handlerErr
334
331
  });
335
332
  }
336
- this.#clientWs.triggerError(error);
337
- this.#actorWs.triggerError(error);
333
+ this.#clientWs.triggerError(err);
334
+ this.#actorWs.triggerError(err);
338
335
  }
339
336
  #close(code, reason) {
340
337
  if (this.#readyState === 3 || this.#readyState === 2) {
@@ -347,8 +344,8 @@ var InlineWebSocketAdapter = class {
347
344
  { code, reason, wasClean: true },
348
345
  this.#wsContext
349
346
  );
350
- } catch (error) {
351
- logger().error({ msg: "error closing websocket", error });
347
+ } catch (err) {
348
+ logger().error({ msg: "error closing websocket", error: err });
352
349
  } finally {
353
350
  this.#readyState = 3;
354
351
  this.#clientWs.triggerClose(code, reason);
@@ -357,9 +354,6 @@ var InlineWebSocketAdapter = class {
357
354
  }
358
355
  };
359
356
 
360
- // src/registry/index.ts
361
- import { Hono } from "hono";
362
-
363
357
  // src/common/engine.ts
364
358
  var ENGINE_PORT = 6420;
365
359
  var ENGINE_ENDPOINT = `http://127.0.0.1:${ENGINE_PORT}`;
@@ -456,145 +450,6 @@ async function configureServerlessPool(config) {
456
450
  throw lastError;
457
451
  }
458
452
 
459
- // src/utils/serve.ts
460
- import getPort from "get-port";
461
- var serveStaticLoaderPromises = {};
462
- async function crossPlatformServe(config, httpPort, app, runtime = detectRuntime()) {
463
- logger2().debug({ msg: "detected runtime for serve", runtime });
464
- switch (runtime) {
465
- case "deno":
466
- return serveDeno(config, httpPort, app);
467
- case "bun":
468
- return serveBun(config, httpPort, app);
469
- case "node":
470
- return serveNode(config, httpPort, app);
471
- default:
472
- return serveNode(config, httpPort, app);
473
- }
474
- }
475
- async function loadRuntimeServeStatic(runtime) {
476
- if (!serveStaticLoaderPromises[runtime]) {
477
- if (runtime === "node") {
478
- const nodeServeStaticModule = "@hono/node-server/serve-static";
479
- serveStaticLoaderPromises[runtime] = import(
480
- /* webpackIgnore: true */
481
- nodeServeStaticModule
482
- ).then((x) => x.serveStatic);
483
- } else if (runtime === "bun") {
484
- const bunModule = "hono/bun";
485
- serveStaticLoaderPromises[runtime] = import(
486
- /* webpackIgnore: true */
487
- bunModule
488
- ).then((x) => x.serveStatic);
489
- } else if (runtime === "deno") {
490
- const denoModule = "hono/deno";
491
- serveStaticLoaderPromises[runtime] = import(
492
- /* webpackIgnore: true */
493
- denoModule
494
- ).then((x) => x.serveStatic);
495
- } else {
496
- throw new Error(`unsupported runtime: ${runtime}`);
497
- }
498
- }
499
- return await serveStaticLoaderPromises[runtime];
500
- }
501
- async function serveNode(config, httpPort, app) {
502
- const nodeServerModule = "@hono/node-server";
503
- let serve;
504
- try {
505
- const dep = await import(
506
- /* webpackIgnore: true */
507
- nodeServerModule
508
- );
509
- serve = dep.serve;
510
- } catch (err) {
511
- logger2().error({
512
- msg: "failed to import @hono/node-server. please run 'npm install @hono/node-server @hono/node-ws'",
513
- error: stringifyError(err)
514
- });
515
- process.exit(1);
516
- }
517
- const nodeWsModule = "@hono/node-ws";
518
- let createNodeWebSocket;
519
- try {
520
- const dep = await import(
521
- /* webpackIgnore: true */
522
- nodeWsModule
523
- );
524
- createNodeWebSocket = dep.createNodeWebSocket;
525
- } catch (err) {
526
- logger2().error({
527
- msg: "failed to import @hono/node-ws. please run 'npm install @hono/node-server @hono/node-ws'",
528
- error: stringifyError(err)
529
- });
530
- process.exit(1);
531
- }
532
- const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({
533
- app
534
- });
535
- const port = httpPort;
536
- const hostname = config.httpHost;
537
- const server = serve(
538
- { fetch: app.fetch, port, hostname },
539
- () => logger2().info({ msg: "server listening", port, hostname })
540
- );
541
- injectWebSocket(server);
542
- const closeServer = () => {
543
- server.close();
544
- };
545
- return { upgradeWebSocket, closeServer };
546
- }
547
- async function serveDeno(config, httpPort, app) {
548
- const honoDenoModule = "hono/deno";
549
- let upgradeWebSocket;
550
- try {
551
- const dep = await import(
552
- /* webpackIgnore: true */
553
- honoDenoModule
554
- );
555
- upgradeWebSocket = dep.upgradeWebSocket;
556
- } catch (err) {
557
- logger2().error({
558
- msg: "failed to import hono/deno",
559
- error: stringifyError(err)
560
- });
561
- process.exit(1);
562
- }
563
- const port = httpPort;
564
- const hostname = config.httpHost;
565
- Deno.serve({ port, hostname }, app.fetch);
566
- logger2().info({ msg: "server listening", port, hostname });
567
- return { upgradeWebSocket };
568
- }
569
- async function serveBun(config, httpPort, app) {
570
- const honoBunModule = "hono/bun";
571
- let createBunWebSocket;
572
- try {
573
- const dep = await import(
574
- /* webpackIgnore: true */
575
- honoBunModule
576
- );
577
- createBunWebSocket = dep.createBunWebSocket;
578
- } catch (err) {
579
- logger2().error({
580
- msg: "failed to import hono/bun",
581
- error: stringifyError(err)
582
- });
583
- process.exit(1);
584
- }
585
- const { websocket, upgradeWebSocket } = createBunWebSocket();
586
- const port = httpPort;
587
- const hostname = config.httpHost;
588
- Bun.serve({
589
- fetch: app.fetch,
590
- port,
591
- hostname,
592
- websocket
593
- });
594
- logger2().info({ msg: "server listening", port, hostname });
595
- return { upgradeWebSocket };
596
- }
597
-
598
453
  // src/registry/config/index.ts
599
454
  import { z as z3 } from "zod";
600
455
 
@@ -1299,29 +1154,6 @@ function lastInsertRowIdColumnName(sql) {
1299
1154
  return alias;
1300
1155
  }
1301
1156
 
1302
- // src/registry/write-through-proxy.ts
1303
- import onChange from "@rivetkit/on-change";
1304
- function createWriteThroughProxy(value, commit, beforeChange) {
1305
- if (!value || typeof value !== "object") {
1306
- return value;
1307
- }
1308
- return onChange(
1309
- value,
1310
- () => {
1311
- commit(value);
1312
- },
1313
- {
1314
- // Rejection is throw-based: beforeChange throws to prevent the
1315
- // mutation. We always return true so on-change applies the change
1316
- // if beforeChange did not throw.
1317
- onValidate(_path, newValue) {
1318
- beforeChange == null ? void 0 : beforeChange(newValue);
1319
- return true;
1320
- }
1321
- }
1322
- );
1323
- }
1324
-
1325
1157
  // src/registry/runtime.ts
1326
1158
  function normalizeRuntimeSqlExecuteResult(result) {
1327
1159
  return result;
@@ -1442,15 +1274,32 @@ var NapiCoreRuntime = class {
1442
1274
  async shutdownRegistry(registry) {
1443
1275
  await asNativeRegistry(registry).shutdown();
1444
1276
  }
1445
- async registryDiagnostics(registry) {
1446
- const diagnostics = await asNativeRegistry(registry).diagnostics();
1277
+ async registryActorStopThresholdMs(registry) {
1278
+ return await asNativeRegistry(registry).actorStopThresholdMs() ?? void 0;
1279
+ }
1280
+ async registryHealth(registry) {
1281
+ const response = await asNativeRegistry(registry).health();
1447
1282
  return {
1448
- mode: diagnostics.mode,
1449
- envoyActiveActorCount: diagnostics.envoyActiveActorCount
1283
+ status: response.status,
1284
+ headers: response.headers,
1285
+ body: response.body
1450
1286
  };
1451
1287
  }
1452
- async registryActorStopThresholdMs(registry) {
1453
- return await asNativeRegistry(registry).actorStopThresholdMs() ?? void 0;
1288
+ async registryMetadata(registry) {
1289
+ const response = asNativeRegistry(registry).metadata();
1290
+ return {
1291
+ status: response.status,
1292
+ headers: response.headers,
1293
+ body: response.body
1294
+ };
1295
+ }
1296
+ async registryMetrics(registry) {
1297
+ const response = asNativeRegistry(registry).metrics();
1298
+ return {
1299
+ status: response.status,
1300
+ headers: response.headers,
1301
+ body: response.body
1302
+ };
1454
1303
  }
1455
1304
  async handleServerlessRequest(registry, req, onStreamEvent, cancelToken, config) {
1456
1305
  return await asNativeRegistry(registry).handleServerlessRequest(
@@ -1992,8 +1841,18 @@ var WasmCoreRuntime = class {
1992
1841
  async shutdownRegistry(registry) {
1993
1842
  await callWasm(() => asWasmRegistry(registry).shutdown());
1994
1843
  }
1995
- async registryDiagnostics() {
1996
- return { mode: "wasm", envoyActiveActorCount: null };
1844
+ async registryHealth() {
1845
+ return {
1846
+ status: 200,
1847
+ headers: { "content-type": "application/json" },
1848
+ body: new TextEncoder().encode(
1849
+ JSON.stringify({
1850
+ status: "ok",
1851
+ runtime: "rivetkit",
1852
+ version: "wasm"
1853
+ })
1854
+ )
1855
+ };
1997
1856
  }
1998
1857
  async handleServerlessRequest(registry, req, onStreamEvent, cancelToken, config) {
1999
1858
  return await callHandleAsync(
@@ -2542,14 +2401,6 @@ function databaseNotConfiguredError() {
2542
2401
  { public: true }
2543
2402
  );
2544
2403
  }
2545
- function databaseClientNotReadyError() {
2546
- return new RivetError(
2547
- "actor",
2548
- "database_client_not_ready",
2549
- "actor database client was not initialized before user code ran. this is an internal lifecycle error; the migration callback should have pre-warmed the client. file an issue if you can reproduce.",
2550
- { public: true }
2551
- );
2552
- }
2553
2404
  function stateNotEnabledError() {
2554
2405
  return new RivetError(
2555
2406
  "actor",
@@ -2602,20 +2453,7 @@ function clearNativeRuntimeState(runtime, ctx) {
2602
2453
  callNativeSync(() => runtime.actorClearRuntimeState(ctx));
2603
2454
  }
2604
2455
  async function cleanupNativeSleepRuntimeState(runtime, ctx) {
2605
- const waitStarted = Date.now();
2606
- const drained = await runtime.actorWaitForTrackedShutdownWork(ctx);
2607
- const waitMs = Date.now() - waitStarted;
2608
- if (drained) {
2609
- logger2().debug({
2610
- msg: "sleep cleanup: tracked shutdown work drained",
2611
- waitMs
2612
- });
2613
- } else {
2614
- logger2().warn({
2615
- msg: "sleep cleanup: shutdown deadline reached before tracked work drained; closing DB anyway",
2616
- waitMs
2617
- });
2618
- }
2456
+ await runtime.actorWaitForTrackedShutdownWork(ctx);
2619
2457
  await closeNativeDatabaseClient(runtime, ctx);
2620
2458
  await closeNativeSqlDatabase(runtime, ctx);
2621
2459
  clearNativeRuntimeState(runtime, ctx);
@@ -2995,6 +2833,44 @@ function decodeArgs(value) {
2995
2833
  const decoded = decodeValue(value);
2996
2834
  return Array.isArray(decoded) ? decoded : decoded === void 0 ? [] : [decoded];
2997
2835
  }
2836
+ function createWriteThroughProxy(value, commit, beforeChange) {
2837
+ if (!value || typeof value !== "object") {
2838
+ return value;
2839
+ }
2840
+ const proxies = /* @__PURE__ */ new WeakMap();
2841
+ const wrap = (target) => {
2842
+ const cached = proxies.get(target);
2843
+ if (cached) {
2844
+ return cached;
2845
+ }
2846
+ const proxy = new Proxy(target, {
2847
+ get(innerTarget, property, receiver) {
2848
+ const result = Reflect.get(innerTarget, property, receiver);
2849
+ return result && typeof result === "object" ? wrap(result) : result;
2850
+ },
2851
+ set(innerTarget, property, nextValue, receiver) {
2852
+ beforeChange == null ? void 0 : beforeChange();
2853
+ const updated = Reflect.set(
2854
+ innerTarget,
2855
+ property,
2856
+ nextValue,
2857
+ receiver
2858
+ );
2859
+ commit(value);
2860
+ return updated;
2861
+ },
2862
+ deleteProperty(innerTarget, property) {
2863
+ beforeChange == null ? void 0 : beforeChange();
2864
+ const updated = Reflect.deleteProperty(innerTarget, property);
2865
+ commit(value);
2866
+ return updated;
2867
+ }
2868
+ });
2869
+ proxies.set(target, proxy);
2870
+ return proxy;
2871
+ };
2872
+ return wrap(value);
2873
+ }
2998
2874
  function buildRequest(init) {
2999
2875
  const url = init.uri.startsWith("http") ? init.uri : new URL(init.uri, "http://127.0.0.1").toString();
3000
2876
  const body = init.body && init.body.length > 0 ? runtimeBytesToArrayBuffer(init.body) : void 0;
@@ -3047,19 +2923,13 @@ var NativeConnAdapter = class {
3047
2923
  decodeValue(this.#runtime.connParams(this.#conn))
3048
2924
  );
3049
2925
  }
3050
- [RAW_STATE_SYMBOL]() {
3051
- return this.#readState();
3052
- }
3053
2926
  get state() {
3054
2927
  const nextState = this.#readState();
3055
2928
  return createWriteThroughProxy(nextState, (nextValue) => {
3056
2929
  this.#writeState(nextValue, { writeNative: true });
3057
- }, (newValue) => {
3058
- assertJsonCompatValue(newValue);
3059
2930
  });
3060
2931
  }
3061
2932
  set state(value) {
3062
- assertJsonCompatValue(value);
3063
2933
  this.#writeState(value, { writeNative: true });
3064
2934
  }
3065
2935
  initializeState(value) {
@@ -3883,70 +3753,6 @@ var TrackedWebSocketHandleAdapter = class {
3883
3753
  return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
3884
3754
  }
3885
3755
  };
3886
- var NativeConnectionMap = class {
3887
- #runtime;
3888
- #ctx;
3889
- #schemas;
3890
- constructor(runtime, ctx, schemas) {
3891
- this.#runtime = runtime;
3892
- this.#ctx = ctx;
3893
- this.#schemas = schemas;
3894
- }
3895
- #connToAdapter(conn) {
3896
- return new NativeConnAdapter(
3897
- this.#runtime,
3898
- conn,
3899
- this.#schemas,
3900
- this.#ctx,
3901
- (connId) => callNativeSync(
3902
- () => this.#runtime.actorQueueHibernationRemoval(
3903
- this.#ctx,
3904
- connId
3905
- )
3906
- )
3907
- );
3908
- }
3909
- get size() {
3910
- return callNativeSync(() => this.#runtime.actorConns(this.#ctx)).length;
3911
- }
3912
- get(key) {
3913
- const conns = callNativeSync(() => this.#runtime.actorConns(this.#ctx));
3914
- const conn = conns.find(
3915
- (c) => this.#runtime.connId(c) === key
3916
- );
3917
- if (!conn) return void 0;
3918
- return this.#connToAdapter(conn);
3919
- }
3920
- has(key) {
3921
- const conns = callNativeSync(() => this.#runtime.actorConns(this.#ctx));
3922
- return conns.some((c) => this.#runtime.connId(c) === key);
3923
- }
3924
- keys() {
3925
- const conns = callNativeSync(() => this.#runtime.actorConns(this.#ctx));
3926
- return conns.map((c) => this.#runtime.connId(c))[Symbol.iterator]();
3927
- }
3928
- values() {
3929
- const conns = callNativeSync(() => this.#runtime.actorConns(this.#ctx));
3930
- return conns.map((c) => this.#connToAdapter(c))[Symbol.iterator]();
3931
- }
3932
- entries() {
3933
- const conns = callNativeSync(() => this.#runtime.actorConns(this.#ctx));
3934
- return conns.map(
3935
- (c) => [this.#runtime.connId(c), this.#connToAdapter(c)]
3936
- )[Symbol.iterator]();
3937
- }
3938
- forEach(callback, thisArg) {
3939
- const conns = callNativeSync(() => this.#runtime.actorConns(this.#ctx));
3940
- for (const conn of conns) {
3941
- const id = this.#runtime.connId(conn);
3942
- callback.call(thisArg, this.#connToAdapter(conn), id, this);
3943
- }
3944
- }
3945
- [Symbol.iterator]() {
3946
- return this.entries();
3947
- }
3948
- [Symbol.toStringTag] = "NativeConnectionMap";
3949
- };
3950
3756
  var ActorContextHandleAdapter = class {
3951
3757
  #runtime;
3952
3758
  #ctx;
@@ -3955,9 +3761,9 @@ var ActorContextHandleAdapter = class {
3955
3761
  #abortSignalCleanup;
3956
3762
  #client;
3957
3763
  #clientFactory;
3958
- #connMap;
3959
3764
  #databaseProvider;
3960
3765
  #db;
3766
+ #dbProxy;
3961
3767
  #dispatchCancelToken;
3962
3768
  #kv;
3963
3769
  #queue;
@@ -4000,45 +3806,56 @@ var ActorContextHandleAdapter = class {
4000
3806
  if (!this.#databaseProvider) {
4001
3807
  throw databaseNotConfiguredError();
4002
3808
  }
4003
- if (this.#db) {
4004
- return this.#db;
4005
- }
4006
- const runtimeState = getNativeRuntimeState(this.#runtime, this.#ctx);
4007
- const cachedClient = runtimeState.databaseClient;
4008
- if (cachedClient) {
4009
- this.#db = cachedClient.client;
4010
- return this.#db;
4011
- }
4012
- throw databaseClientNotReadyError();
4013
- }
4014
- [RAW_STATE_SYMBOL]() {
4015
- if (!this.#stateEnabled) {
4016
- throw stateNotEnabledError();
3809
+ if (!this.#dbProxy) {
3810
+ this.#dbProxy = new Proxy(
3811
+ {},
3812
+ {
3813
+ get: (_target, property) => {
3814
+ if (property === "then") {
3815
+ return void 0;
3816
+ }
3817
+ return async (...args) => {
3818
+ const client = await this.ensureDatabaseClient();
3819
+ const value = Reflect.get(
3820
+ client,
3821
+ property
3822
+ );
3823
+ if (typeof value !== "function") {
3824
+ return value;
3825
+ }
3826
+ return await value.apply(client, args);
3827
+ };
3828
+ }
3829
+ }
3830
+ );
4017
3831
  }
4018
- return this.#readState();
3832
+ return this.#dbProxy;
4019
3833
  }
4020
3834
  get state() {
4021
3835
  if (!this.#stateEnabled) {
4022
3836
  throw stateNotEnabledError();
4023
3837
  }
3838
+ const actorState = getNativePersistState(this.#runtime, this.#ctx);
4024
3839
  const nextState = this.#readState();
4025
- return createWriteThroughProxy(
4026
- nextState,
4027
- (nextValue) => {
4028
- this.#writeState(nextValue, { scheduleSave: true });
4029
- },
4030
- (newValue) => {
4031
- this.#assertCanMutateState();
4032
- assertJsonCompatValue(newValue);
4033
- }
4034
- );
3840
+ if (actorState.stateProxy === void 0 || actorState.stateProxyTarget !== nextState) {
3841
+ actorState.stateProxyTarget = nextState;
3842
+ actorState.stateProxy = createWriteThroughProxy(
3843
+ nextState,
3844
+ (nextValue) => {
3845
+ this.#writeState(nextValue, { scheduleSave: true });
3846
+ },
3847
+ () => {
3848
+ this.#assertCanMutateState();
3849
+ }
3850
+ );
3851
+ }
3852
+ return actorState.stateProxy;
4035
3853
  }
4036
3854
  set state(value) {
4037
3855
  if (!this.#stateEnabled) {
4038
3856
  throw stateNotEnabledError();
4039
3857
  }
4040
3858
  this.#assertCanMutateState();
4041
- assertJsonCompatValue(value);
4042
3859
  this.#writeState(value, { scheduleSave: true });
4043
3860
  }
4044
3861
  initializeState(value) {
@@ -4095,10 +3912,25 @@ var ActorContextHandleAdapter = class {
4095
3912
  return callNativeSync(() => this.#runtime.actorRegion(this.#ctx));
4096
3913
  }
4097
3914
  get conns() {
4098
- if (!this.#connMap) {
4099
- this.#connMap = new NativeConnectionMap(this.#runtime, this.#ctx, this.#schemas);
4100
- }
4101
- return this.#connMap;
3915
+ return new Map(
3916
+ callNativeSync(() => this.#runtime.actorConns(this.#ctx)).map(
3917
+ (conn) => [
3918
+ this.#runtime.connId(conn),
3919
+ new NativeConnAdapter(
3920
+ this.#runtime,
3921
+ conn,
3922
+ this.#schemas,
3923
+ this.#ctx,
3924
+ (connId) => callNativeSync(
3925
+ () => this.#runtime.actorQueueHibernationRemoval(
3926
+ this.#ctx,
3927
+ connId
3928
+ )
3929
+ )
3930
+ )
3931
+ ]
3932
+ )
3933
+ );
4102
3934
  }
4103
3935
  get log() {
4104
3936
  return logger2();
@@ -4296,39 +4128,20 @@ var ActorContextHandleAdapter = class {
4296
4128
  });
4297
4129
  }
4298
4130
  keepAwake(promise) {
4299
- const startedAt = Date.now();
4300
- logger2().debug({
4301
- msg: "keepAwake registered",
4302
- at: startedAt
4303
- });
4304
- const trackedPromise = Promise.resolve(promise).then(
4305
- () => {
4306
- logger2().debug({
4307
- msg: "keepAwake promise resolved",
4308
- durationMs: Date.now() - startedAt
4309
- });
4310
- },
4311
- (error) => {
4312
- logger2().warn({
4313
- msg: "keepAwake promise rejected",
4314
- durationMs: Date.now() - startedAt,
4315
- error: stringifyError(error)
4316
- });
4317
- }
4318
- ).then(() => null);
4131
+ const trackedPromise = Promise.resolve(promise).catch((error) => {
4132
+ logger2().warn({
4133
+ msg: "keepAwake promise rejected",
4134
+ error: stringifyError(error)
4135
+ });
4136
+ }).then(() => null);
4319
4137
  try {
4320
4138
  callNativeSync(
4321
4139
  () => this.#runtime.actorKeepAwake(this.#ctx, trackedPromise)
4322
4140
  );
4323
4141
  } catch (error) {
4324
- if (isClosedTaskRegistrationError(error)) {
4325
- logger2().warn({
4326
- msg: "keepAwake registration dropped (teardown already started); promise will not delay grace",
4327
- error: stringifyError(error)
4328
- });
4329
- return promise;
4142
+ if (!isClosedTaskRegistrationError(error)) {
4143
+ throw error;
4330
4144
  }
4331
- throw error;
4332
4145
  }
4333
4146
  return promise;
4334
4147
  }
@@ -4411,6 +4224,7 @@ var ActorContextHandleAdapter = class {
4411
4224
  }
4412
4225
  async dispose() {
4413
4226
  var _a;
4227
+ this.#flushStateChange();
4414
4228
  (_a = this.#abortSignalCleanup) == null ? void 0 : _a.call(this);
4415
4229
  this.#sql = void 0;
4416
4230
  }
@@ -4438,13 +4252,12 @@ var ActorContextHandleAdapter = class {
4438
4252
  return actorState.state;
4439
4253
  }
4440
4254
  #writeState(value, options) {
4441
- encodeValue(value);
4442
4255
  const actorState = getNativePersistState(this.#runtime, this.#ctx);
4443
4256
  actorState.state = value;
4444
4257
  if (!options.scheduleSave) {
4445
4258
  return;
4446
4259
  }
4447
- this.#handleStateChange();
4260
+ this.#scheduleSave();
4448
4261
  }
4449
4262
  #assertCanMutateState() {
4450
4263
  const actorState = getNativePersistState(this.#runtime, this.#ctx);
@@ -4452,9 +4265,31 @@ var ActorContextHandleAdapter = class {
4452
4265
  throw stateMutationReentrantError();
4453
4266
  }
4454
4267
  }
4455
- #handleStateChange() {
4268
+ // Coalesce the request-save and onStateChange work to once per event loop
4269
+ // tick. A synchronous burst of mutations (for example
4270
+ // `Object.assign(c.state, ...)`) would otherwise cross the NAPI boundary and
4271
+ // run onStateChange once per field, re-serializing the whole state each time
4272
+ // and pinning the event loop on large state.
4273
+ #scheduleSave() {
4456
4274
  const actorState = getNativePersistState(this.#runtime, this.#ctx);
4457
- encodeValue(actorState.state);
4275
+ if (actorState.saveScheduled) {
4276
+ return;
4277
+ }
4278
+ actorState.saveScheduled = true;
4279
+ actorState.pendingSaveHandle = setImmediate(() => {
4280
+ this.#flushStateChange();
4281
+ });
4282
+ }
4283
+ #flushStateChange() {
4284
+ const actorState = getNativePersistState(this.#runtime, this.#ctx);
4285
+ if (!actorState.saveScheduled) {
4286
+ return;
4287
+ }
4288
+ actorState.saveScheduled = false;
4289
+ if (actorState.pendingSaveHandle !== void 0) {
4290
+ clearImmediate(actorState.pendingSaveHandle);
4291
+ actorState.pendingSaveHandle = void 0;
4292
+ }
4458
4293
  callNativeSync(
4459
4294
  () => this.#runtime.actorRequestSave(this.#ctx, { immediate: false })
4460
4295
  );
@@ -4852,10 +4687,6 @@ function buildNativeFactory(runtime, registryConfig, definition) {
4852
4687
  isWorkflowEnabled: getNativeWorkflowInspector(ctx) !== void 0
4853
4688
  });
4854
4689
  } catch (error) {
4855
- logger2().error({
4856
- msg: "error replaying workflow history",
4857
- error
4858
- });
4859
4690
  return errorResponse(error);
4860
4691
  }
4861
4692
  }
@@ -5007,10 +4838,6 @@ function buildNativeFactory(runtime, registryConfig, definition) {
5007
4838
  );
5008
4839
  return jsonResponse({ output });
5009
4840
  } catch (error) {
5010
- logger2().error({
5011
- msg: "Error handling inspector action request",
5012
- error
5013
- });
5014
4841
  return errorResponse(error);
5015
4842
  }
5016
4843
  }
@@ -5024,10 +4851,6 @@ function buildNativeFactory(runtime, registryConfig, definition) {
5024
4851
  { status: 404 }
5025
4852
  );
5026
4853
  } catch (error) {
5027
- logger2().error({
5028
- msg: "Error handling inspector request",
5029
- error
5030
- });
5031
4854
  return errorResponse(error);
5032
4855
  } finally {
5033
4856
  await actorCtx.dispose();
@@ -5642,10 +5465,6 @@ async function buildRegistryWithRuntime(config, runtime) {
5642
5465
  }
5643
5466
  async function buildConfiguredRegistry(config) {
5644
5467
  const runtime = await loadConfiguredRuntime(config);
5645
- if (runtime.kind === "napi") {
5646
- const { startProcessMetrics } = await import("./process-metrics-NW754INA.js");
5647
- startProcessMetrics();
5648
- }
5649
5468
  return buildRegistryWithRuntime(
5650
5469
  normalizeRuntimeConfig(config, runtime),
5651
5470
  runtime
@@ -5669,6 +5488,7 @@ function finishShutdownSignal(signal) {
5669
5488
  }
5670
5489
  var Registry = class {
5671
5490
  #config;
5491
+ routes;
5672
5492
  get config() {
5673
5493
  return this.#config;
5674
5494
  }
@@ -5685,6 +5505,11 @@ var Registry = class {
5685
5505
  #signalHandlers = {};
5686
5506
  constructor(config) {
5687
5507
  this.#config = config;
5508
+ this.routes = {
5509
+ health: () => this.#healthRoute(),
5510
+ metadata: () => this.#metadataRoute(),
5511
+ prometheusMetrics: (request) => this.#prometheusMetricsRoute(request)
5512
+ };
5688
5513
  }
5689
5514
  #ensureServerlessPoolConfigured(config) {
5690
5515
  if (!config.configurePool) return void 0;
@@ -5878,46 +5703,88 @@ var Registry = class {
5878
5703
  };
5879
5704
  }
5880
5705
  /**
5881
- * Starts an HTTP server that dispatches every request through the
5882
- * serverless handler. Uses `crossPlatformServe` to pick the right
5883
- * runtime (Node, Bun, Deno).
5884
- *
5885
- * @param opts.port Port to listen on. Defaults to 3000.
5886
- * @param opts.publicDir If set, serves static files from this directory
5887
- * before falling through to the registry handler.
5888
- *
5889
- * @example
5890
- * ```ts
5891
- * await registry.listen();
5892
- * await registry.listen({ port: 8080, publicDir: "./public" });
5893
- * ```
5706
+ * Returns a health response suitable for mounting in a user-owned router.
5894
5707
  */
5895
- async listen(opts = {}) {
5896
- const port = opts.port ?? 3e3;
5897
- const config = this.parseConfig();
5898
- const runtime = detectRuntime();
5899
- const app = new Hono();
5900
- if (opts.publicDir) {
5901
- const serveStatic = await loadRuntimeServeStatic(runtime);
5902
- app.use("*", serveStatic({ root: opts.publicDir }));
5708
+ async #healthRoute() {
5709
+ const configured = await this.#activeConfiguredRegistry();
5710
+ if (!configured) {
5711
+ return jsonRouteResponse(503, {
5712
+ status: "not_started",
5713
+ runtime: "rivetkit",
5714
+ version: VERSION
5715
+ });
5716
+ }
5717
+ const { runtime, registry } = configured;
5718
+ if (!runtime.registryHealth) {
5719
+ return jsonRouteResponse(501, {
5720
+ status: "unsupported",
5721
+ runtime: "rivetkit",
5722
+ version: VERSION
5723
+ });
5903
5724
  }
5904
- app.all("*", (c) => this.handler(c.req.raw));
5905
- await crossPlatformServe(config, port, app, runtime);
5725
+ const response = await runtime.registryHealth(registry);
5726
+ return new Response(new Uint8Array(response.body), {
5727
+ status: response.status,
5728
+ headers: response.headers
5729
+ });
5906
5730
  }
5907
- async diagnostics() {
5908
- var _a;
5731
+ /**
5732
+ * Returns serverless metadata suitable for mounting in a user-owned router.
5733
+ */
5734
+ async #metadataRoute() {
5735
+ const configured = await this.#activeConfiguredRegistry();
5736
+ if (!configured) {
5737
+ return new Response("registry not started\n", {
5738
+ status: 503,
5739
+ headers: { "content-type": "text/plain; charset=utf-8" }
5740
+ });
5741
+ }
5742
+ const { runtime, registry } = configured;
5743
+ if (!runtime.registryMetadata) {
5744
+ return new Response("metadata is not supported by this runtime\n", {
5745
+ status: 501,
5746
+ headers: { "content-type": "text/plain; charset=utf-8" }
5747
+ });
5748
+ }
5749
+ const response = await runtime.registryMetadata(registry);
5750
+ return new Response(new Uint8Array(response.body), {
5751
+ status: response.status,
5752
+ headers: response.headers
5753
+ });
5754
+ }
5755
+ /**
5756
+ * Returns a Prometheus metrics response suitable for mounting in a user-owned router.
5757
+ */
5758
+ async #prometheusMetricsRoute(_request) {
5759
+ const configured = await this.#activeConfiguredRegistry();
5760
+ if (!configured) {
5761
+ return new Response("registry not started\n", {
5762
+ status: 503,
5763
+ headers: { "content-type": "text/plain; charset=utf-8" }
5764
+ });
5765
+ }
5766
+ const { runtime, registry } = configured;
5767
+ if (!runtime.registryMetrics) {
5768
+ return new Response("metrics are not supported by this runtime\n", {
5769
+ status: 501,
5770
+ headers: { "content-type": "text/plain; charset=utf-8" }
5771
+ });
5772
+ }
5773
+ const response = await runtime.registryMetrics(registry);
5774
+ return new Response(new Uint8Array(response.body), {
5775
+ status: response.status,
5776
+ headers: response.headers
5777
+ });
5778
+ }
5779
+ async #activeConfiguredRegistry() {
5909
5780
  const candidates = [
5910
5781
  this.#runtimeServerlessPromise,
5911
5782
  this.#runtimeServeConfiguredPromise
5912
5783
  ].filter(
5913
5784
  (candidate) => candidate !== void 0
5914
5785
  );
5915
- for (const candidate of candidates) {
5916
- const { runtime, registry } = await candidate;
5917
- const diagnostics = await ((_a = runtime.registryDiagnostics) == null ? void 0 : _a.call(runtime, registry));
5918
- if (diagnostics) return diagnostics;
5919
- }
5920
- return { mode: "not_started", envoyActiveActorCount: null };
5786
+ if (candidates.length === 0) return void 0;
5787
+ return await candidates[0];
5921
5788
  }
5922
5789
  /**
5923
5790
  * Starts an actor envoy for standalone server deployments.
@@ -5928,8 +5795,8 @@ var Registry = class {
5928
5795
  this.#runtimeServeConfiguredPromise = configuredRegistryPromise;
5929
5796
  this.#runtimeServePromise = configuredRegistryPromise.then(async ({ runtime, registry, serveConfig }) => {
5930
5797
  await runtime.serveRegistry(registry, serveConfig);
5931
- }).catch((error) => {
5932
- logger2().warn({ error }, "runtime registry serve errored");
5798
+ }).catch((err) => {
5799
+ logger2().warn({ err }, "runtime registry serve errored");
5933
5800
  });
5934
5801
  this.#installSignalHandlers(config, configuredRegistryPromise);
5935
5802
  }
@@ -5967,8 +5834,8 @@ var Registry = class {
5967
5834
  signal,
5968
5835
  config,
5969
5836
  configuredRegistryPromise
5970
- ).catch((error) => {
5971
- logger2().warn({ error }, "shutdown error");
5837
+ ).catch((err) => {
5838
+ logger2().warn({ err }, "shutdown error");
5972
5839
  });
5973
5840
  }
5974
5841
  async #runShutdown(signal, config, configuredRegistryPromise) {
@@ -5980,9 +5847,9 @@ var Registry = class {
5980
5847
  try {
5981
5848
  const { runtime, registry } = await configuredRegistryPromise;
5982
5849
  await runtime.shutdownRegistry(registry);
5983
- } catch (error) {
5850
+ } catch (err) {
5984
5851
  logger2().warn(
5985
- { error },
5852
+ { err },
5986
5853
  "runtime registry shutdown errored (mode A)"
5987
5854
  );
5988
5855
  }
@@ -5997,7 +5864,7 @@ var Registry = class {
5997
5864
  await runtime.shutdownRegistry(registry);
5998
5865
  } catch (err) {
5999
5866
  logger2().warn(
6000
- { error: err },
5867
+ { err },
6001
5868
  "runtime registry shutdown errored (mode B)"
6002
5869
  );
6003
5870
  }
@@ -6099,6 +5966,12 @@ function isServerlessMetadataRequest(request, basePath) {
6099
5966
  const normalizedBase = basePath === "/" ? "" : `/${basePath.replace(/^\/+|\/+$/g, "")}`;
6100
5967
  return parsed.pathname === `${normalizedBase}/metadata`;
6101
5968
  }
5969
+ function jsonRouteResponse(status, body) {
5970
+ return new Response(JSON.stringify(body), {
5971
+ status,
5972
+ headers: { "content-type": "application/json" }
5973
+ });
5974
+ }
6102
5975
  function setup(input) {
6103
5976
  return new Registry(input);
6104
5977
  }