composed-di 0.2.9 → 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 (62) 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 +3 -2
  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 +25 -4
  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 +2 -0
  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 +131 -6
  47. package/dist/main.d.ts +0 -2
  48. package/dist/main.d.ts.map +0 -1
  49. package/dist/main.js +0 -15
  50. package/dist/main.js.map +0 -1
  51. package/dist/plugin/index.d.ts +0 -66
  52. package/dist/plugin/index.d.ts.map +0 -1
  53. package/dist/plugin/index.js +0 -397
  54. package/dist/plugin/index.js.map +0 -1
  55. package/dist/serviceProvider.d.ts +0 -5
  56. package/dist/serviceProvider.d.ts.map +0 -1
  57. package/dist/serviceProvider.js +0 -3
  58. package/dist/serviceProvider.js.map +0 -1
  59. package/dist/test-from.d.ts +0 -2
  60. package/dist/test-from.d.ts.map +0 -1
  61. package/dist/test-from.js +0 -68
  62. package/dist/test-from.js.map +0 -1
@@ -1,12 +1,93 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ServiceKey = void 0;
4
- // @ts-ignore
3
+ exports.ServiceSelectorKey = exports.ServiceKey = void 0;
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
+ */
5
32
  class ServiceKey {
33
+ /**
34
+ * Creates a new ServiceKey with the given name.
35
+ *
36
+ * @param name A human-readable name for the service, used in error messages and debugging.
37
+ */
6
38
  constructor(name) {
7
39
  this.name = name;
8
40
  this.symbol = Symbol(name);
9
41
  }
10
42
  }
11
43
  exports.ServiceKey = ServiceKey;
44
+ /**
45
+ * A specialized ServiceKey that groups multiple ServiceKeys of the same type,
46
+ * allowing a service to depend on a selector that can retrieve any of the grouped services.
47
+ *
48
+ * When used in a factory's `dependsOn` array, the factory's `initialize` callback
49
+ * receives a `ServiceSelector<T>` instance instead of a direct service instance.
50
+ * This enables runtime selection between multiple implementations of the same interface.
51
+ *
52
+ * @template T The common type shared by all service keys in this selector.
53
+ *
54
+ * @example
55
+ * ```ts
56
+ * interface Logger {
57
+ * log: (msg: string) => void;
58
+ * }
59
+ *
60
+ * const ConsoleLoggerKey = new ServiceKey<Logger>('ConsoleLogger');
61
+ * const FileLoggerKey = new ServiceKey<Logger>('FileLogger');
62
+ *
63
+ * // Group multiple logger implementations under one selector
64
+ * const LoggerSelectorKey = new ServiceSelectorKey<Logger>([
65
+ * ConsoleLoggerKey,
66
+ * FileLoggerKey,
67
+ * ]);
68
+ *
69
+ * // Use in a factory's dependsOn array
70
+ * const appFactory = ServiceFactory.singleton({
71
+ * provides: AppKey,
72
+ * dependsOn: [LoggerSelectorKey] as const,
73
+ * initialize: (loggerSelector: ServiceSelector<Logger>) => {
74
+ * // loggerSelector.get(ConsoleLoggerKey) or loggerSelector.get(FileLoggerKey)
75
+ * return new App(loggerSelector);
76
+ * },
77
+ * });
78
+ * ```
79
+ */
80
+ class ServiceSelectorKey extends ServiceKey {
81
+ /**
82
+ * Creates a new ServiceSelectorKey that groups the provided service keys.
83
+ *
84
+ * @param values An array of ServiceKeys that this selector can provide access to.
85
+ * All keys must be registered in the ServiceModule for dependency validation to pass.
86
+ */
87
+ constructor(values) {
88
+ super(`ServiceSelector[${values}]`);
89
+ this.values = values;
90
+ }
91
+ }
92
+ exports.ServiceSelectorKey = ServiceSelectorKey;
12
93
  //# sourceMappingURL=serviceKey.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"serviceKey.js","sourceRoot":"","sources":["../src/serviceKey.ts"],"names":[],"mappings":";;;AAAA,aAAa;AACb,MAAa,UAAU;IAGrB,YAA4B,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;QACtC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;CACF;AAND,gCAMC"}
1
+ {"version":3,"file":"serviceKey.js","sourceRoot":"","sources":["../src/serviceKey.ts"],"names":[],"mappings":";;;AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAa,UAAU;IAOrB;;;;OAIG;IACH,YAA4B,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;QACtC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;CACF;AAfD,gCAeC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAa,kBAAsB,SAAQ,UAA8B;IACvE;;;;;OAKG;IACH,YAAqB,MAAuB;QAC1C,KAAK,CAAC,mBAAmB,MAAM,GAAG,CAAC,CAAC;QADjB,WAAM,GAAN,MAAM,CAAiB;IAE5C,CAAC;CACF;AAVD,gDAUC"}
@@ -2,9 +2,29 @@ import { ServiceKey } from './serviceKey';
2
2
  import { ServiceFactory } from './serviceFactory';
3
3
  import { ServiceScope } from './serviceScope';
4
4
  type GenericFactory = ServiceFactory<unknown, readonly ServiceKey<any>[]>;
5
+ /**
6
+ * ServiceModule is a container for service factories and manages dependency resolution.
7
+ *
8
+ * It provides a way to retrieve service instances based on their ServiceKey,
9
+ * ensuring that all dependencies are resolved and initialized in the correct order.
10
+ * It also handles circular dependency detection and missing dependency validation
11
+ * at the time of module creation.
12
+ */
5
13
  export declare class ServiceModule {
6
14
  readonly factories: GenericFactory[];
15
+ /**
16
+ * Private constructor to enforce module creation through the `static from` method.
17
+ *
18
+ * @param factories An array of service factories that this module will manage.
19
+ */
7
20
  private constructor();
21
+ /**
22
+ * Retrieves an instance for the given ServiceKey.
23
+ *
24
+ * @param key - The key of the service to retrieve.
25
+ * @return A promise that resolves to the service instance.
26
+ * @throws {ServiceFactoryNotFoundError} If no suitable factory is found for the given key.
27
+ */
8
28
  get<T>(key: ServiceKey<T>): Promise<T>;
9
29
  /**
10
30
  * Disposes of service factories within the specified scope or all factories if no scope is provided.
@@ -12,9 +32,9 @@ export declare class ServiceModule {
12
32
  * This method is useful for cleaning up resources and instances held by service factories,
13
33
  * such as singleton factories, as they may hold database connections or other resources that need to be released.
14
34
  *
15
- * @param {ServiceScope} [scope] The scope to filter the factories to be disposed.
35
+ * @param scope The scope to filter the factories to be disposed.
16
36
  * If not provided, all factories are disposed of.
17
- * @return {void} No return value.
37
+ * @return No return value.
18
38
  */
19
39
  dispose(scope?: ServiceScope): void;
20
40
  /**
@@ -23,9 +43,10 @@ export declare class ServiceModule {
23
43
  * If multiple factories provide the same
24
44
  * ServiceKey, the last one in the list takes precedence.
25
45
  *
26
- * @param {Array<ServiceModule | GenericFactory>} entries - An array of ServiceModule or GenericFactory
46
+ * @param entries - An array of ServiceModule or GenericFactory
27
47
  * instances to be processed into a single ServiceModule.
28
- * @return {ServiceModule} A new ServiceModule containing the deduplicated factories.
48
+ * @return A new ServiceModule containing the deduplicated factories.
49
+ * @throws {ServiceModuleInitError} If circular or missing dependencies are detected during module creation.
29
50
  */
30
51
  static from(entries: (ServiceModule | GenericFactory)[]): ServiceModule;
31
52
  }
@@ -1 +1 @@
1
- {"version":3,"file":"serviceModule.d.ts","sourceRoot":"","sources":["../src/serviceModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,KAAK,cAAc,GAAG,cAAc,CAAC,OAAO,EAAE,SAAS,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAG1E,qBAAa,aAAa;IACJ,QAAQ,CAAC,SAAS,EAAE,cAAc,EAAE;IAAxD,OAAO;IAOM,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAqBnD;;;;;;;;;OASG;IACI,OAAO,CAAC,KAAK,CAAC,EAAE,YAAY;IAQnC;;;;;;;;;OASG;IACH,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,aAAa,GAAG,cAAc,CAAC,EAAE,GAAG,aAAa;CAcxE"}
1
+ {"version":3,"file":"serviceModule.d.ts","sourceRoot":"","sources":["../src/serviceModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAI9C,KAAK,cAAc,GAAG,cAAc,CAAC,OAAO,EAAE,SAAS,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAG1E;;;;;;;GAOG;AACH,qBAAa,aAAa;IAMJ,QAAQ,CAAC,SAAS,EAAE,cAAc,EAAE;IALxD;;;;OAIG;IACH,OAAO;IAOP;;;;;;OAMG;IACU,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IA2BnD;;;;;;;;;OASG;IACI,OAAO,CAAC,KAAK,CAAC,EAAE,YAAY;IAQnC;;;;;;;;;;OAUG;IACH,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,aAAa,GAAG,cAAc,CAAC,EAAE,GAAG,aAAa;CAcxE"}
@@ -10,14 +10,37 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.ServiceModule = void 0;
13
+ const serviceKey_1 = require("./serviceKey");
14
+ const serviceSelector_1 = require("./serviceSelector");
15
+ const errors_1 = require("./errors");
16
+ /**
17
+ * ServiceModule is a container for service factories and manages dependency resolution.
18
+ *
19
+ * It provides a way to retrieve service instances based on their ServiceKey,
20
+ * ensuring that all dependencies are resolved and initialized in the correct order.
21
+ * It also handles circular dependency detection and missing dependency validation
22
+ * at the time of module creation.
23
+ */
13
24
  class ServiceModule {
25
+ /**
26
+ * Private constructor to enforce module creation through the `static from` method.
27
+ *
28
+ * @param factories An array of service factories that this module will manage.
29
+ */
14
30
  constructor(factories) {
15
31
  this.factories = factories;
32
+ checkCircularDependencies(this.factories);
16
33
  factories.forEach((factory) => {
17
- checkRecursiveDependencies(factory);
18
34
  checkMissingDependencies(factory, this.factories);
19
35
  });
20
36
  }
37
+ /**
38
+ * Retrieves an instance for the given ServiceKey.
39
+ *
40
+ * @param key - The key of the service to retrieve.
41
+ * @return A promise that resolves to the service instance.
42
+ * @throws {ServiceFactoryNotFoundError} If no suitable factory is found for the given key.
43
+ */
21
44
  get(key) {
22
45
  return __awaiter(this, void 0, void 0, function* () {
23
46
  const factory = this.factories.find((factory) => {
@@ -25,10 +48,14 @@ class ServiceModule {
25
48
  });
26
49
  // Check if a factory to supply the requested key was not found
27
50
  if (!factory) {
28
- throw new Error(`Could not find a suitable factory for ${key.name}`);
51
+ throw new errors_1.ServiceFactoryNotFoundError(`Could not find a suitable factory for ${key.name}`);
29
52
  }
30
53
  // Resolve all dependencies first
31
54
  const dependencies = yield Promise.all(factory.dependsOn.map((dependencyKey) => {
55
+ // If the dependency is a ServiceSelectorKey, create a ServiceSelector instance
56
+ if (dependencyKey instanceof serviceKey_1.ServiceSelectorKey) {
57
+ return new serviceSelector_1.ServiceSelector(this, dependencyKey);
58
+ }
32
59
  return this.get(dependencyKey);
33
60
  }));
34
61
  // Call the factory to retrieve the dependency
@@ -41,9 +68,9 @@ class ServiceModule {
41
68
  * This method is useful for cleaning up resources and instances held by service factories,
42
69
  * such as singleton factories, as they may hold database connections or other resources that need to be released.
43
70
  *
44
- * @param {ServiceScope} [scope] The scope to filter the factories to be disposed.
71
+ * @param scope The scope to filter the factories to be disposed.
45
72
  * If not provided, all factories are disposed of.
46
- * @return {void} No return value.
73
+ * @return No return value.
47
74
  */
48
75
  dispose(scope) {
49
76
  const factories = scope
@@ -57,9 +84,10 @@ class ServiceModule {
57
84
  * If multiple factories provide the same
58
85
  * ServiceKey, the last one in the list takes precedence.
59
86
  *
60
- * @param {Array<ServiceModule | GenericFactory>} entries - An array of ServiceModule or GenericFactory
87
+ * @param entries - An array of ServiceModule or GenericFactory
61
88
  * instances to be processed into a single ServiceModule.
62
- * @return {ServiceModule} A new ServiceModule containing the deduplicated factories.
89
+ * @return A new ServiceModule containing the deduplicated factories.
90
+ * @throws {ServiceModuleInitError} If circular or missing dependencies are detected during module creation.
63
91
  */
64
92
  static from(entries) {
65
93
  // Flatten entries and keep only the last factory for each ServiceKey
@@ -73,17 +101,66 @@ class ServiceModule {
73
101
  }
74
102
  }
75
103
  exports.ServiceModule = ServiceModule;
76
- function checkRecursiveDependencies(factory) {
77
- const recursive = factory.dependsOn.some((dependencyKey) => {
78
- return dependencyKey === factory.provides;
79
- });
80
- if (recursive) {
81
- throw new Error('Recursive dependency detected on: ' + factory.provides.name);
104
+ /**
105
+ * Validates that there are no circular dependencies among the provided factories.
106
+ *
107
+ * @param factories The list of factories to check for cycles.
108
+ * @throws {ServiceModuleInitError} If a circular dependency is detected.
109
+ */
110
+ function checkCircularDependencies(factories) {
111
+ const factoryMap = new Map();
112
+ for (const f of factories) {
113
+ factoryMap.set(f.provides.symbol, f);
114
+ }
115
+ const visited = new Set();
116
+ const stack = new Set();
117
+ function walk(factory, path) {
118
+ const symbol = factory.provides.symbol;
119
+ if (stack.has(symbol)) {
120
+ const cyclePath = [...path, factory.provides.name].join(' -> ');
121
+ throw new errors_1.ServiceModuleInitError(`Circular dependency detected: ${cyclePath}`);
122
+ }
123
+ if (visited.has(symbol)) {
124
+ return;
125
+ }
126
+ visited.add(symbol);
127
+ stack.add(symbol);
128
+ for (const depKey of factory.dependsOn) {
129
+ const keysToCheck = depKey instanceof serviceKey_1.ServiceSelectorKey ? depKey.values : [depKey];
130
+ for (const key of keysToCheck) {
131
+ const depFactory = factoryMap.get(key.symbol);
132
+ if (depFactory) {
133
+ walk(depFactory, [...path, factory.provides.name]);
134
+ }
135
+ }
136
+ }
137
+ stack.delete(symbol);
138
+ }
139
+ for (const factory of factories) {
140
+ walk(factory, []);
82
141
  }
83
142
  }
143
+ /**
144
+ * Validates that all dependencies of a given factory are present in the list of factories.
145
+ *
146
+ * @param factory The factory whose dependencies are to be checked.
147
+ * @param factories The list of available factories in the module.
148
+ * @throws {ServiceModuleInitError} If any dependency is missing.
149
+ */
84
150
  function checkMissingDependencies(factory, factories) {
85
- const missingDependencies = factory.dependsOn.filter((dependencyKey) => {
86
- return !isRegistered(dependencyKey, factories);
151
+ const missingDependencies = [];
152
+ factory.dependsOn.forEach((dependencyKey) => {
153
+ // For ServiceSelectorKey, check all contained keys are registered
154
+ if (dependencyKey instanceof serviceKey_1.ServiceSelectorKey) {
155
+ dependencyKey.values.forEach((key) => {
156
+ if (!isRegistered(key, factories)) {
157
+ missingDependencies.push(key);
158
+ }
159
+ });
160
+ }
161
+ else if (!isRegistered(dependencyKey, factories)) {
162
+ missingDependencies.push(dependencyKey);
163
+ }
87
164
  });
88
165
  if (missingDependencies.length === 0) {
89
166
  return;
@@ -91,11 +168,25 @@ function checkMissingDependencies(factory, factories) {
91
168
  const dependencyList = missingDependencies
92
169
  .map((dependencyKey) => ` -> ${dependencyKey.name}`)
93
170
  .join('\n');
94
- throw new Error(`${factory.provides.name} will fail because it depends on:\n ${dependencyList}`);
171
+ throw new errors_1.ServiceModuleInitError(`${factory.provides.name} will fail because it depends on:\n ${dependencyList}`);
95
172
  }
173
+ /**
174
+ * Checks if a ServiceKey is registered among the provided factories.
175
+ *
176
+ * @param key The ServiceKey to look for.
177
+ * @param factories The list of factories to search in.
178
+ * @returns True if a factory provides the given key, false otherwise.
179
+ */
96
180
  function isRegistered(key, factories) {
97
181
  return factories.some((factory) => { var _a; return ((_a = factory.provides) === null || _a === void 0 ? void 0 : _a.symbol) === (key === null || key === void 0 ? void 0 : key.symbol); });
98
182
  }
183
+ /**
184
+ * Determines if a factory is suitable for providing a specific ServiceKey.
185
+ *
186
+ * @param key The ServiceKey being requested.
187
+ * @param factory The factory to check.
188
+ * @returns True if the factory provides the key, false otherwise.
189
+ */
99
190
  function isSuitable(key, factory) {
100
191
  var _a;
101
192
  return ((_a = factory === null || factory === void 0 ? void 0 : factory.provides) === null || _a === void 0 ? void 0 : _a.symbol) === (key === null || key === void 0 ? void 0 : key.symbol);
@@ -1 +1 @@
1
- {"version":3,"file":"serviceModule.js","sourceRoot":"","sources":["../src/serviceModule.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"serviceModule.js","sourceRoot":"","sources":["../src/serviceModule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ import { ServiceKey, ServiceSelectorKey } from './serviceKey';
2
+ import { ServiceModule } from './serviceModule';
3
+ /**
4
+ * A runtime selector that provides access to multiple service implementations of the same type.
5
+ *
6
+ * ServiceSelector is automatically created and injected when a factory depends on a
7
+ * `ServiceSelectorKey<T>`. It allows the dependent service to dynamically choose which
8
+ * implementation to use at runtime, rather than being bound to a single implementation
9
+ * at configuration time.
10
+ *
11
+ * @template T The common type shared by all services accessible through this selector.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * // In a factory that depends on ServiceSelectorKey
16
+ * const appFactory = ServiceFactory.singleton({
17
+ * provides: AppKey,
18
+ * dependsOn: [LoggerSelectorKey] as const,
19
+ * initialize: (loggerSelector: ServiceSelector<Logger>) => {
20
+ * return {
21
+ * logWithConsole: async () => {
22
+ * const logger = await loggerSelector.get(ConsoleLoggerKey);
23
+ * logger.log('Using console logger');
24
+ * },
25
+ * logWithFile: async () => {
26
+ * const logger = await loggerSelector.get(FileLoggerKey);
27
+ * logger.log('Using file logger');
28
+ * },
29
+ * };
30
+ * },
31
+ * });
32
+ * ```
33
+ */
34
+ export declare class ServiceSelector<T> {
35
+ readonly serviceModule: ServiceModule;
36
+ readonly selectorKey: ServiceSelectorKey<T>;
37
+ /**
38
+ * Creates a new ServiceSelector instance.
39
+ *
40
+ * Note: ServiceSelector instances are created automatically by ServiceModule
41
+ * when resolving dependencies. You typically don't need to create them manually.
42
+ *
43
+ * @param serviceModule The ServiceModule used to resolve the selected service.
44
+ * @param selectorKey The ServiceSelectorKey that defines which services can be selected.
45
+ */
46
+ constructor(serviceModule: ServiceModule, selectorKey: ServiceSelectorKey<T>);
47
+ /**
48
+ * Retrieves a service instance by its key from the available services in this selector.
49
+ *
50
+ * The key must be one of the keys that were included in the `ServiceSelectorKey`
51
+ * used to create this selector.
52
+ *
53
+ * @param key The ServiceKey identifying which service implementation to retrieve.
54
+ * @returns A Promise that resolves to the requested service instance.
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * const logger = await loggerSelector.get(ConsoleLoggerKey);
59
+ * logger.log('Hello!');
60
+ * ```
61
+ */
62
+ get(key: ServiceKey<T>): Promise<T>;
63
+ }
64
+ //# sourceMappingURL=serviceSelector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serviceSelector.d.ts","sourceRoot":"","sources":["../src/serviceSelector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,eAAe,CAAC,CAAC;IAW1B,QAAQ,CAAC,aAAa,EAAE,aAAa;IACrC,QAAQ,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAX7C;;;;;;;;OAQG;gBAEQ,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAG7C;;;;;;;;;;;;;;OAcG;IACH,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAGpC"}
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ServiceSelector = void 0;
4
+ /**
5
+ * A runtime selector that provides access to multiple service implementations of the same type.
6
+ *
7
+ * ServiceSelector is automatically created and injected when a factory depends on a
8
+ * `ServiceSelectorKey<T>`. It allows the dependent service to dynamically choose which
9
+ * implementation to use at runtime, rather than being bound to a single implementation
10
+ * at configuration time.
11
+ *
12
+ * @template T The common type shared by all services accessible through this selector.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * // In a factory that depends on ServiceSelectorKey
17
+ * const appFactory = ServiceFactory.singleton({
18
+ * provides: AppKey,
19
+ * dependsOn: [LoggerSelectorKey] as const,
20
+ * initialize: (loggerSelector: ServiceSelector<Logger>) => {
21
+ * return {
22
+ * logWithConsole: async () => {
23
+ * const logger = await loggerSelector.get(ConsoleLoggerKey);
24
+ * logger.log('Using console logger');
25
+ * },
26
+ * logWithFile: async () => {
27
+ * const logger = await loggerSelector.get(FileLoggerKey);
28
+ * logger.log('Using file logger');
29
+ * },
30
+ * };
31
+ * },
32
+ * });
33
+ * ```
34
+ */
35
+ class ServiceSelector {
36
+ /**
37
+ * Creates a new ServiceSelector instance.
38
+ *
39
+ * Note: ServiceSelector instances are created automatically by ServiceModule
40
+ * when resolving dependencies. You typically don't need to create them manually.
41
+ *
42
+ * @param serviceModule The ServiceModule used to resolve the selected service.
43
+ * @param selectorKey The ServiceSelectorKey that defines which services can be selected.
44
+ */
45
+ constructor(serviceModule, selectorKey) {
46
+ this.serviceModule = serviceModule;
47
+ this.selectorKey = selectorKey;
48
+ }
49
+ /**
50
+ * Retrieves a service instance by its key from the available services in this selector.
51
+ *
52
+ * The key must be one of the keys that were included in the `ServiceSelectorKey`
53
+ * used to create this selector.
54
+ *
55
+ * @param key The ServiceKey identifying which service implementation to retrieve.
56
+ * @returns A Promise that resolves to the requested service instance.
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * const logger = await loggerSelector.get(ConsoleLoggerKey);
61
+ * logger.log('Hello!');
62
+ * ```
63
+ */
64
+ get(key) {
65
+ return this.serviceModule.get(key);
66
+ }
67
+ }
68
+ exports.ServiceSelector = ServiceSelector;
69
+ //# sourceMappingURL=serviceSelector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serviceSelector.js","sourceRoot":"","sources":["../src/serviceSelector.ts"],"names":[],"mappings":";;;AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAa,eAAe;IAC1B;;;;;;;;OAQG;IACH,YACW,aAA4B,EAC5B,WAAkC;QADlC,kBAAa,GAAb,aAAa,CAAe;QAC5B,gBAAW,GAAX,WAAW,CAAuB;IAC1C,CAAC;IAEJ;;;;;;;;;;;;;;OAcG;IACH,GAAG,CAAC,GAAkB;QACpB,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;CACF;AAjCD,0CAiCC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=test-service-selector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-service-selector.d.ts","sourceRoot":"","sources":["../src/test-service-selector.ts"],"names":[],"mappings":""}
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const serviceKey_1 = require("./serviceKey");
13
+ const serviceFactory_1 = require("./serviceFactory");
14
+ const serviceModule_1 = require("./serviceModule");
15
+ // Create service keys for different logger implementations
16
+ const ConsoleLoggerKey = new serviceKey_1.ServiceKey('ConsoleLogger');
17
+ const FileLoggerKey = new serviceKey_1.ServiceKey('FileLogger');
18
+ // Create a ServiceSelectorKey that groups both logger keys
19
+ const LoggerSelectorKey = new serviceKey_1.ServiceSelectorKey([
20
+ ConsoleLoggerKey,
21
+ FileLoggerKey,
22
+ ]);
23
+ // Create factories for the logger implementations
24
+ const consoleLoggerFactory = serviceFactory_1.ServiceFactory.singleton({
25
+ provides: ConsoleLoggerKey,
26
+ dependsOn: [],
27
+ initialize: () => ({
28
+ type: 'console',
29
+ log: (msg) => console.log(`[Console] ${msg}`),
30
+ }),
31
+ });
32
+ const fileLoggerFactory = serviceFactory_1.ServiceFactory.singleton({
33
+ provides: FileLoggerKey,
34
+ dependsOn: [],
35
+ initialize: () => ({
36
+ type: 'file',
37
+ log: (msg) => console.log(`[File] ${msg}`),
38
+ }),
39
+ });
40
+ const AppKey = new serviceKey_1.ServiceKey('App');
41
+ const appFactory = serviceFactory_1.ServiceFactory.singleton({
42
+ provides: AppKey,
43
+ dependsOn: [LoggerSelectorKey],
44
+ initialize: (loggerSelector) => {
45
+ return {
46
+ useLogger: (key) => __awaiter(void 0, void 0, void 0, function* () {
47
+ const logger = yield loggerSelector.get(key);
48
+ logger.log('Hello from App!');
49
+ }),
50
+ };
51
+ },
52
+ });
53
+ function runTests() {
54
+ return __awaiter(this, void 0, void 0, function* () {
55
+ console.log('=== Testing ServiceSelectorKey Implementation ===\n');
56
+ // Test 1: Module creation with ServiceSelectorKey dependency
57
+ console.log('Test 1: Creating ServiceModule with ServiceSelectorKey dependency...');
58
+ const module = serviceModule_1.ServiceModule.from([
59
+ consoleLoggerFactory,
60
+ fileLoggerFactory,
61
+ appFactory,
62
+ ]);
63
+ console.log('✓ ServiceModule created successfully\n');
64
+ // Test 2: Get the App service (which depends on ServiceSelectorKey)
65
+ console.log('Test 2: Resolving App service with ServiceSelector dependency...');
66
+ const app = yield module.get(AppKey);
67
+ console.log('✓ App service resolved successfully\n');
68
+ // Test 3: Use the ServiceSelector to get different logger implementations
69
+ console.log('Test 3: Using ServiceSelector to get ConsoleLogger...');
70
+ yield app.useLogger(ConsoleLoggerKey);
71
+ console.log('✓ ConsoleLogger retrieved and used successfully\n');
72
+ console.log('Test 4: Using ServiceSelector to get FileLogger...');
73
+ yield app.useLogger(FileLoggerKey);
74
+ console.log('✓ FileLogger retrieved and used successfully\n');
75
+ // Test 5: Verify missing dependency detection for ServiceSelectorKey
76
+ console.log('Test 5: Testing missing dependency detection for ServiceSelectorKey...');
77
+ const MissingLoggerKey = new serviceKey_1.ServiceKey('MissingLogger');
78
+ const selectorWithMissing = new serviceKey_1.ServiceSelectorKey([
79
+ ConsoleLoggerKey,
80
+ MissingLoggerKey,
81
+ ]);
82
+ const appWithMissingFactory = serviceFactory_1.ServiceFactory.singleton({
83
+ provides: new serviceKey_1.ServiceKey('AppWithMissing'),
84
+ dependsOn: [selectorWithMissing],
85
+ initialize: (_selector) => ({
86
+ useLogger: () => __awaiter(this, void 0, void 0, function* () { }),
87
+ }),
88
+ });
89
+ try {
90
+ serviceModule_1.ServiceModule.from([consoleLoggerFactory, appWithMissingFactory]);
91
+ console.log('✗ Should have thrown an error for missing dependency\n');
92
+ process.exit(1);
93
+ }
94
+ catch (error) {
95
+ if (error.message.includes('MissingLogger')) {
96
+ console.log('✓ Missing dependency correctly detected\n');
97
+ }
98
+ else {
99
+ console.log(`✗ Unexpected error: ${error.message}\n`);
100
+ process.exit(1);
101
+ }
102
+ }
103
+ console.log('=== All tests passed! ===');
104
+ });
105
+ }
106
+ runTests().catch((error) => {
107
+ console.error('Test failed:', error);
108
+ process.exit(1);
109
+ });
110
+ //# sourceMappingURL=test-service-selector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-service-selector.js","sourceRoot":"","sources":["../src/test-service-selector.ts"],"names":[],"mappings":"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"}