@whatwg-node/router
Version:
Fetch API compliant HTTP Router
138 lines (133 loc) • 5.1 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
const server = require('@whatwg-node/server');
const fetch = require('@whatwg-node/fetch');
const HTTP_METHODS = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH'];
function createRouter(options) {
var _a;
const routesByMethod = new Map();
function addHandlersToMethod(method, path, ...handlers) {
let methodPatternMaps = routesByMethod.get(method);
if (!methodPatternMaps) {
methodPatternMaps = new Map();
routesByMethod.set(method, methodPatternMaps);
}
const basePath = (options === null || options === void 0 ? void 0 : options.base) || '/';
let fullPath = '';
if (basePath === '/') {
fullPath = path;
}
else if (path === '/') {
fullPath = basePath;
}
else {
fullPath = `${basePath}${path}`;
}
const pattern = new fetch.URLPattern({ pathname: fullPath });
methodPatternMaps.set(pattern, handlers);
}
async function handleRequest(request, context) {
const method = request.method;
let _parsedUrl;
function getParsedUrl() {
if (!_parsedUrl) {
_parsedUrl = new URL(request.url);
}
return _parsedUrl;
}
const methodPatternMaps = routesByMethod.get(method);
if (methodPatternMaps) {
const queryProxy = new Proxy({}, {
get(_, prop) {
const parsedUrl = getParsedUrl();
const allQueries = parsedUrl.searchParams.getAll(prop.toString());
return allQueries.length === 1 ? allQueries[0] : allQueries;
},
has(_, prop) {
const parsedUrl = getParsedUrl();
return parsedUrl.searchParams.has(prop.toString());
},
});
for (const [pattern, handlers] of methodPatternMaps) {
const match = pattern.exec(request.url);
if (match) {
const routerRequest = new Proxy(request, {
get(target, prop) {
if (prop === 'parsedUrl') {
return getParsedUrl();
}
if (prop === 'params') {
return match.pathname.groups;
}
if (prop === 'query') {
return queryProxy;
}
const targetProp = target[prop];
if (typeof targetProp === 'function') {
return targetProp.bind(target);
}
return targetProp;
},
has(target, prop) {
return prop in target || prop === 'parsedUrl' || prop === 'params' || prop === 'query';
},
});
for (const handler of handlers) {
const result = await handler(routerRequest, context);
if (result) {
return result;
}
}
}
}
}
}
let routerBaseObject = new Proxy({}, {
get(_, prop) {
if (prop === 'handle') {
return handleRequest;
}
const method = prop.toString().toLowerCase();
return function routeMethodKeyFn(path, ...handlers) {
if (method === 'all') {
for (const httpMethod of HTTP_METHODS) {
addHandlersToMethod(httpMethod, path, ...handlers);
}
}
else {
addHandlersToMethod(method.toUpperCase(), path, ...handlers);
}
return this;
};
},
});
(_a = options === null || options === void 0 ? void 0 : options.plugins) === null || _a === void 0 ? void 0 : _a.forEach(plugin => {
routerBaseObject = plugin(routerBaseObject);
});
return server.createServerAdapter(routerBaseObject, (options === null || options === void 0 ? void 0 : options.RequestCtor) || fetch.Request);
}
Object.defineProperty(exports, 'withCORS', {
enumerable: true,
get: function () {
return server.withCORS;
}
});
Object.defineProperty(exports, 'withErrorHandling', {
enumerable: true,
get: function () {
return server.withErrorHandling;
}
});
Object.defineProperty(exports, 'Response', {
enumerable: true,
get: function () {
return fetch.Response;
}
});
Object.defineProperty(exports, 'URLPattern', {
enumerable: true,
get: function () {
return fetch.URLPattern;
}
});
exports.createRouter = createRouter;