@webpieces/nx-webpieces-rules 0.3.244 → 0.3.246

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.
Files changed (38) hide show
  1. package/package.json +6 -6
  2. package/src/executors/di-graph-generate/executor.js +42 -12
  3. package/src/executors/di-graph-generate/executor.js.map +1 -1
  4. package/src/lib/di-graph/analyzer-strategy.d.ts +47 -0
  5. package/src/lib/di-graph/analyzer-strategy.js +86 -0
  6. package/src/lib/di-graph/analyzer-strategy.js.map +1 -0
  7. package/src/lib/di-graph/analyzer.d.ts +128 -5
  8. package/src/lib/di-graph/analyzer.js +190 -65
  9. package/src/lib/di-graph/analyzer.js.map +1 -1
  10. package/src/lib/di-graph/angular-analyzer.d.ts +28 -0
  11. package/src/lib/di-graph/angular-analyzer.js +139 -0
  12. package/src/lib/di-graph/angular-analyzer.js.map +1 -0
  13. package/src/lib/di-graph/angular-providers.d.ts +32 -0
  14. package/src/lib/di-graph/angular-providers.js +177 -0
  15. package/src/lib/di-graph/angular-providers.js.map +1 -0
  16. package/src/lib/di-graph/angular-roots.d.ts +21 -0
  17. package/src/lib/di-graph/angular-roots.js +150 -0
  18. package/src/lib/di-graph/angular-roots.js.map +1 -0
  19. package/src/lib/di-graph/dot.js +8 -5
  20. package/src/lib/di-graph/dot.js.map +1 -1
  21. package/src/lib/di-graph/mermaid.js +12 -7
  22. package/src/lib/di-graph/mermaid.js.map +1 -1
  23. package/src/lib/di-graph/model.d.ts +17 -3
  24. package/src/lib/di-graph/model.js +19 -2
  25. package/src/lib/di-graph/model.js.map +1 -1
  26. package/src/lib/framework-resolver.d.ts +8 -4
  27. package/src/lib/framework-resolver.js +10 -6
  28. package/src/lib/framework-resolver.js.map +1 -1
  29. package/src/lib/graph-loader.d.ts +5 -0
  30. package/src/lib/graph-loader.js +5 -0
  31. package/src/lib/graph-loader.js.map +1 -1
  32. package/src/lib/graph-metadata.d.ts +19 -0
  33. package/src/lib/graph-metadata.js +40 -1
  34. package/src/lib/graph-metadata.js.map +1 -1
  35. package/src/lib/graph-sorter.d.ts +3 -1
  36. package/src/lib/graph-sorter.js.map +1 -1
  37. package/src/lib/graph-visualizer.js +24 -16
  38. package/src/lib/graph-visualizer.js.map +1 -1
@@ -15,7 +15,14 @@
15
15
  * (the tops of the local DAG).
16
16
  */
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.InversifyDesignBuilder = exports.DiDesignBuilder = exports.Injection = exports.ParamInjection = void 0;
19
+ exports.readParamDecorators = readParamDecorators;
18
20
  exports.isControllerClass = isControllerClass;
21
+ exports.findConstructor = findConstructor;
22
+ exports.projectClasses = projectClasses;
23
+ exports.byClassName = byClassName;
24
+ exports.assignLevels = assignLevels;
25
+ exports.buildDesign = buildDesign;
19
26
  exports.buildDiGraph = buildDiGraph;
20
27
  const tslib_1 = require("tslib");
21
28
  const ts = tslib_1.__importStar(require("typescript"));
@@ -36,6 +43,7 @@ class ParamInjection {
36
43
  this.unmanaged = unmanaged;
37
44
  }
38
45
  }
46
+ exports.ParamInjection = ParamInjection;
39
47
  function readParamDecorators(param) {
40
48
  let expr = null;
41
49
  let multi = false;
@@ -102,12 +110,50 @@ function projectClasses(program, workspaceRoot, projectRoot) {
102
110
  }
103
111
  return classes;
104
112
  }
113
+ /**
114
+ * One normalized injection site, framework-agnostic — produced by a builder's
115
+ * `collectInjections(cls)` hook and processed by the shared base. Inversify
116
+ * emits `token`/`type` from constructor params; Angular emits `angularToken`
117
+ * from constructor params AND `inject()` field initializers.
118
+ *
119
+ * Modes:
120
+ * - `token` Inversify `@inject`/`@multiInject`: table lookup; an unbound
121
+ * token becomes an `unresolved` node (no class fallback).
122
+ * - `type` Inversify bare typed param: resolve the declared TYPE to a
123
+ * class (inject-by-type); no table lookup.
124
+ * - `angularToken` Angular `inject(T)` / `@Inject(T)` / bare typed ctor param:
125
+ * table lookup FIRST (provider table), then fall back to
126
+ * resolving the token expression as a class, else unresolved.
127
+ */
128
+ class Injection {
129
+ mode;
130
+ /** Token/type expression (modes `token`/`angularToken`, or the type identifier for `type`). */
131
+ expr;
132
+ multi;
133
+ optional;
134
+ paramName;
135
+ paramType;
136
+ constructor(mode, expr, paramName, paramType, multi = false, optional = false) {
137
+ this.mode = mode;
138
+ this.expr = expr;
139
+ this.paramName = paramName;
140
+ this.paramType = paramType;
141
+ this.multi = multi;
142
+ this.optional = optional;
143
+ }
144
+ }
145
+ exports.Injection = Injection;
105
146
  /**
106
147
  * Builds ONE self-contained `DiDesign` for a single root. A fresh instance is
107
148
  * created per root so its maps (visited/classIds/usedIds/...) are scoped to
108
- * that root's tree — a dependency shared by two controllers is therefore walked
109
- * (and duplicated) into each controller's design, not hidden under whichever
110
- * controller reached it first.
149
+ * that root's tree — a dependency shared by two roots is therefore walked
150
+ * (and duplicated) into each root's design, not hidden under whichever root
151
+ * reached it first.
152
+ *
153
+ * Framework-agnostic base: subclasses implement {@link collectInjections} (and
154
+ * override {@link rootKindOf} for Angular components); everything else — node
155
+ * ids, leaf/unresolved labeling, token→binding resolution, factory-dep edges,
156
+ * level assignment — is shared so Inversify and Angular render identically.
111
157
  */
112
158
  class DiDesignBuilder {
113
159
  checker;
@@ -125,6 +171,10 @@ class DiDesignBuilder {
125
171
  this.workspaceRoot = workspaceRoot;
126
172
  this.design = design;
127
173
  }
174
+ /** Node kind for a root/reached class — `controller` (Inversify) or `component` (Angular). */
175
+ rootKindOf(cls) {
176
+ return isControllerClass(cls) ? 'controller' : 'class';
177
+ }
128
178
  addRoot(cls) {
129
179
  const id = this.classNode(cls);
130
180
  this.design.root = id;
@@ -145,8 +195,7 @@ class DiDesignBuilder {
145
195
  this.classIds.set(cls, id);
146
196
  const declaredScope = this.classScope(cls);
147
197
  const scope = declaredScope !== 'unknown' ? declaredScope : scopeHint;
148
- const kind = isControllerClass(cls) ? 'controller' : 'class';
149
- this.design.nodes.push(new model_1.DiNode(id, className, kind, scope, file));
198
+ this.design.nodes.push(new model_1.DiNode(id, className, this.rootKindOf(cls), scope, file));
150
199
  return id;
151
200
  }
152
201
  claimId(preferred, file) {
@@ -173,108 +222,176 @@ class DiDesignBuilder {
173
222
  }
174
223
  return 'unknown';
175
224
  }
176
- leafNode(binding, kind) {
225
+ /**
226
+ * Leaf box for a constant/dynamic binding. B0: the box is labeled by the
227
+ * DECLARED param TYPE (e.g. `FirestoreConfig`, `ClientConfig`) — the DI
228
+ * contract — while the bound expression (`buildConfigFromEnv(...)` /
229
+ * `TOKEN (dynamic)`) is kept as `detail`. A dynamic leaf also fans out to
230
+ * each of its `useFactory` `deps` (Angular; empty for Inversify).
231
+ */
232
+ leafNode(binding, kind, paramType) {
177
233
  const existing = this.leafIds.get(binding);
178
234
  if (existing)
179
235
  return existing;
180
- // Dynamic values are factory functions their source text is noise, so label
181
- // them by the token they satisfy. Constants keep their (short) expression text.
182
- const className = kind === 'dynamic'
183
- ? `${binding.tokenDisplay} (dynamic)`
184
- : binding.valueText !== '' ? binding.valueText : binding.tokenDisplay;
236
+ const detail = kind === 'dynamic' ? `${binding.tokenDisplay} (dynamic)` : binding.valueText;
237
+ const className = paramType !== '' ? paramType : detail !== '' ? detail : binding.tokenDisplay;
185
238
  const id = this.claimId(className, binding.file);
186
239
  this.leafIds.set(binding, id);
187
- this.design.nodes.push(new model_1.DiNode(id, className, kind, binding.scope, binding.file));
240
+ this.design.nodes.push(new model_1.DiNode(id, className, kind, binding.scope, binding.file, 0, detail));
241
+ if (kind === 'dynamic')
242
+ this.expandFactoryDeps(id, binding);
188
243
  return id;
189
244
  }
190
- unresolvedNode(display, file) {
191
- const key = `${display} ${file}`;
245
+ /** Edges from a `useFactory` leaf to each declared `deps: [...]` token (Angular). */
246
+ expandFactoryDeps(leafId, binding) {
247
+ for (const dep of binding.factoryDeps) {
248
+ const bindings = this.table.lookup(dep.key);
249
+ if (bindings.length > 0) {
250
+ for (const depBinding of bindings) {
251
+ // The dep token IS the declared type — label the box with it.
252
+ const toId = this.bindingTarget(depBinding, dep.display);
253
+ this.design.edges.push(new model_1.DiEdge(leafId, toId, 'type', dep.display, dep.key, dep.display, dep.display));
254
+ }
255
+ }
256
+ else {
257
+ const toId = this.unresolvedNode(dep.display, binding.file, '');
258
+ this.design.edges.push(new model_1.DiEdge(leafId, toId, 'type', dep.display, dep.key, dep.display, dep.display));
259
+ }
260
+ }
261
+ }
262
+ /**
263
+ * `unresolved` placeholder box. B0: labeled by the declared param TYPE
264
+ * (`className`) with the resolving token expression kept as `detail` (and
265
+ * surfaced in `design.unresolved` for diagnostics).
266
+ */
267
+ unresolvedNode(className, file, detail) {
268
+ const key = `${className}|${detail}|${file}`;
192
269
  const existing = this.unresolvedIds.get(key);
193
270
  if (existing)
194
271
  return existing;
195
- const id = this.claimId(display, file);
272
+ const id = this.claimId(className, file);
196
273
  this.unresolvedIds.set(key, id);
197
- this.design.nodes.push(new model_1.DiNode(id, display, 'unresolved', 'unknown', file));
198
- this.design.unresolved.push(display);
274
+ this.design.nodes.push(new model_1.DiNode(id, className, 'unresolved', 'unknown', file, 0, detail !== className ? detail : ''));
275
+ this.design.unresolved.push(detail !== '' ? detail : className);
199
276
  return id;
200
277
  }
201
278
  walkClass(cls) {
202
279
  if (this.visited.has(cls))
203
280
  return;
204
281
  this.visited.add(cls);
205
- const ctor = findConstructor(cls);
206
- if (!ctor)
207
- return;
208
282
  const fromId = this.classNode(cls);
209
- for (const param of ctor.parameters) {
210
- this.walkParam(fromId, cls, param);
283
+ for (const injection of this.collectInjections(cls)) {
284
+ this.processInjection(fromId, cls, injection);
211
285
  }
212
286
  }
213
- walkParam(fromId, cls, param) {
214
- const injection = readParamDecorators(param);
215
- if (injection.unmanaged)
216
- return;
217
- const paramName = ts.isIdentifier(param.name) ? param.name.text : param.name.getText();
218
- const paramType = param.type ? param.type.getText() : '';
219
- if (injection.expr) {
220
- this.walkTokenParam(fromId, cls, injection, paramName, paramType);
287
+ /** Resolve one injection to a node and record the edge(s). Never throws. */
288
+ processInjection(fromId, cls, injection) {
289
+ if (injection.mode === 'type') {
290
+ this.processTypeInjection(fromId, cls, injection);
221
291
  }
222
292
  else {
223
- this.walkTypeParam(fromId, cls, param, paramName, paramType);
293
+ this.processTokenInjection(fromId, cls, injection);
224
294
  }
225
295
  }
226
- walkTokenParam(fromId, cls, injection, paramName, paramType) {
296
+ /** Inversify `@inject`/`@multiInject` and Angular `inject()`/`@Inject`/bare token. */
297
+ processTokenInjection(fromId, cls, injection) {
227
298
  const expr = injection.expr;
228
299
  if (!expr)
229
300
  return;
230
301
  const token = (0, token_resolver_1.resolveTokenKey)(expr, this.checker, this.workspaceRoot);
231
302
  const kind = injection.multi ? 'multiInject' : 'token';
232
303
  const bindings = this.table.lookup(token.key);
233
- if (bindings.length === 0) {
234
- // @multiInject @optional with zero bindings is legal — no edge, no error.
235
- if (injection.multi && injection.optional)
236
- return;
237
- const file = (0, token_resolver_1.relativeFile)(this.workspaceRoot, cls.getSourceFile());
238
- const toId = this.unresolvedNode(token.display, file);
239
- this.design.edges.push(new model_1.DiEdge(fromId, toId, kind, token.display, token.key, paramName, paramType));
304
+ if (bindings.length > 0) {
305
+ for (const binding of bindings) {
306
+ const toId = this.bindingTarget(binding, injection.paramType);
307
+ this.design.edges.push(new model_1.DiEdge(fromId, toId, kind, token.display, token.key, injection.paramName, injection.paramType));
308
+ }
240
309
  return;
241
310
  }
242
- for (const binding of bindings) {
243
- const toId = this.bindingTarget(binding);
244
- this.design.edges.push(new model_1.DiEdge(fromId, toId, kind, token.display, token.key, paramName, paramType));
311
+ // @multiInject @optional with zero bindings is legal — no edge, no error.
312
+ if (injection.multi && injection.optional)
313
+ return;
314
+ // Angular: a token with no explicit provider may still be a bare @Injectable
315
+ // class — resolve the token expression as a class and inject it by type.
316
+ if (injection.mode === 'angularToken') {
317
+ const target = (0, bindings_1.resolveClassDeclaration)(expr, this.checker);
318
+ if (target) {
319
+ const classToken = (0, token_resolver_1.classTokenKey)(target, this.workspaceRoot);
320
+ const toId = this.classNode(target);
321
+ this.walkClass(target);
322
+ this.design.edges.push(new model_1.DiEdge(fromId, toId, 'type', classToken.display, classToken.key, injection.paramName, injection.paramType));
323
+ return;
324
+ }
245
325
  }
326
+ const file = (0, token_resolver_1.relativeFile)(this.workspaceRoot, cls.getSourceFile());
327
+ const label = injection.paramType !== '' ? injection.paramType : token.display;
328
+ const toId = this.unresolvedNode(label, file, token.display);
329
+ this.design.edges.push(new model_1.DiEdge(fromId, toId, kind, token.display, token.key, injection.paramName, injection.paramType));
246
330
  }
247
- bindingTarget(binding) {
331
+ bindingTarget(binding, paramType) {
248
332
  if (binding.implClass) {
249
333
  const toId = this.classNode(binding.implClass, binding.scope);
250
334
  this.walkClass(binding.implClass);
251
335
  return toId;
252
336
  }
253
337
  if (binding.kind === 'toConstantValue')
254
- return this.leafNode(binding, 'constant');
338
+ return this.leafNode(binding, 'constant', paramType);
255
339
  if (binding.kind === 'toDynamicValue')
256
- return this.leafNode(binding, 'dynamic');
340
+ return this.leafNode(binding, 'dynamic', paramType);
257
341
  // .to(X) where X did not resolve to a class declaration.
258
- return this.unresolvedNode(binding.valueText !== '' ? binding.valueText : binding.tokenDisplay, binding.file);
342
+ const detail = binding.valueText !== '' ? binding.valueText : binding.tokenDisplay;
343
+ const label = paramType !== '' ? paramType : detail;
344
+ return this.unresolvedNode(label, binding.file, detail);
259
345
  }
260
- walkTypeParam(fromId, cls, param, paramName, paramType) {
261
- const typeName = param.type && ts.isTypeReferenceNode(param.type) ? param.type.typeName : null;
262
- const target = typeName && ts.isIdentifier(typeName)
263
- ? (0, bindings_1.resolveClassDeclaration)(typeName, this.checker)
264
- : null;
346
+ /** Inversify bare typed param resolve the declared type directly to a class. */
347
+ processTypeInjection(fromId, cls, injection) {
348
+ const typeRef = injection.expr && ts.isIdentifier(injection.expr) ? injection.expr : null;
349
+ const target = typeRef ? (0, bindings_1.resolveClassDeclaration)(typeRef, this.checker) : null;
265
350
  if (target) {
266
351
  const token = (0, token_resolver_1.classTokenKey)(target, this.workspaceRoot);
267
352
  const toId = this.classNode(target);
268
353
  this.walkClass(target);
269
- this.design.edges.push(new model_1.DiEdge(fromId, toId, 'type', token.display, token.key, paramName, paramType));
354
+ this.design.edges.push(new model_1.DiEdge(fromId, toId, 'type', token.display, token.key, injection.paramName, injection.paramType));
270
355
  return;
271
356
  }
272
357
  // Bare param whose type is not a resolvable class (interface, primitive, etc.).
273
358
  const file = (0, token_resolver_1.relativeFile)(this.workspaceRoot, cls.getSourceFile());
274
- const toId = this.unresolvedNode(paramType !== '' ? paramType : paramName, file);
275
- this.design.edges.push(new model_1.DiEdge(fromId, toId, 'type', paramType, `type:${paramType}`, paramName, paramType));
359
+ const label = injection.paramType !== '' ? injection.paramType : injection.paramName;
360
+ const toId = this.unresolvedNode(label, file, '');
361
+ this.design.edges.push(new model_1.DiEdge(fromId, toId, 'type', injection.paramType, `type:${injection.paramType}`, injection.paramName, injection.paramType));
362
+ }
363
+ }
364
+ exports.DiDesignBuilder = DiDesignBuilder;
365
+ /**
366
+ * Inversify builder: injection sites are constructor params — `@inject`/
367
+ * `@multiInject` tokens or bare typed (inject-by-type) params.
368
+ */
369
+ class InversifyDesignBuilder extends DiDesignBuilder {
370
+ collectInjections(cls) {
371
+ const ctor = findConstructor(cls);
372
+ if (!ctor)
373
+ return [];
374
+ const injections = [];
375
+ for (const param of ctor.parameters) {
376
+ const decorated = readParamDecorators(param);
377
+ if (decorated.unmanaged)
378
+ continue;
379
+ const paramName = ts.isIdentifier(param.name) ? param.name.text : param.name.getText();
380
+ const paramType = param.type ? param.type.getText() : '';
381
+ if (decorated.expr) {
382
+ injections.push(new Injection('token', decorated.expr, paramName, paramType, decorated.multi, decorated.optional));
383
+ }
384
+ else {
385
+ const typeRef = param.type && ts.isTypeReferenceNode(param.type) && ts.isIdentifier(param.type.typeName)
386
+ ? param.type.typeName
387
+ : null;
388
+ injections.push(new Injection('type', typeRef, paramName, paramType));
389
+ }
390
+ }
391
+ return injections;
276
392
  }
277
393
  }
394
+ exports.InversifyDesignBuilder = InversifyDesignBuilder;
278
395
  function byClassName(a, b) {
279
396
  const nameA = a.name ? a.name.text : '';
280
397
  const nameB = b.name ? b.name.text : '';
@@ -350,23 +467,28 @@ function assignLevels(design) {
350
467
  }
351
468
  design.maxLevel = maxLevel;
352
469
  }
353
- /** Build one self-contained downward design tree for a single root class. */
354
- function buildDesign(root, checker, table, workspaceRoot) {
470
+ /**
471
+ * Build one self-contained downward design tree for a single root class, using
472
+ * the builder produced by `makeBuilder` (Inversify or Angular). `rootKind` is
473
+ * the node kind for the root box (`controller`/`component`/`class`).
474
+ */
475
+ function buildDesign(root, rootKind, workspaceRoot, makeBuilder) {
355
476
  const className = root.name ? root.name.text : '<anonymous>';
356
- const rootKind = isControllerClass(root) ? 'controller' : 'class';
357
477
  const file = (0, token_resolver_1.relativeFile)(workspaceRoot, root.getSourceFile());
358
478
  const design = new model_1.DiDesign(className, rootKind, file);
359
- const builder = new DiDesignBuilder(checker, table, workspaceRoot, design);
360
- builder.addRoot(root);
479
+ makeBuilder(design).addRoot(root);
361
480
  assignLevels(design);
362
481
  return design;
363
482
  }
364
483
  /**
365
- * Build the full DI graph for one project: one self-contained `DiDesign` per
366
- * root every @Controller class, or (when the project has no controllers)
367
- * every top-of-DAG DI class. `projectRoot` is workspace-relative.
484
+ * Build the full Inversify DI graph for one project: one self-contained
485
+ * `DiDesign` per @Controller root. `projectRoot` is workspace-relative.
486
+ *
487
+ * `includeLibraryRoots` (default false, the v1 executor path) roots ONLY on
488
+ * @Controller classes; when true, a controller-less project falls back to its
489
+ * top-of-DAG DI classes (the deferred library behavior, still unit-tested).
368
490
  */
369
- function buildDiGraph(program, workspaceRoot, projectRoot, projectName) {
491
+ function buildDiGraph(program, workspaceRoot, projectRoot, projectName, includeLibraryRoots = false) {
370
492
  const checker = program.getTypeChecker();
371
493
  const table = (0, bindings_1.collectBindings)(program, checker, workspaceRoot);
372
494
  const graph = new model_1.DiGraph(projectName);
@@ -374,9 +496,12 @@ function buildDiGraph(program, workspaceRoot, projectRoot, projectName) {
374
496
  const controllers = classes.filter((cls) => isControllerClass(cls));
375
497
  const roots = controllers.length > 0
376
498
  ? controllers
377
- : findLibraryRoots(classes, checker, table, workspaceRoot);
499
+ : includeLibraryRoots
500
+ ? findLibraryRoots(classes, checker, table, workspaceRoot)
501
+ : [];
378
502
  for (const root of [...roots].sort(byClassName)) {
379
- graph.designs.push(buildDesign(root, checker, table, workspaceRoot));
503
+ const rootKind = isControllerClass(root) ? 'controller' : 'class';
504
+ graph.designs.push(buildDesign(root, rootKind, workspaceRoot, (design) => new InversifyDesignBuilder(checker, table, workspaceRoot, design)));
380
505
  }
381
506
  return graph;
382
507
  }
@@ -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\nclass 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\nfunction 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\nfunction 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. */\nfunction 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 * 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 controllers is therefore walked\n * (and duplicated) into each controller's design, not hidden under whichever\n * controller reached it first.\n */\nclass DiDesignBuilder {\n private readonly checker: ts.TypeChecker;\n private readonly table: BindingTable;\n private readonly workspaceRoot: string;\n private 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 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 private 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 const kind: DiNodeKind = isControllerClass(cls) ? 'controller' : 'class';\n this.design.nodes.push(new DiNode(id, className, kind, 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 private leafNode(binding: Binding, kind: DiNodeKind): string {\n const existing = this.leafIds.get(binding);\n if (existing) return existing;\n\n // Dynamic values are factory functions — their source text is noise, so label\n // them by the token they satisfy. Constants keep their (short) expression text.\n const className = kind === 'dynamic'\n ? `${binding.tokenDisplay} (dynamic)`\n : binding.valueText !== '' ? binding.valueText : 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));\n return id;\n }\n\n private unresolvedNode(display: string, file: string): string {\n const key = `${display} ${file}`;\n const existing = this.unresolvedIds.get(key);\n if (existing) return existing;\n\n const id = this.claimId(display, file);\n this.unresolvedIds.set(key, id);\n this.design.nodes.push(new DiNode(id, display, 'unresolved', 'unknown', file));\n this.design.unresolved.push(display);\n return id;\n }\n\n walkClass(cls: ts.ClassDeclaration): void {\n if (this.visited.has(cls)) return;\n this.visited.add(cls);\n\n const ctor = findConstructor(cls);\n if (!ctor) return;\n const fromId = this.classNode(cls);\n\n for (const param of ctor.parameters) {\n this.walkParam(fromId, cls, param);\n }\n }\n\n private walkParam(fromId: string, cls: ts.ClassDeclaration, param: ts.ParameterDeclaration): void {\n const injection = readParamDecorators(param);\n if (injection.unmanaged) return;\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 (injection.expr) {\n this.walkTokenParam(fromId, cls, injection, paramName, paramType);\n } else {\n this.walkTypeParam(fromId, cls, param, paramName, paramType);\n }\n }\n\n private walkTokenParam(\n fromId: string,\n cls: ts.ClassDeclaration,\n injection: ParamInjection,\n paramName: string,\n paramType: string,\n ): 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 // @multiInject @optional with zero bindings is legal — no edge, no error.\n if (injection.multi && injection.optional) return;\n const file = relativeFile(this.workspaceRoot, cls.getSourceFile());\n const toId = this.unresolvedNode(token.display, file);\n this.design.edges.push(new DiEdge(fromId, toId, kind, token.display, token.key, paramName, paramType));\n return;\n }\n\n for (const binding of bindings) {\n const toId = this.bindingTarget(binding);\n this.design.edges.push(new DiEdge(fromId, toId, kind, token.display, token.key, paramName, paramType));\n }\n }\n\n private bindingTarget(binding: Binding): 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');\n if (binding.kind === 'toDynamicValue') return this.leafNode(binding, 'dynamic');\n // .to(X) where X did not resolve to a class declaration.\n return this.unresolvedNode(binding.valueText !== '' ? binding.valueText : binding.tokenDisplay, binding.file);\n }\n\n private walkTypeParam(\n fromId: string,\n cls: ts.ClassDeclaration,\n param: ts.ParameterDeclaration,\n paramName: string,\n paramType: string,\n ): void {\n const typeName = param.type && ts.isTypeReferenceNode(param.type) ? param.type.typeName : null;\n const target = typeName && ts.isIdentifier(typeName)\n ? resolveClassDeclaration(typeName, this.checker)\n : 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(new DiEdge(fromId, toId, 'type', token.display, token.key, paramName, paramType));\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 toId = this.unresolvedNode(paramType !== '' ? paramType : paramName, file);\n this.design.edges.push(new DiEdge(fromId, toId, 'type', paramType, `type:${paramType}`, paramName, paramType));\n }\n}\n\nfunction 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 BFS shortest-path depth from the design's root (root =\n * level 0, its direct injections = level 1, ...) and record the deepest level.\n * A node reached from multiple parents keeps its SHALLOWEST depth. Cycles are\n * safe: a node is levelled once, the first (shallowest) time BFS reaches it.\n */\nfunction 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 const nodeById = new Map<string, DiNode>(design.nodes.map((n: DiNode) => [n.id, n]));\n const levelById = new Map<string, number>();\n\n let frontier = [design.root];\n let level = 0;\n while (frontier.length > 0) {\n const next: string[] = [];\n for (const id of frontier) {\n if (levelById.has(id)) continue;\n levelById.set(id, level);\n for (const to of outgoing.get(id) ?? []) {\n if (!levelById.has(to)) next.push(to);\n }\n }\n frontier = next;\n level++;\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/** Build one self-contained downward design tree for a single root class. */\nfunction buildDesign(\n root: ts.ClassDeclaration,\n checker: ts.TypeChecker,\n table: BindingTable,\n workspaceRoot: string,\n): DiDesign {\n const className = root.name ? root.name.text : '<anonymous>';\n const rootKind: DiNodeKind = isControllerClass(root) ? 'controller' : 'class';\n const file = relativeFile(workspaceRoot, root.getSourceFile());\n const design = new DiDesign(className, rootKind, file);\n const builder = new DiDesignBuilder(checker, table, workspaceRoot, design);\n builder.addRoot(root);\n assignLevels(design);\n return design;\n}\n\n/**\n * Build the full DI graph for one project: one self-contained `DiDesign` per\n * root — every @Controller class, or (when the project has no controllers)\n * every top-of-DAG DI class. `projectRoot` is workspace-relative.\n */\nexport function buildDiGraph(\n program: ts.Program,\n workspaceRoot: string,\n projectRoot: string,\n projectName: string,\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 = controllers.length > 0\n ? controllers\n : findLibraryRoots(classes, checker, table, workspaceRoot);\n\n for (const root of [...roots].sort(byClassName)) {\n graph.designs.push(buildDesign(root, checker, table, workspaceRoot));\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 */\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 BFS shortest-path depth from the design's root (root =\n * level 0, its direct injections = level 1, ...) and record the deepest level.\n * A node reached from multiple parents keeps its SHALLOWEST depth. Cycles are\n * safe: a node is levelled once, the first (shallowest) time BFS reaches it.\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 const nodeById = new Map<string, DiNode>(design.nodes.map((n: DiNode) => [n.id, n]));\n const levelById = new Map<string, number>();\n\n let frontier = [design.root];\n let level = 0;\n while (frontier.length > 0) {\n const next: string[] = [];\n for (const id of frontier) {\n if (levelById.has(id)) continue;\n levelById.set(id, level);\n for (const to of outgoing.get(id) ?? []) {\n if (!levelById.has(to)) next.push(to);\n }\n }\n frontier = next;\n level++;\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"]}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Angular DI Analyzer (pass 2, Angular flavor)
3
+ *
4
+ * Renders each Angular entry component's injection tree "from the page/root
5
+ * component on down". Reuses the shared {@link DiDesignBuilder} base (node ids,
6
+ * leaf/unresolved labeling, provider-table resolution, factory-dep edges, level
7
+ * assignment) via its `collectInjections` hook — only the front-half (roots,
8
+ * providers, injection-site discovery) is Angular-specific.
9
+ *
10
+ * Angular injection sites per class:
11
+ * 1. Constructor params — `@Inject(TOKEN)` (capital I), `forwardRef(() => X)`,
12
+ * `@Optional`/`@Self`/`@SkipSelf`/`@Host`, or a bare typed param (the class
13
+ * itself is the token).
14
+ * 2. Field initializers calling `inject()` — the standalone pattern
15
+ * (`private saveApi = inject(SaveApi)`); the field name is the edge label
16
+ * and the declared/token type labels the box.
17
+ *
18
+ * Every site is an `angularToken` injection: the provider table is consulted
19
+ * first, then the token expression is resolved as a bare `@Injectable` class,
20
+ * else it becomes an `unresolved` node. Generation never fails.
21
+ */
22
+ import * as ts from 'typescript';
23
+ import { DiGraph } from './model';
24
+ /**
25
+ * Build the full Angular DI graph for one project: one self-contained `DiDesign`
26
+ * per entry component (bootstrap + routed). `projectRoot` is workspace-relative.
27
+ */
28
+ export declare function buildAngularDiGraph(program: ts.Program, workspaceRoot: string, projectRoot: string, projectName: string): DiGraph;