express-fs-routers
Version:
Nextjs Like Api
93 lines (81 loc) • 2.61 kB
JavaScript
const chokidar = require('chokidar');
const fsWalk = require('@nodelib/fs.walk');
const _path_ = require('path');
const withPrifix = (prefix) => {
return new RegExp(`(^\/${prefix}$)|(^\/${prefix}\/.*$)`);
};
/** MOST DEPENDENT FUNCTION **/
const getRouteByPath = (_path) => {
let path = _path.replace(/\\/g, '/');
if (path.endsWith('.js')) {
// Check For Dynamic Route Like -> [hey]/[id].js
const matches = path.match(/\[[a-z A-Z 0-9]*\]/g);
matches?.map((param) => {
path = path.replace(param, `:${param.slice(1, -1)}`);
});
return `/${path.slice(0, path.endsWith('index.js') ? -9 : -3)}`;
}
};
const initial_routes = (path) => {
const result = [];
fsWalk.walkSync(path).map((e) => {
if (e.dirent.isFile()) result.push(e.path);
});
return result;
};
const resolveModulesPath = (_path) => {
return _path_.resolve(`./${_path.replace(/\\/g, '/')}`);
};
/* Excecution Context */
const watchFsRouter = (app, path) => {
chokidar
.watch(path)
.on('add', (_path, _event) => {
console.log(path);
try {
const handler = require(resolveModulesPath(_path));
if (handler) app.all(getRouteByPath(_path), handler);
} catch (error) {
console.error(error);
}
})
.on('change', (_path, _event) => {
try {
delete require.cache[require.resolve(resolveModulesPath(_path))];
app._router.stack.forEach((route, i, routes) => {
if (route.route?.path == getRouteByPath(_path)) {
app._router.stack.splice(i, 1);
// console.log('Matched Route', route.route?.path);
}
});
const handler = require(resolveModulesPath(_path));
if (handler) app.all(getRouteByPath(_path), handler);
} catch (error) {
console.error(error);
}
})
.on('unlink', (_path, _event) => {
app._router.stack.forEach((route, i, routes) => {
if (route.route?.path == getRouteByPath(_path)) {
app._router.stack.splice(i, 1);
// console.log('Matched Route', route.route?.path);
}
});
delete require.cache[require.resolve(resolveModulesPath(_path))];
});
};
const useFsRouter = (app, path) => {
initial_routes(path).map((r) => {
try {
const handler = require(resolveModulesPath(r));
if (handler) app.all(getRouteByPath(r), handler);
} catch (error) {
console.log(error);
}
});
};
module.exports = {
watchFsRouter,
useFsRouter,
getRouteByPath,
};