@webpieces/nx-webpieces-rules 0.4.897 → 0.4.899
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 +5 -1
- package/package.json +7 -7
- package/src/configs/tag-truth-configs.d.ts +31 -5
- package/src/configs/tag-truth-configs.js +37 -6
- package/src/configs/tag-truth-configs.js.map +1 -1
- package/src/executors/generate/executor.js +3 -3
- package/src/executors/generate/executor.js.map +1 -1
- package/src/executors/visualize/executor.js +3 -1
- package/src/executors/visualize/executor.js.map +1 -1
- package/src/index.d.ts +3 -2
- package/src/index.js +5 -1
- package/src/index.js.map +1 -1
- package/src/lib/graph-color-modes.d.ts +8 -0
- package/src/lib/graph-color-modes.js +7 -0
- package/src/lib/graph-color-modes.js.map +1 -1
- package/src/lib/graph-filter.client.d.ts +5 -2
- package/src/lib/graph-filter.client.js +9 -4
- package/src/lib/graph-filter.client.js.map +1 -1
- package/src/lib/graph-legend.d.ts +8 -0
- package/src/lib/graph-legend.js +24 -2
- package/src/lib/graph-legend.js.map +1 -1
- package/src/lib/graph-products.d.ts +14 -0
- package/src/lib/graph-products.js +22 -1
- package/src/lib/graph-products.js.map +1 -1
- package/src/lib/graph-render-model.d.ts +19 -2
- package/src/lib/graph-render-model.js +19 -4
- package/src/lib/graph-render-model.js.map +1 -1
- package/src/lib/graph-visualizer.client.d.ts +2 -0
- package/src/lib/graph-visualizer.client.js +6 -0
- package/src/lib/graph-visualizer.client.js.map +1 -1
- package/src/lib/graph-visualizer.d.ts +11 -1
- package/src/lib/graph-visualizer.js +26 -7
- package/src/lib/graph-visualizer.js.map +1 -1
- package/src/lib/product-dependencies.d.ts +52 -0
- package/src/lib/product-dependencies.js +128 -0
- package/src/lib/product-dependencies.js.map +1 -0
- package/src/lib/tag-truth.d.ts +12 -3
- package/src/lib/tag-truth.js +27 -4
- package/src/lib/tag-truth.js.map +1 -1
- package/src/rule-help.js +1 -1
- package/src/rule-help.js.map +1 -1
- package/src/rule-settings.js +1 -0
- package/src/rule-settings.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-products.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/graph-products.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Products on the architecture graphs (#1179).\n *\n * A monorepo can hold several PRODUCTS, each with its own clients and servers. A product is declared\n * on its entry points with the nx tag `product:<name>` (product-resolver.ts); everything else a\n * product consists of is DERIVED here, never declared:\n *\n * - ProductMembership — the dependency graph. A project's OWN `product:` tags are FINAL (#1201): a\n * project that declares any keeps exactly its declared set. An UNTAGGED project belongs to every\n * product whose tagged project reaches it by a downward walk over `dependsOn` — and that walk stops\n * at a tagged project, whose own dependencies are reached by its own seed walk. That closure is\n * everything that can change the product's behaviour, so it is what a reviewer of that product\n * reviews. It must start from EVERY entry point, clients and servers both: a client reaches its\n * server only over HTTP, never through an nx edge, so a server is in its product only because it is\n * tagged. Why final: a project is one product's, never two by accident — the example apps depend on\n * the platform libraries, and a platform library tagged `product:platform` must not be painted\n * `example` because an example reaches it. A published library whose entry points live in OTHER\n * repos carries its own tag for exactly that reason: no in-repo walk can ever reach it correctly.\n * - RuntimeProductMembership — the runtime graph, under the same rule. A service that already carries\n * products (declared, or derived on the dependency graph above) keeps exactly them; a service with\n * none belongs to every product whose service reaches it over RUNTIME `dependsOn`, including through\n * a queue to its consumers, and that walk stops at a service with products of its own. A call from\n * one product into another product's service still shows — as the runtime EDGE between them.\n * - ProductPalette — the Product color mode's colors: a fixed palette of eight assigned in sorted\n * product-name order, a neutral fill for a box shared by EVERY product, and a dashed white box for\n * one in no product.\n *\n * Membership is stable per checkout (it depends on tags and edges, never on a diff), so it is written\n * into the committed dependencies.json / runtime-dependencies.json rather than into a sidecar.\n */\n\nimport type { EnhancedGraph } from './graph-sorter';\nimport type { RuntimeGraph } from './runtime-graph-model';\n\n// The same two text colors graph-color-modes.ts writes on every fill. Spelled here rather than\n// imported because graph-color-modes.ts imports THIS file (for the palette), and a file-import cycle\n// is refused by `no-file-import-cycles`.\nconst DARK_TEXT = '#1a1c22';\nconst LIGHT_TEXT = '#ffffff';\n\n/** One product's color, and the text color that reads on it. Data-only. */\nexport class ProductColor {\n constructor(\n public readonly product: string,\n public readonly color: string,\n public readonly fontColor: string,\n /** False for a product past the palette's eight, which is painted with the neutral fill. */\n public readonly inPalette: boolean,\n ) {}\n}\n\n/** The eight product colors, in assignment order. Distinct from every runtime and role color. */\nconst PRODUCT_COLORS: readonly (readonly [string, string])[] = [\n ['#3f6fb5', LIGHT_TEXT],\n ['#f28e2b', DARK_TEXT],\n ['#c0392b', LIGHT_TEXT],\n ['#5cb8b2', DARK_TEXT],\n ['#3d8b3d', LIGHT_TEXT],\n ['#edc948', DARK_TEXT],\n ['#8e5ea2', LIGHT_TEXT],\n ['#ff9da7', DARK_TEXT],\n];\n\n/** How many products get a color of their own; any further product uses the neutral fill. */\nexport const PRODUCT_PALETTE_SIZE = PRODUCT_COLORS.length;\n\n/** A box shared by EVERY product, and every product past the palette's eight. */\nexport const PRODUCT_SHARED_FILL = '#c9ced8';\n/** A box in no product: white, with a dashed border. */\nexport const PRODUCT_NONE_FILL = '#ffffff';\nexport const PRODUCT_NONE_BORDER = '#8a90a0';\n\nexport class ProductPalette {\n /** Every declared product, sorted, each with its color. */\n readonly colors: ProductColor[];\n\n constructor(products: readonly string[]) {\n const sorted = [...new Set(products)].sort();\n this.colors = sorted.map((product: string, index: number): ProductColor => {\n const entry = PRODUCT_COLORS[index];\n if (entry === undefined) return new ProductColor(product, PRODUCT_SHARED_FILL, DARK_TEXT, false);\n return new ProductColor(product, entry[0], entry[1], true);\n });\n }\n\n /** Every product carried by a project of the graph, as one palette. */\n // webpieces-disable no-function-outside-class -- static factory of this class\n static fromGraph(graph: EnhancedGraph): ProductPalette {\n const all: string[] = [];\n for (const entry of Object.values(graph)) all.push(...(entry.products ?? []));\n return new ProductPalette(all);\n }\n\n names(): string[] {\n return this.colors.map((color: ProductColor): string => color.product);\n }\n\n colorOf(product: string): ProductColor {\n return (\n this.colors.find((color: ProductColor): boolean => color.product === product) ??\n new ProductColor(product, PRODUCT_SHARED_FILL, DARK_TEXT, false)\n );\n }\n\n /** True for a box carrying every product of a workspace that declares two or more. */\n sharedByAll(products: readonly string[]): boolean {\n return this.colors.length > 1 && this.colors.every((color: ProductColor): boolean => products.includes(color.product));\n }\n\n /** True when some product is past the palette's eight, so the legend must say it is neutral. */\n overflows(): boolean {\n return this.colors.some((color: ProductColor): boolean => !color.inPalette);\n }\n}\n\n/**\n * The architecture graph's product membership: declared seeds walked DOWN over `dependsOn`, where a\n * project's own declared products are final.\n */\nexport class ProductMembership {\n /**\n * @param seeds project → the products it DECLARES (its `product:` tags)\n * @returns project → its sorted products: exactly its declared set when it declares any; otherwise\n * every product whose tagged project reaches it without passing through another tagged\n * project. A project in no product is absent, so with no tag anywhere the map is empty.\n */\n compute(seeds: ReadonlyMap<string, readonly string[]>, graph: EnhancedGraph): Map<string, string[]> {\n const declared = new Map<string, readonly string[]>();\n seeds.forEach((products: readonly string[], seed: string): void => {\n if (products.length > 0 && graph[seed] !== undefined) declared.set(seed, products);\n });\n const members = new Map<string, Set<string>>();\n declared.forEach((products: readonly string[], seed: string): void => {\n members.set(seed, new Set(products));\n });\n declared.forEach((products: readonly string[], seed: string): void => {\n for (const project of this.closure(seed, graph, declared)) {\n const set = members.get(project) ?? new Set<string>();\n for (const product of products) set.add(product);\n members.set(project, set);\n }\n });\n const result = new Map<string, string[]>();\n members.forEach((set: Set<string>, project: string): void => {\n result.set(project, [...set].sort());\n });\n return result;\n }\n\n /**\n * Every UNTAGGED project `seed` reaches through `dependsOn`. A tagged project is neither collected\n * nor walked through: its products are final, and its own seed walk covers its dependencies.\n */\n private closure(seed: string, graph: EnhancedGraph, declared: ReadonlyMap<string, readonly string[]>): Set<string> {\n const seen = new Set<string>([seed]);\n const reached = new Set<string>();\n const stack = [seed];\n while (stack.length > 0) {\n const project = stack.pop() as string;\n for (const dep of graph[project]?.dependsOn ?? []) {\n if (seen.has(dep)) continue;\n seen.add(dep);\n if (declared.has(dep)) continue;\n reached.add(dep);\n stack.push(dep);\n }\n }\n return reached;\n }\n}\n\n/**\n * The runtime graph's product membership: services that carry products walked over RUNTIME\n * `dependsOn`, where a service's own products are final.\n */\nexport class RuntimeProductMembership {\n /**\n * Stamp `products` onto every service of `graph` that some product reaches. Seeds are the\n * services whose dependencies.json entry carries `products`, and each keeps exactly those; a\n * service with none gets every product whose seed reaches it without passing through another\n * seed. A `queue:<Api.method>` dependency is followed to that queue's consumers. A service in no\n * product gets no field.\n */\n apply(graph: RuntimeGraph, projects: EnhancedGraph): void {\n const seeds = new Map<string, readonly string[]>();\n for (const name of Object.keys(graph.services)) {\n const own = projects[name]?.products ?? [];\n if (own.length > 0) seeds.set(name, own);\n }\n const members = new Map<string, Set<string>>();\n seeds.forEach((own: readonly string[], name: string): void => {\n members.set(name, new Set(own));\n });\n seeds.forEach((own: readonly string[], name: string): void => {\n for (const reached of this.closure(name, graph, seeds)) {\n const set = members.get(reached) ?? new Set<string>();\n for (const product of own) set.add(product);\n members.set(reached, set);\n }\n });\n members.forEach((set: Set<string>, name: string): void => {\n const service = graph.services[name];\n if (service !== undefined) service.products = [...set].sort();\n });\n }\n\n /** Every service WITHOUT products of its own that `seed` reaches; a seed is neither collected nor walked through. */\n private closure(seed: string, graph: RuntimeGraph, seeds: ReadonlyMap<string, readonly string[]>): Set<string> {\n const seen = new Set<string>([seed]);\n const reached = new Set<string>();\n const stack = [seed];\n while (stack.length > 0) {\n const name = stack.pop() as string;\n for (const next of this.callees(name, graph)) {\n if (seen.has(next) || graph.services[next] === undefined) continue;\n seen.add(next);\n if (seeds.has(next)) continue;\n reached.add(next);\n stack.push(next);\n }\n }\n return reached;\n }\n\n /** The services one service calls: direct ones, and the consumers behind every queue it feeds. */\n private callees(name: string, graph: RuntimeGraph): string[] {\n const callees: string[] = [];\n for (const dep of graph.services[name]?.dependsOn ?? []) {\n if (!dep.startsWith('queue:')) {\n callees.push(dep);\n continue;\n }\n callees.push(...(graph.queues[dep.slice('queue:'.length)]?.consumedBy ?? []));\n }\n return callees;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"graph-products.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/graph-products.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Products on the architecture graphs (#1179).\n *\n * A monorepo can hold several PRODUCTS, each with its own clients and servers. A product is declared\n * on its entry points with the nx tag `product:<name>` (product-resolver.ts); everything else a\n * product consists of is DERIVED here, never declared:\n *\n * - ProductMembership — the dependency graph. A project's OWN `product:` tags are FINAL (#1201): a\n * project that declares any keeps exactly its declared set. An UNTAGGED project belongs to every\n * product whose tagged project reaches it by a downward walk over `dependsOn` — and that walk stops\n * at a tagged project, whose own dependencies are reached by its own seed walk. That closure is\n * everything that can change the product's behaviour, so it is what a reviewer of that product\n * reviews. It must start from EVERY entry point, clients and servers both: a client reaches its\n * server only over HTTP, never through an nx edge, so a server is in its product only because it is\n * tagged. Why final: a project is one product's, never two by accident — the example apps depend on\n * the platform libraries, and a platform library tagged `product:platform` must not be painted\n * `example` because an example reaches it. A published library whose entry points live in OTHER\n * repos carries its own tag for exactly that reason: no in-repo walk can ever reach it correctly.\n * - RuntimeProductMembership — the runtime graph, under the same rule. A service that already carries\n * products (declared, or derived on the dependency graph above) keeps exactly them; a service with\n * none belongs to every product whose service reaches it over RUNTIME `dependsOn`, including through\n * a queue to its consumers, and that walk stops at a service with products of its own. A call from\n * one product into another product's service still shows — as the runtime EDGE between them.\n * - ProductPalette — the Product color mode's colors: a fixed palette of eight assigned in sorted\n * product-name order, a neutral fill for a box shared by EVERY product, and a dashed white box for\n * one in no product.\n * - ProductBoundary — which dependency edges cross from one product into another (#1204), drawn\n * dashed in the target product's color in the Product color mode.\n *\n * Membership is stable per checkout (it depends on tags and edges, never on a diff), so it is written\n * into the committed dependencies.json / runtime-dependencies.json rather than into a sidecar.\n */\n\nimport type { EnhancedGraph } from './graph-sorter';\nimport type { RuntimeGraph } from './runtime-graph-model';\n\n// The same two text colors graph-color-modes.ts writes on every fill. Spelled here rather than\n// imported because graph-color-modes.ts imports THIS file (for the palette), and a file-import cycle\n// is refused by `no-file-import-cycles`.\nconst DARK_TEXT = '#1a1c22';\nconst LIGHT_TEXT = '#ffffff';\n\n/** One product's color, and the text color that reads on it. Data-only. */\nexport class ProductColor {\n constructor(\n public readonly product: string,\n public readonly color: string,\n public readonly fontColor: string,\n /** False for a product past the palette's eight, which is painted with the neutral fill. */\n public readonly inPalette: boolean,\n ) {}\n}\n\n/** The eight product colors, in assignment order. Distinct from every runtime and role color. */\nconst PRODUCT_COLORS: readonly (readonly [string, string])[] = [\n ['#3f6fb5', LIGHT_TEXT],\n ['#f28e2b', DARK_TEXT],\n ['#c0392b', LIGHT_TEXT],\n ['#5cb8b2', DARK_TEXT],\n ['#3d8b3d', LIGHT_TEXT],\n ['#edc948', DARK_TEXT],\n ['#8e5ea2', LIGHT_TEXT],\n ['#ff9da7', DARK_TEXT],\n];\n\n/** How many products get a color of their own; any further product uses the neutral fill. */\nexport const PRODUCT_PALETTE_SIZE = PRODUCT_COLORS.length;\n\n/** A box shared by EVERY product, and every product past the palette's eight. */\nexport const PRODUCT_SHARED_FILL = '#c9ced8';\n/** A box in no product: white, with a dashed border. */\nexport const PRODUCT_NONE_FILL = '#ffffff';\nexport const PRODUCT_NONE_BORDER = '#8a90a0';\n\nexport class ProductPalette {\n /** Every declared product, sorted, each with its color. */\n readonly colors: ProductColor[];\n\n constructor(products: readonly string[]) {\n const sorted = [...new Set(products)].sort();\n this.colors = sorted.map((product: string, index: number): ProductColor => {\n const entry = PRODUCT_COLORS[index];\n if (entry === undefined) return new ProductColor(product, PRODUCT_SHARED_FILL, DARK_TEXT, false);\n return new ProductColor(product, entry[0], entry[1], true);\n });\n }\n\n /** Every product carried by a project of the graph, as one palette. */\n // webpieces-disable no-function-outside-class -- static factory of this class\n static fromGraph(graph: EnhancedGraph): ProductPalette {\n const all: string[] = [];\n for (const entry of Object.values(graph)) all.push(...(entry.products ?? []));\n return new ProductPalette(all);\n }\n\n names(): string[] {\n return this.colors.map((color: ProductColor): string => color.product);\n }\n\n colorOf(product: string): ProductColor {\n return (\n this.colors.find((color: ProductColor): boolean => color.product === product) ??\n new ProductColor(product, PRODUCT_SHARED_FILL, DARK_TEXT, false)\n );\n }\n\n /** True for a box carrying every product of a workspace that declares two or more. */\n sharedByAll(products: readonly string[]): boolean {\n return this.colors.length > 1 && this.colors.every((color: ProductColor): boolean => products.includes(color.product));\n }\n\n /** True when some product is past the palette's eight, so the legend must say it is neutral. */\n overflows(): boolean {\n return this.colors.some((color: ProductColor): boolean => !color.inPalette);\n }\n}\n\n/**\n * Where a dependency edge crosses a product boundary (#1204), for the Product color mode: an edge\n * A -> B crosses when B does not carry every product of A, and it is drawn dashed in the color of the\n * product it crosses INTO, so the boundaries read at a glance while same-product edges stay quiet.\n * Whether a crossing is ALLOWED is the product dependency matrix's call (product-dependencies.ts):\n * with `product-tags` ON, generation already refused every crossing the matrix does not allow, so\n * every crossing drawn is an allowed one.\n */\nexport class ProductBoundary {\n /** The product the edge crosses into, or null when the target carries every product of the source. */\n crossedInto(from: readonly string[], to: readonly string[]): string | null {\n if (from.length === 0 || to.length === 0) return null;\n if (from.every((product: string): boolean => to.includes(product))) return null;\n return to.find((product: string): boolean => !from.includes(product)) ?? to[0];\n }\n}\n\n/**\n * The architecture graph's product membership: declared seeds walked DOWN over `dependsOn`, where a\n * project's own declared products are final.\n */\nexport class ProductMembership {\n /**\n * @param seeds project → the products it DECLARES (its `product:` tags)\n * @returns project → its sorted products: exactly its declared set when it declares any; otherwise\n * every product whose tagged project reaches it without passing through another tagged\n * project. A project in no product is absent, so with no tag anywhere the map is empty.\n */\n compute(seeds: ReadonlyMap<string, readonly string[]>, graph: EnhancedGraph): Map<string, string[]> {\n const declared = new Map<string, readonly string[]>();\n seeds.forEach((products: readonly string[], seed: string): void => {\n if (products.length > 0 && graph[seed] !== undefined) declared.set(seed, products);\n });\n const members = new Map<string, Set<string>>();\n declared.forEach((products: readonly string[], seed: string): void => {\n members.set(seed, new Set(products));\n });\n declared.forEach((products: readonly string[], seed: string): void => {\n for (const project of this.closure(seed, graph, declared)) {\n const set = members.get(project) ?? new Set<string>();\n for (const product of products) set.add(product);\n members.set(project, set);\n }\n });\n const result = new Map<string, string[]>();\n members.forEach((set: Set<string>, project: string): void => {\n result.set(project, [...set].sort());\n });\n return result;\n }\n\n /**\n * Every UNTAGGED project `seed` reaches through `dependsOn`. A tagged project is neither collected\n * nor walked through: its products are final, and its own seed walk covers its dependencies.\n */\n private closure(seed: string, graph: EnhancedGraph, declared: ReadonlyMap<string, readonly string[]>): Set<string> {\n const seen = new Set<string>([seed]);\n const reached = new Set<string>();\n const stack = [seed];\n while (stack.length > 0) {\n const project = stack.pop() as string;\n for (const dep of graph[project]?.dependsOn ?? []) {\n if (seen.has(dep)) continue;\n seen.add(dep);\n if (declared.has(dep)) continue;\n reached.add(dep);\n stack.push(dep);\n }\n }\n return reached;\n }\n}\n\n/**\n * The runtime graph's product membership: services that carry products walked over RUNTIME\n * `dependsOn`, where a service's own products are final.\n */\nexport class RuntimeProductMembership {\n /**\n * Stamp `products` onto every service of `graph` that some product reaches. Seeds are the\n * services whose dependencies.json entry carries `products`, and each keeps exactly those; a\n * service with none gets every product whose seed reaches it without passing through another\n * seed. A `queue:<Api.method>` dependency is followed to that queue's consumers. A service in no\n * product gets no field.\n */\n apply(graph: RuntimeGraph, projects: EnhancedGraph): void {\n const seeds = new Map<string, readonly string[]>();\n for (const name of Object.keys(graph.services)) {\n const own = projects[name]?.products ?? [];\n if (own.length > 0) seeds.set(name, own);\n }\n const members = new Map<string, Set<string>>();\n seeds.forEach((own: readonly string[], name: string): void => {\n members.set(name, new Set(own));\n });\n seeds.forEach((own: readonly string[], name: string): void => {\n for (const reached of this.closure(name, graph, seeds)) {\n const set = members.get(reached) ?? new Set<string>();\n for (const product of own) set.add(product);\n members.set(reached, set);\n }\n });\n members.forEach((set: Set<string>, name: string): void => {\n const service = graph.services[name];\n if (service !== undefined) service.products = [...set].sort();\n });\n }\n\n /** Every service WITHOUT products of its own that `seed` reaches; a seed is neither collected nor walked through. */\n private closure(seed: string, graph: RuntimeGraph, seeds: ReadonlyMap<string, readonly string[]>): Set<string> {\n const seen = new Set<string>([seed]);\n const reached = new Set<string>();\n const stack = [seed];\n while (stack.length > 0) {\n const name = stack.pop() as string;\n for (const next of this.callees(name, graph)) {\n if (seen.has(next) || graph.services[next] === undefined) continue;\n seen.add(next);\n if (seeds.has(next)) continue;\n reached.add(next);\n stack.push(next);\n }\n }\n return reached;\n }\n\n /** The services one service calls: direct ones, and the consumers behind every queue it feeds. */\n private callees(name: string, graph: RuntimeGraph): string[] {\n const callees: string[] = [];\n for (const dep of graph.services[name]?.dependsOn ?? []) {\n if (!dep.startsWith('queue:')) {\n callees.push(dep);\n continue;\n }\n callees.push(...(graph.queues[dep.slice('queue:'.length)]?.consumedBy ?? []));\n }\n return callees;\n }\n}\n"]}
|
|
@@ -31,7 +31,19 @@ export declare class RenderEdge {
|
|
|
31
31
|
readonly to: string;
|
|
32
32
|
readonly dot: string;
|
|
33
33
|
readonly id: string;
|
|
34
|
-
|
|
34
|
+
/**
|
|
35
|
+
* The statement the architecture page's Product color mode draws instead of `dot` (#1204): a
|
|
36
|
+
* dependency crossing into another product, dashed in that product's color. Null for every
|
|
37
|
+
* other edge, which draws `dot` in every mode.
|
|
38
|
+
*/
|
|
39
|
+
readonly productDot: string | null;
|
|
40
|
+
constructor(from: string, to: string, dot: string, id: string,
|
|
41
|
+
/**
|
|
42
|
+
* The statement the architecture page's Product color mode draws instead of `dot` (#1204): a
|
|
43
|
+
* dependency crossing into another product, dashed in that product's color. Null for every
|
|
44
|
+
* other edge, which draws `dot` in every mode.
|
|
45
|
+
*/
|
|
46
|
+
productDot?: string | null);
|
|
35
47
|
}
|
|
36
48
|
/** The immutable drawable snapshot carried by a generated page. */
|
|
37
49
|
export declare class GraphRenderModel {
|
|
@@ -55,7 +67,12 @@ export declare class GraphRenderModel {
|
|
|
55
67
|
/** A box drawn differently per color mode; `fullDot` carries its RUNTIME statement. */
|
|
56
68
|
styledNode(facts: NodeFacts, modes: NodeModeDots): string;
|
|
57
69
|
completeEndpoints(): void;
|
|
58
|
-
|
|
70
|
+
/**
|
|
71
|
+
* One edge. `productAttrs`, when not empty, is the attribute list the Product color mode adds to
|
|
72
|
+
* the statement (a later list overrides an earlier one in DOT), e.g. a cross-product dependency's
|
|
73
|
+
* dash and color; `fullDot` always carries the plain statement.
|
|
74
|
+
*/
|
|
75
|
+
edge(from: string, to: string, dot: string, productAttrs?: string): string;
|
|
59
76
|
}
|
|
60
77
|
/** Shared filter chrome and script-safe JSON for pages opened directly from disk. */
|
|
61
78
|
export declare class GraphFilterAssets {
|
|
@@ -47,11 +47,19 @@ class RenderEdge {
|
|
|
47
47
|
to;
|
|
48
48
|
dot;
|
|
49
49
|
id;
|
|
50
|
-
|
|
50
|
+
productDot;
|
|
51
|
+
constructor(from, to, dot, id,
|
|
52
|
+
/**
|
|
53
|
+
* The statement the architecture page's Product color mode draws instead of `dot` (#1204): a
|
|
54
|
+
* dependency crossing into another product, dashed in that product's color. Null for every
|
|
55
|
+
* other edge, which draws `dot` in every mode.
|
|
56
|
+
*/
|
|
57
|
+
productDot = null) {
|
|
51
58
|
this.from = from;
|
|
52
59
|
this.to = to;
|
|
53
60
|
this.dot = dot;
|
|
54
61
|
this.id = id;
|
|
62
|
+
this.productDot = productDot;
|
|
55
63
|
}
|
|
56
64
|
}
|
|
57
65
|
exports.RenderEdge = RenderEdge;
|
|
@@ -113,10 +121,17 @@ class GraphRenderModel {
|
|
|
113
121
|
}
|
|
114
122
|
}
|
|
115
123
|
}
|
|
116
|
-
|
|
124
|
+
/**
|
|
125
|
+
* One edge. `productAttrs`, when not empty, is the attribute list the Product color mode adds to
|
|
126
|
+
* the statement (a later list overrides an earlier one in DOT), e.g. a cross-product dependency's
|
|
127
|
+
* dash and color; `fullDot` always carries the plain statement.
|
|
128
|
+
*/
|
|
129
|
+
edge(from, to, dot, productAttrs = '') {
|
|
117
130
|
const id = `wp-real-edge-${this.edges.length}`;
|
|
118
|
-
const
|
|
119
|
-
|
|
131
|
+
const base = `${dot.slice(0, -2)} [id="${id}"]`;
|
|
132
|
+
const statement = `${base};\n`;
|
|
133
|
+
const productDot = productAttrs === '' ? null : `${base} [${productAttrs}];\n`;
|
|
134
|
+
this.edges.push(new RenderEdge(from, to, statement, id, productDot));
|
|
120
135
|
return statement;
|
|
121
136
|
}
|
|
122
137
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-render-model.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/graph-render-model.ts"],"names":[],"mappings":"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","sourcesContent":["import { dotValue } from './dot-syntax';\nimport { LevelBand } from './graph-level-bands';\nimport { LegendFacts, NodeFacts, NodeModeDots } from './graph-color-modes';\n\n/**\n * Renderer-owned records, captured while emitting DOT, never recovered by parsing labels.\n *\n * `dot` is the statement `fullDot` carries. `modes` carries per-mode statements in both viewers; `tags` carries declared service/project\n * metadata. Runtime auxiliary entities leave tags null so facets count services and retain context\n * separately.\n *\n * `products` is set on BOTH graphs (#1179): the products a box belongs to, which each page's product\n * filter matches on. Empty for a box in no product.\n */\nexport class RenderNode {\n constructor(\n public readonly id: string,\n public readonly dot: string,\n public readonly modes: NodeModeDots | null,\n public readonly tags: NodeTags | null,\n public readonly products: string[],\n public readonly queueKeys: string[] = [],\n ) {}\n}\n\n/** What the architecture page's Filter matches a box on: its level, role and framework tags. */\nexport class NodeTags {\n constructor(\n public readonly level: number,\n public readonly role: string,\n public readonly frameworks: string[],\n ) {}\n}\n\nexport class RenderEdge {\n constructor(\n public readonly from: string,\n public readonly to: string,\n public readonly dot: string,\n public readonly id: string,\n ) {}\n}\n\n/** The immutable drawable snapshot carried by a generated page. */\nexport class GraphRenderModel {\n viewer: 'architecture' | 'runtime' = 'architecture';\n readonly nodes: RenderNode[] = [];\n readonly edges: RenderEdge[] = [];\n bands: LevelBand[] = [];\n fullDot = '';\n header = '';\n footer = '';\n /** The colors and roles in use, so the page's legend lists exactly those (architecture graph). */\n legend = new LegendFacts();\n\n node(id: string, dot: string, products: string[] = [], queueKeys: string[] = []): string {\n this.nodes.push(new RenderNode(id, dot, null, null, products, queueKeys));\n return dot;\n }\n\n /**\n * Every product a declared box (a queue, a cron trigger, an external system) inherits from the\n * services its edges touch (#1179): it belongs to whichever product's services it is attached to.\n * Called by the runtime graph once every edge is emitted; RenderNode is immutable, so a node gains\n * its products by being replaced.\n */\n attachProducts(isService: (id: string) => boolean): void {\n const byId = new Map<string, RenderNode>();\n for (const node of this.nodes) byId.set(node.id, node);\n for (let index = 0; index < this.nodes.length; index++) {\n const node = this.nodes[index];\n if (isService(node.id)) continue;\n const inherited = new Set<string>();\n for (const edge of this.edges) {\n const other =\n edge.from === node.id ? edge.to : edge.to === node.id ? edge.from : null;\n if (other === null || !isService(other)) continue;\n for (const product of byId.get(other)?.products ?? []) inherited.add(product);\n }\n if (inherited.size === 0) continue;\n this.nodes[index] = new RenderNode(\n node.id,\n node.dot,\n node.modes,\n node.tags,\n [...inherited].sort(),\n node.queueKeys,\n );\n }\n }\n\n /** A box drawn differently per color mode; `fullDot` carries its RUNTIME statement. */\n styledNode(facts: NodeFacts, modes: NodeModeDots): string {\n this.nodes.push(\n new RenderNode(\n facts.nodeId,\n modes.runtime,\n modes,\n new NodeTags(facts.level, facts.role, facts.frameworks),\n facts.products,\n ),\n );\n return modes.runtime;\n }\n\n completeEndpoints(): void {\n const ids = new Set(this.nodes.map((node) => node.id));\n for (const edge of this.edges) {\n for (const id of [edge.from, edge.to]) {\n if (ids.has(id)) continue;\n ids.add(id);\n this.node(id, ` \"${dotValue(id)}\";\\n`);\n }\n }\n }\n\n edge(from: string, to: string, dot: string): string {\n const id = `wp-real-edge-${this.edges.length}`;\n const statement = `${dot.slice(0, -2)} [id=\"${id}\"];\\n`;\n this.edges.push(new RenderEdge(from, to, statement, id));\n return statement;\n }\n}\n\n/** Shared filter chrome and script-safe JSON for pages opened directly from disk. */\nexport class GraphFilterAssets {\n json<T>(value: T): string {\n return JSON.stringify(value).replace(/</g, '\\\\u003c');\n }\n\n html(): string {\n return (\n '<p id=\"wp-filter-status\" hidden>Filtering: <strong id=\"wp-filter-anchor\"></strong> ' +\n '<button id=\"wp-filter-off\" type=\"button\">Turn off Filter</button></p>' +\n '<p id=\"wp-graph-error\" role=\"alert\" hidden></p>'\n );\n }\n\n styles(): string {\n return (\n '#wp-filter-status { text-align:center; } #wp-graph-error { color:#b71c1c; } ' +\n '#graph .wp-filter-anchor polygon, #graph .wp-filter-anchor path, ' +\n '#graph .wp-filter-anchor ellipse { stroke:#8b3cf0; stroke-width:3; }'\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"graph-render-model.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/graph-render-model.ts"],"names":[],"mappings":"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","sourcesContent":["import { dotValue } from './dot-syntax';\nimport { LevelBand } from './graph-level-bands';\nimport { LegendFacts, NodeFacts, NodeModeDots } from './graph-color-modes';\n\n/**\n * Renderer-owned records, captured while emitting DOT, never recovered by parsing labels.\n *\n * `dot` is the statement `fullDot` carries. `modes` carries per-mode statements in both viewers; `tags` carries declared service/project\n * metadata. Runtime auxiliary entities leave tags null so facets count services and retain context\n * separately.\n *\n * `products` is set on BOTH graphs (#1179): the products a box belongs to, which each page's product\n * filter matches on. Empty for a box in no product.\n */\nexport class RenderNode {\n constructor(\n public readonly id: string,\n public readonly dot: string,\n public readonly modes: NodeModeDots | null,\n public readonly tags: NodeTags | null,\n public readonly products: string[],\n public readonly queueKeys: string[] = [],\n ) {}\n}\n\n/** What the architecture page's Filter matches a box on: its level, role and framework tags. */\nexport class NodeTags {\n constructor(\n public readonly level: number,\n public readonly role: string,\n public readonly frameworks: string[],\n ) {}\n}\n\nexport class RenderEdge {\n constructor(\n public readonly from: string,\n public readonly to: string,\n public readonly dot: string,\n public readonly id: string,\n /**\n * The statement the architecture page's Product color mode draws instead of `dot` (#1204): a\n * dependency crossing into another product, dashed in that product's color. Null for every\n * other edge, which draws `dot` in every mode.\n */\n public readonly productDot: string | null = null,\n ) {}\n}\n\n/** The immutable drawable snapshot carried by a generated page. */\nexport class GraphRenderModel {\n viewer: 'architecture' | 'runtime' = 'architecture';\n readonly nodes: RenderNode[] = [];\n readonly edges: RenderEdge[] = [];\n bands: LevelBand[] = [];\n fullDot = '';\n header = '';\n footer = '';\n /** The colors and roles in use, so the page's legend lists exactly those (architecture graph). */\n legend = new LegendFacts();\n\n node(id: string, dot: string, products: string[] = [], queueKeys: string[] = []): string {\n this.nodes.push(new RenderNode(id, dot, null, null, products, queueKeys));\n return dot;\n }\n\n /**\n * Every product a declared box (a queue, a cron trigger, an external system) inherits from the\n * services its edges touch (#1179): it belongs to whichever product's services it is attached to.\n * Called by the runtime graph once every edge is emitted; RenderNode is immutable, so a node gains\n * its products by being replaced.\n */\n attachProducts(isService: (id: string) => boolean): void {\n const byId = new Map<string, RenderNode>();\n for (const node of this.nodes) byId.set(node.id, node);\n for (let index = 0; index < this.nodes.length; index++) {\n const node = this.nodes[index];\n if (isService(node.id)) continue;\n const inherited = new Set<string>();\n for (const edge of this.edges) {\n const other =\n edge.from === node.id ? edge.to : edge.to === node.id ? edge.from : null;\n if (other === null || !isService(other)) continue;\n for (const product of byId.get(other)?.products ?? []) inherited.add(product);\n }\n if (inherited.size === 0) continue;\n this.nodes[index] = new RenderNode(\n node.id,\n node.dot,\n node.modes,\n node.tags,\n [...inherited].sort(),\n node.queueKeys,\n );\n }\n }\n\n /** A box drawn differently per color mode; `fullDot` carries its RUNTIME statement. */\n styledNode(facts: NodeFacts, modes: NodeModeDots): string {\n this.nodes.push(\n new RenderNode(\n facts.nodeId,\n modes.runtime,\n modes,\n new NodeTags(facts.level, facts.role, facts.frameworks),\n facts.products,\n ),\n );\n return modes.runtime;\n }\n\n completeEndpoints(): void {\n const ids = new Set(this.nodes.map((node) => node.id));\n for (const edge of this.edges) {\n for (const id of [edge.from, edge.to]) {\n if (ids.has(id)) continue;\n ids.add(id);\n this.node(id, ` \"${dotValue(id)}\";\\n`);\n }\n }\n }\n\n /**\n * One edge. `productAttrs`, when not empty, is the attribute list the Product color mode adds to\n * the statement (a later list overrides an earlier one in DOT), e.g. a cross-product dependency's\n * dash and color; `fullDot` always carries the plain statement.\n */\n edge(from: string, to: string, dot: string, productAttrs: string = ''): string {\n const id = `wp-real-edge-${this.edges.length}`;\n const base = `${dot.slice(0, -2)} [id=\"${id}\"]`;\n const statement = `${base};\\n`;\n const productDot = productAttrs === '' ? null : `${base} [${productAttrs}];\\n`;\n this.edges.push(new RenderEdge(from, to, statement, id, productDot));\n return statement;\n }\n}\n\n/** Shared filter chrome and script-safe JSON for pages opened directly from disk. */\nexport class GraphFilterAssets {\n json<T>(value: T): string {\n return JSON.stringify(value).replace(/</g, '\\\\u003c');\n }\n\n html(): string {\n return (\n '<p id=\"wp-filter-status\" hidden>Filtering: <strong id=\"wp-filter-anchor\"></strong> ' +\n '<button id=\"wp-filter-off\" type=\"button\">Turn off Filter</button></p>' +\n '<p id=\"wp-graph-error\" role=\"alert\" hidden></p>'\n );\n }\n\n styles(): string {\n return (\n '#wp-filter-status { text-align:center; } #wp-graph-error { color:#b71c1c; } ' +\n '#graph .wp-filter-anchor polygon, #graph .wp-filter-anchor path, ' +\n '#graph .wp-filter-anchor ellipse { stroke:#8b3cf0; stroke-width:3; }'\n );\n }\n}\n"]}
|
|
@@ -126,6 +126,8 @@ declare class GraphPage extends WpFilterPage {
|
|
|
126
126
|
protected captureBinding(_svg: SVGSVGElement | null): () => void;
|
|
127
127
|
protected wireControls(): void;
|
|
128
128
|
protected nodeDot(node: RenderNodeJson): string;
|
|
129
|
+
/** Product mode dashes a dependency that crosses into another product (#1204); every other mode draws it plain. */
|
|
130
|
+
protected edgeDot(edge: RenderEdgeJson): string;
|
|
129
131
|
protected usesFullDot(): boolean;
|
|
130
132
|
protected narrow(retained: Set<string>): Set<string>;
|
|
131
133
|
/** Filtering keeps every box in its own L-row: an emptied level stays as a thin labeled band. */
|
|
@@ -678,6 +678,12 @@ class GraphPage extends WpFilterPage {
|
|
|
678
678
|
return modes.product;
|
|
679
679
|
return modes.runtime;
|
|
680
680
|
}
|
|
681
|
+
/** Product mode dashes a dependency that crosses into another product (#1204); every other mode draws it plain. */
|
|
682
|
+
edgeDot(edge) {
|
|
683
|
+
if (this.modes.mode === 'product' && edge.productDot !== null)
|
|
684
|
+
return edge.productDot;
|
|
685
|
+
return edge.dot;
|
|
686
|
+
}
|
|
681
687
|
usesFullDot() {
|
|
682
688
|
return this.modes.mode === 'runtime' && this.applied.count() === 0;
|
|
683
689
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-visualizer.client.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/graph-visualizer.client.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * One state of the Filter popover: a change scope plus the selected Runtime, Role and Product chips.\n * The page holds the APPLIED one; the popover edits a copy until \"Show N projects\".\n */\nclass WpFilterChoice {\n scope = 'everything';\n readonly runtimes = new Set<string>();\n readonly roles = new Set<string>();\n readonly products = new Set<string>();\n\n copy(): WpFilterChoice {\n const copy = new WpFilterChoice();\n copy.scope = this.scope;\n for (const runtime of this.runtimes) copy.runtimes.add(runtime);\n for (const role of this.roles) copy.roles.add(role);\n for (const product of this.products) copy.products.add(product);\n return copy;\n }\n\n /** How many filters are active: the drawer button's badge. */\n count(): number {\n return (this.scope === 'everything' ? 0 : 1) + this.runtimes.size + this.roles.size + this.products.size;\n }\n\n /** The chip set a `data-wp-chip-group` (or a pill's group) names. */\n group(name: string): Set<string> {\n if (name === 'role') return this.roles;\n if (name === 'product') return this.products;\n return this.runtimes;\n }\n}\n\n/**\n * The Filter popover's four groups, INTERSECTED: a box stays when it is in the change scope, AND has\n * any selected runtime chip (when one is selected), AND has any selected role chip (likewise), AND\n * belongs to any selected product (likewise — several products are the UNION of their closures).\n */\nclass WpProjectFilter {\n constructor(\n private readonly model: RenderModelJson,\n private readonly modes: WpModeState,\n ) {}\n\n /** The node ids a change scope keeps; null for \"everything\" (and whenever Impact is unavailable). */\n scopeSet(scope: string): Set<string> | null {\n const impact = this.modes.impact;\n if (scope === 'everything' || impact === null || this.modes.impactReason() !== '') return null;\n const ids: string[] = [...impact.touched];\n if (scope === 'dependents' || scope === 'build') ids.push(...impact.affected);\n if (scope === 'dependencies') ids.push(...impact.dependencies);\n if (scope === 'build') ids.push(...impact.buildInputs);\n return new Set(ids);\n }\n\n /** How many drawn projects a scope keeps on its own: the count beside each option. */\n scopeCount(scope: string): number {\n const set = this.scopeSet(scope);\n return this.model.nodes.filter((node: RenderNodeJson): boolean => this.isService(node) && (set === null || set.has(node.id))).length;\n }\n\n /** `base` (everything, or the Hide-unconnected chain) narrowed by `choice`. */\n apply(base: Set<string>, choice: WpFilterChoice): Set<string> {\n const scope = this.scopeSet(choice.scope);\n const kept = new Set<string>();\n for (const node of this.model.nodes) {\n if (!base.has(node.id) || !this.isService(node)) continue;\n if (scope !== null && !scope.has(node.id)) continue;\n if (!this.anyOf(choice.runtimes, node.tags?.frameworks ?? [])) continue;\n if (!this.anyOf(choice.roles, node.tags === null ? [] : [node.tags.role])) continue;\n if (!this.anyOf(choice.products, node.products)) continue;\n kept.add(node.id);\n }\n if (this.model.viewer === 'runtime') {\n for (const node of this.model.nodes) {\n if (node.tags !== null || !base.has(node.id)) continue;\n if (this.model.edges.some(edge => (edge.from === node.id && kept.has(edge.to)) || (edge.to === node.id && kept.has(edge.from)))) kept.add(node.id);\n }\n }\n return kept;\n }\n\n isService(node: RenderNodeJson): boolean { return this.model.viewer !== 'runtime' || node.tags !== null; }\n\n /** An empty chip group matches every box; otherwise the box must carry one of the chips. */\n private anyOf(selected: Set<string>, carried: string[]): boolean {\n return selected.size === 0 || carried.some((value: string): boolean => selected.has(value));\n }\n}\n\n/** Architecture interactions bind to each new SVG; logical Lock/Filter state belongs to the page. */\nclass GraphHighlighter {\n private readonly nodeByName = new Map<string, SVGGElement>();\n private hovered: string | null = null;\n\n constructor(\n private readonly svg: SVGSVGElement,\n private readonly chain: WpGraphChain,\n private readonly model: RenderModelJson,\n private readonly page: GraphPage,\n ) {}\n\n wire(): void {\n this.svg.querySelectorAll<SVGGElement>('g.node').forEach((g: SVGGElement) => {\n if (g.classList.contains('wp-layout')) return;\n const name = g.querySelector('title')?.textContent;\n if (name !== null && name !== undefined) this.nodeByName.set(name, g);\n });\n this.wireHover();\n this.wireMenu();\n this.relight();\n }\n\n private clear(): void {\n this.svg.classList.remove('wp-dim');\n this.svg.querySelectorAll('.wp-focus, .wp-neighbor, .wp-hl, .wp-locked').forEach((el: Element) => {\n el.classList.remove('wp-focus', 'wp-neighbor', 'wp-hl', 'wp-locked');\n });\n }\n\n relight(): void {\n this.clear();\n const locked = this.page.lockSelection();\n if (locked !== null) this.nodeByName.get(locked)?.classList.add('wp-locked');\n // A filtered-out Lock is suspended, including its otherwise visible relatives.\n const anchors = [locked, this.hovered].filter(\n (name: string | null): name is string => name !== null && this.nodeByName.has(name),\n );\n if (anchors.length === 0) return;\n const lit = new Set<string>();\n for (const name of anchors) {\n this.nodeByName.get(name)?.classList.add('wp-focus');\n for (const id of this.chain.nodes(name)) {\n if (this.nodeByName.has(id)) lit.add(id);\n }\n }\n this.svg.classList.add('wp-dim');\n for (const id of lit) this.nodeByName.get(id)?.classList.add('wp-neighbor');\n for (const edge of this.model.edges) {\n if (lit.has(edge.from) && lit.has(edge.to)) {\n this.svg.querySelector(`[id=\"${edge.id}\"]`)?.classList.add('wp-hl');\n }\n }\n }\n\n private wireHover(): void {\n this.nodeByName.forEach((g: SVGGElement, name: string) => {\n g.addEventListener('mouseenter', () => {\n this.hovered = name;\n this.relight();\n });\n g.addEventListener('mouseleave', () => {\n this.hovered = null;\n this.relight();\n });\n });\n }\n\n private wireMenu(): void {\n const designs = new Map<string, string>();\n for (const link of __DESIGN_LINKS__) designs.set(link.nodeId, link.href);\n WpNodeMenu.wire(this.svg, (name: string, node: SVGGElement): WpNodeMenuItem[] => {\n const items: WpNodeMenuItem[] = [];\n const href = designs.get(name);\n if (href !== undefined)\n items.push(new WpNodeMenuItem('View Design', () => window.open(href, '_blank')));\n const locked = this.page.lockSelection() === name;\n items.push(\n new WpNodeMenuItem(locked ? 'Unlock' : 'Lock', () =>\n locked ? this.page.clearSelection() : this.page.setLock(name),\n ),\n );\n items.push(this.page.filterItem(name));\n const implemented = window.__WP_RUNTIME__?.implementsItem(name, node);\n if (implemented) items.push(implemented);\n return items;\n });\n }\n}\n\n/**\n * The Filter popover: edits a COPY of the page's applied filter, shows what each choice would keep,\n * and hands the copy to the page on \"Show N projects\". Closing it any other way discards the edit.\n */\nclass GraphFilterPopover {\n private draft = new WpFilterChoice();\n\n constructor(private readonly page: GraphPage) {}\n\n wire(): void {\n this.byId('wp-filter-open')?.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n if (this.isOpen()) this.close();\n else this.open();\n });\n this.byId('wp-filter-close')?.addEventListener('click', () => this.close());\n this.byId('wp-filter-clear')?.addEventListener('click', () => {\n this.draft = new WpFilterChoice();\n this.paint();\n });\n this.byId('wp-filter-apply')?.addEventListener('click', () => {\n this.page.applyFilter(this.draft.copy());\n this.close();\n });\n document.querySelectorAll<HTMLInputElement>('input[name=\"wp-scope\"]').forEach((radio: HTMLInputElement) => {\n radio.addEventListener('change', () => {\n if (!radio.checked) return;\n this.draft.scope = radio.value;\n this.paint();\n });\n });\n document.querySelectorAll<HTMLButtonElement>('.wp-chip[data-wp-chip]').forEach((chip: HTMLButtonElement) => {\n chip.addEventListener('click', () => {\n const set = this.draft.group(chip.dataset['wpChipGroup'] ?? '');\n const value = chip.dataset['wpChip'] ?? '';\n if (set.has(value)) set.delete(value);\n else set.add(value);\n this.paint();\n });\n });\n }\n\n isOpen(): boolean {\n return this.byId('wp-filter-pop')?.hidden === false;\n }\n\n /** The active Impact scan changed: an open popover's counts and labels follow it. */\n refresh(): void {\n if (this.isOpen()) this.paint();\n }\n\n open(): void {\n const pop = this.byId('wp-filter-pop');\n if (pop === null) return;\n this.draft = this.page.appliedFilter().copy();\n this.paint();\n pop.hidden = false;\n this.byId('wp-filter-open')?.setAttribute('aria-expanded', 'true');\n }\n\n close(): void {\n const pop = this.byId('wp-filter-pop');\n if (pop === null || pop.hidden) return;\n pop.hidden = true;\n this.byId('wp-filter-open')?.setAttribute('aria-expanded', 'false');\n }\n\n /** Repaint the controls from the draft: checked scope, pressed chips, counts and the footer. */\n private paint(): void {\n const reason = this.page.scopeReason();\n const group = this.byId('wp-scope-group') as HTMLFieldSetElement | null;\n if (group !== null) group.disabled = reason !== '';\n const reasonEl = this.byId('wp-scope-reason');\n if (reasonEl !== null) {\n reasonEl.textContent = reason;\n reasonEl.hidden = reason === '';\n }\n document.querySelectorAll<HTMLInputElement>('input[name=\"wp-scope\"]').forEach((radio: HTMLInputElement) => {\n radio.checked = radio.value === this.draft.scope;\n });\n document.querySelectorAll<HTMLElement>('[data-wp-scope-count]').forEach((count: HTMLElement) => {\n count.textContent = reason === '' ? String(this.page.scopeCount(count.dataset['wpScopeCount'] ?? '')) : '';\n });\n document.querySelectorAll<HTMLButtonElement>('.wp-chip[data-wp-chip]').forEach((chip: HTMLButtonElement) => {\n const set = this.draft.group(chip.dataset['wpChipGroup'] ?? '');\n chip.setAttribute('aria-pressed', String(set.has(chip.dataset['wpChip'] ?? '')));\n });\n const apply = this.byId('wp-filter-apply');\n if (apply !== null) {\n const shown = this.page.preview(this.draft);\n apply.textContent = `Show ${shown} ${this.page.noun()}${shown === 1 ? '' : 's'}`;\n }\n }\n\n private byId(id: string): HTMLElement | null {\n return document.getElementById(id);\n }\n}\n\n/**\n * The drawer and its floating panels: every control outside the graph itself. Holds no graph state —\n * each control calls back into the page, and `sync()` repaints the controls from the page's state.\n */\nclass GraphDrawer {\n readonly popover: GraphFilterPopover;\n private readonly openers = new Map<string, HTMLElement>();\n\n constructor(private readonly page: GraphPage) {\n this.popover = new GraphFilterPopover(page);\n }\n\n wire(): void {\n this.wireModeMenu();\n this.popover.wire();\n this.wireImpactKinds();\n this.wireLock();\n this.byId('wp-lock-toggle')?.addEventListener('click', () => this.page.toggleLock());\n this.byId('wp-filter-toggle')?.addEventListener('click', () => this.page.toggleFilter());\n this.toggles('wp-collapse', 'wp-shell', true);\n this.toggles('wp-help-btn', 'wp-help', false);\n this.toggles('wp-help-close', 'wp-help', false);\n this.toggles('wp-legend-pop', 'wp-legend-popout', false);\n this.toggles('wp-legend-close', 'wp-legend-popout', false);\n this.toggles('wp-resp-open', 'wp-resp-panel', false);\n this.toggles('wp-resp-close', 'wp-resp-panel', false);\n this.toggles('wp-snapshot-open', 'wp-snapshot', false);\n window.addEventListener('keydown', (ev: KeyboardEvent) => this.onKey(ev), true);\n window.addEventListener('hashchange', () => this.page.setMode(location.hash.slice(1)));\n document.addEventListener('click', (ev: MouseEvent) => {\n const target = ev.target;\n if (target instanceof Node && this.byId('wp-mode-menu')?.parentElement?.contains(target)) return;\n this.closeModeMenu(false);\n this.dismissOutside(target);\n });\n }\n\n /** \"Color by\": the pill trigger opens the menu of four; picking one switches and closes it. */\n private wireModeMenu(): void {\n this.byId('wp-mode-trigger')?.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n const menu = this.byId('wp-mode-menu');\n if (menu === null) return;\n if (!menu.hidden) {\n this.closeModeMenu(false);\n return;\n }\n menu.hidden = false;\n this.byId('wp-mode-trigger')?.setAttribute('aria-expanded', 'true');\n menu.querySelector<HTMLButtonElement>('.wp-mode[aria-checked=\"true\"]')?.focus({ preventScroll: true });\n });\n document.querySelectorAll<HTMLButtonElement>('.wp-mode[data-wp-mode]').forEach((button: HTMLButtonElement) => {\n button.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n this.closeModeMenu(true);\n this.page.setMode(button.dataset['wpMode'] ?? 'runtime');\n });\n });\n }\n\n /** The \"Changed on this branch\" / \"Last commit\" toggle, in the drawer and in the Filter popover. */\n private wireImpactKinds(): void {\n document.querySelectorAll<HTMLButtonElement>('[data-wp-impact-kind]').forEach((button: HTMLButtonElement) => {\n button.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n this.page.setImpactKind(button.dataset['wpImpactKind'] ?? '');\n this.popover.refresh();\n });\n });\n }\n\n /** Shown only when two scans exist; the drawer's copy only while Impact colors the graph. */\n private syncImpactKinds(modes: WpModeState): void {\n document.querySelectorAll<HTMLElement>('[data-wp-impact-kinds]').forEach((group: HTMLElement) => {\n const inDrawer = group.dataset['wpImpactKinds'] === 'drawer';\n group.hidden = modes.scans.length < 2 || (inDrawer && modes.mode !== 'impact');\n });\n document.querySelectorAll<HTMLButtonElement>('[data-wp-impact-kind]').forEach((button: HTMLButtonElement) => {\n const kind = button.dataset['wpImpactKind'] ?? '';\n button.setAttribute('aria-pressed', String(kind === modes.kind));\n button.disabled = !modes.kindAvailable(kind);\n const scan = modes.scans.find((candidate: ImpactJson): boolean => candidate.kind === kind);\n button.title = scan === undefined ? '' : scan.available ? scan.label : scan.reason;\n });\n const legend = this.byId('wp-scope-legend');\n if (legend !== null) legend.textContent = modes.impact?.label ?? 'Changes on this branch';\n }\n\n private closeModeMenu(returnFocus: boolean): void {\n const menu = this.byId('wp-mode-menu');\n if (menu === null || menu.hidden) return;\n menu.hidden = true;\n const trigger = this.byId('wp-mode-trigger');\n trigger?.setAttribute('aria-expanded', 'false');\n if (returnFocus) trigger?.focus({ preventScroll: true });\n }\n\n /** Type-to-search lock: an exact project id (or a unique short name) locks, empty or Esc unlocks. */\n private wireLock(): void {\n const input = this.lockInput();\n if (input === null) return;\n input.addEventListener('input', () => {\n const value = input.value.trim();\n if (value === '') this.page.clearSelection();\n else if (this.page.hasNode(value)) this.page.setLock(value);\n });\n input.addEventListener('change', () => {\n const match = this.page.resolveName(input.value.trim());\n if (match !== null) this.page.setLock(match);\n else input.value = this.page.lockSelection() ?? '';\n });\n input.addEventListener('keydown', (ev: KeyboardEvent) => {\n if (ev.key !== 'Escape') return;\n ev.preventDefault();\n input.value = '';\n this.page.clearSelection();\n input.blur();\n });\n }\n\n /**\n * Page keys, in the CAPTURE phase so the open/closed state of the node menu is read before the\n * menu's own Escape handler closes it: Esc with a menu open only closes the menu. Esc closes an\n * open Color-by menu or Filter popover first, too.\n */\n private onKey(ev: KeyboardEvent): void {\n if (ev.altKey || ev.ctrlKey || ev.metaKey) return;\n if (ev.key === 'Escape' && this.byId('wp-mode-menu')?.hidden === false) {\n this.closeModeMenu(true);\n return;\n }\n if (ev.key === 'Escape' && this.popover.isOpen()) {\n this.popover.close();\n return;\n }\n if (ev.key === 'Escape' && this.dismissOverlay()) return;\n const target = ev.target;\n if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) return;\n const menuOpen = document.getElementById('wp-node-menu') !== null || document.querySelector('.wp-graph-details:not([hidden])') !== null;\n if (ev.key === '/') {\n this.byId('wp-shell')?.classList.remove('wp-collapsed');\n this.byId('wp-collapse')?.setAttribute('aria-expanded', 'true');\n ev.preventDefault();\n this.lockInput()?.focus();\n return;\n }\n const index = ['1', '2', '3', '4'].indexOf(ev.key);\n if (index >= 0 && !menuOpen) {\n this.page.setMode(WpModeState.MODES[index]);\n return;\n }\n if (ev.key === 'Escape' && !menuOpen && this.page.lockSelection() !== null) this.page.setLock(null);\n }\n\n /** `button` shows/hides `target`; for the drawer itself it toggles the collapsed class instead. */\n private toggles(buttonId: string, targetId: string, collapse: boolean): void {\n const button = this.byId(buttonId);\n const target = this.byId(targetId);\n if (button === null || target === null) return;\n button.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n let expanded: boolean;\n if (collapse) {\n expanded = !target.classList.toggle('wp-collapsed');\n } else {\n target.hidden = !target.hidden;\n expanded = !target.hidden;\n if (expanded) this.openers.set(targetId, button);\n else this.openers.get(targetId)?.focus({ preventScroll: true });\n }\n document.querySelectorAll(`[aria-controls=\"${targetId}\"], #${buttonId}[aria-expanded]`).forEach(\n (el: Element) => el.setAttribute('aria-expanded', String(expanded)),\n );\n });\n }\n\n private dismissOverlay(): boolean {\n for (const id of ['wp-help', 'wp-legend-popout', 'wp-snapshot', 'wp-resp-panel']) {\n const panel = this.byId(id);\n if (!panel || panel.hidden) continue;\n panel.hidden = true;\n this.openers.get(id)?.focus({ preventScroll: true });\n this.openers.get(id)?.setAttribute('aria-expanded', 'false');\n return true;\n }\n return false;\n }\n\n private dismissOutside(target: EventTarget | null): void {\n if (!(target instanceof Node)) return;\n const filter = this.byId('wp-filter-pop');\n if (this.popover.isOpen() && !filter?.contains(target) && !this.byId('wp-filter-open')?.contains(target)) this.popover.close();\n for (const entry of this.openers) {\n const id = entry[0];\n const opener = entry[1];\n const panel = this.byId(id);\n if (panel && !panel.hidden && !panel.contains(target) && !opener.contains(target)) {\n panel.hidden = true;\n opener.setAttribute('aria-expanded', 'false');\n }\n }\n }\n\n /** Repaint every control from the page's state. */\n sync(modes: WpModeState, locked: string | null, filtering: boolean, filter: WpFilterChoice): void {\n const reason = modes.impactReason();\n document.querySelectorAll<HTMLButtonElement>('.wp-mode[data-wp-mode]').forEach((button: HTMLButtonElement) => {\n const mode = button.dataset['wpMode'] ?? '';\n button.setAttribute('aria-checked', String(mode === modes.mode));\n button.disabled = !modes.available(mode);\n if (mode === 'impact') button.title = reason === '' ? 'Key 3' : reason;\n if (mode === 'product') button.title = modes.productReason() === '' ? 'Key 4' : modes.productReason();\n });\n this.text('wp-mode-current', modes.name(modes.mode));\n this.text('wp-mode-current-sub', modes.subtitle(modes.mode));\n const reasonEl = this.byId('wp-impact-reason');\n if (reasonEl !== null) {\n reasonEl.textContent = reason;\n reasonEl.hidden = reason === '';\n }\n document.querySelectorAll<HTMLElement>('[data-wp-legend-mode]').forEach((section: HTMLElement) => {\n section.hidden = section.dataset['wpLegendMode'] !== modes.mode;\n });\n document.querySelectorAll<HTMLElement>('[data-wp-impact-note]').forEach((note: HTMLElement) => {\n note.textContent = this.impactNote(modes);\n });\n this.syncImpactKinds(modes);\n const title = this.byId('wp-legend-pop-title');\n if (title !== null) title.textContent = `Legend · ${modes.name(modes.mode)}`;\n const input = this.lockInput();\n if (input !== null && document.activeElement !== input) input.value = this.page.focusSelection() ?? '';\n const lockToggle = this.byId('wp-lock-toggle') as HTMLButtonElement | null;\n if (lockToggle !== null) {\n lockToggle.setAttribute('aria-pressed', String(locked !== null));\n lockToggle.disabled = locked === null && this.page.focusSelection() === null;\n lockToggle.title = lockToggle.disabled ? 'Select a node in Focus first' : '';\n }\n this.syncFilterToggle(locked, filtering);\n this.syncFilter(filter);\n this.crumb(modes.name(modes.mode), locked);\n }\n\n private syncFilterToggle(locked: string | null, filtering: boolean): void {\n const toggle = this.byId('wp-filter-toggle') as HTMLButtonElement | null;\n if (toggle === null) return;\n toggle.setAttribute('aria-pressed', String(filtering));\n toggle.disabled = !filtering && locked === null;\n toggle.title = toggle.disabled ? 'Lock a project first' : '';\n }\n\n /** The drawer button's count badge, and one removable pill per active filter in the top bar. */\n private syncFilter(filter: WpFilterChoice): void {\n const badge = this.byId('wp-filter-badge');\n if (badge !== null) {\n badge.textContent = String(filter.count());\n badge.hidden = filter.count() === 0;\n }\n const pills = this.byId('wp-filter-pills');\n if (pills === null) return;\n const items: HTMLElement[] = [];\n if (filter.scope !== 'everything') items.push(this.pill(this.scopeLabel(filter.scope), 'scope', filter.scope));\n for (const runtime of filter.runtimes) items.push(this.pill(runtime, 'runtime', runtime));\n for (const role of filter.roles) items.push(this.pill(role, 'role', role));\n for (const product of filter.products) items.push(this.pill(`product: ${product}`, 'product', product));\n pills.replaceChildren(...items);\n }\n\n /** A change scope's name, read from the Filter popover's markup: the shell owns the ONE copy. */\n private scopeLabel(scope: string): string {\n return document.querySelector(`[data-wp-scope-label=\"${scope}\"]`)?.textContent ?? scope;\n }\n\n /** A pill, built with text nodes so no value is parsed as HTML. */\n private pill(label: string, group: string, value: string): HTMLElement {\n const pill = document.createElement('span');\n pill.className = 'wp-pill';\n pill.dataset['wpPill'] = `${group}:${value}`;\n pill.append(label);\n const remove = document.createElement('button');\n remove.type = 'button';\n remove.textContent = '✕';\n remove.setAttribute('aria-label', `Remove filter ${label}`);\n remove.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n this.page.removeFilter(group, value);\n });\n pill.append(remove);\n return pill;\n }\n\n private impactNote(modes: WpModeState): string {\n const impact = modes.impact;\n if (impact === null || !impact.available) return '';\n // An available scan with a note is an EMPTY one, e.g. \"Nothing changed on this branch yet\".\n if (impact.reason !== '') return `${impact.label}: ${impact.reason}.`;\n const stats =\n `${impact.label}: ${impact.touched.length} changed · ${impact.affected.length} dependents · ` +\n `${impact.buildInputs.length} dependencies — nx affected, ${impact.changedFiles} changed files.`;\n const cause = this.globalCause(impact);\n return cause === '' ? stats : `${cause}. ${stats}`;\n }\n\n /**\n * When files changed but no project owns one, everything nx affected is affected by a\n * workspace-global input (a lockfile, the workspace manifest). That is correct for CI, and\n * baffling on a graph, so the note names the cause.\n */\n private globalCause(impact: ImpactJson): string {\n if (impact.touched.length > 0 || impact.changedFiles === 0) return '';\n const affected = impact.affected.length;\n const who = affected >= this.page.projectCount() ? 'Every project affected' : `${affected} projects affected`;\n const files = impact.globalFiles;\n if (files.length === 0)\n return `${who}: ${impact.changedFiles} changed files that no project owns (workspace-global input)`;\n const named = files.slice(0, 2).join(', ') + (files.length > 2 ? ` and ${files.length - 2} more` : '');\n return `${who}: ${named} changed (workspace-global input${files.length > 1 ? 's' : ''})`;\n }\n\n /** \"Mode: <b>Runtime</b> · Locked: <b>x</b>\", built with text nodes so no name is parsed as HTML. */\n private crumb(mode: string, locked: string | null): void {\n const crumb = this.byId('wp-crumb');\n if (crumb === null) return;\n const bold = (text: string): HTMLElement => {\n const b = document.createElement('b');\n b.textContent = text;\n return b;\n };\n const parts: (string | Node)[] = ['Mode: ', bold(mode)];\n if (locked !== null) parts.push(' · Locked: ', bold(locked));\n crumb.replaceChildren(...parts);\n }\n\n private text(id: string, value: string): void {\n const el = this.byId(id);\n if (el !== null) el.textContent = value;\n }\n\n private lockInput(): HTMLInputElement | null {\n return document.getElementById('wp-lock') as HTMLInputElement | null;\n }\n\n private byId(id: string): HTMLElement | null {\n return document.getElementById(id);\n }\n}\n\nclass GraphPage extends WpFilterPage {\n private highlighter: GraphHighlighter | null = null;\n private selected: string | null = null;\n private readonly modes = new WpModeState(\n this.model.nodes.some((node: RenderNodeJson): boolean => node.products.length > 0),\n this.model.viewer ?? 'architecture',\n );\n private readonly projects = new WpProjectFilter(this.model, this.modes);\n private applied = new WpFilterChoice();\n private readonly drawer = new GraphDrawer(this);\n\n protected override captureBinding(_svg: SVGSVGElement | null): () => void {\n const previous = this.highlighter;\n return (): void => {\n this.highlighter = previous;\n this.filterCards();\n this.syncControls();\n };\n }\n\n protected override wireControls(): void {\n this.drawer.wire();\n this.syncControls();\n }\n\n protected override nodeDot(node: RenderNodeJson): string {\n const modes = node.modes;\n if (modes === null) return node.dot;\n if (this.modes.mode === 'architecture') return modes.architecture;\n if (this.modes.mode === 'impact') return modes[this.modes.status(node.id)];\n if (this.modes.mode === 'product') return modes.product;\n return modes.runtime;\n }\n\n protected override usesFullDot(): boolean {\n return this.modes.mode === 'runtime' && this.applied.count() === 0;\n }\n\n protected override narrow(retained: Set<string>): Set<string> {\n return this.projects.apply(retained, this.applied);\n }\n\n /** Filtering keeps every box in its own L-row: an emptied level stays as a thin labeled band. */\n protected override keepsEmptyLevels(): boolean {\n return true;\n }\n\n protected override prepareSvg(svg: SVGSVGElement): void { window.__WP_RUNTIME__?.prepare(svg); }\n\n protected wireSvg(svg: SVGSVGElement): void {\n this.highlighter = new GraphHighlighter(svg, this.chain, this.model, this);\n this.highlighter.wire();\n this.filterCards();\n this.syncControls();\n svg.querySelectorAll<SVGGElement>('g.node').forEach((node: SVGGElement) => {\n if (node.querySelector('title')?.textContent === this.anchor)\n node.classList.add('wp-filter-anchor');\n });\n }\n\n lockSelection(): string | null {\n return this.locked;\n }\n\n hasNode(id: string): boolean {\n return this.model.nodes.some((node: RenderNodeJson): boolean => node.id === id);\n }\n\n noun(): string { return this.model.viewer === 'runtime' ? 'service' : 'project'; }\n\n projectCount(): number { return this.model.nodes.filter(node => this.projects.isService(node)).length; }\n\n focusSelection(): string | null { return this.selected; }\n\n toggleLock(): void {\n if (this.locked !== null) this.setLock(null);\n else if (this.selected !== null) this.setLock(this.selected);\n }\n\n /** An exact id, else the one id whose short name (after any scope) is `text`; null if none or several. */\n resolveName(text: string): string | null {\n if (text === '') return null;\n if (this.hasNode(text)) return text;\n const matches = this.model.nodes.filter(\n (node: RenderNodeJson): boolean => node.id.split('/').pop() === text,\n );\n return matches.length === 1 ? matches[0].id : null;\n }\n\n setLock(name: string | null): void {\n this.locked = name;\n if (name !== null) this.selected = name;\n this.highlighter?.relight();\n this.filterCards();\n this.syncControls();\n }\n\n clearSelection(): void { this.selected = null; this.setLock(null); }\n\n setMode(mode: string): void {\n if (mode === this.modes.mode || !this.modes.set(mode)) return;\n this.syncControls();\n this.redraw();\n }\n\n /** Switch the active Impact scan: Impact recolours and an active change-scope filter re-applies. */\n setImpactKind(kind: string): void {\n if (kind === this.modes.kind || !this.modes.setKind(kind)) return;\n this.syncControls();\n this.redraw();\n }\n\n /** The drawer's \"Hide unconnected\": filter to the locked box's chain, or turn the filter off. */\n toggleFilter(): void {\n if (this.anchor !== null) this.filter(null);\n else if (this.locked !== null) this.filter(this.locked);\n }\n\n appliedFilter(): WpFilterChoice {\n return this.applied;\n }\n\n /** '' when the change-scope group can be used, else Impact's reason (the group is disabled). */\n scopeReason(): string {\n return this.modes.impactReason();\n }\n\n scopeCount(scope: string): number {\n if (this.model.viewer !== 'runtime') return this.projects.scopeCount(scope);\n const choice = new WpFilterChoice(); choice.scope = scope;\n return this.preview(choice);\n }\n\n /** How many boxes `choice` would show, with the current Hide-unconnected chain. */\n preview(choice: WpFilterChoice): number {\n const base =\n this.anchor === null\n ? new Set(this.model.nodes.map((node: RenderNodeJson): string => node.id))\n : this.chain.nodes(this.anchor);\n const kept = this.projects.apply(base, choice);\n return this.model.nodes.filter(node => kept.has(node.id) && this.projects.isService(node)).length;\n }\n\n applyFilter(choice: WpFilterChoice): void {\n if (this.scopeReason() !== '') choice.scope = 'everything';\n this.applied = choice;\n this.syncControls();\n this.redraw();\n }\n\n /** A top-bar pill's ✕. */\n removeFilter(group: string, value: string): void {\n const next = this.applied.copy();\n if (group === 'scope') next.scope = 'everything';\n else next.group(group).delete(value);\n this.applyFilter(next);\n }\n\n private syncControls(): void {\n this.drawer.sync(this.modes, this.locked, this.anchor !== null, this.applied);\n const count = this.model.nodes.filter(node => this.retained.has(node.id) && this.projects.isService(node)).length;\n const empty = document.getElementById('wp-empty');\n if (empty !== null) empty.hidden = count !== 0;\n const context = document.getElementById('wp-context-count');\n if (context !== null) context.textContent = `${count} services · ${this.retained.size - count} contextual nodes`;\n this.syncLegend();\n }\n\n private syncLegend(): void {\n document.querySelectorAll<HTMLElement>('[data-wp-legend-value]').forEach(row => {\n const group = row.dataset['wpLegendGroup'];\n const value = row.dataset['wpLegendValue'] ?? '';\n row.hidden = !this.model.nodes.some(node => this.retained.has(node.id) &&\n (group === 'runtime' ? (value === 'unknown' ? node.tags !== null && node.tags.frameworks.length === 0 : node.tags?.frameworks.includes(value)) : group === 'role' ? node.tags?.role === value : node.products.includes(value)));\n });\n }\n\n private filterCards(): void {\n const lit = this.locked === null ? this.retained : this.chain.nodes(this.locked);\n document.querySelectorAll('.wp-resp-card').forEach((card: Element) => {\n const name = card.getAttribute('data-node');\n card.classList.toggle(\n 'wp-hidden',\n name === null || !this.retained.has(name) || !lit.has(name),\n );\n });\n }\n}\n\nnew GraphPage(__RENDER_MODEL__).render();\n"]}
|
|
1
|
+
{"version":3,"file":"graph-visualizer.client.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/graph-visualizer.client.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * One state of the Filter popover: a change scope plus the selected Runtime, Role and Product chips.\n * The page holds the APPLIED one; the popover edits a copy until \"Show N projects\".\n */\nclass WpFilterChoice {\n scope = 'everything';\n readonly runtimes = new Set<string>();\n readonly roles = new Set<string>();\n readonly products = new Set<string>();\n\n copy(): WpFilterChoice {\n const copy = new WpFilterChoice();\n copy.scope = this.scope;\n for (const runtime of this.runtimes) copy.runtimes.add(runtime);\n for (const role of this.roles) copy.roles.add(role);\n for (const product of this.products) copy.products.add(product);\n return copy;\n }\n\n /** How many filters are active: the drawer button's badge. */\n count(): number {\n return (this.scope === 'everything' ? 0 : 1) + this.runtimes.size + this.roles.size + this.products.size;\n }\n\n /** The chip set a `data-wp-chip-group` (or a pill's group) names. */\n group(name: string): Set<string> {\n if (name === 'role') return this.roles;\n if (name === 'product') return this.products;\n return this.runtimes;\n }\n}\n\n/**\n * The Filter popover's four groups, INTERSECTED: a box stays when it is in the change scope, AND has\n * any selected runtime chip (when one is selected), AND has any selected role chip (likewise), AND\n * belongs to any selected product (likewise — several products are the UNION of their closures).\n */\nclass WpProjectFilter {\n constructor(\n private readonly model: RenderModelJson,\n private readonly modes: WpModeState,\n ) {}\n\n /** The node ids a change scope keeps; null for \"everything\" (and whenever Impact is unavailable). */\n scopeSet(scope: string): Set<string> | null {\n const impact = this.modes.impact;\n if (scope === 'everything' || impact === null || this.modes.impactReason() !== '') return null;\n const ids: string[] = [...impact.touched];\n if (scope === 'dependents' || scope === 'build') ids.push(...impact.affected);\n if (scope === 'dependencies') ids.push(...impact.dependencies);\n if (scope === 'build') ids.push(...impact.buildInputs);\n return new Set(ids);\n }\n\n /** How many drawn projects a scope keeps on its own: the count beside each option. */\n scopeCount(scope: string): number {\n const set = this.scopeSet(scope);\n return this.model.nodes.filter((node: RenderNodeJson): boolean => this.isService(node) && (set === null || set.has(node.id))).length;\n }\n\n /** `base` (everything, or the Hide-unconnected chain) narrowed by `choice`. */\n apply(base: Set<string>, choice: WpFilterChoice): Set<string> {\n const scope = this.scopeSet(choice.scope);\n const kept = new Set<string>();\n for (const node of this.model.nodes) {\n if (!base.has(node.id) || !this.isService(node)) continue;\n if (scope !== null && !scope.has(node.id)) continue;\n if (!this.anyOf(choice.runtimes, node.tags?.frameworks ?? [])) continue;\n if (!this.anyOf(choice.roles, node.tags === null ? [] : [node.tags.role])) continue;\n if (!this.anyOf(choice.products, node.products)) continue;\n kept.add(node.id);\n }\n if (this.model.viewer === 'runtime') {\n for (const node of this.model.nodes) {\n if (node.tags !== null || !base.has(node.id)) continue;\n if (this.model.edges.some(edge => (edge.from === node.id && kept.has(edge.to)) || (edge.to === node.id && kept.has(edge.from)))) kept.add(node.id);\n }\n }\n return kept;\n }\n\n isService(node: RenderNodeJson): boolean { return this.model.viewer !== 'runtime' || node.tags !== null; }\n\n /** An empty chip group matches every box; otherwise the box must carry one of the chips. */\n private anyOf(selected: Set<string>, carried: string[]): boolean {\n return selected.size === 0 || carried.some((value: string): boolean => selected.has(value));\n }\n}\n\n/** Architecture interactions bind to each new SVG; logical Lock/Filter state belongs to the page. */\nclass GraphHighlighter {\n private readonly nodeByName = new Map<string, SVGGElement>();\n private hovered: string | null = null;\n\n constructor(\n private readonly svg: SVGSVGElement,\n private readonly chain: WpGraphChain,\n private readonly model: RenderModelJson,\n private readonly page: GraphPage,\n ) {}\n\n wire(): void {\n this.svg.querySelectorAll<SVGGElement>('g.node').forEach((g: SVGGElement) => {\n if (g.classList.contains('wp-layout')) return;\n const name = g.querySelector('title')?.textContent;\n if (name !== null && name !== undefined) this.nodeByName.set(name, g);\n });\n this.wireHover();\n this.wireMenu();\n this.relight();\n }\n\n private clear(): void {\n this.svg.classList.remove('wp-dim');\n this.svg.querySelectorAll('.wp-focus, .wp-neighbor, .wp-hl, .wp-locked').forEach((el: Element) => {\n el.classList.remove('wp-focus', 'wp-neighbor', 'wp-hl', 'wp-locked');\n });\n }\n\n relight(): void {\n this.clear();\n const locked = this.page.lockSelection();\n if (locked !== null) this.nodeByName.get(locked)?.classList.add('wp-locked');\n // A filtered-out Lock is suspended, including its otherwise visible relatives.\n const anchors = [locked, this.hovered].filter(\n (name: string | null): name is string => name !== null && this.nodeByName.has(name),\n );\n if (anchors.length === 0) return;\n const lit = new Set<string>();\n for (const name of anchors) {\n this.nodeByName.get(name)?.classList.add('wp-focus');\n for (const id of this.chain.nodes(name)) {\n if (this.nodeByName.has(id)) lit.add(id);\n }\n }\n this.svg.classList.add('wp-dim');\n for (const id of lit) this.nodeByName.get(id)?.classList.add('wp-neighbor');\n for (const edge of this.model.edges) {\n if (lit.has(edge.from) && lit.has(edge.to)) {\n this.svg.querySelector(`[id=\"${edge.id}\"]`)?.classList.add('wp-hl');\n }\n }\n }\n\n private wireHover(): void {\n this.nodeByName.forEach((g: SVGGElement, name: string) => {\n g.addEventListener('mouseenter', () => {\n this.hovered = name;\n this.relight();\n });\n g.addEventListener('mouseleave', () => {\n this.hovered = null;\n this.relight();\n });\n });\n }\n\n private wireMenu(): void {\n const designs = new Map<string, string>();\n for (const link of __DESIGN_LINKS__) designs.set(link.nodeId, link.href);\n WpNodeMenu.wire(this.svg, (name: string, node: SVGGElement): WpNodeMenuItem[] => {\n const items: WpNodeMenuItem[] = [];\n const href = designs.get(name);\n if (href !== undefined)\n items.push(new WpNodeMenuItem('View Design', () => window.open(href, '_blank')));\n const locked = this.page.lockSelection() === name;\n items.push(\n new WpNodeMenuItem(locked ? 'Unlock' : 'Lock', () =>\n locked ? this.page.clearSelection() : this.page.setLock(name),\n ),\n );\n items.push(this.page.filterItem(name));\n const implemented = window.__WP_RUNTIME__?.implementsItem(name, node);\n if (implemented) items.push(implemented);\n return items;\n });\n }\n}\n\n/**\n * The Filter popover: edits a COPY of the page's applied filter, shows what each choice would keep,\n * and hands the copy to the page on \"Show N projects\". Closing it any other way discards the edit.\n */\nclass GraphFilterPopover {\n private draft = new WpFilterChoice();\n\n constructor(private readonly page: GraphPage) {}\n\n wire(): void {\n this.byId('wp-filter-open')?.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n if (this.isOpen()) this.close();\n else this.open();\n });\n this.byId('wp-filter-close')?.addEventListener('click', () => this.close());\n this.byId('wp-filter-clear')?.addEventListener('click', () => {\n this.draft = new WpFilterChoice();\n this.paint();\n });\n this.byId('wp-filter-apply')?.addEventListener('click', () => {\n this.page.applyFilter(this.draft.copy());\n this.close();\n });\n document.querySelectorAll<HTMLInputElement>('input[name=\"wp-scope\"]').forEach((radio: HTMLInputElement) => {\n radio.addEventListener('change', () => {\n if (!radio.checked) return;\n this.draft.scope = radio.value;\n this.paint();\n });\n });\n document.querySelectorAll<HTMLButtonElement>('.wp-chip[data-wp-chip]').forEach((chip: HTMLButtonElement) => {\n chip.addEventListener('click', () => {\n const set = this.draft.group(chip.dataset['wpChipGroup'] ?? '');\n const value = chip.dataset['wpChip'] ?? '';\n if (set.has(value)) set.delete(value);\n else set.add(value);\n this.paint();\n });\n });\n }\n\n isOpen(): boolean {\n return this.byId('wp-filter-pop')?.hidden === false;\n }\n\n /** The active Impact scan changed: an open popover's counts and labels follow it. */\n refresh(): void {\n if (this.isOpen()) this.paint();\n }\n\n open(): void {\n const pop = this.byId('wp-filter-pop');\n if (pop === null) return;\n this.draft = this.page.appliedFilter().copy();\n this.paint();\n pop.hidden = false;\n this.byId('wp-filter-open')?.setAttribute('aria-expanded', 'true');\n }\n\n close(): void {\n const pop = this.byId('wp-filter-pop');\n if (pop === null || pop.hidden) return;\n pop.hidden = true;\n this.byId('wp-filter-open')?.setAttribute('aria-expanded', 'false');\n }\n\n /** Repaint the controls from the draft: checked scope, pressed chips, counts and the footer. */\n private paint(): void {\n const reason = this.page.scopeReason();\n const group = this.byId('wp-scope-group') as HTMLFieldSetElement | null;\n if (group !== null) group.disabled = reason !== '';\n const reasonEl = this.byId('wp-scope-reason');\n if (reasonEl !== null) {\n reasonEl.textContent = reason;\n reasonEl.hidden = reason === '';\n }\n document.querySelectorAll<HTMLInputElement>('input[name=\"wp-scope\"]').forEach((radio: HTMLInputElement) => {\n radio.checked = radio.value === this.draft.scope;\n });\n document.querySelectorAll<HTMLElement>('[data-wp-scope-count]').forEach((count: HTMLElement) => {\n count.textContent = reason === '' ? String(this.page.scopeCount(count.dataset['wpScopeCount'] ?? '')) : '';\n });\n document.querySelectorAll<HTMLButtonElement>('.wp-chip[data-wp-chip]').forEach((chip: HTMLButtonElement) => {\n const set = this.draft.group(chip.dataset['wpChipGroup'] ?? '');\n chip.setAttribute('aria-pressed', String(set.has(chip.dataset['wpChip'] ?? '')));\n });\n const apply = this.byId('wp-filter-apply');\n if (apply !== null) {\n const shown = this.page.preview(this.draft);\n apply.textContent = `Show ${shown} ${this.page.noun()}${shown === 1 ? '' : 's'}`;\n }\n }\n\n private byId(id: string): HTMLElement | null {\n return document.getElementById(id);\n }\n}\n\n/**\n * The drawer and its floating panels: every control outside the graph itself. Holds no graph state —\n * each control calls back into the page, and `sync()` repaints the controls from the page's state.\n */\nclass GraphDrawer {\n readonly popover: GraphFilterPopover;\n private readonly openers = new Map<string, HTMLElement>();\n\n constructor(private readonly page: GraphPage) {\n this.popover = new GraphFilterPopover(page);\n }\n\n wire(): void {\n this.wireModeMenu();\n this.popover.wire();\n this.wireImpactKinds();\n this.wireLock();\n this.byId('wp-lock-toggle')?.addEventListener('click', () => this.page.toggleLock());\n this.byId('wp-filter-toggle')?.addEventListener('click', () => this.page.toggleFilter());\n this.toggles('wp-collapse', 'wp-shell', true);\n this.toggles('wp-help-btn', 'wp-help', false);\n this.toggles('wp-help-close', 'wp-help', false);\n this.toggles('wp-legend-pop', 'wp-legend-popout', false);\n this.toggles('wp-legend-close', 'wp-legend-popout', false);\n this.toggles('wp-resp-open', 'wp-resp-panel', false);\n this.toggles('wp-resp-close', 'wp-resp-panel', false);\n this.toggles('wp-snapshot-open', 'wp-snapshot', false);\n window.addEventListener('keydown', (ev: KeyboardEvent) => this.onKey(ev), true);\n window.addEventListener('hashchange', () => this.page.setMode(location.hash.slice(1)));\n document.addEventListener('click', (ev: MouseEvent) => {\n const target = ev.target;\n if (target instanceof Node && this.byId('wp-mode-menu')?.parentElement?.contains(target)) return;\n this.closeModeMenu(false);\n this.dismissOutside(target);\n });\n }\n\n /** \"Color by\": the pill trigger opens the menu of four; picking one switches and closes it. */\n private wireModeMenu(): void {\n this.byId('wp-mode-trigger')?.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n const menu = this.byId('wp-mode-menu');\n if (menu === null) return;\n if (!menu.hidden) {\n this.closeModeMenu(false);\n return;\n }\n menu.hidden = false;\n this.byId('wp-mode-trigger')?.setAttribute('aria-expanded', 'true');\n menu.querySelector<HTMLButtonElement>('.wp-mode[aria-checked=\"true\"]')?.focus({ preventScroll: true });\n });\n document.querySelectorAll<HTMLButtonElement>('.wp-mode[data-wp-mode]').forEach((button: HTMLButtonElement) => {\n button.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n this.closeModeMenu(true);\n this.page.setMode(button.dataset['wpMode'] ?? 'runtime');\n });\n });\n }\n\n /** The \"Changed on this branch\" / \"Last commit\" toggle, in the drawer and in the Filter popover. */\n private wireImpactKinds(): void {\n document.querySelectorAll<HTMLButtonElement>('[data-wp-impact-kind]').forEach((button: HTMLButtonElement) => {\n button.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n this.page.setImpactKind(button.dataset['wpImpactKind'] ?? '');\n this.popover.refresh();\n });\n });\n }\n\n /** Shown only when two scans exist; the drawer's copy only while Impact colors the graph. */\n private syncImpactKinds(modes: WpModeState): void {\n document.querySelectorAll<HTMLElement>('[data-wp-impact-kinds]').forEach((group: HTMLElement) => {\n const inDrawer = group.dataset['wpImpactKinds'] === 'drawer';\n group.hidden = modes.scans.length < 2 || (inDrawer && modes.mode !== 'impact');\n });\n document.querySelectorAll<HTMLButtonElement>('[data-wp-impact-kind]').forEach((button: HTMLButtonElement) => {\n const kind = button.dataset['wpImpactKind'] ?? '';\n button.setAttribute('aria-pressed', String(kind === modes.kind));\n button.disabled = !modes.kindAvailable(kind);\n const scan = modes.scans.find((candidate: ImpactJson): boolean => candidate.kind === kind);\n button.title = scan === undefined ? '' : scan.available ? scan.label : scan.reason;\n });\n const legend = this.byId('wp-scope-legend');\n if (legend !== null) legend.textContent = modes.impact?.label ?? 'Changes on this branch';\n }\n\n private closeModeMenu(returnFocus: boolean): void {\n const menu = this.byId('wp-mode-menu');\n if (menu === null || menu.hidden) return;\n menu.hidden = true;\n const trigger = this.byId('wp-mode-trigger');\n trigger?.setAttribute('aria-expanded', 'false');\n if (returnFocus) trigger?.focus({ preventScroll: true });\n }\n\n /** Type-to-search lock: an exact project id (or a unique short name) locks, empty or Esc unlocks. */\n private wireLock(): void {\n const input = this.lockInput();\n if (input === null) return;\n input.addEventListener('input', () => {\n const value = input.value.trim();\n if (value === '') this.page.clearSelection();\n else if (this.page.hasNode(value)) this.page.setLock(value);\n });\n input.addEventListener('change', () => {\n const match = this.page.resolveName(input.value.trim());\n if (match !== null) this.page.setLock(match);\n else input.value = this.page.lockSelection() ?? '';\n });\n input.addEventListener('keydown', (ev: KeyboardEvent) => {\n if (ev.key !== 'Escape') return;\n ev.preventDefault();\n input.value = '';\n this.page.clearSelection();\n input.blur();\n });\n }\n\n /**\n * Page keys, in the CAPTURE phase so the open/closed state of the node menu is read before the\n * menu's own Escape handler closes it: Esc with a menu open only closes the menu. Esc closes an\n * open Color-by menu or Filter popover first, too.\n */\n private onKey(ev: KeyboardEvent): void {\n if (ev.altKey || ev.ctrlKey || ev.metaKey) return;\n if (ev.key === 'Escape' && this.byId('wp-mode-menu')?.hidden === false) {\n this.closeModeMenu(true);\n return;\n }\n if (ev.key === 'Escape' && this.popover.isOpen()) {\n this.popover.close();\n return;\n }\n if (ev.key === 'Escape' && this.dismissOverlay()) return;\n const target = ev.target;\n if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) return;\n const menuOpen = document.getElementById('wp-node-menu') !== null || document.querySelector('.wp-graph-details:not([hidden])') !== null;\n if (ev.key === '/') {\n this.byId('wp-shell')?.classList.remove('wp-collapsed');\n this.byId('wp-collapse')?.setAttribute('aria-expanded', 'true');\n ev.preventDefault();\n this.lockInput()?.focus();\n return;\n }\n const index = ['1', '2', '3', '4'].indexOf(ev.key);\n if (index >= 0 && !menuOpen) {\n this.page.setMode(WpModeState.MODES[index]);\n return;\n }\n if (ev.key === 'Escape' && !menuOpen && this.page.lockSelection() !== null) this.page.setLock(null);\n }\n\n /** `button` shows/hides `target`; for the drawer itself it toggles the collapsed class instead. */\n private toggles(buttonId: string, targetId: string, collapse: boolean): void {\n const button = this.byId(buttonId);\n const target = this.byId(targetId);\n if (button === null || target === null) return;\n button.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n let expanded: boolean;\n if (collapse) {\n expanded = !target.classList.toggle('wp-collapsed');\n } else {\n target.hidden = !target.hidden;\n expanded = !target.hidden;\n if (expanded) this.openers.set(targetId, button);\n else this.openers.get(targetId)?.focus({ preventScroll: true });\n }\n document.querySelectorAll(`[aria-controls=\"${targetId}\"], #${buttonId}[aria-expanded]`).forEach(\n (el: Element) => el.setAttribute('aria-expanded', String(expanded)),\n );\n });\n }\n\n private dismissOverlay(): boolean {\n for (const id of ['wp-help', 'wp-legend-popout', 'wp-snapshot', 'wp-resp-panel']) {\n const panel = this.byId(id);\n if (!panel || panel.hidden) continue;\n panel.hidden = true;\n this.openers.get(id)?.focus({ preventScroll: true });\n this.openers.get(id)?.setAttribute('aria-expanded', 'false');\n return true;\n }\n return false;\n }\n\n private dismissOutside(target: EventTarget | null): void {\n if (!(target instanceof Node)) return;\n const filter = this.byId('wp-filter-pop');\n if (this.popover.isOpen() && !filter?.contains(target) && !this.byId('wp-filter-open')?.contains(target)) this.popover.close();\n for (const entry of this.openers) {\n const id = entry[0];\n const opener = entry[1];\n const panel = this.byId(id);\n if (panel && !panel.hidden && !panel.contains(target) && !opener.contains(target)) {\n panel.hidden = true;\n opener.setAttribute('aria-expanded', 'false');\n }\n }\n }\n\n /** Repaint every control from the page's state. */\n sync(modes: WpModeState, locked: string | null, filtering: boolean, filter: WpFilterChoice): void {\n const reason = modes.impactReason();\n document.querySelectorAll<HTMLButtonElement>('.wp-mode[data-wp-mode]').forEach((button: HTMLButtonElement) => {\n const mode = button.dataset['wpMode'] ?? '';\n button.setAttribute('aria-checked', String(mode === modes.mode));\n button.disabled = !modes.available(mode);\n if (mode === 'impact') button.title = reason === '' ? 'Key 3' : reason;\n if (mode === 'product') button.title = modes.productReason() === '' ? 'Key 4' : modes.productReason();\n });\n this.text('wp-mode-current', modes.name(modes.mode));\n this.text('wp-mode-current-sub', modes.subtitle(modes.mode));\n const reasonEl = this.byId('wp-impact-reason');\n if (reasonEl !== null) {\n reasonEl.textContent = reason;\n reasonEl.hidden = reason === '';\n }\n document.querySelectorAll<HTMLElement>('[data-wp-legend-mode]').forEach((section: HTMLElement) => {\n section.hidden = section.dataset['wpLegendMode'] !== modes.mode;\n });\n document.querySelectorAll<HTMLElement>('[data-wp-impact-note]').forEach((note: HTMLElement) => {\n note.textContent = this.impactNote(modes);\n });\n this.syncImpactKinds(modes);\n const title = this.byId('wp-legend-pop-title');\n if (title !== null) title.textContent = `Legend · ${modes.name(modes.mode)}`;\n const input = this.lockInput();\n if (input !== null && document.activeElement !== input) input.value = this.page.focusSelection() ?? '';\n const lockToggle = this.byId('wp-lock-toggle') as HTMLButtonElement | null;\n if (lockToggle !== null) {\n lockToggle.setAttribute('aria-pressed', String(locked !== null));\n lockToggle.disabled = locked === null && this.page.focusSelection() === null;\n lockToggle.title = lockToggle.disabled ? 'Select a node in Focus first' : '';\n }\n this.syncFilterToggle(locked, filtering);\n this.syncFilter(filter);\n this.crumb(modes.name(modes.mode), locked);\n }\n\n private syncFilterToggle(locked: string | null, filtering: boolean): void {\n const toggle = this.byId('wp-filter-toggle') as HTMLButtonElement | null;\n if (toggle === null) return;\n toggle.setAttribute('aria-pressed', String(filtering));\n toggle.disabled = !filtering && locked === null;\n toggle.title = toggle.disabled ? 'Lock a project first' : '';\n }\n\n /** The drawer button's count badge, and one removable pill per active filter in the top bar. */\n private syncFilter(filter: WpFilterChoice): void {\n const badge = this.byId('wp-filter-badge');\n if (badge !== null) {\n badge.textContent = String(filter.count());\n badge.hidden = filter.count() === 0;\n }\n const pills = this.byId('wp-filter-pills');\n if (pills === null) return;\n const items: HTMLElement[] = [];\n if (filter.scope !== 'everything') items.push(this.pill(this.scopeLabel(filter.scope), 'scope', filter.scope));\n for (const runtime of filter.runtimes) items.push(this.pill(runtime, 'runtime', runtime));\n for (const role of filter.roles) items.push(this.pill(role, 'role', role));\n for (const product of filter.products) items.push(this.pill(`product: ${product}`, 'product', product));\n pills.replaceChildren(...items);\n }\n\n /** A change scope's name, read from the Filter popover's markup: the shell owns the ONE copy. */\n private scopeLabel(scope: string): string {\n return document.querySelector(`[data-wp-scope-label=\"${scope}\"]`)?.textContent ?? scope;\n }\n\n /** A pill, built with text nodes so no value is parsed as HTML. */\n private pill(label: string, group: string, value: string): HTMLElement {\n const pill = document.createElement('span');\n pill.className = 'wp-pill';\n pill.dataset['wpPill'] = `${group}:${value}`;\n pill.append(label);\n const remove = document.createElement('button');\n remove.type = 'button';\n remove.textContent = '✕';\n remove.setAttribute('aria-label', `Remove filter ${label}`);\n remove.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n this.page.removeFilter(group, value);\n });\n pill.append(remove);\n return pill;\n }\n\n private impactNote(modes: WpModeState): string {\n const impact = modes.impact;\n if (impact === null || !impact.available) return '';\n // An available scan with a note is an EMPTY one, e.g. \"Nothing changed on this branch yet\".\n if (impact.reason !== '') return `${impact.label}: ${impact.reason}.`;\n const stats =\n `${impact.label}: ${impact.touched.length} changed · ${impact.affected.length} dependents · ` +\n `${impact.buildInputs.length} dependencies — nx affected, ${impact.changedFiles} changed files.`;\n const cause = this.globalCause(impact);\n return cause === '' ? stats : `${cause}. ${stats}`;\n }\n\n /**\n * When files changed but no project owns one, everything nx affected is affected by a\n * workspace-global input (a lockfile, the workspace manifest). That is correct for CI, and\n * baffling on a graph, so the note names the cause.\n */\n private globalCause(impact: ImpactJson): string {\n if (impact.touched.length > 0 || impact.changedFiles === 0) return '';\n const affected = impact.affected.length;\n const who = affected >= this.page.projectCount() ? 'Every project affected' : `${affected} projects affected`;\n const files = impact.globalFiles;\n if (files.length === 0)\n return `${who}: ${impact.changedFiles} changed files that no project owns (workspace-global input)`;\n const named = files.slice(0, 2).join(', ') + (files.length > 2 ? ` and ${files.length - 2} more` : '');\n return `${who}: ${named} changed (workspace-global input${files.length > 1 ? 's' : ''})`;\n }\n\n /** \"Mode: <b>Runtime</b> · Locked: <b>x</b>\", built with text nodes so no name is parsed as HTML. */\n private crumb(mode: string, locked: string | null): void {\n const crumb = this.byId('wp-crumb');\n if (crumb === null) return;\n const bold = (text: string): HTMLElement => {\n const b = document.createElement('b');\n b.textContent = text;\n return b;\n };\n const parts: (string | Node)[] = ['Mode: ', bold(mode)];\n if (locked !== null) parts.push(' · Locked: ', bold(locked));\n crumb.replaceChildren(...parts);\n }\n\n private text(id: string, value: string): void {\n const el = this.byId(id);\n if (el !== null) el.textContent = value;\n }\n\n private lockInput(): HTMLInputElement | null {\n return document.getElementById('wp-lock') as HTMLInputElement | null;\n }\n\n private byId(id: string): HTMLElement | null {\n return document.getElementById(id);\n }\n}\n\nclass GraphPage extends WpFilterPage {\n private highlighter: GraphHighlighter | null = null;\n private selected: string | null = null;\n private readonly modes = new WpModeState(\n this.model.nodes.some((node: RenderNodeJson): boolean => node.products.length > 0),\n this.model.viewer ?? 'architecture',\n );\n private readonly projects = new WpProjectFilter(this.model, this.modes);\n private applied = new WpFilterChoice();\n private readonly drawer = new GraphDrawer(this);\n\n protected override captureBinding(_svg: SVGSVGElement | null): () => void {\n const previous = this.highlighter;\n return (): void => {\n this.highlighter = previous;\n this.filterCards();\n this.syncControls();\n };\n }\n\n protected override wireControls(): void {\n this.drawer.wire();\n this.syncControls();\n }\n\n protected override nodeDot(node: RenderNodeJson): string {\n const modes = node.modes;\n if (modes === null) return node.dot;\n if (this.modes.mode === 'architecture') return modes.architecture;\n if (this.modes.mode === 'impact') return modes[this.modes.status(node.id)];\n if (this.modes.mode === 'product') return modes.product;\n return modes.runtime;\n }\n\n /** Product mode dashes a dependency that crosses into another product (#1204); every other mode draws it plain. */\n protected override edgeDot(edge: RenderEdgeJson): string {\n if (this.modes.mode === 'product' && edge.productDot !== null) return edge.productDot;\n return edge.dot;\n }\n\n protected override usesFullDot(): boolean {\n return this.modes.mode === 'runtime' && this.applied.count() === 0;\n }\n\n protected override narrow(retained: Set<string>): Set<string> {\n return this.projects.apply(retained, this.applied);\n }\n\n /** Filtering keeps every box in its own L-row: an emptied level stays as a thin labeled band. */\n protected override keepsEmptyLevels(): boolean {\n return true;\n }\n\n protected override prepareSvg(svg: SVGSVGElement): void { window.__WP_RUNTIME__?.prepare(svg); }\n\n protected wireSvg(svg: SVGSVGElement): void {\n this.highlighter = new GraphHighlighter(svg, this.chain, this.model, this);\n this.highlighter.wire();\n this.filterCards();\n this.syncControls();\n svg.querySelectorAll<SVGGElement>('g.node').forEach((node: SVGGElement) => {\n if (node.querySelector('title')?.textContent === this.anchor)\n node.classList.add('wp-filter-anchor');\n });\n }\n\n lockSelection(): string | null {\n return this.locked;\n }\n\n hasNode(id: string): boolean {\n return this.model.nodes.some((node: RenderNodeJson): boolean => node.id === id);\n }\n\n noun(): string { return this.model.viewer === 'runtime' ? 'service' : 'project'; }\n\n projectCount(): number { return this.model.nodes.filter(node => this.projects.isService(node)).length; }\n\n focusSelection(): string | null { return this.selected; }\n\n toggleLock(): void {\n if (this.locked !== null) this.setLock(null);\n else if (this.selected !== null) this.setLock(this.selected);\n }\n\n /** An exact id, else the one id whose short name (after any scope) is `text`; null if none or several. */\n resolveName(text: string): string | null {\n if (text === '') return null;\n if (this.hasNode(text)) return text;\n const matches = this.model.nodes.filter(\n (node: RenderNodeJson): boolean => node.id.split('/').pop() === text,\n );\n return matches.length === 1 ? matches[0].id : null;\n }\n\n setLock(name: string | null): void {\n this.locked = name;\n if (name !== null) this.selected = name;\n this.highlighter?.relight();\n this.filterCards();\n this.syncControls();\n }\n\n clearSelection(): void { this.selected = null; this.setLock(null); }\n\n setMode(mode: string): void {\n if (mode === this.modes.mode || !this.modes.set(mode)) return;\n this.syncControls();\n this.redraw();\n }\n\n /** Switch the active Impact scan: Impact recolours and an active change-scope filter re-applies. */\n setImpactKind(kind: string): void {\n if (kind === this.modes.kind || !this.modes.setKind(kind)) return;\n this.syncControls();\n this.redraw();\n }\n\n /** The drawer's \"Hide unconnected\": filter to the locked box's chain, or turn the filter off. */\n toggleFilter(): void {\n if (this.anchor !== null) this.filter(null);\n else if (this.locked !== null) this.filter(this.locked);\n }\n\n appliedFilter(): WpFilterChoice {\n return this.applied;\n }\n\n /** '' when the change-scope group can be used, else Impact's reason (the group is disabled). */\n scopeReason(): string {\n return this.modes.impactReason();\n }\n\n scopeCount(scope: string): number {\n if (this.model.viewer !== 'runtime') return this.projects.scopeCount(scope);\n const choice = new WpFilterChoice(); choice.scope = scope;\n return this.preview(choice);\n }\n\n /** How many boxes `choice` would show, with the current Hide-unconnected chain. */\n preview(choice: WpFilterChoice): number {\n const base =\n this.anchor === null\n ? new Set(this.model.nodes.map((node: RenderNodeJson): string => node.id))\n : this.chain.nodes(this.anchor);\n const kept = this.projects.apply(base, choice);\n return this.model.nodes.filter(node => kept.has(node.id) && this.projects.isService(node)).length;\n }\n\n applyFilter(choice: WpFilterChoice): void {\n if (this.scopeReason() !== '') choice.scope = 'everything';\n this.applied = choice;\n this.syncControls();\n this.redraw();\n }\n\n /** A top-bar pill's ✕. */\n removeFilter(group: string, value: string): void {\n const next = this.applied.copy();\n if (group === 'scope') next.scope = 'everything';\n else next.group(group).delete(value);\n this.applyFilter(next);\n }\n\n private syncControls(): void {\n this.drawer.sync(this.modes, this.locked, this.anchor !== null, this.applied);\n const count = this.model.nodes.filter(node => this.retained.has(node.id) && this.projects.isService(node)).length;\n const empty = document.getElementById('wp-empty');\n if (empty !== null) empty.hidden = count !== 0;\n const context = document.getElementById('wp-context-count');\n if (context !== null) context.textContent = `${count} services · ${this.retained.size - count} contextual nodes`;\n this.syncLegend();\n }\n\n private syncLegend(): void {\n document.querySelectorAll<HTMLElement>('[data-wp-legend-value]').forEach(row => {\n const group = row.dataset['wpLegendGroup'];\n const value = row.dataset['wpLegendValue'] ?? '';\n row.hidden = !this.model.nodes.some(node => this.retained.has(node.id) &&\n (group === 'runtime' ? (value === 'unknown' ? node.tags !== null && node.tags.frameworks.length === 0 : node.tags?.frameworks.includes(value)) : group === 'role' ? node.tags?.role === value : node.products.includes(value)));\n });\n }\n\n private filterCards(): void {\n const lit = this.locked === null ? this.retained : this.chain.nodes(this.locked);\n document.querySelectorAll('.wp-resp-card').forEach((card: Element) => {\n const name = card.getAttribute('data-node');\n card.classList.toggle(\n 'wp-hidden',\n name === null || !this.retained.has(name) || !lit.has(name),\n );\n });\n }\n}\n\nnew GraphPage(__RENDER_MODEL__).render();\n"]}
|