composed-di 0.2.9-ts4 → 0.3.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.
- package/README.md +182 -141
- package/dist/errors.d.ts +17 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +26 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/serviceFactory.d.ts +6 -5
- package/dist/serviceFactory.d.ts.map +1 -1
- package/dist/serviceFactory.js +22 -7
- package/dist/serviceFactory.js.map +1 -1
- package/dist/serviceFactoryWrapper.d.ts +2 -0
- package/dist/serviceFactoryWrapper.d.ts.map +1 -0
- package/dist/serviceFactoryWrapper.js +16 -0
- package/dist/serviceFactoryWrapper.js.map +1 -0
- package/dist/serviceKey.d.ts +84 -0
- package/dist/serviceKey.d.ts.map +1 -1
- package/dist/serviceKey.js +83 -2
- package/dist/serviceKey.js.map +1 -1
- package/dist/serviceModule.d.ts +26 -5
- package/dist/serviceModule.d.ts.map +1 -1
- package/dist/serviceModule.js +106 -15
- package/dist/serviceModule.js.map +1 -1
- package/dist/serviceSelector.d.ts +64 -0
- package/dist/serviceSelector.d.ts.map +1 -0
- package/dist/serviceSelector.js +69 -0
- package/dist/serviceSelector.js.map +1 -0
- package/dist/test-service-selector.d.ts +2 -0
- package/dist/test-service-selector.d.ts.map +1 -0
- package/dist/test-service-selector.js +110 -0
- package/dist/test-service-selector.js.map +1 -0
- package/dist/utils.d.ts +33 -6
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +100 -6
- package/dist/utils.js.map +1 -1
- package/package.json +45 -41
- package/src/errors.ts +23 -0
- package/src/index.ts +7 -5
- package/src/serviceFactory.ts +104 -83
- package/src/serviceKey.ts +95 -8
- package/src/serviceModule.ts +223 -123
- package/src/serviceScope.ts +7 -7
- package/src/serviceSelector.ts +68 -0
- package/src/utils.ts +277 -152
package/dist/utils.d.ts
CHANGED
|
@@ -9,6 +9,14 @@ export interface DotGraphOptions {
|
|
|
9
9
|
/** Show nodes with no dependents in a different color */
|
|
10
10
|
highlightRoots?: boolean;
|
|
11
11
|
}
|
|
12
|
+
export interface MermaidGraphOptions {
|
|
13
|
+
/** Graph direction: 'TB' (top-bottom), 'LR' (left-right), 'BT' (bottom-top), 'RL' (right-left) */
|
|
14
|
+
direction?: 'TB' | 'LR' | 'BT' | 'RL';
|
|
15
|
+
/** Show nodes with no dependencies in a different color */
|
|
16
|
+
highlightLeaves?: boolean;
|
|
17
|
+
/** Show nodes with no dependents in a different color */
|
|
18
|
+
highlightRoots?: boolean;
|
|
19
|
+
}
|
|
12
20
|
/**
|
|
13
21
|
* Generates a DOT notation graph from a ServiceModule.
|
|
14
22
|
* The output can be visualized using Graphviz tools or online viewers like:
|
|
@@ -17,18 +25,37 @@ export interface DotGraphOptions {
|
|
|
17
25
|
*
|
|
18
26
|
* Arrows point from dependencies to dependents (from what is needed to what needs it).
|
|
19
27
|
*
|
|
20
|
-
* @param
|
|
21
|
-
* @param
|
|
22
|
-
* @returns
|
|
28
|
+
* @param module - The ServiceModule to convert to DOT notation
|
|
29
|
+
* @param options - Optional configuration for the graph appearance
|
|
30
|
+
* @returns A string containing the DOT notation graph
|
|
23
31
|
*/
|
|
24
32
|
export declare function createDotGraph(module: ServiceModule, { direction, title, highlightLeaves, highlightRoots }?: DotGraphOptions): string;
|
|
25
33
|
/**
|
|
26
34
|
* Prints a DOT representation of a service module graph to the console.
|
|
27
35
|
* The output can be used to visualize the graph using online graph visualization tools.
|
|
28
36
|
*
|
|
29
|
-
* @param
|
|
30
|
-
* @param
|
|
31
|
-
* @return {void} - This function does not return a value.
|
|
37
|
+
* @param module - The service module representing the graph to be converted into DOT format.
|
|
38
|
+
* @param options - Optional configurations to customize the output of the DOT graph.
|
|
32
39
|
*/
|
|
33
40
|
export declare function printDotGraph(module: ServiceModule, options?: DotGraphOptions): void;
|
|
41
|
+
/**
|
|
42
|
+
* Generates a Mermaid flowchart from a ServiceModule.
|
|
43
|
+
* The output can be visualized using Mermaid-compatible tools or online viewers like:
|
|
44
|
+
* - https://mermaid.live/
|
|
45
|
+
*
|
|
46
|
+
* Arrows point from dependents to dependencies (what needs it -> what provides it).
|
|
47
|
+
*
|
|
48
|
+
* @param module - The ServiceModule to convert to Mermaid notation
|
|
49
|
+
* @param options - Optional configuration for the graph appearance
|
|
50
|
+
* @returns A string containing the Mermaid flowchart
|
|
51
|
+
*/
|
|
52
|
+
export declare function createMermaidGraph(module: ServiceModule, { direction, highlightLeaves, highlightRoots }?: MermaidGraphOptions): string;
|
|
53
|
+
/**
|
|
54
|
+
* Prints a Mermaid representation of a service module graph to the console.
|
|
55
|
+
* The output can be used to visualize the graph using online Mermaid tools.
|
|
56
|
+
*
|
|
57
|
+
* @param module - The service module representing the graph to be converted into Mermaid format.
|
|
58
|
+
* @param options - Optional configurations to customize the output of the Mermaid graph.
|
|
59
|
+
*/
|
|
60
|
+
export declare function printMermaidGraph(module: ServiceModule, options?: MermaidGraphOptions): void;
|
|
34
61
|
//# sourceMappingURL=utils.d.ts.map
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,MAAM,WAAW,eAAe;IAC9B,kGAAkG;IAClG,SAAS,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACtC,0BAA0B;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,yDAAyD;IACzD,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,MAAM,WAAW,eAAe;IAC9B,kGAAkG;IAClG,SAAS,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACtC,0BAA0B;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,yDAAyD;IACzD,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,kGAAkG;IAClG,SAAS,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACtC,2DAA2D;IAC3D,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,yDAAyD;IACzD,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAgBD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,aAAa,EACrB,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,GAAE,eAKtD,GACA,MAAM,CA6FR;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,eAAe,GACxB,IAAI,CAIN;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,aAAa,EACrB,EAAE,SAAS,EAAE,eAAe,EAAE,cAAc,EAAE,GAAE,mBAI/C,GACA,MAAM,CA0ER;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,IAAI,CAIN"}
|
package/dist/utils.js
CHANGED
|
@@ -2,12 +2,20 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createDotGraph = createDotGraph;
|
|
4
4
|
exports.printDotGraph = printDotGraph;
|
|
5
|
+
exports.createMermaidGraph = createMermaidGraph;
|
|
6
|
+
exports.printMermaidGraph = printMermaidGraph;
|
|
5
7
|
/**
|
|
6
8
|
* Escapes special characters in strings for DOT notation
|
|
7
9
|
*/
|
|
8
10
|
function escapeDotString(str) {
|
|
9
11
|
return str.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n');
|
|
10
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Escapes special characters in strings for Mermaid notation
|
|
15
|
+
*/
|
|
16
|
+
function escapeMermaidString(str) {
|
|
17
|
+
return str.replace(/"/g, '#quot;');
|
|
18
|
+
}
|
|
11
19
|
/**
|
|
12
20
|
* Generates a DOT notation graph from a ServiceModule.
|
|
13
21
|
* The output can be visualized using Graphviz tools or online viewers like:
|
|
@@ -16,9 +24,9 @@ function escapeDotString(str) {
|
|
|
16
24
|
*
|
|
17
25
|
* Arrows point from dependencies to dependents (from what is needed to what needs it).
|
|
18
26
|
*
|
|
19
|
-
* @param
|
|
20
|
-
* @param
|
|
21
|
-
* @returns
|
|
27
|
+
* @param module - The ServiceModule to convert to DOT notation
|
|
28
|
+
* @param options - Optional configuration for the graph appearance
|
|
29
|
+
* @returns A string containing the DOT notation graph
|
|
22
30
|
*/
|
|
23
31
|
function createDotGraph(module, { direction, title, highlightLeaves, highlightRoots } = {
|
|
24
32
|
direction: 'TB',
|
|
@@ -103,13 +111,99 @@ function createDotGraph(module, { direction, title, highlightLeaves, highlightRo
|
|
|
103
111
|
* Prints a DOT representation of a service module graph to the console.
|
|
104
112
|
* The output can be used to visualize the graph using online graph visualization tools.
|
|
105
113
|
*
|
|
106
|
-
* @param
|
|
107
|
-
* @param
|
|
108
|
-
* @return {void} - This function does not return a value.
|
|
114
|
+
* @param module - The service module representing the graph to be converted into DOT format.
|
|
115
|
+
* @param options - Optional configurations to customize the output of the DOT graph.
|
|
109
116
|
*/
|
|
110
117
|
function printDotGraph(module, options) {
|
|
111
118
|
console.log(createDotGraph(module, options));
|
|
112
119
|
console.log('\n\nCopy the DOT output above and paste it into:');
|
|
113
120
|
console.log('https://dreampuf.github.io/GraphvizOnline/');
|
|
114
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* Generates a Mermaid flowchart from a ServiceModule.
|
|
124
|
+
* The output can be visualized using Mermaid-compatible tools or online viewers like:
|
|
125
|
+
* - https://mermaid.live/
|
|
126
|
+
*
|
|
127
|
+
* Arrows point from dependents to dependencies (what needs it -> what provides it).
|
|
128
|
+
*
|
|
129
|
+
* @param module - The ServiceModule to convert to Mermaid notation
|
|
130
|
+
* @param options - Optional configuration for the graph appearance
|
|
131
|
+
* @returns A string containing the Mermaid flowchart
|
|
132
|
+
*/
|
|
133
|
+
function createMermaidGraph(module, { direction, highlightLeaves, highlightRoots } = {
|
|
134
|
+
direction: 'TB',
|
|
135
|
+
highlightLeaves: true,
|
|
136
|
+
highlightRoots: true,
|
|
137
|
+
}) {
|
|
138
|
+
const factories = module.factories;
|
|
139
|
+
const lines = [];
|
|
140
|
+
// Start the flowchart
|
|
141
|
+
lines.push(`flowchart ${direction}`);
|
|
142
|
+
// Build dependency maps to identify leaves and roots
|
|
143
|
+
const hasDependencies = new Set();
|
|
144
|
+
const hasDependents = new Set();
|
|
145
|
+
factories.forEach((factory) => {
|
|
146
|
+
const serviceName = factory.provides.name;
|
|
147
|
+
if (factory.dependsOn.length > 0) {
|
|
148
|
+
hasDependencies.add(serviceName);
|
|
149
|
+
}
|
|
150
|
+
factory.dependsOn.forEach((dependency) => {
|
|
151
|
+
hasDependents.add(dependency.name);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
// Define nodes with special styling for leaves and roots
|
|
155
|
+
const nodeIds = new Map();
|
|
156
|
+
let nodeCounter = 0;
|
|
157
|
+
factories.forEach((factory) => {
|
|
158
|
+
const serviceName = factory.provides.name;
|
|
159
|
+
const nodeId = `node${nodeCounter++}`;
|
|
160
|
+
nodeIds.set(serviceName, nodeId);
|
|
161
|
+
lines.push(` ${nodeId}["${escapeMermaidString(serviceName)}"]`);
|
|
162
|
+
});
|
|
163
|
+
lines.push('');
|
|
164
|
+
// Define edges (dependencies)
|
|
165
|
+
factories.forEach((factory) => {
|
|
166
|
+
const serviceName = factory.provides.name;
|
|
167
|
+
const serviceNodeId = nodeIds.get(serviceName);
|
|
168
|
+
factory.dependsOn.forEach((dependency) => {
|
|
169
|
+
const depName = dependency.name;
|
|
170
|
+
const depNodeId = nodeIds.get(depName);
|
|
171
|
+
if (depNodeId) {
|
|
172
|
+
// Arrow points from dependent to dependency (what needs it -> what provides it)
|
|
173
|
+
lines.push(` ${serviceNodeId} --> ${depNodeId}`);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
lines.push('');
|
|
178
|
+
// Apply styling
|
|
179
|
+
factories.forEach((factory) => {
|
|
180
|
+
const serviceName = factory.provides.name;
|
|
181
|
+
const serviceNodeId = nodeIds.get(serviceName);
|
|
182
|
+
const isLeaf = !hasDependencies.has(serviceName);
|
|
183
|
+
const isRoot = !hasDependents.has(serviceName);
|
|
184
|
+
if (highlightLeaves && isLeaf) {
|
|
185
|
+
lines.push(` style ${serviceNodeId} fill:#c8e6c9,stroke:#388e3c`);
|
|
186
|
+
}
|
|
187
|
+
else if (highlightRoots && isRoot) {
|
|
188
|
+
lines.push(` style ${serviceNodeId} fill:#ffccbc,stroke:#d84315`);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
// Default style
|
|
192
|
+
lines.push(` style ${serviceNodeId} fill:#e1f5ff,stroke:#0288d1`);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
return lines.join('\n');
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Prints a Mermaid representation of a service module graph to the console.
|
|
199
|
+
* The output can be used to visualize the graph using online Mermaid tools.
|
|
200
|
+
*
|
|
201
|
+
* @param module - The service module representing the graph to be converted into Mermaid format.
|
|
202
|
+
* @param options - Optional configurations to customize the output of the Mermaid graph.
|
|
203
|
+
*/
|
|
204
|
+
function printMermaidGraph(module, options) {
|
|
205
|
+
console.log(createMermaidGraph(module, options));
|
|
206
|
+
console.log('\n\nCopy the Mermaid output above and paste it into:');
|
|
207
|
+
console.log('https://mermaid.live/');
|
|
208
|
+
}
|
|
115
209
|
//# sourceMappingURL=utils.js.map
|
package/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,41 +1,45 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "composed-di",
|
|
3
|
-
"private": false,
|
|
4
|
-
"version": "0.
|
|
5
|
-
"author": "Juan Herrera juanhr454@gmail.com",
|
|
6
|
-
"type": "commonjs",
|
|
7
|
-
"main": "./dist/index.js",
|
|
8
|
-
"types": "./dist/index.d.ts",
|
|
9
|
-
"exports": {
|
|
10
|
-
".": {
|
|
11
|
-
"types": "./dist/index.d.ts",
|
|
12
|
-
"require": "./dist/index.js",
|
|
13
|
-
"default": "./dist/index.js"
|
|
14
|
-
}
|
|
15
|
-
},
|
|
16
|
-
"files": [
|
|
17
|
-
"dist",
|
|
18
|
-
"src"
|
|
19
|
-
],
|
|
20
|
-
"sideEffects": false,
|
|
21
|
-
"keywords": [
|
|
22
|
-
"dependency injection",
|
|
23
|
-
"di"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "composed-di",
|
|
3
|
+
"private": false,
|
|
4
|
+
"version": "0.3.0",
|
|
5
|
+
"author": "Juan Herrera juanhr454@gmail.com",
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"require": "./dist/index.js",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"src"
|
|
19
|
+
],
|
|
20
|
+
"sideEffects": false,
|
|
21
|
+
"keywords": [
|
|
22
|
+
"dependency injection",
|
|
23
|
+
"di",
|
|
24
|
+
"lazy dependency injection"
|
|
25
|
+
],
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/imherrera/composed-di.git"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsc --build",
|
|
33
|
+
"clean": "tsc --build --clean",
|
|
34
|
+
"prepublishOnly": "npm run build",
|
|
35
|
+
"test": "vitest run",
|
|
36
|
+
"test:watch": "vitest"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@tsconfig/recommended": "^1.0.10",
|
|
40
|
+
"@types/node": "24.0.10",
|
|
41
|
+
"prettier": "^3.3.1",
|
|
42
|
+
"typescript": "^5.2.2",
|
|
43
|
+
"vitest": "^4.0.16"
|
|
44
|
+
}
|
|
45
|
+
}
|
package/src/errors.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error thrown when there is an issue during the initialization or configuration of a ServiceModule.
|
|
3
|
+
* This can include circular dependencies or missing dependencies that are detected during module creation.
|
|
4
|
+
*/
|
|
5
|
+
export class ServiceModuleInitError extends Error {
|
|
6
|
+
name = 'ServiceModuleInitError';
|
|
7
|
+
|
|
8
|
+
constructor(message: string) {
|
|
9
|
+
super(message);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Error thrown when a requested service cannot be found within the ServiceModule.
|
|
15
|
+
* This typically occurs when no factory has been registered for the given ServiceKey.
|
|
16
|
+
*/
|
|
17
|
+
export class ServiceFactoryNotFoundError extends Error {
|
|
18
|
+
name = 'ServiceFactoryNotFoundError';
|
|
19
|
+
|
|
20
|
+
constructor(message: string) {
|
|
21
|
+
super(message);
|
|
22
|
+
}
|
|
23
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
export * from './serviceKey';
|
|
2
|
-
export * from './serviceModule';
|
|
3
|
-
export * from './serviceFactory';
|
|
4
|
-
export * from './serviceScope';
|
|
5
|
-
export * from './
|
|
1
|
+
export * from './serviceKey';
|
|
2
|
+
export * from './serviceModule';
|
|
3
|
+
export * from './serviceFactory';
|
|
4
|
+
export * from './serviceScope';
|
|
5
|
+
export * from './serviceSelector';
|
|
6
|
+
export * from './errors';
|
|
7
|
+
export * from './utils';
|
package/src/serviceFactory.ts
CHANGED
|
@@ -1,83 +1,104 @@
|
|
|
1
|
-
import { ServiceKey } from './serviceKey';
|
|
2
|
-
import { ServiceScope } from './serviceScope';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
scope
|
|
37
|
-
provides
|
|
38
|
-
dependsOn
|
|
39
|
-
initialize
|
|
40
|
-
dispose
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
1
|
+
import { ServiceKey, ServiceSelectorKey } from './serviceKey';
|
|
2
|
+
import { ServiceScope } from './serviceScope';
|
|
3
|
+
import { ServiceSelector } from './serviceSelector';
|
|
4
|
+
|
|
5
|
+
// Helper types to extract the type from ServiceKey or ServiceSelectorKey
|
|
6
|
+
type ServiceType<T> =
|
|
7
|
+
T extends ServiceSelectorKey<infer U>
|
|
8
|
+
? ServiceSelector<U>
|
|
9
|
+
: T extends ServiceKey<infer U>
|
|
10
|
+
? U
|
|
11
|
+
: never;
|
|
12
|
+
|
|
13
|
+
// Helper types to convert an array/tuple of ServiceKey to tuple of their types
|
|
14
|
+
type DependencyTypes<T extends readonly ServiceKey<unknown>[]> = {
|
|
15
|
+
[K in keyof T]: ServiceType<T[K]>;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export abstract class ServiceFactory<
|
|
19
|
+
const T,
|
|
20
|
+
const D extends readonly ServiceKey<unknown>[] = [],
|
|
21
|
+
> {
|
|
22
|
+
abstract provides: ServiceKey<T>;
|
|
23
|
+
abstract dependsOn: D;
|
|
24
|
+
abstract scope?: ServiceScope;
|
|
25
|
+
abstract initialize: (...dependencies: DependencyTypes<D>) => T | Promise<T>;
|
|
26
|
+
abstract dispose?: () => void;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Creates a singleton service factory that ensures a single instance of the provided service is initialized
|
|
30
|
+
* and used throughout the scope lifecycle.
|
|
31
|
+
*/
|
|
32
|
+
static singleton<
|
|
33
|
+
const T,
|
|
34
|
+
const D extends readonly ServiceKey<unknown>[] = [],
|
|
35
|
+
>({
|
|
36
|
+
scope,
|
|
37
|
+
provides,
|
|
38
|
+
dependsOn = [] as unknown as D,
|
|
39
|
+
initialize,
|
|
40
|
+
dispose = () => {},
|
|
41
|
+
}: {
|
|
42
|
+
scope?: ServiceScope;
|
|
43
|
+
provides: ServiceKey<T>;
|
|
44
|
+
dependsOn?: D;
|
|
45
|
+
initialize: (...dependencies: DependencyTypes<D>) => T | Promise<T>;
|
|
46
|
+
dispose?: (instance: T) => void;
|
|
47
|
+
}): ServiceFactory<T, D> {
|
|
48
|
+
let promisedInstance: Promise<T> | undefined;
|
|
49
|
+
let resolvedInstance: T | undefined;
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
scope,
|
|
53
|
+
provides,
|
|
54
|
+
dependsOn,
|
|
55
|
+
async initialize(...dependencies: DependencyTypes<D>): Promise<T> {
|
|
56
|
+
if (resolvedInstance !== undefined) {
|
|
57
|
+
return resolvedInstance;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (promisedInstance !== undefined) {
|
|
61
|
+
return promisedInstance;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Store the reference to the promise so that concurrent requests can wait for it
|
|
65
|
+
promisedInstance = (async () => {
|
|
66
|
+
try {
|
|
67
|
+
resolvedInstance = await initialize(...dependencies);
|
|
68
|
+
return resolvedInstance;
|
|
69
|
+
} finally {
|
|
70
|
+
promisedInstance = undefined;
|
|
71
|
+
}
|
|
72
|
+
})();
|
|
73
|
+
return promisedInstance;
|
|
74
|
+
},
|
|
75
|
+
dispose(): void {
|
|
76
|
+
if (resolvedInstance !== undefined) {
|
|
77
|
+
dispose(resolvedInstance);
|
|
78
|
+
resolvedInstance = undefined;
|
|
79
|
+
}
|
|
80
|
+
promisedInstance = undefined;
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Creates a one-shot service factory that initializes a new instance of the provided service
|
|
87
|
+
* every time it is requested.
|
|
88
|
+
*/
|
|
89
|
+
static oneShot<const T, const D extends readonly ServiceKey<unknown>[] = []>({
|
|
90
|
+
provides,
|
|
91
|
+
dependsOn,
|
|
92
|
+
initialize,
|
|
93
|
+
}: {
|
|
94
|
+
provides: ServiceKey<T>;
|
|
95
|
+
dependsOn: D;
|
|
96
|
+
initialize: (...dependencies: DependencyTypes<D>) => T | Promise<T>;
|
|
97
|
+
}): ServiceFactory<T, D> {
|
|
98
|
+
return {
|
|
99
|
+
provides,
|
|
100
|
+
dependsOn,
|
|
101
|
+
initialize,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
package/src/serviceKey.ts
CHANGED
|
@@ -1,8 +1,95 @@
|
|
|
1
|
-
// @ts-ignore
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
// @ts-ignore
|
|
2
|
+
import { ServiceSelector } from './serviceSelector';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A typed token used to identify and retrieve a service from a ServiceModule.
|
|
6
|
+
*
|
|
7
|
+
* ServiceKey acts as a unique identifier for a service type, allowing type-safe
|
|
8
|
+
* dependency injection. Each key has a unique symbol to ensure identity comparison
|
|
9
|
+
* works correctly even if two keys have the same name.
|
|
10
|
+
*
|
|
11
|
+
* @template T The type of service this key identifies.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* interface Logger {
|
|
16
|
+
* log: (msg: string) => void;
|
|
17
|
+
* }
|
|
18
|
+
*
|
|
19
|
+
* const LoggerKey = new ServiceKey<Logger>('Logger');
|
|
20
|
+
*
|
|
21
|
+
* // Use with ServiceFactory and ServiceModule
|
|
22
|
+
* const loggerFactory = ServiceFactory.singleton({
|
|
23
|
+
* provides: LoggerKey,
|
|
24
|
+
* dependsOn: [],
|
|
25
|
+
* initialize: () => console,
|
|
26
|
+
* });
|
|
27
|
+
*
|
|
28
|
+
* const module = ServiceModule.from([loggerFactory]);
|
|
29
|
+
* const logger = await module.get(LoggerKey);
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export class ServiceKey<T> {
|
|
33
|
+
/**
|
|
34
|
+
* A unique symbol that identifies this service key.
|
|
35
|
+
* Used internally for identity comparison between keys.
|
|
36
|
+
*/
|
|
37
|
+
public readonly symbol: symbol;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Creates a new ServiceKey with the given name.
|
|
41
|
+
*
|
|
42
|
+
* @param name A human-readable name for the service, used in error messages and debugging.
|
|
43
|
+
*/
|
|
44
|
+
constructor(public readonly name: string) {
|
|
45
|
+
this.symbol = Symbol(name);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* A specialized ServiceKey that groups multiple ServiceKeys of the same type,
|
|
51
|
+
* allowing a service to depend on a selector that can retrieve any of the grouped services.
|
|
52
|
+
*
|
|
53
|
+
* When used in a factory's `dependsOn` array, the factory's `initialize` callback
|
|
54
|
+
* receives a `ServiceSelector<T>` instance instead of a direct service instance.
|
|
55
|
+
* This enables runtime selection between multiple implementations of the same interface.
|
|
56
|
+
*
|
|
57
|
+
* @template T The common type shared by all service keys in this selector.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* interface Logger {
|
|
62
|
+
* log: (msg: string) => void;
|
|
63
|
+
* }
|
|
64
|
+
*
|
|
65
|
+
* const ConsoleLoggerKey = new ServiceKey<Logger>('ConsoleLogger');
|
|
66
|
+
* const FileLoggerKey = new ServiceKey<Logger>('FileLogger');
|
|
67
|
+
*
|
|
68
|
+
* // Group multiple logger implementations under one selector
|
|
69
|
+
* const LoggerSelectorKey = new ServiceSelectorKey<Logger>([
|
|
70
|
+
* ConsoleLoggerKey,
|
|
71
|
+
* FileLoggerKey,
|
|
72
|
+
* ]);
|
|
73
|
+
*
|
|
74
|
+
* // Use in a factory's dependsOn array
|
|
75
|
+
* const appFactory = ServiceFactory.singleton({
|
|
76
|
+
* provides: AppKey,
|
|
77
|
+
* dependsOn: [LoggerSelectorKey] as const,
|
|
78
|
+
* initialize: (loggerSelector: ServiceSelector<Logger>) => {
|
|
79
|
+
* // loggerSelector.get(ConsoleLoggerKey) or loggerSelector.get(FileLoggerKey)
|
|
80
|
+
* return new App(loggerSelector);
|
|
81
|
+
* },
|
|
82
|
+
* });
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export class ServiceSelectorKey<T> extends ServiceKey<ServiceSelector<T>> {
|
|
86
|
+
/**
|
|
87
|
+
* Creates a new ServiceSelectorKey that groups the provided service keys.
|
|
88
|
+
*
|
|
89
|
+
* @param values An array of ServiceKeys that this selector can provide access to.
|
|
90
|
+
* All keys must be registered in the ServiceModule for dependency validation to pass.
|
|
91
|
+
*/
|
|
92
|
+
constructor(readonly values: ServiceKey<T>[]) {
|
|
93
|
+
super(`ServiceSelector[${values}]`);
|
|
94
|
+
}
|
|
95
|
+
}
|