UNPKG

webpack-mock-server

Version:

Mocks api requests for webpack-dev-server with hot-replacement

212 lines (211 loc) 9.58 kB
"use strict"; 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 () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __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 handlePathAlias(definedTSOptions) { definedTSOptions._toResolveAliasPaths = []; const aliasPaths = definedTSOptions.paths; const { outDir } = definedTSOptions; if (aliasPaths && outDir) { const allPathsMap = Object.keys(aliasPaths); definedTSOptions._toResolveAliasPaths = allPathsMap; const rootDir = definedTSOptions.rootDir; const pathsBasePath = definedTSOptions.pathsBasePath || rootDir; const resolvedPaths = {}; Object.keys(aliasPaths).forEach((key) => { resolvedPaths[key] = aliasPaths[key].map((p) => { const absoluteSourcePath = path_1.default.resolve(pathsBasePath, p); const relToRootDir = path_1.default.relative(rootDir, absoluteSourcePath); return path_1.default.join(outDir, relToRootDir); }); }); definedTSOptions.paths = resolvedPaths; } return definedTSOptions; } 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._toResolveAliasPaths.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 = handlePathAlias(definedTSOptions); 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.rmSync(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(); }); }); }