@izumisy/kyrage 1.5.8 → 1.6.0
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 +14 -2
- package/dist/index.mjs +1 -1
- package/dist/main.mjs +38 -6
- package/dist/naming-Dnle4KtH.mjs +1 -0
- package/package.json +10 -10
package/dist/index.d.mts
CHANGED
|
@@ -21,15 +21,20 @@ declare const databaseSchema: z.ZodObject<{
|
|
|
21
21
|
dialect: z.ZodEnum<{
|
|
22
22
|
postgres: "postgres";
|
|
23
23
|
cockroachdb: "cockroachdb";
|
|
24
|
+
sqlite: "sqlite";
|
|
24
25
|
}>;
|
|
25
26
|
connectionString: z.ZodString;
|
|
26
27
|
}, z.core.$strip>;
|
|
27
28
|
type DatabaseValue = z.infer<typeof databaseSchema>;
|
|
28
29
|
declare const devDatabaseSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
29
|
-
container: z.ZodObject<{
|
|
30
|
+
container: z.ZodDefault<z.ZodObject<{
|
|
30
31
|
image: z.ZodDefault<z.ZodString>;
|
|
31
32
|
name: z.ZodOptional<z.ZodString>;
|
|
32
|
-
}, z.core.$strip
|
|
33
|
+
}, z.core.$strip>>;
|
|
34
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
35
|
+
file: z.ZodDefault<z.ZodObject<{
|
|
36
|
+
name: z.ZodDefault<z.ZodString>;
|
|
37
|
+
}, z.core.$strip>>;
|
|
33
38
|
}, z.core.$strip>]>;
|
|
34
39
|
type DevDatabaseValue = z.infer<typeof devDatabaseSchema>;
|
|
35
40
|
//#endregion
|
|
@@ -131,10 +136,12 @@ declare const defineTable: <T extends Record<string, DefinedColumn>>(
|
|
|
131
136
|
/**
|
|
132
137
|
* The name of the table.
|
|
133
138
|
*/
|
|
139
|
+
|
|
134
140
|
name: string,
|
|
135
141
|
/**
|
|
136
142
|
* The columns in the table.
|
|
137
143
|
*/
|
|
144
|
+
|
|
138
145
|
columns: T,
|
|
139
146
|
/**
|
|
140
147
|
* The expression builders for the table.
|
|
@@ -142,6 +149,7 @@ columns: T,
|
|
|
142
149
|
* This is where you can define additional indexes, constraints, or other
|
|
143
150
|
* database-specific features for the table.
|
|
144
151
|
*/
|
|
152
|
+
|
|
145
153
|
tableExpBuilder?: (builder: ExpressionBuilders<T>) => ReadonlyArray<ReturnType<ExpressionBuilders<T>["index"]> | ReturnType<ExpressionBuilders<T>["primaryKey"]> | ReturnType<ExpressionBuilders<T>["unique"]> | ReturnType<ExpressionBuilders<T>["reference"]>>) => {
|
|
146
154
|
tableName: string;
|
|
147
155
|
columns: T;
|
|
@@ -168,6 +176,10 @@ declare const defineConfig: (config: DefineConfigProp) => {
|
|
|
168
176
|
image: string;
|
|
169
177
|
name?: string | undefined;
|
|
170
178
|
};
|
|
179
|
+
} | {
|
|
180
|
+
file: {
|
|
181
|
+
name: string;
|
|
182
|
+
};
|
|
171
183
|
} | undefined;
|
|
172
184
|
readonly indexes: {
|
|
173
185
|
columns: readonly string[];
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import{t as e}from"./naming-Dnle4KtH.mjs";const t=(e,t)=>({type:e,notNull:t?.notNull,primaryKey:t?.primaryKey,unique:t?.unique,defaultSql:t?.defaultSql}),n=(t,n,r)=>{let i=e=>{if(e.length===0)throw Error(`At least one column must be specified.`)},a=(e,n)=>`${e}_${t}_${n.join(`_`)}`,o=r?r({index:(e,t)=>(i(e),{kind:`index`,name:t?.name??a(`idx`,e),columns:e,unique:t?.unique??!1}),primaryKey:(e,t)=>(i(e),{kind:`primaryKey`,name:t?.name??a(`pk`,e),columns:e}),unique:(e,t)=>(i(e),{kind:`unique`,name:t?.name??a(`uq`,e),columns:e}),reference:(n,r,a,o)=>{let s=Array.isArray(n)?n:[n],c=Array.isArray(a)?a:[a];return i(s),i(c),{kind:`foreignKey`,name:o?.name??e.foreignKey(t,s),columns:s,referencedTable:r.tableName,referencedColumns:c,onDelete:o?.onDelete,onUpdate:o?.onUpdate,inline:o?.inline??!0}}}):[];return{tableName:t,columns:n,indexes:o.filter(e=>e.kind===`index`),primaryKeys:o.filter(e=>e.kind===`primaryKey`),uniques:o.filter(e=>e.kind===`unique`),foreignKeys:o.filter(e=>e.kind===`foreignKey`)}},r=t=>{let n=new Map,r=new Map,i=new Map,a=new Map;for(let o of t.tables){let t=o.tableName;for(let e of o.indexes??[])n.set(`${t}:${e.name}`,{table:t,name:e.name,columns:e.columns,unique:e.unique});for(let e of o.primaryKeys??[])r.set(`${t}:${e.name}`,{table:t,name:e.name,columns:e.columns});for(let e of o.uniques??[])i.set(`${t}:${e.name}`,{table:t,name:e.name,columns:e.columns});for(let e of o.foreignKeys??[])a.set(`${t}:${e.name}`,{table:t,name:e.name,columns:e.columns,referencedTable:e.referencedTable,referencedColumns:e.referencedColumns,onDelete:e.onDelete,onUpdate:e.onUpdate,inline:e.inline});for(let[n,a]of Object.entries(o.columns)){if(a.primaryKey){let i=e.primaryKey(t,[n]),a=`${t}:${i}`;r.has(a)||r.set(a,{table:t,name:i,columns:[n]})}if(a.unique){let r=e.unique(t,[n]),a=`${t}:${r}`;i.has(a)||i.set(a,{table:t,name:r,columns:[n]})}}}return{...t,dev:t.dev,indexes:Array.from(n.values()),primaryKeyConstraints:Array.from(r.values()),uniqueConstraints:Array.from(i.values()),foreignKeyConstraints:Array.from(a.values())}};export{t as column,r as defineConfig,n as defineTable};
|
package/dist/main.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{defineCommand as
|
|
1
|
+
import{n as e}from"./naming-Dnle4KtH.mjs";import{defineCommand as t,runMain as n}from"citty";import r from"zod";import{loadConfig as i}from"c12";import{getContainerRuntimeClient as a}from"testcontainers";import*as o from"fs/promises";import*as s from"path";import{join as c}from"path";import*as l from"os";import{DEFAULT_MIGRATION_TABLE as u,DummyDriver as ee,Kysely as te,Migrator as ne,PostgresAdapter as re,PostgresDialect as d,SqliteDialect as ie,isColumnDataType as ae,sql as f}from"kysely";import{Pool as p}from"pg";import{PostgreSqlContainer as oe}from"@testcontainers/postgresql";import*as m from"ramda";import{CockroachDbContainer as se}from"@testcontainers/cockroachdb";import ce from"better-sqlite3";import{createConsola as le}from"consola";import{CycleError as ue,Graph as de,topologicalSort as fe}from"graph-data-structure";import{format as pe}from"sql-formatter";var me=`1.6.0`;const h=r.object({type:r.string()}).catchall(r.any()),g=r.object({table:r.string(),name:r.string()}),_=r.object({table:r.string(),column:r.string()}),he=r.object({...g.shape,columns:r.array(r.string()).readonly()}),v=r.object({...g.shape,columns:r.array(r.string()).readonly()}),y=r.enum([`cascade`,`set null`,`set default`,`restrict`,`no action`]),b=r.object({...g.shape,columns:r.array(r.string()).readonly(),referencedTable:r.string(),referencedColumns:r.array(r.string()).readonly(),onDelete:y.optional(),onUpdate:y.optional(),inline:r.boolean().optional()}),x=e=>r.object({container:r.object({image:r.string().default(e.defaultImage),name:r.string().optional()}).default({image:e.defaultImage})});var S=class{constructor(e,t){this.dialect=e,this.containerFactory=t}async setup(e,t){return new _e({dialect:this.dialect,manageType:t,containerName:e.container.name,containerFactory:()=>this.containerFactory(e.container.image)})}async hasExisting(e){return e===`dev-start`?C(this.dialect):!1}async cleanup(){await ve()}};const ge=`kyrage.managed`;var _e=class{constructor(e){this.options=e,this.startedContainer=null,this.container=this.setupContainer()}setupContainer(){let e=this.options.containerFactory();return e.withLabels({"kyrage.dialect":this.options.dialect,[ge]:`true`,"kyrage.managed-by":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 ve(),this.startedContainer=null}getConnectionString(){if(!this.startedContainer)throw Error(`Container is not started`);return this.startedContainer.getConnectionUri()}async getStatus(){if(!this.startedContainer)return{type:`unavailable`};let e=await a();try{let t=await e.container.getById(this.startedContainer.getId()).inspect();return t.State.Running?{type:`container`,imageName:t.Config.Image,containerID:t.Id}:{type:`unavailable`}}catch{return{type:`unavailable`}}}async isAvailable(){return(await this.getStatus()).type===`container`}};const C=async e=>(await(await a()).container.list()).some(t=>t.Labels[`kyrage.managed`]===`true`&&t.Labels[`kyrage.managed-by`]===`dev-start`&&t.Labels[`kyrage.dialect`]===e&&t.State===`running`),ve=async()=>{let e=await a(),t=(await e.container.list()).filter(e=>e.Labels[ge]===`true`).map(e=>e.Id);await Promise.allSettled(t.map(async t=>e.container.getById(t).remove({force:!0})))},w=`default`,T=()=>r.object({file:r.object({name:r.string().default(w)}).default({name:w})});var ye=class{async setup(e,t){return new be({manageType:t,name:e.file?.name})}async hasExisting(e){if(e===`dev-start`){let e=this.getDevStartPath();try{return await o.access(e),!0}catch{return!1}}return!1}getDevStartPath(e){let t=e||w;return s.join(l.tmpdir(),`kyrage___dev-${t}.db`)}async cleanup(){try{let e=l.tmpdir(),t=(await o.readdir(e)).filter(e=>e.startsWith(`kyrage___dev-`));await Promise.allSettled(t.map(t=>o.unlink(s.join(e,t))))}catch{}}},be=class{constructor(e){this.options=e,this.connectionString=null,this.filePath=null}async start(){if(this.options.manageType===`dev-start`)this.filePath=this.getDevStartPath(),this.connectionString=this.filePath;else{let e=s.join(l.tmpdir(),`kyrage-test-${Date.now()}-${Math.random().toString(36).slice(2)}.db`);this.filePath=e,this.connectionString=e}}async stop(){if(this.options.manageType===`one-off`&&this.filePath){try{await o.unlink(this.filePath)}catch{}this.filePath=null,this.connectionString=null}}async remove(){if(this.filePath)try{await o.unlink(this.filePath)}catch{}this.connectionString=null,this.filePath=null}getConnectionString(){if(!this.connectionString)throw Error(`File database is not started`);return this.connectionString}async getStatus(){return this.connectionString?this.connectionString===`:memory:`?{type:`file`,filePath:`:memory:`,mode:`memory`}:{type:`file`,filePath:this.connectionString,mode:`file`}:{type:`unavailable`}}async isAvailable(){return(await this.getStatus()).type===`file`}getDevStartPath(){let e=this.options.name||w;return s.join(l.tmpdir(),`kyrage___dev-${e}.db`)}};const xe=r.object({type:r.string(),primaryKey:r.boolean().optional().default(!1),notNull:r.boolean().optional().default(!1),unique:r.boolean().optional().default(!1),defaultSql:r.string().optional()}),Se=r.object({tableName:r.string(),columns:r.record(r.string(),xe)}),Ce=r.object({...g.shape,columns:r.array(r.string()).readonly(),unique:r.boolean().default(!1)}),we=r.enum([`postgres`,`cockroachdb`,`sqlite`]),Te=r.object({dialect:we,connectionString:r.string()}),Ee=r.union([x({defaultImage:``}),T()]),De=r.object({database:Te,dev:Ee.optional(),tables:r.array(Se).readonly(),indexes:r.array(Ce).readonly(),primaryKeyConstraints:r.array(he).readonly(),uniqueConstraints:r.array(v).readonly(),foreignKeyConstraints:r.array(b).readonly()}),Oe=async()=>{let e=await i({name:`kyrage`});return De.parse(e.config)},ke=(e,t)=>{let n=e=>t=>m.any(m.whereEq({name:t.name,table:t.table}),e),[r,i]=m.partition(n(e.uniqueConstraints),t.constraints.unique),[a,o]=m.partition(n(e.indexes),t.indexes),s=m.reject(n(a),i),c=m.reject(n(r),o);return{indexes:[...a,...c],uniqueConstraints:[...r,...s]}};var Ae=class{getName(){return`postgres`}createKyselyDialect(e){return new d({pool:new p({connectionString:e})})}createIntrospectionDriver(e){return{convertTypeName:D,introspect:E(e)}}createDevDatabaseProvider(){return new S(this.getName(),e=>new oe(e))}parseDevDatabaseConfig(e){return x({defaultImage:`postgres:16`}).parse(e)}async hasReusableDevDatabase(){return C(this.getName())}};const E=e=>async t=>{await using n=e.getDB();let[r,i,a]=await Promise.all([je(n),Me(n),Ne(n)]),{indexes:o,uniqueConstraints:s}=ke(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,je=async e=>{let{rows:t}=await f`
|
|
2
2
|
SELECT
|
|
3
3
|
n.nspname AS table_schema,
|
|
4
4
|
c.relname AS table_name,
|
|
@@ -18,7 +18,7 @@ import{defineCommand as e,runMain as t}from"citty";import n from"zod";import{loa
|
|
|
18
18
|
AND a.attnum > 0
|
|
19
19
|
AND NOT a.attisdropped
|
|
20
20
|
ORDER BY c.relname, a.attnum;
|
|
21
|
-
`.$castTo().execute(e);return t.map(e=>({schema:e.table_schema,table:e.table_name,name:e.column_name,default:e.column_default,characterMaximumLength:e.character_maximum_length?Number(e.character_maximum_length):null}))},
|
|
21
|
+
`.$castTo().execute(e);return t.map(e=>({schema:e.table_schema,table:e.table_name,name:e.column_name,default:e.column_default,characterMaximumLength:e.character_maximum_length?Number(e.character_maximum_length):null}))},Me=async e=>{let{rows:t}=await f`
|
|
22
22
|
SELECT
|
|
23
23
|
t.relname AS table_name,
|
|
24
24
|
c.relname AS index_name,
|
|
@@ -33,7 +33,7 @@ import{defineCommand as e,runMain as t}from"citty";import n from"zod";import{loa
|
|
|
33
33
|
AND n.nspname = 'public'
|
|
34
34
|
AND NOT i.indisprimary
|
|
35
35
|
GROUP BY t.relname, c.relname, i.indisunique, i.indisprimary, c.oid;
|
|
36
|
-
`.$castTo().execute(e);return t.map(e=>({table:e.table_name,name:e.index_name,columns:e.column_names,unique:e.is_unique}))},
|
|
36
|
+
`.$castTo().execute(e);return t.map(e=>({table:e.table_name,name:e.index_name,columns:e.column_names,unique:e.is_unique}))},Ne=async e=>{let{rows:t}=await f`
|
|
37
37
|
SELECT
|
|
38
38
|
n.nspname AS schema,
|
|
39
39
|
t.relname AS table,
|
|
@@ -89,8 +89,40 @@ 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(`
|
|
93
|
-
|
|
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 Pe=class{getName(){return`cockroachdb`}createKyselyDialect(e){return new Ie({pool:new p({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 S(this.getName(),e=>new se(e))}parseDevDatabaseConfig(e){return x({defaultImage:`cockroachdb/cockroach:latest-v24.3`}).parse(e)}async hasReusableDevDatabase(){return C(this.getName())}},Fe=class extends re{async acquireMigrationLock(e,t){await e.selectFrom(t.lockTable).selectAll().forUpdate().execute()}},Ie=class extends d{createAdapter(){return new Fe}},Le=class{getName(){return`sqlite`}createKyselyDialect(e){return new ie({database:new ce(e)})}createIntrospectionDriver(e){return{convertTypeName:ze,introspect:Re(e)}}createDevDatabaseProvider(){return new ye}parseDevDatabaseConfig(e){return T().parse(e)}async hasReusableDevDatabase(){return!1}};const Re=e=>async t=>{await using n=e.getDB();let[r,i,a]=await Promise.all([Be(n),Ve(n),He(n)]),{indexes:o,uniqueConstraints:s}=ke(t.config,{indexes:i,constraints:a});return{tables:r,indexes:o,constraints:{...a,unique:s}}},ze=e=>{let t={INTEGER:`integer`,TEXT:`text`,REAL:`real`,BLOB:`blob`,NUMERIC:`numeric`,INT8:`bigint`,BOOLEAN:`boolean`,VARCHAR:`varchar`,CHAR:`char`,UUID:`uuid`},n=e.match(/^(varchar|char)\((\d+)\)$/i);if(n)return n[1].toLowerCase();let r=e.toUpperCase();return t[r]?t[r]:e.toLowerCase()},Be=async e=>{let{rows:t}=await f`
|
|
93
|
+
SELECT name FROM sqlite_master
|
|
94
|
+
WHERE type = 'table'
|
|
95
|
+
AND name NOT LIKE 'sqlite_%'
|
|
96
|
+
AND name != 'kysely_migration'
|
|
97
|
+
AND name != 'kysely_migration_lock'
|
|
98
|
+
`.$castTo().execute(e),n=[];for(let r of t){let{rows:t}=await f`
|
|
99
|
+
SELECT * FROM pragma_table_info(${r.name})
|
|
100
|
+
`.$castTo().execute(e);n.push(...t.map(e=>{let t=null,n=e.type.match(/^(?:varchar|char)\((\d+)\)$/i);return n&&(t=parseInt(n[1],10)),{schema:`public`,table:r.name,name:e.name,default:e.dflt_value,characterMaximumLength:t}}))}return n},Ve=async e=>{let{rows:t}=await f`
|
|
101
|
+
SELECT name FROM sqlite_master
|
|
102
|
+
WHERE type = 'table'
|
|
103
|
+
AND name NOT LIKE 'sqlite_%'
|
|
104
|
+
AND name != 'kysely_migration'
|
|
105
|
+
AND name != 'kysely_migration_lock'
|
|
106
|
+
`.$castTo().execute(e),n=[];for(let r of t){let{rows:t}=await f`
|
|
107
|
+
SELECT * FROM pragma_index_list(${r.name})
|
|
108
|
+
`.$castTo().execute(e);for(let i of t)if(i.origin===`c`){let{rows:t}=await f`
|
|
109
|
+
SELECT * FROM pragma_index_info(${i.name})
|
|
110
|
+
`.$castTo().execute(e);n.push({table:r.name,name:i.name,columns:t.map(e=>e.name),unique:i.unique===1})}}return n.sort((e,t)=>e.table===t.table?e.name.localeCompare(t.name):e.table.localeCompare(t.table))},He=async t=>{let{rows:n}=await f`
|
|
111
|
+
SELECT name, sql FROM sqlite_master
|
|
112
|
+
WHERE type = 'table'
|
|
113
|
+
AND name NOT LIKE 'sqlite_%'
|
|
114
|
+
AND name != 'kysely_migration'
|
|
115
|
+
AND name != 'kysely_migration_lock'
|
|
116
|
+
`.$castTo().execute(t),r=[],i=[],a=[];for(let o of n){let{rows:n}=await f`
|
|
117
|
+
SELECT * FROM pragma_table_info(${o.name})
|
|
118
|
+
`.$castTo().execute(t),s=n.filter(e=>e.pk>0).sort((e,t)=>e.pk-t.pk).map(e=>e.name);s.length>0&&r.push({schema:`public`,table:o.name,name:e(o.name,s),type:`PRIMARY KEY`,columns:s,on_delete:null,on_update:null,referenced_columns:null,referenced_table:null});let{rows:c}=await f`
|
|
119
|
+
SELECT * FROM pragma_foreign_key_list(${o.name})
|
|
120
|
+
`.$castTo().execute(t),l=c.reduce((e,t)=>(e[t.id]||(e[t.id]=[]),e[t.id].push(t),e),{});Object.entries(l).forEach(([,e])=>{let t=e.map(e=>e.from),n=e.length>0&&e[0].from?`fk_${e[0].from}`:`fk_${o.name}_${e[0].table}`;a.push({schema:`public`,table:o.name,name:n,type:`FOREIGN KEY`,columns:t,referencedTable:e[0].table,referencedColumns:e.map(e=>e.to),onDelete:Ue(e[0].on_delete),onUpdate:Ue(e[0].on_update)})});let{rows:u}=await f`
|
|
121
|
+
SELECT * FROM pragma_index_list(${o.name})
|
|
122
|
+
`.$castTo().execute(t);for(let e of u)if(e.unique===1&&e.origin===`u`){let{rows:n}=await f`
|
|
123
|
+
SELECT * FROM pragma_index_info(${e.name})
|
|
124
|
+
`.$castTo().execute(t),r=n.map(e=>e.name),a=r.length===1?`${o.name}_${r[0]}_unique`:`uq_${o.name}_${r.join(`_`)}`;i.push({schema:`public`,table:o.name,name:a,type:`UNIQUE`,columns:r,on_delete:null,on_update:null,referenced_columns:null,referenced_table:null})}}return{primaryKey:r.sort((e,t)=>e.table===t.table?e.name.localeCompare(t.name):e.table.localeCompare(t.table)),unique:i.sort((e,t)=>e.table===t.table?e.name.localeCompare(t.name):e.table.localeCompare(t.table)),foreignKey:a.sort((e,t)=>e.table===t.table?e.name.localeCompare(t.name):e.table.localeCompare(t.table))}},Ue=e=>({CASCADE:`cascade`,"SET NULL":`set null`,"SET DEFAULT":`set default`,RESTRICT:`restrict`,"NO ACTION":`no action`})[e.toUpperCase()],We={postgres:new Ae,cockroachdb:new Pe,sqlite:new Le},O=e=>{let t=We[e];if(!t)throw Error(`Unsupported dialect: ${e}`);return t};var Ge=class extends ee{constructor(e){super(),this.queries=e}async acquireConnection(){return new Ke(this.queries)}},Ke=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 qe=e=>new Je({databaseProps:e.database,options:e.options});var Je=class{constructor(e){this.constructorProps=e}getDB(e){let t=O(this.constructorProps.databaseProps.dialect).createKyselyDialect(this.constructorProps.databaseProps.connectionString);return new Ye({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}},Ye=class extends te{constructor(e,t){let n=[];super({dialect:{...e.dialect,createDriver:()=>t.isPlan?new Ge(n):e.dialect.createDriver()}}),this.plannedQueries=[],this.plannedQueries=n}getPlannedQueries(){return this.plannedQueries}};const k={stdout:e=>console.log(e),reporter:{...le({stdout:process.stderr})}},A={stdout:()=>void 0,reporter:{info:()=>void 0,warn:()=>void 0,success:()=>void 0,log:()=>void 0,error:()=>void 0}};async function j(){let e=await Oe();return{client:qe({database:e.database}),logger:k,fs:o,config:e}}const M=e=>{if(!ae(e))throw Error(`Unsupported data type: ${e}`)},N=e=>e,Xe=N({typeName:`create_table`,schema:r.object({type:r.literal(`create_table`),table:r.string(),columns:r.record(r.string(),h)}),execute:async(e,t)=>{let n=e.schema.createTable(t.table);n=P(n,t.columns),await n.execute()}}),Ze=(e,t)=>({type:`create_table`,table:e,columns:t});function P(e,t){let n=e;for(let[e,r]of Object.entries(t)){let t=r.type;M(t),n=n.addColumn(e,t,e=>{let t=e;return r.notNull&&(t=t.notNull()),typeof r.defaultSql==`string`&&(t=t.defaultTo(f.raw(r.defaultSql))),t})}return n}const Qe=N({typeName:`create_table_with_constraints`,schema:r.object({type:r.literal(`create_table_with_constraints`),table:r.string(),columns:r.record(r.string(),h),constraints:r.object({primaryKey:r.object({name:r.string(),columns:r.array(r.string()).readonly()}).optional(),unique:r.array(r.object({name:r.string(),columns:r.array(r.string()).readonly()})).readonly().optional(),foreignKeys:r.array(r.object({name:r.string(),columns:r.array(r.string()).readonly(),referencedTable:r.string(),referencedColumns:r.array(r.string()).readonly(),onDelete:y.optional(),onUpdate:y.optional(),inline:r.boolean().optional()})).readonly().optional()}).optional()}),execute:async(e,t)=>{let n=e.schema.createTable(t.table);if(n=P(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()}}),$e=(e,t,n)=>({type:`create_table_with_constraints`,table:e,columns:t,constraints:{primaryKey:n?.primaryKey,unique:n?.unique??[],foreignKeys:n?.foreignKeys??[]}}),et=N({typeName:`drop_table`,schema:r.object({type:r.literal(`drop_table`),table:r.string()}),execute:async(e,t)=>{await e.schema.dropTable(t.table).execute()}}),tt=e=>({type:`drop_table`,table:e}),nt=N({typeName:`add_column`,schema:r.object({..._.shape,type:r.literal(`add_column`),attributes:h}),execute:async(e,t)=>{let n=t.attributes.type;M(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(f.raw(t.attributes.defaultSql))),n}).execute()}}),rt=(e,t)=>({...e,type:`add_column`,attributes:t}),it=N({typeName:`drop_column`,schema:r.object({..._.shape,type:r.literal(`drop_column`),attributes:h}),execute:async(e,t)=>{await e.schema.alterTable(t.table).dropColumn(t.column).execute()}}),at=(e,t)=>({...e,type:`drop_column`,attributes:t}),ot=N({typeName:`alter_column`,schema:r.object({..._.shape,type:r.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;M(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())}}),st=(e,t,n)=>({...e,type:`alter_column`,before:t,after:n}),ct=N({typeName:`create_index`,schema:r.object({...g.shape,type:r.literal(`create_index`),columns:r.array(r.string()).readonly(),unique:r.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()}}),F=e=>({...e,type:`create_index`}),lt=N({typeName:`drop_index`,schema:r.object({...g.shape,type:r.literal(`drop_index`)}),execute:async(e,t)=>{await e.schema.dropIndex(t.name).execute()}}),I=e=>({...e,type:`drop_index`}),ut=N({typeName:`create_primary_key_constraint`,schema:r.object({...he.shape,type:r.literal(`create_primary_key_constraint`)}),execute:async(e,t)=>{await e.schema.alterTable(t.table).addPrimaryKeyConstraint(t.name,t.columns).execute()}}),L=e=>({...e,type:`create_primary_key_constraint`}),dt=N({typeName:`drop_primary_key_constraint`,schema:r.object({...g.shape,type:r.literal(`drop_primary_key_constraint`)}),execute:async(e,t)=>{await e.schema.alterTable(t.table).dropConstraint(t.name).execute()}}),R=e=>({...e,type:`drop_primary_key_constraint`}),ft=N({typeName:`create_unique_constraint`,schema:r.object({...v.shape,type:r.literal(`create_unique_constraint`)}),execute:async(e,t)=>{await e.schema.alterTable(t.table).addUniqueConstraint(t.name,t.columns).execute()}}),z=e=>({...e,type:`create_unique_constraint`}),pt=N({typeName:`drop_unique_constraint`,schema:r.object({...g.shape,type:r.literal(`drop_unique_constraint`)}),execute:async(e,t)=>{await e.schema.alterTable(t.table).dropConstraint(t.name).execute()}}),B=e=>({...e,type:`drop_unique_constraint`}),mt=N({typeName:`create_foreign_key_constraint`,schema:r.object({...b.shape,type:r.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()}}),V=(e,t)=>({...e,...t,type:`create_foreign_key_constraint`}),ht=N({typeName:`drop_foreign_key_constraint`,schema:r.object({...g.shape,type:r.literal(`drop_foreign_key_constraint`)}),execute:async(e,t)=>{await e.schema.alterTable(t.table).dropConstraint(t.name).execute()}}),H=e=>({...e,type:`drop_foreign_key_constraint`}),U=[Qe,Xe,et,nt,it,ot,ct,lt,ut,dt,ft,pt,mt,ht],gt=r.union(U.map(e=>e.schema));async function _t(e,t){return await vt(t.type)(e,t)}function vt(e){let t=U.find(t=>t.typeName===e);if(!t)throw Error(`Unknown operation type: ${e}`);return t.execute}const yt=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))},bt=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($e(e.table,e.columns,i))}),[...a,...i]},xt=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})},W=e=>`table`in e?e.table:null,St=e=>{let t=new Set;return e.forEach(e=>{let n=W(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[]}},wt=e=>{let t=new de;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},Tt=(e,t)=>{try{let n=fe(wt(t)),r=new Set(n);return[...Array.from(e).filter(e=>!r.has(e)).sort(),...n]}catch(e){throw e instanceof ue?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}},Et=e=>new Map(e.map((e,t)=>[e,t])),Dt=e=>(t,n)=>{let r=G[t.type],i=G[n.type];if(r!==i)return r-i;let a=W(t),o=W(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||``)},G={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},Ot=m.pipe(yt,bt,xt,e=>m.sort(Dt(m.pipe(St,t=>Tt(t,e),Et)(e)),e)),kt=e=>({getMigrations:async()=>{let t=await e.migrationsResolver(),n={};return t.forEach(e=>{n[e.id]={up:async t=>{for(let n of Ot(e.diff.operations))await _t(t,n)}}}),n}}),At=r.object({operations:r.array(gt).readonly()}),jt=r.object({id:r.string(),version:r.string(),diff:At}),K=`migrations`,q=async e=>{let{fs:t}=e;try{let e=(await t.readdir(K)).filter(e=>e.endsWith(`.json`)).map(async e=>jt.parse(JSON.parse(await t.readFile(c(K,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 q({fs:n});if(!(await r.introspection.getTables({withInternalKyselyTables:!0})).map(e=>e.name).includes(u))return i;let a=await r.selectFrom(u).select([`name`,`timestamp`]).$narrowType().execute();return i.filter(e=>!a.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 ne({db:a,provider:kt({migrationsResolver:async()=>t.plan?await J(e):await q(e),options:{plan:t.plan}})}).migrateToLatest(),c=a.getPlannedQueries();if(c.length>0){c.forEach(e=>{r.stdout(t.pretty?pe(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 Mt=t({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 j(),{plan:e.args.plan,pretty:e.args.pretty})}catch(e){k.reporter.error(e),process.exit(1)}}}),X=()=>({added:(e,t,n)=>m.pipe(m.difference(t),m.map(n))(e),removed:(e,t,n)=>m.pipe(m.difference(e),m.map(n))(t),changed:(e,t,n,r)=>m.pipe(m.intersection(e),m.filter(n),m.map(r))(t)}),Z=m.prop(`name`),Nt=m.eqBy(e=>[e.type,e.notNull??!1,e.primaryKey??!1,e.unique??!1]);function Pt(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(rt({table:e.name,column:t.column},t.attributes))}),r.removed(o,s,e=>({column:e,attributes:i[e]})).forEach(t=>{n.push(at({table:e.name,column:t.column},t.attributes))}),r.changed(o,s,e=>!Nt(i[e],a[e]),e=>({column:e,before:i[e],after:a[e]})).forEach(t=>{n.push(st({table:e.name,column:t.column},t.before,t.after))}),n}function Ft(e){let{current:t,ideal:n}=e,r=[],i=X(),a=m.map(Z,t),o=m.map(Z,n);return i.added(a,o,e=>n.find(t=>t.name===e)).forEach(e=>{r.push(Ze(e.name,e.columns))}),i.removed(a,o,m.identity).forEach(e=>{r.push(tt(e))}),m.filter(e=>n.some(t=>t.name===e.name))(t).forEach(e=>{let t=n.find(t=>t.name===e.name);r.push(...Pt(e,t))}),r}function It(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(F(e))}),i.removed(c,l,e=>{let t=o.get(e);return{table:t.table,name:t.name}}).forEach(e=>{r.push(I(e))}),i.changed(c,l,e=>{let t=o.get(e),n=s.get(e);return!m.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(I(e)),r.push(F(t))}),r}function Lt(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(L(e))}),i.removed(c,l,e=>{let t=o.get(e);return{table:t.table,name:t.name}}).forEach(e=>{r.push(R(e))}),i.changed(c,l,e=>{let t=o.get(e),n=s.get(e);return!m.equals(t.columns,n.columns)},e=>({current:o.get(e),ideal:s.get(e)})).forEach(({current:e,ideal:t})=>{r.push(R(e)),r.push(L(t))}),r}function Rt(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(z(e))}),i.removed(c,l,e=>{let t=o.get(e);return{table:t.table,name:t.name}}).forEach(e=>{r.push(B(e))}),i.changed(c,l,e=>{let t=o.get(e),n=s.get(e);return!m.equals(t.columns,n.columns)},e=>({current:o.get(e),ideal:s.get(e)})).forEach(({current:e,ideal:t})=>{r.push(B(e)),r.push(z(t))}),r}function zt(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 V({table:n,name:r},i)})),t.push(...n.removed(r,i,t=>H(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:!(m.equals(n.columns,r.columns)&&n.referencedTable===r.referencedTable&&m.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[H(n),V({table:r,name:i},a)]}).flat()),t}function Bt(e){let t=Ft({current:e.current.tables,ideal:e.ideal.tables}),n=It({current:e.current.indexes,ideal:e.ideal.indexes}),r=Lt({current:e.current.primaryKeyConstraints,ideal:e.ideal.primaryKeyConstraints}),i=Rt({current:e.current.uniqueConstraints,ideal:e.ideal.uniqueConstraints}),a=zt({current:e.current.foreignKeyConstraints,ideal:e.ideal.foreignKeyConstraints});return{operations:[...t,...n,...r,...i,...a]}}const Vt=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=new Set;for(let e of s.primaryKey)for(let t of e.columns)c.add(`${e.table}.${t}`);let l=()=>i.map(e=>{let n={};for(let r of e.columns){let i=a.find(t=>t.table===e.name&&t.name===r.name);if(!i)continue;let o=c.has(`${e.name}.${r.name}`);n[r.name]={schema:e.schema??`public`,table:e.name,name:r.name,dataType:t.convertTypeName(r.dataType),default:i.default??null,characterMaximumLength:i.characterMaximumLength??null,notNull:!r.isNullable||o}}return{schema:e.schema??`public`,name:e.name,columns:n}}),u=e=>!e.table.startsWith(`kysely_`);return{tables:l(),indexes:o.filter(u),constraints:{primaryKey:s.primaryKey.filter(u),unique:s.unique.filter(u),foreignKey:s.foreignKey.filter(u)}}}}},Q=async(e,t,n)=>{let r=O(t);return{manageType:n,instance:await r.createDevDatabaseProvider().setup(r.parseDevDatabaseConfig(e),n)}};async function Ht(e,t){let{config:n}=e,r=O(n.database.dialect);switch(t.mode){case`dev-start`:{let e=await r.hasReusableDevDatabase(),{instance:t,manageType:i}=await Q(n.dev,n.database.dialect,`dev-start`);return{manageType:i,manager:t,result:{reused:e}}}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 Ut(e,t){let{config:n}=e,{reporter:r}=t.logger||A;if(!n.dev)throw Error(`Dev database configuration is required`);let{manageType:i,manager:a,result:o}=await Ht(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=qe({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:A,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 Wt(e,t){let{logger:n,config:r,fs:i}=e,{reporter:a}=n;t.squash&&await Gt(e);let{client:o,cleanup:s}=t.dev?await Ut(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(`
|
|
125
|
+
`));return}}let s=await Kt({client:o,config:r});if(!s){a.info(`No changes detected, no migration needed.`);return}qt(n,s.diff);let c=`${K}/${s.id}.json`;await i.mkdir(K,{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 Gt=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=>c(K,`${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}`)}},Kt=async e=>{let{client:t,config:n}=e,{tables:r,indexes:i,constraints:a}=await Vt(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=Bt({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}},qt=(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
126
|
`));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
127
|
`));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(`
|
|
96
|
-
`))},
|
|
128
|
+
`))},Jt=t({meta:{name:`generate`,description:`Generate migration files based on the current schema`},args:{"ignore-pending":{type:`boolean`,description:`Ignore pending migrations and generate a new one`,default:!1},dev:{type:`boolean`,description:`Use dev database for safe migration generation`,default:!1},squash:{type:`boolean`,description:`Consolidate pending migrations into a single migration file`,default:!1}},run:async e=>{try{await Wt(await j(),{ignorePending:e.args[`ignore-pending`],dev:e.args.dev,squash:e.args.squash})}catch(e){k.reporter.error(e),process.exit(1)}}});async function Yt(e){let{manager:t,logger:n}=e,r=await t.getStatus();if(!r||r.type!==`container`){n.reporter.info(`No running dev containers found`);return}n.reporter.info(`Running: ${r.containerID} (${r.imageName})`)}async function Xt(e){let{manager:t,logger:n}=e;if(!await t.isAvailable()){n.reporter.info(`No running dev containers found`);return}await t.start(),console.log(t.getConnectionString())}async function Zt(e){let{manager:t,logger:n}=e;if(!await t.isAvailable()){n.reporter.info(`No dev containers found`);return}await t.remove(),n.reporter.success(`Cleaned up dev containers`)}async function Qt(e){let{logger:t}=e,{reporter:n}=t,{manager:r}=await Ut(e,{mode:`dev-start`,logger:t});n.success(`✨ Dev database ready: ${r.getConnectionString()}`)}async function $(){let e=await j();if(!e.config.dev)throw Error(`No dev database configuration found`);let{instance:t}=await Q(e.config.dev,e.config.database.dialect,`dev-start`);return{...e,manager:t}}const $t=t({meta:{name:`start`,description:`Start development database with migrations applied`},run:async()=>{try{await Qt(await j())}catch(e){k.reporter.error(e),process.exit(1)}}}),en=t({meta:{name:`status`,description:`Show status of kyrage dev container`},run:async()=>{try{await Yt(await $())}catch(e){k.reporter.error(e),process.exit(1)}}}),tn=t({meta:{name:`get-url`,description:`Print connection URL for running dev container`},run:async()=>{try{await Xt(await $())}catch(e){k.reporter.error(e),process.exit(1)}}}),nn=t({meta:{name:`clean`,description:`Remove all kyrage dev containers`},run:async()=>{try{await Zt(await $())}catch(e){k.reporter.error(e),process.exit(1)}}}),rn=t({meta:{name:`dev`,description:`Manage development database containers`},subCommands:{start:$t,status:en,"get-url":tn,clean:nn}});n(t({meta:{name:`kyrage`,version:me,description:`Kysely migration CLI with declarative schema`},subCommands:{apply:Mt,generate:Jt,dev:rn}}));export{};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=(e,t)=>t.length===1?`${e}_${t[0]}_primary_key`:`pk_${e}_${t.join(`_`)}`,t={primaryKey:e,unique:(e,t)=>t.length===1?`${e}_${t[0]}_unique`:`uq_${e}_${t.join(`_`)}`,index:(e,t)=>`idx_${e}_${t.join(`_`)}`,foreignKey:(e,t)=>`fk_${e}_${t.join(`_`)}`};export{e as n,t};
|
package/package.json
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"name": "@izumisy/kyrage",
|
|
3
3
|
"private": false,
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "1.
|
|
6
|
-
"description": "A minimal, schema-based declarative migration tool for Node.js ecosystem",
|
|
5
|
+
"version": "1.6.0",
|
|
6
|
+
"description": "A minimal, database-agnostic, schema-based declarative migration tool for Node.js ecosystem",
|
|
7
7
|
"author": "Seiya Izumi (https://github.com/IzumiSy)",
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"repository": {
|
|
@@ -30,30 +30,30 @@
|
|
|
30
30
|
"kyrage": "./dist/main.mjs"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@testcontainers/cockroachdb": "^11.
|
|
34
|
-
"@testcontainers/postgresql": "^11.
|
|
33
|
+
"@testcontainers/cockroachdb": "^11.13.0",
|
|
34
|
+
"@testcontainers/postgresql": "^11.13.0",
|
|
35
35
|
"better-sqlite3": "^12.6.2",
|
|
36
36
|
"c12": "^3.3.3",
|
|
37
37
|
"citty": "^0.1.6",
|
|
38
38
|
"consola": "^3.4.2",
|
|
39
39
|
"graph-data-structure": "^4.5.0",
|
|
40
40
|
"kysely": "^0.28.9",
|
|
41
|
-
"mysql2": "^3.
|
|
41
|
+
"mysql2": "^3.17.2",
|
|
42
42
|
"pg": "^8.16.3",
|
|
43
43
|
"ramda": "^0.32.0",
|
|
44
44
|
"sql-formatter": "^15.7.0",
|
|
45
|
-
"testcontainers": "^11.
|
|
46
|
-
"zod": "^4.3.
|
|
45
|
+
"testcontainers": "^11.13.0",
|
|
46
|
+
"zod": "^4.3.6"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@swc/core": "^1.15.
|
|
49
|
+
"@swc/core": "^1.15.18",
|
|
50
50
|
"@types/better-sqlite3": "^7.6.13",
|
|
51
51
|
"@types/node": "^25",
|
|
52
52
|
"@types/pg": "^8.16.0",
|
|
53
53
|
"@types/ramda": "^0.31.1",
|
|
54
|
-
"memfs": "^4.
|
|
54
|
+
"memfs": "^4.56.11",
|
|
55
55
|
"prettier": "^3",
|
|
56
|
-
"tsdown": "^0.
|
|
56
|
+
"tsdown": "^0.21.4",
|
|
57
57
|
"typescript": "^5",
|
|
58
58
|
"vitest": "^4.0.16"
|
|
59
59
|
},
|