1 | "use strict";
|
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3 | if (k2 === undefined) k2 = k;
|
4 | var desc = Object.getOwnPropertyDescriptor(m, k);
|
5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6 | desc = { enumerable: true, get: function() { return m[k]; } };
|
7 | }
|
8 | Object.defineProperty(o, k2, desc);
|
9 | }) : (function(o, m, k, k2) {
|
10 | if (k2 === undefined) k2 = k;
|
11 | o[k2] = m[k];
|
12 | }));
|
13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
14 | Object.defineProperty(o, "default", { enumerable: true, value: v });
|
15 | }) : function(o, v) {
|
16 | o["default"] = v;
|
17 | });
|
18 | var __importStar = (this && this.__importStar) || function (mod) {
|
19 | if (mod && mod.__esModule) return mod;
|
20 | var result = {};
|
21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
22 | __setModuleDefault(result, mod);
|
23 | return result;
|
24 | };
|
25 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
26 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
27 | };
|
28 | Object.defineProperty(exports, "__esModule", { value: true });
|
29 |
|
30 | const fs_1 = __importDefault(require("fs"));
|
31 | const path_1 = __importDefault(require("path"));
|
32 | const typescript_1 = __importDefault(require("typescript"));
|
33 | const compilerOutRootFiles_1 = __importDefault(require("./compilerOutRootFiles"));
|
34 | const log_1 = __importDefault(require("./log"));
|
35 | const versionContainer_1 = __importStar(require("./versionContainer"));
|
36 | const formatHost = {
|
37 | getCanonicalFileName: (path) => path,
|
38 | getCurrentDirectory: typescript_1.default.sys.getCurrentDirectory,
|
39 | getNewLine: () => typescript_1.default.sys.newLine,
|
40 | };
|
41 | function reportDiagnostic(diagnostic) {
|
42 | var _a;
|
43 | let linePointer = "";
|
44 | if (diagnostic.file) {
|
45 | const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start || 0);
|
46 | linePointer = `in ${(_a = diagnostic.file) === null || _a === void 0 ? void 0 : _a.fileName} (${line + 1},${character + 1})`;
|
47 | }
|
48 | log_1.default.error(`TS${diagnostic.code}: ${linePointer}\n${typescript_1.default.flattenDiagnosticMessageText(diagnostic.messageText, formatHost.getNewLine())}`);
|
49 | }
|
50 |
|
51 | function clearNodeCache(rootPath) {
|
52 | Object.keys(require.cache).forEach((key) => {
|
53 | var _a;
|
54 | if ((_a = require.cache[key]) === null || _a === void 0 ? void 0 : _a.filename.startsWith(rootPath)) {
|
55 | log_1.default.debug("delete node-cache for", key);
|
56 | delete require.cache[key];
|
57 | }
|
58 | });
|
59 | }
|
60 |
|
61 | function compiler(entry, tsConfigFileName, extendCompilerOptions, onChanged) {
|
62 | const tsVer = Number.parseFloat(typescript_1.default.versionMajorMinor);
|
63 | if (tsVer < 2.7) {
|
64 | throw new Error(`WebpackMockServer. Typescript version >=2.7 is expected. Current is ${typescript_1.default.versionMajorMinor}`);
|
65 | }
|
66 | log_1.default.debug(`typescript version: ${typescript_1.default.version}`);
|
67 | const entries = entry && (Array.isArray(entry) ? entry : [entry]);
|
68 | entries &&
|
69 | entries.forEach((v) => {
|
70 | if (typeof v !== "string") {
|
71 | throw new Error(`WebpackMockServer. Option [entry]. Only 'string' is expected: ${v}`);
|
72 | }
|
73 | if (v.includes("*")) {
|
74 | throw new Error(`WebpackMockServer. Option [entry]. Wildcard is not supported. Set 'Null' to [entry] and use tsConfig.json with 'files' and 'include' options instead.
|
75 | More details here: https://github.com/Yegorich555/webpack-mock-server#options`);
|
76 | }
|
77 | });
|
78 |
|
79 | let isOutputChanged = true;
|
80 | const outMockFiles = new compilerOutRootFiles_1.default();
|
81 | const emptyWatcher = {
|
82 |
|
83 | close: () => { },
|
84 | };
|
85 | const sysConfig = Object.assign({}, typescript_1.default.sys);
|
86 | sysConfig.watchFile = function watchFile(path) {
|
87 | if (path.includes("node_modules")) {
|
88 | return emptyWatcher;
|
89 | }
|
90 |
|
91 | return typescript_1.default.sys.watchFile(...arguments);
|
92 | };
|
93 | sysConfig.watchDirectory = function watchDir(path) {
|
94 | if (path.includes("node_modules")) {
|
95 | return emptyWatcher;
|
96 | }
|
97 |
|
98 | return typescript_1.default.sys.watchDirectory(...arguments);
|
99 | };
|
100 |
|
101 | function resolvePathAlias(filePath, path) {
|
102 | var _a;
|
103 |
|
104 | const isMatchAlias = definedTSOptions.pathsArr.some((v) => v[0] === filePath[0]);
|
105 | if (isMatchAlias) {
|
106 | const m = (_a = typescript_1.default.resolveModuleName(filePath, path, definedTSOptions, host)
|
107 | .resolvedModule) === null || _a === void 0 ? void 0 : _a.resolvedFileName;
|
108 |
|
109 | return m || filePath;
|
110 | }
|
111 | return filePath;
|
112 | }
|
113 | sysConfig.writeFile = function writeFile(path, data) {
|
114 | log_1.default.debug("write", path);
|
115 | isOutputChanged = true;
|
116 | if (data) {
|
117 | arguments[1] = data.replace(/require\(["']([^./\\][^\n\r]+)["']\)/g, (_str, mPath) =>
|
118 |
|
119 | `require(require.resolve("${resolvePathAlias(mPath, path)}", {paths:[process.cwd(), "${process.env.NODE_PATH || ''}"]} ))`);
|
120 | }
|
121 |
|
122 | return typescript_1.default.sys.writeFile(...arguments);
|
123 | };
|
124 | sysConfig.readFile = function readFile(path) {
|
125 | log_1.default.debug("read", path);
|
126 |
|
127 | const data = typescript_1.default.sys.readFile(...arguments);
|
128 | if (!data && path === tsConfigFileName) {
|
129 | log_1.default.debug(`file ${tsConfigFileName} is not found. Compilation with default settings...`);
|
130 | return JSON.stringify({});
|
131 | }
|
132 | if (!data || path.includes("node_modules")) {
|
133 | return data;
|
134 | }
|
135 |
|
136 | const absolutePath = path_1.default.resolve(path);
|
137 | return data
|
138 | .replace(/(?<![/).])__dirname/g, `String.raw\`${path_1.default.dirname(absolutePath)}\``)
|
139 | .replace(/(?<![/).])__filename/g, `String.raw\`${absolutePath}\``);
|
140 | };
|
141 |
|
142 |
|
143 | const host = typescript_1.default.createWatchCompilerHost(tsConfigFileName, extendCompilerOptions, sysConfig, typescript_1.default.createEmitAndSemanticDiagnosticsBuilderProgram, reportDiagnostic, (diagnostic) => {
|
144 | if (isOutputChanged && onChanged && diagnostic.code === 6194) {
|
145 | clearNodeCache(extendCompilerOptions.outDir);
|
146 | onChanged(outMockFiles.files);
|
147 | isOutputChanged = false;
|
148 | }
|
149 | else {
|
150 | log_1.default.debug(typescript_1.default.formatDiagnostic(diagnostic, formatHost));
|
151 | }
|
152 | });
|
153 | let definedTSOptions;
|
154 | const origCreateProgram = host.createProgram;
|
155 | host.createProgram = function hookCreateProgram(tsRootNames, allOptions) {
|
156 | const definedRootNames = entries && entries.length ? entries : tsRootNames;
|
157 | arguments[0] = definedRootNames;
|
158 | const tsOptions = allOptions;
|
159 |
|
160 | definedTSOptions = JSON.parse(JSON.stringify(tsOptions));
|
161 | definedTSOptions.baseUrl = definedTSOptions.outDir;
|
162 | definedTSOptions.pathsArr =
|
163 | (definedTSOptions.paths && Object.keys(definedTSOptions.paths)) || [];
|
164 | isOutputChanged = outMockFiles.update(definedRootNames, tsOptions.rootDir, tsOptions.outDir);
|
165 | log_1.default.debug("defined root names", "", definedRootNames);
|
166 | log_1.default.debug("TS options", "", tsOptions);
|
167 |
|
168 | return origCreateProgram(...arguments);
|
169 | };
|
170 | const program = typescript_1.default.createWatchProgram(host);
|
171 | |
172 |
|
173 |
|
174 |
|
175 | function clearTmpOutput() {
|
176 | log_1.default.debug("clearing tmp folder ", extendCompilerOptions.outDir);
|
177 |
|
178 | try {
|
179 | fs_1.default.rmdirSync(extendCompilerOptions.outDir, {
|
180 | recursive: true,
|
181 | });
|
182 |
|
183 | }
|
184 | catch (ex) {
|
185 | const nodeJsRequired = new versionContainer_1.default("12.10.0");
|
186 | if (versionContainer_1.nodeJsVer > nodeJsRequired)
|
187 | log_1.default.error("error in clearing tmp folder", ex);
|
188 | }
|
189 | }
|
190 |
|
191 | let closed = false;
|
192 | function close() {
|
193 | if (closed) {
|
194 | return;
|
195 | }
|
196 | program && program.close();
|
197 | clearTmpOutput();
|
198 | closed = true;
|
199 | }
|
200 | const signals = ["SIGINT", "SIGTERM"];
|
201 | signals.forEach((s) => {
|
202 | process.on(s, () => {
|
203 | close();
|
204 | process.exit();
|
205 | });
|
206 | });
|
207 | }
|
208 | exports.default = compiler;
|