@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 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[], cache?: FileLintCache): ts.CodeFixAction[];
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, cache: undefined | FileLintCache) => Rules;
20
- getConfigs: (fileName: string, cache: undefined | FileLintCache) => {
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
- if (mode === 'typescript-plugin') {
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
- if (debug) {
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 (debugInfo) {
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
- console.error(err);
235
- if (debugInfo) {
236
- debugInfo.messageText += ` - ${currentRuleId} (❌ ${err && typeof err === 'object' && 'stack' in err ? err.stack : String(err)}})\n`;
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, traceOffset = 0) {
249
- return report(ts.DiagnosticCategory.Error, message, start, end, traceOffset);
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, traceOffset = 0) {
252
- return report(ts.DiagnosticCategory.Warning, message, start, end, traceOffset);
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, traceOffset = 0) {
255
- return report(ts.DiagnosticCategory.Suggestion, message, start, end, traceOffset);
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, traceOffset) {
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
- const stacks = traceOffset === false
281
- ? []
282
- : ErrorStackParser.parse(new Error());
283
- if (typeof traceOffset === 'number') {
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, cache) {
366
- const configs = getFileConfigs(fileName, cache);
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, cache) {
353
+ function getFileRules(fileName, minimatchCache) {
452
354
  let result = fileRules.get(fileName);
453
355
  if (!result) {
454
356
  result = {};
455
- const configs = getFileConfigs(fileName, cache);
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, cache) {
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 (cache) {
488
- if (pattern in cache[4]) {
489
- return cache[4][pattern];
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 (cache) {
499
- cache[4][pattern] = res;
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
- import type { Config } from '@tsslint/config';
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.buildConfigFile = buildConfigFile;
3
+ exports.buildConfig = buildConfig;
4
4
  const watch_1 = require("./watch");
5
- function buildConfigFile(configFilePath, createHash,
5
+ const _path = require("path");
6
+ function buildConfig(configFilePath, createHash,
6
7
  // @ts-expect-error
7
- logger) {
8
- return new Promise((resolve, reject) => {
9
- (0, watch_1.watchConfigFile)(configFilePath, (config, result) => {
10
- if (config) {
11
- resolve(config);
12
- }
13
- else {
14
- reject(result);
15
- }
16
- }, false, createHash, logger);
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
- import type { Config } from '@tsslint/config';
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.watchConfigFile = watchConfigFile;
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
- const ErrorStackParser = require("error-stack-parser");
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
- logger) {
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 configFileDisplayPath = _path.relative(process.cwd(), configFilePath);
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
- const loadStart = Date.now();
34
- configBuildingSpinner?.message(buildResultText + ', importing...');
35
- try {
36
- config = (await import(url.pathToFileURL(outFile).toString() + '?time=' + Date.now())).default;
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
- configBuildingSpinner?.message('Downloading ' + importUrl);
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
- const result = await ctx.rebuild();
146
- await ctx.dispose();
147
- resultHandler(result);
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.6",
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.3.6",
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": "d153aa87c92803b4c20fef1f5cf2799f1a599099"
26
+ "gitHead": "9a3f7ce55f079eaaedfb61af9b72d8ba736f0123"
28
27
  }