@rivetkit/cloudflare-workers 0.9.0 → 0.9.1
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 +15 -17
- package/dist/mod.cjs.map +1 -1
- package/dist/mod.d.cts +13 -13
- package/dist/mod.d.ts +13 -13
- package/dist/mod.js +17 -19
- package/dist/mod.js.map +1 -1
- package/package.json +4 -4
- package/src/actor-driver.ts +5 -2
- package/src/actor-handler-do.ts +5 -5
- package/src/config.ts +1 -1
- package/src/handler.ts +8 -8
- package/src/manager-driver.ts +11 -11
- package/src/mod.ts +1 -1
- package/src/util.ts +73 -74
- package/src/websocket.ts +1 -1
package/dist/mod.cjs
CHANGED
|
@@ -1,19 +1,16 @@
|
|
|
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(); } }// src/
|
|
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(); } }// src/handler.ts
|
|
2
|
+
var _async_hooks = require('async_hooks');
|
|
3
|
+
var _partition = require('@rivetkit/core/topologies/partition');
|
|
4
|
+
var _hono = require('hono');
|
|
5
|
+
var _invariant = require('invariant'); var _invariant2 = _interopRequireDefault(_invariant);
|
|
6
|
+
|
|
7
|
+
// src/actor-handler-do.ts
|
|
2
8
|
var _cloudflareworkers = require('cloudflare:workers');
|
|
3
9
|
var _driverhelpers = require('@rivetkit/core/driver-helpers');
|
|
4
10
|
|
|
5
|
-
// src/log.ts
|
|
6
|
-
var _log = require('@rivetkit/core/log');
|
|
7
|
-
var LOGGER_NAME = "driver-cloudflare-workers";
|
|
8
|
-
function logger() {
|
|
9
|
-
return _log.getLogger.call(void 0, LOGGER_NAME);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// src/actor-handler-do.ts
|
|
13
|
-
var _partition = require('@rivetkit/core/topologies/partition');
|
|
14
11
|
|
|
15
12
|
// src/actor-driver.ts
|
|
16
|
-
|
|
13
|
+
|
|
17
14
|
var CloudflareDurableObjectGlobalState = class {
|
|
18
15
|
// Single map for all actor state
|
|
19
16
|
#dos = /* @__PURE__ */ new Map();
|
|
@@ -52,6 +49,13 @@ var CloudflareActorsActorDriver = class {
|
|
|
52
49
|
}
|
|
53
50
|
};
|
|
54
51
|
|
|
52
|
+
// src/log.ts
|
|
53
|
+
var _log = require('@rivetkit/core/log');
|
|
54
|
+
var LOGGER_NAME = "driver-cloudflare-workers";
|
|
55
|
+
function logger() {
|
|
56
|
+
return _log.getLogger.call(void 0, LOGGER_NAME);
|
|
57
|
+
}
|
|
58
|
+
|
|
55
59
|
// src/actor-handler-do.ts
|
|
56
60
|
var KEYS = {
|
|
57
61
|
NAME: "rivetkit:name",
|
|
@@ -162,10 +166,6 @@ var ConfigSchema = _driverhelpers.RunConfigSchema.removeDefault().omit({ driver:
|
|
|
162
166
|
app: _zod.z.custom().optional()
|
|
163
167
|
}).default({});
|
|
164
168
|
|
|
165
|
-
// src/handler.ts
|
|
166
|
-
var _hono = require('hono');
|
|
167
|
-
|
|
168
|
-
|
|
169
169
|
// src/manager-driver.ts
|
|
170
170
|
|
|
171
171
|
|
|
@@ -487,8 +487,6 @@ var upgradeWebSocket = _ws.defineWebSocketHelper.call(void 0, async (c, events)
|
|
|
487
487
|
});
|
|
488
488
|
|
|
489
489
|
// src/handler.ts
|
|
490
|
-
|
|
491
|
-
var _async_hooks = require('async_hooks');
|
|
492
490
|
var CF_AMBIENT_ENV = new (0, _async_hooks.AsyncLocalStorage)();
|
|
493
491
|
function getCloudflareAmbientEnv() {
|
|
494
492
|
const env = CF_AMBIENT_ENV.getStore();
|
package/dist/mod.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/nathan/rivetkit/packages/platforms/cloudflare-workers/dist/mod.cjs","../src/actor-handler-do.ts","../src/log.ts","../src/actor-driver.ts","../src/config.ts","../src/handler.ts","../src/manager-driver.ts","../src/util.ts","../src/websocket.ts"],"names":["_a","invariant"],"mappings":"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","file":"/home/nathan/rivetkit/packages/platforms/cloudflare-workers/dist/mod.cjs","sourcesContent":[null,"import { DurableObject } from \"cloudflare:workers\";\nimport type { Registry, RunConfig, ActorKey } from \"@rivetkit/core\";\nimport { serializeEmptyPersistData } from \"@rivetkit/core/driver-helpers\";\nimport { logger } from \"./log\";\nimport { PartitionTopologyActor } from \"@rivetkit/core/topologies/partition\";\nimport {\n\tCloudflareDurableObjectGlobalState,\n\tCloudflareActorsActorDriver,\n} from \"./actor-driver\";\nimport { Bindings, CF_AMBIENT_ENV } from \"./handler\";\nimport { ExecutionContext } from \"hono\";\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\tactorTopology: PartitionTopologyActor;\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// Configure actor driver\n\t\t\trunConfig.driver.actor = new CloudflareActorsActorDriver(globalState);\n\n\t\t\tconst actorTopology = new PartitionTopologyActor(\n\t\t\t\tregistry.config,\n\t\t\t\trunConfig,\n\t\t\t);\n\n\t\t\t// Register DO with global state\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// Save actor\n\t\t\tthis.#actor = {\n\t\t\t\tactorTopology,\n\t\t\t};\n\n\t\t\t// Start actor\n\t\t\tawait actorTopology.start(\n\t\t\t\tactorId,\n\t\t\t\tthis.#initialized.name,\n\t\t\t\tthis.#initialized.key,\n\t\t\t\t// TODO:\n\t\t\t\t\"unknown\",\n\t\t\t);\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 { actorTopology } = await this.#loadActor();\n\n\t\t\t\tconst ctx = this.ctx;\n\t\t\t\treturn await actorTopology.router.fetch(\n\t\t\t\t\trequest,\n\t\t\t\t\tthis.env,\n\t\t\t\t\t// Implement execution context so we can wait on requests\n\t\t\t\t\t{\n\t\t\t\t\t\twaitUntil(promise: Promise<unknown>) {\n\t\t\t\t\t\t\tctx.waitUntil(promise);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpassThroughOnException() {\n\t\t\t\t\t\t\t// Do nothing\n\t\t\t\t\t\t},\n\t\t\t\t\t\tprops: {},\n\t\t\t\t\t} satisfies ExecutionContext,\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\tconst { actorTopology } = await this.#loadActor();\n\t\t\t\tawait actorTopology.actor.onAlarm();\n\t\t\t});\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 type { ActorDriver, AnyActorInstance } 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\nexport class CloudflareActorsActorDriver implements ActorDriver {\n\t#globalState: CloudflareDurableObjectGlobalState;\n\n\tconstructor(globalState: CloudflareDurableObjectGlobalState) {\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\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","import { RunConfigSchema } from \"@rivetkit/core/driver-helpers\";\nimport { 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 {\n\ttype DurableObjectConstructor,\n\ttype ActorHandlerInterface,\n\tcreateActorDurableObject,\n} from \"./actor-handler-do\";\nimport { ConfigSchema, type Config, type InputConfig } from \"./config\";\nimport { Hono } from \"hono\";\nimport { PartitionTopologyManager } from \"@rivetkit/core/topologies/partition\";\nimport type { Client } from \"@rivetkit/core/client\";\nimport { CloudflareActorsManagerDriver } from \"./manager-driver\";\nimport { DriverConfig, Registry, RunConfig } from \"@rivetkit/core\";\nimport { upgradeWebSocket } from \"./websocket\";\nimport invariant from \"invariant\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\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\ttopology: \"partition\",\n\t\t\tmanager: new CloudflareActorsManagerDriver(),\n\t\t\t// HACK: We can't build the actor driver until we're inside the Druable 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\tconst managerTopology = new PartitionTopologyManager(\n\t\tregistry.config,\n\t\trunConfig,\n\t);\n\n\treturn {\n\t\tclient: managerTopology.inlineClient 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\n\t\t\tapp.route(\"/registry\", managerTopology.router);\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 {\n\ttype ManagerDriver,\n\ttype GetForIdInput,\n\ttype GetWithKeyInput,\n\ttype ActorOutput,\n\ttype CreateInput,\n\ttype GetOrCreateWithKeyInput,\n\ttype ConnRoutingHandler,\n\tHEADER_EXPOSE_INTERNAL_ERROR,\n\tHEADER_ENCODING,\n\tHEADER_CONN_PARAMS,\n\tHEADER_AUTH_DATA,\n} from \"@rivetkit/core/driver-helpers\";\nimport { ActorAlreadyExists, InternalError } from \"@rivetkit/core/errors\";\nimport { Bindings } from \"./mod\";\nimport { logger } from \"./log\";\nimport { serializeNameAndKey, serializeKey } from \"./util\";\nimport { getCloudflareAmbientEnv } from \"./handler\";\nimport { Encoding } from \"@rivetkit/core\";\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\tconnRoutingHandler: ConnRoutingHandler;\n\n\tconstructor() {\n\t\tthis.connRoutingHandler = {\n\t\t\tcustom: {\n\t\t\t\tsendRequest: async (actorId, actorRequest): Promise<Response> => {\n\t\t\t\t\tconst env = getCloudflareAmbientEnv();\n\n\t\t\t\t\tlogger().debug(\"sending request to durable object\", {\n\t\t\t\t\t\tactorId,\n\t\t\t\t\t\tmethod: actorRequest.method,\n\t\t\t\t\t\turl: actorRequest.url,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst id = env.ACTOR_DO.idFromString(actorId);\n\t\t\t\t\tconst stub = env.ACTOR_DO.get(id);\n\n\t\t\t\t\treturn await stub.fetch(actorRequest);\n\t\t\t\t},\n\n\t\t\t\topenWebSocket: async (\n\t\t\t\t\tactorId,\n\t\t\t\t\tencodingKind: Encoding,\n\t\t\t\t\tparams: unknown,\n\t\t\t\t): Promise<WebSocket> => {\n\t\t\t\t\tconst env = getCloudflareAmbientEnv();\n\n\t\t\t\t\tlogger().debug(\"opening websocket to durable object\", { actorId });\n\n\t\t\t\t\t// Make a fetch request to the Durable Object with WebSocket upgrade\n\t\t\t\t\tconst id = env.ACTOR_DO.idFromString(actorId);\n\t\t\t\t\tconst stub = env.ACTOR_DO.get(id);\n\n\t\t\t\t\tconst headers: Record<string, string> = {\n\t\t\t\t\t\tUpgrade: \"websocket\",\n\t\t\t\t\t\tConnection: \"Upgrade\",\n\t\t\t\t\t\t[HEADER_EXPOSE_INTERNAL_ERROR]: \"true\",\n\t\t\t\t\t\t[HEADER_ENCODING]: encodingKind,\n\t\t\t\t\t};\n\t\t\t\t\tif (params) {\n\t\t\t\t\t\theaders[HEADER_CONN_PARAMS] = JSON.stringify(params);\n\t\t\t\t\t}\n\t\t\t\t\t// HACK: See packages/platforms/cloudflare-workers/src/websocket.ts\n\t\t\t\t\theaders[\"sec-websocket-protocol\"] = \"rivetkit\";\n\n\t\t\t\t\tconst response = await stub.fetch(\"http://actor/connect/websocket\", {\n\t\t\t\t\t\theaders,\n\t\t\t\t\t});\n\t\t\t\t\tconst webSocket = response.webSocket;\n\n\t\t\t\t\tif (!webSocket) {\n\t\t\t\t\t\tthrow new InternalError(\n\t\t\t\t\t\t\t\"missing websocket connection in response from DO\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tlogger().debug(\"durable object websocket connection open\", {\n\t\t\t\t\t\tactorId,\n\t\t\t\t\t});\n\n\t\t\t\t\twebSocket.accept();\n\n\t\t\t\t\t// TODO: Is this still needed?\n\t\t\t\t\t// HACK: Cloudflare does not call onopen automatically, so we need\n\t\t\t\t\t// to call this on the next tick\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t(webSocket as any).onopen?.(new Event(\"open\"));\n\t\t\t\t\t}, 0);\n\n\t\t\t\t\treturn webSocket as unknown as WebSocket;\n\t\t\t\t},\n\n\t\t\t\tproxyRequest: async (c, actorRequest, actorId): Promise<Response> => {\n\t\t\t\t\tlogger().debug(\"forwarding request to durable object\", {\n\t\t\t\t\t\tactorId,\n\t\t\t\t\t\tmethod: actorRequest.method,\n\t\t\t\t\t\turl: actorRequest.url,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst id = c.env.ACTOR_DO.idFromString(actorId);\n\t\t\t\t\tconst stub = c.env.ACTOR_DO.get(id);\n\n\t\t\t\t\treturn await stub.fetch(actorRequest);\n\t\t\t\t},\n\t\t\t\tproxyWebSocket: async (\n\t\t\t\t\tc,\n\t\t\t\t\tpath,\n\t\t\t\t\tactorId,\n\t\t\t\t\tencoding,\n\t\t\t\t\tparams,\n\t\t\t\t\tauthData,\n\t\t\t\t) => {\n\t\t\t\t\tlogger().debug(\"forwarding websocket to durable object\", {\n\t\t\t\t\t\tactorId,\n\t\t\t\t\t\tpath,\n\t\t\t\t\t});\n\n\t\t\t\t\t// Validate upgrade\n\t\t\t\t\tconst upgradeHeader = c.req.header(\"Upgrade\");\n\t\t\t\t\tif (!upgradeHeader || upgradeHeader !== \"websocket\") {\n\t\t\t\t\t\treturn new Response(\"Expected Upgrade: websocket\", {\n\t\t\t\t\t\t\tstatus: 426,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\t// TODO: strip headers\n\t\t\t\t\tconst newUrl = new URL(`http://actor${path}`);\n\t\t\t\t\tconst actorRequest = new Request(newUrl, c.req.raw);\n\n\t\t\t\t\t// Always build fresh request to prevent forwarding unwanted headers\n\t\t\t\t\t// HACK: Since we can't build a new request, we need to remove\n\t\t\t\t\t// non-standard headers manually\n\t\t\t\t\tconst headerKeys: string[] = [];\n\t\t\t\t\tactorRequest.headers.forEach((v, k) => headerKeys.push(k));\n\t\t\t\t\tfor (const k of headerKeys) {\n\t\t\t\t\t\tif (!STANDARD_WEBSOCKET_HEADERS.includes(k)) {\n\t\t\t\t\t\t\tactorRequest.headers.delete(k);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Add RivetKit headers\n\t\t\t\t\tactorRequest.headers.set(HEADER_EXPOSE_INTERNAL_ERROR, \"true\");\n\t\t\t\t\tactorRequest.headers.set(HEADER_ENCODING, encoding);\n\t\t\t\t\tif (params) {\n\t\t\t\t\t\tactorRequest.headers.set(\n\t\t\t\t\t\t\tHEADER_CONN_PARAMS,\n\t\t\t\t\t\t\tJSON.stringify(params),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (authData) {\n\t\t\t\t\t\tactorRequest.headers.set(\n\t\t\t\t\t\t\tHEADER_AUTH_DATA,\n\t\t\t\t\t\t\tJSON.stringify(authData),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst id = c.env.ACTOR_DO.idFromString(actorId);\n\t\t\t\t\tconst stub = c.env.ACTOR_DO.get(id);\n\n\t\t\t\t\treturn await stub.fetch(actorRequest);\n\t\t\t\t},\n\t\t\t},\n\t\t};\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 // Escape colons in the name\n const escapedName = name.replace(/:/g, \"\\\\:\");\n\n // For empty keys, just return the name and a marker\n if (key.length === 0) {\n return `${escapedName}:${EMPTY_KEY}`;\n }\n\n // Serialize the key array\n const serializedKey = serializeKey(key);\n\n // Combine name and serialized key\n return `${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 // Use a special marker for empty key arrays\n if (key.length === 0) {\n return EMPTY_KEY;\n }\n\n // Escape each key part to handle the separator and the empty key marker\n const escapedParts = key.map(part => {\n // First check if it matches our empty key marker\n if (part === EMPTY_KEY) {\n return `\\\\${EMPTY_KEY}`;\n }\n\n // Escape backslashes first, then commas\n let escaped = part.replace(/\\\\/g, \"\\\\\\\\\");\n escaped = escaped.replace(/,/g, \"\\\\,\");\n return escaped;\n });\n\n return 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 // Handle empty values\n if (!keyString) {\n return [];\n }\n\n // Check for special empty key marker\n if (keyString === EMPTY_KEY) {\n return [];\n }\n\n // Split by unescaped commas and unescape the escaped characters\n const parts: string[] = [];\n let currentPart = '';\n let escaping = false;\n\n for (let i = 0; i < keyString.length; i++) {\n const char = keyString[i];\n\n if (escaping) {\n // This is an escaped character, add it directly\n currentPart += char;\n escaping = false;\n } else if (char === '\\\\') {\n // Start of an escape sequence\n escaping = true;\n } else if (char === KEY_SEPARATOR) {\n // This is a separator\n parts.push(currentPart);\n currentPart = '';\n } else {\n // Regular character\n currentPart += char;\n }\n }\n\n // Add the last part if it exists\n if (currentPart || parts.length > 0) {\n parts.push(currentPart);\n }\n\n return parts;\n}\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 { WSContext, defineWebSocketHelper } from \"hono/ws\";\nimport type { UpgradeWebSocket, WSEvents, WSReadyState } 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/platforms/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"],"mappings":"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","file":"/home/nathan/rivetkit/packages/platforms/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 { PartitionTopologyManager } from \"@rivetkit/core/topologies/partition\";\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\ttopology: \"partition\",\n\t\t\tmanager: new CloudflareActorsManagerDriver(),\n\t\t\t// HACK: We can't build the actor driver until we're inside the Druable 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\tconst managerTopology = new PartitionTopologyManager(\n\t\tregistry.config,\n\t\trunConfig,\n\t);\n\n\treturn {\n\t\tclient: managerTopology.inlineClient 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\n\t\t\tapp.route(\"/registry\", managerTopology.router);\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 { ActorKey, Registry, RunConfig } from \"@rivetkit/core\";\nimport { serializeEmptyPersistData } from \"@rivetkit/core/driver-helpers\";\nimport { PartitionTopologyActor } from \"@rivetkit/core/topologies/partition\";\nimport type { ExecutionContext } from \"hono\";\nimport {\n\tCloudflareActorsActorDriver,\n\tCloudflareDurableObjectGlobalState,\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\tactorTopology: PartitionTopologyActor;\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// Configure actor driver\n\t\t\trunConfig.driver.actor = new CloudflareActorsActorDriver(globalState);\n\n\t\t\tconst actorTopology = new PartitionTopologyActor(\n\t\t\t\tregistry.config,\n\t\t\t\trunConfig,\n\t\t\t);\n\n\t\t\t// Register DO with global state\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// Save actor\n\t\t\tthis.#actor = {\n\t\t\t\tactorTopology,\n\t\t\t};\n\n\t\t\t// Start actor\n\t\t\tawait actorTopology.start(\n\t\t\t\tactorId,\n\t\t\t\tthis.#initialized.name,\n\t\t\t\tthis.#initialized.key,\n\t\t\t\t// TODO:\n\t\t\t\t\"unknown\",\n\t\t\t);\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 { actorTopology } = await this.#loadActor();\n\n\t\t\t\tconst ctx = this.ctx;\n\t\t\t\treturn await actorTopology.router.fetch(\n\t\t\t\t\trequest,\n\t\t\t\t\tthis.env,\n\t\t\t\t\t// Implement execution context so we can wait on requests\n\t\t\t\t\t{\n\t\t\t\t\t\twaitUntil(promise: Promise<unknown>) {\n\t\t\t\t\t\t\tctx.waitUntil(promise);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpassThroughOnException() {\n\t\t\t\t\t\t\t// Do nothing\n\t\t\t\t\t\t},\n\t\t\t\t\t\tprops: {},\n\t\t\t\t\t} satisfies ExecutionContext,\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\tconst { actorTopology } = await this.#loadActor();\n\t\t\t\tawait actorTopology.actor.onAlarm();\n\t\t\t});\n\t\t}\n\t};\n}\n","import type {\n\tActorDriver,\n\tAnyActorInstance,\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\nexport class CloudflareActorsActorDriver implements ActorDriver {\n\t#globalState: CloudflareDurableObjectGlobalState;\n\n\tconstructor(globalState: CloudflareDurableObjectGlobalState) {\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\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","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 ConnRoutingHandler,\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 { 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\tconnRoutingHandler: ConnRoutingHandler;\n\n\tconstructor() {\n\t\tthis.connRoutingHandler = {\n\t\t\tcustom: {\n\t\t\t\tsendRequest: async (actorId, actorRequest): Promise<Response> => {\n\t\t\t\t\tconst env = getCloudflareAmbientEnv();\n\n\t\t\t\t\tlogger().debug(\"sending request to durable object\", {\n\t\t\t\t\t\tactorId,\n\t\t\t\t\t\tmethod: actorRequest.method,\n\t\t\t\t\t\turl: actorRequest.url,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst id = env.ACTOR_DO.idFromString(actorId);\n\t\t\t\t\tconst stub = env.ACTOR_DO.get(id);\n\n\t\t\t\t\treturn await stub.fetch(actorRequest);\n\t\t\t\t},\n\n\t\t\t\topenWebSocket: async (\n\t\t\t\t\tactorId,\n\t\t\t\t\tencodingKind: Encoding,\n\t\t\t\t\tparams: unknown,\n\t\t\t\t): Promise<WebSocket> => {\n\t\t\t\t\tconst env = getCloudflareAmbientEnv();\n\n\t\t\t\t\tlogger().debug(\"opening websocket to durable object\", { actorId });\n\n\t\t\t\t\t// Make a fetch request to the Durable Object with WebSocket upgrade\n\t\t\t\t\tconst id = env.ACTOR_DO.idFromString(actorId);\n\t\t\t\t\tconst stub = env.ACTOR_DO.get(id);\n\n\t\t\t\t\tconst headers: Record<string, string> = {\n\t\t\t\t\t\tUpgrade: \"websocket\",\n\t\t\t\t\t\tConnection: \"Upgrade\",\n\t\t\t\t\t\t[HEADER_EXPOSE_INTERNAL_ERROR]: \"true\",\n\t\t\t\t\t\t[HEADER_ENCODING]: encodingKind,\n\t\t\t\t\t};\n\t\t\t\t\tif (params) {\n\t\t\t\t\t\theaders[HEADER_CONN_PARAMS] = JSON.stringify(params);\n\t\t\t\t\t}\n\t\t\t\t\t// HACK: See packages/platforms/cloudflare-workers/src/websocket.ts\n\t\t\t\t\theaders[\"sec-websocket-protocol\"] = \"rivetkit\";\n\n\t\t\t\t\tconst response = await stub.fetch(\"http://actor/connect/websocket\", {\n\t\t\t\t\t\theaders,\n\t\t\t\t\t});\n\t\t\t\t\tconst webSocket = response.webSocket;\n\n\t\t\t\t\tif (!webSocket) {\n\t\t\t\t\t\tthrow new InternalError(\n\t\t\t\t\t\t\t\"missing websocket connection in response from DO\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tlogger().debug(\"durable object websocket connection open\", {\n\t\t\t\t\t\tactorId,\n\t\t\t\t\t});\n\n\t\t\t\t\twebSocket.accept();\n\n\t\t\t\t\t// TODO: Is this still needed?\n\t\t\t\t\t// HACK: Cloudflare does not call onopen automatically, so we need\n\t\t\t\t\t// to call this on the next tick\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t(webSocket as any).onopen?.(new Event(\"open\"));\n\t\t\t\t\t}, 0);\n\n\t\t\t\t\treturn webSocket as unknown as WebSocket;\n\t\t\t\t},\n\n\t\t\t\tproxyRequest: async (c, actorRequest, actorId): Promise<Response> => {\n\t\t\t\t\tlogger().debug(\"forwarding request to durable object\", {\n\t\t\t\t\t\tactorId,\n\t\t\t\t\t\tmethod: actorRequest.method,\n\t\t\t\t\t\turl: actorRequest.url,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst id = c.env.ACTOR_DO.idFromString(actorId);\n\t\t\t\t\tconst stub = c.env.ACTOR_DO.get(id);\n\n\t\t\t\t\treturn await stub.fetch(actorRequest);\n\t\t\t\t},\n\t\t\t\tproxyWebSocket: async (\n\t\t\t\t\tc,\n\t\t\t\t\tpath,\n\t\t\t\t\tactorId,\n\t\t\t\t\tencoding,\n\t\t\t\t\tparams,\n\t\t\t\t\tauthData,\n\t\t\t\t) => {\n\t\t\t\t\tlogger().debug(\"forwarding websocket to durable object\", {\n\t\t\t\t\t\tactorId,\n\t\t\t\t\t\tpath,\n\t\t\t\t\t});\n\n\t\t\t\t\t// Validate upgrade\n\t\t\t\t\tconst upgradeHeader = c.req.header(\"Upgrade\");\n\t\t\t\t\tif (!upgradeHeader || upgradeHeader !== \"websocket\") {\n\t\t\t\t\t\treturn new Response(\"Expected Upgrade: websocket\", {\n\t\t\t\t\t\t\tstatus: 426,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\t// TODO: strip headers\n\t\t\t\t\tconst newUrl = new URL(`http://actor${path}`);\n\t\t\t\t\tconst actorRequest = new Request(newUrl, c.req.raw);\n\n\t\t\t\t\t// Always build fresh request to prevent forwarding unwanted headers\n\t\t\t\t\t// HACK: Since we can't build a new request, we need to remove\n\t\t\t\t\t// non-standard headers manually\n\t\t\t\t\tconst headerKeys: string[] = [];\n\t\t\t\t\tactorRequest.headers.forEach((v, k) => headerKeys.push(k));\n\t\t\t\t\tfor (const k of headerKeys) {\n\t\t\t\t\t\tif (!STANDARD_WEBSOCKET_HEADERS.includes(k)) {\n\t\t\t\t\t\t\tactorRequest.headers.delete(k);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Add RivetKit headers\n\t\t\t\t\tactorRequest.headers.set(HEADER_EXPOSE_INTERNAL_ERROR, \"true\");\n\t\t\t\t\tactorRequest.headers.set(HEADER_ENCODING, encoding);\n\t\t\t\t\tif (params) {\n\t\t\t\t\t\tactorRequest.headers.set(\n\t\t\t\t\t\t\tHEADER_CONN_PARAMS,\n\t\t\t\t\t\t\tJSON.stringify(params),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (authData) {\n\t\t\t\t\t\tactorRequest.headers.set(\n\t\t\t\t\t\t\tHEADER_AUTH_DATA,\n\t\t\t\t\t\t\tJSON.stringify(authData),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst id = c.env.ACTOR_DO.idFromString(actorId);\n\t\t\t\t\tconst stub = c.env.ACTOR_DO.get(id);\n\n\t\t\t\t\treturn await stub.fetch(actorRequest);\n\t\t\t\t},\n\t\t\t},\n\t\t};\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
|
@@ -1,23 +1,13 @@
|
|
|
1
|
-
import { DurableObject } from 'cloudflare:workers';
|
|
2
|
-
import * as _rivetkit_core from '@rivetkit/core';
|
|
3
|
-
import { ActorKey, Registry } from '@rivetkit/core';
|
|
4
1
|
import * as hono_types from 'hono/types';
|
|
5
2
|
import * as hono from 'hono';
|
|
6
3
|
import { Hono } from 'hono';
|
|
7
4
|
import * as _rivetkit_core_utils from '@rivetkit/core/utils';
|
|
5
|
+
import * as _rivetkit_core from '@rivetkit/core';
|
|
6
|
+
import { ActorKey, Registry } from '@rivetkit/core';
|
|
8
7
|
import * as _rivetkit_core_driver_helpers from '@rivetkit/core/driver-helpers';
|
|
9
8
|
import { z } from 'zod';
|
|
10
9
|
import { Client } from '@rivetkit/core/client';
|
|
11
|
-
|
|
12
|
-
interface ActorHandlerInterface extends DurableObject {
|
|
13
|
-
initialize(req: ActorInitRequest): Promise<void>;
|
|
14
|
-
}
|
|
15
|
-
interface ActorInitRequest {
|
|
16
|
-
name: string;
|
|
17
|
-
key: ActorKey;
|
|
18
|
-
input?: unknown;
|
|
19
|
-
}
|
|
20
|
-
type DurableObjectConstructor = new (...args: ConstructorParameters<typeof DurableObject<Bindings>>) => DurableObject<Bindings>;
|
|
10
|
+
import { DurableObject } from 'cloudflare:workers';
|
|
21
11
|
|
|
22
12
|
declare const ConfigSchema: z.ZodDefault<z.ZodObject<Omit<{
|
|
23
13
|
driver: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
@@ -113,6 +103,16 @@ declare const ConfigSchema: z.ZodDefault<z.ZodObject<Omit<{
|
|
|
113
103
|
}>>;
|
|
114
104
|
type InputConfig = z.input<typeof ConfigSchema>;
|
|
115
105
|
|
|
106
|
+
interface ActorHandlerInterface extends DurableObject {
|
|
107
|
+
initialize(req: ActorInitRequest): Promise<void>;
|
|
108
|
+
}
|
|
109
|
+
interface ActorInitRequest {
|
|
110
|
+
name: string;
|
|
111
|
+
key: ActorKey;
|
|
112
|
+
input?: unknown;
|
|
113
|
+
}
|
|
114
|
+
type DurableObjectConstructor = new (...args: ConstructorParameters<typeof DurableObject<Bindings>>) => DurableObject<Bindings>;
|
|
115
|
+
|
|
116
116
|
/** Cloudflare Workers env */
|
|
117
117
|
interface Bindings {
|
|
118
118
|
ACTOR_KV: KVNamespace;
|
package/dist/mod.d.ts
CHANGED
|
@@ -1,23 +1,13 @@
|
|
|
1
|
-
import { DurableObject } from 'cloudflare:workers';
|
|
2
|
-
import * as _rivetkit_core from '@rivetkit/core';
|
|
3
|
-
import { ActorKey, Registry } from '@rivetkit/core';
|
|
4
1
|
import * as hono_types from 'hono/types';
|
|
5
2
|
import * as hono from 'hono';
|
|
6
3
|
import { Hono } from 'hono';
|
|
7
4
|
import * as _rivetkit_core_utils from '@rivetkit/core/utils';
|
|
5
|
+
import * as _rivetkit_core from '@rivetkit/core';
|
|
6
|
+
import { ActorKey, Registry } from '@rivetkit/core';
|
|
8
7
|
import * as _rivetkit_core_driver_helpers from '@rivetkit/core/driver-helpers';
|
|
9
8
|
import { z } from 'zod';
|
|
10
9
|
import { Client } from '@rivetkit/core/client';
|
|
11
|
-
|
|
12
|
-
interface ActorHandlerInterface extends DurableObject {
|
|
13
|
-
initialize(req: ActorInitRequest): Promise<void>;
|
|
14
|
-
}
|
|
15
|
-
interface ActorInitRequest {
|
|
16
|
-
name: string;
|
|
17
|
-
key: ActorKey;
|
|
18
|
-
input?: unknown;
|
|
19
|
-
}
|
|
20
|
-
type DurableObjectConstructor = new (...args: ConstructorParameters<typeof DurableObject<Bindings>>) => DurableObject<Bindings>;
|
|
10
|
+
import { DurableObject } from 'cloudflare:workers';
|
|
21
11
|
|
|
22
12
|
declare const ConfigSchema: z.ZodDefault<z.ZodObject<Omit<{
|
|
23
13
|
driver: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
@@ -113,6 +103,16 @@ declare const ConfigSchema: z.ZodDefault<z.ZodObject<Omit<{
|
|
|
113
103
|
}>>;
|
|
114
104
|
type InputConfig = z.input<typeof ConfigSchema>;
|
|
115
105
|
|
|
106
|
+
interface ActorHandlerInterface extends DurableObject {
|
|
107
|
+
initialize(req: ActorInitRequest): Promise<void>;
|
|
108
|
+
}
|
|
109
|
+
interface ActorInitRequest {
|
|
110
|
+
name: string;
|
|
111
|
+
key: ActorKey;
|
|
112
|
+
input?: unknown;
|
|
113
|
+
}
|
|
114
|
+
type DurableObjectConstructor = new (...args: ConstructorParameters<typeof DurableObject<Bindings>>) => DurableObject<Bindings>;
|
|
115
|
+
|
|
116
116
|
/** Cloudflare Workers env */
|
|
117
117
|
interface Bindings {
|
|
118
118
|
ACTOR_KV: KVNamespace;
|
package/dist/mod.js
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
|
+
// src/handler.ts
|
|
2
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
3
|
+
import { PartitionTopologyManager } from "@rivetkit/core/topologies/partition";
|
|
4
|
+
import { Hono } from "hono";
|
|
5
|
+
import invariant2 from "invariant";
|
|
6
|
+
|
|
1
7
|
// src/actor-handler-do.ts
|
|
2
8
|
import { DurableObject } from "cloudflare:workers";
|
|
3
9
|
import { serializeEmptyPersistData } from "@rivetkit/core/driver-helpers";
|
|
4
|
-
|
|
5
|
-
// src/log.ts
|
|
6
|
-
import { getLogger } from "@rivetkit/core/log";
|
|
7
|
-
var LOGGER_NAME = "driver-cloudflare-workers";
|
|
8
|
-
function logger() {
|
|
9
|
-
return getLogger(LOGGER_NAME);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// src/actor-handler-do.ts
|
|
13
10
|
import { PartitionTopologyActor } from "@rivetkit/core/topologies/partition";
|
|
14
11
|
|
|
15
12
|
// src/actor-driver.ts
|
|
@@ -52,6 +49,13 @@ var CloudflareActorsActorDriver = class {
|
|
|
52
49
|
}
|
|
53
50
|
};
|
|
54
51
|
|
|
52
|
+
// src/log.ts
|
|
53
|
+
import { getLogger } from "@rivetkit/core/log";
|
|
54
|
+
var LOGGER_NAME = "driver-cloudflare-workers";
|
|
55
|
+
function logger() {
|
|
56
|
+
return getLogger(LOGGER_NAME);
|
|
57
|
+
}
|
|
58
|
+
|
|
55
59
|
// src/actor-handler-do.ts
|
|
56
60
|
var KEYS = {
|
|
57
61
|
NAME: "rivetkit:name",
|
|
@@ -162,16 +166,12 @@ var ConfigSchema = RunConfigSchema.removeDefault().omit({ driver: true, getUpgra
|
|
|
162
166
|
app: z.custom().optional()
|
|
163
167
|
}).default({});
|
|
164
168
|
|
|
165
|
-
// src/handler.ts
|
|
166
|
-
import { Hono } from "hono";
|
|
167
|
-
import { PartitionTopologyManager } from "@rivetkit/core/topologies/partition";
|
|
168
|
-
|
|
169
169
|
// src/manager-driver.ts
|
|
170
170
|
import {
|
|
171
|
-
|
|
172
|
-
HEADER_ENCODING,
|
|
171
|
+
HEADER_AUTH_DATA,
|
|
173
172
|
HEADER_CONN_PARAMS,
|
|
174
|
-
|
|
173
|
+
HEADER_ENCODING,
|
|
174
|
+
HEADER_EXPOSE_INTERNAL_ERROR
|
|
175
175
|
} from "@rivetkit/core/driver-helpers";
|
|
176
176
|
import { ActorAlreadyExists, InternalError } from "@rivetkit/core/errors";
|
|
177
177
|
|
|
@@ -423,7 +423,7 @@ var CloudflareActorsManagerDriver = class {
|
|
|
423
423
|
};
|
|
424
424
|
|
|
425
425
|
// src/websocket.ts
|
|
426
|
-
import {
|
|
426
|
+
import { defineWebSocketHelper, WSContext } from "hono/ws";
|
|
427
427
|
var upgradeWebSocket = defineWebSocketHelper(async (c, events) => {
|
|
428
428
|
var _a, _b;
|
|
429
429
|
const upgradeHeader = c.req.header("Upgrade");
|
|
@@ -487,8 +487,6 @@ var upgradeWebSocket = defineWebSocketHelper(async (c, events) => {
|
|
|
487
487
|
});
|
|
488
488
|
|
|
489
489
|
// src/handler.ts
|
|
490
|
-
import invariant2 from "invariant";
|
|
491
|
-
import { AsyncLocalStorage } from "async_hooks";
|
|
492
490
|
var CF_AMBIENT_ENV = new AsyncLocalStorage();
|
|
493
491
|
function getCloudflareAmbientEnv() {
|
|
494
492
|
const env = CF_AMBIENT_ENV.getStore();
|
package/dist/mod.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/actor-handler-do.ts","../src/log.ts","../src/actor-driver.ts","../src/config.ts","../src/handler.ts","../src/manager-driver.ts","../src/util.ts","../src/websocket.ts"],"sourcesContent":["import { DurableObject } from \"cloudflare:workers\";\nimport type { Registry, RunConfig, ActorKey } from \"@rivetkit/core\";\nimport { serializeEmptyPersistData } from \"@rivetkit/core/driver-helpers\";\nimport { logger } from \"./log\";\nimport { PartitionTopologyActor } from \"@rivetkit/core/topologies/partition\";\nimport {\n\tCloudflareDurableObjectGlobalState,\n\tCloudflareActorsActorDriver,\n} from \"./actor-driver\";\nimport { Bindings, CF_AMBIENT_ENV } from \"./handler\";\nimport { ExecutionContext } from \"hono\";\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\tactorTopology: PartitionTopologyActor;\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// Configure actor driver\n\t\t\trunConfig.driver.actor = new CloudflareActorsActorDriver(globalState);\n\n\t\t\tconst actorTopology = new PartitionTopologyActor(\n\t\t\t\tregistry.config,\n\t\t\t\trunConfig,\n\t\t\t);\n\n\t\t\t// Register DO with global state\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// Save actor\n\t\t\tthis.#actor = {\n\t\t\t\tactorTopology,\n\t\t\t};\n\n\t\t\t// Start actor\n\t\t\tawait actorTopology.start(\n\t\t\t\tactorId,\n\t\t\t\tthis.#initialized.name,\n\t\t\t\tthis.#initialized.key,\n\t\t\t\t// TODO:\n\t\t\t\t\"unknown\",\n\t\t\t);\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 { actorTopology } = await this.#loadActor();\n\n\t\t\t\tconst ctx = this.ctx;\n\t\t\t\treturn await actorTopology.router.fetch(\n\t\t\t\t\trequest,\n\t\t\t\t\tthis.env,\n\t\t\t\t\t// Implement execution context so we can wait on requests\n\t\t\t\t\t{\n\t\t\t\t\t\twaitUntil(promise: Promise<unknown>) {\n\t\t\t\t\t\t\tctx.waitUntil(promise);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpassThroughOnException() {\n\t\t\t\t\t\t\t// Do nothing\n\t\t\t\t\t\t},\n\t\t\t\t\t\tprops: {},\n\t\t\t\t\t} satisfies ExecutionContext,\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\tconst { actorTopology } = await this.#loadActor();\n\t\t\t\tawait actorTopology.actor.onAlarm();\n\t\t\t});\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 type { ActorDriver, AnyActorInstance } 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\nexport class CloudflareActorsActorDriver implements ActorDriver {\n\t#globalState: CloudflareDurableObjectGlobalState;\n\n\tconstructor(globalState: CloudflareDurableObjectGlobalState) {\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\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","import { RunConfigSchema } from \"@rivetkit/core/driver-helpers\";\nimport { 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 {\n\ttype DurableObjectConstructor,\n\ttype ActorHandlerInterface,\n\tcreateActorDurableObject,\n} from \"./actor-handler-do\";\nimport { ConfigSchema, type Config, type InputConfig } from \"./config\";\nimport { Hono } from \"hono\";\nimport { PartitionTopologyManager } from \"@rivetkit/core/topologies/partition\";\nimport type { Client } from \"@rivetkit/core/client\";\nimport { CloudflareActorsManagerDriver } from \"./manager-driver\";\nimport { DriverConfig, Registry, RunConfig } from \"@rivetkit/core\";\nimport { upgradeWebSocket } from \"./websocket\";\nimport invariant from \"invariant\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\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\ttopology: \"partition\",\n\t\t\tmanager: new CloudflareActorsManagerDriver(),\n\t\t\t// HACK: We can't build the actor driver until we're inside the Druable 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\tconst managerTopology = new PartitionTopologyManager(\n\t\tregistry.config,\n\t\trunConfig,\n\t);\n\n\treturn {\n\t\tclient: managerTopology.inlineClient 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\n\t\t\tapp.route(\"/registry\", managerTopology.router);\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 {\n\ttype ManagerDriver,\n\ttype GetForIdInput,\n\ttype GetWithKeyInput,\n\ttype ActorOutput,\n\ttype CreateInput,\n\ttype GetOrCreateWithKeyInput,\n\ttype ConnRoutingHandler,\n\tHEADER_EXPOSE_INTERNAL_ERROR,\n\tHEADER_ENCODING,\n\tHEADER_CONN_PARAMS,\n\tHEADER_AUTH_DATA,\n} from \"@rivetkit/core/driver-helpers\";\nimport { ActorAlreadyExists, InternalError } from \"@rivetkit/core/errors\";\nimport { Bindings } from \"./mod\";\nimport { logger } from \"./log\";\nimport { serializeNameAndKey, serializeKey } from \"./util\";\nimport { getCloudflareAmbientEnv } from \"./handler\";\nimport { Encoding } from \"@rivetkit/core\";\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\tconnRoutingHandler: ConnRoutingHandler;\n\n\tconstructor() {\n\t\tthis.connRoutingHandler = {\n\t\t\tcustom: {\n\t\t\t\tsendRequest: async (actorId, actorRequest): Promise<Response> => {\n\t\t\t\t\tconst env = getCloudflareAmbientEnv();\n\n\t\t\t\t\tlogger().debug(\"sending request to durable object\", {\n\t\t\t\t\t\tactorId,\n\t\t\t\t\t\tmethod: actorRequest.method,\n\t\t\t\t\t\turl: actorRequest.url,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst id = env.ACTOR_DO.idFromString(actorId);\n\t\t\t\t\tconst stub = env.ACTOR_DO.get(id);\n\n\t\t\t\t\treturn await stub.fetch(actorRequest);\n\t\t\t\t},\n\n\t\t\t\topenWebSocket: async (\n\t\t\t\t\tactorId,\n\t\t\t\t\tencodingKind: Encoding,\n\t\t\t\t\tparams: unknown,\n\t\t\t\t): Promise<WebSocket> => {\n\t\t\t\t\tconst env = getCloudflareAmbientEnv();\n\n\t\t\t\t\tlogger().debug(\"opening websocket to durable object\", { actorId });\n\n\t\t\t\t\t// Make a fetch request to the Durable Object with WebSocket upgrade\n\t\t\t\t\tconst id = env.ACTOR_DO.idFromString(actorId);\n\t\t\t\t\tconst stub = env.ACTOR_DO.get(id);\n\n\t\t\t\t\tconst headers: Record<string, string> = {\n\t\t\t\t\t\tUpgrade: \"websocket\",\n\t\t\t\t\t\tConnection: \"Upgrade\",\n\t\t\t\t\t\t[HEADER_EXPOSE_INTERNAL_ERROR]: \"true\",\n\t\t\t\t\t\t[HEADER_ENCODING]: encodingKind,\n\t\t\t\t\t};\n\t\t\t\t\tif (params) {\n\t\t\t\t\t\theaders[HEADER_CONN_PARAMS] = JSON.stringify(params);\n\t\t\t\t\t}\n\t\t\t\t\t// HACK: See packages/platforms/cloudflare-workers/src/websocket.ts\n\t\t\t\t\theaders[\"sec-websocket-protocol\"] = \"rivetkit\";\n\n\t\t\t\t\tconst response = await stub.fetch(\"http://actor/connect/websocket\", {\n\t\t\t\t\t\theaders,\n\t\t\t\t\t});\n\t\t\t\t\tconst webSocket = response.webSocket;\n\n\t\t\t\t\tif (!webSocket) {\n\t\t\t\t\t\tthrow new InternalError(\n\t\t\t\t\t\t\t\"missing websocket connection in response from DO\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tlogger().debug(\"durable object websocket connection open\", {\n\t\t\t\t\t\tactorId,\n\t\t\t\t\t});\n\n\t\t\t\t\twebSocket.accept();\n\n\t\t\t\t\t// TODO: Is this still needed?\n\t\t\t\t\t// HACK: Cloudflare does not call onopen automatically, so we need\n\t\t\t\t\t// to call this on the next tick\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t(webSocket as any).onopen?.(new Event(\"open\"));\n\t\t\t\t\t}, 0);\n\n\t\t\t\t\treturn webSocket as unknown as WebSocket;\n\t\t\t\t},\n\n\t\t\t\tproxyRequest: async (c, actorRequest, actorId): Promise<Response> => {\n\t\t\t\t\tlogger().debug(\"forwarding request to durable object\", {\n\t\t\t\t\t\tactorId,\n\t\t\t\t\t\tmethod: actorRequest.method,\n\t\t\t\t\t\turl: actorRequest.url,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst id = c.env.ACTOR_DO.idFromString(actorId);\n\t\t\t\t\tconst stub = c.env.ACTOR_DO.get(id);\n\n\t\t\t\t\treturn await stub.fetch(actorRequest);\n\t\t\t\t},\n\t\t\t\tproxyWebSocket: async (\n\t\t\t\t\tc,\n\t\t\t\t\tpath,\n\t\t\t\t\tactorId,\n\t\t\t\t\tencoding,\n\t\t\t\t\tparams,\n\t\t\t\t\tauthData,\n\t\t\t\t) => {\n\t\t\t\t\tlogger().debug(\"forwarding websocket to durable object\", {\n\t\t\t\t\t\tactorId,\n\t\t\t\t\t\tpath,\n\t\t\t\t\t});\n\n\t\t\t\t\t// Validate upgrade\n\t\t\t\t\tconst upgradeHeader = c.req.header(\"Upgrade\");\n\t\t\t\t\tif (!upgradeHeader || upgradeHeader !== \"websocket\") {\n\t\t\t\t\t\treturn new Response(\"Expected Upgrade: websocket\", {\n\t\t\t\t\t\t\tstatus: 426,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\t// TODO: strip headers\n\t\t\t\t\tconst newUrl = new URL(`http://actor${path}`);\n\t\t\t\t\tconst actorRequest = new Request(newUrl, c.req.raw);\n\n\t\t\t\t\t// Always build fresh request to prevent forwarding unwanted headers\n\t\t\t\t\t// HACK: Since we can't build a new request, we need to remove\n\t\t\t\t\t// non-standard headers manually\n\t\t\t\t\tconst headerKeys: string[] = [];\n\t\t\t\t\tactorRequest.headers.forEach((v, k) => headerKeys.push(k));\n\t\t\t\t\tfor (const k of headerKeys) {\n\t\t\t\t\t\tif (!STANDARD_WEBSOCKET_HEADERS.includes(k)) {\n\t\t\t\t\t\t\tactorRequest.headers.delete(k);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Add RivetKit headers\n\t\t\t\t\tactorRequest.headers.set(HEADER_EXPOSE_INTERNAL_ERROR, \"true\");\n\t\t\t\t\tactorRequest.headers.set(HEADER_ENCODING, encoding);\n\t\t\t\t\tif (params) {\n\t\t\t\t\t\tactorRequest.headers.set(\n\t\t\t\t\t\t\tHEADER_CONN_PARAMS,\n\t\t\t\t\t\t\tJSON.stringify(params),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (authData) {\n\t\t\t\t\t\tactorRequest.headers.set(\n\t\t\t\t\t\t\tHEADER_AUTH_DATA,\n\t\t\t\t\t\t\tJSON.stringify(authData),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst id = c.env.ACTOR_DO.idFromString(actorId);\n\t\t\t\t\tconst stub = c.env.ACTOR_DO.get(id);\n\n\t\t\t\t\treturn await stub.fetch(actorRequest);\n\t\t\t\t},\n\t\t\t},\n\t\t};\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 // Escape colons in the name\n const escapedName = name.replace(/:/g, \"\\\\:\");\n\n // For empty keys, just return the name and a marker\n if (key.length === 0) {\n return `${escapedName}:${EMPTY_KEY}`;\n }\n\n // Serialize the key array\n const serializedKey = serializeKey(key);\n\n // Combine name and serialized key\n return `${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 // Use a special marker for empty key arrays\n if (key.length === 0) {\n return EMPTY_KEY;\n }\n\n // Escape each key part to handle the separator and the empty key marker\n const escapedParts = key.map(part => {\n // First check if it matches our empty key marker\n if (part === EMPTY_KEY) {\n return `\\\\${EMPTY_KEY}`;\n }\n\n // Escape backslashes first, then commas\n let escaped = part.replace(/\\\\/g, \"\\\\\\\\\");\n escaped = escaped.replace(/,/g, \"\\\\,\");\n return escaped;\n });\n\n return 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 // Handle empty values\n if (!keyString) {\n return [];\n }\n\n // Check for special empty key marker\n if (keyString === EMPTY_KEY) {\n return [];\n }\n\n // Split by unescaped commas and unescape the escaped characters\n const parts: string[] = [];\n let currentPart = '';\n let escaping = false;\n\n for (let i = 0; i < keyString.length; i++) {\n const char = keyString[i];\n\n if (escaping) {\n // This is an escaped character, add it directly\n currentPart += char;\n escaping = false;\n } else if (char === '\\\\') {\n // Start of an escape sequence\n escaping = true;\n } else if (char === KEY_SEPARATOR) {\n // This is a separator\n parts.push(currentPart);\n currentPart = '';\n } else {\n // Regular character\n currentPart += char;\n }\n }\n\n // Add the last part if it exists\n if (currentPart || parts.length > 0) {\n parts.push(currentPart);\n }\n\n return parts;\n}\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 { WSContext, defineWebSocketHelper } from \"hono/ws\";\nimport type { UpgradeWebSocket, WSEvents, WSReadyState } 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":["KEYS","_a","invariant"]}
|
|
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 { PartitionTopologyManager } from \"@rivetkit/core/topologies/partition\";\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\ttopology: \"partition\",\n\t\t\tmanager: new CloudflareActorsManagerDriver(),\n\t\t\t// HACK: We can't build the actor driver until we're inside the Druable 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\tconst managerTopology = new PartitionTopologyManager(\n\t\tregistry.config,\n\t\trunConfig,\n\t);\n\n\treturn {\n\t\tclient: managerTopology.inlineClient 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\n\t\t\tapp.route(\"/registry\", managerTopology.router);\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 { ActorKey, Registry, RunConfig } from \"@rivetkit/core\";\nimport { serializeEmptyPersistData } from \"@rivetkit/core/driver-helpers\";\nimport { PartitionTopologyActor } from \"@rivetkit/core/topologies/partition\";\nimport type { ExecutionContext } from \"hono\";\nimport {\n\tCloudflareActorsActorDriver,\n\tCloudflareDurableObjectGlobalState,\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\tactorTopology: PartitionTopologyActor;\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// Configure actor driver\n\t\t\trunConfig.driver.actor = new CloudflareActorsActorDriver(globalState);\n\n\t\t\tconst actorTopology = new PartitionTopologyActor(\n\t\t\t\tregistry.config,\n\t\t\t\trunConfig,\n\t\t\t);\n\n\t\t\t// Register DO with global state\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// Save actor\n\t\t\tthis.#actor = {\n\t\t\t\tactorTopology,\n\t\t\t};\n\n\t\t\t// Start actor\n\t\t\tawait actorTopology.start(\n\t\t\t\tactorId,\n\t\t\t\tthis.#initialized.name,\n\t\t\t\tthis.#initialized.key,\n\t\t\t\t// TODO:\n\t\t\t\t\"unknown\",\n\t\t\t);\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 { actorTopology } = await this.#loadActor();\n\n\t\t\t\tconst ctx = this.ctx;\n\t\t\t\treturn await actorTopology.router.fetch(\n\t\t\t\t\trequest,\n\t\t\t\t\tthis.env,\n\t\t\t\t\t// Implement execution context so we can wait on requests\n\t\t\t\t\t{\n\t\t\t\t\t\twaitUntil(promise: Promise<unknown>) {\n\t\t\t\t\t\t\tctx.waitUntil(promise);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpassThroughOnException() {\n\t\t\t\t\t\t\t// Do nothing\n\t\t\t\t\t\t},\n\t\t\t\t\t\tprops: {},\n\t\t\t\t\t} satisfies ExecutionContext,\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\tconst { actorTopology } = await this.#loadActor();\n\t\t\t\tawait actorTopology.actor.onAlarm();\n\t\t\t});\n\t\t}\n\t};\n}\n","import type {\n\tActorDriver,\n\tAnyActorInstance,\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\nexport class CloudflareActorsActorDriver implements ActorDriver {\n\t#globalState: CloudflareDurableObjectGlobalState;\n\n\tconstructor(globalState: CloudflareDurableObjectGlobalState) {\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\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","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 ConnRoutingHandler,\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 { 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\tconnRoutingHandler: ConnRoutingHandler;\n\n\tconstructor() {\n\t\tthis.connRoutingHandler = {\n\t\t\tcustom: {\n\t\t\t\tsendRequest: async (actorId, actorRequest): Promise<Response> => {\n\t\t\t\t\tconst env = getCloudflareAmbientEnv();\n\n\t\t\t\t\tlogger().debug(\"sending request to durable object\", {\n\t\t\t\t\t\tactorId,\n\t\t\t\t\t\tmethod: actorRequest.method,\n\t\t\t\t\t\turl: actorRequest.url,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst id = env.ACTOR_DO.idFromString(actorId);\n\t\t\t\t\tconst stub = env.ACTOR_DO.get(id);\n\n\t\t\t\t\treturn await stub.fetch(actorRequest);\n\t\t\t\t},\n\n\t\t\t\topenWebSocket: async (\n\t\t\t\t\tactorId,\n\t\t\t\t\tencodingKind: Encoding,\n\t\t\t\t\tparams: unknown,\n\t\t\t\t): Promise<WebSocket> => {\n\t\t\t\t\tconst env = getCloudflareAmbientEnv();\n\n\t\t\t\t\tlogger().debug(\"opening websocket to durable object\", { actorId });\n\n\t\t\t\t\t// Make a fetch request to the Durable Object with WebSocket upgrade\n\t\t\t\t\tconst id = env.ACTOR_DO.idFromString(actorId);\n\t\t\t\t\tconst stub = env.ACTOR_DO.get(id);\n\n\t\t\t\t\tconst headers: Record<string, string> = {\n\t\t\t\t\t\tUpgrade: \"websocket\",\n\t\t\t\t\t\tConnection: \"Upgrade\",\n\t\t\t\t\t\t[HEADER_EXPOSE_INTERNAL_ERROR]: \"true\",\n\t\t\t\t\t\t[HEADER_ENCODING]: encodingKind,\n\t\t\t\t\t};\n\t\t\t\t\tif (params) {\n\t\t\t\t\t\theaders[HEADER_CONN_PARAMS] = JSON.stringify(params);\n\t\t\t\t\t}\n\t\t\t\t\t// HACK: See packages/platforms/cloudflare-workers/src/websocket.ts\n\t\t\t\t\theaders[\"sec-websocket-protocol\"] = \"rivetkit\";\n\n\t\t\t\t\tconst response = await stub.fetch(\"http://actor/connect/websocket\", {\n\t\t\t\t\t\theaders,\n\t\t\t\t\t});\n\t\t\t\t\tconst webSocket = response.webSocket;\n\n\t\t\t\t\tif (!webSocket) {\n\t\t\t\t\t\tthrow new InternalError(\n\t\t\t\t\t\t\t\"missing websocket connection in response from DO\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tlogger().debug(\"durable object websocket connection open\", {\n\t\t\t\t\t\tactorId,\n\t\t\t\t\t});\n\n\t\t\t\t\twebSocket.accept();\n\n\t\t\t\t\t// TODO: Is this still needed?\n\t\t\t\t\t// HACK: Cloudflare does not call onopen automatically, so we need\n\t\t\t\t\t// to call this on the next tick\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t(webSocket as any).onopen?.(new Event(\"open\"));\n\t\t\t\t\t}, 0);\n\n\t\t\t\t\treturn webSocket as unknown as WebSocket;\n\t\t\t\t},\n\n\t\t\t\tproxyRequest: async (c, actorRequest, actorId): Promise<Response> => {\n\t\t\t\t\tlogger().debug(\"forwarding request to durable object\", {\n\t\t\t\t\t\tactorId,\n\t\t\t\t\t\tmethod: actorRequest.method,\n\t\t\t\t\t\turl: actorRequest.url,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst id = c.env.ACTOR_DO.idFromString(actorId);\n\t\t\t\t\tconst stub = c.env.ACTOR_DO.get(id);\n\n\t\t\t\t\treturn await stub.fetch(actorRequest);\n\t\t\t\t},\n\t\t\t\tproxyWebSocket: async (\n\t\t\t\t\tc,\n\t\t\t\t\tpath,\n\t\t\t\t\tactorId,\n\t\t\t\t\tencoding,\n\t\t\t\t\tparams,\n\t\t\t\t\tauthData,\n\t\t\t\t) => {\n\t\t\t\t\tlogger().debug(\"forwarding websocket to durable object\", {\n\t\t\t\t\t\tactorId,\n\t\t\t\t\t\tpath,\n\t\t\t\t\t});\n\n\t\t\t\t\t// Validate upgrade\n\t\t\t\t\tconst upgradeHeader = c.req.header(\"Upgrade\");\n\t\t\t\t\tif (!upgradeHeader || upgradeHeader !== \"websocket\") {\n\t\t\t\t\t\treturn new Response(\"Expected Upgrade: websocket\", {\n\t\t\t\t\t\t\tstatus: 426,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\t// TODO: strip headers\n\t\t\t\t\tconst newUrl = new URL(`http://actor${path}`);\n\t\t\t\t\tconst actorRequest = new Request(newUrl, c.req.raw);\n\n\t\t\t\t\t// Always build fresh request to prevent forwarding unwanted headers\n\t\t\t\t\t// HACK: Since we can't build a new request, we need to remove\n\t\t\t\t\t// non-standard headers manually\n\t\t\t\t\tconst headerKeys: string[] = [];\n\t\t\t\t\tactorRequest.headers.forEach((v, k) => headerKeys.push(k));\n\t\t\t\t\tfor (const k of headerKeys) {\n\t\t\t\t\t\tif (!STANDARD_WEBSOCKET_HEADERS.includes(k)) {\n\t\t\t\t\t\t\tactorRequest.headers.delete(k);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Add RivetKit headers\n\t\t\t\t\tactorRequest.headers.set(HEADER_EXPOSE_INTERNAL_ERROR, \"true\");\n\t\t\t\t\tactorRequest.headers.set(HEADER_ENCODING, encoding);\n\t\t\t\t\tif (params) {\n\t\t\t\t\t\tactorRequest.headers.set(\n\t\t\t\t\t\t\tHEADER_CONN_PARAMS,\n\t\t\t\t\t\t\tJSON.stringify(params),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (authData) {\n\t\t\t\t\t\tactorRequest.headers.set(\n\t\t\t\t\t\t\tHEADER_AUTH_DATA,\n\t\t\t\t\t\t\tJSON.stringify(authData),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst id = c.env.ACTOR_DO.idFromString(actorId);\n\t\t\t\t\tconst stub = c.env.ACTOR_DO.get(id);\n\n\t\t\t\t\treturn await stub.fetch(actorRequest);\n\t\t\t\t},\n\t\t\t},\n\t\t};\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":";AAAA,SAAS,yBAAyB;AAGlC,SAAS,gCAAgC;AACzC,SAAS,YAAY;AACrB,OAAOA,gBAAe;;;ACLtB,SAAS,qBAAqB;AAE9B,SAAS,iCAAiC;AAC1C,SAAS,8BAA8B;;;ACCvC,OAAO,eAAe;AAaf,IAAM,qCAAN,MAAyC;AAAA;AAAA,EAE/C,OAA8C,oBAAI,IAAI;AAAA,EAEtD,WAAW,SAA2C;AACrD,UAAM,QAAQ,KAAK,KAAK,IAAI,OAAO;AACnC,cAAU,UAAU,QAAW,0CAA0C;AACzE,WAAO;AAAA,EACR;AAAA,EAEA,WAAW,SAAiB,OAAiC;AAC5D,SAAK,KAAK,IAAI,SAAS,KAAK;AAAA,EAC7B;AACD;AAOO,IAAM,8BAAN,MAAyD;AAAA,EAC/D;AAAA,EAEA,YAAY,aAAiD;AAC5D,SAAK,eAAe;AAAA,EACrB;AAAA,EAEA,UAAU,SAAiB;AAC1B,WAAO,KAAK,aAAa,WAAW,OAAO,EAAE;AAAA,EAC9C;AAAA,EAEA,WAAW,SAAqC;AAC/C,UAAM,QAAQ,KAAK,aAAa,WAAW,OAAO;AAClD,WAAO,EAAE,KAAK,MAAM,KAAK,KAAK,MAAM,IAAI;AAAA,EACzC;AAAA,EAEA,MAAM,kBAAkB,SAAkD;AACzE,WAAO,MAAM,KAAK,UAAU,OAAO,EAAE,QAAQ,IAAI,KAAK,YAAY;AAAA,EACnE;AAAA,EAEA,MAAM,mBAAmB,SAAiB,MAAiC;AAC1E,UAAM,KAAK,UAAU,OAAO,EAAE,QAAQ,IAAI,KAAK,cAAc,IAAI;AAAA,EAClE;AAAA,EAEA,MAAM,SAAS,OAAyB,WAAkC;AACzE,UAAM,KAAK,UAAU,MAAM,EAAE,EAAE,QAAQ,SAAS,SAAS;AAAA,EAC1D;AAAA,EAEA,MAAM,YAAY,SAA+C;AAChE,WAAO,KAAK,UAAU,OAAO,EAAE,QAAQ;AAAA,EACxC;AACD;;;ACpEA,SAAS,iBAAiB;AAEnB,IAAM,cAAc;AAEpB,SAAS,SAAS;AACxB,SAAO,UAAU,WAAW;AAC7B;;;AFMO,IAAM,OAAO;AAAA,EACnB,MAAM;AAAA,EACN,KAAK;AAAA,EACL,cAAc;AACf;AAyBO,SAAS,yBACf,UACA,WAC2B;AAC3B,QAAM,cAAc,IAAI,mCAAmC;AAQ3D,SAAO,MAAM,qBACJ,cAET;AAAA,IACC;AAAA,IACA;AAAA,IAEA;AAAA,IAEA,MAAM,aAAmC;AAIxC,UAAI,CAAC,KAAK,cAAc;AAEvB,YAAI,KAAK,qBAAqB;AAC7B,gBAAM,KAAK,oBAAoB;AAAA,QAChC,OAAO;AACN,eAAK,sBAAsB,QAAQ,cAAc;AACjD,gBAAM,MAAM,MAAM,KAAK,IAAI,QAAQ,IAAI;AAAA,YACtC,KAAK;AAAA,YACL,KAAK;AAAA,YACL,KAAK;AAAA,UACN,CAAC;AACD,cAAI,IAAI,IAAI,KAAK,YAAY,GAAG;AAC/B,kBAAM,OAAO,IAAI,IAAI,KAAK,IAAI;AAC9B,gBAAI,CAAC,KAAM,OAAM,IAAI,MAAM,oBAAoB;AAC/C,kBAAM,MAAM,IAAI,IAAI,KAAK,GAAG;AAC5B,gBAAI,CAAC,IAAK,OAAM,IAAI,MAAM,mBAAmB;AAE7C,mBAAO,EAAE,MAAM,uBAAuB,EAAE,MAAM,IAAI,CAAC;AAEnD,iBAAK,eAAe,EAAE,MAAM,IAAI;AAChC,iBAAK,oBAAoB,QAAQ;AAAA,UAClC,OAAO;AACN,mBAAO,EAAE,MAAM,uBAAuB;AAAA,UACvC;AAAA,QACD;AAAA,MACD;AAGA,UAAI,KAAK,QAAQ;AAChB,eAAO,KAAK;AAAA,MACb;AAEA,UAAI,CAAC,KAAK,aAAc,OAAM,IAAI,MAAM,iBAAiB;AAGzD,gBAAU,OAAO,QAAQ,IAAI,4BAA4B,WAAW;AAEpE,YAAM,gBAAgB,IAAI;AAAA,QACzB,SAAS;AAAA,QACT;AAAA,MACD;AAMA,YAAM,UAAU,KAAK,IAAI,GAAG,SAAS;AACrC,kBAAY,WAAW,SAAS,EAAE,KAAK,KAAK,KAAK,KAAK,KAAK,IAAI,CAAC;AAGhE,WAAK,SAAS;AAAA,QACb;AAAA,MACD;AAGA,YAAM,cAAc;AAAA,QACnB;AAAA,QACA,KAAK,aAAa;AAAA,QAClB,KAAK,aAAa;AAAA;AAAA,QAElB;AAAA,MACD;AAEA,aAAO,KAAK;AAAA,IACb;AAAA;AAAA,IAGA,MAAM,WAAW,KAAuB;AAGvC,aAAO,MAAM,eAAe,IAAI,KAAK,KAAK,YAAY;AACrD,cAAM,KAAK,IAAI,QAAQ,IAAI;AAAA,UAC1B,CAAC,KAAK,IAAI,GAAG,IAAI;AAAA,UACjB,CAAC,KAAK,GAAG,GAAG,IAAI;AAAA,UAChB,CAAC,KAAK,YAAY,GAAG,0BAA0B,IAAI,KAAK;AAAA,QACzD,CAAC;AACD,aAAK,eAAe;AAAA,UACnB,MAAM,IAAI;AAAA,UACV,KAAK,IAAI;AAAA,QACV;AAEA,eAAO,EAAE,MAAM,qBAAqB,EAAE,KAAK,IAAI,IAAI,CAAC;AAGpD,cAAM,KAAK,WAAW;AAAA,MACvB,CAAC;AAAA,IACF;AAAA,IAEA,MAAM,MAAM,SAAqC;AAChD,aAAO,MAAM,eAAe,IAAI,KAAK,KAAK,YAAY;AACrD,cAAM,EAAE,cAAc,IAAI,MAAM,KAAK,WAAW;AAEhD,cAAM,MAAM,KAAK;AACjB,eAAO,MAAM,cAAc,OAAO;AAAA,UACjC;AAAA,UACA,KAAK;AAAA;AAAA,UAEL;AAAA,YACC,UAAU,SAA2B;AACpC,kBAAI,UAAU,OAAO;AAAA,YACtB;AAAA,YACA,yBAAyB;AAAA,YAEzB;AAAA,YACA,OAAO,CAAC;AAAA,UACT;AAAA,QACD;AAAA,MACD,CAAC;AAAA,IACF;AAAA,IAEA,MAAM,QAAuB;AAC5B,aAAO,MAAM,eAAe,IAAI,KAAK,KAAK,YAAY;AACrD,cAAM,EAAE,cAAc,IAAI,MAAM,KAAK,WAAW;AAChD,cAAM,cAAc,MAAM,QAAQ;AAAA,MACnC,CAAC;AAAA,IACF;AAAA,EACD;AACD;;;AGvLA,SAAS,uBAAuB;AAEhC,SAAS,SAAS;AAEX,IAAM,eAAe,gBAAgB,cAAc,EACxD,KAAK,EAAE,QAAQ,MAAM,qBAAqB,KAAK,CAAC,EAChD,OAAO;AAAA,EACP,KAAK,EAAE,OAAa,EAAE,SAAS;AAChC,CAAC,EACA,QAAQ,CAAC,CAAC;;;ACRZ;AAAA,EAOC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEM;AACP,SAAS,oBAAoB,qBAAqB;;;ACb3C,IAAM,YAAY;AAClB,IAAM,gBAAgB;AAStB,SAAS,oBAAoB,MAAc,KAAuB;AAExE,QAAM,cAAc,KAAK,QAAQ,MAAM,KAAK;AAG5C,MAAI,IAAI,WAAW,GAAG;AACrB,WAAO,GAAG,WAAW,IAAI,SAAS;AAAA,EACnC;AAGA,QAAM,gBAAgB,aAAa,GAAG;AAGtC,SAAO,GAAG,WAAW,IAAI,aAAa;AACvC;AAQO,SAAS,aAAa,KAAuB;AAEnD,MAAI,IAAI,WAAW,GAAG;AACrB,WAAO;AAAA,EACR;AAGA,QAAM,eAAe,IAAI,IAAI,CAAC,SAAS;AAEtC,QAAI,SAAS,WAAW;AACvB,aAAO,KAAK,SAAS;AAAA,IACtB;AAGA,QAAI,UAAU,KAAK,QAAQ,OAAO,MAAM;AACxC,cAAU,QAAQ,QAAQ,MAAM,KAAK;AACrC,WAAO;AAAA,EACR,CAAC;AAED,SAAO,aAAa,KAAK,aAAa;AACvC;;;AD1BA,IAAMC,QAAO;AAAA,EACZ,OAAO;AAAA;AAAA,IAEN,UAAU,CAAC,YAAoB,SAAS,OAAO;AAAA;AAAA,IAG/C,UAAU,CAAC,MAAc,MAAgB,CAAC,MAAM;AAE/C,aAAO,aAAa,aAAa,GAAG,CAAC;AAAA,IACtC;AAAA,EACD;AACD;AAEA,IAAM,6BAA6B;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAEO,IAAM,gCAAN,MAA6D;AAAA,EACnE;AAAA,EAEA,cAAc;AACb,SAAK,qBAAqB;AAAA,MACzB,QAAQ;AAAA,QACP,aAAa,OAAO,SAAS,iBAAoC;AAChE,gBAAM,MAAM,wBAAwB;AAEpC,iBAAO,EAAE,MAAM,qCAAqC;AAAA,YACnD;AAAA,YACA,QAAQ,aAAa;AAAA,YACrB,KAAK,aAAa;AAAA,UACnB,CAAC;AAED,gBAAM,KAAK,IAAI,SAAS,aAAa,OAAO;AAC5C,gBAAM,OAAO,IAAI,SAAS,IAAI,EAAE;AAEhC,iBAAO,MAAM,KAAK,MAAM,YAAY;AAAA,QACrC;AAAA,QAEA,eAAe,OACd,SACA,cACA,WACwB;AACxB,gBAAM,MAAM,wBAAwB;AAEpC,iBAAO,EAAE,MAAM,uCAAuC,EAAE,QAAQ,CAAC;AAGjE,gBAAM,KAAK,IAAI,SAAS,aAAa,OAAO;AAC5C,gBAAM,OAAO,IAAI,SAAS,IAAI,EAAE;AAEhC,gBAAM,UAAkC;AAAA,YACvC,SAAS;AAAA,YACT,YAAY;AAAA,YACZ,CAAC,4BAA4B,GAAG;AAAA,YAChC,CAAC,eAAe,GAAG;AAAA,UACpB;AACA,cAAI,QAAQ;AACX,oBAAQ,kBAAkB,IAAI,KAAK,UAAU,MAAM;AAAA,UACpD;AAEA,kBAAQ,wBAAwB,IAAI;AAEpC,gBAAM,WAAW,MAAM,KAAK,MAAM,kCAAkC;AAAA,YACnE;AAAA,UACD,CAAC;AACD,gBAAM,YAAY,SAAS;AAE3B,cAAI,CAAC,WAAW;AACf,kBAAM,IAAI;AAAA,cACT;AAAA,YACD;AAAA,UACD;AAEA,iBAAO,EAAE,MAAM,4CAA4C;AAAA,YAC1D;AAAA,UACD,CAAC;AAED,oBAAU,OAAO;AAKjB,qBAAW,MAAM;AAnHtB;AAoHM,aAAC,eAAkB,WAAlB,mCAA2B,IAAI,MAAM,MAAM;AAAA,UAC7C,GAAG,CAAC;AAEJ,iBAAO;AAAA,QACR;AAAA,QAEA,cAAc,OAAO,GAAG,cAAc,YAA+B;AACpE,iBAAO,EAAE,MAAM,wCAAwC;AAAA,YACtD;AAAA,YACA,QAAQ,aAAa;AAAA,YACrB,KAAK,aAAa;AAAA,UACnB,CAAC;AAED,gBAAM,KAAK,EAAE,IAAI,SAAS,aAAa,OAAO;AAC9C,gBAAM,OAAO,EAAE,IAAI,SAAS,IAAI,EAAE;AAElC,iBAAO,MAAM,KAAK,MAAM,YAAY;AAAA,QACrC;AAAA,QACA,gBAAgB,OACf,GACA,MACA,SACA,UACA,QACA,aACI;AACJ,iBAAO,EAAE,MAAM,0CAA0C;AAAA,YACxD;AAAA,YACA;AAAA,UACD,CAAC;AAGD,gBAAM,gBAAgB,EAAE,IAAI,OAAO,SAAS;AAC5C,cAAI,CAAC,iBAAiB,kBAAkB,aAAa;AACpD,mBAAO,IAAI,SAAS,+BAA+B;AAAA,cAClD,QAAQ;AAAA,YACT,CAAC;AAAA,UACF;AAGA,gBAAM,SAAS,IAAI,IAAI,eAAe,IAAI,EAAE;AAC5C,gBAAM,eAAe,IAAI,QAAQ,QAAQ,EAAE,IAAI,GAAG;AAKlD,gBAAM,aAAuB,CAAC;AAC9B,uBAAa,QAAQ,QAAQ,CAAC,GAAG,MAAM,WAAW,KAAK,CAAC,CAAC;AACzD,qBAAW,KAAK,YAAY;AAC3B,gBAAI,CAAC,2BAA2B,SAAS,CAAC,GAAG;AAC5C,2BAAa,QAAQ,OAAO,CAAC;AAAA,YAC9B;AAAA,UACD;AAGA,uBAAa,QAAQ,IAAI,8BAA8B,MAAM;AAC7D,uBAAa,QAAQ,IAAI,iBAAiB,QAAQ;AAClD,cAAI,QAAQ;AACX,yBAAa,QAAQ;AAAA,cACpB;AAAA,cACA,KAAK,UAAU,MAAM;AAAA,YACtB;AAAA,UACD;AACA,cAAI,UAAU;AACb,yBAAa,QAAQ;AAAA,cACpB;AAAA,cACA,KAAK,UAAU,QAAQ;AAAA,YACxB;AAAA,UACD;AAEA,gBAAM,KAAK,EAAE,IAAI,SAAS,aAAa,OAAO;AAC9C,gBAAM,OAAO,EAAE,IAAI,SAAS,IAAI,EAAE;AAElC,iBAAO,MAAM,KAAK,MAAM,YAAY;AAAA,QACrC;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAAA,EAEA,MAAM,SAAS;AAAA,IACd;AAAA,IACA;AAAA,EACD,GAA4E;AAC3E,UAAM,MAAM,wBAAwB;AAGpC,UAAM,YAAa,MAAM,IAAI,SAAS,IAAIA,MAAK,MAAM,SAAS,OAAO,GAAG;AAAA,MACvE,MAAM;AAAA,IACP,CAAC;AAGD,QAAI,CAAC,WAAW;AACf,aAAO;AAAA,IACR;AAEA,WAAO;AAAA,MACN;AAAA,MACA,MAAM,UAAU;AAAA,MAChB,KAAK,UAAU;AAAA,IAChB;AAAA,EACD;AAAA,EAEA,MAAM,WAAW;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,EACD,GAEE;AACD,UAAM,MAAM,wBAAwB;AAEpC,WAAO,EAAE,MAAM,mCAAmC,EAAE,MAAM,IAAI,CAAC;AAI/D,UAAM,gBAAgB,oBAAoB,MAAM,GAAG;AACnD,UAAM,UAAU,IAAI,SAAS,WAAW,aAAa,EAAE,SAAS;AAGhE,UAAM,YAAY,MAAM,IAAI,SAAS,IAAIA,MAAK,MAAM,SAAS,OAAO,GAAG;AAAA,MACtE,MAAM;AAAA,IACP,CAAC;AAED,QAAI,CAAC,WAAW;AACf,aAAO,EAAE,MAAM,yDAAyD;AAAA,QACvE;AAAA,QACA;AAAA,QACA;AAAA,MACD,CAAC;AACD,aAAO;AAAA,IACR;AAEA,WAAO,EAAE,MAAM,sDAAsD;AAAA,MACpE;AAAA,MACA;AAAA,MACA;AAAA,IACD,CAAC;AACD,WAAO,KAAK,kBAAkB,GAAG,OAAO;AAAA,EACzC;AAAA,EAEA,MAAM,mBACL,OACuB;AAEvB,UAAM,YAAY,MAAM,KAAK,WAAW,KAAK;AAC7C,QAAI,WAAW;AACd,aAAO;AAAA,IACR,OAAO;AACN,aAAO,MAAM,KAAK,YAAY,KAAK;AAAA,IACpC;AAAA,EACD;AAAA,EAEA,MAAM,YAAY;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,GAA8D;AAC7D,UAAM,MAAM,wBAAwB;AAGpC,UAAM,gBAAgB,MAAM,KAAK,WAAW,EAAE,GAAG,MAAM,IAAI,CAAC;AAC5D,QAAI,eAAe;AAClB,YAAM,IAAI,mBAAmB,MAAM,GAAG;AAAA,IACvC;AAIA,UAAM,gBAAgB,oBAAoB,MAAM,GAAG;AACnD,UAAM,OAAO,IAAI,SAAS,WAAW,aAAa;AAClD,UAAM,UAAU,KAAK,SAAS;AAG9B,UAAM,QAAQ,IAAI,SAAS,IAAI,IAAI;AACnC,UAAM,MAAM,WAAW;AAAA,MACtB;AAAA,MACA;AAAA,MACA;AAAA,IACD,CAAC;AAGD,UAAM,YAAuB,EAAE,MAAM,IAAI;AACzC,UAAM,IAAI,SAAS;AAAA,MAClBA,MAAK,MAAM,SAAS,OAAO;AAAA,MAC3B,KAAK,UAAU,SAAS;AAAA,IACzB;AAGA,UAAM,IAAI,SAAS,IAAIA,MAAK,MAAM,SAAS,MAAM,GAAG,GAAG,OAAO;AAE9D,WAAO;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAAA;AAAA,EAGA,MAAM,kBACL,GACA,SACmC;AACnC,UAAM,MAAM,wBAAwB;AAEpC,UAAM,YAAa,MAAM,IAAI,SAAS,IAAIA,MAAK,MAAM,SAAS,OAAO,GAAG;AAAA,MACvE,MAAM;AAAA,IACP,CAAC;AAED,QAAI,CAAC,WAAW;AACf,aAAO;AAAA,IACR;AAEA,WAAO;AAAA,MACN;AAAA,MACA,MAAM,UAAU;AAAA,MAChB,KAAK,UAAU;AAAA,IAChB;AAAA,EACD;AACD;;;AEzUA,SAAS,uBAAuB,iBAAiB;AAG1C,IAAM,mBAKT,sBAAsB,OAAO,GAAG,WAAW;AAb/C;AAcC,QAAM,gBAAgB,EAAE,IAAI,OAAO,SAAS;AAC5C,MAAI,kBAAkB,aAAa;AAClC;AAAA,EACD;AAEA,QAAM,gBAAgB,IAAI,cAAc;AACxC,QAAM,SAAoB,cAAc,CAAC;AACzC,QAAM,SAAoB,cAAc,CAAC;AAEzC,QAAM,YAAY,IAAI,UAAqB;AAAA,IAC1C,OAAO,CAAC,MAAM,WAAW,OAAO,MAAM,MAAM,MAAM;AAAA,IAClD,IAAI,WAAW;AACd,aAAO,OAAO;AAAA,IACf;AAAA,IACA,KAAK;AAAA,IACL,IAAI,aAAa;AAChB,aAAO,OAAO;AAAA,IACf;AAAA,IACA,KAAK,OAAO,MAAM,IAAI,IAAI,OAAO,GAAG,IAAI;AAAA,IACxC,MAAM,CAAC,WAAW,OAAO,KAAK,MAAM;AAAA,EACrC,CAAC;AAED,MAAI,OAAO,SAAS;AACnB,WAAO;AAAA,MAAiB;AAAA,MAAS,CAAC,QAAiB;AArCrD,YAAAC;AAsCG,gBAAAA,MAAA,OAAO,YAAP,gBAAAA,IAAA,aAAiB,KAAK;AAAA;AAAA,IACvB;AAAA,EACD;AACA,MAAI,OAAO,WAAW;AACrB,WAAO;AAAA,MAAiB;AAAA,MAAW,CAAC,QAAmB;AA1CzD,YAAAA;AA2CG,gBAAAA,MAAA,OAAO,cAAP,gBAAAA,IAAA,aAAmB,KAAK;AAAA;AAAA,IACzB;AAAA,EACD;AACA,MAAI,OAAO,SAAS;AACnB,WAAO;AAAA,MAAiB;AAAA,MAAS,CAAC,QAAY;AA/ChD,YAAAA;AAgDG,gBAAAA,MAAA,OAAO,YAAP,gBAAAA,IAAA,aAAiB,KAAK;AAAA;AAAA,IACvB;AAAA,EACD;AAEA,eAAO,WAAP;AAKA,eAAO,WAAP,gCAAgB,IAAI,MAAM,MAAM,GAAG;AAEnC,SAAO,IAAI,SAAS,MAAM;AAAA,IACzB,QAAQ;AAAA,IACR,SAAS;AAAA;AAAA;AAAA;AAAA,MAIR,0BAA0B;AAAA,IAC3B;AAAA,IACA,WAAW;AAAA,EACZ,CAAC;AACF,CAAC;;;AP3CM,IAAM,iBAAiB,IAAI,kBAA4B;AAEvD,SAAS,0BAAoC;AACnD,QAAM,MAAM,eAAe,SAAS;AACpC,EAAAC,WAAU,KAAK,wBAAwB;AACvC,SAAO;AACR;AAYO,SAAS,oBACf,UACA,aACU;AACV,QAAM,EAAE,cAAc,IAAI,aAAa,UAAU,WAAW;AAC5D,SAAO,cAAc;AACtB;AAEO,SAAS,aACf,UACA,aACiB;AACjB,QAAM,SAAS,aAAa,MAAM,WAAW;AAG7C,QAAM,YAAY;AAAA,IACjB,QAAQ;AAAA,MACP,UAAU;AAAA,MACV,SAAS,IAAI,8BAA8B;AAAA;AAAA,MAE3C,OAAO;AAAA,IACR;AAAA,IACA,qBAAqB,MAAM;AAAA,IAC3B,GAAG;AAAA,EACJ;AAGA,QAAM,eAAe,yBAAyB,UAAU,SAAS;AAEjE,QAAM,kBAAkB,IAAI;AAAA,IAC3B,SAAS;AAAA,IACT;AAAA,EACD;AAEA,SAAO;AAAA,IACN,QAAQ,gBAAgB;AAAA,IACxB,eAAe,CAAC,SAAS;AAExB,YAAM,MAAM,QAAQ,IAAI,KAAK;AAG7B,UAAI,MAAM,aAAa,gBAAgB,MAAM;AAG7C,YAAM,UAAU;AAAA,QACf,OAAO,CAAC,SAAS,KAAK,QAAQ;AAC7B,iBAAO,eAAe,IAAI,KAAK,MAAM,IAAI,MAAM,SAAS,KAAK,GAAG,CAAC;AAAA,QAClE;AAAA,MACD;AAEA,aAAO,EAAE,SAAS,aAAa;AAAA,IAChC;AAAA,EACD;AACD;","names":["invariant","KEYS","_a","invariant"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rivetkit/cloudflare-workers",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"rivetkit",
|
|
6
6
|
"cloudflare",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"sideEffects": false,
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"@rivetkit/core": "*",
|
|
34
|
-
"hono": "
|
|
34
|
+
"hono": "4.8.3"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@cloudflare/workers-types": "^4.20250129.0",
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"tsup": "^8.4.0",
|
|
41
41
|
"typescript": "^5.5.2",
|
|
42
42
|
"vitest": "^3.1.1",
|
|
43
|
-
"wrangler": "^
|
|
44
|
-
"@rivetkit/core": "0.9.
|
|
43
|
+
"wrangler": "^4.22.0",
|
|
44
|
+
"@rivetkit/core": "0.9.1"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"invariant": "^2.2.4",
|
package/src/actor-driver.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
ActorDriver,
|
|
3
|
+
AnyActorInstance,
|
|
4
|
+
} from "@rivetkit/core/driver-helpers";
|
|
2
5
|
import invariant from "invariant";
|
|
3
|
-
import { KEYS } from
|
|
6
|
+
import { KEYS } from "./actor-handler-do";
|
|
4
7
|
|
|
5
8
|
interface DurableObjectGlobalState {
|
|
6
9
|
ctx: DurableObjectState;
|
package/src/actor-handler-do.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { DurableObject } from "cloudflare:workers";
|
|
2
|
-
import type { Registry, RunConfig
|
|
2
|
+
import type { ActorKey, Registry, RunConfig } from "@rivetkit/core";
|
|
3
3
|
import { serializeEmptyPersistData } from "@rivetkit/core/driver-helpers";
|
|
4
|
-
import { logger } from "./log";
|
|
5
4
|
import { PartitionTopologyActor } from "@rivetkit/core/topologies/partition";
|
|
5
|
+
import type { ExecutionContext } from "hono";
|
|
6
6
|
import {
|
|
7
|
-
CloudflareDurableObjectGlobalState,
|
|
8
7
|
CloudflareActorsActorDriver,
|
|
8
|
+
CloudflareDurableObjectGlobalState,
|
|
9
9
|
} from "./actor-driver";
|
|
10
|
-
import { Bindings, CF_AMBIENT_ENV } from "./handler";
|
|
11
|
-
import {
|
|
10
|
+
import { type Bindings, CF_AMBIENT_ENV } from "./handler";
|
|
11
|
+
import { logger } from "./log";
|
|
12
12
|
|
|
13
13
|
export const KEYS = {
|
|
14
14
|
NAME: "rivetkit:name",
|
package/src/config.ts
CHANGED
package/src/handler.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
import type { Registry, RunConfig } from "@rivetkit/core";
|
|
3
|
+
import type { Client } from "@rivetkit/core/client";
|
|
4
|
+
import { PartitionTopologyManager } from "@rivetkit/core/topologies/partition";
|
|
5
|
+
import { Hono } from "hono";
|
|
6
|
+
import invariant from "invariant";
|
|
1
7
|
import {
|
|
2
|
-
type DurableObjectConstructor,
|
|
3
8
|
type ActorHandlerInterface,
|
|
4
9
|
createActorDurableObject,
|
|
10
|
+
type DurableObjectConstructor,
|
|
5
11
|
} from "./actor-handler-do";
|
|
6
|
-
import { ConfigSchema, type
|
|
7
|
-
import { Hono } from "hono";
|
|
8
|
-
import { PartitionTopologyManager } from "@rivetkit/core/topologies/partition";
|
|
9
|
-
import type { Client } from "@rivetkit/core/client";
|
|
12
|
+
import { ConfigSchema, type InputConfig } from "./config";
|
|
10
13
|
import { CloudflareActorsManagerDriver } from "./manager-driver";
|
|
11
|
-
import { DriverConfig, Registry, RunConfig } from "@rivetkit/core";
|
|
12
14
|
import { upgradeWebSocket } from "./websocket";
|
|
13
|
-
import invariant from "invariant";
|
|
14
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
15
15
|
|
|
16
16
|
/** Cloudflare Workers env */
|
|
17
17
|
export interface Bindings {
|
package/src/manager-driver.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
+
import type { Encoding } from "@rivetkit/core";
|
|
1
2
|
import {
|
|
2
|
-
type ManagerDriver,
|
|
3
|
-
type GetForIdInput,
|
|
4
|
-
type GetWithKeyInput,
|
|
5
3
|
type ActorOutput,
|
|
4
|
+
type ConnRoutingHandler,
|
|
6
5
|
type CreateInput,
|
|
6
|
+
type GetForIdInput,
|
|
7
7
|
type GetOrCreateWithKeyInput,
|
|
8
|
-
type
|
|
9
|
-
HEADER_EXPOSE_INTERNAL_ERROR,
|
|
10
|
-
HEADER_ENCODING,
|
|
11
|
-
HEADER_CONN_PARAMS,
|
|
8
|
+
type GetWithKeyInput,
|
|
12
9
|
HEADER_AUTH_DATA,
|
|
10
|
+
HEADER_CONN_PARAMS,
|
|
11
|
+
HEADER_ENCODING,
|
|
12
|
+
HEADER_EXPOSE_INTERNAL_ERROR,
|
|
13
|
+
type ManagerDriver,
|
|
13
14
|
} from "@rivetkit/core/driver-helpers";
|
|
14
15
|
import { ActorAlreadyExists, InternalError } from "@rivetkit/core/errors";
|
|
15
|
-
import { Bindings } from "./mod";
|
|
16
|
-
import { logger } from "./log";
|
|
17
|
-
import { serializeNameAndKey, serializeKey } from "./util";
|
|
18
16
|
import { getCloudflareAmbientEnv } from "./handler";
|
|
19
|
-
import {
|
|
17
|
+
import { logger } from "./log";
|
|
18
|
+
import type { Bindings } from "./mod";
|
|
19
|
+
import { serializeKey, serializeNameAndKey } from "./util";
|
|
20
20
|
|
|
21
21
|
// Actor metadata structure
|
|
22
22
|
interface ActorData {
|
package/src/mod.ts
CHANGED
package/src/util.ts
CHANGED
|
@@ -4,102 +4,101 @@ export const KEY_SEPARATOR = ",";
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Serializes an array of key strings into a single string for use with idFromName
|
|
7
|
-
*
|
|
7
|
+
*
|
|
8
8
|
* @param name The actor name
|
|
9
9
|
* @param key Array of key strings to serialize
|
|
10
10
|
* @returns A single string containing the serialized name and key
|
|
11
11
|
*/
|
|
12
12
|
export function serializeNameAndKey(name: string, key: string[]): string {
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
// Escape colons in the name
|
|
14
|
+
const escapedName = name.replace(/:/g, "\\:");
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
// For empty keys, just return the name and a marker
|
|
17
|
+
if (key.length === 0) {
|
|
18
|
+
return `${escapedName}:${EMPTY_KEY}`;
|
|
19
|
+
}
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
// Serialize the key array
|
|
22
|
+
const serializedKey = serializeKey(key);
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
// Combine name and serialized key
|
|
25
|
+
return `${escapedName}:${serializedKey}`;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Serializes an array of key strings into a single string
|
|
30
|
-
*
|
|
30
|
+
*
|
|
31
31
|
* @param key Array of key strings to serialize
|
|
32
32
|
* @returns A single string containing the serialized key
|
|
33
33
|
*/
|
|
34
34
|
export function serializeKey(key: string[]): string {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
35
|
+
// Use a special marker for empty key arrays
|
|
36
|
+
if (key.length === 0) {
|
|
37
|
+
return EMPTY_KEY;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Escape each key part to handle the separator and the empty key marker
|
|
41
|
+
const escapedParts = key.map((part) => {
|
|
42
|
+
// First check if it matches our empty key marker
|
|
43
|
+
if (part === EMPTY_KEY) {
|
|
44
|
+
return `\\${EMPTY_KEY}`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Escape backslashes first, then commas
|
|
48
|
+
let escaped = part.replace(/\\/g, "\\\\");
|
|
49
|
+
escaped = escaped.replace(/,/g, "\\,");
|
|
50
|
+
return escaped;
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
return escapedParts.join(KEY_SEPARATOR);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
/**
|
|
57
57
|
* Deserializes a key string back into an array of key strings
|
|
58
|
-
*
|
|
58
|
+
*
|
|
59
59
|
* @param keyString The serialized key string
|
|
60
60
|
* @returns Array of key strings
|
|
61
61
|
*/
|
|
62
62
|
export function deserializeKey(keyString: string): string[] {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
63
|
+
// Handle empty values
|
|
64
|
+
if (!keyString) {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Check for special empty key marker
|
|
69
|
+
if (keyString === EMPTY_KEY) {
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Split by unescaped commas and unescape the escaped characters
|
|
74
|
+
const parts: string[] = [];
|
|
75
|
+
let currentPart = "";
|
|
76
|
+
let escaping = false;
|
|
77
|
+
|
|
78
|
+
for (let i = 0; i < keyString.length; i++) {
|
|
79
|
+
const char = keyString[i];
|
|
80
|
+
|
|
81
|
+
if (escaping) {
|
|
82
|
+
// This is an escaped character, add it directly
|
|
83
|
+
currentPart += char;
|
|
84
|
+
escaping = false;
|
|
85
|
+
} else if (char === "\\") {
|
|
86
|
+
// Start of an escape sequence
|
|
87
|
+
escaping = true;
|
|
88
|
+
} else if (char === KEY_SEPARATOR) {
|
|
89
|
+
// This is a separator
|
|
90
|
+
parts.push(currentPart);
|
|
91
|
+
currentPart = "";
|
|
92
|
+
} else {
|
|
93
|
+
// Regular character
|
|
94
|
+
currentPart += char;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Add the last part if it exists
|
|
99
|
+
if (currentPart || parts.length > 0) {
|
|
100
|
+
parts.push(currentPart);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return parts;
|
|
104
104
|
}
|
|
105
|
-
|
package/src/websocket.ts
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
//
|
|
3
3
|
// This version calls the open event by default
|
|
4
4
|
|
|
5
|
-
import { WSContext, defineWebSocketHelper } from "hono/ws";
|
|
6
5
|
import type { UpgradeWebSocket, WSEvents, WSReadyState } from "hono/ws";
|
|
6
|
+
import { defineWebSocketHelper, WSContext } from "hono/ws";
|
|
7
7
|
|
|
8
8
|
// Based on https://github.com/honojs/hono/issues/1153#issuecomment-1767321332
|
|
9
9
|
export const upgradeWebSocket: UpgradeWebSocket<
|