@tsslint/cli 1.3.4 → 1.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +112 -71
- package/package.json +4 -4
package/index.js
CHANGED
|
@@ -6,12 +6,12 @@ const core = require("@tsslint/core");
|
|
|
6
6
|
const cache = require("./lib/cache");
|
|
7
7
|
const glob = require("glob");
|
|
8
8
|
const fs = require("fs");
|
|
9
|
-
const
|
|
10
|
-
const purple = '\x1b[35m';
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
9
|
+
const _reset = '\x1b[0m';
|
|
10
|
+
const purple = (s) => '\x1b[35m' + s + _reset;
|
|
11
|
+
const darkGray = (s) => '\x1b[90m' + s + _reset;
|
|
12
|
+
const lightRed = (s) => '\x1b[91m' + s + _reset;
|
|
13
|
+
const lightGreen = (s) => '\x1b[92m' + s + _reset;
|
|
14
|
+
const lightYellow = (s) => '\x1b[93m' + s + _reset;
|
|
15
15
|
(async () => {
|
|
16
16
|
let hasError = false;
|
|
17
17
|
let projectVersion = 0;
|
|
@@ -54,8 +54,16 @@ const reset = '\x1b[0m';
|
|
|
54
54
|
const languageService = ts.createLanguageService(languageServiceHost);
|
|
55
55
|
if (process.argv.includes('--project')) {
|
|
56
56
|
const projectIndex = process.argv.indexOf('--project');
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
let tsconfig = process.argv[projectIndex + 1];
|
|
58
|
+
if (tsconfig.startsWith('-') || !tsconfig) {
|
|
59
|
+
clack.log.error(lightRed(`Missing argument for --project.`));
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
if (!tsconfig.startsWith('.')) {
|
|
63
|
+
tsconfig = `./${tsconfig}`;
|
|
64
|
+
}
|
|
65
|
+
await projectWorker(tsconfig);
|
|
66
|
+
}
|
|
59
67
|
}
|
|
60
68
|
else if (process.argv.includes('--projects')) {
|
|
61
69
|
const projectsIndex = process.argv.indexOf('--projects');
|
|
@@ -74,20 +82,21 @@ const reset = '\x1b[0m';
|
|
|
74
82
|
}
|
|
75
83
|
}
|
|
76
84
|
else {
|
|
77
|
-
await
|
|
85
|
+
const tsconfig = await askTSConfig();
|
|
86
|
+
await projectWorker(tsconfig);
|
|
78
87
|
}
|
|
79
88
|
process.exit(hasError ? 1 : 0);
|
|
80
89
|
async function projectWorker(tsconfigOption) {
|
|
81
|
-
const tsconfig =
|
|
82
|
-
clack.intro(`${purple
|
|
90
|
+
const tsconfig = require.resolve(tsconfigOption, { paths: [process.cwd()] });
|
|
91
|
+
clack.intro(`${purple('[project]')} ${path.relative(process.cwd(), tsconfig)}`);
|
|
83
92
|
parsed = parseCommonLine(tsconfig);
|
|
84
93
|
if (!parsed.fileNames.length) {
|
|
85
|
-
clack.outro(
|
|
94
|
+
clack.outro(lightYellow('No included files.'));
|
|
86
95
|
return;
|
|
87
96
|
}
|
|
88
97
|
const configFile = ts.findConfigFile(path.dirname(tsconfig), ts.sys.fileExists, 'tsslint.config.ts');
|
|
89
98
|
if (!configFile) {
|
|
90
|
-
clack.outro(
|
|
99
|
+
clack.outro(lightYellow('No tsslint.config.ts found.'));
|
|
91
100
|
return;
|
|
92
101
|
}
|
|
93
102
|
if (!configs.has(configFile)) {
|
|
@@ -103,9 +112,6 @@ const reset = '\x1b[0m';
|
|
|
103
112
|
if (!tsslintConfig) {
|
|
104
113
|
return;
|
|
105
114
|
}
|
|
106
|
-
if (!parsed.fileNames) {
|
|
107
|
-
throw new Error('No input files found in tsconfig!');
|
|
108
|
-
}
|
|
109
115
|
projectVersion++;
|
|
110
116
|
typeRootsVersion++;
|
|
111
117
|
const lintCache = process.argv.includes('--force')
|
|
@@ -119,16 +125,23 @@ const reset = '\x1b[0m';
|
|
|
119
125
|
tsconfig: ts.server.toNormalizedPath(tsconfig),
|
|
120
126
|
};
|
|
121
127
|
const linter = core.createLinter(projectContext, tsslintConfig, 'cli', clack);
|
|
122
|
-
|
|
128
|
+
let lintSpinner = clack.spinner();
|
|
123
129
|
let hasFix = false;
|
|
130
|
+
let excluded = 0;
|
|
124
131
|
let passed = 0;
|
|
125
132
|
let errors = 0;
|
|
126
133
|
let warnings = 0;
|
|
127
134
|
let cached = 0;
|
|
128
|
-
|
|
135
|
+
let t = Date.now();
|
|
136
|
+
lintSpinner.start(darkGray(`[1/${parsed.fileNames.length}] ${path.relative(process.cwd(), parsed.fileNames[0])}`));
|
|
137
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
129
138
|
for (let i = 0; i < parsed.fileNames.length; i++) {
|
|
130
139
|
const fileName = parsed.fileNames[i];
|
|
131
|
-
|
|
140
|
+
if (Date.now() - t > 100) {
|
|
141
|
+
t = Date.now();
|
|
142
|
+
lintSpinner.message(darkGray(`[${i + 1}/${parsed.fileNames.length}] ${path.relative(process.cwd(), fileName)}`));
|
|
143
|
+
await new Promise(resolve => setTimeout(resolve, 0));
|
|
144
|
+
}
|
|
132
145
|
const fileMtime = fs.statSync(fileName).mtimeMs;
|
|
133
146
|
let fileCache = lintCache[fileName];
|
|
134
147
|
if (fileCache) {
|
|
@@ -146,6 +159,7 @@ const reset = '\x1b[0m';
|
|
|
146
159
|
else {
|
|
147
160
|
lintCache[fileName] = fileCache = [fileMtime, {}, [], [], {}];
|
|
148
161
|
}
|
|
162
|
+
let diagnostics;
|
|
149
163
|
if (process.argv.includes('--fix')) {
|
|
150
164
|
let retry = 3;
|
|
151
165
|
let shouldRetry = true;
|
|
@@ -159,7 +173,7 @@ const reset = '\x1b[0m';
|
|
|
159
173
|
fileCache[2].length = 0;
|
|
160
174
|
fileCache[3].length = 0;
|
|
161
175
|
}
|
|
162
|
-
|
|
176
|
+
diagnostics = linter.lint(fileName, fileCache);
|
|
163
177
|
const fixes = linter.getCodeFixes(fileName, 0, Number.MAX_VALUE, diagnostics, fileCache);
|
|
164
178
|
const textChanges = core.combineCodeFixes(fileName, fixes);
|
|
165
179
|
if (textChanges.length) {
|
|
@@ -175,9 +189,16 @@ const reset = '\x1b[0m';
|
|
|
175
189
|
ts.sys.writeFile(fileName, newSnapshot.getText(0, newSnapshot.getLength()));
|
|
176
190
|
fileCache[0] = fs.statSync(fileName).mtimeMs;
|
|
177
191
|
}
|
|
192
|
+
if (shouldRetry) {
|
|
193
|
+
diagnostics = linter.lint(fileName, fileCache);
|
|
194
|
+
}
|
|
178
195
|
}
|
|
179
196
|
else {
|
|
180
|
-
|
|
197
|
+
diagnostics = linter.lint(fileName, fileCache);
|
|
198
|
+
}
|
|
199
|
+
if (diagnostics.length) {
|
|
200
|
+
hasFix ||= linter.hasCodeFixes(fileName);
|
|
201
|
+
hasError ||= diagnostics.some(diagnostic => diagnostic.category === ts.DiagnosticCategory.Error);
|
|
181
202
|
for (const diagnostic of diagnostics) {
|
|
182
203
|
if (diagnostic.category === ts.DiagnosticCategory.Suggestion) {
|
|
183
204
|
continue;
|
|
@@ -187,73 +208,93 @@ const reset = '\x1b[0m';
|
|
|
187
208
|
getCanonicalFileName: ts.sys.useCaseSensitiveFileNames ? x => x : x => x.toLowerCase(),
|
|
188
209
|
getNewLine: () => ts.sys.newLine,
|
|
189
210
|
});
|
|
190
|
-
output = output.replace(`TS${diagnostic.code}`,
|
|
191
|
-
if (
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
211
|
+
output = output.replace(`TS${diagnostic.code}`, String(diagnostic.code));
|
|
212
|
+
if (lintSpinner) {
|
|
213
|
+
if (diagnostic.category === ts.DiagnosticCategory.Error) {
|
|
214
|
+
errors++;
|
|
215
|
+
lintSpinner.stop(output, 1);
|
|
216
|
+
}
|
|
217
|
+
else if (diagnostic.category === ts.DiagnosticCategory.Warning) {
|
|
218
|
+
warnings++;
|
|
219
|
+
lintSpinner.stop(output, 2);
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
lintSpinner.stop(output);
|
|
223
|
+
}
|
|
224
|
+
lintSpinner = undefined;
|
|
198
225
|
}
|
|
199
226
|
else {
|
|
200
|
-
|
|
227
|
+
if (diagnostic.category === ts.DiagnosticCategory.Error) {
|
|
228
|
+
errors++;
|
|
229
|
+
clack.log.error(output);
|
|
230
|
+
}
|
|
231
|
+
else if (diagnostic.category === ts.DiagnosticCategory.Warning) {
|
|
232
|
+
warnings++;
|
|
233
|
+
clack.log.warning(output);
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
clack.log.info(output);
|
|
237
|
+
}
|
|
201
238
|
}
|
|
202
239
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
240
|
+
}
|
|
241
|
+
else if (!Object.keys(linter.getRules(fileName, fileCache)).length) {
|
|
242
|
+
excluded++;
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
passed++;
|
|
246
|
+
}
|
|
247
|
+
if (!lintSpinner) {
|
|
248
|
+
lintSpinner = clack.spinner();
|
|
249
|
+
lintSpinner.start(darkGray(`[${i + 1}/${parsed.fileNames.length}] ${path.relative(process.cwd(), parsed.fileNames[i])}`));
|
|
250
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
210
251
|
}
|
|
211
252
|
}
|
|
212
253
|
if (cached) {
|
|
213
|
-
lintSpinner.stop(
|
|
254
|
+
lintSpinner.stop(darkGray(`Processed ${parsed.fileNames.length} files with cache. (Use --force to ignore cache.)`));
|
|
214
255
|
}
|
|
215
256
|
else {
|
|
216
|
-
lintSpinner.stop(
|
|
217
|
-
}
|
|
218
|
-
if (hasFix) {
|
|
219
|
-
clack.log.message(`${gray}Use --fix to apply fixes.${reset}`);
|
|
257
|
+
lintSpinner.stop(darkGray(`Processed ${parsed.fileNames.length} files.`));
|
|
220
258
|
}
|
|
221
259
|
const data = [
|
|
222
|
-
[passed, 'passed',
|
|
223
|
-
[errors, 'errors',
|
|
224
|
-
[warnings, 'warnings',
|
|
260
|
+
[passed, 'passed', lightGreen],
|
|
261
|
+
[errors, 'errors', lightRed],
|
|
262
|
+
[warnings, 'warnings', lightYellow],
|
|
263
|
+
[excluded, 'excluded', darkGray],
|
|
225
264
|
];
|
|
226
|
-
|
|
265
|
+
let summary = data
|
|
227
266
|
.filter(([count]) => count)
|
|
228
|
-
.map(([count, label, color]) => `${
|
|
229
|
-
.join(
|
|
267
|
+
.map(([count, label, color]) => color(`${count} ${label}`))
|
|
268
|
+
.join(darkGray(' | '));
|
|
269
|
+
if (hasFix) {
|
|
270
|
+
summary += darkGray(` (Use --fix to apply automatic fixes.)`);
|
|
271
|
+
}
|
|
272
|
+
else if (errors || warnings) {
|
|
273
|
+
summary += darkGray(` (No fixes available.)`);
|
|
274
|
+
}
|
|
230
275
|
clack.outro(summary);
|
|
231
276
|
cache.saveCache(configFile, lintCache, ts.sys.createHash);
|
|
232
277
|
}
|
|
233
|
-
async function
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
shortTsconfig = `./${shortTsconfig}`;
|
|
239
|
-
}
|
|
240
|
-
tsconfig = await clack.text({
|
|
241
|
-
message: 'Select the tsconfig project. (Use --project or --projects to skip this prompt.)',
|
|
242
|
-
placeholder: shortTsconfig ? `${shortTsconfig} (${parseCommonLine(tsconfig).fileNames.length} files)` : 'No tsconfig.json/jsconfig.json found, please enter the path to the tsconfig.json/jsconfig.json file.',
|
|
243
|
-
defaultValue: shortTsconfig,
|
|
244
|
-
validate(value) {
|
|
245
|
-
value ||= shortTsconfig;
|
|
246
|
-
try {
|
|
247
|
-
require.resolve(value, { paths: [process.cwd()] });
|
|
248
|
-
}
|
|
249
|
-
catch {
|
|
250
|
-
return `File not found!`;
|
|
251
|
-
}
|
|
252
|
-
},
|
|
253
|
-
});
|
|
278
|
+
async function askTSConfig() {
|
|
279
|
+
const presetConfig = ts.findConfigFile(process.cwd(), ts.sys.fileExists);
|
|
280
|
+
let shortTsconfig = presetConfig ? path.relative(process.cwd(), presetConfig) : undefined;
|
|
281
|
+
if (!shortTsconfig?.startsWith('.')) {
|
|
282
|
+
shortTsconfig = `./${shortTsconfig}`;
|
|
254
283
|
}
|
|
255
|
-
|
|
256
|
-
|
|
284
|
+
return await clack.text({
|
|
285
|
+
message: 'Select the project. (Use --project or --projects to skip this prompt.)',
|
|
286
|
+
placeholder: shortTsconfig ? `${shortTsconfig} (${parseCommonLine(presetConfig).fileNames.length} files)` : 'No tsconfig.json/jsconfig.json found, please enter the path to the tsconfig.json/jsconfig.json file.',
|
|
287
|
+
defaultValue: shortTsconfig,
|
|
288
|
+
validate(value) {
|
|
289
|
+
value ||= shortTsconfig;
|
|
290
|
+
try {
|
|
291
|
+
require.resolve(value, { paths: [process.cwd()] });
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
return 'No such file.';
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
});
|
|
257
298
|
}
|
|
258
299
|
function parseCommonLine(tsconfig) {
|
|
259
300
|
const jsonConfigFile = ts.readJsonConfigFile(tsconfig, ts.sys.readFile);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsslint/cli",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.6",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bin": {
|
|
6
6
|
"tsslint": "./bin/tsslint.js"
|
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@clack/prompts": "^0.8.2",
|
|
19
|
-
"@tsslint/config": "1.3.
|
|
20
|
-
"@tsslint/core": "1.3.
|
|
19
|
+
"@tsslint/config": "1.3.6",
|
|
20
|
+
"@tsslint/core": "1.3.6",
|
|
21
21
|
"glob": "^10.4.1"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
24
|
"typescript": "*"
|
|
25
25
|
},
|
|
26
|
-
"gitHead": "
|
|
26
|
+
"gitHead": "d153aa87c92803b4c20fef1f5cf2799f1a599099"
|
|
27
27
|
}
|