@iridium/dev-server
Version:
Run now project in local
89 lines (72 loc) • 2.53 kB
JavaScript
const url = require('url');
const http = require('http');
const qs = require('querystring');
const dir = process.cwd();
const fs = require('fs');
const { join, resolve } = require('path');
const chokidar = require('chokidar');
const nowDir = resolve(`${dir}/now.json`);
const lambdas = {};
function requireUncached(pkg) {
delete require.cache[require.resolve(pkg)];
return require(pkg);
}
function runner(port = 3000, watch = false) {
if (!fs.existsSync(nowDir)) console.log('now.json is required') || process.exit(0);
if (watch)
chokidar
.watch(dir, {
ignored: ['**/node_modules', '**/.git'],
persistent: true
})
.on('change', path => {
console.log(`File ${path} has been changed`);
resetLambdas();
});
executeServer(port);
}
const resetLambdas = () => Object.keys(lambdas).forEach(key => delete lambdas[key]);
async function executeServer(port = 3000) {
const { routes } = require(nowDir);
const server = http.createServer(async (req, res) => {
const { pathname, href, query } = url.parse(req.url);
const params = qs.parse(query);
const route = routes.find(route => {
const method = route.methods || ['GET'];
if (!method.includes(req.method)) return false;
return pathname.match(route.src);
});
if (!route) return notFound(res);
if (route.status) res.statusCode = route.status;
if (route.headers) for (const header of Object.entries(route.headers)) res.setHeader(...header);
const path = route.dest ? route.dest.split('.')[0] : null;
const rex = new RegExp(route.src.replace(/\//gim, '\\/'), 'gmi');
const { groups } = rex.exec(pathname) || {};
const q = Object.assign({}, params, groups);
req.url = `${href.split('?')[0]}?${qs.stringify(q)}`;
if (!lambdas[path]) {
const lambda = resolve(join(dir, `${path}.js`));
if (fs.existsSync(lambda)) lambdas[path] = requireUncached(lambda);
}
const fn = lambdas[path];
// redirect
if (!fn && res.getHeader('Location')) {
console.log('Redirect to: ', res.getHeader('Location'));
return res.end();
}
// not found
if (!fn) {
console.log('Path of request not found');
return notFound(res);
}
// lambda
console.log('Path of request: ', path);
await fn(req, res);
});
server.listen(port, () => console.log(`> Local server running at port ${port}`));
}
function notFound(res) {
res.writeHead(200);
res.end('Not found');
}
module.exports = runner;