webpack-mock-server
Version:
Mocks api requests for webpack-dev-server with hot-replacement
182 lines (181 loc) • 8.4 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = compiler;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const typescript_1 = __importDefault(require("typescript"));
const compilerOutRootFiles_1 = __importDefault(require("./compilerOutRootFiles"));
const log_1 = __importDefault(require("./log"));
const versionContainer_1 = __importStar(require("./versionContainer"));
const formatHost = {
getCanonicalFileName: (path) => path,
getCurrentDirectory: typescript_1.default.sys.getCurrentDirectory,
getNewLine: () => typescript_1.default.sys.newLine,
};
function reportDiagnostic(diagnostic) {
var _a;
let linePointer = "";
if (diagnostic.file) {
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start || 0);
linePointer = `in ${(_a = diagnostic.file) === null || _a === void 0 ? void 0 : _a.fileName} (${line + 1},${character + 1})`;
}
log_1.default.error(`TS${diagnostic.code}: ${linePointer}\n${typescript_1.default.flattenDiagnosticMessageText(diagnostic.messageText, formatHost.getNewLine())}`);
}
function clearNodeCache(rootPath) {
Object.keys(require.cache).forEach((key) => {
var _a;
if ((_a = require.cache[key]) === null || _a === void 0 ? void 0 : _a.filename.startsWith(rootPath)) {
log_1.default.debug("delete node-cache for", key);
delete require.cache[key];
}
});
}
function compiler(entry, tsConfigFileName, extendCompilerOptions, onChanged) {
const tsVer = Number.parseFloat(typescript_1.default.versionMajorMinor);
if (tsVer < 2.7) {
throw new Error(`WebpackMockServer. Typescript version >=2.7 is expected. Current is ${typescript_1.default.versionMajorMinor}`);
}
log_1.default.debug(`typescript version: ${typescript_1.default.version}`);
const entries = entry && (Array.isArray(entry) ? entry : [entry]);
entries &&
entries.forEach((v) => {
if (typeof v !== "string") {
throw new Error(`WebpackMockServer. Option [entry]. Only 'string' is expected: ${v}`);
}
if (v.includes("*")) {
throw new Error(`WebpackMockServer. Option [entry]. Wildcard is not supported. Set 'Null' to [entry] and use tsConfig.json with 'files' and 'include' options instead.
More details here: https://github.com/Yegorich555/webpack-mock-server#options`);
}
});
let isOutputChanged = true;
const outMockFiles = new compilerOutRootFiles_1.default();
const emptyWatcher = {
close: () => { },
};
const sysConfig = Object.assign({}, typescript_1.default.sys);
sysConfig.watchFile = function watchFile(path) {
if (path.includes("node_modules")) {
return emptyWatcher;
}
return typescript_1.default.sys.watchFile(...arguments);
};
sysConfig.watchDirectory = function watchDir(path) {
if (path.includes("node_modules")) {
return emptyWatcher;
}
return typescript_1.default.sys.watchDirectory(...arguments);
};
function resolvePathAlias(filePath, path) {
var _a;
const isMatchAlias = definedTSOptions.pathsArr.some((v) => v[0] === filePath[0]);
if (isMatchAlias) {
const m = (_a = typescript_1.default.resolveModuleName(filePath, path, definedTSOptions, host).resolvedModule) === null || _a === void 0 ? void 0 : _a.resolvedFileName;
return m || filePath;
}
return filePath;
}
sysConfig.writeFile = function writeFile(path, data) {
log_1.default.debug("write", path);
isOutputChanged = true;
if (data) {
arguments[1] = data.replace(/require\(["']([^./\\][^\n\r]+)["']\)/g, (_str, mPath) => `require(require.resolve("${resolvePathAlias(mPath, path)}", {paths:[process.cwd(), "${process.env.NODE_PATH || ''}"]} ))`);
}
return typescript_1.default.sys.writeFile(...arguments);
};
sysConfig.readFile = function readFile(path) {
log_1.default.debug("read", path);
const data = typescript_1.default.sys.readFile(...arguments);
if (!data && path === tsConfigFileName) {
log_1.default.debug(`file ${tsConfigFileName} is not found. Compilation with default settings...`);
return JSON.stringify({});
}
if (!data || path.includes("node_modules")) {
return data;
}
const absolutePath = path_1.default.resolve(path);
return data
.replace(/(?<![/).])__dirname/g, `String.raw\`${path_1.default.dirname(absolutePath)}\``)
.replace(/(?<![/).])__filename/g, `String.raw\`${absolutePath}\``);
};
const host = typescript_1.default.createWatchCompilerHost(tsConfigFileName, extendCompilerOptions, sysConfig, typescript_1.default.createEmitAndSemanticDiagnosticsBuilderProgram, reportDiagnostic, (diagnostic) => {
if (isOutputChanged && onChanged && diagnostic.code === 6194) {
clearNodeCache(extendCompilerOptions.outDir);
onChanged(outMockFiles.files.filter((f) => !f.rootName.endsWith(".d.ts")));
isOutputChanged = false;
}
else {
log_1.default.debug(typescript_1.default.formatDiagnostic(diagnostic, formatHost));
}
});
let definedTSOptions;
const origCreateProgram = host.createProgram;
host.createProgram = function hookCreateProgram(tsRootNames, allOptions) {
const definedRootNames = entries && entries.length ? entries : tsRootNames;
arguments[0] = definedRootNames;
if (allOptions) {
definedTSOptions = JSON.parse(JSON.stringify(allOptions));
definedTSOptions.baseUrl = definedTSOptions.outDir;
definedTSOptions.pathsArr = (definedTSOptions.paths && Object.keys(definedTSOptions.paths)) || [];
isOutputChanged = outMockFiles.update(definedRootNames, allOptions.rootDir, allOptions.outDir);
log_1.default.debug("defined root names", "", definedRootNames);
log_1.default.debug("TS options", "", allOptions);
}
return origCreateProgram(...arguments);
};
const program = typescript_1.default.createWatchProgram(host);
function clearTmpOutput() {
log_1.default.debug("clearing tmp folder ", extendCompilerOptions.outDir);
try {
fs_1.default.rmdirSync(extendCompilerOptions.outDir, {
recursive: true,
});
}
catch (ex) {
const nodeJsRequired = new versionContainer_1.default("12.10.0");
if (versionContainer_1.nodeJsVer > nodeJsRequired)
log_1.default.error("error in clearing tmp folder", ex);
}
}
let closed = false;
function close() {
if (closed) {
return;
}
program && program.close();
clearTmpOutput();
closed = true;
}
const signals = ["SIGINT", "SIGTERM"];
signals.forEach((s) => {
process.on(s, () => {
close();
process.exit();
});
});
}