The NestJS Expandable Library is a powerful and flexible extension for NestJS applications, providing a generic pattern for resource expansion in REST APIs. It allows you to dynamically expand and include related resources in API responses, enhancing the flexibility of your API design.
- Dynamic Resource Expansion: Easily expand related resources in API responses using query parameters.
- Dynamic Field Selection: Easily select only the fields you want to get from the API responses using query parameters.
- Decorator-Based Configuration: Use decorators to mark classes and methods as expanders and expandable, simplifying configuration.
- Enhanced Metadata Handling: Improved handling of metadata allows for multiple decorators of the same type on the same target.
- Configuration and Customization: Configure and customize the library to suit your application's specific needs.
- Error Handling: Graceful handling of errors during expansion with customizable logging options.
- Tested and Reliable: Extensive unit tests ensure the reliability of the library.
yarn add @golevelup/nestjs-discovery @cisstech/nestjs-expand
-
- Decorate Expandable Endpoints
// user.controller.ts import { Controller, Get, NotFoundException } from '@nestjs/common' import { Expandable } from '@cisstech/nestjs-expand' import { UserDTO } from './user.dto' import { UserService } from './user.service' @Controller('users') export class UserController { constructor(private readonly userService: UserService) {} @Get(':id') @Expandable(UserDTO) async getById(@Param('id') id: string): Promise<UserDTO> { const user = await this.userService.getById(id) if (!user) { throw new NotFoundException(`User not found: ${id}`) } return new UserDTO(user) } }
-
- Implement Expander Services
// user.expander.ts import { Injectable, NotFoundException } from '@nestjs/common' import { ExpandContext, Expander, Expandable } from '@cisstech/nestjs-expand' import { UserDTO } from './user.dto' import { CustomerService } from './user.service' @Injectable() @Expander(UserDTO) export class UserExpander { constructor(private readonly customerService: CustomerService) {} async customer(context: ExpandContext<Request, UserDTO>): Promise<CustomerDTO> { const user = context.parent const customer = await this.customerService.getById(user.customerId) if (!customer) { throw new NotFoundException(`Customer not found: ${user.customerId}`) } return new CustomerDTO(customer) } }
-
- Register the controllers and expanders
// app.module.ts
import { Module } from '@nestjs/common'
import { NestKitExpandModule } from '@cisstech/nestjs-expand'
import { UserExpander } from 'PATH_TO_FILE'
import { UserController } from 'PATH_TO_FILE'
@Module({
imports: [NestKitExpandModule.forRoot()],
controllers: [UserController],
providers: [UserExpander],
})
export class AppModule {}
The library provides configuration options to customize its behavior. You can pass an optional configuration object when initializing the ExpandService in your module.
// app.module.ts
import { Module } from '@nestjs/common'
import { NestKitExpandModule } from '@cisstech/nestjs-expand'
import { UserExpander } from 'PATH_TO_FILE'
import { UserController } from 'PATH_TO_FILE'
@Module({
imports: [
NestKitExpandModule.forRoot({
enableLogging: true,
enableGlobalSelection: true,
}),
],
controllers: [UserController],
providers: [UserExpander],
})
export class AppModule {}
For detailed documentation, examples, and advanced usage, please refer to the official documentation at https://cisstech.github.io/nestkit/docs/nestjs-expand/getting-started
A presentation article is also available medium
MIT © Mamadou Cisse