Giter Site home page Giter Site logo

tsedio / tsed Goto Github PK

View Code? Open in Web Editor NEW
2.7K 41.0 278.0 64.39 MB

:triangular_ruler: Ts.ED is a Node.js and TypeScript framework on top of Express to write your application with TypeScript (or ES6). It provides a lot of decorators and guideline to make your code more readable and less error-prone. ⭐️ Star to support our work!

Home Page: https://tsed.io/

License: MIT License

TypeScript 96.72% HTML 0.10% JavaScript 2.33% EJS 0.79% Shell 0.06%
typescript decorators nodejs lifecycle-hooks middleware ioc dependency-injection rest-api socket-io multer

tsed's Introduction

Ts.ED logo


Build & Release PR Welcome npm version semantic-release code style: prettier github opencollective

Website   •   Getting started   •   Slack   •   Twitter

A Node.js and TypeScript Framework on top of Express. It provides a lot of decorators and guidelines to write your code.

What it is

Ts.ED is a Node.js and TypeScript Framework on top of Express/Koa.js. Ts.ED is a framework on top of Express/Koa to write your application with TypeScript (or ES6). It provides a lot of decorators and guideline to make your code more readable and less error-prone.

Features

  • Use our CLI to create a new project https://cli.tsed.io
  • Support TypeORM, Mongoose, GraphQL, Socket.io, Swagger-ui, Passport.js, etc...
  • Define class as Controller,
  • Define class as Service (IoC),
  • Define class as Middleware and MiddlewareError,
  • Define class as Json Mapper (POJ to Model and Model to POJ),
  • Define root path for an entire controller and versioning your Rest API,
  • Define as sub-route path for a method,
  • Define routes on GET, POST, PUT, DELETE and HEAD verbs,
  • Define middlewares on routes,
  • Define required parameters,
  • Inject data from query string, path parameters, entire body, cookies, session or header,
  • Inject Request, Response, Next object from Express request,
  • Template (View),
  • Testing.

Links

Getting started

See our getting started here to create new Ts.ED project or use our CLI

Overview

Server example

Here an example to create a Server with Ts.ED:

import {Configuration, Inject} from "@tsed/di";
import {PlatformApplication} from "@tsed/common";
import "@tsed/platform-express";
import cookieParser from "cookie-parser";
import compress from "compress";
import methodOverride from "method-override";

@Configuration({
  port: 3000,
  middlewares: ["cookie-parser", "compression", "method-override", "json-parser", "urlencoded-parser"]
})
export class Server {}

To run your server, you have to use Platform API to bootstrap your application with the expected platform like Express.

import {$log} from "@tsed/common";
import {PlatformExpress} from "@tsed/platform-express";
import {Server} from "./Server";

async function bootstrap() {
  try {
    $log.debug("Start server...");
    const platform = await PlatformExpress.bootstrap(Server);

    await platform.listen();
    $log.debug("Server initialized");
  } catch (er) {
    $log.error(er);
  }
}

bootstrap();

To customize the server settings see Configure server with decorator

Controller example

This is a simple controller to expose user resource. It use decorators to build the endpoints:

import {Inject} from "@tsed/di";
import {Summary} from "@tsed/swagger";
import {
  Controller,
  Get,
  QueryParams,
  PathParams,
  Delete,
  Post,
  Required,
  BodyParams,
  Status,
  Put,
  Returns,
  ReturnsArray
} from "@tsed/common";
import {BadRequest} from "@tsed/exceptions";
import {UsersService} from "../services/UsersService";
import {User} from "../models/User";

@Controller("/users")
export class UsersCtrl {
  @Inject()
  private usersService: UsersService;

  @Get("/:id")
  @Summary("Get a user from his Id")
  @Returns(User)
  async getUser(@PathParams("id") id: string): Promise<User> {
    return this.usersService.findById(id);
  }

  @Post("/")
  @Status(201)
  @Summary("Create a new user")
  @Returns(User)
  async postUser(@Required() @BodyParams() user: User): Promise<User> {
    return this.usersService.save(user);
  }

  @Put("/:id")
  @Status(201)
  @Summary("Update the given user")
  @Returns(User)
  async putUser(@PathParams("id") id: string, @Required() @BodyParams() user: User): Promise<User> {
    if (user.id !== id) {
      throw new BadRequest("ID mismatch with the given payload");
    }

    return this.usersService.save(user);
  }

  @Delete("/:id")
  @Summary("Remove a user")
  @Status(204)
  async deleteUser(@PathParams("id") @Required() id: string): Promise<User> {
    await this.usersService.delete(user);
  }

  @Get("/")
  @Summary("Get all users")
  @Returns(200, Array).Of(User)
  async findUser(@QueryParams("name") name: string) {
    return this.usersService.find({name});
  }
}

Repository stats

Alt

Contributors

Please read contributing guidelines here.

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

License

The MIT License (MIT)

Copyright (c) 2016 - 2023 Romain Lenzotti

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

tsed's People

Contributors

abenerd avatar alex-dev avatar alexproca avatar camfou avatar dependabot[bot] avatar derevnjuk avatar einfachhans avatar emilienleroy avatar eugenepisotsky avatar jojoxd avatar klotztech avatar lamoglia avatar loic5 avatar lorianee avatar lwallent avatar matthiasferraina avatar milewski avatar nicojs avatar ochrstn avatar romakita avatar semantic-release-bot avatar stefanvanherwijnen avatar superkaleider avatar szauka avatar tomer-amir-vonage avatar troyanskiy avatar vincent178 avatar xcryzed avatar yanzolo avatar youssefsalameh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tsed's Issues

[Decorators] Use, UseBefore, UseAfter can be used on class

Status

Enhancement

Description

Use, UseBefore and UseAfter can be applied directly on a Controller.
All middlewares added on a Controller will be use by Express according to the context decorator.

Usage example

@Controller("/")
@UseBefore(myMiddlewareBefore)
@UseAfter(myMiddlewareAfter)
export MyClassCtrl {

}

Acceptance criteria

  • Use, UseBefore and UseAfter is added to the router (Express.Router)
  • UseBefore middlewares added to the controller. They are called before the endpoints of the controller.
  • Use middlewares are added for each endpoint and called just before the endpoint of the controller.
  • UseAfter middlewares added to the controller. They are called after the endpoints of the controller, if nothing response is sent.

[Decorator] EndpointInfo

EndpointInfo decorator provide info on the endpoint that called by an incoming Request.
With the new @Middleware decorator, it's necessary to give a decorator to retrieve the metadata stored on the method controller (endpoint).

Here use case:

import {IMiddleware, Middleware, ResponseData, Response, Endpoint, EndpointInfo} from "ts-express-decorators";
import * as Express from "express";
import {RESPONSE_VIEW, RESPONSE_VIEW_OPTIONS} from "../constants/metadata-keys";

@Middleware()
export default class ResponseViewMiddleware implements IMiddleware {

    public use(@ResponseData() data: any, @EndpointInfo() endpoint: Endpoint, @Response() response: Express.Response) {

        if (!response.headersSent) {
           return;
        }

        const viewPath = endpoint.getMetadata(RESPONSE_VIEW);
        const viewOptions = endpoint.getMetadata(RESPONSE_VIEW_OPTIONS);

        if (viewPath !== undefined) {

            if (viewOptions !== undefined ) {
                data = Object.assign({}, data, viewOptions);
            }

            response.render(viewPath, data);
        }

    }
}

@Controller('/test')
class TestCtrl {
     @Get('/')
     @ResponseView('page.html')
     public getHtml() {
           return {test: "Print test"}
     }
}

ResponseView decorator add the middleware ResponseViewMiddleware to the middlewares collections.

[Decorator] @Scope on Service

Hi,

Did you think about the implementation of something like Spring bean's scope (https://www.tutorialspoint.com/spring/spring_bean_scopes.htm) for services? Like the following:

@Service
@Scope('request')
export class BlaBlaService { ...

For example: default scope is a singleton which is a single instance per IoC container. But it's also possible to choose request scope where instance exists only in the context of current HTTP request.

It would be useful to store user profile data which was obtained in the middleware for example. Of course, data from middleware can be stored within express context as a param, but it's not very comfortable to provide type safety and it isn't object oriented way :)

Controller dependencies: add dependent Controller dynamically?

Hi,

I have a small server framework build on ts-express-decorators containing a generic abstract Controller implementation for the CRUD operations:

export abstract class ControllerBase<T, TId extends IToString> {

constructor(service: OvertimeService) {
        super(service, 'overtime', 'id');
    }


    @Authenticated()
    @Post('/')
    public create(
        @Request() request: Express.Request
        ): Promise<Overtime> {
        return super.createInternal(<Overtime>(<any>request).body);
    }
...
}

When I want to add some additional function to a concrete controller, what's the best way to do?
I have one solution based on dependent controller like:

@Controller('/query')
class QueryController {
    constructor(private service: OvertimeService) {
    }
    @Authenticated()
    @Post('/')
    public query(
        @Request() request: Express.Request
        ): Promise<Overtime[]> {
        let query = <IQuery> (<any>request).body;
        return this.service.query(query);
    }
}

@Controller('/overtime', QueryController)
export class OvertimeController extends ControllerBase<Overtime, number> {
...

But then I always have to implement this kind of code statically.

Is there a way to dynamically add a dependent controller with his corresponding route?

Or by adding a new decorator:

Example:

...
   @Authenticated()
   @Post('/query', OvertimeController)   
    public query(
        @Request() request: Express.Request
        ): Promise<Overtime[]> {
        let query = <IQuery> (<any>request).body;
        return this.service.query(query);
    }

Regards,
Walter

Use promise rejection as output message in controllers

AFAIK actually the promise rejection is not being user for anything, i notice it because i had to use the response object to set the error manually, but what about if the reject of the promise handles the user response, BTW the status code must have to be set manually but doing what i suggest will allow developers write less code

error TS2344: Type 'string | Function' does not satisfy the constraint 'object'.

Hi,

this morning I got this error after rebuilding my project from scratch:

.../server/node_modules/ts-express-decorators/dts/services/injector.d.ts(8,52): error TS2344: Type 'st
ring | Function' does not satisfy the constraint 'object'.
Type 'string' is not assignable to type 'object'.

I used typescript "^2.1.5".

After experimenting and doing some analysis I found that the problem seems to be related to ts 2.2.x.
When changing the typescript version to "2.1.5" (without caret) the error has gone.

Any idea?

Regards,
Walter

Add file definition to package.json

{
"name": "ts-express-decorators",
"version": "1.2.0-0",
"description": "Use TypeScript decorators to create your Express application and Rest API",
"main": "index.js",
"typings": "index.d.ts"
...
}
Need a new task to generate the index.d.ts.

[Decorator] Improve Required() decorator on Model deserialization

Status

Enhancement

Description

As a developer, I want to be able to Required decorator on a model Property.

Usage example

class Model {
   @Required()
   name: string;

   @Required()
   @Allow(null)
   obj: Object;
}

class ResponseModel {
   @Required()
   _id: string;

   @Required()
   name: string;

   @Required()
   @Allow(null)
   obj: Object;
}

class MyController {
    @Post("/")
    async save(@Required() @BodyParams() model: Model): Promise<ResponseModel> {
       return new ResponseModel() // will use to validate the structure and required value
    }
}

Acceptance criteria

  • Required can be used on model property
  • Required add bad request on swagger documentation
  • Model can be used on return type method
  • Allow decorator create value exception when Required is used

Get PathParams from controller path

Hello,

Currently I am setting up a api server with express-decorators and I am trying to use something like:

@controller('/:tenantid/projects')
export class ProjectController {
...

@Get('')
public getAll(@PathParams('tenantid') tenantid: string): ...

But this doesn't seems to work, the param 'tenantid' is undefined. Is there a way or pattern to have my routes configured like this ?

Grtz,

Peter

[Decorator] Session

@Get('/')
public get(@Session() session: ContextSession);
public get(@Session("userId") userId);

Support for `router.all`

Hello everyone,
Thanks again for this lib :)
I'm looking for a support for route-range-based authentication, something like this

app.all('admin/*', authenticate)

But I can't find a direct way with current router. So, is there a support for router.all or app.all?
I tried injecting both ExpressApplication and RouterController into $onMountingMiddlewares but in vain. All other hooks doesn't suit and I think a beforeControllerRoutesInit hook would be ideal for this use case.

Thanks.

$afterCtrlsInit vs $afterRoutesInit

server-loader.ts line 92:
const $afterRoutesInit = (this).$afterCtrlsInit || new Function; // TODO Fallback
i believe should be $afterRoutesInit on both sides, as the interface and documentation references $afterRoutesInit.

Option to autogenerate swagger

It would be nice to have the option to auto-generate an OpenAPI (swagger) definition on route mounting step and expose it at some configurable path with default value /openapi

question: global middleware for custom serialization

Hi,

I would like create some hook to perform custom serialization for incoming request data and outgoing response data like it's implemented in SendResponseMiddleware.

I experimented a little bit with global middleware, but with no success; I found no way to manipulate the data. Do you have some hint for me?

Regards,
Walter

A good way to inject service into middlewares

Hi @Romakita ,

is there a good way to inject service into middleware?

For example:

I have a middleware called currentUser, it's just a basic express middleware which receive three parameters: req, res, next. The currentUser aims to get the userId from session, and use UserService to get the user information.

[Decorator] Filter

Create filter to provide custom decorator for an endpoint method like @BodyParams or @Locals.

For example with bodyparams:

@Controller('/')
class MyClass {
    @Get('/')
    myMethod(@BodyParams('expresssion') value)
}

// filter
@Filter()
class BodyParamsFilter {
    constructor(private parseService: ParseService){}
    transform(expression, request, response) {
         return this.parse(expression, request);
    }
}

// decorator
function BodyParams(expression?: string | any, useType?: any): Function {

    return (target: any, propertyKey: string | symbol, parameterIndex: number): void => {

        if (typeof parameterIndex === "number") {

            ParamsRegistry.useFilter(BodyParamsFilter,  {
                target,
                propertyKey,
                parameterIndex,
                expression,
                useType
            });
        }
    };
}

[Decorator] Response formatting

@ResponseSet(headers) let you to configure response header from annotation.

@Controller("/calendars")
export class CalendarCtrl {

    @Get("/:id")
    @ResponseSet({"Content-Type": "application/json", status: 200})
    public get(): ICalendar {

        return <ICalendar> {id: request.params.id, name: "test"};
    }
// or
    @Get("/:id")
    @ResponseSet("Content-Type",  "application/json")
    @ResponseSet("status",  200)
    public get(): ICalendar {

        return <ICalendar> {id: request.params.id, name: "test"};
    }
}

Annotation's name is a proposal. If you have a better idea of name, tell-it !

[Decorator] Templating decorator (Jade, EJS, etc...)

@ResponseView(partialName) decorator use the render express method to send the response using the template HTML (or ejs, jade, etc...). In addition, the data returned by the method, will be used by ResponseView to provide the final HTML response (or any other format).

@Controller("/events")
export class EventCtrl {

    @Get("/:id")
    @ResponseView("eventCard")
    public get(request: Express.Request, response: Express.Response): any {
        return {startDate: new Date(), name: "MyEvent"};
    }
}

eventCard => views/eventCard.html

Annotation's name is a proposal. If you have a better idea of name, tell-it !

Idea for new decorators

Hi,

In express, we are able to send data from one middleware to anoher via the response.locals attribute. Would it be possible to have a decorator (something like the QueryParams one) that allows us to get this data without changing its type ?

Example :
In my middleware :
response.locals["myLocalAttribute"] = "test";
In my controller
@Locals("myLocalAttribute") attr : any

Thanks in advance

Upgraded to 1.4.0, but it seems like `next()`/`response.send()` isn't called within the passport example

Hey!

I'm not entirely sure why, but it seems like the following method never really triggers the next()/ response.send() functions (even though it's returned as a promise) and the server hangs when I call login using 1.4.0.

Let me know if you have any ideas on where I could look to resolve this.

Cheers!

/**
     * Authenticate user with local info (in Database).
     * @param email
     * @param password
     * @param request
     * @param response
     * @param next
     */
    @Post('/login')
    public login(
        @Required() @BodyParams('email') email: string,
        @Required() @BodyParams('password') password: string,
        @Request() request: Express.Request,
        @Response() response: Express.Response,
        @Next() next: Express.NextFunction
    ) {
        console.log('resquest.cookies', request.cookies);

        return new Promise<IUser>((resolve, reject) => {

            try{
                Passport
                    .authenticate('login', (err, user: IUser) => {

                        if (err) {
                            reject(err);
                        }

                        request.logIn(user, (err) => {

                            if (err) {
                                reject(err);
                            }

                            resolve(user);
                        });

                    })(request, response, next);
            }catch (er){
                console.error(er);
            }
        })
            .catch((err) => {

                if(err && err.message === "Failed to serialize user into session") {
                    throw new NotFound('user not found');
                }

                return Promise.reject(err);
            });

    }

EDIT

Adding something like following after the promise creation seems to resolve this:

...
         .then(x => {
            response.send(x);
            next();
        })
...

[Decorator] Static

If we want to add some static resources we have to:

this.getExpressApp()
            .use(Express.static('./app'))
            .get('*', (req, res) => {
                res.sendFile(__dirname + '/app/index.html')
            })

It would be nice to add static resources from decorators. This decorator could be added to server.

Example:

@Static({
  '/': './app',
  '/css', './css-files'
})
export Server extends ServerLoader {
......
}

Route add order mechanism

The order of adding routers to express matters. For example if we have following class.

@Controller("/account")
export class Account {

  @Get("/:id")
  getAccountById( @PathParam("id") id: string ) {...}

  @Get("/manager")
  getManagerAccount() {...}
}

Request
GET /account/manager

Expected
Method getManagerAccount() respond

Actual
Method getAccountById() will respond with manager injected as id

Workaround

@Controller("/account")
export class Account {

  @Get("/manager")
  getManagerAccount() {...}

  @Get("/:id")
  getAccountById( @PathParam("id") id: string ) {...}

}

Conclusion

When adding Routers to express app, fixed routes should go first then parametrised ones.

[Decorator] Middleware

Example 1

We can use middleware to manage ResponseView decorator. (see issue #19).

This example is an implementation of the ResponseViewMiddleware used by TsExpressDecorators.

import {IMiddleware, Middlewaren, ResponseData, Response, EndpointInfo, Endpoint} from "ts-express-decorators";
import * as Express from "express";

@Middleware()
export default class ResponseViewMiddleware implements IMiddleware {

    public use(@ResponseData() data: any, @EndpointInfo() endpoint: Endpoint, @Response() response: Express.Response) {

        if (response.headersSent) {
           return;
        }

        const viewPath = endpoint.getMetadata('response:view');
        const viewOptions = endpoint.getMetadata('response:view:options');

        if (viewPath !== undefined) {

            if (viewOptions !== undefined ) {
                data = Object.assign({}, data, viewOptions);
            }

            response.render(viewPath, data);
        }

    }
}

@Controller('/test')
class TestCtrl {
     @Get('/')
     @ResponseView('page.html') 
     public getHtml() {
           return {test: "Print test"}
     }
}

Example 2

import {IMiddleware, Middlewaren, ResponseData, Response, EndpointInfo, ConverterService} from "ts-express-decorators";

@Middleware()
export default class SendResponseMiddleware implements IMiddleware {

    constructor(private converterService: ConverterService) {

    }

    public use(@ResponseData() data: any, @Response() response: Express.Response) {

        if (response.headersSent) {
            return data;
        }

        const type = typeof data;

        if (data === undefined) {
            response.send("");
        } else if (data === null || ["number", "boolean", "string"].indexOf(type) > -1) {
            response.send(data);
        } else {

            response.setHeader("Content-Type", "text/json");
            response.json(this.converterService.serialize(data));

        }

    }
}

@Controller('/test')
class TestCtrl {
     @Get('/')
     @UseAfter(SendResponseMiddleware) 
     public get() {
           return {test: "test"}
     }
}

Example 3

Use middleware in ServerLoader !

class Server extends ServerLoader implements IServerLifecycle {

    public $onMountingMiddlewares(): void | Promise  {
        
        this.use(MyGlobalErrorHandlerMiddleware);

    }
}

Note: You must use the `ServerLoader.use () method to add a Middleware class.

[Decorator] UseBefore and UserAfter hooks

Hi @Romakita and @alexproca ,

I'm thinking about add BeforeAction and AfterAction for this project.

The main reason here is using middleware can add generic logic with request, response next way, but for our controller methods aka endpoints, is there a way to intercept the result around the method? The BeforeAction AfterAction is my proposal.

For example

@Controller("")
export default class HomeController {

    ...
    @Get("/")
    @ResponseView("home/index")
    @AfterAction('renderAssets')
    public async indexAction(request: Express.Request): Promise<Object> {

        const members = await this.memberService.findAll();
        
        return {
            title: 'blog | 博客',
            content: "This is content",
            members
        };
    }

    private renderAssets(result: any,
                         request?: Express.Request,
                         response?: Express.Response,
                         next?: Function) {

        const assets = {};
        result['assets'] = assets;
        return result;
    }
}

With AfterAction, I have a way to change the data before render to the page.

For global Actions, we can register these functions in ServerLoader.

Do you guys think it's a right way to go? or you guys have any idea on this?

Comments are very welcome.

Thanks,
Vincent

[Decorator] Model deserialization

@BodyParams can deserialize an entire object and restore his methods if the type is provided via ReflectMetadata and Typescript.

Example:

@Controller("/")
export class EventCtrl {

     @Post("/")
     save(@BodyParams() event: Event){
          console.log(event instanceof Event); // true
     } 

     //OR
     @Post("/")
     save(@BodyParams('event') event: Event){}
}

[Question] Middleware to use after @Authenticated()

Hey!

I was wondering if there is a way to use middleware within the controller after an @Authenticated call. Seems like if I call a @Use, the middleware executes before the $onAuth call (I set a request.user within that call).

Thanks in advance for your help!

Controller constructor is being called every request

Is it normal that the constructor of any class decorated with the controller decorator, is being called every request? What if I need to initialize some thing just once or play with some dependency just once? And what is the reason behind this behavior originally if it is intended?

A handy way to inject path parameters with the controller base route

Hello again, guys.

I want a handy way to build the following routes and successfully get the path parameters:

POST | /api/blogs/:blogId/posts/ | PostCtrl.addPost()
POST | /api/blogs/:blogId/posts/ | PostCtrl.getPosts()
POST | /api/blogs/:blogId/posts/:postId/comments/ | Comments.addComment()
GET | /api/blogs/:blogId/posts/:postId/comments/ | Comments.getComments()
...

What I tried (and I wish it could work) so far:

@Controller(`/:postId/comments`)
export class Comments {
  ...
  @Post(`/`)
  public addComment (
    @PathParams('blogId') blogId: string,
    @PathParams('postId') postId: string,
  ) {
    console.log(blogId, postId); // both are undefined
  }
  ...
}

@Controller(`/:blogId/posts`, Comments)
export class PostCtrl {
  ...
}

The problem is that the path parameters defined within the controller base route are not injected to the controller api methods. Any ideas?

isAuthenticated is not a function

Am I meant to implement the isAuthenticated() method that's in the doc myself? The doc isn't clear on that point.

EG:

class Server extends ServerLoader {
    public $onAuth(request, response, next): void {
        next(request.isAuthenticated());
    }
}

[ERROR] TypeError: request.isAuthenticated is not a function

I used jwt

import jwt = require('express-jwt');

export let jwtCheck = jwt({
  secret: 'y',
  audience: 'x'
});
//....
this.use(jwtCheck); // this = server

error TS2304: Cannot find name 'XMLHttpRequest'

Hi Romain,

I'm trying do play around with your library. But installation fails.

Environment:

  • Windows10, x64
  • cygwin, vscode
  • node v7.0.0, npm: 3.10.9
  • typescript 2.0.3

when i run the command:
npm install --save ts-express-decorators

I get the following errors:

(regards, Walter)
...
[email protected] postinstall D:\Entwicklung\angular2\angular-cli\christian-lehmeier\ts-express-decorators-test\node_modules\ts-express-decorators

npm run build

[email protected] build D:\Entwicklung\angular2\angular-cli\christian-lehmeier\ts-express-decorators-test\node_modules\ts-express-decorators
npm run tsc:es5 && npm run tsc:es6

[email protected] tsc:es5 D:\Entwicklung\angular2\angular-cli\christian-lehmeier\ts-express-decorators-test\node_modules\ts-express-decorators
tsc --project tsconfig.json

../@types/superagent/index.d.ts(79,12): error TS2304: Cannot find name 'XMLHttpRequest'.

npm ERR! Windows_NT 10.0.14393
npm ERR! argv "C:\Program Files\nodejs\node.exe" "C:\Users\Walter\AppData\Roaming\npm\node_modules\npm\bin\npm-cli.js" "run" "tsc:es5"
npm ERR! node v7.0.0
npm ERR! npm v3.10.9
npm ERR! code ELIFECYCLE
npm ERR! [email protected] tsc:es5: tsc --project tsconfig.json
npm ERR! Exit status 2
npm ERR!
npm ERR! Failed at the [email protected] tsc:es5 script 'tsc --project tsconfig.json'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the ts-express-decorators package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! tsc --project tsconfig.json
npm ERR! You can get information on how to open an issue for this project with:
npm ERR! npm bugs ts-express-decorators
npm ERR! Or if that isn't available, you can get their info via:
npm ERR! npm owner ls ts-express-decorators
npm ERR! There is likely additional logging output above.
npm WARN Local package.json exists, but node_modules missing, did you mean to install?

npm ERR! Please include the following file with any support request:
npm ERR! D:\Entwicklung\angular2\angular-cli\christian-lehmeier\ts-express-decorators-test\node_modules\ts-express-decorators\npm-debug.log

npm ERR! Windows_NT 10.0.14393
npm ERR! argv "C:\Program Files\nodejs\node.exe" "C:\Users\Walter\AppData\Roaming\npm\node_modules\npm\bin\npm-cli.js" "run" "build"
npm ERR! node v7.0.0
npm ERR! npm v3.10.9
npm ERR! code ELIFECYCLE
npm ERR! [email protected] build: npm run tsc:es5 && npm run tsc:es6
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] build script 'npm run tsc:es5 && npm run tsc:es6'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the ts-express-decorators package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! npm run tsc:es5 && npm run tsc:es6
npm ERR! You can get information on how to open an issue for this project with:
npm ERR! npm bugs ts-express-decorators
npm ERR! Or if that isn't available, you can get their info via:
npm ERR! npm owner ls ts-express-decorators
npm ERR! There is likely additional logging output above.
npm WARN Local package.json exists, but node_modules missing, did you mean to install?

npm ERR! Please include the following file with any support request:
npm ERR! D:\Entwicklung\angular2\angular-cli\christian-lehmeier\ts-express-decorators-test\node_modules\ts-express-decorators\npm-debug.log
npm WARN [email protected] requires a peer of express@^4 but none was installed.
npm WARN [email protected] No description
npm WARN [email protected] No repository field.
npm ERR! Windows_NT 10.0.14393
npm ERR! argv "C:\Program Files\nodejs\node.exe" "C:\Users\Walter\AppData\Roaming\npm\node_modules\npm\bin\npm-cli.js" "install" "--save" "ts-express-decorators"
npm ERR! node v7.0.0
npm ERR! npm v3.10.9
npm ERR! code ELIFECYCLE

npm ERR! [email protected] postinstall: npm run build
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] postinstall script 'npm run build'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the ts-express-decorators package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! npm run build
npm ERR! You can get information on how to open an issue for this project with:
npm ERR! npm bugs ts-express-decorators
npm ERR! Or if that isn't available, you can get their info via:
npm ERR! npm owner ls ts-express-decorators
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR! D:\Entwicklung\angular2\angular-cli\christian-lehmeier\ts-express-decorators-test\npm-debug.log

Is there a way to integrate socket.io?

Actually i'm working with a project that require socket.io. I did it long time ago using js but i want to update it and your decorators looks awesome, so there is a way to create some kind of integration?

Thanks in advance

POST requests return 201

Hello everyone,
@ ts-express-decorators/src/controllers/endpoint.ts I saw this

        if (request.method === "POST") { // TODO remove that in future version
            response.status(201);
        }

Could you please explain for me the reason for setting status here? Thank you.

[Question] Specify type for @PathParams

Hey!

I was wondering if there are any examples converting @PathParams to any other primitives types (e.g. number) other than string. I can do the conversion within the controller, but I wanted to leverage the attribute in a more global way.

E.g.

    @Get('/:id(\\d+)')
    @Authenticated()
    public getById(@Request() request: Express.Request,
                        @PathParams('id') id: number) {
        console.log(id); // id will be of type 'string'
        return id;
    }

Cheers!

Mount controllers to different endpoints

Right now we can add all controller under same endpoint

this.setEndpoint('/rest')
            .scan(appPath + "/controllers/**/**.js")
            .createHttpServer(8000)
            ;

I would be nice to have the ability to mount various directories under various endpoints.

this.mount('/rest', appPath + "/controllers/**/**.js")
    .mount('/rest/v1', appPath + "/v1/controllers/**/**.js")
            .createHttpServer(8000)
            ;

[Decorator] Inject

Add @Inject() on a method let you to inject Services on method parameters.

Here an example with ServerLoader hooks:

class Server extends ServerLoader implements IServerLifecycle {

    @Inject()
    public $onMountingMiddlewares(myService: MyService): void | Promise  {

        myService.configure('dev');

        const morgan = require('morgan'),
            cookieParser = require('cookie-parser'),
            bodyParser = require('body-parser'),
            compress = require('compression'),
            methodOverride = require('method-override'),
            session = require('express-session');

        this.use(morgan('dev'))
            .use(ServerLoader.AcceptMime("application/json"))
            .use(bodyParser.json())
            .use(bodyParser.urlencoded({
                extended: true
            }))
            .use(cookieParser())
            .use(compress({}))
            .use(methodOverride());

         
    }
}

Are there any examples with more complicated routing?

Hey,

Great work on this library!

I had a quick question regarding the routing engine. It seems like if I have potentially overlapping routes (like /me and /:id) both controller methods would get hit. Is there any way to restrict the response from trickling down to the second method? Currently, it seems like it's throwing an exception on:

...
response.setHeader("X-Managed-By", "Express-router-decorator");
...
Error: Can't set headers after they are sent.

I set breakpoints on both methods, and found that both methods get hit.

Also, I'm not sure if there's a way to order the resolution of the routes. Maybe using the order found within the controller class?

Cheers,

how to access request headers...

Hi, probably stupid question...

Where can i access request headers within the controllers ?

I'm new to decorators...so i'm trying to find out how to debug the function behind the decorator and access basic functionality within the express server...

Way to get all routes in a node micro-service

Hello,

I'm working on a project with many micro-services.
All controllers have routes.
But in my case, i would like get all controller's routes in on of my micro-service (for the scalability).

For exemple :

  • MyServCtrl1
    • /myServ1/put
  • MyServCtrl2
    • /myServ2/post
    • /myServ2/get
      If I start a server with MyServCtrl1 (scan folder MyServ1). I would like to get all routes from both controllers when I'm using routeService getRoutes()

So i decided to launch 1 server with all controllers, saves all routes, stop it and create the micro-service. But, the second server, keep the first server routes ! (In the Properties Metadata map).

Do you have a mean to retrieve all routes in this micro-service ?

Thanks in advance

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.