@kaokei/di 2.0.8 → 3.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 +27 -56
- package/dist/binding.d.cts +36 -0
- package/dist/binding.d.ts +36 -0
- package/dist/cachemap.d.cts +21 -0
- package/dist/cachemap.d.ts +21 -0
- package/dist/constants.d.cts +28 -0
- package/dist/constants.d.ts +28 -0
- package/dist/container.d.cts +29 -0
- package/dist/container.d.ts +29 -0
- package/dist/decorator.d.cts +18 -0
- package/dist/decorator.d.ts +18 -0
- package/dist/errors/BaseError.d.cts +4 -0
- package/dist/errors/BaseError.d.ts +4 -0
- package/dist/errors/BindingNotFoundError.d.cts +5 -0
- package/dist/errors/BindingNotFoundError.d.ts +5 -0
- package/dist/errors/BindingNotValidError.d.cts +5 -0
- package/dist/errors/BindingNotValidError.d.ts +5 -0
- package/dist/errors/CircularDependencyError.d.cts +5 -0
- package/dist/errors/CircularDependencyError.d.ts +5 -0
- package/dist/errors/DuplicateBindingError.d.cts +5 -0
- package/dist/errors/DuplicateBindingError.d.ts +5 -0
- package/dist/errors/PostConstructError.d.cts +5 -0
- package/dist/errors/PostConstructError.d.ts +5 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +402 -0
- package/dist/interfaces.d.cts +47 -0
- package/dist/interfaces.d.ts +47 -0
- package/dist/lazyinject.d.cts +4 -0
- package/dist/lazyinject.d.ts +4 -0
- package/dist/token.d.cts +12 -0
- package/dist/token.d.ts +12 -0
- package/package.json +38 -97
- package/dist/index.cjs.js +0 -746
- package/dist/index.cjs.js.map +0 -1
- package/dist/index.cjs.min.js +0 -11
- package/dist/index.cjs.min.js.map +0 -1
- package/dist/index.cjs.runtime.js +0 -735
- package/dist/index.cjs.runtime.js.map +0 -1
- package/dist/index.cjs.runtime.min.js +0 -11
- package/dist/index.cjs.runtime.min.js.map +0 -1
- package/dist/index.esm.js +0 -724
- package/dist/index.esm.js.map +0 -1
- package/dist/index.esm.min.js +0 -11
- package/dist/index.esm.min.js.map +0 -1
- package/dist/index.esm.runtime.js +0 -713
- package/dist/index.esm.runtime.js.map +0 -1
- package/dist/index.esm.runtime.min.js +0 -11
- package/dist/index.esm.runtime.min.js.map +0 -1
- package/dist/index.iife.js +0 -749
- package/dist/index.iife.js.map +0 -1
- package/dist/index.iife.min.js +0 -11
- package/dist/index.iife.min.js.map +0 -1
- package/dist/src/Injector.d.ts +0 -143
- package/dist/src/Injector.d.ts.map +0 -1
- package/dist/src/constants.d.ts +0 -17
- package/dist/src/constants.d.ts.map +0 -1
- package/dist/src/decorator.d.ts +0 -42
- package/dist/src/decorator.d.ts.map +0 -1
- package/dist/src/errors/CircularDependencyError.d.ts +0 -6
- package/dist/src/errors/CircularDependencyError.d.ts.map +0 -1
- package/dist/src/errors/ConstructorInjectMissTokenError.d.ts +0 -6
- package/dist/src/errors/ConstructorInjectMissTokenError.d.ts.map +0 -1
- package/dist/src/errors/InjectFailedError.d.ts +0 -6
- package/dist/src/errors/InjectFailedError.d.ts.map +0 -1
- package/dist/src/errors/PropertyInjectMissTokenError.d.ts +0 -6
- package/dist/src/errors/PropertyInjectMissTokenError.d.ts.map +0 -1
- package/dist/src/errors/ProviderNotValidError.d.ts +0 -6
- package/dist/src/errors/ProviderNotValidError.d.ts.map +0 -1
- package/dist/src/errors/TokenNotFoundError.d.ts +0 -6
- package/dist/src/errors/TokenNotFoundError.d.ts.map +0 -1
- package/dist/src/errors/index.d.ts +0 -7
- package/dist/src/errors/index.d.ts.map +0 -1
- package/dist/src/forwardRef.d.ts +0 -7
- package/dist/src/forwardRef.d.ts.map +0 -1
- package/dist/src/index.d.ts +0 -7
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/utils.d.ts +0 -4
- package/dist/src/utils.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<h1 align="center">di</h1>
|
|
1
|
+
<h1 align="center">npm install @kaokei/di</h1>
|
|
2
2
|
<div align="center">
|
|
3
3
|
|
|
4
4
|
[](https://github.com/kaokei/di/actions/workflows/build.yml)
|
|
@@ -6,74 +6,45 @@
|
|
|
6
6
|
[](https://npmcharts.com/compare/@kaokei/di?minimal=true)
|
|
7
7
|
[](https://www.npmjs.com/package/@kaokei/di)
|
|
8
8
|
[](https://www.npmjs.com/package/@kaokei/di)
|
|
9
|
+

|
|
9
10
|
|
|
10
11
|
</div>
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
- [online playground](https://codesandbox.io/s/di-playground-zjnyv)
|
|
14
|
-
- [online demo](https://kaokei.com/project/di/)
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
npm install @kaokei/di reflect-metadata
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## 灵感
|
|
21
|
-
|
|
22
|
-
Inspired by [Spring](https://spring.io/), [Angular](https://angular.io/), [typedi](https://github.com/typestack/typedi), [InversifyJS](https://github.com/inversify/InversifyJS)
|
|
23
|
-
|
|
24
|
-
其他类似的 library 可以[参考这里](https://github.com/topics/ioc?l=typescript)和[参考这里](https://github.com/topics/dependency-injection?l=typescript)
|
|
13
|
+
## 简介
|
|
25
14
|
|
|
26
|
-
|
|
15
|
+
本库是一个轻量级的依赖注入库,类似的其他比较流行的库有`InversifyJS`和`typedi`。
|
|
27
16
|
|
|
28
|
-
|
|
17
|
+
本库主要特点是参考借鉴了`InversifyJS`的优秀 API 设计,不依赖`reflect-metadata`,支持循环依赖。
|
|
29
18
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
## 已经支持的特性
|
|
37
|
-
|
|
38
|
-
- 支持类,Symbol,字符串等作为服务的 token
|
|
39
|
-
- 支持类,值,工厂函数等作为服务
|
|
40
|
-
- 支持@Inject、@Skip、@Self、@Optional 以及 forwardRef 控制获取服务
|
|
41
|
-
- 支持@Optional 配置可选注入以及类属性的初始值作为默认值
|
|
42
|
-
- Injector 作为 DI 容器,易于测试
|
|
43
|
-
- 同一个服务在同一个 Injector 中一定是单例的。相对的[Inversify 支持 3 种 Scope](https://github.com/inversify/InversifyJS/blob/master/wiki/scope.md)。
|
|
44
|
-
- 支持分层 DI 系统
|
|
45
|
-
- 支持属性注入和构造函数注入
|
|
46
|
-
- 支持部分循环依赖,对于不支持的循环依赖会有相应的提示
|
|
47
|
-
- 支持类型提示,以及 InjectionKey 的类型提示
|
|
48
|
-
- 支持 dispose 生命周期钩子
|
|
19
|
+
- [入门指南](./docs/guide/README.md)
|
|
20
|
+
- [API 文档](./docs/api/README.md)
|
|
21
|
+
- [博客文章](./docs/note/01.什么是Token.md)
|
|
22
|
+
- [online playground](https://codesandbox.io/s/di-playground-zjnyv)
|
|
23
|
+
- [online demo](https://codesandbox.io/s/di-playground-zjnyv)
|
|
49
24
|
|
|
50
|
-
##
|
|
25
|
+
## todo
|
|
51
26
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
- 暂时不实现 providers 中使用 forwardRef,主要是不了解使用场景,目前只支持在@Inject 中使用 forwardRef
|
|
56
|
-
- 不支持异步实例化,即该实例对象的状态和数据依赖服务器端数据,需要异步获取,等待获取数据成功之后才实例化对象。对于这种场景建议在实例对象中维护类似 loading/ready/inited 这种字段来表明数据是否准备完毕。
|
|
57
|
-
- 不支持 LazyInject
|
|
58
|
-
- 不支持 onInit/PostConstruct 生命周期钩子,虽然 Spring 中是支持的,但是实际场景中并不常用,[参考这里](https://github.com/angular/angular/issues/23235)以及[参考这里](https://github.com/inversify/InversifyJS/blob/master/wiki/post_construct.md)
|
|
59
|
-
- 不支持中间件,有需要可以[参考这里](https://github.com/inversify/InversifyJS/blob/master/wiki/middleware.md)
|
|
60
|
-
- 原来确实导出了 autobind,后续删除了该导出,有业务需要可以自己 `npm install autobind-decorator` 即可。
|
|
61
|
-
- 没有实现自定义装饰器,比如@Prev、@Post、@Aop 等装饰器,类似 autobind,应该独立维护。
|
|
27
|
+
1. 实现 LazyInject 功能
|
|
28
|
+
关键是怎么实现 container 和 class 的绑定
|
|
29
|
+
正常 inject 时,是可以通过 container.get 获取上下文的,但是 lazyInject 拿不到这个上下文
|
|
62
30
|
|
|
63
|
-
|
|
31
|
+
LazyInject是否需要@Self/@Optional/@SkipSelf来配合?
|
|
32
|
+
需要协调@LazyInject/@Inject,因为现在是两条并行的路线,也就是@Self/@Optional/@SkipSelf默认是和@Inject配合的,现在如果和@LazyInject就会报找不到@Inject的异常
|
|
33
|
+
可以作为低优先级的需求,后续有需要再考虑。
|
|
64
34
|
|
|
65
|
-
|
|
35
|
+
1. 直接使用javascript,不依赖typescript
|
|
66
36
|
|
|
67
|
-
|
|
68
|
-
- [Support for classes](https://github.com/inversify/InversifyJS/blob/master/wiki/classes_as_id.md#known-limitation-classes-as-identifiers-and-circular-dependencies)
|
|
37
|
+
1. getter支持缓存,使用computed支持缓存
|
|
69
38
|
|
|
70
|
-
|
|
39
|
+
应该在use-vue-service中实现
|
|
71
40
|
|
|
72
|
-
|
|
41
|
+
https://yuanbao.tencent.com/bot/app/share/chat/tUbGmhHdY1Ta
|
|
73
42
|
|
|
74
|
-
|
|
43
|
+
2. 优化 https://github.com/kaokei/utils/blob/main/src/index.ts 的文档
|
|
75
44
|
|
|
76
|
-
问题二:已经使用 forawrdRef 解藕了 A 和 B。仍然有运行时错误。
|
|
77
45
|
|
|
78
|
-
|
|
79
|
-
|
|
46
|
+
```ts
|
|
47
|
+
function useAppService<T>(token: interfaces.ServiceIdentifier<T>, app: any) {
|
|
48
|
+
return app.runWithContext(() => useService(token));
|
|
49
|
+
}
|
|
50
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Container } from './container';
|
|
2
|
+
import { Newable, Context, Options, CommonToken, DynamicValue, ActivationHandler, DeactivationHandler } from './interfaces';
|
|
3
|
+
export declare class Binding<T = unknown> {
|
|
4
|
+
container: Container;
|
|
5
|
+
context: Context;
|
|
6
|
+
token: CommonToken<T>;
|
|
7
|
+
type: string;
|
|
8
|
+
status: string;
|
|
9
|
+
classValue: Newable<T>;
|
|
10
|
+
constantValue: T;
|
|
11
|
+
dynamicValue: DynamicValue<T>;
|
|
12
|
+
cache: T;
|
|
13
|
+
postConstructResult?: Promise<void> | Symbol;
|
|
14
|
+
onActivationHandler?: ActivationHandler<T>;
|
|
15
|
+
onDeactivationHandler?: DeactivationHandler<T>;
|
|
16
|
+
constructor(token: CommonToken<T>, container: Container);
|
|
17
|
+
onActivation(handler: ActivationHandler<T>): void;
|
|
18
|
+
onDeactivation(handler: DeactivationHandler<T>): void;
|
|
19
|
+
activate(input: T): T;
|
|
20
|
+
deactivate(): void;
|
|
21
|
+
to(constructor: Newable<T>): this;
|
|
22
|
+
toSelf(): this;
|
|
23
|
+
toConstantValue(value: T): this;
|
|
24
|
+
toDynamicValue(func: DynamicValue<T>): this;
|
|
25
|
+
toService(token: CommonToken<T>): this;
|
|
26
|
+
get(options: Options<T>): T;
|
|
27
|
+
private getAwaitBindings;
|
|
28
|
+
private postConstruct;
|
|
29
|
+
preDestroy(): any;
|
|
30
|
+
private execute;
|
|
31
|
+
private resolveInstanceValue;
|
|
32
|
+
private resolveConstantValue;
|
|
33
|
+
private resolveDynamicValue;
|
|
34
|
+
private getConstructorParameters;
|
|
35
|
+
private getInjectProperties;
|
|
36
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Container } from './container';
|
|
2
|
+
import { Newable, Context, Options, CommonToken, DynamicValue, ActivationHandler, DeactivationHandler } from './interfaces';
|
|
3
|
+
export declare class Binding<T = unknown> {
|
|
4
|
+
container: Container;
|
|
5
|
+
context: Context;
|
|
6
|
+
token: CommonToken<T>;
|
|
7
|
+
type: string;
|
|
8
|
+
status: string;
|
|
9
|
+
classValue: Newable<T>;
|
|
10
|
+
constantValue: T;
|
|
11
|
+
dynamicValue: DynamicValue<T>;
|
|
12
|
+
cache: T;
|
|
13
|
+
postConstructResult?: Promise<void> | Symbol;
|
|
14
|
+
onActivationHandler?: ActivationHandler<T>;
|
|
15
|
+
onDeactivationHandler?: DeactivationHandler<T>;
|
|
16
|
+
constructor(token: CommonToken<T>, container: Container);
|
|
17
|
+
onActivation(handler: ActivationHandler<T>): void;
|
|
18
|
+
onDeactivation(handler: DeactivationHandler<T>): void;
|
|
19
|
+
activate(input: T): T;
|
|
20
|
+
deactivate(): void;
|
|
21
|
+
to(constructor: Newable<T>): this;
|
|
22
|
+
toSelf(): this;
|
|
23
|
+
toConstantValue(value: T): this;
|
|
24
|
+
toDynamicValue(func: DynamicValue<T>): this;
|
|
25
|
+
toService(token: CommonToken<T>): this;
|
|
26
|
+
get(options: Options<T>): T;
|
|
27
|
+
private getAwaitBindings;
|
|
28
|
+
private postConstruct;
|
|
29
|
+
preDestroy(): any;
|
|
30
|
+
private execute;
|
|
31
|
+
private resolveInstanceValue;
|
|
32
|
+
private resolveConstantValue;
|
|
33
|
+
private resolveDynamicValue;
|
|
34
|
+
private getConstructorParameters;
|
|
35
|
+
private getInjectProperties;
|
|
36
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { CommonToken, META_KEYS, META_KEY_INJECTED_PARAMS, META_KEY_INJECTED_PROPS, META_KEY_POST_CONSTRUCT, META_KEY_PRE_DESTROY, META_VALUES, META_VALUE_INJECTED_PARAMS, META_VALUE_INJECTED_PROPS, META_VALUE_POST_CONSTRUCT, META_VALUE_PRE_DESTROY } from './interfaces';
|
|
2
|
+
export declare function defineMetadata(metadataKey: META_KEY_INJECTED_PARAMS, metadataValue: META_VALUE_INJECTED_PARAMS, target: CommonToken): void;
|
|
3
|
+
export declare function defineMetadata(metadataKey: META_KEY_INJECTED_PROPS, metadataValue: META_VALUE_INJECTED_PROPS, target: CommonToken): void;
|
|
4
|
+
export declare function defineMetadata(metadataKey: META_KEY_POST_CONSTRUCT, metadataValue: META_VALUE_POST_CONSTRUCT, target: CommonToken): void;
|
|
5
|
+
export declare function defineMetadata(metadataKey: META_KEY_PRE_DESTROY, metadataValue: META_VALUE_PRE_DESTROY, target: CommonToken): void;
|
|
6
|
+
export declare function defineMetadata(metadataKey: META_KEYS, metadataValue: META_VALUES, target: CommonToken): void;
|
|
7
|
+
export declare function getOwnMetadata(metadataKey: META_KEY_INJECTED_PARAMS, target: CommonToken): META_VALUE_INJECTED_PARAMS | undefined;
|
|
8
|
+
export declare function getOwnMetadata(metadataKey: META_KEY_INJECTED_PROPS, target: CommonToken): META_VALUE_INJECTED_PROPS | undefined;
|
|
9
|
+
export declare function getOwnMetadata(metadataKey: META_KEY_POST_CONSTRUCT, target: CommonToken): META_VALUE_POST_CONSTRUCT | undefined;
|
|
10
|
+
export declare function getOwnMetadata(metadataKey: META_KEY_PRE_DESTROY, target: CommonToken): META_VALUE_PRE_DESTROY | undefined;
|
|
11
|
+
export declare function getOwnMetadata(metadataKey: META_KEYS, target: CommonToken): META_VALUES | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* 使用hasParentClass判断当前target有没有父类
|
|
14
|
+
* 如果没有父类直接使用getOwnMetadata获取数据
|
|
15
|
+
* 如果有父类,那么需要合并getOwnMetadata(target)和getMetadata(target的父类)
|
|
16
|
+
* 不支持META_KEY_INJECTED_PARAMS作为metadataKey
|
|
17
|
+
*/
|
|
18
|
+
export declare function getMetadata(metadataKey: META_KEY_INJECTED_PROPS, target: CommonToken): META_VALUE_INJECTED_PROPS | undefined;
|
|
19
|
+
export declare function getMetadata(metadataKey: META_KEY_POST_CONSTRUCT, target: CommonToken): META_VALUE_POST_CONSTRUCT | undefined;
|
|
20
|
+
export declare function getMetadata(metadataKey: META_KEY_PRE_DESTROY, target: CommonToken): META_VALUE_PRE_DESTROY | undefined;
|
|
21
|
+
export declare function getMetadata(metadataKey: Exclude<META_KEYS, META_KEY_INJECTED_PARAMS>, target: CommonToken): Exclude<META_VALUES, META_VALUE_INJECTED_PARAMS> | undefined;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { CommonToken, META_KEYS, META_KEY_INJECTED_PARAMS, META_KEY_INJECTED_PROPS, META_KEY_POST_CONSTRUCT, META_KEY_PRE_DESTROY, META_VALUES, META_VALUE_INJECTED_PARAMS, META_VALUE_INJECTED_PROPS, META_VALUE_POST_CONSTRUCT, META_VALUE_PRE_DESTROY } from './interfaces';
|
|
2
|
+
export declare function defineMetadata(metadataKey: META_KEY_INJECTED_PARAMS, metadataValue: META_VALUE_INJECTED_PARAMS, target: CommonToken): void;
|
|
3
|
+
export declare function defineMetadata(metadataKey: META_KEY_INJECTED_PROPS, metadataValue: META_VALUE_INJECTED_PROPS, target: CommonToken): void;
|
|
4
|
+
export declare function defineMetadata(metadataKey: META_KEY_POST_CONSTRUCT, metadataValue: META_VALUE_POST_CONSTRUCT, target: CommonToken): void;
|
|
5
|
+
export declare function defineMetadata(metadataKey: META_KEY_PRE_DESTROY, metadataValue: META_VALUE_PRE_DESTROY, target: CommonToken): void;
|
|
6
|
+
export declare function defineMetadata(metadataKey: META_KEYS, metadataValue: META_VALUES, target: CommonToken): void;
|
|
7
|
+
export declare function getOwnMetadata(metadataKey: META_KEY_INJECTED_PARAMS, target: CommonToken): META_VALUE_INJECTED_PARAMS | undefined;
|
|
8
|
+
export declare function getOwnMetadata(metadataKey: META_KEY_INJECTED_PROPS, target: CommonToken): META_VALUE_INJECTED_PROPS | undefined;
|
|
9
|
+
export declare function getOwnMetadata(metadataKey: META_KEY_POST_CONSTRUCT, target: CommonToken): META_VALUE_POST_CONSTRUCT | undefined;
|
|
10
|
+
export declare function getOwnMetadata(metadataKey: META_KEY_PRE_DESTROY, target: CommonToken): META_VALUE_PRE_DESTROY | undefined;
|
|
11
|
+
export declare function getOwnMetadata(metadataKey: META_KEYS, target: CommonToken): META_VALUES | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* 使用hasParentClass判断当前target有没有父类
|
|
14
|
+
* 如果没有父类直接使用getOwnMetadata获取数据
|
|
15
|
+
* 如果有父类,那么需要合并getOwnMetadata(target)和getMetadata(target的父类)
|
|
16
|
+
* 不支持META_KEY_INJECTED_PARAMS作为metadataKey
|
|
17
|
+
*/
|
|
18
|
+
export declare function getMetadata(metadataKey: META_KEY_INJECTED_PROPS, target: CommonToken): META_VALUE_INJECTED_PROPS | undefined;
|
|
19
|
+
export declare function getMetadata(metadataKey: META_KEY_POST_CONSTRUCT, target: CommonToken): META_VALUE_POST_CONSTRUCT | undefined;
|
|
20
|
+
export declare function getMetadata(metadataKey: META_KEY_PRE_DESTROY, target: CommonToken): META_VALUE_PRE_DESTROY | undefined;
|
|
21
|
+
export declare function getMetadata(metadataKey: Exclude<META_KEYS, META_KEY_INJECTED_PARAMS>, target: CommonToken): Exclude<META_VALUES, META_VALUE_INJECTED_PARAMS> | undefined;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export declare const KEYS: {
|
|
2
|
+
readonly INJECTED_PARAMS: "injected:params";
|
|
3
|
+
readonly INJECTED_PROPS: "injected:props";
|
|
4
|
+
readonly INJECT: "inject";
|
|
5
|
+
readonly SELF: "self";
|
|
6
|
+
readonly SKIP_SELF: "skipSelf";
|
|
7
|
+
readonly OPTIONAL: "optional";
|
|
8
|
+
readonly POST_CONSTRUCT: "postConstruct";
|
|
9
|
+
readonly PRE_DESTROY: "preDestroy";
|
|
10
|
+
};
|
|
11
|
+
export declare const STATUS: {
|
|
12
|
+
readonly DEFAULT: "default";
|
|
13
|
+
readonly INITING: "initing";
|
|
14
|
+
readonly ACTIVATED: "activated";
|
|
15
|
+
};
|
|
16
|
+
export declare const BINDING: {
|
|
17
|
+
readonly Invalid: "Invalid";
|
|
18
|
+
readonly Instance: "Instance";
|
|
19
|
+
readonly ConstantValue: "ConstantValue";
|
|
20
|
+
readonly DynamicValue: "DynamicValue";
|
|
21
|
+
};
|
|
22
|
+
export declare const ERRORS: {
|
|
23
|
+
readonly POST_CONSTRUCT: "Cannot apply @PostConstruct decorator multiple times in the same class.";
|
|
24
|
+
readonly PRE_DESTROY: "Cannot apply @PreDestroy decorator multiple times in the same class.";
|
|
25
|
+
readonly MISS_INJECT: "Expected a @Inject decorator to explicitly specify the token.";
|
|
26
|
+
readonly MISS_CONTAINER: "@LazyInject decorator cannot find the corresponding container.";
|
|
27
|
+
};
|
|
28
|
+
export declare const DEFAULT_VALUE: unique symbol;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export declare const KEYS: {
|
|
2
|
+
readonly INJECTED_PARAMS: "injected:params";
|
|
3
|
+
readonly INJECTED_PROPS: "injected:props";
|
|
4
|
+
readonly INJECT: "inject";
|
|
5
|
+
readonly SELF: "self";
|
|
6
|
+
readonly SKIP_SELF: "skipSelf";
|
|
7
|
+
readonly OPTIONAL: "optional";
|
|
8
|
+
readonly POST_CONSTRUCT: "postConstruct";
|
|
9
|
+
readonly PRE_DESTROY: "preDestroy";
|
|
10
|
+
};
|
|
11
|
+
export declare const STATUS: {
|
|
12
|
+
readonly DEFAULT: "default";
|
|
13
|
+
readonly INITING: "initing";
|
|
14
|
+
readonly ACTIVATED: "activated";
|
|
15
|
+
};
|
|
16
|
+
export declare const BINDING: {
|
|
17
|
+
readonly Invalid: "Invalid";
|
|
18
|
+
readonly Instance: "Instance";
|
|
19
|
+
readonly ConstantValue: "ConstantValue";
|
|
20
|
+
readonly DynamicValue: "DynamicValue";
|
|
21
|
+
};
|
|
22
|
+
export declare const ERRORS: {
|
|
23
|
+
readonly POST_CONSTRUCT: "Cannot apply @PostConstruct decorator multiple times in the same class.";
|
|
24
|
+
readonly PRE_DESTROY: "Cannot apply @PreDestroy decorator multiple times in the same class.";
|
|
25
|
+
readonly MISS_INJECT: "Expected a @Inject decorator to explicitly specify the token.";
|
|
26
|
+
readonly MISS_CONTAINER: "@LazyInject decorator cannot find the corresponding container.";
|
|
27
|
+
};
|
|
28
|
+
export declare const DEFAULT_VALUE: unique symbol;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Binding } from './binding';
|
|
2
|
+
import { Options, CommonToken, ActivationHandler, DeactivationHandler } from './interfaces';
|
|
3
|
+
export declare class Container {
|
|
4
|
+
parent?: Container;
|
|
5
|
+
private bindings;
|
|
6
|
+
private onActivationHandler?;
|
|
7
|
+
private onDeactivationHandler?;
|
|
8
|
+
bind<T>(token: CommonToken<T>): Binding<T>;
|
|
9
|
+
unbind<T>(token: CommonToken<T>): void;
|
|
10
|
+
unbindAll(): void;
|
|
11
|
+
isCurrentBound<T>(token: CommonToken<T>): boolean;
|
|
12
|
+
isBound<T>(token: CommonToken<T>): boolean;
|
|
13
|
+
createChild(): Container;
|
|
14
|
+
get<T>(token: CommonToken<T>, options: Options<T> & {
|
|
15
|
+
optional: true;
|
|
16
|
+
}): T | void;
|
|
17
|
+
get<T>(token: CommonToken<T>, options?: Options<T> & {
|
|
18
|
+
optional?: false;
|
|
19
|
+
}): T;
|
|
20
|
+
get<T>(token: CommonToken<T>, options?: Options<T>): T | void;
|
|
21
|
+
onActivation(handler: ActivationHandler): void;
|
|
22
|
+
onDeactivation(handler: DeactivationHandler): void;
|
|
23
|
+
activate<T>(input: T, token: CommonToken<T>): T;
|
|
24
|
+
deactivate<T>(binding: Binding<T>): void;
|
|
25
|
+
private buildBinding;
|
|
26
|
+
private getBinding;
|
|
27
|
+
private checkBindingNotFoundError;
|
|
28
|
+
}
|
|
29
|
+
export declare const CONTAINER_MAP: WeakMap<any, Container>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Binding } from './binding';
|
|
2
|
+
import { Options, CommonToken, ActivationHandler, DeactivationHandler } from './interfaces';
|
|
3
|
+
export declare class Container {
|
|
4
|
+
parent?: Container;
|
|
5
|
+
private bindings;
|
|
6
|
+
private onActivationHandler?;
|
|
7
|
+
private onDeactivationHandler?;
|
|
8
|
+
bind<T>(token: CommonToken<T>): Binding<T>;
|
|
9
|
+
unbind<T>(token: CommonToken<T>): void;
|
|
10
|
+
unbindAll(): void;
|
|
11
|
+
isCurrentBound<T>(token: CommonToken<T>): boolean;
|
|
12
|
+
isBound<T>(token: CommonToken<T>): boolean;
|
|
13
|
+
createChild(): Container;
|
|
14
|
+
get<T>(token: CommonToken<T>, options: Options<T> & {
|
|
15
|
+
optional: true;
|
|
16
|
+
}): T | void;
|
|
17
|
+
get<T>(token: CommonToken<T>, options?: Options<T> & {
|
|
18
|
+
optional?: false;
|
|
19
|
+
}): T;
|
|
20
|
+
get<T>(token: CommonToken<T>, options?: Options<T>): T | void;
|
|
21
|
+
onActivation(handler: ActivationHandler): void;
|
|
22
|
+
onDeactivation(handler: DeactivationHandler): void;
|
|
23
|
+
activate<T>(input: T, token: CommonToken<T>): T;
|
|
24
|
+
deactivate<T>(binding: Binding<T>): void;
|
|
25
|
+
private buildBinding;
|
|
26
|
+
private getBinding;
|
|
27
|
+
private checkBindingNotFoundError;
|
|
28
|
+
}
|
|
29
|
+
export declare const CONTAINER_MAP: WeakMap<any, Container>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { InjectFunction } from './interfaces';
|
|
2
|
+
/**
|
|
3
|
+
* 创建装饰器的高阶函数
|
|
4
|
+
* 装饰器的通用逻辑就是通过cachemap记录到全局的WeakMap中
|
|
5
|
+
*
|
|
6
|
+
* @param {(string )} decoratorKey 代表某个装饰器的名称
|
|
7
|
+
* @param {*} [defaultValue] 该装饰器函数的默认参数
|
|
8
|
+
* @return {*} 装饰器函数
|
|
9
|
+
*/
|
|
10
|
+
declare function createDecorator(decoratorKey: string, defaultValue?: any): (decoratorValue?: any) => (target: any, targetKey?: string, index?: number) => void;
|
|
11
|
+
export declare const Inject: InjectFunction<ReturnType<typeof createDecorator>>;
|
|
12
|
+
export declare const Self: (decoratorValue?: any) => (target: any, targetKey?: string, index?: number) => void;
|
|
13
|
+
export declare const SkipSelf: (decoratorValue?: any) => (target: any, targetKey?: string, index?: number) => void;
|
|
14
|
+
export declare const Optional: (decoratorValue?: any) => (target: any, targetKey?: string, index?: number) => void;
|
|
15
|
+
export declare const PostConstruct: (metaValue: import('./interfaces').PostConstructParam) => (target: any, propertyKey: string) => void;
|
|
16
|
+
export declare const PreDestroy: (metaValue: void) => (target: any, propertyKey: string) => void;
|
|
17
|
+
export declare function decorate(decorator: any, target: any, key: number | string): void;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { InjectFunction } from './interfaces';
|
|
2
|
+
/**
|
|
3
|
+
* 创建装饰器的高阶函数
|
|
4
|
+
* 装饰器的通用逻辑就是通过cachemap记录到全局的WeakMap中
|
|
5
|
+
*
|
|
6
|
+
* @param {(string )} decoratorKey 代表某个装饰器的名称
|
|
7
|
+
* @param {*} [defaultValue] 该装饰器函数的默认参数
|
|
8
|
+
* @return {*} 装饰器函数
|
|
9
|
+
*/
|
|
10
|
+
declare function createDecorator(decoratorKey: string, defaultValue?: any): (decoratorValue?: any) => (target: any, targetKey?: string, index?: number) => void;
|
|
11
|
+
export declare const Inject: InjectFunction<ReturnType<typeof createDecorator>>;
|
|
12
|
+
export declare const Self: (decoratorValue?: any) => (target: any, targetKey?: string, index?: number) => void;
|
|
13
|
+
export declare const SkipSelf: (decoratorValue?: any) => (target: any, targetKey?: string, index?: number) => void;
|
|
14
|
+
export declare const Optional: (decoratorValue?: any) => (target: any, targetKey?: string, index?: number) => void;
|
|
15
|
+
export declare const PostConstruct: (metaValue: import('./interfaces').PostConstructParam) => (target: any, propertyKey: string) => void;
|
|
16
|
+
export declare const PreDestroy: (metaValue: void) => (target: any, propertyKey: string) => void;
|
|
17
|
+
export declare function decorate(decorator: any, target: any, key: number | string): void;
|
|
18
|
+
export {};
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var w=Object.defineProperty;var _=(n,t,e)=>t in n?w(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var o=(n,t,e)=>_(n,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l={INJECTED_PARAMS:"injected:params",INJECTED_PROPS:"injected:props",INJECT:"inject",SELF:"self",SKIP_SELF:"skipSelf",OPTIONAL:"optional",POST_CONSTRUCT:"postConstruct",PRE_DESTROY:"preDestroy"},p={DEFAULT:"default",INITING:"initing",ACTIVATED:"activated"},d={Invalid:"Invalid",Instance:"Instance",ConstantValue:"ConstantValue",DynamicValue:"DynamicValue"},I={POST_CONSTRUCT:"Cannot apply @PostConstruct decorator multiple times in the same class.",PRE_DESTROY:"Cannot apply @PreDestroy decorator multiple times in the same class.",MISS_INJECT:"Expected a @Inject decorator to explicitly specify the token.",MISS_CONTAINER:"@LazyInject decorator cannot find the corresponding container."},P=Symbol(),S=new WeakMap;function j(n){return typeof n=="function"&&Object.getPrototypeOf(n)!==Function.prototype}function N(n,t,e){const s=S.get(e)||{};s[n]=t,S.set(e,s)}function C(n,t){return(S.get(t)||{})[n]}function g(n,t){const e=C(n,t);if(!j(t))return e;const s=g(n,Object.getPrototypeOf(t));if(s||e)return{...s||{},...e||{}}}class k{constructor(t){o(this,"_","");o(this,"name");this.name=t}}class O{constructor(t){o(this,"callback");this.callback=t}resolve(){return this.callback()}}function v(n){if(!n)throw new Error(I.MISS_INJECT);return n instanceof O?n.resolve():n}class T extends Error{constructor(t,e){super(),this.name=this.constructor.name,this.message=`${t}${e==null?void 0:e.name}`}}class b extends T{constructor(t){super("");const e=[];let s=t;for(;s&&s.token;)e.push(s.token),s=s.parent;const i=e.reverse().map(a=>a.name).join(" --> ");this.message=`Circular dependency found: ${i}`}}class B extends T{constructor(t){super("Invalid binding: ",t)}}class M extends b{constructor(t){super(t),this.name="CircularDependencyError inside @PostConstruct"}}class L{constructor(t,e){o(this,"container");o(this,"context");o(this,"token");o(this,"type",d.Invalid);o(this,"status",p.DEFAULT);o(this,"classValue");o(this,"constantValue");o(this,"dynamicValue");o(this,"cache");o(this,"postConstructResult",P);o(this,"onActivationHandler");o(this,"onDeactivationHandler");this.container=e,this.context={container:this.container},this.token=t}onActivation(t){this.onActivationHandler=t}onDeactivation(t){this.onDeactivationHandler=t}activate(t){const e=this.onActivationHandler?this.onActivationHandler(this.context,t):t;return this.container.activate(e,this.token)}deactivate(){this.onDeactivationHandler&&this.onDeactivationHandler(this.cache)}to(t){return this.type=d.Instance,this.classValue=t,this}toSelf(){return this.to(this.token)}toConstantValue(t){return this.type=d.ConstantValue,this.constantValue=t,this}toDynamicValue(t){return this.type=d.DynamicValue,this.dynamicValue=t,this}toService(t){return this.toDynamicValue(e=>e.container.get(t,{parent:{token:this.token}}))}get(t){if(p.INITING===this.status)throw new b(t);if(p.ACTIVATED===this.status)return this.cache;if(d.Instance===this.type)return this.resolveInstanceValue(t);if(d.ConstantValue===this.type)return this.resolveConstantValue();if(d.DynamicValue===this.type)return this.resolveDynamicValue();throw new B(this.token)}getAwaitBindings(t,e){return e===!0?t:Array.isArray(e)?t.filter(s=>e.includes(s.token)):typeof e=="function"?t.filter(e):[]}postConstruct(t,e,s){if(d.Instance===this.type){const{key:i,value:a}=g(l.POST_CONSTRUCT,this.token)||{};if(i)if(a){const r=[...e,...s].filter(u=>d.Instance===(u==null?void 0:u.type)),c=this.getAwaitBindings(r,a);for(const u of c)if(u&&u.postConstructResult===P)throw new M({token:u.token,parent:t});const h=c.map(u=>u.postConstructResult);this.postConstructResult=Promise.all(h).then(()=>this.execute(i))}else this.postConstructResult=this.execute(i);else this.postConstructResult=void 0}}preDestroy(){if(d.Instance===this.type){const{key:t}=g(l.PRE_DESTROY,this.token)||{};if(t)return this.execute(t)}this.container=null,this.context=null}execute(t){const e=this.cache[t];return e==null?void 0:e.call(this.cache)}resolveInstanceValue(t){this.status=p.INITING;const e=this.classValue,[s,i]=this.getConstructorParameters(t),a=new e(...s);this.cache=this.activate(a),this.status=p.ACTIVATED,m.set(this.cache,this.container);const[r,c]=this.getInjectProperties(t);return Object.assign(this.cache,r),this.postConstruct(t,i,c),this.cache}resolveConstantValue(){return this.status=p.INITING,this.cache=this.activate(this.constantValue),this.status=p.ACTIVATED,this.cache}resolveDynamicValue(){this.status=p.INITING;const t=this.dynamicValue.call(this,this.context);return this.cache=this.activate(t),this.status=p.ACTIVATED,this.cache}getConstructorParameters(t){const e=C(l.INJECTED_PARAMS,this.classValue)||[],s=[],i=[];for(let a=0;a<e.length;a++){const r=e[a],{inject:c,...h}=r;h.parent=t;const u=this.container.get(v(c),h);s.push(u),i.push(h.binding)}return[s,i]}getInjectProperties(t){const e=g(l.INJECTED_PROPS,this.classValue)||{},s=Object.keys(e),i=Object.create(null),a=[];for(let r=0;r<s.length;r++){const c=s[r],h=e[c],{inject:u,...f}=h;f.parent=t;const y=this.container.get(v(u),f);y===void 0&&h.optional||(i[c]=y),a.push(f.binding)}return[i,a]}}class x extends T{constructor(t){super("No matching binding found for token: ",t)}}class H extends T{constructor(t){super("Cannot bind token multiple times: ",t)}}class D{constructor(){o(this,"parent");o(this,"bindings",new Map);o(this,"onActivationHandler");o(this,"onDeactivationHandler")}bind(t){if(this.bindings.has(t))throw new H(t);const e=this.buildBinding(t);return this.bindings.set(t,e),e}unbind(t){if(this.bindings.has(t)){const e=this.getBinding(t);this.deactivate(e),e.preDestroy(),this.bindings.delete(t)}}unbindAll(){this.bindings.forEach(t=>{this.unbind(t.token)})}isCurrentBound(t){return this.bindings.has(t)}isBound(t){return this.isCurrentBound(t)||!!this.parent&&this.parent.isBound(t)}createChild(){const t=new D;return t.parent=this,t}get(t,e={}){const s=this.getBinding(t);if(e.skipSelf){if(this.parent)return e.skipSelf=!1,this.parent.get(t,e)}else if(e.self||s){if(s)return e.token=t,e.binding=s,s.get(e)}else if(this.parent)return this.parent.get(t,e);return this.checkBindingNotFoundError(t,e)}onActivation(t){this.onActivationHandler=t}onDeactivation(t){this.onDeactivationHandler=t}activate(t,e){return this.onActivationHandler?this.onActivationHandler({container:this},t,e):t}deactivate(t){this.onDeactivationHandler&&this.onDeactivationHandler(t.cache,t.token),t.deactivate()}buildBinding(t){return new L(t,this)}getBinding(t){return this.bindings.get(t)}checkBindingNotFoundError(t,e){if(!e.optional)throw new x(t)}}const m=new WeakMap;function E(n,t){return function(e){return function(s,i,a){const r=typeof a=="number",c=r?s:s.constructor,h=r?a:i,u=r?l.INJECTED_PARAMS:l.INJECTED_PROPS,f=r?C(u,c)||[]:g(u,c)||{},y=f[h]||{};y[n]=e===void 0?t:e,f[h]=y,N(u,f,c)}}}function V(n,t){return e=>(s,i)=>{if(C(n,s.constructor))throw new Error(t);N(n,{key:i,value:e},s.constructor)}}const F=E(l.INJECT),J=E(l.SELF,!0),U=E(l.SKIP_SELF,!0),z=E(l.OPTIONAL,!0),G=V(l.POST_CONSTRUCT,I.POST_CONSTRUCT),Y=V(l.PRE_DESTROY,I.PRE_DESTROY);function A(n,t,e,s){for(let i=n.length-1;i>=0;i--)n[i](t,e,s)}function K(n,t,e){n=Array.isArray(n)?n:[n],typeof e=="number"?A(n,t,void 0,e):typeof e=="string"&&A(n,t.prototype,e)}function $(n,t,e,s){function i(){const r=Symbol.for(t);if(!this.hasOwnProperty(r)){const c=s||m.get(this),h=this.constructor;if(!c)throw new Error(`${I.MISS_CONTAINER} ${h.name}`);this[r]=c.get(v(e),{parent:{token:h}})}return this[r]}function a(r){const c=Symbol.for(t);this[c]=r}Object.defineProperty(n,t,{configurable:!0,enumerable:!0,get:i,set:a})}function R(n,t){return function(e,s){$(e,s,n,t)}}function W(n){return function(t){return R(t,n)}}exports.CONTAINER_MAP=m;exports.Container=D;exports.Inject=F;exports.LazyInject=R;exports.LazyToken=O;exports.Optional=z;exports.PostConstruct=G;exports.PreDestroy=Y;exports.Self=J;exports.SkipSelf=U;exports.Token=k;exports.createLazyInject=W;exports.decorate=K;
|
package/dist/index.d.cts
ADDED
package/dist/index.d.ts
ADDED