qfai 0.2.5
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.md +28 -0
- package/assets/init/qfai/README.md +6 -0
- package/assets/init/qfai/contracts/api/api-0001-sample.yaml +14 -0
- package/assets/init/qfai/contracts/db/db-0001-sample.sql +5 -0
- package/assets/init/qfai/contracts/ui/ui-0001-sample.yaml +4 -0
- package/assets/init/qfai/prompts/makeBusinessFlow.md +34 -0
- package/assets/init/qfai/prompts/makeOverview.md +27 -0
- package/assets/init/qfai/spec/decisions/ADR-0001.md +7 -0
- package/assets/init/qfai/spec/scenarios.feature +6 -0
- package/assets/init/qfai/spec/spec-0001-sample.md +29 -0
- package/assets/init/root/.github/workflows/qfai.yml +22 -0
- package/assets/init/root/qfai.config.yaml +29 -0
- package/dist/cli/commands/init.d.ts +8 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +30 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/report.d.ts +8 -0
- package/dist/cli/commands/report.d.ts.map +1 -0
- package/dist/cli/commands/report.js +83 -0
- package/dist/cli/commands/report.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +10 -0
- package/dist/cli/commands/validate.d.ts.map +1 -0
- package/dist/cli/commands/validate.js +66 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/index.cjs +2003 -0
- package/dist/cli/index.cjs.map +1 -0
- package/dist/cli/index.d.cts +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +7 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/index.mjs +1980 -0
- package/dist/cli/index.mjs.map +1 -0
- package/dist/cli/lib/args.d.ts +19 -0
- package/dist/cli/lib/args.d.ts.map +1 -0
- package/dist/cli/lib/args.js +107 -0
- package/dist/cli/lib/args.js.map +1 -0
- package/dist/cli/lib/assets.d.ts +2 -0
- package/dist/cli/lib/assets.d.ts.map +1 -0
- package/dist/cli/lib/assets.js +8 -0
- package/dist/cli/lib/assets.js.map +1 -0
- package/dist/cli/lib/failOn.d.ts +5 -0
- package/dist/cli/lib/failOn.d.ts.map +1 -0
- package/dist/cli/lib/failOn.js +10 -0
- package/dist/cli/lib/failOn.js.map +1 -0
- package/dist/cli/lib/fs.d.ts +11 -0
- package/dist/cli/lib/fs.d.ts.map +1 -0
- package/dist/cli/lib/fs.js +91 -0
- package/dist/cli/lib/fs.js.map +1 -0
- package/dist/cli/lib/logger.d.ts +4 -0
- package/dist/cli/lib/logger.d.ts.map +1 -0
- package/dist/cli/lib/logger.js +10 -0
- package/dist/cli/lib/logger.js.map +1 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +73 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/core/config.d.ts +46 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +224 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/discovery.d.ts +11 -0
- package/dist/core/discovery.d.ts.map +1 -0
- package/dist/core/discovery.js +31 -0
- package/dist/core/discovery.js.map +1 -0
- package/dist/core/fs.d.ts +6 -0
- package/dist/core/fs.d.ts.map +1 -0
- package/dist/core/fs.js +55 -0
- package/dist/core/fs.js.map +1 -0
- package/dist/core/ids.d.ts +5 -0
- package/dist/core/ids.d.ts.map +1 -0
- package/dist/core/ids.js +49 -0
- package/dist/core/ids.js.map +1 -0
- package/dist/core/index.d.ts +11 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +11 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/report.d.ts +41 -0
- package/dist/core/report.d.ts.map +1 -0
- package/dist/core/report.js +238 -0
- package/dist/core/report.js.map +1 -0
- package/dist/core/types.d.ts +27 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/validate.d.ts +4 -0
- package/dist/core/validate.d.ts.map +1 -0
- package/dist/core/validate.js +32 -0
- package/dist/core/validate.js.map +1 -0
- package/dist/core/validators/contracts.d.ts +5 -0
- package/dist/core/validators/contracts.d.ts.map +1 -0
- package/dist/core/validators/contracts.js +157 -0
- package/dist/core/validators/contracts.js.map +1 -0
- package/dist/core/validators/scenario.d.ts +5 -0
- package/dist/core/validators/scenario.d.ts.map +1 -0
- package/dist/core/validators/scenario.js +82 -0
- package/dist/core/validators/scenario.js.map +1 -0
- package/dist/core/validators/spec.d.ts +5 -0
- package/dist/core/validators/spec.d.ts.map +1 -0
- package/dist/core/validators/spec.js +69 -0
- package/dist/core/validators/spec.js.map +1 -0
- package/dist/core/validators/traceability.d.ts +4 -0
- package/dist/core/validators/traceability.d.ts.map +1 -0
- package/dist/core/validators/traceability.js +148 -0
- package/dist/core/validators/traceability.js.map +1 -0
- package/dist/core/version.d.ts +2 -0
- package/dist/core/version.d.ts.map +1 -0
- package/dist/core/version.js +25 -0
- package/dist/core/version.js.map +1 -0
- package/dist/index.cjs +1579 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +132 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1523 -0
- package/dist/index.mjs.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# QFAI Toolkit (v0.2.5)
|
|
2
|
+
|
|
3
|
+
Single-package distribution for QFAI.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
npm i -D qfai
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
npx qfai init
|
|
15
|
+
npx qfai validate --fail-on error --format github --json-path .qfai/out/validate.json
|
|
16
|
+
npx qfai report --json-path .qfai/out/validate.json --out .qfai/out/report.md
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
`validate` は `--fail-on` / `--strict` によって CI ゲート化できます。
|
|
22
|
+
JSON 出力は `--json-path` 指定、または `qfai.config.yaml` の `output.format: json` で有効化できます。
|
|
23
|
+
`report` は `validate.json` が必須で、未生成の場合は exit code 2 で次の手順を案内します。
|
|
24
|
+
`report` の入力は `--json-path` が優先で、未指定の場合は `output.jsonPath` を使います。どちらも未設定の場合はレポートを生成できないため、いずれかを必ず指定してください。既定の出力は `.qfai/out/report.md`(`--format json` の場合は `.qfai/out/report.json`)です。
|
|
25
|
+
`init --yes` は非対話でデフォルトを採用します(現状の init は非対話が既定のため挙動は同じです。将来対話が導入されても自動で承認されます)。既存ファイルがある場合は `--force` が必要です。
|
|
26
|
+
|
|
27
|
+
設定はリポジトリ直下の `qfai.config.yaml` で行います。
|
|
28
|
+
命名規約は `docs/rules/naming.md` を参照してください。
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# makeBusinessFlow
|
|
2
|
+
|
|
3
|
+
あなたは業務フロー(Business Flow: BF)を“推測せず”に整理するアシスタントです。
|
|
4
|
+
Spec群を読み、Specに明示されている情報のみを根拠として、代表的な業務フロー候補と、ステップ→Specの対応表を作成してください。
|
|
5
|
+
|
|
6
|
+
## Inputs
|
|
7
|
+
|
|
8
|
+
- 対象: qfai/spec/spec.md と qfai/spec/spec-0001-\*.md 形式のファイル(4 桁の数字 + ハイフン + slug。実際のパターン: `spec-\d{4}-[^/\\]+\.md`。存在するもの全て)
|
|
9
|
+
|
|
10
|
+
## Output (Option)
|
|
11
|
+
|
|
12
|
+
- docs/flows/overview.md(BF一覧)
|
|
13
|
+
- docs/flows/bf-0001-<slug>.md 等(個別BF)
|
|
14
|
+
|
|
15
|
+
## Hard Rules
|
|
16
|
+
|
|
17
|
+
- Specに書かれていない業務フローを“創作”しない。
|
|
18
|
+
- 根拠が薄い場合は候補として列挙し `TBD` を付ける。
|
|
19
|
+
- BFの各ステップは必ず SPEC-ID に紐づける。
|
|
20
|
+
- BR/SC/UI/API/DB の参照は Spec に書かれているもののみ。
|
|
21
|
+
|
|
22
|
+
## BF Document Format (per BF)
|
|
23
|
+
|
|
24
|
+
- BF-ID / Title
|
|
25
|
+
- Scope(開始条件/終了条件)
|
|
26
|
+
- Actors(登場人物)
|
|
27
|
+
- Steps(番号付き): step → SPEC-ID → 一行説明
|
|
28
|
+
- Related BR / SC
|
|
29
|
+
- Open Questions(TBD列挙)
|
|
30
|
+
|
|
31
|
+
## Safety
|
|
32
|
+
|
|
33
|
+
- 既存ファイルがある場合は、`<!-- qfai:generated:start -->` と `<!-- qfai:generated:end -->` の範囲だけ更新。
|
|
34
|
+
- それ以外の手書き領域は絶対に変更しない。
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# makeOverview
|
|
2
|
+
|
|
3
|
+
あなたはドキュメント生成アシスタントです。リポジトリ内の Spec を走査し、Spec一覧(overview)を生成してください。
|
|
4
|
+
|
|
5
|
+
## Inputs
|
|
6
|
+
|
|
7
|
+
- 対象: qfai/spec/spec.md と qfai/spec/spec-0001-\*.md 形式のファイル(4 桁の数字 + ハイフン + slug。実際のパターン: `spec-\d{4}-[^/\\]+\.md`。存在するもの全て)
|
|
8
|
+
|
|
9
|
+
## Output
|
|
10
|
+
|
|
11
|
+
- docs/specs/overview.md を更新
|
|
12
|
+
- 更新は必ず次の範囲のみ:
|
|
13
|
+
- <!-- qfai:generated:start -->
|
|
14
|
+
- <!-- qfai:generated:end -->
|
|
15
|
+
|
|
16
|
+
## Rules
|
|
17
|
+
|
|
18
|
+
- Spec本文に書かれていないことは推測しない(不明は `TBD` と書く)。
|
|
19
|
+
- SpecのIDとタイトルは、本文先頭の `# SPEC-xxxx ...` を正とし、ファイル名は補助。
|
|
20
|
+
- 各Specについて最低限以下を表にする:
|
|
21
|
+
- SPEC-ID / Title / Outcome(1行) / Status / SC / UI / API / DB(or DATA) / Tags
|
|
22
|
+
- 参照が欠けている場合(例: SCが未記載)は “欠落一覧” に列挙する。
|
|
23
|
+
|
|
24
|
+
## Format
|
|
25
|
+
|
|
26
|
+
- Markdown table
|
|
27
|
+
- 生成日時(JST)と、参照したSpecファイル一覧を末尾に付記する。
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: qfai
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
validate:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
- uses: actions/setup-node@v4
|
|
14
|
+
with:
|
|
15
|
+
node-version: 20
|
|
16
|
+
cache: npm
|
|
17
|
+
- run: npm ci
|
|
18
|
+
- run: npx qfai validate --fail-on error --format github --json-path .qfai/out/validate.json
|
|
19
|
+
- uses: actions/upload-artifact@v4
|
|
20
|
+
with:
|
|
21
|
+
name: qfai-validation
|
|
22
|
+
path: .qfai/out/validate.json
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
paths:
|
|
2
|
+
specDir: qfai/spec
|
|
3
|
+
decisionsDir: qfai/spec/decisions
|
|
4
|
+
scenariosDir: qfai/spec
|
|
5
|
+
rulesDir: qfai/rules
|
|
6
|
+
contractsDir: qfai/contracts
|
|
7
|
+
uiContractsDir: qfai/contracts/ui
|
|
8
|
+
apiContractsDir: qfai/contracts/api
|
|
9
|
+
dataContractsDir: qfai/contracts/db
|
|
10
|
+
srcDir: src
|
|
11
|
+
testsDir: tests
|
|
12
|
+
validation:
|
|
13
|
+
failOn: error
|
|
14
|
+
require:
|
|
15
|
+
specSections:
|
|
16
|
+
- 背景
|
|
17
|
+
- スコープ
|
|
18
|
+
- 非ゴール
|
|
19
|
+
- 用語
|
|
20
|
+
- 前提
|
|
21
|
+
- 決定事項
|
|
22
|
+
- 業務ルール
|
|
23
|
+
traceability:
|
|
24
|
+
brMustHaveSc: true
|
|
25
|
+
scMustTouchContracts: true
|
|
26
|
+
allowOrphanContracts: false
|
|
27
|
+
output:
|
|
28
|
+
format: text
|
|
29
|
+
jsonPath: .qfai/out/validate.json
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,EAAE,OAAO,CAAC;CACd,CAAC;AAEF,wBAAsB,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBjE"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { copyTemplateTree } from "../lib/fs.js";
|
|
3
|
+
import { getInitAssetsDir } from "../lib/assets.js";
|
|
4
|
+
import { info } from "../lib/logger.js";
|
|
5
|
+
export async function runInit(options) {
|
|
6
|
+
const assetsRoot = getInitAssetsDir();
|
|
7
|
+
const rootAssets = path.join(assetsRoot, "root");
|
|
8
|
+
const qfaiAssets = path.join(assetsRoot, "qfai");
|
|
9
|
+
const destRoot = path.resolve(options.dir);
|
|
10
|
+
const destQfai = path.join(destRoot, "qfai");
|
|
11
|
+
const rootResult = await copyTemplateTree(rootAssets, destRoot, {
|
|
12
|
+
force: options.force,
|
|
13
|
+
dryRun: options.dryRun,
|
|
14
|
+
});
|
|
15
|
+
const qfaiResult = await copyTemplateTree(qfaiAssets, destQfai, {
|
|
16
|
+
force: options.force,
|
|
17
|
+
dryRun: options.dryRun,
|
|
18
|
+
});
|
|
19
|
+
report([...rootResult.copied, ...qfaiResult.copied], [...rootResult.skipped, ...qfaiResult.skipped], options.dryRun, "init");
|
|
20
|
+
}
|
|
21
|
+
function report(copied, skipped, dryRun, label) {
|
|
22
|
+
info(`qfai ${label}: ${dryRun ? "dry-run" : "done"}`);
|
|
23
|
+
if (copied.length > 0) {
|
|
24
|
+
info(` created: ${copied.length}`);
|
|
25
|
+
}
|
|
26
|
+
if (skipped.length > 0) {
|
|
27
|
+
info(` skipped: ${skipped.length}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AASxC,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAAoB;IAChD,MAAM,UAAU,GAAG,gBAAgB,EAAE,CAAC;IACtC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAEjD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAE7C,MAAM,UAAU,GAAG,MAAM,gBAAgB,CAAC,UAAU,EAAE,QAAQ,EAAE;QAC9D,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,MAAM,gBAAgB,CAAC,UAAU,EAAE,QAAQ,EAAE;QAC9D,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IAEH,MAAM,CACJ,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,EAC5C,CAAC,GAAG,UAAU,CAAC,OAAO,EAAE,GAAG,UAAU,CAAC,OAAO,CAAC,EAC9C,OAAO,CAAC,MAAM,EACd,MAAM,CACP,CAAC;AACJ,CAAC;AAED,SAAS,MAAM,CACb,MAAgB,EAChB,OAAiB,EACjB,MAAe,EACf,KAAa;IAEb,IAAI,CAAC,QAAQ,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IACtD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,IAAI,CAAC,cAAc,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IACtC,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,IAAI,CAAC,cAAc,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACvC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/report.ts"],"names":[],"mappings":"AAeA,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,IAAI,GAAG,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wBAAsB,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA4CrE"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { loadConfig } from "../../core/config.js";
|
|
4
|
+
import { createReportData, formatReportJson, formatReportMarkdown, } from "../../core/report.js";
|
|
5
|
+
import { VALIDATION_SCHEMA_VERSION, } from "../../core/types.js";
|
|
6
|
+
import { error, info } from "../lib/logger.js";
|
|
7
|
+
export async function runReport(options) {
|
|
8
|
+
const root = path.resolve(options.root);
|
|
9
|
+
const configResult = await loadConfig(root);
|
|
10
|
+
const input = options.jsonPath ?? configResult.config.output.jsonPath;
|
|
11
|
+
const inputPath = path.isAbsolute(input) ? input : path.resolve(root, input);
|
|
12
|
+
let validation;
|
|
13
|
+
try {
|
|
14
|
+
validation = await readValidationResult(inputPath);
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
if (isMissingFileError(err)) {
|
|
18
|
+
error([
|
|
19
|
+
`qfai report: 入力ファイルが見つかりません: ${inputPath}`,
|
|
20
|
+
"",
|
|
21
|
+
"まず validate.json を生成してください。例:",
|
|
22
|
+
` qfai validate --json-path ${input}`,
|
|
23
|
+
"",
|
|
24
|
+
"GitHub Actions テンプレを使っている場合は、workflow の validate ジョブを先に実行してください。",
|
|
25
|
+
].join("\n"));
|
|
26
|
+
process.exitCode = 2;
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
throw err;
|
|
30
|
+
}
|
|
31
|
+
const data = await createReportData(root, validation, configResult);
|
|
32
|
+
const output = options.format === "json"
|
|
33
|
+
? formatReportJson(data)
|
|
34
|
+
: formatReportMarkdown(data);
|
|
35
|
+
const defaultOut = options.format === "json" ? ".qfai/out/report.json" : ".qfai/out/report.md";
|
|
36
|
+
const out = options.outPath ?? defaultOut;
|
|
37
|
+
const outPath = path.isAbsolute(out) ? out : path.resolve(root, out);
|
|
38
|
+
await mkdir(path.dirname(outPath), { recursive: true });
|
|
39
|
+
await writeFile(outPath, `${output}\n`, "utf-8");
|
|
40
|
+
info(`report: info=${validation.counts.info} warning=${validation.counts.warning} error=${validation.counts.error}`);
|
|
41
|
+
info(`wrote report: ${outPath}`);
|
|
42
|
+
}
|
|
43
|
+
async function readValidationResult(inputPath) {
|
|
44
|
+
const raw = await readFile(inputPath, "utf-8");
|
|
45
|
+
const parsed = JSON.parse(raw);
|
|
46
|
+
if (!isValidationResult(parsed)) {
|
|
47
|
+
throw new Error(`validate.json の形式が不正です: ${inputPath}`);
|
|
48
|
+
}
|
|
49
|
+
if (parsed.schemaVersion !== VALIDATION_SCHEMA_VERSION) {
|
|
50
|
+
throw new Error(`validate.json の schemaVersion が不一致です: expected ${VALIDATION_SCHEMA_VERSION}, actual ${parsed.schemaVersion}`);
|
|
51
|
+
}
|
|
52
|
+
return parsed;
|
|
53
|
+
}
|
|
54
|
+
function isValidationResult(value) {
|
|
55
|
+
if (!value || typeof value !== "object") {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
const record = value;
|
|
59
|
+
if (typeof record.schemaVersion !== "string") {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
if (typeof record.toolVersion !== "string") {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
if (!Array.isArray(record.issues)) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
const counts = record.counts;
|
|
69
|
+
if (!counts) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
return (typeof counts.info === "number" &&
|
|
73
|
+
typeof counts.warning === "number" &&
|
|
74
|
+
typeof counts.error === "number");
|
|
75
|
+
}
|
|
76
|
+
function isMissingFileError(error) {
|
|
77
|
+
if (!error || typeof error !== "object") {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
const record = error;
|
|
81
|
+
return record.code === "ENOENT";
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/cli/commands/report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FailOn, OutputFormat } from "../../core/config.js";
|
|
2
|
+
export type ValidateOptions = {
|
|
3
|
+
root: string;
|
|
4
|
+
strict: boolean;
|
|
5
|
+
failOn?: FailOn;
|
|
6
|
+
format?: OutputFormat;
|
|
7
|
+
jsonPath?: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function runValidate(options: ValidateOptions): Promise<number>;
|
|
10
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/validate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAMjE,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAsB,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CA0B3E"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { loadConfig } from "../../core/config.js";
|
|
4
|
+
import { validateProject } from "../../core/validate.js";
|
|
5
|
+
import { shouldFail } from "../lib/failOn.js";
|
|
6
|
+
export async function runValidate(options) {
|
|
7
|
+
const root = path.resolve(options.root);
|
|
8
|
+
const configResult = await loadConfig(root);
|
|
9
|
+
const result = await validateProject(root, configResult);
|
|
10
|
+
const format = options.format ?? configResult.config.output.format;
|
|
11
|
+
const explicitJsonPath = options.jsonPath;
|
|
12
|
+
if (format === "text") {
|
|
13
|
+
emitText(result);
|
|
14
|
+
}
|
|
15
|
+
if (format === "github") {
|
|
16
|
+
result.issues.forEach(emitGitHub);
|
|
17
|
+
}
|
|
18
|
+
const shouldWriteJson = format === "json" || explicitJsonPath !== undefined;
|
|
19
|
+
if (shouldWriteJson) {
|
|
20
|
+
const jsonPath = format === "json"
|
|
21
|
+
? (options.jsonPath ?? configResult.config.output.jsonPath)
|
|
22
|
+
: explicitJsonPath;
|
|
23
|
+
if (jsonPath) {
|
|
24
|
+
await emitJson(result, root, jsonPath);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const failOn = resolveFailOn(options, configResult.config.validation.failOn);
|
|
28
|
+
return shouldFail(result, failOn) ? 1 : 0;
|
|
29
|
+
}
|
|
30
|
+
function resolveFailOn(options, fallback) {
|
|
31
|
+
if (options.failOn) {
|
|
32
|
+
return options.failOn;
|
|
33
|
+
}
|
|
34
|
+
if (options.strict) {
|
|
35
|
+
return "warning";
|
|
36
|
+
}
|
|
37
|
+
return fallback;
|
|
38
|
+
}
|
|
39
|
+
function emitText(result) {
|
|
40
|
+
for (const item of result.issues) {
|
|
41
|
+
const location = item.file ? ` (${item.file})` : "";
|
|
42
|
+
const refs = item.refs && item.refs.length > 0 ? ` refs=${item.refs.join(",")}` : "";
|
|
43
|
+
process.stdout.write(`[${item.severity}] ${item.code} ${item.message}${location}${refs}\n`);
|
|
44
|
+
}
|
|
45
|
+
process.stdout.write(`counts: info=${result.counts.info} warning=${result.counts.warning} error=${result.counts.error}\n`);
|
|
46
|
+
}
|
|
47
|
+
function emitGitHub(issue) {
|
|
48
|
+
const level = issue.severity === "error"
|
|
49
|
+
? "error"
|
|
50
|
+
: issue.severity === "warning"
|
|
51
|
+
? "warning"
|
|
52
|
+
: "notice";
|
|
53
|
+
const file = issue.file ? `file=${issue.file}` : "";
|
|
54
|
+
const line = issue.loc?.line ? `,line=${issue.loc.line}` : "";
|
|
55
|
+
const column = issue.loc?.column ? `,col=${issue.loc.column}` : "";
|
|
56
|
+
const location = file ? ` ${file}${line}${column}` : "";
|
|
57
|
+
process.stdout.write(`::${level}${location}::${issue.code}: ${issue.message}\n`);
|
|
58
|
+
}
|
|
59
|
+
async function emitJson(result, root, jsonPath) {
|
|
60
|
+
const abs = path.isAbsolute(jsonPath)
|
|
61
|
+
? jsonPath
|
|
62
|
+
: path.resolve(root, jsonPath);
|
|
63
|
+
await mkdir(path.dirname(abs), { recursive: true });
|
|
64
|
+
await writeFile(abs, `${JSON.stringify(result, null, 2)}\n`, "utf-8");
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/cli/commands/validate.ts"],"names":[],"mappings":"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"}
|