@izumisy/kyrage 1.5.5 → 1.5.7

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.
Files changed (2) hide show
  1. package/dist/main.mjs +2 -2
  2. package/package.json +8 -8
package/dist/main.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import{defineCommand as e,runMain as t}from"citty";import n from"zod";import{loadConfig as r}from"c12";import{getContainerRuntimeClient as i}from"testcontainers";import{DEFAULT_MIGRATION_TABLE as a,DummyDriver as o,Kysely as s,Migrator as c,PostgresAdapter as l,PostgresDialect as u,isColumnDataType as ee,sql as d}from"kysely";import{Pool as f}from"pg";import{PostgreSqlContainer as te}from"@testcontainers/postgresql";import*as p from"ramda";import{CockroachDbContainer as ne}from"@testcontainers/cockroachdb";import{createConsola as re}from"consola";import*as ie from"fs/promises";import{join as m}from"path";import{CycleError as ae,Graph as oe,topologicalSort as se}from"graph-data-structure";import{format as ce}from"sql-formatter";var le=`1.5.5`;const h=n.object({type:n.string()}).catchall(n.any()),g=n.object({table:n.string(),name:n.string()}),_=n.object({table:n.string(),column:n.string()}),ue=n.object({...g.shape,columns:n.array(n.string()).readonly()}),de=n.object({...g.shape,columns:n.array(n.string()).readonly()}),v=n.enum([`cascade`,`set null`,`set default`,`restrict`,`no action`]),fe=n.object({...g.shape,columns:n.array(n.string()).readonly(),referencedTable:n.string(),referencedColumns:n.array(n.string()).readonly(),onDelete:v.optional(),onUpdate:v.optional(),inline:n.boolean().optional()}),y=e=>n.object({container:n.object({image:n.string().default(e.defaultImage),name:n.string().optional()})});var b=class{constructor(e,t){this.dialect=e,this.containerFactory=t}async setup(e,t){return new pe({dialect:this.dialect,manageType:t,containerName:e.container.name,containerFactory:()=>this.containerFactory(e.container.image)})}async hasExisting(e){return e===`dev-start`?w(this.dialect):!1}async cleanup(){await T()}};const x=`kyrage.dialect`,S=`kyrage.managed`,C=`kyrage.managed-by`;var pe=class{constructor(e){this.options=e,this.startedContainer=null,this.container=this.setupContainer()}setupContainer(){let e=this.options.containerFactory();return e.withLabels({[x]:this.options.dialect,[S]:`true`,[C]:this.options.manageType}),this.options.manageType===`dev-start`&&e.withReuse(),this.options.containerName&&e.withName(this.options.containerName),e}async start(){this.startedContainer=await this.container.start()}async stop(){this.startedContainer&&=(await this.startedContainer.stop(),null)}async remove(){await T(),this.startedContainer=null}getConnectionString(){if(!this.startedContainer)throw Error(`Container is not started`);return this.startedContainer.getConnectionUri()}async getStatus(){let e=await(await i()).container.fetchByLabel(x,this.options.dialect,{status:[`running`]});if(e){let t=await e.inspect();return{type:`container`,imageName:t.Config.Image,containerID:t.Id}}return{type:`unavailable`}}async isAvailable(){return(await this.getStatus()).type===`container`}};const w=async e=>(await(await i()).container.list()).some(t=>t.Labels[S]===`true`&&t.Labels[C]===`dev-start`&&t.Labels[x]===e&&t.State===`running`),T=async()=>{let e=await i(),t=(await e.container.list()).filter(e=>e.Labels[S]===`true`).map(e=>e.Id);await Promise.allSettled(t.map(async t=>e.container.getById(t).remove({force:!0})))},me=n.object({type:n.string(),primaryKey:n.boolean().optional().default(!1),notNull:n.boolean().optional().default(!1),unique:n.boolean().optional().default(!1),defaultSql:n.string().optional()}),he=n.object({tableName:n.string(),columns:n.record(n.string(),me)}),ge=n.object({...g.shape,columns:n.array(n.string()).readonly(),unique:n.boolean().default(!1)}),_e=n.enum([`postgres`,`cockroachdb`]),ve=n.object({dialect:_e,connectionString:n.string()}),ye=n.union([y({defaultImage:``})]),be=n.object({database:ve,dev:ye.optional(),tables:n.array(he).readonly(),indexes:n.array(ge).readonly(),primaryKeyConstraints:n.array(ue).readonly(),uniqueConstraints:n.array(de).readonly(),foreignKeyConstraints:n.array(fe).readonly()}),xe=async()=>{let e=await r({name:`kyrage`});return be.parse(e.config)},Se=(e,t)=>{let n=e=>t=>p.any(p.whereEq({name:t.name,table:t.table}),e),[r,i]=p.partition(n(e.uniqueConstraints),t.constraints.unique),[a,o]=p.partition(n(e.indexes),t.indexes),s=p.reject(n(a),i),c=p.reject(n(r),o);return{indexes:[...a,...c],uniqueConstraints:[...r,...s]}};var Ce=class{getName(){return`postgres`}createKyselyDialect(e){return new u({pool:new f({connectionString:e})})}createIntrospectionDriver(e){return{convertTypeName:D,introspect:E(e)}}createDevDatabaseProvider(){return new b(this.getName(),e=>new te(e))}parseDevDatabaseConfig(e){return y({defaultImage:`postgres:16`}).parse(e)}async hasReusableDevDatabase(){return w(this.getName())}};const E=e=>async t=>{await using n=e.getDB();let[r,i,a]=await Promise.all([we(n),Te(n),Ee(n)]),{indexes:o,uniqueConstraints:s}=Se(t.config,{indexes:i,constraints:a});return{tables:r,indexes:o,constraints:{...a,unique:s}}},D=e=>({bool:`boolean`,int2:`smallint`,int4:`integer`,int8:`bigint`})[e]??e,we=async e=>{let{rows:t}=await d`
1
+ import{defineCommand as e,runMain as t}from"citty";import n from"zod";import{loadConfig as r}from"c12";import{getContainerRuntimeClient as i}from"testcontainers";import{DEFAULT_MIGRATION_TABLE as a,DummyDriver as o,Kysely as s,Migrator as c,PostgresAdapter as l,PostgresDialect as u,isColumnDataType as ee,sql as d}from"kysely";import{Pool as f}from"pg";import{PostgreSqlContainer as te}from"@testcontainers/postgresql";import*as p from"ramda";import{CockroachDbContainer as ne}from"@testcontainers/cockroachdb";import{createConsola as re}from"consola";import*as ie from"fs/promises";import{join as m}from"path";import{CycleError as ae,Graph as oe,topologicalSort as se}from"graph-data-structure";import{format as ce}from"sql-formatter";var le=`1.5.7`;const h=n.object({type:n.string()}).catchall(n.any()),g=n.object({table:n.string(),name:n.string()}),_=n.object({table:n.string(),column:n.string()}),ue=n.object({...g.shape,columns:n.array(n.string()).readonly()}),de=n.object({...g.shape,columns:n.array(n.string()).readonly()}),v=n.enum([`cascade`,`set null`,`set default`,`restrict`,`no action`]),fe=n.object({...g.shape,columns:n.array(n.string()).readonly(),referencedTable:n.string(),referencedColumns:n.array(n.string()).readonly(),onDelete:v.optional(),onUpdate:v.optional(),inline:n.boolean().optional()}),y=e=>n.object({container:n.object({image:n.string().default(e.defaultImage),name:n.string().optional()})});var b=class{constructor(e,t){this.dialect=e,this.containerFactory=t}async setup(e,t){return new pe({dialect:this.dialect,manageType:t,containerName:e.container.name,containerFactory:()=>this.containerFactory(e.container.image)})}async hasExisting(e){return e===`dev-start`?w(this.dialect):!1}async cleanup(){await T()}};const x=`kyrage.dialect`,S=`kyrage.managed`,C=`kyrage.managed-by`;var pe=class{constructor(e){this.options=e,this.startedContainer=null,this.container=this.setupContainer()}setupContainer(){let e=this.options.containerFactory();return e.withLabels({[x]:this.options.dialect,[S]:`true`,[C]:this.options.manageType}),this.options.manageType===`dev-start`&&e.withReuse(),this.options.containerName&&e.withName(this.options.containerName),e}async start(){this.startedContainer=await this.container.start()}async stop(){this.startedContainer&&=(await this.startedContainer.stop(),null)}async remove(){await T(),this.startedContainer=null}getConnectionString(){if(!this.startedContainer)throw Error(`Container is not started`);return this.startedContainer.getConnectionUri()}async getStatus(){let e=await(await i()).container.fetchByLabel(x,this.options.dialect,{status:[`running`]});if(e){let t=await e.inspect();return{type:`container`,imageName:t.Config.Image,containerID:t.Id}}return{type:`unavailable`}}async isAvailable(){return(await this.getStatus()).type===`container`}};const w=async e=>(await(await i()).container.list()).some(t=>t.Labels[S]===`true`&&t.Labels[C]===`dev-start`&&t.Labels[x]===e&&t.State===`running`),T=async()=>{let e=await i(),t=(await e.container.list()).filter(e=>e.Labels[S]===`true`).map(e=>e.Id);await Promise.allSettled(t.map(async t=>e.container.getById(t).remove({force:!0})))},me=n.object({type:n.string(),primaryKey:n.boolean().optional().default(!1),notNull:n.boolean().optional().default(!1),unique:n.boolean().optional().default(!1),defaultSql:n.string().optional()}),he=n.object({tableName:n.string(),columns:n.record(n.string(),me)}),ge=n.object({...g.shape,columns:n.array(n.string()).readonly(),unique:n.boolean().default(!1)}),_e=n.enum([`postgres`,`cockroachdb`]),ve=n.object({dialect:_e,connectionString:n.string()}),ye=n.union([y({defaultImage:``})]),be=n.object({database:ve,dev:ye.optional(),tables:n.array(he).readonly(),indexes:n.array(ge).readonly(),primaryKeyConstraints:n.array(ue).readonly(),uniqueConstraints:n.array(de).readonly(),foreignKeyConstraints:n.array(fe).readonly()}),xe=async()=>{let e=await r({name:`kyrage`});return be.parse(e.config)},Se=(e,t)=>{let n=e=>t=>p.any(p.whereEq({name:t.name,table:t.table}),e),[r,i]=p.partition(n(e.uniqueConstraints),t.constraints.unique),[a,o]=p.partition(n(e.indexes),t.indexes),s=p.reject(n(a),i),c=p.reject(n(r),o);return{indexes:[...a,...c],uniqueConstraints:[...r,...s]}};var Ce=class{getName(){return`postgres`}createKyselyDialect(e){return new u({pool:new f({connectionString:e})})}createIntrospectionDriver(e){return{convertTypeName:D,introspect:E(e)}}createDevDatabaseProvider(){return new b(this.getName(),e=>new te(e))}parseDevDatabaseConfig(e){return y({defaultImage:`postgres:16`}).parse(e)}async hasReusableDevDatabase(){return w(this.getName())}};const E=e=>async t=>{await using n=e.getDB();let[r,i,a]=await Promise.all([we(n),Te(n),Ee(n)]),{indexes:o,uniqueConstraints:s}=Se(t.config,{indexes:i,constraints:a});return{tables:r,indexes:o,constraints:{...a,unique:s}}},D=e=>({bool:`boolean`,int2:`smallint`,int4:`integer`,int8:`bigint`})[e]??e,we=async e=>{let{rows:t}=await d`
2
2
  SELECT
3
3
  n.nspname AS table_schema,
4
4
  c.relname AS table_name,
@@ -89,7 +89,7 @@ import{defineCommand as e,runMain as t}from"citty";import n from"zod";import{loa
89
89
  GROUP BY n.nspname, t.relname, c.conname, c.contype, c.oid, c.conkey, t.oid,
90
90
  rt.relname, c.confkey, c.confdeltype, c.confupdtype
91
91
  ORDER BY t.relname, c.conname;
92
- `.$castTo().execute(e);return{primaryKey:t.filter(e=>e.type===`PRIMARY KEY`),unique:t.filter(e=>e.type===`UNIQUE`),foreignKey:t.filter(e=>e.type===`FOREIGN KEY`).map(e=>{let{referenced_table:t,referenced_columns:n,on_delete:r,on_update:i,...a}=e;return{...a,referencedTable:t,referencedColumns:n,onDelete:r,onUpdate:i}})}};var De=class{getName(){return`cockroachdb`}createKyselyDialect(e){return new ke({pool:new f({connectionString:e})})}createIntrospectionDriver(e){let t=[`rowid`];return{convertTypeName:D,introspect:async n=>{let r=await E(e)(n);return{tables:r.tables.filter(e=>!t.includes(e.name)),indexes:r.indexes,constraints:r.constraints}}}}createDevDatabaseProvider(){return new b(this.getName(),e=>new ne(e))}parseDevDatabaseConfig(e){return y({defaultImage:`cockroachdb/cockroach:latest-v24.3`}).parse(e)}async hasReusableDevDatabase(){return w(this.getName())}},Oe=class extends l{async acquireMigrationLock(e,t){await e.selectFrom(t.lockTable).selectAll().forUpdate().execute()}},ke=class extends u{createAdapter(){return new Oe}};const Ae={postgres:new Ce,cockroachdb:new De},O=e=>{let t=Ae[e];if(!t)throw Error(`Unsupported dialect: ${e}`);return t};var je=class extends o{constructor(e){super(),this.queries=e}async acquireConnection(){return new Me(this.queries)}},Me=class{constructor(e){this.queries=e}async executeQuery(e){let t=e.query.kind;if(t===`CreateTableNode`||t===`DropTableNode`||t===`AlterTableNode`){if(e.query.table.table.identifier.name.startsWith(`kysely_`))return{rows:[]};this.queries.push(e)}else (t===`CreateIndexNode`||t===`DropIndexNode`)&&this.queries.push(e);return{rows:[]}}async*streamQuery(){}};const k=e=>new Ne({databaseProps:e.database,options:e.options});var Ne=class{constructor(e){this.constructorProps=e}getDB(e){let t=O(this.constructorProps.databaseProps.dialect).createKyselyDialect(this.constructorProps.databaseProps.connectionString);return new Pe({dialect:{createAdapter:()=>t.createAdapter(),createDriver:()=>t.createDriver(),createIntrospector:e=>t.createIntrospector(e),createQueryCompiler:()=>t.createQueryCompiler()}},{isPlan:e?.plan===!0})}getDialect(){return this.constructorProps.databaseProps.dialect}},Pe=class extends s{constructor(e,t){let n=[];super({dialect:{...e.dialect,createDriver:()=>t.isPlan?new je(n):e.dialect.createDriver()}}),this.plannedQueries=[],this.plannedQueries=n}getPlannedQueries(){return this.plannedQueries}};const A={stdout:e=>console.log(e),reporter:{...re({stdout:process.stderr})}},j={stdout:()=>void 0,reporter:{info:()=>void 0,warn:()=>void 0,success:()=>void 0,log:()=>void 0,error:()=>void 0}};async function M(){let e=await xe();return{client:k({database:e.database}),logger:A,fs:ie,config:e}}const N=e=>{if(!ee(e))throw Error(`Unsupported data type: ${e}`)},P=e=>e,Fe=P({typeName:`create_table`,schema:n.object({type:n.literal(`create_table`),table:n.string(),columns:n.record(n.string(),h)}),execute:async(e,t)=>{let n=e.schema.createTable(t.table);n=F(n,t.columns),await n.execute()}}),Ie=(e,t)=>({type:`create_table`,table:e,columns:t});function F(e,t){let n=e;for(let[e,r]of Object.entries(t)){let t=r.type;N(t),n=n.addColumn(e,t,e=>{let t=e;return r.notNull&&(t=t.notNull()),typeof r.defaultSql==`string`&&(t=t.defaultTo(d.raw(r.defaultSql))),t})}return n}const Le=P({typeName:`create_table_with_constraints`,schema:n.object({type:n.literal(`create_table_with_constraints`),table:n.string(),columns:n.record(n.string(),h),constraints:n.object({primaryKey:n.object({name:n.string(),columns:n.array(n.string()).readonly()}).optional(),unique:n.array(n.object({name:n.string(),columns:n.array(n.string()).readonly()})).readonly().optional(),foreignKeys:n.array(n.object({name:n.string(),columns:n.array(n.string()).readonly(),referencedTable:n.string(),referencedColumns:n.array(n.string()).readonly(),onDelete:v.optional(),onUpdate:v.optional(),inline:n.boolean().optional()})).readonly().optional()}).optional()}),execute:async(e,t)=>{let n=e.schema.createTable(t.table);if(n=F(n,t.columns),t.constraints){let{primaryKey:e,unique:r,foreignKeys:i}=t.constraints;if(e&&(n=n.addPrimaryKeyConstraint(e.name,e.columns)),r)for(let e of r)n=n.addUniqueConstraint(e.name,e.columns);if(i)for(let e of i)n=n.addForeignKeyConstraint(e.name,e.columns,e.referencedTable,e.referencedColumns,t=>{let n=t;return e.onDelete&&(n=n.onDelete(e.onDelete)),e.onUpdate&&(n=n.onUpdate(e.onUpdate)),n})}await n.execute()}}),Re=(e,t,n)=>({type:`create_table_with_constraints`,table:e,columns:t,constraints:{primaryKey:n?.primaryKey,unique:n?.unique??[],foreignKeys:n?.foreignKeys??[]}}),ze=P({typeName:`drop_table`,schema:n.object({type:n.literal(`drop_table`),table:n.string()}),execute:async(e,t)=>{await e.schema.dropTable(t.table).execute()}}),Be=e=>({type:`drop_table`,table:e}),Ve=P({typeName:`add_column`,schema:n.object({..._.shape,type:n.literal(`add_column`),attributes:h}),execute:async(e,t)=>{let n=t.attributes.type;N(n),await e.schema.alterTable(t.table).addColumn(t.column,n,e=>{let n=e;return t.attributes.notNull&&(n=n.notNull()),typeof t.attributes.defaultSql==`string`&&(n=n.defaultTo(d.raw(t.attributes.defaultSql))),n}).execute()}}),He=(e,t)=>({...e,type:`add_column`,attributes:t}),Ue=P({typeName:`drop_column`,schema:n.object({..._.shape,type:n.literal(`drop_column`),attributes:h}),execute:async(e,t)=>{await e.schema.alterTable(t.table).dropColumn(t.column).execute()}}),We=(e,t)=>({...e,type:`drop_column`,attributes:t}),Ge=P({typeName:`alter_column`,schema:n.object({..._.shape,type:n.literal(`alter_column`),before:h,after:h}),execute:async(e,t)=>{let{table:n,column:r,before:i,after:a}=t;if(i.type!==a.type){let t=a.type;N(t),await e.schema.alterTable(n).alterColumn(r,e=>e.setDataType(t)).execute()}a.notNull!==i.notNull&&(a.notNull?await e.schema.alterTable(n).alterColumn(r,e=>e.setNotNull()).execute():await e.schema.alterTable(n).alterColumn(r,e=>e.dropNotNull()).execute())}}),Ke=(e,t,n)=>({...e,type:`alter_column`,before:t,after:n}),qe=P({typeName:`create_index`,schema:n.object({...g.shape,type:n.literal(`create_index`),columns:n.array(n.string()).readonly(),unique:n.boolean()}),execute:async(e,t)=>{let n=e.schema.createIndex(t.name).on(t.table);for(let e of t.columns)n=n.column(e);t.unique&&(n=n.unique()),await n.execute()}}),I=e=>({...e,type:`create_index`}),Je=P({typeName:`drop_index`,schema:n.object({...g.shape,type:n.literal(`drop_index`)}),execute:async(e,t)=>{await e.schema.dropIndex(t.name).execute()}}),L=e=>({...e,type:`drop_index`}),Ye=P({typeName:`create_primary_key_constraint`,schema:n.object({...ue.shape,type:n.literal(`create_primary_key_constraint`)}),execute:async(e,t)=>{await e.schema.alterTable(t.table).addPrimaryKeyConstraint(t.name,t.columns).execute()}}),R=e=>({...e,type:`create_primary_key_constraint`}),Xe=P({typeName:`drop_primary_key_constraint`,schema:n.object({...g.shape,type:n.literal(`drop_primary_key_constraint`)}),execute:async(e,t)=>{await e.schema.alterTable(t.table).dropConstraint(t.name).execute()}}),z=e=>({...e,type:`drop_primary_key_constraint`}),Ze=P({typeName:`create_unique_constraint`,schema:n.object({...de.shape,type:n.literal(`create_unique_constraint`)}),execute:async(e,t)=>{await e.schema.alterTable(t.table).addUniqueConstraint(t.name,t.columns).execute()}}),B=e=>({...e,type:`create_unique_constraint`}),Qe=P({typeName:`drop_unique_constraint`,schema:n.object({...g.shape,type:n.literal(`drop_unique_constraint`)}),execute:async(e,t)=>{await e.schema.alterTable(t.table).dropConstraint(t.name).execute()}}),V=e=>({...e,type:`drop_unique_constraint`}),$e=P({typeName:`create_foreign_key_constraint`,schema:n.object({...fe.shape,type:n.literal(`create_foreign_key_constraint`)}),execute:async(e,t)=>{let n=e.schema.alterTable(t.table).addForeignKeyConstraint(t.name,t.columns,t.referencedTable,t.referencedColumns);t.onDelete&&(n=n.onDelete(t.onDelete)),t.onUpdate&&(n=n.onUpdate(t.onUpdate)),await n.execute()}}),H=(e,t)=>({...e,...t,type:`create_foreign_key_constraint`}),et=P({typeName:`drop_foreign_key_constraint`,schema:n.object({...g.shape,type:n.literal(`drop_foreign_key_constraint`)}),execute:async(e,t)=>{await e.schema.alterTable(t.table).dropConstraint(t.name).execute()}}),U=e=>({...e,type:`drop_foreign_key_constraint`}),W=[Le,Fe,ze,Ve,Ue,Ge,qe,Je,Ye,Xe,Ze,Qe,$e,et],tt=n.union(W.map(e=>e.schema));async function nt(e,t){return await rt(t.type)(e,t)}function rt(e){let t=W.find(t=>t.typeName===e);if(!t)throw Error(`Unknown operation type: ${e}`);return t.execute}const it=e=>{let t=new Set;return e.forEach(e=>{e.type===`drop_table`&&t.add(e.table)}),t.size===0?e:e.filter(e=>e.type===`drop_table`?!0:!t.has(e.table))},at=e=>{let t=new Set;if(e.forEach(e=>{e.type===`create_table`&&t.add(e.table)}),t.size===0)return e;let n=new Map,r=new Map,i=[];e.forEach(e=>{e.type===`create_table`&&n.set(e.table,e)}),e.forEach(e=>{switch(e.type){case`create_table`:return;case`create_primary_key_constraint`:case`create_unique_constraint`:if(t.has(e.table)){let t=r.get(e.table)||[];r.set(e.table,[...t,e])}else i.push(e);break;case`create_foreign_key_constraint`:if(t.has(e.table)&&e.inline!==!1){let t=n.get(e.table),i=e.columns.filter(e=>!(e in t.columns));if(i.length>0)throw Error(`Foreign key constraint "${e.name}" references non-existent columns: ${i.join(`, `)}`);let a=r.get(e.table)||[];r.set(e.table,[...a,e])}else i.push(e);break;default:i.push(e);break}});let a=[];return n.forEach((e,t)=>{let n=r.get(t)||[];if(n.length===0){a.push(e);return}let i={unique:[],foreignKeys:[]};n.forEach(e=>{switch(e.type){case`create_primary_key_constraint`:i.primaryKey=e;break;case`create_unique_constraint`:i.unique.push(e);break;case`create_foreign_key_constraint`:i.foreignKeys.push(e);break}}),a.push(Re(e.table,e.columns,i))}),[...a,...i]},ot=e=>{let t=new Set;return e.forEach(e=>{(e.type===`drop_unique_constraint`||e.type===`drop_primary_key_constraint`)&&t.add(`${e.table}.${e.name}`)}),e.filter(e=>{if(e.type===`drop_index`){let n=`${e.table}.${e.name}`;if(t.has(n))return!1}return!0})},G=e=>`table`in e?e.table:null,st=e=>{let t=new Set;return e.forEach(e=>{let n=G(e);n&&t.add(n)}),t},ct=e=>{switch(e.type){case`create_foreign_key_constraint`:return[{table:e.table,referencedTable:e.referencedTable}];case`create_table_with_constraints`:return(e.constraints?.foreignKeys||[]).map(t=>({table:e.table,referencedTable:t.referencedTable}));default:return[]}},lt=e=>{let t=new oe;return e.forEach(e=>ct(e).forEach(n=>{n.table!==n.referencedTable&&(e.type!==`create_foreign_key_constraint`||e.inline!==!1)&&t.addEdge(n.referencedTable,n.table)})),t},ut=(e,t)=>{try{let n=se(lt(t)),r=new Set(n);return[...Array.from(e).filter(e=>!r.has(e)).sort(),...n]}catch(e){throw e instanceof ae?Error(`Circular dependency detected in foreign key constraints. Please resolve this by setting 'inline: false' for one of the foreign key constraints in each circular relationship.`):e}},dt=e=>new Map(e.map((e,t)=>[e,t])),ft=e=>(t,n)=>{let r=K[t.type],i=K[n.type];if(r!==i)return r-i;let a=G(t),o=G(n);if(a&&o){let t=e.get(a)??2**53-1,n=e.get(o)??2**53-1;if(t!==n)return t-n}return(a||``).localeCompare(o||``)},K={drop_foreign_key_constraint:0,drop_unique_constraint:1,drop_primary_key_constraint:2,drop_index:3,drop_column:4,drop_table:5,create_table_with_constraints:6,create_table:7,add_column:8,alter_column:9,create_index:10,create_primary_key_constraint:11,create_unique_constraint:12,create_foreign_key_constraint:13},pt=p.pipe(it,at,ot,e=>p.sort(ft(p.pipe(st,t=>ut(t,e),dt)(e)),e)),mt=e=>({getMigrations:async()=>{let t=await e.migrationsResolver(),n={};return t.forEach(e=>{n[e.id]={up:async t=>{for(let n of pt(e.diff.operations))await nt(t,n)}}}),n}}),ht=n.object({operations:n.array(tt).readonly()}),gt=n.object({id:n.string(),version:n.string(),diff:ht}),q=`migrations`,_t=async e=>{let{fs:t}=e;try{let e=(await t.readdir(q)).filter(e=>e.endsWith(`.json`)).map(async e=>gt.parse(JSON.parse(await t.readFile(m(q,e),`utf-8`))));return await Promise.all(e)}catch(e){if(e instanceof Object&&`code`in e&&e.code===`ENOENT`)return[];throw e}},J=async e=>{let{client:t,fs:n}=e;await using r=t.getDB();let i=await _t({fs:n});if(!(await r.introspection.getTables({withInternalKyselyTables:!0})).map(e=>e.name).includes(a))return i;let o=await r.selectFrom(a).select([`name`,`timestamp`]).$narrowType().execute();return i.filter(e=>!o.some(t=>t.name===e.id))};async function Y(e,t){let{client:n,logger:r}=e,{reporter:i}=r;await using a=n.getDB({plan:t.plan});let{results:o,error:s}=await new c({db:a,provider:mt({migrationsResolver:async()=>t.plan?await J(e):await _t(e),options:{plan:t.plan}})}).migrateToLatest(),l=a.getPlannedQueries();if(l.length>0){l.forEach(e=>{r.stdout(t.pretty?ce(e.sql):e.sql)});return}if(o&&o.length>0?o.forEach(e=>{e.status===`Error`?i.error(`Migration failed: ${e.migrationName}`):e.status===`Success`&&i.success(`Migration applied: ${e.migrationName}`)}):i.info(`No migrations to run`),s)throw s instanceof Error?s:Error(`Migration error: ${s}`)}const vt=e({meta:{name:`apply`,description:`Run migrations to sync database schema`},args:{plan:{type:`boolean`,description:`Plan the migration without applying it`,default:!1},pretty:{type:`boolean`,description:`Pretty print the migration SQL (only for --plan)`,default:!1}},run:async e=>{try{await Y(await M(),{plan:e.args.plan,pretty:e.args.pretty})}catch(e){A.reporter.error(e),process.exit(1)}}}),X=()=>({added:(e,t,n)=>p.pipe(p.difference(t),p.map(n))(e),removed:(e,t,n)=>p.pipe(p.difference(e),p.map(n))(t),changed:(e,t,n,r)=>p.pipe(p.intersection(e),p.filter(n),p.map(r))(t)}),Z=p.prop(`name`),yt=p.eqBy(e=>[e.type,e.notNull??!1,e.primaryKey??!1,e.unique??!1]);function bt(e,t){let n=[],r=X(),i=e.columns,a=t.columns,o=Object.keys(i),s=Object.keys(a);return r.added(o,s,e=>({column:e,attributes:a[e]})).forEach(t=>{n.push(He({table:e.name,column:t.column},t.attributes))}),r.removed(o,s,e=>({column:e,attributes:i[e]})).forEach(t=>{n.push(We({table:e.name,column:t.column},t.attributes))}),r.changed(o,s,e=>!yt(i[e],a[e]),e=>({column:e,before:i[e],after:a[e]})).forEach(t=>{n.push(Ke({table:e.name,column:t.column},t.before,t.after))}),n}function xt(e){let{current:t,ideal:n}=e,r=[],i=X(),a=p.map(Z,t),o=p.map(Z,n);return i.added(a,o,e=>n.find(t=>t.name===e)).forEach(e=>{r.push(Ie(e.name,e.columns))}),i.removed(a,o,p.identity).forEach(e=>{r.push(Be(e))}),p.filter(e=>n.some(t=>t.name===e.name))(t).forEach(e=>{let t=n.find(t=>t.name===e.name);r.push(...bt(e,t))}),r}function St(e){let{current:t,ideal:n}=e,r=[],i=X(),a=e=>`${e.table}:${e.name}`,o=new Map(t.map(e=>[a(e),e])),s=new Map(n.map(e=>[a(e),e])),c=Array.from(o.keys()),l=Array.from(s.keys());return i.added(c,l,e=>s.get(e)).forEach(e=>{r.push(I(e))}),i.removed(c,l,e=>{let t=o.get(e);return{table:t.table,name:t.name}}).forEach(e=>{r.push(L(e))}),i.changed(c,l,e=>{let t=o.get(e),n=s.get(e);return!p.equals(t.columns,n.columns)||t.unique!==n.unique},e=>({current:o.get(e),ideal:s.get(e)})).forEach(({current:e,ideal:t})=>{r.push(L(e)),r.push(I(t))}),r}function Ct(e){let{current:t,ideal:n}=e,r=[],i=X(),a=e=>`${e.table}:${e.name}`,o=new Map(t.map(e=>[a(e),e])),s=new Map(n.map(e=>[a(e),e])),c=Array.from(o.keys()),l=Array.from(s.keys());return i.added(c,l,e=>s.get(e)).forEach(e=>{r.push(R(e))}),i.removed(c,l,e=>{let t=o.get(e);return{table:t.table,name:t.name}}).forEach(e=>{r.push(z(e))}),i.changed(c,l,e=>{let t=o.get(e),n=s.get(e);return!p.equals(t.columns,n.columns)},e=>({current:o.get(e),ideal:s.get(e)})).forEach(({current:e,ideal:t})=>{r.push(z(e)),r.push(R(t))}),r}function wt(e){let{current:t,ideal:n}=e,r=[],i=X(),a=e=>`${e.table}:${e.name}`,o=new Map(t.map(e=>[a(e),e])),s=new Map(n.map(e=>[a(e),e])),c=Array.from(o.keys()),l=Array.from(s.keys());return i.added(c,l,e=>s.get(e)).forEach(e=>{r.push(B(e))}),i.removed(c,l,e=>{let t=o.get(e);return{table:t.table,name:t.name}}).forEach(e=>{r.push(V(e))}),i.changed(c,l,e=>{let t=o.get(e),n=s.get(e);return!p.equals(t.columns,n.columns)},e=>({current:o.get(e),ideal:s.get(e)})).forEach(({current:e,ideal:t})=>{r.push(V(e)),r.push(B(t))}),r}function Tt(e){let t=[],n=X(),r=e.current.map(Z),i=e.ideal.map(Z);return t.push(...n.added(r,i,t=>{let{table:n,name:r,...i}=e.ideal.find(e=>e.name===t);return H({table:n,name:r},i)})),t.push(...n.removed(r,i,t=>U(e.current.find(e=>e.name===t)))),t.push(...n.changed(r,i,t=>{let n=e.current.find(e=>e.name===t),r=e.ideal.find(e=>e.name===t);return!n||!r?!1:!(p.equals(n.columns,r.columns)&&n.referencedTable===r.referencedTable&&p.equals(n.referencedColumns,r.referencedColumns)&&n.onDelete===r.onDelete&&n.onUpdate===r.onUpdate)},t=>{let n=e.current.find(e=>e.name===t),{table:r,name:i,...a}=e.ideal.find(e=>e.name===t);return[U(n),H({table:r,name:i},a)]}).flat()),t}function Et(e){let t=xt({current:e.current.tables,ideal:e.ideal.tables}),n=St({current:e.current.indexes,ideal:e.ideal.indexes}),r=Ct({current:e.current.primaryKeyConstraints,ideal:e.ideal.primaryKeyConstraints}),i=wt({current:e.current.uniqueConstraints,ideal:e.ideal.uniqueConstraints}),a=Tt({current:e.current.foreignKeyConstraints,ideal:e.ideal.foreignKeyConstraints});return{operations:[...t,...n,...r,...i,...a]}}const Dt=e=>{let t=O(e.getDialect()).createIntrospectionDriver(e);return{introspect:async n=>{await using r=e.getDB();let i=await r.introspection.getTables(),{tables:a,indexes:o,constraints:s}=await t.introspect({config:n}),c=()=>i.map(e=>{let n={};for(let r of e.columns){let i=a.find(t=>t.table===e.name&&t.name===r.name);i&&(n[r.name]={schema:e.schema,table:e.name,name:r.name,dataType:t.convertTypeName(r.dataType),default:i.default??null,characterMaximumLength:i.characterMaximumLength??null,notNull:!r.isNullable})}return{schema:e.schema,name:e.name,columns:n}}),l=e=>!e.table.startsWith(`kysely_`);return{tables:c(),indexes:(()=>o.filter(l))(),constraints:(()=>({primaryKey:s.primaryKey.filter(l),unique:s.unique.filter(l),foreignKey:s.foreignKey.filter(l)}))()}}}},Q=async(e,t,n)=>{let r=O(t);return{manageType:n,instance:await r.createDevDatabaseProvider().setup(r.parseDevDatabaseConfig(e),n)}};async function Ot(e,t){let{config:n}=e,r=O(n.database.dialect);switch(t.mode){case`dev-start`:{let{instance:e,manageType:t}=await Q(n.dev,n.database.dialect,`dev-start`);return{manageType:t,manager:e,result:{reused:await e.isAvailable()}}}case`generate-dev`:{let e=await r.hasReusableDevDatabase(),{instance:t,manageType:i}=await Q(n.dev,n.database.dialect,e?`dev-start`:`one-off`);return{manageType:i,manager:t,result:{reused:e}}}}}async function kt(e,t){let{config:n}=e,{reporter:r}=t.logger||j;if(!n.dev)throw Error(`Dev database configuration is required`);let{manageType:i,manager:a,result:o}=await Ot(e,t);o.reused?r.info(`🔄 Reusing existing dev database...`):r.info(`🚀 Starting dev database...`),await a.start(),r.success(`Dev database started: ${n.database.dialect}`);let s=k({database:{dialect:n.database.dialect,connectionString:a.getConnectionString()}}),c=await J(e);return c.length>0?(r.info(`🔄 Applying ${c.length} pending migrations...`),await Y({client:s,logger:j,fs:e.fs,config:n},{plan:!1,pretty:!1}),r.success(`Applied ${c.length} migrations`)):r.info(`No pending migrations found`),{client:s,manager:a,cleanup:async()=>{switch(t.mode){case`dev-start`:r.success(`Persistent dev database ready: `+n.database.dialect);break;case`generate-dev`:i===`dev-start`?r.info(`Dev start container remains running`):(await a.stop(),r.success(`Temporary dev database stopped`));break}}}}async function At(e,t){let{logger:n,config:r,fs:i}=e,{reporter:a}=n;t.squash&&await jt(e);let{client:o,cleanup:s}=t.dev?await kt(e,{mode:`generate-dev`,logger:n}):{client:e.client,cleanup:async()=>void 0};try{if(!t.ignorePending){let n=await J(e);if(n.length>0)if(t.dev)a.info(`Dev database has ${n.length} pending migrations. These will be applied automatically as baseline.`);else{a.warn([`There are pending migrations: ${n.map(e=>e.id).join(`, `)}`,`Please apply them first before generating a new migration.`,`Otherwise, use --ignore-pending to skip this check.`].join(`
92
+ `.$castTo().execute(e);return{primaryKey:t.filter(e=>e.type===`PRIMARY KEY`),unique:t.filter(e=>e.type===`UNIQUE`),foreignKey:t.filter(e=>e.type===`FOREIGN KEY`).map(e=>{let{referenced_table:t,referenced_columns:n,on_delete:r,on_update:i,...a}=e;return{...a,referencedTable:t,referencedColumns:n,onDelete:r,onUpdate:i}})}};var De=class{getName(){return`cockroachdb`}createKyselyDialect(e){return new ke({pool:new f({connectionString:e})})}createIntrospectionDriver(e){let t=[`rowid`];return{convertTypeName:D,introspect:async n=>{let r=await E(e)(n);return{tables:r.tables.filter(e=>!t.includes(e.name)),indexes:r.indexes,constraints:r.constraints}}}}createDevDatabaseProvider(){return new b(this.getName(),e=>new ne(e))}parseDevDatabaseConfig(e){return y({defaultImage:`cockroachdb/cockroach:latest-v24.3`}).parse(e)}async hasReusableDevDatabase(){return w(this.getName())}},Oe=class extends l{async acquireMigrationLock(e,t){await e.selectFrom(t.lockTable).selectAll().forUpdate().execute()}},ke=class extends u{createAdapter(){return new Oe}};const Ae={postgres:new Ce,cockroachdb:new De},O=e=>{let t=Ae[e];if(!t)throw Error(`Unsupported dialect: ${e}`);return t};var je=class extends o{constructor(e){super(),this.queries=e}async acquireConnection(){return new Me(this.queries)}},Me=class{constructor(e){this.queries=e}async executeQuery(e){let t=e.query.kind;if(t===`CreateTableNode`||t===`DropTableNode`||t===`AlterTableNode`){if(e.query.table.table.identifier.name.startsWith(`kysely_`))return{rows:[]};this.queries.push(e)}else (t===`CreateIndexNode`||t===`DropIndexNode`)&&this.queries.push(e);return{rows:[]}}async*streamQuery(){}};const k=e=>new Ne({databaseProps:e.database,options:e.options});var Ne=class{constructor(e){this.constructorProps=e}getDB(e){let t=O(this.constructorProps.databaseProps.dialect).createKyselyDialect(this.constructorProps.databaseProps.connectionString);return new Pe({dialect:{createAdapter:()=>t.createAdapter(),createDriver:()=>t.createDriver(),createIntrospector:e=>t.createIntrospector(e),createQueryCompiler:()=>t.createQueryCompiler()}},{isPlan:e?.plan===!0})}getDialect(){return this.constructorProps.databaseProps.dialect}},Pe=class extends s{constructor(e,t){let n=[];super({dialect:{...e.dialect,createDriver:()=>t.isPlan?new je(n):e.dialect.createDriver()}}),this.plannedQueries=[],this.plannedQueries=n}getPlannedQueries(){return this.plannedQueries}};const A={stdout:e=>console.log(e),reporter:{...re({stdout:process.stderr})}},j={stdout:()=>void 0,reporter:{info:()=>void 0,warn:()=>void 0,success:()=>void 0,log:()=>void 0,error:()=>void 0}};async function M(){let e=await xe();return{client:k({database:e.database}),logger:A,fs:ie,config:e}}const N=e=>{if(!ee(e))throw Error(`Unsupported data type: ${e}`)},P=e=>e,Fe=P({typeName:`create_table`,schema:n.object({type:n.literal(`create_table`),table:n.string(),columns:n.record(n.string(),h)}),execute:async(e,t)=>{let n=e.schema.createTable(t.table);n=F(n,t.columns),await n.execute()}}),Ie=(e,t)=>({type:`create_table`,table:e,columns:t});function F(e,t){let n=e;for(let[e,r]of Object.entries(t)){let t=r.type;N(t),n=n.addColumn(e,t,e=>{let t=e;return r.notNull&&(t=t.notNull()),typeof r.defaultSql==`string`&&(t=t.defaultTo(d.raw(r.defaultSql))),t})}return n}const Le=P({typeName:`create_table_with_constraints`,schema:n.object({type:n.literal(`create_table_with_constraints`),table:n.string(),columns:n.record(n.string(),h),constraints:n.object({primaryKey:n.object({name:n.string(),columns:n.array(n.string()).readonly()}).optional(),unique:n.array(n.object({name:n.string(),columns:n.array(n.string()).readonly()})).readonly().optional(),foreignKeys:n.array(n.object({name:n.string(),columns:n.array(n.string()).readonly(),referencedTable:n.string(),referencedColumns:n.array(n.string()).readonly(),onDelete:v.optional(),onUpdate:v.optional(),inline:n.boolean().optional()})).readonly().optional()}).optional()}),execute:async(e,t)=>{let n=e.schema.createTable(t.table);if(n=F(n,t.columns),t.constraints){let{primaryKey:e,unique:r,foreignKeys:i}=t.constraints;if(e&&(n=n.addPrimaryKeyConstraint(e.name,e.columns)),r)for(let e of r)n=n.addUniqueConstraint(e.name,e.columns);if(i)for(let e of i)n=n.addForeignKeyConstraint(e.name,e.columns,e.referencedTable,e.referencedColumns,t=>{let n=t;return e.onDelete&&(n=n.onDelete(e.onDelete)),e.onUpdate&&(n=n.onUpdate(e.onUpdate)),n})}await n.execute()}}),Re=(e,t,n)=>({type:`create_table_with_constraints`,table:e,columns:t,constraints:{primaryKey:n?.primaryKey,unique:n?.unique??[],foreignKeys:n?.foreignKeys??[]}}),ze=P({typeName:`drop_table`,schema:n.object({type:n.literal(`drop_table`),table:n.string()}),execute:async(e,t)=>{await e.schema.dropTable(t.table).execute()}}),Be=e=>({type:`drop_table`,table:e}),Ve=P({typeName:`add_column`,schema:n.object({..._.shape,type:n.literal(`add_column`),attributes:h}),execute:async(e,t)=>{let n=t.attributes.type;N(n),await e.schema.alterTable(t.table).addColumn(t.column,n,e=>{let n=e;return t.attributes.notNull&&(n=n.notNull()),typeof t.attributes.defaultSql==`string`&&(n=n.defaultTo(d.raw(t.attributes.defaultSql))),n}).execute()}}),He=(e,t)=>({...e,type:`add_column`,attributes:t}),Ue=P({typeName:`drop_column`,schema:n.object({..._.shape,type:n.literal(`drop_column`),attributes:h}),execute:async(e,t)=>{await e.schema.alterTable(t.table).dropColumn(t.column).execute()}}),We=(e,t)=>({...e,type:`drop_column`,attributes:t}),Ge=P({typeName:`alter_column`,schema:n.object({..._.shape,type:n.literal(`alter_column`),before:h,after:h}),execute:async(e,t)=>{let{table:n,column:r,before:i,after:a}=t;if(i.type!==a.type){let t=a.type;N(t),await e.schema.alterTable(n).alterColumn(r,e=>e.setDataType(t)).execute()}a.notNull!==i.notNull&&(a.notNull?await e.schema.alterTable(n).alterColumn(r,e=>e.setNotNull()).execute():await e.schema.alterTable(n).alterColumn(r,e=>e.dropNotNull()).execute())}}),Ke=(e,t,n)=>({...e,type:`alter_column`,before:t,after:n}),qe=P({typeName:`create_index`,schema:n.object({...g.shape,type:n.literal(`create_index`),columns:n.array(n.string()).readonly(),unique:n.boolean()}),execute:async(e,t)=>{let n=e.schema.createIndex(t.name).on(t.table);for(let e of t.columns)n=n.column(e);t.unique&&(n=n.unique()),await n.execute()}}),I=e=>({...e,type:`create_index`}),Je=P({typeName:`drop_index`,schema:n.object({...g.shape,type:n.literal(`drop_index`)}),execute:async(e,t)=>{await e.schema.dropIndex(t.name).execute()}}),L=e=>({...e,type:`drop_index`}),Ye=P({typeName:`create_primary_key_constraint`,schema:n.object({...ue.shape,type:n.literal(`create_primary_key_constraint`)}),execute:async(e,t)=>{await e.schema.alterTable(t.table).addPrimaryKeyConstraint(t.name,t.columns).execute()}}),R=e=>({...e,type:`create_primary_key_constraint`}),Xe=P({typeName:`drop_primary_key_constraint`,schema:n.object({...g.shape,type:n.literal(`drop_primary_key_constraint`)}),execute:async(e,t)=>{await e.schema.alterTable(t.table).dropConstraint(t.name).execute()}}),z=e=>({...e,type:`drop_primary_key_constraint`}),Ze=P({typeName:`create_unique_constraint`,schema:n.object({...de.shape,type:n.literal(`create_unique_constraint`)}),execute:async(e,t)=>{await e.schema.alterTable(t.table).addUniqueConstraint(t.name,t.columns).execute()}}),B=e=>({...e,type:`create_unique_constraint`}),Qe=P({typeName:`drop_unique_constraint`,schema:n.object({...g.shape,type:n.literal(`drop_unique_constraint`)}),execute:async(e,t)=>{await e.schema.alterTable(t.table).dropConstraint(t.name).execute()}}),V=e=>({...e,type:`drop_unique_constraint`}),$e=P({typeName:`create_foreign_key_constraint`,schema:n.object({...fe.shape,type:n.literal(`create_foreign_key_constraint`)}),execute:async(e,t)=>{let n=e.schema.alterTable(t.table).addForeignKeyConstraint(t.name,t.columns,t.referencedTable,t.referencedColumns);t.onDelete&&(n=n.onDelete(t.onDelete)),t.onUpdate&&(n=n.onUpdate(t.onUpdate)),await n.execute()}}),H=(e,t)=>({...e,...t,type:`create_foreign_key_constraint`}),et=P({typeName:`drop_foreign_key_constraint`,schema:n.object({...g.shape,type:n.literal(`drop_foreign_key_constraint`)}),execute:async(e,t)=>{await e.schema.alterTable(t.table).dropConstraint(t.name).execute()}}),U=e=>({...e,type:`drop_foreign_key_constraint`}),W=[Le,Fe,ze,Ve,Ue,Ge,qe,Je,Ye,Xe,Ze,Qe,$e,et],tt=n.union(W.map(e=>e.schema));async function nt(e,t){return await rt(t.type)(e,t)}function rt(e){let t=W.find(t=>t.typeName===e);if(!t)throw Error(`Unknown operation type: ${e}`);return t.execute}const it=e=>{let t=new Set;return e.forEach(e=>{e.type===`drop_table`&&t.add(e.table)}),t.size===0?e:e.filter(e=>e.type===`drop_table`?!0:!t.has(e.table))},at=e=>{let t=new Set;if(e.forEach(e=>{e.type===`create_table`&&t.add(e.table)}),t.size===0)return e;let n=new Map,r=new Map,i=[];e.forEach(e=>{e.type===`create_table`&&n.set(e.table,e)}),e.forEach(e=>{switch(e.type){case`create_table`:return;case`create_primary_key_constraint`:case`create_unique_constraint`:if(t.has(e.table)){let t=r.get(e.table)||[];r.set(e.table,[...t,e])}else i.push(e);break;case`create_foreign_key_constraint`:if(t.has(e.table)&&e.inline!==!1){let t=n.get(e.table),i=e.columns.filter(e=>!(e in t.columns));if(i.length>0)throw Error(`Foreign key constraint "${e.name}" references non-existent columns: ${i.join(`, `)}`);let a=r.get(e.table)||[];r.set(e.table,[...a,e])}else i.push(e);break;default:i.push(e);break}});let a=[];return n.forEach((e,t)=>{let n=r.get(t)||[];if(n.length===0){a.push(e);return}let i={unique:[],foreignKeys:[]};n.forEach(e=>{switch(e.type){case`create_primary_key_constraint`:i.primaryKey=e;break;case`create_unique_constraint`:i.unique.push(e);break;case`create_foreign_key_constraint`:i.foreignKeys.push(e);break}}),a.push(Re(e.table,e.columns,i))}),[...a,...i]},ot=e=>{let t=new Set;return e.forEach(e=>{(e.type===`drop_unique_constraint`||e.type===`drop_primary_key_constraint`)&&t.add(`${e.table}.${e.name}`)}),e.filter(e=>{if(e.type===`drop_index`){let n=`${e.table}.${e.name}`;if(t.has(n))return!1}return!0})},G=e=>`table`in e?e.table:null,st=e=>{let t=new Set;return e.forEach(e=>{let n=G(e);n&&t.add(n)}),t},ct=e=>{switch(e.type){case`create_foreign_key_constraint`:return[{table:e.table,referencedTable:e.referencedTable}];case`create_table_with_constraints`:return(e.constraints?.foreignKeys||[]).map(t=>({table:e.table,referencedTable:t.referencedTable}));default:return[]}},lt=e=>{let t=new oe;return e.forEach(e=>ct(e).forEach(n=>{n.table!==n.referencedTable&&(e.type!==`create_foreign_key_constraint`||e.inline!==!1)&&t.addEdge(n.referencedTable,n.table)})),t},ut=(e,t)=>{try{let n=se(lt(t)),r=new Set(n);return[...Array.from(e).filter(e=>!r.has(e)).sort(),...n]}catch(e){throw e instanceof ae?Error(`Circular dependency detected in foreign key constraints. Please resolve this by setting 'inline: false' for one of the foreign key constraints in each circular relationship.`):e}},dt=e=>new Map(e.map((e,t)=>[e,t])),ft=e=>(t,n)=>{let r=K[t.type],i=K[n.type];if(r!==i)return r-i;let a=G(t),o=G(n);if(a&&o){let t=e.get(a)??2**53-1,n=e.get(o)??2**53-1;if(t!==n)return t-n}return(a||``).localeCompare(o||``)},K={drop_foreign_key_constraint:0,drop_unique_constraint:1,drop_primary_key_constraint:2,drop_index:3,drop_column:4,drop_table:5,create_table_with_constraints:6,create_table:7,add_column:8,alter_column:9,create_index:10,create_primary_key_constraint:11,create_unique_constraint:12,create_foreign_key_constraint:13},pt=p.pipe(it,at,ot,e=>p.sort(ft(p.pipe(st,t=>ut(t,e),dt)(e)),e)),mt=e=>({getMigrations:async()=>{let t=await e.migrationsResolver(),n={};return t.forEach(e=>{n[e.id]={up:async t=>{for(let n of pt(e.diff.operations))await nt(t,n)}}}),n}}),ht=n.object({operations:n.array(tt).readonly()}),gt=n.object({id:n.string(),version:n.string(),diff:ht}),q=`migrations`,_t=async e=>{let{fs:t}=e;try{let e=(await t.readdir(q)).filter(e=>e.endsWith(`.json`)).map(async e=>gt.parse(JSON.parse(await t.readFile(m(q,e),`utf-8`))));return await Promise.all(e)}catch(e){if(e instanceof Object&&`code`in e&&e.code===`ENOENT`)return[];throw e}},J=async e=>{let{client:t,fs:n}=e;await using r=t.getDB();let i=await _t({fs:n});if(!(await r.introspection.getTables({withInternalKyselyTables:!0})).map(e=>e.name).includes(a))return i;let o=await r.selectFrom(a).select([`name`,`timestamp`]).$narrowType().execute();return i.filter(e=>!o.some(t=>t.name===e.id))};async function Y(e,t){let{client:n,logger:r}=e,{reporter:i}=r;await using a=n.getDB({plan:t.plan});let{results:o,error:s}=await new c({db:a,provider:mt({migrationsResolver:async()=>t.plan?await J(e):await _t(e),options:{plan:t.plan}})}).migrateToLatest(),l=a.getPlannedQueries();if(l.length>0){l.forEach(e=>{r.stdout(t.pretty?ce(e.sql):e.sql)});return}if(o&&o.length>0?o.forEach(e=>{e.status===`Error`?i.error(`Migration failed: ${e.migrationName}`):e.status===`Success`&&i.success(`Migration applied: ${e.migrationName}`)}):i.info(`No migrations to run`),s)throw s instanceof Error?s:Error(`Migration error: ${s}`)}const vt=e({meta:{name:`apply`,description:`Run migrations to sync database schema`},args:{plan:{type:`boolean`,description:`Plan the migration without applying it`,default:!1},pretty:{type:`boolean`,description:`Pretty print the migration SQL (only for --plan)`,default:!1}},run:async e=>{try{await Y(await M(),{plan:e.args.plan,pretty:e.args.pretty})}catch(e){A.reporter.error(e),process.exit(1)}}}),X=()=>({added:(e,t,n)=>p.pipe(p.difference(t),p.map(n))(e),removed:(e,t,n)=>p.pipe(p.difference(e),p.map(n))(t),changed:(e,t,n,r)=>p.pipe(p.intersection(e),p.filter(n),p.map(r))(t)}),Z=p.prop(`name`),yt=p.eqBy(e=>[e.type,e.notNull??!1,e.primaryKey??!1,e.unique??!1]);function bt(e,t){let n=[],r=X(),i=e.columns,a=t.columns,o=Object.keys(i),s=Object.keys(a);return r.added(o,s,e=>({column:e,attributes:a[e]})).forEach(t=>{n.push(He({table:e.name,column:t.column},t.attributes))}),r.removed(o,s,e=>({column:e,attributes:i[e]})).forEach(t=>{n.push(We({table:e.name,column:t.column},t.attributes))}),r.changed(o,s,e=>!yt(i[e],a[e]),e=>({column:e,before:i[e],after:a[e]})).forEach(t=>{n.push(Ke({table:e.name,column:t.column},t.before,t.after))}),n}function xt(e){let{current:t,ideal:n}=e,r=[],i=X(),a=p.map(Z,t),o=p.map(Z,n);return i.added(a,o,e=>n.find(t=>t.name===e)).forEach(e=>{r.push(Ie(e.name,e.columns))}),i.removed(a,o,p.identity).forEach(e=>{r.push(Be(e))}),p.filter(e=>n.some(t=>t.name===e.name))(t).forEach(e=>{let t=n.find(t=>t.name===e.name);r.push(...bt(e,t))}),r}function St(e){let{current:t,ideal:n}=e,r=[],i=X(),a=e=>`${e.table}:${e.name}`,o=new Map(t.map(e=>[a(e),e])),s=new Map(n.map(e=>[a(e),e])),c=Array.from(o.keys()),l=Array.from(s.keys());return i.added(c,l,e=>s.get(e)).forEach(e=>{r.push(I(e))}),i.removed(c,l,e=>{let t=o.get(e);return{table:t.table,name:t.name}}).forEach(e=>{r.push(L(e))}),i.changed(c,l,e=>{let t=o.get(e),n=s.get(e);return!p.equals(t.columns,n.columns)||t.unique!==n.unique},e=>({current:o.get(e),ideal:s.get(e)})).forEach(({current:e,ideal:t})=>{r.push(L(e)),r.push(I(t))}),r}function Ct(e){let{current:t,ideal:n}=e,r=[],i=X(),a=e=>`${e.table}:${e.name}`,o=new Map(t.map(e=>[a(e),e])),s=new Map(n.map(e=>[a(e),e])),c=Array.from(o.keys()),l=Array.from(s.keys());return i.added(c,l,e=>s.get(e)).forEach(e=>{r.push(R(e))}),i.removed(c,l,e=>{let t=o.get(e);return{table:t.table,name:t.name}}).forEach(e=>{r.push(z(e))}),i.changed(c,l,e=>{let t=o.get(e),n=s.get(e);return!p.equals(t.columns,n.columns)},e=>({current:o.get(e),ideal:s.get(e)})).forEach(({current:e,ideal:t})=>{r.push(z(e)),r.push(R(t))}),r}function wt(e){let{current:t,ideal:n}=e,r=[],i=X(),a=e=>`${e.table}:${e.name}`,o=new Map(t.map(e=>[a(e),e])),s=new Map(n.map(e=>[a(e),e])),c=Array.from(o.keys()),l=Array.from(s.keys());return i.added(c,l,e=>s.get(e)).forEach(e=>{r.push(B(e))}),i.removed(c,l,e=>{let t=o.get(e);return{table:t.table,name:t.name}}).forEach(e=>{r.push(V(e))}),i.changed(c,l,e=>{let t=o.get(e),n=s.get(e);return!p.equals(t.columns,n.columns)},e=>({current:o.get(e),ideal:s.get(e)})).forEach(({current:e,ideal:t})=>{r.push(V(e)),r.push(B(t))}),r}function Tt(e){let t=[],n=X(),r=e.current.map(Z),i=e.ideal.map(Z);return t.push(...n.added(r,i,t=>{let{table:n,name:r,...i}=e.ideal.find(e=>e.name===t);return H({table:n,name:r},i)})),t.push(...n.removed(r,i,t=>U(e.current.find(e=>e.name===t)))),t.push(...n.changed(r,i,t=>{let n=e.current.find(e=>e.name===t),r=e.ideal.find(e=>e.name===t);return!n||!r?!1:!(p.equals(n.columns,r.columns)&&n.referencedTable===r.referencedTable&&p.equals(n.referencedColumns,r.referencedColumns)&&n.onDelete===r.onDelete&&n.onUpdate===r.onUpdate)},t=>{let n=e.current.find(e=>e.name===t),{table:r,name:i,...a}=e.ideal.find(e=>e.name===t);return[U(n),H({table:r,name:i},a)]}).flat()),t}function Et(e){let t=xt({current:e.current.tables,ideal:e.ideal.tables}),n=St({current:e.current.indexes,ideal:e.ideal.indexes}),r=Ct({current:e.current.primaryKeyConstraints,ideal:e.ideal.primaryKeyConstraints}),i=wt({current:e.current.uniqueConstraints,ideal:e.ideal.uniqueConstraints}),a=Tt({current:e.current.foreignKeyConstraints,ideal:e.ideal.foreignKeyConstraints});return{operations:[...t,...n,...r,...i,...a]}}const Dt=e=>{let t=O(e.getDialect()).createIntrospectionDriver(e);return{introspect:async n=>{await using r=e.getDB();let i=await r.introspection.getTables(),{tables:a,indexes:o,constraints:s}=await t.introspect({config:n}),c=()=>i.map(e=>{let n={};for(let r of e.columns){let i=a.find(t=>t.table===e.name&&t.name===r.name);i&&(n[r.name]={schema:e.schema,table:e.name,name:r.name,dataType:t.convertTypeName(r.dataType),default:i.default??null,characterMaximumLength:i.characterMaximumLength??null,notNull:!r.isNullable})}return{schema:e.schema,name:e.name,columns:n}}),l=e=>!e.table.startsWith(`kysely_`);return{tables:c(),indexes:o.filter(l),constraints:{primaryKey:s.primaryKey.filter(l),unique:s.unique.filter(l),foreignKey:s.foreignKey.filter(l)}}}}},Q=async(e,t,n)=>{let r=O(t);return{manageType:n,instance:await r.createDevDatabaseProvider().setup(r.parseDevDatabaseConfig(e),n)}};async function Ot(e,t){let{config:n}=e,r=O(n.database.dialect);switch(t.mode){case`dev-start`:{let{instance:e,manageType:t}=await Q(n.dev,n.database.dialect,`dev-start`);return{manageType:t,manager:e,result:{reused:await e.isAvailable()}}}case`generate-dev`:{let e=await r.hasReusableDevDatabase(),{instance:t,manageType:i}=await Q(n.dev,n.database.dialect,e?`dev-start`:`one-off`);return{manageType:i,manager:t,result:{reused:e}}}}}async function kt(e,t){let{config:n}=e,{reporter:r}=t.logger||j;if(!n.dev)throw Error(`Dev database configuration is required`);let{manageType:i,manager:a,result:o}=await Ot(e,t);o.reused?r.info(`🔄 Reusing existing dev database...`):r.info(`🚀 Starting dev database...`),await a.start(),r.success(`Dev database started: ${n.database.dialect}`);let s=k({database:{dialect:n.database.dialect,connectionString:a.getConnectionString()}}),c=await J(e);return c.length>0?(r.info(`🔄 Applying ${c.length} pending migrations...`),await Y({client:s,logger:j,fs:e.fs,config:n},{plan:!1,pretty:!1}),r.success(`Applied ${c.length} migrations`)):r.info(`No pending migrations found`),{client:s,manager:a,cleanup:async()=>{switch(t.mode){case`dev-start`:r.success(`Persistent dev database ready: `+n.database.dialect);break;case`generate-dev`:i===`dev-start`?r.info(`Dev start container remains running`):(await a.stop(),r.success(`Temporary dev database stopped`));break}}}}async function At(e,t){let{logger:n,config:r,fs:i}=e,{reporter:a}=n;t.squash&&await jt(e);let{client:o,cleanup:s}=t.dev?await kt(e,{mode:`generate-dev`,logger:n}):{client:e.client,cleanup:async()=>void 0};try{if(!t.ignorePending){let n=await J(e);if(n.length>0)if(t.dev)a.info(`Dev database has ${n.length} pending migrations. These will be applied automatically as baseline.`);else{a.warn([`There are pending migrations: ${n.map(e=>e.id).join(`, `)}`,`Please apply them first before generating a new migration.`,`Otherwise, use --ignore-pending to skip this check.`].join(`
93
93
  `));return}}let s=await Mt({client:o,config:r});if(!s){a.info(`No changes detected, no migration needed.`);return}Nt(n,s.diff);let c=`${q}/${s.id}.json`;await i.mkdir(q,{recursive:!0}),await i.writeFile(c,JSON.stringify(s,null,2));let l=t.squash?`Generated squashed migration: ${c}`:`Migration file generated: ${c}`;a.success(l),t.dev&&await Y({...e,client:o},{plan:!1,pretty:!1})}finally{await s()}}const jt=async e=>{let{logger:t,fs:n}=e,{reporter:r}=t,i=await J(e);if(i.length===0){r.info(`No pending migrations found, nothing to squash.`);return}r.info(`Found ${i.length} pending migrations to squash:`),i.forEach(e=>{r.info(` - ${e.id}.json`)});let a=i.map(e=>m(q,`${e.id}.json`));try{await Promise.all(a.map(e=>n.unlink(e))),r.success(`🗑️ Removed ${a.length} pending migration files`)}catch(e){throw Error(`Failed to remove pending migration files: ${e}`)}},Mt=async e=>{let{client:t,config:n}=e,{tables:r,indexes:i,constraints:a}=await Dt(t).introspect(n),o=(e,t)=>n=>n.some(n=>n.table===e&&n.columns.length===1&&n.columns[0]===t),s=r.map(e=>({name:e.name,columns:Object.fromEntries(Object.entries(e.columns).map(([t,n])=>{let r=o(e.name,t),i=r(a.primaryKey),s=r(a.unique),c=a.primaryKey.some(n=>n.table===e.name&&n.columns.length>1&&n.columns.includes(t))?!0:n.notNull;return[t,{type:n.dataType,notNull:c,defaultSql:n.default??void 0,primaryKey:i,unique:s}]}))})),c=n.tables.map(e=>({name:e.tableName,columns:Object.fromEntries(Object.entries(e.columns).map(([t,r])=>{let i=(n.primaryKeyConstraints??[]).some(n=>n.table===e.tableName&&n.columns.includes(t)),a=r.primaryKey||r.notNull||i;return[t,{...r,notNull:a}]}))})),l=Et({current:{tables:s,indexes:i,uniqueConstraints:a.unique,primaryKeyConstraints:a.primaryKey,foreignKeyConstraints:a.foreignKey},ideal:{...n,tables:c}});return l.operations.length===0?null:{version:`1`,id:Date.now()+``,diff:l}},Nt=(e,t)=>{let n=[];t.operations.forEach(e=>{switch(e.type){case`create_table`:n.push(`-- create_table: ${e.table}`),Object.entries(e.columns).forEach(([e,t])=>{n.push(` -> column: ${e} (${JSON.stringify(t)})`)});break;case`drop_table`:n.push(`-- remove_table: ${e.table}`);break;case`add_column`:n.push([`-- add_column: ${e.table}.${e.column}`,` -> to: ${JSON.stringify(e.attributes)}`].join(`
94
94
  `));break;case`drop_column`:n.push(`-- remove_column: ${e.table}.${e.column}`);break;case`alter_column`:n.push([`-- change_column: ${e.table}.${e.column}`,` -> from: ${JSON.stringify(e.before)}`,` -> to: ${JSON.stringify(e.after)}`].join(`
95
95
  `));break;case`create_index`:n.push(`-- create_index: ${e.table}.${e.name} (${e.columns.join(`, `)})${e.unique?` [unique]`:``}`);break;case`drop_index`:n.push(`-- drop_index: ${e.table}.${e.name}`);break;case`create_primary_key_constraint`:n.push(`-- create_primary_key_constraint: ${e.table}.${e.name} (${e.columns.join(`, `)})`);break;case`drop_primary_key_constraint`:n.push(`-- drop_primary_key_constraint: ${e.table}.${e.name}`);break;case`create_unique_constraint`:n.push(`-- create_unique_constraint: ${e.table}.${e.name} (${e.columns.join(`, `)})`);break;case`drop_unique_constraint`:n.push(`-- drop_unique_constraint: ${e.table}.${e.name}`);break;case`create_foreign_key_constraint`:n.push(`-- create_foreign_key_constraint: ${e.table}.${e.name} (${e.columns.join(`, `)}) -> ${e.referencedTable} (${e.referencedColumns.join(`, `)})${e.onDelete?` ON DELETE ${e.onDelete.toUpperCase()}`:``}${e.onUpdate?` ON UPDATE ${e.onUpdate.toUpperCase()}`:``}`);break;case`drop_foreign_key_constraint`:n.push(`-- drop_foreign_key_constraint: ${e.table}.${e.name}`);break;default:break}}),e.reporter.log(n.join(`
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@izumisy/kyrage",
3
3
  "private": false,
4
4
  "type": "module",
5
- "version": "1.5.5",
5
+ "version": "1.5.7",
6
6
  "description": "A minimal, schema-based declarative migration tool for Node.js ecosystem",
7
7
  "author": "Seiya Izumi (https://github.com/IzumiSy)",
8
8
  "license": "MIT",
@@ -37,25 +37,25 @@
37
37
  "citty": "^0.1.6",
38
38
  "consola": "^3.4.2",
39
39
  "graph-data-structure": "^4.5.0",
40
- "kysely": "^0.28.8",
40
+ "kysely": "^0.28.9",
41
41
  "mysql2": "^3.16.0",
42
42
  "pg": "^8.16.3",
43
43
  "ramda": "^0.32.0",
44
- "sql-formatter": "^15.6.10",
44
+ "sql-formatter": "^15.6.12",
45
45
  "testcontainers": "^11.11.0",
46
- "zod": "^4.1.12"
46
+ "zod": "^4.3.5"
47
47
  },
48
48
  "devDependencies": {
49
- "@swc/core": "^1.13.5",
49
+ "@swc/core": "^1.15.8",
50
50
  "@types/better-sqlite3": "^7.6.13",
51
51
  "@types/node": "^25",
52
- "@types/pg": "^8.15.5",
52
+ "@types/pg": "^8.16.0",
53
53
  "@types/ramda": "^0.31.1",
54
54
  "memfs": "^4.49.0",
55
55
  "prettier": "^3",
56
- "tsdown": "^0.18.4",
56
+ "tsdown": "^0.19.0",
57
57
  "typescript": "^5",
58
- "vitest": "^3.2.4"
58
+ "vitest": "^4.0.16"
59
59
  },
60
60
  "scripts": {
61
61
  "dev": "NODE_ENV=development tsdown --watch",