diff --git a/.github/workflows/pull-request-check.yml b/.github/workflows/pull-request-check.yml index c5e6505..bf45c9d 100644 --- a/.github/workflows/pull-request-check.yml +++ b/.github/workflows/pull-request-check.yml @@ -26,6 +26,7 @@ jobs: - name: Run Biome run: biome ci . build: + needs: [biome-check] runs-on: ubuntu-latest steps: - name: Checkout code @@ -54,6 +55,7 @@ jobs: - name: Start run: pnpm start & test: + needs: [biome-check] runs-on: ubuntu-latest steps: - name: Checkout code @@ -75,9 +77,9 @@ jobs: run: pnpm db:generate - name: Migrate database run: pnpm db:migrate + - name: Seed database + run: pnpm db:seed - name: Build run: pnpm build - name: Test run: pnpm test - - diff --git a/db/seeding/seeding-tables.ts b/db/seeding/seeding-tables.ts new file mode 100644 index 0000000..9cf4415 --- /dev/null +++ b/db/seeding/seeding-tables.ts @@ -0,0 +1,17 @@ +import { departmentsTable } from "@/db/tables/departments"; +import { expensesTable } from "@/db/tables/expenses"; +import { fieldsOfStudyTable } from "@/db/tables/fields-of-study"; +import { teamApplicationsTable } from "@/db/tables/team-applications"; +import { teamsTable } from "@/db/tables/teams"; +import { usersTable } from "@/db/tables/users"; + +export const seedingTables = { + departmentsTable, + fieldsOfStudyTable, + teamsTable, + usersTable, + //teamUsersTable, these two tables dont work currently + //assistantUsersTable, + teamApplicationsTable, + expensesTable, +}; diff --git a/db/seeding/seeding.ts b/db/seeding/seeding.ts new file mode 100644 index 0000000..069a137 --- /dev/null +++ b/db/seeding/seeding.ts @@ -0,0 +1,49 @@ +import { + getDatabaseErrorPrivateMessage, + postgresErrorParser, +} from "@/db/errors/postgres-error"; +import { seedingTables } from "@/db/seeding/seeding-tables"; +import { database } from "@/db/setup/query-postgres"; +import { reset, seed } from "drizzle-seed"; + +const doRevertSeeding = + process.argv.length === 3 && process.argv[2] === "--reset"; +const hasUnknownOption = + process.argv.length > 3 || + (process.argv.length === 3 && process.argv[2] !== "--reset"); +if (hasUnknownOption) { + console.error("Unknown option"); + process.exit(1); +} + +if (doRevertSeeding) { + await reset(database, seedingTables); + console.info("Database seeding has been reverted"); + process.exit(0); +} + +try { + await seed(database, seedingTables); + console.info("Database has been seeded"); +} catch (error) { + const postgresErrorResult = postgresErrorParser.safeParse(error); + if (postgresErrorResult.success) { + console.error("Database error:"); + console.error(getDatabaseErrorPrivateMessage(postgresErrorResult.data)); + } else if (error instanceof Error) { + // The drizzle-seed library has awful errorhandling and just throws + // new Error() everywhere. So this is the best way to handle it + console.error(error.message); + } else { + console.error(error); + } + if (doRevertSeeding) { + console.error("Failed to reset seeded database"); + } else { + console.error("Failed to seed database"); + await reset(database, seedingTables); + } + process.exit(1); +} + +process.exit(0); diff --git a/db/setup/create-database.ts b/db/setup/create-database.ts deleted file mode 100644 index 0b708a9..0000000 --- a/db/setup/create-database.ts +++ /dev/null @@ -1,42 +0,0 @@ -import "dotenv/config"; -import { databaseConnectionParameters } from "@/db/config/parameters"; -import { - getDatabaseErrorPrivateMessage, - postgresErrorParser, -} from "@/db/errors/postgres-error"; -import pg from "pg"; // It does not work to import { Client } from "pg" - -const postgresClient = new pg.Client({ - ...databaseConnectionParameters, - database: "postgres", -}); - -try { - await postgresClient.connect(); - const databaseListResponse = await postgresClient.query( - `SELECT pg_catalog.pg_database.datname FROM pg_catalog.pg_database WHERE pg_catalog.pg_database.datname = '${databaseConnectionParameters.database}';`, - ); - - if (databaseListResponse.rowCount === 0) { - console.info( - `${databaseConnectionParameters.database} database not found, creating it`, - ); - await postgresClient.query( - `CREATE DATABASE "${databaseConnectionParameters.database}";`, - ); - console.info(`Created database ${databaseConnectionParameters.database}`); - } else { - console.info(`Database ${databaseConnectionParameters.database} exists`); - } - await postgresClient.end(); -} catch (error) { - const errorResult = postgresErrorParser.safeParse(error); - if (errorResult.success) { - console.error(getDatabaseErrorPrivateMessage(errorResult.data)); - } else { - console.error(error); - } - await postgresClient.end(); - console.error("Error when checking if database already exists."); - process.exit(1); -} diff --git a/package.json b/package.json index 9407c6c..e2bae66 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "db:generate": "drizzle-kit generate --config=db/config/drizzle.config.ts", "db:migrate": "drizzle-kit migrate --config=db/config/drizzle.config.ts", "db:studio": "drizzle-kit studio --config=db/config/drizzle.config.ts", + "db:seed": "tsx ./db/seeding/seeding.ts", "docs:generate": "tsx ./src/openapi/generateDocument.ts" }, "license": "ISC", @@ -24,6 +25,7 @@ "cors": "^2.8.5", "dotenv": "^16.4.5", "drizzle-orm": "^0.33.0", + "drizzle-seed": "^0.3.1", "drizzle-zod": "^0.5.1", "express": "^4.21.1", "pg": "^8.13.0", @@ -51,5 +53,5 @@ "typescript": "^5.6.3", "yaml": "^2.6.0" }, - "packageManager": "pnpm@10.6.3+sha512.bb45e34d50a9a76e858a95837301bfb6bd6d35aea2c5d52094fa497a467c43f5c440103ce2511e9e0a2f89c3d6071baac3358fc68ac6fb75e2ceb3d2736065e6" + "packageManager": "pnpm@10.6.4+sha512.da3d715bfd22a9a105e6e8088cfc7826699332ded60c423b14ec613a185f1602206702ff0fe4c438cb15c979081ce4cb02568e364b15174503a63c7a8e2a5f6c" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 56dfdb0..dc2d014 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,9 @@ importers: drizzle-orm: specifier: ^0.33.0 version: 0.33.0(@types/pg@8.11.11)(pg@8.13.3) + drizzle-seed: + specifier: ^0.3.1 + version: 0.3.1(drizzle-orm@0.33.0(@types/pg@8.11.11)(pg@8.13.3)) drizzle-zod: specifier: ^0.5.1 version: 0.5.1(drizzle-orm@0.33.0(@types/pg@8.11.11)(pg@8.13.3))(zod@3.24.2) @@ -914,6 +917,14 @@ packages: sqlite3: optional: true + drizzle-seed@0.3.1: + resolution: {integrity: sha512-F/0lgvfOAsqlYoHM/QAGut4xXIOXoE5VoAdv2FIl7DpGYVXlAzKuJO+IphkKUFK3Dz+rFlOsQLnMNrvoQ0cx7g==} + peerDependencies: + drizzle-orm: '>=0.36.4' + peerDependenciesMeta: + drizzle-orm: + optional: true + drizzle-zod@0.5.1: resolution: {integrity: sha512-C/8bvzUH/zSnVfwdSibOgFjLhtDtbKYmkbPbUCq46QZyZCH6kODIMSOgZ8R7rVjoI+tCj3k06MRJMDqsIeoS4A==} peerDependencies: @@ -1314,6 +1325,9 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} + pure-rand@6.1.0: + resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + qs@6.13.0: resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} engines: {node: '>=0.6'} @@ -2035,6 +2049,12 @@ snapshots: '@types/pg': 8.11.11 pg: 8.13.3 + drizzle-seed@0.3.1(drizzle-orm@0.33.0(@types/pg@8.11.11)(pg@8.13.3)): + dependencies: + pure-rand: 6.1.0 + optionalDependencies: + drizzle-orm: 0.33.0(@types/pg@8.11.11)(pg@8.13.3) + drizzle-zod@0.5.1(drizzle-orm@0.33.0(@types/pg@8.11.11)(pg@8.13.3))(zod@3.24.2): dependencies: drizzle-orm: 0.33.0(@types/pg@8.11.11)(pg@8.13.3) @@ -2495,6 +2515,8 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 + pure-rand@6.1.0: {} + qs@6.13.0: dependencies: side-channel: 1.1.0