From 65b4915831513a7ec4b50eb45599cd341dc18316 Mon Sep 17 00:00:00 2001 From: Supan Adit Pratama Date: Sat, 2 Nov 2024 00:08:02 +0700 Subject: [PATCH] wip: new way to extend a controller --- libs/skeleton/src/constants.ts | 2 + .../skeleton-controller.decorator.ts | 4 +- .../decoratos/unique-override.decorator.ts | 19 ++++ .../controller/controller.option.ts | 3 + libs/skeleton/src/skeleton-crud.controller.ts | 93 ++++++++++--------- src/example/custom/custom.controller.ts | 6 +- src/example/simple/simple.controller.ts | 16 +++- 7 files changed, 91 insertions(+), 52 deletions(-) create mode 100644 libs/skeleton/src/decoratos/unique-override.decorator.ts create mode 100644 libs/skeleton/src/interfaces/controller/controller.option.ts diff --git a/libs/skeleton/src/constants.ts b/libs/skeleton/src/constants.ts index 647b4ef..e4c6cd6 100644 --- a/libs/skeleton/src/constants.ts +++ b/libs/skeleton/src/constants.ts @@ -4,3 +4,5 @@ export const LIST_PROCESS = 'LIST_PROCESS'; export const PAGINATION_PROCESS = 'PAGINATION_PROCESS'; export const READ_PROCESS = 'READ_PROCESS'; export const UPDATE_PROCESS = 'UPDATE_PROCESS'; + +export const UNIQUE_IDENTIFIER = 'PARAM:UNIQUE_IDENTIFIER'; diff --git a/libs/skeleton/src/decoratos/skeleton-controller.decorator.ts b/libs/skeleton/src/decoratos/skeleton-controller.decorator.ts index 8a5e32d..1060dd6 100644 --- a/libs/skeleton/src/decoratos/skeleton-controller.decorator.ts +++ b/libs/skeleton/src/decoratos/skeleton-controller.decorator.ts @@ -1,5 +1,7 @@ +import { UNIQUE_IDENTIFIER } from '../constants'; + export function SkeletonController(): ClassDecorator { return (target: object) => { - console.log('STARTED', target); + Reflect.defineMetadata(UNIQUE_IDENTIFIER, 'haha', target); }; } diff --git a/libs/skeleton/src/decoratos/unique-override.decorator.ts b/libs/skeleton/src/decoratos/unique-override.decorator.ts new file mode 100644 index 0000000..25b698d --- /dev/null +++ b/libs/skeleton/src/decoratos/unique-override.decorator.ts @@ -0,0 +1,19 @@ +import { UNIQUE_IDENTIFIER } from '../constants'; + +export const UniqueOverride = (): MethodDecorator => { + return ( + target: object, + key: string | symbol, + descriptor: TypedPropertyDescriptor, + ) => { + // const result = Reflect.getMetadata(UNIQUE_IDENTIFIER, descriptor.value); + // console.log(result); + // console.log(Object.getOwnPropertyNames(props)); + + let result = Reflect.getOwnMetadata(UNIQUE_IDENTIFIER, target); + console.log(target.constructor); + + console.log(result); + return descriptor; + }; +}; diff --git a/libs/skeleton/src/interfaces/controller/controller.option.ts b/libs/skeleton/src/interfaces/controller/controller.option.ts new file mode 100644 index 0000000..3ffdeed --- /dev/null +++ b/libs/skeleton/src/interfaces/controller/controller.option.ts @@ -0,0 +1,3 @@ +export interface ControllerOption { + uniqueIdentifier?: string; +} diff --git a/libs/skeleton/src/skeleton-crud.controller.ts b/libs/skeleton/src/skeleton-crud.controller.ts index cdcbbe2..147d002 100644 --- a/libs/skeleton/src/skeleton-crud.controller.ts +++ b/libs/skeleton/src/skeleton-crud.controller.ts @@ -1,6 +1,5 @@ import { Body, - ClassSerializerInterceptor, Delete, Get, Inject, @@ -8,7 +7,6 @@ import { Patch, Post, Query, - UseInterceptors, UsePipes, ValidationPipe, } from '@nestjs/common'; @@ -27,52 +25,57 @@ import { DeleteExecutor } from './executors/delete.executor'; import { ListExecutor } from './executors/list.executor'; import { ReadExecutor } from './executors/read.executor'; import { UpdateExecutor } from './executors/update.executor'; +import { ControllerOption } from './interfaces/controller/controller.option'; import { ISkeletonCRUDController } from './interfaces/controller/skeleton-crud.controller.interface'; -export class SkeletonCRUDController implements ISkeletonCRUDController { - constructor( - @Inject(CREATE_PROCESS) - public readonly createProcess, - @Inject(DELETE_PROCESS) - public readonly deleteProcess, - @Inject(LIST_PROCESS) - public readonly listProcess, - @Inject(PAGINATION_PROCESS) - public readonly paginationProcess, - @Inject(READ_PROCESS) - public readonly readProcess, - @Inject(UPDATE_PROCESS) - public readonly updateProcess, - ) {} +export function getBaseController(option?: ControllerOption): any { + class SkeletonCRUDController implements ISkeletonCRUDController { + constructor( + @Inject(CREATE_PROCESS) + public readonly createProcess, + @Inject(DELETE_PROCESS) + public readonly deleteProcess, + @Inject(LIST_PROCESS) + public readonly listProcess, + @Inject(PAGINATION_PROCESS) + public readonly paginationProcess, + @Inject(READ_PROCESS) + public readonly readProcess, + @Inject(UPDATE_PROCESS) + public readonly updateProcess, + ) {} - @Post() - async create(@Body() body): Promise { - return await CreateExcutor.bootstrap(this.createProcess, body); + @Post() + async create(@Body() body): Promise { + return await CreateExcutor.bootstrap(this.createProcess, body); + } + + @Delete(`:${option?.uniqueIdentifier ?? 'id'}`) + async delete(@Param(`${option?.uniqueIdentifier}`) id) { + return await DeleteExecutor.bootstrap(this.deleteProcess, id); + } + + @Get('list') + async list() { + return await ListExecutor.bootstrap(this.listProcess); + } + + @Get() + @UsePipes(new ValidationPipe({ transform: true })) + async pagination(@Query() params: PaginationParamDTO) { + return await PaginationExecutor.bootstrap(this.paginationProcess, params); + } + + @Get(`:${option?.uniqueIdentifier}`) + async read(@Param(`${option?.uniqueIdentifier}`) id) { + return await ReadExecutor.bootstrap(this.readProcess, id); + } + + @Patch(`:${option?.uniqueIdentifier}`) + async update(@Param(`${option?.uniqueIdentifier}`) id, @Body() body) { + return await UpdateExecutor.bootstrap(this.updateProcess, id, body); + } } - @Delete(':id') - async delete(@Param('id') id) { - return await DeleteExecutor.bootstrap(this.deleteProcess, id); - } - - @Get('list') - async list() { - return await ListExecutor.bootstrap(this.listProcess); - } - - @Get() - @UsePipes(new ValidationPipe({ transform: true })) - async pagination(@Query() params: PaginationParamDTO) { - return await PaginationExecutor.bootstrap(this.paginationProcess, params); - } - - @Get(':id') - async read(@Param('id') id) { - return await ReadExecutor.bootstrap(this.readProcess, id); - } - - @Patch(':id') - async update(@Param('id') id, @Body() body) { - return await UpdateExecutor.bootstrap(this.updateProcess, id, body); - } + return SkeletonCRUDController; } diff --git a/src/example/custom/custom.controller.ts b/src/example/custom/custom.controller.ts index 1f3bdc1..b3b60f6 100644 --- a/src/example/custom/custom.controller.ts +++ b/src/example/custom/custom.controller.ts @@ -1,5 +1,7 @@ +import { getBaseController } from '@aditama-labs/nest-autocrud/skeleton'; import { Controller } from '@nestjs/common'; -import { SkeletonCRUDController } from 'libs'; @Controller('example/custom') -export class CustomController extends SkeletonCRUDController {} +export class CustomController extends getBaseController({ + uniqueIdentifier: 'key', +}) {} diff --git a/src/example/simple/simple.controller.ts b/src/example/simple/simple.controller.ts index 739f593..a7c17fe 100644 --- a/src/example/simple/simple.controller.ts +++ b/src/example/simple/simple.controller.ts @@ -1,6 +1,14 @@ -import { Controller } from '@nestjs/common'; -import { SkeletonController, SkeletonCRUDController } from 'libs'; +import { UniqueOverride } from '@aditama-labs/nest-autocrud/skeleton/src/decoratos/unique-override.decorator'; +import { Controller, Get } from '@nestjs/common'; +import { getBaseController, SkeletonController, UNIQUE_IDENTIFIER } from 'libs'; -@Controller('example/simple') @SkeletonController() -export class SimpleController extends SkeletonCRUDController {} +@Controller('example/simple') +export class SimpleController extends getBaseController() { + @UniqueOverride() + @Get('list') + async list(): Promise { + console.log(Reflect.getOwnMetadata(UNIQUE_IDENTIFIER, this.constructor)); + return super.list(); + } +}