Skip to content
This repository has been archived by the owner on Mar 12, 2024. It is now read-only.

Commit

Permalink
Replace express with fastify (#50)
Browse files Browse the repository at this point in the history
* Add fastify as http engine

* Change schema storage and processing

* Set and update schema compiler

* Add query dto decorator

* Adjust controller for fastify

* Adjust tests to new handling model

* Ignore typings for test

* Remove unused deps

* Return send function

* Rebase tests for reply body
  • Loading branch information
DanTsk authored Dec 16, 2018
1 parent ba8792a commit d738440
Show file tree
Hide file tree
Showing 25 changed files with 285 additions and 680 deletions.
663 changes: 142 additions & 521 deletions package-lock.json

Large diffs are not rendered by default.

11 changes: 4 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@
"license": "MIT",
"devDependencies": {
"@types/chai": "^4.1.7",
"@types/express": "^4.16.0",
"@types/mocha": "^5.2.5",
"autocannon": "^3.2.0",
"chai": "^4.2.0",
"fastify": "^1.13.1",
"istanbul": "^0.4.5",
"mocha": "^5.2.0",
"node-mocks-http": "^1.7.3",
Expand All @@ -46,27 +46,24 @@
},
"dependencies": {
"@types/ajv": "^1.0.0",
"@types/cookie-parser": "^1.4.1",
"@types/express": "^4.16.0",
"@types/glob": "^7.1.1",
"@types/jsonwebtoken": "^7.2.8",
"@types/node": "^10.12.12",
"@types/reflect-metadata": "^0.1.0",
"@types/shortid": "0.0.29",
"@types/socket.io": "^1.4.38",
"ajv": "^6.6.1",
"body-parser": "^1.18.3",
"chalk": "^2.4.1",
"cookie-parser": "^1.4.3",
"express": "^4.16.4",
"fastify-cookie": "^2.1.4",
"glob": "^7.1.3",
"reflect-metadata": "^0.1.12",
"shortid": "^2.2.14"
},
"optionalDependencies": {
"socket.io": "^2.1.1",
"typeorm": "^0.2.8",
"jsonwebtoken": "^8.4.0"
"jsonwebtoken": "^8.4.0",
"fastify": "^1.13.1"
},
"nyc": {
"include": [
Expand Down
26 changes: 20 additions & 6 deletions src/aliases.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
import { Response as ERes, Request as EReq } from 'express';
import { Server, IncomingMessage, ServerResponse} from 'http'

export { Request, Response, RequestHandler } from 'express';
export type Context = {
request: EReq,
response: ERes
};
import {
FastifyRequest,
FastifyReply,
RequestHandler as FastifyRequestHandler,
FastifyMiddleware
} from 'fastify';

export type RequestHandler = FastifyRequestHandler<IncomingMessage, ServerResponse>;

export type RequestMiddleware = FastifyMiddleware<Server, IncomingMessage, ServerResponse>;

export type Request = FastifyRequest<IncomingMessage>;

export type Response = FastifyReply<ServerResponse>;

export interface Context {
request: Request;
response: Response;
}
1 change: 0 additions & 1 deletion src/auth/local/auth.container.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Request } from "express";
import { CoreAuth } from "./auth.interface";
import { SignOptions, VerifyOptions, DecodeOptions } from "./auth.types";

Expand Down
3 changes: 1 addition & 2 deletions src/auth/local/auth.interface.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Request, Context } from '../../aliases';
import { UserData } from './auth.container';
import { SignOptions, VerifyOptions, DecodeOptions } from './auth.types';

export abstract class CoreAuth<T extends object, U>{
protected secret: string;
protected container: string | undefined;
Expand All @@ -18,7 +17,7 @@ export abstract class CoreAuth<T extends object, U>{
}

private extractToken(ctx: Request, container: string = this.container = "authorization"){
const header = ctx.get(container);
const header = ctx.headers[container];

let def;
if(header){
Expand Down
21 changes: 11 additions & 10 deletions src/core/server.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import * as express from 'express';
import * as fastify from 'fastify';
import * as cookie from 'fastify-cookie'

import * as bodyparser from 'body-parser';
import * as cookieparser from 'cookie-parser';

import { Application } from 'express';
import { FastifyInstance } from 'fastify';
import { createServer, Server as HttpServer } from 'http';

import { ConnectionOptions } from "typeorm";
import { CoreAuth } from '../auth/local/auth.interface';
import { DB_CONNECTION } from '../definitions';
import { DependencyManager } from '../dependency/dependency.manager';
import DependencyComposer from '../dependency/dependency.composer';
import { GAJV } from '../dto/dto.storage';


export interface CoreOptions{
Expand Down Expand Up @@ -42,7 +41,7 @@ export class Core{

protected options: CoreOptions;
protected server: HttpServer;
protected app: Application;
protected app: FastifyInstance;


protected auth: typeof CoreAuth;
Expand All @@ -52,7 +51,10 @@ export class Core{
this.options = options;
this.dependencyComposer = new DependencyComposer();

this.app = express();
this.app = fastify();

// Explicitly set AJV as schema compiler
this.app.setSchemaCompiler(shema => GAJV.compile(shema))
}

private async setUp(): Promise<any>{
Expand All @@ -67,14 +69,13 @@ export class Core{
await this.loadDependencies();
this.afterDependeciesLoad();

this.server = createServer(this.app);
this.server = this.app.server;
}

protected afterDependeciesLoad(){};

protected setMiddleware(): void{
this.app.use(bodyparser.json(), bodyparser.urlencoded({ extended: true }));
this.app.use(cookieparser());
this.app.register(cookie);
}

protected async setDatabase(): Promise<any> {
Expand Down
1 change: 1 addition & 0 deletions src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const INJECT_ID = `${naming}_inject_id`;

/* DTO */
export const DATA_CLASS = `${naming}_data_class`;
export const QUERY_CLASS = `${naming}_query_class`
export const DATA_VALIDATION_PROP = `${naming}_data_validation`

/* Auth */
Expand Down
6 changes: 2 additions & 4 deletions src/dependency/dependency.manager.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { Application } from "express";

import { AuthLoader } from "../auth/local/auth.loader";
import { AUTH, CONTROLLER, REPOSITORY, SERVICE, SOCKET } from "../definitions";
import { RepositoryLoader } from "../respositories/repository.loader";
import { ControllersLoader } from "../routing/controllers/controller.loader";
import { ServicesLoader } from "../services/services.loader";
import { ILoader, inject } from "../utils/directory.loader";
import DependencyComposer from "./dependency.composer";
import { FastifyInstance } from "fastify";

export enum DepType{
Controller = 1,
Expand All @@ -19,7 +18,7 @@ export enum DepType{

export interface Options{
rootPath : string
app : Application,
app : FastifyInstance,
dependencyComposer: DependencyComposer
}

Expand Down Expand Up @@ -88,7 +87,6 @@ export class DependencyManager {
}
}


private getType(target: any): DepType{
let belongsTo = this.getRefer(target);

Expand Down
19 changes: 13 additions & 6 deletions src/dto/dto.decorators.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
import * as shortid from 'shortid';

import { ValidateFunction } from 'ajv';
import { DATA_CLASS, DATA_VALIDATION_PROP } from "../definitions";
import { DATA_CLASS, DATA_VALIDATION_PROP, QUERY_CLASS } from "../definitions";
import { ValidatorFormat } from "./dto.type";
import { buildSchema } from "./dto.validator";
import { DtoPropsStorage, getSchema, GAJV, DtoPropsTypes } from "./dto.storage";


export function Data(): ClassDecorator {
function dtoFactory(key: string) {
return (target: any) => {
Reflect.defineMetadata(DATA_CLASS, true, target);
Reflect.defineMetadata(key, true, target);

/* Build schema and write to global DTO */
// Build schema and write to global DTO
buildSchema(target);
}
};
}

export function Data(): ClassDecorator {
return dtoFactory(DATA_CLASS);
}

export function Query(): ClassDecorator {
return dtoFactory(QUERY_CLASS);
}

export function validationFactory(object: any): PropertyDecorator {
Expand Down
17 changes: 11 additions & 6 deletions src/dto/dto.storage.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import { ValidateFunction } from 'ajv';
import * as ajv from 'ajv';

import { Ajv } from 'ajv';
import { isObject } from 'util';


export const GAJV = require('ajv')({ allErrors: true });
export const GAJV: Ajv = ajv({
removeAdditional: true,
useDefaults: true,
coerceTypes: true
});

export const DtoSchemaStorage = new WeakMap<object, ValidateFunction>();
export const DtoSchemaStorage = new WeakMap<object, object>();
export const DtoPropsStorage = new WeakMap<object, (string | symbol)[]>();

/* Perfably */
// Perfably
export const DtoPropsTypes = new WeakMap<object, { [key: string]: any }>();


export const getSchema = (target: any) => DtoSchemaStorage.has(target) ? DtoSchemaStorage.get(target)!.schema : {};
export const getSchema = (target: any) => DtoSchemaStorage.has(target) ? DtoSchemaStorage.get(target)! : {};

export function getDtoProps(prototype: any): any[]{
if(!prototype || !isObject(prototype)){
Expand Down
6 changes: 3 additions & 3 deletions src/dto/dto.validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { reflectType } from "../utils/directory.loader";
import { DATA_CLASS, DATA_VALIDATION_PROP } from "../definitions";
import { DtoSchemaStorage, getSchema, GAJV, getDtoProps } from "./dto.storage";
import { metadata } from "../utils/metadata.utils";
import { Ajv } from 'ajv';


function extractBase(type: any) {
Expand Down Expand Up @@ -64,12 +65,11 @@ export function buildSchema(target: any) {
};
}

const schema = {
const schema: object = {
properties,
$async: true,
required: requiredProperties
};

DtoSchemaStorage.set(target, GAJV.compile(schema));
DtoSchemaStorage.set(target, schema);
return schema;
}
6 changes: 4 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import 'reflect-metadata'

export { Core } from './core/server'


import { Core } from './core/server'
export { CoreAuth } from './auth/local/auth.interface'
export { UserData } from './auth/local/auth.container'

Expand All @@ -24,4 +26,4 @@ export { define, onInit } from './dependency/dependency.utils'
export * from './http/http.error'
export * from './aliases'

export * from './http'
export * from './http'
20 changes: 8 additions & 12 deletions src/routing/controllers/controller.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { CoreAuth } from "../../auth/local/auth.interface";
import { UserData } from "../../auth/local/auth.container";

import { Decoding, User } from "./controller.types";
import { CookieOptions } from "express";
import { CookieSerializeOptions } from "fastify";

export class IController<T = any>{
private authService: CoreAuth<Decoding<T>, User<T>>;
Expand Down Expand Up @@ -38,32 +38,28 @@ export class IController<T = any>{
}

getHeader(key: string) {
return this.request.get(key);
return this.request.headers[key];
}


/* Single set */
setCookie(key: string, value: string, options: CookieOptions = {}): void{
this.response.cookie(key, value, options);
setCookie(key: string, value: string, options: CookieSerializeOptions = {}): void{
this.response.setCookie(key, value, options);
}

setHeader(key: string, value: string){
this.response.set(key, value);
this.response.header(key, value);
}


/* Useful actions */
redirect(url: string){
return this.response.redirect(url)
}

render(template: string, params = {}){
return this.response.render(template, params);
redirect(url: string, code: number = 302){
return this.response.redirect(code, url)
}

/* Set status */
setStatus(status: number) {
return this.response.status(status);
return this.response.code(status);
}


Expand Down
Loading

0 comments on commit d738440

Please sign in to comment.