@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 +25 -45
- package/dist/index.mjs +1 -1
- package/dist/main.d.mts +1 -1
- package/dist/main.mjs +5 -5
- package/package.json +15 -15
- /package/dist/{naming-Dnle4KtH.mjs → naming-DSgOe9tq.mjs} +0 -0
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
|
-
|
|
205
|
-
|
|
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-
|
|
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-
|
|
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}`)
|
|
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}})
|
|
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.
|
|
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": "^
|
|
34
|
-
"@testcontainers/postgresql": "^
|
|
35
|
-
"better-sqlite3": "^12.
|
|
36
|
-
"c12": "^3.3.
|
|
37
|
-
"citty": "^0.1
|
|
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.
|
|
42
|
-
"pg": "^8.
|
|
41
|
+
"mysql2": "^3.20.0",
|
|
42
|
+
"pg": "^8.20.0",
|
|
43
43
|
"ramda": "^0.32.0",
|
|
44
|
-
"sql-formatter": "^15.7.
|
|
45
|
-
"testcontainers": "^
|
|
46
|
-
"zod": "^4.3
|
|
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.
|
|
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.
|
|
57
|
-
"typescript": "^
|
|
58
|
-
"vitest": "^4.
|
|
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",
|
|
File without changes
|