@stencil/core
Version:
A Compiler for Web Components and Progressive Web Apps
915 lines (896 loc) • 30 kB
JavaScript
;
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var node = require('../sys/node');
var utils = require('../utils');
var path = require('path');
var path__default = _interopDefault(path);
var querystring = require('querystring');
var Url = require('url');
var zlib = require('zlib');
var buffer = require('buffer');
var net = require('net');
var fs = require('fs');
var http = require('http');
var https = require('https');
function sendMsg(process, msg) {
process.send(msg);
}
function sendError(process, e) {
const msg = {
error: {
message: e
}
};
if (typeof e === 'string') {
msg.error.message = e + '';
}
else if (e) {
Object.keys(e).forEach(key => {
try {
msg.error[key] = e[key] + '';
}
catch (idk) {
console.log(idk);
}
});
}
sendMsg(process, msg);
}
function responseHeaders(headers) {
return Object.assign({}, DEFAULT_HEADERS, headers);
}
const DEFAULT_HEADERS = {
'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0',
'Expires': '0',
'X-Powered-By': 'Stencil Dev Server',
'Access-Control-Allow-Origin': '*'
};
function getBrowserUrl(protocol, address, port, basePath, pathname) {
address = (address === `0.0.0.0`) ? `localhost` : address;
const portSuffix = (!port || port === 80 || port === 443) ? '' : (':' + port);
let path = basePath;
if (pathname.startsWith('/')) {
pathname = pathname.substring(1);
}
path += pathname;
protocol = protocol.replace(/\:/g, '');
return `${protocol}://${address}${portSuffix}${path}`;
}
function getDevServerClientUrl(devServerConfig, host) {
let address = devServerConfig.address;
let port = devServerConfig.port;
if (host) {
address = host;
port = null;
}
return getBrowserUrl(devServerConfig.protocol, address, port, devServerConfig.basePath, DEV_SERVER_URL);
}
function getContentType(devServerConfig, filePath) {
const last = filePath.replace(/^.*[/\\]/, '').toLowerCase();
const ext = last.replace(/^.*\./, '').toLowerCase();
const hasPath = last.length < filePath.length;
const hasDot = ext.length < last.length - 1;
return ((hasDot || !hasPath) && devServerConfig.contentTypes[ext]) || 'application/octet-stream';
}
function isHtmlFile(filePath) {
filePath = filePath.toLowerCase().trim();
return (filePath.endsWith('.html') || filePath.endsWith('.htm'));
}
function isCssFile(filePath) {
filePath = filePath.toLowerCase().trim();
return filePath.endsWith('.css');
}
const TXT_EXT = ['css', 'html', 'htm', 'js', 'json', 'svg', 'xml'];
function isSimpleText(filePath) {
const ext = filePath.toLowerCase().trim().split('.').pop();
return TXT_EXT.includes(ext);
}
function isDevClient(pathname) {
return pathname.startsWith(DEV_SERVER_URL);
}
function isOpenInEditor(pathname) {
return pathname === OPEN_IN_EDITOR_URL;
}
function isInitialDevServerLoad(pathname) {
return pathname === DEV_SERVER_INIT_URL;
}
function isDevServerClient(pathname) {
return pathname === DEV_SERVER_URL;
}
const DEV_SERVER_URL = '/~dev-server';
const DEV_SERVER_INIT_URL = `${DEV_SERVER_URL}-init`;
const OPEN_IN_EDITOR_URL = `${DEV_SERVER_URL}-open-in-editor`;
function shouldCompress(devServerConfig, req) {
if (!devServerConfig.gzip) {
return false;
}
if (req.method !== 'GET') {
return false;
}
const acceptEncoding = req.headers && req.headers['accept-encoding'];
if (typeof acceptEncoding !== 'string') {
return false;
}
if (!acceptEncoding.includes('gzip')) {
return false;
}
return true;
}
function serve500(devServerConfig, req, res, error) {
try {
res.writeHead(500, responseHeaders({
'Content-Type': 'text/plain'
}));
let errorMsg = '';
if (typeof error === 'string') {
errorMsg = error;
}
else if (error) {
if (error.message) {
errorMsg += error.message + '\n';
}
if (error.stack) {
errorMsg += error.stack + '\n';
}
}
res.write(errorMsg);
res.end();
if (devServerConfig.logRequests) {
sendMsg(process, {
requestLog: {
method: req.method,
url: req.url,
status: 200
}
});
}
}
catch (e) {
sendError(process, 'serve500: ' + e);
}
}
async function serve404(devServerConfig, fs, req, res) {
try {
if (req.pathname === '/favicon.ico') {
try {
const defaultFavicon = path.join(devServerConfig.devServerDir, 'static', 'favicon.ico');
res.writeHead(200, responseHeaders({
'Content-Type': 'image/x-icon'
}));
fs.createReadStream(defaultFavicon).pipe(res);
return;
}
catch (e) { }
}
const content = [
'404 File Not Found',
'Url: ' + req.pathname,
'File: ' + req.filePath
].join('\n');
serve404Content(devServerConfig, req, res, content);
if (devServerConfig.logRequests) {
sendMsg(process, {
requestLog: {
method: req.method,
url: req.url,
status: 404
}
});
}
}
catch (e) {
serve500(devServerConfig, req, res, e);
}
}
function serve404Content(devServerConfig, req, res, content) {
try {
const headers = responseHeaders({
'Content-Type': 'text/plain'
});
res.writeHead(404, headers);
res.write(content);
res.end();
}
catch (e) {
serve500(devServerConfig, req, res, e);
}
}
async function serveFile(devServerConfig, fs, req, res) {
try {
if (isSimpleText(req.filePath)) {
// easy text file, use the internal cache
let content = await fs.readFile(req.filePath);
if (devServerConfig.websocket && isHtmlFile(req.filePath) && !isDevServerClient(req.pathname)) {
// auto inject our dev server script
content += getDevServerClientScript(devServerConfig, req);
}
else if (isCssFile(req.filePath)) {
content = updateStyleUrls(req.url, content);
}
if (shouldCompress(devServerConfig, req)) {
// let's gzip this well known web dev text file
res.writeHead(200, responseHeaders({
'Content-Type': getContentType(devServerConfig, req.filePath),
'Content-Encoding': 'gzip',
'Vary': 'Accept-Encoding'
}));
zlib.gzip(content, { level: 9 }, (_, data) => {
res.end(data);
});
}
else {
// let's not gzip this file
res.writeHead(200, responseHeaders({
'Content-Type': getContentType(devServerConfig, req.filePath),
'Content-Length': buffer.Buffer.byteLength(content, 'utf8')
}));
res.write(content);
res.end();
}
}
else {
// non-well-known text file or other file, probably best we use a stream
// but don't bother trying to gzip this file for the dev server
res.writeHead(200, responseHeaders({
'Content-Type': getContentType(devServerConfig, req.filePath),
'Content-Length': req.stats.size
}));
fs.createReadStream(req.filePath).pipe(res);
}
if (devServerConfig.logRequests) {
sendMsg(process, {
requestLog: {
method: req.method,
url: req.url,
status: 200
}
});
}
}
catch (e) {
serve500(devServerConfig, req, res, e);
}
}
function updateStyleUrls(cssUrl, oldCss) {
const parsedUrl = Url.parse(cssUrl);
const qs = querystring.parse(parsedUrl.query);
const versionId = qs['s-hmr'];
const hmrUrls = qs['s-hmr-urls'];
if (versionId && hmrUrls) {
hmrUrls.split(',').forEach(hmrUrl => {
urlVersionIds.set(hmrUrl, versionId);
});
}
const reg = /url\((['"]?)(.*)\1\)/ig;
let result;
let newCss = oldCss;
while ((result = reg.exec(oldCss)) !== null) {
const oldUrl = result[2];
const parsedUrl = Url.parse(oldUrl);
const fileName = path__default.basename(parsedUrl.pathname);
const versionId = urlVersionIds.get(fileName);
if (!versionId) {
continue;
}
const qs = querystring.parse(parsedUrl.query);
qs['s-hmr'] = versionId;
parsedUrl.search = querystring.stringify(qs);
const newUrl = Url.format(parsedUrl);
newCss = newCss.replace(oldUrl, newUrl);
}
return newCss;
}
const urlVersionIds = new Map();
function getDevServerClientScript(devServerConfig, req) {
const devServerClientUrl = getDevServerClientUrl(devServerConfig, req.host);
return `\n<iframe title="Stencil Dev Server Connector ⚡" src="${devServerClientUrl}" style="display:block;width:0;height:0;border:0"></iframe>`;
}
const openInEditorPath = path.join(__dirname, '..', 'sys', 'node', 'open-in-editor.js');
async function serveOpenInEditor(devServerConfig, fs, req, res) {
let status = 200;
const data = {};
try {
if (devServerConfig.editors.length > 0) {
await parseData(devServerConfig, fs, req, data);
await openInEditor(data);
}
else {
data.error = `no editors available`;
}
}
catch (e) {
data.error = e + '';
status = 500;
}
res.writeHead(status, responseHeaders({
'Content-Type': 'application/json'
}));
res.write(JSON.stringify(data, null, 2));
res.end();
}
async function parseData(devServerConfig, fs, req, data) {
const query = Url.parse(req.url).query;
const qs = querystring.parse(query);
if (typeof qs.file !== 'string') {
data.error = `missing file`;
return;
}
data.file = qs.file;
if (qs.line != null && !isNaN(qs.line)) {
data.line = parseInt(qs.line, 10);
}
if (typeof data.line !== 'number' || data.line < 1) {
data.line = 1;
}
if (qs.column != null && !isNaN(qs.column)) {
data.column = parseInt(qs.column, 10);
}
if (typeof data.column !== 'number' || data.column < 1) {
data.column = 1;
}
if (typeof qs.editor === 'string') {
qs.editor = qs.editor.trim().toLowerCase();
if (devServerConfig.editors.some(e => e.id === qs.editor)) {
data.editor = qs.editor;
}
else {
data.error = `invalid editor: ${qs.editor}`;
return;
}
}
else {
data.editor = devServerConfig.editors[0].id;
}
try {
const stat = await fs.stat(data.file);
data.exists = stat.isFile();
}
catch (e) {
data.exists = false;
}
}
async function openInEditor(data) {
if (!data.exists || data.error) {
return;
}
try {
const opts = {
editor: data.editor
};
const oie = require(openInEditorPath);
const editor = oie.openInEditor.configure(opts, (err) => data.error = err + '');
if (data.error) {
return;
}
data.open = `${data.file}:${data.line}:${data.column}`;
await editor.open(data.open);
}
catch (e) {
data.error = e + '';
}
}
async function getEditors() {
const editors = [];
try {
const oie = require(openInEditorPath);
await Promise.all(Object.keys(oie.editors).map(async (id) => {
const isSupported = await isEditorSupported(oie, id);
editors.push({
id: id,
priority: EDITOR_PRIORITY[id],
supported: isSupported
});
}));
}
catch (e) { }
return editors
.filter(e => e.supported)
.sort((a, b) => {
if (a.priority < b.priority)
return -1;
if (a.priority > b.priority)
return 1;
return 0;
}).map(e => {
return {
id: e.id,
name: EDITORS[e.id]
};
});
}
async function isEditorSupported(oie, editor) {
let isSupported = false;
try {
await oie.editors[editor].detect();
isSupported = true;
}
catch (e) { }
return isSupported;
}
const EDITORS = {
atom: 'Atom',
code: 'Code',
emacs: 'Emacs',
idea14ce: 'IDEA 14 Community Edition',
phpstorm: 'PhpStorm',
sublime: 'Sublime',
webstorm: 'WebStorm',
vim: 'Vim',
visualstudio: 'Visual Studio',
};
const EDITOR_PRIORITY = {
code: 1,
atom: 2,
sublime: 3,
visualstudio: 4,
idea14ce: 5,
webstorm: 6,
phpstorm: 7,
vim: 8,
emacs: 9,
};
async function serveDevClient(devServerConfig, fs, req, res) {
try {
if (isOpenInEditor(req.pathname)) {
return serveOpenInEditor(devServerConfig, fs, req, res);
}
if (isDevServerClient(req.pathname)) {
return serveDevClientScript(devServerConfig, fs, req, res);
}
if (isInitialDevServerLoad(req.pathname)) {
req.filePath = path__default.join(devServerConfig.devServerDir, 'templates', 'initial-load.html');
}
else {
const staticFile = req.pathname.replace(DEV_SERVER_URL + '/', '');
req.filePath = path__default.join(devServerConfig.devServerDir, 'static', staticFile);
}
try {
req.stats = await fs.stat(req.filePath);
return serveFile(devServerConfig, fs, req, res);
}
catch (e) {
return serve404(devServerConfig, fs, req, res);
}
}
catch (e) {
return serve500(devServerConfig, req, res, e);
}
}
async function serveDevClientScript(devServerConfig, fs, req, res) {
const filePath = path__default.join(devServerConfig.devServerDir, 'static', 'dev-server-client.html');
let content = await fs.readFile(filePath);
const devClientConfig = {
basePath: devServerConfig.basePath,
editors: devServerConfig.editors,
reloadStrategy: devServerConfig.reloadStrategy
};
content = content.replace('window.__DEV_CLIENT_CONFIG__', JSON.stringify(devClientConfig));
res.writeHead(200, responseHeaders({
'Content-Type': 'text/html'
}));
res.write(content);
res.end();
if (devServerConfig.logRequests) {
sendMsg(process, {
requestLog: {
method: req.method,
url: req.url,
status: 200
}
});
}
}
async function serveDirectoryIndex(devServerConfig, fs, req, res) {
try {
const indexFilePath = path__default.join(req.filePath, 'index.html');
req.stats = await fs.stat(indexFilePath);
if (req.stats.isFile()) {
req.filePath = indexFilePath;
return serveFile(devServerConfig, fs, req, res);
}
}
catch (e) { }
if (!req.pathname.endsWith('/')) {
if (devServerConfig.logRequests) {
sendMsg(process, {
requestLog: {
method: req.method,
url: req.url,
status: 302
}
});
}
res.writeHead(302, {
'location': req.pathname + '/'
});
return res.end();
}
try {
const dirItemNames = await fs.readdir(req.filePath);
try {
const dirTemplatePath = path__default.join(devServerConfig.devServerDir, 'templates', 'directory-index.html');
const dirTemplate = await fs.readFile(dirTemplatePath);
const files = await getFiles(fs, req.filePath, req.pathname, dirItemNames);
const templateHtml = dirTemplate
.replace('{{title}}', getTitle(req.pathname))
.replace('{{nav}}', getName(req.pathname))
.replace('{{files}}', files);
res.writeHead(200, responseHeaders({
'Content-Type': 'text/html',
'X-Directory-Index': req.pathname
}));
res.write(templateHtml);
res.end();
if (devServerConfig.logRequests) {
sendMsg(process, {
requestLog: {
method: req.method,
url: req.url,
status: 200
}
});
}
}
catch (e) {
serve500(devServerConfig, req, res, e);
}
}
catch (e) {
serve404(devServerConfig, fs, req, res);
}
}
async function getFiles(fs, filePath, urlPathName, dirItemNames) {
const items = await getDirectoryItems(fs, filePath, urlPathName, dirItemNames);
if (urlPathName !== '/') {
items.unshift({
isDirectory: true,
pathname: '../',
name: '..'
});
}
return items
.map(item => {
return (`
<li class="${item.isDirectory ? 'directory' : 'file'}">
<a href="${item.pathname}">
<span class="icon"></span>
<span>${item.name}</span>
</a>
</li>`);
})
.join('');
}
async function getDirectoryItems(fs, filePath, urlPathName, dirItemNames) {
const items = await Promise.all(dirItemNames.map(async (dirItemName) => {
const absPath = path__default.join(filePath, dirItemName);
const stats = await fs.stat(absPath);
const item = {
name: dirItemName,
pathname: Url.resolve(urlPathName, dirItemName),
isDirectory: stats.isDirectory()
};
return item;
}));
return items;
}
function getTitle(pathName) {
return pathName;
}
function getName(pathName) {
const dirs = pathName.split('/');
dirs.pop();
let url = '';
return dirs.map((dir, index) => {
url += dir + '/';
const text = (index === 0 ? `~` : dir);
return `<a href="${url}">${text}</a>`;
}).join('<span>/</span>') + '<span>/</span>';
}
function createRequestHandler(devServerConfig, fs) {
return async function (incomingReq, res) {
try {
const req = normalizeHttpRequest(devServerConfig, incomingReq);
if (req.url === '') {
res.writeHead(302, { 'location': '/' });
if (devServerConfig.logRequests) {
sendMsg(process, {
requestLog: {
method: req.method,
url: req.url,
status: 302
}
});
}
return res.end();
}
if (isDevClient(req.pathname) && devServerConfig.websocket) {
return serveDevClient(devServerConfig, fs, req, res);
}
if (!req.url.startsWith(devServerConfig.basePath)) {
if (devServerConfig.logRequests) {
sendMsg(process, {
requestLog: {
method: req.method,
url: req.url,
status: 404
}
});
}
return serve404Content(devServerConfig, req, res, `404 File Not Found, base path: ${devServerConfig.basePath}`);
}
try {
req.stats = await fs.stat(req.filePath);
if (req.stats.isFile()) {
return serveFile(devServerConfig, fs, req, res);
}
if (req.stats.isDirectory()) {
return serveDirectoryIndex(devServerConfig, fs, req, res);
}
}
catch (e) { }
if (isValidHistoryApi(devServerConfig, req)) {
try {
const indexFilePath = path__default.join(devServerConfig.root, devServerConfig.historyApiFallback.index);
req.stats = await fs.stat(indexFilePath);
if (req.stats.isFile()) {
req.filePath = indexFilePath;
return serveFile(devServerConfig, fs, req, res);
}
}
catch (e) { }
}
return serve404(devServerConfig, fs, req, res);
}
catch (e) {
return serve500(devServerConfig, incomingReq, res, e);
}
};
}
function normalizeHttpRequest(devServerConfig, incomingReq) {
const req = {
method: (incomingReq.method || 'GET').toUpperCase(),
headers: incomingReq.headers,
acceptHeader: (incomingReq.headers && typeof incomingReq.headers.accept === 'string' && incomingReq.headers.accept) || '',
url: (incomingReq.url || '').trim() || '',
host: (incomingReq.headers && typeof incomingReq.headers.host === 'string' && incomingReq.headers.host) || null
};
const parsedUrl = Url.parse(req.url);
const parts = (parsedUrl.pathname || '').replace(/\\/g, '/').split('/');
req.pathname = parts.map(part => decodeURIComponent(part)).join('/');
if (req.pathname.length > 0 && !isDevClient(req.pathname)) {
req.pathname = '/' + req.pathname.substring(devServerConfig.basePath.length);
}
req.filePath = utils.normalizePath(path__default.normalize(path__default.join(devServerConfig.root, path__default.relative('/', req.pathname))));
return req;
}
function isValidHistoryApi(devServerConfig, req) {
if (!devServerConfig.historyApiFallback) {
return false;
}
if (req.method !== 'GET') {
return false;
}
if (!req.acceptHeader.includes('text/html')) {
return false;
}
if (!devServerConfig.historyApiFallback.disableDotRule && req.pathname.includes('.')) {
return false;
}
return true;
}
async function findClosestOpenPort(host, port) {
async function t(portToCheck) {
const isTaken = await isPortTaken(host, portToCheck);
if (!isTaken) {
return portToCheck;
}
return t(portToCheck + 1);
}
return t(port);
}
function isPortTaken(host, port) {
return new Promise((resolve, reject) => {
const tester = net.createServer()
.once('error', () => {
resolve(true);
})
.once('listening', () => {
tester.once('close', () => {
resolve(false);
})
.close();
})
.on('error', (err) => {
reject(err);
})
.listen(port, host);
});
}
// import getDevelopmentCertificate from 'devcert-san';
async function getSSL() {
const cert = await installSSL();
return {
key: fs.readFileSync(cert.keyPath, 'utf-8'),
cert: fs.readFileSync(cert.certPath, 'utf-8')
};
}
async function installSSL() {
// try {
// // Certificates are cached by name, so two calls for getDevelopmentCertificate('foo') will return the same key and certificate
// return getDevelopmentCertificate('stencil-dev-server-ssl', {
// installCertutil: true
// });
// } catch (err) {
// throw new Error(`Failed to generate dev SSL certificate: ${err}\n`);
// }
}
async function createHttpServer(devServerConfig, fs, destroys) {
// figure out the port to be listening on
// by figuring out the first one available
devServerConfig.port = await findClosestOpenPort(devServerConfig.address, devServerConfig.port);
// create our request handler
const reqHandler = createRequestHandler(devServerConfig, fs);
let server;
if (devServerConfig.protocol === 'https') {
// https server
server = https.createServer(await getSSL(), reqHandler);
}
else {
// http server
server = http.createServer(reqHandler);
}
destroys.push(() => {
// close down the serve on destroy
server.close();
server = null;
});
return server;
}
const WebSocket = require('../sys/node/websocket').WebSocket;
function createWebSocket(process, httpServer, destroys) {
const wsConfig = {
server: httpServer
};
const wsServer = new WebSocket.Server(wsConfig);
function heartbeat() {
this.isAlive = true;
}
wsServer.on('connection', (ws) => {
ws.on('message', (data) => {
// the server process has received a message from the browser
// pass the message received from the browser to the main cli process
process.send(JSON.parse(data.toString()));
});
ws.isAlive = true;
ws.on('pong', heartbeat);
});
const pingInternval = setInterval(() => {
wsServer.clients.forEach((ws) => {
if (!ws.isAlive) {
return ws.close(1000);
}
ws.isAlive = false;
ws.ping(utils.noop);
});
}, 10000);
function onMessageFromCli(msg) {
// the server process has received a message from the cli's main thread
// pass the data to each web socket for each browser/tab connected
if (msg) {
const data = JSON.stringify(msg);
wsServer.clients.forEach(ws => {
if (ws.readyState === ws.OPEN) {
ws.send(data);
}
});
}
}
process.addListener('message', onMessageFromCli);
destroys.push(() => {
clearInterval(pingInternval);
wsServer.clients.forEach(ws => {
ws.close(1000);
});
});
}
/*
* exit
* https://github.com/cowboy/node-exit
*
* Copyright (c) 2013 "Cowboy" Ben Alman
* Licensed under the MIT license.
*/
var exit = function exit(exitCode, streams) {
if (!streams) { streams = [process.stdout, process.stderr]; }
var drainCount = 0;
// Actually exit if all streams are drained.
function tryToExit() {
if (drainCount === streams.length) {
process.exit(exitCode);
}
}
streams.forEach(function(stream) {
// Count drained streams now, but monitor non-drained streams.
if (stream.bufferSize === 0) {
drainCount++;
} else {
stream.write('', 'utf-8', function() {
drainCount++;
tryToExit();
});
}
// Prevent further writing.
stream.write = function() {};
});
// If all streams were already drained, exit now.
tryToExit();
// In Windows, when run as a Node.js child process, a script utilizing
// this library might just exit with a 0 exit code, regardless. This code,
// despite the fact that it looks a bit crazy, appears to fix that.
process.on('exit', function() {
process.exit(exitCode);
});
};
async function startDevServerWorker(process, devServerConfig, fs) {
try {
const destroys = [];
devServerConfig.editors = await getEditors();
// create the http server listening for and responding to requests from the browser
let httpServer = await createHttpServer(devServerConfig, fs, destroys);
if (devServerConfig.websocket) {
// upgrade web socket requests the server receives
createWebSocket(process, httpServer, destroys);
}
// start listening!
httpServer.listen(devServerConfig.port, devServerConfig.address);
// have the server worker send a message to the main cli
// process that the server has successfully started up
sendMsg(process, {
serverStated: {
browserUrl: getBrowserUrl(devServerConfig.protocol, devServerConfig.address, devServerConfig.port, devServerConfig.basePath, '/'),
initialLoadUrl: getBrowserUrl(devServerConfig.protocol, devServerConfig.address, devServerConfig.port, devServerConfig.basePath, devServerConfig.initialLoadUrl || DEV_SERVER_INIT_URL)
}
});
const closeServer = () => {
// probably recived a SIGINT message from the parent cli process
// let's do our best to gracefully close everything down first
destroys.forEach(destroy => {
destroy();
});
destroys.length = 0;
httpServer = null;
setTimeout(() => {
exit(0);
}, 5000).unref();
process.removeAllListeners('message');
};
process.once('SIGINT', closeServer);
}
catch (e) {
sendError(process, e);
}
}
async function startServer(devServerConfig) {
// received a message from main to start the server
try {
const fs = new node.NodeFs(process);
devServerConfig.contentTypes = await loadContentTypes(fs);
startDevServerWorker(process, devServerConfig, fs);
}
catch (e) {
sendError(process, e);
}
}
async function loadContentTypes(fs) {
const contentTypePath = path__default.join(__dirname, 'content-type-db.json');
const contentTypeJson = await fs.readFile(contentTypePath);
return JSON.parse(contentTypeJson);
}
process.on('message', (msg) => {
if (msg.startServer) {
startServer(msg.startServer);
}
});
process.on('unhandledRejection', (e) => {
console.log(e);
});