0.1.3 • Published 9 months ago

@achtjs/router v0.1.3

Weekly downloads
-
License
MIT
Repository
github
Last release
9 months ago

@achtjs/router

Suggestions

For suggestions and features you want to see in the future you can visit our issues section.

Getting started

Before installing this package make sure to download and install Node.js 10 or higher.

Setup Node

To check your node version

npm -v

For new project kindly initialize npm using the command below or see documentation here.

npm init

Setup Typescript

Install typescript and typescript watcher

npm i typescript ts-node-dev -D

Initialize typescript

tsc --init

Setup Router

Install achtjs router

npm i @achtjs/router

Add start script on your package.json

"scripts": {
  "start": "tsnd src"
}

Features

  • Simple and easy
  • Lightweight library
  • Built with TypeScript
  • No third party library
  • Modules for shareable code
  • Dependency Injection and IOC
  • Fast execution with route caching
  • Supports beginners to advanced developers
  • Function and Class based coding style
  • Supports third party middlewares like ExpressJS

Quick Start

The easiest way to get started is to create a simple route. Create a src folder inside your project folder. Inside the src folder create an index.ts file. Copy the code below into index.ts file.

import achtjs from "@achtjs/router";
import http from "http";

const PORT = 3000;
const app = achtjs();

app.add([
    {
        path: "/",
        GET: () => "Hello, World",
    },
]);

http.createServer(app).listen(PORT, () =>
    console.log(`Server listening on port ${PORT}.`)
);

RUN

To run your achtjs project open a terminal inside your current project and run the command below.

npm start

ROUTE

Defining routes in AchtJS is like creating a JSON object.

const user = {
    path: "user",
    GET: () => {
        //  ...
    },
    POST: () => {
        //  ...
    },
    PUT: () => {
        //  ...
    },
    PATCH: () => {
        //  ...
    },
    DELETE: () => {
        //  ...
    },
    OPTIONS: () => {
        //  ...
    },
};

As seen above each method name has a callback function. AchtJS will set the correct content-type based on what the method callback will return.

const route = {
    path: "user",
    GET: () => {
        // This will return `undefined`
        // This will have a content-type of "text/plain"
    },
    POST: () => {
        return "Hello"; // This will have a content-type of "text/plain"
    },
    PUT: () => {
        return { message: "Hello" }; // This will have a content-type of "application/json"
    },
    PATCH: () => {
        return "<h1>Hello</h1>"; // This will have a content-type of "text/html"
    },
};

Incase you need to use a middleware for an specific route method you need to create a route object instead.

const route = {
    path: "user",
    GET: {
        middlewares: [middleware],
        callback: () => {
            // ...
        },
    },
};

PARAMS

AchtJS passes a context object on each route method. You can acces the route params by destructuring the context object on the callback method.

const route = {
    path: "user/:id",
    GET: ({ params }) => {
        // `params` object contains the value of `id` define on the path above e.g. `user/hello`
        return params.id; // This has a value of "hello"
    },
};

QUERY STRING

You can also access the query string using the context object provided by AchtJS on your route method callback function.

const route = {
    path: "user",
    GET: ({ query }) => {
        // `query` object contains all the value on your query string e.g. `user?id=1`
        return query.id; // This has a value of 1
    },
};

BODY

Request body is also accessible in the context but you need a middleware before you can actually uses. There is a popular middleware called body-parser that we can use to achieve this.

import achtjs from "@achtjs/router";
// Third party middleware you need to install
import bodyParser from "body-parser";

const app = achtjs();

// Initialize body parser for achtjs to use it internally
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

const route = {
    path: "user",
    POST: ({ body }) => {
        // `body` object contains all the value from the request body
        return body; // This has a value of req.body
    },
};

app.add([route]);

MIDDLEWARES

As seen above how we used third party middlewares to parse the request body. We can also create our own middlewares. Although AchtJS supports all ExpressJs Middlewares, we also can create a AchtJsMiddleware of our own. The context is where you can access params, query and body objects.

router.use((context, next, error) => {
    // This `error` variable comes from the previous middleware
    console.log(error);

    // The `next` function will trigger the end of this callback function
    // and execute the next middleware in the list
    next(
        "Error message or any value that you want to pass to the next middleware"
    );
});

CHILD ROUTES

A child route is a route that appended to its parent route. It can be added using the children property from the route object.

app.add([
    {
        path: "parent", // This is the `parent` route
        children: [
            {
                path: "child", // You can call this child route by `parent/child`
                GET: () => "This is from a child route",
            },
        ],
    },
]);
NOTE: A `child` route can also have its own `children`.
app.add([
    {
        path: "parent", // This is the `parent` route
        GET: () => "This is a parent route",
        children: [
            {
                path: "child", // You can call this child route by `users/child`
                GET: () => "This is a child route",
                children: [
                    {
                        path: "grandchild", // You can call this child route by `parent/child/grandchild`
                        GET: () => "This is a grandchild route",
                    },
                ],
            },
        ],
    },
]);

CONTROLLER

A controller is a class that act as a replacement for the route method objects. It can be used to make your code more modular and manageable when your code base get bigger.

class UsersController extends Controller {
    GET() {
        return "Hello form UsersController";
    }

    // You can also add additional route method like this
    POST() {
        // ...
    }

    // Other routes available are PUT, PATCH, DELETE and OPTIONS
}

app.add([
    {
        path: "user",
        controller: UsersController,
    },
]);

If you want to add middleware a middleware to a specific method you can add the middleware property in a controller.

class UsersController extends Controller {
    middleware = {
        GET: [middleware], // This middleware will be added to the `GET` method below
    };

    GET() {
        //  ...
    }
}
NOTE: A controller has no `children` property

SERVICES

A service is an injectable class that can be used inside of a controller or another service.

export class UsersServices extends Services {
    // Every function inside the service can be accessed by the class its injected
    // All public properties are also accessible
    // A service is instatiated once and making it a singleton

    add() {
        // ...
    }
}

class UsersController extends Controller {
    constructor(userServices: UsersServices) {
        super();
    }

    addUser() {
        // This `add` function coming from the `UsersService`.
        // It is accessible on this controller via dependency injection.
        // AchtJS automatically instantiated it and created it singleton instance.
        this.userServices.add();
    }
}

MODULE

A module is a like a container of routes, controller and services that act on its own. This will allow your code to modular and shareable accross all routes.

class UsersModule extends AchtJsModule {
    // List of `module` or `services` that this module will use for its controllers
    imports = [];
    // List of controllers that this module will use
    declarations = [];
    // List of services that can be use inside this module
    providers = [];
    // List of services that this module will exports that can be used by other modules
    exports = [];
    // List of dependencies that will be injected to this module
    dependencies = [];
}

As you can see when we create a module we dont have any way to add routes on it. Below is an example of implementation of how to add a RouterModule for this module to add routes.

import { UsersController, UsersIdController } from "./controller";
import { RouterModule } from "@achtjs/router";
import { UsersServices } from "./services";

// Define the routes
const routes = [
    {
        path: "/",
        controller: UsersController,
    },
    {
        path: ":id",
        controller: UsersIdController,
    },
];

export class UsersModule extends AchtJsModule {
    // User `RouterModule.forRoot` to inject the routes
    imports = [RouterModule.forRoot(routes)];
    // Declare the controllers that will be used inside the routes
    declarations = [UsersIdController, UsersController];
}

CUSTOM MODULE

Unlike the common achtjs module, custom modules provide other functionality aside from managing your controllers. One example of this the RouterModule that is reponsible for adding routes to your module. A key concept of a custom module is it has an invoke and forRoot function that provides additional functionalities.

export class UsersModule extends CustomModule {
    invoke() {
        // This function will run after an instance of this module is created
        // But the providers will stay singleton on each instance
    }

    static forRoot(options: any) {
        return {
            module: UsersModule, // Returns the current module reference
            providers: [], // List of providers that this module will use on its controllers
        };
    }
}

Now we know how to create a module but how we can call it on our routes. We are now introducing to loadChildren property of our route object. AchtJS will automatically resolve the module asynchronously when the path is added on the route list.

import achtjs from "@achtjs/router";
import http from "http";

const app = achtjs();

app.add([
    {
        path: "users",
        // We are using dynamic importing so we don't need it to manually import the module in the file
        // AchtJS will resolve the module asynchronously
        loadChildren: () => import("./users.module").then((m) => m.UsersModule),
    },
]);

License

MIT

0.1.3

9 months ago

0.1.2

9 months ago

0.1.1

9 months ago

0.1.0

9 months ago

0.0.0

9 months ago