From b0088e4f63da1436f8faf0ff7ab3624e52872690 Mon Sep 17 00:00:00 2001 From: Supan Adit Pratama Date: Sat, 2 Nov 2024 09:41:20 +0700 Subject: [PATCH] feat: implement unique identifier when searching to database --- libs/prisma/src/processes/delete.process.ts | 5 ++-- libs/prisma/src/processes/read.process.ts | 5 ++-- libs/prisma/src/processes/update.process.ts | 5 ++-- .../skeleton/src/executors/delete.executor.ts | 17 ++++++++++--- libs/skeleton/src/executors/read.executor.ts | 13 +++++++--- .../skeleton/src/executors/update.executor.ts | 24 +++++++++++++++--- libs/skeleton/src/processes/delete.process.ts | 3 ++- libs/skeleton/src/processes/read.process.ts | 3 ++- libs/skeleton/src/processes/update.process.ts | 3 ++- libs/skeleton/src/skeleton-crud.controller.ts | 25 ++++++++++++++----- .../migration.sql | 12 +++++++++ prisma/schema.prisma | 7 +++--- .../custom/domain/custom.read.process.ts | 2 +- 13 files changed, 93 insertions(+), 31 deletions(-) create mode 100644 prisma/migrations/20241102024042_account_username/migration.sql diff --git a/libs/prisma/src/processes/delete.process.ts b/libs/prisma/src/processes/delete.process.ts index 3b68fae..e240ef9 100644 --- a/libs/prisma/src/processes/delete.process.ts +++ b/libs/prisma/src/processes/delete.process.ts @@ -5,11 +5,12 @@ export class PrismaDeleteProcess extends PrismaProcess implements DeleteProcess { - public identity; + public identityData; + public identityKey: string = 'id'; async process() { this.result = await this.getDelegate().delete({ - where: { id: this.identity }, + where: { [this.identityKey]: this.identityData }, }); } } diff --git a/libs/prisma/src/processes/read.process.ts b/libs/prisma/src/processes/read.process.ts index d1010b8..75f9c29 100644 --- a/libs/prisma/src/processes/read.process.ts +++ b/libs/prisma/src/processes/read.process.ts @@ -2,11 +2,12 @@ import { ReadProcess } from '@aditama-labs/nest-autocrud/skeleton'; import { PrismaProcess } from './prisma.process'; export class PrismaReadProcess extends PrismaProcess implements ReadProcess { - public identity; + public identityData; + public identityKey: string = 'id'; async process() { this.result = await this.getDelegate().findUnique({ - where: { id: this.identity }, + where: { [this.identityKey]: this.identityData }, }); } } diff --git a/libs/prisma/src/processes/update.process.ts b/libs/prisma/src/processes/update.process.ts index 14f9f28..391655e 100644 --- a/libs/prisma/src/processes/update.process.ts +++ b/libs/prisma/src/processes/update.process.ts @@ -5,13 +5,14 @@ export class PrismaUpdateProcess extends PrismaProcess implements UpdateProcess { - public identity; + public identityData; + public identityKey: string = 'id'; public payload; async process() { this.result = await this.getDelegate().update({ data: this.payload, - where: { id: this.identity }, + where: { [this.identityKey]: this.identityData }, }); } } diff --git a/libs/skeleton/src/executors/delete.executor.ts b/libs/skeleton/src/executors/delete.executor.ts index 5b2d084..8979cff 100644 --- a/libs/skeleton/src/executors/delete.executor.ts +++ b/libs/skeleton/src/executors/delete.executor.ts @@ -3,14 +3,23 @@ import { DefaultExecutor } from './default.executor'; // @TODO: ReadExecutor and DeleteExecutor can be merged into one executor export class DeleteExecutor extends DefaultExecutor { - constructor(process: DeleteProcess, id) { + constructor( + process: DeleteProcess, + identityData, + identityKey: string = 'id', + ) { super(process); // Set the id of the data - process.identity = id; + process.identityData = identityData; + process.identityKey = identityKey; } - static async bootstrap(process: DeleteProcess, id) { - const executor = new DeleteExecutor(process, id); + static async bootstrap( + process: DeleteProcess, + identityData, + identityKey: string = 'id', + ) { + const executor = new DeleteExecutor(process, identityData, identityKey); await executor.execute(); return executor.getOutput(); } diff --git a/libs/skeleton/src/executors/read.executor.ts b/libs/skeleton/src/executors/read.executor.ts index 19be374..aa16ad8 100644 --- a/libs/skeleton/src/executors/read.executor.ts +++ b/libs/skeleton/src/executors/read.executor.ts @@ -2,14 +2,19 @@ import { ReadProcess } from '../processes'; import { DefaultExecutor } from './default.executor'; export class ReadExecutor extends DefaultExecutor { - constructor(process: ReadProcess, id) { + constructor(process: ReadProcess, identityData, identityKey: string = 'id') { super(process); // Set the id of the data - process.identity = id; + process.identityData = identityData; + process.identityKey = identityKey; } - static async bootstrap(process: ReadProcess, id) { - const executor = new ReadExecutor(process, id); + static async bootstrap( + process: ReadProcess, + identityData, + identityKey: string = 'id', + ) { + const executor = new ReadExecutor(process, identityData, identityKey); await executor.execute(); return executor.getOutput(); } diff --git a/libs/skeleton/src/executors/update.executor.ts b/libs/skeleton/src/executors/update.executor.ts index 891b74c..9e3c35b 100644 --- a/libs/skeleton/src/executors/update.executor.ts +++ b/libs/skeleton/src/executors/update.executor.ts @@ -3,15 +3,31 @@ import { DefaultExecutor } from './default.executor'; // @TODO: This executor should be able to extend from ReadExecutor and CreateExecutor export class UpdateExecutor extends DefaultExecutor { - constructor(process: UpdateProcess, id, data) { + constructor( + process: UpdateProcess, + identityData, + data, + identityKey: string = 'id', + ) { super(process); // Set the id and data to process - process.identity = id; + process.identityData = identityData; process.payload = data; + process.identityKey = identityKey; } - static async bootstrap(process: UpdateProcess, id, data) { - const executor = new UpdateExecutor(process, id, data); + static async bootstrap( + process: UpdateProcess, + identityData, + data, + identityKey: string = 'id', + ) { + const executor = new UpdateExecutor( + process, + identityData, + data, + identityKey, + ); await executor.execute(); return executor.getOutput(); } diff --git a/libs/skeleton/src/processes/delete.process.ts b/libs/skeleton/src/processes/delete.process.ts index ed7ec3d..0ff1225 100644 --- a/libs/skeleton/src/processes/delete.process.ts +++ b/libs/skeleton/src/processes/delete.process.ts @@ -2,5 +2,6 @@ import { DefaultProcess } from './default.process'; // @TODO: DeleteProcess and ReadProcess are the same, should be refactored next export class DeleteProcess extends DefaultProcess { - public identity; + public identityData; + public identityKey: string = 'id'; } diff --git a/libs/skeleton/src/processes/read.process.ts b/libs/skeleton/src/processes/read.process.ts index a15eef3..64fdbd5 100644 --- a/libs/skeleton/src/processes/read.process.ts +++ b/libs/skeleton/src/processes/read.process.ts @@ -1,5 +1,6 @@ import { DefaultProcess } from './default.process'; export class ReadProcess extends DefaultProcess { - public identity; + public identityData; + public identityKey: string = 'id'; } diff --git a/libs/skeleton/src/processes/update.process.ts b/libs/skeleton/src/processes/update.process.ts index 5f0ca61..72c2bfb 100644 --- a/libs/skeleton/src/processes/update.process.ts +++ b/libs/skeleton/src/processes/update.process.ts @@ -2,7 +2,8 @@ import { DefaultProcess } from './default.process'; export class UpdateProcess extends DefaultProcess { // @TODO: The property of id can be take from ReadProcess which is extended - public identity; + public identityData; + public identityKey: string = 'id'; // @TODO: The property of data can be take from CreateProcess which is extended public payload; } diff --git a/libs/skeleton/src/skeleton-crud.controller.ts b/libs/skeleton/src/skeleton-crud.controller.ts index 65756f5..9369349 100644 --- a/libs/skeleton/src/skeleton-crud.controller.ts +++ b/libs/skeleton/src/skeleton-crud.controller.ts @@ -95,8 +95,12 @@ export const CustomCRUDController = (options?: ControllerOption) => { } @Delete(`:${uniqueIdentifier}`) - async delete(@Param(uniqueIdentifier) id) { - return await super.delete(id); + async delete(@Param(uniqueIdentifier) identityData) { + return await DeleteExecutor.bootstrap( + this.deleteProcess, + identityData, + uniqueIdentifier, + ); } @Get('list') @@ -111,13 +115,22 @@ export const CustomCRUDController = (options?: ControllerOption) => { } @Get(`:${uniqueIdentifier}`) - async read(@Param(uniqueIdentifier) id) { - return await super.read(id); + async read(@Param(uniqueIdentifier) identityData) { + return await ReadExecutor.bootstrap( + this.readProcess, + identityData, + uniqueIdentifier, + ); } @Patch(`:${uniqueIdentifier}`) - async update(@Param(uniqueIdentifier) id, @Body() body) { - return await super.update(id, body); + async update(@Param(uniqueIdentifier) identityData, @Body() body) { + return await UpdateExecutor.bootstrap( + this.updateProcess, + identityData, + body, + uniqueIdentifier, + ); } } diff --git a/prisma/migrations/20241102024042_account_username/migration.sql b/prisma/migrations/20241102024042_account_username/migration.sql new file mode 100644 index 0000000..bf0ce7d --- /dev/null +++ b/prisma/migrations/20241102024042_account_username/migration.sql @@ -0,0 +1,12 @@ +/* + Warnings: + + - A unique constraint covering the columns `[username]` on the table `account` will be added. If there are existing duplicate values, this will fail. + - Added the required column `username` to the `account` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "account" ADD COLUMN "username" TEXT NOT NULL; + +-- CreateIndex +CREATE UNIQUE INDEX "account_username_key" ON "account"("username"); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 44cee97..4e4f6bb 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -16,9 +16,10 @@ datasource db { } model User { - id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid - name String - Todo Todo[] + id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid + username String @unique + name String + Todo Todo[] @@map("account") } diff --git a/src/example/custom/domain/custom.read.process.ts b/src/example/custom/domain/custom.read.process.ts index 8d4d572..350b9c4 100644 --- a/src/example/custom/domain/custom.read.process.ts +++ b/src/example/custom/domain/custom.read.process.ts @@ -4,7 +4,7 @@ export class CustomReadProcess extends PrismaReadProcess { customResult; async before(): Promise { - console.log('The ID requested in path parameter', this.identity); + console.log('The ID requested in path parameter', this.identityData); } async after(): Promise { this.customResult = {