@noego/ioc 0.0.11 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/framework/decorators/Provider.cjs +40 -0
- package/dist/framework/decorators/Provider.cjs.map +1 -0
- package/dist/framework/decorators/Provider.d.cts +29 -0
- package/dist/framework/decorators/Provider.d.ts +29 -0
- package/dist/framework/decorators/Provider.js +16 -0
- package/dist/framework/decorators/Provider.js.map +1 -0
- package/dist/framework/decorators/index.cjs +4 -1
- package/dist/framework/decorators/index.cjs.map +1 -1
- package/dist/framework/decorators/index.d.cts +1 -0
- package/dist/framework/decorators/index.d.ts +1 -0
- package/dist/framework/decorators/index.js +3 -1
- package/dist/framework/decorators/index.js.map +1 -1
- package/dist/framework/implementation/Container.cjs +47 -47
- package/dist/framework/implementation/Container.cjs.map +1 -1
- package/dist/framework/implementation/Container.d.cts +10 -4
- package/dist/framework/implementation/Container.d.ts +10 -4
- package/dist/framework/implementation/Container.js +46 -47
- package/dist/framework/implementation/Container.js.map +1 -1
- package/dist/framework/interface/Container.cjs.map +1 -1
- package/dist/framework/interface/Container.d.cts +2 -2
- package/dist/framework/interface/Container.d.ts +2 -2
- package/dist/index.cjs +4 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/readme.md +97 -5
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var Provider_exports = {};
|
|
20
|
+
__export(Provider_exports, {
|
|
21
|
+
Provider: () => Provider
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(Provider_exports);
|
|
24
|
+
var import_reflect_metadata = require("reflect-metadata");
|
|
25
|
+
var import_metadataKeys = require("./metadataKeys.cjs");
|
|
26
|
+
var import_LoadAs = require("../implementation/LoadAs.cjs");
|
|
27
|
+
function Provider(options = {}) {
|
|
28
|
+
return (target) => {
|
|
29
|
+
const finalOptions = {
|
|
30
|
+
scope: options.scope ?? import_LoadAs.LoadAs.Scoped
|
|
31
|
+
};
|
|
32
|
+
Reflect.defineMetadata(import_metadataKeys.COMPONENT_OPTIONS_METADATA_KEY, finalOptions, target);
|
|
33
|
+
Reflect.defineMetadata("ComponentOptions", finalOptions, target);
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
37
|
+
0 && (module.exports = {
|
|
38
|
+
Provider
|
|
39
|
+
});
|
|
40
|
+
//# sourceMappingURL=Provider.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../framework/decorators/Provider.ts"],"sourcesContent":["// framework/decorators/Provider.ts\nimport 'reflect-metadata';\nimport { COMPONENT_OPTIONS_METADATA_KEY } from './metadataKeys.cjs';\nimport { LoadAs } from '../implementation/LoadAs.cjs';\nimport { ComponentOptions } from './Component.cjs';\n\n/**\n * Marks a class as a provider managed by the IOC container.\n * Providers are scoped by default, making them ideal for the provider pattern\n * where instances should be scoped to a particular container context.\n *\n * This is equivalent to @Component({ scope: LoadAs.Scoped })\n *\n * @param options Configuration options. Defaults to Scoped lifetime.\n *\n * @example\n * ```typescript\n * import { Provider, SCOPED_CONTAINER, IContainer } from '@noego/ioc';\n *\n * @Provider()\n * class ServiceFactory {\n * constructor(@Inject(SCOPED_CONTAINER) private container: IContainer) {}\n *\n * async createService(name: string) {\n * return this.container.instance(MyService);\n * }\n * }\n * ```\n */\nexport function Provider(options: ComponentOptions = {}): ClassDecorator {\n return (target: Function) => {\n // Default to Scoped for providers\n const finalOptions: Required<ComponentOptions> = {\n scope: options.scope ?? LoadAs.Scoped,\n };\n\n // Define metadata on the class constructor\n Reflect.defineMetadata(COMPONENT_OPTIONS_METADATA_KEY, finalOptions, target);\n\n // Also define with string key for easier debugging\n Reflect.defineMetadata('ComponentOptions', finalOptions, target);\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,8BAAO;AACP,0BAA+C;AAC/C,oBAAuB;AA0BhB,SAAS,SAAS,UAA4B,CAAC,GAAmB;AACrE,SAAO,CAAC,WAAqB;AAEzB,UAAM,eAA2C;AAAA,MAC7C,OAAO,QAAQ,SAAS,qBAAO;AAAA,IACnC;AAGA,YAAQ,eAAe,oDAAgC,cAAc,MAAM;AAG3E,YAAQ,eAAe,oBAAoB,cAAc,MAAM;AAAA,EACnE;AACJ;","names":[]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ComponentOptions } from './Component.cjs';
|
|
2
|
+
import '../implementation/LoadAs.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Marks a class as a provider managed by the IOC container.
|
|
6
|
+
* Providers are scoped by default, making them ideal for the provider pattern
|
|
7
|
+
* where instances should be scoped to a particular container context.
|
|
8
|
+
*
|
|
9
|
+
* This is equivalent to @Component({ scope: LoadAs.Scoped })
|
|
10
|
+
*
|
|
11
|
+
* @param options Configuration options. Defaults to Scoped lifetime.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { Provider, SCOPED_CONTAINER, IContainer } from '@noego/ioc';
|
|
16
|
+
*
|
|
17
|
+
* @Provider()
|
|
18
|
+
* class ServiceFactory {
|
|
19
|
+
* constructor(@Inject(SCOPED_CONTAINER) private container: IContainer) {}
|
|
20
|
+
*
|
|
21
|
+
* async createService(name: string) {
|
|
22
|
+
* return this.container.instance(MyService);
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
declare function Provider(options?: ComponentOptions): ClassDecorator;
|
|
28
|
+
|
|
29
|
+
export { Provider };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ComponentOptions } from './Component.js';
|
|
2
|
+
import '../implementation/LoadAs.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Marks a class as a provider managed by the IOC container.
|
|
6
|
+
* Providers are scoped by default, making them ideal for the provider pattern
|
|
7
|
+
* where instances should be scoped to a particular container context.
|
|
8
|
+
*
|
|
9
|
+
* This is equivalent to @Component({ scope: LoadAs.Scoped })
|
|
10
|
+
*
|
|
11
|
+
* @param options Configuration options. Defaults to Scoped lifetime.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { Provider, SCOPED_CONTAINER, IContainer } from '@noego/ioc';
|
|
16
|
+
*
|
|
17
|
+
* @Provider()
|
|
18
|
+
* class ServiceFactory {
|
|
19
|
+
* constructor(@Inject(SCOPED_CONTAINER) private container: IContainer) {}
|
|
20
|
+
*
|
|
21
|
+
* async createService(name: string) {
|
|
22
|
+
* return this.container.instance(MyService);
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
declare function Provider(options?: ComponentOptions): ClassDecorator;
|
|
28
|
+
|
|
29
|
+
export { Provider };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import "reflect-metadata";
|
|
2
|
+
import { COMPONENT_OPTIONS_METADATA_KEY } from "./metadataKeys.js";
|
|
3
|
+
import { LoadAs } from "../implementation/LoadAs.js";
|
|
4
|
+
function Provider(options = {}) {
|
|
5
|
+
return (target) => {
|
|
6
|
+
const finalOptions = {
|
|
7
|
+
scope: options.scope ?? LoadAs.Scoped
|
|
8
|
+
};
|
|
9
|
+
Reflect.defineMetadata(COMPONENT_OPTIONS_METADATA_KEY, finalOptions, target);
|
|
10
|
+
Reflect.defineMetadata("ComponentOptions", finalOptions, target);
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
Provider
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=Provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../framework/decorators/Provider.ts"],"sourcesContent":["// framework/decorators/Provider.ts\nimport 'reflect-metadata';\nimport { COMPONENT_OPTIONS_METADATA_KEY } from './metadataKeys.js';\nimport { LoadAs } from '../implementation/LoadAs.js';\nimport { ComponentOptions } from './Component.js';\n\n/**\n * Marks a class as a provider managed by the IOC container.\n * Providers are scoped by default, making them ideal for the provider pattern\n * where instances should be scoped to a particular container context.\n *\n * This is equivalent to @Component({ scope: LoadAs.Scoped })\n *\n * @param options Configuration options. Defaults to Scoped lifetime.\n *\n * @example\n * ```typescript\n * import { Provider, SCOPED_CONTAINER, IContainer } from '@noego/ioc';\n *\n * @Provider()\n * class ServiceFactory {\n * constructor(@Inject(SCOPED_CONTAINER) private container: IContainer) {}\n *\n * async createService(name: string) {\n * return this.container.instance(MyService);\n * }\n * }\n * ```\n */\nexport function Provider(options: ComponentOptions = {}): ClassDecorator {\n return (target: Function) => {\n // Default to Scoped for providers\n const finalOptions: Required<ComponentOptions> = {\n scope: options.scope ?? LoadAs.Scoped,\n };\n\n // Define metadata on the class constructor\n Reflect.defineMetadata(COMPONENT_OPTIONS_METADATA_KEY, finalOptions, target);\n\n // Also define with string key for easier debugging\n Reflect.defineMetadata('ComponentOptions', finalOptions, target);\n };\n}\n"],"mappings":"AACA,OAAO;AACP,SAAS,sCAAsC;AAC/C,SAAS,cAAc;AA0BhB,SAAS,SAAS,UAA4B,CAAC,GAAmB;AACrE,SAAO,CAAC,WAAqB;AAEzB,UAAM,eAA2C;AAAA,MAC7C,OAAO,QAAQ,SAAS,OAAO;AAAA,IACnC;AAGA,YAAQ,eAAe,gCAAgC,cAAc,MAAM;AAG3E,YAAQ,eAAe,oBAAoB,cAAc,MAAM;AAAA,EACnE;AACJ;","names":[]}
|
|
@@ -20,16 +20,19 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
var decorators_exports = {};
|
|
21
21
|
__export(decorators_exports, {
|
|
22
22
|
Component: () => import_Component.Component,
|
|
23
|
-
Inject: () => import_Inject.Inject
|
|
23
|
+
Inject: () => import_Inject.Inject,
|
|
24
|
+
Provider: () => import_Provider.Provider
|
|
24
25
|
});
|
|
25
26
|
module.exports = __toCommonJS(decorators_exports);
|
|
26
27
|
var import_Component = require("./Component.cjs");
|
|
28
|
+
var import_Provider = require("./Provider.cjs");
|
|
27
29
|
var import_Inject = require("./Inject.cjs");
|
|
28
30
|
__reExport(decorators_exports, require("./metadataKeys.cjs"), module.exports);
|
|
29
31
|
// Annotate the CommonJS export names for ESM import in node:
|
|
30
32
|
0 && (module.exports = {
|
|
31
33
|
Component,
|
|
32
34
|
Inject,
|
|
35
|
+
Provider,
|
|
33
36
|
...require("./metadataKeys.cjs")
|
|
34
37
|
});
|
|
35
38
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../framework/decorators/index.ts"],"sourcesContent":["// Export decorators\nexport { Component } from './Component.cjs';\nexport { Inject } from './Inject.cjs';\nexport * from './metadataKeys.cjs';\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,uBAA0B;AAC1B,oBAAuB;AACvB,+BAAc,+
|
|
1
|
+
{"version":3,"sources":["../../../framework/decorators/index.ts"],"sourcesContent":["// Export decorators\nexport { Component } from './Component.cjs';\nexport { Provider } from './Provider.cjs';\nexport { Inject } from './Inject.cjs';\nexport * from './metadataKeys.cjs';\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,uBAA0B;AAC1B,sBAAyB;AACzB,oBAAuB;AACvB,+BAAc,+BAJd;","names":[]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { Component } from './Component.cjs';
|
|
2
|
+
export { Provider } from './Provider.cjs';
|
|
2
3
|
export { Inject } from './Inject.cjs';
|
|
3
4
|
export { COMPONENT_OPTIONS_METADATA_KEY, INJECT_TOKEN_METADATA_KEY, PARAM_TYPES_METADATA_KEY } from './metadataKeys.cjs';
|
|
4
5
|
import '../implementation/LoadAs.cjs';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { Component } from './Component.js';
|
|
2
|
+
export { Provider } from './Provider.js';
|
|
2
3
|
export { Inject } from './Inject.js';
|
|
3
4
|
export { COMPONENT_OPTIONS_METADATA_KEY, INJECT_TOKEN_METADATA_KEY, PARAM_TYPES_METADATA_KEY } from './metadataKeys.js';
|
|
4
5
|
import '../implementation/LoadAs.js';
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Component } from "./Component.js";
|
|
2
|
+
import { Provider } from "./Provider.js";
|
|
2
3
|
import { Inject } from "./Inject.js";
|
|
3
4
|
export * from "./metadataKeys.js";
|
|
4
5
|
export {
|
|
5
6
|
Component,
|
|
6
|
-
Inject
|
|
7
|
+
Inject,
|
|
8
|
+
Provider
|
|
7
9
|
};
|
|
8
10
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../framework/decorators/index.ts"],"sourcesContent":["// Export decorators\nexport { Component } from './Component.js';\nexport { Inject } from './Inject.js';\nexport * from './metadataKeys.js';\n"],"mappings":"AACA,SAAS,iBAAiB;AAC1B,SAAS,cAAc;AACvB,cAAc;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../framework/decorators/index.ts"],"sourcesContent":["// Export decorators\nexport { Component } from './Component.js';\nexport { Provider } from './Provider.js';\nexport { Inject } from './Inject.js';\nexport * from './metadataKeys.js';\n"],"mappings":"AACA,SAAS,iBAAiB;AAC1B,SAAS,gBAAgB;AACzB,SAAS,cAAc;AACvB,cAAc;","names":[]}
|
|
@@ -29,6 +29,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
29
29
|
var Container_exports = {};
|
|
30
30
|
__export(Container_exports, {
|
|
31
31
|
Container: () => Container,
|
|
32
|
+
SCOPED_CONTAINER: () => SCOPED_CONTAINER,
|
|
32
33
|
createContainer: () => createContainer,
|
|
33
34
|
isPromise: () => isPromise
|
|
34
35
|
});
|
|
@@ -41,6 +42,7 @@ var import_DecoratorSupport = require("./DecoratorSupport.cjs");
|
|
|
41
42
|
var import_ProxyFactory = require("./ProxyFactory.cjs");
|
|
42
43
|
var TraceLoggerModule = __toESM(require("./TraceLogger.cjs"), 1);
|
|
43
44
|
var import_TraceCleanup = require("./TraceCleanup.cjs");
|
|
45
|
+
const SCOPED_CONTAINER = Symbol.for("ioc:scoped-container");
|
|
44
46
|
var ContainerRouting = /* @__PURE__ */ ((ContainerRouting2) => {
|
|
45
47
|
ContainerRouting2["FUNCTIONAL"] = "FUNCTIONAL";
|
|
46
48
|
ContainerRouting2["CLASS"] = "CLASS";
|
|
@@ -220,8 +222,8 @@ class Container {
|
|
|
220
222
|
return "transient";
|
|
221
223
|
}
|
|
222
224
|
}
|
|
223
|
-
// Central resolution logic
|
|
224
|
-
|
|
225
|
+
// Central resolution logic - sync-first, returns T or Promise<T>
|
|
226
|
+
loadInstance(label, params = [], resolutionChain = [], parentProxyId) {
|
|
225
227
|
const currentLabelStr = typeof label === "function" && label.name ? label.name : String(label);
|
|
226
228
|
if (resolutionChain.includes(currentLabelStr)) {
|
|
227
229
|
console.error(`[IOC LoadInstance] Circular dependency detected: ${[...resolutionChain, currentLabelStr].join(" -> ")}`);
|
|
@@ -230,11 +232,14 @@ class Container {
|
|
|
230
232
|
const nextResolutionChain = [...resolutionChain, currentLabelStr];
|
|
231
233
|
if (label instanceof import_Parameter.Parameter) {
|
|
232
234
|
try {
|
|
233
|
-
return
|
|
235
|
+
return this.resolveParameterValue(label, [...params]);
|
|
234
236
|
} catch (e) {
|
|
235
|
-
|
|
237
|
+
throw e;
|
|
236
238
|
}
|
|
237
239
|
}
|
|
240
|
+
if (label === SCOPED_CONTAINER) {
|
|
241
|
+
return this;
|
|
242
|
+
}
|
|
238
243
|
if (this.isRegisteredAsClass(label)) {
|
|
239
244
|
return this.loadClassInstance(label, params, nextResolutionChain, parentProxyId);
|
|
240
245
|
}
|
|
@@ -279,58 +284,52 @@ class Container {
|
|
|
279
284
|
futureProxyId = (0, import_ProxyFactory.reserveProxyId)();
|
|
280
285
|
}
|
|
281
286
|
const paramsCopy = [...params];
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
+
const resolvedDependencies = [];
|
|
288
|
+
let hasAsyncDependency = false;
|
|
289
|
+
for (const dependencyIdentifier of dependenciesToResolve) {
|
|
290
|
+
const resolved = this.loadInstance(dependencyIdentifier, paramsCopy, resolutionChain, futureProxyId);
|
|
291
|
+
resolvedDependencies.push(resolved);
|
|
292
|
+
if (isPromise(resolved)) {
|
|
293
|
+
hasAsyncDependency = true;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
const instantiate = (deps) => {
|
|
297
|
+
try {
|
|
298
|
+
const instance = new classDefinition(...deps);
|
|
299
|
+
if (this._enableTracing && futureProxyId !== void 0) {
|
|
300
|
+
return (0, import_ProxyFactory.wrapWithProxy)(instance, className, parentProxyId, futureProxyId);
|
|
301
|
+
}
|
|
302
|
+
return instance;
|
|
303
|
+
} catch (err) {
|
|
304
|
+
console.error(`[IOC LoadClass] Error during instantiation of ${className}: ${err.message}`, err.stack);
|
|
305
|
+
throw err;
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
if (!hasAsyncDependency) {
|
|
309
|
+
const instance = instantiate(resolvedDependencies);
|
|
310
|
+
if (storageType && storageType !== "transient") {
|
|
311
|
+
this.setInstance(classDefinition, instance, storageType);
|
|
312
|
+
}
|
|
313
|
+
return instance;
|
|
314
|
+
}
|
|
315
|
+
const asyncInstance = Promise.all(resolvedDependencies).then((deps) => {
|
|
316
|
+
const instance = instantiate(deps);
|
|
317
|
+
if (storageType && storageType !== "transient") {
|
|
318
|
+
this.setInstance(classDefinition, instance, storageType);
|
|
319
|
+
}
|
|
320
|
+
return instance;
|
|
321
|
+
}).catch((error) => {
|
|
287
322
|
console.error(`[IOC LoadClass] Failed to resolve one or more dependencies for ${className}:`, error);
|
|
288
323
|
if (storageType && this.isRegisteredAsClass(classDefinition)) {
|
|
289
324
|
if (storageType === "singleton") this._classStorageSingleton.delete(classDefinition);
|
|
290
325
|
if (storageType === "scoped") this._classStorageScoped.delete(classDefinition);
|
|
291
326
|
}
|
|
292
327
|
throw error;
|
|
293
|
-
}).then(async (resolvedDependencies) => {
|
|
294
|
-
let instancePromise;
|
|
295
|
-
if (storageType && !this.hasInstance(classDefinition)) {
|
|
296
|
-
instancePromise = (async () => {
|
|
297
|
-
try {
|
|
298
|
-
const instance = new classDefinition(...resolvedDependencies);
|
|
299
|
-
let wrappedInstance = instance;
|
|
300
|
-
if (this._enableTracing && futureProxyId !== void 0) {
|
|
301
|
-
wrappedInstance = (0, import_ProxyFactory.wrapWithProxy)(instance, className, parentProxyId, futureProxyId);
|
|
302
|
-
}
|
|
303
|
-
this.setInstance(classDefinition, wrappedInstance, storageType);
|
|
304
|
-
return wrappedInstance;
|
|
305
|
-
} catch (err) {
|
|
306
|
-
console.error(`[IOC LoadClass] Error during instantiation of ${className}: ${err.message}`, err.stack);
|
|
307
|
-
if (storageType === "singleton") this._classStorageSingleton.delete(classDefinition);
|
|
308
|
-
if (storageType === "scoped") this._classStorageScoped.delete(classDefinition);
|
|
309
|
-
throw err;
|
|
310
|
-
}
|
|
311
|
-
})();
|
|
312
|
-
this.setInstance(classDefinition, instancePromise, storageType);
|
|
313
|
-
} else {
|
|
314
|
-
instancePromise = (async () => {
|
|
315
|
-
try {
|
|
316
|
-
const instance = new classDefinition(...resolvedDependencies);
|
|
317
|
-
let wrappedInstance = instance;
|
|
318
|
-
if (this._enableTracing && futureProxyId !== void 0) {
|
|
319
|
-
wrappedInstance = (0, import_ProxyFactory.wrapWithProxy)(instance, className, parentProxyId, futureProxyId);
|
|
320
|
-
}
|
|
321
|
-
return wrappedInstance;
|
|
322
|
-
} catch (err) {
|
|
323
|
-
console.error(`[IOC LoadClass] Error during instantiation of transient ${className}: ${err.message}`, err.stack);
|
|
324
|
-
throw err;
|
|
325
|
-
}
|
|
326
|
-
})();
|
|
327
|
-
}
|
|
328
|
-
return await instancePromise;
|
|
329
328
|
});
|
|
330
329
|
if (storageType && storageType !== "transient") {
|
|
331
|
-
this.setInstance(classDefinition,
|
|
330
|
+
this.setInstance(classDefinition, asyncInstance, storageType);
|
|
332
331
|
}
|
|
333
|
-
return
|
|
332
|
+
return asyncInstance;
|
|
334
333
|
}
|
|
335
334
|
loadFunctionInstance(funcLabel, params, resolutionChain) {
|
|
336
335
|
const functionConfig = this._functionDefinition.get(funcLabel);
|
|
@@ -398,6 +397,7 @@ function createContainer() {
|
|
|
398
397
|
// Annotate the CommonJS export names for ESM import in node:
|
|
399
398
|
0 && (module.exports = {
|
|
400
399
|
Container,
|
|
400
|
+
SCOPED_CONTAINER,
|
|
401
401
|
createContainer,
|
|
402
402
|
isPromise
|
|
403
403
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../framework/implementation/Container.ts"],"sourcesContent":["import 'reflect-metadata'; // Ensure polyfill is loaded conceptually\nimport type { ContainerOptions, IContainerClient, IContainerFunctionDefinition, IContainerSetup } from \"../interface/Container.cjs\";\nimport { LoadAs } from \"./LoadAs.cjs\";\nimport { Parameter } from \"./Parameter.cjs\";\nimport type { ParameterValue } from \"./Parameter.cjs\";\nimport { NotAClassDefinitionError, ParameterNotFoundError, DependencyNotFoundError, InstanceNotCreatedError, CircularDependencyError } from \"../errors/ContainerErrors.cjs\";\nimport {\n getScope,\n getComponentOptions, // Use helper\n getResolvedDependencies // Use helper\n} from './DecoratorSupport'; // Assume helpers exist or create them\nimport { wrapWithProxy, setTraceLogger, reserveProxyId } from \"./ProxyFactory.cjs\";\nimport * as TraceLoggerModule from \"./TraceLogger.cjs\";\nimport { TraceCleanup } from \"./TraceCleanup.cjs\";\n\nenum ContainerRouting {\n FUNCTIONAL = \"FUNCTIONAL\",\n CLASS = \"CLASS\"\n // No need for COMPONENT route, just check metadata if CLASS/FUNCTIONAL fails\n}\n\ntype StorageType = 'singleton' | 'scoped' | 'transient';\n\nexport class Container implements IContainerClient, IContainerSetup {\n // Routing and definition maps\n private _routing: Map<any, ContainerRouting> = new Map();\n private _functionDefinition: Map<any, IContainerFunctionDefinition> = new Map();\n private _classDefinition: Map<Function, Partial<ContainerOptions>> = new Map();\n\n // Storage maps\n private _functionStorageSingleton: Map<any, any> = new Map();\n private _functionStorageScoped: Map<any, any> = new Map();\n private _classStorageSingleton: Map<Function, any> = new Map();\n private _classStorageScoped: Map<Function, any> = new Map();\n\n // Tracing configuration\n private _enableTracing: boolean = false;\n private _traceRetentionMinutes: number = 5;\n\n // Registration methods\n registerClass<T>(classDefinition: new (...args: any[]) => T, options?: Partial<ContainerOptions>): void {\n // Basic validation\n if (typeof classDefinition !== 'function' || !classDefinition.prototype) {\n console.warn(`[IOC] Attempted to register non-class: ${String(classDefinition)}`);\n // Optional: throw error instead?\n // throw new NotAClassDefinitionError(`Attempted to register non-class: ${String(classDefinition)}`);\n return; // Don't proceed if not a class constructor\n }\n\n // Always clear previous definitions for this exact class constructor\n this.clearDefinitions(classDefinition);\n\n // Always set the routing type so 'isClassDefinition' works\n this._routing.set(classDefinition, ContainerRouting.CLASS);\n\n // Store manual options *only if they are actually provided and have content*\n if (options && Object.keys(options).length > 0) {\n this._classDefinition.set(classDefinition, options);\n // console.log(`[IOC RegClass] Manually registered ${classDefinition.name} with options:`, options);\n } else {\n // console.log(`[IOC RegClass] Manually registered ${classDefinition.name} with no specific options (will use decorators if present).`);\n // If no options are provided, we don't store anything in _classDefinition,\n // effectively clearing any previous manual config and letting decorators take over if present.\n }\n }\n\n registerFunction<T extends (...arg: any[]) => any>(label: any, func: T, options: Partial<ContainerOptions> = {} as any): void {\n this.clearDefinitions(label);\n this._routing.set(label, ContainerRouting.FUNCTIONAL);\n this._functionDefinition.set(label, { function: func, options });\n // console.log(`[IOC RegFunc] Registered function with label ${String(label)} and options:`, options);\n }\n\n // Instance resolution methods - Simplify to just call loadInstance\n instance<T, Args extends any[]>(classDefinition: new (...args: Args) => T, params: ParameterValue<any>[] = []): Promise<T> {\n // Basic check upfront\n if (typeof classDefinition !== 'function' || !classDefinition.prototype) {\n throw new NotAClassDefinitionError(`Cannot resolve instance for non-class: ${String(classDefinition)}`);\n }\n return this.loadInstance(classDefinition, params) as Promise<T>;\n }\n\n get<T>(label: any, param: ParameterValue<any>[] = []): Promise<T> | T {\n // Just delegate to loadInstance, which handles routing and auto-registration\n return this.loadInstance(label, param);\n }\n\n extend(): IContainerClient & IContainerSetup {\n const childContainer = createContainer() as Container;\n\n // Copy routing and definition maps (share the registration knowledge)\n childContainer._routing = new Map(this._routing);\n childContainer._functionDefinition = new Map(this._functionDefinition);\n childContainer._classDefinition = new Map(this._classDefinition);\n\n // Share singleton storage (singletons are shared across all containers)\n childContainer._functionStorageSingleton = this._functionStorageSingleton;\n childContainer._classStorageSingleton = this._classStorageSingleton;\n\n // Do NOT share scoped storage (new container = new scope)\n // Child gets its own empty scoped storage\n\n // Share tracing configuration\n childContainer._enableTracing = this._enableTracing;\n childContainer._traceRetentionMinutes = this._traceRetentionMinutes;\n\n // console.log('[IOC Extend] Created child container.');\n return childContainer;\n }\n\n // Tracing API\n setTracingEnabled(enabled: boolean): void {\n this._enableTracing = enabled;\n if (enabled && !TraceCleanup.isCleanupRunning()) {\n // Set the trace logger for the ProxyFactory\n setTraceLogger(TraceLoggerModule as any);\n // Start automatic cleanup\n TraceCleanup.start(this._traceRetentionMinutes);\n }\n }\n\n isTracingEnabled(): boolean {\n return this._enableTracing;\n }\n\n setTraceRetentionMinutes(minutes: number): void {\n this._traceRetentionMinutes = Math.max(1, minutes);\n }\n\n getTraces(retentionMinutes?: number): any[] {\n const retention = retentionMinutes ?? this._traceRetentionMinutes;\n return TraceLoggerModule.getRecentTraces(retention);\n }\n\n getAllTraces(): any[] {\n return TraceLoggerModule.getAllTraces();\n }\n\n clearTraces(): void {\n TraceLoggerModule.clearAllTraces();\n }\n\n exportTraces(filepath: string): void {\n const data = TraceLoggerModule.exportTracesToJson();\n const fs = require('fs');\n fs.writeFileSync(filepath, JSON.stringify(data, null, 2));\n }\n\n getTraceStatistics(): any {\n return TraceLoggerModule.getTraceStatistics();\n }\n\n // Private helper methods\n private clearDefinitions(label: any): void {\n this._routing.delete(label);\n this._functionDefinition.delete(label);\n // Only delete from classDefinition if the label is actually a function constructor\n if (typeof label === 'function') {\n this._classDefinition.delete(label);\n }\n }\n\n // Checks if the label is *currently* registered as a class\n private isRegisteredAsClass(label: any): boolean {\n return this._routing.get(label) === ContainerRouting.CLASS;\n }\n\n // Checks if the label is *currently* registered as a function\n private isRegisteredAsFunction(label: any): boolean {\n return this._routing.get(label) === ContainerRouting.FUNCTIONAL;\n }\n\n\n private hasInstance(label: any): boolean {\n const storageType = this.getStorageType(label); // This checks decorators if needed\n\n if (!storageType) {\n // Transient instances are never stored\n return false;\n }\n\n // Determine if it's treated as a class (registered or decorated) *after* getting type\n const isClass = this.isClassType(label); // Use a helper that checks routing OR decorator\n\n if (isClass) {\n return storageType === 'singleton'\n ? this._classStorageSingleton.has(label)\n : this._classStorageScoped.has(label);\n } else { // Must be a function if not a class\n return storageType === 'singleton'\n ? this._functionStorageSingleton.has(label)\n : this._functionStorageScoped.has(label);\n }\n }\n\n // Helper to determine if something should be treated as a class (registered or decorated)\n private isClassType(label: any): boolean {\n if (this.isRegisteredAsClass(label)) {\n return true;\n }\n // If not explicitly registered as a class, check if it's a function with @Component\n if (typeof label === 'function' && label.prototype && !this.isRegisteredAsFunction(label)) {\n return getComponentOptions(label) !== null;\n }\n return false;\n }\n\n private getInstance(label: any): any {\n const storageType = this.getStorageType(label); // Checks decorators if needed\n\n if (!storageType) {\n // This should ideally not be reached if called after hasInstance check\n console.error(`[IOC GetInstance] Attempted to get instance for non-stored type: ${String(label)}`);\n throw new InstanceNotCreatedError();\n }\n\n const isClass = this.isClassType(label); // Check routing OR decorator\n\n if (isClass) {\n return storageType === 'singleton'\n ? this._classStorageSingleton.get(label)\n : this._classStorageScoped.get(label);\n } else { // Must be a function\n return storageType === 'singleton'\n ? this._functionStorageSingleton.get(label)\n : this._functionStorageScoped.get(label);\n }\n }\n\n private setInstance(label: any, instance: any, storageType?: StorageType): void { // Made storageType non-optional\n const isClass = this.isClassType(label); // Determine type based on routing OR decorator\n\n if (isClass) {\n if (storageType === 'singleton') {\n this._classStorageSingleton.set(label, instance);\n } else if (storageType == 'scoped'){ // storageType === 'scoped'\n this._classStorageScoped.set(label, instance);\n }\n } else { // Must be a function\n if (storageType === 'singleton') {\n this._functionStorageSingleton.set(label, instance);\n } else if(storageType === \"scoped\"){ // storageType === 'scoped'\n this._functionStorageScoped.set(label, instance);\n }\n }\n }\n\n private getStorageType(label: any): StorageType {\n let manualLoadAs: LoadAs | undefined;\n let decoratorScope: LoadAs | undefined;\n const isPotentialClass = typeof label === 'function' && label.prototype;\n\n // Get manual registration options if available\n if (this.isRegisteredAsClass(label)) { // Use helper\n manualLoadAs = this._classDefinition.get(label)?.loadAs;\n } else if (this.isRegisteredAsFunction(label)) { // Use helper\n manualLoadAs = this._functionDefinition.get(label)?.options?.loadAs;\n }\n\n // Get decorator scope only if it's potentially a class *and not explicitly registered as a function*\n if (isPotentialClass && !this.isRegisteredAsFunction(label)) {\n decoratorScope = getScope(label); // Uses getComponentOptions internally\n }\n\n // Determine final scope: Manual > Decorator > Default (Transient)\n const finalScope = manualLoadAs ?? decoratorScope ?? LoadAs.Transient;\n\n if (finalScope === LoadAs.Singleton) {\n return 'singleton';\n } else if (finalScope === LoadAs.Scoped) {\n return 'scoped';\n }else{\n return 'transient'; // Transient\n }\n }\n\n // Central resolution logic\n protected async loadInstance(\n label: any,\n params: ParameterValue<any>[] = [],\n resolutionChain: string[] = [], // Track resolution path\n parentProxyId?: number // For proxy hierarchy tracking\n ): Promise<any> {\n\n // --- Circular Dependency Check ---\n const currentLabelStr = (typeof label === 'function' && label.name) ? label.name : String(label);\n if (resolutionChain.includes(currentLabelStr)) {\n console.error(`[IOC LoadInstance] Circular dependency detected: ${[...resolutionChain, currentLabelStr].join(' -> ')}`);\n throw new CircularDependencyError([...resolutionChain, currentLabelStr]);\n }\n const nextResolutionChain = [...resolutionChain, currentLabelStr];\n // --- End Circular Dependency Check ---\n\n // --- Handle Parameters ---\n if (label instanceof Parameter) {\n try {\n // Pass a *copy* of params to avoid side effects in resolveParameterValue\n return Promise.resolve(this.resolveParameterValue(label, [...params]));\n } catch (e) {\n // console.error(`[IOC LoadInstance] Error resolving parameter ${param.toString()}:`, e);\n return Promise.reject(e);\n }\n }\n // --- End Handle Parameters ---\n\n\n // --- Check Explicit Registrations ---\n if (this.isRegisteredAsClass(label)) {\n // console.log(`[IOC LoadInstance] Resolving explicitly registered class: ${currentLabelStr}`);\n return this.loadClassInstance(label, params, nextResolutionChain, parentProxyId);\n }\n if (this.isRegisteredAsFunction(label)) {\n // console.log(`[IOC LoadInstance] Resolving explicitly registered function: ${currentLabelStr}`);\n return this.loadFunctionInstance(label, params, nextResolutionChain);\n }\n // --- End Check Explicit Registrations ---\n\n\n // --- Attempt Auto-Registration/Resolution for Decorated Classes ---\n if (typeof label === 'function' && label.prototype) {\n const componentOptions = getComponentOptions(label); // Check for @Component\n if (componentOptions !== null) {\n // console.log(`[IOC LoadInstance] Auto-resolving @Component class: ${currentLabelStr}`);\n // Set routing *now* so subsequent internal checks work correctly\n if (!this._routing.has(label)) { // Only set if not already set\n this._routing.set(label, ContainerRouting.CLASS);\n // console.log(`[IOC LoadInstance] Set routing for auto-resolved class: ${currentLabelStr}`);\n }\n // Proceed to load it as a class\n return this.loadClassInstance(label, params, nextResolutionChain, parentProxyId);\n }\n }\n // --- End Auto-Registration ---\n\n\n // --- Dependency Not Found ---\n console.error(`[IOC LoadInstance] Dependency not found and cannot be resolved: ${currentLabelStr}`);\n throw new DependencyNotFoundError(currentLabelStr);\n }\n\n\n private resolveParameterValue(param: Parameter, params: ParameterValue<any>[]): any { // No mutation\n // Find the *last* provided value for the parameter\n const valueContainer = [...params].reverse().find((p) => p.belongsTo(param));\n if (!valueContainer) {\n // console.error(`[IOC ResolveParam] Parameter not found: ${param.toString()}`);\n throw new ParameterNotFoundError(param.toString());\n }\n // console.log(`[IOC ResolveParam] Resolved parameter ${param.toString()}`);\n return valueContainer.value;\n }\n\n private loadClassInstance(\n classDefinition: any, // Should be a class constructor here\n params: ParameterValue<any>[],\n resolutionChain: string[],\n parentProxyId?: number\n ): Promise<any> {\n const storageType = this.getStorageType(classDefinition);\n const className = classDefinition.name || '[Anonymous Class]';\n\n // Check storage first (handle stored promises)\n if (storageType && this.hasInstance(classDefinition)) {\n const instance = this.getInstance(classDefinition);\n // console.log(`[IOC LoadClass] Found existing ${storageType} instance for ${className}. IsPromise: ${isPromise(instance)}`);\n return instance\n }\n // console.log(`[IOC LoadClass] Creating new ${storageType || 'transient'} instance for ${className}`);\n\n // --- Determine Dependencies ---\n const manualOptions = this._classDefinition.get(classDefinition) as ContainerOptions | undefined;\n let dependenciesToResolve: any[];\n\n if (manualOptions?.param && Array.isArray(manualOptions.param)) {\n dependenciesToResolve = manualOptions.param;\n // console.log(`[IOC LoadClass] Using manual dependencies for ${className}`);\n } else {\n // Use decorator-derived dependencies\n dependenciesToResolve = getResolvedDependencies(classDefinition);\n // console.log(`[IOC LoadClass] Using decorator/reflected dependencies for ${className}:`, dependenciesToResolve.map(d => typeof d === 'function' ? d.name : String(d)));\n }\n // --- End Determine Dependencies ---\n\n // Reserve a proxy ID if tracing is enabled\n let futureProxyId: number | undefined;\n if (this._enableTracing) {\n futureProxyId = reserveProxyId();\n }\n\n // --- Resolve Dependencies ---\n // Create a *copy* of params to pass down for dependency resolution\n const paramsCopy = [...params];\n const resolutionPromises = dependenciesToResolve.map(dependencyIdentifier =>\n this.loadInstance(dependencyIdentifier, paramsCopy, resolutionChain, futureProxyId) // Recursive call handles auto-registration\n );\n\n let finalInstance = Promise.all(resolutionPromises)\n .catch((error)=>{\n console.error(`[IOC LoadClass] Failed to resolve one or more dependencies for ${className}:`, error);\n // Clean up potential partially stored promise if this was going to be singleton/scoped\n if (storageType && this.isRegisteredAsClass(classDefinition)) { // Check if it was actually *being* stored\n if (storageType === 'singleton') this._classStorageSingleton.delete(classDefinition);\n if (storageType === 'scoped') this._classStorageScoped.delete(classDefinition);\n }\n throw error; // Re-throw dependency resolution error\n }).then(async(resolvedDependencies)=>{\n // --- Instantiate Class ---\n // Store the promise *before* starting instantiation for concurrent requests\n let instancePromise: Promise<any> | undefined;\n if (storageType && !this.hasInstance(classDefinition)) { // Check again in case of race condition?\n // Create the promise wrapper immediately\n instancePromise = (async () => {\n try {\n // console.log(`[IOC LoadClass] Instantiating ${className} with ${resolvedDependencies.length} args.`);\n const instance = new classDefinition(...resolvedDependencies);\n\n // Wrap with proxy if tracing is enabled\n let wrappedInstance = instance;\n if (this._enableTracing && futureProxyId !== undefined) {\n wrappedInstance = wrapWithProxy(instance, className, parentProxyId, futureProxyId);\n }\n\n // Overwrite the stored promise with the actual instance *after* it's created\n this.setInstance(classDefinition, wrappedInstance, storageType); // Use the correct storageType\n // console.log(`[IOC LoadClass] Stored actual ${storageType} instance for ${className}`);\n return wrappedInstance;\n } catch (err: any) {\n console.error(`[IOC LoadClass] Error during instantiation of ${className}: ${err.message}`, err.stack);\n // Clean up the stored promise on failure\n if (storageType === 'singleton') this._classStorageSingleton.delete(classDefinition);\n if (storageType === 'scoped') this._classStorageScoped.delete(classDefinition);\n throw err; // Re-throw instantiation error\n }\n })();\n // console.log(`[IOC LoadClass] Storing promise for concurrent requests (${storageType}) for ${className}`);\n this.setInstance(classDefinition, instancePromise, storageType);\n } else {\n // If already has instance (from storage check) or is transient, just instantiate directly\n instancePromise = (async () => {\n try {\n // console.log(`[IOC LoadClass] Instantiating transient ${className} with ${resolvedDependencies.length} args.`);\n const instance = new classDefinition(...resolvedDependencies);\n\n // Wrap with proxy if tracing is enabled\n let wrappedInstance = instance;\n if (this._enableTracing && futureProxyId !== undefined) {\n wrappedInstance = wrapWithProxy(instance, className, parentProxyId, futureProxyId);\n }\n\n // No storing for transient\n return wrappedInstance;\n } catch (err: any) {\n console.error(`[IOC LoadClass] Error during instantiation of transient ${className}: ${err.message}`, err.stack);\n throw err; // Re-throw instantiation error\n }\n })();\n }\n // --- End Instantiate Class ---\n // Await and return the final instance (either newly created or from the stored promise)\n return await instancePromise;\n });\n\n if(storageType && storageType !== 'transient'){\n this.setInstance(classDefinition, finalInstance, storageType); // Store the promise\n }\n return finalInstance\n }\n\n private loadFunctionInstance(\n funcLabel: any,\n params: ParameterValue<any>[],\n resolutionChain: string[]\n ): Promise<any> { // Always return Promise<any> since this is an async function\n const functionConfig = this._functionDefinition.get(funcLabel)!; // Assumed to exist by caller\n const storageType = this.getStorageType(funcLabel); // Only uses manual options for functions\n const labelStr = String(funcLabel);\n\n // Check storage first\n if (storageType && this.hasInstance(funcLabel)) {\n const instance = this.getInstance(funcLabel);\n // console.log(`[IOC LoadFunc] Found existing ${storageType} instance for ${labelStr}. IsPromise: ${isPromise(instance)}`);\n return instance;\n }\n // console.log(`[IOC LoadFunc] Creating new ${storageType || 'transient'} instance for ${labelStr}`);\n\n const ioc_func = functionConfig.function;\n const options = functionConfig.options;\n const dependenciesToResolve: any[] = options?.param || [];\n\n // --- Resolve Dependencies ---\n const paramsCopy = [...params]; // Create a copy\n const resolutionPromises = dependenciesToResolve.map(dependencyIdentifier =>\n this.loadInstance(dependencyIdentifier, paramsCopy, resolutionChain)\n );\n\n let finalInstance = Promise.all(resolutionPromises).catch((error)=>{\n console.error(`[IOC LoadFunc] Failed to resolve dependencies for function ${labelStr}:`, error);\n // Clean up potential partial storage\n if (storageType && this.isRegisteredAsFunction(funcLabel)) {\n if (storageType === 'singleton') this._functionStorageSingleton.delete(funcLabel);\n if (storageType === 'scoped') this._functionStorageScoped.delete(funcLabel);\n }\n throw error;\n }).then(async(resolvedArgs)=>{\n let instancePromise: Promise<any> | undefined;\n if (storageType && !this.hasInstance(funcLabel)) {\n instancePromise = (async () => {\n try {\n // console.log(`[IOC LoadFunc] Invoking ${labelStr} with ${resolvedArgs.length} args.`);\n const result = await ioc_func.apply(null, resolvedArgs); // Await in case function is async\n // Overwrite stored promise with actual result\n this.setInstance(funcLabel, result, storageType);\n // console.log(`[IOC LoadFunc] Stored actual ${storageType} instance for ${labelStr}`);\n return result;\n } catch (err: any) {\n console.error(`[IOC LoadFunc] Error executing function ${labelStr}: ${err.message}`, err.stack);\n // Clean up stored promise on failure\n if (storageType === 'singleton') this._functionStorageSingleton.delete(funcLabel);\n if (storageType === 'scoped') this._functionStorageScoped.delete(funcLabel);\n throw err;\n }\n })();\n // console.log(`[IOC LoadFunc] Storing promise for concurrent requests (${storageType}) for ${labelStr}`);\n this.setInstance(funcLabel, instancePromise, storageType);\n } else {\n // Transient or already resolved from storage check\n instancePromise = (async () => {\n try {\n // console.log(`[IOC LoadFunc] Invoking transient ${labelStr} with ${resolvedArgs.length} args.`);\n const result = await ioc_func.apply(null, resolvedArgs); // Await in case function is async\n // No storing for transient\n return result;\n } catch (err: any) {\n console.error(`[IOC LoadFunc] Error executing transient function ${labelStr}: ${err.message}`, err.stack);\n throw err;\n }\n })();\n }\n // --- End Invoke Function ---\n\n return await instancePromise; // Return the final (awaited) result\n });\n\n if(storageType && storageType !== 'transient'){\n this.setInstance(funcLabel, finalInstance, storageType); // Store the promise\n }\n\n return finalInstance;\n }\n}\n\n// Helper functions\nexport function isPromise(obj: any): obj is Promise<any> {\n // Simplified check - more robust check might be needed depending on environment\n return !!obj && typeof obj.then === 'function';\n}\n\nexport function createContainer(): IContainerClient & IContainerSetup {\n return new Container();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,8BAAO;AAEP,oBAAuB;AACvB,uBAA0B;AAE1B,6BAA4I;AAC5I,8BAIO;AACP,0BAA8D;AAC9D,wBAAmC;AACnC,0BAA6B;AAE7B,IAAK,mBAAL,kBAAKA,sBAAL;AACI,EAAAA,kBAAA,gBAAa;AACb,EAAAA,kBAAA,WAAQ;AAFP,SAAAA;AAAA,GAAA;AAQE,MAAM,UAAuD;AAAA,EAA7D;AAEH;AAAA,SAAQ,WAAuC,oBAAI,IAAI;AACvD,SAAQ,sBAA8D,oBAAI,IAAI;AAC9E,SAAQ,mBAA6D,oBAAI,IAAI;AAG7E;AAAA,SAAQ,4BAA2C,oBAAI,IAAI;AAC3D,SAAQ,yBAAwC,oBAAI,IAAI;AACxD,SAAQ,yBAA6C,oBAAI,IAAI;AAC7D,SAAQ,sBAA0C,oBAAI,IAAI;AAG1D;AAAA,SAAQ,iBAA0B;AAClC,SAAQ,yBAAiC;AAAA;AAAA;AAAA,EAGzC,cAAiB,iBAA4C,SAA2C;AAEpG,QAAI,OAAO,oBAAoB,cAAc,CAAC,gBAAgB,WAAW;AACpE,cAAQ,KAAK,0CAA0C,OAAO,eAAe,CAAC,EAAE;AAGhF;AAAA,IACL;AAGA,SAAK,iBAAiB,eAAe;AAGrC,SAAK,SAAS,IAAI,iBAAiB,mBAAsB;AAGzD,QAAI,WAAW,OAAO,KAAK,OAAO,EAAE,SAAS,GAAG;AAC5C,WAAK,iBAAiB,IAAI,iBAAiB,OAAO;AAAA,IAEtD,OAAO;AAAA,IAIP;AAAA,EACJ;AAAA,EAEA,iBAAmD,OAAY,MAAS,UAAqC,CAAC,GAAgB;AAC1H,SAAK,iBAAiB,KAAK;AAC3B,SAAK,SAAS,IAAI,OAAO,6BAA2B;AACpD,SAAK,oBAAoB,IAAI,OAAO,EAAE,UAAU,MAAM,QAAQ,CAAC;AAAA,EAEnE;AAAA;AAAA,EAGA,SAAgC,iBAA2C,SAAgC,CAAC,GAAe;AAEvH,QAAI,OAAO,oBAAoB,cAAc,CAAC,gBAAgB,WAAW;AACpE,YAAM,IAAI,gDAAyB,0CAA0C,OAAO,eAAe,CAAC,EAAE;AAAA,IAC3G;AACA,WAAO,KAAK,aAAa,iBAAiB,MAAM;AAAA,EACpD;AAAA,EAEA,IAAO,OAAY,QAA+B,CAAC,GAAmB;AAElE,WAAO,KAAK,aAAa,OAAO,KAAK;AAAA,EACzC;AAAA,EAEA,SAA6C;AACzC,UAAM,iBAAiB,gBAAgB;AAGvC,mBAAe,WAAW,IAAI,IAAI,KAAK,QAAQ;AAC/C,mBAAe,sBAAsB,IAAI,IAAI,KAAK,mBAAmB;AACrE,mBAAe,mBAAmB,IAAI,IAAI,KAAK,gBAAgB;AAG/D,mBAAe,4BAA4B,KAAK;AAChD,mBAAe,yBAAyB,KAAK;AAM7C,mBAAe,iBAAiB,KAAK;AACrC,mBAAe,yBAAyB,KAAK;AAG7C,WAAO;AAAA,EACX;AAAA;AAAA,EAGA,kBAAkB,SAAwB;AACtC,SAAK,iBAAiB;AACtB,QAAI,WAAW,CAAC,iCAAa,iBAAiB,GAAG;AAE7C,8CAAe,iBAAwB;AAEvC,uCAAa,MAAM,KAAK,sBAAsB;AAAA,IAClD;AAAA,EACJ;AAAA,EAEA,mBAA4B;AACxB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,yBAAyB,SAAuB;AAC5C,SAAK,yBAAyB,KAAK,IAAI,GAAG,OAAO;AAAA,EACrD;AAAA,EAEA,UAAU,kBAAkC;AACxC,UAAM,YAAY,oBAAoB,KAAK;AAC3C,WAAO,kBAAkB,gBAAgB,SAAS;AAAA,EACtD;AAAA,EAEA,eAAsB;AAClB,WAAO,kBAAkB,aAAa;AAAA,EAC1C;AAAA,EAEA,cAAoB;AAChB,sBAAkB,eAAe;AAAA,EACrC;AAAA,EAEA,aAAa,UAAwB;AACjC,UAAM,OAAO,kBAAkB,mBAAmB;AAClD,UAAM,KAAK,QAAQ,IAAI;AACvB,OAAG,cAAc,UAAU,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,EAC5D;AAAA,EAEA,qBAA0B;AACtB,WAAO,kBAAkB,mBAAmB;AAAA,EAChD;AAAA;AAAA,EAGQ,iBAAiB,OAAkB;AACvC,SAAK,SAAS,OAAO,KAAK;AAC1B,SAAK,oBAAoB,OAAO,KAAK;AAErC,QAAI,OAAO,UAAU,YAAY;AAC7B,WAAK,iBAAiB,OAAO,KAAK;AAAA,IACtC;AAAA,EACJ;AAAA;AAAA,EAGQ,oBAAoB,OAAqB;AAC7C,WAAO,KAAK,SAAS,IAAI,KAAK,MAAM;AAAA,EACxC;AAAA;AAAA,EAGS,uBAAuB,OAAqB;AAChD,WAAO,KAAK,SAAS,IAAI,KAAK,MAAM;AAAA,EACxC;AAAA,EAGO,YAAY,OAAqB;AACrC,UAAM,cAAc,KAAK,eAAe,KAAK;AAE7C,QAAI,CAAC,aAAa;AAEd,aAAO;AAAA,IACX;AAGA,UAAM,UAAU,KAAK,YAAY,KAAK;AAEtC,QAAI,SAAS;AACT,aAAO,gBAAgB,cACjB,KAAK,uBAAuB,IAAI,KAAK,IACrC,KAAK,oBAAoB,IAAI,KAAK;AAAA,IAC5C,OAAO;AACH,aAAO,gBAAgB,cACjB,KAAK,0BAA0B,IAAI,KAAK,IACxC,KAAK,uBAAuB,IAAI,KAAK;AAAA,IAC/C;AAAA,EACJ;AAAA;AAAA,EAGS,YAAY,OAAqB;AACrC,QAAI,KAAK,oBAAoB,KAAK,GAAG;AACjC,aAAO;AAAA,IACX;AAEA,QAAI,OAAO,UAAU,cAAc,MAAM,aAAa,CAAC,KAAK,uBAAuB,KAAK,GAAG;AACtF,iBAAO,6CAAoB,KAAK,MAAM;AAAA,IAC3C;AACA,WAAO;AAAA,EACX;AAAA,EAEO,YAAY,OAAiB;AACjC,UAAM,cAAc,KAAK,eAAe,KAAK;AAE5C,QAAI,CAAC,aAAa;AAEd,cAAQ,MAAM,oEAAoE,OAAO,KAAK,CAAC,EAAE;AACjG,YAAM,IAAI,+CAAwB;AAAA,IACtC;AAED,UAAM,UAAU,KAAK,YAAY,KAAK;AAEtC,QAAI,SAAS;AACT,aAAO,gBAAgB,cACjB,KAAK,uBAAuB,IAAI,KAAK,IACrC,KAAK,oBAAoB,IAAI,KAAK;AAAA,IAC5C,OAAO;AACH,aAAO,gBAAgB,cACjB,KAAK,0BAA0B,IAAI,KAAK,IACxC,KAAK,uBAAuB,IAAI,KAAK;AAAA,IAC/C;AAAA,EACJ;AAAA,EAEQ,YAAY,OAAY,UAAe,aAAiC;AAC5E,UAAM,UAAU,KAAK,YAAY,KAAK;AAEtC,QAAI,SAAS;AACT,UAAI,gBAAgB,aAAa;AAC7B,aAAK,uBAAuB,IAAI,OAAO,QAAQ;AAAA,MACnD,WAAW,eAAe,UAAS;AAC/B,aAAK,oBAAoB,IAAI,OAAO,QAAQ;AAAA,MAChD;AAAA,IACJ,OAAO;AACH,UAAI,gBAAgB,aAAa;AAC7B,aAAK,0BAA0B,IAAI,OAAO,QAAQ;AAAA,MACtD,WAAU,gBAAgB,UAAS;AAC/B,aAAK,uBAAuB,IAAI,OAAO,QAAQ;AAAA,MACnD;AAAA,IACJ;AAAA,EACJ;AAAA,EAEQ,eAAe,OAAyB;AAC5C,QAAI;AACJ,QAAI;AACJ,UAAM,mBAAmB,OAAO,UAAU,cAAc,MAAM;AAG9D,QAAI,KAAK,oBAAoB,KAAK,GAAG;AACjC,qBAAe,KAAK,iBAAiB,IAAI,KAAK,GAAG;AAAA,IACrD,WAAW,KAAK,uBAAuB,KAAK,GAAG;AAC3C,qBAAe,KAAK,oBAAoB,IAAI,KAAK,GAAG,SAAS;AAAA,IACjE;AAGA,QAAI,oBAAoB,CAAC,KAAK,uBAAuB,KAAK,GAAG;AACzD,2BAAiB,kCAAS,KAAK;AAAA,IACnC;AAGA,UAAM,aAAa,gBAAgB,kBAAkB,qBAAO;AAE5D,QAAI,eAAe,qBAAO,WAAW;AACjC,aAAO;AAAA,IACX,WAAW,eAAe,qBAAO,QAAQ;AACrC,aAAO;AAAA,IACX,OAAK;AACD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA,EAGA,MAAgB,aACZ,OACA,SAAgC,CAAC,GACjC,kBAA4B,CAAC,GAC7B,eACY;AAGZ,UAAM,kBAAmB,OAAO,UAAU,cAAc,MAAM,OAAQ,MAAM,OAAO,OAAO,KAAK;AAC/F,QAAI,gBAAgB,SAAS,eAAe,GAAG;AAC3C,cAAQ,MAAM,oDAAoD,CAAC,GAAG,iBAAiB,eAAe,EAAE,KAAK,MAAM,CAAC,EAAE;AACtH,YAAM,IAAI,+CAAwB,CAAC,GAAG,iBAAiB,eAAe,CAAC;AAAA,IAC3E;AACA,UAAM,sBAAsB,CAAC,GAAG,iBAAiB,eAAe;AAIhE,QAAI,iBAAiB,4BAAW;AAC5B,UAAI;AAEA,eAAO,QAAQ,QAAQ,KAAK,sBAAsB,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC;AAAA,MACzE,SAAS,GAAG;AAER,eAAO,QAAQ,OAAO,CAAC;AAAA,MAC3B;AAAA,IACJ;AAKA,QAAI,KAAK,oBAAoB,KAAK,GAAG;AAEjC,aAAO,KAAK,kBAAkB,OAAO,QAAQ,qBAAqB,aAAa;AAAA,IACnF;AACA,QAAI,KAAK,uBAAuB,KAAK,GAAG;AAEpC,aAAO,KAAK,qBAAqB,OAAO,QAAQ,mBAAmB;AAAA,IACvE;AAKA,QAAI,OAAO,UAAU,cAAc,MAAM,WAAW;AAChD,YAAM,uBAAmB,6CAAoB,KAAK;AAClD,UAAI,qBAAqB,MAAM;AAG3B,YAAI,CAAC,KAAK,SAAS,IAAI,KAAK,GAAG;AAC1B,eAAK,SAAS,IAAI,OAAO,mBAAsB;AAAA,QAEpD;AAEA,eAAO,KAAK,kBAAkB,OAAO,QAAQ,qBAAqB,aAAa;AAAA,MACnF;AAAA,IACJ;AAKA,YAAQ,MAAM,mEAAmE,eAAe,EAAE;AAClG,UAAM,IAAI,+CAAwB,eAAe;AAAA,EACrD;AAAA,EAGQ,sBAAsB,OAAkB,QAAoC;AAEhF,UAAM,iBAAiB,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,KAAK,CAAC;AAC3E,QAAI,CAAC,gBAAgB;AAEjB,YAAM,IAAI,8CAAuB,MAAM,SAAS,CAAC;AAAA,IACrD;AAEA,WAAO,eAAe;AAAA,EAC1B;AAAA,EAEQ,kBACJ,iBACA,QACA,iBACA,eACY;AACZ,UAAM,cAAc,KAAK,eAAe,eAAe;AACvD,UAAM,YAAY,gBAAgB,QAAQ;AAG1C,QAAI,eAAe,KAAK,YAAY,eAAe,GAAG;AAClD,YAAM,WAAW,KAAK,YAAY,eAAe;AAEjD,aAAO;AAAA,IACX;AAIA,UAAM,gBAAgB,KAAK,iBAAiB,IAAI,eAAe;AAC/D,QAAI;AAEJ,QAAI,eAAe,SAAS,MAAM,QAAQ,cAAc,KAAK,GAAG;AAC5D,8BAAwB,cAAc;AAAA,IAE1C,OAAO;AAEH,kCAAwB,iDAAwB,eAAe;AAAA,IAEnE;AAIA,QAAI;AACJ,QAAI,KAAK,gBAAgB;AACrB,0BAAgB,oCAAe;AAAA,IACnC;AAIA,UAAM,aAAa,CAAC,GAAG,MAAM;AAC7B,UAAM,qBAAqB,sBAAsB;AAAA,MAAI,0BACjD,KAAK,aAAa,sBAAsB,YAAY,iBAAiB,aAAa;AAAA;AAAA,IACtF;AAEA,QAAI,gBAAgB,QAAQ,IAAI,kBAAkB,EACjD,MAAM,CAAC,UAAQ;AACZ,cAAQ,MAAM,kEAAkE,SAAS,KAAK,KAAK;AAEnG,UAAI,eAAe,KAAK,oBAAoB,eAAe,GAAG;AAC1D,YAAI,gBAAgB,YAAa,MAAK,uBAAuB,OAAO,eAAe;AACnF,YAAI,gBAAgB,SAAU,MAAK,oBAAoB,OAAO,eAAe;AAAA,MACjF;AACA,YAAM;AAAA,IACV,CAAC,EAAE,KAAK,OAAM,yBAAuB;AAGjC,UAAI;AACJ,UAAI,eAAe,CAAC,KAAK,YAAY,eAAe,GAAG;AAEnD,2BAAmB,YAAY;AAC3B,cAAI;AAEA,kBAAM,WAAW,IAAI,gBAAgB,GAAG,oBAAoB;AAG5D,gBAAI,kBAAkB;AACtB,gBAAI,KAAK,kBAAkB,kBAAkB,QAAW;AACpD,oCAAkB,mCAAc,UAAU,WAAW,eAAe,aAAa;AAAA,YACrF;AAGA,iBAAK,YAAY,iBAAiB,iBAAiB,WAAW;AAE9D,mBAAO;AAAA,UACX,SAAS,KAAU;AACf,oBAAQ,MAAM,iDAAiD,SAAS,KAAK,IAAI,OAAO,IAAI,IAAI,KAAK;AAErG,gBAAI,gBAAgB,YAAa,MAAK,uBAAuB,OAAO,eAAe;AACnF,gBAAI,gBAAgB,SAAU,MAAK,oBAAoB,OAAO,eAAe;AAC7E,kBAAM;AAAA,UACV;AAAA,QACJ,GAAG;AAEH,aAAK,YAAY,iBAAiB,iBAAiB,WAAW;AAAA,MAClE,OAAO;AAEF,2BAAmB,YAAY;AAC1B,cAAI;AAEC,kBAAM,WAAW,IAAI,gBAAgB,GAAG,oBAAoB;AAG5D,gBAAI,kBAAkB;AACtB,gBAAI,KAAK,kBAAkB,kBAAkB,QAAW;AACpD,oCAAkB,mCAAc,UAAU,WAAW,eAAe,aAAa;AAAA,YACrF;AAGA,mBAAO;AAAA,UACZ,SAAS,KAAU;AACd,oBAAQ,MAAM,2DAA2D,SAAS,KAAK,IAAI,OAAO,IAAI,IAAI,KAAK;AAC/G,kBAAM;AAAA,UACX;AAAA,QACL,GAAG;AAAA,MACR;AAGA,aAAO,MAAM;AAAA,IACjB,CAAC;AAED,QAAG,eAAe,gBAAgB,aAAY;AAC1C,WAAK,YAAY,iBAAiB,eAAe,WAAW;AAAA,IAChE;AACA,WAAO;AAAA,EACX;AAAA,EAEQ,qBACJ,WACA,QACA,iBACY;AACZ,UAAM,iBAAiB,KAAK,oBAAoB,IAAI,SAAS;AAC7D,UAAM,cAAc,KAAK,eAAe,SAAS;AACjD,UAAM,WAAW,OAAO,SAAS;AAGjC,QAAI,eAAe,KAAK,YAAY,SAAS,GAAG;AAC5C,YAAM,WAAW,KAAK,YAAY,SAAS;AAE3C,aAAO;AAAA,IACX;AAGA,UAAM,WAAW,eAAe;AAChC,UAAM,UAAU,eAAe;AAC/B,UAAM,wBAA+B,SAAS,SAAS,CAAC;AAGxD,UAAM,aAAa,CAAC,GAAG,MAAM;AAC7B,UAAM,qBAAqB,sBAAsB;AAAA,MAAI,0BACjD,KAAK,aAAa,sBAAsB,YAAY,eAAe;AAAA,IACvE;AAEA,QAAI,gBAAgB,QAAQ,IAAI,kBAAkB,EAAE,MAAM,CAAC,UAAQ;AAC/D,cAAQ,MAAM,8DAA8D,QAAQ,KAAK,KAAK;AAE/F,UAAI,eAAe,KAAK,uBAAuB,SAAS,GAAG;AACtD,YAAI,gBAAgB,YAAa,MAAK,0BAA0B,OAAO,SAAS;AAChF,YAAI,gBAAgB,SAAU,MAAK,uBAAuB,OAAO,SAAS;AAAA,MAC/E;AACA,YAAM;AAAA,IACT,CAAC,EAAE,KAAK,OAAM,iBAAe;AACzB,UAAI;AACR,UAAI,eAAe,CAAC,KAAK,YAAY,SAAS,GAAG;AAC5C,2BAAmB,YAAY;AAC3B,cAAI;AAEA,kBAAM,SAAS,MAAM,SAAS,MAAM,MAAM,YAAY;AAEtD,iBAAK,YAAY,WAAW,QAAQ,WAAW;AAE/C,mBAAO;AAAA,UACX,SAAS,KAAU;AACf,oBAAQ,MAAM,2CAA2C,QAAQ,KAAK,IAAI,OAAO,IAAI,IAAI,KAAK;AAE9F,gBAAI,gBAAgB,YAAa,MAAK,0BAA0B,OAAO,SAAS;AAChF,gBAAI,gBAAgB,SAAU,MAAK,uBAAuB,OAAO,SAAS;AAC1E,kBAAM;AAAA,UACV;AAAA,QACJ,GAAG;AAEH,aAAK,YAAY,WAAW,iBAAiB,WAAW;AAAA,MAC7D,OAAO;AAEF,2BAAmB,YAAY;AAC1B,cAAI;AAEA,kBAAM,SAAS,MAAM,SAAS,MAAM,MAAM,YAAY;AAEtD,mBAAO;AAAA,UACX,SAAS,KAAU;AACf,oBAAQ,MAAM,qDAAqD,QAAQ,KAAK,IAAI,OAAO,IAAI,IAAI,KAAK;AACxG,kBAAM;AAAA,UACV;AAAA,QACL,GAAG;AAAA,MACR;AAGA,aAAO,MAAM;AAAA,IACb,CAAC;AAED,QAAG,eAAe,gBAAgB,aAAY;AAC1C,WAAK,YAAY,WAAW,eAAe,WAAW;AAAA,IAC1D;AAEA,WAAO;AAAA,EACX;AACJ;AAGO,SAAS,UAAU,KAA+B;AAErD,SAAO,CAAC,CAAC,OAAO,OAAO,IAAI,SAAS;AACxC;AAEO,SAAS,kBAAsD;AAClE,SAAO,IAAI,UAAU;AACzB;","names":["ContainerRouting"]}
|
|
1
|
+
{"version":3,"sources":["../../../framework/implementation/Container.ts"],"sourcesContent":["import 'reflect-metadata'; // Ensure polyfill is loaded conceptually\nimport type { ContainerOptions, IContainerClient, IContainerFunctionDefinition, IContainerSetup } from \"../interface/Container.cjs\";\nimport { LoadAs } from \"./LoadAs.cjs\";\nimport { Parameter } from \"./Parameter.cjs\";\nimport type { ParameterValue } from \"./Parameter.cjs\";\nimport { NotAClassDefinitionError, ParameterNotFoundError, DependencyNotFoundError, InstanceNotCreatedError, CircularDependencyError } from \"../errors/ContainerErrors.cjs\";\nimport {\n getScope,\n getComponentOptions, // Use helper\n getResolvedDependencies // Use helper\n} from './DecoratorSupport'; // Assume helpers exist or create them\nimport { wrapWithProxy, setTraceLogger, reserveProxyId } from \"./ProxyFactory.cjs\";\nimport * as TraceLoggerModule from \"./TraceLogger.cjs\";\nimport { TraceCleanup } from \"./TraceCleanup.cjs\";\n\n/**\n * A special injection token that resolves to the current scoped container.\n * Use this as a dependency in param arrays to have the container inject itself.\n * This allows provider classes to resolve additional dependencies on demand.\n */\nexport const SCOPED_CONTAINER = Symbol.for(\"ioc:scoped-container\");\n\nenum ContainerRouting {\n FUNCTIONAL = \"FUNCTIONAL\",\n CLASS = \"CLASS\"\n // No need for COMPONENT route, just check metadata if CLASS/FUNCTIONAL fails\n}\n\ntype StorageType = 'singleton' | 'scoped' | 'transient';\n\nexport class Container implements IContainerClient, IContainerSetup {\n // Routing and definition maps\n private _routing: Map<any, ContainerRouting> = new Map();\n private _functionDefinition: Map<any, IContainerFunctionDefinition> = new Map();\n private _classDefinition: Map<Function, Partial<ContainerOptions>> = new Map();\n\n // Storage maps\n private _functionStorageSingleton: Map<any, any> = new Map();\n private _functionStorageScoped: Map<any, any> = new Map();\n private _classStorageSingleton: Map<Function, any> = new Map();\n private _classStorageScoped: Map<Function, any> = new Map();\n\n // Tracing configuration\n private _enableTracing: boolean = false;\n private _traceRetentionMinutes: number = 5;\n\n // Registration methods\n registerClass<T>(classDefinition: new (...args: any[]) => T, options?: Partial<ContainerOptions>): void {\n // Basic validation\n if (typeof classDefinition !== 'function' || !classDefinition.prototype) {\n console.warn(`[IOC] Attempted to register non-class: ${String(classDefinition)}`);\n // Optional: throw error instead?\n // throw new NotAClassDefinitionError(`Attempted to register non-class: ${String(classDefinition)}`);\n return; // Don't proceed if not a class constructor\n }\n\n // Always clear previous definitions for this exact class constructor\n this.clearDefinitions(classDefinition);\n\n // Always set the routing type so 'isClassDefinition' works\n this._routing.set(classDefinition, ContainerRouting.CLASS);\n\n // Store manual options *only if they are actually provided and have content*\n if (options && Object.keys(options).length > 0) {\n this._classDefinition.set(classDefinition, options);\n // console.log(`[IOC RegClass] Manually registered ${classDefinition.name} with options:`, options);\n } else {\n // console.log(`[IOC RegClass] Manually registered ${classDefinition.name} with no specific options (will use decorators if present).`);\n // If no options are provided, we don't store anything in _classDefinition,\n // effectively clearing any previous manual config and letting decorators take over if present.\n }\n }\n\n registerFunction<T extends (...arg: any[]) => any>(label: any, func: T, options: Partial<ContainerOptions> = {} as any): void {\n this.clearDefinitions(label);\n this._routing.set(label, ContainerRouting.FUNCTIONAL);\n this._functionDefinition.set(label, { function: func, options });\n // console.log(`[IOC RegFunc] Registered function with label ${String(label)} and options:`, options);\n }\n\n // Instance resolution methods - Simplify to just call loadInstance\n instance<T, Sync extends boolean = false>(classDefinition: new (...args: any[]) => T, params: ParameterValue<any>[] = []): Sync extends true ? T : Promise<T> | T {\n // Basic check upfront\n if (typeof classDefinition !== 'function' || !classDefinition.prototype) {\n throw new NotAClassDefinitionError(`Cannot resolve instance for non-class: ${String(classDefinition)}`);\n }\n return this.loadInstance(classDefinition, params);\n }\n\n get<T, Sync extends boolean = false>(label: any, param: ParameterValue<any>[] = []): Sync extends true ? T : Promise<T> | T {\n // Just delegate to loadInstance, which handles routing and auto-registration\n return this.loadInstance(label, param);\n }\n\n extend(): IContainerClient & IContainerSetup {\n const childContainer = createContainer() as Container;\n\n // Copy routing and definition maps (share the registration knowledge)\n childContainer._routing = new Map(this._routing);\n childContainer._functionDefinition = new Map(this._functionDefinition);\n childContainer._classDefinition = new Map(this._classDefinition);\n\n // Share singleton storage (singletons are shared across all containers)\n childContainer._functionStorageSingleton = this._functionStorageSingleton;\n childContainer._classStorageSingleton = this._classStorageSingleton;\n\n // Do NOT share scoped storage (new container = new scope)\n // Child gets its own empty scoped storage\n\n // Share tracing configuration\n childContainer._enableTracing = this._enableTracing;\n childContainer._traceRetentionMinutes = this._traceRetentionMinutes;\n\n // console.log('[IOC Extend] Created child container.');\n return childContainer;\n }\n\n // Tracing API\n setTracingEnabled(enabled: boolean): void {\n this._enableTracing = enabled;\n if (enabled && !TraceCleanup.isCleanupRunning()) {\n // Set the trace logger for the ProxyFactory\n setTraceLogger(TraceLoggerModule as any);\n // Start automatic cleanup\n TraceCleanup.start(this._traceRetentionMinutes);\n }\n }\n\n isTracingEnabled(): boolean {\n return this._enableTracing;\n }\n\n setTraceRetentionMinutes(minutes: number): void {\n this._traceRetentionMinutes = Math.max(1, minutes);\n }\n\n getTraces(retentionMinutes?: number): any[] {\n const retention = retentionMinutes ?? this._traceRetentionMinutes;\n return TraceLoggerModule.getRecentTraces(retention);\n }\n\n getAllTraces(): any[] {\n return TraceLoggerModule.getAllTraces();\n }\n\n clearTraces(): void {\n TraceLoggerModule.clearAllTraces();\n }\n\n exportTraces(filepath: string): void {\n const data = TraceLoggerModule.exportTracesToJson();\n const fs = require('fs');\n fs.writeFileSync(filepath, JSON.stringify(data, null, 2));\n }\n\n getTraceStatistics(): any {\n return TraceLoggerModule.getTraceStatistics();\n }\n\n // Private helper methods\n private clearDefinitions(label: any): void {\n this._routing.delete(label);\n this._functionDefinition.delete(label);\n // Only delete from classDefinition if the label is actually a function constructor\n if (typeof label === 'function') {\n this._classDefinition.delete(label);\n }\n }\n\n // Checks if the label is *currently* registered as a class\n private isRegisteredAsClass(label: any): boolean {\n return this._routing.get(label) === ContainerRouting.CLASS;\n }\n\n // Checks if the label is *currently* registered as a function\n private isRegisteredAsFunction(label: any): boolean {\n return this._routing.get(label) === ContainerRouting.FUNCTIONAL;\n }\n\n\n private hasInstance(label: any): boolean {\n const storageType = this.getStorageType(label); // This checks decorators if needed\n\n if (!storageType) {\n // Transient instances are never stored\n return false;\n }\n\n // Determine if it's treated as a class (registered or decorated) *after* getting type\n const isClass = this.isClassType(label); // Use a helper that checks routing OR decorator\n\n if (isClass) {\n return storageType === 'singleton'\n ? this._classStorageSingleton.has(label)\n : this._classStorageScoped.has(label);\n } else { // Must be a function if not a class\n return storageType === 'singleton'\n ? this._functionStorageSingleton.has(label)\n : this._functionStorageScoped.has(label);\n }\n }\n\n // Helper to determine if something should be treated as a class (registered or decorated)\n private isClassType(label: any): boolean {\n if (this.isRegisteredAsClass(label)) {\n return true;\n }\n // If not explicitly registered as a class, check if it's a function with @Component\n if (typeof label === 'function' && label.prototype && !this.isRegisteredAsFunction(label)) {\n return getComponentOptions(label) !== null;\n }\n return false;\n }\n\n private getInstance(label: any): any {\n const storageType = this.getStorageType(label); // Checks decorators if needed\n\n if (!storageType) {\n // This should ideally not be reached if called after hasInstance check\n console.error(`[IOC GetInstance] Attempted to get instance for non-stored type: ${String(label)}`);\n throw new InstanceNotCreatedError();\n }\n\n const isClass = this.isClassType(label); // Check routing OR decorator\n\n if (isClass) {\n return storageType === 'singleton'\n ? this._classStorageSingleton.get(label)\n : this._classStorageScoped.get(label);\n } else { // Must be a function\n return storageType === 'singleton'\n ? this._functionStorageSingleton.get(label)\n : this._functionStorageScoped.get(label);\n }\n }\n\n private setInstance(label: any, instance: any, storageType?: StorageType): void { // Made storageType non-optional\n const isClass = this.isClassType(label); // Determine type based on routing OR decorator\n\n if (isClass) {\n if (storageType === 'singleton') {\n this._classStorageSingleton.set(label, instance);\n } else if (storageType == 'scoped'){ // storageType === 'scoped'\n this._classStorageScoped.set(label, instance);\n }\n } else { // Must be a function\n if (storageType === 'singleton') {\n this._functionStorageSingleton.set(label, instance);\n } else if(storageType === \"scoped\"){ // storageType === 'scoped'\n this._functionStorageScoped.set(label, instance);\n }\n }\n }\n\n private getStorageType(label: any): StorageType {\n let manualLoadAs: LoadAs | undefined;\n let decoratorScope: LoadAs | undefined;\n const isPotentialClass = typeof label === 'function' && label.prototype;\n\n // Get manual registration options if available\n if (this.isRegisteredAsClass(label)) { // Use helper\n manualLoadAs = this._classDefinition.get(label)?.loadAs;\n } else if (this.isRegisteredAsFunction(label)) { // Use helper\n manualLoadAs = this._functionDefinition.get(label)?.options?.loadAs;\n }\n\n // Get decorator scope only if it's potentially a class *and not explicitly registered as a function*\n if (isPotentialClass && !this.isRegisteredAsFunction(label)) {\n decoratorScope = getScope(label); // Uses getComponentOptions internally\n }\n\n // Determine final scope: Manual > Decorator > Default (Transient)\n const finalScope = manualLoadAs ?? decoratorScope ?? LoadAs.Transient;\n\n if (finalScope === LoadAs.Singleton) {\n return 'singleton';\n } else if (finalScope === LoadAs.Scoped) {\n return 'scoped';\n }else{\n return 'transient'; // Transient\n }\n }\n\n // Central resolution logic - sync-first, returns T or Promise<T>\n protected loadInstance(\n label: any,\n params: ParameterValue<any>[] = [],\n resolutionChain: string[] = [], // Track resolution path\n parentProxyId?: number // For proxy hierarchy tracking\n ): any {\n\n // --- Circular Dependency Check ---\n const currentLabelStr = (typeof label === 'function' && label.name) ? label.name : String(label);\n if (resolutionChain.includes(currentLabelStr)) {\n console.error(`[IOC LoadInstance] Circular dependency detected: ${[...resolutionChain, currentLabelStr].join(' -> ')}`);\n throw new CircularDependencyError([...resolutionChain, currentLabelStr]);\n }\n const nextResolutionChain = [...resolutionChain, currentLabelStr];\n // --- End Circular Dependency Check ---\n\n // --- Handle Parameters ---\n if (label instanceof Parameter) {\n try {\n // Pass a *copy* of params to avoid side effects in resolveParameterValue\n return this.resolveParameterValue(label, [...params]);\n } catch (e) {\n // console.error(`[IOC LoadInstance] Error resolving parameter ${param.toString()}:`, e);\n throw e;\n }\n }\n // --- End Handle Parameters ---\n\n // --- Handle Scoped Container Injection ---\n if (label === SCOPED_CONTAINER) {\n return this;\n }\n // --- End Handle Scoped Container Injection ---\n\n // --- Check Explicit Registrations ---\n if (this.isRegisteredAsClass(label)) {\n // console.log(`[IOC LoadInstance] Resolving explicitly registered class: ${currentLabelStr}`);\n return this.loadClassInstance(label, params, nextResolutionChain, parentProxyId);\n }\n if (this.isRegisteredAsFunction(label)) {\n // console.log(`[IOC LoadInstance] Resolving explicitly registered function: ${currentLabelStr}`);\n return this.loadFunctionInstance(label, params, nextResolutionChain);\n }\n // --- End Check Explicit Registrations ---\n\n\n // --- Attempt Auto-Registration/Resolution for Decorated Classes ---\n if (typeof label === 'function' && label.prototype) {\n const componentOptions = getComponentOptions(label); // Check for @Component\n if (componentOptions !== null) {\n // console.log(`[IOC LoadInstance] Auto-resolving @Component class: ${currentLabelStr}`);\n // Set routing *now* so subsequent internal checks work correctly\n if (!this._routing.has(label)) { // Only set if not already set\n this._routing.set(label, ContainerRouting.CLASS);\n // console.log(`[IOC LoadInstance] Set routing for auto-resolved class: ${currentLabelStr}`);\n }\n // Proceed to load it as a class\n return this.loadClassInstance(label, params, nextResolutionChain, parentProxyId);\n }\n }\n // --- End Auto-Registration ---\n\n\n // --- Dependency Not Found ---\n console.error(`[IOC LoadInstance] Dependency not found and cannot be resolved: ${currentLabelStr}`);\n throw new DependencyNotFoundError(currentLabelStr);\n }\n\n\n private resolveParameterValue(param: Parameter, params: ParameterValue<any>[]): any { // No mutation\n // Find the *last* provided value for the parameter\n const valueContainer = [...params].reverse().find((p) => p.belongsTo(param));\n if (!valueContainer) {\n // console.error(`[IOC ResolveParam] Parameter not found: ${param.toString()}`);\n throw new ParameterNotFoundError(param.toString());\n }\n // console.log(`[IOC ResolveParam] Resolved parameter ${param.toString()}`);\n return valueContainer.value;\n }\n\n private loadClassInstance(\n classDefinition: any, // Should be a class constructor here\n params: ParameterValue<any>[],\n resolutionChain: string[],\n parentProxyId?: number\n ): any {\n const storageType = this.getStorageType(classDefinition);\n const className = classDefinition.name || '[Anonymous Class]';\n\n // Check storage first (may be sync value or Promise)\n if (storageType && this.hasInstance(classDefinition)) {\n const instance = this.getInstance(classDefinition);\n // console.log(`[IOC LoadClass] Found existing ${storageType} instance for ${className}. IsPromise: ${isPromise(instance)}`);\n return instance;\n }\n // console.log(`[IOC LoadClass] Creating new ${storageType || 'transient'} instance for ${className}`);\n\n // --- Determine Dependencies ---\n const manualOptions = this._classDefinition.get(classDefinition) as ContainerOptions | undefined;\n let dependenciesToResolve: any[];\n\n if (manualOptions?.param && Array.isArray(manualOptions.param)) {\n dependenciesToResolve = manualOptions.param;\n // console.log(`[IOC LoadClass] Using manual dependencies for ${className}`);\n } else {\n // Use decorator-derived dependencies\n dependenciesToResolve = getResolvedDependencies(classDefinition);\n // console.log(`[IOC LoadClass] Using decorator/reflected dependencies for ${className}:`, dependenciesToResolve.map(d => typeof d === 'function' ? d.name : String(d)));\n }\n // --- End Determine Dependencies ---\n\n // Reserve a proxy ID if tracing is enabled\n let futureProxyId: number | undefined;\n if (this._enableTracing) {\n futureProxyId = reserveProxyId();\n }\n\n // --- Resolve Dependencies (sync-first) ---\n const paramsCopy = [...params];\n const resolvedDependencies: any[] = [];\n let hasAsyncDependency = false;\n\n // Resolve each dependency and check if any return Promises\n for (const dependencyIdentifier of dependenciesToResolve) {\n const resolved = this.loadInstance(dependencyIdentifier, paramsCopy, resolutionChain, futureProxyId);\n resolvedDependencies.push(resolved);\n if (isPromise(resolved)) {\n hasAsyncDependency = true;\n }\n }\n\n // Helper to instantiate the class\n const instantiate = (deps: any[]): any => {\n try {\n const instance = new classDefinition(...deps);\n\n // Wrap with proxy if tracing is enabled\n if (this._enableTracing && futureProxyId !== undefined) {\n return wrapWithProxy(instance, className, parentProxyId, futureProxyId);\n }\n return instance;\n } catch (err: any) {\n console.error(`[IOC LoadClass] Error during instantiation of ${className}: ${err.message}`, err.stack);\n throw err;\n }\n };\n\n // --- Sync Path: All dependencies resolved synchronously ---\n if (!hasAsyncDependency) {\n const instance = instantiate(resolvedDependencies);\n\n // Store if singleton/scoped\n if (storageType && storageType !== 'transient') {\n this.setInstance(classDefinition, instance, storageType);\n }\n return instance;\n }\n\n // --- Async Path: At least one dependency is a Promise ---\n const asyncInstance = Promise.all(resolvedDependencies)\n .then((deps) => {\n const instance = instantiate(deps);\n\n // Store if singleton/scoped (overwrite the promise with the instance)\n if (storageType && storageType !== 'transient') {\n this.setInstance(classDefinition, instance, storageType);\n }\n return instance;\n })\n .catch((error) => {\n console.error(`[IOC LoadClass] Failed to resolve one or more dependencies for ${className}:`, error);\n // Clean up stored promise on failure\n if (storageType && this.isRegisteredAsClass(classDefinition)) {\n if (storageType === 'singleton') this._classStorageSingleton.delete(classDefinition);\n if (storageType === 'scoped') this._classStorageScoped.delete(classDefinition);\n }\n throw error;\n });\n\n // Store the promise for singleton/scoped to handle concurrent requests\n if (storageType && storageType !== 'transient') {\n this.setInstance(classDefinition, asyncInstance, storageType);\n }\n\n return asyncInstance;\n }\n\n private loadFunctionInstance(\n funcLabel: any,\n params: ParameterValue<any>[],\n resolutionChain: string[]\n ): Promise<any> { // Always return Promise<any> since this is an async function\n const functionConfig = this._functionDefinition.get(funcLabel)!; // Assumed to exist by caller\n const storageType = this.getStorageType(funcLabel); // Only uses manual options for functions\n const labelStr = String(funcLabel);\n\n // Check storage first\n if (storageType && this.hasInstance(funcLabel)) {\n const instance = this.getInstance(funcLabel);\n // console.log(`[IOC LoadFunc] Found existing ${storageType} instance for ${labelStr}. IsPromise: ${isPromise(instance)}`);\n return instance;\n }\n // console.log(`[IOC LoadFunc] Creating new ${storageType || 'transient'} instance for ${labelStr}`);\n\n const ioc_func = functionConfig.function;\n const options = functionConfig.options;\n const dependenciesToResolve: any[] = options?.param || [];\n\n // --- Resolve Dependencies ---\n const paramsCopy = [...params]; // Create a copy\n const resolutionPromises = dependenciesToResolve.map(dependencyIdentifier =>\n this.loadInstance(dependencyIdentifier, paramsCopy, resolutionChain)\n );\n\n let finalInstance = Promise.all(resolutionPromises).catch((error)=>{\n console.error(`[IOC LoadFunc] Failed to resolve dependencies for function ${labelStr}:`, error);\n // Clean up potential partial storage\n if (storageType && this.isRegisteredAsFunction(funcLabel)) {\n if (storageType === 'singleton') this._functionStorageSingleton.delete(funcLabel);\n if (storageType === 'scoped') this._functionStorageScoped.delete(funcLabel);\n }\n throw error;\n }).then(async(resolvedArgs)=>{\n let instancePromise: Promise<any> | undefined;\n if (storageType && !this.hasInstance(funcLabel)) {\n instancePromise = (async () => {\n try {\n // console.log(`[IOC LoadFunc] Invoking ${labelStr} with ${resolvedArgs.length} args.`);\n const result = await ioc_func.apply(null, resolvedArgs); // Await in case function is async\n // Overwrite stored promise with actual result\n this.setInstance(funcLabel, result, storageType);\n // console.log(`[IOC LoadFunc] Stored actual ${storageType} instance for ${labelStr}`);\n return result;\n } catch (err: any) {\n console.error(`[IOC LoadFunc] Error executing function ${labelStr}: ${err.message}`, err.stack);\n // Clean up stored promise on failure\n if (storageType === 'singleton') this._functionStorageSingleton.delete(funcLabel);\n if (storageType === 'scoped') this._functionStorageScoped.delete(funcLabel);\n throw err;\n }\n })();\n // console.log(`[IOC LoadFunc] Storing promise for concurrent requests (${storageType}) for ${labelStr}`);\n this.setInstance(funcLabel, instancePromise, storageType);\n } else {\n // Transient or already resolved from storage check\n instancePromise = (async () => {\n try {\n // console.log(`[IOC LoadFunc] Invoking transient ${labelStr} with ${resolvedArgs.length} args.`);\n const result = await ioc_func.apply(null, resolvedArgs); // Await in case function is async\n // No storing for transient\n return result;\n } catch (err: any) {\n console.error(`[IOC LoadFunc] Error executing transient function ${labelStr}: ${err.message}`, err.stack);\n throw err;\n }\n })();\n }\n // --- End Invoke Function ---\n\n return await instancePromise; // Return the final (awaited) result\n });\n\n if(storageType && storageType !== 'transient'){\n this.setInstance(funcLabel, finalInstance, storageType); // Store the promise\n }\n\n return finalInstance;\n }\n}\n\n// Helper functions\nexport function isPromise(obj: any): obj is Promise<any> {\n // Simplified check - more robust check might be needed depending on environment\n return !!obj && typeof obj.then === 'function';\n}\n\nexport function createContainer(): IContainerClient & IContainerSetup {\n return new Container();\n}\n"],"mappings":"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","names":["ContainerRouting"]}
|
|
@@ -2,6 +2,12 @@ import { IContainerClient, IContainerSetup, ContainerOptions } from '../interfac
|
|
|
2
2
|
import { ParameterValue } from './Parameter.cjs';
|
|
3
3
|
import './LoadAs.cjs';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* A special injection token that resolves to the current scoped container.
|
|
7
|
+
* Use this as a dependency in param arrays to have the container inject itself.
|
|
8
|
+
* This allows provider classes to resolve additional dependencies on demand.
|
|
9
|
+
*/
|
|
10
|
+
declare const SCOPED_CONTAINER: unique symbol;
|
|
5
11
|
declare class Container implements IContainerClient, IContainerSetup {
|
|
6
12
|
private _routing;
|
|
7
13
|
private _functionDefinition;
|
|
@@ -14,8 +20,8 @@ declare class Container implements IContainerClient, IContainerSetup {
|
|
|
14
20
|
private _traceRetentionMinutes;
|
|
15
21
|
registerClass<T>(classDefinition: new (...args: any[]) => T, options?: Partial<ContainerOptions>): void;
|
|
16
22
|
registerFunction<T extends (...arg: any[]) => any>(label: any, func: T, options?: Partial<ContainerOptions>): void;
|
|
17
|
-
instance<T,
|
|
18
|
-
get<T>(label: any, param?: ParameterValue<any>[]): Promise<T> | T;
|
|
23
|
+
instance<T, Sync extends boolean = false>(classDefinition: new (...args: any[]) => T, params?: ParameterValue<any>[]): Sync extends true ? T : Promise<T> | T;
|
|
24
|
+
get<T, Sync extends boolean = false>(label: any, param?: ParameterValue<any>[]): Sync extends true ? T : Promise<T> | T;
|
|
19
25
|
extend(): IContainerClient & IContainerSetup;
|
|
20
26
|
setTracingEnabled(enabled: boolean): void;
|
|
21
27
|
isTracingEnabled(): boolean;
|
|
@@ -34,7 +40,7 @@ declare class Container implements IContainerClient, IContainerSetup {
|
|
|
34
40
|
private setInstance;
|
|
35
41
|
private getStorageType;
|
|
36
42
|
protected loadInstance(label: any, params?: ParameterValue<any>[], resolutionChain?: string[], // Track resolution path
|
|
37
|
-
parentProxyId?: number):
|
|
43
|
+
parentProxyId?: number): any;
|
|
38
44
|
private resolveParameterValue;
|
|
39
45
|
private loadClassInstance;
|
|
40
46
|
private loadFunctionInstance;
|
|
@@ -42,4 +48,4 @@ declare class Container implements IContainerClient, IContainerSetup {
|
|
|
42
48
|
declare function isPromise(obj: any): obj is Promise<any>;
|
|
43
49
|
declare function createContainer(): IContainerClient & IContainerSetup;
|
|
44
50
|
|
|
45
|
-
export { Container, createContainer, isPromise };
|
|
51
|
+
export { Container, SCOPED_CONTAINER, createContainer, isPromise };
|
|
@@ -2,6 +2,12 @@ import { IContainerClient, IContainerSetup, ContainerOptions } from '../interfac
|
|
|
2
2
|
import { ParameterValue } from './Parameter.js';
|
|
3
3
|
import './LoadAs.js';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* A special injection token that resolves to the current scoped container.
|
|
7
|
+
* Use this as a dependency in param arrays to have the container inject itself.
|
|
8
|
+
* This allows provider classes to resolve additional dependencies on demand.
|
|
9
|
+
*/
|
|
10
|
+
declare const SCOPED_CONTAINER: unique symbol;
|
|
5
11
|
declare class Container implements IContainerClient, IContainerSetup {
|
|
6
12
|
private _routing;
|
|
7
13
|
private _functionDefinition;
|
|
@@ -14,8 +20,8 @@ declare class Container implements IContainerClient, IContainerSetup {
|
|
|
14
20
|
private _traceRetentionMinutes;
|
|
15
21
|
registerClass<T>(classDefinition: new (...args: any[]) => T, options?: Partial<ContainerOptions>): void;
|
|
16
22
|
registerFunction<T extends (...arg: any[]) => any>(label: any, func: T, options?: Partial<ContainerOptions>): void;
|
|
17
|
-
instance<T,
|
|
18
|
-
get<T>(label: any, param?: ParameterValue<any>[]): Promise<T> | T;
|
|
23
|
+
instance<T, Sync extends boolean = false>(classDefinition: new (...args: any[]) => T, params?: ParameterValue<any>[]): Sync extends true ? T : Promise<T> | T;
|
|
24
|
+
get<T, Sync extends boolean = false>(label: any, param?: ParameterValue<any>[]): Sync extends true ? T : Promise<T> | T;
|
|
19
25
|
extend(): IContainerClient & IContainerSetup;
|
|
20
26
|
setTracingEnabled(enabled: boolean): void;
|
|
21
27
|
isTracingEnabled(): boolean;
|
|
@@ -34,7 +40,7 @@ declare class Container implements IContainerClient, IContainerSetup {
|
|
|
34
40
|
private setInstance;
|
|
35
41
|
private getStorageType;
|
|
36
42
|
protected loadInstance(label: any, params?: ParameterValue<any>[], resolutionChain?: string[], // Track resolution path
|
|
37
|
-
parentProxyId?: number):
|
|
43
|
+
parentProxyId?: number): any;
|
|
38
44
|
private resolveParameterValue;
|
|
39
45
|
private loadClassInstance;
|
|
40
46
|
private loadFunctionInstance;
|
|
@@ -42,4 +48,4 @@ declare class Container implements IContainerClient, IContainerSetup {
|
|
|
42
48
|
declare function isPromise(obj: any): obj is Promise<any>;
|
|
43
49
|
declare function createContainer(): IContainerClient & IContainerSetup;
|
|
44
50
|
|
|
45
|
-
export { Container, createContainer, isPromise };
|
|
51
|
+
export { Container, SCOPED_CONTAINER, createContainer, isPromise };
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
import { wrapWithProxy, setTraceLogger, reserveProxyId } from "./ProxyFactory.js";
|
|
11
11
|
import * as TraceLoggerModule from "./TraceLogger.js";
|
|
12
12
|
import { TraceCleanup } from "./TraceCleanup.js";
|
|
13
|
+
const SCOPED_CONTAINER = Symbol.for("ioc:scoped-container");
|
|
13
14
|
var ContainerRouting = /* @__PURE__ */ ((ContainerRouting2) => {
|
|
14
15
|
ContainerRouting2["FUNCTIONAL"] = "FUNCTIONAL";
|
|
15
16
|
ContainerRouting2["CLASS"] = "CLASS";
|
|
@@ -189,8 +190,8 @@ class Container {
|
|
|
189
190
|
return "transient";
|
|
190
191
|
}
|
|
191
192
|
}
|
|
192
|
-
// Central resolution logic
|
|
193
|
-
|
|
193
|
+
// Central resolution logic - sync-first, returns T or Promise<T>
|
|
194
|
+
loadInstance(label, params = [], resolutionChain = [], parentProxyId) {
|
|
194
195
|
const currentLabelStr = typeof label === "function" && label.name ? label.name : String(label);
|
|
195
196
|
if (resolutionChain.includes(currentLabelStr)) {
|
|
196
197
|
console.error(`[IOC LoadInstance] Circular dependency detected: ${[...resolutionChain, currentLabelStr].join(" -> ")}`);
|
|
@@ -199,11 +200,14 @@ class Container {
|
|
|
199
200
|
const nextResolutionChain = [...resolutionChain, currentLabelStr];
|
|
200
201
|
if (label instanceof Parameter) {
|
|
201
202
|
try {
|
|
202
|
-
return
|
|
203
|
+
return this.resolveParameterValue(label, [...params]);
|
|
203
204
|
} catch (e) {
|
|
204
|
-
|
|
205
|
+
throw e;
|
|
205
206
|
}
|
|
206
207
|
}
|
|
208
|
+
if (label === SCOPED_CONTAINER) {
|
|
209
|
+
return this;
|
|
210
|
+
}
|
|
207
211
|
if (this.isRegisteredAsClass(label)) {
|
|
208
212
|
return this.loadClassInstance(label, params, nextResolutionChain, parentProxyId);
|
|
209
213
|
}
|
|
@@ -248,58 +252,52 @@ class Container {
|
|
|
248
252
|
futureProxyId = reserveProxyId();
|
|
249
253
|
}
|
|
250
254
|
const paramsCopy = [...params];
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
255
|
+
const resolvedDependencies = [];
|
|
256
|
+
let hasAsyncDependency = false;
|
|
257
|
+
for (const dependencyIdentifier of dependenciesToResolve) {
|
|
258
|
+
const resolved = this.loadInstance(dependencyIdentifier, paramsCopy, resolutionChain, futureProxyId);
|
|
259
|
+
resolvedDependencies.push(resolved);
|
|
260
|
+
if (isPromise(resolved)) {
|
|
261
|
+
hasAsyncDependency = true;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
const instantiate = (deps) => {
|
|
265
|
+
try {
|
|
266
|
+
const instance = new classDefinition(...deps);
|
|
267
|
+
if (this._enableTracing && futureProxyId !== void 0) {
|
|
268
|
+
return wrapWithProxy(instance, className, parentProxyId, futureProxyId);
|
|
269
|
+
}
|
|
270
|
+
return instance;
|
|
271
|
+
} catch (err) {
|
|
272
|
+
console.error(`[IOC LoadClass] Error during instantiation of ${className}: ${err.message}`, err.stack);
|
|
273
|
+
throw err;
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
if (!hasAsyncDependency) {
|
|
277
|
+
const instance = instantiate(resolvedDependencies);
|
|
278
|
+
if (storageType && storageType !== "transient") {
|
|
279
|
+
this.setInstance(classDefinition, instance, storageType);
|
|
280
|
+
}
|
|
281
|
+
return instance;
|
|
282
|
+
}
|
|
283
|
+
const asyncInstance = Promise.all(resolvedDependencies).then((deps) => {
|
|
284
|
+
const instance = instantiate(deps);
|
|
285
|
+
if (storageType && storageType !== "transient") {
|
|
286
|
+
this.setInstance(classDefinition, instance, storageType);
|
|
287
|
+
}
|
|
288
|
+
return instance;
|
|
289
|
+
}).catch((error) => {
|
|
256
290
|
console.error(`[IOC LoadClass] Failed to resolve one or more dependencies for ${className}:`, error);
|
|
257
291
|
if (storageType && this.isRegisteredAsClass(classDefinition)) {
|
|
258
292
|
if (storageType === "singleton") this._classStorageSingleton.delete(classDefinition);
|
|
259
293
|
if (storageType === "scoped") this._classStorageScoped.delete(classDefinition);
|
|
260
294
|
}
|
|
261
295
|
throw error;
|
|
262
|
-
}).then(async (resolvedDependencies) => {
|
|
263
|
-
let instancePromise;
|
|
264
|
-
if (storageType && !this.hasInstance(classDefinition)) {
|
|
265
|
-
instancePromise = (async () => {
|
|
266
|
-
try {
|
|
267
|
-
const instance = new classDefinition(...resolvedDependencies);
|
|
268
|
-
let wrappedInstance = instance;
|
|
269
|
-
if (this._enableTracing && futureProxyId !== void 0) {
|
|
270
|
-
wrappedInstance = wrapWithProxy(instance, className, parentProxyId, futureProxyId);
|
|
271
|
-
}
|
|
272
|
-
this.setInstance(classDefinition, wrappedInstance, storageType);
|
|
273
|
-
return wrappedInstance;
|
|
274
|
-
} catch (err) {
|
|
275
|
-
console.error(`[IOC LoadClass] Error during instantiation of ${className}: ${err.message}`, err.stack);
|
|
276
|
-
if (storageType === "singleton") this._classStorageSingleton.delete(classDefinition);
|
|
277
|
-
if (storageType === "scoped") this._classStorageScoped.delete(classDefinition);
|
|
278
|
-
throw err;
|
|
279
|
-
}
|
|
280
|
-
})();
|
|
281
|
-
this.setInstance(classDefinition, instancePromise, storageType);
|
|
282
|
-
} else {
|
|
283
|
-
instancePromise = (async () => {
|
|
284
|
-
try {
|
|
285
|
-
const instance = new classDefinition(...resolvedDependencies);
|
|
286
|
-
let wrappedInstance = instance;
|
|
287
|
-
if (this._enableTracing && futureProxyId !== void 0) {
|
|
288
|
-
wrappedInstance = wrapWithProxy(instance, className, parentProxyId, futureProxyId);
|
|
289
|
-
}
|
|
290
|
-
return wrappedInstance;
|
|
291
|
-
} catch (err) {
|
|
292
|
-
console.error(`[IOC LoadClass] Error during instantiation of transient ${className}: ${err.message}`, err.stack);
|
|
293
|
-
throw err;
|
|
294
|
-
}
|
|
295
|
-
})();
|
|
296
|
-
}
|
|
297
|
-
return await instancePromise;
|
|
298
296
|
});
|
|
299
297
|
if (storageType && storageType !== "transient") {
|
|
300
|
-
this.setInstance(classDefinition,
|
|
298
|
+
this.setInstance(classDefinition, asyncInstance, storageType);
|
|
301
299
|
}
|
|
302
|
-
return
|
|
300
|
+
return asyncInstance;
|
|
303
301
|
}
|
|
304
302
|
loadFunctionInstance(funcLabel, params, resolutionChain) {
|
|
305
303
|
const functionConfig = this._functionDefinition.get(funcLabel);
|
|
@@ -366,6 +364,7 @@ function createContainer() {
|
|
|
366
364
|
}
|
|
367
365
|
export {
|
|
368
366
|
Container,
|
|
367
|
+
SCOPED_CONTAINER,
|
|
369
368
|
createContainer,
|
|
370
369
|
isPromise
|
|
371
370
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../framework/implementation/Container.ts"],"sourcesContent":["import 'reflect-metadata'; // Ensure polyfill is loaded conceptually\nimport type { ContainerOptions, IContainerClient, IContainerFunctionDefinition, IContainerSetup } from \"../interface/Container.js\";\nimport { LoadAs } from \"./LoadAs.js\";\nimport { Parameter } from \"./Parameter.js\";\nimport type { ParameterValue } from \"./Parameter.js\";\nimport { NotAClassDefinitionError, ParameterNotFoundError, DependencyNotFoundError, InstanceNotCreatedError, CircularDependencyError } from \"../errors/ContainerErrors.js\";\nimport {\n getScope,\n getComponentOptions, // Use helper\n getResolvedDependencies // Use helper\n} from './DecoratorSupport'; // Assume helpers exist or create them\nimport { wrapWithProxy, setTraceLogger, reserveProxyId } from \"./ProxyFactory.js\";\nimport * as TraceLoggerModule from \"./TraceLogger.js\";\nimport { TraceCleanup } from \"./TraceCleanup.js\";\n\nenum ContainerRouting {\n FUNCTIONAL = \"FUNCTIONAL\",\n CLASS = \"CLASS\"\n // No need for COMPONENT route, just check metadata if CLASS/FUNCTIONAL fails\n}\n\ntype StorageType = 'singleton' | 'scoped' | 'transient';\n\nexport class Container implements IContainerClient, IContainerSetup {\n // Routing and definition maps\n private _routing: Map<any, ContainerRouting> = new Map();\n private _functionDefinition: Map<any, IContainerFunctionDefinition> = new Map();\n private _classDefinition: Map<Function, Partial<ContainerOptions>> = new Map();\n\n // Storage maps\n private _functionStorageSingleton: Map<any, any> = new Map();\n private _functionStorageScoped: Map<any, any> = new Map();\n private _classStorageSingleton: Map<Function, any> = new Map();\n private _classStorageScoped: Map<Function, any> = new Map();\n\n // Tracing configuration\n private _enableTracing: boolean = false;\n private _traceRetentionMinutes: number = 5;\n\n // Registration methods\n registerClass<T>(classDefinition: new (...args: any[]) => T, options?: Partial<ContainerOptions>): void {\n // Basic validation\n if (typeof classDefinition !== 'function' || !classDefinition.prototype) {\n console.warn(`[IOC] Attempted to register non-class: ${String(classDefinition)}`);\n // Optional: throw error instead?\n // throw new NotAClassDefinitionError(`Attempted to register non-class: ${String(classDefinition)}`);\n return; // Don't proceed if not a class constructor\n }\n\n // Always clear previous definitions for this exact class constructor\n this.clearDefinitions(classDefinition);\n\n // Always set the routing type so 'isClassDefinition' works\n this._routing.set(classDefinition, ContainerRouting.CLASS);\n\n // Store manual options *only if they are actually provided and have content*\n if (options && Object.keys(options).length > 0) {\n this._classDefinition.set(classDefinition, options);\n // console.log(`[IOC RegClass] Manually registered ${classDefinition.name} with options:`, options);\n } else {\n // console.log(`[IOC RegClass] Manually registered ${classDefinition.name} with no specific options (will use decorators if present).`);\n // If no options are provided, we don't store anything in _classDefinition,\n // effectively clearing any previous manual config and letting decorators take over if present.\n }\n }\n\n registerFunction<T extends (...arg: any[]) => any>(label: any, func: T, options: Partial<ContainerOptions> = {} as any): void {\n this.clearDefinitions(label);\n this._routing.set(label, ContainerRouting.FUNCTIONAL);\n this._functionDefinition.set(label, { function: func, options });\n // console.log(`[IOC RegFunc] Registered function with label ${String(label)} and options:`, options);\n }\n\n // Instance resolution methods - Simplify to just call loadInstance\n instance<T, Args extends any[]>(classDefinition: new (...args: Args) => T, params: ParameterValue<any>[] = []): Promise<T> {\n // Basic check upfront\n if (typeof classDefinition !== 'function' || !classDefinition.prototype) {\n throw new NotAClassDefinitionError(`Cannot resolve instance for non-class: ${String(classDefinition)}`);\n }\n return this.loadInstance(classDefinition, params) as Promise<T>;\n }\n\n get<T>(label: any, param: ParameterValue<any>[] = []): Promise<T> | T {\n // Just delegate to loadInstance, which handles routing and auto-registration\n return this.loadInstance(label, param);\n }\n\n extend(): IContainerClient & IContainerSetup {\n const childContainer = createContainer() as Container;\n\n // Copy routing and definition maps (share the registration knowledge)\n childContainer._routing = new Map(this._routing);\n childContainer._functionDefinition = new Map(this._functionDefinition);\n childContainer._classDefinition = new Map(this._classDefinition);\n\n // Share singleton storage (singletons are shared across all containers)\n childContainer._functionStorageSingleton = this._functionStorageSingleton;\n childContainer._classStorageSingleton = this._classStorageSingleton;\n\n // Do NOT share scoped storage (new container = new scope)\n // Child gets its own empty scoped storage\n\n // Share tracing configuration\n childContainer._enableTracing = this._enableTracing;\n childContainer._traceRetentionMinutes = this._traceRetentionMinutes;\n\n // console.log('[IOC Extend] Created child container.');\n return childContainer;\n }\n\n // Tracing API\n setTracingEnabled(enabled: boolean): void {\n this._enableTracing = enabled;\n if (enabled && !TraceCleanup.isCleanupRunning()) {\n // Set the trace logger for the ProxyFactory\n setTraceLogger(TraceLoggerModule as any);\n // Start automatic cleanup\n TraceCleanup.start(this._traceRetentionMinutes);\n }\n }\n\n isTracingEnabled(): boolean {\n return this._enableTracing;\n }\n\n setTraceRetentionMinutes(minutes: number): void {\n this._traceRetentionMinutes = Math.max(1, minutes);\n }\n\n getTraces(retentionMinutes?: number): any[] {\n const retention = retentionMinutes ?? this._traceRetentionMinutes;\n return TraceLoggerModule.getRecentTraces(retention);\n }\n\n getAllTraces(): any[] {\n return TraceLoggerModule.getAllTraces();\n }\n\n clearTraces(): void {\n TraceLoggerModule.clearAllTraces();\n }\n\n exportTraces(filepath: string): void {\n const data = TraceLoggerModule.exportTracesToJson();\n const fs = require('fs');\n fs.writeFileSync(filepath, JSON.stringify(data, null, 2));\n }\n\n getTraceStatistics(): any {\n return TraceLoggerModule.getTraceStatistics();\n }\n\n // Private helper methods\n private clearDefinitions(label: any): void {\n this._routing.delete(label);\n this._functionDefinition.delete(label);\n // Only delete from classDefinition if the label is actually a function constructor\n if (typeof label === 'function') {\n this._classDefinition.delete(label);\n }\n }\n\n // Checks if the label is *currently* registered as a class\n private isRegisteredAsClass(label: any): boolean {\n return this._routing.get(label) === ContainerRouting.CLASS;\n }\n\n // Checks if the label is *currently* registered as a function\n private isRegisteredAsFunction(label: any): boolean {\n return this._routing.get(label) === ContainerRouting.FUNCTIONAL;\n }\n\n\n private hasInstance(label: any): boolean {\n const storageType = this.getStorageType(label); // This checks decorators if needed\n\n if (!storageType) {\n // Transient instances are never stored\n return false;\n }\n\n // Determine if it's treated as a class (registered or decorated) *after* getting type\n const isClass = this.isClassType(label); // Use a helper that checks routing OR decorator\n\n if (isClass) {\n return storageType === 'singleton'\n ? this._classStorageSingleton.has(label)\n : this._classStorageScoped.has(label);\n } else { // Must be a function if not a class\n return storageType === 'singleton'\n ? this._functionStorageSingleton.has(label)\n : this._functionStorageScoped.has(label);\n }\n }\n\n // Helper to determine if something should be treated as a class (registered or decorated)\n private isClassType(label: any): boolean {\n if (this.isRegisteredAsClass(label)) {\n return true;\n }\n // If not explicitly registered as a class, check if it's a function with @Component\n if (typeof label === 'function' && label.prototype && !this.isRegisteredAsFunction(label)) {\n return getComponentOptions(label) !== null;\n }\n return false;\n }\n\n private getInstance(label: any): any {\n const storageType = this.getStorageType(label); // Checks decorators if needed\n\n if (!storageType) {\n // This should ideally not be reached if called after hasInstance check\n console.error(`[IOC GetInstance] Attempted to get instance for non-stored type: ${String(label)}`);\n throw new InstanceNotCreatedError();\n }\n\n const isClass = this.isClassType(label); // Check routing OR decorator\n\n if (isClass) {\n return storageType === 'singleton'\n ? this._classStorageSingleton.get(label)\n : this._classStorageScoped.get(label);\n } else { // Must be a function\n return storageType === 'singleton'\n ? this._functionStorageSingleton.get(label)\n : this._functionStorageScoped.get(label);\n }\n }\n\n private setInstance(label: any, instance: any, storageType?: StorageType): void { // Made storageType non-optional\n const isClass = this.isClassType(label); // Determine type based on routing OR decorator\n\n if (isClass) {\n if (storageType === 'singleton') {\n this._classStorageSingleton.set(label, instance);\n } else if (storageType == 'scoped'){ // storageType === 'scoped'\n this._classStorageScoped.set(label, instance);\n }\n } else { // Must be a function\n if (storageType === 'singleton') {\n this._functionStorageSingleton.set(label, instance);\n } else if(storageType === \"scoped\"){ // storageType === 'scoped'\n this._functionStorageScoped.set(label, instance);\n }\n }\n }\n\n private getStorageType(label: any): StorageType {\n let manualLoadAs: LoadAs | undefined;\n let decoratorScope: LoadAs | undefined;\n const isPotentialClass = typeof label === 'function' && label.prototype;\n\n // Get manual registration options if available\n if (this.isRegisteredAsClass(label)) { // Use helper\n manualLoadAs = this._classDefinition.get(label)?.loadAs;\n } else if (this.isRegisteredAsFunction(label)) { // Use helper\n manualLoadAs = this._functionDefinition.get(label)?.options?.loadAs;\n }\n\n // Get decorator scope only if it's potentially a class *and not explicitly registered as a function*\n if (isPotentialClass && !this.isRegisteredAsFunction(label)) {\n decoratorScope = getScope(label); // Uses getComponentOptions internally\n }\n\n // Determine final scope: Manual > Decorator > Default (Transient)\n const finalScope = manualLoadAs ?? decoratorScope ?? LoadAs.Transient;\n\n if (finalScope === LoadAs.Singleton) {\n return 'singleton';\n } else if (finalScope === LoadAs.Scoped) {\n return 'scoped';\n }else{\n return 'transient'; // Transient\n }\n }\n\n // Central resolution logic\n protected async loadInstance(\n label: any,\n params: ParameterValue<any>[] = [],\n resolutionChain: string[] = [], // Track resolution path\n parentProxyId?: number // For proxy hierarchy tracking\n ): Promise<any> {\n\n // --- Circular Dependency Check ---\n const currentLabelStr = (typeof label === 'function' && label.name) ? label.name : String(label);\n if (resolutionChain.includes(currentLabelStr)) {\n console.error(`[IOC LoadInstance] Circular dependency detected: ${[...resolutionChain, currentLabelStr].join(' -> ')}`);\n throw new CircularDependencyError([...resolutionChain, currentLabelStr]);\n }\n const nextResolutionChain = [...resolutionChain, currentLabelStr];\n // --- End Circular Dependency Check ---\n\n // --- Handle Parameters ---\n if (label instanceof Parameter) {\n try {\n // Pass a *copy* of params to avoid side effects in resolveParameterValue\n return Promise.resolve(this.resolveParameterValue(label, [...params]));\n } catch (e) {\n // console.error(`[IOC LoadInstance] Error resolving parameter ${param.toString()}:`, e);\n return Promise.reject(e);\n }\n }\n // --- End Handle Parameters ---\n\n\n // --- Check Explicit Registrations ---\n if (this.isRegisteredAsClass(label)) {\n // console.log(`[IOC LoadInstance] Resolving explicitly registered class: ${currentLabelStr}`);\n return this.loadClassInstance(label, params, nextResolutionChain, parentProxyId);\n }\n if (this.isRegisteredAsFunction(label)) {\n // console.log(`[IOC LoadInstance] Resolving explicitly registered function: ${currentLabelStr}`);\n return this.loadFunctionInstance(label, params, nextResolutionChain);\n }\n // --- End Check Explicit Registrations ---\n\n\n // --- Attempt Auto-Registration/Resolution for Decorated Classes ---\n if (typeof label === 'function' && label.prototype) {\n const componentOptions = getComponentOptions(label); // Check for @Component\n if (componentOptions !== null) {\n // console.log(`[IOC LoadInstance] Auto-resolving @Component class: ${currentLabelStr}`);\n // Set routing *now* so subsequent internal checks work correctly\n if (!this._routing.has(label)) { // Only set if not already set\n this._routing.set(label, ContainerRouting.CLASS);\n // console.log(`[IOC LoadInstance] Set routing for auto-resolved class: ${currentLabelStr}`);\n }\n // Proceed to load it as a class\n return this.loadClassInstance(label, params, nextResolutionChain, parentProxyId);\n }\n }\n // --- End Auto-Registration ---\n\n\n // --- Dependency Not Found ---\n console.error(`[IOC LoadInstance] Dependency not found and cannot be resolved: ${currentLabelStr}`);\n throw new DependencyNotFoundError(currentLabelStr);\n }\n\n\n private resolveParameterValue(param: Parameter, params: ParameterValue<any>[]): any { // No mutation\n // Find the *last* provided value for the parameter\n const valueContainer = [...params].reverse().find((p) => p.belongsTo(param));\n if (!valueContainer) {\n // console.error(`[IOC ResolveParam] Parameter not found: ${param.toString()}`);\n throw new ParameterNotFoundError(param.toString());\n }\n // console.log(`[IOC ResolveParam] Resolved parameter ${param.toString()}`);\n return valueContainer.value;\n }\n\n private loadClassInstance(\n classDefinition: any, // Should be a class constructor here\n params: ParameterValue<any>[],\n resolutionChain: string[],\n parentProxyId?: number\n ): Promise<any> {\n const storageType = this.getStorageType(classDefinition);\n const className = classDefinition.name || '[Anonymous Class]';\n\n // Check storage first (handle stored promises)\n if (storageType && this.hasInstance(classDefinition)) {\n const instance = this.getInstance(classDefinition);\n // console.log(`[IOC LoadClass] Found existing ${storageType} instance for ${className}. IsPromise: ${isPromise(instance)}`);\n return instance\n }\n // console.log(`[IOC LoadClass] Creating new ${storageType || 'transient'} instance for ${className}`);\n\n // --- Determine Dependencies ---\n const manualOptions = this._classDefinition.get(classDefinition) as ContainerOptions | undefined;\n let dependenciesToResolve: any[];\n\n if (manualOptions?.param && Array.isArray(manualOptions.param)) {\n dependenciesToResolve = manualOptions.param;\n // console.log(`[IOC LoadClass] Using manual dependencies for ${className}`);\n } else {\n // Use decorator-derived dependencies\n dependenciesToResolve = getResolvedDependencies(classDefinition);\n // console.log(`[IOC LoadClass] Using decorator/reflected dependencies for ${className}:`, dependenciesToResolve.map(d => typeof d === 'function' ? d.name : String(d)));\n }\n // --- End Determine Dependencies ---\n\n // Reserve a proxy ID if tracing is enabled\n let futureProxyId: number | undefined;\n if (this._enableTracing) {\n futureProxyId = reserveProxyId();\n }\n\n // --- Resolve Dependencies ---\n // Create a *copy* of params to pass down for dependency resolution\n const paramsCopy = [...params];\n const resolutionPromises = dependenciesToResolve.map(dependencyIdentifier =>\n this.loadInstance(dependencyIdentifier, paramsCopy, resolutionChain, futureProxyId) // Recursive call handles auto-registration\n );\n\n let finalInstance = Promise.all(resolutionPromises)\n .catch((error)=>{\n console.error(`[IOC LoadClass] Failed to resolve one or more dependencies for ${className}:`, error);\n // Clean up potential partially stored promise if this was going to be singleton/scoped\n if (storageType && this.isRegisteredAsClass(classDefinition)) { // Check if it was actually *being* stored\n if (storageType === 'singleton') this._classStorageSingleton.delete(classDefinition);\n if (storageType === 'scoped') this._classStorageScoped.delete(classDefinition);\n }\n throw error; // Re-throw dependency resolution error\n }).then(async(resolvedDependencies)=>{\n // --- Instantiate Class ---\n // Store the promise *before* starting instantiation for concurrent requests\n let instancePromise: Promise<any> | undefined;\n if (storageType && !this.hasInstance(classDefinition)) { // Check again in case of race condition?\n // Create the promise wrapper immediately\n instancePromise = (async () => {\n try {\n // console.log(`[IOC LoadClass] Instantiating ${className} with ${resolvedDependencies.length} args.`);\n const instance = new classDefinition(...resolvedDependencies);\n\n // Wrap with proxy if tracing is enabled\n let wrappedInstance = instance;\n if (this._enableTracing && futureProxyId !== undefined) {\n wrappedInstance = wrapWithProxy(instance, className, parentProxyId, futureProxyId);\n }\n\n // Overwrite the stored promise with the actual instance *after* it's created\n this.setInstance(classDefinition, wrappedInstance, storageType); // Use the correct storageType\n // console.log(`[IOC LoadClass] Stored actual ${storageType} instance for ${className}`);\n return wrappedInstance;\n } catch (err: any) {\n console.error(`[IOC LoadClass] Error during instantiation of ${className}: ${err.message}`, err.stack);\n // Clean up the stored promise on failure\n if (storageType === 'singleton') this._classStorageSingleton.delete(classDefinition);\n if (storageType === 'scoped') this._classStorageScoped.delete(classDefinition);\n throw err; // Re-throw instantiation error\n }\n })();\n // console.log(`[IOC LoadClass] Storing promise for concurrent requests (${storageType}) for ${className}`);\n this.setInstance(classDefinition, instancePromise, storageType);\n } else {\n // If already has instance (from storage check) or is transient, just instantiate directly\n instancePromise = (async () => {\n try {\n // console.log(`[IOC LoadClass] Instantiating transient ${className} with ${resolvedDependencies.length} args.`);\n const instance = new classDefinition(...resolvedDependencies);\n\n // Wrap with proxy if tracing is enabled\n let wrappedInstance = instance;\n if (this._enableTracing && futureProxyId !== undefined) {\n wrappedInstance = wrapWithProxy(instance, className, parentProxyId, futureProxyId);\n }\n\n // No storing for transient\n return wrappedInstance;\n } catch (err: any) {\n console.error(`[IOC LoadClass] Error during instantiation of transient ${className}: ${err.message}`, err.stack);\n throw err; // Re-throw instantiation error\n }\n })();\n }\n // --- End Instantiate Class ---\n // Await and return the final instance (either newly created or from the stored promise)\n return await instancePromise;\n });\n\n if(storageType && storageType !== 'transient'){\n this.setInstance(classDefinition, finalInstance, storageType); // Store the promise\n }\n return finalInstance\n }\n\n private loadFunctionInstance(\n funcLabel: any,\n params: ParameterValue<any>[],\n resolutionChain: string[]\n ): Promise<any> { // Always return Promise<any> since this is an async function\n const functionConfig = this._functionDefinition.get(funcLabel)!; // Assumed to exist by caller\n const storageType = this.getStorageType(funcLabel); // Only uses manual options for functions\n const labelStr = String(funcLabel);\n\n // Check storage first\n if (storageType && this.hasInstance(funcLabel)) {\n const instance = this.getInstance(funcLabel);\n // console.log(`[IOC LoadFunc] Found existing ${storageType} instance for ${labelStr}. IsPromise: ${isPromise(instance)}`);\n return instance;\n }\n // console.log(`[IOC LoadFunc] Creating new ${storageType || 'transient'} instance for ${labelStr}`);\n\n const ioc_func = functionConfig.function;\n const options = functionConfig.options;\n const dependenciesToResolve: any[] = options?.param || [];\n\n // --- Resolve Dependencies ---\n const paramsCopy = [...params]; // Create a copy\n const resolutionPromises = dependenciesToResolve.map(dependencyIdentifier =>\n this.loadInstance(dependencyIdentifier, paramsCopy, resolutionChain)\n );\n\n let finalInstance = Promise.all(resolutionPromises).catch((error)=>{\n console.error(`[IOC LoadFunc] Failed to resolve dependencies for function ${labelStr}:`, error);\n // Clean up potential partial storage\n if (storageType && this.isRegisteredAsFunction(funcLabel)) {\n if (storageType === 'singleton') this._functionStorageSingleton.delete(funcLabel);\n if (storageType === 'scoped') this._functionStorageScoped.delete(funcLabel);\n }\n throw error;\n }).then(async(resolvedArgs)=>{\n let instancePromise: Promise<any> | undefined;\n if (storageType && !this.hasInstance(funcLabel)) {\n instancePromise = (async () => {\n try {\n // console.log(`[IOC LoadFunc] Invoking ${labelStr} with ${resolvedArgs.length} args.`);\n const result = await ioc_func.apply(null, resolvedArgs); // Await in case function is async\n // Overwrite stored promise with actual result\n this.setInstance(funcLabel, result, storageType);\n // console.log(`[IOC LoadFunc] Stored actual ${storageType} instance for ${labelStr}`);\n return result;\n } catch (err: any) {\n console.error(`[IOC LoadFunc] Error executing function ${labelStr}: ${err.message}`, err.stack);\n // Clean up stored promise on failure\n if (storageType === 'singleton') this._functionStorageSingleton.delete(funcLabel);\n if (storageType === 'scoped') this._functionStorageScoped.delete(funcLabel);\n throw err;\n }\n })();\n // console.log(`[IOC LoadFunc] Storing promise for concurrent requests (${storageType}) for ${labelStr}`);\n this.setInstance(funcLabel, instancePromise, storageType);\n } else {\n // Transient or already resolved from storage check\n instancePromise = (async () => {\n try {\n // console.log(`[IOC LoadFunc] Invoking transient ${labelStr} with ${resolvedArgs.length} args.`);\n const result = await ioc_func.apply(null, resolvedArgs); // Await in case function is async\n // No storing for transient\n return result;\n } catch (err: any) {\n console.error(`[IOC LoadFunc] Error executing transient function ${labelStr}: ${err.message}`, err.stack);\n throw err;\n }\n })();\n }\n // --- End Invoke Function ---\n\n return await instancePromise; // Return the final (awaited) result\n });\n\n if(storageType && storageType !== 'transient'){\n this.setInstance(funcLabel, finalInstance, storageType); // Store the promise\n }\n\n return finalInstance;\n }\n}\n\n// Helper functions\nexport function isPromise(obj: any): obj is Promise<any> {\n // Simplified check - more robust check might be needed depending on environment\n return !!obj && typeof obj.then === 'function';\n}\n\nexport function createContainer(): IContainerClient & IContainerSetup {\n return new Container();\n}\n"],"mappings":"AAAA,OAAO;AAEP,SAAS,cAAc;AACvB,SAAS,iBAAiB;AAE1B,SAAS,0BAA0B,wBAAwB,yBAAyB,yBAAyB,+BAA+B;AAC5I;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,OACG;AACP,SAAS,eAAe,gBAAgB,sBAAsB;AAC9D,YAAY,uBAAuB;AACnC,SAAS,oBAAoB;AAE7B,IAAK,mBAAL,kBAAKA,sBAAL;AACI,EAAAA,kBAAA,gBAAa;AACb,EAAAA,kBAAA,WAAQ;AAFP,SAAAA;AAAA,GAAA;AAQE,MAAM,UAAuD;AAAA,EAA7D;AAEH;AAAA,SAAQ,WAAuC,oBAAI,IAAI;AACvD,SAAQ,sBAA8D,oBAAI,IAAI;AAC9E,SAAQ,mBAA6D,oBAAI,IAAI;AAG7E;AAAA,SAAQ,4BAA2C,oBAAI,IAAI;AAC3D,SAAQ,yBAAwC,oBAAI,IAAI;AACxD,SAAQ,yBAA6C,oBAAI,IAAI;AAC7D,SAAQ,sBAA0C,oBAAI,IAAI;AAG1D;AAAA,SAAQ,iBAA0B;AAClC,SAAQ,yBAAiC;AAAA;AAAA;AAAA,EAGzC,cAAiB,iBAA4C,SAA2C;AAEpG,QAAI,OAAO,oBAAoB,cAAc,CAAC,gBAAgB,WAAW;AACpE,cAAQ,KAAK,0CAA0C,OAAO,eAAe,CAAC,EAAE;AAGhF;AAAA,IACL;AAGA,SAAK,iBAAiB,eAAe;AAGrC,SAAK,SAAS,IAAI,iBAAiB,mBAAsB;AAGzD,QAAI,WAAW,OAAO,KAAK,OAAO,EAAE,SAAS,GAAG;AAC5C,WAAK,iBAAiB,IAAI,iBAAiB,OAAO;AAAA,IAEtD,OAAO;AAAA,IAIP;AAAA,EACJ;AAAA,EAEA,iBAAmD,OAAY,MAAS,UAAqC,CAAC,GAAgB;AAC1H,SAAK,iBAAiB,KAAK;AAC3B,SAAK,SAAS,IAAI,OAAO,6BAA2B;AACpD,SAAK,oBAAoB,IAAI,OAAO,EAAE,UAAU,MAAM,QAAQ,CAAC;AAAA,EAEnE;AAAA;AAAA,EAGA,SAAgC,iBAA2C,SAAgC,CAAC,GAAe;AAEvH,QAAI,OAAO,oBAAoB,cAAc,CAAC,gBAAgB,WAAW;AACpE,YAAM,IAAI,yBAAyB,0CAA0C,OAAO,eAAe,CAAC,EAAE;AAAA,IAC3G;AACA,WAAO,KAAK,aAAa,iBAAiB,MAAM;AAAA,EACpD;AAAA,EAEA,IAAO,OAAY,QAA+B,CAAC,GAAmB;AAElE,WAAO,KAAK,aAAa,OAAO,KAAK;AAAA,EACzC;AAAA,EAEA,SAA6C;AACzC,UAAM,iBAAiB,gBAAgB;AAGvC,mBAAe,WAAW,IAAI,IAAI,KAAK,QAAQ;AAC/C,mBAAe,sBAAsB,IAAI,IAAI,KAAK,mBAAmB;AACrE,mBAAe,mBAAmB,IAAI,IAAI,KAAK,gBAAgB;AAG/D,mBAAe,4BAA4B,KAAK;AAChD,mBAAe,yBAAyB,KAAK;AAM7C,mBAAe,iBAAiB,KAAK;AACrC,mBAAe,yBAAyB,KAAK;AAG7C,WAAO;AAAA,EACX;AAAA;AAAA,EAGA,kBAAkB,SAAwB;AACtC,SAAK,iBAAiB;AACtB,QAAI,WAAW,CAAC,aAAa,iBAAiB,GAAG;AAE7C,qBAAe,iBAAwB;AAEvC,mBAAa,MAAM,KAAK,sBAAsB;AAAA,IAClD;AAAA,EACJ;AAAA,EAEA,mBAA4B;AACxB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,yBAAyB,SAAuB;AAC5C,SAAK,yBAAyB,KAAK,IAAI,GAAG,OAAO;AAAA,EACrD;AAAA,EAEA,UAAU,kBAAkC;AACxC,UAAM,YAAY,oBAAoB,KAAK;AAC3C,WAAO,kBAAkB,gBAAgB,SAAS;AAAA,EACtD;AAAA,EAEA,eAAsB;AAClB,WAAO,kBAAkB,aAAa;AAAA,EAC1C;AAAA,EAEA,cAAoB;AAChB,sBAAkB,eAAe;AAAA,EACrC;AAAA,EAEA,aAAa,UAAwB;AACjC,UAAM,OAAO,kBAAkB,mBAAmB;AAClD,UAAM,KAAK,QAAQ,IAAI;AACvB,OAAG,cAAc,UAAU,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,EAC5D;AAAA,EAEA,qBAA0B;AACtB,WAAO,kBAAkB,mBAAmB;AAAA,EAChD;AAAA;AAAA,EAGQ,iBAAiB,OAAkB;AACvC,SAAK,SAAS,OAAO,KAAK;AAC1B,SAAK,oBAAoB,OAAO,KAAK;AAErC,QAAI,OAAO,UAAU,YAAY;AAC7B,WAAK,iBAAiB,OAAO,KAAK;AAAA,IACtC;AAAA,EACJ;AAAA;AAAA,EAGQ,oBAAoB,OAAqB;AAC7C,WAAO,KAAK,SAAS,IAAI,KAAK,MAAM;AAAA,EACxC;AAAA;AAAA,EAGS,uBAAuB,OAAqB;AAChD,WAAO,KAAK,SAAS,IAAI,KAAK,MAAM;AAAA,EACxC;AAAA,EAGO,YAAY,OAAqB;AACrC,UAAM,cAAc,KAAK,eAAe,KAAK;AAE7C,QAAI,CAAC,aAAa;AAEd,aAAO;AAAA,IACX;AAGA,UAAM,UAAU,KAAK,YAAY,KAAK;AAEtC,QAAI,SAAS;AACT,aAAO,gBAAgB,cACjB,KAAK,uBAAuB,IAAI,KAAK,IACrC,KAAK,oBAAoB,IAAI,KAAK;AAAA,IAC5C,OAAO;AACH,aAAO,gBAAgB,cACjB,KAAK,0BAA0B,IAAI,KAAK,IACxC,KAAK,uBAAuB,IAAI,KAAK;AAAA,IAC/C;AAAA,EACJ;AAAA;AAAA,EAGS,YAAY,OAAqB;AACrC,QAAI,KAAK,oBAAoB,KAAK,GAAG;AACjC,aAAO;AAAA,IACX;AAEA,QAAI,OAAO,UAAU,cAAc,MAAM,aAAa,CAAC,KAAK,uBAAuB,KAAK,GAAG;AACtF,aAAO,oBAAoB,KAAK,MAAM;AAAA,IAC3C;AACA,WAAO;AAAA,EACX;AAAA,EAEO,YAAY,OAAiB;AACjC,UAAM,cAAc,KAAK,eAAe,KAAK;AAE5C,QAAI,CAAC,aAAa;AAEd,cAAQ,MAAM,oEAAoE,OAAO,KAAK,CAAC,EAAE;AACjG,YAAM,IAAI,wBAAwB;AAAA,IACtC;AAED,UAAM,UAAU,KAAK,YAAY,KAAK;AAEtC,QAAI,SAAS;AACT,aAAO,gBAAgB,cACjB,KAAK,uBAAuB,IAAI,KAAK,IACrC,KAAK,oBAAoB,IAAI,KAAK;AAAA,IAC5C,OAAO;AACH,aAAO,gBAAgB,cACjB,KAAK,0BAA0B,IAAI,KAAK,IACxC,KAAK,uBAAuB,IAAI,KAAK;AAAA,IAC/C;AAAA,EACJ;AAAA,EAEQ,YAAY,OAAY,UAAe,aAAiC;AAC5E,UAAM,UAAU,KAAK,YAAY,KAAK;AAEtC,QAAI,SAAS;AACT,UAAI,gBAAgB,aAAa;AAC7B,aAAK,uBAAuB,IAAI,OAAO,QAAQ;AAAA,MACnD,WAAW,eAAe,UAAS;AAC/B,aAAK,oBAAoB,IAAI,OAAO,QAAQ;AAAA,MAChD;AAAA,IACJ,OAAO;AACH,UAAI,gBAAgB,aAAa;AAC7B,aAAK,0BAA0B,IAAI,OAAO,QAAQ;AAAA,MACtD,WAAU,gBAAgB,UAAS;AAC/B,aAAK,uBAAuB,IAAI,OAAO,QAAQ;AAAA,MACnD;AAAA,IACJ;AAAA,EACJ;AAAA,EAEQ,eAAe,OAAyB;AAC5C,QAAI;AACJ,QAAI;AACJ,UAAM,mBAAmB,OAAO,UAAU,cAAc,MAAM;AAG9D,QAAI,KAAK,oBAAoB,KAAK,GAAG;AACjC,qBAAe,KAAK,iBAAiB,IAAI,KAAK,GAAG;AAAA,IACrD,WAAW,KAAK,uBAAuB,KAAK,GAAG;AAC3C,qBAAe,KAAK,oBAAoB,IAAI,KAAK,GAAG,SAAS;AAAA,IACjE;AAGA,QAAI,oBAAoB,CAAC,KAAK,uBAAuB,KAAK,GAAG;AACzD,uBAAiB,SAAS,KAAK;AAAA,IACnC;AAGA,UAAM,aAAa,gBAAgB,kBAAkB,OAAO;AAE5D,QAAI,eAAe,OAAO,WAAW;AACjC,aAAO;AAAA,IACX,WAAW,eAAe,OAAO,QAAQ;AACrC,aAAO;AAAA,IACX,OAAK;AACD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA,EAGA,MAAgB,aACZ,OACA,SAAgC,CAAC,GACjC,kBAA4B,CAAC,GAC7B,eACY;AAGZ,UAAM,kBAAmB,OAAO,UAAU,cAAc,MAAM,OAAQ,MAAM,OAAO,OAAO,KAAK;AAC/F,QAAI,gBAAgB,SAAS,eAAe,GAAG;AAC3C,cAAQ,MAAM,oDAAoD,CAAC,GAAG,iBAAiB,eAAe,EAAE,KAAK,MAAM,CAAC,EAAE;AACtH,YAAM,IAAI,wBAAwB,CAAC,GAAG,iBAAiB,eAAe,CAAC;AAAA,IAC3E;AACA,UAAM,sBAAsB,CAAC,GAAG,iBAAiB,eAAe;AAIhE,QAAI,iBAAiB,WAAW;AAC5B,UAAI;AAEA,eAAO,QAAQ,QAAQ,KAAK,sBAAsB,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC;AAAA,MACzE,SAAS,GAAG;AAER,eAAO,QAAQ,OAAO,CAAC;AAAA,MAC3B;AAAA,IACJ;AAKA,QAAI,KAAK,oBAAoB,KAAK,GAAG;AAEjC,aAAO,KAAK,kBAAkB,OAAO,QAAQ,qBAAqB,aAAa;AAAA,IACnF;AACA,QAAI,KAAK,uBAAuB,KAAK,GAAG;AAEpC,aAAO,KAAK,qBAAqB,OAAO,QAAQ,mBAAmB;AAAA,IACvE;AAKA,QAAI,OAAO,UAAU,cAAc,MAAM,WAAW;AAChD,YAAM,mBAAmB,oBAAoB,KAAK;AAClD,UAAI,qBAAqB,MAAM;AAG3B,YAAI,CAAC,KAAK,SAAS,IAAI,KAAK,GAAG;AAC1B,eAAK,SAAS,IAAI,OAAO,mBAAsB;AAAA,QAEpD;AAEA,eAAO,KAAK,kBAAkB,OAAO,QAAQ,qBAAqB,aAAa;AAAA,MACnF;AAAA,IACJ;AAKA,YAAQ,MAAM,mEAAmE,eAAe,EAAE;AAClG,UAAM,IAAI,wBAAwB,eAAe;AAAA,EACrD;AAAA,EAGQ,sBAAsB,OAAkB,QAAoC;AAEhF,UAAM,iBAAiB,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,KAAK,CAAC;AAC3E,QAAI,CAAC,gBAAgB;AAEjB,YAAM,IAAI,uBAAuB,MAAM,SAAS,CAAC;AAAA,IACrD;AAEA,WAAO,eAAe;AAAA,EAC1B;AAAA,EAEQ,kBACJ,iBACA,QACA,iBACA,eACY;AACZ,UAAM,cAAc,KAAK,eAAe,eAAe;AACvD,UAAM,YAAY,gBAAgB,QAAQ;AAG1C,QAAI,eAAe,KAAK,YAAY,eAAe,GAAG;AAClD,YAAM,WAAW,KAAK,YAAY,eAAe;AAEjD,aAAO;AAAA,IACX;AAIA,UAAM,gBAAgB,KAAK,iBAAiB,IAAI,eAAe;AAC/D,QAAI;AAEJ,QAAI,eAAe,SAAS,MAAM,QAAQ,cAAc,KAAK,GAAG;AAC5D,8BAAwB,cAAc;AAAA,IAE1C,OAAO;AAEH,8BAAwB,wBAAwB,eAAe;AAAA,IAEnE;AAIA,QAAI;AACJ,QAAI,KAAK,gBAAgB;AACrB,sBAAgB,eAAe;AAAA,IACnC;AAIA,UAAM,aAAa,CAAC,GAAG,MAAM;AAC7B,UAAM,qBAAqB,sBAAsB;AAAA,MAAI,0BACjD,KAAK,aAAa,sBAAsB,YAAY,iBAAiB,aAAa;AAAA;AAAA,IACtF;AAEA,QAAI,gBAAgB,QAAQ,IAAI,kBAAkB,EACjD,MAAM,CAAC,UAAQ;AACZ,cAAQ,MAAM,kEAAkE,SAAS,KAAK,KAAK;AAEnG,UAAI,eAAe,KAAK,oBAAoB,eAAe,GAAG;AAC1D,YAAI,gBAAgB,YAAa,MAAK,uBAAuB,OAAO,eAAe;AACnF,YAAI,gBAAgB,SAAU,MAAK,oBAAoB,OAAO,eAAe;AAAA,MACjF;AACA,YAAM;AAAA,IACV,CAAC,EAAE,KAAK,OAAM,yBAAuB;AAGjC,UAAI;AACJ,UAAI,eAAe,CAAC,KAAK,YAAY,eAAe,GAAG;AAEnD,2BAAmB,YAAY;AAC3B,cAAI;AAEA,kBAAM,WAAW,IAAI,gBAAgB,GAAG,oBAAoB;AAG5D,gBAAI,kBAAkB;AACtB,gBAAI,KAAK,kBAAkB,kBAAkB,QAAW;AACpD,gCAAkB,cAAc,UAAU,WAAW,eAAe,aAAa;AAAA,YACrF;AAGA,iBAAK,YAAY,iBAAiB,iBAAiB,WAAW;AAE9D,mBAAO;AAAA,UACX,SAAS,KAAU;AACf,oBAAQ,MAAM,iDAAiD,SAAS,KAAK,IAAI,OAAO,IAAI,IAAI,KAAK;AAErG,gBAAI,gBAAgB,YAAa,MAAK,uBAAuB,OAAO,eAAe;AACnF,gBAAI,gBAAgB,SAAU,MAAK,oBAAoB,OAAO,eAAe;AAC7E,kBAAM;AAAA,UACV;AAAA,QACJ,GAAG;AAEH,aAAK,YAAY,iBAAiB,iBAAiB,WAAW;AAAA,MAClE,OAAO;AAEF,2BAAmB,YAAY;AAC1B,cAAI;AAEC,kBAAM,WAAW,IAAI,gBAAgB,GAAG,oBAAoB;AAG5D,gBAAI,kBAAkB;AACtB,gBAAI,KAAK,kBAAkB,kBAAkB,QAAW;AACpD,gCAAkB,cAAc,UAAU,WAAW,eAAe,aAAa;AAAA,YACrF;AAGA,mBAAO;AAAA,UACZ,SAAS,KAAU;AACd,oBAAQ,MAAM,2DAA2D,SAAS,KAAK,IAAI,OAAO,IAAI,IAAI,KAAK;AAC/G,kBAAM;AAAA,UACX;AAAA,QACL,GAAG;AAAA,MACR;AAGA,aAAO,MAAM;AAAA,IACjB,CAAC;AAED,QAAG,eAAe,gBAAgB,aAAY;AAC1C,WAAK,YAAY,iBAAiB,eAAe,WAAW;AAAA,IAChE;AACA,WAAO;AAAA,EACX;AAAA,EAEQ,qBACJ,WACA,QACA,iBACY;AACZ,UAAM,iBAAiB,KAAK,oBAAoB,IAAI,SAAS;AAC7D,UAAM,cAAc,KAAK,eAAe,SAAS;AACjD,UAAM,WAAW,OAAO,SAAS;AAGjC,QAAI,eAAe,KAAK,YAAY,SAAS,GAAG;AAC5C,YAAM,WAAW,KAAK,YAAY,SAAS;AAE3C,aAAO;AAAA,IACX;AAGA,UAAM,WAAW,eAAe;AAChC,UAAM,UAAU,eAAe;AAC/B,UAAM,wBAA+B,SAAS,SAAS,CAAC;AAGxD,UAAM,aAAa,CAAC,GAAG,MAAM;AAC7B,UAAM,qBAAqB,sBAAsB;AAAA,MAAI,0BACjD,KAAK,aAAa,sBAAsB,YAAY,eAAe;AAAA,IACvE;AAEA,QAAI,gBAAgB,QAAQ,IAAI,kBAAkB,EAAE,MAAM,CAAC,UAAQ;AAC/D,cAAQ,MAAM,8DAA8D,QAAQ,KAAK,KAAK;AAE/F,UAAI,eAAe,KAAK,uBAAuB,SAAS,GAAG;AACtD,YAAI,gBAAgB,YAAa,MAAK,0BAA0B,OAAO,SAAS;AAChF,YAAI,gBAAgB,SAAU,MAAK,uBAAuB,OAAO,SAAS;AAAA,MAC/E;AACA,YAAM;AAAA,IACT,CAAC,EAAE,KAAK,OAAM,iBAAe;AACzB,UAAI;AACR,UAAI,eAAe,CAAC,KAAK,YAAY,SAAS,GAAG;AAC5C,2BAAmB,YAAY;AAC3B,cAAI;AAEA,kBAAM,SAAS,MAAM,SAAS,MAAM,MAAM,YAAY;AAEtD,iBAAK,YAAY,WAAW,QAAQ,WAAW;AAE/C,mBAAO;AAAA,UACX,SAAS,KAAU;AACf,oBAAQ,MAAM,2CAA2C,QAAQ,KAAK,IAAI,OAAO,IAAI,IAAI,KAAK;AAE9F,gBAAI,gBAAgB,YAAa,MAAK,0BAA0B,OAAO,SAAS;AAChF,gBAAI,gBAAgB,SAAU,MAAK,uBAAuB,OAAO,SAAS;AAC1E,kBAAM;AAAA,UACV;AAAA,QACJ,GAAG;AAEH,aAAK,YAAY,WAAW,iBAAiB,WAAW;AAAA,MAC7D,OAAO;AAEF,2BAAmB,YAAY;AAC1B,cAAI;AAEA,kBAAM,SAAS,MAAM,SAAS,MAAM,MAAM,YAAY;AAEtD,mBAAO;AAAA,UACX,SAAS,KAAU;AACf,oBAAQ,MAAM,qDAAqD,QAAQ,KAAK,IAAI,OAAO,IAAI,IAAI,KAAK;AACxG,kBAAM;AAAA,UACV;AAAA,QACL,GAAG;AAAA,MACR;AAGA,aAAO,MAAM;AAAA,IACb,CAAC;AAED,QAAG,eAAe,gBAAgB,aAAY;AAC1C,WAAK,YAAY,WAAW,eAAe,WAAW;AAAA,IAC1D;AAEA,WAAO;AAAA,EACX;AACJ;AAGO,SAAS,UAAU,KAA+B;AAErD,SAAO,CAAC,CAAC,OAAO,OAAO,IAAI,SAAS;AACxC;AAEO,SAAS,kBAAsD;AAClE,SAAO,IAAI,UAAU;AACzB;","names":["ContainerRouting"]}
|
|
1
|
+
{"version":3,"sources":["../../../framework/implementation/Container.ts"],"sourcesContent":["import 'reflect-metadata'; // Ensure polyfill is loaded conceptually\nimport type { ContainerOptions, IContainerClient, IContainerFunctionDefinition, IContainerSetup } from \"../interface/Container.js\";\nimport { LoadAs } from \"./LoadAs.js\";\nimport { Parameter } from \"./Parameter.js\";\nimport type { ParameterValue } from \"./Parameter.js\";\nimport { NotAClassDefinitionError, ParameterNotFoundError, DependencyNotFoundError, InstanceNotCreatedError, CircularDependencyError } from \"../errors/ContainerErrors.js\";\nimport {\n getScope,\n getComponentOptions, // Use helper\n getResolvedDependencies // Use helper\n} from './DecoratorSupport'; // Assume helpers exist or create them\nimport { wrapWithProxy, setTraceLogger, reserveProxyId } from \"./ProxyFactory.js\";\nimport * as TraceLoggerModule from \"./TraceLogger.js\";\nimport { TraceCleanup } from \"./TraceCleanup.js\";\n\n/**\n * A special injection token that resolves to the current scoped container.\n * Use this as a dependency in param arrays to have the container inject itself.\n * This allows provider classes to resolve additional dependencies on demand.\n */\nexport const SCOPED_CONTAINER = Symbol.for(\"ioc:scoped-container\");\n\nenum ContainerRouting {\n FUNCTIONAL = \"FUNCTIONAL\",\n CLASS = \"CLASS\"\n // No need for COMPONENT route, just check metadata if CLASS/FUNCTIONAL fails\n}\n\ntype StorageType = 'singleton' | 'scoped' | 'transient';\n\nexport class Container implements IContainerClient, IContainerSetup {\n // Routing and definition maps\n private _routing: Map<any, ContainerRouting> = new Map();\n private _functionDefinition: Map<any, IContainerFunctionDefinition> = new Map();\n private _classDefinition: Map<Function, Partial<ContainerOptions>> = new Map();\n\n // Storage maps\n private _functionStorageSingleton: Map<any, any> = new Map();\n private _functionStorageScoped: Map<any, any> = new Map();\n private _classStorageSingleton: Map<Function, any> = new Map();\n private _classStorageScoped: Map<Function, any> = new Map();\n\n // Tracing configuration\n private _enableTracing: boolean = false;\n private _traceRetentionMinutes: number = 5;\n\n // Registration methods\n registerClass<T>(classDefinition: new (...args: any[]) => T, options?: Partial<ContainerOptions>): void {\n // Basic validation\n if (typeof classDefinition !== 'function' || !classDefinition.prototype) {\n console.warn(`[IOC] Attempted to register non-class: ${String(classDefinition)}`);\n // Optional: throw error instead?\n // throw new NotAClassDefinitionError(`Attempted to register non-class: ${String(classDefinition)}`);\n return; // Don't proceed if not a class constructor\n }\n\n // Always clear previous definitions for this exact class constructor\n this.clearDefinitions(classDefinition);\n\n // Always set the routing type so 'isClassDefinition' works\n this._routing.set(classDefinition, ContainerRouting.CLASS);\n\n // Store manual options *only if they are actually provided and have content*\n if (options && Object.keys(options).length > 0) {\n this._classDefinition.set(classDefinition, options);\n // console.log(`[IOC RegClass] Manually registered ${classDefinition.name} with options:`, options);\n } else {\n // console.log(`[IOC RegClass] Manually registered ${classDefinition.name} with no specific options (will use decorators if present).`);\n // If no options are provided, we don't store anything in _classDefinition,\n // effectively clearing any previous manual config and letting decorators take over if present.\n }\n }\n\n registerFunction<T extends (...arg: any[]) => any>(label: any, func: T, options: Partial<ContainerOptions> = {} as any): void {\n this.clearDefinitions(label);\n this._routing.set(label, ContainerRouting.FUNCTIONAL);\n this._functionDefinition.set(label, { function: func, options });\n // console.log(`[IOC RegFunc] Registered function with label ${String(label)} and options:`, options);\n }\n\n // Instance resolution methods - Simplify to just call loadInstance\n instance<T, Sync extends boolean = false>(classDefinition: new (...args: any[]) => T, params: ParameterValue<any>[] = []): Sync extends true ? T : Promise<T> | T {\n // Basic check upfront\n if (typeof classDefinition !== 'function' || !classDefinition.prototype) {\n throw new NotAClassDefinitionError(`Cannot resolve instance for non-class: ${String(classDefinition)}`);\n }\n return this.loadInstance(classDefinition, params);\n }\n\n get<T, Sync extends boolean = false>(label: any, param: ParameterValue<any>[] = []): Sync extends true ? T : Promise<T> | T {\n // Just delegate to loadInstance, which handles routing and auto-registration\n return this.loadInstance(label, param);\n }\n\n extend(): IContainerClient & IContainerSetup {\n const childContainer = createContainer() as Container;\n\n // Copy routing and definition maps (share the registration knowledge)\n childContainer._routing = new Map(this._routing);\n childContainer._functionDefinition = new Map(this._functionDefinition);\n childContainer._classDefinition = new Map(this._classDefinition);\n\n // Share singleton storage (singletons are shared across all containers)\n childContainer._functionStorageSingleton = this._functionStorageSingleton;\n childContainer._classStorageSingleton = this._classStorageSingleton;\n\n // Do NOT share scoped storage (new container = new scope)\n // Child gets its own empty scoped storage\n\n // Share tracing configuration\n childContainer._enableTracing = this._enableTracing;\n childContainer._traceRetentionMinutes = this._traceRetentionMinutes;\n\n // console.log('[IOC Extend] Created child container.');\n return childContainer;\n }\n\n // Tracing API\n setTracingEnabled(enabled: boolean): void {\n this._enableTracing = enabled;\n if (enabled && !TraceCleanup.isCleanupRunning()) {\n // Set the trace logger for the ProxyFactory\n setTraceLogger(TraceLoggerModule as any);\n // Start automatic cleanup\n TraceCleanup.start(this._traceRetentionMinutes);\n }\n }\n\n isTracingEnabled(): boolean {\n return this._enableTracing;\n }\n\n setTraceRetentionMinutes(minutes: number): void {\n this._traceRetentionMinutes = Math.max(1, minutes);\n }\n\n getTraces(retentionMinutes?: number): any[] {\n const retention = retentionMinutes ?? this._traceRetentionMinutes;\n return TraceLoggerModule.getRecentTraces(retention);\n }\n\n getAllTraces(): any[] {\n return TraceLoggerModule.getAllTraces();\n }\n\n clearTraces(): void {\n TraceLoggerModule.clearAllTraces();\n }\n\n exportTraces(filepath: string): void {\n const data = TraceLoggerModule.exportTracesToJson();\n const fs = require('fs');\n fs.writeFileSync(filepath, JSON.stringify(data, null, 2));\n }\n\n getTraceStatistics(): any {\n return TraceLoggerModule.getTraceStatistics();\n }\n\n // Private helper methods\n private clearDefinitions(label: any): void {\n this._routing.delete(label);\n this._functionDefinition.delete(label);\n // Only delete from classDefinition if the label is actually a function constructor\n if (typeof label === 'function') {\n this._classDefinition.delete(label);\n }\n }\n\n // Checks if the label is *currently* registered as a class\n private isRegisteredAsClass(label: any): boolean {\n return this._routing.get(label) === ContainerRouting.CLASS;\n }\n\n // Checks if the label is *currently* registered as a function\n private isRegisteredAsFunction(label: any): boolean {\n return this._routing.get(label) === ContainerRouting.FUNCTIONAL;\n }\n\n\n private hasInstance(label: any): boolean {\n const storageType = this.getStorageType(label); // This checks decorators if needed\n\n if (!storageType) {\n // Transient instances are never stored\n return false;\n }\n\n // Determine if it's treated as a class (registered or decorated) *after* getting type\n const isClass = this.isClassType(label); // Use a helper that checks routing OR decorator\n\n if (isClass) {\n return storageType === 'singleton'\n ? this._classStorageSingleton.has(label)\n : this._classStorageScoped.has(label);\n } else { // Must be a function if not a class\n return storageType === 'singleton'\n ? this._functionStorageSingleton.has(label)\n : this._functionStorageScoped.has(label);\n }\n }\n\n // Helper to determine if something should be treated as a class (registered or decorated)\n private isClassType(label: any): boolean {\n if (this.isRegisteredAsClass(label)) {\n return true;\n }\n // If not explicitly registered as a class, check if it's a function with @Component\n if (typeof label === 'function' && label.prototype && !this.isRegisteredAsFunction(label)) {\n return getComponentOptions(label) !== null;\n }\n return false;\n }\n\n private getInstance(label: any): any {\n const storageType = this.getStorageType(label); // Checks decorators if needed\n\n if (!storageType) {\n // This should ideally not be reached if called after hasInstance check\n console.error(`[IOC GetInstance] Attempted to get instance for non-stored type: ${String(label)}`);\n throw new InstanceNotCreatedError();\n }\n\n const isClass = this.isClassType(label); // Check routing OR decorator\n\n if (isClass) {\n return storageType === 'singleton'\n ? this._classStorageSingleton.get(label)\n : this._classStorageScoped.get(label);\n } else { // Must be a function\n return storageType === 'singleton'\n ? this._functionStorageSingleton.get(label)\n : this._functionStorageScoped.get(label);\n }\n }\n\n private setInstance(label: any, instance: any, storageType?: StorageType): void { // Made storageType non-optional\n const isClass = this.isClassType(label); // Determine type based on routing OR decorator\n\n if (isClass) {\n if (storageType === 'singleton') {\n this._classStorageSingleton.set(label, instance);\n } else if (storageType == 'scoped'){ // storageType === 'scoped'\n this._classStorageScoped.set(label, instance);\n }\n } else { // Must be a function\n if (storageType === 'singleton') {\n this._functionStorageSingleton.set(label, instance);\n } else if(storageType === \"scoped\"){ // storageType === 'scoped'\n this._functionStorageScoped.set(label, instance);\n }\n }\n }\n\n private getStorageType(label: any): StorageType {\n let manualLoadAs: LoadAs | undefined;\n let decoratorScope: LoadAs | undefined;\n const isPotentialClass = typeof label === 'function' && label.prototype;\n\n // Get manual registration options if available\n if (this.isRegisteredAsClass(label)) { // Use helper\n manualLoadAs = this._classDefinition.get(label)?.loadAs;\n } else if (this.isRegisteredAsFunction(label)) { // Use helper\n manualLoadAs = this._functionDefinition.get(label)?.options?.loadAs;\n }\n\n // Get decorator scope only if it's potentially a class *and not explicitly registered as a function*\n if (isPotentialClass && !this.isRegisteredAsFunction(label)) {\n decoratorScope = getScope(label); // Uses getComponentOptions internally\n }\n\n // Determine final scope: Manual > Decorator > Default (Transient)\n const finalScope = manualLoadAs ?? decoratorScope ?? LoadAs.Transient;\n\n if (finalScope === LoadAs.Singleton) {\n return 'singleton';\n } else if (finalScope === LoadAs.Scoped) {\n return 'scoped';\n }else{\n return 'transient'; // Transient\n }\n }\n\n // Central resolution logic - sync-first, returns T or Promise<T>\n protected loadInstance(\n label: any,\n params: ParameterValue<any>[] = [],\n resolutionChain: string[] = [], // Track resolution path\n parentProxyId?: number // For proxy hierarchy tracking\n ): any {\n\n // --- Circular Dependency Check ---\n const currentLabelStr = (typeof label === 'function' && label.name) ? label.name : String(label);\n if (resolutionChain.includes(currentLabelStr)) {\n console.error(`[IOC LoadInstance] Circular dependency detected: ${[...resolutionChain, currentLabelStr].join(' -> ')}`);\n throw new CircularDependencyError([...resolutionChain, currentLabelStr]);\n }\n const nextResolutionChain = [...resolutionChain, currentLabelStr];\n // --- End Circular Dependency Check ---\n\n // --- Handle Parameters ---\n if (label instanceof Parameter) {\n try {\n // Pass a *copy* of params to avoid side effects in resolveParameterValue\n return this.resolveParameterValue(label, [...params]);\n } catch (e) {\n // console.error(`[IOC LoadInstance] Error resolving parameter ${param.toString()}:`, e);\n throw e;\n }\n }\n // --- End Handle Parameters ---\n\n // --- Handle Scoped Container Injection ---\n if (label === SCOPED_CONTAINER) {\n return this;\n }\n // --- End Handle Scoped Container Injection ---\n\n // --- Check Explicit Registrations ---\n if (this.isRegisteredAsClass(label)) {\n // console.log(`[IOC LoadInstance] Resolving explicitly registered class: ${currentLabelStr}`);\n return this.loadClassInstance(label, params, nextResolutionChain, parentProxyId);\n }\n if (this.isRegisteredAsFunction(label)) {\n // console.log(`[IOC LoadInstance] Resolving explicitly registered function: ${currentLabelStr}`);\n return this.loadFunctionInstance(label, params, nextResolutionChain);\n }\n // --- End Check Explicit Registrations ---\n\n\n // --- Attempt Auto-Registration/Resolution for Decorated Classes ---\n if (typeof label === 'function' && label.prototype) {\n const componentOptions = getComponentOptions(label); // Check for @Component\n if (componentOptions !== null) {\n // console.log(`[IOC LoadInstance] Auto-resolving @Component class: ${currentLabelStr}`);\n // Set routing *now* so subsequent internal checks work correctly\n if (!this._routing.has(label)) { // Only set if not already set\n this._routing.set(label, ContainerRouting.CLASS);\n // console.log(`[IOC LoadInstance] Set routing for auto-resolved class: ${currentLabelStr}`);\n }\n // Proceed to load it as a class\n return this.loadClassInstance(label, params, nextResolutionChain, parentProxyId);\n }\n }\n // --- End Auto-Registration ---\n\n\n // --- Dependency Not Found ---\n console.error(`[IOC LoadInstance] Dependency not found and cannot be resolved: ${currentLabelStr}`);\n throw new DependencyNotFoundError(currentLabelStr);\n }\n\n\n private resolveParameterValue(param: Parameter, params: ParameterValue<any>[]): any { // No mutation\n // Find the *last* provided value for the parameter\n const valueContainer = [...params].reverse().find((p) => p.belongsTo(param));\n if (!valueContainer) {\n // console.error(`[IOC ResolveParam] Parameter not found: ${param.toString()}`);\n throw new ParameterNotFoundError(param.toString());\n }\n // console.log(`[IOC ResolveParam] Resolved parameter ${param.toString()}`);\n return valueContainer.value;\n }\n\n private loadClassInstance(\n classDefinition: any, // Should be a class constructor here\n params: ParameterValue<any>[],\n resolutionChain: string[],\n parentProxyId?: number\n ): any {\n const storageType = this.getStorageType(classDefinition);\n const className = classDefinition.name || '[Anonymous Class]';\n\n // Check storage first (may be sync value or Promise)\n if (storageType && this.hasInstance(classDefinition)) {\n const instance = this.getInstance(classDefinition);\n // console.log(`[IOC LoadClass] Found existing ${storageType} instance for ${className}. IsPromise: ${isPromise(instance)}`);\n return instance;\n }\n // console.log(`[IOC LoadClass] Creating new ${storageType || 'transient'} instance for ${className}`);\n\n // --- Determine Dependencies ---\n const manualOptions = this._classDefinition.get(classDefinition) as ContainerOptions | undefined;\n let dependenciesToResolve: any[];\n\n if (manualOptions?.param && Array.isArray(manualOptions.param)) {\n dependenciesToResolve = manualOptions.param;\n // console.log(`[IOC LoadClass] Using manual dependencies for ${className}`);\n } else {\n // Use decorator-derived dependencies\n dependenciesToResolve = getResolvedDependencies(classDefinition);\n // console.log(`[IOC LoadClass] Using decorator/reflected dependencies for ${className}:`, dependenciesToResolve.map(d => typeof d === 'function' ? d.name : String(d)));\n }\n // --- End Determine Dependencies ---\n\n // Reserve a proxy ID if tracing is enabled\n let futureProxyId: number | undefined;\n if (this._enableTracing) {\n futureProxyId = reserveProxyId();\n }\n\n // --- Resolve Dependencies (sync-first) ---\n const paramsCopy = [...params];\n const resolvedDependencies: any[] = [];\n let hasAsyncDependency = false;\n\n // Resolve each dependency and check if any return Promises\n for (const dependencyIdentifier of dependenciesToResolve) {\n const resolved = this.loadInstance(dependencyIdentifier, paramsCopy, resolutionChain, futureProxyId);\n resolvedDependencies.push(resolved);\n if (isPromise(resolved)) {\n hasAsyncDependency = true;\n }\n }\n\n // Helper to instantiate the class\n const instantiate = (deps: any[]): any => {\n try {\n const instance = new classDefinition(...deps);\n\n // Wrap with proxy if tracing is enabled\n if (this._enableTracing && futureProxyId !== undefined) {\n return wrapWithProxy(instance, className, parentProxyId, futureProxyId);\n }\n return instance;\n } catch (err: any) {\n console.error(`[IOC LoadClass] Error during instantiation of ${className}: ${err.message}`, err.stack);\n throw err;\n }\n };\n\n // --- Sync Path: All dependencies resolved synchronously ---\n if (!hasAsyncDependency) {\n const instance = instantiate(resolvedDependencies);\n\n // Store if singleton/scoped\n if (storageType && storageType !== 'transient') {\n this.setInstance(classDefinition, instance, storageType);\n }\n return instance;\n }\n\n // --- Async Path: At least one dependency is a Promise ---\n const asyncInstance = Promise.all(resolvedDependencies)\n .then((deps) => {\n const instance = instantiate(deps);\n\n // Store if singleton/scoped (overwrite the promise with the instance)\n if (storageType && storageType !== 'transient') {\n this.setInstance(classDefinition, instance, storageType);\n }\n return instance;\n })\n .catch((error) => {\n console.error(`[IOC LoadClass] Failed to resolve one or more dependencies for ${className}:`, error);\n // Clean up stored promise on failure\n if (storageType && this.isRegisteredAsClass(classDefinition)) {\n if (storageType === 'singleton') this._classStorageSingleton.delete(classDefinition);\n if (storageType === 'scoped') this._classStorageScoped.delete(classDefinition);\n }\n throw error;\n });\n\n // Store the promise for singleton/scoped to handle concurrent requests\n if (storageType && storageType !== 'transient') {\n this.setInstance(classDefinition, asyncInstance, storageType);\n }\n\n return asyncInstance;\n }\n\n private loadFunctionInstance(\n funcLabel: any,\n params: ParameterValue<any>[],\n resolutionChain: string[]\n ): Promise<any> { // Always return Promise<any> since this is an async function\n const functionConfig = this._functionDefinition.get(funcLabel)!; // Assumed to exist by caller\n const storageType = this.getStorageType(funcLabel); // Only uses manual options for functions\n const labelStr = String(funcLabel);\n\n // Check storage first\n if (storageType && this.hasInstance(funcLabel)) {\n const instance = this.getInstance(funcLabel);\n // console.log(`[IOC LoadFunc] Found existing ${storageType} instance for ${labelStr}. IsPromise: ${isPromise(instance)}`);\n return instance;\n }\n // console.log(`[IOC LoadFunc] Creating new ${storageType || 'transient'} instance for ${labelStr}`);\n\n const ioc_func = functionConfig.function;\n const options = functionConfig.options;\n const dependenciesToResolve: any[] = options?.param || [];\n\n // --- Resolve Dependencies ---\n const paramsCopy = [...params]; // Create a copy\n const resolutionPromises = dependenciesToResolve.map(dependencyIdentifier =>\n this.loadInstance(dependencyIdentifier, paramsCopy, resolutionChain)\n );\n\n let finalInstance = Promise.all(resolutionPromises).catch((error)=>{\n console.error(`[IOC LoadFunc] Failed to resolve dependencies for function ${labelStr}:`, error);\n // Clean up potential partial storage\n if (storageType && this.isRegisteredAsFunction(funcLabel)) {\n if (storageType === 'singleton') this._functionStorageSingleton.delete(funcLabel);\n if (storageType === 'scoped') this._functionStorageScoped.delete(funcLabel);\n }\n throw error;\n }).then(async(resolvedArgs)=>{\n let instancePromise: Promise<any> | undefined;\n if (storageType && !this.hasInstance(funcLabel)) {\n instancePromise = (async () => {\n try {\n // console.log(`[IOC LoadFunc] Invoking ${labelStr} with ${resolvedArgs.length} args.`);\n const result = await ioc_func.apply(null, resolvedArgs); // Await in case function is async\n // Overwrite stored promise with actual result\n this.setInstance(funcLabel, result, storageType);\n // console.log(`[IOC LoadFunc] Stored actual ${storageType} instance for ${labelStr}`);\n return result;\n } catch (err: any) {\n console.error(`[IOC LoadFunc] Error executing function ${labelStr}: ${err.message}`, err.stack);\n // Clean up stored promise on failure\n if (storageType === 'singleton') this._functionStorageSingleton.delete(funcLabel);\n if (storageType === 'scoped') this._functionStorageScoped.delete(funcLabel);\n throw err;\n }\n })();\n // console.log(`[IOC LoadFunc] Storing promise for concurrent requests (${storageType}) for ${labelStr}`);\n this.setInstance(funcLabel, instancePromise, storageType);\n } else {\n // Transient or already resolved from storage check\n instancePromise = (async () => {\n try {\n // console.log(`[IOC LoadFunc] Invoking transient ${labelStr} with ${resolvedArgs.length} args.`);\n const result = await ioc_func.apply(null, resolvedArgs); // Await in case function is async\n // No storing for transient\n return result;\n } catch (err: any) {\n console.error(`[IOC LoadFunc] Error executing transient function ${labelStr}: ${err.message}`, err.stack);\n throw err;\n }\n })();\n }\n // --- End Invoke Function ---\n\n return await instancePromise; // Return the final (awaited) result\n });\n\n if(storageType && storageType !== 'transient'){\n this.setInstance(funcLabel, finalInstance, storageType); // Store the promise\n }\n\n return finalInstance;\n }\n}\n\n// Helper functions\nexport function isPromise(obj: any): obj is Promise<any> {\n // Simplified check - more robust check might be needed depending on environment\n return !!obj && typeof obj.then === 'function';\n}\n\nexport function createContainer(): IContainerClient & IContainerSetup {\n return new Container();\n}\n"],"mappings":"AAAA,OAAO;AAEP,SAAS,cAAc;AACvB,SAAS,iBAAiB;AAE1B,SAAS,0BAA0B,wBAAwB,yBAAyB,yBAAyB,+BAA+B;AAC5I;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,OACG;AACP,SAAS,eAAe,gBAAgB,sBAAsB;AAC9D,YAAY,uBAAuB;AACnC,SAAS,oBAAoB;AAOtB,MAAM,mBAAmB,OAAO,IAAI,sBAAsB;AAEjE,IAAK,mBAAL,kBAAKA,sBAAL;AACI,EAAAA,kBAAA,gBAAa;AACb,EAAAA,kBAAA,WAAQ;AAFP,SAAAA;AAAA,GAAA;AAQE,MAAM,UAAuD;AAAA,EAA7D;AAEH;AAAA,SAAQ,WAAuC,oBAAI,IAAI;AACvD,SAAQ,sBAA8D,oBAAI,IAAI;AAC9E,SAAQ,mBAA6D,oBAAI,IAAI;AAG7E;AAAA,SAAQ,4BAA2C,oBAAI,IAAI;AAC3D,SAAQ,yBAAwC,oBAAI,IAAI;AACxD,SAAQ,yBAA6C,oBAAI,IAAI;AAC7D,SAAQ,sBAA0C,oBAAI,IAAI;AAG1D;AAAA,SAAQ,iBAA0B;AAClC,SAAQ,yBAAiC;AAAA;AAAA;AAAA,EAGzC,cAAiB,iBAA4C,SAA2C;AAEpG,QAAI,OAAO,oBAAoB,cAAc,CAAC,gBAAgB,WAAW;AACpE,cAAQ,KAAK,0CAA0C,OAAO,eAAe,CAAC,EAAE;AAGhF;AAAA,IACL;AAGA,SAAK,iBAAiB,eAAe;AAGrC,SAAK,SAAS,IAAI,iBAAiB,mBAAsB;AAGzD,QAAI,WAAW,OAAO,KAAK,OAAO,EAAE,SAAS,GAAG;AAC5C,WAAK,iBAAiB,IAAI,iBAAiB,OAAO;AAAA,IAEtD,OAAO;AAAA,IAIP;AAAA,EACJ;AAAA,EAEA,iBAAmD,OAAY,MAAS,UAAqC,CAAC,GAAgB;AAC1H,SAAK,iBAAiB,KAAK;AAC3B,SAAK,SAAS,IAAI,OAAO,6BAA2B;AACpD,SAAK,oBAAoB,IAAI,OAAO,EAAE,UAAU,MAAM,QAAQ,CAAC;AAAA,EAEnE;AAAA;AAAA,EAGA,SAA0C,iBAA4C,SAAgC,CAAC,GAA2C;AAE9J,QAAI,OAAO,oBAAoB,cAAc,CAAC,gBAAgB,WAAW;AACpE,YAAM,IAAI,yBAAyB,0CAA0C,OAAO,eAAe,CAAC,EAAE;AAAA,IAC3G;AACA,WAAO,KAAK,aAAa,iBAAiB,MAAM;AAAA,EACpD;AAAA,EAEA,IAAqC,OAAY,QAA+B,CAAC,GAA2C;AAExH,WAAO,KAAK,aAAa,OAAO,KAAK;AAAA,EACzC;AAAA,EAEA,SAA6C;AACzC,UAAM,iBAAiB,gBAAgB;AAGvC,mBAAe,WAAW,IAAI,IAAI,KAAK,QAAQ;AAC/C,mBAAe,sBAAsB,IAAI,IAAI,KAAK,mBAAmB;AACrE,mBAAe,mBAAmB,IAAI,IAAI,KAAK,gBAAgB;AAG/D,mBAAe,4BAA4B,KAAK;AAChD,mBAAe,yBAAyB,KAAK;AAM7C,mBAAe,iBAAiB,KAAK;AACrC,mBAAe,yBAAyB,KAAK;AAG7C,WAAO;AAAA,EACX;AAAA;AAAA,EAGA,kBAAkB,SAAwB;AACtC,SAAK,iBAAiB;AACtB,QAAI,WAAW,CAAC,aAAa,iBAAiB,GAAG;AAE7C,qBAAe,iBAAwB;AAEvC,mBAAa,MAAM,KAAK,sBAAsB;AAAA,IAClD;AAAA,EACJ;AAAA,EAEA,mBAA4B;AACxB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,yBAAyB,SAAuB;AAC5C,SAAK,yBAAyB,KAAK,IAAI,GAAG,OAAO;AAAA,EACrD;AAAA,EAEA,UAAU,kBAAkC;AACxC,UAAM,YAAY,oBAAoB,KAAK;AAC3C,WAAO,kBAAkB,gBAAgB,SAAS;AAAA,EACtD;AAAA,EAEA,eAAsB;AAClB,WAAO,kBAAkB,aAAa;AAAA,EAC1C;AAAA,EAEA,cAAoB;AAChB,sBAAkB,eAAe;AAAA,EACrC;AAAA,EAEA,aAAa,UAAwB;AACjC,UAAM,OAAO,kBAAkB,mBAAmB;AAClD,UAAM,KAAK,QAAQ,IAAI;AACvB,OAAG,cAAc,UAAU,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,EAC5D;AAAA,EAEA,qBAA0B;AACtB,WAAO,kBAAkB,mBAAmB;AAAA,EAChD;AAAA;AAAA,EAGQ,iBAAiB,OAAkB;AACvC,SAAK,SAAS,OAAO,KAAK;AAC1B,SAAK,oBAAoB,OAAO,KAAK;AAErC,QAAI,OAAO,UAAU,YAAY;AAC7B,WAAK,iBAAiB,OAAO,KAAK;AAAA,IACtC;AAAA,EACJ;AAAA;AAAA,EAGQ,oBAAoB,OAAqB;AAC7C,WAAO,KAAK,SAAS,IAAI,KAAK,MAAM;AAAA,EACxC;AAAA;AAAA,EAGS,uBAAuB,OAAqB;AAChD,WAAO,KAAK,SAAS,IAAI,KAAK,MAAM;AAAA,EACxC;AAAA,EAGO,YAAY,OAAqB;AACrC,UAAM,cAAc,KAAK,eAAe,KAAK;AAE7C,QAAI,CAAC,aAAa;AAEd,aAAO;AAAA,IACX;AAGA,UAAM,UAAU,KAAK,YAAY,KAAK;AAEtC,QAAI,SAAS;AACT,aAAO,gBAAgB,cACjB,KAAK,uBAAuB,IAAI,KAAK,IACrC,KAAK,oBAAoB,IAAI,KAAK;AAAA,IAC5C,OAAO;AACH,aAAO,gBAAgB,cACjB,KAAK,0BAA0B,IAAI,KAAK,IACxC,KAAK,uBAAuB,IAAI,KAAK;AAAA,IAC/C;AAAA,EACJ;AAAA;AAAA,EAGS,YAAY,OAAqB;AACrC,QAAI,KAAK,oBAAoB,KAAK,GAAG;AACjC,aAAO;AAAA,IACX;AAEA,QAAI,OAAO,UAAU,cAAc,MAAM,aAAa,CAAC,KAAK,uBAAuB,KAAK,GAAG;AACtF,aAAO,oBAAoB,KAAK,MAAM;AAAA,IAC3C;AACA,WAAO;AAAA,EACX;AAAA,EAEO,YAAY,OAAiB;AACjC,UAAM,cAAc,KAAK,eAAe,KAAK;AAE5C,QAAI,CAAC,aAAa;AAEd,cAAQ,MAAM,oEAAoE,OAAO,KAAK,CAAC,EAAE;AACjG,YAAM,IAAI,wBAAwB;AAAA,IACtC;AAED,UAAM,UAAU,KAAK,YAAY,KAAK;AAEtC,QAAI,SAAS;AACT,aAAO,gBAAgB,cACjB,KAAK,uBAAuB,IAAI,KAAK,IACrC,KAAK,oBAAoB,IAAI,KAAK;AAAA,IAC5C,OAAO;AACH,aAAO,gBAAgB,cACjB,KAAK,0BAA0B,IAAI,KAAK,IACxC,KAAK,uBAAuB,IAAI,KAAK;AAAA,IAC/C;AAAA,EACJ;AAAA,EAEQ,YAAY,OAAY,UAAe,aAAiC;AAC5E,UAAM,UAAU,KAAK,YAAY,KAAK;AAEtC,QAAI,SAAS;AACT,UAAI,gBAAgB,aAAa;AAC7B,aAAK,uBAAuB,IAAI,OAAO,QAAQ;AAAA,MACnD,WAAW,eAAe,UAAS;AAC/B,aAAK,oBAAoB,IAAI,OAAO,QAAQ;AAAA,MAChD;AAAA,IACJ,OAAO;AACH,UAAI,gBAAgB,aAAa;AAC7B,aAAK,0BAA0B,IAAI,OAAO,QAAQ;AAAA,MACtD,WAAU,gBAAgB,UAAS;AAC/B,aAAK,uBAAuB,IAAI,OAAO,QAAQ;AAAA,MACnD;AAAA,IACJ;AAAA,EACJ;AAAA,EAEQ,eAAe,OAAyB;AAC5C,QAAI;AACJ,QAAI;AACJ,UAAM,mBAAmB,OAAO,UAAU,cAAc,MAAM;AAG9D,QAAI,KAAK,oBAAoB,KAAK,GAAG;AACjC,qBAAe,KAAK,iBAAiB,IAAI,KAAK,GAAG;AAAA,IACrD,WAAW,KAAK,uBAAuB,KAAK,GAAG;AAC3C,qBAAe,KAAK,oBAAoB,IAAI,KAAK,GAAG,SAAS;AAAA,IACjE;AAGA,QAAI,oBAAoB,CAAC,KAAK,uBAAuB,KAAK,GAAG;AACzD,uBAAiB,SAAS,KAAK;AAAA,IACnC;AAGA,UAAM,aAAa,gBAAgB,kBAAkB,OAAO;AAE5D,QAAI,eAAe,OAAO,WAAW;AACjC,aAAO;AAAA,IACX,WAAW,eAAe,OAAO,QAAQ;AACrC,aAAO;AAAA,IACX,OAAK;AACD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA,EAGU,aACN,OACA,SAAgC,CAAC,GACjC,kBAA4B,CAAC,GAC7B,eACG;AAGH,UAAM,kBAAmB,OAAO,UAAU,cAAc,MAAM,OAAQ,MAAM,OAAO,OAAO,KAAK;AAC/F,QAAI,gBAAgB,SAAS,eAAe,GAAG;AAC3C,cAAQ,MAAM,oDAAoD,CAAC,GAAG,iBAAiB,eAAe,EAAE,KAAK,MAAM,CAAC,EAAE;AACtH,YAAM,IAAI,wBAAwB,CAAC,GAAG,iBAAiB,eAAe,CAAC;AAAA,IAC3E;AACA,UAAM,sBAAsB,CAAC,GAAG,iBAAiB,eAAe;AAIhE,QAAI,iBAAiB,WAAW;AAC5B,UAAI;AAEA,eAAO,KAAK,sBAAsB,OAAO,CAAC,GAAG,MAAM,CAAC;AAAA,MACxD,SAAS,GAAG;AAER,cAAM;AAAA,MACV;AAAA,IACJ;AAIA,QAAI,UAAU,kBAAkB;AAC5B,aAAO;AAAA,IACX;AAIA,QAAI,KAAK,oBAAoB,KAAK,GAAG;AAEjC,aAAO,KAAK,kBAAkB,OAAO,QAAQ,qBAAqB,aAAa;AAAA,IACnF;AACA,QAAI,KAAK,uBAAuB,KAAK,GAAG;AAEpC,aAAO,KAAK,qBAAqB,OAAO,QAAQ,mBAAmB;AAAA,IACvE;AAKA,QAAI,OAAO,UAAU,cAAc,MAAM,WAAW;AAChD,YAAM,mBAAmB,oBAAoB,KAAK;AAClD,UAAI,qBAAqB,MAAM;AAG3B,YAAI,CAAC,KAAK,SAAS,IAAI,KAAK,GAAG;AAC1B,eAAK,SAAS,IAAI,OAAO,mBAAsB;AAAA,QAEpD;AAEA,eAAO,KAAK,kBAAkB,OAAO,QAAQ,qBAAqB,aAAa;AAAA,MACnF;AAAA,IACJ;AAKA,YAAQ,MAAM,mEAAmE,eAAe,EAAE;AAClG,UAAM,IAAI,wBAAwB,eAAe;AAAA,EACrD;AAAA,EAGQ,sBAAsB,OAAkB,QAAoC;AAEhF,UAAM,iBAAiB,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,KAAK,CAAC;AAC3E,QAAI,CAAC,gBAAgB;AAEjB,YAAM,IAAI,uBAAuB,MAAM,SAAS,CAAC;AAAA,IACrD;AAEA,WAAO,eAAe;AAAA,EAC1B;AAAA,EAEQ,kBACJ,iBACA,QACA,iBACA,eACG;AACH,UAAM,cAAc,KAAK,eAAe,eAAe;AACvD,UAAM,YAAY,gBAAgB,QAAQ;AAG1C,QAAI,eAAe,KAAK,YAAY,eAAe,GAAG;AAClD,YAAM,WAAW,KAAK,YAAY,eAAe;AAEjD,aAAO;AAAA,IACX;AAIA,UAAM,gBAAgB,KAAK,iBAAiB,IAAI,eAAe;AAC/D,QAAI;AAEJ,QAAI,eAAe,SAAS,MAAM,QAAQ,cAAc,KAAK,GAAG;AAC5D,8BAAwB,cAAc;AAAA,IAE1C,OAAO;AAEH,8BAAwB,wBAAwB,eAAe;AAAA,IAEnE;AAIA,QAAI;AACJ,QAAI,KAAK,gBAAgB;AACrB,sBAAgB,eAAe;AAAA,IACnC;AAGA,UAAM,aAAa,CAAC,GAAG,MAAM;AAC7B,UAAM,uBAA8B,CAAC;AACrC,QAAI,qBAAqB;AAGzB,eAAW,wBAAwB,uBAAuB;AACtD,YAAM,WAAW,KAAK,aAAa,sBAAsB,YAAY,iBAAiB,aAAa;AACnG,2BAAqB,KAAK,QAAQ;AAClC,UAAI,UAAU,QAAQ,GAAG;AACrB,6BAAqB;AAAA,MACzB;AAAA,IACJ;AAGA,UAAM,cAAc,CAAC,SAAqB;AACtC,UAAI;AACA,cAAM,WAAW,IAAI,gBAAgB,GAAG,IAAI;AAG5C,YAAI,KAAK,kBAAkB,kBAAkB,QAAW;AACpD,iBAAO,cAAc,UAAU,WAAW,eAAe,aAAa;AAAA,QAC1E;AACA,eAAO;AAAA,MACX,SAAS,KAAU;AACf,gBAAQ,MAAM,iDAAiD,SAAS,KAAK,IAAI,OAAO,IAAI,IAAI,KAAK;AACrG,cAAM;AAAA,MACV;AAAA,IACJ;AAGA,QAAI,CAAC,oBAAoB;AACrB,YAAM,WAAW,YAAY,oBAAoB;AAGjD,UAAI,eAAe,gBAAgB,aAAa;AAC5C,aAAK,YAAY,iBAAiB,UAAU,WAAW;AAAA,MAC3D;AACA,aAAO;AAAA,IACX;AAGA,UAAM,gBAAgB,QAAQ,IAAI,oBAAoB,EACjD,KAAK,CAAC,SAAS;AACZ,YAAM,WAAW,YAAY,IAAI;AAGjC,UAAI,eAAe,gBAAgB,aAAa;AAC5C,aAAK,YAAY,iBAAiB,UAAU,WAAW;AAAA,MAC3D;AACA,aAAO;AAAA,IACX,CAAC,EACA,MAAM,CAAC,UAAU;AACd,cAAQ,MAAM,kEAAkE,SAAS,KAAK,KAAK;AAEnG,UAAI,eAAe,KAAK,oBAAoB,eAAe,GAAG;AAC1D,YAAI,gBAAgB,YAAa,MAAK,uBAAuB,OAAO,eAAe;AACnF,YAAI,gBAAgB,SAAU,MAAK,oBAAoB,OAAO,eAAe;AAAA,MACjF;AACA,YAAM;AAAA,IACV,CAAC;AAGL,QAAI,eAAe,gBAAgB,aAAa;AAC5C,WAAK,YAAY,iBAAiB,eAAe,WAAW;AAAA,IAChE;AAEA,WAAO;AAAA,EACX;AAAA,EAEQ,qBACJ,WACA,QACA,iBACY;AACZ,UAAM,iBAAiB,KAAK,oBAAoB,IAAI,SAAS;AAC7D,UAAM,cAAc,KAAK,eAAe,SAAS;AACjD,UAAM,WAAW,OAAO,SAAS;AAGjC,QAAI,eAAe,KAAK,YAAY,SAAS,GAAG;AAC5C,YAAM,WAAW,KAAK,YAAY,SAAS;AAE3C,aAAO;AAAA,IACX;AAGA,UAAM,WAAW,eAAe;AAChC,UAAM,UAAU,eAAe;AAC/B,UAAM,wBAA+B,SAAS,SAAS,CAAC;AAGxD,UAAM,aAAa,CAAC,GAAG,MAAM;AAC7B,UAAM,qBAAqB,sBAAsB;AAAA,MAAI,0BACjD,KAAK,aAAa,sBAAsB,YAAY,eAAe;AAAA,IACvE;AAEA,QAAI,gBAAgB,QAAQ,IAAI,kBAAkB,EAAE,MAAM,CAAC,UAAQ;AAC/D,cAAQ,MAAM,8DAA8D,QAAQ,KAAK,KAAK;AAE/F,UAAI,eAAe,KAAK,uBAAuB,SAAS,GAAG;AACtD,YAAI,gBAAgB,YAAa,MAAK,0BAA0B,OAAO,SAAS;AAChF,YAAI,gBAAgB,SAAU,MAAK,uBAAuB,OAAO,SAAS;AAAA,MAC/E;AACA,YAAM;AAAA,IACT,CAAC,EAAE,KAAK,OAAM,iBAAe;AACzB,UAAI;AACR,UAAI,eAAe,CAAC,KAAK,YAAY,SAAS,GAAG;AAC5C,2BAAmB,YAAY;AAC3B,cAAI;AAEA,kBAAM,SAAS,MAAM,SAAS,MAAM,MAAM,YAAY;AAEtD,iBAAK,YAAY,WAAW,QAAQ,WAAW;AAE/C,mBAAO;AAAA,UACX,SAAS,KAAU;AACf,oBAAQ,MAAM,2CAA2C,QAAQ,KAAK,IAAI,OAAO,IAAI,IAAI,KAAK;AAE9F,gBAAI,gBAAgB,YAAa,MAAK,0BAA0B,OAAO,SAAS;AAChF,gBAAI,gBAAgB,SAAU,MAAK,uBAAuB,OAAO,SAAS;AAC1E,kBAAM;AAAA,UACV;AAAA,QACJ,GAAG;AAEH,aAAK,YAAY,WAAW,iBAAiB,WAAW;AAAA,MAC7D,OAAO;AAEF,2BAAmB,YAAY;AAC1B,cAAI;AAEA,kBAAM,SAAS,MAAM,SAAS,MAAM,MAAM,YAAY;AAEtD,mBAAO;AAAA,UACX,SAAS,KAAU;AACf,oBAAQ,MAAM,qDAAqD,QAAQ,KAAK,IAAI,OAAO,IAAI,IAAI,KAAK;AACxG,kBAAM;AAAA,UACV;AAAA,QACL,GAAG;AAAA,MACR;AAGA,aAAO,MAAM;AAAA,IACb,CAAC;AAED,QAAG,eAAe,gBAAgB,aAAY;AAC1C,WAAK,YAAY,WAAW,eAAe,WAAW;AAAA,IAC1D;AAEA,WAAO;AAAA,EACX;AACJ;AAGO,SAAS,UAAU,KAA+B;AAErD,SAAO,CAAC,CAAC,OAAO,OAAO,IAAI,SAAS;AACxC;AAEO,SAAS,kBAAsD;AAClE,SAAO,IAAI,UAAU;AACzB;","names":["ContainerRouting"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../framework/interface/Container.ts"],"sourcesContent":["import type { ParameterValue } from \"../implementation/Parameter.cjs\"\r\nimport type { LoadAs } from \"../implementation/LoadAs.cjs\"\r\n\r\nexport interface IContainerClient {\r\n instance<T,
|
|
1
|
+
{"version":3,"sources":["../../../framework/interface/Container.ts"],"sourcesContent":["import type { ParameterValue } from \"../implementation/Parameter.cjs\"\r\nimport type { LoadAs } from \"../implementation/LoadAs.cjs\"\r\n\r\nexport interface IContainerClient {\r\n instance<T, Sync extends boolean = false>(classDefinition: new (...args: any[]) => T,params?:ParameterValue<any>[]): Sync extends true ? T : Promise<T> | T\r\n get<T, Sync extends boolean = false>(label:any,param?:ParameterValue<any>[]):Sync extends true ? T : Promise<T> | T\r\n extend(): IContainerClient & IContainerSetup\r\n}\r\n\r\n\r\nexport interface IContainerSetup{\r\n registerClass<T, Args extends any[]>(classDefinition: { new (...args: Args): T }, options?: Partial<ContainerOptions>): void\r\n registerFunction<T extends (...arg:any[])=>any>(label:any,func: T, options?: ContainerOptions): void\r\n\r\n // Tracing API\r\n setTracingEnabled(enabled: boolean): void\r\n isTracingEnabled(): boolean\r\n setTraceRetentionMinutes(minutes: number): void\r\n getTraces(retentionMinutes?: number): any[]\r\n getAllTraces(): any[]\r\n clearTraces(): void\r\n exportTraces(filepath: string): void\r\n getTraceStatistics(): any\r\n}\r\n\r\n\r\nexport type IContainer = IContainerClient & IContainerSetup\r\n\r\nexport type ContainerOptions = {\r\n param?: any[]\r\n loadAs?: LoadAs\r\n}\r\n\r\n\r\nexport interface IContainerFunctionDefinition{\r\n function:Function\r\n options:Partial<ContainerOptions>\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
|
|
@@ -2,8 +2,8 @@ import { ParameterValue } from '../implementation/Parameter.cjs';
|
|
|
2
2
|
import { LoadAs } from '../implementation/LoadAs.cjs';
|
|
3
3
|
|
|
4
4
|
interface IContainerClient {
|
|
5
|
-
instance<T,
|
|
6
|
-
get<T>(label: any, param?: ParameterValue<any>[]): Promise<T> | T;
|
|
5
|
+
instance<T, Sync extends boolean = false>(classDefinition: new (...args: any[]) => T, params?: ParameterValue<any>[]): Sync extends true ? T : Promise<T> | T;
|
|
6
|
+
get<T, Sync extends boolean = false>(label: any, param?: ParameterValue<any>[]): Sync extends true ? T : Promise<T> | T;
|
|
7
7
|
extend(): IContainerClient & IContainerSetup;
|
|
8
8
|
}
|
|
9
9
|
interface IContainerSetup {
|
|
@@ -2,8 +2,8 @@ import { ParameterValue } from '../implementation/Parameter.js';
|
|
|
2
2
|
import { LoadAs } from '../implementation/LoadAs.js';
|
|
3
3
|
|
|
4
4
|
interface IContainerClient {
|
|
5
|
-
instance<T,
|
|
6
|
-
get<T>(label: any, param?: ParameterValue<any>[]): Promise<T> | T;
|
|
5
|
+
instance<T, Sync extends boolean = false>(classDefinition: new (...args: any[]) => T, params?: ParameterValue<any>[]): Sync extends true ? T : Promise<T> | T;
|
|
6
|
+
get<T, Sync extends boolean = false>(label: any, param?: ParameterValue<any>[]): Sync extends true ? T : Promise<T> | T;
|
|
7
7
|
extend(): IContainerClient & IContainerSetup;
|
|
8
8
|
}
|
|
9
9
|
interface IContainerSetup {
|
package/dist/index.cjs
CHANGED
|
@@ -28,6 +28,8 @@ __export(index_exports, {
|
|
|
28
28
|
NotAClassDefinitionError: () => import_ContainerErrors.NotAClassDefinitionError,
|
|
29
29
|
Parameter: () => import_Parameter.Parameter,
|
|
30
30
|
ParameterNotFoundError: () => import_ContainerErrors.ParameterNotFoundError,
|
|
31
|
+
Provider: () => import_decorators.Provider,
|
|
32
|
+
SCOPED_CONTAINER: () => import_Container.SCOPED_CONTAINER,
|
|
31
33
|
createContainer: () => import_Container3.createContainer,
|
|
32
34
|
default: () => index_default
|
|
33
35
|
});
|
|
@@ -53,6 +55,8 @@ var index_default = import_Container.createContainer;
|
|
|
53
55
|
NotAClassDefinitionError,
|
|
54
56
|
Parameter,
|
|
55
57
|
ParameterNotFoundError,
|
|
58
|
+
Provider,
|
|
59
|
+
SCOPED_CONTAINER,
|
|
56
60
|
createContainer
|
|
57
61
|
});
|
|
58
62
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../index.ts"],"sourcesContent":["import 'reflect-metadata';\nimport { createContainer } from \"./framework/implementation/Container.cjs\"\nimport { Container } from \"./framework/implementation/Container.cjs\"\nimport { LoadAs } from \"./framework/implementation/LoadAs.cjs\"\nimport { Parameter } from \"./framework/implementation/Parameter.cjs\"\nimport type { IContainer, IContainerClient, IContainerSetup } from \"./framework/interface/Container.cjs\"\nimport { NotAClassDefinitionError, ParameterNotFoundError, DependencyNotFoundError, InstanceNotCreatedError, CircularDependencyError } from \"./framework/errors/ContainerErrors.cjs\"\nimport { Component, Inject } from \"./framework/decorators/index.cjs\"\n\nexport type { IContainer, IContainerClient, IContainerSetup }\nexport { LoadAs }\nexport { Parameter }\nexport { Container }\nexport { NotAClassDefinitionError, ParameterNotFoundError, DependencyNotFoundError, InstanceNotCreatedError, CircularDependencyError }\nexport { Component, Inject }\nexport { createContainer } from \"./framework/implementation/Container.cjs\"\nexport default createContainer\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,8BAAO;AACP,
|
|
1
|
+
{"version":3,"sources":["../index.ts"],"sourcesContent":["import 'reflect-metadata';\nimport { createContainer, SCOPED_CONTAINER } from \"./framework/implementation/Container.cjs\"\nimport { Container } from \"./framework/implementation/Container.cjs\"\nimport { LoadAs } from \"./framework/implementation/LoadAs.cjs\"\nimport { Parameter } from \"./framework/implementation/Parameter.cjs\"\nimport type { IContainer, IContainerClient, IContainerSetup } from \"./framework/interface/Container.cjs\"\nimport { NotAClassDefinitionError, ParameterNotFoundError, DependencyNotFoundError, InstanceNotCreatedError, CircularDependencyError } from \"./framework/errors/ContainerErrors.cjs\"\nimport { Component, Provider, Inject } from \"./framework/decorators/index.cjs\"\n\nexport type { IContainer, IContainerClient, IContainerSetup }\nexport { LoadAs }\nexport { Parameter }\nexport { Container }\nexport { NotAClassDefinitionError, ParameterNotFoundError, DependencyNotFoundError, InstanceNotCreatedError, CircularDependencyError }\nexport { Component, Provider, Inject }\nexport { SCOPED_CONTAINER }\nexport { createContainer } from \"./framework/implementation/Container.cjs\"\nexport default createContainer\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,8BAAO;AACP,uBAAkD;AAClD,IAAAA,oBAA0B;AAC1B,oBAAuB;AACvB,uBAA0B;AAE1B,6BAA4I;AAC5I,wBAA4C;AAS5C,IAAAA,oBAAgC;AAChC,IAAO,gBAAQ;","names":["import_Container"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { createContainer } from './framework/implementation/Container.cjs';
|
|
2
|
-
export { Container } from './framework/implementation/Container.cjs';
|
|
2
|
+
export { Container, SCOPED_CONTAINER } from './framework/implementation/Container.cjs';
|
|
3
3
|
export { LoadAs } from './framework/implementation/LoadAs.cjs';
|
|
4
4
|
export { Parameter } from './framework/implementation/Parameter.cjs';
|
|
5
5
|
export { IContainer, IContainerClient, IContainerSetup } from './framework/interface/Container.cjs';
|
|
6
6
|
export { CircularDependencyError, DependencyNotFoundError, InstanceNotCreatedError, NotAClassDefinitionError, ParameterNotFoundError } from './framework/errors/ContainerErrors.cjs';
|
|
7
7
|
export { Component } from './framework/decorators/Component.cjs';
|
|
8
|
+
export { Provider } from './framework/decorators/Provider.cjs';
|
|
8
9
|
export { Inject } from './framework/decorators/Inject.cjs';
|
|
9
10
|
|
|
10
11
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { createContainer } from './framework/implementation/Container.js';
|
|
2
|
-
export { Container } from './framework/implementation/Container.js';
|
|
2
|
+
export { Container, SCOPED_CONTAINER } from './framework/implementation/Container.js';
|
|
3
3
|
export { LoadAs } from './framework/implementation/LoadAs.js';
|
|
4
4
|
export { Parameter } from './framework/implementation/Parameter.js';
|
|
5
5
|
export { IContainer, IContainerClient, IContainerSetup } from './framework/interface/Container.js';
|
|
6
6
|
export { CircularDependencyError, DependencyNotFoundError, InstanceNotCreatedError, NotAClassDefinitionError, ParameterNotFoundError } from './framework/errors/ContainerErrors.js';
|
|
7
7
|
export { Component } from './framework/decorators/Component.js';
|
|
8
|
+
export { Provider } from './framework/decorators/Provider.js';
|
|
8
9
|
export { Inject } from './framework/decorators/Inject.js';
|
|
9
10
|
|
|
10
11
|
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import "reflect-metadata";
|
|
2
|
-
import { createContainer } from "./framework/implementation/Container.js";
|
|
2
|
+
import { createContainer, SCOPED_CONTAINER } from "./framework/implementation/Container.js";
|
|
3
3
|
import { Container } from "./framework/implementation/Container.js";
|
|
4
4
|
import { LoadAs } from "./framework/implementation/LoadAs.js";
|
|
5
5
|
import { Parameter } from "./framework/implementation/Parameter.js";
|
|
6
6
|
import { NotAClassDefinitionError, ParameterNotFoundError, DependencyNotFoundError, InstanceNotCreatedError, CircularDependencyError } from "./framework/errors/ContainerErrors.js";
|
|
7
|
-
import { Component, Inject } from "./framework/decorators/index.js";
|
|
7
|
+
import { Component, Provider, Inject } from "./framework/decorators/index.js";
|
|
8
8
|
import { createContainer as createContainer2 } from "./framework/implementation/Container.js";
|
|
9
9
|
var index_default = createContainer;
|
|
10
10
|
export {
|
|
@@ -18,6 +18,8 @@ export {
|
|
|
18
18
|
NotAClassDefinitionError,
|
|
19
19
|
Parameter,
|
|
20
20
|
ParameterNotFoundError,
|
|
21
|
+
Provider,
|
|
22
|
+
SCOPED_CONTAINER,
|
|
21
23
|
createContainer2 as createContainer,
|
|
22
24
|
index_default as default
|
|
23
25
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../index.ts"],"sourcesContent":["import 'reflect-metadata';\nimport { createContainer } from \"./framework/implementation/Container.js\"\nimport { Container } from \"./framework/implementation/Container.js\"\nimport { LoadAs } from \"./framework/implementation/LoadAs.js\"\nimport { Parameter } from \"./framework/implementation/Parameter.js\"\nimport type { IContainer, IContainerClient, IContainerSetup } from \"./framework/interface/Container.js\"\nimport { NotAClassDefinitionError, ParameterNotFoundError, DependencyNotFoundError, InstanceNotCreatedError, CircularDependencyError } from \"./framework/errors/ContainerErrors.js\"\nimport { Component, Inject } from \"./framework/decorators/index.js\"\n\nexport type { IContainer, IContainerClient, IContainerSetup }\nexport { LoadAs }\nexport { Parameter }\nexport { Container }\nexport { NotAClassDefinitionError, ParameterNotFoundError, DependencyNotFoundError, InstanceNotCreatedError, CircularDependencyError }\nexport { Component, Inject }\nexport { createContainer } from \"./framework/implementation/Container.js\"\nexport default createContainer\n"],"mappings":"AAAA,OAAO;AACP,SAAS,
|
|
1
|
+
{"version":3,"sources":["../index.ts"],"sourcesContent":["import 'reflect-metadata';\nimport { createContainer, SCOPED_CONTAINER } from \"./framework/implementation/Container.js\"\nimport { Container } from \"./framework/implementation/Container.js\"\nimport { LoadAs } from \"./framework/implementation/LoadAs.js\"\nimport { Parameter } from \"./framework/implementation/Parameter.js\"\nimport type { IContainer, IContainerClient, IContainerSetup } from \"./framework/interface/Container.js\"\nimport { NotAClassDefinitionError, ParameterNotFoundError, DependencyNotFoundError, InstanceNotCreatedError, CircularDependencyError } from \"./framework/errors/ContainerErrors.js\"\nimport { Component, Provider, Inject } from \"./framework/decorators/index.js\"\n\nexport type { IContainer, IContainerClient, IContainerSetup }\nexport { LoadAs }\nexport { Parameter }\nexport { Container }\nexport { NotAClassDefinitionError, ParameterNotFoundError, DependencyNotFoundError, InstanceNotCreatedError, CircularDependencyError }\nexport { Component, Provider, Inject }\nexport { SCOPED_CONTAINER }\nexport { createContainer } from \"./framework/implementation/Container.js\"\nexport default createContainer\n"],"mappings":"AAAA,OAAO;AACP,SAAS,iBAAiB,wBAAwB;AAClD,SAAS,iBAAiB;AAC1B,SAAS,cAAc;AACvB,SAAS,iBAAiB;AAE1B,SAAS,0BAA0B,wBAAwB,yBAAyB,yBAAyB,+BAA+B;AAC5I,SAAS,WAAW,UAAU,cAAc;AAS5C,SAAS,mBAAAA,wBAAuB;AAChC,IAAO,gBAAQ;","names":["createContainer"]}
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -10,9 +10,11 @@ A lightweight, flexible Inversion of Control (IoC) container for Node.js and Typ
|
|
|
10
10
|
- **Class & Function Registration**: Register both classes and functions as dependencies
|
|
11
11
|
- **Parameter Injection**: Inject parameter values at resolution time
|
|
12
12
|
- **Container Extension**: Create child containers that inherit parent registrations
|
|
13
|
-
- **
|
|
13
|
+
- **Container Self-Injection**: Use the provider pattern with `SCOPED_CONTAINER` for dynamic service creation and factories
|
|
14
|
+
- **Decorator Support**: Use @Component, @Provider, and @Inject decorators for clean, declarative DI
|
|
14
15
|
- **TypeScript Support**: Built with full TypeScript support for type safety
|
|
15
|
-
- **
|
|
16
|
+
- **Sync-First Resolution**: Synchronous resolution when all dependencies are sync, with async fallback when needed
|
|
17
|
+
- **Type-Safe Sync Mode**: Generic `Sync` parameter on `get` and `instance` for compile-time type narrowing
|
|
16
18
|
- **Method Call Tracing**: Automatic tracing of method calls with performance metrics and dependency hierarchies
|
|
17
19
|
- **Trace Analytics**: Export and analyze traces, track statistics, and monitor dependency interactions
|
|
18
20
|
- **Lightweight**: Small footprint with minimal external dependencies
|
|
@@ -395,6 +397,21 @@ Manual registration options take precedence over decorators:
|
|
|
395
397
|
|
|
396
398
|
This allows you to change behavior at registration time without modifying the decorated class.
|
|
397
399
|
|
|
400
|
+
### Sync Resolution
|
|
401
|
+
|
|
402
|
+
By default, `get` and `instance` return `Promise<T> | T`. When your entire dependency graph is synchronous (no async factory functions), the container resolves synchronously. If you know at the call site that resolution will be sync, pass `true` as the second generic parameter to get a narrowed `T` return type:
|
|
403
|
+
|
|
404
|
+
```typescript
|
|
405
|
+
// Default — returns Promise<T> | T
|
|
406
|
+
const service = container.instance(UserService);
|
|
407
|
+
|
|
408
|
+
// When you know the dependency graph is sync — returns T
|
|
409
|
+
const service = container.instance<UserService, true>(UserService);
|
|
410
|
+
const logger = container.get<Logger, true>(Logger);
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
This is purely a compile-time hint — no runtime behavior changes. If a dependency turns out to be async at runtime, you'll get a Promise back regardless of the type annotation.
|
|
414
|
+
|
|
398
415
|
### Extending Containers
|
|
399
416
|
|
|
400
417
|
You can create a child container that inherits all the registrations from the parent but allows overriding:
|
|
@@ -414,6 +431,76 @@ childContainer.registerClass(Database, { /* different configuration */ });
|
|
|
414
431
|
// Child container uses the new registration
|
|
415
432
|
```
|
|
416
433
|
|
|
434
|
+
### Provider Pattern with SCOPED_CONTAINER
|
|
435
|
+
|
|
436
|
+
The `@Provider` decorator creates factory classes that can dynamically resolve dependencies at runtime. Use `@Inject(SCOPED_CONTAINER)` to inject the container itself, enabling polymorphic service creation based on runtime conditions.
|
|
437
|
+
|
|
438
|
+
```typescript
|
|
439
|
+
import createContainer, { Provider, Inject, SCOPED_CONTAINER, IContainer, Component } from "@noego/ioc";
|
|
440
|
+
|
|
441
|
+
// Define payment processor implementations
|
|
442
|
+
interface PaymentProcessor {
|
|
443
|
+
process(amount: number): Promise<string>;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
@Component()
|
|
447
|
+
class StripeProcessor implements PaymentProcessor {
|
|
448
|
+
async process(amount: number) {
|
|
449
|
+
return `Processed $${amount} via Stripe`;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
@Component()
|
|
454
|
+
class PayPalProcessor implements PaymentProcessor {
|
|
455
|
+
async process(amount: number) {
|
|
456
|
+
return `Processed $${amount} via PayPal`;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// Provider that creates the right processor at runtime
|
|
461
|
+
@Provider()
|
|
462
|
+
class PaymentProcessorFactory {
|
|
463
|
+
constructor(
|
|
464
|
+
@Inject(SCOPED_CONTAINER) private container: IContainer
|
|
465
|
+
) {}
|
|
466
|
+
|
|
467
|
+
async getProcessor(type: 'stripe' | 'paypal'): Promise<PaymentProcessor> {
|
|
468
|
+
switch (type) {
|
|
469
|
+
case 'stripe':
|
|
470
|
+
return this.container.instance(StripeProcessor);
|
|
471
|
+
case 'paypal':
|
|
472
|
+
return this.container.instance(PayPalProcessor);
|
|
473
|
+
default:
|
|
474
|
+
throw new Error(`Unknown payment processor: ${type}`);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// Service that injects the factory and changes behavior at runtime
|
|
480
|
+
@Component()
|
|
481
|
+
class OrderService {
|
|
482
|
+
constructor(private paymentFactory: PaymentProcessorFactory) {}
|
|
483
|
+
|
|
484
|
+
async processOrder(amount: number, paymentMethod: 'stripe' | 'paypal') {
|
|
485
|
+
// Get the right processor based on runtime parameter
|
|
486
|
+
const processor = await this.paymentFactory.getProcessor(paymentMethod);
|
|
487
|
+
|
|
488
|
+
// Behavior changes based on what the user selected
|
|
489
|
+
const result = await processor.process(amount);
|
|
490
|
+
return { success: true, message: result };
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// Usage - behavior determined at runtime
|
|
495
|
+
const container = createContainer();
|
|
496
|
+
const orderService = await container.instance(OrderService);
|
|
497
|
+
|
|
498
|
+
await orderService.processOrder(100, 'stripe'); // Uses Stripe
|
|
499
|
+
await orderService.processOrder(200, 'paypal'); // Uses PayPal
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
This pattern is ideal for plugin systems, multi-tenancy, polymorphic services, and any scenario where you need to select implementations based on runtime data. The `@Provider` decorator defaults to `Scoped` lifetime, making instances scoped per container context.
|
|
503
|
+
|
|
417
504
|
### Method Call Tracing and Monitoring
|
|
418
505
|
|
|
419
506
|
The container supports automatic tracing of method calls on resolved instances. This is useful for debugging, monitoring, and understanding dependency interactions in your application.
|
|
@@ -539,8 +626,8 @@ await service.getUsers();
|
|
|
539
626
|
- `createContainer()`: Creates a new IoC container
|
|
540
627
|
- `registerClass<T>(classDefinition, options?)`: Register a class
|
|
541
628
|
- `registerFunction(label, function, options?)`: Register a function
|
|
542
|
-
- `instance<T>(classDefinition, params?)`: Resolve a class instance
|
|
543
|
-
- `get<T>(label, params?)`: Resolve a dependency by key
|
|
629
|
+
- `instance<T, Sync>(classDefinition, params?)`: Resolve a class instance. Pass `Sync = true` for sync type narrowing
|
|
630
|
+
- `get<T, Sync>(label, params?)`: Resolve a dependency by key. Pass `Sync = true` for sync type narrowing
|
|
544
631
|
- `extend()`: Create a child container
|
|
545
632
|
- `setTracingEnabled(enabled: boolean)`: Enable/disable method call tracing
|
|
546
633
|
- `isTracingEnabled(): boolean`: Check if tracing is enabled
|
|
@@ -553,7 +640,8 @@ await service.getUsers();
|
|
|
553
640
|
|
|
554
641
|
### Decorators
|
|
555
642
|
|
|
556
|
-
- `@Component(options?)`: Mark a class as container-managed
|
|
643
|
+
- `@Component(options?)`: Mark a class as container-managed (defaults to Transient scope)
|
|
644
|
+
- `@Provider(options?)`: Mark a class as a provider (defaults to Scoped scope, ideal for factories)
|
|
557
645
|
- `@Inject(token)`: Specify a token for a constructor parameter
|
|
558
646
|
|
|
559
647
|
### Options
|
|
@@ -580,6 +668,10 @@ enum LoadAs {
|
|
|
580
668
|
- `Parameter.create()`: Create a new parameter
|
|
581
669
|
- `parameter.value(value)`: Create a parameter value
|
|
582
670
|
|
|
671
|
+
### Injectable Tokens
|
|
672
|
+
|
|
673
|
+
- `SCOPED_CONTAINER`: A special injection token that resolves to the current container instance. Use this in parameter arrays or with `@Inject` to enable the provider pattern and dynamic dependency resolution.
|
|
674
|
+
|
|
583
675
|
### Component Options
|
|
584
676
|
|
|
585
677
|
```typescript
|