This package has been deprecated

Author message:

Package has moved to @travetto/rest

@travetto/express

0.2.2 • Public • Published

travetto: Express

The module provides a declarative API for creating and describing an express application. Since the framework is declarative, decorators are used to configure almost everything.

Route management

Controller

To define a route, you must first declare a @Controller which is only allowed on classes. Controllers can be configured with:

  • title - The definition of the controller
  • description - High level description fo the controller

JSDoc comments can also be used to define the title attribute.

Endpoints

Once the controller is declared, each method of the controller is a candidate for routing. By design, everything is asynchronous, and so async/await is natively supported.

The HTTP methods that are supported via:

  • @Get
  • @Post
  • @Put
  • @Delete
  • @Patch
  • @Head
  • @Options

Each endpoint decorator handles the following config:

  • title - The definition of the endpoint
  • description - High level description fo the endpoint
  • responseType? - Class describing the response type
  • requestType? - Class describing the request body

JSDoc comments can also be used to define the title attribute, as well as describing the parameters using @param tags in the comment.

Additionally, the annotated return type on the method will also be used to describe the responseType if specified.

Parameters

Endpoints can be configured to describe and enforce parameter behavior. Request parameters can be defined in three areas:

  • @PathParam
  • @QueryParam
  • @BodyParam

Each @*Param can be configured to indicate:

  • name - Name of param, field name
  • description - Description of param
  • required? - Is the field required?
  • type - The class of the type to be enforced

JSDoc comments can also be used to describe parameters using @param tags in the comment.

Example

A simple example is:

@Controller('/simple')
export class Simple {

  constructor(private service: MockService) {}

  /**
   * Get a random user by name
   */
  @Get('/name')
  async doIt(): string {
    const user = await this.service.fetch();
    return `/simple/name => ${user.first.toLowerCase()}`;
  }

  /**
   * Get a user by id
   */
  @Get('/:id')
  @PathParam({ name: 'id', type: Number })
  async doIt(req: Request): string {
    const user = await this.service.fetch(req.params.id);
    return `/simple/name => ${user.first.toLowerCase()}`;
  }


  @Post('/name')
  async doIt(req: Request) {
    const user = await this.service.update({ name: req.body.name });
    return { success : true };
  }

  @Get(/\/img(.*)[.](jpg|png|gif)/)
  @QueryParam({ name: 'w', type: Number })
  @QueryParam({ name: 'h', type: Number })
  async getImage(req: Request, res:Response) {
    const img =  await this.service.fetch(req.path, req.query);
    ... return image ...
  }
}

Additionally, the module is predicated upon Dependency Injection, and so all standard di techniques work on controllers.

NOTE in development mode the module supports hot reloading of classes. Routes can be added/modified/removed at runtime.

Input/Output

The module provides standard structure for rendering content on the response. This includes:

  • JSON
  • String responses
  • Files

Additionally, there is support for typing requests and request bodies. This can be utilized by other modules to handle special types of requests.

Express initialization

When working with express applications, the module provides what is assumed to be a sufficient set of basic filters. Specifically:

  • compression()
  • cookieParser()
  • bodyParser.json()
  • bodyParser.urlencoded()
  • bodyParser.raw({ type: 'image/*' })
  • session(this.config.session)

Additionally it is sometimes necessary to register custom filters. Filters can be registered with the Dependency Injection by extending the Operator class.

@Injectable({
  target: ExpressOperator,
  qualifier: AUTH
})
export class LoggingOperator extends ExpressOperator {
  operate(app: ExpressApp) {
    app.get().use(async (req, res, next) => {

      console.log(req.method, req.path, req.query);

      if (next) {
        next();
      }
    });
  }
}

Documentation

As shown above, the controllers and endpoints can be described via decorators, comments, or typings. This only provides the general metadata internally. To generate a usable API doc, a separate module should be used. Currently Swagger is the only module that exists, but other implementations should be available in the future.

Extensions

Integration with other modules can be supported by extensions. The dependencies are in optionalExtensionDependencies and must be installed directly if you want to use them:

Context

Context provides support for automatically injecting an async context into every request. The context management is provided via an Operator and is transparent to the programmer.

 ...
  @Post('/preferences')
  @SchemaBody(User)
  async save(req: TypedBody<Preferences>) {
    await this.service.update(req.body);
    return { success : true };
  }
 ...
 class PreferenceService {
   private context: Context;

   async update(prefs: Preferences) {
     const userId = this.context.get().userId;
     ... store preferences for user ...
     return;  
   }
 }

Package Sidebar

Install

npm i @travetto/express

Homepage

travetto.io

Weekly Downloads

1

Version

0.2.2

License

MIT

Unpacked Size

48.9 kB

Total Files

42

Last publish

Collaborators

  • arcsine