ts-ioc-container 48.0.0 → 49.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 +12 -13
- package/cjm/injector/inject.js +1 -1
- package/esm/injector/inject.js +1 -1
- package/package.json +1 -1
- package/typings/injector/inject.d.ts +1 -1
package/README.md
CHANGED
|
@@ -1912,13 +1912,15 @@ When you pass an `InjectionToken` via `token.args(...)`, the container resolves
|
|
|
1912
1912
|
- `ServiceToken.args(new ClassToken(SomeService))` — `SomeService` is constructed by the container
|
|
1913
1913
|
- `ServiceToken.args('literal')` — literal value passed directly
|
|
1914
1914
|
|
|
1915
|
-
### Positional arg injection with `args(index)`
|
|
1915
|
+
### Positional arg injection with `args(index)` and `argsFn`
|
|
1916
1916
|
|
|
1917
1917
|
Constructor parameters that should pick up positional args from `ProviderOptions` must be annotated with `@inject(args(index))`. Parameters without `@inject` resolve to `undefined`.
|
|
1918
1918
|
|
|
1919
1919
|
- `@inject(args(0))` — resolves the first element of the `args` array passed at resolution time
|
|
1920
1920
|
- Works together with `token.args(...)` to pass typed dependencies through the args context
|
|
1921
1921
|
|
|
1922
|
+
`args(index)` and `argsFn(fn)` are thin shortcuts for an `InjectFn`. Every `InjectFn` receives `(scope, options)`, where `options.args` is the runtime args array — so `args(0)` is just `(scope, { args = [] }) => args[0]`, and `argsFn(fn)` is `(scope, { args = [] }) => fn(...args)` (the runtime args are spread into your callback as positional parameters).
|
|
1923
|
+
|
|
1922
1924
|
### Immutable token chaining
|
|
1923
1925
|
|
|
1924
1926
|
`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).
|
|
@@ -1962,12 +1964,13 @@ describe('ArgsProvider', function () {
|
|
|
1962
1964
|
|
|
1963
1965
|
describe('Static Arguments', () => {
|
|
1964
1966
|
it('can pass static arguments to constructor', function () {
|
|
1967
|
+
// Pre-configure the logger with a filename
|
|
1968
|
+
@register(setArgs('/var/log/app.log'))
|
|
1965
1969
|
class FileLogger {
|
|
1966
1970
|
constructor(@inject(args(0)) public filename: string) {}
|
|
1967
1971
|
}
|
|
1968
1972
|
|
|
1969
|
-
|
|
1970
|
-
const root = createContainer().addRegistration(R.fromClass(FileLogger).pipe(setArgs('/var/log/app.log')));
|
|
1973
|
+
const root = createContainer().addRegistration(R.fromClass(FileLogger));
|
|
1971
1974
|
|
|
1972
1975
|
// Resolve by class name (default key) to use the registered provider
|
|
1973
1976
|
const logger = root.resolve<FileLogger>('FileLogger');
|
|
@@ -1975,15 +1978,15 @@ describe('ArgsProvider', function () {
|
|
|
1975
1978
|
});
|
|
1976
1979
|
|
|
1977
1980
|
it('prioritizes provided args over resolve args', function () {
|
|
1981
|
+
// 'FixedContext' wins over any runtime args
|
|
1982
|
+
@register(setArgs('FixedContext'))
|
|
1978
1983
|
class Logger {
|
|
1979
1984
|
constructor(@inject(args(0)) public context: string) {}
|
|
1980
1985
|
}
|
|
1981
1986
|
|
|
1982
|
-
|
|
1983
|
-
const root = createContainer().addRegistration(R.fromClass(Logger).pipe(setArgs('FixedContext')));
|
|
1987
|
+
const root = createContainer().addRegistration(R.fromClass(Logger));
|
|
1984
1988
|
|
|
1985
1989
|
// Even if we ask for 'RuntimeContext', we get 'FixedContext'
|
|
1986
|
-
// Resolve by class name to use the registered provider
|
|
1987
1990
|
const logger = root.resolve<Logger>('Logger', { args: ['RuntimeContext'] });
|
|
1988
1991
|
|
|
1989
1992
|
expect(logger.context).toBe('FixedContext');
|
|
@@ -1996,19 +1999,15 @@ describe('ArgsProvider', function () {
|
|
|
1996
1999
|
env = 'production';
|
|
1997
2000
|
}
|
|
1998
2001
|
|
|
2002
|
+
// Extract 'env' from Config service dynamically
|
|
2003
|
+
@register(setArgsFn((scope) => [scope.resolve<Config>('Config').env]))
|
|
1999
2004
|
class Service {
|
|
2000
2005
|
constructor(@inject(args(0)) public env: string) {}
|
|
2001
2006
|
}
|
|
2002
2007
|
|
|
2003
2008
|
const root = createContainer()
|
|
2004
2009
|
.addRegistration(R.fromClass(Config)) // Key: 'Config'
|
|
2005
|
-
.addRegistration(
|
|
2006
|
-
R.fromClass(Service).pipe(
|
|
2007
|
-
// Extract 'env' from Config service dynamically
|
|
2008
|
-
// Note: We resolve 'Config' by string key to get the registered instance (if it were singleton)
|
|
2009
|
-
setArgsFn((scope) => [scope.resolve<Config>('Config').env]),
|
|
2010
|
-
),
|
|
2011
|
-
);
|
|
2010
|
+
.addRegistration(R.fromClass(Service));
|
|
2012
2011
|
|
|
2013
2012
|
const service = root.resolve<Service>('Service');
|
|
2014
2013
|
expect(service.env).toBe('production');
|
package/cjm/injector/inject.js
CHANGED
|
@@ -15,7 +15,7 @@ const args = (index) => (c, { args = [] }) => {
|
|
|
15
15
|
return args[index];
|
|
16
16
|
};
|
|
17
17
|
exports.args = args;
|
|
18
|
-
const argsFn = (fn) => (c, options) => fn(options.args ?? []);
|
|
18
|
+
const argsFn = (fn) => (c, options) => fn(...(options.args ?? []));
|
|
19
19
|
exports.argsFn = argsFn;
|
|
20
20
|
const resolveTokens = (scope, deps) => deps.map((v) => ((0, InjectionToken_1.isInjectionToken)(v) ? v : new ConstantToken_1.ConstantToken(v))).map((t) => t.resolve(scope));
|
|
21
21
|
const resolveArgs = (Target, methodName) => {
|
package/esm/injector/inject.js
CHANGED
|
@@ -10,7 +10,7 @@ export const inject = (fn) => (target, propertyKey, parameterIndex) => {
|
|
|
10
10
|
export const args = (index) => (c, { args = [] }) => {
|
|
11
11
|
return args[index];
|
|
12
12
|
};
|
|
13
|
-
export const argsFn = (fn) => (c, options) => fn(options.args ?? []);
|
|
13
|
+
export const argsFn = (fn) => (c, options) => fn(...(options.args ?? []));
|
|
14
14
|
const resolveTokens = (scope, deps) => deps.map((v) => (isInjectionToken(v) ? v : new ConstantToken(v))).map((t) => t.resolve(scope));
|
|
15
15
|
export const resolveArgs = (Target, methodName) => {
|
|
16
16
|
const argsMetaTokens = getParamMeta(hookMetaKey(methodName), Target);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-ioc-container",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "49.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
|
"workspaces": [
|
|
6
6
|
"docs"
|
|
@@ -5,5 +5,5 @@ import { type constructor } from '../utils/basic';
|
|
|
5
5
|
import { ProviderOptions } from '../provider/IProvider';
|
|
6
6
|
export declare const inject: <T>(fn: InjectionToken<T> | InjectFn<T> | symbol | string | constructor<T>) => ParameterDecorator;
|
|
7
7
|
export declare const args: (index: number) => InjectFn;
|
|
8
|
-
export declare const argsFn: <T>(fn: (args: unknown[]) => T) => InjectFn<T>;
|
|
8
|
+
export declare const argsFn: <T>(fn: (...args: unknown[]) => T) => InjectFn<T>;
|
|
9
9
|
export declare const resolveArgs: (Target: constructor<unknown>, methodName?: string) => (scope: IContainer, { args, lazy }: ProviderOptions) => unknown[];
|