ts-ioc-container 31.8.0 → 31.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 +98 -1
- package/cjm/index.js +24 -16
- package/cjm/provider/LazyProvider.js +23 -0
- package/esm/index.js +13 -7
- package/esm/provider/LazyProvider.js +18 -0
- package/package.json +2 -2
- package/typings/index.d.ts +9 -8
- package/typings/provider/LazyProvider.d.ts +8 -0
package/README.md
CHANGED
|
@@ -34,7 +34,9 @@
|
|
|
34
34
|
- [Arguments](#arguments) `args`
|
|
35
35
|
- [Visibility](#visibility) `visible`
|
|
36
36
|
- [Alias](#alias) `alias`
|
|
37
|
-
- [
|
|
37
|
+
- [Lazy](#lazy) `lazy`
|
|
38
|
+
- [Registration](#registration) `@register`
|
|
39
|
+
- [Key](#key) `key`
|
|
38
40
|
- [Scope](#scope) `scope`
|
|
39
41
|
- [Module](#module)
|
|
40
42
|
- [Hook](#hook) `@hook`
|
|
@@ -806,6 +808,95 @@ describe('alias', () => {
|
|
|
806
808
|
|
|
807
809
|
```
|
|
808
810
|
|
|
811
|
+
### Lazy
|
|
812
|
+
Sometimes you want to create dependency only when somebody want to invoke it's method or property. This is what `LazyProvider` is for.
|
|
813
|
+
- `@provider(lazy)`
|
|
814
|
+
|
|
815
|
+
```typescript
|
|
816
|
+
import { lazy, Container, inject, MetadataInjector, provider, Registration as R, singleton, by } from 'ts-ioc-container';
|
|
817
|
+
|
|
818
|
+
describe('lazy provider', () => {
|
|
819
|
+
@provider(singleton())
|
|
820
|
+
class Flag {
|
|
821
|
+
isSet = false;
|
|
822
|
+
|
|
823
|
+
set() {
|
|
824
|
+
this.isSet = true;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
@provider(lazy)
|
|
829
|
+
class Service {
|
|
830
|
+
name = 'Service';
|
|
831
|
+
|
|
832
|
+
constructor(@inject(by.key('Flag')) private flag: Flag) {
|
|
833
|
+
this.flag.set();
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
greet() {
|
|
837
|
+
return 'Hello';
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
function createContainer() {
|
|
842
|
+
const container = new Container(new MetadataInjector());
|
|
843
|
+
container.add(R.fromClass(Flag)).add(R.fromClass(Service));
|
|
844
|
+
return container;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
it('should not create an instance until method is not invoked', () => {
|
|
848
|
+
// Arrange
|
|
849
|
+
const container = createContainer();
|
|
850
|
+
|
|
851
|
+
// Act
|
|
852
|
+
const service = container.resolve<Service>('Service');
|
|
853
|
+
const flag = container.resolve<Flag>('Flag');
|
|
854
|
+
|
|
855
|
+
// Assert
|
|
856
|
+
expect(service.greet()).toBe('Hello');
|
|
857
|
+
expect(flag.isSet).toBe(true);
|
|
858
|
+
});
|
|
859
|
+
|
|
860
|
+
it('should create an instance only when some method/property is invoked', () => {
|
|
861
|
+
// Arrange
|
|
862
|
+
const container = createContainer();
|
|
863
|
+
|
|
864
|
+
// Act
|
|
865
|
+
const service = container.resolve<Service>('Service');
|
|
866
|
+
const flag = container.resolve<Flag>('Flag');
|
|
867
|
+
|
|
868
|
+
// Assert
|
|
869
|
+
expect(flag.isSet).toBe(false);
|
|
870
|
+
});
|
|
871
|
+
|
|
872
|
+
it('should not create instance on every method invoked', () => {
|
|
873
|
+
// Arrange
|
|
874
|
+
const container = createContainer();
|
|
875
|
+
|
|
876
|
+
// Act
|
|
877
|
+
const service = container.resolve<Service>('Service');
|
|
878
|
+
|
|
879
|
+
// Assert
|
|
880
|
+
expect(service.greet()).toBe('Hello');
|
|
881
|
+
expect(service.greet()).toBe('Hello');
|
|
882
|
+
expect(container.getInstances().filter((x) => x instanceof Service).length).toBe(1);
|
|
883
|
+
});
|
|
884
|
+
|
|
885
|
+
it('should create instance when property is invoked', () => {
|
|
886
|
+
// Arrange
|
|
887
|
+
const container = createContainer();
|
|
888
|
+
|
|
889
|
+
// Act
|
|
890
|
+
const service = container.resolve<Service>('Service');
|
|
891
|
+
const flag = container.resolve<Flag>('Flag');
|
|
892
|
+
|
|
893
|
+
// Assert
|
|
894
|
+
expect(service.name).toBe('Service');
|
|
895
|
+
expect(flag.isSet).toBe(true);
|
|
896
|
+
});
|
|
897
|
+
});
|
|
898
|
+
|
|
899
|
+
```
|
|
809
900
|
|
|
810
901
|
## Registration
|
|
811
902
|
Registration is provider factory which registers provider in container.
|
|
@@ -815,6 +906,12 @@ Registration is provider factory which registers provider in container.
|
|
|
815
906
|
- `Registration.fromValue(Logger)`
|
|
816
907
|
- `Registration.fromFn((container, ...args) => container.resolve(Logger, {args}))`
|
|
817
908
|
|
|
909
|
+
### Key
|
|
910
|
+
Sometimes you want to register provider with certain key. This is what `key` is for.
|
|
911
|
+
|
|
912
|
+
- by default, key is class name
|
|
913
|
+
- you can assign the same key to different registrations
|
|
914
|
+
|
|
818
915
|
```typescript
|
|
819
916
|
import 'reflect-metadata';
|
|
820
917
|
import { Container, key, MetadataInjector, provider, register, Registration as R, scope, singleton } from 'ts-ioc-container';
|
package/cjm/index.js
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
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.IMemoKey = exports.by = exports.hasHooks = exports.hook = exports.getHooks = exports.
|
|
3
|
+
exports.getParameterMetadata = exports.getMethodMetadata = exports.setMethodMetadata = exports.setParameterMetadata = exports.getMetadata = exports.setMetadata = exports.IMemoKey = exports.by = exports.hasHooks = exports.hook = exports.getHooks = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyNotFoundError = exports.Registration = exports.register = exports.scope = exports.key = exports.lazy = exports.LazyProvider = 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.inject = exports.MetadataInjector = exports.AutoMockedContainer = exports.EmptyContainer = exports.Container = exports.isDependencyKey = void 0;
|
|
4
|
+
// Containers
|
|
4
5
|
var IContainer_1 = require("./container/IContainer");
|
|
5
6
|
Object.defineProperty(exports, "isDependencyKey", { enumerable: true, get: function () { return IContainer_1.isDependencyKey; } });
|
|
6
7
|
var Container_1 = require("./container/Container");
|
|
7
8
|
Object.defineProperty(exports, "Container", { enumerable: true, get: function () { return Container_1.Container; } });
|
|
8
9
|
var EmptyContainer_1 = require("./container/EmptyContainer");
|
|
9
10
|
Object.defineProperty(exports, "EmptyContainer", { enumerable: true, get: function () { return EmptyContainer_1.EmptyContainer; } });
|
|
10
|
-
var
|
|
11
|
-
Object.defineProperty(exports, "
|
|
12
|
-
var
|
|
13
|
-
Object.defineProperty(exports, "
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
var AutoMockedContainer_1 = require("./container/AutoMockedContainer");
|
|
12
|
+
Object.defineProperty(exports, "AutoMockedContainer", { enumerable: true, get: function () { return AutoMockedContainer_1.AutoMockedContainer; } });
|
|
13
|
+
var MetadataInjector_1 = require("./injector/MetadataInjector");
|
|
14
|
+
Object.defineProperty(exports, "MetadataInjector", { enumerable: true, get: function () { return MetadataInjector_1.MetadataInjector; } });
|
|
15
|
+
Object.defineProperty(exports, "inject", { enumerable: true, get: function () { return MetadataInjector_1.inject; } });
|
|
16
|
+
var SimpleInjector_1 = require("./injector/SimpleInjector");
|
|
17
|
+
Object.defineProperty(exports, "SimpleInjector", { enumerable: true, get: function () { return SimpleInjector_1.SimpleInjector; } });
|
|
18
|
+
var ProxyInjector_1 = require("./injector/ProxyInjector");
|
|
19
|
+
Object.defineProperty(exports, "ProxyInjector", { enumerable: true, get: function () { return ProxyInjector_1.ProxyInjector; } });
|
|
20
|
+
// Providers
|
|
16
21
|
var IProvider_1 = require("./provider/IProvider");
|
|
17
22
|
Object.defineProperty(exports, "provider", { enumerable: true, get: function () { return IProvider_1.provider; } });
|
|
18
23
|
Object.defineProperty(exports, "visible", { enumerable: true, get: function () { return IProvider_1.visible; } });
|
|
@@ -28,21 +33,24 @@ Object.defineProperty(exports, "SingletonProvider", { enumerable: true, get: fun
|
|
|
28
33
|
var MultiCache_1 = require("./provider/singleton/MultiCache");
|
|
29
34
|
Object.defineProperty(exports, "MultiCache", { enumerable: true, get: function () { return MultiCache_1.MultiCache; } });
|
|
30
35
|
Object.defineProperty(exports, "multiCache", { enumerable: true, get: function () { return MultiCache_1.multiCache; } });
|
|
31
|
-
var
|
|
32
|
-
Object.defineProperty(exports, "
|
|
36
|
+
var LazyProvider_1 = require("./provider/LazyProvider");
|
|
37
|
+
Object.defineProperty(exports, "LazyProvider", { enumerable: true, get: function () { return LazyProvider_1.LazyProvider; } });
|
|
38
|
+
Object.defineProperty(exports, "lazy", { enumerable: true, get: function () { return LazyProvider_1.lazy; } });
|
|
39
|
+
// Registrations
|
|
33
40
|
var IRegistration_1 = require("./registration/IRegistration");
|
|
34
41
|
Object.defineProperty(exports, "key", { enumerable: true, get: function () { return IRegistration_1.key; } });
|
|
35
42
|
Object.defineProperty(exports, "scope", { enumerable: true, get: function () { return IRegistration_1.scope; } });
|
|
36
43
|
Object.defineProperty(exports, "register", { enumerable: true, get: function () { return IRegistration_1.register; } });
|
|
37
44
|
var Registration_1 = require("./registration/Registration");
|
|
38
45
|
Object.defineProperty(exports, "Registration", { enumerable: true, get: function () { return Registration_1.Registration; } });
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
Object.defineProperty(exports, "
|
|
42
|
-
var
|
|
43
|
-
Object.defineProperty(exports, "
|
|
44
|
-
var
|
|
45
|
-
Object.defineProperty(exports, "
|
|
46
|
+
// Errors
|
|
47
|
+
var DependencyNotFoundError_1 = require("./errors/DependencyNotFoundError");
|
|
48
|
+
Object.defineProperty(exports, "DependencyNotFoundError", { enumerable: true, get: function () { return DependencyNotFoundError_1.DependencyNotFoundError; } });
|
|
49
|
+
var MethodNotImplementedError_1 = require("./errors/MethodNotImplementedError");
|
|
50
|
+
Object.defineProperty(exports, "MethodNotImplementedError", { enumerable: true, get: function () { return MethodNotImplementedError_1.MethodNotImplementedError; } });
|
|
51
|
+
var ContainerDisposedError_1 = require("./errors/ContainerDisposedError");
|
|
52
|
+
Object.defineProperty(exports, "ContainerDisposedError", { enumerable: true, get: function () { return ContainerDisposedError_1.ContainerDisposedError; } });
|
|
53
|
+
// Others
|
|
46
54
|
var hook_1 = require("./hook");
|
|
47
55
|
Object.defineProperty(exports, "getHooks", { enumerable: true, get: function () { return hook_1.getHooks; } });
|
|
48
56
|
Object.defineProperty(exports, "hook", { enumerable: true, get: function () { return hook_1.hook; } });
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.lazy = exports.LazyProvider = void 0;
|
|
4
|
+
const IProvider_1 = require("./IProvider");
|
|
5
|
+
class LazyProvider extends IProvider_1.ProviderDecorator {
|
|
6
|
+
constructor(provider) {
|
|
7
|
+
super(provider);
|
|
8
|
+
this.provider = provider;
|
|
9
|
+
}
|
|
10
|
+
resolve(container, ...args) {
|
|
11
|
+
let instance;
|
|
12
|
+
return new Proxy({}, {
|
|
13
|
+
get: (_, prop) => {
|
|
14
|
+
instance = instance ?? this.provider.resolve(container, ...args);
|
|
15
|
+
// @ts-ignore
|
|
16
|
+
return instance[prop];
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.LazyProvider = LazyProvider;
|
|
22
|
+
const lazy = (provider) => new LazyProvider(provider);
|
|
23
|
+
exports.lazy = lazy;
|
package/esm/index.js
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
1
|
+
// Containers
|
|
1
2
|
export { isDependencyKey, } from './container/IContainer';
|
|
2
3
|
export { Container } from './container/Container';
|
|
3
4
|
export { EmptyContainer } from './container/EmptyContainer';
|
|
4
|
-
export {
|
|
5
|
-
export {
|
|
6
|
-
export {
|
|
5
|
+
export { AutoMockedContainer } from './container/AutoMockedContainer';
|
|
6
|
+
export { MetadataInjector, inject } from './injector/MetadataInjector';
|
|
7
|
+
export { SimpleInjector } from './injector/SimpleInjector';
|
|
8
|
+
export { ProxyInjector } from './injector/ProxyInjector';
|
|
9
|
+
// Providers
|
|
7
10
|
export { provider, visible, alias, argsFn, args, ProviderDecorator, } from './provider/IProvider';
|
|
8
11
|
export { Provider } from './provider/Provider';
|
|
9
12
|
export { singleton, SingletonProvider } from './provider/singleton/SingletonProvider';
|
|
10
13
|
export { MultiCache, multiCache } from './provider/singleton/MultiCache';
|
|
11
|
-
export {
|
|
14
|
+
export { LazyProvider, lazy } from './provider/LazyProvider';
|
|
15
|
+
// Registrations
|
|
12
16
|
export { key, scope, register } from './registration/IRegistration';
|
|
13
17
|
export { Registration } from './registration/Registration';
|
|
14
|
-
|
|
15
|
-
export {
|
|
16
|
-
export {
|
|
18
|
+
// Errors
|
|
19
|
+
export { DependencyNotFoundError } from './errors/DependencyNotFoundError';
|
|
20
|
+
export { MethodNotImplementedError } from './errors/MethodNotImplementedError';
|
|
21
|
+
export { ContainerDisposedError } from './errors/ContainerDisposedError';
|
|
22
|
+
// Others
|
|
17
23
|
export { getHooks, hook, hasHooks } from './hook';
|
|
18
24
|
export { by, IMemoKey } from './by';
|
|
19
25
|
export { setMetadata, getMetadata, setParameterMetadata, setMethodMetadata, getMethodMetadata, getParameterMetadata, } from './metadata';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ProviderDecorator } from './IProvider';
|
|
2
|
+
export class LazyProvider extends ProviderDecorator {
|
|
3
|
+
constructor(provider) {
|
|
4
|
+
super(provider);
|
|
5
|
+
this.provider = provider;
|
|
6
|
+
}
|
|
7
|
+
resolve(container, ...args) {
|
|
8
|
+
let instance;
|
|
9
|
+
return new Proxy({}, {
|
|
10
|
+
get: (_, prop) => {
|
|
11
|
+
instance = instance ?? this.provider.resolve(container, ...args);
|
|
12
|
+
// @ts-ignore
|
|
13
|
+
return instance[prop];
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export const lazy = (provider) => new LazyProvider(provider);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-ioc-container",
|
|
3
|
-
"version": "31.
|
|
3
|
+
"version": "31.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": "c0874ed0eb277f524b3aa96ed2a39d626af2ba8b"
|
|
63
63
|
}
|
package/typings/index.d.ts
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
export { IContainer, Resolvable, IContainerModule, isDependencyKey, DependencyKey, InjectionToken, Tag, Tagged, } from './container/IContainer';
|
|
2
|
-
export { constructor } from './utils';
|
|
3
2
|
export { Container } from './container/Container';
|
|
4
3
|
export { EmptyContainer } from './container/EmptyContainer';
|
|
4
|
+
export { AutoMockedContainer } from './container/AutoMockedContainer';
|
|
5
5
|
export { IInjector } from './injector/IInjector';
|
|
6
|
-
export {
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
6
|
+
export { MetadataInjector, inject } from './injector/MetadataInjector';
|
|
7
|
+
export { SimpleInjector } from './injector/SimpleInjector';
|
|
8
|
+
export { ProxyInjector } from './injector/ProxyInjector';
|
|
9
9
|
export { ResolveDependency, IProvider, provider, visible, alias, argsFn, args, ArgsFn, ProviderDecorator, } from './provider/IProvider';
|
|
10
10
|
export { Provider } from './provider/Provider';
|
|
11
11
|
export { singleton, SingletonProvider } from './provider/singleton/SingletonProvider';
|
|
12
12
|
export { MultiCache, multiCache } from './provider/singleton/MultiCache';
|
|
13
13
|
export { Cache } from './provider/singleton/Cache';
|
|
14
|
-
export {
|
|
14
|
+
export { LazyProvider, lazy } from './provider/LazyProvider';
|
|
15
15
|
export { key, IRegistration, scope, register } from './registration/IRegistration';
|
|
16
16
|
export { Registration } from './registration/Registration';
|
|
17
|
-
export {
|
|
18
|
-
export {
|
|
19
|
-
export {
|
|
17
|
+
export { DependencyNotFoundError } from './errors/DependencyNotFoundError';
|
|
18
|
+
export { MethodNotImplementedError } from './errors/MethodNotImplementedError';
|
|
19
|
+
export { ContainerDisposedError } from './errors/ContainerDisposedError';
|
|
20
20
|
export { getHooks, hook, hasHooks } from './hook';
|
|
21
21
|
export { by, InstancePredicate, IMemo, IMemoKey } from './by';
|
|
22
|
+
export { constructor } from './utils';
|
|
22
23
|
export { setMetadata, getMetadata, setParameterMetadata, setMethodMetadata, getMethodMetadata, getParameterMetadata, } from './metadata';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { IProvider, ProviderDecorator } from './IProvider';
|
|
2
|
+
import { IContainer } from '../container/IContainer';
|
|
3
|
+
export declare class LazyProvider<Instance> extends ProviderDecorator<Instance> {
|
|
4
|
+
private provider;
|
|
5
|
+
constructor(provider: IProvider<Instance>);
|
|
6
|
+
resolve(container: IContainer, ...args: unknown[]): Instance;
|
|
7
|
+
}
|
|
8
|
+
export declare const lazy: <Instance>(provider: IProvider<Instance>) => LazyProvider<Instance>;
|