/kiwi

Built using only nodejs core. Lightweight, intuitive together with great performance and response timing.

Primary LanguageTypeScript

logo

Framework to help rest api development using typescript and node.

Table of Contents

Installation

  1. Install module: npm install kiwi-server --save

    npm install kiwi-server-cli -g

    Optional: https://github.com/ollita7/kiwi-cli

  2. You need to have these options in tsconfig.json file of your project:

    {
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true
    }

Sample

  1. Create your first controller class TestController.ts

    import { Get, Post, JsonController, Param, Body } from 'kiwi-server';
    
    @JsonController('/testcontroller')
    export class TestController {
    
        @Get('/getAction/:id/:id2/:id3')
        public get(@Param('id') id: string, @Param('id2') id2: string, @Param('id3') id3: string) {
            return {method: "get test"};
        }
    
        @Post('/postAction/:id')
        public post( @Body() request: any, @Param('id') id: string) {
            return {
                method: "post test",
                request: request
            };
        }
        
    }

    We can use QueryParams to get an object with tha key values that we send on the url. For example if you send something like that http://*******/testcontroller/queryparam/1?name=guille&lastname=fernandez you will recevie a json like beloow

    @Get('/queryparam/:id')
    public queryparam(@QueryParam() object: any, @Param('id') id: string){
        return object;
    }
    {
        "name": "guille",
        "lastname": "fernandez"
    }

    We can use HeaderParams to get http headers. In the next sample we are going to receive the token http header if it is in the header.

    @Get('/queryparam/:id')
    public queryparam(@Param('id') id: string, @HeaderParam('token') token: string){
        return object;
    }
  2. After you create the controller you must create the server that use that controller.

    import { createKiwiServer } from 'kiwi-server';
    import { TestController } from './test-controller';
    
    const options = {
        controllers: [TestController],
    }
    const server = createKiwiServer(options);
    server.listen(8086);

Middlewares

  1. You can create middlewares to execute activities before and and after the execution of an action. For example to enable cors we use a specific middleware that is in charge to add the http headers for that. Its important to execute next if you want that the flow continue executing. In other case the flow finish and you must do something with the response, if you dont do anything the client never gets a response. Below is a sample that execute before any action. Also you can add the order that you want to execute your middlewares like the sample bellow.
    import { IMiddleware } from 'kiwi-server';
    import { MiddlewareBefore } from 'kiwi-server';
    import * as http from 'http';
    @MiddlewareBefore(7)
    export class TestMiddleware implements IMiddleware{
    	execute(request: http.IncomingMessage, response: http.ServerResponse, next: any){
    		response.setHeader( 'Authorization', 'hola' );
    		console.log('TestMiddleware execute');
    		next();
    	}
    }

Authorization

  1. You have to specify on controller what actions need to be authorized. To do that you have a decorator @Authorization. In the sample you can see that we only need authorization to postAction. Also yo can put the authorization in the controller so all the actions must me authorized.

    import { Get, Post, JsonController, Authorize } from 'kiwi-server';
    
    @JsonController('/testcontroller2')
    export class TestController2 {
        @Get('/getAction')
        public get(){
            return "get test2";
        }
    
        @Authorize(['ADMIN', 'USER'])
        @Post('/postAction')
        public post(@Body() request: any) {
            return {
                method: "post test2",
                request: request
            };
        }
    }
  2. On the server you must define the function that is going to be executed everytime that an action or a controller has the @Authorization decorator. If that function return false the service is going to return 401 http error, in other case it will contnue the normal execution path.

    import { createKiwiServer } from 'kiwi-server';
    import { TestController } from './test-controller';
    import { TestController2 } from './test-controller2';
    
    function validateAuthentication(roles: Array<string>){
        console.log(roles);
        return false;
    }
    
    const options = {
        controllers: [TestController, TestController2],
        authorization: validateAuthentication
    }
    const server = createKiwiServer(options);
    server.listen(8086);

Cors

  1. You can enable cross domain by configuration

    import { createKiwiServer } from 'kiwi-server';
    import { TestController } from './test-controller';
    import { TestController2 } from './test-controller2';
    
    const options = {
        controllers: [TestController, TestController2],
        cors: true
    }
    const server = createKiwiServer(options);
    server.listen(8086);

Prefix

  1. You can add a prefix for all urls. If you see the sample you will have all url with v1 prefixed.

    import { createKiwiServer } from 'kiwi-server';
    import { TestController } from './test-controller';
    import { TestController2 } from './test-controller2';
    
    const options = {
        controllers: [TestController, TestController2],
        cors: true,
        prefix: 'v1/'
    }
    const server = createKiwiServer(options);
    server.listen(8086);

Dependency Injection

  1. You can use dependency injection in your controllers. The only thing that you have to do is to add arguments on the constructor of the controller. Then you can use that in any method that you want.

    import { Get, Post, JsonController, Param, Body, QueryParam, Authorize } from 'kiwi-server';
    import {Utils} from './utils';
    
    @Authorize(['role1, role2'])
    @JsonController('/testcontroller')
    export class TestController {
        
        constructor(private utils: Utils){}
        
        @Post('/meetupjs')
        public test23(@Body() body: any){
            return body;
        }
    
        @Get('/queryparam/:id')
        public queryparam(@QueryParam() object: any, @Param('id') id: string){
            this.utils.print();
            return object;
        }

Sockets

  1. We integrate socket.io to our framework.

    const options = {
        controllers: [TestController, TestController2],
        cors: true,
        documentation: {
            enabled: true,
            path: '/apidoc'
        },
        socket: true
    }

    You have to enable socket suppor by adding socket property to options.

    const server = createKiwiServer(options, socketInit);
    
    function socketInit() {
        const io = getSocket();
        io.on('connection', (socket: any) => {
            socket.userId  = socket.handshake.query.user;
        });
    }

    Finally you only have to use getSocket in any place of the framework and start using it.

Documentation

  1. You can enable cross domain by configuration

    import { createKiwiServer } from 'kiwi-server';
    import { TestController } from './test-controller';
    import { TestController2 } from './test-controller2';
    
    const options = {
        controllers: [TestController, TestController2],
        cors: true,
        documentation: {
            enabled: true,
            path: '/apidoc'
        }
    }
    const server = createKiwiServer(options);
    server.listen(8086);