@bungres/kit 0.4.0 → 0.5.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @bungres/kit
2
2
 
3
- CLI toolkit for [`@bungres/orm`](https://www.npmjs.com/package/@bungres/orm) — generate, migrate, push, pull, status, and drop your database schema with ease. 🐘✨
3
+ CLI toolkit for [`@bungres/orm`](https://www.npmjs.com/package/@bungres/orm) — initialize, generate, migrate, push, pull, status, and drop your database schema with ease. 🐘✨
4
4
 
5
5
  ## Requirements
6
6
 
@@ -25,7 +25,7 @@ export default defineConfig({
25
25
  schema: "./src/db/schema.ts",
26
26
  out: "./bungres", // Directory for migrations & generated files
27
27
  dbCredentials: {
28
- url: process.env.DATABASE_URL!,
28
+ url: Bun.env.DATABASE_URL!,
29
29
  },
30
30
  });
31
31
  ```
@@ -40,6 +40,7 @@ bun run bungres --help
40
40
 
41
41
  | Command | Description |
42
42
  |---|---|
43
+ | `bungres init` | Initialize bungres project with config file and db folder structure |
43
44
  | `bungres generate` | Write a timestamped `.sql` migration file from your schema |
44
45
  | `bungres migrate` | Run pending `.sql` files, track applied in `__bungres_migrations` |
45
46
  | `bungres push` | Apply schema directly to DB — no files (great for dev/prototyping) |
@@ -55,6 +56,7 @@ bun run bungres --help
55
56
  ### Usage Examples
56
57
 
57
58
  ```bash
59
+ bun run bungres init
58
60
  bun run bungres generate
59
61
  bun run bungres migrate
60
62
  bun run bungres push
package/dist/cli.js CHANGED
@@ -70,7 +70,7 @@ function createTableFactory(casing) {
70
70
  return Object.assign(tableObj, columnConfigs);
71
71
  };
72
72
  }
73
- var table = createTableFactory("none");
73
+ var table = createTableFactory("snake");
74
74
  var snakeCase = { table: createTableFactory("snake") };
75
75
  var camelCase = { table: createTableFactory("camel") };
76
76
  // ../bungres-orm/src/schema/columns.ts
@@ -1162,7 +1162,7 @@ class BungresTransaction {
1162
1162
  return Array.from(result2);
1163
1163
  }
1164
1164
  }
1165
- function createDB(config2) {
1165
+ function bungres(config2) {
1166
1166
  const db2 = new BungresDB(config2);
1167
1167
  if (typeof config2 === "object" && config2.schema) {
1168
1168
  const schema = config2.schema;
@@ -1345,14 +1345,19 @@ async function runDrop(config2, opts = {}) {
1345
1345
  }
1346
1346
  const sql2 = new Bun.SQL(config2.dbUrl);
1347
1347
  try {
1348
- const existingTablesResult = await sql2`
1349
- SELECT table_name
1350
- FROM information_schema.tables
1351
- WHERE table_schema = 'public' OR table_schema = current_schema()
1352
- `;
1353
- const existingTableNames = new Set(existingTablesResult.map((row) => row.table_name));
1354
- const migrationTableExists = existingTableNames.has("__bungres_migrations");
1355
- const pushTableExists = existingTableNames.has("__bungres_push");
1348
+ const userSchema = config2.dbSchema;
1349
+ const existingUserTablesResult = await sql2.unsafe(`SELECT table_name FROM information_schema.tables WHERE table_schema = $1`, [userSchema]);
1350
+ const existingTableNames = new Set(existingUserTablesResult.map((r) => r.table_name));
1351
+ const migTableCheck = await sql2.unsafe(`SELECT EXISTS (
1352
+ SELECT 1 FROM information_schema.tables
1353
+ WHERE table_schema = $1 AND table_name = $2
1354
+ ) AS exists`, [config2.migrationsSchema, config2.migrationsTable]);
1355
+ const migrationTableExists = migTableCheck[0]?.exists ?? false;
1356
+ const pushTableCheck = await sql2.unsafe(`SELECT EXISTS (
1357
+ SELECT 1 FROM information_schema.tables
1358
+ WHERE table_schema = $1 AND table_name = $2
1359
+ ) AS exists`, [config2.migrationsSchema, "__bungres_push"]);
1360
+ const pushTableExists = pushTableCheck[0]?.exists ?? false;
1356
1361
  const tablesToDrop = schemas2.filter((s) => existingTableNames.has(s.config.name));
1357
1362
  if (tablesToDrop.length === 0 && !migrationTableExists && !pushTableExists) {
1358
1363
  console.log("No tables to drop (they either don't exist or were already dropped).");
@@ -1360,10 +1365,10 @@ async function runDrop(config2, opts = {}) {
1360
1365
  }
1361
1366
  const tableNamesToPrint = tablesToDrop.map((s) => (s.config.schema ? s.config.schema + "." : "") + s.config.name);
1362
1367
  if (migrationTableExists) {
1363
- tableNamesToPrint.push("__bungres_migrations");
1368
+ tableNamesToPrint.push(`${config2.migrationsSchema}.${config2.migrationsTable}`);
1364
1369
  }
1365
1370
  if (pushTableExists) {
1366
- tableNamesToPrint.push("__bungres_push");
1371
+ tableNamesToPrint.push(`${config2.migrationsSchema}.__bungres_push`);
1367
1372
  }
1368
1373
  if (!opts.force) {
1369
1374
  console.warn(colorize(`
@@ -1387,12 +1392,13 @@ Are you sure? Type YES to continue: `, "cyan"));
1387
1392
  console.log(colorize(` \u2713 dropped ${entry.config.name}`, "green"));
1388
1393
  }
1389
1394
  if (migrationTableExists) {
1390
- await sql2.unsafe("DROP TABLE IF EXISTS public.__bungres_migrations CASCADE");
1391
- console.log(colorize(` \u2713 dropped __bungres_migrations`, "green"));
1395
+ const qualifiedMigTable = `"${config2.migrationsSchema}"."${config2.migrationsTable}"`;
1396
+ await sql2.unsafe(`DROP TABLE IF EXISTS ${qualifiedMigTable} CASCADE`);
1397
+ console.log(colorize(` \u2713 dropped ${config2.migrationsSchema}.${config2.migrationsTable}`, "green"));
1392
1398
  }
1393
1399
  if (pushTableExists) {
1394
- await sql2.unsafe("DROP TABLE IF EXISTS public.__bungres_push CASCADE");
1395
- console.log(colorize(` \u2713 dropped __bungres_push`, "green"));
1400
+ await sql2.unsafe(`DROP TABLE IF EXISTS "${config2.migrationsSchema}"."__bungres_push" CASCADE`);
1401
+ console.log(colorize(` \u2713 dropped ${config2.migrationsSchema}.__bungres_push`, "green"));
1396
1402
  }
1397
1403
  console.log(colorize(`
1398
1404
  Drop complete.`, "green"));
@@ -1403,19 +1409,22 @@ Drop complete.`, "green"));
1403
1409
 
1404
1410
  // src/commands/migrate.ts
1405
1411
  import { join as join2, resolve as resolve2 } from "path";
1406
- var MIGRATIONS_TABLE = "__bungres_migrations";
1407
- var CREATE_MIGRATIONS_TABLE = `
1408
- CREATE TABLE IF NOT EXISTS "${MIGRATIONS_TABLE}" (
1412
+ async function runMigrate(config2) {
1413
+ const migrationsDir = resolve2(config2.out);
1414
+ const sql2 = new Bun.SQL(config2.dbUrl);
1415
+ const table2 = config2.migrationsTable;
1416
+ const schema = config2.migrationsSchema;
1417
+ const qualifiedTable = `"${schema}"."${table2}"`;
1418
+ const createSchema = `CREATE SCHEMA IF NOT EXISTS "${schema}";`;
1419
+ const createMigrationsTable = `
1420
+ CREATE TABLE IF NOT EXISTS ${qualifiedTable} (
1409
1421
  id SERIAL PRIMARY KEY,
1410
1422
  name TEXT NOT NULL UNIQUE,
1411
1423
  applied_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
1412
- );
1413
- `.trim();
1414
- async function runMigrate(config2) {
1415
- const migrationsDir = resolve2(config2.migrationsDir);
1416
- const sql2 = new Bun.SQL(config2.dbUrl);
1424
+ );`.trim();
1417
1425
  try {
1418
- await sql2.unsafe(CREATE_MIGRATIONS_TABLE);
1426
+ await sql2.unsafe(createSchema);
1427
+ await sql2.unsafe(createMigrationsTable);
1419
1428
  const glob = new Bun.Glob("*.sql");
1420
1429
  const files = [];
1421
1430
  for await (const file of glob.scan({ cwd: migrationsDir, absolute: false })) {
@@ -1427,7 +1436,7 @@ async function runMigrate(config2) {
1427
1436
  console.log(colorize("Run `bungres generate` first.", "yellow"));
1428
1437
  return;
1429
1438
  }
1430
- const applied = await sql2.unsafe(`SELECT name FROM "${MIGRATIONS_TABLE}"`);
1439
+ const applied = await sql2.unsafe(`SELECT name FROM ${qualifiedTable}`);
1431
1440
  const appliedSet = new Set(applied.map((r) => r.name));
1432
1441
  const pending = files.filter((f) => !appliedSet.has(f));
1433
1442
  if (pending.length === 0) {
@@ -1445,11 +1454,11 @@ ${content}
1445
1454
  `);
1446
1455
  }
1447
1456
  await sql2.transaction(async (txSql) => {
1448
- const statements = content.split(";").map((s) => s.trim()).filter(Boolean);
1457
+ const statements = config2.breakpoints ? content.split(/-->statement-breakpoint/g).flatMap((chunk) => chunk.split(";").map((s) => s.trim()).filter(Boolean)) : content.split(";").map((s) => s.trim()).filter(Boolean);
1449
1458
  for (const stmt of statements) {
1450
1459
  await txSql.unsafe(stmt + ";");
1451
1460
  }
1452
- await txSql.unsafe(`INSERT INTO "${MIGRATIONS_TABLE}" (name) VALUES ($1)`, [file]);
1461
+ await txSql.unsafe(`INSERT INTO ${qualifiedTable} (name) VALUES ($1)`, [file]);
1453
1462
  });
1454
1463
  console.log(colorize(` \u2713 ${file}`, "green"));
1455
1464
  }
@@ -1648,7 +1657,7 @@ async function runGenerate(config2, name) {
1648
1657
  console.warn(colorize("No table definitions found. Check your schema glob pattern.", "yellow"));
1649
1658
  return;
1650
1659
  }
1651
- const migrationsDir = resolve3(config2.migrationsDir);
1660
+ const migrationsDir = resolve3(config2.out);
1652
1661
  await Bun.$`mkdir -p ${migrationsDir}`.quiet();
1653
1662
  const currentSnapshot = Object.fromEntries(schemas2.map((s) => [s.config.name, s.config]));
1654
1663
  const snapshotPath = join3(migrationsDir, SNAPSHOT_FILE);
@@ -1764,7 +1773,7 @@ export default defineConfig({
1764
1773
  schema: "./src/db/schema.ts",
1765
1774
  out: "./bungres",
1766
1775
  dbCredentials: {
1767
- url: Bun.env.DATABASE_URL!,
1776
+ url: process.env.DATABASE_URL!,
1768
1777
  },
1769
1778
  });
1770
1779
  `;
@@ -1779,12 +1788,12 @@ export default defineConfig({
1779
1788
  uuid,
1780
1789
  varchar,
1781
1790
  timestamptz,
1782
- snakeCase,
1791
+ table,
1783
1792
  unique,
1784
1793
  index
1785
1794
  } from "@bungres/orm";
1786
1795
 
1787
- export const users = snakeCase.table("users", {
1796
+ export const users = table("users", {
1788
1797
  id: uuid({ primaryKey: true }),
1789
1798
  name: varchar({ length: 255, notNull: true }),
1790
1799
  email: varchar({ length: 255, notNull: true }),
@@ -1800,12 +1809,12 @@ export const users = snakeCase.table("users", {
1800
1809
  } catch (e) {
1801
1810
  console.error("Failed to create schema file:", e);
1802
1811
  }
1803
- const clientContent = `import { createDB } from "@bungres/orm";
1812
+ const clientContent = `import { bungres } from "@bungres/orm";
1804
1813
  import * as schema from "./schema";
1805
1814
 
1806
1815
  const url = Bun.env.DATABASE_URL || "postgres://postgres:postgres@localhost:5432/postgres";
1807
1816
 
1808
- export const db = createDB({ url, schema });
1817
+ export const db = bungres({ url, schema });
1809
1818
  `;
1810
1819
  try {
1811
1820
  await Bun.write(join4(dbDir, "client.ts"), clientContent);
@@ -1921,7 +1930,7 @@ function generateSchemaTS(tableMap, dbSchema) {
1921
1930
  `// Generated at: ${new Date().toISOString()}`,
1922
1931
  ``,
1923
1932
  `import {`,
1924
- ` snakeCase,`,
1933
+ ` table,`,
1925
1934
  ` text, varchar, char, integer, bigint, smallint,`,
1926
1935
  ` serial, bigserial, boolean, real, doublePrecision,`,
1927
1936
  ` numeric, decimal, json, jsonb,`,
@@ -1933,7 +1942,7 @@ function generateSchemaTS(tableMap, dbSchema) {
1933
1942
  ];
1934
1943
  for (const [, table2] of tableMap) {
1935
1944
  const varName = toCamelCase(table2.tableName);
1936
- lines.push(`export const ${varName} = snakeCase.table("${table2.tableName}", {`);
1945
+ lines.push(`export const ${varName} = table("${table2.tableName}", {`);
1937
1946
  for (const col2 of table2.columns) {
1938
1947
  const colExpr = buildColumnExpression(col2);
1939
1948
  lines.push(` ${toCamelCase(col2.name)}: ${colExpr},`);
@@ -2193,7 +2202,7 @@ Running seeder: ${config2.seed}...`, "cyan"));
2193
2202
  cwd: process.cwd(),
2194
2203
  stdout: "inherit",
2195
2204
  stderr: "inherit",
2196
- env: { ...process.env, DATABASE_URL: config2.dbUrl }
2205
+ env: { ...Bun.env, DATABASE_URL: config2.dbUrl }
2197
2206
  });
2198
2207
  const exitCode = await proc.exited;
2199
2208
  if (exitCode === 0) {
@@ -2208,15 +2217,17 @@ Seed failed with exit code ${exitCode}.`);
2208
2217
 
2209
2218
  // src/commands/status.ts
2210
2219
  import { resolve as resolve6 } from "path";
2211
- var MIGRATIONS_TABLE2 = "__bungres_migrations";
2212
2220
  async function runStatus(config2) {
2213
- const migrationsDir = resolve6(config2.migrationsDir);
2221
+ const migrationsDir = resolve6(config2.out);
2214
2222
  const sql2 = new Bun.SQL(config2.dbUrl);
2223
+ const table2 = config2.migrationsTable;
2224
+ const schema = config2.migrationsSchema;
2225
+ const qualifiedTable = `"${schema}"."${table2}"`;
2215
2226
  try {
2216
2227
  const tableCheck = await sql2.unsafe(`SELECT EXISTS (
2217
2228
  SELECT 1 FROM information_schema.tables
2218
- WHERE table_name = $1
2219
- ) AS exists`, [MIGRATIONS_TABLE2]);
2229
+ WHERE table_schema = $1 AND table_name = $2
2230
+ ) AS exists`, [schema, table2]);
2220
2231
  const trackingExists = tableCheck[0]?.exists ?? false;
2221
2232
  const glob = new Bun.Glob("*.sql");
2222
2233
  const files = [];
@@ -2230,7 +2241,7 @@ async function runStatus(config2) {
2230
2241
  }
2231
2242
  let appliedSet = new Set;
2232
2243
  if (trackingExists) {
2233
- const applied = await sql2.unsafe(`SELECT name FROM "${MIGRATIONS_TABLE2}" ORDER BY applied_at`);
2244
+ const applied = await sql2.unsafe(`SELECT name FROM ${qualifiedTable} ORDER BY applied_at`);
2234
2245
  appliedSet = new Set(applied.map((r) => r.name));
2235
2246
  }
2236
2247
  console.log(colorize(`
@@ -2263,8 +2274,8 @@ async function runStudio(config2) {
2263
2274
  for (const s of schemas2) {
2264
2275
  schemaObj2[s.exportName] = s.table;
2265
2276
  }
2266
- const db2 = createDB({ url: config2.dbUrl, schema: schemaObj2 });
2267
- const port = process.env.PORT ? parseInt(process.env.PORT, 10) : 5555;
2277
+ const db2 = bungres({ url: config2.dbUrl, schema: schemaObj2 });
2278
+ const port = Bun.env.PORT ? parseInt(Bun.env.PORT, 10) : 5555;
2268
2279
  const server = Bun.serve({
2269
2280
  port,
2270
2281
  async fetch(req) {
@@ -3069,7 +3080,7 @@ async function runTusky(config) {
3069
3080
  for (const s of schemas) {
3070
3081
  schemaObj[s.exportName] = s.table;
3071
3082
  }
3072
- const db = createDB({ url: config.dbUrl, schema: schemaObj });
3083
+ const db = bungres({ url: config.dbUrl, schema: schemaObj });
3073
3084
  console.log("=========================================");
3074
3085
  console.log("\uD83D\uDC18 Welcome to Bungres REPL (Tusky)");
3075
3086
  console.log("=========================================");
@@ -3127,7 +3138,7 @@ Example query: await db.select().from(users)`);
3127
3138
  }
3128
3139
 
3129
3140
  // src/config.ts
3130
- import { resolve as resolve7, join as join6 } from "path";
3141
+ import { join as join6, resolve as resolve7 } from "path";
3131
3142
  var CONFIG_FILES = [
3132
3143
  "bungres.config.ts",
3133
3144
  "bungres.config.js",
@@ -3144,7 +3155,7 @@ async function loadConfig(cwd = process.cwd()) {
3144
3155
  break;
3145
3156
  }
3146
3157
  }
3147
- const dbUrl = userConfig.dbCredentials?.url ?? process.env["DATABASE_URL"] ?? process.env["POSTGRES_URL"] ?? "";
3158
+ const dbUrl = userConfig.dbCredentials?.url ?? Bun.env.DATABASE_URL ?? Bun.env.POSTGRES_URL ?? "";
3148
3159
  if (!dbUrl) {
3149
3160
  console.error(`bungres: No database URL found.
3150
3161
  Add dbCredentials.url to bungres.config.ts or set DATABASE_URL.`);
@@ -3157,7 +3168,10 @@ async function loadConfig(cwd = process.cwd()) {
3157
3168
  out,
3158
3169
  dbUrl,
3159
3170
  dbSchema: userConfig.dbSchema ?? "public",
3160
- migrationsDir: out,
3171
+ migrationsTable: userConfig.migrations?.table ?? "__bungres_migrations",
3172
+ migrationsSchema: userConfig.migrations?.schema ?? "bungres",
3173
+ breakpoints: userConfig.breakpoints ?? true,
3174
+ strict: userConfig.strict ?? false,
3161
3175
  outDir: "./src/db/generated",
3162
3176
  verbose: userConfig.verbose ?? false
3163
3177
  };
@@ -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,CA8Ef"}
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":"migrate.d.ts","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAiBnD,wBAAsB,UAAU,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAiEtE"}
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":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AASnD,wBAAsB,SAAS,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAqDrE"}
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"}
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
- * Equivalent to drizzle's `out`. Default: "./migrations"
14
+ * Default: "./migrations"
15
15
  */
16
16
  out?: string;
17
17
  /**
@@ -26,6 +26,33 @@ 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;
29
56
  /** Print every SQL statement executed. Default: false */
30
57
  verbose?: boolean;
31
58
  }
@@ -35,8 +62,10 @@ export interface ResolvedConfig {
35
62
  out: string;
36
63
  dbUrl: string;
37
64
  dbSchema: string;
38
- /** @deprecated use out — kept internally for compat */
39
- migrationsDir: string;
65
+ migrationsTable: string;
66
+ migrationsSchema: string;
67
+ breakpoints: boolean;
68
+ strict: boolean;
40
69
  outDir: string;
41
70
  verbose: boolean;
42
71
  }
@@ -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,uDAAuD;IACvD,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AASD,wBAAsB,UAAU,CAAC,GAAG,SAAgB,GAAG,OAAO,CAAC,cAAc,CAAC,CAuC7E"}
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,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/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // @bun
2
2
  // src/config.ts
3
- import { resolve, join } from "path";
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 ?? process.env["DATABASE_URL"] ?? process.env["POSTGRES_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,7 +30,10 @@ async function loadConfig(cwd = process.cwd()) {
30
30
  out,
31
31
  dbUrl,
32
32
  dbSchema: userConfig.dbSchema ?? "public",
33
- migrationsDir: out,
33
+ migrationsTable: userConfig.migrations?.table ?? "__bungres_migrations",
34
+ migrationsSchema: userConfig.migrations?.schema ?? "bungres",
35
+ breakpoints: userConfig.breakpoints ?? true,
36
+ strict: userConfig.strict ?? false,
34
37
  outDir: "./src/db/generated",
35
38
  verbose: userConfig.verbose ?? false
36
39
  };
@@ -104,7 +107,7 @@ function createTableFactory(casing) {
104
107
  return Object.assign(tableObj, columnConfigs);
105
108
  };
106
109
  }
107
- var table = createTableFactory("none");
110
+ var table = createTableFactory("snake");
108
111
  var snakeCase = { table: createTableFactory("snake") };
109
112
  var camelCase = { table: createTableFactory("camel") };
110
113
  // ../bungres-orm/src/schema/columns.ts
@@ -1196,7 +1199,7 @@ class BungresTransaction {
1196
1199
  return Array.from(result);
1197
1200
  }
1198
1201
  }
1199
- function createDB(config) {
1202
+ function bungres(config) {
1200
1203
  const db = new BungresDB(config);
1201
1204
  if (typeof config === "object" && config.schema) {
1202
1205
  const schema = config.schema;
@@ -1619,7 +1622,7 @@ async function runGenerate(config, name) {
1619
1622
  console.warn(colorize("No table definitions found. Check your schema glob pattern.", "yellow"));
1620
1623
  return;
1621
1624
  }
1622
- const migrationsDir = resolve3(config.migrationsDir);
1625
+ const migrationsDir = resolve3(config.out);
1623
1626
  await Bun.$`mkdir -p ${migrationsDir}`.quiet();
1624
1627
  const currentSnapshot = Object.fromEntries(schemas.map((s) => [s.config.name, s.config]));
1625
1628
  const snapshotPath = join3(migrationsDir, SNAPSHOT_FILE);
@@ -1712,19 +1715,22 @@ function topoSort(schemas) {
1712
1715
  }
1713
1716
  // src/commands/migrate.ts
1714
1717
  import { join as join4, resolve as resolve4 } from "path";
1715
- var MIGRATIONS_TABLE = "__bungres_migrations";
1716
- var CREATE_MIGRATIONS_TABLE = `
1717
- CREATE TABLE IF NOT EXISTS "${MIGRATIONS_TABLE}" (
1718
+ async function runMigrate(config) {
1719
+ const migrationsDir = resolve4(config.out);
1720
+ const sql2 = new Bun.SQL(config.dbUrl);
1721
+ const table2 = config.migrationsTable;
1722
+ const schema = config.migrationsSchema;
1723
+ const qualifiedTable = `"${schema}"."${table2}"`;
1724
+ const createSchema = `CREATE SCHEMA IF NOT EXISTS "${schema}";`;
1725
+ const createMigrationsTable = `
1726
+ CREATE TABLE IF NOT EXISTS ${qualifiedTable} (
1718
1727
  id SERIAL PRIMARY KEY,
1719
1728
  name TEXT NOT NULL UNIQUE,
1720
1729
  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);
1730
+ );`.trim();
1726
1731
  try {
1727
- await sql2.unsafe(CREATE_MIGRATIONS_TABLE);
1732
+ await sql2.unsafe(createSchema);
1733
+ await sql2.unsafe(createMigrationsTable);
1728
1734
  const glob = new Bun.Glob("*.sql");
1729
1735
  const files = [];
1730
1736
  for await (const file of glob.scan({ cwd: migrationsDir, absolute: false })) {
@@ -1736,7 +1742,7 @@ async function runMigrate(config) {
1736
1742
  console.log(colorize("Run `bungres generate` first.", "yellow"));
1737
1743
  return;
1738
1744
  }
1739
- const applied = await sql2.unsafe(`SELECT name FROM "${MIGRATIONS_TABLE}"`);
1745
+ const applied = await sql2.unsafe(`SELECT name FROM ${qualifiedTable}`);
1740
1746
  const appliedSet = new Set(applied.map((r) => r.name));
1741
1747
  const pending = files.filter((f) => !appliedSet.has(f));
1742
1748
  if (pending.length === 0) {
@@ -1754,11 +1760,11 @@ ${content}
1754
1760
  `);
1755
1761
  }
1756
1762
  await sql2.transaction(async (txSql) => {
1757
- const statements = content.split(";").map((s) => s.trim()).filter(Boolean);
1763
+ 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
1764
  for (const stmt of statements) {
1759
1765
  await txSql.unsafe(stmt + ";");
1760
1766
  }
1761
- await txSql.unsafe(`INSERT INTO "${MIGRATIONS_TABLE}" (name) VALUES ($1)`, [file]);
1767
+ await txSql.unsafe(`INSERT INTO ${qualifiedTable} (name) VALUES ($1)`, [file]);
1762
1768
  });
1763
1769
  console.log(colorize(` \u2713 ${file}`, "green"));
1764
1770
  }
@@ -1866,7 +1872,7 @@ function generateSchemaTS(tableMap, dbSchema) {
1866
1872
  `// Generated at: ${new Date().toISOString()}`,
1867
1873
  ``,
1868
1874
  `import {`,
1869
- ` snakeCase,`,
1875
+ ` table,`,
1870
1876
  ` text, varchar, char, integer, bigint, smallint,`,
1871
1877
  ` serial, bigserial, boolean, real, doublePrecision,`,
1872
1878
  ` numeric, decimal, json, jsonb,`,
@@ -1878,7 +1884,7 @@ function generateSchemaTS(tableMap, dbSchema) {
1878
1884
  ];
1879
1885
  for (const [, table2] of tableMap) {
1880
1886
  const varName = toCamelCase(table2.tableName);
1881
- lines.push(`export const ${varName} = snakeCase.table("${table2.tableName}", {`);
1887
+ lines.push(`export const ${varName} = table("${table2.tableName}", {`);
1882
1888
  for (const col2 of table2.columns) {
1883
1889
  const colExpr = buildColumnExpression(col2);
1884
1890
  lines.push(` ${toCamelCase(col2.name)}: ${colExpr},`);
@@ -2025,15 +2031,17 @@ function toCamelCase(str) {
2025
2031
  }
2026
2032
  // src/commands/status.ts
2027
2033
  import { resolve as resolve6 } from "path";
2028
- var MIGRATIONS_TABLE2 = "__bungres_migrations";
2029
2034
  async function runStatus(config) {
2030
- const migrationsDir = resolve6(config.migrationsDir);
2035
+ const migrationsDir = resolve6(config.out);
2031
2036
  const sql2 = new Bun.SQL(config.dbUrl);
2037
+ const table2 = config.migrationsTable;
2038
+ const schema = config.migrationsSchema;
2039
+ const qualifiedTable = `"${schema}"."${table2}"`;
2032
2040
  try {
2033
2041
  const tableCheck = await sql2.unsafe(`SELECT EXISTS (
2034
2042
  SELECT 1 FROM information_schema.tables
2035
- WHERE table_name = $1
2036
- ) AS exists`, [MIGRATIONS_TABLE2]);
2043
+ WHERE table_schema = $1 AND table_name = $2
2044
+ ) AS exists`, [schema, table2]);
2037
2045
  const trackingExists = tableCheck[0]?.exists ?? false;
2038
2046
  const glob = new Bun.Glob("*.sql");
2039
2047
  const files = [];
@@ -2047,7 +2055,7 @@ async function runStatus(config) {
2047
2055
  }
2048
2056
  let appliedSet = new Set;
2049
2057
  if (trackingExists) {
2050
- const applied = await sql2.unsafe(`SELECT name FROM "${MIGRATIONS_TABLE2}" ORDER BY applied_at`);
2058
+ const applied = await sql2.unsafe(`SELECT name FROM ${qualifiedTable} ORDER BY applied_at`);
2051
2059
  appliedSet = new Set(applied.map((r) => r.name));
2052
2060
  }
2053
2061
  console.log(colorize(`
@@ -2077,14 +2085,19 @@ async function runDrop(config, opts = {}) {
2077
2085
  }
2078
2086
  const sql2 = new Bun.SQL(config.dbUrl);
2079
2087
  try {
2080
- const existingTablesResult = await sql2`
2081
- SELECT table_name
2082
- FROM information_schema.tables
2083
- WHERE table_schema = 'public' OR table_schema = current_schema()
2084
- `;
2085
- const existingTableNames = new Set(existingTablesResult.map((row) => row.table_name));
2086
- const migrationTableExists = existingTableNames.has("__bungres_migrations");
2087
- const pushTableExists = existingTableNames.has("__bungres_push");
2088
+ const userSchema = config.dbSchema;
2089
+ const existingUserTablesResult = await sql2.unsafe(`SELECT table_name FROM information_schema.tables WHERE table_schema = $1`, [userSchema]);
2090
+ const existingTableNames = new Set(existingUserTablesResult.map((r) => r.table_name));
2091
+ const migTableCheck = await sql2.unsafe(`SELECT EXISTS (
2092
+ SELECT 1 FROM information_schema.tables
2093
+ WHERE table_schema = $1 AND table_name = $2
2094
+ ) AS exists`, [config.migrationsSchema, config.migrationsTable]);
2095
+ const migrationTableExists = migTableCheck[0]?.exists ?? false;
2096
+ const pushTableCheck = await sql2.unsafe(`SELECT EXISTS (
2097
+ SELECT 1 FROM information_schema.tables
2098
+ WHERE table_schema = $1 AND table_name = $2
2099
+ ) AS exists`, [config.migrationsSchema, "__bungres_push"]);
2100
+ const pushTableExists = pushTableCheck[0]?.exists ?? false;
2088
2101
  const tablesToDrop = schemas.filter((s) => existingTableNames.has(s.config.name));
2089
2102
  if (tablesToDrop.length === 0 && !migrationTableExists && !pushTableExists) {
2090
2103
  console.log("No tables to drop (they either don't exist or were already dropped).");
@@ -2092,10 +2105,10 @@ async function runDrop(config, opts = {}) {
2092
2105
  }
2093
2106
  const tableNamesToPrint = tablesToDrop.map((s) => (s.config.schema ? s.config.schema + "." : "") + s.config.name);
2094
2107
  if (migrationTableExists) {
2095
- tableNamesToPrint.push("__bungres_migrations");
2108
+ tableNamesToPrint.push(`${config.migrationsSchema}.${config.migrationsTable}`);
2096
2109
  }
2097
2110
  if (pushTableExists) {
2098
- tableNamesToPrint.push("__bungres_push");
2111
+ tableNamesToPrint.push(`${config.migrationsSchema}.__bungres_push`);
2099
2112
  }
2100
2113
  if (!opts.force) {
2101
2114
  console.warn(colorize(`
@@ -2119,12 +2132,13 @@ Are you sure? Type YES to continue: `, "cyan"));
2119
2132
  console.log(colorize(` \u2713 dropped ${entry.config.name}`, "green"));
2120
2133
  }
2121
2134
  if (migrationTableExists) {
2122
- await sql2.unsafe("DROP TABLE IF EXISTS public.__bungres_migrations CASCADE");
2123
- console.log(colorize(` \u2713 dropped __bungres_migrations`, "green"));
2135
+ const qualifiedMigTable = `"${config.migrationsSchema}"."${config.migrationsTable}"`;
2136
+ await sql2.unsafe(`DROP TABLE IF EXISTS ${qualifiedMigTable} CASCADE`);
2137
+ console.log(colorize(` \u2713 dropped ${config.migrationsSchema}.${config.migrationsTable}`, "green"));
2124
2138
  }
2125
2139
  if (pushTableExists) {
2126
- await sql2.unsafe("DROP TABLE IF EXISTS public.__bungres_push CASCADE");
2127
- console.log(colorize(` \u2713 dropped __bungres_push`, "green"));
2140
+ await sql2.unsafe(`DROP TABLE IF EXISTS "${config.migrationsSchema}"."__bungres_push" CASCADE`);
2141
+ console.log(colorize(` \u2713 dropped ${config.migrationsSchema}.__bungres_push`, "green"));
2128
2142
  }
2129
2143
  console.log(colorize(`
2130
2144
  Drop complete.`, "green"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bungres/kit",
3
- "version": "0.4.0",
3
+ "version": "0.5.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/@bungres/kit"
32
+ "directory": "packages/bungres-kit"
33
33
  },
34
34
  "bugs": {
35
35
  "url": "https://github.com/bungres/bungres/issues"