reboost
Version:
A super fast dev server for rapid web development
267 lines (266 loc) • 10.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.mergeSourceMaps = exports.getReadableHRTime = exports.getExternalHost = exports.onServerCreated = exports.isVersionLessThan = exports.getTimestamp = exports.diff = exports.bind = exports.serializeObject = exports.objectPaths = exports.observable = exports.deepFreeze = exports.rmDir = exports.isDirectory = exports.ensureDir = exports.clone = exports.merge = exports.isPlainObject = exports.uniqueID = exports.toPosix = void 0;
const tslib_1 = require("tslib");
const source_map_1 = require("source-map");
const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
const fs_1 = (0, tslib_1.__importDefault)(require("fs"));
const path_1 = (0, tslib_1.__importDefault)(require("path"));
const os_1 = (0, tslib_1.__importDefault)(require("os"));
const net_1 = (0, tslib_1.__importDefault)(require("net"));
const toPosix = (pathString) => pathString.replace(/\\/g, '/');
exports.toPosix = toPosix;
const uniqueID = (length = 32) => Array(length).fill(0).map(() => (Math.random() * 16 | 0).toString(16)).join('');
exports.uniqueID = uniqueID;
const isPlainObject = (data) => !!data && data.constructor === Object;
exports.isPlainObject = isPlainObject;
const merge = (source, target) => {
for (const key in target) {
if ((0, exports.isPlainObject)(source[key]) && (0, exports.isPlainObject)(target[key])) {
(0, exports.merge)(source[key], target[key]);
}
else {
source[key] = target[key];
}
}
return source;
};
exports.merge = merge;
const clone = (object) => {
const cloned = Array.isArray(object) ? [] : {};
for (const key in object) {
if ((0, exports.isPlainObject)(object[key]) || Array.isArray(object[key])) {
cloned[key] = (0, exports.clone)(object[key]);
continue;
}
cloned[key] = object[key];
}
return cloned;
};
exports.clone = clone;
const ensureDir = (dirPath) => {
if (!fs_1.default.existsSync(dirPath))
fs_1.default.mkdirSync(dirPath, { recursive: true });
};
exports.ensureDir = ensureDir;
const isDirectory = (dirPath) => fs_1.default.lstatSync(dirPath).isDirectory();
exports.isDirectory = isDirectory;
const rmDir = (dirPath) => {
if (!fs_1.default.existsSync(dirPath))
return;
fs_1.default.readdirSync(dirPath).forEach((file) => {
const filePath = path_1.default.join(dirPath, file);
if ((0, exports.isDirectory)(filePath))
return (0, exports.rmDir)(filePath);
fs_1.default.unlinkSync(filePath);
});
fs_1.default.rmdirSync(dirPath);
};
exports.rmDir = rmDir;
const deepFreeze = (obj) => {
for (const key in obj) {
if ((0, exports.isPlainObject)(obj[key]) || Array.isArray(obj[key])) {
(0, exports.deepFreeze)(obj[key]);
}
}
return Object.freeze(obj);
};
exports.deepFreeze = deepFreeze;
const observable = (object, onChange) => {
const handler = {
set: (target, key, value, receiver) => {
if (typeof value === 'object')
value = (0, exports.observable)(value, onChange);
const result = Reflect.set(target, key, value, receiver);
onChange();
return result;
}
};
Object.keys(object).forEach((key) => {
if (typeof object[key] === 'object') {
object[key] = (0, exports.observable)(object[key], onChange);
}
});
return new Proxy(object, handler);
};
exports.observable = observable;
const objectPaths = (object, pPath) => {
const paths = [];
Object.keys(object).forEach((key) => {
const currentPath = (pPath ? pPath + '.' : '') + key;
if (typeof object[key] === 'object') {
const nestedPaths = (0, exports.objectPaths)(object[key], currentPath);
if (nestedPaths.length)
return paths.push(...nestedPaths);
}
paths.push(currentPath);
});
return paths;
};
exports.objectPaths = objectPaths;
const serializeObject = (object, excludePaths, stringify = true, pPath) => {
if (excludePaths && pPath !== '') {
if (!Array.isArray(excludePaths)) {
excludePaths = (0, exports.objectPaths)(excludePaths);
}
}
const mapper = (key) => {
const currentPath = (pPath ? pPath + '.' : '') + key;
if (excludePaths && excludePaths.includes(currentPath))
return;
let value = object[key];
if (value && typeof value === 'object') {
value = (0, exports.isPlainObject)(value) || Array.isArray(value)
? (0, exports.serializeObject)(value, excludePaths, false, currentPath)
: value.toString
? value.toString()
: '';
}
else if (typeof value === 'function') {
value = value.toString();
}
return [key, value];
};
const serialized = (Array.isArray(object)
? object.map((_, i) => mapper(i))
: Object.keys(object).sort().map(mapper)).filter((a) => a);
return (stringify ? JSON.stringify(serialized) : serialized);
};
exports.serializeObject = serializeObject;
// eslint-disable-next-line @typescript-eslint/ban-types
const bind = (func, bindTo) => func.bind(bindTo);
exports.bind = bind;
const diff = (oldA, newA) => ({
added: newA.filter((a) => !oldA.includes(a)),
removed: oldA.filter((a) => !newA.includes(a))
});
exports.diff = diff;
const getTimestamp = () => {
const date = new Date();
const f = (num) => ('' + num).length === 1 ? '0' + num : num;
return `[${f(date.getHours())}:${f(date.getMinutes())}:${f(date.getSeconds())}]`;
};
exports.getTimestamp = getTimestamp;
const isVersionLessThan = (version, toCompareWith) => {
const [aMajor, aMinor, aPatch] = version.split('.').map(Number);
const [bMajor, bMinor, bPatch] = toCompareWith.split('.').map(Number);
if (aMajor < bMajor)
return true;
if (aMajor > bMajor)
return false;
if (aMinor < bMinor)
return true;
if (aMinor > bMinor)
return false;
if (aPatch < bPatch)
return true;
if (aPatch > bPatch)
return false;
return false;
};
exports.isVersionLessThan = isVersionLessThan;
const onServerCreated = (app, cb) => {
const defaultListenFunc = app.listen;
app.listen = (...args) => {
const server = defaultListenFunc.apply(app, args);
cb(server);
return server;
};
};
exports.onServerCreated = onServerCreated;
const getExternalHost = async (instance) => {
const { externalHost } = instance.config;
if (typeof externalHost === 'string') {
if (!net_1.default.isIPv4(externalHost)) {
return instance.log('info', chalk_1.default.red(`The provided external host address "${externalHost}" is not a valid IPv4 address. ` +
'Please provide a different host address.'));
}
const isServerUsable = await new Promise((resolve) => {
const server = net_1.default.createServer();
server.once('listening', () => {
server.close();
resolve(true);
});
server.once('error', (err) => {
server.close();
if (err.code === 'EADDRNOTAVAIL' || err.code === 'EINVAL') {
resolve(false);
}
});
server.listen(/* Any port number */ 1678, externalHost);
});
if (!isServerUsable) {
return instance.log('info', chalk_1.default.red(`The provided external host "${externalHost}" is not available. ` +
'Please provide a different host address.'));
}
return externalHost;
}
if (externalHost) {
const interfaces = os_1.default.networkInterfaces();
for (const dev in interfaces) {
for (const details of interfaces[dev]) {
if (details.family === 'IPv4' && !details.internal) {
return details.address;
}
}
}
}
};
exports.getExternalHost = getExternalHost;
/* istanbul ignore next */
const getReadableHRTime = ([seconds, nanoseconds]) => {
if (seconds) {
return `${seconds}s ${Math.floor(nanoseconds / 1e6)}ms`;
}
const ms = Math.floor(nanoseconds / 1e6);
return (ms ? `${ms}ms ` : '') + `${Math.floor((nanoseconds % 1e6) / 1e3)}μs`;
};
exports.getReadableHRTime = getReadableHRTime;
const isUndefOrNull = (d) => d === null || d === undefined;
/**
* Forked version of merge-source-map
* Original author KATO Kei
* Licensed under MIT License - https://github.com/keik/merge-source-map/blob/master/LICENSE
*/
const mergeSourceMaps = async (oldMap, newMap) => {
if (!oldMap)
return newMap;
if (!newMap)
return oldMap;
const oldMapConsumer = await new source_map_1.SourceMapConsumer(oldMap);
const newMapConsumer = await new source_map_1.SourceMapConsumer(newMap);
const mergedMapGenerator = new source_map_1.SourceMapGenerator();
newMapConsumer.eachMapping((m) => {
if (isUndefOrNull(m.originalLine))
return;
const origPosInOldMap = oldMapConsumer.originalPositionFor({
line: m.originalLine,
column: m.originalColumn
});
if (isUndefOrNull(origPosInOldMap.source))
return;
mergedMapGenerator.addMapping({
original: {
line: origPosInOldMap.line,
column: origPosInOldMap.column
},
generated: {
line: m.generatedLine,
column: m.generatedColumn
},
source: origPosInOldMap.source,
name: origPosInOldMap.name
});
});
const consumers = [newMapConsumer, oldMapConsumer];
consumers.forEach((consumer) => {
consumer.sources.forEach((sourceFile) => {
const sourceContent = consumer.sourceContentFor(sourceFile);
if (!isUndefOrNull(sourceContent)) {
mergedMapGenerator.setSourceContent(sourceFile, sourceContent);
}
});
});
return JSON.parse(mergedMapGenerator.toString());
};
exports.mergeSourceMaps = mergeSourceMaps;