Skip to content

Commit 53b3132

Browse files
authored
ENG-822 Reactivate automated generation of dbTypes (#453)
* Create a migrate script that does migrations, and optionally genotypes * Create a setup tasks that includes genenv and migrations (and hence genTypes). Use in dev and build. * separate lint of schema and functions, allow lint:fix for all subtasks. * documentation: task dependencies
1 parent c54a276 commit 53b3132

9 files changed

Lines changed: 303 additions & 84 deletions

File tree

packages/database/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ We follow the Supabase [Declarative Database Schema](https://supabase.com/docs/g
4343
3. See if there would be a migration to apply with `supabase db diff`
4444
5. If applying the new schema fails, repeat step 4
4545
6. If you are satisfied with the migration, create a migration file with `npm run dbdiff:save some_meaningful_migration_name`
46-
1. If all goes well, there should be a new file named `supabase/migration/2..._some_meaningful_migration_name.sql` which you should `git add`.
47-
7. `turbo build`, which will do the following:
46+
1. If all goes well, there should be a new file named `supabase/migrations/2..._some_meaningful_migration_name.sql` which you should `git add`.
47+
7. `npm run migrate`, which will do the following:
4848
1. Start Supabase
4949
2. Apply the new migration locally
5050
3. Regenerate the types file with `supabase gen types typescript --local > src/dbTypes.ts`
51-
4. Copy it where appropriate
51+
4. Note that you can reapply an idempotent migration with `npm run migrate -- --reapply <migration timestamp>`. This will tell supabase to reapply the migration as if it were new; it may fail if your migration is not idempotent. It allows you to iterate on a migration. If your migration is not idempotent, you should revert changes in the supabase studio before reapplying.
5252
8. You can start using your changes again `turbo dev`
5353
9. When your migration is pushed in a branch, Supabase will create a branch instance. Note there is a small cost to this, so we do not want those branches to linger.
5454
The branch will be also created without data. (Seed data could be added to `.../supabase/seed.sql`)
@@ -65,7 +65,7 @@ If schema changes are deployed to `main` by another developer while you work on
6565
2. If your migration is not idempotent (which you'll notice in stage 4), you may have to revert some of your migration's changes in the local database, using the SQL editor in the studio, or `psql`.
6666
3. If all else fails, you can reset your local database with `supabase db reset --local`
6767
3. If you have an ongoing migration file, the timestamp at the start of the name should come after the latest new migration. Rename (or `git mv`) as needed.
68-
4. Apply `turbo build` again, so the incoming migrations are applied, and then your working migration. You may have to fix the schema and migration to take the changes into account.
68+
4. Out-of-order incoming migrations may be applied with `npm run migrate -- --include-all`. You may have to fix the schema and reapply your own migration to take the changes into account.
6969

7070
### Testing the backend
7171

packages/database/doc/tasks.dot

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
DiGraph G {
2+
3+
/* package-level tasks */
4+
5+
node [color=orange]
6+
7+
dev
8+
setup
9+
serve
10+
stop
11+
check_types
12+
check_schema
13+
lint
14+
build
15+
test
16+
genenv
17+
dbdiff
18+
dbdiff_save
19+
deploy
20+
deploy_functions
21+
migrate
22+
gentypes
23+
24+
/* supabase functions */
25+
node [color=purple]
26+
27+
sup_db_diff_save
28+
sup_db_diff
29+
sup_functions
30+
sup_start
31+
sup_stop
32+
migrations_up
33+
generate_schema
34+
35+
36+
37+
/* scripts */
38+
node [color=blue; shape=rectangle]
39+
40+
s_createEnv
41+
s_genTypes
42+
s_migrate
43+
s_lint_schemas
44+
s_lint_functions
45+
s_deploy
46+
s_serve
47+
48+
/* Other scripts */
49+
node [color=black]
50+
sqruff
51+
deno_lint
52+
tsc
53+
cucumber_js
54+
55+
/* links */
56+
57+
migrate -> s_migrate -> gentypes -> s_genTypes
58+
s_migrate -> migrations_up
59+
dev -> setup
60+
dev -> serve
61+
setup -> genenv
62+
setup -> migrate
63+
serve -> s_serve
64+
s_serve -> sup_start
65+
s_serve -> sup_functions
66+
s_createEnv -> sup_start
67+
stop -> sup_stop
68+
check_types -> tsc
69+
check_schema -> s_lint_schemas
70+
check_schema -> dbdiff
71+
lint -> eslint
72+
lint -> s_lint_functions -> deno_lint
73+
lint -> s_lint_schemas -> sqruff
74+
test -> build
75+
test -> cucumber_js
76+
genenv -> s_createEnv
77+
dbdiff -> sup_stop
78+
dbdiff -> sup_db_diff
79+
dbdiff_save -> sup_db_diff_save
80+
deploy -> s_deploy
81+
deploy_functions -> s_deploy
82+
build -> setup
83+
build -> tsc
84+
s_genTypes -> generate_schema
85+
s_migrate -> sup_start
86+
}

packages/database/package.json

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,23 @@
2222
},
2323
"scripts": {
2424
"init": "supabase login",
25-
"dev": "tsx scripts/dev.ts",
26-
"serve": "supabase start && tsx scripts/createEnv.mts && supabase functions serve",
25+
"setup": "npm run genenv && npm run migrate",
26+
"dev": "npm run setup && npm run serve",
27+
"build": "npm run setup && tsc",
28+
"serve": "tsx scripts/serve.ts",
2729
"stop": "supabase stop",
2830
"check-types": "tsc --noEmit --skipLibCheck",
29-
"check-schema": "tsx scripts/lint.ts && supabase stop && npm run dbdiff",
30-
"lint": "eslint . && tsx scripts/lint.ts",
31-
"lint:fix": "tsx scripts/lint.ts -f",
32-
"build": "tsx scripts/createEnv.mts && tsc",
33-
"build-schema": "tsx scripts/build.ts && tsx scripts/createEnv.mts -- local",
34-
"test": "tsc && cucumber-js",
31+
"check-schema": "tsx scripts/lintSchemas.ts && supabase stop && npm run dbdiff",
32+
"lint": "eslint . && tsx scripts/lintSchemas.ts && tsx scripts/lintFunctions.ts",
33+
"lint:fix": "eslint --fix . && tsx scripts/lintSchemas.ts -f && tsx scripts/lintFunctions.ts",
34+
"migrate": "tsx scripts/migrate.ts",
35+
"test": "npm run build && cucumber-js",
3536
"genenv": "tsx scripts/createEnv.mts",
36-
"gentypes:production": "supabase start && supabase gen types typescript --project-id \"$SUPABASE_PROJECT_ID\" --schema public > src/dbTypes.ts",
37+
"gentypes": "tsx scripts/genTypes.ts",
3738
"dbdiff": "supabase stop && supabase db diff",
3839
"dbdiff:save": "supabase stop && supabase db diff -f",
3940
"deploy": "tsx scripts/deploy.ts",
40-
"deploy:functions": "tsx scripts/lint.ts -f"
41+
"deploy:functions": "tsx scripts/deploy.ts -f"
4142
},
4243
"dependencies": {
4344
"@repo/utils": "*",
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ if (process.env.HOME !== "/vercel") {
1313
process.exit(0);
1414
}
1515
execSync("supabase start", { cwd: projectRoot, stdio: "inherit" });
16-
execSync("supabase migrations up", { cwd: projectRoot, stdio: "inherit" });
1716
const stdout = execSync(
1817
"supabase gen types typescript --local --schema public",
1918
{ encoding: "utf8", cwd: projectRoot },

packages/database/scripts/lint.ts

Lines changed: 0 additions & 68 deletions
This file was deleted.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { exec, spawnSync } from "node:child_process";
2+
import { readdir, Dirent } from "node:fs";
3+
import { join, dirname } from "path";
4+
5+
const __dirname = dirname(__filename);
6+
const projectRoot = join(__dirname, "..");
7+
8+
const main = () => {
9+
try {
10+
let denoError = false;
11+
exec("which deno", (err) => {
12+
if (err) {
13+
console.error("Could not find deno, you may want to install it.");
14+
// Do not fail yet
15+
} else {
16+
const fnDir = join(projectRoot, "supabase", "functions");
17+
const fix = process.argv.length == 3 && process.argv[2] == "-f";
18+
readdir(fnDir, { withFileTypes: true }, (err, files: Dirent[]) => {
19+
if (err) {
20+
console.error("error:", err);
21+
return;
22+
}
23+
const dirs = files.filter((f) => f.isDirectory()).map((d) => d.name);
24+
for (const dir of dirs) {
25+
const args = ["lint"];
26+
if (fix) args.push("--fix");
27+
args.push("index.ts");
28+
const res = spawnSync("deno", args, { cwd: join(fnDir, dir) });
29+
const cleanedStderr = (res.stderr?.toString() ?? "")
30+
.replace("Checked 1 file", "")
31+
.trim();
32+
const out = (res.stdout?.toString() ?? "") + cleanedStderr;
33+
if (res.status !== 0 || cleanedStderr.length > 0) {
34+
console.error(`deno errors for ${dir}:\n${out}`);
35+
denoError = true;
36+
} else {
37+
console.log(`deno checked types of ${dir}`);
38+
}
39+
}
40+
if (denoError) process.exit(1);
41+
});
42+
}
43+
});
44+
// exit handled after linting completes
45+
} catch (error) {
46+
console.error("error:", error);
47+
process.exit(1);
48+
}
49+
};
50+
if (__filename === process.argv[1]) main();
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { exec } from "node:child_process";
2+
3+
const main = () => {
4+
try {
5+
exec("sqruff --version", (err) => {
6+
if (err) {
7+
console.error("Could not find sqruff, you may want to install it.");
8+
// Do not fail yet
9+
} else {
10+
const command =
11+
process.argv.length == 3 && process.argv[2] == "-f" ? "fix" : "lint";
12+
exec(
13+
`sqruff ${command} supabase/schemas`,
14+
{},
15+
(err, stdout, stderr) => {
16+
console.log(`${stdout}`);
17+
if (stderr) console.log(`${stderr}`);
18+
process.exit(err ? err.code : 0);
19+
},
20+
);
21+
}
22+
});
23+
} catch (error) {
24+
console.error("error:", error);
25+
process.exit(1);
26+
}
27+
};
28+
if (__filename === process.argv[1]) main();

0 commit comments

Comments
 (0)