Methods
autoBox(ary) → {Array}
Ensures a value is always an array by wrapping non-array values
Parameters:
Name | Type | Description |
---|---|---|
ary |
* | The value to convert to an array |
Returns:
- Wraps the value in an array, or if the input was an array already it will return it as is.
- Type
- Array
Examples
// With a non-array value
autoBox(5); // Returns: [5]
// With an array value
autoBox([1, 2, 3]); // Returns: [1, 2, 3]
// With null or undefined
autoBox(null); // Returns: [null]
autoBox(undefined); // Returns: [undefined]
// With an object
autoBox({ key: 'value' }); // Returns: [{ key: 'value' }]
(async) buildMiddlewareDictionary(basePath, baseURL, optionsopt) → {Object.<string, Array.<function()>>}
Builds a dictionary of middleware functions from a directory structure
Recursively scans the given directory for '_middleware.js' files and builds a dictionary
mapping URL paths to their corresponding middleware functions
Parameters:
Name | Type | Attributes | Description |
---|---|---|---|
basePath |
string | Base filesystem path to start scanning | |
baseURL |
string | Base URL path for the routes | |
options |
Object |
<optional> |
Options that can be passed to all controllers when they are executed. |
Returns:
Dictionary where keys are URL paths and values are arrays of middleware functions
- Type
- Object.<string, Array.<function()>>
Examples
// Basic directory structure with middleware
// ./src/routes/_middleware.js -> exports a global middleware
// ./src/routes/users/_middleware.js -> exports a users-specific middleware
const middlewares = buildMiddlewareDictionary('./src/routes', '/api');
// Returns: {
// '/api/': [globalMiddleware],
// '/api/users/': [usersMiddleware]
// }
// With dynamic route parameters
// ./src/routes/users/[id]/_middleware.js -> exports a user-specific middleware
const middlewares = buildMiddlewareDictionary('./src/routes', '/api');
// Returns: {
// '/api/': [globalMiddleware],
// '/api/users/': [usersMiddleware],
// '/api/users/:id/': [userSpecificMiddleware]
// }
// With middleware exporting multiple functions
// ./src/routes/_middleware.js -> exports [authMiddleware, logMiddleware]
const middlewares = buildMiddlewareDictionary('./src/routes', '/api');
// Returns: {
// '/api/': [authMiddleware, logMiddleware]
// }
// With middleware exporting a single function
// ./src/routes/_middleware.js -> exports singleMiddleware (not in an array)
const middlewares = buildMiddlewareDictionary('./src/routes', '/api');
// Returns: {
// '/api/': [singleMiddleware]
// }
buildRoutes(basePath, baseURL) → {Array.<Array.<string>>}
Builds an array of route mappings from a directory structure
Recursively scans the given directory for 'index.js' files and builds an array of
URL paths and their corresponding file paths, converting directory placeholders to Express params
Parameters:
Name | Type | Description |
---|---|---|
basePath |
string | Base filesystem path to start scanning |
baseURL |
string | Base URL path for the routes |
Returns:
Array of tuples where first element is URL path and second is file path
- Type
- Array.<Array.<string>>
Examples
// Basic directory structure
// ./src/routes/users/index.js
// ./src/routes/posts/index.js
const routes = buildRoutes('./src/routes', '/api');
// Returns: [
// ['/api/users/', './src/routes/users/index.js'],
// ['/api/posts/', './src/routes/posts/index.js']
// ]
// With dynamic route parameters
// ./src/routes/users/[id]/index.js
const routes = buildRoutes('./src/routes', '/api');
// Returns: [
// ['/api/users/:id/', './src/routes/users/[id]/index.js']
// ]
// With nested dynamic routes
// ./src/routes/users/[userId]/posts/[postId]/index.js
const routes = buildRoutes('./src/routes', '/api');
// Returns: [
// ['/api/users/:userId/posts/:postId/', './src/routes/users/[userId]/posts/[postId]/index.js']
// ]
// With root route
// ./src/routes/index.js
const routes = buildRoutes('./src/routes', '/api');
// Returns: [
// ['/api/', './src/routes/index.js']
// ]
(async) composeRoutes(express, routeMappings, optionsopt) → {Object}
Composes Express routes from a directory structure with middleware support.
This is the main function that processes route mappings, builds middleware dictionaries,
and configures an Express router with all discovered routes and middleware.
Parameters:
Name | Type | Attributes | Description | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
express |
Object | The Express module instance | |||||||||||||||||
routeMappings |
Array.<Object> | Array of route mapping configurations
Properties
|
|||||||||||||||||
options |
Object |
<optional> |
Configuration options
Properties
|
Returns:
Configured Express router with applied routes
- Type
- Object
Examples
// Basic usage with a single route mapping
const express = require('express');
const app = express();
const router = composeRoutes(express, [
{
basePath: './src/routes',
baseURL: '/api'
}
]);
app.use(router);
// This will set up all routes found in './src/routes' with their middleware
// With multiple route mappings
const router = composeRoutes(express, [
{
basePath: './src/api/routes',
baseURL: '/api'
},
{
basePath: './src/admin/routes',
baseURL: '/admin'
}
]);
// With custom router options
const router = composeRoutes(express, [
{
basePath: './src/routes',
baseURL: '/api'
}
], {
routerOptions: {
strict: true,
}
});
// With an existing router instance
const existingRouter = express.Router();
const router = composeRoutes(express, [
{
basePath: './src/routes',
baseURL: '/api'
}
], {
router: existingRouter
});
curryObjectMethods(router, urlPath, …initialMiddleWareFunctions) → {Object}
Creates a curried router object with pre-configured URL path and middleware
Returns a proxy to the original router that applies the given URL path and middleware functions
to all HTTP method calls (get, post, put, etc.) automatically
Parameters:
Name | Type | Attributes | Description |
---|---|---|---|
router |
Object | Express router instance | |
urlPath |
string | The URL path to be curried | |
initialMiddleWareFunctions |
function |
<repeatable> |
Initial middleware functions to be applied (rest parameter, accepts multiple functions) |
Returns:
- Curried router proxy with pre-configured path and middleware
- Type
- Object
Examples
// Basic usage with a single middleware function
const router = express.Router();
const curriedRouter = curryObjectMethods(router, '/users', authMiddleware);
curriedRouter.get((req, res) => res.json({}));
// Equivalent to: router.get('/users', authMiddleware, (req, res) => res.json({}));
// With multiple middleware functions
const curriedRouter = curryObjectMethods(router, '/posts', authMiddleware, logMiddleware);
curriedRouter.post((req, res) => res.status(201).json({}));
// Equivalent to: router.post('/posts', authMiddleware, logMiddleware, (req, res) => res.status(201).json({}));
// With no middleware
const curriedRouter = curryObjectMethods(router, '/public');
curriedRouter.get((req, res) => res.send('Hello'));
// Equivalent to: router.get('/public', (req, res) => res.send('Hello'));
// Accessing the original router object
const curriedRouter = curryObjectMethods(router, '/api');
const originalRouter = curriedRouter._getOriginalObject();
// originalRouter is the router instance passed in the first parameter
dictionaryKeyStartsWithPath(dictionary, path) → {Array.<function()>}
Retrieves and sorts middleware functions that match a given path
Finds all entries in the dictionary where the given path starts with the dictionary key,
sorts them by key length (shortest first), and returns the flattened array of middleware functions
Supports both legacy middleware format (plain functions) and priority object format ({ fn, priority })
with backward compatibility. Priority objects are sorted using the four-level priority system.
Parameters:
Name | Type | Description |
---|---|---|
dictionary |
Object.<string, (function()|Array.<function()>|Array.<Object>)> | Dictionary of paths to middleware functions or priority objects |
path |
string | The path to match |
Returns:
- Array of middleware functions that apply to the path, ordered by priority and path specificity
- Type
- Array.<function()>
Examples
// With matching paths (legacy format)
const dict = {
'/api/': [authMiddleware],
'/api/users/': [userMiddleware]
};
dictionaryKeyStartsWithPath(dict, '/api/users/profile');
// Returns: [authMiddleware, userMiddleware] (in order from least to most specific)
// With priority objects (new format)
const dict = {
'/api/': [
{ fn: corsMiddleware, priority: 5 },
{ fn: authMiddleware, priority: 20 }
],
'/api/users/': [
{ fn: userValidationMiddleware, priority: 15 }
]
};
dictionaryKeyStartsWithPath(dict, '/api/users/profile');
// Returns: [corsMiddleware, userValidationMiddleware, authMiddleware] (sorted by priority)
// With mixed legacy and priority format (backward compatible)
const dict = {
'/api/': [legacyMiddleware, { fn: priorityMiddleware, priority: 10 }],
'/api/users/': userMiddleware // Single function
};
dictionaryKeyStartsWithPath(dict, '/api/users/');
// Returns: [priorityMiddleware, legacyMiddleware, userMiddleware] (priority objects sorted first)
// With no matching paths
const dict = {
'/api/': [authMiddleware],
'/api/users/': [userMiddleware]
};
dictionaryKeyStartsWithPath(dict, '/admin/');
// Returns: []
// With null or undefined values in the dictionary (they are filtered out)
const dict = {
'/api/': [authMiddleware, null],
'/api/users/': undefined
};
dictionaryKeyStartsWithPath(dict, '/api/users/');
// Returns: [authMiddleware]
isMiddlewareFile(entry) → {boolean}
Checks if a directory entry is a middleware file
Parameters:
Name | Type | Description |
---|---|---|
entry |
Object | The directory entry to check (fs.Dirent object) |
Returns:
- True if the entry is a file named '_middleware.js'
- Type
- boolean
Examples
// With a file entry for '_middleware.js'
const middlewareEntry = { isFile: () => true, name: '_middleware.js' };
isMiddlewareFile(middlewareEntry); // Returns: true
// With a directory entry
const dirEntry = { isFile: () => false, name: '_middleware.js' };
isMiddlewareFile(dirEntry); // Returns: false
// With a different file
const otherFileEntry = { isFile: () => true, name: 'index.js' };
isMiddlewareFile(otherFileEntry); // Returns: false
isPlaceholder(urlPath) → {boolean}
Checks if a URL path contains a placeholder
Parameters:
Name | Type | Description |
---|---|---|
urlPath |
string | The URL path to check |
Returns:
- True if the path contains a placeholder
- Type
- boolean
Examples
// With placeholder
isPlaceholder('/users/[id]'); // Returns: true
// With multiple placeholders
isPlaceholder('/users/[id]/posts/[postId]'); // Returns: true
// Without placeholder
isPlaceholder('/users/list'); // Returns: false
// With square brackets in a different context (not a placeholder)
isPlaceholder('/users/list[all]'); // Returns: true (matches the regex pattern)
joinUrlPaths(base, segment) → {string}
Safely joins URL paths without creating double slashes
Removes trailing slash from base and ensures segment starts with slash
Parameters:
Name | Type | Description |
---|---|---|
base |
string | The base URL path |
segment |
string | The path segment to append |
Returns:
- The joined path without double slashes
- Type
- string
Examples
// With base having trailing slash
joinUrlPaths('/api/', 'users')
// Returns: '/api/users'
// With base not having trailing slash
joinUrlPaths('/api', 'users')
// Returns: '/api/users'
// With segment having leading slash
joinUrlPaths('/api', '/users')
// Returns: '/api/users'
// Preventing double slashes
joinUrlPaths('/api/', '/users')
// Returns: '/api/users'
// With empty base (edge case)
joinUrlPaths('', 'users')
// Returns: '/users'
// With empty segment (edge case)
joinUrlPaths('/api', '')
// Returns: '/api/'
// With both empty (edge case)
joinUrlPaths('', '')
// Returns: '/'
loadModule(modulePath) → {Promise.<any>|any}
Universal module loader that handles both CommonJS and ESM modules
Tries CommonJS first, falls back to dynamic import for ESM
Parameters:
Name | Type | Description |
---|---|---|
modulePath |
string | Path to the module to load |
Returns:
- The loaded module
- Type
- Promise.<any> | any
normalizeMiddlewarePriority(middleware, sourceIndex, sourcePath) → {Array}
Normalizes middleware to priority objects with consistent structure
Parameters:
Name | Type | Default | Description |
---|---|---|---|
middleware |
function | Object | Array | Middleware function(s) or priority objects | |
sourceIndex |
number | 0 | Original array position for tracking |
sourcePath |
string | Source path for specificity tracking |
Returns:
Array of {fn, priority, sourceIndex, sourcePath} objects
- Type
- Array
Examples
// With plain function
normalizeMiddlewarePriority(corsMiddleware, 0, '/api/')
// Returns: [{ fn: corsMiddleware, priority: 50, sourceIndex: 0, sourcePath: '/api/' }]
// With priority object
normalizeMiddlewarePriority({ fn: authMiddleware, priority: 10 }, 1, '/api/')
// Returns: [{ fn: authMiddleware, priority: 10, sourceIndex: 1, sourcePath: '/api/' }]
// With array of mixed types
normalizeMiddlewarePriority([corsMiddleware, { fn: authMiddleware, priority: 20 }], 0, '/api/')
// Returns: [
// { fn: corsMiddleware, priority: 50, sourceIndex: 0, sourcePath: '/api/' },
// { fn: authMiddleware, priority: 20, sourceIndex: 1, sourcePath: '/api/' }
// ]
parseDirectoryPriority(dirName) → {Object}
Parses directory name for priority prefix, extracts route name, and detects route type
Parameters:
Name | Type | Description |
---|---|---|
dirName |
string | Directory name (e.g., "10-users", "users", "05-[id]", "[sessionId]") |
Returns:
- { priority: number, name: string, hasPrefix: boolean, isDynamic: boolean }
- Type
- Object
Examples
// With priority prefix and static route
parseDirectoryPriority("10-users")
// Returns: { priority: 10, name: "users", hasPrefix: true, isDynamic: false }
// With priority prefix and dynamic route
parseDirectoryPriority("05-[userId]")
// Returns: { priority: 5, name: "[userId]", hasPrefix: true, isDynamic: true }
// Without priority prefix (static route)
parseDirectoryPriority("users")
// Returns: { priority: 50, name: "users", hasPrefix: false, isDynamic: false }
// Without priority prefix (dynamic route)
parseDirectoryPriority("[sessionId]")
// Returns: { priority: 50, name: "[sessionId]", hasPrefix: false, isDynamic: true }
// Invalid priority range (falls back to default)
parseDirectoryPriority("150-invalid")
// Logs: "Invalid priority prefix detected in directory "150-invalid", using default priority 50"
// Returns: { priority: 50, name: "150-invalid", hasPrefix: false, isDynamic: false }
// Invalid priority format (falls back to default)
parseDirectoryPriority("x5-invalid")
// Returns: { priority: 50, name: "x5-invalid", hasPrefix: false, isDynamic: false }
replaceUrlPlaceholders(urlPath) → {string}
Converts URL placeholder syntax [param] to Express parameter syntax :param
Parameters:
Name | Type | Description |
---|---|---|
urlPath |
string | The URL path containing placeholders |
Returns:
- The URL path with Express-style parameters
- Type
- string
Examples
// With single placeholder
replaceUrlPlaceholders('/users/[id]'); // Returns: '/users/:id'
// With multiple placeholders
replaceUrlPlaceholders('/users/[id]/posts/[postId]'); // Returns: '/users/:id/posts/:postId'
// With no placeholders
replaceUrlPlaceholders('/users/list'); // Returns: '/users/list'
// With nested/complex placeholders
replaceUrlPlaceholders('/products/[category]/[id]/reviews/[reviewId]');
// Returns: '/products/:category/:id/reviews/:reviewId'
sortMiddlewareFunctions(middlewareArray) → {Array}
Sorts and flattens middleware functions by four-level priority system
Parameters:
Name | Type | Description |
---|---|---|
middlewareArray |
Array | Array of {fn, priority, sourceIndex, sourcePath} objects |
Returns:
Array of middleware functions sorted by priority
- Type
- Array
Example
// With mixed priority middleware
const middleware = [
{ fn: authMiddleware, priority: 20, sourceIndex: 0, sourcePath: '/api/' },
{ fn: corsMiddleware, priority: 5, sourceIndex: 1, sourcePath: '/api/' },
{ fn: loggingMiddleware, priority: 90, sourceIndex: 0, sourcePath: '/api/users/' }
]
sortMiddlewareFunctions(middleware)
// Returns: [corsMiddleware, authMiddleware, loggingMiddleware]
validatePath(path)
Validates if a path is a non-empty string
Parameters:
Name | Type | Description |
---|---|---|
path |
string | The path to validate |
Throws:
-
If path is not a string or is empty
- Type
- Error
Examples
// With valid path
validatePath('/api/users'); // No error thrown
// With empty string
try {
validatePath('');
} catch (error) {
console.error(error.message); // Outputs: 'Invalid path provided'
}
// With null value
try {
validatePath(null);
} catch (error) {
console.error(error.message); // Outputs: 'Invalid path provided'
}
// With non-string value
try {
validatePath(123);
} catch (error) {
console.error(error.message); // Outputs: 'Invalid path provided'
}