feat: custom unique identifier

This commit is contained in:
Supan Adit Pratama 2024-11-02 00:48:19 +07:00
parent 65b4915831
commit c7ae346c07
7 changed files with 83 additions and 74 deletions

View File

@ -1 +0,0 @@
export * from './skeleton-controller.decorator';

View File

@ -1,7 +0,0 @@
import { UNIQUE_IDENTIFIER } from '../constants';
export function SkeletonController(): ClassDecorator {
return (target: object) => {
Reflect.defineMetadata(UNIQUE_IDENTIFIER, 'haha', target);
};
}

View File

@ -1,19 +0,0 @@
import { UNIQUE_IDENTIFIER } from '../constants';
export const UniqueOverride = (): MethodDecorator => {
return (
target: object,
key: string | symbol,
descriptor: TypedPropertyDescriptor<any>,
) => {
// 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;
};
};

View File

@ -1,5 +1,4 @@
export * from './constants'; export * from './constants';
export * from './decoratos';
export * from './dto'; export * from './dto';
export * from './entities'; export * from './entities';
export * from './executors'; export * from './executors';

View File

@ -28,8 +28,7 @@ import { UpdateExecutor } from './executors/update.executor';
import { ControllerOption } from './interfaces/controller/controller.option'; import { ControllerOption } from './interfaces/controller/controller.option';
import { ISkeletonCRUDController } from './interfaces/controller/skeleton-crud.controller.interface'; import { ISkeletonCRUDController } from './interfaces/controller/skeleton-crud.controller.interface';
export function getBaseController(option?: ControllerOption): any { class SkeletonCRUDController implements ISkeletonCRUDController {
class SkeletonCRUDController implements ISkeletonCRUDController {
constructor( constructor(
@Inject(CREATE_PROCESS) @Inject(CREATE_PROCESS)
public readonly createProcess, public readonly createProcess,
@ -50,9 +49,9 @@ export function getBaseController(option?: ControllerOption): any {
return await CreateExcutor.bootstrap(this.createProcess, body); return await CreateExcutor.bootstrap(this.createProcess, body);
} }
@Delete(`:${option?.uniqueIdentifier ?? 'id'}`) @Delete(':id')
async delete(@Param(`${option?.uniqueIdentifier}`) id) { async delete(@Param('id') providedKey) {
return await DeleteExecutor.bootstrap(this.deleteProcess, id); return await DeleteExecutor.bootstrap(this.deleteProcess, providedKey);
} }
@Get('list') @Get('list')
@ -66,16 +65,63 @@ export function getBaseController(option?: ControllerOption): any {
return await PaginationExecutor.bootstrap(this.paginationProcess, params); return await PaginationExecutor.bootstrap(this.paginationProcess, params);
} }
@Get(`:${option?.uniqueIdentifier}`) @Get(':id')
async read(@Param(`${option?.uniqueIdentifier}`) id) { async read(@Param('id') providedKey) {
return await ReadExecutor.bootstrap(this.readProcess, id); return await ReadExecutor.bootstrap(this.readProcess, providedKey);
} }
@Patch(`:${option?.uniqueIdentifier}`) @Patch(':id')
async update(@Param(`${option?.uniqueIdentifier}`) id, @Body() body) { async update(@Param('id') providedKey, @Body() body) {
return await UpdateExecutor.bootstrap(this.updateProcess, id, body); return await UpdateExecutor.bootstrap(
this.updateProcess,
providedKey,
body,
);
} }
}
return SkeletonCRUDController;
} }
// NOTES:
// - This method only works when return as `any`
// - I know this is not recommended but.... is there any way to pass custom unique identifier ?
// - Everyone still can use SkeletonCRUDController with no issue if don't want or don't like this approach, but... unique identifier must ID for sure and the type should either UUID, String or Number
// - Correct me if I wrong. I already read the main repository of NestJS and they use Reflect for passing some metadata ( I know how to do it ) but... it still not possible for dynamic unique identifier
// Known issue:
// - OpenAPI ( Swagger ) cannot read any decorator inside this
export const AutoCRUDController = (options?: ControllerOption): any => {
const uniqueIdentifier = `${options?.uniqueIdentifier ?? 'id'}`;
class CRUDController extends SkeletonCRUDController {
@Post()
async create(@Body() body): Promise<any> {
return await super.create(body);
}
@Delete(`:${uniqueIdentifier}`)
async delete(@Param(uniqueIdentifier) id) {
return await super.delete(id);
}
@Get('list')
async list() {
return await super.list();
}
@Get()
@UsePipes(new ValidationPipe({ transform: true }))
async pagination(@Query() params: PaginationParamDTO) {
return await super.pagination(params);
}
@Get(`:${uniqueIdentifier}`)
async read(@Param(uniqueIdentifier) id) {
return await super.read(id);
}
@Patch(`:${uniqueIdentifier}`)
async update(@Param(uniqueIdentifier) id, @Body() body) {
return await super.update(id, body);
}
}
return CRUDController;
};

View File

@ -1,7 +1,5 @@
import { getBaseController } from '@aditama-labs/nest-autocrud/skeleton'; import { AutoCRUDController } from '@aditama-labs/nest-autocrud/skeleton';
import { Controller } from '@nestjs/common'; import { Controller } from '@nestjs/common';
@Controller('example/custom') @Controller('example/custom')
export class CustomController extends getBaseController({ export class CustomController extends AutoCRUDController() {}
uniqueIdentifier: 'key',
}) {}

View File

@ -1,14 +1,7 @@
import { UniqueOverride } from '@aditama-labs/nest-autocrud/skeleton/src/decoratos/unique-override.decorator'; import { Controller } from '@nestjs/common';
import { Controller, Get } from '@nestjs/common'; import { AutoCRUDController } from 'libs';
import { getBaseController, SkeletonController, UNIQUE_IDENTIFIER } from 'libs';
@SkeletonController()
@Controller('example/simple') @Controller('example/simple')
export class SimpleController extends getBaseController() { export class SimpleController extends AutoCRUDController({
@UniqueOverride() uniqueIdentifier: 'username',
@Get('list') }) {}
async list(): Promise<any> {
console.log(Reflect.getOwnMetadata(UNIQUE_IDENTIFIER, this.constructor));
return super.list();
}
}