@ankhorage/doctor 0.10.13 → 0.10.14
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 +6 -0
- package/dist/dependencyPolicyAnalysis.d.ts +6 -0
- package/dist/dependencyPolicyAnalysis.d.ts.map +1 -1
- package/dist/dependencyPolicyAnalysis.js +10 -68
- package/dist/dependencyPolicyAnalysis.js.map +1 -1
- package/package.json +1 -1
- package/src/dependencyPolicyAnalysis.ts +10 -95
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.10.14
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- e6c0f2d: Remove the obsolete Ankh-specific Devtools runtime dependency placement rule now that Ankh dynamically discovers providers instead of bundling core providers.
|
|
8
|
+
|
|
3
9
|
## 0.10.13
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { type DoctorAnalysisRequest, type DoctorAnalysisResult } from './analysis.js';
|
|
2
|
+
/***
|
|
3
|
+
* Analyze a Doctor target and apply repository-level dependency and runtime policies.
|
|
4
|
+
*/
|
|
2
5
|
export declare function analyzeDoctorTarget(request: DoctorAnalysisRequest): Promise<DoctorAnalysisResult>;
|
|
6
|
+
/***
|
|
7
|
+
* Analyze a Doctor target with CLI layout validation and repository-level policies.
|
|
8
|
+
*/
|
|
3
9
|
export declare function analyzeDoctorTargetWithCliLayout(request: DoctorAnalysisRequest): Promise<DoctorAnalysisResult>;
|
|
4
10
|
//# sourceMappingURL=dependencyPolicyAnalysis.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependencyPolicyAnalysis.d.ts","sourceRoot":"","sources":["../src/dependencyPolicyAnalysis.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dependencyPolicyAnalysis.d.ts","sourceRoot":"","sources":["../src/dependencyPolicyAnalysis.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EAC1B,MAAM,eAAe,CAAC;AAIvB;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAE/B;AAED;;GAEG;AACH,wBAAsB,gCAAgC,CACpD,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAE/B"}
|
|
@@ -1,80 +1,22 @@
|
|
|
1
|
-
import { promises as fs } from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
1
|
import { analyzeDoctorTarget as analyzeBaseDoctorTarget, } from './analysis.js';
|
|
4
2
|
import { applyBunRuntimePolicy } from './bunPolicyAnalysis.js';
|
|
5
3
|
import { analyzeDoctorTargetWithCliLayout as analyzeBaseDoctorTargetWithCliLayout } from './cliLayoutAnalysis.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
/***
|
|
5
|
+
* Analyze a Doctor target and apply repository-level dependency and runtime policies.
|
|
6
|
+
*/
|
|
9
7
|
export async function analyzeDoctorTarget(request) {
|
|
10
8
|
return applyRepositoryPolicies(await analyzeBaseDoctorTarget(request));
|
|
11
9
|
}
|
|
10
|
+
/***
|
|
11
|
+
* Analyze a Doctor target with CLI layout validation and repository-level policies.
|
|
12
|
+
*/
|
|
12
13
|
export async function analyzeDoctorTargetWithCliLayout(request) {
|
|
13
14
|
return applyRepositoryPolicies(await analyzeBaseDoctorTargetWithCliLayout(request));
|
|
14
15
|
}
|
|
16
|
+
/***
|
|
17
|
+
* Apply repository policies that remain independent from concrete package identities.
|
|
18
|
+
*/
|
|
15
19
|
async function applyRepositoryPolicies(result) {
|
|
16
|
-
return applyBunRuntimePolicy(
|
|
17
|
-
}
|
|
18
|
-
async function applyDevtoolsDependencyPlacementPolicy(result) {
|
|
19
|
-
if (!result.hasPackageJson) {
|
|
20
|
-
return result;
|
|
21
|
-
}
|
|
22
|
-
const packageJsonPath = path.join(result.targetPath, 'package.json');
|
|
23
|
-
const packageJson = await readPackageJson(packageJsonPath);
|
|
24
|
-
if (packageJson?.name !== ANKH_PACKAGE_NAME || !expectsDevtools(packageJson)) {
|
|
25
|
-
return result;
|
|
26
|
-
}
|
|
27
|
-
const dependencies = isRecord(packageJson.dependencies) ? packageJson.dependencies : null;
|
|
28
|
-
const hasRuntimeDevtools = hasDependency(dependencies, DEVTOOLS_PACKAGE_NAME);
|
|
29
|
-
const diagnosticsWithoutPlacementRule = result.diagnostics.filter((diagnostic) => diagnostic.ruleId !== DEVTOOLS_REQUIRED_RULE_ID);
|
|
30
|
-
const diagnostics = hasRuntimeDevtools
|
|
31
|
-
? diagnosticsWithoutPlacementRule
|
|
32
|
-
: [
|
|
33
|
-
...diagnosticsWithoutPlacementRule,
|
|
34
|
-
createMissingRuntimeDevtoolsDiagnostic(packageJsonPath, result),
|
|
35
|
-
];
|
|
36
|
-
return {
|
|
37
|
-
...result,
|
|
38
|
-
diagnostics,
|
|
39
|
-
fixPlan: result.fixPlan === null ? null : { ...result.fixPlan, diagnostics },
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
async function readPackageJson(packageJsonPath) {
|
|
43
|
-
try {
|
|
44
|
-
const parsed = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
|
|
45
|
-
return isRecord(parsed) ? parsed : null;
|
|
46
|
-
}
|
|
47
|
-
catch {
|
|
48
|
-
return null;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
function createMissingRuntimeDevtoolsDiagnostic(packageJsonPath, result) {
|
|
52
|
-
return {
|
|
53
|
-
code: 'missing-dependency',
|
|
54
|
-
message: '@ankhorage/ankh bundles @ankhorage/devtools as a runtime core provider and must declare it in dependencies.',
|
|
55
|
-
path: packageJsonPath,
|
|
56
|
-
profile: result.profile,
|
|
57
|
-
ruleId: DEVTOOLS_REQUIRED_RULE_ID,
|
|
58
|
-
severity: 'error',
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
function expectsDevtools(packageJson) {
|
|
62
|
-
const scripts = isRecord(packageJson.scripts) ? packageJson.scripts : null;
|
|
63
|
-
if (scripts === null) {
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
66
|
-
return Object.values(scripts).some((scriptValue) => isNonEmptyString(scriptValue) &&
|
|
67
|
-
(scriptValue.includes('ankhorage-eslint') ||
|
|
68
|
-
scriptValue.includes('ankhorage-prettier') ||
|
|
69
|
-
scriptValue.includes('ankhorage-knip')));
|
|
70
|
-
}
|
|
71
|
-
function hasDependency(dependencyMap, dependencyName) {
|
|
72
|
-
return dependencyMap !== null && isNonEmptyString(dependencyMap[dependencyName]);
|
|
73
|
-
}
|
|
74
|
-
function isNonEmptyString(value) {
|
|
75
|
-
return typeof value === 'string' && value.trim() !== '';
|
|
76
|
-
}
|
|
77
|
-
function isRecord(value) {
|
|
78
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
20
|
+
return applyBunRuntimePolicy(result);
|
|
79
21
|
}
|
|
80
22
|
//# sourceMappingURL=dependencyPolicyAnalysis.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependencyPolicyAnalysis.js","sourceRoot":"","sources":["../src/dependencyPolicyAnalysis.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"dependencyPolicyAnalysis.js","sourceRoot":"","sources":["../src/dependencyPolicyAnalysis.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,IAAI,uBAAuB,GAG/C,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,gCAAgC,IAAI,oCAAoC,EAAE,MAAM,wBAAwB,CAAC;AAElH;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,OAA8B;IAE9B,OAAO,uBAAuB,CAAC,MAAM,uBAAuB,CAAC,OAAO,CAAC,CAAC,CAAC;AACzE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gCAAgC,CACpD,OAA8B;IAE9B,OAAO,uBAAuB,CAAC,MAAM,oCAAoC,CAAC,OAAO,CAAC,CAAC,CAAC;AACtF,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,uBAAuB,CACpC,MAA4B;IAE5B,OAAO,qBAAqB,CAAC,MAAM,CAAC,CAAC;AACvC,CAAC","sourcesContent":["import {\n analyzeDoctorTarget as analyzeBaseDoctorTarget,\n type DoctorAnalysisRequest,\n type DoctorAnalysisResult,\n} from './analysis.js';\nimport { applyBunRuntimePolicy } from './bunPolicyAnalysis.js';\nimport { analyzeDoctorTargetWithCliLayout as analyzeBaseDoctorTargetWithCliLayout } from './cliLayoutAnalysis.js';\n\n/***\n * Analyze a Doctor target and apply repository-level dependency and runtime policies.\n */\nexport async function analyzeDoctorTarget(\n request: DoctorAnalysisRequest,\n): Promise<DoctorAnalysisResult> {\n return applyRepositoryPolicies(await analyzeBaseDoctorTarget(request));\n}\n\n/***\n * Analyze a Doctor target with CLI layout validation and repository-level policies.\n */\nexport async function analyzeDoctorTargetWithCliLayout(\n request: DoctorAnalysisRequest,\n): Promise<DoctorAnalysisResult> {\n return applyRepositoryPolicies(await analyzeBaseDoctorTargetWithCliLayout(request));\n}\n\n/***\n * Apply repository policies that remain independent from concrete package identities.\n */\nasync function applyRepositoryPolicies(\n result: DoctorAnalysisResult,\n): Promise<DoctorAnalysisResult> {\n return applyBunRuntimePolicy(result);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import { promises as fs } from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
|
|
4
1
|
import {
|
|
5
2
|
analyzeDoctorTarget as analyzeBaseDoctorTarget,
|
|
6
3
|
type DoctorAnalysisRequest,
|
|
@@ -8,112 +5,30 @@ import {
|
|
|
8
5
|
} from './analysis.js';
|
|
9
6
|
import { applyBunRuntimePolicy } from './bunPolicyAnalysis.js';
|
|
10
7
|
import { analyzeDoctorTargetWithCliLayout as analyzeBaseDoctorTargetWithCliLayout } from './cliLayoutAnalysis.js';
|
|
11
|
-
import type { DoctorDiagnostic } from './diagnostics.js';
|
|
12
|
-
|
|
13
|
-
const ANKH_PACKAGE_NAME = '@ankhorage/ankh';
|
|
14
|
-
const DEVTOOLS_PACKAGE_NAME = '@ankhorage/devtools';
|
|
15
|
-
const DEVTOOLS_REQUIRED_RULE_ID = 'package.dependencies.devtools.required';
|
|
16
8
|
|
|
9
|
+
/***
|
|
10
|
+
* Analyze a Doctor target and apply repository-level dependency and runtime policies.
|
|
11
|
+
*/
|
|
17
12
|
export async function analyzeDoctorTarget(
|
|
18
13
|
request: DoctorAnalysisRequest,
|
|
19
14
|
): Promise<DoctorAnalysisResult> {
|
|
20
15
|
return applyRepositoryPolicies(await analyzeBaseDoctorTarget(request));
|
|
21
16
|
}
|
|
22
17
|
|
|
18
|
+
/***
|
|
19
|
+
* Analyze a Doctor target with CLI layout validation and repository-level policies.
|
|
20
|
+
*/
|
|
23
21
|
export async function analyzeDoctorTargetWithCliLayout(
|
|
24
22
|
request: DoctorAnalysisRequest,
|
|
25
23
|
): Promise<DoctorAnalysisResult> {
|
|
26
24
|
return applyRepositoryPolicies(await analyzeBaseDoctorTargetWithCliLayout(request));
|
|
27
25
|
}
|
|
28
26
|
|
|
27
|
+
/***
|
|
28
|
+
* Apply repository policies that remain independent from concrete package identities.
|
|
29
|
+
*/
|
|
29
30
|
async function applyRepositoryPolicies(
|
|
30
31
|
result: DoctorAnalysisResult,
|
|
31
32
|
): Promise<DoctorAnalysisResult> {
|
|
32
|
-
return applyBunRuntimePolicy(
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async function applyDevtoolsDependencyPlacementPolicy(
|
|
36
|
-
result: DoctorAnalysisResult,
|
|
37
|
-
): Promise<DoctorAnalysisResult> {
|
|
38
|
-
if (!result.hasPackageJson) {
|
|
39
|
-
return result;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const packageJsonPath = path.join(result.targetPath, 'package.json');
|
|
43
|
-
const packageJson = await readPackageJson(packageJsonPath);
|
|
44
|
-
if (packageJson?.name !== ANKH_PACKAGE_NAME || !expectsDevtools(packageJson)) {
|
|
45
|
-
return result;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const dependencies = isRecord(packageJson.dependencies) ? packageJson.dependencies : null;
|
|
49
|
-
const hasRuntimeDevtools = hasDependency(dependencies, DEVTOOLS_PACKAGE_NAME);
|
|
50
|
-
const diagnosticsWithoutPlacementRule = result.diagnostics.filter(
|
|
51
|
-
(diagnostic) => diagnostic.ruleId !== DEVTOOLS_REQUIRED_RULE_ID,
|
|
52
|
-
);
|
|
53
|
-
const diagnostics = hasRuntimeDevtools
|
|
54
|
-
? diagnosticsWithoutPlacementRule
|
|
55
|
-
: [
|
|
56
|
-
...diagnosticsWithoutPlacementRule,
|
|
57
|
-
createMissingRuntimeDevtoolsDiagnostic(packageJsonPath, result),
|
|
58
|
-
];
|
|
59
|
-
|
|
60
|
-
return {
|
|
61
|
-
...result,
|
|
62
|
-
diagnostics,
|
|
63
|
-
fixPlan: result.fixPlan === null ? null : { ...result.fixPlan, diagnostics },
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
async function readPackageJson(packageJsonPath: string): Promise<Record<string, unknown> | null> {
|
|
68
|
-
try {
|
|
69
|
-
const parsed = JSON.parse(await fs.readFile(packageJsonPath, 'utf8')) as unknown;
|
|
70
|
-
return isRecord(parsed) ? parsed : null;
|
|
71
|
-
} catch {
|
|
72
|
-
return null;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function createMissingRuntimeDevtoolsDiagnostic(
|
|
77
|
-
packageJsonPath: string,
|
|
78
|
-
result: DoctorAnalysisResult,
|
|
79
|
-
): DoctorDiagnostic {
|
|
80
|
-
return {
|
|
81
|
-
code: 'missing-dependency',
|
|
82
|
-
message:
|
|
83
|
-
'@ankhorage/ankh bundles @ankhorage/devtools as a runtime core provider and must declare it in dependencies.',
|
|
84
|
-
path: packageJsonPath,
|
|
85
|
-
profile: result.profile,
|
|
86
|
-
ruleId: DEVTOOLS_REQUIRED_RULE_ID,
|
|
87
|
-
severity: 'error',
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function expectsDevtools(packageJson: Record<string, unknown>): boolean {
|
|
92
|
-
const scripts = isRecord(packageJson.scripts) ? packageJson.scripts : null;
|
|
93
|
-
if (scripts === null) {
|
|
94
|
-
return false;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return Object.values(scripts).some(
|
|
98
|
-
(scriptValue) =>
|
|
99
|
-
isNonEmptyString(scriptValue) &&
|
|
100
|
-
(scriptValue.includes('ankhorage-eslint') ||
|
|
101
|
-
scriptValue.includes('ankhorage-prettier') ||
|
|
102
|
-
scriptValue.includes('ankhorage-knip')),
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function hasDependency(
|
|
107
|
-
dependencyMap: Record<string, unknown> | null,
|
|
108
|
-
dependencyName: string,
|
|
109
|
-
): boolean {
|
|
110
|
-
return dependencyMap !== null && isNonEmptyString(dependencyMap[dependencyName]);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function isNonEmptyString(value: unknown): value is string {
|
|
114
|
-
return typeof value === 'string' && value.trim() !== '';
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
118
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
33
|
+
return applyBunRuntimePolicy(result);
|
|
119
34
|
}
|