@rivetkit/next-js 2.0.40 → 2.0.41

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/rivet/rivet/rivetkit-typescript/packages/next-js/dist/client/mod.js","../../src/client/mod.ts"],"names":[],"mappings":"AAAA;ACAA,mEAAc","file":"/home/runner/work/rivet/rivet/rivetkit-typescript/packages/next-js/dist/client/mod.js","sourcesContent":[null,"export * from \"@rivetkit/react\";\n"]}
1
+ {"version":3,"sources":["/Users/nathan/rivet/rivetkit-typescript/packages/next-js/dist/client/mod.js","../../src/client/mod.ts"],"names":[],"mappings":"AAAA;ACAA,mEAAc","file":"/Users/nathan/rivet/rivetkit-typescript/packages/next-js/dist/client/mod.js","sourcesContent":[null,"export * from \"@rivetkit/react\";\n"]}
package/dist/mod.js CHANGED
@@ -1,20 +1,11 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }// src/mod.ts
2
- var _fs = require('fs');
3
- var _path = require('path');
4
- var _utils = require('rivetkit/utils');
5
-
6
- // src/log.ts
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }// src/log.ts
7
2
  var _log = require('rivetkit/log');
8
3
  function logger() {
9
4
  return _log.getLogger.call(void 0, "driver-next-js");
10
5
  }
11
6
 
12
7
  // src/mod.ts
13
- var ROUTE_FILE = _path.join.call(void 0,
14
- process.cwd(),
15
- ".next/server/app/api/rivet/[...all]/route.js"
16
- );
17
- var WATCH_INTERVAL_MS = 500;
8
+ var DEV_RUNNER_VERSION = Math.floor(Date.now() / 1e3);
18
9
  var toNextHandler = (registry) => {
19
10
  registry.config.serveManager = false;
20
11
  registry.config.serverless = {
@@ -35,6 +26,10 @@ var toNextHandler = (registry) => {
35
26
  slotsPerRunner: 1,
36
27
  metadata: { provider: "next-js" }
37
28
  };
29
+ registry.config.runner = {
30
+ ...registry.config.runner,
31
+ version: DEV_RUNNER_VERSION
32
+ };
38
33
  } else {
39
34
  logger().debug(
40
35
  "detected production environment, will not auto-start engine and auto-configure serverless"
@@ -45,13 +40,6 @@ var toNextHandler = (registry) => {
45
40
  const { all } = await params;
46
41
  const targetUrl = new URL(request.url);
47
42
  targetUrl.pathname = `/${all.join("/")}`;
48
- if (process.env.NODE_ENV !== "production") {
49
- return await handleRequestWithFileWatcher(
50
- registry,
51
- request,
52
- targetUrl
53
- );
54
- }
55
43
  return await registry.handler(new Request(targetUrl, request));
56
44
  };
57
45
  return {
@@ -64,121 +52,6 @@ var toNextHandler = (registry) => {
64
52
  OPTIONS: fetchWrapper
65
53
  };
66
54
  };
67
- async function handleRequestWithFileWatcher(registry, request, newUrl) {
68
- const mergedController = new AbortController();
69
- const abortMerged = () => mergedController.abort();
70
- request.signal.addEventListener("abort", abortMerged);
71
- const watchIntervalId = watchRouteFile(mergedController);
72
- const clearWatcher = () => clearInterval(watchIntervalId);
73
- request.signal.addEventListener("abort", () => {
74
- logger().debug("clearing file watcher interval: request aborted");
75
- clearWatcher();
76
- });
77
- const newReq = cloneRequestWithSignal(
78
- newUrl,
79
- request,
80
- mergedController.signal
81
- );
82
- let response;
83
- try {
84
- response = await registry.handler(newReq);
85
- } catch (err) {
86
- logger().warn({
87
- msg: "file watcher handler failed, falling back to direct handler",
88
- err: _utils.stringifyError.call(void 0, err)
89
- });
90
- clearWatcher();
91
- return await registry.handler(new Request(newUrl, request));
92
- }
93
- if (response.body) {
94
- const wrappedStream = waitForStreamFinish(response.body, () => {
95
- logger().debug("clearing file watcher interval: stream finished");
96
- clearWatcher();
97
- });
98
- return new Response(wrappedStream, {
99
- status: response.status,
100
- statusText: response.statusText,
101
- headers: response.headers
102
- });
103
- }
104
- logger().debug("clearing file watcher interval: no response body");
105
- clearWatcher();
106
- return response;
107
- }
108
- function cloneRequestWithSignal(newUrl, request, signal) {
109
- const baseReq = new Request(newUrl, request);
110
- return new Request(baseReq, { signal });
111
- }
112
- function watchRouteFile(abortController) {
113
- logger().debug("starting file watcher");
114
- let lastMtime;
115
- let missingWarningShown = false;
116
- const checkFile = () => {
117
- logger().debug({
118
- msg: "checking for file changes",
119
- routePath: ROUTE_FILE
120
- });
121
- try {
122
- if (!_fs.existsSync.call(void 0, ROUTE_FILE)) {
123
- if (!missingWarningShown) {
124
- logger().warn({
125
- msg: "route file missing, hot reloading disabled until it recompiles",
126
- routePath: ROUTE_FILE
127
- });
128
- missingWarningShown = true;
129
- }
130
- lastMtime = void 0;
131
- return;
132
- }
133
- missingWarningShown = false;
134
- const stats = _fs.statSync.call(void 0, ROUTE_FILE);
135
- const mtime = stats.mtimeMs;
136
- if (lastMtime !== void 0 && mtime !== lastMtime) {
137
- logger().info({
138
- msg: "route file changed",
139
- routePath: ROUTE_FILE
140
- });
141
- abortController.abort();
142
- }
143
- lastMtime = mtime;
144
- } catch (err) {
145
- logger().info({
146
- msg: "failed to check for route file change",
147
- err: _utils.stringifyError.call(void 0, err)
148
- });
149
- }
150
- };
151
- checkFile();
152
- return setInterval(checkFile, WATCH_INTERVAL_MS);
153
- }
154
- function waitForStreamFinish(body, onFinish) {
155
- const reader = body.getReader();
156
- return new ReadableStream({
157
- async start(controller) {
158
- try {
159
- while (true) {
160
- const { done, value } = await reader.read();
161
- if (done) {
162
- logger().debug("stream completed");
163
- onFinish();
164
- controller.close();
165
- break;
166
- }
167
- controller.enqueue(value);
168
- }
169
- } catch (err) {
170
- logger().debug("stream errored");
171
- onFinish();
172
- controller.error(err);
173
- }
174
- },
175
- cancel() {
176
- logger().debug("stream cancelled");
177
- onFinish();
178
- reader.cancel();
179
- }
180
- });
181
- }
182
55
 
183
56
 
184
57
  exports.toNextHandler = toNextHandler;
package/dist/mod.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/rivet/rivet/rivetkit-typescript/packages/next-js/dist/mod.js","../src/mod.ts","../src/log.ts"],"names":[],"mappings":"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","file":"/home/runner/work/rivet/rivet/rivetkit-typescript/packages/next-js/dist/mod.js","sourcesContent":[null,"import { existsSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Registry } from \"rivetkit\";\nimport { stringifyError } from \"rivetkit/utils\";\nimport { logger } from \"./log\";\n\nconst ROUTE_FILE = join(\n\tprocess.cwd(),\n\t\".next/server/app/api/rivet/[...all]/route.js\",\n);\nconst WATCH_INTERVAL_MS = 500;\n\nexport const toNextHandler = (registry: Registry<any>) => {\n\t// Don't run server locally since we're using the fetch handler directly\n\tregistry.config.serveManager = false;\n\n\t// Set basePath to \"/\" since Next.js route strips the /api/rivet prefix\n\tregistry.config.serverless = {\n\t\t...registry.config.serverless,\n\t\tbasePath: \"/\",\n\t};\n\n\tif (process.env.NODE_ENV !== \"production\") {\n\t\tlogger().debug(\n\t\t\t\"detected development environment, auto-starting engine and auto-configuring serverless\",\n\t\t);\n\n\t\tconst publicUrl =\n\t\t\tprocess.env.NEXT_PUBLIC_SITE_URL ??\n\t\t\tprocess.env.NEXT_PUBLIC_VERCEL_URL ??\n\t\t\t`http://127.0.0.1:${process.env.PORT ?? 3000}`;\n\n\t\t// Set these on the registry's config directly since the legacy inputConfig\n\t\t// isn't used by the serverless router\n\t\tregistry.config.serverless.spawnEngine = true;\n\t\tregistry.config.serverless.configureRunnerPool = {\n\t\t\turl: `${publicUrl}/api/rivet`,\n\t\t\tminRunners: 0,\n\t\t\tmaxRunners: 100_000,\n\t\t\trequestLifespan: 300,\n\t\t\tslotsPerRunner: 1,\n\t\t\tmetadata: { provider: \"next-js\" },\n\t\t};\n\t} else {\n\t\tlogger().debug(\n\t\t\t\"detected production environment, will not auto-start engine and auto-configure serverless\",\n\t\t);\n\t}\n\n\t// Next logs this on every request\n\tregistry.config.noWelcome = true;\n\n\tconst fetchWrapper = async (\n\t\trequest: Request,\n\t\t{ params }: { params: Promise<{ all: string[] }> },\n\t): Promise<Response> => {\n\t\tconst { all } = await params;\n\t\tconst targetUrl = new URL(request.url);\n\t\ttargetUrl.pathname = `/${all.join(\"/\")}`;\n\n\t\tif (process.env.NODE_ENV !== \"production\") {\n\t\t\treturn await handleRequestWithFileWatcher(\n\t\t\t\tregistry,\n\t\t\t\trequest,\n\t\t\t\ttargetUrl,\n\t\t\t);\n\t\t}\n\n\t\treturn await registry.handler(new Request(targetUrl, request));\n\t};\n\n\treturn {\n\t\tGET: fetchWrapper,\n\t\tPOST: fetchWrapper,\n\t\tPUT: fetchWrapper,\n\t\tDELETE: fetchWrapper,\n\t\tPATCH: fetchWrapper,\n\t\tHEAD: fetchWrapper,\n\t\tOPTIONS: fetchWrapper,\n\t};\n};\n\n/**\n * Special request handler that will watch the source file to terminate this\n * request once complete.\n *\n * See docs on watchRouteFile for more information.\n */\nasync function handleRequestWithFileWatcher(\n\tregistry: Registry<any>,\n\trequest: Request,\n\tnewUrl: URL,\n): Promise<Response> {\n\t// Create a new abort controller that we can abort since we cannot control the\n\t// signal on the Request passed in by Next.js\n\tconst mergedController = new AbortController();\n\tconst abortMerged = () => mergedController.abort();\n\trequest.signal.addEventListener(\"abort\", abortMerged);\n\n\tconst watchIntervalId = watchRouteFile(mergedController);\n\tconst clearWatcher = () => clearInterval(watchIntervalId);\n\n\t// Clear interval if request is aborted\n\trequest.signal.addEventListener(\"abort\", () => {\n\t\tlogger().debug(\"clearing file watcher interval: request aborted\");\n\t\tclearWatcher();\n\t});\n\n\tconst newReq = cloneRequestWithSignal(\n\t\tnewUrl,\n\t\trequest,\n\t\tmergedController.signal,\n\t);\n\n\tlet response: Response;\n\ttry {\n\t\t// Handle request with merged abort signal\n\t\tresponse = await registry.handler(newReq);\n\t} catch (err) {\n\t\tlogger().warn({\n\t\t\tmsg: \"file watcher handler failed, falling back to direct handler\",\n\t\t\terr: stringifyError(err),\n\t\t});\n\t\tclearWatcher();\n\t\treturn await registry.handler(new Request(newUrl, request));\n\t}\n\n\t// HACK: Next.js does not provide a way to detect when a request finishes, so\n\t// we need to tap the response stream.\n\tif (response.body) {\n\t\tconst wrappedStream = waitForStreamFinish(response.body, () => {\n\t\t\tlogger().debug(\"clearing file watcher interval: stream finished\");\n\t\t\tclearWatcher();\n\t\t});\n\t\treturn new Response(wrappedStream, {\n\t\t\tstatus: response.status,\n\t\t\tstatusText: response.statusText,\n\t\t\theaders: response.headers,\n\t\t});\n\t}\n\n\tlogger().debug(\"clearing file watcher interval: no response body\");\n\tclearWatcher();\n\treturn response;\n}\n\nfunction cloneRequestWithSignal(\n\tnewUrl: URL,\n\trequest: Request,\n\tsignal: AbortSignal,\n): Request {\n\tconst baseReq = new Request(newUrl, request);\n\treturn new Request(baseReq, { signal });\n}\n\n/**\n * HACK: Watch for file changes on this route in order to shut down the runner.\n * We do this because Next.js does not terminate long-running requests on file\n * change, so we need to manually shut down the runner in order to trigger a\n * new `/start` request with the new code.\n *\n * We don't use file watchers since those are frequently buggy x-platform and\n * subject to misconfigured inotify limits.\n */\nfunction watchRouteFile(abortController: AbortController): NodeJS.Timeout {\n\tlogger().debug(\"starting file watcher\");\n\n\tlet lastMtime: number | undefined;\n\tlet missingWarningShown = false;\n\n\tconst checkFile = () => {\n\t\tlogger().debug({\n\t\t\tmsg: \"checking for file changes\",\n\t\t\troutePath: ROUTE_FILE,\n\t\t});\n\n\t\ttry {\n\t\t\tif (!existsSync(ROUTE_FILE)) {\n\t\t\t\tif (!missingWarningShown) {\n\t\t\t\t\tlogger().warn({\n\t\t\t\t\t\tmsg: \"route file missing, hot reloading disabled until it recompiles\",\n\t\t\t\t\t\troutePath: ROUTE_FILE,\n\t\t\t\t\t});\n\t\t\t\t\tmissingWarningShown = true;\n\t\t\t\t}\n\t\t\t\tlastMtime = undefined;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tmissingWarningShown = false;\n\n\t\t\tconst stats = statSync(ROUTE_FILE);\n\t\t\tconst mtime = stats.mtimeMs;\n\n\t\t\tif (lastMtime !== undefined && mtime !== lastMtime) {\n\t\t\t\tlogger().info({\n\t\t\t\t\tmsg: \"route file changed\",\n\t\t\t\t\troutePath: ROUTE_FILE,\n\t\t\t\t});\n\t\t\t\tabortController.abort();\n\t\t\t}\n\n\t\t\tlastMtime = mtime;\n\t\t} catch (err) {\n\t\t\tlogger().info({\n\t\t\t\tmsg: \"failed to check for route file change\",\n\t\t\t\terr: stringifyError(err),\n\t\t\t});\n\t\t}\n\t};\n\n\tcheckFile();\n\n\treturn setInterval(checkFile, WATCH_INTERVAL_MS);\n}\n\n/**\n * Waits for a stream to finish and calls onFinish on complete.\n *\n * Used for cancelling the file watcher.\n */\nfunction waitForStreamFinish(\n\tbody: ReadableStream<Uint8Array>,\n\tonFinish: () => void,\n): ReadableStream {\n\tconst reader = body.getReader();\n\treturn new ReadableStream({\n\t\tasync start(controller) {\n\t\t\ttry {\n\t\t\t\twhile (true) {\n\t\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\t\tif (done) {\n\t\t\t\t\t\tlogger().debug(\"stream completed\");\n\t\t\t\t\t\tonFinish();\n\t\t\t\t\t\tcontroller.close();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcontroller.enqueue(value);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tlogger().debug(\"stream errored\");\n\t\t\t\tonFinish();\n\t\t\t\tcontroller.error(err);\n\t\t\t}\n\t\t},\n\t\tcancel() {\n\t\t\tlogger().debug(\"stream cancelled\");\n\t\t\tonFinish();\n\t\t\treader.cancel();\n\t\t},\n\t});\n}\n","import { getLogger } from \"rivetkit/log\";\n\nexport function logger() {\n\treturn getLogger(\"driver-next-js\");\n}\n"]}
1
+ {"version":3,"sources":["/Users/nathan/rivet/rivetkit-typescript/packages/next-js/dist/mod.js","../src/log.ts","../src/mod.ts"],"names":[],"mappings":"AAAA;ACAA,mCAA0B;AAEnB,SAAS,MAAA,CAAA,EAAS;AACxB,EAAA,OAAO,4BAAA,gBAA0B,CAAA;AAClC;ADCA;AACA;AEIA,IAAM,mBAAA,EAAqB,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,GAAI,CAAA;AAEhD,IAAM,cAAA,EAAgB,CAAC,QAAA,EAAA,GAA4B;AAEzD,EAAA,QAAA,CAAS,MAAA,CAAO,aAAA,EAAe,KAAA;AAG/B,EAAA,QAAA,CAAS,MAAA,CAAO,WAAA,EAAa;AAAA,IAC5B,GAAG,QAAA,CAAS,MAAA,CAAO,UAAA;AAAA,IACnB,QAAA,EAAU;AAAA,EACX,CAAA;AAEA,EAAA,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,SAAA,IAAa,YAAA,EAAc;AAC1C,IAAA,MAAA,CAAO,CAAA,CAAE,KAAA;AAAA,MACR;AAAA,IACD,CAAA;AAEA,IAAA,MAAM,UAAA,oCACL,OAAA,CAAQ,GAAA,CAAI,oBAAA,UACZ,OAAA,CAAQ,GAAA,CAAI,wBAAA,UACZ,CAAA,iBAAA,mBAAoB,OAAA,CAAQ,GAAA,CAAI,IAAA,UAAQ,KAAI,CAAA,GAAA;AAIJ,IAAA;AACQ,IAAA;AAC/B,MAAA;AACL,MAAA;AACA,MAAA;AACK,MAAA;AACD,MAAA;AACgB,MAAA;AACjC,IAAA;AAGyB,IAAA;AACL,MAAA;AACV,MAAA;AACV,IAAA;AACM,EAAA;AACG,IAAA;AACR,MAAA;AACD,IAAA;AACD,EAAA;AAG4B,EAAA;AAKJ,EAAA;AACD,IAAA;AACe,IAAA;AACC,IAAA;AAEuB,IAAA;AAC9D,EAAA;AAEO,EAAA;AACD,IAAA;AACC,IAAA;AACD,IAAA;AACG,IAAA;AACD,IAAA;AACD,IAAA;AACG,IAAA;AACV,EAAA;AACD;AFxB4I;AACA;AACA","file":"/Users/nathan/rivet/rivetkit-typescript/packages/next-js/dist/mod.js","sourcesContent":[null,"import { getLogger } from \"rivetkit/log\";\n\nexport function logger() {\n\treturn getLogger(\"driver-next-js\");\n}\n","import type { Registry } from \"rivetkit\";\nimport { logger } from \"./log\";\n\n// Runner version set to seconds since epoch when the module loads in development mode.\n//\n// This creates a version number that increments each time the code is updated\n// and the module reloads, allowing the engine to detect code changes via the\n// /metadata endpoint and hot-reload all actors by draining older runners.\n//\n// We use seconds (not milliseconds) because the runner version is a u32 on the engine side.\nconst DEV_RUNNER_VERSION = Math.floor(Date.now() / 1000);\n\nexport const toNextHandler = (registry: Registry<any>) => {\n\t// Don't run server locally since we're using the fetch handler directly\n\tregistry.config.serveManager = false;\n\n\t// Set basePath to \"/\" since Next.js route strips the /api/rivet prefix\n\tregistry.config.serverless = {\n\t\t...registry.config.serverless,\n\t\tbasePath: \"/\",\n\t};\n\n\tif (process.env.NODE_ENV !== \"production\") {\n\t\tlogger().debug(\n\t\t\t\"detected development environment, auto-starting engine and auto-configuring serverless\",\n\t\t);\n\n\t\tconst publicUrl =\n\t\t\tprocess.env.NEXT_PUBLIC_SITE_URL ??\n\t\t\tprocess.env.NEXT_PUBLIC_VERCEL_URL ??\n\t\t\t`http://127.0.0.1:${process.env.PORT ?? 3000}`;\n\n\t\t// Set these on the registry's config directly since the legacy inputConfig\n\t\t// isn't used by the serverless router\n\t\tregistry.config.serverless.spawnEngine = true;\n\t\tregistry.config.serverless.configureRunnerPool = {\n\t\t\turl: `${publicUrl}/api/rivet`,\n\t\t\tminRunners: 0,\n\t\t\tmaxRunners: 100_000,\n\t\t\trequestLifespan: 300,\n\t\t\tslotsPerRunner: 1,\n\t\t\tmetadata: { provider: \"next-js\" },\n\t\t};\n\n\t\t// Set runner version to enable hot-reloading on code changes\n\t\tregistry.config.runner = {\n\t\t\t...registry.config.runner,\n\t\t\tversion: DEV_RUNNER_VERSION,\n\t\t};\n\t} else {\n\t\tlogger().debug(\n\t\t\t\"detected production environment, will not auto-start engine and auto-configure serverless\",\n\t\t);\n\t}\n\n\t// Next logs this on every request\n\tregistry.config.noWelcome = true;\n\n\tconst fetchWrapper = async (\n\t\trequest: Request,\n\t\t{ params }: { params: Promise<{ all: string[] }> },\n\t): Promise<Response> => {\n\t\tconst { all } = await params;\n\t\tconst targetUrl = new URL(request.url);\n\t\ttargetUrl.pathname = `/${all.join(\"/\")}`;\n\n\t\treturn await registry.handler(new Request(targetUrl, request));\n\t};\n\n\treturn {\n\t\tGET: fetchWrapper,\n\t\tPOST: fetchWrapper,\n\t\tPUT: fetchWrapper,\n\t\tDELETE: fetchWrapper,\n\t\tPATCH: fetchWrapper,\n\t\tHEAD: fetchWrapper,\n\t\tOPTIONS: fetchWrapper,\n\t};\n};\n"]}
package/dist/mod.mjs CHANGED
@@ -1,8 +1,3 @@
1
- // src/mod.ts
2
- import { existsSync, statSync } from "fs";
3
- import { join } from "path";
4
- import { stringifyError } from "rivetkit/utils";
5
-
6
1
  // src/log.ts
7
2
  import { getLogger } from "rivetkit/log";
8
3
  function logger() {
@@ -10,11 +5,7 @@ function logger() {
10
5
  }
11
6
 
12
7
  // src/mod.ts
13
- var ROUTE_FILE = join(
14
- process.cwd(),
15
- ".next/server/app/api/rivet/[...all]/route.js"
16
- );
17
- var WATCH_INTERVAL_MS = 500;
8
+ var DEV_RUNNER_VERSION = Math.floor(Date.now() / 1e3);
18
9
  var toNextHandler = (registry) => {
19
10
  registry.config.serveManager = false;
20
11
  registry.config.serverless = {
@@ -35,6 +26,10 @@ var toNextHandler = (registry) => {
35
26
  slotsPerRunner: 1,
36
27
  metadata: { provider: "next-js" }
37
28
  };
29
+ registry.config.runner = {
30
+ ...registry.config.runner,
31
+ version: DEV_RUNNER_VERSION
32
+ };
38
33
  } else {
39
34
  logger().debug(
40
35
  "detected production environment, will not auto-start engine and auto-configure serverless"
@@ -45,13 +40,6 @@ var toNextHandler = (registry) => {
45
40
  const { all } = await params;
46
41
  const targetUrl = new URL(request.url);
47
42
  targetUrl.pathname = `/${all.join("/")}`;
48
- if (process.env.NODE_ENV !== "production") {
49
- return await handleRequestWithFileWatcher(
50
- registry,
51
- request,
52
- targetUrl
53
- );
54
- }
55
43
  return await registry.handler(new Request(targetUrl, request));
56
44
  };
57
45
  return {
@@ -64,121 +52,6 @@ var toNextHandler = (registry) => {
64
52
  OPTIONS: fetchWrapper
65
53
  };
66
54
  };
67
- async function handleRequestWithFileWatcher(registry, request, newUrl) {
68
- const mergedController = new AbortController();
69
- const abortMerged = () => mergedController.abort();
70
- request.signal.addEventListener("abort", abortMerged);
71
- const watchIntervalId = watchRouteFile(mergedController);
72
- const clearWatcher = () => clearInterval(watchIntervalId);
73
- request.signal.addEventListener("abort", () => {
74
- logger().debug("clearing file watcher interval: request aborted");
75
- clearWatcher();
76
- });
77
- const newReq = cloneRequestWithSignal(
78
- newUrl,
79
- request,
80
- mergedController.signal
81
- );
82
- let response;
83
- try {
84
- response = await registry.handler(newReq);
85
- } catch (err) {
86
- logger().warn({
87
- msg: "file watcher handler failed, falling back to direct handler",
88
- err: stringifyError(err)
89
- });
90
- clearWatcher();
91
- return await registry.handler(new Request(newUrl, request));
92
- }
93
- if (response.body) {
94
- const wrappedStream = waitForStreamFinish(response.body, () => {
95
- logger().debug("clearing file watcher interval: stream finished");
96
- clearWatcher();
97
- });
98
- return new Response(wrappedStream, {
99
- status: response.status,
100
- statusText: response.statusText,
101
- headers: response.headers
102
- });
103
- }
104
- logger().debug("clearing file watcher interval: no response body");
105
- clearWatcher();
106
- return response;
107
- }
108
- function cloneRequestWithSignal(newUrl, request, signal) {
109
- const baseReq = new Request(newUrl, request);
110
- return new Request(baseReq, { signal });
111
- }
112
- function watchRouteFile(abortController) {
113
- logger().debug("starting file watcher");
114
- let lastMtime;
115
- let missingWarningShown = false;
116
- const checkFile = () => {
117
- logger().debug({
118
- msg: "checking for file changes",
119
- routePath: ROUTE_FILE
120
- });
121
- try {
122
- if (!existsSync(ROUTE_FILE)) {
123
- if (!missingWarningShown) {
124
- logger().warn({
125
- msg: "route file missing, hot reloading disabled until it recompiles",
126
- routePath: ROUTE_FILE
127
- });
128
- missingWarningShown = true;
129
- }
130
- lastMtime = void 0;
131
- return;
132
- }
133
- missingWarningShown = false;
134
- const stats = statSync(ROUTE_FILE);
135
- const mtime = stats.mtimeMs;
136
- if (lastMtime !== void 0 && mtime !== lastMtime) {
137
- logger().info({
138
- msg: "route file changed",
139
- routePath: ROUTE_FILE
140
- });
141
- abortController.abort();
142
- }
143
- lastMtime = mtime;
144
- } catch (err) {
145
- logger().info({
146
- msg: "failed to check for route file change",
147
- err: stringifyError(err)
148
- });
149
- }
150
- };
151
- checkFile();
152
- return setInterval(checkFile, WATCH_INTERVAL_MS);
153
- }
154
- function waitForStreamFinish(body, onFinish) {
155
- const reader = body.getReader();
156
- return new ReadableStream({
157
- async start(controller) {
158
- try {
159
- while (true) {
160
- const { done, value } = await reader.read();
161
- if (done) {
162
- logger().debug("stream completed");
163
- onFinish();
164
- controller.close();
165
- break;
166
- }
167
- controller.enqueue(value);
168
- }
169
- } catch (err) {
170
- logger().debug("stream errored");
171
- onFinish();
172
- controller.error(err);
173
- }
174
- },
175
- cancel() {
176
- logger().debug("stream cancelled");
177
- onFinish();
178
- reader.cancel();
179
- }
180
- });
181
- }
182
55
  export {
183
56
  toNextHandler
184
57
  };
package/dist/mod.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/mod.ts","../src/log.ts"],"sourcesContent":["import { existsSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Registry } from \"rivetkit\";\nimport { stringifyError } from \"rivetkit/utils\";\nimport { logger } from \"./log\";\n\nconst ROUTE_FILE = join(\n\tprocess.cwd(),\n\t\".next/server/app/api/rivet/[...all]/route.js\",\n);\nconst WATCH_INTERVAL_MS = 500;\n\nexport const toNextHandler = (registry: Registry<any>) => {\n\t// Don't run server locally since we're using the fetch handler directly\n\tregistry.config.serveManager = false;\n\n\t// Set basePath to \"/\" since Next.js route strips the /api/rivet prefix\n\tregistry.config.serverless = {\n\t\t...registry.config.serverless,\n\t\tbasePath: \"/\",\n\t};\n\n\tif (process.env.NODE_ENV !== \"production\") {\n\t\tlogger().debug(\n\t\t\t\"detected development environment, auto-starting engine and auto-configuring serverless\",\n\t\t);\n\n\t\tconst publicUrl =\n\t\t\tprocess.env.NEXT_PUBLIC_SITE_URL ??\n\t\t\tprocess.env.NEXT_PUBLIC_VERCEL_URL ??\n\t\t\t`http://127.0.0.1:${process.env.PORT ?? 3000}`;\n\n\t\t// Set these on the registry's config directly since the legacy inputConfig\n\t\t// isn't used by the serverless router\n\t\tregistry.config.serverless.spawnEngine = true;\n\t\tregistry.config.serverless.configureRunnerPool = {\n\t\t\turl: `${publicUrl}/api/rivet`,\n\t\t\tminRunners: 0,\n\t\t\tmaxRunners: 100_000,\n\t\t\trequestLifespan: 300,\n\t\t\tslotsPerRunner: 1,\n\t\t\tmetadata: { provider: \"next-js\" },\n\t\t};\n\t} else {\n\t\tlogger().debug(\n\t\t\t\"detected production environment, will not auto-start engine and auto-configure serverless\",\n\t\t);\n\t}\n\n\t// Next logs this on every request\n\tregistry.config.noWelcome = true;\n\n\tconst fetchWrapper = async (\n\t\trequest: Request,\n\t\t{ params }: { params: Promise<{ all: string[] }> },\n\t): Promise<Response> => {\n\t\tconst { all } = await params;\n\t\tconst targetUrl = new URL(request.url);\n\t\ttargetUrl.pathname = `/${all.join(\"/\")}`;\n\n\t\tif (process.env.NODE_ENV !== \"production\") {\n\t\t\treturn await handleRequestWithFileWatcher(\n\t\t\t\tregistry,\n\t\t\t\trequest,\n\t\t\t\ttargetUrl,\n\t\t\t);\n\t\t}\n\n\t\treturn await registry.handler(new Request(targetUrl, request));\n\t};\n\n\treturn {\n\t\tGET: fetchWrapper,\n\t\tPOST: fetchWrapper,\n\t\tPUT: fetchWrapper,\n\t\tDELETE: fetchWrapper,\n\t\tPATCH: fetchWrapper,\n\t\tHEAD: fetchWrapper,\n\t\tOPTIONS: fetchWrapper,\n\t};\n};\n\n/**\n * Special request handler that will watch the source file to terminate this\n * request once complete.\n *\n * See docs on watchRouteFile for more information.\n */\nasync function handleRequestWithFileWatcher(\n\tregistry: Registry<any>,\n\trequest: Request,\n\tnewUrl: URL,\n): Promise<Response> {\n\t// Create a new abort controller that we can abort since we cannot control the\n\t// signal on the Request passed in by Next.js\n\tconst mergedController = new AbortController();\n\tconst abortMerged = () => mergedController.abort();\n\trequest.signal.addEventListener(\"abort\", abortMerged);\n\n\tconst watchIntervalId = watchRouteFile(mergedController);\n\tconst clearWatcher = () => clearInterval(watchIntervalId);\n\n\t// Clear interval if request is aborted\n\trequest.signal.addEventListener(\"abort\", () => {\n\t\tlogger().debug(\"clearing file watcher interval: request aborted\");\n\t\tclearWatcher();\n\t});\n\n\tconst newReq = cloneRequestWithSignal(\n\t\tnewUrl,\n\t\trequest,\n\t\tmergedController.signal,\n\t);\n\n\tlet response: Response;\n\ttry {\n\t\t// Handle request with merged abort signal\n\t\tresponse = await registry.handler(newReq);\n\t} catch (err) {\n\t\tlogger().warn({\n\t\t\tmsg: \"file watcher handler failed, falling back to direct handler\",\n\t\t\terr: stringifyError(err),\n\t\t});\n\t\tclearWatcher();\n\t\treturn await registry.handler(new Request(newUrl, request));\n\t}\n\n\t// HACK: Next.js does not provide a way to detect when a request finishes, so\n\t// we need to tap the response stream.\n\tif (response.body) {\n\t\tconst wrappedStream = waitForStreamFinish(response.body, () => {\n\t\t\tlogger().debug(\"clearing file watcher interval: stream finished\");\n\t\t\tclearWatcher();\n\t\t});\n\t\treturn new Response(wrappedStream, {\n\t\t\tstatus: response.status,\n\t\t\tstatusText: response.statusText,\n\t\t\theaders: response.headers,\n\t\t});\n\t}\n\n\tlogger().debug(\"clearing file watcher interval: no response body\");\n\tclearWatcher();\n\treturn response;\n}\n\nfunction cloneRequestWithSignal(\n\tnewUrl: URL,\n\trequest: Request,\n\tsignal: AbortSignal,\n): Request {\n\tconst baseReq = new Request(newUrl, request);\n\treturn new Request(baseReq, { signal });\n}\n\n/**\n * HACK: Watch for file changes on this route in order to shut down the runner.\n * We do this because Next.js does not terminate long-running requests on file\n * change, so we need to manually shut down the runner in order to trigger a\n * new `/start` request with the new code.\n *\n * We don't use file watchers since those are frequently buggy x-platform and\n * subject to misconfigured inotify limits.\n */\nfunction watchRouteFile(abortController: AbortController): NodeJS.Timeout {\n\tlogger().debug(\"starting file watcher\");\n\n\tlet lastMtime: number | undefined;\n\tlet missingWarningShown = false;\n\n\tconst checkFile = () => {\n\t\tlogger().debug({\n\t\t\tmsg: \"checking for file changes\",\n\t\t\troutePath: ROUTE_FILE,\n\t\t});\n\n\t\ttry {\n\t\t\tif (!existsSync(ROUTE_FILE)) {\n\t\t\t\tif (!missingWarningShown) {\n\t\t\t\t\tlogger().warn({\n\t\t\t\t\t\tmsg: \"route file missing, hot reloading disabled until it recompiles\",\n\t\t\t\t\t\troutePath: ROUTE_FILE,\n\t\t\t\t\t});\n\t\t\t\t\tmissingWarningShown = true;\n\t\t\t\t}\n\t\t\t\tlastMtime = undefined;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tmissingWarningShown = false;\n\n\t\t\tconst stats = statSync(ROUTE_FILE);\n\t\t\tconst mtime = stats.mtimeMs;\n\n\t\t\tif (lastMtime !== undefined && mtime !== lastMtime) {\n\t\t\t\tlogger().info({\n\t\t\t\t\tmsg: \"route file changed\",\n\t\t\t\t\troutePath: ROUTE_FILE,\n\t\t\t\t});\n\t\t\t\tabortController.abort();\n\t\t\t}\n\n\t\t\tlastMtime = mtime;\n\t\t} catch (err) {\n\t\t\tlogger().info({\n\t\t\t\tmsg: \"failed to check for route file change\",\n\t\t\t\terr: stringifyError(err),\n\t\t\t});\n\t\t}\n\t};\n\n\tcheckFile();\n\n\treturn setInterval(checkFile, WATCH_INTERVAL_MS);\n}\n\n/**\n * Waits for a stream to finish and calls onFinish on complete.\n *\n * Used for cancelling the file watcher.\n */\nfunction waitForStreamFinish(\n\tbody: ReadableStream<Uint8Array>,\n\tonFinish: () => void,\n): ReadableStream {\n\tconst reader = body.getReader();\n\treturn new ReadableStream({\n\t\tasync start(controller) {\n\t\t\ttry {\n\t\t\t\twhile (true) {\n\t\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\t\tif (done) {\n\t\t\t\t\t\tlogger().debug(\"stream completed\");\n\t\t\t\t\t\tonFinish();\n\t\t\t\t\t\tcontroller.close();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcontroller.enqueue(value);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tlogger().debug(\"stream errored\");\n\t\t\t\tonFinish();\n\t\t\t\tcontroller.error(err);\n\t\t\t}\n\t\t},\n\t\tcancel() {\n\t\t\tlogger().debug(\"stream cancelled\");\n\t\t\tonFinish();\n\t\t\treader.cancel();\n\t\t},\n\t});\n}\n","import { getLogger } from \"rivetkit/log\";\n\nexport function logger() {\n\treturn getLogger(\"driver-next-js\");\n}\n"],"mappings":";AAAA,SAAS,YAAY,gBAAgB;AACrC,SAAS,YAAY;AAErB,SAAS,sBAAsB;;;ACH/B,SAAS,iBAAiB;AAEnB,SAAS,SAAS;AACxB,SAAO,UAAU,gBAAgB;AAClC;;;ADEA,IAAM,aAAa;AAAA,EAClB,QAAQ,IAAI;AAAA,EACZ;AACD;AACA,IAAM,oBAAoB;AAEnB,IAAM,gBAAgB,CAAC,aAA4B;AAEzD,WAAS,OAAO,eAAe;AAG/B,WAAS,OAAO,aAAa;AAAA,IAC5B,GAAG,SAAS,OAAO;AAAA,IACnB,UAAU;AAAA,EACX;AAEA,MAAI,QAAQ,IAAI,aAAa,cAAc;AAC1C,WAAO,EAAE;AAAA,MACR;AAAA,IACD;AAEA,UAAM,YACL,QAAQ,IAAI,wBACZ,QAAQ,IAAI,0BACZ,oBAAoB,QAAQ,IAAI,QAAQ,GAAI;AAI7C,aAAS,OAAO,WAAW,cAAc;AACzC,aAAS,OAAO,WAAW,sBAAsB;AAAA,MAChD,KAAK,GAAG,SAAS;AAAA,MACjB,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,UAAU,EAAE,UAAU,UAAU;AAAA,IACjC;AAAA,EACD,OAAO;AACN,WAAO,EAAE;AAAA,MACR;AAAA,IACD;AAAA,EACD;AAGA,WAAS,OAAO,YAAY;AAE5B,QAAM,eAAe,OACpB,SACA,EAAE,OAAO,MACc;AACvB,UAAM,EAAE,IAAI,IAAI,MAAM;AACtB,UAAM,YAAY,IAAI,IAAI,QAAQ,GAAG;AACrC,cAAU,WAAW,IAAI,IAAI,KAAK,GAAG,CAAC;AAEtC,QAAI,QAAQ,IAAI,aAAa,cAAc;AAC1C,aAAO,MAAM;AAAA,QACZ;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAEA,WAAO,MAAM,SAAS,QAAQ,IAAI,QAAQ,WAAW,OAAO,CAAC;AAAA,EAC9D;AAEA,SAAO;AAAA,IACN,KAAK;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,MAAM;AAAA,IACN,SAAS;AAAA,EACV;AACD;AAQA,eAAe,6BACd,UACA,SACA,QACoB;AAGpB,QAAM,mBAAmB,IAAI,gBAAgB;AAC7C,QAAM,cAAc,MAAM,iBAAiB,MAAM;AACjD,UAAQ,OAAO,iBAAiB,SAAS,WAAW;AAEpD,QAAM,kBAAkB,eAAe,gBAAgB;AACvD,QAAM,eAAe,MAAM,cAAc,eAAe;AAGxD,UAAQ,OAAO,iBAAiB,SAAS,MAAM;AAC9C,WAAO,EAAE,MAAM,iDAAiD;AAChE,iBAAa;AAAA,EACd,CAAC;AAED,QAAM,SAAS;AAAA,IACd;AAAA,IACA;AAAA,IACA,iBAAiB;AAAA,EAClB;AAEA,MAAI;AACJ,MAAI;AAEH,eAAW,MAAM,SAAS,QAAQ,MAAM;AAAA,EACzC,SAAS,KAAK;AACb,WAAO,EAAE,KAAK;AAAA,MACb,KAAK;AAAA,MACL,KAAK,eAAe,GAAG;AAAA,IACxB,CAAC;AACD,iBAAa;AACb,WAAO,MAAM,SAAS,QAAQ,IAAI,QAAQ,QAAQ,OAAO,CAAC;AAAA,EAC3D;AAIA,MAAI,SAAS,MAAM;AAClB,UAAM,gBAAgB,oBAAoB,SAAS,MAAM,MAAM;AAC9D,aAAO,EAAE,MAAM,iDAAiD;AAChE,mBAAa;AAAA,IACd,CAAC;AACD,WAAO,IAAI,SAAS,eAAe;AAAA,MAClC,QAAQ,SAAS;AAAA,MACjB,YAAY,SAAS;AAAA,MACrB,SAAS,SAAS;AAAA,IACnB,CAAC;AAAA,EACF;AAEA,SAAO,EAAE,MAAM,kDAAkD;AACjE,eAAa;AACb,SAAO;AACR;AAEA,SAAS,uBACR,QACA,SACA,QACU;AACV,QAAM,UAAU,IAAI,QAAQ,QAAQ,OAAO;AAC3C,SAAO,IAAI,QAAQ,SAAS,EAAE,OAAO,CAAC;AACvC;AAWA,SAAS,eAAe,iBAAkD;AACzE,SAAO,EAAE,MAAM,uBAAuB;AAEtC,MAAI;AACJ,MAAI,sBAAsB;AAE1B,QAAM,YAAY,MAAM;AACvB,WAAO,EAAE,MAAM;AAAA,MACd,KAAK;AAAA,MACL,WAAW;AAAA,IACZ,CAAC;AAED,QAAI;AACH,UAAI,CAAC,WAAW,UAAU,GAAG;AAC5B,YAAI,CAAC,qBAAqB;AACzB,iBAAO,EAAE,KAAK;AAAA,YACb,KAAK;AAAA,YACL,WAAW;AAAA,UACZ,CAAC;AACD,gCAAsB;AAAA,QACvB;AACA,oBAAY;AACZ;AAAA,MACD;AAEA,4BAAsB;AAEtB,YAAM,QAAQ,SAAS,UAAU;AACjC,YAAM,QAAQ,MAAM;AAEpB,UAAI,cAAc,UAAa,UAAU,WAAW;AACnD,eAAO,EAAE,KAAK;AAAA,UACb,KAAK;AAAA,UACL,WAAW;AAAA,QACZ,CAAC;AACD,wBAAgB,MAAM;AAAA,MACvB;AAEA,kBAAY;AAAA,IACb,SAAS,KAAK;AACb,aAAO,EAAE,KAAK;AAAA,QACb,KAAK;AAAA,QACL,KAAK,eAAe,GAAG;AAAA,MACxB,CAAC;AAAA,IACF;AAAA,EACD;AAEA,YAAU;AAEV,SAAO,YAAY,WAAW,iBAAiB;AAChD;AAOA,SAAS,oBACR,MACA,UACiB;AACjB,QAAM,SAAS,KAAK,UAAU;AAC9B,SAAO,IAAI,eAAe;AAAA,IACzB,MAAM,MAAM,YAAY;AACvB,UAAI;AACH,eAAO,MAAM;AACZ,gBAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,cAAI,MAAM;AACT,mBAAO,EAAE,MAAM,kBAAkB;AACjC,qBAAS;AACT,uBAAW,MAAM;AACjB;AAAA,UACD;AACA,qBAAW,QAAQ,KAAK;AAAA,QACzB;AAAA,MACD,SAAS,KAAK;AACb,eAAO,EAAE,MAAM,gBAAgB;AAC/B,iBAAS;AACT,mBAAW,MAAM,GAAG;AAAA,MACrB;AAAA,IACD;AAAA,IACA,SAAS;AACR,aAAO,EAAE,MAAM,kBAAkB;AACjC,eAAS;AACT,aAAO,OAAO;AAAA,IACf;AAAA,EACD,CAAC;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/log.ts","../src/mod.ts"],"sourcesContent":["import { getLogger } from \"rivetkit/log\";\n\nexport function logger() {\n\treturn getLogger(\"driver-next-js\");\n}\n","import type { Registry } from \"rivetkit\";\nimport { logger } from \"./log\";\n\n// Runner version set to seconds since epoch when the module loads in development mode.\n//\n// This creates a version number that increments each time the code is updated\n// and the module reloads, allowing the engine to detect code changes via the\n// /metadata endpoint and hot-reload all actors by draining older runners.\n//\n// We use seconds (not milliseconds) because the runner version is a u32 on the engine side.\nconst DEV_RUNNER_VERSION = Math.floor(Date.now() / 1000);\n\nexport const toNextHandler = (registry: Registry<any>) => {\n\t// Don't run server locally since we're using the fetch handler directly\n\tregistry.config.serveManager = false;\n\n\t// Set basePath to \"/\" since Next.js route strips the /api/rivet prefix\n\tregistry.config.serverless = {\n\t\t...registry.config.serverless,\n\t\tbasePath: \"/\",\n\t};\n\n\tif (process.env.NODE_ENV !== \"production\") {\n\t\tlogger().debug(\n\t\t\t\"detected development environment, auto-starting engine and auto-configuring serverless\",\n\t\t);\n\n\t\tconst publicUrl =\n\t\t\tprocess.env.NEXT_PUBLIC_SITE_URL ??\n\t\t\tprocess.env.NEXT_PUBLIC_VERCEL_URL ??\n\t\t\t`http://127.0.0.1:${process.env.PORT ?? 3000}`;\n\n\t\t// Set these on the registry's config directly since the legacy inputConfig\n\t\t// isn't used by the serverless router\n\t\tregistry.config.serverless.spawnEngine = true;\n\t\tregistry.config.serverless.configureRunnerPool = {\n\t\t\turl: `${publicUrl}/api/rivet`,\n\t\t\tminRunners: 0,\n\t\t\tmaxRunners: 100_000,\n\t\t\trequestLifespan: 300,\n\t\t\tslotsPerRunner: 1,\n\t\t\tmetadata: { provider: \"next-js\" },\n\t\t};\n\n\t\t// Set runner version to enable hot-reloading on code changes\n\t\tregistry.config.runner = {\n\t\t\t...registry.config.runner,\n\t\t\tversion: DEV_RUNNER_VERSION,\n\t\t};\n\t} else {\n\t\tlogger().debug(\n\t\t\t\"detected production environment, will not auto-start engine and auto-configure serverless\",\n\t\t);\n\t}\n\n\t// Next logs this on every request\n\tregistry.config.noWelcome = true;\n\n\tconst fetchWrapper = async (\n\t\trequest: Request,\n\t\t{ params }: { params: Promise<{ all: string[] }> },\n\t): Promise<Response> => {\n\t\tconst { all } = await params;\n\t\tconst targetUrl = new URL(request.url);\n\t\ttargetUrl.pathname = `/${all.join(\"/\")}`;\n\n\t\treturn await registry.handler(new Request(targetUrl, request));\n\t};\n\n\treturn {\n\t\tGET: fetchWrapper,\n\t\tPOST: fetchWrapper,\n\t\tPUT: fetchWrapper,\n\t\tDELETE: fetchWrapper,\n\t\tPATCH: fetchWrapper,\n\t\tHEAD: fetchWrapper,\n\t\tOPTIONS: fetchWrapper,\n\t};\n};\n"],"mappings":";AAAA,SAAS,iBAAiB;AAEnB,SAAS,SAAS;AACxB,SAAO,UAAU,gBAAgB;AAClC;;;ACMA,IAAM,qBAAqB,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAEhD,IAAM,gBAAgB,CAAC,aAA4B;AAEzD,WAAS,OAAO,eAAe;AAG/B,WAAS,OAAO,aAAa;AAAA,IAC5B,GAAG,SAAS,OAAO;AAAA,IACnB,UAAU;AAAA,EACX;AAEA,MAAI,QAAQ,IAAI,aAAa,cAAc;AAC1C,WAAO,EAAE;AAAA,MACR;AAAA,IACD;AAEA,UAAM,YACL,QAAQ,IAAI,wBACZ,QAAQ,IAAI,0BACZ,oBAAoB,QAAQ,IAAI,QAAQ,GAAI;AAI7C,aAAS,OAAO,WAAW,cAAc;AACzC,aAAS,OAAO,WAAW,sBAAsB;AAAA,MAChD,KAAK,GAAG,SAAS;AAAA,MACjB,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,UAAU,EAAE,UAAU,UAAU;AAAA,IACjC;AAGA,aAAS,OAAO,SAAS;AAAA,MACxB,GAAG,SAAS,OAAO;AAAA,MACnB,SAAS;AAAA,IACV;AAAA,EACD,OAAO;AACN,WAAO,EAAE;AAAA,MACR;AAAA,IACD;AAAA,EACD;AAGA,WAAS,OAAO,YAAY;AAE5B,QAAM,eAAe,OACpB,SACA,EAAE,OAAO,MACc;AACvB,UAAM,EAAE,IAAI,IAAI,MAAM;AACtB,UAAM,YAAY,IAAI,IAAI,QAAQ,GAAG;AACrC,cAAU,WAAW,IAAI,IAAI,KAAK,GAAG,CAAC;AAEtC,WAAO,MAAM,SAAS,QAAQ,IAAI,QAAQ,WAAW,OAAO,CAAC;AAAA,EAC9D;AAEA,SAAO;AAAA,IACN,KAAK;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,MAAM;AAAA,IACN,SAAS;AAAA,EACV;AACD;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rivetkit/next-js",
3
- "version": "2.0.40",
3
+ "version": "2.0.41",
4
4
  "description": "Next.js integration for RivetKit actors and client",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -49,8 +49,8 @@
49
49
  },
50
50
  "dependencies": {
51
51
  "hono": "^4.8.3",
52
- "@rivetkit/react": "2.0.40",
53
- "rivetkit": "^2.0.40"
52
+ "@rivetkit/react": "2.0.41",
53
+ "rivetkit": "^2.0.41"
54
54
  },
55
55
  "peerDependencies": {
56
56
  "react": "^18 || ^19",