@yuu1111/quality-check 0.9.0 → 0.11.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,7 +10,10 @@ 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` で理由付きに宣言する
13
+ このCLIは `comment-check`、`document-style-check`、`tsdoc-check` を、configの型がengineの公開するrule名を取り込むためpeer dependencyとして持つ
14
+ package managerはこのCLIと一緒に導入し、engineのbinaryは利用Projectの `node_modules/.bin` から実行時に解決する
15
+
16
+ `@yuu1111/code-style-check` を宣言するProjectではKnipが未使用依存として報告するため `knip.ts` の `ignoreDependencies` で理由付きに宣言する
14
17
 
15
18
  ## Usage
16
19
 
@@ -90,7 +93,7 @@ engineは `biome` → `typecheck` → `knip` → `code-style-check` → `comment
90
93
  | `code-style-check` | `code-style-check --json` | `ignore`、`targets`、`args` |
91
94
  | `comment-check` | `comment-check --json` | `ignore`、`targets`、`args`、`enable`(有効にするrule名) |
92
95
  | `document-style-check` | `document-style-check lint --json` | `ignore`、`targets`、`args`、`enable`(有効にするrule名) |
93
- | `tsdoc-check` | `tsdoc-check --json` | `ignore`、`targets`、`args`、`error`(違反として扱うrule名) |
96
+ | `tsdoc-check` | `tsdoc-check --json` | `ignore`、`targets`、`args`、`enable`(有効にするrule名)、`error`(違反として扱うrule名) |
94
97
 
95
98
  `args` はengineの既定引数の後ろへ足す
96
99
  設定fileで表せない起動条件や、engineの引数が変わったときの逃げ道として使う
@@ -102,8 +105,8 @@ engineが受け取らない条件は渡さず、その旨をそのengineのsecti
102
105
  biome: ignore skipped (biome.json holds its settings)
103
106
  ```
104
107
 
105
- `enable` は `comment-check` と `document-style-check` の `--enable <rule>` になり、他のengineでは拒否される
106
- このCLIはengineを同梱しないため、opt-in ruleを有効にするProjectは対応するengine packageも同じ変更で更新する
108
+ `enable` は `comment-check` と `document-style-check` と `tsdoc-check` の `--enable <rule>` になり、他のengineでは拒否される
109
+ 値は導入済みengineが `rule-ids` で公開するrule名で型付けするため、engineが知らない名前は起動時の失敗ではなく型errorになる
107
110
 
108
111
  `comment-check` はbaseline差分を無効化する未作成のpathを渡して起動する
109
112
  新規と解消済みの判定はengineごとではなく統合CLIが1つのbaseline fileで行うため、既存の `comment-baseline.json` がある場合は `--update-baseline` で移す
package/README.md CHANGED
@@ -11,8 +11,10 @@ The baseline diff lives here too.
11
11
  bun add -D @yuu1111/quality-check
12
12
  ```
13
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.
14
+ `comment-check`, `document-style-check`, and `tsdoc-check` are peer dependencies of this CLI, because the config types embed the rule names those engines publish.
15
+ A package manager installs them with this CLI, and each engine binary is resolved at run time from the project's `node_modules/.bin`.
16
+
17
+ A project that declares `@yuu1111/code-style-check` sees Knip report it as an unused dependency, so it names it in `ignoreDependencies` with the reason.
16
18
 
17
19
  ## Usage
18
20
 
@@ -94,7 +96,7 @@ Each engine runs:
94
96
  | `code-style-check` | `code-style-check --json` | `ignore`, `targets`, `args` |
95
97
  | `comment-check` | `comment-check --json` | `ignore`, `targets`, `args`, `enable` (rule names to turn on) |
96
98
  | `document-style-check` | `document-style-check lint --json` | `ignore`, `targets`, `args`, `enable` (rule names to turn on) |
97
- | `tsdoc-check` | `tsdoc-check --json` | `ignore`, `targets`, `args`, `error` (rule names to fail on) |
99
+ | `tsdoc-check` | `tsdoc-check --json` | `ignore`, `targets`, `args`, `enable` (rule names to turn on), `error` (rule names to fail on) |
98
100
 
99
101
  `args` is appended after the engine defaults, for conditions the config cannot express and for the case where an engine changes its arguments.
100
102
 
@@ -105,8 +107,8 @@ A condition that an engine does not take is not passed on, and the section says
105
107
  biome: ignore skipped (biome.json holds its settings)
106
108
  ```
107
109
 
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
+ `enable` becomes `--enable <rule>` on `comment-check`, `document-style-check`, and `tsdoc-check`, and the other engines reject the field.
111
+ Each value is typed with the rule names the installed engine publishes from its `rule-ids` entry, so a name that engine does not know is a type error rather than a start-up failure.
110
112
 
111
113
  `comment-check` runs with an unwritten baseline path so that it reports every finding.
112
114
  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`.
package/dist/cli.js CHANGED
@@ -223,7 +223,7 @@ var ENGINE_OPTION_KEYS = {
223
223
  "code-style-check": ["args", "ignore", "targets"],
224
224
  "comment-check": ["args", "enable", "ignore", "targets"],
225
225
  "document-style-check": ["args", "enable", "ignore", "targets"],
226
- "tsdoc-check": ["args", "error", "ignore", "targets"]
226
+ "tsdoc-check": ["args", "enable", "error", "ignore", "targets"]
227
227
  };
228
228
  function readStringArray(value, field) {
229
229
  if (value === undefined) {
@@ -264,7 +264,7 @@ function parseEngines(value, source) {
264
264
  }
265
265
  function parseEngineExtras(value, source, name) {
266
266
  const extras = {};
267
- if (name === "comment-check" || name === "document-style-check") {
267
+ if (name === "comment-check" || name === "document-style-check" || name === "tsdoc-check") {
268
268
  const enable = readStringArray(value.enable, `${source}: config.${name}.enable`);
269
269
  if (enable !== undefined) {
270
270
  extras.enable = enable;
@@ -517,6 +517,7 @@ function buildEngineCommand(name, executable, context) {
517
517
  return [
518
518
  executable,
519
519
  "--json",
520
+ ...enableArguments(engineConfig(context.config, "tsdoc-check")),
520
521
  ...errorArguments,
521
522
  ...targets,
522
523
  ...ignoreArguments,
@@ -646,8 +647,8 @@ function parseJson(engine, stdout) {
646
647
  let value;
647
648
  try {
648
649
  value = JSON.parse(stdout);
649
- } catch {
650
- throw new Error(`${engine} did not print JSON`);
650
+ } catch (error) {
651
+ throw new Error(`${engine} did not print JSON`, { cause: error });
651
652
  }
652
653
  if (!isJsonObject(value)) {
653
654
  throw new Error(`${engine} printed an unexpected JSON value`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuu1111/quality-check",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "description": "Integrated quality check runner",
5
5
  "repository": {
6
6
  "type": "git",
@@ -29,6 +29,11 @@
29
29
  "quality",
30
30
  "lint"
31
31
  ],
32
+ "peerDependencies": {
33
+ "@yuu1111/comment-check": ">=2.3.0",
34
+ "@yuu1111/document-style-check": ">=0.5.0",
35
+ "@yuu1111/tsdoc-check": ">=2.2.0"
36
+ },
32
37
  "devDependencies": {
33
38
  "@yuu1111/shared": "workspace:*"
34
39
  }
package/src/config.ts CHANGED
@@ -1,6 +1,12 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { resolve } from "node:path";
3
3
  import { pathToFileURL } from "node:url";
4
+ import type { OptInRuleId as CommentCheckRuleName } from "@yuu1111/comment-check/rule-ids";
5
+ import type { OptInRuleId as DocumentStyleCheckRuleName } from "@yuu1111/document-style-check/rule-ids";
6
+ import type {
7
+ OptInRuleId as TsdocCheckRuleName,
8
+ TsdocRule,
9
+ } from "@yuu1111/tsdoc-check/rule-ids";
4
10
 
5
11
  /**
6
12
  * 統合CLIが起動できるengineの名前 並び順が実行順になる
@@ -36,24 +42,26 @@ export interface EngineOptions {
36
42
  * comment-checkへ渡す起動条件
37
43
  */
38
44
  export interface CommentCheckOptions extends EngineOptions {
39
- /** 既定で無効のopt-in ruleのうち有効にするrule名 */
40
- enable?: string[];
45
+ /** 既定で無効のopt-in ruleのうち有効にするrule名 comment-checkが公開するunionで縛る */
46
+ enable?: CommentCheckRuleName[];
41
47
  }
42
48
 
43
49
  /**
44
50
  * document-style-checkへ渡す起動条件
45
51
  */
46
52
  export interface DocumentStyleCheckOptions extends EngineOptions {
47
- /** 既定で無効のopt-in ruleのうち有効にするrule名 */
48
- enable?: string[];
53
+ /** 既定で無効のopt-in ruleのうち有効にするrule名 document-style-checkが公開するunionで縛る */
54
+ enable?: DocumentStyleCheckRuleName[];
49
55
  }
50
56
 
51
57
  /**
52
58
  * TSDoc検査へ渡す起動条件
53
59
  */
54
60
  export interface TsdocCheckOptions extends EngineOptions {
55
- /** 違反として扱うrule名 */
56
- error?: string[];
61
+ /** 既定で無効のopt-in ruleのうち有効にするruletsdoc-checkが公開するunionで縛る */
62
+ enable?: TsdocCheckRuleName[];
63
+ /** 違反として扱うrule名 tsdoc-checkが公開するunionで縛る */
64
+ error?: TsdocRule[];
57
65
  }
58
66
 
59
67
  /**
@@ -91,6 +99,9 @@ export interface QualityConfig {
91
99
 
92
100
  /**
93
101
  * 設定fileを型付けするための恒等関数
102
+ *
103
+ * @param config - 型付けする統合検査の設定
104
+ * @returns 引数をそのまま返した統合検査の設定
94
105
  */
95
106
  export function defineConfig(config: QualityConfig): QualityConfig {
96
107
  return config;
@@ -128,7 +139,7 @@ const ENGINE_OPTION_KEYS: Record<EngineName, readonly string[]> = {
128
139
  "code-style-check": ["args", "ignore", "targets"],
129
140
  "comment-check": ["args", "enable", "ignore", "targets"],
130
141
  "document-style-check": ["args", "enable", "ignore", "targets"],
131
- "tsdoc-check": ["args", "error", "ignore", "targets"],
142
+ "tsdoc-check": ["args", "enable", "error", "ignore", "targets"],
132
143
  };
133
144
 
134
145
  function readStringArray(value: unknown, field: string): string[] | undefined {
@@ -197,7 +208,11 @@ function parseEngineExtras(
197
208
  name: EngineName,
198
209
  ): ParsedEngineOptions {
199
210
  const extras: ParsedEngineOptions = {};
200
- if (name === "comment-check" || name === "document-style-check") {
211
+ if (
212
+ name === "comment-check" ||
213
+ name === "document-style-check" ||
214
+ name === "tsdoc-check"
215
+ ) {
201
216
  const enable = readStringArray(
202
217
  value.enable,
203
218
  `${source}: config.${name}.enable`,
@@ -275,7 +290,7 @@ function parseEngineConfig(
275
290
  if (!isJsonObject(value)) {
276
291
  throw new Error(`${source}: config must be an object`);
277
292
  }
278
- const config: Partial<EngineConfigMap> = {};
293
+ const config: Partial<Record<EngineName, ParsedEngineOptions>> = {};
279
294
  for (const [name, options] of Object.entries(value)) {
280
295
  if (!isEngineName(name)) {
281
296
  throw new Error(`${source}: unknown engine in config: ${name}`);
@@ -285,11 +300,17 @@ function parseEngineConfig(
285
300
  }
286
301
  config[name] = parseEngineOptions(options, source, name);
287
302
  }
288
- return config;
303
+
304
+ // rule名はengineが公開するunionで縛る 実行時の入力は文字列として届くため検証済みの値をここで型へ寄せる
305
+ return config as Partial<EngineConfigMap>;
289
306
  }
290
307
 
291
308
  /**
292
309
  * 読み込んだ設定を検証して不足分を補う
310
+ *
311
+ * @param value - config fileがexportした検証前の値
312
+ * @param source - errorメッセージへ載せるconfig fileのpath
313
+ * @returns 検証して既定値を補った統合検査の設定
293
314
  */
294
315
  export function parseConfig(value: unknown, source: string): QualityConfig {
295
316
  if (!isJsonObject(value)) {
@@ -311,6 +332,9 @@ export function parseConfig(value: unknown, source: string): QualityConfig {
311
332
 
312
333
  /**
313
334
  * 有効なengineを実行順で返す
335
+ *
336
+ * @param config - engineの有効無効を持つ統合検査の設定
337
+ * @returns 有効なengine名を実行順に並べた配列
314
338
  */
315
339
  export function enabledEngines(config: QualityConfig): EngineName[] {
316
340
  return ENGINE_NAMES.filter((name) => Boolean(config.engines[name]));
@@ -318,6 +342,11 @@ export function enabledEngines(config: QualityConfig): EngineName[] {
318
342
 
319
343
  /**
320
344
  * engineの起動条件を返す 無効なengineにはnullを返す
345
+ *
346
+ * @typeParam K - 起動条件を取り出すengine名の型
347
+ * @param config - engineごとの起動条件を持つ統合検査の設定
348
+ * @param name - 起動条件を取り出すengine名
349
+ * @returns 指定したengineの起動条件 無効なengineならnull
321
350
  */
322
351
  export function engineConfig<K extends EngineName>(
323
352
  config: QualityConfig,
@@ -331,6 +360,9 @@ export function engineConfig<K extends EngineName>(
331
360
 
332
361
  /**
333
362
  * 作業ディレクトリからconfig fileを探す
363
+ *
364
+ * @param cwd - 探索を開始する作業ディレクトリのpath
365
+ * @returns 見つけたconfig fileのpath 見つからなければnull
334
366
  */
335
367
  export function findConfigFile(cwd: string): string | null {
336
368
  for (const name of DEFAULT_CONFIG_FILES) {
@@ -344,6 +376,9 @@ export function findConfigFile(cwd: string): string | null {
344
376
 
345
377
  /**
346
378
  * config fileを読み込んで検証する
379
+ *
380
+ * @param path - 読み込むconfig fileのpath
381
+ * @returns 読み込んで検証した統合検査の設定
347
382
  */
348
383
  export async function loadConfig(path: string): Promise<QualityConfig> {
349
384
  const module: unknown = await import(pathToFileURL(path).href);
package/src/engines.ts CHANGED
@@ -85,6 +85,10 @@ export const ENGINE_LIMITS: Record<
85
85
 
86
86
  /**
87
87
  * engineが受け取らないため渡さなかった起動条件を返す
88
+ *
89
+ * @param name - 受け取れない起動条件を引くengine名
90
+ * @param options - engineへ渡そうとした起動条件
91
+ * @returns 渡さなかった起動条件とその理由の一覧
88
92
  */
89
93
  export function skippedEngineOptions(
90
94
  name: EngineName,
@@ -106,6 +110,9 @@ export function skippedEngineOptions(
106
110
 
107
111
  /**
108
112
  * 検出をJSONで返すengineか
113
+ *
114
+ * @param name - 判定するengine名
115
+ * @returns 検出をJSONで返すengineならtrue
109
116
  */
110
117
  export function isFindingEngine(name: EngineName): boolean {
111
118
  return (
@@ -118,6 +125,10 @@ export function isFindingEngine(name: EngineName): boolean {
118
125
 
119
126
  /**
120
127
  * node_modules/.binとPATHからengineの実行fileを探す
128
+ *
129
+ * @param name - 実行fileを探すengine名
130
+ * @param cwd - 探索を開始する作業ディレクトリのpath
131
+ * @returns 見つけた実行fileのpath PATHにも無ければnull
121
132
  */
122
133
  export function resolveExecutable(
123
134
  name: EngineName,
@@ -193,6 +204,11 @@ function enableArguments(
193
204
 
194
205
  /**
195
206
  * engineへ渡すコマンドを組み立てる
207
+ *
208
+ * @param name - コマンドを組み立てるengine名
209
+ * @param executable - 起動するengineの実行fileのpath
210
+ * @param context - 設定と上書きを持つ実行条件
211
+ * @returns engineへ渡す引数を並べたコマンド
196
212
  */
197
213
  export function buildEngineCommand(
198
214
  name: EngineName,
@@ -258,6 +274,7 @@ export function buildEngineCommand(
258
274
  return [
259
275
  executable,
260
276
  "--json",
277
+ ...enableArguments(engineConfig(context.config, "tsdoc-check")),
261
278
  ...errorArguments,
262
279
  ...targets,
263
280
  ...ignoreArguments,
@@ -267,6 +284,11 @@ export function buildEngineCommand(
267
284
 
268
285
  /**
269
286
  * engineの起動コマンドを順番に返す 型検査だけはprojectsごとに起動する
287
+ *
288
+ * @param name - コマンドを組み立てるengine名
289
+ * @param executable - 起動するengineの実行fileのpath
290
+ * @param context - 設定と上書きを持つ実行条件
291
+ * @returns 起動する順に並べたコマンドの配列
270
292
  */
271
293
  export function buildEngineCommands(
272
294
  name: EngineName,
@@ -287,6 +309,10 @@ export function buildEngineCommands(
287
309
 
288
310
  /**
289
311
  * Bun.spawnでengineを起動する既定のrunner
312
+ *
313
+ * @param command - 実行fileと引数を並べたコマンド
314
+ * @param options - engineを起動する作業ディレクトリを持つ条件
315
+ * @returns 終了codeと標準出力と標準エラーを持つ結果
290
316
  */
291
317
  export async function runEngineProcess(
292
318
  command: string[],