@ontrails/warden 1.0.0-beta.17 → 1.0.0-beta.19
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 +89 -0
- package/README.md +12 -30
- package/bin/warden.ts +29 -1
- package/package.json +9 -8
- package/src/adapter-check.ts +136 -0
- package/src/cli.ts +238 -60
- package/src/command.ts +26 -0
- package/src/drift.ts +1 -1
- package/src/fix.ts +120 -0
- package/src/formatters.ts +14 -2
- package/src/guide.ts +11 -0
- package/src/index.ts +31 -1
- package/src/rules/ast.ts +84 -25
- package/src/rules/circular-refs.ts +1 -1
- package/src/rules/{cross-declarations.ts → composes-declarations.ts} +198 -89
- package/src/rules/context-no-surface-types.ts +4 -4
- package/src/rules/contour-exists.ts +1 -1
- package/src/rules/dead-internal-trail.ts +22 -9
- package/src/rules/fires-declarations.ts +3 -3
- package/src/rules/implementation-returns-result.ts +269 -76
- package/src/rules/index.ts +51 -3
- package/src/rules/intent-propagation.ts +6 -6
- package/src/rules/metadata.ts +117 -12
- package/src/rules/missing-visibility.ts +14 -14
- package/src/rules/no-destructured-compose.ts +192 -0
- package/src/rules/no-direct-implementation-call.ts +2 -2
- package/src/rules/no-legacy-layer-imports.ts +19 -1
- package/src/rules/no-redundant-result-error-wrap.ts +331 -0
- package/src/rules/no-sync-result-assumption.ts +2 -2
- package/src/rules/no-throw-in-implementation.ts +2 -3
- package/src/rules/no-top-level-surface.ts +389 -0
- package/src/rules/on-references-exist.ts +1 -1
- package/src/rules/reference-exists.ts +1 -1
- package/src/rules/registry-names.ts +28 -2
- package/src/rules/resolved-import-boundary.ts +2 -2
- package/src/rules/resource-declarations.ts +4 -4
- package/src/rules/resource-exists.ts +1 -1
- package/src/rules/resource-mock-coverage.ts +115 -0
- package/src/rules/scan.ts +39 -0
- package/src/rules/trail-versioning-source.ts +1094 -0
- package/src/rules/trail-versioning-topo.ts +172 -0
- package/src/rules/types.ts +87 -5
- package/src/rules/valid-detour-contract.ts +1 -1
- package/src/rules/warden-export-symmetry.ts +1 -1
- package/src/rules/warden-rules-use-ast.ts +2 -2
- package/src/trails/activation-orphan.trail.ts +4 -1
- package/src/trails/composes-declarations.trail.ts +22 -0
- package/src/trails/dead-internal-trail.trail.ts +4 -4
- package/src/trails/deprecation-without-guidance.trail.ts +21 -0
- package/src/trails/fork-without-preserved-blaze.trail.ts +31 -0
- package/src/trails/index.ts +12 -1
- package/src/trails/intent-propagation.trail.ts +3 -3
- package/src/trails/marker-schema-unsupported.trail.ts +23 -0
- package/src/trails/missing-visibility.trail.ts +2 -2
- package/src/trails/no-destructured-compose.trail.ts +44 -0
- package/src/trails/no-direct-implementation-call.trail.ts +2 -2
- package/src/trails/no-legacy-layer-imports.trail.ts +6 -0
- package/src/trails/no-redundant-result-error-wrap.trail.ts +55 -0
- package/src/trails/no-top-level-surface.trail.ts +43 -0
- package/src/trails/pending-force.trail.ts +21 -0
- package/src/trails/public-internal-deep-imports.trail.ts +1 -1
- package/src/trails/resolved-import-boundary.trail.ts +4 -4
- package/src/trails/resource-mock-coverage.trail.ts +40 -0
- package/src/trails/run.ts +2 -2
- package/src/trails/schema.ts +32 -6
- package/src/trails/signal-graph-coaching.trail.ts +4 -1
- package/src/trails/unmaterialized-activation-source.trail.ts +4 -1
- package/src/trails/valid-detour-contract.trail.ts +1 -1
- package/src/trails/version-gap.trail.ts +35 -0
- package/src/trails/version-pinned-compose.trail.ts +23 -0
- package/src/trails/version-without-examples.trail.ts +38 -0
- package/src/trails/wrap-rule.ts +5 -3
- package/src/trails/cross-declarations.trail.ts +0 -22
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,94 @@
|
|
|
1
1
|
# @ontrails/warden
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.19
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- 1eb5bdc: Rename first-class trail composition from the `cross` API family to the `compose` family across core contracts, testing helpers, topo projections, Warden rules, CLI scaffolds, and docs. `composes`, `ctx.compose`, `composeInput`, and `Compose*` type names are now the public authoring vocabulary; topo persistence migrates legacy composition rows and graph keys forward.
|
|
8
|
+
|
|
9
|
+
### Minor Changes
|
|
10
|
+
|
|
11
|
+
- 120caf5: Promote topo artifact commands to `trails compile` and `trails validate`.
|
|
12
|
+
- 1c975c3: Define the Warden fix-metadata contract (`WardenFix`, `WardenFixCapability`, `WardenFixClass`, `WardenFixSafety`, `WardenFixEdit`) with optional `fix` metadata on diagnostics and rule metadata, projected through the guide, manifest, markdown, and agent guidance. Export `wardenFixClasses`/`wardenFixSafeties` value arrays and surface the rule `fix` capability in the `warden.guide` trail output schema. Dormant until a rule declares it.
|
|
13
|
+
- d5d518e: Add `warden --fix` to apply safe source fixes. The executor applies only `safety: 'safe'` edits last-to-first, re-reading and rewriting affected files, while review-required, edit-less, and topo diagnostics stay reported but unapplied. The report surfaces applied, changed-file, and skipped counts.
|
|
14
|
+
|
|
15
|
+
Expose `fix` through the Trails app wrapper and mark the `warden` trail as write intent with explicit public access because `fix: true` mutates source files while the local governance command remains directly runnable.
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- f8d80b9: Refresh current-facing compose vocabulary in package documentation after the composition cutover.
|
|
20
|
+
- f0f7e2f: Avoid draft-marker false positives when a packed Warden install scans the Trails framework source tree from a different package location.
|
|
21
|
+
- 64fb15a: Add Warden rules for trail version lifecycle guidance, version gaps, marker-safe schemas, pinned composes, examples, and pending force audit events.
|
|
22
|
+
- 5d88104: Polish Trails blaze terminology across package docs and Warden guidance.
|
|
23
|
+
- 48d5ff4: Attach term-rewrite fix metadata to the `no-legacy-layer-imports` rule, marking it review-required with no mechanical edits (the legacy layers were removed, not renamed) so `warden --fix` reports but never auto-applies the migration.
|
|
24
|
+
- 216bf10: Fix a false `dead-internal-trail` warning by unioning file-local compose evidence with the project-context compose set, so same-file composition in scanned-but-unregistered packages is recognized.
|
|
25
|
+
- 678cb1c: Expose the shared adapter readiness engine through Warden's opt-in
|
|
26
|
+
`--adapter-check` diagnostics and the local `trails adapter check` authoring
|
|
27
|
+
workflow.
|
|
28
|
+
- 5874fd6: Preserve diagnostic fix metadata through Warden rule trail outputs.
|
|
29
|
+
- 619cb15: Add a Warden rule (`no-destructured-compose`) that coaches trail blazes to call `ctx.compose(...)` directly instead of destructuring `compose` from the context.
|
|
30
|
+
|
|
31
|
+
Keep the generated `create` trail on the direct `ctx.compose(...)` shape so framework-authored trails follow the same composition guidance.
|
|
32
|
+
|
|
33
|
+
- 4642268: Make the standalone `warden --help` entry point print CLI help instead of running Warden with an unknown-option diagnostic.
|
|
34
|
+
- 9bab0cf: Follow schema aliases when detecting hidden optional wrappers in version marker
|
|
35
|
+
schemas.
|
|
36
|
+
- 3ceeba8: Expand marker-schema-unsupported diagnostics to catch Zod schema constructs that
|
|
37
|
+
runtime marker derivation rejects.
|
|
38
|
+
- beafd03: Add a warning for blazes that re-wrap an existing Result error with Result.err(result.error) instead of returning the original Result.
|
|
39
|
+
- 7b173e0: Warn when a `resource('id', { ... })` definition declares neither a `mock` factory nor an explicit `unmockable` reason, so `testAll(app)` can provision it without production configuration (common pitfall #10).
|
|
40
|
+
- 6e50e7b: Recognize Result-returning helper provenance when helpers use an imported Result type alias.
|
|
41
|
+
- 48edf8d: Expose shared Warden source scan-target predicates so downstream consumers can
|
|
42
|
+
preserve the CLI runner's test and declaration-file filtering before invoking
|
|
43
|
+
Warden-owned rules directly.
|
|
44
|
+
- 12ffa3b: Align Warden signal-rule trail examples so producer trails call `ctx.fire()` for their declared signals.
|
|
45
|
+
- 2f262f7: Improve Warden diagnostics so names-only findings teach the canonical fix instead of only naming the violation.
|
|
46
|
+
- 58b01f2: Warn when topo export modules open Trails surfaces at module top level.
|
|
47
|
+
- Updated dependencies [bb81ffe]
|
|
48
|
+
- Updated dependencies [e41c382]
|
|
49
|
+
- Updated dependencies [a2f1825]
|
|
50
|
+
- Updated dependencies [a2f1825]
|
|
51
|
+
- Updated dependencies [1eb5bdc]
|
|
52
|
+
- Updated dependencies [f8d80b9]
|
|
53
|
+
- Updated dependencies [846a597]
|
|
54
|
+
- Updated dependencies [223aaad]
|
|
55
|
+
- Updated dependencies [3125f4d]
|
|
56
|
+
- Updated dependencies [2494dc6]
|
|
57
|
+
- Updated dependencies [4bc8a99]
|
|
58
|
+
- Updated dependencies [120caf5]
|
|
59
|
+
- Updated dependencies [2d53717]
|
|
60
|
+
- Updated dependencies [16cb740]
|
|
61
|
+
- Updated dependencies [8894ecb]
|
|
62
|
+
- Updated dependencies [fdf7ec9]
|
|
63
|
+
- Updated dependencies [92e709b]
|
|
64
|
+
- Updated dependencies [d76be13]
|
|
65
|
+
- Updated dependencies [84f56a5]
|
|
66
|
+
- Updated dependencies [653d1fc]
|
|
67
|
+
- Updated dependencies [431b04c]
|
|
68
|
+
- Updated dependencies [2e76288]
|
|
69
|
+
- Updated dependencies [5d88104]
|
|
70
|
+
- Updated dependencies [f04a9ef]
|
|
71
|
+
- Updated dependencies [fc00aeb]
|
|
72
|
+
- Updated dependencies [ab1c77c]
|
|
73
|
+
- Updated dependencies [4f43874]
|
|
74
|
+
- Updated dependencies [678cb1c]
|
|
75
|
+
- @ontrails/adapter-kit@1.0.0-beta.19
|
|
76
|
+
- @ontrails/core@1.0.0-beta.19
|
|
77
|
+
- @ontrails/cli@1.0.0-beta.19
|
|
78
|
+
- @ontrails/store@1.0.0-beta.19
|
|
79
|
+
- @ontrails/topographer@1.0.0-beta.19
|
|
80
|
+
- @ontrails/permits@1.0.0-beta.19
|
|
81
|
+
|
|
82
|
+
## 1.0.0-beta.18
|
|
83
|
+
|
|
84
|
+
### Patch Changes
|
|
85
|
+
|
|
86
|
+
- @ontrails/cli@1.0.0-beta.18
|
|
87
|
+
- @ontrails/core@1.0.0-beta.18
|
|
88
|
+
- @ontrails/permits@1.0.0-beta.18
|
|
89
|
+
- @ontrails/store@1.0.0-beta.18
|
|
90
|
+
- @ontrails/topographer@1.0.0-beta.18
|
|
91
|
+
|
|
3
92
|
## 1.0.0-beta.17
|
|
4
93
|
|
|
5
94
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
# @ontrails/warden
|
|
2
2
|
|
|
3
|
-
AST-based code convention rules for Trails. Built-in lint rules catch contract
|
|
4
|
-
violations at development time, alongside lock drift detection and CI
|
|
5
|
-
formatters.
|
|
3
|
+
AST-based code convention rules for Trails. Built-in lint rules catch contract violations at development time, alongside lock drift detection and CI formatters.
|
|
6
4
|
|
|
7
|
-
Structural checks (
|
|
8
|
-
recursive crossing, example schema validation) live in `validateTopo()` from
|
|
9
|
-
`@ontrails/core`. Warden handles the code-level rules that need AST analysis.
|
|
5
|
+
Structural checks (compose target existence, declared resource existence, recursive composition, example schema validation) live in `validateTopo()` from `@ontrails/core`. Warden handles the code-level rules that need AST analysis.
|
|
10
6
|
|
|
11
|
-
For rule-home boundaries and authoring doctrine, see the
|
|
12
|
-
[Warden guide](../../docs/warden.md) and
|
|
13
|
-
[Rule Design](../../docs/rule-design.md).
|
|
7
|
+
For rule-home boundaries and authoring doctrine, see the [Warden guide](../../docs/warden.md) and [Warden Rules](../../docs/contributing/warden-rules.md).
|
|
14
8
|
|
|
15
9
|
## Usage
|
|
16
10
|
|
|
@@ -31,22 +25,17 @@ console.log(formatWardenReport(report));
|
|
|
31
25
|
|
|
32
26
|
## Rules
|
|
33
27
|
|
|
34
|
-
Built-in rules are registered in `wardenRules` and `wardenTopoRules`; use those
|
|
35
|
-
registries or `wardenTopo.ids()` for the current rule list instead of copying a
|
|
36
|
-
static table into docs.
|
|
28
|
+
Built-in rules are registered in `wardenRules` and `wardenTopoRules`; use those registries or `wardenTopo.ids()` for the current rule list instead of copying a static table into docs.
|
|
37
29
|
|
|
38
30
|
Rules cover several families:
|
|
39
31
|
|
|
40
32
|
- blaze and `Result` contract checks
|
|
41
|
-
-
|
|
33
|
+
- compose, fire, resource, and detour declaration drift
|
|
42
34
|
- draft-state containment
|
|
43
35
|
- source-static guardrails such as surface-type leakage
|
|
44
36
|
- topo-aware checks that need the resolved graph or resource mock shape
|
|
45
37
|
|
|
46
|
-
When adding or auditing rules, follow [
|
|
47
|
-
name the invariant, import owner-held framework data, choose the narrowest
|
|
48
|
-
Warden tier, and collapse families only when the data model, traversal, and
|
|
49
|
-
diagnostic shape are shared.
|
|
38
|
+
When adding or auditing rules, follow [Warden Rules](../../docs/contributing/warden-rules.md): name the invariant, import owner-held framework data, choose the narrowest Warden tier, and collapse families only when the data model, traversal, and diagnostic shape are shared.
|
|
50
39
|
|
|
51
40
|
## Drift detection
|
|
52
41
|
|
|
@@ -57,7 +46,7 @@ import { checkDrift } from '@ontrails/warden';
|
|
|
57
46
|
|
|
58
47
|
const drift = await checkDrift(process.cwd(), graph);
|
|
59
48
|
if (drift.stale) {
|
|
60
|
-
console.log('lock file is stale -- regenerate with `trails
|
|
49
|
+
console.log('lock file is stale -- regenerate with `trails compile`');
|
|
61
50
|
}
|
|
62
51
|
```
|
|
63
52
|
|
|
@@ -83,8 +72,7 @@ import {
|
|
|
83
72
|
} from '@ontrails/warden';
|
|
84
73
|
```
|
|
85
74
|
|
|
86
|
-
Parser helpers for rule authoring and repo-local tooling live on the dedicated
|
|
87
|
-
AST entrypoint:
|
|
75
|
+
Parser helpers for rule authoring and repo-local tooling live on the dedicated AST entrypoint:
|
|
88
76
|
|
|
89
77
|
```typescript
|
|
90
78
|
import { findStringLiterals, parse, walk } from '@ontrails/warden/ast';
|
|
@@ -92,8 +80,7 @@ import { findStringLiterals, parse, walk } from '@ontrails/warden/ast';
|
|
|
92
80
|
|
|
93
81
|
## Trail-based API
|
|
94
82
|
|
|
95
|
-
Every built-in warden rule is also available as a composable trail. This makes
|
|
96
|
-
rules queryable, testable, and invocable through any Trails surface.
|
|
83
|
+
Every built-in warden rule is also available as a composable trail. This makes rules queryable, testable, and invocable through any Trails surface.
|
|
97
84
|
|
|
98
85
|
```typescript
|
|
99
86
|
import {
|
|
@@ -115,8 +102,7 @@ const diagnostics = await runWardenTrails(filePath, sourceCode, {
|
|
|
115
102
|
const topoDiagnostics = await runTopoAwareWardenTrails(myApp);
|
|
116
103
|
```
|
|
117
104
|
|
|
118
|
-
To wrap a custom rule as a trail, import `wrapRule` from the root package
|
|
119
|
-
entrypoint:
|
|
105
|
+
To wrap a custom rule as a trail, import `wrapRule` from the root package entrypoint:
|
|
120
106
|
|
|
121
107
|
```typescript
|
|
122
108
|
import { wrapRule } from '@ontrails/warden';
|
|
@@ -143,13 +129,9 @@ This is the same factory used internally to build all built-in rule trails.
|
|
|
143
129
|
| `formatSummary(report)` | Compact summary line |
|
|
144
130
|
| `wrapRule(rule)` | Wrap a custom rule as a trail (same factory used for all built-in rule trails) |
|
|
145
131
|
|
|
146
|
-
AST parser helpers are exported from `@ontrails/warden/ast`, not the root
|
|
147
|
-
runtime barrel. The stable authoring surface includes `parse`, `walk`,
|
|
148
|
-
`walkScope`, `offsetToLine`, `findTrailDefinitions`, `findBlazeBodies`,
|
|
149
|
-
`findContourDefinitions`, `isBlazeCall`, and string-literal helpers.
|
|
132
|
+
AST parser helpers are exported from `@ontrails/warden/ast`, not the root runtime barrel. The stable authoring surface includes `parse`, `walk`, `walkScope`, `offsetToLine`, `findTrailDefinitions`, `findBlazeBodies`, `findContourDefinitions`, `isBlazeCall`, and string-literal helpers.
|
|
150
133
|
|
|
151
|
-
`runWarden({ tier })` can narrow a run to `source-static`, `project-static`,
|
|
152
|
-
`topo-aware`, `drift`, or `advisory`. Omit `tier` for the default full run.
|
|
134
|
+
`runWarden({ tier })` can narrow a run to `source-static`, `project-static`, `topo-aware`, `drift`, or `advisory`. Omit `tier` for the default full run.
|
|
153
135
|
|
|
154
136
|
See the [API Reference](../../docs/api-reference.md) for the full list.
|
|
155
137
|
|
package/bin/warden.ts
CHANGED
|
@@ -3,9 +3,37 @@
|
|
|
3
3
|
|
|
4
4
|
import { runWardenCommand } from '../src/command.js';
|
|
5
5
|
|
|
6
|
+
const HELP = `Usage: warden [options]
|
|
7
|
+
|
|
8
|
+
Run Trails Warden governance checks.
|
|
9
|
+
|
|
10
|
+
Options:
|
|
11
|
+
--ci Apply CI defaults
|
|
12
|
+
--pre-push Apply pre-push defaults
|
|
13
|
+
--apps, -a <names> Comma-delimited Trails app names
|
|
14
|
+
--config-path <path> Path to trails.config.* file
|
|
15
|
+
--root-dir <path> Project root to inspect
|
|
16
|
+
--fix Apply safe source fixes
|
|
17
|
+
--adapter-check Include shared adapter authoring diagnostics
|
|
18
|
+
--depth <value> source, project, topo, or all
|
|
19
|
+
--fail-on <value> error or warning
|
|
20
|
+
--format <value> summary, github, or json
|
|
21
|
+
--drafts <value> include, exclude, or only
|
|
22
|
+
--lock <value> auto, cached, refresh, or skip
|
|
23
|
+
--no-lock-mutation Do not write lock artifacts
|
|
24
|
+
--strict Fail on warnings
|
|
25
|
+
-h, --help Display help for command
|
|
26
|
+
`;
|
|
27
|
+
|
|
28
|
+
const args = Bun.argv.slice(2);
|
|
29
|
+
if (args.includes('--help') || args.includes('-h') || args[0] === 'help') {
|
|
30
|
+
console.log(HELP);
|
|
31
|
+
process.exit(0);
|
|
32
|
+
}
|
|
33
|
+
|
|
6
34
|
const env = { ...process.env } as Record<string, string | undefined>;
|
|
7
35
|
const result = await runWardenCommand({
|
|
8
|
-
args
|
|
36
|
+
args,
|
|
9
37
|
cwd: process.cwd(),
|
|
10
38
|
env,
|
|
11
39
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ontrails/warden",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.19",
|
|
4
4
|
"bin": {
|
|
5
5
|
"warden": "./bin/warden.ts"
|
|
6
6
|
},
|
|
@@ -28,19 +28,20 @@
|
|
|
28
28
|
"clean": "rm -rf dist *.tsbuildinfo"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@ontrails/
|
|
32
|
-
"@ontrails/
|
|
33
|
-
"@ontrails/
|
|
31
|
+
"@ontrails/adapter-kit": "^1.0.0-beta.19",
|
|
32
|
+
"@ontrails/cli": "^1.0.0-beta.19",
|
|
33
|
+
"@ontrails/permits": "^1.0.0-beta.19",
|
|
34
|
+
"@ontrails/store": "^1.0.0-beta.19",
|
|
34
35
|
"oxc-parser": "^0.121.0",
|
|
35
36
|
"oxc-resolver": "11.19.1",
|
|
36
37
|
"zod": "^4.3.5"
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
|
39
|
-
"@ontrails/config": "^1.0.0-beta.
|
|
40
|
-
"@ontrails/testing": "^1.0.0-beta.
|
|
40
|
+
"@ontrails/config": "^1.0.0-beta.19",
|
|
41
|
+
"@ontrails/testing": "^1.0.0-beta.19"
|
|
41
42
|
},
|
|
42
43
|
"peerDependencies": {
|
|
43
|
-
"@ontrails/core": "^1.0.0-beta.
|
|
44
|
-
"@ontrails/topographer": "^1.0.0-beta.
|
|
44
|
+
"@ontrails/core": "^1.0.0-beta.19",
|
|
45
|
+
"@ontrails/topographer": "^1.0.0-beta.19"
|
|
45
46
|
}
|
|
46
47
|
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Warden projection for shared adapter readiness checks.
|
|
3
|
+
*
|
|
4
|
+
* Adapter facts stay in @ontrails/adapter-kit. Warden only maps those facts
|
|
5
|
+
* into governance diagnostics and severity.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { checkAdapters } from '@ontrails/adapter-kit';
|
|
9
|
+
import type { AdapterCheckDiagnostic } from '@ontrails/adapter-kit';
|
|
10
|
+
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
11
|
+
import { join } from 'node:path';
|
|
12
|
+
|
|
13
|
+
import type { WardenDiagnostic } from './rules/types.js';
|
|
14
|
+
|
|
15
|
+
export const adapterCheckRuleName = 'adapter-check';
|
|
16
|
+
const adapterCheckRootCode = 'adapter-check-root';
|
|
17
|
+
|
|
18
|
+
const isRecord = (value: unknown): value is Readonly<Record<string, unknown>> =>
|
|
19
|
+
typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
20
|
+
|
|
21
|
+
const toWardenDiagnostic = (
|
|
22
|
+
diagnostic: AdapterCheckDiagnostic
|
|
23
|
+
): WardenDiagnostic => ({
|
|
24
|
+
code: diagnostic.code,
|
|
25
|
+
filePath: diagnostic.packageJsonPath,
|
|
26
|
+
line: 1,
|
|
27
|
+
message: diagnostic.message,
|
|
28
|
+
rule: adapterCheckRuleName,
|
|
29
|
+
severity: 'warn',
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const toRootDiagnostic = (
|
|
33
|
+
message: string,
|
|
34
|
+
filePath: string
|
|
35
|
+
): WardenDiagnostic => ({
|
|
36
|
+
code: adapterCheckRootCode,
|
|
37
|
+
filePath,
|
|
38
|
+
line: 1,
|
|
39
|
+
message,
|
|
40
|
+
rule: adapterCheckRuleName,
|
|
41
|
+
severity: 'error',
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const workspacePatternsFromManifest = (
|
|
45
|
+
manifest: Readonly<Record<string, unknown>>
|
|
46
|
+
): readonly string[] => {
|
|
47
|
+
const { workspaces } = manifest;
|
|
48
|
+
if (Array.isArray(workspaces)) {
|
|
49
|
+
return workspaces.filter(
|
|
50
|
+
(pattern): pattern is string => typeof pattern === 'string'
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const packages = isRecord(workspaces) ? workspaces['packages'] : undefined;
|
|
55
|
+
return Array.isArray(packages)
|
|
56
|
+
? packages.filter(
|
|
57
|
+
(pattern): pattern is string => typeof pattern === 'string'
|
|
58
|
+
)
|
|
59
|
+
: [];
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const validateAdapterCheckRoot = (
|
|
63
|
+
rootDir: string
|
|
64
|
+
): readonly WardenDiagnostic[] => {
|
|
65
|
+
if (!existsSync(rootDir)) {
|
|
66
|
+
return [
|
|
67
|
+
toRootDiagnostic(
|
|
68
|
+
`adapter.check rootDir does not exist: "${rootDir}"`,
|
|
69
|
+
rootDir
|
|
70
|
+
),
|
|
71
|
+
];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (!statSync(rootDir).isDirectory()) {
|
|
75
|
+
return [
|
|
76
|
+
toRootDiagnostic(
|
|
77
|
+
`adapter.check rootDir must be a directory: "${rootDir}"`,
|
|
78
|
+
rootDir
|
|
79
|
+
),
|
|
80
|
+
];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const packageJsonPath = join(rootDir, 'package.json');
|
|
84
|
+
if (!existsSync(packageJsonPath)) {
|
|
85
|
+
return [
|
|
86
|
+
toRootDiagnostic(
|
|
87
|
+
`adapter.check rootDir must contain a package.json workspace manifest: "${packageJsonPath}"`,
|
|
88
|
+
packageJsonPath
|
|
89
|
+
),
|
|
90
|
+
];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
let manifest: unknown;
|
|
94
|
+
try {
|
|
95
|
+
manifest = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
96
|
+
} catch (error) {
|
|
97
|
+
const reason = error instanceof Error ? `: ${error.message}` : '';
|
|
98
|
+
return [
|
|
99
|
+
toRootDiagnostic(
|
|
100
|
+
`adapter.check could not read root package.json: "${packageJsonPath}"${reason}`,
|
|
101
|
+
packageJsonPath
|
|
102
|
+
),
|
|
103
|
+
];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (!isRecord(manifest)) {
|
|
107
|
+
return [
|
|
108
|
+
toRootDiagnostic(
|
|
109
|
+
`adapter.check root package.json must contain a JSON object: "${packageJsonPath}"`,
|
|
110
|
+
packageJsonPath
|
|
111
|
+
),
|
|
112
|
+
];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (workspacePatternsFromManifest(manifest).length === 0) {
|
|
116
|
+
return [
|
|
117
|
+
toRootDiagnostic(
|
|
118
|
+
`adapter.check root package.json must declare workspace packages: "${packageJsonPath}"`,
|
|
119
|
+
packageJsonPath
|
|
120
|
+
),
|
|
121
|
+
];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return [];
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export const runWardenAdapterChecks = (
|
|
128
|
+
rootDir: string
|
|
129
|
+
): readonly WardenDiagnostic[] => {
|
|
130
|
+
const rootDiagnostics = validateAdapterCheckRoot(rootDir);
|
|
131
|
+
if (rootDiagnostics.length > 0) {
|
|
132
|
+
return rootDiagnostics;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return checkAdapters(rootDir).diagnostics.map(toWardenDiagnostic);
|
|
136
|
+
};
|