@lunora/cli 1.0.0-alpha.487 → 1.0.0-alpha.489
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.
- package/dist/index.d.mts +8 -18
- package/dist/index.d.ts +8 -18
- package/dist/index.mjs +1 -1
- package/dist/packem_chunks/cli.mjs +1 -1
- package/dist/packem_chunks/dispatch.mjs +1 -1
- package/dist/packem_chunks/handler.mjs +1 -1
- package/dist/packem_chunks/handler31.mjs +1 -1
- package/dist/packem_chunks/handler9.mjs +1 -1
- package/dist/packem_chunks/runDevCommand.mjs +7 -7
- package/dist/packem_shared/binding-manifest-file-BZyQFSTF.mjs +2 -0
- package/dist/packem_shared/diffSnapshots-DcE-jQUz.mjs +9 -0
- package/dist/packem_shared/plan-BF2E-dq4.mjs +5 -0
- package/dist/packem_shared/{planDevCommand-Jr0dFWPV.mjs → planDevCommand-C8QHZzEJ.mjs} +1 -1
- package/dist/packem_shared/{runDeployCommand-BZA7xzuz.mjs → runDeployCommand-D4hsYdg0.mjs} +1 -1
- package/dist/packem_shared/{runMigrateGenerateCommand-CguLEIZp.mjs → runMigrateGenerateCommand-DHdSMKbu.mjs} +1 -1
- package/dist/packem_shared/{schemaIrToSnapshot-Ck7DSPdf.mjs → schemaIrToSnapshot-CbWOjany.mjs} +1 -1
- package/package.json +5 -5
- package/dist/packem_shared/binding-manifest-file-CQ1eQYy1.mjs +0 -2
- package/dist/packem_shared/diffSnapshots-Y1G8am6C.mjs +0 -7
- package/dist/packem_shared/plan-BH6l7s48.mjs +0 -5
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import{existsSync as q,mkdirSync as Te,openSync as J,closeSync as X,statSync as Pe,readFileSync as Q,readSync as be}from"node:fs";import{join as N,dirname as _e}from"node:path";import{readDevServiceBindings as $e}from"@lunora/codegen";import{readLiveDevServerState as C,discoverContainerInfo as Re,streamContainerLogs as Ne,formatLunoraEvent as Ce,updateDevServerState as b,resolveLazyFunctions as Z,targetRunsOwnDevServer as D,resolveProjectTarget as ee,claimDevServerState as De,DEV_HANDOFF_ENV as Oe,clearDevServerState as E,readDevServerState as O,isDevServerReady as j,detectFramework as re,readProjectDependencyNames as xe,DEV_LOG_FILE_ENV as Ae,DEV_DAEMON_ENV as Me,LAZY_FUNCTIONS_ENV as Ue,readProjectManifest as Ge,isRecordedProcessCurrent as Fe,DEV_LOG_FILE as je,CODEGEN_ENV as te,isCodegenDisabled as Ve,planToolchainInvocation as We,startCelldDevSession as Be,resolveDeployDriver as ne,DEV_VARS_FILE as oe,parseDevVariableEntries as Ke,resolveSchemaDirectory as ze}from"@lunora/config";import{warnCloudflareCliConfigOnce as He,findWranglerFile as L,readWranglerJsonc as x,materializeDevWranglerConfig as Ye,materializeServiceDevConfigs as qe}from"@lunora/config/cloudflare";import{f as Je}from"./free-port-DjbFhaaT.mjs";import{networkInterfaces as Xe}from"node:os";import{spawn as ie,spawnSync as T}from"node:child_process";import{setTimeout as w}from"node:timers/promises";import{EXIT_CODE as se}from"./EXIT_CODE-DQVhSE-1.mjs";import{a as h}from"./output-format-DWe_tkTR.mjs";import{spawnShellCompat as ae,defaultSpawner as Qe}from"./createRecordingSpawner-DchLi0gR.mjs";import{isLunoraError as Ze}from"@lunora/errors";import{s as V}from"./index-oHZBGBwB.mjs";import{createInterface as er}from"node:readline";import{detectPackageManager as A,execArgsFor as ce,toolchainExecArgs as le,runScriptCommand as rr}from"@lunora/config/cli";const tr=12e4,_=250,nr=1e3,or="LUNORA_DEV_READY_TIMEOUT_MS",ir=e=>{if(e!==void 0)return e;const r=Number(process.env[or]??"");return Number.isFinite(r)&&r>0?r:tr},sr=async(e,r)=>{try{const n=AbortSignal.timeout(nr);return await(await fetch(new URL("/_lunora/status",e),{redirect:"manual",signal:r===void 0?n:AbortSignal.any([r,n])})).body?.cancel(),!0}catch{return!1}},de=async(e,r,n)=>{const t=Date.now()+n.timeoutMs;for(;n.signal?.aborted!==!0;){const o=r(C(e));if(o!==void 0)return o;if(Date.now()>=t)return;try{await w(n.intervalMs??500,void 0,{signal:n.signal})}catch{return}}},W=(e,r)=>{er({crlfDelay:Number.POSITIVE_INFINITY,input:e}).on("line",r)},ar=5e3,ue=(e,r,n,t)=>{if(e.length===0)return;const o=Ce(e);if(o){t[o.level](`[lunora] ${o.text}`);return}const i=`[${r}] ${e}`;n==="stderr"?t.warn(i):t.info(i)},cr=(e,r,n=process.platform,t=T)=>{try{if(r==="SIGKILL"&&n==="win32"&&e.pid!==void 0){t("taskkill",["/pid",String(e.pid),"/T","/F"],{stdio:"ignore"});return}e.kill(r)}catch{}},fe=(e,r,n)=>{const t=e.direct===!0?{args:[...e.args],command:e.command,shell:!1}:ae(e.command,e.args),o=ie(t.command,t.args,{cwd:e.cwd??process.cwd(),env:e.env?{...process.env,...e.env}:process.env,shell:t.shell,stdio:[e.direct===!0?"ignore":"inherit","pipe","pipe"]});return W(o.stdout,i=>{r(i,"stdout")}),W(o.stderr,i=>{r(i,"stderr")}),{exited:new Promise(i=>{o.on("error",s=>{n?.(s),i(1)}),o.on("exit",(s,a)=>{i(s??(a?1:0))})}),kill:i=>{cr(o,i)}}},gt=(e,r)=>fe(e,(n,t)=>{ue(n.trimEnd(),e.tag,t,r)},n=>{r.error(`[${e.tag}] failed to start: ${n.message}`)}),pt=(e,r)=>{if(process.env.LUNORA_CONTAINER_LOGS==="0")return;const t=Re(e,"lunora").containers.map(o=>({className:o.className,exportName:o.exportName}));if(t.length!==0)return Ne({containers:t,onLine:o=>{const i=`[container:${o.name}] ${o.text}`;o.level==="error"?r.warn(i):r.info(i)},onUnavailable:o=>{r.warn(`[container] Docker engine unreachable — container logs unavailable (${o})`)}})},mt=async e=>{e.readyProbe?.abort(),await e.tunnel?.close(),await e.codegen?.close().catch(()=>{}),e.containerLogs?.close(),await e.studio?.close().catch(()=>{}),await e.hyperdrive?.stop().catch(()=>{});try{e.remoteCleanup?.(),e.serviceConfigCleanup?.()}catch{}},wt=async e=>await new Promise(r=>{const n={},t=s=>{e.info(`received ${s} — shutting down`),n.sigint&&process.off("SIGINT",n.sigint),n.sigterm&&process.off("SIGTERM",n.sigterm),r(0)},o=()=>{t("SIGINT")},i=()=>{t("SIGTERM")};n.sigint=o,n.sigterm=i,process.on("SIGINT",o),process.on("SIGTERM",i)}),ht=async(e,r,n)=>{let t=0,o;const i=l=>{e.kill(l),r?.kill(l)},s=()=>{t+=1,t===1?(n.info("received SIGINT — shutting down (press Ctrl-C again to force-kill)"),i("SIGTERM"),o=setTimeout(()=>{i("SIGKILL")},ar),o.unref()):i("SIGKILL")},a=()=>{i("SIGTERM")};process.on("SIGINT",s),process.on("SIGTERM",a);const c=await Promise.race([e.exited.then(l=>({code:l,who:"worker"})),...r===void 0?[]:[r.exited.then(l=>({code:l,who:"sidecar"}))]]);return r!==void 0&&(c.who==="sidecar"?(n.warn("[worker] the Lunora sidecar (wrangler dev) exited — shutting down the framework dev server"),e.kill("SIGTERM")):r.kill("SIGTERM"),await Promise.allSettled([e.exited,r.exited])),o&&clearTimeout(o),process.off("SIGINT",s),process.off("SIGTERM",a),c.code},y="2026.9.3",lr="https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/downloads/",dr=/version (\S+)/u,B=/https:\/\/[\da-z-]+\.trycloudflare\.com/u,ur="1s",fr=5e3,K=async(e,r)=>await Promise.race([e.then(()=>!0),w(r,!1,{ref:!1})]),vr=6e4,gr='Vite answers 403 for hosts it does not know — add `server: { allowedHosts: [".trycloudflare.com"] }` to vite.config if the URL is blocked.',pr=async e=>{const r=`Install or update it: ${lr} (macOS: \`brew install cloudflared\`).`;let n;try{const o=await e({args:["--version"],captureStdoutSilently:!0,command:"cloudflared"});if(o.code!==0)return{message:`\`cloudflared --version\` exited ${String(o.code)}. ${r}`,ok:!1};n=o.stdout??""}catch(o){return Ze(o)&&o.code==="LOCAL_DEPENDENCY_MISSING"?{message:`--tunnel needs \`cloudflared\` ${y} or newer, and it is not on your PATH. ${r}`,ok:!1}:{message:`\`cloudflared --version\` could not run: ${o instanceof Error?o.message:String(o)}. ${r}`,ok:!1}}const t=V.coerce(dr.exec(n)?.[1])?.version;return t===void 0?{ok:!0,version:void 0}:V.gte(t,y)?{ok:!0,version:t}:{message:`--tunnel needs \`cloudflared\` ${y} or newer (protected quick tunnels); found ${t}. ${r}`,ok:!1}},mr=e=>{const r=[],n=[];for(const t of e??[]){const o=t.split(",").map(i=>i.trim()).filter(i=>i.length>0);o.length>0&&(n.push(...o.filter(i=>!i.includes("@"))),r.push(o.join(",")))}return{entries:r,invalid:n}},wr=(e,r)=>["tunnel","--url",e,"--output","json","--grace-period",ur,...r.flatMap(n=>["--allowed-mail",n])],hr=e=>{let r;try{r=JSON.parse(e)}catch{r=void 0}if(typeof r=="object"&&r!==null){const n=r,t=typeof n.message=="string"?n.message:"";return{level:typeof n.level=="string"?n.level:void 0,text:t,url:B.exec(t)?.[0]}}return{level:void 0,text:e,url:B.exec(e)?.[0]}},Sr=e=>{e.warn(" ⚠ PUBLIC TUNNEL: anyone with the tunnel URL can reach this dev server — there is no sign-in in front of it."),e.warn(" Protect it with a one-time-PIN email allow-list: lunora dev --tunnel --allow-mail you@example.com"),e.warn(" (repeat --allow-mail, pass a comma-separated list, or allow a whole domain with '*@example.com')")},kr=async(e,r,n,{intervalMs:t,timeoutMs:o=vr}={})=>{const i=await de(e,s=>s?.mode==="vite"?{origin:s.url,ownerPid:s.pid}:void 0,{intervalMs:t,signal:n,timeoutMs:o});return i===void 0&&!n.aborted&&r.warn(`--tunnel: the Vite dev server did not report its URL within ${String(o/1e3)}s — continuing without a tunnel.`),i},Ir=e=>{const{allowMail:r,cwd:n,logger:t}=e,o=r.length===0,i=new AbortController,{signal:s}=i,a=()=>s.aborted,c=e.closeTimeoutMs??fr;let l;const d=()=>{i.abort()};process.once("SIGINT",d),process.once("SIGTERM",d);const p=(async()=>{const u=await pr(e.spawner??Qe);if(!u.ok){t.error(u.message),t.warn("continuing without a tunnel.");return}u.version===void 0&&t.warn(`could not read the cloudflared version — --tunnel needs ${y} or newer; trying anyway.`);const v=e.origin.kind==="fixed"?{origin:e.origin.origin,ownerPid:process.pid}:await kr(n,t,s);if(v===void 0||s.aborted)return;o&&Sr(t),t.info(`starting a Cloudflare quick tunnel to ${v.origin}${o?"":" (email one-time-PIN protected)"}…`);let S;const U={failedToStart:!1},Le=k=>{if(k.length===0)return;const g=hr(k);if(g.url!==void 0&&S===void 0){S=g.url,t.success(` ➜ Tunnel: ${g.url}${o?" (PUBLIC)":""}`),o||t.info(` Allowed: ${r.join(", ")} — visitors confirm with a one-time PIN; a session lasts up to 4 hours`),e.origin.kind==="vite"&&t.info(` ${gr}`),b(n,{tunnelUrl:g.url},{expectedPid:v.ownerPid});return}g.level==="error"||g.level==="fatal"?t.warn(`[cloudflared] ${g.text}`):t.debug?.(`[cloudflared] ${g.text}`)},P=(e.startChild??fe)({args:wr(v.origin,r),command:"cloudflared",direct:!0},Le,k=>{U.failedToStart=!0,t.error(`could not start cloudflared (${k.message}) — continuing without a tunnel.`)});l=P;const G=()=>{P.kill("SIGTERM")};s.addEventListener("abort",G,{once:!0});const F=await P.exited;s.removeEventListener("abort",G),l=void 0,S!==void 0&&b(n,{tunnelUrl:void 0},{expectedPid:v.ownerPid}),!(a()||U.failedToStart)&&t.warn(S===void 0?`cloudflared exited (${String(F)}) before a tunnel URL was assigned — continuing without a tunnel.`:`cloudflared exited (${String(F)}) — the tunnel is closed; the dev server keeps running.`)})().catch(u=>{t.error(`--tunnel failed (${u instanceof Error?u.message:String(u)}) — continuing without a tunnel.`)});return{close:async()=>{if(process.off("SIGINT",d),process.off("SIGTERM",d),i.abort(),await K(p,c))return;const u=l;u!==void 0&&(t.warn(`cloudflared did not exit within ${String(c/1e3)}s of SIGTERM — force-killing it.`),u.kill("SIGKILL"),!await K(u.exited,c)&&t.error(`could not confirm that cloudflared stopped — ${o?"the PUBLIC tunnel":"the tunnel"} may still be reachable. Stop the \`cloudflared\` process manually.`))}}},St=e=>{const{cwd:r,logger:n,plan:t,tunnel:o}=e;if(o!==void 0)return Ir({allowMail:o.allowMail,cwd:r,logger:n,origin:t.flavor==="wrangler"?{kind:"fixed",origin:t.workerOrigin}:{kind:"vite"},spawner:o.spawner,startChild:o.startChild})},yr=(e,r)=>{const n=["dev"];if(e.apiSpec!==void 0&&n.push("--api-spec",e.apiSpec),Z(e.lazyFunctions)&&n.push("--lazy-functions"),e.port!==void 0&&n.push("--port",String(e.port)),e.workerPort!==void 0&&n.push("--worker-port",String(e.workerPort)),e.inspectorPort!==void 0&&n.push("--inspector-port",String(e.inspectorPort)),e.emitBindings!==void 0&&n.push("--emit-bindings",e.emitBindings),e.codegen===!1&&n.push("--no-codegen"),e.studio===!1&&n.push("--no-studio"),e.worker===!1&&n.push("--no-worker"),e.target!==void 0&&n.push("--target",e.target),e.tunnel===!0){n.push("--tunnel");for(const t of mr(e.allowMail).entries)n.push("--allow-mail",t)}return r&&n.push("--remote"),e.local===!0&&n.push("--local"),n},Er=1e4,Lr=100,Tr=40,I=256*1024,Pr=new Set(["nuxt","sveltekit"]),br=["@lunora/rspack","@lunora/vite"],M=e=>{if(Pr.has(re(e).framework))return"framework-worker";const r=xe(e);return br.some(n=>r.has(n))?"vite":"wrangler"},ve=e=>{const r=A(e),n=Ge(e)?.scripts,t=typeof n=="object"&&n!==null?n.dev:void 0;if(typeof t!="string"||t.trim()===""||t.includes("lunora")){const o=ce(r,"vite",["dev"]);return{args:o.args,command:o.command}}return{args:["run","dev"],command:r}},_r=e=>{Te(_e(e.logPath),{recursive:!0});const r=J(e.logPath,"w",384);let n;const t=ae(e.command,e.args);try{n=ie(t.command,t.args,{cwd:e.cwd,detached:!0,env:e.env,shell:t.shell,stdio:["ignore",r,r],windowsHide:!0})}finally{X(r)}return n.unref(),{exited:new Promise(o=>{n.on("error",()=>{o(1)}),n.on("exit",(i,s)=>{o(i??(s?1:0))})}),pid:n.pid}},$r=e=>{try{const{size:r}=Pe(e);if(r<=I)return Q(e,"utf8");const n=J(e,"r");try{const t=Buffer.alloc(I),o=be(n,t,0,I,r-I),i=t.toString("utf8",0,o);return i.slice(i.indexOf(`
|
|
2
|
-
`)+1)}finally{X(n)}}catch{return}},ge=(e,r)=>{const n=$r(e);if(n===void 0)return[];const t=n.split(`
|
|
3
|
-
`);return t.at(-1)===""&&t.pop(),r>0?t.slice(-r):t},pe=(e,r)=>r?.logFile??N(e,je),me=e=>{e.info(" Stop: lunora dev stop"),e.info(" Status: lunora dev status"),e.info(" Logs: lunora dev logs")},Rr=(e,r)=>{He(r,n=>{e.warn(n)})},Nr=(e,r)=>{e.warn(`Dev server already running at ${r.url} (pid ${String(r.pid)})`),me(e)},Cr=(e,r)=>{e.success(`Dev server running at ${r.url} (pid ${String(r.pid)})`),r.studioUrl!==void 0&&e.info(` Studio: ${r.studioUrl}`),r.tunnelUrl!==void 0&&e.info(` Tunnel: ${r.tunnelUrl}`),me(e)},Dr=3e4,Or=async(e,r,n,t)=>{const o=await de(e,i=>i?.tunnelUrl,{intervalMs:n,timeoutMs:t});o===void 0?r.warn(" Tunnel: no URL yet — `lunora dev status` shows it once cloudflared reports one; `lunora dev logs` says why if it does not."):r.success(` Tunnel: ${o}`)},xr=async e=>{const{child:r,cwd:n,deadline:t,pollIntervalMs:o,probe:i}=e,s=r.exited.then(a=>({exitCode:a}));for(;Date.now()<t;){const a=C(n);if(a!==void 0&&a.pid!==process.pid&&await i(a.url))return{state:a,status:"ready"};const c=await Promise.race([s,w(o)]);if(c!==void 0)return{...c,status:"exited"}}return{status:"timeout"}},Ar=async e=>{const{cwd:r,logger:n}=e,t=pe(r,void 0),o=ir(e.readyTimeoutMs),i=(e.spawnDetached??_r)({args:e.command.args,command:e.command.command,cwd:r,env:{...process.env,...e.env,[Me]:"1",[Ae]:t,...process.env.FORCE_COLOR===void 0?{NO_COLOR:"1"}:{},...e.json?{LUNORA_LOG_JSON:"1"}:{}},logPath:t}),s=await xr({child:i,cwd:r,deadline:Date.now()+o,pollIntervalMs:e.pollIntervalMs??_,probe:e.probe??sr});if(s.status==="ready")return Cr(n,s.state),e.tunnel===!0&&s.state.tunnelUrl===void 0&&await Or(r,n,e.pollIntervalMs??_,e.tunnelUrlTimeoutMs??Dr),{code:0};if(s.status==="exited"){n.error(`dev server exited before becoming ready (exit code ${String(s.exitCode)}). Last output:`);for(const c of ge(t,Tr))n.error(` ${c}`);return E(r,i.pid??process.pid),{code:s.exitCode===0?1:s.exitCode}}i.pid!==void 0&&O(r)?.pid===process.pid&&b(r,{logFile:t,pid:i.pid});const a=i.pid===void 0?"":` (pid ${String(i.pid)})`;return n.warn(`dev server did not confirm ready within ${String(Math.round(o/1e3))}s — it may still be compiling${a}. Check \`lunora dev status\` and \`lunora dev logs\`; \`lunora dev stop\` shuts it down.`),{code:se.UNAVAILABLE}},we=e=>e.codegen!==!1&&!Ve(process.env[te]),he=e=>{const r={...Z(e.lazyFunctions)?{[Ue]:"1"}:{},...e.remote===!0?{LUNORA_REMOTE:"1"}:{},...e.codegen===!1?{[te]:"0"}:{}};return Object.keys(r).length>0?{env:r}:{}},kt=async e=>{const{cwd:r,jsonLogs:n,logger:t,options:o,remote:i}=e,s=e.run??Ar,a=M(r),c=a==="vite"&&D(o.target??ee(r))?"wrangler":a,l=c==="wrangler"?`http://localhost:${String(o.workerPort??8787)}`:"http://localhost:5173",d=De(r,{background:!0,mode:"cli",pid:process.pid,startedAt:new Date().toISOString(),url:l});if(!d.ok)return d.existing!==void 0&&Nr(t,d.existing),{code:0};const f={[Oe]:String(process.pid)};Rr(t,r);try{return c==="vite"&&o.tunnel!==!0?await s({command:ve(r),cwd:r,env:{...he({...o,remote:i}).env,...f},json:n,logger:t}):await s({command:{args:[process.argv[1]??"lunora",...yr(o,i)],command:process.execPath},cwd:r,env:f,json:n,logger:t,tunnel:o.tunnel===!0})}finally{E(r,process.pid)}},Mr=e=>{try{const r=T("ps",["-o","pgid=","-p",String(e)],{encoding:"utf8"}),n=Number.parseInt(r.stdout.trim(),10);return Number.isInteger(n)&&n>0?n:void 0}catch{return}},Ur=(e,r,n=process.platform,t=T)=>{if(n==="win32"){try{t("taskkill",["/pid",String(e.pid),"/T","/F"],{stdio:"ignore"})}catch{}return}if(e.background===!0)try{r(-(Mr(e.pid)??e.pid),"SIGKILL");return}catch{}try{r(e.pid,"SIGKILL")}catch{}},Gr=(e,r)=>(r.json?h({pid:e.pid,stopped:!1}):r.logger.error(`dev server (pid ${String(e.pid)}) survived the force-kill — record kept; retry \`lunora dev stop\` or kill the process manually.`),{code:1}),Fr=async e=>{const{cwd:r,logger:n}=e,t=O(r),o=e.alive??(f=>f===t?.pid&&Fe(t)),i=e.signal??((f,p)=>{process.kill(f,p)}),s=e.pollIntervalMs??_,a=e.stopGraceMs??Er,c=e.platform??process.platform,l=e.spawnSyncImpl??T;if(t===void 0||!o(t.pid))return t!==void 0&&E(r,t.pid),e.json?h({running:!1,stopped:!1}):n.info("No dev server running."),{code:0};try{i(t.pid,"SIGTERM")}catch{}const d=Date.now()+a;for(;o(t.pid)&&Date.now()<d;)await w(s);return o(t.pid)&&(Ur(t,i,c,l),await w(s),o(t.pid))?Gr(t,e):(E(r,t.pid),e.json?h({pid:t.pid,stopped:!0}):n.success(`Stopped dev server (pid ${String(t.pid)}).`),{code:0})},jr=e=>{const{cwd:r,logger:n}=e,t=C(r);if(t===void 0)return e.json?h({running:!1}):n.info("No dev server running."),{code:0};const o=e.now??Date.now,i=t.startedAt===void 0?Number.NaN:Date.parse(t.startedAt),s=Number.isFinite(i)?Math.max(0,Math.round((o()-i)/1e3)):void 0;if(e.json)return h({background:t.background===!0,logFile:t.logFile,mode:t.mode,pid:t.pid,ready:j(t),readyAt:t.readyAt,running:!0,startedAt:t.startedAt,studioUrl:t.studioUrl,tunnelUrl:t.tunnelUrl,uptimeSeconds:s,url:t.url}),{code:0};const a=[`pid ${String(t.pid)}`,...s===void 0?[]:[`uptime ${String(s)}s`],t.background===!0?"background":"foreground",j(t)?"ready":"starting"];return n.success(`Dev server running at ${t.url} (${a.join(", ")})`),t.studioUrl!==void 0&&n.info(` Studio: ${t.studioUrl}`),t.tunnelUrl!==void 0&&n.info(` Tunnel: ${t.tunnelUrl}`),t.logFile!==void 0&&n.info(` Logs: lunora dev logs (${t.logFile})`),{code:0}},Vr=e=>{const{cwd:r,logger:n}=e,t=O(r),o=pe(r,t);if(!q(o))return n.info("No dev server logs found — output is captured when the server runs in background mode (`lunora dev --background`)."),{code:0};const i=ge(o,e.lines??Lr);return i.length>0&&process.stdout.write(`${i.join(`
|
|
4
|
-
`)}
|
|
5
|
-
`),{code:0}},It=e=>{const{cwd:r,json:n,lines:t,logger:o,subcommand:i}=e;if(i==="stop")return Fr({cwd:r,json:n,logger:o});if(i==="status")return jr({cwd:r,json:n,logger:o});if(i==="logs")return Vr({cwd:r,lines:t,logger:o});if(i!==void 0)return o.error(`dev: unknown subcommand "${i}" — expected stop | status | logs (or no subcommand to start the dev server)`),{code:se.USAGE}},yt=(e,r,n)=>D(e)?(r!=="wrangler"&&n.info(`target ${e} runs its own dev server, so lunora dev serves the worker on it — start the frontend's dev server separately`),"wrangler"):r,Et=async e=>{const{logger:r}=e,n=await(e.start??Be)({log:(i,{stream:s,tag:a})=>{ue(i,a,s,r)},port:e.port,projectRoot:e.projectRoot});let t=()=>{};const o=new Promise(i=>{t=i});return{exited:Promise.race([o,n.exited]),kill:()=>{n.stop().then(()=>0,()=>1).then(t).catch(()=>{})}}},Wr=e=>{const{cwd:r,driver:n,options:t,studioPort:o,workerPort:i}=e,{projectConfig:s,toolchain:a}=n;if(s===void 0||a===void 0)throw new Error(`deploy target "${n.id}" runs its own dev server but ships no config projection or toolchain for it`);if(t.remote===!0)throw new Error(`--remote proxies bindings to Cloudflare; ${n.name} has no remote bindings to proxy to`);t.inspectorPort!==void 0&&t.logger.warn(`--inspector-port is a wrangler dev flag; ${n.name} dev has no inspector to pin`);const{command:c,projection:l}=We(n,r,"dev",f=>a.dev({configPath:f,extraArgs:["--port",String(i)]}));l!==void 0&&l.dropped.length>0&&t.logger.info(`${n.name} ignores these wrangler keys, so its dev server runs without them: ${l.dropped.join(", ")}`);const d=le(A(r),c);return{flavor:"wrangler",ipv4LoopbackForced:!1,remote:{bindings:[],cleanup:()=>{},enabled:!1,withheld:[]},runsCodegenWatch:we(t),celldSession:!0,studioEnabled:t.studio!==!1,studioPort:o,workerEnabled:t.worker!==!1,workerOrigin:`http://localhost:${String(i)}`,workerPort:i,wrangler:{args:d.args,command:d.command,cwd:r,tag:c.tool}}},Se=(e=Xe)=>Object.values(e()).some(r=>r?.some(n=>n.internal&&n.address==="::1")),$="wrangler.dev.jsonc",R=6173,m=8787,z=5173,ke=()=>{},Br=(e,r)=>{if(!e.remote&&e.local===!0)return{args:[],plan:{bindings:[],cleanup:ke,enabled:!1,withheld:[]}};const t=(e.materializeDev??Ye)({projectRoot:r,remote:e.remote===!0}),i={bindings:t.remoteBindings.map(s=>`${s.binding} (${s.kind})`),cleanup:t.cleanup,enabled:e.remote===!0,reason:t.reason,withheld:t.withheld};return{args:t.configPath===void 0?[]:["--config",t.configPath],plan:i}},Ie=(e,r)=>{const n=[...new Set($e(r,ze(r)).services.map(s=>s.wranglerPath))],{cleanup:t,configPaths:o,withheld:i}=(e.materializeServiceConfigs??qe)(n,{projectRoot:r});return{args:o.flatMap(s=>["--config",s]),cleanup:t,withheld:i}},Kr=(e,r,n)=>{const t=L(e);return r.length===0||t===void 0?[]:[...n.length>0?[]:["--config",t],...r]},ye=e=>e.local===!0?["--local"]:[],H=e=>x(e).parsed?.dev?.ip,Ee=(e,r,n)=>{if(n!==void 0){const o=N(e,n);if(q(o)&&H(o)!==void 0)return[]}const t=L(e);return t!==void 0&&H(t)!==void 0?[]:r()?[]:["--ip","127.0.0.1"]},zr=new Set(["127.0.0.1","::1","[::1]","localhost"]),Hr=(e,r)=>{let n;try{n=Q(N(e,oe),"utf8")}catch{return[]}const t=[];for(const o of Ke(n)){let i;try{i=new URL(o.value)}catch{continue}zr.has(i.hostname)&&i.port===String(r)&&t.push(o.key)}return t},Y=async(e,r)=>{if(e.workerPort!==void 0)return e.workerPort;const n=L(r);if(n!==void 0){const{parsed:i}=x(n);if(typeof i?.dev?.port=="number")return i.dev.port}const t=await(e.findFreePort??Je)(m);if(t===m)return t;const o=Hr(r,m);if(o.length>0)throw new Error(`port ${String(m)} is in use, but ${oe} pins the worker origin to it (${o.join(", ")}). Serving on ${String(t)} would leave those URLs pointing at nothing. Stop whatever holds ${String(m)}, or run \`lunora dev --worker-port ${String(t)}\` and update those values to match.`);return t},Yr=(e,r)=>{if(e.inspectorPort!==void 0)return e.inspectorPort;const n=L(r);if(n===void 0)return;const{parsed:t}=x(n),o=t?.dev?.inspector_port;return typeof o=="number"?o:void 0},qr=(e,r,n)=>{const t=Ee(r,e.hasIpv6Loopback??Se,$),o=ne(e.target??ee(r));if(o.toolchain===void 0)throw new Error(`deploy target "${o.id}" has no dev server to run the worker sidecar`);const i=Ie(e,r),s=o.toolchain.dev({configPath:$,extraArgs:[...t,...ye(e),"--var","WORKER_ENV:development",...i.args]}),a=le(n,s);return{cleanup:i.cleanup,sidecar:{args:a.args,command:a.command,cwd:r,tag:"worker"},withheld:i.withheld}},Jr=(e,r)=>{e.worker===!1&&e.logger.warn(`--no-worker does not apply to the ${r} flavor: Vite owns the worker, codegen and studio in-process. Run your framework's dev script instead.`),e.inspectorPort!==void 0&&e.logger.warn(r==="framework-worker"?`--inspector-port does not apply to the ${r} flavor: pin \`dev.inspector_port\` in ${$} — that is the config the worker sidecar runs.`:`--inspector-port does not apply to the ${r} flavor: Vite owns the worker. Pin it in vite.config — \`lunora({ cloudflare: { inspectorPort: ${String(e.inspectorPort)} } })\`.`),e.local===!0&&r==="vite"&&e.logger.warn("--local does not apply to the vite flavor: Vite owns the worker. Turn remote bindings off in vite.config — `lunora({ cloudflare: { remoteBindings: false } })`.")},Xr=e=>{const r=e.cwd??process.cwd(),n=A(r),t=e.flavor??M(r);if(t==="vite"||t==="framework-worker"){const p=ve(r),u=t==="framework-worker"?qr(e,r,n):void 0,v=u?.sidecar;return Jr(e,t),{runsCodegenWatch:!1,flavor:t,ipv4LoopbackForced:!1,remote:{bindings:[],cleanup:ke,enabled:e.remote===!0,withheld:u?.withheld??[]},...u?{serviceConfigCleanup:u.cleanup}:{},...v?{sidecar:v}:{},studioEnabled:!1,studioPort:e.port??R,workerEnabled:!0,workerOrigin:`http://localhost:${String(z)}`,workerPort:z,wrangler:{args:p.args,command:p.command,cwd:r,...he(e),tag:"vite"}}}const o=re(r),i=o.framework==="none"?void 0:`this project uses ${o.framework} — the worker runs inside Vite there. run \`${rr(n,"dev")}\` for the full app (frontend + HMR); \`lunora dev\` starts only the worker.`,s=e.workerPort??m,a=Br(e,r),c=Ee(r,e.hasIpv6Loopback??Se),l=e.inspectorPort===void 0?[]:["--inspector-port",String(e.inspectorPort)],d=Ie(e,r),f=ce(n,"wrangler",["dev","--port",String(s),...l,...c,...ye(e),"--var","WORKER_ENV:development",...a.args,...Kr(r,d.args,a.args)]);return{runsCodegenWatch:we(e),flavor:t,frameworkHint:i,ipv4LoopbackForced:c.length>0,remote:{...a.plan,withheld:[...a.plan.withheld,...d.withheld]},serviceConfigCleanup:d.cleanup,studioEnabled:e.studio!==!1,studioPort:e.port??R,workerEnabled:e.worker!==!1,workerOrigin:`http://localhost:${String(s)}`,workerPort:s,wrangler:{args:f.args,command:f.command,cwd:r,tag:"wrangler"}}},Lt=async e=>{const r=e.cwd??process.cwd();if(e.target!==void 0&&D(e.target))return Wr({cwd:r,driver:ne(e.target),options:e,studioPort:e.port??R,workerPort:await Y(e,r)});const n=e.flavor??M(r),t=n==="wrangler"?await Y(e,r):e.workerPort,o=n==="wrangler"?Yr(e,r):e.inspectorPort;return Xr({...e,cwd:r,flavor:n,inspectorPort:o,workerPort:t})};export{_ as P,It as a,Nr as b,Sr as c,sr as d,M as e,yt as f,Lt as g,Rr as h,St as i,gt as j,ht as k,we as l,Et as m,mr as n,pt as o,Xr as p,Yr as q,ir as r,kt as s,mt as t,Y as u,wt as w};
|