@tstdl/base 0.93.126 → 0.93.127
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/injector/graph.js +27 -6
- package/package.json +1 -1
package/injector/graph.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { toArray } from '../utils/array/array.js';
|
|
2
2
|
import { isArray, isDefined, isFunction } from '../utils/type-guards.js';
|
|
3
|
+
import { typeOf } from '../utils/type-of.js';
|
|
3
4
|
import { Injector } from './injector.js';
|
|
4
5
|
import { afterResolve } from './interfaces.js';
|
|
5
6
|
import { isClassProvider, isFactoryProvider, isProviderWithInitializer, isTokenProvider, isValueProvider } from './provider.js';
|
|
@@ -185,8 +186,8 @@ export function getDependencyGraph(injector, options = {}) {
|
|
|
185
186
|
label += ' (multi)';
|
|
186
187
|
}
|
|
187
188
|
if (isDefined(node.argument)) {
|
|
188
|
-
const s = JSON.stringify(node.argument);
|
|
189
|
-
label += `\narg: ${s.length > 20 ? `${s.
|
|
189
|
+
const s = isFunction(node.argument) ? typeOf(node.argument) : JSON.stringify(node.argument) ?? 'Could not stringify argument';
|
|
190
|
+
label += `\narg: ${(s.length > 20) ? `${s.slice(0, 17)}...` : s}`;
|
|
190
191
|
}
|
|
191
192
|
if (node.isCached) {
|
|
192
193
|
label += '\n(cached)';
|
|
@@ -281,6 +282,7 @@ export function renderDependencyGraphToDot(graph, options = {}) {
|
|
|
281
282
|
return tokenToId.get(token);
|
|
282
283
|
};
|
|
283
284
|
const lines = ['strict digraph G {'];
|
|
285
|
+
// --- Graph Global Attributes ---
|
|
284
286
|
if (bgcolor) {
|
|
285
287
|
lines.push(` bgcolor=${JSON.stringify(bgcolor)};`);
|
|
286
288
|
}
|
|
@@ -293,6 +295,7 @@ export function renderDependencyGraphToDot(graph, options = {}) {
|
|
|
293
295
|
lines.push(` node [shape=box, fontname=${JSON.stringify(fontname)}, style=filled, fillcolor="#f9f9f9", fontsize=${fontsize}];`);
|
|
294
296
|
lines.push(` edge [fontname=${JSON.stringify(fontname)}, fontsize=${fontsize - 1}];`);
|
|
295
297
|
lines.push(` rankdir=${rankdir}; compound=true;`);
|
|
298
|
+
// --- 1. Render Edges ---
|
|
296
299
|
for (const edge of graph.edges) {
|
|
297
300
|
const color = edge.isCycle ? '#e74c3c' : edge.color;
|
|
298
301
|
const penwidth = edge.isCycle ? 2.0 : edge.penwidth;
|
|
@@ -304,18 +307,30 @@ export function renderDependencyGraphToDot(graph, options = {}) {
|
|
|
304
307
|
].filter(Boolean).join(', ');
|
|
305
308
|
lines.push(` ${getTokenId(edge.from)} -> ${getTokenId(edge.to)} [${attributes}];`);
|
|
306
309
|
}
|
|
310
|
+
// --- Helper: Render Node Definition ---
|
|
307
311
|
const renderNode = (node) => {
|
|
308
312
|
const metadata = node.metadata;
|
|
309
313
|
const lifecycle = metadata.lifecycle;
|
|
310
314
|
const first = lifecycle.split('|')[0];
|
|
311
|
-
const colors = {
|
|
312
|
-
|
|
315
|
+
const colors = {
|
|
316
|
+
singleton: '#d1e7dd',
|
|
317
|
+
injector: '#fff3cd',
|
|
318
|
+
resolution: '#cfe2ff',
|
|
319
|
+
transient: '#f8d7da',
|
|
320
|
+
};
|
|
321
|
+
const shapes = {
|
|
322
|
+
singleton: 'doubleoctagon',
|
|
323
|
+
injector: 'component',
|
|
324
|
+
resolution: 'ellipse',
|
|
325
|
+
transient: 'box',
|
|
326
|
+
};
|
|
313
327
|
const name = node.name + (metadata.hasAfterResolve ? ' *' : '');
|
|
314
328
|
const label = showMetadata ? `${name}\n[${lifecycle}, ${metadata.type}]` : name;
|
|
315
329
|
const fillcolor = colors[first] ?? '#f9f9f9';
|
|
316
330
|
const shape = shapes[first] ?? 'box';
|
|
317
331
|
return ` ${getTokenId(node.token)} [label=${JSON.stringify(label)}, fillcolor=${JSON.stringify(fillcolor)}, shape=${JSON.stringify(shape)}];`;
|
|
318
332
|
};
|
|
333
|
+
// --- 2. Render Injector Clusters and Nodes ---
|
|
319
334
|
const injectors = groupByInjector ? Array.from(graph.injectorNames.keys()) : [0];
|
|
320
335
|
for (const injectorId of injectors) {
|
|
321
336
|
if (groupByInjector) {
|
|
@@ -330,11 +345,14 @@ export function renderDependencyGraphToDot(graph, options = {}) {
|
|
|
330
345
|
if (!graph.nodes.has(owner)) {
|
|
331
346
|
continue;
|
|
332
347
|
}
|
|
333
|
-
const subNodes = Array.from(tokens)
|
|
348
|
+
const subNodes = Array.from(tokens)
|
|
349
|
+
.filter((token) => graph.nodes.has(token) && (!groupByInjector || graph.nodes.get(token).injectorId == injectorId))
|
|
350
|
+
.map((token) => graph.nodes.get(token));
|
|
334
351
|
if (subNodes.length == 0) {
|
|
335
352
|
continue;
|
|
336
353
|
}
|
|
337
|
-
|
|
354
|
+
const ownerName = graph.nodes.get(owner).name;
|
|
355
|
+
lines.push(` subgraph cluster_${injectorId}_${getTokenId(owner)} { label = ${JSON.stringify(`Dynamic Resolutions of ${ownerName}`)}; style = dashed; color = "#9b59b6"; fontname = ${JSON.stringify(fontname)}; fontsize = ${fontsize};`);
|
|
338
356
|
for (const node of subNodes) {
|
|
339
357
|
lines.push(renderNode(node));
|
|
340
358
|
inDynamic.add(node.token);
|
|
@@ -351,6 +369,7 @@ export function renderDependencyGraphToDot(graph, options = {}) {
|
|
|
351
369
|
lines.push(' }');
|
|
352
370
|
}
|
|
353
371
|
}
|
|
372
|
+
// --- 3. Render Legend ---
|
|
354
373
|
if (showLegend) {
|
|
355
374
|
const legendFontSize = fontsize - 1;
|
|
356
375
|
lines.push(` subgraph cluster_legend { label = "Legend"; style = solid; color = gray; fontname = ${JSON.stringify(`${fontname}-Bold`)}; fontsize = ${fontsize + 1};`);
|
|
@@ -404,7 +423,9 @@ export function renderDependencyGraphToDot(graph, options = {}) {
|
|
|
404
423
|
lines.push(' l_circular_from -> l_cached_from -> l_optional_from -> l_cross_from [style=invis];');
|
|
405
424
|
lines.push(' l_circular_to -> l_cached_to -> l_optional_to -> l_cross_to [style=invis];');
|
|
406
425
|
lines.push(' l_alias_from -> l_forward_from -> l_dynamic_from -> l_spacer_from [style=invis];');
|
|
426
|
+
lines.push(' }');
|
|
407
427
|
}
|
|
428
|
+
lines.push('}');
|
|
408
429
|
return lines.join('\n');
|
|
409
430
|
}
|
|
410
431
|
/**
|