@zeno-lib/db 0.6.0 → 0.7.0-beta.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/dist/config.mjs CHANGED
@@ -1,4 +1,41 @@
1
1
  import { defineConfig } from "drizzle-kit";
2
+ import { existsSync, readdirSync, renameSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { styleText } from "node:util";
5
+ //#region src/move-generated-sql.ts
6
+ const GENERATED_SQL = "migration.sql";
7
+ /**
8
+ * Move each `<name>/migration.sql` to `<name>.sql`,
9
+ * because the Supabase CLI only reads `.sql` files at the top of the folder.
10
+ * Throws if a `<name>.sql` already exists.
11
+ */
12
+ function moveGeneratedSql(options) {
13
+ const { migrationsDir } = options;
14
+ const names = existsSync(migrationsDir) ? readdirSync(migrationsDir).filter((name) => existsSync(join(migrationsDir, name, GENERATED_SQL))).sort() : [];
15
+ const taken = names.map((name) => join(migrationsDir, `${name}.sql`)).filter((target) => existsSync(target));
16
+ if (taken.length > 0) throw new Error(`Cannot move the generated SQL, because these files already exist: ${taken.join(", ")}`);
17
+ return { moved: names.map((name) => {
18
+ const target = join(migrationsDir, `${name}.sql`);
19
+ renameSync(join(migrationsDir, name, GENERATED_SQL), target);
20
+ return target;
21
+ }) };
22
+ }
23
+ /** Run `moveGeneratedSql` when `drizzle-kit generate` exits. */
24
+ function moveGeneratedSqlAfterGenerate(options) {
25
+ if (process.argv[2] !== "generate") return;
26
+ process.once("exit", (code) => {
27
+ if (code !== 0) return;
28
+ try {
29
+ const check = styleText("green", "✓", { stream: process.stderr });
30
+ for (const path of moveGeneratedSql(options).moved) console.error(`${check} Moved the generated SQL to ${path}`);
31
+ } catch (error) {
32
+ const message = error instanceof Error ? error.message : String(error);
33
+ console.error(styleText("red", `✗ ${message}`, { stream: process.stderr }));
34
+ process.exitCode = 1;
35
+ }
36
+ });
37
+ }
38
+ //#endregion
2
39
  //#region src/config.ts
3
40
  /**
4
41
  * Roles a Supabase project ships that drizzle-kit's `provider: "supabase"` does
@@ -43,7 +80,7 @@ const DEFAULT_SCHEMA_FILTER = ["public"];
43
80
  function defineDrizzleConfig(overrides = {}) {
44
81
  const { entities, ...configOverrides } = overrides;
45
82
  const roleOverrides = typeof entities?.roles === "object" ? entities.roles : {};
46
- return defineConfig({
83
+ const config = defineConfig({
47
84
  dbCredentials: { url: process.env.SUPABASE_DATABASE_URL ?? "" },
48
85
  dialect: "postgresql",
49
86
  entities: {
@@ -59,6 +96,8 @@ function defineDrizzleConfig(overrides = {}) {
59
96
  schemaFilter: DEFAULT_SCHEMA_FILTER,
60
97
  ...configOverrides
61
98
  });
99
+ if (config.out) moveGeneratedSqlAfterGenerate({ migrationsDir: config.out });
100
+ return config;
62
101
  }
63
102
  //#endregion
64
103
  export { defineDrizzleConfig, supabaseManagedRoles };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeno-lib/db",
3
- "version": "0.6.0",
3
+ "version": "0.7.0-beta.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -92,7 +92,6 @@
92
92
  "stop": "pnpm exec supabase stop",
93
93
  "reset": "pnpm exec supabase db reset",
94
94
  "db:generate": "drizzle-kit generate",
95
- "db:migrate": "drizzle-kit migrate",
96
95
  "db:push": "drizzle-kit push",
97
96
  "db:studio": "drizzle-kit studio",
98
97
  "test": "vitest --run",
package/src/config.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  // https://orm.drizzle.team/docs/drizzle-config-file
2
2
  // https://orm.drizzle.team/docs/rls#migrations (entities.roles.provider: "supabase")
3
3
  import { type Config, defineConfig } from "drizzle-kit"
4
+ import { moveGeneratedSqlAfterGenerate } from "./move-generated-sql.ts"
4
5
 
5
6
  /**
6
7
  * Roles a Supabase project ships that drizzle-kit's `provider: "supabase"` does
@@ -54,7 +55,7 @@ export function defineDrizzleConfig(
54
55
  const roleOverrides =
55
56
  typeof entities?.roles === "object" ? entities.roles : {}
56
57
 
57
- return defineConfig({
58
+ const config = defineConfig({
58
59
  dbCredentials: { url: process.env.SUPABASE_DATABASE_URL ?? "" },
59
60
  dialect: "postgresql",
60
61
  // Tells drizzle-kit that Supabase's built-in roles (anon, authenticated,
@@ -74,4 +75,10 @@ export function defineDrizzleConfig(
74
75
  schemaFilter: DEFAULT_SCHEMA_FILTER,
75
76
  ...configOverrides,
76
77
  } as Config)
78
+
79
+ if (config.out) {
80
+ moveGeneratedSqlAfterGenerate({ migrationsDir: config.out })
81
+ }
82
+
83
+ return config
77
84
  }
@@ -0,0 +1,80 @@
1
+ import { existsSync, readdirSync, renameSync } from "node:fs"
2
+ import { join } from "node:path"
3
+ import { styleText } from "node:util"
4
+
5
+ export type MoveGeneratedSqlOptions = {
6
+ /** drizzle-kit writes migrations to this folder. */
7
+ migrationsDir: string
8
+ }
9
+
10
+ export type MoveGeneratedSqlResult = {
11
+ /** The new paths of the SQL files, sorted by name. */
12
+ moved: string[]
13
+ }
14
+
15
+ const GENERATED_SQL = "migration.sql"
16
+
17
+ /**
18
+ * Move each `<name>/migration.sql` to `<name>.sql`,
19
+ * because the Supabase CLI only reads `.sql` files at the top of the folder.
20
+ * Throws if a `<name>.sql` already exists.
21
+ */
22
+ export function moveGeneratedSql(
23
+ options: MoveGeneratedSqlOptions
24
+ ): MoveGeneratedSqlResult {
25
+ const { migrationsDir } = options
26
+
27
+ const names = existsSync(migrationsDir)
28
+ ? readdirSync(migrationsDir)
29
+ .filter((name) => existsSync(join(migrationsDir, name, GENERATED_SQL)))
30
+ .sort()
31
+ : []
32
+
33
+ const taken = names
34
+ .map((name) => join(migrationsDir, `${name}.sql`))
35
+ .filter((target) => existsSync(target))
36
+ if (taken.length > 0) {
37
+ throw new Error(
38
+ `Cannot move the generated SQL, because these files already exist: ${taken.join(", ")}`
39
+ )
40
+ }
41
+
42
+ const moved = names.map((name) => {
43
+ const target = join(migrationsDir, `${name}.sql`)
44
+ renameSync(join(migrationsDir, name, GENERATED_SQL), target)
45
+ return target
46
+ })
47
+
48
+ return { moved }
49
+ }
50
+
51
+ /** Run `moveGeneratedSql` when `drizzle-kit generate` exits. */
52
+ export function moveGeneratedSqlAfterGenerate(
53
+ options: MoveGeneratedSqlOptions
54
+ ): void {
55
+ // drizzle-kit loads the config for every command.
56
+ // Only `generate` writes a migration.
57
+ if (process.argv[2] !== "generate") {
58
+ return
59
+ }
60
+
61
+ process.once("exit", (code) => {
62
+ if (code !== 0) {
63
+ return
64
+ }
65
+
66
+ // Print to stderr, so the JSON from `--output json` on stdout stays valid.
67
+ try {
68
+ const check = styleText("green", "✓", { stream: process.stderr })
69
+ for (const path of moveGeneratedSql(options).moved) {
70
+ console.error(`${check} Moved the generated SQL to ${path}`)
71
+ }
72
+ } catch (error) {
73
+ const message = error instanceof Error ? error.message : String(error)
74
+ console.error(
75
+ styleText("red", `✗ ${message}`, { stream: process.stderr })
76
+ )
77
+ process.exitCode = 1
78
+ }
79
+ })
80
+ }