@lunora/cli 1.0.0-alpha.487 → 1.0.0-alpha.488
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.mjs +1 -1
- package/dist/packem_chunks/dispatch.mjs +1 -1
- package/dist/packem_chunks/handler.mjs +1 -1
- package/dist/packem_shared/diffSnapshots-DcE-jQUz.mjs +9 -0
- package/dist/packem_shared/{runMigrateGenerateCommand-CguLEIZp.mjs → runMigrateGenerateCommand-DHdSMKbu.mjs} +1 -1
- package/dist/packem_shared/{schemaIrToSnapshot-Ck7DSPdf.mjs → schemaIrToSnapshot-CbWOjany.mjs} +1 -1
- package/package.json +4 -4
- package/dist/packem_shared/diffSnapshots-Y1G8am6C.mjs +0 -7
package/dist/index.d.mts
CHANGED
|
@@ -1724,6 +1724,11 @@ declare const validatorKindToSqlType: (kind: string) => ColumnSnapshot["sqlType"
|
|
|
1724
1724
|
* which table and field to split.
|
|
1725
1725
|
*/
|
|
1726
1726
|
declare const renderCreateTable: (table: TableSnapshot) => string;
|
|
1727
|
+
/**
|
|
1728
|
+
* `wrangler d1 execute` ignores the marker; it matters only to a user who splits the file at each `;` into
|
|
1729
|
+
* `MigrationRunner` entries by hand. On the line before the statement, so the split keeps it with its `DROP` rather than
|
|
1730
|
+
* handing it to the next statement.
|
|
1731
|
+
*/
|
|
1727
1732
|
declare const renderDropTable: (tableName: string) => string;
|
|
1728
1733
|
/**
|
|
1729
1734
|
* `ALTER TABLE … ADD COLUMN`, always nullable. SQLite rejects `ADD COLUMN … NOT NULL` without a default on a table
|
|
@@ -1735,6 +1740,7 @@ declare const renderDropTable: (tableName: string) => string;
|
|
|
1735
1740
|
*/
|
|
1736
1741
|
declare const renderAddColumn: (tableName: string, columnName: string, column: ColumnSnapshot) => string;
|
|
1737
1742
|
declare const renderCreateIndex: (tableName: string, index: IndexSnapshot) => string;
|
|
1743
|
+
/** Confirmed for `MigrationRunner` the same way as {@link renderDropTable}. */
|
|
1738
1744
|
declare const renderDropIndex: (tableName: string, indexName: string) => string;
|
|
1739
1745
|
/**
|
|
1740
1746
|
* Compute a {@link SchemaDiff} from two snapshots. Pure function — no I/O.
|
package/dist/index.d.ts
CHANGED
|
@@ -1724,6 +1724,11 @@ declare const validatorKindToSqlType: (kind: string) => ColumnSnapshot["sqlType"
|
|
|
1724
1724
|
* which table and field to split.
|
|
1725
1725
|
*/
|
|
1726
1726
|
declare const renderCreateTable: (table: TableSnapshot) => string;
|
|
1727
|
+
/**
|
|
1728
|
+
* `wrangler d1 execute` ignores the marker; it matters only to a user who splits the file at each `;` into
|
|
1729
|
+
* `MigrationRunner` entries by hand. On the line before the statement, so the split keeps it with its `DROP` rather than
|
|
1730
|
+
* handing it to the next statement.
|
|
1731
|
+
*/
|
|
1727
1732
|
declare const renderDropTable: (tableName: string) => string;
|
|
1728
1733
|
/**
|
|
1729
1734
|
* `ALTER TABLE … ADD COLUMN`, always nullable. SQLite rejects `ADD COLUMN … NOT NULL` without a default on a table
|
|
@@ -1735,6 +1740,7 @@ declare const renderDropTable: (tableName: string) => string;
|
|
|
1735
1740
|
*/
|
|
1736
1741
|
declare const renderAddColumn: (tableName: string, columnName: string, column: ColumnSnapshot) => string;
|
|
1737
1742
|
declare const renderCreateIndex: (tableName: string, index: IndexSnapshot) => string;
|
|
1743
|
+
/** Confirmed for `MigrationRunner` the same way as {@link renderDropTable}. */
|
|
1738
1744
|
declare const renderDropIndex: (tableName: string, indexName: string) => string;
|
|
1739
1745
|
/**
|
|
1740
1746
|
* Compute a {@link SchemaDiff} from two snapshots. Pure function — no I/O.
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{C as o,V as a,r as n}from"./packem_chunks/cli.mjs";import{runCodegenCommand as m}from"./packem_chunks/runCodegenCommand.mjs";import{r as p}from"./packem_chunks/handler.mjs";import{runDevCommand as f}from"./packem_chunks/runDevCommand.mjs";import{p as i}from"./packem_shared/plan-BH6l7s48.mjs";import{runInitCommand as l}from"./packem_chunks/runInitCommand.mjs";import{runMigrateGenerateCommand as I}from"./packem_shared/runMigrateGenerateCommand-
|
|
1
|
+
import{C as o,V as a,r as n}from"./packem_chunks/cli.mjs";import{runCodegenCommand as m}from"./packem_chunks/runCodegenCommand.mjs";import{r as p}from"./packem_chunks/handler.mjs";import{runDevCommand as f}from"./packem_chunks/runDevCommand.mjs";import{p as i}from"./packem_shared/plan-BH6l7s48.mjs";import{runInitCommand as l}from"./packem_chunks/runInitCommand.mjs";import{runMigrateGenerateCommand as I}from"./packem_shared/runMigrateGenerateCommand-DHdSMKbu.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-DQVhSE-1.mjs";import{insertSchemaExtension as v}from"./packem_shared/insertSchemaExtension-CbTH3lCQ.mjs";import{createLogger as b,pail as O}from"./packem_shared/createLogger-4TujevyB.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-DcE-jQUz.mjs";import{default as N}from"./packem_shared/schemaIrToSnapshot-CbWOjany.mjs";import{createRecordingSpawner as j,defaultSpawner as q}from"./packem_shared/createRecordingSpawner-DchLi0gR.mjs";import{default as K}from"./packem_shared/parseManifest-CwPTKdtS.mjs";import{D as Y,r as Z}from"./packem_shared/import-3Y59Ry9F.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-CkuCMUP_.mjs";import{runExportCommand as pr}from"./packem_shared/runExportCommand-_PtkJJDT.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{d as u}from"../packem_shared/command-BpMv2n0o.mjs";import{EXIT_CODE as d}from"../packem_shared/EXIT_CODE-DQVhSE-1.mjs";import{r as m}from"../packem_shared/resolve-target-BRvw8Pf7.mjs";import{runMigrateGenerateCommand as l,runMigrateDataCommand as p,runMigrateBackendCommand as g,runMigrateCreateCommand as y}from"../packem_shared/runMigrateGenerateCommand-
|
|
1
|
+
import{d as u}from"../packem_shared/command-BpMv2n0o.mjs";import{EXIT_CODE as d}from"../packem_shared/EXIT_CODE-DQVhSE-1.mjs";import{r as m}from"../packem_shared/resolve-target-BRvw8Pf7.mjs";import{runMigrateGenerateCommand as l,runMigrateDataCommand as p,runMigrateBackendCommand as g,runMigrateCreateCommand as y}from"../packem_shared/runMigrateGenerateCommand-DHdSMKbu.mjs";const b=a=>{const{argument:o,cwd:s,logger:r,options:t}=a,e=l({cwd:s,logger:r,name:o[1]??t.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(a,o)=>{const{logger:s,options:r}=a,t=await g({batchSize:r.batchSize,direction:o,fromToken:r.fromToken??r.token,fromUrl:r.fromUrl??r.url,logger:s,out:r.out,prod:r.prod===!0,replace:r.replace===!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,replaced:t.replaced,subcommand:o},...t.error===void 0?{}:{error:t.error}}},h=async a=>{const{argument:o,cwd:s,logger:r,options:t}=a,e=o[1]??t.name;if(!e){const c="migrate create requires a name. Usage: lunora migrate create <name> [--table <table>]";return r.error(c),{code:d.USAGE,error:c}}const n=await y({cwd:s,logger:r,name:e,table:t.table});return{code:n.code,data:{file:n.file===""?void 0:n.file,name:e,subcommand:"create"}}},w=async(a,o)=>{const{argument:s,cwd:r,logger:t,options:e}=a,n=s[1]??e.name;if(!n){const i=`migrate ${o} requires a migration id. Usage: lunora migrate ${o} <id>`;return t.error(i),{code:d.USAGE,error:i}}const c=await p({batchSize:e.batchSize,cwd:r,dryRun:e.dryRun===!0,id:n,logger:t,maxBatches:e.steps,prod:e.prod===!0,subcommand:o,token:e.token,url:m({cwd:r,prod:e.prod===!0,url:e.url}),yes:e.yes===!0});return{code:c.code,data:{id:n,result:c.body,subcommand:o}}},C=u(async({argument:a,cwd:o,logger:s,options:r})=>{const t=a[0],e={argument:a,cwd:o,logger:s,options:r};switch(t){case"create":return await h(e);case"d1-to-hyperdrive":case"hyperdrive-to-d1":return await f(e,t);case"down":case"status":case"up":return await w(e,t);case"generate":return b(e);default:{const n=`unknown migrate subcommand: "${t??""}" — expected generate | create | up | down | status | d1-to-hyperdrive | hyperdrive-to-d1`;return e.logger.error(n),{code:d.USAGE,error:n}}}});export{C as execute};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{mkdirSync as Re,writeFileSync as X,existsSync as b,readFileSync as E,readdirSync as K,statSync as Te,rmSync as oe,mkdtempSync as pt,realpathSync as vt}from"node:fs";import{dirname as R,join as p,resolve as _,relative as L,sep as x,extname as yt}from"node:path";import{PROJECT_CONFIG_FILENAMES as wt,isTestPath as we,discoverMigrations as kt,readServiceBindings as bt,readBoundServiceBindings as yr,runCodegen as $t}from"@lunora/codegen";import{readLinkedProject as Ce,discoverSchemaInfo as Pe,resolveSchemaDirectory as O,startDevProcess as St,acceptsConnection as Et,readApiSpecMarker as wr,resolveTargetOrThrow as ke,detectFramework as At,DEFAULT_BUNDLE_META_PATH as Rt,STRICT_ADVISORIES_ENV as Tt,LAZY_FUNCTIONS_ENV as Ct,BUNDLE_META_PATH_ENV as Pt,BUILD_TARGET_ENV as _t,BUILD_ROOT_ENV as It,canonicalPath as jt,COMPOSED_WORKER_ENTRY as Ve,discoverContainerInfo as kr,D1_PLACEHOLDER_ID as Ke,writeLinkedProject as Dt,DEV_VARS_FILE as N,parseDevVariableEntries as br,secretSourcesFromBindings as Ot,inferLunoraBindings as $r,requiredSecrets as Lt,mintableSecretKeysFor as Nt,generateSecretValue as xt,upsertDevVariableLine as Ft,writeDevVariablesFileAtomically as Mt,isPlaceholderValue as Ut,ensureGitignoreEntries as Bt,resolveLazyFunctions as de,resolveDeployDriver as le,MissingBuildOutputError as Wt,clearApiSpecMarker as Ht,createDiscoveryCache as qt,planToolchainInvocation as Sr,probeCelldToolchain as Gt,runPostCodegenHook as Vt}from"@lunora/config";import{findWranglerFile as D,readWranglerJsonc as I,HYPERDRIVE_PLACEHOLDER_ID as Er,applyModify as Ar,mergeWranglerEnvironment as ue,bindingsNeedingDatabase as Kt,warnCloudflareCliConfigOnce as zt,validateWranglerProject as Jt,wranglerCodegenInputs as Yt,reconcileWranglerBindings as Xt,reconcileWranglerCompatibilityDate as Qt,reconcileWranglerCrons as Zt,describePreservedCrons as en}from"@lunora/config/cloudflare";import{Spinner as rn}from"@visulima/spinner";import{r as tn}from"../packem_shared/admin-token-VdUnvnKW.mjs";import{n as nn,r as on,a as sn}from"../packem_shared/admin-url-DJB8P6Jh.mjs";import{r as _e,a as an,e as cn}from"../packem_shared/platform-diagnostics-Cn2g6Jh-.mjs";import{p as dn}from"../packem_shared/api-spec-lYyq4vL6.mjs";import{e as ln,m as un,g as fn,i as Rr,d as gn,b as hn}from"../packem_shared/vectorize-metadata-DK61NmVx.mjs";import{w as mn}from"../packem_shared/binding-manifest-file-CQ1eQYy1.mjs";import{d as pn}from"../packem_shared/command-BpMv2n0o.mjs";import{r as Ie}from"../packem_shared/wrangler-name-Dsk5K1f-.mjs";import{a as vn}from"../packem_shared/deploy-target-resolve-BTCW1Iv4.mjs";import{EXIT_CODE as y}from"../packem_shared/EXIT_CODE-DQVhSE-1.mjs";import{spawn as Tr,spawnSync as yn}from"node:child_process";import{createHash as wn,randomUUID as Cr}from"node:crypto";import{setTimeout as kn}from"node:timers/promises";import{stripVTControlCharacters as bn}from"node:util";import{toolchainExecArgs as z,detectPackageManager as F,execArgsFor as je}from"@lunora/config/cli";import{ts as w,Project as Pr,SyntaxKind as k,Node as S}from"ts-morph";import{r as _r,c as Ir}from"../packem_shared/cloudflare-credentials-BVmZnDZk.mjs";import{f as $n}from"../packem_shared/free-port-DjbFhaaT.mjs";import{l as V}from"../packem_shared/js-literal-FWLi94Lh.mjs";import{containerBuildTag as Sn}from"@lunora/container";import{a as En,i as An}from"../packem_shared/docker-DpVxvYpL.mjs";import{defaultSpawner as q}from"../packem_shared/createRecordingSpawner-DchLi0gR.mjs";import{a as De}from"../packem_shared/resolve-target-BRvw8Pf7.mjs";import{p as Rn,H as Tn,a as Cn,r as Pn,c as _n,b as In}from"../packem_shared/health-probe-By9T5x2y.mjs";import{runAdvisor as jn,openShardAccess as ze}from"@lunora/advisor";import{join as A,relative as J,dirname as jr}from"@visulima/path";import{runMigrateDataCommand as Dn}from"../packem_shared/runMigrateGenerateCommand-
|
|
1
|
+
import{mkdirSync as Re,writeFileSync as X,existsSync as b,readFileSync as E,readdirSync as K,statSync as Te,rmSync as oe,mkdtempSync as pt,realpathSync as vt}from"node:fs";import{dirname as R,join as p,resolve as _,relative as L,sep as x,extname as yt}from"node:path";import{PROJECT_CONFIG_FILENAMES as wt,isTestPath as we,discoverMigrations as kt,readServiceBindings as bt,readBoundServiceBindings as yr,runCodegen as $t}from"@lunora/codegen";import{readLinkedProject as Ce,discoverSchemaInfo as Pe,resolveSchemaDirectory as O,startDevProcess as St,acceptsConnection as Et,readApiSpecMarker as wr,resolveTargetOrThrow as ke,detectFramework as At,DEFAULT_BUNDLE_META_PATH as Rt,STRICT_ADVISORIES_ENV as Tt,LAZY_FUNCTIONS_ENV as Ct,BUNDLE_META_PATH_ENV as Pt,BUILD_TARGET_ENV as _t,BUILD_ROOT_ENV as It,canonicalPath as jt,COMPOSED_WORKER_ENTRY as Ve,discoverContainerInfo as kr,D1_PLACEHOLDER_ID as Ke,writeLinkedProject as Dt,DEV_VARS_FILE as N,parseDevVariableEntries as br,secretSourcesFromBindings as Ot,inferLunoraBindings as $r,requiredSecrets as Lt,mintableSecretKeysFor as Nt,generateSecretValue as xt,upsertDevVariableLine as Ft,writeDevVariablesFileAtomically as Mt,isPlaceholderValue as Ut,ensureGitignoreEntries as Bt,resolveLazyFunctions as de,resolveDeployDriver as le,MissingBuildOutputError as Wt,clearApiSpecMarker as Ht,createDiscoveryCache as qt,planToolchainInvocation as Sr,probeCelldToolchain as Gt,runPostCodegenHook as Vt}from"@lunora/config";import{findWranglerFile as D,readWranglerJsonc as I,HYPERDRIVE_PLACEHOLDER_ID as Er,applyModify as Ar,mergeWranglerEnvironment as ue,bindingsNeedingDatabase as Kt,warnCloudflareCliConfigOnce as zt,validateWranglerProject as Jt,wranglerCodegenInputs as Yt,reconcileWranglerBindings as Xt,reconcileWranglerCompatibilityDate as Qt,reconcileWranglerCrons as Zt,describePreservedCrons as en}from"@lunora/config/cloudflare";import{Spinner as rn}from"@visulima/spinner";import{r as tn}from"../packem_shared/admin-token-VdUnvnKW.mjs";import{n as nn,r as on,a as sn}from"../packem_shared/admin-url-DJB8P6Jh.mjs";import{r as _e,a as an,e as cn}from"../packem_shared/platform-diagnostics-Cn2g6Jh-.mjs";import{p as dn}from"../packem_shared/api-spec-lYyq4vL6.mjs";import{e as ln,m as un,g as fn,i as Rr,d as gn,b as hn}from"../packem_shared/vectorize-metadata-DK61NmVx.mjs";import{w as mn}from"../packem_shared/binding-manifest-file-CQ1eQYy1.mjs";import{d as pn}from"../packem_shared/command-BpMv2n0o.mjs";import{r as Ie}from"../packem_shared/wrangler-name-Dsk5K1f-.mjs";import{a as vn}from"../packem_shared/deploy-target-resolve-BTCW1Iv4.mjs";import{EXIT_CODE as y}from"../packem_shared/EXIT_CODE-DQVhSE-1.mjs";import{spawn as Tr,spawnSync as yn}from"node:child_process";import{createHash as wn,randomUUID as Cr}from"node:crypto";import{setTimeout as kn}from"node:timers/promises";import{stripVTControlCharacters as bn}from"node:util";import{toolchainExecArgs as z,detectPackageManager as F,execArgsFor as je}from"@lunora/config/cli";import{ts as w,Project as Pr,SyntaxKind as k,Node as S}from"ts-morph";import{r as _r,c as Ir}from"../packem_shared/cloudflare-credentials-BVmZnDZk.mjs";import{f as $n}from"../packem_shared/free-port-DjbFhaaT.mjs";import{l as V}from"../packem_shared/js-literal-FWLi94Lh.mjs";import{containerBuildTag as Sn}from"@lunora/container";import{a as En,i as An}from"../packem_shared/docker-DpVxvYpL.mjs";import{defaultSpawner as q}from"../packem_shared/createRecordingSpawner-DchLi0gR.mjs";import{a as De}from"../packem_shared/resolve-target-BRvw8Pf7.mjs";import{p as Rn,H as Tn,a as Cn,r as Pn,c as _n,b as In}from"../packem_shared/health-probe-By9T5x2y.mjs";import{runAdvisor as jn,openShardAccess as ze}from"@lunora/advisor";import{join as A,relative as J,dirname as jr}from"@visulima/path";import{runMigrateDataCommand as Dn}from"../packem_shared/runMigrateGenerateCommand-DHdSMKbu.mjs";import{c as On}from"../packem_shared/tui-prompts-B3YwUhGw.mjs";import{l as Ln}from"../packem_shared/wrangler-secrets-C9siMBwN.mjs";const Nn=Object.freeze({edges:[],nodes:[],modules:[],unresolved:[],version:1}),xn=20,Je=e=>`${e.from} -${e.kind}-> ${e.to}`,ee=(e,r)=>{const t=new Set(e);return r.filter(n=>!t.has(n)).toSorted((n,o)=>n.localeCompare(o))},Fn=(e,r)=>{const t=e.modules.map(i=>i.name),n=r.modules.map(i=>i.name),o=e.edges.map(i=>Je(i)),s=r.edges.map(i=>Je(i));return{addedEdges:ee(o,s),addedModules:ee(t,n),removedEdges:ee(s,o),removedModules:ee(n,t)}},re=(e,r,t)=>{if(t.length===0)return[];const n=t.slice(0,xn).map(s=>` ${e} ${s}`),o=t.length-n.length;return[`${r}:`,...n,...o>0?[` … and ${o.toString()} more`]:[]]},Mn=e=>{const r=[...re("+","modules added",e.addedModules),...re("-","modules removed",e.removedModules),...re("+","edges added",e.addedEdges),...re("-","edges removed",e.removedEdges)];return r.length===0?void 0:`architecture changes since the last deploy:
|
|
2
2
|
${r.join(`
|
|
3
3
|
`)}`},Un=(e,r)=>p(e,".lunora",r===void 0?"architecture.json":`architecture.${r}.json`),Bn=e=>{if(b(e))try{const r=JSON.parse(E(e,"utf8"));return r.version===1&&Array.isArray(r.modules)&&Array.isArray(r.edges)?r:void 0}catch{return}},Wn=e=>{const{cwd:r,environment:t,logger:n}=e,o=Un(r,t),s=Bn(o),i=e.current??(s===void 0?void 0:Nn);if(i===void 0)return;const a=s===void 0?void 0:Mn(Fn(s,i));return a!==void 0&&n.info(a),()=>{try{Re(R(o),{recursive:!0}),X(o,`${JSON.stringify(i,void 0,2)}
|
|
4
4
|
`,"utf8")}catch(c){n.warn(`could not record the deployed architecture at ${o}: ${c instanceof Error?c.message:String(c)}`)}}},Hn=e=>{const{cwd:r,env:t,logger:n,mintedSecretsFile:o}=e;try{const s=Ce(r),i=s?.workerName??Ie(r),a=e.url??s?.workerUrl;n.success("deploy complete"),n.info(` worker: ${i??"(see wrangler output above)"}`),t!==void 0&&n.info(` env: ${t}`),a===void 0?n.info(" url: run `lunora link --url <https://your-worker>` to record it"):n.info(` url: ${a}`),o!==void 0&&n.info(` secrets: generated value(s) recorded in ${o}`),e.logsAvailable&&n.info(" logs: lunora logs")}catch{}},qn=/\/index$/u,Gn=/[^\dA-Za-z]/gu,Vn=e=>e.replace(qn,"").split("/").map(r=>r.replaceAll(Gn,"_")),Kn=e=>Vn(e).join("_"),zn=/[^a-z0-9-]/gu,Jn=/-$/u,Ye=7,Yn=(e,r)=>{const t=e.toLowerCase(),n=t.replaceAll(zn,"-");if(n===t&&n.length<=r)return n;const o=wn("sha256").update(t).digest("hex").slice(0,Ye-1);return`${n.slice(0,r-Ye).replace(Jn,"")}-${o}`},Xn=32,Dr=15e3,Qn=5432,Zn=3306,eo=/[^A-Za-z0-9]/gu,Y=e=>`LUNORA_${e.replaceAll(eo,"_").toUpperCase()}_URL`,ro=e=>{const r=new Map;for(const t of e){const n=Y(t),o=r.get(n);if(o!==void 0)return{bindings:[o,t],variable:n};r.set(n,t)}},to=(e,r)=>Yn(`${e}-${r}`,Xn),Xe=e=>e==="postgresql"?"postgres":e==="mariadb"?"mysql":e,no=e=>e==="mysql"?Zn:Qn,oo=e=>{try{const r=new URL(e),t=r.protocol.slice(0,-1),n=decodeURIComponent(r.pathname.slice(1));return!["mariadb","mysql","postgres","postgresql"].includes(t)||r.hostname===""||n===""?void 0:{database:n,host:r.hostname,password:decodeURIComponent(r.password),port:r.port===""?no(Xe(t)):Number(r.port),scheme:Xe(t),user:decodeURIComponent(r.username)}}catch{return}},so=(e,r)=>{const t=typeof r?.password=="string"?r.password:"",n=t===""?[]:[t,JSON.stringify(t).slice(1,-1),encodeURIComponent(t)];let o=e;for(const s of n)o=o.replaceAll(s,"<redacted>");return o.split(" ").map(s=>s.includes("://")?"<url>":s).join(" ")},Or=e=>(Array.isArray(e)?e:[]).flatMap((r,t)=>{const{binding:n,id:o}=typeof r=="object"&&r!==null?r:{};return typeof n=="string"&&o===Er?[{binding:n,index:t}]:[]}),se=e=>{let r="";try{const{errors:t}=JSON.parse(e.text);r=(t??[]).flatMap(n=>typeof n.message=="string"?[n.message]:[]).slice(0,2).join("; ")}catch{}return r===""?`HTTP ${String(e.status)}`:`HTTP ${String(e.status)}: ${r}`},io=e=>typeof e=="string"||typeof e=="number"?e.toString():void 0,ao=["scheme","host","port","database","user"],co=e=>e==="postgresql"?"postgres":e,Qe=(e,r)=>{const t=io(r);return e==="scheme"?co(t):t},Ze=50,lo=async(e,r)=>{for(let t=1;t<=Ze;t+=1){const n=await e(t===1?"/hyperdrive/configs":`/hyperdrive/configs?page=${String(t)}`);if(!n.ok)throw new Error(`listing Hyperdrive configs failed (${se(n)})`);if(!Array.isArray(n.body.result))throw new TypeError("the listing of Hyperdrive configs had no result list");const o=n.body.result.find(i=>i.name===r),s=typeof n.body.result_info=="object"&&n.body.result_info!==null?n.body.result_info:{};if(o!==void 0||typeof s.total_pages!="number"||t>=s.total_pages)return o}throw new Error(`the listing of Hyperdrive configs has more than ${String(Ze)} pages, so "${r}" can't be shown to be absent`)},uo=async(e,r,t,n)=>{const o=n?{caching:{disabled:!0}}:{},s=await lo(e,r);if(typeof s?.id=="string"){const c=ao.filter(d=>Qe(d,s.origin?.[d])!==Qe(d,t[d]));if(c.length>0)throw new Error(`a Hyperdrive config named "${r}" already exists for a different origin, or one that can't be confirmed (${c.join(", ")}). Delete it, or rename the Worker, so the binding does not reach the wrong database.`);const l=await e(`/hyperdrive/configs/${encodeURIComponent(s.id)}`,{body:JSON.stringify({origin:t,...o}),method:"PATCH"});if(!l.ok)throw new Error(`updating its credentials failed (${se(l)})`);return{id:s.id,reused:!0}}const i=await e("/hyperdrive/configs",{body:JSON.stringify({name:r,origin:t,...o}),method:"POST"});if(!i.ok)throw new Error(`creating it failed (${se(i)})`);const{id:a}=typeof i.body.result=="object"&&i.body.result!==null?i.body.result:{};if(typeof a!="string")throw new TypeError("the response carried no id");return{id:a,reused:!1}},fo=(e,r,t,n)=>r===void 0&&n?`${Y(e)} is set but is not a usable connection string for the "${e}" Hyperdrive binding: it needs a postgres://, postgresql:// or mysql:// scheme, a host and a database name, with any special characters percent-encoded.`:r===void 0?`the "${e}" Hyperdrive binding has no config yet. Set ${Y(e)} to its postgres:// or mysql:// connection string and Lunora creates the config, or run \`wrangler hyperdrive create\` and put its id in wrangler.jsonc.`:t?void 0:`creating the "${e}" Hyperdrive config needs CLOUDFLARE_API_TOKEN (Hyperdrive: Edit) and CLOUDFLARE_ACCOUNT_ID, or run \`wrangler hyperdrive create\` and put its id in wrangler.jsonc.`,go=async(e,r)=>{const t=to(e.workerName,e.binding),{id:n,reused:o}=await uo(async(s,i)=>Ir({accountId:e.accountId,apiToken:e.token,...e.fetch===void 0?{}:{fetch:e.fetch},init:{...i,signal:AbortSignal.timeout(Dr)},path:s}),t,e.origin,e.disableCaching);return e.logger.success(`${o?"reusing":"created"} Hyperdrive config "${t}" for ${e.binding} → ${e.wranglerPath}`),{id:n,text:Ar(r,[...e.path,e.index,"id"],n)}},ho=e=>e===void 0||e===""?void 0:e,Oe=e=>{const r=p(R(e),".wrangler","deploy","config.json");try{const{configPath:t}=JSON.parse(E(r,"utf8"));return typeof t=="string"?_(R(r),t):void 0}catch{return}},mo=(e,r,t,n,o)=>{const s=Oe(e);if(s===void 0||s===e)return;if(n.built!==n.deployed){o.warn(`the build output ${s} was made for ${n.built===void 0?"the default environment":`"${n.built}"`}, not ${n.deployed===void 0?"the default environment":`"${n.deployed}"`}, so the "${r}" Hyperdrive id was not written there. Build with CLOUDFLARE_ENV set to the environment you deploy, then deploy again.`);return}let i;try{i=I(s)}catch{return}const a=Or(i.parsed?.hyperdrive).find(c=>c.binding===r);a!==void 0&&X(s,Ar(i.text,["hyperdrive",a.index,"id"],t),"utf8")},po=(e,r)=>{const t=typeof e.name=="string"&&e.name!==""?e.name:"lunora";if(r===void 0)return t;const n=e.env?.[r]?.name;return typeof n=="string"&&n!==""?n:`${t}-${r}`},fe=(e,r,t)=>{const n=t??D(e),o=n===void 0?void 0:I(n).parsed;if(n===void 0||o===void 0)return;const s=r===void 0?void 0:o.env?.[r],i=Or(r===void 0?o.hyperdrive:s?.hyperdrive);return i.length===0?void 0:{accountId:s?.account_id??o.account_id,entries:i,path:r===void 0?["hyperdrive"]:["env",r,"hyperdrive"],workerName:po(o,r),wranglerPath:n}},vo=(e,r,t)=>{const n=ro(e.map(({binding:o})=>o));if(n!==void 0){const o=`deploy blocked: the Hyperdrive bindings ${n.bindings.map(s=>`"${s}"`).join(" and ")} both read ${n.variable} and would share one config. Rename one so their names differ in letters or digits, not only in punctuation.`;return t.logger.error(o),o}for(const{binding:o,origin:s,supplied:i}of e){const a=fo(o,s,r,i);if(a!==void 0&&t.dryRun===!0)t.logger.warn(`dry run: ${a} A real deploy stops here.`);else if(a!==void 0){const c=`deploy blocked: ${a}`;return t.logger.error(c),c}}},yo=async(e,r,t,n)=>{let o;try{o=await e(`/hyperdrive/configs/${encodeURIComponent(t)}`)}catch(i){n.warn(`could not check whether the "${r}" Hyperdrive config has query caching off (${i instanceof Error?i.message:String(i)}).`);return}if(!o.ok){n.warn(`could not check whether the "${r}" Hyperdrive config has query caching off (${se(o)}).`);return}const{caching:s}=typeof o.body.result=="object"&&o.body.result!==null?o.body.result:{};s?.disabled!==!0&&n.warn(`the "${r}" Hyperdrive config has query caching on, so .global() tables would read rows up to 75 s old. Run \`wrangler hyperdrive update ${t} --caching-disabled\`.`)},wo=async(e,r)=>{const t=e.wranglerPath??D(e.cwd),n=t===void 0?void 0:I(t).parsed,o=e.wranglerEnvironment===void 0?n:n?.env?.[e.wranglerEnvironment],{accountId:s,token:i}=_r(r,o?.account_id??n?.account_id);if(s===void 0||i===void 0)return;const a=async(c,l)=>Ir({accountId:s,apiToken:i,...e.fetch===void 0?{}:{fetch:e.fetch},init:{...l,signal:AbortSignal.timeout(Dr)},path:c});for(const c of Array.isArray(o?.hyperdrive)?o.hyperdrive:[]){const{binding:l,id:d}=typeof c=="object"&&c!==null?c:{};typeof l=="string"&&typeof d=="string"&&d!==Er&&await yo(a,l,d,e.logger)}},ko=async e=>{const r=e.environment??process.env;e.disableCaching===!0&&e.checkOnly!==!0&&e.dryRun!==!0&&await wo(e,r);const t=fe(e.cwd,e.wranglerEnvironment,e.wranglerPath);if(t===void 0)return;const{entries:n,path:o,wranglerPath:s}=t,{accountId:i,token:a}=_r(r,t.accountId),c=n.map(({binding:d})=>{const u=r[Y(d)]??"";return{binding:d,origin:oo(u),supplied:u!==""}}),l=vo(c,a!==void 0&&i!==void 0,e);if(l!==void 0)return l;if(!(e.dryRun===!0||e.checkOnly===!0))for(const[d,{binding:u,index:f}]of n.entries()){const g=c[d]?.origin;if(!(g===void 0||a===void 0||i===void 0))try{const{id:h,text:v}=await go({accountId:i,binding:u,disableCaching:e.disableCaching===!0,fetch:e.fetch,index:f,logger:e.logger,origin:g,path:o,token:a,workerName:t.workerName,wranglerPath:s},E(s,"utf8"));X(s,v,"utf8"),mo(s,u,h,{built:ho(r.CLOUDFLARE_ENV),deployed:e.wranglerEnvironment},e.logger)}catch(h){const v=h instanceof Error?h.message:String(h),m=`deploy blocked: the "${u}" Hyperdrive config could not be set up: ${so(v,c[d]?.origin)}`;return e.logger.error(m),m}}},bo=(e,r)=>{const t=fe(e,r.env)?.entries[0]?.binding;if(t===void 0)return;const n=`prepare blocked: the "${t}" Hyperdrive binding still has its placeholder id. Run \`lunora deploy\` with ${Y(t)} set to create the config, or put the id from \`wrangler hyperdrive create\` in wrangler.jsonc.`;return r.logger.error(n),n},$o=(e,r)=>{const t=fe(e,r.env)?.entries[0]?.binding;if(t===void 0)return;const n=`deploy blocked: the "${t}" Hyperdrive binding has no config, and a --temporary deploy cannot create one: it would be made in your account while the Worker goes to a temporary one, which a temporary account has no database for. Deploy without --temporary.`;return r.logger.error(n),n},H=async(e,r,t,n,o="create",s)=>{if(n!=="cloudflare")return;if(t==="prepare")return bo(e,r);if(r.temporary===!0)return $o(e,r);const i=r.clientBuildEnvironment===void 0?void 0:{...process.env,CLOUDFLARE_ENV:r.clientBuildEnvironment},a=Pe(e,O(e),r.discoveryCache);return a.error!==void 0&&r.logger.warn(`could not read the schema (${a.error}), so Hyperdrive configs are set up with query caching off.`),ko({checkOnly:o==="check",cwd:e,disableCaching:a.error!==void 0||a.info?.hasHyperdriveGlobalTable===!0,dryRun:r.dryRun,environment:i,logger:r.logger,wranglerEnvironment:r.env,wranglerPath:s})},So=(e,r,t)=>fe(e,r,t)!==void 0,pe=[".ts",".tsx",".mts",".js",".mjs"],Eo=/^[a-z]+:/u,er=/\.[cm]?js$/u,Ao=e=>!e.startsWith(".")&&!e.startsWith("/")&&!e.startsWith("#")&&!Eo.test(e),Ro=e=>e.split("/").slice(0,e.startsWith("@")?2:1).join("/"),To=e=>e.split(x).some(r=>r==="_generated"||r==="node_modules"),Co=e=>e.split(x).includes("node_modules"),rr=(e,r)=>{const t=_(R(e),r),n=er.test(t)?t.replace(er,""):void 0;return[t,...n===void 0?[]:pe.map(s=>`${n}${s}`),...pe.map(s=>`${t}${s}`),...pe.map(s=>p(t,`index${s}`))].find(s=>b(s)&&Te(s).isFile())},Po=/^lunora\.config\.[cm]?[jt]s$/u,be=e=>{if(typeof e=="string")return e;if(typeof e=="object"&&e!==null)for(const[r,t]of Object.entries(e)){const n=r==="types"?void 0:be(t);if(n!==void 0)return n}},_o=(e,r)=>{let t;try{t=JSON.parse(E(p(e,"package.json"),"utf8")).imports}catch{return}const n=be(t?.[r]);if(n!==void 0)return n;for(const[o,s]of Object.entries(t??{})){const[i="",a=""]=o.split("*"),c=be(s);if(c!==void 0&&o.includes("*")&&r.startsWith(i)&&r.endsWith(a)&&r.length>=o.length-1){const l=r.slice(i.length,r.length-a.length);return c.replaceAll("*",()=>l)}}},Io=(e,r)=>{const t=p(e,r,"_generated"),n=K(e).find(o=>Po.test(o));return[...b(t)?K(t).filter(o=>o.endsWith(".ts")).map(o=>p(t,o)):[],...n===void 0?[]:[p(e,n)]]},jo=e=>{const r=w.findConfigFile(e,n=>w.sys.fileExists(n));if(r===void 0)return!1;const t=w.readConfigFile(r,n=>w.sys.readFile(n));return w.parseJsonConfigFileContent(t.config??{},w.sys,R(r)).options.verbatimModuleSyntax===!0},tr=e=>e!==void 0&&(w.isNamedImports(e)||w.isNamedExports(e))&&e.elements.length>0&&e.elements.every(r=>r.isTypeOnly),Do=(e,r)=>{if(w.isImportDeclaration(e)){const{importClause:t}=e;return!(t?.phaseModifier===w.SyntaxKind.TypeKeyword||!r&&t?.name===void 0&&tr(t?.namedBindings))&&w.isStringLiteral(e.moduleSpecifier)?e.moduleSpecifier.text:void 0}if(w.isExportDeclaration(e))return!(e.isTypeOnly||!r&&tr(e.exportClause))&&e.moduleSpecifier!==void 0&&w.isStringLiteral(e.moduleSpecifier)?e.moduleSpecifier.text:void 0},Oo=e=>{if(!w.isCallExpression(e)||e.expression.kind!==w.SyntaxKind.ImportKeyword)return;const[r]=e.arguments;return r!==void 0&&w.isStringLiteralLike(r)?r.text:void 0},Lo=(e,r)=>{const t=w.createSourceFile(e,E(e,"utf8"),w.ScriptTarget.Latest,!1),n=[],o=[],s=i=>{const a=Oo(i),c=a??Do(i,r);c?.startsWith(".")||c?.startsWith("#")?o.push(c):a!==void 0&&Ao(a)&&n.push(a),w.forEachChild(i,s)};return s(t),{dynamicPackages:n,relative:o}},No=(e,r)=>{for(let t=e;;t=R(t)){if(b(p(t,"node_modules",r,"package.json")))return!0;if(R(t)===t)return!1}},xo=(e,r,t)=>{const n=jo(e),o=new Set,s=new Set,i=r!==void 0&&b(_(e,r))?[_(e,r)]:Io(e,t);for(let a=i.shift();a!==void 0;a=i.shift())if(!o.has(a)&&!Co(L(e,a))){o.add(a);const{dynamicPackages:c,relative:l}=Lo(a,n);if(!To(L(e,a)))for(const d of c)s.add(d);i.push(...l.flatMap(d=>{if(!d.startsWith("#"))return rr(a,d)??[];const u=_o(e,d);return u===void 0?[]:rr(p(e,"package.json"),u)??[]}))}return[...s].filter(a=>No(e,Ro(a))).toSorted((a,c)=>a.localeCompare(c))},Fo=18787,nr=3,$e=12e4,Lr=5e3,W=10,Nr=new Set([".js",".mjs",".mts",".ts",".tsx"]),Mo=/\(void 0\)|is not a function|before initialization|of undefined/u,Uo=e=>typeof e=="object"&&e!==null&&typeof e.functionPath=="string"&&(e.deferred===void 0||["agent","module","queue","workflow"].includes(e.deferred))&&typeof e.message=="string",Bo=e=>{const r=O(e),t=new Map;let n;try{n=K(p(e,r),{recursive:!0,encoding:"utf8"})}catch{return t}for(const o of n){const s=yt(o);Nr.has(s)&&!o.split(x).some(i=>i==="_generated"||i==="node_modules")&&t.set(Kn(o.slice(0,-s.length).split(x).join("/")),p(r,o))}return t},or=e=>Mo.test(e)?`
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import{quoteIdentifier as a,sqlAffinityForKind as T,frameworkColumnDdl as y,OCC_VERSION_COLUMN as E,MAX_D1_TABLE_COLUMNS as d,columnRef as L,physicalIndexName as c}from"@lunora/d1/dialect";import{LunoraError as g}from"@lunora/errors";const f="-- lunora:allow-destructive",w=e=>T(e),p=(e,i)=>{const s=[a(e),i.sqlType];return i.nullable||s.push("NOT NULL"),s.join(" ")},O=e=>{const i=Object.entries(e.columns).map(([o,r])=>` ${p(o,r)}`),s=[...y(),`${a(E)} INTEGER`],n=s.length+i.length;if(n>d)throw new g("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=[...s.map(o=>` ${o}`),...i].join(`,
|
|
2
|
+
`);return`CREATE TABLE IF NOT EXISTS ${a(e.name)} (
|
|
3
|
+
${t}
|
|
4
|
+
);`},C=e=>`${f}
|
|
5
|
+
DROP TABLE IF EXISTS ${a(e)};`,S=(e,i,s)=>{const n=`ALTER TABLE ${a(e)} ADD COLUMN ${p(i,{...s,nullable:!0})};`;return s.nullable?n:`${n}
|
|
6
|
+
-- ${a(e)}.${a(i)} is required, so rows written before it read NULL. Backfill them:
|
|
7
|
+
-- UPDATE ${a(e)} SET ${a(i)} = <value> WHERE ${a(i)} IS NULL;`},$=(e,i)=>{const s=i.fields.map(t=>L(t)).join(", ");return`CREATE ${i.unique?"UNIQUE ":""}INDEX IF NOT EXISTS ${c(e,i.name)} ON ${a(e)} (${s});`},I=(e,i)=>`${f}
|
|
8
|
+
DROP INDEX IF EXISTS ${c(e,i)};`,u=e=>e.field===void 0?void 0:JSON.stringify({...e.field,optional:void 0,refined:void 0}),R="https://lunora.sh/docs/concepts/migrations#relaxing-not-null-on-a-d1-table",b=(e,i,s,n,t)=>{const o=u(s),r=u(n);if(s.sqlType!==n.sqlType)t.push({kind:"columnTypeChange",summary:`column type change on ${e}.${i}: ${s.sqlType} → ${n.sqlType} (write SQL manually)`});else if(o!==void 0&&r!==void 0&&o!==r){const l=s.field?.kind===n.field?.kind?`${String(n.field?.kind)} shape/constraints changed`:`${String(s.field?.kind)} → ${String(n.field?.kind)}`;t.push({kind:"columnTypeChange",summary:`column type change on ${e}.${i}: ${l} (write SQL manually)`})}if(s.nullable!==n.nullable){const l=n.nullable?`rebuild the table — ${R}`:"write SQL manually";t.push({kind:"columnTypeChange",summary:`nullability change on ${e}.${i}: ${s.nullable?"NULL":"NOT NULL"} → ${n.nullable?"NULL":"NOT NULL"} (${l})`})}},q=(e,i,s,n,t)=>{for(const[o,r]of Object.entries(s)){const l=i[o];if(l===void 0){n.push({kind:"addColumn",sql:S(e,o,r),summary:`ADD COLUMN ${e}.${o}`});continue}b(e,o,l,r,t)}for(const o of Object.keys(i))s[o]===void 0&&t.push({kind:"dropColumn",summary:`DROP COLUMN ${e}.${o} (SQLite drop-column requires careful migration — write SQL manually)`})},D=(e,i,s,n,t)=>{for(const[o,r]of Object.entries(s)){const l=i[o];if(l===void 0){n.push({kind:"createIndex",sql:$(e,r),summary:`CREATE INDEX ${o} ON ${e}`});continue}(!(l.fields.length===r.fields.length&&l.fields.every((m,h)=>m===r.fields[h]))||l.unique!==r.unique)&&t.push({kind:"indexRename",summary:`index ${o} changed on ${e} — drop+create manually if intentional`})}for(const o of Object.keys(i))s[o]===void 0&&n.push({kind:"dropIndex",sql:I(e,o),summary:`DROP INDEX ${o}`})},N=(e,i,s)=>{s.push({kind:"createTable",sql:O(i),summary:`CREATE TABLE ${e}`});for(const n of Object.values(i.indexes))s.push({kind:"createIndex",sql:$(e,n),summary:`CREATE INDEX ${n.name} ON ${e}`})},U=(e,i)=>{const s=e?.tables??{},n=[],t=[];for(const[o,r]of Object.entries(i.tables)){const l=s[o];if(l===void 0){N(o,r,n);continue}q(o,l.columns,r.columns,n,t),D(o,l.indexes,r.indexes,n,t)}for(const o of Object.keys(s))i.tables[o]===void 0&&n.push({kind:"dropTable",sql:C(o),summary:`DROP TABLE ${o}`});return{empty:n.length===0&&t.length===0,entries:n,unsupported:t}},x=(e,i,s)=>{const n=[`-- Lunora migration: ${e}`,`-- Generated at ${s}`,"-- 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(`
|
|
9
|
+
`)};export{U as diffSnapshots,S as renderAddColumn,$ as renderCreateIndex,O as renderCreateTable,I as renderDropIndex,C as renderDropTable,x as renderMigrationFile,w as validatorKindToSqlType};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{existsSync as p,mkdirSync as _,writeFileSync as w,mkdtempSync as C,rmSync as F,readFileSync as U}from"node:fs";import{tmpdir as O}from"node:os";import{discoverMigrations as k,discoverSchema as x,readPackageDependencies as D}from"@lunora/codegen";import{isInteractive as G,promptSelect as P,promptText as j}from"@lunora/config";import{LunoraError as T}from"@lunora/errors";import{join as m}from"@visulima/path";import{Project as v}from"ts-morph";import{r as z,t as L}from"./admin-token-VdUnvnKW.mjs";import{r as B,a as q,n as H}from"./admin-url-DJB8P6Jh.mjs";import{isRefusal as W,exitCodeForStatus as J,EXIT_CODE as d}from"./EXIT_CODE-DQVhSE-1.mjs";import{diffSnapshots as K,renderMigrationFile as V}from"./diffSnapshots-
|
|
1
|
+
import{existsSync as p,mkdirSync as _,writeFileSync as w,mkdtempSync as C,rmSync as F,readFileSync as U}from"node:fs";import{tmpdir as O}from"node:os";import{discoverMigrations as k,discoverSchema as x,readPackageDependencies as D}from"@lunora/codegen";import{isInteractive as G,promptSelect as P,promptText as j}from"@lunora/config";import{LunoraError as T}from"@lunora/errors";import{join as m}from"@visulima/path";import{Project as v}from"ts-morph";import{r as z,t as L}from"./admin-token-VdUnvnKW.mjs";import{r as B,a as q,n as H}from"./admin-url-DJB8P6Jh.mjs";import{isRefusal as W,exitCodeForStatus as J,EXIT_CODE as d}from"./EXIT_CODE-DQVhSE-1.mjs";import{diffSnapshots as K,renderMigrationFile as V}from"./diffSnapshots-DcE-jQUz.mjs";import X from"./schemaIrToSnapshot-CbWOjany.mjs";import{runExportCommand as Z}from"./runExportCommand-_PtkJJDT.mjs";import{r as Q}from"./import-3Y59Ry9F.mjs";import{readAndLogBody as Y}from"../packem_chunks/runRpcCommand.mjs";const h="__lunora_reproject__",ee=e=>{if(!e.startsWith(h))return;const r=e.slice(h.length);return r===""?void 0:r},re=".snapshot.json",N=/[^\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)},te=e=>{const r=M(e.toLowerCase().replaceAll(N,"_"),"_");return r===""?"auto":r},oe=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())}`},ae=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})}},je=e=>{const r=e.cwd??process.cwd(),t=m(r,"lunora","schema.ts");if(!p(t)){const f=`schema not found: ${t} — run \`vis generate lunora-table --name=<name>\` to create one`;return e.logger.error(f),{code:d.NOT_FOUND,empty:!0,error:f,migrationFile:""}}const o=new v({skipAddingFilesFromTsConfig:!0}),n=x(o,t),l=X(n),c=m(r,"lunora","migrations"),s=m(c,re);let a;try{a=ae(s)}catch(f){const S=f instanceof Error?f.message:String(f);return e.logger.error(S),{code:d.USAGE,empty:!0,error:S,migrationFile:""}}const i=K(a,l);if(i.empty)return e.logger.info("no schema changes detected — snapshot is already up to date"),{code:0,empty:!0,migrationFile:""};const g=(e.now??(()=>new Date))(),$=te(e.name??"auto"),y=`${oe(g)}_${$}.sql`,b=m(c,y);_(c,{recursive:!0});const R=V($,i,g.toISOString());return w(b,R,"utf8"),w(s,`${JSON.stringify(l,void 0,4)}
|
|
2
2
|
`,"utf8"),e.logger.success(`wrote ${b}`),i.unsupported.length>0&&e.logger.warn(`${String(i.unsupported.length)} unsupported diff(s) — see the comment block in ${y} and write the SQL manually`),{code:0,empty:!1,migrationFile:b}},ne="migrations.ts",A=/^[A-Za-z_]\w*$/u,ie=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"]),E=/^import\s*\{\s*defineMigration\s*\}\s*from\s*["'](?:@lunora\/server|lunorash\/server)["'][^\n]*$/mu,se=e=>`import { defineMigration } from "${D(e)?.has("lunorash")??!1?"lunorash/server":"@lunora/server"}";`,ce="__lunora_admin__:runMigration",de="__lunora_admin__:migrationStatus",le="/_lunora/migrate",ue=e=>M(e.trim().toLowerCase().replaceAll(N,"-"),"-"),me=e=>e.split("-").filter(r=>r.length>0).map((r,t)=>t===0?r:r.charAt(0).toUpperCase()+r.slice(1)).join(""),ge=e=>{const r=m(e,"lunora","schema.ts");if(!p(r))return[];try{const t=new v({skipAddingFilesFromTsConfig:!0});return x(t,r).tables.map(o=>o.name)}catch{return[]}},fe=async e=>e.length>0?P("Which table does this migration iterate?",e.map(r=>({label:r,value:r}))):j("Target table for the migration: "),he=async(e,r)=>{if(r.table!==void 0)return r.table;const t=r.promptTable??(G()?fe: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 n=(await t(ge(e)))?.trim();if(n===void 0||n===""){r.logger.error("no table selected — re-run with --table <table>");return}return n},ze=async e=>{const r=e.cwd??process.cwd(),t=ue(e.name);if(t==="")return e.logger.error(`invalid migration name: "${e.name}" — must contain at least one alphanumeric character`),{code:d.USAGE,file:""};const o=me(t);if(!A.test(o)||ie.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:d.USAGE,file:""};const n=await he(r,e);if(n===void 0)return{code:d.USAGE,file:""};if(!A.test(n))return e.logger.error(`invalid table: "${n}" — must be a valid identifier ([A-Za-z_][A-Za-z0-9_]*)`),{code:d.USAGE,file:""};const l=m(r,"lunora"),c=m(l,ne);let s=p(c)?U(c,"utf8"):"";if(s.includes(`id: "${t}"`)||new RegExp(String.raw`\bexport const ${o}\b`,"u").test(s))return e.logger.error(`a migration with id "${t}" (export \`${o}\`) already exists in ${c}`),{code:d.CONFLICT,file:""};const a=se(r);s.trim()===""?s=`${a}
|
|
3
3
|
`:E.test(s)?s=s.replace(E,a):s=`${a}
|
|
4
4
|
${s}`;const i=`export const ${o} = defineMigration({
|
package/dist/packem_shared/{schemaIrToSnapshot-Ck7DSPdf.mjs → schemaIrToSnapshot-CbWOjany.mjs}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{buildSchemaSnapshot as b,isD1GlobalTable as d}from"@lunora/codegen";import{validatorKindToSqlType as p}from"./diffSnapshots-
|
|
1
|
+
import{buildSchemaSnapshot as b,isD1GlobalTable as d}from"@lunora/codegen";import{validatorKindToSqlType as p}from"./diffSnapshots-DcE-jQUz.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.488",
|
|
4
4
|
"description": "The Lunora CLI: init, dev, deploy, codegen, migrate, seed, doctor, insights, logs, registry, and the rest of the project commands",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent-skills",
|
|
@@ -58,13 +58,13 @@
|
|
|
58
58
|
"@bomb.sh/tab": "0.0.22",
|
|
59
59
|
"@lunora/advisor": "^1.0.0-alpha.289",
|
|
60
60
|
"@lunora/bindings": "1.0.0-alpha.151",
|
|
61
|
-
"@lunora/codegen": "^1.0.0-alpha.
|
|
62
|
-
"@lunora/config": "^1.0.0-alpha.
|
|
61
|
+
"@lunora/codegen": "^1.0.0-alpha.403",
|
|
62
|
+
"@lunora/config": "^1.0.0-alpha.459",
|
|
63
63
|
"@lunora/container": "1.0.0-alpha.108",
|
|
64
64
|
"@lunora/d1": "^1.0.0-alpha.233",
|
|
65
65
|
"@lunora/errors": ">=1.0.0-alpha.51 <2.0.0-0",
|
|
66
66
|
"@lunora/mcp": "^1.0.0-alpha.291",
|
|
67
|
-
"@lunora/runtime": "^1.0.0-alpha.
|
|
67
|
+
"@lunora/runtime": "^1.0.0-alpha.280",
|
|
68
68
|
"@lunora/seed": "^1.0.0-alpha.282",
|
|
69
69
|
"@lunora/wire": "1.0.0-alpha.6",
|
|
70
70
|
"@visulima/cerebro": "4.0.1",
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import{quoteIdentifier as a,sqlAffinityForKind as h,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 L}from"@lunora/errors";const A=e=>h(e),f=(e,i)=>{const s=[a(e),i.sqlType];return i.nullable||s.push("NOT NULL"),s.join(" ")},g=e=>{const i=Object.entries(e.columns).map(([o,r])=>` ${f(o,r)}`),s=[...y(),`${a(T)} INTEGER`],n=s.length+i.length;if(n>d)throw new L("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=[...s.map(o=>` ${o}`),...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,s)=>{const n=`ALTER TABLE ${a(e)} ADD COLUMN ${f(i,{...s,nullable:!0})};`;return s.nullable?n:`${n}
|
|
5
|
-
-- ${a(e)}.${a(i)} is required, so rows written before it read NULL. Backfill them:
|
|
6
|
-
-- UPDATE ${a(e)} SET ${a(i)} = <value> WHERE ${a(i)} IS NULL;`},p=(e,i)=>{const s=i.fields.map(t=>E(t)).join(", ");return`CREATE ${i.unique?"UNIQUE ":""}INDEX IF NOT EXISTS ${c(e,i.name)} ON ${a(e)} (${s});`},S=(e,i)=>`DROP INDEX IF EXISTS ${c(e,i)};`,u=e=>e.field===void 0?void 0:JSON.stringify({...e.field,optional:void 0,refined:void 0}),I="https://lunora.sh/docs/concepts/migrations#relaxing-not-null-on-a-d1-table",b=(e,i,s,n,t)=>{const o=u(s),r=u(n);if(s.sqlType!==n.sqlType)t.push({kind:"columnTypeChange",summary:`column type change on ${e}.${i}: ${s.sqlType} → ${n.sqlType} (write SQL manually)`});else if(o!==void 0&&r!==void 0&&o!==r){const l=s.field?.kind===n.field?.kind?`${String(n.field?.kind)} shape/constraints changed`:`${String(s.field?.kind)} → ${String(n.field?.kind)}`;t.push({kind:"columnTypeChange",summary:`column type change on ${e}.${i}: ${l} (write SQL manually)`})}if(s.nullable!==n.nullable){const l=n.nullable?`rebuild the table — ${I}`:"write SQL manually";t.push({kind:"columnTypeChange",summary:`nullability change on ${e}.${i}: ${s.nullable?"NULL":"NOT NULL"} → ${n.nullable?"NULL":"NOT NULL"} (${l})`})}},q=(e,i,s,n,t)=>{for(const[o,r]of Object.entries(s)){const l=i[o];if(l===void 0){n.push({kind:"addColumn",sql:C(e,o,r),summary:`ADD COLUMN ${e}.${o}`});continue}b(e,o,l,r,t)}for(const o of Object.keys(i))s[o]===void 0&&t.push({kind:"dropColumn",summary:`DROP COLUMN ${e}.${o} (SQLite drop-column requires careful migration — write SQL manually)`})},N=(e,i,s,n,t)=>{for(const[o,r]of Object.entries(s)){const l=i[o];if(l===void 0){n.push({kind:"createIndex",sql:p(e,r),summary:`CREATE INDEX ${o} ON ${e}`});continue}(!(l.fields.length===r.fields.length&&l.fields.every((m,$)=>m===r.fields[$]))||l.unique!==r.unique)&&t.push({kind:"indexRename",summary:`index ${o} changed on ${e} — drop+create manually if intentional`})}for(const o of Object.keys(i))s[o]===void 0&&n.push({kind:"dropIndex",sql:S(e,o),summary:`DROP INDEX ${o}`})},D=(e,i,s)=>{s.push({kind:"createTable",sql:g(i),summary:`CREATE TABLE ${e}`});for(const n of Object.values(i.indexes))s.push({kind:"createIndex",sql:p(e,n),summary:`CREATE INDEX ${n.name} ON ${e}`})},w=(e,i)=>{const s=e?.tables??{},n=[],t=[];for(const[o,r]of Object.entries(i.tables)){const l=s[o];if(l===void 0){D(o,r,n);continue}q(o,l.columns,r.columns,n,t),N(o,l.indexes,r.indexes,n,t)}for(const o of Object.keys(s))i.tables[o]===void 0&&n.push({kind:"dropTable",sql:O(o),summary:`DROP TABLE ${o}`});return{empty:n.length===0&&t.length===0,entries:n,unsupported:t}},U=(e,i,s)=>{const n=[`-- Lunora migration: ${e}`,`-- Generated at ${s}`,"-- 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(`
|
|
7
|
-
`)};export{w as diffSnapshots,C as renderAddColumn,p as renderCreateIndex,g as renderCreateTable,S as renderDropIndex,O as renderDropTable,U as renderMigrationFile,A as validatorKindToSqlType};
|