@bungres/kit 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/dist/cli.js +393 -194
- package/dist/commands/drop.d.ts.map +1 -1
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/push.d.ts.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/studio.d.ts.map +1 -1
- package/dist/config.d.ts +37 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/ensure-db.d.ts.map +1 -1
- package/dist/index.js +109 -57
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drop.d.ts","sourceRoot":"","sources":["../../src/commands/drop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AASnD,wBAAsB,OAAO,CAC3B,MAAM,EAAE,cAAc,EACtB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAC7B,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"drop.d.ts","sourceRoot":"","sources":["../../src/commands/drop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AASnD,wBAAsB,OAAO,CAC3B,MAAM,EAAE,cAAc,EACtB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAC7B,OAAO,CAAC,IAAI,CAAC,CA8Ff"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/commands/generate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAgBnD,wBAAsB,WAAW,CAC/B,MAAM,EAAE,cAAc,EACtB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/commands/generate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAgBnD,wBAAsB,WAAW,CAC/B,MAAM,EAAE,cAAc,EACtB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CA+Ff"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAOnD,wBAAsB,UAAU,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAoFtE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../src/commands/push.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAUnD,wBAAsB,OAAO,CAC3B,MAAM,EAAE,cAAc,EACtB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAC7B,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../src/commands/push.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAUnD,wBAAsB,OAAO,CAC3B,MAAM,EAAE,cAAc,EACtB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAC7B,OAAO,CAAC,IAAI,CAAC,CAqFf"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAOnD,wBAAsB,SAAS,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAyDrE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"studio.d.ts","sourceRoot":"","sources":["../../src/commands/studio.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAQnD,wBAAsB,SAAS,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"studio.d.ts","sourceRoot":"","sources":["../../src/commands/studio.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAQnD,wBAAsB,SAAS,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAyIrE"}
|
package/dist/config.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export interface BungresKitConfig {
|
|
|
11
11
|
seed?: string;
|
|
12
12
|
/**
|
|
13
13
|
* Output directory for generated migration .sql files.
|
|
14
|
-
*
|
|
14
|
+
* Default: "./migrations"
|
|
15
15
|
*/
|
|
16
16
|
out?: string;
|
|
17
17
|
/**
|
|
@@ -26,6 +26,38 @@ export interface BungresKitConfig {
|
|
|
26
26
|
* Default: "public"
|
|
27
27
|
*/
|
|
28
28
|
dbSchema?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Migrations tracking options.
|
|
31
|
+
*/
|
|
32
|
+
migrations?: {
|
|
33
|
+
/**
|
|
34
|
+
* Name of the table used to track applied migrations.
|
|
35
|
+
* Default: "__bungres_migrations"
|
|
36
|
+
*/
|
|
37
|
+
table?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Postgres schema where the migrations tracking table lives.
|
|
40
|
+
* Default: "bungres"
|
|
41
|
+
*/
|
|
42
|
+
schema?: string;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* When true, split generated SQL at `-->statement-breakpoint` comments
|
|
46
|
+
* and execute each statement individually inside a transaction.
|
|
47
|
+
* Default: true
|
|
48
|
+
*/
|
|
49
|
+
breakpoints?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* When true, commands like `push` and `drop` will prompt for confirmation
|
|
52
|
+
* before making destructive changes.
|
|
53
|
+
* Default: false
|
|
54
|
+
*/
|
|
55
|
+
strict?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Output directory for `bungres pull` generated TypeScript.
|
|
58
|
+
* Default: "./src/db/generated"
|
|
59
|
+
*/
|
|
60
|
+
outDir?: string;
|
|
29
61
|
/** Print every SQL statement executed. Default: false */
|
|
30
62
|
verbose?: boolean;
|
|
31
63
|
}
|
|
@@ -35,8 +67,10 @@ export interface ResolvedConfig {
|
|
|
35
67
|
out: string;
|
|
36
68
|
dbUrl: string;
|
|
37
69
|
dbSchema: string;
|
|
38
|
-
|
|
39
|
-
|
|
70
|
+
migrationsTable: string;
|
|
71
|
+
migrationsSchema: string;
|
|
72
|
+
breakpoints: boolean;
|
|
73
|
+
strict: boolean;
|
|
40
74
|
outDir: string;
|
|
41
75
|
verbose: boolean;
|
|
42
76
|
}
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAE1B;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,aAAa,CAAC,EAAE;QACd,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IAEF;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,yDAAyD;IACzD,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAE1B;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,aAAa,CAAC,EAAE;QACd,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IAEF;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,UAAU,CAAC,EAAE;QACX;;;WAGG;QACH,KAAK,CAAC,EAAE,MAAM,CAAC;QACf;;;WAGG;QACH,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IAEF;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,yDAAyD;IACzD,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AASD,wBAAsB,UAAU,CAAC,GAAG,SAAgB,GAAG,OAAO,CAAC,cAAc,CAAC,CA0C7E"}
|
package/dist/ensure-db.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ensure-db.d.ts","sourceRoot":"","sources":["../src/ensure-db.ts"],"names":[],"mappings":"AAAA,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"ensure-db.d.ts","sourceRoot":"","sources":["../src/ensure-db.ts"],"names":[],"mappings":"AAAA,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCjE"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// src/config.ts
|
|
3
|
-
import {
|
|
3
|
+
import { join, resolve } from "path";
|
|
4
4
|
var CONFIG_FILES = [
|
|
5
5
|
"bungres.config.ts",
|
|
6
6
|
"bungres.config.js",
|
|
@@ -17,7 +17,7 @@ async function loadConfig(cwd = process.cwd()) {
|
|
|
17
17
|
break;
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
|
-
const dbUrl = userConfig.dbCredentials?.url ??
|
|
20
|
+
const dbUrl = userConfig.dbCredentials?.url ?? Bun.env.DATABASE_URL ?? Bun.env.POSTGRES_URL ?? "";
|
|
21
21
|
if (!dbUrl) {
|
|
22
22
|
console.error(`bungres: No database URL found.
|
|
23
23
|
Add dbCredentials.url to bungres.config.ts or set DATABASE_URL.`);
|
|
@@ -30,8 +30,11 @@ async function loadConfig(cwd = process.cwd()) {
|
|
|
30
30
|
out,
|
|
31
31
|
dbUrl,
|
|
32
32
|
dbSchema: userConfig.dbSchema ?? "public",
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
migrationsTable: userConfig.migrations?.table ?? "__bungres_migrations",
|
|
34
|
+
migrationsSchema: userConfig.migrations?.schema ?? "bungres",
|
|
35
|
+
breakpoints: userConfig.breakpoints ?? true,
|
|
36
|
+
strict: userConfig.strict ?? false,
|
|
37
|
+
outDir: userConfig.outDir ?? "./src/db/generated",
|
|
35
38
|
verbose: userConfig.verbose ?? false
|
|
36
39
|
};
|
|
37
40
|
}
|
|
@@ -104,9 +107,10 @@ function createTableFactory(casing) {
|
|
|
104
107
|
return Object.assign(tableObj, columnConfigs);
|
|
105
108
|
};
|
|
106
109
|
}
|
|
107
|
-
var table = createTableFactory("
|
|
110
|
+
var table = createTableFactory("snake");
|
|
108
111
|
var snakeCase = { table: createTableFactory("snake") };
|
|
109
112
|
var camelCase = { table: createTableFactory("camel") };
|
|
113
|
+
var noCasing = { table: createTableFactory("none") };
|
|
110
114
|
// ../bungres-orm/src/schema/columns.ts
|
|
111
115
|
function buildColumn(dataType, nameOrOpts, opts) {
|
|
112
116
|
let name = "";
|
|
@@ -201,14 +205,14 @@ function sqlJoin(chunks, separator = ", ") {
|
|
|
201
205
|
function rawSql(query) {
|
|
202
206
|
return { sql: query, params: [] };
|
|
203
207
|
}
|
|
204
|
-
|
|
205
|
-
var colName = (c) => {
|
|
208
|
+
function colName(c) {
|
|
206
209
|
if (typeof c === "string")
|
|
207
210
|
return `"${c}"`;
|
|
208
211
|
if (isSQLChunk(c))
|
|
209
212
|
return c.sql;
|
|
210
213
|
return c.tableName ? `${c.tableName}."${c.name}"` : `"${c.name}"`;
|
|
211
|
-
}
|
|
214
|
+
}
|
|
215
|
+
// ../bungres-orm/src/core/conditions.ts
|
|
212
216
|
function isColumnConfig(val) {
|
|
213
217
|
return val !== null && typeof val === "object" && "name" in val && "dataType" in val;
|
|
214
218
|
}
|
|
@@ -265,6 +269,14 @@ var inArray = (column, values) => {
|
|
|
265
269
|
const placeholders = params.map((_, i) => `$${i + 1}`).join(", ");
|
|
266
270
|
return { sql: `${colName(column)} = ANY(ARRAY[${placeholders}])`, params };
|
|
267
271
|
};
|
|
272
|
+
var notInArray = (column, values) => {
|
|
273
|
+
if (values.length === 0)
|
|
274
|
+
return rawSql("TRUE");
|
|
275
|
+
const params = values;
|
|
276
|
+
const placeholders = params.map((_, i) => `$${i + 1}`).join(", ");
|
|
277
|
+
return { sql: `${colName(column)} != ALL(ARRAY[${placeholders}])`, params };
|
|
278
|
+
};
|
|
279
|
+
var between = (column, min, max) => sql`${rawSql(colName(column))} BETWEEN ${min} AND ${max}`;
|
|
268
280
|
var and = (...conditions) => sqlJoin(conditions, " AND ");
|
|
269
281
|
var or = (...conditions) => {
|
|
270
282
|
const joined = sqlJoin(conditions, " OR ");
|
|
@@ -315,6 +327,10 @@ function parseWhereObject(tableConfig, whereObj) {
|
|
|
315
327
|
conditions.push(lte(columnArg, opVal.lte));
|
|
316
328
|
if (opVal.in !== undefined)
|
|
317
329
|
conditions.push(inArray(columnArg, opVal.in));
|
|
330
|
+
if (opVal.notIn !== undefined)
|
|
331
|
+
conditions.push(notInArray(columnArg, opVal.notIn));
|
|
332
|
+
if (opVal.between !== undefined)
|
|
333
|
+
conditions.push(between(columnArg, opVal.between[0], opVal.between[1]));
|
|
318
334
|
if (opVal.like !== undefined)
|
|
319
335
|
conditions.push(like(columnArg, opVal.like));
|
|
320
336
|
if (opVal.ilike !== undefined)
|
|
@@ -395,6 +411,9 @@ class DeleteBuilder {
|
|
|
395
411
|
if (this._returning) {
|
|
396
412
|
query += " RETURNING " + (this._returning[0] === "*" ? Object.keys(getTableConfig(this._table).columns).map((c) => `"${getTableConfig(this._table).columns[c].name}" AS "${c}"`).join(", ") : this._returning.map((c) => `"${getTableConfig(this._table).columns[c]?.name ?? c}" AS "${c}"`).join(", "));
|
|
397
413
|
}
|
|
414
|
+
if (this._comment) {
|
|
415
|
+
query += ` /* ${this._comment.replace(/\*\//g, "")} */`;
|
|
416
|
+
}
|
|
398
417
|
return { sql: query, params };
|
|
399
418
|
}
|
|
400
419
|
}
|
|
@@ -505,7 +524,7 @@ class InsertBuilder {
|
|
|
505
524
|
query += " RETURNING " + (this._returning[0] === "*" ? Object.keys(tConfig.columns).map((c) => `"${tConfig.columns[c].name}" AS "${c}"`).join(", ") : this._returning.map((c) => `"${tConfig.columns[c]?.name ?? c}" AS "${c}"`).join(", "));
|
|
506
525
|
}
|
|
507
526
|
if (this._comment) {
|
|
508
|
-
query += ` /* ${this._comment} */`;
|
|
527
|
+
query += ` /* ${this._comment.replace(/\*\//g, "")} */`;
|
|
509
528
|
}
|
|
510
529
|
return { sql: query, params };
|
|
511
530
|
}
|
|
@@ -702,7 +721,7 @@ class SelectBuilder {
|
|
|
702
721
|
query += ` OFFSET $${params.length}`;
|
|
703
722
|
}
|
|
704
723
|
if (this._comment) {
|
|
705
|
-
query += ` /* ${this._comment} */`;
|
|
724
|
+
query += ` /* ${this._comment.replace(/\*\//g, "")} */`;
|
|
706
725
|
}
|
|
707
726
|
return { sql: query, params };
|
|
708
727
|
}
|
|
@@ -802,10 +821,22 @@ class UpdateBuilder {
|
|
|
802
821
|
if (this._returning) {
|
|
803
822
|
query += " RETURNING " + (this._returning[0] === "*" ? Object.keys(getTableConfig(this._table).columns).map((c) => `"${getTableConfig(this._table).columns[c].name}" AS "${c}"`).join(", ") : this._returning.map((c) => `"${getTableConfig(this._table).columns[c]?.name ?? c}" AS "${c}"`).join(", "));
|
|
804
823
|
}
|
|
824
|
+
if (this._comment) {
|
|
825
|
+
query += ` /* ${this._comment.replace(/\*\//g, "")} */`;
|
|
826
|
+
}
|
|
805
827
|
return { sql: query, params };
|
|
806
828
|
}
|
|
807
829
|
}
|
|
808
830
|
// ../bungres-orm/src/builders/relational.ts
|
|
831
|
+
function getPkColumn(tableConfig) {
|
|
832
|
+
if (tableConfig.primaryKeys?.length > 0)
|
|
833
|
+
return tableConfig.primaryKeys[0];
|
|
834
|
+
for (const [, col2] of Object.entries(tableConfig.columns)) {
|
|
835
|
+
if (col2.primaryKey)
|
|
836
|
+
return col2.name;
|
|
837
|
+
}
|
|
838
|
+
return "id";
|
|
839
|
+
}
|
|
809
840
|
var _relationsCache = new WeakMap;
|
|
810
841
|
|
|
811
842
|
class RelationalQueryBuilder {
|
|
@@ -956,14 +987,17 @@ class RelationalQueryBuilder {
|
|
|
956
987
|
if (relations.ones[relKey]) {
|
|
957
988
|
const rel = relations.ones[relKey];
|
|
958
989
|
const subAlias = `${alias}_${relKey}`;
|
|
959
|
-
const
|
|
990
|
+
const targetConfig = this._schema[rel.targetTable][TableConfigSymbol];
|
|
991
|
+
const targetPk = getPkColumn(targetConfig);
|
|
992
|
+
const joinCond = `"${subAlias}"."${targetPk}" = "${alias}"."${rel.sourceColumn}"`;
|
|
960
993
|
const subQuery = this._buildSelectJson(rel.targetTable, rArgs, subAlias, params, alias, joinCond);
|
|
961
994
|
const subSql = `SELECT ${subQuery.sql} ${subQuery.from}`;
|
|
962
995
|
jsonFields.push(`'${relKey}', (${subSql})`);
|
|
963
996
|
} else if (relations.manys[relKey]) {
|
|
964
997
|
const rel = relations.manys[relKey];
|
|
965
998
|
const subAlias = `${alias}_${relKey}`;
|
|
966
|
-
const
|
|
999
|
+
const thisPk = getPkColumn(tableConfig);
|
|
1000
|
+
const joinCond = `"${subAlias}"."${rel.targetColumn}" = "${alias}"."${thisPk}"`;
|
|
967
1001
|
const subQuery = this._buildSelectJson(rel.targetTable, rArgs, subAlias, params, alias, joinCond);
|
|
968
1002
|
const aggAlias = `${subAlias}_agg`;
|
|
969
1003
|
const aggSql = `
|
|
@@ -982,9 +1016,9 @@ class RelationalQueryBuilder {
|
|
|
982
1016
|
const junctionTableConfig = this._schema[rel.junctionTable][TableConfigSymbol];
|
|
983
1017
|
const fromExtra = `
|
|
984
1018
|
INNER JOIN ${junctionTableConfig.qualifiedName} AS "${junctionAlias}"
|
|
985
|
-
ON "${junctionAlias}"."${rel.joinTargetColumn}" = "${subAlias}"."${targetTableConfig
|
|
1019
|
+
ON "${junctionAlias}"."${rel.joinTargetColumn}" = "${subAlias}"."${getPkColumn(targetTableConfig)}"
|
|
986
1020
|
`;
|
|
987
|
-
const whereExtra = `"${junctionAlias}"."${rel.joinSourceColumn}" = "${alias}"."${tableConfig
|
|
1021
|
+
const whereExtra = `"${junctionAlias}"."${rel.joinSourceColumn}" = "${alias}"."${getPkColumn(tableConfig)}"`;
|
|
988
1022
|
const subQuery = this._buildSelectJson(rel.targetTable, rArgs, subAlias, params, alias, whereExtra, fromExtra);
|
|
989
1023
|
const aggSql = `
|
|
990
1024
|
SELECT COALESCE(json_agg(_sub.obj), '[]'::json)
|
|
@@ -1196,7 +1230,7 @@ class BungresTransaction {
|
|
|
1196
1230
|
return Array.from(result);
|
|
1197
1231
|
}
|
|
1198
1232
|
}
|
|
1199
|
-
function
|
|
1233
|
+
function bungres(config) {
|
|
1200
1234
|
const db = new BungresDB(config);
|
|
1201
1235
|
if (typeof config === "object" && config.schema) {
|
|
1202
1236
|
const schema = config.schema;
|
|
@@ -1497,6 +1531,14 @@ function diffColumn(prev, next) {
|
|
|
1497
1531
|
const col2 = `"${next.name}"`;
|
|
1498
1532
|
if (prev.dataType !== next.dataType) {
|
|
1499
1533
|
changes.push(`ALTER COLUMN ${col2} TYPE ${next.dataType.toUpperCase()} USING ${col2}::${next.dataType}`);
|
|
1534
|
+
} else {
|
|
1535
|
+
const prevLen = prev.length;
|
|
1536
|
+
const nextLen = next.length;
|
|
1537
|
+
if (prevLen !== nextLen && (next.dataType === "varchar" || next.dataType === "char")) {
|
|
1538
|
+
const typeName = next.dataType === "varchar" ? "VARCHAR" : "CHAR";
|
|
1539
|
+
const typeStr = nextLen ? `${typeName}(${nextLen})` : typeName;
|
|
1540
|
+
changes.push(`ALTER COLUMN ${col2} TYPE ${typeStr}`);
|
|
1541
|
+
}
|
|
1500
1542
|
}
|
|
1501
1543
|
if (!prev.notNull && next.notNull) {
|
|
1502
1544
|
changes.push(`ALTER COLUMN ${col2} SET NOT NULL`);
|
|
@@ -1541,13 +1583,15 @@ async function runPush(config, opts = {}) {
|
|
|
1541
1583
|
}
|
|
1542
1584
|
const sql2 = new Bun.SQL(config.dbUrl);
|
|
1543
1585
|
try {
|
|
1586
|
+
await sql2.unsafe(`CREATE SCHEMA IF NOT EXISTS "${config.migrationsSchema}";`);
|
|
1587
|
+
const qualifiedPush = `"${config.migrationsSchema}"."__bungres_push"`;
|
|
1544
1588
|
await sql2.unsafe(`
|
|
1545
|
-
CREATE TABLE IF NOT EXISTS
|
|
1589
|
+
CREATE TABLE IF NOT EXISTS ${qualifiedPush} (
|
|
1546
1590
|
id SERIAL PRIMARY KEY,
|
|
1547
1591
|
snapshot JSONB NOT NULL
|
|
1548
1592
|
);
|
|
1549
1593
|
`);
|
|
1550
|
-
const rows = await sql2.unsafe(`SELECT snapshot FROM
|
|
1594
|
+
const rows = await sql2.unsafe(`SELECT snapshot FROM ${qualifiedPush} ORDER BY id DESC LIMIT 1;`);
|
|
1551
1595
|
let prevSnapshot = {};
|
|
1552
1596
|
if (rows.length > 0) {
|
|
1553
1597
|
prevSnapshot = typeof rows[0].snapshot === "string" ? JSON.parse(rows[0].snapshot) : rows[0].snapshot;
|
|
@@ -1582,14 +1626,13 @@ Are you sure you want to push these changes? Type YES to continue: `);
|
|
|
1582
1626
|
}
|
|
1583
1627
|
console.log(`
|
|
1584
1628
|
Pushing changes...`);
|
|
1585
|
-
await sql2.unsafe(`CREATE EXTENSION IF NOT EXISTS "pgcrypto";`);
|
|
1586
1629
|
for (const stmt of diff.statements) {
|
|
1587
1630
|
if (config.verbose) {
|
|
1588
1631
|
console.log(`-- ${stmt}`);
|
|
1589
1632
|
}
|
|
1590
1633
|
await sql2.unsafe(stmt);
|
|
1591
1634
|
}
|
|
1592
|
-
await sql2.unsafe(`INSERT INTO
|
|
1635
|
+
await sql2.unsafe(`INSERT INTO ${qualifiedPush} (snapshot) VALUES ($1);`, [JSON.stringify(currentSnapshot)]);
|
|
1593
1636
|
console.log(`
|
|
1594
1637
|
Push complete.`);
|
|
1595
1638
|
} finally {
|
|
@@ -1605,9 +1648,9 @@ async function readLine() {
|
|
|
1605
1648
|
import { join as join3, resolve as resolve3 } from "path";
|
|
1606
1649
|
|
|
1607
1650
|
// src/utils/colors.ts
|
|
1608
|
-
function colorize(
|
|
1651
|
+
function colorize(text, color) {
|
|
1609
1652
|
const code = Bun.color(color, "ansi");
|
|
1610
|
-
return code ? `${code}${
|
|
1653
|
+
return code ? `${code}${text}\x1B[0m` : text;
|
|
1611
1654
|
}
|
|
1612
1655
|
|
|
1613
1656
|
// src/commands/generate.ts
|
|
@@ -1619,7 +1662,7 @@ async function runGenerate(config, name) {
|
|
|
1619
1662
|
console.warn(colorize("No table definitions found. Check your schema glob pattern.", "yellow"));
|
|
1620
1663
|
return;
|
|
1621
1664
|
}
|
|
1622
|
-
const migrationsDir = resolve3(config.
|
|
1665
|
+
const migrationsDir = resolve3(config.out);
|
|
1623
1666
|
await Bun.$`mkdir -p ${migrationsDir}`.quiet();
|
|
1624
1667
|
const currentSnapshot = Object.fromEntries(schemas.map((s) => [s.config.name, s.config]));
|
|
1625
1668
|
const snapshotPath = join3(migrationsDir, SNAPSHOT_FILE);
|
|
@@ -1642,8 +1685,6 @@ async function runGenerate(config, name) {
|
|
|
1642
1685
|
if (isFirstMigration) {
|
|
1643
1686
|
const sorted = topoSort(schemas);
|
|
1644
1687
|
statements = [
|
|
1645
|
-
`CREATE EXTENSION IF NOT EXISTS "pgcrypto";`,
|
|
1646
|
-
``,
|
|
1647
1688
|
...sorted.flatMap((entry) => [
|
|
1648
1689
|
`-- ${entry.exportName}`,
|
|
1649
1690
|
generateCreateTable(entry.config, true),
|
|
@@ -1712,19 +1753,22 @@ function topoSort(schemas) {
|
|
|
1712
1753
|
}
|
|
1713
1754
|
// src/commands/migrate.ts
|
|
1714
1755
|
import { join as join4, resolve as resolve4 } from "path";
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1756
|
+
async function runMigrate(config) {
|
|
1757
|
+
const migrationsDir = resolve4(config.out);
|
|
1758
|
+
const sql2 = new Bun.SQL(config.dbUrl);
|
|
1759
|
+
const table2 = config.migrationsTable;
|
|
1760
|
+
const schema = config.migrationsSchema;
|
|
1761
|
+
const qualifiedTable = `"${schema}"."${table2}"`;
|
|
1762
|
+
const createSchema = `CREATE SCHEMA IF NOT EXISTS "${schema}";`;
|
|
1763
|
+
const createMigrationsTable = `
|
|
1764
|
+
CREATE TABLE IF NOT EXISTS ${qualifiedTable} (
|
|
1718
1765
|
id SERIAL PRIMARY KEY,
|
|
1719
1766
|
name TEXT NOT NULL UNIQUE,
|
|
1720
1767
|
applied_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
1721
|
-
);
|
|
1722
|
-
`.trim();
|
|
1723
|
-
async function runMigrate(config) {
|
|
1724
|
-
const migrationsDir = resolve4(config.migrationsDir);
|
|
1725
|
-
const sql2 = new Bun.SQL(config.dbUrl);
|
|
1768
|
+
);`.trim();
|
|
1726
1769
|
try {
|
|
1727
|
-
await sql2.unsafe(
|
|
1770
|
+
await sql2.unsafe(createSchema);
|
|
1771
|
+
await sql2.unsafe(createMigrationsTable);
|
|
1728
1772
|
const glob = new Bun.Glob("*.sql");
|
|
1729
1773
|
const files = [];
|
|
1730
1774
|
for await (const file of glob.scan({ cwd: migrationsDir, absolute: false })) {
|
|
@@ -1736,7 +1780,7 @@ async function runMigrate(config) {
|
|
|
1736
1780
|
console.log(colorize("Run `bungres generate` first.", "yellow"));
|
|
1737
1781
|
return;
|
|
1738
1782
|
}
|
|
1739
|
-
const applied = await sql2.unsafe(`SELECT name FROM
|
|
1783
|
+
const applied = await sql2.unsafe(`SELECT name FROM ${qualifiedTable}`);
|
|
1740
1784
|
const appliedSet = new Set(applied.map((r) => r.name));
|
|
1741
1785
|
const pending = files.filter((f) => !appliedSet.has(f));
|
|
1742
1786
|
if (pending.length === 0) {
|
|
@@ -1754,11 +1798,11 @@ ${content}
|
|
|
1754
1798
|
`);
|
|
1755
1799
|
}
|
|
1756
1800
|
await sql2.transaction(async (txSql) => {
|
|
1757
|
-
const statements = content.split(";").map((s) => s.trim()).filter(Boolean);
|
|
1801
|
+
const statements = config.breakpoints ? content.split(/-->statement-breakpoint/g).flatMap((chunk) => chunk.split(";").map((s) => s.trim()).filter(Boolean)) : content.split(";").map((s) => s.trim()).filter(Boolean);
|
|
1758
1802
|
for (const stmt of statements) {
|
|
1759
1803
|
await txSql.unsafe(stmt + ";");
|
|
1760
1804
|
}
|
|
1761
|
-
await txSql.unsafe(`INSERT INTO
|
|
1805
|
+
await txSql.unsafe(`INSERT INTO ${qualifiedTable} (name) VALUES ($1)`, [file]);
|
|
1762
1806
|
});
|
|
1763
1807
|
console.log(colorize(` \u2713 ${file}`, "green"));
|
|
1764
1808
|
}
|
|
@@ -1866,7 +1910,7 @@ function generateSchemaTS(tableMap, dbSchema) {
|
|
|
1866
1910
|
`// Generated at: ${new Date().toISOString()}`,
|
|
1867
1911
|
``,
|
|
1868
1912
|
`import {`,
|
|
1869
|
-
`
|
|
1913
|
+
` table,`,
|
|
1870
1914
|
` text, varchar, char, integer, bigint, smallint,`,
|
|
1871
1915
|
` serial, bigserial, boolean, real, doublePrecision,`,
|
|
1872
1916
|
` numeric, decimal, json, jsonb,`,
|
|
@@ -1878,7 +1922,7 @@ function generateSchemaTS(tableMap, dbSchema) {
|
|
|
1878
1922
|
];
|
|
1879
1923
|
for (const [, table2] of tableMap) {
|
|
1880
1924
|
const varName = toCamelCase(table2.tableName);
|
|
1881
|
-
lines.push(`export const ${varName} =
|
|
1925
|
+
lines.push(`export const ${varName} = table("${table2.tableName}", {`);
|
|
1882
1926
|
for (const col2 of table2.columns) {
|
|
1883
1927
|
const colExpr = buildColumnExpression(col2);
|
|
1884
1928
|
lines.push(` ${toCamelCase(col2.name)}: ${colExpr},`);
|
|
@@ -2025,15 +2069,17 @@ function toCamelCase(str) {
|
|
|
2025
2069
|
}
|
|
2026
2070
|
// src/commands/status.ts
|
|
2027
2071
|
import { resolve as resolve6 } from "path";
|
|
2028
|
-
var MIGRATIONS_TABLE2 = "__bungres_migrations";
|
|
2029
2072
|
async function runStatus(config) {
|
|
2030
|
-
const migrationsDir = resolve6(config.
|
|
2073
|
+
const migrationsDir = resolve6(config.out);
|
|
2031
2074
|
const sql2 = new Bun.SQL(config.dbUrl);
|
|
2075
|
+
const table2 = config.migrationsTable;
|
|
2076
|
+
const schema = config.migrationsSchema;
|
|
2077
|
+
const qualifiedTable = `"${schema}"."${table2}"`;
|
|
2032
2078
|
try {
|
|
2033
2079
|
const tableCheck = await sql2.unsafe(`SELECT EXISTS (
|
|
2034
2080
|
SELECT 1 FROM information_schema.tables
|
|
2035
|
-
WHERE table_name = $
|
|
2036
|
-
) AS exists`, [
|
|
2081
|
+
WHERE table_schema = $1 AND table_name = $2
|
|
2082
|
+
) AS exists`, [schema, table2]);
|
|
2037
2083
|
const trackingExists = tableCheck[0]?.exists ?? false;
|
|
2038
2084
|
const glob = new Bun.Glob("*.sql");
|
|
2039
2085
|
const files = [];
|
|
@@ -2047,7 +2093,7 @@ async function runStatus(config) {
|
|
|
2047
2093
|
}
|
|
2048
2094
|
let appliedSet = new Set;
|
|
2049
2095
|
if (trackingExists) {
|
|
2050
|
-
const applied = await sql2.unsafe(`SELECT name FROM
|
|
2096
|
+
const applied = await sql2.unsafe(`SELECT name FROM ${qualifiedTable} ORDER BY applied_at`);
|
|
2051
2097
|
appliedSet = new Set(applied.map((r) => r.name));
|
|
2052
2098
|
}
|
|
2053
2099
|
console.log(colorize(`
|
|
@@ -2077,14 +2123,19 @@ async function runDrop(config, opts = {}) {
|
|
|
2077
2123
|
}
|
|
2078
2124
|
const sql2 = new Bun.SQL(config.dbUrl);
|
|
2079
2125
|
try {
|
|
2080
|
-
const
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
const
|
|
2126
|
+
const userSchema = config.dbSchema;
|
|
2127
|
+
const existingUserTablesResult = await sql2.unsafe(`SELECT table_name FROM information_schema.tables WHERE table_schema = $1`, [userSchema]);
|
|
2128
|
+
const existingTableNames = new Set(existingUserTablesResult.map((r) => r.table_name));
|
|
2129
|
+
const migTableCheck = await sql2.unsafe(`SELECT EXISTS (
|
|
2130
|
+
SELECT 1 FROM information_schema.tables
|
|
2131
|
+
WHERE table_schema = $1 AND table_name = $2
|
|
2132
|
+
) AS exists`, [config.migrationsSchema, config.migrationsTable]);
|
|
2133
|
+
const migrationTableExists = migTableCheck[0]?.exists ?? false;
|
|
2134
|
+
const pushTableCheck = await sql2.unsafe(`SELECT EXISTS (
|
|
2135
|
+
SELECT 1 FROM information_schema.tables
|
|
2136
|
+
WHERE table_schema = $1 AND table_name = $2
|
|
2137
|
+
) AS exists`, [config.migrationsSchema, "__bungres_push"]);
|
|
2138
|
+
const pushTableExists = pushTableCheck[0]?.exists ?? false;
|
|
2088
2139
|
const tablesToDrop = schemas.filter((s) => existingTableNames.has(s.config.name));
|
|
2089
2140
|
if (tablesToDrop.length === 0 && !migrationTableExists && !pushTableExists) {
|
|
2090
2141
|
console.log("No tables to drop (they either don't exist or were already dropped).");
|
|
@@ -2092,10 +2143,10 @@ async function runDrop(config, opts = {}) {
|
|
|
2092
2143
|
}
|
|
2093
2144
|
const tableNamesToPrint = tablesToDrop.map((s) => (s.config.schema ? s.config.schema + "." : "") + s.config.name);
|
|
2094
2145
|
if (migrationTableExists) {
|
|
2095
|
-
tableNamesToPrint.push(
|
|
2146
|
+
tableNamesToPrint.push(`${config.migrationsSchema}.${config.migrationsTable}`);
|
|
2096
2147
|
}
|
|
2097
2148
|
if (pushTableExists) {
|
|
2098
|
-
tableNamesToPrint.push(
|
|
2149
|
+
tableNamesToPrint.push(`${config.migrationsSchema}.__bungres_push`);
|
|
2099
2150
|
}
|
|
2100
2151
|
if (!opts.force) {
|
|
2101
2152
|
console.warn(colorize(`
|
|
@@ -2119,12 +2170,13 @@ Are you sure? Type YES to continue: `, "cyan"));
|
|
|
2119
2170
|
console.log(colorize(` \u2713 dropped ${entry.config.name}`, "green"));
|
|
2120
2171
|
}
|
|
2121
2172
|
if (migrationTableExists) {
|
|
2122
|
-
|
|
2123
|
-
|
|
2173
|
+
const qualifiedMigTable = `"${config.migrationsSchema}"."${config.migrationsTable}"`;
|
|
2174
|
+
await sql2.unsafe(`DROP TABLE IF EXISTS ${qualifiedMigTable} CASCADE`);
|
|
2175
|
+
console.log(colorize(` \u2713 dropped ${config.migrationsSchema}.${config.migrationsTable}`, "green"));
|
|
2124
2176
|
}
|
|
2125
2177
|
if (pushTableExists) {
|
|
2126
|
-
await sql2.unsafe(
|
|
2127
|
-
console.log(colorize(` \u2713 dropped __bungres_push`, "green"));
|
|
2178
|
+
await sql2.unsafe(`DROP TABLE IF EXISTS "${config.migrationsSchema}"."__bungres_push" CASCADE`);
|
|
2179
|
+
console.log(colorize(` \u2713 dropped ${config.migrationsSchema}.__bungres_push`, "green"));
|
|
2128
2180
|
}
|
|
2129
2181
|
console.log(colorize(`
|
|
2130
2182
|
Drop complete.`, "green"));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bungres/kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "CLI toolkit for @bungres/orm — migrate, push, generate, pull",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"repository": {
|
|
30
30
|
"type": "git",
|
|
31
31
|
"url": "https://github.com/bungres/bungres.git",
|
|
32
|
-
"directory": "packages
|
|
32
|
+
"directory": "packages/bungres-kit"
|
|
33
33
|
},
|
|
34
34
|
"bugs": {
|
|
35
35
|
"url": "https://github.com/bungres/bungres/issues"
|