@lunora/cli 1.0.0-alpha.471 → 1.0.0-alpha.472

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.
@@ -1,6 +1,8 @@
1
- import{readServiceBindings as re,createCodegenProject as te,refreshCodegenProject as ne,findTsconfig as oe,projectConfigCandidatePaths as ae,PROJECT_CONFIG_FILENAMES as ie,runCodegen as V}from"@lunora/codegen";import{runPostCodegenHook as se,resolveLazyFunctions as k,detectAgentRules as B,updateDevServerState as z,readDevServerState as ce,DEV_DAEMON_ENV as G,detectAiAgent as de,readProjectRemotePreference as le,readLiveDevServerState as X,createDiscoveryCache as ue,DEV_HANDOFF_ENV as T,clearDevServerState as fe,claimDevServerState as ge,DEV_LOG_FILE_ENV as ve,secretSourcesFromBindings as me,inferLunoraBindings as we,resolveSchemaDirectory as he,ensureDevVarsExample as ye,ensureDevVariables as Se,isInteractive as pe,DEV_VARS_FILE as $,DEV_VARS_EXAMPLE_FILE as Ee,fillDevSecrets as be,DEV_BINDINGS_FILE as _e,DEV_STATE_FILE as J,writeCelldDevProjection as ke,claimAgentRulesHint as Pe,AGENT_RULES_HINT as Re}from"@lunora/config";import{wranglerCodegenInputs as Y,resolveRemoteEnabled as De,startLocalHyperdrive as Te,describeWithheld as Ce}from"@lunora/config/cloudflare";import{p as $e}from"../packem_shared/api-spec-lYyq4vL6.mjs";import{w as Ae}from"../packem_shared/binding-manifest-file-CQ1eQYy1.mjs";import{existsSync as Oe,watch as A,readFileSync as Fe,statSync as Ie}from"node:fs";import{join as P,dirname as K}from"node:path";import{STUDIO_WRITE_TEMP_SUFFIX as Le,consumeStudioWrite as O,loadStudioAssets as F,studioAssetsStamp as I,createStudioDocumentCache as je,renderStudioHtml as Ne,resolveAdminToken as Me,requestPathname as L,transportRejectionReason as j,SCHEMA_EDIT_ENDPOINT as We,POLICY_SCAFFOLD_ENDPOINT as He,SEED_ENDPOINT as xe,sendStudioDocument as Ue,serveJsonHandler as Ve,isStandaloneModulePath as Be,readStandaloneAsset as ze,assetContentType as Ge,handleSchemaEditRequest as Xe,handlePolicyScaffoldRequest as Je,handleSeedRequest as Ye,sendStudioAsset as Ke}from"@lunora/config/studio-host";import{ts as N}from"ts-morph";import{a as Qe}from"../packem_shared/codegen-error-AmH54ofi.mjs";import{a as Ze}from"../packem_shared/platform-diagnostics-Cn2g6Jh-.mjs";import{d as qe}from"../packem_shared/command-BpMv2n0o.mjs";import{a as er}from"../packem_shared/deploy-target-resolve-BTCW1Iv4.mjs";import{EXIT_CODE as R}from"../packem_shared/EXIT_CODE-DQVhSE-1.mjs";import{forceJsonLogging as rr}from"../packem_shared/createLogger-4TujevyB.mjs";import{createServer as tr,request as nr}from"node:http";import{connect as or}from"node:net";import{pipeline as ar}from"node:stream";import{c as ir}from"../packem_shared/tui-prompts-B3YwUhGw.mjs";import{setTimeout as sr}from"node:timers/promises";import{r as cr,d as dr,P as lr,a as ur,b as C,c as fr,s as gr,n as Q,e as vr,f as mr,g as wr,h as hr,i as M,w as yr,j as Sr,k as pr,t as Er,l as br,m as _r,o as kr}from"../packem_shared/plan-pog5AvMk.mjs";import{b as Pr}from"./handler.mjs";const Rr=100,Dr=/(?:\.[cm]?[jt]sx?|(?:^|[/\\])tsconfig(?:\..+)?\.json)$/u,Tr=300,W=/[/\\]/u,H=e=>{try{return Fe(e,"utf8")}catch{return""}},Cr=e=>{try{const{mtimeMs:r,size:n}=Ie(e);return`${String(r)}:${String(n)}`}catch{return""}},$r=["pnpm-lock.yaml","package-lock.json","yarn.lock","bun.lock","node_modules/.modules.yaml","node_modules/.package-lock.json","node_modules/.yarn-integrity"],Z=e=>{const r=K(e);return r===e?[e]:[e,...Z(r)]},Ar=e=>{const r={...N.sys,onUnRecoverableConfigFileDiagnostic:()=>{},readDirectory:()=>[]},n=N.getParsedCommandLineOfConfigFile(e,{},r);return n===void 0?"":JSON.stringify(n.options)},Or=(e,r)=>{const n=oe(r),o=[...new Set([...ae(r),...ie.map(s=>P(e,s))])].map(s=>`${s}
2
- ${H(s)}`),i=Z(e).flatMap(s=>$r.map(a=>`${P(s,a)}
3
- ${Cr(P(s,a))}`));return[n===void 0?"":`${n}
4
- ${H(n)}
5
- ${Ar(n)}`,...o,...i].join("\0")},Fr=(e,r)=>{let n,t;return{drop:()=>{n=void 0},get:()=>{const o=Or(e,r);return n===void 0||o!==t?(t=o,n=te(r)):ne(n,r),n}}},Ir=(e,r,n,t)=>{const{apiSpec:o,lazyFunctions:i,logger:l,projectRoot:s,target:a}=e;try{const u=V({apiSpec:o,lazyFunctions:k(i),lunoraDirectory:r,project:t.get(),projectRoot:s,target:a,...Y(s)});l.success(`codegen: wrote ${r}/_generated (${n})`),Ze(u.platformDiagnostics,l)}catch(u){return t.drop(),l.error(Qe(u,n)),!1}return!0},Lr=e=>{const r=e.lunoraDirectory??"lunora",n=P(e.projectRoot,r),t=e.debounceMs??Rr;let o=!1,i=!1,l=!1,s,a=0,u=Promise.resolve();const b=Fr(e.projectRoot,n);let w;const c=new Promise(v=>{w=v}),d=(v,m)=>{o||(s={codegen:m||s?.codegen===!0,reason:v},!i&&(i=!0,u=(async()=>{try{for(;s!==void 0;){const h=s;if(s=void 0,!(h.codegen&&!Ir(e,r,h.reason,b))){l=!0;try{(await se({cwd:e.projectRoot,logger:e.logger,spawner:e.spawner,stdoutToStderr:e.jsonLogs})).ran&&(a=Date.now())}finally{l=!1}}}}catch(h){e.logger.error(`codegen watch: ${h instanceof Error?h.message:String(h)}`)}finally{i=!1,w()}})()))};d("startup",!0);const f=v=>(e.logger.warn(`codegen watch unavailable (${v}) — schema edits will NOT auto-regenerate. Run \`lunora codegen\` manually after each edit.`),{close:()=>(o=!0,s=void 0,u),ready:c,watchAvailable:!1});let g,y;if(!Oe(n))return f(`no such directory: ${n}`);const S=new Set;let p=!1;const _=(v,m)=>{if(l||Date.now()-a<Tr){g&&(clearTimeout(g),g=void 0);let h=!1;for(const E of[...S,v])E!==void 0&&O(E)&&(h=!0);S.clear(),p=!1,h&&d(`change: ${m}`,!1);return}v===void 0?p=!0:S.add(v),g&&clearTimeout(g),g=setTimeout(()=>{const h=[...S].map(ee=>O(ee)),E=p||h.includes(!1);S.clear(),p=!1,d(`change: ${m}`,E)},t)},D=[];try{y=A(n,{recursive:!0},(v,m)=>{if(typeof m!="string"){_(void 0,"?");return}m.split(W).includes("_generated")||m.endsWith(Le)||_(P(n,m),m)});for(const v of re(e.projectRoot).services)if(v.rpcEntrypoint!==void 0){const m=A(K(v.wranglerPath),{recursive:!0},(h,E)=>{typeof E=="string"&&Dr.test(E)&&!E.split(W).includes("node_modules")&&_(void 0,E)});m.on("error",h=>{e.logger.warn(`codegen watch: stopped watching service "${v.name}" (${h.message})`),m.close()}),D.push(m)}}catch(v){y?.close();for(const m of D)m.close();return f(v instanceof Error?v.message:String(v))}const q=y;return{close:()=>{o=!0,s=void 0,g&&clearTimeout(g),q.close();for(const v of D)v.close();return u},ready:c,watchAvailable:!0}},x="/_lunora",jr=3e4,U=(e,r,n,t=jr)=>{const o=nr({headers:{...e.headers,host:n.host},hostname:n.hostname,method:e.method,path:e.url,port:n.port},i=>{o.setTimeout(0),r.writeHead(i.statusCode??502,i.headers),ar(i,r,()=>{})});o.setTimeout(t,()=>{o.destroy(new Error(`no response within ${String(t)}ms`))}),o.on("error",i=>{if(r.headersSent){r.destroy();return}r.statusCode=i.message.startsWith("no response within")?504:502,r.end(`lunora dev: worker unreachable (${i.message})`)}),r.on("close",()=>{r.writableFinished||o.destroy()}),e.pipe(o)},Nr=5e3,Mr=(e,r,n,t)=>{const o=or({host:t.hostname,port:Number(t.port)},()=>{o.setTimeout(0);const i=[`${e.method??"GET"} ${e.url??"/"} HTTP/1.1`];for(const[l,s]of Object.entries(e.headers))if(l!=="host")for(const a of Array.isArray(s)?s:[s])a!==void 0&&i.push(`${l}: ${a}`);i.push(`host: ${t.host}`,"",""),o.write(i.join(`\r
6
- `)),n.length>0&&o.write(n),o.pipe(r),r.pipe(o)});o.setTimeout(Nr,()=>o.destroy()),o.on("error",()=>r.destroy()),r.on("error",()=>o.destroy())},Wr=async e=>{const r=e.host??"127.0.0.1",n=r==="127.0.0.1"||r==="localhost"||r==="::1",t=new URL(e.workerOrigin);let o=F(e.logger,import.meta.url),i=I(import.meta.url);const l=je(e.cwd,()=>Buffer.from(Ne({adminToken:n?Me(e.cwd):void 0,basePath:"/",dataEditable:n,rulesInstalled:B(e.cwd).installed,runAsIdentity:n,schemaEditable:n,scriptSrc:"/studio.js",styleHref:"/styles.css"}))),s=(c,d,f,g,y)=>{Ke(c,d,f,g,y,i)},a=(c,d,f)=>{c.statusCode=d,c.setHeader("Content-Type","text/plain"),c.end(f)},u=(c,d,f,g)=>{if(n){Ve(c,d,f,e.cwd,{apiSpec:e.apiSpec,lazyFunctions:k(e.lazyFunctions)});return}a(d,403,g)},b=(c,d,f)=>{const g=c==="/styles.css",y=Be(c);if(!g&&!y)return!1;const S=I(import.meta.url);if(S!==i&&(o=F(e.logger,import.meta.url),i=S),o===void 0)return a(f,501,"Lunora studio assets not found — install and build @lunora/studio."),!0;if(g)return s(d,f,o.styles,"text/css; charset=utf-8","styles.css"),!0;const p=c.slice(c.lastIndexOf("/")+1),_=ze(p,import.meta.url);return _===void 0?(a(f,404,"Not found"),!0):(s(d,f,_,Ge(p),p),!0)};l();const w=tr((c,d)=>{const f=L(c.url??"/");if(n){const y=j(c,e.logger);if(y!==void 0){a(d,403,y);return}}if(f.startsWith(x)){if(!n){a(d,403,"Lunora studio: the worker admin proxy is only available on a loopback bind.");return}U(c,d,t);return}if(f===We){u(c,d,Xe,"Lunora schema editing is only available on loopback hosts in dev.");return}if(f===He){u(c,d,Je,"Lunora policy scaffolding is only available on loopback hosts in dev.");return}if(f===xe){u(c,d,Ye,"Lunora data seeding is only available on loopback hosts in dev.");return}if(b(f,c,d))return;const g=c.headers["sec-fetch-mode"];if(n&&typeof g=="string"&&g!=="navigate"){U(c,d,t);return}Ue(d,l())});return w.on("upgrade",(c,d,f)=>{if(!n||j(c,e.logger)!==void 0){d.destroy();return}L(c.url??"").startsWith(x)?Mr(c,d,f,t):d.destroy()}),await new Promise((c,d)=>{w.once("error",f=>{f.code==="EADDRINUSE"?d(new Error(`studio port ${String(e.port)} is already in use — pass a different port with --port, or stop the process using it`,{cause:f})):d(f)}),w.listen(e.port,r,()=>{c()})}),{close:()=>new Promise(c=>{w.close(()=>{c()})}),url:`http://${r==="0.0.0.0"||r==="::"?"localhost":r}:${String(e.port)}`}},Hr=async e=>{const{cwd:r,logger:n,origin:t,signal:o}=e,i=e.probe??dr,l=cr(e.readyTimeoutMs),s=Date.now()+l,a=()=>o.aborted;for(;!a()&&Date.now()<s;){let u=!1;try{u=await i(t,o)}catch{}if(a()||Date.now()>=s)break;if(u)return z(r,{readyAt:new Date().toISOString()},{expectedPid:process.pid}),ce(r)?.readyAt!==void 0;try{await sr(lr,void 0,{signal:o})}catch{}}return a()||n.warn(`server did not answer on ${t} within ${String(Math.round(l/1e3))}s — .lunora/dev.json will have no readyAt, so anything polling for readiness will keep waiting. The server itself is unaffected; raise LUNORA_DEV_READY_TIMEOUT_MS if it is just slow to boot.`),!1},xr=(e,r,n,t)=>{e.info(""),e.success("Lunora dev"),e.info(` ➜ Worker: ${r.workerOrigin}`),n!==void 0&&e.info(` ➜ Studio: ${n}`),r.runsCodegenWatch&&e.info(" ➜ Codegen: watching lunora/"),t!==void 0&&e.info(` ➜ Supervisor: ${t} (needs) · ${J} (status)`),r.remote.enabled&&(r.remote.bindings.length>0?e.info(` ➜ Remote: ${r.remote.bindings.join(", ")} → deployed worker`):r.remote.reason!==void 0&&e.warn(` ➜ Remote: requested but inactive (${r.remote.reason}) — running fully local`));for(const o of r.remote.withheld)e.warn(` ➜ ${Ce(o)}`);e.info("")},Ur=(e,r)=>{B(r).installed||!Pe()||(e.info(` ⓘ ${Re}`),e.info(""))},Vr=async(e,r,n)=>{let t;try{t=me(await we({cache:n,projectRoot:r,schemaDir:he(r)}))}catch{}if(t!==void 0)try{const i=(e.ensureExample??ye)(r,t);if(i.length>0){const l=t.map(s=>s.includes(":")?`${s.replace(":"," (")})`:s);e.logger.info(`Updated .dev.vars.example with secrets for: ${l.join(", ")} (${i.join(", ")})`)}}catch{}(await(e.ensureEnv??Se)({confirm:ir(),cwd:r,info:i=>{e.logger.info(i)}})).status==="declined"&&!pe()&&e.logger.info(`hint: ${$} was not scaffolded (non-interactive run). Copy ${Ee} → ${$} and fill in secrets, or run \`lunora dev\` in an interactive terminal to scaffold automatically.`);try{(e.fillSecrets??be)({cwd:r,secretSources:t,info:i=>{e.logger.info(i)}})}catch{}},Br=(e,r,n,t,o)=>{if(e.flavor!=="wrangler")return;t!==void 0&&z(r,{studioUrl:t});let i;try{i=kr(r,n)}catch{}return xr(n,e,t,o),i},zr=(e,r)=>{const n=Number(process.env[T]),t=ge(r,{background:process.env[G]==="1",logFile:process.env[ve],mode:"cli",pid:process.pid,startedAt:new Date().toISOString(),url:e.workerOrigin},Number.isInteger(n)&&n>0?{supersedePid:n}:void 0);return t.ok?void 0:t.existing},Gr=e=>{const{cwd:r,destination:n,logger:t,plan:o}=e,i=n!==void 0,l=n??_e,s=Ae({destination:l,dev:{...o.flavor==="wrangler"?{origin:o.workerOrigin}:{},statusFile:J},logger:i?t:{...t,success:()=>{},warn:()=>{}},projectRoot:r});return s.error!==void 0?i?s:(t.debug?.(`skipped the default binding manifest: ${s.error}`),{}):{written:l}},Xr=async(e,r,n,t)=>{if(r.studioEnabled)try{return await(e.startStudio??Wr)({apiSpec:e.apiSpec,lazyFunctions:k(e.lazyFunctions),cwd:n,logger:{warnOnce:o=>{t.warn(o)}},port:r.studioPort,workerOrigin:r.workerOrigin})}catch(o){t.warn(`studio server failed to start (${o instanceof Error?o.message:String(o)}) — continuing without it`);return}},Jr=e=>{const r=[e.runsCodegenWatch?"codegen watch":void 0,e.studioEnabled?"studio":void 0].filter(t=>t!==void 0);return`--no-worker: not starting wrangler. ${r.length>0?`${r.join(" + ")} running`:"nothing else to run"}; your task runner owns the worker on ${e.workerOrigin}.`},Yr=(e,r,n,t,o)=>{if(!(e.sidecar===void 0||!br(r)))try{V({apiSpec:r.apiSpec,lazyFunctions:k(r.lazyFunctions),lunoraDirectory:"lunora",projectRoot:n,target:o,...Y(n)})}catch(i){t.warn(`codegen (pre-sidecar) failed: ${i instanceof Error?i.message:String(i)} — the framework dev server will retry`)}},Kr=e=>e.flavor==="vite"?"starting vite dev (worker + studio + codegen run inside Vite via @lunora/vite)":`starting ${e.wrangler.tag} dev + studio`,Qr=(e,r)=>{e.ipv4LoopbackForced&&r.info("no IPv6 loopback (::1) on this host — binding the worker to 127.0.0.1 (--ip) so wrangler dev doesn't crash. Pin `dev.ip` in wrangler.jsonc to override.")},Zr=async(e,r,n,t)=>{if(e.celldSession!==!0||e.workerEnabled)return!0;try{for(const o of await(r.writeCelldProjection??ke)({projectRoot:n}))t.warn(o);return!0}catch(o){return t.error(`could not write the celld projection: ${o instanceof Error?o.message:String(o)}`),!1}},qr=async(e,r,n,t,o)=>{try{return e.celldSession===!0?await _r({logger:o,port:e.workerPort,projectRoot:t,start:r.startCelldSession}):n(e.wrangler,o)}catch(i){o.error(`could not start the worker: ${i instanceof Error?i.message:String(i)}`);return}},et=async(e,r,n)=>{const t=await(e.startHyperdrive??Te)({onWarning:o=>{n.warn(o)},projectRoot:r});return t!==void 0&&t.bindings.length>0&&n.info(`Hyperdrive ${t.bindings.join(", ")}: embedded Postgres (PGlite), data in .wrangler/state/lunora-pglite. Set CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_<BINDING> to use your own.`),t},rt=async e=>{const{logger:r}=e,n=ue(),t=e.cwd??process.cwd(),o=e.flavor??vr(t),i=er(t,e.target);if(i.target===void 0)throw new Error(i.error??"unknown deploy target");const{target:l}=i,s=mr(l,o,r);s==="wrangler"&&await Pr(t,r,void 0,l,void 0,n);const a=await wr({...e,flavor:s,target:l}),u={remoteCleanup:a.remote.cleanup,serviceConfigCleanup:a.serviceConfigCleanup};try{const b=Number(process.env[T]),w=X(t);if(w!==void 0&&w.pid!==process.pid&&w.pid!==b)return C(r,w),{code:0,plan:a};const c=zr(a,t);if(c!==void 0)return C(r,c),{code:0,plan:a};(a.flavor==="vite"||a.flavor==="framework-worker")&&(a.wrangler.env={...a.wrangler.env,[T]:String(process.pid)}),a.workerEnabled&&l==="cloudflare"&&(u.hyperdrive=await et(e,t,r)),await Vr(e,t,n),r.info(Kr(a)),hr(r,t),Qr(a,r),a.runsCodegenWatch&&(u.codegen=(e.startCodegen??Lr)({apiSpec:e.apiSpec,lazyFunctions:k(e.lazyFunctions),jsonLogs:e.jsonLogs,logger:r,projectRoot:t,target:l})),u.studio=await Xr(e,a,t,r);const d=Gr({cwd:t,destination:e.emitBindings,logger:r,plan:a});if(d.error!==void 0)return r.error(d.error),{code:R.USAGE,plan:a};await u.codegen?.ready;const f=u.studio?.url;a.frameworkHint!==void 0&&r.warn(a.frameworkHint);const g=()=>{a.flavor==="wrangler"&&(u.readyProbe=new AbortController,Hr({cwd:t,logger:r,origin:a.workerOrigin,probe:e.probeReady,signal:u.readyProbe.signal}))};if(!await Zr(a,e,t,r))return{code:R.FAILURE,plan:a};if(!a.workerEnabled)return g(),r.info(Jr(a)),u.tunnel=M({cwd:t,logger:r,plan:a,tunnel:e.tunnel}),{code:await(e.waitForInterrupt??yr)(r),plan:a};Yr(a,e,t,r,l);const y=e.startWorker??Sr,S=await qr(a,e,y,t,r);if(S===void 0)return{code:R.FAILURE,plan:a};const p=a.sidecar===void 0?void 0:y(a.sidecar,r);return g(),u.containerLogs=Br(a,t,r,f,d.written),u.tunnel=M({cwd:t,logger:r,plan:a,tunnel:e.tunnel}),Ur(r,t),{code:await pr(S,p,r),plan:a}}finally{u.readyProbe?.abort(),fe(t,process.pid),await Er(u)}},tt=e=>({codegen:e.codegen===!1?!1:void 0,studio:e.studio===!1?!1:void 0,worker:e.worker===!1?!1:void 0}),nt=e=>{if(e.local===!0&&e.remote===!0)return"`--local` and `--remote` are mutually exclusive — pass at most one.";const{entries:r,invalid:n}=Q(e.allowMail);if(n.length>0)return`\`--allow-mail\` takes email addresses or '*@domain' — not ${n.map(t=>`"${t}"`).join(", ")}.`;if(r.length>0&&e.tunnel!==!0)return"`--allow-mail` only applies to a tunnel — add `--tunnel`."},ot=e=>e.tunnel===!0?{allowMail:Q(e.allowMail).entries}:void 0,Dt=qe(async({argument:e,cwd:r,logger:n,options:t})=>{const o=t.json===!0,i=ur({cwd:r,json:o,lines:t.lines,logger:n,subcommand:e[0]});if(i!==void 0)return i;const l=process.env[G]==="1",s=l?void 0:de(),a=o||s!==void 0;a&&rr(),s!==void 0&&t.background!==!0&&n.info(`AI agent detected (${s.name} via ${s.variable}) — starting the dev server in background mode with JSON logs. Set LUNORA_AGENT_MODE=0 to opt out.`);const u=nt(t);if(u!==void 0)return n.error(`dev: ${u}`),{code:R.USAGE};const b=ot(t),w=t.local===!0?!1:De({configPreference:le(r),envValue:process.env.LUNORA_REMOTE,flag:t.remote});if(!l&&(t.background===!0||s!==void 0)){const c=X(r);return c!==void 0?(C(n,c),{code:0}):(b?.allowMail.length===0&&fr(n),gr({cwd:r,jsonLogs:a,logger:n,options:t,remote:w}))}return rt({apiSpec:$e(t.apiSpec),cwd:r,emitBindings:t.emitBindings,inspectorPort:t.inspectorPort,lazyFunctions:k(t.lazyFunctions),jsonLogs:a,local:t.local,logger:n,port:t.port,remote:w,target:t.target,tunnel:b,workerPort:t.workerPort,...tt(t)})});export{nt as devFlagConflict,Dt as execute,tt as negatableDevFlags,rt as runDevCommand};
1
+ import{projectConfigCandidatePaths as F,readServiceBindings as ge,createCodegenProject as ve,refreshCodegenProject as me,findTsconfig as he,PROJECT_CONFIG_FILENAMES as we,runCodegen as ee}from"@lunora/codegen";import{runPostCodegenHook as ye,resolveLazyFunctions as P,detectAgentRules as re,updateDevServerState as te,readDevServerState as pe,DEV_DAEMON_ENV as ne,detectAiAgent as Se,readProjectRemotePreference as Ee,readLiveDevServerState as oe,createDiscoveryCache as be,DEV_HANDOFF_ENV as I,clearDevServerState as _e,claimDevServerState as ke,DEV_LOG_FILE_ENV as Pe,secretSourcesFromBindings as De,inferLunoraBindings as Re,resolveSchemaDirectory as Te,ensureDevVarsExample as $e,ensureDevVariables as Ce,isInteractive as Ae,DEV_VARS_FILE as H,DEV_VARS_EXAMPLE_FILE as Oe,fillDevSecrets as Fe,DEV_BINDINGS_FILE as Ie,DEV_STATE_FILE as ae,writeCelldDevProjection as Le,claimAgentRulesHint as je,AGENT_RULES_HINT as Ne}from"@lunora/config";import{wranglerCodegenInputs as ie,resolveRemoteEnabled as Me,startLocalHyperdrive as We,describeWithheld as He}from"@lunora/config/cloudflare";import{p as xe}from"../packem_shared/api-spec-lYyq4vL6.mjs";import{w as Ue}from"../packem_shared/binding-manifest-file-CQ1eQYy1.mjs";import{createHash as Ve}from"node:crypto";import{existsSync as N,watch as L,readFileSync as se,statSync as Be}from"node:fs";import{join as k,dirname as M}from"node:path";import{STUDIO_WRITE_TEMP_SUFFIX as ze,consumeStudioWrite as x,loadStudioAssets as U,studioAssetsStamp as V,createStudioDocumentCache as Ge,renderStudioHtml as Xe,resolveAdminToken as Je,requestPathname as B,transportRejectionReason as z,SCHEMA_EDIT_ENDPOINT as Ye,POLICY_SCAFFOLD_ENDPOINT as Ke,SEED_ENDPOINT as Qe,sendStudioDocument as Ze,serveJsonHandler as qe,isStandaloneModulePath as er,readStandaloneAsset as rr,assetContentType as tr,handleSchemaEditRequest as nr,handlePolicyScaffoldRequest as or,handleSeedRequest as ar,sendStudioAsset as ir}from"@lunora/config/studio-host";import{ts as G}from"ts-morph";import{a as sr}from"../packem_shared/codegen-error-AmH54ofi.mjs";import{a as cr}from"../packem_shared/platform-diagnostics-Cn2g6Jh-.mjs";import{d as dr}from"../packem_shared/command-BpMv2n0o.mjs";import{a as lr}from"../packem_shared/deploy-target-resolve-BTCW1Iv4.mjs";import{EXIT_CODE as T}from"../packem_shared/EXIT_CODE-DQVhSE-1.mjs";import{forceJsonLogging as ur}from"../packem_shared/createLogger-4TujevyB.mjs";import{createServer as fr,request as gr}from"node:http";import{connect as vr}from"node:net";import{pipeline as mr}from"node:stream";import{c as hr}from"../packem_shared/tui-prompts-B3YwUhGw.mjs";import{setTimeout as wr}from"node:timers/promises";import{r as yr,d as pr,P as Sr,a as Er,b as j,c as br,s as _r,n as ce,e as kr,f as Pr,g as Dr,h as Rr,i as X,w as Tr,j as $r,k as Cr,t as Ar,l as Or,m as Fr,o as Ir}from"../packem_shared/plan-pog5AvMk.mjs";import{b as Lr}from"./handler.mjs";const jr=100,Nr=/(?:\.[cm]?[jt]sx?|(?:^|[/\\])tsconfig(?:\..+)?\.json)$/u,O=300,J=/[/\\]/u,Y=e=>{try{return se(e,"utf8")}catch{return""}},Mr=e=>{try{const{mtimeMs:r,size:n}=Be(e);return`${String(r)}:${String(n)}`}catch{return""}},Wr=["pnpm-lock.yaml","package-lock.json","yarn.lock","bun.lock","node_modules/.modules.yaml","node_modules/.package-lock.json","node_modules/.yarn-integrity"],de=e=>{const r=M(e);return r===e?[e]:[e,...de(r)]},Hr=e=>{const r={...G.sys,onUnRecoverableConfigFileDiagnostic:()=>{},readDirectory:()=>[]},n=G.getParsedCommandLineOfConfigFile(e,{},r);return n===void 0?"":JSON.stringify(n.options)},xr=(e,r)=>{const n=he(r),o=[...new Set([...F(r),...we.map(s=>k(e,s))])].map(s=>`${s}
2
+ ${Y(s)}`),a=de(e).flatMap(s=>Wr.map(i=>`${k(s,i)}
3
+ ${Mr(k(s,i))}`));return[n===void 0?"":`${n}
4
+ ${Y(n)}
5
+ ${Hr(n)}`,...o,...a].join("\0")},Ur=(e,r)=>{let n,t;return{drop:()=>{n=void 0},get:()=>{const o=xr(e,r);return n===void 0||o!==t?(t=o,n=ve(r)):me(n,r),n}}},Vr=(e,r,n,t)=>{const{apiSpec:o,lazyFunctions:a,logger:d,projectRoot:s,target:i}=e;try{const f=ee({apiSpec:o,lazyFunctions:P(a),lunoraDirectory:r,project:t.get(),projectRoot:s,target:i,...ie(s)});d.success(`codegen: wrote ${r}/_generated (${n})`),cr(f.platformDiagnostics,d)}catch(f){return t.drop(),d.error(sr(f,n)),!1}return!0},K=e=>{const r=Ve("sha256");for(const n of e){if(r.update(n).update("\0"),N(n))try{r.update(se(n))}catch{r.update("unreadable")}r.update("\0")}return r.digest("hex")},Q=e=>e instanceof Error?e.stack??e.message:String(e),Br=(e,r,n)=>{const t=[];for(const o of new Set([...e].map(a=>M(a))))if(N(o))try{const a=L(o,(d,s)=>{typeof s!="string"?r(void 0):e.has(k(o,s))&&r(s)});a.on("error",d=>{n(`codegen watch: stopped watching ${o} for lunora.config changes
6
+ ${Q(d)}`),a.close()}),t.push(a)}catch(a){n(`codegen watch: could not watch ${o} for lunora.config changes
7
+ ${Q(a)}`)}return t},zr=e=>{const r=e.lunoraDirectory??"lunora",n=k(e.projectRoot,r),t=e.debounceMs??jr;let o=!1,a=!1,d=!1,s,i=0,f;const E=F(n);let m=Promise.resolve();const c=Ur(e.projectRoot,n);let l;const g=new Promise(u=>{l=u}),h=(u,v)=>{o||(s={codegen:v||s?.codegen===!0,reason:u},!a&&(a=!0,m=(async()=>{try{for(;s!==void 0;){const w=s;if(s=void 0,w.codegen&&(f=K(E)),!(w.codegen&&!Vr(e,r,w.reason,c))){d=!0;try{(await ye({cwd:e.projectRoot,logger:e.logger,spawner:e.spawner,stdoutToStderr:e.jsonLogs})).ran&&(i=Date.now())}finally{d=!1}}}}catch(w){e.logger.error(`codegen watch: ${w instanceof Error?w.message:String(w)}`)}finally{a=!1,l()}})()))};h("startup",!0);const p=u=>(e.logger.warn(`codegen watch unavailable (${u}) — schema edits will NOT auto-regenerate. Run \`lunora codegen\` manually after each edit.`),{close:()=>(o=!0,s=void 0,m),ready:g,watchAvailable:!1});let y,b;if(!N(n))return p(`no such directory: ${n}`);const _=new Set;let D=!1;const R=(u,v)=>{if(d||Date.now()-i<O){y&&(clearTimeout(y),y=void 0);let w=!1;for(const S of[..._,u])S!==void 0&&x(S)&&(w=!0);_.clear(),D=!1,w&&h(`change: ${v}`,!1);return}u===void 0?D=!0:_.add(u),y&&clearTimeout(y),y=setTimeout(()=>{const w=[..._].map(fe=>x(fe)),S=D||w.includes(!1);_.clear(),D=!1,h(`change: ${v}`,S)},t)},$=[],C=[],le=new Set(F(n));let A;const W=u=>{if(!o){if(!d&&Date.now()-i>=O){(u===void 0||K(E)!==f)&&R(void 0,u??"?");return}clearTimeout(A),A=setTimeout(()=>{W(u)},O)}};try{b=L(n,{recursive:!0},(u,v)=>{if(typeof v!="string"){R(void 0,"?");return}v.split(J).includes("_generated")||v.endsWith(ze)||R(k(n,v),v)});for(const u of ge(e.projectRoot).services)if(u.rpcEntrypoint!==void 0){const v=L(M(u.wranglerPath),{recursive:!0},(w,S)=>{typeof S=="string"&&Nr.test(S)&&!S.split(J).includes("node_modules")&&R(void 0,S)});v.on("error",w=>{e.logger.warn(`codegen watch: stopped watching service "${u.name}" (${w.message})`),v.close()}),$.push(v)}C.push(...Br(le,u=>{W(u)},u=>{e.logger.warn(u)}))}catch(u){b?.close();for(const v of $)v.close();for(const v of C)v.close();return p(u instanceof Error?u.message:String(u))}const ue=b;return{close:()=>{o=!0,s=void 0,y&&clearTimeout(y),clearTimeout(A),ue.close();for(const u of $)u.close();for(const u of C)u.close();return m},ready:g,watchAvailable:!0}},Z="/_lunora",Gr=3e4,q=(e,r,n,t=Gr)=>{const o=gr({headers:{...e.headers,host:n.host},hostname:n.hostname,method:e.method,path:e.url,port:n.port},a=>{o.setTimeout(0),r.writeHead(a.statusCode??502,a.headers),mr(a,r,()=>{})});o.setTimeout(t,()=>{o.destroy(new Error(`no response within ${String(t)}ms`))}),o.on("error",a=>{if(r.headersSent){r.destroy();return}r.statusCode=a.message.startsWith("no response within")?504:502,r.end(`lunora dev: worker unreachable (${a.message})`)}),r.on("close",()=>{r.writableFinished||o.destroy()}),e.pipe(o)},Xr=5e3,Jr=(e,r,n,t)=>{const o=vr({host:t.hostname,port:Number(t.port)},()=>{o.setTimeout(0);const a=[`${e.method??"GET"} ${e.url??"/"} HTTP/1.1`];for(const[d,s]of Object.entries(e.headers))if(d!=="host")for(const i of Array.isArray(s)?s:[s])i!==void 0&&a.push(`${d}: ${i}`);a.push(`host: ${t.host}`,"",""),o.write(a.join(`\r
8
+ `)),n.length>0&&o.write(n),o.pipe(r),r.pipe(o)});o.setTimeout(Xr,()=>o.destroy()),o.on("error",()=>r.destroy()),r.on("error",()=>o.destroy())},Yr=async e=>{const r=e.host??"127.0.0.1",n=r==="127.0.0.1"||r==="localhost"||r==="::1",t=new URL(e.workerOrigin);let o=U(e.logger,import.meta.url),a=V(import.meta.url);const d=Ge(e.cwd,()=>Buffer.from(Xe({adminToken:n?Je(e.cwd):void 0,basePath:"/",dataEditable:n,rulesInstalled:re(e.cwd).installed,runAsIdentity:n,schemaEditable:n,scriptSrc:"/studio.js",styleHref:"/styles.css"}))),s=(c,l,g,h,p)=>{ir(c,l,g,h,p,a)},i=(c,l,g)=>{c.statusCode=l,c.setHeader("Content-Type","text/plain"),c.end(g)},f=(c,l,g,h)=>{if(n){qe(c,l,g,e.cwd,{apiSpec:e.apiSpec,lazyFunctions:P(e.lazyFunctions)});return}i(l,403,h)},E=(c,l,g)=>{const h=c==="/styles.css",p=er(c);if(!h&&!p)return!1;const y=V(import.meta.url);if(y!==a&&(o=U(e.logger,import.meta.url),a=y),o===void 0)return i(g,501,"Lunora studio assets not found — install and build @lunora/studio."),!0;if(h)return s(l,g,o.styles,"text/css; charset=utf-8","styles.css"),!0;const b=c.slice(c.lastIndexOf("/")+1),_=rr(b,import.meta.url);return _===void 0?(i(g,404,"Not found"),!0):(s(l,g,_,tr(b),b),!0)};d();const m=fr((c,l)=>{const g=B(c.url??"/");if(n){const p=z(c,e.logger);if(p!==void 0){i(l,403,p);return}}if(g.startsWith(Z)){if(!n){i(l,403,"Lunora studio: the worker admin proxy is only available on a loopback bind.");return}q(c,l,t);return}if(g===Ye){f(c,l,nr,"Lunora schema editing is only available on loopback hosts in dev.");return}if(g===Ke){f(c,l,or,"Lunora policy scaffolding is only available on loopback hosts in dev.");return}if(g===Qe){f(c,l,ar,"Lunora data seeding is only available on loopback hosts in dev.");return}if(E(g,c,l))return;const h=c.headers["sec-fetch-mode"];if(n&&typeof h=="string"&&h!=="navigate"){q(c,l,t);return}Ze(l,d())});return m.on("upgrade",(c,l,g)=>{if(!n||z(c,e.logger)!==void 0){l.destroy();return}B(c.url??"").startsWith(Z)?Jr(c,l,g,t):l.destroy()}),await new Promise((c,l)=>{m.once("error",g=>{g.code==="EADDRINUSE"?l(new Error(`studio port ${String(e.port)} is already in use — pass a different port with --port, or stop the process using it`,{cause:g})):l(g)}),m.listen(e.port,r,()=>{c()})}),{close:()=>new Promise(c=>{m.close(()=>{c()})}),url:`http://${r==="0.0.0.0"||r==="::"?"localhost":r}:${String(e.port)}`}},Kr=async e=>{const{cwd:r,logger:n,origin:t,signal:o}=e,a=e.probe??pr,d=yr(e.readyTimeoutMs),s=Date.now()+d,i=()=>o.aborted;for(;!i()&&Date.now()<s;){let f=!1;try{f=await a(t,o)}catch{}if(i()||Date.now()>=s)break;if(f)return te(r,{readyAt:new Date().toISOString()},{expectedPid:process.pid}),pe(r)?.readyAt!==void 0;try{await wr(Sr,void 0,{signal:o})}catch{}}return i()||n.warn(`server did not answer on ${t} within ${String(Math.round(d/1e3))}s — .lunora/dev.json will have no readyAt, so anything polling for readiness will keep waiting. The server itself is unaffected; raise LUNORA_DEV_READY_TIMEOUT_MS if it is just slow to boot.`),!1},Qr=(e,r,n,t)=>{e.info(""),e.success("Lunora dev"),e.info(` ➜ Worker: ${r.workerOrigin}`),n!==void 0&&e.info(` ➜ Studio: ${n}`),r.runsCodegenWatch&&e.info(" ➜ Codegen: watching lunora/"),t!==void 0&&e.info(` ➜ Supervisor: ${t} (needs) · ${ae} (status)`),r.remote.enabled&&(r.remote.bindings.length>0?e.info(` ➜ Remote: ${r.remote.bindings.join(", ")} → deployed worker`):r.remote.reason!==void 0&&e.warn(` ➜ Remote: requested but inactive (${r.remote.reason}) — running fully local`));for(const o of r.remote.withheld)e.warn(` ➜ ${He(o)}`);e.info("")},Zr=(e,r)=>{re(r).installed||!je()||(e.info(` ⓘ ${Ne}`),e.info(""))},qr=async(e,r,n)=>{let t;try{t=De(await Re({cache:n,projectRoot:r,schemaDir:Te(r)}))}catch{}if(t!==void 0)try{const a=(e.ensureExample??$e)(r,t);if(a.length>0){const d=t.map(s=>s.includes(":")?`${s.replace(":"," (")})`:s);e.logger.info(`Updated .dev.vars.example with secrets for: ${d.join(", ")} (${a.join(", ")})`)}}catch{}(await(e.ensureEnv??Ce)({confirm:hr(),cwd:r,info:a=>{e.logger.info(a)}})).status==="declined"&&!Ae()&&e.logger.info(`hint: ${H} was not scaffolded (non-interactive run). Copy ${Oe} → ${H} and fill in secrets, or run \`lunora dev\` in an interactive terminal to scaffold automatically.`);try{(e.fillSecrets??Fe)({cwd:r,secretSources:t,info:a=>{e.logger.info(a)}})}catch{}},et=(e,r,n,t,o)=>{if(e.flavor!=="wrangler")return;t!==void 0&&te(r,{studioUrl:t});let a;try{a=Ir(r,n)}catch{}return Qr(n,e,t,o),a},rt=(e,r)=>{const n=Number(process.env[I]),t=ke(r,{background:process.env[ne]==="1",logFile:process.env[Pe],mode:"cli",pid:process.pid,startedAt:new Date().toISOString(),url:e.workerOrigin},Number.isInteger(n)&&n>0?{supersedePid:n}:void 0);return t.ok?void 0:t.existing},tt=e=>{const{cwd:r,destination:n,logger:t,plan:o}=e,a=n!==void 0,d=n??Ie,s=Ue({destination:d,dev:{...o.flavor==="wrangler"?{origin:o.workerOrigin}:{},statusFile:ae},logger:a?t:{...t,success:()=>{},warn:()=>{}},projectRoot:r});return s.error!==void 0?a?s:(t.debug?.(`skipped the default binding manifest: ${s.error}`),{}):{written:d}},nt=async(e,r,n,t)=>{if(r.studioEnabled)try{return await(e.startStudio??Yr)({apiSpec:e.apiSpec,lazyFunctions:P(e.lazyFunctions),cwd:n,logger:{warnOnce:o=>{t.warn(o)}},port:r.studioPort,workerOrigin:r.workerOrigin})}catch(o){t.warn(`studio server failed to start (${o instanceof Error?o.message:String(o)}) — continuing without it`);return}},ot=e=>{const r=[e.runsCodegenWatch?"codegen watch":void 0,e.studioEnabled?"studio":void 0].filter(t=>t!==void 0);return`--no-worker: not starting wrangler. ${r.length>0?`${r.join(" + ")} running`:"nothing else to run"}; your task runner owns the worker on ${e.workerOrigin}.`},at=(e,r,n,t,o)=>{if(!(e.sidecar===void 0||!Or(r)))try{ee({apiSpec:r.apiSpec,lazyFunctions:P(r.lazyFunctions),lunoraDirectory:"lunora",projectRoot:n,target:o,...ie(n)})}catch(a){t.warn(`codegen (pre-sidecar) failed: ${a instanceof Error?a.message:String(a)} — the framework dev server will retry`)}},it=e=>e.flavor==="vite"?"starting vite dev (worker + studio + codegen run inside Vite via @lunora/vite)":`starting ${e.wrangler.tag} dev + studio`,st=(e,r)=>{e.ipv4LoopbackForced&&r.info("no IPv6 loopback (::1) on this host — binding the worker to 127.0.0.1 (--ip) so wrangler dev doesn't crash. Pin `dev.ip` in wrangler.jsonc to override.")},ct=async(e,r,n,t)=>{if(e.celldSession!==!0||e.workerEnabled)return!0;try{for(const o of await(r.writeCelldProjection??Le)({projectRoot:n}))t.warn(o);return!0}catch(o){return t.error(`could not write the celld projection: ${o instanceof Error?o.message:String(o)}`),!1}},dt=async(e,r,n,t,o)=>{try{return e.celldSession===!0?await Fr({logger:o,port:e.workerPort,projectRoot:t,start:r.startCelldSession}):n(e.wrangler,o)}catch(a){o.error(`could not start the worker: ${a instanceof Error?a.message:String(a)}`);return}},lt=async(e,r,n)=>{const t=await(e.startHyperdrive??We)({onWarning:o=>{n.warn(o)},projectRoot:r});return t!==void 0&&t.bindings.length>0&&n.info(`Hyperdrive ${t.bindings.join(", ")}: embedded Postgres (PGlite), data in .wrangler/state/lunora-pglite. Set CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_<BINDING> to use your own.`),t},ut=async e=>{const{logger:r}=e,n=be(),t=e.cwd??process.cwd(),o=e.flavor??kr(t),a=lr(t,e.target);if(a.target===void 0)throw new Error(a.error??"unknown deploy target");const{target:d}=a,s=Pr(d,o,r);s==="wrangler"&&await Lr(t,r,void 0,d,void 0,n);const i=await Dr({...e,flavor:s,target:d}),f={remoteCleanup:i.remote.cleanup,serviceConfigCleanup:i.serviceConfigCleanup};try{const E=Number(process.env[I]),m=oe(t);if(m!==void 0&&m.pid!==process.pid&&m.pid!==E)return j(r,m),{code:0,plan:i};const c=rt(i,t);if(c!==void 0)return j(r,c),{code:0,plan:i};(i.flavor==="vite"||i.flavor==="framework-worker")&&(i.wrangler.env={...i.wrangler.env,[I]:String(process.pid)}),i.workerEnabled&&d==="cloudflare"&&(f.hyperdrive=await lt(e,t,r)),await qr(e,t,n),r.info(it(i)),Rr(r,t),st(i,r),i.runsCodegenWatch&&(f.codegen=(e.startCodegen??zr)({apiSpec:e.apiSpec,lazyFunctions:P(e.lazyFunctions),jsonLogs:e.jsonLogs,logger:r,projectRoot:t,target:d})),f.studio=await nt(e,i,t,r);const l=tt({cwd:t,destination:e.emitBindings,logger:r,plan:i});if(l.error!==void 0)return r.error(l.error),{code:T.USAGE,plan:i};await f.codegen?.ready;const g=f.studio?.url;i.frameworkHint!==void 0&&r.warn(i.frameworkHint);const h=()=>{i.flavor==="wrangler"&&(f.readyProbe=new AbortController,Kr({cwd:t,logger:r,origin:i.workerOrigin,probe:e.probeReady,signal:f.readyProbe.signal}))};if(!await ct(i,e,t,r))return{code:T.FAILURE,plan:i};if(!i.workerEnabled)return h(),r.info(ot(i)),f.tunnel=X({cwd:t,logger:r,plan:i,tunnel:e.tunnel}),{code:await(e.waitForInterrupt??Tr)(r),plan:i};at(i,e,t,r,d);const p=e.startWorker??$r,y=await dt(i,e,p,t,r);if(y===void 0)return{code:T.FAILURE,plan:i};const b=i.sidecar===void 0?void 0:p(i.sidecar,r);return h(),f.containerLogs=et(i,t,r,g,l.written),f.tunnel=X({cwd:t,logger:r,plan:i,tunnel:e.tunnel}),Zr(r,t),{code:await Cr(y,b,r),plan:i}}finally{f.readyProbe?.abort(),_e(t,process.pid),await Ar(f)}},ft=e=>({codegen:e.codegen===!1?!1:void 0,studio:e.studio===!1?!1:void 0,worker:e.worker===!1?!1:void 0}),gt=e=>{if(e.local===!0&&e.remote===!0)return"`--local` and `--remote` are mutually exclusive — pass at most one.";const{entries:r,invalid:n}=ce(e.allowMail);if(n.length>0)return`\`--allow-mail\` takes email addresses or '*@domain' — not ${n.map(t=>`"${t}"`).join(", ")}.`;if(r.length>0&&e.tunnel!==!0)return"`--allow-mail` only applies to a tunnel — add `--tunnel`."},vt=e=>e.tunnel===!0?{allowMail:ce(e.allowMail).entries}:void 0,Mt=dr(async({argument:e,cwd:r,logger:n,options:t})=>{const o=t.json===!0,a=Er({cwd:r,json:o,lines:t.lines,logger:n,subcommand:e[0]});if(a!==void 0)return a;const d=process.env[ne]==="1",s=d?void 0:Se(),i=o||s!==void 0;i&&ur(),s!==void 0&&t.background!==!0&&n.info(`AI agent detected (${s.name} via ${s.variable}) — starting the dev server in background mode with JSON logs. Set LUNORA_AGENT_MODE=0 to opt out.`);const f=gt(t);if(f!==void 0)return n.error(`dev: ${f}`),{code:T.USAGE};const E=vt(t),m=t.local===!0?!1:Me({configPreference:Ee(r),envValue:process.env.LUNORA_REMOTE,flag:t.remote});if(!d&&(t.background===!0||s!==void 0)){const c=oe(r);return c!==void 0?(j(n,c),{code:0}):(E?.allowMail.length===0&&br(n),_r({cwd:r,jsonLogs:i,logger:n,options:t,remote:m}))}return ut({apiSpec:xe(t.apiSpec),cwd:r,emitBindings:t.emitBindings,inspectorPort:t.inspectorPort,lazyFunctions:P(t.lazyFunctions),jsonLogs:i,local:t.local,logger:n,port:t.port,remote:m,target:t.target,tunnel:E,workerPort:t.workerPort,...ft(t)})});export{gt as devFlagConflict,Mt as execute,ft as negatableDevFlags,ut as runDevCommand};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/cli",
3
- "version": "1.0.0-alpha.471",
3
+ "version": "1.0.0-alpha.472",
4
4
  "description": "The Lunora CLI: init, dev, deploy, codegen, migrate, seed, doctor, insights, logs, registry, and the rest of the project commands",
5
5
  "keywords": [
6
6
  "agent-skills",
@@ -58,14 +58,14 @@
58
58
  "@bomb.sh/tab": "0.0.22",
59
59
  "@lunora/advisor": "1.0.0-alpha.284",
60
60
  "@lunora/bindings": "1.0.0-alpha.150",
61
- "@lunora/codegen": "1.0.0-alpha.390",
62
- "@lunora/config": "1.0.0-alpha.447",
61
+ "@lunora/codegen": "1.0.0-alpha.391",
62
+ "@lunora/config": "1.0.0-alpha.448",
63
63
  "@lunora/container": "1.0.0-alpha.108",
64
64
  "@lunora/d1": "1.0.0-alpha.230",
65
65
  "@lunora/errors": ">=1.0.0-alpha.51 <2.0.0-0",
66
66
  "@lunora/mcp": "1.0.0-alpha.288",
67
67
  "@lunora/runtime": "1.0.0-alpha.272",
68
- "@lunora/seed": "1.0.0-alpha.278",
68
+ "@lunora/seed": "1.0.0-alpha.279",
69
69
  "@lunora/wire": "1.0.0-alpha.6",
70
70
  "@visulima/cerebro": "4.0.1",
71
71
  "@visulima/error": "6.1.0",