reboost
Version:
A super fast dev server for rapid web development
101 lines (100 loc) • 4.48 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.messageClient = exports.createProxyServer = exports.createRouter = void 0;
const tslib_1 = require("tslib");
const koa_1 = (0, tslib_1.__importDefault)(require("koa"));
const cors_1 = (0, tslib_1.__importDefault)(require("@koa/cors"));
const ws_1 = (0, tslib_1.__importDefault)(require("ws"));
const fs_1 = (0, tslib_1.__importDefault)(require("fs"));
const path_1 = (0, tslib_1.__importDefault)(require("path"));
const import_resolver_1 = require("./transformer/import-resolver");
const file_handler_1 = require("./file-handler");
const utils_1 = require("./utils");
const webSockets = new Set();
const createRouter = (instance) => {
const routedPaths = {};
routedPaths['/transformed'] = (0, file_handler_1.createFileHandler)(instance);
const loadRuntimeCode = () => (fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../browser/runtime.js'), 'utf8'));
const runtimeCode = loadRuntimeCode();
routedPaths['/runtime'] = (ctx) => {
ctx.type = 'text/javascript';
ctx.body = `const address = "${instance.proxyAddress}";\n`;
ctx.body += `const debugMode = ${instance.config.debugMode};\n`;
ctx.body += `const mode = "${instance.config.mode}";\n`;
ctx.body += `const hotReload = ${instance.config.hotReload};\n\n`;
ctx.body += instance.config.debugMode ? loadRuntimeCode() : runtimeCode;
};
const eTagKey = (0, utils_1.uniqueID)(10) + '-';
routedPaths['/raw'] = async (ctx) => {
const filePath = ctx.query.q;
try {
const stat = await fs_1.default.promises.stat(filePath);
const etag = eTagKey + Math.floor(stat.mtimeMs);
if (ctx.get('If-None-Match') === etag) {
ctx.status = 304;
}
else {
ctx.body = fs_1.default.createReadStream(filePath);
ctx.set('Content-Length', stat.size + '');
ctx.set('ETag', etag);
}
}
catch (e) { /* The file probably doesn't exist */ }
};
routedPaths['/hot'] = (ctx) => {
ctx.type = 'text/javascript';
ctx.body = 'import { Hot } from "/runtime";\n';
ctx.body += `export const hot = new Hot(${JSON.stringify(ctx.query.q)});`;
};
const importerCode = fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../browser/importer.js'), 'utf8');
routedPaths['/importer'] = (ctx) => {
ctx.type = 'text/javascript';
ctx.body = `const address = "${instance.proxyAddress}";\n`;
ctx.body += `const commonJSInteropMode = ${instance.config.commonJSInterop.mode};\n\n`;
ctx.body += importerCode;
};
routedPaths['/unresolved'] = (ctx) => {
const { query } = ctx;
ctx.type = 'text/javascript';
ctx.body = `
console.error('[reboost] Unable to resolve import ${JSON.stringify(query.import)} of ${JSON.stringify(query.importer)}');
`.trim();
};
routedPaths['/resolve'] = async (ctx) => {
const relativeTo = ctx.query.from;
const pathToResolve = ctx.query.to;
const finalPath = await (0, import_resolver_1.resolveDependency)(instance, pathToResolve, relativeTo);
if (finalPath) {
ctx.type = 'text/plain';
ctx.body = finalPath;
}
};
return async (ctx, next) => {
if (routedPaths[ctx.path]) {
await routedPaths[ctx.path](ctx);
}
return next();
};
};
exports.createRouter = createRouter;
const createProxyServer = (instance) => {
const proxyServer = new koa_1.default();
const router = (0, exports.createRouter)(instance);
proxyServer
.use((0, cors_1.default)({ origin: '*' }))
.use(router);
(0, utils_1.onServerCreated)(proxyServer, (server) => {
const wss = new ws_1.default.Server({ server });
wss.on('connection', (socket) => {
webSockets.add(socket);
socket.on('close', () => webSockets.delete(socket));
});
instance.onStop("Closes proxy server's websocket", () => wss.close());
});
return proxyServer;
};
exports.createProxyServer = createProxyServer;
const messageClient = (message) => {
webSockets.forEach((ws) => ws.send(JSON.stringify(message)));
};
exports.messageClient = messageClient;