{"version":3,"file":"plugin.mjs","names":["#ws"],"sources":["../../src/dev-environment.ts","../../src/forwarded-host.ts","../../src/websockets.ts","../../src/dev-plugin.ts","../../src/preview-plugin.ts","../../src/plugin.ts"],"sourcesContent":["import type { ExportTypes } from \"@distilled.cloud/cloudflare-rolldown-plugin/export-types\";\nimport { isExportTypes } from \"@distilled.cloud/cloudflare-rolldown-plugin/export-types\";\nimport { MODULE_REFERENCE_REGEX } from \"@distilled.cloud/cloudflare-rolldown-plugin/plugins\";\nimport assert from \"node:assert\";\nimport * as vite from \"vite\";\nimport type { FetchFunctionOptions } from \"vite/module-runner\";\nimport {\n  ENVIRONMENT_NAME_HEADER,\n  EXPORT_TYPES_EVENT,\n  INIT_PATH,\n  REQUEST_EXPORT_TYPES_EVENT,\n} from \"./module-runner/constants.shared\";\n\n/** How long to wait for the Worker to report its export types before giving up. */\nconst EXPORT_TYPES_TIMEOUT_MS = 10_000;\n\nexport class DistilledDevEnvironment extends vite.DevEnvironment {\n  transport: HotChannel;\n\n  constructor(name: string, config: vite.ResolvedConfig) {\n    const transport = new HotChannel();\n    super(name, config, {\n      hot: true,\n      transport,\n    });\n    this.transport = transport;\n  }\n\n  async connect(address: string | URL) {\n    const url = new URL(address);\n    url.protocol = \"ws\";\n    url.pathname = INIT_PATH;\n    const ws = new WebSocket(url, {\n      headers: {\n        [ENVIRONMENT_NAME_HEADER]: this.name,\n      },\n    });\n    await new Promise<void>((resolve, reject) => {\n      ws.addEventListener(\"open\", () => {\n        resolve();\n      });\n      ws.addEventListener(\"error\", (event) => {\n        // Depending on which global WebSocket type wins (bun-types vs\n        // @types/node's undici), the event may or may not carry `error`.\n        reject(\"error\" in event ? event.error : new Error(\"WebSocket connection error\"));\n      });\n    });\n    this.transport.ws = ws;\n  }\n  override async close(): Promise<void> {\n    await super.close();\n    // `transport.close()` is idempotent; make sure the module-runner socket is\n    // released even if Vite didn't close the hot channel itself.\n    this.transport.close();\n  }\n\n  /**\n   * Asks the Worker to evaluate the entry module and classify its exports.\n   *\n   * Resolves to `undefined` if the Worker could not evaluate the entry — the\n   * error is surfaced to the user by whichever request hits the entry next, and\n   * the dev server keeps whatever export types it already has.\n   */\n  async requestExportTypes(\n    timeoutMs: number = EXPORT_TYPES_TIMEOUT_MS,\n  ): Promise<ExportTypes | undefined> {\n    return await new Promise<ExportTypes | undefined>((resolve) => {\n      let timer: ReturnType<typeof setTimeout>;\n      const listener = (data: unknown) => {\n        clearTimeout(timer);\n        this.transport.off(EXPORT_TYPES_EVENT, listener);\n        resolve(isExportTypes(data) ? data : undefined);\n      };\n      timer = setTimeout(() => {\n        this.transport.off(EXPORT_TYPES_EVENT, listener);\n        resolve(undefined);\n      }, timeoutMs);\n      this.transport.on(EXPORT_TYPES_EVENT, listener);\n      this.transport.send({ type: \"custom\", event: REQUEST_EXPORT_TYPES_EVENT });\n    });\n  }\n\n  override async fetchModule(\n    id: string,\n    importer?: string,\n    options?: FetchFunctionOptions,\n  ): Promise<vite.FetchResult> {\n    // Additional modules (CompiledWasm, Data, Text) are resolved to\n    // `__CLOUDFLARE_MODULE__...` ids and must be externalized so the module\n    // runner loads them via native `import()` → workerd's module fallback.\n    if (MODULE_REFERENCE_REGEX.test(id)) {\n      return {\n        externalize: id,\n        type: \"module\",\n      };\n    }\n    return super.fetchModule(id, importer, options);\n  }\n}\n\nclass HotChannel implements vite.HotChannel {\n  #ws?: WebSocket;\n  queue?: Array<string>;\n  listeners = new Map<string, Set<vite.HotChannelListener>>();\n\n  /**\n   * Replaces the socket, which also happens when the Worker runtime is\n   * restarted mid-session.\n   *\n   * Messages are dispatched from the moment a socket is attached rather than\n   * from `listen()`: the dev server queries the Worker for its export types\n   * during `configureServer`, which is before Vite calls `listen()`.\n   */\n  set ws(ws: WebSocket) {\n    this.#ws?.removeEventListener(\"message\", this.boundDispatch);\n    this.#ws = ws;\n    ws.addEventListener(\"message\", this.boundDispatch);\n    if (this.queue) {\n      for (const message of this.queue) {\n        ws.send(message);\n      }\n      this.queue = undefined;\n    }\n  }\n\n  send(payload: vite.CustomPayload) {\n    const json = JSON.stringify(payload);\n    if (this.#ws) {\n      this.#ws.send(json);\n    } else {\n      this.queue ??= [];\n      this.queue.push(json);\n    }\n  }\n\n  on(event: string, listener: vite.HotChannelListener) {\n    const listeners = this.listeners.get(event) ?? new Set();\n    listeners.add(listener);\n    this.listeners.set(event, listeners);\n  }\n\n  off(event: string, listener: vite.HotChannelListener) {\n    this.listeners.get(event)?.delete(listener);\n  }\n\n  private boundDispatch = this.dispatch.bind(this);\n\n  listen() {\n    assert(this.#ws, \"WebSocket is not connected\");\n    // Already dispatching — see the `ws` setter.\n  }\n\n  close() {\n    // The channel can be closed before a runner ever connected (e.g. a dev\n    // server created and torn down during a framework's type generation), so\n    // tolerate a missing socket — and close it so the runtime connection does\n    // not leak across server restarts.\n    if (!this.#ws) return;\n    this.#ws.removeEventListener(\"message\", this.boundDispatch);\n    this.#ws.close();\n    this.#ws = undefined;\n  }\n\n  private dispatch(event: MessageEvent) {\n    const payload = JSON.parse(event.data.toString()) as vite.CustomPayload;\n\n    const listeners = this.listeners.get(payload.event) ?? new Set();\n    for (const listener of listeners) {\n      listener(payload.data, this.client);\n    }\n  }\n\n  private client: vite.HotChannelClient = {\n    send: (payload) => {\n      assert(this.#ws, \"WebSocket is not connected\");\n\n      this.#ws.send(JSON.stringify(payload));\n    },\n  };\n}\n","import type { IncomingHttpHeaders } from \"node:http\";\n\n/**\n * Resolves the client-facing host of an incoming dev-server request.\n *\n * When the dev server runs behind a proxy or tunnel (e.g. ngrok or\n * `cloudflared`), the `Host` header carries the local address while the\n * public host arrives in `X-Forwarded-Host`. Preferring the forwarded host\n * lets the worker see the URL the client actually requested.\n */\nexport function resolveForwardedHost(headers: IncomingHttpHeaders, fallbackHost: string): string {\n  return (\n    firstHeaderValue(headers[\"x-forwarded-host\"]) ?? firstHeaderValue(headers.host) ?? fallbackHost\n  );\n}\n\nfunction firstHeaderValue(value: string | Array<string> | undefined): string | undefined {\n  // Proxy chains may append to a single header (\"host1, host2\") instead of\n  // repeating it; only the first entry is the client-facing host.\n  const raw = Array.isArray(value) ? value[0] : value;\n  const first = raw?.split(\",\")[0]?.trim();\n  return first ? first : undefined;\n}\n","import * as NodeHttp from \"node:http\";\nimport type { IncomingMessage } from \"node:http\";\nimport type { Duplex } from \"node:stream\";\nimport type * as vite from \"vite\";\nimport { resolveForwardedHost } from \"./forwarded-host.js\";\n\n/**\n * Handles 'upgrade' requests on the Vite HTTP server and forwards the\n * WebSocket handshake to the local workerd address as a raw HTTP upgrade.\n *\n * Returns a cleanup function that removes the listener (used on server restart).\n */\nexport function handleWebSocket(httpServer: vite.HttpServer, address: string | URL): () => void {\n  const upstreamBase = typeof address === \"string\" ? new URL(address) : address;\n\n  // Sockets hijacked by an `upgrade` are not reaped by `server.closeAllConnections()`,\n  // yet `server.close()` still waits on them — so a lingering proxied WebSocket blocks\n  // the HTTP server from closing on restart. Track live sockets and destroy them in the\n  // cleanup function to close deterministically.\n  const sockets = new Set<Duplex>();\n  const track = (socket: Duplex) => {\n    sockets.add(socket);\n    socket.on(\"close\", () => sockets.delete(socket));\n  };\n\n  const onUpgrade = (request: IncomingMessage, socket: Duplex, head: Buffer) => {\n    // Unhandled socket errors crash Node.\n    socket.on(\"error\", () => socket.destroy());\n\n    // The URL — and thus the Sandbox-origin check below — is built from the\n    // resolved (forwarded) host, not the raw `Host` header. This diverges from\n    // upstream, which keys the origin off `Host`; here it's intentional so a\n    // tunnel-fronted Sandbox preview still matches. Direct Sandbox hits carry no\n    // `X-Forwarded-Host`, so they fall back to `Host` and behave identically.\n    const rawHost = resolveForwardedHost(request.headers, \"localhost\");\n    const base = /^https?:\\/\\//i.test(rawHost) ? rawHost : `http://${rawHost}`;\n    const url = new URL(request.url ?? \"/\", base);\n\n    const isViteRequest = request.headers[\"sec-websocket-protocol\"]?.startsWith(\"vite\") ?? false;\n    const isSandboxRequest = hasSandboxOrigin(url.origin);\n\n    // Vite handles its own HMR upgrades; forward Sandbox preview URLs anyway.\n    if (isViteRequest && !isSandboxRequest) {\n      return;\n    }\n\n    const target = new URL(url.pathname + url.search, upstreamBase);\n    const upstream = NodeHttp.request({\n      hostname: target.hostname,\n      port: target.port,\n      path: target.pathname + target.search,\n      method: request.method,\n      // Forward the client-facing host so the worker sees the URL the client\n      // requested rather than the local workerd address.\n      headers: { ...request.headers, host: url.host },\n    });\n\n    const cleanup = () => {\n      upstream.destroy();\n      socket.destroy();\n    };\n\n    upstream.on(\"error\", cleanup);\n    socket.on(\"close\", () => upstream.destroy());\n\n    upstream.on(\"response\", (response) => {\n      // Worker did not accept the upgrade.\n      if (!socket.destroyed) {\n        socket.destroy();\n      }\n      response.resume();\n    });\n\n    upstream.on(\"upgrade\", (upstreamRes, upstreamSocket, upstreamHead) => {\n      upstreamSocket.on(\"error\", () => upstreamSocket.destroy());\n\n      if (socket.destroyed) {\n        upstreamSocket.destroy();\n        return;\n      }\n\n      track(socket);\n      track(upstreamSocket);\n\n      const statusLine = `HTTP/1.1 ${upstreamRes.statusCode ?? 101} ${\n        upstreamRes.statusMessage ?? \"Switching Protocols\"\n      }`;\n      const headerLines: Array<string> = [statusLine];\n      for (let i = 0; i < upstreamRes.rawHeaders.length; i += 2) {\n        headerLines.push(`${upstreamRes.rawHeaders[i]}: ${upstreamRes.rawHeaders[i + 1]}`);\n      }\n      socket.write(`${headerLines.join(\"\\r\\n\")}\\r\\n\\r\\n`);\n\n      if (upstreamHead.length > 0) {\n        socket.write(upstreamHead);\n      }\n      if (head.length > 0) {\n        upstreamSocket.write(head);\n      }\n\n      socket.pipe(upstreamSocket).pipe(socket);\n    });\n\n    // WebSocket upgrade requests carry no body, and any early client bytes are\n    // forwarded above via `upstreamSocket.write(head)`. Ending the request\n    // directly flushes the upstream handshake deterministically, rather than\n    // relying on the incoming `request` stream to emit `end` (which can be\n    // delayed by TCP timing) and avoids a second consumer of the client socket.\n    upstream.end();\n  };\n\n  httpServer.on(\"upgrade\", onUpgrade);\n  return () => {\n    httpServer.off(\"upgrade\", onUpgrade);\n    for (const socket of sockets) {\n      socket.destroy();\n    }\n    sockets.clear();\n  };\n}\n\n/**\n * Matches the origin of a Sandbox SDK preview URL.\n * See: https://developers.cloudflare.com/sandbox/concepts/preview-urls/\n *\n * Pattern: https?://<port(4+ digits)>-<id(no dots)>-<token>.localhost\n *\n * IMPORTANT: The token segment is [a-z0-9_]+ (no hyphens) to prevent ReDoS — two adjacent\n * [^.]+ groups separated by - cause quadratic backtracking on hyphen-heavy input. Tokens\n * are documented as letters/digits/underscores only.\n */\nconst SANDBOX_ORIGIN_REGEXP = /^https?:\\/\\/\\d{4,}-[^.]+-[a-z0-9_]+\\.localhost(:\\d+)?$/i;\n\nfunction hasSandboxOrigin(origin: string) {\n  return SANDBOX_ORIGIN_REGEXP.test(origin);\n}\n","import type { ExportTypes } from \"@distilled.cloud/cloudflare-rolldown-plugin/export-types\";\nimport {\n  haveExportTypesChanged,\n  isExportTypes,\n  WORKER_EXPORT_TYPES_EVENT,\n} from \"@distilled.cloud/cloudflare-rolldown-plugin/export-types\";\nimport { parseViteEnvironments } from \"@distilled.cloud/cloudflare-rolldown-plugin/options\";\nimport type { OptionsApi } from \"@distilled.cloud/cloudflare-rolldown-plugin/plugins\";\nimport { workerEntryId } from \"@distilled.cloud/cloudflare-rolldown-plugin/plugins\";\nimport { resolvePluginApi } from \"@distilled.cloud/cloudflare-rolldown-plugin/utils\";\nimport type { RuntimeServices } from \"@distilled.cloud/cloudflare-runtime\";\nimport type * as Context from \"effect/Context\";\nimport * as NodeHttp from \"node:http\";\nimport * as vite from \"vite\";\nimport { DistilledDevEnvironment } from \"./dev-environment.js\";\nimport type { ServerHandle } from \"./dev-server.js\";\nimport { configuredExportTypes, mergeExportTypes } from \"./export-types.js\";\nimport { resolveForwardedHost } from \"./forwarded-host.js\";\nimport type { CloudflareVitePluginOptions } from \"./plugin.js\";\nimport { handleWebSocket } from \"./websockets.js\";\n\nlet context: Context.Context<RuntimeServices> | undefined;\n\nexport function dev(options: CloudflareVitePluginOptions): Array<vite.Plugin> {\n  const environmentNames = parseViteEnvironments(options);\n  const configured = configuredExportTypes(options);\n  // Which exports the running Worker was generated for. Kept across dev server\n  // restarts so a restart does not undo what was detected.\n  let exportTypes: ExportTypes = configured;\n  let handle: ServerHandle | undefined;\n  let isServerRestarting = false;\n  let removeUpgradeListener: (() => void) | undefined;\n  const close = async () => {\n    removeUpgradeListener?.();\n    removeUpgradeListener = undefined;\n    await handle?.close();\n    handle = undefined;\n  };\n  let optionsApi: OptionsApi | undefined;\n  const plugins: Array<vite.Plugin> = [];\n  // The proxy middleware registers in a `configureServer` post callback, which\n  // Vite runs in plugin order — so when this plugin is appended after a\n  // framework's plugins, the framework's own post middlewares (e.g. a Node\n  // request bridge that assumes a runnable environment) would see requests\n  // first. With `middlewareOrder: \"pre\"` the proxy is instead inserted\n  // directly after Vite's internal middlewares, ahead of every other plugin's\n  // post middlewares. This companion plugin records that insertion point: its\n  // post callback runs before all normal plugins' post callbacks (it is\n  // `enforce: \"pre\"`), i.e. right after Vite registered its internal\n  // middlewares and before any other plugin registered post middlewares.\n  let middlewareBoundary: number | undefined;\n  if (options.dev?.middlewareOrder === \"pre\") {\n    plugins.push({\n      name: \"distilled-cloudflare:dev-middleware-boundary\",\n      enforce: \"pre\",\n      configureServer(server) {\n        middlewareBoundary = undefined;\n        return () => {\n          middlewareBoundary = server.middlewares.stack.length;\n        };\n      },\n    });\n  }\n  const plugin: vite.Plugin = {\n    name: \"distilled-cloudflare:dev\",\n    configResolved({ plugins }) {\n      optionsApi = resolvePluginApi<OptionsApi>(plugins ?? [], \"distilled-cloudflare:options\");\n    },\n    config() {\n      const environment: vite.EnvironmentOptions = {\n        dev: {\n          createEnvironment(name, config) {\n            // Framework integrations strip `configureServer` off this plugin\n            // when they create throwaway dev servers (e.g. Astro's type-gen\n            // during `build`/`sync`) so we don't boot workerd mid-build. In\n            // that case there is no runtime to proxy to — degrade to Vite's\n            // default runnable environment. Check this exact plugin instance\n            // (not the resolved plugin list) so multiple instances and\n            // renamed/wrapped plugins behave predictably.\n            if (!hasConfigureServerHook(plugin)) {\n              return vite.createRunnableDevEnvironment(name, config);\n            }\n            return new DistilledDevEnvironment(name, config);\n          },\n        },\n      };\n      return {\n        environments: Object.fromEntries(environmentNames.map((name) => [name, environment])),\n      };\n    },\n    async buildEnd() {\n      if (!isServerRestarting) {\n        await close();\n      }\n    },\n    async closeBundle() {\n      if (!isServerRestarting) {\n        await close();\n      }\n    },\n    async configureServer(server) {\n      const restartServer = server.restart.bind(server);\n      server.restart = async () => {\n        try {\n          isServerRestarting = true;\n          await restartServer();\n        } finally {\n          isServerRestarting = false;\n        }\n      };\n      if (!optionsApi) {\n        throw new Error(\"Cannot resolve the cloudflare-runtime:options plugin\");\n      }\n      const inputs = Object.values(optionsApi.input());\n      if (inputs.length > 1) {\n        throw new Error(\n          `Expected exactly one entry in the input, got ${inputs.length} entries: ${JSON.stringify(inputs)}`,\n        );\n      }\n      const { createDefaultContext, startServer } = await import(\"./dev-server.ts\");\n      if (!options.context) {\n        context ??= await createDefaultContext();\n      }\n      const [input] = inputs;\n      const entryEnvironment = {\n        environmentName: environmentNames[0],\n        // The module runner imports the generated Worker entry rather than the\n        // user entry: it is the module that re-exports everything the Worker\n        // needs and that reports its export types over `import.meta.hot`.\n        entryId: input ? workerEntryId(input) : input,\n        entryName: input,\n      };\n      const entryEnvironments = () =>\n        environmentNames\n          .map((name) => server.environments[name])\n          .filter((environment) => environment instanceof DistilledDevEnvironment);\n\n      const connect = async (address: string | URL) => {\n        for (const environment of entryEnvironments()) {\n          await environment.depsOptimizer?.init();\n          await environment.connect(address);\n        }\n      };\n      handle ??= await startServer(\n        options,\n        entryEnvironment,\n        server,\n        options.context ?? context!,\n        exportTypes,\n      );\n      await connect(handle.address);\n      let address = handle.address;\n\n      const bindWebSocket = () => {\n        removeUpgradeListener?.();\n        removeUpgradeListener = server.httpServer\n          ? handleWebSocket(server.httpServer, address)\n          : undefined;\n      };\n\n      /**\n       * Replaces the Worker runtime so it is regenerated for `exportTypes`.\n       * workerd needs a named export for every entrypoint, Durable Object, and\n       * Workflow class, and those exports are baked into the Worker's entry\n       * module at startup.\n       */\n      const restartRuntime = async () => {\n        await handle?.close();\n        handle = await startServer(\n          options,\n          entryEnvironment,\n          server,\n          options.context ?? context!,\n          exportTypes,\n        );\n        await connect(handle.address);\n        address = handle.address;\n        bindWebSocket();\n      };\n\n      /**\n       * Applies export types reported by the Worker. Returns `true` when they\n       * no longer match what the running Worker was generated for, in which\n       * case a runtime restart has been queued on `applying`.\n       */\n      let applying: Promise<void> = Promise.resolve();\n      const applyExportTypes = (detected: ExportTypes): boolean => {\n        const next = mergeExportTypes(configured, detected);\n        if (!haveExportTypesChanged(exportTypes, next)) {\n          return false;\n        }\n        exportTypes = next;\n        applying = applying\n          .catch(() => {})\n          .then(restartRuntime)\n          .catch((error: unknown) => {\n            server.config.logger.error(`Failed to reload the Worker runtime: ${String(error)}`, {\n              error: error instanceof Error ? error : undefined,\n              timestamp: true,\n            });\n          });\n        return true;\n      };\n\n      if (input) {\n        // Vite's internal CSS plugins rely on `buildStart` having run for the\n        // client environment before a server environment transforms a module.\n        // Vite does that while initializing the dev server, which is after\n        // this hook, and evaluating the entry now would fail without it.\n        await server.environments.client.pluginContainer.buildStart();\n        // Detect up front so that the first request already reaches a Worker\n        // exposing every entrypoint the entry module defines.\n        const detected = await entryEnvironments()[0]?.requestExportTypes();\n        if (detected && applyExportTypes(detected)) {\n          await applying;\n        }\n        // From here on the entry reports its exports over HMR every time it is\n        // re-evaluated, which is how entrypoints added later get picked up.\n        for (const environment of entryEnvironments()) {\n          environment.hot.on(WORKER_EXPORT_TYPES_EVENT, (data: unknown) => {\n            if (!isExportTypes(data) || !applyExportTypes(data)) {\n              return;\n            }\n            server.config.logger.info(\"Worker exports changed, reloading the Worker runtime.\", {\n              timestamp: true,\n            });\n          });\n        }\n      }\n\n      if (!input) {\n        // If there is no input, we are in SPA mode, so we don't need to route requests to the server.\n        return;\n      }\n      bindWebSocket();\n      return () => {\n        server.middlewares.use(function distilledCloudflareProxyMiddleware(req, res) {\n          const url = new URL(req.originalUrl ?? req.url ?? \"/\", address);\n          const request = NodeHttp.request(url, {\n            method: req.method,\n            headers: { ...req.headers, host: resolveForwardedHost(req.headers, url.host) },\n          });\n          req.pipe(request);\n          request.on(\"response\", (response) => {\n            res.writeHead(response.statusCode ?? 500, response.headers);\n            response.pipe(res);\n          });\n          // Without a listener a connection error is an unhandled `error`\n          // event, which takes down the dev server. Requests in flight while\n          // the Worker runtime is being replaced hit exactly that.\n          request.on(\"error\", (error) => {\n            server.config.logger.error(`Worker request failed: ${error.message}`, {\n              error,\n              timestamp: true,\n            });\n            if (!res.headersSent) {\n              res.writeHead(502, { \"content-type\": \"text/plain\" });\n            }\n            res.end(\"Bad Gateway\");\n          });\n        });\n        if (options.dev?.middlewareOrder === \"pre\" && middlewareBoundary !== undefined) {\n          // Move the proxy middleware from the end of the stack to directly\n          // after Vite's internal middlewares, ahead of the post middlewares\n          // other plugins registered.\n          const stack = server.middlewares.stack;\n          const entry = stack.pop();\n          if (entry) {\n            stack.splice(middlewareBoundary, 0, entry);\n          }\n        }\n      };\n    },\n  };\n  plugins.push(plugin);\n  return plugins;\n}\n\nconst hasConfigureServerHook = (plugin: vite.Plugin): boolean => {\n  const hook = plugin.configureServer;\n  if (hook == null) return false;\n  return typeof hook === \"function\" || typeof hook.handler === \"function\";\n};\n","import { parseViteEnvironments } from \"@distilled.cloud/cloudflare-rolldown-plugin/options\";\nimport type { OptionsApi } from \"@distilled.cloud/cloudflare-rolldown-plugin/plugins\";\nimport { resolvePluginApi } from \"@distilled.cloud/cloudflare-rolldown-plugin/utils\";\nimport * as NodeFs from \"node:fs\";\nimport * as NodeHttp from \"node:http\";\nimport * as NodePath from \"node:path\";\nimport type * as vite from \"vite\";\nimport { resolveForwardedHost } from \"./forwarded-host.js\";\nimport type { CloudflareVitePluginOptions } from \"./plugin.js\";\nimport { handleWebSocket } from \"./websockets.js\";\n\n/**\n * Preview mode: serve the freshly built worker through workerd.\n *\n * `vite preview` (and any framework that drives it programmatically — e.g.\n * waku's SSG step, which boots a preview server mid-`buildApp` and renders\n * every static page through it) resolves the same plugins as the build. This\n * plugin's `configurePreviewServer` hook reads the built worker output from\n * the entry environment's `build.outDir`, boots workerd over it via\n * `cloudflare-runtime`, and registers a proxy middleware ahead of Vite's\n * internal middlewares so every request — static assets included, via the\n * runtime's assets plugin — is handled exactly as on the deployed worker.\n *\n * This mirrors what upstream `@cloudflare/vite-plugin` provides via its own\n * `configurePreviewServer` (miniflare over the built output), and is what\n * makes SSG-in-workerd work: a top-level `import { env } from\n * \"cloudflare:workers\"` in a prerendered page module loads fine, because the\n * page renders inside workerd rather than the Node process.\n */\nexport function preview(options: CloudflareVitePluginOptions): vite.Plugin {\n  return {\n    name: \"distilled-cloudflare:preview\",\n    async configurePreviewServer(server) {\n      const config = server.config;\n      const optionsApi = resolvePluginApi<OptionsApi>(\n        config.plugins,\n        \"distilled-cloudflare:options\",\n      );\n      if (!optionsApi) {\n        throw new Error(\"Cannot resolve the distilled-cloudflare:options plugin\");\n      }\n      const input = optionsApi.input();\n      const inputNames = Object.keys(input);\n      if (inputNames.length === 0) {\n        // SPA mode: no worker entry — leave the preview server to Vite's\n        // static file serving.\n        return;\n      }\n      if (inputNames.length > 1) {\n        throw new Error(\n          `Expected exactly one entry in the input, got ${inputNames.length} entries: ${JSON.stringify(input)}`,\n        );\n      }\n      const [entryEnvironmentName] = parseViteEnvironments(options);\n      const entryEnvironment = config.environments[entryEnvironmentName!];\n      if (!entryEnvironment) {\n        throw new Error(\n          `Cannot resolve the \"${entryEnvironmentName}\" environment from the preview config`,\n        );\n      }\n      const directory = NodePath.resolve(config.root, entryEnvironment.build.outDir);\n      const entryModule = findEntryModule(directory, inputNames[0]!);\n      const clientEnvironment = config.environments[\"client\"];\n      const assetsDirectory = clientEnvironment\n        ? NodePath.resolve(config.root, clientEnvironment.build.outDir)\n        : undefined;\n\n      const { startPreviewServer } = await import(\"./preview-server.ts\");\n      const handle = await startPreviewServer(options, {\n        directory,\n        entryModule,\n        assetsDirectory:\n          assetsDirectory !== undefined && NodeFs.existsSync(assetsDirectory)\n            ? assetsDirectory\n            : undefined,\n      });\n      const address = handle.address;\n      const removeUpgradeListener = server.httpServer\n        ? handleWebSocket(server.httpServer, address)\n        : undefined;\n      const close = server.close.bind(server);\n      server.close = async () => {\n        removeUpgradeListener?.();\n        await handle.close();\n        await close();\n      };\n      // Registered directly (not via the returned post hook), so the proxy\n      // runs ahead of Vite's internal static-file middlewares and of any\n      // middleware a framework appends afterwards (e.g. waku's Node SSG\n      // fallback) — the worker handles every request, like in production.\n      server.middlewares.use(function distilledCloudflarePreviewMiddleware(req, res) {\n        const url = new URL(req.url ?? \"/\", address);\n        const request = NodeHttp.request(url, {\n          method: req.method,\n          headers: { ...req.headers, host: resolveForwardedHost(req.headers, url.host) },\n        });\n        req.pipe(request);\n        request.on(\"response\", (response) => {\n          res.writeHead(response.statusCode ?? 500, response.headers);\n          response.pipe(res);\n        });\n      });\n    },\n  };\n}\n\n/**\n * Locate the built entry chunk for the (single) worker input. Entry chunks\n * are emitted as `[name].js` (Vite's server-build default `entryFileNames`);\n * `.mjs` is accepted for configs that override the extension.\n */\nconst findEntryModule = (directory: string, inputName: string): string => {\n  const candidates = [`${inputName}.js`, `${inputName}.mjs`];\n  for (const candidate of candidates) {\n    if (NodeFs.existsSync(NodePath.join(directory, candidate))) {\n      return candidate;\n    }\n  }\n  throw new Error(\n    `Cannot find the built worker entry (${candidates.join(\" or \")}) in \"${directory}\". ` +\n      \"Run the build before starting the preview server.\",\n  );\n};\n","import type { BasePluginOptions } from \"@distilled.cloud/cloudflare-rolldown-plugin/options\";\nimport {\n  additionalModulesPlugin,\n  cloudflareExternalsPlugin,\n  nodejsAlsPlugin,\n  nodejsImportWarningPlugin,\n  nodejsUnenvPlugin,\n  optionsPlugin,\n  virtualModulesPlugin,\n  wasmInitPlugin,\n} from \"@distilled.cloud/cloudflare-rolldown-plugin/plugins\";\nimport type {\n  BindingHooks,\n  RuntimeServices,\n  RuntimeWorker,\n} from \"@distilled.cloud/cloudflare-runtime\";\nimport type * as Context from \"effect/Context\";\nimport type * as vite from \"vite\";\nimport { dev } from \"./dev-plugin.ts\";\nimport { preview } from \"./preview-plugin.ts\";\n\nexport interface CloudflareVitePluginDevOptions {\n  /**\n   * Where the Worker request-proxy middleware registers relative to the\n   * `configureServer` post middlewares of other plugins.\n   *\n   * - `\"post\"` (default): append in plugin order. Required by frameworks whose\n   *   own dev middlewares must see requests first (e.g. Astro's prerender\n   *   handler and dev handler).\n   * - `\"pre\"`: insert directly after Vite's internal middlewares, ahead of the\n   *   post middlewares other plugins registered. Use this when appending the\n   *   Cloudflare plugin after a framework's config-file plugins and the\n   *   framework registers its own Node request-bridge middleware that cannot\n   *   handle the Worker environment (e.g. Waku's RSC bridge, which assumes a\n   *   runnable Node environment).\n   *\n   * @default \"post\"\n   */\n  middlewareOrder?: \"pre\" | \"post\";\n}\n\nexport interface CloudflareVitePluginOptions<\n  B extends BindingHooks = BindingHooks,\n> extends BasePluginOptions {\n  worker?: Omit<RuntimeWorker<B>, \"compatibilityDate\" | \"compatibilityFlags\" | \"modules\">;\n  context?: Context.Context<RuntimeServices>;\n  dev?: CloudflareVitePluginDevOptions;\n}\n\nexport default function cloudflareVitePlugin(\n  options: CloudflareVitePluginOptions = {},\n): vite.PluginOption {\n  return [\n    optionsPlugin.vite(options),\n    cloudflareExternalsPlugin.vite(options),\n    nodejsAlsPlugin.vite(options),\n    nodejsImportWarningPlugin.vite(options),\n    nodejsUnenvPlugin.vite(options),\n    virtualModulesPlugin.vite(options),\n    wasmInitPlugin.vite(options),\n    additionalModulesPlugin.vite(options),\n    {\n      name: \"distilled-cloudflare:rsc\",\n      enforce: \"pre\",\n      config() {\n        return { rsc: { serverHandler: false } } as vite.UserConfig;\n      },\n    } as vite.Plugin,\n    ...dev(options),\n    preview(options),\n    // Some of the composed plugins are conditional (e.g. the nodejs-compat\n    // family) and resolve to `null`; filter them out so integrations that\n    // post-process the returned plugins don't have to handle sparse entries.\n  ].filter((plugin): plugin is vite.Plugin => plugin !== null);\n}\n"],"mappings":"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"}