Add routes and fix mappers and migration scripts
This commit is contained in:
parent
58a581fbac
commit
801739ea30
11 changed files with 184 additions and 97 deletions
|
|
@ -1,44 +1,78 @@
|
|||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
/**
|
||||
* Migration to convert role column from varchar to enum
|
||||
* Converts the `role` column on the `user` table from varchar to a proper
|
||||
* PostgreSQL enum type.
|
||||
*
|
||||
* File name should be: TIMESTAMP-ConvertRoleToEnum.ts
|
||||
* Example: 1701234567890-ConvertRoleToEnum.ts
|
||||
* Existing rows are safe: the varchar values 'user' and 'admin' inserted by
|
||||
* CreateUserTable1661234567890 match the enum members exactly, so the USING
|
||||
* cast succeeds without any data transformation.
|
||||
*
|
||||
* Place in: src/migrations/
|
||||
* down() reverts cleanly by casting back to text and dropping the enum type.
|
||||
*/
|
||||
export class ConvertRoleToEnum1701234567890 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
// Create the enum type if it doesn't already exist
|
||||
await queryRunner.query(`
|
||||
DO $$ BEGIN
|
||||
CREATE TYPE user_role_enum AS ENUM ('user', 'admin');
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
`);
|
||||
DO $$ BEGIN
|
||||
CREATE TYPE user_role_enum AS ENUM ('user', 'admin');
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
`);
|
||||
|
||||
// Ensure any existing role values that differ only by whitespace or
|
||||
// casing are normalised before the cast
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "user"
|
||||
ALTER COLUMN "role" TYPE user_role_enum
|
||||
USING "role"::user_role_enum;
|
||||
`);
|
||||
UPDATE "user"
|
||||
SET "role" = LOWER(TRIM("role"))
|
||||
WHERE "role" IS NOT NULL;
|
||||
`);
|
||||
|
||||
// Drop the varchar default before retyping — PostgreSQL cannot cast it
|
||||
// automatically and will reject the ALTER COLUMN otherwise
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "user"
|
||||
ALTER COLUMN "role" SET DEFAULT 'user';
|
||||
`);
|
||||
ALTER TABLE "user"
|
||||
ALTER COLUMN "role" DROP DEFAULT;
|
||||
`);
|
||||
|
||||
// Convert the column — existing 'user' and 'admin' values cast directly
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "user"
|
||||
ALTER COLUMN "role" TYPE user_role_enum
|
||||
USING "role"::user_role_enum;
|
||||
`);
|
||||
|
||||
// Re-apply the default using the enum literal
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "user"
|
||||
ALTER COLUMN "role" SET DEFAULT 'user'::user_role_enum;
|
||||
`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
// Drop the enum default first so the column can be retyped
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "user"
|
||||
ALTER COLUMN "role" TYPE varchar
|
||||
USING "role"::text;
|
||||
`);
|
||||
ALTER TABLE "user"
|
||||
ALTER COLUMN "role" DROP DEFAULT;
|
||||
`);
|
||||
|
||||
// Cast enum values back to plain text
|
||||
await queryRunner.query(`
|
||||
DROP TYPE IF EXISTS user_role_enum;
|
||||
`);
|
||||
ALTER TABLE "user"
|
||||
ALTER COLUMN "role" TYPE varchar
|
||||
USING "role"::text;
|
||||
`);
|
||||
|
||||
// Restore the original varchar default
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "user"
|
||||
ALTER COLUMN "role" SET DEFAULT 'user';
|
||||
`);
|
||||
|
||||
// Drop the enum type — only safe once no column references it
|
||||
await queryRunner.query(`
|
||||
DROP TYPE IF EXISTS user_role_enum;
|
||||
`);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import {MigrationInterface, QueryRunner, Table} from "typeorm";
|
||||
import {MigrationInterface, QueryRunner, Table, TableUnique} from "typeorm";
|
||||
|
||||
/**
|
||||
* Creates the `tag` table.
|
||||
|
|
@ -15,6 +15,7 @@ export class CreateTagTable1771658108802 implements MigrationInterface {
|
|||
type: "uuid",
|
||||
isPrimary: true,
|
||||
generationStrategy: "uuid",
|
||||
isGenerated: true,
|
||||
default: "uuid_generate_v4()",
|
||||
},
|
||||
{
|
||||
|
|
@ -38,9 +39,20 @@ export class CreateTagTable1771658108802 implements MigrationInterface {
|
|||
}),
|
||||
true // ifNotExists
|
||||
);
|
||||
|
||||
// Add a unique constraint on desciption
|
||||
await queryRunner.createUniqueConstraint(
|
||||
"tag",
|
||||
new TableUnique({
|
||||
columnNames: ["description"],
|
||||
name: "UQ_tag_description",
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
// Drop the unique constraint first
|
||||
await queryRunner.dropUniqueConstraint("tag", "UQ_tag_description");
|
||||
await queryRunner.dropTable("tag", true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue