uws-autoload
Version:
Plugin for [µWebSockets.js](https://github.com/uNetworking/uWebSockets.js) that autoloads all routes in a directory.
56 lines (52 loc) • 2.34 kB
JavaScript
import fs from 'node:fs';
import { pathToFileURL } from 'node:url';
const countParams = (filepath) => {
return (filepath.match(/\[(.*?)\]/gu) || []).length;
};
const sortRoutesByParams = (routes) => {
return routes.sort((a, b) => countParams(a) - countParams(b));
};
const transformToRoute = (filepath) => {
return filepath.replace(/\.(ts|tsx|mjs|js|jsx|cjs)$/u, "").replaceAll(/\[\.\.\..*?\]/gu, "*").replaceAll(/\[(.+?)\]/gu, (_, match) => `:${match}`).replace(/\/?\((.*?)\)/, "").replaceAll("]-[", "-:").replaceAll("]/", "/").replaceAll(/\[|\]/gu, "").replace(/\/?index$/, "");
};
const DEFAULT_ROUTES_DIR = "./routes";
const DEFAULT_PATTERN = "**/*.{ts,tsx,mjs,js,jsx,cjs}";
const autoloadRoutes = async (app, {
importKey = "default",
failGlob = true,
pattern = DEFAULT_PATTERN,
prefix = "",
routesDir = DEFAULT_ROUTES_DIR,
skipImportErrors = false
}) => {
if (!fs.existsSync(routesDir)) {
throw new Error(`Directory ${routesDir} doesn't exist`);
}
if (!fs.statSync(routesDir).isDirectory()) {
throw new Error(`${routesDir} isn't a directory`);
}
const files = typeof Bun === "undefined" ? fs.globSync(pattern, { cwd: routesDir }) : await Array.fromAsync(new Bun.Glob(pattern).scan({ cwd: routesDir }));
if (failGlob && files.length === 0) {
throw new Error(`No matches found in ${routesDir} (you can disable this error with 'failGlob' option to false)`);
}
for (const file of sortRoutesByParams(files)) {
const universalFile = file.replaceAll("\\", "/");
const filePath = `${routesDir}/${universalFile}`;
const importedFile = await import(pathToFileURL(filePath).href);
const resolvedImportName = typeof importKey === "string" ? importKey : importKey(importedFile);
const importedRoute = importedFile[resolvedImportName];
if (!importedRoute && !skipImportErrors) {
throw new Error(`${filePath} doesn't export ${resolvedImportName}`);
}
if (typeof importedRoute === "function") {
const matchedFile = universalFile.match(/\/?\((.*?)\)/);
const method = matchedFile ? matchedFile[1] : "get";
const route = `${prefix}/${transformToRoute(universalFile)}`;
app[method](route, importedRoute);
} else {
console.warn(`Exported function of ${filePath} is not a function`);
}
}
return app;
};
export { autoloadRoutes };