UNPKG

@solid-nestjs/rest-api

Version:

solid-nestjs Rest-API utilities

301 lines 14.9 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CrudControllerFrom = CrudControllerFrom; const common_1 = require("@nestjs/common"); const swagger_1 = require("@nestjs/swagger"); const common_2 = require("@solid-nestjs/common"); const decorators_1 = require("../decorators"); const data_controller_mixin_1 = require("./data-controller.mixin"); /** * Generates a CRUD controller class based on the provided structure and configuration. * * This mixin function dynamically creates a controller class with standard CRUD endpoints * (`create`, `update`, `remove`, and optionally `hardRemove`) for a given entity type. * The generated controller methods are decorated with NestJS and Swagger decorators for * routing, validation, and API documentation. Methods can be selectively enabled or disabled * via the `controllerStructure.operations` configuration. * * @param controllerStructure - The configuration object describing the entity, input types, * service, decorators, and operation settings for the controller. * * @returns A NestJS controller class with CRUD endpoints for the specified entity. * * @remarks * - The `hardRemove` method is disabled by default unless explicitly enabled. * - Supports custom parameter decorators and pipe transforms for the entity ID. * - Integrates with Swagger for API documentation. */ function CrudControllerFrom(controllerStructure) { const { entityType, createInputType, updateInputType } = controllerStructure; const ContextDecorator = controllerStructure.parameterDecorators?.context ?? common_2.CurrentContext; let idType = Number; let pipeTransforms = [common_1.ParseIntPipe]; if (controllerStructure.entityId) { idType = controllerStructure.entityId.type; pipeTransforms = controllerStructure.entityId.pipeTransforms ?? []; } const createSettings = (0, data_controller_mixin_1.extractOperationSettings)(controllerStructure.operations?.create, { disabled: controllerStructure.operations?.create === false, route: undefined, summary: 'Create ' + entityType.name.toLowerCase() + ' record', description: 'creation of ' + entityType.name.toLowerCase() + ' record', successCode: common_1.HttpStatus.CREATED, errorCodes: [common_1.HttpStatus.BAD_REQUEST], }); const updateSettings = (0, data_controller_mixin_1.extractOperationSettings)(controllerStructure.operations?.update, { disabled: controllerStructure.operations?.update === false, route: ':id', summary: 'Update ' + entityType.name.toLowerCase() + ' record', description: 'update of ' + entityType.name.toLowerCase() + ' record', successCode: common_1.HttpStatus.ACCEPTED, errorCodes: [common_1.HttpStatus.BAD_REQUEST, common_1.HttpStatus.NOT_FOUND], }); const removeSettings = (0, data_controller_mixin_1.extractOperationSettings)(controllerStructure.operations?.remove, { disabled: controllerStructure.operations?.remove === false, route: ':id', summary: 'Remove ' + entityType.name.toLowerCase() + ' record', description: 'removal of ' + entityType.name.toLowerCase() + ' record', successCode: common_1.HttpStatus.ACCEPTED, errorCodes: [common_1.HttpStatus.BAD_REQUEST, common_1.HttpStatus.NOT_FOUND], }); const hardRemoveSettings = (0, data_controller_mixin_1.extractOperationSettings)(controllerStructure.operations?.hardRemove, { disabled: !controllerStructure.operations?.hardRemove, route: 'hard/:id', summary: 'Remove (HARD) ' + entityType.name.toLowerCase() + ' record', description: 'removal (HARD) of ' + entityType.name.toLowerCase() + ' record', successCode: common_1.HttpStatus.ACCEPTED, errorCodes: [common_1.HttpStatus.BAD_REQUEST, common_1.HttpStatus.NOT_FOUND], }); const softRemoveSettings = (0, data_controller_mixin_1.extractOperationSettings)(controllerStructure.operations?.softRemove, { disabled: !controllerStructure.operations?.softRemove, route: 'soft/:id', summary: 'Soft remove ' + entityType.name.toLowerCase() + ' record', description: 'soft removal of ' + entityType.name.toLowerCase() + ' record', successCode: common_1.HttpStatus.ACCEPTED, errorCodes: [common_1.HttpStatus.BAD_REQUEST, common_1.HttpStatus.NOT_FOUND], }); const recoverSettings = (0, data_controller_mixin_1.extractOperationSettings)(controllerStructure.operations?.recover, { disabled: !controllerStructure.operations?.recover, route: 'recover/:id', summary: 'Recover ' + entityType.name.toLowerCase() + ' record', description: 'recovery of ' + entityType.name.toLowerCase() + ' record', successCode: common_1.HttpStatus.ACCEPTED, errorCodes: [common_1.HttpStatus.BAD_REQUEST, common_1.HttpStatus.NOT_FOUND], }); const paramApiConfig = { name: 'id', description: 'ID of the ' + entityType.name + ' entity', required: true, }; class CrudControllerClass extends (0, data_controller_mixin_1.DataControllerFrom)(controllerStructure) { async create(context, createInput) { return this.service.create(context, createInput); } async update(context, id, updateInput) { return this.service.update(context, id, updateInput); } async remove(context, id) { return this.service.remove(context, id); } async hardRemove(context, id) { if (!(0, common_2.isSoftDeletableCrudService)(this.service)) throw new common_1.HttpException('Hard remove operation is not supported by this service', common_1.HttpStatus.NOT_IMPLEMENTED); return this.service.hardRemove(context, id); } async softRemove(context, id) { if (!(0, common_2.isSoftDeletableCrudService)(this.service)) throw new common_1.HttpException('Soft remove operation is not supported by this service', common_1.HttpStatus.NOT_IMPLEMENTED); return this.service.softRemove(context, id); } async recover(context, id) { if (!(0, common_2.isSoftDeletableCrudService)(this.service)) throw new common_1.HttpException('Recover operation is not supported by this service', common_1.HttpStatus.NOT_IMPLEMENTED); return this.service.recover(context, id); } } __decorate([ (0, common_1.Post)(createSettings.route), (0, common_2.applyMethodDecorators)(createSettings.decorators), (0, swagger_1.ApiOperation)({ summary: createSettings.summary, description: createSettings.description, operationId: createSettings.operationId, }), (0, swagger_1.ApiBody)({ type: createInputType, description: createSettings.description, required: true, isArray: false, }), (0, common_1.HttpCode)(createSettings.successCode), (0, decorators_1.ApiResponses)({ type: entityType, successCodes: createSettings.successCodes, errorCodes: createSettings.errorCodes, }), __param(0, ContextDecorator()), __param(1, (0, common_1.Body)(new common_1.ValidationPipe({ transform: true, expectedType: createInputType, whitelist: true, forbidNonWhitelisted: true, forbidUnknownValues: true, }))), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], CrudControllerClass.prototype, "create", null); __decorate([ (0, common_1.Put)(updateSettings.route), (0, common_2.applyMethodDecorators)(updateSettings.decorators), (0, swagger_1.ApiOperation)({ summary: updateSettings.summary, description: updateSettings.description, operationId: updateSettings.operationId, }), (0, swagger_1.ApiBody)({ type: updateInputType, description: updateSettings.description, required: true, isArray: false, }), (0, swagger_1.ApiParam)(paramApiConfig), (0, common_1.HttpCode)(updateSettings.successCode), (0, decorators_1.ApiResponses)({ type: entityType, successCodes: updateSettings.successCodes, errorCodes: updateSettings.errorCodes, }), __param(0, ContextDecorator()), __param(1, (0, common_1.Param)('id', ...pipeTransforms)), __param(2, (0, common_1.Body)(new common_1.ValidationPipe({ transform: true, expectedType: updateInputType, whitelist: true, forbidNonWhitelisted: true, forbidUnknownValues: true, }))), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object, Object]), __metadata("design:returntype", Promise) ], CrudControllerClass.prototype, "update", null); __decorate([ (0, common_1.Delete)(removeSettings.route), (0, common_2.applyMethodDecorators)(removeSettings.decorators), (0, swagger_1.ApiOperation)({ summary: removeSettings.summary, description: removeSettings.description, operationId: removeSettings.operationId, }), (0, swagger_1.ApiParam)(paramApiConfig), (0, common_1.HttpCode)(removeSettings.successCode), (0, decorators_1.ApiResponses)({ type: entityType, successCodes: removeSettings.successCodes, errorCodes: removeSettings.errorCodes, }), __param(0, ContextDecorator()), __param(1, (0, common_1.Param)('id', ...pipeTransforms)), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], CrudControllerClass.prototype, "remove", null); __decorate([ (0, common_1.Delete)(hardRemoveSettings.route), (0, common_2.applyMethodDecorators)(hardRemoveSettings.decorators), (0, swagger_1.ApiOperation)({ summary: hardRemoveSettings.summary, description: hardRemoveSettings.description, operationId: hardRemoveSettings.operationId, }), (0, swagger_1.ApiParam)(paramApiConfig), (0, common_1.HttpCode)(hardRemoveSettings.successCode), (0, decorators_1.ApiResponses)({ type: entityType, successCodes: hardRemoveSettings.successCodes, errorCodes: hardRemoveSettings.errorCodes, }), __param(0, ContextDecorator()), __param(1, (0, common_1.Param)('id', ...pipeTransforms)), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], CrudControllerClass.prototype, "hardRemove", null); __decorate([ (0, common_1.Delete)(softRemoveSettings.route), (0, common_2.applyMethodDecorators)(softRemoveSettings.decorators), (0, swagger_1.ApiOperation)({ summary: softRemoveSettings.summary, description: softRemoveSettings.description, operationId: softRemoveSettings.operationId, }), (0, swagger_1.ApiParam)(paramApiConfig), (0, common_1.HttpCode)(softRemoveSettings.successCode), (0, decorators_1.ApiResponses)({ type: entityType, successCodes: softRemoveSettings.successCodes, errorCodes: softRemoveSettings.errorCodes, }), __param(0, ContextDecorator()), __param(1, (0, common_1.Param)('id', ...pipeTransforms)), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], CrudControllerClass.prototype, "softRemove", null); __decorate([ (0, common_1.Patch)(recoverSettings.route), (0, common_2.applyMethodDecorators)(recoverSettings.decorators), (0, swagger_1.ApiOperation)({ summary: recoverSettings.summary, description: recoverSettings.description, operationId: recoverSettings.operationId, }), (0, swagger_1.ApiParam)(paramApiConfig), (0, common_1.HttpCode)(recoverSettings.successCode), (0, decorators_1.ApiResponses)({ type: entityType, successCodes: recoverSettings.successCodes, errorCodes: recoverSettings.errorCodes, }), __param(0, ContextDecorator()), __param(1, (0, common_1.Param)('id', ...pipeTransforms)), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], CrudControllerClass.prototype, "recover", null); //remove controller methods if they are disabled in the structure if (createSettings.disabled) { delete CrudControllerClass.prototype.create; } if (updateSettings.disabled) { delete CrudControllerClass.prototype.update; } if (removeSettings.disabled) { delete CrudControllerClass.prototype.remove; } //this method is disabled by default if (hardRemoveSettings.disabled) { delete CrudControllerClass.prototype.hardRemove; } //softRemove and recover are enabled by default if not explicitly disabled if (softRemoveSettings.disabled) { delete CrudControllerClass.prototype.softRemove; } if (recoverSettings.disabled) { delete CrudControllerClass.prototype.recover; } return (0, common_1.mixin)(CrudControllerClass); } //# sourceMappingURL=crud-controller.mixin.js.map