@lunora/cli 1.0.0-alpha.315 → 1.0.0-alpha.317
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/dispatch.mjs +1 -1
- package/dist/packem_chunks/runDeployCommand.mjs +1 -1
- package/dist/packem_shared/diffSnapshots-WWwx-KvZ.mjs +5 -0
- package/dist/packem_shared/{runMigrateGenerateCommand-BfBHaTLi.mjs → runMigrateGenerateCommand-CDHswpMU.mjs} +1 -1
- package/dist/packem_shared/schemaIrToSnapshot-BjK-0IRo.mjs +1 -0
- package/package.json +11 -11
- package/dist/packem_shared/diffSnapshots-DtC5Cs4Z.mjs +0 -5
- package/dist/packem_shared/schemaIrToSnapshot-irmd5g0Y.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-DOpChqUe.mjs";import{runCodegenCommand as m}from"./packem_chunks/runCodegenCommand.mjs";import{runDeployCommand as p}from"./packem_chunks/runDeployCommand.mjs";import{planDevCommand as C,runDevCommand as f}from"./packem_chunks/planDevCommand.mjs";import{runInitCommand as s}from"./packem_chunks/runInitCommand.mjs";import{runMigrateGenerateCommand as u}from"./packem_shared/runMigrateGenerateCommand-
|
|
1
|
+
import{C as o,V as a,r as n}from"./packem_shared/cli-DOpChqUe.mjs";import{runCodegenCommand as m}from"./packem_chunks/runCodegenCommand.mjs";import{runDeployCommand as p}from"./packem_chunks/runDeployCommand.mjs";import{planDevCommand as C,runDevCommand as f}from"./packem_chunks/planDevCommand.mjs";import{runInitCommand as s}from"./packem_chunks/runInitCommand.mjs";import{runMigrateGenerateCommand as u}from"./packem_shared/runMigrateGenerateCommand-CDHswpMU.mjs";import{runResetCommand as E}from"./packem_chunks/runResetCommand.mjs";import{runRpcCommand as D}from"./packem_chunks/runRpcCommand.mjs";import{EXIT_CODE as R,exitCodeForCode as S,exitCodeForError as A,exitCodeForStatus as c}from"./packem_shared/EXIT_CODE-08cwt3MK.mjs";import{insertSchemaExtension as _}from"./packem_shared/insertSchemaExtension-DuiV6cba.mjs";import{createLogger as F,pail as b}from"./packem_shared/createLogger-Cl18I8AX.mjs";import{diffSnapshots as h,renderAddColumn as y,renderCreateIndex as L,renderCreateTable as w,renderDropIndex as B,renderDropTable as P,renderMigrationFile as U,validatorKindToSqlType as V}from"./packem_shared/diffSnapshots-WWwx-KvZ.mjs";import{default as G}from"./packem_shared/schemaIrToSnapshot-BjK-0IRo.mjs";import{createRecordingSpawner as Q,defaultSpawner as j}from"./packem_shared/createRecordingSpawner-sS7LEN7x.mjs";import{default as H}from"./packem_shared/parseManifest-CwPTKdtS.mjs";import{D as X,r as Y}from"./packem_shared/import-D7qdpSmJ.mjs";import{REQUIRED_COMPATIBILITY_DATE as k,REQUIRED_FLAG as z,validateWranglerProject as J,validateWranglerConfig as $}from"@lunora/config/cloudflare";import{b as er}from"./packem_shared/catalog-Cbzph90w.mjs";import{r as ar,a as nr,b as tr}from"./packem_shared/commands-CdVObzRk.mjs";import{runExportCommand as dr}from"./packem_shared/runExportCommand-DxsJHYZt.mjs";export{o as COMMANDS,X as DEFAULT_IMPORT_BATCH_SIZE,R as EXIT_CODE,k as REQUIRED_COMPATIBILITY_DATE,z as REQUIRED_FLAG,a as VERSION,er as buildRegistryIndex,F as createLogger,Q as createRecordingSpawner,j as defaultSpawner,h as diffSnapshots,S as exitCodeForCode,A as exitCodeForError,c as exitCodeForStatus,_ as insertSchemaExtension,b as pail,H as parseManifest,C as planDevCommand,y as renderAddColumn,L as renderCreateIndex,w as renderCreateTable,B as renderDropIndex,P as renderDropTable,U as renderMigrationFile,ar as runAddCommand,nr as runBuildIndexCommand,n as runCli,m as runCodegenCommand,p as runDeployCommand,f as runDevCommand,dr as runExportCommand,Y as runImportCommand,s as runInitCommand,u as runMigrateGenerateCommand,tr as runRegistryViewCommand,E as runResetCommand,D as runRpcCommand,G as schemaIrToSnapshot,J as validateWrangler,$ as validateWranglerConfig,V as validatorKindToSqlType};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{d as u}from"../packem_shared/command-Mmxzxyr5.mjs";import{EXIT_CODE as c}from"../packem_shared/EXIT_CODE-08cwt3MK.mjs";import{a as m}from"../packem_shared/resolve-target-C_ZloTvd.mjs";import{runMigrateGenerateCommand as l,runMigrateDataCommand as g,runMigrateToHyperdriveCommand as p,runMigrateCreateCommand as y}from"../packem_shared/runMigrateGenerateCommand-
|
|
1
|
+
import{d as u}from"../packem_shared/command-Mmxzxyr5.mjs";import{EXIT_CODE as c}from"../packem_shared/EXIT_CODE-08cwt3MK.mjs";import{a as m}from"../packem_shared/resolve-target-C_ZloTvd.mjs";import{runMigrateGenerateCommand as l,runMigrateDataCommand as g,runMigrateToHyperdriveCommand as p,runMigrateCreateCommand as y}from"../packem_shared/runMigrateGenerateCommand-CDHswpMU.mjs";const b=n=>{const{argument:o,cwd:r,logger:t,options:a}=n,e=l({cwd:r,logger:t,name:o[1]??a.name});return{code:e.code,data:{empty:e.empty,migrationFile:e.migrationFile===""?void 0:e.migrationFile,subcommand:"generate"},...e.error===void 0?{}:{error:e.error}}},f=async n=>{const{logger:o,options:r}=n,t=await p({batchSize:r.batchSize,fromToken:r.fromToken??r.token,fromUrl:r.fromUrl??r.url,logger:o,out:r.out,prod:r.prod===!0,tables:r.tables,toToken:r.toToken??r.token,toUrl:r.toUrl??r.url,yes:r.yes===!0});return{code:t.code,data:{bytes:t.bytes,exported:t.exported,imported:t.imported,subcommand:"d1-to-hyperdrive"},...t.error===void 0?{}:{error:t.error}}},w=async n=>{const{argument:o,cwd:r,logger:t,options:a}=n,e=o[1]??a.name;if(!e){const i="migrate create requires a name. Usage: lunora migrate create <name> [--table <table>]";return t.error(i),{code:c.USAGE,error:i}}const s=await y({cwd:r,logger:t,name:e,table:a.table});return{code:s.code,data:{file:s.file===""?void 0:s.file,name:e,subcommand:"create"}}},h=async(n,o)=>{const{argument:r,cwd:t,logger:a,options:e}=n,s=r[1]??e.name;if(!s){const d=`migrate ${o} requires a migration id. Usage: lunora migrate ${o} <id>`;return a.error(d),{code:c.USAGE,error:d}}const i=await g({batchSize:e.batchSize,cwd:t,dryRun:e.dryRun===!0,id:s,logger:a,maxBatches:e.steps,prod:e.prod===!0,subcommand:o,token:e.token,url:m({cwd:t,prod:e.prod===!0,url:e.url}),yes:e.yes===!0});return{code:i.code,data:{id:s,result:i.body,subcommand:o}}},C=u(async({argument:n,cwd:o,logger:r,options:t})=>{const a=n[0],e={argument:n,cwd:o,logger:r,options:t};switch(a){case"create":return await w(e);case"d1-to-hyperdrive":return await f(e);case"down":case"status":case"up":return await h(e,a);case"generate":return b(e);default:{const s=`unknown migrate subcommand: "${a??""}" — expected generate | create | up | down | status`;return e.logger.error(s),{code:c.USAGE,error:s}}}});export{C as execute};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{readFileSync as w,writeFileSync as _,existsSync as p}from"node:fs";import{runCodegen as V,discoverMigrations as H}from"@lunora/codegen";import{readLinkedProject as L,writeLinkedProject as G,execArgsFor as k,detectPackageManager as b,discoverContainerInfo as I,DEV_VARS_FILE as y,parseDevVariableEntries as U,isMintableSecretKey as P,runPostCodegenHook as K,resolveDeployDriver as E,inferLunoraBindings as W,packageNamesFromBindings as q,requiredSecrets as Y,generateSecretValue as z,upsertDevVariableLine as J,writeDevVariablesFileAtomically as X,COMPOSED_WORKER_ENTRY as j,discoverSchemaInfo as Q}from"@lunora/config";import{findWranglerFile as O,validateWranglerProject as Z,reconcileWranglerBindings as ee,reconcileWranglerCompatibilityDate as re,reconcileWranglerCrons as te,describePreservedCrons as ne,readWranglerJsonc as ae,mergeWranglerEnvironment as oe}from"@lunora/config/cloudflare";import{join as v}from"@visulima/path";import{Spinner as ie}from"@visulima/spinner";import{Project as se}from"ts-morph";import{i as ce,m as le,e as de}from"../packem_shared/vectorize-metadata-dXpl2_Ar.mjs";import{r as ue,a as ge,e as me}from"../packem_shared/platform-diagnostics-Cn2g6Jh-.mjs";import{p as fe,a as he}from"../packem_shared/deploy-target-DCWwiuAe.mjs";import{r as R}from"../packem_shared/wrangler-name-Dsk5K1f-.mjs";import{w as ve}from"../packem_shared/binding-manifest-file-CQ1eQYy1.mjs";import{d as pe}from"../packem_shared/command-Mmxzxyr5.mjs";import{a as ye,i as we}from"../packem_shared/docker-DpVxvYpL.mjs";import{EXIT_CODE as h}from"../packem_shared/EXIT_CODE-08cwt3MK.mjs";import{r as ke,p as be,H as $e,a as Se}from"../packem_shared/schema-drift-gate-BDCkQ1S6.mjs";import{containerBuildTag as De}from"@lunora/container";import{defaultSpawner as $}from"../packem_shared/createRecordingSpawner-sS7LEN7x.mjs";import{r as F}from"../packem_shared/resolve-target-C_ZloTvd.mjs";import{c as Ee}from"../packem_shared/tui-prompts-B3YwUhGw.mjs";import{l as Re}from"../packem_shared/wrangler-secrets-C9lJnd5N.mjs";import{runMigrateDataCommand as Ae}from"../packem_shared/runMigrateGenerateCommand-
|
|
1
|
+
import{readFileSync as w,writeFileSync as _,existsSync as p}from"node:fs";import{runCodegen as V,discoverMigrations as H}from"@lunora/codegen";import{readLinkedProject as L,writeLinkedProject as G,execArgsFor as k,detectPackageManager as b,discoverContainerInfo as I,DEV_VARS_FILE as y,parseDevVariableEntries as U,isMintableSecretKey as P,runPostCodegenHook as K,resolveDeployDriver as E,inferLunoraBindings as W,packageNamesFromBindings as q,requiredSecrets as Y,generateSecretValue as z,upsertDevVariableLine as J,writeDevVariablesFileAtomically as X,COMPOSED_WORKER_ENTRY as j,discoverSchemaInfo as Q}from"@lunora/config";import{findWranglerFile as O,validateWranglerProject as Z,reconcileWranglerBindings as ee,reconcileWranglerCompatibilityDate as re,reconcileWranglerCrons as te,describePreservedCrons as ne,readWranglerJsonc as ae,mergeWranglerEnvironment as oe}from"@lunora/config/cloudflare";import{join as v}from"@visulima/path";import{Spinner as ie}from"@visulima/spinner";import{Project as se}from"ts-morph";import{i as ce,m as le,e as de}from"../packem_shared/vectorize-metadata-dXpl2_Ar.mjs";import{r as ue,a as ge,e as me}from"../packem_shared/platform-diagnostics-Cn2g6Jh-.mjs";import{p as fe,a as he}from"../packem_shared/deploy-target-DCWwiuAe.mjs";import{r as R}from"../packem_shared/wrangler-name-Dsk5K1f-.mjs";import{w as ve}from"../packem_shared/binding-manifest-file-CQ1eQYy1.mjs";import{d as pe}from"../packem_shared/command-Mmxzxyr5.mjs";import{a as ye,i as we}from"../packem_shared/docker-DpVxvYpL.mjs";import{EXIT_CODE as h}from"../packem_shared/EXIT_CODE-08cwt3MK.mjs";import{r as ke,p as be,H as $e,a as Se}from"../packem_shared/schema-drift-gate-BDCkQ1S6.mjs";import{containerBuildTag as De}from"@lunora/container";import{defaultSpawner as $}from"../packem_shared/createRecordingSpawner-sS7LEN7x.mjs";import{r as F}from"../packem_shared/resolve-target-C_ZloTvd.mjs";import{c as Ee}from"../packem_shared/tui-prompts-B3YwUhGw.mjs";import{l as Re}from"../packem_shared/wrangler-secrets-C9lJnd5N.mjs";import{runMigrateDataCommand as Ae}from"../packem_shared/runMigrateGenerateCommand-CDHswpMU.mjs";const Ce=/https?:\/\/[^\s"'<>]+\.workers\.dev[^\s"'<>]*/u,Pe=/https:\/\/[^\s"'<>]+/u,je=e=>{if(e===void 0)return;const r=Ce.exec(e);return r?r[0]:Pe.exec(e)?.[0]},x=e=>e===void 0?"":` (--env ${e})`,xe=({cwd:e,env:r,logger:a,now:t,url:n})=>{if(n!==void 0)try{const o=L(e);if(o!==void 0){if(o.workerUrl===n&&o.env===r)return;a.warn(`link: .lunora/project.json records ${o.workerUrl??"(no url)"}${x(o.env)}, but this deploy published ${n}${x(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()))();G(e,{env:r,linkedAt:i,workerName:R(e),workerUrl:n}),a.success(`link: recorded ${n} in .lunora/project.json (run \`lunora link\` to change)`)}catch{}},Te=e=>{const{cwd:r,env:a,logger:t,mintedSecretsFile:n}=e;try{const o=L(r),i=o?.workerName??R(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}`),t.info(" logs: lunora logs")}catch{}},Ne=async e=>{if(e.targets.length===0)return{builtTags:[],code:0};if(!(e.railpackAvailable??ye)()){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=k(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 d=`railpack build failed for container "${t.exportName}" (${t.buildDir})`;return e.logger.error(d),{builtTags:a,code:c.code,error:d}}e.logger.info(`railpack: pushing ${n} to the Cloudflare Registry`);const l=await r(s);if(l.code!==0){const d=`wrangler containers push failed for "${t.exportName}" (${n})`;return e.logger.error(d),{builtTags:a,code:l.code,error:d}}a.push(n)}return{builtTags:a,code:0}},_e=e=>{const r=O(e),a=r===void 0?void 0:w(r,"utf8");return()=>{r!==void 0&&a!==void 0&&_(r,a,"utf8")}},B="<replace-with-d1-create-id>",T=e=>Array.isArray(e)?e.filter(r=>r!=null):void 0,A=(e,r)=>{const a=O(e);if(!a)return;const{parsed:t}=ae(a);if(t===void 0)return;const{error:n,merged:o}=oe(t,r),i=n===void 0?o:t,{containers:s,d1_databases:c,vars:l}=i;return{containers:T(s),d1_databases:T(c),vars:typeof l=="object"&&l!==null&&!Array.isArray(l)?l:void 0}},Le=/^127(?:\.\d{1,3}){3}$/,Ie=e=>{try{const{hostname:r}=new URL(e);return r==="localhost"||Le.test(r)||r==="::1"||r==="[::1]"}catch{return!1}},Ue=e=>e.startsWith("./")||e.startsWith("../")||e.startsWith("/")||e.includes("Dockerfile"),We=(e,r,a,t="deploy",n)=>{const o=(A(e,n)?.containers??[]).filter(s=>typeof s?.image=="string"&&Ue(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},Oe=e=>p(v(e,j))?j:void 0,Fe=(e,r,a="deploy")=>{for(const t of I(e,"lunora").containers){const{image:n}=t;if(n.kind==="dockerfile"&&!p(v(e,n.dockerfilePath))){const o=`${a} blocked: container "${t.exportName}" references a Dockerfile at "${n.dockerfilePath}" that does not exist. Create it or fix the \`image\` path in lunora/containers.ts.`;return r.error(o),o}if(n.kind==="build"&&!p(v(e,n.buildDir))){const o=`${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(o),o}}},M=e=>e.format==="json"?!1:e.interactive!==void 0?e.interactive:process.stdout.isTTY&&!process.env.CI,Be=(e,r)=>(A(e,r)?.d1_databases??[]).find(a=>a.database_id===B)?.binding,Me=async(e,r)=>{if(r.dryRun===!0)return;const a=I(e,"lunora").containers.filter(n=>n.image.kind==="build").map(n=>({buildDir:n.image.buildDir,exportName:n.exportName}));if(a.length===0)return;const t=await Ne({cwd:e,logger:r.logger,railpackAvailable:r.railpackAvailable,spawner:r.spawner,targets:a});return t.code===0?void 0:t.error??"railpack build failed"},Ve=(e,r,a)=>{if(a!==void 0)try{const t=te(e,a);t.changed&&r.success(`synced ${String(a.length)} cron trigger(s) → ${t.wranglerPath??"wrangler.jsonc"}`);for(const o of t.warnings)r.warn(o);const n=ne(t.preserved);n!==void 0&&r.info(n)}catch(t){const n=t instanceof Error?t.message:String(t);r.warn(`cron trigger sync skipped: ${n}`)}},He=async(e,r,a,t,n)=>{try{E(t);const o=await W({projectRoot:e}),i=ee(e,o,n),s=i.wranglerPath??"wrangler.jsonc";i.added.length>0&&r.success(`provisioned bindings: ${i.added.join(", ")} → ${s}`),i.updated.length>0&&r.success(`updated bindings: ${i.updated.join(", ")} → ${s}`);for(const c of i.warnings)r.warn(c)}catch(o){const i=o instanceof Error?o.message:String(o);r.warn(`binding inference skipped: ${i}`)}try{const o=re(e);o.changed&&r.success(`bumped compatibility_date to ${o.date??"unknown"} (Workers Cache enabled) → ${o.wranglerPath??"wrangler.jsonc"}`)}catch(o){const i=o instanceof Error?o.message:String(o);r.warn(`compatibility date sync skipped: ${i}`)}Ve(e,r,a)},Ge=(e,r)=>{const a=v(e,y);if(!p(a))return;let t;try{t=U(w(a,"utf8")).length}catch{return}t!==0&&r.warn(`Note: \`lunora deploy\` does not push secrets. ${y} has ${String(t)} key(s); if you changed them, run \`lunora env push --yes\` to update the deployed secrets.`)},Ke=async e=>{let r=[];try{r=q(await W({projectRoot:e}))}catch{}const a=Y(r).map(n=>n.key);let t=[];try{const n=v(e,y);p(n)&&(t=U(w(n,"utf8")).map(o=>o.key).filter(o=>ce(o)))}catch{}return[...new Set([...a,...t])]},qe=async(e,r,a,t)=>{const{logger:n}=r,o=r.spawner??$,i=b(e),s=r.env===void 0?"":` --env ${r.env}`,{toolchain:c}=E(t);if(c===void 0)return n.error("deploy target has no command-line toolchain; cannot push secrets"),{minted:[],ok:!1};const l=[];for(const d of a){const g=z(),u=c.secretPut({environment:r.env,key:d,temporary:r.temporary}),m=k(i,u.tool,u.args),f=await o({args:m.args,command:m.command,cwd:e,input:g});if(f.code!==0)return n.error(`failed to push secret ${d} (exit ${String(f.code)}); set it manually with \`wrangler secret put ${d}${s}\`.`),{minted:l,ok:!1};l.push({key:d,value:g}),n.success(`generated + pushed ${d}`)}return{minted:l,ok:!0}},Ye=/^[\w-]+$/u,S=[".dev.vars",".dev.vars.*","!.dev.vars.example"],ze=/\r?\n/u,Je=(e,r)=>{const a=v(e,".gitignore");try{const t=p(a)?w(a,"utf8"):"",n=new Set(t.split(ze).map(c=>c.trim())),o=S.filter(c=>!n.has(c));if(o.length===0)return;const i=o.some(c=>!c.startsWith("!"))?[...o.filter(c=>!c.startsWith("!")),...S.filter(c=>c.startsWith("!"))]:o,s=t.length>0&&!t.endsWith(`
|
|
2
2
|
`)?`
|
|
3
3
|
`:"";_(a,`${t}${s}
|
|
4
4
|
# Lunora — never commit a minted secret
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{quoteIdentifier as a,sqlAffinityForKind as $,frameworkColumnDdl as y,OCC_VERSION_COLUMN as T,MAX_D1_TABLE_COLUMNS as d,columnRef as g,physicalIndexName as c}from"@lunora/d1/dialect";import{LunoraError as E}from"@lunora/errors";const v=e=>$(e),f=(e,i)=>{const o=[a(e),i.sqlType];return i.nullable||o.push("NOT NULL"),o.join(" ")},L=e=>{const i=Object.entries(e.columns).map(([s,r])=>` ${f(s,r)}`),o=[...y(),`${a(T)} INTEGER`],n=o.length+i.length;if(n>d)throw new E("VALIDATION_ERROR",`table "${e.name}" needs ${String(n)} columns, over D1's ${String(d)}-column limit — split the table, or move the extra fields into one object field`);const t=[...o.map(s=>` ${s}`),...i].join(`,
|
|
2
|
+
`);return`CREATE TABLE IF NOT EXISTS ${a(e.name)} (
|
|
3
|
+
${t}
|
|
4
|
+
);`},O=e=>`DROP TABLE IF EXISTS ${a(e)};`,C=(e,i,o)=>`ALTER TABLE ${a(e)} ADD COLUMN ${f(i,o)};`,m=(e,i)=>{const o=i.fields.map(t=>g(t)).join(", ");return`CREATE ${i.unique?"UNIQUE ":""}INDEX IF NOT EXISTS ${c(e,i.name)} ON ${a(e)} (${o});`},N=(e,i)=>`DROP INDEX IF EXISTS ${c(e,i)};`,u=e=>e.field===void 0?void 0:JSON.stringify({...e.field,optional:void 0}),I="https://lunora.sh/docs/concepts/migrations#relaxing-not-null-on-a-d1-table",S=(e,i,o,n,t)=>{const s=u(o),r=u(n);if(o.sqlType!==n.sqlType)t.push({kind:"columnTypeChange",summary:`column type change on ${e}.${i}: ${o.sqlType} → ${n.sqlType} (write SQL manually)`});else if(s!==void 0&&r!==void 0&&s!==r){const l=o.field?.kind===n.field?.kind?`${String(n.field?.kind)} shape/constraints changed`:`${String(o.field?.kind)} → ${String(n.field?.kind)}`;t.push({kind:"columnTypeChange",summary:`column type change on ${e}.${i}: ${l} (write SQL manually)`})}if(o.nullable!==n.nullable){const l=n.nullable?`rebuild the table — ${I}`:"write SQL manually";t.push({kind:"columnTypeChange",summary:`nullability change on ${e}.${i}: ${o.nullable?"NULL":"NOT NULL"} → ${n.nullable?"NULL":"NOT NULL"} (${l})`})}},b=(e,i,o,n,t)=>{for(const[s,r]of Object.entries(o)){const l=i[s];if(l===void 0){n.push({kind:"addColumn",sql:C(e,s,r),summary:`ADD COLUMN ${e}.${s}`});continue}S(e,s,l,r,t)}for(const s of Object.keys(i))o[s]===void 0&&t.push({kind:"dropColumn",summary:`DROP COLUMN ${e}.${s} (SQLite drop-column requires careful migration — write SQL manually)`})},q=(e,i,o,n,t)=>{for(const[s,r]of Object.entries(o)){const l=i[s];if(l===void 0){n.push({kind:"createIndex",sql:m(e,r),summary:`CREATE INDEX ${s} ON ${e}`});continue}(!(l.fields.length===r.fields.length&&l.fields.every((p,h)=>p===r.fields[h]))||l.unique!==r.unique)&&t.push({kind:"indexRename",summary:`index ${s} changed on ${e} — drop+create manually if intentional`})}for(const s of Object.keys(i))o[s]===void 0&&n.push({kind:"dropIndex",sql:N(e,s),summary:`DROP INDEX ${s}`})},D=(e,i,o)=>{o.push({kind:"createTable",sql:L(i),summary:`CREATE TABLE ${e}`});for(const n of Object.values(i.indexes))o.push({kind:"createIndex",sql:m(e,n),summary:`CREATE INDEX ${n.name} ON ${e}`})},w=(e,i)=>{const o=e?.tables??{},n=[],t=[];for(const[s,r]of Object.entries(i.tables)){const l=o[s];if(l===void 0){D(s,r,n);continue}b(s,l.columns,r.columns,n,t),q(s,l.indexes,r.indexes,n,t)}for(const s of Object.keys(o))i.tables[s]===void 0&&n.push({kind:"dropTable",sql:O(s),summary:`DROP TABLE ${s}`});return{empty:n.length===0&&t.length===0,entries:n,unsupported:t}},x=(e,i,o)=>{const n=[`-- Lunora migration: ${e}`,`-- Generated at ${o}`,"-- This file was produced by `lunora migrate generate`. Review carefully before applying.",""];for(const t of i.entries)n.push(`-- ${t.summary}`,t.sql,"");if(i.unsupported.length>0){n.push("-- ---------------------------------------------------------------","-- The following deltas are NOT auto-generated in v0.1.","-- Write the appropriate SQL below by hand:","--");for(const t of i.unsupported)n.push(`-- * ${t.summary}`);n.push("-- ---------------------------------------------------------------","")}return i.empty&&n.push("-- No changes detected. Re-running `lunora migrate generate` will overwrite this file.",""),n.join(`
|
|
5
|
+
`)};export{w as diffSnapshots,C as renderAddColumn,m as renderCreateIndex,L as renderCreateTable,N as renderDropIndex,O as renderDropTable,x as renderMigrationFile,v as validatorKindToSqlType};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{existsSync as p,mkdirSync as _,writeFileSync as v,mkdtempSync as x,rmSync as F,readFileSync as U}from"node:fs";import{tmpdir as O}from"node:os";import{discoverMigrations as k,discoverSchema as N,readPackageDependencies as D}from"@lunora/codegen";import{isInteractive as P,promptSelect as G,promptText as j}from"@lunora/config";import{LunoraError as T}from"@lunora/errors";import{join as l}from"@visulima/path";import{Project as w}from"ts-morph";import{r as z,t as L}from"./admin-token-VdUnvnKW.mjs";import{r as q,n as H}from"./admin-url-BhF5ufg1.mjs";import{isRefusal as B,exitCodeForStatus as W,EXIT_CODE as c}from"./EXIT_CODE-08cwt3MK.mjs";import{diffSnapshots as J,renderMigrationFile as V}from"./diffSnapshots-
|
|
1
|
+
import{existsSync as p,mkdirSync as _,writeFileSync as v,mkdtempSync as x,rmSync as F,readFileSync as U}from"node:fs";import{tmpdir as O}from"node:os";import{discoverMigrations as k,discoverSchema as N,readPackageDependencies as D}from"@lunora/codegen";import{isInteractive as P,promptSelect as G,promptText as j}from"@lunora/config";import{LunoraError as T}from"@lunora/errors";import{join as l}from"@visulima/path";import{Project as w}from"ts-morph";import{r as z,t as L}from"./admin-token-VdUnvnKW.mjs";import{r as q,n as H}from"./admin-url-BhF5ufg1.mjs";import{isRefusal as B,exitCodeForStatus as W,EXIT_CODE as c}from"./EXIT_CODE-08cwt3MK.mjs";import{diffSnapshots as J,renderMigrationFile as V}from"./diffSnapshots-WWwx-KvZ.mjs";import X from"./schemaIrToSnapshot-BjK-0IRo.mjs";import{runExportCommand as Z}from"./runExportCommand-DxsJHYZt.mjs";import{r as K}from"./import-D7qdpSmJ.mjs";import{readAndLogBody as Q}from"../packem_chunks/runRpcCommand.mjs";const h="__lunora_reproject__",Y=e=>{if(!e.startsWith(h))return;const r=e.slice(h.length);return r===""?void 0:r},ee=".snapshot.json",R=/[^\da-z]+/gu,M=(e,r)=>{let t=0,o=e.length;for(;t<o&&e[t]===r;)t+=1;for(;o>t&&e[o-1]===r;)o-=1;return e.slice(t,o)},re=e=>{const r=M(e.toLowerCase().replaceAll(R,"_"),"_");return r===""?"auto":r},te=e=>{const r=(t,o=2)=>t.toString().padStart(o,"0");return`${String(e.getUTCFullYear())}${r(e.getUTCMonth()+1)}${r(e.getUTCDate())}${r(e.getUTCHours())}${r(e.getUTCMinutes())}${r(e.getUTCSeconds())}`},oe=e=>{if(p(e))try{const r=U(e,"utf8"),t=JSON.parse(r);if(t.version!==1)throw new T("INTERNAL",`unsupported snapshot version: ${t.version}`);return t}catch(r){const t=r instanceof Error?r.message:String(r);throw new T("INTERNAL",`failed to read ${e}: ${t}`,{cause:r})}},ke=e=>{const r=e.cwd??process.cwd(),t=l(r,"lunora","schema.ts");if(!p(t)){const m=`schema not found: ${t} — run \`vis generate lunora-table --name=<name>\` to create one`;return e.logger.error(m),{code:c.NOT_FOUND,empty:!0,error:m,migrationFile:""}}const o=new w({skipAddingFilesFromTsConfig:!0}),a=N(o,t),s=X(a),n=l(r,"lunora","migrations"),i=l(n,ee);let d;try{d=oe(i)}catch(m){const S=m instanceof Error?m.message:String(m);return e.logger.error(S),{code:c.USAGE,empty:!0,error:S,migrationFile:""}}const u=J(d,s);if(u.empty)return e.logger.info("no schema changes detected — snapshot is already up to date"),{code:0,empty:!0,migrationFile:""};const f=(e.now??(()=>new Date))(),y=re(e.name??"auto"),$=`${te(f)}_${y}.sql`,b=l(n,$);_(n,{recursive:!0});const C=V(y,u,f.toISOString());return v(b,C,"utf8"),v(i,`${JSON.stringify(s,void 0,4)}
|
|
2
2
|
`,"utf8"),e.logger.success(`wrote ${b}`),u.unsupported.length>0&&e.logger.warn(`${String(u.unsupported.length)} unsupported diff(s) — see the comment block in ${$} and write the SQL manually`),{code:0,empty:!1,migrationFile:b}},ne="migrations.ts",I=/^[A-Za-z_]\w*$/u,ae=new Set(["await","break","case","catch","class","const","continue","debugger","default","delete","do","else","enum","export","extends","false","finally","for","function","if","implements","import","in","instanceof","interface","let","new","null","package","private","protected","public","return","static","super","switch","this","throw","true","try","typeof","var","void","while","with","yield"]),A=/^import\s*\{\s*defineMigration\s*\}\s*from\s*["'](?:@lunora\/server|lunorash\/server)["'][^\n]*$/mu,ie=e=>`import { defineMigration } from "${D(e)?.has("lunorash")??!1?"lunorash/server":"@lunora/server"}";`,se="__lunora_admin__:runMigration",ce="__lunora_admin__:migrationStatus",de="/_lunora/migrate",le=e=>M(e.trim().toLowerCase().replaceAll(R,"-"),"-"),ue=e=>e.split("-").filter(r=>r.length>0).map((r,t)=>t===0?r:r.charAt(0).toUpperCase()+r.slice(1)).join(""),me=e=>{const r=l(e,"lunora","schema.ts");if(!p(r))return[];try{const t=new w({skipAddingFilesFromTsConfig:!0});return N(t,r).tables.map(o=>o.name)}catch{return[]}},ge=async e=>e.length>0?G("Which table does this migration iterate?",e.map(r=>({label:r,value:r}))):j("Target table for the migration: "),fe=async(e,r)=>{if(r.table!==void 0)return r.table;const t=r.promptTable??(P()?ge:void 0);if(t===void 0){r.logger.error("migrate create requires a target table when not running interactively — re-run with --table <table>");return}const a=(await t(me(e)))?.trim();if(a===void 0||a===""){r.logger.error("no table selected — re-run with --table <table>");return}return a},De=async e=>{const r=e.cwd??process.cwd(),t=le(e.name);if(t==="")return e.logger.error(`invalid migration name: "${e.name}" — must contain at least one alphanumeric character`),{code:c.USAGE,file:""};const o=ue(t);if(!I.test(o)||ae.has(o))return e.logger.error(`invalid migration name: "${e.name}" derives the export \`${o}\`, which is not a valid identifier — pick a name that starts with a letter and isn't a reserved word`),{code:c.USAGE,file:""};const a=await fe(r,e);if(a===void 0)return{code:c.USAGE,file:""};if(!I.test(a))return e.logger.error(`invalid table: "${a}" — must be a valid identifier ([A-Za-z_][A-Za-z0-9_]*)`),{code:c.USAGE,file:""};const s=l(r,"lunora"),n=l(s,ne);let i=p(n)?U(n,"utf8"):"";if(i.includes(`id: "${t}"`)||new RegExp(String.raw`\bexport const ${o}\b`,"u").test(i))return e.logger.error(`a migration with id "${t}" (export \`${o}\`) already exists in ${n}`),{code:c.CONFLICT,file:""};const d=ie(r);i.trim()===""?i=`${d}
|
|
3
3
|
`:A.test(i)?i=i.replace(A,d):i=`${d}
|
|
4
4
|
${i}`;const u=`export const ${o} = defineMigration({
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{buildSchemaSnapshot as b,isD1GlobalTable as d}from"@lunora/codegen";import{validatorKindToSqlType as p}from"./diffSnapshots-WWwx-KvZ.mjs";const k=new Set(["any","null"]),f=(n,e)=>{const t=e.kindOf(n);return t!==void 0&&k.has(t)||e.nullableOf(n)?!0:t==="union"&&(e.membersOf(n)??[]).some(l=>f(l,e))},m=n=>n.kind==="optional"&&n.inner?m(n.inner):n.kind==="literal"&&n.literalValue==="null"?"null":n.kind,i=n=>n.kind==="optional"&&n.inner?i(n.inner):n,O=n=>f(n,{kindOf:m,membersOf:e=>i(e).members,nullableOf:e=>i(e).column?.notNull===!1}),N=n=>p(n.kind==="optional"&&n.inner?n.inner.kind:n.kind),T=(n,e)=>n.kind==="optional"||O(n)?!0:e===void 0?!1:e.nullable===!0,h=d,y=n=>{const e={},t=b(n,[]);for(const l of n.tables){if(!h(l))continue;const a={};for(const[o,c]of Object.entries(l.shape)){const s=t.tables[l.name]?.fields[o],r={nullable:T(c,s),sqlType:N(c)};a[o]=s===void 0?r:{...r,field:s}}const u={};for(const o of l.indexes)u[o.name]={fields:[...o.fields],name:o.name,unique:o.unique??!1};e[l.name]={columns:a,indexes:u,name:l.name}}return{tables:e,version:1}};export{y as default};
|
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.317",
|
|
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,16 +52,16 @@
|
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@bomb.sh/tab": "0.0.22",
|
|
55
|
-
"@lunora/advisor": "1.0.0-alpha.
|
|
56
|
-
"@lunora/bindings": "1.0.0-alpha.
|
|
57
|
-
"@lunora/codegen": "1.0.0-alpha.
|
|
58
|
-
"@lunora/config": "1.0.0-alpha.
|
|
59
|
-
"@lunora/container": "1.0.0-alpha.
|
|
60
|
-
"@lunora/d1": "1.0.0-alpha.
|
|
61
|
-
"@lunora/errors": "1.0.0-alpha.
|
|
62
|
-
"@lunora/mcp": "1.0.0-alpha.
|
|
63
|
-
"@lunora/runtime": "1.0.0-alpha.
|
|
64
|
-
"@lunora/seed": "1.0.0-alpha.
|
|
55
|
+
"@lunora/advisor": "1.0.0-alpha.167",
|
|
56
|
+
"@lunora/bindings": "1.0.0-alpha.80",
|
|
57
|
+
"@lunora/codegen": "1.0.0-alpha.233",
|
|
58
|
+
"@lunora/config": "1.0.0-alpha.276",
|
|
59
|
+
"@lunora/container": "1.0.0-alpha.62",
|
|
60
|
+
"@lunora/d1": "1.0.0-alpha.146",
|
|
61
|
+
"@lunora/errors": "1.0.0-alpha.46",
|
|
62
|
+
"@lunora/mcp": "1.0.0-alpha.191",
|
|
63
|
+
"@lunora/runtime": "1.0.0-alpha.159",
|
|
64
|
+
"@lunora/seed": "1.0.0-alpha.164",
|
|
65
65
|
"@visulima/cerebro": "3.1.1",
|
|
66
66
|
"@visulima/error": "6.1.0",
|
|
67
67
|
"@visulima/fs": "6.0.7",
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import{quoteIdentifier as a,sqlAffinityForKind as $,frameworkColumnDdl as y,OCC_VERSION_COLUMN as T,MAX_D1_TABLE_COLUMNS as d,columnRef as E,physicalIndexName as c}from"@lunora/d1/dialect";import{LunoraError as g}from"@lunora/errors";const v=e=>$(e),f=(e,n)=>{const o=[a(e),n.sqlType];return n.nullable||o.push("NOT NULL"),o.join(" ")},O=e=>{const n=Object.entries(e.columns).map(([s,r])=>` ${f(s,r)}`),o=[...y(),`${a(T)} INTEGER`],i=o.length+n.length;if(i>d)throw new g("VALIDATION_ERROR",`table "${e.name}" needs ${String(i)} columns, over D1's ${String(d)}-column limit — split the table, or move the extra fields into one object field`);const t=[...o.map(s=>` ${s}`),...n].join(`,
|
|
2
|
-
`);return`CREATE TABLE IF NOT EXISTS ${a(e.name)} (
|
|
3
|
-
${t}
|
|
4
|
-
);`},L=e=>`DROP TABLE IF EXISTS ${a(e)};`,C=(e,n,o)=>`ALTER TABLE ${a(e)} ADD COLUMN ${f(n,o)};`,m=(e,n)=>{const o=n.fields.map(t=>E(t)).join(", ");return`CREATE ${n.unique?"UNIQUE ":""}INDEX IF NOT EXISTS ${c(e,n.name)} ON ${a(e)} (${o});`},I=(e,n)=>`DROP INDEX IF EXISTS ${c(e,n)};`,u=e=>e.field===void 0?void 0:JSON.stringify({...e.field,optional:void 0}),N=(e,n,o,i,t)=>{const s=u(o),r=u(i);if(o.sqlType!==i.sqlType)t.push({kind:"columnTypeChange",summary:`column type change on ${e}.${n}: ${o.sqlType} → ${i.sqlType} (write SQL manually)`});else if(s!==void 0&&r!==void 0&&s!==r){const l=o.field?.kind===i.field?.kind?`${String(i.field?.kind)} shape/constraints changed`:`${String(o.field?.kind)} → ${String(i.field?.kind)}`;t.push({kind:"columnTypeChange",summary:`column type change on ${e}.${n}: ${l} (write SQL manually)`})}o.nullable!==i.nullable&&t.push({kind:"columnTypeChange",summary:`nullability change on ${e}.${n}: ${o.nullable?"NULL":"NOT NULL"} → ${i.nullable?"NULL":"NOT NULL"} (write SQL manually)`})},S=(e,n,o,i,t)=>{for(const[s,r]of Object.entries(o)){const l=n[s];if(l===void 0){i.push({kind:"addColumn",sql:C(e,s,r),summary:`ADD COLUMN ${e}.${s}`});continue}N(e,s,l,r,t)}for(const s of Object.keys(n))o[s]===void 0&&t.push({kind:"dropColumn",summary:`DROP COLUMN ${e}.${s} (SQLite drop-column requires careful migration — write SQL manually)`})},q=(e,n,o,i,t)=>{for(const[s,r]of Object.entries(o)){const l=n[s];if(l===void 0){i.push({kind:"createIndex",sql:m(e,r),summary:`CREATE INDEX ${s} ON ${e}`});continue}(!(l.fields.length===r.fields.length&&l.fields.every((p,h)=>p===r.fields[h]))||l.unique!==r.unique)&&t.push({kind:"indexRename",summary:`index ${s} changed on ${e} — drop+create manually if intentional`})}for(const s of Object.keys(n))o[s]===void 0&&i.push({kind:"dropIndex",sql:I(e,s),summary:`DROP INDEX ${s}`})},k=(e,n,o)=>{o.push({kind:"createTable",sql:O(n),summary:`CREATE TABLE ${e}`});for(const i of Object.values(n.indexes))o.push({kind:"createIndex",sql:m(e,i),summary:`CREATE INDEX ${i.name} ON ${e}`})},A=(e,n)=>{const o=e?.tables??{},i=[],t=[];for(const[s,r]of Object.entries(n.tables)){const l=o[s];if(l===void 0){k(s,r,i);continue}S(s,l.columns,r.columns,i,t),q(s,l.indexes,r.indexes,i,t)}for(const s of Object.keys(o))n.tables[s]===void 0&&i.push({kind:"dropTable",sql:L(s),summary:`DROP TABLE ${s}`});return{empty:i.length===0&&t.length===0,entries:i,unsupported:t}},w=(e,n,o)=>{const i=[`-- Lunora migration: ${e}`,`-- Generated at ${o}`,"-- This file was produced by `lunora migrate generate`. Review carefully before applying.",""];for(const t of n.entries)i.push(`-- ${t.summary}`,t.sql,"");if(n.unsupported.length>0){i.push("-- ---------------------------------------------------------------","-- The following deltas are NOT auto-generated in v0.1.","-- Write the appropriate SQL below by hand:","--");for(const t of n.unsupported)i.push(`-- * ${t.summary}`);i.push("-- ---------------------------------------------------------------","")}return n.empty&&i.push("-- No changes detected. Re-running `lunora migrate generate` will overwrite this file.",""),i.join(`
|
|
5
|
-
`)};export{A as diffSnapshots,C as renderAddColumn,m as renderCreateIndex,O as renderCreateTable,I as renderDropIndex,L as renderDropTable,w as renderMigrationFile,v as validatorKindToSqlType};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{buildSchemaSnapshot as u,isD1GlobalTable as f}from"@lunora/codegen";import{validatorKindToSqlType as m}from"./diffSnapshots-DtC5Cs4Z.mjs";const d=n=>m(n.kind==="optional"&&n.inner?n.inner.kind:n.kind),b=(n,s)=>n.kind==="optional"?!0:s===void 0?!1:s.nullable===!0,p=f,q=n=>{const s={},r=u(n,[]);for(const o of n.tables){if(!p(o))continue;const l={};for(const[e,i]of Object.entries(o.shape)){const t=r.tables[o.name]?.fields[e],c={nullable:b(i,t),sqlType:d(i)};l[e]=t===void 0?c:{...c,field:t}}const a={};for(const e of o.indexes)a[e.name]={fields:[...e.fields],name:e.name,unique:e.unique??!1};s[o.name]={columns:l,indexes:a,name:o.name}}return{tables:s,version:1}};export{q as default};
|