back(db): infra migrations TypeORM + migration initiale
- data-source.ts (CLI) + scripts migration:generate/run/revert/show - migration InitialSchema : schéma complet (categories, api_entries), vérifiée en l'appliquant sur une base vierge (crée aussi l'ext uuid-ossp) - app.module: charge les migrations et migrationsRun en prod uniquement. Corrige un trou : la prod avait synchronize:false SANS migrations (schéma vide au déploiement). Dev inchangé (synchronize:true). Bascule de dev vers migrations-only (synchronize:false + baseline de la base dev existante) = étape ultérieure à faire en supervisé. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -10,7 +10,11 @@
|
||||
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\"",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"test:cov": "vitest run --coverage"
|
||||
"test:cov": "vitest run --coverage",
|
||||
"migration:generate": "typeorm-ts-node-commonjs migration:generate -d src/data-source.ts",
|
||||
"migration:run": "typeorm-ts-node-commonjs migration:run -d src/data-source.ts",
|
||||
"migration:revert": "typeorm-ts-node-commonjs migration:revert -d src/data-source.ts",
|
||||
"migration:show": "typeorm-ts-node-commonjs migration:show -d src/data-source.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@asyncapi/bundler": "^1.0.1",
|
||||
|
||||
@@ -22,7 +22,11 @@ import { validateEnv } from './config/env.validation';
|
||||
password: config.getOrThrow<string>('DATABASE_PASSWORD'),
|
||||
database: config.getOrThrow<string>('DATABASE_NAME'),
|
||||
entities: [__dirname + '/**/*.entity{.ts,.js}'],
|
||||
migrations: [__dirname + '/migrations/*{.ts,.js}'],
|
||||
// Dev : synchronize auto (itération rapide). Prod : pas de synchronize,
|
||||
// le schéma est appliqué par les migrations exécutées au démarrage.
|
||||
synchronize: config.get('NODE_ENV') !== 'production',
|
||||
migrationsRun: config.get('NODE_ENV') === 'production',
|
||||
logging: config.get('NODE_ENV') === 'development',
|
||||
}),
|
||||
}),
|
||||
|
||||
20
back/src/data-source.ts
Normal file
20
back/src/data-source.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import 'reflect-metadata';
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
/**
|
||||
* DataSource dédié à la CLI TypeORM (migrations). Lit l'environnement
|
||||
* directement (les mêmes DATABASE_* que l'app). Utilisé par les scripts
|
||||
* migration:generate / migration:run / migration:revert.
|
||||
*
|
||||
* NB : la config runtime de l'app vit dans app.module.ts (TypeOrmModule).
|
||||
*/
|
||||
export default new DataSource({
|
||||
type: 'postgres',
|
||||
host: process.env.DATABASE_HOST ?? 'localhost',
|
||||
port: Number(process.env.DATABASE_PORT ?? 5432),
|
||||
username: process.env.DATABASE_USER ?? 'datacat',
|
||||
password: process.env.DATABASE_PASSWORD ?? 'datacat',
|
||||
database: process.env.DATABASE_NAME ?? 'datacat',
|
||||
entities: ['src/**/*.entity.ts'],
|
||||
migrations: ['src/migrations/*.ts'],
|
||||
});
|
||||
16
back/src/migrations/1782543826810-InitialSchema.ts
Normal file
16
back/src/migrations/1782543826810-InitialSchema.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class InitialSchema1782543826810 implements MigrationInterface {
|
||||
name = 'InitialSchema1782543826810'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`CREATE TABLE "categories" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "name" character varying(255) NOT NULL, "description" text, "parent_id" character varying(36), "order_index" integer NOT NULL DEFAULT '0', "created_at" TIMESTAMP NOT NULL DEFAULT now(), "updated_at" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_24dbc6126a28ff948da33e97d3b" PRIMARY KEY ("id"))`);
|
||||
await queryRunner.query(`CREATE TABLE "api_entries" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "convention" character varying(30) NOT NULL DEFAULT 'CONSULTER', "name" character varying(255) NOT NULL DEFAULT '', "description" text, "type" character varying(10) NOT NULL, "provider" character varying(255) NOT NULL DEFAULT '', "version_major" integer NOT NULL DEFAULT '0', "version_minor" integer NOT NULL DEFAULT '0', "version_patch" integer NOT NULL DEFAULT '0', "yaml_content" text NOT NULL, "html_path" character varying(500), "status" character varying(10) NOT NULL DEFAULT 'PENDING', "error_message" text, "category_id" character varying(36), "is_current" boolean NOT NULL DEFAULT true, "contact_functional_name" character varying(255) NOT NULL DEFAULT '', "contact_functional_entity" character varying(255) NOT NULL DEFAULT '', "contact_functional_email" character varying(255) NOT NULL DEFAULT '', "contact_technical_name" character varying(255) NOT NULL DEFAULT '', "contact_technical_entity" character varying(255) NOT NULL DEFAULT '', "contact_technical_email" character varying(255) NOT NULL DEFAULT '', "created_at" TIMESTAMP NOT NULL DEFAULT now(), "updated_at" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_d7b668541d2539a0c212b198d32" PRIMARY KEY ("id"))`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP TABLE "api_entries"`);
|
||||
await queryRunner.query(`DROP TABLE "categories"`);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user