{
  "version": 3,
  "sources": ["../../../../src/workers/core/dev-registry-proxy.worker.ts", "../../../../src/workers/core/dev-registry-proxy-shared.worker.ts"],
  "sourcesContent": ["import { WorkerEntrypoint } from \"cloudflare:workers\";\nimport {\n\tresolveTarget,\n\ttailEventsReplacer,\n\ttailEventsReviver,\n\tworkerNotFoundMessage,\n} from \"./dev-registry-proxy-shared.worker\";\nimport type { WorkerdDebugPortConnector } from \"./dev-registry-proxy-shared.worker\";\n\nexport {\n\tcreateProxyDurableObjectClass,\n\tsetRegistry,\n} from \"./dev-registry-proxy-shared.worker\";\n\nconst HANDLER_RESERVED_KEYS = new Set([\n\t\"alarm\",\n\t\"connect\",\n\t\"self\",\n\t\"tail\",\n\t\"tailStream\",\n\t\"test\",\n\t\"trace\",\n\t\"webSocketClose\",\n\t\"webSocketError\",\n\t\"webSocketMessage\",\n]);\n\ninterface Env {\n\tDEV_REGISTRY_DEBUG_PORT: WorkerdDebugPortConnector;\n}\n\ninterface Props {\n\tservice: string;\n\tentrypoint: string | null;\n\t// User-supplied `props` from the original service binding / tail consumer.\n\t// Forwarded to the remote entrypoint via the debug port so they are\n\t// available as `ctx.props` on the callee.\n\tuserProps?: Record<string, unknown>;\n}\n\nfunction resolve(props: Props, env: Env): Fetcher | null {\n\tconst { service, entrypoint, userProps } = props;\n\tconst target = resolveTarget(service);\n\tif (!target || !target.debugPortAddress) {\n\t\treturn null;\n\t}\n\tconst serviceName =\n\t\tentrypoint === null || entrypoint === \"default\"\n\t\t\t? target.defaultEntrypointService\n\t\t\t: target.userWorkerService;\n\tconst client = env.DEV_REGISTRY_DEBUG_PORT.connect(target.debugPortAddress);\n\treturn client.getEntrypoint(serviceName, entrypoint ?? undefined, userProps);\n}\n\nexport class ExternalServiceProxy extends WorkerEntrypoint<Env, Props> {\n\t_fetcher: Fetcher | null = null;\n\t_entryFetcher: Fetcher | null = null;\n\n\tconstructor(ctx: ExecutionContext<Props>, env: Env) {\n\t\tsuper(ctx, env);\n\t\tthis._fetcher = resolve(ctx.props, env);\n\n\t\t// Separate connection for scheduled: the debug port's EventDispatcher\n\t\t// doesn't support runScheduled/runAlarm/queue, so we forward via HTTP.\n\t\tconst target = resolveTarget(ctx.props.service);\n\t\tif (target && target.debugPortAddress) {\n\t\t\tconst client = env.DEV_REGISTRY_DEBUG_PORT.connect(\n\t\t\t\ttarget.debugPortAddress\n\t\t\t);\n\t\t\tthis._entryFetcher = client.getEntrypoint(\"core:entry\");\n\t\t}\n\n\t\treturn new Proxy(this, {\n\t\t\tget(target, prop) {\n\t\t\t\tif (Reflect.has(target, prop)) {\n\t\t\t\t\treturn Reflect.get(target, prop);\n\t\t\t\t}\n\t\t\t\tif (typeof prop === \"string\" && HANDLER_RESERVED_KEYS.has(prop)) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\tif (!target._fetcher) {\n\t\t\t\t\tthrow new Error(workerNotFoundMessage(ctx.props.service));\n\t\t\t\t}\n\t\t\t\treturn Reflect.get(target._fetcher, prop);\n\t\t\t},\n\t\t});\n\t}\n\n\tfetch(request: Request): Promise<Response> | Response {\n\t\tif (!this._fetcher) {\n\t\t\treturn new Response(workerNotFoundMessage(this.ctx.props.service), {\n\t\t\t\tstatus: 503,\n\t\t\t});\n\t\t}\n\t\treturn this._fetcher.fetch(request);\n\t}\n\n\tasync scheduled(controller: ScheduledController) {\n\t\tif (!this._entryFetcher) {\n\t\t\tthrow new Error(workerNotFoundMessage(this.ctx.props.service));\n\t\t}\n\t\tconst params = new URLSearchParams();\n\t\tif (controller.cron) {\n\t\t\tparams.set(\"cron\", controller.cron);\n\t\t}\n\t\tif (controller.scheduledTime) {\n\t\t\tparams.set(\"time\", String(controller.scheduledTime));\n\t\t}\n\t\tconst response = await this._entryFetcher.fetch(\n\t\t\tnew Request(`http://localhost/cdn-cgi/handler/scheduled?${params}`, {\n\t\t\t\theaders: { \"MF-Route-Override\": this.ctx.props.service },\n\t\t\t})\n\t\t);\n\t\tif (!response.ok) {\n\t\t\tconst body = await response.text();\n\t\t\tthrow new Error(\n\t\t\t\t`Scheduled handler returned HTTP ${response.status}: ${body}`\n\t\t\t);\n\t\t}\n\t}\n\n\t// Forward tail events to the remote worker via RPC.\n\t// Events with rpcMethod===\"tail\" are filtered out to prevent infinite\n\t// recursion (the remote tail() call would itself produce a tail event).\n\ttail(events: TraceItem[]) {\n\t\tif (!this._fetcher) {\n\t\t\treturn;\n\t\t}\n\t\tconst filtered = events.filter(\n\t\t\t(e) => (e.event as { rpcMethod?: string } | null)?.rpcMethod !== \"tail\"\n\t\t);\n\t\tif (filtered.length === 0) {\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tconst serializedEvents = JSON.parse(\n\t\t\t\tJSON.stringify(filtered, tailEventsReplacer),\n\t\t\t\ttailEventsReviver\n\t\t\t);\n\t\t\t// @ts-expect-error .tail is not in the `Fetcher` type but it's a valid RPC call\n\t\t\treturn this._fetcher.tail(serializedEvents);\n\t\t} catch (e) {\n\t\t\tconsole.warn(\n\t\t\t\t`[dev-registry] Failed to forward tail events to \"${\n\t\t\t\t\tthis.ctx.props.service\n\t\t\t\t}\": ${e instanceof Error ? e.message : String(e)}`\n\t\t\t);\n\t\t}\n\t}\n}\n", "import { DurableObject } from \"cloudflare:workers\";\n\n/**\n * Represents the workerd debug port's ability to open connections to other\n * workerd instances by address. Mirrors the Cap'n Proto RPC interface exposed\n * by the workerd debug port.\n *\n * @see https://github.com/cloudflare/workerd/blob/main/src/workerd/server/server.c++\n */\nexport interface WorkerdDebugPortConnector {\n\tconnect(address: string): WorkerdDebugPortClient;\n}\n\n/**\n * A connected debug port client that can resolve service entrypoints and\n * Durable Object actors on a remote workerd instance.\n */\nexport interface WorkerdDebugPortClient {\n\tgetEntrypoint(\n\t\tservice: string,\n\t\tentrypoint?: string,\n\t\tprops?: Record<string, unknown>\n\t): Fetcher;\n\tgetActor(service: string, entrypoint: string, actorId: string): Fetcher;\n}\n\n/**\n * A dev registry entry describing how to reach a worker's debug port and\n * which workerd services correspond to its default entrypoint and user code.\n */\nexport interface RegistryEntry {\n\tdebugPortAddress: string;\n\tdefaultEntrypointService: string;\n\tuserWorkerService: string;\n}\n\nlet registry = new Map<string, RegistryEntry>();\n\n/**\n * Replace the in-memory registry with the given entries.\n * Called whenever the Node.js side pushes an updated registry snapshot.\n */\nexport function setRegistry(data: Record<string, RegistryEntry>): void {\n\tregistry = new Map(Object.entries(data));\n}\n\n/**\n * Look up a worker's registry entry by service name.\n */\nexport function resolveTarget(service: string): RegistryEntry | undefined {\n\tconst entry = registry.get(service);\n\tif (!entry || !(\"debugPortAddress\" in entry)) {\n\t\treturn undefined;\n\t}\n\treturn entry;\n}\n\n/**\n * Check whether a registry entry exists for the given service, even if it's\n * from an incompatible wrangler version.\n */\nexport function hasRegistryEntry(service: string): boolean {\n\treturn registry.has(service);\n}\n\n/**\n * Return an appropriate error message for a worker that can't be resolved.\n */\nexport function workerNotFoundMessage(service: string): string {\n\tif (hasRegistryEntry(service)) {\n\t\treturn `Worker \"${service}\" is not compatible with this version of the dev server. Please update all Worker instances to the same version.`;\n\t}\n\treturn `Worker \"${service}\" not found. Make sure it is running locally.`;\n}\n\n/**\n * Connect to a Durable Object actor on a remote workerd instance via the\n * debug port, returning a {@link Fetcher} that proxies requests to it.\n */\nexport function connectToActor(\n\tdebugPort: WorkerdDebugPortConnector,\n\tscriptName: string,\n\tclassName: string,\n\tactorId: string\n): Fetcher | null {\n\tconst target = resolveTarget(scriptName);\n\tif (!target || !target.debugPortAddress) {\n\t\treturn null;\n\t}\n\tconst client = debugPort.connect(target.debugPortAddress);\n\treturn client.getActor(target.userWorkerService, className, actorId);\n}\n\n/**\n * Create a {@link DurableObject} subclass that proxies all method calls\n * and fetch requests to a Durable Object running in a separate workerd\n * instance via the debug port RPC. Uses a {@link Proxy} to forward\n * arbitrary RPC method calls to the remote actor's {@link Fetcher}.\n */\nexport function createProxyDurableObjectClass({\n\tscriptName,\n\tclassName,\n}: {\n\tscriptName: string;\n\tclassName: string;\n}): typeof DurableObject {\n\treturn class extends DurableObject<{\n\t\tDEV_REGISTRY_DEBUG_PORT: WorkerdDebugPortConnector;\n\t}> {\n\t\t_cachedFetcher: Fetcher | undefined;\n\t\t_cachedDebugPortAddress: string | undefined;\n\n\t\t// Lazily resolve and cache. Invalidates when debugPortAddress changes.\n\t\t_resolve(): Fetcher | null {\n\t\t\tconst target = resolveTarget(scriptName);\n\t\t\tif (\n\t\t\t\tthis._cachedFetcher &&\n\t\t\t\ttarget?.debugPortAddress === this._cachedDebugPortAddress\n\t\t\t) {\n\t\t\t\treturn this._cachedFetcher;\n\t\t\t}\n\t\t\tthis._cachedFetcher = undefined;\n\t\t\tthis._cachedDebugPortAddress = undefined;\n\n\t\t\tconst fetcher = connectToActor(\n\t\t\t\tthis.env.DEV_REGISTRY_DEBUG_PORT,\n\t\t\t\tscriptName,\n\t\t\t\tclassName,\n\t\t\t\tthis.ctx.id.toString()\n\t\t\t);\n\t\t\tif (fetcher && target) {\n\t\t\t\tthis._cachedFetcher = fetcher;\n\t\t\t\tthis._cachedDebugPortAddress = target.debugPortAddress;\n\t\t\t}\n\t\t\treturn fetcher;\n\t\t}\n\n\t\tconstructor(\n\t\t\tctx: DurableObjectState,\n\t\t\tenv: { DEV_REGISTRY_DEBUG_PORT: WorkerdDebugPortConnector }\n\t\t) {\n\t\t\tsuper(ctx, env);\n\n\t\t\treturn new Proxy(this, {\n\t\t\t\tget(target, prop) {\n\t\t\t\t\tif (Reflect.has(target, prop)) {\n\t\t\t\t\t\treturn Reflect.get(target, prop);\n\t\t\t\t\t}\n\t\t\t\t\tconst fetcher = target._resolve();\n\t\t\t\t\tif (!fetcher) {\n\t\t\t\t\t\t// Return a function-that-throws rather than throwing immediately:\n\t\t\t\t\t\t// workerd probes DO properties (fetch, alarm, etc.) via the get\n\t\t\t\t\t\t// trap, and throwing here would crash those internal checks.\n\t\t\t\t\t\treturn () => {\n\t\t\t\t\t\t\tthrow new Error(workerNotFoundMessage(scriptName));\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\treturn Reflect.get(fetcher, prop);\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\tfetch(request: Request): Promise<Response> {\n\t\t\tconst fetcher = this._resolve();\n\t\t\tif (!fetcher) {\n\t\t\t\treturn Promise.resolve(\n\t\t\t\t\tnew Response(workerNotFoundMessage(scriptName), { status: 503 })\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn fetcher.fetch(request);\n\t\t}\n\t} as unknown as typeof DurableObject;\n}\n\nconst SERIALIZED_DATE = \"___serialized_date___\";\nconst SERIALIZED_BIGINT = \"___serialized_bigint___\";\n\n/**\n * JSON replacer that serializes `Date` and `bigint` values into tagged\n * objects so they survive a JSON round-trip in tail event forwarding.\n */\nexport function tailEventsReplacer(_: string, value: any) {\n\tif (value instanceof Date) {\n\t\treturn { [SERIALIZED_DATE]: value.toISOString() };\n\t} else if (typeof value === \"bigint\") {\n\t\treturn { [SERIALIZED_BIGINT]: value.toString() };\n\t}\n\treturn value;\n}\n\n/**\n * JSON reviver that restores `Date` and `bigint` values from the tagged\n * objects produced by {@link tailEventsReplacer}.\n */\nexport function tailEventsReviver(_: string, value: any) {\n\tif (value && typeof value === \"object\") {\n\t\tif (SERIALIZED_DATE in value) {\n\t\t\treturn new Date(value[SERIALIZED_DATE]);\n\t\t} else if (SERIALIZED_BIGINT in value) {\n\t\t\treturn BigInt(value[SERIALIZED_BIGINT]);\n\t\t}\n\t}\n\treturn value;\n}\n"],
  "mappings": "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",
  "names": ["target"]
}
