UNPKG

nestjs-prisma-base

Version:

A reusable NestJS module for Prisma ORM with base classes for controller, service and DTOs

277 lines (217 loc) 7.43 kB
# NestJS Prisma Base A reusable NestJS module for Prisma ORM with base classes for controllers, services, and DTOs. ## Installation ```bash npm install nestjs-prisma-base ``` ## Features - Ready-to-use Prisma module with proper lifecycle management - Base service with common CRUD operations - Base controller with configurable REST endpoints - Base DTOs for standardizing request/response data - Utility decorators for easier implementation - Factory functions to auto-generate components from Prisma models - Selective endpoint activation for precise API control ## Usage ### Option 1: Extending Base Classes (Manual Approach) #### 1. Import the PrismaModule in your app module ```typescript import { Module } from '@nestjs/common'; import { PrismaModule } from 'nestjs-prisma-base'; @Module({ imports: [ PrismaModule.forRoot(), // Your other modules ], }) export class AppModule {} ``` #### 2. Create your entity DTOs by extending the base DTOs ```typescript // user.dto.ts import { BaseCreateDto, BaseUpdateDto, BaseResponseDto } from 'nestjs-prisma-base'; import { IsEmail, IsString, IsOptional } from 'class-validator'; export class CreateUserDto extends BaseCreateDto { @IsString() name: string; @IsEmail() email: string; @IsString() password: string; } export class UpdateUserDto extends BaseUpdateDto { @IsString() @IsOptional() name?: string; @IsEmail() @IsOptional() email?: string; } export class UserResponseDto extends BaseResponseDto { name: string; email: string; } ``` #### 3. Create your service by extending the base service ```typescript // user.service.ts import { Injectable } from '@nestjs/common'; import { BaseService, ModelName, PrismaService } from 'nestjs-prisma-base'; import { User } from '@prisma/client'; import { CreateUserDto, UpdateUserDto } from './user.dto'; @Injectable() @ModelName('user') export class UserService extends BaseService<User, CreateUserDto, UpdateUserDto> { constructor(prisma: PrismaService) { super(prisma); } // Add custom methods here } ``` #### 4. Create your controller by extending the base controller with endpoint configuration ```typescript // user.controller.ts import { Controller } from '@nestjs/common'; import { BaseController, EnableEndpoint, EndpointType, EnableAllEndpoints, DisableEndpoint } from 'nestjs-prisma-base'; import { User } from '@prisma/client'; import { UserService } from './user.service'; import { CreateUserDto, UpdateUserDto } from './user.dto'; @Controller('users') // Option 1: Enable specific endpoints @EnableEndpoint(EndpointType.FIND_ALL) @EnableEndpoint(EndpointType.FIND_ONE) @EnableEndpoint(EndpointType.CREATE) // Option 2: Enable all endpoints at once // @EnableAllEndpoints() // Option 3: Enable all except specific ones // @EnableAllEndpoints() // @DisableEndpoint(EndpointType.REMOVE) export class UserController extends BaseController<User, CreateUserDto, UpdateUserDto> { constructor(private readonly userService: UserService) { super(userService); } // Add custom endpoints here // Don't forget to enable your custom endpoints! @EnableEndpoint('findByEmail') @Get('by-email/:email') findByEmail(@Param('email') email: string) { return this.userService.findByEmail(email); } } ``` ### Option 2: Using Factory Functions (Auto-Generated Approach) #### 1. Generate an entire module for a model with configurable endpoints ```typescript // user.module.ts import { createModelModule, EndpointType } from 'nestjs-prisma-base'; // Option 1: Create module with specific enabled endpoints export const UserModule = createModelModule({ modelName: 'user', routePath: 'users', enabledEndpoints: [EndpointType.FIND_ALL, EndpointType.FIND_ONE, EndpointType.CREATE], }); // Option 2: Create module with all endpoints enabled export const ProductModule = createModelModule({ modelName: 'product', enableAllEndpoints: true, }); // Option 3: Create module with custom service export const CategoryModule = createModelModule({ modelName: 'category', enableAllEndpoints: true, serviceType: CategoryService, // Your custom service class providers: [ /* Additional providers */ ], imports: [ /* Additional imports */ ], exports: [ /* Additional exports */ ], }); ``` #### 2. Import the generated module in your app module ```typescript // app.module.ts import { Module } from '@nestjs/common'; import { PrismaModule } from 'nestjs-prisma-base'; import { UserModule } from './user.module'; @Module({ imports: [ PrismaModule.forRoot(), UserModule, // Other modules ], }) export class AppModule {} ``` ## Endpoint Configuration **Important: By default, all endpoints are disabled for security reasons.** In version 0.2.0 and above, you must explicitly enable each endpoint you want to expose. This provides better security and control over your API surface. ### Available Endpoint Types ```typescript export enum EndpointType { FIND_ALL = 'findAll', // GET /resource FIND_ONE = 'findOne', // GET /resource/:id CREATE = 'create', // POST /resource UPDATE = 'update', // PATCH /resource/:id REMOVE = 'remove', // DELETE /resource/:id } ``` ### Swagger Integration When using this package with Swagger documentation, endpoints that are disabled will be automatically hidden from the Swagger UI. This is accomplished through the `ApiExcludeDisabledEndpoint` decorator that's applied to all standard endpoints in the `BaseController`. If you're creating custom endpoints, you can use the decorator to hide them from Swagger when they're disabled: ```typescript @Get('custom-endpoint') @ApiExcludeDisabledEndpoint('customEndpoint') customEndpoint() { if (!this.isEndpointEnabled('customEndpoint')) { throw new NotFoundException('Endpoint not available'); } // Your implementation } ``` This requires the `@nestjs/swagger` package to be installed in your project. ### Enabling Endpoints with Decorators You can enable endpoints at the controller level: ```typescript @Controller('users') @EnableEndpoint(EndpointType.FIND_ALL) @EnableEndpoint(EndpointType.FIND_ONE) export class UserController extends BaseController<User, CreateUserDto, UpdateUserDto> { // ... } ``` Or enable all endpoints at once: ```typescript @Controller('users') @EnableAllEndpoints() export class UserController extends BaseController<User, CreateUserDto, UpdateUserDto> { // ... } ``` ### Disabling Specific Endpoints You can disable specific endpoints even when using `@EnableAllEndpoints()`: ```typescript @Controller('users') @EnableAllEndpoints() @DisableEndpoint(EndpointType.REMOVE) export class UserController extends BaseController<User, CreateUserDto, UpdateUserDto> { // ... } ``` ### Enabling Method-Level Endpoints You can also selectively enable endpoints at the method level: ```typescript @Controller('users') export class UserController extends BaseController<User, CreateUserDto, UpdateUserDto> { // Only this method will be available @EnableEndpoint('findAdmins') @Get('admins') findAdmins() { return this.userService.findAdmins(); } } ``` ## License MIT