@ankhorage/doctor 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/analysis.d.ts +2 -0
- package/dist/analysis.d.ts.map +1 -1
- package/dist/analysis.js.map +1 -1
- package/dist/authReadinessAnalysis.d.ts +8 -0
- package/dist/authReadinessAnalysis.d.ts.map +1 -0
- package/dist/authReadinessAnalysis.js +38 -0
- package/dist/authReadinessAnalysis.js.map +1 -0
- package/dist/authReadinessDiagnostic.d.ts +9 -0
- package/dist/authReadinessDiagnostic.d.ts.map +1 -0
- package/dist/authReadinessDiagnostic.js +11 -0
- package/dist/authReadinessDiagnostic.js.map +1 -0
- package/dist/authReadinessEnvironment.d.ts +16 -0
- package/dist/authReadinessEnvironment.d.ts.map +1 -0
- package/dist/authReadinessEnvironment.js +29 -0
- package/dist/authReadinessEnvironment.js.map +1 -0
- package/dist/authReadinessFileAnalysis.d.ts +3 -0
- package/dist/authReadinessFileAnalysis.d.ts.map +1 -0
- package/dist/authReadinessFileAnalysis.js +12 -0
- package/dist/authReadinessFileAnalysis.js.map +1 -0
- package/dist/authReadinessNativeDiagnostic.d.ts +4 -0
- package/dist/authReadinessNativeDiagnostic.d.ts.map +1 -0
- package/dist/authReadinessNativeDiagnostic.js +11 -0
- package/dist/authReadinessNativeDiagnostic.js.map +1 -0
- package/dist/authReadinessProvider.d.ts +15 -0
- package/dist/authReadinessProvider.d.ts.map +1 -0
- package/dist/authReadinessProvider.js +44 -0
- package/dist/authReadinessProvider.js.map +1 -0
- package/dist/authReadinessProviderEnvironment.d.ts +15 -0
- package/dist/authReadinessProviderEnvironment.d.ts.map +1 -0
- package/dist/authReadinessProviderEnvironment.js +35 -0
- package/dist/authReadinessProviderEnvironment.js.map +1 -0
- package/dist/authReadinessRequirements.d.ts +10 -0
- package/dist/authReadinessRequirements.d.ts.map +1 -0
- package/dist/authReadinessRequirements.js +34 -0
- package/dist/authReadinessRequirements.js.map +1 -0
- package/dist/authReadinessTargetFallback.d.ts +3 -0
- package/dist/authReadinessTargetFallback.d.ts.map +1 -0
- package/dist/authReadinessTargetFallback.js +32 -0
- package/dist/authReadinessTargetFallback.js.map +1 -0
- package/dist/authReadinessTargetResolution.d.ts +8 -0
- package/dist/authReadinessTargetResolution.d.ts.map +1 -0
- package/dist/authReadinessTargetResolution.js +2 -0
- package/dist/authReadinessTargetResolution.js.map +1 -0
- package/dist/authReadinessTargets.d.ts +3 -0
- package/dist/authReadinessTargets.d.ts.map +1 -0
- package/dist/authReadinessTargets.js +26 -0
- package/dist/authReadinessTargets.js.map +1 -0
- package/dist/authReadinessUnsupported.d.ts +13 -0
- package/dist/authReadinessUnsupported.d.ts.map +1 -0
- package/dist/authReadinessUnsupported.js +22 -0
- package/dist/authReadinessUnsupported.js.map +1 -0
- package/dist/authReadinessUnsupportedBackend.d.ts +12 -0
- package/dist/authReadinessUnsupportedBackend.d.ts.map +1 -0
- package/dist/authReadinessUnsupportedBackend.js +18 -0
- package/dist/authReadinessUnsupportedBackend.js.map +1 -0
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +14 -0
- package/dist/commands.js.map +1 -1
- package/dist/diagnostics.d.ts +1 -1
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/manifestAnalysis.d.ts.map +1 -1
- package/dist/manifestAnalysis.js +4 -1
- package/dist/manifestAnalysis.js.map +1 -1
- package/dist/readiness.d.ts +13 -0
- package/dist/readiness.d.ts.map +1 -0
- package/dist/readiness.js +2 -0
- package/dist/readiness.js.map +1 -0
- package/package.json +3 -2
- package/src/analysis.ts +2 -0
- package/src/authReadinessAnalysis.ts +50 -0
- package/src/authReadinessDiagnostic.ts +18 -0
- package/src/authReadinessEnvironment.ts +51 -0
- package/src/authReadinessFileAnalysis.ts +14 -0
- package/src/authReadinessNativeDiagnostic.ts +17 -0
- package/src/authReadinessProvider.ts +61 -0
- package/src/authReadinessProviderEnvironment.ts +54 -0
- package/src/authReadinessRequirements.ts +50 -0
- package/src/authReadinessTargetFallback.ts +38 -0
- package/src/authReadinessTargetResolution.ts +9 -0
- package/src/authReadinessTargets.ts +35 -0
- package/src/authReadinessUnsupported.ts +34 -0
- package/src/authReadinessUnsupportedBackend.ts +34 -0
- package/src/commands.ts +16 -0
- package/src/diagnostics.ts +5 -0
- package/src/index.ts +3 -0
- package/src/manifestAnalysis.ts +4 -1
- package/src/readiness.ts +14 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { createAuthReadinessDiagnostic } from './authReadinessDiagnostic.js';
|
|
2
|
+
import type { AuthReadinessTargetResolution } from './authReadinessTargetResolution.js';
|
|
3
|
+
|
|
4
|
+
export function resolveAuthReadinessTargetFallback(
|
|
5
|
+
deploy: unknown,
|
|
6
|
+
manifestPath: string,
|
|
7
|
+
): AuthReadinessTargetResolution {
|
|
8
|
+
if (deploy === undefined) {
|
|
9
|
+
return {
|
|
10
|
+
diagnostics: [
|
|
11
|
+
createAuthReadinessDiagnostic({
|
|
12
|
+
code: 'field-missing',
|
|
13
|
+
message:
|
|
14
|
+
'deploy.targets is missing; Doctor evaluates legacy Web-only readiness until canonical targets are persisted.',
|
|
15
|
+
path: manifestPath,
|
|
16
|
+
ruleId: 'manifest.deploy.targets.legacy-web',
|
|
17
|
+
severity: 'warning',
|
|
18
|
+
}),
|
|
19
|
+
],
|
|
20
|
+
enabledTargets: ['web'],
|
|
21
|
+
targets: { web: { enabled: true } },
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
diagnostics: [
|
|
27
|
+
createAuthReadinessDiagnostic({
|
|
28
|
+
code: 'field-invalid',
|
|
29
|
+
message: 'manifest.deploy must match the canonical Contracts deploy target model.',
|
|
30
|
+
path: manifestPath,
|
|
31
|
+
ruleId: 'manifest.deploy.valid-shape',
|
|
32
|
+
severity: 'error',
|
|
33
|
+
}),
|
|
34
|
+
],
|
|
35
|
+
enabledTargets: [],
|
|
36
|
+
targets: null,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AppDeployTargetId, AppDeployTargets } from '@ankhorage/contracts/deploy';
|
|
2
|
+
|
|
3
|
+
import type { DoctorDiagnostic } from './diagnostics.js';
|
|
4
|
+
|
|
5
|
+
export interface AuthReadinessTargetResolution {
|
|
6
|
+
readonly diagnostics: readonly DoctorDiagnostic[];
|
|
7
|
+
readonly enabledTargets: readonly AppDeployTargetId[];
|
|
8
|
+
readonly targets: AppDeployTargets | null;
|
|
9
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { APP_DEPLOY_TARGET_IDS, isAppDeployManifest } from '@ankhorage/contracts/deploy';
|
|
2
|
+
|
|
3
|
+
import { createAuthReadinessDiagnostic } from './authReadinessDiagnostic.js';
|
|
4
|
+
import { resolveAuthReadinessTargetFallback } from './authReadinessTargetFallback.js';
|
|
5
|
+
import type { AuthReadinessTargetResolution } from './authReadinessTargetResolution.js';
|
|
6
|
+
|
|
7
|
+
export function resolveAuthReadinessTargets(
|
|
8
|
+
deploy: unknown,
|
|
9
|
+
manifestPath: string,
|
|
10
|
+
): AuthReadinessTargetResolution {
|
|
11
|
+
if (!isAppDeployManifest(deploy)) {
|
|
12
|
+
return resolveAuthReadinessTargetFallback(deploy, manifestPath);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const enabledTargets = APP_DEPLOY_TARGET_IDS.filter(
|
|
16
|
+
(target) => deploy.targets[target]?.enabled === true,
|
|
17
|
+
);
|
|
18
|
+
if (enabledTargets.length > 0) {
|
|
19
|
+
return { diagnostics: [], enabledTargets, targets: deploy.targets };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
diagnostics: [
|
|
24
|
+
createAuthReadinessDiagnostic({
|
|
25
|
+
code: 'field-missing',
|
|
26
|
+
message: 'manifest.deploy.targets must enable at least one application target.',
|
|
27
|
+
path: manifestPath,
|
|
28
|
+
ruleId: 'manifest.deploy.targets.enabled',
|
|
29
|
+
severity: 'error',
|
|
30
|
+
}),
|
|
31
|
+
],
|
|
32
|
+
enabledTargets,
|
|
33
|
+
targets: deploy.targets,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { AppDeployEnvironmentId, AppDeployTargetId } from '@ankhorage/contracts/deploy';
|
|
2
|
+
|
|
3
|
+
import { createAuthReadinessDiagnostic } from './authReadinessDiagnostic.js';
|
|
4
|
+
import type { DoctorDiagnostic } from './diagnostics.js';
|
|
5
|
+
import type { DoctorReadiness } from './readiness.js';
|
|
6
|
+
|
|
7
|
+
export function createUnsupportedAuthReadiness(input: {
|
|
8
|
+
readonly environment: AppDeployEnvironmentId;
|
|
9
|
+
readonly provider: string;
|
|
10
|
+
readonly targets: readonly AppDeployTargetId[];
|
|
11
|
+
}): DoctorReadiness[] {
|
|
12
|
+
return input.targets.map((target) => ({
|
|
13
|
+
category: 'auth-oauth',
|
|
14
|
+
environment: input.environment,
|
|
15
|
+
message: 'The selected backend/provider/transport combination has no setup capability.',
|
|
16
|
+
provider: input.provider,
|
|
17
|
+
status: 'unsupported',
|
|
18
|
+
target,
|
|
19
|
+
transport: 'brokeredRedirect',
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function createUnsupportedAuthDiagnostic(input: {
|
|
24
|
+
readonly message: string;
|
|
25
|
+
readonly path: string;
|
|
26
|
+
}): DoctorDiagnostic {
|
|
27
|
+
return createAuthReadinessDiagnostic({
|
|
28
|
+
code: 'field-invalid',
|
|
29
|
+
message: input.message,
|
|
30
|
+
path: input.path,
|
|
31
|
+
ruleId: 'manifest.auth.oauth.setup.supported',
|
|
32
|
+
severity: 'error',
|
|
33
|
+
});
|
|
34
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { AppDeployTargetId } from '@ankhorage/contracts/deploy';
|
|
2
|
+
import { APP_DEPLOY_ENVIRONMENT_IDS } from '@ankhorage/contracts/deploy';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
createUnsupportedAuthDiagnostic,
|
|
6
|
+
createUnsupportedAuthReadiness,
|
|
7
|
+
} from './authReadinessUnsupported.js';
|
|
8
|
+
import type { DoctorDiagnostic } from './diagnostics.js';
|
|
9
|
+
import type { DoctorReadiness } from './readiness.js';
|
|
10
|
+
|
|
11
|
+
export function analyzeUnsupportedAuthBackend(input: {
|
|
12
|
+
readonly enabledTargets: readonly AppDeployTargetId[];
|
|
13
|
+
readonly manifestPath: string;
|
|
14
|
+
readonly provider: string;
|
|
15
|
+
}): {
|
|
16
|
+
readonly diagnostics: readonly DoctorDiagnostic[];
|
|
17
|
+
readonly readiness: readonly DoctorReadiness[];
|
|
18
|
+
} {
|
|
19
|
+
return {
|
|
20
|
+
diagnostics: [
|
|
21
|
+
createUnsupportedAuthDiagnostic({
|
|
22
|
+
message: 'Configured OAuth backend has no Doctor setup resolver.',
|
|
23
|
+
path: input.manifestPath,
|
|
24
|
+
}),
|
|
25
|
+
],
|
|
26
|
+
readiness: APP_DEPLOY_ENVIRONMENT_IDS.flatMap((environment) =>
|
|
27
|
+
createUnsupportedAuthReadiness({
|
|
28
|
+
environment,
|
|
29
|
+
provider: input.provider,
|
|
30
|
+
targets: input.enabledTargets,
|
|
31
|
+
}),
|
|
32
|
+
),
|
|
33
|
+
};
|
|
34
|
+
}
|
package/src/commands.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
type DoctorDiagnostic,
|
|
10
10
|
} from './diagnostics.js';
|
|
11
11
|
import { DOCTOR_CAPABILITIES, DOCTOR_COMMAND_CATEGORY } from './packageMetadata.js';
|
|
12
|
+
import type { DoctorReadiness } from './readiness.js';
|
|
12
13
|
|
|
13
14
|
type DoctorCommandName = 'fix' | 'package' | 'repo' | 'validate';
|
|
14
15
|
|
|
@@ -289,6 +290,17 @@ function renderAnalysisReport(
|
|
|
289
290
|
}
|
|
290
291
|
}
|
|
291
292
|
|
|
293
|
+
const readiness = result.readiness ?? [];
|
|
294
|
+
lines.push('');
|
|
295
|
+
lines.push('Readiness:');
|
|
296
|
+
if (readiness.length === 0) {
|
|
297
|
+
lines.push(' none');
|
|
298
|
+
} else {
|
|
299
|
+
for (const item of readiness) {
|
|
300
|
+
lines.push(renderReadinessLine(item));
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
292
304
|
if (commandName === 'fix') {
|
|
293
305
|
lines.push('');
|
|
294
306
|
lines.push('Planned changes:');
|
|
@@ -316,6 +328,10 @@ function renderDiagnosticLine(diagnostic: DoctorDiagnostic): string {
|
|
|
316
328
|
return ` - ${diagnostic.severity.toUpperCase()} ${diagnostic.ruleId} (${diagnostic.code}): ${diagnostic.message}`;
|
|
317
329
|
}
|
|
318
330
|
|
|
331
|
+
function renderReadinessLine(item: DoctorReadiness): string {
|
|
332
|
+
return ` - ${item.target} ${item.environment} ${item.provider} ${item.transport}: ${item.status} — ${item.message}`;
|
|
333
|
+
}
|
|
334
|
+
|
|
319
335
|
function renderPlannedChangeLine(change: DoctorPlannedChange): string {
|
|
320
336
|
return ` - ${change.ruleId} [${change.kind}]: ${change.description}`;
|
|
321
337
|
}
|
package/src/diagnostics.ts
CHANGED
|
@@ -30,13 +30,18 @@ export type DoctorRuleId =
|
|
|
30
30
|
| 'manifest.auth.flow.unauthorized-route.valid'
|
|
31
31
|
| 'manifest.auth.flow.valid-shape'
|
|
32
32
|
| 'manifest.auth.oauth.callback-route.valid'
|
|
33
|
+
| 'manifest.auth.oauth.callback-target.configured'
|
|
33
34
|
| 'manifest.auth.oauth.provider.credentials-ref.required'
|
|
34
35
|
| 'manifest.auth.oauth.provider.credentials-ref.valid'
|
|
35
36
|
| 'manifest.auth.oauth.provider.duplicate'
|
|
36
37
|
| 'manifest.auth.oauth.provider.inline-secret.disallowed'
|
|
37
38
|
| 'manifest.auth.oauth.providers.valid'
|
|
39
|
+
| 'manifest.auth.oauth.setup.supported'
|
|
38
40
|
| 'manifest.auth.oauth.valid-shape'
|
|
39
41
|
| 'manifest.auth.valid-shape'
|
|
42
|
+
| 'manifest.deploy.targets.enabled'
|
|
43
|
+
| 'manifest.deploy.targets.legacy-web'
|
|
44
|
+
| 'manifest.deploy.valid-shape'
|
|
40
45
|
| 'manifest.infra.valid-shape'
|
|
41
46
|
| 'manifest.json.readable'
|
|
42
47
|
| 'manifest.json.valid'
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,8 @@ export type {
|
|
|
7
7
|
DoctorTargetCheck,
|
|
8
8
|
DoctorTargetMode,
|
|
9
9
|
} from './analysis.js';
|
|
10
|
+
export { analyzeAuthReadiness, type DoctorAuthReadinessAnalysis } from './authReadinessAnalysis.js';
|
|
11
|
+
export { analyzeAuthReadinessFile } from './authReadinessFileAnalysis.js';
|
|
10
12
|
export {
|
|
11
13
|
createDoctorRuntimeProvider,
|
|
12
14
|
type CreateDoctorRuntimeProviderOptions,
|
|
@@ -37,3 +39,4 @@ export {
|
|
|
37
39
|
DOCTOR_PACKAGE_NAME,
|
|
38
40
|
DOCTOR_PACKAGE_VERSION,
|
|
39
41
|
} from './packageMetadata.js';
|
|
42
|
+
export type { DoctorReadiness, DoctorReadinessStatus } from './readiness.js';
|
package/src/manifestAnalysis.ts
CHANGED
|
@@ -10,6 +10,7 @@ import type {
|
|
|
10
10
|
DoctorFixPlan,
|
|
11
11
|
DoctorPlannedChange,
|
|
12
12
|
} from './analysis.js';
|
|
13
|
+
import { analyzeAuthReadinessFile } from './authReadinessFileAnalysis.js';
|
|
13
14
|
import type {
|
|
14
15
|
DoctorDiagnostic,
|
|
15
16
|
DoctorDiagnosticCode,
|
|
@@ -52,7 +53,8 @@ export async function analyzeAppManifestTarget(
|
|
|
52
53
|
return null;
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
const
|
|
56
|
+
const authReadiness = await analyzeAuthReadinessFile(targetPath);
|
|
57
|
+
const diagnostics = [...(await analyzeAppManifestFile(targetPath)), ...authReadiness.diagnostics];
|
|
56
58
|
const plannedChanges: DoctorPlannedChange[] = [];
|
|
57
59
|
const fixPlan: DoctorFixPlan | null =
|
|
58
60
|
request.mode === 'fix'
|
|
@@ -71,6 +73,7 @@ export async function analyzeAppManifestTarget(
|
|
|
71
73
|
hasPackageJson: false,
|
|
72
74
|
plannedChanges,
|
|
73
75
|
profile: MANIFEST_PROFILE,
|
|
76
|
+
readiness: authReadiness.readiness,
|
|
74
77
|
repoMarkers: [],
|
|
75
78
|
targetPath,
|
|
76
79
|
};
|
package/src/readiness.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AuthOAuthProviderId, AuthOAuthTransportId } from '@ankhorage/contracts/auth';
|
|
2
|
+
import type { AppDeployEnvironmentId, AppDeployTargetId } from '@ankhorage/contracts/deploy';
|
|
3
|
+
|
|
4
|
+
export type DoctorReadinessStatus = 'missing' | 'ready' | 'unsupported';
|
|
5
|
+
|
|
6
|
+
export interface DoctorReadiness {
|
|
7
|
+
readonly category: 'auth-oauth';
|
|
8
|
+
readonly environment: AppDeployEnvironmentId;
|
|
9
|
+
readonly message: string;
|
|
10
|
+
readonly provider: AuthOAuthProviderId;
|
|
11
|
+
readonly status: DoctorReadinessStatus;
|
|
12
|
+
readonly target: AppDeployTargetId;
|
|
13
|
+
readonly transport: AuthOAuthTransportId;
|
|
14
|
+
}
|