npm package: @nordic-lake/nano-api
Description: A simple and lightweight API framework for Node.js
Latest version: 2.0.6

# @nordic-lake/nano-api

A lightweight and flexible Node.js server library for building HTTP APIs with ease. Designed for simplicity and minimalistic setups, `@nordic-lake/nano-api` provides essential tools to develop robust API endpoints. It is built on top of the [http](https://nodejs.org/api/http.html) module and has no external dependencies.

## Features

-   **Simple API Routing**: Define routes for common HTTP methods like GET, POST, PUT, PATCH, and DELETE with ease.
-   **Middleware Support**: Implement middleware functions for pre-processing or post-processing of requests and responses.
-   **Error Handling**: Efficient error handling mechanisms with custom error handler support.
-   **Async/Await Support**: Write asynchronous route handlers and middleware using modern JavaScript features.
-   **Lightweight Design**: Minimal overhead and dependencies, making it ideal for small to medium-sized projects.
-   **Easy Integration**: Seamlessly integrates with existing Node.js applications.

## Installation

Install `@nordic-lake/nano-api` using npm:

```bash
npm install @nordic-lake/nano-api
```

## Quick Start

Here's a quick example to get your server up and running:

```javascript
import NanoServer from '@nordic-lake/nano-api';

// Create a new server instance
const server = new NanoServer();

// Define a GET endpoint
server.get('/hello', (request, response) => {
    response.body('Hello World!');
});

// Start listening on port 3000
server.listen(3000, () => {
    console.log(`Server listening on http://localhost:3000`);
});
```

## API Reference

-   **useBefore(middleware)**: Add middleware that executes before route handlers.
-   **useAfter(middleware)**: Add middleware that executes after route handlers.
-   **useErrorHandling(errorHandler)**: Register a custom error handler.
-   **get(path, handler)**: Define a GET route.
-   **post(path, handler)**: Define a POST route.
-   **put(path, handler)**: Define a PUT route.
-   **delete(path, handler)**: Define a DELETE route.
-   **patch(path, handler)**: Define a PATCH route.
-   **listen(port, callback)**: Start the server on the specified port (use port 0 to assign a random port).
-   **close(callback)**: Stop the server from accepting new connections.

## Examples

### Setup Server

```javascript
import NanoServer from '@nordic-lake/nano-api';

// Create a new server instance
const server = new NanoServer();

// Configurations...

// Start listening on port 3000
server.listen(3000, (url) => {
    console.log(`Server listening on ${url.href}`);
});
```

### Simple Endpoint

```javascript
// Define a GET endpoint
server.get('/hello', (request, response) => {
    response.body('Hello World!');
});

// Start listening on port 3000
server.listen(3000, () => {
    console.log(`Server listening on http://localhost:3000`);
});
```

### Route Parameters

```javascript
// Define a GET endpoint with a route parameter
server.get('/hello/:name', (request, response) => {
    const { name } = request.params;
    response.body(`Hello ${name}!`);
});
```

### Route Wildcards

```javascript
// Define a GET endpoint with a wildcard route parameter (matches e.g. /hello/any/home)
server.get('/hello/*/home', (request, response) => {
    const { wildcard } = request.params;
    response.body(`Hello ${wildcard}!`);
});

// Define a GET endpoint with a wildcard route parameter (matches e.g. /hello/any/path/here)
server.get('/hello/**', (request, response) => {
    const { wildcard } = request.params;
    response.body(`Hello ${wildcard}!`);
});
```

### Route Query Parameters

```javascript
// Define a GET endpoint with a query parameter
server.get('/hello', (request, response) => {
    const { name } = request.query;
    response.body(`Hello ${name}!`);
});
```

### Route Middleware

```javascript
// Define a middleware function
const middleware = (request, response, next) => {
    // Do something (e.g. logging)...
    console.log(`${request.method} ${request.url} called`);

    next();
};

app.useBefore(middleware);
// or
app.useAfter(middleware);
```

### Route Error Handling

```javascript
// Define a custom error handler
const errorHandler = (error, request, response, next) => {
    // Do something (e.g. logging)...
    console.error(error);

    if (error instanceof Error && error.name === 'ValidationError') {
        response.status(400).body(error.message);
        // Return true to indicate that the error has been handled and does not need to be passed to the next error handler
        return true;
    }
};
```

## Notes

-   The handling lifecycle of a request is as follows:
    1.  The server receives a request.
    2.  The server executes all middleware functions that were registered with `useBefore()`.
    3.  The server executes the route handler.
    4.  The server executes all middleware functions that were registered with `useAfter()`.
    5.  If an error occurred during the handling of the request, the server executes the error handlers that were registered with `useErrorHandling()`, until one of them returns `true`.
    6.  The server sends the response.
-   Route handlers and middleware functions can be asynchronous by using the `async` keyword or by returning a `Promise`.
-   When a error is unhandled, the server will respond with a generic 404 error message, if the handler could not be found, or a generic 500 error message, if the handler or middleware threw an error.