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
Fully working example can be found in example folder.
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);
HttpModule
- main module to start an application:
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 { }
ExpressAdapter
- adapter for express from@decorators/server/express
FastifyAdapter
- adapter for fastify from@decorators/server/fastify
KoaAdapter
- adapter for koa from@decorators/server/koa
Adapter can be instantiated with existing application (for example express application):
HttpModule.create(new ExpressAdapter(app));
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 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.
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 { }
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 { }
This module supports dependency injection provided by @decorators/di
package. For convinience, @decorators/server
reexports all decorators from @decorators/di
package.
@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 optionsoptions?.ignoreVersion
- ignore global version prefix (providedAPP_VERSION
), can be useful to setup global handlers, such as 404 handling
@Pipe(pipe: ClassConstructor<ProcessPipe>)
- Registers a pipe for a controller
@Pipe(pipe: ClassConstructor<ProcessPipe>)
- Registers a pipe for a method
-
@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
const app = await Application.create(AppModule);
const module = await app.inject<HttpModule>(HttpModule);
module.set('views', join(__dirname, '/views'));
@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
Package exports two main helpers to create custom decorators:
Decorate
- allows to create custom class or method decorators
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
import { createParamDecorator } from '@decorators/server';
function AccessParam() {
return createParamDecorator((context: HttpContext) => {
const req = context.getRequest<Request>();
return req.query.access;
});
}
// ...
create(@AccessParam() access: string) {}
Swagger decorators are available in
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 { }
@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.
@ApiParameter(parammeter: { description?: string })
- Specifies a description for a property defined in the class-decorator based classes
npm install socket.io --save
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;
}
}
If error occurres, system will send error
event to the client with an error object.
SocketIoAdapter
- adapter for socket.io from@decorators/server/socket-io
Validation works similarly to http module see validation section.
Pipes work similarly to http module see pipes section.
@Connection()
- Registersconnection
event.@Disconnect()
- Registersdisconnect
event@Disconnecting()
- Registersdisconnecting
event@Event(event: string)
- Register custom event. Returned data from the handler will be sent through Ack.
@Param(paramValidator?: Validator)
- Returns param sent viaemit
. Not available forconnection
,disconnect
anddisconnecting
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