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.
Files changed (46) hide show
  1. package/README.md +182 -141
  2. package/dist/errors.d.ts +17 -0
  3. package/dist/errors.d.ts.map +1 -0
  4. package/dist/errors.js +26 -0
  5. package/dist/errors.js.map +1 -0
  6. package/dist/index.d.ts +2 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +2 -0
  9. package/dist/index.js.map +1 -1
  10. package/dist/serviceFactory.d.ts +6 -5
  11. package/dist/serviceFactory.d.ts.map +1 -1
  12. package/dist/serviceFactory.js +22 -7
  13. package/dist/serviceFactory.js.map +1 -1
  14. package/dist/serviceFactoryWrapper.d.ts +2 -0
  15. package/dist/serviceFactoryWrapper.d.ts.map +1 -0
  16. package/dist/serviceFactoryWrapper.js +16 -0
  17. package/dist/serviceFactoryWrapper.js.map +1 -0
  18. package/dist/serviceKey.d.ts +84 -0
  19. package/dist/serviceKey.d.ts.map +1 -1
  20. package/dist/serviceKey.js +83 -2
  21. package/dist/serviceKey.js.map +1 -1
  22. package/dist/serviceModule.d.ts +26 -5
  23. package/dist/serviceModule.d.ts.map +1 -1
  24. package/dist/serviceModule.js +106 -15
  25. package/dist/serviceModule.js.map +1 -1
  26. package/dist/serviceSelector.d.ts +64 -0
  27. package/dist/serviceSelector.d.ts.map +1 -0
  28. package/dist/serviceSelector.js +69 -0
  29. package/dist/serviceSelector.js.map +1 -0
  30. package/dist/test-service-selector.d.ts +2 -0
  31. package/dist/test-service-selector.d.ts.map +1 -0
  32. package/dist/test-service-selector.js +110 -0
  33. package/dist/test-service-selector.js.map +1 -0
  34. package/dist/utils.d.ts +33 -6
  35. package/dist/utils.d.ts.map +1 -1
  36. package/dist/utils.js +100 -6
  37. package/dist/utils.js.map +1 -1
  38. package/package.json +45 -41
  39. package/src/errors.ts +23 -0
  40. package/src/index.ts +7 -5
  41. package/src/serviceFactory.ts +104 -83
  42. package/src/serviceKey.ts +95 -8
  43. package/src/serviceModule.ts +223 -123
  44. package/src/serviceScope.ts +7 -7
  45. package/src/serviceSelector.ts +68 -0
  46. 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 {ServiceModule} module - The ServiceModule to convert to DOT notation
21
- * @param {DotGraphOptions} options - Optional configuration for the graph appearance
22
- * @returns {string} A string containing the DOT notation graph
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 {ServiceModule} module - The service module representing the graph to be converted into DOT format.
30
- * @param {DotGraphOptions} [options] - Optional configurations to customize the output of the DOT graph.
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
@@ -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;AASD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,aAAa,EACrB,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,GAAE,eAKtD,GACA,MAAM,CA6FR;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,eAAe,GACxB,IAAI,CAIN"}
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 {ServiceModule} module - The ServiceModule to convert to DOT notation
20
- * @param {DotGraphOptions} options - Optional configuration for the graph appearance
21
- * @returns {string} A string containing the DOT notation graph
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 {ServiceModule} module - The service module representing the graph to be converted into DOT format.
107
- * @param {DotGraphOptions} [options] - Optional configurations to customize the output of the DOT graph.
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":"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"}
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.2.9-ts4",
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
- "license": "MIT",
26
- "repository": {
27
- "type": "git",
28
- "url": "git+https://github.com/imherrera/composed-di.git"
29
- },
30
- "scripts": {
31
- "build": "tsc --build",
32
- "clean": "tsc --build --clean",
33
- "prepublishOnly": "npm run build"
34
- },
35
- "devDependencies": {
36
- "@tsconfig/recommended": "^1.0.10",
37
- "@types/node": "24.0.10",
38
- "prettier": "^3.3.1",
39
- "typescript": "4.9.3"
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 './utils';
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';
@@ -1,83 +1,104 @@
1
- import { ServiceKey } from './serviceKey';
2
- import { ServiceScope } from './serviceScope';
3
-
4
- // Helper types to extract the type from ServiceKey
5
- type ServiceType<T> = T extends ServiceKey<infer U> ? U : never;
6
-
7
- // Helper types to convert an array/tuple of ServiceKey to tuple of their types
8
- type DependencyTypes<T extends readonly ServiceKey<unknown>[]> = {
9
- [K in keyof T]: ServiceType<T[K]>;
10
- };
11
-
12
- export abstract class ServiceFactory<
13
- T,
14
- D extends readonly ServiceKey<unknown>[] = [],
15
- > {
16
- abstract provides: ServiceKey<T>;
17
- abstract dependsOn: D;
18
- abstract scope?: ServiceScope;
19
- abstract initialize: (...dependencies: DependencyTypes<D>) => T | Promise<T>;
20
- abstract dispose?: () => void;
21
-
22
- /**
23
- * Creates a singleton service factory that ensures a single instance of the provided service is initialized
24
- * and used throughout the scope lifecycle.
25
- */
26
- static singleton<
27
- T,
28
- D extends readonly ServiceKey<unknown>[] = [],
29
- >({
30
- scope,
31
- provides,
32
- dependsOn = [] as unknown as D,
33
- initialize,
34
- dispose = () => {},
35
- }: {
36
- scope?: ServiceScope;
37
- provides: ServiceKey<T>;
38
- dependsOn?: D;
39
- initialize: (...dependencies: DependencyTypes<D>) => T | Promise<T>;
40
- dispose?: (instance: T) => void;
41
- }): ServiceFactory<T, D> {
42
- let instance: T | undefined;
43
-
44
- return {
45
- scope,
46
- provides,
47
- dependsOn,
48
- async initialize(...dependencies: DependencyTypes<D>): Promise<T> {
49
- if (instance === undefined) {
50
- instance = await initialize(...dependencies);
51
- }
52
-
53
- return instance;
54
- },
55
- dispose(): void {
56
- if (instance !== undefined) {
57
- dispose(instance);
58
- instance = undefined;
59
- }
60
- },
61
- };
62
- }
63
-
64
- /**
65
- * Creates a one-shot service factory that initializes a new instance of the provided service
66
- * every time it is requested.
67
- */
68
- static oneShot<T, D extends readonly ServiceKey<unknown>[] = []>({
69
- provides,
70
- dependsOn,
71
- initialize,
72
- }: {
73
- provides: ServiceKey<T>;
74
- dependsOn: D;
75
- initialize: (...dependencies: DependencyTypes<D>) => T | Promise<T>;
76
- }): ServiceFactory<T, D> {
77
- return {
78
- provides,
79
- dependsOn,
80
- initialize,
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
- export class ServiceKey<T> {
3
- public readonly symbol: symbol;
4
-
5
- constructor(public readonly name: string) {
6
- this.symbol = Symbol(name);
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
+ }