@yuu1111/quality-check 0.8.0 → 0.9.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/README.ja.md CHANGED
@@ -10,6 +10,8 @@ Projectごとのscriptから個別に呼んでいたBiome、型検査、Knip、c
10
10
  bun add -D @yuu1111/quality-check
11
11
  ```
12
12
 
13
+ engineのbinaryは利用Projectの `node_modules/.bin` から実行時に解決する engineを自分のscriptから呼ばないProjectではKnipが `@yuu1111/comment-check` などを未使用依存として報告するため `knip.ts` の `ignoreDependencies` で理由付きに宣言する
14
+
13
15
  ## Usage
14
16
 
15
17
  `quality.config.ts` で起動するengineとengineごとの起動条件を指定し、scriptから起動する
@@ -50,27 +52,29 @@ export default defineConfig({
50
52
  });
51
53
  ```
52
54
 
53
- engineごとの出力と集約summaryを並べて出し、どのengineが失敗したかを1回の実行で示す
55
+ engineごとの出力と所要時間、集約summaryを並べて出し、どのengineが失敗したかと実行にかかった合計時間を1回の実行で示す
54
56
 
55
57
  ```text
56
58
  == biome ==
57
59
  Checked 128 files in 260ms. No fixes applied.
58
- biome: passed (exit 0)
60
+ biome: passed (exit 0, 296ms)
59
61
 
60
62
  == comment-check ==
61
63
  src/queue.ts:18:2 placeholder-comment placeholder comment should be resolved or tracked
62
- comment-check: failed (1 new, 0 resolved, 0 warnings)
64
+ comment-check: failed (1 new, 0 resolved, 0 warnings, 118ms)
63
65
 
64
- quality-check: 1 of 3 engines failed
66
+ quality-check: 1 of 3 engines failed (1250ms)
65
67
  failed: comment-check
66
68
  passed: biome, tsdoc-check
67
69
  ```
68
70
 
71
+ 終了codeは0が全engine成功、1が失敗したengineあり、2が設定またはengine起動の失敗
72
+
69
73
  ## Config
70
74
 
71
- | Field | Description |
75
+ | Field | 説明 |
72
76
  |-------|-------------|
73
- | `engines` | 起動するengine 値は `true` または `false` |
77
+ | `engines` | 起動するengine、値は `true` または `false` |
74
78
  | `config` | engineごとの起動条件 |
75
79
  | `baseline` | baseline fileのpath `false` なら差分判定を行わない |
76
80
 
@@ -78,7 +82,7 @@ engineは `biome` → `typecheck` → `knip` → `code-style-check` → `comment
78
82
 
79
83
  `engines` は起動の委任だけを表し、起動条件は `config` のengineの下へ置く engineごとの条件は複数行のobjectとして書き、ruleやoptionを足しても他のengineの行が動かないようにする engineが受け取る条件は次のとおり
80
84
 
81
- | engine | 起動するcommand | 受け取る条件 |
85
+ | Engine | Command | 条件 |
82
86
  |--------|-----------------|--------------|
83
87
  | `biome` | `biome check` | `targets`、`args` 除外pathは `biome.json` が持つ |
84
88
  | `typecheck` | `tsc --noEmit` | `args`、`projects` 設定は `tsconfig.json` が持つ |
@@ -88,41 +92,35 @@ engineは `biome` → `typecheck` → `knip` → `code-style-check` → `comment
88
92
  | `document-style-check` | `document-style-check lint --json` | `ignore`、`targets`、`args`、`enable`(有効にするrule名) |
89
93
  | `tsdoc-check` | `tsdoc-check --json` | `ignore`、`targets`、`args`、`error`(違反として扱うrule名) |
90
94
 
91
- `args` はengineの既定引数の後ろへ足す 設定fileで表せない起動条件や、engineの引数が変わったときの逃げ道として使う
95
+ `args` はengineの既定引数の後ろへ足す
96
+ 設定fileで表せない起動条件や、engineの引数が変わったときの逃げ道として使う
97
+
98
+ engineが受け取らない条件は渡さず、その旨をそのengineのsectionへ出す
99
+
100
+ ```text
101
+ == biome ==
102
+ biome: ignore skipped (biome.json holds its settings)
103
+ ```
104
+
105
+ `enable` は `comment-check` と `document-style-check` の `--enable <rule>` になり、他のengineでは拒否される
106
+ このCLIはengineを同梱しないため、opt-in ruleを有効にするProjectは対応するengine packageも同じ変更で更新する
107
+
108
+ `comment-check` はbaseline差分を無効化する未作成のpathを渡して起動する
109
+ 新規と解消済みの判定はengineごとではなく統合CLIが1つのbaseline fileで行うため、既存の `comment-baseline.json` がある場合は `--update-baseline` で移す
110
+
111
+ `typecheck` は `projects` に並べたtsconfigごとに `tsc --noEmit -p <path>` を起動する
112
+ 省略時はカレントの `tsconfig.json` を1回だけ読む
92
113
 
93
114
  ## Options
94
115
 
95
- | Option | Description |
116
+ | Option | 説明 |
96
117
  |--------|-------------|
97
118
  | `--config <path>` | 読み込むconfig file(既定は `quality.config.ts`) |
98
119
  | `--baseline <path>` | baseline fileを上書きする |
99
- | `--ignore <path>` | 除外pathを追加する 複数指定できる |
120
+ | `--ignore <path>` | 除外pathを追加する、複数指定できる |
100
121
  | `--update-baseline` | 現在の検出でbaselineを置き換える |
101
122
  | `--json` | engineごとの結果をJSONで出力する |
102
123
 
103
124
  `--ignore` と位置引数の対象pathは、その条件を受け取るengineへだけ渡す
104
125
 
105
- ## Notes
106
-
107
- 終了codeは0が全engine成功、1が失敗したengineあり、2が設定またはengine起動の失敗
108
-
109
126
  色は標準出力が端末のときだけ付ける `NO_COLOR` で無効にし、`FORCE_COLOR` で強制できる `--json` の出力には付けない
110
-
111
- 色を扱えるengineへは自身の出力の色も許可する Biomeは `--colors=force`、tscは `--pretty` を受け取る
112
-
113
- engineが受け取らない条件を書いた場合は渡さず、その旨をそのengineのsectionへ出す
114
-
115
- ```text
116
- == biome ==
117
- biome: ignore skipped (biome.json holds its settings)
118
- ```
119
-
120
- Biome、型検査、Knipの設定は `biome.json`、`tsconfig.json`、`knip.ts` が持つ このCLIは同じfileからengineの起動と結果の集約だけを行う
121
-
122
- engineのbinaryは利用Projectの `node_modules/.bin` から実行時に解決する engineを自分のscriptから呼ばないProjectではKnipが `@yuu1111/comment-check` などを未使用依存として報告するため `knip.ts` の `ignoreDependencies` で理由付きに宣言する
123
-
124
- `comment-check` はbaseline差分を無効化する未作成のpathを渡して起動する 新規と解消済みの判定はengineごとではなく統合CLIが1つのbaseline fileで行うため、既存の `comment-baseline.json` がある場合は `--update-baseline` で移す
125
-
126
- `enable` は `comment-check` と `document-style-check` のopt-in ruleだけを受け取り、それぞれのcommandの `--enable <rule>` になる 他のengineへ書くとunknown optionとして拒否し、既定のrule集合は変えない このCLIはengineを同梱しないため、opt-in ruleを有効にするProjectは対応するengine packageも同じ変更で更新する
127
-
128
- `typecheck` は `projects` に並べたtsconfigごとに `tsc --noEmit -p <path>` を起動する 省略時はカレントの `tsconfig.json` を1回だけ読み、`args` はすべての起動へ足す
package/README.md CHANGED
@@ -2,8 +2,7 @@
2
2
 
3
3
  # @yuu1111/quality-check
4
4
 
5
- Runs Biome, the type checker, Knip, code-style-check, comment-check,
6
- document-style-check, and the TSDoc checker from one CLI instead of one script per project.
5
+ Runs Biome, the type checker, Knip, code-style-check, comment-check, document-style-check, and the TSDoc checker from one CLI instead of one script per project.
7
6
  The baseline diff lives here too.
8
7
 
9
8
  ## Install
@@ -12,10 +11,12 @@ The baseline diff lives here too.
12
11
  bun add -D @yuu1111/quality-check
13
12
  ```
14
13
 
14
+ An engine binary is resolved at run time from the project's `node_modules/.bin`.
15
+ A project that never calls an engine from its own scripts therefore sees Knip report `@yuu1111/comment-check` and its siblings as unused dependencies, so it declares them in `ignoreDependencies` with the reason.
16
+
15
17
  ## Usage
16
18
 
17
- Declare the engines to run and the conditions of each engine in
18
- `quality.config.ts`, then call the CLI from a script:
19
+ Declare the engines to run and the conditions of each engine in `quality.config.ts`, then call the CLI from a script:
19
20
 
20
21
  ```json
21
22
  {
@@ -53,23 +54,24 @@ export default defineConfig({
53
54
  });
54
55
  ```
55
56
 
56
- Each engine prints its own section, and the summary names the engines that
57
- failed:
57
+ Each engine prints its own section with its own time, and the summary names the engines that failed and the total time the run took:
58
58
 
59
59
  ```text
60
60
  == biome ==
61
61
  Checked 128 files in 260ms. No fixes applied.
62
- biome: passed (exit 0)
62
+ biome: passed (exit 0, 296ms)
63
63
 
64
64
  == comment-check ==
65
65
  src/queue.ts:18:2 placeholder-comment placeholder comment should be resolved or tracked
66
- comment-check: failed (1 new, 0 resolved, 0 warnings)
66
+ comment-check: failed (1 new, 0 resolved, 0 warnings, 118ms)
67
67
 
68
- quality-check: 1 of 3 engines failed
68
+ quality-check: 1 of 3 engines failed (1250ms)
69
69
  failed: comment-check
70
70
  passed: biome, tsdoc-check
71
71
  ```
72
72
 
73
+ Exit code 0 means every engine passed, 1 that at least one failed, and 2 that the configuration or an engine could not start.
74
+
73
75
  ## Config
74
76
 
75
77
  | Field | Description |
@@ -78,12 +80,11 @@ quality-check: 1 of 3 engines failed
78
80
  | `config` | Conditions of each engine |
79
81
  | `baseline` | Baseline file path; `false` disables the diff |
80
82
 
81
- Engines run in the order `biome`, `typecheck`, `knip`, `code-style-check`,
82
- `comment-check`, `document-style-check`, `tsdoc-check`.
83
+ Engines run in the order `biome`, `typecheck`, `knip`, `code-style-check`, `comment-check`, `document-style-check`, `tsdoc-check`.
83
84
 
84
- `engines` only delegates the start-up, and the conditions belong under the
85
- engine in `config`. Write an engine's conditions as a multi-line object, so a
86
- new rule or option changes one engine's block alone. Each engine runs:
85
+ `engines` only delegates the start-up, and the conditions belong under the engine in `config`.
86
+ Write an engine's conditions as a multi-line object, so a new rule or option changes one engine's block alone.
87
+ Each engine runs:
87
88
 
88
89
  | Engine | Command | Conditions |
89
90
  |--------|---------|------------|
@@ -95,8 +96,22 @@ new rule or option changes one engine's block alone. Each engine runs:
95
96
  | `document-style-check` | `document-style-check lint --json` | `ignore`, `targets`, `args`, `enable` (rule names to turn on) |
96
97
  | `tsdoc-check` | `tsdoc-check --json` | `ignore`, `targets`, `args`, `error` (rule names to fail on) |
97
98
 
98
- `args` is appended after the engine defaults, for conditions the config cannot
99
- express and for the case where an engine changes its arguments.
99
+ `args` is appended after the engine defaults, for conditions the config cannot express and for the case where an engine changes its arguments.
100
+
101
+ A condition that an engine does not take is not passed on, and the section says so:
102
+
103
+ ```text
104
+ == biome ==
105
+ biome: ignore skipped (biome.json holds its settings)
106
+ ```
107
+
108
+ `enable` becomes `--enable <rule>` on `comment-check` and `document-style-check`, and the other engines reject the field.
109
+ This CLI ships no engine of its own, so a project that turns an opt-in rule on updates the matching engine package in the same change.
110
+
111
+ `comment-check` runs with an unwritten baseline path so that it reports every finding.
112
+ The new-and-resolved diff is done by this CLI from a single baseline file, so an existing `comment-baseline.json` is moved over with `--update-baseline`.
113
+
114
+ `typecheck` starts `tsc --noEmit -p <path>` once per path in `projects`, and falls back to the current `tsconfig.json`.
100
115
 
101
116
  ## Options
102
117
 
@@ -110,45 +125,5 @@ express and for the case where an engine changes its arguments.
110
125
 
111
126
  `--ignore` and the positional targets reach only the engines that take them.
112
127
 
113
- ## Notes
114
-
115
- Exit code 0 means every engine passed, 1 that at least one failed, and 2 that the
116
- configuration or an engine could not start.
117
-
118
- Color is added only when stdout is a terminal. `NO_COLOR` turns it off and
119
- `FORCE_COLOR` turns it on; the `--json` output stays plain.
120
-
121
- The engines that can color their own output receive the same permission: Biome
122
- gets `--colors=force` and tsc gets `--pretty`.
123
-
124
- A condition that an engine does not take is not passed on, and the section says
125
- so:
126
-
127
- ```text
128
- == biome ==
129
- biome: ignore skipped (biome.json holds its settings)
130
- ```
131
-
132
- Biome, the type checker, and Knip keep their settings in `biome.json`,
133
- `tsconfig.json`, and `knip.ts`. This CLI starts the engines from one file and
134
- aggregates the results.
135
-
136
- An engine binary is resolved at run time from the `node_modules/.bin` of the
137
- project. A project that never calls an engine from its own scripts therefore
138
- sees Knip report `@yuu1111/comment-check` and its siblings as unused
139
- dependencies, so it declares them in `ignoreDependencies` with the reason.
140
-
141
- `comment-check` runs with an unwritten baseline path so that it reports every
142
- finding. The new-and-resolved diff is done by this CLI from a single baseline
143
- file, so an existing `comment-baseline.json` is moved over with
144
- `--update-baseline`.
145
-
146
- `enable` names the opt-in rules of `comment-check` and `document-style-check`
147
- and becomes `--enable <rule>` on each of their commands. The other engines
148
- reject the field, and the default rule set stays as it is. This CLI ships no
149
- engine of its own, so a project that turns an opt-in rule on updates the
150
- matching engine package in the same change.
151
-
152
- `typecheck` starts `tsc --noEmit -p <path>` once per path in `projects`. Without
153
- it the current `tsconfig.json` is read once, and `args` are added to every
154
- start.
128
+ Color is added only when stdout is a terminal.
129
+ `NO_COLOR` turns it off and `FORCE_COLOR` turns it on; the `--json` output stays plain.
package/dist/cli.js CHANGED
@@ -555,12 +555,17 @@ function describeCounts(result) {
555
555
  }
556
556
  return `${result.reported.length} new, ${result.resolved} resolved, ${result.warnings.length} warnings`;
557
557
  }
558
+ function formatMillis(elapsedMs) {
559
+ return `${Math.round(elapsedMs)}ms`;
560
+ }
558
561
  function describeStatus(result, paint) {
559
562
  if (result.status === "error") {
560
- return paint("error", "error");
563
+ const status = paint("error", "error");
564
+ return result.durationMs === null ? status : `${status} (${formatMillis(result.durationMs)})`;
561
565
  }
562
566
  const tone = result.status === "passed" ? "pass" : "error";
563
- return `${paint(result.status, tone)} (${describeCounts(result)})`;
567
+ const elapsed = result.durationMs === null ? "" : `, ${formatMillis(result.durationMs)}`;
568
+ return `${paint(result.status, tone)} (${describeCounts(result)}${elapsed})`;
564
569
  }
565
570
  function formatEngineSection(result, paint = plainPainter) {
566
571
  const lines = [paint(`== ${result.name} ==`, "header")];
@@ -583,14 +588,15 @@ function formatEngineSection(result, paint = plainPainter) {
583
588
  return lines.join(`
584
589
  `);
585
590
  }
586
- function formatSummary(results, paint = plainPainter) {
591
+ function formatSummary(results, elapsedMs, paint = plainPainter) {
587
592
  const failed = results.filter((result) => result.status !== "passed").map((result) => result.name);
588
593
  const passed = results.filter((result) => result.status === "passed").map((result) => result.name);
594
+ const elapsed = ` (${formatMillis(elapsedMs)})`;
589
595
  if (failed.length === 0) {
590
- return paint(`quality-check: ${results.length} engines passed`, "pass");
596
+ return paint(`quality-check: ${results.length} engines passed${elapsed}`, "pass");
591
597
  }
592
598
  const lines = [
593
- paint(`quality-check: ${failed.length} of ${results.length} engines failed`, "error"),
599
+ paint(`quality-check: ${failed.length} of ${results.length} engines failed${elapsed}`, "error"),
594
600
  ` ${paint("failed:", "error")} ${failed.join(", ")}`
595
601
  ];
596
602
  if (passed.length > 0) {
@@ -599,10 +605,12 @@ function formatSummary(results, paint = plainPainter) {
599
605
  return lines.join(`
600
606
  `);
601
607
  }
602
- function toJsonReport(results) {
608
+ function toJsonReport(results, elapsedMs) {
603
609
  return {
610
+ elapsedMs: Math.round(elapsedMs),
604
611
  engines: results.map((result) => ({
605
612
  detected: result.detected.length,
613
+ durationMs: result.durationMs === null ? null : Math.round(result.durationMs),
606
614
  exitCode: result.exitCode,
607
615
  message: result.message ?? null,
608
616
  name: result.name,
@@ -754,25 +762,24 @@ async function runProcessEngine(name, options, executable, context, runner) {
754
762
  status: exitCode === 0 ? "passed" : "failed"
755
763
  };
756
764
  }
757
- async function executeEngine(name, options, context, runner) {
765
+ async function runEngine(name, options, context, runner) {
758
766
  const executable = (options.resolve ?? resolveExecutable)(name, options.cwd);
767
+ const skipped = skippedEngineOptions(name, options.config.config?.[name]);
759
768
  if (executable === null) {
760
769
  return {
761
770
  ...baseResult(name, null, ""),
771
+ durationMs: null,
762
772
  message: `${ENGINE_BINS[name]} is not installed`,
773
+ skipped,
763
774
  status: "error"
764
775
  };
765
776
  }
766
- if (isFindingEngine(name)) {
767
- return await runFindingEngine(name, options, executable, context, runner);
768
- }
769
- return await runProcessEngine(name, options, executable, context, runner);
770
- }
771
- async function runEngine(name, options, context, runner) {
772
- const result = await executeEngine(name, options, context, runner);
777
+ const startedAt = performance.now();
778
+ const result = isFindingEngine(name) ? await runFindingEngine(name, options, executable, context, runner) : await runProcessEngine(name, options, executable, context, runner);
773
779
  return {
774
780
  ...result,
775
- skipped: skippedEngineOptions(name, options.config.config?.[name])
781
+ durationMs: performance.now() - startedAt,
782
+ skipped
776
783
  };
777
784
  }
778
785
  async function runEngines(options) {
@@ -837,6 +844,7 @@ async function main(argv) {
837
844
  }
838
845
  const config = await loadConfig(configPath);
839
846
  const baselinePath = resolveBaselinePath(options, config, cwd);
847
+ const startedAt = performance.now();
840
848
  const results = await runEngines({
841
849
  baseline: options.update || baselinePath === null ? null : readBaseline(baselinePath, "quality"),
842
850
  color,
@@ -845,6 +853,7 @@ async function main(argv) {
845
853
  overrides: { ignore: options.ignores, targets: options.targets },
846
854
  rawBaseline: join2(tmpdir(), `quality-check-raw-${process.pid}.json`)
847
855
  });
856
+ const elapsedMs = performance.now() - startedAt;
848
857
  if (options.update) {
849
858
  if (baselinePath === null) {
850
859
  console.error("baseline is disabled by the configuration");
@@ -856,12 +865,12 @@ async function main(argv) {
856
865
  return 0;
857
866
  }
858
867
  if (options.json) {
859
- console.log(JSON.stringify(toJsonReport(results), null, "\t"));
868
+ console.log(JSON.stringify(toJsonReport(results, elapsedMs), null, "\t"));
860
869
  } else {
861
870
  for (const result of results) {
862
871
  console.log(formatEngineSection(result, paint));
863
872
  }
864
- console.log(formatSummary(results, paint));
873
+ console.log(formatSummary(results, elapsedMs, paint));
865
874
  }
866
875
  return results.some((result) => result.status !== "passed") ? 1 : 0;
867
876
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuu1111/quality-check",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Integrated quality check runner",
5
5
  "repository": {
6
6
  "type": "git",