@lunora/cli
Version:
The Lunora CLI: init, dev, deploy, codegen, migrate, seed, doctor, insights, logs, registry, and the rest of the project commands
6 lines (5 loc) • 3.65 kB
JavaScript
import{quoteIdentifier as u,sqlAffinityForKind as y,frameworkColumnDdl as T,MAX_D1_TABLE_COLUMNS as a,columnRef as $,physicalIndexName as d}from"@lunora/d1/dialect";import{LunoraError as h}from"@lunora/errors";const R=e=>y(e),c=(e,n)=>{const s=[u(e),n.sqlType];return n.nullable||s.push("NOT NULL"),s.join(" ")},E=e=>{const n=Object.entries(e.columns).map(([i,r])=>` ${c(i,r)}`),s=T(),o=s.length+n.length;if(o>a)throw new h("VALIDATION_ERROR",`table "${e.name}" needs ${String(o)} columns, over D1's ${String(a)}-column limit — split the table, or move the extra fields into one object field`);const t=[...s.map(i=>` ${i}`),...n].join(`,
`);return`CREATE TABLE IF NOT EXISTS ${u(e.name)} (
${t}
);`},L=e=>`DROP TABLE IF EXISTS ${u(e)};`,O=(e,n,s)=>`ALTER TABLE ${u(e)} ADD COLUMN ${c(n,s)};`,m=(e,n)=>{const s=n.fields.map(t=>$(t)).join(", ");return`CREATE ${n.unique?"UNIQUE ":""}INDEX IF NOT EXISTS ${d(e,n.name)} ON ${u(e)} (${s});`},g=(e,n)=>`DROP INDEX IF EXISTS ${d(e,n)};`,I=(e,n,s,o,t)=>{s.sqlType!==o.sqlType&&t.push({kind:"columnTypeChange",summary:`column type change on ${e}.${n}: ${s.sqlType} → ${o.sqlType} (write SQL manually)`}),s.nullable!==o.nullable&&t.push({kind:"columnTypeChange",summary:`nullability change on ${e}.${n}: ${s.nullable?"NULL":"NOT NULL"} → ${o.nullable?"NULL":"NOT NULL"} (write SQL manually)`})},q=(e,n,s,o,t)=>{for(const[i,r]of Object.entries(s)){const l=n[i];if(l===void 0){o.push({kind:"addColumn",sql:O(e,i,r),summary:`ADD COLUMN ${e}.${i}`});continue}I(e,i,l,r,t)}for(const i of Object.keys(n))s[i]===void 0&&t.push({kind:"dropColumn",summary:`DROP COLUMN ${e}.${i} (SQLite drop-column requires careful migration — write SQL manually)`})},C=(e,n,s,o,t)=>{for(const[i,r]of Object.entries(s)){const l=n[i];if(l===void 0){o.push({kind:"createIndex",sql:m(e,r),summary:`CREATE INDEX ${i} ON ${e}`});continue}(!(l.fields.length===r.fields.length&&l.fields.every((f,p)=>f===r.fields[p]))||l.unique!==r.unique)&&t.push({kind:"indexRename",summary:`index ${i} changed on ${e} — drop+create manually if intentional`})}for(const i of Object.keys(n))s[i]===void 0&&o.push({kind:"dropIndex",sql:g(e,i),summary:`DROP INDEX ${i}`})},N=(e,n,s)=>{s.push({kind:"createTable",sql:E(n),summary:`CREATE TABLE ${e}`});for(const o of Object.values(n.indexes))s.push({kind:"createIndex",sql:m(e,o),summary:`CREATE INDEX ${o.name} ON ${e}`})},S=(e,n)=>{const s=e?.tables??{},o=[],t=[];for(const[i,r]of Object.entries(n.tables)){const l=s[i];if(l===void 0){N(i,r,o);continue}q(i,l.columns,r.columns,o,t),C(i,l.indexes,r.indexes,o,t)}for(const i of Object.keys(s))n.tables[i]===void 0&&o.push({kind:"dropTable",sql:L(i),summary:`DROP TABLE ${i}`});return{empty:o.length===0&&t.length===0,entries:o,unsupported:t}},k=(e,n,s)=>{const o=[`-- Lunora migration: ${e}`,`-- Generated at ${s}`,"-- This file was produced by `lunora migrate generate`. Review carefully before applying.",""];for(const t of n.entries)o.push(`-- ${t.summary}`,t.sql,"");if(n.unsupported.length>0){o.push("-- ---------------------------------------------------------------","-- The following deltas are NOT auto-generated in v0.1.","-- Write the appropriate SQL below by hand:","--");for(const t of n.unsupported)o.push(`-- * ${t.summary}`);o.push("-- ---------------------------------------------------------------","")}return n.empty&&o.push("-- No changes detected. Re-running `lunora migrate generate` will overwrite this file.",""),o.join(`
`)};export{S as diffSnapshots,O as renderAddColumn,m as renderCreateIndex,E as renderCreateTable,g as renderDropIndex,L as renderDropTable,k as renderMigrationFile,R as validatorKindToSqlType};