JavaScripting

The definitive source of the best
JavaScript libraries, frameworks, and plugins.


  • ×

    Node Decorators

    node-decorators
    Filed under  › 

    • 🔾31%Overall
    • 375
    • 24.5 days
    • 🕩31
    • 👥13

    Node Decorators

    Http

    Installation

    Main dependencies

    npm install @decorators/server @decorators/di --save
    

    Adapter specific imports

    npm install express body-parser --save
    

    Or

    npm install fastify @fastify/cookie @fastify/static @fastify/view --save
    

    Or

    npm install koa koa-bodyparser koa-mount koa-static koa-views --save
    

    Example

    Fully working example can be found in example folder.

    Application

    In order to create an application, use Application class with app root module:

    const app = await Application.create(AppModule, server?);
    

    Application instance provides an inject method to retrieve instances of any provided objects:

    const app = await Application.create(AppModule);
    const module = await app.inject<HttpModule>(HttpModule);
    
    module.use(json());
    
    await module.listen(3000);
    

    Modules

    • HttpModule - main module to start an application: ```typescript import { Module } from '@decorators/server'; import { HttpModule } from '@decorators/server/http'; import { ExpressAdapter } from '@decorators/server/express';

    @Module({ modules: [ HttpModule.create(ExpressAdapter), ], }) export class AppModule { }

    
    ## Adapters
    * `ExpressAdapter` - adapter for [express](https://github.com/expressjs/express) from `@decorators/server/express`
    * `FastifyAdapter` - adapter for [fastify](https://github.com/fastify/fastify) from `@decorators/server/fastify`
    * `KoaAdapter` - adapter for [koa](https://github.com/koajs/koa) from `@decorators/server/koa`
    
    Adapter can be instantiated with existing application (for example express application):
    ```ts
    HttpModule.create(new ExpressAdapter(app));
    

    Payload vaidation

    Package supports class-validator and class-transformer packages, basic types validation is supported as well:

    @Get(':id', 200)
    post(@Params() user: UserDto) {
      return user;
    }
    

    Pipes

    Pipes allow to add additional "interceptors" before and after main route function. In order to implement a pipe import ProcessPipe interface and implement it:

    import { PipeHandle, ProcessPipe } from '@decorators/server';
    import { HttpContext } from '@decorators/server/http';
    
    export class TransformPipe implements ProcessPipe {
      async run(context: HttpContext, handle: PipeHandle<string>) {
        const message = await handle();
    
        return message.toLocaleString();
      }
    }
    

    Add @Pipe decorator to the method or to entire controller:

    @Pipe(TransformPipe)
    process(@Body() body: object)
    

    Pipes can be used both for controller and methods.

    Injectables

    Global server pipes can be applied by providing them via GLOBAL_PIPE injectable with multi (see di package for details) flag:

    import { GLOBAL_PIPE, Module } from '@decorators/server';
    
    @Module({
      providers: [
        {
          provide: GLOBAL_PIPE,
          useClass: ServerPipe,
          multi: true,
        },
      ],
    })
    export class AppModule { }
    

    App prefix

    To create global application prefix (aka version, namespace) use APP_VERSION injectable:

    import { APP_VERSION, Module } from '@decorators/server';
    
    @Module({
      providers: [
        {
          provide: APP_VERSION,
          useValue: 'v1',
        },
      ],
    })
    export class AppModule { }
    

    Dependency injection

    This module supports dependency injection provided by @decorators/di package. For convinience, @decorators/server reexports all decorators from @decorators/di package.

    Decorators

    Class

    • @Module(options: ModuleOptions) - Defines a module (namespace) for DI providers, controllers etc.
    • @Controller(url: string, options?: Record<string, unknown>) - Registers controller for base url with optional options
      • options?.ignoreVersion - ignore global version prefix (provided APP_VERSION), can be useful to setup global handlers, such as 404 handling
    • @Pipe(pipe: ClassConstructor<ProcessPipe>) - Registers a pipe for a controller

    Method

    • @Pipe(pipe: ClassConstructor<ProcessPipe>) - Registers a pipe for a method

    @decorators/server/http

    • @Delete(url: string, status?: number) - Registers delete route
    • @Get(url: string, status?: number) - Registers get route
    • @Head(url: string, status?: number) - Registers head route
    • @Options(url: string, status?: number) - Registers options route
    • @Patch(url: string, status?: number) - Registers patch route
    • @Post(url: string, status?: number) - Registers post route
    • @Put(url: string, status?: number) - Registers put route

    • @Render(template: string) - Renders a template in the configured views folder ```typescript const app = await Application.create(AppModule); const module = await app.inject(HttpModule);

    module.set('views', join(__dirname, '/views'));

    
    ### Parameter
    * `@Body(paramName?: string, paramValidator?: Validator)` - Request body object or single body param
    * `@Cookies(paramName?: string, paramValidator?: Validator)` - Request cookies or single cookies param
    * `@Headers(paramName?: string, paramValidator?: Validator)` - Request headers object or single headers param
    * `@Params(paramName?: string, paramValidator?: Validator)` -  Request params object or single param
    * `@Query(paramName?: string, paramValidator?: Validator)` - Request query object or single query param
    * `@Request(paramName?: string)` - Returns request object or any other object available in req object itself
    * `@Response(paramName?: string)` - Returns response object or any other object available in response object itself
    
    ## Custom Decorators
    Package exports two main helpers to create custom decorators:
    * `Decorate` - allows to create custom class or method decorators
    ```typescript
    import { Decorate } from '@decorators/server';
    // ...
    @Decorate('hasAccess', 'granted')
    create() {}
    

    To read custom metadata use Reflector injectable and its getMeatada method:

    @Injectable()
    export class AccessPipe implements ProcessPipe {
      constructor(private reflector: Reflector) { }
    
      async run(context: HttpContext, handle: PipeHandle<string>) {
        const access = this.reflector.getMetadata('hasAccess', context.getHandler());
        const req = context.getRequest<Request>();
    
        if (access === req.query.access) {
          return handle();
        }
    
        throw new ApiError('unauthorized');
      }
    }
    
    • createParamDecorator(factory: (context: Context) => any) - allows to create custom parameter decorators ```typescript import { createParamDecorator } from '@decorators/server';

    function AccessParam() { return createParamDecorator((context: HttpContext) => { const req = context.getRequest();

    return req.query.access;
    

    }); }

    // ... create(@AccessParam() access: string) {}

    
    ---
    
    # Swagger
    Swagger decorators are available in
    ```typescript
    import { SwaggerModule } from '@decorators/server/swagger';
    

    To start with swagger decorators provide SwaggerModule in the AppModule, for example:

    import { SwaggerModule } from '@decorators/server/swagger';
    
    @Module({
      modules: [
        HttpModule.create(ExpressAdapter),
        SwaggerModule.forRoot({
          description: 'Decorators Example App',
          title: '@decorators/server',
        }),
        ...
      ],
    })
    export class AppModule { }
    

    Decorators

    Method

    • @ApiOperation(operation: OpenAPIV3_1.OperationObject) - Registers an operation
    • @ApiResponse(description: string, type?: ClassConstructor) - Registers simple response for a method. This decorator uses status provided by the route decorator, e.g. @Get(route, status).
    • @ApiResponseSchema(responses: ApiResponses) - Registers a response for a method. This method accepts more complex types of responses, if method returns more than one.
    • @ApiBearerAuth() - Defines a bearer authentication method for a route
    • @ApiSecurity(security: OpenAPIV3_1.SecuritySchemeObject) - Defines more complex authentication methods for a route.

    Property

    • @ApiParameter(parammeter: { description?: string }) - Specifies a description for a property defined in the class-decorator based classes

    Sockets

    Installation

    npm install socket.io --save
    

    Setup

    To start provide SocketsModule with one of the provided adapters

    import { Module } from '@decorators/server';
    import { SocketsModule } from '@decorators/server/sockets';
    import { SocketIoAdapter } from '@decorators/server/socket-io';
    
    @Module({
      modules: [
        SocketsModule.create(SocketIoAdapter),
      ],
    })
    export class AppModule { }
    

    Inject SocketsModule to start listeners

    const app = await Application.create(AppModule);
    const module = await app.inject<SocketsModule>(SocketsModule);
    
    await module.listen();
    

    Add a controller

    import { Controller } from '@server';
    import { Connection, Disconnect, Event, Param } from '@server/sockets';
    
    @Controller()
    export class EventsController {
      @Connection()
      connection() { }
    
      @Disconnect()
      disconnect() { }
    
      @Event('message')
      event(@Param() message: MessageType) {
        return message;
      }
    }
    

    Errors

    If error occurres, system will send error event to the client with an error object.

    Adapters

    • SocketIoAdapter - adapter for socket.io from @decorators/server/socket-io

    Payload vaidation

    Validation works similarly to http module see validation section.

    Pipes

    Pipes work similarly to http module see pipes section.

    Decorators

    Method

    • @Connection() - Registers connection event.
    • @Disconnect() - Registers disconnect event
    • @Disconnecting() - Registers disconnecting event
    • @Event(event: string) - Register custom event. Returned data from the handler will be sent through Ack.

    Parameter

    • @Param(paramValidator?: Validator) - Returns param sent via emit. Not available for connection, disconnect and disconnecting events. Multiple params can be used to receive all the params:

      message(
      @Param() message1: string,
      @Param() message2: string,
      ) { }
      
    • @Server() - Returns server object

    • @Socket() - Returns socket object
    Show All