@webpieces/nx-webpieces-rules 0.4.847 → 0.4.849
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/README.md +28 -15
- package/executors.json +1 -66
- package/package.json +9 -9
- package/src/executors/validate-architecture-unchanged/executor.d.ts +8 -0
- package/src/executors/validate-architecture-unchanged/executor.js +20 -18
- package/src/executors/validate-architecture-unchanged/executor.js.map +1 -1
- package/src/executors/validate-code/executor.d.ts +2 -7
- package/src/executors/validate-code/executor.js +31 -2
- package/src/executors/validate-code/executor.js.map +1 -1
- package/src/executors/validate-code/schema.json +6 -281
- package/src/executors/validate-runtime-architecture/schema.json +1 -1
- package/src/lib/api-usage/wire-closure.d.ts +3 -3
- package/src/lib/api-usage/wire-closure.js +5 -5
- package/src/lib/api-usage/wire-closure.js.map +1 -1
- package/src/lib/api-usage/wire-suffix-entry.d.ts +5 -0
- package/src/lib/api-usage/wire-suffix-entry.js +10 -0
- package/src/lib/api-usage/wire-suffix-entry.js.map +1 -0
- package/src/lib/rule-gate.d.ts +1 -2
- package/src/lib/rule-gate.js +3 -4
- package/src/lib/rule-gate.js.map +1 -1
- package/src/lib/runtime-visualizer.d.ts +4 -4
- package/src/lib/runtime-visualizer.js +2 -2
- package/src/lib/runtime-visualizer.js.map +1 -1
- package/src/native-actions.d.ts +23 -0
- package/src/native-actions.js +69 -0
- package/src/native-actions.js.map +1 -0
- package/src/nx-policy-registry.d.ts +8 -0
- package/src/nx-policy-registry.js +40 -0
- package/src/nx-policy-registry.js.map +1 -0
- package/src/pack-build-runner.d.ts +6 -0
- package/src/pack-build-runner.js +46 -0
- package/src/pack-build-runner.js.map +1 -0
- package/src/plugin.js +6 -40
- package/src/plugin.js.map +1 -1
- package/src/rule-help.d.ts +3 -0
- package/src/rule-help.js +24 -0
- package/src/rule-help.js.map +1 -0
- package/src/rule-pack.js +5 -28
- package/src/rule-pack.js.map +1 -1
- package/src/rule-runtime.d.ts +5 -0
- package/src/rule-runtime.js +94 -0
- package/src/rule-runtime.js.map +1 -0
- package/src/validation-targets.js +21 -5
- package/src/validation-targets.js.map +1 -1
- package/src/executors/validate-catch-error-pattern/executor.d.ts +0 -4
- package/src/executors/validate-catch-error-pattern/executor.js +0 -8
- package/src/executors/validate-catch-error-pattern/executor.js.map +0 -1
- package/src/executors/validate-catch-error-pattern/schema.json +0 -24
- package/src/executors/validate-dtos/executor.d.ts +0 -4
- package/src/executors/validate-dtos/executor.js +0 -8
- package/src/executors/validate-dtos/executor.js.map +0 -1
- package/src/executors/validate-dtos/schema.json +0 -33
- package/src/executors/validate-modified-files/executor.d.ts +0 -4
- package/src/executors/validate-modified-files/executor.js +0 -8
- package/src/executors/validate-modified-files/executor.js.map +0 -1
- package/src/executors/validate-modified-files/schema.json +0 -25
- package/src/executors/validate-modified-methods/executor.d.ts +0 -4
- package/src/executors/validate-modified-methods/executor.js +0 -8
- package/src/executors/validate-modified-methods/executor.js.map +0 -1
- package/src/executors/validate-modified-methods/schema.json +0 -25
- package/src/executors/validate-new-methods/executor.d.ts +0 -4
- package/src/executors/validate-new-methods/executor.js +0 -8
- package/src/executors/validate-new-methods/executor.js.map +0 -1
- package/src/executors/validate-new-methods/schema.json +0 -25
- package/src/executors/validate-no-any-unknown/executor.d.ts +0 -4
- package/src/executors/validate-no-any-unknown/executor.js +0 -8
- package/src/executors/validate-no-any-unknown/executor.js.map +0 -1
- package/src/executors/validate-no-any-unknown/schema.json +0 -24
- package/src/executors/validate-no-destructure/executor.d.ts +0 -4
- package/src/executors/validate-no-destructure/executor.js +0 -8
- package/src/executors/validate-no-destructure/executor.js.map +0 -1
- package/src/executors/validate-no-destructure/schema.json +0 -24
- package/src/executors/validate-no-direct-api-resolver/executor.d.ts +0 -4
- package/src/executors/validate-no-direct-api-resolver/executor.js +0 -8
- package/src/executors/validate-no-direct-api-resolver/executor.js.map +0 -1
- package/src/executors/validate-no-direct-api-resolver/schema.json +0 -29
- package/src/executors/validate-no-implicit-any/executor.d.ts +0 -4
- package/src/executors/validate-no-implicit-any/executor.js +0 -8
- package/src/executors/validate-no-implicit-any/executor.js.map +0 -1
- package/src/executors/validate-no-implicit-any/schema.json +0 -24
- package/src/executors/validate-no-inline-types/executor.d.ts +0 -4
- package/src/executors/validate-no-inline-types/executor.js +0 -8
- package/src/executors/validate-no-inline-types/executor.js.map +0 -1
- package/src/executors/validate-no-inline-types/schema.json +0 -24
- package/src/executors/validate-no-unmanaged-exceptions/executor.d.ts +0 -4
- package/src/executors/validate-no-unmanaged-exceptions/executor.js +0 -8
- package/src/executors/validate-no-unmanaged-exceptions/executor.js.map +0 -1
- package/src/executors/validate-no-unmanaged-exceptions/schema.json +0 -24
- package/src/executors/validate-prisma-converters/executor.d.ts +0 -4
- package/src/executors/validate-prisma-converters/executor.js +0 -8
- package/src/executors/validate-prisma-converters/executor.js.map +0 -1
- package/src/executors/validate-prisma-converters/schema.json +0 -38
- package/src/executors/validate-return-types/executor.d.ts +0 -4
- package/src/executors/validate-return-types/executor.js +0 -8
- package/src/executors/validate-return-types/executor.js.map +0 -1
- package/src/executors/validate-return-types/schema.json +0 -24
package/README.md
CHANGED
|
@@ -27,32 +27,45 @@ It is wired into the build: the `@nx/js:tsc` target default lists it in
|
|
|
27
27
|
|
|
28
28
|
### Configuration
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
the rule key `no-file-import-cycles`:
|
|
30
|
+
`webpieces.config.json` declares each owning pack and its config path in the root
|
|
31
|
+
`rulePacks` array. For example, the Nx entry is:
|
|
33
32
|
|
|
34
|
-
```
|
|
33
|
+
```json
|
|
35
34
|
{
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
35
|
+
"package": "@webpieces/nx-webpieces-rules",
|
|
36
|
+
"config": ".webpieces/rules/nx.json"
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Keep the other selected owners and required root settings. Policy settings come
|
|
41
|
+
from the declared owner file's direct policy-ID map. This entry belongs directly
|
|
42
|
+
in `.webpieces/rules/nx.json` (an excerpt; the other owned policies also require
|
|
43
|
+
explicit settings):
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"no-file-import-cycles": {
|
|
48
|
+
"mode": "RUN_EVERY_TIME",
|
|
49
|
+
"turnOffRuleUntilEpoch": 0,
|
|
50
|
+
"turnOffRuleWhileOnBranch": null,
|
|
51
|
+
"ignoreTypeOnly": false
|
|
46
52
|
}
|
|
47
53
|
}
|
|
48
54
|
```
|
|
49
55
|
|
|
56
|
+
Use complete `OFF` settings for an intentional opt-out. `ignoreTypeOnly: true`
|
|
57
|
+
ignores type-only import/re-export cycles. A future `turnOffRuleUntilEpoch` value
|
|
58
|
+
uses epoch seconds; `0` and a `null` branch hatch keep enforcement active.
|
|
59
|
+
After reviewing the declarations, `pnpm wp-rules-sync` explicitly seeds missing
|
|
60
|
+
owner settings and refreshes the lock/catalog artifacts. Review and commit its
|
|
61
|
+
changes; normal loading never supplies missing required settings.
|
|
62
|
+
|
|
50
63
|
Semantics, mirroring the method/file-size dated-disable model:
|
|
51
64
|
|
|
52
65
|
| Situation | Result |
|
|
53
66
|
| ------------------------------------------- | ------------------------------- |
|
|
54
67
|
| `mode: "OFF"` | Skipped (passes), no madge run |
|
|
55
|
-
| Cycle found,
|
|
68
|
+
| Cycle found, `turnOffRuleUntilEpoch: 0` | **Fails** |
|
|
56
69
|
| Cycle found, `now < turnOffRuleUntilEpoch` | Reported but **passes** (warn) |
|
|
57
70
|
| Cycle found, `now >= turnOffRuleUntilEpoch` | **Fails** again |
|
|
58
71
|
| No cycle | Passes |
|
package/executors.json
CHANGED
|
@@ -65,75 +65,10 @@
|
|
|
65
65
|
"schema": "./src/executors/validate-rules-config/schema.json",
|
|
66
66
|
"description": "Validate webpieces.config.json once at the scoped rules:check boundary"
|
|
67
67
|
},
|
|
68
|
-
"validate-no-any-unknown": {
|
|
69
|
-
"implementation": "./src/executors/validate-no-any-unknown/executor",
|
|
70
|
-
"schema": "./src/executors/validate-no-any-unknown/schema.json",
|
|
71
|
-
"description": "Validate no any/unknown keywords are used - use specific types instead"
|
|
72
|
-
},
|
|
73
|
-
"validate-new-methods": {
|
|
74
|
-
"implementation": "./src/executors/validate-new-methods/executor",
|
|
75
|
-
"schema": "./src/executors/validate-new-methods/schema.json",
|
|
76
|
-
"description": "Validate newly added methods don't exceed maximum line count"
|
|
77
|
-
},
|
|
78
|
-
"validate-modified-methods": {
|
|
79
|
-
"implementation": "./src/executors/validate-modified-methods/executor",
|
|
80
|
-
"schema": "./src/executors/validate-modified-methods/schema.json",
|
|
81
|
-
"description": "Validate modified methods don't exceed maximum line count"
|
|
82
|
-
},
|
|
83
|
-
"validate-modified-files": {
|
|
84
|
-
"implementation": "./src/executors/validate-modified-files/executor",
|
|
85
|
-
"schema": "./src/executors/validate-modified-files/schema.json",
|
|
86
|
-
"description": "Validate modified files don't exceed maximum line count"
|
|
87
|
-
},
|
|
88
|
-
"validate-return-types": {
|
|
89
|
-
"implementation": "./src/executors/validate-return-types/executor",
|
|
90
|
-
"schema": "./src/executors/validate-return-types/schema.json",
|
|
91
|
-
"description": "Validate methods have explicit return type annotations"
|
|
92
|
-
},
|
|
93
|
-
"validate-no-inline-types": {
|
|
94
|
-
"implementation": "./src/executors/validate-no-inline-types/executor",
|
|
95
|
-
"schema": "./src/executors/validate-no-inline-types/schema.json",
|
|
96
|
-
"description": "Validate no inline type literals are used - prefer named types"
|
|
97
|
-
},
|
|
98
|
-
"validate-no-implicit-any": {
|
|
99
|
-
"implementation": "./src/executors/validate-no-implicit-any/executor",
|
|
100
|
-
"schema": "./src/executors/validate-no-implicit-any/schema.json",
|
|
101
|
-
"description": "Validate no implicit-any inferences on parameters, variables, or properties"
|
|
102
|
-
},
|
|
103
|
-
"validate-catch-error-pattern": {
|
|
104
|
-
"implementation": "./src/executors/validate-catch-error-pattern/executor",
|
|
105
|
-
"schema": "./src/executors/validate-catch-error-pattern/schema.json",
|
|
106
|
-
"description": "Validate catch blocks follow standardized pattern: catch (err: unknown) { const error = toError(err); }"
|
|
107
|
-
},
|
|
108
|
-
"validate-no-unmanaged-exceptions": {
|
|
109
|
-
"implementation": "./src/executors/validate-no-unmanaged-exceptions/executor",
|
|
110
|
-
"schema": "./src/executors/validate-no-unmanaged-exceptions/schema.json",
|
|
111
|
-
"description": "Validate try/catch blocks are not used outside chokepoints"
|
|
112
|
-
},
|
|
113
|
-
"validate-no-destructure": {
|
|
114
|
-
"implementation": "./src/executors/validate-no-destructure/executor",
|
|
115
|
-
"schema": "./src/executors/validate-no-destructure/schema.json",
|
|
116
|
-
"description": "Validate no destructuring patterns are used - use explicit property access instead"
|
|
117
|
-
},
|
|
118
|
-
"validate-no-direct-api-resolver": {
|
|
119
|
-
"implementation": "./src/executors/validate-no-direct-api-resolver/executor",
|
|
120
|
-
"schema": "./src/executors/validate-no-direct-api-resolver/schema.json",
|
|
121
|
-
"description": "Validate resolvers use services (not APIs) and components subscribe to observables (not route.snapshot.data)"
|
|
122
|
-
},
|
|
123
|
-
"validate-dtos": {
|
|
124
|
-
"implementation": "./src/executors/validate-dtos/executor",
|
|
125
|
-
"schema": "./src/executors/validate-dtos/schema.json",
|
|
126
|
-
"description": "Validate DTO fields match Prisma Dbo model fields"
|
|
127
|
-
},
|
|
128
|
-
"validate-prisma-converters": {
|
|
129
|
-
"implementation": "./src/executors/validate-prisma-converters/executor",
|
|
130
|
-
"schema": "./src/executors/validate-prisma-converters/schema.json",
|
|
131
|
-
"description": "Validate Prisma converter method patterns and Dto creation locations"
|
|
132
|
-
},
|
|
133
68
|
"validate-code": {
|
|
134
69
|
"implementation": "./src/executors/validate-code/executor",
|
|
135
70
|
"schema": "./src/executors/validate-code/schema.json",
|
|
136
|
-
"description": "
|
|
71
|
+
"description": "Execute declared build contributions through their public owner runtimes, with optional single-rule debug execution"
|
|
137
72
|
},
|
|
138
73
|
"help": {
|
|
139
74
|
"implementation": "./src/executors/help/executor",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webpieces/nx-webpieces-rules",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.849",
|
|
4
4
|
"description": "Nx-specific webpieces validation rules, graph tooling, executors, and inference plugin.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"./package.json": "./package.json",
|
|
11
11
|
"./plugin": "./src/plugin.js",
|
|
12
12
|
"./executors.json": "./executors.json",
|
|
13
|
-
"./rule-pack": "./src/rule-pack.js"
|
|
13
|
+
"./rule-pack": "./src/rule-pack.js",
|
|
14
|
+
"./rule-runtime": "./src/rule-runtime.js"
|
|
14
15
|
},
|
|
15
16
|
"files": [
|
|
16
17
|
"src/**/*",
|
|
@@ -19,13 +20,12 @@
|
|
|
19
20
|
"README.md"
|
|
20
21
|
],
|
|
21
22
|
"dependencies": {
|
|
22
|
-
"@webpieces/api-doc-model": "0.4.
|
|
23
|
-
"@webpieces/
|
|
24
|
-
"@webpieces/
|
|
25
|
-
"@webpieces/
|
|
26
|
-
"@webpieces/rules-config": "0.4.847",
|
|
23
|
+
"@webpieces/api-doc-model": "0.4.849",
|
|
24
|
+
"@webpieces/core-util": "0.4.849",
|
|
25
|
+
"@webpieces/eslint-rules": "0.4.849",
|
|
26
|
+
"@webpieces/rules-config": "0.4.849",
|
|
27
27
|
"madge": "8.0.0",
|
|
28
|
-
"@webpieces/rules-sdk": "0.4.
|
|
28
|
+
"@webpieces/rules-sdk": "0.4.849"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
31
|
"@nx/devkit": ">=18.0.0"
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"access": "public"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@webpieces/tooling-testkit": "0.4.
|
|
44
|
+
"@webpieces/tooling-testkit": "0.4.849"
|
|
45
45
|
},
|
|
46
46
|
"types": "./src/index.d.ts",
|
|
47
47
|
"bin": {
|
|
@@ -24,6 +24,14 @@ export interface ExecutorResult {
|
|
|
24
24
|
* fixing it is the same single command either way, so listing both adds noise rather than information.
|
|
25
25
|
*/
|
|
26
26
|
export declare function describeTableDrift(current: CurrentArchitecture, saved: DependenciesFile): string | null;
|
|
27
|
+
/**
|
|
28
|
+
* Build the current dependency graph exactly as the generator does: reduce the nx
|
|
29
|
+
* graph, sort into levels, enrich with metadata, and attach the derived
|
|
30
|
+
* apiRelations — so this validator compares like-for-like against the committed file.
|
|
31
|
+
*/
|
|
32
|
+
export declare class CurrentGraphBuilder {
|
|
33
|
+
build(workspaceRoot: string): Promise<CurrentArchitecture>;
|
|
34
|
+
}
|
|
27
35
|
/** The regenerated graph plus the two tables beside it — everything dependencies.json holds. */
|
|
28
36
|
export declare class CurrentArchitecture {
|
|
29
37
|
readonly graph: EnhancedGraph;
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* nx run architecture:validate-architecture-unchanged
|
|
10
10
|
*/
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.CurrentArchitecture = void 0;
|
|
12
|
+
exports.CurrentArchitecture = exports.CurrentGraphBuilder = void 0;
|
|
13
13
|
exports.describeTableDrift = describeTableDrift;
|
|
14
14
|
exports.default = runExecutor;
|
|
15
15
|
const rules_config_1 = require("@webpieces/rules-config");
|
|
@@ -112,23 +112,25 @@ function describeExternalSystemDrift(current, saved) {
|
|
|
112
112
|
* graph, sort into levels, enrich with metadata, and attach the derived
|
|
113
113
|
* apiRelations — so this validator compares like-for-like against the committed file.
|
|
114
114
|
*/
|
|
115
|
-
|
|
116
|
-
async
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
115
|
+
class CurrentGraphBuilder {
|
|
116
|
+
async build(workspaceRoot) {
|
|
117
|
+
console.log('📊 Generating current dependency graph...');
|
|
118
|
+
const reducedGraph = await (0, graph_generator_1.generateReducedGraph)();
|
|
119
|
+
console.log('🔄 Computing topological layers...');
|
|
120
|
+
const currentGraph = (0, graph_sorter_1.sortGraphTopologically)(reducedGraph);
|
|
121
|
+
console.log('🏷️ Enriching graph with framework + responsibilities metadata...');
|
|
122
|
+
const projectInfos = await (0, graph_metadata_1.collectProjectInfo)();
|
|
123
|
+
(0, graph_metadata_1.enrichGraph)(currentGraph, projectInfos, workspaceRoot);
|
|
124
|
+
new tag_truth_1.TagTruthCheck().assertTrue(currentGraph, projectInfos, workspaceRoot);
|
|
125
|
+
console.log('🔎 Scanning source for implements/uses API relations...');
|
|
126
|
+
// The SAME externalApiPaths the generator uses: scanning without them would drop every vendor
|
|
127
|
+
// relation from the regenerated graph and report drift against a perfectly fresh file.
|
|
128
|
+
const externalApiPaths = (0, runtime_config_1.loadRuntimeConfig)(workspaceRoot).externalApiPaths;
|
|
129
|
+
const scan = (0, api_scanner_1.scanAndAttachApiRelations)(workspaceRoot, currentGraph, projectInfos, externalApiPaths);
|
|
130
|
+
return new CurrentArchitecture(currentGraph, new api_contract_files_1.ApiContractFiles().refsFor((0, api_scanner_1.buildApiContracts)(scan)), (0, external_systems_1.buildExternalSystems)(scan.apiIndex, projectInfos));
|
|
131
|
+
}
|
|
131
132
|
}
|
|
133
|
+
exports.CurrentGraphBuilder = CurrentGraphBuilder;
|
|
132
134
|
/** The regenerated graph plus the two tables beside it — everything dependencies.json holds. */
|
|
133
135
|
class CurrentArchitecture {
|
|
134
136
|
graph;
|
|
@@ -170,7 +172,7 @@ async function runExecutor(options, context) {
|
|
|
170
172
|
}
|
|
171
173
|
// Steps 1-3: build + enrich + scan the current graph (same pipeline the
|
|
172
174
|
// generator runs, so any drift is caught).
|
|
173
|
-
const currentGraph = await
|
|
175
|
+
const currentGraph = await new CurrentGraphBuilder().build(workspaceRoot);
|
|
174
176
|
// Step 4: Load saved graph
|
|
175
177
|
console.log('📂 Loading saved graph...');
|
|
176
178
|
const savedGraph = (0, graph_loader_1.loadBlessedGraph)(workspaceRoot, graphPath);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/executors/validate-architecture-unchanged/executor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validate Architecture Unchanged Executor\n *\n * Validates that the current architecture graph matches the saved blessed graph.\n * This ensures no unapproved architecture changes have been made.\n *\n * Usage:\n * nx run architecture:validate-architecture-unchanged\n */\n\nimport type { ExecutorContext } from '@nx/devkit';\nimport { writeTemplate, RuleFailError, renderRuleFailForHuman } from '@webpieces/rules-config';\nimport { generateReducedGraph } from '../../lib/graph-generator';\nimport { sortGraphTopologically } from '../../lib/graph-sorter';\nimport { compareGraphs } from '../../lib/graph-comparator';\nimport { loadBlessedGraph, graphFileExists } from '../../lib/graph-loader';\nimport type { DependenciesFile } from '../../lib/graph-loader';\nimport { collectProjectInfo, enrichGraph, MetadataValidationError } from '../../lib/graph-metadata';\nimport { TagTruthCheck } from '../../lib/tag-truth';\nimport { scanAndAttachApiRelations, buildApiContracts } from '../../lib/api-usage/api-scanner';\nimport { buildExternalSystems } from '../../lib/api-usage/external-systems';\nimport type { ExternalSystemDecls } from '../../lib/api-usage/api-relations';\nimport { ApiContractFiles } from '../../lib/api-contract-files';\nimport type { ApiContractFileRefs } from '../../lib/api-contract-files';\nimport { loadRuntimeConfig } from '../../lib/runtime-config';\nimport { RuleGate } from '../../lib/rule-gate';\nimport type { EnhancedGraph } from '../../lib/graph-sorter';\nimport { toError } from '../../toError';\n\nexport interface ValidateArchitectureUnchangedOptions {\n graphPath?: string;\n}\n\nexport interface ExecutorResult {\n success: boolean;\n}\n\nconst TMP_MD_FILE = 'webpieces.dependencies.md';\n\n/**\n * Write the instructions documentation to .webpieces/instruct-ai/.\n * Sourced from @webpieces/rules-config.\n */\nfunction writeTmpInstructionsFile(workspaceRoot: string): string {\n const mdPath = writeTemplate(workspaceRoot, TMP_MD_FILE);\n\n return mdPath;\n}\n\n/**\n * Report a current-vs-saved graph mismatch and write the AI instructions file.\n */\nfunction reportMismatch(summary: string, workspaceRoot: string): void {\n const mdPath = writeTmpInstructionsFile(workspaceRoot);\n\n console.error('❌ Architecture has changed since last update!');\n console.error('\\nDifferences:');\n console.error(summary);\n console.error('');\n console.error('⚠️ *** Refer to ' + mdPath + ' for instructions on how to fix *** ⚠️');\n console.error('');\n console.error('To fix:');\n console.error(' 1. Review the changes above');\n console.error(' 2. If intentional, ASK USER to run: nx run architecture:generate since this is a critical change');\n console.error(' 3. Commit the updated architecture/dependencies.json');\n}\n\n/**\n * Which APIs dependencies.json links to a contract file, compared by LINK only — an added or removed\n * API. The endpoints inside `architecture/apis/<Api>.json` are deliberately NOT compared (#949): an\n * endpoint change must not fail this rule. Null when the links match.\n */\n// webpieces-disable no-function-outside-class -- executor step helper, matches reportMismatch in this file\nfunction describeContractLinkDrift(current: ApiContractFileRefs, saved: ApiContractFileRefs): string | null {\n const names = [...new Set([...Object.keys(current), ...Object.keys(saved)])].sort();\n const changes: string[] = [];\n for (const name of names) {\n const a = current[name];\n const b = saved[name];\n if (a === undefined) changes.push(` - ${name}: linked in dependencies.json but no longer in source`);\n else if (b === undefined) changes.push(` + ${name}: in source but not linked from dependencies.json`);\n else if (a !== b) changes.push(` ~ ${name}: contract file link changed (${b} -> ${a})`);\n }\n if (changes.length === 0) return null;\n return `apiContractFiles drift (${changes.length} api(s)):\\n${changes.join('\\n')}`;\n}\n\n/**\n * Drift in EITHER side table of dependencies.json — the api contract-file links or the\n * external-system declarations — or null when both match. The first difference found is reported;\n * fixing it is the same single command either way, so listing both adds noise rather than information.\n */\n// webpieces-disable no-function-outside-class -- executor step helper, matches describeContractLinkDrift above\nexport function describeTableDrift(current: CurrentArchitecture, saved: DependenciesFile): string | null {\n const linkDrift = describeContractLinkDrift(current.apiContractFiles, saved.apiContractFiles);\n if (linkDrift !== null) return linkDrift;\n return describeExternalSystemDrift(current.externalSystems, saved.externalSystems);\n}\n\n/**\n * The same drift report for the declared external systems, or null when they match. Named per\n * system so the message points at the database that changed rather than dumping two JSON blobs.\n */\n// webpieces-disable no-function-outside-class -- executor step helper, matches describeContractLinkDrift above\nfunction describeExternalSystemDrift(current: ExternalSystemDecls, saved: ExternalSystemDecls): string | null {\n const names = [...new Set([...Object.keys(current), ...Object.keys(saved)])].sort();\n const changes: string[] = [];\n for (const name of names) {\n const a = current[name];\n const b = saved[name];\n if (a === undefined) changes.push(` - ${name}: in dependencies.json but no longer declared in source`);\n else if (b === undefined) changes.push(` + ${name}: declared in source but missing from dependencies.json`);\n else if (JSON.stringify(a) !== JSON.stringify(b)) changes.push(` ~ ${name}: kind/label/declarers changed`);\n }\n if (changes.length === 0) return null;\n return `externalSystems drift (${changes.length} system(s)):\\n${changes.join('\\n')}`;\n}\n\n/**\n * Build the current dependency graph exactly as the generator does: reduce the nx\n * graph, sort into levels, enrich with metadata, and attach the derived\n * apiRelations — so this validator compares like-for-like against the committed file.\n */\n// webpieces-disable no-function-outside-class -- executor step helper, matches reportMismatch/writeTmpInstructionsFile in this file\nasync function buildCurrentGraph(workspaceRoot: string): Promise<CurrentArchitecture> {\n console.log('📊 Generating current dependency graph...');\n const reducedGraph = await generateReducedGraph();\n console.log('🔄 Computing topological layers...');\n const currentGraph = sortGraphTopologically(reducedGraph);\n console.log('🏷️ Enriching graph with framework + responsibilities metadata...');\n const projectInfos = await collectProjectInfo();\n enrichGraph(currentGraph, projectInfos, workspaceRoot);\n new TagTruthCheck().assertTrue(currentGraph, projectInfos, workspaceRoot);\n console.log('🔎 Scanning source for implements/uses API relations...');\n // The SAME externalApiPaths the generator uses: scanning without them would drop every vendor\n // relation from the regenerated graph and report drift against a perfectly fresh file.\n const externalApiPaths = loadRuntimeConfig(workspaceRoot).externalApiPaths;\n const scan = scanAndAttachApiRelations(workspaceRoot, currentGraph, projectInfos, externalApiPaths);\n return new CurrentArchitecture(\n currentGraph,\n new ApiContractFiles().refsFor(buildApiContracts(scan)),\n buildExternalSystems(scan.apiIndex, projectInfos),\n );\n}\n\n/** The regenerated graph plus the two tables beside it — everything dependencies.json holds. */\nexport class CurrentArchitecture {\n constructor(\n public readonly graph: EnhancedGraph,\n public readonly apiContractFiles: ApiContractFileRefs,\n public readonly externalSystems: ExternalSystemDecls,\n ) {}\n}\n\n/** The bootstrap path: there is nothing to diff against yet, so say how to create it. */\n// webpieces-disable no-function-outside-class -- executor step helper, matches reportMismatch in this file\nfunction reportMissingGraph(): void {\n console.error('❌ No saved graph found at architecture/dependencies.json');\n console.error('');\n console.error('To initialize:');\n console.error(' 1. Run: nx run architecture:generate');\n console.error(' 2. Run: nx run architecture:visualize');\n console.error(' 3. Manually inspect the generated graph to confirm it is the desired architecture');\n console.error(' 4. Commit architecture/dependencies.json');\n}\n\nexport default async function runExecutor(\n options: ValidateArchitectureUnchangedOptions,\n context: ExecutorContext\n): Promise<ExecutorResult> {\n const graphPath = options.graphPath;\n const workspaceRoot = context.root;\n\n // Epoch-gateable: this rule diffs against the blessed architecture/dependencies.json, so\n // \"grandfather the current drift until <epoch>\" is meaningful — hence honorEpoch = true.\n if (new RuleGate().isDisabled(workspaceRoot, 'validate-architecture-unchanged', true)) {\n return { success: true };\n }\n\n console.log('\\n🔍 Validating Architecture Unchanged\\n');\n\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n // Check if saved graph exists\n if (!graphFileExists(workspaceRoot, graphPath)) {\n reportMissingGraph();\n return { success: false };\n }\n\n // Steps 1-3: build + enrich + scan the current graph (same pipeline the\n // generator runs, so any drift is caught).\n const currentGraph = await buildCurrentGraph(workspaceRoot);\n\n // Step 4: Load saved graph\n console.log('📂 Loading saved graph...');\n const savedGraph = loadBlessedGraph(workspaceRoot, graphPath);\n\n if (!savedGraph) {\n console.error('❌ Could not load saved graph');\n return { success: false };\n }\n\n // Step 5: Compare graphs\n console.log('🔍 Comparing current graph to saved graph...');\n const comparison = compareGraphs(currentGraph.graph, savedGraph.projects);\n\n if (!comparison.identical) {\n reportMismatch(comparison.summary, workspaceRoot);\n return { success: false };\n }\n\n // Step 6: Compare the two side tables as well: which APIs are linked to a contract file, and\n // the external-system declarations. The endpoints inside architecture/apis/<Api>.json are\n // NOT compared — an endpoint change must never fail this rule (#949).\n const tableDrift = describeTableDrift(currentGraph, savedGraph);\n if (tableDrift !== null) {\n reportMismatch(tableDrift, workspaceRoot);\n return { success: false };\n }\n\n console.log('✅ Architecture unchanged - current graph matches saved graph');\n return { success: true };\n } catch (err: unknown) {\n const error = toError(err);\n // A RuleFailError (e.g. a dependencies.json still carrying the moved `apiContracts` key)\n // carries its cures in Option[]; render them rather than dropping them with `.message`.\n const rendered = error instanceof RuleFailError ? renderRuleFailForHuman(error) : error.message;\n console.error('❌ Architecture validation failed:', rendered);\n if (error instanceof MetadataValidationError) {\n const mdPath = writeTemplate(workspaceRoot, 'webpieces.responsibilities.md');\n console.error('');\n console.error('⚠️ *** Refer to ' + mdPath + ' for how to author responsibilities.md files *** ⚠️');\n }\n return { success: false };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/executors/validate-architecture-unchanged/executor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validate Architecture Unchanged Executor\n *\n * Validates that the current architecture graph matches the saved blessed graph.\n * This ensures no unapproved architecture changes have been made.\n *\n * Usage:\n * nx run architecture:validate-architecture-unchanged\n */\n\nimport type { ExecutorContext } from '@nx/devkit';\nimport { writeTemplate, RuleFailError, renderRuleFailForHuman } from '@webpieces/rules-config';\nimport { generateReducedGraph } from '../../lib/graph-generator';\nimport { sortGraphTopologically } from '../../lib/graph-sorter';\nimport { compareGraphs } from '../../lib/graph-comparator';\nimport { loadBlessedGraph, graphFileExists } from '../../lib/graph-loader';\nimport type { DependenciesFile } from '../../lib/graph-loader';\nimport { collectProjectInfo, enrichGraph, MetadataValidationError } from '../../lib/graph-metadata';\nimport { TagTruthCheck } from '../../lib/tag-truth';\nimport { scanAndAttachApiRelations, buildApiContracts } from '../../lib/api-usage/api-scanner';\nimport { buildExternalSystems } from '../../lib/api-usage/external-systems';\nimport type { ExternalSystemDecls } from '../../lib/api-usage/api-relations';\nimport { ApiContractFiles } from '../../lib/api-contract-files';\nimport type { ApiContractFileRefs } from '../../lib/api-contract-files';\nimport { loadRuntimeConfig } from '../../lib/runtime-config';\nimport { RuleGate } from '../../lib/rule-gate';\nimport type { EnhancedGraph } from '../../lib/graph-sorter';\nimport { toError } from '../../toError';\n\nexport interface ValidateArchitectureUnchangedOptions {\n graphPath?: string;\n}\n\nexport interface ExecutorResult {\n success: boolean;\n}\n\nconst TMP_MD_FILE = 'webpieces.dependencies.md';\n\n/**\n * Write the instructions documentation to .webpieces/instruct-ai/.\n * Sourced from @webpieces/rules-config.\n */\nfunction writeTmpInstructionsFile(workspaceRoot: string): string {\n const mdPath = writeTemplate(workspaceRoot, TMP_MD_FILE);\n\n return mdPath;\n}\n\n/**\n * Report a current-vs-saved graph mismatch and write the AI instructions file.\n */\nfunction reportMismatch(summary: string, workspaceRoot: string): void {\n const mdPath = writeTmpInstructionsFile(workspaceRoot);\n\n console.error('❌ Architecture has changed since last update!');\n console.error('\\nDifferences:');\n console.error(summary);\n console.error('');\n console.error('⚠️ *** Refer to ' + mdPath + ' for instructions on how to fix *** ⚠️');\n console.error('');\n console.error('To fix:');\n console.error(' 1. Review the changes above');\n console.error(' 2. If intentional, ASK USER to run: nx run architecture:generate since this is a critical change');\n console.error(' 3. Commit the updated architecture/dependencies.json');\n}\n\n/**\n * Which APIs dependencies.json links to a contract file, compared by LINK only — an added or removed\n * API. The endpoints inside `architecture/apis/<Api>.json` are deliberately NOT compared (#949): an\n * endpoint change must not fail this rule. Null when the links match.\n */\n// webpieces-disable no-function-outside-class -- executor step helper, matches reportMismatch in this file\nfunction describeContractLinkDrift(\n current: ApiContractFileRefs,\n saved: ApiContractFileRefs,\n): string | null {\n const names = [...new Set([...Object.keys(current), ...Object.keys(saved)])].sort();\n const changes: string[] = [];\n for (const name of names) {\n const a = current[name];\n const b = saved[name];\n if (a === undefined)\n changes.push(` - ${name}: linked in dependencies.json but no longer in source`);\n else if (b === undefined)\n changes.push(` + ${name}: in source but not linked from dependencies.json`);\n else if (a !== b) changes.push(` ~ ${name}: contract file link changed (${b} -> ${a})`);\n }\n if (changes.length === 0) return null;\n return `apiContractFiles drift (${changes.length} api(s)):\\n${changes.join('\\n')}`;\n}\n\n/**\n * Drift in EITHER side table of dependencies.json — the api contract-file links or the\n * external-system declarations — or null when both match. The first difference found is reported;\n * fixing it is the same single command either way, so listing both adds noise rather than information.\n */\n// webpieces-disable no-function-outside-class -- executor step helper, matches describeContractLinkDrift above\nexport function describeTableDrift(current: CurrentArchitecture, saved: DependenciesFile): string | null {\n const linkDrift = describeContractLinkDrift(current.apiContractFiles, saved.apiContractFiles);\n if (linkDrift !== null) return linkDrift;\n return describeExternalSystemDrift(current.externalSystems, saved.externalSystems);\n}\n\n/**\n * The same drift report for the declared external systems, or null when they match. Named per\n * system so the message points at the database that changed rather than dumping two JSON blobs.\n */\n// webpieces-disable no-function-outside-class -- executor step helper, matches describeContractLinkDrift above\nfunction describeExternalSystemDrift(\n current: ExternalSystemDecls,\n saved: ExternalSystemDecls,\n): string | null {\n const names = [...new Set([...Object.keys(current), ...Object.keys(saved)])].sort();\n const changes: string[] = [];\n for (const name of names) {\n const a = current[name];\n const b = saved[name];\n if (a === undefined)\n changes.push(` - ${name}: in dependencies.json but no longer declared in source`);\n else if (b === undefined)\n changes.push(` + ${name}: declared in source but missing from dependencies.json`);\n else if (JSON.stringify(a) !== JSON.stringify(b))\n changes.push(` ~ ${name}: kind/label/declarers changed`);\n }\n if (changes.length === 0) return null;\n return `externalSystems drift (${changes.length} system(s)):\\n${changes.join('\\n')}`;\n}\n\n/**\n * Build the current dependency graph exactly as the generator does: reduce the nx\n * graph, sort into levels, enrich with metadata, and attach the derived\n * apiRelations — so this validator compares like-for-like against the committed file.\n */\nexport class CurrentGraphBuilder {\n async build(workspaceRoot: string): Promise<CurrentArchitecture> {\n console.log('📊 Generating current dependency graph...');\n const reducedGraph = await generateReducedGraph();\n console.log('🔄 Computing topological layers...');\n const currentGraph = sortGraphTopologically(reducedGraph);\n console.log('🏷️ Enriching graph with framework + responsibilities metadata...');\n const projectInfos = await collectProjectInfo();\n enrichGraph(currentGraph, projectInfos, workspaceRoot);\n new TagTruthCheck().assertTrue(currentGraph, projectInfos, workspaceRoot);\n console.log('🔎 Scanning source for implements/uses API relations...');\n // The SAME externalApiPaths the generator uses: scanning without them would drop every vendor\n // relation from the regenerated graph and report drift against a perfectly fresh file.\n const externalApiPaths = loadRuntimeConfig(workspaceRoot).externalApiPaths;\n const scan = scanAndAttachApiRelations(workspaceRoot, currentGraph, projectInfos, externalApiPaths);\n return new CurrentArchitecture(\n currentGraph,\n new ApiContractFiles().refsFor(buildApiContracts(scan)),\n buildExternalSystems(scan.apiIndex, projectInfos),\n );\n }\n}\n\n/** The regenerated graph plus the two tables beside it — everything dependencies.json holds. */\nexport class CurrentArchitecture {\n constructor(\n public readonly graph: EnhancedGraph,\n public readonly apiContractFiles: ApiContractFileRefs,\n public readonly externalSystems: ExternalSystemDecls,\n ) {}\n}\n\n/** The bootstrap path: there is nothing to diff against yet, so say how to create it. */\n// webpieces-disable no-function-outside-class -- executor step helper, matches reportMismatch in this file\nfunction reportMissingGraph(): void {\n console.error('❌ No saved graph found at architecture/dependencies.json');\n console.error('');\n console.error('To initialize:');\n console.error(' 1. Run: nx run architecture:generate');\n console.error(' 2. Run: nx run architecture:visualize');\n console.error(' 3. Manually inspect the generated graph to confirm it is the desired architecture');\n console.error(' 4. Commit architecture/dependencies.json');\n}\n\nexport default async function runExecutor(\n options: ValidateArchitectureUnchangedOptions,\n context: ExecutorContext\n): Promise<ExecutorResult> {\n const graphPath = options.graphPath;\n const workspaceRoot = context.root;\n\n // Epoch-gateable: this rule diffs against the blessed architecture/dependencies.json, so\n // \"grandfather the current drift until <epoch>\" is meaningful — hence honorEpoch = true.\n if (new RuleGate().isDisabled(workspaceRoot, 'validate-architecture-unchanged', true)) {\n return { success: true };\n }\n\n console.log('\\n🔍 Validating Architecture Unchanged\\n');\n\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n // Check if saved graph exists\n if (!graphFileExists(workspaceRoot, graphPath)) {\n reportMissingGraph();\n return { success: false };\n }\n\n // Steps 1-3: build + enrich + scan the current graph (same pipeline the\n // generator runs, so any drift is caught).\n const currentGraph = await new CurrentGraphBuilder().build(workspaceRoot);\n\n // Step 4: Load saved graph\n console.log('📂 Loading saved graph...');\n const savedGraph = loadBlessedGraph(workspaceRoot, graphPath);\n\n if (!savedGraph) {\n console.error('❌ Could not load saved graph');\n return { success: false };\n }\n\n // Step 5: Compare graphs\n console.log('🔍 Comparing current graph to saved graph...');\n const comparison = compareGraphs(currentGraph.graph, savedGraph.projects);\n\n if (!comparison.identical) {\n reportMismatch(comparison.summary, workspaceRoot);\n return { success: false };\n }\n\n // Step 6: Compare the two side tables as well: which APIs are linked to a contract file, and\n // the external-system declarations. The endpoints inside architecture/apis/<Api>.json are\n // NOT compared — an endpoint change must never fail this rule (#949).\n const tableDrift = describeTableDrift(currentGraph, savedGraph);\n if (tableDrift !== null) {\n reportMismatch(tableDrift, workspaceRoot);\n return { success: false };\n }\n\n console.log('✅ Architecture unchanged - current graph matches saved graph');\n return { success: true };\n } catch (err: unknown) {\n const error = toError(err);\n // A RuleFailError (e.g. a dependencies.json still carrying the moved `apiContracts` key)\n // carries its cures in Option[]; render them rather than dropping them with `.message`.\n const rendered = error instanceof RuleFailError ? renderRuleFailForHuman(error) : error.message;\n console.error('❌ Architecture validation failed:', rendered);\n if (error instanceof MetadataValidationError) {\n const mdPath = writeTemplate(workspaceRoot, 'webpieces.responsibilities.md');\n console.error('');\n console.error('⚠️ *** Refer to ' + mdPath + ' for how to author responsibilities.md files *** ⚠️');\n }\n return { success: false };\n }\n}\n"]}
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import type { ExecutorContext } from '@nx/devkit';
|
|
2
2
|
import { ExecutorResult } from '../../executor-result';
|
|
3
|
-
/**
|
|
4
|
-
|
|
5
|
-
* from here; these only turn ONE run into a debug run of one rule:
|
|
6
|
-
* nx run architecture:validate-code --rule=<name> [--mode=RUN_EVERY_TIME] [--projects=a,b]
|
|
7
|
-
* All absent → the gate, at every committed mode.
|
|
8
|
-
*/
|
|
9
|
-
export interface ValidateCodeOptions {
|
|
3
|
+
/** Runtime policy options come only from validated owner files. These flags request one ephemeral debug run. */
|
|
4
|
+
export declare class ValidateCodeOptions {
|
|
10
5
|
rule?: string;
|
|
11
6
|
mode?: string;
|
|
12
7
|
projects?: string | string[];
|
|
@@ -1,8 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ValidateCodeOptions = void 0;
|
|
3
4
|
exports.default = runExecutor;
|
|
4
|
-
const
|
|
5
|
+
const rules_sdk_1 = require("@webpieces/rules-sdk");
|
|
6
|
+
const rules_config_1 = require("@webpieces/rules-config");
|
|
7
|
+
const rules_config_2 = require("@webpieces/rules-config");
|
|
8
|
+
const pack_build_runner_1 = require("../../pack-build-runner");
|
|
9
|
+
/** Runtime policy options come only from validated owner files. These flags request one ephemeral debug run. */
|
|
10
|
+
class ValidateCodeOptions {
|
|
11
|
+
rule;
|
|
12
|
+
mode;
|
|
13
|
+
projects;
|
|
14
|
+
}
|
|
15
|
+
exports.ValidateCodeOptions = ValidateCodeOptions;
|
|
16
|
+
// webpieces-disable no-function-outside-class -- Nx's required public executor entry point
|
|
5
17
|
async function runExecutor(options, context) {
|
|
6
|
-
|
|
18
|
+
const loaded = (0, rules_config_1.loadAndValidate)(context.root);
|
|
19
|
+
if (loaded.configPath === null)
|
|
20
|
+
throw new rules_config_2.RuleFailError('policy-configuration', 'Missing webpieces.config.json. Configure explicit rulePacks before running build policies.');
|
|
21
|
+
if (options.rule === undefined &&
|
|
22
|
+
options.mode === undefined &&
|
|
23
|
+
options.projects === undefined) {
|
|
24
|
+
return new pack_build_runner_1.PackBuildRunner().run(context.root, loaded);
|
|
25
|
+
}
|
|
26
|
+
if (options.rule === undefined)
|
|
27
|
+
throw new rules_config_2.RuleFailError('policy-configuration', '--mode and --projects require --rule=<name>: a debug run judges exactly one rule.');
|
|
28
|
+
const modules = new rules_config_1.RuleRuntimeModules();
|
|
29
|
+
const group = modules
|
|
30
|
+
.groups(loaded.ruleRegistry, 'build')
|
|
31
|
+
.find((entry) => entry.ruleIds.includes(options.rule));
|
|
32
|
+
if (!group)
|
|
33
|
+
throw new rules_config_2.RuleFailError('policy-configuration', `No declared build contribution for ${options.rule}. Use a rule from the generated policy catalog.`);
|
|
34
|
+
const exports = modules.load(group, loaded.ruleRegistry.manifestModules, new rules_config_1.NodeRuleRuntimeModuleLoader(context.root));
|
|
35
|
+
return modules.runBuildDebug(exports, new rules_sdk_1.BuildDebugRequest(context.root, new rules_sdk_1.PolicyDebugSelection(options.rule, options.mode, options.projects)));
|
|
7
36
|
}
|
|
8
37
|
//# sourceMappingURL=executor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/executors/validate-code/executor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/executors/validate-code/executor.ts"],"names":[],"mappings":";;;AAoBA,8BA2CC;AA9DD,oDAA+E;AAC/E,0DAKiC;AACjC,0DAAwD;AACxD,+DAA0D;AAG1D,gHAAgH;AAChH,MAAa,mBAAmB;IAC5B,IAAI,CAAU;IACd,IAAI,CAAU;IACd,QAAQ,CAAqB;CAChC;AAJD,kDAIC;AAED,2FAA2F;AAC5E,KAAK,UAAU,WAAW,CACrC,OAA4B,EAC5B,OAAwB;IAExB,MAAM,MAAM,GAAG,IAAA,8BAAe,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,IAAI,MAAM,CAAC,UAAU,KAAK,IAAI;QAC1B,MAAM,IAAI,4BAAa,CACnB,sBAAsB,EACtB,4FAA4F,CAC/F,CAAC;IACN,IACI,OAAO,CAAC,IAAI,KAAK,SAAS;QAC1B,OAAO,CAAC,IAAI,KAAK,SAAS;QAC1B,OAAO,CAAC,QAAQ,KAAK,SAAS,EAChC,CAAC;QACC,OAAO,IAAI,mCAAe,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS;QAC1B,MAAM,IAAI,4BAAa,CACnB,sBAAsB,EACtB,mFAAmF,CACtF,CAAC;IACN,MAAM,OAAO,GAAG,IAAI,iCAAkB,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,OAAO;SAChB,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC;SACpC,IAAI,CAAC,CAAC,KAA+B,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAK,CAAC,CAAC,CAAC;IACtF,IAAI,CAAC,KAAK;QACN,MAAM,IAAI,4BAAa,CACnB,sBAAsB,EACtB,sCAAsC,OAAO,CAAC,IAAI,iDAAiD,CACtG,CAAC;IACN,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CACxB,KAAK,EACL,MAAM,CAAC,YAAY,CAAC,eAAe,EACnC,IAAI,0CAA2B,CAAC,OAAO,CAAC,IAAI,CAAC,CAChD,CAAC;IACF,OAAO,OAAO,CAAC,aAAa,CACxB,OAAO,EACP,IAAI,6BAAiB,CACjB,OAAO,CAAC,IAAI,EACZ,IAAI,gCAAoB,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CACzE,CACJ,CAAC;AACN,CAAC","sourcesContent":["import type { ExecutorContext } from '@nx/devkit';\nimport { BuildDebugRequest, PolicyDebugSelection } from '@webpieces/rules-sdk';\nimport {\n loadAndValidate,\n NodeRuleRuntimeModuleLoader,\n RuleRuntimeModules,\n RuntimeContributionGroup,\n} from '@webpieces/rules-config';\nimport { RuleFailError } from '@webpieces/rules-config';\nimport { PackBuildRunner } from '../../pack-build-runner';\nimport { ExecutorResult } from '../../executor-result';\n\n/** Runtime policy options come only from validated owner files. These flags request one ephemeral debug run. */\nexport class ValidateCodeOptions {\n rule?: string;\n mode?: string;\n projects?: string | string[];\n}\n\n// webpieces-disable no-function-outside-class -- Nx's required public executor entry point\nexport default async function runExecutor(\n options: ValidateCodeOptions,\n context: ExecutorContext,\n): Promise<ExecutorResult> {\n const loaded = loadAndValidate(context.root);\n if (loaded.configPath === null)\n throw new RuleFailError(\n 'policy-configuration',\n 'Missing webpieces.config.json. Configure explicit rulePacks before running build policies.',\n );\n if (\n options.rule === undefined &&\n options.mode === undefined &&\n options.projects === undefined\n ) {\n return new PackBuildRunner().run(context.root, loaded);\n }\n if (options.rule === undefined)\n throw new RuleFailError(\n 'policy-configuration',\n '--mode and --projects require --rule=<name>: a debug run judges exactly one rule.',\n );\n const modules = new RuleRuntimeModules();\n const group = modules\n .groups(loaded.ruleRegistry, 'build')\n .find((entry: RuntimeContributionGroup) => entry.ruleIds.includes(options.rule!));\n if (!group)\n throw new RuleFailError(\n 'policy-configuration',\n `No declared build contribution for ${options.rule}. Use a rule from the generated policy catalog.`,\n );\n const exports = modules.load(\n group,\n loaded.ruleRegistry.manifestModules,\n new NodeRuleRuntimeModuleLoader(context.root),\n );\n return modules.runBuildDebug(\n exports,\n new BuildDebugRequest(\n context.root,\n new PolicyDebugSelection(options.rule, options.mode, options.projects),\n ),\n );\n}\n"]}
|