@webpieces/nx-webpieces-rules 0.4.884 → 0.4.885
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 +41 -8
- package/package.json +7 -7
- package/src/executors/visualize-runtime/executor.js +13 -1
- package/src/executors/visualize-runtime/executor.js.map +1 -1
- package/src/lib/dot-syntax.js +26 -0
- package/src/lib/dot-syntax.js.map +1 -1
- package/src/lib/graph-color-modes.d.ts +2 -1
- package/src/lib/graph-color-modes.js +5 -2
- package/src/lib/graph-color-modes.js.map +1 -1
- package/src/lib/graph-impact.js +1 -0
- package/src/lib/graph-impact.js.map +1 -1
- package/src/lib/graph-legend.d.ts +1 -1
- package/src/lib/graph-legend.js.map +1 -1
- package/src/lib/graph-mode-state.client.d.ts +32 -0
- package/src/lib/graph-mode-state.client.js +141 -0
- package/src/lib/graph-mode-state.client.js.map +1 -0
- package/src/lib/graph-page-shell.d.ts +5 -1
- package/src/lib/graph-page-shell.js +31 -12
- package/src/lib/graph-page-shell.js.map +1 -1
- package/src/lib/graph-render-model.d.ts +7 -5
- package/src/lib/graph-render-model.js +11 -8
- package/src/lib/graph-render-model.js.map +1 -1
- package/src/lib/graph-visualizer.client.d.ts +11 -46
- package/src/lib/graph-visualizer.client.js +103 -160
- package/src/lib/graph-visualizer.client.js.map +1 -1
- package/src/lib/graph-visualizer.js +2 -1
- package/src/lib/graph-visualizer.js.map +1 -1
- package/src/lib/runtime-details.d.ts +4 -1
- package/src/lib/runtime-details.js +102 -55
- package/src/lib/runtime-details.js.map +1 -1
- package/src/lib/runtime-html-page.d.ts +13 -40
- package/src/lib/runtime-html-page.js +96 -129
- package/src/lib/runtime-html-page.js.map +1 -1
- package/src/lib/runtime-viewer-adapter.d.ts +16 -0
- package/src/lib/runtime-viewer-adapter.js +58 -0
- package/src/lib/runtime-viewer-adapter.js.map +1 -0
- package/src/lib/runtime-visualizer.client.d.ts +9 -19
- package/src/lib/runtime-visualizer.client.js +75 -75
- package/src/lib/runtime-visualizer.client.js.map +1 -1
- package/src/lib/runtime-visualizer.d.ts +2 -16
- package/src/lib/runtime-visualizer.js +22 -44
- package/src/lib/runtime-visualizer.js.map +1 -1
- package/src/lib/runtime-viz-options.d.ts +19 -0
- package/src/lib/runtime-viz-options.js +22 -0
- package/src/lib/runtime-viz-options.js.map +1 -0
|
@@ -14,7 +14,7 @@ exports.RuntimeNodeDetails = RuntimeNodeDetails;
|
|
|
14
14
|
class RuntimeDetails {
|
|
15
15
|
nodes = {};
|
|
16
16
|
edges = {};
|
|
17
|
-
constructor(graph, showExternalNodes) {
|
|
17
|
+
constructor(graph, showExternalNodes, model = null) {
|
|
18
18
|
for (const [name, service] of Object.entries(graph.services)) {
|
|
19
19
|
const implemented = service.implements.map((api) => `${graph.apis[api]?.owner ?? '?'}#${api}` +
|
|
20
20
|
(service.implementsVia?.[api] === undefined
|
|
@@ -38,8 +38,8 @@ class RuntimeDetails {
|
|
|
38
38
|
` (${contract?.type ?? 'rpc'})${external && !showExternalNodes ? ' — destination hidden' : ''}`);
|
|
39
39
|
}
|
|
40
40
|
for (const ref of service.wiringImplements ?? []) {
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
implemented.push(`${graph.apis[ref.api]?.owner ?? '?'}#${ref.api} via ${ref.declaredVia ?? name}` +
|
|
42
|
+
(ref.conditional === undefined ? '' : ` conditional on ${ref.conditional}`));
|
|
43
43
|
}
|
|
44
44
|
for (const ref of service.wiringUses ?? []) {
|
|
45
45
|
used.push(`${graph.apis[ref.api]?.owner ?? '?'}#${ref.api} → ${ref.targetService ?? 'unknown external target'} via ${ref.declaredVia ?? name}` +
|
|
@@ -63,6 +63,53 @@ class RuntimeDetails {
|
|
|
63
63
|
}
|
|
64
64
|
this.nodes[name] = new RuntimeNodeDetails(implemented, [...new Set(used)]);
|
|
65
65
|
}
|
|
66
|
+
if (model !== null)
|
|
67
|
+
this.renderEdges(graph, model);
|
|
68
|
+
}
|
|
69
|
+
/** Bind detail facts to renderer-owned identities, including grouped queue hops. */
|
|
70
|
+
renderEdges(graph, model) {
|
|
71
|
+
for (const edge of model.edges) {
|
|
72
|
+
const identity = `${edge.from}->${edge.to}`;
|
|
73
|
+
const service = graph.services[edge.from] === undefined ? edge.to : edge.from;
|
|
74
|
+
const queue = model.nodes.find((node) => node.id === (edge.from.startsWith('queue__') ? edge.from : edge.to));
|
|
75
|
+
const via = graph.runtimeEdges.filter((call) => {
|
|
76
|
+
if (call.type !== 'pubsub')
|
|
77
|
+
return call.from === edge.from && call.to === edge.to;
|
|
78
|
+
if (call.from !== service && call.to !== service)
|
|
79
|
+
return false;
|
|
80
|
+
return (queue !== undefined &&
|
|
81
|
+
queue.queueKeys.includes(call.queue ?? `${call.from}->${call.to}`));
|
|
82
|
+
});
|
|
83
|
+
const entries = [...(this.edges[identity] ?? [])];
|
|
84
|
+
for (const call of via) {
|
|
85
|
+
for (const api of call.via) {
|
|
86
|
+
entries.push(`${graph.apis[api]?.owner ?? '?'}#${api} → ${call.to} (${call.type ?? 'rpc'})` +
|
|
87
|
+
(call.queue === undefined ? '' : ` via ${call.queue}`));
|
|
88
|
+
for (const ref of graph.services[call.from]?.wiringUses ?? []) {
|
|
89
|
+
if (ref.api !== api ||
|
|
90
|
+
(ref.targetService !== undefined && ref.targetService !== call.to))
|
|
91
|
+
continue;
|
|
92
|
+
entries.push(`${ref.api} via ${ref.declaredVia ?? call.from}` +
|
|
93
|
+
(ref.conditional === undefined
|
|
94
|
+
? ''
|
|
95
|
+
: ` conditional on ${ref.conditional}`) +
|
|
96
|
+
(ref.methodsInferred
|
|
97
|
+
? ' — queue methods inferred from contract'
|
|
98
|
+
: ''));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
for (const ref of graph.services[service]?.wiringUses ?? []) {
|
|
103
|
+
if (!entries.some((entry) => entry.includes(`#${ref.api} →`)))
|
|
104
|
+
continue;
|
|
105
|
+
entries.push(`${ref.api} via ${ref.declaredVia ?? service}` +
|
|
106
|
+
(ref.conditional === undefined
|
|
107
|
+
? ''
|
|
108
|
+
: ` conditional on ${ref.conditional}`) +
|
|
109
|
+
(ref.methodsInferred ? ' — queue methods inferred from contract' : ''));
|
|
110
|
+
}
|
|
111
|
+
this.edges[identity] = [...new Set(entries)];
|
|
112
|
+
}
|
|
66
113
|
}
|
|
67
114
|
script() {
|
|
68
115
|
const encoded = JSON.stringify(this).replace(/</g, '\\u003c');
|
|
@@ -70,15 +117,14 @@ class RuntimeDetails {
|
|
|
70
117
|
}
|
|
71
118
|
}
|
|
72
119
|
exports.RuntimeDetails = RuntimeDetails;
|
|
73
|
-
/**
|
|
120
|
+
/** Explicit click controller; redraws rebind edge controls and dismiss stale anchors. */
|
|
74
121
|
class RuntimeDetailsController {
|
|
75
122
|
data;
|
|
76
123
|
host = document.getElementById('graph');
|
|
77
124
|
panel = document.createElement('div');
|
|
78
125
|
anchor = null;
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
timer;
|
|
126
|
+
identity = '';
|
|
127
|
+
implemented = false;
|
|
82
128
|
constructor(data) {
|
|
83
129
|
this.data = data;
|
|
84
130
|
if (this.host === null)
|
|
@@ -88,19 +134,27 @@ class RuntimeDetailsController {
|
|
|
88
134
|
this.panel.setAttribute('role', 'dialog');
|
|
89
135
|
this.panel.setAttribute('aria-label', 'API relationships');
|
|
90
136
|
document.body.append(this.panel);
|
|
91
|
-
this.panel.addEventListener('pointerenter', () => clearTimeout(this.timer));
|
|
92
|
-
this.panel.addEventListener('pointerleave', () => this.later());
|
|
93
137
|
new MutationObserver(() => this.attach()).observe(this.host, { childList: true });
|
|
94
138
|
this.attach();
|
|
139
|
+
document.addEventListener('wp-runtime-implements', (event) => {
|
|
140
|
+
const detail = event.detail;
|
|
141
|
+
this.open(detail.node, this.data.nodes[detail.name]?.implemented ?? [], detail.name, true);
|
|
142
|
+
});
|
|
95
143
|
document.addEventListener('keydown', (event) => {
|
|
96
|
-
if (event.key === 'Escape' && !this.panel.hidden)
|
|
144
|
+
if (event.key === 'Escape' && !this.panel.hidden) {
|
|
145
|
+
event.stopPropagation();
|
|
97
146
|
this.close();
|
|
147
|
+
}
|
|
98
148
|
});
|
|
99
149
|
document.addEventListener('click', (event) => {
|
|
100
|
-
if (event.target instanceof Node &&
|
|
101
|
-
this.
|
|
150
|
+
if (event.target instanceof Node &&
|
|
151
|
+
!this.panel.contains(event.target) &&
|
|
152
|
+
!this.anchor?.contains(event.target))
|
|
153
|
+
this.close();
|
|
102
154
|
});
|
|
103
155
|
document.addEventListener('wp-graph-transform', () => this.position());
|
|
156
|
+
this.host.addEventListener('scroll', () => this.position());
|
|
157
|
+
window.addEventListener('resize', () => this.position());
|
|
104
158
|
}
|
|
105
159
|
position() {
|
|
106
160
|
if (this.anchor === null || this.panel.hidden)
|
|
@@ -109,81 +163,74 @@ class RuntimeDetailsController {
|
|
|
109
163
|
this.panel.style.left = `${Math.max(12, Math.min(rect.left, innerWidth - this.panel.offsetWidth - 12))}px`;
|
|
110
164
|
this.panel.style.top = `${Math.max(12, Math.min(rect.bottom + 6, innerHeight - this.panel.offsetHeight - 12))}px`;
|
|
111
165
|
}
|
|
112
|
-
hide() {
|
|
113
|
-
this.panel.hidden = true;
|
|
114
|
-
this.pinned = false;
|
|
115
|
-
this.anchor = null;
|
|
116
|
-
}
|
|
117
166
|
close() {
|
|
167
|
+
if (this.panel.hidden)
|
|
168
|
+
return;
|
|
118
169
|
const old = this.anchor;
|
|
119
|
-
this.
|
|
120
|
-
this.
|
|
121
|
-
old?.
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
later() {
|
|
125
|
-
if (!this.pinned)
|
|
126
|
-
this.timer = setTimeout(() => this.hide(), 250);
|
|
170
|
+
this.panel.hidden = true;
|
|
171
|
+
this.anchor = null;
|
|
172
|
+
if (old?.isConnected)
|
|
173
|
+
old.focus();
|
|
127
174
|
}
|
|
128
|
-
open(element, entries,
|
|
129
|
-
clearTimeout(this.timer);
|
|
130
|
-
this.pinned = pin;
|
|
175
|
+
open(element, entries, identity, implemented) {
|
|
131
176
|
this.anchor = element;
|
|
132
|
-
this.
|
|
177
|
+
this.identity = identity;
|
|
178
|
+
this.implemented = implemented;
|
|
133
179
|
const close = document.createElement('button');
|
|
134
180
|
close.type = 'button';
|
|
135
181
|
close.textContent = 'Close';
|
|
136
182
|
close.onclick = () => this.close();
|
|
137
183
|
const list = document.createElement('ul');
|
|
138
|
-
for (const entry of entries
|
|
184
|
+
for (const entry of entries.length === 0
|
|
185
|
+
? ['No implemented contracts recorded in this saved snapshot.']
|
|
186
|
+
: entries) {
|
|
139
187
|
const item = document.createElement('li');
|
|
140
188
|
item.textContent = entry;
|
|
141
189
|
list.append(item);
|
|
142
190
|
}
|
|
143
|
-
this.panel.
|
|
191
|
+
this.panel.replaceChildren(close, list);
|
|
144
192
|
this.panel.hidden = false;
|
|
145
193
|
this.position();
|
|
194
|
+
close.focus({ preventScroll: true });
|
|
146
195
|
}
|
|
147
196
|
attach() {
|
|
148
|
-
for (const
|
|
149
|
-
|
|
197
|
+
for (const group of Array.from(this.host?.querySelectorAll('g.edge') ?? [])) {
|
|
198
|
+
const identity = group.querySelector('title')?.textContent ?? '';
|
|
199
|
+
const entries = this.data.edges[identity];
|
|
200
|
+
if (entries === undefined || entries.length === 0)
|
|
150
201
|
continue;
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
202
|
+
const element = group.querySelector('text');
|
|
203
|
+
if (element !== null && element.dataset['wpDetails'] !== 'true')
|
|
204
|
+
this.attachElement(element, entries, identity);
|
|
205
|
+
}
|
|
206
|
+
if (this.panel.hidden || this.anchor?.isConnected)
|
|
207
|
+
return;
|
|
208
|
+
const groups = Array.from(this.host?.querySelectorAll(this.implemented ? 'g.node' : 'g.edge') ?? []);
|
|
209
|
+
const group = groups.find((node) => node.querySelector('title')?.textContent === this.identity);
|
|
210
|
+
const replacement = this.implemented ? group : group?.querySelector('text');
|
|
211
|
+
if (replacement) {
|
|
212
|
+
this.anchor = replacement;
|
|
213
|
+
this.position();
|
|
161
214
|
}
|
|
215
|
+
else
|
|
216
|
+
this.close();
|
|
162
217
|
}
|
|
163
|
-
attachElement(element, entries) {
|
|
218
|
+
attachElement(element, entries, identity) {
|
|
164
219
|
element.dataset['wpDetails'] = 'true';
|
|
165
220
|
element.classList.add('wp-api-detail');
|
|
166
221
|
element.setAttribute('tabindex', '0');
|
|
167
222
|
element.setAttribute('role', 'button');
|
|
223
|
+
element.setAttribute('aria-label', `Uses: ${identity}`);
|
|
168
224
|
element.setAttribute('aria-haspopup', 'dialog');
|
|
169
|
-
element.addEventListener('pointerenter', () => {
|
|
170
|
-
if (!this.pinned)
|
|
171
|
-
this.open(element, entries, false);
|
|
172
|
-
});
|
|
173
|
-
element.addEventListener('pointerleave', () => this.later());
|
|
174
|
-
element.addEventListener('focus', () => {
|
|
175
|
-
if (!this.pinned && !this.suppressFocus)
|
|
176
|
-
this.open(element, entries, false);
|
|
177
|
-
});
|
|
178
225
|
element.addEventListener('click', (event) => {
|
|
179
226
|
event.stopPropagation();
|
|
180
|
-
this.open(element, entries,
|
|
227
|
+
this.open(element, entries, identity, false);
|
|
181
228
|
});
|
|
182
229
|
element.addEventListener('keydown', (event) => {
|
|
183
230
|
if (event.key === 'Enter' || event.key === ' ') {
|
|
184
231
|
event.preventDefault();
|
|
185
232
|
event.stopPropagation();
|
|
186
|
-
this.open(element, entries,
|
|
233
|
+
this.open(element, entries, identity, false);
|
|
187
234
|
}
|
|
188
235
|
});
|
|
189
236
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-details.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-details.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RuntimeGraph } from './runtime-graph-model';\n\nexport class RuntimeNodeDetails {\n constructor(\n public readonly implemented: string[],\n public readonly used: string[],\n ) {}\n}\n\n/** View data stays complete even when external destinations are hidden from DOT. */\nexport class RuntimeDetails {\n readonly nodes: Record<string, RuntimeNodeDetails> = {};\n readonly edges: Record<string, string[]> = {};\n\n constructor(graph: RuntimeGraph, showExternalNodes: boolean) {\n for (const [name, service] of Object.entries(graph.services)) {\n const implemented = service.implements.map(\n (api) =>\n `${graph.apis[api]?.owner ?? '?'}#${api}` +\n (service.implementsVia?.[api] === undefined\n ? ''\n : ` via ${service.implementsVia[api]}`),\n );\n const used: string[] = [];\n for (const edge of graph.runtimeEdges.filter((edge) => edge.from === name)) {\n const entries = edge.via.map(\n (api) =>\n `${graph.apis[api]?.owner ?? '?'}#${api} → ${edge.to} (${edge.type ?? 'rpc'})` +\n (edge.queue === undefined ? '' : ` via ${edge.queue}`),\n );\n if (service.wiringUses === undefined) used.push(...entries);\n if (edge.type !== 'pubsub') this.edges[`${edge.from}->${edge.to}`] = entries;\n }\n for (const api of service.wiringUses === undefined ? service.uses : []) {\n if (graph.runtimeEdges.some((edge) => edge.from === name && edge.via.includes(api)))\n continue;\n const contract = graph.apis[api];\n const external =\n contract?.type === 'external' || contract?.implementedBy.length === 0;\n used.push(\n `${contract?.owner ?? '?'}#${api} → ${external ? (contract?.externalSystem?.label ?? contract?.owner ?? 'unknown external') : 'unknown / inferred target'}` +\n ` (${contract?.type ?? 'rpc'})${external && !showExternalNodes ? ' — destination hidden' : ''}`,\n );\n }\n for (const ref of service.wiringImplements ?? []) {\n if (ref.conditional !== undefined)\n implemented.push(`${ref.api} conditional on ${ref.conditional}`);\n }\n for (const ref of service.wiringUses ?? []) {\n used.push(\n `${graph.apis[ref.api]?.owner ?? '?'}#${ref.api} → ${ref.targetService ?? 'unknown external target'} via ${ref.declaredVia ?? name}` +\n (ref.conditional === undefined\n ? ''\n : ` conditional on ${ref.conditional}`) +\n (ref.methodsInferred ? ' — queue methods inferred from contract' : ''),\n );\n }\n for (const [identity, system] of Object.entries(graph.externalSystems ?? {})) {\n if (!system.usedBy.includes(name)) continue;\n this.edges[`${name}->system__${identity.replace(/[^a-zA-Z0-9_]/g, '_')}`] =\n system.apis.map(\n (api) =>\n `${graph.apis[api]?.owner ?? '?'}#${api} → ${system.label} (${system.kind})`,\n );\n }\n for (const use of graph.unresolvedUses.filter((use) => use.service === name)) {\n if (graph.apis[use.api]?.externalSystem !== undefined) continue;\n const owner = graph.apis[use.api]?.owner ?? use.api;\n const key = `${name}->external__${owner}`;\n (this.edges[key] ??= []).push(`${owner}#${use.api} → ${owner} (external)`);\n }\n this.nodes[name] = new RuntimeNodeDetails(implemented, [...new Set(used)]);\n }\n }\n\n script(): string {\n const encoded = JSON.stringify(this).replace(/</g, '\\\\u003c');\n return `new (${RuntimeDetailsController.toString()})(${encoded});`;\n }\n}\n\n/** Serialized native DOM controller; no application or framework dependencies. */\nclass RuntimeDetailsController {\n private readonly host = document.getElementById('graph');\n private readonly panel = document.createElement('div');\n private anchor: SVGTextElement | null = null;\n private pinned = false;\n private suppressFocus = false;\n private timer: ReturnType<typeof setTimeout> | undefined;\n\n constructor(private readonly data: RuntimeDetails) {\n if (this.host === null) return;\n this.panel.className = 'wp-graph-details';\n this.panel.hidden = true;\n this.panel.setAttribute('role', 'dialog');\n this.panel.setAttribute('aria-label', 'API relationships');\n document.body.append(this.panel);\n this.panel.addEventListener('pointerenter', () => clearTimeout(this.timer));\n this.panel.addEventListener('pointerleave', () => this.later());\n new MutationObserver(() => this.attach()).observe(this.host, { childList: true });\n this.attach();\n document.addEventListener('keydown', (event) => {\n if (event.key === 'Escape' && !this.panel.hidden) this.close();\n });\n document.addEventListener('click', (event) => {\n if (event.target instanceof Node && !this.panel.contains(event.target)) this.hide();\n });\n document.addEventListener('wp-graph-transform', () => this.position());\n }\n\n private position(): void {\n if (this.anchor === null || this.panel.hidden) return;\n const rect = this.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 }\n\n private hide(): void {\n this.panel.hidden = true;\n this.pinned = false;\n this.anchor = null;\n }\n\n private close(): void {\n const old = this.anchor;\n this.suppressFocus = true;\n this.hide();\n old?.focus();\n this.suppressFocus = false;\n }\n\n private later(): void {\n if (!this.pinned) this.timer = setTimeout(() => this.hide(), 250);\n }\n\n private open(element: SVGTextElement, entries: string[], pin: boolean): void {\n clearTimeout(this.timer);\n this.pinned = pin;\n this.anchor = element;\n this.panel.replaceChildren();\n const close = document.createElement('button');\n close.type = 'button';\n close.textContent = 'Close';\n close.onclick = () => this.close();\n const list = document.createElement('ul');\n for (const entry of entries) {\n const item = document.createElement('li');\n item.textContent = entry;\n list.append(item);\n }\n this.panel.append(close, list);\n this.panel.hidden = false;\n this.position();\n }\n\n private attach(): void {\n for (const element of Array.from(\n this.host?.querySelectorAll<SVGTextElement>('g.node text, g.edge text') ?? [],\n )) {\n if (element.dataset['wpDetails'] === 'true') continue;\n const identity = element.parentElement?.querySelector('title')?.textContent ?? '';\n const label = element.textContent ?? '';\n const node = this.data.nodes[identity];\n const entries = label.startsWith('Implements (')\n ? node?.implemented\n : label.startsWith('Uses (')\n ? (node?.used ?? this.data.edges[identity])\n : undefined;\n if (entries !== undefined) this.attachElement(element, entries);\n }\n }\n\n private attachElement(element: SVGTextElement, entries: string[]): void {\n element.dataset['wpDetails'] = 'true';\n element.classList.add('wp-api-detail');\n element.setAttribute('tabindex', '0');\n element.setAttribute('role', 'button');\n element.setAttribute('aria-haspopup', 'dialog');\n element.addEventListener('pointerenter', () => {\n if (!this.pinned) this.open(element, entries, false);\n });\n element.addEventListener('pointerleave', () => this.later());\n element.addEventListener('focus', () => {\n if (!this.pinned && !this.suppressFocus) this.open(element, entries, false);\n });\n element.addEventListener('click', (event) => {\n event.stopPropagation();\n this.open(element, entries, true);\n });\n element.addEventListener('keydown', (event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n event.stopPropagation();\n this.open(element, entries, true);\n }\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"runtime-details.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-details.ts"],"names":[],"mappings":"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","sourcesContent":["import type { GraphRenderModel } from './graph-render-model';\nimport type { RuntimeGraph } from './runtime-graph-model';\n\nexport class RuntimeNodeDetails {\n constructor(\n public readonly implemented: string[],\n public readonly used: string[],\n ) {}\n}\n\n/** View data stays complete even when external destinations are hidden from DOT. */\nexport class RuntimeDetails {\n readonly nodes: Record<string, RuntimeNodeDetails> = {};\n readonly edges: Record<string, string[]> = {};\n\n constructor(\n graph: RuntimeGraph,\n showExternalNodes: boolean,\n model: GraphRenderModel | null = null,\n ) {\n for (const [name, service] of Object.entries(graph.services)) {\n const implemented = service.implements.map(\n (api) =>\n `${graph.apis[api]?.owner ?? '?'}#${api}` +\n (service.implementsVia?.[api] === undefined\n ? ''\n : ` via ${service.implementsVia[api]}`),\n );\n const used: string[] = [];\n for (const edge of graph.runtimeEdges.filter((edge) => edge.from === name)) {\n const entries = edge.via.map(\n (api) =>\n `${graph.apis[api]?.owner ?? '?'}#${api} → ${edge.to} (${edge.type ?? 'rpc'})` +\n (edge.queue === undefined ? '' : ` via ${edge.queue}`),\n );\n if (service.wiringUses === undefined) used.push(...entries);\n if (edge.type !== 'pubsub') this.edges[`${edge.from}->${edge.to}`] = entries;\n }\n for (const api of service.wiringUses === undefined ? service.uses : []) {\n if (graph.runtimeEdges.some((edge) => edge.from === name && edge.via.includes(api)))\n continue;\n const contract = graph.apis[api];\n const external =\n contract?.type === 'external' || contract?.implementedBy.length === 0;\n used.push(\n `${contract?.owner ?? '?'}#${api} → ${external ? (contract?.externalSystem?.label ?? contract?.owner ?? 'unknown external') : 'unknown / inferred target'}` +\n ` (${contract?.type ?? 'rpc'})${external && !showExternalNodes ? ' — destination hidden' : ''}`,\n );\n }\n for (const ref of service.wiringImplements ?? []) {\n implemented.push(\n `${graph.apis[ref.api]?.owner ?? '?'}#${ref.api} via ${ref.declaredVia ?? name}` +\n (ref.conditional === undefined ? '' : ` conditional on ${ref.conditional}`),\n );\n }\n for (const ref of service.wiringUses ?? []) {\n used.push(\n `${graph.apis[ref.api]?.owner ?? '?'}#${ref.api} → ${ref.targetService ?? 'unknown external target'} via ${ref.declaredVia ?? name}` +\n (ref.conditional === undefined\n ? ''\n : ` conditional on ${ref.conditional}`) +\n (ref.methodsInferred ? ' — queue methods inferred from contract' : ''),\n );\n }\n for (const [identity, system] of Object.entries(graph.externalSystems ?? {})) {\n if (!system.usedBy.includes(name)) continue;\n this.edges[`${name}->system__${identity.replace(/[^a-zA-Z0-9_]/g, '_')}`] =\n system.apis.map(\n (api) =>\n `${graph.apis[api]?.owner ?? '?'}#${api} → ${system.label} (${system.kind})`,\n );\n }\n for (const use of graph.unresolvedUses.filter((use) => use.service === name)) {\n if (graph.apis[use.api]?.externalSystem !== undefined) continue;\n const owner = graph.apis[use.api]?.owner ?? use.api;\n const key = `${name}->external__${owner}`;\n (this.edges[key] ??= []).push(`${owner}#${use.api} → ${owner} (external)`);\n }\n this.nodes[name] = new RuntimeNodeDetails(implemented, [...new Set(used)]);\n }\n if (model !== null) this.renderEdges(graph, model);\n }\n\n /** Bind detail facts to renderer-owned identities, including grouped queue hops. */\n private renderEdges(graph: RuntimeGraph, model: GraphRenderModel): void {\n for (const edge of model.edges) {\n const identity = `${edge.from}->${edge.to}`;\n const service = graph.services[edge.from] === undefined ? edge.to : edge.from;\n const queue = model.nodes.find(\n (node) => node.id === (edge.from.startsWith('queue__') ? edge.from : edge.to),\n );\n const via = graph.runtimeEdges.filter((call) => {\n if (call.type !== 'pubsub') return call.from === edge.from && call.to === edge.to;\n if (call.from !== service && call.to !== service) return false;\n return (\n queue !== undefined &&\n queue.queueKeys.includes(call.queue ?? `${call.from}->${call.to}`)\n );\n });\n const entries = [...(this.edges[identity] ?? [])];\n for (const call of via) {\n for (const api of call.via) {\n entries.push(\n `${graph.apis[api]?.owner ?? '?'}#${api} → ${call.to} (${call.type ?? 'rpc'})` +\n (call.queue === undefined ? '' : ` via ${call.queue}`),\n );\n for (const ref of graph.services[call.from]?.wiringUses ?? []) {\n if (\n ref.api !== api ||\n (ref.targetService !== undefined && ref.targetService !== call.to)\n )\n continue;\n entries.push(\n `${ref.api} via ${ref.declaredVia ?? call.from}` +\n (ref.conditional === undefined\n ? ''\n : ` conditional on ${ref.conditional}`) +\n (ref.methodsInferred\n ? ' — queue methods inferred from contract'\n : ''),\n );\n }\n }\n }\n for (const ref of graph.services[service]?.wiringUses ?? []) {\n if (!entries.some((entry) => entry.includes(`#${ref.api} →`))) continue;\n entries.push(\n `${ref.api} via ${ref.declaredVia ?? service}` +\n (ref.conditional === undefined\n ? ''\n : ` conditional on ${ref.conditional}`) +\n (ref.methodsInferred ? ' — queue methods inferred from contract' : ''),\n );\n }\n this.edges[identity] = [...new Set(entries)];\n }\n }\n\n script(): string {\n const encoded = JSON.stringify(this).replace(/</g, '\\\\u003c');\n return `new (${RuntimeDetailsController.toString()})(${encoded});`;\n }\n}\n\n/** Explicit click controller; redraws rebind edge controls and dismiss stale anchors. */\nclass RuntimeDetailsController {\n private readonly host = document.getElementById('graph');\n private readonly panel = document.createElement('div');\n private anchor: SVGElement | null = null;\n private identity = '';\n private implemented = false;\n\n constructor(private readonly data: RuntimeDetails) {\n if (this.host === null) return;\n this.panel.className = 'wp-graph-details';\n this.panel.hidden = true;\n this.panel.setAttribute('role', 'dialog');\n this.panel.setAttribute('aria-label', 'API relationships');\n document.body.append(this.panel);\n new MutationObserver(() => this.attach()).observe(this.host, { childList: true });\n this.attach();\n document.addEventListener('wp-runtime-implements', (event) => {\n const detail = (event as CustomEvent<RuntimeImplementsPayload>).detail;\n this.open(\n detail.node,\n this.data.nodes[detail.name]?.implemented ?? [],\n detail.name,\n true,\n );\n });\n document.addEventListener('keydown', (event) => {\n if (event.key === 'Escape' && !this.panel.hidden) {\n event.stopPropagation();\n this.close();\n }\n });\n document.addEventListener('click', (event) => {\n if (\n event.target instanceof Node &&\n !this.panel.contains(event.target) &&\n !this.anchor?.contains(event.target)\n )\n this.close();\n });\n document.addEventListener('wp-graph-transform', () => this.position());\n this.host.addEventListener('scroll', () => this.position());\n window.addEventListener('resize', () => this.position());\n }\n\n private position(): void {\n if (this.anchor === null || this.panel.hidden) return;\n const rect = this.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 }\n\n private close(): void {\n if (this.panel.hidden) return;\n const old = this.anchor;\n this.panel.hidden = true;\n this.anchor = null;\n if (old?.isConnected) old.focus();\n }\n\n private open(\n element: SVGElement,\n entries: string[],\n identity: string,\n implemented: boolean,\n ): void {\n this.anchor = element;\n this.identity = identity;\n this.implemented = implemented;\n const close = document.createElement('button');\n close.type = 'button';\n close.textContent = 'Close';\n close.onclick = () => this.close();\n const list = document.createElement('ul');\n for (const entry of entries.length === 0\n ? ['No implemented contracts recorded in this saved snapshot.']\n : entries) {\n const item = document.createElement('li');\n item.textContent = entry;\n list.append(item);\n }\n this.panel.replaceChildren(close, list);\n this.panel.hidden = false;\n this.position();\n close.focus({ preventScroll: true });\n }\n\n private attach(): void {\n for (const group of Array.from(this.host?.querySelectorAll<SVGGElement>('g.edge') ?? [])) {\n const identity = group.querySelector('title')?.textContent ?? '';\n const entries = this.data.edges[identity];\n if (entries === undefined || entries.length === 0) continue;\n const element = group.querySelector('text');\n if (element !== null && element.dataset['wpDetails'] !== 'true')\n this.attachElement(element, entries, identity);\n }\n if (this.panel.hidden || this.anchor?.isConnected) return;\n const groups = Array.from(\n this.host?.querySelectorAll<SVGGElement>(this.implemented ? 'g.node' : 'g.edge') ?? [],\n );\n const group = groups.find(\n (node) => node.querySelector('title')?.textContent === this.identity,\n );\n const replacement = this.implemented ? group : group?.querySelector('text');\n if (replacement) {\n this.anchor = replacement;\n this.position();\n } else this.close();\n }\n\n private attachElement(element: SVGTextElement, entries: string[], identity: string): void {\n element.dataset['wpDetails'] = 'true';\n element.classList.add('wp-api-detail');\n element.setAttribute('tabindex', '0');\n element.setAttribute('role', 'button');\n element.setAttribute('aria-label', `Uses: ${identity}`);\n element.setAttribute('aria-haspopup', 'dialog');\n element.addEventListener('click', (event) => {\n event.stopPropagation();\n this.open(element, entries, identity, false);\n });\n element.addEventListener('keydown', (event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n event.stopPropagation();\n this.open(element, entries, identity, false);\n }\n });\n }\n}\n"]}
|
|
@@ -1,46 +1,19 @@
|
|
|
1
1
|
import { GraphRenderModel } from './graph-render-model';
|
|
2
2
|
import type { RuntimeGraph } from './runtime-graph-model';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* and the legend.
|
|
6
|
-
*
|
|
7
|
-
* A CLASS rather than a bag of module functions so the client-text seam can be a constructor
|
|
8
|
-
* parameter the way GraphVisualizer's is: the default reads the COMPILED sibling, which exists in
|
|
9
|
-
* dist and in the published tarball but NOT in a source checkout, and a unit test running from
|
|
10
|
-
* source hands in the text itself instead of requiring the package to have been built first.
|
|
11
|
-
*/
|
|
3
|
+
import { RuntimeVizOptions } from './runtime-viz-options';
|
|
4
|
+
/** Runtime facts and shape adapter inside the same shell/controller as the project viewer. */
|
|
12
5
|
export declare class RuntimeHtmlPage {
|
|
13
6
|
private readonly clientJs;
|
|
14
7
|
private readonly filterJs;
|
|
15
|
-
private readonly
|
|
16
|
-
private readonly
|
|
17
|
-
|
|
18
|
-
private readonly
|
|
19
|
-
constructor(clientJs?: () => string, filterJs?: () => string);
|
|
20
|
-
render(model: GraphRenderModel, title: string, graph: RuntimeGraph,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
*/
|
|
27
|
-
productChips(graph: RuntimeGraph): string;
|
|
28
|
-
/**
|
|
29
|
-
* The browser half lives in runtime-visualizer.client.ts (matching graph-visualizer.client.ts)
|
|
30
|
-
* rather than in a template literal here: it renders with @viz-js/viz v3, redraws every queue
|
|
31
|
-
* node as a true horizontal cylinder, and wires the shared node menu onto every box — more
|
|
32
|
-
* logic than belongs inline in a .ts string. The substitution is a blind split/join, so the
|
|
33
|
-
* render-model placeholder must appear EXACTLY ONCE in the client.
|
|
34
|
-
*/
|
|
35
|
-
private script;
|
|
36
|
-
/**
|
|
37
|
-
* Page styles, including the shared menu stylesheet: the clickable cursor + blue glow on every
|
|
38
|
-
* box, and the dim/undim rules the lock toggles, scoped to this page's `#graph` host. Those two
|
|
39
|
-
* blocks are shared verbatim with architecture/dependencies.html and every design.html.
|
|
40
|
-
*
|
|
41
|
-
* The legend swatches are hand-drawn inline SVG on purpose: the alternative is shelling out to
|
|
42
|
-
* Graphviz at generate time, which would make writing the HTML depend on a `dot` binary being
|
|
43
|
-
* installed — a dependency this tool does not otherwise have, since rendering is client-side.
|
|
44
|
-
*/
|
|
45
|
-
private styles;
|
|
8
|
+
private readonly sharedJs;
|
|
9
|
+
private readonly assets;
|
|
10
|
+
private readonly menu;
|
|
11
|
+
private readonly navigation;
|
|
12
|
+
constructor(clientJs?: () => string, filterJs?: () => string, sharedJs?: () => string);
|
|
13
|
+
render(model: GraphRenderModel, title: string, graph: RuntimeGraph, options?: RuntimeVizOptions): string;
|
|
14
|
+
private designLinks;
|
|
15
|
+
private lockControl;
|
|
16
|
+
private legend;
|
|
17
|
+
private edgeKey;
|
|
18
|
+
private responsibilities;
|
|
46
19
|
}
|