@a11yst/cli 1.0.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.
Files changed (165) hide show
  1. package/LICENSE +373 -0
  2. package/NOTICE.md +11 -0
  3. package/README.md +60 -0
  4. package/TRADEMARKS.md +52 -0
  5. package/dist/bin.d.ts +3 -0
  6. package/dist/bin.d.ts.map +1 -0
  7. package/dist/bin.js +9 -0
  8. package/dist/bin.js.map +1 -0
  9. package/dist/ci-policy-options.d.ts +15 -0
  10. package/dist/ci-policy-options.d.ts.map +1 -0
  11. package/dist/ci-policy-options.js +54 -0
  12. package/dist/ci-policy-options.js.map +1 -0
  13. package/dist/cli-progress.d.ts +16 -0
  14. package/dist/cli-progress.d.ts.map +1 -0
  15. package/dist/cli-progress.js +35 -0
  16. package/dist/cli-progress.js.map +1 -0
  17. package/dist/command-program.d.ts +7 -0
  18. package/dist/command-program.d.ts.map +1 -0
  19. package/dist/command-program.js +950 -0
  20. package/dist/command-program.js.map +1 -0
  21. package/dist/commands/audit-flow-output.d.ts +4 -0
  22. package/dist/commands/audit-flow-output.d.ts.map +1 -0
  23. package/dist/commands/audit-flow-output.js +119 -0
  24. package/dist/commands/audit-flow-output.js.map +1 -0
  25. package/dist/commands/audit-policy-output.d.ts +9 -0
  26. package/dist/commands/audit-policy-output.d.ts.map +1 -0
  27. package/dist/commands/audit-policy-output.js +95 -0
  28. package/dist/commands/audit-policy-output.js.map +1 -0
  29. package/dist/commands/audit.d.ts +15 -0
  30. package/dist/commands/audit.d.ts.map +1 -0
  31. package/dist/commands/audit.js +178 -0
  32. package/dist/commands/audit.js.map +1 -0
  33. package/dist/commands/baseline-config.d.ts +14 -0
  34. package/dist/commands/baseline-config.d.ts.map +1 -0
  35. package/dist/commands/baseline-config.js +33 -0
  36. package/dist/commands/baseline-config.js.map +1 -0
  37. package/dist/commands/baseline.d.ts +86 -0
  38. package/dist/commands/baseline.d.ts.map +1 -0
  39. package/dist/commands/baseline.js +392 -0
  40. package/dist/commands/baseline.js.map +1 -0
  41. package/dist/commands/classify.d.ts +30 -0
  42. package/dist/commands/classify.d.ts.map +1 -0
  43. package/dist/commands/classify.js +105 -0
  44. package/dist/commands/classify.js.map +1 -0
  45. package/dist/commands/detect.d.ts +12 -0
  46. package/dist/commands/detect.d.ts.map +1 -0
  47. package/dist/commands/detect.js +213 -0
  48. package/dist/commands/detect.js.map +1 -0
  49. package/dist/commands/doctor.d.ts +16 -0
  50. package/dist/commands/doctor.d.ts.map +1 -0
  51. package/dist/commands/doctor.js +404 -0
  52. package/dist/commands/doctor.js.map +1 -0
  53. package/dist/commands/findings.d.ts +45 -0
  54. package/dist/commands/findings.d.ts.map +1 -0
  55. package/dist/commands/findings.js +220 -0
  56. package/dist/commands/findings.js.map +1 -0
  57. package/dist/commands/flows.d.ts +30 -0
  58. package/dist/commands/flows.d.ts.map +1 -0
  59. package/dist/commands/flows.js +108 -0
  60. package/dist/commands/flows.js.map +1 -0
  61. package/dist/commands/init.d.ts +64 -0
  62. package/dist/commands/init.d.ts.map +1 -0
  63. package/dist/commands/init.js +293 -0
  64. package/dist/commands/init.js.map +1 -0
  65. package/dist/commands/profiles.d.ts +5 -0
  66. package/dist/commands/profiles.d.ts.map +1 -0
  67. package/dist/commands/profiles.js +39 -0
  68. package/dist/commands/profiles.js.map +1 -0
  69. package/dist/commands/report.d.ts +72 -0
  70. package/dist/commands/report.d.ts.map +1 -0
  71. package/dist/commands/report.js +284 -0
  72. package/dist/commands/report.js.map +1 -0
  73. package/dist/commands/results-loader.d.ts +15 -0
  74. package/dist/commands/results-loader.d.ts.map +1 -0
  75. package/dist/commands/results-loader.js +100 -0
  76. package/dist/commands/results-loader.js.map +1 -0
  77. package/dist/commands/routes.d.ts +35 -0
  78. package/dist/commands/routes.d.ts.map +1 -0
  79. package/dist/commands/routes.js +201 -0
  80. package/dist/commands/routes.js.map +1 -0
  81. package/dist/commands/unclassify.d.ts +22 -0
  82. package/dist/commands/unclassify.d.ts.map +1 -0
  83. package/dist/commands/unclassify.js +79 -0
  84. package/dist/commands/unclassify.js.map +1 -0
  85. package/dist/index.d.ts +11 -0
  86. package/dist/index.d.ts.map +1 -0
  87. package/dist/index.js +10 -0
  88. package/dist/index.js.map +1 -0
  89. package/dist/output.d.ts +9 -0
  90. package/dist/output.d.ts.map +1 -0
  91. package/dist/output.js +29 -0
  92. package/dist/output.js.map +1 -0
  93. package/dist/presentation/ansi.d.ts +12 -0
  94. package/dist/presentation/ansi.d.ts.map +1 -0
  95. package/dist/presentation/ansi.js +51 -0
  96. package/dist/presentation/ansi.js.map +1 -0
  97. package/dist/presentation/audit-presentation.d.ts +20 -0
  98. package/dist/presentation/audit-presentation.d.ts.map +1 -0
  99. package/dist/presentation/audit-presentation.js +409 -0
  100. package/dist/presentation/audit-presentation.js.map +1 -0
  101. package/dist/presentation/boundary.d.ts +5 -0
  102. package/dist/presentation/boundary.d.ts.map +1 -0
  103. package/dist/presentation/boundary.js +4 -0
  104. package/dist/presentation/boundary.js.map +1 -0
  105. package/dist/presentation/brand-header.d.ts +6 -0
  106. package/dist/presentation/brand-header.d.ts.map +1 -0
  107. package/dist/presentation/brand-header.js +18 -0
  108. package/dist/presentation/brand-header.js.map +1 -0
  109. package/dist/presentation/capabilities.d.ts +4 -0
  110. package/dist/presentation/capabilities.d.ts.map +1 -0
  111. package/dist/presentation/capabilities.js +25 -0
  112. package/dist/presentation/capabilities.js.map +1 -0
  113. package/dist/presentation/color.d.ts +13 -0
  114. package/dist/presentation/color.d.ts.map +1 -0
  115. package/dist/presentation/color.js +27 -0
  116. package/dist/presentation/color.js.map +1 -0
  117. package/dist/presentation/disclaimers.d.ts +3 -0
  118. package/dist/presentation/disclaimers.d.ts.map +1 -0
  119. package/dist/presentation/disclaimers.js +3 -0
  120. package/dist/presentation/disclaimers.js.map +1 -0
  121. package/dist/presentation/finding-groups.d.ts +14 -0
  122. package/dist/presentation/finding-groups.d.ts.map +1 -0
  123. package/dist/presentation/finding-groups.js +77 -0
  124. package/dist/presentation/finding-groups.js.map +1 -0
  125. package/dist/presentation/finding-source-report.d.ts +21 -0
  126. package/dist/presentation/finding-source-report.d.ts.map +1 -0
  127. package/dist/presentation/finding-source-report.js +134 -0
  128. package/dist/presentation/finding-source-report.js.map +1 -0
  129. package/dist/presentation/human-output.d.ts +4 -0
  130. package/dist/presentation/human-output.d.ts.map +1 -0
  131. package/dist/presentation/human-output.js +8 -0
  132. package/dist/presentation/human-output.js.map +1 -0
  133. package/dist/presentation/index.d.ts +15 -0
  134. package/dist/presentation/index.d.ts.map +1 -0
  135. package/dist/presentation/index.js +13 -0
  136. package/dist/presentation/index.js.map +1 -0
  137. package/dist/presentation/mode.d.ts +4 -0
  138. package/dist/presentation/mode.d.ts.map +1 -0
  139. package/dist/presentation/mode.js +8 -0
  140. package/dist/presentation/mode.js.map +1 -0
  141. package/dist/presentation/progress-mode.d.ts +20 -0
  142. package/dist/presentation/progress-mode.d.ts.map +1 -0
  143. package/dist/presentation/progress-mode.js +38 -0
  144. package/dist/presentation/progress-mode.js.map +1 -0
  145. package/dist/presentation/progress-reporter.d.ts +18 -0
  146. package/dist/presentation/progress-reporter.d.ts.map +1 -0
  147. package/dist/presentation/progress-reporter.js +236 -0
  148. package/dist/presentation/progress-reporter.js.map +1 -0
  149. package/dist/presentation/progress-signals.d.ts +2 -0
  150. package/dist/presentation/progress-signals.d.ts.map +1 -0
  151. package/dist/presentation/progress-signals.js +14 -0
  152. package/dist/presentation/progress-signals.js.map +1 -0
  153. package/dist/presentation/status.d.ts +11 -0
  154. package/dist/presentation/status.d.ts.map +1 -0
  155. package/dist/presentation/status.js +14 -0
  156. package/dist/presentation/status.js.map +1 -0
  157. package/dist/presentation/types.d.ts +23 -0
  158. package/dist/presentation/types.d.ts.map +1 -0
  159. package/dist/presentation/types.js +2 -0
  160. package/dist/presentation/types.js.map +1 -0
  161. package/dist/run-cli.d.ts +6 -0
  162. package/dist/run-cli.d.ts.map +1 -0
  163. package/dist/run-cli.js +15 -0
  164. package/dist/run-cli.js.map +1 -0
  165. package/package.json +69 -0
@@ -0,0 +1,12 @@
1
+ import type { ProjectDetectionResult, WorkspaceDetectionResult } from "@a11yst/types";
2
+ /**
3
+ * Run static detection for `options.cwd`. A thin pass-through to
4
+ * `@a11yst/detect` — no additional heuristics live here.
5
+ */
6
+ export declare function runDetect(options: {
7
+ cwd: string;
8
+ workspace?: boolean;
9
+ }): Promise<ProjectDetectionResult | WorkspaceDetectionResult>;
10
+ export declare function formatDetectHuman(result: ProjectDetectionResult | WorkspaceDetectionResult): string;
11
+ export declare function formatDetectJson(result: ProjectDetectionResult | WorkspaceDetectionResult): unknown;
12
+ //# sourceMappingURL=detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/commands/detect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAOV,sBAAsB,EACtB,wBAAwB,EACzB,MAAM,eAAe,CAAC;AAqBvB;;;GAGG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,GAAG,OAAO,CAAC,sBAAsB,GAAG,wBAAwB,CAAC,CAK7D;AAsFD,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,sBAAsB,GAAG,wBAAwB,GACxD,MAAM,CA4BR;AAmED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,sBAAsB,GAAG,wBAAwB,GACxD,OAAO,CA0BT"}
@@ -0,0 +1,213 @@
1
+ import { detectProject, detectWorkspace } from "@a11yst/detect";
2
+ import { productMetadata } from "@a11yst/types";
3
+ import { formatLabelValue } from "../output.js";
4
+ const EVIDENCE_TYPE_LABELS = {
5
+ dependency: "Dependency",
6
+ devDependency: "Dev dependency",
7
+ file: "File",
8
+ directory: "Directory",
9
+ "package-script": "Script",
10
+ configuration: "Configuration",
11
+ workspace: "Workspace",
12
+ fallback: "Fallback",
13
+ };
14
+ function isWorkspaceResult(result) {
15
+ return "projects" in result;
16
+ }
17
+ /**
18
+ * Run static detection for `options.cwd`. A thin pass-through to
19
+ * `@a11yst/detect` — no additional heuristics live here.
20
+ */
21
+ export async function runDetect(options) {
22
+ if (options.workspace) {
23
+ return detectWorkspace({ cwd: options.cwd });
24
+ }
25
+ return detectProject({ cwd: options.cwd });
26
+ }
27
+ function isAmbiguous(project) {
28
+ const framework = project.framework;
29
+ if (framework.diagnostics.some((d) => d.code === "FRAMEWORK_AMBIGUOUS")) {
30
+ return true;
31
+ }
32
+ return ((framework.confidence === "medium" || framework.confidence === "low") &&
33
+ framework.alternatives.length > 0);
34
+ }
35
+ function formatEvidenceLines(evidence) {
36
+ if (evidence.length === 0) {
37
+ return [];
38
+ }
39
+ return [
40
+ "Evidence",
41
+ ...evidence.map((item) => `- ${EVIDENCE_TYPE_LABELS[item.type]}: ${item.value}`),
42
+ ];
43
+ }
44
+ function formatDiagnosticsLines(diagnostics) {
45
+ if (diagnostics.length === 0) {
46
+ return [];
47
+ }
48
+ const lines = ["Diagnostics"];
49
+ for (const diagnostic of diagnostics) {
50
+ lines.push(`- [${diagnostic.code}] ${diagnostic.message}`);
51
+ if (diagnostic.hint) {
52
+ lines.push(` Hint: ${diagnostic.hint}`);
53
+ }
54
+ }
55
+ return lines;
56
+ }
57
+ function formatProjectLines(project) {
58
+ const framework = project.framework;
59
+ const ambiguous = isAmbiguous(project);
60
+ const bestDevServer = project.devServers[0];
61
+ const topAlternative = framework.alternatives[0];
62
+ const lines = [ambiguous ? "Framework detection is ambiguous." : "Project detection", ""];
63
+ lines.push(formatLabelValue("Root", project.relativeRoot));
64
+ lines.push(formatLabelValue("Platform", framework.platform));
65
+ if (ambiguous) {
66
+ lines.push(formatLabelValue("Selected", framework.framework));
67
+ if (topAlternative) {
68
+ lines.push(formatLabelValue("Alternative", topAlternative.framework));
69
+ }
70
+ }
71
+ else {
72
+ lines.push(formatLabelValue("Framework", framework.framework));
73
+ }
74
+ lines.push(formatLabelValue("Support", framework.supportLevel));
75
+ lines.push(formatLabelValue("Confidence", framework.confidence));
76
+ lines.push(formatLabelValue("Package mgr", project.packageManager.name));
77
+ if (bestDevServer?.command) {
78
+ lines.push(formatLabelValue("Dev command", bestDevServer.command));
79
+ }
80
+ if (bestDevServer?.inferredUrl) {
81
+ lines.push(formatLabelValue("URL", bestDevServer.inferredUrl));
82
+ if (bestDevServer.inferredUrlSource) {
83
+ lines.push(formatLabelValue("URL source", bestDevServer.inferredUrlSource));
84
+ }
85
+ }
86
+ const evidenceLines = formatEvidenceLines(framework.evidence);
87
+ if (evidenceLines.length > 0) {
88
+ lines.push("", ...evidenceLines);
89
+ }
90
+ const allDiagnostics = [
91
+ ...project.diagnostics,
92
+ ...framework.diagnostics,
93
+ ...project.packageManager.diagnostics,
94
+ ];
95
+ const diagnosticsLines = formatDiagnosticsLines(allDiagnostics);
96
+ if (diagnosticsLines.length > 0) {
97
+ lines.push("", ...diagnosticsLines);
98
+ }
99
+ return lines;
100
+ }
101
+ export function formatDetectHuman(result) {
102
+ if (!isWorkspaceResult(result)) {
103
+ return formatProjectLines(result.project).join("\n");
104
+ }
105
+ const lines = ["Workspace detection", ""];
106
+ lines.push(formatLabelValue("Root", result.workspaceRoot));
107
+ lines.push(formatLabelValue("Package mgr", result.packageManager.name));
108
+ lines.push(formatLabelValue("Projects", String(result.projects.length)));
109
+ if (result.projects.length === 0) {
110
+ lines.push("", "No auditable projects were found.");
111
+ }
112
+ else {
113
+ for (const project of result.projects) {
114
+ lines.push("");
115
+ lines.push(`- ${project.relativeRoot}`);
116
+ lines.push(` ${formatLabelValue("Platform", project.framework.platform, 12)}`);
117
+ lines.push(` ${formatLabelValue("Framework", project.framework.framework, 12)}`);
118
+ lines.push(` ${formatLabelValue("Confidence", project.framework.confidence, 12)}`);
119
+ }
120
+ }
121
+ const diagnosticsLines = formatDiagnosticsLines(result.diagnostics);
122
+ if (diagnosticsLines.length > 0) {
123
+ lines.push("", ...diagnosticsLines);
124
+ }
125
+ return lines.join("\n");
126
+ }
127
+ function serializeEvidence(evidence) {
128
+ return evidence.map((item) => ({
129
+ type: item.type,
130
+ value: item.value,
131
+ description: item.description,
132
+ weight: item.weight,
133
+ }));
134
+ }
135
+ function serializeDiagnostics(diagnostics) {
136
+ return diagnostics.map((diagnostic) => ({
137
+ code: diagnostic.code,
138
+ severity: diagnostic.severity,
139
+ message: diagnostic.message,
140
+ hint: diagnostic.hint,
141
+ path: diagnostic.path,
142
+ }));
143
+ }
144
+ function serializeFrameworkCandidate(candidate) {
145
+ return {
146
+ framework: candidate.framework,
147
+ score: candidate.score,
148
+ evidence: serializeEvidence(candidate.evidence),
149
+ };
150
+ }
151
+ function serializeDevServer(devServer) {
152
+ return {
153
+ command: devServer.command,
154
+ sourceScript: devServer.sourceScript,
155
+ confidence: devServer.confidence,
156
+ inferredPort: devServer.inferredPort,
157
+ inferredUrl: devServer.inferredUrl,
158
+ evidence: serializeEvidence(devServer.evidence),
159
+ };
160
+ }
161
+ function serializeProject(project) {
162
+ return {
163
+ name: project.name,
164
+ rootDir: project.rootDir,
165
+ relativeRoot: project.relativeRoot,
166
+ isLibrary: project.isLibrary,
167
+ framework: {
168
+ platform: project.framework.platform,
169
+ framework: project.framework.framework,
170
+ supportLevel: project.framework.supportLevel,
171
+ confidence: project.framework.confidence,
172
+ score: project.framework.score,
173
+ evidence: serializeEvidence(project.framework.evidence),
174
+ alternatives: project.framework.alternatives.map(serializeFrameworkCandidate),
175
+ diagnostics: serializeDiagnostics(project.framework.diagnostics),
176
+ },
177
+ packageManager: {
178
+ name: project.packageManager.name,
179
+ confidence: project.packageManager.confidence,
180
+ evidence: serializeEvidence(project.packageManager.evidence),
181
+ diagnostics: serializeDiagnostics(project.packageManager.diagnostics),
182
+ },
183
+ devServers: project.devServers.map(serializeDevServer),
184
+ diagnostics: serializeDiagnostics(project.diagnostics),
185
+ };
186
+ }
187
+ export function formatDetectJson(result) {
188
+ if (isWorkspaceResult(result)) {
189
+ return {
190
+ kind: "workspace",
191
+ product: productMetadata.name,
192
+ cwd: result.cwd,
193
+ workspaceRoot: result.workspaceRoot,
194
+ packageManager: {
195
+ name: result.packageManager.name,
196
+ confidence: result.packageManager.confidence,
197
+ evidence: serializeEvidence(result.packageManager.evidence),
198
+ diagnostics: serializeDiagnostics(result.packageManager.diagnostics),
199
+ },
200
+ projects: result.projects.map(serializeProject),
201
+ diagnostics: serializeDiagnostics(result.diagnostics),
202
+ };
203
+ }
204
+ return {
205
+ kind: "project",
206
+ product: productMetadata.name,
207
+ cwd: result.cwd,
208
+ rootDir: result.rootDir,
209
+ project: serializeProject(result.project),
210
+ diagnostics: serializeDiagnostics(result.diagnostics),
211
+ };
212
+ }
213
+ //# sourceMappingURL=detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/commands/detect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export type DoctorStatus = "ok" | "warn" | "fail";
2
+ export interface DoctorCheck {
3
+ id: string;
4
+ title: string;
5
+ status: DoctorStatus;
6
+ detail: string;
7
+ hint?: string;
8
+ }
9
+ export interface DoctorReport {
10
+ status: DoctorStatus;
11
+ checks: DoctorCheck[];
12
+ }
13
+ export declare function runDoctor(cwd: string): Promise<DoctorReport>;
14
+ export declare function formatDoctorHuman(report: DoctorReport): string;
15
+ export declare function formatDoctorJson(report: DoctorReport): unknown;
16
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAmBA,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;AAElD,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AA4UD,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAmGlE;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAkB9D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAM9D"}
@@ -0,0 +1,404 @@
1
+ import { accessSync, constants, existsSync, mkdirSync, rmSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join, resolve } from "node:path";
4
+ import { ConfigError, findConfigPath, loadConfig, resolveProjectPath, } from "@a11yst/config";
5
+ import { detectPackageManager, detectProject, detectWorkspace, readPackageJson } from "@a11yst/detect";
6
+ import { createAdapterContext, FIRST_CLASS_ADAPTERS, readAngularJson, resolveAdapter, } from "@a11yst/adapters";
7
+ import { productMetadata } from "@a11yst/types";
8
+ function worstStatus(statuses) {
9
+ if (statuses.includes("fail"))
10
+ return "fail";
11
+ if (statuses.includes("warn"))
12
+ return "warn";
13
+ return "ok";
14
+ }
15
+ function parseVersion(raw) {
16
+ return raw
17
+ .replace(/^v/, "")
18
+ .split(".")
19
+ .map((part) => Number.parseInt(part, 10) || 0);
20
+ }
21
+ function isNodeCompatible(current, minimum) {
22
+ const a = parseVersion(current);
23
+ const b = parseVersion(minimum);
24
+ for (let i = 0; i < Math.max(a.length, b.length); i += 1) {
25
+ const left = a[i] ?? 0;
26
+ const right = b[i] ?? 0;
27
+ if (left > right)
28
+ return true;
29
+ if (left < right)
30
+ return false;
31
+ }
32
+ return true;
33
+ }
34
+ /** Best-effort extraction of the package.json script name a dev command invokes. */
35
+ function extractScriptName(command) {
36
+ const trimmed = command.trim();
37
+ const runMatch = /^(?:npm|bun)\s+run\s+(\S+)/.exec(trimmed);
38
+ if (runMatch?.[1])
39
+ return runMatch[1];
40
+ const directMatch = /^(?:pnpm|yarn)\s+(\S+)/.exec(trimmed);
41
+ if (directMatch?.[1])
42
+ return directMatch[1];
43
+ const parts = trimmed.split(/\s+/).filter(Boolean);
44
+ return parts.length > 0 ? parts[parts.length - 1] : undefined;
45
+ }
46
+ function checkArtifactsWritable(cwd) {
47
+ const artifactsDir = join(cwd, ".a11yst");
48
+ const probe = join(artifactsDir, `.doctor-write-${process.pid}`);
49
+ try {
50
+ mkdirSync(artifactsDir, { recursive: true });
51
+ accessSync(artifactsDir, constants.W_OK);
52
+ // Touch and clean a probe file under the artifacts directory.
53
+ mkdirSync(probe, { recursive: true });
54
+ rmSync(probe, { recursive: true, force: true });
55
+ return {
56
+ id: "artifacts-writable",
57
+ title: "Artifacts directory",
58
+ status: "ok",
59
+ detail: `Writable artifacts directory available at ${artifactsDir}.`,
60
+ };
61
+ }
62
+ catch (error) {
63
+ // Fallback: try system temp to distinguish permission vs path issues
64
+ const tempProbe = join(tmpdir(), `a11yst-doctor-${process.pid}`);
65
+ try {
66
+ mkdirSync(tempProbe, { recursive: true });
67
+ rmSync(tempProbe, { recursive: true, force: true });
68
+ }
69
+ catch {
70
+ // ignore
71
+ }
72
+ return {
73
+ id: "artifacts-writable",
74
+ title: "Artifacts directory",
75
+ status: "fail",
76
+ detail: `Cannot write to ${artifactsDir}: ${error instanceof Error ? error.message : String(error)}`,
77
+ hint: `Ensure the project directory is writable so ${productMetadata.name} can store future reports.`,
78
+ };
79
+ }
80
+ }
81
+ function checkPackageManager(cwd) {
82
+ const manifest = readPackageJson(cwd);
83
+ const detection = detectPackageManager(cwd, manifest);
84
+ const unknown = detection.name === "unknown";
85
+ return {
86
+ id: "package-manager",
87
+ title: "Package manager",
88
+ status: unknown ? "warn" : "ok",
89
+ detail: unknown
90
+ ? "No lockfile or packageManager field detected."
91
+ : `Detected package manager: ${detection.name} (confidence: ${detection.confidence}).`,
92
+ hint: unknown ? "This is optional. A lockfile helps reproducible installs." : undefined,
93
+ };
94
+ }
95
+ async function checkProjectsAgainstDetection(config) {
96
+ const checks = [];
97
+ for (const project of config.projects) {
98
+ const rootAbs = resolveProjectPath(config.configDir, project.rootDir);
99
+ if (!existsSync(rootAbs)) {
100
+ checks.push({
101
+ id: `project-root:${project.name}`,
102
+ title: `Project root (${project.name})`,
103
+ status: "fail",
104
+ detail: `Configured rootDir "${project.rootDir}" for project "${project.name}" does not exist at ${rootAbs}.`,
105
+ hint: "Fix rootDir in the configuration or create the missing directory.",
106
+ });
107
+ continue;
108
+ }
109
+ checks.push({
110
+ id: `project-root:${project.name}`,
111
+ title: `Project root (${project.name})`,
112
+ status: "ok",
113
+ detail: `Root directory exists at ${rootAbs}.`,
114
+ });
115
+ const detection = await detectProject({ cwd: rootAbs });
116
+ const detectedFramework = detection.project.framework;
117
+ if (detectedFramework.platform !== "unknown" && detectedFramework.platform !== project.platform) {
118
+ checks.push({
119
+ id: `platform-match:${project.name}`,
120
+ title: `Platform match (${project.name})`,
121
+ status: "fail",
122
+ detail: `Project "${project.name}" is configured as "${project.platform}" but detection found "${detectedFramework.platform}".`,
123
+ hint: `Update platform to "${detectedFramework.platform}", or verify rootDir points at the intended project.`,
124
+ });
125
+ }
126
+ else {
127
+ checks.push({
128
+ id: `platform-match:${project.name}`,
129
+ title: `Platform match (${project.name})`,
130
+ status: "ok",
131
+ detail: `Configured platform "${project.platform}" agrees with detection.`,
132
+ });
133
+ }
134
+ if (detectedFramework.framework === "unknown") {
135
+ const configuredIsUnknown = project.framework === "unknown";
136
+ checks.push({
137
+ id: `framework-match:${project.name}`,
138
+ title: `Framework detection (${project.name})`,
139
+ status: configuredIsUnknown ? "ok" : "warn",
140
+ detail: configuredIsUnknown
141
+ ? `No framework signals detected for "${project.name}"; framework remains "unknown".`
142
+ : `Configured framework "${project.framework}" could not be verified: no recognizable framework signals were found at ${rootAbs}.`,
143
+ hint: configuredIsUnknown ? undefined : "Confirm the framework value manually.",
144
+ });
145
+ }
146
+ else if (detectedFramework.framework !== project.framework) {
147
+ checks.push({
148
+ id: `framework-match:${project.name}`,
149
+ title: `Framework detection (${project.name})`,
150
+ status: "warn",
151
+ detail: `Project "${project.name}" is configured with framework "${project.framework}" but detection found "${detectedFramework.framework}" (confidence: ${detectedFramework.confidence}).`,
152
+ hint: "Update the framework in the configuration if detection is correct.",
153
+ });
154
+ }
155
+ else {
156
+ checks.push({
157
+ id: `framework-match:${project.name}`,
158
+ title: `Framework detection (${project.name})`,
159
+ status: "ok",
160
+ detail: `Configured framework "${project.framework}" agrees with detection (confidence: ${detectedFramework.confidence}).`,
161
+ });
162
+ }
163
+ if (project.platform === "web" && project.devServer?.command) {
164
+ const scriptName = extractScriptName(project.devServer.command);
165
+ const manifest = readPackageJson(rootAbs);
166
+ const scripts = manifest?.scripts ?? {};
167
+ const hasScript = scriptName !== undefined && Object.hasOwn(scripts, scriptName);
168
+ checks.push({
169
+ id: `dev-server-script:${project.name}`,
170
+ title: `Dev server script (${project.name})`,
171
+ status: hasScript ? "ok" : "warn",
172
+ detail: hasScript
173
+ ? `Script "${scriptName}" referenced by devServer.command exists in package.json.`
174
+ : `Could not find a package.json script matching devServer.command "${project.devServer.command}" at ${rootAbs}.`,
175
+ hint: hasScript ? undefined : "Verify devServer.command matches an existing package.json script.",
176
+ });
177
+ }
178
+ }
179
+ return checks;
180
+ }
181
+ const META_FRAMEWORK_PAIRS = [
182
+ { detected: "next", misconfigured: "react", label: "Next.js detected but configured as React" },
183
+ { detected: "nuxt", misconfigured: "vue", label: "Nuxt detected but configured as Vue" },
184
+ ];
185
+ const FIRST_CLASS_FRAMEWORKS = new Set(FIRST_CLASS_ADAPTERS.map((adapter) => adapter.framework));
186
+ async function checkAdapterIntegration(config, project) {
187
+ const checks = [];
188
+ const rootAbs = resolveProjectPath(config.configDir, project.rootDir);
189
+ const detection = await detectProject({ cwd: rootAbs });
190
+ const detectedFramework = detection.project.framework.framework;
191
+ for (const pair of META_FRAMEWORK_PAIRS) {
192
+ if (detectedFramework === pair.detected &&
193
+ project.framework === pair.misconfigured) {
194
+ checks.push({
195
+ id: `adapter-meta-framework:${project.name}`,
196
+ title: `Adapter mismatch (${project.name})`,
197
+ status: "warn",
198
+ detail: `${pair.label}. Use framework "${pair.detected}" for dedicated route discovery and readiness.`,
199
+ hint: `Update framework to "${pair.detected}" in the configuration.`,
200
+ });
201
+ }
202
+ }
203
+ if (project.adapterId === "generic-web" &&
204
+ detectedFramework !== "unknown" &&
205
+ FIRST_CLASS_FRAMEWORKS.has(detectedFramework)) {
206
+ checks.push({
207
+ id: `adapter-generic-web:${project.name}`,
208
+ title: `Adapter selection (${project.name})`,
209
+ status: "warn",
210
+ detail: `Project "${project.name}" resolves to the generic-web adapter but detection found first-class framework "${detectedFramework}".`,
211
+ hint: `Set framework to "${detectedFramework}" for adapter-specific route discovery and readiness.`,
212
+ });
213
+ }
214
+ else if (project.adapterId === "generic-web" &&
215
+ !FIRST_CLASS_FRAMEWORKS.has(project.framework)) {
216
+ checks.push({
217
+ id: `adapter-generic-web:${project.name}`,
218
+ title: `Adapter selection (${project.name})`,
219
+ status: "ok",
220
+ detail: `Framework "${project.framework}" uses the generic-web adapter (support varies by framework).`,
221
+ });
222
+ }
223
+ const adapter = resolveAdapter({ framework: project.framework, platform: project.platform }) ??
224
+ resolveAdapter({ framework: "unknown", platform: "web" });
225
+ if (adapter) {
226
+ const context = createAdapterContext(rootAbs, config.configDir, project);
227
+ const discovery = await adapter.discoverRoutes(context);
228
+ const adapterDiagnostics = await adapter.getDiagnostics(context);
229
+ for (const diagnostic of [...discovery.diagnostics, ...adapterDiagnostics]) {
230
+ checks.push({
231
+ id: `adapter-diagnostic:${project.name}:${diagnostic.code}`,
232
+ title: `Adapter diagnostic (${project.name})`,
233
+ status: diagnostic.severity === "error"
234
+ ? "fail"
235
+ : diagnostic.severity === "warning"
236
+ ? "warn"
237
+ : "ok",
238
+ detail: diagnostic.message,
239
+ hint: diagnostic.hint,
240
+ });
241
+ }
242
+ const samples = project.routeDiscovery.samples;
243
+ for (const skipped of discovery.skippedPatterns) {
244
+ const samplePaths = samples[skipped.pattern];
245
+ if (!samplePaths || samplePaths.length === 0) {
246
+ checks.push({
247
+ id: `adapter-dynamic-samples:${project.name}:${skipped.pattern}`,
248
+ title: `Dynamic route samples (${project.name})`,
249
+ status: "warn",
250
+ detail: `Dynamic pattern "${skipped.pattern}" has no samples configured.`,
251
+ hint: 'Add sample paths under routeDiscovery.samples or list explicit routes.',
252
+ });
253
+ }
254
+ }
255
+ }
256
+ if (project.framework === "angular" || detectedFramework === "angular") {
257
+ const angularJson = readAngularJson(rootAbs);
258
+ const projectNames = angularJson?.projects
259
+ ? Object.keys(angularJson.projects)
260
+ : [];
261
+ if (projectNames.length > 1 && !angularJson?.defaultProject) {
262
+ checks.push({
263
+ id: `adapter-angular-workspace:${project.name}`,
264
+ title: `Angular workspace (${project.name})`,
265
+ status: "warn",
266
+ detail: `angular.json defines ${projectNames.length} projects without defaultProject.`,
267
+ hint: "Set defaultProject in angular.json or list routes explicitly in a11yst.config.ts.",
268
+ });
269
+ }
270
+ }
271
+ return checks;
272
+ }
273
+ async function checkWorkspaceCoverage(cwd, config) {
274
+ const workspace = await detectWorkspace({ cwd });
275
+ const isRealWorkspace = !workspace.diagnostics.some((d) => d.code === "WORKSPACE_CONFIG_NOT_FOUND");
276
+ if (!isRealWorkspace || workspace.projects.length <= config.projects.length) {
277
+ return undefined;
278
+ }
279
+ const configuredRoots = new Set(config.projects.map((project) => resolve(resolveProjectPath(config.configDir, project.rootDir))));
280
+ const unconfigured = workspace.projects.filter((project) => !configuredRoots.has(resolve(project.rootDir)));
281
+ if (unconfigured.length === 0) {
282
+ return undefined;
283
+ }
284
+ return {
285
+ id: "workspace-coverage",
286
+ title: "Workspace coverage",
287
+ status: "warn",
288
+ detail: `Workspace has ${workspace.projects.length} detected app(s) but only ${config.projects.length} configured. Unconfigured: ${unconfigured
289
+ .map((project) => project.relativeRoot)
290
+ .join(", ")}.`,
291
+ hint: "Add these projects to the configuration if they should be audited, or ignore this if intentional.",
292
+ };
293
+ }
294
+ export async function runDoctor(cwd) {
295
+ const checks = [];
296
+ const nodeOk = isNodeCompatible(process.versions.node, productMetadata.minNodeVersion);
297
+ checks.push({
298
+ id: "node-version",
299
+ title: "Node.js version",
300
+ status: nodeOk ? "ok" : "fail",
301
+ detail: nodeOk
302
+ ? `Node.js ${process.versions.node} satisfies minimum ${productMetadata.minNodeVersion}.`
303
+ : `Node.js ${process.versions.node} is below minimum ${productMetadata.minNodeVersion}.`,
304
+ hint: nodeOk
305
+ ? undefined
306
+ : `Upgrade Node.js to ${productMetadata.minNodeVersion} or newer.`,
307
+ });
308
+ const configPath = findConfigPath(cwd);
309
+ let config;
310
+ if (!configPath) {
311
+ checks.push({
312
+ id: "config-exists",
313
+ title: "Configuration file",
314
+ status: "fail",
315
+ detail: `No ${productMetadata.command}.config.* found from ${cwd}.`,
316
+ hint: `Run \`${productMetadata.command} init\` to create a starter configuration.`,
317
+ });
318
+ }
319
+ else {
320
+ checks.push({
321
+ id: "config-exists",
322
+ title: "Configuration file",
323
+ status: "ok",
324
+ detail: `Found ${configPath}.`,
325
+ });
326
+ try {
327
+ config = await loadConfig({ cwd, configPath });
328
+ checks.push({
329
+ id: "config-valid",
330
+ title: "Configuration validity",
331
+ status: "ok",
332
+ detail: `Configuration is valid (${config.projects.length} project(s)).`,
333
+ });
334
+ }
335
+ catch (error) {
336
+ const detail = error instanceof ConfigError
337
+ ? error.format()
338
+ : error instanceof Error
339
+ ? error.message
340
+ : String(error);
341
+ checks.push({
342
+ id: "config-valid",
343
+ title: "Configuration validity",
344
+ status: "fail",
345
+ detail,
346
+ hint: error instanceof ConfigError
347
+ ? error.hint
348
+ : "Fix validation errors in the configuration file.",
349
+ });
350
+ }
351
+ }
352
+ checks.push(checkArtifactsWritable(cwd));
353
+ checks.push(checkPackageManager(cwd));
354
+ if (config) {
355
+ checks.push(...(await checkProjectsAgainstDetection(config)));
356
+ for (const project of config.projects) {
357
+ if (project.platform === "web") {
358
+ checks.push(...(await checkAdapterIntegration(config, project)));
359
+ }
360
+ }
361
+ for (const [index, diagnostic] of config.diagnostics.entries()) {
362
+ checks.push({
363
+ id: `config-diagnostic:${diagnostic.code}:${index}`,
364
+ title: `Configuration diagnostic (${diagnostic.code})`,
365
+ status: diagnostic.severity === "error" ? "fail" : diagnostic.severity === "warning" ? "warn" : "ok",
366
+ detail: diagnostic.message,
367
+ hint: diagnostic.hint,
368
+ });
369
+ }
370
+ const workspaceCheck = await checkWorkspaceCoverage(cwd, config);
371
+ if (workspaceCheck) {
372
+ checks.push(workspaceCheck);
373
+ }
374
+ }
375
+ return {
376
+ status: worstStatus(checks.map((check) => check.status)),
377
+ checks,
378
+ };
379
+ }
380
+ export function formatDoctorHuman(report) {
381
+ const lines = [
382
+ "Environment check",
383
+ "",
384
+ `Overall status: ${report.status.toUpperCase()}`,
385
+ "",
386
+ ];
387
+ for (const check of report.checks) {
388
+ lines.push(`[${check.status.toUpperCase()}] ${check.title}`);
389
+ lines.push(` ${check.detail}`);
390
+ if (check.hint) {
391
+ lines.push(` Hint: ${check.hint}`);
392
+ }
393
+ lines.push("");
394
+ }
395
+ return lines.join("\n").trimEnd();
396
+ }
397
+ export function formatDoctorJson(report) {
398
+ return {
399
+ status: report.status,
400
+ product: productMetadata.name,
401
+ checks: report.checks,
402
+ };
403
+ }
404
+ //# sourceMappingURL=doctor.js.map