ts-ioc-container 32.7.0 → 32.9.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 +55 -0
- package/cjm/hooks/ExecutionContext.js +4 -0
- package/cjm/hooks/hook.js +16 -3
- package/cjm/index.js +5 -2
- package/esm/hooks/ExecutionContext.js +4 -0
- package/esm/hooks/hook.js +13 -2
- package/esm/index.js +3 -2
- package/package.json +2 -2
- package/typings/hooks/ExecutionContext.d.ts +2 -0
- package/typings/hooks/hook.d.ts +6 -0
- package/typings/index.d.ts +1 -1
package/README.md
CHANGED
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
- supports `tagged scopes`
|
|
15
15
|
- fully test covered :100:
|
|
16
16
|
- can be used with decorators `@inject`
|
|
17
|
+
- can [inject properties](#inject-property)
|
|
18
|
+
- can inject [lazy dependencies](#lazy)
|
|
17
19
|
- composable and open to extend
|
|
18
20
|
- awesome for testing (auto mocking)
|
|
19
21
|
|
|
@@ -43,6 +45,8 @@
|
|
|
43
45
|
- [Hook](#hook) `@hook`
|
|
44
46
|
- [OnConstruct](#onconstruct) `@onConstruct`
|
|
45
47
|
- [OnDispose](#ondispose) `@onDispose`
|
|
48
|
+
- [Inject Property](#inject-property)
|
|
49
|
+
- [Inject Method](#inject-method)
|
|
46
50
|
- [Mock](#mock)
|
|
47
51
|
- [Error](#error)
|
|
48
52
|
|
|
@@ -357,6 +361,7 @@ describe('lazy provider', () => {
|
|
|
357
361
|
|
|
358
362
|
### Metadata
|
|
359
363
|
This type of injector uses `@inject` decorator to mark where dependencies should be injected. It's bases on `reflect-metadata` package. That's why I call it `MetadataInjector`.
|
|
364
|
+
Also you can [inject property.](#inject-property)
|
|
360
365
|
|
|
361
366
|
```typescript
|
|
362
367
|
import 'reflect-metadata';
|
|
@@ -1255,6 +1260,56 @@ describe('onDispose', function () {
|
|
|
1255
1260
|
|
|
1256
1261
|
```
|
|
1257
1262
|
|
|
1263
|
+
### Inject property
|
|
1264
|
+
|
|
1265
|
+
```typescript
|
|
1266
|
+
import { by, Container, executeHooks, hook, injectProp, MetadataInjector, Registration } from 'ts-ioc-container';
|
|
1267
|
+
|
|
1268
|
+
describe('inject property', () => {
|
|
1269
|
+
it('should inject property', () => {
|
|
1270
|
+
class App {
|
|
1271
|
+
@hook('onInit', injectProp(by.key('greeting')))
|
|
1272
|
+
greeting!: string;
|
|
1273
|
+
}
|
|
1274
|
+
const expected = 'Hello world!';
|
|
1275
|
+
|
|
1276
|
+
const container = new Container(new MetadataInjector()).add(Registration.fromValue(expected).to('greeting'));
|
|
1277
|
+
const app = container.resolve(App);
|
|
1278
|
+
executeHooks(app, 'onInit', { scope: container });
|
|
1279
|
+
|
|
1280
|
+
expect(app.greeting).toBe(expected);
|
|
1281
|
+
});
|
|
1282
|
+
});
|
|
1283
|
+
|
|
1284
|
+
```
|
|
1285
|
+
|
|
1286
|
+
### Inject method
|
|
1287
|
+
|
|
1288
|
+
```typescript
|
|
1289
|
+
import { by, Container, executeHooks, hook, inject, invokeExecution, MetadataInjector, Registration } from 'ts-ioc-container';
|
|
1290
|
+
|
|
1291
|
+
describe('inject method', () => {
|
|
1292
|
+
it('should inject method', () => {
|
|
1293
|
+
class App {
|
|
1294
|
+
greeting!: string;
|
|
1295
|
+
|
|
1296
|
+
@hook('onInit', invokeExecution({ handleError: jest.fn(), handleResult: jest.fn() }))
|
|
1297
|
+
setGreeting(@inject(by.key('greeting')) greeting: string) {
|
|
1298
|
+
this.greeting = greeting;
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
const expected = 'Hello world!';
|
|
1302
|
+
|
|
1303
|
+
const container = new Container(new MetadataInjector()).add(Registration.fromValue(expected).to('greeting'));
|
|
1304
|
+
const app = container.resolve(App);
|
|
1305
|
+
executeHooks(app, 'onInit', { scope: container });
|
|
1306
|
+
|
|
1307
|
+
expect(app.greeting).toBe(expected);
|
|
1308
|
+
});
|
|
1309
|
+
});
|
|
1310
|
+
|
|
1311
|
+
```
|
|
1312
|
+
|
|
1258
1313
|
## Mock
|
|
1259
1314
|
Sometimes you need to automatically mock all dependencies in container. This is what `AutoMockedContainer` is for.
|
|
1260
1315
|
|
package/cjm/hooks/hook.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.executeHooks = exports.hasHooks = exports.getHooks = exports.hook = void 0;
|
|
3
|
+
exports.invokeExecution = exports.injectProp = exports.executeHooks = exports.hasHooks = exports.getHooks = exports.hook = void 0;
|
|
4
4
|
const ExecutionContext_1 = require("./ExecutionContext");
|
|
5
|
-
const
|
|
5
|
+
const MetadataInjector_1 = require("../injector/MetadataInjector");
|
|
6
6
|
const hook = (key, ...fns) => (target, propertyKey) => {
|
|
7
7
|
const hooks = Reflect.hasMetadata(key, target.constructor)
|
|
8
8
|
? Reflect.getMetadata(key, target.constructor)
|
|
9
|
-
:
|
|
9
|
+
: new Map();
|
|
10
10
|
hooks.set(propertyKey, (hooks.get(propertyKey) ?? []).concat(fns));
|
|
11
11
|
Reflect.defineMetadata(key, hooks, target.constructor); // eslint-disable-line @typescript-eslint/ban-types
|
|
12
12
|
};
|
|
@@ -27,3 +27,16 @@ const executeHooks = (target, key, { scope, createContext = (c) => c, }) => {
|
|
|
27
27
|
}
|
|
28
28
|
};
|
|
29
29
|
exports.executeHooks = executeHooks;
|
|
30
|
+
const injectProp = (fn) => (context) => context.injectProperty(fn);
|
|
31
|
+
exports.injectProp = injectProp;
|
|
32
|
+
const invokeExecution = ({ handleError, handleResult, }) => (context) => {
|
|
33
|
+
const args = (0, MetadataInjector_1.resolveArgs)(context.instance.constructor, context.methodName)(context.scope);
|
|
34
|
+
try {
|
|
35
|
+
const result = context.invokeMethod({ args });
|
|
36
|
+
handleResult(result, context);
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
handleError(e, context.scope);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
exports.invokeExecution = invokeExecution;
|
package/cjm/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getParameterMetadata = exports.getMethodMetadata = exports.setMethodMetadata = exports.setParameterMetadata = exports.getMetadata = exports.setMetadata = exports.byAliases = exports.byAlias = exports.IMemoKey = exports.by = exports.ExecutionContext = exports.executeHooks = exports.hasHooks = exports.hook = exports.getHooks = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyNotFoundError = exports.Registration = exports.register = exports.scope = exports.key = exports.decorate = exports.multiCache = exports.MultiCache = exports.SingletonProvider = exports.singleton = exports.Provider = exports.ProviderDecorator = exports.args = exports.argsFn = exports.alias = exports.visible = exports.provider = exports.ProxyInjector = exports.SimpleInjector = exports.getInjectFns = exports.resolveArgs = exports.inject = exports.MetadataInjector = exports.AutoMockedContainer = exports.EmptyContainer = exports.Container = exports.isDependencyKey = void 0;
|
|
3
|
+
exports.getParameterMetadata = exports.getMethodMetadata = exports.setMethodMetadata = exports.setParameterMetadata = exports.getMetadata = exports.setMetadata = exports.byAliases = exports.byAlias = exports.IMemoKey = exports.by = exports.ExecutionContext = exports.invokeExecution = exports.injectProp = exports.executeHooks = exports.hasHooks = exports.hook = exports.getHooks = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyNotFoundError = exports.Registration = exports.register = exports.scope = exports.key = exports.decorate = exports.multiCache = exports.MultiCache = exports.SingletonProvider = exports.singleton = exports.Provider = exports.ProviderDecorator = exports.args = exports.argsFn = exports.alias = exports.visible = exports.provider = exports.ProxyInjector = exports.SimpleInjector = exports.getInjectFns = exports.resolveArgs = exports.inject = exports.MetadataInjector = exports.AutoMockedContainer = exports.EmptyContainer = exports.Container = exports.isDependencyKey = void 0;
|
|
4
4
|
// Containers
|
|
5
5
|
var IContainer_1 = require("./container/IContainer");
|
|
6
6
|
Object.defineProperty(exports, "isDependencyKey", { enumerable: true, get: function () { return IContainer_1.isDependencyKey; } });
|
|
@@ -51,14 +51,17 @@ var MethodNotImplementedError_1 = require("./errors/MethodNotImplementedError");
|
|
|
51
51
|
Object.defineProperty(exports, "MethodNotImplementedError", { enumerable: true, get: function () { return MethodNotImplementedError_1.MethodNotImplementedError; } });
|
|
52
52
|
var ContainerDisposedError_1 = require("./errors/ContainerDisposedError");
|
|
53
53
|
Object.defineProperty(exports, "ContainerDisposedError", { enumerable: true, get: function () { return ContainerDisposedError_1.ContainerDisposedError; } });
|
|
54
|
-
//
|
|
54
|
+
// Hooks
|
|
55
55
|
var hook_1 = require("./hooks/hook");
|
|
56
56
|
Object.defineProperty(exports, "getHooks", { enumerable: true, get: function () { return hook_1.getHooks; } });
|
|
57
57
|
Object.defineProperty(exports, "hook", { enumerable: true, get: function () { return hook_1.hook; } });
|
|
58
58
|
Object.defineProperty(exports, "hasHooks", { enumerable: true, get: function () { return hook_1.hasHooks; } });
|
|
59
59
|
Object.defineProperty(exports, "executeHooks", { enumerable: true, get: function () { return hook_1.executeHooks; } });
|
|
60
|
+
Object.defineProperty(exports, "injectProp", { enumerable: true, get: function () { return hook_1.injectProp; } });
|
|
61
|
+
Object.defineProperty(exports, "invokeExecution", { enumerable: true, get: function () { return hook_1.invokeExecution; } });
|
|
60
62
|
var ExecutionContext_1 = require("./hooks/ExecutionContext");
|
|
61
63
|
Object.defineProperty(exports, "ExecutionContext", { enumerable: true, get: function () { return ExecutionContext_1.ExecutionContext; } });
|
|
64
|
+
// Others
|
|
62
65
|
var by_1 = require("./by");
|
|
63
66
|
Object.defineProperty(exports, "by", { enumerable: true, get: function () { return by_1.by; } });
|
|
64
67
|
Object.defineProperty(exports, "IMemoKey", { enumerable: true, get: function () { return by_1.IMemoKey; } });
|
package/esm/hooks/hook.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ExecutionContext } from './ExecutionContext';
|
|
2
|
-
|
|
2
|
+
import { resolveArgs } from '../injector/MetadataInjector';
|
|
3
3
|
export const hook = (key, ...fns) => (target, propertyKey) => {
|
|
4
4
|
const hooks = Reflect.hasMetadata(key, target.constructor)
|
|
5
5
|
? Reflect.getMetadata(key, target.constructor)
|
|
6
|
-
:
|
|
6
|
+
: new Map();
|
|
7
7
|
hooks.set(propertyKey, (hooks.get(propertyKey) ?? []).concat(fns));
|
|
8
8
|
Reflect.defineMetadata(key, hooks, target.constructor); // eslint-disable-line @typescript-eslint/ban-types
|
|
9
9
|
};
|
|
@@ -20,3 +20,14 @@ export const executeHooks = (target, key, { scope, createContext = (c) => c, })
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
|
+
export const injectProp = (fn) => (context) => context.injectProperty(fn);
|
|
24
|
+
export const invokeExecution = ({ handleError, handleResult, }) => (context) => {
|
|
25
|
+
const args = resolveArgs(context.instance.constructor, context.methodName)(context.scope);
|
|
26
|
+
try {
|
|
27
|
+
const result = context.invokeMethod({ args });
|
|
28
|
+
handleResult(result, context);
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
handleError(e, context.scope);
|
|
32
|
+
}
|
|
33
|
+
};
|
package/esm/index.js
CHANGED
|
@@ -19,8 +19,9 @@ export { Registration } from './registration/Registration';
|
|
|
19
19
|
export { DependencyNotFoundError } from './errors/DependencyNotFoundError';
|
|
20
20
|
export { MethodNotImplementedError } from './errors/MethodNotImplementedError';
|
|
21
21
|
export { ContainerDisposedError } from './errors/ContainerDisposedError';
|
|
22
|
-
//
|
|
23
|
-
export { getHooks, hook, hasHooks, executeHooks } from './hooks/hook';
|
|
22
|
+
// Hooks
|
|
23
|
+
export { getHooks, hook, hasHooks, executeHooks, injectProp, invokeExecution } from './hooks/hook';
|
|
24
24
|
export { ExecutionContext } from './hooks/ExecutionContext';
|
|
25
|
+
// Others
|
|
25
26
|
export { by, IMemoKey, byAlias, byAliases } from './by';
|
|
26
27
|
export { setMetadata, getMetadata, setParameterMetadata, setMethodMetadata, getMethodMetadata, getParameterMetadata, } from './metadata';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-ioc-container",
|
|
3
|
-
"version": "32.
|
|
3
|
+
"version": "32.9.0",
|
|
4
4
|
"description": "Typescript IoC container",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"ts-node": "^10.9.1",
|
|
60
60
|
"typescript": "5.4.3"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "17060847c051dbbdfd167675ec27af2ae78efbfe"
|
|
63
63
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { InjectFn } from '../injector/MetadataInjector';
|
|
1
2
|
import { IContainer } from '../container/IContainer';
|
|
2
3
|
export declare class ExecutionContext {
|
|
3
4
|
instance: object;
|
|
@@ -8,4 +9,5 @@ export declare class ExecutionContext {
|
|
|
8
9
|
invokeMethod({ args }: {
|
|
9
10
|
args: unknown[];
|
|
10
11
|
}): unknown;
|
|
12
|
+
injectProperty(fn: InjectFn): void;
|
|
11
13
|
}
|
package/typings/hooks/hook.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { IContainer } from '../container/IContainer';
|
|
2
2
|
import { ExecutionContext } from './ExecutionContext';
|
|
3
|
+
import { InjectFn } from '../injector/MetadataInjector';
|
|
3
4
|
export type Execution<T extends ExecutionContext = ExecutionContext> = (context: T) => void;
|
|
4
5
|
export declare const hook: (key: string | symbol, ...fns: Execution[]) => (target: object, propertyKey: string | symbol) => void;
|
|
5
6
|
export declare function getHooks(target: object, key: string | symbol): Map<string, Execution[]>;
|
|
@@ -8,3 +9,8 @@ export declare const executeHooks: <Context extends ExecutionContext>(target: ob
|
|
|
8
9
|
scope: IContainer;
|
|
9
10
|
createContext?: ((c: ExecutionContext) => Context) | undefined;
|
|
10
11
|
}) => void;
|
|
12
|
+
export declare const injectProp: (fn: InjectFn) => Execution;
|
|
13
|
+
export declare const invokeExecution: ({ handleError, handleResult, }: {
|
|
14
|
+
handleError: (e: Error, s: IContainer) => void;
|
|
15
|
+
handleResult: (result: unknown, context: ExecutionContext) => void;
|
|
16
|
+
}) => Execution;
|
package/typings/index.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export { Registration } from './registration/Registration';
|
|
|
17
17
|
export { DependencyNotFoundError } from './errors/DependencyNotFoundError';
|
|
18
18
|
export { MethodNotImplementedError } from './errors/MethodNotImplementedError';
|
|
19
19
|
export { ContainerDisposedError } from './errors/ContainerDisposedError';
|
|
20
|
-
export { getHooks, hook, hasHooks, Execution, executeHooks } from './hooks/hook';
|
|
20
|
+
export { getHooks, hook, hasHooks, Execution, executeHooks, injectProp, invokeExecution } from './hooks/hook';
|
|
21
21
|
export { ExecutionContext } from './hooks/ExecutionContext';
|
|
22
22
|
export { by, InstancePredicate, IMemo, IMemoKey, byAlias, byAliases } from './by';
|
|
23
23
|
export { constructor } from './utils';
|