@rivetkit/cloudflare-workers 0.9.8 → 0.9.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mod.cjs CHANGED
@@ -1,10 +1,9 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } var _class;// src/handler.ts
2
- var _async_hooks = require('async_hooks');
2
+ var _cloudflareworkers = require('cloudflare:workers');
3
3
  var _hono = require('hono');
4
- var _invariant = require('invariant'); var _invariant2 = _interopRequireDefault(_invariant);
5
4
 
6
5
  // src/actor-handler-do.ts
7
- var _cloudflareworkers = require('cloudflare:workers');
6
+
8
7
 
9
8
 
10
9
 
@@ -18,7 +17,7 @@ var _driverhelpers = require('@rivetkit/core/driver-helpers');
18
17
 
19
18
 
20
19
 
21
-
20
+ var _invariant = require('invariant'); var _invariant2 = _interopRequireDefault(_invariant);
22
21
  var CloudflareDurableObjectGlobalState = class {
23
22
  // Single map for all actor state
24
23
  #dos = /* @__PURE__ */ new Map();
@@ -103,7 +102,7 @@ var CloudflareActorsActorDriver = class {
103
102
  }
104
103
  getContext(actorId) {
105
104
  const state = this.#globalState.getDOState(actorId);
106
- return { ctx: state.ctx, env: state.env };
105
+ return { state: state.ctx };
107
106
  }
108
107
  async readPersistedData(actorId) {
109
108
  return await this.#getDOCtx(actorId).storage.get(KEYS.PERSIST_DATA);
@@ -178,7 +177,7 @@ function createActorDurableObject(registry, runConfig) {
178
177
  }
179
178
  if (!this.#initialized) throw new Error("Not initialized");
180
179
  const actorId = this.ctx.id.toString();
181
- globalState.setDOState(actorId, { ctx: this.ctx, env: this.env });
180
+ globalState.setDOState(actorId, { ctx: this.ctx, env: _cloudflareworkers.env });
182
181
  runConfig.driver.actor = createCloudflareActorsActorDriverBuilder(globalState);
183
182
  const managerDriver = runConfig.driver.manager(
184
183
  registry.config,
@@ -202,49 +201,43 @@ function createActorDurableObject(registry, runConfig) {
202
201
  }
203
202
  /** RPC called by the service that creates the DO to initialize it. */
204
203
  async initialize(req) {
205
- return await CF_AMBIENT_ENV.run(this.env, async () => {
206
- await this.ctx.storage.put({
207
- [KEYS.NAME]: req.name,
208
- [KEYS.KEY]: req.key,
209
- [KEYS.PERSIST_DATA]: _driverhelpers.serializeEmptyPersistData.call(void 0, req.input)
210
- });
211
- this.#initialized = {
212
- name: req.name,
213
- key: req.key
214
- };
215
- logger().debug("initialized actor", { key: req.key });
216
- await this.#loadActor();
204
+ await this.ctx.storage.put({
205
+ [KEYS.NAME]: req.name,
206
+ [KEYS.KEY]: req.key,
207
+ [KEYS.PERSIST_DATA]: _driverhelpers.serializeEmptyPersistData.call(void 0, req.input)
217
208
  });
209
+ this.#initialized = {
210
+ name: req.name,
211
+ key: req.key
212
+ };
213
+ logger().debug("initialized actor", { key: req.key });
214
+ await this.#loadActor();
218
215
  }
219
216
  async fetch(request) {
220
- return await CF_AMBIENT_ENV.run(this.env, async () => {
221
- const { actorRouter } = await this.#loadActor();
222
- const actorId = this.ctx.id.toString();
223
- return await actorRouter.fetch(request, {
224
- actorId
225
- });
217
+ const { actorRouter } = await this.#loadActor();
218
+ const actorId = this.ctx.id.toString();
219
+ return await actorRouter.fetch(request, {
220
+ actorId
226
221
  });
227
222
  }
228
223
  async alarm() {
229
- return await CF_AMBIENT_ENV.run(this.env, async () => {
230
- await this.#loadActor();
231
- const actorId = this.ctx.id.toString();
232
- const managerDriver = runConfig.driver.manager(
233
- registry.config,
234
- runConfig
235
- );
236
- const inlineClient = _core.createClientWithDriver.call(void 0,
237
- _core.createInlineClientDriver.call(void 0, managerDriver)
238
- );
239
- const actorDriver = runConfig.driver.actor(
240
- registry.config,
241
- runConfig,
242
- managerDriver,
243
- inlineClient
244
- );
245
- const actor = await actorDriver.loadActor(actorId);
246
- await actor.onAlarm();
247
- });
224
+ await this.#loadActor();
225
+ const actorId = this.ctx.id.toString();
226
+ const managerDriver = runConfig.driver.manager(
227
+ registry.config,
228
+ runConfig
229
+ );
230
+ const inlineClient = _core.createClientWithDriver.call(void 0,
231
+ _core.createInlineClientDriver.call(void 0, managerDriver)
232
+ );
233
+ const actorDriver = runConfig.driver.actor(
234
+ registry.config,
235
+ runConfig,
236
+ managerDriver,
237
+ inlineClient
238
+ );
239
+ const actor = await actorDriver.loadActor(actorId);
240
+ await actor.onAlarm();
248
241
  }
249
242
  };
250
243
  }
@@ -312,21 +305,21 @@ var STANDARD_WEBSOCKET_HEADERS = [
312
305
  ];
313
306
  var CloudflareActorsManagerDriver = class {
314
307
  async sendRequest(actorId, actorRequest) {
315
- const env = getCloudflareAmbientEnv();
308
+ const env3 = getCloudflareAmbientEnv();
316
309
  logger().debug("sending request to durable object", {
317
310
  actorId,
318
311
  method: actorRequest.method,
319
312
  url: actorRequest.url
320
313
  });
321
- const id = env.ACTOR_DO.idFromString(actorId);
322
- const stub = env.ACTOR_DO.get(id);
314
+ const id = env3.ACTOR_DO.idFromString(actorId);
315
+ const stub = env3.ACTOR_DO.get(id);
323
316
  return await stub.fetch(actorRequest);
324
317
  }
325
318
  async openWebSocket(path, actorId, encoding, params) {
326
- const env = getCloudflareAmbientEnv();
319
+ const env3 = getCloudflareAmbientEnv();
327
320
  logger().debug("opening websocket to durable object", { actorId, path });
328
- const id = env.ACTOR_DO.idFromString(actorId);
329
- const stub = env.ACTOR_DO.get(id);
321
+ const id = env3.ACTOR_DO.idFromString(actorId);
322
+ const stub = env3.ACTOR_DO.get(id);
330
323
  const headers = {
331
324
  Upgrade: "websocket",
332
325
  Connection: "Upgrade",
@@ -413,8 +406,8 @@ var CloudflareActorsManagerDriver = class {
413
406
  c,
414
407
  actorId
415
408
  }) {
416
- const env = getCloudflareAmbientEnv();
417
- const actorData = await env.ACTOR_KV.get(KEYS2.ACTOR.metadata(actorId), {
409
+ const env3 = getCloudflareAmbientEnv();
410
+ const actorData = await env3.ACTOR_KV.get(KEYS2.ACTOR.metadata(actorId), {
418
411
  type: "json"
419
412
  });
420
413
  if (!actorData) {
@@ -431,11 +424,11 @@ var CloudflareActorsManagerDriver = class {
431
424
  name,
432
425
  key
433
426
  }) {
434
- const env = getCloudflareAmbientEnv();
427
+ const env3 = getCloudflareAmbientEnv();
435
428
  logger().debug("getWithKey: searching for actor", { name, key });
436
429
  const nameKeyString = serializeNameAndKey(name, key);
437
- const actorId = env.ACTOR_DO.idFromName(nameKeyString).toString();
438
- const actorData = await env.ACTOR_KV.get(KEYS2.ACTOR.metadata(actorId), {
430
+ const actorId = env3.ACTOR_DO.idFromName(nameKeyString).toString();
431
+ const actorData = await env3.ACTOR_KV.get(KEYS2.ACTOR.metadata(actorId), {
439
432
  type: "json"
440
433
  });
441
434
  if (!actorData) {
@@ -467,26 +460,26 @@ var CloudflareActorsManagerDriver = class {
467
460
  key,
468
461
  input
469
462
  }) {
470
- const env = getCloudflareAmbientEnv();
463
+ const env3 = getCloudflareAmbientEnv();
471
464
  const existingActor = await this.getWithKey({ c, name, key });
472
465
  if (existingActor) {
473
466
  throw new (0, _errors.ActorAlreadyExists)(name, key);
474
467
  }
475
468
  const nameKeyString = serializeNameAndKey(name, key);
476
- const doId = env.ACTOR_DO.idFromName(nameKeyString);
469
+ const doId = env3.ACTOR_DO.idFromName(nameKeyString);
477
470
  const actorId = doId.toString();
478
- const actor = env.ACTOR_DO.get(doId);
471
+ const actor = env3.ACTOR_DO.get(doId);
479
472
  await actor.initialize({
480
473
  name,
481
474
  key,
482
475
  input
483
476
  });
484
477
  const actorData = { name, key };
485
- await env.ACTOR_KV.put(
478
+ await env3.ACTOR_KV.put(
486
479
  KEYS2.ACTOR.metadata(actorId),
487
480
  JSON.stringify(actorData)
488
481
  );
489
- await env.ACTOR_KV.put(KEYS2.ACTOR.keyIndex(name, key), actorId);
482
+ await env3.ACTOR_KV.put(KEYS2.ACTOR.keyIndex(name, key), actorId);
490
483
  return {
491
484
  actorId,
492
485
  name,
@@ -495,8 +488,8 @@ var CloudflareActorsManagerDriver = class {
495
488
  }
496
489
  // Helper method to build actor output from an ID
497
490
  async #buildActorOutput(c, actorId) {
498
- const env = getCloudflareAmbientEnv();
499
- const actorData = await env.ACTOR_KV.get(KEYS2.ACTOR.metadata(actorId), {
491
+ const env3 = getCloudflareAmbientEnv();
492
+ const actorData = await env3.ACTOR_KV.get(KEYS2.ACTOR.metadata(actorId), {
500
493
  type: "json"
501
494
  });
502
495
  if (!actorData) {
@@ -575,11 +568,8 @@ var upgradeWebSocket = _ws.defineWebSocketHelper.call(void 0, async (c, events)
575
568
  });
576
569
 
577
570
  // src/handler.ts
578
- var CF_AMBIENT_ENV = new (0, _async_hooks.AsyncLocalStorage)();
579
571
  function getCloudflareAmbientEnv() {
580
- const env = CF_AMBIENT_ENV.getStore();
581
- _invariant2.default.call(void 0, env, "missing CF_AMBIENT_ENV");
582
- return env;
572
+ return _cloudflareworkers.env;
583
573
  }
584
574
  function createServerHandler(registry, inputConfig) {
585
575
  const { createHandler } = createServer(registry, inputConfig);
@@ -607,8 +597,8 @@ function createServer(registry, inputConfig) {
607
597
  app.route("/registry", serverOutput.hono);
608
598
  }
609
599
  const handler = {
610
- fetch: (request, env, ctx) => {
611
- return CF_AMBIENT_ENV.run(env, () => app.fetch(request, env, ctx));
600
+ fetch: (request, env3, ctx) => {
601
+ return app.fetch(request, env3, ctx);
612
602
  }
613
603
  };
614
604
  return { handler, ActorHandler: ActorHandler2 };
package/dist/mod.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/nathan/rivetkit/packages/drivers/cloudflare-workers/dist/mod.cjs","../src/handler.ts","../src/actor-handler-do.ts","../src/actor-driver.ts","../src/log.ts","../src/config.ts","../src/manager-driver.ts","../src/util.ts","../src/websocket.ts"],"names":["_a","invariant","ActorHandler"],"mappings":"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","file":"/home/nathan/rivetkit/packages/drivers/cloudflare-workers/dist/mod.cjs","sourcesContent":[null,"import { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { Registry, RunConfig } from \"@rivetkit/core\";\nimport type { Client } from \"@rivetkit/core/client\";\nimport { Hono } from \"hono\";\nimport invariant from \"invariant\";\nimport {\n\ttype ActorHandlerInterface,\n\tcreateActorDurableObject,\n\ttype DurableObjectConstructor,\n} from \"./actor-handler-do\";\nimport { ConfigSchema, type InputConfig } from \"./config\";\nimport { CloudflareActorsManagerDriver } from \"./manager-driver\";\nimport { upgradeWebSocket } from \"./websocket\";\n\n/** Cloudflare Workers env */\nexport interface Bindings {\n\tACTOR_KV: KVNamespace;\n\tACTOR_DO: DurableObjectNamespace<ActorHandlerInterface>;\n}\n\n/**\n * Stores the env for the current request. Required since some contexts like the inline client driver does not have access to the Hono context.\n *\n * Use getCloudflareAmbientEnv unless using CF_AMBIENT_ENV.run.\n */\nexport const CF_AMBIENT_ENV = new AsyncLocalStorage<Bindings>();\n\nexport function getCloudflareAmbientEnv(): Bindings {\n\tconst env = CF_AMBIENT_ENV.getStore();\n\tinvariant(env, \"missing CF_AMBIENT_ENV\");\n\treturn env;\n}\n\ninterface Handler {\n\thandler: ExportedHandler<Bindings>;\n\tActorHandler: DurableObjectConstructor;\n}\n\ninterface SetupOutput<A extends Registry<any>> {\n\tclient: Client<A>;\n\tcreateHandler: (hono?: Hono) => Handler;\n}\n\nexport function createServerHandler<R extends Registry<any>>(\n\tregistry: R,\n\tinputConfig?: InputConfig,\n): Handler {\n\tconst { createHandler } = createServer(registry, inputConfig);\n\treturn createHandler();\n}\n\nexport function createServer<R extends Registry<any>>(\n\tregistry: R,\n\tinputConfig?: InputConfig,\n): SetupOutput<R> {\n\tconst config = ConfigSchema.parse(inputConfig);\n\n\t// Create config\n\tconst runConfig = {\n\t\tdriver: {\n\t\t\tname: \"cloudflare-workers\",\n\t\t\tmanager: () => new CloudflareActorsManagerDriver(),\n\t\t\t// HACK: We can't build the actor driver until we're inside the Durable Object\n\t\t\tactor: undefined as any,\n\t\t},\n\t\tgetUpgradeWebSocket: () => upgradeWebSocket,\n\t\t...config,\n\t} satisfies RunConfig;\n\n\t// Create Durable Object\n\tconst ActorHandler = createActorDurableObject(registry, runConfig);\n\n\t// Create server\n\tconst serverOutput = registry.createServer(runConfig);\n\n\treturn {\n\t\tclient: serverOutput.client as Client<R>,\n\t\tcreateHandler: (hono) => {\n\t\t\t// Build base router\n\t\t\tconst app = hono ?? new Hono();\n\n\t\t\t// Mount registry router at /registry\n\t\t\tif (!hono) {\n\t\t\t\tapp.route(\"/registry\", serverOutput.hono);\n\t\t\t}\n\n\t\t\t// Create Cloudflare handler\n\t\t\tconst handler = {\n\t\t\t\tfetch: (request, env, ctx) => {\n\t\t\t\t\treturn CF_AMBIENT_ENV.run(env, () => app.fetch(request, env, ctx));\n\t\t\t\t},\n\t\t\t} satisfies ExportedHandler<Bindings>;\n\n\t\t\treturn { handler, ActorHandler };\n\t\t},\n\t};\n}\n","import { DurableObject } from \"cloudflare:workers\";\nimport type {\n\tActorKey,\n\tActorRouter,\n\tRegistry,\n\tRunConfig,\n} from \"@rivetkit/core\";\nimport {\n\tcreateActorRouter,\n\tcreateClientWithDriver,\n\tcreateInlineClientDriver,\n} from \"@rivetkit/core\";\nimport { serializeEmptyPersistData } from \"@rivetkit/core/driver-helpers\";\nimport type { ExecutionContext } from \"hono\";\nimport {\n\tCloudflareDurableObjectGlobalState,\n\tcreateCloudflareActorsActorDriverBuilder,\n} from \"./actor-driver\";\nimport { type Bindings, CF_AMBIENT_ENV } from \"./handler\";\nimport { logger } from \"./log\";\n\nexport const KEYS = {\n\tNAME: \"rivetkit:name\",\n\tKEY: \"rivetkit:key\",\n\tPERSIST_DATA: \"rivetkit:data\",\n};\n\nexport interface ActorHandlerInterface extends DurableObject {\n\tinitialize(req: ActorInitRequest): Promise<void>;\n}\n\nexport interface ActorInitRequest {\n\tname: string;\n\tkey: ActorKey;\n\tinput?: unknown;\n}\n\ninterface InitializedData {\n\tname: string;\n\tkey: ActorKey;\n}\n\nexport type DurableObjectConstructor = new (\n\t...args: ConstructorParameters<typeof DurableObject<Bindings>>\n) => DurableObject<Bindings>;\n\ninterface LoadedActor {\n\tactorRouter: ActorRouter;\n}\n\nexport function createActorDurableObject(\n\tregistry: Registry<any>,\n\trunConfig: RunConfig,\n): DurableObjectConstructor {\n\tconst globalState = new CloudflareDurableObjectGlobalState();\n\n\t/**\n\t * Startup steps:\n\t * 1. If not already created call `initialize`, otherwise check KV to ensure it's initialized\n\t * 2. Load actor\n\t * 3. Start service requests\n\t */\n\treturn class ActorHandler\n\t\textends DurableObject<Bindings>\n\t\timplements ActorHandlerInterface\n\t{\n\t\t#initialized?: InitializedData;\n\t\t#initializedPromise?: PromiseWithResolvers<void>;\n\n\t\t#actor?: LoadedActor;\n\n\t\tasync #loadActor(): Promise<LoadedActor> {\n\t\t\t// This is always called from another context using CF_AMBIENT_ENV\n\n\t\t\t// Wait for init\n\t\t\tif (!this.#initialized) {\n\t\t\t\t// Wait for init\n\t\t\t\tif (this.#initializedPromise) {\n\t\t\t\t\tawait this.#initializedPromise.promise;\n\t\t\t\t} else {\n\t\t\t\t\tthis.#initializedPromise = Promise.withResolvers();\n\t\t\t\t\tconst res = await this.ctx.storage.get([\n\t\t\t\t\t\tKEYS.NAME,\n\t\t\t\t\t\tKEYS.KEY,\n\t\t\t\t\t\tKEYS.PERSIST_DATA,\n\t\t\t\t\t]);\n\t\t\t\t\tif (res.get(KEYS.PERSIST_DATA)) {\n\t\t\t\t\t\tconst name = res.get(KEYS.NAME) as string;\n\t\t\t\t\t\tif (!name) throw new Error(\"missing actor name\");\n\t\t\t\t\t\tconst key = res.get(KEYS.KEY) as ActorKey;\n\t\t\t\t\t\tif (!key) throw new Error(\"missing actor key\");\n\n\t\t\t\t\t\tlogger().debug(\"already initialized\", { name, key });\n\n\t\t\t\t\t\tthis.#initialized = { name, key };\n\t\t\t\t\t\tthis.#initializedPromise.resolve();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger().debug(\"waiting to initialize\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check if already loaded\n\t\t\tif (this.#actor) {\n\t\t\t\treturn this.#actor;\n\t\t\t}\n\n\t\t\tif (!this.#initialized) throw new Error(\"Not initialized\");\n\n\t\t\t// Register DO with global state first\n\t\t\t// HACK: This leaks the DO context, but DO does not provide a native way\n\t\t\t// of knowing when the DO shuts down. We're making a broad assumption\n\t\t\t// that DO will boot a new isolate frequenlty enough that this is not an issue.\n\t\t\tconst actorId = this.ctx.id.toString();\n\t\t\tglobalState.setDOState(actorId, { ctx: this.ctx, env: this.env });\n\n\t\t\t// Configure actor driver\n\t\t\trunConfig.driver.actor =\n\t\t\t\tcreateCloudflareActorsActorDriverBuilder(globalState);\n\n\t\t\t// Create manager driver (we need this for the actor router)\n\t\t\tconst managerDriver = runConfig.driver.manager(\n\t\t\t\tregistry.config,\n\t\t\t\trunConfig,\n\t\t\t);\n\n\t\t\t// Create inline client\n\t\t\tconst inlineClient = createClientWithDriver(\n\t\t\t\tcreateInlineClientDriver(managerDriver),\n\t\t\t);\n\n\t\t\t// Create actor driver\n\t\t\tconst actorDriver = runConfig.driver.actor(\n\t\t\t\tregistry.config,\n\t\t\t\trunConfig,\n\t\t\t\tmanagerDriver,\n\t\t\t\tinlineClient,\n\t\t\t);\n\n\t\t\t// Create actor router\n\t\t\tconst actorRouter = createActorRouter(runConfig, actorDriver);\n\n\t\t\t// Save actor\n\t\t\tthis.#actor = {\n\t\t\t\tactorRouter,\n\t\t\t};\n\n\t\t\t// Initialize the actor instance with proper metadata\n\t\t\t// This ensures the actor driver knows about this actor\n\t\t\tawait actorDriver.loadActor(actorId);\n\n\t\t\treturn this.#actor;\n\t\t}\n\n\t\t/** RPC called by the service that creates the DO to initialize it. */\n\t\tasync initialize(req: ActorInitRequest) {\n\t\t\t// TODO: Need to add this to a core promise that needs to be resolved before start\n\n\t\t\treturn await CF_AMBIENT_ENV.run(this.env, async () => {\n\t\t\t\tawait this.ctx.storage.put({\n\t\t\t\t\t[KEYS.NAME]: req.name,\n\t\t\t\t\t[KEYS.KEY]: req.key,\n\t\t\t\t\t[KEYS.PERSIST_DATA]: serializeEmptyPersistData(req.input),\n\t\t\t\t});\n\t\t\t\tthis.#initialized = {\n\t\t\t\t\tname: req.name,\n\t\t\t\t\tkey: req.key,\n\t\t\t\t};\n\n\t\t\t\tlogger().debug(\"initialized actor\", { key: req.key });\n\n\t\t\t\t// Preemptively actor so the lifecycle hooks are called\n\t\t\t\tawait this.#loadActor();\n\t\t\t});\n\t\t}\n\n\t\tasync fetch(request: Request): Promise<Response> {\n\t\t\treturn await CF_AMBIENT_ENV.run(this.env, async () => {\n\t\t\t\tconst { actorRouter } = await this.#loadActor();\n\n\t\t\t\tconst actorId = this.ctx.id.toString();\n\t\t\t\treturn await actorRouter.fetch(request, {\n\t\t\t\t\tactorId,\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\t\tasync alarm(): Promise<void> {\n\t\t\treturn await CF_AMBIENT_ENV.run(this.env, async () => {\n\t\t\t\tawait this.#loadActor();\n\t\t\t\tconst actorId = this.ctx.id.toString();\n\n\t\t\t\t// Get the actor driver\n\t\t\t\tconst managerDriver = runConfig.driver.manager(\n\t\t\t\t\tregistry.config,\n\t\t\t\t\trunConfig,\n\t\t\t\t);\n\t\t\t\tconst inlineClient = createClientWithDriver(\n\t\t\t\t\tcreateInlineClientDriver(managerDriver),\n\t\t\t\t);\n\t\t\t\tconst actorDriver = runConfig.driver.actor(\n\t\t\t\t\tregistry.config,\n\t\t\t\t\trunConfig,\n\t\t\t\t\tmanagerDriver,\n\t\t\t\t\tinlineClient,\n\t\t\t\t);\n\n\t\t\t\t// Load the actor instance and trigger alarm\n\t\t\t\tconst actor = await actorDriver.loadActor(actorId);\n\t\t\t\tawait actor.onAlarm();\n\t\t\t});\n\t\t}\n\t};\n}\n","import type {\n\tAnyActorInstance as CoreAnyActorInstance,\n\tRegistryConfig,\n\tRunConfig,\n} from \"@rivetkit/core\";\nimport {\n\tcreateGenericConnDrivers,\n\tGenericConnGlobalState,\n\tlookupInRegistry,\n} from \"@rivetkit/core\";\nimport type { Client } from \"@rivetkit/core/client\";\nimport type {\n\tActorDriver,\n\tAnyActorInstance,\n\tManagerDriver,\n} from \"@rivetkit/core/driver-helpers\";\nimport invariant from \"invariant\";\nimport { KEYS } from \"./actor-handler-do\";\n\ninterface DurableObjectGlobalState {\n\tctx: DurableObjectState;\n\tenv: unknown;\n}\n\n/**\n * Cloudflare DO can have multiple DO running within the same global scope.\n *\n * This allows for storing the actor context globally and looking it up by ID in `CloudflareActorsActorDriver`.\n */\nexport class CloudflareDurableObjectGlobalState {\n\t// Single map for all actor state\n\t#dos: Map<string, DurableObjectGlobalState> = new Map();\n\n\tgetDOState(actorId: string): DurableObjectGlobalState {\n\t\tconst state = this.#dos.get(actorId);\n\t\tinvariant(state !== undefined, \"durable object state not in global state\");\n\t\treturn state;\n\t}\n\n\tsetDOState(actorId: string, state: DurableObjectGlobalState) {\n\t\tthis.#dos.set(actorId, state);\n\t}\n}\n\nexport interface ActorDriverContext {\n\tctx: DurableObjectState;\n\tenv: unknown;\n}\n\n// Actor handler to track running instances\nclass ActorHandler {\n\tactor?: AnyActorInstance;\n\tactorPromise?: PromiseWithResolvers<void> = Promise.withResolvers();\n\tgenericConnGlobalState = new GenericConnGlobalState();\n}\n\nexport class CloudflareActorsActorDriver implements ActorDriver {\n\t#registryConfig: RegistryConfig;\n\t#runConfig: RunConfig;\n\t#managerDriver: ManagerDriver;\n\t#inlineClient: Client<any>;\n\t#globalState: CloudflareDurableObjectGlobalState;\n\t#actors: Map<string, ActorHandler> = new Map();\n\n\tconstructor(\n\t\tregistryConfig: RegistryConfig,\n\t\trunConfig: RunConfig,\n\t\tmanagerDriver: ManagerDriver,\n\t\tinlineClient: Client<any>,\n\t\tglobalState: CloudflareDurableObjectGlobalState,\n\t) {\n\t\tthis.#registryConfig = registryConfig;\n\t\tthis.#runConfig = runConfig;\n\t\tthis.#managerDriver = managerDriver;\n\t\tthis.#inlineClient = inlineClient;\n\t\tthis.#globalState = globalState;\n\t}\n\n\t#getDOCtx(actorId: string) {\n\t\treturn this.#globalState.getDOState(actorId).ctx;\n\t}\n\n\tasync loadActor(actorId: string): Promise<AnyActorInstance> {\n\t\t// Check if actor is already loaded\n\t\tlet handler = this.#actors.get(actorId);\n\t\tif (handler) {\n\t\t\tif (handler.actorPromise) await handler.actorPromise.promise;\n\t\t\tif (!handler.actor) throw new Error(\"Actor should be loaded\");\n\t\t\treturn handler.actor;\n\t\t}\n\n\t\t// Create new actor handler\n\t\thandler = new ActorHandler();\n\t\tthis.#actors.set(actorId, handler);\n\n\t\t// Get the actor metadata from Durable Object storage\n\t\tconst doState = this.#globalState.getDOState(actorId);\n\t\tconst storage = doState.ctx.storage;\n\n\t\t// Load actor metadata\n\t\tconst [name, key] = await Promise.all([\n\t\t\tstorage.get<string>(KEYS.NAME),\n\t\t\tstorage.get<string[]>(KEYS.KEY),\n\t\t]);\n\n\t\tif (!name) {\n\t\t\tthrow new Error(`Actor ${actorId} is not initialized - missing name`);\n\t\t}\n\t\tif (!key) {\n\t\t\tthrow new Error(`Actor ${actorId} is not initialized - missing key`);\n\t\t}\n\n\t\t// Create actor instance\n\t\tconst definition = lookupInRegistry(this.#registryConfig, name);\n\t\thandler.actor = definition.instantiate();\n\n\t\t// Start actor\n\t\tconst connDrivers = createGenericConnDrivers(\n\t\t\thandler.genericConnGlobalState,\n\t\t);\n\t\tawait handler.actor.start(\n\t\t\tconnDrivers,\n\t\t\tthis,\n\t\t\tthis.#inlineClient,\n\t\t\tactorId,\n\t\t\tname,\n\t\t\tkey,\n\t\t\t\"unknown\", // TODO: Support regions in Cloudflare\n\t\t);\n\n\t\t// Finish\n\t\thandler.actorPromise?.resolve();\n\t\thandler.actorPromise = undefined;\n\n\t\treturn handler.actor;\n\t}\n\n\tgetGenericConnGlobalState(actorId: string): GenericConnGlobalState {\n\t\tconst handler = this.#actors.get(actorId);\n\t\tif (!handler) {\n\t\t\tthrow new Error(`Actor ${actorId} not loaded`);\n\t\t}\n\t\treturn handler.genericConnGlobalState;\n\t}\n\n\tgetContext(actorId: string): ActorDriverContext {\n\t\tconst state = this.#globalState.getDOState(actorId);\n\t\treturn { ctx: state.ctx, env: state.env };\n\t}\n\n\tasync readPersistedData(actorId: string): Promise<Uint8Array | undefined> {\n\t\treturn await this.#getDOCtx(actorId).storage.get(KEYS.PERSIST_DATA);\n\t}\n\n\tasync writePersistedData(actorId: string, data: Uint8Array): Promise<void> {\n\t\tawait this.#getDOCtx(actorId).storage.put(KEYS.PERSIST_DATA, data);\n\t}\n\n\tasync setAlarm(actor: AnyActorInstance, timestamp: number): Promise<void> {\n\t\tawait this.#getDOCtx(actor.id).storage.setAlarm(timestamp);\n\t}\n\n\tasync getDatabase(actorId: string): Promise<unknown | undefined> {\n\t\treturn this.#getDOCtx(actorId).storage.sql;\n\t}\n}\n\nexport function createCloudflareActorsActorDriverBuilder(\n\tglobalState: CloudflareDurableObjectGlobalState,\n) {\n\treturn (\n\t\tregistryConfig: RegistryConfig,\n\t\trunConfig: RunConfig,\n\t\tmanagerDriver: ManagerDriver,\n\t\tinlineClient: Client<any>,\n\t) => {\n\t\treturn new CloudflareActorsActorDriver(\n\t\t\tregistryConfig,\n\t\t\trunConfig,\n\t\t\tmanagerDriver,\n\t\t\tinlineClient,\n\t\t\tglobalState,\n\t\t);\n\t};\n}\n","import { getLogger } from \"@rivetkit/core/log\";\n\nexport const LOGGER_NAME = \"driver-cloudflare-workers\";\n\nexport function logger() {\n\treturn getLogger(LOGGER_NAME);\n}\n","import { RunConfigSchema } from \"@rivetkit/core/driver-helpers\";\nimport type { Hono } from \"hono\";\nimport { z } from \"zod\";\n\nexport const ConfigSchema = RunConfigSchema.removeDefault()\n\t.omit({ driver: true, getUpgradeWebSocket: true })\n\t.extend({\n\t\tapp: z.custom<Hono>().optional(),\n\t})\n\t.default({});\nexport type InputConfig = z.input<typeof ConfigSchema>;\nexport type Config = z.infer<typeof ConfigSchema>;\n","import type { Encoding } from \"@rivetkit/core\";\nimport {\n\ttype ActorOutput,\n\ttype CreateInput,\n\ttype GetForIdInput,\n\ttype GetOrCreateWithKeyInput,\n\ttype GetWithKeyInput,\n\tHEADER_AUTH_DATA,\n\tHEADER_CONN_PARAMS,\n\tHEADER_ENCODING,\n\tHEADER_EXPOSE_INTERNAL_ERROR,\n\ttype ManagerDriver,\n} from \"@rivetkit/core/driver-helpers\";\nimport { ActorAlreadyExists, InternalError } from \"@rivetkit/core/errors\";\nimport type { Context as HonoContext } from \"hono\";\nimport { getCloudflareAmbientEnv } from \"./handler\";\nimport { logger } from \"./log\";\nimport type { Bindings } from \"./mod\";\nimport { serializeKey, serializeNameAndKey } from \"./util\";\n\n// Actor metadata structure\ninterface ActorData {\n\tname: string;\n\tkey: string[];\n}\n\n// Key constants similar to Redis implementation\nconst KEYS = {\n\tACTOR: {\n\t\t// Combined key for actor metadata (name and key)\n\t\tmetadata: (actorId: string) => `actor:${actorId}:metadata`,\n\n\t\t// Key index function for actor lookup\n\t\tkeyIndex: (name: string, key: string[] = []) => {\n\t\t\t// Use serializeKey for consistent handling of all keys\n\t\t\treturn `actor_key:${serializeKey(key)}`;\n\t\t},\n\t},\n};\n\nconst STANDARD_WEBSOCKET_HEADERS = [\n\t\"connection\",\n\t\"upgrade\",\n\t\"sec-websocket-key\",\n\t\"sec-websocket-version\",\n\t\"sec-websocket-protocol\",\n\t\"sec-websocket-extensions\",\n];\n\nexport class CloudflareActorsManagerDriver implements ManagerDriver {\n\tasync sendRequest(actorId: string, actorRequest: Request): Promise<Response> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\tlogger().debug(\"sending request to durable object\", {\n\t\t\tactorId,\n\t\t\tmethod: actorRequest.method,\n\t\t\turl: actorRequest.url,\n\t\t});\n\n\t\tconst id = env.ACTOR_DO.idFromString(actorId);\n\t\tconst stub = env.ACTOR_DO.get(id);\n\n\t\treturn await stub.fetch(actorRequest);\n\t}\n\n\tasync openWebSocket(\n\t\tpath: string,\n\t\tactorId: string,\n\t\tencoding: Encoding,\n\t\tparams: unknown,\n\t): Promise<WebSocket> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\tlogger().debug(\"opening websocket to durable object\", { actorId, path });\n\n\t\t// Make a fetch request to the Durable Object with WebSocket upgrade\n\t\tconst id = env.ACTOR_DO.idFromString(actorId);\n\t\tconst stub = env.ACTOR_DO.get(id);\n\n\t\tconst headers: Record<string, string> = {\n\t\t\tUpgrade: \"websocket\",\n\t\t\tConnection: \"Upgrade\",\n\t\t\t[HEADER_EXPOSE_INTERNAL_ERROR]: \"true\",\n\t\t\t[HEADER_ENCODING]: encoding,\n\t\t};\n\t\tif (params) {\n\t\t\theaders[HEADER_CONN_PARAMS] = JSON.stringify(params);\n\t\t}\n\t\t// HACK: See packages/drivers/cloudflare-workers/src/websocket.ts\n\t\theaders[\"sec-websocket-protocol\"] = \"rivetkit\";\n\n\t\t// Use the path parameter to determine the URL\n\t\tconst url = `http://actor${path}`;\n\n\t\tlogger().debug(\"rewriting websocket url\", {\n\t\t\tfrom: path,\n\t\t\tto: url,\n\t\t});\n\n\t\tconst response = await stub.fetch(url, {\n\t\t\theaders,\n\t\t});\n\t\tconst webSocket = response.webSocket;\n\n\t\tif (!webSocket) {\n\t\t\tthrow new InternalError(\n\t\t\t\t\"missing websocket connection in response from DO\",\n\t\t\t);\n\t\t}\n\n\t\tlogger().debug(\"durable object websocket connection open\", {\n\t\t\tactorId,\n\t\t});\n\n\t\twebSocket.accept();\n\n\t\t// TODO: Is this still needed?\n\t\t// HACK: Cloudflare does not call onopen automatically, so we need\n\t\t// to call this on the next tick\n\t\tsetTimeout(() => {\n\t\t\tconst event = new Event(\"open\");\n\t\t\t(webSocket as any).onopen?.(event);\n\t\t\t(webSocket as any).dispatchEvent(event);\n\t\t}, 0);\n\n\t\treturn webSocket as unknown as WebSocket;\n\t}\n\n\tasync proxyRequest(\n\t\tc: HonoContext<{ Bindings: Bindings }>,\n\t\tactorRequest: Request,\n\t\tactorId: string,\n\t): Promise<Response> {\n\t\tlogger().debug(\"forwarding request to durable object\", {\n\t\t\tactorId,\n\t\t\tmethod: actorRequest.method,\n\t\t\turl: actorRequest.url,\n\t\t});\n\n\t\tconst id = c.env.ACTOR_DO.idFromString(actorId);\n\t\tconst stub = c.env.ACTOR_DO.get(id);\n\n\t\treturn await stub.fetch(actorRequest);\n\t}\n\n\tasync proxyWebSocket(\n\t\tc: HonoContext<{ Bindings: Bindings }>,\n\t\tpath: string,\n\t\tactorId: string,\n\t\tencoding: Encoding,\n\t\tparams: unknown,\n\t\tauthData: unknown,\n\t): Promise<Response> {\n\t\tlogger().debug(\"forwarding websocket to durable object\", {\n\t\t\tactorId,\n\t\t\tpath,\n\t\t});\n\n\t\t// Validate upgrade\n\t\tconst upgradeHeader = c.req.header(\"Upgrade\");\n\t\tif (!upgradeHeader || upgradeHeader !== \"websocket\") {\n\t\t\treturn new Response(\"Expected Upgrade: websocket\", {\n\t\t\t\tstatus: 426,\n\t\t\t});\n\t\t}\n\n\t\t// TODO: strip headers\n\t\tconst newUrl = new URL(`http://actor${path}`);\n\t\tconst actorRequest = new Request(newUrl, c.req.raw);\n\n\t\tlogger().debug(\"rewriting websocket url\", {\n\t\t\tfrom: c.req.url,\n\t\t\tto: actorRequest.url,\n\t\t});\n\n\t\t// Always build fresh request to prevent forwarding unwanted headers\n\t\t// HACK: Since we can't build a new request, we need to remove\n\t\t// non-standard headers manually\n\t\tconst headerKeys: string[] = [];\n\t\tactorRequest.headers.forEach((v, k) => headerKeys.push(k));\n\t\tfor (const k of headerKeys) {\n\t\t\tif (!STANDARD_WEBSOCKET_HEADERS.includes(k)) {\n\t\t\t\tactorRequest.headers.delete(k);\n\t\t\t}\n\t\t}\n\n\t\t// Add RivetKit headers\n\t\tactorRequest.headers.set(HEADER_EXPOSE_INTERNAL_ERROR, \"true\");\n\t\tactorRequest.headers.set(HEADER_ENCODING, encoding);\n\t\tif (params) {\n\t\t\tactorRequest.headers.set(HEADER_CONN_PARAMS, JSON.stringify(params));\n\t\t}\n\t\tif (authData) {\n\t\t\tactorRequest.headers.set(HEADER_AUTH_DATA, JSON.stringify(authData));\n\t\t}\n\n\t\tconst id = c.env.ACTOR_DO.idFromString(actorId);\n\t\tconst stub = c.env.ACTOR_DO.get(id);\n\n\t\treturn await stub.fetch(actorRequest);\n\t}\n\n\tasync getForId({\n\t\tc,\n\t\tactorId,\n\t}: GetForIdInput<{ Bindings: Bindings }>): Promise<ActorOutput | undefined> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\t// Get actor metadata from KV (combined name and key)\n\t\tconst actorData = (await env.ACTOR_KV.get(KEYS.ACTOR.metadata(actorId), {\n\t\t\ttype: \"json\",\n\t\t})) as ActorData | null;\n\n\t\t// If the actor doesn't exist, return undefined\n\t\tif (!actorData) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tactorId,\n\t\t\tname: actorData.name,\n\t\t\tkey: actorData.key,\n\t\t};\n\t}\n\n\tasync getWithKey({\n\t\tc,\n\t\tname,\n\t\tkey,\n\t}: GetWithKeyInput<{ Bindings: Bindings }>): Promise<\n\t\tActorOutput | undefined\n\t> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\tlogger().debug(\"getWithKey: searching for actor\", { name, key });\n\n\t\t// Generate deterministic ID from the name and key\n\t\t// This is aligned with how createActor generates IDs\n\t\tconst nameKeyString = serializeNameAndKey(name, key);\n\t\tconst actorId = env.ACTOR_DO.idFromName(nameKeyString).toString();\n\n\t\t// Check if the actor metadata exists\n\t\tconst actorData = await env.ACTOR_KV.get(KEYS.ACTOR.metadata(actorId), {\n\t\t\ttype: \"json\",\n\t\t});\n\n\t\tif (!actorData) {\n\t\t\tlogger().debug(\"getWithKey: no actor found with matching name and key\", {\n\t\t\t\tname,\n\t\t\t\tkey,\n\t\t\t\tactorId,\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\n\t\tlogger().debug(\"getWithKey: found actor with matching name and key\", {\n\t\t\tactorId,\n\t\t\tname,\n\t\t\tkey,\n\t\t});\n\t\treturn this.#buildActorOutput(c, actorId);\n\t}\n\n\tasync getOrCreateWithKey(\n\t\tinput: GetOrCreateWithKeyInput,\n\t): Promise<ActorOutput> {\n\t\t// TODO: Prevent race condition here\n\t\tconst getOutput = await this.getWithKey(input);\n\t\tif (getOutput) {\n\t\t\treturn getOutput;\n\t\t} else {\n\t\t\treturn await this.createActor(input);\n\t\t}\n\t}\n\n\tasync createActor({\n\t\tc,\n\t\tname,\n\t\tkey,\n\t\tinput,\n\t}: CreateInput<{ Bindings: Bindings }>): Promise<ActorOutput> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\t// Check if actor with the same name and key already exists\n\t\tconst existingActor = await this.getWithKey({ c, name, key });\n\t\tif (existingActor) {\n\t\t\tthrow new ActorAlreadyExists(name, key);\n\t\t}\n\n\t\t// Create a deterministic ID from the actor name and key\n\t\t// This ensures that actors with the same name and key will have the same ID\n\t\tconst nameKeyString = serializeNameAndKey(name, key);\n\t\tconst doId = env.ACTOR_DO.idFromName(nameKeyString);\n\t\tconst actorId = doId.toString();\n\n\t\t// Init actor\n\t\tconst actor = env.ACTOR_DO.get(doId);\n\t\tawait actor.initialize({\n\t\t\tname,\n\t\t\tkey,\n\t\t\tinput,\n\t\t});\n\n\t\t// Store combined actor metadata (name and key)\n\t\tconst actorData: ActorData = { name, key };\n\t\tawait env.ACTOR_KV.put(\n\t\t\tKEYS.ACTOR.metadata(actorId),\n\t\t\tJSON.stringify(actorData),\n\t\t);\n\n\t\t// Add to key index for lookups by name and key\n\t\tawait env.ACTOR_KV.put(KEYS.ACTOR.keyIndex(name, key), actorId);\n\n\t\treturn {\n\t\t\tactorId,\n\t\t\tname,\n\t\t\tkey,\n\t\t};\n\t}\n\n\t// Helper method to build actor output from an ID\n\tasync #buildActorOutput(\n\t\tc: any,\n\t\tactorId: string,\n\t): Promise<ActorOutput | undefined> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\tconst actorData = (await env.ACTOR_KV.get(KEYS.ACTOR.metadata(actorId), {\n\t\t\ttype: \"json\",\n\t\t})) as ActorData | null;\n\n\t\tif (!actorData) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tactorId,\n\t\t\tname: actorData.name,\n\t\t\tkey: actorData.key,\n\t\t};\n\t}\n}\n","// Constants for key handling\nexport const EMPTY_KEY = \"(none)\";\nexport const KEY_SEPARATOR = \",\";\n\n/**\n * Serializes an array of key strings into a single string for use with idFromName\n *\n * @param name The actor name\n * @param key Array of key strings to serialize\n * @returns A single string containing the serialized name and key\n */\nexport function serializeNameAndKey(name: string, key: string[]): string {\n\t// Escape colons in the name\n\tconst escapedName = name.replace(/:/g, \"\\\\:\");\n\n\t// For empty keys, just return the name and a marker\n\tif (key.length === 0) {\n\t\treturn `${escapedName}:${EMPTY_KEY}`;\n\t}\n\n\t// Serialize the key array\n\tconst serializedKey = serializeKey(key);\n\n\t// Combine name and serialized key\n\treturn `${escapedName}:${serializedKey}`;\n}\n\n/**\n * Serializes an array of key strings into a single string\n *\n * @param key Array of key strings to serialize\n * @returns A single string containing the serialized key\n */\nexport function serializeKey(key: string[]): string {\n\t// Use a special marker for empty key arrays\n\tif (key.length === 0) {\n\t\treturn EMPTY_KEY;\n\t}\n\n\t// Escape each key part to handle the separator and the empty key marker\n\tconst escapedParts = key.map((part) => {\n\t\t// First check if it matches our empty key marker\n\t\tif (part === EMPTY_KEY) {\n\t\t\treturn `\\\\${EMPTY_KEY}`;\n\t\t}\n\n\t\t// Escape backslashes first, then commas\n\t\tlet escaped = part.replace(/\\\\/g, \"\\\\\\\\\");\n\t\tescaped = escaped.replace(/,/g, \"\\\\,\");\n\t\treturn escaped;\n\t});\n\n\treturn escapedParts.join(KEY_SEPARATOR);\n}\n\n/**\n * Deserializes a key string back into an array of key strings\n *\n * @param keyString The serialized key string\n * @returns Array of key strings\n */\nexport function deserializeKey(keyString: string): string[] {\n\t// Handle empty values\n\tif (!keyString) {\n\t\treturn [];\n\t}\n\n\t// Check for special empty key marker\n\tif (keyString === EMPTY_KEY) {\n\t\treturn [];\n\t}\n\n\t// Split by unescaped commas and unescape the escaped characters\n\tconst parts: string[] = [];\n\tlet currentPart = \"\";\n\tlet escaping = false;\n\n\tfor (let i = 0; i < keyString.length; i++) {\n\t\tconst char = keyString[i];\n\n\t\tif (escaping) {\n\t\t\t// This is an escaped character, add it directly\n\t\t\tcurrentPart += char;\n\t\t\tescaping = false;\n\t\t} else if (char === \"\\\\\") {\n\t\t\t// Start of an escape sequence\n\t\t\tescaping = true;\n\t\t} else if (char === KEY_SEPARATOR) {\n\t\t\t// This is a separator\n\t\t\tparts.push(currentPart);\n\t\t\tcurrentPart = \"\";\n\t\t} else {\n\t\t\t// Regular character\n\t\t\tcurrentPart += char;\n\t\t}\n\t}\n\n\t// Add the last part if it exists\n\tif (currentPart || parts.length > 0) {\n\t\tparts.push(currentPart);\n\t}\n\n\treturn parts;\n}\n","// Modified from https://github.com/honojs/hono/blob/40ea0eee58e39b31053a0246c595434f1094ad31/src/adapter/cloudflare-workers/websocket.ts#L17\n//\n// This version calls the open event by default\n\nimport type { UpgradeWebSocket, WSEvents, WSReadyState } from \"hono/ws\";\nimport { defineWebSocketHelper, WSContext } from \"hono/ws\";\n\n// Based on https://github.com/honojs/hono/issues/1153#issuecomment-1767321332\nexport const upgradeWebSocket: UpgradeWebSocket<\n\tWebSocket,\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tany,\n\tWSEvents<WebSocket>\n> = defineWebSocketHelper(async (c, events) => {\n\tconst upgradeHeader = c.req.header(\"Upgrade\");\n\tif (upgradeHeader !== \"websocket\") {\n\t\treturn;\n\t}\n\n\tconst webSocketPair = new WebSocketPair();\n\tconst client: WebSocket = webSocketPair[0];\n\tconst server: WebSocket = webSocketPair[1];\n\n\tconst wsContext = new WSContext<WebSocket>({\n\t\tclose: (code, reason) => server.close(code, reason),\n\t\tget protocol() {\n\t\t\treturn server.protocol;\n\t\t},\n\t\traw: server,\n\t\tget readyState() {\n\t\t\treturn server.readyState as WSReadyState;\n\t\t},\n\t\turl: server.url ? new URL(server.url) : null,\n\t\tsend: (source) => server.send(source),\n\t});\n\n\tif (events.onClose) {\n\t\tserver.addEventListener(\"close\", (evt: CloseEvent) =>\n\t\t\tevents.onClose?.(evt, wsContext),\n\t\t);\n\t}\n\tif (events.onMessage) {\n\t\tserver.addEventListener(\"message\", (evt: MessageEvent) =>\n\t\t\tevents.onMessage?.(evt, wsContext),\n\t\t);\n\t}\n\tif (events.onError) {\n\t\tserver.addEventListener(\"error\", (evt: Event) =>\n\t\t\tevents.onError?.(evt, wsContext),\n\t\t);\n\t}\n\n\tserver.accept?.();\n\n\t// note: cloudflare actors doesn't support 'open' event, so we call it immediately with a fake event\n\t//\n\t// we have to do this after `server.accept() is called`\n\tevents.onOpen?.(new Event(\"open\"), wsContext);\n\n\treturn new Response(null, {\n\t\tstatus: 101,\n\t\theaders: {\n\t\t\t// HACK: Required in order for Cloudflare to not error with \"Network connection lost\"\n\t\t\t//\n\t\t\t// This bug undocumented. Cannot easily reproduce outside of RivetKit.\n\t\t\t\"Sec-WebSocket-Protocol\": \"rivetkit\",\n\t\t},\n\t\twebSocket: client,\n\t});\n});\n"]}
1
+ {"version":3,"sources":["/home/nathan/rivetkit/packages/drivers/cloudflare-workers/dist/mod.cjs","../src/handler.ts","../src/actor-handler-do.ts","../src/actor-driver.ts","../src/log.ts","../src/config.ts","../src/manager-driver.ts","../src/util.ts","../src/websocket.ts"],"names":["env","_a","ActorHandler"],"mappings":"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","file":"/home/nathan/rivetkit/packages/drivers/cloudflare-workers/dist/mod.cjs","sourcesContent":[null,"import { env } from \"cloudflare:workers\";\nimport type { Registry, RunConfig } from \"@rivetkit/core\";\nimport type { Client } from \"@rivetkit/core/client\";\nimport { Hono } from \"hono\";\nimport {\n\ttype ActorHandlerInterface,\n\tcreateActorDurableObject,\n\ttype DurableObjectConstructor,\n} from \"./actor-handler-do\";\nimport { ConfigSchema, type InputConfig } from \"./config\";\nimport { CloudflareActorsManagerDriver } from \"./manager-driver\";\nimport { upgradeWebSocket } from \"./websocket\";\n\n/** Cloudflare Workers env */\nexport interface Bindings {\n\tACTOR_KV: KVNamespace;\n\tACTOR_DO: DurableObjectNamespace<ActorHandlerInterface>;\n}\n\n/**\n * Stores the env for the current request. Required since some contexts like the inline client driver does not have access to the Hono context.\n *\n * Use getCloudflareAmbientEnv unless using CF_AMBIENT_ENV.run.\n */\nexport function getCloudflareAmbientEnv(): Bindings {\n\treturn env as unknown as Bindings;\n}\n\ninterface Handler {\n\thandler: ExportedHandler<Bindings>;\n\tActorHandler: DurableObjectConstructor;\n}\n\ninterface SetupOutput<A extends Registry<any>> {\n\tclient: Client<A>;\n\tcreateHandler: (hono?: Hono) => Handler;\n}\n\nexport function createServerHandler<R extends Registry<any>>(\n\tregistry: R,\n\tinputConfig?: InputConfig,\n): Handler {\n\tconst { createHandler } = createServer(registry, inputConfig);\n\treturn createHandler();\n}\n\nexport function createServer<R extends Registry<any>>(\n\tregistry: R,\n\tinputConfig?: InputConfig,\n): SetupOutput<R> {\n\tconst config = ConfigSchema.parse(inputConfig);\n\n\t// Create config\n\tconst runConfig = {\n\t\tdriver: {\n\t\t\tname: \"cloudflare-workers\",\n\t\t\tmanager: () => new CloudflareActorsManagerDriver(),\n\t\t\t// HACK: We can't build the actor driver until we're inside the Durable Object\n\t\t\tactor: undefined as any,\n\t\t},\n\t\tgetUpgradeWebSocket: () => upgradeWebSocket,\n\t\t...config,\n\t} satisfies RunConfig;\n\n\t// Create Durable Object\n\tconst ActorHandler = createActorDurableObject(registry, runConfig);\n\n\t// Create server\n\tconst serverOutput = registry.createServer(runConfig);\n\n\treturn {\n\t\tclient: serverOutput.client as Client<R>,\n\t\tcreateHandler: (hono) => {\n\t\t\t// Build base router\n\t\t\tconst app = hono ?? new Hono();\n\n\t\t\t// Mount registry router at /registry\n\t\t\tif (!hono) {\n\t\t\t\tapp.route(\"/registry\", serverOutput.hono);\n\t\t\t}\n\n\t\t\t// Create Cloudflare handler\n\t\t\tconst handler = {\n\t\t\t\tfetch: (request, env, ctx) => {\n\t\t\t\t\treturn app.fetch(request, env, ctx);\n\t\t\t\t},\n\t\t\t} satisfies ExportedHandler<Bindings>;\n\n\t\t\treturn { handler, ActorHandler };\n\t\t},\n\t};\n}\n","import { DurableObject, env } from \"cloudflare:workers\";\nimport type {\n\tActorKey,\n\tActorRouter,\n\tRegistry,\n\tRunConfig,\n} from \"@rivetkit/core\";\nimport {\n\tcreateActorRouter,\n\tcreateClientWithDriver,\n\tcreateInlineClientDriver,\n} from \"@rivetkit/core\";\nimport { serializeEmptyPersistData } from \"@rivetkit/core/driver-helpers\";\nimport type { ExecutionContext } from \"hono\";\nimport {\n\tCloudflareDurableObjectGlobalState,\n\tcreateCloudflareActorsActorDriverBuilder,\n} from \"./actor-driver\";\nimport type { Bindings } from \"./handler\";\nimport { logger } from \"./log\";\n\nexport const KEYS = {\n\tNAME: \"rivetkit:name\",\n\tKEY: \"rivetkit:key\",\n\tPERSIST_DATA: \"rivetkit:data\",\n};\n\nexport interface ActorHandlerInterface extends DurableObject {\n\tinitialize(req: ActorInitRequest): Promise<void>;\n}\n\nexport interface ActorInitRequest {\n\tname: string;\n\tkey: ActorKey;\n\tinput?: unknown;\n}\n\ninterface InitializedData {\n\tname: string;\n\tkey: ActorKey;\n}\n\nexport type DurableObjectConstructor = new (\n\t...args: ConstructorParameters<typeof DurableObject<Bindings>>\n) => DurableObject<Bindings>;\n\ninterface LoadedActor {\n\tactorRouter: ActorRouter;\n}\n\nexport function createActorDurableObject(\n\tregistry: Registry<any>,\n\trunConfig: RunConfig,\n): DurableObjectConstructor {\n\tconst globalState = new CloudflareDurableObjectGlobalState();\n\n\t/**\n\t * Startup steps:\n\t * 1. If not already created call `initialize`, otherwise check KV to ensure it's initialized\n\t * 2. Load actor\n\t * 3. Start service requests\n\t */\n\treturn class ActorHandler\n\t\textends DurableObject<Bindings>\n\t\timplements ActorHandlerInterface\n\t{\n\t\t#initialized?: InitializedData;\n\t\t#initializedPromise?: PromiseWithResolvers<void>;\n\n\t\t#actor?: LoadedActor;\n\n\t\tasync #loadActor(): Promise<LoadedActor> {\n\t\t\t// Wait for init\n\t\t\tif (!this.#initialized) {\n\t\t\t\t// Wait for init\n\t\t\t\tif (this.#initializedPromise) {\n\t\t\t\t\tawait this.#initializedPromise.promise;\n\t\t\t\t} else {\n\t\t\t\t\tthis.#initializedPromise = Promise.withResolvers();\n\t\t\t\t\tconst res = await this.ctx.storage.get([\n\t\t\t\t\t\tKEYS.NAME,\n\t\t\t\t\t\tKEYS.KEY,\n\t\t\t\t\t\tKEYS.PERSIST_DATA,\n\t\t\t\t\t]);\n\t\t\t\t\tif (res.get(KEYS.PERSIST_DATA)) {\n\t\t\t\t\t\tconst name = res.get(KEYS.NAME) as string;\n\t\t\t\t\t\tif (!name) throw new Error(\"missing actor name\");\n\t\t\t\t\t\tconst key = res.get(KEYS.KEY) as ActorKey;\n\t\t\t\t\t\tif (!key) throw new Error(\"missing actor key\");\n\n\t\t\t\t\t\tlogger().debug(\"already initialized\", { name, key });\n\n\t\t\t\t\t\tthis.#initialized = { name, key };\n\t\t\t\t\t\tthis.#initializedPromise.resolve();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger().debug(\"waiting to initialize\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check if already loaded\n\t\t\tif (this.#actor) {\n\t\t\t\treturn this.#actor;\n\t\t\t}\n\n\t\t\tif (!this.#initialized) throw new Error(\"Not initialized\");\n\n\t\t\t// Register DO with global state first\n\t\t\t// HACK: This leaks the DO context, but DO does not provide a native way\n\t\t\t// of knowing when the DO shuts down. We're making a broad assumption\n\t\t\t// that DO will boot a new isolate frequenlty enough that this is not an issue.\n\t\t\tconst actorId = this.ctx.id.toString();\n\t\t\tglobalState.setDOState(actorId, { ctx: this.ctx, env: env });\n\n\t\t\t// Configure actor driver\n\t\t\trunConfig.driver.actor =\n\t\t\t\tcreateCloudflareActorsActorDriverBuilder(globalState);\n\n\t\t\t// Create manager driver (we need this for the actor router)\n\t\t\tconst managerDriver = runConfig.driver.manager(\n\t\t\t\tregistry.config,\n\t\t\t\trunConfig,\n\t\t\t);\n\n\t\t\t// Create inline client\n\t\t\tconst inlineClient = createClientWithDriver(\n\t\t\t\tcreateInlineClientDriver(managerDriver),\n\t\t\t);\n\n\t\t\t// Create actor driver\n\t\t\tconst actorDriver = runConfig.driver.actor(\n\t\t\t\tregistry.config,\n\t\t\t\trunConfig,\n\t\t\t\tmanagerDriver,\n\t\t\t\tinlineClient,\n\t\t\t);\n\n\t\t\t// Create actor router\n\t\t\tconst actorRouter = createActorRouter(runConfig, actorDriver);\n\n\t\t\t// Save actor\n\t\t\tthis.#actor = {\n\t\t\t\tactorRouter,\n\t\t\t};\n\n\t\t\t// Initialize the actor instance with proper metadata\n\t\t\t// This ensures the actor driver knows about this actor\n\t\t\tawait actorDriver.loadActor(actorId);\n\n\t\t\treturn this.#actor;\n\t\t}\n\n\t\t/** RPC called by the service that creates the DO to initialize it. */\n\t\tasync initialize(req: ActorInitRequest) {\n\t\t\t// TODO: Need to add this to a core promise that needs to be resolved before start\n\n\t\t\tawait this.ctx.storage.put({\n\t\t\t\t[KEYS.NAME]: req.name,\n\t\t\t\t[KEYS.KEY]: req.key,\n\t\t\t\t[KEYS.PERSIST_DATA]: serializeEmptyPersistData(req.input),\n\t\t\t});\n\t\t\tthis.#initialized = {\n\t\t\t\tname: req.name,\n\t\t\t\tkey: req.key,\n\t\t\t};\n\n\t\t\tlogger().debug(\"initialized actor\", { key: req.key });\n\n\t\t\t// Preemptively actor so the lifecycle hooks are called\n\t\t\tawait this.#loadActor();\n\t\t}\n\n\t\tasync fetch(request: Request): Promise<Response> {\n\t\t\tconst { actorRouter } = await this.#loadActor();\n\n\t\t\tconst actorId = this.ctx.id.toString();\n\t\t\treturn await actorRouter.fetch(request, {\n\t\t\t\tactorId,\n\t\t\t});\n\t\t}\n\n\t\tasync alarm(): Promise<void> {\n\t\t\tawait this.#loadActor();\n\t\t\tconst actorId = this.ctx.id.toString();\n\n\t\t\t// Get the actor driver\n\t\t\tconst managerDriver = runConfig.driver.manager(\n\t\t\t\tregistry.config,\n\t\t\t\trunConfig,\n\t\t\t);\n\t\t\tconst inlineClient = createClientWithDriver(\n\t\t\t\tcreateInlineClientDriver(managerDriver),\n\t\t\t);\n\t\t\tconst actorDriver = runConfig.driver.actor(\n\t\t\t\tregistry.config,\n\t\t\t\trunConfig,\n\t\t\t\tmanagerDriver,\n\t\t\t\tinlineClient,\n\t\t\t);\n\n\t\t\t// Load the actor instance and trigger alarm\n\t\t\tconst actor = await actorDriver.loadActor(actorId);\n\t\t\tawait actor.onAlarm();\n\t\t}\n\t};\n}\n","import type {\n\tAnyActorInstance as CoreAnyActorInstance,\n\tRegistryConfig,\n\tRunConfig,\n} from \"@rivetkit/core\";\nimport {\n\tcreateGenericConnDrivers,\n\tGenericConnGlobalState,\n\tlookupInRegistry,\n} from \"@rivetkit/core\";\nimport type { Client } from \"@rivetkit/core/client\";\nimport type {\n\tActorDriver,\n\tAnyActorInstance,\n\tManagerDriver,\n} from \"@rivetkit/core/driver-helpers\";\nimport invariant from \"invariant\";\nimport { KEYS } from \"./actor-handler-do\";\n\ninterface DurableObjectGlobalState {\n\tctx: DurableObjectState;\n\tenv: unknown;\n}\n\n/**\n * Cloudflare DO can have multiple DO running within the same global scope.\n *\n * This allows for storing the actor context globally and looking it up by ID in `CloudflareActorsActorDriver`.\n */\nexport class CloudflareDurableObjectGlobalState {\n\t// Single map for all actor state\n\t#dos: Map<string, DurableObjectGlobalState> = new Map();\n\n\tgetDOState(actorId: string): DurableObjectGlobalState {\n\t\tconst state = this.#dos.get(actorId);\n\t\tinvariant(state !== undefined, \"durable object state not in global state\");\n\t\treturn state;\n\t}\n\n\tsetDOState(actorId: string, state: DurableObjectGlobalState) {\n\t\tthis.#dos.set(actorId, state);\n\t}\n}\n\nexport interface DriverContext {\n\tstate: DurableObjectState;\n}\n\n// Actor handler to track running instances\nclass ActorHandler {\n\tactor?: AnyActorInstance;\n\tactorPromise?: PromiseWithResolvers<void> = Promise.withResolvers();\n\tgenericConnGlobalState = new GenericConnGlobalState();\n}\n\nexport class CloudflareActorsActorDriver implements ActorDriver {\n\t#registryConfig: RegistryConfig;\n\t#runConfig: RunConfig;\n\t#managerDriver: ManagerDriver;\n\t#inlineClient: Client<any>;\n\t#globalState: CloudflareDurableObjectGlobalState;\n\t#actors: Map<string, ActorHandler> = new Map();\n\n\tconstructor(\n\t\tregistryConfig: RegistryConfig,\n\t\trunConfig: RunConfig,\n\t\tmanagerDriver: ManagerDriver,\n\t\tinlineClient: Client<any>,\n\t\tglobalState: CloudflareDurableObjectGlobalState,\n\t) {\n\t\tthis.#registryConfig = registryConfig;\n\t\tthis.#runConfig = runConfig;\n\t\tthis.#managerDriver = managerDriver;\n\t\tthis.#inlineClient = inlineClient;\n\t\tthis.#globalState = globalState;\n\t}\n\n\t#getDOCtx(actorId: string) {\n\t\treturn this.#globalState.getDOState(actorId).ctx;\n\t}\n\n\tasync loadActor(actorId: string): Promise<AnyActorInstance> {\n\t\t// Check if actor is already loaded\n\t\tlet handler = this.#actors.get(actorId);\n\t\tif (handler) {\n\t\t\tif (handler.actorPromise) await handler.actorPromise.promise;\n\t\t\tif (!handler.actor) throw new Error(\"Actor should be loaded\");\n\t\t\treturn handler.actor;\n\t\t}\n\n\t\t// Create new actor handler\n\t\thandler = new ActorHandler();\n\t\tthis.#actors.set(actorId, handler);\n\n\t\t// Get the actor metadata from Durable Object storage\n\t\tconst doState = this.#globalState.getDOState(actorId);\n\t\tconst storage = doState.ctx.storage;\n\n\t\t// Load actor metadata\n\t\tconst [name, key] = await Promise.all([\n\t\t\tstorage.get<string>(KEYS.NAME),\n\t\t\tstorage.get<string[]>(KEYS.KEY),\n\t\t]);\n\n\t\tif (!name) {\n\t\t\tthrow new Error(`Actor ${actorId} is not initialized - missing name`);\n\t\t}\n\t\tif (!key) {\n\t\t\tthrow new Error(`Actor ${actorId} is not initialized - missing key`);\n\t\t}\n\n\t\t// Create actor instance\n\t\tconst definition = lookupInRegistry(this.#registryConfig, name);\n\t\thandler.actor = definition.instantiate();\n\n\t\t// Start actor\n\t\tconst connDrivers = createGenericConnDrivers(\n\t\t\thandler.genericConnGlobalState,\n\t\t);\n\t\tawait handler.actor.start(\n\t\t\tconnDrivers,\n\t\t\tthis,\n\t\t\tthis.#inlineClient,\n\t\t\tactorId,\n\t\t\tname,\n\t\t\tkey,\n\t\t\t\"unknown\", // TODO: Support regions in Cloudflare\n\t\t);\n\n\t\t// Finish\n\t\thandler.actorPromise?.resolve();\n\t\thandler.actorPromise = undefined;\n\n\t\treturn handler.actor;\n\t}\n\n\tgetGenericConnGlobalState(actorId: string): GenericConnGlobalState {\n\t\tconst handler = this.#actors.get(actorId);\n\t\tif (!handler) {\n\t\t\tthrow new Error(`Actor ${actorId} not loaded`);\n\t\t}\n\t\treturn handler.genericConnGlobalState;\n\t}\n\n\tgetContext(actorId: string): DriverContext {\n\t\tconst state = this.#globalState.getDOState(actorId);\n\t\treturn { state: state.ctx };\n\t}\n\n\tasync readPersistedData(actorId: string): Promise<Uint8Array | undefined> {\n\t\treturn await this.#getDOCtx(actorId).storage.get(KEYS.PERSIST_DATA);\n\t}\n\n\tasync writePersistedData(actorId: string, data: Uint8Array): Promise<void> {\n\t\tawait this.#getDOCtx(actorId).storage.put(KEYS.PERSIST_DATA, data);\n\t}\n\n\tasync setAlarm(actor: AnyActorInstance, timestamp: number): Promise<void> {\n\t\tawait this.#getDOCtx(actor.id).storage.setAlarm(timestamp);\n\t}\n\n\tasync getDatabase(actorId: string): Promise<unknown | undefined> {\n\t\treturn this.#getDOCtx(actorId).storage.sql;\n\t}\n}\n\nexport function createCloudflareActorsActorDriverBuilder(\n\tglobalState: CloudflareDurableObjectGlobalState,\n) {\n\treturn (\n\t\tregistryConfig: RegistryConfig,\n\t\trunConfig: RunConfig,\n\t\tmanagerDriver: ManagerDriver,\n\t\tinlineClient: Client<any>,\n\t) => {\n\t\treturn new CloudflareActorsActorDriver(\n\t\t\tregistryConfig,\n\t\t\trunConfig,\n\t\t\tmanagerDriver,\n\t\t\tinlineClient,\n\t\t\tglobalState,\n\t\t);\n\t};\n}\n","import { getLogger } from \"@rivetkit/core/log\";\n\nexport const LOGGER_NAME = \"driver-cloudflare-workers\";\n\nexport function logger() {\n\treturn getLogger(LOGGER_NAME);\n}\n","import { RunConfigSchema } from \"@rivetkit/core/driver-helpers\";\nimport type { Hono } from \"hono\";\nimport { z } from \"zod\";\n\nexport const ConfigSchema = RunConfigSchema.removeDefault()\n\t.omit({ driver: true, getUpgradeWebSocket: true })\n\t.extend({\n\t\tapp: z.custom<Hono>().optional(),\n\t})\n\t.default({});\nexport type InputConfig = z.input<typeof ConfigSchema>;\nexport type Config = z.infer<typeof ConfigSchema>;\n","import type { Encoding } from \"@rivetkit/core\";\nimport {\n\ttype ActorOutput,\n\ttype CreateInput,\n\ttype GetForIdInput,\n\ttype GetOrCreateWithKeyInput,\n\ttype GetWithKeyInput,\n\tHEADER_AUTH_DATA,\n\tHEADER_CONN_PARAMS,\n\tHEADER_ENCODING,\n\tHEADER_EXPOSE_INTERNAL_ERROR,\n\ttype ManagerDriver,\n} from \"@rivetkit/core/driver-helpers\";\nimport { ActorAlreadyExists, InternalError } from \"@rivetkit/core/errors\";\nimport type { Context as HonoContext } from \"hono\";\nimport { getCloudflareAmbientEnv } from \"./handler\";\nimport { logger } from \"./log\";\nimport type { Bindings } from \"./mod\";\nimport { serializeKey, serializeNameAndKey } from \"./util\";\n\n// Actor metadata structure\ninterface ActorData {\n\tname: string;\n\tkey: string[];\n}\n\n// Key constants similar to Redis implementation\nconst KEYS = {\n\tACTOR: {\n\t\t// Combined key for actor metadata (name and key)\n\t\tmetadata: (actorId: string) => `actor:${actorId}:metadata`,\n\n\t\t// Key index function for actor lookup\n\t\tkeyIndex: (name: string, key: string[] = []) => {\n\t\t\t// Use serializeKey for consistent handling of all keys\n\t\t\treturn `actor_key:${serializeKey(key)}`;\n\t\t},\n\t},\n};\n\nconst STANDARD_WEBSOCKET_HEADERS = [\n\t\"connection\",\n\t\"upgrade\",\n\t\"sec-websocket-key\",\n\t\"sec-websocket-version\",\n\t\"sec-websocket-protocol\",\n\t\"sec-websocket-extensions\",\n];\n\nexport class CloudflareActorsManagerDriver implements ManagerDriver {\n\tasync sendRequest(actorId: string, actorRequest: Request): Promise<Response> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\tlogger().debug(\"sending request to durable object\", {\n\t\t\tactorId,\n\t\t\tmethod: actorRequest.method,\n\t\t\turl: actorRequest.url,\n\t\t});\n\n\t\tconst id = env.ACTOR_DO.idFromString(actorId);\n\t\tconst stub = env.ACTOR_DO.get(id);\n\n\t\treturn await stub.fetch(actorRequest);\n\t}\n\n\tasync openWebSocket(\n\t\tpath: string,\n\t\tactorId: string,\n\t\tencoding: Encoding,\n\t\tparams: unknown,\n\t): Promise<WebSocket> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\tlogger().debug(\"opening websocket to durable object\", { actorId, path });\n\n\t\t// Make a fetch request to the Durable Object with WebSocket upgrade\n\t\tconst id = env.ACTOR_DO.idFromString(actorId);\n\t\tconst stub = env.ACTOR_DO.get(id);\n\n\t\tconst headers: Record<string, string> = {\n\t\t\tUpgrade: \"websocket\",\n\t\t\tConnection: \"Upgrade\",\n\t\t\t[HEADER_EXPOSE_INTERNAL_ERROR]: \"true\",\n\t\t\t[HEADER_ENCODING]: encoding,\n\t\t};\n\t\tif (params) {\n\t\t\theaders[HEADER_CONN_PARAMS] = JSON.stringify(params);\n\t\t}\n\t\t// HACK: See packages/drivers/cloudflare-workers/src/websocket.ts\n\t\theaders[\"sec-websocket-protocol\"] = \"rivetkit\";\n\n\t\t// Use the path parameter to determine the URL\n\t\tconst url = `http://actor${path}`;\n\n\t\tlogger().debug(\"rewriting websocket url\", {\n\t\t\tfrom: path,\n\t\t\tto: url,\n\t\t});\n\n\t\tconst response = await stub.fetch(url, {\n\t\t\theaders,\n\t\t});\n\t\tconst webSocket = response.webSocket;\n\n\t\tif (!webSocket) {\n\t\t\tthrow new InternalError(\n\t\t\t\t\"missing websocket connection in response from DO\",\n\t\t\t);\n\t\t}\n\n\t\tlogger().debug(\"durable object websocket connection open\", {\n\t\t\tactorId,\n\t\t});\n\n\t\twebSocket.accept();\n\n\t\t// TODO: Is this still needed?\n\t\t// HACK: Cloudflare does not call onopen automatically, so we need\n\t\t// to call this on the next tick\n\t\tsetTimeout(() => {\n\t\t\tconst event = new Event(\"open\");\n\t\t\t(webSocket as any).onopen?.(event);\n\t\t\t(webSocket as any).dispatchEvent(event);\n\t\t}, 0);\n\n\t\treturn webSocket as unknown as WebSocket;\n\t}\n\n\tasync proxyRequest(\n\t\tc: HonoContext<{ Bindings: Bindings }>,\n\t\tactorRequest: Request,\n\t\tactorId: string,\n\t): Promise<Response> {\n\t\tlogger().debug(\"forwarding request to durable object\", {\n\t\t\tactorId,\n\t\t\tmethod: actorRequest.method,\n\t\t\turl: actorRequest.url,\n\t\t});\n\n\t\tconst id = c.env.ACTOR_DO.idFromString(actorId);\n\t\tconst stub = c.env.ACTOR_DO.get(id);\n\n\t\treturn await stub.fetch(actorRequest);\n\t}\n\n\tasync proxyWebSocket(\n\t\tc: HonoContext<{ Bindings: Bindings }>,\n\t\tpath: string,\n\t\tactorId: string,\n\t\tencoding: Encoding,\n\t\tparams: unknown,\n\t\tauthData: unknown,\n\t): Promise<Response> {\n\t\tlogger().debug(\"forwarding websocket to durable object\", {\n\t\t\tactorId,\n\t\t\tpath,\n\t\t});\n\n\t\t// Validate upgrade\n\t\tconst upgradeHeader = c.req.header(\"Upgrade\");\n\t\tif (!upgradeHeader || upgradeHeader !== \"websocket\") {\n\t\t\treturn new Response(\"Expected Upgrade: websocket\", {\n\t\t\t\tstatus: 426,\n\t\t\t});\n\t\t}\n\n\t\t// TODO: strip headers\n\t\tconst newUrl = new URL(`http://actor${path}`);\n\t\tconst actorRequest = new Request(newUrl, c.req.raw);\n\n\t\tlogger().debug(\"rewriting websocket url\", {\n\t\t\tfrom: c.req.url,\n\t\t\tto: actorRequest.url,\n\t\t});\n\n\t\t// Always build fresh request to prevent forwarding unwanted headers\n\t\t// HACK: Since we can't build a new request, we need to remove\n\t\t// non-standard headers manually\n\t\tconst headerKeys: string[] = [];\n\t\tactorRequest.headers.forEach((v, k) => headerKeys.push(k));\n\t\tfor (const k of headerKeys) {\n\t\t\tif (!STANDARD_WEBSOCKET_HEADERS.includes(k)) {\n\t\t\t\tactorRequest.headers.delete(k);\n\t\t\t}\n\t\t}\n\n\t\t// Add RivetKit headers\n\t\tactorRequest.headers.set(HEADER_EXPOSE_INTERNAL_ERROR, \"true\");\n\t\tactorRequest.headers.set(HEADER_ENCODING, encoding);\n\t\tif (params) {\n\t\t\tactorRequest.headers.set(HEADER_CONN_PARAMS, JSON.stringify(params));\n\t\t}\n\t\tif (authData) {\n\t\t\tactorRequest.headers.set(HEADER_AUTH_DATA, JSON.stringify(authData));\n\t\t}\n\n\t\tconst id = c.env.ACTOR_DO.idFromString(actorId);\n\t\tconst stub = c.env.ACTOR_DO.get(id);\n\n\t\treturn await stub.fetch(actorRequest);\n\t}\n\n\tasync getForId({\n\t\tc,\n\t\tactorId,\n\t}: GetForIdInput<{ Bindings: Bindings }>): Promise<ActorOutput | undefined> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\t// Get actor metadata from KV (combined name and key)\n\t\tconst actorData = (await env.ACTOR_KV.get(KEYS.ACTOR.metadata(actorId), {\n\t\t\ttype: \"json\",\n\t\t})) as ActorData | null;\n\n\t\t// If the actor doesn't exist, return undefined\n\t\tif (!actorData) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tactorId,\n\t\t\tname: actorData.name,\n\t\t\tkey: actorData.key,\n\t\t};\n\t}\n\n\tasync getWithKey({\n\t\tc,\n\t\tname,\n\t\tkey,\n\t}: GetWithKeyInput<{ Bindings: Bindings }>): Promise<\n\t\tActorOutput | undefined\n\t> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\tlogger().debug(\"getWithKey: searching for actor\", { name, key });\n\n\t\t// Generate deterministic ID from the name and key\n\t\t// This is aligned with how createActor generates IDs\n\t\tconst nameKeyString = serializeNameAndKey(name, key);\n\t\tconst actorId = env.ACTOR_DO.idFromName(nameKeyString).toString();\n\n\t\t// Check if the actor metadata exists\n\t\tconst actorData = await env.ACTOR_KV.get(KEYS.ACTOR.metadata(actorId), {\n\t\t\ttype: \"json\",\n\t\t});\n\n\t\tif (!actorData) {\n\t\t\tlogger().debug(\"getWithKey: no actor found with matching name and key\", {\n\t\t\t\tname,\n\t\t\t\tkey,\n\t\t\t\tactorId,\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\n\t\tlogger().debug(\"getWithKey: found actor with matching name and key\", {\n\t\t\tactorId,\n\t\t\tname,\n\t\t\tkey,\n\t\t});\n\t\treturn this.#buildActorOutput(c, actorId);\n\t}\n\n\tasync getOrCreateWithKey(\n\t\tinput: GetOrCreateWithKeyInput,\n\t): Promise<ActorOutput> {\n\t\t// TODO: Prevent race condition here\n\t\tconst getOutput = await this.getWithKey(input);\n\t\tif (getOutput) {\n\t\t\treturn getOutput;\n\t\t} else {\n\t\t\treturn await this.createActor(input);\n\t\t}\n\t}\n\n\tasync createActor({\n\t\tc,\n\t\tname,\n\t\tkey,\n\t\tinput,\n\t}: CreateInput<{ Bindings: Bindings }>): Promise<ActorOutput> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\t// Check if actor with the same name and key already exists\n\t\tconst existingActor = await this.getWithKey({ c, name, key });\n\t\tif (existingActor) {\n\t\t\tthrow new ActorAlreadyExists(name, key);\n\t\t}\n\n\t\t// Create a deterministic ID from the actor name and key\n\t\t// This ensures that actors with the same name and key will have the same ID\n\t\tconst nameKeyString = serializeNameAndKey(name, key);\n\t\tconst doId = env.ACTOR_DO.idFromName(nameKeyString);\n\t\tconst actorId = doId.toString();\n\n\t\t// Init actor\n\t\tconst actor = env.ACTOR_DO.get(doId);\n\t\tawait actor.initialize({\n\t\t\tname,\n\t\t\tkey,\n\t\t\tinput,\n\t\t});\n\n\t\t// Store combined actor metadata (name and key)\n\t\tconst actorData: ActorData = { name, key };\n\t\tawait env.ACTOR_KV.put(\n\t\t\tKEYS.ACTOR.metadata(actorId),\n\t\t\tJSON.stringify(actorData),\n\t\t);\n\n\t\t// Add to key index for lookups by name and key\n\t\tawait env.ACTOR_KV.put(KEYS.ACTOR.keyIndex(name, key), actorId);\n\n\t\treturn {\n\t\t\tactorId,\n\t\t\tname,\n\t\t\tkey,\n\t\t};\n\t}\n\n\t// Helper method to build actor output from an ID\n\tasync #buildActorOutput(\n\t\tc: any,\n\t\tactorId: string,\n\t): Promise<ActorOutput | undefined> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\tconst actorData = (await env.ACTOR_KV.get(KEYS.ACTOR.metadata(actorId), {\n\t\t\ttype: \"json\",\n\t\t})) as ActorData | null;\n\n\t\tif (!actorData) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tactorId,\n\t\t\tname: actorData.name,\n\t\t\tkey: actorData.key,\n\t\t};\n\t}\n}\n","// Constants for key handling\nexport const EMPTY_KEY = \"(none)\";\nexport const KEY_SEPARATOR = \",\";\n\n/**\n * Serializes an array of key strings into a single string for use with idFromName\n *\n * @param name The actor name\n * @param key Array of key strings to serialize\n * @returns A single string containing the serialized name and key\n */\nexport function serializeNameAndKey(name: string, key: string[]): string {\n\t// Escape colons in the name\n\tconst escapedName = name.replace(/:/g, \"\\\\:\");\n\n\t// For empty keys, just return the name and a marker\n\tif (key.length === 0) {\n\t\treturn `${escapedName}:${EMPTY_KEY}`;\n\t}\n\n\t// Serialize the key array\n\tconst serializedKey = serializeKey(key);\n\n\t// Combine name and serialized key\n\treturn `${escapedName}:${serializedKey}`;\n}\n\n/**\n * Serializes an array of key strings into a single string\n *\n * @param key Array of key strings to serialize\n * @returns A single string containing the serialized key\n */\nexport function serializeKey(key: string[]): string {\n\t// Use a special marker for empty key arrays\n\tif (key.length === 0) {\n\t\treturn EMPTY_KEY;\n\t}\n\n\t// Escape each key part to handle the separator and the empty key marker\n\tconst escapedParts = key.map((part) => {\n\t\t// First check if it matches our empty key marker\n\t\tif (part === EMPTY_KEY) {\n\t\t\treturn `\\\\${EMPTY_KEY}`;\n\t\t}\n\n\t\t// Escape backslashes first, then commas\n\t\tlet escaped = part.replace(/\\\\/g, \"\\\\\\\\\");\n\t\tescaped = escaped.replace(/,/g, \"\\\\,\");\n\t\treturn escaped;\n\t});\n\n\treturn escapedParts.join(KEY_SEPARATOR);\n}\n\n/**\n * Deserializes a key string back into an array of key strings\n *\n * @param keyString The serialized key string\n * @returns Array of key strings\n */\nexport function deserializeKey(keyString: string): string[] {\n\t// Handle empty values\n\tif (!keyString) {\n\t\treturn [];\n\t}\n\n\t// Check for special empty key marker\n\tif (keyString === EMPTY_KEY) {\n\t\treturn [];\n\t}\n\n\t// Split by unescaped commas and unescape the escaped characters\n\tconst parts: string[] = [];\n\tlet currentPart = \"\";\n\tlet escaping = false;\n\n\tfor (let i = 0; i < keyString.length; i++) {\n\t\tconst char = keyString[i];\n\n\t\tif (escaping) {\n\t\t\t// This is an escaped character, add it directly\n\t\t\tcurrentPart += char;\n\t\t\tescaping = false;\n\t\t} else if (char === \"\\\\\") {\n\t\t\t// Start of an escape sequence\n\t\t\tescaping = true;\n\t\t} else if (char === KEY_SEPARATOR) {\n\t\t\t// This is a separator\n\t\t\tparts.push(currentPart);\n\t\t\tcurrentPart = \"\";\n\t\t} else {\n\t\t\t// Regular character\n\t\t\tcurrentPart += char;\n\t\t}\n\t}\n\n\t// Add the last part if it exists\n\tif (currentPart || parts.length > 0) {\n\t\tparts.push(currentPart);\n\t}\n\n\treturn parts;\n}\n","// Modified from https://github.com/honojs/hono/blob/40ea0eee58e39b31053a0246c595434f1094ad31/src/adapter/cloudflare-workers/websocket.ts#L17\n//\n// This version calls the open event by default\n\nimport type { UpgradeWebSocket, WSEvents, WSReadyState } from \"hono/ws\";\nimport { defineWebSocketHelper, WSContext } from \"hono/ws\";\n\n// Based on https://github.com/honojs/hono/issues/1153#issuecomment-1767321332\nexport const upgradeWebSocket: UpgradeWebSocket<\n\tWebSocket,\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tany,\n\tWSEvents<WebSocket>\n> = defineWebSocketHelper(async (c, events) => {\n\tconst upgradeHeader = c.req.header(\"Upgrade\");\n\tif (upgradeHeader !== \"websocket\") {\n\t\treturn;\n\t}\n\n\tconst webSocketPair = new WebSocketPair();\n\tconst client: WebSocket = webSocketPair[0];\n\tconst server: WebSocket = webSocketPair[1];\n\n\tconst wsContext = new WSContext<WebSocket>({\n\t\tclose: (code, reason) => server.close(code, reason),\n\t\tget protocol() {\n\t\t\treturn server.protocol;\n\t\t},\n\t\traw: server,\n\t\tget readyState() {\n\t\t\treturn server.readyState as WSReadyState;\n\t\t},\n\t\turl: server.url ? new URL(server.url) : null,\n\t\tsend: (source) => server.send(source),\n\t});\n\n\tif (events.onClose) {\n\t\tserver.addEventListener(\"close\", (evt: CloseEvent) =>\n\t\t\tevents.onClose?.(evt, wsContext),\n\t\t);\n\t}\n\tif (events.onMessage) {\n\t\tserver.addEventListener(\"message\", (evt: MessageEvent) =>\n\t\t\tevents.onMessage?.(evt, wsContext),\n\t\t);\n\t}\n\tif (events.onError) {\n\t\tserver.addEventListener(\"error\", (evt: Event) =>\n\t\t\tevents.onError?.(evt, wsContext),\n\t\t);\n\t}\n\n\tserver.accept?.();\n\n\t// note: cloudflare actors doesn't support 'open' event, so we call it immediately with a fake event\n\t//\n\t// we have to do this after `server.accept() is called`\n\tevents.onOpen?.(new Event(\"open\"), wsContext);\n\n\treturn new Response(null, {\n\t\tstatus: 101,\n\t\theaders: {\n\t\t\t// HACK: Required in order for Cloudflare to not error with \"Network connection lost\"\n\t\t\t//\n\t\t\t// This bug undocumented. Cannot easily reproduce outside of RivetKit.\n\t\t\t\"Sec-WebSocket-Protocol\": \"rivetkit\",\n\t\t},\n\t\twebSocket: client,\n\t});\n});\n"]}
package/dist/mod.d.cts CHANGED
@@ -9,6 +9,10 @@ import { z } from 'zod';
9
9
  import { Client } from '@rivetkit/core/client';
10
10
  import { DurableObject } from 'cloudflare:workers';
11
11
 
12
+ interface DriverContext {
13
+ state: DurableObjectState;
14
+ }
15
+
12
16
  declare const ConfigSchema: z.ZodDefault<z.ZodObject<Omit<{
13
17
  driver: z.ZodDefault<z.ZodOptional<z.ZodObject<{
14
18
  name: z.ZodString;
@@ -84,6 +88,7 @@ declare const ConfigSchema: z.ZodDefault<z.ZodObject<Omit<{
84
88
  token?: ((...args: unknown[]) => string) | undefined;
85
89
  defaultEndpoint?: string | undefined;
86
90
  }>>>;
91
+ basePath: z.ZodDefault<z.ZodOptional<z.ZodString>>;
87
92
  }, "driver" | "getUpgradeWebSocket"> & {
88
93
  app: z.ZodOptional<z.ZodType<Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">, z.ZodTypeDef, Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">>>;
89
94
  }, "strip", z.ZodTypeAny, {
@@ -101,6 +106,7 @@ declare const ConfigSchema: z.ZodDefault<z.ZodObject<Omit<{
101
106
  token: (...args: unknown[]) => string;
102
107
  defaultEndpoint?: string | undefined;
103
108
  };
109
+ basePath: string;
104
110
  cors?: {
105
111
  origin: string | string[] | ((origin: string, c: hono.Context) => string | undefined | null);
106
112
  allowMethods?: string[] | ((origin: string, c: hono.Context) => string[]);
@@ -133,6 +139,7 @@ declare const ConfigSchema: z.ZodDefault<z.ZodObject<Omit<{
133
139
  token?: ((...args: unknown[]) => string) | undefined;
134
140
  defaultEndpoint?: string | undefined;
135
141
  } | undefined;
142
+ basePath?: string | undefined;
136
143
  app?: Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/"> | undefined;
137
144
  }>>;
138
145
  type InputConfig = z.input<typeof ConfigSchema>;
@@ -163,4 +170,4 @@ interface SetupOutput<A extends Registry<any>> {
163
170
  declare function createServerHandler<R extends Registry<any>>(registry: R, inputConfig?: InputConfig): Handler;
164
171
  declare function createServer<R extends Registry<any>>(registry: R, inputConfig?: InputConfig): SetupOutput<R>;
165
172
 
166
- export { type Bindings, type InputConfig as Config, createServer, createServerHandler };
173
+ export { type Bindings, type InputConfig as Config, type DriverContext, createServer, createServerHandler };
package/dist/mod.d.ts CHANGED
@@ -9,6 +9,10 @@ import { z } from 'zod';
9
9
  import { Client } from '@rivetkit/core/client';
10
10
  import { DurableObject } from 'cloudflare:workers';
11
11
 
12
+ interface DriverContext {
13
+ state: DurableObjectState;
14
+ }
15
+
12
16
  declare const ConfigSchema: z.ZodDefault<z.ZodObject<Omit<{
13
17
  driver: z.ZodDefault<z.ZodOptional<z.ZodObject<{
14
18
  name: z.ZodString;
@@ -84,6 +88,7 @@ declare const ConfigSchema: z.ZodDefault<z.ZodObject<Omit<{
84
88
  token?: ((...args: unknown[]) => string) | undefined;
85
89
  defaultEndpoint?: string | undefined;
86
90
  }>>>;
91
+ basePath: z.ZodDefault<z.ZodOptional<z.ZodString>>;
87
92
  }, "driver" | "getUpgradeWebSocket"> & {
88
93
  app: z.ZodOptional<z.ZodType<Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">, z.ZodTypeDef, Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">>>;
89
94
  }, "strip", z.ZodTypeAny, {
@@ -101,6 +106,7 @@ declare const ConfigSchema: z.ZodDefault<z.ZodObject<Omit<{
101
106
  token: (...args: unknown[]) => string;
102
107
  defaultEndpoint?: string | undefined;
103
108
  };
109
+ basePath: string;
104
110
  cors?: {
105
111
  origin: string | string[] | ((origin: string, c: hono.Context) => string | undefined | null);
106
112
  allowMethods?: string[] | ((origin: string, c: hono.Context) => string[]);
@@ -133,6 +139,7 @@ declare const ConfigSchema: z.ZodDefault<z.ZodObject<Omit<{
133
139
  token?: ((...args: unknown[]) => string) | undefined;
134
140
  defaultEndpoint?: string | undefined;
135
141
  } | undefined;
142
+ basePath?: string | undefined;
136
143
  app?: Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/"> | undefined;
137
144
  }>>;
138
145
  type InputConfig = z.input<typeof ConfigSchema>;
@@ -163,4 +170,4 @@ interface SetupOutput<A extends Registry<any>> {
163
170
  declare function createServerHandler<R extends Registry<any>>(registry: R, inputConfig?: InputConfig): Handler;
164
171
  declare function createServer<R extends Registry<any>>(registry: R, inputConfig?: InputConfig): SetupOutput<R>;
165
172
 
166
- export { type Bindings, type InputConfig as Config, createServer, createServerHandler };
173
+ export { type Bindings, type InputConfig as Config, type DriverContext, createServer, createServerHandler };
package/dist/mod.js CHANGED
@@ -1,10 +1,9 @@
1
1
  // src/handler.ts
2
- import { AsyncLocalStorage } from "async_hooks";
2
+ import { env as env2 } from "cloudflare:workers";
3
3
  import { Hono } from "hono";
4
- import invariant2 from "invariant";
5
4
 
6
5
  // src/actor-handler-do.ts
7
- import { DurableObject } from "cloudflare:workers";
6
+ import { DurableObject, env } from "cloudflare:workers";
8
7
  import {
9
8
  createActorRouter,
10
9
  createClientWithDriver,
@@ -103,7 +102,7 @@ var CloudflareActorsActorDriver = class {
103
102
  }
104
103
  getContext(actorId) {
105
104
  const state = this.#globalState.getDOState(actorId);
106
- return { ctx: state.ctx, env: state.env };
105
+ return { state: state.ctx };
107
106
  }
108
107
  async readPersistedData(actorId) {
109
108
  return await this.#getDOCtx(actorId).storage.get(KEYS.PERSIST_DATA);
@@ -178,7 +177,7 @@ function createActorDurableObject(registry, runConfig) {
178
177
  }
179
178
  if (!this.#initialized) throw new Error("Not initialized");
180
179
  const actorId = this.ctx.id.toString();
181
- globalState.setDOState(actorId, { ctx: this.ctx, env: this.env });
180
+ globalState.setDOState(actorId, { ctx: this.ctx, env });
182
181
  runConfig.driver.actor = createCloudflareActorsActorDriverBuilder(globalState);
183
182
  const managerDriver = runConfig.driver.manager(
184
183
  registry.config,
@@ -202,49 +201,43 @@ function createActorDurableObject(registry, runConfig) {
202
201
  }
203
202
  /** RPC called by the service that creates the DO to initialize it. */
204
203
  async initialize(req) {
205
- return await CF_AMBIENT_ENV.run(this.env, async () => {
206
- await this.ctx.storage.put({
207
- [KEYS.NAME]: req.name,
208
- [KEYS.KEY]: req.key,
209
- [KEYS.PERSIST_DATA]: serializeEmptyPersistData(req.input)
210
- });
211
- this.#initialized = {
212
- name: req.name,
213
- key: req.key
214
- };
215
- logger().debug("initialized actor", { key: req.key });
216
- await this.#loadActor();
204
+ await this.ctx.storage.put({
205
+ [KEYS.NAME]: req.name,
206
+ [KEYS.KEY]: req.key,
207
+ [KEYS.PERSIST_DATA]: serializeEmptyPersistData(req.input)
217
208
  });
209
+ this.#initialized = {
210
+ name: req.name,
211
+ key: req.key
212
+ };
213
+ logger().debug("initialized actor", { key: req.key });
214
+ await this.#loadActor();
218
215
  }
219
216
  async fetch(request) {
220
- return await CF_AMBIENT_ENV.run(this.env, async () => {
221
- const { actorRouter } = await this.#loadActor();
222
- const actorId = this.ctx.id.toString();
223
- return await actorRouter.fetch(request, {
224
- actorId
225
- });
217
+ const { actorRouter } = await this.#loadActor();
218
+ const actorId = this.ctx.id.toString();
219
+ return await actorRouter.fetch(request, {
220
+ actorId
226
221
  });
227
222
  }
228
223
  async alarm() {
229
- return await CF_AMBIENT_ENV.run(this.env, async () => {
230
- await this.#loadActor();
231
- const actorId = this.ctx.id.toString();
232
- const managerDriver = runConfig.driver.manager(
233
- registry.config,
234
- runConfig
235
- );
236
- const inlineClient = createClientWithDriver(
237
- createInlineClientDriver(managerDriver)
238
- );
239
- const actorDriver = runConfig.driver.actor(
240
- registry.config,
241
- runConfig,
242
- managerDriver,
243
- inlineClient
244
- );
245
- const actor = await actorDriver.loadActor(actorId);
246
- await actor.onAlarm();
247
- });
224
+ await this.#loadActor();
225
+ const actorId = this.ctx.id.toString();
226
+ const managerDriver = runConfig.driver.manager(
227
+ registry.config,
228
+ runConfig
229
+ );
230
+ const inlineClient = createClientWithDriver(
231
+ createInlineClientDriver(managerDriver)
232
+ );
233
+ const actorDriver = runConfig.driver.actor(
234
+ registry.config,
235
+ runConfig,
236
+ managerDriver,
237
+ inlineClient
238
+ );
239
+ const actor = await actorDriver.loadActor(actorId);
240
+ await actor.onAlarm();
248
241
  }
249
242
  };
250
243
  }
@@ -312,21 +305,21 @@ var STANDARD_WEBSOCKET_HEADERS = [
312
305
  ];
313
306
  var CloudflareActorsManagerDriver = class {
314
307
  async sendRequest(actorId, actorRequest) {
315
- const env = getCloudflareAmbientEnv();
308
+ const env3 = getCloudflareAmbientEnv();
316
309
  logger().debug("sending request to durable object", {
317
310
  actorId,
318
311
  method: actorRequest.method,
319
312
  url: actorRequest.url
320
313
  });
321
- const id = env.ACTOR_DO.idFromString(actorId);
322
- const stub = env.ACTOR_DO.get(id);
314
+ const id = env3.ACTOR_DO.idFromString(actorId);
315
+ const stub = env3.ACTOR_DO.get(id);
323
316
  return await stub.fetch(actorRequest);
324
317
  }
325
318
  async openWebSocket(path, actorId, encoding, params) {
326
- const env = getCloudflareAmbientEnv();
319
+ const env3 = getCloudflareAmbientEnv();
327
320
  logger().debug("opening websocket to durable object", { actorId, path });
328
- const id = env.ACTOR_DO.idFromString(actorId);
329
- const stub = env.ACTOR_DO.get(id);
321
+ const id = env3.ACTOR_DO.idFromString(actorId);
322
+ const stub = env3.ACTOR_DO.get(id);
330
323
  const headers = {
331
324
  Upgrade: "websocket",
332
325
  Connection: "Upgrade",
@@ -413,8 +406,8 @@ var CloudflareActorsManagerDriver = class {
413
406
  c,
414
407
  actorId
415
408
  }) {
416
- const env = getCloudflareAmbientEnv();
417
- const actorData = await env.ACTOR_KV.get(KEYS2.ACTOR.metadata(actorId), {
409
+ const env3 = getCloudflareAmbientEnv();
410
+ const actorData = await env3.ACTOR_KV.get(KEYS2.ACTOR.metadata(actorId), {
418
411
  type: "json"
419
412
  });
420
413
  if (!actorData) {
@@ -431,11 +424,11 @@ var CloudflareActorsManagerDriver = class {
431
424
  name,
432
425
  key
433
426
  }) {
434
- const env = getCloudflareAmbientEnv();
427
+ const env3 = getCloudflareAmbientEnv();
435
428
  logger().debug("getWithKey: searching for actor", { name, key });
436
429
  const nameKeyString = serializeNameAndKey(name, key);
437
- const actorId = env.ACTOR_DO.idFromName(nameKeyString).toString();
438
- const actorData = await env.ACTOR_KV.get(KEYS2.ACTOR.metadata(actorId), {
430
+ const actorId = env3.ACTOR_DO.idFromName(nameKeyString).toString();
431
+ const actorData = await env3.ACTOR_KV.get(KEYS2.ACTOR.metadata(actorId), {
439
432
  type: "json"
440
433
  });
441
434
  if (!actorData) {
@@ -467,26 +460,26 @@ var CloudflareActorsManagerDriver = class {
467
460
  key,
468
461
  input
469
462
  }) {
470
- const env = getCloudflareAmbientEnv();
463
+ const env3 = getCloudflareAmbientEnv();
471
464
  const existingActor = await this.getWithKey({ c, name, key });
472
465
  if (existingActor) {
473
466
  throw new ActorAlreadyExists(name, key);
474
467
  }
475
468
  const nameKeyString = serializeNameAndKey(name, key);
476
- const doId = env.ACTOR_DO.idFromName(nameKeyString);
469
+ const doId = env3.ACTOR_DO.idFromName(nameKeyString);
477
470
  const actorId = doId.toString();
478
- const actor = env.ACTOR_DO.get(doId);
471
+ const actor = env3.ACTOR_DO.get(doId);
479
472
  await actor.initialize({
480
473
  name,
481
474
  key,
482
475
  input
483
476
  });
484
477
  const actorData = { name, key };
485
- await env.ACTOR_KV.put(
478
+ await env3.ACTOR_KV.put(
486
479
  KEYS2.ACTOR.metadata(actorId),
487
480
  JSON.stringify(actorData)
488
481
  );
489
- await env.ACTOR_KV.put(KEYS2.ACTOR.keyIndex(name, key), actorId);
482
+ await env3.ACTOR_KV.put(KEYS2.ACTOR.keyIndex(name, key), actorId);
490
483
  return {
491
484
  actorId,
492
485
  name,
@@ -495,8 +488,8 @@ var CloudflareActorsManagerDriver = class {
495
488
  }
496
489
  // Helper method to build actor output from an ID
497
490
  async #buildActorOutput(c, actorId) {
498
- const env = getCloudflareAmbientEnv();
499
- const actorData = await env.ACTOR_KV.get(KEYS2.ACTOR.metadata(actorId), {
491
+ const env3 = getCloudflareAmbientEnv();
492
+ const actorData = await env3.ACTOR_KV.get(KEYS2.ACTOR.metadata(actorId), {
500
493
  type: "json"
501
494
  });
502
495
  if (!actorData) {
@@ -575,11 +568,8 @@ var upgradeWebSocket = defineWebSocketHelper(async (c, events) => {
575
568
  });
576
569
 
577
570
  // src/handler.ts
578
- var CF_AMBIENT_ENV = new AsyncLocalStorage();
579
571
  function getCloudflareAmbientEnv() {
580
- const env = CF_AMBIENT_ENV.getStore();
581
- invariant2(env, "missing CF_AMBIENT_ENV");
582
- return env;
572
+ return env2;
583
573
  }
584
574
  function createServerHandler(registry, inputConfig) {
585
575
  const { createHandler } = createServer(registry, inputConfig);
@@ -607,8 +597,8 @@ function createServer(registry, inputConfig) {
607
597
  app.route("/registry", serverOutput.hono);
608
598
  }
609
599
  const handler = {
610
- fetch: (request, env, ctx) => {
611
- return CF_AMBIENT_ENV.run(env, () => app.fetch(request, env, ctx));
600
+ fetch: (request, env3, ctx) => {
601
+ return app.fetch(request, env3, ctx);
612
602
  }
613
603
  };
614
604
  return { handler, ActorHandler: ActorHandler2 };
package/dist/mod.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/handler.ts","../src/actor-handler-do.ts","../src/actor-driver.ts","../src/log.ts","../src/config.ts","../src/manager-driver.ts","../src/util.ts","../src/websocket.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { Registry, RunConfig } from \"@rivetkit/core\";\nimport type { Client } from \"@rivetkit/core/client\";\nimport { Hono } from \"hono\";\nimport invariant from \"invariant\";\nimport {\n\ttype ActorHandlerInterface,\n\tcreateActorDurableObject,\n\ttype DurableObjectConstructor,\n} from \"./actor-handler-do\";\nimport { ConfigSchema, type InputConfig } from \"./config\";\nimport { CloudflareActorsManagerDriver } from \"./manager-driver\";\nimport { upgradeWebSocket } from \"./websocket\";\n\n/** Cloudflare Workers env */\nexport interface Bindings {\n\tACTOR_KV: KVNamespace;\n\tACTOR_DO: DurableObjectNamespace<ActorHandlerInterface>;\n}\n\n/**\n * Stores the env for the current request. Required since some contexts like the inline client driver does not have access to the Hono context.\n *\n * Use getCloudflareAmbientEnv unless using CF_AMBIENT_ENV.run.\n */\nexport const CF_AMBIENT_ENV = new AsyncLocalStorage<Bindings>();\n\nexport function getCloudflareAmbientEnv(): Bindings {\n\tconst env = CF_AMBIENT_ENV.getStore();\n\tinvariant(env, \"missing CF_AMBIENT_ENV\");\n\treturn env;\n}\n\ninterface Handler {\n\thandler: ExportedHandler<Bindings>;\n\tActorHandler: DurableObjectConstructor;\n}\n\ninterface SetupOutput<A extends Registry<any>> {\n\tclient: Client<A>;\n\tcreateHandler: (hono?: Hono) => Handler;\n}\n\nexport function createServerHandler<R extends Registry<any>>(\n\tregistry: R,\n\tinputConfig?: InputConfig,\n): Handler {\n\tconst { createHandler } = createServer(registry, inputConfig);\n\treturn createHandler();\n}\n\nexport function createServer<R extends Registry<any>>(\n\tregistry: R,\n\tinputConfig?: InputConfig,\n): SetupOutput<R> {\n\tconst config = ConfigSchema.parse(inputConfig);\n\n\t// Create config\n\tconst runConfig = {\n\t\tdriver: {\n\t\t\tname: \"cloudflare-workers\",\n\t\t\tmanager: () => new CloudflareActorsManagerDriver(),\n\t\t\t// HACK: We can't build the actor driver until we're inside the Durable Object\n\t\t\tactor: undefined as any,\n\t\t},\n\t\tgetUpgradeWebSocket: () => upgradeWebSocket,\n\t\t...config,\n\t} satisfies RunConfig;\n\n\t// Create Durable Object\n\tconst ActorHandler = createActorDurableObject(registry, runConfig);\n\n\t// Create server\n\tconst serverOutput = registry.createServer(runConfig);\n\n\treturn {\n\t\tclient: serverOutput.client as Client<R>,\n\t\tcreateHandler: (hono) => {\n\t\t\t// Build base router\n\t\t\tconst app = hono ?? new Hono();\n\n\t\t\t// Mount registry router at /registry\n\t\t\tif (!hono) {\n\t\t\t\tapp.route(\"/registry\", serverOutput.hono);\n\t\t\t}\n\n\t\t\t// Create Cloudflare handler\n\t\t\tconst handler = {\n\t\t\t\tfetch: (request, env, ctx) => {\n\t\t\t\t\treturn CF_AMBIENT_ENV.run(env, () => app.fetch(request, env, ctx));\n\t\t\t\t},\n\t\t\t} satisfies ExportedHandler<Bindings>;\n\n\t\t\treturn { handler, ActorHandler };\n\t\t},\n\t};\n}\n","import { DurableObject } from \"cloudflare:workers\";\nimport type {\n\tActorKey,\n\tActorRouter,\n\tRegistry,\n\tRunConfig,\n} from \"@rivetkit/core\";\nimport {\n\tcreateActorRouter,\n\tcreateClientWithDriver,\n\tcreateInlineClientDriver,\n} from \"@rivetkit/core\";\nimport { serializeEmptyPersistData } from \"@rivetkit/core/driver-helpers\";\nimport type { ExecutionContext } from \"hono\";\nimport {\n\tCloudflareDurableObjectGlobalState,\n\tcreateCloudflareActorsActorDriverBuilder,\n} from \"./actor-driver\";\nimport { type Bindings, CF_AMBIENT_ENV } from \"./handler\";\nimport { logger } from \"./log\";\n\nexport const KEYS = {\n\tNAME: \"rivetkit:name\",\n\tKEY: \"rivetkit:key\",\n\tPERSIST_DATA: \"rivetkit:data\",\n};\n\nexport interface ActorHandlerInterface extends DurableObject {\n\tinitialize(req: ActorInitRequest): Promise<void>;\n}\n\nexport interface ActorInitRequest {\n\tname: string;\n\tkey: ActorKey;\n\tinput?: unknown;\n}\n\ninterface InitializedData {\n\tname: string;\n\tkey: ActorKey;\n}\n\nexport type DurableObjectConstructor = new (\n\t...args: ConstructorParameters<typeof DurableObject<Bindings>>\n) => DurableObject<Bindings>;\n\ninterface LoadedActor {\n\tactorRouter: ActorRouter;\n}\n\nexport function createActorDurableObject(\n\tregistry: Registry<any>,\n\trunConfig: RunConfig,\n): DurableObjectConstructor {\n\tconst globalState = new CloudflareDurableObjectGlobalState();\n\n\t/**\n\t * Startup steps:\n\t * 1. If not already created call `initialize`, otherwise check KV to ensure it's initialized\n\t * 2. Load actor\n\t * 3. Start service requests\n\t */\n\treturn class ActorHandler\n\t\textends DurableObject<Bindings>\n\t\timplements ActorHandlerInterface\n\t{\n\t\t#initialized?: InitializedData;\n\t\t#initializedPromise?: PromiseWithResolvers<void>;\n\n\t\t#actor?: LoadedActor;\n\n\t\tasync #loadActor(): Promise<LoadedActor> {\n\t\t\t// This is always called from another context using CF_AMBIENT_ENV\n\n\t\t\t// Wait for init\n\t\t\tif (!this.#initialized) {\n\t\t\t\t// Wait for init\n\t\t\t\tif (this.#initializedPromise) {\n\t\t\t\t\tawait this.#initializedPromise.promise;\n\t\t\t\t} else {\n\t\t\t\t\tthis.#initializedPromise = Promise.withResolvers();\n\t\t\t\t\tconst res = await this.ctx.storage.get([\n\t\t\t\t\t\tKEYS.NAME,\n\t\t\t\t\t\tKEYS.KEY,\n\t\t\t\t\t\tKEYS.PERSIST_DATA,\n\t\t\t\t\t]);\n\t\t\t\t\tif (res.get(KEYS.PERSIST_DATA)) {\n\t\t\t\t\t\tconst name = res.get(KEYS.NAME) as string;\n\t\t\t\t\t\tif (!name) throw new Error(\"missing actor name\");\n\t\t\t\t\t\tconst key = res.get(KEYS.KEY) as ActorKey;\n\t\t\t\t\t\tif (!key) throw new Error(\"missing actor key\");\n\n\t\t\t\t\t\tlogger().debug(\"already initialized\", { name, key });\n\n\t\t\t\t\t\tthis.#initialized = { name, key };\n\t\t\t\t\t\tthis.#initializedPromise.resolve();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger().debug(\"waiting to initialize\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check if already loaded\n\t\t\tif (this.#actor) {\n\t\t\t\treturn this.#actor;\n\t\t\t}\n\n\t\t\tif (!this.#initialized) throw new Error(\"Not initialized\");\n\n\t\t\t// Register DO with global state first\n\t\t\t// HACK: This leaks the DO context, but DO does not provide a native way\n\t\t\t// of knowing when the DO shuts down. We're making a broad assumption\n\t\t\t// that DO will boot a new isolate frequenlty enough that this is not an issue.\n\t\t\tconst actorId = this.ctx.id.toString();\n\t\t\tglobalState.setDOState(actorId, { ctx: this.ctx, env: this.env });\n\n\t\t\t// Configure actor driver\n\t\t\trunConfig.driver.actor =\n\t\t\t\tcreateCloudflareActorsActorDriverBuilder(globalState);\n\n\t\t\t// Create manager driver (we need this for the actor router)\n\t\t\tconst managerDriver = runConfig.driver.manager(\n\t\t\t\tregistry.config,\n\t\t\t\trunConfig,\n\t\t\t);\n\n\t\t\t// Create inline client\n\t\t\tconst inlineClient = createClientWithDriver(\n\t\t\t\tcreateInlineClientDriver(managerDriver),\n\t\t\t);\n\n\t\t\t// Create actor driver\n\t\t\tconst actorDriver = runConfig.driver.actor(\n\t\t\t\tregistry.config,\n\t\t\t\trunConfig,\n\t\t\t\tmanagerDriver,\n\t\t\t\tinlineClient,\n\t\t\t);\n\n\t\t\t// Create actor router\n\t\t\tconst actorRouter = createActorRouter(runConfig, actorDriver);\n\n\t\t\t// Save actor\n\t\t\tthis.#actor = {\n\t\t\t\tactorRouter,\n\t\t\t};\n\n\t\t\t// Initialize the actor instance with proper metadata\n\t\t\t// This ensures the actor driver knows about this actor\n\t\t\tawait actorDriver.loadActor(actorId);\n\n\t\t\treturn this.#actor;\n\t\t}\n\n\t\t/** RPC called by the service that creates the DO to initialize it. */\n\t\tasync initialize(req: ActorInitRequest) {\n\t\t\t// TODO: Need to add this to a core promise that needs to be resolved before start\n\n\t\t\treturn await CF_AMBIENT_ENV.run(this.env, async () => {\n\t\t\t\tawait this.ctx.storage.put({\n\t\t\t\t\t[KEYS.NAME]: req.name,\n\t\t\t\t\t[KEYS.KEY]: req.key,\n\t\t\t\t\t[KEYS.PERSIST_DATA]: serializeEmptyPersistData(req.input),\n\t\t\t\t});\n\t\t\t\tthis.#initialized = {\n\t\t\t\t\tname: req.name,\n\t\t\t\t\tkey: req.key,\n\t\t\t\t};\n\n\t\t\t\tlogger().debug(\"initialized actor\", { key: req.key });\n\n\t\t\t\t// Preemptively actor so the lifecycle hooks are called\n\t\t\t\tawait this.#loadActor();\n\t\t\t});\n\t\t}\n\n\t\tasync fetch(request: Request): Promise<Response> {\n\t\t\treturn await CF_AMBIENT_ENV.run(this.env, async () => {\n\t\t\t\tconst { actorRouter } = await this.#loadActor();\n\n\t\t\t\tconst actorId = this.ctx.id.toString();\n\t\t\t\treturn await actorRouter.fetch(request, {\n\t\t\t\t\tactorId,\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\t\tasync alarm(): Promise<void> {\n\t\t\treturn await CF_AMBIENT_ENV.run(this.env, async () => {\n\t\t\t\tawait this.#loadActor();\n\t\t\t\tconst actorId = this.ctx.id.toString();\n\n\t\t\t\t// Get the actor driver\n\t\t\t\tconst managerDriver = runConfig.driver.manager(\n\t\t\t\t\tregistry.config,\n\t\t\t\t\trunConfig,\n\t\t\t\t);\n\t\t\t\tconst inlineClient = createClientWithDriver(\n\t\t\t\t\tcreateInlineClientDriver(managerDriver),\n\t\t\t\t);\n\t\t\t\tconst actorDriver = runConfig.driver.actor(\n\t\t\t\t\tregistry.config,\n\t\t\t\t\trunConfig,\n\t\t\t\t\tmanagerDriver,\n\t\t\t\t\tinlineClient,\n\t\t\t\t);\n\n\t\t\t\t// Load the actor instance and trigger alarm\n\t\t\t\tconst actor = await actorDriver.loadActor(actorId);\n\t\t\t\tawait actor.onAlarm();\n\t\t\t});\n\t\t}\n\t};\n}\n","import type {\n\tAnyActorInstance as CoreAnyActorInstance,\n\tRegistryConfig,\n\tRunConfig,\n} from \"@rivetkit/core\";\nimport {\n\tcreateGenericConnDrivers,\n\tGenericConnGlobalState,\n\tlookupInRegistry,\n} from \"@rivetkit/core\";\nimport type { Client } from \"@rivetkit/core/client\";\nimport type {\n\tActorDriver,\n\tAnyActorInstance,\n\tManagerDriver,\n} from \"@rivetkit/core/driver-helpers\";\nimport invariant from \"invariant\";\nimport { KEYS } from \"./actor-handler-do\";\n\ninterface DurableObjectGlobalState {\n\tctx: DurableObjectState;\n\tenv: unknown;\n}\n\n/**\n * Cloudflare DO can have multiple DO running within the same global scope.\n *\n * This allows for storing the actor context globally and looking it up by ID in `CloudflareActorsActorDriver`.\n */\nexport class CloudflareDurableObjectGlobalState {\n\t// Single map for all actor state\n\t#dos: Map<string, DurableObjectGlobalState> = new Map();\n\n\tgetDOState(actorId: string): DurableObjectGlobalState {\n\t\tconst state = this.#dos.get(actorId);\n\t\tinvariant(state !== undefined, \"durable object state not in global state\");\n\t\treturn state;\n\t}\n\n\tsetDOState(actorId: string, state: DurableObjectGlobalState) {\n\t\tthis.#dos.set(actorId, state);\n\t}\n}\n\nexport interface ActorDriverContext {\n\tctx: DurableObjectState;\n\tenv: unknown;\n}\n\n// Actor handler to track running instances\nclass ActorHandler {\n\tactor?: AnyActorInstance;\n\tactorPromise?: PromiseWithResolvers<void> = Promise.withResolvers();\n\tgenericConnGlobalState = new GenericConnGlobalState();\n}\n\nexport class CloudflareActorsActorDriver implements ActorDriver {\n\t#registryConfig: RegistryConfig;\n\t#runConfig: RunConfig;\n\t#managerDriver: ManagerDriver;\n\t#inlineClient: Client<any>;\n\t#globalState: CloudflareDurableObjectGlobalState;\n\t#actors: Map<string, ActorHandler> = new Map();\n\n\tconstructor(\n\t\tregistryConfig: RegistryConfig,\n\t\trunConfig: RunConfig,\n\t\tmanagerDriver: ManagerDriver,\n\t\tinlineClient: Client<any>,\n\t\tglobalState: CloudflareDurableObjectGlobalState,\n\t) {\n\t\tthis.#registryConfig = registryConfig;\n\t\tthis.#runConfig = runConfig;\n\t\tthis.#managerDriver = managerDriver;\n\t\tthis.#inlineClient = inlineClient;\n\t\tthis.#globalState = globalState;\n\t}\n\n\t#getDOCtx(actorId: string) {\n\t\treturn this.#globalState.getDOState(actorId).ctx;\n\t}\n\n\tasync loadActor(actorId: string): Promise<AnyActorInstance> {\n\t\t// Check if actor is already loaded\n\t\tlet handler = this.#actors.get(actorId);\n\t\tif (handler) {\n\t\t\tif (handler.actorPromise) await handler.actorPromise.promise;\n\t\t\tif (!handler.actor) throw new Error(\"Actor should be loaded\");\n\t\t\treturn handler.actor;\n\t\t}\n\n\t\t// Create new actor handler\n\t\thandler = new ActorHandler();\n\t\tthis.#actors.set(actorId, handler);\n\n\t\t// Get the actor metadata from Durable Object storage\n\t\tconst doState = this.#globalState.getDOState(actorId);\n\t\tconst storage = doState.ctx.storage;\n\n\t\t// Load actor metadata\n\t\tconst [name, key] = await Promise.all([\n\t\t\tstorage.get<string>(KEYS.NAME),\n\t\t\tstorage.get<string[]>(KEYS.KEY),\n\t\t]);\n\n\t\tif (!name) {\n\t\t\tthrow new Error(`Actor ${actorId} is not initialized - missing name`);\n\t\t}\n\t\tif (!key) {\n\t\t\tthrow new Error(`Actor ${actorId} is not initialized - missing key`);\n\t\t}\n\n\t\t// Create actor instance\n\t\tconst definition = lookupInRegistry(this.#registryConfig, name);\n\t\thandler.actor = definition.instantiate();\n\n\t\t// Start actor\n\t\tconst connDrivers = createGenericConnDrivers(\n\t\t\thandler.genericConnGlobalState,\n\t\t);\n\t\tawait handler.actor.start(\n\t\t\tconnDrivers,\n\t\t\tthis,\n\t\t\tthis.#inlineClient,\n\t\t\tactorId,\n\t\t\tname,\n\t\t\tkey,\n\t\t\t\"unknown\", // TODO: Support regions in Cloudflare\n\t\t);\n\n\t\t// Finish\n\t\thandler.actorPromise?.resolve();\n\t\thandler.actorPromise = undefined;\n\n\t\treturn handler.actor;\n\t}\n\n\tgetGenericConnGlobalState(actorId: string): GenericConnGlobalState {\n\t\tconst handler = this.#actors.get(actorId);\n\t\tif (!handler) {\n\t\t\tthrow new Error(`Actor ${actorId} not loaded`);\n\t\t}\n\t\treturn handler.genericConnGlobalState;\n\t}\n\n\tgetContext(actorId: string): ActorDriverContext {\n\t\tconst state = this.#globalState.getDOState(actorId);\n\t\treturn { ctx: state.ctx, env: state.env };\n\t}\n\n\tasync readPersistedData(actorId: string): Promise<Uint8Array | undefined> {\n\t\treturn await this.#getDOCtx(actorId).storage.get(KEYS.PERSIST_DATA);\n\t}\n\n\tasync writePersistedData(actorId: string, data: Uint8Array): Promise<void> {\n\t\tawait this.#getDOCtx(actorId).storage.put(KEYS.PERSIST_DATA, data);\n\t}\n\n\tasync setAlarm(actor: AnyActorInstance, timestamp: number): Promise<void> {\n\t\tawait this.#getDOCtx(actor.id).storage.setAlarm(timestamp);\n\t}\n\n\tasync getDatabase(actorId: string): Promise<unknown | undefined> {\n\t\treturn this.#getDOCtx(actorId).storage.sql;\n\t}\n}\n\nexport function createCloudflareActorsActorDriverBuilder(\n\tglobalState: CloudflareDurableObjectGlobalState,\n) {\n\treturn (\n\t\tregistryConfig: RegistryConfig,\n\t\trunConfig: RunConfig,\n\t\tmanagerDriver: ManagerDriver,\n\t\tinlineClient: Client<any>,\n\t) => {\n\t\treturn new CloudflareActorsActorDriver(\n\t\t\tregistryConfig,\n\t\t\trunConfig,\n\t\t\tmanagerDriver,\n\t\t\tinlineClient,\n\t\t\tglobalState,\n\t\t);\n\t};\n}\n","import { getLogger } from \"@rivetkit/core/log\";\n\nexport const LOGGER_NAME = \"driver-cloudflare-workers\";\n\nexport function logger() {\n\treturn getLogger(LOGGER_NAME);\n}\n","import { RunConfigSchema } from \"@rivetkit/core/driver-helpers\";\nimport type { Hono } from \"hono\";\nimport { z } from \"zod\";\n\nexport const ConfigSchema = RunConfigSchema.removeDefault()\n\t.omit({ driver: true, getUpgradeWebSocket: true })\n\t.extend({\n\t\tapp: z.custom<Hono>().optional(),\n\t})\n\t.default({});\nexport type InputConfig = z.input<typeof ConfigSchema>;\nexport type Config = z.infer<typeof ConfigSchema>;\n","import type { Encoding } from \"@rivetkit/core\";\nimport {\n\ttype ActorOutput,\n\ttype CreateInput,\n\ttype GetForIdInput,\n\ttype GetOrCreateWithKeyInput,\n\ttype GetWithKeyInput,\n\tHEADER_AUTH_DATA,\n\tHEADER_CONN_PARAMS,\n\tHEADER_ENCODING,\n\tHEADER_EXPOSE_INTERNAL_ERROR,\n\ttype ManagerDriver,\n} from \"@rivetkit/core/driver-helpers\";\nimport { ActorAlreadyExists, InternalError } from \"@rivetkit/core/errors\";\nimport type { Context as HonoContext } from \"hono\";\nimport { getCloudflareAmbientEnv } from \"./handler\";\nimport { logger } from \"./log\";\nimport type { Bindings } from \"./mod\";\nimport { serializeKey, serializeNameAndKey } from \"./util\";\n\n// Actor metadata structure\ninterface ActorData {\n\tname: string;\n\tkey: string[];\n}\n\n// Key constants similar to Redis implementation\nconst KEYS = {\n\tACTOR: {\n\t\t// Combined key for actor metadata (name and key)\n\t\tmetadata: (actorId: string) => `actor:${actorId}:metadata`,\n\n\t\t// Key index function for actor lookup\n\t\tkeyIndex: (name: string, key: string[] = []) => {\n\t\t\t// Use serializeKey for consistent handling of all keys\n\t\t\treturn `actor_key:${serializeKey(key)}`;\n\t\t},\n\t},\n};\n\nconst STANDARD_WEBSOCKET_HEADERS = [\n\t\"connection\",\n\t\"upgrade\",\n\t\"sec-websocket-key\",\n\t\"sec-websocket-version\",\n\t\"sec-websocket-protocol\",\n\t\"sec-websocket-extensions\",\n];\n\nexport class CloudflareActorsManagerDriver implements ManagerDriver {\n\tasync sendRequest(actorId: string, actorRequest: Request): Promise<Response> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\tlogger().debug(\"sending request to durable object\", {\n\t\t\tactorId,\n\t\t\tmethod: actorRequest.method,\n\t\t\turl: actorRequest.url,\n\t\t});\n\n\t\tconst id = env.ACTOR_DO.idFromString(actorId);\n\t\tconst stub = env.ACTOR_DO.get(id);\n\n\t\treturn await stub.fetch(actorRequest);\n\t}\n\n\tasync openWebSocket(\n\t\tpath: string,\n\t\tactorId: string,\n\t\tencoding: Encoding,\n\t\tparams: unknown,\n\t): Promise<WebSocket> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\tlogger().debug(\"opening websocket to durable object\", { actorId, path });\n\n\t\t// Make a fetch request to the Durable Object with WebSocket upgrade\n\t\tconst id = env.ACTOR_DO.idFromString(actorId);\n\t\tconst stub = env.ACTOR_DO.get(id);\n\n\t\tconst headers: Record<string, string> = {\n\t\t\tUpgrade: \"websocket\",\n\t\t\tConnection: \"Upgrade\",\n\t\t\t[HEADER_EXPOSE_INTERNAL_ERROR]: \"true\",\n\t\t\t[HEADER_ENCODING]: encoding,\n\t\t};\n\t\tif (params) {\n\t\t\theaders[HEADER_CONN_PARAMS] = JSON.stringify(params);\n\t\t}\n\t\t// HACK: See packages/drivers/cloudflare-workers/src/websocket.ts\n\t\theaders[\"sec-websocket-protocol\"] = \"rivetkit\";\n\n\t\t// Use the path parameter to determine the URL\n\t\tconst url = `http://actor${path}`;\n\n\t\tlogger().debug(\"rewriting websocket url\", {\n\t\t\tfrom: path,\n\t\t\tto: url,\n\t\t});\n\n\t\tconst response = await stub.fetch(url, {\n\t\t\theaders,\n\t\t});\n\t\tconst webSocket = response.webSocket;\n\n\t\tif (!webSocket) {\n\t\t\tthrow new InternalError(\n\t\t\t\t\"missing websocket connection in response from DO\",\n\t\t\t);\n\t\t}\n\n\t\tlogger().debug(\"durable object websocket connection open\", {\n\t\t\tactorId,\n\t\t});\n\n\t\twebSocket.accept();\n\n\t\t// TODO: Is this still needed?\n\t\t// HACK: Cloudflare does not call onopen automatically, so we need\n\t\t// to call this on the next tick\n\t\tsetTimeout(() => {\n\t\t\tconst event = new Event(\"open\");\n\t\t\t(webSocket as any).onopen?.(event);\n\t\t\t(webSocket as any).dispatchEvent(event);\n\t\t}, 0);\n\n\t\treturn webSocket as unknown as WebSocket;\n\t}\n\n\tasync proxyRequest(\n\t\tc: HonoContext<{ Bindings: Bindings }>,\n\t\tactorRequest: Request,\n\t\tactorId: string,\n\t): Promise<Response> {\n\t\tlogger().debug(\"forwarding request to durable object\", {\n\t\t\tactorId,\n\t\t\tmethod: actorRequest.method,\n\t\t\turl: actorRequest.url,\n\t\t});\n\n\t\tconst id = c.env.ACTOR_DO.idFromString(actorId);\n\t\tconst stub = c.env.ACTOR_DO.get(id);\n\n\t\treturn await stub.fetch(actorRequest);\n\t}\n\n\tasync proxyWebSocket(\n\t\tc: HonoContext<{ Bindings: Bindings }>,\n\t\tpath: string,\n\t\tactorId: string,\n\t\tencoding: Encoding,\n\t\tparams: unknown,\n\t\tauthData: unknown,\n\t): Promise<Response> {\n\t\tlogger().debug(\"forwarding websocket to durable object\", {\n\t\t\tactorId,\n\t\t\tpath,\n\t\t});\n\n\t\t// Validate upgrade\n\t\tconst upgradeHeader = c.req.header(\"Upgrade\");\n\t\tif (!upgradeHeader || upgradeHeader !== \"websocket\") {\n\t\t\treturn new Response(\"Expected Upgrade: websocket\", {\n\t\t\t\tstatus: 426,\n\t\t\t});\n\t\t}\n\n\t\t// TODO: strip headers\n\t\tconst newUrl = new URL(`http://actor${path}`);\n\t\tconst actorRequest = new Request(newUrl, c.req.raw);\n\n\t\tlogger().debug(\"rewriting websocket url\", {\n\t\t\tfrom: c.req.url,\n\t\t\tto: actorRequest.url,\n\t\t});\n\n\t\t// Always build fresh request to prevent forwarding unwanted headers\n\t\t// HACK: Since we can't build a new request, we need to remove\n\t\t// non-standard headers manually\n\t\tconst headerKeys: string[] = [];\n\t\tactorRequest.headers.forEach((v, k) => headerKeys.push(k));\n\t\tfor (const k of headerKeys) {\n\t\t\tif (!STANDARD_WEBSOCKET_HEADERS.includes(k)) {\n\t\t\t\tactorRequest.headers.delete(k);\n\t\t\t}\n\t\t}\n\n\t\t// Add RivetKit headers\n\t\tactorRequest.headers.set(HEADER_EXPOSE_INTERNAL_ERROR, \"true\");\n\t\tactorRequest.headers.set(HEADER_ENCODING, encoding);\n\t\tif (params) {\n\t\t\tactorRequest.headers.set(HEADER_CONN_PARAMS, JSON.stringify(params));\n\t\t}\n\t\tif (authData) {\n\t\t\tactorRequest.headers.set(HEADER_AUTH_DATA, JSON.stringify(authData));\n\t\t}\n\n\t\tconst id = c.env.ACTOR_DO.idFromString(actorId);\n\t\tconst stub = c.env.ACTOR_DO.get(id);\n\n\t\treturn await stub.fetch(actorRequest);\n\t}\n\n\tasync getForId({\n\t\tc,\n\t\tactorId,\n\t}: GetForIdInput<{ Bindings: Bindings }>): Promise<ActorOutput | undefined> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\t// Get actor metadata from KV (combined name and key)\n\t\tconst actorData = (await env.ACTOR_KV.get(KEYS.ACTOR.metadata(actorId), {\n\t\t\ttype: \"json\",\n\t\t})) as ActorData | null;\n\n\t\t// If the actor doesn't exist, return undefined\n\t\tif (!actorData) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tactorId,\n\t\t\tname: actorData.name,\n\t\t\tkey: actorData.key,\n\t\t};\n\t}\n\n\tasync getWithKey({\n\t\tc,\n\t\tname,\n\t\tkey,\n\t}: GetWithKeyInput<{ Bindings: Bindings }>): Promise<\n\t\tActorOutput | undefined\n\t> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\tlogger().debug(\"getWithKey: searching for actor\", { name, key });\n\n\t\t// Generate deterministic ID from the name and key\n\t\t// This is aligned with how createActor generates IDs\n\t\tconst nameKeyString = serializeNameAndKey(name, key);\n\t\tconst actorId = env.ACTOR_DO.idFromName(nameKeyString).toString();\n\n\t\t// Check if the actor metadata exists\n\t\tconst actorData = await env.ACTOR_KV.get(KEYS.ACTOR.metadata(actorId), {\n\t\t\ttype: \"json\",\n\t\t});\n\n\t\tif (!actorData) {\n\t\t\tlogger().debug(\"getWithKey: no actor found with matching name and key\", {\n\t\t\t\tname,\n\t\t\t\tkey,\n\t\t\t\tactorId,\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\n\t\tlogger().debug(\"getWithKey: found actor with matching name and key\", {\n\t\t\tactorId,\n\t\t\tname,\n\t\t\tkey,\n\t\t});\n\t\treturn this.#buildActorOutput(c, actorId);\n\t}\n\n\tasync getOrCreateWithKey(\n\t\tinput: GetOrCreateWithKeyInput,\n\t): Promise<ActorOutput> {\n\t\t// TODO: Prevent race condition here\n\t\tconst getOutput = await this.getWithKey(input);\n\t\tif (getOutput) {\n\t\t\treturn getOutput;\n\t\t} else {\n\t\t\treturn await this.createActor(input);\n\t\t}\n\t}\n\n\tasync createActor({\n\t\tc,\n\t\tname,\n\t\tkey,\n\t\tinput,\n\t}: CreateInput<{ Bindings: Bindings }>): Promise<ActorOutput> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\t// Check if actor with the same name and key already exists\n\t\tconst existingActor = await this.getWithKey({ c, name, key });\n\t\tif (existingActor) {\n\t\t\tthrow new ActorAlreadyExists(name, key);\n\t\t}\n\n\t\t// Create a deterministic ID from the actor name and key\n\t\t// This ensures that actors with the same name and key will have the same ID\n\t\tconst nameKeyString = serializeNameAndKey(name, key);\n\t\tconst doId = env.ACTOR_DO.idFromName(nameKeyString);\n\t\tconst actorId = doId.toString();\n\n\t\t// Init actor\n\t\tconst actor = env.ACTOR_DO.get(doId);\n\t\tawait actor.initialize({\n\t\t\tname,\n\t\t\tkey,\n\t\t\tinput,\n\t\t});\n\n\t\t// Store combined actor metadata (name and key)\n\t\tconst actorData: ActorData = { name, key };\n\t\tawait env.ACTOR_KV.put(\n\t\t\tKEYS.ACTOR.metadata(actorId),\n\t\t\tJSON.stringify(actorData),\n\t\t);\n\n\t\t// Add to key index for lookups by name and key\n\t\tawait env.ACTOR_KV.put(KEYS.ACTOR.keyIndex(name, key), actorId);\n\n\t\treturn {\n\t\t\tactorId,\n\t\t\tname,\n\t\t\tkey,\n\t\t};\n\t}\n\n\t// Helper method to build actor output from an ID\n\tasync #buildActorOutput(\n\t\tc: any,\n\t\tactorId: string,\n\t): Promise<ActorOutput | undefined> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\tconst actorData = (await env.ACTOR_KV.get(KEYS.ACTOR.metadata(actorId), {\n\t\t\ttype: \"json\",\n\t\t})) as ActorData | null;\n\n\t\tif (!actorData) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tactorId,\n\t\t\tname: actorData.name,\n\t\t\tkey: actorData.key,\n\t\t};\n\t}\n}\n","// Constants for key handling\nexport const EMPTY_KEY = \"(none)\";\nexport const KEY_SEPARATOR = \",\";\n\n/**\n * Serializes an array of key strings into a single string for use with idFromName\n *\n * @param name The actor name\n * @param key Array of key strings to serialize\n * @returns A single string containing the serialized name and key\n */\nexport function serializeNameAndKey(name: string, key: string[]): string {\n\t// Escape colons in the name\n\tconst escapedName = name.replace(/:/g, \"\\\\:\");\n\n\t// For empty keys, just return the name and a marker\n\tif (key.length === 0) {\n\t\treturn `${escapedName}:${EMPTY_KEY}`;\n\t}\n\n\t// Serialize the key array\n\tconst serializedKey = serializeKey(key);\n\n\t// Combine name and serialized key\n\treturn `${escapedName}:${serializedKey}`;\n}\n\n/**\n * Serializes an array of key strings into a single string\n *\n * @param key Array of key strings to serialize\n * @returns A single string containing the serialized key\n */\nexport function serializeKey(key: string[]): string {\n\t// Use a special marker for empty key arrays\n\tif (key.length === 0) {\n\t\treturn EMPTY_KEY;\n\t}\n\n\t// Escape each key part to handle the separator and the empty key marker\n\tconst escapedParts = key.map((part) => {\n\t\t// First check if it matches our empty key marker\n\t\tif (part === EMPTY_KEY) {\n\t\t\treturn `\\\\${EMPTY_KEY}`;\n\t\t}\n\n\t\t// Escape backslashes first, then commas\n\t\tlet escaped = part.replace(/\\\\/g, \"\\\\\\\\\");\n\t\tescaped = escaped.replace(/,/g, \"\\\\,\");\n\t\treturn escaped;\n\t});\n\n\treturn escapedParts.join(KEY_SEPARATOR);\n}\n\n/**\n * Deserializes a key string back into an array of key strings\n *\n * @param keyString The serialized key string\n * @returns Array of key strings\n */\nexport function deserializeKey(keyString: string): string[] {\n\t// Handle empty values\n\tif (!keyString) {\n\t\treturn [];\n\t}\n\n\t// Check for special empty key marker\n\tif (keyString === EMPTY_KEY) {\n\t\treturn [];\n\t}\n\n\t// Split by unescaped commas and unescape the escaped characters\n\tconst parts: string[] = [];\n\tlet currentPart = \"\";\n\tlet escaping = false;\n\n\tfor (let i = 0; i < keyString.length; i++) {\n\t\tconst char = keyString[i];\n\n\t\tif (escaping) {\n\t\t\t// This is an escaped character, add it directly\n\t\t\tcurrentPart += char;\n\t\t\tescaping = false;\n\t\t} else if (char === \"\\\\\") {\n\t\t\t// Start of an escape sequence\n\t\t\tescaping = true;\n\t\t} else if (char === KEY_SEPARATOR) {\n\t\t\t// This is a separator\n\t\t\tparts.push(currentPart);\n\t\t\tcurrentPart = \"\";\n\t\t} else {\n\t\t\t// Regular character\n\t\t\tcurrentPart += char;\n\t\t}\n\t}\n\n\t// Add the last part if it exists\n\tif (currentPart || parts.length > 0) {\n\t\tparts.push(currentPart);\n\t}\n\n\treturn parts;\n}\n","// Modified from https://github.com/honojs/hono/blob/40ea0eee58e39b31053a0246c595434f1094ad31/src/adapter/cloudflare-workers/websocket.ts#L17\n//\n// This version calls the open event by default\n\nimport type { UpgradeWebSocket, WSEvents, WSReadyState } from \"hono/ws\";\nimport { defineWebSocketHelper, WSContext } from \"hono/ws\";\n\n// Based on https://github.com/honojs/hono/issues/1153#issuecomment-1767321332\nexport const upgradeWebSocket: UpgradeWebSocket<\n\tWebSocket,\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tany,\n\tWSEvents<WebSocket>\n> = defineWebSocketHelper(async (c, events) => {\n\tconst upgradeHeader = c.req.header(\"Upgrade\");\n\tif (upgradeHeader !== \"websocket\") {\n\t\treturn;\n\t}\n\n\tconst webSocketPair = new WebSocketPair();\n\tconst client: WebSocket = webSocketPair[0];\n\tconst server: WebSocket = webSocketPair[1];\n\n\tconst wsContext = new WSContext<WebSocket>({\n\t\tclose: (code, reason) => server.close(code, reason),\n\t\tget protocol() {\n\t\t\treturn server.protocol;\n\t\t},\n\t\traw: server,\n\t\tget readyState() {\n\t\t\treturn server.readyState as WSReadyState;\n\t\t},\n\t\turl: server.url ? new URL(server.url) : null,\n\t\tsend: (source) => server.send(source),\n\t});\n\n\tif (events.onClose) {\n\t\tserver.addEventListener(\"close\", (evt: CloseEvent) =>\n\t\t\tevents.onClose?.(evt, wsContext),\n\t\t);\n\t}\n\tif (events.onMessage) {\n\t\tserver.addEventListener(\"message\", (evt: MessageEvent) =>\n\t\t\tevents.onMessage?.(evt, wsContext),\n\t\t);\n\t}\n\tif (events.onError) {\n\t\tserver.addEventListener(\"error\", (evt: Event) =>\n\t\t\tevents.onError?.(evt, wsContext),\n\t\t);\n\t}\n\n\tserver.accept?.();\n\n\t// note: cloudflare actors doesn't support 'open' event, so we call it immediately with a fake event\n\t//\n\t// we have to do this after `server.accept() is called`\n\tevents.onOpen?.(new Event(\"open\"), wsContext);\n\n\treturn new Response(null, {\n\t\tstatus: 101,\n\t\theaders: {\n\t\t\t// HACK: Required in order for Cloudflare to not error with \"Network connection lost\"\n\t\t\t//\n\t\t\t// This bug undocumented. Cannot easily reproduce outside of RivetKit.\n\t\t\t\"Sec-WebSocket-Protocol\": \"rivetkit\",\n\t\t},\n\t\twebSocket: client,\n\t});\n});\n"],"mappings":"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","names":["invariant","KEYS","_a","invariant","ActorHandler"]}
1
+ {"version":3,"sources":["../src/handler.ts","../src/actor-handler-do.ts","../src/actor-driver.ts","../src/log.ts","../src/config.ts","../src/manager-driver.ts","../src/util.ts","../src/websocket.ts"],"sourcesContent":["import { env } from \"cloudflare:workers\";\nimport type { Registry, RunConfig } from \"@rivetkit/core\";\nimport type { Client } from \"@rivetkit/core/client\";\nimport { Hono } from \"hono\";\nimport {\n\ttype ActorHandlerInterface,\n\tcreateActorDurableObject,\n\ttype DurableObjectConstructor,\n} from \"./actor-handler-do\";\nimport { ConfigSchema, type InputConfig } from \"./config\";\nimport { CloudflareActorsManagerDriver } from \"./manager-driver\";\nimport { upgradeWebSocket } from \"./websocket\";\n\n/** Cloudflare Workers env */\nexport interface Bindings {\n\tACTOR_KV: KVNamespace;\n\tACTOR_DO: DurableObjectNamespace<ActorHandlerInterface>;\n}\n\n/**\n * Stores the env for the current request. Required since some contexts like the inline client driver does not have access to the Hono context.\n *\n * Use getCloudflareAmbientEnv unless using CF_AMBIENT_ENV.run.\n */\nexport function getCloudflareAmbientEnv(): Bindings {\n\treturn env as unknown as Bindings;\n}\n\ninterface Handler {\n\thandler: ExportedHandler<Bindings>;\n\tActorHandler: DurableObjectConstructor;\n}\n\ninterface SetupOutput<A extends Registry<any>> {\n\tclient: Client<A>;\n\tcreateHandler: (hono?: Hono) => Handler;\n}\n\nexport function createServerHandler<R extends Registry<any>>(\n\tregistry: R,\n\tinputConfig?: InputConfig,\n): Handler {\n\tconst { createHandler } = createServer(registry, inputConfig);\n\treturn createHandler();\n}\n\nexport function createServer<R extends Registry<any>>(\n\tregistry: R,\n\tinputConfig?: InputConfig,\n): SetupOutput<R> {\n\tconst config = ConfigSchema.parse(inputConfig);\n\n\t// Create config\n\tconst runConfig = {\n\t\tdriver: {\n\t\t\tname: \"cloudflare-workers\",\n\t\t\tmanager: () => new CloudflareActorsManagerDriver(),\n\t\t\t// HACK: We can't build the actor driver until we're inside the Durable Object\n\t\t\tactor: undefined as any,\n\t\t},\n\t\tgetUpgradeWebSocket: () => upgradeWebSocket,\n\t\t...config,\n\t} satisfies RunConfig;\n\n\t// Create Durable Object\n\tconst ActorHandler = createActorDurableObject(registry, runConfig);\n\n\t// Create server\n\tconst serverOutput = registry.createServer(runConfig);\n\n\treturn {\n\t\tclient: serverOutput.client as Client<R>,\n\t\tcreateHandler: (hono) => {\n\t\t\t// Build base router\n\t\t\tconst app = hono ?? new Hono();\n\n\t\t\t// Mount registry router at /registry\n\t\t\tif (!hono) {\n\t\t\t\tapp.route(\"/registry\", serverOutput.hono);\n\t\t\t}\n\n\t\t\t// Create Cloudflare handler\n\t\t\tconst handler = {\n\t\t\t\tfetch: (request, env, ctx) => {\n\t\t\t\t\treturn app.fetch(request, env, ctx);\n\t\t\t\t},\n\t\t\t} satisfies ExportedHandler<Bindings>;\n\n\t\t\treturn { handler, ActorHandler };\n\t\t},\n\t};\n}\n","import { DurableObject, env } from \"cloudflare:workers\";\nimport type {\n\tActorKey,\n\tActorRouter,\n\tRegistry,\n\tRunConfig,\n} from \"@rivetkit/core\";\nimport {\n\tcreateActorRouter,\n\tcreateClientWithDriver,\n\tcreateInlineClientDriver,\n} from \"@rivetkit/core\";\nimport { serializeEmptyPersistData } from \"@rivetkit/core/driver-helpers\";\nimport type { ExecutionContext } from \"hono\";\nimport {\n\tCloudflareDurableObjectGlobalState,\n\tcreateCloudflareActorsActorDriverBuilder,\n} from \"./actor-driver\";\nimport type { Bindings } from \"./handler\";\nimport { logger } from \"./log\";\n\nexport const KEYS = {\n\tNAME: \"rivetkit:name\",\n\tKEY: \"rivetkit:key\",\n\tPERSIST_DATA: \"rivetkit:data\",\n};\n\nexport interface ActorHandlerInterface extends DurableObject {\n\tinitialize(req: ActorInitRequest): Promise<void>;\n}\n\nexport interface ActorInitRequest {\n\tname: string;\n\tkey: ActorKey;\n\tinput?: unknown;\n}\n\ninterface InitializedData {\n\tname: string;\n\tkey: ActorKey;\n}\n\nexport type DurableObjectConstructor = new (\n\t...args: ConstructorParameters<typeof DurableObject<Bindings>>\n) => DurableObject<Bindings>;\n\ninterface LoadedActor {\n\tactorRouter: ActorRouter;\n}\n\nexport function createActorDurableObject(\n\tregistry: Registry<any>,\n\trunConfig: RunConfig,\n): DurableObjectConstructor {\n\tconst globalState = new CloudflareDurableObjectGlobalState();\n\n\t/**\n\t * Startup steps:\n\t * 1. If not already created call `initialize`, otherwise check KV to ensure it's initialized\n\t * 2. Load actor\n\t * 3. Start service requests\n\t */\n\treturn class ActorHandler\n\t\textends DurableObject<Bindings>\n\t\timplements ActorHandlerInterface\n\t{\n\t\t#initialized?: InitializedData;\n\t\t#initializedPromise?: PromiseWithResolvers<void>;\n\n\t\t#actor?: LoadedActor;\n\n\t\tasync #loadActor(): Promise<LoadedActor> {\n\t\t\t// Wait for init\n\t\t\tif (!this.#initialized) {\n\t\t\t\t// Wait for init\n\t\t\t\tif (this.#initializedPromise) {\n\t\t\t\t\tawait this.#initializedPromise.promise;\n\t\t\t\t} else {\n\t\t\t\t\tthis.#initializedPromise = Promise.withResolvers();\n\t\t\t\t\tconst res = await this.ctx.storage.get([\n\t\t\t\t\t\tKEYS.NAME,\n\t\t\t\t\t\tKEYS.KEY,\n\t\t\t\t\t\tKEYS.PERSIST_DATA,\n\t\t\t\t\t]);\n\t\t\t\t\tif (res.get(KEYS.PERSIST_DATA)) {\n\t\t\t\t\t\tconst name = res.get(KEYS.NAME) as string;\n\t\t\t\t\t\tif (!name) throw new Error(\"missing actor name\");\n\t\t\t\t\t\tconst key = res.get(KEYS.KEY) as ActorKey;\n\t\t\t\t\t\tif (!key) throw new Error(\"missing actor key\");\n\n\t\t\t\t\t\tlogger().debug(\"already initialized\", { name, key });\n\n\t\t\t\t\t\tthis.#initialized = { name, key };\n\t\t\t\t\t\tthis.#initializedPromise.resolve();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger().debug(\"waiting to initialize\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check if already loaded\n\t\t\tif (this.#actor) {\n\t\t\t\treturn this.#actor;\n\t\t\t}\n\n\t\t\tif (!this.#initialized) throw new Error(\"Not initialized\");\n\n\t\t\t// Register DO with global state first\n\t\t\t// HACK: This leaks the DO context, but DO does not provide a native way\n\t\t\t// of knowing when the DO shuts down. We're making a broad assumption\n\t\t\t// that DO will boot a new isolate frequenlty enough that this is not an issue.\n\t\t\tconst actorId = this.ctx.id.toString();\n\t\t\tglobalState.setDOState(actorId, { ctx: this.ctx, env: env });\n\n\t\t\t// Configure actor driver\n\t\t\trunConfig.driver.actor =\n\t\t\t\tcreateCloudflareActorsActorDriverBuilder(globalState);\n\n\t\t\t// Create manager driver (we need this for the actor router)\n\t\t\tconst managerDriver = runConfig.driver.manager(\n\t\t\t\tregistry.config,\n\t\t\t\trunConfig,\n\t\t\t);\n\n\t\t\t// Create inline client\n\t\t\tconst inlineClient = createClientWithDriver(\n\t\t\t\tcreateInlineClientDriver(managerDriver),\n\t\t\t);\n\n\t\t\t// Create actor driver\n\t\t\tconst actorDriver = runConfig.driver.actor(\n\t\t\t\tregistry.config,\n\t\t\t\trunConfig,\n\t\t\t\tmanagerDriver,\n\t\t\t\tinlineClient,\n\t\t\t);\n\n\t\t\t// Create actor router\n\t\t\tconst actorRouter = createActorRouter(runConfig, actorDriver);\n\n\t\t\t// Save actor\n\t\t\tthis.#actor = {\n\t\t\t\tactorRouter,\n\t\t\t};\n\n\t\t\t// Initialize the actor instance with proper metadata\n\t\t\t// This ensures the actor driver knows about this actor\n\t\t\tawait actorDriver.loadActor(actorId);\n\n\t\t\treturn this.#actor;\n\t\t}\n\n\t\t/** RPC called by the service that creates the DO to initialize it. */\n\t\tasync initialize(req: ActorInitRequest) {\n\t\t\t// TODO: Need to add this to a core promise that needs to be resolved before start\n\n\t\t\tawait this.ctx.storage.put({\n\t\t\t\t[KEYS.NAME]: req.name,\n\t\t\t\t[KEYS.KEY]: req.key,\n\t\t\t\t[KEYS.PERSIST_DATA]: serializeEmptyPersistData(req.input),\n\t\t\t});\n\t\t\tthis.#initialized = {\n\t\t\t\tname: req.name,\n\t\t\t\tkey: req.key,\n\t\t\t};\n\n\t\t\tlogger().debug(\"initialized actor\", { key: req.key });\n\n\t\t\t// Preemptively actor so the lifecycle hooks are called\n\t\t\tawait this.#loadActor();\n\t\t}\n\n\t\tasync fetch(request: Request): Promise<Response> {\n\t\t\tconst { actorRouter } = await this.#loadActor();\n\n\t\t\tconst actorId = this.ctx.id.toString();\n\t\t\treturn await actorRouter.fetch(request, {\n\t\t\t\tactorId,\n\t\t\t});\n\t\t}\n\n\t\tasync alarm(): Promise<void> {\n\t\t\tawait this.#loadActor();\n\t\t\tconst actorId = this.ctx.id.toString();\n\n\t\t\t// Get the actor driver\n\t\t\tconst managerDriver = runConfig.driver.manager(\n\t\t\t\tregistry.config,\n\t\t\t\trunConfig,\n\t\t\t);\n\t\t\tconst inlineClient = createClientWithDriver(\n\t\t\t\tcreateInlineClientDriver(managerDriver),\n\t\t\t);\n\t\t\tconst actorDriver = runConfig.driver.actor(\n\t\t\t\tregistry.config,\n\t\t\t\trunConfig,\n\t\t\t\tmanagerDriver,\n\t\t\t\tinlineClient,\n\t\t\t);\n\n\t\t\t// Load the actor instance and trigger alarm\n\t\t\tconst actor = await actorDriver.loadActor(actorId);\n\t\t\tawait actor.onAlarm();\n\t\t}\n\t};\n}\n","import type {\n\tAnyActorInstance as CoreAnyActorInstance,\n\tRegistryConfig,\n\tRunConfig,\n} from \"@rivetkit/core\";\nimport {\n\tcreateGenericConnDrivers,\n\tGenericConnGlobalState,\n\tlookupInRegistry,\n} from \"@rivetkit/core\";\nimport type { Client } from \"@rivetkit/core/client\";\nimport type {\n\tActorDriver,\n\tAnyActorInstance,\n\tManagerDriver,\n} from \"@rivetkit/core/driver-helpers\";\nimport invariant from \"invariant\";\nimport { KEYS } from \"./actor-handler-do\";\n\ninterface DurableObjectGlobalState {\n\tctx: DurableObjectState;\n\tenv: unknown;\n}\n\n/**\n * Cloudflare DO can have multiple DO running within the same global scope.\n *\n * This allows for storing the actor context globally and looking it up by ID in `CloudflareActorsActorDriver`.\n */\nexport class CloudflareDurableObjectGlobalState {\n\t// Single map for all actor state\n\t#dos: Map<string, DurableObjectGlobalState> = new Map();\n\n\tgetDOState(actorId: string): DurableObjectGlobalState {\n\t\tconst state = this.#dos.get(actorId);\n\t\tinvariant(state !== undefined, \"durable object state not in global state\");\n\t\treturn state;\n\t}\n\n\tsetDOState(actorId: string, state: DurableObjectGlobalState) {\n\t\tthis.#dos.set(actorId, state);\n\t}\n}\n\nexport interface DriverContext {\n\tstate: DurableObjectState;\n}\n\n// Actor handler to track running instances\nclass ActorHandler {\n\tactor?: AnyActorInstance;\n\tactorPromise?: PromiseWithResolvers<void> = Promise.withResolvers();\n\tgenericConnGlobalState = new GenericConnGlobalState();\n}\n\nexport class CloudflareActorsActorDriver implements ActorDriver {\n\t#registryConfig: RegistryConfig;\n\t#runConfig: RunConfig;\n\t#managerDriver: ManagerDriver;\n\t#inlineClient: Client<any>;\n\t#globalState: CloudflareDurableObjectGlobalState;\n\t#actors: Map<string, ActorHandler> = new Map();\n\n\tconstructor(\n\t\tregistryConfig: RegistryConfig,\n\t\trunConfig: RunConfig,\n\t\tmanagerDriver: ManagerDriver,\n\t\tinlineClient: Client<any>,\n\t\tglobalState: CloudflareDurableObjectGlobalState,\n\t) {\n\t\tthis.#registryConfig = registryConfig;\n\t\tthis.#runConfig = runConfig;\n\t\tthis.#managerDriver = managerDriver;\n\t\tthis.#inlineClient = inlineClient;\n\t\tthis.#globalState = globalState;\n\t}\n\n\t#getDOCtx(actorId: string) {\n\t\treturn this.#globalState.getDOState(actorId).ctx;\n\t}\n\n\tasync loadActor(actorId: string): Promise<AnyActorInstance> {\n\t\t// Check if actor is already loaded\n\t\tlet handler = this.#actors.get(actorId);\n\t\tif (handler) {\n\t\t\tif (handler.actorPromise) await handler.actorPromise.promise;\n\t\t\tif (!handler.actor) throw new Error(\"Actor should be loaded\");\n\t\t\treturn handler.actor;\n\t\t}\n\n\t\t// Create new actor handler\n\t\thandler = new ActorHandler();\n\t\tthis.#actors.set(actorId, handler);\n\n\t\t// Get the actor metadata from Durable Object storage\n\t\tconst doState = this.#globalState.getDOState(actorId);\n\t\tconst storage = doState.ctx.storage;\n\n\t\t// Load actor metadata\n\t\tconst [name, key] = await Promise.all([\n\t\t\tstorage.get<string>(KEYS.NAME),\n\t\t\tstorage.get<string[]>(KEYS.KEY),\n\t\t]);\n\n\t\tif (!name) {\n\t\t\tthrow new Error(`Actor ${actorId} is not initialized - missing name`);\n\t\t}\n\t\tif (!key) {\n\t\t\tthrow new Error(`Actor ${actorId} is not initialized - missing key`);\n\t\t}\n\n\t\t// Create actor instance\n\t\tconst definition = lookupInRegistry(this.#registryConfig, name);\n\t\thandler.actor = definition.instantiate();\n\n\t\t// Start actor\n\t\tconst connDrivers = createGenericConnDrivers(\n\t\t\thandler.genericConnGlobalState,\n\t\t);\n\t\tawait handler.actor.start(\n\t\t\tconnDrivers,\n\t\t\tthis,\n\t\t\tthis.#inlineClient,\n\t\t\tactorId,\n\t\t\tname,\n\t\t\tkey,\n\t\t\t\"unknown\", // TODO: Support regions in Cloudflare\n\t\t);\n\n\t\t// Finish\n\t\thandler.actorPromise?.resolve();\n\t\thandler.actorPromise = undefined;\n\n\t\treturn handler.actor;\n\t}\n\n\tgetGenericConnGlobalState(actorId: string): GenericConnGlobalState {\n\t\tconst handler = this.#actors.get(actorId);\n\t\tif (!handler) {\n\t\t\tthrow new Error(`Actor ${actorId} not loaded`);\n\t\t}\n\t\treturn handler.genericConnGlobalState;\n\t}\n\n\tgetContext(actorId: string): DriverContext {\n\t\tconst state = this.#globalState.getDOState(actorId);\n\t\treturn { state: state.ctx };\n\t}\n\n\tasync readPersistedData(actorId: string): Promise<Uint8Array | undefined> {\n\t\treturn await this.#getDOCtx(actorId).storage.get(KEYS.PERSIST_DATA);\n\t}\n\n\tasync writePersistedData(actorId: string, data: Uint8Array): Promise<void> {\n\t\tawait this.#getDOCtx(actorId).storage.put(KEYS.PERSIST_DATA, data);\n\t}\n\n\tasync setAlarm(actor: AnyActorInstance, timestamp: number): Promise<void> {\n\t\tawait this.#getDOCtx(actor.id).storage.setAlarm(timestamp);\n\t}\n\n\tasync getDatabase(actorId: string): Promise<unknown | undefined> {\n\t\treturn this.#getDOCtx(actorId).storage.sql;\n\t}\n}\n\nexport function createCloudflareActorsActorDriverBuilder(\n\tglobalState: CloudflareDurableObjectGlobalState,\n) {\n\treturn (\n\t\tregistryConfig: RegistryConfig,\n\t\trunConfig: RunConfig,\n\t\tmanagerDriver: ManagerDriver,\n\t\tinlineClient: Client<any>,\n\t) => {\n\t\treturn new CloudflareActorsActorDriver(\n\t\t\tregistryConfig,\n\t\t\trunConfig,\n\t\t\tmanagerDriver,\n\t\t\tinlineClient,\n\t\t\tglobalState,\n\t\t);\n\t};\n}\n","import { getLogger } from \"@rivetkit/core/log\";\n\nexport const LOGGER_NAME = \"driver-cloudflare-workers\";\n\nexport function logger() {\n\treturn getLogger(LOGGER_NAME);\n}\n","import { RunConfigSchema } from \"@rivetkit/core/driver-helpers\";\nimport type { Hono } from \"hono\";\nimport { z } from \"zod\";\n\nexport const ConfigSchema = RunConfigSchema.removeDefault()\n\t.omit({ driver: true, getUpgradeWebSocket: true })\n\t.extend({\n\t\tapp: z.custom<Hono>().optional(),\n\t})\n\t.default({});\nexport type InputConfig = z.input<typeof ConfigSchema>;\nexport type Config = z.infer<typeof ConfigSchema>;\n","import type { Encoding } from \"@rivetkit/core\";\nimport {\n\ttype ActorOutput,\n\ttype CreateInput,\n\ttype GetForIdInput,\n\ttype GetOrCreateWithKeyInput,\n\ttype GetWithKeyInput,\n\tHEADER_AUTH_DATA,\n\tHEADER_CONN_PARAMS,\n\tHEADER_ENCODING,\n\tHEADER_EXPOSE_INTERNAL_ERROR,\n\ttype ManagerDriver,\n} from \"@rivetkit/core/driver-helpers\";\nimport { ActorAlreadyExists, InternalError } from \"@rivetkit/core/errors\";\nimport type { Context as HonoContext } from \"hono\";\nimport { getCloudflareAmbientEnv } from \"./handler\";\nimport { logger } from \"./log\";\nimport type { Bindings } from \"./mod\";\nimport { serializeKey, serializeNameAndKey } from \"./util\";\n\n// Actor metadata structure\ninterface ActorData {\n\tname: string;\n\tkey: string[];\n}\n\n// Key constants similar to Redis implementation\nconst KEYS = {\n\tACTOR: {\n\t\t// Combined key for actor metadata (name and key)\n\t\tmetadata: (actorId: string) => `actor:${actorId}:metadata`,\n\n\t\t// Key index function for actor lookup\n\t\tkeyIndex: (name: string, key: string[] = []) => {\n\t\t\t// Use serializeKey for consistent handling of all keys\n\t\t\treturn `actor_key:${serializeKey(key)}`;\n\t\t},\n\t},\n};\n\nconst STANDARD_WEBSOCKET_HEADERS = [\n\t\"connection\",\n\t\"upgrade\",\n\t\"sec-websocket-key\",\n\t\"sec-websocket-version\",\n\t\"sec-websocket-protocol\",\n\t\"sec-websocket-extensions\",\n];\n\nexport class CloudflareActorsManagerDriver implements ManagerDriver {\n\tasync sendRequest(actorId: string, actorRequest: Request): Promise<Response> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\tlogger().debug(\"sending request to durable object\", {\n\t\t\tactorId,\n\t\t\tmethod: actorRequest.method,\n\t\t\turl: actorRequest.url,\n\t\t});\n\n\t\tconst id = env.ACTOR_DO.idFromString(actorId);\n\t\tconst stub = env.ACTOR_DO.get(id);\n\n\t\treturn await stub.fetch(actorRequest);\n\t}\n\n\tasync openWebSocket(\n\t\tpath: string,\n\t\tactorId: string,\n\t\tencoding: Encoding,\n\t\tparams: unknown,\n\t): Promise<WebSocket> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\tlogger().debug(\"opening websocket to durable object\", { actorId, path });\n\n\t\t// Make a fetch request to the Durable Object with WebSocket upgrade\n\t\tconst id = env.ACTOR_DO.idFromString(actorId);\n\t\tconst stub = env.ACTOR_DO.get(id);\n\n\t\tconst headers: Record<string, string> = {\n\t\t\tUpgrade: \"websocket\",\n\t\t\tConnection: \"Upgrade\",\n\t\t\t[HEADER_EXPOSE_INTERNAL_ERROR]: \"true\",\n\t\t\t[HEADER_ENCODING]: encoding,\n\t\t};\n\t\tif (params) {\n\t\t\theaders[HEADER_CONN_PARAMS] = JSON.stringify(params);\n\t\t}\n\t\t// HACK: See packages/drivers/cloudflare-workers/src/websocket.ts\n\t\theaders[\"sec-websocket-protocol\"] = \"rivetkit\";\n\n\t\t// Use the path parameter to determine the URL\n\t\tconst url = `http://actor${path}`;\n\n\t\tlogger().debug(\"rewriting websocket url\", {\n\t\t\tfrom: path,\n\t\t\tto: url,\n\t\t});\n\n\t\tconst response = await stub.fetch(url, {\n\t\t\theaders,\n\t\t});\n\t\tconst webSocket = response.webSocket;\n\n\t\tif (!webSocket) {\n\t\t\tthrow new InternalError(\n\t\t\t\t\"missing websocket connection in response from DO\",\n\t\t\t);\n\t\t}\n\n\t\tlogger().debug(\"durable object websocket connection open\", {\n\t\t\tactorId,\n\t\t});\n\n\t\twebSocket.accept();\n\n\t\t// TODO: Is this still needed?\n\t\t// HACK: Cloudflare does not call onopen automatically, so we need\n\t\t// to call this on the next tick\n\t\tsetTimeout(() => {\n\t\t\tconst event = new Event(\"open\");\n\t\t\t(webSocket as any).onopen?.(event);\n\t\t\t(webSocket as any).dispatchEvent(event);\n\t\t}, 0);\n\n\t\treturn webSocket as unknown as WebSocket;\n\t}\n\n\tasync proxyRequest(\n\t\tc: HonoContext<{ Bindings: Bindings }>,\n\t\tactorRequest: Request,\n\t\tactorId: string,\n\t): Promise<Response> {\n\t\tlogger().debug(\"forwarding request to durable object\", {\n\t\t\tactorId,\n\t\t\tmethod: actorRequest.method,\n\t\t\turl: actorRequest.url,\n\t\t});\n\n\t\tconst id = c.env.ACTOR_DO.idFromString(actorId);\n\t\tconst stub = c.env.ACTOR_DO.get(id);\n\n\t\treturn await stub.fetch(actorRequest);\n\t}\n\n\tasync proxyWebSocket(\n\t\tc: HonoContext<{ Bindings: Bindings }>,\n\t\tpath: string,\n\t\tactorId: string,\n\t\tencoding: Encoding,\n\t\tparams: unknown,\n\t\tauthData: unknown,\n\t): Promise<Response> {\n\t\tlogger().debug(\"forwarding websocket to durable object\", {\n\t\t\tactorId,\n\t\t\tpath,\n\t\t});\n\n\t\t// Validate upgrade\n\t\tconst upgradeHeader = c.req.header(\"Upgrade\");\n\t\tif (!upgradeHeader || upgradeHeader !== \"websocket\") {\n\t\t\treturn new Response(\"Expected Upgrade: websocket\", {\n\t\t\t\tstatus: 426,\n\t\t\t});\n\t\t}\n\n\t\t// TODO: strip headers\n\t\tconst newUrl = new URL(`http://actor${path}`);\n\t\tconst actorRequest = new Request(newUrl, c.req.raw);\n\n\t\tlogger().debug(\"rewriting websocket url\", {\n\t\t\tfrom: c.req.url,\n\t\t\tto: actorRequest.url,\n\t\t});\n\n\t\t// Always build fresh request to prevent forwarding unwanted headers\n\t\t// HACK: Since we can't build a new request, we need to remove\n\t\t// non-standard headers manually\n\t\tconst headerKeys: string[] = [];\n\t\tactorRequest.headers.forEach((v, k) => headerKeys.push(k));\n\t\tfor (const k of headerKeys) {\n\t\t\tif (!STANDARD_WEBSOCKET_HEADERS.includes(k)) {\n\t\t\t\tactorRequest.headers.delete(k);\n\t\t\t}\n\t\t}\n\n\t\t// Add RivetKit headers\n\t\tactorRequest.headers.set(HEADER_EXPOSE_INTERNAL_ERROR, \"true\");\n\t\tactorRequest.headers.set(HEADER_ENCODING, encoding);\n\t\tif (params) {\n\t\t\tactorRequest.headers.set(HEADER_CONN_PARAMS, JSON.stringify(params));\n\t\t}\n\t\tif (authData) {\n\t\t\tactorRequest.headers.set(HEADER_AUTH_DATA, JSON.stringify(authData));\n\t\t}\n\n\t\tconst id = c.env.ACTOR_DO.idFromString(actorId);\n\t\tconst stub = c.env.ACTOR_DO.get(id);\n\n\t\treturn await stub.fetch(actorRequest);\n\t}\n\n\tasync getForId({\n\t\tc,\n\t\tactorId,\n\t}: GetForIdInput<{ Bindings: Bindings }>): Promise<ActorOutput | undefined> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\t// Get actor metadata from KV (combined name and key)\n\t\tconst actorData = (await env.ACTOR_KV.get(KEYS.ACTOR.metadata(actorId), {\n\t\t\ttype: \"json\",\n\t\t})) as ActorData | null;\n\n\t\t// If the actor doesn't exist, return undefined\n\t\tif (!actorData) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tactorId,\n\t\t\tname: actorData.name,\n\t\t\tkey: actorData.key,\n\t\t};\n\t}\n\n\tasync getWithKey({\n\t\tc,\n\t\tname,\n\t\tkey,\n\t}: GetWithKeyInput<{ Bindings: Bindings }>): Promise<\n\t\tActorOutput | undefined\n\t> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\tlogger().debug(\"getWithKey: searching for actor\", { name, key });\n\n\t\t// Generate deterministic ID from the name and key\n\t\t// This is aligned with how createActor generates IDs\n\t\tconst nameKeyString = serializeNameAndKey(name, key);\n\t\tconst actorId = env.ACTOR_DO.idFromName(nameKeyString).toString();\n\n\t\t// Check if the actor metadata exists\n\t\tconst actorData = await env.ACTOR_KV.get(KEYS.ACTOR.metadata(actorId), {\n\t\t\ttype: \"json\",\n\t\t});\n\n\t\tif (!actorData) {\n\t\t\tlogger().debug(\"getWithKey: no actor found with matching name and key\", {\n\t\t\t\tname,\n\t\t\t\tkey,\n\t\t\t\tactorId,\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\n\t\tlogger().debug(\"getWithKey: found actor with matching name and key\", {\n\t\t\tactorId,\n\t\t\tname,\n\t\t\tkey,\n\t\t});\n\t\treturn this.#buildActorOutput(c, actorId);\n\t}\n\n\tasync getOrCreateWithKey(\n\t\tinput: GetOrCreateWithKeyInput,\n\t): Promise<ActorOutput> {\n\t\t// TODO: Prevent race condition here\n\t\tconst getOutput = await this.getWithKey(input);\n\t\tif (getOutput) {\n\t\t\treturn getOutput;\n\t\t} else {\n\t\t\treturn await this.createActor(input);\n\t\t}\n\t}\n\n\tasync createActor({\n\t\tc,\n\t\tname,\n\t\tkey,\n\t\tinput,\n\t}: CreateInput<{ Bindings: Bindings }>): Promise<ActorOutput> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\t// Check if actor with the same name and key already exists\n\t\tconst existingActor = await this.getWithKey({ c, name, key });\n\t\tif (existingActor) {\n\t\t\tthrow new ActorAlreadyExists(name, key);\n\t\t}\n\n\t\t// Create a deterministic ID from the actor name and key\n\t\t// This ensures that actors with the same name and key will have the same ID\n\t\tconst nameKeyString = serializeNameAndKey(name, key);\n\t\tconst doId = env.ACTOR_DO.idFromName(nameKeyString);\n\t\tconst actorId = doId.toString();\n\n\t\t// Init actor\n\t\tconst actor = env.ACTOR_DO.get(doId);\n\t\tawait actor.initialize({\n\t\t\tname,\n\t\t\tkey,\n\t\t\tinput,\n\t\t});\n\n\t\t// Store combined actor metadata (name and key)\n\t\tconst actorData: ActorData = { name, key };\n\t\tawait env.ACTOR_KV.put(\n\t\t\tKEYS.ACTOR.metadata(actorId),\n\t\t\tJSON.stringify(actorData),\n\t\t);\n\n\t\t// Add to key index for lookups by name and key\n\t\tawait env.ACTOR_KV.put(KEYS.ACTOR.keyIndex(name, key), actorId);\n\n\t\treturn {\n\t\t\tactorId,\n\t\t\tname,\n\t\t\tkey,\n\t\t};\n\t}\n\n\t// Helper method to build actor output from an ID\n\tasync #buildActorOutput(\n\t\tc: any,\n\t\tactorId: string,\n\t): Promise<ActorOutput | undefined> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\tconst actorData = (await env.ACTOR_KV.get(KEYS.ACTOR.metadata(actorId), {\n\t\t\ttype: \"json\",\n\t\t})) as ActorData | null;\n\n\t\tif (!actorData) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tactorId,\n\t\t\tname: actorData.name,\n\t\t\tkey: actorData.key,\n\t\t};\n\t}\n}\n","// Constants for key handling\nexport const EMPTY_KEY = \"(none)\";\nexport const KEY_SEPARATOR = \",\";\n\n/**\n * Serializes an array of key strings into a single string for use with idFromName\n *\n * @param name The actor name\n * @param key Array of key strings to serialize\n * @returns A single string containing the serialized name and key\n */\nexport function serializeNameAndKey(name: string, key: string[]): string {\n\t// Escape colons in the name\n\tconst escapedName = name.replace(/:/g, \"\\\\:\");\n\n\t// For empty keys, just return the name and a marker\n\tif (key.length === 0) {\n\t\treturn `${escapedName}:${EMPTY_KEY}`;\n\t}\n\n\t// Serialize the key array\n\tconst serializedKey = serializeKey(key);\n\n\t// Combine name and serialized key\n\treturn `${escapedName}:${serializedKey}`;\n}\n\n/**\n * Serializes an array of key strings into a single string\n *\n * @param key Array of key strings to serialize\n * @returns A single string containing the serialized key\n */\nexport function serializeKey(key: string[]): string {\n\t// Use a special marker for empty key arrays\n\tif (key.length === 0) {\n\t\treturn EMPTY_KEY;\n\t}\n\n\t// Escape each key part to handle the separator and the empty key marker\n\tconst escapedParts = key.map((part) => {\n\t\t// First check if it matches our empty key marker\n\t\tif (part === EMPTY_KEY) {\n\t\t\treturn `\\\\${EMPTY_KEY}`;\n\t\t}\n\n\t\t// Escape backslashes first, then commas\n\t\tlet escaped = part.replace(/\\\\/g, \"\\\\\\\\\");\n\t\tescaped = escaped.replace(/,/g, \"\\\\,\");\n\t\treturn escaped;\n\t});\n\n\treturn escapedParts.join(KEY_SEPARATOR);\n}\n\n/**\n * Deserializes a key string back into an array of key strings\n *\n * @param keyString The serialized key string\n * @returns Array of key strings\n */\nexport function deserializeKey(keyString: string): string[] {\n\t// Handle empty values\n\tif (!keyString) {\n\t\treturn [];\n\t}\n\n\t// Check for special empty key marker\n\tif (keyString === EMPTY_KEY) {\n\t\treturn [];\n\t}\n\n\t// Split by unescaped commas and unescape the escaped characters\n\tconst parts: string[] = [];\n\tlet currentPart = \"\";\n\tlet escaping = false;\n\n\tfor (let i = 0; i < keyString.length; i++) {\n\t\tconst char = keyString[i];\n\n\t\tif (escaping) {\n\t\t\t// This is an escaped character, add it directly\n\t\t\tcurrentPart += char;\n\t\t\tescaping = false;\n\t\t} else if (char === \"\\\\\") {\n\t\t\t// Start of an escape sequence\n\t\t\tescaping = true;\n\t\t} else if (char === KEY_SEPARATOR) {\n\t\t\t// This is a separator\n\t\t\tparts.push(currentPart);\n\t\t\tcurrentPart = \"\";\n\t\t} else {\n\t\t\t// Regular character\n\t\t\tcurrentPart += char;\n\t\t}\n\t}\n\n\t// Add the last part if it exists\n\tif (currentPart || parts.length > 0) {\n\t\tparts.push(currentPart);\n\t}\n\n\treturn parts;\n}\n","// Modified from https://github.com/honojs/hono/blob/40ea0eee58e39b31053a0246c595434f1094ad31/src/adapter/cloudflare-workers/websocket.ts#L17\n//\n// This version calls the open event by default\n\nimport type { UpgradeWebSocket, WSEvents, WSReadyState } from \"hono/ws\";\nimport { defineWebSocketHelper, WSContext } from \"hono/ws\";\n\n// Based on https://github.com/honojs/hono/issues/1153#issuecomment-1767321332\nexport const upgradeWebSocket: UpgradeWebSocket<\n\tWebSocket,\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tany,\n\tWSEvents<WebSocket>\n> = defineWebSocketHelper(async (c, events) => {\n\tconst upgradeHeader = c.req.header(\"Upgrade\");\n\tif (upgradeHeader !== \"websocket\") {\n\t\treturn;\n\t}\n\n\tconst webSocketPair = new WebSocketPair();\n\tconst client: WebSocket = webSocketPair[0];\n\tconst server: WebSocket = webSocketPair[1];\n\n\tconst wsContext = new WSContext<WebSocket>({\n\t\tclose: (code, reason) => server.close(code, reason),\n\t\tget protocol() {\n\t\t\treturn server.protocol;\n\t\t},\n\t\traw: server,\n\t\tget readyState() {\n\t\t\treturn server.readyState as WSReadyState;\n\t\t},\n\t\turl: server.url ? new URL(server.url) : null,\n\t\tsend: (source) => server.send(source),\n\t});\n\n\tif (events.onClose) {\n\t\tserver.addEventListener(\"close\", (evt: CloseEvent) =>\n\t\t\tevents.onClose?.(evt, wsContext),\n\t\t);\n\t}\n\tif (events.onMessage) {\n\t\tserver.addEventListener(\"message\", (evt: MessageEvent) =>\n\t\t\tevents.onMessage?.(evt, wsContext),\n\t\t);\n\t}\n\tif (events.onError) {\n\t\tserver.addEventListener(\"error\", (evt: Event) =>\n\t\t\tevents.onError?.(evt, wsContext),\n\t\t);\n\t}\n\n\tserver.accept?.();\n\n\t// note: cloudflare actors doesn't support 'open' event, so we call it immediately with a fake event\n\t//\n\t// we have to do this after `server.accept() is called`\n\tevents.onOpen?.(new Event(\"open\"), wsContext);\n\n\treturn new Response(null, {\n\t\tstatus: 101,\n\t\theaders: {\n\t\t\t// HACK: Required in order for Cloudflare to not error with \"Network connection lost\"\n\t\t\t//\n\t\t\t// This bug undocumented. Cannot easily reproduce outside of RivetKit.\n\t\t\t\"Sec-WebSocket-Protocol\": \"rivetkit\",\n\t\t},\n\t\twebSocket: client,\n\t});\n});\n"],"mappings":"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","names":["env","KEYS","env","_a","env","ActorHandler"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rivetkit/cloudflare-workers",
3
- "version": "0.9.8",
3
+ "version": "0.9.9",
4
4
  "keywords": [
5
5
  "rivetkit",
6
6
  "cloudflare",
@@ -42,7 +42,7 @@
42
42
  "invariant": "^2.2.4",
43
43
  "zod": "^3.25.76",
44
44
  "hono": "4.8.3",
45
- "@rivetkit/core": "0.9.8"
45
+ "@rivetkit/core": "0.9.9"
46
46
  },
47
47
  "stableVersion": "0.8.0",
48
48
  "scripts": {
@@ -42,9 +42,8 @@ export class CloudflareDurableObjectGlobalState {
42
42
  }
43
43
  }
44
44
 
45
- export interface ActorDriverContext {
46
- ctx: DurableObjectState;
47
- env: unknown;
45
+ export interface DriverContext {
46
+ state: DurableObjectState;
48
47
  }
49
48
 
50
49
  // Actor handler to track running instances
@@ -143,9 +142,9 @@ export class CloudflareActorsActorDriver implements ActorDriver {
143
142
  return handler.genericConnGlobalState;
144
143
  }
145
144
 
146
- getContext(actorId: string): ActorDriverContext {
145
+ getContext(actorId: string): DriverContext {
147
146
  const state = this.#globalState.getDOState(actorId);
148
- return { ctx: state.ctx, env: state.env };
147
+ return { state: state.ctx };
149
148
  }
150
149
 
151
150
  async readPersistedData(actorId: string): Promise<Uint8Array | undefined> {
@@ -1,4 +1,4 @@
1
- import { DurableObject } from "cloudflare:workers";
1
+ import { DurableObject, env } from "cloudflare:workers";
2
2
  import type {
3
3
  ActorKey,
4
4
  ActorRouter,
@@ -16,7 +16,7 @@ import {
16
16
  CloudflareDurableObjectGlobalState,
17
17
  createCloudflareActorsActorDriverBuilder,
18
18
  } from "./actor-driver";
19
- import { type Bindings, CF_AMBIENT_ENV } from "./handler";
19
+ import type { Bindings } from "./handler";
20
20
  import { logger } from "./log";
21
21
 
22
22
  export const KEYS = {
@@ -70,8 +70,6 @@ export function createActorDurableObject(
70
70
  #actor?: LoadedActor;
71
71
 
72
72
  async #loadActor(): Promise<LoadedActor> {
73
- // This is always called from another context using CF_AMBIENT_ENV
74
-
75
73
  // Wait for init
76
74
  if (!this.#initialized) {
77
75
  // Wait for init
@@ -112,7 +110,7 @@ export function createActorDurableObject(
112
110
  // of knowing when the DO shuts down. We're making a broad assumption
113
111
  // that DO will boot a new isolate frequenlty enough that this is not an issue.
114
112
  const actorId = this.ctx.id.toString();
115
- globalState.setDOState(actorId, { ctx: this.ctx, env: this.env });
113
+ globalState.setDOState(actorId, { ctx: this.ctx, env: env });
116
114
 
117
115
  // Configure actor driver
118
116
  runConfig.driver.actor =
@@ -156,59 +154,53 @@ export function createActorDurableObject(
156
154
  async initialize(req: ActorInitRequest) {
157
155
  // TODO: Need to add this to a core promise that needs to be resolved before start
158
156
 
159
- return await CF_AMBIENT_ENV.run(this.env, async () => {
160
- await this.ctx.storage.put({
161
- [KEYS.NAME]: req.name,
162
- [KEYS.KEY]: req.key,
163
- [KEYS.PERSIST_DATA]: serializeEmptyPersistData(req.input),
164
- });
165
- this.#initialized = {
166
- name: req.name,
167
- key: req.key,
168
- };
169
-
170
- logger().debug("initialized actor", { key: req.key });
171
-
172
- // Preemptively actor so the lifecycle hooks are called
173
- await this.#loadActor();
157
+ await this.ctx.storage.put({
158
+ [KEYS.NAME]: req.name,
159
+ [KEYS.KEY]: req.key,
160
+ [KEYS.PERSIST_DATA]: serializeEmptyPersistData(req.input),
174
161
  });
162
+ this.#initialized = {
163
+ name: req.name,
164
+ key: req.key,
165
+ };
166
+
167
+ logger().debug("initialized actor", { key: req.key });
168
+
169
+ // Preemptively actor so the lifecycle hooks are called
170
+ await this.#loadActor();
175
171
  }
176
172
 
177
173
  async fetch(request: Request): Promise<Response> {
178
- return await CF_AMBIENT_ENV.run(this.env, async () => {
179
- const { actorRouter } = await this.#loadActor();
174
+ const { actorRouter } = await this.#loadActor();
180
175
 
181
- const actorId = this.ctx.id.toString();
182
- return await actorRouter.fetch(request, {
183
- actorId,
184
- });
176
+ const actorId = this.ctx.id.toString();
177
+ return await actorRouter.fetch(request, {
178
+ actorId,
185
179
  });
186
180
  }
187
181
 
188
182
  async alarm(): Promise<void> {
189
- return await CF_AMBIENT_ENV.run(this.env, async () => {
190
- await this.#loadActor();
191
- const actorId = this.ctx.id.toString();
192
-
193
- // Get the actor driver
194
- const managerDriver = runConfig.driver.manager(
195
- registry.config,
196
- runConfig,
197
- );
198
- const inlineClient = createClientWithDriver(
199
- createInlineClientDriver(managerDriver),
200
- );
201
- const actorDriver = runConfig.driver.actor(
202
- registry.config,
203
- runConfig,
204
- managerDriver,
205
- inlineClient,
206
- );
207
-
208
- // Load the actor instance and trigger alarm
209
- const actor = await actorDriver.loadActor(actorId);
210
- await actor.onAlarm();
211
- });
183
+ await this.#loadActor();
184
+ const actorId = this.ctx.id.toString();
185
+
186
+ // Get the actor driver
187
+ const managerDriver = runConfig.driver.manager(
188
+ registry.config,
189
+ runConfig,
190
+ );
191
+ const inlineClient = createClientWithDriver(
192
+ createInlineClientDriver(managerDriver),
193
+ );
194
+ const actorDriver = runConfig.driver.actor(
195
+ registry.config,
196
+ runConfig,
197
+ managerDriver,
198
+ inlineClient,
199
+ );
200
+
201
+ // Load the actor instance and trigger alarm
202
+ const actor = await actorDriver.loadActor(actorId);
203
+ await actor.onAlarm();
212
204
  }
213
205
  };
214
206
  }
package/src/handler.ts CHANGED
@@ -1,8 +1,7 @@
1
- import { AsyncLocalStorage } from "node:async_hooks";
1
+ import { env } from "cloudflare:workers";
2
2
  import type { Registry, RunConfig } from "@rivetkit/core";
3
3
  import type { Client } from "@rivetkit/core/client";
4
4
  import { Hono } from "hono";
5
- import invariant from "invariant";
6
5
  import {
7
6
  type ActorHandlerInterface,
8
7
  createActorDurableObject,
@@ -23,12 +22,8 @@ export interface Bindings {
23
22
  *
24
23
  * Use getCloudflareAmbientEnv unless using CF_AMBIENT_ENV.run.
25
24
  */
26
- export const CF_AMBIENT_ENV = new AsyncLocalStorage<Bindings>();
27
-
28
25
  export function getCloudflareAmbientEnv(): Bindings {
29
- const env = CF_AMBIENT_ENV.getStore();
30
- invariant(env, "missing CF_AMBIENT_ENV");
31
- return env;
26
+ return env as unknown as Bindings;
32
27
  }
33
28
 
34
29
  interface Handler {
@@ -87,7 +82,7 @@ export function createServer<R extends Registry<any>>(
87
82
  // Create Cloudflare handler
88
83
  const handler = {
89
84
  fetch: (request, env, ctx) => {
90
- return CF_AMBIENT_ENV.run(env, () => app.fetch(request, env, ctx));
85
+ return app.fetch(request, env, ctx);
91
86
  },
92
87
  } satisfies ExportedHandler<Bindings>;
93
88
 
package/src/mod.ts CHANGED
@@ -1,2 +1,3 @@
1
+ export type { DriverContext } from "./actor-driver";
1
2
  export type { InputConfig as Config } from "./config";
2
3
  export { type Bindings, createServer, createServerHandler } from "./handler";