Skip to content

Commit aa7adcf

Browse files
committed
fix(dev): using TypeScript Go typechecker / compiler in "start:dev:quick" mode during watcher process (single pass for entire codebase, in-terminal reporting, not interrupting in React GUI, unlike "start:dev")
1 parent 7c37418 commit aa7adcf

9 files changed

+187
-6
lines changed

package-lock.json

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,7 @@
411411
"markdown-loader": "^8.0.0",
412412
"mini-css-extract-plugin": "^2.9.2",
413413
"ncp": "^2.0.0",
414+
"node-pty": "^1.0.0",
414415
"npm-scripts-lifecycle": "^1.0.0",
415416
"prettier": "^3.5.3",
416417
"remote-redux-devtools": "^0.5.16",
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
// https://github.com/piecyk/tsc-webpack-plugin/blob/main/index.js
2+
3+
const path = require("path");
4+
const os = require("os");
5+
const pty = require("node-pty");
6+
7+
class TsgoError extends Error {
8+
constructor(message) {
9+
super(message);
10+
this.name = "TsgoError";
11+
this.stack = "";
12+
}
13+
}
14+
15+
const removeNewLinesAtEnd = (str) => str.replace(/(\r\n|\n|\r)+$/g, "");
16+
17+
const PLUGIN_NAME = "tsgo-plugin";
18+
19+
class TsgoWebpackPlugin {
20+
constructor(options = {}) {
21+
this.name = options.name;
22+
if (options.name) {
23+
options.name = undefined;
24+
delete options.name;
25+
}
26+
this.options = options;
27+
this.initialized = false;
28+
}
29+
async apply(compiler) {
30+
const isWatch = await new Promise((resolve) => {
31+
compiler.hooks.run.tap(PLUGIN_NAME, () => {
32+
if (!this.initialized) {
33+
this.initialized = true;
34+
35+
resolve(false);
36+
}
37+
});
38+
39+
compiler.hooks.watchRun.tap(PLUGIN_NAME, () => {
40+
if (!this.initialized) {
41+
this.initialized = true;
42+
43+
resolve(true);
44+
}
45+
});
46+
});
47+
48+
const file = path.resolve(
49+
compiler.context,
50+
`./node_modules/.bin/tsgo${os.platform() === "win32" ? ".exe" : ""}`
51+
);
52+
53+
const options = {
54+
...this.options,
55+
...(isWatch ? { watch: "", preserveWatchOutput: "" } : {}),
56+
};
57+
58+
const args = [
59+
...new Set(
60+
Object.keys(options)
61+
.reduce((acc, key) => [...acc, `--${key}`, String(options[key])], [])
62+
.filter(Boolean)
63+
),
64+
];
65+
66+
const ptyProcess = pty.spawn(file, args, {
67+
name: "xterm-color",
68+
});
69+
70+
process.once("exit", () => {
71+
ptyProcess.emit("exit");
72+
});
73+
74+
const logger = compiler.getInfrastructureLogger(PLUGIN_NAME);
75+
76+
let messages = [];
77+
78+
ptyProcess.onData((data) => {
79+
const d = removeNewLinesAtEnd(data);
80+
if (!d.includes("build starting") && (!d.includes("build finished") || d.includes("error"))) {
81+
process.stderr.write("\x07"); // beep
82+
}
83+
84+
// console.log(`==TSGO[${this.name}] data:`);
85+
// logger.info(`--TSGO[${this.name}] data:`);
86+
// console.log(d);
87+
logger.info(d);
88+
if (!isWatch) {
89+
messages.push(data);
90+
}
91+
});
92+
93+
if (isWatch) {
94+
// console.log(`==TSGO[${this.name}] start (watch)...`);
95+
logger.info(`--TSGO[${this.name}] start (watch)...`);
96+
97+
ptyProcess.onExit((e) => {
98+
process.exit(e.exitCode);
99+
});
100+
} else {
101+
// console.log(`==TSGO[${this.name}] start (not watch)...`);
102+
logger.info(`--TSGO[${this.name}] start (not watch)...`);
103+
104+
compiler.hooks.afterEmit.tapPromise(PLUGIN_NAME, async (compilation) => {
105+
// console.log(`==TSGO[${this.name}] compiler.hooks.afterEmit.tapPromise...`);
106+
logger.info(`--TSGO[${this.name}] compiler.hooks.afterEmit.tapPromise...`);
107+
108+
await new Promise((resolve) => {
109+
ptyProcess.onExit(() => {
110+
resolve();
111+
});
112+
});
113+
114+
if (messages.length > 0) {
115+
// console.log(`==TSGO[${this.name}] ${messages.length} errors!`);
116+
logger.info(`--TSGO[${this.name}] ${messages.length} errors!`);
117+
118+
messages
119+
.map((m) =>
120+
removeNewLinesAtEnd(
121+
m
122+
.split("\r\n")
123+
.map((s) => s.replace(/^Found \d+ errors?\b.$/, ""))
124+
.join("\r\n")
125+
)
126+
)
127+
.filter(Boolean)
128+
.map((m) => compilation.errors.push(new TsgoError(m)));
129+
130+
messages = [];
131+
} else {
132+
// console.log(`--TSGO[${this.name}] zero errors.`);
133+
logger.info(`==TSGO[${this.name}] zero errors.`);
134+
}
135+
});
136+
}
137+
}
138+
}
139+
140+
module.exports = TsgoWebpackPlugin;

tsconfig-cli.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"extends": "./tsconfig",
33
"compilerOptions": {
4-
"skipLibCheck": true,
4+
// "skipLibCheck": true,
55
// NODENEXT works because "typed-redux-saga/macro" in WebPack Babel config is not used when compiling from the CLI with tsc or tsgo
66
// "module": "esnext", // 99
77
// "module": "ES2020", // 6

tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"traceResolution": false,
4343
"disableSizeLimit": false,
4444
"removeComments": true,
45-
"skipLibCheck": false,
45+
"skipLibCheck": true,
4646
// NODENEXT does not work because of "typed-redux-saga/macro" in WebPack Babel config
4747
"module": "esnext", // 99
4848
// "module": "ES2020", // 6

webpack.config.main.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ console.log(`MAIN nodeEnv: ${nodeEnv}`);
1313

1414
// https://github.com/edrlab/thorium-reader/issues/1097#issuecomment-643406149
1515
const useLegacyTypeScriptLoader = process.env.USE_LEGACY_TYPESCRIPT_LOADER ? true : false;
16+
const GoTsCheckerWebpackPlugin = require("./scripts/go-ts-checker-webpack-plugin");
1617
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
1718
ForkTsCheckerWebpackPlugin.prototype[require("util").inspect.custom] = (_depth, _options) => {
1819
return "ForkTsCheckerWebpackPlugin";
@@ -254,7 +255,11 @@ config.plugins.push(new webpack.IgnorePlugin({ resourceRegExp: /^.\/runtime-fs$/
254255

255256
config.plugins.push(new webpack.IgnorePlugin({ resourceRegExp: /^canvas$/ })); // pdfjs
256257

257-
if (!checkTypeScriptSkip) {
258+
if (checkTypeScriptSkip) {
259+
// config.plugins.push(
260+
// new GoTsCheckerWebpackPlugin({name: "MAIN"}),
261+
// );
262+
} else {
258263
config.plugins.push(
259264
new ForkTsCheckerWebpackPlugin({
260265
// measureCompilationTime: true,

webpack.config.renderer-library.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ console.log(`LIBRARY nodeEnv: ${nodeEnv}`);
3232

3333
// https://github.com/edrlab/thorium-reader/issues/1097#issuecomment-643406149
3434
const useLegacyTypeScriptLoader = process.env.USE_LEGACY_TYPESCRIPT_LOADER ? true : false;
35+
const GoTsCheckerWebpackPlugin = require("./scripts/go-ts-checker-webpack-plugin");
3536
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
3637
ForkTsCheckerWebpackPlugin.prototype[require("util").inspect.custom] = (_depth, _options) => {
3738
return "ForkTsCheckerWebpackPlugin";
@@ -407,7 +408,12 @@ let config = Object.assign(
407408
},
408409
);
409410

410-
if (!checkTypeScriptSkip) {
411+
412+
if (checkTypeScriptSkip) {
413+
config.plugins.push(
414+
new GoTsCheckerWebpackPlugin({name: "LIBRARY"}), // we use a single-pass fast-compile/typecheck in this LIBRARY watcher, no need in READER (and MAIN + PDF configs do not activate a watcher)
415+
);
416+
} else {
411417
config.plugins.push(
412418
new ForkTsCheckerWebpackPlugin({
413419
// measureCompilationTime: true,

webpack.config.renderer-pdf.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ console.log(`PDF nodeEnv: ${nodeEnv}`);
2323

2424
// https://github.com/edrlab/thorium-reader/issues/1097#issuecomment-643406149
2525
const useLegacyTypeScriptLoader = process.env.USE_LEGACY_TYPESCRIPT_LOADER ? true : false;
26+
const GoTsCheckerWebpackPlugin = require("./scripts/go-ts-checker-webpack-plugin");
2627
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
2728
ForkTsCheckerWebpackPlugin.prototype[require("util").inspect.custom] = (_depth, _options) => {
2829
return "ForkTsCheckerWebpackPlugin";
@@ -183,7 +184,11 @@ let config = Object.assign(
183184
},
184185
);
185186

186-
if (!checkTypeScriptSkip) {
187+
if (checkTypeScriptSkip) {
188+
// config.plugins.push(
189+
// new GoTsCheckerWebpackPlugin({name: "PDF"}),
190+
// );
191+
} else {
187192
config.plugins.push(
188193
new ForkTsCheckerWebpackPlugin({
189194
// measureCompilationTime: true,

webpack.config.renderer-reader.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ console.log(`READER nodeEnv: ${nodeEnv}`);
3333

3434
// https://github.com/edrlab/thorium-reader/issues/1097#issuecomment-643406149
3535
const useLegacyTypeScriptLoader = process.env.USE_LEGACY_TYPESCRIPT_LOADER ? true : false;
36+
const GoTsCheckerWebpackPlugin = require("./scripts/go-ts-checker-webpack-plugin");
3637
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
3738
ForkTsCheckerWebpackPlugin.prototype[require("util").inspect.custom] = (_depth, _options) => {
3839
return "ForkTsCheckerWebpackPlugin";
@@ -394,7 +395,11 @@ let config = Object.assign(
394395
},
395396
);
396397

397-
if (!checkTypeScriptSkip) {
398+
if (checkTypeScriptSkip) {
399+
// config.plugins.push(
400+
// new GoTsCheckerWebpackPlugin({name: "READER"}),
401+
// );
402+
} else {
398403
config.plugins.push(
399404
new ForkTsCheckerWebpackPlugin({
400405
// measureCompilationTime: true,

0 commit comments

Comments
 (0)