auto-cr-cmd 2.0.21 → 2.0.23

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/dist/index.js CHANGED
@@ -73,7 +73,7 @@ var auto_cr_rules_1 = require("auto-cr-rules");
73
73
  var loader_1 = require("./rules/loader");
74
74
  function run() {
75
75
  return __awaiter(this, arguments, void 0, function (filePaths, ruleDir) {
76
- var t, validPaths, allFiles, _i, validPaths_1, targetPath, stat, directoryFiles, customRules, rules, _a, allFiles_1, file, error_1;
76
+ var t, validPaths, allFiles, _i, validPaths_1, targetPath, stat, directoryFiles, scannableFiles, customRules, rules, filesWithErrors, filesWithWarnings, filesWithOptimizing, _a, scannableFiles_1, file, summary, error_1;
77
77
  if (filePaths === void 0) { filePaths = []; }
78
78
  return __generator(this, function (_b) {
79
79
  switch (_b.label) {
@@ -84,12 +84,12 @@ function run() {
84
84
  _b.trys.push([1, 6, , 7]);
85
85
  if (filePaths.length === 0) {
86
86
  consola_1.consola.info(t.noPathsProvided());
87
- return [2 /*return*/];
87
+ return [2 /*return*/, { scannedFiles: 0, filesWithErrors: 0, filesWithWarnings: 0, filesWithOptimizing: 0 }];
88
88
  }
89
89
  validPaths = filePaths.filter(function (candidate) { return (0, file_1.checkPathExists)(candidate); });
90
90
  if (validPaths.length === 0) {
91
91
  consola_1.consola.error(t.allPathsMissing());
92
- return [2 /*return*/];
92
+ return [2 /*return*/, { scannedFiles: 0, filesWithErrors: 0, filesWithWarnings: 0, filesWithOptimizing: 0 }];
93
93
  }
94
94
  allFiles = [];
95
95
  for (_i = 0, validPaths_1 = validPaths; _i < validPaths_1.length; _i++) {
@@ -105,38 +105,53 @@ function run() {
105
105
  }
106
106
  if (allFiles.length === 0) {
107
107
  consola_1.consola.info(t.noFilesFound());
108
- return [2 /*return*/];
108
+ return [2 /*return*/, { scannedFiles: 0, filesWithErrors: 0, filesWithWarnings: 0, filesWithOptimizing: 0 }];
109
109
  }
110
+ scannableFiles = allFiles.filter(function (candidate) { return !candidate.endsWith('.d.ts'); });
110
111
  customRules = (0, loader_1.loadCustomRules)(ruleDir);
111
112
  rules = __spreadArray(__spreadArray([], auto_cr_rules_1.builtinRules, true), customRules, true);
112
113
  if (rules.length === 0) {
113
114
  consola_1.consola.warn(t.noRulesLoaded());
114
- return [2 /*return*/];
115
+ return [2 /*return*/, {
116
+ scannedFiles: 0,
117
+ filesWithErrors: 0,
118
+ filesWithWarnings: 0,
119
+ filesWithOptimizing: 0,
120
+ }];
115
121
  }
116
- _a = 0, allFiles_1 = allFiles;
122
+ filesWithErrors = 0;
123
+ filesWithWarnings = 0;
124
+ filesWithOptimizing = 0;
125
+ _a = 0, scannableFiles_1 = scannableFiles;
117
126
  _b.label = 2;
118
127
  case 2:
119
- if (!(_a < allFiles_1.length)) return [3 /*break*/, 5];
120
- file = allFiles_1[_a];
121
- if (file.endsWith('.d.ts')) {
122
- return [3 /*break*/, 4];
123
- }
128
+ if (!(_a < scannableFiles_1.length)) return [3 /*break*/, 5];
129
+ file = scannableFiles_1[_a];
124
130
  return [4 /*yield*/, analyzeFile(file, rules)];
125
131
  case 3:
126
- _b.sent();
132
+ summary = _b.sent();
133
+ if (summary.severityCounts.error > 0) {
134
+ filesWithErrors += 1;
135
+ }
136
+ if (summary.severityCounts.warning > 0) {
137
+ filesWithWarnings += 1;
138
+ }
139
+ if (summary.severityCounts.optimizing > 0) {
140
+ filesWithOptimizing += 1;
141
+ }
127
142
  _b.label = 4;
128
143
  case 4:
129
144
  _a++;
130
145
  return [3 /*break*/, 2];
131
- case 5:
132
- consola_1.consola.log(' ');
133
- consola_1.consola.success(t.scanComplete());
134
- return [3 /*break*/, 7];
146
+ case 5: return [2 /*return*/, {
147
+ scannedFiles: scannableFiles.length,
148
+ filesWithErrors: filesWithErrors,
149
+ filesWithWarnings: filesWithWarnings,
150
+ filesWithOptimizing: filesWithOptimizing,
151
+ }];
135
152
  case 6:
136
153
  error_1 = _b.sent();
137
- consola_1.consola.error(t.scanError(), error_1 instanceof Error ? error_1.message : error_1);
138
- process.exit(1);
139
- return [3 /*break*/, 7];
154
+ throw error_1 instanceof Error ? error_1 : new Error(String(error_1));
140
155
  case 7: return [2 /*return*/];
141
156
  }
142
157
  });
@@ -144,7 +159,7 @@ function run() {
144
159
  }
145
160
  function analyzeFile(file, rules) {
146
161
  return __awaiter(this, void 0, void 0, function () {
147
- var source, reporter, t, ast, parseOptions, language, baseContext, sharedHelpers, _loop_1, _i, rules_1, rule;
162
+ var source, reporter, t, ast, parseOptions, language, baseContext, sharedHelpers, _loop_1, _i, rules_1, rule, summary;
148
163
  return __generator(this, function (_a) {
149
164
  switch (_a.label) {
150
165
  case 0:
@@ -157,7 +172,13 @@ function analyzeFile(file, rules) {
157
172
  }
158
173
  catch (error) {
159
174
  consola_1.consola.error(t.parseFileFailed({ file: file }), error instanceof Error ? error.message : error);
160
- return [2 /*return*/];
175
+ return [2 /*return*/, {
176
+ severityCounts: {
177
+ error: 1,
178
+ warning: 0,
179
+ optimizing: 0,
180
+ },
181
+ }];
161
182
  }
162
183
  language = (0, i18n_1.getLanguage)();
163
184
  baseContext = (0, auto_cr_rules_1.createRuleContext)({
@@ -169,28 +190,35 @@ function analyzeFile(file, rules) {
169
190
  });
170
191
  sharedHelpers = baseContext.helpers;
171
192
  _loop_1 = function (rule) {
172
- var scopedReporter_1, helpers, context, error_2;
193
+ var scopedReporter_1, reporterWithRecord_1, helpers, context, error_2;
173
194
  return __generator(this, function (_b) {
174
195
  switch (_b.label) {
175
196
  case 0:
176
197
  _b.trys.push([0, 2, , 3]);
177
198
  scopedReporter_1 = reporter.forRule(rule);
178
- helpers = __assign(__assign({}, sharedHelpers), { reportViolation: function (input, span) {
179
- var normalized = normalizeViolationInputForCli(input, span);
180
- if (typeof scopedReporter_1.record === 'function') {
181
- scopedReporter_1.record(normalized);
199
+ reporterWithRecord_1 = scopedReporter_1;
200
+ helpers = __assign(__assign({}, sharedHelpers), { reportViolation: (function (input, span) {
201
+ var normalized = normalizeViolationInput(input, span);
202
+ if (typeof reporterWithRecord_1.record === 'function') {
203
+ reporterWithRecord_1.record({
204
+ description: normalized.message,
205
+ code: normalized.code,
206
+ suggestions: normalized.suggestions,
207
+ span: normalized.span,
208
+ line: normalized.line,
209
+ });
182
210
  return;
183
211
  }
184
212
  if (normalized.span) {
185
- scopedReporter_1.errorAtSpan(normalized.span, normalized.description);
213
+ scopedReporter_1.errorAtSpan(normalized.span, normalized.message);
186
214
  return;
187
215
  }
188
216
  if (typeof normalized.line === 'number') {
189
- scopedReporter_1.errorAtLine(normalized.line, normalized.description);
217
+ scopedReporter_1.errorAtLine(normalized.line, normalized.message);
190
218
  return;
191
219
  }
192
- scopedReporter_1.error(normalized.description);
193
- } });
220
+ scopedReporter_1.error(normalized.message);
221
+ }) });
194
222
  context = __assign(__assign({}, baseContext), { reporter: scopedReporter_1, helpers: helpers });
195
223
  return [4 /*yield*/, rule.run(context)];
196
224
  case 1:
@@ -217,27 +245,64 @@ function analyzeFile(file, rules) {
217
245
  _i++;
218
246
  return [3 /*break*/, 1];
219
247
  case 4:
220
- reporter.flush();
221
- return [2 /*return*/];
248
+ summary = reporter.flush();
249
+ return [2 /*return*/, {
250
+ severityCounts: summary.severityCounts,
251
+ }];
222
252
  }
223
253
  });
224
254
  });
225
255
  }
226
- function normalizeViolationInputForCli(input, spanArg) {
227
- var _a, _b;
256
+ function normalizeViolationInput(input, spanArg) {
257
+ var _a;
228
258
  if (typeof input === 'string') {
229
259
  return {
230
- description: input,
260
+ message: input,
231
261
  span: spanArg,
232
262
  };
233
263
  }
234
- var description = (_a = input.description) !== null && _a !== void 0 ? _a : input.message;
264
+ if (input && typeof input === 'object') {
265
+ var candidate = input;
266
+ var description = typeof candidate.description === 'string'
267
+ ? candidate.description
268
+ : typeof candidate.message === 'string'
269
+ ? candidate.message
270
+ : undefined;
271
+ var code = typeof candidate.code === 'string' ? candidate.code : undefined;
272
+ var suggestions = void 0;
273
+ if (Array.isArray(candidate.suggestions)) {
274
+ var normalizedSuggestions = [];
275
+ for (var _i = 0, _b = candidate.suggestions; _i < _b.length; _i++) {
276
+ var entry = _b[_i];
277
+ if (typeof entry === 'string') {
278
+ normalizedSuggestions.push({ text: entry });
279
+ continue;
280
+ }
281
+ if (entry && typeof entry === 'object') {
282
+ var suggestion = entry;
283
+ if (typeof suggestion.text === 'string') {
284
+ normalizedSuggestions.push({
285
+ text: suggestion.text,
286
+ link: typeof suggestion.link === 'string' ? suggestion.link : undefined,
287
+ });
288
+ }
289
+ }
290
+ }
291
+ if (normalizedSuggestions.length > 0) {
292
+ suggestions = normalizedSuggestions;
293
+ }
294
+ }
295
+ return {
296
+ message: description !== null && description !== void 0 ? description : 'Rule violation detected.',
297
+ span: (_a = candidate.span) !== null && _a !== void 0 ? _a : spanArg,
298
+ line: typeof candidate.line === 'number' ? candidate.line : undefined,
299
+ code: code,
300
+ suggestions: suggestions,
301
+ };
302
+ }
235
303
  return {
236
- description: description !== null && description !== void 0 ? description : 'Rule violation detected.',
237
- code: input.code,
238
- suggestions: input.suggestions,
239
- span: (_b = input.span) !== null && _b !== void 0 ? _b : spanArg,
240
- line: input.line,
304
+ message: 'Rule violation detected.',
305
+ span: spanArg,
241
306
  };
242
307
  }
243
308
  commander_1.program
@@ -248,7 +313,7 @@ commander_1.program
248
313
  var options = commander_1.program.opts();
249
314
  var filePaths = commander_1.program.args.map(function (target) { return path_1.default.resolve(process.cwd(), target); });
250
315
  (function () { return __awaiter(void 0, void 0, void 0, function () {
251
- var error_3, t;
316
+ var summary, t, language, resultMessage, error_3, t;
252
317
  var _a;
253
318
  return __generator(this, function (_b) {
254
319
  switch (_b.label) {
@@ -257,13 +322,31 @@ var filePaths = commander_1.program.args.map(function (target) { return path_1.d
257
322
  (0, i18n_1.setLanguage)((_a = options.language) !== null && _a !== void 0 ? _a : process.env.LANG);
258
323
  return [4 /*yield*/, run(filePaths, options.ruleDir)];
259
324
  case 1:
260
- _b.sent();
261
- process.exit(0);
325
+ summary = _b.sent();
326
+ t = (0, i18n_1.getTranslator)();
327
+ if (summary.scannedFiles > 0) {
328
+ consola_1.consola.log(' ');
329
+ language = (0, i18n_1.getLanguage)();
330
+ resultMessage = language.startsWith('zh')
331
+ ? " ".concat(t.scanComplete(), "\uFF0C\u672C\u6B21\u5171\u626B\u63CF").concat(summary.scannedFiles, "\u4E2A\u6587\u4EF6\uFF0C\u5176\u4E2D").concat(summary.filesWithErrors, "\u4E2A\u6587\u4EF6\u5B58\u5728\u9519\u8BEF\uFF0C").concat(summary.filesWithWarnings, "\u4E2A\u6587\u4EF6\u5B58\u5728\u8B66\u544A\uFF0C").concat(summary.filesWithOptimizing, "\u4E2A\u6587\u4EF6\u5B58\u5728\u4F18\u5316\u5EFA\u8BAE\uFF01")
332
+ : " ".concat(t.scanComplete(), ", scanned ").concat(summary.scannedFiles, " files: ").concat(summary.filesWithErrors, " with errors, ").concat(summary.filesWithWarnings, " with warnings, ").concat(summary.filesWithOptimizing, " with optimizing hints!");
333
+ if (summary.filesWithErrors > 0) {
334
+ consola_1.consola.success(resultMessage);
335
+ process.exit(1);
336
+ }
337
+ else {
338
+ consola_1.consola.success(resultMessage);
339
+ process.exit(0);
340
+ }
341
+ }
342
+ else {
343
+ process.exit(0);
344
+ }
262
345
  return [3 /*break*/, 3];
263
346
  case 2:
264
347
  error_3 = _b.sent();
265
348
  t = (0, i18n_1.getTranslator)();
266
- consola_1.consola.error(t.unexpectedError(), error_3);
349
+ consola_1.consola.error(t.scanError(), error_3 instanceof Error ? error_3.message : error_3);
267
350
  process.exit(1);
268
351
  return [3 /*break*/, 3];
269
352
  case 3: return [2 /*return*/];
@@ -19,15 +19,33 @@ function createReporter(filePath, source) {
19
19
  var t = (0, i18n_1.getTranslator)();
20
20
  var language = (0, i18n_1.getLanguage)();
21
21
  var records = [];
22
+ var totalViolations = 0;
23
+ var errorViolations = 0;
24
+ var severityCounts = {
25
+ error: 0,
26
+ warning: 0,
27
+ optimizing: 0,
28
+ };
22
29
  var pushRecord = function (record) {
23
30
  records.push(record);
31
+ totalViolations += 1;
32
+ if (record.severity === auto_cr_rules_1.RuleSeverity.Error) {
33
+ errorViolations += 1;
34
+ severityCounts.error += 1;
35
+ }
36
+ else if (record.severity === auto_cr_rules_1.RuleSeverity.Warning) {
37
+ severityCounts.warning += 1;
38
+ }
39
+ else if (record.severity === auto_cr_rules_1.RuleSeverity.Optimizing) {
40
+ severityCounts.optimizing += 1;
41
+ }
24
42
  };
25
43
  var error = function (message) {
26
44
  pushRecord({
27
45
  tag: UNTAGGED_TAG,
28
46
  ruleName: 'general',
29
47
  severity: auto_cr_rules_1.RuleSeverity.Error,
30
- description: message,
48
+ message: message,
31
49
  });
32
50
  };
33
51
  var errorAtLine = function (line, message) {
@@ -35,8 +53,8 @@ function createReporter(filePath, source) {
35
53
  tag: UNTAGGED_TAG,
36
54
  ruleName: 'general',
37
55
  severity: auto_cr_rules_1.RuleSeverity.Error,
38
- description: message,
39
56
  line: line,
57
+ message: message,
40
58
  });
41
59
  };
42
60
  var errorAtSpan = function (spanLike, message) {
@@ -57,17 +75,17 @@ function createReporter(filePath, source) {
57
75
  tag: tag,
58
76
  ruleName: rule.name,
59
77
  severity: severity,
60
- description: payload.description,
78
+ message: payload.message,
61
79
  line: payload.line,
62
80
  code: payload.code,
63
81
  suggestions: payload.suggestions,
64
82
  });
65
83
  };
66
84
  var scopedError = function (message) {
67
- store({ description: message });
85
+ store({ message: message });
68
86
  };
69
87
  var scopedErrorAtLine = function (line, message) {
70
- store({ description: message, line: line });
88
+ store({ message: message, line: line });
71
89
  };
72
90
  var scopedErrorAtSpan = function (spanLike, message) {
73
91
  var span = extractSpan(spanLike);
@@ -78,25 +96,36 @@ function createReporter(filePath, source) {
78
96
  var line = offsetToLine(span.start, offsets);
79
97
  scopedErrorAtLine(line, message);
80
98
  };
81
- var record = function (violation) {
82
- var line = resolveLine(violation, offsets);
99
+ var record = function (payload) {
100
+ var line = resolveLine(payload, offsets);
83
101
  store({
84
- description: violation.description,
102
+ message: payload.description,
85
103
  line: line,
86
- code: violation.code,
87
- suggestions: violation.suggestions,
104
+ code: payload.code,
105
+ suggestions: payload.suggestions,
88
106
  });
89
107
  };
90
- return {
108
+ var reporterWithRecord = {
91
109
  error: scopedError,
92
110
  errorAtLine: scopedErrorAtLine,
93
111
  errorAtSpan: scopedErrorAtSpan,
94
112
  record: record,
95
113
  };
114
+ return reporterWithRecord;
96
115
  };
97
116
  var flush = function () {
117
+ var summary = {
118
+ totalViolations: totalViolations,
119
+ errorViolations: errorViolations,
120
+ severityCounts: {
121
+ error: severityCounts.error,
122
+ warning: severityCounts.warning,
123
+ optimizing: severityCounts.optimizing,
124
+ },
125
+ };
98
126
  if (records.length === 0) {
99
- return;
127
+ resetCounters();
128
+ return summary;
100
129
  }
101
130
  var locale = language === 'zh' ? 'zh-CN' : 'en-US';
102
131
  var formatter = new Intl.DateTimeFormat(locale, {
@@ -108,7 +137,7 @@ function createReporter(filePath, source) {
108
137
  var indent = ' ';
109
138
  var colon = language === 'zh' ? ':' : ':';
110
139
  var headerGap = language === 'zh' ? '' : ' ';
111
- records.forEach(function (violation, index) {
140
+ records.forEach(function (violation) {
112
141
  var timestamp = formatter.format(new Date());
113
142
  var tagLabel = t.ruleTagLabel({ tag: violation.tag });
114
143
  var severityIcon = t.reporterSeverityIcon({ severity: violation.severity });
@@ -117,10 +146,10 @@ function createReporter(filePath, source) {
117
146
  logger(header);
118
147
  var location = typeof violation.line === 'number' ? "".concat(filePath, ":").concat(violation.line) : filePath;
119
148
  consola_1.default.log("".concat(indent).concat(t.reporterFileLabel(), ": ").concat(location));
149
+ consola_1.default.log("".concat(indent).concat(t.reporterDescriptionLabel(), ": ").concat(violation.message));
120
150
  if (violation.code) {
121
151
  consola_1.default.log("".concat(indent).concat(t.reporterCodeLabel(), ": ").concat(violation.code));
122
152
  }
123
- consola_1.default.log("".concat(indent).concat(t.reporterDescriptionLabel(), ": ").concat(violation.description));
124
153
  if (violation.suggestions && violation.suggestions.length > 0) {
125
154
  var suggestionSeparator = language === 'zh' ? '; ' : ' | ';
126
155
  var suggestionLine = violation.suggestions
@@ -130,6 +159,15 @@ function createReporter(filePath, source) {
130
159
  }
131
160
  });
132
161
  records.length = 0;
162
+ resetCounters();
163
+ return summary;
164
+ };
165
+ var resetCounters = function () {
166
+ totalViolations = 0;
167
+ errorViolations = 0;
168
+ severityCounts.error = 0;
169
+ severityCounts.warning = 0;
170
+ severityCounts.optimizing = 0;
133
171
  };
134
172
  return Object.assign({ error: error, errorAtLine: errorAtLine, errorAtSpan: errorAtSpan }, {
135
173
  forRule: buildRuleReporter,
@@ -140,12 +178,12 @@ function getLoggerForSeverity(severity) {
140
178
  var _a;
141
179
  return (_a = severityLoggers[severity]) !== null && _a !== void 0 ? _a : consola_1.default.error;
142
180
  }
143
- function resolveLine(violation, offsets) {
144
- if (typeof violation.line === 'number') {
145
- return violation.line;
181
+ function resolveLine(record, offsets) {
182
+ if (typeof record.line === 'number') {
183
+ return record.line;
146
184
  }
147
- if (violation.span) {
148
- return offsetToLine(violation.span.start, offsets);
185
+ if (record.span) {
186
+ return offsetToLine(record.span.start, offsets);
149
187
  }
150
188
  return undefined;
151
189
  }
@@ -1,6 +1,16 @@
1
1
  import type { Rule, RuleReporter } from 'auto-cr-rules';
2
2
  export interface Reporter extends RuleReporter {
3
3
  forRule(rule: Pick<Rule, 'name' | 'tag' | 'severity'>): RuleReporter;
4
- flush(): void;
4
+ flush(): ReporterSummary;
5
+ }
6
+ interface ReporterSummary {
7
+ totalViolations: number;
8
+ errorViolations: number;
9
+ severityCounts: {
10
+ error: number;
11
+ warning: number;
12
+ optimizing: number;
13
+ };
5
14
  }
6
15
  export declare function createReporter(filePath: string, source: string): Reporter;
16
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auto-cr-cmd",
3
- "version": "2.0.21",
3
+ "version": "2.0.23",
4
4
  "description": "Fast automated code review CLI powered by SWC-based static analysis",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/types/index.d.ts",
@@ -48,15 +48,15 @@
48
48
  "dependencies": {
49
49
  "@swc/core": "^1.13.20",
50
50
  "@swc/wasm": "^1.13.20",
51
- "auto-cr-rules": "^2.0.21",
51
+ "auto-cr-rules": "^2.0.23",
52
52
  "commander": "^14.0.0",
53
53
  "consola": "^3.4.2"
54
54
  },
55
55
  "devDependencies": {
56
- "@eslint/js": "^9.35.0",
56
+ "@eslint/js": "^9.37.0",
57
57
  "@swc/types": "^0.1.25",
58
58
  "@types/node": "^24.3.1",
59
- "eslint": "^9.35.0",
59
+ "eslint": "^9.37.0",
60
60
  "eslint-plugin-prettier": "^5.5.4",
61
61
  "globals": "^16.3.0",
62
62
  "jiti": "^2.5.1",