@composed-di/core 0.5.0-alpha

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/dist/errors.d.ts +17 -0
  2. package/dist/errors.d.ts.map +1 -0
  3. package/dist/errors.js +26 -0
  4. package/dist/errors.js.map +1 -0
  5. package/dist/index.d.ts +9 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +25 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/serviceEventListener.d.ts +120 -0
  10. package/dist/serviceEventListener.d.ts.map +1 -0
  11. package/dist/serviceEventListener.js +3 -0
  12. package/dist/serviceEventListener.js.map +1 -0
  13. package/dist/serviceFactory.d.ts +36 -0
  14. package/dist/serviceFactory.d.ts.map +1 -0
  15. package/dist/serviceFactory.js +68 -0
  16. package/dist/serviceFactory.js.map +1 -0
  17. package/dist/serviceKey.d.ts +90 -0
  18. package/dist/serviceKey.d.ts.map +1 -0
  19. package/dist/serviceKey.js +93 -0
  20. package/dist/serviceKey.js.map +1 -0
  21. package/dist/serviceModule.d.ts +71 -0
  22. package/dist/serviceModule.d.ts.map +1 -0
  23. package/dist/serviceModule.js +329 -0
  24. package/dist/serviceModule.js.map +1 -0
  25. package/dist/serviceScope.d.ts +6 -0
  26. package/dist/serviceScope.d.ts.map +1 -0
  27. package/dist/serviceScope.js +11 -0
  28. package/dist/serviceScope.js.map +1 -0
  29. package/dist/serviceSelector.d.ts +64 -0
  30. package/dist/serviceSelector.d.ts.map +1 -0
  31. package/dist/serviceSelector.js +69 -0
  32. package/dist/serviceSelector.js.map +1 -0
  33. package/dist/utils.d.ts +61 -0
  34. package/dist/utils.d.ts.map +1 -0
  35. package/dist/utils.js +209 -0
  36. package/dist/utils.js.map +1 -0
  37. package/package.json +39 -0
  38. package/src/errors.ts +23 -0
  39. package/src/index.ts +8 -0
  40. package/src/serviceEventListener.ts +130 -0
  41. package/src/serviceFactory.ts +104 -0
  42. package/src/serviceKey.ts +95 -0
  43. package/src/serviceModule.ts +372 -0
  44. package/src/serviceScope.ts +7 -0
  45. package/src/serviceSelector.ts +68 -0
  46. package/src/utils.ts +277 -0
@@ -0,0 +1,329 @@
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
+ exports.ServiceModule = void 0;
13
+ const serviceKey_1 = require("./serviceKey");
14
+ const serviceFactory_1 = require("./serviceFactory");
15
+ const serviceSelector_1 = require("./serviceSelector");
16
+ const errors_1 = require("./errors");
17
+ /**
18
+ * ServiceModule is a container for service factories and manages dependency resolution.
19
+ *
20
+ * It provides a way to retrieve service instances based on their ServiceKey,
21
+ * ensuring that all dependencies are resolved and initialized in the correct order.
22
+ * It also handles circular dependency detection and missing dependency validation
23
+ * at the time of module creation.
24
+ */
25
+ class ServiceModule {
26
+ /**
27
+ * Private constructor to enforce module creation through the `static from` method.
28
+ *
29
+ * @param factories An array of service factories that this module will manage.
30
+ */
31
+ constructor(factories) {
32
+ this.factories = factories;
33
+ checkCircularDependencies(this.factories);
34
+ factories.forEach((factory) => {
35
+ checkMissingDependencies(factory, this.factories);
36
+ });
37
+ }
38
+ /**
39
+ * Retrieves an instance for the given ServiceKey.
40
+ *
41
+ * @param key - The key of the service to retrieve.
42
+ * @return A promise that resolves to the service instance.
43
+ * @throws {ServiceFactoryNotFoundError} If no suitable factory is found for the given key.
44
+ */
45
+ get(key) {
46
+ return __awaiter(this, void 0, void 0, function* () {
47
+ const factory = this.factories.find((factory) => {
48
+ return isSuitable(key, factory);
49
+ });
50
+ // Check if a factory to supply the requested key was not found
51
+ if (!factory) {
52
+ throw new errors_1.ServiceFactoryNotFoundError(`Could not find a suitable factory for ${key.name}`);
53
+ }
54
+ // Resolve all dependencies first
55
+ const dependencies = yield Promise.all(factory.dependsOn.map((dependencyKey) => {
56
+ // If the dependency is a ServiceSelectorKey, create a ServiceSelector instance
57
+ if (dependencyKey instanceof serviceKey_1.ServiceSelectorKey) {
58
+ return new serviceSelector_1.ServiceSelector(this, dependencyKey);
59
+ }
60
+ return this.get(dependencyKey);
61
+ }));
62
+ // Call the factory to retrieve the dependency
63
+ return factory.initialize(...dependencies);
64
+ });
65
+ }
66
+ /**
67
+ * Retrieves the value associated with the given service key or returns null if the service is not found.
68
+ *
69
+ * @param key - The key used to retrieve the associated service.
70
+ * @return A promise that resolves to the service value if found, or null if the service is not found.
71
+ */
72
+ getOrNull(key) {
73
+ return __awaiter(this, void 0, void 0, function* () {
74
+ try {
75
+ return yield this.get(key);
76
+ }
77
+ catch (error) {
78
+ if (error instanceof errors_1.ServiceFactoryNotFoundError) {
79
+ return null;
80
+ }
81
+ throw error;
82
+ }
83
+ });
84
+ }
85
+ /**
86
+ * Disposes of service factories within the specified scope or all factories if no scope is provided.
87
+ *
88
+ * This method is useful for cleaning up resources and instances held by service factories,
89
+ * such as singleton factories, as they may hold database connections or other resources that need to be released.
90
+ *
91
+ * @param scope The scope to filter the factories to be disposed.
92
+ * If not provided, all factories are disposed of.
93
+ * @return No return value.
94
+ */
95
+ dispose(scope) {
96
+ const factories = scope
97
+ ? this.factories.filter((f) => f.scope === scope)
98
+ : this.factories;
99
+ factories.forEach((factory) => { var _a; return (_a = factory.dispose) === null || _a === void 0 ? void 0 : _a.call(factory); });
100
+ }
101
+ /**
102
+ * Creates a new ServiceModule instance by aggregating and deduplicating a list of
103
+ * ServiceModule or GenericFactory instances.
104
+ * If multiple factories provide the same
105
+ * ServiceKey, the last one in the list takes precedence.
106
+ *
107
+ * When a listener is provided, every factory is wrapped with instrumentation:
108
+ * the listener is notified when a service is initialized or disposed and when
109
+ * a method is called on a service instance, and may return an EventSpan per
110
+ * operation to observe its completion. Service instances are wrapped in a
111
+ * Proxy to observe method calls, and errors are rethrown after being
112
+ * reported, so behavior is otherwise unchanged.
113
+ *
114
+ * @param entries - An array of ServiceModule or GenericFactory
115
+ * instances to be processed into a single ServiceModule.
116
+ * @param listener - An optional ServiceEventListener notified of service
117
+ * lifecycle events and method calls in the resulting module.
118
+ * @return A new ServiceModule containing the deduplicated factories.
119
+ * @throws {ServiceModuleInitError} If circular or missing dependencies are detected during module creation.
120
+ */
121
+ static from(entries, listener) {
122
+ // Flatten entries and keep only the last factory for each ServiceKey
123
+ const flattened = entries.flatMap((e) => e instanceof ServiceModule ? e.factories : [e]);
124
+ const byKey = new Map();
125
+ // Later factories overwrite earlier ones (last-wins)
126
+ for (const f of flattened) {
127
+ byKey.set(f.provides.symbol, f);
128
+ }
129
+ if (listener) {
130
+ return new ServiceModule(Array.from(byKey.values()).map((factory) => {
131
+ return makeObservable(listener, factory);
132
+ }));
133
+ }
134
+ return new ServiceModule(Array.from(byKey.values()));
135
+ }
136
+ }
137
+ exports.ServiceModule = ServiceModule;
138
+ /**
139
+ * Validates that there are no circular dependencies among the provided factories.
140
+ *
141
+ * @param factories The list of factories to check for cycles.
142
+ * @throws {ServiceModuleInitError} If a circular dependency is detected.
143
+ */
144
+ function checkCircularDependencies(factories) {
145
+ const factoryMap = new Map();
146
+ for (const f of factories) {
147
+ factoryMap.set(f.provides.symbol, f);
148
+ }
149
+ const visited = new Set();
150
+ const stack = new Set();
151
+ function walk(factory, path) {
152
+ const symbol = factory.provides.symbol;
153
+ if (stack.has(symbol)) {
154
+ const cyclePath = [...path, factory.provides.name].join(' -> ');
155
+ throw new errors_1.ServiceModuleInitError(`Circular dependency detected: ${cyclePath}`);
156
+ }
157
+ if (visited.has(symbol)) {
158
+ return;
159
+ }
160
+ visited.add(symbol);
161
+ stack.add(symbol);
162
+ for (const depKey of factory.dependsOn) {
163
+ const keysToCheck = depKey instanceof serviceKey_1.ServiceSelectorKey ? depKey.values : [depKey];
164
+ for (const key of keysToCheck) {
165
+ const depFactory = factoryMap.get(key.symbol);
166
+ if (depFactory) {
167
+ walk(depFactory, [...path, factory.provides.name]);
168
+ }
169
+ }
170
+ }
171
+ stack.delete(symbol);
172
+ }
173
+ for (const factory of factories) {
174
+ walk(factory, []);
175
+ }
176
+ }
177
+ /**
178
+ * Validates that all dependencies of a given factory are present in the list of factories.
179
+ *
180
+ * @param factory The factory whose dependencies are to be checked.
181
+ * @param factories The list of available factories in the module.
182
+ * @throws {ServiceModuleInitError} If any dependency is missing.
183
+ */
184
+ function checkMissingDependencies(factory, factories) {
185
+ const missingDependencies = [];
186
+ factory.dependsOn.forEach((dependencyKey) => {
187
+ // For ServiceSelectorKey, check all contained keys are registered
188
+ if (dependencyKey instanceof serviceKey_1.ServiceSelectorKey) {
189
+ dependencyKey.values.forEach((key) => {
190
+ if (!isRegistered(key, factories)) {
191
+ missingDependencies.push(key);
192
+ }
193
+ });
194
+ }
195
+ else if (!isRegistered(dependencyKey, factories)) {
196
+ missingDependencies.push(dependencyKey);
197
+ }
198
+ });
199
+ if (missingDependencies.length === 0) {
200
+ return;
201
+ }
202
+ const dependencyList = missingDependencies
203
+ .map((dependencyKey) => ` -> ${dependencyKey.name}`)
204
+ .join('\n');
205
+ throw new errors_1.ServiceModuleInitError(`${factory.provides.name} will fail because it depends on:\n ${dependencyList}`);
206
+ }
207
+ /**
208
+ * Checks if a ServiceKey is registered among the provided factories.
209
+ *
210
+ * @param key The ServiceKey to look for.
211
+ * @param factories The list of factories to search in.
212
+ * @returns True if a factory provides the given key, false otherwise.
213
+ */
214
+ function isRegistered(key, factories) {
215
+ 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); });
216
+ }
217
+ /**
218
+ * Determines if a factory is suitable for providing a specific ServiceKey.
219
+ *
220
+ * @param key The ServiceKey being requested.
221
+ * @param factory The factory to check.
222
+ * @returns True if the factory provides the key, false otherwise.
223
+ */
224
+ function isSuitable(key, factory) {
225
+ var _a;
226
+ 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);
227
+ }
228
+ /**
229
+ * Wraps a given service factory with instrumentation to notify a listener of
230
+ * lifecycle events and method calls.
231
+ *
232
+ * For each of initialize, dispose, and method calls, the listener is invoked
233
+ * at the start of the operation and may return an EventSpan whose `end` or
234
+ * `error` is called when the operation finishes. Errors are rethrown after
235
+ * being reported.
236
+ *
237
+ * @param listener The listener notified of lifecycle and method call events.
238
+ * @param delegate The original service factory to be instrumented.
239
+ * @return A new service factory that provides the same dependencies but includes event notification logic.
240
+ */
241
+ function makeObservable(listener, delegate) {
242
+ const key = delegate.provides;
243
+ return serviceFactory_1.ServiceFactory.singleton({
244
+ scope: delegate.scope,
245
+ provides: delegate.provides,
246
+ dependsOn: delegate.dependsOn,
247
+ dispose: () => {
248
+ var _a, _b, _c;
249
+ const dispose = delegate.dispose;
250
+ if (dispose) {
251
+ const span = (_a = listener.onDispose) === null || _a === void 0 ? void 0 : _a.call(listener, { key });
252
+ try {
253
+ dispose();
254
+ }
255
+ catch (error) {
256
+ (_b = span === null || span === void 0 ? void 0 : span.error) === null || _b === void 0 ? void 0 : _b.call(span, error);
257
+ throw error;
258
+ }
259
+ (_c = span === null || span === void 0 ? void 0 : span.end) === null || _c === void 0 ? void 0 : _c.call(span);
260
+ }
261
+ },
262
+ initialize: (...args) => __awaiter(this, void 0, void 0, function* () {
263
+ var _a, _b, _c;
264
+ const span = (_a = listener.onInitialize) === null || _a === void 0 ? void 0 : _a.call(listener, { key });
265
+ try {
266
+ const instance = observeMethodCalls(yield delegate.initialize(...args), listener, key);
267
+ (_b = span === null || span === void 0 ? void 0 : span.end) === null || _b === void 0 ? void 0 : _b.call(span, { result: instance });
268
+ return instance;
269
+ }
270
+ catch (error) {
271
+ (_c = span === null || span === void 0 ? void 0 : span.error) === null || _c === void 0 ? void 0 : _c.call(span, error);
272
+ throw error;
273
+ }
274
+ }),
275
+ });
276
+ }
277
+ /**
278
+ * Wraps an object with a Proxy to notify the listener of method calls.
279
+ *
280
+ * Methods returning a promise report end/error when the promise settles,
281
+ * not when the method returns.
282
+ *
283
+ * @param thing The object whose method calls need to be observed.
284
+ * @param listener The listener notified of method call events.
285
+ * @param key The service key used to identify the service in events.
286
+ * @return A Proxy wrapping the input object, with all method calls being reported.
287
+ */
288
+ function observeMethodCalls(thing, listener, key) {
289
+ if (typeof thing !== 'object' || thing === null) {
290
+ return thing;
291
+ }
292
+ return new Proxy(thing, {
293
+ get(target, prop) {
294
+ const value = Reflect.get(target, prop);
295
+ if (typeof value === 'function' && typeof prop === 'string') {
296
+ return (...args) => {
297
+ var _a, _b, _c;
298
+ const span = (_a = listener.onMethodCall) === null || _a === void 0 ? void 0 : _a.call(listener, {
299
+ key,
300
+ methodName: prop,
301
+ args,
302
+ });
303
+ try {
304
+ const result = value.apply(target, args);
305
+ if (result instanceof Promise) {
306
+ return result.then((resolved) => {
307
+ var _a;
308
+ (_a = span === null || span === void 0 ? void 0 : span.end) === null || _a === void 0 ? void 0 : _a.call(span, { result: resolved });
309
+ return resolved;
310
+ }, (error) => {
311
+ var _a;
312
+ (_a = span === null || span === void 0 ? void 0 : span.error) === null || _a === void 0 ? void 0 : _a.call(span, error);
313
+ throw error;
314
+ });
315
+ }
316
+ (_b = span === null || span === void 0 ? void 0 : span.end) === null || _b === void 0 ? void 0 : _b.call(span, { result });
317
+ return result;
318
+ }
319
+ catch (error) {
320
+ (_c = span === null || span === void 0 ? void 0 : span.error) === null || _c === void 0 ? void 0 : _c.call(span, error);
321
+ throw error;
322
+ }
323
+ };
324
+ }
325
+ return value;
326
+ },
327
+ });
328
+ }
329
+ //# sourceMappingURL=serviceModule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serviceModule.js","sourceRoot":"","sources":["../src/serviceModule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare class ServiceScope {
2
+ readonly name: string;
3
+ readonly symbol: symbol;
4
+ constructor(name: string);
5
+ }
6
+ //# sourceMappingURL=serviceScope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serviceScope.d.ts","sourceRoot":"","sources":["../src/serviceScope.ts"],"names":[],"mappings":"AAAA,qBAAa,YAAY;IAGX,QAAQ,CAAC,IAAI,EAAE,MAAM;IAFjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEH,IAAI,EAAE,MAAM;CAGlC"}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ServiceScope = void 0;
4
+ class ServiceScope {
5
+ constructor(name) {
6
+ this.name = name;
7
+ this.symbol = Symbol(name);
8
+ }
9
+ }
10
+ exports.ServiceScope = ServiceScope;
11
+ //# sourceMappingURL=serviceScope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serviceScope.js","sourceRoot":"","sources":["../src/serviceScope.ts"],"names":[],"mappings":";;;AAAA,MAAa,YAAY;IAGvB,YAAqB,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;QAC/B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;CACF;AAND,oCAMC"}
@@ -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,61 @@
1
+ import { ServiceModule } from './serviceModule';
2
+ export interface DotGraphOptions {
3
+ /** Graph direction: 'TB' (top-bottom), 'LR' (left-right), 'BT' (bottom-top), 'RL' (right-left) */
4
+ direction?: 'TB' | 'LR' | 'BT' | 'RL';
5
+ /** Title for the graph */
6
+ title?: string;
7
+ /** Show nodes with no dependencies in a different color */
8
+ highlightLeaves?: boolean;
9
+ /** Show nodes with no dependents in a different color */
10
+ highlightRoots?: boolean;
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
+ }
20
+ /**
21
+ * Generates a DOT notation graph from a ServiceModule.
22
+ * The output can be visualized using Graphviz tools or online viewers like:
23
+ * - https://dreampuf.github.io/GraphvizOnline/
24
+ * - https://edotor.net/
25
+ *
26
+ * Arrows point from dependencies to dependents (from what is needed to what needs it).
27
+ *
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
31
+ */
32
+ export declare function createDotGraph(module: ServiceModule, { direction, title, highlightLeaves, highlightRoots }?: DotGraphOptions): string;
33
+ /**
34
+ * Prints a DOT representation of a service module graph to the console.
35
+ * The output can be used to visualize the graph using online graph visualization tools.
36
+ *
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.
39
+ */
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;
61
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +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;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"}