@webpieces/nx-webpieces-rules 0.4.911 → 0.4.913
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 +11 -0
- package/executors.json +5 -0
- package/package.json +7 -7
- package/src/executors/help/executor.js +2 -0
- package/src/executors/help/executor.js.map +1 -1
- package/src/executors/visualize-runtime/executor.d.ts +3 -1
- package/src/executors/visualize-runtime/executor.js +9 -3
- package/src/executors/visualize-runtime/executor.js.map +1 -1
- package/src/executors/visualize-runtime-goal/executor.d.ts +27 -0
- package/src/executors/visualize-runtime-goal/executor.js +98 -0
- package/src/executors/visualize-runtime-goal/executor.js.map +1 -0
- package/src/executors/visualize-runtime-goal/schema.json +13 -0
- package/src/index.d.ts +1 -1
- package/src/index.js +3 -1
- package/src/index.js.map +1 -1
- package/src/lib/graph-color-modes.d.ts +15 -1
- package/src/lib/graph-color-modes.js +19 -1
- package/src/lib/graph-color-modes.js.map +1 -1
- package/src/lib/graph-filter.client.d.ts +9 -2
- package/src/lib/graph-filter.client.js +15 -0
- package/src/lib/graph-filter.client.js.map +1 -1
- package/src/lib/graph-legend.js +1 -1
- package/src/lib/graph-legend.js.map +1 -1
- package/src/lib/graph-mode-state.client.d.ts +9 -2
- package/src/lib/graph-mode-state.client.js +17 -4
- package/src/lib/graph-mode-state.client.js.map +1 -1
- package/src/lib/graph-page-shell.d.ts +11 -4
- package/src/lib/graph-page-shell.js +11 -9
- package/src/lib/graph-page-shell.js.map +1 -1
- package/src/lib/graph-products.d.ts +22 -3
- package/src/lib/graph-products.js +63 -13
- package/src/lib/graph-products.js.map +1 -1
- package/src/lib/graph-render-model.d.ts +41 -0
- package/src/lib/graph-render-model.js +45 -1
- package/src/lib/graph-render-model.js.map +1 -1
- package/src/lib/graph-visualizer.client.d.ts +7 -1
- package/src/lib/graph-visualizer.client.js +37 -4
- package/src/lib/graph-visualizer.client.js.map +1 -1
- package/src/lib/graph-visualizer.js +1 -1
- package/src/lib/graph-visualizer.js.map +1 -1
- package/src/lib/runtime-goal-comparison.d.ts +55 -0
- package/src/lib/runtime-goal-comparison.js +209 -0
- package/src/lib/runtime-goal-comparison.js.map +1 -0
- package/src/lib/runtime-goal-details.d.ts +17 -0
- package/src/lib/runtime-goal-details.js +118 -0
- package/src/lib/runtime-goal-details.js.map +1 -0
- package/src/lib/runtime-goal-file.d.ts +72 -0
- package/src/lib/runtime-goal-file.js +201 -0
- package/src/lib/runtime-goal-file.js.map +1 -0
- package/src/lib/runtime-goal-styles.d.ts +10 -0
- package/src/lib/runtime-goal-styles.js +25 -0
- package/src/lib/runtime-goal-styles.js.map +1 -0
- package/src/lib/runtime-goal-validator.d.ts +39 -0
- package/src/lib/runtime-goal-validator.js +236 -0
- package/src/lib/runtime-goal-validator.js.map +1 -0
- package/src/lib/runtime-goal-view.d.ts +22 -0
- package/src/lib/runtime-goal-view.js +64 -0
- package/src/lib/runtime-goal-view.js.map +1 -0
- package/src/lib/runtime-graph-diff.d.ts +107 -0
- package/src/lib/runtime-graph-diff.js +346 -0
- package/src/lib/runtime-graph-diff.js.map +1 -0
- package/src/lib/runtime-html-page.d.ts +8 -0
- package/src/lib/runtime-html-page.js +39 -6
- package/src/lib/runtime-html-page.js.map +1 -1
- package/src/lib/runtime-layout.d.ts +2 -0
- package/src/lib/runtime-layout.js +4 -0
- package/src/lib/runtime-layout.js.map +1 -1
- package/src/lib/runtime-union-graph.d.ts +20 -0
- package/src/lib/runtime-union-graph.js +94 -0
- package/src/lib/runtime-union-graph.js.map +1 -0
- package/src/lib/runtime-viewer-adapter.js +7 -5
- package/src/lib/runtime-viewer-adapter.js.map +1 -1
- package/src/lib/runtime-visualizer.client.js +7 -3
- package/src/lib/runtime-visualizer.client.js.map +1 -1
- package/src/lib/runtime-visualizer.d.ts +8 -3
- package/src/lib/runtime-visualizer.js +18 -10
- package/src/lib/runtime-visualizer.js.map +1 -1
- package/src/lib/runtime-viz-options.d.ts +28 -1
- package/src/lib/runtime-viz-options.js +36 -2
- package/src/lib/runtime-viz-options.js.map +1 -1
- package/src/plugin.js +2 -2
- package/src/plugin.js.map +1 -1
- package/src/runtime-targets.d.ts +6 -0
- package/src/runtime-targets.js +17 -0
- package/src/runtime-targets.js.map +1 -1
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RuntimeGoalDetails = exports.RuntimeGoalDetailsData = void 0;
|
|
4
|
+
/** The before/after lines the page's Goal vs Current details panel shows, keyed by overlay id. */
|
|
5
|
+
class RuntimeGoalDetailsData {
|
|
6
|
+
nodes;
|
|
7
|
+
edges;
|
|
8
|
+
constructor(nodes, edges) {
|
|
9
|
+
this.nodes = nodes;
|
|
10
|
+
this.edges = edges;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.RuntimeGoalDetailsData = RuntimeGoalDetailsData;
|
|
14
|
+
/**
|
|
15
|
+
* Goal vs Current details (#1239): the page script that opens before/after lines for a clicked box
|
|
16
|
+
* (a "Goal vs Current" item in the SHARED node menu) or a clicked arrow, while that mode is on.
|
|
17
|
+
* Inlined with toString, like RuntimeDetails, so the page works from `file://` with no fetch.
|
|
18
|
+
*/
|
|
19
|
+
class RuntimeGoalDetails {
|
|
20
|
+
comparison;
|
|
21
|
+
constructor(comparison) {
|
|
22
|
+
this.comparison = comparison;
|
|
23
|
+
}
|
|
24
|
+
script() {
|
|
25
|
+
const data = new RuntimeGoalDetailsData(this.comparison?.nodeDetails ?? {}, this.comparison?.edgeDetails ?? {});
|
|
26
|
+
const encoded = JSON.stringify(data).replace(/</g, '\\u003c');
|
|
27
|
+
return `window.__WP_GOAL__ = new (${RuntimeGoalDetailsController.toString()})(${encoded});`;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.RuntimeGoalDetails = RuntimeGoalDetails;
|
|
31
|
+
/** Browser controller: one floating panel, rebound to each redrawn overlay SVG. */
|
|
32
|
+
class RuntimeGoalDetailsController {
|
|
33
|
+
data;
|
|
34
|
+
host = document.getElementById('graph');
|
|
35
|
+
panel = document.createElement('div');
|
|
36
|
+
anchor = null;
|
|
37
|
+
constructor(data) {
|
|
38
|
+
this.data = data;
|
|
39
|
+
this.panel.className = 'wp-goal-details';
|
|
40
|
+
this.panel.hidden = true;
|
|
41
|
+
this.panel.setAttribute('role', 'dialog');
|
|
42
|
+
this.panel.setAttribute('aria-label', 'Goal vs Current details');
|
|
43
|
+
document.body.append(this.panel);
|
|
44
|
+
if (this.host !== null)
|
|
45
|
+
new MutationObserver(() => this.attach()).observe(this.host, { childList: true });
|
|
46
|
+
document.addEventListener('keydown', (event) => {
|
|
47
|
+
if (event.key === 'Escape' && !this.panel.hidden) {
|
|
48
|
+
event.stopPropagation();
|
|
49
|
+
this.close();
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
document.addEventListener('click', (event) => {
|
|
53
|
+
if (event.target instanceof Node && !this.panel.contains(event.target) && !this.anchor?.contains(event.target))
|
|
54
|
+
this.close();
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/** The node menu's item, only while Goal vs Current is the active mode and the box has details. */
|
|
58
|
+
item(name, node) {
|
|
59
|
+
if (!this.active() || this.data.nodes[name] === undefined)
|
|
60
|
+
return null;
|
|
61
|
+
return new WpNodeMenuItem('Goal vs Current details', () => this.open(node, this.data.nodes[name]));
|
|
62
|
+
}
|
|
63
|
+
active() {
|
|
64
|
+
return document.body.dataset['wpMode'] === 'goal';
|
|
65
|
+
}
|
|
66
|
+
/** Every overlay arrow opens its relationship's before/after lines (capture: ahead of the Uses popup). */
|
|
67
|
+
attach() {
|
|
68
|
+
this.close();
|
|
69
|
+
if (!this.active() || this.host === null)
|
|
70
|
+
return;
|
|
71
|
+
for (const group of Array.from(this.host.querySelectorAll('g.edge'))) {
|
|
72
|
+
const lines = this.data.edges[group.id];
|
|
73
|
+
if (lines === undefined || group.dataset['wpGoal'] === 'true')
|
|
74
|
+
continue;
|
|
75
|
+
group.dataset['wpGoal'] = 'true';
|
|
76
|
+
group.classList.add('wp-goal-edge');
|
|
77
|
+
group.setAttribute('tabindex', '0');
|
|
78
|
+
group.setAttribute('role', 'button');
|
|
79
|
+
group.setAttribute('aria-label', `Goal vs Current: ${lines[0]}`);
|
|
80
|
+
group.addEventListener('click', (event) => {
|
|
81
|
+
event.stopPropagation();
|
|
82
|
+
this.open(group, lines);
|
|
83
|
+
}, true);
|
|
84
|
+
group.addEventListener('keydown', (event) => {
|
|
85
|
+
if (event.key !== 'Enter' && event.key !== ' ')
|
|
86
|
+
return;
|
|
87
|
+
event.preventDefault();
|
|
88
|
+
this.open(group, lines);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
open(anchor, lines) {
|
|
93
|
+
this.anchor = anchor;
|
|
94
|
+
const close = document.createElement('button');
|
|
95
|
+
close.type = 'button';
|
|
96
|
+
close.textContent = 'Close';
|
|
97
|
+
close.onclick = () => this.close();
|
|
98
|
+
const title = document.createElement('p');
|
|
99
|
+
title.textContent = 'Current → Goal';
|
|
100
|
+
const list = document.createElement('ul');
|
|
101
|
+
for (const line of lines.length === 0 ? ['Unchanged: present in both saved files with the same facts.'] : lines) {
|
|
102
|
+
const item = document.createElement('li');
|
|
103
|
+
item.textContent = line;
|
|
104
|
+
list.append(item);
|
|
105
|
+
}
|
|
106
|
+
this.panel.replaceChildren(close, title, list);
|
|
107
|
+
this.panel.hidden = false;
|
|
108
|
+
const rect = anchor.getBoundingClientRect();
|
|
109
|
+
this.panel.style.left = `${Math.max(12, Math.min(rect.left, innerWidth - this.panel.offsetWidth - 12))}px`;
|
|
110
|
+
this.panel.style.top = `${Math.max(12, Math.min(rect.bottom + 6, innerHeight - this.panel.offsetHeight - 12))}px`;
|
|
111
|
+
close.focus({ preventScroll: true });
|
|
112
|
+
}
|
|
113
|
+
close() {
|
|
114
|
+
this.panel.hidden = true;
|
|
115
|
+
this.anchor = null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=runtime-goal-details.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-goal-details.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-goal-details.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RuntimeComparisonView } from './graph-render-model';\n\n/** The before/after lines the page's Goal vs Current details panel shows, keyed by overlay id. */\nexport class RuntimeGoalDetailsData {\n constructor(\n public readonly nodes: Record<string, string[]>,\n public readonly edges: Record<string, string[]>,\n ) {}\n}\n\n/**\n * Goal vs Current details (#1239): the page script that opens before/after lines for a clicked box\n * (a \"Goal vs Current\" item in the SHARED node menu) or a clicked arrow, while that mode is on.\n * Inlined with toString, like RuntimeDetails, so the page works from `file://` with no fetch.\n */\nexport class RuntimeGoalDetails {\n constructor(private readonly comparison: RuntimeComparisonView | null) {}\n\n script(): string {\n const data = new RuntimeGoalDetailsData(this.comparison?.nodeDetails ?? {}, this.comparison?.edgeDetails ?? {});\n const encoded = JSON.stringify(data).replace(/</g, '\\\\u003c');\n return `window.__WP_GOAL__ = new (${RuntimeGoalDetailsController.toString()})(${encoded});`;\n }\n}\n\n/** Browser controller: one floating panel, rebound to each redrawn overlay SVG. */\nclass RuntimeGoalDetailsController {\n private readonly host = document.getElementById('graph');\n private readonly panel = document.createElement('div');\n private anchor: Element | null = null;\n\n constructor(private readonly data: RuntimeGoalDetailsData) {\n this.panel.className = 'wp-goal-details';\n this.panel.hidden = true;\n this.panel.setAttribute('role', 'dialog');\n this.panel.setAttribute('aria-label', 'Goal vs Current details');\n document.body.append(this.panel);\n if (this.host !== null) new MutationObserver(() => this.attach()).observe(this.host, { childList: true });\n document.addEventListener('keydown', (event: KeyboardEvent) => {\n if (event.key === 'Escape' && !this.panel.hidden) {\n event.stopPropagation();\n this.close();\n }\n });\n document.addEventListener('click', (event: MouseEvent) => {\n if (event.target instanceof Node && !this.panel.contains(event.target) && !this.anchor?.contains(event.target)) this.close();\n });\n }\n\n /** The node menu's item, only while Goal vs Current is the active mode and the box has details. */\n item(name: string, node: SVGGElement): WpNodeMenuItem | null {\n if (!this.active() || this.data.nodes[name] === undefined) return null;\n return new WpNodeMenuItem('Goal vs Current details', () => this.open(node, this.data.nodes[name]));\n }\n\n private active(): boolean {\n return document.body.dataset['wpMode'] === 'goal';\n }\n\n /** Every overlay arrow opens its relationship's before/after lines (capture: ahead of the Uses popup). */\n private attach(): void {\n this.close();\n if (!this.active() || this.host === null) return;\n for (const group of Array.from(this.host.querySelectorAll<SVGGElement>('g.edge'))) {\n const lines = this.data.edges[group.id];\n if (lines === undefined || group.dataset['wpGoal'] === 'true') continue;\n group.dataset['wpGoal'] = 'true';\n group.classList.add('wp-goal-edge');\n group.setAttribute('tabindex', '0');\n group.setAttribute('role', 'button');\n group.setAttribute('aria-label', `Goal vs Current: ${lines[0]}`);\n group.addEventListener('click', (event: MouseEvent) => {\n event.stopPropagation();\n this.open(group, lines);\n }, true);\n group.addEventListener('keydown', (event: KeyboardEvent) => {\n if (event.key !== 'Enter' && event.key !== ' ') return;\n event.preventDefault();\n this.open(group, lines);\n });\n }\n }\n\n private open(anchor: Element, lines: string[]): void {\n this.anchor = anchor;\n const close = document.createElement('button');\n close.type = 'button';\n close.textContent = 'Close';\n close.onclick = () => this.close();\n const title = document.createElement('p');\n title.textContent = 'Current → Goal';\n const list = document.createElement('ul');\n for (const line of lines.length === 0 ? ['Unchanged: present in both saved files with the same facts.'] : lines) {\n const item = document.createElement('li');\n item.textContent = line;\n list.append(item);\n }\n this.panel.replaceChildren(close, title, list);\n this.panel.hidden = false;\n const rect = anchor.getBoundingClientRect();\n this.panel.style.left = `${Math.max(12, Math.min(rect.left, innerWidth - this.panel.offsetWidth - 12))}px`;\n this.panel.style.top = `${Math.max(12, Math.min(rect.bottom + 6, innerHeight - this.panel.offsetHeight - 12))}px`;\n close.focus({ preventScroll: true });\n }\n\n private close(): void {\n this.panel.hidden = true;\n this.anchor = null;\n }\n}\n"]}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The runtime architecture GOAL (#1239): `architecture/runtime-dependencies-goal.json`.
|
|
3
|
+
*
|
|
4
|
+
* A proposal, not a fact. `architecture/runtime-dependencies.json` is GENERATED from source and its
|
|
5
|
+
* unchanged-validator rightly treats any hand edit as drift, so a proposal needs its own durable,
|
|
6
|
+
* reviewable file in the same RuntimeGraph shape. Nothing in the generator reads, writes or deletes
|
|
7
|
+
* this file: only a person (or an AI) edits it, and only the explicit `--prepare` step below rewrites
|
|
8
|
+
* its derived fields.
|
|
9
|
+
*
|
|
10
|
+
* Errors here never tell anyone to regenerate from source — a goal has no source. They name the goal
|
|
11
|
+
* path, the broken element, and the edit or the explicit preparation command that repairs it.
|
|
12
|
+
*/
|
|
13
|
+
import { Option } from '@webpieces/rules-config';
|
|
14
|
+
import type { RuntimeGraph } from './runtime-graph-model';
|
|
15
|
+
export declare const DEFAULT_RUNTIME_GOAL_PATH = "architecture/runtime-dependencies-goal.json";
|
|
16
|
+
export declare const RUNTIME_GOAL_RULE_NAME = "runtime-architecture-goal";
|
|
17
|
+
export declare const RUNTIME_GOAL_PREPARE_COMMAND = "pnpm nx run architecture:visualize-runtime-goal --prepare";
|
|
18
|
+
export declare const RUNTIME_GOAL_INIT_COMMAND = "cp architecture/runtime-dependencies.json architecture/runtime-dependencies-goal.json";
|
|
19
|
+
/** The derived fields `--prepare` rewrote, as `field: before → after` lines; empty when none moved. */
|
|
20
|
+
export declare class RuntimeGoalPreparation {
|
|
21
|
+
readonly graph: RuntimeGraph;
|
|
22
|
+
readonly changes: string[];
|
|
23
|
+
/** Whether the goal file was rewritten (also true when only explanatory levelBecause text moved). */
|
|
24
|
+
readonly written: boolean;
|
|
25
|
+
constructor(graph: RuntimeGraph, changes: string[],
|
|
26
|
+
/** Whether the goal file was rewritten (also true when only explanatory levelBecause text moved). */
|
|
27
|
+
written: boolean);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* What viewing found about the goal's derived facts: a CYCLE (only an edit of runtimeEdges fixes it,
|
|
31
|
+
* `--prepare` refuses it too) or field DIFFERENCES that `--prepare` would rewrite.
|
|
32
|
+
*/
|
|
33
|
+
export declare class RuntimeGoalDrift {
|
|
34
|
+
readonly cycle: string | null;
|
|
35
|
+
readonly differences: string[];
|
|
36
|
+
constructor(cycle: string | null, differences: string[]);
|
|
37
|
+
}
|
|
38
|
+
/** Loads, checks and (only on request) prepares the hand-authored runtime goal. */
|
|
39
|
+
export declare class RuntimeGoalFile {
|
|
40
|
+
readonly goalPath: string;
|
|
41
|
+
private readonly validator;
|
|
42
|
+
constructor(goalPath?: string);
|
|
43
|
+
exists(workspaceRoot: string): boolean;
|
|
44
|
+
/** The goal as saved, after its shape, references and derived facts check out. Never writes anything. */
|
|
45
|
+
load(workspaceRoot: string): RuntimeGraph;
|
|
46
|
+
/**
|
|
47
|
+
* Where the saved derived facts disagree with what the existing runtime level machinery
|
|
48
|
+
* (RuntimeNodeLevels — the generator's own) computes from the goal's relationships. Reported, not
|
|
49
|
+
* fixed: viewing is read-only, and `--prepare` is the explicit step that rewrites them.
|
|
50
|
+
*/
|
|
51
|
+
drift(graph: RuntimeGraph): RuntimeGoalDrift;
|
|
52
|
+
/**
|
|
53
|
+
* Recompute levels, self-queue flags, contract queues and maxLevel, and WRITE the goal. Gated on
|
|
54
|
+
* STRUCTURAL problems only: missing or stale derived facts are exactly what this step computes.
|
|
55
|
+
*/
|
|
56
|
+
prepare(workspaceRoot: string): RuntimeGoalPreparation;
|
|
57
|
+
/** The edit that clears a cycle verdict — `--prepare` cannot. */
|
|
58
|
+
cycleOption(): Option;
|
|
59
|
+
private structurallyValid;
|
|
60
|
+
/** A deep copy with the generator's level machinery applied, or the cycle it refused. */
|
|
61
|
+
private recompute;
|
|
62
|
+
private differences;
|
|
63
|
+
private contractDifferences;
|
|
64
|
+
private missing;
|
|
65
|
+
private editOption;
|
|
66
|
+
private failure;
|
|
67
|
+
}
|
|
68
|
+
/** What a goal page says it is: a hand-authored proposal, not a generated snapshot (#1239). */
|
|
69
|
+
export declare class RuntimeGoalProvenance {
|
|
70
|
+
message(): string;
|
|
71
|
+
html(): string;
|
|
72
|
+
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The runtime architecture GOAL (#1239): `architecture/runtime-dependencies-goal.json`.
|
|
4
|
+
*
|
|
5
|
+
* A proposal, not a fact. `architecture/runtime-dependencies.json` is GENERATED from source and its
|
|
6
|
+
* unchanged-validator rightly treats any hand edit as drift, so a proposal needs its own durable,
|
|
7
|
+
* reviewable file in the same RuntimeGraph shape. Nothing in the generator reads, writes or deletes
|
|
8
|
+
* this file: only a person (or an AI) edits it, and only the explicit `--prepare` step below rewrites
|
|
9
|
+
* its derived fields.
|
|
10
|
+
*
|
|
11
|
+
* Errors here never tell anyone to regenerate from source — a goal has no source. They name the goal
|
|
12
|
+
* path, the broken element, and the edit or the explicit preparation command that repairs it.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.RuntimeGoalProvenance = exports.RuntimeGoalFile = exports.RuntimeGoalDrift = exports.RuntimeGoalPreparation = exports.RUNTIME_GOAL_INIT_COMMAND = exports.RUNTIME_GOAL_PREPARE_COMMAND = exports.RUNTIME_GOAL_RULE_NAME = exports.DEFAULT_RUNTIME_GOAL_PATH = void 0;
|
|
16
|
+
const tslib_1 = require("tslib");
|
|
17
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
18
|
+
const path = tslib_1.__importStar(require("path"));
|
|
19
|
+
const rules_config_1 = require("@webpieces/rules-config");
|
|
20
|
+
const runtime_graph_io_1 = require("./runtime-graph-io");
|
|
21
|
+
const runtime_node_levels_1 = require("./runtime-node-levels");
|
|
22
|
+
const runtime_goal_validator_1 = require("./runtime-goal-validator");
|
|
23
|
+
const toError_1 = require("../toError");
|
|
24
|
+
exports.DEFAULT_RUNTIME_GOAL_PATH = 'architecture/runtime-dependencies-goal.json';
|
|
25
|
+
exports.RUNTIME_GOAL_RULE_NAME = 'runtime-architecture-goal';
|
|
26
|
+
exports.RUNTIME_GOAL_PREPARE_COMMAND = 'pnpm nx run architecture:visualize-runtime-goal --prepare';
|
|
27
|
+
exports.RUNTIME_GOAL_INIT_COMMAND = `cp ${runtime_graph_io_1.DEFAULT_RUNTIME_GRAPH_PATH} ${exports.DEFAULT_RUNTIME_GOAL_PATH}`;
|
|
28
|
+
/** The derived fields `--prepare` rewrote, as `field: before → after` lines; empty when none moved. */
|
|
29
|
+
class RuntimeGoalPreparation {
|
|
30
|
+
graph;
|
|
31
|
+
changes;
|
|
32
|
+
written;
|
|
33
|
+
constructor(graph, changes,
|
|
34
|
+
/** Whether the goal file was rewritten (also true when only explanatory levelBecause text moved). */
|
|
35
|
+
written) {
|
|
36
|
+
this.graph = graph;
|
|
37
|
+
this.changes = changes;
|
|
38
|
+
this.written = written;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.RuntimeGoalPreparation = RuntimeGoalPreparation;
|
|
42
|
+
/**
|
|
43
|
+
* What viewing found about the goal's derived facts: a CYCLE (only an edit of runtimeEdges fixes it,
|
|
44
|
+
* `--prepare` refuses it too) or field DIFFERENCES that `--prepare` would rewrite.
|
|
45
|
+
*/
|
|
46
|
+
class RuntimeGoalDrift {
|
|
47
|
+
cycle;
|
|
48
|
+
differences;
|
|
49
|
+
constructor(cycle, differences) {
|
|
50
|
+
this.cycle = cycle;
|
|
51
|
+
this.differences = differences;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.RuntimeGoalDrift = RuntimeGoalDrift;
|
|
55
|
+
/** Loads, checks and (only on request) prepares the hand-authored runtime goal. */
|
|
56
|
+
class RuntimeGoalFile {
|
|
57
|
+
goalPath;
|
|
58
|
+
validator;
|
|
59
|
+
constructor(goalPath = exports.DEFAULT_RUNTIME_GOAL_PATH) {
|
|
60
|
+
this.goalPath = goalPath;
|
|
61
|
+
this.validator = new runtime_goal_validator_1.RuntimeGoalValidator(goalPath);
|
|
62
|
+
}
|
|
63
|
+
exists(workspaceRoot) {
|
|
64
|
+
return fs.existsSync(path.join(workspaceRoot, this.goalPath));
|
|
65
|
+
}
|
|
66
|
+
/** The goal as saved, after its shape, references and derived facts check out. Never writes anything. */
|
|
67
|
+
load(workspaceRoot) {
|
|
68
|
+
const parsed = this.structurallyValid(workspaceRoot);
|
|
69
|
+
const derived = this.validator.derived(parsed);
|
|
70
|
+
if (derived.length > 0)
|
|
71
|
+
throw this.failure(`${this.goalPath} lacks derived facts the viewer needs:\n ${derived.join('\n ')}`, [
|
|
72
|
+
new rules_config_1.Option(`Compute them from the goal's relationships: ${exports.RUNTIME_GOAL_PREPARE_COMMAND}`, true),
|
|
73
|
+
this.editOption(false),
|
|
74
|
+
]);
|
|
75
|
+
return parsed;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Where the saved derived facts disagree with what the existing runtime level machinery
|
|
79
|
+
* (RuntimeNodeLevels — the generator's own) computes from the goal's relationships. Reported, not
|
|
80
|
+
* fixed: viewing is read-only, and `--prepare` is the explicit step that rewrites them.
|
|
81
|
+
*/
|
|
82
|
+
drift(graph) {
|
|
83
|
+
const recomputed = this.recompute(graph);
|
|
84
|
+
if (typeof recomputed === 'string')
|
|
85
|
+
return new RuntimeGoalDrift(recomputed, []);
|
|
86
|
+
return new RuntimeGoalDrift(null, this.differences(graph, recomputed));
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Recompute levels, self-queue flags, contract queues and maxLevel, and WRITE the goal. Gated on
|
|
90
|
+
* STRUCTURAL problems only: missing or stale derived facts are exactly what this step computes.
|
|
91
|
+
*/
|
|
92
|
+
prepare(workspaceRoot) {
|
|
93
|
+
const saved = this.structurallyValid(workspaceRoot);
|
|
94
|
+
const recomputed = this.recompute(saved);
|
|
95
|
+
if (typeof recomputed === 'string')
|
|
96
|
+
throw this.failure(recomputed, [this.cycleOption()]);
|
|
97
|
+
const changes = this.differences(saved, recomputed);
|
|
98
|
+
const written = JSON.stringify(saved) !== JSON.stringify(recomputed);
|
|
99
|
+
if (written)
|
|
100
|
+
(0, runtime_graph_io_1.saveRuntimeGraph)(recomputed, workspaceRoot, this.goalPath);
|
|
101
|
+
return new RuntimeGoalPreparation(recomputed, changes, written);
|
|
102
|
+
}
|
|
103
|
+
/** The edit that clears a cycle verdict — `--prepare` cannot. */
|
|
104
|
+
cycleOption() {
|
|
105
|
+
return new rules_config_1.Option(`Break the cycle by editing "runtimeEdges" (or the queues it flows through) in ${this.goalPath}.`, true);
|
|
106
|
+
}
|
|
107
|
+
structurallyValid(workspaceRoot) {
|
|
108
|
+
if (!this.exists(workspaceRoot))
|
|
109
|
+
throw this.missing();
|
|
110
|
+
let parsed;
|
|
111
|
+
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- hand-authored JSON decoding boundary adds the goal path and repair while preserving the cause
|
|
112
|
+
try {
|
|
113
|
+
parsed = JSON.parse(fs.readFileSync(path.join(workspaceRoot, this.goalPath), 'utf-8'));
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
const error = (0, toError_1.toError)(err);
|
|
117
|
+
throw this.failure(`${this.goalPath} is not valid JSON: ${error.message}`, [this.editOption(true)], error);
|
|
118
|
+
}
|
|
119
|
+
const problems = this.validator.structural(parsed);
|
|
120
|
+
if (problems.length > 0)
|
|
121
|
+
throw this.failure(`${this.goalPath} is not a usable runtime goal:\n ${problems.join('\n ')}`, [this.editOption(true)]);
|
|
122
|
+
return parsed;
|
|
123
|
+
}
|
|
124
|
+
/** A deep copy with the generator's level machinery applied, or the cycle it refused. */
|
|
125
|
+
recompute(graph) {
|
|
126
|
+
const copy = JSON.parse(JSON.stringify(graph));
|
|
127
|
+
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- the shared level machinery throws its cycle verdict; the goal reports it against its own path
|
|
128
|
+
try {
|
|
129
|
+
new runtime_node_levels_1.RuntimeNodeLevels().apply(copy);
|
|
130
|
+
return copy;
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
const error = (0, toError_1.toError)(err);
|
|
134
|
+
if (!(error instanceof rules_config_1.RuleFailError))
|
|
135
|
+
throw error;
|
|
136
|
+
return `${this.goalPath} describes a runtime graph the level machinery cannot order: ${error.message}`;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
differences(saved, recomputed) {
|
|
140
|
+
const lines = [];
|
|
141
|
+
const level = (where, before, after) => {
|
|
142
|
+
if (before !== after)
|
|
143
|
+
lines.push(`${where} level: L${before ?? '?'} → L${after}`);
|
|
144
|
+
};
|
|
145
|
+
for (const [name, service] of Object.entries(recomputed.services))
|
|
146
|
+
level(`services["${name}"]`, saved.services[name].level, service.level);
|
|
147
|
+
for (const [key, queue] of Object.entries(recomputed.queues)) {
|
|
148
|
+
level(`queues["${key}"]`, saved.queues[key].level, queue.level);
|
|
149
|
+
if (saved.queues[key].selfQueue !== queue.selfQueue)
|
|
150
|
+
lines.push(`queues["${key}"] selfQueue: ${saved.queues[key].selfQueue} → ${queue.selfQueue}`);
|
|
151
|
+
}
|
|
152
|
+
lines.push(...this.contractDifferences(saved.contractQueues ?? {}, recomputed.contractQueues));
|
|
153
|
+
recomputed.triggers.forEach((trigger, index) => level(`triggers[${index}]`, saved.triggers[index].level, trigger.level));
|
|
154
|
+
if (saved.maxLevel !== recomputed.maxLevel)
|
|
155
|
+
lines.push(`maxLevel: ${saved.maxLevel} → ${recomputed.maxLevel}`);
|
|
156
|
+
return lines;
|
|
157
|
+
}
|
|
158
|
+
contractDifferences(saved, recomputed) {
|
|
159
|
+
const lines = [];
|
|
160
|
+
const fields = (flow) => flow === undefined
|
|
161
|
+
? '(absent)'
|
|
162
|
+
: `L${flow.level} self=${flow.selfQueue} producers=[${flow.producedBy.join(', ')}] consumers=[${flow.consumedBy.join(', ')}]`;
|
|
163
|
+
for (const api of [...new Set([...Object.keys(saved), ...Object.keys(recomputed)])].sort()) {
|
|
164
|
+
const before = fields(saved[api]);
|
|
165
|
+
const after = fields(recomputed[api]);
|
|
166
|
+
if (before !== after)
|
|
167
|
+
lines.push(`contractQueues["${api}"]: ${before} → ${after}`);
|
|
168
|
+
}
|
|
169
|
+
return lines;
|
|
170
|
+
}
|
|
171
|
+
missing() {
|
|
172
|
+
return this.failure(`No runtime goal at ${this.goalPath}. Viewing never creates or replaces the goal, and never renders the current graph in its place.`, [
|
|
173
|
+
new rules_config_1.Option(`Start a proposal from the saved current runtime graph: ${exports.RUNTIME_GOAL_INIT_COMMAND} — then edit the copy and commit it.`, true),
|
|
174
|
+
new rules_config_1.Option(`Write ${this.goalPath} by hand in the RuntimeGraph shape of ${runtime_graph_io_1.DEFAULT_RUNTIME_GRAPH_PATH}.`),
|
|
175
|
+
]);
|
|
176
|
+
}
|
|
177
|
+
editOption(preferred) {
|
|
178
|
+
return new rules_config_1.Option(`Edit ${this.goalPath} by hand — it is a hand-authored proposal, so the fix is in the file, not in source.`, preferred);
|
|
179
|
+
}
|
|
180
|
+
failure(message, options, cause) {
|
|
181
|
+
return new rules_config_1.RuleFailError(exports.RUNTIME_GOAL_RULE_NAME, message, undefined, undefined, options, undefined, cause);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
exports.RuntimeGoalFile = RuntimeGoalFile;
|
|
185
|
+
/** What a goal page says it is: a hand-authored proposal, not a generated snapshot (#1239). */
|
|
186
|
+
class RuntimeGoalProvenance {
|
|
187
|
+
message() {
|
|
188
|
+
return (`Goal / Proposed runtime architecture from ${exports.DEFAULT_RUNTIME_GOAL_PATH}. Hand-authored; not generated from source, ` +
|
|
189
|
+
'and never written by architecture:generate. Viewing changes no file. ' +
|
|
190
|
+
`After editing relationships, recompute derived levels explicitly: ${exports.RUNTIME_GOAL_PREPARE_COMMAND}`);
|
|
191
|
+
}
|
|
192
|
+
html() {
|
|
193
|
+
return (`<p class="hint"><strong>Goal / Proposed runtime architecture.</strong> Hand-authored proposal read from ` +
|
|
194
|
+
`<code>${exports.DEFAULT_RUNTIME_GOAL_PATH}</code>; not generated from source and never written by ` +
|
|
195
|
+
`<code>architecture:generate</code>. Viewing changes no file. After editing relationships, recompute derived ` +
|
|
196
|
+
`levels explicitly: <code>${exports.RUNTIME_GOAL_PREPARE_COMMAND}</code>. Compare with the saved current graph ` +
|
|
197
|
+
`(<code>${runtime_graph_io_1.DEFAULT_RUNTIME_GRAPH_PATH}</code>) in Color by → Goal vs Current.</p>`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
exports.RuntimeGoalProvenance = RuntimeGoalProvenance;
|
|
201
|
+
//# sourceMappingURL=runtime-goal-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-goal-file.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-goal-file.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The runtime architecture GOAL (#1239): `architecture/runtime-dependencies-goal.json`.\n *\n * A proposal, not a fact. `architecture/runtime-dependencies.json` is GENERATED from source and its\n * unchanged-validator rightly treats any hand edit as drift, so a proposal needs its own durable,\n * reviewable file in the same RuntimeGraph shape. Nothing in the generator reads, writes or deletes\n * this file: only a person (or an AI) edits it, and only the explicit `--prepare` step below rewrites\n * its derived fields.\n *\n * Errors here never tell anyone to regenerate from source — a goal has no source. They name the goal\n * path, the broken element, and the edit or the explicit preparation command that repairs it.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { RuleFailError, Option } from '@webpieces/rules-config';\nimport type { RuntimeGraph, RuntimeQueueFlow, RuntimeTrigger } from './runtime-graph-model';\nimport { DEFAULT_RUNTIME_GRAPH_PATH, saveRuntimeGraph } from './runtime-graph-io';\nimport { RuntimeNodeLevels } from './runtime-node-levels';\nimport { RuntimeGoalValidator } from './runtime-goal-validator';\nimport { toError } from '../toError';\n\nexport const DEFAULT_RUNTIME_GOAL_PATH = 'architecture/runtime-dependencies-goal.json';\nexport const RUNTIME_GOAL_RULE_NAME = 'runtime-architecture-goal';\nexport const RUNTIME_GOAL_PREPARE_COMMAND = 'pnpm nx run architecture:visualize-runtime-goal --prepare';\nexport const RUNTIME_GOAL_INIT_COMMAND = `cp ${DEFAULT_RUNTIME_GRAPH_PATH} ${DEFAULT_RUNTIME_GOAL_PATH}`;\n\n/** The derived fields `--prepare` rewrote, as `field: before → after` lines; empty when none moved. */\nexport class RuntimeGoalPreparation {\n constructor(\n public readonly graph: RuntimeGraph,\n public readonly changes: string[],\n /** Whether the goal file was rewritten (also true when only explanatory levelBecause text moved). */\n public readonly written: boolean,\n ) {}\n}\n\n/**\n * What viewing found about the goal's derived facts: a CYCLE (only an edit of runtimeEdges fixes it,\n * `--prepare` refuses it too) or field DIFFERENCES that `--prepare` would rewrite.\n */\nexport class RuntimeGoalDrift {\n constructor(\n public readonly cycle: string | null,\n public readonly differences: string[],\n ) {}\n}\n\n/** Loads, checks and (only on request) prepares the hand-authored runtime goal. */\nexport class RuntimeGoalFile {\n private readonly validator: RuntimeGoalValidator;\n\n constructor(public readonly goalPath: string = DEFAULT_RUNTIME_GOAL_PATH) {\n this.validator = new RuntimeGoalValidator(goalPath);\n }\n\n exists(workspaceRoot: string): boolean {\n return fs.existsSync(path.join(workspaceRoot, this.goalPath));\n }\n\n /** The goal as saved, after its shape, references and derived facts check out. Never writes anything. */\n load(workspaceRoot: string): RuntimeGraph {\n const parsed = this.structurallyValid(workspaceRoot);\n const derived = this.validator.derived(parsed);\n if (derived.length > 0)\n throw this.failure(`${this.goalPath} lacks derived facts the viewer needs:\\n ${derived.join('\\n ')}`, [\n new Option(`Compute them from the goal's relationships: ${RUNTIME_GOAL_PREPARE_COMMAND}`, true),\n this.editOption(false),\n ]);\n return parsed;\n }\n\n /**\n * Where the saved derived facts disagree with what the existing runtime level machinery\n * (RuntimeNodeLevels — the generator's own) computes from the goal's relationships. Reported, not\n * fixed: viewing is read-only, and `--prepare` is the explicit step that rewrites them.\n */\n drift(graph: RuntimeGraph): RuntimeGoalDrift {\n const recomputed = this.recompute(graph);\n if (typeof recomputed === 'string') return new RuntimeGoalDrift(recomputed, []);\n return new RuntimeGoalDrift(null, this.differences(graph, recomputed));\n }\n\n /**\n * Recompute levels, self-queue flags, contract queues and maxLevel, and WRITE the goal. Gated on\n * STRUCTURAL problems only: missing or stale derived facts are exactly what this step computes.\n */\n prepare(workspaceRoot: string): RuntimeGoalPreparation {\n const saved = this.structurallyValid(workspaceRoot);\n const recomputed = this.recompute(saved);\n if (typeof recomputed === 'string') throw this.failure(recomputed, [this.cycleOption()]);\n const changes = this.differences(saved, recomputed);\n const written = JSON.stringify(saved) !== JSON.stringify(recomputed);\n if (written) saveRuntimeGraph(recomputed, workspaceRoot, this.goalPath);\n return new RuntimeGoalPreparation(recomputed, changes, written);\n }\n\n /** The edit that clears a cycle verdict — `--prepare` cannot. */\n cycleOption(): Option {\n return new Option(`Break the cycle by editing \"runtimeEdges\" (or the queues it flows through) in ${this.goalPath}.`, true);\n }\n\n private structurallyValid(workspaceRoot: string): RuntimeGraph {\n if (!this.exists(workspaceRoot)) throw this.missing();\n let parsed: RuntimeGraph;\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- hand-authored JSON decoding boundary adds the goal path and repair while preserving the cause\n try {\n parsed = JSON.parse(fs.readFileSync(path.join(workspaceRoot, this.goalPath), 'utf-8')) as RuntimeGraph;\n } catch (err: unknown) {\n const error = toError(err);\n throw this.failure(`${this.goalPath} is not valid JSON: ${error.message}`, [this.editOption(true)], error);\n }\n const problems = this.validator.structural(parsed);\n if (problems.length > 0)\n throw this.failure(`${this.goalPath} is not a usable runtime goal:\\n ${problems.join('\\n ')}`, [this.editOption(true)]);\n return parsed;\n }\n\n /** A deep copy with the generator's level machinery applied, or the cycle it refused. */\n private recompute(graph: RuntimeGraph): RuntimeGraph | string {\n const copy = JSON.parse(JSON.stringify(graph)) as RuntimeGraph;\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- the shared level machinery throws its cycle verdict; the goal reports it against its own path\n try {\n new RuntimeNodeLevels().apply(copy);\n return copy;\n } catch (err: unknown) {\n const error = toError(err);\n if (!(error instanceof RuleFailError)) throw error;\n return `${this.goalPath} describes a runtime graph the level machinery cannot order: ${error.message}`;\n }\n }\n\n private differences(saved: RuntimeGraph, recomputed: RuntimeGraph): string[] {\n const lines: string[] = [];\n const level = (where: string, before: number | undefined, after: number): void => {\n if (before !== after) lines.push(`${where} level: L${before ?? '?'} → L${after}`);\n };\n for (const [name, service] of Object.entries(recomputed.services)) level(`services[\"${name}\"]`, saved.services[name].level, service.level);\n for (const [key, queue] of Object.entries(recomputed.queues)) {\n level(`queues[\"${key}\"]`, saved.queues[key].level, queue.level);\n if (saved.queues[key].selfQueue !== queue.selfQueue)\n lines.push(`queues[\"${key}\"] selfQueue: ${saved.queues[key].selfQueue} → ${queue.selfQueue}`);\n }\n lines.push(...this.contractDifferences(saved.contractQueues ?? {}, recomputed.contractQueues));\n recomputed.triggers.forEach((trigger: RuntimeTrigger, index: number) =>\n level(`triggers[${index}]`, saved.triggers[index].level, trigger.level),\n );\n if (saved.maxLevel !== recomputed.maxLevel) lines.push(`maxLevel: ${saved.maxLevel} → ${recomputed.maxLevel}`);\n return lines;\n }\n\n private contractDifferences(saved: Record<string, RuntimeQueueFlow>, recomputed: Record<string, RuntimeQueueFlow>): string[] {\n const lines: string[] = [];\n const fields = (flow: RuntimeQueueFlow | undefined): string =>\n flow === undefined\n ? '(absent)'\n : `L${flow.level} self=${flow.selfQueue} producers=[${flow.producedBy.join(', ')}] consumers=[${flow.consumedBy.join(', ')}]`;\n for (const api of [...new Set([...Object.keys(saved), ...Object.keys(recomputed)])].sort()) {\n const before = fields(saved[api]);\n const after = fields(recomputed[api]);\n if (before !== after) lines.push(`contractQueues[\"${api}\"]: ${before} → ${after}`);\n }\n return lines;\n }\n\n private missing(): RuleFailError {\n return this.failure(\n `No runtime goal at ${this.goalPath}. Viewing never creates or replaces the goal, and never renders the current graph in its place.`,\n [\n new Option(`Start a proposal from the saved current runtime graph: ${RUNTIME_GOAL_INIT_COMMAND} — then edit the copy and commit it.`, true),\n new Option(`Write ${this.goalPath} by hand in the RuntimeGraph shape of ${DEFAULT_RUNTIME_GRAPH_PATH}.`),\n ],\n );\n }\n\n private editOption(preferred: boolean): Option {\n return new Option(`Edit ${this.goalPath} by hand — it is a hand-authored proposal, so the fix is in the file, not in source.`, preferred);\n }\n\n private failure(message: string, options: Option[], cause?: Error): RuleFailError {\n return new RuleFailError(RUNTIME_GOAL_RULE_NAME, message, undefined, undefined, options, undefined, cause);\n }\n}\n\n/** What a goal page says it is: a hand-authored proposal, not a generated snapshot (#1239). */\nexport class RuntimeGoalProvenance {\n message(): string {\n return (\n `Goal / Proposed runtime architecture from ${DEFAULT_RUNTIME_GOAL_PATH}. Hand-authored; not generated from source, ` +\n 'and never written by architecture:generate. Viewing changes no file. ' +\n `After editing relationships, recompute derived levels explicitly: ${RUNTIME_GOAL_PREPARE_COMMAND}`\n );\n }\n\n html(): string {\n return (\n `<p class=\"hint\"><strong>Goal / Proposed runtime architecture.</strong> Hand-authored proposal read from ` +\n `<code>${DEFAULT_RUNTIME_GOAL_PATH}</code>; not generated from source and never written by ` +\n `<code>architecture:generate</code>. Viewing changes no file. After editing relationships, recompute derived ` +\n `levels explicitly: <code>${RUNTIME_GOAL_PREPARE_COMMAND}</code>. Compare with the saved current graph ` +\n `(<code>${DEFAULT_RUNTIME_GRAPH_PATH}</code>) in Color by → Goal vs Current.</p>`\n );\n }\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { RuntimeDiffStatus } from './runtime-graph-diff';
|
|
2
|
+
/** One status's colors. Text color stays readable on the fill. */
|
|
3
|
+
export declare class DiffStyle {
|
|
4
|
+
readonly fill: string;
|
|
5
|
+
readonly border: string;
|
|
6
|
+
readonly text: string;
|
|
7
|
+
readonly word: string;
|
|
8
|
+
constructor(fill: string, border: string, text: string, word: string);
|
|
9
|
+
}
|
|
10
|
+
export declare const DIFF_STYLES: Record<RuntimeDiffStatus, DiffStyle>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DIFF_STYLES = exports.DiffStyle = void 0;
|
|
4
|
+
const runtime_graph_diff_1 = require("./runtime-graph-diff");
|
|
5
|
+
/** One status's colors. Text color stays readable on the fill. */
|
|
6
|
+
class DiffStyle {
|
|
7
|
+
fill;
|
|
8
|
+
border;
|
|
9
|
+
text;
|
|
10
|
+
word;
|
|
11
|
+
constructor(fill, border, text, word) {
|
|
12
|
+
this.fill = fill;
|
|
13
|
+
this.border = border;
|
|
14
|
+
this.text = text;
|
|
15
|
+
this.word = word;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.DiffStyle = DiffStyle;
|
|
19
|
+
exports.DIFF_STYLES = {
|
|
20
|
+
[runtime_graph_diff_1.RuntimeDiffStatus.ADDED]: new DiffStyle('#c9f0d3', '#1f8a3b', '#1a1c22', 'added in goal'),
|
|
21
|
+
[runtime_graph_diff_1.RuntimeDiffStatus.REMOVED]: new DiffStyle('#fde0e0', '#c62828', '#7a1c1c', 'removed from goal'),
|
|
22
|
+
[runtime_graph_diff_1.RuntimeDiffStatus.CHANGED]: new DiffStyle('#fde7b0', '#d88a00', '#1a1c22', 'changed'),
|
|
23
|
+
[runtime_graph_diff_1.RuntimeDiffStatus.UNCHANGED]: new DiffStyle('#eef0f4', '#b4b9c4', '#6b7180', 'unchanged'),
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=runtime-goal-styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-goal-styles.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-goal-styles.ts"],"names":[],"mappings":";;;AAAA,6DAAyD;AAEzD,kEAAkE;AAClE,MAAa,SAAS;IAEE;IACA;IACA;IACA;IAJpB,YACoB,IAAY,EACZ,MAAc,EACd,IAAY,EACZ,IAAY;QAHZ,SAAI,GAAJ,IAAI,CAAQ;QACZ,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAAQ;QACZ,SAAI,GAAJ,IAAI,CAAQ;IAC7B,CAAC;CACP;AAPD,8BAOC;AAEY,QAAA,WAAW,GAAyC;IAC7D,CAAC,sCAAiB,CAAC,KAAK,CAAC,EAAE,IAAI,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,eAAe,CAAC;IAC1F,CAAC,sCAAiB,CAAC,OAAO,CAAC,EAAE,IAAI,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,mBAAmB,CAAC;IAChG,CAAC,sCAAiB,CAAC,OAAO,CAAC,EAAE,IAAI,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC;IACtF,CAAC,sCAAiB,CAAC,SAAS,CAAC,EAAE,IAAI,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,CAAC;CAC7F,CAAC","sourcesContent":["import { RuntimeDiffStatus } from './runtime-graph-diff';\n\n/** One status's colors. Text color stays readable on the fill. */\nexport class DiffStyle {\n constructor(\n public readonly fill: string,\n public readonly border: string,\n public readonly text: string,\n public readonly word: string,\n ) {}\n}\n\nexport const DIFF_STYLES: Record<RuntimeDiffStatus, DiffStyle> = {\n [RuntimeDiffStatus.ADDED]: new DiffStyle('#c9f0d3', '#1f8a3b', '#1a1c22', 'added in goal'),\n [RuntimeDiffStatus.REMOVED]: new DiffStyle('#fde0e0', '#c62828', '#7a1c1c', 'removed from goal'),\n [RuntimeDiffStatus.CHANGED]: new DiffStyle('#fde7b0', '#d88a00', '#1a1c22', 'changed'),\n [RuntimeDiffStatus.UNCHANGED]: new DiffStyle('#eef0f4', '#b4b9c4', '#6b7180', 'unchanged'),\n};\n"]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { RuntimeGraph } from './runtime-graph-model';
|
|
2
|
+
/**
|
|
3
|
+
* Shape and internal-reference checks for a HAND-AUTHORED runtime goal (#1239).
|
|
4
|
+
*
|
|
5
|
+
* The generated current graph is validated by regenerating it from source; a goal has no source to
|
|
6
|
+
* regenerate from, so every problem is named against the goal file itself, with the element that is
|
|
7
|
+
* wrong and the edit that fixes it. Problems are collected, never thrown one at a time, so one run
|
|
8
|
+
* names every broken reference.
|
|
9
|
+
*
|
|
10
|
+
* Two kinds of problem, because they have different cures:
|
|
11
|
+
* - STRUCTURAL (shape, dangling references): only an edit of the goal file fixes them.
|
|
12
|
+
* - DERIVED (a missing or invalid level, a missing contract queue, maxLevel): the explicit
|
|
13
|
+
* `--prepare` step computes them from the relationships, so it must accept a goal that has them.
|
|
14
|
+
* Facts that are present but merely disagree with the relationships are drift, reported by
|
|
15
|
+
* RuntimeGoalFile.drift().
|
|
16
|
+
*/
|
|
17
|
+
export declare class RuntimeGoalValidator {
|
|
18
|
+
private readonly goalPath;
|
|
19
|
+
constructor(goalPath: string);
|
|
20
|
+
/** Problems only an edit of the goal file can fix; empty when `--prepare` can run. */
|
|
21
|
+
structural(graph: unknown): string[];
|
|
22
|
+
/** Derived facts `--prepare` computes; call only on a structurally valid goal. */
|
|
23
|
+
derived(graph: RuntimeGraph): string[];
|
|
24
|
+
private shape;
|
|
25
|
+
/** The renderer places every node by its saved level, so each needs one. */
|
|
26
|
+
private levels;
|
|
27
|
+
private references;
|
|
28
|
+
private services;
|
|
29
|
+
private edges;
|
|
30
|
+
private edge;
|
|
31
|
+
/** Every contract-level pubsub edge needs its contract queue, which `--prepare` derives. */
|
|
32
|
+
private contractQueues;
|
|
33
|
+
private queues;
|
|
34
|
+
private triggers;
|
|
35
|
+
private externals;
|
|
36
|
+
private remotes;
|
|
37
|
+
private strings;
|
|
38
|
+
private isMap;
|
|
39
|
+
}
|