url-route-handler
Version:
The library provides a flexible and efficient way to map URL patterns to their respective handler methods. By defining a set of URL patterns and the corresponding handler functions, this package allows seamless routing, ensuring that each url is processed
136 lines (131 loc) • 3.79 kB
JavaScript
'use strict';
var pathToRegexp = require('path-to-regexp');
class RouteLayer {
handle;
name;
params;
path;
regexp;
keys;
constructor(path, options, callback) {
options = options || {};
this.handle = callback;
this.name = callback.name || '<anonymous>';
const { regexp, keys } = pathToRegexp.pathToRegexp(path, options);
this.regexp = regexp;
this.keys = keys;
}
match(path) {
let match;
if (path != null) {
if (path === '/') {
this.params = {};
this.path = '';
return true;
}
if (path === '/*') {
this.params = { '0': decodeParam(path) };
this.path = path;
return true;
}
match = this.regexp.exec(path);
}
if (!match) {
this.params = undefined;
this.path = undefined;
return false;
}
this.params = {};
this.path = match[0];
var keys = this.keys;
var params = this.params;
for (var i = 1; i < match.length; i++) {
var key = keys[i - 1];
var prop = key.name;
var val = decodeParam(match[i]);
if (val !== undefined || !(Object.hasOwnProperty.call(params, prop))) {
params[prop] = val;
}
}
return true;
}
handleError(err) {
return {
status: 'error',
message: err.message,
};
}
handleRequest(urlObj, ...args) {
try {
const result = this.handle(urlObj, ...args);
if (isPromise(result)) {
return result.then((res) => {
return {
status: 'success',
data: res,
};
}).catch((err) => {
return this.handleError(err);
});
}
return {
status: 'success',
data: result,
};
}
catch (err) {
return this.handleError(err);
}
}
}
function isPromise(obj) {
return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function';
}
function decodeParam(val) {
if (typeof val !== 'string' || val.length === 0) {
return val;
}
try {
return decodeURIComponent(val);
}
catch (err) {
if (err instanceof URIError) {
err.message = 'Failed to decode param \'' + val + '\'';
err.status = 400;
}
throw err;
}
}
class Router {
layers = [];
use(path, callback) {
this.layers.push(new RouteLayer(path, {}, callback));
}
handle(url, ...args) {
const urlObj = new URL(url, 'http://localhost');
for (const layer of this.layers) {
if (layer.match(urlObj.pathname)) {
const queryParam = {};
urlObj.searchParams?.forEach((value, key) => {
queryParam[key] = value;
});
return layer.handleRequest({
url: urlObj.href,
host: urlObj.host,
origin: urlObj.origin,
pathname: urlObj.pathname,
protocol: urlObj.protocol,
query: queryParam,
params: { ...layer.params },
hash: urlObj.hash?.slice(1),
}, ...args);
}
}
return {
status: 'error',
message: 'No route found',
};
}
}
exports.Router = Router;
//# sourceMappingURL=index.cjs.map