import{loadDevelopmentEnvironmentFiles}from"#cli/dev/environment.js";import{pruneDevelopmentRuntimeArtifactsSnapshotsInBackground}from"#internal/nitro/dev-runtime-artifacts.js";import{build,createDevServer,prepare}from"nitro/builder";import{createApplicationNitro}from"#internal/nitro/host/create-application-nitro.js";import{prepareApplicationHost}from"#internal/nitro/host/prepare-application-host.js";import{createNitroArtifactsConfig}from"#internal/nitro/host/artifacts-config.js";import{resolveNitroCompiledArtifactsSource}from"#internal/nitro/routes/runtime-artifacts.js";import{prewarmAppSandboxes}from"#execution/sandbox/prewarm.js";import{pruneLocalSandboxTemplatesInBackground}from"#execution/sandbox/bindings/local.js";const MAX_ALLOWED_DEVELOPMENT_SERVER_PORT=65535,WORKFLOW_LOCAL_BASE_URL_ENV=`WORKFLOW_LOCAL_BASE_URL`,PORT_ENV=`PORT`,WILDCARD_LISTEN_HOSTNAMES=new Set([`[::]`,`::`,`0.0.0.0`]);function normalizeDevelopmentServerClientUrl(e){let t=new URL(e);return WILDCARD_LISTEN_HOSTNAMES.has(t.hostname)?(t.hostname=`127.0.0.1`,t.toString()):e}function isAddressInUseError(e){return e instanceof Error&&`code`in e&&e.code===`EADDRINUSE`}function resolveDevelopmentServerPort(e){let t=typeof e==`string`?Number(e):e??3e3;if(!Number.isInteger(t)||t<0||t>MAX_ALLOWED_DEVELOPMENT_SERVER_PORT)throw Error(`Invalid development server port "${String(e)}". Expected an integer between 0 and ${MAX_ALLOWED_DEVELOPMENT_SERVER_PORT}.`);return t}function readEnvironmentPort(){let e=process.env[PORT_ENV];if(e===void 0||e.trim()===``)return;let t=Number(e);if(!Number.isInteger(t)||t<0||t>MAX_ALLOWED_DEVELOPMENT_SERVER_PORT)throw Error(`Invalid ${PORT_ENV} environment variable "${e}". Expected an integer between 0 and ${MAX_ALLOWED_DEVELOPMENT_SERVER_PORT}.`);return t}function resolveDevelopmentServerPorts(e){let t=resolveDevelopmentServerPort(e.port);if(t===0||!e.retryOnAddressInUse)return[t];let n=[];for(let e=0;e<10;e+=1){let r=t+e;if(r>65535)break;n.push(r)}return n}function installWorkflowLocalQueueEnvironment(e){let t=process.env[WORKFLOW_LOCAL_BASE_URL_ENV],n=process.env[PORT_ENV],r=new URL(normalizeDevelopmentServerClientUrl(e));return process.env[WORKFLOW_LOCAL_BASE_URL_ENV]=r.origin,r.port&&(process.env[PORT_ENV]=r.port),()=>{t===void 0?delete process.env[WORKFLOW_LOCAL_BASE_URL_ENV]:process.env[WORKFLOW_LOCAL_BASE_URL_ENV]=t,n===void 0?delete process.env[PORT_ENV]:process.env[PORT_ENV]=n}}function attachTemporarySocketErrorHandler(e){let onSocketError=()=>{};return e.once(`error`,onSocketError),()=>{e.off(`error`,onSocketError)}}function shouldProxyDevelopmentServerWebSocketUpgrades(e){return e.options.features.websocket===!0||e.options.experimental.websocket===!0}function guardDevelopmentServerWebSocketUpgrades(e,t){let n=t.upgrade.bind(t),r=shouldProxyDevelopmentServerWebSocketUpgrades(e);t.upgrade=async(e,t,i)=>{if(!r){t.destroyed||t.destroy();return}let a=attachTemporarySocketErrorHandler(t);try{await n(e,t,i)}catch{t.destroyed||t.destroy()}finally{a()}}}async function listenForDevelopmentServer(e){let t=resolveDevelopmentServerPorts({port:e.port,retryOnAddressInUse:e.retryOnAddressInUse}),n;for(let r of t){let t=e.devServer.listen({hostname:e.host,port:r,silent:!0});try{return await t.ready(),t}catch(r){if(n=r,await t.close().catch(()=>{}),!isAddressInUseError(r)||!e.retryOnAddressInUse)throw r}}throw Error(`Failed to start Nitro dev server after ${t.length} attempts. Tried ports ${t.join(`, `)}.`,{cause:n})}async function startDevelopmentServer(o,s={}){loadDevelopmentEnvironmentFiles(o);let c=await prepareApplicationHost(o,{dev:!0});pruneDevelopmentRuntimeArtifactsSnapshotsInBackground(c.appRoot);let l=resolveNitroCompiledArtifactsSource(createNitroArtifactsConfig({appRoot:c.appRoot,dev:!0}));await prewarmAppSandboxes({appRoot:c.appRoot,compiledArtifactsSource:l,log:e=>console.log(e)}),pruneLocalSandboxTemplatesInBackground(c.appRoot);let u=await createApplicationNitro(c,!0),d=createDevServer(u);guardDevelopmentServerWebSocketUpgrades(u,d);let f=s.host??u.options.devServer.hostname,p=s.port??readEnvironmentPort(),m=p??u.options.devServer.port,h=p===void 0,g,_;try{let e=await listenForDevelopmentServer({devServer:d,host:f,port:m,retryOnAddressInUse:h});if(!e.url)throw Error(`Nitro dev server did not expose a URL.`);g=installWorkflowLocalQueueEnvironment(e.url),await prepare(u),await build(u);let{startAuthoredSourceWatcher:t}=await import(`#internal/nitro/host/dev-authored-source-watcher.js`);_=await t({nitro:u,preparedHost:c});let r=g;if(r===void 0)throw Error(`Workflow local queue environment was not initialized.`);let a=_;return{async close(){try{await a.close(),await d.close(),await u.close()}finally{r()}},url:normalizeDevelopmentServerClientUrl(e.url)}}catch(e){throw await _?.close().catch(()=>{}),g?.(),await d.close().catch(()=>{}),await u.close().catch(()=>{}),e}}export{normalizeDevelopmentServerClientUrl,startDevelopmentServer};