@khapu2906/treasure-chest 1.4.1 → 1.5.0

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.
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Dependency graph for inspecting and filtering container bindings
3
+ *
4
+ * @module Graph
5
+ */
6
+ import type { Lifecycle, ServiceKey } from './types';
7
+ /** A single node in the dependency graph, representing one registered binding */
8
+ export interface GraphNode {
9
+ /** Stable string form of the service key */
10
+ key: string;
11
+ /** Lifecycle of the binding (transient, singleton, scoped) */
12
+ lifecycle: Lifecycle;
13
+ /** Whether this binding is registered as lazy */
14
+ lazy: boolean;
15
+ /** Context this binding is scoped to, if it's a contextual binding */
16
+ context?: string;
17
+ /** Original key this node is an alias for, if any */
18
+ aliasOf?: string;
19
+ /** Whether this binding comes from a parent or composed container */
20
+ inherited: boolean;
21
+ /** Whether an instance has already been created and cached */
22
+ resolved: boolean;
23
+ }
24
+ /** A directed edge meaning `from` depends on `to` */
25
+ export interface GraphEdge {
26
+ from: string;
27
+ to: string;
28
+ }
29
+ /** Raw data used to build a Graph; produced by Container#graph() */
30
+ export interface GraphSnapshot {
31
+ nodes: GraphNode[];
32
+ edges: GraphEdge[];
33
+ }
34
+ /** A GraphNode nested with its dependencies, for tree-shaped UI rendering */
35
+ export interface GraphTreeNode extends GraphNode {
36
+ children: GraphTreeNode[];
37
+ /**
38
+ * True if this key already appears higher up in the current branch.
39
+ * Recursion stops here instead of looping forever - `children` will be empty.
40
+ */
41
+ cyclic?: boolean;
42
+ }
43
+ /** Criteria for filtering graph nodes */
44
+ export interface GraphNodeFilter {
45
+ /** Only include nodes matching this lifecycle (or one of these) */
46
+ lifecycle?: Lifecycle | Lifecycle[];
47
+ /** Only include nodes whose instance has (or hasn't) been resolved */
48
+ resolved?: boolean;
49
+ /** Only include lazy (or non-lazy) bindings */
50
+ lazy?: boolean;
51
+ /** Only include inherited (or own) bindings */
52
+ inherited?: boolean;
53
+ /** Only include keys matching this substring or RegExp */
54
+ key?: string | RegExp;
55
+ }
56
+ /**
57
+ * Read-only, filterable view over a container's bindings and the
58
+ * dependency edges discovered while resolving them.
59
+ *
60
+ * Edges are recorded as `resolve()` runs, so they only reflect
61
+ * dependencies that have actually been resolved at least once - this is
62
+ * a runtime graph, not a static analysis of factory source code.
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * const graph = container.graph();
67
+ *
68
+ * const singletons = graph.getNodes({ lifecycle: 'singleton' });
69
+ * const unresolved = graph.getNodes({ resolved: false });
70
+ * const deps = graph.dependenciesOf('userService');
71
+ *
72
+ * console.log(graph.toDot()); // paste into a Graphviz viewer
73
+ * ```
74
+ */
75
+ export declare class Graph {
76
+ private readonly nodes;
77
+ private readonly edges;
78
+ private readonly byPlainKey;
79
+ constructor(snapshot: GraphSnapshot);
80
+ /**
81
+ * Get all nodes, optionally filtered
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * graph.getNodes({ lifecycle: ['singleton', 'scoped'], resolved: true });
86
+ * graph.getNodes({ key: /Repository$/ });
87
+ * ```
88
+ */
89
+ getNodes(filter?: GraphNodeFilter): GraphNode[];
90
+ /**
91
+ * Get a single (non-contextual) node by key
92
+ */
93
+ getNode(key: ServiceKey): GraphNode | undefined;
94
+ /**
95
+ * Get all edges, optionally filtered by source and/or target key
96
+ */
97
+ getEdges(filter?: {
98
+ from?: ServiceKey;
99
+ to?: ServiceKey;
100
+ }): GraphEdge[];
101
+ /**
102
+ * Direct dependencies of a key - the services it needs
103
+ */
104
+ dependenciesOf(key: ServiceKey): GraphNode[];
105
+ /**
106
+ * Direct dependents of a key - the services that need it
107
+ */
108
+ dependentsOf(key: ServiceKey): GraphNode[];
109
+ /**
110
+ * Nodes that nothing else depends on (candidate entry points)
111
+ */
112
+ roots(): GraphNode[];
113
+ /**
114
+ * Nodes with no recorded dependencies (leaves of the graph)
115
+ */
116
+ leaves(): GraphNode[];
117
+ /**
118
+ * Build a nested tree starting at `key`, recursively expanding
119
+ * dependencies into `children`. Handy for rendering a dependency tree in
120
+ * a UI (e.g. a collapsible tree view).
121
+ *
122
+ * A node that reappears along the same branch (A depends on B, B depends
123
+ * on A, recorded from two separate resolve() calls) is marked
124
+ * `cyclic: true` instead of recursing forever - `children` stays empty
125
+ * there. Nodes that appear in multiple, unrelated branches (e.g. two
126
+ * services sharing the same `db` dependency) are duplicated as separate
127
+ * tree nodes, which is expected for a tree view.
128
+ *
129
+ * @param key The root key to build the tree from
130
+ * @returns The tree, or undefined if `key` isn't a known node
131
+ *
132
+ * @example
133
+ * ```typescript
134
+ * const tree = container.graph().toTree('service');
135
+ * // { key: 'service', children: [{ key: 'repo', children: [{ key: 'db', children: [] }] }] }
136
+ * ```
137
+ */
138
+ toTree(key: ServiceKey, _visited?: Set<string>): GraphTreeNode | undefined;
139
+ /**
140
+ * Build a tree for every root (nodes nothing else depends on), covering
141
+ * the whole graph at once - ready to hand to a UI as-is.
142
+ *
143
+ * @example
144
+ * ```typescript
145
+ * const forest = container.graph().forest();
146
+ * // [{ key: 'service', children: [...] }, { key: 'unusedSingleton', children: [] }]
147
+ * ```
148
+ */
149
+ forest(): GraphTreeNode[];
150
+ /**
151
+ * Plain JSON-serializable snapshot of the graph
152
+ */
153
+ toJSON(): GraphSnapshot;
154
+ /**
155
+ * Export as Graphviz DOT source, for visualizing the graph
156
+ */
157
+ toDot(): string;
158
+ }
159
+ //# sourceMappingURL=Graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Graph.d.ts","sourceRoot":"","sources":["../../src/Graph.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErD,iFAAiF;AACjF,MAAM,WAAW,SAAS;IACxB,4CAA4C;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,8DAA8D;IAC9D,SAAS,EAAE,SAAS,CAAC;IACrB,iDAAiD;IACjD,IAAI,EAAE,OAAO,CAAC;IACd,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,SAAS,EAAE,OAAO,CAAC;IACnB,8DAA8D;IAC9D,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,qDAAqD;AACrD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,oEAAoE;AACpE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,KAAK,EAAE,SAAS,EAAE,CAAC;CACpB;AAED,6EAA6E;AAC7E,MAAM,WAAW,aAAc,SAAQ,SAAS;IAC9C,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,yCAAyC;AACzC,MAAM,WAAW,eAAe;IAC9B,mEAAmE;IACnE,SAAS,CAAC,EAAE,SAAS,GAAG,SAAS,EAAE,CAAC;IACpC,sEAAsE;IACtE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,+CAA+C;IAC/C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,KAAK;IAChB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IACpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;gBAExC,QAAQ,EAAE,aAAa;IAYnC;;;;;;;;OAQG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,SAAS,EAAE;IAsC/C;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS;IAI/C;;OAEG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,UAAU,CAAC;QAAC,EAAE,CAAC,EAAE,UAAU,CAAA;KAAE,GAAG,SAAS,EAAE;IAgBtE;;OAEG;IACH,cAAc,CAAC,GAAG,EAAE,UAAU,GAAG,SAAS,EAAE;IAQ5C;;OAEG;IACH,YAAY,CAAC,GAAG,EAAE,UAAU,GAAG,SAAS,EAAE;IAQ1C;;OAEG;IACH,KAAK,IAAI,SAAS,EAAE;IAKpB;;OAEG;IACH,MAAM,IAAI,SAAS,EAAE;IAKrB;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CACJ,GAAG,EAAE,UAAU,EACf,QAAQ,GAAE,GAAG,CAAC,MAAM,CAAa,GAChC,aAAa,GAAG,SAAS;IAmB5B;;;;;;;;;OASG;IACH,MAAM,IAAI,aAAa,EAAE;IAMzB;;OAEG;IACH,MAAM,IAAI,aAAa;IAIvB;;OAEG;IACH,KAAK,IAAI,MAAM;CAehB"}
@@ -17,6 +17,7 @@
17
17
  * - High-performance Map-based storage (v1.2.0)
18
18
  * - Auto-dispose for IDisposable instances (v1.2.0)
19
19
  * - Modular architecture (v1.2.0)
20
+ * - Dependency graph inspection with filtering, tree, and DOT export (v1.5.0)
20
21
  *
21
22
  * @example
22
23
  * ```typescript
@@ -30,5 +31,7 @@
30
31
  export { Container } from './Container';
31
32
  export { Lazy } from './Lazy';
32
33
  export { Scope } from './Scope';
33
- export type { Lifecycle, IDisposable, DisposeFn } from './types';
34
+ export { Graph } from './Graph';
35
+ export type { Lifecycle, IDisposable, DisposeFn, ServiceKey } from './types';
36
+ export type { GraphNode, GraphEdge, GraphSnapshot, GraphNodeFilter, GraphTreeNode, } from './Graph';
34
37
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGhC,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGhC,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC7E,YAAY,EACV,SAAS,EACT,SAAS,EACT,aAAa,EACb,eAAe,EACf,aAAa,GACd,MAAM,SAAS,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khapu2906/treasure-chest",
3
- "version": "1.4.1",
3
+ "version": "1.5.0",
4
4
  "description": "A lightweight TypeScript dependency injection container for managing service dependencies",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -43,7 +43,8 @@
43
43
  "example:12": "tsx examples/12-singleton-vs-composition.ts",
44
44
  "example:13": "tsx examples/13-hybrid-architecture.ts",
45
45
  "example:14": "tsx examples/14-explain-composition.ts",
46
- "examples": "npm run example:01 && npm run example:02 && npm run example:03 && npm run example:04 && npm run example:05 && npm run example:06 && npm run example:07 && npm run example:08 && npm run example:09 && npm run example:10 && npm run example:11 && npm run example:12 && npm run example:13 && npm run example:14",
46
+ "example:15": "tsx examples/15-dependency-graph.ts",
47
+ "examples": "npm run example:01 && npm run example:02 && npm run example:03 && npm run example:04 && npm run example:05 && npm run example:06 && npm run example:07 && npm run example:08 && npm run example:09 && npm run example:10 && npm run example:11 && npm run example:12 && npm run example:13 && npm run example:14 && npm run example:15",
47
48
  "lint": "eslint . --ext .ts",
48
49
  "lint:fix": "eslint . --ext .ts --fix",
49
50
  "format": "prettier --write \"**/*.{ts,json,md}\"",