@statewalker/cellb 0.1.0 → 0.2.0
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/README.md +45 -21
- package/dist/adapters/wasm-sqlite.d.ts +11 -0
- package/dist/adapters/wasm-sqlite.js +26 -3
- package/dist/adapters/wasm-sqlite.js.map +1 -1
- package/dist/bindings/assets.js +2 -2
- package/dist/bindings/assets.js.map +1 -1
- package/dist/bindings/r2.js +2 -2
- package/dist/bindings/r2.js.map +1 -1
- package/dist/browser.d.ts +0 -1
- package/dist/browser.js +0 -1
- package/dist/browser.js.map +1 -1
- package/dist/bucket/celld-cells.js +1 -1
- package/dist/bucket/celld-cells.js.map +1 -1
- package/dist/bucket/s3-object-store.js +1 -1
- package/dist/bucket/s3-object-store.js.map +1 -1
- package/dist/core/handles.d.ts +5 -2
- package/dist/core/handles.js +12 -1
- package/dist/core/handles.js.map +1 -1
- package/dist/core/id.js +3 -3
- package/dist/core/id.js.map +1 -1
- package/dist/core/namespace.d.ts +1 -1
- package/dist/core/namespace.js +2 -1
- package/dist/core/namespace.js.map +1 -1
- package/dist/core/object-host.d.ts +23 -0
- package/dist/core/object-host.js +87 -6
- package/dist/core/object-host.js.map +1 -1
- package/dist/core/runtime.d.ts +10 -0
- package/dist/core/runtime.js +43 -2
- package/dist/core/runtime.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/isolate/browser.js +1 -1
- package/dist/isolate/browser.js.map +1 -1
- package/dist/isolate/host.d.ts +5 -1
- package/dist/isolate/host.js +19 -3
- package/dist/isolate/host.js.map +1 -1
- package/dist/isolate/isolate-worker.js +11 -1
- package/dist/isolate/isolate-worker.js.map +1 -1
- package/dist/isolate/isolate.js +12 -0
- package/dist/isolate/isolate.js.map +1 -1
- package/dist/isolate/node-entry.js +11 -0
- package/dist/isolate/node-entry.js.map +1 -1
- package/dist/isolate/protocol.d.ts +4 -0
- package/dist/isolate/protocol.js +118 -2
- package/dist/isolate/protocol.js.map +1 -1
- package/dist/node-compat/crypto.js +3 -3
- package/dist/node-compat/crypto.js.map +1 -1
- package/dist/project/browser-host.js +3 -2
- package/dist/project/browser-host.js.map +1 -1
- package/dist/project/node-project.js +13 -1
- package/dist/project/node-project.js.map +1 -1
- package/dist/project/site-loader.d.ts +45 -0
- package/dist/project/site-loader.js +97 -0
- package/dist/project/site-loader.js.map +1 -0
- package/dist/project/site.d.ts +0 -36
- package/dist/project/site.js +11 -99
- package/dist/project/site.js.map +1 -1
- package/dist/project/wrangler.js +10 -0
- package/dist/project/wrangler.js.map +1 -1
- package/dist/router/cell-router.js +1 -1
- package/dist/router/cell-router.js.map +1 -1
- package/dist/site.d.ts +1 -0
- package/dist/site.js +6 -0
- package/dist/site.js.map +1 -0
- package/dist/ws/frames.d.ts +14 -0
- package/dist/ws/frames.js +51 -0
- package/dist/ws/frames.js.map +1 -1
- package/dist/ws/server.d.ts +4 -0
- package/dist/ws/server.js +17 -2
- package/dist/ws/server.js.map +1 -1
- package/package.json +25 -5
package/dist/project/wrangler.js
CHANGED
|
@@ -159,6 +159,16 @@ export function createProjectRuntime(config, module, host) {
|
|
|
159
159
|
},
|
|
160
160
|
};
|
|
161
161
|
}
|
|
162
|
+
// The isolates of loaded Workers end with the runtime (on Node, a worker thread's port would
|
|
163
|
+
// keep the process alive; in a browser, a Dedicated Worker would outlive the runtime).
|
|
164
|
+
const isolated = host.isolatedModules;
|
|
165
|
+
if (config.worker_loaders?.length && isolated?.close) {
|
|
166
|
+
const close = runtime.close.bind(runtime);
|
|
167
|
+
runtime.close = async () => {
|
|
168
|
+
await close();
|
|
169
|
+
isolated.close?.();
|
|
170
|
+
};
|
|
171
|
+
}
|
|
162
172
|
for (const l of config.worker_loaders ?? []) {
|
|
163
173
|
if (!host.loadModules)
|
|
164
174
|
unsupported.push(`worker_loaders[${l.binding}] (the host provides no module loader)`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrangler.js","sourceRoot":"","sources":["../../src/project/wrangler.ts"],"names":[],"mappings":"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","sourcesContent":["import type { FilesApi } from \"@statewalker/webrun-files\";\nimport { type AssetFiles, type AssetsConfig, createAssets } from \"../bindings/assets.js\";\nimport { celldKv } from \"../bindings/celld-kv.js\";\nimport { celldQueues, type QueueConsumerConfig } from \"../bindings/celld-queues.js\";\nimport { celldWorkflows } from \"../bindings/celld-workflows.js\";\nimport { startCronTriggers } from \"../bindings/cron.js\";\nimport { r2Bucket, r2BucketOn } from \"../bindings/r2.js\";\nimport { celldR2Backend } from \"../bindings/r2-celld.js\";\nimport { type ModuleLoader, workerLoader } from \"../bindings/worker-loader.js\";\nimport { type WorkersAiOptions, workersAi } from \"../bindings/workers-ai.js\";\nimport { entrypointStub } from \"../core/handles.js\";\nimport type { DurableObjectNamespace } from \"../core/namespace.js\";\nimport {\n type CellRuntime,\n type CellRuntimeOptions,\n createCellRuntime,\n type WorkerModule,\n} from \"../core/runtime.js\";\nimport { splitSqlStatements } from \"../core/sql-split.js\";\nimport { filesApiBlobService } from \"../miniflare-compat/blob-service.js\";\nimport { simulatorFetcher } from \"../miniflare-compat/simulator-fetcher.js\";\nimport { D1DatabaseObject, makeD1Binding } from \"../miniflare-compat/vendored.js\";\nimport { systemClock } from \"../ports.js\";\n\n/** The subset of wrangler.json(c) that celld deploys (and cellb reads). */\nexport interface WranglerConfig {\n name?: string;\n main?: string;\n compatibility_date?: string;\n compatibility_flags?: string[];\n vars?: Record<string, unknown>;\n durable_objects?: { bindings?: { name: string; class_name: string; script_name?: string }[] };\n migrations?: {\n tag: string;\n new_sqlite_classes?: string[];\n new_classes?: string[];\n renamed_classes?: { from: string; to: string }[];\n deleted_classes?: string[];\n }[];\n kv_namespaces?: { binding: string; id?: string }[];\n d1_databases?: { binding: string; database_name?: string; database_id?: string }[];\n r2_buckets?: { binding: string; bucket_name: string }[];\n queues?: {\n producers?: { binding: string; queue: string; delivery_delay?: number }[];\n consumers?: QueueConsumerConfig[];\n };\n workflows?: WorkflowConfig[];\n triggers?: { crons?: string[] };\n assets?: AssetsConfig;\n services?: { binding: string; service: string; entrypoint?: string; props?: unknown }[];\n worker_loaders?: { binding: string }[];\n /** Workers AI: served by the host's OpenAI-compatible endpoint (`ProjectHost.ai`), if any. */\n ai?: { binding: string };\n /** Containers (celld runs them with Docker or Podman): not supported, reported. */\n containers?: { class_name: string; image?: string }[];\n}\n\n/** wrangler `workflows` entries. */\nexport interface WorkflowConfig {\n binding: string;\n name: string;\n class_name: string;\n}\n\n/** Runs the Worker's `queue(batch, env, ctx)` handler for a batch celld's queue cell leased. */\ninterface QueueDispatcher {\n deliver(batch: unknown): Promise<void>;\n}\n\nexport interface ProjectHost\n extends Pick<CellRuntimeOptions, \"openSql\" | \"storage\" | \"clock\" | \"peers\" | \"route\"> {\n /** Files of `assets.directory` (path \"/a/b.html\" → bytes), loaded by the host. */\n assetFiles?: AssetFiles;\n /** Runs each loaded Worker in its own realm (celld isolates); classes still use `loadModules`. */\n isolatedModules?: ModuleLoader;\n /** Compiles code given to a Worker Loader binding (esbuild on Node, webrun-modules in browsers). */\n loadModules?: ModuleLoader;\n /** Blob store of the KV simulator (large values): OPFS in a browser, a directory or S3 on a server. */\n files: FilesApi;\n /** The OpenAI-compatible endpoint behind the `ai` binding; without it the binding is unsupported. */\n ai?: WorkersAiOptions;\n}\n\nexport interface ProjectRuntime {\n runtime: CellRuntime;\n /** Configuration entries cellb does not support yet (reported, not silently ignored). */\n unsupported: string[];\n}\n\n/**\n * What `env` of `cloudflare:workers` holds while the Worker's module is evaluated, before the\n * runtime exists: the vars, and the bindings that need no runtime (`ai`; Flue's entry reads\n * `env.AI` at load).\n */\nexport function loadTimeEnv(\n config: WranglerConfig,\n ai?: WorkersAiOptions,\n): Record<string, unknown> {\n const env: Record<string, unknown> = { ...config.vars };\n if (config.ai && ai) env[config.ai.binding] = workersAi(ai);\n return env;\n}\n\n// Internal bindings carrying the runtime-supplied objects behind KV and D1.\nconst KV_OBJECTS = \"__CELLS_KV_OBJECTS\";\nconst D1_OBJECTS = \"__CELLS_D1_OBJECTS\";\nconst QUEUE_OBJECTS = \"__CELLS_QUEUE_OBJECTS\";\nconst WORKFLOW_OBJECTS = \"__CELLS_WORKFLOW_OBJECTS\";\n\n/**\n * Builds a runtime from a wrangler config and the Worker's module namespace — the same\n * inputs celld deploys. Hosts differ only in `host` (storage) and in how they load `main`.\n */\nexport function createProjectRuntime(\n config: WranglerConfig,\n module: WorkerModule,\n host: ProjectHost,\n): ProjectRuntime {\n config = withResourceIds(config);\n const unsupported: string[] = [];\n const durableObjects: NonNullable<CellRuntimeOptions[\"durableObjects\"]> = {};\n const sqliteClasses = new Set<string>();\n for (const m of config.migrations ?? []) {\n for (const c of m.new_sqlite_classes ?? []) sqliteClasses.add(c);\n for (const c of m.new_classes ?? []) sqliteClasses.add(c); // KV-backed on Cloudflare; SQLite here (superset)\n for (const r of m.renamed_classes ?? [])\n unsupported.push(`migrations.renamed_classes (${r.from} → ${r.to})`);\n }\n for (const c of config.containers ?? [])\n unsupported.push(`containers[${c.class_name}] (cellb runs no containers)`);\n for (const b of config.durable_objects?.bindings ?? []) {\n if (b.script_name) unsupported.push(`durable_objects.bindings[${b.name}].script_name`);\n durableObjects[b.name] = { className: b.class_name };\n }\n const worker: WorkerModule = { ...module };\n let kv: ReturnType<typeof celldKv> | undefined;\n if (config.kv_namespaces?.length) {\n kv = celldKv(host.files);\n worker.__KvNamespace = kv.KvNamespaceCell as never;\n durableObjects[KV_OBJECTS] = { className: \"__KvNamespace\" };\n }\n if (config.d1_databases?.length) {\n worker.__D1Database = D1DatabaseObject;\n durableObjects[D1_OBJECTS] = { className: \"__D1Database\" };\n }\n // Queues: every queue is a cell of a runtime-supplied class (as on celld).\n const consumers = new Map((config.queues?.consumers ?? []).map((c) => [c.queue, c]));\n // celld's own queue code (vendor/celld/queues.js): its queue cell, producer and consumer\n // batch, so a queue's cell (and pending messages) is celld's format.\n let queueDispatcher: QueueDispatcher | undefined;\n let queues: ReturnType<typeof celldQueues> | undefined;\n if (config.queues?.producers?.length || consumers.size) {\n queues = celldQueues({\n namespace: () => runtime.env[QUEUE_OBJECTS] as never,\n consumers: [...consumers.values()],\n compatibilityDate: config.compatibility_date,\n runConsumer: (batch) => queueDispatcher!.deliver(batch as never),\n });\n worker.__Queue = queues.QueueCell as never;\n durableObjects[QUEUE_OBJECTS] = { className: \"__Queue\" };\n }\n // Workflows: every instance is a cell of a runtime-supplied class (as on celld).\n // celld's own workflow code (vendor/celld/workflows.js): its instance cell and binding.\n let workflows: ReturnType<typeof celldWorkflows> | undefined;\n if (config.workflows?.length) {\n workflows = celldWorkflows({\n script: config.name ?? \"worker\",\n workflows: Object.fromEntries(config.workflows.map((w) => [w.name, w.class_name])),\n exports: () => module as Record<string, unknown>,\n env: () => runtime.env,\n namespace: () => runtime.env[WORKFLOW_OBJECTS],\n });\n worker[workflows.className] = workflows.WorkflowCell as never;\n durableObjects[WORKFLOW_OBJECTS] = { className: workflows.className };\n }\n if (config.ai && !host.ai)\n unsupported.push(\n `ai[${config.ai.binding}] (Workers AI: give the host an OpenAI-compatible \\`ai\\`)`,\n );\n for (const s of config.services ?? [])\n if (s.service !== config.name)\n unsupported.push(\n `services[${s.binding}] → \"${s.service}\" (only this script's own entrypoints)`,\n );\n const sqlExtensions: string[] = [];\n let deleteAllPreservesAlarm = false;\n for (const f of config.compatibility_flags ?? []) {\n if (f === \"delete_all_preserves_alarm\") deleteAllPreservesAlarm = true;\n else if (f === \"delete_all_deletes_alarm\")\n continue; // the default\n else if (f === \"sqlite_vec\")\n sqlExtensions.push(\"sqlite_vec\"); // vec0 virtual tables, as on celld\n else if (f === \"nodejs_compat\" || f === \"nodejs_compat_v2\")\n continue; // the host's bundler maps node:*\n else if (f === \"websocket_standard_binary_type\")\n continue; // the host picks the project's WebSocketPair\n else unsupported.push(`compatibility_flags: ${f}`);\n }\n\n const runtime = createCellRuntime({\n worker,\n durableObjects,\n vars: { ...config.vars, MINIFLARE_BLOBS: filesApiBlobService(host.files) },\n openSql: host.openSql,\n sqlExtensions,\n deleteAllPreservesAlarm,\n scriptName: config.name ?? \"worker\",\n // celld's fleet-wide namespaces for the resources several scripts can share.\n namespaceKeys: {\n __KvNamespace: \"cells:v1:kv:__KvNamespace\",\n __D1Database: \"cells:v1:d1:__D1Database\",\n __Queue: \"cells:v1:queue:__Queue\",\n },\n storage: host.storage,\n clock: host.clock,\n peers: host.peers,\n route: host.route,\n });\n const env = runtime.env as Record<string, unknown>;\n if (config.ai && host.ai) env[config.ai.binding] = workersAi(host.ai);\n // KV: celld's own client against celld's own namespace cell (cell name \"<id>/<shard>\").\n for (const ns of config.kv_namespaces ?? [])\n env[ns.binding] = new kv!.KvNamespace(() => env[KV_OBJECTS], `${ns.id}/0`);\n for (const p of config.queues?.producers ?? [])\n env[p.binding] = queues!.producer(p.queue, p.delivery_delay ?? 0);\n if (consumers.size) {\n const handler = (module.default as { queue?: (b: unknown, e: unknown, c: unknown) => unknown })\n .queue;\n if (typeof handler !== \"function\")\n unsupported.push(\"queues.consumers without a queue() handler\");\n queueDispatcher = {\n deliver: async (batch) => {\n const pending: Promise<unknown>[] = [];\n await handler?.call(module.default, batch, env, {\n waitUntil: (p: Promise<unknown>) => pending.push(p),\n passThroughOnException() {},\n });\n await Promise.allSettled(pending);\n },\n };\n }\n for (const l of config.worker_loaders ?? []) {\n if (!host.loadModules)\n unsupported.push(`worker_loaders[${l.binding}] (the host provides no module loader)`);\n else\n env[l.binding] = host.isolatedModules\n ? workerLoader(host.isolatedModules) // facets of loaded code run in the isolate as well\n : workerLoader(host.loadModules);\n }\n // Cron Triggers (validated at load time like `celld deploy` does).\n const crons = config.triggers?.crons ?? [];\n if (crons.length) {\n const scheduled = (\n module.default as { scheduled?: (c: unknown, e: unknown, x: unknown) => unknown }\n ).scheduled;\n if (typeof scheduled !== \"function\")\n unsupported.push(\"triggers.crons without a scheduled() handler\");\n else {\n const db = host.openSql(\"__cellb/cron\");\n const stop = startCronTriggers(\n crons,\n (c, x) => runtime.runEvent(() => scheduled.call(module.default, c, env, x)),\n host.clock ?? systemClock,\n cronState(db),\n );\n const close = runtime.close.bind(runtime);\n runtime.close = async () => {\n stop();\n db.close();\n await close();\n };\n }\n }\n // Static assets: routed before the Worker; `assets.binding` exposes env.ASSETS.\n if (config.assets) {\n const hasWorker = typeof (module.default as { fetch?: unknown })?.fetch === \"function\";\n if (host.assetFiles?.has(\"/.assetsignore\"))\n throw new Error(\n `${config.assets.directory ?? \"assets\"}/.assetsignore is not supported by celld; remove it`,\n );\n const assets = createAssets(host.assetFiles ?? new Map(), config.assets, hasWorker);\n if (config.assets.binding) env[config.assets.binding] = assets.binding;\n const workerFetch = runtime.fetch.bind(runtime);\n runtime.fetch = async (req) =>\n assets.route(req) ??\n (hasWorker ? workerFetch(req) : new Response(\"Not found\", { status: 404 }));\n }\n for (const w of config.workflows ?? []) env[w.binding] = workflows!.binding(w.name);\n // Service bindings to this script's own entrypoints (a celld fleet runs one application):\n // default export or a named WorkerEntrypoint, with fetch() and JS RPC.\n for (const s of config.services ?? []) {\n if (s.service !== config.name) continue;\n const target = s.entrypoint ? module[s.entrypoint] : module.default;\n if (!target)\n unsupported.push(`services[${s.binding}].entrypoint \"${s.entrypoint}\" is not exported`);\n else env[s.binding] = entrypointStub(target, env, s.props);\n }\n // R2 objects live directly in the host's store, as celld keeps them in the fleet bucket.\n // With a celld fleet bucket, R2 objects live in it as celld keeps them; else in the FilesApi.\n for (const r2 of config.r2_buckets ?? [])\n env[r2.binding] = host.storage?.objects\n ? r2BucketOn(celldR2Backend(host.storage.objects, r2.bucket_name), r2.binding)\n : r2Bucket(host.files, `/r2/${r2.bucket_name}`, r2.binding);\n for (const d1 of config.d1_databases ?? [])\n env[d1.binding] = celldExec(\n makeD1Binding({\n fetcher: simulatorFetcher(\n env[D1_OBJECTS] as DurableObjectNamespace,\n d1.database_id as string, // set by withResourceIds\n ) as never,\n }) as D1Like,\n );\n for (const name of [...sqliteClasses])\n if (!Object.values(durableObjects).some((d) => d.className === name)) {\n // A migrated class without a binding is fine (reachable through other code paths only).\n }\n return { runtime, unsupported };\n}\n\ninterface D1Like {\n exec(sql: string): Promise<{ count: number; duration: number }>;\n prepare(sql: string): { run(): Promise<unknown> };\n}\n\n/**\n * `D1Database#exec` as celld implements it: statements are split by SQL syntax.\n * workerd's d1-api.ts splits on NEWLINES (Cloudflare's documented behaviour), so a\n * multi-line `CREATE TABLE` fails there but works on celld — and celld is the\n * reference here (verified on celld 0.6.2 by the d1 example in conformance/).\n */\nfunction celldExec<T extends D1Like>(db: T): T {\n const exec = async (sql: string) => {\n const t0 = Date.now();\n const statements = splitSqlStatements(sql).filter((s) => s.trim());\n for (const statement of statements) {\n if (/^\\s*BEGIN\\b/i.test(statement))\n throw new Error(\n \"D1_EXEC_ERROR: the SQL ends in an incomplete statement, which did not run: terminate the last statement with a semicolon\",\n );\n guard(statement);\n await db.prepare(statement).run();\n }\n return { count: statements.length, duration: Date.now() - t0 };\n };\n return celldD1(db, exec) as T;\n}\n\n/**\n * celld's D1 rules on top of workerd's client (celld docs/services/d1.md, checked by the\n * d1-details project): ATTACH/DETACH and TEMP objects are \"not authorized\", VACUUM is\n * \"authorization denied\"; there is one primary and no replica, so sessions return the\n * bookmark \"celld:primary\" and every result reports served_by_primary/served_by_region\n * \"local\"; a read-only statement reports last_row_id and changes as 0.\n */\nfunction guard(sql: string): void {\n if (/^\\s*(ATTACH|DETACH)\\b/i.test(sql) || /^\\s*CREATE\\s+(TEMP|TEMPORARY)\\b/i.test(sql))\n throw new Error(\"D1_ERROR: not authorized\");\n if (/^\\s*VACUUM\\b/i.test(sql)) throw new Error(\"D1_ERROR: authorization denied\");\n}\n\nfunction celldMeta(r: any): any {\n if (!r?.meta) return r;\n r.meta.served_by_primary = true;\n r.meta.served_by_region = \"local\";\n if (r.meta.changed_db === false) {\n r.meta.last_row_id = 0;\n r.meta.changes = 0;\n }\n return r;\n}\n\nfunction celldStatement(stmt: any): any {\n return new Proxy(stmt, {\n get(t, p, r) {\n const v = Reflect.get(t, p, r);\n if (p === \"bind\") return (...a: unknown[]) => celldStatement(v.apply(t, a));\n if (p === \"run\" || p === \"all\")\n return async (...a: unknown[]) => celldMeta(await v.apply(t, a));\n return typeof v === \"function\" ? v.bind(t) : v;\n },\n });\n}\n\nfunction celldD1(db: any, exec?: (sql: string) => Promise<unknown>): any {\n return new Proxy(db, {\n get(t, p, r) {\n if (p === \"exec\" && exec) return exec;\n const v = Reflect.get(t, p, r);\n if (p === \"prepare\")\n return (sql: string) => {\n guard(sql);\n return celldStatement(v.call(t, sql));\n };\n if (p === \"batch\")\n return async (stmts: unknown[], ...a: unknown[]) =>\n ((await v.call(t, stmts, ...a)) as unknown[]).map(celldMeta);\n if (p === \"withSession\")\n return () => {\n const session = celldD1(t);\n return new Proxy(session, {\n get: (s, q, rr) =>\n q === \"getBookmark\" ? () => \"celld:primary\" : Reflect.get(s, q, rr),\n });\n };\n if (p === \"getBookmark\") return () => \"celld:primary\";\n return typeof v === \"function\" ? v.bind(t) : v;\n },\n });\n}\n\n/** Last fired occurrence per cron expression, in a small SQLite database of the host. */\nfunction cronState(db: ReturnType<ProjectHost[\"openSql\"]>) {\n db.exec(\n \"CREATE TABLE IF NOT EXISTS cron_state (expression TEXT PRIMARY KEY, scheduled_time INTEGER)\",\n [],\n );\n return {\n get: (e: string) => {\n const row = db.exec(\"SELECT scheduled_time FROM cron_state WHERE expression = ?\", [e])\n .rows[0];\n return row ? Number(row[0]) : undefined;\n },\n set: (e: string, t: number) =>\n void db.exec(\"INSERT OR REPLACE INTO cron_state (expression, scheduled_time) VALUES (?, ?)\", [\n e,\n t,\n ]),\n };\n}\n\n/**\n * KV namespaces and D1 databases may omit their ids: wrangler provisions them on deploy, and\n * framework builds (Astro's Cloudflare adapter, for one) emit such entries. A KV namespace\n * then takes its binding name as id; a D1 database its `database_name`, else its binding name.\n * Entries with ids are kept as they are, so storage shared with celld keeps its names.\n */\nexport function withResourceIds(config: WranglerConfig): WranglerConfig {\n const kv = config.kv_namespaces;\n const d1 = config.d1_databases;\n if (!kv?.some((n) => !n.id) && !d1?.some((d) => !d.database_id)) return config;\n return {\n ...config,\n kv_namespaces: kv?.map((n) => (n.id ? n : { ...n, id: n.binding })),\n d1_databases: d1?.map((d) =>\n d.database_id ? d : { ...d, database_id: d.database_name ?? d.binding },\n ),\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"wrangler.js","sourceRoot":"","sources":["../../src/project/wrangler.ts"],"names":[],"mappings":"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","sourcesContent":["import type { FilesApi } from \"@statewalker/webrun-files\";\nimport { type AssetFiles, type AssetsConfig, createAssets } from \"../bindings/assets.js\";\nimport { celldKv } from \"../bindings/celld-kv.js\";\nimport { celldQueues, type QueueConsumerConfig } from \"../bindings/celld-queues.js\";\nimport { celldWorkflows } from \"../bindings/celld-workflows.js\";\nimport { startCronTriggers } from \"../bindings/cron.js\";\nimport { r2Bucket, r2BucketOn } from \"../bindings/r2.js\";\nimport { celldR2Backend } from \"../bindings/r2-celld.js\";\nimport { type ModuleLoader, workerLoader } from \"../bindings/worker-loader.js\";\nimport { type WorkersAiOptions, workersAi } from \"../bindings/workers-ai.js\";\nimport { entrypointStub } from \"../core/handles.js\";\nimport type { DurableObjectNamespace } from \"../core/namespace.js\";\nimport {\n type CellRuntime,\n type CellRuntimeOptions,\n createCellRuntime,\n type WorkerModule,\n} from \"../core/runtime.js\";\nimport { splitSqlStatements } from \"../core/sql-split.js\";\nimport { filesApiBlobService } from \"../miniflare-compat/blob-service.js\";\nimport { simulatorFetcher } from \"../miniflare-compat/simulator-fetcher.js\";\nimport { D1DatabaseObject, makeD1Binding } from \"../miniflare-compat/vendored.js\";\nimport { systemClock } from \"../ports.js\";\n\n/** The subset of wrangler.json(c) that celld deploys (and cellb reads). */\nexport interface WranglerConfig {\n name?: string;\n main?: string;\n compatibility_date?: string;\n compatibility_flags?: string[];\n vars?: Record<string, unknown>;\n durable_objects?: { bindings?: { name: string; class_name: string; script_name?: string }[] };\n migrations?: {\n tag: string;\n new_sqlite_classes?: string[];\n new_classes?: string[];\n renamed_classes?: { from: string; to: string }[];\n deleted_classes?: string[];\n }[];\n kv_namespaces?: { binding: string; id?: string }[];\n d1_databases?: { binding: string; database_name?: string; database_id?: string }[];\n r2_buckets?: { binding: string; bucket_name: string }[];\n queues?: {\n producers?: { binding: string; queue: string; delivery_delay?: number }[];\n consumers?: QueueConsumerConfig[];\n };\n workflows?: WorkflowConfig[];\n triggers?: { crons?: string[] };\n assets?: AssetsConfig;\n services?: { binding: string; service: string; entrypoint?: string; props?: unknown }[];\n worker_loaders?: { binding: string }[];\n /** Workers AI: served by the host's OpenAI-compatible endpoint (`ProjectHost.ai`), if any. */\n ai?: { binding: string };\n /** Containers (celld runs them with Docker or Podman): not supported, reported. */\n containers?: { class_name: string; image?: string }[];\n}\n\n/** wrangler `workflows` entries. */\nexport interface WorkflowConfig {\n binding: string;\n name: string;\n class_name: string;\n}\n\n/** Runs the Worker's `queue(batch, env, ctx)` handler for a batch celld's queue cell leased. */\ninterface QueueDispatcher {\n deliver(batch: unknown): Promise<void>;\n}\n\nexport interface ProjectHost\n extends Pick<CellRuntimeOptions, \"openSql\" | \"storage\" | \"clock\" | \"peers\" | \"route\"> {\n /** Files of `assets.directory` (path \"/a/b.html\" → bytes), loaded by the host. */\n assetFiles?: AssetFiles;\n /** Runs each loaded Worker in its own realm (celld isolates); classes still use `loadModules`. */\n isolatedModules?: ModuleLoader;\n /** Compiles code given to a Worker Loader binding (esbuild on Node, webrun-modules in browsers). */\n loadModules?: ModuleLoader;\n /** Blob store of the KV simulator (large values): OPFS in a browser, a directory or S3 on a server. */\n files: FilesApi;\n /** The OpenAI-compatible endpoint behind the `ai` binding; without it the binding is unsupported. */\n ai?: WorkersAiOptions;\n}\n\nexport interface ProjectRuntime {\n runtime: CellRuntime;\n /** Configuration entries cellb does not support yet (reported, not silently ignored). */\n unsupported: string[];\n}\n\n/**\n * What `env` of `cloudflare:workers` holds while the Worker's module is evaluated, before the\n * runtime exists: the vars, and the bindings that need no runtime (`ai`; Flue's entry reads\n * `env.AI` at load).\n */\nexport function loadTimeEnv(\n config: WranglerConfig,\n ai?: WorkersAiOptions,\n): Record<string, unknown> {\n const env: Record<string, unknown> = { ...config.vars };\n if (config.ai && ai) env[config.ai.binding] = workersAi(ai);\n return env;\n}\n\n// Internal bindings carrying the runtime-supplied objects behind KV and D1.\nconst KV_OBJECTS = \"__CELLS_KV_OBJECTS\";\nconst D1_OBJECTS = \"__CELLS_D1_OBJECTS\";\nconst QUEUE_OBJECTS = \"__CELLS_QUEUE_OBJECTS\";\nconst WORKFLOW_OBJECTS = \"__CELLS_WORKFLOW_OBJECTS\";\n\n/**\n * Builds a runtime from a wrangler config and the Worker's module namespace — the same\n * inputs celld deploys. Hosts differ only in `host` (storage) and in how they load `main`.\n */\nexport function createProjectRuntime(\n config: WranglerConfig,\n module: WorkerModule,\n host: ProjectHost,\n): ProjectRuntime {\n config = withResourceIds(config);\n const unsupported: string[] = [];\n const durableObjects: NonNullable<CellRuntimeOptions[\"durableObjects\"]> = {};\n const sqliteClasses = new Set<string>();\n for (const m of config.migrations ?? []) {\n for (const c of m.new_sqlite_classes ?? []) sqliteClasses.add(c);\n for (const c of m.new_classes ?? []) sqliteClasses.add(c); // KV-backed on Cloudflare; SQLite here (superset)\n for (const r of m.renamed_classes ?? [])\n unsupported.push(`migrations.renamed_classes (${r.from} → ${r.to})`);\n }\n for (const c of config.containers ?? [])\n unsupported.push(`containers[${c.class_name}] (cellb runs no containers)`);\n for (const b of config.durable_objects?.bindings ?? []) {\n if (b.script_name) unsupported.push(`durable_objects.bindings[${b.name}].script_name`);\n durableObjects[b.name] = { className: b.class_name };\n }\n const worker: WorkerModule = { ...module };\n let kv: ReturnType<typeof celldKv> | undefined;\n if (config.kv_namespaces?.length) {\n kv = celldKv(host.files);\n worker.__KvNamespace = kv.KvNamespaceCell as never;\n durableObjects[KV_OBJECTS] = { className: \"__KvNamespace\" };\n }\n if (config.d1_databases?.length) {\n worker.__D1Database = D1DatabaseObject;\n durableObjects[D1_OBJECTS] = { className: \"__D1Database\" };\n }\n // Queues: every queue is a cell of a runtime-supplied class (as on celld).\n const consumers = new Map((config.queues?.consumers ?? []).map((c) => [c.queue, c]));\n // celld's own queue code (vendor/celld/queues.js): its queue cell, producer and consumer\n // batch, so a queue's cell (and pending messages) is celld's format.\n let queueDispatcher: QueueDispatcher | undefined;\n let queues: ReturnType<typeof celldQueues> | undefined;\n if (config.queues?.producers?.length || consumers.size) {\n queues = celldQueues({\n namespace: () => runtime.env[QUEUE_OBJECTS] as never,\n consumers: [...consumers.values()],\n compatibilityDate: config.compatibility_date,\n runConsumer: (batch) => queueDispatcher!.deliver(batch as never),\n });\n worker.__Queue = queues.QueueCell as never;\n durableObjects[QUEUE_OBJECTS] = { className: \"__Queue\" };\n }\n // Workflows: every instance is a cell of a runtime-supplied class (as on celld).\n // celld's own workflow code (vendor/celld/workflows.js): its instance cell and binding.\n let workflows: ReturnType<typeof celldWorkflows> | undefined;\n if (config.workflows?.length) {\n workflows = celldWorkflows({\n script: config.name ?? \"worker\",\n workflows: Object.fromEntries(config.workflows.map((w) => [w.name, w.class_name])),\n exports: () => module as Record<string, unknown>,\n env: () => runtime.env,\n namespace: () => runtime.env[WORKFLOW_OBJECTS],\n });\n worker[workflows.className] = workflows.WorkflowCell as never;\n durableObjects[WORKFLOW_OBJECTS] = { className: workflows.className };\n }\n if (config.ai && !host.ai)\n unsupported.push(\n `ai[${config.ai.binding}] (Workers AI: give the host an OpenAI-compatible \\`ai\\`)`,\n );\n for (const s of config.services ?? [])\n if (s.service !== config.name)\n unsupported.push(\n `services[${s.binding}] → \"${s.service}\" (only this script's own entrypoints)`,\n );\n const sqlExtensions: string[] = [];\n let deleteAllPreservesAlarm = false;\n for (const f of config.compatibility_flags ?? []) {\n if (f === \"delete_all_preserves_alarm\") deleteAllPreservesAlarm = true;\n else if (f === \"delete_all_deletes_alarm\")\n continue; // the default\n else if (f === \"sqlite_vec\")\n sqlExtensions.push(\"sqlite_vec\"); // vec0 virtual tables, as on celld\n else if (f === \"nodejs_compat\" || f === \"nodejs_compat_v2\")\n continue; // the host's bundler maps node:*\n else if (f === \"websocket_standard_binary_type\")\n continue; // the host picks the project's WebSocketPair\n else unsupported.push(`compatibility_flags: ${f}`);\n }\n\n const runtime = createCellRuntime({\n worker,\n durableObjects,\n vars: { ...config.vars, MINIFLARE_BLOBS: filesApiBlobService(host.files) },\n openSql: host.openSql,\n sqlExtensions,\n deleteAllPreservesAlarm,\n scriptName: config.name ?? \"worker\",\n // celld's fleet-wide namespaces for the resources several scripts can share.\n namespaceKeys: {\n __KvNamespace: \"cells:v1:kv:__KvNamespace\",\n __D1Database: \"cells:v1:d1:__D1Database\",\n __Queue: \"cells:v1:queue:__Queue\",\n },\n storage: host.storage,\n clock: host.clock,\n peers: host.peers,\n route: host.route,\n });\n const env = runtime.env as Record<string, unknown>;\n if (config.ai && host.ai) env[config.ai.binding] = workersAi(host.ai);\n // KV: celld's own client against celld's own namespace cell (cell name \"<id>/<shard>\").\n for (const ns of config.kv_namespaces ?? [])\n env[ns.binding] = new kv!.KvNamespace(() => env[KV_OBJECTS], `${ns.id}/0`);\n for (const p of config.queues?.producers ?? [])\n env[p.binding] = queues!.producer(p.queue, p.delivery_delay ?? 0);\n if (consumers.size) {\n const handler = (module.default as { queue?: (b: unknown, e: unknown, c: unknown) => unknown })\n .queue;\n if (typeof handler !== \"function\")\n unsupported.push(\"queues.consumers without a queue() handler\");\n queueDispatcher = {\n deliver: async (batch) => {\n const pending: Promise<unknown>[] = [];\n await handler?.call(module.default, batch, env, {\n waitUntil: (p: Promise<unknown>) => pending.push(p),\n passThroughOnException() {},\n });\n await Promise.allSettled(pending);\n },\n };\n }\n // The isolates of loaded Workers end with the runtime (on Node, a worker thread's port would\n // keep the process alive; in a browser, a Dedicated Worker would outlive the runtime).\n const isolated = host.isolatedModules as (ModuleLoader & { close?(): void }) | undefined;\n if (config.worker_loaders?.length && isolated?.close) {\n const close = runtime.close.bind(runtime);\n runtime.close = async () => {\n await close();\n isolated.close?.();\n };\n }\n for (const l of config.worker_loaders ?? []) {\n if (!host.loadModules)\n unsupported.push(`worker_loaders[${l.binding}] (the host provides no module loader)`);\n else\n env[l.binding] = host.isolatedModules\n ? workerLoader(host.isolatedModules) // facets of loaded code run in the isolate as well\n : workerLoader(host.loadModules);\n }\n // Cron Triggers (validated at load time like `celld deploy` does).\n const crons = config.triggers?.crons ?? [];\n if (crons.length) {\n const scheduled = (\n module.default as { scheduled?: (c: unknown, e: unknown, x: unknown) => unknown }\n ).scheduled;\n if (typeof scheduled !== \"function\")\n unsupported.push(\"triggers.crons without a scheduled() handler\");\n else {\n const db = host.openSql(\"__cellb/cron\");\n const stop = startCronTriggers(\n crons,\n (c, x) => runtime.runEvent(() => scheduled.call(module.default, c, env, x)),\n host.clock ?? systemClock,\n cronState(db),\n );\n const close = runtime.close.bind(runtime);\n runtime.close = async () => {\n stop();\n db.close();\n await close();\n };\n }\n }\n // Static assets: routed before the Worker; `assets.binding` exposes env.ASSETS.\n if (config.assets) {\n const hasWorker = typeof (module.default as { fetch?: unknown })?.fetch === \"function\";\n if (host.assetFiles?.has(\"/.assetsignore\"))\n throw new Error(\n `${config.assets.directory ?? \"assets\"}/.assetsignore is not supported by celld; remove it`,\n );\n const assets = createAssets(host.assetFiles ?? new Map(), config.assets, hasWorker);\n if (config.assets.binding) env[config.assets.binding] = assets.binding;\n const workerFetch = runtime.fetch.bind(runtime);\n runtime.fetch = async (req) =>\n assets.route(req) ??\n (hasWorker ? workerFetch(req) : new Response(\"Not found\", { status: 404 }));\n }\n for (const w of config.workflows ?? []) env[w.binding] = workflows!.binding(w.name);\n // Service bindings to this script's own entrypoints (a celld fleet runs one application):\n // default export or a named WorkerEntrypoint, with fetch() and JS RPC.\n for (const s of config.services ?? []) {\n if (s.service !== config.name) continue;\n const target = s.entrypoint ? module[s.entrypoint] : module.default;\n if (!target)\n unsupported.push(`services[${s.binding}].entrypoint \"${s.entrypoint}\" is not exported`);\n else env[s.binding] = entrypointStub(target, env, s.props);\n }\n // R2 objects live directly in the host's store, as celld keeps them in the fleet bucket.\n // With a celld fleet bucket, R2 objects live in it as celld keeps them; else in the FilesApi.\n for (const r2 of config.r2_buckets ?? [])\n env[r2.binding] = host.storage?.objects\n ? r2BucketOn(celldR2Backend(host.storage.objects, r2.bucket_name), r2.binding)\n : r2Bucket(host.files, `/r2/${r2.bucket_name}`, r2.binding);\n for (const d1 of config.d1_databases ?? [])\n env[d1.binding] = celldExec(\n makeD1Binding({\n fetcher: simulatorFetcher(\n env[D1_OBJECTS] as DurableObjectNamespace,\n d1.database_id as string, // set by withResourceIds\n ) as never,\n }) as D1Like,\n );\n for (const name of [...sqliteClasses])\n if (!Object.values(durableObjects).some((d) => d.className === name)) {\n // A migrated class without a binding is fine (reachable through other code paths only).\n }\n return { runtime, unsupported };\n}\n\ninterface D1Like {\n exec(sql: string): Promise<{ count: number; duration: number }>;\n prepare(sql: string): { run(): Promise<unknown> };\n}\n\n/**\n * `D1Database#exec` as celld implements it: statements are split by SQL syntax.\n * workerd's d1-api.ts splits on NEWLINES (Cloudflare's documented behaviour), so a\n * multi-line `CREATE TABLE` fails there but works on celld — and celld is the\n * reference here (verified on celld 0.6.2 by the d1 example in conformance/).\n */\nfunction celldExec<T extends D1Like>(db: T): T {\n const exec = async (sql: string) => {\n const t0 = Date.now();\n const statements = splitSqlStatements(sql).filter((s) => s.trim());\n for (const statement of statements) {\n if (/^\\s*BEGIN\\b/i.test(statement))\n throw new Error(\n \"D1_EXEC_ERROR: the SQL ends in an incomplete statement, which did not run: terminate the last statement with a semicolon\",\n );\n guard(statement);\n await db.prepare(statement).run();\n }\n return { count: statements.length, duration: Date.now() - t0 };\n };\n return celldD1(db, exec) as T;\n}\n\n/**\n * celld's D1 rules on top of workerd's client (celld docs/services/d1.md, checked by the\n * d1-details project): ATTACH/DETACH and TEMP objects are \"not authorized\", VACUUM is\n * \"authorization denied\"; there is one primary and no replica, so sessions return the\n * bookmark \"celld:primary\" and every result reports served_by_primary/served_by_region\n * \"local\"; a read-only statement reports last_row_id and changes as 0.\n */\nfunction guard(sql: string): void {\n if (/^\\s*(ATTACH|DETACH)\\b/i.test(sql) || /^\\s*CREATE\\s+(TEMP|TEMPORARY)\\b/i.test(sql))\n throw new Error(\"D1_ERROR: not authorized\");\n if (/^\\s*VACUUM\\b/i.test(sql)) throw new Error(\"D1_ERROR: authorization denied\");\n}\n\nfunction celldMeta(r: any): any {\n if (!r?.meta) return r;\n r.meta.served_by_primary = true;\n r.meta.served_by_region = \"local\";\n if (r.meta.changed_db === false) {\n r.meta.last_row_id = 0;\n r.meta.changes = 0;\n }\n return r;\n}\n\nfunction celldStatement(stmt: any): any {\n return new Proxy(stmt, {\n get(t, p, r) {\n const v = Reflect.get(t, p, r);\n if (p === \"bind\") return (...a: unknown[]) => celldStatement(v.apply(t, a));\n if (p === \"run\" || p === \"all\")\n return async (...a: unknown[]) => celldMeta(await v.apply(t, a));\n return typeof v === \"function\" ? v.bind(t) : v;\n },\n });\n}\n\nfunction celldD1(db: any, exec?: (sql: string) => Promise<unknown>): any {\n return new Proxy(db, {\n get(t, p, r) {\n if (p === \"exec\" && exec) return exec;\n const v = Reflect.get(t, p, r);\n if (p === \"prepare\")\n return (sql: string) => {\n guard(sql);\n return celldStatement(v.call(t, sql));\n };\n if (p === \"batch\")\n return async (stmts: unknown[], ...a: unknown[]) =>\n ((await v.call(t, stmts, ...a)) as unknown[]).map(celldMeta);\n if (p === \"withSession\")\n return () => {\n const session = celldD1(t);\n return new Proxy(session, {\n get: (s, q, rr) =>\n q === \"getBookmark\" ? () => \"celld:primary\" : Reflect.get(s, q, rr),\n });\n };\n if (p === \"getBookmark\") return () => \"celld:primary\";\n return typeof v === \"function\" ? v.bind(t) : v;\n },\n });\n}\n\n/** Last fired occurrence per cron expression, in a small SQLite database of the host. */\nfunction cronState(db: ReturnType<ProjectHost[\"openSql\"]>) {\n db.exec(\n \"CREATE TABLE IF NOT EXISTS cron_state (expression TEXT PRIMARY KEY, scheduled_time INTEGER)\",\n [],\n );\n return {\n get: (e: string) => {\n const row = db.exec(\"SELECT scheduled_time FROM cron_state WHERE expression = ?\", [e])\n .rows[0];\n return row ? Number(row[0]) : undefined;\n },\n set: (e: string, t: number) =>\n void db.exec(\"INSERT OR REPLACE INTO cron_state (expression, scheduled_time) VALUES (?, ?)\", [\n e,\n t,\n ]),\n };\n}\n\n/**\n * KV namespaces and D1 databases may omit their ids: wrangler provisions them on deploy, and\n * framework builds (Astro's Cloudflare adapter, for one) emit such entries. A KV namespace\n * then takes its binding name as id; a D1 database its `database_name`, else its binding name.\n * Entries with ids are kept as they are, so storage shared with celld keeps its names.\n */\nexport function withResourceIds(config: WranglerConfig): WranglerConfig {\n const kv = config.kv_namespaces;\n const d1 = config.d1_databases;\n if (!kv?.some((n) => !n.id) && !d1?.some((d) => !d.database_id)) return config;\n return {\n ...config,\n kv_namespaces: kv?.map((n) => (n.id ? n : { ...n, id: n.binding })),\n d1_databases: d1?.map((d) =>\n d.database_id ? d : { ...d, database_id: d.database_name ?? d.binding },\n ),\n };\n}\n"]}
|
|
@@ -142,7 +142,7 @@ export class CellRouter {
|
|
|
142
142
|
lost,
|
|
143
143
|
]);
|
|
144
144
|
if (!res.body)
|
|
145
|
-
return done(), res;
|
|
145
|
+
return (done(), res);
|
|
146
146
|
const { readable, writable } = new TransformStream();
|
|
147
147
|
res.body.pipeTo(writable, { signal: ac.signal }).then(done, done);
|
|
148
148
|
return new Response(readable, res);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cell-router.js","sourceRoot":"","sources":["../../src/router/cell-router.ts"],"names":[],"mappings":"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","sourcesContent":["import { idFromName, namespaceKey } from \"../core/id.js\";\nimport { shardOf } from \"../core/shard.js\";\nimport { errorResponse, stripControl } from \"../transport/cells-http.js\";\nimport { H, type Send } from \"../transport/cells-link.js\";\nimport {\n type ControlMessage,\n type ControlPort,\n PortRendezvous,\n shardOfControlId,\n} from \"../ws/control.js\";\n\nexport interface CellRouterOptions {\n shards: number;\n /** Durable Object binding → class name, as in wrangler config. */\n bindings: Record<string, string>;\n /** The Worker script's name: ids derive from it (default \"worker\", as the runtime's). */\n scriptName?: string;\n /** Called when a request needs a shard that has no live link (e.g. ask pages to re-attach). */\n onMissingShard?: (shard: number) => void;\n /** How long a request waits for its shard to be attached (default 10 s). */\n attachTimeoutMs?: number;\n /**\n * Liveness probe of the owner that attached `token`. Polled every\n * `livenessIntervalMs` while the shard has requests in flight; `false`\n * invalidates the link. In a ServiceWorker: is the shard's Web Lock still\n * held by the same holder? (MessagePort has no close event in Chromium.)\n */\n isAlive?: (shard: number, token: unknown) => Promise<boolean>;\n livenessIntervalMs?: number;\n /**\n * Event-driven liveness (preferred over polling): resolves when the owner that\n * attached `token` is gone. Browser: a pending request on the owner's own Web\n * Lock, granted the moment its worker/tab dies. Node: worker \"exit\".\n */\n watchOwner?: (shard: number, token: unknown) => Promise<unknown>;\n}\n\n/** Thrown into in-flight requests of a shard whose owner is gone (CF: \"Durable Object reset\"). */\nexport class ShardOwnerLostError extends Error {\n constructor(shard: number) {\n super(`Owner of cell shard ${shard} was lost; the request may or may not have been applied`);\n this.name = \"ShardOwnerLostError\";\n }\n}\n\ninterface Link {\n send: Send;\n token: unknown;\n inflight: Set<AbortController>;\n ctl?: ControlPort;\n /** Being handed over: no new requests (they wait for the next owner), the current ones finish. */\n draining?: boolean;\n}\n\n/**\n * The single \"server\" of an origin (ServiceWorker, page or Node main thread):\n * knows which shard owns which cell and holds one HTTP link per shard worker.\n *\n * - `ingress(req)`: public requests → any live shard's Worker `fetch`. Control\n * headers are stripped first, so clients cannot address objects directly.\n * - `internal(req)`: requests from shard workers (DO → DO across shards) →\n * forwarded to the owning shard, control headers intact.\n */\nexport class CellRouter {\n readonly #opts: CellRouterOptions;\n readonly #links = new Map<number, Link>();\n #watchdog: ReturnType<typeof setInterval> | undefined;\n readonly #waiters = new Map<number, (() => void)[]>();\n #rr = 0;\n #wsSeq = 0;\n readonly #wsShard = new Map<string, number>();\n readonly #ports = new PortRendezvous();\n\n constructor(opts: CellRouterOptions) {\n this.#opts = opts;\n }\n\n get attachedShards(): number[] {\n return [...this.#links]\n .filter(([, l]) => !l.draining)\n .map(([shard]) => shard)\n .sort((a, b) => a - b);\n }\n\n /**\n * Attaches the link of a shard. Replacing a link means the previous owner is\n * gone (Web Locks / leases guarantee a single live owner): its in-flight\n * requests fail at once instead of hanging on a dead port.\n */\n attach(shard: number, send: Send, token?: unknown, ctl?: ControlPort): void {\n const prev = this.#links.get(shard);\n this.#links.set(shard, { send, token, inflight: new Set(), ctl });\n if (ctl) {\n ctl.onmessage = (e) => this.#onControl(e.data as ControlMessage);\n ctl.start?.();\n }\n if (prev) this.#fail(shard, prev);\n if (token !== undefined && this.#opts.watchOwner)\n this.#opts.watchOwner(shard, token).then(\n () => this.#links.get(shard)?.token === token && this.detach(shard),\n () => {},\n );\n for (const wake of this.#waiters.get(shard) ?? []) wake();\n this.#waiters.delete(shard);\n }\n\n detach(shard: number, send?: Send): void {\n const link = this.#links.get(shard);\n if (!link || (send && link.send !== send)) return;\n this.#links.delete(shard);\n this.#fail(shard, link);\n }\n\n /**\n * A planned hand-over of `shard`: new requests wait for the next owner to attach, the ones in\n * flight get up to `timeoutMs` to finish, then the link goes (the rest fail as when an owner is\n * lost). Only the link attached with `token` is drained.\n */\n async drain(shard: number, token: unknown, timeoutMs: number): Promise<void> {\n const link = this.#links.get(shard);\n if (!link || link.token !== token) return;\n link.draining = true;\n const end = Date.now() + timeoutMs;\n while (link.inflight.size && Date.now() < end && this.#links.get(shard) === link)\n await new Promise((r) => setTimeout(r, 20));\n this.detach(shard, link.send);\n }\n\n /** Number of requests currently forwarded to a shard (diagnostics/tests). */\n inflight(shard: number): number {\n return this.#links.get(shard)?.inflight.size ?? 0;\n }\n\n /**\n * WebSocket ingress (a ServiceWorker cannot intercept WebSockets): asks a live\n * shard, over its control channel, to run the Worker's fetch with an Upgrade\n * request; resolves with the client end's port (transfer it to the page).\n */\n async connectWebSocket(url: string, protocols: string[] = [], headers?: [string, string][]) {\n const shard = this.#pick();\n const link = await this.#linkFor(shard);\n if (!link.ctl) throw new Error(`shard ${shard} has no control channel: WebSockets unavailable`);\n const id = `r:${++this.#wsSeq}`;\n this.#wsShard.set(id, shard);\n link.ctl.postMessage({ t: \"ws-connect\", id, url, protocols, headers } satisfies ControlMessage);\n try {\n return await this.#ports.wait(id);\n } finally {\n this.#wsShard.delete(id);\n }\n }\n\n #onControl(m: ControlMessage): void {\n if (m.t !== \"ws-accept\" && m.t !== \"ws-refuse\") return;\n const target = shardOfControlId(m.id);\n if (target !== undefined) {\n // Cross-shard hand-over: the Worker that asked lives in shard `target`.\n const ctl = this.#links.get(target)?.ctl;\n if (!ctl) {\n if (m.t === \"ws-accept\") m.port.close();\n return;\n }\n ctl.postMessage(m, m.t === \"ws-accept\" ? [m.port as unknown as Transferable] : []);\n return;\n }\n this.#ports.deliver(\n m.id,\n m.t === \"ws-accept\" ? { port: m.port, protocol: m.protocol } : new Error(m.message),\n );\n }\n\n #fail(shard: number, link: Link): void {\n this.#ports.failAll((id) => this.#wsShard.get(id) === shard, new ShardOwnerLostError(shard));\n for (const ac of link.inflight) ac.abort(new ShardOwnerLostError(shard));\n link.inflight.clear();\n }\n\n /** Forwards with an abort handle; the handle lives until the response body ends. */\n async #forward(shard: number, req: Request): Promise<Response> {\n const link = await this.#linkFor(shard);\n const ac = new AbortController();\n link.inflight.add(ac);\n this.#ensureWatchdog();\n const done = () => link.inflight.delete(ac);\n const lost = new Promise<never>((_, reject) =>\n ac.signal.addEventListener(\"abort\", () => reject(ac.signal.reason), { once: true }),\n );\n lost.catch(() => {});\n try {\n const signal = AbortSignal.any([req.signal, ac.signal]);\n const res = await Promise.race([\n link.send(new Request(req, { signal, duplex: \"half\" } as RequestInit)),\n lost,\n ]);\n if (!res.body) return done(), res;\n const { readable, writable } = new TransformStream();\n res.body.pipeTo(writable, { signal: ac.signal }).then(done, done);\n return new Response(readable, res);\n } catch (e) {\n done();\n throw ac.signal.aborted ? ac.signal.reason : e;\n }\n }\n\n #ensureWatchdog(): void {\n if (this.#watchdog || !this.#opts.isAlive) return;\n this.#watchdog = setInterval(async () => {\n const busy = [...this.#links].filter(([, l]) => l.inflight.size > 0);\n if (!busy.length) {\n clearInterval(this.#watchdog);\n this.#watchdog = undefined;\n return;\n }\n for (const [shard, link] of busy) {\n const alive = await this.#opts.isAlive!(shard, link.token).catch(() => true);\n if (!alive && this.#links.get(shard) === link) this.detach(shard);\n }\n }, this.#opts.livenessIntervalMs ?? 1000);\n }\n\n /**\n * The shard for ingress: the live one with the fewest requests in flight (a long request\n * keeps its shard busy, wherever its Durable Objects run), round robin among equals.\n */\n #pick(): number {\n const live = this.attachedShards;\n if (!live.length) return 0;\n const start = this.#rr++ % live.length;\n let best = live[start];\n for (let i = 1; i < live.length; i++) {\n const s = live[(start + i) % live.length];\n if (this.inflight(s) < this.inflight(best)) best = s;\n }\n return best;\n }\n\n ingress = async (req: Request): Promise<Response> => {\n const shard = this.#pick();\n try {\n // The page's cookies (x-cellb-cookie, set by the ServiceWorker) go on to the shard.\n return await this.#forward(shard, stripControl(req, [H.cookie]));\n } catch (e) {\n return new Response(`Cell shard ${shard} unavailable: ${(e as Error).message}`, {\n status: 503,\n });\n }\n };\n\n internal = async (req: Request): Promise<Response> => {\n const kind = req.headers.get(H.kind);\n try {\n if (kind === \"describe\") return Response.json({ bindings: this.#opts.bindings });\n if (kind !== \"fetch\" && kind !== \"rpc\") return await this.ingress(req);\n return await this.#forward(this.shardOfRequest(req), req);\n } catch (e) {\n return errorResponse(e, 503);\n }\n };\n\n shardOfRequest(req: Request): number {\n const explicit = req.headers.get(H.shard);\n if (explicit !== null) {\n const shard = Number(explicit);\n if (Number.isInteger(shard) && shard >= 0 && shard < this.#opts.shards) return shard;\n throw new Error(`Invalid cell shard \"${explicit}\"`);\n }\n const binding = req.headers.get(H.binding) ?? \"\";\n const target = req.headers.get(H.target) ?? \"\";\n const className = this.#opts.bindings[binding];\n if (!className) throw new Error(`Unknown Durable Object binding \"${binding}\"`);\n const hex = target.startsWith(\"name:\")\n ? idFromName(\n namespaceKey(this.#opts.scriptName ?? \"worker\", className),\n target.slice(5),\n ).toString()\n : target.slice(3);\n return shardOf(hex, this.#opts.shards);\n }\n\n async #linkFor(shard: number): Promise<Link> {\n const link = this.#links.get(shard);\n if (link && !link.draining) return link;\n this.#opts.onMissingShard?.(shard);\n const timeout = this.#opts.attachTimeoutMs ?? 10_000;\n await new Promise<void>((resolve, reject) => {\n const t = setTimeout(\n () => reject(new Error(`shard ${shard} not attached within ${timeout} ms`)),\n timeout,\n );\n const list = this.#waiters.get(shard) ?? [];\n list.push(() => (clearTimeout(t), resolve()));\n this.#waiters.set(shard, list);\n });\n return this.#links.get(shard)!;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"cell-router.js","sourceRoot":"","sources":["../../src/router/cell-router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,EAAE,CAAC,EAAa,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAGL,cAAc,EACd,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AA4B1B,kGAAkG;AAClG,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,KAAa;QACvB,KAAK,CAAC,uBAAuB,KAAK,yDAAyD,CAAC,CAAC;QAC7F,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAWD;;;;;;;;GAQG;AACH,MAAM,OAAO,UAAU;IACZ,KAAK,CAAoB;IACzB,MAAM,GAAG,IAAI,GAAG,EAAgB,CAAC;IAC1C,SAAS,CAA6C;IAC7C,QAAQ,GAAG,IAAI,GAAG,EAA0B,CAAC;IACtD,GAAG,GAAG,CAAC,CAAC;IACR,MAAM,GAAG,CAAC,CAAC;IACF,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IACrC,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;IAEvC,YAAY,IAAuB;QACjC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACpB,CAAC;IAED,IAAI,cAAc;QAChB,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;aACpB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;aAC9B,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC;aACvB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,KAAa,EAAE,IAAU,EAAE,KAAe,EAAE,GAAiB;QAClE,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,GAAG,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;QAClE,IAAI,GAAG,EAAE,CAAC;YACR,GAAG,CAAC,SAAS,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAsB,CAAC,CAAC;YACjE,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC;QAChB,CAAC;QACD,IAAI,IAAI;YAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAClC,IAAI,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU;YAC9C,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,IAAI,CACtC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EACnE,GAAG,EAAE,GAAE,CAAC,CACT,CAAC;QACJ,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE;YAAE,IAAI,EAAE,CAAC;QAC1D,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED,MAAM,CAAC,KAAa,EAAE,IAAW;QAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC;YAAE,OAAO;QAClD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,KAAK,CAAC,KAAa,EAAE,KAAc,EAAE,SAAiB;QAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK;YAAE,OAAO;QAC1C,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QACnC,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI;YAC9E,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAED,6EAA6E;IAC7E,QAAQ,CAAC,KAAa;QACpB,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,CAAC;IACpD,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,gBAAgB,CAAC,GAAW,EAAE,SAAS,GAAa,EAAE,EAAE,OAA4B;QACxF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,SAAS,KAAK,iDAAiD,CAAC,CAAC;QAChG,MAAM,EAAE,GAAG,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;QAChC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAC7B,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAA2B,CAAC,CAAC;QAChG,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpC,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,UAAU,CAAC,CAAiB;QAC1B,IAAI,CAAC,CAAC,CAAC,KAAK,WAAW,IAAI,CAAC,CAAC,CAAC,KAAK,WAAW;YAAE,OAAO;QACvD,MAAM,MAAM,GAAG,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,wEAAwE;YACxE,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC;YACzC,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,IAAI,CAAC,CAAC,CAAC,KAAK,WAAW;oBAAE,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACxC,OAAO;YACT,CAAC;YACD,GAAG,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAA+B,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACnF,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,OAAO,CACjB,CAAC,CAAC,EAAE,EACJ,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CACpF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,KAAa,EAAE,IAAU;QAC7B,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,KAAK,EAAE,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7F,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,QAAQ;YAAE,EAAE,CAAC,KAAK,CAAC,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC;QACzE,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;IAED,oFAAoF;IACpF,KAAK,CAAC,QAAQ,CAAC,KAAa,EAAE,GAAY;QACxC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,CAAC;QACjC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtB,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC5C,MAAM,IAAI,GAAG,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAC5C,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CACpF,CAAC;QACF,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;YACxD,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;gBAC7B,IAAI,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAiB,CAAC,CAAC;gBACtE,IAAI;aACL,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,IAAI;gBAAE,OAAO,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;YACpC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,IAAI,eAAe,EAAE,CAAC;YACrD,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAClE,OAAO,IAAI,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,EAAE,CAAC;YACP,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAED,eAAe;QACb,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO;YAAE,OAAO;QAClD,IAAI,CAAC,SAAS,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;YACtC,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;YACrE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACjB,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBAC9B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;gBAC3B,OAAO;YACT,CAAC;YACD,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;gBACjC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;gBAC7E,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI;oBAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACpE,CAAC;QACH,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,kBAAkB,IAAI,IAAI,CAAC,CAAC;IAC5C,CAAC;IAED;;;OAGG;IACH,KAAK;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,CAAC;QACjC,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,CAAC,CAAC;QAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;QACvC,IAAI,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1C,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,IAAI,GAAG,CAAC,CAAC;QACvD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,GAAG,KAAK,EAAE,GAAY,EAAqB,EAAE;QAClD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,oFAAoF;YACpF,OAAO,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACnE,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,IAAI,QAAQ,CAAC,cAAc,KAAK,iBAAkB,CAAW,CAAC,OAAO,EAAE,EAAE;gBAC9E,MAAM,EAAE,GAAG;aACZ,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;IAEF,QAAQ,GAAG,KAAK,EAAE,GAAY,EAAqB,EAAE;QACnD,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC;YACH,IAAI,IAAI,KAAK,UAAU;gBAAE,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;YACjF,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,KAAK;gBAAE,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACvE,OAAO,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;QAC5D,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,aAAa,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC,CAAC;IAEF,cAAc,CAAC,GAAY;QACzB,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YACtB,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC/B,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM;gBAAE,OAAO,KAAK,CAAC;YACrF,MAAM,IAAI,KAAK,CAAC,uBAAuB,QAAQ,GAAG,CAAC,CAAC;QACtD,CAAC;QACD,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACjD,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAC/C,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC/C,IAAI,CAAC,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,OAAO,GAAG,CAAC,CAAC;QAC/E,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC;YACpC,CAAC,CAAC,UAAU,CACR,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,QAAQ,EAAE,SAAS,CAAC,EAC1D,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAChB,CAAC,QAAQ,EAAE;YACd,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACpB,OAAO,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAa;QAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC;QACxC,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,IAAI,MAAM,CAAC;QACrD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC1C,MAAM,CAAC,GAAG,UAAU,CAClB,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,KAAK,wBAAwB,OAAO,KAAK,CAAC,CAAC,EAC3E,OAAO,CACR,CAAC;YACF,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YAC5C,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;YAC9C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC;IACjC,CAAC;CACF","sourcesContent":["import { idFromName, namespaceKey } from \"../core/id.js\";\nimport { shardOf } from \"../core/shard.js\";\nimport { errorResponse, stripControl } from \"../transport/cells-http.js\";\nimport { H, type Send } from \"../transport/cells-link.js\";\nimport {\n type ControlMessage,\n type ControlPort,\n PortRendezvous,\n shardOfControlId,\n} from \"../ws/control.js\";\n\nexport interface CellRouterOptions {\n shards: number;\n /** Durable Object binding → class name, as in wrangler config. */\n bindings: Record<string, string>;\n /** The Worker script's name: ids derive from it (default \"worker\", as the runtime's). */\n scriptName?: string;\n /** Called when a request needs a shard that has no live link (e.g. ask pages to re-attach). */\n onMissingShard?: (shard: number) => void;\n /** How long a request waits for its shard to be attached (default 10 s). */\n attachTimeoutMs?: number;\n /**\n * Liveness probe of the owner that attached `token`. Polled every\n * `livenessIntervalMs` while the shard has requests in flight; `false`\n * invalidates the link. In a ServiceWorker: is the shard's Web Lock still\n * held by the same holder? (MessagePort has no close event in Chromium.)\n */\n isAlive?: (shard: number, token: unknown) => Promise<boolean>;\n livenessIntervalMs?: number;\n /**\n * Event-driven liveness (preferred over polling): resolves when the owner that\n * attached `token` is gone. Browser: a pending request on the owner's own Web\n * Lock, granted the moment its worker/tab dies. Node: worker \"exit\".\n */\n watchOwner?: (shard: number, token: unknown) => Promise<unknown>;\n}\n\n/** Thrown into in-flight requests of a shard whose owner is gone (CF: \"Durable Object reset\"). */\nexport class ShardOwnerLostError extends Error {\n constructor(shard: number) {\n super(`Owner of cell shard ${shard} was lost; the request may or may not have been applied`);\n this.name = \"ShardOwnerLostError\";\n }\n}\n\ninterface Link {\n send: Send;\n token: unknown;\n inflight: Set<AbortController>;\n ctl?: ControlPort;\n /** Being handed over: no new requests (they wait for the next owner), the current ones finish. */\n draining?: boolean;\n}\n\n/**\n * The single \"server\" of an origin (ServiceWorker, page or Node main thread):\n * knows which shard owns which cell and holds one HTTP link per shard worker.\n *\n * - `ingress(req)`: public requests → any live shard's Worker `fetch`. Control\n * headers are stripped first, so clients cannot address objects directly.\n * - `internal(req)`: requests from shard workers (DO → DO across shards) →\n * forwarded to the owning shard, control headers intact.\n */\nexport class CellRouter {\n readonly #opts: CellRouterOptions;\n readonly #links = new Map<number, Link>();\n #watchdog: ReturnType<typeof setInterval> | undefined;\n readonly #waiters = new Map<number, (() => void)[]>();\n #rr = 0;\n #wsSeq = 0;\n readonly #wsShard = new Map<string, number>();\n readonly #ports = new PortRendezvous();\n\n constructor(opts: CellRouterOptions) {\n this.#opts = opts;\n }\n\n get attachedShards(): number[] {\n return [...this.#links]\n .filter(([, l]) => !l.draining)\n .map(([shard]) => shard)\n .sort((a, b) => a - b);\n }\n\n /**\n * Attaches the link of a shard. Replacing a link means the previous owner is\n * gone (Web Locks / leases guarantee a single live owner): its in-flight\n * requests fail at once instead of hanging on a dead port.\n */\n attach(shard: number, send: Send, token?: unknown, ctl?: ControlPort): void {\n const prev = this.#links.get(shard);\n this.#links.set(shard, { send, token, inflight: new Set(), ctl });\n if (ctl) {\n ctl.onmessage = (e) => this.#onControl(e.data as ControlMessage);\n ctl.start?.();\n }\n if (prev) this.#fail(shard, prev);\n if (token !== undefined && this.#opts.watchOwner)\n this.#opts.watchOwner(shard, token).then(\n () => this.#links.get(shard)?.token === token && this.detach(shard),\n () => {},\n );\n for (const wake of this.#waiters.get(shard) ?? []) wake();\n this.#waiters.delete(shard);\n }\n\n detach(shard: number, send?: Send): void {\n const link = this.#links.get(shard);\n if (!link || (send && link.send !== send)) return;\n this.#links.delete(shard);\n this.#fail(shard, link);\n }\n\n /**\n * A planned hand-over of `shard`: new requests wait for the next owner to attach, the ones in\n * flight get up to `timeoutMs` to finish, then the link goes (the rest fail as when an owner is\n * lost). Only the link attached with `token` is drained.\n */\n async drain(shard: number, token: unknown, timeoutMs: number): Promise<void> {\n const link = this.#links.get(shard);\n if (!link || link.token !== token) return;\n link.draining = true;\n const end = Date.now() + timeoutMs;\n while (link.inflight.size && Date.now() < end && this.#links.get(shard) === link)\n await new Promise((r) => setTimeout(r, 20));\n this.detach(shard, link.send);\n }\n\n /** Number of requests currently forwarded to a shard (diagnostics/tests). */\n inflight(shard: number): number {\n return this.#links.get(shard)?.inflight.size ?? 0;\n }\n\n /**\n * WebSocket ingress (a ServiceWorker cannot intercept WebSockets): asks a live\n * shard, over its control channel, to run the Worker's fetch with an Upgrade\n * request; resolves with the client end's port (transfer it to the page).\n */\n async connectWebSocket(url: string, protocols: string[] = [], headers?: [string, string][]) {\n const shard = this.#pick();\n const link = await this.#linkFor(shard);\n if (!link.ctl) throw new Error(`shard ${shard} has no control channel: WebSockets unavailable`);\n const id = `r:${++this.#wsSeq}`;\n this.#wsShard.set(id, shard);\n link.ctl.postMessage({ t: \"ws-connect\", id, url, protocols, headers } satisfies ControlMessage);\n try {\n return await this.#ports.wait(id);\n } finally {\n this.#wsShard.delete(id);\n }\n }\n\n #onControl(m: ControlMessage): void {\n if (m.t !== \"ws-accept\" && m.t !== \"ws-refuse\") return;\n const target = shardOfControlId(m.id);\n if (target !== undefined) {\n // Cross-shard hand-over: the Worker that asked lives in shard `target`.\n const ctl = this.#links.get(target)?.ctl;\n if (!ctl) {\n if (m.t === \"ws-accept\") m.port.close();\n return;\n }\n ctl.postMessage(m, m.t === \"ws-accept\" ? [m.port as unknown as Transferable] : []);\n return;\n }\n this.#ports.deliver(\n m.id,\n m.t === \"ws-accept\" ? { port: m.port, protocol: m.protocol } : new Error(m.message),\n );\n }\n\n #fail(shard: number, link: Link): void {\n this.#ports.failAll((id) => this.#wsShard.get(id) === shard, new ShardOwnerLostError(shard));\n for (const ac of link.inflight) ac.abort(new ShardOwnerLostError(shard));\n link.inflight.clear();\n }\n\n /** Forwards with an abort handle; the handle lives until the response body ends. */\n async #forward(shard: number, req: Request): Promise<Response> {\n const link = await this.#linkFor(shard);\n const ac = new AbortController();\n link.inflight.add(ac);\n this.#ensureWatchdog();\n const done = () => link.inflight.delete(ac);\n const lost = new Promise<never>((_, reject) =>\n ac.signal.addEventListener(\"abort\", () => reject(ac.signal.reason), { once: true }),\n );\n lost.catch(() => {});\n try {\n const signal = AbortSignal.any([req.signal, ac.signal]);\n const res = await Promise.race([\n link.send(new Request(req, { signal, duplex: \"half\" } as RequestInit)),\n lost,\n ]);\n if (!res.body) return (done(), res);\n const { readable, writable } = new TransformStream();\n res.body.pipeTo(writable, { signal: ac.signal }).then(done, done);\n return new Response(readable, res);\n } catch (e) {\n done();\n throw ac.signal.aborted ? ac.signal.reason : e;\n }\n }\n\n #ensureWatchdog(): void {\n if (this.#watchdog || !this.#opts.isAlive) return;\n this.#watchdog = setInterval(async () => {\n const busy = [...this.#links].filter(([, l]) => l.inflight.size > 0);\n if (!busy.length) {\n clearInterval(this.#watchdog);\n this.#watchdog = undefined;\n return;\n }\n for (const [shard, link] of busy) {\n const alive = await this.#opts.isAlive!(shard, link.token).catch(() => true);\n if (!alive && this.#links.get(shard) === link) this.detach(shard);\n }\n }, this.#opts.livenessIntervalMs ?? 1000);\n }\n\n /**\n * The shard for ingress: the live one with the fewest requests in flight (a long request\n * keeps its shard busy, wherever its Durable Objects run), round robin among equals.\n */\n #pick(): number {\n const live = this.attachedShards;\n if (!live.length) return 0;\n const start = this.#rr++ % live.length;\n let best = live[start];\n for (let i = 1; i < live.length; i++) {\n const s = live[(start + i) % live.length];\n if (this.inflight(s) < this.inflight(best)) best = s;\n }\n return best;\n }\n\n ingress = async (req: Request): Promise<Response> => {\n const shard = this.#pick();\n try {\n // The page's cookies (x-cellb-cookie, set by the ServiceWorker) go on to the shard.\n return await this.#forward(shard, stripControl(req, [H.cookie]));\n } catch (e) {\n return new Response(`Cell shard ${shard} unavailable: ${(e as Error).message}`, {\n status: 503,\n });\n }\n };\n\n internal = async (req: Request): Promise<Response> => {\n const kind = req.headers.get(H.kind);\n try {\n if (kind === \"describe\") return Response.json({ bindings: this.#opts.bindings });\n if (kind !== \"fetch\" && kind !== \"rpc\") return await this.ingress(req);\n return await this.#forward(this.shardOfRequest(req), req);\n } catch (e) {\n return errorResponse(e, 503);\n }\n };\n\n shardOfRequest(req: Request): number {\n const explicit = req.headers.get(H.shard);\n if (explicit !== null) {\n const shard = Number(explicit);\n if (Number.isInteger(shard) && shard >= 0 && shard < this.#opts.shards) return shard;\n throw new Error(`Invalid cell shard \"${explicit}\"`);\n }\n const binding = req.headers.get(H.binding) ?? \"\";\n const target = req.headers.get(H.target) ?? \"\";\n const className = this.#opts.bindings[binding];\n if (!className) throw new Error(`Unknown Durable Object binding \"${binding}\"`);\n const hex = target.startsWith(\"name:\")\n ? idFromName(\n namespaceKey(this.#opts.scriptName ?? \"worker\", className),\n target.slice(5),\n ).toString()\n : target.slice(3);\n return shardOf(hex, this.#opts.shards);\n }\n\n async #linkFor(shard: number): Promise<Link> {\n const link = this.#links.get(shard);\n if (link && !link.draining) return link;\n this.#opts.onMissingShard?.(shard);\n const timeout = this.#opts.attachTimeoutMs ?? 10_000;\n await new Promise<void>((resolve, reject) => {\n const t = setTimeout(\n () => reject(new Error(`shard ${shard} not attached within ${timeout} ms`)),\n timeout,\n );\n const list = this.#waiters.get(shard) ?? [];\n list.push(() => (clearTimeout(t), resolve()));\n this.#waiters.set(shard, list);\n });\n return this.#links.get(shard)!;\n }\n}\n"]}
|
package/dist/site.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createProjectSite } from "./project/site.js";
|
package/dist/site.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// @statewalker/cellb/site: a project's sources compiled and served in the browser (an in-browser
|
|
2
|
+
// HTTP server for `browserProjectRuntime({ site })`). It needs the optional peer dependencies
|
|
3
|
+
// @statewalker/webrun-modules and @statewalker/webrun-site-builder; the embedder hosts the site in
|
|
4
|
+
// a ServiceWorker with @statewalker/webrun-site-host, the third optional peer.
|
|
5
|
+
export { createProjectSite } from "./project/site.js";
|
|
6
|
+
//# sourceMappingURL=site.js.map
|
package/dist/site.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"site.js","sourceRoot":"","sources":["../src/site.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,8FAA8F;AAC9F,mGAAmG;AACnG,+EAA+E;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC","sourcesContent":["// @statewalker/cellb/site: a project's sources compiled and served in the browser (an in-browser\n// HTTP server for `browserProjectRuntime({ site })`). It needs the optional peer dependencies\n// @statewalker/webrun-modules and @statewalker/webrun-site-builder; the embedder hosts the site in\n// a ServiceWorker with @statewalker/webrun-site-host, the third optional peer.\nexport { createProjectSite } from \"./project/site.js\";\n"]}
|
package/dist/ws/frames.d.ts
CHANGED
|
@@ -36,3 +36,17 @@ export declare class CellsCloseEvent extends Event {
|
|
|
36
36
|
wasClean?: boolean;
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
|
+
/** One side of a frame relay: a MessagePort, or a port of a multiplexer. */
|
|
40
|
+
export interface FrameEnd {
|
|
41
|
+
post(f: Frame): void;
|
|
42
|
+
listen(fn: (f: Frame) => void): void;
|
|
43
|
+
close(): void;
|
|
44
|
+
}
|
|
45
|
+
export declare const portEnd: (port: MessagePort) => FrameEnd;
|
|
46
|
+
/**
|
|
47
|
+
* Relays a socket's frames between `a` and `b`. Once a close frame has passed each way (the
|
|
48
|
+
* closing handshake) both ends are closed, after a moment for the last frames to arrive.
|
|
49
|
+
* Returns a function that ends the relay at once, telling `a` the socket closed with `code`;
|
|
50
|
+
* `onDone` runs when the relay ends either way.
|
|
51
|
+
*/
|
|
52
|
+
export declare function relayFrames(a: FrameEnd, b: FrameEnd, onDone?: () => void): (code: number, reason: string) => void;
|
package/dist/ws/frames.js
CHANGED
|
@@ -36,4 +36,55 @@ export class CellsCloseEvent extends Event {
|
|
|
36
36
|
this.wasClean = init.wasClean ?? false;
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
+
export const portEnd = (port) => ({
|
|
40
|
+
post: (f) => port.postMessage(f),
|
|
41
|
+
listen: (fn) => {
|
|
42
|
+
port.onmessage = (e) => fn(e.data);
|
|
43
|
+
},
|
|
44
|
+
close: () => port.close(),
|
|
45
|
+
});
|
|
46
|
+
/**
|
|
47
|
+
* Relays a socket's frames between `a` and `b`. Once a close frame has passed each way (the
|
|
48
|
+
* closing handshake) both ends are closed, after a moment for the last frames to arrive.
|
|
49
|
+
* Returns a function that ends the relay at once, telling `a` the socket closed with `code`;
|
|
50
|
+
* `onDone` runs when the relay ends either way.
|
|
51
|
+
*/
|
|
52
|
+
export function relayFrames(a, b, onDone) {
|
|
53
|
+
let fromA = false;
|
|
54
|
+
let fromB = false;
|
|
55
|
+
let done = false;
|
|
56
|
+
const finish = () => {
|
|
57
|
+
if (done)
|
|
58
|
+
return;
|
|
59
|
+
done = true;
|
|
60
|
+
onDone?.();
|
|
61
|
+
const t = setTimeout(() => {
|
|
62
|
+
a.close();
|
|
63
|
+
b.close();
|
|
64
|
+
}, 1_000);
|
|
65
|
+
t.unref?.();
|
|
66
|
+
};
|
|
67
|
+
a.listen((f) => {
|
|
68
|
+
b.post(f);
|
|
69
|
+
if (f.t !== "c")
|
|
70
|
+
return;
|
|
71
|
+
fromA = true;
|
|
72
|
+
if (fromB)
|
|
73
|
+
finish();
|
|
74
|
+
});
|
|
75
|
+
b.listen((f) => {
|
|
76
|
+
a.post(f);
|
|
77
|
+
if (f.t !== "c")
|
|
78
|
+
return;
|
|
79
|
+
fromB = true;
|
|
80
|
+
if (fromA)
|
|
81
|
+
finish();
|
|
82
|
+
});
|
|
83
|
+
return (code, reason) => {
|
|
84
|
+
if (done)
|
|
85
|
+
return;
|
|
86
|
+
a.post({ t: "c", code, reason });
|
|
87
|
+
finish();
|
|
88
|
+
};
|
|
89
|
+
}
|
|
39
90
|
//# sourceMappingURL=frames.js.map
|
package/dist/ws/frames.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frames.js","sourceRoot":"","sources":["../../src/ws/frames.ts"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAE3C,8FAA8F;AAC9F,MAAM,UAAU,QAAQ,CAAC,CAAuB;IAC9C,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;AACvF,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAa;IACvC,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC1C,IAAI,IAAI,YAAY,WAAW;QAAE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACtD,IAAI,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC;QAC1B,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAgB,CAAC;IAC9F,MAAM,IAAI,SAAS,CACjB,gFAAgF,CACjF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAa,EAAE,MAAe;IACvD,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,CAAC;QACrE,MAAM,IAAI,YAAY,CACpB,iEAAiE,IAAI,cAAc,EACnF,oBAAoB,CACrB,CAAC;IACJ,IAAI,MAAM,KAAK,SAAS,IAAI,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,UAAU,GAAG,GAAG;QAC3E,MAAM,IAAI,YAAY,CACpB,4DAA4D,EAC5D,aAAa,CACd,CAAC;AACN,CAAC;AAED,0FAA0F;AAC1F,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAC/B,IAAI,CAAS;IACb,MAAM,CAAS;IACf,QAAQ,CAAU;IAC3B,YAAY,IAAY,EAAE,IAAI,GAA2D,EAAE;QACzF,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;QAC9B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;QAChC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC;IACzC,CAAC;CACF","sourcesContent":["/** Wire protocol of a WebSocket carried by a MessagePort (both directions). */\nexport type Frame =\n | { t: \"m\"; d: string | ArrayBuffer } // message\n | { t: \"c\"; code: number; reason: string } // close (initiating or echo)\n | { t: \"p\"; hb: number } // ping (client → server), carries the heartbeat period\n | { t: \"q\" } // pong (server → client)\n | { t: \"a\" }; // ack: the server end dispatched the oldest message not acknowledged yet\n\n/**\n * MessagePorts never report that the other side died (no `close` event in\n * browsers), so both ends run a heartbeat: the client pings every `hb` ms and\n * closes with 1006 when pongs stop for 2·hb; the server closes with 1006 when\n * pings stop for 3·hb. This is what makes a socket notice a closed tab.\n */\nexport const DEFAULT_HEARTBEAT_MS = 10_000;\n\n/** What a message adds to the sender's `bufferedAmount` (WHATWG: UTF-8 bytes of a string). */\nexport function byteSize(d: string | ArrayBuffer): number {\n return typeof d === \"string\" ? new TextEncoder().encode(d).byteLength : d.byteLength;\n}\n\nexport function toFrameData(data: unknown): string | ArrayBuffer {\n if (typeof data === \"string\") return data;\n if (data instanceof ArrayBuffer) return data.slice(0);\n if (ArrayBuffer.isView(data))\n return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength) as ArrayBuffer;\n throw new TypeError(\n \"WebSocket.send: unsupported data type (string, ArrayBuffer or ArrayBufferView)\",\n );\n}\n\nexport function checkClose(code?: number, reason?: string): void {\n if (code !== undefined && code !== 1000 && (code < 3000 || code > 4999))\n throw new DOMException(\n `The close code must be either 1000, or between 3000 and 4999. ${code} is neither.`,\n \"InvalidAccessError\",\n );\n if (reason !== undefined && new TextEncoder().encode(reason).byteLength > 123)\n throw new DOMException(\n \"The close reason must not be greater than 123 UTF-8 bytes.\",\n \"SyntaxError\",\n );\n}\n\n/** CloseEvent is not a global in every runtime (Node 22): a compatible Event subclass. */\nexport class CellsCloseEvent extends Event {\n readonly code: number;\n readonly reason: string;\n readonly wasClean: boolean;\n constructor(type: string, init: { code?: number; reason?: string; wasClean?: boolean } = {}) {\n super(type);\n this.code = init.code ?? 1005;\n this.reason = init.reason ?? \"\";\n this.wasClean = init.wasClean ?? false;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"frames.js","sourceRoot":"","sources":["../../src/ws/frames.ts"],"names":[],"mappings":"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","sourcesContent":["/** Wire protocol of a WebSocket carried by a MessagePort (both directions). */\nexport type Frame =\n | { t: \"m\"; d: string | ArrayBuffer } // message\n | { t: \"c\"; code: number; reason: string } // close (initiating or echo)\n | { t: \"p\"; hb: number } // ping (client → server), carries the heartbeat period\n | { t: \"q\" } // pong (server → client)\n | { t: \"a\" }; // ack: the server end dispatched the oldest message not acknowledged yet\n\n/**\n * MessagePorts never report that the other side died (no `close` event in\n * browsers), so both ends run a heartbeat: the client pings every `hb` ms and\n * closes with 1006 when pongs stop for 2·hb; the server closes with 1006 when\n * pings stop for 3·hb. This is what makes a socket notice a closed tab.\n */\nexport const DEFAULT_HEARTBEAT_MS = 10_000;\n\n/** What a message adds to the sender's `bufferedAmount` (WHATWG: UTF-8 bytes of a string). */\nexport function byteSize(d: string | ArrayBuffer): number {\n return typeof d === \"string\" ? new TextEncoder().encode(d).byteLength : d.byteLength;\n}\n\nexport function toFrameData(data: unknown): string | ArrayBuffer {\n if (typeof data === \"string\") return data;\n if (data instanceof ArrayBuffer) return data.slice(0);\n if (ArrayBuffer.isView(data))\n return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength) as ArrayBuffer;\n throw new TypeError(\n \"WebSocket.send: unsupported data type (string, ArrayBuffer or ArrayBufferView)\",\n );\n}\n\nexport function checkClose(code?: number, reason?: string): void {\n if (code !== undefined && code !== 1000 && (code < 3000 || code > 4999))\n throw new DOMException(\n `The close code must be either 1000, or between 3000 and 4999. ${code} is neither.`,\n \"InvalidAccessError\",\n );\n if (reason !== undefined && new TextEncoder().encode(reason).byteLength > 123)\n throw new DOMException(\n \"The close reason must not be greater than 123 UTF-8 bytes.\",\n \"SyntaxError\",\n );\n}\n\n/** CloseEvent is not a global in every runtime (Node 22): a compatible Event subclass. */\nexport class CellsCloseEvent extends Event {\n readonly code: number;\n readonly reason: string;\n readonly wasClean: boolean;\n constructor(type: string, init: { code?: number; reason?: string; wasClean?: boolean } = {}) {\n super(type);\n this.code = init.code ?? 1005;\n this.reason = init.reason ?? \"\";\n this.wasClean = init.wasClean ?? false;\n }\n}\n\n/** One side of a frame relay: a MessagePort, or a port of a multiplexer. */\nexport interface FrameEnd {\n post(f: Frame): void;\n listen(fn: (f: Frame) => void): void;\n close(): void;\n}\n\nexport const portEnd = (port: MessagePort): FrameEnd => ({\n post: (f) => port.postMessage(f),\n listen: (fn) => {\n port.onmessage = (e) => fn(e.data as Frame);\n },\n close: () => port.close(),\n});\n\n/**\n * Relays a socket's frames between `a` and `b`. Once a close frame has passed each way (the\n * closing handshake) both ends are closed, after a moment for the last frames to arrive.\n * Returns a function that ends the relay at once, telling `a` the socket closed with `code`;\n * `onDone` runs when the relay ends either way.\n */\nexport function relayFrames(\n a: FrameEnd,\n b: FrameEnd,\n onDone?: () => void,\n): (code: number, reason: string) => void {\n let fromA = false;\n let fromB = false;\n let done = false;\n const finish = () => {\n if (done) return;\n done = true;\n onDone?.();\n const t = setTimeout(() => {\n a.close();\n b.close();\n }, 1_000);\n (t as { unref?(): void }).unref?.();\n };\n a.listen((f) => {\n b.post(f);\n if (f.t !== \"c\") return;\n fromA = true;\n if (fromB) finish();\n });\n b.listen((f) => {\n a.post(f);\n if (f.t !== \"c\") return;\n fromB = true;\n if (fromA) finish();\n });\n return (code, reason) => {\n if (done) return;\n a.post({ t: \"c\", code, reason });\n finish();\n };\n}\n"]}
|
package/dist/ws/server.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { type Frame } from "./frames.js";
|
|
1
2
|
declare const kPort: unique symbol;
|
|
3
|
+
declare const kTakeQueued: unique symbol;
|
|
2
4
|
/**
|
|
3
5
|
* Cloudflare Workers' server-side WebSocket (one end of a WebSocketPair):
|
|
4
6
|
* events are delivered only after `accept()`; `send`/`close` as in workerd.
|
|
@@ -18,6 +20,8 @@ export declare class CfWebSocket extends EventTarget {
|
|
|
18
20
|
get binaryType(): "blob" | "arraybuffer";
|
|
19
21
|
set binaryType(v: "blob" | "arraybuffer");
|
|
20
22
|
[kPort]: MessagePort | undefined;
|
|
23
|
+
/** The frames that arrived before accept(), removed (takeClientPort hands them over). */
|
|
24
|
+
[kTakeQueued](): Frame[];
|
|
21
25
|
constructor(port: MessagePort);
|
|
22
26
|
/** The other end of the WebSocketPair (the runtime checks how the server end was accepted). */
|
|
23
27
|
peer?: CfWebSocket;
|
package/dist/ws/server.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { CellsCloseEvent, checkClose, toFrameData } from "./frames.js";
|
|
1
|
+
import { CellsCloseEvent, checkClose, portEnd, relayFrames, toFrameData, } from "./frames.js";
|
|
2
2
|
const kPort = Symbol("cellb.ws.port");
|
|
3
|
+
const kTakeQueued = Symbol("cellb.ws.takeQueued");
|
|
3
4
|
/** Server ends accepted in this realm and not yet closed (see `CfWebSocket.goAway`). */
|
|
4
5
|
const acceptedEnds = new Set();
|
|
5
6
|
/**
|
|
@@ -28,6 +29,10 @@ export class CfWebSocket extends EventTarget {
|
|
|
28
29
|
[kPort];
|
|
29
30
|
#accepted = false;
|
|
30
31
|
#queued = [];
|
|
32
|
+
/** The frames that arrived before accept(), removed (takeClientPort hands them over). */
|
|
33
|
+
[kTakeQueued]() {
|
|
34
|
+
return this.#queued.splice(0);
|
|
35
|
+
}
|
|
31
36
|
#attachment;
|
|
32
37
|
#lastPing = 0;
|
|
33
38
|
#watch;
|
|
@@ -209,7 +214,17 @@ export function takeClientPort(ws) {
|
|
|
209
214
|
ws[kPort] = undefined;
|
|
210
215
|
port.onmessage = null;
|
|
211
216
|
ws.readyState = 3; // handed over: this end must not answer pings any more
|
|
212
|
-
|
|
217
|
+
// Frames the server sent before the response was handed over (partyserver greets in
|
|
218
|
+
// onConnect, before it returns the 101) reached this end and wait in its queue: the new
|
|
219
|
+
// holder gets them first, then the rest, through a channel that relays both ways.
|
|
220
|
+
const queued = ws[kTakeQueued]();
|
|
221
|
+
if (!queued.length)
|
|
222
|
+
return port;
|
|
223
|
+
const relay = new MessageChannel();
|
|
224
|
+
for (const f of queued)
|
|
225
|
+
relay.port2.postMessage(f);
|
|
226
|
+
relayFrames(portEnd(relay.port2), portEnd(port)); // closed with the socket's handshake
|
|
227
|
+
return relay.port1;
|
|
213
228
|
}
|
|
214
229
|
/**
|
|
215
230
|
* `Response` that also accepts Cloudflare's `{ status: 101, webSocket }` init —
|
package/dist/ws/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/ws/server.ts"],"names":[],"mappings":"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","sourcesContent":["import { CellsCloseEvent, checkClose, type Frame, toFrameData } from \"./frames.js\";\n\nconst kPort = Symbol(\"cellb.ws.port\");\n/** Server ends accepted in this realm and not yet closed (see `CfWebSocket.goAway`). */\nconst acceptedEnds = new Set<CfWebSocket>();\n\n/**\n * Cloudflare Workers' server-side WebSocket (one end of a WebSocketPair):\n * events are delivered only after `accept()`; `send`/`close` as in workerd.\n * Hibernation (`ctx.acceptWebSocket`) is a later prototype.\n */\nexport class CfWebSocket extends EventTarget {\n static readonly READY_STATE_CONNECTING = 0;\n static readonly READY_STATE_OPEN = 1;\n static readonly READY_STATE_CLOSING = 2;\n static readonly READY_STATE_CLOSED = 3;\n readyState = 1;\n url: string | null = null;\n\n protocol: string | null = null;\n extensions: string | null = null;\n #binaryType: \"blob\" | \"arraybuffer\" = \"arraybuffer\";\n /** How binary messages arrive; other values are ignored, as in browsers. */\n get binaryType(): \"blob\" | \"arraybuffer\" {\n return this.#binaryType;\n }\n set binaryType(v: \"blob\" | \"arraybuffer\") {\n if (v === \"blob\" || v === \"arraybuffer\") this.#binaryType = v;\n }\n [kPort]: MessagePort | undefined;\n #accepted = false;\n #queued: Frame[] = [];\n #attachment: unknown;\n\n #lastPing = 0;\n #watch: ReturnType<typeof setInterval> | undefined;\n\n constructor(port: MessagePort) {\n super();\n this[kPort] = port;\n port.onmessage = (e) => {\n const f = e.data as Frame;\n if (f.t === \"p\") return this.#ping(f.hb); // answered even before accept()\n if (this.#accepted) this.#frame(f);\n else this.#queued.push(f);\n };\n }\n\n /** Heartbeat: answer the client's ping; close 1006 when pings stop for 3 periods. */\n #ping(hb: number): void {\n this.#lastPing = Date.now();\n this[kPort]?.postMessage({ t: \"q\" } satisfies Frame);\n if (this.#watch || !hb) return;\n this.#watch = setInterval(() => {\n if (this.readyState === 3) return clearInterval(this.#watch);\n if (Date.now() - this.#lastPing > 3 * hb) this.#gone();\n }, hb);\n }\n\n /** The client stopped pinging (tab closed, worker killed): abnormal closure. */\n #gone(): void {\n clearInterval(this.#watch);\n if (this.readyState === 3) return;\n this.readyState = 3;\n acceptedEnds.delete(this);\n this[kPort]?.close();\n this.dispatchEvent(new CellsCloseEvent(\"close\", { code: 1006, reason: \"\", wasClean: false }));\n }\n\n /** The other end of the WebSocketPair (the runtime checks how the server end was accepted). */\n peer?: CfWebSocket;\n /** Accepted through ctx.acceptWebSocket() (hibernatable) rather than accept(). */\n hibernatable = false;\n get accepted(): boolean {\n return this.#accepted;\n }\n\n accept(): void {\n if (this.#accepted) return;\n if (!this[kPort])\n throw new TypeError(\"This WebSocket end was handed to a client; it cannot be accepted.\");\n this.#accepted = true;\n acceptedEnds.add(this);\n this[kPort].start?.();\n for (const f of this.#queued.splice(0)) this.#frame(f);\n }\n\n serializeAttachment(v: unknown): void {\n this.#attachment = structuredClone(v);\n }\n deserializeAttachment(): unknown {\n return structuredClone(this.#attachment);\n }\n\n #frame(f: Frame): void {\n if (f.t === \"m\") {\n const data = typeof f.d !== \"string\" && this.#binaryType === \"blob\" ? new Blob([f.d]) : f.d;\n this.dispatchEvent(new MessageEvent(\"message\", { data }));\n this[kPort]?.postMessage({ t: \"a\" } satisfies Frame); // the sender's bufferedAmount drains\n return;\n }\n if (f.t !== \"c\") return;\n const wasOpen = this.readyState === 1;\n if (wasOpen)\n this[kPort]!.postMessage({ t: \"c\", code: f.code, reason: f.reason } satisfies Frame);\n this.readyState = 3;\n acceptedEnds.delete(this);\n clearInterval(this.#watch);\n this[kPort]!.close();\n this.dispatchEvent(\n new CellsCloseEvent(\"close\", { code: f.code, reason: f.reason, wasClean: true }),\n );\n }\n\n /**\n * Closes every server end accepted in this realm with 1001 (going away). A shard worker that\n * hands its cells to another tab does it before it stops, so that clients reconnect at once\n * instead of noticing through the heartbeat; Worker code cannot send 1001 itself (`close`).\n */\n static goAway(reason = \"moving to another worker\"): void {\n for (const ws of acceptedEnds) {\n acceptedEnds.delete(ws);\n if (ws.readyState >= 2) continue;\n ws.readyState = 2;\n ws[kPort]?.postMessage({ t: \"c\", code: 1001, reason } satisfies Frame);\n }\n }\n\n send(data: string | ArrayBuffer | ArrayBufferView): void {\n // celld lets either end of a pair send before accept() (workerd refuses); frames wait in\n // the port until the other end listens.\n if (this.readyState !== 1) throw new TypeError(\"Can't call WebSocket send() after close().\");\n const d = toFrameData(data);\n this[kPort]!.postMessage({ t: \"m\", d } satisfies Frame, typeof d === \"string\" ? [] : [d]);\n }\n\n close(code?: number, reason?: string): void {\n checkClose(code, reason);\n if (this.readyState >= 2) return;\n this.readyState = 2;\n this[kPort]!.postMessage({ t: \"c\", code: code ?? 1005, reason: reason ?? \"\" } satisfies Frame);\n }\n}\n\n/** The host's own WebSocket (Node's, or the browser's): the client sockets Worker code opens. */\nconst HostWebSocket = (\n globalThis as { WebSocket?: new (url: string, p?: string | string[]) => object }\n).WebSocket;\n\n/**\n * The `WebSocket` global of Worker code. On workerd one class covers both ends of a\n * WebSocketPair and the client sockets `new WebSocket(url)` opens, and libraries rely on that:\n * the Agents SDK (partyserver) reads attachments with\n * `WebSocket.prototype.deserializeAttachment.call(ws)` and compares `readyState` with\n * `WebSocket.READY_STATE_OPEN`. So its prototype is the server end's (`CfWebSocket`), its\n * statics are workerd's, `instanceof` holds for both kinds, and `new WebSocket(url)` still opens\n * the host's client socket.\n */\nexport const WorkersWebSocket = (() => {\n function WebSocket(this: unknown, url: string, protocols?: string | string[]): object {\n if (!new.target)\n throw new TypeError(\"Failed to construct 'WebSocket': Please use the 'new' operator.\");\n if (!HostWebSocket) throw new Error(\"WebSocket clients are not available in this realm.\");\n return new HostWebSocket(url, protocols);\n }\n WebSocket.prototype = CfWebSocket.prototype;\n const states = { CONNECTING: 0, OPEN: 1, CLOSING: 2, CLOSED: 3 } as const;\n for (const [name, value] of Object.entries(states)) {\n Object.defineProperty(WebSocket, name, { value, enumerable: true });\n Object.defineProperty(WebSocket, `READY_STATE_${name}`, { value, enumerable: true });\n }\n Object.defineProperty(WebSocket, Symbol.hasInstance, {\n value: (v: unknown) =>\n v instanceof CfWebSocket || (HostWebSocket !== undefined && v instanceof HostWebSocket),\n });\n return WebSocket as unknown as typeof CfWebSocket & {\n new (url: string, protocols?: string | string[]): CfWebSocket;\n readonly CONNECTING: 0;\n readonly OPEN: 1;\n readonly CLOSING: 2;\n readonly CLOSED: 3;\n };\n})();\n\n/** `new WebSocketPair()` → `{ 0: client, 1: server }`, entangled over a MessageChannel. */\nexport class WebSocketPair {\n 0: CfWebSocket;\n 1: CfWebSocket;\n constructor() {\n const { port1, port2 } = new MessageChannel();\n this[0] = new CfWebSocket(port1);\n this[1] = new CfWebSocket(port2);\n this[0].peer = this[1];\n this[1].peer = this[0];\n }\n /** `const [client, server] = new WebSocketPair()`, as in workerd. */\n *[Symbol.iterator](): IterableIterator<CfWebSocket> {\n yield this[0];\n yield this[1];\n }\n}\n\n/**\n * `WebSocketPair` under the `websocket_standard_binary_type` compatibility flag: both ends\n * start with `binaryType` \"blob\", as browsers' WebSockets do. Without it they start with\n * \"arraybuffer\", workerd's older default.\n */\nexport class StandardWebSocketPair extends WebSocketPair {\n constructor() {\n super();\n this[0].binaryType = \"blob\";\n this[1].binaryType = \"blob\";\n }\n}\n\n/**\n * Detaches the transport of the CLIENT end returned in a 101 response, so the\n * runtime can hand the raw MessagePort to the real client (transferable).\n */\nexport function takeClientPort(ws: CfWebSocket): MessagePort {\n const port = ws[kPort];\n if (!port) throw new TypeError(\"WebSocket end already handed over\");\n ws[kPort] = undefined;\n port.onmessage = null;\n ws.readyState = 3; // handed over: this end must not answer pings any more\n return port;\n}\n\n/**\n * `Response` that also accepts Cloudflare's `{ status: 101, webSocket }` init —\n * the platform `Response` rejects status 101. Provided to user code via ~deps.\n */\n/** The platform `Response`, as this module sees it (it is external to user bundles). */\nconst HostResponse = Response;\n\n/** Browsers drop `Set-Cookie` from every Response they build (Node keeps it). */\nconst dropsSetCookie = !new HostResponse(null, { headers: { \"set-cookie\": \"a=b\" } }).headers.has(\n \"set-cookie\",\n);\n\nexport class CellsResponse extends Response {\n readonly #status: number;\n readonly webSocket: CfWebSocket | null;\n constructor(\n body?: BodyInit | null,\n init: ResponseInit & { webSocket?: CfWebSocket | null } = {},\n ) {\n const upgrade = init.status === 101;\n // The init's members read one by one, as Fetch reads a dictionary: an init that is itself a\n // Response (`new Response(body, response)`, as opencode's SDK does) keeps its headers and\n // statusText, which a spread would drop (they are getters on its prototype).\n super(upgrade ? null : body, {\n status: upgrade ? 200 : init.status,\n statusText: init.statusText,\n headers: init.headers,\n });\n this.#status = init.status ?? 200;\n this.webSocket = init.webSocket ?? null;\n if (dropsSetCookie) {\n // In a browser the platform's headers drop `Set-Cookie`, which Workers set (Astro appends\n // its cookies to the response): the response keeps its headers in a standalone `Headers`,\n // the ones the platform derived (content-type) plus the Set-Cookie values of the init.\n const headers = new Headers(super.headers);\n const given = init.headers instanceof Headers ? init.headers : new Headers(init.headers);\n for (const c of given.getSetCookie()) headers.append(\"set-cookie\", c);\n Object.defineProperty(this, \"headers\", {\n value: headers,\n configurable: true,\n enumerable: true,\n });\n }\n }\n get status(): number {\n // Static helpers (CellsResponse.json(), .redirect(), .error()) may build instances\n // without running this constructor: fall back to the platform's status.\n return #status in this ? this.#status : super.status;\n }\n\n /**\n * Every platform `Response` is a Workers `Response`, as on workerd: `Response.json()`,\n * `Response.redirect()` and `Response.error()` (the platform's static helpers, which build\n * platform instances, not instances of this subclass) and `fetch()` results pass\n * `instanceof Response` in Worker code. Astro checks every endpoint's result that way.\n */\n static [Symbol.hasInstance](v: unknown): boolean {\n return v instanceof HostResponse;\n }\n\n // In a browser the platform's static helpers build platform responses, whose headers drop\n // `Set-Cookie`: these build instances of this class there (`Response.json()` is how most\n // APIs answer, and their cookies are appended to it afterwards).\n static override json(data: unknown, init: ResponseInit = {}): Response {\n if (!dropsSetCookie) return super.json(data, init);\n const headers = new Headers(init.headers);\n if (!headers.has(\"content-type\")) headers.set(\"content-type\", \"application/json\");\n return new CellsResponse(JSON.stringify(data), { ...init, headers });\n }\n\n static override redirect(url: string | URL, status = 302): Response {\n if (!dropsSetCookie) return super.redirect(url, status);\n if (![301, 302, 303, 307, 308].includes(status))\n throw new RangeError(`Invalid status ${status}`);\n const base = (globalThis as { location?: { href: string } }).location?.href;\n return new CellsResponse(null, { status, headers: { location: new URL(url, base).href } });\n }\n}\n\n/** Workers `WebSocketRequestResponsePair` (ctx.setWebSocketAutoResponse). */\nexport class WebSocketRequestResponsePair {\n readonly request: string;\n readonly response: string;\n constructor(request: string, response: string) {\n this.request = request;\n this.response = response;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/ws/server.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,UAAU,EAEV,OAAO,EACP,WAAW,EACX,WAAW,GACZ,MAAM,aAAa,CAAC;AAErB,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;AACtC,MAAM,WAAW,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAClD,wFAAwF;AACxF,MAAM,YAAY,GAAG,IAAI,GAAG,EAAe,CAAC;AAE5C;;;;GAIG;AACH,MAAM,OAAO,WAAY,SAAQ,WAAW;IAC1C,MAAM,CAAU,sBAAsB,GAAG,CAAC,CAAC;IAC3C,MAAM,CAAU,gBAAgB,GAAG,CAAC,CAAC;IACrC,MAAM,CAAU,mBAAmB,GAAG,CAAC,CAAC;IACxC,MAAM,CAAU,kBAAkB,GAAG,CAAC,CAAC;IACvC,UAAU,GAAG,CAAC,CAAC;IACf,GAAG,GAAkB,IAAI,CAAC;IAE1B,QAAQ,GAAkB,IAAI,CAAC;IAC/B,UAAU,GAAkB,IAAI,CAAC;IACjC,WAAW,GAA2B,aAAa,CAAC;IACpD,4EAA4E;IAC5E,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IACD,IAAI,UAAU,CAAC,CAAyB;QACtC,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,aAAa;YAAE,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;IAChE,CAAC;IACD,CAAC,KAAK,CAAC,CAA0B;IACjC,SAAS,GAAG,KAAK,CAAC;IAClB,OAAO,GAAY,EAAE,CAAC;IACtB,yFAAyF;IACzF,CAAC,WAAW,CAAC;QACX,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC;IACD,WAAW,CAAU;IAErB,SAAS,GAAG,CAAC,CAAC;IACd,MAAM,CAA6C;IAEnD,YAAY,IAAiB;QAC3B,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,EAAE,EAAE;YACrB,MAAM,CAAC,GAAG,CAAC,CAAC,IAAa,CAAC;YAC1B,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG;gBAAE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,gCAAgC;YAC1E,IAAI,IAAI,CAAC,SAAS;gBAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;;gBAC9B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5B,CAAC,CAAC;IACJ,CAAC;IAED,qFAAqF;IACrF,KAAK,CAAC,EAAU;QACd,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC,EAAE,CAAC,EAAE,GAAG,EAAkB,CAAC,CAAC;QACrD,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE;YAAE,OAAO;QAC/B,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE;YAC7B,IAAI,IAAI,CAAC,UAAU,KAAK,CAAC;gBAAE,OAAO,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC7D,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC,GAAG,EAAE;gBAAE,IAAI,CAAC,KAAK,EAAE,CAAC;QACzD,CAAC,EAAE,EAAE,CAAC,CAAC;IACT,CAAC;IAED,gFAAgF;IAChF,KAAK;QACH,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC3B,IAAI,IAAI,CAAC,UAAU,KAAK,CAAC;YAAE,OAAO;QAClC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACpB,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC;QACrB,IAAI,CAAC,aAAa,CAAC,IAAI,eAAe,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAChG,CAAC;IAED,+FAA+F;IAC/F,IAAI,CAAe;IACnB,kFAAkF;IAClF,YAAY,GAAG,KAAK,CAAC;IACrB,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,MAAM;QACJ,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;YACd,MAAM,IAAI,SAAS,CAAC,mEAAmE,CAAC,CAAC;QAC3F,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACvB,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;QACtB,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;YAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,mBAAmB,CAAC,CAAU;QAC5B,IAAI,CAAC,WAAW,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,qBAAqB;QACnB,OAAO,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,CAAC,CAAQ;QACb,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YAChB,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5F,IAAI,CAAC,aAAa,CAAC,IAAI,YAAY,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAC1D,IAAI,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC,EAAE,CAAC,EAAE,GAAG,EAAkB,CAAC,CAAC,CAAC,qCAAqC;YAC3F,OAAO;QACT,CAAC;QACD,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG;YAAE,OAAO;QACxB,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,KAAK,CAAC,CAAC;QACtC,IAAI,OAAO;YACT,IAAI,CAAC,KAAK,CAAE,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAkB,CAAC,CAAC;QACvF,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACpB,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC1B,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAE,CAAC,KAAK,EAAE,CAAC;QACrB,IAAI,CAAC,aAAa,CAChB,IAAI,eAAe,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CACjF,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,0BAA0B;QAC/C,KAAK,MAAM,EAAE,IAAI,YAAY,EAAE,CAAC;YAC9B,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACxB,IAAI,EAAE,CAAC,UAAU,IAAI,CAAC;gBAAE,SAAS;YACjC,EAAE,CAAC,UAAU,GAAG,CAAC,CAAC;YAClB,EAAE,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAkB,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IAED,IAAI,CAAC,IAA4C;QAC/C,yFAAyF;QACzF,wCAAwC;QACxC,IAAI,IAAI,CAAC,UAAU,KAAK,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,4CAA4C,CAAC,CAAC;QAC7F,MAAM,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAE,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAkB,EAAE,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5F,CAAC;IAED,KAAK,CAAC,IAAa,EAAE,MAAe;QAClC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzB,IAAI,IAAI,CAAC,UAAU,IAAI,CAAC;YAAE,OAAO;QACjC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACpB,IAAI,CAAC,KAAK,CAAE,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,MAAM,EAAE,MAAM,IAAI,EAAE,EAAkB,CAAC,CAAC;IACjG,CAAC;CACF;AAED,iGAAiG;AACjG,MAAM,aAAa,GACjB,UACD,CAAC,SAAS,CAAC;AAEZ;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE;IACpC,SAAS,SAAS,CAAgB,GAAW,EAAE,SAA6B;QAC1E,IAAI,CAAC,IAAI,MAAM;YACb,MAAM,IAAI,SAAS,CAAC,iEAAiE,CAAC,CAAC;QACzF,IAAI,CAAC,aAAa;YAAE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;QAC1F,OAAO,IAAI,aAAa,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC3C,CAAC;IACD,SAAS,CAAC,SAAS,GAAG,WAAW,CAAC,SAAS,CAAC;IAC5C,MAAM,MAAM,GAAG,EAAE,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAW,CAAC;IAC1E,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnD,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;QACpE,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,eAAe,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;IACvF,CAAC;IACD,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,MAAM,CAAC,WAAW,EAAE;QACnD,KAAK,EAAE,CAAC,CAAU,EAAE,EAAE,CACpB,CAAC,YAAY,WAAW,IAAI,CAAC,aAAa,KAAK,SAAS,IAAI,CAAC,YAAY,aAAa,CAAC;KAC1F,CAAC,CAAC;IACH,OAAO,SAMN,CAAC;AACJ,CAAC,CAAC,EAAE,CAAC;AAEL,2FAA2F;AAC3F,MAAM,OAAO,aAAa;IACxB,CAAC,CAAc;IACf,CAAC,CAAc;IACf;QACE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,IAAI,cAAc,EAAE,CAAC;QAC9C,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACvB,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;IACD,qEAAqE;IACrE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;QAChB,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC;QACd,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC;IAChB,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,qBAAsB,SAAQ,aAAa;IACtD;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,MAAM,CAAC;QAC5B,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,MAAM,CAAC;IAC9B,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,EAAe;IAC5C,MAAM,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;IACvB,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,SAAS,CAAC,mCAAmC,CAAC,CAAC;IACpE,EAAE,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC;IACtB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IACtB,EAAE,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,uDAAuD;IAC1E,oFAAoF;IACpF,wFAAwF;IACxF,kFAAkF;IAClF,MAAM,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC;IACjC,IAAI,CAAC,MAAM,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAChC,MAAM,KAAK,GAAG,IAAI,cAAc,EAAE,CAAC;IACnC,KAAK,MAAM,CAAC,IAAI,MAAM;QAAE,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IACnD,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,qCAAqC;IACvF,OAAO,KAAK,CAAC,KAAK,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,wFAAwF;AACxF,MAAM,YAAY,GAAG,QAAQ,CAAC;AAE9B,iFAAiF;AACjF,MAAM,cAAc,GAAG,CAAC,IAAI,YAAY,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAC9F,YAAY,CACb,CAAC;AAEF,MAAM,OAAO,aAAc,SAAQ,QAAQ;IAChC,OAAO,CAAS;IAChB,SAAS,CAAqB;IACvC,YACE,IAAsB,EACtB,IAAI,GAAsD,EAAE;QAE5D,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,KAAK,GAAG,CAAC;QACpC,4FAA4F;QAC5F,0FAA0F;QAC1F,6EAA6E;QAC7E,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE;YAC3B,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM;YACnC,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC;QAClC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC;QACxC,IAAI,cAAc,EAAE,CAAC;YACnB,0FAA0F;YAC1F,0FAA0F;YAC1F,uFAAuF;YACvF,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,YAAY,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACzF,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,YAAY,EAAE;gBAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;YACtE,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,SAAS,EAAE;gBACrC,KAAK,EAAE,OAAO;gBACd,YAAY,EAAE,IAAI;gBAClB,UAAU,EAAE,IAAI;aACjB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,IAAI,MAAM;QACR,mFAAmF;QACnF,wEAAwE;QACxE,OAAO,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;IACvD,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAU;QACpC,OAAO,CAAC,YAAY,YAAY,CAAC;IACnC,CAAC;IAED,0FAA0F;IAC1F,yFAAyF;IACzF,iEAAiE;IACjE,MAAM,CAAU,IAAI,CAAC,IAAa,EAAE,IAAI,GAAiB,EAAE;QACzD,IAAI,CAAC,cAAc;YAAE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACnD,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;QAClF,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,CAAU,QAAQ,CAAC,GAAiB,EAAE,MAAM,GAAG,GAAG;QACtD,IAAI,CAAC,cAAc;YAAE,OAAO,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACxD,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC7C,MAAM,IAAI,UAAU,CAAC,kBAAkB,MAAM,EAAE,CAAC,CAAC;QACnD,MAAM,IAAI,GAAI,UAA8C,CAAC,QAAQ,EAAE,IAAI,CAAC;QAC5E,OAAO,IAAI,aAAa,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC7F,CAAC;CACF;AAED,6EAA6E;AAC7E,MAAM,OAAO,4BAA4B;IAC9B,OAAO,CAAS;IAChB,QAAQ,CAAS;IAC1B,YAAY,OAAe,EAAE,QAAgB;QAC3C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CACF","sourcesContent":["import {\n CellsCloseEvent,\n checkClose,\n type Frame,\n portEnd,\n relayFrames,\n toFrameData,\n} from \"./frames.js\";\n\nconst kPort = Symbol(\"cellb.ws.port\");\nconst kTakeQueued = Symbol(\"cellb.ws.takeQueued\");\n/** Server ends accepted in this realm and not yet closed (see `CfWebSocket.goAway`). */\nconst acceptedEnds = new Set<CfWebSocket>();\n\n/**\n * Cloudflare Workers' server-side WebSocket (one end of a WebSocketPair):\n * events are delivered only after `accept()`; `send`/`close` as in workerd.\n * Hibernation (`ctx.acceptWebSocket`) is a later prototype.\n */\nexport class CfWebSocket extends EventTarget {\n static readonly READY_STATE_CONNECTING = 0;\n static readonly READY_STATE_OPEN = 1;\n static readonly READY_STATE_CLOSING = 2;\n static readonly READY_STATE_CLOSED = 3;\n readyState = 1;\n url: string | null = null;\n\n protocol: string | null = null;\n extensions: string | null = null;\n #binaryType: \"blob\" | \"arraybuffer\" = \"arraybuffer\";\n /** How binary messages arrive; other values are ignored, as in browsers. */\n get binaryType(): \"blob\" | \"arraybuffer\" {\n return this.#binaryType;\n }\n set binaryType(v: \"blob\" | \"arraybuffer\") {\n if (v === \"blob\" || v === \"arraybuffer\") this.#binaryType = v;\n }\n [kPort]: MessagePort | undefined;\n #accepted = false;\n #queued: Frame[] = [];\n /** The frames that arrived before accept(), removed (takeClientPort hands them over). */\n [kTakeQueued](): Frame[] {\n return this.#queued.splice(0);\n }\n #attachment: unknown;\n\n #lastPing = 0;\n #watch: ReturnType<typeof setInterval> | undefined;\n\n constructor(port: MessagePort) {\n super();\n this[kPort] = port;\n port.onmessage = (e) => {\n const f = e.data as Frame;\n if (f.t === \"p\") return this.#ping(f.hb); // answered even before accept()\n if (this.#accepted) this.#frame(f);\n else this.#queued.push(f);\n };\n }\n\n /** Heartbeat: answer the client's ping; close 1006 when pings stop for 3 periods. */\n #ping(hb: number): void {\n this.#lastPing = Date.now();\n this[kPort]?.postMessage({ t: \"q\" } satisfies Frame);\n if (this.#watch || !hb) return;\n this.#watch = setInterval(() => {\n if (this.readyState === 3) return clearInterval(this.#watch);\n if (Date.now() - this.#lastPing > 3 * hb) this.#gone();\n }, hb);\n }\n\n /** The client stopped pinging (tab closed, worker killed): abnormal closure. */\n #gone(): void {\n clearInterval(this.#watch);\n if (this.readyState === 3) return;\n this.readyState = 3;\n acceptedEnds.delete(this);\n this[kPort]?.close();\n this.dispatchEvent(new CellsCloseEvent(\"close\", { code: 1006, reason: \"\", wasClean: false }));\n }\n\n /** The other end of the WebSocketPair (the runtime checks how the server end was accepted). */\n peer?: CfWebSocket;\n /** Accepted through ctx.acceptWebSocket() (hibernatable) rather than accept(). */\n hibernatable = false;\n get accepted(): boolean {\n return this.#accepted;\n }\n\n accept(): void {\n if (this.#accepted) return;\n if (!this[kPort])\n throw new TypeError(\"This WebSocket end was handed to a client; it cannot be accepted.\");\n this.#accepted = true;\n acceptedEnds.add(this);\n this[kPort].start?.();\n for (const f of this.#queued.splice(0)) this.#frame(f);\n }\n\n serializeAttachment(v: unknown): void {\n this.#attachment = structuredClone(v);\n }\n deserializeAttachment(): unknown {\n return structuredClone(this.#attachment);\n }\n\n #frame(f: Frame): void {\n if (f.t === \"m\") {\n const data = typeof f.d !== \"string\" && this.#binaryType === \"blob\" ? new Blob([f.d]) : f.d;\n this.dispatchEvent(new MessageEvent(\"message\", { data }));\n this[kPort]?.postMessage({ t: \"a\" } satisfies Frame); // the sender's bufferedAmount drains\n return;\n }\n if (f.t !== \"c\") return;\n const wasOpen = this.readyState === 1;\n if (wasOpen)\n this[kPort]!.postMessage({ t: \"c\", code: f.code, reason: f.reason } satisfies Frame);\n this.readyState = 3;\n acceptedEnds.delete(this);\n clearInterval(this.#watch);\n this[kPort]!.close();\n this.dispatchEvent(\n new CellsCloseEvent(\"close\", { code: f.code, reason: f.reason, wasClean: true }),\n );\n }\n\n /**\n * Closes every server end accepted in this realm with 1001 (going away). A shard worker that\n * hands its cells to another tab does it before it stops, so that clients reconnect at once\n * instead of noticing through the heartbeat; Worker code cannot send 1001 itself (`close`).\n */\n static goAway(reason = \"moving to another worker\"): void {\n for (const ws of acceptedEnds) {\n acceptedEnds.delete(ws);\n if (ws.readyState >= 2) continue;\n ws.readyState = 2;\n ws[kPort]?.postMessage({ t: \"c\", code: 1001, reason } satisfies Frame);\n }\n }\n\n send(data: string | ArrayBuffer | ArrayBufferView): void {\n // celld lets either end of a pair send before accept() (workerd refuses); frames wait in\n // the port until the other end listens.\n if (this.readyState !== 1) throw new TypeError(\"Can't call WebSocket send() after close().\");\n const d = toFrameData(data);\n this[kPort]!.postMessage({ t: \"m\", d } satisfies Frame, typeof d === \"string\" ? [] : [d]);\n }\n\n close(code?: number, reason?: string): void {\n checkClose(code, reason);\n if (this.readyState >= 2) return;\n this.readyState = 2;\n this[kPort]!.postMessage({ t: \"c\", code: code ?? 1005, reason: reason ?? \"\" } satisfies Frame);\n }\n}\n\n/** The host's own WebSocket (Node's, or the browser's): the client sockets Worker code opens. */\nconst HostWebSocket = (\n globalThis as { WebSocket?: new (url: string, p?: string | string[]) => object }\n).WebSocket;\n\n/**\n * The `WebSocket` global of Worker code. On workerd one class covers both ends of a\n * WebSocketPair and the client sockets `new WebSocket(url)` opens, and libraries rely on that:\n * the Agents SDK (partyserver) reads attachments with\n * `WebSocket.prototype.deserializeAttachment.call(ws)` and compares `readyState` with\n * `WebSocket.READY_STATE_OPEN`. So its prototype is the server end's (`CfWebSocket`), its\n * statics are workerd's, `instanceof` holds for both kinds, and `new WebSocket(url)` still opens\n * the host's client socket.\n */\nexport const WorkersWebSocket = (() => {\n function WebSocket(this: unknown, url: string, protocols?: string | string[]): object {\n if (!new.target)\n throw new TypeError(\"Failed to construct 'WebSocket': Please use the 'new' operator.\");\n if (!HostWebSocket) throw new Error(\"WebSocket clients are not available in this realm.\");\n return new HostWebSocket(url, protocols);\n }\n WebSocket.prototype = CfWebSocket.prototype;\n const states = { CONNECTING: 0, OPEN: 1, CLOSING: 2, CLOSED: 3 } as const;\n for (const [name, value] of Object.entries(states)) {\n Object.defineProperty(WebSocket, name, { value, enumerable: true });\n Object.defineProperty(WebSocket, `READY_STATE_${name}`, { value, enumerable: true });\n }\n Object.defineProperty(WebSocket, Symbol.hasInstance, {\n value: (v: unknown) =>\n v instanceof CfWebSocket || (HostWebSocket !== undefined && v instanceof HostWebSocket),\n });\n return WebSocket as unknown as typeof CfWebSocket & {\n new (url: string, protocols?: string | string[]): CfWebSocket;\n readonly CONNECTING: 0;\n readonly OPEN: 1;\n readonly CLOSING: 2;\n readonly CLOSED: 3;\n };\n})();\n\n/** `new WebSocketPair()` → `{ 0: client, 1: server }`, entangled over a MessageChannel. */\nexport class WebSocketPair {\n 0: CfWebSocket;\n 1: CfWebSocket;\n constructor() {\n const { port1, port2 } = new MessageChannel();\n this[0] = new CfWebSocket(port1);\n this[1] = new CfWebSocket(port2);\n this[0].peer = this[1];\n this[1].peer = this[0];\n }\n /** `const [client, server] = new WebSocketPair()`, as in workerd. */\n *[Symbol.iterator](): IterableIterator<CfWebSocket> {\n yield this[0];\n yield this[1];\n }\n}\n\n/**\n * `WebSocketPair` under the `websocket_standard_binary_type` compatibility flag: both ends\n * start with `binaryType` \"blob\", as browsers' WebSockets do. Without it they start with\n * \"arraybuffer\", workerd's older default.\n */\nexport class StandardWebSocketPair extends WebSocketPair {\n constructor() {\n super();\n this[0].binaryType = \"blob\";\n this[1].binaryType = \"blob\";\n }\n}\n\n/**\n * Detaches the transport of the CLIENT end returned in a 101 response, so the\n * runtime can hand the raw MessagePort to the real client (transferable).\n */\nexport function takeClientPort(ws: CfWebSocket): MessagePort {\n const port = ws[kPort];\n if (!port) throw new TypeError(\"WebSocket end already handed over\");\n ws[kPort] = undefined;\n port.onmessage = null;\n ws.readyState = 3; // handed over: this end must not answer pings any more\n // Frames the server sent before the response was handed over (partyserver greets in\n // onConnect, before it returns the 101) reached this end and wait in its queue: the new\n // holder gets them first, then the rest, through a channel that relays both ways.\n const queued = ws[kTakeQueued]();\n if (!queued.length) return port;\n const relay = new MessageChannel();\n for (const f of queued) relay.port2.postMessage(f);\n relayFrames(portEnd(relay.port2), portEnd(port)); // closed with the socket's handshake\n return relay.port1;\n}\n\n/**\n * `Response` that also accepts Cloudflare's `{ status: 101, webSocket }` init —\n * the platform `Response` rejects status 101. Provided to user code via ~deps.\n */\n/** The platform `Response`, as this module sees it (it is external to user bundles). */\nconst HostResponse = Response;\n\n/** Browsers drop `Set-Cookie` from every Response they build (Node keeps it). */\nconst dropsSetCookie = !new HostResponse(null, { headers: { \"set-cookie\": \"a=b\" } }).headers.has(\n \"set-cookie\",\n);\n\nexport class CellsResponse extends Response {\n readonly #status: number;\n readonly webSocket: CfWebSocket | null;\n constructor(\n body?: BodyInit | null,\n init: ResponseInit & { webSocket?: CfWebSocket | null } = {},\n ) {\n const upgrade = init.status === 101;\n // The init's members read one by one, as Fetch reads a dictionary: an init that is itself a\n // Response (`new Response(body, response)`, as opencode's SDK does) keeps its headers and\n // statusText, which a spread would drop (they are getters on its prototype).\n super(upgrade ? null : body, {\n status: upgrade ? 200 : init.status,\n statusText: init.statusText,\n headers: init.headers,\n });\n this.#status = init.status ?? 200;\n this.webSocket = init.webSocket ?? null;\n if (dropsSetCookie) {\n // In a browser the platform's headers drop `Set-Cookie`, which Workers set (Astro appends\n // its cookies to the response): the response keeps its headers in a standalone `Headers`,\n // the ones the platform derived (content-type) plus the Set-Cookie values of the init.\n const headers = new Headers(super.headers);\n const given = init.headers instanceof Headers ? init.headers : new Headers(init.headers);\n for (const c of given.getSetCookie()) headers.append(\"set-cookie\", c);\n Object.defineProperty(this, \"headers\", {\n value: headers,\n configurable: true,\n enumerable: true,\n });\n }\n }\n get status(): number {\n // Static helpers (CellsResponse.json(), .redirect(), .error()) may build instances\n // without running this constructor: fall back to the platform's status.\n return #status in this ? this.#status : super.status;\n }\n\n /**\n * Every platform `Response` is a Workers `Response`, as on workerd: `Response.json()`,\n * `Response.redirect()` and `Response.error()` (the platform's static helpers, which build\n * platform instances, not instances of this subclass) and `fetch()` results pass\n * `instanceof Response` in Worker code. Astro checks every endpoint's result that way.\n */\n static [Symbol.hasInstance](v: unknown): boolean {\n return v instanceof HostResponse;\n }\n\n // In a browser the platform's static helpers build platform responses, whose headers drop\n // `Set-Cookie`: these build instances of this class there (`Response.json()` is how most\n // APIs answer, and their cookies are appended to it afterwards).\n static override json(data: unknown, init: ResponseInit = {}): Response {\n if (!dropsSetCookie) return super.json(data, init);\n const headers = new Headers(init.headers);\n if (!headers.has(\"content-type\")) headers.set(\"content-type\", \"application/json\");\n return new CellsResponse(JSON.stringify(data), { ...init, headers });\n }\n\n static override redirect(url: string | URL, status = 302): Response {\n if (!dropsSetCookie) return super.redirect(url, status);\n if (![301, 302, 303, 307, 308].includes(status))\n throw new RangeError(`Invalid status ${status}`);\n const base = (globalThis as { location?: { href: string } }).location?.href;\n return new CellsResponse(null, { status, headers: { location: new URL(url, base).href } });\n }\n}\n\n/** Workers `WebSocketRequestResponsePair` (ctx.setWebSocketAutoResponse). */\nexport class WebSocketRequestResponsePair {\n readonly request: string;\n readonly response: string;\n constructor(request: string, response: string) {\n this.request = request;\n this.response = response;\n }\n}\n"]}
|