ts-ioc-container 47.3.1 → 47.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +22 -14
  2. package/cjm/hooks/HookContext.js +3 -1
  3. package/cjm/index.js +16 -15
  4. package/cjm/injector/MetadataInjector.js +1 -1
  5. package/cjm/injector/inject.js +8 -4
  6. package/cjm/provider/IProvider.js +5 -5
  7. package/cjm/token/FunctionToken.js +14 -7
  8. package/esm/hooks/HookContext.js +3 -1
  9. package/esm/index.js +7 -7
  10. package/esm/injector/MetadataInjector.js +1 -1
  11. package/esm/injector/inject.js +6 -3
  12. package/esm/provider/IProvider.js +2 -2
  13. package/esm/token/FunctionToken.js +14 -7
  14. package/package.json +4 -4
  15. package/typings/hooks/hook.d.ts +2 -1
  16. package/typings/index.d.ts +7 -7
  17. package/typings/injector/inject.d.ts +3 -1
  18. package/typings/provider/IProvider.d.ts +2 -2
  19. package/typings/token/FunctionToken.d.ts +5 -2
  20. /package/cjm/{metadata → utils}/debounce.js +0 -0
  21. /package/cjm/{metadata → utils}/errorHandler.js +0 -0
  22. /package/cjm/{metadata → utils}/once.js +0 -0
  23. /package/cjm/{metadata → utils}/shallowCache.js +0 -0
  24. /package/cjm/{metadata → utils}/throttle.js +0 -0
  25. /package/esm/{metadata → utils}/debounce.js +0 -0
  26. /package/esm/{metadata → utils}/errorHandler.js +0 -0
  27. /package/esm/{metadata → utils}/once.js +0 -0
  28. /package/esm/{metadata → utils}/shallowCache.js +0 -0
  29. /package/esm/{metadata → utils}/throttle.js +0 -0
  30. /package/typings/{metadata → utils}/debounce.d.ts +0 -0
  31. /package/typings/{metadata → utils}/errorHandler.d.ts +0 -0
  32. /package/typings/{metadata → utils}/once.d.ts +0 -0
  33. /package/typings/{metadata → utils}/shallowCache.d.ts +0 -0
  34. /package/typings/{metadata → utils}/throttle.d.ts +0 -0
package/README.md CHANGED
@@ -39,7 +39,7 @@
39
39
  - [Proxy](#proxy)
40
40
  - [Provider](#provider) `provider`
41
41
  - [Singleton](#singleton) `singleton`
42
- - [Arguments](#arguments) `args` `argsFn`
42
+ - [Arguments](#arguments) `setArgs` `setArgsFn`
43
43
  - [Visibility](#visibility) `visible`
44
44
  - [Alias](#alias) `asAlias`
45
45
  - [Decorator](#decorator) `decorate`
@@ -1592,8 +1592,8 @@ Provider is dependency factory which creates dependency.
1592
1592
 
1593
1593
  ```typescript
1594
1594
  import {
1595
- args,
1596
- argsFn,
1595
+ setArgs,
1596
+ setArgsFn,
1597
1597
  bindTo,
1598
1598
  Container,
1599
1599
  lazy,
@@ -1672,7 +1672,10 @@ describe('Provider', () => {
1672
1672
  constructor(readonly basePath: string) {}
1673
1673
  }
1674
1674
 
1675
- const container = new Container().register('FileService', Provider.fromClass(FileService).pipe(args('/var/data')));
1675
+ const container = new Container().register(
1676
+ 'FileService',
1677
+ Provider.fromClass(FileService).pipe(setArgs('/var/data')),
1678
+ );
1676
1679
 
1677
1680
  const service = container.resolve<FileService>('FileService');
1678
1681
  expect(service.basePath).toBe('/var/data');
@@ -1687,7 +1690,7 @@ describe('Provider', () => {
1687
1690
  'Database',
1688
1691
  Provider.fromClass(Database).pipe(
1689
1692
  // Dynamically resolve connection string at creation time
1690
- argsFn((scope) => [`postgres://${scope.resolve('DbPath')}`]),
1693
+ setArgsFn((scope) => [`postgres://${scope.resolve('DbPath')}`]),
1691
1694
  ),
1692
1695
  );
1693
1696
 
@@ -1825,15 +1828,20 @@ describe('Singleton', function () {
1825
1828
 
1826
1829
  ### Arguments
1827
1830
  Sometimes you want to bind some arguments to provider. This is what `ArgsProvider` is for.
1828
- - `provider(args('someArgument'))`
1829
- - `provider(argsFn((container) => [container.resolve(Logger), 'someValue']))`
1830
- - `Provider.fromClass(Logger).pipe(args('someArgument'))`
1831
+ - `provider(setArgs('someArgument'))`
1832
+ - `provider(setArgsFn((container) => [container.resolve(Logger), 'someValue']))`
1833
+ - `Provider.fromClass(Logger).pipe(setArgs('someArgument'))`
1831
1834
  - NOTICE: args from this provider has higher priority than args from `resolve` method.
1832
1835
 
1836
+ ### Positional arg injection with `args(index)`
1837
+ Use `@inject(args(index))` to explicitly bind a constructor parameter to a positional argument from `ProviderOptions`. This is useful when combining `setArgsFn(resolveByArgs)` with token-based arg passing.
1838
+ - `@inject(args(0))` — resolves the first element of the `args` array passed at resolution time
1839
+ - Works together with `token.args(...)` to pass typed dependencies through the args context
1840
+
1833
1841
  ```typescript
1834
1842
  import {
1835
- args,
1836
- argsFn,
1843
+ setArgs,
1844
+ setArgsFn,
1837
1845
  bindTo,
1838
1846
  Container,
1839
1847
  inject,
@@ -1867,7 +1875,7 @@ describe('ArgsProvider', function () {
1867
1875
  }
1868
1876
 
1869
1877
  // Pre-configure the logger with a filename
1870
- const root = createContainer().addRegistration(R.fromClass(FileLogger).pipe(args('/var/log/app.log')));
1878
+ const root = createContainer().addRegistration(R.fromClass(FileLogger).pipe(setArgs('/var/log/app.log')));
1871
1879
 
1872
1880
  // Resolve by class name (default key) to use the registered provider
1873
1881
  const logger = root.resolve<FileLogger>('FileLogger');
@@ -1880,7 +1888,7 @@ describe('ArgsProvider', function () {
1880
1888
  }
1881
1889
 
1882
1890
  // 'FixedContext' wins over any runtime args
1883
- const root = createContainer().addRegistration(R.fromClass(Logger).pipe(args('FixedContext')));
1891
+ const root = createContainer().addRegistration(R.fromClass(Logger).pipe(setArgs('FixedContext')));
1884
1892
 
1885
1893
  // Even if we ask for 'RuntimeContext', we get 'FixedContext'
1886
1894
  // Resolve by class name to use the registered provider
@@ -1906,7 +1914,7 @@ describe('ArgsProvider', function () {
1906
1914
  R.fromClass(Service).pipe(
1907
1915
  // Extract 'env' from Config service dynamically
1908
1916
  // Note: We resolve 'Config' by string key to get the registered instance (if it were singleton)
1909
- argsFn((scope) => [scope.resolve<Config>('Config').env]),
1917
+ setArgsFn((scope) => [scope.resolve<Config>('Config').env]),
1910
1918
  ),
1911
1919
  );
1912
1920
 
@@ -1943,7 +1951,7 @@ describe('ArgsProvider', function () {
1943
1951
 
1944
1952
  @register(
1945
1953
  bindTo(EntityManagerToken),
1946
- argsFn(resolveByArgs), // <--- Key magic: resolves dependencies based on arguments passed to token
1954
+ setArgsFn(resolveByArgs), // <--- Key magic: resolves dependencies based on arguments passed to token
1947
1955
  singleton(MultiCache.fromFirstArg), // Cache unique instance per repository type
1948
1956
  )
1949
1957
  class EntityManager {
@@ -14,7 +14,9 @@ class HookContext {
14
14
  this.instance = (0, proxy_1.isProxy)(instance) ? (0, proxy_1.getProxyTarget)(instance) : instance;
15
15
  }
16
16
  resolveArgs(...args) {
17
- return (0, inject_1.resolveArgs)(this.instance.constructor, this.methodName)(this.scope, ...[...this.initialArgs, ...args]);
17
+ return (0, inject_1.resolveArgs)(this.instance.constructor, this.methodName)(this.scope, {
18
+ args: [...this.initialArgs, ...args],
19
+ });
18
20
  }
19
21
  invokeMethod({ args = this.resolveArgs() } = {}) {
20
22
  // @ts-ignore
package/cjm/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ClassToken = exports.toSingleAlias = exports.SingleAliasToken = exports.toGroupAlias = exports.GroupAliasToken = exports.InjectionToken = exports.HooksRunner = exports.AddOnDisposeHookModule = exports.onDispose = exports.onDisposeHooksRunner = exports.AddOnConstructHookModule = exports.onConstruct = exports.onConstructHooksRunner = exports.injectProp = exports.createHookContext = exports.createHookContextFactory = exports.HookContext = exports.hasHooks = exports.hook = exports.getHooks = exports.UnexpectedHookResultError = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyMissingKeyError = exports.DependencyNotFoundError = exports.Registration = exports.bindTo = exports.register = exports.scope = exports.decorate = exports.MultiCache = exports.multiCache = exports.SingletonProvider = exports.singleton = exports.Provider = exports.resolveByArgs = exports.ProviderDecorator = exports.args = exports.argsFn = exports.lazy = exports.scopeAccess = exports.ProxyInjector = exports.SimpleInjector = exports.MetadataInjector = exports.Injector = exports.resolveArgs = exports.inject = exports.EmptyContainer = exports.Container = exports.isDependencyKey = void 0;
4
- exports.resolveConstructor = exports.Is = exports.pipe = exports.select = exports.getMethodTags = exports.methodTag = exports.getMethodLabels = exports.methodLabel = exports.getMethodMeta = exports.methodMeta = exports.getParamTags = exports.paramTag = exports.getParamLabels = exports.paramLabel = exports.getParamMeta = exports.paramMeta = exports.getClassTags = exports.classTag = exports.getClassLabels = exports.classLabel = exports.getClassMeta = exports.classMeta = exports.once = exports.shallowCache = exports.debounce = exports.throttle = exports.handleAsyncError = exports.handleError = exports.GroupInstanceToken = exports.ConstantToken = exports.FunctionToken = exports.SingleToken = void 0;
3
+ exports.toSingleAlias = exports.SingleAliasToken = exports.toGroupAlias = exports.GroupAliasToken = exports.InjectionToken = exports.HooksRunner = exports.AddOnDisposeHookModule = exports.onDispose = exports.onDisposeHooksRunner = exports.AddOnConstructHookModule = exports.onConstruct = exports.onConstructHooksRunner = exports.injectProp = exports.createHookContext = exports.createHookContextFactory = exports.HookContext = exports.hasHooks = exports.hook = exports.getHooks = exports.UnexpectedHookResultError = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyMissingKeyError = exports.DependencyNotFoundError = exports.Registration = exports.bindTo = exports.register = exports.scope = exports.decorate = exports.MultiCache = exports.multiCache = exports.SingletonProvider = exports.singleton = exports.Provider = exports.resolveByArgs = exports.ProviderDecorator = exports.setArgs = exports.setArgsFn = exports.lazy = exports.scopeAccess = exports.ProxyInjector = exports.SimpleInjector = exports.MetadataInjector = exports.Injector = exports.args = exports.resolveArgs = exports.inject = exports.EmptyContainer = exports.Container = exports.isDependencyKey = void 0;
4
+ exports.resolveConstructor = exports.Is = exports.pipe = exports.select = exports.once = exports.shallowCache = exports.debounce = exports.throttle = exports.handleAsyncError = exports.handleError = exports.getMethodTags = exports.methodTag = exports.getMethodLabels = exports.methodLabel = exports.getMethodMeta = exports.methodMeta = exports.getParamTags = exports.paramTag = exports.getParamLabels = exports.paramLabel = exports.getParamMeta = exports.paramMeta = exports.getClassTags = exports.classTag = exports.getClassLabels = exports.classLabel = exports.getClassMeta = exports.classMeta = exports.GroupInstanceToken = exports.ConstantToken = exports.FunctionToken = exports.SingleToken = exports.ClassToken = void 0;
5
5
  // Containers
6
6
  var IContainer_1 = require("./container/IContainer");
7
7
  Object.defineProperty(exports, "isDependencyKey", { enumerable: true, get: function () { return IContainer_1.isDependencyKey; } });
@@ -13,6 +13,7 @@ Object.defineProperty(exports, "EmptyContainer", { enumerable: true, get: functi
13
13
  var inject_1 = require("./injector/inject");
14
14
  Object.defineProperty(exports, "inject", { enumerable: true, get: function () { return inject_1.inject; } });
15
15
  Object.defineProperty(exports, "resolveArgs", { enumerable: true, get: function () { return inject_1.resolveArgs; } });
16
+ Object.defineProperty(exports, "args", { enumerable: true, get: function () { return inject_1.args; } });
16
17
  var IInjector_1 = require("./injector/IInjector");
17
18
  Object.defineProperty(exports, "Injector", { enumerable: true, get: function () { return IInjector_1.Injector; } });
18
19
  var MetadataInjector_1 = require("./injector/MetadataInjector");
@@ -25,8 +26,8 @@ Object.defineProperty(exports, "ProxyInjector", { enumerable: true, get: functio
25
26
  var IProvider_1 = require("./provider/IProvider");
26
27
  Object.defineProperty(exports, "scopeAccess", { enumerable: true, get: function () { return IProvider_1.scopeAccess; } });
27
28
  Object.defineProperty(exports, "lazy", { enumerable: true, get: function () { return IProvider_1.lazy; } });
28
- Object.defineProperty(exports, "argsFn", { enumerable: true, get: function () { return IProvider_1.argsFn; } });
29
- Object.defineProperty(exports, "args", { enumerable: true, get: function () { return IProvider_1.args; } });
29
+ Object.defineProperty(exports, "setArgsFn", { enumerable: true, get: function () { return IProvider_1.setArgsFn; } });
30
+ Object.defineProperty(exports, "setArgs", { enumerable: true, get: function () { return IProvider_1.setArgs; } });
30
31
  Object.defineProperty(exports, "ProviderDecorator", { enumerable: true, get: function () { return IProvider_1.ProviderDecorator; } });
31
32
  Object.defineProperty(exports, "resolveByArgs", { enumerable: true, get: function () { return IProvider_1.resolveByArgs; } });
32
33
  var Provider_1 = require("./provider/Provider");
@@ -98,17 +99,6 @@ Object.defineProperty(exports, "ConstantToken", { enumerable: true, get: functio
98
99
  var GroupInstanceToken_1 = require("./token/GroupInstanceToken");
99
100
  Object.defineProperty(exports, "GroupInstanceToken", { enumerable: true, get: function () { return GroupInstanceToken_1.GroupInstanceToken; } });
100
101
  // Metadata
101
- var errorHandler_1 = require("./metadata/errorHandler");
102
- Object.defineProperty(exports, "handleError", { enumerable: true, get: function () { return errorHandler_1.handleError; } });
103
- Object.defineProperty(exports, "handleAsyncError", { enumerable: true, get: function () { return errorHandler_1.handleAsyncError; } });
104
- var throttle_1 = require("./metadata/throttle");
105
- Object.defineProperty(exports, "throttle", { enumerable: true, get: function () { return throttle_1.throttle; } });
106
- var debounce_1 = require("./metadata/debounce");
107
- Object.defineProperty(exports, "debounce", { enumerable: true, get: function () { return debounce_1.debounce; } });
108
- var shallowCache_1 = require("./metadata/shallowCache");
109
- Object.defineProperty(exports, "shallowCache", { enumerable: true, get: function () { return shallowCache_1.shallowCache; } });
110
- var once_1 = require("./metadata/once");
111
- Object.defineProperty(exports, "once", { enumerable: true, get: function () { return once_1.once; } });
112
102
  var class_1 = require("./metadata/class");
113
103
  Object.defineProperty(exports, "classMeta", { enumerable: true, get: function () { return class_1.classMeta; } });
114
104
  Object.defineProperty(exports, "getClassMeta", { enumerable: true, get: function () { return class_1.getClassMeta; } });
@@ -130,6 +120,17 @@ Object.defineProperty(exports, "methodLabel", { enumerable: true, get: function
130
120
  Object.defineProperty(exports, "getMethodLabels", { enumerable: true, get: function () { return method_1.getMethodLabels; } });
131
121
  Object.defineProperty(exports, "methodTag", { enumerable: true, get: function () { return method_1.methodTag; } });
132
122
  Object.defineProperty(exports, "getMethodTags", { enumerable: true, get: function () { return method_1.getMethodTags; } });
123
+ var errorHandler_1 = require("./utils/errorHandler");
124
+ Object.defineProperty(exports, "handleError", { enumerable: true, get: function () { return errorHandler_1.handleError; } });
125
+ Object.defineProperty(exports, "handleAsyncError", { enumerable: true, get: function () { return errorHandler_1.handleAsyncError; } });
126
+ var throttle_1 = require("./utils/throttle");
127
+ Object.defineProperty(exports, "throttle", { enumerable: true, get: function () { return throttle_1.throttle; } });
128
+ var debounce_1 = require("./utils/debounce");
129
+ Object.defineProperty(exports, "debounce", { enumerable: true, get: function () { return debounce_1.debounce; } });
130
+ var shallowCache_1 = require("./utils/shallowCache");
131
+ Object.defineProperty(exports, "shallowCache", { enumerable: true, get: function () { return shallowCache_1.shallowCache; } });
132
+ var once_1 = require("./utils/once");
133
+ Object.defineProperty(exports, "once", { enumerable: true, get: function () { return once_1.once; } });
133
134
  // Utils
134
135
  var select_1 = require("./select");
135
136
  Object.defineProperty(exports, "select", { enumerable: true, get: function () { return select_1.select; } });
@@ -5,7 +5,7 @@ const IInjector_1 = require("./IInjector");
5
5
  const inject_1 = require("./inject");
6
6
  class MetadataInjector extends IInjector_1.Injector {
7
7
  createInstance(scope, Target, { args: deps = [] } = {}) {
8
- const args = (0, inject_1.resolveArgs)(Target)(scope, ...deps);
8
+ const args = (0, inject_1.resolveArgs)(Target)(scope, { args: deps });
9
9
  return new Target(...args);
10
10
  }
11
11
  }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resolveArgs = exports.inject = void 0;
3
+ exports.resolveArgs = exports.args = exports.inject = void 0;
4
4
  const ConstantToken_1 = require("../token/ConstantToken");
5
5
  const toToken_1 = require("../token/toToken");
6
6
  const array_1 = require("../utils/array");
@@ -11,12 +11,16 @@ const inject = (fn) => (target, propertyKey, parameterIndex) => {
11
11
  (0, parameter_1.paramMeta)(hookMetaKey(propertyKey), () => (0, toToken_1.toToken)(fn))(basic_1.Is.instance(target) ? target.constructor : target, propertyKey, parameterIndex);
12
12
  };
13
13
  exports.inject = inject;
14
+ const args = (index) => (c, { args = [] }) => {
15
+ return args[index];
16
+ };
17
+ exports.args = args;
14
18
  const resolveArgs = (Target, methodName) => {
15
19
  const argsTokens = (0, parameter_1.getParamMeta)(hookMetaKey(methodName), Target);
16
- return (scope, ...deps) => {
17
- const depsTokens = deps.map((v) => new ConstantToken_1.ConstantToken(v));
20
+ return (scope, { args = [], lazy }) => {
21
+ const depsTokens = args.map((v) => new ConstantToken_1.ConstantToken(v));
18
22
  const allTokens = (0, array_1.fillEmptyIndexes)(argsTokens, depsTokens);
19
- return allTokens.map((fn) => fn.resolve(scope));
23
+ return allTokens.map((fn) => fn.resolve(scope, { args, lazy }));
20
24
  };
21
25
  };
22
26
  exports.resolveArgs = resolveArgs;
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ProviderDecorator = exports.lazy = exports.scopeAccess = exports.resolveByArgs = exports.argsFn = exports.args = void 0;
3
+ exports.ProviderDecorator = exports.lazy = exports.scopeAccess = exports.resolveByArgs = exports.setArgsFn = exports.setArgs = void 0;
4
4
  const ProviderPipe_1 = require("./ProviderPipe");
5
5
  const InjectionToken_1 = require("../token/InjectionToken");
6
6
  const basic_1 = require("../utils/basic");
7
- const args = (...extraArgs) => (0, ProviderPipe_1.registerPipe)((p) => p.setArgs(() => extraArgs));
8
- exports.args = args;
9
- const argsFn = (fn) => (0, ProviderPipe_1.registerPipe)((p) => p.setArgs(fn));
10
- exports.argsFn = argsFn;
7
+ const setArgs = (...extraArgs) => (0, ProviderPipe_1.registerPipe)((p) => p.setArgs(() => extraArgs));
8
+ exports.setArgs = setArgs;
9
+ const setArgsFn = (fn) => (0, ProviderPipe_1.registerPipe)((p) => p.setArgs(fn));
10
+ exports.setArgsFn = setArgsFn;
11
11
  const resolveByArgs = (s, ...deps) => deps.map((d) => {
12
12
  if (d instanceof InjectionToken_1.InjectionToken) {
13
13
  return d.resolve(s);
@@ -2,24 +2,31 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FunctionToken = void 0;
4
4
  const InjectionToken_1 = require("./InjectionToken");
5
- const MethodNotImplementedError_1 = require("../errors/MethodNotImplementedError");
6
5
  class FunctionToken extends InjectionToken_1.InjectionToken {
7
6
  fn;
7
+ getArgsFn = () => [];
8
+ isLazy = false;
8
9
  constructor(fn) {
9
10
  super();
10
11
  this.fn = fn;
11
12
  }
12
- resolve(s) {
13
- return this.fn(s);
13
+ resolve(s, { args = [], lazy = false } = {}) {
14
+ return this.fn(s, {
15
+ args: [...args, ...this.getArgsFn(s)],
16
+ lazy: this.isLazy || lazy,
17
+ });
14
18
  }
15
19
  args(...deps) {
16
- throw new MethodNotImplementedError_1.MethodNotImplementedError('not implemented');
20
+ this.getArgsFn = () => deps;
21
+ return this;
17
22
  }
18
23
  argsFn(getArgsFn) {
19
- throw new MethodNotImplementedError_1.MethodNotImplementedError('not implemented');
24
+ this.getArgsFn = getArgsFn;
25
+ return this;
20
26
  }
21
- lazy() {
22
- throw new MethodNotImplementedError_1.MethodNotImplementedError('not implemented');
27
+ lazy(isLazy = true) {
28
+ this.isLazy = isLazy;
29
+ return this;
23
30
  }
24
31
  }
25
32
  exports.FunctionToken = FunctionToken;
@@ -11,7 +11,9 @@ export class HookContext {
11
11
  this.instance = isProxy(instance) ? getProxyTarget(instance) : instance;
12
12
  }
13
13
  resolveArgs(...args) {
14
- return resolveArgs(this.instance.constructor, this.methodName)(this.scope, ...[...this.initialArgs, ...args]);
14
+ return resolveArgs(this.instance.constructor, this.methodName)(this.scope, {
15
+ args: [...this.initialArgs, ...args],
16
+ });
15
17
  }
16
18
  invokeMethod({ args = this.resolveArgs() } = {}) {
17
19
  // @ts-ignore
package/esm/index.js CHANGED
@@ -3,13 +3,13 @@ export { isDependencyKey, } from './container/IContainer';
3
3
  export { Container } from './container/Container';
4
4
  export { EmptyContainer } from './container/EmptyContainer';
5
5
  // Injectors
6
- export { inject, resolveArgs } from './injector/inject';
6
+ export { inject, resolveArgs, args } from './injector/inject';
7
7
  export { Injector } from './injector/IInjector';
8
8
  export { MetadataInjector } from './injector/MetadataInjector';
9
9
  export { SimpleInjector } from './injector/SimpleInjector';
10
10
  export { ProxyInjector } from './injector/ProxyInjector';
11
11
  // Providers
12
- export { scopeAccess, lazy, argsFn, args, ProviderDecorator, resolveByArgs, } from './provider/IProvider';
12
+ export { scopeAccess, lazy, setArgsFn, setArgs, ProviderDecorator, resolveByArgs, } from './provider/IProvider';
13
13
  export { Provider } from './provider/Provider';
14
14
  export { singleton, SingletonProvider } from './provider/SingletonProvider';
15
15
  export { multiCache, MultiCache } from './provider/Cache';
@@ -40,14 +40,14 @@ export { FunctionToken } from './token/FunctionToken';
40
40
  export { ConstantToken } from './token/ConstantToken';
41
41
  export { GroupInstanceToken } from './token/GroupInstanceToken';
42
42
  // Metadata
43
- export { handleError, handleAsyncError } from './metadata/errorHandler';
44
- export { throttle } from './metadata/throttle';
45
- export { debounce } from './metadata/debounce';
46
- export { shallowCache } from './metadata/shallowCache';
47
- export { once } from './metadata/once';
48
43
  export { classMeta, getClassMeta, classLabel, getClassLabels, classTag, getClassTags } from './metadata/class';
49
44
  export { paramMeta, getParamMeta, paramLabel, getParamLabels, paramTag, getParamTags } from './metadata/parameter';
50
45
  export { methodMeta, getMethodMeta, methodLabel, getMethodLabels, methodTag, getMethodTags } from './metadata/method';
46
+ export { handleError, handleAsyncError } from './utils/errorHandler';
47
+ export { throttle } from './utils/throttle';
48
+ export { debounce } from './utils/debounce';
49
+ export { shallowCache } from './utils/shallowCache';
50
+ export { once } from './utils/once';
51
51
  // Utils
52
52
  export { select } from './select';
53
53
  export { pipe } from './utils/fp';
@@ -2,7 +2,7 @@ import { Injector } from './IInjector';
2
2
  import { resolveArgs } from './inject';
3
3
  export class MetadataInjector extends Injector {
4
4
  createInstance(scope, Target, { args: deps = [] } = {}) {
5
- const args = resolveArgs(Target)(scope, ...deps);
5
+ const args = resolveArgs(Target)(scope, { args: deps });
6
6
  return new Target(...args);
7
7
  }
8
8
  }
@@ -7,11 +7,14 @@ const hookMetaKey = (methodName = 'constructor') => `inject:${methodName}`;
7
7
  export const inject = (fn) => (target, propertyKey, parameterIndex) => {
8
8
  paramMeta(hookMetaKey(propertyKey), () => toToken(fn))(Is.instance(target) ? target.constructor : target, propertyKey, parameterIndex);
9
9
  };
10
+ export const args = (index) => (c, { args = [] }) => {
11
+ return args[index];
12
+ };
10
13
  export const resolveArgs = (Target, methodName) => {
11
14
  const argsTokens = getParamMeta(hookMetaKey(methodName), Target);
12
- return (scope, ...deps) => {
13
- const depsTokens = deps.map((v) => new ConstantToken(v));
15
+ return (scope, { args = [], lazy }) => {
16
+ const depsTokens = args.map((v) => new ConstantToken(v));
14
17
  const allTokens = fillEmptyIndexes(argsTokens, depsTokens);
15
- return allTokens.map((fn) => fn.resolve(scope));
18
+ return allTokens.map((fn) => fn.resolve(scope, { args, lazy }));
16
19
  };
17
20
  };
@@ -1,8 +1,8 @@
1
1
  import { isProviderPipe, registerPipe } from './ProviderPipe';
2
2
  import { InjectionToken } from '../token/InjectionToken';
3
3
  import { Is } from '../utils/basic';
4
- export const args = (...extraArgs) => registerPipe((p) => p.setArgs(() => extraArgs));
5
- export const argsFn = (fn) => registerPipe((p) => p.setArgs(fn));
4
+ export const setArgs = (...extraArgs) => registerPipe((p) => p.setArgs(() => extraArgs));
5
+ export const setArgsFn = (fn) => registerPipe((p) => p.setArgs(fn));
6
6
  export const resolveByArgs = (s, ...deps) => deps.map((d) => {
7
7
  if (d instanceof InjectionToken) {
8
8
  return d.resolve(s);
@@ -1,21 +1,28 @@
1
1
  import { InjectionToken } from './InjectionToken';
2
- import { MethodNotImplementedError } from '../errors/MethodNotImplementedError';
3
2
  export class FunctionToken extends InjectionToken {
4
3
  fn;
4
+ getArgsFn = () => [];
5
+ isLazy = false;
5
6
  constructor(fn) {
6
7
  super();
7
8
  this.fn = fn;
8
9
  }
9
- resolve(s) {
10
- return this.fn(s);
10
+ resolve(s, { args = [], lazy = false } = {}) {
11
+ return this.fn(s, {
12
+ args: [...args, ...this.getArgsFn(s)],
13
+ lazy: this.isLazy || lazy,
14
+ });
11
15
  }
12
16
  args(...deps) {
13
- throw new MethodNotImplementedError('not implemented');
17
+ this.getArgsFn = () => deps;
18
+ return this;
14
19
  }
15
20
  argsFn(getArgsFn) {
16
- throw new MethodNotImplementedError('not implemented');
21
+ this.getArgsFn = getArgsFn;
22
+ return this;
17
23
  }
18
- lazy() {
19
- throw new MethodNotImplementedError('not implemented');
24
+ lazy(isLazy = true) {
25
+ this.isLazy = isLazy;
26
+ return this;
20
27
  }
21
28
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-ioc-container",
3
- "version": "47.3.1",
3
+ "version": "47.4.0",
4
4
  "description": "Typescript IoC container",
5
5
  "workspaces": [
6
6
  "docs"
@@ -73,7 +73,7 @@
73
73
  "@semantic-release/npm": "^13.1.2",
74
74
  "@swc/core": "^1.15.24",
75
75
  "@types/node": "^25.5.2",
76
- "@typescript-eslint/eslint-plugin": "8.29.1",
76
+ "@typescript-eslint/eslint-plugin": "8.32.1",
77
77
  "@typescript-eslint/parser": "8.29.1",
78
78
  "@vitest/coverage-v8": "^4.1.2",
79
79
  "cz-conventional-changelog": "^3.3.0",
@@ -82,12 +82,12 @@
82
82
  "eslint-plugin-prettier": "5.2.6",
83
83
  "handlebars": "^4.7.8",
84
84
  "husky": "^9.1.7",
85
- "lint-staged": "^15.5.0",
85
+ "lint-staged": "^16.4.0",
86
86
  "moq.ts": "^10.0.8",
87
87
  "prettier": "3.5.3",
88
88
  "prettier-plugin-astro": "^0.14.1",
89
89
  "reflect-metadata": "^0.2.2",
90
- "rimraf": "6.0.1",
90
+ "rimraf": "6.1.3",
91
91
  "semantic-release": "^25.0.2",
92
92
  "tsx": "^4.21.0",
93
93
  "typescript": "5.8.3",
@@ -1,7 +1,8 @@
1
1
  import { type IHookContext } from './HookContext';
2
2
  import type { IContainer } from '../container/IContainer';
3
3
  import { type constructor } from '../utils/basic';
4
- export type InjectFn<T = unknown> = (s: IContainer) => T;
4
+ import { ProviderOptions } from '../provider/IProvider';
5
+ export type InjectFn<T = unknown> = (s: IContainer, context: ProviderOptions) => T;
5
6
  export type HookFn<T extends IHookContext = IHookContext> = (context: T) => void | Promise<void>;
6
7
  export interface HookClass<T extends IHookContext = IHookContext> {
7
8
  execute(context: Omit<T, 'scope'>): void | Promise<void>;
@@ -1,12 +1,12 @@
1
1
  export { type IContainer, type Resolvable, type IContainerModule, type DependencyKey, type Tag, type Tagged, type ResolveOneOptions, type ResolveManyOptions, isDependencyKey, } from './container/IContainer';
2
2
  export { Container } from './container/Container';
3
3
  export { EmptyContainer } from './container/EmptyContainer';
4
- export { inject, resolveArgs } from './injector/inject';
4
+ export { inject, resolveArgs, args } from './injector/inject';
5
5
  export { type IInjector, type InjectOptions, type IInjectFnResolver, Injector } from './injector/IInjector';
6
6
  export { MetadataInjector } from './injector/MetadataInjector';
7
7
  export { SimpleInjector } from './injector/SimpleInjector';
8
8
  export { ProxyInjector } from './injector/ProxyInjector';
9
- export { type ResolveDependency, type IProvider, scopeAccess, lazy, argsFn, args, type ArgsFn, ProviderDecorator, resolveByArgs, type IMapper, type ProviderOptions, } from './provider/IProvider';
9
+ export { type ResolveDependency, type IProvider, scopeAccess, lazy, setArgsFn, setArgs, type ArgsFn, ProviderDecorator, resolveByArgs, type IMapper, type ProviderOptions, } from './provider/IProvider';
10
10
  export { Provider } from './provider/Provider';
11
11
  export { singleton, SingletonProvider } from './provider/SingletonProvider';
12
12
  export { type Cache, multiCache, MultiCache } from './provider/Cache';
@@ -33,14 +33,14 @@ export { SingleToken } from './token/SingleToken';
33
33
  export { FunctionToken } from './token/FunctionToken';
34
34
  export { ConstantToken } from './token/ConstantToken';
35
35
  export { type InstancePredicate, GroupInstanceToken } from './token/GroupInstanceToken';
36
- export { handleError, handleAsyncError, type HandleErrorParams } from './metadata/errorHandler';
37
- export { throttle } from './metadata/throttle';
38
- export { debounce } from './metadata/debounce';
39
- export { shallowCache } from './metadata/shallowCache';
40
- export { once } from './metadata/once';
41
36
  export { classMeta, getClassMeta, classLabel, getClassLabels, classTag, getClassTags } from './metadata/class';
42
37
  export { paramMeta, getParamMeta, paramLabel, getParamLabels, paramTag, getParamTags } from './metadata/parameter';
43
38
  export { methodMeta, getMethodMeta, methodLabel, getMethodLabels, methodTag, getMethodTags } from './metadata/method';
39
+ export { handleError, handleAsyncError, type HandleErrorParams } from './utils/errorHandler';
40
+ export { throttle } from './utils/throttle';
41
+ export { debounce } from './utils/debounce';
42
+ export { shallowCache } from './utils/shallowCache';
43
+ export { once } from './utils/once';
44
44
  export { select } from './select';
45
45
  export { pipe, type MapFn } from './utils/fp';
46
46
  export { type constructor, type Instance, Is, resolveConstructor } from './utils/basic';
@@ -2,5 +2,7 @@ import { type IContainer } from '../container/IContainer';
2
2
  import { InjectionToken } from '../token/InjectionToken';
3
3
  import { InjectFn } from '../hooks/hook';
4
4
  import { type constructor } from '../utils/basic';
5
+ import { ProviderOptions } from '../provider/IProvider';
5
6
  export declare const inject: <T>(fn: InjectionToken<T> | InjectFn<T> | symbol | string | constructor<T>) => ParameterDecorator;
6
- export declare const resolveArgs: (Target: constructor<unknown>, methodName?: string) => (scope: IContainer, ...deps: unknown[]) => unknown[];
7
+ export declare const args: (index: number) => (c: IContainer, { args }: ProviderOptions) => unknown;
8
+ export declare const resolveArgs: (Target: constructor<unknown>, methodName?: string) => (scope: IContainer, { args, lazy }: ProviderOptions) => unknown[];
@@ -24,8 +24,8 @@ export interface IProvider<T = any> {
24
24
  setArgs(argsFn: ArgsFn): this;
25
25
  lazy(): this;
26
26
  }
27
- export declare const args: <T>(...extraArgs: unknown[]) => ProviderPipe<T>;
28
- export declare const argsFn: <T>(fn: ArgsFn) => ProviderPipe<T>;
27
+ export declare const setArgs: <T>(...extraArgs: unknown[]) => ProviderPipe<T>;
28
+ export declare const setArgsFn: <T>(fn: ArgsFn) => ProviderPipe<T>;
29
29
  export declare const resolveByArgs: (s: IContainer, ...deps: unknown[]) => any[];
30
30
  export declare const scopeAccess: <T>(rule: ScopeAccessRule) => ProviderPipe<T>;
31
31
  export declare const lazy: <T>() => ProviderPipe<T>;
@@ -1,11 +1,14 @@
1
1
  import type { IContainer } from '../container/IContainer';
2
2
  import { InjectionToken } from './InjectionToken';
3
3
  import { InjectFn } from '../hooks/hook';
4
+ import { ProviderOptions } from '../provider/IProvider';
4
5
  export declare class FunctionToken<T = any> extends InjectionToken<T> {
5
6
  private readonly fn;
7
+ private getArgsFn;
8
+ private isLazy;
6
9
  constructor(fn: InjectFn<T>);
7
- resolve(s: IContainer): T;
10
+ resolve(s: IContainer, { args, lazy }?: ProviderOptions): T;
8
11
  args(...deps: unknown[]): InjectionToken<T>;
9
12
  argsFn(getArgsFn: (s: IContainer) => unknown[]): InjectionToken<T>;
10
- lazy(): InjectionToken<T>;
13
+ lazy(isLazy?: boolean): InjectionToken<T>;
11
14
  }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes