@statewalker/cellb 0.7.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +2 -1
  2. package/dist/bindings/html-rewriter.d.ts +7 -0
  3. package/dist/bindings/html-rewriter.js +4 -11
  4. package/dist/bindings/html-rewriter.js.map +1 -1
  5. package/dist/index.d.ts +1 -1
  6. package/dist/index.js +1 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/project/browser-bundle.d.ts +3 -0
  9. package/dist/project/browser-bundle.js +2 -0
  10. package/dist/project/browser-bundle.js.map +1 -1
  11. package/dist/project/browser-host.js +2 -1
  12. package/dist/project/browser-host.js.map +1 -1
  13. package/dist/project/browser-modules.js +14 -4
  14. package/dist/project/browser-modules.js.map +1 -1
  15. package/dist/project/browser-shards.d.ts +2 -23
  16. package/dist/project/browser-shards.js +2 -8
  17. package/dist/project/browser-shards.js.map +1 -1
  18. package/dist/project/browser-tab-protocol.d.ts +30 -0
  19. package/dist/project/browser-tab-protocol.js +9 -0
  20. package/dist/project/browser-tab-protocol.js.map +1 -0
  21. package/dist/project/browser-tabs.js +1 -1
  22. package/dist/project/browser-tabs.js.map +1 -1
  23. package/dist/project/build.js +1 -0
  24. package/dist/project/build.js.map +1 -1
  25. package/dist/project/lower-await.js +22 -2
  26. package/dist/project/lower-await.js.map +1 -1
  27. package/dist/project/module-rules.d.ts +26 -0
  28. package/dist/project/module-rules.js +131 -0
  29. package/dist/project/module-rules.js.map +1 -0
  30. package/dist/project/module-specifiers.d.ts +14 -0
  31. package/dist/project/module-specifiers.js +302 -0
  32. package/dist/project/module-specifiers.js.map +1 -0
  33. package/dist/project/node-load.js +2 -1
  34. package/dist/project/node-load.js.map +1 -1
  35. package/dist/project/node-project.d.ts +3 -0
  36. package/dist/project/node-project.js +5 -1
  37. package/dist/project/node-project.js.map +1 -1
  38. package/dist/project/wrangler.d.ts +27 -3
  39. package/dist/project/wrangler.js +45 -22
  40. package/dist/project/wrangler.js.map +1 -1
  41. package/dist/tabs.d.ts +1 -0
  42. package/dist/tabs.js +8 -0
  43. package/dist/tabs.js.map +1 -0
  44. package/package.json +5 -1
@@ -1 +1 @@
1
- {"version":3,"file":"browser-shards.js","sourceRoot":"","sources":["../../src/project/browser-shards.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * One project in several browser workers, so that its cells run in parallel threads. Each worker\n * hosts the project with `browserProjectRuntime` and its own OPFS pool, owns the cells that\n * `shardOf(id, shards)` gives it, and reaches every other cell through the worker that owns it\n * over a MessagePort. Any worker takes ingress; the page spreads requests over them.\n *\n * page: startProjectShards({ shards, spawn, config, code, name }) → { fetch, close }\n * worker: serveProjectShard({ sqlite3 })\n *\n * Placement is fixed by the cell id (no rebalancing), and a closed page takes its workers along:\n * for cells that must outlive a tab, use a fleet bucket (`bucket`), as for one worker.\n */\nimport {\n serveHttpInWorker,\n type WorkerHttpService,\n webSocketUpgradeResponse,\n} from \"@statewalker/webrun-http-browser/sw\";\nimport { withUrl } from \"../core/request-body.js\";\nimport type { CellRuntimeOptions } from \"../core/runtime.js\";\nimport { shardOf } from \"../core/shard.js\";\nimport { cellsHttpHandler, type RemoteRuntime } from \"../transport/cells-http.js\";\nimport { H, keepUpgrade } from \"../transport/cells-link.js\";\nimport { connectRuntime, linkOverPort, serveRuntime } from \"../transport/port.js\";\nimport { CellsResponse, CfWebSocket, takeClientPort } from \"../ws/server.js\";\nimport {\n type BrowserBucket,\n type BrowserProjectOptions,\n browserProjectRuntime,\n} from \"./browser-host.js\";\n\nconst INIT = \"cellb:shard\";\nconst CLOSE = \"cellb:shard-close\";\n/**\n * A shard of a project shared by the tabs of an origin (`joinProjectShards`): it serves through\n * the ServiceWorker's router (webrun-http-browser's `serveHttpInWorker`), which the tab attaches\n * it to, and reaches the other shards through it.\n */\nexport const TAB_INIT = \"cellb:tab-shard\";\n/** The host calls between shards go to through the router: `http://cellb.internal/<project>/`. */\nexport const INTERNAL_ORIGIN = \"http://cellb.internal\";\n\n/** What a shard worker shared by tabs is told: no peers, it reaches them through the router. */\nexport interface TabShardInit {\n type: typeof TAB_INIT;\n name: string;\n shard: number;\n shards: number;\n config: BrowserProjectOptions[\"config\"];\n code: BrowserProjectOptions[\"code\"];\n assetFiles?: BrowserProjectOptions[\"assetFiles\"];\n /** The OpenAI-compatible endpoint behind the project's `ai` binding. */\n ai?: BrowserProjectOptions[\"ai\"];\n bucket?: BrowserBucket;\n pool: string;\n filesDir: string;\n}\n\n/** What a shard worker is told (the ports travel next to it). */\ninterface ShardInit {\n type: typeof INIT;\n shard: number;\n shards: number;\n config: BrowserProjectOptions[\"config\"];\n code: BrowserProjectOptions[\"code\"];\n assetFiles?: BrowserProjectOptions[\"assetFiles\"];\n /** The OpenAI-compatible endpoint behind the project's `ai` binding. */\n ai?: BrowserProjectOptions[\"ai\"];\n bucket?: BrowserBucket;\n pool: string;\n filesDir: string;\n /** For ports[2..]: the shard each port links to (`link`) or is served to (`serve`). */\n peers: { shard: number; role: \"link\" | \"serve\" }[];\n}\n\n/**\n * The worker side: hosts one shard when a page says so — of `startProjectShards` (peers wired\n * directly) or of `joinProjectShards` (shared by the tabs, linked to the ServiceWorker's router).\n * Messages of other types are left to the worker's own listeners.\n */\nexport function serveProjectShard(opts: {\n /** An initialized SQLite WASM module, or a function that makes one. */\n sqlite3: unknown | (() => Promise<unknown>);\n /** `browserProjectRuntime`'s `isolateScript`. */\n isolateScript?: URL;\n}): void {\n const scope = globalThis as unknown as {\n addEventListener(type: \"message\", fn: (e: MessageEvent) => void): void;\n postMessage(message: unknown): void;\n };\n let host: Awaited<ReturnType<typeof browserProjectRuntime>> | undefined;\n let service: WorkerHttpService | undefined;\n const sqlite3 = () =>\n typeof opts.sqlite3 === \"function\"\n ? (opts.sqlite3 as () => Promise<unknown>)()\n : Promise.resolve(opts.sqlite3);\n scope.addEventListener(\"message\", async (e: MessageEvent) => {\n const type = (e.data as { type?: string } | undefined)?.type;\n if (![INIT, CLOSE, TAB_INIT].includes(type as string)) return;\n const reply = e.ports[0] as MessagePort;\n try {\n if (type === CLOSE) {\n try {\n // The cells move elsewhere: their sockets' clients reconnect there now.\n CfWebSocket.goAway();\n await host?.close();\n } finally {\n host = undefined;\n // The router sees this shard's owner gone (its owner lock), even if closing failed.\n await service?.close().catch(() => {});\n service = undefined;\n }\n return reply.postMessage({ ok: true });\n }\n if (type === TAB_INIT) {\n const init = e.data as TabShardInit;\n let ready!: (s: WorkerHttpService) => void;\n const serviceReady = new Promise<WorkerHttpService>((r) => (ready = r));\n host = await browserProjectRuntime({\n config: init.config,\n code: init.code,\n assetFiles: init.assetFiles,\n ai: init.ai,\n bucket: init.bucket,\n sqlite3: await sqlite3(),\n pool: init.pool,\n filesDir: init.filesDir,\n isolateScript: opts.isolateScript,\n route: throughRouter(init, serviceReady),\n });\n // Served through the ServiceWorker's router, which the tab attaches this worker to. The\n // package keeps the link: an owner lock the router watches, re-linking after a restart,\n // keep-alive while calls are in flight.\n const handler = cellsHttpHandler(host.runtime, { passUpgrades: true });\n service = serveHttpInWorker(async (req) => upgradeOverPort(await handler(req)));\n ready(service);\n return reply.postMessage({ ok: true, unsupported: host.unsupported });\n }\n const init = e.data as ShardInit;\n const links = new Map<number, (req: Request) => Promise<Response>>();\n const served: MessagePort[] = [e.ports[1] as MessagePort]; // ingress from the page\n for (const [i, peer] of init.peers.entries()) {\n const port = e.ports[i + 2] as MessagePort;\n if (peer.role === \"link\") links.set(peer.shard, (await linkOverPort(port)).send);\n else served.push(port);\n }\n host = await browserProjectRuntime({\n config: init.config,\n code: init.code,\n assetFiles: init.assetFiles,\n ai: init.ai,\n bucket: init.bucket,\n sqlite3: await sqlite3(),\n pool: init.pool,\n filesDir: init.filesDir,\n isolateScript: opts.isolateScript,\n route: (_key, id) => {\n const owner = shardOf(id.toString(), init.shards);\n return owner === init.shard ? undefined : links.get(owner);\n },\n });\n for (const port of served) await serveRuntime(port, host.runtime);\n reply.postMessage({ ok: true, unsupported: host.unsupported });\n } catch (err) {\n reply.postMessage({ ok: false, error: String((err as Error)?.stack ?? err) });\n }\n });\n}\n\n/**\n * A 101 with a Workers WebSocket, as the ServiceWorker's router hands sockets over: the client\n * end's port in webrun-http-browser's 101.\n */\nfunction upgradeOverPort(res: Response): Response {\n const ws = (res as Response & { webSocket?: CfWebSocket | null }).webSocket;\n if (res.status !== 101 || !ws) return res;\n return webSocketUpgradeResponse(\n takeClientPort(ws),\n res.headers.get(\"Sec-WebSocket-Protocol\") ?? \"\",\n );\n}\n\n/**\n * The cells of other shards, through the ServiceWorker's router: a call goes to\n * `http://cellb.internal/<project>/` (the router's key for the project) naming its shard, with the\n * url it was made with in `H.url`; a socket opens through the router the same way.\n */\nfunction throughRouter(\n init: { name: string; shard: number; shards: number },\n service: Promise<WorkerHttpService>,\n): NonNullable<CellRuntimeOptions[\"route\"]> {\n const target = `${INTERNAL_ORIGIN}/${encodeURIComponent(init.name)}/`;\n return (_key, id) => {\n const owner = shardOf(id.toString(), init.shards);\n if (owner === init.shard) return undefined;\n // `postVia` (the runtime's) adds the scheme header and rethrows error responses.\n return async (req) => {\n const svc = await service;\n if (req.headers.get(\"upgrade\")?.toLowerCase() === \"websocket\") {\n const protocols = (req.headers.get(\"sec-websocket-protocol\") ?? \"\")\n .split(\",\")\n .map((p) => p.trim())\n .filter(Boolean);\n const headers: [string, string][] = [];\n for (const [k, v] of req.headers) if (k.startsWith(\"x-cellb\")) headers.push([k, v]);\n headers.push([H.shard, String(owner)], [H.url, req.url]);\n const { port, protocol } = await svc.connectWebSocket(target, protocols, headers);\n return new CellsResponse(null, {\n status: 101,\n webSocket: new CfWebSocket(port),\n headers: protocol ? { \"Sec-WebSocket-Protocol\": protocol } : {},\n });\n }\n const moved = await withUrl(req, target);\n const headers = new Headers(req.headers);\n headers.set(H.shard, String(owner));\n headers.set(H.url, req.url);\n try {\n return await svc.fetch(keepUpgrade(req, new Request(moved, { headers })));\n } catch (err) {\n // The words Worker code has always seen for it (CellRouter's), for a call the\n // ServiceWorker lost in flight only: a call that never left (no link, the handler\n // closed) keeps the package's words, as it was certainly not applied.\n if (\n err instanceof Error &&\n err.name === \"LinkLostError\" &&\n err.message.startsWith(\"The ServiceWorker was lost while this call was in flight\")\n )\n throw new Error(\n \"The router was lost while this call was in flight; it may or may not have been applied\",\n );\n throw err;\n }\n };\n };\n}\n\nexport interface ProjectShards {\n /** Ingress: a request to the project's Worker, in the next shard (round robin). */\n fetch(req: Request): Promise<Response>;\n /** The shards' runtimes, by shard number. */\n readonly shards: RemoteRuntime[];\n /** Configuration entries the runtime does not support (as `browserProjectRuntime` reports). */\n readonly unsupported: string[];\n /** Closes every shard's runtime (releasing bucket leases), then its worker. */\n close(): Promise<void>;\n}\n\n/** The page side: starts `shards` workers that each run `serveProjectShard`, wired together. */\nexport async function startProjectShards(opts: {\n shards: number;\n /** Starts one worker whose script calls `serveProjectShard`. */\n spawn: (shard: number) => Worker;\n config: BrowserProjectOptions[\"config\"];\n code: BrowserProjectOptions[\"code\"];\n assetFiles?: BrowserProjectOptions[\"assetFiles\"];\n /** The OpenAI-compatible endpoint behind the project's `ai` binding. */\n ai?: BrowserProjectOptions[\"ai\"];\n /** Each shard is its own fleet node, named `<node>-s<shard>`. */\n bucket?: BrowserBucket;\n /** Prefix of the shards' OPFS pools and files directories (`<name>-<shard>`). */\n name: string;\n}): Promise<ProjectShards> {\n const workers = Array.from({ length: opts.shards }, (_, i) => opts.spawn(i));\n const ask = (w: Worker, data: unknown, ports: MessagePort[] = []) =>\n new Promise<{ ok: boolean; error?: string; unsupported?: string[] }>((resolve) => {\n const { port1, port2 } = new MessageChannel();\n port1.onmessage = (e) => {\n port1.close();\n resolve(e.data);\n };\n w.postMessage(data, [port2, ...ports]);\n });\n // A channel between every two shards: one end links (sends to), the other is served.\n const wiring = workers.map(() => ({\n peers: [] as ShardInit[\"peers\"],\n ports: [] as MessagePort[],\n }));\n for (let i = 0; i < opts.shards; i++)\n for (let j = 0; j < opts.shards; j++) {\n if (i === j) continue;\n const { port1, port2 } = new MessageChannel();\n wiring[i].peers.push({ shard: j, role: \"link\" });\n wiring[i].ports.push(port1);\n wiring[j].peers.push({ shard: i, role: \"serve\" });\n wiring[j].ports.push(port2);\n }\n const ingress = workers.map(() => new MessageChannel());\n try {\n const started = await Promise.all(\n workers.map((w, i) =>\n ask(\n w,\n {\n type: INIT,\n shard: i,\n shards: opts.shards,\n config: opts.config,\n code: opts.code,\n assetFiles: opts.assetFiles,\n ai: opts.ai,\n bucket: opts.bucket && { ...opts.bucket, node: `${opts.bucket.node}-s${i}` },\n pool: `${opts.name}-${i}`,\n filesDir: `${opts.name}-files-${i}`,\n peers: wiring[i].peers,\n } satisfies ShardInit,\n [ingress[i].port2, ...wiring[i].ports],\n ),\n ),\n );\n const failed = started.find((r) => !r.ok);\n if (failed) throw new Error(`a project shard did not start: ${failed.error}`);\n const remotes = await Promise.all(ingress.map((c) => connectRuntime(c.port1)));\n let next = 0;\n return {\n fetch: (req) => remotes[next++ % remotes.length].fetch(req),\n shards: remotes,\n unsupported: started[0].unsupported ?? [],\n async close() {\n await Promise.all(remotes.map((r) => r.close()));\n await Promise.all(workers.map((w) => ask(w, { type: CLOSE })));\n for (const w of workers) w.terminate();\n },\n };\n } catch (err) {\n for (const w of workers) w.terminate();\n throw err;\n }\n}\n"]}
1
+ {"version":3,"file":"browser-shards.js","sourceRoot":"","sources":["../../src/project/browser-shards.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * One project in several browser workers, so that its cells run in parallel threads. Each worker\n * hosts the project with `browserProjectRuntime` and its own OPFS pool, owns the cells that\n * `shardOf(id, shards)` gives it, and reaches every other cell through the worker that owns it\n * over a MessagePort. Any worker takes ingress; the page spreads requests over them.\n *\n * page: startProjectShards({ shards, spawn, config, code, name }) → { fetch, close }\n * worker: serveProjectShard({ sqlite3 })\n *\n * Placement is fixed by the cell id (no rebalancing), and a closed page takes its workers along:\n * for cells that must outlive a tab, use a fleet bucket (`bucket`), as for one worker.\n */\nimport {\n serveHttpInWorker,\n type WorkerHttpService,\n webSocketUpgradeResponse,\n} from \"@statewalker/webrun-http-browser/sw\";\nimport { withUrl } from \"../core/request-body.js\";\nimport type { CellRuntimeOptions } from \"../core/runtime.js\";\nimport { shardOf } from \"../core/shard.js\";\nimport { cellsHttpHandler, type RemoteRuntime } from \"../transport/cells-http.js\";\nimport { H, keepUpgrade } from \"../transport/cells-link.js\";\nimport { connectRuntime, linkOverPort, serveRuntime } from \"../transport/port.js\";\nimport { CellsResponse, CfWebSocket, takeClientPort } from \"../ws/server.js\";\nimport {\n type BrowserBucket,\n type BrowserProjectOptions,\n browserProjectRuntime,\n} from \"./browser-host.js\";\nimport { INTERNAL_ORIGIN, TAB_INIT, type TabShardInit } from \"./browser-tab-protocol.js\";\n\nexport { INTERNAL_ORIGIN, TAB_INIT, type TabShardInit };\n\nconst INIT = \"cellb:shard\";\nconst CLOSE = \"cellb:shard-close\";\n/** What a shard worker is told (the ports travel next to it). */\ninterface ShardInit {\n type: typeof INIT;\n shard: number;\n shards: number;\n config: BrowserProjectOptions[\"config\"];\n code: BrowserProjectOptions[\"code\"];\n assetFiles?: BrowserProjectOptions[\"assetFiles\"];\n /** The OpenAI-compatible endpoint behind the project's `ai` binding. */\n ai?: BrowserProjectOptions[\"ai\"];\n bucket?: BrowserBucket;\n pool: string;\n filesDir: string;\n /** For ports[2..]: the shard each port links to (`link`) or is served to (`serve`). */\n peers: { shard: number; role: \"link\" | \"serve\" }[];\n}\n\n/**\n * The worker side: hosts one shard when a page says so — of `startProjectShards` (peers wired\n * directly) or of `joinProjectShards` (shared by the tabs, linked to the ServiceWorker's router).\n * Messages of other types are left to the worker's own listeners.\n */\nexport function serveProjectShard(opts: {\n /** An initialized SQLite WASM module, or a function that makes one. */\n sqlite3: unknown | (() => Promise<unknown>);\n /** `browserProjectRuntime`'s `isolateScript`. */\n isolateScript?: URL;\n}): void {\n const scope = globalThis as unknown as {\n addEventListener(type: \"message\", fn: (e: MessageEvent) => void): void;\n postMessage(message: unknown): void;\n };\n let host: Awaited<ReturnType<typeof browserProjectRuntime>> | undefined;\n let service: WorkerHttpService | undefined;\n const sqlite3 = () =>\n typeof opts.sqlite3 === \"function\"\n ? (opts.sqlite3 as () => Promise<unknown>)()\n : Promise.resolve(opts.sqlite3);\n scope.addEventListener(\"message\", async (e: MessageEvent) => {\n const type = (e.data as { type?: string } | undefined)?.type;\n if (![INIT, CLOSE, TAB_INIT].includes(type as string)) return;\n const reply = e.ports[0] as MessagePort;\n try {\n if (type === CLOSE) {\n try {\n // The cells move elsewhere: their sockets' clients reconnect there now.\n CfWebSocket.goAway();\n await host?.close();\n } finally {\n host = undefined;\n // The router sees this shard's owner gone (its owner lock), even if closing failed.\n await service?.close().catch(() => {});\n service = undefined;\n }\n return reply.postMessage({ ok: true });\n }\n if (type === TAB_INIT) {\n const init = e.data as TabShardInit;\n let ready!: (s: WorkerHttpService) => void;\n const serviceReady = new Promise<WorkerHttpService>((r) => (ready = r));\n host = await browserProjectRuntime({\n config: init.config,\n code: init.code,\n assetFiles: init.assetFiles,\n ai: init.ai,\n bucket: init.bucket,\n sqlite3: await sqlite3(),\n pool: init.pool,\n filesDir: init.filesDir,\n isolateScript: opts.isolateScript,\n route: throughRouter(init, serviceReady),\n });\n // Served through the ServiceWorker's router, which the tab attaches this worker to. The\n // package keeps the link: an owner lock the router watches, re-linking after a restart,\n // keep-alive while calls are in flight.\n const handler = cellsHttpHandler(host.runtime, { passUpgrades: true });\n service = serveHttpInWorker(async (req) => upgradeOverPort(await handler(req)));\n ready(service);\n return reply.postMessage({ ok: true, unsupported: host.unsupported });\n }\n const init = e.data as ShardInit;\n const links = new Map<number, (req: Request) => Promise<Response>>();\n const served: MessagePort[] = [e.ports[1] as MessagePort]; // ingress from the page\n for (const [i, peer] of init.peers.entries()) {\n const port = e.ports[i + 2] as MessagePort;\n if (peer.role === \"link\") links.set(peer.shard, (await linkOverPort(port)).send);\n else served.push(port);\n }\n host = await browserProjectRuntime({\n config: init.config,\n code: init.code,\n assetFiles: init.assetFiles,\n ai: init.ai,\n bucket: init.bucket,\n sqlite3: await sqlite3(),\n pool: init.pool,\n filesDir: init.filesDir,\n isolateScript: opts.isolateScript,\n route: (_key, id) => {\n const owner = shardOf(id.toString(), init.shards);\n return owner === init.shard ? undefined : links.get(owner);\n },\n });\n for (const port of served) await serveRuntime(port, host.runtime);\n reply.postMessage({ ok: true, unsupported: host.unsupported });\n } catch (err) {\n reply.postMessage({ ok: false, error: String((err as Error)?.stack ?? err) });\n }\n });\n}\n\n/**\n * A 101 with a Workers WebSocket, as the ServiceWorker's router hands sockets over: the client\n * end's port in webrun-http-browser's 101.\n */\nfunction upgradeOverPort(res: Response): Response {\n const ws = (res as Response & { webSocket?: CfWebSocket | null }).webSocket;\n if (res.status !== 101 || !ws) return res;\n return webSocketUpgradeResponse(\n takeClientPort(ws),\n res.headers.get(\"Sec-WebSocket-Protocol\") ?? \"\",\n );\n}\n\n/**\n * The cells of other shards, through the ServiceWorker's router: a call goes to\n * `http://cellb.internal/<project>/` (the router's key for the project) naming its shard, with the\n * url it was made with in `H.url`; a socket opens through the router the same way.\n */\nfunction throughRouter(\n init: { name: string; shard: number; shards: number },\n service: Promise<WorkerHttpService>,\n): NonNullable<CellRuntimeOptions[\"route\"]> {\n const target = `${INTERNAL_ORIGIN}/${encodeURIComponent(init.name)}/`;\n return (_key, id) => {\n const owner = shardOf(id.toString(), init.shards);\n if (owner === init.shard) return undefined;\n // `postVia` (the runtime's) adds the scheme header and rethrows error responses.\n return async (req) => {\n const svc = await service;\n if (req.headers.get(\"upgrade\")?.toLowerCase() === \"websocket\") {\n const protocols = (req.headers.get(\"sec-websocket-protocol\") ?? \"\")\n .split(\",\")\n .map((p) => p.trim())\n .filter(Boolean);\n const headers: [string, string][] = [];\n for (const [k, v] of req.headers) if (k.startsWith(\"x-cellb\")) headers.push([k, v]);\n headers.push([H.shard, String(owner)], [H.url, req.url]);\n const { port, protocol } = await svc.connectWebSocket(target, protocols, headers);\n return new CellsResponse(null, {\n status: 101,\n webSocket: new CfWebSocket(port),\n headers: protocol ? { \"Sec-WebSocket-Protocol\": protocol } : {},\n });\n }\n const moved = await withUrl(req, target);\n const headers = new Headers(req.headers);\n headers.set(H.shard, String(owner));\n headers.set(H.url, req.url);\n try {\n return await svc.fetch(keepUpgrade(req, new Request(moved, { headers })));\n } catch (err) {\n // The words Worker code has always seen for it (CellRouter's), for a call the\n // ServiceWorker lost in flight only: a call that never left (no link, the handler\n // closed) keeps the package's words, as it was certainly not applied.\n if (\n err instanceof Error &&\n err.name === \"LinkLostError\" &&\n err.message.startsWith(\"The ServiceWorker was lost while this call was in flight\")\n )\n throw new Error(\n \"The router was lost while this call was in flight; it may or may not have been applied\",\n );\n throw err;\n }\n };\n };\n}\n\nexport interface ProjectShards {\n /** Ingress: a request to the project's Worker, in the next shard (round robin). */\n fetch(req: Request): Promise<Response>;\n /** The shards' runtimes, by shard number. */\n readonly shards: RemoteRuntime[];\n /** Configuration entries the runtime does not support (as `browserProjectRuntime` reports). */\n readonly unsupported: string[];\n /** Closes every shard's runtime (releasing bucket leases), then its worker. */\n close(): Promise<void>;\n}\n\n/** The page side: starts `shards` workers that each run `serveProjectShard`, wired together. */\nexport async function startProjectShards(opts: {\n shards: number;\n /** Starts one worker whose script calls `serveProjectShard`. */\n spawn: (shard: number) => Worker;\n config: BrowserProjectOptions[\"config\"];\n code: BrowserProjectOptions[\"code\"];\n assetFiles?: BrowserProjectOptions[\"assetFiles\"];\n /** The OpenAI-compatible endpoint behind the project's `ai` binding. */\n ai?: BrowserProjectOptions[\"ai\"];\n /** Each shard is its own fleet node, named `<node>-s<shard>`. */\n bucket?: BrowserBucket;\n /** Prefix of the shards' OPFS pools and files directories (`<name>-<shard>`). */\n name: string;\n}): Promise<ProjectShards> {\n const workers = Array.from({ length: opts.shards }, (_, i) => opts.spawn(i));\n const ask = (w: Worker, data: unknown, ports: MessagePort[] = []) =>\n new Promise<{ ok: boolean; error?: string; unsupported?: string[] }>((resolve) => {\n const { port1, port2 } = new MessageChannel();\n port1.onmessage = (e) => {\n port1.close();\n resolve(e.data);\n };\n w.postMessage(data, [port2, ...ports]);\n });\n // A channel between every two shards: one end links (sends to), the other is served.\n const wiring = workers.map(() => ({\n peers: [] as ShardInit[\"peers\"],\n ports: [] as MessagePort[],\n }));\n for (let i = 0; i < opts.shards; i++)\n for (let j = 0; j < opts.shards; j++) {\n if (i === j) continue;\n const { port1, port2 } = new MessageChannel();\n wiring[i].peers.push({ shard: j, role: \"link\" });\n wiring[i].ports.push(port1);\n wiring[j].peers.push({ shard: i, role: \"serve\" });\n wiring[j].ports.push(port2);\n }\n const ingress = workers.map(() => new MessageChannel());\n try {\n const started = await Promise.all(\n workers.map((w, i) =>\n ask(\n w,\n {\n type: INIT,\n shard: i,\n shards: opts.shards,\n config: opts.config,\n code: opts.code,\n assetFiles: opts.assetFiles,\n ai: opts.ai,\n bucket: opts.bucket && { ...opts.bucket, node: `${opts.bucket.node}-s${i}` },\n pool: `${opts.name}-${i}`,\n filesDir: `${opts.name}-files-${i}`,\n peers: wiring[i].peers,\n } satisfies ShardInit,\n [ingress[i].port2, ...wiring[i].ports],\n ),\n ),\n );\n const failed = started.find((r) => !r.ok);\n if (failed) throw new Error(`a project shard did not start: ${failed.error}`);\n const remotes = await Promise.all(ingress.map((c) => connectRuntime(c.port1)));\n let next = 0;\n return {\n fetch: (req) => remotes[next++ % remotes.length].fetch(req),\n shards: remotes,\n unsupported: started[0].unsupported ?? [],\n async close() {\n await Promise.all(remotes.map((r) => r.close()));\n await Promise.all(workers.map((w) => ask(w, { type: CLOSE })));\n for (const w of workers) w.terminate();\n },\n };\n } catch (err) {\n for (const w of workers) w.terminate();\n throw err;\n }\n}\n"]}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * What a tab and a shard worker it starts agree on (`joinProjectShards` → `serveProjectShard`).
3
+ * Its own module, with type-only imports, so that the tab side and the ServiceWorker do not
4
+ * import the shard's runtime (browser-shards.ts → browser-host.ts and every binding) for two
5
+ * constants.
6
+ */
7
+ import type { BrowserBucket, BrowserProjectOptions } from "./browser-host.js";
8
+ /**
9
+ * A shard of a project shared by the tabs of an origin (`joinProjectShards`): it serves through
10
+ * the ServiceWorker's router (webrun-http-browser's `serveHttpInWorker`), which the tab attaches
11
+ * it to, and reaches the other shards through it.
12
+ */
13
+ export declare const TAB_INIT = "cellb:tab-shard";
14
+ /** The host calls between shards go to through the router: `http://cellb.internal/<project>/`. */
15
+ export declare const INTERNAL_ORIGIN = "http://cellb.internal";
16
+ /** What a shard worker shared by tabs is told: no peers, it reaches them through the router. */
17
+ export interface TabShardInit {
18
+ type: typeof TAB_INIT;
19
+ name: string;
20
+ shard: number;
21
+ shards: number;
22
+ config: BrowserProjectOptions["config"];
23
+ code: BrowserProjectOptions["code"];
24
+ assetFiles?: BrowserProjectOptions["assetFiles"];
25
+ /** The OpenAI-compatible endpoint behind the project's `ai` binding. */
26
+ ai?: BrowserProjectOptions["ai"];
27
+ bucket?: BrowserBucket;
28
+ pool: string;
29
+ filesDir: string;
30
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * A shard of a project shared by the tabs of an origin (`joinProjectShards`): it serves through
3
+ * the ServiceWorker's router (webrun-http-browser's `serveHttpInWorker`), which the tab attaches
4
+ * it to, and reaches the other shards through it.
5
+ */
6
+ export const TAB_INIT = "cellb:tab-shard";
7
+ /** The host calls between shards go to through the router: `http://cellb.internal/<project>/`. */
8
+ export const INTERNAL_ORIGIN = "http://cellb.internal";
9
+ //# sourceMappingURL=browser-tab-protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-tab-protocol.js","sourceRoot":"","sources":["../../src/project/browser-tab-protocol.ts"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,iBAAiB,CAAC;AAC1C,kGAAkG;AAClG,MAAM,CAAC,MAAM,eAAe,GAAG,uBAAuB,CAAC","sourcesContent":["/**\n * What a tab and a shard worker it starts agree on (`joinProjectShards` → `serveProjectShard`).\n * Its own module, with type-only imports, so that the tab side and the ServiceWorker do not\n * import the shard's runtime (browser-shards.ts → browser-host.ts and every binding) for two\n * constants.\n */\nimport type { BrowserBucket, BrowserProjectOptions } from \"./browser-host.js\";\n\n/**\n * A shard of a project shared by the tabs of an origin (`joinProjectShards`): it serves through\n * the ServiceWorker's router (webrun-http-browser's `serveHttpInWorker`), which the tab attaches\n * it to, and reaches the other shards through it.\n */\nexport const TAB_INIT = \"cellb:tab-shard\";\n/** The host calls between shards go to through the router: `http://cellb.internal/<project>/`. */\nexport const INTERNAL_ORIGIN = \"http://cellb.internal\";\n\n/** What a shard worker shared by tabs is told: no peers, it reaches them through the router. */\nexport interface TabShardInit {\n type: typeof TAB_INIT;\n name: string;\n shard: number;\n shards: number;\n config: BrowserProjectOptions[\"config\"];\n code: BrowserProjectOptions[\"code\"];\n assetFiles?: BrowserProjectOptions[\"assetFiles\"];\n /** The OpenAI-compatible endpoint behind the project's `ai` binding. */\n ai?: BrowserProjectOptions[\"ai\"];\n bucket?: BrowserBucket;\n pool: string;\n filesDir: string;\n}\n"]}
@@ -22,7 +22,7 @@ import { errorResponse } from "../transport/cells-http.js";
22
22
  import { H } from "../transport/cells-link.js";
23
23
  import { SW_SOCKET } from "../ws/sw-connector.js";
24
24
  import { applyWorkerCookies, withPageCookies } from "./browser-cookies.js";
25
- import { INTERNAL_ORIGIN, TAB_INIT } from "./browser-shards.js";
25
+ import { INTERNAL_ORIGIN, TAB_INIT } from "./browser-tab-protocol.js";
26
26
  /** The ServiceWorker asks a project's tabs to attach their shards again (a host page's wait). */
27
27
  const NEED_LINKS = "cellb:need-links";
28
28
  /** A page opens a socket (`serviceWorkerConnector`). */
@@ -1 +1 @@
1
- {"version":3,"file":"browser-tabs.js","sourceRoot":"","sources":["../../src/project/browser-tabs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAGL,aAAa,EACb,aAAa,EACb,gBAAgB,GAEjB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,CAAC,EAAE,MAAM,4BAA4B,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE3E,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAqB,MAAM,qBAAqB,CAAC;AAEnF,iGAAiG;AACjG,MAAM,UAAU,GAAG,kBAAkB,CAAC;AACtC,wDAAwD;AACxD,MAAM,MAAM,GAAG,SAAS,CAAC;AAEzB;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,IAAc;IACtD,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IACnC,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IAChC,OAAO,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;AACvC,CAAC;AAiDD,6FAA6F;AAC7F,MAAM,OAAO,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,SAAS,KAAK,EAAE,CAAC;AAEpD,0EAA0E;AAC1E,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAwB;IAC9D,MAAM,MAAM,GAAG,SAAS,IAAI,CAAC,IAAI,EAAE,CAAC;IACpC,MAAM,KAAK,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC;IACnF,MAAM,YAAY,GAAG,GAAG,MAAM,QAAQ,KAAK,EAAE,CAAC;IAC9C,IAAI,KAAkB,CAAC;IACvB,MAAM,IAAI,OAAO,CAAO,CAAC,IAAI,EAAE,EAAE;QAC/B,KAAK,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,EAAE;YAC9C,IAAI,EAAE,CAAC;YACP,OAAO,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC,GAAG,MAAM,OAAO,CAAC,CAAC;IACvD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAgB,CAAC;IACrC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,MAAM,IAAI,GAAG,KAAK,IAAuB,EAAE;QACzC,MAAM,EAAE,IAAI,EAAE,KAAK,GAAG,EAAE,EAAE,GAAG,MAAM,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAC3D,MAAM,GAAG,GAAG,KAAK;aACd,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;aACxB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,CAAC;aAC7C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QAChD,OAAO,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,KAAK,CAAC,CAAC;IACrD,CAAC,CAAC;IAEF,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,IAAa,EAAE,KAAK,GAAkB,EAAE,EAAE,EAAE,CAClE,IAAI,OAAO,CAIR,CAAC,OAAO,EAAE,EAAE;QACb,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,IAAI,cAAc,EAAE,CAAC;QAC9C,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,EAAE,EAAE;YACtB,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC,CAAC;QACF,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEL,6FAA6F;IAC7F,4FAA4F;IAC5F,qFAAqF;IACrF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;IAC1C,4FAA4F;IAC5F,2EAA2E;IAC3E,MAAM,YAAY,GAAG,CAAC,MAAM,SAAS,CAAC,aAAa,CAAC,gBAAgB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CACjF,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CACrD,CAAC;IACF,IAAI,CAAC,YAAY;QACf,MAAM,IAAI,KAAK,CAAC,kDAAkD,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;IACxF,MAAM,OAAO,GAAG,IAAI,aAAa,CAAC;QAChC,GAAG,EAAE,IAAI,CAAC,IAAI;QACd,YAAY;QACZ,EAAE,EAAE,OAAO,KAAK,EAAE;KACnB,CAAC,CAAC;IACH,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACtB,MAAM,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;IAE5C,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAE1E,gFAAgF;IAChF,MAAM,IAAI,GAAG,CAAC,KAAa,EAAE,EAAE;QAC7B,MAAM,CAAC,GAAS,EAAE,IAAI,EAAE,IAAI,eAAe,EAAE,EAAE,CAAC;QAChD,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QACnB,CAAC,CAAC,OAAO,GAAG,SAAS,CAAC,KAAK;aACxB,OAAO,CAAC,GAAG,MAAM,UAAU,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,KAAK,IAAI,EAAE;YACzE,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC5B,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;YACb,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,CAAC,EAAE;oBAC3B,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,KAAK;oBACL,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,UAAU,EAAE,IAAI,CAAC,UAAU;oBAC3B,EAAE,EAAE,IAAI,CAAC,EAAE;oBACX,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,KAAK,EAAE,EAAE;oBAChF,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,UAAU,KAAK,EAAE;oBACnC,QAAQ,EAAE,GAAG,IAAI,CAAC,IAAI,UAAU,KAAK,EAAE;iBACjB,CAAC,CAAC;gBAC1B,IAAI,CAAC,OAAO,CAAC,EAAE;oBAAE,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;gBAChD,oFAAoF;gBACpF,wEAAwE;gBACxE,IAAI,OAAO,CAAC,WAAW,EAAE,MAAM;oBAC7B,OAAO,CAAC,IAAI,CACV,kBAAkB,IAAI,CAAC,IAAI,UAAU,KAAK,kBAAkB,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC7F,CAAC;gBACJ,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;oBAC3B,KAAK,CAAC,GAAG,CACP,KAAK,EACL,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC,EAAE;wBAC5B,GAAG,EAAE,IAAI,CAAC,IAAI;wBACd,EAAE,EAAE,OAAO,CAAC,KAAK,CAAC;wBAClB,IAAI,EAAE,EAAE,KAAK,EAAE;qBAChB,CAAC,CACH,CAAC;oBACF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;oBACnB,OAAO,EAAE,CAAC;oBACV,MAAM,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,CAC5B,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CACjF,CAAC;gBACJ,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,oFAAoF;gBACpF,sEAAsE;gBACtE,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBAC9B,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACpB,IAAI,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;oBAC5B,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;gBAClE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACtB,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;gBAC5D,CAAC,CAAC,SAAS,EAAE,CAAC;gBACd,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACb,+EAA+E;YAC/E,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO;gBACxB,OAAO,CAAC,KAAK,CACX,UAAU,IAAI,CAAC,IAAI,UAAU,KAAK,YAAa,GAAa,EAAE,OAAO,IAAI,GAAG,EAAE,CAC/E,CAAC;QACN,CAAC,CAAC;aACD,OAAO,CAAC,GAAG,EAAE;YACZ,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC;gBAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;IAEF,IAAI,SAAoC,CAAC;IACzC,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,oEAAoE;IACpE,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE;QACzB,IAAI,SAAS,EAAE,CAAC;YACd,KAAK,GAAG,IAAI,CAAC;YACb,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,SAAS,GAAG,CAAC,KAAK,IAAI,EAAE;YACtB,GAAG,CAAC;gBACF,KAAK,GAAG,KAAK,CAAC;gBACd,IAAI,MAAM;oBAAE,OAAO;gBACnB,MAAM,OAAO,GAAG,MAAM,IAAI,EAAE,CAAC;gBAC7B,4EAA4E;gBAC5E,IAAI,MAAM;oBAAE,OAAO;gBACnB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;oBACjD,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,KAAK,CAAC;oBAClD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;oBAC1B,IAAI,IAAI,IAAI,CAAC,CAAC;wBAAE,IAAI,CAAC,KAAK,CAAC,CAAC;yBACvB,IAAI,CAAC,IAAI,IAAI,CAAC;wBAAE,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACtC,CAAC;YACH,CAAC,QAAQ,KAAK,EAAE;QAClB,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC;QAC5C,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;IAEF,OAAO,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC,KAAK,OAAO,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,EAAE,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC;IACtE,MAAM,IAAI,GAAG,CAAC,CAAe,EAAE,EAAE;QAC/B,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO;QACtF,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC;IACF,SAAS,CAAC,aAAa,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC1D,OAAO,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACvC,MAAM,OAAO,EAAE,CAAC;IAEhB,OAAO;QACL,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;QAC/C,IAAI;QACJ,KAAK,CAAC,KAAK;YACT,MAAM,GAAG,IAAI,CAAC;YACd,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,SAAS,CAAC,aAAa,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YAC7D,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YACpC,KAAK,MAAM,CAAC,IAAI,QAAQ;gBAAE,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YACzC,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YAClD,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACrC,KAAK,EAAE,CAAC;YACR,OAAO,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YACrC,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;KACF,CAAC;AACJ,CAAC;AAYD;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAClC,KAAyB,EACzB,IAsBC;IAED,MAAM,EAAE,GAAG,KAA4C,CAAC;IACxD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC;IAC/E,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,CAAC;IAE1C,4DAA4D;IAC5D,MAAM,MAAM,GAAG,CAAC,GAAQ,EAAE,EAAE,CAC1B,CAAC,CAAC,IAAI,CAAC,IAAI;QACX,GAAG,CAAC,MAAM,KAAK,EAAE,CAAC,QAAQ,CAAC,MAAM;QACjC,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC;QAC9B,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAEzE;;;;OAIG;IACH,MAAM,KAAK,GAAG,CAAC,GAAQ,EAA8D,EAAE;QACrF,IAAI,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC,GAAG,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QAC9F,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,SAAS,CAAC;QAC1F,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAChC,MAAM,GAAG,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;QACrC,OAAO,IAAI;YACT,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,GAAG,EAAE,EAAE;YAC9E,CAAC,CAAC,SAAS,CAAC;IAChB,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,CAAC,CAAc,EAAE,EAAE,CAAC,OAAQ,CAAC,CAAC,IAA4B,EAAE,KAAK,KAAK,QAAQ,CAAC;IAC/F,IAAI,EAAE,GAAG,CAAC,CAAC;IACX,MAAM,UAAU,GAAG,IAAI,gBAAgB,CAAC;QACtC,IAAI,EAAE,EAAE;QACR,WAAW,EAAE,KAAK;QAClB,eAAe,EAAE,IAAI,CAAC,eAAe,IAAI,MAAM;QAC/C,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACX,uDAAuD;YACvD,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAC/B,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBACxC,OAAO,IAAI,CAAC,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACrD,CAAC;YACD,OAAO,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;QAC1B,CAAC;QACD,0FAA0F;QAC1F,6FAA6F;QAC7F,yEAAyE;QACzE,KAAK,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;YACjC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACxC,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YAC3C,IAAI,KAAK,KAAK,IAAI;gBAChB,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAE,CAAC,CAAC,IAA0B,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YACnF,IAAI,CAAC,MAAM,CAAC,MAAM;gBAAE,OAAO,SAAS,CAAC;YACrC,MAAM,KAAK,GAAG,EAAE,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC;YACnC,IAAI,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACvC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;gBAC9C,IAAI,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ;oBAAE,IAAI,GAAG,CAAC,CAAC;YAC3C,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,0FAA0F;QAC1F,+BAA+B;QAC/B,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC;QACvD,yFAAyF;QACzF,aAAa,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAC/B,IAAI,KAAK,MAAM;YACb,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;YACxE,CAAC,CAAC,OAAO;KACd,CAAC,CAAC;IACH,UAAU,CAAC,KAAK,EAAE,CAAC;IAEnB,MAAM,MAAM,GAAG,CAAC,OAAgB,EAAE,OAAwB,EAAY,EAAE;QACtE,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,IAAI,GAAG,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,cAAc,KAAK,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC;QACpE,MAAM,KAAK,GACT,OAAO,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,CAAC,KAAK,YAAY,aAAa,IAAI,KAAK,KAAK,IAAI;YACjF,CAAC,CAAC,IAAI,mBAAmB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACxC,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS;gBAC1B,CAAC,CAAC,IAAI,KAAK,CAAC,GAAG,IAAI,2BAA2B,CAAC;gBAC/C,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM;oBACvB,CAAC,CAAC,IAAI,KAAK,CAAC,GAAG,IAAI,wBAAwB,CAAC;oBAC5C,CAAC,CAAE,OAAO,CAAC,KAAe,CAAC;QACnC,IAAI,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI;YAAE,OAAO,aAAa,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC3E,OAAO,IAAI,QAAQ,CAAC,UAAW,KAAe,EAAE,OAAO,IAAI,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IACvF,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,KAAK,EAAE,IAAY,EAAE,EAAE;QACzC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC,CAAC;QACzF,KAAK,MAAM,CAAC,IAAI,OAAO;YAAE,CAAC,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;IACrE,CAAC,CAAC;IAEF,sFAAsF;IACtF,MAAM,aAAa,GAAG,KAAK,EAAE,IAAY,EAAE,EAAU,EAAoB,EAAE;QACzE,MAAM,UAAU,CAAC,KAAK,CAAC;QACvB,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7D,IAAI,IAAI,EAAE;YAAE,OAAO,IAAI,CAAC;QACxB,KAAK,WAAW,CAAC,IAAI,CAAC,CAAC;QACvB,KAAK,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAI,CAAC;YACzD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YAC7C,IAAI,IAAI,EAAE;gBAAE,OAAO,IAAI,CAAC;QAC1B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEF,6FAA6F;IAC7F,MAAM,MAAM,GAAG,CAAC,GAAY,EAAE,MAAc,EAAE,IAAa,EAAW,EAAE;QACtE,gEAAgE;QAChE,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACzC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;YAAE,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM;gBAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACxE,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzD,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;IAEF,oFAAoF;IACpF,MAAM,KAAK,GAAG,KAAK,EACjB,EAAE,IAAI,EAAE,MAAM,EAAoC,EAClD,GAAY,EACZ,IAAa,EACM,EAAE;QACrB,IAAI,CAAC;YACH,2FAA2F;YAC3F,wFAAwF;YACxF,+BAA+B;YAC/B,MAAM,UAAU,CAAC,KAAK,CAAC;YACvB,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC;gBAAE,OAAO,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;YACtD,MAAM,OAAO,GAAG,MAAM,eAAe,CACnC,EAAE,EACF,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAC7D,CAAC;YACF,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,QAAQ,CACnC,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE;gBACnB,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,OAAO;gBACP,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,MAAM,EAAE,MAAM;aACA,CAAC,CAClB,CAAC;YACF,OAAO,MAAM,kBAAkB,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC3C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,0EAA0E;YAC1E,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,MAAM,IAAI,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,UAAU,EAAE,GAAG,CAAC,CAAC;YAChF,OAAO,IAAI,QAAQ,CAAC,UAAW,GAAa,EAAE,KAAK,IAAI,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACjF,CAAC;IACH,CAAC,CAAC;IAEF,EAAE,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,CAAa,EAAE,EAAE;QAC7C,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC;QACtB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU;YAAE,OAAO,CAAC,0CAA0C;QACxF,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3B,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,MAAM,QAAQ,GAAG,IAAI,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;QACnF,IAAI,QAAQ;YACV,CAAC,CAAC,WAAW,CACX,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,UAAU,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAC3E,OAAO;gBACL,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC;gBAC3B,CAAC,CAAC,QAAQ,CAAC,QAAQ,CACf,GAAG,IAAI,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,SAAS,kBAAkB,CAAC,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAClG,GAAG,CACJ,CACN,CACF,CAAC;;YACC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,6FAA6F;IAC7F,WAAW;IACX,EAAE,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,CAAyB,EAAE,EAAE;QAC3D,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QACjB,IAAI,CAAC,EAAE,IAAI,KAAK,MAAM;YAAE,OAAO;QAC/B,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACzB,CAAC,CAAC,SAAS,CACT,CAAC,KAAK,IAAI,EAAE;YACV,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBAC3B,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;gBAC7B,IAAI,OAAO,CAAC,QAAQ,KAAK,KAAK;oBAAE,OAAO,CAAC,QAAQ,GAAG,OAAO,CAAC;qBACtD,IAAI,OAAO,CAAC,QAAQ,KAAK,MAAM;oBAAE,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;gBAClE,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;gBAC/B,IAAI,CAAC,OAAO;oBAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;gBAC7D,MAAM,OAAO,GAAuB,EAAE,CAAC;gBACvC,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;oBAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;gBAC/E,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,MAAM,UAAU,CAAC,gBAAgB,CAC1D,GAAG,OAAO,EAAE,EACZ,CAAC,CAAC,SAAS,IAAI,EAAE,EACjB,OAAO,CACR,CAAC;gBACF,KAAK,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;YAC1D,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,KAAK,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAE,GAAa,EAAE,OAAO,IAAI,GAAG,CAAC,EAAE,CAAC,CAAC;YAClF,CAAC;QACH,CAAC,CAAC,EAAE,CACL,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,UAAU,EAAE,CAAC;AACxB,CAAC","sourcesContent":["/**\n * One project shared by every tab of an origin, its shards balanced over the tabs.\n *\n * ServiceWorker: installProjectRouter(self, { basePath: \"/app/\" })\n * each page: joinProjectShards({ name, shards, spawn, config, code, serviceWorker })\n * shard worker: serveProjectShard({ sqlite3 })\n *\n * Requests to `<basePath><name>/…` reach the project's Worker through the ServiceWorker, whichever\n * tab sent them (with their URL unchanged, unless `stripBase`); a Durable Object call runs in the\n * shard that owns the object, whichever tab holds that shard.\n *\n * Each tab holds a presence lock; every tab computes the same owner for each shard from the tabs\n * present (`shardOwner`: an even split, oldest tabs first), takes the shards it should own (one\n * Web Lock each) and gives up the others. A shard's OPFS pool belongs to the origin, so its cells\n * move with it from tab to tab. A shard given up is drained first (its requests in flight\n * finish, new ones wait for the next owner); a tab that closes runs no code, so the requests in\n * flight in its shards fail (ShardOwnerLostError) and the other tabs take the shards over.\n */\nimport {\n type DispatchFailure,\n type HandlerInfo,\n LinkLostError,\n SwHttpAdapter,\n SwHttpDispatcher,\n type WorkerLink,\n} from \"@statewalker/webrun-http-browser/sw\";\nimport { ShardOwnerLostError } from \"../router/cell-router.js\";\nimport { errorResponse } from \"../transport/cells-http.js\";\nimport { H } from \"../transport/cells-link.js\";\nimport { SW_SOCKET } from \"../ws/sw-connector.js\";\nimport { applyWorkerCookies, withPageCookies } from \"./browser-cookies.js\";\nimport type { BrowserBucket, BrowserProjectOptions } from \"./browser-host.js\";\nimport { INTERNAL_ORIGIN, TAB_INIT, type TabShardInit } from \"./browser-shards.js\";\n\n/** The ServiceWorker asks a project's tabs to attach their shards again (a host page's wait). */\nconst NEED_LINKS = \"cellb:need-links\";\n/** A page opens a socket (`serviceWorkerConnector`). */\nconst SOCKET = SW_SOCKET;\n\n/**\n * The tab that should run `shard`: the tabs sorted by id (ids start with the time the tab joined),\n * shard i to tab i mod n — every tab runs ⌊shards/n⌋ or ⌈shards/n⌉ shards. A tab joining or\n * leaving moves the shards whose owner index changes; the oldest tabs keep theirs first.\n */\nexport function shardOwner(shard: number, tabs: string[]): string | undefined {\n if (!tabs.length) return undefined;\n const sorted = [...tabs].sort();\n return sorted[shard % sorted.length];\n}\n\nexport interface ProjectTabsOptions {\n /** The project's name in this origin: its URL path, locks and OPFS pools derive from it. */\n name: string;\n shards: number;\n /** Starts the worker of one shard; its script calls `serveProjectShard`. */\n spawn: (shard: number) => Worker;\n config: BrowserProjectOptions[\"config\"];\n code: BrowserProjectOptions[\"code\"];\n assetFiles?: BrowserProjectOptions[\"assetFiles\"];\n /** The OpenAI-compatible endpoint behind the project's `ai` binding. */\n ai?: BrowserProjectOptions[\"ai\"];\n /** Each shard is its own fleet node, `<node>-s<shard>`. */\n bucket?: BrowserBucket;\n /**\n * The active ServiceWorker that runs `installProjectRouter`. This page must be inside its scope\n * and controlled by it (webrun-http-browser's adapter asks the worker to claim the page if it\n * is not, and rejects with a `ServiceWorkerControlError` after 30 s if that fails: after a hard\n * reload, say).\n */\n serviceWorker: () => Promise<ServiceWorker>;\n /** Called whenever the shards this tab runs change. */\n onChange?: (owned: number[]) => void;\n /** How often the tab checks who is present (tabs that crash release their locks silently). */\n checkMs?: number;\n /**\n * A shard handed to another tab first lets its requests in flight finish, for up to this long\n * (default 5 s); new ones wait for the next owner.\n */\n drainMs?: number;\n}\n\nexport interface ProjectTabs {\n /** The shards this tab runs now. */\n owned(): number[];\n /** Ids of the tabs present (this one included). */\n tabs(): Promise<string[]>;\n /** Gives up every shard (closing its runtime first) and leaves. */\n close(): Promise<void>;\n}\n\ninterface Held {\n /** Aborts the wait for the lock, or ends the hold once running. */\n stop: AbortController;\n worker?: Worker;\n running?: Promise<void>;\n}\n\n/** A shard's handler id under the project's key: the router's `route` picks shards by it. */\nconst shardId = (shard: number) => `shard:${shard}`;\n\n/** The page side: this tab takes part in running the project's shards. */\nexport async function joinProjectShards(opts: ProjectTabsOptions): Promise<ProjectTabs> {\n const prefix = `cellb:${opts.name}`;\n const tabId = `${Date.now().toString(36).padStart(9, \"0\")}-${crypto.randomUUID()}`;\n const presenceLock = `${prefix}:tab:${tabId}`;\n let leave!: () => void;\n await new Promise<void>((held) => {\n void navigator.locks.request(presenceLock, () => {\n held();\n return new Promise<void>((r) => (leave = r));\n });\n });\n const channel = new BroadcastChannel(`${prefix}:tabs`);\n const held = new Map<number, Held>();\n const running = new Set<number>();\n let closed = false;\n\n const tabs = async (): Promise<string[]> => {\n const { held: locks = [] } = await navigator.locks.query();\n const ids = locks\n .map((l) => l.name ?? \"\")\n .filter((n) => n.startsWith(`${prefix}:tab:`))\n .map((n) => n.slice(`${prefix}:tab:`.length));\n return ids.includes(tabId) ? ids : [...ids, tabId];\n };\n\n const ask = (w: Worker, data: unknown, ports: MessagePort[] = []) =>\n new Promise<{\n ok: boolean;\n error?: string;\n unsupported?: string[];\n }>((resolve) => {\n const { port1, port2 } = new MessageChannel();\n port1.onmessage = (e) => {\n port1.close();\n resolve(e.data);\n };\n w.postMessage(data, [port2, ...ports]);\n });\n\n // The tab's side of the ServiceWorker's router (webrun-http-browser): it attaches this tab's\n // shard workers under the project's key, and attaches them again whenever the ServiceWorker\n // asks (after a restart). The page itself attaches no handler the router would pick.\n const worker = await opts.serviceWorker();\n // The given worker's registration, not `navigator.serviceWorker.ready` (that is this page's\n // scope's registration, and never settles for a page outside every scope).\n const registration = (await navigator.serviceWorker.getRegistrations()).find((r) =>\n [r.active, r.waiting, r.installing].includes(worker),\n );\n if (!registration)\n throw new Error(`cellb: no registration holds the ServiceWorker ${worker.scriptURL}`);\n const adapter = new SwHttpAdapter({\n key: opts.name,\n registration,\n id: `tab:${tabId}`,\n });\n await adapter.start();\n const links = new Map<number, WorkerLink>();\n\n const changed = () => opts.onChange?.([...running].sort((a, b) => a - b));\n\n /** Waits for the shard's lock, then runs its worker until `stop` is aborted. */\n const take = (shard: number) => {\n const h: Held = { stop: new AbortController() };\n held.set(shard, h);\n h.running = navigator.locks\n .request(`${prefix}:shard:${shard}`, { signal: h.stop.signal }, async () => {\n const w = opts.spawn(shard);\n h.worker = w;\n try {\n const started = await ask(w, {\n type: TAB_INIT,\n name: opts.name,\n shard,\n shards: opts.shards,\n config: opts.config,\n code: opts.code,\n assetFiles: opts.assetFiles,\n ai: opts.ai,\n bucket: opts.bucket && { ...opts.bucket, node: `${opts.bucket.node}-s${shard}` },\n pool: `${opts.name}-shard-${shard}`,\n filesDir: `${opts.name}-files-${shard}`,\n } satisfies TabShardInit);\n if (!started.ok) throw new Error(started.error);\n // What the configuration asks for and this runtime does not provide (a cron trigger\n // without a scheduled() handler, say): said once, not silently ignored.\n if (started.unsupported?.length)\n console.warn(\n `cellb: project ${opts.name} shard ${shard}: unsupported: ${started.unsupported.join(\"; \")}`,\n );\n if (!h.stop.signal.aborted) {\n links.set(\n shard,\n await adapter.attachWorker(w, {\n key: opts.name,\n id: shardId(shard),\n meta: { shard },\n }),\n );\n running.add(shard);\n changed();\n await new Promise<void>((r) =>\n h.stop.signal.aborted ? r() : h.stop.signal.addEventListener(\"abort\", () => r()),\n );\n }\n } finally {\n // A planned hand-over drains the shard's requests in flight first; then the runtime\n // closes (and the pool with it) before the lock goes to the next tab.\n const link = links.get(shard);\n links.delete(shard);\n if (link && running.has(shard))\n await link.drain({ ms: opts.drainMs ?? 5_000 }).catch(() => {});\n running.delete(shard);\n await ask(w, { type: \"cellb:shard-close\" }).catch(() => {});\n w.terminate();\n changed();\n }\n })\n .catch((err) => {\n // Aborted while waiting is expected; a shard that failed to start is reported.\n if (!h.stop.signal.aborted)\n console.error(\n `cellb: ${opts.name} shard ${shard} failed: ${(err as Error)?.message ?? err}`,\n );\n })\n .finally(() => {\n if (held.get(shard) === h) held.delete(shard);\n });\n };\n\n let balancing: Promise<void> | undefined;\n let again = false;\n /** Takes the shards this tab should own and gives up the others. */\n const balance = async () => {\n if (balancing) {\n again = true;\n return balancing;\n }\n balancing = (async () => {\n do {\n again = false;\n if (closed) return;\n const present = await tabs();\n // close() may have run while `tabs()` was answering: take nothing after it.\n if (closed) return;\n for (let shard = 0; shard < opts.shards; shard++) {\n const mine = shardOwner(shard, present) === tabId;\n const h = held.get(shard);\n if (mine && !h) take(shard);\n else if (!mine && h) h.stop.abort();\n }\n } while (again);\n })().finally(() => (balancing = undefined));\n return balancing;\n };\n\n channel.onmessage = () => void balance();\n const timer = setInterval(() => void balance(), opts.checkMs ?? 1000);\n const onSw = (e: MessageEvent) => {\n if (e.data?.type !== NEED_LINKS || (e.data.name && e.data.name !== opts.name)) return;\n void adapter.relink().catch(() => {});\n };\n navigator.serviceWorker.addEventListener(\"message\", onSw);\n channel.postMessage({ joined: tabId });\n await balance();\n\n return {\n owned: () => [...running].sort((a, b) => a - b),\n tabs,\n async close() {\n closed = true;\n clearInterval(timer);\n navigator.serviceWorker.removeEventListener(\"message\", onSw);\n const stopping = [...held.values()];\n for (const h of stopping) h.stop.abort();\n await Promise.all(stopping.map((h) => h.running));\n await adapter.stop().catch(() => {});\n leave();\n channel.postMessage({ left: tabId });\n channel.close();\n },\n };\n}\n\n/**\n * A ServiceWorker's global scope (its `self`), as `installProjectRouter` takes it: typed without\n * TypeScript's WebWorker lib, so that code importing cellb compiles with the DOM lib alone.\n */\nexport interface ServiceWorkerScope {\n readonly location: { readonly origin: string };\n readonly clients: unknown;\n addEventListener(type: string, listener: (event: never) => unknown): void;\n}\n\n/**\n * The ServiceWorker side: webrun-http-browser's dispatcher, with the project as its key and the\n * tabs' shard workers as its handlers. What cellb adds: its urls (`<basePath><name>/`, a root\n * project, `http://cellb.internal/<name>/` for calls between shards), which shard a call goes to,\n * the page's cookies, no control headers from pages, and the host page.\n */\nexport function installProjectRouter(\n scope: ServiceWorkerScope,\n opts: {\n /** Requests to `<basePath><name>/…` go to project `name`. */\n basePath: string;\n /**\n * The Worker sees the request's URL as the page sent it (default), as a Worker on a\n * Cloudflare route does: mount its routes under `<basePath><name>/`. With `stripBase`, it\n * sees `/<rest>` instead — URLs it builds from the request then lack the prefix.\n */\n stripBase?: boolean;\n attachTimeoutMs?: number;\n /**\n * A project served at the origin's root, for apps that build absolute paths (EmDash's\n * `/_emdash/…`, say) and so cannot live under `<basePath><n>/`. Every same-origin request\n * outside `basePath` and outside the `passthrough` path prefixes (the host page's own files)\n * goes to project `name` with its URL unchanged, navigations included.\n *\n * With `hostPage`, a navigation that finds no tab running the project's shards (after\n * `hostWaitMs`, default 2 s, for one to link) is redirected there, with the URL it asked\n * for as `?next=`: the page that starts the project, which a person reopening the site\n * would otherwise never reach, as every path of the origin belongs to the project.\n */\n root?: { name: string; passthrough?: string[]; hostPage?: string; hostWaitMs?: number };\n },\n): { dispatcher: SwHttpDispatcher } {\n const sw = scope as unknown as ServiceWorkerGlobalScope;\n const base = opts.basePath.endsWith(\"/\") ? opts.basePath : `${opts.basePath}/`;\n const internal = new URL(INTERNAL_ORIGIN);\n\n /** Whether `url` goes to the root project (`opts.root`). */\n const atRoot = (url: URL) =>\n !!opts.root &&\n url.origin === sw.location.origin &&\n !url.pathname.startsWith(base) &&\n !(opts.root.passthrough ?? []).some((p) => url.pathname.startsWith(p));\n\n /**\n * `<base><name>/<rest>` → the project's name, the Worker's path `/<rest>`, and `<base><name>` as\n * the URL spells it (`prefix`: what `stripBase` cuts, so a name the URL leaves unescaped, `a@b`,\n * or escapes where it need not, `%61pp`, is cut as written).\n */\n const split = (url: URL): { name: string; path: string; prefix: string } | undefined => {\n if (opts.root && atRoot(url)) return { name: opts.root.name, path: url.pathname, prefix: \"\" };\n if (url.origin !== sw.location.origin || !url.pathname.startsWith(base)) return undefined;\n const rest = url.pathname.slice(base.length);\n const slash = rest.indexOf(\"/\");\n const raw = slash < 0 ? rest : rest.slice(0, slash);\n const name = decodeURIComponent(raw);\n return name\n ? { name, path: slash < 0 ? \"/\" : rest.slice(slash), prefix: `${base}${raw}` }\n : undefined;\n };\n\n const isShard = (h: HandlerInfo) => typeof (h.meta as { shard?: unknown })?.shard === \"number\";\n let rr = 0;\n const dispatcher = new SwHttpDispatcher({\n self: sw,\n handleFetch: false,\n attachTimeoutMs: opts.attachTimeoutMs ?? 15_000,\n key: (url) => {\n // Calls between shards: http://cellb.internal/<name>/.\n if (url.host === internal.host) {\n const name = url.pathname.split(\"/\")[1];\n return name ? decodeURIComponent(name) : undefined;\n }\n return split(url)?.name;\n },\n // A call between shards names its shard (it waits for that one); the rest go to the shard\n // with the fewest requests in flight, round robin among equals. The tabs' pages are handlers\n // of the key too (their adapters'), with nothing to serve: never picked.\n route: (request, _key, handlers) => {\n const shards = handlers.filter(isShard);\n const named = request.headers.get(H.shard);\n if (named !== null)\n return shards.find((h) => (h.meta as { shard: number }).shard === Number(named));\n if (!shards.length) return undefined;\n const start = rr++ % shards.length;\n let best = shards[start];\n for (let i = 1; i < shards.length; i++) {\n const h = shards[(start + i) % shards.length];\n if (h.inflight < best.inflight) best = h;\n }\n return best;\n },\n // A call between shards fails as an error its caller rethrows (postVia); a page's request\n // gets a response it can read.\n failure: (request, failure) => failed(request, failure),\n // Pages may not address objects or shards directly: no control headers on their sockets.\n socketHeaders: (headers, from) =>\n from === \"page\"\n ? headers?.filter(([name]) => !name.toLowerCase().startsWith(\"x-cellb\"))\n : headers,\n });\n dispatcher.start();\n\n const failed = (request: Request, failure: DispatchFailure): Response => {\n const named = request.headers.get(H.shard);\n const what = named !== null ? `cell shard ${named}` : \"the project\";\n const error =\n failure.kind === \"lost\" && failure.error instanceof LinkLostError && named !== null\n ? new ShardOwnerLostError(Number(named))\n : failure.kind === \"timeout\"\n ? new Error(`${what} was not attached in time`)\n : failure.kind === \"gone\"\n ? new Error(`${what} has no tab running it`)\n : (failure.error as Error);\n if (request.headers.get(H.kind) !== null) return errorResponse(error, 503);\n return new Response(`cellb: ${(error as Error)?.message ?? error}`, { status: 503 });\n };\n\n const askForLinks = async (name: string) => {\n const clients = await sw.clients.matchAll({ type: \"window\", includeUncontrolled: true });\n for (const c of clients) c.postMessage({ type: NEED_LINKS, name });\n };\n\n /** Whether a tab runs project `name`'s shards, waiting up to `ms` for one to link. */\n const runningShards = async (name: string, ms: number): Promise<boolean> => {\n await dispatcher.ready;\n const live = () => dispatcher.table.live(name).some(isShard);\n if (live()) return true;\n void askForLinks(name);\n for (const until = Date.now() + ms; Date.now() < until; ) {\n await new Promise((r) => setTimeout(r, 100));\n if (live()) return true;\n }\n return false;\n };\n\n /** Headers for a request the router sends on: no control headers from the page, its base. */\n const routed = (req: Request, prefix: string, root: boolean): Headers => {\n // Headers only: a Request built from `req` would take its body.\n const headers = new Headers(req.headers);\n for (const h of Object.values(H)) if (h !== H.cookie) headers.delete(h);\n if (opts.stripBase && !root) headers.set(H.base, prefix);\n return headers;\n };\n\n /** A request to project `name`, with the page's cookies in and the Worker's out. */\n const serve = async (\n { name, prefix }: { name: string; prefix: string },\n req: Request,\n root: boolean,\n ): Promise<Response> => {\n try {\n // A project no tab has ever served is not the router's: the page's own request goes to the\n // network, as if there were no router (not the copy below, with the page's cookies in a\n // header and a streamed body).\n await dispatcher.ready;\n if (!dispatcher.serves(name)) return await fetch(req);\n const headers = await withPageCookies(\n sw,\n new Request(req.url, { headers: routed(req, prefix, root) }),\n );\n const res = await dispatcher.dispatch(\n new Request(req.url, {\n method: req.method,\n headers,\n body: req.body,\n signal: req.signal,\n duplex: \"half\",\n } as RequestInit),\n );\n return await applyWorkerCookies(sw, res);\n } catch (err) {\n // A response the page can read, instead of a network error with no cause.\n console.error(`cellb: ${req.method} ${new URL(req.url).pathname} failed:`, err);\n return new Response(`cellb: ${(err as Error)?.stack ?? err}`, { status: 502 });\n }\n };\n\n sw.addEventListener(\"fetch\", (e: FetchEvent) => {\n const req = e.request;\n const url = new URL(req.url);\n const root = atRoot(url);\n if (!root && req.mode === \"navigate\") return; // the pages under basePath are the host's\n const project = split(url);\n if (!project) return;\n const hostPage = root && req.mode === \"navigate\" ? opts.root?.hostPage : undefined;\n if (hostPage)\n e.respondWith(\n runningShards(project.name, opts.root?.hostWaitMs ?? 2_000).then((running) =>\n running\n ? serve(project, req, root)\n : Response.redirect(\n `${new URL(hostPage, url.origin).href}?next=${encodeURIComponent(`${url.pathname}${url.search}`)}`,\n 302,\n ),\n ),\n );\n else e.respondWith(serve(project, req, root));\n });\n\n // A page's socket (`serviceWorkerConnector`): routed as a fetch would be, without the page's\n // headers.\n sw.addEventListener(\"message\", (e: ExtendableMessageEvent) => {\n const m = e.data;\n if (m?.type !== SOCKET) return;\n const reply = e.ports[0];\n e.waitUntil(\n (async () => {\n try {\n const url = new URL(m.url);\n const httpUrl = new URL(url);\n if (httpUrl.protocol === \"ws:\") httpUrl.protocol = \"http:\";\n else if (httpUrl.protocol === \"wss:\") httpUrl.protocol = \"https:\";\n const project = split(httpUrl);\n if (!project) throw new Error(`not a project URL: ${m.url}`);\n const headers: [string, string][] = [];\n if (opts.stripBase && !atRoot(httpUrl)) headers.push([H.base, project.prefix]);\n const { port, protocol } = await dispatcher.connectWebSocket(\n `${httpUrl}`,\n m.protocols ?? [],\n headers,\n );\n reply.postMessage({ ok: true, port, protocol }, [port]);\n } catch (err) {\n reply.postMessage({ ok: false, error: String((err as Error)?.message ?? err) });\n }\n })(),\n );\n });\n\n return { dispatcher };\n}\n"]}
1
+ {"version":3,"file":"browser-tabs.js","sourceRoot":"","sources":["../../src/project/browser-tabs.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * One project shared by every tab of an origin, its shards balanced over the tabs.\n *\n * ServiceWorker: installProjectRouter(self, { basePath: \"/app/\" })\n * each page: joinProjectShards({ name, shards, spawn, config, code, serviceWorker })\n * shard worker: serveProjectShard({ sqlite3 })\n *\n * Requests to `<basePath><name>/…` reach the project's Worker through the ServiceWorker, whichever\n * tab sent them (with their URL unchanged, unless `stripBase`); a Durable Object call runs in the\n * shard that owns the object, whichever tab holds that shard.\n *\n * Each tab holds a presence lock; every tab computes the same owner for each shard from the tabs\n * present (`shardOwner`: an even split, oldest tabs first), takes the shards it should own (one\n * Web Lock each) and gives up the others. A shard's OPFS pool belongs to the origin, so its cells\n * move with it from tab to tab. A shard given up is drained first (its requests in flight\n * finish, new ones wait for the next owner); a tab that closes runs no code, so the requests in\n * flight in its shards fail (ShardOwnerLostError) and the other tabs take the shards over.\n */\nimport {\n type DispatchFailure,\n type HandlerInfo,\n LinkLostError,\n SwHttpAdapter,\n SwHttpDispatcher,\n type WorkerLink,\n} from \"@statewalker/webrun-http-browser/sw\";\nimport { ShardOwnerLostError } from \"../router/cell-router.js\";\nimport { errorResponse } from \"../transport/cells-http.js\";\nimport { H } from \"../transport/cells-link.js\";\nimport { SW_SOCKET } from \"../ws/sw-connector.js\";\nimport { applyWorkerCookies, withPageCookies } from \"./browser-cookies.js\";\nimport type { BrowserBucket, BrowserProjectOptions } from \"./browser-host.js\";\nimport { INTERNAL_ORIGIN, TAB_INIT, type TabShardInit } from \"./browser-tab-protocol.js\";\n\n/** The ServiceWorker asks a project's tabs to attach their shards again (a host page's wait). */\nconst NEED_LINKS = \"cellb:need-links\";\n/** A page opens a socket (`serviceWorkerConnector`). */\nconst SOCKET = SW_SOCKET;\n\n/**\n * The tab that should run `shard`: the tabs sorted by id (ids start with the time the tab joined),\n * shard i to tab i mod n — every tab runs ⌊shards/n⌋ or ⌈shards/n⌉ shards. A tab joining or\n * leaving moves the shards whose owner index changes; the oldest tabs keep theirs first.\n */\nexport function shardOwner(shard: number, tabs: string[]): string | undefined {\n if (!tabs.length) return undefined;\n const sorted = [...tabs].sort();\n return sorted[shard % sorted.length];\n}\n\nexport interface ProjectTabsOptions {\n /** The project's name in this origin: its URL path, locks and OPFS pools derive from it. */\n name: string;\n shards: number;\n /** Starts the worker of one shard; its script calls `serveProjectShard`. */\n spawn: (shard: number) => Worker;\n config: BrowserProjectOptions[\"config\"];\n code: BrowserProjectOptions[\"code\"];\n assetFiles?: BrowserProjectOptions[\"assetFiles\"];\n /** The OpenAI-compatible endpoint behind the project's `ai` binding. */\n ai?: BrowserProjectOptions[\"ai\"];\n /** Each shard is its own fleet node, `<node>-s<shard>`. */\n bucket?: BrowserBucket;\n /**\n * The active ServiceWorker that runs `installProjectRouter`. This page must be inside its scope\n * and controlled by it (webrun-http-browser's adapter asks the worker to claim the page if it\n * is not, and rejects with a `ServiceWorkerControlError` after 30 s if that fails: after a hard\n * reload, say).\n */\n serviceWorker: () => Promise<ServiceWorker>;\n /** Called whenever the shards this tab runs change. */\n onChange?: (owned: number[]) => void;\n /** How often the tab checks who is present (tabs that crash release their locks silently). */\n checkMs?: number;\n /**\n * A shard handed to another tab first lets its requests in flight finish, for up to this long\n * (default 5 s); new ones wait for the next owner.\n */\n drainMs?: number;\n}\n\nexport interface ProjectTabs {\n /** The shards this tab runs now. */\n owned(): number[];\n /** Ids of the tabs present (this one included). */\n tabs(): Promise<string[]>;\n /** Gives up every shard (closing its runtime first) and leaves. */\n close(): Promise<void>;\n}\n\ninterface Held {\n /** Aborts the wait for the lock, or ends the hold once running. */\n stop: AbortController;\n worker?: Worker;\n running?: Promise<void>;\n}\n\n/** A shard's handler id under the project's key: the router's `route` picks shards by it. */\nconst shardId = (shard: number) => `shard:${shard}`;\n\n/** The page side: this tab takes part in running the project's shards. */\nexport async function joinProjectShards(opts: ProjectTabsOptions): Promise<ProjectTabs> {\n const prefix = `cellb:${opts.name}`;\n const tabId = `${Date.now().toString(36).padStart(9, \"0\")}-${crypto.randomUUID()}`;\n const presenceLock = `${prefix}:tab:${tabId}`;\n let leave!: () => void;\n await new Promise<void>((held) => {\n void navigator.locks.request(presenceLock, () => {\n held();\n return new Promise<void>((r) => (leave = r));\n });\n });\n const channel = new BroadcastChannel(`${prefix}:tabs`);\n const held = new Map<number, Held>();\n const running = new Set<number>();\n let closed = false;\n\n const tabs = async (): Promise<string[]> => {\n const { held: locks = [] } = await navigator.locks.query();\n const ids = locks\n .map((l) => l.name ?? \"\")\n .filter((n) => n.startsWith(`${prefix}:tab:`))\n .map((n) => n.slice(`${prefix}:tab:`.length));\n return ids.includes(tabId) ? ids : [...ids, tabId];\n };\n\n const ask = (w: Worker, data: unknown, ports: MessagePort[] = []) =>\n new Promise<{\n ok: boolean;\n error?: string;\n unsupported?: string[];\n }>((resolve) => {\n const { port1, port2 } = new MessageChannel();\n port1.onmessage = (e) => {\n port1.close();\n resolve(e.data);\n };\n w.postMessage(data, [port2, ...ports]);\n });\n\n // The tab's side of the ServiceWorker's router (webrun-http-browser): it attaches this tab's\n // shard workers under the project's key, and attaches them again whenever the ServiceWorker\n // asks (after a restart). The page itself attaches no handler the router would pick.\n const worker = await opts.serviceWorker();\n // The given worker's registration, not `navigator.serviceWorker.ready` (that is this page's\n // scope's registration, and never settles for a page outside every scope).\n const registration = (await navigator.serviceWorker.getRegistrations()).find((r) =>\n [r.active, r.waiting, r.installing].includes(worker),\n );\n if (!registration)\n throw new Error(`cellb: no registration holds the ServiceWorker ${worker.scriptURL}`);\n const adapter = new SwHttpAdapter({\n key: opts.name,\n registration,\n id: `tab:${tabId}`,\n });\n await adapter.start();\n const links = new Map<number, WorkerLink>();\n\n const changed = () => opts.onChange?.([...running].sort((a, b) => a - b));\n\n /** Waits for the shard's lock, then runs its worker until `stop` is aborted. */\n const take = (shard: number) => {\n const h: Held = { stop: new AbortController() };\n held.set(shard, h);\n h.running = navigator.locks\n .request(`${prefix}:shard:${shard}`, { signal: h.stop.signal }, async () => {\n const w = opts.spawn(shard);\n h.worker = w;\n try {\n const started = await ask(w, {\n type: TAB_INIT,\n name: opts.name,\n shard,\n shards: opts.shards,\n config: opts.config,\n code: opts.code,\n assetFiles: opts.assetFiles,\n ai: opts.ai,\n bucket: opts.bucket && { ...opts.bucket, node: `${opts.bucket.node}-s${shard}` },\n pool: `${opts.name}-shard-${shard}`,\n filesDir: `${opts.name}-files-${shard}`,\n } satisfies TabShardInit);\n if (!started.ok) throw new Error(started.error);\n // What the configuration asks for and this runtime does not provide (a cron trigger\n // without a scheduled() handler, say): said once, not silently ignored.\n if (started.unsupported?.length)\n console.warn(\n `cellb: project ${opts.name} shard ${shard}: unsupported: ${started.unsupported.join(\"; \")}`,\n );\n if (!h.stop.signal.aborted) {\n links.set(\n shard,\n await adapter.attachWorker(w, {\n key: opts.name,\n id: shardId(shard),\n meta: { shard },\n }),\n );\n running.add(shard);\n changed();\n await new Promise<void>((r) =>\n h.stop.signal.aborted ? r() : h.stop.signal.addEventListener(\"abort\", () => r()),\n );\n }\n } finally {\n // A planned hand-over drains the shard's requests in flight first; then the runtime\n // closes (and the pool with it) before the lock goes to the next tab.\n const link = links.get(shard);\n links.delete(shard);\n if (link && running.has(shard))\n await link.drain({ ms: opts.drainMs ?? 5_000 }).catch(() => {});\n running.delete(shard);\n await ask(w, { type: \"cellb:shard-close\" }).catch(() => {});\n w.terminate();\n changed();\n }\n })\n .catch((err) => {\n // Aborted while waiting is expected; a shard that failed to start is reported.\n if (!h.stop.signal.aborted)\n console.error(\n `cellb: ${opts.name} shard ${shard} failed: ${(err as Error)?.message ?? err}`,\n );\n })\n .finally(() => {\n if (held.get(shard) === h) held.delete(shard);\n });\n };\n\n let balancing: Promise<void> | undefined;\n let again = false;\n /** Takes the shards this tab should own and gives up the others. */\n const balance = async () => {\n if (balancing) {\n again = true;\n return balancing;\n }\n balancing = (async () => {\n do {\n again = false;\n if (closed) return;\n const present = await tabs();\n // close() may have run while `tabs()` was answering: take nothing after it.\n if (closed) return;\n for (let shard = 0; shard < opts.shards; shard++) {\n const mine = shardOwner(shard, present) === tabId;\n const h = held.get(shard);\n if (mine && !h) take(shard);\n else if (!mine && h) h.stop.abort();\n }\n } while (again);\n })().finally(() => (balancing = undefined));\n return balancing;\n };\n\n channel.onmessage = () => void balance();\n const timer = setInterval(() => void balance(), opts.checkMs ?? 1000);\n const onSw = (e: MessageEvent) => {\n if (e.data?.type !== NEED_LINKS || (e.data.name && e.data.name !== opts.name)) return;\n void adapter.relink().catch(() => {});\n };\n navigator.serviceWorker.addEventListener(\"message\", onSw);\n channel.postMessage({ joined: tabId });\n await balance();\n\n return {\n owned: () => [...running].sort((a, b) => a - b),\n tabs,\n async close() {\n closed = true;\n clearInterval(timer);\n navigator.serviceWorker.removeEventListener(\"message\", onSw);\n const stopping = [...held.values()];\n for (const h of stopping) h.stop.abort();\n await Promise.all(stopping.map((h) => h.running));\n await adapter.stop().catch(() => {});\n leave();\n channel.postMessage({ left: tabId });\n channel.close();\n },\n };\n}\n\n/**\n * A ServiceWorker's global scope (its `self`), as `installProjectRouter` takes it: typed without\n * TypeScript's WebWorker lib, so that code importing cellb compiles with the DOM lib alone.\n */\nexport interface ServiceWorkerScope {\n readonly location: { readonly origin: string };\n readonly clients: unknown;\n addEventListener(type: string, listener: (event: never) => unknown): void;\n}\n\n/**\n * The ServiceWorker side: webrun-http-browser's dispatcher, with the project as its key and the\n * tabs' shard workers as its handlers. What cellb adds: its urls (`<basePath><name>/`, a root\n * project, `http://cellb.internal/<name>/` for calls between shards), which shard a call goes to,\n * the page's cookies, no control headers from pages, and the host page.\n */\nexport function installProjectRouter(\n scope: ServiceWorkerScope,\n opts: {\n /** Requests to `<basePath><name>/…` go to project `name`. */\n basePath: string;\n /**\n * The Worker sees the request's URL as the page sent it (default), as a Worker on a\n * Cloudflare route does: mount its routes under `<basePath><name>/`. With `stripBase`, it\n * sees `/<rest>` instead — URLs it builds from the request then lack the prefix.\n */\n stripBase?: boolean;\n attachTimeoutMs?: number;\n /**\n * A project served at the origin's root, for apps that build absolute paths (EmDash's\n * `/_emdash/…`, say) and so cannot live under `<basePath><n>/`. Every same-origin request\n * outside `basePath` and outside the `passthrough` path prefixes (the host page's own files)\n * goes to project `name` with its URL unchanged, navigations included.\n *\n * With `hostPage`, a navigation that finds no tab running the project's shards (after\n * `hostWaitMs`, default 2 s, for one to link) is redirected there, with the URL it asked\n * for as `?next=`: the page that starts the project, which a person reopening the site\n * would otherwise never reach, as every path of the origin belongs to the project.\n */\n root?: { name: string; passthrough?: string[]; hostPage?: string; hostWaitMs?: number };\n },\n): { dispatcher: SwHttpDispatcher } {\n const sw = scope as unknown as ServiceWorkerGlobalScope;\n const base = opts.basePath.endsWith(\"/\") ? opts.basePath : `${opts.basePath}/`;\n const internal = new URL(INTERNAL_ORIGIN);\n\n /** Whether `url` goes to the root project (`opts.root`). */\n const atRoot = (url: URL) =>\n !!opts.root &&\n url.origin === sw.location.origin &&\n !url.pathname.startsWith(base) &&\n !(opts.root.passthrough ?? []).some((p) => url.pathname.startsWith(p));\n\n /**\n * `<base><name>/<rest>` → the project's name, the Worker's path `/<rest>`, and `<base><name>` as\n * the URL spells it (`prefix`: what `stripBase` cuts, so a name the URL leaves unescaped, `a@b`,\n * or escapes where it need not, `%61pp`, is cut as written).\n */\n const split = (url: URL): { name: string; path: string; prefix: string } | undefined => {\n if (opts.root && atRoot(url)) return { name: opts.root.name, path: url.pathname, prefix: \"\" };\n if (url.origin !== sw.location.origin || !url.pathname.startsWith(base)) return undefined;\n const rest = url.pathname.slice(base.length);\n const slash = rest.indexOf(\"/\");\n const raw = slash < 0 ? rest : rest.slice(0, slash);\n const name = decodeURIComponent(raw);\n return name\n ? { name, path: slash < 0 ? \"/\" : rest.slice(slash), prefix: `${base}${raw}` }\n : undefined;\n };\n\n const isShard = (h: HandlerInfo) => typeof (h.meta as { shard?: unknown })?.shard === \"number\";\n let rr = 0;\n const dispatcher = new SwHttpDispatcher({\n self: sw,\n handleFetch: false,\n attachTimeoutMs: opts.attachTimeoutMs ?? 15_000,\n key: (url) => {\n // Calls between shards: http://cellb.internal/<name>/.\n if (url.host === internal.host) {\n const name = url.pathname.split(\"/\")[1];\n return name ? decodeURIComponent(name) : undefined;\n }\n return split(url)?.name;\n },\n // A call between shards names its shard (it waits for that one); the rest go to the shard\n // with the fewest requests in flight, round robin among equals. The tabs' pages are handlers\n // of the key too (their adapters'), with nothing to serve: never picked.\n route: (request, _key, handlers) => {\n const shards = handlers.filter(isShard);\n const named = request.headers.get(H.shard);\n if (named !== null)\n return shards.find((h) => (h.meta as { shard: number }).shard === Number(named));\n if (!shards.length) return undefined;\n const start = rr++ % shards.length;\n let best = shards[start];\n for (let i = 1; i < shards.length; i++) {\n const h = shards[(start + i) % shards.length];\n if (h.inflight < best.inflight) best = h;\n }\n return best;\n },\n // A call between shards fails as an error its caller rethrows (postVia); a page's request\n // gets a response it can read.\n failure: (request, failure) => failed(request, failure),\n // Pages may not address objects or shards directly: no control headers on their sockets.\n socketHeaders: (headers, from) =>\n from === \"page\"\n ? headers?.filter(([name]) => !name.toLowerCase().startsWith(\"x-cellb\"))\n : headers,\n });\n dispatcher.start();\n\n const failed = (request: Request, failure: DispatchFailure): Response => {\n const named = request.headers.get(H.shard);\n const what = named !== null ? `cell shard ${named}` : \"the project\";\n const error =\n failure.kind === \"lost\" && failure.error instanceof LinkLostError && named !== null\n ? new ShardOwnerLostError(Number(named))\n : failure.kind === \"timeout\"\n ? new Error(`${what} was not attached in time`)\n : failure.kind === \"gone\"\n ? new Error(`${what} has no tab running it`)\n : (failure.error as Error);\n if (request.headers.get(H.kind) !== null) return errorResponse(error, 503);\n return new Response(`cellb: ${(error as Error)?.message ?? error}`, { status: 503 });\n };\n\n const askForLinks = async (name: string) => {\n const clients = await sw.clients.matchAll({ type: \"window\", includeUncontrolled: true });\n for (const c of clients) c.postMessage({ type: NEED_LINKS, name });\n };\n\n /** Whether a tab runs project `name`'s shards, waiting up to `ms` for one to link. */\n const runningShards = async (name: string, ms: number): Promise<boolean> => {\n await dispatcher.ready;\n const live = () => dispatcher.table.live(name).some(isShard);\n if (live()) return true;\n void askForLinks(name);\n for (const until = Date.now() + ms; Date.now() < until; ) {\n await new Promise((r) => setTimeout(r, 100));\n if (live()) return true;\n }\n return false;\n };\n\n /** Headers for a request the router sends on: no control headers from the page, its base. */\n const routed = (req: Request, prefix: string, root: boolean): Headers => {\n // Headers only: a Request built from `req` would take its body.\n const headers = new Headers(req.headers);\n for (const h of Object.values(H)) if (h !== H.cookie) headers.delete(h);\n if (opts.stripBase && !root) headers.set(H.base, prefix);\n return headers;\n };\n\n /** A request to project `name`, with the page's cookies in and the Worker's out. */\n const serve = async (\n { name, prefix }: { name: string; prefix: string },\n req: Request,\n root: boolean,\n ): Promise<Response> => {\n try {\n // A project no tab has ever served is not the router's: the page's own request goes to the\n // network, as if there were no router (not the copy below, with the page's cookies in a\n // header and a streamed body).\n await dispatcher.ready;\n if (!dispatcher.serves(name)) return await fetch(req);\n const headers = await withPageCookies(\n sw,\n new Request(req.url, { headers: routed(req, prefix, root) }),\n );\n const res = await dispatcher.dispatch(\n new Request(req.url, {\n method: req.method,\n headers,\n body: req.body,\n signal: req.signal,\n duplex: \"half\",\n } as RequestInit),\n );\n return await applyWorkerCookies(sw, res);\n } catch (err) {\n // A response the page can read, instead of a network error with no cause.\n console.error(`cellb: ${req.method} ${new URL(req.url).pathname} failed:`, err);\n return new Response(`cellb: ${(err as Error)?.stack ?? err}`, { status: 502 });\n }\n };\n\n sw.addEventListener(\"fetch\", (e: FetchEvent) => {\n const req = e.request;\n const url = new URL(req.url);\n const root = atRoot(url);\n if (!root && req.mode === \"navigate\") return; // the pages under basePath are the host's\n const project = split(url);\n if (!project) return;\n const hostPage = root && req.mode === \"navigate\" ? opts.root?.hostPage : undefined;\n if (hostPage)\n e.respondWith(\n runningShards(project.name, opts.root?.hostWaitMs ?? 2_000).then((running) =>\n running\n ? serve(project, req, root)\n : Response.redirect(\n `${new URL(hostPage, url.origin).href}?next=${encodeURIComponent(`${url.pathname}${url.search}`)}`,\n 302,\n ),\n ),\n );\n else e.respondWith(serve(project, req, root));\n });\n\n // A page's socket (`serviceWorkerConnector`): routed as a fetch would be, without the page's\n // headers.\n sw.addEventListener(\"message\", (e: ExtendableMessageEvent) => {\n const m = e.data;\n if (m?.type !== SOCKET) return;\n const reply = e.ports[0];\n e.waitUntil(\n (async () => {\n try {\n const url = new URL(m.url);\n const httpUrl = new URL(url);\n if (httpUrl.protocol === \"ws:\") httpUrl.protocol = \"http:\";\n else if (httpUrl.protocol === \"wss:\") httpUrl.protocol = \"https:\";\n const project = split(httpUrl);\n if (!project) throw new Error(`not a project URL: ${m.url}`);\n const headers: [string, string][] = [];\n if (opts.stripBase && !atRoot(httpUrl)) headers.push([H.base, project.prefix]);\n const { port, protocol } = await dispatcher.connectWebSocket(\n `${httpUrl}`,\n m.protocols ?? [],\n headers,\n );\n reply.postMessage({ ok: true, port, protocol }, [port]);\n } catch (err) {\n reply.postMessage({ ok: false, error: String((err as Error)?.message ?? err) });\n }\n })(),\n );\n });\n\n return { dispatcher };\n}\n"]}
@@ -24,6 +24,7 @@ export async function buildProject(dir, outDir, opts = {}) {
24
24
  ? await bundleWorkerForBrowser(resolve(dir, config.main), {
25
25
  nodeCompat,
26
26
  lowerAwait: opts.lowerAwait,
27
+ rules: config.rules,
27
28
  })
28
29
  : null;
29
30
  const assets = config.assets?.directory
@@ -1 +1 @@
1
- {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/project/build.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `buildProject` (`cellb build`): the build step whose output folder `loadProject` loads, in a\n * browser or on Node. Imports no SQLite: the command stays quiet and light.\n */\nimport { mkdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { bundleWorkerForBrowser } from \"./browser-bundle.js\";\nimport {\n BUILD_FORMAT,\n BUILD_MANIFEST,\n BUILT_ASSETS,\n BUILT_WORKER,\n type BuildManifest,\n builtConfig,\n} from \"./built-project.js\";\nimport { readAssetDirectory, readWranglerConfig } from \"./node-project.js\";\nimport { hasNodeCompat } from \"./wrangler.js\";\n\nexport interface BuildProjectOptions {\n /**\n * Lower `await` to generators (default: with nodejs_compat), as `bundleWorkerForBrowser`;\n * `false` for browsers with TC39 AsyncContext only.\n */\n lowerAwait?: boolean;\n}\n\n/**\n * `cellb build`: writes the project in `dir` as a folder any static host serves and\n * `loadProject` (browser or Node) loads: `wrangler.json`, `worker.js` (`main` bundled for a\n * browser realm, with nodejs_compat when the flags ask for it), `assets/` and `cellb.json`.\n */\nexport async function buildProject(\n dir: string,\n outDir: string,\n opts: BuildProjectOptions = {},\n): Promise<BuildManifest> {\n dir = resolve(dir);\n outDir = resolve(outDir);\n const config = readWranglerConfig(dir);\n if (!config.main && !config.assets)\n throw new Error(\"wrangler config has neither `main` nor `assets`\");\n const nodeCompat = hasNodeCompat(config);\n const code = config.main\n ? await bundleWorkerForBrowser(resolve(dir, config.main), {\n nodeCompat,\n lowerAwait: opts.lowerAwait,\n })\n : null;\n const assets = config.assets?.directory\n ? readAssetDirectory(resolve(dir, config.assets.directory))\n : new Map<string, Uint8Array>();\n // A fresh folder: files of an earlier build must not linger as assets.\n for (const name of [BUILD_MANIFEST, \"wrangler.json\", BUILT_WORKER, BUILT_ASSETS])\n rmSync(join(outDir, name), { recursive: true, force: true });\n mkdirSync(outDir, { recursive: true });\n writeFileSync(join(outDir, \"wrangler.json\"), `${JSON.stringify(builtConfig(config), null, 2)}\\n`);\n if (code !== null) writeFileSync(join(outDir, BUILT_WORKER), code);\n for (const [path, bytes] of assets) {\n const out = join(outDir, BUILT_ASSETS, path);\n mkdirSync(dirname(out), { recursive: true });\n writeFileSync(out, bytes);\n }\n const manifest: BuildManifest = {\n format: BUILD_FORMAT,\n main: code !== null ? BUILT_WORKER : null,\n assets: [...assets.keys()].sort(),\n };\n // Written last: a folder with a manifest is a complete build.\n writeFileSync(join(outDir, BUILD_MANIFEST), `${JSON.stringify(manifest, null, 2)}\\n`);\n return manifest;\n}\n"]}
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/project/build.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `buildProject` (`cellb build`): the build step whose output folder `loadProject` loads, in a\n * browser or on Node. Imports no SQLite: the command stays quiet and light.\n */\nimport { mkdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { bundleWorkerForBrowser } from \"./browser-bundle.js\";\nimport {\n BUILD_FORMAT,\n BUILD_MANIFEST,\n BUILT_ASSETS,\n BUILT_WORKER,\n type BuildManifest,\n builtConfig,\n} from \"./built-project.js\";\nimport { readAssetDirectory, readWranglerConfig } from \"./node-project.js\";\nimport { hasNodeCompat } from \"./wrangler.js\";\n\nexport interface BuildProjectOptions {\n /**\n * Lower `await` to generators (default: with nodejs_compat), as `bundleWorkerForBrowser`;\n * `false` for browsers with TC39 AsyncContext only.\n */\n lowerAwait?: boolean;\n}\n\n/**\n * `cellb build`: writes the project in `dir` as a folder any static host serves and\n * `loadProject` (browser or Node) loads: `wrangler.json`, `worker.js` (`main` bundled for a\n * browser realm, with nodejs_compat when the flags ask for it), `assets/` and `cellb.json`.\n */\nexport async function buildProject(\n dir: string,\n outDir: string,\n opts: BuildProjectOptions = {},\n): Promise<BuildManifest> {\n dir = resolve(dir);\n outDir = resolve(outDir);\n const config = readWranglerConfig(dir);\n if (!config.main && !config.assets)\n throw new Error(\"wrangler config has neither `main` nor `assets`\");\n const nodeCompat = hasNodeCompat(config);\n const code = config.main\n ? await bundleWorkerForBrowser(resolve(dir, config.main), {\n nodeCompat,\n lowerAwait: opts.lowerAwait,\n rules: config.rules,\n })\n : null;\n const assets = config.assets?.directory\n ? readAssetDirectory(resolve(dir, config.assets.directory))\n : new Map<string, Uint8Array>();\n // A fresh folder: files of an earlier build must not linger as assets.\n for (const name of [BUILD_MANIFEST, \"wrangler.json\", BUILT_WORKER, BUILT_ASSETS])\n rmSync(join(outDir, name), { recursive: true, force: true });\n mkdirSync(outDir, { recursive: true });\n writeFileSync(join(outDir, \"wrangler.json\"), `${JSON.stringify(builtConfig(config), null, 2)}\\n`);\n if (code !== null) writeFileSync(join(outDir, BUILT_WORKER), code);\n for (const [path, bytes] of assets) {\n const out = join(outDir, BUILT_ASSETS, path);\n mkdirSync(dirname(out), { recursive: true });\n writeFileSync(out, bytes);\n }\n const manifest: BuildManifest = {\n format: BUILD_FORMAT,\n main: code !== null ? BUILT_WORKER : null,\n assets: [...assets.keys()].sort(),\n };\n // Written last: a folder with a manifest is a complete build.\n writeFileSync(join(outDir, BUILD_MANIFEST), `${JSON.stringify(manifest, null, 2)}\\n`);\n return manifest;\n}\n"]}
@@ -52,6 +52,26 @@ function usesSuperOrNewTarget(fn) {
52
52
  visit(fn.body);
53
53
  return found;
54
54
  }
55
+ /**
56
+ * Whether an arrow reads `arguments` itself: an `arguments` identifier in its body, not in a
57
+ * function of its own (which has its own `arguments`). A word in a string or a comment is not.
58
+ */
59
+ function readsArguments(fn) {
60
+ let found = false;
61
+ const visit = (n) => {
62
+ if (found)
63
+ return;
64
+ if (n.type === "Identifier" && n.name === "arguments") {
65
+ found = true;
66
+ return;
67
+ }
68
+ for (const c of childrenOf(n))
69
+ if (!(isFunction(c) && c.type !== "ArrowFunctionExpression"))
70
+ visit(c);
71
+ };
72
+ visit(fn.body);
73
+ return found;
74
+ }
55
75
  const lowered = (n) => isFunction(n) && n.async && !n.generator && !usesSuperOrNewTarget(n);
56
76
  /** `code` with its async functions lowered; `code` itself when it has none or does not parse. */
57
77
  export function lowerAwait(code) {
@@ -121,8 +141,8 @@ export function lowerAwait(code) {
121
141
  if (child !== fn.body)
122
142
  return body;
123
143
  // An arrow's `arguments` is its enclosing function's: pass them on only when it reads them
124
- // (a module has none).
125
- const call = !arrow || /\barguments\b/.test(body) ? ".apply(this, arguments)" : ".call(this)";
144
+ // (a module, a class field or a static block has none, and naming it there is an error).
145
+ const call = !arrow || readsArguments(fn) ? ".apply(this, arguments)" : ".call(this)";
126
146
  if (fn.expression)
127
147
  return `__cellbAsync(function* () { return ${body}; }${call})`;
128
148
  return `{ return __cellbAsync(function* () ${body}${call}); }`;
@@ -1 +1 @@
1
- {"version":3,"file":"lower-await.js","sourceRoot":"","sources":["../../src/project/lower-await.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `async`/`await` lowered to generators, for the modules an in-browser site serves (what\n * esbuild's `supported: { \"async-await\": false }` does for `bundleWorkerForBrowser`): each `await`\n * then resumes through `Promise.prototype.then`, which cellb's `node:async_hooks` polyfill makes\n * carry the AsyncLocalStorage stores (see `installAsyncContext`).\n *\n * async function f(a) { BODY } → function f(a) { return __cellbAsync(function* () { BODY }.apply(this, arguments)); }\n * async (a) => EXPR → (a) => __cellbAsync(function* () { return EXPR; }.call(this))\n * await X → (yield X)\n * for await (L of R) BODY → a loop over `yield it.next()`, closing the iterator on exit\n *\n * Left as they are: async generators (their awaits stay native, as their bodies), functions that\n * use `super` or `new.target` (a generator nested in them cannot), and top-level await. Their\n * awaits resume in the polyfill's root frame: they see no store rather than another event's.\n */\nimport { type Node, parse } from \"acorn\";\n\n// biome-ignore lint/suspicious/noExplicitAny: walking acorn's ESTree nodes by their properties\ntype AnyNode = Node & Record<string, any>;\n\nconst ASYNC_RUNNER =\n 'function __cellbAsync(g){return new Promise(function(res,rej){function step(m,v){var r;try{r=g[m](v)}catch(e){rej(e);return}if(r.done)res(r.value);else Promise.resolve(r.value).then(function(x){step(\"next\",x)},function(e){step(\"throw\",e)})}step(\"next\")})}';\nconst ASYNC_ITERATOR =\n \"function __cellbIter(o){var m=o[Symbol.asyncIterator];if(m)return m.call(o);var it=o[Symbol.iterator](),w=function(r){return Promise.resolve(r.value).then(function(x){return{value:x,done:r.done}})};return{next:function(v){return w(it.next(v))},return:it.return&&function(v){return w(it.return(v))}}}\";\n\nconst isFunction = (n: AnyNode) =>\n n.type === \"FunctionDeclaration\" ||\n n.type === \"FunctionExpression\" ||\n n.type === \"ArrowFunctionExpression\";\n\nfunction childrenOf(node: AnyNode): AnyNode[] {\n const out: AnyNode[] = [];\n for (const key in node) {\n if (key === \"type\" || key === \"start\" || key === \"end\" || key === \"loc\" || key === \"range\")\n continue;\n const v = node[key];\n if (Array.isArray(v)) {\n for (const c of v) if (c && typeof c.type === \"string\") out.push(c);\n } else if (v && typeof v.type === \"string\") out.push(v);\n }\n return out.sort((a, b) => a.start - b.start);\n}\n\n/** `super` or `new.target` in `fn`'s own body (not in the functions it declares). */\nfunction usesSuperOrNewTarget(fn: AnyNode): boolean {\n let found = false;\n const visit = (n: AnyNode) => {\n if (found) return;\n if (n.type === \"Super\" || n.type === \"MetaProperty\") {\n found = true;\n return;\n }\n for (const c of childrenOf(n))\n if (!(isFunction(c) && c.type !== \"ArrowFunctionExpression\") && c.type !== \"ClassBody\")\n visit(c);\n };\n visit(fn.body);\n return found;\n}\n\nconst lowered = (n: AnyNode) =>\n isFunction(n) && n.async && !n.generator && !usesSuperOrNewTarget(n);\n\n/** `code` with its async functions lowered; `code` itself when it has none or does not parse. */\nexport function lowerAwait(code: string): string {\n if (!/\\basync\\b/.test(code)) return code;\n let program: AnyNode;\n try {\n program = parse(code, {\n ecmaVersion: \"latest\",\n sourceType: \"module\",\n allowHashBang: true,\n }) as AnyNode;\n } catch {\n return code;\n }\n let changed = false;\n let iterUsed = false;\n let temp = 0;\n\n // `inLowered`: whether `await` here belongs to a function being lowered.\n const render = (node: AnyNode, inLowered: boolean): string => {\n if (isFunction(node)) return renderFunction(node);\n if (inLowered && node.type === \"AwaitExpression\")\n return `(yield ${render(node.argument, inLowered)})`;\n if (inLowered && node.type === \"ForOfStatement\" && node.await)\n return renderForAwait(node, \"\", inLowered);\n if (inLowered && node.type === \"LabeledStatement\") {\n let labels = \"\";\n let body = node;\n while (body.type === \"LabeledStatement\") {\n labels += `${body.label.name}: `;\n body = body.body;\n }\n if (body.type === \"ForOfStatement\" && body.await)\n return renderForAwait(body, labels, inLowered);\n }\n let text = generic(node, inLowered);\n // `async` of a lowered method sits before its key (`static async [k]() {}`).\n if (\n (node.type === \"MethodDefinition\" || (node.type === \"Property\" && node.method)) &&\n lowered(node.value)\n ) {\n const head = node.key.start - node.start - (node.computed ? 1 : 0);\n const prefix = text.slice(0, head).replace(/\\basync\\b\\s*/, \"\");\n text = prefix + text.slice(head);\n }\n return text;\n };\n\n const generic = (\n node: AnyNode,\n inLowered: boolean,\n wrap?: (child: AnyNode, text: string) => string,\n ): string => {\n let out = \"\";\n let at = node.start;\n for (const c of childrenOf(node)) {\n if (c.start < at) continue; // the same node twice (a shorthand property's key and value)\n out += code.slice(at, c.start);\n const text = render(c, inLowered);\n out += wrap ? wrap(c, text) : text;\n at = c.end;\n }\n return out + code.slice(at, node.end);\n };\n\n const renderFunction = (fn: AnyNode): string => {\n if (!lowered(fn)) return generic(fn, false);\n changed = true;\n const arrow = fn.type === \"ArrowFunctionExpression\";\n const text = generic(fn, true, (child, body) => {\n if (child !== fn.body) return body;\n // An arrow's `arguments` is its enclosing function's: pass them on only when it reads them\n // (a module has none).\n const call = !arrow || /\\barguments\\b/.test(body) ? \".apply(this, arguments)\" : \".call(this)\";\n if (fn.expression) return `__cellbAsync(function* () { return ${body}; }${call})`;\n return `{ return __cellbAsync(function* () ${body}${call}); }`;\n });\n return text.replace(/^async\\b\\s*/, \"\");\n };\n\n const renderForAwait = (loop: AnyNode, labels: string, inLowered: boolean): string => {\n iterUsed = true;\n const n = temp++;\n const it = `__cellbIt${n}`;\n const step = `__cellbStep${n}`;\n const left = render(loop.left, inLowered);\n const assign =\n loop.left.type === \"VariableDeclaration\"\n ? `${left} = ${step}.value;`\n : `(${left} = ${step}.value);`;\n return (\n `{ const ${it} = __cellbIter(${render(loop.right, inLowered)}); let ${step}; ` +\n `try { ${labels}for (;;) { ${step} = undefined; ${step} = yield ${it}.next(); ` +\n `if (${step}.done) break; { ${assign} ${render(loop.body, inLowered)} } } } ` +\n `finally { if (${step} && !${step}.done && ${it}.return) yield ${it}.return(); } }`\n );\n };\n\n const out = render(program, false);\n if (!changed) return code;\n return `${out}\\n${ASYNC_RUNNER}\\n${iterUsed ? `${ASYNC_ITERATOR}\\n` : \"\"}`;\n}\n"]}
1
+ {"version":3,"file":"lower-await.js","sourceRoot":"","sources":["../../src/project/lower-await.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `async`/`await` lowered to generators, for the modules an in-browser site serves (what\n * esbuild's `supported: { \"async-await\": false }` does for `bundleWorkerForBrowser`): each `await`\n * then resumes through `Promise.prototype.then`, which cellb's `node:async_hooks` polyfill makes\n * carry the AsyncLocalStorage stores (see `installAsyncContext`).\n *\n * async function f(a) { BODY } → function f(a) { return __cellbAsync(function* () { BODY }.apply(this, arguments)); }\n * async (a) => EXPR → (a) => __cellbAsync(function* () { return EXPR; }.call(this))\n * await X → (yield X)\n * for await (L of R) BODY → a loop over `yield it.next()`, closing the iterator on exit\n *\n * Left as they are: async generators (their awaits stay native, as their bodies), functions that\n * use `super` or `new.target` (a generator nested in them cannot), and top-level await. Their\n * awaits resume in the polyfill's root frame: they see no store rather than another event's.\n */\nimport { type Node, parse } from \"acorn\";\n\n// biome-ignore lint/suspicious/noExplicitAny: walking acorn's ESTree nodes by their properties\ntype AnyNode = Node & Record<string, any>;\n\nconst ASYNC_RUNNER =\n 'function __cellbAsync(g){return new Promise(function(res,rej){function step(m,v){var r;try{r=g[m](v)}catch(e){rej(e);return}if(r.done)res(r.value);else Promise.resolve(r.value).then(function(x){step(\"next\",x)},function(e){step(\"throw\",e)})}step(\"next\")})}';\nconst ASYNC_ITERATOR =\n \"function __cellbIter(o){var m=o[Symbol.asyncIterator];if(m)return m.call(o);var it=o[Symbol.iterator](),w=function(r){return Promise.resolve(r.value).then(function(x){return{value:x,done:r.done}})};return{next:function(v){return w(it.next(v))},return:it.return&&function(v){return w(it.return(v))}}}\";\n\nconst isFunction = (n: AnyNode) =>\n n.type === \"FunctionDeclaration\" ||\n n.type === \"FunctionExpression\" ||\n n.type === \"ArrowFunctionExpression\";\n\nfunction childrenOf(node: AnyNode): AnyNode[] {\n const out: AnyNode[] = [];\n for (const key in node) {\n if (key === \"type\" || key === \"start\" || key === \"end\" || key === \"loc\" || key === \"range\")\n continue;\n const v = node[key];\n if (Array.isArray(v)) {\n for (const c of v) if (c && typeof c.type === \"string\") out.push(c);\n } else if (v && typeof v.type === \"string\") out.push(v);\n }\n return out.sort((a, b) => a.start - b.start);\n}\n\n/** `super` or `new.target` in `fn`'s own body (not in the functions it declares). */\nfunction usesSuperOrNewTarget(fn: AnyNode): boolean {\n let found = false;\n const visit = (n: AnyNode) => {\n if (found) return;\n if (n.type === \"Super\" || n.type === \"MetaProperty\") {\n found = true;\n return;\n }\n for (const c of childrenOf(n))\n if (!(isFunction(c) && c.type !== \"ArrowFunctionExpression\") && c.type !== \"ClassBody\")\n visit(c);\n };\n visit(fn.body);\n return found;\n}\n\n/**\n * Whether an arrow reads `arguments` itself: an `arguments` identifier in its body, not in a\n * function of its own (which has its own `arguments`). A word in a string or a comment is not.\n */\nfunction readsArguments(fn: AnyNode): boolean {\n let found = false;\n const visit = (n: AnyNode) => {\n if (found) return;\n if (n.type === \"Identifier\" && n.name === \"arguments\") {\n found = true;\n return;\n }\n for (const c of childrenOf(n))\n if (!(isFunction(c) && c.type !== \"ArrowFunctionExpression\")) visit(c);\n };\n visit(fn.body);\n return found;\n}\n\nconst lowered = (n: AnyNode) =>\n isFunction(n) && n.async && !n.generator && !usesSuperOrNewTarget(n);\n\n/** `code` with its async functions lowered; `code` itself when it has none or does not parse. */\nexport function lowerAwait(code: string): string {\n if (!/\\basync\\b/.test(code)) return code;\n let program: AnyNode;\n try {\n program = parse(code, {\n ecmaVersion: \"latest\",\n sourceType: \"module\",\n allowHashBang: true,\n }) as AnyNode;\n } catch {\n return code;\n }\n let changed = false;\n let iterUsed = false;\n let temp = 0;\n\n // `inLowered`: whether `await` here belongs to a function being lowered.\n const render = (node: AnyNode, inLowered: boolean): string => {\n if (isFunction(node)) return renderFunction(node);\n if (inLowered && node.type === \"AwaitExpression\")\n return `(yield ${render(node.argument, inLowered)})`;\n if (inLowered && node.type === \"ForOfStatement\" && node.await)\n return renderForAwait(node, \"\", inLowered);\n if (inLowered && node.type === \"LabeledStatement\") {\n let labels = \"\";\n let body = node;\n while (body.type === \"LabeledStatement\") {\n labels += `${body.label.name}: `;\n body = body.body;\n }\n if (body.type === \"ForOfStatement\" && body.await)\n return renderForAwait(body, labels, inLowered);\n }\n let text = generic(node, inLowered);\n // `async` of a lowered method sits before its key (`static async [k]() {}`).\n if (\n (node.type === \"MethodDefinition\" || (node.type === \"Property\" && node.method)) &&\n lowered(node.value)\n ) {\n const head = node.key.start - node.start - (node.computed ? 1 : 0);\n const prefix = text.slice(0, head).replace(/\\basync\\b\\s*/, \"\");\n text = prefix + text.slice(head);\n }\n return text;\n };\n\n const generic = (\n node: AnyNode,\n inLowered: boolean,\n wrap?: (child: AnyNode, text: string) => string,\n ): string => {\n let out = \"\";\n let at = node.start;\n for (const c of childrenOf(node)) {\n if (c.start < at) continue; // the same node twice (a shorthand property's key and value)\n out += code.slice(at, c.start);\n const text = render(c, inLowered);\n out += wrap ? wrap(c, text) : text;\n at = c.end;\n }\n return out + code.slice(at, node.end);\n };\n\n const renderFunction = (fn: AnyNode): string => {\n if (!lowered(fn)) return generic(fn, false);\n changed = true;\n const arrow = fn.type === \"ArrowFunctionExpression\";\n const text = generic(fn, true, (child, body) => {\n if (child !== fn.body) return body;\n // An arrow's `arguments` is its enclosing function's: pass them on only when it reads them\n // (a module, a class field or a static block has none, and naming it there is an error).\n const call = !arrow || readsArguments(fn) ? \".apply(this, arguments)\" : \".call(this)\";\n if (fn.expression) return `__cellbAsync(function* () { return ${body}; }${call})`;\n return `{ return __cellbAsync(function* () ${body}${call}); }`;\n });\n return text.replace(/^async\\b\\s*/, \"\");\n };\n\n const renderForAwait = (loop: AnyNode, labels: string, inLowered: boolean): string => {\n iterUsed = true;\n const n = temp++;\n const it = `__cellbIt${n}`;\n const step = `__cellbStep${n}`;\n const left = render(loop.left, inLowered);\n const assign =\n loop.left.type === \"VariableDeclaration\"\n ? `${left} = ${step}.value;`\n : `(${left} = ${step}.value);`;\n return (\n `{ const ${it} = __cellbIter(${render(loop.right, inLowered)}); let ${step}; ` +\n `try { ${labels}for (;;) { ${step} = undefined; ${step} = yield ${it}.next(); ` +\n `if (${step}.done) break; { ${assign} ${render(loop.body, inLowered)} } } } ` +\n `finally { if (${step} && !${step}.done && ${it}.return) yield ${it}.return(); } }`\n );\n };\n\n const out = render(program, false);\n if (!changed) return code;\n return `${out}\\n${ASYNC_RUNNER}\\n${iterUsed ? `${ASYNC_ITERATOR}\\n` : \"\"}`;\n}\n"]}
@@ -0,0 +1,26 @@
1
+ import type { Plugin } from "esbuild";
2
+ /** A wrangler `rules` entry. */
3
+ export interface ModuleRule {
4
+ type: "ESModule" | "CommonJS" | "CompiledWasm" | "Data" | "Text" | (string & {});
5
+ globs: string[];
6
+ /** `true`: later rules of the same type (the defaults among them) apply too. */
7
+ fallthrough?: boolean;
8
+ }
9
+ /** wrangler's (and workerd's) defaults, applied after a project's own rules. */
10
+ export declare const DEFAULT_MODULE_RULES: ModuleRule[];
11
+ /**
12
+ * A glob as an esbuild filter (Go regexp) on the import specifier, as wrangler matches it
13
+ * (glob-to-regexp with globstar): `**` spans any folders, `*` stays within one, the rest is literal.
14
+ */
15
+ export declare function globFilter(glob: string): RegExp;
16
+ /**
17
+ * The rules in effect, as wrangler's `parseRules`: the project's, then the defaults. The first rule
18
+ * of a type without `fallthrough: true` closes the type: later rules of it are dropped (`ignored`
19
+ * names the project's own, unless the closing rule says `fallthrough: false`).
20
+ */
21
+ export declare function effectiveRules(userRules?: ModuleRule[]): {
22
+ rules: ModuleRule[];
23
+ ignored: string[];
24
+ };
25
+ /** The esbuild plugin applying `rules` (with the defaults) to a bundle's imports. */
26
+ export declare function moduleRulesPlugin(userRules?: ModuleRule[]): Plugin;