rivetkit 2.3.7 → 2.3.8

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 (90) hide show
  1. package/dist/browser/client.d.ts +34 -6
  2. package/dist/browser/client.js +33 -14
  3. package/dist/browser/client.js.map +1 -1
  4. package/dist/browser/inspector/client.js +1 -1
  5. package/dist/browser/inspector/client.js.map +1 -1
  6. package/dist/tsup/agent-os/index.cjs +1 -1
  7. package/dist/tsup/agent-os/index.cjs.map +1 -1
  8. package/dist/tsup/agent-os/index.d.cts +34 -6
  9. package/dist/tsup/agent-os/index.d.ts +34 -6
  10. package/dist/tsup/agent-os/index.js +1 -1
  11. package/dist/tsup/agent-os/index.js.map +1 -1
  12. package/dist/tsup/{chunk-46AE7JOI.cjs → chunk-5MJPN3QU.cjs} +172 -151
  13. package/dist/tsup/chunk-5MJPN3QU.cjs.map +1 -0
  14. package/dist/tsup/{chunk-MNZFNIVI.cjs → chunk-7TNEDX3Y.cjs} +3 -3
  15. package/dist/tsup/{chunk-MNZFNIVI.cjs.map → chunk-7TNEDX3Y.cjs.map} +1 -1
  16. package/dist/tsup/{chunk-YU3C5OCU.js → chunk-BL6ERZQO.js} +36 -15
  17. package/dist/tsup/chunk-BL6ERZQO.js.map +1 -0
  18. package/dist/tsup/{chunk-DOPH7DT2.cjs → chunk-F6GCLL5Z.cjs} +7 -7
  19. package/dist/tsup/{chunk-DOPH7DT2.cjs.map → chunk-F6GCLL5Z.cjs.map} +1 -1
  20. package/dist/tsup/{chunk-6D2WRHJV.js → chunk-HWBISPRP.js} +2 -2
  21. package/dist/tsup/{chunk-UIZZCJ5W.cjs → chunk-IJMVVULS.cjs} +4 -4
  22. package/dist/tsup/{chunk-UIZZCJ5W.cjs.map → chunk-IJMVVULS.cjs.map} +1 -1
  23. package/dist/tsup/{chunk-7YQJXWBW.js → chunk-MY6BRV3S.js} +3 -3
  24. package/dist/tsup/{chunk-2SGPZEAJ.cjs → chunk-NUMGL52R.cjs} +6 -3
  25. package/dist/tsup/chunk-NUMGL52R.cjs.map +1 -0
  26. package/dist/tsup/{chunk-TQHMPWL6.cjs → chunk-TMTJPSHQ.cjs} +9 -9
  27. package/dist/tsup/{chunk-TQHMPWL6.cjs.map → chunk-TMTJPSHQ.cjs.map} +1 -1
  28. package/dist/tsup/{chunk-YHPFCYL3.js → chunk-V7PJYBA5.js} +2 -2
  29. package/dist/tsup/{chunk-CH25U5NO.js → chunk-YFXQ7DBH.js} +3 -3
  30. package/dist/tsup/{chunk-OG4OR2CM.js → chunk-ZKDZW5DQ.js} +6 -3
  31. package/dist/tsup/chunk-ZKDZW5DQ.js.map +1 -0
  32. package/dist/tsup/client/mod.cjs +5 -5
  33. package/dist/tsup/client/mod.d.cts +2 -2
  34. package/dist/tsup/client/mod.d.ts +2 -2
  35. package/dist/tsup/client/mod.js +4 -4
  36. package/dist/tsup/common/log.cjs +2 -2
  37. package/dist/tsup/common/log.js +1 -1
  38. package/dist/tsup/common/websocket.cjs +3 -3
  39. package/dist/tsup/common/websocket.js +2 -2
  40. package/dist/tsup/{config-BRpVbJCD.d.ts → config-CUymbyM6.d.ts} +35 -7
  41. package/dist/tsup/{config-BobvQpex.d.cts → config-CpB-e4I9.d.cts} +35 -7
  42. package/dist/tsup/{context-Cj-DFyiy.d.ts → context-YBUBTwTS.d.ts} +1 -1
  43. package/dist/tsup/{context-YEBNJrws.d.cts → context-c-6G4mjk.d.cts} +1 -1
  44. package/dist/tsup/db/drizzle.cjs +2 -2
  45. package/dist/tsup/db/drizzle.js +1 -1
  46. package/dist/tsup/db/mod.cjs +2 -2
  47. package/dist/tsup/db/mod.js +1 -1
  48. package/dist/tsup/dynamic/mod.d.cts +1 -1
  49. package/dist/tsup/dynamic/mod.d.ts +1 -1
  50. package/dist/tsup/inspector/mod.cjs +4 -4
  51. package/dist/tsup/inspector/mod.js +3 -3
  52. package/dist/tsup/inspector-tab/mod.d.cts +2 -2
  53. package/dist/tsup/inspector-tab/mod.d.ts +2 -2
  54. package/dist/tsup/mod.cjs +449 -124
  55. package/dist/tsup/mod.cjs.map +1 -1
  56. package/dist/tsup/mod.d.cts +3 -3
  57. package/dist/tsup/mod.d.ts +3 -3
  58. package/dist/tsup/mod.js +388 -63
  59. package/dist/tsup/mod.js.map +1 -1
  60. package/dist/tsup/test/mod.cjs +6 -6
  61. package/dist/tsup/test/mod.d.cts +1 -1
  62. package/dist/tsup/test/mod.d.ts +1 -1
  63. package/dist/tsup/test/mod.js +4 -4
  64. package/dist/tsup/utils.cjs +2 -2
  65. package/dist/tsup/utils.js +1 -1
  66. package/dist/tsup/workflow/mod.cjs +6 -6
  67. package/dist/tsup/workflow/mod.d.cts +3 -3
  68. package/dist/tsup/workflow/mod.d.ts +3 -3
  69. package/dist/tsup/workflow/mod.js +3 -3
  70. package/package.json +8 -8
  71. package/src/client/actor-handle.ts +3 -1
  72. package/src/client/raw-utils.ts +11 -2
  73. package/src/common/actor-router-consts.ts +1 -0
  74. package/src/common/encoding.ts +4 -1
  75. package/src/common/fetch-like.ts +49 -0
  76. package/src/engine-client/actor-http-client.ts +6 -22
  77. package/src/registry/index.ts +159 -14
  78. package/src/registry/napi-runtime.ts +74 -0
  79. package/src/registry/native-http.ts +208 -0
  80. package/src/registry/native.ts +111 -63
  81. package/src/registry/runtime.ts +35 -0
  82. package/src/registry/wasm-runtime.ts +11 -0
  83. package/dist/tsup/chunk-2SGPZEAJ.cjs.map +0 -1
  84. package/dist/tsup/chunk-46AE7JOI.cjs.map +0 -1
  85. package/dist/tsup/chunk-OG4OR2CM.js.map +0 -1
  86. package/dist/tsup/chunk-YU3C5OCU.js.map +0 -1
  87. /package/dist/tsup/{chunk-6D2WRHJV.js.map → chunk-HWBISPRP.js.map} +0 -0
  88. /package/dist/tsup/{chunk-7YQJXWBW.js.map → chunk-MY6BRV3S.js.map} +0 -0
  89. /package/dist/tsup/{chunk-YHPFCYL3.js.map → chunk-V7PJYBA5.js.map} +0 -0
  90. /package/dist/tsup/{chunk-CH25U5NO.js.map → chunk-YFXQ7DBH.js.map} +0 -0
package/dist/tsup/mod.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  decodeWorkflowHistoryTransport
3
- } from "./chunk-6D2WRHJV.js";
3
+ } from "./chunk-HWBISPRP.js";
4
4
  import {
5
5
  ACTOR_CONTEXT_INTERNAL_SYMBOL,
6
6
  ActorConfigSchema,
@@ -16,18 +16,20 @@ import {
16
16
  import {
17
17
  ALLOWED_PUBLIC_HEADERS,
18
18
  HEADER_CONN_PARAMS,
19
+ HEADER_ORIGINAL_REQUEST_URL,
19
20
  RemoteEngineControlClient,
20
21
  convertRegistryConfigToClientConfig,
21
22
  createClientWithDriver,
22
23
  getDatacenters,
24
+ isResponseLike,
23
25
  tryParseEndpoint,
24
26
  updateRunnerConfig
25
- } from "./chunk-YU3C5OCU.js";
27
+ } from "./chunk-BL6ERZQO.js";
26
28
  import {
27
29
  makePrefixedKey,
28
30
  removePrefixFromKey
29
31
  } from "./chunk-JI6GZ2C2.js";
30
- import "./chunk-YHPFCYL3.js";
32
+ import "./chunk-V7PJYBA5.js";
31
33
  import "./chunk-7AFZMFPQ.js";
32
34
  import {
33
35
  LogLevelSchema,
@@ -61,7 +63,7 @@ import {
61
63
  parsePortEnv,
62
64
  stringifyError,
63
65
  toUint8Array
64
- } from "./chunk-OG4OR2CM.js";
66
+ } from "./chunk-ZKDZW5DQ.js";
65
67
  import {
66
68
  INTERNAL_ERROR_CODE,
67
69
  RivetError,
@@ -1433,6 +1435,36 @@ function toNapiSqlBatchStatement(statement) {
1433
1435
  function toNapiBuffer(value) {
1434
1436
  return Buffer.from(value);
1435
1437
  }
1438
+ function toNapiApplication(application) {
1439
+ return async (error, request) => {
1440
+ if (error) throw error;
1441
+ if (!request) {
1442
+ throw new Error("application fetch callback received no request");
1443
+ }
1444
+ const response = await application(
1445
+ {
1446
+ ...request,
1447
+ body: new Uint8Array(request.body),
1448
+ cancelToken: request.cancelToken
1449
+ },
1450
+ request.responseBodyStream ? fromNapiHttpResponseBodyStream(
1451
+ request.responseBodyStream
1452
+ ) : void 0
1453
+ );
1454
+ return {
1455
+ ...response,
1456
+ body: response.body === void 0 ? void 0 : toNapiBuffer(response.body)
1457
+ };
1458
+ };
1459
+ }
1460
+ function fromNapiHttpResponseBodyStream(stream) {
1461
+ return {
1462
+ cancelled: () => stream.cancelled(),
1463
+ write: (chunk) => stream.write(Buffer.from(chunk)),
1464
+ end: () => stream.end(),
1465
+ error: (message) => stream.error(message)
1466
+ };
1467
+ }
1436
1468
  function toNapiHttpRequest(request) {
1437
1469
  if (!request) {
1438
1470
  return request;
@@ -1539,12 +1571,25 @@ var NapiCoreRuntime = class {
1539
1571
  );
1540
1572
  }
1541
1573
  async serveListener(registry, listener, config) {
1574
+ const application = listener.application ? toNapiApplication(listener.application) : void 0;
1542
1575
  await asNativeRegistry(registry).serveListener(
1543
1576
  {
1544
1577
  port: listener.port,
1545
1578
  host: listener.host,
1546
1579
  publicDir: listener.publicDir
1547
1580
  },
1581
+ config,
1582
+ application
1583
+ );
1584
+ }
1585
+ async serveApplicationListener(registry, listener, config) {
1586
+ await asNativeRegistry(registry).serveApplicationListener(
1587
+ {
1588
+ port: listener.port,
1589
+ host: listener.host,
1590
+ publicDir: listener.publicDir
1591
+ },
1592
+ toNapiApplication(listener.application),
1548
1593
  config
1549
1594
  );
1550
1595
  }
@@ -1932,6 +1977,137 @@ async function loadNapiRuntime() {
1932
1977
  };
1933
1978
  }
1934
1979
 
1980
+ // src/registry/native-http.ts
1981
+ var HTTP_BODY_CHUNK_SIZE = 64 * 1024;
1982
+ function runtimeBytesToArrayBuffer(value) {
1983
+ return value.buffer.slice(
1984
+ value.byteOffset,
1985
+ value.byteOffset + value.byteLength
1986
+ );
1987
+ }
1988
+ function buildNativeHttpRequest(init) {
1989
+ var _a;
1990
+ const headers = new Headers(init.headers);
1991
+ const originalUrl = headers.get(HEADER_ORIGINAL_REQUEST_URL);
1992
+ headers.delete(HEADER_ORIGINAL_REQUEST_URL);
1993
+ const url = originalUrl ?? (init.uri.startsWith("http") ? init.uri : new URL(init.uri, "http://127.0.0.1").toString());
1994
+ const method2 = init.method.toUpperCase();
1995
+ const bodyForbidden = method2 === "GET" || method2 === "HEAD";
1996
+ const body = bodyForbidden ? void 0 : init.bodyStream ? new ReadableStream({
1997
+ async pull(controller) {
1998
+ var _a2, _b;
1999
+ try {
2000
+ if (init.body && init.body.length > 0) {
2001
+ controller.enqueue(new Uint8Array(init.body));
2002
+ init.body = void 0;
2003
+ return;
2004
+ }
2005
+ const chunk = await ((_a2 = init.bodyStream) == null ? void 0 : _a2.read());
2006
+ if (!chunk) {
2007
+ controller.close();
2008
+ } else {
2009
+ controller.enqueue(new Uint8Array(chunk));
2010
+ }
2011
+ } catch (error) {
2012
+ (_b = init.abortController) == null ? void 0 : _b.abort(error);
2013
+ controller.error(error);
2014
+ }
2015
+ },
2016
+ async cancel() {
2017
+ var _a2;
2018
+ await ((_a2 = init.bodyStream) == null ? void 0 : _a2.cancel());
2019
+ }
2020
+ }) : init.body && init.body.length > 0 ? runtimeBytesToArrayBuffer(init.body) : void 0;
2021
+ const streamInit = init.bodyStream && !bodyForbidden ? { duplex: "half" } : {};
2022
+ return new Request(url, {
2023
+ method: method2,
2024
+ headers,
2025
+ body,
2026
+ signal: ((_a = init.abortController) == null ? void 0 : _a.signal) ?? init.signal,
2027
+ ...streamInit
2028
+ });
2029
+ }
2030
+ async function cancelNativeHttpRequestBody(bodyStream) {
2031
+ await (bodyStream == null ? void 0 : bodyStream.cancel());
2032
+ }
2033
+ async function writeResponseChunk(stream, chunk) {
2034
+ for (let offset = 0; offset < chunk.byteLength; offset += HTTP_BODY_CHUNK_SIZE) {
2035
+ await stream.write(
2036
+ chunk.subarray(offset, offset + HTTP_BODY_CHUNK_SIZE)
2037
+ );
2038
+ }
2039
+ }
2040
+ async function pumpResponseBody(reader, stream) {
2041
+ var _a;
2042
+ const cancelled = stream.cancelled().then(() => ({ cancelled: true }));
2043
+ try {
2044
+ for (; ; ) {
2045
+ const read = reader.read().then((next2) => ({ cancelled: false, next: next2 }));
2046
+ const result = await Promise.race([read, cancelled]);
2047
+ if (result.cancelled) {
2048
+ await reader.cancel(
2049
+ new Error("native http response stream receiver dropped")
2050
+ );
2051
+ return;
2052
+ }
2053
+ const { next } = result;
2054
+ if (next.done) {
2055
+ await stream.end();
2056
+ return;
2057
+ }
2058
+ if ((_a = next.value) == null ? void 0 : _a.byteLength) {
2059
+ await writeResponseChunk(stream, next.value);
2060
+ }
2061
+ }
2062
+ } catch (error) {
2063
+ try {
2064
+ await stream.error(stringifyError(error));
2065
+ } catch (streamError) {
2066
+ logger2().debug({
2067
+ msg: "failed to report native http response stream error",
2068
+ error: streamError
2069
+ });
2070
+ }
2071
+ try {
2072
+ await reader.cancel(error);
2073
+ } catch {
2074
+ }
2075
+ } finally {
2076
+ reader.releaseLock();
2077
+ }
2078
+ }
2079
+ async function convertNativeHttpResponse(response, responseBodyStream) {
2080
+ const headers = Object.fromEntries(response.headers.entries());
2081
+ if (!response.body) {
2082
+ return {
2083
+ response: {
2084
+ status: response.status,
2085
+ headers,
2086
+ body: new Uint8Array()
2087
+ }
2088
+ };
2089
+ }
2090
+ if (responseBodyStream) {
2091
+ const reader = response.body.getReader();
2092
+ const bodyCompletion = pumpResponseBody(reader, responseBodyStream);
2093
+ return {
2094
+ response: {
2095
+ status: response.status,
2096
+ headers,
2097
+ stream: true
2098
+ },
2099
+ bodyCompletion
2100
+ };
2101
+ }
2102
+ return {
2103
+ response: {
2104
+ status: response.status,
2105
+ headers,
2106
+ body: new Uint8Array(await response.arrayBuffer())
2107
+ }
2108
+ };
2109
+ }
2110
+
1935
2111
  // src/registry/native-validation.ts
1936
2112
  var CONN_PARAMS_KEY = "__conn_params__";
1937
2113
  function validateActionArgs(schemas, name, args) {
@@ -2204,6 +2380,11 @@ var WasmCoreRuntime = class {
2204
2380
  "registry.listen() is not supported on the wasm runtime; use registry.serve() and mount the handler in your platform's HTTP server instead"
2205
2381
  );
2206
2382
  }
2383
+ async serveApplicationListener(_registry, _listener, _config) {
2384
+ throw new Error(
2385
+ "registry.listen() is not supported on the wasm runtime; use an application-owned HTTP server instead"
2386
+ );
2387
+ }
2207
2388
  createActorFactory(callbacks, config) {
2208
2389
  return callWasmSync(
2209
2390
  () => asActorFactoryHandle2(
@@ -3061,7 +3242,7 @@ function toRuntimeBytes(value) {
3061
3242
  function arrayBufferViewToRuntimeBytes(value) {
3062
3243
  return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
3063
3244
  }
3064
- function runtimeBytesToArrayBuffer(value) {
3245
+ function runtimeBytesToArrayBuffer2(value) {
3065
3246
  return value.buffer.slice(
3066
3247
  value.byteOffset,
3067
3248
  value.byteOffset + value.byteLength
@@ -3391,24 +3572,6 @@ function decodeArgs(value) {
3391
3572
  const decoded = decodeValue(value);
3392
3573
  return normalizeArgs(decoded);
3393
3574
  }
3394
- function buildRequest(init) {
3395
- const url = init.uri.startsWith("http") ? init.uri : new URL(init.uri, "http://127.0.0.1").toString();
3396
- const body = init.body && init.body.length > 0 ? runtimeBytesToArrayBuffer(init.body) : void 0;
3397
- return new Request(url, {
3398
- method: init.method,
3399
- headers: init.headers,
3400
- body
3401
- });
3402
- }
3403
- async function toRuntimeHttpResponse(response) {
3404
- const headers = Object.fromEntries(response.headers.entries());
3405
- const body = new Uint8Array(await response.arrayBuffer());
3406
- return {
3407
- status: response.status,
3408
- headers,
3409
- body
3410
- };
3411
- }
3412
3575
  function toActorKey(segments) {
3413
3576
  return segments.map(
3414
3577
  (segment) => segment.kind === "number" ? String(segment.numberValue ?? 0) : segment.stringValue ?? ""
@@ -4073,7 +4236,7 @@ var NativeWebSocketAdapter = class {
4073
4236
  this.#runtime.webSocketSetEventCallback(this.#ws, (event2) => {
4074
4237
  if (event2.kind === "message") {
4075
4238
  this.#virtual.triggerMessage(
4076
- event2.binary ? runtimeBytesToArrayBuffer(event2.data) : event2.data,
4239
+ event2.binary ? runtimeBytesToArrayBuffer2(event2.data) : event2.data,
4077
4240
  event2.messageIndex
4078
4241
  );
4079
4242
  return;
@@ -5305,12 +5468,14 @@ function buildNativeFactory(runtime, registryConfig, definition) {
5305
5468
  onStateChange,
5306
5469
  cancelToken
5307
5470
  );
5308
- const maybeHandleNativeInspectorRequest = async (ctx, _rawRequest, jsRequest) => {
5471
+ const maybeHandleNativeInspectorRequest = async (ctx, rawRequest) => {
5309
5472
  var _a2, _b, _c, _d;
5310
- const url = new URL(jsRequest.url);
5473
+ const rawUrl = rawRequest.uri.startsWith("http") ? rawRequest.uri : new URL(rawRequest.uri, "http://127.0.0.1").toString();
5474
+ const url = new URL(rawUrl);
5311
5475
  if (!url.pathname.startsWith("/inspector/")) {
5312
5476
  return void 0;
5313
5477
  }
5478
+ const jsRequest = buildNativeHttpRequest(rawRequest);
5314
5479
  const jsonResponse = (body, init) => new Response(JSON.stringify(body), {
5315
5480
  status: (init == null ? void 0 : init.status) ?? 200,
5316
5481
  headers: {
@@ -5841,7 +6006,7 @@ function buildNativeFactory(runtime, registryConfig, definition) {
5841
6006
  );
5842
6007
  const actorCtx = makeActorCtx(
5843
6008
  ctx,
5844
- request ? buildRequest(request) : void 0
6009
+ request ? buildNativeHttpRequest(request) : void 0
5845
6010
  );
5846
6011
  try {
5847
6012
  await config.onBeforeConnect(
@@ -5861,7 +6026,7 @@ function buildNativeFactory(runtime, registryConfig, definition) {
5861
6026
  const { ctx, conn, params, request } = unwrapTsfnPayload(error, payload);
5862
6027
  const actorCtx = makeActorCtx(
5863
6028
  ctx,
5864
- request ? buildRequest(request) : void 0
6029
+ request ? buildNativeHttpRequest(request) : void 0
5865
6030
  );
5866
6031
  const connAdapter = new NativeConnAdapter(
5867
6032
  runtime,
@@ -5898,7 +6063,7 @@ function buildNativeFactory(runtime, registryConfig, definition) {
5898
6063
  );
5899
6064
  const actorCtx = makeActorCtx(
5900
6065
  ctx,
5901
- request ? buildRequest(request) : void 0
6066
+ request ? buildNativeHttpRequest(request) : void 0
5902
6067
  );
5903
6068
  const connAdapter = new NativeConnAdapter(
5904
6069
  runtime,
@@ -6003,27 +6168,45 @@ function buildNativeFactory(runtime, registryConfig, definition) {
6003
6168
  onRequest: wrapNativeCallback(
6004
6169
  async (error, payload) => {
6005
6170
  try {
6006
- const { ctx, request, cancelToken } = unwrapTsfnPayload(
6007
- error,
6008
- payload
6009
- );
6010
- const jsRequest = buildRequest(request);
6011
- const inspectorResponse = await maybeHandleNativeInspectorRequest(
6012
- ctx,
6013
- request,
6014
- jsRequest
6015
- );
6171
+ const { ctx, request, cancelToken, responseBodyStream } = unwrapTsfnPayload(error, payload);
6172
+ const inspectorResponse = await maybeHandleNativeInspectorRequest(ctx, request);
6016
6173
  if (inspectorResponse) {
6017
- return await toRuntimeHttpResponse(inspectorResponse);
6174
+ await cancelNativeHttpRequestBody(request.bodyStream);
6175
+ return (await convertNativeHttpResponse(
6176
+ inspectorResponse,
6177
+ responseBodyStream
6178
+ )).response;
6018
6179
  }
6019
6180
  if (typeof config.onRequest !== "function") {
6020
- return await toRuntimeHttpResponse(
6021
- new Response(null, { status: 404 })
6022
- );
6181
+ await cancelNativeHttpRequestBody(request.bodyStream);
6182
+ return (await convertNativeHttpResponse(
6183
+ new Response(null, { status: 404 }),
6184
+ responseBodyStream
6185
+ )).response;
6023
6186
  }
6024
- const rawConnParams = jsRequest.headers.get(HEADER_CONN_PARAMS);
6187
+ const requestAbortController = new AbortController();
6188
+ const handlerRequest = buildNativeHttpRequest({
6189
+ ...request,
6190
+ abortController: requestAbortController
6191
+ });
6192
+ const rawConnParams = handlerRequest.headers.get(HEADER_CONN_PARAMS);
6025
6193
  let requestCtx;
6026
6194
  let conn;
6195
+ let removeRequestAbortListener;
6196
+ let cleanupDeferredToBody = false;
6197
+ let cleanedUp = false;
6198
+ const cleanupRequest = async () => {
6199
+ if (cleanedUp) return;
6200
+ cleanedUp = true;
6201
+ removeRequestAbortListener == null ? void 0 : removeRequestAbortListener();
6202
+ try {
6203
+ await (requestCtx == null ? void 0 : requestCtx.dispose());
6204
+ } finally {
6205
+ if (conn) {
6206
+ await runtime.connDisconnect(conn);
6207
+ }
6208
+ }
6209
+ };
6027
6210
  try {
6028
6211
  const connParams = validateConnParams(
6029
6212
  schemaConfig.connParamsSchema,
@@ -6039,23 +6222,56 @@ function buildNativeFactory(runtime, registryConfig, definition) {
6039
6222
  requestCtx = makeConnCtx(
6040
6223
  ctx,
6041
6224
  conn,
6042
- jsRequest,
6225
+ handlerRequest,
6043
6226
  cancelToken
6044
6227
  );
6228
+ const ctxAbortSignal = requestCtx.abortSignal;
6229
+ const abortRequest = () => requestAbortController.abort(ctxAbortSignal.reason);
6230
+ if (ctxAbortSignal.aborted) {
6231
+ abortRequest();
6232
+ } else {
6233
+ ctxAbortSignal.addEventListener(
6234
+ "abort",
6235
+ abortRequest,
6236
+ { once: true }
6237
+ );
6238
+ removeRequestAbortListener = () => ctxAbortSignal.removeEventListener(
6239
+ "abort",
6240
+ abortRequest
6241
+ );
6242
+ }
6045
6243
  const response = await config.onRequest(
6046
6244
  requestCtx,
6047
- jsRequest
6245
+ handlerRequest
6048
6246
  );
6049
- if (!(response instanceof Response)) {
6247
+ if (!isResponseLike(response)) {
6050
6248
  throw new Error(
6051
6249
  "onRequest handler must return a Response"
6052
6250
  );
6053
6251
  }
6054
- return await toRuntimeHttpResponse(response);
6252
+ const conversion = await convertNativeHttpResponse(
6253
+ response,
6254
+ responseBodyStream
6255
+ );
6256
+ if (conversion.bodyCompletion) {
6257
+ cleanupDeferredToBody = true;
6258
+ void conversion.bodyCompletion.then(cleanupRequest).catch((cleanupError) => {
6259
+ logger2().error({
6260
+ msg: "failed to clean up native streaming http request",
6261
+ error: cleanupError
6262
+ });
6263
+ });
6264
+ }
6265
+ return conversion.response;
6055
6266
  } finally {
6056
- await (requestCtx == null ? void 0 : requestCtx.dispose());
6057
- if (conn) {
6058
- await runtime.connDisconnect(conn);
6267
+ try {
6268
+ await cancelNativeHttpRequestBody(
6269
+ request.bodyStream
6270
+ );
6271
+ } finally {
6272
+ if (!cleanupDeferredToBody) {
6273
+ await cleanupRequest();
6274
+ }
6059
6275
  }
6060
6276
  }
6061
6277
  } catch (error2) {
@@ -6070,7 +6286,7 @@ function buildNativeFactory(runtime, registryConfig, definition) {
6070
6286
  onWebSocket: typeof config.onWebSocket === "function" ? wrapNativeCallback(
6071
6287
  async (error, payload) => {
6072
6288
  const { ctx, conn, ws, request } = unwrapTsfnPayload(error, payload);
6073
- const jsRequest = request ? buildRequest(request) : void 0;
6289
+ const jsRequest = request ? buildNativeHttpRequest(request) : void 0;
6074
6290
  const actorCtx = makeConnCtx(ctx, conn, jsRequest);
6075
6291
  try {
6076
6292
  await config.onWebSocket(
@@ -6167,7 +6383,7 @@ function buildNativeFactory(runtime, registryConfig, definition) {
6167
6383
  timeoutMs,
6168
6384
  cancelToken
6169
6385
  } = unwrapTsfnPayload(error, payload);
6170
- const jsRequest = buildRequest(request);
6386
+ const jsRequest = buildNativeHttpRequest(request);
6171
6387
  const actorCtx = withConnContext(
6172
6388
  runtime,
6173
6389
  ctx,
@@ -6318,6 +6534,54 @@ function finishShutdownSignal(signal) {
6318
6534
  }
6319
6535
  process.kill(process.pid, signal);
6320
6536
  }
6537
+ function createApplicationFetch(application, runtime) {
6538
+ return async (request, responseBodyStream) => {
6539
+ const method2 = request.method.toUpperCase();
6540
+ const body = method2 === "GET" || method2 === "HEAD" || request.body.length === 0 ? void 0 : Uint8Array.from(request.body).buffer;
6541
+ const abortController = new AbortController();
6542
+ if (request.cancelToken) {
6543
+ if (runtime.cancellationTokenAborted(request.cancelToken)) {
6544
+ abortController.abort();
6545
+ } else {
6546
+ runtime.onCancellationTokenCancelled(
6547
+ request.cancelToken,
6548
+ () => abortController.abort()
6549
+ );
6550
+ }
6551
+ }
6552
+ const response = await application.fetch(
6553
+ new Request(request.url, {
6554
+ method: method2,
6555
+ headers: request.headers,
6556
+ body,
6557
+ signal: abortController.signal
6558
+ })
6559
+ );
6560
+ if (!isResponseLike(response)) {
6561
+ throw new TypeError(
6562
+ "registry.listen() application fetch must return a Response"
6563
+ );
6564
+ }
6565
+ const conversion = await convertNativeHttpResponse(
6566
+ response,
6567
+ responseBodyStream
6568
+ );
6569
+ if (conversion.bodyCompletion) {
6570
+ void conversion.bodyCompletion.catch((error) => {
6571
+ logger2().error({
6572
+ msg: "application response stream failed",
6573
+ error
6574
+ });
6575
+ });
6576
+ }
6577
+ return {
6578
+ status: conversion.response.status ?? response.status,
6579
+ headers: conversion.response.headers ?? Object.fromEntries(response.headers.entries()),
6580
+ body: conversion.response.body,
6581
+ stream: conversion.response.stream
6582
+ };
6583
+ };
6584
+ }
6321
6585
  var Registry = class {
6322
6586
  #config;
6323
6587
  #buildConfiguredRegistry;
@@ -6333,6 +6597,7 @@ var Registry = class {
6333
6597
  #runtimeReadyPromise;
6334
6598
  #runtimeServeConfiguredPromise;
6335
6599
  #runtimeServerlessPromise;
6600
+ #applicationListenerPromise;
6336
6601
  #configureServerlessPoolPromise;
6337
6602
  #welcomePrinted = false;
6338
6603
  #shutdownInstalled = false;
@@ -6558,18 +6823,67 @@ var Registry = class {
6558
6823
  * @param opts.host Address to bind. Defaults to `0.0.0.0`.
6559
6824
  * @param opts.publicDir If set, serves static files from this directory
6560
6825
  * as a fallback below the framework routes.
6826
+ * @param opts.application If set, handles requests that do not match a
6827
+ * framework route.
6561
6828
  *
6562
6829
  * @example
6563
6830
  * ```ts
6564
6831
  * await registry.listen();
6565
- * await registry.listen({ port: 8080, publicDir: "./public" });
6832
+ * await registry.listen({ application: app });
6566
6833
  * ```
6567
6834
  */
6568
6835
  async listen(opts = {}) {
6569
6836
  const port = opts.port ?? parsePortEnv(process.env.RIVET_PORT) ?? 3e3;
6570
6837
  const publicDir = opts.publicDir ?? getRivetkitPublicDir();
6571
6838
  const config = this.parseConfig();
6572
- const configuredRegistryPromise = buildConfiguredRegistry(config);
6839
+ if (opts.application && getRivetkitRuntimeMode() !== "serverless") {
6840
+ if (config.runtime === "wasm") {
6841
+ throw new Error(
6842
+ "registry.listen() requires the native runtime; use an application-owned HTTP server with WebAssembly"
6843
+ );
6844
+ }
6845
+ this.#installSignalHandlers(config);
6846
+ this.#printWelcome(config, "serverful", {
6847
+ port,
6848
+ host: opts.host,
6849
+ publicDir
6850
+ });
6851
+ this.#startEnvoy(config, true);
6852
+ const readyPromise = this.startAndWait();
6853
+ const configuredRegistryPromise2 = this.#runtimeServeConfiguredPromise;
6854
+ if (!configuredRegistryPromise2) {
6855
+ throw new Error("registry envoy startup did not initialize");
6856
+ }
6857
+ const { runtime: runtime2, registry: registry2, serveConfig: serveConfig2 } = await configuredRegistryPromise2;
6858
+ const application2 = createApplicationFetch(
6859
+ opts.application,
6860
+ runtime2
6861
+ );
6862
+ await readyPromise;
6863
+ const listenerPromise = runtime2.serveApplicationListener(
6864
+ registry2,
6865
+ {
6866
+ port,
6867
+ host: opts.host,
6868
+ publicDir,
6869
+ application: application2
6870
+ },
6871
+ serveConfig2
6872
+ );
6873
+ this.#applicationListenerPromise = listenerPromise;
6874
+ const serveLifecyclePromise = this.#runtimeServeLifecyclePromise;
6875
+ if (!serveLifecyclePromise) {
6876
+ throw new Error(
6877
+ "registry envoy serve lifecycle did not initialize"
6878
+ );
6879
+ }
6880
+ await Promise.all([
6881
+ listenerPromise,
6882
+ serveLifecyclePromise
6883
+ ]);
6884
+ return;
6885
+ }
6886
+ const configuredRegistryPromise = this.#buildConfiguredRegistry(config);
6573
6887
  this.#runtimeServeConfiguredPromise = configuredRegistryPromise;
6574
6888
  this.#runtimeServerlessPromise = configuredRegistryPromise;
6575
6889
  this.#installSignalHandlers(config);
@@ -6580,9 +6894,15 @@ var Registry = class {
6580
6894
  });
6581
6895
  this.#ensureServerlessPoolConfigured(config);
6582
6896
  const { runtime, registry, serveConfig } = await configuredRegistryPromise;
6897
+ const application = opts.application ? createApplicationFetch(opts.application, runtime) : void 0;
6583
6898
  await runtime.serveListener(
6584
6899
  registry,
6585
- { port, host: opts.host, publicDir },
6900
+ {
6901
+ port,
6902
+ host: opts.host,
6903
+ publicDir,
6904
+ application
6905
+ },
6586
6906
  serveConfig
6587
6907
  );
6588
6908
  }
@@ -6682,11 +7002,9 @@ var Registry = class {
6682
7002
  await runtime.serveRegistry(registry, serveConfig);
6683
7003
  }
6684
7004
  );
6685
- this.#runtimeServePromise = this.#runtimeServeLifecyclePromise.catch(
6686
- (error) => {
6687
- logger2().warn({ error }, "runtime registry serve errored");
6688
- }
6689
- );
7005
+ this.#runtimeServePromise = this.#runtimeServeLifecyclePromise.catch((error) => {
7006
+ logger2().warn({ error }, "runtime registry serve errored");
7007
+ });
6690
7008
  this.#installSignalHandlers(config);
6691
7009
  }
6692
7010
  if (printWelcome) {
@@ -6793,6 +7111,9 @@ var Registry = class {
6793
7111
  if (runtimeServePromise !== void 0) {
6794
7112
  await runtimeServePromise.catch(() => void 0);
6795
7113
  }
7114
+ if (this.#applicationListenerPromise !== void 0) {
7115
+ await this.#applicationListenerPromise.catch(() => void 0);
7116
+ }
6796
7117
  };
6797
7118
  await Promise.race([
6798
7119
  drain(),
@@ -6843,7 +7164,9 @@ var Registry = class {
6843
7164
  startAndWait() {
6844
7165
  if (this.#shutdownInFlight !== null) {
6845
7166
  return Promise.reject(
6846
- new Error("registry.startAndWait() cannot run after shutdown has begun")
7167
+ new Error(
7168
+ "registry.startAndWait() cannot run after shutdown has begun"
7169
+ )
6847
7170
  );
6848
7171
  }
6849
7172
  if (this.#runtimeReadyPromise) return this.#runtimeReadyPromise;
@@ -6884,7 +7207,9 @@ var Registry = class {
6884
7207
  const readinessPromise = (async () => {
6885
7208
  const { runtime, registry } = await configuredRegistryPromise;
6886
7209
  const stoppedBeforeReady = serveLifecyclePromise.then(() => {
6887
- throw new Error("RivetKit registry stopped before becoming ready");
7210
+ throw new Error(
7211
+ "RivetKit registry stopped before becoming ready"
7212
+ );
6888
7213
  });
6889
7214
  await Promise.race([
6890
7215
  runtime.waitRegistryReady(registry),