Skip to content

Router Configurations

As mentioned previously, the router is highly configurable to each project needs and desires. The point of the router is to enforce predictable thus making the API more extensible. Below is a table of all the configuration options available:

Example

Don't like reading documentation? Then look at our examples which can run locally!

Configuration Options

option type required description
routesPath string yes glob pattern to match handler files (supports TypeScript paths with auto-transform)
basePath string no the base path to strip from requests (e.g., '/api/v1')
schemaPath string no; required if using autoValidate file path pointing to the location of the openapi.yml file
buildOutputDir string no build output directory for TypeScript compilation (auto-detects if not specified)
cache enum no; 'all', 'dynamic', 'static', 'none' cache mode for route resolution (default: optimized caching)
autoValidate boolean no; requires schemaPath automatically validate requests against OpenAPI schema
validateResponse boolean no validate responses against schema (useful for development)
timeout number no global timeout in milliseconds for all endpoints
outputError boolean no, (default: false) output detailed error messages (recommended for non-production)
globalLogger boolean no enable global logger accessible via global.logger
loggerCallback function no custom callback function for all log messages
beforeAll function no middleware to run before EVERY request
afterAll function no middleware to run after EVERY request
withAuth function no global authentication middleware (triggered by @Auth() or auth: true)
onError function no error handler for unhandled errors (not validation errors)
onTimeout function no timeout handler when requests exceed timeout setting

Example: Router Configuration

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import 'reflect-metadata';
import { Router } from 'acai-ts';
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
import { MiddlewareUtils } from './logic/middleware';
import { Authenticator } from './logic/authenticator';

const router = new Router({
    basePath: '/api/v1',
    routesPath: './src/handlers/**/*.ts',    // File-based routing with auto-transform
    schemaPath: './openapi.yml',
    buildOutputDir: '.build',               // Optional: auto-detects if not specified
    cache: 'all',                          // Cache all routes for performance
    autoValidate: true,
    validateResponse: process.env.STAGE !== 'prod', // Validate responses in dev
    timeout: 30000,                        // 30 seconds in milliseconds
    outputError: process.env.STAGE !== 'prod',      // Show errors in dev
    globalLogger: true,
    loggerCallback: MiddlewareUtils.loggerCallback,
    beforeAll: MiddlewareUtils.beforeAll,
    afterAll: MiddlewareUtils.afterAll,
    withAuth: Authenticator.authenticate,   // Global auth middleware
    onError: MiddlewareUtils.onError,
    onTimeout: MiddlewareUtils.onTimeout
});

// Optional: pre-load routes and schema for better cold start performance
router.autoLoad();

export const handler = async (
    event: APIGatewayProxyEvent
): Promise<APIGatewayProxyResult> => {
    return await router.route(event);
};

Example: Router Config with Minimal Setup

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import 'reflect-metadata';
import { Router } from 'acai-ts';
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';

// Minimal configuration - most options are optional and have sensible defaults
const router = new Router({
    routesPath: './src/handlers/**/*.ts'  // Only required option
});

export const handler = async (
    event: APIGatewayProxyEvent
): Promise<APIGatewayProxyResult> => {
    return await router.route(event);
};

Example: Advanced Router Configuration

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import 'reflect-metadata';
import { Router } from 'acai-ts';
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';

// Custom middleware functions
const authMiddleware = async (request, response) => {
    const token = request.headers.authorization?.replace('Bearer ', '');
    if (!token || !validateJWT(token)) {
        response.code = 401;
        response.setError('auth', 'Unauthorized');
    }
};

const loggerCallback = (log) => {
    // Send to external logging service
    console.log(JSON.stringify(log));
};

const router = new Router({
    // Required
    routesPath: './src/handlers/**/*.ts',

    // Optional configurations
    basePath: '/api/v1',
    schemaPath: './openapi.yml',
    buildOutputDir: '.build',
    cache: 'all',
    autoValidate: true,
    validateResponse: process.env.NODE_ENV === 'development',
    timeout: 30000,
    outputError: process.env.NODE_ENV !== 'production',
    globalLogger: true,
    loggerCallback,

    // Middleware
    beforeAll: async (request, response) => {
        console.log(`${request.method} ${request.path}`);
    },
    afterAll: async (request, response) => {
        console.log(`Response: ${response.code}`);
    },
    withAuth: authMiddleware,
    onError: async (request, response, error) => {
        console.error('Unhandled error:', error.message);
    },
    onTimeout: async (request, response, error) => {
        console.warn('Request timeout:', request.path);
    }
});

router.autoLoad();

export const handler = async (
    event: APIGatewayProxyEvent
): Promise<APIGatewayProxyResult> => {
    return await router.route(event);
};

Route Path Patterns

The routesPath option supports flexible glob patterns for organizing your handlers:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// Standard structure
routesPath: './src/handlers/**/*.ts'

// Controller pattern
routesPath: './src/api/**/*.controller.ts'

// Specific directories
routesPath: './src/endpoints/**/*.ts'

// Multiple patterns (if your build tool supports it)
routesPath: './src/{handlers,endpoints}/**/*.ts'

File Structure Examples

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Standard Structure
src/handlers/
├── users.ts              → /users
├── users/{id}.ts         → /users/{id}
└── products/
    ├── index.ts          → /products
    └── {id}/reviews.ts   → /products/{id}/reviews

# Controller Pattern
src/api/
├── users.controller.ts      → /users  
├── user-detail.controller.ts → /user-detail
└── products/
    └── product.controller.ts → /products/product