@lunora/cli 1.0.0-alpha.349 → 1.0.0-alpha.350
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.mjs +1 -1
- package/dist/packem_chunks/handler17.mjs +1 -1
- package/dist/packem_chunks/handler2.mjs +1 -1
- package/dist/packem_chunks/handler21.mjs +1 -1
- package/dist/packem_chunks/handler25.mjs +1 -1
- package/dist/packem_chunks/handler3.mjs +1 -1
- package/dist/packem_chunks/handler4.mjs +1 -1
- package/dist/packem_chunks/handler6.mjs +1 -1
- package/dist/packem_chunks/runDeployCommand.mjs +1 -1
- package/dist/packem_chunks/runDevCommand.mjs +1 -1
- package/dist/packem_chunks/runInitCommand.mjs +1 -1
- package/dist/packem_shared/createRecordingSpawner-Ch7zuQQE.mjs +1 -0
- package/dist/packem_shared/{plan-TuKFsXOj.mjs → plan-Cod9Cgll.mjs} +1 -1
- package/dist/packem_shared/{planDevCommand-DmFurevU.mjs → planDevCommand-1uuaH06D.mjs} +1 -1
- package/dist/packem_shared/{wrangler-secrets-Bqi6kLuq.mjs → wrangler-secrets-3chIVv3H.mjs} +1 -1
- package/package.json +15 -15
- package/dist/packem_shared/createRecordingSpawner-CYhdPBD5.mjs +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{C as o,V as a,r as n}from"./packem_shared/cli-CG_JgNKu.mjs";import{runCodegenCommand as m}from"./packem_chunks/runCodegenCommand.mjs";import{runDeployCommand as p}from"./packem_chunks/runDeployCommand.mjs";import{runDevCommand as f}from"./packem_chunks/runDevCommand.mjs";import{p as i}from"./packem_shared/plan-
|
|
1
|
+
import{C as o,V as a,r as n}from"./packem_shared/cli-CG_JgNKu.mjs";import{runCodegenCommand as m}from"./packem_chunks/runCodegenCommand.mjs";import{runDeployCommand as p}from"./packem_chunks/runDeployCommand.mjs";import{runDevCommand as f}from"./packem_chunks/runDevCommand.mjs";import{p as i}from"./packem_shared/plan-Cod9Cgll.mjs";import{runInitCommand as l}from"./packem_chunks/runInitCommand.mjs";import{runMigrateGenerateCommand as I}from"./packem_shared/runMigrateGenerateCommand-Ii_WMZEA.mjs";import{runResetCommand as g}from"./packem_chunks/runResetCommand.mjs";import{runRpcCommand as T}from"./packem_chunks/runRpcCommand.mjs";import{EXIT_CODE as S,exitCodeForCode as A,exitCodeForError as c,exitCodeForStatus as M}from"./packem_shared/EXIT_CODE-D_XCixv8.mjs";import{insertSchemaExtension as v}from"./packem_shared/insertSchemaExtension-DuiV6cba.mjs";import{createLogger as b,pail as O}from"./packem_shared/createLogger-Cl18I8AX.mjs";import{diffSnapshots as y,renderAddColumn as L,renderCreateIndex as w,renderCreateTable as B,renderDropIndex as P,renderDropTable as U,renderMigrationFile as V,validatorKindToSqlType as W}from"./packem_shared/diffSnapshots-WWwx-KvZ.mjs";import{default as N}from"./packem_shared/schemaIrToSnapshot-BjK-0IRo.mjs";import{createRecordingSpawner as j,defaultSpawner as q}from"./packem_shared/createRecordingSpawner-Ch7zuQQE.mjs";import{default as K}from"./packem_shared/parseManifest-CwPTKdtS.mjs";import{D as Y,r as Z}from"./packem_shared/import-BRM1hs7j.mjs";import{REQUIRED_COMPATIBILITY_DATE as z,REQUIRED_FLAG as J,validateWranglerProject as $,validateWranglerConfig as rr}from"@lunora/config/cloudflare";import{b as or}from"./packem_shared/catalog-CahzmDLV.mjs";import{r as nr,a as tr,b as mr}from"./packem_shared/commands-Cg06JNO2.mjs";import{runExportCommand as pr}from"./packem_shared/runExportCommand-slAq5BCF.mjs";export{o as COMMANDS,Y as DEFAULT_IMPORT_BATCH_SIZE,S as EXIT_CODE,z as REQUIRED_COMPATIBILITY_DATE,J as REQUIRED_FLAG,a as VERSION,or as buildRegistryIndex,b as createLogger,j as createRecordingSpawner,q as defaultSpawner,y as diffSnapshots,A as exitCodeForCode,c as exitCodeForError,M as exitCodeForStatus,v as insertSchemaExtension,O as pail,K as parseManifest,i as planDevCommand,L as renderAddColumn,w as renderCreateIndex,B as renderCreateTable,P as renderDropIndex,U as renderDropTable,V as renderMigrationFile,nr as runAddCommand,tr as runBuildIndexCommand,n as runCli,m as runCodegenCommand,p as runDeployCommand,f as runDevCommand,pr as runExportCommand,Z as runImportCommand,l as runInitCommand,I as runMigrateGenerateCommand,mr as runRegistryViewCommand,g as runResetCommand,T as runRpcCommand,N as schemaIrToSnapshot,$ as validateWrangler,rr as validateWranglerConfig,W as validatorKindToSqlType};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync as m}from"node:fs";import{join as p}from"node:path";import{runCodegen as u}from"@lunora/codegen";import{a as v,e as g,r as y}from"../packem_shared/platform-diagnostics-Cn2g6Jh-.mjs";import{p as w,r as S}from"../packem_shared/deploy-target-DCWwiuAe.mjs";import{r as k}from"../packem_shared/codegen-error-AmH54ofi.mjs";import{d as j}from"../packem_shared/command-CAXl2A1S.mjs";import{EXIT_CODE as E}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import{r as A,p as D}from"../packem_shared/health-probe-Bw9JFfIy.mjs";import{defaultSpawner as R}from"../packem_shared/createRecordingSpawner-
|
|
1
|
+
import{existsSync as m}from"node:fs";import{join as p}from"node:path";import{runCodegen as u}from"@lunora/codegen";import{a as v,e as g,r as y}from"../packem_shared/platform-diagnostics-Cn2g6Jh-.mjs";import{p as w,r as S}from"../packem_shared/deploy-target-DCWwiuAe.mjs";import{r as k}from"../packem_shared/codegen-error-AmH54ofi.mjs";import{d as j}from"../packem_shared/command-CAXl2A1S.mjs";import{EXIT_CODE as E}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import{r as A,p as D}from"../packem_shared/health-probe-Bw9JFfIy.mjs";import{defaultSpawner as R}from"../packem_shared/createRecordingSpawner-Ch7zuQQE.mjs";import{validateWranglerProject as $}from"@lunora/config/cloudflare";import{execArgsFor as b,detectPackageManager as U}from"@lunora/config";const x=async(r,a,t)=>{if(!m(p(r,"tsconfig.json")))return{warning:"no tsconfig.json found — skipping TypeScript type-check"};const o=b(U(r),"tsc",["--noEmit","-p","tsconfig.json"]),e=await a({args:o.args,command:o.command,cwd:r,stdoutToStderr:t==="json"});return e.code===0?{}:{error:`type errors: tsc --noEmit exited ${String(e.code)}`}},P=async(r,a)=>{if(r.healthUrl===void 0||r.healthUrl==="")return;const t=await D({baseUrl:r.healthUrl,fetchImpl:r.healthFetch});if(t.error===void 0){a.success(`verify: health probe ok (${t.url})`);return}return t.error},T=(r,a)=>{const{errorAdvisories:t,names:o,shouldBlock:e}=g(r,y(a));if(e)return`${t.length.toString()} ERROR-level ${t.length===1?"advisory":"advisories"} (${o.join(", ")}). Pass --no-strict-advisories to downgrade this to a warning and continue.`},C=(r,a,t,o)=>{if(a.length===0&&t.length===0)return r.success("verify: project is valid"),{code:0,errors:[],warnings:[],wranglerPath:o};if(t.length>0){r.warn("verify: warnings:");for(const e of t)r.warn(` - ${e}`)}if(a.length>0){r.error("verify: errors:");for(const e of a){r.error(` - ${e}`);const n=k(e);n!==void 0&&r.error(n)}return{code:1,error:a[0],errors:a,warnings:t,wranglerPath:o}}return r.success("verify: project is valid (with warnings)"),{code:0,errors:[],warnings:t,wranglerPath:o}},H=async r=>{const a=r.cwd??process.cwd(),{logger:t}=r,o=$({environment:r.env,projectRoot:a}),e=[...o.report.errors],n=[...o.report.warnings];try{const s=S(a,r.target);if(s.target===void 0){const c=s.error??"unknown deploy target";return t.error(c),{code:E.USAGE,error:c,errors:[c],warnings:[],wranglerPath:void 0}}const i=u({apiSpec:r.apiSpec,dryRun:!0,projectRoot:a,target:s.target}),f=v(i.platformDiagnostics,t);e.push(...f.errors),n.push(...f.warnings);const l=T(i.advisories,r);l!==void 0&&e.push(l);const h=A({allowDrift:r.allowSchemaDrift===!0,codegen:i,command:"verify",logger:t,readOnly:!0});h.blocked&&e.push(h.reason)}catch(s){const i=s instanceof Error?s.message:String(s);e.push(`codegen failed: ${i}`)}if(r.typecheck!==!1){const s=await x(a,r.spawner??R,r.format??"pretty");s.error!==void 0&&e.push(s.error),s.warning!==void 0&&n.push(s.warning)}const d=await P(r,t);return d!==void 0&&e.push(d),C(t,e,n,o.wranglerPath)},J=j(async({cwd:r,format:a,logger:t,options:o})=>{const e=await H({allowSchemaDrift:o.allowSchemaDrift===!0,apiSpec:w(o.apiSpec),cwd:r,env:o.env,format:a,healthUrl:o.healthUrl,logger:t,strictAdvisories:o.strictAdvisories,target:o.target,typecheck:o.typecheck===!1?!1:void 0});return{code:e.code,data:{errors:e.errors,warnings:e.warnings,wranglerPath:e.wranglerPath},error:e.error}});export{J as execute,H as runVerifyCommand};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{mkdtempSync as p,rmSync as u,existsSync as m,readdirSync as $,statSync as g}from"node:fs";import{tmpdir as S}from"node:os";import{join as y,relative as w}from"node:path";import{d as z}from"../packem_shared/command-CAXl2A1S.mjs";import{EXIT_CODE as B}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import{defaultSpawner as F}from"../packem_shared/createRecordingSpawner-
|
|
1
|
+
import{mkdtempSync as p,rmSync as u,existsSync as m,readdirSync as $,statSync as g}from"node:fs";import{tmpdir as S}from"node:os";import{join as y,relative as w}from"node:path";import{d as z}from"../packem_shared/command-CAXl2A1S.mjs";import{EXIT_CODE as B}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import{defaultSpawner as F}from"../packem_shared/createRecordingSpawner-Ch7zuQQE.mjs";import{execArgsFor as h,detectPackageManager as x}from"@lunora/config";const v=e=>{const t=[],n=o=>{for(const s of $(o)){const r=y(o,s),i=g(r);i.isDirectory()?n(r):i.isFile()&&t.push({path:w(e,r),sizeBytes:i.size})}};return n(e),t},l=e=>e<1024?`${String(e)} B`:e<1024*1024?`${(e/1024).toFixed(1)} KiB`:`${(e/(1024*1024)).toFixed(2)} MiB`,M=e=>{const t=v(e),n=t.toSorted((r,i)=>i.sizeBytes-r.sizeBytes),o=t.reduce((r,i)=>r+i.sizeBytes,0);return{generatedFiles:t.filter(r=>r.path.includes("_generated")),outdir:e,topModules:n.slice(0,10),totalBytes:o,totalFiles:t.length}},O=(e,t)=>{if(t.info(`outdir: ${e.outdir}`),t.info(`total: ${String(e.totalFiles)} files, ${l(e.totalBytes)}`),e.topModules.length>0){t.info(""),t.info("top modules by size:");for(const n of e.topModules)t.info(` ${l(n.sizeBytes).padStart(10," ")} ${n.path}`)}if(e.generatedFiles.length>0){t.info(""),t.info(`_generated/ files: ${String(e.generatedFiles.length)}`);for(const n of e.generatedFiles)t.info(` ${l(n.sizeBytes).padStart(10," ")} ${n.path}`)}},j=async e=>{const t=e.cwd??process.cwd(),n=e.format==="json",{logger:o}=e;let s,r,i=!1;if(e.inspectOnly)s=e.inspectOnly;else{s=p(y(S(),"lunora-analyze-")),i=!0;const a=h(x(t),"wrangler",["deploy","--dry-run","--outdir",s]);r={args:a.args,command:a.command,cwd:t,stdoutToStderr:n},o.info(`analyze: building via ${r.command} ${r.args.join(" ")}`);const d=await(e.spawner??F)(r);if(d.code!==0){const f=`analyze: wrangler dry-run failed (exit ${String(d.code)})`;return o.error(f),u(s,{force:!0,recursive:!0}),{code:d.code,descriptor:r,error:f,report:void 0}}}try{if(!m(s)){const c=`analyze: outdir not found at ${s}`;return o.error(c),{code:B.NOT_FOUND,descriptor:r,error:c,report:void 0}}const a=M(s);return n||O(a,o),{code:0,descriptor:r,report:a}}finally{if(i&&m(s))try{u(s,{force:!0,recursive:!0})}catch{}}},N=z(async({cwd:e,format:t,logger:n})=>{const o=await j({cwd:e,format:t,logger:n});return{code:o.code,data:o.report,error:o.error}});export{N as execute,j as runAnalyzeCommand};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{join as u,resolve as m}from"node:path";import{p as f}from"../packem_shared/deploy-target-DCWwiuAe.mjs";import{d as p}from"../packem_shared/command-CAXl2A1S.mjs";import{defaultSpawner as w}from"../packem_shared/createRecordingSpawner-
|
|
1
|
+
import{join as u,resolve as m}from"node:path";import{p as f}from"../packem_shared/deploy-target-DCWwiuAe.mjs";import{d as p}from"../packem_shared/command-CAXl2A1S.mjs";import{defaultSpawner as w}from"../packem_shared/createRecordingSpawner-Ch7zuQQE.mjs";import{runDeployCommand as y}from"./runDeployCommand.mjs";import{readdirSync as g,readFileSync as S}from"node:fs";import{gzipSync as b}from"node:zlib";const d=64*1024*1024,h=e=>!e.endsWith(".map")&&e!=="bundle-meta.json"&&e!=="README.md",v=e=>{let n;try{n=g(e,{recursive:!0,withFileTypes:!0})}catch{return}let o=0,r=0,t=0;for(const i of n){if(!i.isFile()||!h(i.name))continue;const a=S(u(i.parentPath,i.name));o+=1,t+=a.byteLength,r+=b(a).byteLength}return o===0?void 0:{files:o,gzipBytes:r,rawBytes:t}},l=".lunora/build",B=async e=>w({...e,stdoutToStderr:!0}),c=e=>`${(e/1024).toFixed(1)} KiB`,D=async e=>{const n=e.outDir??l,o=e.format==="json",{logger:r}=e,t=await y({allowSchemaDrift:e.allowSchemaDrift,apiSpec:e.apiSpec,commandName:"build",cwd:e.cwd,dryRun:!0,emitBindings:e.emitBindings,format:void 0,interactive:o?!1:void 0,logger:r,outDir:n,spawner:e.spawner??(o?B:void 0),strictAdvisories:e.strictAdvisories,target:e.target});if(t.code!==0)return t;r.success(`build complete — bundle written to ${n}`);const i=v(m(e.cwd??process.cwd(),n));if(i===void 0)r.warn(`could not weigh the bundle — nothing uploadable was found in ${n}`);else{const a=(i.rawBytes/d*100).toFixed(1),s=`bundle: ${c(i.rawBytes)} raw across ${String(i.files)} file(s) — ${a}% of Cloudflare's 64 MiB uncompressed Worker size limit (${c(i.gzipBytes)} gzipped, for reference; there is no compressed limit)`;i.rawBytes>d?r.warn(`${s} — Cloudflare will reject this upload`):r.info(s)}return{...t,bundle:i}},R=p(async({cwd:e,format:n,logger:o,options:r})=>{const t=await D({allowSchemaDrift:r.allowSchemaDrift===!0,apiSpec:f(r.apiSpec),cwd:e,emitBindings:r.emitBindings,format:n,logger:o,outDir:r.outDir,strictAdvisories:r.strictAdvisories,target:r.target});return{code:t.code,data:{bundle:t.bundle,deployment:t.deployment,outDir:r.outDir??l,validation:t.validation},error:t.error}});export{R as execute,D as runBuildCommand};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{readLinkedProject as v,resolveDeployDriver as h,toolchainExecArgs as b,detectPackageManager as y}from"@lunora/config";import{d as w}from"../packem_shared/command-CAXl2A1S.mjs";import{EXIT_CODE as d}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import{defaultSpawner as L}from"../packem_shared/createRecordingSpawner-
|
|
1
|
+
import{readLinkedProject as v,resolveDeployDriver as h,toolchainExecArgs as b,detectPackageManager as y}from"@lunora/config";import{d as w}from"../packem_shared/command-CAXl2A1S.mjs";import{EXIT_CODE as d}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import{defaultSpawner as L}from"../packem_shared/createRecordingSpawner-Ch7zuQQE.mjs";import{createR2Sql as S}from"@lunora/bindings/r2sql";import{createPipelineLogReader as _}from"@lunora/runtime";const E=["trace","debug","log","info","warn","error","fatal"],T=new Set(E),f=/^\d+$/,u=(e,t)=>{if(e===void 0)return;const a=e.trim();if(f.test(a))return Number(a);const n=Date.parse(a);if(Number.isNaN(n))throw new TypeError(`logs: invalid ${t} "${e}" — pass epoch-millis or an ISO 8601 date`);return n},C=e=>Buffer.from(JSON.stringify(e),"utf8").toString("base64url"),I=e=>{const t=e.trim();if(f.test(t))return{ts:Number(t)};let a;try{a=JSON.parse(Buffer.from(t,"base64url").toString("utf8"))}catch{throw new TypeError(`logs: invalid --cursor "${e}" — expected the token printed by the previous page (or a bare epoch-millis ts)`)}if(typeof a!="object"||a===null||typeof a.ts!="number"||!Number.isFinite(a.ts))throw new TypeError(`logs: invalid --cursor "${e}" — expected the token printed by the previous page (or a bare epoch-millis ts)`);const{ts:n}=a,r=a.seen,s=Array.isArray(r)?r.filter(i=>typeof i=="string"):void 0;return s!==void 0&&s.length>0?{seen:s,ts:n}:{ts:n}},m=(e,t)=>{if(e!==void 0){if(!T.has(e))throw new TypeError(`logs: invalid ${t} "${e}" — expected one of trace, debug, log, info, warn, error, fatal`);return e}},p=e=>{const t={},a=u(e.since,"--since");a!==void 0&&(t.sinceTs=a);const n=u(e.until,"--until");n!==void 0&&(t.untilTs=n);const r=m(e.level,"--level");r!==void 0&&(t.level=r);const s=m(e.minLevel,"--min-level");if(s!==void 0&&(t.minLevel=s),e.functionPrefix!==void 0&&(t.functionPathPrefix=e.functionPrefix),e.traceId!==void 0&&(t.traceId=e.traceId),e.shardKey!==void 0&&(t.shardKey=e.shardKey),e.userId!==void 0&&(t.userId=e.userId),e.limit!==void 0){const i=Number(e.limit);if(!Number.isFinite(i))throw new TypeError(`logs: invalid --limit "${e.limit}" — expected a number`);t.limit=i}return e.cursor!==void 0&&(t.cursor=I(e.cursor)),t},R=e=>{const t=new Date(e.ts).toISOString(),a=e.level.toUpperCase().padEnd(5);return`${t} ${a} ${e.functionPath} ${e.message}`},$=async e=>{const t=e.environment??process.env,a=t.R2_SQL_ACCOUNT_ID,n=t.R2_SQL_TOKEN,r=t.R2_SQL_BUCKET,s=[];if((a===void 0||a.length===0)&&s.push("R2_SQL_ACCOUNT_ID"),(n===void 0||n.length===0)&&s.push("R2_SQL_TOKEN"),(r===void 0||r.length===0)&&s.push("R2_SQL_BUCKET"),(e.table===void 0||e.table.length===0)&&s.push("--table"),s.length>0)return e.logger.error(`logs --durable: R2 SQL not configured (missing ${s.join(", ")}). The Pipeline must write to an R2 Data Catalog (Iceberg) table, and you must supply R2_SQL_ACCOUNT_ID / R2_SQL_TOKEN / R2_SQL_BUCKET plus --table — see the observability docs.`),{code:d.USAGE,error:"not configured"};let i;try{i=p(e)}catch(c){return e.logger.error(c instanceof Error?c.message:String(c)),{code:d.USAGE,error:"invalid option"}}const o=S({accountId:a,apiToken:n,bucket:r,fetch:e.fetch}),l=await _(o,{namespace:e.namespace,table:e.table}).query(i);for(const c of l.rows)process.stdout.write(`${e.ndjson===!0?JSON.stringify(c):R(c)}
|
|
2
2
|
`);return l.rows.length===0?e.logger.info("logs --durable: no matching log records"):l.nextCursor!==void 0&&e.logger.info(`logs --durable: more rows available — pass --cursor ${C(l.nextCursor)} for the next page`),{code:0,rows:l.rows}},N=async e=>{const t=e.cwd??process.cwd(),a=e.env??v(t)?.env,n=h(e.target),r=n.toolchain?.tail;if(r===void 0){const c=`logs: deploy target "${n.id}" has no log tail`;return e.logger.error(c),{code:d.USAGE,descriptor:void 0,error:c}}const s=r({environment:a,format:e.format,search:e.search,status:e.status,temporary:e.temporary,worker:e.worker}),i=b(y(t),s),o={args:i.args,command:i.command,cwd:t};return e.logger.info(`tailing logs via ${o.command} ${o.args.join(" ")}`),{code:(await(e.spawner??L)(o)).code,delegated:!0,descriptor:o}},U=w(async({argument:e,cwd:t,format:a,logger:n,options:r})=>{if(r.durable===!0){const s=await $({cursor:r.cursor,functionPrefix:r.functionPrefix,level:r.level,limit:r.limit,logger:n,minLevel:r.minLevel,namespace:r.namespace,ndjson:r.ndjson===!0,shardKey:r.shardKey,since:r.since,table:r.table,traceId:r.traceId,until:r.until,userId:r.userId});return{...s,...s.rows===void 0?{}:{delegated:!0}}}return N({cwd:t,env:r.env,format:a,logger:n,search:r.search,status:r.status,target:r.target,temporary:r.temporary===!0,worker:e[0]})});export{U as execute,N as runLogsCommand};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{d as h}from"../packem_shared/command-CAXl2A1S.mjs";import{i as p}from"../packem_shared/docker-DpVxvYpL.mjs";import{EXIT_CODE as m}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import{defaultSpawner as S}from"../packem_shared/createRecordingSpawner-
|
|
1
|
+
import{d as h}from"../packem_shared/command-CAXl2A1S.mjs";import{i as p}from"../packem_shared/docker-DpVxvYpL.mjs";import{EXIT_CODE as m}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import{defaultSpawner as S}from"../packem_shared/createRecordingSpawner-Ch7zuQQE.mjs";import{execArgsFor as w,detectPackageManager as v}from"@lunora/config";const u=new Set(["build","delete","images","info","list","push"]),b=new Set(["build","push"]),f=new Set(["images list","info","list"]),E=async e=>{const[r,...t]=e.argument;if(r===void 0||!u.has(r)){const n=`lunora containers requires a subcommand: ${[...u].toSorted((i,d)=>i.localeCompare(d)).join(" | ")}. Example: lunora containers build ./containers/app --tag app:v1 --push`;return e.logger.error(n),{code:m.USAGE,error:n}}const o=e.format==="json",s=r==="images"?`images ${t[0]??""}`.trim():r;if(o&&!f.has(s)){const n=`containers ${s}: --format json is only available for the read subcommands (${[...f].toSorted((i,d)=>i.localeCompare(d)).join(" | ")}) — wrangler has no JSON rendering for the rest.`;return e.logger.error(n),{code:m.USAGE,error:n}}if(b.has(r)&&!(e.dockerAvailable??p)()){const n=`containers ${r} needs a running Docker-compatible engine (it builds/pushes images locally). Start Docker or Colima and retry. Note: container images must target linux/amd64.`;return e.logger.error(n),{code:m.MISSING_DEPENDENCY,error:n}}const a=["containers",r,...t];o&&a.push("--json"),e.tag!==void 0&&a.push("--tag",e.tag),e.push===!0&&a.push("--push"),e.env!==void 0&&a.push("--env",e.env);const l=e.cwd??process.cwd(),g=w(v(l),"wrangler",a),c={args:g.args,command:g.command,cwd:l};return e.logger.info(`running ${c.command} ${c.args.join(" ")}`),{code:(await(e.spawner??S)(c)).code,delegated:o,descriptor:c}},k=h(async({argument:e,cwd:r,format:t,logger:o,options:s})=>{const a=await E({argument:e,cwd:r,env:s.env,format:t,logger:o,push:s.push===!0,tag:s.tag});return{code:a.code,delegated:a.delegated,error:a.error}});export{k as execute,E as runContainersCommand};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{d as i}from"../packem_shared/command-CAXl2A1S.mjs";import{EXIT_CODE as c}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import{defaultSpawner as l}from"../packem_shared/createRecordingSpawner-
|
|
1
|
+
import{d as i}from"../packem_shared/command-CAXl2A1S.mjs";import{EXIT_CODE as c}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import{defaultSpawner as l}from"../packem_shared/createRecordingSpawner-Ch7zuQQE.mjs";import{execArgsFor as u,detectPackageManager as g}from"@lunora/config";const a=(e,r)=>(r!==void 0&&e.push("--env",r),e),f=e=>{const r=a(["deployments","list"],e.env);return e.format==="json"&&r.push("--json"),r},v=e=>{switch(e.subcommand){case"inspect":return e.versionId===void 0?{error:"deployments inspect requires a version id. Usage: lunora deployments inspect <version-id>"}:{args:a(["versions","view",e.versionId],e.env)};case"list":return{args:f(e)};case"promote":{if(e.versionId===void 0)return{error:"deployments promote requires a version id. Usage: lunora deployments promote <version-id> --yes"};if(!e.yes)return{error:"deployments promote shifts 100% of live traffic. Re-run with --yes to confirm."};const r=a(["versions","deploy",`${e.versionId}@100%`,"--yes"],e.env);return e.message!==void 0&&r.push("--message",e.message),{args:r}}case"rollback":{if(!e.yes)return{error:"deployments rollback changes the live version. Re-run with --yes to confirm."};const r=a(["rollback"],e.env);return e.versionId!==void 0&&r.push(e.versionId),r.push("--yes"),e.message!==void 0&&r.push("--message",e.message),{args:r}}default:return{error:`deployments: unknown subcommand "${e.subcommand}"`}}},y=async e=>{if(e.format==="json"&&e.subcommand!=="list"){const m=`deployments ${e.subcommand}: --format json is only available for \`deployments list\` — wrangler has no JSON rendering for the others.`;return e.logger.error(m),{code:c.USAGE,descriptor:void 0,error:m}}const{args:r,error:t}=v(e);if(t!==void 0||r===void 0)return e.logger.error(t??"deployments: nothing to run"),{code:c.USAGE,descriptor:void 0,error:t};const{logger:d}=e,n=e.cwd??process.cwd(),o=u(g(n),"wrangler",r),s={args:o.args,command:o.command,cwd:n};return d.info(`${s.command} ${s.args.join(" ")}`),{code:(await(e.spawner??l)(s)).code,delegated:e.format==="json",descriptor:s}},p=e=>e==="list"||e==="inspect"||e==="rollback"||e==="promote",A=i(({argument:e,cwd:r,format:t,logger:d,options:n})=>{const o=e[0];if(!p(o)){const s=`deployments: unknown subcommand "${o??""}" — expected list | inspect | rollback | promote`;return d.error(s),{code:c.USAGE,error:s}}return y({cwd:r,env:n.env,format:t,logger:d,message:n.message,subcommand:o,versionId:e[1],yes:n.yes===!0})});export{A as execute,y as runDeploymentsCommand};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{existsSync as E,readFileSync as P}from"node:fs";import{join as D}from"node:path";import{DEV_VARS_FILE as m,DEV_VARS_KEY_PATTERN as b,writeDevVariablesFileAtomically as w,removeDevVariableLine as K,upsertDevVariableLine as _,isPlaceholderValue as S,detectPackageManager as j,resolveDeployDriver as z,resolveProjectTarget as M,toolchainExecArgs as T,generateSecretValue as C,DEV_VARS_EXAMPLE_FILE as g,parseDevVariableEntries as G,packageNamesFromBindings as O,inferLunoraBindings as Y,resolveSchemaDirectory as F,requiredSecrets as q,isMintableSecretKey as U}from"@lunora/config";import{d as Z}from"../packem_shared/command-CAXl2A1S.mjs";import{EXIT_CODE as d}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import{defaultSpawner as B}from"../packem_shared/createRecordingSpawner-
|
|
1
|
+
import{existsSync as E,readFileSync as P}from"node:fs";import{join as D}from"node:path";import{DEV_VARS_FILE as m,DEV_VARS_KEY_PATTERN as b,writeDevVariablesFileAtomically as w,removeDevVariableLine as K,upsertDevVariableLine as _,isPlaceholderValue as S,detectPackageManager as j,resolveDeployDriver as z,resolveProjectTarget as M,toolchainExecArgs as T,generateSecretValue as C,DEV_VARS_EXAMPLE_FILE as g,parseDevVariableEntries as G,packageNamesFromBindings as O,inferLunoraBindings as Y,resolveSchemaDirectory as F,requiredSecrets as q,isMintableSecretKey as U}from"@lunora/config";import{d as Z}from"../packem_shared/command-CAXl2A1S.mjs";import{EXIT_CODE as d}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import{defaultSpawner as B}from"../packem_shared/createRecordingSpawner-Ch7zuQQE.mjs";import{l as I}from"../packem_shared/wrangler-secrets-3chIVv3H.mjs";const X=/[\r\n]/u,H=/["\\]/u,L=e=>new Map(G(e).map(o=>[o.key,o])),h=e=>E(e)?P(e,"utf8"):"",N=e=>e.length<=4?"****":`${e.slice(0,4)}${"*".repeat(Math.min(8,e.length-4))}`,p=e=>L(h(e)),$=e=>e.env??(e.prod===!0?"production":void 0),W=e=>{const o=p(e.devVariablesPath),t={file:m,keys:[...o.keys()],subcommand:"list"};if(o.size===0)return e.logger.info(`${m}: (empty)`),{code:0,data:t,descriptors:[]};for(const r of o.values())e.logger.info(`${r.key}=${N(r.value)}`);return{code:0,data:t,descriptors:[]}},J=e=>{const{devVariablesPath:o,logger:t,options:r}=e;if(!r.key)return t.error("env get requires a key. Usage: lunora env get <KEY>"),{code:d.USAGE,descriptors:[]};const s=p(o).get(r.key);return s?(r.format!=="json"&&process.stdout.write(`${s.value}
|
|
2
2
|
`),{code:0,data:{key:r.key,subcommand:"get",value:s.value},descriptors:[]}):(t.error(`env: ${r.key} is not set in ${m}`),{code:d.NOT_FOUND,descriptors:[]})},Q=e=>{const{devVariablesPath:o,logger:t,options:r}=e;if(!r.key)return t.error("env set requires a key. Usage: lunora env set <KEY> <VALUE>"),{code:d.USAGE,descriptors:[]};if(!b.test(r.key))return t.error(`env: invalid key "${r.key}" — must match [A-Za-z_][A-Za-z0-9_]*`),{code:d.USAGE,descriptors:[]};if(r.value===void 0)return t.error("env set requires a value. Usage: lunora env set <KEY> <VALUE>"),{code:d.USAGE,descriptors:[]};if(X.test(r.value))return t.error(`env: value for "${r.key}" contains a newline, which .dev.vars cannot represent`),{code:d.USAGE,descriptors:[]};if(H.test(r.value))return t.error(`env: value for "${r.key}" contains a double-quote or backslash, which .dev.vars cannot round-trip`),{code:d.USAGE,descriptors:[]};const s=h(o);return w(o,_(s,r.key,r.value)),t.success(`env: set ${r.key} (${N(r.value)}) in ${m}`),{code:0,data:{key:r.key,subcommand:"set"},descriptors:[]}},x=e=>{const{devVariablesPath:o,logger:t,options:r}=e;if(!r.key)return t.error("env unset requires a key. Usage: lunora env unset <KEY>"),{code:d.USAGE,descriptors:[]};if(!b.test(r.key))return t.error(`env: invalid key "${r.key}" — must match [A-Za-z_][A-Za-z0-9_]*`),{code:d.USAGE,descriptors:[]};const s=h(o);return L(s).has(r.key)?(w(o,K(s,r.key)),t.success(`env: unset ${r.key} in ${m}`),{code:0,data:{key:r.key,removed:!0,subcommand:"unset"},descriptors:[]}):(t.warn(`env: ${r.key} was not set in ${m}`),{code:0,data:{key:r.key,removed:!1,subcommand:"unset"},descriptors:[]})},ee=async e=>{const{devVariablesPath:o,logger:t,options:r}=e;if(!r.yes)return t.error("env push uploads secrets to Cloudflare. Re-run with --yes to confirm."),{code:d.USAGE,descriptors:[]};const s=p(o);if(s.size===0)return t.warn(`${m}: nothing to push (empty)`),{code:0,data:{pushed:[],subcommand:"push",target:$(r)},descriptors:[]};const n=[...s.values()].filter(a=>S(a.value)).map(a=>a.key);if(n.length>0)return t.error(`env push: refusing to upload placeholder value(s) for ${n.join(", ")} — run \`lunora env doctor\` to review, and \`lunora env generate --set\` (or \`lunora env set <KEY> <VALUE>\`) to fill them, then re-run.`),{code:d.USAGE,descriptors:[]};const c=r.spawner??B,u=r.cwd??process.cwd(),l=j(u),i=[],v=$(r),f=z(M(u)),y=f.toolchain?.secretPut;if(y===void 0)return t.error(`deploy target "${f.id}" has no secret store; cannot push secrets`),{code:d.USAGE,descriptors:[]};for(const a of s.values()){const R=y({environment:v,key:a.key,temporary:r.temporary}),A=T(l,R),V={args:A.args,command:A.command,cwd:u,input:a.value};i.push(V),t.info(`pushing ${a.key} -> wrangler secret${v===void 0?"":` (${v})`}`);const k=await c(V);if(k.code!==0)return t.error(`env push: failed at ${a.key} (exit ${String(k.code)})`),{code:k.code,descriptors:i}}return t.success(`env: pushed ${String(s.size)} secret(s)`),{code:0,data:{pushed:[...s.keys()],subcommand:"push",target:v},descriptors:i}},re=e=>(e.options.secretLister??I)({cwd:e.cwd,env:$(e.options),temporary:e.options.temporary}),te=async e=>{const{devVariablesPath:o,logger:t}=e,r=await re(e);if(!r.ok)return t.error(`env diff: ${r.error??"failed to list remote secrets"}`),{code:1,descriptors:[]};const s=new Set(p(o).keys()),n=new Set(r.names),c=[...s].filter(i=>!n.has(i)).toSorted((i,v)=>i.localeCompare(v)),u=r.names.filter(i=>!s.has(i)),l=[...s].filter(i=>n.has(i)).toSorted((i,v)=>i.localeCompare(v));for(const i of c)t.info(`local only (run \`lunora env push\`): ${i}`);for(const i of u)t.info(`remote only (in Cloudflare, not ${m}): ${i}`);return t.info(`in both: ${String(l.length)} secret(s)`),c.length===0&&u.length===0&&t.success("env diff: local and remote secret names match"),{code:0,data:{both:l,localOnly:c,remoteOnly:u,subcommand:"diff"},descriptors:[]}},se=e=>{const{cwd:o,devVariablesPath:t,logger:r}=e,s=D(o,g);if(!E(s))return r.info(`env doctor: no ${g} to check against — nothing to validate.`),{code:0,data:{extra:[],missing:[],ok:!0,placeholders:[],subcommand:"doctor"},descriptors:[]};const n=G(P(s,"utf8")).map(a=>a.key),c=p(t);if(!E(t))return r.error(`env doctor: ${m} is missing. Run \`lunora dev\` to scaffold it, or \`lunora env set <KEY> <VALUE>\`.`),r.info(`expected (from ${g}): ${n.join(", ")}`),{code:d.NOT_FOUND,descriptors:[]};const u=n.filter(a=>!c.has(a)),l=[...c.values()].filter(a=>S(a.value)).map(a=>a.key),i=new Set(n),v=[...c.keys()].filter(a=>!i.has(a));for(const a of u)r.error(`missing: ${a} is in ${g} but not ${m}`);for(const a of l)r.error(`unset: ${a} still has a placeholder value`);for(const a of v)r.info(`extra: ${a} is set locally but not listed in ${g}`);const f=u.length===0&&l.length===0,y={extra:v,missing:u,ok:f,placeholders:l,subcommand:"doctor"};return f?(r.success(`env doctor: ${m} looks good (${String(c.size)} var(s)).`),{code:0,data:y,descriptors:[]}):{code:1,data:y,descriptors:[]}},oe=async e=>{let o=[];try{o=O(await Y({projectRoot:e.cwd,schemaDir:F(e.cwd)}))}catch{}const t=q(o).map(s=>s.key).filter(s=>U(s)),r=[...p(e.devVariablesPath).keys()].filter(s=>U(s));return[...new Set([...t,...r])]},ne=(e,o,t)=>{const r=p(e),s=n=>{const c=r.get(n);return c!==void 0&&c.value!==""&&!S(c.value)};return{live:o.filter(n=>s(n.key)).map(n=>n.key),writable:t?o:o.filter(n=>!s(n.key))}},ae=(e,o)=>{const{devVariablesPath:t,logger:r,options:s}=e,{live:n,writable:c}=ne(t,o,s.yes===!0);if(c.length===0)return r.error(`env generate --set: ${n.join(", ")} already hold(s) a live secret and rotating it is irreversible (outstanding signed URLs and bearers stop verifying). Re-run with --yes to rotate anyway.`),{code:d.USAGE,descriptors:[]};n.length>0&&r.warn(`env generate --set: left ${n.join(", ")} untouched (already set) — re-run with --yes to rotate them too`);let u=h(t);for(const l of c)u=_(u,l.key,l.value);return w(t,u),r.success(`env: generated ${String(c.length)} secret(s) into ${m}: ${c.map(l=>l.key).join(", ")}`),{code:0,data:{subcommand:"generate",written:c.map(l=>l.key)},descriptors:[]}},ce=async e=>{const{logger:o,options:t}=e;let r;if(t.key===void 0){if(r=await oe(e),r.length===0)return o.info("env generate: no locally-generatable secrets for this project. Name one explicitly: lunora env generate <KEY>"),{code:0,data:{secrets:[],subcommand:"generate"},descriptors:[]}}else{if(!b.test(t.key))return o.error(`env: invalid key "${t.key}" — must match [A-Za-z_][A-Za-z0-9_]*`),{code:d.USAGE,descriptors:[]};r=[t.key]}const s=r.map(n=>({key:n,value:C()}));if(t.set===!0)return ae(e,s);if(t.format!=="json")for(const n of s)process.stdout.write(`${n.key}=${n.value}
|
|
3
3
|
`);return{code:0,data:{secrets:s,subcommand:"generate"},descriptors:[]}},ie=async e=>{const{options:o}=e;switch(o.subcommand){case"diff":return te(e);case"doctor":return se(e);case"generate":return ce(e);case"get":return J(e);case"list":return W(e);case"push":return ee(e);case"set":return Q(e);case"unset":return x(e);default:return e.logger.error(`env: unknown subcommand "${o.subcommand}"`),{code:d.USAGE,descriptors:[]}}},de=async e=>{const o=e.cwd??process.cwd(),t={cwd:o,devVariablesPath:D(o,m),logger:e.logger,options:e};return ie(t)},ue=new Set(["diff","doctor","generate","get","list","push","set","unset"]),le=e=>typeof e=="string"&&ue.has(e),ke=Z(({argument:e,cwd:o,format:t,logger:r,options:s})=>{const n=e[0];if(!le(n)){const c=`env: unknown subcommand "${n??""}" — expected list | get | set | unset | push | diff | doctor | generate`;return r.error(c),{code:d.USAGE,error:c}}return de({cwd:o,env:s.env,format:t,key:e[1],logger:r,prod:s.prod===!0,set:s.set===!0,subcommand:n,temporary:s.temporary===!0,value:e[2],yes:s.yes===!0})});export{ke as execute,de as runEnvCommand};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{join as z,dirname as J}from"node:path";import{discoverMigrations as X,readServiceBindings as Q,runCodegen as Z}from"@lunora/codegen";import{readLinkedProject as I,execArgsFor as L,detectPackageManager as b,discoverContainerInfo as U,COMPOSED_WORKER_ENTRY as P,writeLinkedProject as ee,discoverSchemaInfo as re,DEV_VARS_FILE as w,parseDevVariableEntries as O,isMintableSecretKey as x,packageNamesFromBindings as te,inferLunoraBindings as F,resolveSchemaDirectory as W,requiredSecrets as ne,generateSecretValue as ae,toolchainExecArgs as R,upsertDevVariableLine as oe,writeDevVariablesFileAtomically as ie,resolveDeployDriver as A,planToolchainInvocation as M,runPostCodegenHook as se}from"@lunora/config";import{findWranglerFile as B,readWranglerJsonc as ce,mergeWranglerEnvironment as le,warnCloudflareCliConfigOnce as de,validateWranglerProject as ue,reconcileWranglerBindings as ge,reconcileWranglerCompatibilityDate as me,reconcileWranglerCrons as fe,describePreservedCrons as he}from"@lunora/config/cloudflare";import{Spinner as ve}from"@visulima/spinner";import{r as pe,a as ye,e as we}from"../packem_shared/platform-diagnostics-Cn2g6Jh-.mjs";import{p as ke,a as be}from"../packem_shared/deploy-target-DCWwiuAe.mjs";import{w as $e}from"../packem_shared/binding-manifest-file-CQ1eQYy1.mjs";import{d as Se}from"../packem_shared/command-CAXl2A1S.mjs";import{r as C}from"../packem_shared/wrangler-name-Dsk5K1f-.mjs";import{EXIT_CODE as h}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import{containerBuildTag as De}from"@lunora/container";import{a as Ee,i as Re}from"../packem_shared/docker-DpVxvYpL.mjs";import{defaultSpawner as $}from"../packem_shared/createRecordingSpawner-CYhdPBD5.mjs";import{r as V}from"../packem_shared/resolve-target-C_ZloTvd.mjs";import{p as Ae,H as Ce,a as je,r as Pe}from"../packem_shared/health-probe-Bw9JFfIy.mjs";import{existsSync as p,readFileSync as k,writeFileSync as H}from"node:fs";import{join as y}from"@visulima/path";import{Project as xe}from"ts-morph";import{m as Te,e as _e,i as Ne}from"../packem_shared/secret-key-DsMeUoEg.mjs";import{runMigrateDataCommand as Ie}from"../packem_shared/runMigrateGenerateCommand-Ii_WMZEA.mjs";import{c as Le}from"../packem_shared/tui-prompts-B3YwUhGw.mjs";import{l as Ue}from"../packem_shared/wrangler-secrets-Bqi6kLuq.mjs";const Oe=e=>{const{cwd:r,env:a,logger:t,mintedSecretsFile:n}=e;try{const o=I(r),i=o?.workerName??C(r),s=e.url??o?.workerUrl;t.success("deploy complete"),t.info(` worker: ${i??"(see wrangler output above)"}`),a!==void 0&&t.info(` env: ${a}`),s===void 0?t.info(" url: run `lunora link --url <https://your-worker>` to record it"):t.info(` url: ${s}`),n!==void 0&&t.info(` secrets: generated value(s) recorded in ${n}`),e.logsAvailable&&t.info(" logs: lunora logs")}catch{}},Fe=async e=>{if(e.targets.length===0)return{builtTags:[],code:0};if(!(e.railpackAvailable??Ee)()){const t="deploy blocked: a container uses `image: { build }` (Railpack), but Railpack isn't ready. Install the `railpack` CLI and start a BuildKit instance, e.g. `docker run --rm --privileged -d --name buildkit moby/buildkit` then `export BUILDKIT_HOST=docker-container://buildkit`. Alternatively switch the container's `image` to a Dockerfile path or a pre-built registry reference.";return e.logger.error(t),{builtTags:[],code:1,error:t}}const r=e.spawner??$,a=[];for(const t of e.targets){const n=De(t.exportName),o={args:["build",t.buildDir,"--name",n],command:"railpack",cwd:e.cwd},i=L(b(e.cwd),"wrangler",["containers","push",n]),s={args:i.args,command:i.command,cwd:e.cwd};e.logger.info(`railpack: building "${t.exportName}" → ${n} from ${t.buildDir}`);const c=await r(o);if(c.code!==0){const l=`railpack build failed for container "${t.exportName}" (${t.buildDir})`;return e.logger.error(l),{builtTags:a,code:c.code,error:l}}e.logger.info(`railpack: pushing ${n} to the Cloudflare Registry`);const d=await r(s);if(d.code!==0){const l=`wrangler containers push failed for "${t.exportName}" (${n})`;return e.logger.error(l),{builtTags:a,code:d.code,error:l}}a.push(n)}return{builtTags:a,code:0}},We=e=>{const a=[B(e),z(e,"package.json")].filter(t=>t!==void 0&&p(t)).map(t=>[t,k(t,"utf8")]);return()=>{for(const[t,n]of a)k(t,"utf8")!==n&&H(t,n,"utf8")}},G="<replace-with-d1-create-id>",T=e=>Array.isArray(e)?e.filter(r=>r!=null):void 0,j=(e,r)=>{const a=B(e);if(!a)return;const{parsed:t}=ce(a);if(t===void 0)return;const{error:n,merged:o}=le(t,r),i=n===void 0?o:t,{containers:s,d1_databases:c,vars:d}=i;return{containers:T(s),d1_databases:T(c),vars:typeof d=="object"&&d!==null&&!Array.isArray(d)?d:void 0}},Me=/^127(?:\.\d{1,3}){3}$/,Be=e=>{try{const{hostname:r}=new URL(e);return r==="localhost"||Me.test(r)||r==="::1"||r==="[::1]"}catch{return!1}},Ve=e=>e.startsWith("./")||e.startsWith("../")||e.startsWith("/")||e.includes("Dockerfile"),He=(e,r,a,t="deploy",n)=>{const o=(j(e,n)?.containers??[]).filter(s=>typeof s?.image=="string"&&Ve(s.image));if(o.length===0||a())return;const i=`${t} blocked: wrangler.jsonc declares ${String(o.length)} container(s) built from a local Dockerfile, but no Docker-compatible engine is available. Start Docker (or Colima), or point the container's \`image\` at a pre-built registry reference. Note: container images must target linux/amd64.`;return r.error(i),i},K=e=>p(y(e,P))?P:void 0,Ge=(e,r,a="deploy")=>{for(const t of U(e,"lunora").containers){const n=t.schedulingPolicy===void 0?t.image:void 0,i=[...n?.kind==="dockerfile"?[{field:"image",path:n.dockerfilePath}]:[],...Object.entries(t.schedulingPolicy==="durable_object"?t.images??{}:{}).flatMap(([s,c])=>c.kind==="dockerfile"?[{field:`images["${s}"]`,path:c.dockerfilePath}]:[])].find(s=>!p(y(e,s.path)));if(i!==void 0){const s=`${a} blocked: container "${t.exportName}" references a Dockerfile at "${i.path}" that does not exist. Create it or fix the \`${i.field}\` path in lunora/containers.ts.`;return r.error(s),s}if(n?.kind==="build"&&!p(y(e,n.buildDir))){const s=`${a} blocked: container "${t.exportName}" references a Railpack build directory "${n.buildDir}" that does not exist. Create it or fix the \`image.build\` path in lunora/containers.ts.`;return r.error(s),s}}},Ke=(e,r)=>(j(e,r)?.d1_databases??[]).find(a=>a.database_id===G)?.binding,qe=e=>{if(!e.migrate||e.dryRun||e.preview)return;if(e.migrateUrl===void 0){const a="--migrate requires --migrate-url <https://your-worker> — the deploy target URL is only known after wrangler runs, and this gate runs before it; refusing to default to localhost";return e.logger.error(a),a}if(e.migrateYes!==!0){const a="--migrate runs production data migrations after deploy. Re-run with --migrate-yes to confirm.";return e.logger.error(a),a}const r=e.migrateToken??process.env.LUNORA_ADMIN_TOKEN;if(r===void 0||r===""){const a="admin token required for --migrate — pass --migrate-token or set LUNORA_ADMIN_TOKEN";return e.logger.error(a),a}},Ye=(e,r,a="deploy",t)=>{const n=Ke(e,t);if(n===void 0)return;const o=`${a} blocked: the "${n}" D1 binding has a placeholder database_id ("${G}"). Run \`wrangler d1 create <name>\` to create the database, then replace the placeholder in wrangler.jsonc with the real id before deploying.`;return r.error(o),o},ze=(e,r,a="deploy",t)=>{const n=j(e,t)?.vars;if(!n)return;const o=Object.entries(n).filter(([,s])=>typeof s=="string"&&Be(s)).map(([s])=>s).toSorted((s,c)=>s.localeCompare(c));if(o.length===0)return;const i=`${a} blocked: ${o.join(", ")} in wrangler.jsonc point at localhost. A deployed Worker can't reach a loopback address, so this silently breaks scheduled-job dispatch, reverse cross-shard relations, and auth callbacks. Set each to the deployed worker's public URL (or move it to a secret with \`wrangler secret put\`) before deploying.`;return r.error(i),i},Je=(e,r,a)=>{const t=Ye(e,r.logger,a,r.env);if(t!==void 0)return{code:h.USAGE,error:t};const n=ze(e,r.logger,a,r.env);if(n!==void 0)return{code:h.USAGE,error:n};const o=Ge(e,r.logger,a);if(o!==void 0)return{code:h.USAGE,error:o};const i=He(e,r.logger,r.dockerAvailable??Re,a,r.env);return i===void 0?void 0:{code:h.MISSING_DEPENDENCY,error:i}},Xe=/https?:\/\/[^\s"'<>]+\.workers\.dev[^\s"'<>]*/u,Qe=/https:\/\/[^\s"'<>]+/u,Ze=e=>{if(e===void 0)return;const r=Xe.exec(e);return r?r[0]:Qe.exec(e)?.[0]},_=e=>e===void 0?"":` (--env ${e})`,er=({cwd:e,env:r,logger:a,now:t,url:n})=>{if(n!==void 0)try{const o=I(e);if(o!==void 0){if(o.workerUrl===n&&o.env===r)return;a.warn(`link: .lunora/project.json records ${o.workerUrl??"(no url)"}${_(o.env)}, but this deploy published ${n}${_(r)}. Keeping the recorded value — run \`lunora link --url ${n}${r===void 0?"":` --env ${r}`}\` to update it.`);return}const i=(t??(()=>new Date().toISOString()))();ee(e,{env:r,linkedAt:i,workerName:C(e),workerUrl:n}),a.success(`link: recorded ${n} in .lunora/project.json (run \`lunora link\` to change)`)}catch{}},rr=async(e,r)=>{const a=new xe({skipAddingFilesFromTsConfig:!0}),t=y(r,"lunora");let n;try{n=X(a,t)}catch(o){const i=o instanceof Error?o.message:String(o);return e.logger.warn(`--migrate: could not discover migrations (${i}); skipping`),0}if(n.length===0)return e.logger.info("--migrate: no data migrations declared in lunora/"),0;e.logger.info(`--migrate: running ${String(n.length)} migration(s) against deployed worker`);for(const o of n){e.logger.info(`--migrate: up "${o.id}" (table "${o.table}")`);const i={cwd:r,fetchImpl:e.fetchImpl,id:o.id,logger:e.logger,prod:!0,subcommand:"up",token:e.migrateToken,url:e.migrateUrl,yes:e.migrateYes===!0},s=await Ie(i);if(s.code!==0)return e.logger.error(`--migrate: migration "${o.id}" failed — see output above`),s.code;e.logger.success(`--migrate: "${o.id}" applied`)}return 0},tr=async(e,r)=>{const{info:a}=re(r,"lunora"),t=a?.vectorMetadata??[];if(t.length===0)return;const n=[];for(const s of t){const c=Te(s.kind);if(c===void 0){e.logger.warn(`vector index "${s.index}" declares metadata "${s.property}", whose column type cannot be filtered on in Vectorize — it is stored with each vector but no filter will match it.`);continue}n.push({index:s.index,property:s.property,type:c})}if(n.length===0)return;const i=(await _e({cwd:r,entries:n,exec:L(b(r),"wrangler",[]),logger:e.logger,spawner:e.spawner??$})).filter(s=>s.status!=="failed").length;i>0&&e.logger.success(`vectorize metadata indexes ready: ${String(i)}/${String(n.length)}`)},N=5,nr=2e3,ar=async(e,r,a)=>{if(e.healthCheck!==!0)return;const t=a??V({cwd:r,env:e.env});if(t===void 0){const o="--health-check: the deploy succeeded, but no URL to probe could be resolved — wrangler's output carried none and this checkout has no link for this environment. Run `lunora link --url <https://your-worker>` and re-deploy, or drop --health-check.";return e.logger.error(o),{error:o,ok:!1,url:""}}const n=await Ae({attempts:N,baseUrl:t,delayMs:nr,fetchImpl:e.healthFetch,paths:[Ce,je],sleep:e.healthSleep});return n.error===void 0?(e.logger.success(`health check ok (${n.url})`),{ok:!0,url:n.url}):(e.logger.error(`--health-check: the deploy succeeded, but the new version did not answer after ${String(N)} attempt(s) — ${n.error}`),{error:n.error,ok:!1,url:n.url})},or=async(e,r,a,t,n,o)=>{await tr(e,r);const i=e.migrate?await rr(e,r):0;return i===0&&n?.(),{code:i,descriptor:a,mintedSecretsFile:o,validation:t}},ir=async({cwd:e,descriptor:r,mintedSecretsFile:a,options:t,reblessSchemaBaseline:n,stdout:o,validation:i})=>{const s={deployedAt:new Date().toISOString(),dryRun:t.dryRun===!0,env:t.env,preview:t.preview===!0,url:t.dryRun===!0?void 0:Ze(o),workerName:C(e)};if(t.dryRun===!0||t.preview===!0)return t.healthCheck===!0&&t.logger.warn(`--health-check skipped: ${t.dryRun===!0?"a dry run publishes nothing":"a preview version serves no live traffic"}`),{code:0,deployment:s,descriptor:r,mintedSecretsFile:a,validation:i};t.temporary!==!0&&er({cwd:e,env:t.env,logger:t.logger,url:s.url});const c=await ar(t,e,s.url);return c?.error!==void 0?{code:h.UNAVAILABLE,deployment:s,descriptor:r,healthCheck:c,mintedSecretsFile:a,validation:i}:{...await or(t,e,r,i,n,a),deployment:s,healthCheck:c}},sr=(e,r,a)=>{const t=y(e,w);if(!p(t))return;let n;try{n=O(k(t,"utf8")).length}catch{return}if(n===0)return;const o=a.toolchain?.secretPut!==void 0;r.warn(o?`Note: \`lunora deploy\` does not push secrets. ${w} has ${String(n)} key(s); if you changed them, run \`lunora env push --yes\` to update the deployed secrets.`:`Note: ${a.name} deploys read no secrets. ${w} has ${String(n)} key(s) that only the dev server sees; put the values the deployed worker needs in wrangler \`vars\`.`)},cr=async e=>{let r=[];try{r=te(await F({projectRoot:e,schemaDir:W(e)}))}catch{}const a=ne(r).map(n=>n.key);let t=[];try{const n=y(e,w);p(n)&&(t=O(k(n,"utf8")).map(o=>o.key).filter(o=>Ne(o)))}catch{}return[...new Set([...a,...t])]},lr=async(e,r,a,t)=>{const{logger:n}=r,o=r.spawner??$,i=b(e),s=r.env===void 0?"":` --env ${r.env}`,c=t.toolchain?.secretPut;if(c===void 0)return n.error(`deploy target "${t.id}" has no secret store; cannot push secrets`),{minted:[],ok:!1};const d=[];for(const l of a){const m=ae(),u=c({environment:r.env,key:l,temporary:r.temporary}),g=R(i,u),f=await o({args:g.args,command:g.command,cwd:e,input:m});if(f.code!==0)return n.error(`failed to push secret ${l} (exit ${String(f.code)}); set it manually with \`wrangler secret put ${l}${s}\`.`),{minted:d,ok:!1};d.push({key:l,value:m}),n.success(`generated + pushed ${l}`)}return{minted:d,ok:!0}},dr=/^[\w-]+$/u,D=[".dev.vars",".dev.vars.*","!.dev.vars.example"],ur=/\r?\n/u,gr=(e,r)=>{const a=y(e,".gitignore");try{const t=p(a)?k(a,"utf8"):"",n=new Set(t.split(ur).map(c=>c.trim())),o=D.filter(c=>!n.has(c));if(o.length===0)return;const i=o.some(c=>!c.startsWith("!"))?[...o.filter(c=>!c.startsWith("!")),...D.filter(c=>c.startsWith("!"))]:o,s=t.length>0&&!t.endsWith(`
|
|
1
|
+
import{join as z,dirname as J}from"node:path";import{discoverMigrations as X,readServiceBindings as Q,runCodegen as Z}from"@lunora/codegen";import{readLinkedProject as I,execArgsFor as L,detectPackageManager as b,discoverContainerInfo as U,COMPOSED_WORKER_ENTRY as P,writeLinkedProject as ee,discoverSchemaInfo as re,DEV_VARS_FILE as w,parseDevVariableEntries as O,isMintableSecretKey as x,packageNamesFromBindings as te,inferLunoraBindings as F,resolveSchemaDirectory as W,requiredSecrets as ne,generateSecretValue as ae,toolchainExecArgs as R,upsertDevVariableLine as oe,writeDevVariablesFileAtomically as ie,resolveDeployDriver as A,planToolchainInvocation as M,runPostCodegenHook as se}from"@lunora/config";import{findWranglerFile as B,readWranglerJsonc as ce,mergeWranglerEnvironment as le,warnCloudflareCliConfigOnce as de,validateWranglerProject as ue,reconcileWranglerBindings as ge,reconcileWranglerCompatibilityDate as me,reconcileWranglerCrons as fe,describePreservedCrons as he}from"@lunora/config/cloudflare";import{Spinner as ve}from"@visulima/spinner";import{r as pe,a as ye,e as we}from"../packem_shared/platform-diagnostics-Cn2g6Jh-.mjs";import{p as ke,a as be}from"../packem_shared/deploy-target-DCWwiuAe.mjs";import{w as $e}from"../packem_shared/binding-manifest-file-CQ1eQYy1.mjs";import{d as Se}from"../packem_shared/command-CAXl2A1S.mjs";import{r as C}from"../packem_shared/wrangler-name-Dsk5K1f-.mjs";import{EXIT_CODE as h}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import{containerBuildTag as De}from"@lunora/container";import{a as Ee,i as Re}from"../packem_shared/docker-DpVxvYpL.mjs";import{defaultSpawner as $}from"../packem_shared/createRecordingSpawner-Ch7zuQQE.mjs";import{r as V}from"../packem_shared/resolve-target-C_ZloTvd.mjs";import{p as Ae,H as Ce,a as je,r as Pe}from"../packem_shared/health-probe-Bw9JFfIy.mjs";import{existsSync as p,readFileSync as k,writeFileSync as H}from"node:fs";import{join as y}from"@visulima/path";import{Project as xe}from"ts-morph";import{m as Te,e as _e,i as Ne}from"../packem_shared/secret-key-DsMeUoEg.mjs";import{runMigrateDataCommand as Ie}from"../packem_shared/runMigrateGenerateCommand-Ii_WMZEA.mjs";import{c as Le}from"../packem_shared/tui-prompts-B3YwUhGw.mjs";import{l as Ue}from"../packem_shared/wrangler-secrets-3chIVv3H.mjs";const Oe=e=>{const{cwd:r,env:a,logger:t,mintedSecretsFile:n}=e;try{const o=I(r),i=o?.workerName??C(r),s=e.url??o?.workerUrl;t.success("deploy complete"),t.info(` worker: ${i??"(see wrangler output above)"}`),a!==void 0&&t.info(` env: ${a}`),s===void 0?t.info(" url: run `lunora link --url <https://your-worker>` to record it"):t.info(` url: ${s}`),n!==void 0&&t.info(` secrets: generated value(s) recorded in ${n}`),e.logsAvailable&&t.info(" logs: lunora logs")}catch{}},Fe=async e=>{if(e.targets.length===0)return{builtTags:[],code:0};if(!(e.railpackAvailable??Ee)()){const t="deploy blocked: a container uses `image: { build }` (Railpack), but Railpack isn't ready. Install the `railpack` CLI and start a BuildKit instance, e.g. `docker run --rm --privileged -d --name buildkit moby/buildkit` then `export BUILDKIT_HOST=docker-container://buildkit`. Alternatively switch the container's `image` to a Dockerfile path or a pre-built registry reference.";return e.logger.error(t),{builtTags:[],code:1,error:t}}const r=e.spawner??$,a=[];for(const t of e.targets){const n=De(t.exportName),o={args:["build",t.buildDir,"--name",n],command:"railpack",cwd:e.cwd},i=L(b(e.cwd),"wrangler",["containers","push",n]),s={args:i.args,command:i.command,cwd:e.cwd};e.logger.info(`railpack: building "${t.exportName}" → ${n} from ${t.buildDir}`);const c=await r(o);if(c.code!==0){const l=`railpack build failed for container "${t.exportName}" (${t.buildDir})`;return e.logger.error(l),{builtTags:a,code:c.code,error:l}}e.logger.info(`railpack: pushing ${n} to the Cloudflare Registry`);const d=await r(s);if(d.code!==0){const l=`wrangler containers push failed for "${t.exportName}" (${n})`;return e.logger.error(l),{builtTags:a,code:d.code,error:l}}a.push(n)}return{builtTags:a,code:0}},We=e=>{const a=[B(e),z(e,"package.json")].filter(t=>t!==void 0&&p(t)).map(t=>[t,k(t,"utf8")]);return()=>{for(const[t,n]of a)k(t,"utf8")!==n&&H(t,n,"utf8")}},G="<replace-with-d1-create-id>",T=e=>Array.isArray(e)?e.filter(r=>r!=null):void 0,j=(e,r)=>{const a=B(e);if(!a)return;const{parsed:t}=ce(a);if(t===void 0)return;const{error:n,merged:o}=le(t,r),i=n===void 0?o:t,{containers:s,d1_databases:c,vars:d}=i;return{containers:T(s),d1_databases:T(c),vars:typeof d=="object"&&d!==null&&!Array.isArray(d)?d:void 0}},Me=/^127(?:\.\d{1,3}){3}$/,Be=e=>{try{const{hostname:r}=new URL(e);return r==="localhost"||Me.test(r)||r==="::1"||r==="[::1]"}catch{return!1}},Ve=e=>e.startsWith("./")||e.startsWith("../")||e.startsWith("/")||e.includes("Dockerfile"),He=(e,r,a,t="deploy",n)=>{const o=(j(e,n)?.containers??[]).filter(s=>typeof s?.image=="string"&&Ve(s.image));if(o.length===0||a())return;const i=`${t} blocked: wrangler.jsonc declares ${String(o.length)} container(s) built from a local Dockerfile, but no Docker-compatible engine is available. Start Docker (or Colima), or point the container's \`image\` at a pre-built registry reference. Note: container images must target linux/amd64.`;return r.error(i),i},K=e=>p(y(e,P))?P:void 0,Ge=(e,r,a="deploy")=>{for(const t of U(e,"lunora").containers){const n=t.schedulingPolicy===void 0?t.image:void 0,i=[...n?.kind==="dockerfile"?[{field:"image",path:n.dockerfilePath}]:[],...Object.entries(t.schedulingPolicy==="durable_object"?t.images??{}:{}).flatMap(([s,c])=>c.kind==="dockerfile"?[{field:`images["${s}"]`,path:c.dockerfilePath}]:[])].find(s=>!p(y(e,s.path)));if(i!==void 0){const s=`${a} blocked: container "${t.exportName}" references a Dockerfile at "${i.path}" that does not exist. Create it or fix the \`${i.field}\` path in lunora/containers.ts.`;return r.error(s),s}if(n?.kind==="build"&&!p(y(e,n.buildDir))){const s=`${a} blocked: container "${t.exportName}" references a Railpack build directory "${n.buildDir}" that does not exist. Create it or fix the \`image.build\` path in lunora/containers.ts.`;return r.error(s),s}}},Ke=(e,r)=>(j(e,r)?.d1_databases??[]).find(a=>a.database_id===G)?.binding,qe=e=>{if(!e.migrate||e.dryRun||e.preview)return;if(e.migrateUrl===void 0){const a="--migrate requires --migrate-url <https://your-worker> — the deploy target URL is only known after wrangler runs, and this gate runs before it; refusing to default to localhost";return e.logger.error(a),a}if(e.migrateYes!==!0){const a="--migrate runs production data migrations after deploy. Re-run with --migrate-yes to confirm.";return e.logger.error(a),a}const r=e.migrateToken??process.env.LUNORA_ADMIN_TOKEN;if(r===void 0||r===""){const a="admin token required for --migrate — pass --migrate-token or set LUNORA_ADMIN_TOKEN";return e.logger.error(a),a}},Ye=(e,r,a="deploy",t)=>{const n=Ke(e,t);if(n===void 0)return;const o=`${a} blocked: the "${n}" D1 binding has a placeholder database_id ("${G}"). Run \`wrangler d1 create <name>\` to create the database, then replace the placeholder in wrangler.jsonc with the real id before deploying.`;return r.error(o),o},ze=(e,r,a="deploy",t)=>{const n=j(e,t)?.vars;if(!n)return;const o=Object.entries(n).filter(([,s])=>typeof s=="string"&&Be(s)).map(([s])=>s).toSorted((s,c)=>s.localeCompare(c));if(o.length===0)return;const i=`${a} blocked: ${o.join(", ")} in wrangler.jsonc point at localhost. A deployed Worker can't reach a loopback address, so this silently breaks scheduled-job dispatch, reverse cross-shard relations, and auth callbacks. Set each to the deployed worker's public URL (or move it to a secret with \`wrangler secret put\`) before deploying.`;return r.error(i),i},Je=(e,r,a)=>{const t=Ye(e,r.logger,a,r.env);if(t!==void 0)return{code:h.USAGE,error:t};const n=ze(e,r.logger,a,r.env);if(n!==void 0)return{code:h.USAGE,error:n};const o=Ge(e,r.logger,a);if(o!==void 0)return{code:h.USAGE,error:o};const i=He(e,r.logger,r.dockerAvailable??Re,a,r.env);return i===void 0?void 0:{code:h.MISSING_DEPENDENCY,error:i}},Xe=/https?:\/\/[^\s"'<>]+\.workers\.dev[^\s"'<>]*/u,Qe=/https:\/\/[^\s"'<>]+/u,Ze=e=>{if(e===void 0)return;const r=Xe.exec(e);return r?r[0]:Qe.exec(e)?.[0]},_=e=>e===void 0?"":` (--env ${e})`,er=({cwd:e,env:r,logger:a,now:t,url:n})=>{if(n!==void 0)try{const o=I(e);if(o!==void 0){if(o.workerUrl===n&&o.env===r)return;a.warn(`link: .lunora/project.json records ${o.workerUrl??"(no url)"}${_(o.env)}, but this deploy published ${n}${_(r)}. Keeping the recorded value — run \`lunora link --url ${n}${r===void 0?"":` --env ${r}`}\` to update it.`);return}const i=(t??(()=>new Date().toISOString()))();ee(e,{env:r,linkedAt:i,workerName:C(e),workerUrl:n}),a.success(`link: recorded ${n} in .lunora/project.json (run \`lunora link\` to change)`)}catch{}},rr=async(e,r)=>{const a=new xe({skipAddingFilesFromTsConfig:!0}),t=y(r,"lunora");let n;try{n=X(a,t)}catch(o){const i=o instanceof Error?o.message:String(o);return e.logger.warn(`--migrate: could not discover migrations (${i}); skipping`),0}if(n.length===0)return e.logger.info("--migrate: no data migrations declared in lunora/"),0;e.logger.info(`--migrate: running ${String(n.length)} migration(s) against deployed worker`);for(const o of n){e.logger.info(`--migrate: up "${o.id}" (table "${o.table}")`);const i={cwd:r,fetchImpl:e.fetchImpl,id:o.id,logger:e.logger,prod:!0,subcommand:"up",token:e.migrateToken,url:e.migrateUrl,yes:e.migrateYes===!0},s=await Ie(i);if(s.code!==0)return e.logger.error(`--migrate: migration "${o.id}" failed — see output above`),s.code;e.logger.success(`--migrate: "${o.id}" applied`)}return 0},tr=async(e,r)=>{const{info:a}=re(r,"lunora"),t=a?.vectorMetadata??[];if(t.length===0)return;const n=[];for(const s of t){const c=Te(s.kind);if(c===void 0){e.logger.warn(`vector index "${s.index}" declares metadata "${s.property}", whose column type cannot be filtered on in Vectorize — it is stored with each vector but no filter will match it.`);continue}n.push({index:s.index,property:s.property,type:c})}if(n.length===0)return;const i=(await _e({cwd:r,entries:n,exec:L(b(r),"wrangler",[]),logger:e.logger,spawner:e.spawner??$})).filter(s=>s.status!=="failed").length;i>0&&e.logger.success(`vectorize metadata indexes ready: ${String(i)}/${String(n.length)}`)},N=5,nr=2e3,ar=async(e,r,a)=>{if(e.healthCheck!==!0)return;const t=a??V({cwd:r,env:e.env});if(t===void 0){const o="--health-check: the deploy succeeded, but no URL to probe could be resolved — wrangler's output carried none and this checkout has no link for this environment. Run `lunora link --url <https://your-worker>` and re-deploy, or drop --health-check.";return e.logger.error(o),{error:o,ok:!1,url:""}}const n=await Ae({attempts:N,baseUrl:t,delayMs:nr,fetchImpl:e.healthFetch,paths:[Ce,je],sleep:e.healthSleep});return n.error===void 0?(e.logger.success(`health check ok (${n.url})`),{ok:!0,url:n.url}):(e.logger.error(`--health-check: the deploy succeeded, but the new version did not answer after ${String(N)} attempt(s) — ${n.error}`),{error:n.error,ok:!1,url:n.url})},or=async(e,r,a,t,n,o)=>{await tr(e,r);const i=e.migrate?await rr(e,r):0;return i===0&&n?.(),{code:i,descriptor:a,mintedSecretsFile:o,validation:t}},ir=async({cwd:e,descriptor:r,mintedSecretsFile:a,options:t,reblessSchemaBaseline:n,stdout:o,validation:i})=>{const s={deployedAt:new Date().toISOString(),dryRun:t.dryRun===!0,env:t.env,preview:t.preview===!0,url:t.dryRun===!0?void 0:Ze(o),workerName:C(e)};if(t.dryRun===!0||t.preview===!0)return t.healthCheck===!0&&t.logger.warn(`--health-check skipped: ${t.dryRun===!0?"a dry run publishes nothing":"a preview version serves no live traffic"}`),{code:0,deployment:s,descriptor:r,mintedSecretsFile:a,validation:i};t.temporary!==!0&&er({cwd:e,env:t.env,logger:t.logger,url:s.url});const c=await ar(t,e,s.url);return c?.error!==void 0?{code:h.UNAVAILABLE,deployment:s,descriptor:r,healthCheck:c,mintedSecretsFile:a,validation:i}:{...await or(t,e,r,i,n,a),deployment:s,healthCheck:c}},sr=(e,r,a)=>{const t=y(e,w);if(!p(t))return;let n;try{n=O(k(t,"utf8")).length}catch{return}if(n===0)return;const o=a.toolchain?.secretPut!==void 0;r.warn(o?`Note: \`lunora deploy\` does not push secrets. ${w} has ${String(n)} key(s); if you changed them, run \`lunora env push --yes\` to update the deployed secrets.`:`Note: ${a.name} deploys read no secrets. ${w} has ${String(n)} key(s) that only the dev server sees; put the values the deployed worker needs in wrangler \`vars\`.`)},cr=async e=>{let r=[];try{r=te(await F({projectRoot:e,schemaDir:W(e)}))}catch{}const a=ne(r).map(n=>n.key);let t=[];try{const n=y(e,w);p(n)&&(t=O(k(n,"utf8")).map(o=>o.key).filter(o=>Ne(o)))}catch{}return[...new Set([...a,...t])]},lr=async(e,r,a,t)=>{const{logger:n}=r,o=r.spawner??$,i=b(e),s=r.env===void 0?"":` --env ${r.env}`,c=t.toolchain?.secretPut;if(c===void 0)return n.error(`deploy target "${t.id}" has no secret store; cannot push secrets`),{minted:[],ok:!1};const d=[];for(const l of a){const m=ae(),u=c({environment:r.env,key:l,temporary:r.temporary}),g=R(i,u),f=await o({args:g.args,command:g.command,cwd:e,input:m});if(f.code!==0)return n.error(`failed to push secret ${l} (exit ${String(f.code)}); set it manually with \`wrangler secret put ${l}${s}\`.`),{minted:d,ok:!1};d.push({key:l,value:m}),n.success(`generated + pushed ${l}`)}return{minted:d,ok:!0}},dr=/^[\w-]+$/u,D=[".dev.vars",".dev.vars.*","!.dev.vars.example"],ur=/\r?\n/u,gr=(e,r)=>{const a=y(e,".gitignore");try{const t=p(a)?k(a,"utf8"):"",n=new Set(t.split(ur).map(c=>c.trim())),o=D.filter(c=>!n.has(c));if(o.length===0)return;const i=o.some(c=>!c.startsWith("!"))?[...o.filter(c=>!c.startsWith("!")),...D.filter(c=>c.startsWith("!"))]:o,s=t.length>0&&!t.endsWith(`
|
|
2
2
|
`)?`
|
|
3
3
|
`:"";H(a,`${t}${s}
|
|
4
4
|
# Lunora — never commit a minted secret
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{runCodegen as L}from"@lunora/codegen";import{runPostCodegenHook as H,detectAgentRules as N,updateDevServerState as I,readDevServerState as V,DEV_DAEMON_ENV as M,detectAiAgent as W,readProjectRemotePreference as B,readLiveDevServerState as j,DEV_HANDOFF_ENV as p,clearDevServerState as U,claimDevServerState as G,DEV_LOG_FILE_ENV as X,inferLunoraBindings as Y,resolveSchemaDirectory as J,packageNamesFromBindings as K,ensureDevVarsExample as z,ensureDevVariables as Q,isInteractive as Z,DEV_VARS_FILE as D,DEV_VARS_EXAMPLE_FILE as q,fillDevSecrets as ee,DEV_BINDINGS_FILE as re,DEV_STATE_FILE as F,claimAgentRulesHint as te,AGENT_RULES_HINT as ne}from"@lunora/config";import{resolveRemoteEnabled as oe}from"@lunora/config/cloudflare";import{p as ae,a as ie}from"../packem_shared/deploy-target-DCWwiuAe.mjs";import{w as se}from"../packem_shared/binding-manifest-file-CQ1eQYy1.mjs";import{existsSync as ce,watch as de}from"node:fs";import{join as le}from"node:path";import{a as ue}from"../packem_shared/codegen-error-AmH54ofi.mjs";import{a as fe}from"../packem_shared/platform-diagnostics-Cn2g6Jh-.mjs";import{d as ge}from"../packem_shared/command-CAXl2A1S.mjs";import{EXIT_CODE as E}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import{forceJsonLogging as ve}from"../packem_shared/createLogger-Cl18I8AX.mjs";import{createServer as me,request as we}from"node:http";import{connect as he}from"node:net";import{pipeline as Se}from"node:stream";import{loadStudioAssets as T,studioAssetsStamp as A,renderStudioHtml as ye,resolveAdminToken as pe,requestPathname as _,transportRejectionReason as P,SCHEMA_EDIT_ENDPOINT as Ee,POLICY_SCAFFOLD_ENDPOINT as be,SEED_ENDPOINT as ke,sendStudioDocument as De,serveJsonHandler as Te,isStandaloneModulePath as Ae,readStandaloneAsset as _e,assetContentType as Pe,handleSchemaEditRequest as Re,handlePolicyScaffoldRequest as Oe,handleSeedRequest as $e,applyStudioAssetCache as Ce}from"@lunora/config/studio-host";import{c as Le}from"../packem_shared/tui-prompts-B3YwUhGw.mjs";import{setTimeout as Ne}from"node:timers/promises";import{r as Ie,d as Me,P as je,a as Fe,b,c as xe,s as He,n as x,e as Ve,f as We,g as Be,h as Ue,i as R,w as Ge,j as Xe,k as Ye,t as Je,l as Ke,m as ze,o as Qe}from"../packem_shared/plan-
|
|
1
|
+
import{runCodegen as L}from"@lunora/codegen";import{runPostCodegenHook as H,detectAgentRules as N,updateDevServerState as I,readDevServerState as V,DEV_DAEMON_ENV as M,detectAiAgent as W,readProjectRemotePreference as B,readLiveDevServerState as j,DEV_HANDOFF_ENV as p,clearDevServerState as U,claimDevServerState as G,DEV_LOG_FILE_ENV as X,inferLunoraBindings as Y,resolveSchemaDirectory as J,packageNamesFromBindings as K,ensureDevVarsExample as z,ensureDevVariables as Q,isInteractive as Z,DEV_VARS_FILE as D,DEV_VARS_EXAMPLE_FILE as q,fillDevSecrets as ee,DEV_BINDINGS_FILE as re,DEV_STATE_FILE as F,claimAgentRulesHint as te,AGENT_RULES_HINT as ne}from"@lunora/config";import{resolveRemoteEnabled as oe}from"@lunora/config/cloudflare";import{p as ae,a as ie}from"../packem_shared/deploy-target-DCWwiuAe.mjs";import{w as se}from"../packem_shared/binding-manifest-file-CQ1eQYy1.mjs";import{existsSync as ce,watch as de}from"node:fs";import{join as le}from"node:path";import{a as ue}from"../packem_shared/codegen-error-AmH54ofi.mjs";import{a as fe}from"../packem_shared/platform-diagnostics-Cn2g6Jh-.mjs";import{d as ge}from"../packem_shared/command-CAXl2A1S.mjs";import{EXIT_CODE as E}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import{forceJsonLogging as ve}from"../packem_shared/createLogger-Cl18I8AX.mjs";import{createServer as me,request as we}from"node:http";import{connect as he}from"node:net";import{pipeline as Se}from"node:stream";import{loadStudioAssets as T,studioAssetsStamp as A,renderStudioHtml as ye,resolveAdminToken as pe,requestPathname as _,transportRejectionReason as P,SCHEMA_EDIT_ENDPOINT as Ee,POLICY_SCAFFOLD_ENDPOINT as be,SEED_ENDPOINT as ke,sendStudioDocument as De,serveJsonHandler as Te,isStandaloneModulePath as Ae,readStandaloneAsset as _e,assetContentType as Pe,handleSchemaEditRequest as Re,handlePolicyScaffoldRequest as Oe,handleSeedRequest as $e,applyStudioAssetCache as Ce}from"@lunora/config/studio-host";import{c as Le}from"../packem_shared/tui-prompts-B3YwUhGw.mjs";import{setTimeout as Ne}from"node:timers/promises";import{r as Ie,d as Me,P as je,a as Fe,b,c as xe,s as He,n as x,e as Ve,f as We,g as Be,h as Ue,i as R,w as Ge,j as Xe,k as Ye,t as Je,l as Ke,m as ze,o as Qe}from"../packem_shared/plan-Cod9Cgll.mjs";import{provisionBindings as Ze}from"./runDeployCommand.mjs";const qe=100,er=300,rr=/[/\\]/u,tr=(e,r,t)=>{const{apiSpec:n,logger:a,projectRoot:i,target:u}=e;try{const o=L({apiSpec:n,lunoraDirectory:r,projectRoot:i,target:u});a.success(`codegen: wrote ${r}/_generated (${t})`),fe(o.platformDiagnostics,a)}catch(o){return a.error(ue(o,t)),!1}return!0},nr=e=>{const r=e.lunoraDirectory??"lunora",t=le(e.projectRoot,r),n=e.debounceMs??qe;let a=!1,i=!1,u=!1,o,d=0,g=Promise.resolve(),h;const S=new Promise(f=>{h=f}),v=f=>{a||(o=f,!i&&(i=!0,g=(async()=>{try{for(;o!==void 0;){const w=o;if(o=void 0,!!tr(e,r,w)){u=!0;try{(await H({cwd:e.projectRoot,logger:e.logger,spawner:e.spawner,stdoutToStderr:e.jsonLogs})).ran&&(d=Date.now())}finally{u=!1}}}}catch(w){e.logger.error(`codegen watch: ${w instanceof Error?w.message:String(w)}`)}finally{i=!1,h()}})()))};v("startup");const c=f=>(e.logger.warn(`codegen watch unavailable (${f}) — schema edits will NOT auto-regenerate. Run \`lunora codegen\` manually after each edit.`),{close:()=>(a=!0,o=void 0,g),ready:S,watchAvailable:!1});let s,l;if(!ce(t))return c(`no such directory: ${t}`);try{l=de(t,{recursive:!0},(f,w)=>{if(!(typeof w=="string"&&w.split(rr).includes("_generated"))){if(u||Date.now()-d<er){s&&(clearTimeout(s),s=void 0);return}s&&clearTimeout(s),s=setTimeout(()=>{v(`change: ${w??"?"}`)},n)}})}catch(f){return c(f instanceof Error?f.message:String(f))}const m=l;return{close:()=>(a=!0,o=void 0,s&&clearTimeout(s),m.close(),g),ready:S,watchAvailable:!0}},O="/_lunora",$=3e4,C=(e,r,t)=>{const n=we({headers:{...e.headers,host:t.host},hostname:t.hostname,method:e.method,path:e.url,port:t.port},a=>{r.writeHead(a.statusCode??502,a.headers),Se(a,r,()=>{})});n.setTimeout($,()=>{n.destroy(new Error(`no response within ${String($)}ms`))}),n.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||n.destroy()}),e.pipe(n)},or=5e3,ar=(e,r,t,n)=>{const a=he({host:n.hostname,port:Number(n.port)},()=>{a.setTimeout(0);const i=[`${e.method??"GET"} ${e.url??"/"} HTTP/1.1`];for(const[u,o]of Object.entries(e.headers))if(u!=="host")for(const d of Array.isArray(o)?o:[o])d!==void 0&&i.push(`${u}: ${d}`);i.push(`host: ${n.host}`,"",""),a.write(i.join(`\r
|
|
2
2
|
`)),t.length>0&&a.write(t),a.pipe(r),r.pipe(a)});a.setTimeout(or,()=>a.destroy()),a.on("error",()=>r.destroy()),r.on("error",()=>a.destroy())},ir=async e=>{const r=e.host??"127.0.0.1",t=r==="127.0.0.1"||r==="localhost"||r==="::1",n=new URL(e.workerOrigin);let a=T(e.logger,import.meta.url),i=A(import.meta.url);const u=ye({adminToken:t?pe(e.cwd):void 0,basePath:"/",dataEditable:t,rulesInstalled:N(e.cwd).installed,runAsIdentity:t,schemaEditable:t,scriptSrc:"/studio.js",styleHref:"/styles.css"}),o=(c,s,l,m,f)=>{Ce(c,s,f,i)||(s.statusCode=200,s.setHeader("Content-Type",m),s.end(l))},d=(c,s,l)=>{c.statusCode=s,c.setHeader("Content-Type","text/plain"),c.end(l)},g=(c,s,l,m)=>{if(t){Te(c,s,l,e.cwd,{apiSpec:e.apiSpec});return}d(s,403,m)},h=(c,s,l)=>{const m=c==="/styles.css",f=Ae(c);if(!m&&!f)return!1;const w=A(import.meta.url);if(w!==i&&(a=T(e.logger,import.meta.url),i=w),a===void 0)return d(l,501,"Lunora studio assets not found — install and build @lunora/studio."),!0;if(m)return o(s,l,a.styles,"text/css; charset=utf-8","styles.css"),!0;const y=c.slice(c.lastIndexOf("/")+1),k=_e(y,import.meta.url);return k===void 0?(d(l,404,"Not found"),!0):(o(s,l,k,Pe(y),y),!0)},S=Buffer.from(u),v=me((c,s)=>{const l=_(c.url??"/");if(t){const f=P(c,e.logger);if(f!==void 0){d(s,403,f);return}}if(l.startsWith(O)){if(!t){d(s,403,"Lunora studio: the worker admin proxy is only available on a loopback bind.");return}C(c,s,n);return}if(l===Ee){g(c,s,Re,"Lunora schema editing is only available on loopback hosts in dev.");return}if(l===be){g(c,s,Oe,"Lunora policy scaffolding is only available on loopback hosts in dev.");return}if(l===ke){g(c,s,$e,"Lunora data seeding is only available on loopback hosts in dev.");return}if(h(l,c,s))return;const m=c.headers["sec-fetch-mode"];if(t&&typeof m=="string"&&m!=="navigate"){C(c,s,n);return}De(s,S)});return v.on("upgrade",(c,s,l)=>{if(!t||P(c,e.logger)!==void 0){s.destroy();return}_(c.url??"").startsWith(O)?ar(c,s,l,n):s.destroy()}),await new Promise((c,s)=>{v.once("error",l=>{l.code==="EADDRINUSE"?s(new Error(`studio port ${String(e.port)} is already in use — pass a different port with --port, or stop the process using it`,{cause:l})):s(l)}),v.listen(e.port,r,()=>{c()})}),{close:()=>new Promise(c=>{v.close(()=>{c()})}),url:`http://${r==="0.0.0.0"||r==="::"?"localhost":r}:${String(e.port)}`}},sr=async e=>{const{cwd:r,logger:t,origin:n,signal:a}=e,i=e.probe??Me,u=Ie(e.readyTimeoutMs),o=Date.now()+u,d=()=>a.aborted;for(;!d()&&Date.now()<o;){let g=!1;try{g=await i(n,a)}catch{}if(d()||Date.now()>=o)break;if(g)return I(r,{readyAt:new Date().toISOString()},{expectedPid:process.pid}),V(r)?.readyAt!==void 0;try{await Ne(je,void 0,{signal:a})}catch{}}return d()||t.warn(`server did not answer on ${n} within ${String(Math.round(u/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},cr=(e,r,t,n)=>{e.info(""),e.success("Lunora dev"),e.info(` ➜ Worker: ${r.workerOrigin}`),t!==void 0&&e.info(` ➜ Studio: ${t}`),r.runsCodegenWatch&&e.info(" ➜ Codegen: watching lunora/"),n!==void 0&&e.info(` ➜ Supervisor: ${n} (needs) · ${F} (status)`),r.remote.enabled&&(r.remote.bindings.length>0?e.info(` ➜ Remote: ${r.remote.bindings.join(", ")} → deployed worker`):e.warn(` ➜ Remote: requested but inactive (${r.remote.reason??"no eligible bindings"}) — running fully local`)),e.info("")},dr=(e,r)=>{N(r).installed||!te()||(e.info(` ⓘ ${ne}`),e.info(""))},lr=async(e,r)=>{try{const n=await Y({projectRoot:r,schemaDir:J(r)}),a=K(n),i=(e.ensureExample??z)(r,a);i.length>0&&e.logger.info(`Updated .dev.vars.example with secrets for: ${a.join(", ")} (${i.join(", ")})`)}catch{}(await(e.ensureEnv??Q)({confirm:Le(),cwd:r,info:n=>{e.logger.info(n)}})).status==="declined"&&!Z()&&e.logger.info(`hint: ${D} was not scaffolded (non-interactive run). Copy ${q} → ${D} and fill in secrets, or run \`lunora dev\` in an interactive terminal to scaffold automatically.`);try{(e.fillSecrets??ee)({cwd:r,info:n=>{e.logger.info(n)}})}catch{}},ur=(e,r,t,n,a)=>{if(e.flavor!=="wrangler")return;n!==void 0&&I(r,{studioUrl:n});let i;try{i=Qe(r,t)}catch{}return cr(t,e,n,a),i},fr=(e,r)=>{const t=Number(process.env[p]),n=G(r,{background:process.env[M]==="1",logFile:process.env[X],mode:"cli",pid:process.pid,startedAt:new Date().toISOString(),url:e.workerOrigin},Number.isInteger(t)&&t>0?{supersedePid:t}:void 0);return n.ok?void 0:n.existing},gr=e=>{const{cwd:r,destination:t,logger:n,plan:a}=e,i=t!==void 0,u=t??re,o=se({destination:u,dev:{...a.flavor==="wrangler"?{origin:a.workerOrigin}:{},statusFile:F},logger:i?n:{...n,success:()=>{},warn:()=>{}},projectRoot:r});return o.error!==void 0?i?o:(n.debug?.(`skipped the default binding manifest: ${o.error}`),{}):{written:u}},vr=async(e,r,t,n)=>{if(r.studioEnabled)try{return await(e.startStudio??ir)({apiSpec:e.apiSpec,cwd:t,logger:{warnOnce:a=>{n.warn(a)}},port:r.studioPort,workerOrigin:r.workerOrigin})}catch(a){n.warn(`studio server failed to start (${a instanceof Error?a.message:String(a)}) — continuing without it`);return}},mr=e=>{const r=[e.runsCodegenWatch?"codegen watch":void 0,e.studioEnabled?"studio":void 0].filter(n=>n!==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}.`},wr=(e,r,t,n,a)=>{if(!(e.sidecar===void 0||!Ke(r)))try{L({apiSpec:r.apiSpec,lunoraDirectory:"lunora",projectRoot:t,target:a})}catch(i){n.warn(`codegen (pre-sidecar) failed: ${i instanceof Error?i.message:String(i)} — the framework dev server will retry`)}},hr=e=>e.flavor==="vite"?"starting vite dev (worker + studio + codegen run inside Vite via @lunora/vite)":`starting ${e.wrangler.tag} dev + studio`,Sr=async(e,r,t,n,a)=>{try{return e.celldSession===!0?await ze({logger:a,port:e.workerPort,projectRoot:n,start:r.startCelldSession}):t(e.wrangler,a)}catch(i){a.error(`could not start the worker: ${i instanceof Error?i.message:String(i)}`);return}},yr=async e=>{const{logger:r}=e,t=e.cwd??process.cwd(),n=e.flavor??Ve(t),a=ie(t,e.target);if(a.target===void 0)throw new Error(a.error??"unknown deploy target");const{target:i}=a,u=We(i,n,r);u==="wrangler"&&await Ze(t,r,void 0,i,void 0);const o=await Be({...e,flavor:u,target:i}),d={remoteCleanup:o.remote.cleanup,serviceConfigCleanup:o.serviceConfigCleanup};try{const g=Number(process.env[p]),h=j(t);if(h!==void 0&&h.pid!==process.pid&&h.pid!==g)return b(r,h),{code:0,plan:o};const S=fr(o,t);if(S!==void 0)return b(r,S),{code:0,plan:o};(o.flavor==="vite"||o.flavor==="framework-worker")&&(o.wrangler.env={...o.wrangler.env,[p]:String(process.pid)}),await lr(e,t),r.info(hr(o)),Ue(r,t),o.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."),o.runsCodegenWatch&&(d.codegen=(e.startCodegen??nr)({apiSpec:e.apiSpec,jsonLogs:e.jsonLogs,logger:r,projectRoot:t,target:i})),d.studio=await vr(e,o,t,r);const v=gr({cwd:t,destination:e.emitBindings,logger:r,plan:o});if(v.error!==void 0)return r.error(v.error),{code:E.USAGE,plan:o};await d.codegen?.ready;const c=d.studio?.url;o.frameworkHint!==void 0&&r.warn(o.frameworkHint);const s=()=>{o.flavor==="wrangler"&&(d.readyProbe=new AbortController,sr({cwd:t,logger:r,origin:o.workerOrigin,probe:e.probeReady,signal:d.readyProbe.signal}))};if(!o.workerEnabled)return s(),r.info(mr(o)),d.tunnel=R({cwd:t,logger:r,plan:o,tunnel:e.tunnel}),{code:await(e.waitForInterrupt??Ge)(r),plan:o};wr(o,e,t,r,i);const l=e.startWorker??Xe,m=await Sr(o,e,l,t,r);if(m===void 0)return{code:E.FAILURE,plan:o};const f=o.sidecar===void 0?void 0:l(o.sidecar,r);return s(),d.containerLogs=ur(o,t,r,c,v.written),d.tunnel=R({cwd:t,logger:r,plan:o,tunnel:e.tunnel}),dr(r,t),{code:await Ye(m,f,r),plan:o}}finally{d.readyProbe?.abort(),U(t,process.pid),await Je(d)}},pr=e=>({codegen:e.codegen===!1?!1:void 0,studio:e.studio===!1?!1:void 0,worker:e.worker===!1?!1:void 0}),Er=e=>{if(e.local===!0&&e.remote===!0)return"`--local` and `--remote` are mutually exclusive — pass at most one.";const{entries:r,invalid:t}=x(e.allowMail);if(t.length>0)return`\`--allow-mail\` takes email addresses or '*@domain' — not ${t.map(n=>`"${n}"`).join(", ")}.`;if(r.length>0&&e.tunnel!==!0)return"`--allow-mail` only applies to a tunnel — add `--tunnel`."},br=e=>e.tunnel===!0?{allowMail:x(e.allowMail).entries}:void 0,Br=ge(async({argument:e,cwd:r,logger:t,options:n})=>{const a=n.json===!0,i=Fe({cwd:r,json:a,lines:n.lines,logger:t,subcommand:e[0]});if(i!==void 0)return i;const u=process.env[M]==="1",o=u?void 0:W(),d=a||o!==void 0;d&&ve(),o!==void 0&&n.background!==!0&&t.info(`AI agent detected (${o.name} via ${o.variable}) — starting the dev server in background mode with JSON logs. Set LUNORA_AGENT_MODE=0 to opt out.`);const g=Er(n);if(g!==void 0)return t.error(`dev: ${g}`),{code:E.USAGE};const h=br(n),S=n.local===!0?!1:oe({configPreference:B(r),envValue:process.env.LUNORA_REMOTE,flag:n.remote});if(!u&&(n.background===!0||o!==void 0)){const v=j(r);return v!==void 0?(b(t,v),{code:0}):(h?.allowMail.length===0&&xe(t),He({cwd:r,jsonLogs:d,logger:t,options:n,remote:S}))}return yr({apiSpec:ae(n.apiSpec),cwd:r,emitBindings:n.emitBindings,inspectorPort:n.inspectorPort,jsonLogs:d,local:n.local,logger:t,port:n.port,remote:S,target:n.target,tunnel:h,workerPort:n.workerPort,...pr(n)})});export{Er as devFlagConflict,Br as execute,pr as negatableDevFlags,yr as runDevCommand};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{existsSync as m,mkdirSync as M,writeFileSync as w,readFileSync as x,readdirSync as de,rmSync as O,lstatSync as ue,mkdtempSync as pe,copyFileSync as Ye,renameSync as Je}from"node:fs";import{tmpdir as he}from"node:os";import{installArgsFor as me,execArgsFor as Xe,detectFramework as Qe,isInteractive as y,LUNA_ART as Ze,LUNA_NAME as et,LUNA_SIGNOFF as tt,BADGES as v,paintAnswer as rt,detectPackageManager as P,detectInstalledManagers as at,runScriptCommand as ot,detectLintTools as nt,addArgsFor as st,applyLintIgnores as it}from"@lunora/config";import{walkSync as lt}from"@visulima/fs";import{join as p,dirname as A,basename as I,resolve as fe,relative as ge}from"@visulima/path";import{downloadTemplate as ve}from"giget";import{modify as ct,applyEdits as dt}from"jsonc-parser";import{join as K,dirname as ut}from"node:path";import{d as pt}from"../packem_shared/command-CAXl2A1S.mjs";import{EXIT_CODE as f}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import ht from"magic-string";import{Project as mt,SyntaxKind as g}from"ts-morph";import{P as q}from"../packem_shared/prompt-cancelled-BvsNxg_Q.mjs";import{m as we,n as ft,o as ye,q as be,b as gt}from"../packem_shared/resolve-DUCSc7jQ.mjs";import{defaultSpawner as ke}from"../packem_shared/createRecordingSpawner-
|
|
1
|
+
import{existsSync as m,mkdirSync as M,writeFileSync as w,readFileSync as x,readdirSync as de,rmSync as O,lstatSync as ue,mkdtempSync as pe,copyFileSync as Ye,renameSync as Je}from"node:fs";import{tmpdir as he}from"node:os";import{installArgsFor as me,execArgsFor as Xe,detectFramework as Qe,isInteractive as y,LUNA_ART as Ze,LUNA_NAME as et,LUNA_SIGNOFF as tt,BADGES as v,paintAnswer as rt,detectPackageManager as P,detectInstalledManagers as at,runScriptCommand as ot,detectLintTools as nt,addArgsFor as st,applyLintIgnores as it}from"@lunora/config";import{walkSync as lt}from"@visulima/fs";import{join as p,dirname as A,basename as I,resolve as fe,relative as ge}from"@visulima/path";import{downloadTemplate as ve}from"giget";import{modify as ct,applyEdits as dt}from"jsonc-parser";import{join as K,dirname as ut}from"node:path";import{d as pt}from"../packem_shared/command-CAXl2A1S.mjs";import{EXIT_CODE as f}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import ht from"magic-string";import{Project as mt,SyntaxKind as g}from"ts-morph";import{P as q}from"../packem_shared/prompt-cancelled-BvsNxg_Q.mjs";import{m as we,n as ft,o as ye,q as be,b as gt}from"../packem_shared/resolve-DUCSc7jQ.mjs";import{defaultSpawner as ke}from"../packem_shared/createRecordingSpawner-Ch7zuQQE.mjs";import{d as vt,e as wt,f as yt,a as xe,t as G,g as Se,h as bt,b as Ce,i as Le,w as kt,j as xt,k as Me,l as St}from"../packem_shared/tui-prompts-B3YwUhGw.mjs";import{A as Ae,E as Ee,p as Ct,w as Lt,M as Mt,r as At,k as Et,e as Nt,c as Ne,l as Ie,i as It,f as Rt}from"../packem_shared/storage-ChJtQ9E4.mjs";import{r as _t}from"../packem_shared/commands-Cg06JNO2.mjs";import{logStep as Q}from"../packem_shared/createLogger-Cl18I8AX.mjs";import{r as $t}from"../packem_shared/lint-ignore-report-DKZagpqk.mjs";import{DEFAULT_OBSERVABILITY as Ot,CLOUDFLARE_TOOLCHAIN_VERSIONS as Z}from"@lunora/config/cloudflare";import Tt from"node:dns/promises";const Y={bun:{githubCacheKey:void 0,githubSetupStep:` - uses: oven-sh/setup-bun@v2
|
|
2
2
|
`,gitlabImage:"oven/bun:1",gitlabProvisionScript:[],installCmd:"bun install --frozen-lockfile",lockfile:"bun.lockb"},npm:{githubCacheKey:"npm",githubSetupStep:"",gitlabImage:"node:22",gitlabProvisionScript:[],installCmd:"npm ci",lockfile:"package-lock.json"},pnpm:{githubCacheKey:"pnpm",githubSetupStep:` - uses: pnpm/action-setup@v4
|
|
3
3
|
with:
|
|
4
4
|
version: latest
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{spawn as S}from"node:child_process";import{StringDecoder as w}from"node:string_decoder";import{LunoraError as h}from"@lunora/errors";const E=/[\s"%&<>^|]/u,g=e=>{let s="",t=0;for(const r of e)r==="\\"?t+=1:(s+=r==='"'?`${"\\".repeat(t*2+1)}"`:`${"\\".repeat(t)}${r}`,t=0);return s+"\\".repeat(t*2)},C=(e,s,t=process.platform)=>{if(t!=="win32"||e===process.execPath)return{args:[...s],command:e,shell:!1};const r=n=>n===""?'""':E.test(n)?`"${g(n)}"`:n;return{args:s.map(n=>r(n)),command:r(e),shell:!0}},P=e=>new Promise((s,t)=>{const r=typeof e.input=="string",n=e.captureStdout===!0,u=e.captureStdoutSilently===!0;let c="inherit";n||u?c="pipe":e.stdoutToStderr&&(c=2);const i=C(e.command,e.args),a=S(i.command,i.args,{cwd:e.cwd??process.cwd(),env:e.env?{...process.env,...e.env}:process.env,shell:i.shell,stdio:[r?"pipe":"inherit",c,e.captureStderr===!0?"pipe":"inherit"]}),d=new w("utf8"),p=new w("utf8");let l="",f="";e.captureStderr===!0&&a.stderr&&a.stderr.on("data",o=>{f+=p.write(o),process.stderr.write(o)}),(n||u)&&a.stdout&&a.stdout.on("data",o=>{l+=d.write(o),n&&process.stdout.write(o)}),a.on("error",o=>{if(o.code==="ENOENT"){t(new h("LOCAL_DEPENDENCY_MISSING",`\`${e.command}\` is not installed or not on your PATH — nothing was run.`,{cause:o}));return}t(o)}),a.on("exit",(o,m)=>{s({code:o??(m?1:0),stderr:e.captureStderr===!0?f+p.end():void 0,stdout:n||u?l+d.end():void 0})}),r&&a.stdin&&(a.stdin.on("error",()=>{}),a.stdin.end(e.input))}),T=(e=0)=>{const s=[];return{calls:s,spawner:r=>(s.push({descriptor:r}),Promise.resolve({code:e}))}};export{T as createRecordingSpawner,P as defaultSpawner,C as spawnShellCompat};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{existsSync as q,readFileSync as N,mkdirSync as Le,openSync as X,closeSync as Q,statSync as Te,readSync as Pe}from"node:fs";import{join as L,dirname as be}from"node:path";import{readServiceBindings as _e}from"@lunora/codegen";import{readLiveDevServerState as O,discoverContainerInfo as Re,streamContainerLogs as $e,formatLunoraEvent as Ce,updateDevServerState as _,targetRunsOwnDevServer as D,resolveProjectTarget as Z,claimDevServerState as Ne,DEV_HANDOFF_ENV as Oe,clearDevServerState as y,readDevServerState as A,isDevServerReady as V,detectFramework as ee,readProjectDependencyNames as De,DEV_LOG_FILE_ENV as Ae,DEV_DAEMON_ENV as xe,detectPackageManager as x,execArgsFor as re,isRecordedProcessCurrent as Me,DEV_LOG_FILE as Ue,CODEGEN_ENV as te,isCodegenDisabled as Ge,planToolchainInvocation as Fe,toolchainExecArgs as ne,startCelldDevSession as je,resolveDeployDriver as oe,DEV_VARS_FILE as se,runScriptCommand as Ve,parseDevVariableEntries as We}from"@lunora/config";import{warnCloudflareCliConfigOnce as Be,findWranglerFile as T,readWranglerJsonc as M,materializeRemoteWranglerConfig as Ke,materializeServiceDevConfigs as He}from"@lunora/config/cloudflare";import{createServer as ze}from"node:net";import{networkInterfaces as Ye}from"node:os";import{spawn as ie,spawnSync as P}from"node:child_process";import{setTimeout as w}from"node:timers/promises";import{EXIT_CODE as ae}from"./EXIT_CODE-D_XCixv8.mjs";import{a as h}from"./output-format-B4eQHi5y.mjs";import{spawnShellCompat as ce,defaultSpawner as Je}from"./createRecordingSpawner-CYhdPBD5.mjs";import{isLunoraError as qe}from"@lunora/errors";import{s as W}from"./index-oHZBGBwB.mjs";import{createInterface as Xe}from"node:readline";const Qe=12e4,R=250,Ze=1e3,er="LUNORA_DEV_READY_TIMEOUT_MS",rr=e=>{if(e!==void 0)return e;const r=Number(process.env[er]??"");return Number.isFinite(r)&&r>0?r:Qe},tr=async(e,r)=>{try{const n=AbortSignal.timeout(Ze);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}},le=async(e,r,n)=>{const t=Date.now()+n.timeoutMs;for(;n.signal?.aborted!==!0;){const o=r(O(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}}},B=(e,r)=>{Xe({crlfDelay:Number.POSITIVE_INFINITY,input:e}).on("line",r)},nr=5e3,de=(e,r,n,t)=>{if(e.length===0)return;const o=Ce(e);if(o){t[o.level](`[lunora] ${o.text}`);return}const s=`[${r}] ${e}`;n==="stderr"?t.warn(s):t.info(s)},or=(e,r,n=process.platform,t=P)=>{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{}},ue=(e,r,n)=>{const t=e.direct===!0?{args:[...e.args],command:e.command,shell:!1}:ce(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 B(o.stdout,s=>{r(s,"stdout")}),B(o.stderr,s=>{r(s,"stderr")}),{exited:new Promise(s=>{o.on("error",i=>{n?.(i),s(1)}),o.on("exit",(i,a)=>{s(i??(a?1:0))})}),kill:s=>{or(o,s)}}},vt=(e,r)=>ue(e,(n,t)=>{de(n.trimEnd(),e.tag,t,r)},n=>{r.error(`[${e.tag}] failed to start: ${n.message}`)}),gt=(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 $e({containers:t,onLine:o=>{const s=`[container:${o.name}] ${o.text}`;o.level==="error"?r.warn(s):r.info(s)},onUnavailable:o=>{r.warn(`[container] Docker engine unreachable — container logs unavailable (${o})`)}})},pt=async e=>{e.readyProbe?.abort(),await e.tunnel?.close(),await e.codegen?.close().catch(()=>{}),e.containerLogs?.close(),await e.studio?.close().catch(()=>{});try{e.remoteCleanup?.(),e.serviceConfigCleanup?.()}catch{}},mt=async e=>await new Promise(r=>{const n={},t=i=>{e.info(`received ${i} — shutting down`),n.sigint&&process.off("SIGINT",n.sigint),n.sigterm&&process.off("SIGTERM",n.sigterm),r(0)},o=()=>{t("SIGINT")},s=()=>{t("SIGTERM")};n.sigint=o,n.sigterm=s,process.on("SIGINT",o),process.on("SIGTERM",s)}),wt=async(e,r,n)=>{let t=0,o;const s=l=>{e.kill(l),r?.kill(l)},i=()=>{t+=1,t===1?(n.info("received SIGINT — shutting down (press Ctrl-C again to force-kill)"),s("SIGTERM"),o=setTimeout(()=>{s("SIGKILL")},nr),o.unref()):s("SIGKILL")},a=()=>{s("SIGTERM")};process.on("SIGINT",i),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",i),process.off("SIGTERM",a),c.code},E="2026.9.3",sr="https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/downloads/",ir=/version (\S+)/u,K=/https:\/\/[\da-z-]+\.trycloudflare\.com/u,ar="1s",cr=5e3,H=async(e,r)=>await Promise.race([e.then(()=>!0),w(r,!1,{ref:!1})]),lr=6e4,dr='Vite answers 403 for hosts it does not know — add `server: { allowedHosts: [".trycloudflare.com"] }` to vite.config if the URL is blocked.',ur=async e=>{const r=`Install or update it: ${sr} (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 qe(o)&&o.code==="LOCAL_DEPENDENCY_MISSING"?{message:`--tunnel needs \`cloudflared\` ${E} 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=W.coerce(ir.exec(n)?.[1])?.version;return t===void 0?{ok:!0,version:void 0}:W.gte(t,E)?{ok:!0,version:t}:{message:`--tunnel needs \`cloudflared\` ${E} or newer (protected quick tunnels); found ${t}. ${r}`,ok:!1}},fr=e=>{const r=[],n=[];for(const t of e??[]){const o=t.split(",").map(s=>s.trim()).filter(s=>s.length>0);o.length>0&&(n.push(...o.filter(s=>!s.includes("@"))),r.push(o.join(",")))}return{entries:r,invalid:n}},vr=(e,r)=>["tunnel","--url",e,"--output","json","--grace-period",ar,...r.flatMap(n=>["--allowed-mail",n])],gr=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:K.exec(t)?.[0]}}return{level:void 0,text:e,url:K.exec(e)?.[0]}},pr=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')")},mr=async(e,r,n,{intervalMs:t,timeoutMs:o=lr}={})=>{const s=await le(e,i=>i?.mode==="vite"?{origin:i.url,ownerPid:i.pid}:void 0,{intervalMs:t,signal:n,timeoutMs:o});return s===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.`),s},wr=e=>{const{allowMail:r,cwd:n,logger:t}=e,o=r.length===0,s=new AbortController,{signal:i}=s,a=()=>i.aborted,c=e.closeTimeoutMs??cr;let l;const d=()=>{s.abort()};process.once("SIGINT",d),process.once("SIGTERM",d);const v=(async()=>{const u=await ur(e.spawner??Je);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 ${E} or newer; trying anyway.`);const g=e.origin.kind==="fixed"?{origin:e.origin.origin,ownerPid:process.pid}:await mr(n,t,i);if(g===void 0||i.aborted)return;o&&pr(t),t.info(`starting a Cloudflare quick tunnel to ${g.origin}${o?"":" (email one-time-PIN protected)"}…`);let S;const G={failedToStart:!1},ye=k=>{if(k.length===0)return;const p=gr(k);if(p.url!==void 0&&S===void 0){S=p.url,t.success(` ➜ Tunnel: ${p.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(` ${dr}`),_(n,{tunnelUrl:p.url},{expectedPid:g.ownerPid});return}p.level==="error"||p.level==="fatal"?t.warn(`[cloudflared] ${p.text}`):t.debug?.(`[cloudflared] ${p.text}`)},b=(e.startChild??ue)({args:vr(g.origin,r),command:"cloudflared",direct:!0},ye,k=>{G.failedToStart=!0,t.error(`could not start cloudflared (${k.message}) — continuing without a tunnel.`)});l=b;const F=()=>{b.kill("SIGTERM")};i.addEventListener("abort",F,{once:!0});const j=await b.exited;i.removeEventListener("abort",F),l=void 0,S!==void 0&&_(n,{tunnelUrl:void 0},{expectedPid:g.ownerPid}),!(a()||G.failedToStart)&&t.warn(S===void 0?`cloudflared exited (${String(j)}) before a tunnel URL was assigned — continuing without a tunnel.`:`cloudflared exited (${String(j)}) — 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),s.abort(),await H(v,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 H(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.`))}}},ht=e=>{const{cwd:r,logger:n,plan:t,tunnel:o}=e;if(o!==void 0)return wr({allowMail:o.allowMail,cwd:r,logger:n,origin:t.flavor==="wrangler"?{kind:"fixed",origin:t.workerOrigin}:{kind:"vite"},spawner:o.spawner,startChild:o.startChild})},hr=(e,r)=>{const n=["dev"];if(e.apiSpec!==void 0&&n.push("--api-spec",e.apiSpec),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 fr(e.allowMail).entries)n.push("--allow-mail",t)}return r&&n.push("--remote"),e.local===!0&&n.push("--local"),n},Sr=1e4,kr=100,Ir=40,I=256*1024,Er=new Set(["nuxt","sveltekit"]),yr=["@lunora/rspack","@lunora/vite"],U=e=>{if(Er.has(ee(e).framework))return"framework-worker";const r=De(e);return yr.some(n=>r.has(n))?"vite":"wrangler"},fe=e=>{const r=x(e);let n;try{const t=N(L(e,"package.json"),"utf8");n=JSON.parse(t).scripts?.dev}catch{}if(n===void 0||n.trim()===""||n.includes("lunora")){const t=re(r,"vite",["dev"]);return{args:t.args,command:t.command}}return{args:["run","dev"],command:r}},Lr=e=>{Le(be(e.logPath),{recursive:!0});const r=X(e.logPath,"w",384);let n;const t=ce(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{Q(r)}return n.unref(),{exited:new Promise(o=>{n.on("error",()=>{o(1)}),n.on("exit",(s,i)=>{o(s??(i?1:0))})}),pid:n.pid}},Tr=e=>{try{const{size:r}=Te(e);if(r<=I)return N(e,"utf8");const n=X(e,"r");try{const t=Buffer.alloc(I),o=Pe(n,t,0,I,r-I),s=t.toString("utf8",0,o);return s.slice(s.indexOf(`
|
|
1
|
+
import{existsSync as q,readFileSync as N,mkdirSync as Le,openSync as X,closeSync as Q,statSync as Te,readSync as Pe}from"node:fs";import{join as L,dirname as be}from"node:path";import{readServiceBindings as _e}from"@lunora/codegen";import{readLiveDevServerState as O,discoverContainerInfo as Re,streamContainerLogs as $e,formatLunoraEvent as Ce,updateDevServerState as _,targetRunsOwnDevServer as D,resolveProjectTarget as Z,claimDevServerState as Ne,DEV_HANDOFF_ENV as Oe,clearDevServerState as y,readDevServerState as A,isDevServerReady as V,detectFramework as ee,readProjectDependencyNames as De,DEV_LOG_FILE_ENV as Ae,DEV_DAEMON_ENV as xe,detectPackageManager as x,execArgsFor as re,isRecordedProcessCurrent as Me,DEV_LOG_FILE as Ue,CODEGEN_ENV as te,isCodegenDisabled as Ge,planToolchainInvocation as Fe,toolchainExecArgs as ne,startCelldDevSession as je,resolveDeployDriver as oe,DEV_VARS_FILE as se,runScriptCommand as Ve,parseDevVariableEntries as We}from"@lunora/config";import{warnCloudflareCliConfigOnce as Be,findWranglerFile as T,readWranglerJsonc as M,materializeRemoteWranglerConfig as Ke,materializeServiceDevConfigs as He}from"@lunora/config/cloudflare";import{createServer as ze}from"node:net";import{networkInterfaces as Ye}from"node:os";import{spawn as ie,spawnSync as P}from"node:child_process";import{setTimeout as w}from"node:timers/promises";import{EXIT_CODE as ae}from"./EXIT_CODE-D_XCixv8.mjs";import{a as h}from"./output-format-B4eQHi5y.mjs";import{spawnShellCompat as ce,defaultSpawner as Je}from"./createRecordingSpawner-Ch7zuQQE.mjs";import{isLunoraError as qe}from"@lunora/errors";import{s as W}from"./index-oHZBGBwB.mjs";import{createInterface as Xe}from"node:readline";const Qe=12e4,R=250,Ze=1e3,er="LUNORA_DEV_READY_TIMEOUT_MS",rr=e=>{if(e!==void 0)return e;const r=Number(process.env[er]??"");return Number.isFinite(r)&&r>0?r:Qe},tr=async(e,r)=>{try{const n=AbortSignal.timeout(Ze);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}},le=async(e,r,n)=>{const t=Date.now()+n.timeoutMs;for(;n.signal?.aborted!==!0;){const o=r(O(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}}},B=(e,r)=>{Xe({crlfDelay:Number.POSITIVE_INFINITY,input:e}).on("line",r)},nr=5e3,de=(e,r,n,t)=>{if(e.length===0)return;const o=Ce(e);if(o){t[o.level](`[lunora] ${o.text}`);return}const s=`[${r}] ${e}`;n==="stderr"?t.warn(s):t.info(s)},or=(e,r,n=process.platform,t=P)=>{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{}},ue=(e,r,n)=>{const t=e.direct===!0?{args:[...e.args],command:e.command,shell:!1}:ce(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 B(o.stdout,s=>{r(s,"stdout")}),B(o.stderr,s=>{r(s,"stderr")}),{exited:new Promise(s=>{o.on("error",i=>{n?.(i),s(1)}),o.on("exit",(i,a)=>{s(i??(a?1:0))})}),kill:s=>{or(o,s)}}},vt=(e,r)=>ue(e,(n,t)=>{de(n.trimEnd(),e.tag,t,r)},n=>{r.error(`[${e.tag}] failed to start: ${n.message}`)}),gt=(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 $e({containers:t,onLine:o=>{const s=`[container:${o.name}] ${o.text}`;o.level==="error"?r.warn(s):r.info(s)},onUnavailable:o=>{r.warn(`[container] Docker engine unreachable — container logs unavailable (${o})`)}})},pt=async e=>{e.readyProbe?.abort(),await e.tunnel?.close(),await e.codegen?.close().catch(()=>{}),e.containerLogs?.close(),await e.studio?.close().catch(()=>{});try{e.remoteCleanup?.(),e.serviceConfigCleanup?.()}catch{}},mt=async e=>await new Promise(r=>{const n={},t=i=>{e.info(`received ${i} — shutting down`),n.sigint&&process.off("SIGINT",n.sigint),n.sigterm&&process.off("SIGTERM",n.sigterm),r(0)},o=()=>{t("SIGINT")},s=()=>{t("SIGTERM")};n.sigint=o,n.sigterm=s,process.on("SIGINT",o),process.on("SIGTERM",s)}),wt=async(e,r,n)=>{let t=0,o;const s=l=>{e.kill(l),r?.kill(l)},i=()=>{t+=1,t===1?(n.info("received SIGINT — shutting down (press Ctrl-C again to force-kill)"),s("SIGTERM"),o=setTimeout(()=>{s("SIGKILL")},nr),o.unref()):s("SIGKILL")},a=()=>{s("SIGTERM")};process.on("SIGINT",i),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",i),process.off("SIGTERM",a),c.code},E="2026.9.3",sr="https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/downloads/",ir=/version (\S+)/u,K=/https:\/\/[\da-z-]+\.trycloudflare\.com/u,ar="1s",cr=5e3,H=async(e,r)=>await Promise.race([e.then(()=>!0),w(r,!1,{ref:!1})]),lr=6e4,dr='Vite answers 403 for hosts it does not know — add `server: { allowedHosts: [".trycloudflare.com"] }` to vite.config if the URL is blocked.',ur=async e=>{const r=`Install or update it: ${sr} (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 qe(o)&&o.code==="LOCAL_DEPENDENCY_MISSING"?{message:`--tunnel needs \`cloudflared\` ${E} 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=W.coerce(ir.exec(n)?.[1])?.version;return t===void 0?{ok:!0,version:void 0}:W.gte(t,E)?{ok:!0,version:t}:{message:`--tunnel needs \`cloudflared\` ${E} or newer (protected quick tunnels); found ${t}. ${r}`,ok:!1}},fr=e=>{const r=[],n=[];for(const t of e??[]){const o=t.split(",").map(s=>s.trim()).filter(s=>s.length>0);o.length>0&&(n.push(...o.filter(s=>!s.includes("@"))),r.push(o.join(",")))}return{entries:r,invalid:n}},vr=(e,r)=>["tunnel","--url",e,"--output","json","--grace-period",ar,...r.flatMap(n=>["--allowed-mail",n])],gr=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:K.exec(t)?.[0]}}return{level:void 0,text:e,url:K.exec(e)?.[0]}},pr=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')")},mr=async(e,r,n,{intervalMs:t,timeoutMs:o=lr}={})=>{const s=await le(e,i=>i?.mode==="vite"?{origin:i.url,ownerPid:i.pid}:void 0,{intervalMs:t,signal:n,timeoutMs:o});return s===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.`),s},wr=e=>{const{allowMail:r,cwd:n,logger:t}=e,o=r.length===0,s=new AbortController,{signal:i}=s,a=()=>i.aborted,c=e.closeTimeoutMs??cr;let l;const d=()=>{s.abort()};process.once("SIGINT",d),process.once("SIGTERM",d);const v=(async()=>{const u=await ur(e.spawner??Je);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 ${E} or newer; trying anyway.`);const g=e.origin.kind==="fixed"?{origin:e.origin.origin,ownerPid:process.pid}:await mr(n,t,i);if(g===void 0||i.aborted)return;o&&pr(t),t.info(`starting a Cloudflare quick tunnel to ${g.origin}${o?"":" (email one-time-PIN protected)"}…`);let S;const G={failedToStart:!1},ye=k=>{if(k.length===0)return;const p=gr(k);if(p.url!==void 0&&S===void 0){S=p.url,t.success(` ➜ Tunnel: ${p.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(` ${dr}`),_(n,{tunnelUrl:p.url},{expectedPid:g.ownerPid});return}p.level==="error"||p.level==="fatal"?t.warn(`[cloudflared] ${p.text}`):t.debug?.(`[cloudflared] ${p.text}`)},b=(e.startChild??ue)({args:vr(g.origin,r),command:"cloudflared",direct:!0},ye,k=>{G.failedToStart=!0,t.error(`could not start cloudflared (${k.message}) — continuing without a tunnel.`)});l=b;const F=()=>{b.kill("SIGTERM")};i.addEventListener("abort",F,{once:!0});const j=await b.exited;i.removeEventListener("abort",F),l=void 0,S!==void 0&&_(n,{tunnelUrl:void 0},{expectedPid:g.ownerPid}),!(a()||G.failedToStart)&&t.warn(S===void 0?`cloudflared exited (${String(j)}) before a tunnel URL was assigned — continuing without a tunnel.`:`cloudflared exited (${String(j)}) — 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),s.abort(),await H(v,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 H(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.`))}}},ht=e=>{const{cwd:r,logger:n,plan:t,tunnel:o}=e;if(o!==void 0)return wr({allowMail:o.allowMail,cwd:r,logger:n,origin:t.flavor==="wrangler"?{kind:"fixed",origin:t.workerOrigin}:{kind:"vite"},spawner:o.spawner,startChild:o.startChild})},hr=(e,r)=>{const n=["dev"];if(e.apiSpec!==void 0&&n.push("--api-spec",e.apiSpec),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 fr(e.allowMail).entries)n.push("--allow-mail",t)}return r&&n.push("--remote"),e.local===!0&&n.push("--local"),n},Sr=1e4,kr=100,Ir=40,I=256*1024,Er=new Set(["nuxt","sveltekit"]),yr=["@lunora/rspack","@lunora/vite"],U=e=>{if(Er.has(ee(e).framework))return"framework-worker";const r=De(e);return yr.some(n=>r.has(n))?"vite":"wrangler"},fe=e=>{const r=x(e);let n;try{const t=N(L(e,"package.json"),"utf8");n=JSON.parse(t).scripts?.dev}catch{}if(n===void 0||n.trim()===""||n.includes("lunora")){const t=re(r,"vite",["dev"]);return{args:t.args,command:t.command}}return{args:["run","dev"],command:r}},Lr=e=>{Le(be(e.logPath),{recursive:!0});const r=X(e.logPath,"w",384);let n;const t=ce(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{Q(r)}return n.unref(),{exited:new Promise(o=>{n.on("error",()=>{o(1)}),n.on("exit",(s,i)=>{o(s??(i?1:0))})}),pid:n.pid}},Tr=e=>{try{const{size:r}=Te(e);if(r<=I)return N(e,"utf8");const n=X(e,"r");try{const t=Buffer.alloc(I),o=Pe(n,t,0,I,r-I),s=t.toString("utf8",0,o);return s.slice(s.indexOf(`
|
|
2
2
|
`)+1)}finally{Q(n)}}catch{return}},ve=(e,r)=>{const n=Tr(e);if(n===void 0)return[];const t=n.split(`
|
|
3
3
|
`);return t.at(-1)===""&&t.pop(),r>0?t.slice(-r):t},ge=(e,r)=>r?.logFile??L(e,Ue),pe=e=>{e.info(" Stop: lunora dev stop"),e.info(" Status: lunora dev status"),e.info(" Logs: lunora dev logs")},Pr=(e,r)=>{Be(r,n=>{e.warn(n)})},br=(e,r)=>{e.warn(`Dev server already running at ${r.url} (pid ${String(r.pid)})`),pe(e)},_r=(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}`),pe(e)},Rr=3e4,$r=async(e,r,n,t)=>{const o=await le(e,s=>s?.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}`)},Cr=async e=>{const{child:r,cwd:n,deadline:t,pollIntervalMs:o,probe:s}=e,i=r.exited.then(a=>({exitCode:a}));for(;Date.now()<t;){const a=O(n);if(a!==void 0&&a.pid!==process.pid&&await s(a.url))return{state:a,status:"ready"};const c=await Promise.race([i,w(o)]);if(c!==void 0)return{...c,status:"exited"}}return{status:"timeout"}},Nr=async e=>{const{cwd:r,logger:n}=e,t=ge(r,void 0),o=rr(e.readyTimeoutMs),s=(e.spawnDetached??Lr)({args:e.command.args,command:e.command.command,cwd:r,env:{...process.env,...e.env,[xe]:"1",[Ae]:t,...process.env.FORCE_COLOR===void 0?{NO_COLOR:"1"}:{},...e.json?{LUNORA_LOG_JSON:"1"}:{}},logPath:t}),i=await Cr({child:s,cwd:r,deadline:Date.now()+o,pollIntervalMs:e.pollIntervalMs??R,probe:e.probe??tr});if(i.status==="ready")return _r(n,i.state),e.tunnel===!0&&i.state.tunnelUrl===void 0&&await $r(r,n,e.pollIntervalMs??R,e.tunnelUrlTimeoutMs??Rr),{code:0};if(i.status==="exited"){n.error(`dev server exited before becoming ready (exit code ${String(i.exitCode)}). Last output:`);for(const c of ve(t,Ir))n.error(` ${c}`);return y(r,s.pid??process.pid),{code:i.exitCode===0?1:i.exitCode}}s.pid!==void 0&&A(r)?.pid===process.pid&&_(r,{logFile:t,pid:s.pid});const a=s.pid===void 0?"":` (pid ${String(s.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:ae.UNAVAILABLE}},me=e=>e.codegen!==!1&&!Ge(process.env[te]),we=e=>{const r={...e.remote===!0?{LUNORA_REMOTE:"1"}:{},...e.codegen===!1?{[te]:"0"}:{}};return Object.keys(r).length>0?{env:r}:{}},St=async e=>{const{cwd:r,jsonLogs:n,logger:t,options:o,remote:s}=e,i=e.run??Nr,a=U(r),c=a==="vite"&&D(o.target??Z(r))?"wrangler":a,l=c==="wrangler"?`http://localhost:${String(o.workerPort??8787)}`:"http://localhost:5173",d=Ne(r,{background:!0,mode:"cli",pid:process.pid,startedAt:new Date().toISOString(),url:l});if(!d.ok)return d.existing!==void 0&&br(t,d.existing),{code:0};const f={[Oe]:String(process.pid)};Pr(t,r);try{return c==="vite"&&o.tunnel!==!0?await i({command:fe(r),cwd:r,env:{...we({...o,remote:s}).env,...f},json:n,logger:t}):await i({command:{args:[process.argv[1]??"lunora",...hr(o,s)],command:process.execPath},cwd:r,env:f,json:n,logger:t,tunnel:o.tunnel===!0})}finally{y(r,process.pid)}},Or=e=>{try{const r=P("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}},Dr=(e,r,n=process.platform,t=P)=>{if(n==="win32"){try{t("taskkill",["/pid",String(e.pid),"/T","/F"],{stdio:"ignore"})}catch{}return}if(e.background===!0)try{r(-(Or(e.pid)??e.pid),"SIGKILL");return}catch{}try{r(e.pid,"SIGKILL")}catch{}},Ar=(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}),xr=async e=>{const{cwd:r,logger:n}=e,t=A(r),o=e.alive??(f=>f===t?.pid&&Me(t)),s=e.signal??((f,v)=>{process.kill(f,v)}),i=e.pollIntervalMs??R,a=e.stopGraceMs??Sr,c=e.platform??process.platform,l=e.spawnSyncImpl??P;if(t===void 0||!o(t.pid))return t!==void 0&&y(r,t.pid),e.json?h({running:!1,stopped:!1}):n.info("No dev server running."),{code:0};try{s(t.pid,"SIGTERM")}catch{}const d=Date.now()+a;for(;o(t.pid)&&Date.now()<d;)await w(i);return o(t.pid)&&(Dr(t,s,c,l),await w(i),o(t.pid))?Ar(t,e):(y(r,t.pid),e.json?h({pid:t.pid,stopped:!0}):n.success(`Stopped dev server (pid ${String(t.pid)}).`),{code:0})},Mr=e=>{const{cwd:r,logger:n}=e,t=O(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,s=t.startedAt===void 0?Number.NaN:Date.parse(t.startedAt),i=Number.isFinite(s)?Math.max(0,Math.round((o()-s)/1e3)):void 0;if(e.json)return h({background:t.background===!0,logFile:t.logFile,mode:t.mode,pid:t.pid,ready:V(t),readyAt:t.readyAt,running:!0,startedAt:t.startedAt,studioUrl:t.studioUrl,tunnelUrl:t.tunnelUrl,uptimeSeconds:i,url:t.url}),{code:0};const a=[`pid ${String(t.pid)}`,...i===void 0?[]:[`uptime ${String(i)}s`],t.background===!0?"background":"foreground",V(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}},Ur=e=>{const{cwd:r,logger:n}=e,t=A(r),o=ge(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 s=ve(o,e.lines??kr);return s.length>0&&process.stdout.write(`${s.join(`
|
|
4
4
|
`)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as r,p as a,q as s,u as l}from"./plan-
|
|
1
|
+
import{g as r,p as a,q as s,u as l}from"./plan-Cod9Cgll.mjs";export{r as buildDevPlan,a as planDevCommand,s as resolveInspectorPort,l as resolveWorkerPort};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{resolveDeployDriver as c,resolveProjectTarget as d,toolchainExecArgs as l,detectPackageManager as i}from"@lunora/config";import{defaultSpawner as u}from"./createRecordingSpawner-
|
|
1
|
+
import{resolveDeployDriver as c,resolveProjectTarget as d,toolchainExecArgs as l,detectPackageManager as i}from"@lunora/config";import{defaultSpawner as u}from"./createRecordingSpawner-Ch7zuQQE.mjs";const m=async(e,t,o)=>{try{const r=await u({args:t,captureStderr:!0,captureStdoutSilently:!0,command:e,cwd:o});return{code:r.code,stderr:r.stderr??"",stdout:r.stdout??""}}catch(r){return{code:1,stderr:r instanceof Error?r.message:String(r),stdout:""}}},f=e=>{let t;try{t=JSON.parse(e)}catch{return}return Array.isArray(t)?[...t.map(r=>r!==null&&typeof r=="object"?r.name:void 0).filter(r=>typeof r=="string"&&r.length>0)].toSorted((r,a)=>r.localeCompare(a)):void 0},y=async e=>{const t=c(d(e.cwd)),o=t.toolchain?.secretList?.({environment:e.env,temporary:e.temporary});if(o===void 0)return{error:`deploy target "${t.id}" has no secret store to list`,names:[],ok:!1};const{args:r,command:a}=l(i(e.cwd),o),s=await(e.runner??m)(a,r,e.cwd);if(s.code!==0)return{error:s.stderr.trim()||`wrangler secret list exited ${String(s.code)}`,names:[],ok:!1};const n=f(s.stdout);return n===void 0?{error:"could not parse `wrangler secret list --format json` output",names:[],ok:!1}:{names:n,ok:!0}};export{y as l};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/cli",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.350",
|
|
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",
|
|
@@ -52,32 +52,32 @@
|
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@bomb.sh/tab": "0.0.22",
|
|
55
|
-
"@lunora/advisor": "1.0.0-alpha.
|
|
55
|
+
"@lunora/advisor": "1.0.0-alpha.190",
|
|
56
56
|
"@lunora/bindings": "1.0.0-alpha.96",
|
|
57
|
-
"@lunora/codegen": "1.0.0-alpha.
|
|
58
|
-
"@lunora/config": "1.0.0-alpha.
|
|
57
|
+
"@lunora/codegen": "1.0.0-alpha.265",
|
|
58
|
+
"@lunora/config": "1.0.0-alpha.308",
|
|
59
59
|
"@lunora/container": "1.0.0-alpha.69",
|
|
60
|
-
"@lunora/d1": "1.0.0-alpha.
|
|
60
|
+
"@lunora/d1": "1.0.0-alpha.163",
|
|
61
61
|
"@lunora/errors": "1.0.0-alpha.50",
|
|
62
|
-
"@lunora/mcp": "1.0.0-alpha.
|
|
63
|
-
"@lunora/runtime": "1.0.0-alpha.
|
|
64
|
-
"@lunora/seed": "1.0.0-alpha.
|
|
62
|
+
"@lunora/mcp": "1.0.0-alpha.215",
|
|
63
|
+
"@lunora/runtime": "1.0.0-alpha.177",
|
|
64
|
+
"@lunora/seed": "1.0.0-alpha.193",
|
|
65
65
|
"@visulima/cerebro": "3.1.2",
|
|
66
66
|
"@visulima/error": "6.1.0",
|
|
67
|
-
"@visulima/fs": "6.0.
|
|
67
|
+
"@visulima/fs": "6.0.28",
|
|
68
68
|
"@visulima/pail": "5.0.0",
|
|
69
69
|
"@visulima/path": "4.0.0",
|
|
70
70
|
"@visulima/spinner": "1.0.1",
|
|
71
|
-
"@visulima/tui": "4.0.
|
|
72
|
-
"@visulima/tui-kit": "1.0.
|
|
71
|
+
"@visulima/tui": "4.0.28",
|
|
72
|
+
"@visulima/tui-kit": "1.0.31",
|
|
73
73
|
"adm-zip": "0.6.1",
|
|
74
|
-
"csv-parse": "7.0.
|
|
74
|
+
"csv-parse": "7.0.3",
|
|
75
75
|
"giget": "3.3.1",
|
|
76
76
|
"jsonc-parser": "^3.3.1",
|
|
77
|
-
"magic-string": "^1.2
|
|
78
|
-
"react": "^19.
|
|
77
|
+
"magic-string": "^1.4.2",
|
|
78
|
+
"react": "^19.3.0",
|
|
79
79
|
"react-reconciler": "^0.33.0",
|
|
80
|
-
"smol-toml": "1.
|
|
80
|
+
"smol-toml": "1.9.0",
|
|
81
81
|
"ts-morph": "^28.0.0"
|
|
82
82
|
},
|
|
83
83
|
"peerDependencies": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{spawn as m}from"node:child_process";import{StringDecoder as S}from"node:string_decoder";import{LunoraError as E}from"@lunora/errors";const h=/[\s"%&<>^|]/u,N=/(\\*)"/gu,g=/(\\+)$/u,_=(t,s,u=process.platform)=>{if(u!=="win32"||t===process.execPath)return{args:[...s],command:t,shell:!1};const o=e=>e===""?'""':h.test(e)?`"${e.replaceAll(N,String.raw`$1$1\"`).replace(g,"$1$1")}"`:e;return{args:s.map(e=>o(e)),command:o(t),shell:!0}},$=t=>new Promise((s,u)=>{const o=typeof t.input=="string",e=t.captureStdout===!0,a=t.captureStdoutSilently===!0;let c="inherit";e||a?c="pipe":t.stdoutToStderr&&(c=2);const d=_(t.command,t.args),n=m(d.command,d.args,{cwd:t.cwd??process.cwd(),env:t.env?{...process.env,...t.env}:process.env,shell:d.shell,stdio:[o?"pipe":"inherit",c,t.captureStderr===!0?"pipe":"inherit"]}),i=new S("utf8"),p=new S("utf8");let l="",w="";t.captureStderr===!0&&n.stderr&&n.stderr.on("data",r=>{w+=p.write(r),process.stderr.write(r)}),(e||a)&&n.stdout&&n.stdout.on("data",r=>{l+=i.write(r),e&&process.stdout.write(r)}),n.on("error",r=>{if(r.code==="ENOENT"){u(new E("LOCAL_DEPENDENCY_MISSING",`\`${t.command}\` is not installed or not on your PATH — nothing was run.`,{cause:r}));return}u(r)}),n.on("exit",(r,f)=>{s({code:r??(f?1:0),stderr:t.captureStderr===!0?w+p.end():void 0,stdout:e||a?l+i.end():void 0})}),o&&n.stdin&&(n.stdin.on("error",()=>{}),n.stdin.end(t.input))}),I=(t=0)=>{const s=[];return{calls:s,spawner:o=>(s.push({descriptor:o}),Promise.resolve({code:t}))}};export{I as createRecordingSpawner,$ as defaultSpawner,_ as spawnShellCompat};
|