@ankhorage/doctor 0.2.1 → 0.3.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 +12 -0
- package/README.md +12 -4
- package/dist/analysis.d.ts +18 -1
- package/dist/analysis.d.ts.map +1 -1
- package/dist/analysis.js +786 -57
- package/dist/analysis.js.map +1 -1
- package/dist/{ankh.provider.d.ts → cli/index.d.ts} +2 -2
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/{ankh.provider.js → cli/index.js} +16 -15
- package/dist/cli/index.js.map +1 -0
- package/dist/commands.d.ts +2 -2
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +19 -4
- package/dist/commands.js.map +1 -1
- package/dist/diagnostics.d.ts +5 -1
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/packageMetadata.d.ts +1 -1
- package/dist/packageMetadata.js +1 -1
- package/dist/packageMetadata.js.map +1 -1
- package/dist/readme-usage.js +11 -3
- package/dist/readme-usage.js.map +1 -1
- package/package.json +7 -2
- package/src/analysis.ts +1082 -145
- package/src/{ankh.provider.ts → cli/index.ts} +12 -9
- package/src/commands.ts +22 -5
- package/src/diagnostics.ts +67 -10
- package/src/index.ts +7 -2
- package/src/packageMetadata.ts +1 -1
- package/src/readme-usage.ts +11 -3
- package/dist/ankh.provider.d.ts.map +0 -1
- package/dist/ankh.provider.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnkhRuntimeCommandProvider } from '@ankhorage/ankh';
|
|
1
|
+
import type { AnkhCommandHandler, AnkhRuntimeCommandProvider } from '@ankhorage/ankh';
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
createProviderCommandDescriptors,
|
|
@@ -6,13 +6,13 @@ import {
|
|
|
6
6
|
type DoctorCommandServices,
|
|
7
7
|
runDoctorCommand,
|
|
8
8
|
type RunDoctorCommandImpl,
|
|
9
|
-
} from '
|
|
9
|
+
} from '../commands.js';
|
|
10
10
|
import {
|
|
11
11
|
DOCTOR_CAPABILITIES,
|
|
12
12
|
DOCTOR_COMMAND_CATEGORY,
|
|
13
13
|
DOCTOR_PACKAGE_NAME,
|
|
14
14
|
DOCTOR_PACKAGE_VERSION,
|
|
15
|
-
} from '
|
|
15
|
+
} from '../packageMetadata.js';
|
|
16
16
|
|
|
17
17
|
export interface CreateDoctorRuntimeProviderOptions {
|
|
18
18
|
readonly runCommandImpl?: RunDoctorCommandImpl;
|
|
@@ -30,10 +30,9 @@ export function createDoctorRuntimeProvider(
|
|
|
30
30
|
version: DOCTOR_PACKAGE_VERSION,
|
|
31
31
|
capabilities: [...DOCTOR_CAPABILITIES],
|
|
32
32
|
commands: createProviderCommandDescriptors(),
|
|
33
|
-
handlers: DOCTOR_COMMANDS.map((command) =>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return runCommandImpl(
|
|
33
|
+
handlers: DOCTOR_COMMANDS.map((command) => {
|
|
34
|
+
const handler: AnkhCommandHandler = (request) =>
|
|
35
|
+
runCommandImpl(
|
|
37
36
|
{
|
|
38
37
|
argv: request.argv,
|
|
39
38
|
command,
|
|
@@ -43,8 +42,12 @@ export function createDoctorRuntimeProvider(
|
|
|
43
42
|
services: options.services,
|
|
44
43
|
},
|
|
45
44
|
);
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
path: command.path,
|
|
48
|
+
handler,
|
|
49
|
+
};
|
|
50
|
+
}),
|
|
48
51
|
} satisfies AnkhRuntimeCommandProvider;
|
|
49
52
|
}
|
|
50
53
|
|
package/src/commands.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AnkhCapabilityId, AnkhCommandDescriptor } from '@ankhorage/contracts/cli';
|
|
2
2
|
|
|
3
|
-
import type { DoctorAnalysisResult, DoctorTargetMode } from './analysis.js';
|
|
3
|
+
import type { DoctorAnalysisResult, DoctorPlannedChange, DoctorTargetMode } from './analysis.js';
|
|
4
4
|
import { analyzeDoctorTarget } from './analysis.js';
|
|
5
5
|
import type { DoctorCommandContext, DoctorCommandRunResult } from './commandContext.js';
|
|
6
6
|
import {
|
|
@@ -64,7 +64,7 @@ export const DOCTOR_COMMANDS = [
|
|
|
64
64
|
path: ['validate'],
|
|
65
65
|
capability: COMMAND_CAPABILITIES.validate,
|
|
66
66
|
mode: 'validate',
|
|
67
|
-
summary: 'Auto-detect
|
|
67
|
+
summary: 'Auto-detect the applicable doctor policy profile and validate a local path.',
|
|
68
68
|
run: runValidateCommand,
|
|
69
69
|
},
|
|
70
70
|
{
|
|
@@ -72,7 +72,7 @@ export const DOCTOR_COMMANDS = [
|
|
|
72
72
|
path: ['fix'],
|
|
73
73
|
capability: COMMAND_CAPABILITIES.fix,
|
|
74
74
|
mode: 'fix',
|
|
75
|
-
summary: '
|
|
75
|
+
summary: 'Build a non-mutating fix plan for deterministic doctor policy violations.',
|
|
76
76
|
run: runFixCommand,
|
|
77
77
|
},
|
|
78
78
|
{
|
|
@@ -226,7 +226,6 @@ async function runFixCommand(
|
|
|
226
226
|
});
|
|
227
227
|
|
|
228
228
|
request.context.writeStdout(renderAnalysisReport('fix', result));
|
|
229
|
-
request.context.writeStdout('No automatic fixes available.\n');
|
|
230
229
|
|
|
231
230
|
return {
|
|
232
231
|
exitCode: countErrorDiagnostics(result.diagnostics) > 0 ? 1 : 0,
|
|
@@ -274,6 +273,7 @@ function renderAnalysisReport(
|
|
|
274
273
|
const lines = [
|
|
275
274
|
`doctor ${commandName}`,
|
|
276
275
|
`target: ${result.targetPath}`,
|
|
276
|
+
`profile: ${result.profile}`,
|
|
277
277
|
`checks: ${result.appliedChecks.length > 0 ? result.appliedChecks.join(', ') : 'none'}`,
|
|
278
278
|
`repoMarkers: ${result.repoMarkers.length > 0 ? result.repoMarkers.join(', ') : 'none'}`,
|
|
279
279
|
'',
|
|
@@ -288,6 +288,19 @@ function renderAnalysisReport(
|
|
|
288
288
|
}
|
|
289
289
|
}
|
|
290
290
|
|
|
291
|
+
if (commandName === 'fix') {
|
|
292
|
+
lines.push('');
|
|
293
|
+
lines.push('Planned changes:');
|
|
294
|
+
|
|
295
|
+
if (result.plannedChanges.length === 0) {
|
|
296
|
+
lines.push(' none');
|
|
297
|
+
} else {
|
|
298
|
+
for (const change of result.plannedChanges) {
|
|
299
|
+
lines.push(renderPlannedChangeLine(change));
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
291
304
|
const errorCount = countErrorDiagnostics(result.diagnostics);
|
|
292
305
|
const warningCount = countWarningDiagnostics(result.diagnostics);
|
|
293
306
|
|
|
@@ -299,7 +312,11 @@ function renderAnalysisReport(
|
|
|
299
312
|
}
|
|
300
313
|
|
|
301
314
|
function renderDiagnosticLine(diagnostic: DoctorDiagnostic): string {
|
|
302
|
-
return ` - ${diagnostic.severity.toUpperCase()} ${diagnostic.code}: ${diagnostic.message}`;
|
|
315
|
+
return ` - ${diagnostic.severity.toUpperCase()} ${diagnostic.ruleId} (${diagnostic.code}): ${diagnostic.message}`;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function renderPlannedChangeLine(change: DoctorPlannedChange): string {
|
|
319
|
+
return ` - ${change.ruleId} [${change.kind}]: ${change.description}`;
|
|
303
320
|
}
|
|
304
321
|
|
|
305
322
|
function renderCommandFailure(commandName: DoctorCommandName, error: unknown): string {
|
package/src/diagnostics.ts
CHANGED
|
@@ -1,26 +1,83 @@
|
|
|
1
1
|
export type DoctorDiagnosticCode =
|
|
2
|
+
| 'field-invalid'
|
|
3
|
+
| 'field-missing'
|
|
2
4
|
| 'invalid-ankh-metadata'
|
|
3
5
|
| 'invalid-package-json'
|
|
4
|
-
| 'missing-
|
|
5
|
-
| 'missing-
|
|
6
|
-
| 'missing-
|
|
7
|
-
| '
|
|
8
|
-
| '
|
|
9
|
-
| 'package-json-missing'
|
|
10
|
-
| 'package-name-missing'
|
|
11
|
-
| 'package-type-missing'
|
|
12
|
-
| 'package-version-missing'
|
|
13
|
-
| 'repo-markers-missing'
|
|
6
|
+
| 'missing-dependency'
|
|
7
|
+
| 'missing-path'
|
|
8
|
+
| 'missing-script'
|
|
9
|
+
| 'provider-source-import-failed'
|
|
10
|
+
| 'provider-source-missing'
|
|
14
11
|
| 'target-not-directory'
|
|
15
12
|
| 'target-not-found'
|
|
16
13
|
| 'unsupported-target';
|
|
17
14
|
|
|
18
15
|
export type DoctorDiagnosticSeverity = 'error' | 'warning';
|
|
16
|
+
export type DoctorPolicyProfile = 'integration-monorepo' | 'public-package' | 'unknown';
|
|
17
|
+
export type DoctorRuleId =
|
|
18
|
+
| 'integration.package.ankh.disallowed'
|
|
19
|
+
| 'integration.package.private.required'
|
|
20
|
+
| 'integration.package.workspaces.required'
|
|
21
|
+
| 'package.ankh.capabilities.match-provider'
|
|
22
|
+
| 'package.ankh.present.valid-shape'
|
|
23
|
+
| 'package.ankh.provider-path.required'
|
|
24
|
+
| 'package.ankh.required-for-provider'
|
|
25
|
+
| 'package.dependencies.changesets.required'
|
|
26
|
+
| 'package.dependencies.devtools.required'
|
|
27
|
+
| 'package.dependencies.paradox.required'
|
|
28
|
+
| 'package.dependencies.types-bun.required'
|
|
29
|
+
| 'package.dependencies.types-node.required'
|
|
30
|
+
| 'package.dependencies.typescript.required'
|
|
31
|
+
| 'package.json.bugs.required'
|
|
32
|
+
| 'package.json.description.required'
|
|
33
|
+
| 'package.json.exports.required'
|
|
34
|
+
| 'package.json.files.required'
|
|
35
|
+
| 'package.json.homepage.required'
|
|
36
|
+
| 'package.json.keywords.required'
|
|
37
|
+
| 'package.json.license.required'
|
|
38
|
+
| 'package.json.name.required'
|
|
39
|
+
| 'package.json.package-manager.bun'
|
|
40
|
+
| 'package.json.package-manager.required'
|
|
41
|
+
| 'package.json.private.public-package-disallowed'
|
|
42
|
+
| 'package.json.publish-config.public'
|
|
43
|
+
| 'package.json.publish-config.required'
|
|
44
|
+
| 'package.json.repository.required'
|
|
45
|
+
| 'package.json.type.module'
|
|
46
|
+
| 'package.json.type.required'
|
|
47
|
+
| 'package.json.version.required'
|
|
48
|
+
| 'package.scripts.build.required'
|
|
49
|
+
| 'package.scripts.changeset-status.required'
|
|
50
|
+
| 'package.scripts.changeset.required'
|
|
51
|
+
| 'package.scripts.docs.required'
|
|
52
|
+
| 'package.scripts.format-check.required'
|
|
53
|
+
| 'package.scripts.format.required'
|
|
54
|
+
| 'package.scripts.knip.required'
|
|
55
|
+
| 'package.scripts.lint-fix.required'
|
|
56
|
+
| 'package.scripts.lint.required'
|
|
57
|
+
| 'package.scripts.test.required'
|
|
58
|
+
| 'package.scripts.typecheck.required'
|
|
59
|
+
| 'package.scripts.version-packages.required'
|
|
60
|
+
| 'provider.commands.match-capabilities'
|
|
61
|
+
| 'provider.commands.match-handlers'
|
|
62
|
+
| 'provider.source.importable'
|
|
63
|
+
| 'provider.source.required'
|
|
64
|
+
| 'repo.changelog.required'
|
|
65
|
+
| 'repo.changeset.required'
|
|
66
|
+
| 'repo.license.required'
|
|
67
|
+
| 'repo.readme.required'
|
|
68
|
+
| 'repo.workflows.required'
|
|
69
|
+
| 'target.package-json.required'
|
|
70
|
+
| 'target.path.directory'
|
|
71
|
+
| 'target.path.exists'
|
|
72
|
+
| 'target.profile.supported'
|
|
73
|
+
| 'target.repo-markers.required';
|
|
19
74
|
|
|
20
75
|
export interface DoctorDiagnostic {
|
|
21
76
|
readonly code: DoctorDiagnosticCode;
|
|
22
77
|
readonly message: string;
|
|
23
78
|
readonly path: string;
|
|
79
|
+
readonly profile: DoctorPolicyProfile;
|
|
80
|
+
readonly ruleId: DoctorRuleId;
|
|
24
81
|
readonly severity: DoctorDiagnosticSeverity;
|
|
25
82
|
}
|
|
26
83
|
|
package/src/index.ts
CHANGED
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
export type {
|
|
2
2
|
DoctorAnalysisRequest,
|
|
3
3
|
DoctorAnalysisResult,
|
|
4
|
+
DoctorFixPlan,
|
|
5
|
+
DoctorPlannedChange,
|
|
6
|
+
DoctorPlannedChangeKind,
|
|
4
7
|
DoctorTargetCheck,
|
|
5
8
|
DoctorTargetMode,
|
|
6
9
|
} from './analysis.js';
|
|
7
10
|
export { analyzeDoctorTarget } from './analysis.js';
|
|
11
|
+
export { runCli } from './cli.js';
|
|
8
12
|
export {
|
|
9
13
|
createDoctorRuntimeProvider,
|
|
10
14
|
type CreateDoctorRuntimeProviderOptions,
|
|
11
|
-
} from './
|
|
12
|
-
export { runCli } from './cli.js';
|
|
15
|
+
} from './cli/index.js';
|
|
13
16
|
export type { DoctorCommandContext, DoctorCommandRunResult } from './commandContext.js';
|
|
14
17
|
export { createDefaultCommandContext } from './commandContext.js';
|
|
15
18
|
export type {
|
|
16
19
|
DoctorDiagnostic,
|
|
17
20
|
DoctorDiagnosticCode,
|
|
18
21
|
DoctorDiagnosticSeverity,
|
|
22
|
+
DoctorPolicyProfile,
|
|
23
|
+
DoctorRuleId,
|
|
19
24
|
} from './diagnostics.js';
|
|
20
25
|
export {
|
|
21
26
|
DOCTOR_CAPABILITIES,
|
package/src/packageMetadata.ts
CHANGED
|
@@ -18,6 +18,6 @@ export const DOCTOR_CAPABILITIES = [
|
|
|
18
18
|
|
|
19
19
|
export const DOCTOR_PACKAGE_METADATA = {
|
|
20
20
|
category: DOCTOR_COMMAND_CATEGORY,
|
|
21
|
-
provider: './dist/
|
|
21
|
+
provider: './dist/cli/index.js',
|
|
22
22
|
capabilities: DOCTOR_CAPABILITIES,
|
|
23
23
|
} as const satisfies AnkhPackageMetadata;
|
package/src/readme-usage.ts
CHANGED
|
@@ -17,10 +17,18 @@ import { runCli } from './cli.js';
|
|
|
17
17
|
* - `repo`
|
|
18
18
|
* - `package`
|
|
19
19
|
*
|
|
20
|
-
* `doctor#
|
|
20
|
+
* `doctor#2` adds a profile-based policy engine:
|
|
21
21
|
*
|
|
22
|
-
* -
|
|
23
|
-
* -
|
|
22
|
+
* - strict `public-package` validation for extracted public package repos
|
|
23
|
+
* - light recognized `integration-monorepo` validation for `ankhorage4`
|
|
24
|
+
* - non-mutating `fix` plans for deterministic mechanical changes only
|
|
25
|
+
*
|
|
26
|
+
* Still deferred:
|
|
27
|
+
*
|
|
28
|
+
* - GitHub checks
|
|
29
|
+
* - CI checks
|
|
30
|
+
* - on-disk `fix --apply`
|
|
31
|
+
* - deeper cross-repo policy enforcement
|
|
24
32
|
*
|
|
25
33
|
* Path handling:
|
|
26
34
|
*
|
|
@@ -1 +0,0 @@
|
|
|
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 +0,0 @@
|
|
|
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"]}
|