@webpieces/nx-webpieces-rules 0.4.910 → 0.4.912

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.
@@ -15,7 +15,6 @@ const graph_node_menu_1 = require("./graph-node-menu");
15
15
  const graph_page_shell_1 = require("./graph-page-shell");
16
16
  const graph_page_styles_1 = require("./graph-page-styles");
17
17
  const graph_legend_1 = require("./graph-legend");
18
- const graph_products_1 = require("./graph-products");
19
18
  const graph_color_modes_1 = require("./graph-color-modes");
20
19
  const graph_impact_1 = require("./graph-impact");
21
20
  const graph_responsibilities_1 = require("./graph-responsibilities");
@@ -41,7 +40,7 @@ class RuntimeHtmlPage {
41
40
  const roles = [
42
41
  ...new Set(model.nodes.flatMap((node) => (node.tags === null ? [] : [node.tags.role]))),
43
42
  ].sort();
44
- const products = [...new Set(model.nodes.flatMap((node) => node.products))].sort();
43
+ const products = this.shownProducts(model);
45
44
  const parts = new graph_page_shell_1.ShellParts(title, this.lockControl(model), this.legend(model), this.edgeKey(), this.assets.html() + '<span id="wp-context-count"></span>', new saved_snapshot_1.SavedSnapshot().html(), this.responsibilities(graph, options), products, true, frameworks, roles, '<div class="wp-empty" id="wp-empty" hidden>No matching services. Open Filter and Clear all, or turn off Hide unconnected.</div>');
46
45
  const shared = this.sharedJs()
47
46
  .split(graph_visualizer_2.CLIENT_MODEL_PLACEHOLDER)
@@ -93,7 +92,7 @@ class RuntimeHtmlPage {
93
92
  ]
94
93
  .map((role) => tag('role', role, graph_color_modes_1.ROLE_STYLES.find((style) => style.role === role)?.fill ?? '#e4e6ec'))
95
94
  .join('');
96
- const products = new graph_products_1.ProductPalette(model.legend.products.map((count) => count.product)).colors
95
+ const products = this.shownProducts(model)
97
96
  .map((color) => tag('product', color.product, color.color))
98
97
  .join('');
99
98
  return (`<section data-wp-legend-mode="runtime" class="wp-legend-list">${frameworks}${tag('runtime', 'unknown', '#e4e6ec')}<p>Neutral: unknown runtime. Nested: specialization; stripes: multiple runtimes. Context retains kind colors.</p></section>
@@ -101,6 +100,15 @@ class RuntimeHtmlPage {
101
100
  `<section data-wp-legend-mode="impact" class="wp-legend-list" hidden>${new graph_legend_1.GraphLegend().impactRows()}</section><section data-wp-legend-mode="product" class="wp-legend-list" hidden>${products}<p>Stripes: several products; neutral: all products; white/dashed: no product. Context inherits adjacent service memberships.</p></section>` +
102
101
  '<p>Queues, clocks, datastores and vendors remain context in Impact; no source ownership or CI status is implied.</p>');
103
102
  }
103
+ /**
104
+ * The products some drawn box carries, colored from the ONE palette the boxes were painted with —
105
+ * built over every declared product (#1244), so a product keeps the dependency viewer's color even
106
+ * though this page lists only the products it shows.
107
+ */
108
+ shownProducts(model) {
109
+ const shown = new Set(model.nodes.flatMap((node) => node.products));
110
+ return model.legend.palette.colors.filter((color) => shown.has(color.product));
111
+ }
104
112
  edgeKey() {
105
113
  return '<div class="wp-legend-list"><p>→ RPC · ⇢ queued/event · red: legacy cycle</p><p>Horizontal cylinder: queue<br>Upright cylinder: datastore<br>⏰: scheduler<br>Dashed box: external system</p></div>';
106
114
  }
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-html-page.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-html-page.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport { DesignLink } from './graph-visualizer';\nimport { GraphRenderModel, GraphFilterAssets } from './graph-render-model';\nimport { RuntimeDetails } from './runtime-details';\nimport type { RuntimeGraph } from './runtime-graph-model';\nimport { RuntimeVizOptions } from './runtime-viz-options';\nimport { GraphNavigation, NavigationLayout } from './graph-navigation';\nimport { SavedSnapshot } from './saved-snapshot';\nimport {\n CLIENT_MODEL_PLACEHOLDER,\n CLIENT_DESIGN_LINKS_PLACEHOLDER,\n readCompiledClient,\n} from './graph-visualizer';\nimport { GraphNodeMenu } from './graph-node-menu';\nimport { GraphPageShell, ShellParts } from './graph-page-shell';\nimport { GraphPageStyles } from './graph-page-styles';\nimport { GraphLegend } from './graph-legend';\nimport { ProductPalette } from './graph-products';\nimport { FRAMEWORK_STYLES, ROLE_STYLES } from './graph-color-modes';\nimport { IMPACT_SIDECAR_SRC } from './graph-impact';\nimport { ResponsibilitiesRenderer } from './graph-responsibilities';\nimport { htmlLabelText } from './dot-syntax';\nimport type { EnhancedGraph } from './graph-sorter';\n\n/** Runtime facts and shape adapter inside the same shell/controller as the project viewer. */\nexport class RuntimeHtmlPage {\n private readonly assets = new GraphFilterAssets();\n private readonly menu = new GraphNodeMenu();\n private readonly navigation = new GraphNavigation(NavigationLayout.FLOATING);\n\n constructor(\n private readonly clientJs: () => string = (): string =>\n readCompiledClient('runtime-visualizer.client.js'),\n private readonly filterJs: () => string = (): string =>\n readCompiledClient('graph-filter.client.js'),\n private readonly sharedJs: () => string = (): string =>\n readCompiledClient('graph-visualizer.client.js'),\n ) {}\n\n render(\n model: GraphRenderModel,\n title: string,\n graph: RuntimeGraph,\n options: RuntimeVizOptions = new RuntimeVizOptions(),\n ): string {\n model.viewer = 'runtime';\n const frameworks = [\n ...new Set(model.nodes.flatMap((node) => node.tags?.frameworks ?? [])),\n ].sort();\n const roles = [\n ...new Set(model.nodes.flatMap((node) => (node.tags === null ? [] : [node.tags.role]))),\n ].sort();\n const products = [...new Set(model.nodes.flatMap((node) => node.products))].sort();\n const parts = new ShellParts(\n title,\n this.lockControl(model),\n this.legend(model),\n this.edgeKey(),\n this.assets.html() + '<span id=\"wp-context-count\"></span>',\n new SavedSnapshot().html(),\n this.responsibilities(graph, options),\n products,\n true,\n frameworks,\n roles,\n '<div class=\"wp-empty\" id=\"wp-empty\" hidden>No matching services. Open Filter and Clear all, or turn off Hide unconnected.</div>',\n );\n const shared = this.sharedJs()\n .split(CLIENT_MODEL_PLACEHOLDER)\n .join(this.assets.json(model))\n .split(CLIENT_DESIGN_LINKS_PLACEHOLDER)\n .join(this.assets.json(this.designLinks(graph, options)));\n return `<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>${htmlLabelText(title)}</title>\n<script src=\"https://cdn.jsdelivr.net/npm/@viz-js/viz@3.28.0/dist/viz-global.js\"></script>\n<script src=\"${IMPACT_SIDECAR_SRC}\"></script>\n<style>${this.menu.styles()}${this.menu.dimStyles('#graph')}${this.assets.styles()}${this.navigation.styles()}${new GraphPageStyles().css()}\n.wp-graph-details { position:fixed; z-index:60; max-width:min(520px,calc(100vw - 24px)); max-height:70vh; overflow:auto; background:var(--wp-surface); border:1px solid var(--wp-line); border-radius:10px; padding:14px; box-shadow:0 8px 24px #0002; }\n.wp-graph-details button { cursor:pointer; } .wp-api-detail { cursor:pointer; text-decoration:underline; }\n.wp-api-detail:focus-visible { outline:3px solid var(--wp-accent); } #wp-context-count { font-size:11px; color:var(--wp-muted); }\n.wp-empty { position:absolute; top:70px; left:16px; padding:16px; background:var(--wp-surface); border-radius:10px; }\n</style></head><body data-wp-project-facts=\"${options.projects !== null}\">${new GraphPageShell().body(parts)}\n<script>${this.menu.script()}</script><script>${this.filterJs()}</script><script>${this.navigation.script()}</script>\n<script>${new RuntimeDetails(graph, options.showExternalNodes, model).script()}</script>\n<script>${this.clientJs()}</script><script>${shared}</script></body></html>`;\n }\n\n private designLinks(graph: RuntimeGraph, options: RuntimeVizOptions): DesignLink[] {\n const links: DesignLink[] = [];\n for (const name of Object.keys(graph.services).sort()) {\n if (graph.services[name].drawOnGraph === false) continue;\n const design = options.projects?.[name]?.designFile?.replace(\n /design\\.json$/,\n 'design.html',\n );\n if (\n !design ||\n !options.workspaceRoot ||\n !fs.existsSync(path.join(options.workspaceRoot, design))\n )\n continue;\n links.push(new DesignLink(name, path.posix.relative('tmp/webpieces', design)));\n }\n return links;\n }\n\n private lockControl(model: GraphRenderModel): string {\n const entries = model.nodes\n .map(\n (node) =>\n `<option value=\"${htmlLabelText(node.id)}\">${htmlLabelText(node.id)} · ${node.tags?.role ?? 'context'}</option>`,\n )\n .join('');\n return `<input type=\"search\" id=\"wp-lock\" list=\"wp-lock-options\" placeholder=\"Lock a node… ( / )\" autocomplete=\"off\" spellcheck=\"false\"><datalist id=\"wp-lock-options\">${entries}</datalist>`;\n }\n\n private legend(model: GraphRenderModel): string {\n const tag = (group: string, value: string, color: string): string =>\n `<div class=\"wp-legend-row\" data-wp-legend-group=\"${group}\" data-wp-legend-value=\"${htmlLabelText(value)}\"><svg width=\"20\" height=\"14\"><rect width=\"20\" height=\"14\" rx=\"2\" fill=\"${color}\"/></svg>${htmlLabelText(value)}</div>`;\n const frameworks = Object.values(FRAMEWORK_STYLES)\n .filter((style) => model.legend.frameworks.includes(style.framework))\n .map((style) => tag('runtime', style.framework, style.color))\n .join('');\n const roles = [\n ...new Set(model.nodes.flatMap((node) => (node.tags === null ? [] : [node.tags.role]))),\n ]\n .map((role) =>\n tag(\n 'role',\n role,\n ROLE_STYLES.find((style) => style.role === role)?.fill ?? '#e4e6ec',\n ),\n )\n .join('');\n const products = new ProductPalette(\n model.legend.products.map((count) => count.product),\n ).colors\n .map((color) => tag('product', color.product, color.color))\n .join('');\n return (\n `<section data-wp-legend-mode=\"runtime\" class=\"wp-legend-list\">${frameworks}${tag('runtime', 'unknown', '#e4e6ec')}<p>Neutral: unknown runtime. Nested: specialization; stripes: multiple runtimes. Context retains kind colors.</p></section>\n<section data-wp-legend-mode=\"architecture\" class=\"wp-legend-list\" hidden>${roles}<p>Auxiliary nodes use kind colors, never project roles.</p></section>` +\n `<section data-wp-legend-mode=\"impact\" class=\"wp-legend-list\" hidden>${new GraphLegend().impactRows()}</section><section data-wp-legend-mode=\"product\" class=\"wp-legend-list\" hidden>${products}<p>Stripes: several products; neutral: all products; white/dashed: no product. Context inherits adjacent service memberships.</p></section>` +\n '<p>Queues, clocks, datastores and vendors remain context in Impact; no source ownership or CI status is implied.</p>'\n );\n }\n\n private edgeKey(): string {\n return '<div class=\"wp-legend-list\"><p>→ RPC · ⇢ queued/event · red: legacy cycle</p><p>Horizontal cylinder: queue<br>Upright cylinder: datastore<br>⏰: scheduler<br>Dashed box: external system</p></div>';\n }\n\n private responsibilities(graph: RuntimeGraph, options: RuntimeVizOptions): string {\n const projects: EnhancedGraph = {};\n for (const [name, service] of Object.entries(graph.services)) {\n projects[name] = {\n ...options.projects?.[name],\n level: service.level,\n dependsOn: service.dependsOn,\n drawOnGraph: service.drawOnGraph,\n };\n }\n return new ResponsibilitiesRenderer().generateSection(projects, options.workspaceRoot);\n }\n}\n"]}
1
+ {"version":3,"file":"runtime-html-page.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-html-page.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport { DesignLink } from './graph-visualizer';\nimport { GraphRenderModel, GraphFilterAssets } from './graph-render-model';\nimport { RuntimeDetails } from './runtime-details';\nimport type { RuntimeGraph } from './runtime-graph-model';\nimport { RuntimeVizOptions } from './runtime-viz-options';\nimport { GraphNavigation, NavigationLayout } from './graph-navigation';\nimport { SavedSnapshot } from './saved-snapshot';\nimport {\n CLIENT_MODEL_PLACEHOLDER,\n CLIENT_DESIGN_LINKS_PLACEHOLDER,\n readCompiledClient,\n} from './graph-visualizer';\nimport { GraphNodeMenu } from './graph-node-menu';\nimport { GraphPageShell, ShellParts } from './graph-page-shell';\nimport { GraphPageStyles } from './graph-page-styles';\nimport { GraphLegend } from './graph-legend';\nimport { ProductColor } from './graph-products';\nimport { FRAMEWORK_STYLES, ROLE_STYLES } from './graph-color-modes';\nimport { IMPACT_SIDECAR_SRC } from './graph-impact';\nimport { ResponsibilitiesRenderer } from './graph-responsibilities';\nimport { htmlLabelText } from './dot-syntax';\nimport type { EnhancedGraph } from './graph-sorter';\n\n/** Runtime facts and shape adapter inside the same shell/controller as the project viewer. */\nexport class RuntimeHtmlPage {\n private readonly assets = new GraphFilterAssets();\n private readonly menu = new GraphNodeMenu();\n private readonly navigation = new GraphNavigation(NavigationLayout.FLOATING);\n\n constructor(\n private readonly clientJs: () => string = (): string =>\n readCompiledClient('runtime-visualizer.client.js'),\n private readonly filterJs: () => string = (): string =>\n readCompiledClient('graph-filter.client.js'),\n private readonly sharedJs: () => string = (): string =>\n readCompiledClient('graph-visualizer.client.js'),\n ) {}\n\n render(\n model: GraphRenderModel,\n title: string,\n graph: RuntimeGraph,\n options: RuntimeVizOptions = new RuntimeVizOptions(),\n ): string {\n model.viewer = 'runtime';\n const frameworks = [\n ...new Set(model.nodes.flatMap((node) => node.tags?.frameworks ?? [])),\n ].sort();\n const roles = [\n ...new Set(model.nodes.flatMap((node) => (node.tags === null ? [] : [node.tags.role]))),\n ].sort();\n const products = this.shownProducts(model);\n const parts = new ShellParts(\n title,\n this.lockControl(model),\n this.legend(model),\n this.edgeKey(),\n this.assets.html() + '<span id=\"wp-context-count\"></span>',\n new SavedSnapshot().html(),\n this.responsibilities(graph, options),\n products,\n true,\n frameworks,\n roles,\n '<div class=\"wp-empty\" id=\"wp-empty\" hidden>No matching services. Open Filter and Clear all, or turn off Hide unconnected.</div>',\n );\n const shared = this.sharedJs()\n .split(CLIENT_MODEL_PLACEHOLDER)\n .join(this.assets.json(model))\n .split(CLIENT_DESIGN_LINKS_PLACEHOLDER)\n .join(this.assets.json(this.designLinks(graph, options)));\n return `<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>${htmlLabelText(title)}</title>\n<script src=\"https://cdn.jsdelivr.net/npm/@viz-js/viz@3.28.0/dist/viz-global.js\"></script>\n<script src=\"${IMPACT_SIDECAR_SRC}\"></script>\n<style>${this.menu.styles()}${this.menu.dimStyles('#graph')}${this.assets.styles()}${this.navigation.styles()}${new GraphPageStyles().css()}\n.wp-graph-details { position:fixed; z-index:60; max-width:min(520px,calc(100vw - 24px)); max-height:70vh; overflow:auto; background:var(--wp-surface); border:1px solid var(--wp-line); border-radius:10px; padding:14px; box-shadow:0 8px 24px #0002; }\n.wp-graph-details button { cursor:pointer; } .wp-api-detail { cursor:pointer; text-decoration:underline; }\n.wp-api-detail:focus-visible { outline:3px solid var(--wp-accent); } #wp-context-count { font-size:11px; color:var(--wp-muted); }\n.wp-empty { position:absolute; top:70px; left:16px; padding:16px; background:var(--wp-surface); border-radius:10px; }\n</style></head><body data-wp-project-facts=\"${options.projects !== null}\">${new GraphPageShell().body(parts)}\n<script>${this.menu.script()}</script><script>${this.filterJs()}</script><script>${this.navigation.script()}</script>\n<script>${new RuntimeDetails(graph, options.showExternalNodes, model).script()}</script>\n<script>${this.clientJs()}</script><script>${shared}</script></body></html>`;\n }\n\n private designLinks(graph: RuntimeGraph, options: RuntimeVizOptions): DesignLink[] {\n const links: DesignLink[] = [];\n for (const name of Object.keys(graph.services).sort()) {\n if (graph.services[name].drawOnGraph === false) continue;\n const design = options.projects?.[name]?.designFile?.replace(\n /design\\.json$/,\n 'design.html',\n );\n if (\n !design ||\n !options.workspaceRoot ||\n !fs.existsSync(path.join(options.workspaceRoot, design))\n )\n continue;\n links.push(new DesignLink(name, path.posix.relative('tmp/webpieces', design)));\n }\n return links;\n }\n\n private lockControl(model: GraphRenderModel): string {\n const entries = model.nodes\n .map(\n (node) =>\n `<option value=\"${htmlLabelText(node.id)}\">${htmlLabelText(node.id)} · ${node.tags?.role ?? 'context'}</option>`,\n )\n .join('');\n return `<input type=\"search\" id=\"wp-lock\" list=\"wp-lock-options\" placeholder=\"Lock a node… ( / )\" autocomplete=\"off\" spellcheck=\"false\"><datalist id=\"wp-lock-options\">${entries}</datalist>`;\n }\n\n private legend(model: GraphRenderModel): string {\n const tag = (group: string, value: string, color: string): string =>\n `<div class=\"wp-legend-row\" data-wp-legend-group=\"${group}\" data-wp-legend-value=\"${htmlLabelText(value)}\"><svg width=\"20\" height=\"14\"><rect width=\"20\" height=\"14\" rx=\"2\" fill=\"${color}\"/></svg>${htmlLabelText(value)}</div>`;\n const frameworks = Object.values(FRAMEWORK_STYLES)\n .filter((style) => model.legend.frameworks.includes(style.framework))\n .map((style) => tag('runtime', style.framework, style.color))\n .join('');\n const roles = [\n ...new Set(model.nodes.flatMap((node) => (node.tags === null ? [] : [node.tags.role]))),\n ]\n .map((role) =>\n tag(\n 'role',\n role,\n ROLE_STYLES.find((style) => style.role === role)?.fill ?? '#e4e6ec',\n ),\n )\n .join('');\n const products = this.shownProducts(model)\n .map((color) => tag('product', color.product, color.color))\n .join('');\n return (\n `<section data-wp-legend-mode=\"runtime\" class=\"wp-legend-list\">${frameworks}${tag('runtime', 'unknown', '#e4e6ec')}<p>Neutral: unknown runtime. Nested: specialization; stripes: multiple runtimes. Context retains kind colors.</p></section>\n<section data-wp-legend-mode=\"architecture\" class=\"wp-legend-list\" hidden>${roles}<p>Auxiliary nodes use kind colors, never project roles.</p></section>` +\n `<section data-wp-legend-mode=\"impact\" class=\"wp-legend-list\" hidden>${new GraphLegend().impactRows()}</section><section data-wp-legend-mode=\"product\" class=\"wp-legend-list\" hidden>${products}<p>Stripes: several products; neutral: all products; white/dashed: no product. Context inherits adjacent service memberships.</p></section>` +\n '<p>Queues, clocks, datastores and vendors remain context in Impact; no source ownership or CI status is implied.</p>'\n );\n }\n\n /**\n * The products some drawn box carries, colored from the ONE palette the boxes were painted with —\n * built over every declared product (#1244), so a product keeps the dependency viewer's color even\n * though this page lists only the products it shows.\n */\n private shownProducts(model: GraphRenderModel): ProductColor[] {\n const shown = new Set(model.nodes.flatMap((node) => node.products));\n return model.legend.palette.colors.filter((color: ProductColor): boolean => shown.has(color.product));\n }\n\n private edgeKey(): string {\n return '<div class=\"wp-legend-list\"><p>→ RPC · ⇢ queued/event · red: legacy cycle</p><p>Horizontal cylinder: queue<br>Upright cylinder: datastore<br>⏰: scheduler<br>Dashed box: external system</p></div>';\n }\n\n private responsibilities(graph: RuntimeGraph, options: RuntimeVizOptions): string {\n const projects: EnhancedGraph = {};\n for (const [name, service] of Object.entries(graph.services)) {\n projects[name] = {\n ...options.projects?.[name],\n level: service.level,\n dependsOn: service.dependsOn,\n drawOnGraph: service.drawOnGraph,\n };\n }\n return new ResponsibilitiesRenderer().generateSection(projects, options.workspaceRoot);\n }\n}\n"]}
@@ -16,11 +16,13 @@ class RuntimeViewerAdapter {
16
16
  constructor(graph, projects) {
17
17
  this.graph = graph;
18
18
  this.projects = projects;
19
- this.palette = new graph_products_1.ProductPalette([
20
- ...new Set(Object.values(graph.services)
21
- .filter((service) => service.drawOnGraph !== false)
22
- .flatMap((service) => service.products ?? [])),
23
- ].sort());
19
+ // The FULL declared product set (#1244), never just the services drawn here: collision
20
+ // resolution depends on the set, so a subset could recolor a product away from the color the
21
+ // dependency viewer gives it.
22
+ const declared = Object.values(graph.services).flatMap((service) => service.products ?? []);
23
+ if (projects !== null)
24
+ declared.push(...graph_products_1.ProductPalette.fromGraph(projects).names());
25
+ this.palette = new graph_products_1.ProductPalette(declared);
24
26
  }
25
27
  service(model, name, service) {
26
28
  const project = this.projects?.[name];
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-viewer-adapter.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-viewer-adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import type { EnhancedGraph } from './graph-sorter';\nimport type { RuntimeGraph, RuntimeService } from './runtime-graph-model';\nimport { GraphRenderModel, RenderNode } from './graph-render-model';\nimport { NodeFacts, NodeModeDots, NodeModeStyler } from './graph-color-modes';\nimport { ProductPalette, PRODUCT_SHARED_FILL, PRODUCT_NONE_FILL } from './graph-products';\nimport { LevelBand } from './graph-level-bands';\nimport { RemoteServiceNodeId } from './remote-service-node-id';\nimport { RuntimeExternalTriggers } from './runtime-external-triggers';\n\n/** Saved project facts enrich presentation without changing runtime derivation or topology. */\nexport class RuntimeViewerAdapter {\n private readonly styler = new NodeModeStyler();\n private readonly palette: ProductPalette;\n\n constructor(\n private readonly graph: RuntimeGraph,\n private readonly projects: EnhancedGraph | null,\n ) {\n this.palette = new ProductPalette(\n [\n ...new Set(\n Object.values(graph.services)\n .filter((service) => service.drawOnGraph !== false)\n .flatMap((service) => service.products ?? []),\n ),\n ].sort(),\n );\n }\n\n service(model: GraphRenderModel, name: string, service: RuntimeService): string {\n const project = this.projects?.[name];\n const role = service.role ?? project?.role ?? 'unknown';\n const facts = new NodeFacts(\n name,\n name.split('/').pop() ?? name,\n service.level,\n role,\n project?.framework ?? [],\n service.products ?? [],\n `Implements (${new Set(service.implements).size})${service.serviceName === undefined ? '' : ` · \"${service.serviceName}\"`}`,\n );\n this.styler.record(model.legend, facts, this.palette);\n return model.styledNode(facts, this.styler.dots(facts, this.palette));\n }\n\n levelBands(model: GraphRenderModel): LevelBand[] {\n const levels = new Map<string, number>();\n const selfQueues = new Set<string>();\n const safe = (name: string): string => name.replace(/[^A-Za-z0-9_]/g, '_');\n for (const [name, service] of Object.entries(this.graph.services))\n levels.set(name, service.level);\n for (const node of model.nodes) {\n if (node.queueKeys.length === 0) continue;\n const key = node.queueKeys[0];\n const queue = key.startsWith('queue:')\n ? this.graph.contractQueues[key.slice(6)]\n : this.graph.queues[key];\n levels.set(node.id, queue.level);\n if (queue.selfQueue && queue.producedBy.length > 0) selfQueues.add(node.id);\n }\n for (const [name, system] of Object.entries(this.graph.externalSystems ?? {}))\n levels.set(`system__${safe(name)}`, system.level);\n for (const [name, remote] of Object.entries(this.graph.remoteServices ?? {}))\n levels.set(new RemoteServiceNodeId().of(name), remote.level);\n for (const trigger of this.graph.triggers) {\n if (trigger.kind === 'cron')\n levels.set(`cron__${safe(`${trigger.api}_${trigger.method}`)}`, trigger.level);\n }\n for (const group of new RuntimeExternalTriggers(this.graph.triggers).groups)\n levels.set(group.from, group.triggers[0].level);\n // Undeclared vendor seams are terminal sinks too, independent of their grouping for display.\n for (const use of this.graph.unresolvedUses) {\n const owner = this.graph.apis[use.api]?.owner ?? use.api;\n levels.set(`external__${owner}`, use.level);\n }\n const bands = new Map<number, string[]>();\n for (const node of model.nodes) {\n const level = levels.get(node.id)!;\n if (!bands.has(level)) bands.set(level, []);\n bands.get(level)!.push(node.id);\n }\n return [...bands.entries()]\n .sort((a, b) => b[0] - a[0])\n .map((entry) => {\n const band = new LevelBand(entry[0], entry[1]);\n band.selfQueueNames = entry[1].filter((id) => selfQueues.has(id));\n return band;\n });\n }\n\n /** Context keeps its shape/kind palette; Impact never paints a queue as a source owner. */\n contextModes(model: GraphRenderModel): void {\n for (let index = 0; index < model.nodes.length; index++) {\n const node = model.nodes[index];\n if (node.tags !== null) continue;\n const colors = node.products.map((product) => this.palette.colorOf(product).color);\n const fill =\n colors.length === 0\n ? PRODUCT_NONE_FILL\n : this.palette.sharedByAll(node.products)\n ? PRODUCT_SHARED_FILL\n : colors.join(':');\n // Graphviz cylinders cannot stripe; a gradient preserves recognizable kind geometry.\n const recolored = node.dot.replace(/fillcolor=\"[^\"]*\"/, `fillcolor=\"${fill}\"`);\n const product =\n colors.length === 0\n ? recolored.replace(/style=\"[^\"]*\"/, 'style=\"filled,dashed\"')\n : recolored;\n const modes = new NodeModeDots(\n node.dot,\n node.dot,\n node.dot,\n node.dot,\n node.dot,\n node.dot,\n product,\n );\n model.nodes[index] = new RenderNode(\n node.id,\n node.dot,\n modes,\n null,\n node.products,\n node.queueKeys,\n );\n }\n }\n}\n"]}
1
+ {"version":3,"file":"runtime-viewer-adapter.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-viewer-adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import type { EnhancedGraph } from './graph-sorter';\nimport type { RuntimeGraph, RuntimeService } from './runtime-graph-model';\nimport { GraphRenderModel, RenderNode } from './graph-render-model';\nimport { NodeFacts, NodeModeDots, NodeModeStyler } from './graph-color-modes';\nimport { ProductPalette, PRODUCT_SHARED_FILL, PRODUCT_NONE_FILL } from './graph-products';\nimport { LevelBand } from './graph-level-bands';\nimport { RemoteServiceNodeId } from './remote-service-node-id';\nimport { RuntimeExternalTriggers } from './runtime-external-triggers';\n\n/** Saved project facts enrich presentation without changing runtime derivation or topology. */\nexport class RuntimeViewerAdapter {\n private readonly styler = new NodeModeStyler();\n private readonly palette: ProductPalette;\n\n constructor(\n private readonly graph: RuntimeGraph,\n private readonly projects: EnhancedGraph | null,\n ) {\n // The FULL declared product set (#1244), never just the services drawn here: collision\n // resolution depends on the set, so a subset could recolor a product away from the color the\n // dependency viewer gives it.\n const declared = Object.values(graph.services).flatMap((service) => service.products ?? []);\n if (projects !== null) declared.push(...ProductPalette.fromGraph(projects).names());\n this.palette = new ProductPalette(declared);\n }\n\n service(model: GraphRenderModel, name: string, service: RuntimeService): string {\n const project = this.projects?.[name];\n const role = service.role ?? project?.role ?? 'unknown';\n const facts = new NodeFacts(\n name,\n name.split('/').pop() ?? name,\n service.level,\n role,\n project?.framework ?? [],\n service.products ?? [],\n `Implements (${new Set(service.implements).size})${service.serviceName === undefined ? '' : ` · \"${service.serviceName}\"`}`,\n );\n this.styler.record(model.legend, facts, this.palette);\n return model.styledNode(facts, this.styler.dots(facts, this.palette));\n }\n\n levelBands(model: GraphRenderModel): LevelBand[] {\n const levels = new Map<string, number>();\n const selfQueues = new Set<string>();\n const safe = (name: string): string => name.replace(/[^A-Za-z0-9_]/g, '_');\n for (const [name, service] of Object.entries(this.graph.services))\n levels.set(name, service.level);\n for (const node of model.nodes) {\n if (node.queueKeys.length === 0) continue;\n const key = node.queueKeys[0];\n const queue = key.startsWith('queue:')\n ? this.graph.contractQueues[key.slice(6)]\n : this.graph.queues[key];\n levels.set(node.id, queue.level);\n if (queue.selfQueue && queue.producedBy.length > 0) selfQueues.add(node.id);\n }\n for (const [name, system] of Object.entries(this.graph.externalSystems ?? {}))\n levels.set(`system__${safe(name)}`, system.level);\n for (const [name, remote] of Object.entries(this.graph.remoteServices ?? {}))\n levels.set(new RemoteServiceNodeId().of(name), remote.level);\n for (const trigger of this.graph.triggers) {\n if (trigger.kind === 'cron')\n levels.set(`cron__${safe(`${trigger.api}_${trigger.method}`)}`, trigger.level);\n }\n for (const group of new RuntimeExternalTriggers(this.graph.triggers).groups)\n levels.set(group.from, group.triggers[0].level);\n // Undeclared vendor seams are terminal sinks too, independent of their grouping for display.\n for (const use of this.graph.unresolvedUses) {\n const owner = this.graph.apis[use.api]?.owner ?? use.api;\n levels.set(`external__${owner}`, use.level);\n }\n const bands = new Map<number, string[]>();\n for (const node of model.nodes) {\n const level = levels.get(node.id)!;\n if (!bands.has(level)) bands.set(level, []);\n bands.get(level)!.push(node.id);\n }\n return [...bands.entries()]\n .sort((a, b) => b[0] - a[0])\n .map((entry) => {\n const band = new LevelBand(entry[0], entry[1]);\n band.selfQueueNames = entry[1].filter((id) => selfQueues.has(id));\n return band;\n });\n }\n\n /** Context keeps its shape/kind palette; Impact never paints a queue as a source owner. */\n contextModes(model: GraphRenderModel): void {\n for (let index = 0; index < model.nodes.length; index++) {\n const node = model.nodes[index];\n if (node.tags !== null) continue;\n const colors = node.products.map((product) => this.palette.colorOf(product).color);\n const fill =\n colors.length === 0\n ? PRODUCT_NONE_FILL\n : this.palette.sharedByAll(node.products)\n ? PRODUCT_SHARED_FILL\n : colors.join(':');\n // Graphviz cylinders cannot stripe; a gradient preserves recognizable kind geometry.\n const recolored = node.dot.replace(/fillcolor=\"[^\"]*\"/, `fillcolor=\"${fill}\"`);\n const product =\n colors.length === 0\n ? recolored.replace(/style=\"[^\"]*\"/, 'style=\"filled,dashed\"')\n : recolored;\n const modes = new NodeModeDots(\n node.dot,\n node.dot,\n node.dot,\n node.dot,\n node.dot,\n node.dot,\n product,\n );\n model.nodes[index] = new RenderNode(\n node.id,\n node.dot,\n modes,\n null,\n node.products,\n node.queueKeys,\n );\n }\n }\n}\n"]}