@ankhorage/doctor 0.2.0 → 0.2.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - d514f5f: Trigger release
8
+
3
9
  ## 0.2.0
4
10
 
5
11
  ### Minor Changes
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # DOCTOR
5
5
 
6
- ![license: MIT](././paradox/badges/license.svg) ![npm: v0.1.0](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
6
+ ![license: MIT](././paradox/badges/license.svg) ![npm: v0.2.0](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
7
7
 
8
8
  Executable doctor provider and standalone CLI for lightweight Ankhorage repo and package compliance diagnostics.
9
9
 
@@ -1,6 +1,6 @@
1
- import type { DoctorDiagnostic } from "./diagnostics.js";
2
- export type DoctorTargetCheck = "package" | "repo";
3
- export type DoctorTargetMode = "fix" | "package" | "repo" | "validate";
1
+ import type { DoctorDiagnostic } from './diagnostics.js';
2
+ export type DoctorTargetCheck = 'package' | 'repo';
3
+ export type DoctorTargetMode = 'fix' | 'package' | 'repo' | 'validate';
4
4
  export interface DoctorAnalysisRequest {
5
5
  readonly cwd: string;
6
6
  readonly inputPath?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"analysis.d.ts","sourceRoot":"","sources":["../src/analysis.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,MAAM,CAAC;AACnD,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,CAAC;AAEvE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;CACjC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,aAAa,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACrD,QAAQ,CAAC,WAAW,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAClD,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAcD,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CA6G/B"}
1
+ {"version":3,"file":"analysis.d.ts","sourceRoot":"","sources":["../src/analysis.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,MAAM,CAAC;AACnD,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,CAAC;AAEvE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;CACjC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,aAAa,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACrD,QAAQ,CAAC,WAAW,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAClD,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAcD,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAgH/B"}
package/dist/analysis.js CHANGED
@@ -1,24 +1,24 @@
1
- import { promises as fs } from "node:fs";
2
- import path from "node:path";
1
+ import { promises as fs } from 'node:fs';
2
+ import path from 'node:path';
3
3
  const REPO_MARKERS = [
4
- { label: ".git", relativePath: ".git" },
5
- { label: ".github/workflows", relativePath: path.join(".github", "workflows") },
6
- { label: ".changeset", relativePath: ".changeset" },
7
- { label: "package.json", relativePath: "package.json" },
8
- { label: "pnpm-workspace.yaml", relativePath: "pnpm-workspace.yaml" },
9
- { label: "bun.lock", relativePath: "bun.lock" },
10
- { label: "bun.lockb", relativePath: "bun.lockb" },
11
- { label: "package-lock.json", relativePath: "package-lock.json" },
12
- { label: "yarn.lock", relativePath: "yarn.lock" },
4
+ { label: '.git', relativePath: '.git' },
5
+ { label: '.github/workflows', relativePath: path.join('.github', 'workflows') },
6
+ { label: '.changeset', relativePath: '.changeset' },
7
+ { label: 'package.json', relativePath: 'package.json' },
8
+ { label: 'pnpm-workspace.yaml', relativePath: 'pnpm-workspace.yaml' },
9
+ { label: 'bun.lock', relativePath: 'bun.lock' },
10
+ { label: 'bun.lockb', relativePath: 'bun.lockb' },
11
+ { label: 'package-lock.json', relativePath: 'package-lock.json' },
12
+ { label: 'yarn.lock', relativePath: 'yarn.lock' },
13
13
  ];
14
14
  export async function analyzeDoctorTarget(request) {
15
- const targetPath = path.resolve(request.cwd, request.inputPath ?? ".");
15
+ const targetPath = path.resolve(request.cwd, request.inputPath ?? '.');
16
16
  const stats = await statOrNull(targetPath);
17
17
  if (stats === null) {
18
18
  return {
19
19
  appliedChecks: [],
20
20
  diagnostics: [
21
- createDiagnostic("error", "target-not-found", targetPath, `Target path does not exist: ${targetPath}`),
21
+ createDiagnostic('error', 'target-not-found', targetPath, `Target path does not exist: ${targetPath}`),
22
22
  ],
23
23
  hasPackageJson: false,
24
24
  repoMarkers: [],
@@ -29,41 +29,39 @@ export async function analyzeDoctorTarget(request) {
29
29
  return {
30
30
  appliedChecks: [],
31
31
  diagnostics: [
32
- createDiagnostic("error", "target-not-directory", targetPath, `Target path must be a directory: ${targetPath}`),
32
+ createDiagnostic('error', 'target-not-directory', targetPath, `Target path must be a directory: ${targetPath}`),
33
33
  ],
34
34
  hasPackageJson: false,
35
35
  repoMarkers: [],
36
36
  targetPath,
37
37
  };
38
38
  }
39
- const repoMarkers = (await Promise.all(REPO_MARKERS.map(async (marker) => (await pathExists(path.join(targetPath, marker.relativePath)))
40
- ? marker.label
41
- : null))).filter((marker) => marker !== null);
42
- const packageJsonPath = path.join(targetPath, "package.json");
43
- const hasPackageJson = repoMarkers.includes("package.json");
39
+ const repoMarkers = (await Promise.all(REPO_MARKERS.map(async (marker) => (await pathExists(path.join(targetPath, marker.relativePath))) ? marker.label : null))).filter((marker) => marker !== null);
40
+ const packageJsonPath = path.join(targetPath, 'package.json');
41
+ const hasPackageJson = repoMarkers.includes('package.json');
44
42
  const appliedChecks = [];
45
43
  const diagnostics = [];
46
- const shouldRunRepoChecks = request.mode === "repo" ||
47
- ((request.mode === "validate" || request.mode === "fix") && repoMarkers.length > 0);
48
- const shouldRunPackageChecks = request.mode === "package" ||
49
- ((request.mode === "validate" || request.mode === "fix") && hasPackageJson);
50
- if (request.mode === "repo" && repoMarkers.length === 0) {
51
- diagnostics.push(createDiagnostic("error", "repo-markers-missing", targetPath, "Target is not a repo/workspace-root candidate because no repo markers were found."));
44
+ const shouldRunRepoChecks = request.mode === 'repo' ||
45
+ ((request.mode === 'validate' || request.mode === 'fix') && repoMarkers.length > 0);
46
+ const shouldRunPackageChecks = request.mode === 'package' ||
47
+ ((request.mode === 'validate' || request.mode === 'fix') && hasPackageJson);
48
+ if (request.mode === 'repo' && repoMarkers.length === 0) {
49
+ diagnostics.push(createDiagnostic('error', 'repo-markers-missing', targetPath, 'Target is not a repo/workspace-root candidate because no repo markers were found.'));
52
50
  }
53
- if (request.mode === "package" && !hasPackageJson) {
54
- diagnostics.push(createDiagnostic("error", "package-json-missing", packageJsonPath, "Target does not contain a readable package.json file."));
51
+ if (request.mode === 'package' && !hasPackageJson) {
52
+ diagnostics.push(createDiagnostic('error', 'package-json-missing', packageJsonPath, 'Target does not contain a readable package.json file.'));
55
53
  }
56
- if ((request.mode === "validate" || request.mode === "fix") &&
54
+ if ((request.mode === 'validate' || request.mode === 'fix') &&
57
55
  repoMarkers.length === 0 &&
58
56
  !hasPackageJson) {
59
- diagnostics.push(createDiagnostic("error", "unsupported-target", targetPath, "Target is neither a repo/workspace-root candidate nor a package root."));
57
+ diagnostics.push(createDiagnostic('error', 'unsupported-target', targetPath, 'Target is neither a repo/workspace-root candidate nor a package root.'));
60
58
  }
61
59
  if (shouldRunRepoChecks && repoMarkers.length > 0) {
62
- appliedChecks.push("repo");
60
+ appliedChecks.push('repo');
63
61
  diagnostics.push(...(await analyzeRepoLight(targetPath)));
64
62
  }
65
63
  if (shouldRunPackageChecks && hasPackageJson) {
66
- appliedChecks.push("package");
64
+ appliedChecks.push('package');
67
65
  diagnostics.push(...(await analyzePackageLight(targetPath, packageJsonPath)));
68
66
  }
69
67
  return {
@@ -76,40 +74,40 @@ export async function analyzeDoctorTarget(request) {
76
74
  }
77
75
  async function analyzeRepoLight(targetPath) {
78
76
  const diagnostics = [];
79
- await maybeWarnForMissingPath(diagnostics, targetPath, "README.md", "missing-readme");
80
- await maybeWarnForMissingPath(diagnostics, targetPath, "CHANGELOG.md", "missing-changelog");
81
- await maybeWarnForMissingPath(diagnostics, targetPath, "LICENSE", "missing-license");
82
- await maybeWarnForMissingPath(diagnostics, targetPath, ".changeset", "missing-changeset-directory");
83
- await maybeWarnForMissingPath(diagnostics, targetPath, path.join(".github", "workflows"), "missing-workflows-directory");
77
+ await maybeWarnForMissingPath(diagnostics, targetPath, 'README.md', 'missing-readme');
78
+ await maybeWarnForMissingPath(diagnostics, targetPath, 'CHANGELOG.md', 'missing-changelog');
79
+ await maybeWarnForMissingPath(diagnostics, targetPath, 'LICENSE', 'missing-license');
80
+ await maybeWarnForMissingPath(diagnostics, targetPath, '.changeset', 'missing-changeset-directory');
81
+ await maybeWarnForMissingPath(diagnostics, targetPath, path.join('.github', 'workflows'), 'missing-workflows-directory');
84
82
  return diagnostics;
85
83
  }
86
84
  async function analyzePackageLight(targetPath, packageJsonPath) {
87
85
  const diagnostics = [];
88
86
  let parsed;
89
87
  try {
90
- parsed = JSON.parse(await fs.readFile(packageJsonPath, "utf8"));
88
+ parsed = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
91
89
  }
92
90
  catch (error) {
93
- diagnostics.push(createDiagnostic("error", "invalid-package-json", packageJsonPath, createInvalidPackageJsonMessage(error)));
91
+ diagnostics.push(createDiagnostic('error', 'invalid-package-json', packageJsonPath, createInvalidPackageJsonMessage(error)));
94
92
  return diagnostics;
95
93
  }
96
94
  if (!isRecord(parsed)) {
97
- diagnostics.push(createDiagnostic("error", "invalid-package-json", packageJsonPath, "package.json must contain a JSON object."));
95
+ diagnostics.push(createDiagnostic('error', 'invalid-package-json', packageJsonPath, 'package.json must contain a JSON object.'));
98
96
  return diagnostics;
99
97
  }
100
98
  if (!isNonEmptyString(parsed.name)) {
101
- diagnostics.push(createDiagnostic("error", "package-name-missing", packageJsonPath, 'package.json must define a non-empty "name" field.'));
99
+ diagnostics.push(createDiagnostic('error', 'package-name-missing', packageJsonPath, 'package.json must define a non-empty "name" field.'));
102
100
  }
103
101
  if (!isNonEmptyString(parsed.version)) {
104
- diagnostics.push(createDiagnostic("error", "package-version-missing", packageJsonPath, 'package.json must define a non-empty "version" field.'));
102
+ diagnostics.push(createDiagnostic('error', 'package-version-missing', packageJsonPath, 'package.json must define a non-empty "version" field.'));
105
103
  }
106
104
  if (!isNonEmptyString(parsed.type)) {
107
- diagnostics.push(createDiagnostic("error", "package-type-missing", packageJsonPath, 'package.json must define a non-empty "type" field.'));
105
+ diagnostics.push(createDiagnostic('error', 'package-type-missing', packageJsonPath, 'package.json must define a non-empty "type" field.'));
108
106
  }
109
- if ("ankh" in parsed) {
107
+ if ('ankh' in parsed) {
110
108
  const validationError = validateAnkhMetadataShape(parsed.ankh);
111
109
  if (validationError !== null) {
112
- diagnostics.push(createDiagnostic("error", "invalid-ankh-metadata", targetPath, validationError));
110
+ diagnostics.push(createDiagnostic('error', 'invalid-ankh-metadata', targetPath, validationError));
113
111
  }
114
112
  }
115
113
  return diagnostics;
@@ -119,7 +117,7 @@ async function maybeWarnForMissingPath(diagnostics, rootPath, relativePath, code
119
117
  if (await pathExists(absolutePath)) {
120
118
  return;
121
119
  }
122
- diagnostics.push(createDiagnostic("warning", code, absolutePath, `Missing expected repo artifact: ${relativePath}`));
120
+ diagnostics.push(createDiagnostic('warning', code, absolutePath, `Missing expected repo artifact: ${relativePath}`));
123
121
  }
124
122
  function validateAnkhMetadataShape(value) {
125
123
  if (!isRecord(value)) {
@@ -165,17 +163,17 @@ async function statOrNull(targetPath) {
165
163
  }
166
164
  function isMissingPathError(error) {
167
165
  return (error instanceof Error &&
168
- "code" in error &&
169
- typeof error.code === "string" &&
170
- error.code === "ENOENT");
166
+ 'code' in error &&
167
+ typeof error.code === 'string' &&
168
+ error.code === 'ENOENT');
171
169
  }
172
170
  function isNonEmptyString(value) {
173
- return typeof value === "string" && value.trim() !== "";
171
+ return typeof value === 'string' && value.trim() !== '';
174
172
  }
175
173
  function isPackageRelativeProviderPath(value) {
176
- return isNonEmptyString(value) && value.startsWith("./");
174
+ return isNonEmptyString(value) && value.startsWith('./');
177
175
  }
178
176
  function isRecord(value) {
179
- return typeof value === "object" && value !== null && !Array.isArray(value);
177
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
180
178
  }
181
179
  //# sourceMappingURL=analysis.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"analysis.js","sourceRoot":"","sources":["../src/analysis.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\n\nimport type { DoctorDiagnostic } from \"./diagnostics.js\";\n\nexport type DoctorTargetCheck = \"package\" | \"repo\";\nexport type DoctorTargetMode = \"fix\" | \"package\" | \"repo\" | \"validate\";\n\nexport interface DoctorAnalysisRequest {\n readonly cwd: string;\n readonly inputPath?: string;\n readonly mode: DoctorTargetMode;\n}\n\nexport interface DoctorAnalysisResult {\n readonly appliedChecks: readonly DoctorTargetCheck[];\n readonly diagnostics: readonly DoctorDiagnostic[];\n readonly hasPackageJson: boolean;\n readonly repoMarkers: readonly string[];\n readonly targetPath: string;\n}\n\nconst REPO_MARKERS = [\n { label: \".git\", relativePath: \".git\" },\n { label: \".github/workflows\", relativePath: path.join(\".github\", \"workflows\") },\n { label: \".changeset\", relativePath: \".changeset\" },\n { label: \"package.json\", relativePath: \"package.json\" },\n { label: \"pnpm-workspace.yaml\", relativePath: \"pnpm-workspace.yaml\" },\n { label: \"bun.lock\", relativePath: \"bun.lock\" },\n { label: \"bun.lockb\", relativePath: \"bun.lockb\" },\n { label: \"package-lock.json\", relativePath: \"package-lock.json\" },\n { label: \"yarn.lock\", relativePath: \"yarn.lock\" },\n] as const;\n\nexport async function analyzeDoctorTarget(\n request: DoctorAnalysisRequest,\n): Promise<DoctorAnalysisResult> {\n const targetPath = path.resolve(request.cwd, request.inputPath ?? \".\");\n const stats = await statOrNull(targetPath);\n\n if (stats === null) {\n return {\n appliedChecks: [],\n diagnostics: [\n createDiagnostic(\"error\", \"target-not-found\", targetPath, `Target path does not exist: ${targetPath}`),\n ],\n hasPackageJson: false,\n repoMarkers: [],\n targetPath,\n };\n }\n\n if (!stats.isDirectory()) {\n return {\n appliedChecks: [],\n diagnostics: [\n createDiagnostic(\n \"error\",\n \"target-not-directory\",\n targetPath,\n `Target path must be a directory: ${targetPath}`,\n ),\n ],\n hasPackageJson: false,\n repoMarkers: [],\n targetPath,\n };\n }\n\n const repoMarkers = (\n await Promise.all(\n REPO_MARKERS.map(async (marker) =>\n (await pathExists(path.join(targetPath, marker.relativePath)))\n ? marker.label\n : null,\n ),\n )\n ).filter((marker): marker is (typeof REPO_MARKERS)[number][\"label\"] => marker !== null);\n\n const packageJsonPath = path.join(targetPath, \"package.json\");\n const hasPackageJson = repoMarkers.includes(\"package.json\");\n const appliedChecks: DoctorTargetCheck[] = [];\n const diagnostics: DoctorDiagnostic[] = [];\n\n const shouldRunRepoChecks =\n request.mode === \"repo\" ||\n ((request.mode === \"validate\" || request.mode === \"fix\") && repoMarkers.length > 0);\n const shouldRunPackageChecks =\n request.mode === \"package\" ||\n ((request.mode === \"validate\" || request.mode === \"fix\") && hasPackageJson);\n\n if (request.mode === \"repo\" && repoMarkers.length === 0) {\n diagnostics.push(\n createDiagnostic(\n \"error\",\n \"repo-markers-missing\",\n targetPath,\n \"Target is not a repo/workspace-root candidate because no repo markers were found.\",\n ),\n );\n }\n\n if (request.mode === \"package\" && !hasPackageJson) {\n diagnostics.push(\n createDiagnostic(\n \"error\",\n \"package-json-missing\",\n packageJsonPath,\n \"Target does not contain a readable package.json file.\",\n ),\n );\n }\n\n if (\n (request.mode === \"validate\" || request.mode === \"fix\") &&\n repoMarkers.length === 0 &&\n !hasPackageJson\n ) {\n diagnostics.push(\n createDiagnostic(\n \"error\",\n \"unsupported-target\",\n targetPath,\n \"Target is neither a repo/workspace-root candidate nor a package root.\",\n ),\n );\n }\n\n if (shouldRunRepoChecks && repoMarkers.length > 0) {\n appliedChecks.push(\"repo\");\n diagnostics.push(...(await analyzeRepoLight(targetPath)));\n }\n\n if (shouldRunPackageChecks && hasPackageJson) {\n appliedChecks.push(\"package\");\n diagnostics.push(...(await analyzePackageLight(targetPath, packageJsonPath)));\n }\n\n return {\n appliedChecks,\n diagnostics,\n hasPackageJson,\n repoMarkers,\n targetPath,\n };\n}\n\nasync function analyzeRepoLight(targetPath: string): Promise<DoctorDiagnostic[]> {\n const diagnostics: DoctorDiagnostic[] = [];\n\n await maybeWarnForMissingPath(diagnostics, targetPath, \"README.md\", \"missing-readme\");\n await maybeWarnForMissingPath(\n diagnostics,\n targetPath,\n \"CHANGELOG.md\",\n \"missing-changelog\",\n );\n await maybeWarnForMissingPath(diagnostics, targetPath, \"LICENSE\", \"missing-license\");\n await maybeWarnForMissingPath(\n diagnostics,\n targetPath,\n \".changeset\",\n \"missing-changeset-directory\",\n );\n await maybeWarnForMissingPath(\n diagnostics,\n targetPath,\n path.join(\".github\", \"workflows\"),\n \"missing-workflows-directory\",\n );\n\n return diagnostics;\n}\n\nasync function analyzePackageLight(\n targetPath: string,\n packageJsonPath: string,\n): Promise<DoctorDiagnostic[]> {\n const diagnostics: DoctorDiagnostic[] = [];\n let parsed: unknown;\n\n try {\n parsed = JSON.parse(await fs.readFile(packageJsonPath, \"utf8\")) as unknown;\n } catch (error) {\n diagnostics.push(\n createDiagnostic(\n \"error\",\n \"invalid-package-json\",\n packageJsonPath,\n createInvalidPackageJsonMessage(error),\n ),\n );\n return diagnostics;\n }\n\n if (!isRecord(parsed)) {\n diagnostics.push(\n createDiagnostic(\n \"error\",\n \"invalid-package-json\",\n packageJsonPath,\n \"package.json must contain a JSON object.\",\n ),\n );\n return diagnostics;\n }\n\n if (!isNonEmptyString(parsed.name)) {\n diagnostics.push(\n createDiagnostic(\n \"error\",\n \"package-name-missing\",\n packageJsonPath,\n 'package.json must define a non-empty \"name\" field.',\n ),\n );\n }\n\n if (!isNonEmptyString(parsed.version)) {\n diagnostics.push(\n createDiagnostic(\n \"error\",\n \"package-version-missing\",\n packageJsonPath,\n 'package.json must define a non-empty \"version\" field.',\n ),\n );\n }\n\n if (!isNonEmptyString(parsed.type)) {\n diagnostics.push(\n createDiagnostic(\n \"error\",\n \"package-type-missing\",\n packageJsonPath,\n 'package.json must define a non-empty \"type\" field.',\n ),\n );\n }\n\n if (\"ankh\" in parsed) {\n const validationError = validateAnkhMetadataShape(parsed.ankh);\n if (validationError !== null) {\n diagnostics.push(\n createDiagnostic(\"error\", \"invalid-ankh-metadata\", targetPath, validationError),\n );\n }\n }\n\n return diagnostics;\n}\n\nasync function maybeWarnForMissingPath(\n diagnostics: DoctorDiagnostic[],\n rootPath: string,\n relativePath: string,\n code:\n | \"missing-changelog\"\n | \"missing-changeset-directory\"\n | \"missing-license\"\n | \"missing-readme\"\n | \"missing-workflows-directory\",\n): Promise<void> {\n const absolutePath = path.join(rootPath, relativePath);\n if (await pathExists(absolutePath)) {\n return;\n }\n\n diagnostics.push(\n createDiagnostic(\n \"warning\",\n code,\n absolutePath,\n `Missing expected repo artifact: ${relativePath}`,\n ),\n );\n}\n\nfunction validateAnkhMetadataShape(value: unknown): string | null {\n if (!isRecord(value)) {\n return 'package.json \"ankh\" metadata must be an object when present.';\n }\n\n if (!isNonEmptyString(value.category)) {\n return 'package.json \"ankh.category\" must be a non-empty string.';\n }\n\n if (!(value.provider === null || isPackageRelativeProviderPath(value.provider))) {\n return 'package.json \"ankh.provider\" must be null or a package-relative \"./...\" string.';\n }\n\n if (\n !Array.isArray(value.capabilities) ||\n value.capabilities.some((capability) => !isNonEmptyString(capability))\n ) {\n return 'package.json \"ankh.capabilities\" must be an array of non-empty strings.';\n }\n\n return null;\n}\n\nfunction createDiagnostic(\n severity: DoctorDiagnostic[\"severity\"],\n code: DoctorDiagnostic[\"code\"],\n diagnosticPath: string,\n message: string,\n): DoctorDiagnostic {\n return {\n code,\n message,\n path: diagnosticPath,\n severity,\n };\n}\n\nfunction createInvalidPackageJsonMessage(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n return `package.json contains invalid JSON: ${message}`;\n}\n\nasync function pathExists(targetPath: string): Promise<boolean> {\n return (await statOrNull(targetPath)) !== null;\n}\n\nasync function statOrNull(targetPath: string) {\n try {\n return await fs.stat(targetPath);\n } catch (error) {\n if (isMissingPathError(error)) {\n return null;\n }\n\n throw error;\n }\n}\n\nfunction isMissingPathError(error: unknown): error is NodeJS.ErrnoException {\n return (\n error instanceof Error &&\n \"code\" in error &&\n typeof error.code === \"string\" &&\n error.code === \"ENOENT\"\n );\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === \"string\" && value.trim() !== \"\";\n}\n\nfunction isPackageRelativeProviderPath(value: unknown): value is string {\n return isNonEmptyString(value) && value.startsWith(\"./\");\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"]}
1
+ {"version":3,"file":"analysis.js","sourceRoot":"","sources":["../src/analysis.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\n\nimport type { DoctorDiagnostic } from './diagnostics.js';\n\nexport type DoctorTargetCheck = 'package' | 'repo';\nexport type DoctorTargetMode = 'fix' | 'package' | 'repo' | 'validate';\n\nexport interface DoctorAnalysisRequest {\n readonly cwd: string;\n readonly inputPath?: string;\n readonly mode: DoctorTargetMode;\n}\n\nexport interface DoctorAnalysisResult {\n readonly appliedChecks: readonly DoctorTargetCheck[];\n readonly diagnostics: readonly DoctorDiagnostic[];\n readonly hasPackageJson: boolean;\n readonly repoMarkers: readonly string[];\n readonly targetPath: string;\n}\n\nconst REPO_MARKERS = [\n { label: '.git', relativePath: '.git' },\n { label: '.github/workflows', relativePath: path.join('.github', 'workflows') },\n { label: '.changeset', relativePath: '.changeset' },\n { label: 'package.json', relativePath: 'package.json' },\n { label: 'pnpm-workspace.yaml', relativePath: 'pnpm-workspace.yaml' },\n { label: 'bun.lock', relativePath: 'bun.lock' },\n { label: 'bun.lockb', relativePath: 'bun.lockb' },\n { label: 'package-lock.json', relativePath: 'package-lock.json' },\n { label: 'yarn.lock', relativePath: 'yarn.lock' },\n] as const;\n\nexport async function analyzeDoctorTarget(\n request: DoctorAnalysisRequest,\n): Promise<DoctorAnalysisResult> {\n const targetPath = path.resolve(request.cwd, request.inputPath ?? '.');\n const stats = await statOrNull(targetPath);\n\n if (stats === null) {\n return {\n appliedChecks: [],\n diagnostics: [\n createDiagnostic(\n 'error',\n 'target-not-found',\n targetPath,\n `Target path does not exist: ${targetPath}`,\n ),\n ],\n hasPackageJson: false,\n repoMarkers: [],\n targetPath,\n };\n }\n\n if (!stats.isDirectory()) {\n return {\n appliedChecks: [],\n diagnostics: [\n createDiagnostic(\n 'error',\n 'target-not-directory',\n targetPath,\n `Target path must be a directory: ${targetPath}`,\n ),\n ],\n hasPackageJson: false,\n repoMarkers: [],\n targetPath,\n };\n }\n\n const repoMarkers = (\n await Promise.all(\n REPO_MARKERS.map(async (marker) =>\n (await pathExists(path.join(targetPath, marker.relativePath))) ? marker.label : null,\n ),\n )\n ).filter((marker): marker is (typeof REPO_MARKERS)[number]['label'] => marker !== null);\n\n const packageJsonPath = path.join(targetPath, 'package.json');\n const hasPackageJson = repoMarkers.includes('package.json');\n const appliedChecks: DoctorTargetCheck[] = [];\n const diagnostics: DoctorDiagnostic[] = [];\n\n const shouldRunRepoChecks =\n request.mode === 'repo' ||\n ((request.mode === 'validate' || request.mode === 'fix') && repoMarkers.length > 0);\n const shouldRunPackageChecks =\n request.mode === 'package' ||\n ((request.mode === 'validate' || request.mode === 'fix') && hasPackageJson);\n\n if (request.mode === 'repo' && repoMarkers.length === 0) {\n diagnostics.push(\n createDiagnostic(\n 'error',\n 'repo-markers-missing',\n targetPath,\n 'Target is not a repo/workspace-root candidate because no repo markers were found.',\n ),\n );\n }\n\n if (request.mode === 'package' && !hasPackageJson) {\n diagnostics.push(\n createDiagnostic(\n 'error',\n 'package-json-missing',\n packageJsonPath,\n 'Target does not contain a readable package.json file.',\n ),\n );\n }\n\n if (\n (request.mode === 'validate' || request.mode === 'fix') &&\n repoMarkers.length === 0 &&\n !hasPackageJson\n ) {\n diagnostics.push(\n createDiagnostic(\n 'error',\n 'unsupported-target',\n targetPath,\n 'Target is neither a repo/workspace-root candidate nor a package root.',\n ),\n );\n }\n\n if (shouldRunRepoChecks && repoMarkers.length > 0) {\n appliedChecks.push('repo');\n diagnostics.push(...(await analyzeRepoLight(targetPath)));\n }\n\n if (shouldRunPackageChecks && hasPackageJson) {\n appliedChecks.push('package');\n diagnostics.push(...(await analyzePackageLight(targetPath, packageJsonPath)));\n }\n\n return {\n appliedChecks,\n diagnostics,\n hasPackageJson,\n repoMarkers,\n targetPath,\n };\n}\n\nasync function analyzeRepoLight(targetPath: string): Promise<DoctorDiagnostic[]> {\n const diagnostics: DoctorDiagnostic[] = [];\n\n await maybeWarnForMissingPath(diagnostics, targetPath, 'README.md', 'missing-readme');\n await maybeWarnForMissingPath(diagnostics, targetPath, 'CHANGELOG.md', 'missing-changelog');\n await maybeWarnForMissingPath(diagnostics, targetPath, 'LICENSE', 'missing-license');\n await maybeWarnForMissingPath(\n diagnostics,\n targetPath,\n '.changeset',\n 'missing-changeset-directory',\n );\n await maybeWarnForMissingPath(\n diagnostics,\n targetPath,\n path.join('.github', 'workflows'),\n 'missing-workflows-directory',\n );\n\n return diagnostics;\n}\n\nasync function analyzePackageLight(\n targetPath: string,\n packageJsonPath: string,\n): Promise<DoctorDiagnostic[]> {\n const diagnostics: DoctorDiagnostic[] = [];\n let parsed: unknown;\n\n try {\n parsed = JSON.parse(await fs.readFile(packageJsonPath, 'utf8')) as unknown;\n } catch (error) {\n diagnostics.push(\n createDiagnostic(\n 'error',\n 'invalid-package-json',\n packageJsonPath,\n createInvalidPackageJsonMessage(error),\n ),\n );\n return diagnostics;\n }\n\n if (!isRecord(parsed)) {\n diagnostics.push(\n createDiagnostic(\n 'error',\n 'invalid-package-json',\n packageJsonPath,\n 'package.json must contain a JSON object.',\n ),\n );\n return diagnostics;\n }\n\n if (!isNonEmptyString(parsed.name)) {\n diagnostics.push(\n createDiagnostic(\n 'error',\n 'package-name-missing',\n packageJsonPath,\n 'package.json must define a non-empty \"name\" field.',\n ),\n );\n }\n\n if (!isNonEmptyString(parsed.version)) {\n diagnostics.push(\n createDiagnostic(\n 'error',\n 'package-version-missing',\n packageJsonPath,\n 'package.json must define a non-empty \"version\" field.',\n ),\n );\n }\n\n if (!isNonEmptyString(parsed.type)) {\n diagnostics.push(\n createDiagnostic(\n 'error',\n 'package-type-missing',\n packageJsonPath,\n 'package.json must define a non-empty \"type\" field.',\n ),\n );\n }\n\n if ('ankh' in parsed) {\n const validationError = validateAnkhMetadataShape(parsed.ankh);\n if (validationError !== null) {\n diagnostics.push(\n createDiagnostic('error', 'invalid-ankh-metadata', targetPath, validationError),\n );\n }\n }\n\n return diagnostics;\n}\n\nasync function maybeWarnForMissingPath(\n diagnostics: DoctorDiagnostic[],\n rootPath: string,\n relativePath: string,\n code:\n | 'missing-changelog'\n | 'missing-changeset-directory'\n | 'missing-license'\n | 'missing-readme'\n | 'missing-workflows-directory',\n): Promise<void> {\n const absolutePath = path.join(rootPath, relativePath);\n if (await pathExists(absolutePath)) {\n return;\n }\n\n diagnostics.push(\n createDiagnostic(\n 'warning',\n code,\n absolutePath,\n `Missing expected repo artifact: ${relativePath}`,\n ),\n );\n}\n\nfunction validateAnkhMetadataShape(value: unknown): string | null {\n if (!isRecord(value)) {\n return 'package.json \"ankh\" metadata must be an object when present.';\n }\n\n if (!isNonEmptyString(value.category)) {\n return 'package.json \"ankh.category\" must be a non-empty string.';\n }\n\n if (!(value.provider === null || isPackageRelativeProviderPath(value.provider))) {\n return 'package.json \"ankh.provider\" must be null or a package-relative \"./...\" string.';\n }\n\n if (\n !Array.isArray(value.capabilities) ||\n value.capabilities.some((capability) => !isNonEmptyString(capability))\n ) {\n return 'package.json \"ankh.capabilities\" must be an array of non-empty strings.';\n }\n\n return null;\n}\n\nfunction createDiagnostic(\n severity: DoctorDiagnostic['severity'],\n code: DoctorDiagnostic['code'],\n diagnosticPath: string,\n message: string,\n): DoctorDiagnostic {\n return {\n code,\n message,\n path: diagnosticPath,\n severity,\n };\n}\n\nfunction createInvalidPackageJsonMessage(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n return `package.json contains invalid JSON: ${message}`;\n}\n\nasync function pathExists(targetPath: string): Promise<boolean> {\n return (await statOrNull(targetPath)) !== null;\n}\n\nasync function statOrNull(targetPath: string) {\n try {\n return await fs.stat(targetPath);\n } catch (error) {\n if (isMissingPathError(error)) {\n return null;\n }\n\n throw error;\n }\n}\n\nfunction isMissingPathError(error: unknown): error is NodeJS.ErrnoException {\n return (\n error instanceof Error &&\n 'code' in error &&\n typeof error.code === 'string' &&\n error.code === 'ENOENT'\n );\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value.trim() !== '';\n}\n\nfunction isPackageRelativeProviderPath(value: unknown): value is string {\n return isNonEmptyString(value) && value.startsWith('./');\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n"]}
@@ -1,5 +1,5 @@
1
- import type { AnkhRuntimeCommandProvider } from "@ankhorage/ankh";
2
- import { type DoctorCommandServices, type RunDoctorCommandImpl } from "./commands.js";
1
+ import type { AnkhRuntimeCommandProvider } from '@ankhorage/ankh';
2
+ import { type DoctorCommandServices, type RunDoctorCommandImpl } from './commands.js';
3
3
  export interface CreateDoctorRuntimeProviderOptions {
4
4
  readonly runCommandImpl?: RunDoctorCommandImpl;
5
5
  readonly services?: Partial<DoctorCommandServices>;
@@ -1 +1 @@
1
- {"version":3,"file":"ankh.provider.d.ts","sourceRoot":"","sources":["../src/ankh.provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAElE,OAAO,EAIL,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EAC1B,MAAM,eAAe,CAAC;AAQvB,MAAM,WAAW,kCAAkC;IACjD,QAAQ,CAAC,cAAc,CAAC,EAAE,oBAAoB,CAAC;IAC/C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACpD;AAED,wBAAgB,2BAA2B,CACzC,OAAO,GAAE,kCAAuC,GAC/C,0BAA0B,CAyB5B;AAED,QAAA,MAAM,QAAQ,4BAAgC,CAAC;AAE/C,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"ankh.provider.d.ts","sourceRoot":"","sources":["../src/ankh.provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAElE,OAAO,EAGL,KAAK,qBAAqB,EAE1B,KAAK,oBAAoB,EAC1B,MAAM,eAAe,CAAC;AAQvB,MAAM,WAAW,kCAAkC;IACjD,QAAQ,CAAC,cAAc,CAAC,EAAE,oBAAoB,CAAC;IAC/C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACpD;AAED,wBAAgB,2BAA2B,CACzC,OAAO,GAAE,kCAAuC,GAC/C,0BAA0B,CAyB5B;AAED,QAAA,MAAM,QAAQ,4BAAgC,CAAC;AAE/C,eAAe,QAAQ,CAAC"}
@@ -1,5 +1,5 @@
1
- import { createProviderCommandDescriptors, DOCTOR_COMMANDS, runDoctorCommand, } from "./commands.js";
2
- import { DOCTOR_CAPABILITIES, DOCTOR_COMMAND_CATEGORY, DOCTOR_PACKAGE_NAME, DOCTOR_PACKAGE_VERSION, } from "./packageMetadata.js";
1
+ import { createProviderCommandDescriptors, DOCTOR_COMMANDS, runDoctorCommand, } from './commands.js';
2
+ import { DOCTOR_CAPABILITIES, DOCTOR_COMMAND_CATEGORY, DOCTOR_PACKAGE_NAME, DOCTOR_PACKAGE_VERSION, } from './packageMetadata.js';
3
3
  export function createDoctorRuntimeProvider(options = {}) {
4
4
  const runCommandImpl = options.runCommandImpl ?? runDoctorCommand;
5
5
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"ankh.provider.js","sourceRoot":"","sources":["../src/ankh.provider.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,gCAAgC,EAChC,eAAe,EACf,gBAAgB,GAGjB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAO9B,MAAM,UAAU,2BAA2B,CACzC,UAA8C,EAAE;IAEhD,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,gBAAgB,CAAC;IAElE,OAAO;QACL,EAAE,EAAE,mBAAmB;QACvB,QAAQ,EAAE,uBAAuB;QACjC,OAAO,EAAE,sBAAsB;QAC/B,YAAY,EAAE,CAAC,GAAG,mBAAmB,CAAC;QACtC,QAAQ,EAAE,gCAAgC,EAAE;QAC5C,QAAQ,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAC1C,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,OAAO,CAAC,OAAO;gBACb,OAAO,cAAc,CACnB;oBACE,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,OAAO;oBACP,OAAO,EAAE,OAAO,CAAC,OAAO;iBACzB,EACD;oBACE,QAAQ,EAAE,OAAO,CAAC,QAAQ;iBAC3B,CACF,CAAC;YACJ,CAAC;SACF,CAAC,CAAC;KACiC,CAAC;AACzC,CAAC;AAED,MAAM,QAAQ,GAAG,2BAA2B,EAAE,CAAC;AAE/C,eAAe,QAAQ,CAAC","sourcesContent":["import type { AnkhRuntimeCommandProvider } from \"@ankhorage/ankh\";\n\nimport {\n createProviderCommandDescriptors,\n DOCTOR_COMMANDS,\n runDoctorCommand,\n type DoctorCommandServices,\n type RunDoctorCommandImpl,\n} from \"./commands.js\";\nimport {\n DOCTOR_CAPABILITIES,\n DOCTOR_COMMAND_CATEGORY,\n DOCTOR_PACKAGE_NAME,\n DOCTOR_PACKAGE_VERSION,\n} from \"./packageMetadata.js\";\n\nexport interface CreateDoctorRuntimeProviderOptions {\n readonly runCommandImpl?: RunDoctorCommandImpl;\n readonly services?: Partial<DoctorCommandServices>;\n}\n\nexport function createDoctorRuntimeProvider(\n options: CreateDoctorRuntimeProviderOptions = {},\n): AnkhRuntimeCommandProvider {\n const runCommandImpl = options.runCommandImpl ?? runDoctorCommand;\n\n return {\n id: DOCTOR_PACKAGE_NAME,\n category: DOCTOR_COMMAND_CATEGORY,\n version: DOCTOR_PACKAGE_VERSION,\n capabilities: [...DOCTOR_CAPABILITIES],\n commands: createProviderCommandDescriptors(),\n handlers: DOCTOR_COMMANDS.map((command) => ({\n path: command.path,\n handler(request) {\n return runCommandImpl(\n {\n argv: request.argv,\n command,\n context: request.context,\n },\n {\n services: options.services,\n },\n );\n },\n })),\n } satisfies AnkhRuntimeCommandProvider;\n}\n\nconst provider = createDoctorRuntimeProvider();\n\nexport default provider;\n"]}
1
+ {"version":3,"file":"ankh.provider.js","sourceRoot":"","sources":["../src/ankh.provider.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,gCAAgC,EAChC,eAAe,EAEf,gBAAgB,GAEjB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAO9B,MAAM,UAAU,2BAA2B,CACzC,UAA8C,EAAE;IAEhD,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,gBAAgB,CAAC;IAElE,OAAO;QACL,EAAE,EAAE,mBAAmB;QACvB,QAAQ,EAAE,uBAAuB;QACjC,OAAO,EAAE,sBAAsB;QAC/B,YAAY,EAAE,CAAC,GAAG,mBAAmB,CAAC;QACtC,QAAQ,EAAE,gCAAgC,EAAE;QAC5C,QAAQ,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAC1C,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,OAAO,CAAC,OAAO;gBACb,OAAO,cAAc,CACnB;oBACE,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,OAAO;oBACP,OAAO,EAAE,OAAO,CAAC,OAAO;iBACzB,EACD;oBACE,QAAQ,EAAE,OAAO,CAAC,QAAQ;iBAC3B,CACF,CAAC;YACJ,CAAC;SACF,CAAC,CAAC;KACiC,CAAC;AACzC,CAAC;AAED,MAAM,QAAQ,GAAG,2BAA2B,EAAE,CAAC;AAE/C,eAAe,QAAQ,CAAC","sourcesContent":["import type { AnkhRuntimeCommandProvider } from '@ankhorage/ankh';\n\nimport {\n createProviderCommandDescriptors,\n DOCTOR_COMMANDS,\n type DoctorCommandServices,\n runDoctorCommand,\n type RunDoctorCommandImpl,\n} from './commands.js';\nimport {\n DOCTOR_CAPABILITIES,\n DOCTOR_COMMAND_CATEGORY,\n DOCTOR_PACKAGE_NAME,\n DOCTOR_PACKAGE_VERSION,\n} from './packageMetadata.js';\n\nexport interface CreateDoctorRuntimeProviderOptions {\n readonly runCommandImpl?: RunDoctorCommandImpl;\n readonly services?: Partial<DoctorCommandServices>;\n}\n\nexport function createDoctorRuntimeProvider(\n options: CreateDoctorRuntimeProviderOptions = {},\n): AnkhRuntimeCommandProvider {\n const runCommandImpl = options.runCommandImpl ?? runDoctorCommand;\n\n return {\n id: DOCTOR_PACKAGE_NAME,\n category: DOCTOR_COMMAND_CATEGORY,\n version: DOCTOR_PACKAGE_VERSION,\n capabilities: [...DOCTOR_CAPABILITIES],\n commands: createProviderCommandDescriptors(),\n handlers: DOCTOR_COMMANDS.map((command) => ({\n path: command.path,\n handler(request) {\n return runCommandImpl(\n {\n argv: request.argv,\n command,\n context: request.context,\n },\n {\n services: options.services,\n },\n );\n },\n })),\n } satisfies AnkhRuntimeCommandProvider;\n}\n\nconst provider = createDoctorRuntimeProvider();\n\nexport default provider;\n"]}
package/dist/cli.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env bun
2
- import type { DoctorCommandContext, DoctorCommandRunResult } from "./commandContext.js";
3
- import { type DoctorCommandServices, type RunDoctorCommandImpl } from "./commands.js";
2
+ import type { DoctorCommandContext, DoctorCommandRunResult } from './commandContext.js';
3
+ import { type DoctorCommandServices, type RunDoctorCommandImpl } from './commands.js';
4
4
  export interface DoctorCliOptions {
5
5
  readonly context?: DoctorCommandContext;
6
6
  readonly runCommandImpl?: RunDoctorCommandImpl;
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAExF,OAAO,EAKL,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EAC1B,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,oBAAoB,CAAC;IACxC,QAAQ,CAAC,cAAc,CAAC,EAAE,oBAAoB,CAAC;IAC/C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACpD;AAED,wBAAsB,MAAM,CAC1B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,sBAAsB,CAAC,CA+BjC"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAExF,OAAO,EACL,KAAK,qBAAqB,EAK1B,KAAK,oBAAoB,EAC1B,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,oBAAoB,CAAC;IACxC,QAAQ,CAAC,cAAc,CAAC,EAAE,oBAAoB,CAAC;IAC/C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACpD;AAED,wBAAsB,MAAM,CAC1B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,sBAAsB,CAAC,CA+BjC"}
package/dist/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env bun
2
- import { createDefaultCommandContext } from "./commandContext.js";
3
- import { findDoctorCommandByStandaloneName, renderRootHelp, renderUnknownCommand, runDoctorCommand, } from "./commands.js";
2
+ import { createDefaultCommandContext } from './commandContext.js';
3
+ import { findDoctorCommandByStandaloneName, renderRootHelp, renderUnknownCommand, runDoctorCommand, } from './commands.js';
4
4
  export async function runCli(argv, options = {}) {
5
5
  const context = options.context ?? createDefaultCommandContext();
6
6
  const runCommand = options.runCommandImpl ?? runDoctorCommand;
@@ -27,10 +27,10 @@ export async function runCli(argv, options = {}) {
27
27
  });
28
28
  }
29
29
  function isHelpToken(value) {
30
- return value === "--help" || value === "-h" || value === "help";
30
+ return value === '--help' || value === '-h' || value === 'help';
31
31
  }
32
32
  function isVersionToken(value) {
33
- return value === "--version" || value === "-v" || value === "version";
33
+ return value === '--version' || value === '-v' || value === 'version';
34
34
  }
35
35
  if (import.meta.main) {
36
36
  const result = await runCli(process.argv.slice(2));
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAGA,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EACL,iCAAiC,EACjC,cAAc,EACd,oBAAoB,EACpB,gBAAgB,GAGjB,MAAM,eAAe,CAAC;AAQvB,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,IAAuB,EACvB,UAA4B,EAAE;IAE9B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,2BAA2B,EAAE,CAAC;IACjE,MAAM,UAAU,GAAG,OAAO,CAAC,cAAc,IAAI,gBAAgB,CAAC;IAC9D,MAAM,CAAC,UAAU,EAAE,GAAG,UAAU,CAAC,GAAG,IAAI,CAAC;IAEzC,IAAI,UAAU,KAAK,SAAS,IAAI,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;QACxD,OAAO,CAAC,WAAW,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;QACrD,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACzB,CAAC;IAED,IAAI,cAAc,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,OAAO,IAAI,CAAC,CAAC;QAC5C,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACzB,CAAC;IAED,MAAM,OAAO,GAAG,iCAAiC,CAAC,UAAU,CAAC,CAAC;IAC9D,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,OAAO,CAAC,WAAW,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC,CAAC;QACtD,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACzB,CAAC;IAED,OAAO,UAAU,CACf;QACE,IAAI,EAAE,UAAU;QAChB,OAAO;QACP,OAAO;KACR,EACD;QACE,QAAQ,EAAE,OAAO,CAAC,QAAQ;KAC3B,CACF,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,KAAa;IAChC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,MAAM,CAAC;AAClE,CAAC;AAED,SAAS,cAAc,CAAC,KAAa;IACnC,OAAO,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,CAAC;AACxE,CAAC;AAED,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACrB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC","sourcesContent":["#!/usr/bin/env bun\n\nimport type { DoctorCommandContext, DoctorCommandRunResult } from \"./commandContext.js\";\nimport { createDefaultCommandContext } from \"./commandContext.js\";\nimport {\n findDoctorCommandByStandaloneName,\n renderRootHelp,\n renderUnknownCommand,\n runDoctorCommand,\n type DoctorCommandServices,\n type RunDoctorCommandImpl,\n} from \"./commands.js\";\n\nexport interface DoctorCliOptions {\n readonly context?: DoctorCommandContext;\n readonly runCommandImpl?: RunDoctorCommandImpl;\n readonly services?: Partial<DoctorCommandServices>;\n}\n\nexport async function runCli(\n argv: readonly string[],\n options: DoctorCliOptions = {},\n): Promise<DoctorCommandRunResult> {\n const context = options.context ?? createDefaultCommandContext();\n const runCommand = options.runCommandImpl ?? runDoctorCommand;\n const [firstToken, ...restTokens] = argv;\n\n if (firstToken === undefined || isHelpToken(firstToken)) {\n context.writeStdout(renderRootHelp(context.version));\n return { exitCode: 0 };\n }\n\n if (isVersionToken(firstToken)) {\n context.writeStdout(`${context.version}\\n`);\n return { exitCode: 0 };\n }\n\n const command = findDoctorCommandByStandaloneName(firstToken);\n if (command === null) {\n context.writeStderr(renderUnknownCommand(firstToken));\n return { exitCode: 1 };\n }\n\n return runCommand(\n {\n argv: restTokens,\n command,\n context,\n },\n {\n services: options.services,\n },\n );\n}\n\nfunction isHelpToken(value: string): boolean {\n return value === \"--help\" || value === \"-h\" || value === \"help\";\n}\n\nfunction isVersionToken(value: string): boolean {\n return value === \"--version\" || value === \"-v\" || value === \"version\";\n}\n\nif (import.meta.main) {\n const result = await runCli(process.argv.slice(2));\n process.exit(result.exitCode);\n}\n"]}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAGA,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAEL,iCAAiC,EACjC,cAAc,EACd,oBAAoB,EACpB,gBAAgB,GAEjB,MAAM,eAAe,CAAC;AAQvB,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,IAAuB,EACvB,UAA4B,EAAE;IAE9B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,2BAA2B,EAAE,CAAC;IACjE,MAAM,UAAU,GAAG,OAAO,CAAC,cAAc,IAAI,gBAAgB,CAAC;IAC9D,MAAM,CAAC,UAAU,EAAE,GAAG,UAAU,CAAC,GAAG,IAAI,CAAC;IAEzC,IAAI,UAAU,KAAK,SAAS,IAAI,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;QACxD,OAAO,CAAC,WAAW,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;QACrD,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACzB,CAAC;IAED,IAAI,cAAc,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,OAAO,IAAI,CAAC,CAAC;QAC5C,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACzB,CAAC;IAED,MAAM,OAAO,GAAG,iCAAiC,CAAC,UAAU,CAAC,CAAC;IAC9D,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,OAAO,CAAC,WAAW,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC,CAAC;QACtD,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACzB,CAAC;IAED,OAAO,UAAU,CACf;QACE,IAAI,EAAE,UAAU;QAChB,OAAO;QACP,OAAO;KACR,EACD;QACE,QAAQ,EAAE,OAAO,CAAC,QAAQ;KAC3B,CACF,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,KAAa;IAChC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,MAAM,CAAC;AAClE,CAAC;AAED,SAAS,cAAc,CAAC,KAAa;IACnC,OAAO,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,CAAC;AACxE,CAAC;AAED,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACrB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC","sourcesContent":["#!/usr/bin/env bun\n\nimport type { DoctorCommandContext, DoctorCommandRunResult } from './commandContext.js';\nimport { createDefaultCommandContext } from './commandContext.js';\nimport {\n type DoctorCommandServices,\n findDoctorCommandByStandaloneName,\n renderRootHelp,\n renderUnknownCommand,\n runDoctorCommand,\n type RunDoctorCommandImpl,\n} from './commands.js';\n\nexport interface DoctorCliOptions {\n readonly context?: DoctorCommandContext;\n readonly runCommandImpl?: RunDoctorCommandImpl;\n readonly services?: Partial<DoctorCommandServices>;\n}\n\nexport async function runCli(\n argv: readonly string[],\n options: DoctorCliOptions = {},\n): Promise<DoctorCommandRunResult> {\n const context = options.context ?? createDefaultCommandContext();\n const runCommand = options.runCommandImpl ?? runDoctorCommand;\n const [firstToken, ...restTokens] = argv;\n\n if (firstToken === undefined || isHelpToken(firstToken)) {\n context.writeStdout(renderRootHelp(context.version));\n return { exitCode: 0 };\n }\n\n if (isVersionToken(firstToken)) {\n context.writeStdout(`${context.version}\\n`);\n return { exitCode: 0 };\n }\n\n const command = findDoctorCommandByStandaloneName(firstToken);\n if (command === null) {\n context.writeStderr(renderUnknownCommand(firstToken));\n return { exitCode: 1 };\n }\n\n return runCommand(\n {\n argv: restTokens,\n command,\n context,\n },\n {\n services: options.services,\n },\n );\n}\n\nfunction isHelpToken(value: string): boolean {\n return value === '--help' || value === '-h' || value === 'help';\n}\n\nfunction isVersionToken(value: string): boolean {\n return value === '--version' || value === '-v' || value === 'version';\n}\n\nif (import.meta.main) {\n const result = await runCli(process.argv.slice(2));\n process.exit(result.exitCode);\n}\n"]}
@@ -1,4 +1,4 @@
1
- import packageJson from "../package.json";
1
+ import packageJson from '../package.json';
2
2
  export function createDefaultCommandContext() {
3
3
  return {
4
4
  cwd: process.cwd(),
@@ -1 +1 @@
1
- {"version":3,"file":"commandContext.js","sourceRoot":"","sources":["../src/commandContext.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAc1C,MAAM,UAAU,2BAA2B;IACzC,OAAO;QACL,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;QAClB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,OAAO,EAAE,WAAW,CAAC,OAAO;QAC5B,WAAW,CAAC,IAAY;YACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;QACD,WAAW,CAAC,IAAY;YACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import packageJson from \"../package.json\";\n\nexport interface DoctorCommandContext {\n readonly cwd: string;\n readonly env: NodeJS.ProcessEnv;\n readonly version: string;\n writeStdout(text: string): void;\n writeStderr(text: string): void;\n}\n\nexport interface DoctorCommandRunResult {\n readonly exitCode: number;\n}\n\nexport function createDefaultCommandContext(): DoctorCommandContext {\n return {\n cwd: process.cwd(),\n env: process.env,\n version: packageJson.version,\n writeStdout(text: string) {\n process.stdout.write(text);\n },\n writeStderr(text: string) {\n process.stderr.write(text);\n },\n };\n}\n"]}
1
+ {"version":3,"file":"commandContext.js","sourceRoot":"","sources":["../src/commandContext.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAc1C,MAAM,UAAU,2BAA2B;IACzC,OAAO;QACL,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;QAClB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,OAAO,EAAE,WAAW,CAAC,OAAO;QAC5B,WAAW,CAAC,IAAY;YACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;QACD,WAAW,CAAC,IAAY;YACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import packageJson from '../package.json';\n\nexport interface DoctorCommandContext {\n readonly cwd: string;\n readonly env: NodeJS.ProcessEnv;\n readonly version: string;\n writeStdout(text: string): void;\n writeStderr(text: string): void;\n}\n\nexport interface DoctorCommandRunResult {\n readonly exitCode: number;\n}\n\nexport function createDefaultCommandContext(): DoctorCommandContext {\n return {\n cwd: process.cwd(),\n env: process.env,\n version: packageJson.version,\n writeStdout(text: string) {\n process.stdout.write(text);\n },\n writeStderr(text: string) {\n process.stderr.write(text);\n },\n };\n}\n"]}
@@ -1,8 +1,8 @@
1
- import type { AnkhCapabilityId, AnkhCommandDescriptor } from "@ankhorage/contracts/cli";
2
- import type { DoctorTargetMode } from "./analysis.js";
3
- import { analyzeDoctorTarget } from "./analysis.js";
4
- import type { DoctorCommandContext, DoctorCommandRunResult } from "./commandContext.js";
5
- type DoctorCommandName = "fix" | "package" | "repo" | "validate";
1
+ import type { AnkhCapabilityId, AnkhCommandDescriptor } from '@ankhorage/contracts/cli';
2
+ import type { DoctorTargetMode } from './analysis.js';
3
+ import { analyzeDoctorTarget } from './analysis.js';
4
+ import type { DoctorCommandContext, DoctorCommandRunResult } from './commandContext.js';
5
+ type DoctorCommandName = 'fix' | 'package' | 'repo' | 'validate';
6
6
  interface DoctorCommandRunRequest {
7
7
  readonly context: DoctorCommandContext;
8
8
  readonly inputPath?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,qBAAqB,EACtB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAwB,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAOpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAExF,KAAK,iBAAiB,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,CAAC;AAEjE,UAAU,uBAAuB;IAC/B,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAC;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,KAAK,2BAA2B,GAAG,CACjC,OAAO,EAAE,uBAAuB,EAChC,QAAQ,EAAE,qBAAqB,KAC5B,OAAO,CAAC,sBAAsB,CAAC,CAAC;AAErC,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAC5C,QAAQ,CAAC,cAAc,EAAE,iBAAiB,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,EAAE,2BAA2B,CAAC;CAC3C;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,uBAAuB,CAAC;IAC1C,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAC;CACxC;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,aAAa,EAAE,OAAO,mBAAmB,CAAC;CACpD;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,cAAc,CAAC,EAAE,oBAAoB,CAAC;IAC/C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACpD;AAED,MAAM,MAAM,oBAAoB,GAAG,CACjC,OAAO,EAAE,uBAAuB,EAChC,OAAO,CAAC,EAAE,uBAAuB,KAC9B,OAAO,CAAC,sBAAsB,CAAC,CAAC;AASrC,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiC2B,CAAC;AAExD,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,uBAAuB,EAChC,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,sBAAsB,CAAC,CAuBjC;AAED,wBAAgB,gCAAgC,IAAI,SAAS,qBAAqB,EAAE,CAMnF;AAED,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,MAAM,GACZ,uBAAuB,GAAG,IAAI,CAEhC;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAmBtD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAO1D;AA4CD,iBAAe,kBAAkB,CAC/B,OAAO,EAAE,uBAAuB,EAChC,QAAQ,EAAE,qBAAqB,GAC9B,OAAO,CAAC,sBAAsB,CAAC,CAYjC;AAED,iBAAe,aAAa,CAC1B,OAAO,EAAE,uBAAuB,EAChC,QAAQ,EAAE,qBAAqB,GAC9B,OAAO,CAAC,sBAAsB,CAAC,CAajC;AAED,iBAAe,cAAc,CAC3B,OAAO,EAAE,uBAAuB,EAChC,QAAQ,EAAE,qBAAqB,GAC9B,OAAO,CAAC,sBAAsB,CAAC,CAYjC;AAED,iBAAe,iBAAiB,CAC9B,OAAO,EAAE,uBAAuB,EAChC,QAAQ,EAAE,qBAAqB,GAC9B,OAAO,CAAC,sBAAsB,CAAC,CAYjC"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAExF,OAAO,KAAK,EAAwB,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAQxF,KAAK,iBAAiB,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,CAAC;AAEjE,UAAU,uBAAuB;IAC/B,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAC;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,KAAK,2BAA2B,GAAG,CACjC,OAAO,EAAE,uBAAuB,EAChC,QAAQ,EAAE,qBAAqB,KAC5B,OAAO,CAAC,sBAAsB,CAAC,CAAC;AAErC,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAC5C,QAAQ,CAAC,cAAc,EAAE,iBAAiB,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,EAAE,2BAA2B,CAAC;CAC3C;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,uBAAuB,CAAC;IAC1C,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAC;CACxC;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,aAAa,EAAE,OAAO,mBAAmB,CAAC;CACpD;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,cAAc,CAAC,EAAE,oBAAoB,CAAC;IAC/C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACpD;AAED,MAAM,MAAM,oBAAoB,GAAG,CACjC,OAAO,EAAE,uBAAuB,EAChC,OAAO,CAAC,EAAE,uBAAuB,KAC9B,OAAO,CAAC,sBAAsB,CAAC,CAAC;AASrC,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiC2B,CAAC;AAExD,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,uBAAuB,EAChC,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,sBAAsB,CAAC,CAqBjC;AAED,wBAAgB,gCAAgC,IAAI,SAAS,qBAAqB,EAAE,CAMnF;AAED,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,MAAM,GAAG,uBAAuB,GAAG,IAAI,CAE/F;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAmBtD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AA4CD,iBAAe,kBAAkB,CAC/B,OAAO,EAAE,uBAAuB,EAChC,QAAQ,EAAE,qBAAqB,GAC9B,OAAO,CAAC,sBAAsB,CAAC,CAYjC;AAED,iBAAe,aAAa,CAC1B,OAAO,EAAE,uBAAuB,EAChC,QAAQ,EAAE,qBAAqB,GAC9B,OAAO,CAAC,sBAAsB,CAAC,CAajC;AAED,iBAAe,cAAc,CAC3B,OAAO,EAAE,uBAAuB,EAChC,QAAQ,EAAE,qBAAqB,GAC9B,OAAO,CAAC,sBAAsB,CAAC,CAYjC;AAED,iBAAe,iBAAiB,CAC9B,OAAO,EAAE,uBAAuB,EAChC,QAAQ,EAAE,qBAAqB,GAC9B,OAAO,CAAC,sBAAsB,CAAC,CAYjC"}
package/dist/commands.js CHANGED
@@ -1,6 +1,6 @@
1
- import { analyzeDoctorTarget } from "./analysis.js";
2
- import { countErrorDiagnostics, countWarningDiagnostics, } from "./diagnostics.js";
3
- import { DOCTOR_CAPABILITIES, DOCTOR_COMMAND_CATEGORY } from "./packageMetadata.js";
1
+ import { analyzeDoctorTarget } from './analysis.js';
2
+ import { countErrorDiagnostics, countWarningDiagnostics, } from './diagnostics.js';
3
+ import { DOCTOR_CAPABILITIES, DOCTOR_COMMAND_CATEGORY } from './packageMetadata.js';
4
4
  const COMMAND_CAPABILITIES = {
5
5
  validate: DOCTOR_CAPABILITIES[0],
6
6
  fix: DOCTOR_CAPABILITIES[1],
@@ -9,35 +9,35 @@ const COMMAND_CAPABILITIES = {
9
9
  };
10
10
  export const DOCTOR_COMMANDS = [
11
11
  {
12
- standaloneName: "validate",
13
- path: ["validate"],
12
+ standaloneName: 'validate',
13
+ path: ['validate'],
14
14
  capability: COMMAND_CAPABILITIES.validate,
15
- mode: "validate",
16
- summary: "Auto-detect lightweight repo and package diagnostics for a local path.",
15
+ mode: 'validate',
16
+ summary: 'Auto-detect lightweight repo and package diagnostics for a local path.',
17
17
  run: runValidateCommand,
18
18
  },
19
19
  {
20
- standaloneName: "fix",
21
- path: ["fix"],
20
+ standaloneName: 'fix',
21
+ path: ['fix'],
22
22
  capability: COMMAND_CAPABILITIES.fix,
23
- mode: "fix",
24
- summary: "Run the same lightweight checks and report that no automatic fixes exist yet.",
23
+ mode: 'fix',
24
+ summary: 'Run the same lightweight checks and report that no automatic fixes exist yet.',
25
25
  run: runFixCommand,
26
26
  },
27
27
  {
28
- standaloneName: "repo",
29
- path: ["repo"],
28
+ standaloneName: 'repo',
29
+ path: ['repo'],
30
30
  capability: COMMAND_CAPABILITIES.repo,
31
- mode: "repo",
32
- summary: "Force repo-light diagnostics for a repo/workspace-root candidate path.",
31
+ mode: 'repo',
32
+ summary: 'Force repo-light diagnostics for a repo/workspace-root candidate path.',
33
33
  run: runRepoCommand,
34
34
  },
35
35
  {
36
- standaloneName: "package",
37
- path: ["package"],
36
+ standaloneName: 'package',
37
+ path: ['package'],
38
38
  capability: COMMAND_CAPABILITIES.package,
39
- mode: "package",
40
- summary: "Force package-light diagnostics for a directory containing package.json.",
39
+ mode: 'package',
40
+ summary: 'Force package-light diagnostics for a directory containing package.json.',
41
41
  run: runPackageCommand,
42
42
  },
43
43
  ];
@@ -45,7 +45,7 @@ export async function runDoctorCommand(request, options = {}) {
45
45
  const services = createDoctorCommandServices(options.services);
46
46
  try {
47
47
  const parsedArgs = parseCommandArguments(request.command, request.argv);
48
- if (parsedArgs.kind === "help") {
48
+ if (parsedArgs.kind === 'help') {
49
49
  request.context.writeStdout(renderCommandHelp(request.command));
50
50
  return { exitCode: 0 };
51
51
  }
@@ -70,42 +70,37 @@ export function findDoctorCommandByStandaloneName(value) {
70
70
  return DOCTOR_COMMANDS.find((command) => command.standaloneName === value) ?? null;
71
71
  }
72
72
  export function renderRootHelp(version) {
73
- const commandLines = DOCTOR_COMMANDS.map((command) => ` ${command.standaloneName.padEnd(8, " ")} ${command.summary}`).join("\n");
73
+ const commandLines = DOCTOR_COMMANDS.map((command) => ` ${command.standaloneName.padEnd(8, ' ')} ${command.summary}`).join('\n');
74
74
  return [
75
75
  `@ankhorage/doctor v${version}`,
76
- "",
77
- "Usage:",
78
- " ankhorage-doctor <command> [path]",
76
+ '',
77
+ 'Usage:',
78
+ ' ankhorage-doctor <command> [path]',
79
79
  ` ankh ${DOCTOR_COMMAND_CATEGORY} <command> [path]`,
80
- "",
81
- "Commands:",
80
+ '',
81
+ 'Commands:',
82
82
  commandLines,
83
- "",
84
- "Path resolution:",
85
- " Pass [path], or omit it to validate the current working directory.",
86
- "",
87
- ].join("\n");
83
+ '',
84
+ 'Path resolution:',
85
+ ' Pass [path], or omit it to validate the current working directory.',
86
+ '',
87
+ ].join('\n');
88
88
  }
89
89
  export function renderUnknownCommand(value) {
90
- return [
91
- `Unknown doctor command: ${value}`,
92
- "",
93
- "Run ankhorage-doctor --help",
94
- "",
95
- ].join("\n");
90
+ return [`Unknown doctor command: ${value}`, '', 'Run ankhorage-doctor --help', ''].join('\n');
96
91
  }
97
92
  function renderCommandHelp(command) {
98
93
  return [
99
94
  command.summary,
100
- "",
101
- "Usage:",
95
+ '',
96
+ 'Usage:',
102
97
  ` ankhorage-doctor ${command.standaloneName} [path]`,
103
- ` ankh ${DOCTOR_COMMAND_CATEGORY} ${command.path.join(" ")} [path]`,
104
- "",
105
- "Path resolution:",
106
- " Pass [path], or omit it to validate the current working directory.",
107
- "",
108
- ].join("\n");
98
+ ` ankh ${DOCTOR_COMMAND_CATEGORY} ${command.path.join(' ')} [path]`,
99
+ '',
100
+ 'Path resolution:',
101
+ ' Pass [path], or omit it to validate the current working directory.',
102
+ '',
103
+ ].join('\n');
109
104
  }
110
105
  function createDoctorCommandServices(overrides = {}) {
111
106
  return {
@@ -113,15 +108,15 @@ function createDoctorCommandServices(overrides = {}) {
113
108
  };
114
109
  }
115
110
  function parseCommandArguments(command, argv) {
116
- const firstArg = argv[0];
111
+ const [firstArg] = argv;
117
112
  if (argv.length === 1 && firstArg !== undefined && isHelpToken(firstArg)) {
118
- return { kind: "help" };
113
+ return { kind: 'help' };
119
114
  }
120
115
  if (argv.length > 1) {
121
116
  throw new Error(`Doctor ${command.standaloneName} accepts at most one path argument.`);
122
117
  }
123
118
  return {
124
- kind: "run",
119
+ kind: 'run',
125
120
  inputPath: firstArg,
126
121
  };
127
122
  }
@@ -129,9 +124,9 @@ async function runValidateCommand(request, services) {
129
124
  const result = await services.analyzeTarget({
130
125
  cwd: request.context.cwd,
131
126
  inputPath: request.inputPath,
132
- mode: "validate",
127
+ mode: 'validate',
133
128
  });
134
- request.context.writeStdout(renderAnalysisReport("validate", result));
129
+ request.context.writeStdout(renderAnalysisReport('validate', result));
135
130
  return {
136
131
  exitCode: countErrorDiagnostics(result.diagnostics) > 0 ? 1 : 0,
137
132
  };
@@ -140,10 +135,10 @@ async function runFixCommand(request, services) {
140
135
  const result = await services.analyzeTarget({
141
136
  cwd: request.context.cwd,
142
137
  inputPath: request.inputPath,
143
- mode: "fix",
138
+ mode: 'fix',
144
139
  });
145
- request.context.writeStdout(renderAnalysisReport("fix", result));
146
- request.context.writeStdout("No automatic fixes available.\n");
140
+ request.context.writeStdout(renderAnalysisReport('fix', result));
141
+ request.context.writeStdout('No automatic fixes available.\n');
147
142
  return {
148
143
  exitCode: countErrorDiagnostics(result.diagnostics) > 0 ? 1 : 0,
149
144
  };
@@ -152,9 +147,9 @@ async function runRepoCommand(request, services) {
152
147
  const result = await services.analyzeTarget({
153
148
  cwd: request.context.cwd,
154
149
  inputPath: request.inputPath,
155
- mode: "repo",
150
+ mode: 'repo',
156
151
  });
157
- request.context.writeStdout(renderAnalysisReport("repo", result));
152
+ request.context.writeStdout(renderAnalysisReport('repo', result));
158
153
  return {
159
154
  exitCode: countErrorDiagnostics(result.diagnostics) > 0 ? 1 : 0,
160
155
  };
@@ -163,9 +158,9 @@ async function runPackageCommand(request, services) {
163
158
  const result = await services.analyzeTarget({
164
159
  cwd: request.context.cwd,
165
160
  inputPath: request.inputPath,
166
- mode: "package",
161
+ mode: 'package',
167
162
  });
168
- request.context.writeStdout(renderAnalysisReport("package", result));
163
+ request.context.writeStdout(renderAnalysisReport('package', result));
169
164
  return {
170
165
  exitCode: countErrorDiagnostics(result.diagnostics) > 0 ? 1 : 0,
171
166
  };
@@ -174,13 +169,13 @@ function renderAnalysisReport(commandName, result) {
174
169
  const lines = [
175
170
  `doctor ${commandName}`,
176
171
  `target: ${result.targetPath}`,
177
- `checks: ${result.appliedChecks.length > 0 ? result.appliedChecks.join(", ") : "none"}`,
178
- `repoMarkers: ${result.repoMarkers.length > 0 ? result.repoMarkers.join(", ") : "none"}`,
179
- "",
180
- "Diagnostics:",
172
+ `checks: ${result.appliedChecks.length > 0 ? result.appliedChecks.join(', ') : 'none'}`,
173
+ `repoMarkers: ${result.repoMarkers.length > 0 ? result.repoMarkers.join(', ') : 'none'}`,
174
+ '',
175
+ 'Diagnostics:',
181
176
  ];
182
177
  if (result.diagnostics.length === 0) {
183
- lines.push(" none");
178
+ lines.push(' none');
184
179
  }
185
180
  else {
186
181
  for (const diagnostic of result.diagnostics) {
@@ -189,19 +184,19 @@ function renderAnalysisReport(commandName, result) {
189
184
  }
190
185
  const errorCount = countErrorDiagnostics(result.diagnostics);
191
186
  const warningCount = countWarningDiagnostics(result.diagnostics);
192
- lines.push("");
187
+ lines.push('');
193
188
  lines.push(`Summary: ${errorCount} error(s), ${warningCount} warning(s)`);
194
- lines.push("");
195
- return lines.join("\n");
189
+ lines.push('');
190
+ return lines.join('\n');
196
191
  }
197
192
  function renderDiagnosticLine(diagnostic) {
198
193
  return ` - ${diagnostic.severity.toUpperCase()} ${diagnostic.code}: ${diagnostic.message}`;
199
194
  }
200
195
  function renderCommandFailure(commandName, error) {
201
196
  const message = error instanceof Error ? error.message : String(error);
202
- return [`Failed to run doctor ${commandName}: ${message}`, ""].join("\n");
197
+ return [`Failed to run doctor ${commandName}: ${message}`, ''].join('\n');
203
198
  }
204
199
  function isHelpToken(value) {
205
- return value === "--help" || value === "-h" || value === "help";
200
+ return value === '--help' || value === '-h' || value === 'help';
206
201
  }
207
202
  //# sourceMappingURL=commands.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EACL,qBAAqB,EACrB,uBAAuB,GAExB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AA4CpF,MAAM,oBAAoB,GAAG;IAC3B,QAAQ,EAAE,mBAAmB,CAAC,CAAC,CAAC;IAChC,GAAG,EAAE,mBAAmB,CAAC,CAAC,CAAC;IAC3B,IAAI,EAAE,mBAAmB,CAAC,CAAC,CAAC;IAC5B,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC;CAC+B,CAAC;AAEjE,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B;QACE,cAAc,EAAE,UAAU;QAC1B,IAAI,EAAE,CAAC,UAAU,CAAC;QAClB,UAAU,EAAE,oBAAoB,CAAC,QAAQ;QACzC,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,wEAAwE;QACjF,GAAG,EAAE,kBAAkB;KACxB;IACD;QACE,cAAc,EAAE,KAAK;QACrB,IAAI,EAAE,CAAC,KAAK,CAAC;QACb,UAAU,EAAE,oBAAoB,CAAC,GAAG;QACpC,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,+EAA+E;QACxF,GAAG,EAAE,aAAa;KACnB;IACD;QACE,cAAc,EAAE,MAAM;QACtB,IAAI,EAAE,CAAC,MAAM,CAAC;QACd,UAAU,EAAE,oBAAoB,CAAC,IAAI;QACrC,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,wEAAwE;QACjF,GAAG,EAAE,cAAc;KACpB;IACD;QACE,cAAc,EAAE,SAAS;QACzB,IAAI,EAAE,CAAC,SAAS,CAAC;QACjB,UAAU,EAAE,oBAAoB,CAAC,OAAO;QACxC,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,0EAA0E;QACnF,GAAG,EAAE,iBAAiB;KACvB;CACoD,CAAC;AAExD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAgC,EAChC,UAAmC,EAAE;IAErC,MAAM,QAAQ,GAAG,2BAA2B,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAE/D,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,qBAAqB,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACxE,IAAI,UAAU,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC/B,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,iBAAiB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;YAChE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;QACzB,CAAC;QAED,OAAO,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,CAC9B;YACE,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,SAAS,EAAE,UAAU,CAAC,SAAS;SAChC,EACD,QAAQ,CACT,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,OAAO,CAAC,WAAW,CACzB,oBAAoB,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,EAAE,KAAK,CAAC,CAC5D,CAAC;QACF,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACzB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gCAAgC;IAC9C,OAAO,eAAe,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACvC,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,OAAO,EAAE,OAAO,CAAC,OAAO;KACzB,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,UAAU,iCAAiC,CAC/C,KAAa;IAEb,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,cAAc,KAAK,KAAK,CAAC,IAAI,IAAI,CAAC;AACrF,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,MAAM,YAAY,GAAG,eAAe,CAAC,GAAG,CACtC,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAC7E,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,OAAO;QACL,sBAAsB,OAAO,EAAE;QAC/B,EAAE;QACF,QAAQ;QACR,qCAAqC;QACrC,UAAU,uBAAuB,mBAAmB;QACpD,EAAE;QACF,WAAW;QACX,YAAY;QACZ,EAAE;QACF,kBAAkB;QAClB,sEAAsE;QACtE,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,OAAO;QACL,2BAA2B,KAAK,EAAE;QAClC,EAAE;QACF,6BAA6B;QAC7B,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAgC;IACzD,OAAO;QACL,OAAO,CAAC,OAAO;QACf,EAAE;QACF,QAAQ;QACR,sBAAsB,OAAO,CAAC,cAAc,SAAS;QACrD,UAAU,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS;QACpE,EAAE;QACF,kBAAkB;QAClB,sEAAsE;QACtE,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,SAAS,2BAA2B,CAClC,YAA4C,EAAE;IAE9C,OAAO;QACL,aAAa,EAAE,SAAS,CAAC,aAAa,IAAI,mBAAmB;KAC9D,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAC5B,OAAgC,EAChC,IAAuB;IAEvB,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAEzB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,KAAK,SAAS,IAAI,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,UAAU,OAAO,CAAC,cAAc,qCAAqC,CAAC,CAAC;IACzF,CAAC;IAED,OAAO;QACL,IAAI,EAAE,KAAK;QACX,SAAS,EAAE,QAAQ;KACpB,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC/B,OAAgC,EAChC,QAA+B;IAE/B,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,aAAa,CAAC;QAC1C,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG;QACxB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,IAAI,EAAE,UAAU;KACjB,CAAC,CAAC;IAEH,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,oBAAoB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;IAEtE,OAAO;QACL,QAAQ,EAAE,qBAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KAChE,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,OAAgC,EAChC,QAA+B;IAE/B,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,aAAa,CAAC;QAC1C,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG;QACxB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,IAAI,EAAE,KAAK;KACZ,CAAC,CAAC;IAEH,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IACjE,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,iCAAiC,CAAC,CAAC;IAE/D,OAAO;QACL,QAAQ,EAAE,qBAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KAChE,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,cAAc,CAC3B,OAAgC,EAChC,QAA+B;IAE/B,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,aAAa,CAAC;QAC1C,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG;QACxB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,IAAI,EAAE,MAAM;KACb,CAAC,CAAC;IAEH,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAElE,OAAO;QACL,QAAQ,EAAE,qBAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KAChE,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,iBAAiB,CAC9B,OAAgC,EAChC,QAA+B;IAE/B,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,aAAa,CAAC;QAC1C,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG;QACxB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,IAAI,EAAE,SAAS;KAChB,CAAC,CAAC;IAEH,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,oBAAoB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;IAErE,OAAO;QACL,QAAQ,EAAE,qBAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KAChE,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAC3B,WAA8B,EAC9B,MAA4B;IAE5B,MAAM,KAAK,GAAG;QACZ,UAAU,WAAW,EAAE;QACvB,WAAW,MAAM,CAAC,UAAU,EAAE;QAC9B,WAAW,MAAM,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE;QACvF,gBAAgB,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE;QACxF,EAAE;QACF,cAAc;KACf,CAAC;IAEF,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvB,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;YAC5C,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,qBAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAC7D,MAAM,YAAY,GAAG,uBAAuB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAEjE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,YAAY,UAAU,cAAc,YAAY,aAAa,CAAC,CAAC;IAC1E,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,oBAAoB,CAAC,UAA4B;IACxD,OAAO,OAAO,UAAU,CAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,UAAU,CAAC,IAAI,KAAK,UAAU,CAAC,OAAO,EAAE,CAAC;AAC9F,CAAC;AAED,SAAS,oBAAoB,CAAC,WAA8B,EAAE,KAAc;IAC1E,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,CAAC,wBAAwB,WAAW,KAAK,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5E,CAAC;AAED,SAAS,WAAW,CAAC,KAAa;IAChC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,MAAM,CAAC;AAClE,CAAC","sourcesContent":["import type {\n AnkhCapabilityId,\n AnkhCommandDescriptor,\n} from \"@ankhorage/contracts/cli\";\n\nimport type { DoctorAnalysisResult, DoctorTargetMode } from \"./analysis.js\";\nimport { analyzeDoctorTarget } from \"./analysis.js\";\nimport {\n countErrorDiagnostics,\n countWarningDiagnostics,\n type DoctorDiagnostic,\n} from \"./diagnostics.js\";\nimport { DOCTOR_CAPABILITIES, DOCTOR_COMMAND_CATEGORY } from \"./packageMetadata.js\";\nimport type { DoctorCommandContext, DoctorCommandRunResult } from \"./commandContext.js\";\n\ntype DoctorCommandName = \"fix\" | \"package\" | \"repo\" | \"validate\";\n\ninterface DoctorCommandRunRequest {\n readonly context: DoctorCommandContext;\n readonly inputPath?: string;\n}\n\ntype DoctorCommandImplementation = (\n request: DoctorCommandRunRequest,\n services: DoctorCommandServices,\n) => Promise<DoctorCommandRunResult>;\n\nexport interface DoctorCommandDefinition {\n readonly capability: AnkhCapabilityId;\n readonly mode: DoctorTargetMode;\n readonly path: readonly [DoctorCommandName];\n readonly standaloneName: DoctorCommandName;\n readonly summary: string;\n readonly run: DoctorCommandImplementation;\n}\n\nexport interface DoctorCommandInvocation {\n readonly argv: readonly string[];\n readonly command: DoctorCommandDefinition;\n readonly context: DoctorCommandContext;\n}\n\nexport interface DoctorCommandServices {\n readonly analyzeTarget: typeof analyzeDoctorTarget;\n}\n\nexport interface RunDoctorCommandOptions {\n readonly runCommandImpl?: RunDoctorCommandImpl;\n readonly services?: Partial<DoctorCommandServices>;\n}\n\nexport type RunDoctorCommandImpl = (\n request: DoctorCommandInvocation,\n options?: RunDoctorCommandOptions,\n) => Promise<DoctorCommandRunResult>;\n\nconst COMMAND_CAPABILITIES = {\n validate: DOCTOR_CAPABILITIES[0],\n fix: DOCTOR_CAPABILITIES[1],\n repo: DOCTOR_CAPABILITIES[2],\n package: DOCTOR_CAPABILITIES[3],\n} as const satisfies Record<DoctorCommandName, AnkhCapabilityId>;\n\nexport const DOCTOR_COMMANDS = [\n {\n standaloneName: \"validate\",\n path: [\"validate\"],\n capability: COMMAND_CAPABILITIES.validate,\n mode: \"validate\",\n summary: \"Auto-detect lightweight repo and package diagnostics for a local path.\",\n run: runValidateCommand,\n },\n {\n standaloneName: \"fix\",\n path: [\"fix\"],\n capability: COMMAND_CAPABILITIES.fix,\n mode: \"fix\",\n summary: \"Run the same lightweight checks and report that no automatic fixes exist yet.\",\n run: runFixCommand,\n },\n {\n standaloneName: \"repo\",\n path: [\"repo\"],\n capability: COMMAND_CAPABILITIES.repo,\n mode: \"repo\",\n summary: \"Force repo-light diagnostics for a repo/workspace-root candidate path.\",\n run: runRepoCommand,\n },\n {\n standaloneName: \"package\",\n path: [\"package\"],\n capability: COMMAND_CAPABILITIES.package,\n mode: \"package\",\n summary: \"Force package-light diagnostics for a directory containing package.json.\",\n run: runPackageCommand,\n },\n] as const satisfies readonly DoctorCommandDefinition[];\n\nexport async function runDoctorCommand(\n request: DoctorCommandInvocation,\n options: RunDoctorCommandOptions = {},\n): Promise<DoctorCommandRunResult> {\n const services = createDoctorCommandServices(options.services);\n\n try {\n const parsedArgs = parseCommandArguments(request.command, request.argv);\n if (parsedArgs.kind === \"help\") {\n request.context.writeStdout(renderCommandHelp(request.command));\n return { exitCode: 0 };\n }\n\n return await request.command.run(\n {\n context: request.context,\n inputPath: parsedArgs.inputPath,\n },\n services,\n );\n } catch (error) {\n request.context.writeStderr(\n renderCommandFailure(request.command.standaloneName, error),\n );\n return { exitCode: 1 };\n }\n}\n\nexport function createProviderCommandDescriptors(): readonly AnkhCommandDescriptor[] {\n return DOCTOR_COMMANDS.map((command) => ({\n capability: command.capability,\n path: command.path,\n summary: command.summary,\n }));\n}\n\nexport function findDoctorCommandByStandaloneName(\n value: string,\n): DoctorCommandDefinition | null {\n return DOCTOR_COMMANDS.find((command) => command.standaloneName === value) ?? null;\n}\n\nexport function renderRootHelp(version: string): string {\n const commandLines = DOCTOR_COMMANDS.map(\n (command) => ` ${command.standaloneName.padEnd(8, \" \")} ${command.summary}`,\n ).join(\"\\n\");\n\n return [\n `@ankhorage/doctor v${version}`,\n \"\",\n \"Usage:\",\n \" ankhorage-doctor <command> [path]\",\n ` ankh ${DOCTOR_COMMAND_CATEGORY} <command> [path]`,\n \"\",\n \"Commands:\",\n commandLines,\n \"\",\n \"Path resolution:\",\n \" Pass [path], or omit it to validate the current working directory.\",\n \"\",\n ].join(\"\\n\");\n}\n\nexport function renderUnknownCommand(value: string): string {\n return [\n `Unknown doctor command: ${value}`,\n \"\",\n \"Run ankhorage-doctor --help\",\n \"\",\n ].join(\"\\n\");\n}\n\nfunction renderCommandHelp(command: DoctorCommandDefinition): string {\n return [\n command.summary,\n \"\",\n \"Usage:\",\n ` ankhorage-doctor ${command.standaloneName} [path]`,\n ` ankh ${DOCTOR_COMMAND_CATEGORY} ${command.path.join(\" \")} [path]`,\n \"\",\n \"Path resolution:\",\n \" Pass [path], or omit it to validate the current working directory.\",\n \"\",\n ].join(\"\\n\");\n}\n\nfunction createDoctorCommandServices(\n overrides: Partial<DoctorCommandServices> = {},\n): DoctorCommandServices {\n return {\n analyzeTarget: overrides.analyzeTarget ?? analyzeDoctorTarget,\n };\n}\n\nfunction parseCommandArguments(\n command: DoctorCommandDefinition,\n argv: readonly string[],\n): { readonly kind: \"help\" } | { readonly kind: \"run\"; readonly inputPath?: string } {\n const firstArg = argv[0];\n\n if (argv.length === 1 && firstArg !== undefined && isHelpToken(firstArg)) {\n return { kind: \"help\" };\n }\n\n if (argv.length > 1) {\n throw new Error(`Doctor ${command.standaloneName} accepts at most one path argument.`);\n }\n\n return {\n kind: \"run\",\n inputPath: firstArg,\n };\n}\n\nasync function runValidateCommand(\n request: DoctorCommandRunRequest,\n services: DoctorCommandServices,\n): Promise<DoctorCommandRunResult> {\n const result = await services.analyzeTarget({\n cwd: request.context.cwd,\n inputPath: request.inputPath,\n mode: \"validate\",\n });\n\n request.context.writeStdout(renderAnalysisReport(\"validate\", result));\n\n return {\n exitCode: countErrorDiagnostics(result.diagnostics) > 0 ? 1 : 0,\n };\n}\n\nasync function runFixCommand(\n request: DoctorCommandRunRequest,\n services: DoctorCommandServices,\n): Promise<DoctorCommandRunResult> {\n const result = await services.analyzeTarget({\n cwd: request.context.cwd,\n inputPath: request.inputPath,\n mode: \"fix\",\n });\n\n request.context.writeStdout(renderAnalysisReport(\"fix\", result));\n request.context.writeStdout(\"No automatic fixes available.\\n\");\n\n return {\n exitCode: countErrorDiagnostics(result.diagnostics) > 0 ? 1 : 0,\n };\n}\n\nasync function runRepoCommand(\n request: DoctorCommandRunRequest,\n services: DoctorCommandServices,\n): Promise<DoctorCommandRunResult> {\n const result = await services.analyzeTarget({\n cwd: request.context.cwd,\n inputPath: request.inputPath,\n mode: \"repo\",\n });\n\n request.context.writeStdout(renderAnalysisReport(\"repo\", result));\n\n return {\n exitCode: countErrorDiagnostics(result.diagnostics) > 0 ? 1 : 0,\n };\n}\n\nasync function runPackageCommand(\n request: DoctorCommandRunRequest,\n services: DoctorCommandServices,\n): Promise<DoctorCommandRunResult> {\n const result = await services.analyzeTarget({\n cwd: request.context.cwd,\n inputPath: request.inputPath,\n mode: \"package\",\n });\n\n request.context.writeStdout(renderAnalysisReport(\"package\", result));\n\n return {\n exitCode: countErrorDiagnostics(result.diagnostics) > 0 ? 1 : 0,\n };\n}\n\nfunction renderAnalysisReport(\n commandName: DoctorCommandName,\n result: DoctorAnalysisResult,\n): string {\n const lines = [\n `doctor ${commandName}`,\n `target: ${result.targetPath}`,\n `checks: ${result.appliedChecks.length > 0 ? result.appliedChecks.join(\", \") : \"none\"}`,\n `repoMarkers: ${result.repoMarkers.length > 0 ? result.repoMarkers.join(\", \") : \"none\"}`,\n \"\",\n \"Diagnostics:\",\n ];\n\n if (result.diagnostics.length === 0) {\n lines.push(\" none\");\n } else {\n for (const diagnostic of result.diagnostics) {\n lines.push(renderDiagnosticLine(diagnostic));\n }\n }\n\n const errorCount = countErrorDiagnostics(result.diagnostics);\n const warningCount = countWarningDiagnostics(result.diagnostics);\n\n lines.push(\"\");\n lines.push(`Summary: ${errorCount} error(s), ${warningCount} warning(s)`);\n lines.push(\"\");\n\n return lines.join(\"\\n\");\n}\n\nfunction renderDiagnosticLine(diagnostic: DoctorDiagnostic): string {\n return ` - ${diagnostic.severity.toUpperCase()} ${diagnostic.code}: ${diagnostic.message}`;\n}\n\nfunction renderCommandFailure(commandName: DoctorCommandName, error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n return [`Failed to run doctor ${commandName}: ${message}`, \"\"].join(\"\\n\");\n}\n\nfunction isHelpToken(value: string): boolean {\n return value === \"--help\" || value === \"-h\" || value === \"help\";\n}\n"]}
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AnkhCapabilityId, AnkhCommandDescriptor } from '@ankhorage/contracts/cli';\n\nimport type { DoctorAnalysisResult, DoctorTargetMode } from './analysis.js';\nimport { analyzeDoctorTarget } from './analysis.js';\nimport type { DoctorCommandContext, DoctorCommandRunResult } from './commandContext.js';\nimport {\n countErrorDiagnostics,\n countWarningDiagnostics,\n type DoctorDiagnostic,\n} from './diagnostics.js';\nimport { DOCTOR_CAPABILITIES, DOCTOR_COMMAND_CATEGORY } from './packageMetadata.js';\n\ntype DoctorCommandName = 'fix' | 'package' | 'repo' | 'validate';\n\ninterface DoctorCommandRunRequest {\n readonly context: DoctorCommandContext;\n readonly inputPath?: string;\n}\n\ntype DoctorCommandImplementation = (\n request: DoctorCommandRunRequest,\n services: DoctorCommandServices,\n) => Promise<DoctorCommandRunResult>;\n\nexport interface DoctorCommandDefinition {\n readonly capability: AnkhCapabilityId;\n readonly mode: DoctorTargetMode;\n readonly path: readonly [DoctorCommandName];\n readonly standaloneName: DoctorCommandName;\n readonly summary: string;\n readonly run: DoctorCommandImplementation;\n}\n\nexport interface DoctorCommandInvocation {\n readonly argv: readonly string[];\n readonly command: DoctorCommandDefinition;\n readonly context: DoctorCommandContext;\n}\n\nexport interface DoctorCommandServices {\n readonly analyzeTarget: typeof analyzeDoctorTarget;\n}\n\nexport interface RunDoctorCommandOptions {\n readonly runCommandImpl?: RunDoctorCommandImpl;\n readonly services?: Partial<DoctorCommandServices>;\n}\n\nexport type RunDoctorCommandImpl = (\n request: DoctorCommandInvocation,\n options?: RunDoctorCommandOptions,\n) => Promise<DoctorCommandRunResult>;\n\nconst COMMAND_CAPABILITIES = {\n validate: DOCTOR_CAPABILITIES[0],\n fix: DOCTOR_CAPABILITIES[1],\n repo: DOCTOR_CAPABILITIES[2],\n package: DOCTOR_CAPABILITIES[3],\n} as const satisfies Record<DoctorCommandName, AnkhCapabilityId>;\n\nexport const DOCTOR_COMMANDS = [\n {\n standaloneName: 'validate',\n path: ['validate'],\n capability: COMMAND_CAPABILITIES.validate,\n mode: 'validate',\n summary: 'Auto-detect lightweight repo and package diagnostics for a local path.',\n run: runValidateCommand,\n },\n {\n standaloneName: 'fix',\n path: ['fix'],\n capability: COMMAND_CAPABILITIES.fix,\n mode: 'fix',\n summary: 'Run the same lightweight checks and report that no automatic fixes exist yet.',\n run: runFixCommand,\n },\n {\n standaloneName: 'repo',\n path: ['repo'],\n capability: COMMAND_CAPABILITIES.repo,\n mode: 'repo',\n summary: 'Force repo-light diagnostics for a repo/workspace-root candidate path.',\n run: runRepoCommand,\n },\n {\n standaloneName: 'package',\n path: ['package'],\n capability: COMMAND_CAPABILITIES.package,\n mode: 'package',\n summary: 'Force package-light diagnostics for a directory containing package.json.',\n run: runPackageCommand,\n },\n] as const satisfies readonly DoctorCommandDefinition[];\n\nexport async function runDoctorCommand(\n request: DoctorCommandInvocation,\n options: RunDoctorCommandOptions = {},\n): Promise<DoctorCommandRunResult> {\n const services = createDoctorCommandServices(options.services);\n\n try {\n const parsedArgs = parseCommandArguments(request.command, request.argv);\n if (parsedArgs.kind === 'help') {\n request.context.writeStdout(renderCommandHelp(request.command));\n return { exitCode: 0 };\n }\n\n return await request.command.run(\n {\n context: request.context,\n inputPath: parsedArgs.inputPath,\n },\n services,\n );\n } catch (error) {\n request.context.writeStderr(renderCommandFailure(request.command.standaloneName, error));\n return { exitCode: 1 };\n }\n}\n\nexport function createProviderCommandDescriptors(): readonly AnkhCommandDescriptor[] {\n return DOCTOR_COMMANDS.map((command) => ({\n capability: command.capability,\n path: command.path,\n summary: command.summary,\n }));\n}\n\nexport function findDoctorCommandByStandaloneName(value: string): DoctorCommandDefinition | null {\n return DOCTOR_COMMANDS.find((command) => command.standaloneName === value) ?? null;\n}\n\nexport function renderRootHelp(version: string): string {\n const commandLines = DOCTOR_COMMANDS.map(\n (command) => ` ${command.standaloneName.padEnd(8, ' ')} ${command.summary}`,\n ).join('\\n');\n\n return [\n `@ankhorage/doctor v${version}`,\n '',\n 'Usage:',\n ' ankhorage-doctor <command> [path]',\n ` ankh ${DOCTOR_COMMAND_CATEGORY} <command> [path]`,\n '',\n 'Commands:',\n commandLines,\n '',\n 'Path resolution:',\n ' Pass [path], or omit it to validate the current working directory.',\n '',\n ].join('\\n');\n}\n\nexport function renderUnknownCommand(value: string): string {\n return [`Unknown doctor command: ${value}`, '', 'Run ankhorage-doctor --help', ''].join('\\n');\n}\n\nfunction renderCommandHelp(command: DoctorCommandDefinition): string {\n return [\n command.summary,\n '',\n 'Usage:',\n ` ankhorage-doctor ${command.standaloneName} [path]`,\n ` ankh ${DOCTOR_COMMAND_CATEGORY} ${command.path.join(' ')} [path]`,\n '',\n 'Path resolution:',\n ' Pass [path], or omit it to validate the current working directory.',\n '',\n ].join('\\n');\n}\n\nfunction createDoctorCommandServices(\n overrides: Partial<DoctorCommandServices> = {},\n): DoctorCommandServices {\n return {\n analyzeTarget: overrides.analyzeTarget ?? analyzeDoctorTarget,\n };\n}\n\nfunction parseCommandArguments(\n command: DoctorCommandDefinition,\n argv: readonly string[],\n): { readonly kind: 'help' } | { readonly kind: 'run'; readonly inputPath?: string } {\n const [firstArg] = argv;\n\n if (argv.length === 1 && firstArg !== undefined && isHelpToken(firstArg)) {\n return { kind: 'help' };\n }\n\n if (argv.length > 1) {\n throw new Error(`Doctor ${command.standaloneName} accepts at most one path argument.`);\n }\n\n return {\n kind: 'run',\n inputPath: firstArg,\n };\n}\n\nasync function runValidateCommand(\n request: DoctorCommandRunRequest,\n services: DoctorCommandServices,\n): Promise<DoctorCommandRunResult> {\n const result = await services.analyzeTarget({\n cwd: request.context.cwd,\n inputPath: request.inputPath,\n mode: 'validate',\n });\n\n request.context.writeStdout(renderAnalysisReport('validate', result));\n\n return {\n exitCode: countErrorDiagnostics(result.diagnostics) > 0 ? 1 : 0,\n };\n}\n\nasync function runFixCommand(\n request: DoctorCommandRunRequest,\n services: DoctorCommandServices,\n): Promise<DoctorCommandRunResult> {\n const result = await services.analyzeTarget({\n cwd: request.context.cwd,\n inputPath: request.inputPath,\n mode: 'fix',\n });\n\n request.context.writeStdout(renderAnalysisReport('fix', result));\n request.context.writeStdout('No automatic fixes available.\\n');\n\n return {\n exitCode: countErrorDiagnostics(result.diagnostics) > 0 ? 1 : 0,\n };\n}\n\nasync function runRepoCommand(\n request: DoctorCommandRunRequest,\n services: DoctorCommandServices,\n): Promise<DoctorCommandRunResult> {\n const result = await services.analyzeTarget({\n cwd: request.context.cwd,\n inputPath: request.inputPath,\n mode: 'repo',\n });\n\n request.context.writeStdout(renderAnalysisReport('repo', result));\n\n return {\n exitCode: countErrorDiagnostics(result.diagnostics) > 0 ? 1 : 0,\n };\n}\n\nasync function runPackageCommand(\n request: DoctorCommandRunRequest,\n services: DoctorCommandServices,\n): Promise<DoctorCommandRunResult> {\n const result = await services.analyzeTarget({\n cwd: request.context.cwd,\n inputPath: request.inputPath,\n mode: 'package',\n });\n\n request.context.writeStdout(renderAnalysisReport('package', result));\n\n return {\n exitCode: countErrorDiagnostics(result.diagnostics) > 0 ? 1 : 0,\n };\n}\n\nfunction renderAnalysisReport(\n commandName: DoctorCommandName,\n result: DoctorAnalysisResult,\n): string {\n const lines = [\n `doctor ${commandName}`,\n `target: ${result.targetPath}`,\n `checks: ${result.appliedChecks.length > 0 ? result.appliedChecks.join(', ') : 'none'}`,\n `repoMarkers: ${result.repoMarkers.length > 0 ? result.repoMarkers.join(', ') : 'none'}`,\n '',\n 'Diagnostics:',\n ];\n\n if (result.diagnostics.length === 0) {\n lines.push(' none');\n } else {\n for (const diagnostic of result.diagnostics) {\n lines.push(renderDiagnosticLine(diagnostic));\n }\n }\n\n const errorCount = countErrorDiagnostics(result.diagnostics);\n const warningCount = countWarningDiagnostics(result.diagnostics);\n\n lines.push('');\n lines.push(`Summary: ${errorCount} error(s), ${warningCount} warning(s)`);\n lines.push('');\n\n return lines.join('\\n');\n}\n\nfunction renderDiagnosticLine(diagnostic: DoctorDiagnostic): string {\n return ` - ${diagnostic.severity.toUpperCase()} ${diagnostic.code}: ${diagnostic.message}`;\n}\n\nfunction renderCommandFailure(commandName: DoctorCommandName, error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n return [`Failed to run doctor ${commandName}: ${message}`, ''].join('\\n');\n}\n\nfunction isHelpToken(value: string): boolean {\n return value === '--help' || value === '-h' || value === 'help';\n}\n"]}
@@ -1,5 +1,5 @@
1
- export type DoctorDiagnosticCode = "invalid-ankh-metadata" | "invalid-package-json" | "missing-changelog" | "missing-changeset-directory" | "missing-license" | "missing-readme" | "missing-workflows-directory" | "package-json-missing" | "package-name-missing" | "package-type-missing" | "package-version-missing" | "repo-markers-missing" | "target-not-directory" | "target-not-found" | "unsupported-target";
2
- export type DoctorDiagnosticSeverity = "error" | "warning";
1
+ export type DoctorDiagnosticCode = 'invalid-ankh-metadata' | 'invalid-package-json' | 'missing-changelog' | 'missing-changeset-directory' | 'missing-license' | 'missing-readme' | 'missing-workflows-directory' | 'package-json-missing' | 'package-name-missing' | 'package-type-missing' | 'package-version-missing' | 'repo-markers-missing' | 'target-not-directory' | 'target-not-found' | 'unsupported-target';
2
+ export type DoctorDiagnosticSeverity = 'error' | 'warning';
3
3
  export interface DoctorDiagnostic {
4
4
  readonly code: DoctorDiagnosticCode;
5
5
  readonly message: string;
@@ -1 +1 @@
1
- {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAC5B,uBAAuB,GACvB,sBAAsB,GACtB,mBAAmB,GACnB,6BAA6B,GAC7B,iBAAiB,GACjB,gBAAgB,GAChB,6BAA6B,GAC7B,sBAAsB,GACtB,sBAAsB,GACtB,sBAAsB,GACtB,yBAAyB,GACzB,sBAAsB,GACtB,sBAAsB,GACtB,kBAAkB,GAClB,oBAAoB,CAAC;AAEzB,MAAM,MAAM,wBAAwB,GAAG,OAAO,GAAG,SAAS,CAAC;AAE3D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,wBAAwB,CAAC;CAC7C;AAED,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,SAAS,gBAAgB,EAAE,GACvC,MAAM,CAGR;AAED,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,SAAS,gBAAgB,EAAE,GACvC,MAAM,CAGR"}
1
+ {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAC5B,uBAAuB,GACvB,sBAAsB,GACtB,mBAAmB,GACnB,6BAA6B,GAC7B,iBAAiB,GACjB,gBAAgB,GAChB,6BAA6B,GAC7B,sBAAsB,GACtB,sBAAsB,GACtB,sBAAsB,GACtB,yBAAyB,GACzB,sBAAsB,GACtB,sBAAsB,GACtB,kBAAkB,GAClB,oBAAoB,CAAC;AAEzB,MAAM,MAAM,wBAAwB,GAAG,OAAO,GAAG,SAAS,CAAC;AAE3D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,wBAAwB,CAAC;CAC7C;AAED,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,SAAS,gBAAgB,EAAE,GAAG,MAAM,CAEtF;AAED,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,SAAS,gBAAgB,EAAE,GAAG,MAAM,CAExF"}
@@ -1,9 +1,7 @@
1
1
  export function countErrorDiagnostics(diagnostics) {
2
- return diagnostics.filter((diagnostic) => diagnostic.severity === "error")
3
- .length;
2
+ return diagnostics.filter((diagnostic) => diagnostic.severity === 'error').length;
4
3
  }
5
4
  export function countWarningDiagnostics(diagnostics) {
6
- return diagnostics.filter((diagnostic) => diagnostic.severity === "warning")
7
- .length;
5
+ return diagnostics.filter((diagnostic) => diagnostic.severity === 'warning').length;
8
6
  }
9
7
  //# sourceMappingURL=diagnostics.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AA0BA,MAAM,UAAU,qBAAqB,CACnC,WAAwC;IAExC,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,KAAK,OAAO,CAAC;SACvE,MAAM,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,WAAwC;IAExC,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,KAAK,SAAS,CAAC;SACzE,MAAM,CAAC;AACZ,CAAC","sourcesContent":["export type DoctorDiagnosticCode =\n | \"invalid-ankh-metadata\"\n | \"invalid-package-json\"\n | \"missing-changelog\"\n | \"missing-changeset-directory\"\n | \"missing-license\"\n | \"missing-readme\"\n | \"missing-workflows-directory\"\n | \"package-json-missing\"\n | \"package-name-missing\"\n | \"package-type-missing\"\n | \"package-version-missing\"\n | \"repo-markers-missing\"\n | \"target-not-directory\"\n | \"target-not-found\"\n | \"unsupported-target\";\n\nexport type DoctorDiagnosticSeverity = \"error\" | \"warning\";\n\nexport interface DoctorDiagnostic {\n readonly code: DoctorDiagnosticCode;\n readonly message: string;\n readonly path: string;\n readonly severity: DoctorDiagnosticSeverity;\n}\n\nexport function countErrorDiagnostics(\n diagnostics: readonly DoctorDiagnostic[],\n): number {\n return diagnostics.filter((diagnostic) => diagnostic.severity === \"error\")\n .length;\n}\n\nexport function countWarningDiagnostics(\n diagnostics: readonly DoctorDiagnostic[],\n): number {\n return diagnostics.filter((diagnostic) => diagnostic.severity === \"warning\")\n .length;\n}\n"]}
1
+ {"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AA0BA,MAAM,UAAU,qBAAqB,CAAC,WAAwC;IAC5E,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,MAAM,CAAC;AACpF,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,WAAwC;IAC9E,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;AACtF,CAAC","sourcesContent":["export type DoctorDiagnosticCode =\n | 'invalid-ankh-metadata'\n | 'invalid-package-json'\n | 'missing-changelog'\n | 'missing-changeset-directory'\n | 'missing-license'\n | 'missing-readme'\n | 'missing-workflows-directory'\n | 'package-json-missing'\n | 'package-name-missing'\n | 'package-type-missing'\n | 'package-version-missing'\n | 'repo-markers-missing'\n | 'target-not-directory'\n | 'target-not-found'\n | 'unsupported-target';\n\nexport type DoctorDiagnosticSeverity = 'error' | 'warning';\n\nexport interface DoctorDiagnostic {\n readonly code: DoctorDiagnosticCode;\n readonly message: string;\n readonly path: string;\n readonly severity: DoctorDiagnosticSeverity;\n}\n\nexport function countErrorDiagnostics(diagnostics: readonly DoctorDiagnostic[]): number {\n return diagnostics.filter((diagnostic) => diagnostic.severity === 'error').length;\n}\n\nexport function countWarningDiagnostics(diagnostics: readonly DoctorDiagnostic[]): number {\n return diagnostics.filter((diagnostic) => diagnostic.severity === 'warning').length;\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- export { runCli } from "./cli.js";
2
- export type { DoctorCommandContext, DoctorCommandRunResult } from "./commandContext.js";
3
- export { createDefaultCommandContext } from "./commandContext.js";
4
- export type { DoctorAnalysisRequest, DoctorAnalysisResult, DoctorTargetCheck, DoctorTargetMode, } from "./analysis.js";
5
- export { analyzeDoctorTarget } from "./analysis.js";
6
- export { createDoctorRuntimeProvider, type CreateDoctorRuntimeProviderOptions, } from "./ankh.provider.js";
7
- export type { DoctorDiagnostic, DoctorDiagnosticCode, DoctorDiagnosticSeverity, } from "./diagnostics.js";
8
- export { DOCTOR_CAPABILITIES, DOCTOR_COMMAND_CATEGORY, DOCTOR_PACKAGE_METADATA, DOCTOR_PACKAGE_NAME, DOCTOR_PACKAGE_VERSION, } from "./packageMetadata.js";
1
+ export type { DoctorAnalysisRequest, DoctorAnalysisResult, DoctorTargetCheck, DoctorTargetMode, } from './analysis.js';
2
+ export { analyzeDoctorTarget } from './analysis.js';
3
+ export { createDoctorRuntimeProvider, type CreateDoctorRuntimeProviderOptions, } from './ankh.provider.js';
4
+ export { runCli } from './cli.js';
5
+ export type { DoctorCommandContext, DoctorCommandRunResult } from './commandContext.js';
6
+ export { createDefaultCommandContext } from './commandContext.js';
7
+ export type { DoctorDiagnostic, DoctorDiagnosticCode, DoctorDiagnosticSeverity, } from './diagnostics.js';
8
+ export { DOCTOR_CAPABILITIES, DOCTOR_COMMAND_CATEGORY, DOCTOR_PACKAGE_METADATA, DOCTOR_PACKAGE_NAME, DOCTOR_PACKAGE_VERSION, } from './packageMetadata.js';
9
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AACxF,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAClE,YAAY,EACV,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EACL,2BAA2B,EAC3B,KAAK,kCAAkC,GACxC,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,gBAAgB,EAChB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,uBAAuB,EACvB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EACL,2BAA2B,EAC3B,KAAK,kCAAkC,GACxC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AACxF,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAClE,YAAY,EACV,gBAAgB,EAChB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,uBAAuB,EACvB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- export { runCli } from "./cli.js";
2
- export { createDefaultCommandContext } from "./commandContext.js";
3
- export { analyzeDoctorTarget } from "./analysis.js";
4
- export { createDoctorRuntimeProvider, } from "./ankh.provider.js";
5
- export { DOCTOR_CAPABILITIES, DOCTOR_COMMAND_CATEGORY, DOCTOR_PACKAGE_METADATA, DOCTOR_PACKAGE_NAME, DOCTOR_PACKAGE_VERSION, } from "./packageMetadata.js";
1
+ export { analyzeDoctorTarget } from './analysis.js';
2
+ export { createDoctorRuntimeProvider, } from './ankh.provider.js';
3
+ export { runCli } from './cli.js';
4
+ export { createDefaultCommandContext } from './commandContext.js';
5
+ export { DOCTOR_CAPABILITIES, DOCTOR_COMMAND_CATEGORY, DOCTOR_PACKAGE_METADATA, DOCTOR_PACKAGE_NAME, DOCTOR_PACKAGE_VERSION, } from './packageMetadata.js';
6
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAOlE,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EACL,2BAA2B,GAE5B,MAAM,oBAAoB,CAAC;AAM5B,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,uBAAuB,EACvB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC","sourcesContent":["export { runCli } from \"./cli.js\";\nexport type { DoctorCommandContext, DoctorCommandRunResult } from \"./commandContext.js\";\nexport { createDefaultCommandContext } from \"./commandContext.js\";\nexport type {\n DoctorAnalysisRequest,\n DoctorAnalysisResult,\n DoctorTargetCheck,\n DoctorTargetMode,\n} from \"./analysis.js\";\nexport { analyzeDoctorTarget } from \"./analysis.js\";\nexport {\n createDoctorRuntimeProvider,\n type CreateDoctorRuntimeProviderOptions,\n} from \"./ankh.provider.js\";\nexport type {\n DoctorDiagnostic,\n DoctorDiagnosticCode,\n DoctorDiagnosticSeverity,\n} from \"./diagnostics.js\";\nexport {\n DOCTOR_CAPABILITIES,\n DOCTOR_COMMAND_CATEGORY,\n DOCTOR_PACKAGE_METADATA,\n DOCTOR_PACKAGE_NAME,\n DOCTOR_PACKAGE_VERSION,\n} from \"./packageMetadata.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EACL,2BAA2B,GAE5B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAMlE,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,uBAAuB,EACvB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC","sourcesContent":["export type {\n DoctorAnalysisRequest,\n DoctorAnalysisResult,\n DoctorTargetCheck,\n DoctorTargetMode,\n} from './analysis.js';\nexport { analyzeDoctorTarget } from './analysis.js';\nexport {\n createDoctorRuntimeProvider,\n type CreateDoctorRuntimeProviderOptions,\n} from './ankh.provider.js';\nexport { runCli } from './cli.js';\nexport type { DoctorCommandContext, DoctorCommandRunResult } from './commandContext.js';\nexport { createDefaultCommandContext } from './commandContext.js';\nexport type {\n DoctorDiagnostic,\n DoctorDiagnosticCode,\n DoctorDiagnosticSeverity,\n} from './diagnostics.js';\nexport {\n DOCTOR_CAPABILITIES,\n DOCTOR_COMMAND_CATEGORY,\n DOCTOR_PACKAGE_METADATA,\n DOCTOR_PACKAGE_NAME,\n DOCTOR_PACKAGE_VERSION,\n} from './packageMetadata.js';\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"packageMetadata.d.ts","sourceRoot":"","sources":["../src/packageMetadata.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,mBAAmB,QAAmB,CAAC;AACpD,eAAO,MAAM,sBAAsB,QAAsB,CAAC;AAC1D,eAAO,MAAM,uBAAuB,UACa,CAAC;AAClD,eAAO,MAAM,mBAAmB,6EAKgB,CAAC;AAEjD,eAAO,MAAM,uBAAuB;;;;CAII,CAAC"}
1
+ {"version":3,"file":"packageMetadata.d.ts","sourceRoot":"","sources":["../src/packageMetadata.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,mBAAmB,QAAmB,CAAC;AACpD,eAAO,MAAM,sBAAsB,QAAsB,CAAC;AAC1D,eAAO,MAAM,uBAAuB,UAAkD,CAAC;AACvF,eAAO,MAAM,mBAAmB,6EAKgB,CAAC;AAEjD,eAAO,MAAM,uBAAuB;;;;CAII,CAAC"}
@@ -1,16 +1,16 @@
1
- import packageJson from "../package.json";
1
+ import packageJson from '../package.json';
2
2
  export const DOCTOR_PACKAGE_NAME = packageJson.name;
3
3
  export const DOCTOR_PACKAGE_VERSION = packageJson.version;
4
- export const DOCTOR_COMMAND_CATEGORY = "doctor";
4
+ export const DOCTOR_COMMAND_CATEGORY = 'doctor';
5
5
  export const DOCTOR_CAPABILITIES = [
6
- "doctor.validate",
7
- "doctor.fix",
8
- "doctor.repo",
9
- "doctor.package",
6
+ 'doctor.validate',
7
+ 'doctor.fix',
8
+ 'doctor.repo',
9
+ 'doctor.package',
10
10
  ];
11
11
  export const DOCTOR_PACKAGE_METADATA = {
12
12
  category: DOCTOR_COMMAND_CATEGORY,
13
- provider: "./dist/ankh.provider.js",
13
+ provider: './dist/ankh.provider.js',
14
14
  capabilities: DOCTOR_CAPABILITIES,
15
15
  };
16
16
  //# sourceMappingURL=packageMetadata.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageMetadata.js","sourceRoot":"","sources":["../src/packageMetadata.ts"],"names":[],"mappings":"AAMA,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAE1C,MAAM,CAAC,MAAM,mBAAmB,GAAG,WAAW,CAAC,IAAI,CAAC;AACpD,MAAM,CAAC,MAAM,sBAAsB,GAAG,WAAW,CAAC,OAAO,CAAC;AAC1D,MAAM,CAAC,MAAM,uBAAuB,GAClC,QAA+C,CAAC;AAClD,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,iBAAiB;IACjB,YAAY;IACZ,aAAa;IACb,gBAAgB;CAC8B,CAAC;AAEjD,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,QAAQ,EAAE,uBAAuB;IACjC,QAAQ,EAAE,yBAAyB;IACnC,YAAY,EAAE,mBAAmB;CACK,CAAC","sourcesContent":["import type {\n AnkhCapabilityId,\n AnkhCommandCategory,\n AnkhPackageMetadata,\n} from \"@ankhorage/contracts/cli\";\n\nimport packageJson from \"../package.json\";\n\nexport const DOCTOR_PACKAGE_NAME = packageJson.name;\nexport const DOCTOR_PACKAGE_VERSION = packageJson.version;\nexport const DOCTOR_COMMAND_CATEGORY =\n \"doctor\" as const satisfies AnkhCommandCategory;\nexport const DOCTOR_CAPABILITIES = [\n \"doctor.validate\",\n \"doctor.fix\",\n \"doctor.repo\",\n \"doctor.package\",\n] as const satisfies readonly AnkhCapabilityId[];\n\nexport const DOCTOR_PACKAGE_METADATA = {\n category: DOCTOR_COMMAND_CATEGORY,\n provider: \"./dist/ankh.provider.js\",\n capabilities: DOCTOR_CAPABILITIES,\n} as const satisfies AnkhPackageMetadata;\n"]}
1
+ {"version":3,"file":"packageMetadata.js","sourceRoot":"","sources":["../src/packageMetadata.ts"],"names":[],"mappings":"AAMA,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAE1C,MAAM,CAAC,MAAM,mBAAmB,GAAG,WAAW,CAAC,IAAI,CAAC;AACpD,MAAM,CAAC,MAAM,sBAAsB,GAAG,WAAW,CAAC,OAAO,CAAC;AAC1D,MAAM,CAAC,MAAM,uBAAuB,GAAG,QAA+C,CAAC;AACvF,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,iBAAiB;IACjB,YAAY;IACZ,aAAa;IACb,gBAAgB;CAC8B,CAAC;AAEjD,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,QAAQ,EAAE,uBAAuB;IACjC,QAAQ,EAAE,yBAAyB;IACnC,YAAY,EAAE,mBAAmB;CACK,CAAC","sourcesContent":["import type {\n AnkhCapabilityId,\n AnkhCommandCategory,\n AnkhPackageMetadata,\n} from '@ankhorage/contracts/cli';\n\nimport packageJson from '../package.json';\n\nexport const DOCTOR_PACKAGE_NAME = packageJson.name;\nexport const DOCTOR_PACKAGE_VERSION = packageJson.version;\nexport const DOCTOR_COMMAND_CATEGORY = 'doctor' as const satisfies AnkhCommandCategory;\nexport const DOCTOR_CAPABILITIES = [\n 'doctor.validate',\n 'doctor.fix',\n 'doctor.repo',\n 'doctor.package',\n] as const satisfies readonly AnkhCapabilityId[];\n\nexport const DOCTOR_PACKAGE_METADATA = {\n category: DOCTOR_COMMAND_CATEGORY,\n provider: './dist/ankh.provider.js',\n capabilities: DOCTOR_CAPABILITIES,\n} as const satisfies AnkhPackageMetadata;\n"]}
@@ -1,4 +1,4 @@
1
- import { runCli } from "./cli.js";
1
+ import { runCli } from './cli.js';
2
2
  /***
3
3
  * Provider and CLI surface
4
4
  *
@@ -28,5 +28,5 @@ import { runCli } from "./cli.js";
28
28
  *
29
29
  * @usage
30
30
  */
31
- await runCli(["--help"]);
31
+ await runCli(['--help']);
32
32
  //# sourceMappingURL=readme-usage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"readme-usage.js","sourceRoot":"","sources":["../src/readme-usage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC","sourcesContent":["import { runCli } from \"./cli.js\";\n\n/***\n * Provider and CLI surface\n *\n * `@ankhorage/doctor` is the repo/package compliance provider for Ankhorage.\n *\n * The same shared command implementation backs both:\n *\n * - `ankh doctor ...`\n * - `bunx @ankhorage/doctor ...`\n *\n * Current command surface:\n *\n * - `validate`\n * - `fix`\n * - `repo`\n * - `package`\n *\n * `doctor#1` intentionally stays lightweight:\n *\n * - path-aware local repo/package diagnostics are implemented now\n * - GitHub checks, CI checks, full policy enforcement, and autofix rules are deferred\n *\n * Path handling:\n *\n * - pass `[path]`, or\n * - omit it to inspect the current working directory\n *\n * @usage\n */\nawait runCli([\"--help\"]);\n"]}
1
+ {"version":3,"file":"readme-usage.js","sourceRoot":"","sources":["../src/readme-usage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC","sourcesContent":["import { runCli } from './cli.js';\n\n/***\n * Provider and CLI surface\n *\n * `@ankhorage/doctor` is the repo/package compliance provider for Ankhorage.\n *\n * The same shared command implementation backs both:\n *\n * - `ankh doctor ...`\n * - `bunx @ankhorage/doctor ...`\n *\n * Current command surface:\n *\n * - `validate`\n * - `fix`\n * - `repo`\n * - `package`\n *\n * `doctor#1` intentionally stays lightweight:\n *\n * - path-aware local repo/package diagnostics are implemented now\n * - GitHub checks, CI checks, full policy enforcement, and autofix rules are deferred\n *\n * Path handling:\n *\n * - pass `[path]`, or\n * - omit it to inspect the current working directory\n *\n * @usage\n */\nawait runCli(['--help']);\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ankhorage/doctor",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Executable Ankh provider and standalone CLI for lightweight repo and package compliance diagnostics.",
5
5
  "license": "MIT",
6
6
  "publishConfig": {