From 5d069b43025002de2277da6d92cab772b4f0e475 Mon Sep 17 00:00:00 2001 From: Nikolay Gagarinov Date: Thu, 6 Jun 2024 22:14:27 +0500 Subject: [PATCH 1/5] improve migrations --- backend/Makefile | 10 +- backend/src/config/data-source.config.ts | 43 ++---- .../src/migrations/1663236009774-migration.ts | 111 ---------------- .../src/migrations/1670352324202-migration.ts | 16 --- .../migrations/1673189643179-migrations.ts | 44 ------- .../migrations/1673189675326-migrations.ts | 44 ------- .../1677580680097-AdduserRecoverHash.ts | 14 -- .../1682678760453-fill-null-slugs-snippets.ts | 28 ---- .../1691073864288-RenameLoginToUsername.ts | 16 --- .../migrations/1699462100238-migrations.ts | 124 ++++++++++++++++-- 10 files changed, 133 insertions(+), 317 deletions(-) delete mode 100644 backend/src/migrations/1663236009774-migration.ts delete mode 100644 backend/src/migrations/1670352324202-migration.ts delete mode 100644 backend/src/migrations/1673189643179-migrations.ts delete mode 100644 backend/src/migrations/1673189675326-migrations.ts delete mode 100644 backend/src/migrations/1677580680097-AdduserRecoverHash.ts delete mode 100644 backend/src/migrations/1682678760453-fill-null-slugs-snippets.ts delete mode 100644 backend/src/migrations/1691073864288-RenameLoginToUsername.ts diff --git a/backend/Makefile b/backend/Makefile index 2fb2cc77..ce5f8a60 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -4,10 +4,16 @@ install: npm install db-migrate: - npm run typeorm -- migration:run -d src/data-source + npm run typeorm -- migration:run -d src/data-source.ts db-generate: - npm run typeorm -- migration:generate src/migrations/migrations -d src/data-source + npm run typeorm -- migration:generate src/migrations -d src/data-source + +db-create-migration: + npm run typeorm migration:create src/migrations/$(NAME) + +db-drop: + npm run typeorm -- schema:drop start: npm run start diff --git a/backend/src/config/data-source.config.ts b/backend/src/config/data-source.config.ts index 937d92a8..569d544d 100644 --- a/backend/src/config/data-source.config.ts +++ b/backend/src/config/data-source.config.ts @@ -1,17 +1,14 @@ import { DataSourceOptions } from 'typeorm'; -import { Users } from '../entities/user.entity'; -import { Snippets } from '../entities/snippet.entity'; -import { migration1663236009774 } from '../migrations/1663236009774-migration'; -import { migration1670352324202 } from '../migrations/1670352324202-migration'; -import { AdduserRecoverHash1677580680097 } from '../migrations/1677580680097-AdduserRecoverHash'; -import { FillNullSlugsSnippets1682678760453 } from '../migrations/1682678760453-fill-null-slugs-snippets'; -import { RenameLoginToUsername1691073864288 } from '../migrations/1691073864288-RenameLoginToUsername'; -import { Migrations1699462100238 } from '../migrations/1699462100238-migrations'; - export default (): DataSourceOptions => { + const defaultConfig = { + entities: [ __dirname + `/../entities/**/*{.ts,.js}`], + migrations: [ __dirname + `/../migrations/**/*{.ts,.js}`], + + }; switch (process.env.NODE_ENV) { case 'production': return { + ...defaultConfig, type: 'postgres', username: process.env.DATABASE_USERNAME, password: process.env.DATABASE_PASSWORD, @@ -19,43 +16,21 @@ export default (): DataSourceOptions => { url: process.env.DATABASE_URL, synchronize: false, ssl: { rejectUnauthorized: false }, - entities: [Users, Snippets], - migrations: [ - migration1663236009774, - migration1670352324202, - AdduserRecoverHash1677580680097, - FillNullSlugsSnippets1682678760453, - RenameLoginToUsername1691073864288, - Migrations1699462100238, - ], }; case 'test': return { + ...defaultConfig, type: 'sqlite', database: ':memory:', synchronize: true, - entities: [Users, Snippets], - migrations: [ - migration1663236009774, - migration1670352324202, - AdduserRecoverHash1677580680097, - RenameLoginToUsername1691073864288, - Migrations1699462100238, - ], + }; default: return { + ...defaultConfig, type: 'sqlite', database: 'runit.sqlite', synchronize: false, - entities: [Users, Snippets], - migrations: [ - migration1663236009774, - migration1670352324202, - AdduserRecoverHash1677580680097, - RenameLoginToUsername1691073864288, - Migrations1699462100238, - ], }; } }; diff --git a/backend/src/migrations/1663236009774-migration.ts b/backend/src/migrations/1663236009774-migration.ts deleted file mode 100644 index fba897c9..00000000 --- a/backend/src/migrations/1663236009774-migration.ts +++ /dev/null @@ -1,111 +0,0 @@ -/* eslint-disable class-methods-use-this */ -import { MigrationInterface, QueryRunner, Table } from 'typeorm'; - -export class migration1663236009774 implements MigrationInterface { - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.createTable( - new Table({ - name: 'users', - columns: [ - { - name: 'id', - type: 'integer', - isGenerated: true, - generatedIdentity: 'ALWAYS', - generationStrategy: 'increment', - isNullable: false, - isPrimary: true, - }, - { - name: 'login', - type: 'varchar(20)', - isNullable: false, - isUnique: true, - }, - { - name: 'email', - type: 'varchar(60)', - isNullable: false, - isUnique: true, - }, - { - name: 'password', - type: 'varchar(60)', - isNullable: false, - }, - { - name: 'created_at', - type: 'timestamp', - isNullable: false, - default: 'CURRENT_TIMESTAMP', - }, - { - name: 'updated_at', - type: 'timestamp', - isNullable: false, - default: 'CURRENT_TIMESTAMP', - }, - ], - }), - ); - - await queryRunner.createTable( - new Table({ - name: 'snippets', - columns: [ - { - name: 'id', - type: 'integer', - isGenerated: true, - generatedIdentity: 'ALWAYS', - generationStrategy: 'increment', - isNullable: false, - isPrimary: true, - }, - { - name: 'name', - type: 'varchar(30)', - isNullable: false, - default: "'Untitled'", - }, - { - name: 'code', - type: 'text', - isNullable: false, - }, - { - name: 'created_at', - type: 'timestamp', - isNullable: false, - default: 'CURRENT_TIMESTAMP', - }, - { - name: 'updated_at', - type: 'timestamp', - isNullable: false, - default: 'CURRENT_TIMESTAMP', - }, - { - name: 'userId', - type: 'int', - }, - ], - foreignKeys: [ - { - name: 'userId', - columnNames: ['userId'], - referencedTableName: 'users', - referencedColumnNames: ['id'], - onUpdate: 'cascade', - onDelete: 'cascade', - }, - ], - }), - ); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.dropTable('users'); - await queryRunner.dropTable('snippets'); - } -} diff --git a/backend/src/migrations/1670352324202-migration.ts b/backend/src/migrations/1670352324202-migration.ts deleted file mode 100644 index 8df2764f..00000000 --- a/backend/src/migrations/1670352324202-migration.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* eslint-disable class-methods-use-this */ -import { MigrationInterface, QueryRunner } from 'typeorm'; - -export class migration1670352324202 implements MigrationInterface { - name = 'migration1670352324202'; - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `ALTER TABLE "snippets" ADD COLUMN "slug" varchar(30)`, - ); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`ALTER TABLE "snippets" DELETE COLUMN "slug"`); - } -} diff --git a/backend/src/migrations/1673189643179-migrations.ts b/backend/src/migrations/1673189643179-migrations.ts deleted file mode 100644 index 2d8fa762..00000000 --- a/backend/src/migrations/1673189643179-migrations.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* eslint class-methods-use-this: ["error", { "exceptMethods": ["up", "down"] }] */ -import { MigrationInterface, QueryRunner } from 'typeorm'; - -export class migrations1673189643179 implements MigrationInterface { - name = 'migrations1673189643179'; - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `CREATE TABLE "users" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "login" varchar NOT NULL, "email" varchar NOT NULL, "password" varchar NOT NULL, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), CONSTRAINT "UQ_2d443082eccd5198f95f2a36e2c" UNIQUE ("login"))`, - ); - await queryRunner.query( - `CREATE UNIQUE INDEX "IDX_97672ac88f789774dd47f7c8be" ON "users" ("email") `, - ); - await queryRunner.query( - `CREATE TABLE "snippets" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL DEFAULT ('Untitled'), "code" varchar NOT NULL, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "userId" integer)`, - ); - await queryRunner.query( - `CREATE TABLE "temporary_snippets" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL DEFAULT ('Untitled'), "code" varchar NOT NULL, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "userId" integer, CONSTRAINT "FK_8fdfc80b4a5bf0ac48946a2ca1f" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)`, - ); - await queryRunner.query( - `INSERT INTO "temporary_snippets"("id", "name", "code", "created_at", "updated_at", "userId") SELECT "id", "name", "code", "created_at", "updated_at", "userId" FROM "snippets"`, - ); - await queryRunner.query(`DROP TABLE "snippets"`); - await queryRunner.query( - `ALTER TABLE "temporary_snippets" RENAME TO "snippets"`, - ); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `ALTER TABLE "snippets" RENAME TO "temporary_snippets"`, - ); - await queryRunner.query( - `CREATE TABLE "snippets" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL DEFAULT ('Untitled'), "code" varchar NOT NULL, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "userId" integer)`, - ); - await queryRunner.query( - `INSERT INTO "snippets"("id", "name", "code", "created_at", "updated_at", "userId") SELECT "id", "name", "code", "created_at", "updated_at", "userId" FROM "temporary_snippets"`, - ); - await queryRunner.query(`DROP TABLE "temporary_snippets"`); - await queryRunner.query(`DROP TABLE "snippets"`); - await queryRunner.query(`DROP INDEX "IDX_97672ac88f789774dd47f7c8be"`); - await queryRunner.query(`DROP TABLE "users"`); - } -} diff --git a/backend/src/migrations/1673189675326-migrations.ts b/backend/src/migrations/1673189675326-migrations.ts deleted file mode 100644 index bb5488e9..00000000 --- a/backend/src/migrations/1673189675326-migrations.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* eslint class-methods-use-this: ["error", { "exceptMethods": ["up", "down"] }] */ -import { MigrationInterface, QueryRunner } from 'typeorm'; - -export class migrations1673189675326 implements MigrationInterface { - name = 'migrations1673189675326'; - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `CREATE TABLE "users" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "login" varchar NOT NULL, "email" varchar NOT NULL, "password" varchar NOT NULL, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), CONSTRAINT "UQ_2d443082eccd5198f95f2a36e2c" UNIQUE ("login"))`, - ); - await queryRunner.query( - `CREATE UNIQUE INDEX "IDX_97672ac88f789774dd47f7c8be" ON "users" ("email") `, - ); - await queryRunner.query( - `CREATE TABLE "snippets" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL DEFAULT ('Untitled'), "code" varchar NOT NULL, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "userId" integer)`, - ); - await queryRunner.query( - `CREATE TABLE "temporary_snippets" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL DEFAULT ('Untitled'), "code" varchar NOT NULL, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "userId" integer, CONSTRAINT "FK_8fdfc80b4a5bf0ac48946a2ca1f" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)`, - ); - await queryRunner.query( - `INSERT INTO "temporary_snippets"("id", "name", "code", "created_at", "updated_at", "userId") SELECT "id", "name", "code", "created_at", "updated_at", "userId" FROM "snippets"`, - ); - await queryRunner.query(`DROP TABLE "snippets"`); - await queryRunner.query( - `ALTER TABLE "temporary_snippets" RENAME TO "snippets"`, - ); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `ALTER TABLE "snippets" RENAME TO "temporary_snippets"`, - ); - await queryRunner.query( - `CREATE TABLE "snippets" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL DEFAULT ('Untitled'), "code" varchar NOT NULL, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "userId" integer)`, - ); - await queryRunner.query( - `INSERT INTO "snippets"("id", "name", "code", "created_at", "updated_at", "userId") SELECT "id", "name", "code", "created_at", "updated_at", "userId" FROM "temporary_snippets"`, - ); - await queryRunner.query(`DROP TABLE "temporary_snippets"`); - await queryRunner.query(`DROP TABLE "snippets"`); - await queryRunner.query(`DROP INDEX "IDX_97672ac88f789774dd47f7c8be"`); - await queryRunner.query(`DROP TABLE "users"`); - } -} diff --git a/backend/src/migrations/1677580680097-AdduserRecoverHash.ts b/backend/src/migrations/1677580680097-AdduserRecoverHash.ts deleted file mode 100644 index 90808689..00000000 --- a/backend/src/migrations/1677580680097-AdduserRecoverHash.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* eslint class-methods-use-this: ["error", { "exceptMethods": ["up", "down"] }] */ -import { MigrationInterface, QueryRunner } from 'typeorm'; - -export class AdduserRecoverHash1677580680097 implements MigrationInterface { - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `ALTER TABLE "users" ADD COLUMN "recover_hash" varchar(50) DEFAULT NULL`, - ); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`ALTER TABLE "users" DROP COLUMN recover_hash`); - } -} diff --git a/backend/src/migrations/1682678760453-fill-null-slugs-snippets.ts b/backend/src/migrations/1682678760453-fill-null-slugs-snippets.ts deleted file mode 100644 index 18f3bddb..00000000 --- a/backend/src/migrations/1682678760453-fill-null-slugs-snippets.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* eslint-disable no-console */ -/* eslint class-methods-use-this: ["error", { "exceptMethods": ["up", "down"] }] */ -import { MigrationInterface, QueryRunner } from 'typeorm'; -import { generateUniqSlug } from '../snippets/utils/generate-uniq-slug'; -import { Snippets } from '../entities/snippet.entity'; - -export class FillNullSlugsSnippets1682678760453 implements MigrationInterface { - public async up(queryRunner: QueryRunner): Promise { - const snippets: Snippets[] = await queryRunner.query( - `SELECT id, slug FROM snippets;`, - ); - const nullSnippets = snippets.filter((snippet) => !snippet.slug); - - nullSnippets.forEach(async (nullSnippet) => { - const slug = generateUniqSlug(snippets); - - await queryRunner.query( - `UPDATE snippets SET slug='${slug}' WHERE id=${nullSnippet.id};`, - ); - }); - } - - public async down(): Promise { - console.log( - `Revert migrations for filling null slugs in snippets is not specified!`, - ); - } -} diff --git a/backend/src/migrations/1691073864288-RenameLoginToUsername.ts b/backend/src/migrations/1691073864288-RenameLoginToUsername.ts deleted file mode 100644 index fd37962e..00000000 --- a/backend/src/migrations/1691073864288-RenameLoginToUsername.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* eslint class-methods-use-this: ["error", { "exceptMethods": ["up", "down"] }] */ -import { MigrationInterface, QueryRunner } from 'typeorm'; - -export class RenameLoginToUsername1691073864288 implements MigrationInterface { - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `ALTER TABLE "users" RENAME COLUMN "login" TO "username"`, - ); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `ALTER TABLE "users" RENAME COLUMN "username" TO "login"`, - ); - } -} diff --git a/backend/src/migrations/1699462100238-migrations.ts b/backend/src/migrations/1699462100238-migrations.ts index 9ae9d846..35a46260 100644 --- a/backend/src/migrations/1699462100238-migrations.ts +++ b/backend/src/migrations/1699462100238-migrations.ts @@ -1,14 +1,122 @@ /* eslint class-methods-use-this: ["error", { "exceptMethods": ["up", "down"] }] */ -import { MigrationInterface, QueryRunner } from 'typeorm'; +import { MigrationInterface, QueryRunner, Table } from 'typeorm'; export class Migrations1699462100238 implements MigrationInterface { - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `ALTER TABLE "snippets" ADD COLUMN "language" varchar(50) DEFAULT NULL`, + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.createTable( + new Table({ + name: 'users', + columns: [ + { + name: 'id', + type: 'integer', + isGenerated: true, + generatedIdentity: 'ALWAYS', + generationStrategy: 'increment', + isNullable: false, + isPrimary: true, + }, + { + name: 'username', + type: 'varchar', + isNullable: false, + isUnique: true, + }, + { + name: 'email', + type: 'varchar', + isNullable: false, + isUnique: true, + }, + { + name: 'password', + type: 'varchar', + isNullable: false, + }, + { + name: 'recover_hash', + type: 'varchar(50)', + }, + { + name: 'created_at', + type: 'timestamp', + isNullable: false, + default: 'CURRENT_TIMESTAMP', + }, + { + name: 'updated_at', + type: 'timestamp', + isNullable: false, + default: 'CURRENT_TIMESTAMP', + }, + ], + }), ); - } - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`ALTER TABLE "snippets" DROP COLUMN language`); - } + await queryRunner.createTable( + new Table({ + name: 'snippets', + columns: [ + { + name: 'id', + type: 'integer', + isGenerated: true, + generatedIdentity: 'ALWAYS', + generationStrategy: 'increment', + isNullable: false, + isPrimary: true, + }, + { + name: 'name', + type: 'text', + isNullable: false, + }, + { + name: 'slug', + type: 'text', + isNullable: false, + }, + { + name: 'code', + type: 'text', + isNullable: false, + }, + { + name: 'languages', + type: 'text', + isNullable: false, + }, + { + name: 'created_at', + type: 'timestamp', + isNullable: false, + default: 'CURRENT_TIMESTAMP', + }, + { + name: 'updated_at', + type: 'timestamp', + isNullable: false, + default: 'CURRENT_TIMESTAMP', + }, + { + name: 'userId', + type: 'int', + }, + ], + foreignKeys: [ + { + name: 'userId', + columnNames: ['userId'], + referencedTableName: 'users', + referencedColumnNames: ['id'], + }, + ], + }), + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE "users"`); + await queryRunner.query(`DROP TABLE "snippets"`); + } } From 7d1ab844824f27670e3eb117fcbc73eb7c1ac78a Mon Sep 17 00:00:00 2001 From: Nikolay Gagarinov Date: Thu, 6 Jun 2024 23:31:10 +0500 Subject: [PATCH 2/5] fix migrations --- backend/Makefile | 7 +++++- .../migrations/1699462100238-migrations.ts | 23 ++++++++++--------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/backend/Makefile b/backend/Makefile index ce5f8a60..039ff938 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -9,11 +9,16 @@ db-migrate: db-generate: npm run typeorm -- migration:generate src/migrations -d src/data-source +db-revert: + npm run typeorm -- migration:revert -d src/data-source.ts + +db-refresh: db-revert db-migrate + db-create-migration: npm run typeorm migration:create src/migrations/$(NAME) db-drop: - npm run typeorm -- schema:drop + npm run typeorm -- schema:drop -d src/data-source.ts start: npm run start diff --git a/backend/src/migrations/1699462100238-migrations.ts b/backend/src/migrations/1699462100238-migrations.ts index 35a46260..3bba5afc 100644 --- a/backend/src/migrations/1699462100238-migrations.ts +++ b/backend/src/migrations/1699462100238-migrations.ts @@ -18,24 +18,25 @@ export class Migrations1699462100238 implements MigrationInterface { }, { name: 'username', - type: 'varchar', + type: 'varchar(20)', isNullable: false, isUnique: true, }, { name: 'email', - type: 'varchar', + type: 'varchar(60)', isNullable: false, isUnique: true, }, { name: 'password', - type: 'varchar', + type: 'varchar(60)', isNullable: false, }, { name: 'recover_hash', type: 'varchar(50)', + isNullable: true, }, { name: 'created_at', @@ -68,13 +69,13 @@ export class Migrations1699462100238 implements MigrationInterface { }, { name: 'name', - type: 'text', + type: 'varchar(30)', isNullable: false, }, { name: 'slug', - type: 'text', - isNullable: false, + type: 'varchar(30)', + isNullable: true, }, { name: 'code', @@ -82,9 +83,9 @@ export class Migrations1699462100238 implements MigrationInterface { isNullable: false, }, { - name: 'languages', - type: 'text', - isNullable: false, + name: 'language', + type: 'varchar(50)', + isNullable: true, }, { name: 'created_at', @@ -116,7 +117,7 @@ export class Migrations1699462100238 implements MigrationInterface { } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DROP TABLE "users"`); - await queryRunner.query(`DROP TABLE "snippets"`); + await queryRunner.query(`DROP TABLE "snippets"`); + await queryRunner.query(`DROP TABLE "users"`); } } From d3ff9c6621f1995ca487f0cc0346602b6db6833a Mon Sep 17 00:00:00 2001 From: Nikolay Gagarinov Date: Thu, 6 Jun 2024 23:45:20 +0500 Subject: [PATCH 3/5] refactor entities --- backend/__tests__/auth.e2e-spec.ts | 8 ++--- backend/__tests__/snippets.e2e-spec.ts | 14 ++++---- backend/__tests__/users.e2e-spec.ts | 14 ++++---- backend/src/entities/snippet.entity.ts | 10 +++--- backend/src/entities/user.entity.ts | 10 +++--- ...pets.interface.ts => snippet.interface.ts} | 2 +- backend/src/snippets/snippets.controller.ts | 12 +++---- backend/src/snippets/snippets.module.ts | 6 ++-- backend/src/snippets/snippets.service.ts | 28 ++++++++-------- backend/src/snippets/snippets.subscriber.ts | 8 ++--- .../src/snippets/utils/generate-uniq-slug.ts | 4 +-- .../src/users/interfaces/users.interface.ts | 2 +- backend/src/users/users.controller.ts | 10 +++--- backend/src/users/users.module.ts | 6 ++-- backend/src/users/users.service.ts | 32 +++++++++---------- backend/src/users/users.subscriber.ts | 8 ++--- .../src/users/validation/validation.module.ts | 4 +-- 17 files changed, 89 insertions(+), 89 deletions(-) rename backend/src/snippets/interfaces/{snippets.interface.ts => snippet.interface.ts} (64%) diff --git a/backend/__tests__/auth.e2e-spec.ts b/backend/__tests__/auth.e2e-spec.ts index 45355e63..0b47c98b 100644 --- a/backend/__tests__/auth.e2e-spec.ts +++ b/backend/__tests__/auth.e2e-spec.ts @@ -7,7 +7,7 @@ import { Repository } from 'typeorm'; import { ValidationPipe } from '@nestjs/common'; import * as cookieParser from 'cookie-parser'; import { JwtService } from '@nestjs/jwt'; -import { Users } from '../src/entities/user.entity'; +import { User } from '../src/entities/user.entity'; import { AuthModule } from '../src/auth/auth.module'; import getDataSourceConfig from '../src/config/data-source.config'; import { AppModule } from '../src/app.module'; @@ -15,11 +15,11 @@ import { UsersModule } from '../src/users/users.module'; describe('AuthController (e2e)', () => { let app: NestExpressApplication; - let usersRepo: Repository; + let usersRepo: Repository; let testData: Record; let users: Array>; let moduleFixture: TestingModule; - let usersData: Users[]; + let usersData: User[]; let jwtService: JwtService; // FIXME: все тесты проходят если beforeEach @@ -32,7 +32,7 @@ describe('AuthController (e2e)', () => { UsersModule, AuthModule, TypeOrmModule.forRoot(getDataSourceConfig()), - TypeOrmModule.forFeature([Users]), + TypeOrmModule.forFeature([User]), ], }).compile(); diff --git a/backend/__tests__/snippets.e2e-spec.ts b/backend/__tests__/snippets.e2e-spec.ts index fd4d3476..dd24ecc5 100644 --- a/backend/__tests__/snippets.e2e-spec.ts +++ b/backend/__tests__/snippets.e2e-spec.ts @@ -12,20 +12,20 @@ import { AuthModule } from '../src/auth/auth.module'; import { AppService } from '../src/app.service'; import { UsersService } from '../src/users/users.service'; import { AppModule } from '../src/app.module'; -import { Users } from '../src/entities/user.entity'; -import { Snippets } from '../src/entities/snippet.entity'; +import { User } from '../src/entities/user.entity'; +import { Snippet } from '../src/entities/snippet.entity'; import getDataSourceConfig from '../src/config/data-source.config'; describe('SnippetsController (e2e)', () => { let app: NestExpressApplication; - let usersRepo: Repository; - let snippetsRepo: Repository; + let usersRepo: Repository; + let snippetsRepo: Repository; let testData: Record; let users: Array>; let snippets: Array>; let moduleFixture: TestingModule; - let usersData: Users[]; - let snippetsData: Snippets[]; + let usersData: User[]; + let snippetsData: Snippet[]; let jwtService: JwtService; let token: string; @@ -36,7 +36,7 @@ describe('SnippetsController (e2e)', () => { UsersModule, AuthModule, TypeOrmModule.forRoot(getDataSourceConfig()), - TypeOrmModule.forFeature([Users, Snippets]), + TypeOrmModule.forFeature([User, Snippet]), ], providers: [AppService, UsersService], }).compile(); diff --git a/backend/__tests__/users.e2e-spec.ts b/backend/__tests__/users.e2e-spec.ts index 2065dc8a..5d3ffb6b 100644 --- a/backend/__tests__/users.e2e-spec.ts +++ b/backend/__tests__/users.e2e-spec.ts @@ -14,20 +14,20 @@ import { AppService } from '../src/app.service'; import { UsersService } from '../src/users/users.service'; import { CheckEmail } from '../src/users/validation/check-email'; import { AppModule } from '../src/app.module'; -import { Users } from '../src/entities/user.entity'; -import { Snippets } from '../src/entities/snippet.entity'; +import { User } from '../src/entities/user.entity'; +import { Snippet } from '../src/entities/snippet.entity'; import getDataSourceConfig from '../src/config/data-source.config'; describe('UsersController (e2e)', () => { let app: NestExpressApplication; - let usersRepo: Repository; - let snippetsRepo: Repository; + let usersRepo: Repository; + let snippetsRepo: Repository; let testData: Record; let users: Array>; let snippets: Array>; let moduleFixture: TestingModule; - let usersData: Users[]; - let snippetsData: Snippets[]; + let usersData: User[]; + let snippetsData: Snippet[]; let jwtService: JwtService; let token: string; @@ -38,7 +38,7 @@ describe('UsersController (e2e)', () => { UsersModule, AuthModule, TypeOrmModule.forRoot(getDataSourceConfig()), - TypeOrmModule.forFeature([Users, Snippets]), + TypeOrmModule.forFeature([User, Snippet]), ], providers: [AppService, UsersService, CheckEmail], }).compile(); diff --git a/backend/src/entities/snippet.entity.ts b/backend/src/entities/snippet.entity.ts index 67845505..a9481f65 100644 --- a/backend/src/entities/snippet.entity.ts +++ b/backend/src/entities/snippet.entity.ts @@ -7,10 +7,10 @@ import { PrimaryGeneratedColumn, UpdateDateColumn, } from 'typeorm'; -import type { Users } from './user.entity'; +import { User } from './user.entity'; -@Entity() -export class Snippets { +@Entity('snippets') +export class Snippet { @PrimaryGeneratedColumn() id: number; @@ -26,9 +26,9 @@ export class Snippets { @Column('text') language: string; - @ManyToOne('Users', 'snippets', { onDelete: 'CASCADE' }) + @ManyToOne(() => User, (user) => user.snippets) @JoinColumn() - user: Users; + user: User; @CreateDateColumn() created_at: string; diff --git a/backend/src/entities/user.entity.ts b/backend/src/entities/user.entity.ts index 2000f3a9..835c6b17 100644 --- a/backend/src/entities/user.entity.ts +++ b/backend/src/entities/user.entity.ts @@ -11,10 +11,10 @@ import { UpdateDateColumn, } from 'typeorm'; import { encrypt } from '../users/secure/encrypt'; -import type { Snippets } from './snippet.entity'; +import { Snippet } from './snippet.entity'; -@Entity() -export class Users { +@Entity('users') +export class User { @PrimaryGeneratedColumn() id: number; @@ -28,8 +28,8 @@ export class Users { @Column('text') password: string; - @OneToMany('Snippets', 'user') - snippets: Snippets[]; + @OneToMany(() => Snippet, (snippet) => snippet.user) + snippets: Snippet[]; @Column({ nullable: true }) recover_hash: string; diff --git a/backend/src/snippets/interfaces/snippets.interface.ts b/backend/src/snippets/interfaces/snippet.interface.ts similarity index 64% rename from backend/src/snippets/interfaces/snippets.interface.ts rename to backend/src/snippets/interfaces/snippet.interface.ts index 341615d9..de37241f 100644 --- a/backend/src/snippets/interfaces/snippets.interface.ts +++ b/backend/src/snippets/interfaces/snippet.interface.ts @@ -1,4 +1,4 @@ -export interface Snippet { +export interface ISnippet { name: string; code: any; language: string; diff --git a/backend/src/snippets/snippets.controller.ts b/backend/src/snippets/snippets.controller.ts index 54646e93..82033a17 100644 --- a/backend/src/snippets/snippets.controller.ts +++ b/backend/src/snippets/snippets.controller.ts @@ -24,13 +24,13 @@ import { import { User as UserDecorator } from '../users/users.decorator'; import { CreateSnippetDto } from './dto/create-snippet.dto'; import { UpdateSnippetDto } from './dto/update-snippet.dto'; -import { Snippet } from './interfaces/snippets.interface'; +import { ISnippet } from './interfaces/snippet.interface'; import { SnippetsService } from './snippets.service'; import { HttpExceptionFilter } from './exceptions/http-exception.filter'; import { ParseIntPipe } from './pipes/parse-int.pipe'; import { JwtAuthGuard } from '../auth/jwt-auth.guard'; import { ValidationPipe } from './validation/validation.pipe'; -import { User } from '../users/interfaces/users.interface'; +import { IUser } from '../users/interfaces/users.interface'; @ApiTags('snippets') @Controller('snippets') @@ -40,7 +40,7 @@ export class SnippetsController { @Get() @ApiOkResponse({ description: 'Successfully returned all snippets' }) - async findAll(): Promise { + async findAll(): Promise { return this.snippetsService.findAll(); } @@ -57,13 +57,13 @@ export class SnippetsController { async findOneByUsernameSlug( @Param('username') username: string, @Param('slug') slug: string, - ): Promise { + ): Promise { return this.snippetsService.findByUsernameSlug(username, slug); } @Get(':id') @ApiOkResponse({ description: 'Successfully returned snippet by id' }) - async findOne(@Param('id', new ParseIntPipe()) id: number): Promise { + async findOne(@Param('id', new ParseIntPipe()) id: number): Promise { return this.snippetsService.findOne(id); } @@ -74,7 +74,7 @@ export class SnippetsController { @ApiBadRequestResponse({ description: 'Validation failed!' }) @ApiCreatedResponse({ description: 'Snippet successfully created!' }) async create( - @UserDecorator('user') user: User, + @UserDecorator('user') user: IUser, @Body(new ValidationPipe()) createSnippetDto: CreateSnippetDto, ) { diff --git a/backend/src/snippets/snippets.module.ts b/backend/src/snippets/snippets.module.ts index ca5863e1..45169dad 100644 --- a/backend/src/snippets/snippets.module.ts +++ b/backend/src/snippets/snippets.module.ts @@ -2,15 +2,15 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { JwtService } from '@nestjs/jwt'; import { AuthService } from '../auth/auth.service'; -import { Users } from '../entities/user.entity'; -import { Snippets } from '../entities/snippet.entity'; +import { User } from '../entities/user.entity'; +import { Snippet } from '../entities/snippet.entity'; import { SnippetsController } from './snippets.controller'; import { SnippetsService } from './snippets.service'; import { SnippetSubscriber } from './snippets.subscriber'; import { UsersService } from '../users/users.service'; @Module({ - imports: [TypeOrmModule.forFeature([Snippets, Users])], + imports: [TypeOrmModule.forFeature([Snippet, User])], controllers: [SnippetsController], providers: [ SnippetsService, diff --git a/backend/src/snippets/snippets.service.ts b/backend/src/snippets/snippets.service.ts index fd2b41ee..c7dbb9a5 100644 --- a/backend/src/snippets/snippets.service.ts +++ b/backend/src/snippets/snippets.service.ts @@ -4,11 +4,11 @@ import { Injectable } from '@nestjs/common'; import { InjectEntityManager, InjectRepository } from '@nestjs/typeorm'; import { EntityManager, Repository } from 'typeorm'; import { faker } from '@faker-js/faker/locale/en'; -import { Users } from '../entities/user.entity'; +import { User } from '../entities/user.entity'; import { CreateSnippetDto } from './dto/create-snippet.dto'; import { UpdateSnippetDto } from './dto/update-snippet.dto'; -import { Snippets } from '../entities/snippet.entity'; -import { User } from '../users/interfaces/users.interface'; +import { Snippet } from '../entities/snippet.entity'; +import { IUser } from '../users/interfaces/users.interface'; import { generateUniqSlug } from './utils/generate-uniq-slug'; @Injectable() @@ -16,13 +16,13 @@ export class SnippetsService { constructor( @InjectEntityManager() private snippetManager: EntityManager, - @InjectRepository(Snippets) - private snippetsRepository: Repository, - @InjectRepository(Users) - private usersRepository: Repository, + @InjectRepository(Snippet) + private snippetsRepository: Repository, + @InjectRepository(User) + private usersRepository: Repository, ) {} - async findOne(id: number): Promise { + async findOne(id: number): Promise { return this.snippetsRepository.findOneBy({ id }); } @@ -41,7 +41,7 @@ export class SnippetsService { async getSlug(id: number): Promise { const snippets = await this.snippetManager - .createQueryBuilder(Snippets, 'snippet') + .createQueryBuilder(Snippet, 'snippet') .where('snippet.userId= :id', { id }) .getMany(); return generateUniqSlug(snippets); @@ -49,9 +49,9 @@ export class SnippetsService { async create( createSnippetDto: CreateSnippetDto, - { id }: User, - ): Promise { - const snippet = new Snippets(); + { id }: IUser, + ): Promise { + const snippet = new Snippet(); const { name, code, language } = createSnippetDto; const user = await this.usersRepository.findOneBy({ id }); snippet.slug = await this.getSlug(id); @@ -65,7 +65,7 @@ export class SnippetsService { async update( id: number, updateSnippetDto: UpdateSnippetDto, - ): Promise { + ): Promise { await this.snippetsRepository.update(id, updateSnippetDto); return this.snippetsRepository.findOneBy({ id }); } @@ -74,7 +74,7 @@ export class SnippetsService { await this.snippetsRepository.delete(id); } - findAll(): Promise { + findAll(): Promise { return this.snippetsRepository.find(); } diff --git a/backend/src/snippets/snippets.subscriber.ts b/backend/src/snippets/snippets.subscriber.ts index e7578354..6004f471 100644 --- a/backend/src/snippets/snippets.subscriber.ts +++ b/backend/src/snippets/snippets.subscriber.ts @@ -6,19 +6,19 @@ import { EventSubscriber, InsertEvent, } from 'typeorm'; -import { Snippets } from '../entities/snippet.entity'; +import { Snippet } from '../entities/snippet.entity'; @EventSubscriber() -export class SnippetSubscriber implements EntitySubscriberInterface { +export class SnippetSubscriber implements EntitySubscriberInterface { constructor(dataSource: DataSource) { dataSource.subscribers.push(this); } listenTo() { - return Snippets; + return Snippet; } - beforeInsert(event: InsertEvent): void | Promise { + beforeInsert(event: InsertEvent): void | Promise { console.log('BEFORE SNIPPET INSERTER: ', event.entity); } } diff --git a/backend/src/snippets/utils/generate-uniq-slug.ts b/backend/src/snippets/utils/generate-uniq-slug.ts index 51dd1177..14296437 100644 --- a/backend/src/snippets/utils/generate-uniq-slug.ts +++ b/backend/src/snippets/utils/generate-uniq-slug.ts @@ -1,7 +1,7 @@ import { faker } from '@faker-js/faker'; -import { Snippets } from '../../entities/snippet.entity'; +import { Snippet } from '../../entities/snippet.entity'; -export const generateUniqSlug = (snippets: Snippets[]): string => { +export const generateUniqSlug = (snippets: Snippet[]): string => { const slug = faker.random.alpha({ count: 7, casing: 'mixed' }); return !snippets.find((snippet) => snippet.slug === slug) ? slug diff --git a/backend/src/users/interfaces/users.interface.ts b/backend/src/users/interfaces/users.interface.ts index 635b06b9..e0da0c2a 100644 --- a/backend/src/users/interfaces/users.interface.ts +++ b/backend/src/users/interfaces/users.interface.ts @@ -1,4 +1,4 @@ -export interface User { +export interface IUser { id: number; username: string; email: string; diff --git a/backend/src/users/users.controller.ts b/backend/src/users/users.controller.ts index 3e69d173..9434eded 100644 --- a/backend/src/users/users.controller.ts +++ b/backend/src/users/users.controller.ts @@ -25,7 +25,7 @@ import { import { CreateUserDto } from './dto/create-user.dto'; import { UpdateUserDto } from './dto/update-user.dto'; import { User as UserDecorator } from './users.decorator'; -import { User } from './interfaces/users.interface'; +import { IUser } from './interfaces/users.interface'; import { UsersService } from './users.service'; import { HttpExceptionFilter } from './exceptions/http-exception.filter'; import { ParseIntPipe } from './pipes/parse-int.pipe'; @@ -48,7 +48,7 @@ export class UsersController { @ApiCookieAuth('access_token') @ApiOkResponse({ description: 'Successfully returned all users' }) @ApiUnauthorizedResponse({ description: 'Unauthorized' }) - async findAll(): Promise { + async findAll(): Promise { return this.usersService.findAll(); } @@ -57,7 +57,7 @@ export class UsersController { @ApiCookieAuth('access_token') @ApiOkResponse({ description: 'Successfully returned user profile' }) @ApiUnauthorizedResponse({ description: 'Unauthorized' }) - async getProfile(@UserDecorator('user') user: User) { + async getProfile(@UserDecorator('user') user: IUser) { return this.usersService.getData(user); } @@ -66,7 +66,7 @@ export class UsersController { @ApiCookieAuth('access_token') @ApiOkResponse({ description: 'Successfully returned user' }) @ApiUnauthorizedResponse({ description: 'Unauthorized' }) - async findOne(@Param('id', new ParseIntPipe()) id: number): Promise { + async findOne(@Param('id', new ParseIntPipe()) id: number): Promise { return this.usersService.findOne(id); } @@ -75,7 +75,7 @@ export class UsersController { @ApiCookieAuth('access_token') @ApiOkResponse({ description: 'Successfully returned user by username' }) @ApiUnauthorizedResponse({ description: 'Unauthorized' }) - async findByUsername(@Param('username') username: string): Promise { + async findByUsername(@Param('username') username: string): Promise { return this.usersService.findByUsername(username); } diff --git a/backend/src/users/users.module.ts b/backend/src/users/users.module.ts index 89d948f3..812954ea 100644 --- a/backend/src/users/users.module.ts +++ b/backend/src/users/users.module.ts @@ -1,9 +1,9 @@ import { Module } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { Snippets } from '../entities/snippet.entity'; +import { Snippet } from '../entities/snippet.entity'; import { AuthService } from '../auth/auth.service'; -import { Users } from '../entities/user.entity'; +import { User } from '../entities/user.entity'; import { UsersController } from './users.controller'; import { UsersService } from './users.service'; import { UsersSubscriber } from './users.subscriber'; @@ -12,7 +12,7 @@ import { CheckUsername } from './validation/check-username'; import { CheckPassword } from './validation/check-password'; @Module({ - imports: [TypeOrmModule.forFeature([Users, Snippets])], + imports: [TypeOrmModule.forFeature([User, Snippet])], controllers: [UsersController], providers: [ UsersService, diff --git a/backend/src/users/users.service.ts b/backend/src/users/users.service.ts index 04c35438..5ec3f2ba 100644 --- a/backend/src/users/users.service.ts +++ b/backend/src/users/users.service.ts @@ -10,48 +10,48 @@ import { MailerService } from '@nestjs-modules/mailer'; import { InjectSentry, SentryService } from '@ntegral/nestjs-sentry'; import { CreateUserDto } from './dto/create-user.dto'; import { UpdateUserDto } from './dto/update-user.dto'; -import { Users } from '../entities/user.entity'; -import { Snippets } from '../entities/snippet.entity'; -import { User } from './interfaces/users.interface'; +import { User } from '../entities/user.entity'; +import { Snippet } from '../entities/snippet.entity'; +import { IUser } from './interfaces/users.interface'; import { RecoverUserDto } from './dto/recover-user.dto'; import { cipher, decipher } from './secure/cipher'; @Injectable() export class UsersService { constructor( - @InjectRepository(Users) - private usersRepository: Repository, - @InjectRepository(Snippets) - private snippetsRepository: Repository, + @InjectRepository(User) + private usersRepository: Repository, + @InjectRepository(Snippet) + private snippetsRepository: Repository, private readonly mailerService: MailerService, @InjectSentry() private readonly sentryService: SentryService, ) {} - async findOne(id: number): Promise { + async findOne(id: number): Promise { return this.usersRepository.findOneBy({ id }); } - async find(email: string): Promise { + async find(email: string): Promise { return this.usersRepository.findOneBy({ email }); } - async findByUsername(username: string): Promise { + async findByUsername(username: string): Promise { return this.usersRepository.findOneBy({ username: ILike(username) }); } - async findByEmail(email: string): Promise { + async findByEmail(email: string): Promise { return this.usersRepository.findOneBy({ email }); } - create(createUserDto: CreateUserDto): Promise { - const user = new Users(); + create(createUserDto: CreateUserDto): Promise { + const user = new User(); user.username = createUserDto.username; user.email = createUserDto.email.toLowerCase(); user.password = createUserDto.password; return this.usersRepository.save(user); } - async update(id: number, updateUserDto: UpdateUserDto): Promise { + async update(id: number, updateUserDto: UpdateUserDto): Promise { const { ...data } = updateUserDto; const currentUser = await this.usersRepository.findOneBy({ id }); const updatedUser = this.usersRepository.merge(currentUser, data); @@ -136,11 +136,11 @@ export class UsersService { await this.usersRepository.delete(id); } - findAll(): Promise { + findAll(): Promise { return this.usersRepository.find(); } - async getData({ id }: User): Promise { + async getData({ id }: IUser): Promise { const currentUser = await this.usersRepository.findOneBy({ id }); const snippets = await this.snippetsRepository.find({ relations: { diff --git a/backend/src/users/users.subscriber.ts b/backend/src/users/users.subscriber.ts index 65666204..6d425648 100644 --- a/backend/src/users/users.subscriber.ts +++ b/backend/src/users/users.subscriber.ts @@ -6,19 +6,19 @@ import { EventSubscriber, InsertEvent, } from 'typeorm'; -import { Users } from '../entities/user.entity'; +import { User } from '../entities/user.entity'; @EventSubscriber() -export class UsersSubscriber implements EntitySubscriberInterface { +export class UsersSubscriber implements EntitySubscriberInterface { constructor(dataSource: DataSource) { dataSource.subscribers.push(this); } listenTo() { - return Users; + return User; } - beforeInsert(event: InsertEvent): void | Promise { + beforeInsert(event: InsertEvent): void | Promise { console.log('BEFORE USER INSERTER: ', event.entity); } } diff --git a/backend/src/users/validation/validation.module.ts b/backend/src/users/validation/validation.module.ts index 362820c8..4ae1b460 100644 --- a/backend/src/users/validation/validation.module.ts +++ b/backend/src/users/validation/validation.module.ts @@ -2,10 +2,10 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { UsersService } from '../users.service'; import { UsersController } from '../users.controller'; -import { Users } from '../../entities/user.entity'; +import { User } from '../../entities/user.entity'; @Module({ - imports: [TypeOrmModule.forFeature([Users])], + imports: [TypeOrmModule.forFeature([User])], controllers: [UsersController], providers: [UsersService], }) From 38a0f8f49e1a82d0a657776e75e33a27ab87adc4 Mon Sep 17 00:00:00 2001 From: Nikolay Gagarinov Date: Fri, 7 Jun 2024 00:06:43 +0500 Subject: [PATCH 4/5] update snippets with null language --- .../1717697901307-fix-old-snippets-language.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 backend/src/migrations/1717697901307-fix-old-snippets-language.ts diff --git a/backend/src/migrations/1717697901307-fix-old-snippets-language.ts b/backend/src/migrations/1717697901307-fix-old-snippets-language.ts new file mode 100644 index 00000000..cbff5a12 --- /dev/null +++ b/backend/src/migrations/1717697901307-fix-old-snippets-language.ts @@ -0,0 +1,16 @@ +import { Snippet } from "../entities/snippet.entity" +import { MigrationInterface, QueryRunner } from "typeorm" + +export class FixOldSnippetsLanguage1717697901307 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.manager.getRepository(Snippet).createQueryBuilder() + .update() + .set({ language: "javascript" }) + .where("language IS NULL") + .execute(); + } + + public async down(queryRunner: QueryRunner): Promise { + } + +} From 2c8501bc608569ee9dddb3659cd81366131623ae Mon Sep 17 00:00:00 2001 From: Nikolay Gagarinov Date: Fri, 7 Jun 2024 00:36:12 +0500 Subject: [PATCH 5/5] fix lint --- backend/.eslintrc.yml | 3 +++ backend/src/config/data-source.config.ts | 7 +++-- backend/src/entities/snippet.entity.ts | 4 +-- backend/src/entities/user.entity.ts | 4 +-- .../migrations/1699462100238-migrations.ts | 13 +++++----- ...1717697901307-fix-old-snippets-language.ts | 26 ++++++++++--------- backend/src/snippets/snippets.controller.ts | 4 ++- 7 files changed, 33 insertions(+), 28 deletions(-) diff --git a/backend/.eslintrc.yml b/backend/.eslintrc.yml index 4f96e782..75982e1c 100644 --- a/backend/.eslintrc.yml +++ b/backend/.eslintrc.yml @@ -36,6 +36,9 @@ settings: - .ts rules: + class-methods-use-this: + - 2 + - exceptMethods: ["up", "down"] import/no-cycle: [2, { maxDepth: 1 }] import/prefer-default-export: 0 import/extensions: 0 diff --git a/backend/src/config/data-source.config.ts b/backend/src/config/data-source.config.ts index 569d544d..d34f84b3 100644 --- a/backend/src/config/data-source.config.ts +++ b/backend/src/config/data-source.config.ts @@ -1,9 +1,9 @@ import { DataSourceOptions } from 'typeorm'; + export default (): DataSourceOptions => { const defaultConfig = { - entities: [ __dirname + `/../entities/**/*{.ts,.js}`], - migrations: [ __dirname + `/../migrations/**/*{.ts,.js}`], - + entities: [`${__dirname}/../entities/**/*{.ts,.js}`], + migrations: [`${__dirname}/../migrations/**/*{.ts,.js}`], }; switch (process.env.NODE_ENV) { case 'production': @@ -23,7 +23,6 @@ export default (): DataSourceOptions => { type: 'sqlite', database: ':memory:', synchronize: true, - }; default: return { diff --git a/backend/src/entities/snippet.entity.ts b/backend/src/entities/snippet.entity.ts index a9481f65..3e7d96b3 100644 --- a/backend/src/entities/snippet.entity.ts +++ b/backend/src/entities/snippet.entity.ts @@ -7,7 +7,7 @@ import { PrimaryGeneratedColumn, UpdateDateColumn, } from 'typeorm'; -import { User } from './user.entity'; +import type { User } from './user.entity'; @Entity('snippets') export class Snippet { @@ -26,7 +26,7 @@ export class Snippet { @Column('text') language: string; - @ManyToOne(() => User, (user) => user.snippets) + @ManyToOne('User', 'snippets') @JoinColumn() user: User; diff --git a/backend/src/entities/user.entity.ts b/backend/src/entities/user.entity.ts index 835c6b17..8ad030f4 100644 --- a/backend/src/entities/user.entity.ts +++ b/backend/src/entities/user.entity.ts @@ -11,7 +11,7 @@ import { UpdateDateColumn, } from 'typeorm'; import { encrypt } from '../users/secure/encrypt'; -import { Snippet } from './snippet.entity'; +import type { Snippet } from './snippet.entity'; @Entity('users') export class User { @@ -28,7 +28,7 @@ export class User { @Column('text') password: string; - @OneToMany(() => Snippet, (snippet) => snippet.user) + @OneToMany('Snippet', 'user') snippets: Snippet[]; @Column({ nullable: true }) diff --git a/backend/src/migrations/1699462100238-migrations.ts b/backend/src/migrations/1699462100238-migrations.ts index 3bba5afc..dba22d7d 100644 --- a/backend/src/migrations/1699462100238-migrations.ts +++ b/backend/src/migrations/1699462100238-migrations.ts @@ -1,8 +1,7 @@ -/* eslint class-methods-use-this: ["error", { "exceptMethods": ["up", "down"] }] */ import { MigrationInterface, QueryRunner, Table } from 'typeorm'; export class Migrations1699462100238 implements MigrationInterface { - public async up(queryRunner: QueryRunner): Promise { + public async up(queryRunner: QueryRunner): Promise { await queryRunner.createTable( new Table({ name: 'users', @@ -114,10 +113,10 @@ export class Migrations1699462100238 implements MigrationInterface { ], }), ); - } + } - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DROP TABLE "snippets"`); - await queryRunner.query(`DROP TABLE "users"`); - } + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE "snippets"`); + await queryRunner.query(`DROP TABLE "users"`); + } } diff --git a/backend/src/migrations/1717697901307-fix-old-snippets-language.ts b/backend/src/migrations/1717697901307-fix-old-snippets-language.ts index cbff5a12..405b7022 100644 --- a/backend/src/migrations/1717697901307-fix-old-snippets-language.ts +++ b/backend/src/migrations/1717697901307-fix-old-snippets-language.ts @@ -1,16 +1,18 @@ -import { Snippet } from "../entities/snippet.entity" -import { MigrationInterface, QueryRunner } from "typeorm" +import { MigrationInterface, QueryRunner } from 'typeorm'; +import { Snippet } from '../entities/snippet.entity'; export class FixOldSnippetsLanguage1717697901307 implements MigrationInterface { - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.manager.getRepository(Snippet).createQueryBuilder() - .update() - .set({ language: "javascript" }) - .where("language IS NULL") - .execute(); - } - - public async down(queryRunner: QueryRunner): Promise { - } + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.manager + .getRepository(Snippet) + .createQueryBuilder() + .update() + .set({ language: 'javascript' }) + .where('language IS NULL') + .execute(); + } + public async down(): Promise { + // nothing + } } diff --git a/backend/src/snippets/snippets.controller.ts b/backend/src/snippets/snippets.controller.ts index 82033a17..8d6207c7 100644 --- a/backend/src/snippets/snippets.controller.ts +++ b/backend/src/snippets/snippets.controller.ts @@ -63,7 +63,9 @@ export class SnippetsController { @Get(':id') @ApiOkResponse({ description: 'Successfully returned snippet by id' }) - async findOne(@Param('id', new ParseIntPipe()) id: number): Promise { + async findOne( + @Param('id', new ParseIntPipe()) id: number, + ): Promise { return this.snippetsService.findOne(id); }