driftsql 2.0.0-beta.2 → 2.0.0-beta.3

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.js CHANGED
@@ -1,52 +1,680 @@
1
- import{a as e,i as t,n,o as r,r as i,t as a}from"./postgres-9C7eE0wB.js";import{n as o,t as s}from"./type-generator-Ba8bgnMm.js";import{Command as c}from"commander";import l from"consola";import u from"node:fs/promises";import d from"node:path";import f from"chalk";import p from"postgres";var m=class{client;constructor(e){this.client=e}async ensureMigrationsTable(){await this.client.query(`
1
+ import { a as __export, i as __esm, n as init_postgres, o as __toCommonJS, r as postgres_exports, t as PostgresGenerator } from "./postgres-CjYq8GvL.js";
2
+ import { n as generateTypesFromSchema, t as TypeGenerator } from "./type-generator-Ba8bgnMm.js";
3
+ import { Command } from "commander";
4
+ import consola from "consola";
5
+ import fs from "node:fs/promises";
6
+ import path from "node:path";
7
+ import chalk from "chalk";
8
+ import postgres from "postgres";
9
+
10
+ //#region src/schema/runner.ts
11
+ var MigrationRunner = class {
12
+ client;
13
+ constructor(client) {
14
+ this.client = client;
15
+ }
16
+ async ensureMigrationsTable() {
17
+ await this.client.query(`
2
18
  CREATE TABLE IF NOT EXISTS _migrations (
3
19
  version VARCHAR(255) PRIMARY KEY,
4
20
  name VARCHAR(255) NOT NULL,
5
21
  applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
6
22
  );
7
- `)}async getAppliedMigrations(){return await this.ensureMigrationsTable(),(await this.client.query(`SELECT version FROM _migrations ORDER BY version`)).rows.map(e=>e.version)}async up(e){if((await this.getAppliedMigrations()).includes(e.version)){l.info(`Migration ${e.version} (${e.name}) already applied`);return}l.start(`Running migration ${e.version} (${e.name})`);for(let t of e.up)await this.client.query(t);await this.client.query(`INSERT INTO _migrations (version, name) VALUES ($1, $2)`,[e.version,e.name]),l.success(`Migration ${e.version} (${e.name}) applied successfully`)}async down(e){if(!(await this.getAppliedMigrations()).includes(e.version)){l.info(`Migration ${e.version} (${e.name}) not applied`);return}l.start(`Rolling back migration ${e.version} (${e.name})`);for(let t of e.down)await this.client.query(t);await this.client.query(`DELETE FROM _migrations WHERE version = $1`,[e.version]),l.success(`Migration ${e.version} (${e.name}) rolled back successfully`)}async upAll(e){let t=await this.getAppliedMigrations(),n=e.filter(e=>!t.includes(e.version));if(n.length===0){l.info(`No pending migrations`);return}l.info(`Found ${n.length} pending migrations`);for(let e of n)await this.up(e)}async downAll(e){let t=await this.getAppliedMigrations(),n=e.filter(e=>t.includes(e.version)).reverse();if(n.length===0){l.info(`No migrations to rollback`);return}l.info(`Rolling back ${n.length} migrations`);for(let e of n)await this.down(e)}async reset(e){await this.downAll(e),await this.upAll(e)}},h=class{snapshotPath;constructor(e=`./.driftsql/snapshot.json`){this.snapshotPath=e}async save(e){let t={version:`1`,timestamp:Date.now(),tables:e},n=d.dirname(this.snapshotPath);await u.mkdir(n,{recursive:!0}),await u.writeFile(this.snapshotPath,JSON.stringify(t,null,2),`utf8`)}async load(){try{let e=await u.readFile(this.snapshotPath,`utf8`);return JSON.parse(e)}catch{return null}}async exists(){try{return await u.access(this.snapshotPath),!0}catch{return!1}}},g=e({MySQLGenerator:()=>_}),_,v=t((()=>{_=class{generateCreateTable(e){let t=[];t.push(`CREATE TABLE \`${e.name}\` (`);let n=[];for(let t of e.columns)n.push(` `+this.generateColumnDefinition(t));if(e.primaryKey&&e.primaryKey.length>0){let t=e.primaryKey.map(e=>`\`${e}\``).join(`, `);n.push(` PRIMARY KEY (${t})`)}if(e.checks&&e.checks.length>0)for(let t of e.checks)n.push(` CONSTRAINT \`${t.name}\` CHECK (${t.expression})`);t.push(n.join(`,
8
- `)),t.push(`) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;`);let r=[t.join(`
9
- `)];if(e.indexes&&e.indexes.length>0)for(let t of e.indexes)r.push(this.generateIndex(e.name,t));return r.join(`
23
+ `);
24
+ }
25
+ async getAppliedMigrations() {
26
+ await this.ensureMigrationsTable();
27
+ return (await this.client.query("SELECT version FROM _migrations ORDER BY version")).rows.map((row) => row.version);
28
+ }
29
+ async up(migration) {
30
+ if ((await this.getAppliedMigrations()).includes(migration.version)) {
31
+ consola.info(`Migration ${migration.version} (${migration.name}) already applied`);
32
+ return;
33
+ }
34
+ consola.start(`Running migration ${migration.version} (${migration.name})`);
35
+ for (const statement of migration.up) await this.client.query(statement);
36
+ await this.client.query("INSERT INTO _migrations (version, name) VALUES ($1, $2)", [migration.version, migration.name]);
37
+ consola.success(`Migration ${migration.version} (${migration.name}) applied successfully`);
38
+ }
39
+ async down(migration) {
40
+ if (!(await this.getAppliedMigrations()).includes(migration.version)) {
41
+ consola.info(`Migration ${migration.version} (${migration.name}) not applied`);
42
+ return;
43
+ }
44
+ consola.start(`Rolling back migration ${migration.version} (${migration.name})`);
45
+ for (const statement of migration.down) await this.client.query(statement);
46
+ await this.client.query("DELETE FROM _migrations WHERE version = $1", [migration.version]);
47
+ consola.success(`Migration ${migration.version} (${migration.name}) rolled back successfully`);
48
+ }
49
+ async upAll(migrations) {
50
+ const applied = await this.getAppliedMigrations();
51
+ const pending = migrations.filter((m) => !applied.includes(m.version));
52
+ if (pending.length === 0) {
53
+ consola.info("No pending migrations");
54
+ return;
55
+ }
56
+ consola.info(`Found ${pending.length} pending migrations`);
57
+ for (const migration of pending) await this.up(migration);
58
+ }
59
+ async downAll(migrations) {
60
+ const applied = await this.getAppliedMigrations();
61
+ const toRollback = migrations.filter((m) => applied.includes(m.version)).reverse();
62
+ if (toRollback.length === 0) {
63
+ consola.info("No migrations to rollback");
64
+ return;
65
+ }
66
+ consola.info(`Rolling back ${toRollback.length} migrations`);
67
+ for (const migration of toRollback) await this.down(migration);
68
+ }
69
+ async reset(migrations) {
70
+ await this.downAll(migrations);
71
+ await this.upAll(migrations);
72
+ }
73
+ };
74
+
75
+ //#endregion
76
+ //#region src/schema/snapshot.ts
77
+ var SnapshotManager = class {
78
+ snapshotPath;
79
+ constructor(snapshotPath = "./.driftsql/snapshot.json") {
80
+ this.snapshotPath = snapshotPath;
81
+ }
82
+ async save(tables) {
83
+ const snapshot = {
84
+ version: "1",
85
+ timestamp: Date.now(),
86
+ tables
87
+ };
88
+ const dir = path.dirname(this.snapshotPath);
89
+ await fs.mkdir(dir, { recursive: true });
90
+ await fs.writeFile(this.snapshotPath, JSON.stringify(snapshot, null, 2), "utf8");
91
+ }
92
+ async load() {
93
+ try {
94
+ const content = await fs.readFile(this.snapshotPath, "utf8");
95
+ return JSON.parse(content);
96
+ } catch {
97
+ return null;
98
+ }
99
+ }
100
+ async exists() {
101
+ try {
102
+ await fs.access(this.snapshotPath);
103
+ return true;
104
+ } catch {
105
+ return false;
106
+ }
107
+ }
108
+ };
109
+
110
+ //#endregion
111
+ //#region src/schema/generators/mysql.ts
112
+ var mysql_exports = /* @__PURE__ */ __export({ MySQLGenerator: () => MySQLGenerator });
113
+ var MySQLGenerator;
114
+ var init_mysql = __esm({ "src/schema/generators/mysql.ts": (() => {
115
+ MySQLGenerator = class {
116
+ generateCreateTable(table) {
117
+ const lines = [];
118
+ lines.push(`CREATE TABLE \`${table.name}\` (`);
119
+ const columnDefs = [];
120
+ for (const column of table.columns) columnDefs.push(" " + this.generateColumnDefinition(column));
121
+ if (table.primaryKey && table.primaryKey.length > 0) {
122
+ const pkColumns = table.primaryKey.map((col) => `\`${col}\``).join(", ");
123
+ columnDefs.push(` PRIMARY KEY (${pkColumns})`);
124
+ }
125
+ if (table.checks && table.checks.length > 0) for (const check of table.checks) columnDefs.push(` CONSTRAINT \`${check.name}\` CHECK (${check.expression})`);
126
+ lines.push(columnDefs.join(",\n"));
127
+ lines.push(") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;");
128
+ const sql = [lines.join("\n")];
129
+ if (table.indexes && table.indexes.length > 0) for (const index of table.indexes) sql.push(this.generateIndex(table.name, index));
130
+ return sql.join("\n\n");
131
+ }
132
+ generateDropTable(tableName) {
133
+ return `DROP TABLE IF EXISTS \`${tableName}\`;`;
134
+ }
135
+ generateColumnDefinition(column) {
136
+ const parts = [`\`${column.name}\``];
137
+ parts.push(this.getColumnType(column));
138
+ if (column.notNull && !column.primaryKey && column.type !== "serial" && column.type !== "bigserial") parts.push("NOT NULL");
139
+ if (column.unique) parts.push("UNIQUE");
140
+ if (column.type === "serial" || column.type === "bigserial") parts.push("AUTO_INCREMENT");
141
+ if (column.default !== void 0) parts.push(`DEFAULT ${this.formatDefault(column.default)}`);
142
+ if (column.references) {
143
+ const ref = column.references;
144
+ parts.push(`REFERENCES \`${ref.table}\`(\`${ref.column}\`)`);
145
+ if (ref.onDelete) parts.push(`ON DELETE ${ref.onDelete}`);
146
+ if (ref.onUpdate) parts.push(`ON UPDATE ${ref.onUpdate}`);
147
+ }
148
+ if (column.check) parts.push(`CHECK (${column.check})`);
149
+ return parts.join(" ");
150
+ }
151
+ getColumnType(column) {
152
+ let typeStr = column.type;
153
+ if (typeStr === "serial") return "INT";
154
+ if (typeStr === "bigserial") return "BIGINT";
155
+ if (typeStr === "timestamptz") return "TIMESTAMP";
156
+ if (typeStr === "jsonb") return "JSON";
157
+ if (typeStr === "bytea") return "BLOB";
158
+ if (typeStr === "double precision") return "DOUBLE";
159
+ let result = typeStr.toUpperCase();
160
+ if (column.length) result += `(${column.length})`;
161
+ else if (column.precision) if (column.scale !== void 0) result += `(${column.precision}, ${column.scale})`;
162
+ else result += `(${column.precision})`;
163
+ return result;
164
+ }
165
+ formatDefault(value) {
166
+ if (typeof value === "string") {
167
+ if (value.toUpperCase() === "NOW()" || value.toUpperCase() === "CURRENT_TIMESTAMP") return "CURRENT_TIMESTAMP";
168
+ return `'${value}'`;
169
+ }
170
+ if (typeof value === "boolean") return value ? "1" : "0";
171
+ return String(value);
172
+ }
173
+ generateIndex(tableName, index) {
174
+ const unique = index.unique ? "UNIQUE " : "";
175
+ const type = index.type && index.type !== "btree" ? ` USING ${index.type.toUpperCase()}` : "";
176
+ const columns = index.columns.map((col) => `\`${col}\``).join(", ");
177
+ return `CREATE ${unique}INDEX \`${index.name}\` ON \`${tableName}\`${type} (${columns});`;
178
+ }
179
+ };
180
+ }) });
181
+
182
+ //#endregion
183
+ //#region src/schema/generators/sqlite.ts
184
+ var sqlite_exports = /* @__PURE__ */ __export({ SQLiteGenerator: () => SQLiteGenerator });
185
+ var SQLiteGenerator;
186
+ var init_sqlite = __esm({ "src/schema/generators/sqlite.ts": (() => {
187
+ SQLiteGenerator = class {
188
+ generateCreateTable(table) {
189
+ const lines = [];
190
+ lines.push(`CREATE TABLE "${table.name}" (`);
191
+ const columnDefs = [];
192
+ for (const column of table.columns) columnDefs.push(" " + this.generateColumnDefinition(column));
193
+ if (table.primaryKey && table.primaryKey.length > 0) {
194
+ const pkColumns = table.primaryKey.map((col) => `"${col}"`).join(", ");
195
+ columnDefs.push(` PRIMARY KEY (${pkColumns})`);
196
+ }
197
+ if (table.checks && table.checks.length > 0) for (const check of table.checks) columnDefs.push(` CONSTRAINT "${check.name}" CHECK (${check.expression})`);
198
+ lines.push(columnDefs.join(",\n"));
199
+ lines.push(");");
200
+ const sql = [lines.join("\n")];
201
+ if (table.indexes && table.indexes.length > 0) for (const index of table.indexes) sql.push(this.generateIndex(table.name, index));
202
+ return sql.join("\n\n");
203
+ }
204
+ generateDropTable(tableName) {
205
+ return `DROP TABLE IF EXISTS "${tableName}";`;
206
+ }
207
+ generateColumnDefinition(column) {
208
+ const parts = [`"${column.name}"`];
209
+ parts.push(this.getColumnType(column));
210
+ if (column.primaryKey) {
211
+ parts.push("PRIMARY KEY");
212
+ if (column.type === "serial" || column.type === "bigserial") parts.push("AUTOINCREMENT");
213
+ }
214
+ if (column.notNull && !column.primaryKey) parts.push("NOT NULL");
215
+ if (column.unique) parts.push("UNIQUE");
216
+ if (column.default !== void 0) parts.push(`DEFAULT ${this.formatDefault(column.default)}`);
217
+ if (column.references) {
218
+ const ref = column.references;
219
+ parts.push(`REFERENCES "${ref.table}"("${ref.column}")`);
220
+ if (ref.onDelete) parts.push(`ON DELETE ${ref.onDelete}`);
221
+ if (ref.onUpdate) parts.push(`ON UPDATE ${ref.onUpdate}`);
222
+ }
223
+ if (column.check) parts.push(`CHECK (${column.check})`);
224
+ return parts.join(" ");
225
+ }
226
+ getColumnType(column) {
227
+ let type = column.type;
228
+ if (type === "serial" || type === "bigserial") return "INTEGER";
229
+ if (type === "bigint") return "INTEGER";
230
+ if (type === "smallint") return "INTEGER";
231
+ if (type === "varchar" || type === "char") return "TEXT";
232
+ if (type === "timestamptz") return "TEXT";
233
+ if (type === "timestamp") return "TEXT";
234
+ if (type === "date") return "TEXT";
235
+ if (type === "time") return "TEXT";
236
+ if (type === "uuid") return "TEXT";
237
+ if (type === "json" || type === "jsonb") return "TEXT";
238
+ if (type === "bytea") return "BLOB";
239
+ if (type === "decimal" || type === "numeric") return "REAL";
240
+ if (type === "real" || type === "double precision") return "REAL";
241
+ if (type === "boolean") return "INTEGER";
242
+ return type.toUpperCase();
243
+ }
244
+ formatDefault(value) {
245
+ if (typeof value === "string") {
246
+ if (value.toUpperCase() === "NOW()" || value.toUpperCase() === "CURRENT_TIMESTAMP") return "CURRENT_TIMESTAMP";
247
+ return `'${value}'`;
248
+ }
249
+ if (typeof value === "boolean") return value ? "1" : "0";
250
+ return String(value);
251
+ }
252
+ generateIndex(tableName, index) {
253
+ const unique = index.unique ? "UNIQUE " : "";
254
+ const columns = index.columns.map((col) => `"${col}"`).join(", ");
255
+ return `CREATE ${unique}INDEX "${index.name}" ON "${tableName}" (${columns});`;
256
+ }
257
+ };
258
+ }) });
10
259
 
11
- `)}generateDropTable(e){return`DROP TABLE IF EXISTS \`${e}\`;`}generateColumnDefinition(e){let t=[`\`${e.name}\``];if(t.push(this.getColumnType(e)),e.notNull&&!e.primaryKey&&e.type!==`serial`&&e.type!==`bigserial`&&t.push(`NOT NULL`),e.unique&&t.push(`UNIQUE`),(e.type===`serial`||e.type===`bigserial`)&&t.push(`AUTO_INCREMENT`),e.default!==void 0&&t.push(`DEFAULT ${this.formatDefault(e.default)}`),e.references){let n=e.references;t.push(`REFERENCES \`${n.table}\`(\`${n.column}\`)`),n.onDelete&&t.push(`ON DELETE ${n.onDelete}`),n.onUpdate&&t.push(`ON UPDATE ${n.onUpdate}`)}return e.check&&t.push(`CHECK (${e.check})`),t.join(` `)}getColumnType(e){let t=e.type;if(t===`serial`)return`INT`;if(t===`bigserial`)return`BIGINT`;if(t===`timestamptz`)return`TIMESTAMP`;if(t===`jsonb`)return`JSON`;if(t===`bytea`)return`BLOB`;if(t===`double precision`)return`DOUBLE`;let n=t.toUpperCase();return e.length?n+=`(${e.length})`:e.precision&&(e.scale===void 0?n+=`(${e.precision})`:n+=`(${e.precision}, ${e.scale})`),n}formatDefault(e){return typeof e==`string`?e.toUpperCase()===`NOW()`||e.toUpperCase()===`CURRENT_TIMESTAMP`?`CURRENT_TIMESTAMP`:`'${e}'`:typeof e==`boolean`?e?`1`:`0`:String(e)}generateIndex(e,t){let n=t.unique?`UNIQUE `:``,r=t.type&&t.type!==`btree`?` USING ${t.type.toUpperCase()}`:``,i=t.columns.map(e=>`\`${e}\``).join(`, `);return`CREATE ${n}INDEX \`${t.name}\` ON \`${e}\`${r} (${i});`}}})),y=e({SQLiteGenerator:()=>b}),b,x=t((()=>{b=class{generateCreateTable(e){let t=[];t.push(`CREATE TABLE "${e.name}" (`);let n=[];for(let t of e.columns)n.push(` `+this.generateColumnDefinition(t));if(e.primaryKey&&e.primaryKey.length>0){let t=e.primaryKey.map(e=>`"${e}"`).join(`, `);n.push(` PRIMARY KEY (${t})`)}if(e.checks&&e.checks.length>0)for(let t of e.checks)n.push(` CONSTRAINT "${t.name}" CHECK (${t.expression})`);t.push(n.join(`,
12
- `)),t.push(`);`);let r=[t.join(`
13
- `)];if(e.indexes&&e.indexes.length>0)for(let t of e.indexes)r.push(this.generateIndex(e.name,t));return r.join(`
260
+ //#endregion
261
+ //#region src/schema/migration.ts
262
+ init_postgres();
263
+ init_mysql();
264
+ init_sqlite();
265
+ var MigrationBuilder = class {
266
+ upStatements = [];
267
+ downStatements = [];
268
+ dialect;
269
+ constructor(dialect = "postgres") {
270
+ this.dialect = dialect;
271
+ }
272
+ createTable(table) {
273
+ const tableDef = table.getDefinition();
274
+ const generator = this.getGenerator();
275
+ this.upStatements.push(generator.generateCreateTable(tableDef));
276
+ this.downStatements.unshift(generator.generateDropTable(tableDef.name));
277
+ return this;
278
+ }
279
+ dropTable(tableName) {
280
+ const generator = this.getGenerator();
281
+ this.upStatements.push(generator.generateDropTable(tableName));
282
+ return this;
283
+ }
284
+ addColumn(tableName, columnSql) {
285
+ this.upStatements.push(`ALTER TABLE "${tableName}" ADD COLUMN ${columnSql};`);
286
+ return this;
287
+ }
288
+ dropColumn(tableName, columnName) {
289
+ this.upStatements.push(`ALTER TABLE "${tableName}" DROP COLUMN "${columnName}";`);
290
+ return this;
291
+ }
292
+ renameTable(oldName, newName) {
293
+ if (this.dialect === "postgres") this.upStatements.push(`ALTER TABLE "${oldName}" RENAME TO "${newName}";`);
294
+ else if (this.dialect === "mysql") this.upStatements.push(`RENAME TABLE \`${oldName}\` TO \`${newName}\`;`);
295
+ else this.upStatements.push(`ALTER TABLE "${oldName}" RENAME TO "${newName}";`);
296
+ return this;
297
+ }
298
+ raw(sql, downSql) {
299
+ this.upStatements.push(sql);
300
+ if (downSql) this.downStatements.unshift(downSql);
301
+ return this;
302
+ }
303
+ build(version, name) {
304
+ return {
305
+ version,
306
+ name,
307
+ up: this.upStatements,
308
+ down: this.downStatements
309
+ };
310
+ }
311
+ getGenerator() {
312
+ switch (this.dialect) {
313
+ case "postgres": return new PostgresGenerator();
314
+ case "mysql": return new MySQLGenerator();
315
+ case "sqlite": return new SQLiteGenerator();
316
+ default: return new PostgresGenerator();
317
+ }
318
+ }
319
+ };
320
+ function createMigration(dialect = "postgres") {
321
+ return new MigrationBuilder(dialect);
322
+ }
14
323
 
15
- `)}generateDropTable(e){return`DROP TABLE IF EXISTS "${e}";`}generateColumnDefinition(e){let t=[`"${e.name}"`];if(t.push(this.getColumnType(e)),e.primaryKey&&(t.push(`PRIMARY KEY`),(e.type===`serial`||e.type===`bigserial`)&&t.push(`AUTOINCREMENT`)),e.notNull&&!e.primaryKey&&t.push(`NOT NULL`),e.unique&&t.push(`UNIQUE`),e.default!==void 0&&t.push(`DEFAULT ${this.formatDefault(e.default)}`),e.references){let n=e.references;t.push(`REFERENCES "${n.table}"("${n.column}")`),n.onDelete&&t.push(`ON DELETE ${n.onDelete}`),n.onUpdate&&t.push(`ON UPDATE ${n.onUpdate}`)}return e.check&&t.push(`CHECK (${e.check})`),t.join(` `)}getColumnType(e){let t=e.type;return t===`serial`||t===`bigserial`||t===`bigint`||t===`smallint`?`INTEGER`:t===`varchar`||t===`char`||t===`timestamptz`||t===`timestamp`||t===`date`||t===`time`||t===`uuid`||t===`json`||t===`jsonb`?`TEXT`:t===`bytea`?`BLOB`:t===`decimal`||t===`numeric`||t===`real`||t===`double precision`?`REAL`:t===`boolean`?`INTEGER`:t.toUpperCase()}formatDefault(e){return typeof e==`string`?e.toUpperCase()===`NOW()`||e.toUpperCase()===`CURRENT_TIMESTAMP`?`CURRENT_TIMESTAMP`:`'${e}'`:typeof e==`boolean`?e?`1`:`0`:String(e)}generateIndex(e,t){let n=t.unique?`UNIQUE `:``,r=t.columns.map(e=>`"${e}"`).join(`, `);return`CREATE ${n}INDEX "${t.name}" ON "${e}" (${r});`}}}));n(),v(),x();var S=class{upStatements=[];downStatements=[];dialect;constructor(e=`postgres`){this.dialect=e}createTable(e){let t=e.getDefinition(),n=this.getGenerator();return this.upStatements.push(n.generateCreateTable(t)),this.downStatements.unshift(n.generateDropTable(t.name)),this}dropTable(e){let t=this.getGenerator();return this.upStatements.push(t.generateDropTable(e)),this}addColumn(e,t){return this.upStatements.push(`ALTER TABLE "${e}" ADD COLUMN ${t};`),this}dropColumn(e,t){return this.upStatements.push(`ALTER TABLE "${e}" DROP COLUMN "${t}";`),this}renameTable(e,t){return this.dialect===`postgres`?this.upStatements.push(`ALTER TABLE "${e}" RENAME TO "${t}";`):this.dialect===`mysql`?this.upStatements.push(`RENAME TABLE \`${e}\` TO \`${t}\`;`):this.upStatements.push(`ALTER TABLE "${e}" RENAME TO "${t}";`),this}raw(e,t){return this.upStatements.push(e),t&&this.downStatements.unshift(t),this}build(e,t){return{version:e,name:t,up:this.upStatements,down:this.downStatements}}getGenerator(){switch(this.dialect){case`postgres`:return new a;case`mysql`:return new _;case`sqlite`:return new b;default:return new a}}};function ee(e=`postgres`){return new S(e)}var C=class{dialect;constructor(e=`postgres`){this.dialect=e}detectChanges(e,t){let n=[],r=new Map(e.map(e=>[e.name,e])),i=new Map(t.map(e=>[e.name,e]));for(let[e,t]of i){let i=r.get(e);i?(n.push(...this.detectColumnChanges(i,t)),n.push(...this.detectIndexChanges(i,t))):n.push({type:`create_table`,table:e,details:t})}for(let[e]of r)i.has(e)||n.push({type:`drop_table`,table:e});return n}detectColumnChanges(e,t){let n=[],r=new Map(e.columns.map(e=>[e.name,e])),i=new Map(t.columns.map(e=>[e.name,e]));for(let[e,a]of i){let i=r.get(e);i?this.hasColumnChanged(i,a)&&n.push({type:`modify_column`,table:t.name,details:{old:i,new:a}}):n.push({type:`add_column`,table:t.name,details:a})}for(let[e]of r)i.has(e)||n.push({type:`drop_column`,table:t.name,details:{name:e}});return n}detectIndexChanges(e,t){let n=[],r=new Map((e.indexes||[]).map(e=>[e.name,e])),i=new Map((t.indexes||[]).map(e=>[e.name,e]));for(let[e,a]of i)r.has(e)||n.push({type:`create_index`,table:t.name,details:a});for(let[e]of r)i.has(e)||n.push({type:`drop_index`,table:t.name,details:{name:e}});return n}hasColumnChanged(e,t){return e.type!==t.type||e.length!==t.length||e.precision!==t.precision||e.scale!==t.scale||e.notNull!==t.notNull||e.unique!==t.unique||e.default!==t.default||JSON.stringify(e.references)!==JSON.stringify(t.references)}generateMigration(e,t,n){let r=new S(this.dialect);for(let t of e)switch(t.type){case`create_table`:{let e=t.details,n=this.getGenerator(),i=n.generateCreateTable(e);r.raw(i,n.generateDropTable(e.name));break}case`drop_table`:{let e=this.getGenerator();r.raw(e.generateDropTable(t.table));break}case`add_column`:{let e=t.details,n=this.generateColumnSQL(e);r.raw(`ALTER TABLE "${t.table}" ADD COLUMN ${n};`,`ALTER TABLE "${t.table}" DROP COLUMN "${e.name}";`);break}case`drop_column`:{let e=t.details.name;r.raw(`ALTER TABLE "${t.table}" DROP COLUMN "${e}";`);break}case`create_index`:{let e=t.details,n=this.generateIndexSQL(t.table,e);r.raw(n,`DROP INDEX "${e.name}";`);break}case`drop_index`:{let e=t.details.name;r.raw(`DROP INDEX "${e}";`);break}}return r}generateColumnSQL(e){let t=[`"${e.name}"`];return t.push(e.type.toUpperCase()),e.length&&(t[1]+=`(${e.length})`),e.notNull&&t.push(`NOT NULL`),e.unique&&t.push(`UNIQUE`),e.default!==void 0&&t.push(`DEFAULT ${this.formatDefault(e.default)}`),t.join(` `)}generateIndexSQL(e,t){let n=t.unique?`UNIQUE `:``,r=t.columns.map(e=>`"${e}"`).join(`, `);return`CREATE ${n}INDEX "${t.name}" ON "${e}" (${r});`}formatDefault(e){return typeof e==`string`?e.toUpperCase()===`NOW()`||e.toUpperCase()===`CURRENT_TIMESTAMP`?e.toUpperCase():`'${e}'`:typeof e==`boolean`?e?`TRUE`:`FALSE`:String(e)}getGenerator(){let{PostgresGenerator:e}=(n(),r(i)),{MySQLGenerator:t}=(v(),r(g)),{SQLiteGenerator:a}=(x(),r(y));switch(this.dialect){case`postgres`:return new e;case`mysql`:return new t;case`sqlite`:return new a;default:return new e}}};function w(e,t,n=`postgres`){return new C(n).detectChanges(e,t)}function T(e,t,n,r=`postgres`){return new C(r).generateMigration(e,t,n)}const E=new c;E.name(`driftsql`).description(`DriftSQL CLI - Database migrations and schema management`).version(`0.0.1`),E.command(`migrate:up`).description(`Run all pending migrations`).option(`-d, --dir <directory>`,`Migrations directory`,`./migrations`).option(`-c, --config <path>`,`Config file path`,`./driftsql.config.ts`).action(async e=>{try{let{client:t,migrations:n}=await O(e.dir,e.config);await new m(t).upAll(n),await t.close(),l.success(`All migrations applied successfully`)}catch(e){l.error(`Migration failed:`,e),process.exit(1)}}),E.command(`migrate:down`).description(`Rollback the last migration`).option(`-d, --dir <directory>`,`Migrations directory`,`./migrations`).option(`-c, --config <path>`,`Config file path`,`./driftsql.config.ts`).action(async e=>{try{let{client:t,migrations:n}=await O(e.dir,e.config),r=new m(t),i=await r.getAppliedMigrations(),a=n.find(e=>e.version===i[i.length-1]);a?await r.down(a):l.info(`No migrations to rollback`),await t.close()}catch(e){l.error(`Rollback failed:`,e),process.exit(1)}}),E.command(`migrate:reset`).description(`Reset all migrations (down then up)`).option(`-d, --dir <directory>`,`Migrations directory`,`./migrations`).option(`-c, --config <path>`,`Config file path`,`./driftsql.config.ts`).action(async e=>{try{let{client:t,migrations:n}=await O(e.dir,e.config);await new m(t).reset(n),await t.close(),l.success(`All migrations reset successfully`)}catch(e){l.error(`Reset failed:`,e),process.exit(1)}}),E.command(`migrate:status`).description(`Show migration status`).option(`-d, --dir <directory>`,`Migrations directory`,`./migrations`).option(`-c, --config <path>`,`Config file path`,`./driftsql.config.ts`).action(async e=>{try{let{client:t,migrations:n}=await O(e.dir,e.config),r=await new m(t).getAppliedMigrations();l.info(`Migration Status:
16
- `);for(let e of n){let t=r.includes(e.version)?`✓ Applied`:`✗ Pending`;l.log(`${t} - ${e.version} (${e.name})`)}await t.close()}catch(e){l.error(`Failed to get status:`,e),process.exit(1)}}),E.command(`migrate:create <name>`).description(`Create a new migration file`).option(`-d, --dir <directory>`,`Migrations directory`,`./migrations`).action(async(e,t)=>{try{let n=new Date().toISOString().replace(/[-:T.]/g,``).slice(0,14),r=`${n}_${e}.ts`,i=d.join(t.dir,r);await u.mkdir(t.dir,{recursive:!0});let a=`import { createMigration } from 'driftsql'
324
+ //#endregion
325
+ //#region src/schema/differ.ts
326
+ var SchemaDiffer = class {
327
+ dialect;
328
+ constructor(dialect = "postgres") {
329
+ this.dialect = dialect;
330
+ }
331
+ detectChanges(oldSchema, newSchema) {
332
+ const changes = [];
333
+ const oldTables = new Map(oldSchema.map((t) => [t.name, t]));
334
+ const newTables = new Map(newSchema.map((t) => [t.name, t]));
335
+ for (const [tableName, newTable] of newTables) {
336
+ const oldTable = oldTables.get(tableName);
337
+ if (!oldTable) changes.push({
338
+ type: "create_table",
339
+ table: tableName,
340
+ details: newTable
341
+ });
342
+ else {
343
+ changes.push(...this.detectColumnChanges(oldTable, newTable));
344
+ changes.push(...this.detectIndexChanges(oldTable, newTable));
345
+ }
346
+ }
347
+ for (const [tableName] of oldTables) if (!newTables.has(tableName)) changes.push({
348
+ type: "drop_table",
349
+ table: tableName
350
+ });
351
+ return changes;
352
+ }
353
+ detectColumnChanges(oldTable, newTable) {
354
+ const changes = [];
355
+ const oldColumns = new Map(oldTable.columns.map((c) => [c.name, c]));
356
+ const newColumns = new Map(newTable.columns.map((c) => [c.name, c]));
357
+ for (const [colName, newCol] of newColumns) {
358
+ const oldCol = oldColumns.get(colName);
359
+ if (!oldCol) changes.push({
360
+ type: "add_column",
361
+ table: newTable.name,
362
+ details: newCol
363
+ });
364
+ else if (this.hasColumnChanged(oldCol, newCol)) changes.push({
365
+ type: "modify_column",
366
+ table: newTable.name,
367
+ details: {
368
+ old: oldCol,
369
+ new: newCol
370
+ }
371
+ });
372
+ }
373
+ for (const [colName] of oldColumns) if (!newColumns.has(colName)) changes.push({
374
+ type: "drop_column",
375
+ table: newTable.name,
376
+ details: { name: colName }
377
+ });
378
+ return changes;
379
+ }
380
+ detectIndexChanges(oldTable, newTable) {
381
+ const changes = [];
382
+ const oldIndexes = new Map((oldTable.indexes || []).map((i) => [i.name, i]));
383
+ const newIndexes = new Map((newTable.indexes || []).map((i) => [i.name, i]));
384
+ for (const [idxName, newIdx] of newIndexes) if (!oldIndexes.has(idxName)) changes.push({
385
+ type: "create_index",
386
+ table: newTable.name,
387
+ details: newIdx
388
+ });
389
+ for (const [idxName] of oldIndexes) if (!newIndexes.has(idxName)) changes.push({
390
+ type: "drop_index",
391
+ table: newTable.name,
392
+ details: { name: idxName }
393
+ });
394
+ return changes;
395
+ }
396
+ hasColumnChanged(oldCol, newCol) {
397
+ return oldCol.type !== newCol.type || oldCol.length !== newCol.length || oldCol.precision !== newCol.precision || oldCol.scale !== newCol.scale || oldCol.notNull !== newCol.notNull || oldCol.unique !== newCol.unique || oldCol.default !== newCol.default || JSON.stringify(oldCol.references) !== JSON.stringify(newCol.references);
398
+ }
399
+ generateMigration(changes, version, name) {
400
+ const migration = new MigrationBuilder(this.dialect);
401
+ for (const change of changes) switch (change.type) {
402
+ case "create_table": {
403
+ const tableDef = change.details;
404
+ const generator = this.getGenerator();
405
+ const sql = generator.generateCreateTable(tableDef);
406
+ migration.raw(sql, generator.generateDropTable(tableDef.name));
407
+ break;
408
+ }
409
+ case "drop_table": {
410
+ const generator = this.getGenerator();
411
+ migration.raw(generator.generateDropTable(change.table));
412
+ break;
413
+ }
414
+ case "add_column": {
415
+ const col = change.details;
416
+ const colSql = this.generateColumnSQL(col);
417
+ migration.raw(`ALTER TABLE "${change.table}" ADD COLUMN ${colSql};`, `ALTER TABLE "${change.table}" DROP COLUMN "${col.name}";`);
418
+ break;
419
+ }
420
+ case "drop_column": {
421
+ const colName = change.details.name;
422
+ migration.raw(`ALTER TABLE "${change.table}" DROP COLUMN "${colName}";`);
423
+ break;
424
+ }
425
+ case "create_index": {
426
+ const idx = change.details;
427
+ const sql = this.generateIndexSQL(change.table, idx);
428
+ migration.raw(sql, `DROP INDEX "${idx.name}";`);
429
+ break;
430
+ }
431
+ case "drop_index": {
432
+ const idxName = change.details.name;
433
+ migration.raw(`DROP INDEX "${idxName}";`);
434
+ break;
435
+ }
436
+ }
437
+ return migration;
438
+ }
439
+ generateColumnSQL(col) {
440
+ const parts = [`"${col.name}"`];
441
+ parts.push(col.type.toUpperCase());
442
+ if (col.length) parts[1] += `(${col.length})`;
443
+ if (col.notNull) parts.push("NOT NULL");
444
+ if (col.unique) parts.push("UNIQUE");
445
+ if (col.default !== void 0) parts.push(`DEFAULT ${this.formatDefault(col.default)}`);
446
+ return parts.join(" ");
447
+ }
448
+ generateIndexSQL(tableName, idx) {
449
+ const unique = idx.unique ? "UNIQUE " : "";
450
+ const columns = idx.columns.map((col) => `"${col}"`).join(", ");
451
+ return `CREATE ${unique}INDEX "${idx.name}" ON "${tableName}" (${columns});`;
452
+ }
453
+ formatDefault(value) {
454
+ if (typeof value === "string") {
455
+ if (value.toUpperCase() === "NOW()" || value.toUpperCase() === "CURRENT_TIMESTAMP") return value.toUpperCase();
456
+ return `'${value}'`;
457
+ }
458
+ if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
459
+ return String(value);
460
+ }
461
+ getGenerator() {
462
+ const { PostgresGenerator: PostgresGenerator$1 } = (init_postgres(), __toCommonJS(postgres_exports));
463
+ const { MySQLGenerator: MySQLGenerator$1 } = (init_mysql(), __toCommonJS(mysql_exports));
464
+ const { SQLiteGenerator: SQLiteGenerator$1 } = (init_sqlite(), __toCommonJS(sqlite_exports));
465
+ switch (this.dialect) {
466
+ case "postgres": return new PostgresGenerator$1();
467
+ case "mysql": return new MySQLGenerator$1();
468
+ case "sqlite": return new SQLiteGenerator$1();
469
+ default: return new PostgresGenerator$1();
470
+ }
471
+ }
472
+ };
473
+ function detectChanges(oldSchema, newSchema, dialect = "postgres") {
474
+ return new SchemaDiffer(dialect).detectChanges(oldSchema, newSchema);
475
+ }
476
+ function generateMigrationFromChanges(changes, version, name, dialect = "postgres") {
477
+ return new SchemaDiffer(dialect).generateMigration(changes, version, name);
478
+ }
479
+
480
+ //#endregion
481
+ //#region src/cli/index.ts
482
+ const program = new Command();
483
+ program.name("driftsql").description("DriftSQL CLI - Database migrations and schema management").version("0.0.1");
484
+ program.command("migrate:up").description("Run all pending migrations").option("-d, --dir <directory>", "Migrations directory", "./migrations").option("-c, --config <path>", "Config file path", "./driftsql.config.ts").action(async (options) => {
485
+ try {
486
+ const { client, migrations } = await loadMigrations(options.dir, options.config);
487
+ await new MigrationRunner(client).upAll(migrations);
488
+ await client.close();
489
+ consola.success("All migrations applied successfully");
490
+ } catch (error) {
491
+ consola.error("Migration failed:", error);
492
+ process.exit(1);
493
+ }
494
+ });
495
+ program.command("migrate:down").description("Rollback the last migration").option("-d, --dir <directory>", "Migrations directory", "./migrations").option("-c, --config <path>", "Config file path", "./driftsql.config.ts").action(async (options) => {
496
+ try {
497
+ const { client, migrations } = await loadMigrations(options.dir, options.config);
498
+ const runner = new MigrationRunner(client);
499
+ const applied = await runner.getAppliedMigrations();
500
+ const lastMigration = migrations.find((m) => m.version === applied[applied.length - 1]);
501
+ if (lastMigration) await runner.down(lastMigration);
502
+ else consola.info("No migrations to rollback");
503
+ await client.close();
504
+ } catch (error) {
505
+ consola.error("Rollback failed:", error);
506
+ process.exit(1);
507
+ }
508
+ });
509
+ program.command("migrate:reset").description("Reset all migrations (down then up)").option("-d, --dir <directory>", "Migrations directory", "./migrations").option("-c, --config <path>", "Config file path", "./driftsql.config.ts").action(async (options) => {
510
+ try {
511
+ const { client, migrations } = await loadMigrations(options.dir, options.config);
512
+ await new MigrationRunner(client).reset(migrations);
513
+ await client.close();
514
+ consola.success("All migrations reset successfully");
515
+ } catch (error) {
516
+ consola.error("Reset failed:", error);
517
+ process.exit(1);
518
+ }
519
+ });
520
+ program.command("migrate:status").description("Show migration status").option("-d, --dir <directory>", "Migrations directory", "./migrations").option("-c, --config <path>", "Config file path", "./driftsql.config.ts").action(async (options) => {
521
+ try {
522
+ const { client, migrations } = await loadMigrations(options.dir, options.config);
523
+ const applied = await new MigrationRunner(client).getAppliedMigrations();
524
+ consola.info("Migration Status:\n");
525
+ for (const migration of migrations) {
526
+ const status = applied.includes(migration.version) ? "✓ Applied" : "✗ Pending";
527
+ consola.log(`${status} - ${migration.version} (${migration.name})`);
528
+ }
529
+ await client.close();
530
+ } catch (error) {
531
+ consola.error("Failed to get status:", error);
532
+ process.exit(1);
533
+ }
534
+ });
535
+ program.command("migrate:create <name>").description("Create a new migration file").option("-d, --dir <directory>", "Migrations directory", "./migrations").action(async (name, options) => {
536
+ try {
537
+ const version = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:T.]/g, "").slice(0, 14);
538
+ const fileName = `${version}_${name}.ts`;
539
+ const filePath = path.join(options.dir, fileName);
540
+ await fs.mkdir(options.dir, { recursive: true });
541
+ const template = `import { createMigration } from 'driftsql'
17
542
 
18
543
  export const migration = createMigration('postgres')
19
544
  .raw('-- Add your migration SQL here')
20
- .build('${n}', '${e}')
21
- `;await u.writeFile(i,a,`utf8`),l.success(`Created migration: ${r}`)}catch(e){l.error(`Failed to create migration:`,e),process.exit(1)}}),E.command(`migrate:generate [name]`).description(`Automatically generate migration from schema changes`).option(`-s, --schema <path>`,`Schema file path`,`./schema.ts`).option(`-d, --dir <directory>`,`Migrations directory`,`./migrations`).action(async(e,t)=>{try{let n=new h,r=d.resolve(process.cwd(),t.schema);l.start(`Loading schema...`);let i=await import(r),a=i.default||i.schema;(!a||!Array.isArray(a))&&(l.error(`Schema file must export default or named "schema" as an array of table definitions`),l.info(`Example: export default [usersTable.getDefinition(), postsTable.getDefinition()]`),process.exit(1));let o=a,s=await n.load();if(!s){l.info(`No previous schema snapshot found, creating initial migration...`);let r=new Date().toISOString().replace(/[-:T.]/g,``).slice(0,14),i=e||`initial`,a=`${r}_${i}.ts`,s=d.join(t.dir,a);await u.mkdir(t.dir,{recursive:!0});let{PostgresGenerator:c}=await import(`./postgres-DWtAqXNK.js`),f=new c,p=o.map(e=>f.generateCreateTable(e)).map(e=>` .raw(\`${e.replace(/`/g,"\\`")}\`)`).join(`
22
- `),m=`import { createMigration } from 'driftsql'
545
+ .build('${version}', '${name}')
546
+ `;
547
+ await fs.writeFile(filePath, template, "utf8");
548
+ consola.success(`Created migration: ${fileName}`);
549
+ } catch (error) {
550
+ consola.error("Failed to create migration:", error);
551
+ process.exit(1);
552
+ }
553
+ });
554
+ program.command("migrate:generate [name]").description("Automatically generate migration from schema changes").option("-s, --schema <path>", "Schema file path", "./schema.ts").option("-d, --dir <directory>", "Migrations directory", "./migrations").action(async (name, options) => {
555
+ try {
556
+ const snapshotManager = new SnapshotManager();
557
+ const schemaPath = path.resolve(process.cwd(), options.schema);
558
+ consola.start("Loading schema...");
559
+ const schemaModule = await import(schemaPath);
560
+ const schema = schemaModule.default || schemaModule.schema;
561
+ if (!schema || !Array.isArray(schema)) {
562
+ consola.error("Schema file must export default or named \"schema\" as an array of table definitions");
563
+ consola.info("Example: export default [usersTable.getDefinition(), postsTable.getDefinition()]");
564
+ process.exit(1);
565
+ }
566
+ const currentSchema = schema;
567
+ const snapshot = await snapshotManager.load();
568
+ if (!snapshot) {
569
+ consola.info("No previous schema snapshot found, creating initial migration...");
570
+ const version$1 = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:T.]/g, "").slice(0, 14);
571
+ const migrationName$1 = name || "initial";
572
+ const fileName$1 = `${version$1}_${migrationName$1}.ts`;
573
+ const filePath$1 = path.join(options.dir, fileName$1);
574
+ await fs.mkdir(options.dir, { recursive: true });
575
+ const { PostgresGenerator: PostgresGenerator$1 } = await import("./postgres-CFQEP3ft.js");
576
+ const generator = new PostgresGenerator$1();
577
+ const upSQL$1 = currentSchema.map((table) => generator.generateCreateTable(table)).map((sql) => ` .raw(\`${sql.replace(/`/g, "\\`")}\`)`).join("\n");
578
+ const migrationContent$1 = `import { createMigration } from 'driftsql'
23
579
 
24
580
  // Initial migration - automatically generated
25
- // Generated at: ${new Date().toISOString()}
581
+ // Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}
26
582
 
27
583
  export const migration = createMigration('postgres')
28
- ${p}
29
- .build('${r}', '${i}')
30
- `;await u.writeFile(s,m,`utf8`),await n.save(o);let{generateTypesFromSchema:h}=await import(`./type-generator-DbcqBk-4.js`);await h(o,d.join(process.cwd(),`db-types.ts`)),l.success(`\nCreated initial migration: ${a}`),l.success(`Generated TypeScript types: db-types.ts`),l.info(`Snapshot saved. Run "driftsql migrate:up" to apply changes.`);return}l.info(`Detecting changes...`);let c=w(s.tables,o,`postgres`);if(c.length===0){l.success(`No schema changes detected!`);return}l.info(`Found ${c.length} change(s):`),c.forEach((e,t)=>{l.log(` ${t+1}. ${e.type} - ${e.table}`)});let f=new Date().toISOString().replace(/[-:T.]/g,``).slice(0,14),p=e||`auto_migration`,m=`${f}_${p}.ts`,g=d.join(t.dir,m);await u.mkdir(t.dir,{recursive:!0});let _=T(c,f,p).build(f,p).up.map(e=>` .raw(\`${e.replace(/`/g,"\\`")}\``).join(`
31
- `),v=`import { createMigration } from 'driftsql'
584
+ ${upSQL$1}
585
+ .build('${version$1}', '${migrationName$1}')
586
+ `;
587
+ await fs.writeFile(filePath$1, migrationContent$1, "utf8");
588
+ await snapshotManager.save(currentSchema);
589
+ const { generateTypesFromSchema: generateTypesFromSchema$2 } = await import("./type-generator-DbcqBk-4.js");
590
+ await generateTypesFromSchema$2(currentSchema, path.join(process.cwd(), "db-types.ts"));
591
+ consola.success(`\nCreated initial migration: ${fileName$1}`);
592
+ consola.success(`Generated TypeScript types: db-types.ts`);
593
+ consola.info("Snapshot saved. Run \"driftsql migrate:up\" to apply changes.");
594
+ return;
595
+ }
596
+ consola.info("Detecting changes...");
597
+ const changes = detectChanges(snapshot.tables, currentSchema, "postgres");
598
+ if (changes.length === 0) {
599
+ consola.success("No schema changes detected!");
600
+ return;
601
+ }
602
+ consola.info(`Found ${changes.length} change(s):`);
603
+ changes.forEach((change, idx) => {
604
+ consola.log(` ${idx + 1}. ${change.type} - ${change.table}`);
605
+ });
606
+ const version = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:T.]/g, "").slice(0, 14);
607
+ const migrationName = name || "auto_migration";
608
+ const fileName = `${version}_${migrationName}.ts`;
609
+ const filePath = path.join(options.dir, fileName);
610
+ await fs.mkdir(options.dir, { recursive: true });
611
+ const upSQL = generateMigrationFromChanges(changes, version, migrationName).build(version, migrationName).up.map((sql) => ` .raw(\`${sql.replace(/`/g, "\\`")}\``).join("\n");
612
+ const migrationContent = `import { createMigration } from 'driftsql'
32
613
 
33
614
  // This migration was automatically generated
34
- // Generated at: ${new Date().toISOString()}
35
- // Changes: ${c.length}
615
+ // Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}
616
+ // Changes: ${changes.length}
36
617
 
37
618
  export const migration = createMigration('postgres')
38
- ${_}
39
- .build('${f}', '${p}')
40
- `;await u.writeFile(g,v,`utf8`),await n.save(o);let{generateTypesFromSchema:y}=await import(`./type-generator-DbcqBk-4.js`);await y(o,d.join(process.cwd(),`db-types.ts`)),l.success(`\nGenerated migration: ${m}`),l.success(`Updated TypeScript types: db-types.ts`),l.info(`Snapshot updated. Run "driftsql migrate:up" to apply changes.`)}catch(e){l.error(`Failed to generate migration:`,e),process.exit(1)}}),E.command(`db:inspect`).description(`Inspect database and generate TypeScript types`).option(`-c, --config <path>`,`Config file path`,`./driftsql.config.ts`).option(`-o, --output <path>`,`Output file path`,`./db-types.ts`).action(async e=>{try{let t=await D(e.config);await t.inspectDB({driver:t.getDriver(),outputFile:e.output}),await t.close()}catch(e){l.error(`Inspection failed:`,e),process.exit(1)}}),E.command(`generate:types`).description(`Generate TypeScript types from schema file`).option(`-s, --schema <path>`,`Schema file path`,`./schema.ts`).option(`-o, --output <path>`,`Output file path`,`./db-types.ts`).action(async e=>{try{let t=d.resolve(process.cwd(),e.schema),n=d.resolve(process.cwd(),e.output);l.start(`Loading schema...`);let r=await import(t),i=r.default||r.schema;(!i||!Array.isArray(i))&&(l.error(`Schema file must export default or named "schema" as an array of table definitions`),process.exit(1));let{generateTypesFromSchema:a}=await import(`./type-generator-DbcqBk-4.js`);await a(i,n),l.success(`TypeScript types generated: ${e.output}`)}catch(e){l.error(`Type generation failed:`,e),process.exit(1)}}),E.command(`init`).description(`Initialize DriftSQL with a basic notes schema`).option(`-d, --dir <directory>`,`Migrations directory`,`./migrations`).action(async e=>{try{await u.mkdir(e.dir,{recursive:!0});let t=`.driftsql/
41
- .env
42
- `,n=d.join(process.cwd(),`driftsql.config.ts`),r=d.join(process.cwd(),`schema.ts`),i=d.join(process.cwd(),`.env.example`),a=d.join(process.cwd(),`.gitignore`),o=[{path:n,content:`import { SQLClient, PostgresDriver } from 'driftsql'
619
+ ${upSQL}
620
+ .build('${version}', '${migrationName}')
621
+ `;
622
+ await fs.writeFile(filePath, migrationContent, "utf8");
623
+ await snapshotManager.save(currentSchema);
624
+ const { generateTypesFromSchema: generateTypesFromSchema$1 } = await import("./type-generator-DbcqBk-4.js");
625
+ await generateTypesFromSchema$1(currentSchema, path.join(process.cwd(), "db-types.ts"));
626
+ consola.success(`\nGenerated migration: ${fileName}`);
627
+ consola.success(`Updated TypeScript types: db-types.ts`);
628
+ consola.info("Snapshot updated. Run \"driftsql migrate:up\" to apply changes.");
629
+ } catch (error) {
630
+ consola.error("Failed to generate migration:", error);
631
+ process.exit(1);
632
+ }
633
+ });
634
+ program.command("db:inspect").description("Inspect database and generate TypeScript types").option("-c, --config <path>", "Config file path", "./driftsql.config.ts").option("-o, --output <path>", "Output file path", "./db-types.ts").action(async (options) => {
635
+ try {
636
+ const client = await loadClient(options.config);
637
+ await client.inspectDB({
638
+ driver: client.getDriver(),
639
+ outputFile: options.output
640
+ });
641
+ await client.close();
642
+ } catch (error) {
643
+ consola.error("Inspection failed:", error);
644
+ process.exit(1);
645
+ }
646
+ });
647
+ program.command("generate:types").description("Generate TypeScript types from schema file").option("-s, --schema <path>", "Schema file path", "./schema.ts").option("-o, --output <path>", "Output file path", "./db-types.ts").action(async (options) => {
648
+ try {
649
+ const schemaPath = path.resolve(process.cwd(), options.schema);
650
+ const outputPath = path.resolve(process.cwd(), options.output);
651
+ consola.start("Loading schema...");
652
+ const schemaModule = await import(schemaPath);
653
+ const schema = schemaModule.default || schemaModule.schema;
654
+ if (!schema || !Array.isArray(schema)) {
655
+ consola.error("Schema file must export default or named \"schema\" as an array of table definitions");
656
+ process.exit(1);
657
+ }
658
+ const { generateTypesFromSchema: generateTypesFromSchema$1 } = await import("./type-generator-DbcqBk-4.js");
659
+ await generateTypesFromSchema$1(schema, outputPath);
660
+ consola.success(`TypeScript types generated: ${options.output}`);
661
+ } catch (error) {
662
+ consola.error("Type generation failed:", error);
663
+ process.exit(1);
664
+ }
665
+ });
666
+ program.command("init").description("Initialize DriftSQL with a basic notes schema").option("-d, --dir <directory>", "Migrations directory", "./migrations").action(async (options) => {
667
+ try {
668
+ await fs.mkdir(options.dir, { recursive: true });
669
+ const configContent = `import { SQLClient, PostgresDriver } from 'driftsql'
43
670
 
44
671
  export default new SQLClient({
45
672
  driver: new PostgresDriver({
46
673
  connectionString: process.env.DATABASE_URL!,
47
674
  }),
48
675
  })
49
- `,name:`driftsql.config.ts`},{path:r,content:`import { createTable, serial, varchar, text, timestamp, boolean } from 'driftsql'
676
+ `;
677
+ const schemaContent = `import { createTable, serial, varchar, text, timestamp, boolean } from 'driftsql'
50
678
 
51
679
  const notesTable = createTable('notes', (table) => {
52
680
  table
@@ -62,23 +690,245 @@ const notesTable = createTable('notes', (table) => {
62
690
 
63
691
  // Export array of table definitions
64
692
  export default [notesTable.getDefinition()]
65
- `,name:`schema.ts`},{path:i,content:`DATABASE_URL=postgresql://user:password@localhost:5432/mydb
66
- `,name:`.env.example`}];for(let e of o)try{await u.access(e.path),l.warn(`${e.name} already exists, skipping...`)}catch{await u.writeFile(e.path,e.content,`utf8`),l.success(`Created ${e.name}`)}try{(await u.readFile(a,`utf8`)).includes(`.driftsql/`)||(await u.appendFile(a,`
67
- `+t),l.success(`Updated .gitignore`))}catch{await u.writeFile(a,t,`utf8`),l.success(`Created .gitignore`)}l.success(`
68
- DriftSQL initialized successfully!
69
- `),l.info(`Next steps:`),l.info(`1. Copy .env.example to .env and update DATABASE_URL`),l.info(`2. Run: driftsql migrate:generate initial (generates migration + types)`),l.info(`3. Run: driftsql migrate:up`),l.info(`4. Import Database type from db-types.ts for type safety`),l.info(`5. Edit schema.ts and run migrate:generate to auto-detect changes!
70
- `)}catch(e){l.error(`Initialization failed:`,e),process.exit(1)}});async function D(e){try{let t=await import(d.resolve(process.cwd(),e));return t.default||t.client}catch(t){throw l.error(`Failed to load config from ${e}`),t}}async function O(e,t){let n=await D(t),r=[];try{let t=d.resolve(process.cwd(),e),i=(await u.readdir(t)).filter(e=>e.endsWith(`.ts`)||e.endsWith(`.js`)).sort();for(let e of i){let n=await import(d.join(t,e)),i=n.migration||n.default;i&&r.push(i)}return{client:n,migrations:r}}catch(t){throw l.error(`Failed to load migrations from ${e}`),t}}E.parse();function k(e){return`transaction`in e&&typeof e.transaction==`function`}function A(e){return`prepare`in e&&typeof e.prepare==`function`}var j=class extends Error{constructor(e,t,n){super(e),this.driverType=t,this.originalError=n,this.name=`DatabaseError`}},M=class extends j{constructor(e,t,n){super(`Query failed: ${t}`,e,n),this.name=`QueryError`}};const N=(e,t=3e4)=>Promise.race([e,new Promise((e,n)=>setTimeout(()=>n(Error(`Query timeout after ${t}ms`)),t))]),P=async(e,t=3,n=1e3)=>{for(let r=1;r<=t;r++)try{return await e()}catch(e){if(r===t)throw e;let i=n*2**(r-1);l.warn(`Query attempt ${r} failed, retrying in ${i}ms...`,e),await new Promise(e=>setTimeout(e,i))}throw Error(`Max retries exceeded`)},F=(e,t=!1,n=`postgres`)=>{let r=t?` | null`:``;switch(e.toLowerCase()){case`uuid`:return`string${r}`;case`character varying`:case`varchar`:case`text`:case`char`:case`character`:case`longtext`:case`mediumtext`:case`tinytext`:return`string${r}`;case`integer`:case`int`:case`int4`:case`smallint`:case`int2`:case`bigint`:case`int8`:case`serial`:case`bigserial`:case`numeric`:case`decimal`:case`real`:case`float4`:case`double precision`:case`float8`:case`tinyint`:case`mediumint`:case`float`:case`double`:return`number${r}`;case`boolean`:case`bool`:case`bit`:return`boolean${r}`;case`timestamp`:case`timestamp with time zone`:case`timestamp without time zone`:case`timestamptz`:case`date`:case`time`:case`time with time zone`:case`time without time zone`:case`timetz`:case`interval`:case`datetime`:case`year`:return`Date${r}`;case`json`:case`jsonb`:return`any${r}`;case`array`:return`any[]${r}`;case`bytea`:case`binary`:case`varbinary`:case`blob`:case`longblob`:case`mediumblob`:case`tinyblob`:return`Buffer${r}`;case`enum`:case`set`:return`string${r}`;default:return l.warn(`Unknown ${n} type: ${e}, defaulting to 'any'`),`any${r}`}},te=e=>`${e.constructor.name||`unknown driver`}`;var ne=async e=>{l.warn(`inspectDB is experimental and may make mistakes when inspecting your database. However it will not destroy your database.`);let{driver:t,outputFile:n=`db-types.ts`}=e,r=te(t);l.start(`Inspecting database using ${r} driver`);let i=new $({driver:t}),a=``;try{let e,t;if(r===`mysql`){let n=(await N(P(()=>i.query("SELECT DATABASE() as `database`",[])),1e4)).rows[0]?.database;if(!n)throw Error(`Could not determine current MySQL database name`);l.success(`Using MySQL database: ${n}`),e=`SELECT TABLE_NAME as table_name
693
+ `;
694
+ const envContent = `DATABASE_URL=postgresql://user:password@localhost:5432/mydb
695
+ `;
696
+ const gitignoreContent = `.driftsql/
697
+ .env
698
+ `;
699
+ const configPath = path.join(process.cwd(), "driftsql.config.ts");
700
+ const schemaPath = path.join(process.cwd(), "schema.ts");
701
+ const envPath = path.join(process.cwd(), ".env.example");
702
+ const gitignorePath = path.join(process.cwd(), ".gitignore");
703
+ const filesToCreate = [
704
+ {
705
+ path: configPath,
706
+ content: configContent,
707
+ name: "driftsql.config.ts"
708
+ },
709
+ {
710
+ path: schemaPath,
711
+ content: schemaContent,
712
+ name: "schema.ts"
713
+ },
714
+ {
715
+ path: envPath,
716
+ content: envContent,
717
+ name: ".env.example"
718
+ }
719
+ ];
720
+ for (const file of filesToCreate) try {
721
+ await fs.access(file.path);
722
+ consola.warn(`${file.name} already exists, skipping...`);
723
+ } catch {
724
+ await fs.writeFile(file.path, file.content, "utf8");
725
+ consola.success(`Created ${file.name}`);
726
+ }
727
+ try {
728
+ if (!(await fs.readFile(gitignorePath, "utf8")).includes(".driftsql/")) {
729
+ await fs.appendFile(gitignorePath, "\n" + gitignoreContent);
730
+ consola.success("Updated .gitignore");
731
+ }
732
+ } catch {
733
+ await fs.writeFile(gitignorePath, gitignoreContent, "utf8");
734
+ consola.success("Created .gitignore");
735
+ }
736
+ consola.success("\n✨ DriftSQL initialized successfully!\n");
737
+ consola.info("Next steps:");
738
+ consola.info("1. Copy .env.example to .env and update DATABASE_URL");
739
+ consola.info("2. Run: driftsql migrate:generate initial (generates migration + types)");
740
+ consola.info("3. Run: driftsql migrate:up");
741
+ consola.info("4. Import Database type from db-types.ts for type safety");
742
+ consola.info("5. Edit schema.ts and run migrate:generate to auto-detect changes!\n");
743
+ } catch (error) {
744
+ consola.error("Initialization failed:", error);
745
+ process.exit(1);
746
+ }
747
+ });
748
+ async function loadClient(configPath) {
749
+ try {
750
+ const config = await import(path.resolve(process.cwd(), configPath));
751
+ return config.default || config.client;
752
+ } catch (error) {
753
+ consola.error(`Failed to load config from ${configPath}`);
754
+ throw error;
755
+ }
756
+ }
757
+ async function loadMigrations(migrationDir, configPath) {
758
+ const client = await loadClient(configPath);
759
+ const migrations = [];
760
+ try {
761
+ const dir = path.resolve(process.cwd(), migrationDir);
762
+ const tsFiles = (await fs.readdir(dir)).filter((f) => f.endsWith(".ts") || f.endsWith(".js")).sort();
763
+ for (const file of tsFiles) {
764
+ const module = await import(path.join(dir, file));
765
+ const migration = module.migration || module.default;
766
+ if (migration) migrations.push(migration);
767
+ }
768
+ return {
769
+ client,
770
+ migrations
771
+ };
772
+ } catch (error) {
773
+ consola.error(`Failed to load migrations from ${migrationDir}`);
774
+ throw error;
775
+ }
776
+ }
777
+ program.parse();
778
+
779
+ //#endregion
780
+ //#region src/types.ts
781
+ function hasTransactionSupport(driver) {
782
+ return "transaction" in driver && typeof driver.transaction === "function";
783
+ }
784
+ function hasPreparedStatementSupport(driver) {
785
+ return "prepare" in driver && typeof driver.prepare === "function";
786
+ }
787
+ var DatabaseError = class extends Error {
788
+ constructor(message, driverType, originalError) {
789
+ super(message);
790
+ this.driverType = driverType;
791
+ this.originalError = originalError;
792
+ this.name = "DatabaseError";
793
+ }
794
+ };
795
+ var QueryError = class extends DatabaseError {
796
+ constructor(driverType, sql, originalError) {
797
+ super(`Query failed: ${sql}`, driverType, originalError);
798
+ this.name = "QueryError";
799
+ }
800
+ };
801
+
802
+ //#endregion
803
+ //#region src/utils/inspect.ts
804
+ const withTimeout = (promise, timeoutMs = 3e4) => {
805
+ return Promise.race([promise, new Promise((_, reject) => setTimeout(() => reject(/* @__PURE__ */ new Error(`Query timeout after ${timeoutMs}ms`)), timeoutMs))]);
806
+ };
807
+ const retryQuery = async (queryFn, maxRetries = 3, baseDelay = 1e3) => {
808
+ for (let attempt = 1; attempt <= maxRetries; attempt++) try {
809
+ return await queryFn();
810
+ } catch (error) {
811
+ if (attempt === maxRetries) throw error;
812
+ const delay = baseDelay * Math.pow(2, attempt - 1);
813
+ consola.warn(`Query attempt ${attempt} failed, retrying in ${delay}ms...`, error);
814
+ await new Promise((resolve) => setTimeout(resolve, delay));
815
+ }
816
+ throw new Error("Max retries exceeded");
817
+ };
818
+ const mapDatabaseTypeToTypeScript = (dataType, isNullable = false, driverType = "postgres") => {
819
+ const nullable = isNullable ? " | null" : "";
820
+ switch (dataType.toLowerCase()) {
821
+ case "uuid": return `string${nullable}`;
822
+ case "character varying":
823
+ case "varchar":
824
+ case "text":
825
+ case "char":
826
+ case "character":
827
+ case "longtext":
828
+ case "mediumtext":
829
+ case "tinytext": return `string${nullable}`;
830
+ case "integer":
831
+ case "int":
832
+ case "int4":
833
+ case "smallint":
834
+ case "int2":
835
+ case "bigint":
836
+ case "int8":
837
+ case "serial":
838
+ case "bigserial":
839
+ case "numeric":
840
+ case "decimal":
841
+ case "real":
842
+ case "float4":
843
+ case "double precision":
844
+ case "float8":
845
+ case "tinyint":
846
+ case "mediumint":
847
+ case "float":
848
+ case "double": return `number${nullable}`;
849
+ case "boolean":
850
+ case "bool":
851
+ case "bit": return `boolean${nullable}`;
852
+ case "timestamp":
853
+ case "timestamp with time zone":
854
+ case "timestamp without time zone":
855
+ case "timestamptz":
856
+ case "date":
857
+ case "time":
858
+ case "time with time zone":
859
+ case "time without time zone":
860
+ case "timetz":
861
+ case "interval":
862
+ case "datetime":
863
+ case "year": return `Date${nullable}`;
864
+ case "json":
865
+ case "jsonb": return `any${nullable}`;
866
+ case "array": return `any[]${nullable}`;
867
+ case "bytea":
868
+ case "binary":
869
+ case "varbinary":
870
+ case "blob":
871
+ case "longblob":
872
+ case "mediumblob":
873
+ case "tinyblob": return `Buffer${nullable}`;
874
+ case "enum":
875
+ case "set": return `string${nullable}`;
876
+ default:
877
+ consola.warn(`Unknown ${driverType} type: ${dataType}, defaulting to 'any'`);
878
+ return `any${nullable}`;
879
+ }
880
+ };
881
+ const getDriverType = (driver) => {
882
+ return `${driver.constructor.name || "unknown driver"}`;
883
+ };
884
+ const inspectDB = async (options) => {
885
+ consola.warn("inspectDB is experimental and may make mistakes when inspecting your database. However it will not destroy your database.");
886
+ const { driver, outputFile = "db-types.ts" } = options;
887
+ const driverType = getDriverType(driver);
888
+ consola.start(`Inspecting database using ${driverType} driver`);
889
+ const client = new SQLClient({ driver });
890
+ let generatedTypes = "";
891
+ try {
892
+ let tablesQuery;
893
+ let tableSchemaFilter;
894
+ if (driverType === "mysql") {
895
+ const currentDatabase = (await withTimeout(retryQuery(() => client.query("SELECT DATABASE() as `database`", [])), 1e4)).rows[0]?.database;
896
+ if (!currentDatabase) throw new Error("Could not determine current MySQL database name");
897
+ consola.success(`Using MySQL database: ${currentDatabase}`);
898
+ tablesQuery = `SELECT TABLE_NAME as table_name
71
899
  FROM information_schema.tables
72
900
  WHERE TABLE_SCHEMA = ?
73
901
  AND TABLE_TYPE = 'BASE TABLE'
74
- ORDER BY TABLE_NAME`,t=n}else if(r===`postgres`||r===`neon`)e=`SELECT table_name
902
+ ORDER BY TABLE_NAME`;
903
+ tableSchemaFilter = currentDatabase;
904
+ } else if (driverType === "postgres" || driverType === "neon") {
905
+ tablesQuery = `SELECT table_name
75
906
  FROM information_schema.tables
76
907
  WHERE table_schema = $1
77
908
  AND table_type = 'BASE TABLE'
78
- ORDER BY table_name`,t=`public`;else if(r===`libsql`||r===`sqlite`||r===`sqlitecloud`)e=`SELECT name as table_name
909
+ ORDER BY table_name`;
910
+ tableSchemaFilter = "public";
911
+ } else if (driverType === "libsql" || driverType === "sqlite" || driverType === "sqlitecloud") {
912
+ tablesQuery = `SELECT name as table_name
79
913
  FROM sqlite_master
80
914
  WHERE type = 'table'
81
- ORDER BY name`,t=void 0;else throw Error(`Unsupported driver type: ${r}`);let o=await N(P(()=>i.query(e,t?[t]:[])),3e4);l.info(`Tables in the database:`,o.rows.map(e=>e.table_name).join(`, `));let s=0,c=o.rows.length;for(let e of o.rows){let n=e.table_name;if(!(n.startsWith(`sqlite_sequence`)||n.startsWith(`_prisma_migrations`))){s++,l.info(`[${s}/${c}] Inspecting table: ${n}`);try{let e,o;r===`mysql`?(e=`
915
+ ORDER BY name`;
916
+ tableSchemaFilter = void 0;
917
+ } else throw new Error(`Unsupported driver type: ${driverType}`);
918
+ const tables = await withTimeout(retryQuery(() => client.query(tablesQuery, tableSchemaFilter ? [tableSchemaFilter] : [])), 3e4);
919
+ consola.info("Tables in the database:", tables.rows.map((t) => t.table_name).join(", "));
920
+ let processedTables = 0;
921
+ const totalTables = tables.rows.length;
922
+ for (const table of tables.rows) {
923
+ const tableName = table.table_name;
924
+ if (tableName.startsWith("sqlite_sequence") || tableName.startsWith("_prisma_migrations")) continue;
925
+ processedTables++;
926
+ consola.info(`[${processedTables}/${totalTables}] Inspecting table: ${tableName}`);
927
+ try {
928
+ let columnsQuery;
929
+ let queryParams;
930
+ if (driverType === "mysql") {
931
+ columnsQuery = `
82
932
  SELECT
83
933
  COLUMN_NAME as column_name,
84
934
  DATA_TYPE as data_type,
@@ -88,7 +938,10 @@ export default [notesTable.getDefinition()]
88
938
  WHERE TABLE_NAME = ?
89
939
  AND TABLE_SCHEMA = ?
90
940
  ORDER BY ORDINAL_POSITION
91
- `,o=[n,t]):r===`postgres`||r===`neon`?(e=`
941
+ `;
942
+ queryParams = [tableName, tableSchemaFilter];
943
+ } else if (driverType === "postgres" || driverType === "neon") {
944
+ columnsQuery = `
92
945
  SELECT
93
946
  column_name,
94
947
  data_type,
@@ -98,7 +951,10 @@ export default [notesTable.getDefinition()]
98
951
  WHERE table_name = $1
99
952
  AND table_schema = $2
100
953
  ORDER BY ordinal_position
101
- `,o=[n,t]):(e=`
954
+ `;
955
+ queryParams = [tableName, tableSchemaFilter];
956
+ } else {
957
+ columnsQuery = `
102
958
  SELECT
103
959
  name as column_name,
104
960
  type as data_type,
@@ -106,9 +962,607 @@ export default [notesTable.getDefinition()]
106
962
  dflt_value as column_default
107
963
  FROM pragma_table_info(?)
108
964
  ORDER BY cid
109
- `,o=[n]);let s=await N(P(()=>i.query(e,o)),15e3);if(s.rows.length===0){l.info(`No columns found for table: ${n}`);continue}l.info(`Columns in '${n}'`),s.rows.forEach(e=>{let t=e.data_type+(e.is_nullable===`YES`?` (nullable)`:``);l.info(` > ${f.bold.yellow(t)} > ${e.column_name}`)});let c=new Map;s.rows.forEach(e=>{c.has(e.column_name)||c.set(e.column_name,e)}),a+=`export interface ${n.charAt(0).toUpperCase()+n.slice(1)} {\n`;for(let e of c.values()){let t=F(e.data_type,e.is_nullable===`YES`,r);a+=` ${e.column_name}: ${t};\n`}a+=`}
965
+ `;
966
+ queryParams = [tableName];
967
+ }
968
+ const columns = await withTimeout(retryQuery(() => client.query(columnsQuery, queryParams)), 15e3);
969
+ if (columns.rows.length === 0) {
970
+ consola.info(`No columns found for table: ${tableName}`);
971
+ continue;
972
+ }
973
+ consola.info(`Columns in '${tableName}'`);
974
+ columns.rows.forEach((c) => {
975
+ const typeDisplay = c.data_type + (c.is_nullable === "YES" ? " (nullable)" : "");
976
+ consola.info(` > ${chalk.bold.yellow(typeDisplay)} > ${c.column_name}`);
977
+ });
978
+ const uniqueColumns = /* @__PURE__ */ new Map();
979
+ columns.rows.forEach((col) => {
980
+ if (!uniqueColumns.has(col.column_name)) uniqueColumns.set(col.column_name, col);
981
+ });
982
+ generatedTypes += `export interface ${tableName.charAt(0).toUpperCase() + tableName.slice(1)} {\n`;
983
+ for (const col of uniqueColumns.values()) {
984
+ const tsType = mapDatabaseTypeToTypeScript(col.data_type, col.is_nullable === "YES", driverType);
985
+ generatedTypes += ` ${col.column_name}: ${tsType};\n`;
986
+ }
987
+ generatedTypes += "}\n\n";
988
+ } catch (error) {
989
+ consola.error(`Failed to process table ${tableName}:`, error);
990
+ consola.info(`Skipping table ${tableName} and continuing...`);
991
+ continue;
992
+ }
993
+ }
994
+ generatedTypes += "export interface Database {\n";
995
+ for (const table of tables.rows) {
996
+ if (table.table_name.startsWith("sqlite_sequence") || table.table_name.startsWith("_prisma_migrations")) continue;
997
+ const interfaceName = table.table_name.charAt(0).toUpperCase() + table.table_name.slice(1);
998
+ generatedTypes += ` ${table.table_name}: ${interfaceName};\n`;
999
+ }
1000
+ generatedTypes += "}\n\n";
1001
+ await fs.writeFile(outputFile, generatedTypes, "utf8");
1002
+ consola.success(`TypeScript types written to ${outputFile}`);
1003
+ consola.success(`Successfully processed ${processedTables} tables`);
1004
+ } catch (error) {
1005
+ consola.error("Fatal error during database inspection:", error);
1006
+ throw error;
1007
+ } finally {
1008
+ await client.close().catch((error) => consola.error("Error closing client:", error));
1009
+ }
1010
+ };
1011
+ var inspect_default = inspectDB;
1012
+
1013
+ //#endregion
1014
+ //#region src/drivers/helpers/postgres.ts
1015
+ function createPostgresHelpers(driver) {
1016
+ return {
1017
+ async findFirst(table, where) {
1018
+ const conditions = [];
1019
+ const params = [];
1020
+ let paramIndex = 1;
1021
+ if (where) for (const [key, value] of Object.entries(where)) {
1022
+ conditions.push(`"${key}" = $${paramIndex}`);
1023
+ params.push(value);
1024
+ paramIndex++;
1025
+ }
1026
+ const sql = `SELECT * FROM "${table}" ${conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : ""} LIMIT 1`;
1027
+ return await driver.query(sql, params);
1028
+ },
1029
+ async findMany(table, options) {
1030
+ const conditions = [];
1031
+ const params = [];
1032
+ let paramIndex = 1;
1033
+ if (options?.where) for (const [key, value] of Object.entries(options.where)) {
1034
+ conditions.push(`"${key}" = $${paramIndex}`);
1035
+ params.push(value);
1036
+ paramIndex++;
1037
+ }
1038
+ const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
1039
+ const limitClause = options?.limit ? `LIMIT $${paramIndex++}` : "";
1040
+ const offsetClause = options?.offset ? `OFFSET $${paramIndex++}` : "";
1041
+ if (options?.limit) params.push(options.limit);
1042
+ if (options?.offset) params.push(options.offset);
1043
+ const sql = `SELECT * FROM "${table}" ${whereClause} ${limitClause} ${offsetClause}`.trim();
1044
+ return await driver.query(sql, params);
1045
+ },
1046
+ async insert(table, data) {
1047
+ const keys = Object.keys(data);
1048
+ const values = Object.values(data);
1049
+ const sql = `INSERT INTO "${table}" (${keys.map((k) => `"${k}"`).join(", ")}) VALUES (${keys.map((_, i) => `$${i + 1}`).join(", ")}) RETURNING *`;
1050
+ return await driver.query(sql, values);
1051
+ },
1052
+ async update(table, data, where) {
1053
+ const setEntries = Object.entries(data);
1054
+ const whereEntries = Object.entries(where);
1055
+ const params = [];
1056
+ let paramIndex = 1;
1057
+ const setClauses = setEntries.map(([key, value]) => {
1058
+ params.push(value);
1059
+ return `"${key}" = $${paramIndex++}`;
1060
+ });
1061
+ const whereClauses = whereEntries.map(([key, value]) => {
1062
+ params.push(value);
1063
+ return `"${key}" = $${paramIndex++}`;
1064
+ });
1065
+ const sql = `UPDATE "${table}" SET ${setClauses.join(", ")} WHERE ${whereClauses.join(" AND ")} RETURNING *`;
1066
+ return await driver.query(sql, params);
1067
+ },
1068
+ async delete(table, where) {
1069
+ const conditions = [];
1070
+ const params = [];
1071
+ let paramIndex = 1;
1072
+ for (const [key, value] of Object.entries(where)) {
1073
+ conditions.push(`"${key}" = $${paramIndex}`);
1074
+ params.push(value);
1075
+ paramIndex++;
1076
+ }
1077
+ const sql = `DELETE FROM "${table}" WHERE ${conditions.join(" AND ")}`;
1078
+ return (await driver.query(sql, params)).rowCount;
1079
+ }
1080
+ };
1081
+ }
1082
+
1083
+ //#endregion
1084
+ //#region src/drivers/postgres.ts
1085
+ var PostgresDriver = class {
1086
+ client;
1087
+ findFirst;
1088
+ findMany;
1089
+ insert;
1090
+ update;
1091
+ delete;
1092
+ constructor(config) {
1093
+ this.client = postgres(config.connectionString, {
1094
+ max: config.max ?? 10,
1095
+ idle_timeout: config.idle_timeout ?? 30,
1096
+ connect_timeout: config.connect_timeout ?? 10,
1097
+ prepare: false,
1098
+ transform: { undefined: null }
1099
+ });
1100
+ const helpers = createPostgresHelpers(this);
1101
+ this.findFirst = helpers.findFirst;
1102
+ this.findMany = helpers.findMany;
1103
+ this.insert = helpers.insert;
1104
+ this.update = helpers.update;
1105
+ this.delete = helpers.delete;
1106
+ }
1107
+ async query(sql, params) {
1108
+ try {
1109
+ const result = await this.client.unsafe(sql, params || []);
1110
+ const rows = Array.isArray(result) ? [...result] : [];
1111
+ return {
1112
+ rows,
1113
+ rowCount: rows.length,
1114
+ command: result.command
1115
+ };
1116
+ } catch (error) {
1117
+ throw new QueryError("postgres", sql, error);
1118
+ }
1119
+ }
1120
+ async close() {
1121
+ await this.client.end();
1122
+ }
1123
+ };
1124
+
1125
+ //#endregion
1126
+ //#region src/drivers/helpers/mysql.ts
1127
+ function createMySQLHelpers(driver) {
1128
+ return {
1129
+ async findFirst(table, where) {
1130
+ const conditions = [];
1131
+ const params = [];
1132
+ if (where) for (const [key, value] of Object.entries(where)) {
1133
+ conditions.push(`\`${key}\` = ?`);
1134
+ params.push(value);
1135
+ }
1136
+ const sql = `SELECT * FROM \`${table}\` ${conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : ""} LIMIT 1`;
1137
+ return await driver.query(sql, params);
1138
+ },
1139
+ async findMany(table, options) {
1140
+ const conditions = [];
1141
+ const params = [];
1142
+ if (options?.where) for (const [key, value] of Object.entries(options.where)) {
1143
+ conditions.push(`\`${key}\` = ?`);
1144
+ params.push(value);
1145
+ }
1146
+ const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
1147
+ const limitClause = options?.limit ? `LIMIT ?` : "";
1148
+ const offsetClause = options?.offset ? `OFFSET ?` : "";
1149
+ if (options?.limit) params.push(options.limit);
1150
+ if (options?.offset) params.push(options.offset);
1151
+ const sql = `SELECT * FROM \`${table}\` ${whereClause} ${limitClause} ${offsetClause}`.trim();
1152
+ return await driver.query(sql, params);
1153
+ },
1154
+ async insert(table, data) {
1155
+ const keys = Object.keys(data);
1156
+ const values = Object.values(data);
1157
+ const sql = `INSERT INTO \`${table}\` (${keys.map((k) => `\`${k}\``).join(", ")}) VALUES (${keys.map(() => "?").join(", ")})`;
1158
+ await driver.query(sql, values);
1159
+ const selectSql = `SELECT * FROM \`${table}\` WHERE id = LAST_INSERT_ID()`;
1160
+ return await driver.query(selectSql);
1161
+ },
1162
+ async update(table, data, where) {
1163
+ const setEntries = Object.entries(data);
1164
+ const whereEntries = Object.entries(where);
1165
+ const params = [];
1166
+ const setClauses = setEntries.map(([key, value]) => {
1167
+ params.push(value);
1168
+ return `\`${key}\` = ?`;
1169
+ });
1170
+ const whereClauses = whereEntries.map(([key, value]) => {
1171
+ params.push(value);
1172
+ return `\`${key}\` = ?`;
1173
+ });
1174
+ const sql = `UPDATE \`${table}\` SET ${setClauses.join(", ")} WHERE ${whereClauses.join(" AND ")}`;
1175
+ await driver.query(sql, params);
1176
+ const selectParams = Object.values(where);
1177
+ const selectSql = `SELECT * FROM \`${table}\` WHERE ${Object.keys(where).map((k) => `\`${k}\` = ?`).join(" AND ")}`;
1178
+ return await driver.query(selectSql, selectParams);
1179
+ },
1180
+ async delete(table, where) {
1181
+ const conditions = [];
1182
+ const params = [];
1183
+ for (const [key, value] of Object.entries(where)) {
1184
+ conditions.push(`\`${key}\` = ?`);
1185
+ params.push(value);
1186
+ }
1187
+ const sql = `DELETE FROM \`${table}\` WHERE ${conditions.join(" AND ")}`;
1188
+ return (await driver.query(sql, params)).rowCount;
1189
+ }
1190
+ };
1191
+ }
1192
+
1193
+ //#endregion
1194
+ //#region src/drivers/helpers/sqlite.ts
1195
+ function createSQLiteHelpers(driver) {
1196
+ return {
1197
+ async findFirst(table, where) {
1198
+ const conditions = [];
1199
+ const params = [];
1200
+ if (where) for (const [key, value] of Object.entries(where)) {
1201
+ conditions.push(`"${key}" = ?`);
1202
+ params.push(value);
1203
+ }
1204
+ const sql = `SELECT * FROM "${table}" ${conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : ""} LIMIT 1`;
1205
+ return await driver.query(sql, params);
1206
+ },
1207
+ async findMany(table, options) {
1208
+ const conditions = [];
1209
+ const params = [];
1210
+ if (options?.where) for (const [key, value] of Object.entries(options.where)) {
1211
+ conditions.push(`"${key}" = ?`);
1212
+ params.push(value);
1213
+ }
1214
+ const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
1215
+ const limitClause = options?.limit ? `LIMIT ?` : "";
1216
+ const offsetClause = options?.offset ? `OFFSET ?` : "";
1217
+ if (options?.limit) params.push(options.limit);
1218
+ if (options?.offset) params.push(options.offset);
1219
+ const sql = `SELECT * FROM "${table}" ${whereClause} ${limitClause} ${offsetClause}`.trim();
1220
+ return await driver.query(sql, params);
1221
+ },
1222
+ async insert(table, data) {
1223
+ const keys = Object.keys(data);
1224
+ const values = Object.values(data);
1225
+ const sql = `INSERT INTO "${table}" (${keys.map((k) => `"${k}"`).join(", ")}) VALUES (${keys.map(() => "?").join(", ")}) RETURNING *`;
1226
+ return await driver.query(sql, values);
1227
+ },
1228
+ async update(table, data, where) {
1229
+ const setEntries = Object.entries(data);
1230
+ const whereEntries = Object.entries(where);
1231
+ const params = [];
1232
+ const setClauses = setEntries.map(([key, value]) => {
1233
+ params.push(value);
1234
+ return `"${key}" = ?`;
1235
+ });
1236
+ const whereClauses = whereEntries.map(([key, value]) => {
1237
+ params.push(value);
1238
+ return `"${key}" = ?`;
1239
+ });
1240
+ const sql = `UPDATE "${table}" SET ${setClauses.join(", ")} WHERE ${whereClauses.join(" AND ")} RETURNING *`;
1241
+ return await driver.query(sql, params);
1242
+ },
1243
+ async delete(table, where) {
1244
+ const conditions = [];
1245
+ const params = [];
1246
+ for (const [key, value] of Object.entries(where)) {
1247
+ conditions.push(`"${key}" = ?`);
1248
+ params.push(value);
1249
+ }
1250
+ const sql = `DELETE FROM "${table}" WHERE ${conditions.join(" AND ")}`;
1251
+ return (await driver.query(sql, params)).rowCount;
1252
+ }
1253
+ };
1254
+ }
1255
+
1256
+ //#endregion
1257
+ //#region src/schema/column.ts
1258
+ var Column = class {
1259
+ definition;
1260
+ constructor(name, type) {
1261
+ this.definition = {
1262
+ name,
1263
+ type
1264
+ };
1265
+ }
1266
+ length(len) {
1267
+ this.definition.length = len;
1268
+ return this;
1269
+ }
1270
+ precision(p, s) {
1271
+ this.definition.precision = p;
1272
+ if (s !== void 0) this.definition.scale = s;
1273
+ return this;
1274
+ }
1275
+ primaryKey() {
1276
+ this.definition.primaryKey = true;
1277
+ this.definition.notNull = true;
1278
+ return this;
1279
+ }
1280
+ notNull() {
1281
+ this.definition.notNull = true;
1282
+ return this;
1283
+ }
1284
+ unique() {
1285
+ this.definition.unique = true;
1286
+ return this;
1287
+ }
1288
+ default(value) {
1289
+ this.definition.default = value;
1290
+ return this;
1291
+ }
1292
+ references(table, column = "id") {
1293
+ this.definition.references = {
1294
+ table,
1295
+ column
1296
+ };
1297
+ return this;
1298
+ }
1299
+ onDelete(action) {
1300
+ if (this.definition.references) this.definition.references.onDelete = action;
1301
+ return this;
1302
+ }
1303
+ onUpdate(action) {
1304
+ if (this.definition.references) this.definition.references.onUpdate = action;
1305
+ return this;
1306
+ }
1307
+ check(expression) {
1308
+ this.definition.check = expression;
1309
+ return this;
1310
+ }
1311
+ getDefinition() {
1312
+ return this.definition;
1313
+ }
1314
+ };
1315
+ function serial(name) {
1316
+ return new Column(name, "serial");
1317
+ }
1318
+ function bigserial(name) {
1319
+ return new Column(name, "bigserial");
1320
+ }
1321
+ function integer(name) {
1322
+ return new Column(name, "integer");
1323
+ }
1324
+ function bigint(name) {
1325
+ return new Column(name, "bigint");
1326
+ }
1327
+ function smallint(name) {
1328
+ return new Column(name, "smallint");
1329
+ }
1330
+ function text(name) {
1331
+ return new Column(name, "text");
1332
+ }
1333
+ function varchar(name, length) {
1334
+ const col = new Column(name, "varchar");
1335
+ if (length) col.length(length);
1336
+ return col;
1337
+ }
1338
+ function char(name, length) {
1339
+ const col = new Column(name, "char");
1340
+ if (length) col.length(length);
1341
+ return col;
1342
+ }
1343
+ function boolean(name) {
1344
+ return new Column(name, "boolean");
1345
+ }
1346
+ function timestamp(name) {
1347
+ return new Column(name, "timestamp");
1348
+ }
1349
+ function timestamptz(name) {
1350
+ return new Column(name, "timestamptz");
1351
+ }
1352
+ function date(name) {
1353
+ return new Column(name, "date");
1354
+ }
1355
+ function time(name) {
1356
+ return new Column(name, "time");
1357
+ }
1358
+ function json(name) {
1359
+ return new Column(name, "json");
1360
+ }
1361
+ function jsonb(name) {
1362
+ return new Column(name, "jsonb");
1363
+ }
1364
+ function uuid(name) {
1365
+ return new Column(name, "uuid");
1366
+ }
1367
+ function decimal(name, precision, scale) {
1368
+ const col = new Column(name, "decimal");
1369
+ if (precision) col.precision(precision, scale);
1370
+ return col;
1371
+ }
1372
+ function numeric(name, precision, scale) {
1373
+ const col = new Column(name, "numeric");
1374
+ if (precision) col.precision(precision, scale);
1375
+ return col;
1376
+ }
1377
+ function real(name) {
1378
+ return new Column(name, "real");
1379
+ }
1380
+ function doublePrecision(name) {
1381
+ return new Column(name, "double precision");
1382
+ }
1383
+ function bytea(name) {
1384
+ return new Column(name, "bytea");
1385
+ }
1386
+
1387
+ //#endregion
1388
+ //#region src/schema/table.ts
1389
+ var Table = class {
1390
+ definition;
1391
+ constructor(name) {
1392
+ this.definition = {
1393
+ name,
1394
+ columns: [],
1395
+ indexes: [],
1396
+ checks: []
1397
+ };
1398
+ }
1399
+ column(column) {
1400
+ this.definition.columns.push(column.getDefinition());
1401
+ return this;
1402
+ }
1403
+ primaryKey(...columns) {
1404
+ this.definition.primaryKey = columns;
1405
+ return this;
1406
+ }
1407
+ index(name, columns, options) {
1408
+ const index = {
1409
+ name,
1410
+ columns,
1411
+ unique: options?.unique,
1412
+ type: options?.type
1413
+ };
1414
+ this.definition.indexes?.push(index);
1415
+ return this;
1416
+ }
1417
+ unique(name, ...columns) {
1418
+ return this.index(name, columns, { unique: true });
1419
+ }
1420
+ check(name, expression) {
1421
+ this.definition.checks?.push({
1422
+ name,
1423
+ expression
1424
+ });
1425
+ return this;
1426
+ }
1427
+ getDefinition() {
1428
+ return this.definition;
1429
+ }
1430
+ };
1431
+ function createTable(name, callback) {
1432
+ const table = new Table(name);
1433
+ callback(table);
1434
+ return table;
1435
+ }
1436
+
1437
+ //#endregion
1438
+ //#region src/schema/index.ts
1439
+ init_postgres();
1440
+ init_mysql();
1441
+ init_sqlite();
110
1442
 
111
- `}catch(e){l.error(`Failed to process table ${n}:`,e),l.info(`Skipping table ${n} and continuing...`);continue}}}a+=`export interface Database {
112
- `;for(let e of o.rows){if(e.table_name.startsWith(`sqlite_sequence`)||e.table_name.startsWith(`_prisma_migrations`))continue;let t=e.table_name.charAt(0).toUpperCase()+e.table_name.slice(1);a+=` ${e.table_name}: ${t};\n`}a+=`}
1443
+ //#endregion
1444
+ //#region src/index.ts
1445
+ var SQLClient = class SQLClient {
1446
+ primaryDriver;
1447
+ fallbackDrivers;
1448
+ queryCache;
1449
+ cacheTTL;
1450
+ maxCacheSize = 100;
1451
+ constructor(options) {
1452
+ this.primaryDriver = options.driver;
1453
+ this.fallbackDrivers = options.fallbackDrivers || [];
1454
+ this.queryCache = /* @__PURE__ */ new Map();
1455
+ this.cacheTTL = options.cacheTTL ?? 5e3;
1456
+ }
1457
+ isCacheValid(entry) {
1458
+ return Date.now() - entry.timestamp < this.cacheTTL;
1459
+ }
1460
+ getCacheKey(sql, params) {
1461
+ return JSON.stringify({
1462
+ sql,
1463
+ params
1464
+ });
1465
+ }
1466
+ maintainCacheSize() {
1467
+ if (this.queryCache.size > this.maxCacheSize) {
1468
+ const firstKey = this.queryCache.keys().next().value;
1469
+ if (firstKey !== void 0) this.queryCache.delete(firstKey);
1470
+ }
1471
+ }
1472
+ cacheResult(cacheKey, result) {
1473
+ this.queryCache.set(cacheKey, {
1474
+ result,
1475
+ timestamp: Date.now()
1476
+ });
1477
+ this.maintainCacheSize();
1478
+ }
1479
+ async tryFallbackDrivers(sql, params) {
1480
+ consola.warn(`Query failed with ${this.primaryDriver.constructor.name}, trying fallbacks`);
1481
+ let lastError;
1482
+ for (const driver of this.fallbackDrivers) try {
1483
+ return await driver.query(sql, params);
1484
+ } catch (error) {
1485
+ lastError = error;
1486
+ }
1487
+ throw lastError || new DatabaseError("All drivers failed to execute query", "unknown");
1488
+ }
1489
+ async query(sql, params) {
1490
+ const cacheKey = this.getCacheKey(sql, params);
1491
+ const cached = this.queryCache.get(cacheKey);
1492
+ if (cached && this.isCacheValid(cached)) return cached.result;
1493
+ try {
1494
+ const result = await this.primaryDriver.query(sql, params);
1495
+ this.cacheResult(cacheKey, result);
1496
+ return result;
1497
+ } catch (primaryError) {
1498
+ if (this.fallbackDrivers.length === 0) throw primaryError;
1499
+ return await this.tryFallbackDrivers(sql, params);
1500
+ }
1501
+ }
1502
+ async transaction(callback) {
1503
+ if (!hasTransactionSupport(this.primaryDriver)) throw new DatabaseError("Primary driver does not support transactions", this.primaryDriver.constructor.name);
1504
+ return await this.primaryDriver.transaction(async (transactionDriver) => {
1505
+ return await callback(new SQLClient({
1506
+ driver: transactionDriver,
1507
+ fallbackDrivers: []
1508
+ }));
1509
+ });
1510
+ }
1511
+ async prepare(sql) {
1512
+ if (!hasPreparedStatementSupport(this.primaryDriver)) throw new DatabaseError("Primary driver does not support prepared statements", this.primaryDriver.constructor.name);
1513
+ return await this.primaryDriver.prepare(sql);
1514
+ }
1515
+ async findFirst(table, where) {
1516
+ if (!this.primaryDriver.findFirst) throw new DatabaseError("Primary driver does not support findFirst", this.primaryDriver.constructor.name);
1517
+ return (await this.primaryDriver.findFirst(table, where))?.rows[0] || null;
1518
+ }
1519
+ async findMany(table, options) {
1520
+ if (!this.primaryDriver.findMany) throw new DatabaseError("Primary driver does not support findMany", this.primaryDriver.constructor.name);
1521
+ return (await this.primaryDriver.findMany(table, options)).rows;
1522
+ }
1523
+ async insert(table, data) {
1524
+ if (!this.primaryDriver.insert) throw new DatabaseError("Primary driver does not support insert", this.primaryDriver.constructor.name);
1525
+ return (await this.primaryDriver.insert(table, data)).rows[0];
1526
+ }
1527
+ async update(table, data, where) {
1528
+ if (!this.primaryDriver.update) throw new DatabaseError("Primary driver does not support update", this.primaryDriver.constructor.name);
1529
+ return (await this.primaryDriver.update(table, data, where)).rows[0] || null;
1530
+ }
1531
+ async delete(table, where) {
1532
+ if (!this.primaryDriver.delete) throw new DatabaseError("Primary driver does not support delete", this.primaryDriver.constructor.name);
1533
+ return await this.primaryDriver.delete(table, where);
1534
+ }
1535
+ getDriver() {
1536
+ return this.primaryDriver;
1537
+ }
1538
+ async inspectDB(options) {
1539
+ return await inspect_default({
1540
+ driver: this.getDriver(),
1541
+ ...options
1542
+ });
1543
+ }
1544
+ supportsTransactions() {
1545
+ return hasTransactionSupport(this.primaryDriver);
1546
+ }
1547
+ supportsPreparedStatements() {
1548
+ return hasPreparedStatementSupport(this.primaryDriver);
1549
+ }
1550
+ clearCache() {
1551
+ this.queryCache.clear();
1552
+ }
1553
+ getCacheStats() {
1554
+ return {
1555
+ size: this.queryCache.size,
1556
+ ttl: this.cacheTTL
1557
+ };
1558
+ }
1559
+ async close() {
1560
+ this.queryCache.clear();
1561
+ const closePromises = [this.primaryDriver, ...this.fallbackDrivers].map((driver) => driver.close().catch((err) => consola.warn(`Error closing ${driver.constructor.name}:`, err)));
1562
+ await Promise.all(closePromises);
1563
+ }
1564
+ };
1565
+ const DriftSQLClient = SQLClient;
113
1566
 
114
- `,await u.writeFile(n,a,`utf8`),l.success(`TypeScript types written to ${n}`),l.success(`Successfully processed ${s} tables`)}catch(e){throw l.error(`Fatal error during database inspection:`,e),e}finally{await i.close().catch(e=>l.error(`Error closing client:`,e))}};function I(e){return{async findFirst(t,n){let r=[],i=[],a=1;if(n)for(let[e,t]of Object.entries(n))r.push(`"${e}" = $${a}`),i.push(t),a++;let o=`SELECT * FROM "${t}" ${r.length>0?`WHERE ${r.join(` AND `)}`:``} LIMIT 1`;return await e.query(o,i)},async findMany(t,n){let r=[],i=[],a=1;if(n?.where)for(let[e,t]of Object.entries(n.where))r.push(`"${e}" = $${a}`),i.push(t),a++;let o=r.length>0?`WHERE ${r.join(` AND `)}`:``,s=n?.limit?`LIMIT $${a++}`:``,c=n?.offset?`OFFSET $${a++}`:``;n?.limit&&i.push(n.limit),n?.offset&&i.push(n.offset);let l=`SELECT * FROM "${t}" ${o} ${s} ${c}`.trim();return await e.query(l,i)},async insert(t,n){let r=Object.keys(n),i=Object.values(n),a=`INSERT INTO "${t}" (${r.map(e=>`"${e}"`).join(`, `)}) VALUES (${r.map((e,t)=>`$${t+1}`).join(`, `)}) RETURNING *`;return await e.query(a,i)},async update(t,n,r){let i=Object.entries(n),a=Object.entries(r),o=[],s=1,c=i.map(([e,t])=>(o.push(t),`"${e}" = $${s++}`)),l=a.map(([e,t])=>(o.push(t),`"${e}" = $${s++}`)),u=`UPDATE "${t}" SET ${c.join(`, `)} WHERE ${l.join(` AND `)} RETURNING *`;return await e.query(u,o)},async delete(t,n){let r=[],i=[],a=1;for(let[e,t]of Object.entries(n))r.push(`"${e}" = $${a}`),i.push(t),a++;let o=`DELETE FROM "${t}" WHERE ${r.join(` AND `)}`;return(await e.query(o,i)).rowCount}}}var L=class{client;findFirst;findMany;insert;update;delete;constructor(e){this.client=p(e.connectionString,{max:e.max??10,idle_timeout:e.idle_timeout??30,connect_timeout:e.connect_timeout??10,prepare:!1,transform:{undefined:null}});let t=I(this);this.findFirst=t.findFirst,this.findMany=t.findMany,this.insert=t.insert,this.update=t.update,this.delete=t.delete}async query(e,t){try{let n=await this.client.unsafe(e,t||[]),r=Array.isArray(n)?[...n]:[];return{rows:r,rowCount:r.length,command:n.command}}catch(t){throw new M(`postgres`,e,t)}}async close(){await this.client.end()}};function R(e){return{async findFirst(t,n){let r=[],i=[];if(n)for(let[e,t]of Object.entries(n))r.push(`\`${e}\` = ?`),i.push(t);let a=`SELECT * FROM \`${t}\` ${r.length>0?`WHERE ${r.join(` AND `)}`:``} LIMIT 1`;return await e.query(a,i)},async findMany(t,n){let r=[],i=[];if(n?.where)for(let[e,t]of Object.entries(n.where))r.push(`\`${e}\` = ?`),i.push(t);let a=r.length>0?`WHERE ${r.join(` AND `)}`:``,o=n?.limit?`LIMIT ?`:``,s=n?.offset?`OFFSET ?`:``;n?.limit&&i.push(n.limit),n?.offset&&i.push(n.offset);let c=`SELECT * FROM \`${t}\` ${a} ${o} ${s}`.trim();return await e.query(c,i)},async insert(t,n){let r=Object.keys(n),i=Object.values(n),a=`INSERT INTO \`${t}\` (${r.map(e=>`\`${e}\``).join(`, `)}) VALUES (${r.map(()=>`?`).join(`, `)})`;await e.query(a,i);let o=`SELECT * FROM \`${t}\` WHERE id = LAST_INSERT_ID()`;return await e.query(o)},async update(t,n,r){let i=Object.entries(n),a=Object.entries(r),o=[],s=i.map(([e,t])=>(o.push(t),`\`${e}\` = ?`)),c=a.map(([e,t])=>(o.push(t),`\`${e}\` = ?`)),l=`UPDATE \`${t}\` SET ${s.join(`, `)} WHERE ${c.join(` AND `)}`;await e.query(l,o);let u=Object.values(r),d=`SELECT * FROM \`${t}\` WHERE ${Object.keys(r).map(e=>`\`${e}\` = ?`).join(` AND `)}`;return await e.query(d,u)},async delete(t,n){let r=[],i=[];for(let[e,t]of Object.entries(n))r.push(`\`${e}\` = ?`),i.push(t);let a=`DELETE FROM \`${t}\` WHERE ${r.join(` AND `)}`;return(await e.query(a,i)).rowCount}}}function z(e){return{async findFirst(t,n){let r=[],i=[];if(n)for(let[e,t]of Object.entries(n))r.push(`"${e}" = ?`),i.push(t);let a=`SELECT * FROM "${t}" ${r.length>0?`WHERE ${r.join(` AND `)}`:``} LIMIT 1`;return await e.query(a,i)},async findMany(t,n){let r=[],i=[];if(n?.where)for(let[e,t]of Object.entries(n.where))r.push(`"${e}" = ?`),i.push(t);let a=r.length>0?`WHERE ${r.join(` AND `)}`:``,o=n?.limit?`LIMIT ?`:``,s=n?.offset?`OFFSET ?`:``;n?.limit&&i.push(n.limit),n?.offset&&i.push(n.offset);let c=`SELECT * FROM "${t}" ${a} ${o} ${s}`.trim();return await e.query(c,i)},async insert(t,n){let r=Object.keys(n),i=Object.values(n),a=`INSERT INTO "${t}" (${r.map(e=>`"${e}"`).join(`, `)}) VALUES (${r.map(()=>`?`).join(`, `)}) RETURNING *`;return await e.query(a,i)},async update(t,n,r){let i=Object.entries(n),a=Object.entries(r),o=[],s=i.map(([e,t])=>(o.push(t),`"${e}" = ?`)),c=a.map(([e,t])=>(o.push(t),`"${e}" = ?`)),l=`UPDATE "${t}" SET ${s.join(`, `)} WHERE ${c.join(` AND `)} RETURNING *`;return await e.query(l,o)},async delete(t,n){let r=[],i=[];for(let[e,t]of Object.entries(n))r.push(`"${e}" = ?`),i.push(t);let a=`DELETE FROM "${t}" WHERE ${r.join(` AND `)}`;return(await e.query(a,i)).rowCount}}}var B=class{definition;constructor(e,t){this.definition={name:e,type:t}}length(e){return this.definition.length=e,this}precision(e,t){return this.definition.precision=e,t!==void 0&&(this.definition.scale=t),this}primaryKey(){return this.definition.primaryKey=!0,this.definition.notNull=!0,this}notNull(){return this.definition.notNull=!0,this}unique(){return this.definition.unique=!0,this}default(e){return this.definition.default=e,this}references(e,t=`id`){return this.definition.references={table:e,column:t},this}onDelete(e){return this.definition.references&&(this.definition.references.onDelete=e),this}onUpdate(e){return this.definition.references&&(this.definition.references.onUpdate=e),this}check(e){return this.definition.check=e,this}getDefinition(){return this.definition}};function V(e){return new B(e,`serial`)}function H(e){return new B(e,`bigserial`)}function U(e){return new B(e,`integer`)}function W(e){return new B(e,`bigint`)}function G(e){return new B(e,`smallint`)}function K(e){return new B(e,`text`)}function q(e,t){let n=new B(e,`varchar`);return t&&n.length(t),n}function J(e,t){let n=new B(e,`char`);return t&&n.length(t),n}function Y(e){return new B(e,`boolean`)}function X(e){return new B(e,`timestamp`)}function re(e){return new B(e,`timestamptz`)}function ie(e){return new B(e,`date`)}function ae(e){return new B(e,`time`)}function oe(e){return new B(e,`json`)}function Z(e){return new B(e,`jsonb`)}function se(e){return new B(e,`uuid`)}function ce(e,t,n){let r=new B(e,`decimal`);return t&&r.precision(t,n),r}function le(e,t,n){let r=new B(e,`numeric`);return t&&r.precision(t,n),r}function ue(e){return new B(e,`real`)}function de(e){return new B(e,`double precision`)}function fe(e){return new B(e,`bytea`)}var Q=class{definition;constructor(e){this.definition={name:e,columns:[],indexes:[],checks:[]}}column(e){return this.definition.columns.push(e.getDefinition()),this}primaryKey(...e){return this.definition.primaryKey=e,this}index(e,t,n){let r={name:e,columns:t,unique:n?.unique,type:n?.type};return this.definition.indexes?.push(r),this}unique(e,...t){return this.index(e,t,{unique:!0})}check(e,t){return this.definition.checks?.push({name:e,expression:t}),this}getDefinition(){return this.definition}};function pe(e,t){let n=new Q(e);return t(n),n}n(),v(),x();var $=class e{primaryDriver;fallbackDrivers;queryCache;cacheTTL;maxCacheSize=100;constructor(e){this.primaryDriver=e.driver,this.fallbackDrivers=e.fallbackDrivers||[],this.queryCache=new Map,this.cacheTTL=e.cacheTTL??5e3}isCacheValid(e){return Date.now()-e.timestamp<this.cacheTTL}getCacheKey(e,t){return JSON.stringify({sql:e,params:t})}maintainCacheSize(){if(this.queryCache.size>this.maxCacheSize){let e=this.queryCache.keys().next().value;e!==void 0&&this.queryCache.delete(e)}}cacheResult(e,t){this.queryCache.set(e,{result:t,timestamp:Date.now()}),this.maintainCacheSize()}async tryFallbackDrivers(e,t){l.warn(`Query failed with ${this.primaryDriver.constructor.name}, trying fallbacks`);let n;for(let r of this.fallbackDrivers)try{return await r.query(e,t)}catch(e){n=e}throw n||new j(`All drivers failed to execute query`,`unknown`)}async query(e,t){let n=this.getCacheKey(e,t),r=this.queryCache.get(n);if(r&&this.isCacheValid(r))return r.result;try{let r=await this.primaryDriver.query(e,t);return this.cacheResult(n,r),r}catch(n){if(this.fallbackDrivers.length===0)throw n;return await this.tryFallbackDrivers(e,t)}}async transaction(t){if(!k(this.primaryDriver))throw new j(`Primary driver does not support transactions`,this.primaryDriver.constructor.name);return await this.primaryDriver.transaction(async n=>await t(new e({driver:n,fallbackDrivers:[]})))}async prepare(e){if(!A(this.primaryDriver))throw new j(`Primary driver does not support prepared statements`,this.primaryDriver.constructor.name);return await this.primaryDriver.prepare(e)}async findFirst(e,t){if(!this.primaryDriver.findFirst)throw new j(`Primary driver does not support findFirst`,this.primaryDriver.constructor.name);return(await this.primaryDriver.findFirst(e,t))?.rows[0]||null}async findMany(e,t){if(!this.primaryDriver.findMany)throw new j(`Primary driver does not support findMany`,this.primaryDriver.constructor.name);return(await this.primaryDriver.findMany(e,t)).rows}async insert(e,t){if(!this.primaryDriver.insert)throw new j(`Primary driver does not support insert`,this.primaryDriver.constructor.name);return(await this.primaryDriver.insert(e,t)).rows[0]}async update(e,t,n){if(!this.primaryDriver.update)throw new j(`Primary driver does not support update`,this.primaryDriver.constructor.name);return(await this.primaryDriver.update(e,t,n)).rows[0]||null}async delete(e,t){if(!this.primaryDriver.delete)throw new j(`Primary driver does not support delete`,this.primaryDriver.constructor.name);return await this.primaryDriver.delete(e,t)}getDriver(){return this.primaryDriver}async inspectDB(e){return await ne({driver:this.getDriver(),...e})}supportsTransactions(){return k(this.primaryDriver)}supportsPreparedStatements(){return A(this.primaryDriver)}clearCache(){this.queryCache.clear()}getCacheStats(){return{size:this.queryCache.size,ttl:this.cacheTTL}}async close(){this.queryCache.clear();let e=[this.primaryDriver,...this.fallbackDrivers].map(e=>e.close().catch(t=>l.warn(`Error closing ${e.constructor.name}:`,t)));await Promise.all(e)}};const me=$;export{B as Column,me as DriftSQLClient,S as MigrationBuilder,m as MigrationRunner,_ as MySQLGenerator,L as PostgresDriver,a as PostgresGenerator,$ as SQLClient,b as SQLiteGenerator,C as SchemaDiffer,h as SnapshotManager,Q as Table,s as TypeGenerator,W as bigint,H as bigserial,Y as boolean,fe as bytea,J as char,ee as createMigration,R as createMySQLHelpers,I as createPostgresHelpers,z as createSQLiteHelpers,pe as createTable,ie as date,ce as decimal,w as detectChanges,de as doublePrecision,T as generateMigrationFromChanges,o as generateTypesFromSchema,U as integer,oe as json,Z as jsonb,le as numeric,ue as real,V as serial,G as smallint,K as text,ae as time,X as timestamp,re as timestamptz,se as uuid,q as varchar};
1567
+ //#endregion
1568
+ export { Column, DriftSQLClient, MigrationBuilder, MigrationRunner, MySQLGenerator, PostgresDriver, PostgresGenerator, SQLClient, SQLiteGenerator, SchemaDiffer, SnapshotManager, Table, TypeGenerator, bigint, bigserial, boolean, bytea, char, createMigration, createMySQLHelpers, createPostgresHelpers, createSQLiteHelpers, createTable, date, decimal, detectChanges, doublePrecision, generateMigrationFromChanges, generateTypesFromSchema, integer, json, jsonb, numeric, real, serial, smallint, text, time, timestamp, timestamptz, uuid, varchar };