ts-ioc-container 68.0.0 → 69.0.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/README.md +83 -14
- package/cjm/errors/ArgumentNotFoundError.js +12 -0
- package/cjm/index.js +7 -3
- package/cjm/injector/MetadataInjector.js +1 -1
- package/cjm/token/ClassToken.js +1 -1
- package/cjm/token/FunctionToken.js +1 -1
- package/cjm/token/GroupAliasToken.js +1 -1
- package/cjm/token/InjectionToken.js +3 -1
- package/cjm/token/SingleAliasToken.js +1 -1
- package/cjm/token/SingleToken.js +1 -1
- package/cjm/utils/array.js +10 -1
- package/esm/errors/ArgumentNotFoundError.js +8 -0
- package/esm/index.js +2 -0
- package/esm/injector/MetadataInjector.js +3 -3
- package/esm/token/ClassToken.js +2 -2
- package/esm/token/FunctionToken.js +2 -2
- package/esm/token/GroupAliasToken.js +2 -2
- package/esm/token/InjectionToken.js +1 -0
- package/esm/token/SingleAliasToken.js +2 -2
- package/esm/token/SingleToken.js +2 -2
- package/esm/utils/array.js +8 -0
- package/package.json +1 -1
- package/typings/errors/ArgumentNotFoundError.d.ts +5 -0
- package/typings/index.d.ts +2 -0
- package/typings/token/InjectionToken.d.ts +2 -1
- package/typings/utils/array.d.ts +2 -0
package/README.md
CHANGED
|
@@ -1774,13 +1774,16 @@ Sometimes you want to bind some arguments to provider.
|
|
|
1774
1774
|
- `provider(appendArgsFn((container) => [container.resolve(Logger), 'someValue']))`
|
|
1775
1775
|
- `Provider.fromClass(Logger).pipe(appendArgs('someArgument'))`
|
|
1776
1776
|
|
|
1777
|
-
###
|
|
1777
|
+
### Dependencies as arguments
|
|
1778
1778
|
|
|
1779
|
-
|
|
1779
|
+
Args are passed to the constructor **as-is** — the library never resolves an `InjectionToken` (or a bare constructor) it finds in the args list. Resolve it at the call site with `argsFn`:
|
|
1780
1780
|
|
|
1781
|
-
- `ServiceToken.
|
|
1782
|
-
- `ServiceToken.
|
|
1781
|
+
- `ServiceToken.argsFn((scope) => [ValueToken.resolve(scope)])` — `ValueToken` is resolved from the container, its value is passed as arg
|
|
1782
|
+
- `ServiceToken.argsFn((scope) => [scope.resolve(SomeService)])` — `SomeService` is constructed by the container
|
|
1783
1783
|
- `ServiceToken.args('literal')` — literal value passed directly
|
|
1784
|
+
- `ServiceToken.args(ValueToken)` — the token object itself is passed as arg
|
|
1785
|
+
|
|
1786
|
+
`argToToken(value)` is the helper for a call site that wants "resolve tokens, pass literals through": it returns an `InjectionToken` as-is and wraps anything else in a `ConstantToken`, so `@inject((scope, { args = [] }) => argToToken(args[0]).resolve(scope))` accepts either.
|
|
1784
1787
|
|
|
1785
1788
|
### Positional arg injection with `arg(index)`, `args`, and `argsFn`
|
|
1786
1789
|
|
|
@@ -1788,10 +1791,73 @@ Constructor parameters that should pick up positional args from `ProviderOptions
|
|
|
1788
1791
|
|
|
1789
1792
|
- `@inject(arg(0))` — resolves the first element of the `args` array passed at resolution time
|
|
1790
1793
|
- `@inject(args)` — resolves the whole runtime `args` array
|
|
1791
|
-
- Works together with `token.args(...)` to pass typed dependencies through the args context
|
|
1794
|
+
- Works together with `token.args(...)` / `token.argsFn(...)` to pass typed dependencies through the args context
|
|
1792
1795
|
|
|
1793
1796
|
`argsFn(predicate)` is the general form: it iterates the runtime `args` array and returns the **first argument matching** `predicate(value, index)` — think `args.find(predicate)`. `arg(index)` is just a shortcut for matching by position: `arg(0)` is `argsFn((value, index) => index === 0)`. `args` is `(scope, options) => options.args`, i.e. it returns the runtime args array as-is. Every `InjectFn` receives `(scope, options)`, where `options.args` is the runtime args array.
|
|
1794
1797
|
|
|
1798
|
+
`findOrFail(predicate)` is the strict, variadic counterpart for places that take the raw args list — `singleton(findOrFail(isUserId))` keys a per-argument singleton, for example. It returns the first argument matching `predicate(value)` and throws `ArgumentNotFoundError` when none does, instead of silently handing out `undefined`.
|
|
1799
|
+
|
|
1800
|
+
### Runtime args flow through tokens
|
|
1801
|
+
|
|
1802
|
+
Every container-backed token (`SingleToken`, `ClassToken`, `SingleAliasToken`, `GroupAliasToken`, `FunctionToken`) forwards the `args` of its own `resolve` call to the provider, exactly like `container.resolve(key, { args })` does. `token.args(...)` and `token.argsFn(...)` **append after** the runtime args, so `token.args('x').resolve(container, { args: ['r'] })` hands the provider `['r', 'x']`.
|
|
1803
|
+
|
|
1804
|
+
Because `@inject(token)` parameters are resolved with the args of the class being constructed, those args **cascade** into every injected dependency: they reach the dependency's provider, its `@inject(arg(index))` parameters, its `scopeAccess` rule and its `singleton()` cache key. That is what lets a per-user `UserService` share a per-user `UserRepository` without passing the id along by hand:
|
|
1805
|
+
|
|
1806
|
+
```typescript
|
|
1807
|
+
import {
|
|
1808
|
+
arg,
|
|
1809
|
+
bindTo,
|
|
1810
|
+
Container,
|
|
1811
|
+
findOrFail,
|
|
1812
|
+
inject,
|
|
1813
|
+
register,
|
|
1814
|
+
Registration as R,
|
|
1815
|
+
singleton,
|
|
1816
|
+
SingleToken,
|
|
1817
|
+
} from 'ts-ioc-container';
|
|
1818
|
+
|
|
1819
|
+
interface IUserRepository {
|
|
1820
|
+
userId: string;
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
const IUserRepositoryKey = new SingleToken<IUserRepository>('IUserRepository');
|
|
1824
|
+
const isUserId = (value: unknown): value is string => typeof value === 'string';
|
|
1825
|
+
|
|
1826
|
+
// one repository per user id - the id is the singleton cache key
|
|
1827
|
+
@register(bindTo(IUserRepositoryKey), singleton(findOrFail<string>(isUserId)))
|
|
1828
|
+
class UserRepository implements IUserRepository {
|
|
1829
|
+
constructor(@inject(arg(0)) public userId: string) {}
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
class UserService {
|
|
1833
|
+
constructor(@inject(IUserRepositoryKey) public repository: IUserRepository) {}
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1836
|
+
describe('Token Runtime Arguments', function () {
|
|
1837
|
+
it('should forward runtime args to the provider behind the token', function () {
|
|
1838
|
+
const container = new Container().addRegistration(R.fromClass(UserRepository));
|
|
1839
|
+
|
|
1840
|
+
expect(IUserRepositoryKey.resolve(container, { args: ['user-1'] }).userId).toBe('user-1');
|
|
1841
|
+
});
|
|
1842
|
+
|
|
1843
|
+
it('should cascade the runtime args of a class into its injected dependencies', function () {
|
|
1844
|
+
const container = new Container().addRegistration(R.fromClass(UserRepository));
|
|
1845
|
+
|
|
1846
|
+
const service = container.resolve(UserService, { args: ['user-1'] });
|
|
1847
|
+
const sameUser = container.resolve(UserService, { args: ['user-1'] });
|
|
1848
|
+
const otherUser = container.resolve(UserService, { args: ['user-2'] });
|
|
1849
|
+
|
|
1850
|
+
expect(service.repository.userId).toBe('user-1');
|
|
1851
|
+
expect(sameUser.repository).toBe(service.repository);
|
|
1852
|
+
expect(otherUser.repository.userId).toBe('user-2');
|
|
1853
|
+
});
|
|
1854
|
+
});
|
|
1855
|
+
|
|
1856
|
+
```
|
|
1857
|
+
|
|
1858
|
+
> [!IMPORTANT]
|
|
1859
|
+
> Runtime args come first. A dependency that reads `@inject(arg(0))` sees the *caller's* first runtime arg whenever the caller was resolved with args, even if its token was specialized with `token.args(...)`. Pick args by shape (`argsFn(predicate)`, `findOrFail(predicate)`) rather than by position when a class can be resolved with runtime args and its dependencies are specialized with `token.args(...)`.
|
|
1860
|
+
|
|
1795
1861
|
### Immutable token chaining
|
|
1796
1862
|
|
|
1797
1863
|
`token.args(...)`, `token.argsFn(...)`, and `token.lazy()` all return **new token instances** — the parent token is never mutated. This allows the same token to be specialized in multiple independent ways (one-way linked list: parent → many children).
|
|
@@ -1949,14 +2015,16 @@ describe('IProvider', function () {
|
|
|
1949
2015
|
}
|
|
1950
2016
|
|
|
1951
2017
|
// EntityManager is generic - it works with ANY repository.
|
|
1952
|
-
// The repository is the first arg
|
|
1953
|
-
//
|
|
1954
|
-
// before
|
|
2018
|
+
// The repository is the first arg; `@inject(arg(0))` reads it. Args are
|
|
2019
|
+
// passed through as-is, so the call site resolves the repository token
|
|
2020
|
+
// itself with `argsFn` before it reaches the constructor.
|
|
1955
2021
|
const EntityManagerToken = new SingleToken<EntityManager>('EntityManager');
|
|
2022
|
+
const withRepository = (token: SingleToken<IRepository>) =>
|
|
2023
|
+
EntityManagerToken.argsFn((scope) => [token.resolve(scope)]);
|
|
1956
2024
|
|
|
1957
2025
|
@register(
|
|
1958
2026
|
bindTo(EntityManagerToken),
|
|
1959
|
-
singleton((
|
|
2027
|
+
singleton((repository) => (repository as IRepository).name), // Cache unique instance per repository type
|
|
1960
2028
|
)
|
|
1961
2029
|
class EntityManager {
|
|
1962
2030
|
constructor(@inject(arg(0)) public repository: IRepository) {}
|
|
@@ -1965,11 +2033,11 @@ describe('IProvider', function () {
|
|
|
1965
2033
|
class App {
|
|
1966
2034
|
constructor(
|
|
1967
2035
|
// Inject EntityManager configured for Users
|
|
1968
|
-
@inject(
|
|
2036
|
+
@inject(withRepository(UserRepositoryToken))
|
|
1969
2037
|
public userManager: EntityManager,
|
|
1970
2038
|
|
|
1971
2039
|
// Inject EntityManager configured for Todos
|
|
1972
|
-
@inject(
|
|
2040
|
+
@inject(withRepository(TodoRepositoryToken))
|
|
1973
2041
|
public todoManager: EntityManager,
|
|
1974
2042
|
) {}
|
|
1975
2043
|
}
|
|
@@ -1993,14 +2061,14 @@ describe('IProvider', function () {
|
|
|
1993
2061
|
.addRegistration(R.fromClass(TodoRepository));
|
|
1994
2062
|
|
|
1995
2063
|
// Resolve user manager twice
|
|
1996
|
-
const userManager1 =
|
|
1997
|
-
const userManager2 =
|
|
2064
|
+
const userManager1 = withRepository(UserRepositoryToken).resolve(root);
|
|
2065
|
+
const userManager2 = withRepository(UserRepositoryToken).resolve(root);
|
|
1998
2066
|
|
|
1999
2067
|
// Should be same instance (cached)
|
|
2000
2068
|
expect(userManager1).toBe(userManager2);
|
|
2001
2069
|
|
|
2002
2070
|
// Resolve todo manager
|
|
2003
|
-
const todoManager =
|
|
2071
|
+
const todoManager = withRepository(TodoRepositoryToken).resolve(root);
|
|
2004
2072
|
|
|
2005
2073
|
// Should be different from user manager
|
|
2006
2074
|
expect(todoManager).not.toBe(userManager1);
|
|
@@ -3398,3 +3466,4 @@ The product-facing error contract is described in
|
|
|
3398
3466
|
- [MethodNotImplementedError.ts](..%2F..%2Flib%2Ferrors%2FMethodNotImplementedError.ts)
|
|
3399
3467
|
- [DependencyMissingKeyError.ts](..%2F..%2Flib%2Ferrors%2FDependencyMissingKeyError.ts)
|
|
3400
3468
|
- [ContainerDisposedError.ts](..%2F..%2Flib%2Ferrors%2FContainerDisposedError.ts)
|
|
3469
|
+
- [ArgumentNotFoundError.ts](..%2F..%2Flib%2Ferrors%2FArgumentNotFoundError.ts)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ArgumentNotFoundError = void 0;
|
|
4
|
+
const ContainerError_1 = require("./ContainerError");
|
|
5
|
+
class ArgumentNotFoundError extends ContainerError_1.ContainerError {
|
|
6
|
+
name = 'ArgumentNotFoundError';
|
|
7
|
+
constructor(message = 'Argument not found') {
|
|
8
|
+
super(message);
|
|
9
|
+
Object.setPrototypeOf(this, ArgumentNotFoundError.prototype);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.ArgumentNotFoundError = ArgumentNotFoundError;
|
package/cjm/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.
|
|
5
|
-
exports.Is = exports.unwrapProxy = void 0;
|
|
3
|
+
exports.injectProp = exports.createHookExecutionContext = exports.createHookContextFactory = exports.HookContext = exports.toHookFn = exports.hasHooks = exports.hook = exports.getHooks = exports.ArgumentNotFoundError = exports.TypedEventDisposedError = exports.UnsupportedTokenTypeError = exports.CannonSingletonApplyTwiceError = exports.ProviderDisposedError = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyMissingKeyError = exports.ContainerNotFoundError = exports.DependencyNotFoundError = exports.ContainerError = exports.Registration = exports.onResolve = exports.appendArgsFn = exports.appendArgs = exports.decorate = exports.singleton = exports.autoResolve = exports.lazy = exports.scopeAccess = exports.scope = exports.bindTo = exports.register = exports.toRegistrationFn = exports.toProviderFn = exports.toBindToken = exports.registerPipe = exports.isProviderPipe = exports.Provider = exports.ProxyInjector = exports.SimpleInjector = exports.resolveArgs = exports.argsFn = exports.args = exports.arg = exports.inject = exports.MetadataInjector = exports.Injector = exports.EmptyContainer = exports.AutoResolveModule = exports.Container = exports.isDependencyKey = void 0;
|
|
4
|
+
exports.pipe = exports.select = exports.TypedEvent = exports.getConstructorChain = exports.memoize = exports.once = exports.shallowCache = exports.debounce = exports.throttle = exports.runAtOnce = exports.runInOrder = exports.handleAsyncError = exports.handleError = exports.getMethodTags = exports.addMethodTag = exports.getMethodLabels = exports.addMethodLabel = exports.getMethodMeta = exports.addMethodMeta = exports.getParamTags = exports.addParamTag = exports.getParamLabels = exports.addParamLabel = exports.getParamMeta = exports.addParamMeta = exports.getClassTags = exports.addClassTag = exports.getClassLabels = exports.addClassLabel = exports.getClassMeta = exports.addClassMeta = exports.resolveConstructor = exports.GroupInstanceToken = exports.ConstantToken = exports.FunctionToken = exports.SingleToken = exports.ClassToken = exports.toSingleAlias = exports.SingleAliasToken = exports.toGroupAlias = exports.GroupAliasToken = exports.argToToken = exports.toMappedToken = exports.toToken = exports.InjectionToken = exports.toTask = exports.HookCollector = exports.oncePerInstance = exports.parallel = exports.sequential = void 0;
|
|
5
|
+
exports.Is = exports.unwrapProxy = exports.ProxyRegistry = exports.findOrFail = void 0;
|
|
6
6
|
var IContainer_1 = require("./container/IContainer");
|
|
7
7
|
Object.defineProperty(exports, "isDependencyKey", { enumerable: true, get: function () { return IContainer_1.isDependencyKey; } });
|
|
8
8
|
var Container_1 = require("./container/Container");
|
|
@@ -65,6 +65,8 @@ var UnsupportedTokenTypeError_1 = require("./errors/UnsupportedTokenTypeError");
|
|
|
65
65
|
Object.defineProperty(exports, "UnsupportedTokenTypeError", { enumerable: true, get: function () { return UnsupportedTokenTypeError_1.UnsupportedTokenTypeError; } });
|
|
66
66
|
var TypedEventDisposedError_1 = require("./errors/TypedEventDisposedError");
|
|
67
67
|
Object.defineProperty(exports, "TypedEventDisposedError", { enumerable: true, get: function () { return TypedEventDisposedError_1.TypedEventDisposedError; } });
|
|
68
|
+
var ArgumentNotFoundError_1 = require("./errors/ArgumentNotFoundError");
|
|
69
|
+
Object.defineProperty(exports, "ArgumentNotFoundError", { enumerable: true, get: function () { return ArgumentNotFoundError_1.ArgumentNotFoundError; } });
|
|
68
70
|
var hook_1 = require("./hooks/hook");
|
|
69
71
|
Object.defineProperty(exports, "getHooks", { enumerable: true, get: function () { return hook_1.getHooks; } });
|
|
70
72
|
Object.defineProperty(exports, "hook", { enumerable: true, get: function () { return hook_1.hook; } });
|
|
@@ -152,6 +154,8 @@ var select_1 = require("./select");
|
|
|
152
154
|
Object.defineProperty(exports, "select", { enumerable: true, get: function () { return select_1.select; } });
|
|
153
155
|
var fp_1 = require("./utils/fp");
|
|
154
156
|
Object.defineProperty(exports, "pipe", { enumerable: true, get: function () { return fp_1.pipe; } });
|
|
157
|
+
var array_1 = require("./utils/array");
|
|
158
|
+
Object.defineProperty(exports, "findOrFail", { enumerable: true, get: function () { return array_1.findOrFail; } });
|
|
155
159
|
var ProxyRegistry_1 = require("./utils/ProxyRegistry");
|
|
156
160
|
Object.defineProperty(exports, "ProxyRegistry", { enumerable: true, get: function () { return ProxyRegistry_1.ProxyRegistry; } });
|
|
157
161
|
Object.defineProperty(exports, "unwrapProxy", { enumerable: true, get: function () { return ProxyRegistry_1.unwrapProxy; } });
|
|
@@ -27,6 +27,6 @@ const args = (c, { args = [] }) => args;
|
|
|
27
27
|
exports.args = args;
|
|
28
28
|
const resolveArgs = (target, methodName) => {
|
|
29
29
|
const tokens = (0, parameter_1.getParamMeta)(hookMetaKey(methodName), target);
|
|
30
|
-
return (scope, { args = [], lazy }) => tokens.map((fn) => fn.resolve(scope, { args
|
|
30
|
+
return (scope, { args = [], lazy }) => tokens.map((fn) => fn.resolve(scope, { args, lazy }));
|
|
31
31
|
};
|
|
32
32
|
exports.resolveArgs = resolveArgs;
|
package/cjm/token/ClassToken.js
CHANGED
|
@@ -6,7 +6,7 @@ class ClassToken extends InjectionToken_1.InjectionToken {
|
|
|
6
6
|
target;
|
|
7
7
|
_getArgsFn;
|
|
8
8
|
_isLazy;
|
|
9
|
-
constructor(target, { getArgsFn =
|
|
9
|
+
constructor(target, { getArgsFn = InjectionToken_1.forwardArgs, isLazy = false } = {}) {
|
|
10
10
|
super();
|
|
11
11
|
this.target = target;
|
|
12
12
|
this._getArgsFn = getArgsFn;
|
|
@@ -6,7 +6,7 @@ class FunctionToken extends InjectionToken_1.InjectionToken {
|
|
|
6
6
|
fn;
|
|
7
7
|
_getArgsFn;
|
|
8
8
|
_isLazy;
|
|
9
|
-
constructor(fn, { getArgsFn =
|
|
9
|
+
constructor(fn, { getArgsFn = InjectionToken_1.forwardArgs, isLazy = false } = {}) {
|
|
10
10
|
super();
|
|
11
11
|
this.fn = fn;
|
|
12
12
|
this._getArgsFn = getArgsFn;
|
|
@@ -6,7 +6,7 @@ class GroupAliasToken extends InjectionToken_1.InjectionToken {
|
|
|
6
6
|
token;
|
|
7
7
|
_getArgsFn;
|
|
8
8
|
_isLazy;
|
|
9
|
-
constructor(token, { getArgsFn =
|
|
9
|
+
constructor(token, { getArgsFn = InjectionToken_1.forwardArgs, isLazy = false } = {}) {
|
|
10
10
|
super();
|
|
11
11
|
this.token = token;
|
|
12
12
|
this._getArgsFn = getArgsFn;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.InjectionToken = void 0;
|
|
3
|
+
exports.InjectionToken = exports.forwardArgs = void 0;
|
|
4
4
|
exports.isInjectionToken = isInjectionToken;
|
|
5
5
|
const basic_1 = require("../utils/basic");
|
|
6
|
+
const forwardArgs = (_, { args = [] } = {}) => args;
|
|
7
|
+
exports.forwardArgs = forwardArgs;
|
|
6
8
|
class InjectionToken {
|
|
7
9
|
}
|
|
8
10
|
exports.InjectionToken = InjectionToken;
|
|
@@ -6,7 +6,7 @@ class SingleAliasToken extends InjectionToken_1.InjectionToken {
|
|
|
6
6
|
token;
|
|
7
7
|
_getArgsFn;
|
|
8
8
|
_isLazy;
|
|
9
|
-
constructor(token, { getArgsFn =
|
|
9
|
+
constructor(token, { getArgsFn = InjectionToken_1.forwardArgs, isLazy = false } = {}) {
|
|
10
10
|
super();
|
|
11
11
|
this.token = token;
|
|
12
12
|
this._getArgsFn = getArgsFn;
|
package/cjm/token/SingleToken.js
CHANGED
|
@@ -6,7 +6,7 @@ class SingleToken extends InjectionToken_1.InjectionToken {
|
|
|
6
6
|
token;
|
|
7
7
|
_getArgsFn;
|
|
8
8
|
_isLazy;
|
|
9
|
-
constructor(token, { getArgsFn =
|
|
9
|
+
constructor(token, { getArgsFn = InjectionToken_1.forwardArgs, isLazy = false } = {}) {
|
|
10
10
|
super();
|
|
11
11
|
this.token = token;
|
|
12
12
|
this._getArgsFn = getArgsFn;
|
package/cjm/utils/array.js
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Filter = void 0;
|
|
3
|
+
exports.findOrFail = exports.Filter = void 0;
|
|
4
|
+
const ArgumentNotFoundError_1 = require("../errors/ArgumentNotFoundError");
|
|
4
5
|
exports.Filter = {
|
|
5
6
|
exclude: (arr) => {
|
|
6
7
|
const excludeSet = arr instanceof Array ? new Set(arr) : arr;
|
|
7
8
|
return (v) => !excludeSet.has(v);
|
|
8
9
|
},
|
|
9
10
|
};
|
|
11
|
+
const findOrFail = (predicate) => (...args) => {
|
|
12
|
+
const index = args.findIndex((arg) => predicate(arg));
|
|
13
|
+
if (index === -1) {
|
|
14
|
+
throw new ArgumentNotFoundError_1.ArgumentNotFoundError();
|
|
15
|
+
}
|
|
16
|
+
return args[index];
|
|
17
|
+
};
|
|
18
|
+
exports.findOrFail = findOrFail;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ContainerError } from './ContainerError.js';
|
|
2
|
+
export class ArgumentNotFoundError extends ContainerError {
|
|
3
|
+
name = 'ArgumentNotFoundError';
|
|
4
|
+
constructor(message = 'Argument not found') {
|
|
5
|
+
super(message);
|
|
6
|
+
Object.setPrototypeOf(this, ArgumentNotFoundError.prototype);
|
|
7
|
+
}
|
|
8
|
+
}
|
package/esm/index.js
CHANGED
|
@@ -19,6 +19,7 @@ export { ProviderDisposedError } from './errors/ProviderDisposedError.js';
|
|
|
19
19
|
export { CannonSingletonApplyTwiceError } from './errors/CannonSingletonApplyTwiceError.js';
|
|
20
20
|
export { UnsupportedTokenTypeError } from './errors/UnsupportedTokenTypeError.js';
|
|
21
21
|
export { TypedEventDisposedError } from './errors/TypedEventDisposedError.js';
|
|
22
|
+
export { ArgumentNotFoundError } from './errors/ArgumentNotFoundError.js';
|
|
22
23
|
export { getHooks, hook, hasHooks, toHookFn, } from './hooks/hook.js';
|
|
23
24
|
export { HookContext, createHookContextFactory, createHookExecutionContext, } from './hooks/HookContext.js';
|
|
24
25
|
export { injectProp } from './hooks/injectProp.js';
|
|
@@ -48,5 +49,6 @@ export { getConstructorChain } from './utils/getConstructorChain.js';
|
|
|
48
49
|
export { TypedEvent } from './utils/TypedEvent.js';
|
|
49
50
|
export { select } from './select.js';
|
|
50
51
|
export { pipe } from './utils/fp.js';
|
|
52
|
+
export { findOrFail } from './utils/array.js';
|
|
51
53
|
export { ProxyRegistry, unwrapProxy } from './utils/ProxyRegistry.js';
|
|
52
54
|
export { Is } from './utils/basic.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Injector } from './IInjector.js';
|
|
2
2
|
import { resolveConstructor } from '../metadata/target.js';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { addParamMeta, getParamMeta } from '../metadata/parameter.js';
|
|
4
|
+
import { toMappedToken } from '../token/toToken.js';
|
|
5
5
|
export class MetadataInjector extends Injector {
|
|
6
6
|
createInstance(scope, Target, { args: deps = [] } = {}) {
|
|
7
7
|
const args = resolveArgs(Target)(scope, { args: deps });
|
|
@@ -19,5 +19,5 @@ export const arg = (index) => argsFn((value, i) => i === index);
|
|
|
19
19
|
export const args = (c, { args = [] }) => args;
|
|
20
20
|
export const resolveArgs = (target, methodName) => {
|
|
21
21
|
const tokens = getParamMeta(hookMetaKey(methodName), target);
|
|
22
|
-
return (scope, { args = [], lazy }) => tokens.map((fn) => fn.resolve(scope, { args
|
|
22
|
+
return (scope, { args = [], lazy }) => tokens.map((fn) => fn.resolve(scope, { args, lazy }));
|
|
23
23
|
};
|
package/esm/token/ClassToken.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { InjectionToken } from './InjectionToken.js';
|
|
1
|
+
import { forwardArgs, InjectionToken } from './InjectionToken.js';
|
|
2
2
|
export class ClassToken extends InjectionToken {
|
|
3
3
|
target;
|
|
4
4
|
_getArgsFn;
|
|
5
5
|
_isLazy;
|
|
6
|
-
constructor(target, { getArgsFn =
|
|
6
|
+
constructor(target, { getArgsFn = forwardArgs, isLazy = false } = {}) {
|
|
7
7
|
super();
|
|
8
8
|
this.target = target;
|
|
9
9
|
this._getArgsFn = getArgsFn;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { InjectionToken } from './InjectionToken.js';
|
|
1
|
+
import { forwardArgs, InjectionToken } from './InjectionToken.js';
|
|
2
2
|
export class FunctionToken extends InjectionToken {
|
|
3
3
|
fn;
|
|
4
4
|
_getArgsFn;
|
|
5
5
|
_isLazy;
|
|
6
|
-
constructor(fn, { getArgsFn =
|
|
6
|
+
constructor(fn, { getArgsFn = forwardArgs, isLazy = false } = {}) {
|
|
7
7
|
super();
|
|
8
8
|
this.fn = fn;
|
|
9
9
|
this._getArgsFn = getArgsFn;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { InjectionToken } from './InjectionToken.js';
|
|
1
|
+
import { forwardArgs, InjectionToken } from './InjectionToken.js';
|
|
2
2
|
export class GroupAliasToken extends InjectionToken {
|
|
3
3
|
token;
|
|
4
4
|
_getArgsFn;
|
|
5
5
|
_isLazy;
|
|
6
|
-
constructor(token, { getArgsFn =
|
|
6
|
+
constructor(token, { getArgsFn = forwardArgs, isLazy = false } = {}) {
|
|
7
7
|
super();
|
|
8
8
|
this.token = token;
|
|
9
9
|
this._getArgsFn = getArgsFn;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { InjectionToken } from './InjectionToken.js';
|
|
1
|
+
import { forwardArgs, InjectionToken } from './InjectionToken.js';
|
|
2
2
|
export class SingleAliasToken extends InjectionToken {
|
|
3
3
|
token;
|
|
4
4
|
_getArgsFn;
|
|
5
5
|
_isLazy;
|
|
6
|
-
constructor(token, { getArgsFn =
|
|
6
|
+
constructor(token, { getArgsFn = forwardArgs, isLazy = false } = {}) {
|
|
7
7
|
super();
|
|
8
8
|
this.token = token;
|
|
9
9
|
this._getArgsFn = getArgsFn;
|
package/esm/token/SingleToken.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { InjectionToken } from './InjectionToken.js';
|
|
1
|
+
import { forwardArgs, InjectionToken } from './InjectionToken.js';
|
|
2
2
|
export class SingleToken extends InjectionToken {
|
|
3
3
|
token;
|
|
4
4
|
_getArgsFn;
|
|
5
5
|
_isLazy;
|
|
6
|
-
constructor(token, { getArgsFn =
|
|
6
|
+
constructor(token, { getArgsFn = forwardArgs, isLazy = false } = {}) {
|
|
7
7
|
super();
|
|
8
8
|
this.token = token;
|
|
9
9
|
this._getArgsFn = getArgsFn;
|
package/esm/utils/array.js
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
import { ArgumentNotFoundError } from '../errors/ArgumentNotFoundError.js';
|
|
1
2
|
export const Filter = {
|
|
2
3
|
exclude: (arr) => {
|
|
3
4
|
const excludeSet = arr instanceof Array ? new Set(arr) : arr;
|
|
4
5
|
return (v) => !excludeSet.has(v);
|
|
5
6
|
},
|
|
6
7
|
};
|
|
8
|
+
export const findOrFail = (predicate) => (...args) => {
|
|
9
|
+
const index = args.findIndex((arg) => predicate(arg));
|
|
10
|
+
if (index === -1) {
|
|
11
|
+
throw new ArgumentNotFoundError();
|
|
12
|
+
}
|
|
13
|
+
return args[index];
|
|
14
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-ioc-container",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "69.0.0",
|
|
4
4
|
"description": "Fast, lightweight TypeScript dependency injection container with a clean API, scoped lifecycles, decorators, tokens, hooks, lazy injection, customizable providers, and no global container objects.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
package/typings/index.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ export { ProviderDisposedError } from './errors/ProviderDisposedError.js';
|
|
|
20
20
|
export { CannonSingletonApplyTwiceError } from './errors/CannonSingletonApplyTwiceError.js';
|
|
21
21
|
export { UnsupportedTokenTypeError } from './errors/UnsupportedTokenTypeError.js';
|
|
22
22
|
export { TypedEventDisposedError } from './errors/TypedEventDisposedError.js';
|
|
23
|
+
export { ArgumentNotFoundError } from './errors/ArgumentNotFoundError.js';
|
|
23
24
|
export { getHooks, hook, hasHooks, toHookFn, type HookFn, type HookClass, type HookType, type InjectFn, type HooksOfClass, } from './hooks/hook.js';
|
|
24
25
|
export { HookContext, createHookContextFactory, createHookExecutionContext, type CreateHookExecutionContext, type IHookContext, } from './hooks/HookContext.js';
|
|
25
26
|
export { injectProp } from './hooks/injectProp.js';
|
|
@@ -50,5 +51,6 @@ export { TypedEvent, type ITypedEvent, type TypedEventListener, type Unsubscribe
|
|
|
50
51
|
export { type ExecutionContext } from './ExecutionContext.js';
|
|
51
52
|
export { select } from './select.js';
|
|
52
53
|
export { pipe, type MapFn } from './utils/fp.js';
|
|
54
|
+
export { findOrFail, type Predicate } from './utils/array.js';
|
|
53
55
|
export { ProxyRegistry, unwrapProxy, type IProxyRegistry } from './utils/ProxyRegistry.js';
|
|
54
56
|
export { type Branded, type constructor, type Instance, Is } from './utils/basic.js';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type IContainer } from '../container/IContainer.js';
|
|
2
|
-
import { ProviderOptions } from '../provider/IProvider.js';
|
|
2
|
+
import { ArgsFn, ProviderOptions } from '../provider/IProvider.js';
|
|
3
|
+
export declare const forwardArgs: ArgsFn;
|
|
3
4
|
export declare abstract class InjectionToken<T = any> {
|
|
4
5
|
abstract resolve(s: IContainer, options?: ProviderOptions): T;
|
|
5
6
|
abstract args(...deps: unknown[]): InjectionToken<T>;
|
package/typings/utils/array.d.ts
CHANGED