@webpieces/nx-webpieces-rules 0.3.250 → 0.3.252

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webpieces/nx-webpieces-rules",
3
- "version": "0.3.250",
3
+ "version": "0.3.252",
4
4
  "description": "Nx-specific webpieces validation rules and graph tooling. Bundles all @webpieces rule packages with Nx graph validators and an inference plugin.",
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -21,11 +21,11 @@
21
21
  "README.md"
22
22
  ],
23
23
  "dependencies": {
24
- "@webpieces/ai-hook-rules": "0.3.250",
25
- "@webpieces/code-rules": "0.3.250",
26
- "@webpieces/eslint-rules": "0.3.250",
27
- "@webpieces/pr-gate": "0.3.250",
28
- "@webpieces/rules-config": "0.3.250",
24
+ "@webpieces/ai-hook-rules": "0.3.252",
25
+ "@webpieces/code-rules": "0.3.252",
26
+ "@webpieces/eslint-rules": "0.3.252",
27
+ "@webpieces/pr-gate": "0.3.252",
28
+ "@webpieces/rules-config": "0.3.252",
29
29
  "madge": "8.0.0"
30
30
  },
31
31
  "peerDependencies": {
@@ -85,8 +85,11 @@ export declare abstract class DiDesignBuilder {
85
85
  * Register (or fetch) the node for a class, returning its stable id.
86
86
  * `scopeHint` carries the scope of the module binding the class was reached
87
87
  * through (e.g. bind(TOKEN).to(X).inSingletonScope() where X is not self-bound).
88
+ * `apiType` is the declared param/field type the class was injected as; when it
89
+ * differs from the impl class name it becomes the node's `api` (rendered as the
90
+ * primary box label, with the impl class in parens). Set on first reach.
88
91
  */
89
- protected classNode(cls: ts.ClassDeclaration, scopeHint?: DiScope): string;
92
+ protected classNode(cls: ts.ClassDeclaration, scopeHint?: DiScope, apiType?: string): string;
90
93
  private claimId;
91
94
  /** Scope from the class's own decorator/module binding, if any. */
92
95
  private classScope;
@@ -184,8 +184,11 @@ class DiDesignBuilder {
184
184
  * Register (or fetch) the node for a class, returning its stable id.
185
185
  * `scopeHint` carries the scope of the module binding the class was reached
186
186
  * through (e.g. bind(TOKEN).to(X).inSingletonScope() where X is not self-bound).
187
+ * `apiType` is the declared param/field type the class was injected as; when it
188
+ * differs from the impl class name it becomes the node's `api` (rendered as the
189
+ * primary box label, with the impl class in parens). Set on first reach.
187
190
  */
188
- classNode(cls, scopeHint = 'unknown') {
191
+ classNode(cls, scopeHint = 'unknown', apiType = '') {
189
192
  const existing = this.classIds.get(cls);
190
193
  if (existing)
191
194
  return existing;
@@ -195,7 +198,13 @@ class DiDesignBuilder {
195
198
  this.classIds.set(cls, id);
196
199
  const declaredScope = this.classScope(cls);
197
200
  const scope = declaredScope !== 'unknown' ? declaredScope : scopeHint;
198
- this.design.nodes.push(new model_1.DiNode(id, className, this.rootKindOf(cls), scope, file));
201
+ const node = new model_1.DiNode(id, className, this.rootKindOf(cls), scope, file);
202
+ // Injected AS an API/interface that resolves to a differently-named impl —
203
+ // record the contract (strip a trailing `[]` from multiInject array params).
204
+ const api = apiType.replace(/\[\]$/, '');
205
+ if (api !== '' && api !== className)
206
+ node.api = api;
207
+ this.design.nodes.push(node);
199
208
  return id;
200
209
  }
201
210
  claimId(preferred, file) {
@@ -317,7 +326,7 @@ class DiDesignBuilder {
317
326
  const target = (0, bindings_1.resolveClassDeclaration)(expr, this.checker);
318
327
  if (target) {
319
328
  const classToken = (0, token_resolver_1.classTokenKey)(target, this.workspaceRoot);
320
- const toId = this.classNode(target);
329
+ const toId = this.classNode(target, 'unknown', injection.paramType);
321
330
  this.walkClass(target);
322
331
  this.design.edges.push(new model_1.DiEdge(fromId, toId, 'type', classToken.display, classToken.key, injection.paramName, injection.paramType));
323
332
  return;
@@ -330,7 +339,7 @@ class DiDesignBuilder {
330
339
  }
331
340
  bindingTarget(binding, paramType) {
332
341
  if (binding.implClass) {
333
- const toId = this.classNode(binding.implClass, binding.scope);
342
+ const toId = this.classNode(binding.implClass, binding.scope, paramType);
334
343
  this.walkClass(binding.implClass);
335
344
  return toId;
336
345
  }
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/di-graph/analyzer.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * DI Graph Analyzer (pass 2)\n *\n * Walks constructor injection from a project's root classes down to leaves:\n *\n * - @inject(TOKEN) params → token lookup in the binding table → bound impl\n * - @multiInject(TOKEN) → fan-out edge to EVERY binding of that token\n * - bare typed params → checker resolves the type to a class (inject-by-type)\n * - toConstantValue/toDynamicValue bindings → leaf nodes, no recursion\n * - unresolvable tokens/types → kind \"unresolved\" nodes (generation never fails)\n *\n * Roots: @Controller() classes when the project has any; otherwise every\n * DI-registered class in the project that no other project class injects\n * (the tops of the local DAG).\n */\n\nimport * as ts from 'typescript';\nimport * as path from 'path';\nimport { Binding, DiDesign, DiEdge, DiGraph, DiNode, DiNodeKind, DiScope } from './model';\nimport {\n BindingTable,\n classDecorators,\n collectBindings,\n decoratorCall,\n decoratorName,\n resolveClassDeclaration,\n} from './bindings';\nimport { classTokenKey, relativeFile, resolveTokenKey } from './token-resolver';\n\nconst DI_DECORATORS = new Set(['provideSingleton', 'provideTransient', 'provideSingletonAs', 'injectable']);\n\nexport class ParamInjection {\n expr: ts.Expression | null;\n multi: boolean;\n optional: boolean;\n unmanaged: boolean;\n\n constructor(expr: ts.Expression | null, multi: boolean, optional: boolean, unmanaged: boolean) {\n this.expr = expr;\n this.multi = multi;\n this.optional = optional;\n this.unmanaged = unmanaged;\n }\n}\n\nexport function readParamDecorators(param: ts.ParameterDeclaration): ParamInjection {\n let expr: ts.Expression | null = null;\n let multi = false;\n let optional = false;\n let unmanaged = false;\n for (const decorator of ts.getDecorators(param) ?? []) {\n const name = decoratorName(decorator);\n const call = decoratorCall(decorator);\n if (name === 'inject' && call?.arguments[0]) {\n expr = call.arguments[0];\n } else if (name === 'multiInject' && call?.arguments[0]) {\n expr = call.arguments[0];\n multi = true;\n } else if (name === 'optional') {\n optional = true;\n } else if (name === 'unmanaged') {\n unmanaged = true;\n }\n }\n return new ParamInjection(expr, multi, optional, unmanaged);\n}\n\nfunction hasDecoratorNamed(cls: ts.ClassDeclaration, names: Set<string>): boolean {\n for (const decorator of classDecorators(cls)) {\n const name = decoratorName(decorator);\n if (name && names.has(name)) return true;\n }\n return false;\n}\n\nexport function isControllerClass(cls: ts.ClassDeclaration): boolean {\n return hasDecoratorNamed(cls, new Set(['Controller']));\n}\n\nfunction isDiRegisteredClass(cls: ts.ClassDeclaration): boolean {\n return hasDecoratorNamed(cls, DI_DECORATORS);\n}\n\nexport function findConstructor(cls: ts.ClassDeclaration): ts.ConstructorDeclaration | null {\n for (const member of cls.members) {\n if (ts.isConstructorDeclaration(member) && member.body) return member;\n if (ts.isConstructorDeclaration(member)) return member;\n }\n return null;\n}\n\n/** All class declarations in files under the project root. */\nexport function projectClasses(\n program: ts.Program,\n workspaceRoot: string,\n projectRoot: string,\n): ts.ClassDeclaration[] {\n const prefix = projectRoot.endsWith('/') ? projectRoot : projectRoot + '/';\n const classes: ts.ClassDeclaration[] = [];\n for (const sourceFile of program.getSourceFiles()) {\n if (sourceFile.isDeclarationFile) continue;\n const rel = relativeFile(workspaceRoot, sourceFile);\n if (!rel.startsWith(prefix)) continue;\n const visit = (node: ts.Node): void => {\n if (ts.isClassDeclaration(node) && node.name) classes.push(node);\n ts.forEachChild(node, visit);\n };\n visit(sourceFile);\n }\n return classes;\n}\n\n/**\n * One normalized injection site, framework-agnostic — produced by a builder's\n * `collectInjections(cls)` hook and processed by the shared base. Inversify\n * emits `token`/`type` from constructor params; Angular emits `angularToken`\n * from constructor params AND `inject()` field initializers.\n *\n * Modes:\n * - `token` Inversify `@inject`/`@multiInject`: table lookup; an unbound\n * token becomes an `unresolved` node (no class fallback).\n * - `type` Inversify bare typed param: resolve the declared TYPE to a\n * class (inject-by-type); no table lookup.\n * - `angularToken` Angular `inject(T)` / `@Inject(T)` / bare typed ctor param:\n * table lookup FIRST (provider table), then fall back to\n * resolving the token expression as a class, else unresolved.\n */\nexport class Injection {\n mode: 'token' | 'type' | 'angularToken';\n /** Token/type expression (modes `token`/`angularToken`, or the type identifier for `type`). */\n expr: ts.Expression | ts.Identifier | null;\n multi: boolean;\n optional: boolean;\n paramName: string;\n paramType: string;\n\n constructor(\n mode: 'token' | 'type' | 'angularToken',\n expr: ts.Expression | ts.Identifier | null,\n paramName: string,\n paramType: string,\n multi = false,\n optional = false,\n ) {\n this.mode = mode;\n this.expr = expr;\n this.paramName = paramName;\n this.paramType = paramType;\n this.multi = multi;\n this.optional = optional;\n }\n}\n\n/**\n * Builds ONE self-contained `DiDesign` for a single root. A fresh instance is\n * created per root so its maps (visited/classIds/usedIds/...) are scoped to\n * that root's tree — a dependency shared by two roots is therefore walked\n * (and duplicated) into each root's design, not hidden under whichever root\n * reached it first.\n *\n * Framework-agnostic base: subclasses implement {@link collectInjections} (and\n * override {@link rootKindOf} for Angular components); everything else — node\n * ids, leaf/unresolved labeling, token→binding resolution, factory-dep edges,\n * level assignment — is shared so Inversify and Angular render identically.\n */\nexport abstract class DiDesignBuilder {\n protected readonly checker: ts.TypeChecker;\n protected readonly table: BindingTable;\n protected readonly workspaceRoot: string;\n protected readonly design: DiDesign;\n private readonly classIds = new Map<ts.ClassDeclaration, string>();\n private readonly leafIds = new Map<Binding, string>();\n private readonly unresolvedIds = new Map<string, string>();\n private readonly usedIds = new Set<string>();\n private readonly visited = new Set<ts.ClassDeclaration>();\n\n constructor(checker: ts.TypeChecker, table: BindingTable, workspaceRoot: string, design: DiDesign) {\n this.checker = checker;\n this.table = table;\n this.workspaceRoot = workspaceRoot;\n this.design = design;\n }\n\n /** Collect the injection sites for one class (constructor params, field inject(), ...). */\n protected abstract collectInjections(cls: ts.ClassDeclaration): Injection[];\n\n /** Node kind for a root/reached class — `controller` (Inversify) or `component` (Angular). */\n protected rootKindOf(cls: ts.ClassDeclaration): DiNodeKind {\n return isControllerClass(cls) ? 'controller' : 'class';\n }\n\n addRoot(cls: ts.ClassDeclaration): void {\n const id = this.classNode(cls);\n this.design.root = id;\n this.walkClass(cls);\n }\n\n /**\n * Register (or fetch) the node for a class, returning its stable id.\n * `scopeHint` carries the scope of the module binding the class was reached\n * through (e.g. bind(TOKEN).to(X).inSingletonScope() where X is not self-bound).\n */\n protected classNode(cls: ts.ClassDeclaration, scopeHint: DiScope = 'unknown'): string {\n const existing = this.classIds.get(cls);\n if (existing) return existing;\n\n const className = cls.name ? cls.name.text : '<anonymous>';\n const file = relativeFile(this.workspaceRoot, cls.getSourceFile());\n const id = this.claimId(className, file);\n this.classIds.set(cls, id);\n\n const declaredScope = this.classScope(cls);\n const scope = declaredScope !== 'unknown' ? declaredScope : scopeHint;\n this.design.nodes.push(new DiNode(id, className, this.rootKindOf(cls), scope, file));\n return id;\n }\n\n private claimId(preferred: string, file: string): string {\n if (!this.usedIds.has(preferred)) {\n this.usedIds.add(preferred);\n return preferred;\n }\n const disambiguated = `${preferred}@${path.posix.dirname(file)}`;\n let id = disambiguated;\n let n = 2;\n while (this.usedIds.has(id)) {\n id = `${disambiguated}~${n}`;\n n++;\n }\n this.usedIds.add(id);\n return id;\n }\n\n /** Scope from the class's own decorator/module binding, if any. */\n private classScope(cls: ts.ClassDeclaration): DiScope {\n const token = classTokenKey(cls, this.workspaceRoot);\n for (const binding of this.table.lookup(token.key)) {\n if (binding.scope !== 'unknown') return binding.scope;\n }\n return 'unknown';\n }\n\n /**\n * Leaf box for a constant/dynamic binding. B0: the box is labeled by the\n * DECLARED param TYPE (e.g. `FirestoreConfig`, `ClientConfig`) — the DI\n * contract — while the bound expression (`buildConfigFromEnv(...)` /\n * `TOKEN (dynamic)`) is kept as `detail`. A dynamic leaf also fans out to\n * each of its `useFactory` `deps` (Angular; empty for Inversify).\n */\n private leafNode(binding: Binding, kind: DiNodeKind, paramType: string): string {\n const existing = this.leafIds.get(binding);\n if (existing) return existing;\n\n const detail = kind === 'dynamic' ? `${binding.tokenDisplay} (dynamic)` : binding.valueText;\n const className = paramType !== '' ? paramType : detail !== '' ? detail : binding.tokenDisplay;\n const id = this.claimId(className, binding.file);\n this.leafIds.set(binding, id);\n this.design.nodes.push(new DiNode(id, className, kind, binding.scope, binding.file, 0, detail));\n if (kind === 'dynamic') this.expandFactoryDeps(id, binding);\n return id;\n }\n\n /** Edges from a `useFactory` leaf to each declared `deps: [...]` token (Angular). */\n private expandFactoryDeps(leafId: string, binding: Binding): void {\n for (const dep of binding.factoryDeps) {\n const bindings = this.table.lookup(dep.key);\n if (bindings.length > 0) {\n for (const depBinding of bindings) {\n // The dep token IS the declared type — label the box with it.\n const toId = this.bindingTarget(depBinding, dep.display);\n this.design.edges.push(new DiEdge(leafId, toId, 'type', dep.display, dep.key, dep.display, dep.display));\n }\n } else {\n const toId = this.unresolvedNode(dep.display, binding.file, '');\n this.design.edges.push(new DiEdge(leafId, toId, 'type', dep.display, dep.key, dep.display, dep.display));\n }\n }\n }\n\n /**\n * `unresolved` placeholder box. B0: labeled by the declared param TYPE\n * (`className`) with the resolving token expression kept as `detail` (and\n * surfaced in `design.unresolved` for diagnostics).\n */\n private unresolvedNode(className: string, file: string, detail: string): string {\n const key = `${className}|${detail}|${file}`;\n const existing = this.unresolvedIds.get(key);\n if (existing) return existing;\n\n const id = this.claimId(className, file);\n this.unresolvedIds.set(key, id);\n this.design.nodes.push(new DiNode(id, className, 'unresolved', 'unknown', file, 0, detail !== className ? detail : ''));\n this.design.unresolved.push(detail !== '' ? detail : className);\n return id;\n }\n\n protected walkClass(cls: ts.ClassDeclaration): void {\n if (this.visited.has(cls)) return;\n this.visited.add(cls);\n\n const fromId = this.classNode(cls);\n for (const injection of this.collectInjections(cls)) {\n this.processInjection(fromId, cls, injection);\n }\n }\n\n /** Resolve one injection to a node and record the edge(s). Never throws. */\n private processInjection(fromId: string, cls: ts.ClassDeclaration, injection: Injection): void {\n if (injection.mode === 'type') {\n this.processTypeInjection(fromId, cls, injection);\n } else {\n this.processTokenInjection(fromId, cls, injection);\n }\n }\n\n /** Inversify `@inject`/`@multiInject` and Angular `inject()`/`@Inject`/bare token. */\n private processTokenInjection(fromId: string, cls: ts.ClassDeclaration, injection: Injection): void {\n const expr = injection.expr;\n if (!expr) return;\n const token = resolveTokenKey(expr, this.checker, this.workspaceRoot);\n const kind = injection.multi ? 'multiInject' : 'token';\n const bindings = this.table.lookup(token.key);\n\n if (bindings.length > 0) {\n for (const binding of bindings) {\n const toId = this.bindingTarget(binding, injection.paramType);\n this.design.edges.push(\n new DiEdge(fromId, toId, kind, token.display, token.key, injection.paramName, injection.paramType),\n );\n }\n return;\n }\n\n // @multiInject @optional with zero bindings is legal — no edge, no error.\n if (injection.multi && injection.optional) return;\n\n // Angular: a token with no explicit provider may still be a bare @Injectable\n // class — resolve the token expression as a class and inject it by type.\n if (injection.mode === 'angularToken') {\n const target = resolveClassDeclaration(expr, this.checker);\n if (target) {\n const classToken = classTokenKey(target, this.workspaceRoot);\n const toId = this.classNode(target);\n this.walkClass(target);\n this.design.edges.push(\n new DiEdge(fromId, toId, 'type', classToken.display, classToken.key, injection.paramName, injection.paramType),\n );\n return;\n }\n }\n\n const file = relativeFile(this.workspaceRoot, cls.getSourceFile());\n const label = injection.paramType !== '' ? injection.paramType : token.display;\n const toId = this.unresolvedNode(label, file, token.display);\n this.design.edges.push(\n new DiEdge(fromId, toId, kind, token.display, token.key, injection.paramName, injection.paramType),\n );\n }\n\n private bindingTarget(binding: Binding, paramType: string): string {\n if (binding.implClass) {\n const toId = this.classNode(binding.implClass, binding.scope);\n this.walkClass(binding.implClass);\n return toId;\n }\n if (binding.kind === 'toConstantValue') return this.leafNode(binding, 'constant', paramType);\n if (binding.kind === 'toDynamicValue') return this.leafNode(binding, 'dynamic', paramType);\n // .to(X) where X did not resolve to a class declaration.\n const detail = binding.valueText !== '' ? binding.valueText : binding.tokenDisplay;\n const label = paramType !== '' ? paramType : detail;\n return this.unresolvedNode(label, binding.file, detail);\n }\n\n /** Inversify bare typed param — resolve the declared type directly to a class. */\n private processTypeInjection(fromId: string, cls: ts.ClassDeclaration, injection: Injection): void {\n const typeRef = injection.expr && ts.isIdentifier(injection.expr) ? injection.expr : null;\n const target = typeRef ? resolveClassDeclaration(typeRef, this.checker) : null;\n\n if (target) {\n const token = classTokenKey(target, this.workspaceRoot);\n const toId = this.classNode(target);\n this.walkClass(target);\n this.design.edges.push(\n new DiEdge(fromId, toId, 'type', token.display, token.key, injection.paramName, injection.paramType),\n );\n return;\n }\n\n // Bare param whose type is not a resolvable class (interface, primitive, etc.).\n const file = relativeFile(this.workspaceRoot, cls.getSourceFile());\n const label = injection.paramType !== '' ? injection.paramType : injection.paramName;\n const toId = this.unresolvedNode(label, file, '');\n this.design.edges.push(\n new DiEdge(fromId, toId, 'type', injection.paramType, `type:${injection.paramType}`, injection.paramName, injection.paramType),\n );\n }\n}\n\n/**\n * Inversify builder: injection sites are constructor params — `@inject`/\n * `@multiInject` tokens or bare typed (inject-by-type) params.\n */\nexport class InversifyDesignBuilder extends DiDesignBuilder {\n protected collectInjections(cls: ts.ClassDeclaration): Injection[] {\n const ctor = findConstructor(cls);\n if (!ctor) return [];\n\n const injections: Injection[] = [];\n for (const param of ctor.parameters) {\n const decorated = readParamDecorators(param);\n if (decorated.unmanaged) continue;\n\n const paramName = ts.isIdentifier(param.name) ? param.name.text : param.name.getText();\n const paramType = param.type ? param.type.getText() : '';\n\n if (decorated.expr) {\n injections.push(\n new Injection('token', decorated.expr, paramName, paramType, decorated.multi, decorated.optional),\n );\n } else {\n const typeRef =\n param.type && ts.isTypeReferenceNode(param.type) && ts.isIdentifier(param.type.typeName)\n ? param.type.typeName\n : null;\n injections.push(new Injection('type', typeRef, paramName, paramType));\n }\n }\n return injections;\n }\n}\n\nexport function byClassName(a: ts.ClassDeclaration, b: ts.ClassDeclaration): number {\n const nameA = a.name ? a.name.text : '';\n const nameB = b.name ? b.name.text : '';\n if (nameA !== nameB) return nameA < nameB ? -1 : 1;\n return a.getSourceFile().fileName < b.getSourceFile().fileName ? -1 : 1;\n}\n\n/**\n * Library-project roots: DI-registered classes in the project that no other\n * project class injects (tops of the local DAG).\n */\nfunction findLibraryRoots(\n classes: ts.ClassDeclaration[],\n checker: ts.TypeChecker,\n table: BindingTable,\n workspaceRoot: string,\n): ts.ClassDeclaration[] {\n const diClasses = classes.filter((cls: ts.ClassDeclaration) => isDiRegisteredClass(cls));\n const injected = new Set<ts.ClassDeclaration>();\n\n for (const cls of diClasses) {\n const ctor = findConstructor(cls);\n for (const param of ctor?.parameters ?? []) {\n const injection = readParamDecorators(param);\n if (injection.unmanaged) continue;\n if (injection.expr) {\n const token = resolveTokenKey(injection.expr, checker, workspaceRoot);\n for (const binding of table.lookup(token.key)) {\n if (binding.implClass) injected.add(binding.implClass);\n }\n } else if (param.type && ts.isTypeReferenceNode(param.type) && ts.isIdentifier(param.type.typeName)) {\n const target = resolveClassDeclaration(param.type.typeName, checker);\n if (target) injected.add(target);\n }\n }\n }\n\n return diClasses.filter((cls: ts.ClassDeclaration) => !injected.has(cls));\n}\n\n/**\n * Assign each node its LONGEST-path depth from the design's root (root = level\n * 0, its direct injections = level 1, ...) and record the deepest level. A node\n * reached from multiple parents takes its DEEPEST depth, so it always sits below\n * everything that depends on it (a dependency is never on the same or a shallower\n * level than its dependent — e.g. a config injected by both a level-2 service and\n * a level-3 client lands at level 4, one below that client). Levels are computed\n * by edge relaxation bounded by the reachable node count, which terminates even\n * if the DI graph contains a cycle; the root is pinned at 0.\n */\nexport function assignLevels(design: DiDesign): void {\n const outgoing = new Map<string, string[]>();\n for (const e of design.edges) {\n const list = outgoing.get(e.from) ?? [];\n list.push(e.to);\n outgoing.set(e.from, list);\n }\n\n // Nodes reachable from the root — only these get a level; the rest fall back\n // to 0 below, matching the previous behaviour for disconnected nodes.\n const reachable = new Set<string>();\n const queue = [design.root];\n for (let i = 0; i < queue.length; i++) {\n const id = queue[i];\n if (reachable.has(id)) continue;\n reachable.add(id);\n for (const to of outgoing.get(id) ?? []) {\n if (!reachable.has(to)) queue.push(to);\n }\n }\n\n const levelById = new Map<string, number>();\n for (const id of reachable) levelById.set(id, 0);\n // Bellman-Ford-style longest-path relaxation. |reachable| passes suffice for\n // any acyclic graph; the pass count also bounds work if a cycle exists.\n for (let pass = 0; pass < reachable.size; pass++) {\n let changed = false;\n for (const e of design.edges) {\n if (!reachable.has(e.from) || e.to === design.root) continue;\n const candidate = (levelById.get(e.from) ?? 0) + 1;\n if (candidate > (levelById.get(e.to) ?? 0)) {\n levelById.set(e.to, candidate);\n changed = true;\n }\n }\n if (!changed) break;\n }\n\n let maxLevel = 0;\n for (const node of design.nodes) {\n node.level = levelById.get(node.id) ?? 0;\n if (node.level > maxLevel) maxLevel = node.level;\n }\n design.maxLevel = maxLevel;\n}\n\n/**\n * Build one self-contained downward design tree for a single root class, using\n * the builder produced by `makeBuilder` (Inversify or Angular). `rootKind` is\n * the node kind for the root box (`controller`/`component`/`class`).\n */\nexport function buildDesign(\n root: ts.ClassDeclaration,\n rootKind: DiNodeKind,\n workspaceRoot: string,\n makeBuilder: (design: DiDesign) => DiDesignBuilder,\n): DiDesign {\n const className = root.name ? root.name.text : '<anonymous>';\n const file = relativeFile(workspaceRoot, root.getSourceFile());\n const design = new DiDesign(className, rootKind, file);\n makeBuilder(design).addRoot(root);\n assignLevels(design);\n return design;\n}\n\n/**\n * Build the full Inversify DI graph for one project: one self-contained\n * `DiDesign` per @Controller root. `projectRoot` is workspace-relative.\n *\n * `includeLibraryRoots` (default false, the v1 executor path) roots ONLY on\n * @Controller classes; when true, a controller-less project falls back to its\n * top-of-DAG DI classes (the deferred library behavior, still unit-tested).\n */\nexport function buildDiGraph(\n program: ts.Program,\n workspaceRoot: string,\n projectRoot: string,\n projectName: string,\n includeLibraryRoots = false,\n): DiGraph {\n const checker = program.getTypeChecker();\n const table = collectBindings(program, checker, workspaceRoot);\n const graph = new DiGraph(projectName);\n\n const classes = projectClasses(program, workspaceRoot, projectRoot);\n const controllers = classes.filter((cls: ts.ClassDeclaration) => isControllerClass(cls));\n const roots =\n controllers.length > 0\n ? controllers\n : includeLibraryRoots\n ? findLibraryRoots(classes, checker, table, workspaceRoot)\n : [];\n\n for (const root of [...roots].sort(byClassName)) {\n const rootKind: DiNodeKind = isControllerClass(root) ? 'controller' : 'class';\n graph.designs.push(\n buildDesign(\n root,\n rootKind,\n workspaceRoot,\n (design: DiDesign) => new InversifyDesignBuilder(checker, table, workspaceRoot, design),\n ),\n );\n }\n\n return graph;\n}\n"]}
1
+ {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/di-graph/analyzer.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * DI Graph Analyzer (pass 2)\n *\n * Walks constructor injection from a project's root classes down to leaves:\n *\n * - @inject(TOKEN) params → token lookup in the binding table → bound impl\n * - @multiInject(TOKEN) → fan-out edge to EVERY binding of that token\n * - bare typed params → checker resolves the type to a class (inject-by-type)\n * - toConstantValue/toDynamicValue bindings → leaf nodes, no recursion\n * - unresolvable tokens/types → kind \"unresolved\" nodes (generation never fails)\n *\n * Roots: @Controller() classes when the project has any; otherwise every\n * DI-registered class in the project that no other project class injects\n * (the tops of the local DAG).\n */\n\nimport * as ts from 'typescript';\nimport * as path from 'path';\nimport { Binding, DiDesign, DiEdge, DiGraph, DiNode, DiNodeKind, DiScope } from './model';\nimport {\n BindingTable,\n classDecorators,\n collectBindings,\n decoratorCall,\n decoratorName,\n resolveClassDeclaration,\n} from './bindings';\nimport { classTokenKey, relativeFile, resolveTokenKey } from './token-resolver';\n\nconst DI_DECORATORS = new Set(['provideSingleton', 'provideTransient', 'provideSingletonAs', 'injectable']);\n\nexport class ParamInjection {\n expr: ts.Expression | null;\n multi: boolean;\n optional: boolean;\n unmanaged: boolean;\n\n constructor(expr: ts.Expression | null, multi: boolean, optional: boolean, unmanaged: boolean) {\n this.expr = expr;\n this.multi = multi;\n this.optional = optional;\n this.unmanaged = unmanaged;\n }\n}\n\nexport function readParamDecorators(param: ts.ParameterDeclaration): ParamInjection {\n let expr: ts.Expression | null = null;\n let multi = false;\n let optional = false;\n let unmanaged = false;\n for (const decorator of ts.getDecorators(param) ?? []) {\n const name = decoratorName(decorator);\n const call = decoratorCall(decorator);\n if (name === 'inject' && call?.arguments[0]) {\n expr = call.arguments[0];\n } else if (name === 'multiInject' && call?.arguments[0]) {\n expr = call.arguments[0];\n multi = true;\n } else if (name === 'optional') {\n optional = true;\n } else if (name === 'unmanaged') {\n unmanaged = true;\n }\n }\n return new ParamInjection(expr, multi, optional, unmanaged);\n}\n\nfunction hasDecoratorNamed(cls: ts.ClassDeclaration, names: Set<string>): boolean {\n for (const decorator of classDecorators(cls)) {\n const name = decoratorName(decorator);\n if (name && names.has(name)) return true;\n }\n return false;\n}\n\nexport function isControllerClass(cls: ts.ClassDeclaration): boolean {\n return hasDecoratorNamed(cls, new Set(['Controller']));\n}\n\nfunction isDiRegisteredClass(cls: ts.ClassDeclaration): boolean {\n return hasDecoratorNamed(cls, DI_DECORATORS);\n}\n\nexport function findConstructor(cls: ts.ClassDeclaration): ts.ConstructorDeclaration | null {\n for (const member of cls.members) {\n if (ts.isConstructorDeclaration(member) && member.body) return member;\n if (ts.isConstructorDeclaration(member)) return member;\n }\n return null;\n}\n\n/** All class declarations in files under the project root. */\nexport function projectClasses(\n program: ts.Program,\n workspaceRoot: string,\n projectRoot: string,\n): ts.ClassDeclaration[] {\n const prefix = projectRoot.endsWith('/') ? projectRoot : projectRoot + '/';\n const classes: ts.ClassDeclaration[] = [];\n for (const sourceFile of program.getSourceFiles()) {\n if (sourceFile.isDeclarationFile) continue;\n const rel = relativeFile(workspaceRoot, sourceFile);\n if (!rel.startsWith(prefix)) continue;\n const visit = (node: ts.Node): void => {\n if (ts.isClassDeclaration(node) && node.name) classes.push(node);\n ts.forEachChild(node, visit);\n };\n visit(sourceFile);\n }\n return classes;\n}\n\n/**\n * One normalized injection site, framework-agnostic — produced by a builder's\n * `collectInjections(cls)` hook and processed by the shared base. Inversify\n * emits `token`/`type` from constructor params; Angular emits `angularToken`\n * from constructor params AND `inject()` field initializers.\n *\n * Modes:\n * - `token` Inversify `@inject`/`@multiInject`: table lookup; an unbound\n * token becomes an `unresolved` node (no class fallback).\n * - `type` Inversify bare typed param: resolve the declared TYPE to a\n * class (inject-by-type); no table lookup.\n * - `angularToken` Angular `inject(T)` / `@Inject(T)` / bare typed ctor param:\n * table lookup FIRST (provider table), then fall back to\n * resolving the token expression as a class, else unresolved.\n */\nexport class Injection {\n mode: 'token' | 'type' | 'angularToken';\n /** Token/type expression (modes `token`/`angularToken`, or the type identifier for `type`). */\n expr: ts.Expression | ts.Identifier | null;\n multi: boolean;\n optional: boolean;\n paramName: string;\n paramType: string;\n\n constructor(\n mode: 'token' | 'type' | 'angularToken',\n expr: ts.Expression | ts.Identifier | null,\n paramName: string,\n paramType: string,\n multi = false,\n optional = false,\n ) {\n this.mode = mode;\n this.expr = expr;\n this.paramName = paramName;\n this.paramType = paramType;\n this.multi = multi;\n this.optional = optional;\n }\n}\n\n/**\n * Builds ONE self-contained `DiDesign` for a single root. A fresh instance is\n * created per root so its maps (visited/classIds/usedIds/...) are scoped to\n * that root's tree — a dependency shared by two roots is therefore walked\n * (and duplicated) into each root's design, not hidden under whichever root\n * reached it first.\n *\n * Framework-agnostic base: subclasses implement {@link collectInjections} (and\n * override {@link rootKindOf} for Angular components); everything else — node\n * ids, leaf/unresolved labeling, token→binding resolution, factory-dep edges,\n * level assignment — is shared so Inversify and Angular render identically.\n */\nexport abstract class DiDesignBuilder {\n protected readonly checker: ts.TypeChecker;\n protected readonly table: BindingTable;\n protected readonly workspaceRoot: string;\n protected readonly design: DiDesign;\n private readonly classIds = new Map<ts.ClassDeclaration, string>();\n private readonly leafIds = new Map<Binding, string>();\n private readonly unresolvedIds = new Map<string, string>();\n private readonly usedIds = new Set<string>();\n private readonly visited = new Set<ts.ClassDeclaration>();\n\n constructor(checker: ts.TypeChecker, table: BindingTable, workspaceRoot: string, design: DiDesign) {\n this.checker = checker;\n this.table = table;\n this.workspaceRoot = workspaceRoot;\n this.design = design;\n }\n\n /** Collect the injection sites for one class (constructor params, field inject(), ...). */\n protected abstract collectInjections(cls: ts.ClassDeclaration): Injection[];\n\n /** Node kind for a root/reached class — `controller` (Inversify) or `component` (Angular). */\n protected rootKindOf(cls: ts.ClassDeclaration): DiNodeKind {\n return isControllerClass(cls) ? 'controller' : 'class';\n }\n\n addRoot(cls: ts.ClassDeclaration): void {\n const id = this.classNode(cls);\n this.design.root = id;\n this.walkClass(cls);\n }\n\n /**\n * Register (or fetch) the node for a class, returning its stable id.\n * `scopeHint` carries the scope of the module binding the class was reached\n * through (e.g. bind(TOKEN).to(X).inSingletonScope() where X is not self-bound).\n * `apiType` is the declared param/field type the class was injected as; when it\n * differs from the impl class name it becomes the node's `api` (rendered as the\n * primary box label, with the impl class in parens). Set on first reach.\n */\n protected classNode(cls: ts.ClassDeclaration, scopeHint: DiScope = 'unknown', apiType = ''): string {\n const existing = this.classIds.get(cls);\n if (existing) return existing;\n\n const className = cls.name ? cls.name.text : '<anonymous>';\n const file = relativeFile(this.workspaceRoot, cls.getSourceFile());\n const id = this.claimId(className, file);\n this.classIds.set(cls, id);\n\n const declaredScope = this.classScope(cls);\n const scope = declaredScope !== 'unknown' ? declaredScope : scopeHint;\n const node = new DiNode(id, className, this.rootKindOf(cls), scope, file);\n // Injected AS an API/interface that resolves to a differently-named impl —\n // record the contract (strip a trailing `[]` from multiInject array params).\n const api = apiType.replace(/\\[\\]$/, '');\n if (api !== '' && api !== className) node.api = api;\n this.design.nodes.push(node);\n return id;\n }\n\n private claimId(preferred: string, file: string): string {\n if (!this.usedIds.has(preferred)) {\n this.usedIds.add(preferred);\n return preferred;\n }\n const disambiguated = `${preferred}@${path.posix.dirname(file)}`;\n let id = disambiguated;\n let n = 2;\n while (this.usedIds.has(id)) {\n id = `${disambiguated}~${n}`;\n n++;\n }\n this.usedIds.add(id);\n return id;\n }\n\n /** Scope from the class's own decorator/module binding, if any. */\n private classScope(cls: ts.ClassDeclaration): DiScope {\n const token = classTokenKey(cls, this.workspaceRoot);\n for (const binding of this.table.lookup(token.key)) {\n if (binding.scope !== 'unknown') return binding.scope;\n }\n return 'unknown';\n }\n\n /**\n * Leaf box for a constant/dynamic binding. B0: the box is labeled by the\n * DECLARED param TYPE (e.g. `FirestoreConfig`, `ClientConfig`) — the DI\n * contract — while the bound expression (`buildConfigFromEnv(...)` /\n * `TOKEN (dynamic)`) is kept as `detail`. A dynamic leaf also fans out to\n * each of its `useFactory` `deps` (Angular; empty for Inversify).\n */\n private leafNode(binding: Binding, kind: DiNodeKind, paramType: string): string {\n const existing = this.leafIds.get(binding);\n if (existing) return existing;\n\n const detail = kind === 'dynamic' ? `${binding.tokenDisplay} (dynamic)` : binding.valueText;\n const className = paramType !== '' ? paramType : detail !== '' ? detail : binding.tokenDisplay;\n const id = this.claimId(className, binding.file);\n this.leafIds.set(binding, id);\n this.design.nodes.push(new DiNode(id, className, kind, binding.scope, binding.file, 0, detail));\n if (kind === 'dynamic') this.expandFactoryDeps(id, binding);\n return id;\n }\n\n /** Edges from a `useFactory` leaf to each declared `deps: [...]` token (Angular). */\n private expandFactoryDeps(leafId: string, binding: Binding): void {\n for (const dep of binding.factoryDeps) {\n const bindings = this.table.lookup(dep.key);\n if (bindings.length > 0) {\n for (const depBinding of bindings) {\n // The dep token IS the declared type — label the box with it.\n const toId = this.bindingTarget(depBinding, dep.display);\n this.design.edges.push(new DiEdge(leafId, toId, 'type', dep.display, dep.key, dep.display, dep.display));\n }\n } else {\n const toId = this.unresolvedNode(dep.display, binding.file, '');\n this.design.edges.push(new DiEdge(leafId, toId, 'type', dep.display, dep.key, dep.display, dep.display));\n }\n }\n }\n\n /**\n * `unresolved` placeholder box. B0: labeled by the declared param TYPE\n * (`className`) with the resolving token expression kept as `detail` (and\n * surfaced in `design.unresolved` for diagnostics).\n */\n private unresolvedNode(className: string, file: string, detail: string): string {\n const key = `${className}|${detail}|${file}`;\n const existing = this.unresolvedIds.get(key);\n if (existing) return existing;\n\n const id = this.claimId(className, file);\n this.unresolvedIds.set(key, id);\n this.design.nodes.push(new DiNode(id, className, 'unresolved', 'unknown', file, 0, detail !== className ? detail : ''));\n this.design.unresolved.push(detail !== '' ? detail : className);\n return id;\n }\n\n protected walkClass(cls: ts.ClassDeclaration): void {\n if (this.visited.has(cls)) return;\n this.visited.add(cls);\n\n const fromId = this.classNode(cls);\n for (const injection of this.collectInjections(cls)) {\n this.processInjection(fromId, cls, injection);\n }\n }\n\n /** Resolve one injection to a node and record the edge(s). Never throws. */\n private processInjection(fromId: string, cls: ts.ClassDeclaration, injection: Injection): void {\n if (injection.mode === 'type') {\n this.processTypeInjection(fromId, cls, injection);\n } else {\n this.processTokenInjection(fromId, cls, injection);\n }\n }\n\n /** Inversify `@inject`/`@multiInject` and Angular `inject()`/`@Inject`/bare token. */\n private processTokenInjection(fromId: string, cls: ts.ClassDeclaration, injection: Injection): void {\n const expr = injection.expr;\n if (!expr) return;\n const token = resolveTokenKey(expr, this.checker, this.workspaceRoot);\n const kind = injection.multi ? 'multiInject' : 'token';\n const bindings = this.table.lookup(token.key);\n\n if (bindings.length > 0) {\n for (const binding of bindings) {\n const toId = this.bindingTarget(binding, injection.paramType);\n this.design.edges.push(\n new DiEdge(fromId, toId, kind, token.display, token.key, injection.paramName, injection.paramType),\n );\n }\n return;\n }\n\n // @multiInject @optional with zero bindings is legal — no edge, no error.\n if (injection.multi && injection.optional) return;\n\n // Angular: a token with no explicit provider may still be a bare @Injectable\n // class — resolve the token expression as a class and inject it by type.\n if (injection.mode === 'angularToken') {\n const target = resolveClassDeclaration(expr, this.checker);\n if (target) {\n const classToken = classTokenKey(target, this.workspaceRoot);\n const toId = this.classNode(target, 'unknown', injection.paramType);\n this.walkClass(target);\n this.design.edges.push(\n new DiEdge(fromId, toId, 'type', classToken.display, classToken.key, injection.paramName, injection.paramType),\n );\n return;\n }\n }\n\n const file = relativeFile(this.workspaceRoot, cls.getSourceFile());\n const label = injection.paramType !== '' ? injection.paramType : token.display;\n const toId = this.unresolvedNode(label, file, token.display);\n this.design.edges.push(\n new DiEdge(fromId, toId, kind, token.display, token.key, injection.paramName, injection.paramType),\n );\n }\n\n private bindingTarget(binding: Binding, paramType: string): string {\n if (binding.implClass) {\n const toId = this.classNode(binding.implClass, binding.scope, paramType);\n this.walkClass(binding.implClass);\n return toId;\n }\n if (binding.kind === 'toConstantValue') return this.leafNode(binding, 'constant', paramType);\n if (binding.kind === 'toDynamicValue') return this.leafNode(binding, 'dynamic', paramType);\n // .to(X) where X did not resolve to a class declaration.\n const detail = binding.valueText !== '' ? binding.valueText : binding.tokenDisplay;\n const label = paramType !== '' ? paramType : detail;\n return this.unresolvedNode(label, binding.file, detail);\n }\n\n /** Inversify bare typed param — resolve the declared type directly to a class. */\n private processTypeInjection(fromId: string, cls: ts.ClassDeclaration, injection: Injection): void {\n const typeRef = injection.expr && ts.isIdentifier(injection.expr) ? injection.expr : null;\n const target = typeRef ? resolveClassDeclaration(typeRef, this.checker) : null;\n\n if (target) {\n const token = classTokenKey(target, this.workspaceRoot);\n const toId = this.classNode(target);\n this.walkClass(target);\n this.design.edges.push(\n new DiEdge(fromId, toId, 'type', token.display, token.key, injection.paramName, injection.paramType),\n );\n return;\n }\n\n // Bare param whose type is not a resolvable class (interface, primitive, etc.).\n const file = relativeFile(this.workspaceRoot, cls.getSourceFile());\n const label = injection.paramType !== '' ? injection.paramType : injection.paramName;\n const toId = this.unresolvedNode(label, file, '');\n this.design.edges.push(\n new DiEdge(fromId, toId, 'type', injection.paramType, `type:${injection.paramType}`, injection.paramName, injection.paramType),\n );\n }\n}\n\n/**\n * Inversify builder: injection sites are constructor params — `@inject`/\n * `@multiInject` tokens or bare typed (inject-by-type) params.\n */\nexport class InversifyDesignBuilder extends DiDesignBuilder {\n protected collectInjections(cls: ts.ClassDeclaration): Injection[] {\n const ctor = findConstructor(cls);\n if (!ctor) return [];\n\n const injections: Injection[] = [];\n for (const param of ctor.parameters) {\n const decorated = readParamDecorators(param);\n if (decorated.unmanaged) continue;\n\n const paramName = ts.isIdentifier(param.name) ? param.name.text : param.name.getText();\n const paramType = param.type ? param.type.getText() : '';\n\n if (decorated.expr) {\n injections.push(\n new Injection('token', decorated.expr, paramName, paramType, decorated.multi, decorated.optional),\n );\n } else {\n const typeRef =\n param.type && ts.isTypeReferenceNode(param.type) && ts.isIdentifier(param.type.typeName)\n ? param.type.typeName\n : null;\n injections.push(new Injection('type', typeRef, paramName, paramType));\n }\n }\n return injections;\n }\n}\n\nexport function byClassName(a: ts.ClassDeclaration, b: ts.ClassDeclaration): number {\n const nameA = a.name ? a.name.text : '';\n const nameB = b.name ? b.name.text : '';\n if (nameA !== nameB) return nameA < nameB ? -1 : 1;\n return a.getSourceFile().fileName < b.getSourceFile().fileName ? -1 : 1;\n}\n\n/**\n * Library-project roots: DI-registered classes in the project that no other\n * project class injects (tops of the local DAG).\n */\nfunction findLibraryRoots(\n classes: ts.ClassDeclaration[],\n checker: ts.TypeChecker,\n table: BindingTable,\n workspaceRoot: string,\n): ts.ClassDeclaration[] {\n const diClasses = classes.filter((cls: ts.ClassDeclaration) => isDiRegisteredClass(cls));\n const injected = new Set<ts.ClassDeclaration>();\n\n for (const cls of diClasses) {\n const ctor = findConstructor(cls);\n for (const param of ctor?.parameters ?? []) {\n const injection = readParamDecorators(param);\n if (injection.unmanaged) continue;\n if (injection.expr) {\n const token = resolveTokenKey(injection.expr, checker, workspaceRoot);\n for (const binding of table.lookup(token.key)) {\n if (binding.implClass) injected.add(binding.implClass);\n }\n } else if (param.type && ts.isTypeReferenceNode(param.type) && ts.isIdentifier(param.type.typeName)) {\n const target = resolveClassDeclaration(param.type.typeName, checker);\n if (target) injected.add(target);\n }\n }\n }\n\n return diClasses.filter((cls: ts.ClassDeclaration) => !injected.has(cls));\n}\n\n/**\n * Assign each node its LONGEST-path depth from the design's root (root = level\n * 0, its direct injections = level 1, ...) and record the deepest level. A node\n * reached from multiple parents takes its DEEPEST depth, so it always sits below\n * everything that depends on it (a dependency is never on the same or a shallower\n * level than its dependent — e.g. a config injected by both a level-2 service and\n * a level-3 client lands at level 4, one below that client). Levels are computed\n * by edge relaxation bounded by the reachable node count, which terminates even\n * if the DI graph contains a cycle; the root is pinned at 0.\n */\nexport function assignLevels(design: DiDesign): void {\n const outgoing = new Map<string, string[]>();\n for (const e of design.edges) {\n const list = outgoing.get(e.from) ?? [];\n list.push(e.to);\n outgoing.set(e.from, list);\n }\n\n // Nodes reachable from the root — only these get a level; the rest fall back\n // to 0 below, matching the previous behaviour for disconnected nodes.\n const reachable = new Set<string>();\n const queue = [design.root];\n for (let i = 0; i < queue.length; i++) {\n const id = queue[i];\n if (reachable.has(id)) continue;\n reachable.add(id);\n for (const to of outgoing.get(id) ?? []) {\n if (!reachable.has(to)) queue.push(to);\n }\n }\n\n const levelById = new Map<string, number>();\n for (const id of reachable) levelById.set(id, 0);\n // Bellman-Ford-style longest-path relaxation. |reachable| passes suffice for\n // any acyclic graph; the pass count also bounds work if a cycle exists.\n for (let pass = 0; pass < reachable.size; pass++) {\n let changed = false;\n for (const e of design.edges) {\n if (!reachable.has(e.from) || e.to === design.root) continue;\n const candidate = (levelById.get(e.from) ?? 0) + 1;\n if (candidate > (levelById.get(e.to) ?? 0)) {\n levelById.set(e.to, candidate);\n changed = true;\n }\n }\n if (!changed) break;\n }\n\n let maxLevel = 0;\n for (const node of design.nodes) {\n node.level = levelById.get(node.id) ?? 0;\n if (node.level > maxLevel) maxLevel = node.level;\n }\n design.maxLevel = maxLevel;\n}\n\n/**\n * Build one self-contained downward design tree for a single root class, using\n * the builder produced by `makeBuilder` (Inversify or Angular). `rootKind` is\n * the node kind for the root box (`controller`/`component`/`class`).\n */\nexport function buildDesign(\n root: ts.ClassDeclaration,\n rootKind: DiNodeKind,\n workspaceRoot: string,\n makeBuilder: (design: DiDesign) => DiDesignBuilder,\n): DiDesign {\n const className = root.name ? root.name.text : '<anonymous>';\n const file = relativeFile(workspaceRoot, root.getSourceFile());\n const design = new DiDesign(className, rootKind, file);\n makeBuilder(design).addRoot(root);\n assignLevels(design);\n return design;\n}\n\n/**\n * Build the full Inversify DI graph for one project: one self-contained\n * `DiDesign` per @Controller root. `projectRoot` is workspace-relative.\n *\n * `includeLibraryRoots` (default false, the v1 executor path) roots ONLY on\n * @Controller classes; when true, a controller-less project falls back to its\n * top-of-DAG DI classes (the deferred library behavior, still unit-tested).\n */\nexport function buildDiGraph(\n program: ts.Program,\n workspaceRoot: string,\n projectRoot: string,\n projectName: string,\n includeLibraryRoots = false,\n): DiGraph {\n const checker = program.getTypeChecker();\n const table = collectBindings(program, checker, workspaceRoot);\n const graph = new DiGraph(projectName);\n\n const classes = projectClasses(program, workspaceRoot, projectRoot);\n const controllers = classes.filter((cls: ts.ClassDeclaration) => isControllerClass(cls));\n const roots =\n controllers.length > 0\n ? controllers\n : includeLibraryRoots\n ? findLibraryRoots(classes, checker, table, workspaceRoot)\n : [];\n\n for (const root of [...roots].sort(byClassName)) {\n const rootKind: DiNodeKind = isControllerClass(root) ? 'controller' : 'class';\n graph.designs.push(\n buildDesign(\n root,\n rootKind,\n workspaceRoot,\n (design: DiDesign) => new InversifyDesignBuilder(checker, table, workspaceRoot, design),\n ),\n );\n }\n\n return graph;\n}\n"]}
@@ -26,7 +26,11 @@ function dotEscape(text) {
26
26
  }
27
27
  function nodeStatement(node) {
28
28
  const color = KIND_COLORS[node.kind] ?? '#F5F5F5';
29
- const label = `${dotEscape(node.className)}\\n(L${node.level}, ${node.scope})`;
29
+ // Injected as an API → show the contract on top, the impl class in parens beneath.
30
+ const name = node.api
31
+ ? `${dotEscape(node.api)}\\n(${dotEscape(node.className)})`
32
+ : dotEscape(node.className);
33
+ const label = `${name}\\n(L${node.level}, ${node.scope})`;
30
34
  const styles = ['filled'];
31
35
  if (node.kind === 'constant' || node.kind === 'dynamic')
32
36
  styles.push('rounded');
@@ -1 +1 @@
1
- {"version":3,"file":"dot.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/di-graph/dot.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;AAmCH,8CAyCC;AAxED;;GAEG;AACH,MAAM,WAAW,GAA2B;IACxC,UAAU,EAAE,SAAS,EAAE,gDAAgD;IACvE,SAAS,EAAE,SAAS,EAAE,iDAAiD;IACvE,KAAK,EAAE,SAAS,EAAE,mCAAmC;IACrD,QAAQ,EAAE,SAAS,EAAE,sCAAsC;IAC3D,OAAO,EAAE,SAAS,EAAE,qCAAqC;IACzD,UAAU,EAAE,SAAS,EAAE,oDAAoD;CAC9E,CAAC;AAEF,2EAA2E;AAC3E,SAAS,SAAS,CAAC,IAAY;IAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC5D,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IAC/B,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC;IAClD,MAAM,KAAK,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,GAAG,CAAC;IAC/E,MAAM,MAAM,GAAa,CAAC,QAAQ,CAAC,CAAC;IACpC,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;QAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAChF,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY;QAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,KAAK,YAAY,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/F,OAAO,MAAM,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,iBAAiB,KAAK,aAAa,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,KAAK,IAAI,QAAQ,MAAM,CAAC;AAC3H,CAAC;AAED;;;GAGG;AACH,SAAgB,iBAAiB,CAAC,MAAgB;IAC9C,IAAI,GAAG,GAAG,YAAY,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;IACpD,GAAG,IAAI,iBAAiB,CAAC;IACzB,GAAG,IAAI,yCAAyC,CAAC;IACjD,GAAG,IAAI,6CAA6C,CAAC;IAErD,2DAA2D;IAC3D,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAC9B,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,GAAG,IAAI,IAAI,CAAC;IAEZ,6DAA6D;IAC7D,MAAM,MAAM,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC3C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAC3C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpB,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IACD,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAS,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACrF,KAAK,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACpC,GAAG,IAAI,kBAAkB,GAAG,CAAC,GAAG,CAAC,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;IAC7F,CAAC;IAED,GAAG,IAAI,IAAI,CAAC;IAEZ,qEAAqE;IACrE,2EAA2E;IAC3E,+BAA+B;IAC/B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAC9B,GAAG,IAAI,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC;IACvE,CAAC;IAED,GAAG,IAAI,qBAAqB,CAAC;IAC7B,GAAG,IAAI,YAAY,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,QAAQ,aAAa,MAAM,CAAC,QAAQ,OAAO,CAAC;IACnG,GAAG,IAAI,kBAAkB,CAAC;IAC1B,GAAG,IAAI,KAAK,CAAC;IAEb,OAAO,GAAG,CAAC;AACf,CAAC","sourcesContent":["/**\n * DI Design DOT Emitter\n *\n * Renders one DiDesign (a single controller/root's dependency tree) as a\n * Graphviz DOT digraph, mirroring the look of the architecture graph\n * (lib/graph-visualizer.ts): rankdir=TB with { rank=same } layers per level,\n * so the controller (level 0) sits at the top and injections fan downward.\n */\n\nimport { DiDesign, DiNode } from './model';\n\n/**\n * Node fill colors by DI node kind.\n */\nconst KIND_COLORS: Record<string, string> = {\n controller: '#E3F2FD', // light blue — the root/entry class (Inversify)\n component: '#E8F5E9', // light green — the root/entry Angular component\n class: '#F5F5F5', // neutral — plain injectable class\n constant: '#FFF3E0', // light orange — toConstantValue leaf\n dynamic: '#FFF3E0', // light orange — toDynamicValue leaf\n unresolved: '#FCE4EC', // light pink — token the analyzer could not resolve\n};\n\n/** Escape a string for use inside a double-quoted DOT identifier/label. */\nfunction dotEscape(text: string): string {\n return text.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n}\n\nfunction nodeStatement(node: DiNode): string {\n const color = KIND_COLORS[node.kind] ?? '#F5F5F5';\n const label = `${dotEscape(node.className)}\\\\n(L${node.level}, ${node.scope})`;\n const styles: string[] = ['filled'];\n if (node.kind === 'constant' || node.kind === 'dynamic') styles.push('rounded');\n if (node.kind === 'unresolved') styles.push('dashed');\n const penwidth = node.kind === 'controller' || node.kind === 'component' ? ', penwidth=2' : '';\n return ` \"${dotEscape(node.id)}\" [fillcolor=\"${color}\", style=\"${styles.join(',')}\", label=\"${label}\"${penwidth}];\\n`;\n}\n\n/**\n * Generate a Graphviz DOT digraph for one design (one controller/root tree).\n * Deterministic for a serializer-sorted design.\n */\nexport function generateDesignDot(design: DiDesign): string {\n let dot = `digraph \"${dotEscape(design.root)}\" {\\n`;\n dot += ' rankdir=TB;\\n';\n dot += ' node [shape=box, fontname=\"Arial\"];\\n';\n dot += ' edge [fontname=\"Arial\", fontsize=11];\\n\\n';\n\n // Nodes, colored by kind, labeled with their level + scope\n for (const node of design.nodes) {\n dot += nodeStatement(node);\n }\n\n dot += '\\n';\n\n // One { rank=same } layer per level so the root stays on top\n const levels = new Map<number, string[]>();\n for (const node of design.nodes) {\n const layer = levels.get(node.level) ?? [];\n layer.push(node.id);\n levels.set(node.level, layer);\n }\n const sortedLevels = Array.from(levels.keys()).sort((a: number, b: number) => a - b);\n for (const level of sortedLevels) {\n const ids = levels.get(level) ?? [];\n dot += ` { rank=same; ${ids.map((id: string) => `\"${dotEscape(id)}\"`).join('; ')}; }\\n`;\n }\n\n dot += '\\n';\n\n // Constructor-injection edges, unlabeled — the arrow alone shows the\n // dependency. The param/field name, token and tokenKey stay in design.json\n // for tooling that wants them.\n for (const edge of design.edges) {\n dot += ` \"${dotEscape(edge.from)}\" -> \"${dotEscape(edge.to)}\";\\n`;\n }\n\n dot += '\\n labelloc=\"t\";\\n';\n dot += ` label=\"${dotEscape(design.root)}\\\\n(${design.rootKind}, Level 0-${design.maxLevel})\";\\n`;\n dot += ' fontsize=16;\\n';\n dot += '}\\n';\n\n return dot;\n}\n"]}
1
+ {"version":3,"file":"dot.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/di-graph/dot.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * DI Design DOT Emitter\n *\n * Renders one DiDesign (a single controller/root's dependency tree) as a\n * Graphviz DOT digraph, mirroring the look of the architecture graph\n * (lib/graph-visualizer.ts): rankdir=TB with { rank=same } layers per level,\n * so the controller (level 0) sits at the top and injections fan downward.\n */\n\nimport { DiDesign, DiNode } from './model';\n\n/**\n * Node fill colors by DI node kind.\n */\nconst KIND_COLORS: Record<string, string> = {\n controller: '#E3F2FD', // light blue — the root/entry class (Inversify)\n component: '#E8F5E9', // light green — the root/entry Angular component\n class: '#F5F5F5', // neutral — plain injectable class\n constant: '#FFF3E0', // light orange — toConstantValue leaf\n dynamic: '#FFF3E0', // light orange — toDynamicValue leaf\n unresolved: '#FCE4EC', // light pink — token the analyzer could not resolve\n};\n\n/** Escape a string for use inside a double-quoted DOT identifier/label. */\nfunction dotEscape(text: string): string {\n return text.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n}\n\nfunction nodeStatement(node: DiNode): string {\n const color = KIND_COLORS[node.kind] ?? '#F5F5F5';\n // Injected as an API → show the contract on top, the impl class in parens beneath.\n const name = node.api\n ? `${dotEscape(node.api)}\\\\n(${dotEscape(node.className)})`\n : dotEscape(node.className);\n const label = `${name}\\\\n(L${node.level}, ${node.scope})`;\n const styles: string[] = ['filled'];\n if (node.kind === 'constant' || node.kind === 'dynamic') styles.push('rounded');\n if (node.kind === 'unresolved') styles.push('dashed');\n const penwidth = node.kind === 'controller' || node.kind === 'component' ? ', penwidth=2' : '';\n return ` \"${dotEscape(node.id)}\" [fillcolor=\"${color}\", style=\"${styles.join(',')}\", label=\"${label}\"${penwidth}];\\n`;\n}\n\n/**\n * Generate a Graphviz DOT digraph for one design (one controller/root tree).\n * Deterministic for a serializer-sorted design.\n */\nexport function generateDesignDot(design: DiDesign): string {\n let dot = `digraph \"${dotEscape(design.root)}\" {\\n`;\n dot += ' rankdir=TB;\\n';\n dot += ' node [shape=box, fontname=\"Arial\"];\\n';\n dot += ' edge [fontname=\"Arial\", fontsize=11];\\n\\n';\n\n // Nodes, colored by kind, labeled with their level + scope\n for (const node of design.nodes) {\n dot += nodeStatement(node);\n }\n\n dot += '\\n';\n\n // One { rank=same } layer per level so the root stays on top\n const levels = new Map<number, string[]>();\n for (const node of design.nodes) {\n const layer = levels.get(node.level) ?? [];\n layer.push(node.id);\n levels.set(node.level, layer);\n }\n const sortedLevels = Array.from(levels.keys()).sort((a: number, b: number) => a - b);\n for (const level of sortedLevels) {\n const ids = levels.get(level) ?? [];\n dot += ` { rank=same; ${ids.map((id: string) => `\"${dotEscape(id)}\"`).join('; ')}; }\\n`;\n }\n\n dot += '\\n';\n\n // Constructor-injection edges, unlabeled — the arrow alone shows the\n // dependency. The param/field name, token and tokenKey stay in design.json\n // for tooling that wants them.\n for (const edge of design.edges) {\n dot += ` \"${dotEscape(edge.from)}\" -> \"${dotEscape(edge.to)}\";\\n`;\n }\n\n dot += '\\n labelloc=\"t\";\\n';\n dot += ` label=\"${dotEscape(design.root)}\\\\n(${design.rootKind}, Level 0-${design.maxLevel})\";\\n`;\n dot += ' fontsize=16;\\n';\n dot += '}\\n';\n\n return dot;\n}\n"]}
@@ -19,7 +19,8 @@ function label(text) {
19
19
  }
20
20
  function nodeStatement(node) {
21
21
  const id = mermaidId(node.id);
22
- const text = label(node.className);
22
+ // Injected as an API → contract on top, impl class in parens (leaves never set `api`).
23
+ const text = node.api ? `${label(node.api)}<br/>(${label(node.className)})` : label(node.className);
23
24
  if (node.kind === 'controller')
24
25
  return ` ${id}["${text}"]:::controller`;
25
26
  if (node.kind === 'component')
@@ -1 +1 @@
1
- {"version":3,"file":"mermaid.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/di-graph/mermaid.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Mermaid Emitter\n *\n * Renders the DI graph as design.md — a Mermaid `graph TD` diagram that GitHub\n * and IDEs render inline, so the DI design is reviewable in every PR. Emitted\n * in the same sorted order as design.json so diffs are equally stable.\n */\n\nimport { DiDesign, DiGraph, DiNode } from './model';\nimport { sortGraph } from './serializer';\n\n/** Mermaid node ids must be simple identifiers — map graph ids to safe ids. */\nfunction mermaidId(id: string): string {\n return id.replace(/[^A-Za-z0-9_]/g, '_');\n}\n\n/** Escape text destined for a quoted mermaid label. */\nfunction label(text: string): string {\n return text.replace(/\"/g, '#quot;');\n}\n\nfunction nodeStatement(node: DiNode): string {\n const id = mermaidId(node.id);\n const text = label(node.className);\n if (node.kind === 'controller') return ` ${id}[\"${text}\"]:::controller`;\n if (node.kind === 'component') return ` ${id}[\"${text}\"]:::component`;\n if (node.kind === 'constant' || node.kind === 'dynamic') return ` ${id}([\"${text}\"])`;\n if (node.kind === 'unresolved') return ` ${id}{{\"${text} ?\"}}:::unresolved`;\n return ` ${id}[\"${text}\"]`;\n}\n\nfunction graphBody(design: DiDesign): string[] {\n const lines: string[] = ['graph TD'];\n for (const node of design.nodes) {\n lines.push(nodeStatement(node));\n }\n for (const edge of design.edges) {\n const from = mermaidId(edge.from);\n const to = mermaidId(edge.to);\n // Unlabeled — the arrow alone shows the dependency; the param/field\n // name and token stay in design.json for tooling that wants them.\n lines.push(` ${from} --> ${to}`);\n }\n lines.push(' classDef controller fill:#1f6feb,color:#ffffff,stroke:#0d419d');\n lines.push(' classDef component fill:#2da44e,color:#ffffff,stroke:#1a7f37');\n lines.push(' classDef unresolved fill:#f0ad4e,color:#000000,stroke:#b8860b,stroke-dasharray: 5 5');\n return lines;\n}\n\n/** One `## Root` section with the design's Mermaid diagram. */\nfunction designSection(design: DiDesign): string[] {\n const kind =\n design.rootKind === 'controller' ? 'controller' : design.rootKind === 'component' ? 'component' : 'root';\n const heading = `## ${design.root} — ${kind}, Level 0…${design.maxLevel}`;\n return [heading, '', '```mermaid', ...graphBody(design), '```', ''];\n}\n\n/**\n * Render the design.md content for a project's DI graph — one Mermaid diagram\n * per design (per controller, or per library top-of-DAG root), each rooted at\n * Level 0 with its injections fanning downward.\n */\nexport function toDesignMarkdown(graph: DiGraph): string {\n sortGraph(graph);\n\n const header = [\n `# DI Design Graph — ${graph.project}`,\n '',\n `> GENERATED by \\`nx run ${graph.project}:di-graph-generate\\` — do not edit by hand.`,\n `> Machine-readable version: [design.json](./design.json)`,\n '',\n `Each section below is one root's dependency tree: Level 0 is the root`,\n `(a \\`@Controller\\` or top-of-DAG class), and constructor injections fan`,\n `downward through Levels 1, 2, … A dependency shared by multiple roots`,\n `appears in each root's tree.`,\n '',\n ];\n\n if (graph.designs.length === 0) {\n return header.concat(['No DI-registered classes found in this project.', '']).join('\\n');\n }\n\n const sections: string[] = [];\n for (const design of graph.designs) {\n sections.push(...designSection(design));\n }\n\n const legend = [\n '',\n 'Edges are constructor/`inject()` dependencies (the injected param/field',\n 'name and token are in `design.json`). Rounded nodes are',\n '`toConstantValue`/`useValue` and `toDynamicValue`/`useFactory` leaves; dashed',\n 'nodes are tokens the analyzer could not resolve.',\n '',\n ];\n\n return header.concat(sections).concat(legend).join('\\n');\n}\n"]}
1
+ {"version":3,"file":"mermaid.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/di-graph/mermaid.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Mermaid Emitter\n *\n * Renders the DI graph as design.md — a Mermaid `graph TD` diagram that GitHub\n * and IDEs render inline, so the DI design is reviewable in every PR. Emitted\n * in the same sorted order as design.json so diffs are equally stable.\n */\n\nimport { DiDesign, DiGraph, DiNode } from './model';\nimport { sortGraph } from './serializer';\n\n/** Mermaid node ids must be simple identifiers — map graph ids to safe ids. */\nfunction mermaidId(id: string): string {\n return id.replace(/[^A-Za-z0-9_]/g, '_');\n}\n\n/** Escape text destined for a quoted mermaid label. */\nfunction label(text: string): string {\n return text.replace(/\"/g, '#quot;');\n}\n\nfunction nodeStatement(node: DiNode): string {\n const id = mermaidId(node.id);\n // Injected as an API → contract on top, impl class in parens (leaves never set `api`).\n const text = node.api ? `${label(node.api)}<br/>(${label(node.className)})` : label(node.className);\n if (node.kind === 'controller') return ` ${id}[\"${text}\"]:::controller`;\n if (node.kind === 'component') return ` ${id}[\"${text}\"]:::component`;\n if (node.kind === 'constant' || node.kind === 'dynamic') return ` ${id}([\"${text}\"])`;\n if (node.kind === 'unresolved') return ` ${id}{{\"${text} ?\"}}:::unresolved`;\n return ` ${id}[\"${text}\"]`;\n}\n\nfunction graphBody(design: DiDesign): string[] {\n const lines: string[] = ['graph TD'];\n for (const node of design.nodes) {\n lines.push(nodeStatement(node));\n }\n for (const edge of design.edges) {\n const from = mermaidId(edge.from);\n const to = mermaidId(edge.to);\n // Unlabeled — the arrow alone shows the dependency; the param/field\n // name and token stay in design.json for tooling that wants them.\n lines.push(` ${from} --> ${to}`);\n }\n lines.push(' classDef controller fill:#1f6feb,color:#ffffff,stroke:#0d419d');\n lines.push(' classDef component fill:#2da44e,color:#ffffff,stroke:#1a7f37');\n lines.push(' classDef unresolved fill:#f0ad4e,color:#000000,stroke:#b8860b,stroke-dasharray: 5 5');\n return lines;\n}\n\n/** One `## Root` section with the design's Mermaid diagram. */\nfunction designSection(design: DiDesign): string[] {\n const kind =\n design.rootKind === 'controller' ? 'controller' : design.rootKind === 'component' ? 'component' : 'root';\n const heading = `## ${design.root} — ${kind}, Level 0…${design.maxLevel}`;\n return [heading, '', '```mermaid', ...graphBody(design), '```', ''];\n}\n\n/**\n * Render the design.md content for a project's DI graph — one Mermaid diagram\n * per design (per controller, or per library top-of-DAG root), each rooted at\n * Level 0 with its injections fanning downward.\n */\nexport function toDesignMarkdown(graph: DiGraph): string {\n sortGraph(graph);\n\n const header = [\n `# DI Design Graph — ${graph.project}`,\n '',\n `> GENERATED by \\`nx run ${graph.project}:di-graph-generate\\` — do not edit by hand.`,\n `> Machine-readable version: [design.json](./design.json)`,\n '',\n `Each section below is one root's dependency tree: Level 0 is the root`,\n `(a \\`@Controller\\` or top-of-DAG class), and constructor injections fan`,\n `downward through Levels 1, 2, … A dependency shared by multiple roots`,\n `appears in each root's tree.`,\n '',\n ];\n\n if (graph.designs.length === 0) {\n return header.concat(['No DI-registered classes found in this project.', '']).join('\\n');\n }\n\n const sections: string[] = [];\n for (const design of graph.designs) {\n sections.push(...designSection(design));\n }\n\n const legend = [\n '',\n 'Edges are constructor/`inject()` dependencies (the injected param/field',\n 'name and token are in `design.json`). Rounded nodes are',\n '`toConstantValue`/`useValue` and `toDynamicValue`/`useFactory` leaves; dashed',\n 'nodes are tokens the analyzer could not resolve.',\n '',\n ];\n\n return header.concat(sections).concat(legend).join('\\n');\n}\n"]}
@@ -37,6 +37,14 @@ export declare class DiNode {
37
37
  * Omitted (undefined → not serialized) for class/controller/component nodes.
38
38
  */
39
39
  detail?: string;
40
+ /**
41
+ * The declared API/interface type this class was injected AS, when it differs
42
+ * from the impl class name — e.g. injected `FirestoreAdminApi`, resolved
43
+ * `.to(FirestoreAdminClient)`. Renderers show it as the primary box label with
44
+ * `className` in parens beneath. Set on first reach; omitted (not serialized)
45
+ * for inject-by-type nodes (declared type == class) and leaves.
46
+ */
47
+ api?: string;
40
48
  constructor(id: string, className: string, kind: DiNodeKind, scope: DiScope, file: string, level?: number, detail?: string);
41
49
  }
42
50
  /**
@@ -35,6 +35,14 @@ class DiNode {
35
35
  * Omitted (undefined → not serialized) for class/controller/component nodes.
36
36
  */
37
37
  detail;
38
+ /**
39
+ * The declared API/interface type this class was injected AS, when it differs
40
+ * from the impl class name — e.g. injected `FirestoreAdminApi`, resolved
41
+ * `.to(FirestoreAdminClient)`. Renderers show it as the primary box label with
42
+ * `className` in parens beneath. Set on first reach; omitted (not serialized)
43
+ * for inject-by-type nodes (declared type == class) and leaves.
44
+ */
45
+ api;
38
46
  constructor(id, className, kind, scope, file, level = 0, detail) {
39
47
  this.id = id;
40
48
  this.className = className;
@@ -1 +1 @@
1
- {"version":3,"file":"model.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/di-graph/model.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * DI Graph Model\n *\n * Data classes for the per-project Inversify dependency DAG that is generated\n * into <projectRoot>/design.json and <projectRoot>/design.md on every build.\n *\n * A project's design.json is a container (`DiGraph`) holding an ARRAY of\n * per-root designs (`DiDesign`) — one self-contained downward tree per\n * @Controller class (or, for controller-less library projects, per top-of-DAG\n * class). Each node in a design carries its `level` = BFS depth from that\n * design's root (root = level 0, its direct injections = level 1, and so on).\n *\n * All structures are classes (not interfaces) per the repo convention for\n * data-only structures.\n */\n\nimport type * as ts from 'typescript';\n\nexport type DiNodeKind = 'controller' | 'component' | 'class' | 'constant' | 'dynamic' | 'unresolved';\n\nexport type DiInjectionKind = 'token' | 'type' | 'multiInject';\n\nexport type DiScope = 'singleton' | 'transient' | 'unknown';\n\nexport type BindingKind = 'to' | 'toSelf' | 'toConstantValue' | 'toDynamicValue' | 'decorator';\n\n/**\n * A node in the DI graph — a class, a constant/dynamic binding leaf, or an\n * unresolved token placeholder.\n */\nexport class DiNode {\n id: string;\n className: string;\n kind: DiNodeKind;\n scope: DiScope;\n file: string;\n /** BFS depth from the design's root (root = 0). Filled in after the walk. */\n level: number;\n /**\n * Secondary detail for constant/dynamic/unresolved leaves whose box is now\n * labeled by the declared param type (see B0): the bound expression text\n * (`toConstantValue`/`toDynamicValue`/`.to(X)` source) or resolving token.\n * Omitted (undefined → not serialized) for class/controller/component nodes.\n */\n detail?: string;\n\n constructor(\n id: string,\n className: string,\n kind: DiNodeKind,\n scope: DiScope,\n file: string,\n level = 0,\n detail?: string,\n ) {\n this.id = id;\n this.className = className;\n this.kind = kind;\n this.scope = scope;\n this.file = file;\n this.level = level;\n if (detail !== undefined && detail !== '') this.detail = detail;\n }\n}\n\n/**\n * A constructor-injection edge: `from` class injects `to` node.\n */\nexport class DiEdge {\n from: string;\n to: string;\n injection: DiInjectionKind;\n token: string;\n tokenKey: string;\n paramName: string;\n paramType: string;\n\n constructor(\n from: string,\n to: string,\n injection: DiInjectionKind,\n token: string,\n tokenKey: string,\n paramName: string,\n paramType: string,\n ) {\n this.from = from;\n this.to = to;\n this.injection = injection;\n this.token = token;\n this.tokenKey = tokenKey;\n this.paramName = paramName;\n this.paramType = paramType;\n }\n}\n\n/**\n * One self-contained DI design tree: a single root (a @Controller, or a\n * library top-of-DAG class) and everything it injects \"on down\". Shared\n * dependencies are duplicated across designs — each design is its own tree so\n * it can be reviewed in isolation.\n */\nexport class DiDesign {\n /** Node id of this design's root (level 0). */\n root: string;\n rootKind: DiNodeKind;\n /** Workspace-relative posix path of the root class's file. */\n file: string;\n /** Deepest level reached from the root (0 when the root has no injections). */\n maxLevel: number;\n nodes: DiNode[];\n edges: DiEdge[];\n unresolved: string[];\n\n constructor(root: string, rootKind: DiNodeKind, file: string) {\n this.root = root;\n this.rootKind = rootKind;\n this.file = file;\n this.maxLevel = 0;\n this.nodes = [];\n this.edges = [];\n this.unresolved = [];\n }\n}\n\n/**\n * The full per-project DI graph, serialized to design.json — a container over\n * one `DiDesign` per root (controller or library top-of-DAG class).\n */\nexport class DiGraph {\n schemaVersion: number;\n project: string;\n designs: DiDesign[];\n\n constructor(project: string) {\n this.schemaVersion = 2;\n this.project = project;\n this.designs = [];\n }\n}\n\n/**\n * Canonical identity of a DI token — the key links `Symbol.for('X')` token\n * definitions to their bind() sites even across packages; display is what a\n * human reads in design.md edge labels (e.g. \"TYPES.Counter\").\n */\nexport class TokenRef {\n key: string;\n display: string;\n\n constructor(key: string, display: string) {\n this.key = key;\n this.display = display;\n }\n}\n\n/**\n * One binding discovered in pass 1 — either a ContainerModule bind() call or a\n * @provideSingleton/@provideSingletonAs/@provideTransient decorator.\n */\nexport class Binding {\n tokenKey: string;\n tokenDisplay: string;\n kind: BindingKind;\n scope: DiScope;\n /** Implementation class for to/toSelf/decorator bindings; null for constant/dynamic. */\n implClass: ts.ClassDeclaration | null;\n /** Source text of the bound expression for constant/dynamic leaves; '' otherwise. */\n valueText: string;\n /** Workspace-relative posix path of the file the binding appears in. */\n file: string;\n /**\n * Angular `useFactory` deps: the declared `deps: [A, B]` tokens. The walker\n * emits an edge from the dynamic leaf to each dep so a factory's true DI\n * boundary is visible (e.g. ClientConfig's factory → EnvironmentConfig +\n * MutableContextStore). Empty for every Inversify binding.\n */\n factoryDeps: TokenRef[];\n\n constructor(\n tokenKey: string,\n tokenDisplay: string,\n kind: BindingKind,\n scope: DiScope,\n implClass: ts.ClassDeclaration | null,\n valueText: string,\n file: string,\n factoryDeps: TokenRef[] = [],\n ) {\n this.tokenKey = tokenKey;\n this.tokenDisplay = tokenDisplay;\n this.kind = kind;\n this.scope = scope;\n this.implClass = implClass;\n this.valueText = valueText;\n this.file = file;\n this.factoryDeps = factoryDeps;\n }\n}\n"]}
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/di-graph/model.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * DI Graph Model\n *\n * Data classes for the per-project Inversify dependency DAG that is generated\n * into <projectRoot>/design.json and <projectRoot>/design.md on every build.\n *\n * A project's design.json is a container (`DiGraph`) holding an ARRAY of\n * per-root designs (`DiDesign`) — one self-contained downward tree per\n * @Controller class (or, for controller-less library projects, per top-of-DAG\n * class). Each node in a design carries its `level` = BFS depth from that\n * design's root (root = level 0, its direct injections = level 1, and so on).\n *\n * All structures are classes (not interfaces) per the repo convention for\n * data-only structures.\n */\n\nimport type * as ts from 'typescript';\n\nexport type DiNodeKind = 'controller' | 'component' | 'class' | 'constant' | 'dynamic' | 'unresolved';\n\nexport type DiInjectionKind = 'token' | 'type' | 'multiInject';\n\nexport type DiScope = 'singleton' | 'transient' | 'unknown';\n\nexport type BindingKind = 'to' | 'toSelf' | 'toConstantValue' | 'toDynamicValue' | 'decorator';\n\n/**\n * A node in the DI graph — a class, a constant/dynamic binding leaf, or an\n * unresolved token placeholder.\n */\nexport class DiNode {\n id: string;\n className: string;\n kind: DiNodeKind;\n scope: DiScope;\n file: string;\n /** BFS depth from the design's root (root = 0). Filled in after the walk. */\n level: number;\n /**\n * Secondary detail for constant/dynamic/unresolved leaves whose box is now\n * labeled by the declared param type (see B0): the bound expression text\n * (`toConstantValue`/`toDynamicValue`/`.to(X)` source) or resolving token.\n * Omitted (undefined → not serialized) for class/controller/component nodes.\n */\n detail?: string;\n /**\n * The declared API/interface type this class was injected AS, when it differs\n * from the impl class name — e.g. injected `FirestoreAdminApi`, resolved\n * `.to(FirestoreAdminClient)`. Renderers show it as the primary box label with\n * `className` in parens beneath. Set on first reach; omitted (not serialized)\n * for inject-by-type nodes (declared type == class) and leaves.\n */\n api?: string;\n\n constructor(\n id: string,\n className: string,\n kind: DiNodeKind,\n scope: DiScope,\n file: string,\n level = 0,\n detail?: string,\n ) {\n this.id = id;\n this.className = className;\n this.kind = kind;\n this.scope = scope;\n this.file = file;\n this.level = level;\n if (detail !== undefined && detail !== '') this.detail = detail;\n }\n}\n\n/**\n * A constructor-injection edge: `from` class injects `to` node.\n */\nexport class DiEdge {\n from: string;\n to: string;\n injection: DiInjectionKind;\n token: string;\n tokenKey: string;\n paramName: string;\n paramType: string;\n\n constructor(\n from: string,\n to: string,\n injection: DiInjectionKind,\n token: string,\n tokenKey: string,\n paramName: string,\n paramType: string,\n ) {\n this.from = from;\n this.to = to;\n this.injection = injection;\n this.token = token;\n this.tokenKey = tokenKey;\n this.paramName = paramName;\n this.paramType = paramType;\n }\n}\n\n/**\n * One self-contained DI design tree: a single root (a @Controller, or a\n * library top-of-DAG class) and everything it injects \"on down\". Shared\n * dependencies are duplicated across designs — each design is its own tree so\n * it can be reviewed in isolation.\n */\nexport class DiDesign {\n /** Node id of this design's root (level 0). */\n root: string;\n rootKind: DiNodeKind;\n /** Workspace-relative posix path of the root class's file. */\n file: string;\n /** Deepest level reached from the root (0 when the root has no injections). */\n maxLevel: number;\n nodes: DiNode[];\n edges: DiEdge[];\n unresolved: string[];\n\n constructor(root: string, rootKind: DiNodeKind, file: string) {\n this.root = root;\n this.rootKind = rootKind;\n this.file = file;\n this.maxLevel = 0;\n this.nodes = [];\n this.edges = [];\n this.unresolved = [];\n }\n}\n\n/**\n * The full per-project DI graph, serialized to design.json — a container over\n * one `DiDesign` per root (controller or library top-of-DAG class).\n */\nexport class DiGraph {\n schemaVersion: number;\n project: string;\n designs: DiDesign[];\n\n constructor(project: string) {\n this.schemaVersion = 2;\n this.project = project;\n this.designs = [];\n }\n}\n\n/**\n * Canonical identity of a DI token — the key links `Symbol.for('X')` token\n * definitions to their bind() sites even across packages; display is what a\n * human reads in design.md edge labels (e.g. \"TYPES.Counter\").\n */\nexport class TokenRef {\n key: string;\n display: string;\n\n constructor(key: string, display: string) {\n this.key = key;\n this.display = display;\n }\n}\n\n/**\n * One binding discovered in pass 1 — either a ContainerModule bind() call or a\n * @provideSingleton/@provideSingletonAs/@provideTransient decorator.\n */\nexport class Binding {\n tokenKey: string;\n tokenDisplay: string;\n kind: BindingKind;\n scope: DiScope;\n /** Implementation class for to/toSelf/decorator bindings; null for constant/dynamic. */\n implClass: ts.ClassDeclaration | null;\n /** Source text of the bound expression for constant/dynamic leaves; '' otherwise. */\n valueText: string;\n /** Workspace-relative posix path of the file the binding appears in. */\n file: string;\n /**\n * Angular `useFactory` deps: the declared `deps: [A, B]` tokens. The walker\n * emits an edge from the dynamic leaf to each dep so a factory's true DI\n * boundary is visible (e.g. ClientConfig's factory → EnvironmentConfig +\n * MutableContextStore). Empty for every Inversify binding.\n */\n factoryDeps: TokenRef[];\n\n constructor(\n tokenKey: string,\n tokenDisplay: string,\n kind: BindingKind,\n scope: DiScope,\n implClass: ts.ClassDeclaration | null,\n valueText: string,\n file: string,\n factoryDeps: TokenRef[] = [],\n ) {\n this.tokenKey = tokenKey;\n this.tokenDisplay = tokenDisplay;\n this.kind = kind;\n this.scope = scope;\n this.implClass = implClass;\n this.valueText = valueText;\n this.file = file;\n this.factoryDeps = factoryDeps;\n }\n}\n"]}