Teeny.js, a route system for Node.js
Tags: javascript, node
Published: 2021-02-03 01:25:13

The main objective of this project is to be light, simple, easy to learn, to serve other projects that need a route system to use together with other libraries and mainly to explore the native resources from language and engine (Node).

## Advantages of using Teeny.js

It is possible to use modules in the routes and method `app.handlerCodes()` and these modules are loaded only when necessary.

When you edit the file containing the routes, **Teeny.js** detects and updates everything on its own without having to restart the server, something that is often necessary in other similar libs. This makes it easy to quickly maintain or reconfigure anything called within `routes.js`.

It is possible to create your own patterns to use in route parameters.

## Get Start

For create a example:

```
mkdir foobar
cd foobar
npm init
```

After this install package:

```
npm i teeny.js
```

Create two files `index.js` and `routes.js` (you can change the names), example:

``` javascript
const { Teeny } = require('teeny.js');

const app = new Teeny(`${__dirname}/routes.js`, 7000);

app.exec();
```

For use with "ECMAScript modules" for load from same level path (like: `__dirname`):

``` javascript
import { Teeny } from 'Teeny.js';
import { createRequire } from 'module';

const app = new Teeny('./routes.js', 7000);

app.setRequire(createRequire(import.meta.url));

app.exec();
```

In routes.js put this:

``` javascript
module.exports = (app) => {
    // Enable (or disable) debug mode
    app.setDebug(true);

    // Access http://localhost:7000/ for see "Hello world"
    app.action('GET', '/', (request, response) => {
        return 'Hello World!';
    });

    // Access http://localhost:7000/async for see response from a async function
    app.action('GET', '/async', async (request, response) => {
        const result = new Promise((resolve) => setTimeout(resolve, 1000, `Async working ${new Date()}!`));

        return result;
    });

    // Access http://localhost:7000/user/mary (or another nickname)
    app.action('GET', '/user/<username:alnum>', (request, response, params) => {
        return `Hello ${params.username}`;
    });
};
```

# Handling Http errors (like `ErrorDocument`)

For handling errors for not defined routes (404 Not Found) and when try access a route with invalid (not defined) method uses `app.handlerCodes(Array codes, Function callback)`, example (in `routes.js`):

```
module.exports = (app) => {
    // Enable (or disable) debug mode
    app.setDebug(true);

    app.handlerCodes([ 404, 405 ], (status) => {
        return `Error page: ${status}`;
    });

...
```
# Route patterns

You can create your own patterns to use with the routes in "Teeny.js", but there are also ready-to-use patterns:

Pattern | Regex used | Description
--- | --- | ---
`alnum` | `[\\da-zA-Z]+` | Matches routes with param using alpha-numeric in route
`alpha` | `[a-zA-Z]+` | Matches routes with param using A to Z letters in route
`decimal` | `\\d+\\.\\d+` | Matches routes with param using decimal format (like `1.2`, `3.5`, `100.50`) in route
`num` | `\\d+` | Matches routes with param using numeric format in route
`noslash` | `[^\\/]+` | Matches routes with param using any character except slashs (`\/` or `/`) in route
`nospace` | `\\S+` | Matches routes with param using any character except spaces, tabs or NUL in route
`uuid` | `[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}` | Matches routes with param using uuid format in route
`version` | `\\d+\\.\\d+(\\.\\d+(-[\\da-zA-Z]+(\\.[\\da-zA-Z]+)*(\\+[\\da-zA-Z]+(\\.[\\da-zA-Z]+)*)?)?)?` | Matches routes with param using [`semver.org`](https://semver.org/) format in route

For use a pattern in routes, set like this:

``` javascript
module.exports = (app) => {
    app.action('GET', '/user/<name:alnum>', (request, response, params) => {
        return `Hello ${params.name}`;
    });

    app.action('GET', '/api/<foobar:version>', (request, response, params) => {
        return `Version: ${params.foobar}`;
    });

    app.action('GET', '/product/<id:num>', (request, response, params) => {
        return `Product ID: ${params.id}`;
    });
...
```