@solid-nestjs/rest-api
Version:
solid-nestjs Rest-API utilities
301 lines • 14.9 kB
JavaScript
;
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