@izumisy/kyrage 1.6.0 → 1.6.1

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 CHANGED
@@ -1,6 +1,5 @@
1
1
  import z from "zod";
2
2
  import { ColumnDataType } from "kysely";
3
-
4
3
  //#region src/config/loader.d.ts
5
4
  declare const columnSchema: z.ZodObject<{
6
5
  type: z.ZodString;
@@ -19,8 +18,8 @@ declare const indexSchema: z.ZodObject<{
19
18
  type IndexSchema = z.infer<typeof indexSchema>;
20
19
  declare const databaseSchema: z.ZodObject<{
21
20
  dialect: z.ZodEnum<{
22
- postgres: "postgres";
23
21
  cockroachdb: "cockroachdb";
22
+ postgres: "postgres";
24
23
  sqlite: "sqlite";
25
24
  }>;
26
25
  connectionString: z.ZodString;
@@ -40,23 +39,23 @@ type DevDatabaseValue = z.infer<typeof devDatabaseSchema>;
40
39
  //#endregion
41
40
  //#region src/operations/shared/types.d.ts
42
41
  declare const primaryKeyConstraintSchema: z.ZodObject<{
43
- columns: z.ZodReadonly<z.ZodArray<z.ZodString>>;
44
42
  table: z.ZodString;
45
43
  name: z.ZodString;
44
+ columns: z.ZodReadonly<z.ZodArray<z.ZodString>>;
46
45
  }, z.core.$strip>;
47
46
  type PrimaryKeyConstraintSchema = z.infer<typeof primaryKeyConstraintSchema>;
48
47
  declare const uniqueConstraintSchema: z.ZodObject<{
49
- columns: z.ZodReadonly<z.ZodArray<z.ZodString>>;
50
48
  table: z.ZodString;
51
49
  name: z.ZodString;
50
+ columns: z.ZodReadonly<z.ZodArray<z.ZodString>>;
52
51
  }, z.core.$strip>;
53
52
  type UniqueConstraintSchema = z.infer<typeof uniqueConstraintSchema>;
54
53
  declare const referentialActionsSchema: z.ZodEnum<{
55
54
  cascade: "cascade";
56
- "set null": "set null";
57
- "set default": "set default";
58
- restrict: "restrict";
59
55
  "no action": "no action";
56
+ restrict: "restrict";
57
+ "set default": "set default";
58
+ "set null": "set null";
60
59
  }>;
61
60
  type ReferentialActions = z.infer<typeof referentialActionsSchema>;
62
61
  //#endregion
@@ -64,7 +63,7 @@ type ReferentialActions = z.infer<typeof referentialActionsSchema>;
64
63
  /**
65
64
  * Defines a column in a table.
66
65
  */
67
- declare const column: (type: ColumnDataType, options?: Partial<Omit<ColumnValue, "type">>) => {
66
+ export declare const column: (type: ColumnDataType, options?: Partial<Omit<ColumnValue, "type">>) => {
68
67
  type: ColumnDataType;
69
68
  notNull: boolean | undefined;
70
69
  primaryKey: boolean | undefined;
@@ -132,25 +131,7 @@ type ExpressionBuilders<T extends Record<string, DefinedColumn>> = {
132
131
  /**
133
132
  * Defines a table with its columns and optional expression builders.
134
133
  */
135
- declare const defineTable: <T extends Record<string, DefinedColumn>>(
136
- /**
137
- * The name of the table.
138
- */
139
-
140
- name: string,
141
- /**
142
- * The columns in the table.
143
- */
144
-
145
- columns: T,
146
- /**
147
- * The expression builders for the table.
148
- *
149
- * This is where you can define additional indexes, constraints, or other
150
- * database-specific features for the table.
151
- */
152
-
153
- tableExpBuilder?: (builder: ExpressionBuilders<T>) => ReadonlyArray<ReturnType<ExpressionBuilders<T>["index"]> | ReturnType<ExpressionBuilders<T>["primaryKey"]> | ReturnType<ExpressionBuilders<T>["unique"]> | ReturnType<ExpressionBuilders<T>["reference"]>>) => {
134
+ export declare const defineTable: <T extends Record<string, DefinedColumn>>(name: string, columns: T, tableExpBuilder?: (builder: ExpressionBuilders<T>) => ReadonlyArray<ReturnType<ExpressionBuilders<T>["index"]> | ReturnType<ExpressionBuilders<T>["primaryKey"]> | ReturnType<ExpressionBuilders<T>["unique"]> | ReturnType<ExpressionBuilders<T>["reference"]>>) => {
154
135
  tableName: string;
155
136
  columns: T;
156
137
  indexes: DefinedIndex[];
@@ -158,28 +139,30 @@ tableExpBuilder?: (builder: ExpressionBuilders<T>) => ReadonlyArray<ReturnType<E
158
139
  uniques: DefinedUniqueConstraint[];
159
140
  foreignKeys: DefinedForeignKeyConstraint[];
160
141
  };
161
- type DefinedTable = ReturnType<typeof defineTable> & {
142
+ export type DefinedTable = ReturnType<typeof defineTable> & {
162
143
  indexes: ReadonlyArray<DefinedIndex>;
163
144
  primaryKeys: ReadonlyArray<DefinedPrimaryKeyConstraint>;
164
145
  uniques: ReadonlyArray<DefinedUniqueConstraint>;
165
146
  foreignKeys: ReadonlyArray<DefinedForeignKeyConstraint>;
166
147
  };
167
- type DefinedTables = ReadonlyArray<DefinedTable>;
168
- type DefineConfigProp = {
148
+ export type DefinedTables = ReadonlyArray<DefinedTable>;
149
+ export type DefineConfigProp = {
169
150
  database: DatabaseValue;
170
151
  dev?: DevDatabaseValue;
171
152
  tables: DefinedTables;
172
153
  };
173
- declare const defineConfig: (config: DefineConfigProp) => {
154
+ export declare const defineConfig: (config: DefineConfigProp) => {
155
+ readonly database: DatabaseValue;
156
+ readonly tables: DefinedTables;
174
157
  readonly dev: {
158
+ file: {
159
+ name: string;
160
+ };
161
+ } | {
175
162
  container: {
176
163
  image: string;
177
164
  name?: string | undefined;
178
165
  };
179
- } | {
180
- file: {
181
- name: string;
182
- };
183
166
  } | undefined;
184
167
  readonly indexes: {
185
168
  columns: readonly string[];
@@ -188,27 +171,24 @@ declare const defineConfig: (config: DefineConfigProp) => {
188
171
  name: string;
189
172
  }[];
190
173
  readonly primaryKeyConstraints: {
191
- columns: readonly string[];
192
174
  table: string;
193
175
  name: string;
176
+ columns: readonly string[];
194
177
  }[];
195
178
  readonly uniqueConstraints: {
196
- columns: readonly string[];
197
179
  table: string;
198
180
  name: string;
181
+ columns: readonly string[];
199
182
  }[];
200
183
  readonly foreignKeyConstraints: {
184
+ table: string;
185
+ name: string;
201
186
  columns: readonly string[];
202
187
  referencedTable: string;
203
188
  referencedColumns: readonly string[];
204
- table: string;
205
- name: string;
206
- onDelete?: "cascade" | "set null" | "set default" | "restrict" | "no action" | undefined;
207
- onUpdate?: "cascade" | "set null" | "set default" | "restrict" | "no action" | undefined;
189
+ onDelete?: "cascade" | "no action" | "restrict" | "set default" | "set null" | undefined;
190
+ onUpdate?: "cascade" | "no action" | "restrict" | "set default" | "set null" | undefined;
208
191
  inline?: boolean | undefined;
209
192
  }[];
210
- readonly database: DatabaseValue;
211
- readonly tables: DefinedTables;
212
193
  };
213
- //#endregion
214
- export { DefineConfigProp, DefinedTable, DefinedTables, column, defineConfig, defineTable };
194
+ //#endregion
package/dist/index.mjs CHANGED
@@ -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};
1
+ import{t as e}from"./naming-DSgOe9tq.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=/* @__PURE__ */ new Map,r=/* @__PURE__ */ new Map,i=/* @__PURE__ */ new Map,a=/* @__PURE__ */ 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.d.mts CHANGED
@@ -1 +1 @@
1
- export { };
1
+ export {}
package/dist/main.mjs CHANGED
@@ -1,4 +1,4 @@
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`
1
+ import{n as e}from"./naming-DSgOe9tq.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.1`;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)}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,
@@ -121,8 +121,8 @@ import{n as e}from"./naming-Dnle4KtH.mjs";import{defineCommand as t,runMain as n
121
121
  SELECT * FROM pragma_index_list(${o.name})
122
122
  `.$castTo().execute(t);for(let e of u)if(e.unique===1&&e.origin===`u`){let{rows:n}=await f`
123
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(`
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=/* @__PURE__ */ 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`||!t.has(e.table))},bt=e=>{let t=/* @__PURE__ */ new Set;if(e.forEach(e=>{e.type===`create_table`&&t.add(e.table)}),t.size===0)return e;let n=/* @__PURE__ */ new Map,r=/* @__PURE__ */ 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)}});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)}}),a.push($e(e.table,e.columns,i))}),[...a,...i]},xt=e=>{let t=/* @__PURE__ */ 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=/* @__PURE__ */ 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=wt(t),r=fe(n),i=new Set(r);return[...Array.from(e).filter(e=>!i.has(e)).sort(),...r]}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 o=kt({migrationsResolver:async()=>t.plan?await J(e):await q(e),options:{plan:t.plan}}),{results:s,error:c}=await new ne({db:a,provider:o}).migrateToLatest(),l=a.getPlannedQueries();if(l.length>0){l.forEach(e=>{r.stdout(t.pretty?pe(e.sql):e.sql)});return}if(s&&s.length>0?s.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`),c)throw c instanceof Error?c:Error(`Migration error: ${c}`)}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=>{let n=e.current.find(e=>e.name===t);return H(n)})),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=/* @__PURE__ */ 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`))}}}}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(`
126
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(`
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(`
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{};
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}`)}}),e.reporter.log(n.join(`
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}}),an=t({meta:{name:`kyrage`,version:me,description:`Kysely migration CLI with declarative schema`},subCommands:{apply:Mt,generate:Jt,dev:rn}});n(an);export{};
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@izumisy/kyrage",
3
3
  "private": false,
4
4
  "type": "module",
5
- "version": "1.6.0",
5
+ "version": "1.6.1",
6
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",
@@ -30,32 +30,32 @@
30
30
  "kyrage": "./dist/main.mjs"
31
31
  },
32
32
  "dependencies": {
33
- "@testcontainers/cockroachdb": "^11.13.0",
34
- "@testcontainers/postgresql": "^11.13.0",
35
- "better-sqlite3": "^12.6.2",
36
- "c12": "^3.3.3",
37
- "citty": "^0.1.6",
33
+ "@testcontainers/cockroachdb": "^12.0.3",
34
+ "@testcontainers/postgresql": "^12.0.3",
35
+ "better-sqlite3": "^12.11.1",
36
+ "c12": "^3.3.4",
37
+ "citty": "^0.2.1",
38
38
  "consola": "^3.4.2",
39
39
  "graph-data-structure": "^4.5.0",
40
40
  "kysely": "^0.28.9",
41
- "mysql2": "^3.17.2",
42
- "pg": "^8.16.3",
41
+ "mysql2": "^3.20.0",
42
+ "pg": "^8.20.0",
43
43
  "ramda": "^0.32.0",
44
- "sql-formatter": "^15.7.0",
45
- "testcontainers": "^11.13.0",
46
- "zod": "^4.3.6"
44
+ "sql-formatter": "^15.7.3",
45
+ "testcontainers": "^12.0.3",
46
+ "zod": "^4.4.3"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@swc/core": "^1.15.18",
50
50
  "@types/better-sqlite3": "^7.6.13",
51
51
  "@types/node": "^25",
52
- "@types/pg": "^8.16.0",
52
+ "@types/pg": "^8.20.0",
53
53
  "@types/ramda": "^0.31.1",
54
54
  "memfs": "^4.56.11",
55
55
  "prettier": "^3",
56
- "tsdown": "^0.21.4",
57
- "typescript": "^5",
58
- "vitest": "^4.0.16"
56
+ "tsdown": "^0.23.0",
57
+ "typescript": "^7",
58
+ "vitest": "^4.1.2"
59
59
  },
60
60
  "scripts": {
61
61
  "dev": "NODE_ENV=development tsdown --watch",