@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,17 @@
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 declare class ServiceModuleInitError extends Error {
6
+ name: string;
7
+ constructor(message: string);
8
+ }
9
+ /**
10
+ * Error thrown when a requested service cannot be found within the ServiceModule.
11
+ * This typically occurs when no factory has been registered for the given ServiceKey.
12
+ */
13
+ export declare class ServiceFactoryNotFoundError extends Error {
14
+ name: string;
15
+ constructor(message: string);
16
+ }
17
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,IAAI,SAA4B;gBAEpB,OAAO,EAAE,MAAM;CAG5B;AAED;;;GAGG;AACH,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,IAAI,SAAiC;gBAEzB,OAAO,EAAE,MAAM;CAG5B"}
package/dist/errors.js ADDED
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ServiceFactoryNotFoundError = exports.ServiceModuleInitError = void 0;
4
+ /**
5
+ * Error thrown when there is an issue during the initialization or configuration of a ServiceModule.
6
+ * This can include circular dependencies or missing dependencies that are detected during module creation.
7
+ */
8
+ class ServiceModuleInitError extends Error {
9
+ constructor(message) {
10
+ super(message);
11
+ this.name = 'ServiceModuleInitError';
12
+ }
13
+ }
14
+ exports.ServiceModuleInitError = ServiceModuleInitError;
15
+ /**
16
+ * Error thrown when a requested service cannot be found within the ServiceModule.
17
+ * This typically occurs when no factory has been registered for the given ServiceKey.
18
+ */
19
+ class ServiceFactoryNotFoundError extends Error {
20
+ constructor(message) {
21
+ super(message);
22
+ this.name = 'ServiceFactoryNotFoundError';
23
+ }
24
+ }
25
+ exports.ServiceFactoryNotFoundError = ServiceFactoryNotFoundError;
26
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACH,MAAa,sBAAuB,SAAQ,KAAK;IAG/C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QAHjB,SAAI,GAAG,wBAAwB,CAAC;IAIhC,CAAC;CACF;AAND,wDAMC;AAED;;;GAGG;AACH,MAAa,2BAA4B,SAAQ,KAAK;IAGpD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QAHjB,SAAI,GAAG,6BAA6B,CAAC;IAIrC,CAAC;CACF;AAND,kEAMC"}
@@ -0,0 +1,9 @@
1
+ export * from './serviceKey';
2
+ export * from './serviceModule';
3
+ export * from './serviceFactory';
4
+ export * from './serviceScope';
5
+ export * from './serviceSelector';
6
+ export * from './serviceEventListener';
7
+ export * from './errors';
8
+ export * from './utils';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./serviceKey"), exports);
18
+ __exportStar(require("./serviceModule"), exports);
19
+ __exportStar(require("./serviceFactory"), exports);
20
+ __exportStar(require("./serviceScope"), exports);
21
+ __exportStar(require("./serviceSelector"), exports);
22
+ __exportStar(require("./serviceEventListener"), exports);
23
+ __exportStar(require("./errors"), exports);
24
+ __exportStar(require("./utils"), exports);
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,kDAAgC;AAChC,mDAAiC;AACjC,iDAA+B;AAC/B,oDAAkC;AAClC,yDAAuC;AACvC,2CAAyB;AACzB,0CAAwB"}
@@ -0,0 +1,120 @@
1
+ import type { ServiceKey } from './serviceKey';
2
+ /**
3
+ * A handle representing a single in-flight operation (initialization,
4
+ * disposal, or method call), returned by a ServiceEventListener when the
5
+ * operation starts.
6
+ *
7
+ * Exactly one of `end` or `error` is invoked when the operation finishes,
8
+ * so implementations can close over per-call state (start time, an
9
+ * OpenTelemetry span, a correlation id) without any bookkeeping to pair
10
+ * concurrent start/finish events.
11
+ */
12
+ export interface EventSpan {
13
+ /**
14
+ * Invoked when the operation completes successfully. For methods that
15
+ * return a promise, this fires when the promise resolves, not when the
16
+ * method returns.
17
+ *
18
+ * Whether to retain or log the outcome is the implementation's choice;
19
+ * the value is passed by reference, so implementations must not mutate it.
20
+ *
21
+ * @param outcome - The outcome of the operation. Present for method call
22
+ * spans (the return or resolved value) and initialize spans (the service
23
+ * instance), absent for dispose spans.
24
+ * @return void
25
+ */
26
+ end?(outcome?: EventOutcome): void;
27
+ /**
28
+ * Invoked when the operation throws or rejects. Terminal like `end`;
29
+ * the two are mutually exclusive. The error is rethrown to the caller
30
+ * after this is invoked.
31
+ *
32
+ * @param error - The error object or value that was thrown or rejected.
33
+ * @return void
34
+ */
35
+ error?(error: unknown): void;
36
+ }
37
+ /**
38
+ * The successful outcome of an operation, delivered to EventSpan.end.
39
+ * Future fields (e.g. a correlation id) are added here rather than as
40
+ * extra parameters.
41
+ */
42
+ export interface EventOutcome {
43
+ /**
44
+ * The value produced by the operation: the return value for synchronous
45
+ * methods, or the resolved value for methods returning a promise.
46
+ */
47
+ result: unknown;
48
+ }
49
+ /**
50
+ * Context of a service initialization, delivered to onInitialize.
51
+ * Future fields are added here rather than as extra parameters.
52
+ */
53
+ export interface InitializeContext {
54
+ /**
55
+ * The unique identifier of the service that is being initialized.
56
+ */
57
+ key: ServiceKey<unknown>;
58
+ }
59
+ /**
60
+ * Context of a service disposal, delivered to onDispose.
61
+ * Future fields are added here rather than as extra parameters.
62
+ */
63
+ export interface DisposeContext {
64
+ /**
65
+ * The unique identifier of the service that is being disposed.
66
+ */
67
+ key: ServiceKey<unknown>;
68
+ }
69
+ /**
70
+ * Context of a method invocation, delivered to onMethodCall.
71
+ * Future fields are added here rather than as extra parameters.
72
+ */
73
+ export interface MethodCallContext {
74
+ /**
75
+ * The unique identifier of the service the method belongs to.
76
+ */
77
+ key: ServiceKey<unknown>;
78
+ /**
79
+ * The name of the method that is being called.
80
+ */
81
+ methodName: string;
82
+ /**
83
+ * The arguments the method was invoked with, passed by reference;
84
+ * implementations must not mutate them.
85
+ */
86
+ args: readonly unknown[];
87
+ }
88
+ /**
89
+ * Interface for listening to service events. Implement this interface to
90
+ * observe lifecycle events and method calls of services in a module.
91
+ *
92
+ * Each method is invoked when the corresponding operation starts and may
93
+ * return an EventSpan that is notified when that operation finishes.
94
+ * Returning nothing opts out of completion tracking for that call.
95
+ */
96
+ export interface ServiceEventListener {
97
+ /**
98
+ * Invoked at the start of the initialization process for a specific service.
99
+ *
100
+ * @param context - Context of the initialization, including the service key.
101
+ * @return An EventSpan notified when initialization finishes, or void.
102
+ */
103
+ onInitialize?(context: InitializeContext): EventSpan | void;
104
+ /**
105
+ * Invoked when the disposal process for a service starts.
106
+ *
107
+ * @param context - Context of the disposal, including the service key.
108
+ * @return An EventSpan notified when disposal finishes, or void.
109
+ */
110
+ onDispose?(context: DisposeContext): EventSpan | void;
111
+ /**
112
+ * Invoked when a method call starts on a service instance.
113
+ *
114
+ * @param context - Context of the invocation, including the service key,
115
+ * the method name, and its arguments.
116
+ * @return An EventSpan notified when the call finishes, or void.
117
+ */
118
+ onMethodCall?(context: MethodCallContext): EventSpan | void;
119
+ }
120
+ //# sourceMappingURL=serviceEventListener.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serviceEventListener.d.ts","sourceRoot":"","sources":["../src/serviceEventListener.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C;;;;;;;;;GASG;AACH,MAAM,WAAW,SAAS;IACxB;;;;;;;;;;;;OAYG;IACH,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAEnC;;;;;;;OAOG;IACH,KAAK,CAAC,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CAC9B;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,GAAG,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,GAAG,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,GAAG,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IAEzB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,IAAI,EAAE,SAAS,OAAO,EAAE,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,YAAY,CAAC,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,GAAG,IAAI,CAAC;IAE5D;;;;;OAKG;IACH,SAAS,CAAC,CAAC,OAAO,EAAE,cAAc,GAAG,SAAS,GAAG,IAAI,CAAC;IAEtD;;;;;;OAMG;IACH,YAAY,CAAC,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,GAAG,IAAI,CAAC;CAC7D"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=serviceEventListener.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serviceEventListener.js","sourceRoot":"","sources":["../src/serviceEventListener.ts"],"names":[],"mappings":""}
@@ -0,0 +1,36 @@
1
+ import { ServiceKey, ServiceSelectorKey } from './serviceKey';
2
+ import { ServiceScope } from './serviceScope';
3
+ import { ServiceSelector } from './serviceSelector';
4
+ type ServiceType<T> = T extends ServiceSelectorKey<infer U> ? ServiceSelector<U> : T extends ServiceKey<infer U> ? U : never;
5
+ type DependencyTypes<T extends readonly ServiceKey<unknown>[]> = {
6
+ [K in keyof T]: ServiceType<T[K]>;
7
+ };
8
+ export declare abstract class ServiceFactory<const T, const D extends readonly ServiceKey<unknown>[] = []> {
9
+ abstract provides: ServiceKey<T>;
10
+ abstract dependsOn: D;
11
+ abstract scope?: ServiceScope;
12
+ abstract initialize: (...dependencies: DependencyTypes<D>) => T | Promise<T>;
13
+ abstract dispose?: () => void;
14
+ /**
15
+ * Creates a singleton service factory that ensures a single instance of the provided service is initialized
16
+ * and used throughout the scope lifecycle.
17
+ */
18
+ static singleton<const T, const D extends readonly ServiceKey<unknown>[] = []>({ scope, provides, dependsOn, initialize, dispose, }: {
19
+ scope?: ServiceScope;
20
+ provides: ServiceKey<T>;
21
+ dependsOn?: D;
22
+ initialize: (...dependencies: DependencyTypes<D>) => T | Promise<T>;
23
+ dispose?: (instance: T) => void;
24
+ }): ServiceFactory<T, D>;
25
+ /**
26
+ * Creates a one-shot service factory that initializes a new instance of the provided service
27
+ * every time it is requested.
28
+ */
29
+ static oneShot<const T, const D extends readonly ServiceKey<unknown>[] = []>({ provides, dependsOn, initialize, }: {
30
+ provides: ServiceKey<T>;
31
+ dependsOn: D;
32
+ initialize: (...dependencies: DependencyTypes<D>) => T | Promise<T>;
33
+ }): ServiceFactory<T, D>;
34
+ }
35
+ export {};
36
+ //# sourceMappingURL=serviceFactory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serviceFactory.d.ts","sourceRoot":"","sources":["../src/serviceFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD,KAAK,WAAW,CAAC,CAAC,IAChB,CAAC,SAAS,kBAAkB,CAAC,MAAM,CAAC,CAAC,GACjC,eAAe,CAAC,CAAC,CAAC,GAClB,CAAC,SAAS,UAAU,CAAC,MAAM,CAAC,CAAC,GAC3B,CAAC,GACD,KAAK,CAAC;AAGd,KAAK,eAAe,CAAC,CAAC,SAAS,SAAS,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI;KAC9D,CAAC,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAClC,CAAC;AAEF,8BAAsB,cAAc,CAClC,KAAK,CAAC,CAAC,EACP,KAAK,CAAC,CAAC,SAAS,SAAS,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE;IAEnD,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,CAAC,GAAG,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC7E,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAE9B;;;OAGG;IACH,MAAM,CAAC,SAAS,CACd,KAAK,CAAC,CAAC,EACP,KAAK,CAAC,CAAC,SAAS,SAAS,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,EACnD,EACA,KAAK,EACL,QAAQ,EACR,SAA8B,EAC9B,UAAU,EACV,OAAkB,GACnB,EAAE;QACD,KAAK,CAAC,EAAE,YAAY,CAAC;QACrB,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;QACxB,SAAS,CAAC,EAAE,CAAC,CAAC;QACd,UAAU,EAAE,CAAC,GAAG,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACpE,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,IAAI,CAAC;KACjC,GAAG,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC;IAsCxB;;;OAGG;IACH,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,SAAS,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,EAAE,EAC3E,QAAQ,EACR,SAAS,EACT,UAAU,GACX,EAAE;QACD,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;QACxB,SAAS,EAAE,CAAC,CAAC;QACb,UAAU,EAAE,CAAC,GAAG,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;KACrE,GAAG,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC;CAOzB"}
@@ -0,0 +1,68 @@
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.ServiceFactory = void 0;
13
+ class ServiceFactory {
14
+ /**
15
+ * Creates a singleton service factory that ensures a single instance of the provided service is initialized
16
+ * and used throughout the scope lifecycle.
17
+ */
18
+ static singleton({ scope, provides, dependsOn = [], initialize, dispose = () => { }, }) {
19
+ let promisedInstance;
20
+ let resolvedInstance;
21
+ return {
22
+ scope,
23
+ provides,
24
+ dependsOn,
25
+ initialize(...dependencies) {
26
+ return __awaiter(this, void 0, void 0, function* () {
27
+ if (resolvedInstance !== undefined) {
28
+ return resolvedInstance;
29
+ }
30
+ if (promisedInstance !== undefined) {
31
+ return promisedInstance;
32
+ }
33
+ // Store the reference to the promise so that concurrent requests can wait for it
34
+ promisedInstance = (() => __awaiter(this, void 0, void 0, function* () {
35
+ try {
36
+ resolvedInstance = yield initialize(...dependencies);
37
+ return resolvedInstance;
38
+ }
39
+ finally {
40
+ promisedInstance = undefined;
41
+ }
42
+ }))();
43
+ return promisedInstance;
44
+ });
45
+ },
46
+ dispose() {
47
+ if (resolvedInstance !== undefined) {
48
+ dispose(resolvedInstance);
49
+ resolvedInstance = undefined;
50
+ }
51
+ promisedInstance = undefined;
52
+ },
53
+ };
54
+ }
55
+ /**
56
+ * Creates a one-shot service factory that initializes a new instance of the provided service
57
+ * every time it is requested.
58
+ */
59
+ static oneShot({ provides, dependsOn, initialize, }) {
60
+ return {
61
+ provides,
62
+ dependsOn,
63
+ initialize,
64
+ };
65
+ }
66
+ }
67
+ exports.ServiceFactory = ServiceFactory;
68
+ //# sourceMappingURL=serviceFactory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serviceFactory.js","sourceRoot":"","sources":["../src/serviceFactory.ts"],"names":[],"mappings":";;;;;;;;;;;;AAiBA,MAAsB,cAAc;IAUlC;;;OAGG;IACH,MAAM,CAAC,SAAS,CAGd,EACA,KAAK,EACL,QAAQ,EACR,SAAS,GAAG,EAAkB,EAC9B,UAAU,EACV,OAAO,GAAG,GAAG,EAAE,GAAE,CAAC,GAOnB;QACC,IAAI,gBAAwC,CAAC;QAC7C,IAAI,gBAA+B,CAAC;QAEpC,OAAO;YACL,KAAK;YACL,QAAQ;YACR,SAAS;YACH,UAAU,CAAC,GAAG,YAAgC;;oBAClD,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;wBACnC,OAAO,gBAAgB,CAAC;oBAC1B,CAAC;oBAED,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;wBACnC,OAAO,gBAAgB,CAAC;oBAC1B,CAAC;oBAED,iFAAiF;oBACjF,gBAAgB,GAAG,CAAC,GAAS,EAAE;wBAC7B,IAAI,CAAC;4BACH,gBAAgB,GAAG,MAAM,UAAU,CAAC,GAAG,YAAY,CAAC,CAAC;4BACrD,OAAO,gBAAgB,CAAC;wBAC1B,CAAC;gCAAS,CAAC;4BACT,gBAAgB,GAAG,SAAS,CAAC;wBAC/B,CAAC;oBACH,CAAC,CAAA,CAAC,EAAE,CAAC;oBACL,OAAO,gBAAgB,CAAC;gBAC1B,CAAC;aAAA;YACD,OAAO;gBACL,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;oBACnC,OAAO,CAAC,gBAAgB,CAAC,CAAC;oBAC1B,gBAAgB,GAAG,SAAS,CAAC;gBAC/B,CAAC;gBACD,gBAAgB,GAAG,SAAS,CAAC;YAC/B,CAAC;SACF,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,OAAO,CAA+D,EAC3E,QAAQ,EACR,SAAS,EACT,UAAU,GAKX;QACC,OAAO;YACL,QAAQ;YACR,SAAS;YACT,UAAU;SACX,CAAC;IACJ,CAAC;CACF;AAtFD,wCAsFC"}
@@ -0,0 +1,90 @@
1
+ import { ServiceSelector } from './serviceSelector';
2
+ /**
3
+ * A typed token used to identify and retrieve a service from a ServiceModule.
4
+ *
5
+ * ServiceKey acts as a unique identifier for a service type, allowing type-safe
6
+ * dependency injection. Each key has a unique symbol to ensure identity comparison
7
+ * works correctly even if two keys have the same name.
8
+ *
9
+ * @template T The type of service this key identifies.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * interface Logger {
14
+ * log: (msg: string) => void;
15
+ * }
16
+ *
17
+ * const LoggerKey = new ServiceKey<Logger>('Logger');
18
+ *
19
+ * // Use with ServiceFactory and ServiceModule
20
+ * const loggerFactory = ServiceFactory.singleton({
21
+ * provides: LoggerKey,
22
+ * dependsOn: [],
23
+ * initialize: () => console,
24
+ * });
25
+ *
26
+ * const module = ServiceModule.from([loggerFactory]);
27
+ * const logger = await module.get(LoggerKey);
28
+ * ```
29
+ */
30
+ export declare class ServiceKey<T> {
31
+ readonly name: string;
32
+ /**
33
+ * A unique symbol that identifies this service key.
34
+ * Used internally for identity comparison between keys.
35
+ */
36
+ readonly symbol: symbol;
37
+ /**
38
+ * Creates a new ServiceKey with the given name.
39
+ *
40
+ * @param name A human-readable name for the service, used in error messages and debugging.
41
+ */
42
+ constructor(name: string);
43
+ }
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
+ export declare class ServiceSelectorKey<T> extends ServiceKey<ServiceSelector<T>> {
81
+ readonly values: ServiceKey<T>[];
82
+ /**
83
+ * Creates a new ServiceSelectorKey that groups the provided service keys.
84
+ *
85
+ * @param values An array of ServiceKeys that this selector can provide access to.
86
+ * All keys must be registered in the ServiceModule for dependency validation to pass.
87
+ */
88
+ constructor(values: ServiceKey<T>[]);
89
+ }
90
+ //# sourceMappingURL=serviceKey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serviceKey.d.ts","sourceRoot":"","sources":["../src/serviceKey.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,UAAU,CAAC,CAAC;aAYK,IAAI,EAAE,MAAM;IAXxC;;;OAGG;IACH,SAAgB,MAAM,EAAE,MAAM,CAAC;IAE/B;;;;OAIG;gBACyB,IAAI,EAAE,MAAM;CAGzC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,qBAAa,kBAAkB,CAAC,CAAC,CAAE,SAAQ,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAO3D,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE;IAN5C;;;;;OAKG;gBACkB,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE;CAG7C"}
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
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
+ */
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
+ */
38
+ constructor(name) {
39
+ this.name = name;
40
+ this.symbol = Symbol(name);
41
+ }
42
+ }
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;
93
+ //# sourceMappingURL=serviceKey.js.map
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,71 @@
1
+ import { ServiceKey } from './serviceKey';
2
+ import { ServiceFactory } from './serviceFactory';
3
+ import { ServiceScope } from './serviceScope';
4
+ import type { ServiceEventListener } from './serviceEventListener';
5
+ type GenericFactory = ServiceFactory<unknown, readonly ServiceKey<any>[]>;
6
+ /**
7
+ * ServiceModule is a container for service factories and manages dependency resolution.
8
+ *
9
+ * It provides a way to retrieve service instances based on their ServiceKey,
10
+ * ensuring that all dependencies are resolved and initialized in the correct order.
11
+ * It also handles circular dependency detection and missing dependency validation
12
+ * at the time of module creation.
13
+ */
14
+ export declare class ServiceModule {
15
+ readonly factories: GenericFactory[];
16
+ /**
17
+ * Private constructor to enforce module creation through the `static from` method.
18
+ *
19
+ * @param factories An array of service factories that this module will manage.
20
+ */
21
+ private constructor();
22
+ /**
23
+ * Retrieves an instance for the given ServiceKey.
24
+ *
25
+ * @param key - The key of the service to retrieve.
26
+ * @return A promise that resolves to the service instance.
27
+ * @throws {ServiceFactoryNotFoundError} If no suitable factory is found for the given key.
28
+ */
29
+ get<T>(key: ServiceKey<T>): Promise<T>;
30
+ /**
31
+ * Retrieves the value associated with the given service key or returns null if the service is not found.
32
+ *
33
+ * @param key - The key used to retrieve the associated service.
34
+ * @return A promise that resolves to the service value if found, or null if the service is not found.
35
+ */
36
+ getOrNull<T>(key: ServiceKey<T>): Promise<T | null>;
37
+ /**
38
+ * Disposes of service factories within the specified scope or all factories if no scope is provided.
39
+ *
40
+ * This method is useful for cleaning up resources and instances held by service factories,
41
+ * such as singleton factories, as they may hold database connections or other resources that need to be released.
42
+ *
43
+ * @param scope The scope to filter the factories to be disposed.
44
+ * If not provided, all factories are disposed of.
45
+ * @return No return value.
46
+ */
47
+ dispose(scope?: ServiceScope): void;
48
+ /**
49
+ * Creates a new ServiceModule instance by aggregating and deduplicating a list of
50
+ * ServiceModule or GenericFactory instances.
51
+ * If multiple factories provide the same
52
+ * ServiceKey, the last one in the list takes precedence.
53
+ *
54
+ * When a listener is provided, every factory is wrapped with instrumentation:
55
+ * the listener is notified when a service is initialized or disposed and when
56
+ * a method is called on a service instance, and may return an EventSpan per
57
+ * operation to observe its completion. Service instances are wrapped in a
58
+ * Proxy to observe method calls, and errors are rethrown after being
59
+ * reported, so behavior is otherwise unchanged.
60
+ *
61
+ * @param entries - An array of ServiceModule or GenericFactory
62
+ * instances to be processed into a single ServiceModule.
63
+ * @param listener - An optional ServiceEventListener notified of service
64
+ * lifecycle events and method calls in the resulting module.
65
+ * @return A new ServiceModule containing the deduplicated factories.
66
+ * @throws {ServiceModuleInitError} If circular or missing dependencies are detected during module creation.
67
+ */
68
+ static from(entries: (ServiceModule | GenericFactory)[], listener?: ServiceEventListener): ServiceModule;
69
+ }
70
+ export {};
71
+ //# sourceMappingURL=serviceModule.d.ts.map
@@ -0,0 +1 @@
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;AAG9C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEnE,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;;;;;OAKG;IACU,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAWhE;;;;;;;;;OASG;IACI,OAAO,CAAC,KAAK,CAAC,EAAE,YAAY;IAQnC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,MAAM,CAAC,IAAI,CACT,OAAO,EAAE,CAAC,aAAa,GAAG,cAAc,CAAC,EAAE,EAC3C,QAAQ,CAAC,EAAE,oBAAoB,GAC9B,aAAa;CAsBjB"}