@rivetkit/supabase 2.3.6 → 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 (3) hide show
  1. package/dist/mod.js +420 -79
  2. package/dist/mod.mjs +420 -79
  3. package/package.json +3 -3
package/dist/mod.js CHANGED
@@ -508,7 +508,7 @@ function unsupportedFeature(feature) {
508
508
  );
509
509
  }
510
510
 
511
- // ../rivetkit/dist/tsup/chunk-RDTFPGU2.js
511
+ // ../rivetkit/dist/tsup/chunk-ZKDZW5DQ.js
512
512
  var import_pino = require("pino");
513
513
 
514
514
  // ../../../node_modules/.pnpm/zod@4.1.13/node_modules/zod/v4/classic/external.js
@@ -13181,7 +13181,7 @@ var classic_default = external_exports;
13181
13181
  // ../../../node_modules/.pnpm/zod@4.1.13/node_modules/zod/v4/index.js
13182
13182
  var v4_default = classic_default;
13183
13183
 
13184
- // ../rivetkit/dist/tsup/chunk-RDTFPGU2.js
13184
+ // ../rivetkit/dist/tsup/chunk-ZKDZW5DQ.js
13185
13185
  var cbor = __toESM(require("cbor-x"), 1);
13186
13186
  var import_invariant = __toESM(require_invariant(), 1);
13187
13187
  var getRivetEngine = () => getEnvUniversal("RIVET_ENGINE");
@@ -13346,7 +13346,7 @@ function noopNext() {
13346
13346
  }
13347
13347
  var package_default = {
13348
13348
  name: "rivetkit",
13349
- version: "2.3.6",
13349
+ version: "2.3.8",
13350
13350
  description: "Lightweight libraries for building stateful actors on edge platforms",
13351
13351
  license: "Apache-2.0",
13352
13352
  keywords: [
@@ -14097,7 +14097,10 @@ function jsonStringifyCompat(input, space) {
14097
14097
  return [JSON_COMPAT_BIGINT, value.toString()];
14098
14098
  }
14099
14099
  if (value instanceof ArrayBuffer) {
14100
- return [JSON_COMPAT_ARRAY_BUFFER, base64EncodeArrayBuffer(value)];
14100
+ return [
14101
+ JSON_COMPAT_ARRAY_BUFFER,
14102
+ base64EncodeArrayBuffer(value)
14103
+ ];
14101
14104
  }
14102
14105
  if (value instanceof Uint8Array) {
14103
14106
  return [JSON_COMPAT_UINT8_ARRAY, base64EncodeUint8Array(value)];
@@ -14636,7 +14639,7 @@ function Config({ initialBufferLength = 1024, maxBufferLength = 1024 * 1024 * 32
14636
14639
  };
14637
14640
  }
14638
14641
 
14639
- // ../rivetkit/dist/tsup/chunk-PLLHHJWR.js
14642
+ // ../rivetkit/dist/tsup/chunk-HWBISPRP.js
14640
14643
  var config2 = /* @__PURE__ */ Config({});
14641
14644
  function readWorkflowCbor(bc) {
14642
14645
  return readData(bc);
@@ -15481,7 +15484,7 @@ function removePrefixFromKey(prefixedKey) {
15481
15484
  return prefixedKey.slice(KEYS.KV.length);
15482
15485
  }
15483
15486
 
15484
- // ../rivetkit/dist/tsup/chunk-OH6CBWUD.js
15487
+ // ../rivetkit/dist/tsup/chunk-V7PJYBA5.js
15485
15488
  function logger() {
15486
15489
  return getLogger("actor-client");
15487
15490
  }
@@ -15547,7 +15550,7 @@ var AsyncMutex = class {
15547
15550
  }
15548
15551
  };
15549
15552
 
15550
- // ../rivetkit/dist/tsup/chunk-F6ZW7JZQ.js
15553
+ // ../rivetkit/dist/tsup/chunk-BL6ERZQO.js
15551
15554
  var import_invariant2 = __toESM(require_invariant(), 1);
15552
15555
 
15553
15556
  // ../../../node_modules/.pnpm/p-retry@6.2.1/node_modules/p-retry/index.js
@@ -15725,7 +15728,7 @@ function createVersionedDataHandler(config3) {
15725
15728
  return new VersionedDataHandler(config3);
15726
15729
  }
15727
15730
 
15728
- // ../rivetkit/dist/tsup/chunk-F6ZW7JZQ.js
15731
+ // ../rivetkit/dist/tsup/chunk-BL6ERZQO.js
15729
15732
  var import_invariant3 = __toESM(require_invariant(), 1);
15730
15733
  var import_invariant4 = __toESM(require_invariant(), 1);
15731
15734
  var PATH_CONNECT = "/connect";
@@ -15734,6 +15737,7 @@ var PATH_WEBSOCKET_PREFIX = "/websocket/";
15734
15737
  var HEADER_ACTOR_QUERY = "x-rivet-query";
15735
15738
  var HEADER_ENCODING = "x-rivet-encoding";
15736
15739
  var HEADER_CONN_PARAMS = "x-rivet-conn-params";
15740
+ var HEADER_ORIGINAL_REQUEST_URL = "x-rivet-internal-original-request-url";
15737
15741
  var HEADER_ACTOR_ID = "x-rivet-actor";
15738
15742
  var HEADER_ACTOR_GENERATION = "x-rivet-actor-generation";
15739
15743
  var HEADER_ACTOR_KEY = "x-rivet-actor-key";
@@ -17786,6 +17790,18 @@ async function checkForSchedulingError(group, code, actorId, query, driver) {
17786
17790
  }
17787
17791
  return null;
17788
17792
  }
17793
+ function isUrlLike(value) {
17794
+ return typeof value === "object" && value !== null && typeof value.href === "string" && typeof value.pathname === "string" && typeof value.search === "string";
17795
+ }
17796
+ function isRequestLike(value) {
17797
+ return typeof value === "object" && value !== null && typeof value.url === "string" && typeof value.method === "string" && isHeadersLike(value.headers);
17798
+ }
17799
+ function isResponseLike(value) {
17800
+ return typeof value === "object" && value !== null && typeof value.status === "number" && isHeadersLike(value.headers) && typeof value.arrayBuffer === "function";
17801
+ }
17802
+ function isHeadersLike(value) {
17803
+ return typeof value === "object" && value !== null && typeof value.entries === "function";
17804
+ }
17789
17805
  function* walkErrorChain(error46, maxDepth = 8) {
17790
17806
  let current = error46;
17791
17807
  let depth = 0;
@@ -18211,14 +18227,17 @@ function createQueueSender(senderOptions) {
18211
18227
  }
18212
18228
  async function rawHttpFetch(driver, target, params, input, init, options = {}) {
18213
18229
  let path2;
18230
+ let originalUrl;
18214
18231
  let mergedInit = init || {};
18215
18232
  if (typeof input === "string") {
18216
18233
  path2 = input;
18217
- } else if (input instanceof URL) {
18234
+ } else if (isUrlLike(input)) {
18218
18235
  path2 = input.pathname + input.search;
18219
- } else if (input instanceof Request) {
18236
+ originalUrl = input.toString();
18237
+ } else if (isRequestLike(input)) {
18220
18238
  const url2 = new URL(input.url);
18221
18239
  path2 = url2.pathname + url2.search;
18240
+ originalUrl = url2.toString();
18222
18241
  const requestHeaders = new Headers(input.headers);
18223
18242
  const initHeaders = new Headers((init == null ? void 0 : init.headers) || {});
18224
18243
  const mergedHeaders = new Headers(requestHeaders);
@@ -18260,6 +18279,10 @@ async function rawHttpFetch(driver, target, params, input, init, options = {}) {
18260
18279
  const normalizedPath = path2.startsWith("/") ? path2.slice(1) : path2;
18261
18280
  const url2 = new URL(`http://actor/request/${normalizedPath}`);
18262
18281
  const proxyRequestHeaders = new Headers(mergedInit.headers);
18282
+ proxyRequestHeaders.delete(HEADER_ORIGINAL_REQUEST_URL);
18283
+ if (originalUrl) {
18284
+ proxyRequestHeaders.set(HEADER_ORIGINAL_REQUEST_URL, originalUrl);
18285
+ }
18263
18286
  if (params) {
18264
18287
  proxyRequestHeaders.set(HEADER_CONN_PARAMS, JSON.stringify(params));
18265
18288
  }
@@ -18728,6 +18751,7 @@ var ActorHandleRaw = class {
18728
18751
  async #fetchWithResolvedActor(input, init) {
18729
18752
  const maxAttempts = this.#getDynamicQueryMaxAttempts();
18730
18753
  let useQueryTarget = false;
18754
+ const retryableRequest = isRequestLike(input) ? input.clone() : void 0;
18731
18755
  const { skipReadyWait, ...requestInit } = init ?? {};
18732
18756
  const gatewayOptions = resolveActorGatewayOptions(
18733
18757
  this.#gatewayOptions,
@@ -18747,7 +18771,7 @@ var ActorHandleRaw = class {
18747
18771
  this.#driver,
18748
18772
  target,
18749
18773
  this.#params,
18750
- input,
18774
+ retryableRequest ? retryableRequest.clone() : input,
18751
18775
  requestInit,
18752
18776
  gatewayOptions
18753
18777
  );
@@ -20480,23 +20504,19 @@ async function sendHttpRequestToGateway(runConfig, gatewayUrl, actorRequest, opt
20480
20504
  if (actorRequest.bodyUsed) {
20481
20505
  throw new Error("Request body has already been consumed");
20482
20506
  }
20483
- const reqBody = await actorRequest.arrayBuffer();
20484
- if (reqBody.byteLength !== 0) {
20485
- bodyToSend = reqBody;
20507
+ if (actorRequest.body) {
20508
+ bodyToSend = actorRequest.body;
20486
20509
  guardHeaders.delete("transfer-encoding");
20487
20510
  guardHeaders.delete("content-length");
20488
20511
  }
20489
20512
  }
20490
- const guardRequest = new Request(gatewayUrl, {
20513
+ return fetch(gatewayUrl, {
20491
20514
  method: actorRequest.method,
20492
20515
  headers: guardHeaders,
20493
20516
  body: bodyToSend,
20494
- signal: actorRequest.signal
20517
+ signal: actorRequest.signal,
20518
+ ...bodyToSend ? { duplex: "half" } : {}
20495
20519
  });
20496
- return mutableResponse(await fetch(guardRequest));
20497
- }
20498
- function mutableResponse(fetchRes) {
20499
- return new Response(fetchRes.body, fetchRes);
20500
20520
  }
20501
20521
  function buildGuardHeaders(runConfig, actorRequest, options) {
20502
20522
  const headers = new Headers();
@@ -23971,6 +23991,36 @@ function toNapiSqlBatchStatement(statement) {
23971
23991
  function toNapiBuffer(value) {
23972
23992
  return Buffer.from(value);
23973
23993
  }
23994
+ function toNapiApplication(application) {
23995
+ return async (error46, request) => {
23996
+ if (error46) throw error46;
23997
+ if (!request) {
23998
+ throw new Error("application fetch callback received no request");
23999
+ }
24000
+ const response = await application(
24001
+ {
24002
+ ...request,
24003
+ body: new Uint8Array(request.body),
24004
+ cancelToken: request.cancelToken
24005
+ },
24006
+ request.responseBodyStream ? fromNapiHttpResponseBodyStream(
24007
+ request.responseBodyStream
24008
+ ) : void 0
24009
+ );
24010
+ return {
24011
+ ...response,
24012
+ body: response.body === void 0 ? void 0 : toNapiBuffer(response.body)
24013
+ };
24014
+ };
24015
+ }
24016
+ function fromNapiHttpResponseBodyStream(stream) {
24017
+ return {
24018
+ cancelled: () => stream.cancelled(),
24019
+ write: (chunk) => stream.write(Buffer.from(chunk)),
24020
+ end: () => stream.end(),
24021
+ error: (message) => stream.error(message)
24022
+ };
24023
+ }
23974
24024
  function toNapiHttpRequest(request) {
23975
24025
  if (!request) {
23976
24026
  return request;
@@ -24077,12 +24127,25 @@ var NapiCoreRuntime = class {
24077
24127
  );
24078
24128
  }
24079
24129
  async serveListener(registry2, listener, config3) {
24130
+ const application = listener.application ? toNapiApplication(listener.application) : void 0;
24080
24131
  await asNativeRegistry(registry2).serveListener(
24081
24132
  {
24082
24133
  port: listener.port,
24083
24134
  host: listener.host,
24084
24135
  publicDir: listener.publicDir
24085
24136
  },
24137
+ config3,
24138
+ application
24139
+ );
24140
+ }
24141
+ async serveApplicationListener(registry2, listener, config3) {
24142
+ await asNativeRegistry(registry2).serveApplicationListener(
24143
+ {
24144
+ port: listener.port,
24145
+ host: listener.host,
24146
+ publicDir: listener.publicDir
24147
+ },
24148
+ toNapiApplication(listener.application),
24086
24149
  config3
24087
24150
  );
24088
24151
  }
@@ -24469,6 +24532,135 @@ async function loadNapiRuntime() {
24469
24532
  runtime: new NapiCoreRuntime(bindings)
24470
24533
  };
24471
24534
  }
24535
+ var HTTP_BODY_CHUNK_SIZE = 64 * 1024;
24536
+ function runtimeBytesToArrayBuffer(value) {
24537
+ return value.buffer.slice(
24538
+ value.byteOffset,
24539
+ value.byteOffset + value.byteLength
24540
+ );
24541
+ }
24542
+ function buildNativeHttpRequest(init) {
24543
+ var _a2;
24544
+ const headers = new Headers(init.headers);
24545
+ const originalUrl = headers.get(HEADER_ORIGINAL_REQUEST_URL);
24546
+ headers.delete(HEADER_ORIGINAL_REQUEST_URL);
24547
+ const url2 = originalUrl ?? (init.uri.startsWith("http") ? init.uri : new URL(init.uri, "http://127.0.0.1").toString());
24548
+ const method2 = init.method.toUpperCase();
24549
+ const bodyForbidden = method2 === "GET" || method2 === "HEAD";
24550
+ const body = bodyForbidden ? void 0 : init.bodyStream ? new ReadableStream({
24551
+ async pull(controller) {
24552
+ var _a22, _b;
24553
+ try {
24554
+ if (init.body && init.body.length > 0) {
24555
+ controller.enqueue(new Uint8Array(init.body));
24556
+ init.body = void 0;
24557
+ return;
24558
+ }
24559
+ const chunk = await ((_a22 = init.bodyStream) == null ? void 0 : _a22.read());
24560
+ if (!chunk) {
24561
+ controller.close();
24562
+ } else {
24563
+ controller.enqueue(new Uint8Array(chunk));
24564
+ }
24565
+ } catch (error46) {
24566
+ (_b = init.abortController) == null ? void 0 : _b.abort(error46);
24567
+ controller.error(error46);
24568
+ }
24569
+ },
24570
+ async cancel() {
24571
+ var _a22;
24572
+ await ((_a22 = init.bodyStream) == null ? void 0 : _a22.cancel());
24573
+ }
24574
+ }) : init.body && init.body.length > 0 ? runtimeBytesToArrayBuffer(init.body) : void 0;
24575
+ const streamInit = init.bodyStream && !bodyForbidden ? { duplex: "half" } : {};
24576
+ return new Request(url2, {
24577
+ method: method2,
24578
+ headers,
24579
+ body,
24580
+ signal: ((_a2 = init.abortController) == null ? void 0 : _a2.signal) ?? init.signal,
24581
+ ...streamInit
24582
+ });
24583
+ }
24584
+ async function cancelNativeHttpRequestBody(bodyStream) {
24585
+ await (bodyStream == null ? void 0 : bodyStream.cancel());
24586
+ }
24587
+ async function writeResponseChunk(stream, chunk) {
24588
+ for (let offset = 0; offset < chunk.byteLength; offset += HTTP_BODY_CHUNK_SIZE) {
24589
+ await stream.write(
24590
+ chunk.subarray(offset, offset + HTTP_BODY_CHUNK_SIZE)
24591
+ );
24592
+ }
24593
+ }
24594
+ async function pumpResponseBody(reader, stream) {
24595
+ var _a2;
24596
+ const cancelled = stream.cancelled().then(() => ({ cancelled: true }));
24597
+ try {
24598
+ for (; ; ) {
24599
+ const read = reader.read().then((next2) => ({ cancelled: false, next: next2 }));
24600
+ const result = await Promise.race([read, cancelled]);
24601
+ if (result.cancelled) {
24602
+ await reader.cancel(
24603
+ new Error("native http response stream receiver dropped")
24604
+ );
24605
+ return;
24606
+ }
24607
+ const { next } = result;
24608
+ if (next.done) {
24609
+ await stream.end();
24610
+ return;
24611
+ }
24612
+ if ((_a2 = next.value) == null ? void 0 : _a2.byteLength) {
24613
+ await writeResponseChunk(stream, next.value);
24614
+ }
24615
+ }
24616
+ } catch (error46) {
24617
+ try {
24618
+ await stream.error(stringifyError(error46));
24619
+ } catch (streamError) {
24620
+ logger22().debug({
24621
+ msg: "failed to report native http response stream error",
24622
+ error: streamError
24623
+ });
24624
+ }
24625
+ try {
24626
+ await reader.cancel(error46);
24627
+ } catch {
24628
+ }
24629
+ } finally {
24630
+ reader.releaseLock();
24631
+ }
24632
+ }
24633
+ async function convertNativeHttpResponse(response, responseBodyStream) {
24634
+ const headers = Object.fromEntries(response.headers.entries());
24635
+ if (!response.body) {
24636
+ return {
24637
+ response: {
24638
+ status: response.status,
24639
+ headers,
24640
+ body: new Uint8Array()
24641
+ }
24642
+ };
24643
+ }
24644
+ if (responseBodyStream) {
24645
+ const reader = response.body.getReader();
24646
+ const bodyCompletion = pumpResponseBody(reader, responseBodyStream);
24647
+ return {
24648
+ response: {
24649
+ status: response.status,
24650
+ headers,
24651
+ stream: true
24652
+ },
24653
+ bodyCompletion
24654
+ };
24655
+ }
24656
+ return {
24657
+ response: {
24658
+ status: response.status,
24659
+ headers,
24660
+ body: new Uint8Array(await response.arrayBuffer())
24661
+ }
24662
+ };
24663
+ }
24472
24664
  var CONN_PARAMS_KEY = "__conn_params__";
24473
24665
  function validateActionArgs(schemas, name, args) {
24474
24666
  if (!(schemas == null ? void 0 : schemas[name])) {
@@ -24738,6 +24930,11 @@ var WasmCoreRuntime = class {
24738
24930
  "registry.listen() is not supported on the wasm runtime; use registry.serve() and mount the handler in your platform's HTTP server instead"
24739
24931
  );
24740
24932
  }
24933
+ async serveApplicationListener(_registry, _listener, _config) {
24934
+ throw new Error(
24935
+ "registry.listen() is not supported on the wasm runtime; use an application-owned HTTP server instead"
24936
+ );
24937
+ }
24741
24938
  createActorFactory(callbacks, config3) {
24742
24939
  return callWasmSync(
24743
24940
  () => asActorFactoryHandle2(
@@ -25590,7 +25787,7 @@ function toRuntimeBytes(value) {
25590
25787
  function arrayBufferViewToRuntimeBytes(value) {
25591
25788
  return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
25592
25789
  }
25593
- function runtimeBytesToArrayBuffer(value) {
25790
+ function runtimeBytesToArrayBuffer2(value) {
25594
25791
  return value.buffer.slice(
25595
25792
  value.byteOffset,
25596
25793
  value.byteOffset + value.byteLength
@@ -25920,24 +26117,6 @@ function decodeArgs(value) {
25920
26117
  const decoded = decodeValue(value);
25921
26118
  return normalizeArgs(decoded);
25922
26119
  }
25923
- function buildRequest(init) {
25924
- const url2 = init.uri.startsWith("http") ? init.uri : new URL(init.uri, "http://127.0.0.1").toString();
25925
- const body = init.body && init.body.length > 0 ? runtimeBytesToArrayBuffer(init.body) : void 0;
25926
- return new Request(url2, {
25927
- method: init.method,
25928
- headers: init.headers,
25929
- body
25930
- });
25931
- }
25932
- async function toRuntimeHttpResponse(response) {
25933
- const headers = Object.fromEntries(response.headers.entries());
25934
- const body = new Uint8Array(await response.arrayBuffer());
25935
- return {
25936
- status: response.status,
25937
- headers,
25938
- body
25939
- };
25940
- }
25941
26120
  function toActorKey(segments) {
25942
26121
  return segments.map(
25943
26122
  (segment) => segment.kind === "number" ? String(segment.numberValue ?? 0) : segment.stringValue ?? ""
@@ -26602,7 +26781,7 @@ var NativeWebSocketAdapter = class {
26602
26781
  this.#runtime.webSocketSetEventCallback(this.#ws, (event2) => {
26603
26782
  if (event2.kind === "message") {
26604
26783
  this.#virtual.triggerMessage(
26605
- event2.binary ? runtimeBytesToArrayBuffer(event2.data) : event2.data,
26784
+ event2.binary ? runtimeBytesToArrayBuffer2(event2.data) : event2.data,
26606
26785
  event2.messageIndex
26607
26786
  );
26608
26787
  return;
@@ -27834,12 +28013,14 @@ function buildNativeFactory(runtime, registryConfig, definition) {
27834
28013
  onStateChange,
27835
28014
  cancelToken
27836
28015
  );
27837
- const maybeHandleNativeInspectorRequest = async (ctx, _rawRequest, jsRequest) => {
28016
+ const maybeHandleNativeInspectorRequest = async (ctx, rawRequest) => {
27838
28017
  var _a22, _b, _c, _d;
27839
- const url2 = new URL(jsRequest.url);
28018
+ const rawUrl = rawRequest.uri.startsWith("http") ? rawRequest.uri : new URL(rawRequest.uri, "http://127.0.0.1").toString();
28019
+ const url2 = new URL(rawUrl);
27840
28020
  if (!url2.pathname.startsWith("/inspector/")) {
27841
28021
  return void 0;
27842
28022
  }
28023
+ const jsRequest = buildNativeHttpRequest(rawRequest);
27843
28024
  const jsonResponse = (body, init) => new Response(JSON.stringify(body), {
27844
28025
  status: (init == null ? void 0 : init.status) ?? 200,
27845
28026
  headers: {
@@ -28370,7 +28551,7 @@ function buildNativeFactory(runtime, registryConfig, definition) {
28370
28551
  );
28371
28552
  const actorCtx = makeActorCtx(
28372
28553
  ctx,
28373
- request ? buildRequest(request) : void 0
28554
+ request ? buildNativeHttpRequest(request) : void 0
28374
28555
  );
28375
28556
  try {
28376
28557
  await config3.onBeforeConnect(
@@ -28390,7 +28571,7 @@ function buildNativeFactory(runtime, registryConfig, definition) {
28390
28571
  const { ctx, conn, params, request } = unwrapTsfnPayload(error46, payload);
28391
28572
  const actorCtx = makeActorCtx(
28392
28573
  ctx,
28393
- request ? buildRequest(request) : void 0
28574
+ request ? buildNativeHttpRequest(request) : void 0
28394
28575
  );
28395
28576
  const connAdapter = new NativeConnAdapter(
28396
28577
  runtime,
@@ -28427,7 +28608,7 @@ function buildNativeFactory(runtime, registryConfig, definition) {
28427
28608
  );
28428
28609
  const actorCtx = makeActorCtx(
28429
28610
  ctx,
28430
- request ? buildRequest(request) : void 0
28611
+ request ? buildNativeHttpRequest(request) : void 0
28431
28612
  );
28432
28613
  const connAdapter = new NativeConnAdapter(
28433
28614
  runtime,
@@ -28532,27 +28713,45 @@ function buildNativeFactory(runtime, registryConfig, definition) {
28532
28713
  onRequest: wrapNativeCallback(
28533
28714
  async (error46, payload) => {
28534
28715
  try {
28535
- const { ctx, request, cancelToken } = unwrapTsfnPayload(
28536
- error46,
28537
- payload
28538
- );
28539
- const jsRequest = buildRequest(request);
28540
- const inspectorResponse = await maybeHandleNativeInspectorRequest(
28541
- ctx,
28542
- request,
28543
- jsRequest
28544
- );
28716
+ const { ctx, request, cancelToken, responseBodyStream } = unwrapTsfnPayload(error46, payload);
28717
+ const inspectorResponse = await maybeHandleNativeInspectorRequest(ctx, request);
28545
28718
  if (inspectorResponse) {
28546
- return await toRuntimeHttpResponse(inspectorResponse);
28719
+ await cancelNativeHttpRequestBody(request.bodyStream);
28720
+ return (await convertNativeHttpResponse(
28721
+ inspectorResponse,
28722
+ responseBodyStream
28723
+ )).response;
28547
28724
  }
28548
28725
  if (typeof config3.onRequest !== "function") {
28549
- return await toRuntimeHttpResponse(
28550
- new Response(null, { status: 404 })
28551
- );
28726
+ await cancelNativeHttpRequestBody(request.bodyStream);
28727
+ return (await convertNativeHttpResponse(
28728
+ new Response(null, { status: 404 }),
28729
+ responseBodyStream
28730
+ )).response;
28552
28731
  }
28553
- const rawConnParams = jsRequest.headers.get(HEADER_CONN_PARAMS);
28732
+ const requestAbortController = new AbortController();
28733
+ const handlerRequest = buildNativeHttpRequest({
28734
+ ...request,
28735
+ abortController: requestAbortController
28736
+ });
28737
+ const rawConnParams = handlerRequest.headers.get(HEADER_CONN_PARAMS);
28554
28738
  let requestCtx;
28555
28739
  let conn;
28740
+ let removeRequestAbortListener;
28741
+ let cleanupDeferredToBody = false;
28742
+ let cleanedUp = false;
28743
+ const cleanupRequest = async () => {
28744
+ if (cleanedUp) return;
28745
+ cleanedUp = true;
28746
+ removeRequestAbortListener == null ? void 0 : removeRequestAbortListener();
28747
+ try {
28748
+ await (requestCtx == null ? void 0 : requestCtx.dispose());
28749
+ } finally {
28750
+ if (conn) {
28751
+ await runtime.connDisconnect(conn);
28752
+ }
28753
+ }
28754
+ };
28556
28755
  try {
28557
28756
  const connParams = validateConnParams(
28558
28757
  schemaConfig.connParamsSchema,
@@ -28568,23 +28767,56 @@ function buildNativeFactory(runtime, registryConfig, definition) {
28568
28767
  requestCtx = makeConnCtx(
28569
28768
  ctx,
28570
28769
  conn,
28571
- jsRequest,
28770
+ handlerRequest,
28572
28771
  cancelToken
28573
28772
  );
28773
+ const ctxAbortSignal = requestCtx.abortSignal;
28774
+ const abortRequest = () => requestAbortController.abort(ctxAbortSignal.reason);
28775
+ if (ctxAbortSignal.aborted) {
28776
+ abortRequest();
28777
+ } else {
28778
+ ctxAbortSignal.addEventListener(
28779
+ "abort",
28780
+ abortRequest,
28781
+ { once: true }
28782
+ );
28783
+ removeRequestAbortListener = () => ctxAbortSignal.removeEventListener(
28784
+ "abort",
28785
+ abortRequest
28786
+ );
28787
+ }
28574
28788
  const response = await config3.onRequest(
28575
28789
  requestCtx,
28576
- jsRequest
28790
+ handlerRequest
28577
28791
  );
28578
- if (!(response instanceof Response)) {
28792
+ if (!isResponseLike(response)) {
28579
28793
  throw new Error(
28580
28794
  "onRequest handler must return a Response"
28581
28795
  );
28582
28796
  }
28583
- return await toRuntimeHttpResponse(response);
28797
+ const conversion = await convertNativeHttpResponse(
28798
+ response,
28799
+ responseBodyStream
28800
+ );
28801
+ if (conversion.bodyCompletion) {
28802
+ cleanupDeferredToBody = true;
28803
+ void conversion.bodyCompletion.then(cleanupRequest).catch((cleanupError) => {
28804
+ logger22().error({
28805
+ msg: "failed to clean up native streaming http request",
28806
+ error: cleanupError
28807
+ });
28808
+ });
28809
+ }
28810
+ return conversion.response;
28584
28811
  } finally {
28585
- await (requestCtx == null ? void 0 : requestCtx.dispose());
28586
- if (conn) {
28587
- await runtime.connDisconnect(conn);
28812
+ try {
28813
+ await cancelNativeHttpRequestBody(
28814
+ request.bodyStream
28815
+ );
28816
+ } finally {
28817
+ if (!cleanupDeferredToBody) {
28818
+ await cleanupRequest();
28819
+ }
28588
28820
  }
28589
28821
  }
28590
28822
  } catch (error210) {
@@ -28599,7 +28831,7 @@ function buildNativeFactory(runtime, registryConfig, definition) {
28599
28831
  onWebSocket: typeof config3.onWebSocket === "function" ? wrapNativeCallback(
28600
28832
  async (error46, payload) => {
28601
28833
  const { ctx, conn, ws, request } = unwrapTsfnPayload(error46, payload);
28602
- const jsRequest = request ? buildRequest(request) : void 0;
28834
+ const jsRequest = request ? buildNativeHttpRequest(request) : void 0;
28603
28835
  const actorCtx = makeConnCtx(ctx, conn, jsRequest);
28604
28836
  try {
28605
28837
  await config3.onWebSocket(
@@ -28696,7 +28928,7 @@ function buildNativeFactory(runtime, registryConfig, definition) {
28696
28928
  timeoutMs,
28697
28929
  cancelToken
28698
28930
  } = unwrapTsfnPayload(error46, payload);
28699
- const jsRequest = buildRequest(request);
28931
+ const jsRequest = buildNativeHttpRequest(request);
28700
28932
  const actorCtx = withConnContext(
28701
28933
  runtime,
28702
28934
  ctx,
@@ -28845,6 +29077,54 @@ function finishShutdownSignal(signal) {
28845
29077
  }
28846
29078
  process.kill(process.pid, signal);
28847
29079
  }
29080
+ function createApplicationFetch(application, runtime) {
29081
+ return async (request, responseBodyStream) => {
29082
+ const method2 = request.method.toUpperCase();
29083
+ const body = method2 === "GET" || method2 === "HEAD" || request.body.length === 0 ? void 0 : Uint8Array.from(request.body).buffer;
29084
+ const abortController = new AbortController();
29085
+ if (request.cancelToken) {
29086
+ if (runtime.cancellationTokenAborted(request.cancelToken)) {
29087
+ abortController.abort();
29088
+ } else {
29089
+ runtime.onCancellationTokenCancelled(
29090
+ request.cancelToken,
29091
+ () => abortController.abort()
29092
+ );
29093
+ }
29094
+ }
29095
+ const response = await application.fetch(
29096
+ new Request(request.url, {
29097
+ method: method2,
29098
+ headers: request.headers,
29099
+ body,
29100
+ signal: abortController.signal
29101
+ })
29102
+ );
29103
+ if (!isResponseLike(response)) {
29104
+ throw new TypeError(
29105
+ "registry.listen() application fetch must return a Response"
29106
+ );
29107
+ }
29108
+ const conversion = await convertNativeHttpResponse(
29109
+ response,
29110
+ responseBodyStream
29111
+ );
29112
+ if (conversion.bodyCompletion) {
29113
+ void conversion.bodyCompletion.catch((error46) => {
29114
+ logger22().error({
29115
+ msg: "application response stream failed",
29116
+ error: error46
29117
+ });
29118
+ });
29119
+ }
29120
+ return {
29121
+ status: conversion.response.status ?? response.status,
29122
+ headers: conversion.response.headers ?? Object.fromEntries(response.headers.entries()),
29123
+ body: conversion.response.body,
29124
+ stream: conversion.response.stream
29125
+ };
29126
+ };
29127
+ }
28848
29128
  var Registry = class {
28849
29129
  #config;
28850
29130
  #buildConfiguredRegistry;
@@ -28860,6 +29140,7 @@ var Registry = class {
28860
29140
  #runtimeReadyPromise;
28861
29141
  #runtimeServeConfiguredPromise;
28862
29142
  #runtimeServerlessPromise;
29143
+ #applicationListenerPromise;
28863
29144
  #configureServerlessPoolPromise;
28864
29145
  #welcomePrinted = false;
28865
29146
  #shutdownInstalled = false;
@@ -29085,18 +29366,67 @@ var Registry = class {
29085
29366
  * @param opts.host Address to bind. Defaults to `0.0.0.0`.
29086
29367
  * @param opts.publicDir If set, serves static files from this directory
29087
29368
  * as a fallback below the framework routes.
29369
+ * @param opts.application If set, handles requests that do not match a
29370
+ * framework route.
29088
29371
  *
29089
29372
  * @example
29090
29373
  * ```ts
29091
29374
  * await registry.listen();
29092
- * await registry.listen({ port: 8080, publicDir: "./public" });
29375
+ * await registry.listen({ application: app });
29093
29376
  * ```
29094
29377
  */
29095
29378
  async listen(opts = {}) {
29096
29379
  const port = opts.port ?? parsePortEnv(process.env.RIVET_PORT) ?? 3e3;
29097
29380
  const publicDir = opts.publicDir ?? getRivetkitPublicDir();
29098
29381
  const config3 = this.parseConfig();
29099
- const configuredRegistryPromise = buildConfiguredRegistry(config3);
29382
+ if (opts.application && getRivetkitRuntimeMode() !== "serverless") {
29383
+ if (config3.runtime === "wasm") {
29384
+ throw new Error(
29385
+ "registry.listen() requires the native runtime; use an application-owned HTTP server with WebAssembly"
29386
+ );
29387
+ }
29388
+ this.#installSignalHandlers(config3);
29389
+ this.#printWelcome(config3, "serverful", {
29390
+ port,
29391
+ host: opts.host,
29392
+ publicDir
29393
+ });
29394
+ this.#startEnvoy(config3, true);
29395
+ const readyPromise = this.startAndWait();
29396
+ const configuredRegistryPromise2 = this.#runtimeServeConfiguredPromise;
29397
+ if (!configuredRegistryPromise2) {
29398
+ throw new Error("registry envoy startup did not initialize");
29399
+ }
29400
+ const { runtime: runtime2, registry: registry22, serveConfig: serveConfig2 } = await configuredRegistryPromise2;
29401
+ const application2 = createApplicationFetch(
29402
+ opts.application,
29403
+ runtime2
29404
+ );
29405
+ await readyPromise;
29406
+ const listenerPromise = runtime2.serveApplicationListener(
29407
+ registry22,
29408
+ {
29409
+ port,
29410
+ host: opts.host,
29411
+ publicDir,
29412
+ application: application2
29413
+ },
29414
+ serveConfig2
29415
+ );
29416
+ this.#applicationListenerPromise = listenerPromise;
29417
+ const serveLifecyclePromise = this.#runtimeServeLifecyclePromise;
29418
+ if (!serveLifecyclePromise) {
29419
+ throw new Error(
29420
+ "registry envoy serve lifecycle did not initialize"
29421
+ );
29422
+ }
29423
+ await Promise.all([
29424
+ listenerPromise,
29425
+ serveLifecyclePromise
29426
+ ]);
29427
+ return;
29428
+ }
29429
+ const configuredRegistryPromise = this.#buildConfiguredRegistry(config3);
29100
29430
  this.#runtimeServeConfiguredPromise = configuredRegistryPromise;
29101
29431
  this.#runtimeServerlessPromise = configuredRegistryPromise;
29102
29432
  this.#installSignalHandlers(config3);
@@ -29107,9 +29437,15 @@ var Registry = class {
29107
29437
  });
29108
29438
  this.#ensureServerlessPoolConfigured(config3);
29109
29439
  const { runtime, registry: registry2, serveConfig } = await configuredRegistryPromise;
29440
+ const application = opts.application ? createApplicationFetch(opts.application, runtime) : void 0;
29110
29441
  await runtime.serveListener(
29111
29442
  registry2,
29112
- { port, host: opts.host, publicDir },
29443
+ {
29444
+ port,
29445
+ host: opts.host,
29446
+ publicDir,
29447
+ application
29448
+ },
29113
29449
  serveConfig
29114
29450
  );
29115
29451
  }
@@ -29209,11 +29545,9 @@ var Registry = class {
29209
29545
  await runtime.serveRegistry(registry2, serveConfig);
29210
29546
  }
29211
29547
  );
29212
- this.#runtimeServePromise = this.#runtimeServeLifecyclePromise.catch(
29213
- (error46) => {
29214
- logger22().warn({ error: error46 }, "runtime registry serve errored");
29215
- }
29216
- );
29548
+ this.#runtimeServePromise = this.#runtimeServeLifecyclePromise.catch((error46) => {
29549
+ logger22().warn({ error: error46 }, "runtime registry serve errored");
29550
+ });
29217
29551
  this.#installSignalHandlers(config3);
29218
29552
  }
29219
29553
  if (printWelcome) {
@@ -29320,6 +29654,9 @@ var Registry = class {
29320
29654
  if (runtimeServePromise !== void 0) {
29321
29655
  await runtimeServePromise.catch(() => void 0);
29322
29656
  }
29657
+ if (this.#applicationListenerPromise !== void 0) {
29658
+ await this.#applicationListenerPromise.catch(() => void 0);
29659
+ }
29323
29660
  };
29324
29661
  await Promise.race([
29325
29662
  drain(),
@@ -29370,7 +29707,9 @@ var Registry = class {
29370
29707
  startAndWait() {
29371
29708
  if (this.#shutdownInFlight !== null) {
29372
29709
  return Promise.reject(
29373
- new Error("registry.startAndWait() cannot run after shutdown has begun")
29710
+ new Error(
29711
+ "registry.startAndWait() cannot run after shutdown has begun"
29712
+ )
29374
29713
  );
29375
29714
  }
29376
29715
  if (this.#runtimeReadyPromise) return this.#runtimeReadyPromise;
@@ -29411,7 +29750,9 @@ var Registry = class {
29411
29750
  const readinessPromise = (async () => {
29412
29751
  const { runtime, registry: registry2 } = await configuredRegistryPromise;
29413
29752
  const stoppedBeforeReady = serveLifecyclePromise.then(() => {
29414
- throw new Error("RivetKit registry stopped before becoming ready");
29753
+ throw new Error(
29754
+ "RivetKit registry stopped before becoming ready"
29755
+ );
29415
29756
  });
29416
29757
  await Promise.race([
29417
29758
  runtime.waitRegistryReady(registry2),