Skip to content
This repository was archived by the owner on Oct 22, 2025. It is now read-only.

Commit 7c74870

Browse files
committed
chore(cloudflare-workers): upgrade to new manager api (#1253)
1 parent 10af3aa commit 7c74870

File tree

10 files changed

+109
-62
lines changed

10 files changed

+109
-62
lines changed

examples/cloudflare-workers/scripts/client.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { registry } from "../src/registry";
33

44
// Create RivetKit client
55
const client = createClient<typeof registry>(
6-
process.env.RIVETKIT_ENDPOINT ?? "http://localhost:8787",
6+
process.env.RIVETKIT_ENDPOINT ?? "http://localhost:8787/rivet",
77
);
88

99
async function main() {
@@ -12,8 +12,6 @@ async function main() {
1212
try {
1313
// Create counter instance
1414
const counter = client.counter.getOrCreate("demo");
15-
const conn = counter.connect();
16-
conn.on("foo", (x) => console.log("output", x));
1715

1816
// Increment counter
1917
console.log("Incrementing counter 'demo'...");
@@ -36,6 +34,33 @@ async function main() {
3634
console.error("❌ Error:", error);
3735
process.exit(1);
3836
}
37+
// try {
38+
// // Create counter instance
39+
// const counter = client.counter.getOrCreate("demo");
40+
// const conn = counter.connect();
41+
// conn.on("foo", (x) => console.log("output", x));
42+
//
43+
// // Increment counter
44+
// console.log("Incrementing counter 'demo'...");
45+
// const result1 = await counter.increment(1);
46+
// console.log("New count:", result1);
47+
//
48+
// // Increment again with larger value
49+
// console.log("Incrementing counter 'demo' by 5...");
50+
// const result2 = await counter.increment(5);
51+
// console.log("New count:", result2);
52+
//
53+
// // Create another counter
54+
// const counter2 = client.counter.getOrCreate("another");
55+
// console.log("Incrementing counter 'another' by 10...");
56+
// const result3 = await counter2.increment(10);
57+
// console.log("New count:", result3);
58+
//
59+
// console.log("✅ Demo completed!");
60+
// } catch (error) {
61+
// console.error("❌ Error:", error);
62+
// process.exit(1);
63+
// }
3964
}
4065

4166
main().catch(console.error);
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { createServerHandler } from "@rivetkit/cloudflare-workers";
1+
import { createHandler } from "@rivetkit/cloudflare-workers";
22
import { registry } from "./registry";
33

4-
const { handler, ActorHandler } = createServerHandler(registry);
4+
const { handler, ActorHandler } = createHandler(registry);
55
export { handler as default, ActorHandler };

packages/cloudflare-workers/src/config.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ import { z } from "zod";
55
export const ConfigSchema = RunConfigSchema.removeDefault()
66
.omit({ driver: true, getUpgradeWebSocket: true })
77
.extend({
8-
app: z.custom<Hono>().optional(),
8+
/** Path that the Rivet manager API will be mounted. */
9+
managerPath: z.string().optional().default("/rivet"),
10+
11+
fetch: z.custom<ExportedHandlerFetchHandler<unknown, unknown>>().optional(),
912
})
1013
.default({});
1114
export type InputConfig = z.input<typeof ConfigSchema>;

packages/cloudflare-workers/src/handler.ts

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { env } from "cloudflare:workers";
2-
import { Hono } from "hono";
2+
import type { Hono } from "hono";
33
import type { Registry, RunConfig } from "rivetkit";
44
import type { Client } from "rivetkit/client";
55
import {
@@ -36,7 +36,7 @@ interface SetupOutput<A extends Registry<any>> {
3636
createHandler: (hono?: Hono) => Handler;
3737
}
3838

39-
export function createServerHandler<R extends Registry<any>>(
39+
export function createHandler<R extends Registry<any>>(
4040
registry: R,
4141
inputConfig?: InputConfig,
4242
): Handler {
@@ -66,23 +66,34 @@ export function createServer<R extends Registry<any>>(
6666
const ActorHandler = createActorDurableObject(registry, runConfig);
6767

6868
// Create server
69-
const serverOutput = registry.createServer(runConfig);
69+
const serverOutput = registry.start(runConfig);
7070

7171
return {
7272
client: serverOutput.client as Client<R>,
73-
createHandler: (hono) => {
74-
// Build base router
75-
const app = hono ?? new Hono();
76-
77-
// Mount registry router at /registry
78-
if (!hono) {
79-
app.route("/registry", serverOutput.hono);
80-
}
81-
73+
createHandler: () => {
8274
// Create Cloudflare handler
8375
const handler = {
8476
fetch: (request, env, ctx) => {
85-
return app.fetch(request, env, ctx);
77+
const url = new URL(request.url);
78+
79+
// Mount Rivet manager API
80+
if (url.pathname.startsWith(config.managerPath)) {
81+
const strippedPath = url.pathname.substring(
82+
config.managerPath.length,
83+
);
84+
url.pathname = strippedPath;
85+
const modifiedRequest = new Request(url.toString(), request);
86+
return serverOutput.fetch(modifiedRequest, env, ctx);
87+
}
88+
89+
if (config.fetch) {
90+
return config.fetch(request, env, ctx);
91+
} else {
92+
return new Response(
93+
"This is a RivetKit server.\n\nLearn more at https://rivetkit.org\n",
94+
{ status: 200 },
95+
);
96+
}
8697
},
8798
} satisfies ExportedHandler<Bindings>;
8899

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
export type { DriverContext } from "./actor-driver";
22
export type { InputConfig as Config } from "./config";
3-
export { type Bindings, createServer, createServerHandler } from "./handler";
3+
export { type Bindings, createHandler, createServer } from "./handler";

packages/cloudflare-workers/tests/driver-tests.test.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,15 +141,12 @@ async function setupProject(projectPath: string) {
141141
await fs.mkdir(rivetKitDir, { recursive: true });
142142

143143
// Copy core package
144-
const corePackagePath = path.join(workspaceRoot, "packages/core");
145-
const targetCorePath = path.join(rivetKitDir, "core");
144+
const corePackagePath = path.join(workspaceRoot, "packages/rivetkit");
145+
const targetCorePath = path.join(rivetKitDir, "rivetkit");
146146
await fs.cp(corePackagePath, targetCorePath, { recursive: true });
147147

148148
// Copy cloudflare-workers package
149-
const cfPackagePath = path.join(
150-
workspaceRoot,
151-
"packages/drivers/cloudflare-workers",
152-
);
149+
const cfPackagePath = path.join(workspaceRoot, "packages/cloudflare-workers");
153150
const targetCfPath = path.join(rivetKitDir, "cloudflare-workers");
154151
await fs.cp(cfPackagePath, targetCfPath, { recursive: true });
155152

packages/rivetkit/src/actor/errors.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ export class MessageTooLong extends ActorError {
165165
super(
166166
"message",
167167
"too_long",
168-
"Message too long. This can be configured with: `registry.runServer({ maxIncomingMessageSize: ... })`",
168+
"Message too long. This can be configured with: `registry.start({ maxIncomingMessageSize: ... })`",
169169
{ public: true },
170170
);
171171
}

packages/rivetkit/src/driver-test-suite/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export async function setupDriverTest(
2121
}
2222

2323
// Build drivers
24-
const projectPath = resolve(__dirname, "../../fixtures/driver-test-suite");
24+
const projectPath = resolve(__dirname, "../../../fixtures/driver-test-suite");
2525
const { endpoint, namespace, runnerName, cleanup } =
2626
await driverTestConfig.start(projectPath);
2727
c.onTestFinished(cleanup);

packages/rivetkit/src/registry/mod.ts

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,10 @@ import {
2121
import { crossPlatformServe } from "./serve";
2222

2323
interface ServerOutput<A extends Registry<any>> {
24-
config: RunConfig;
25-
driver: DriverConfig;
24+
/** Client to communicate with the actors. */
2625
client: Client<A>;
27-
hono: Hono;
28-
handler: (req: Request) => Promise<Response>;
29-
serve: (hono?: Hono) => void;
26+
/** Fetch handler to manually route requests to the Rivet manager API. */
27+
fetch: (request: Request, ...args: any) => Response | Promise<Response>;
3028
}
3129

3230
export class Registry<A extends RegistryActors> {
@@ -43,7 +41,7 @@ export class Registry<A extends RegistryActors> {
4341
/**
4442
* Runs the registry for a server.
4543
*/
46-
public createServer(inputConfig?: RunConfigInput): ServerOutput<this> {
44+
public start(inputConfig?: RunConfigInput): ServerOutput<this> {
4745
const config = RunConfigSchema.parse(inputConfig);
4846

4947
// Configure logger
@@ -62,6 +60,13 @@ export class Registry<A extends RegistryActors> {
6260
// TODO: Find cleaner way of disabling by default
6361
if (driver.name === "engine") {
6462
config.inspector.enabled = false;
63+
config.disableServer = true;
64+
}
65+
if (driver.name === "cloudflare-workers") {
66+
config.inspector.enabled = false;
67+
config.disableServer = true;
68+
config.disableActorDriver = true;
69+
config.noWelcome = true;
6570
}
6671

6772
// Configure getUpgradeWebSocket lazily so we can assign it in crossPlatformServe
@@ -109,41 +114,32 @@ export class Registry<A extends RegistryActors> {
109114
console.log();
110115
}
111116

117+
// HACK: We need to find a better way to let the driver itself decide when to start the actor driver
112118
// Create runner
113119
//
114120
// Even though we do not use the return value, this is required to start the code that will handle incoming actors
115-
const _actorDriver = driver.actor(
116-
this.#config,
117-
config,
118-
managerDriver,
119-
client,
120-
);
121+
if (!config.disableActorDriver) {
122+
const _actorDriver = driver.actor(
123+
this.#config,
124+
config,
125+
managerDriver,
126+
client,
127+
);
128+
}
129+
130+
// Start server
131+
if (!config.disableServer) {
132+
(async () => {
133+
const out = await crossPlatformServe(hono, undefined);
134+
upgradeWebSocket = out.upgradeWebSocket;
135+
})();
136+
}
121137

122138
return {
123-
config,
124-
driver,
125139
client,
126-
hono,
127-
handler: async (req: Request) => await hono.fetch(req),
128-
serve: async (app) => {
129-
const out = await crossPlatformServe(hono, app);
130-
upgradeWebSocket = out.upgradeWebSocket;
131-
},
140+
fetch: hono.fetch.bind(hono),
132141
};
133142
}
134-
135-
/**
136-
* Runs the registry as a standalone server.
137-
*/
138-
public async runServer(inputConfig?: RunConfigInput) {
139-
const { driver, serve } = this.createServer(inputConfig);
140-
141-
// TODO: FInd better way of doing this
142-
// Don't run server by default
143-
if (driver.name !== "engine") {
144-
serve();
145-
}
146-
}
147143
}
148144

149145
export function setup<A extends RegistryActors>(

packages/rivetkit/src/registry/run-config.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,31 @@ export const RunConfigSchema = ClientConfigSchema.extend({
2929

3030
inspector: InspectorConfigSchema,
3131

32+
/** @experimental */
33+
disableServer: z.boolean().optional().default(false),
34+
35+
/** @experimental */
36+
disableActorDriver: z.boolean().optional().default(false),
37+
3238
/**
39+
* @experimental
40+
*
3341
* Base path for the router. This is used to prefix all routes.
3442
* For example, if the base path is `/api`, then the route `/actors` will be
3543
* available at `/api/actors`.
3644
*/
3745
basePath: z.string().optional().default("/"),
3846

39-
/** Disable welcome message. */
47+
/**
48+
* @experimental
49+
*
50+
* Disable welcome message.
51+
* */
4052
noWelcome: z.boolean().optional().default(false),
4153

54+
/**
55+
* @experimental
56+
* */
4257
logging: z
4358
.object({
4459
baseLogger: z.custom<Logger>().optional(),

0 commit comments

Comments
 (0)