{"version":3,"file":"create-entrypoint-CuRJVzTp.mjs","names":[],"sources":["../src/tako/create-entrypoint.ts"],"sourcesContent":["/**\n * Creates a Tako entrypoint for any JS runtime.\n *\n * Each runtime-specific entrypoint calls `createEntrypoint` which handles\n * the runtime-agnostic boot flow.\n *\n * CLI args (appended by tako-server):\n *   <main> --instance <id>\n */\n\nimport { isAbsolute, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { handleTakoEndpoint } from \"./endpoints\";\nimport { normalizeFetchResponse } from \"./fetch-response\";\nimport { writeViaInheritedFd } from \"./readiness\";\nimport { bootstrapChannels } from \"../channels/bootstrap\";\nimport type { ChannelRegistry } from \"../channels\";\nimport { initServerRuntime } from \"./init\";\nimport type { FetchFunction, ReadyableFetchHandler, TakoStatus } from \"../types\";\n\n/** Exported for tests and for runtime entrypoints that want the default impl. */\nexport const signalReadyPortOnFd = writeViaInheritedFd;\n\ninterface ParsedArgs {\n  main: string;\n  instance: string;\n}\n\nfunction parseArgs(argv: string[]): ParsedArgs {\n  const args = argv.slice(2);\n  let main = \"\";\n  let instance = \"unknown\";\n\n  for (let i = 0; i < args.length; i++) {\n    switch (args[i]) {\n      case \"--instance\":\n        instance = args[++i] ?? \"unknown\";\n        break;\n      default:\n        if (!main && !args[i]?.startsWith(\"--\")) {\n          main = args[i] ?? \"\";\n        }\n        break;\n    }\n  }\n\n  return { main, instance };\n}\n\nfunction statusAppName(): string {\n  const [appName = \"\"] = (process.env[\"TAKO_APP_NAME\"] || \"app\").split(\"/\");\n  return appName || \"app\";\n}\n\nexport function createEntrypoint() {\n  const signalReadyPort = (port: number): void => writeViaInheritedFd(4, port);\n\n  const parsed = parseArgs(process.argv);\n  const port = parseInt(process.env[\"PORT\"] || \"3000\", 10);\n  const host = process.env[\"HOST\"] || \"127.0.0.1\";\n\n  const startedAt = Date.now();\n  let currentStatus: TakoStatus[\"status\"] = \"starting\";\n\n  function getStatus(): TakoStatus {\n    return {\n      status: currentStatus,\n      app: statusAppName(),\n      version: process.env[\"TAKO_BUILD\"] || \"unknown\",\n      instance_id: parsed.instance,\n      pid: process.pid,\n      uptime_seconds: Math.floor((Date.now() - startedAt) / 1000),\n    };\n  }\n\n  function setDraining(): void {\n    currentStatus = \"draining\";\n  }\n\n  async function run(\n    startServer: (\n      handleRequest: (request: Request) => Promise<Response>,\n    ) => number | void | Promise<number | void>,\n  ): Promise<void> {\n    if (!parsed.main) {\n      console.error(\"Usage: <runtime> entrypoint <main> [--instance <id>]\");\n      process.exit(1);\n    }\n\n    initServerRuntime();\n\n    let channels: ChannelRegistry;\n    try {\n      const result = await bootstrapChannels({ appDir: process.cwd() });\n      channels = result.registry;\n    } catch (err) {\n      console.error(\"Failed to load channels directory:\", err);\n      process.exit(1);\n    }\n\n    let userFetch: FetchFunction;\n    let userReady: (() => void | Promise<void>) | null = null;\n    try {\n      // `parsed.main` is a filesystem path from the spawner's launch args,\n      // relative to the app cwd. Convert to a file:// URL so dynamic\n      // `import()` resolves it against the app — not the SDK module URL,\n      // which lives under `node_modules/tako.sh/dist/`.\n      const mainPath = isAbsolute(parsed.main) ? parsed.main : resolve(process.cwd(), parsed.main);\n      const mainUrl = pathToFileURL(mainPath).href;\n      const module = (await import(/* @vite-ignore */ mainUrl)) as { default?: unknown };\n      const defaultExport = module.default;\n      if (typeof defaultExport === \"function\") {\n        const readyable = defaultExport as ReadyableFetchHandler;\n        userFetch = readyable;\n        if (typeof readyable.ready === \"function\") {\n          userReady = () => readyable.ready?.();\n        }\n      } else if (\n        defaultExport &&\n        typeof defaultExport === \"object\" &&\n        typeof (defaultExport as { fetch?: unknown }).fetch === \"function\"\n      ) {\n        const obj = defaultExport as { fetch: FetchFunction; ready?: () => void | Promise<void> };\n        userFetch = obj.fetch;\n        if (typeof obj.ready === \"function\") {\n          const ready = obj.ready;\n          userReady = () => ready();\n        }\n      } else {\n        throw new Error(\"App must export a default fetch function or { fetch } object.\");\n      }\n    } catch (err) {\n      console.error(`Failed to import app from ${parsed.main}:`, err);\n      process.exit(1);\n    }\n\n    if (userReady) {\n      try {\n        await userReady();\n      } catch (err) {\n        console.error(`Failed to initialize app readiness from ${parsed.main}:`, err);\n        process.exit(1);\n      }\n    }\n\n    const env: Record<string, string> = {};\n    for (const [key, value] of Object.entries(process.env)) {\n      if (value !== undefined) {\n        env[key] = value;\n      }\n    }\n\n    const handleRequest = async (request: Request): Promise<Response> => {\n      const takoResponse = await handleTakoEndpoint(request, getStatus(), channels);\n      if (takoResponse) {\n        return takoResponse;\n      }\n\n      try {\n        return normalizeFetchResponse(await userFetch(request, env));\n      } catch (err) {\n        console.error(\"Error in user fetch handler:\", err);\n        return new Response(JSON.stringify({ error: \"Internal Server Error\" }), {\n          status: 500,\n          headers: { \"Content-Type\": \"application/json\" },\n        });\n      }\n    };\n\n    const actualPort = await startServer(handleRequest);\n    currentStatus = \"healthy\";\n    if (actualPort != null) {\n      signalReadyPort(actualPort);\n    }\n  }\n\n  return { run, host, port, setDraining };\n}\n"],"mappings":"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"}