@tsslint/core 1.3.6 → 1.4.0
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.d.ts +4 -3
- package/index.js +88 -143
- package/lib/build copy.d.ts +1 -0
- package/lib/build copy.js +19 -0
- package/lib/build.d.ts +1 -2
- package/lib/build.js +23 -12
- package/lib/load.js +43 -0
- package/lib/watch.d.ts +1 -2
- package/lib/watch.js +19 -74
- package/package.json +4 -5
package/index.d.ts
CHANGED
|
@@ -13,16 +13,17 @@ export type Linter = ReturnType<typeof createLinter>;
|
|
|
13
13
|
export declare function createLinter(ctx: ProjectContext, config: Config | Config[], mode: 'cli' | 'typescript-plugin', logger?: typeof import('@clack/prompts')): {
|
|
14
14
|
lint(fileName: string, cache?: FileLintCache): ts.DiagnosticWithLocation[];
|
|
15
15
|
hasCodeFixes(fileName: string): boolean;
|
|
16
|
-
getCodeFixes(fileName: string, start: number, end: number, diagnostics?: ts.Diagnostic[],
|
|
16
|
+
getCodeFixes(fileName: string, start: number, end: number, diagnostics?: ts.Diagnostic[], minimatchCache?: FileLintCache[4]): ts.CodeFixAction[];
|
|
17
17
|
getRefactors(fileName: string, start: number, end: number): ts.RefactorActionInfo[];
|
|
18
18
|
getRefactorEdits(fileName: string, actionName: string): ts.FileTextChanges[] | undefined;
|
|
19
|
-
getRules: (fileName: string,
|
|
20
|
-
getConfigs: (fileName: string,
|
|
19
|
+
getRules: (fileName: string, minimatchCache: undefined | FileLintCache[4]) => Rules;
|
|
20
|
+
getConfigs: (fileName: string, minimatchCache: undefined | FileLintCache[4]) => {
|
|
21
21
|
include: string[];
|
|
22
22
|
exclude: string[];
|
|
23
23
|
rules: Rules;
|
|
24
24
|
plugins: import("@tsslint/types").PluginInstance[];
|
|
25
25
|
}[];
|
|
26
26
|
};
|
|
27
|
+
export declare function createRelatedInformation(ts: typeof import('typescript'), err: Error, stackOffset: number): ts.DiagnosticRelatedInformation | undefined;
|
|
27
28
|
export declare function combineCodeFixes(fileName: string, fixes: ts.CodeFixAction[]): ts.TextChange[];
|
|
28
29
|
export declare function applyTextChanges(baseSnapshot: ts.IScriptSnapshot, textChanges: ts.TextChange[]): ts.IScriptSnapshot;
|
package/index.js
CHANGED
|
@@ -15,6 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
exports.createLinter = createLinter;
|
|
18
|
+
exports.createRelatedInformation = createRelatedInformation;
|
|
18
19
|
exports.combineCodeFixes = combineCodeFixes;
|
|
19
20
|
exports.applyTextChanges = applyTextChanges;
|
|
20
21
|
__exportStar(require("./lib/build"), exports);
|
|
@@ -22,34 +23,18 @@ __exportStar(require("./lib/watch"), exports);
|
|
|
22
23
|
const ErrorStackParser = require("error-stack-parser");
|
|
23
24
|
const path = require("path");
|
|
24
25
|
const minimatch = require("minimatch");
|
|
26
|
+
const typeAwareModeChange = new Error('enable type-aware mode');
|
|
25
27
|
function createLinter(ctx, config, mode,
|
|
26
28
|
// @ts-expect-error
|
|
27
29
|
logger) {
|
|
28
|
-
|
|
29
|
-
require('source-map-support').install({
|
|
30
|
-
retrieveFile(path) {
|
|
31
|
-
if (!path.endsWith('.js.map')) {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
path = path.replace(/\\/g, '/');
|
|
35
|
-
// monkey-fix, refs: https://github.com/typescript-eslint/typescript-eslint/issues/9352
|
|
36
|
-
if (path.includes('/@typescript-eslint/eslint-plugin/dist/rules/')
|
|
37
|
-
|| path.includes('/eslint-plugin-expect-type/lib/rules/')) {
|
|
38
|
-
return JSON.stringify({
|
|
39
|
-
version: 3,
|
|
40
|
-
sources: [],
|
|
41
|
-
sourcesContent: [],
|
|
42
|
-
mappings: '',
|
|
43
|
-
names: [],
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
let languageServiceUsage = mode === 'typescript-plugin' ? 1 : 0;
|
|
30
|
+
let languageServiceUsage = 0;
|
|
50
31
|
const ts = ctx.typescript;
|
|
51
32
|
const languageService = new Proxy(ctx.languageService, {
|
|
52
33
|
get(target, key, receiver) {
|
|
34
|
+
if (!languageServiceUsage) {
|
|
35
|
+
languageServiceUsage++;
|
|
36
|
+
throw typeAwareModeChange;
|
|
37
|
+
}
|
|
53
38
|
languageServiceUsage++;
|
|
54
39
|
return Reflect.get(target, key, receiver);
|
|
55
40
|
},
|
|
@@ -58,7 +43,6 @@ logger) {
|
|
|
58
43
|
const fileConfigs = new Map();
|
|
59
44
|
const fileFixes = new Map();
|
|
60
45
|
const fileRefactors = new Map();
|
|
61
|
-
const sourceFiles = new Map();
|
|
62
46
|
const snapshot2SourceFile = new WeakMap();
|
|
63
47
|
const basePath = path.dirname(ctx.configFile);
|
|
64
48
|
const configs = (Array.isArray(config) ? config : [config])
|
|
@@ -69,12 +53,10 @@ logger) {
|
|
|
69
53
|
plugins: (config.plugins ?? []).map(plugin => plugin(ctx)),
|
|
70
54
|
}));
|
|
71
55
|
const normalizedPath = new Map();
|
|
72
|
-
const debug = (Array.isArray(config) ? config : [config]).some(config => config.debug);
|
|
73
56
|
return {
|
|
74
57
|
lint(fileName, cache) {
|
|
75
58
|
let cacheableDiagnostics = [];
|
|
76
59
|
let uncacheableDiagnostics = [];
|
|
77
|
-
let debugInfo;
|
|
78
60
|
let currentRuleId;
|
|
79
61
|
let currentIssues = 0;
|
|
80
62
|
let currentFixes = 0;
|
|
@@ -82,26 +64,7 @@ logger) {
|
|
|
82
64
|
let currentRuleLanguageServiceUsage = 0;
|
|
83
65
|
let sourceFile;
|
|
84
66
|
let hasUncacheResult = false;
|
|
85
|
-
|
|
86
|
-
debugInfo = {
|
|
87
|
-
category: ts.DiagnosticCategory.Message,
|
|
88
|
-
code: 'debug',
|
|
89
|
-
messageText: '- Config: ' + ctx.configFile + '\n',
|
|
90
|
-
file: getSourceFile(fileName),
|
|
91
|
-
start: 0,
|
|
92
|
-
length: 0,
|
|
93
|
-
source: 'tsslint',
|
|
94
|
-
relatedInformation: [],
|
|
95
|
-
};
|
|
96
|
-
uncacheableDiagnostics.push(debugInfo);
|
|
97
|
-
}
|
|
98
|
-
const rules = getFileRules(fileName, cache);
|
|
99
|
-
if (!rules || !Object.keys(rules).length) {
|
|
100
|
-
if (debugInfo) {
|
|
101
|
-
debugInfo.messageText += '- Rules: ❌ (no rules)\n';
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
const prevLanguageServiceUsage = languageServiceUsage;
|
|
67
|
+
const rules = getFileRules(fileName, cache?.[4]);
|
|
105
68
|
const rulesContext = {
|
|
106
69
|
...ctx,
|
|
107
70
|
languageService,
|
|
@@ -123,14 +86,10 @@ logger) {
|
|
|
123
86
|
}
|
|
124
87
|
fixes.clear();
|
|
125
88
|
refactors.length = 0;
|
|
126
|
-
if (
|
|
127
|
-
debugInfo.messageText += '- Rules:\n';
|
|
128
|
-
}
|
|
129
|
-
runRules(rules);
|
|
130
|
-
if (!!prevLanguageServiceUsage !== !!languageServiceUsage) {
|
|
89
|
+
if (!runRules(rules)) {
|
|
131
90
|
return this.lint(fileName, cache);
|
|
132
91
|
}
|
|
133
|
-
const configs = getFileConfigs(fileName, cache);
|
|
92
|
+
const configs = getFileConfigs(fileName, cache?.[4]);
|
|
134
93
|
if (cache) {
|
|
135
94
|
for (const [ruleId, fixes] of cachedRules) {
|
|
136
95
|
cache[1][ruleId] = fixes;
|
|
@@ -193,7 +152,9 @@ logger) {
|
|
|
193
152
|
break;
|
|
194
153
|
}
|
|
195
154
|
if (typeof rule === 'object') {
|
|
196
|
-
runRules(rule, [...paths, path])
|
|
155
|
+
if (!runRules(rule, [...paths, path])) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
197
158
|
continue;
|
|
198
159
|
}
|
|
199
160
|
currentRuleLanguageServiceUsage = languageServiceUsage;
|
|
@@ -205,56 +166,38 @@ logger) {
|
|
|
205
166
|
continue;
|
|
206
167
|
}
|
|
207
168
|
hasUncacheResult = true;
|
|
208
|
-
const start = Date.now();
|
|
209
169
|
try {
|
|
210
170
|
rule(rulesContext);
|
|
211
|
-
if (debugInfo) {
|
|
212
|
-
const time = Date.now() - start;
|
|
213
|
-
debugInfo.messageText += ` - ${currentRuleId}`;
|
|
214
|
-
const details = [];
|
|
215
|
-
if (currentIssues) {
|
|
216
|
-
details.push(`${currentIssues} issues`);
|
|
217
|
-
}
|
|
218
|
-
if (currentFixes) {
|
|
219
|
-
details.push(`${currentFixes} fixes`);
|
|
220
|
-
}
|
|
221
|
-
if (currentRefactors) {
|
|
222
|
-
details.push(`${currentRefactors} refactors`);
|
|
223
|
-
}
|
|
224
|
-
if (time) {
|
|
225
|
-
details.push(`${time}ms`);
|
|
226
|
-
}
|
|
227
|
-
if (details.length) {
|
|
228
|
-
debugInfo.messageText += ` (${details.join(', ')})`;
|
|
229
|
-
}
|
|
230
|
-
debugInfo.messageText += '\n';
|
|
231
|
-
}
|
|
232
171
|
}
|
|
233
172
|
catch (err) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
173
|
+
if (err === typeAwareModeChange) {
|
|
174
|
+
// logger?.log.message(`Type-aware mode enabled by ${currentRuleId} rule.`);
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
else if (err instanceof Error) {
|
|
178
|
+
report(ts.DiagnosticCategory.Error, err.stack ?? err.message, 0, 0, 0, err);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
report(ts.DiagnosticCategory.Error, String(err), 0, 0, false);
|
|
237
182
|
}
|
|
238
|
-
}
|
|
239
|
-
if (debug && !!currentRuleLanguageServiceUsage !== !!languageServiceUsage) {
|
|
240
|
-
logger?.log.message(`Type-aware mode enabled by ${currentRuleId} rule.`);
|
|
241
183
|
}
|
|
242
184
|
if (cache && currentRuleLanguageServiceUsage === languageServiceUsage) {
|
|
243
185
|
cachedRules.set(currentRuleId, currentFixes);
|
|
244
186
|
}
|
|
245
187
|
}
|
|
188
|
+
return true;
|
|
246
189
|
}
|
|
247
190
|
;
|
|
248
|
-
function reportError(message, start, end,
|
|
249
|
-
return report(ts.DiagnosticCategory.Error, message, start, end,
|
|
191
|
+
function reportError(message, start, end, stackOffset) {
|
|
192
|
+
return report(ts.DiagnosticCategory.Error, message, start, end, stackOffset);
|
|
250
193
|
}
|
|
251
|
-
function reportWarning(message, start, end,
|
|
252
|
-
return report(ts.DiagnosticCategory.Warning, message, start, end,
|
|
194
|
+
function reportWarning(message, start, end, stackOffset) {
|
|
195
|
+
return report(ts.DiagnosticCategory.Warning, message, start, end, stackOffset);
|
|
253
196
|
}
|
|
254
|
-
function reportSuggestion(message, start, end,
|
|
255
|
-
return report(ts.DiagnosticCategory.Suggestion, message, start, end,
|
|
197
|
+
function reportSuggestion(message, start, end, stackOffset) {
|
|
198
|
+
return report(ts.DiagnosticCategory.Suggestion, message, start, end, stackOffset);
|
|
256
199
|
}
|
|
257
|
-
function report(category, message, start, end,
|
|
200
|
+
function report(category, message, start, end, stackOffset = 2, err) {
|
|
258
201
|
const error = {
|
|
259
202
|
category,
|
|
260
203
|
code: currentRuleId,
|
|
@@ -276,15 +219,11 @@ logger) {
|
|
|
276
219
|
})),
|
|
277
220
|
});
|
|
278
221
|
}
|
|
279
|
-
if (mode === 'typescript-plugin') {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
const baseOffset = 2 + traceOffset;
|
|
285
|
-
if (stacks.length > baseOffset) {
|
|
286
|
-
pushRelatedInformation(error, stacks[baseOffset]);
|
|
287
|
-
}
|
|
222
|
+
if (mode === 'typescript-plugin' && typeof stackOffset === 'number') {
|
|
223
|
+
err ??= new Error();
|
|
224
|
+
const relatedInfo = createRelatedInformation(ts, err, stackOffset);
|
|
225
|
+
if (relatedInfo) {
|
|
226
|
+
error.relatedInformation.push(relatedInfo);
|
|
288
227
|
}
|
|
289
228
|
}
|
|
290
229
|
fixes.set(error, []);
|
|
@@ -315,43 +254,6 @@ logger) {
|
|
|
315
254
|
},
|
|
316
255
|
};
|
|
317
256
|
}
|
|
318
|
-
function pushRelatedInformation(error, stack) {
|
|
319
|
-
if (stack.fileName && stack.lineNumber !== undefined && stack.columnNumber !== undefined) {
|
|
320
|
-
let fileName = stack.fileName
|
|
321
|
-
.replace(/\\/g, '/')
|
|
322
|
-
.split('?time=')[0];
|
|
323
|
-
if (fileName.startsWith('file://')) {
|
|
324
|
-
fileName = fileName.substring('file://'.length);
|
|
325
|
-
}
|
|
326
|
-
if (fileName.includes('http-url:')) {
|
|
327
|
-
fileName = fileName.split('http-url:')[1];
|
|
328
|
-
}
|
|
329
|
-
if (!sourceFiles.has(fileName)) {
|
|
330
|
-
const text = ctx.languageServiceHost.readFile(fileName);
|
|
331
|
-
sourceFiles.set(fileName, [
|
|
332
|
-
text !== undefined,
|
|
333
|
-
ts.createSourceFile(fileName, text ?? '', ts.ScriptTarget.Latest, true)
|
|
334
|
-
]);
|
|
335
|
-
}
|
|
336
|
-
const [exist, stackFile] = sourceFiles.get(fileName);
|
|
337
|
-
let pos = 0;
|
|
338
|
-
if (exist) {
|
|
339
|
-
try {
|
|
340
|
-
pos = stackFile.getPositionOfLineAndCharacter(stack.lineNumber - 1, stack.columnNumber - 1) ?? 0;
|
|
341
|
-
}
|
|
342
|
-
catch { }
|
|
343
|
-
}
|
|
344
|
-
error.relatedInformation ??= [];
|
|
345
|
-
error.relatedInformation.push({
|
|
346
|
-
category: ts.DiagnosticCategory.Message,
|
|
347
|
-
code: 0,
|
|
348
|
-
file: stackFile,
|
|
349
|
-
start: pos,
|
|
350
|
-
length: 0,
|
|
351
|
-
messageText: 'at ' + (stack.functionName ?? '<anonymous>'),
|
|
352
|
-
});
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
257
|
},
|
|
356
258
|
hasCodeFixes(fileName) {
|
|
357
259
|
const fixesMap = getFileFixes(fileName);
|
|
@@ -362,8 +264,8 @@ logger) {
|
|
|
362
264
|
}
|
|
363
265
|
return false;
|
|
364
266
|
},
|
|
365
|
-
getCodeFixes(fileName, start, end, diagnostics,
|
|
366
|
-
const configs = getFileConfigs(fileName,
|
|
267
|
+
getCodeFixes(fileName, start, end, diagnostics, minimatchCache) {
|
|
268
|
+
const configs = getFileConfigs(fileName, minimatchCache);
|
|
367
269
|
const fixesMap = getFileFixes(fileName);
|
|
368
270
|
const result = [];
|
|
369
271
|
for (const [diagnostic, actions] of fixesMap) {
|
|
@@ -448,11 +350,11 @@ logger) {
|
|
|
448
350
|
}
|
|
449
351
|
throw new Error('No source file');
|
|
450
352
|
}
|
|
451
|
-
function getFileRules(fileName,
|
|
353
|
+
function getFileRules(fileName, minimatchCache) {
|
|
452
354
|
let result = fileRules.get(fileName);
|
|
453
355
|
if (!result) {
|
|
454
356
|
result = {};
|
|
455
|
-
const configs = getFileConfigs(fileName,
|
|
357
|
+
const configs = getFileConfigs(fileName, minimatchCache);
|
|
456
358
|
for (const { rules } of configs) {
|
|
457
359
|
result = {
|
|
458
360
|
...result,
|
|
@@ -470,7 +372,7 @@ logger) {
|
|
|
470
372
|
}
|
|
471
373
|
return result;
|
|
472
374
|
}
|
|
473
|
-
function getFileConfigs(fileName,
|
|
375
|
+
function getFileConfigs(fileName, minimatchCache) {
|
|
474
376
|
let result = fileConfigs.get(fileName);
|
|
475
377
|
if (!result) {
|
|
476
378
|
result = configs.filter(({ include, exclude }) => {
|
|
@@ -484,9 +386,9 @@ logger) {
|
|
|
484
386
|
});
|
|
485
387
|
fileConfigs.set(fileName, result);
|
|
486
388
|
function _minimatch(pattern) {
|
|
487
|
-
if (
|
|
488
|
-
if (pattern in
|
|
489
|
-
return
|
|
389
|
+
if (minimatchCache) {
|
|
390
|
+
if (pattern in minimatchCache) {
|
|
391
|
+
return minimatchCache[pattern];
|
|
490
392
|
}
|
|
491
393
|
}
|
|
492
394
|
let normalized = normalizedPath.get(pattern);
|
|
@@ -495,8 +397,8 @@ logger) {
|
|
|
495
397
|
normalizedPath.set(pattern, normalized);
|
|
496
398
|
}
|
|
497
399
|
const res = minimatch.minimatch(fileName, normalized);
|
|
498
|
-
if (
|
|
499
|
-
|
|
400
|
+
if (minimatchCache) {
|
|
401
|
+
minimatchCache[pattern] = res;
|
|
500
402
|
}
|
|
501
403
|
return res;
|
|
502
404
|
}
|
|
@@ -516,6 +418,49 @@ logger) {
|
|
|
516
418
|
return fileRefactors.get(fileName);
|
|
517
419
|
}
|
|
518
420
|
}
|
|
421
|
+
const fsFiles = new Map();
|
|
422
|
+
function createRelatedInformation(ts, err, stackOffset) {
|
|
423
|
+
const stacks = ErrorStackParser.parse(err);
|
|
424
|
+
if (stacks.length <= stackOffset) {
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
const stack = stacks[stackOffset];
|
|
428
|
+
if (stack.fileName && stack.lineNumber !== undefined && stack.columnNumber !== undefined) {
|
|
429
|
+
let fileName = stack.fileName.replace(/\\/g, '/');
|
|
430
|
+
if (fileName.startsWith('file://')) {
|
|
431
|
+
fileName = fileName.substring('file://'.length);
|
|
432
|
+
}
|
|
433
|
+
if (fileName.includes('http-url:')) {
|
|
434
|
+
fileName = fileName.split('http-url:')[1];
|
|
435
|
+
}
|
|
436
|
+
const mtime = ts.sys.getModifiedTime?.(fileName)?.getTime() ?? 0;
|
|
437
|
+
const lastMtime = fsFiles.get(fileName)?.[1];
|
|
438
|
+
if (mtime !== lastMtime) {
|
|
439
|
+
const text = ts.sys.readFile(fileName);
|
|
440
|
+
fsFiles.set(fileName, [
|
|
441
|
+
text !== undefined,
|
|
442
|
+
mtime,
|
|
443
|
+
ts.createSourceFile(fileName, text ?? '', ts.ScriptTarget.Latest, true)
|
|
444
|
+
]);
|
|
445
|
+
}
|
|
446
|
+
const [exist, _mtime, relatedFile] = fsFiles.get(fileName);
|
|
447
|
+
let pos = 0;
|
|
448
|
+
if (exist) {
|
|
449
|
+
try {
|
|
450
|
+
pos = relatedFile.getPositionOfLineAndCharacter(stack.lineNumber - 1, stack.columnNumber - 1) ?? 0;
|
|
451
|
+
}
|
|
452
|
+
catch { }
|
|
453
|
+
}
|
|
454
|
+
return {
|
|
455
|
+
category: ts.DiagnosticCategory.Message,
|
|
456
|
+
code: 0,
|
|
457
|
+
file: relatedFile,
|
|
458
|
+
start: pos,
|
|
459
|
+
length: 0,
|
|
460
|
+
messageText: 'at ' + (stack.functionName ?? '<anonymous>'),
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
}
|
|
519
464
|
function combineCodeFixes(fileName, fixes) {
|
|
520
465
|
const changes = fixes
|
|
521
466
|
.map(fix => fix.changes)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function buildConfig(configFilePath: string, createHash?: (path: string) => string, logger?: typeof import('@clack/prompts')): Promise<string>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildConfig = buildConfig;
|
|
4
|
+
const watch_1 = require("./watch");
|
|
5
|
+
function buildConfig(configFilePath, createHash,
|
|
6
|
+
// @ts-expect-error
|
|
7
|
+
logger) {
|
|
8
|
+
return new Promise((resolve, reject) => {
|
|
9
|
+
(0, watch_1.watchConfig)(configFilePath, (config, result) => {
|
|
10
|
+
if (config) {
|
|
11
|
+
resolve(config);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
reject(result);
|
|
15
|
+
}
|
|
16
|
+
}, false, createHash, logger);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=build%20copy.js.map
|
package/lib/build.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export declare function buildConfigFile(configFilePath: string, createHash?: (path: string) => string, logger?: typeof import('@clack/prompts')): Promise<Config | Config[]>;
|
|
1
|
+
export declare function buildConfig(configFilePath: string, createHash?: (path: string) => string, spinner?: ReturnType<typeof import('@clack/prompts').spinner>, stopSnipper?: (message: string, code?: number) => void): Promise<string | undefined>;
|
package/lib/build.js
CHANGED
|
@@ -1,19 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.buildConfig = buildConfig;
|
|
4
4
|
const watch_1 = require("./watch");
|
|
5
|
-
|
|
5
|
+
const _path = require("path");
|
|
6
|
+
function buildConfig(configFilePath, createHash,
|
|
6
7
|
// @ts-expect-error
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
spinner, stopSnipper) {
|
|
9
|
+
const buildStart = Date.now();
|
|
10
|
+
const configFileDisplayPath = _path.relative(process.cwd(), configFilePath);
|
|
11
|
+
spinner?.message('Building ' + configFileDisplayPath);
|
|
12
|
+
return new Promise(async (resolve) => {
|
|
13
|
+
try {
|
|
14
|
+
await (0, watch_1.watchConfig)(configFilePath, builtConfig => {
|
|
15
|
+
if (builtConfig) {
|
|
16
|
+
stopSnipper?.('Built ' + configFileDisplayPath + ' in ' + (Date.now() - buildStart) + 'ms');
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
stopSnipper?.('Failed to build ' + configFileDisplayPath + ' in ' + (Date.now() - buildStart) + 'ms', 1);
|
|
20
|
+
}
|
|
21
|
+
resolve(builtConfig);
|
|
22
|
+
}, false, createHash, spinner, stopSnipper);
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
stopSnipper?.('Failed to build ' + configFileDisplayPath + ' in ' + (Date.now() - buildStart) + 'ms', 1);
|
|
26
|
+
resolve(undefined);
|
|
27
|
+
}
|
|
17
28
|
});
|
|
18
29
|
}
|
|
19
30
|
//# sourceMappingURL=build.js.map
|
package/lib/load.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// import type { Config } from '@tsslint/config';
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
// import url = require('url');
|
|
5
|
+
// // import ErrorStackParser = require('error-stack-parser');
|
|
6
|
+
// export async function loadConfig(outFile: string): Promise<Config | Config[]> {
|
|
7
|
+
// // try {
|
|
8
|
+
// return (await import(url.pathToFileURL(outFile).toString() + '?time=' + Date.now())).default;
|
|
9
|
+
// // } catch (e: any) {
|
|
10
|
+
// // if (e.stack) {
|
|
11
|
+
// // const stack = ErrorStackParser.parse(e)[0];
|
|
12
|
+
// // if (stack.fileName && stack.lineNumber !== undefined && stack.columnNumber !== undefined) {
|
|
13
|
+
// // let fileName = stack.fileName
|
|
14
|
+
// // .replace(/\\/g, '/')
|
|
15
|
+
// // .split('?time=')[0];
|
|
16
|
+
// // if (fileName.startsWith('file://')) {
|
|
17
|
+
// // fileName = fileName.substring('file://'.length);
|
|
18
|
+
// // }
|
|
19
|
+
// // result.errors.push({
|
|
20
|
+
// // id: 'config-import-error',
|
|
21
|
+
// // text: String(e),
|
|
22
|
+
// // location: {
|
|
23
|
+
// // file: fileName,
|
|
24
|
+
// // line: stack.lineNumber,
|
|
25
|
+
// // column: stack.columnNumber - 1,
|
|
26
|
+
// // lineText: '',
|
|
27
|
+
// // },
|
|
28
|
+
// // } as any);
|
|
29
|
+
// // } else {
|
|
30
|
+
// // result.errors.push({
|
|
31
|
+
// // id: 'config-import-error',
|
|
32
|
+
// // text: String(e),
|
|
33
|
+
// // } as any);
|
|
34
|
+
// // }
|
|
35
|
+
// // } else {
|
|
36
|
+
// // result.errors.push({
|
|
37
|
+
// // id: 'config-import-error',
|
|
38
|
+
// // text: String(e),
|
|
39
|
+
// // } as any);
|
|
40
|
+
// // }
|
|
41
|
+
// // }
|
|
42
|
+
// }
|
|
43
|
+
//# sourceMappingURL=load.js.map
|
package/lib/watch.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import esbuild = require('esbuild');
|
|
2
|
-
|
|
3
|
-
export declare function watchConfigFile(configFilePath: string, onBuild: (config: Config | Config[] | undefined, result: esbuild.BuildResult) => void, watch?: boolean, createHash?: (path: string) => string, logger?: typeof import('@clack/prompts')): Promise<esbuild.BuildContext<{
|
|
2
|
+
export declare function watchConfig(configFilePath: string, onBuild: (config: string | undefined, result: esbuild.BuildResult) => void, watch?: boolean, createHash?: (path: string) => string, spinner?: ReturnType<typeof import('@clack/prompts').spinner>, stopSnipper?: (message: string, code?: number) => void): Promise<esbuild.BuildContext<{
|
|
4
3
|
entryPoints: string[];
|
|
5
4
|
bundle: true;
|
|
6
5
|
sourcemap: true;
|
package/lib/watch.js
CHANGED
|
@@ -1,83 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.watchConfig = watchConfig;
|
|
4
4
|
exports.getDotTsslintPath = getDotTsslintPath;
|
|
5
5
|
const esbuild = require("esbuild");
|
|
6
6
|
const _path = require("path");
|
|
7
7
|
const fs = require("fs");
|
|
8
8
|
const url = require("url");
|
|
9
|
-
|
|
10
|
-
async function watchConfigFile(configFilePath, onBuild, watch = true, createHash = btoa,
|
|
9
|
+
async function watchConfig(configFilePath, onBuild, watch = true, createHash = btoa,
|
|
11
10
|
// @ts-expect-error
|
|
12
|
-
|
|
11
|
+
spinner, stopSnipper) {
|
|
13
12
|
const outDir = getDotTsslintPath(configFilePath);
|
|
14
13
|
const outFileName = createHash(_path.relative(outDir, configFilePath)) + '.mjs';
|
|
15
14
|
const outFile = _path.join(outDir, outFileName);
|
|
16
|
-
const
|
|
17
|
-
const resultHandler = async (result) => {
|
|
18
|
-
let config;
|
|
19
|
-
for (const error of [
|
|
20
|
-
...result.errors,
|
|
21
|
-
...result.warnings,
|
|
22
|
-
]) {
|
|
23
|
-
if (error.id) {
|
|
24
|
-
error.id = 'esbuild:' + error.id;
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
error.id = 'config-build-error';
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
const buildResultText = 'Built ' + configFileDisplayPath + ' in ' + (Date.now() - buildStart) + 'ms';
|
|
31
|
-
configBuildingSpinner?.message(buildResultText);
|
|
15
|
+
const resultHandler = (result) => {
|
|
32
16
|
if (!result.errors.length) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
configBuildingSpinner?.stop(buildResultText + ', imported in ' + (Date.now() - loadStart) + 'ms.');
|
|
38
|
-
}
|
|
39
|
-
catch (e) {
|
|
40
|
-
configBuildingSpinner?.stop(buildResultText + ', failed to import.');
|
|
41
|
-
if (e.stack) {
|
|
42
|
-
const stack = ErrorStackParser.parse(e)[0];
|
|
43
|
-
if (stack.fileName && stack.lineNumber !== undefined && stack.columnNumber !== undefined) {
|
|
44
|
-
let fileName = stack.fileName
|
|
45
|
-
.replace(/\\/g, '/')
|
|
46
|
-
.split('?time=')[0];
|
|
47
|
-
if (fileName.startsWith('file://')) {
|
|
48
|
-
fileName = fileName.substring('file://'.length);
|
|
49
|
-
}
|
|
50
|
-
result.errors.push({
|
|
51
|
-
id: 'config-import-error',
|
|
52
|
-
text: String(e),
|
|
53
|
-
location: {
|
|
54
|
-
file: fileName,
|
|
55
|
-
line: stack.lineNumber,
|
|
56
|
-
column: stack.columnNumber - 1,
|
|
57
|
-
lineText: '',
|
|
58
|
-
},
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
result.errors.push({
|
|
63
|
-
id: 'config-import-error',
|
|
64
|
-
text: String(e),
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
result.errors.push({
|
|
70
|
-
id: 'config-import-error',
|
|
71
|
-
text: String(e),
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
}
|
|
17
|
+
onBuild(outFile, result);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
onBuild(undefined, result);
|
|
75
21
|
}
|
|
76
|
-
onBuild(config, result);
|
|
77
22
|
};
|
|
78
|
-
let buildStart;
|
|
79
|
-
const configBuildingSpinner = logger?.spinner();
|
|
80
|
-
configBuildingSpinner?.start('Building ' + configFileDisplayPath);
|
|
81
23
|
const ctx = await esbuild.context({
|
|
82
24
|
entryPoints: [configFilePath],
|
|
83
25
|
bundle: true,
|
|
@@ -88,18 +30,16 @@ logger) {
|
|
|
88
30
|
plugins: [{
|
|
89
31
|
name: 'tsslint',
|
|
90
32
|
setup(build) {
|
|
91
|
-
build.onStart(() => {
|
|
92
|
-
buildStart = Date.now();
|
|
93
|
-
});
|
|
94
33
|
build.onResolve({ filter: /^https?:\/\// }, async ({ path: importUrl }) => {
|
|
95
34
|
const cachePath = _path.join(outDir, importUrl.split('://')[0], ...importUrl.split('://')[1].split('/'));
|
|
96
35
|
if (!fs.existsSync(cachePath)) {
|
|
97
|
-
|
|
36
|
+
const start = Date.now();
|
|
37
|
+
spinner?.message('Downloading ' + importUrl);
|
|
98
38
|
const response = await fetch(importUrl);
|
|
99
|
-
configBuildingSpinner?.message('Building ' + configFileDisplayPath);
|
|
100
39
|
if (!response.ok) {
|
|
101
40
|
throw new Error(`Failed to load ${importUrl}`);
|
|
102
41
|
}
|
|
42
|
+
stopSnipper?.('Downloaded ' + importUrl + ' in ' + (Date.now() - start) + 'ms');
|
|
103
43
|
const text = await response.text();
|
|
104
44
|
fs.mkdirSync(_path.dirname(cachePath), { recursive: true });
|
|
105
45
|
fs.writeFileSync(cachePath, text, 'utf8');
|
|
@@ -142,9 +82,14 @@ logger) {
|
|
|
142
82
|
await ctx.watch();
|
|
143
83
|
}
|
|
144
84
|
else {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
85
|
+
try {
|
|
86
|
+
const result = await ctx.rebuild(); // could throw
|
|
87
|
+
await ctx.dispose();
|
|
88
|
+
resultHandler(result);
|
|
89
|
+
}
|
|
90
|
+
catch (e) {
|
|
91
|
+
throw e;
|
|
92
|
+
}
|
|
148
93
|
}
|
|
149
94
|
return ctx;
|
|
150
95
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsslint/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"files": [
|
|
6
6
|
"**/*.js",
|
|
@@ -12,11 +12,10 @@
|
|
|
12
12
|
"directory": "packages/core"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@tsslint/types": "1.
|
|
15
|
+
"@tsslint/types": "1.4.0",
|
|
16
16
|
"error-stack-parser": "^2.1.4",
|
|
17
17
|
"esbuild": ">=0.17.0",
|
|
18
|
-
"minimatch": "^10.0.1"
|
|
19
|
-
"source-map-support": "^0.5.21"
|
|
18
|
+
"minimatch": "^10.0.1"
|
|
20
19
|
},
|
|
21
20
|
"devDependencies": {
|
|
22
21
|
"@clack/prompts": "^0.8.2"
|
|
@@ -24,5 +23,5 @@
|
|
|
24
23
|
"scripts": {
|
|
25
24
|
"postinstall": "node scripts/cleanCache.js"
|
|
26
25
|
},
|
|
27
|
-
"gitHead": "
|
|
26
|
+
"gitHead": "9a3f7ce55f079eaaedfb61af9b72d8ba736f0123"
|
|
28
27
|
}
|