@kaokei/di 4.0.0 → 5.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 +24 -46
- package/dist/cachemap.d.cts +37 -22
- package/dist/cachemap.d.ts +37 -22
- package/dist/decorator.d.cts +12 -2
- package/dist/decorator.d.ts +12 -2
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +123 -113
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -17,50 +17,28 @@
|
|
|
17
17
|
- [入门指南](./docs/guide/index.md)
|
|
18
18
|
- [API 文档](./docs/api/index.md)
|
|
19
19
|
- [博客文章](./docs/note/01.什么是Token.md)
|
|
20
|
+
- [CodeSandbox 在线示例](./docs/guide/EXAMPLES.md)
|
|
21
|
+
|
|
22
|
+
## Todo
|
|
23
|
+
|
|
24
|
+
- 完善docs中todo项目
|
|
25
|
+
- 最低需要typescript@5.0.0版本,esbuild@0.24.0版本,vite@6.0.0版本,
|
|
26
|
+
这里主要是vite依赖了esbuild,但是低版本esbuild在stage3装饰器的翻译上存在bug,所以esbuild最低版本需要0.24.0,而对应的vite最低版本则是6.0.0
|
|
27
|
+
当然如果明确使用 useDefineForClassFields: true,低版本esbuild也是可以正常工作的。
|
|
28
|
+
https://chatgpt.com/share/69ca7982-2fd0-8321-8e6b-31867f5839e5
|
|
29
|
+
- 需要重构当前的实现方案,应该通过context.metadata来收集依赖注入信息,然后通过类装饰器建立类和context.metadata的关联关系。
|
|
30
|
+
addInitializer → this.constructor → class
|
|
31
|
+
metadata → class decorator → WeakMap
|
|
32
|
+
|
|
33
|
+
- stage3 装饰器执行顺序
|
|
34
|
+
enter method decorator -->
|
|
35
|
+
enter field decorator -->
|
|
36
|
+
enter class decorator -->
|
|
37
|
+
class decorator addInitializer callback -->
|
|
38
|
+
method decorator addInitializer callback -->
|
|
39
|
+
field decorator addInitializer callback -->
|
|
40
|
+
class constructor
|
|
41
|
+
|
|
42
|
+
- 5.0.4,5.1.6并不支持context.metadata
|
|
43
|
+
- 5.2.2 开始支持context.metadata
|
|
20
44
|
|
|
21
|
-
## CodeSandbox 在线示例
|
|
22
|
-
|
|
23
|
-
以下示例托管在 GitHub 仓库的 `examples/` 目录中,可通过 CodeSandbox 直接在线运行。
|
|
24
|
-
|
|
25
|
-
URL 格式:`https://codesandbox.io/p/github/kaokei/di/main?file=/examples/<示例目录>/src/index.ts`
|
|
26
|
-
|
|
27
|
-
| 示例 | 说明 | 在线运行 |
|
|
28
|
-
| ------------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
|
|
29
|
-
| 01-basic-usage | 基础用法:创建容器、绑定服务、属性注入、单例验证 | [打开](https://codesandbox.io/p/github/kaokei/di/main?file=/examples/01-basic-usage/src/index.ts) |
|
|
30
|
-
| 02-token-usage | Token 用法:Token 实例作为标识符,三种绑定方式 | [打开](https://codesandbox.io/p/github/kaokei/di/main?file=/examples/02-token-usage/src/index.ts) |
|
|
31
|
-
| 03-optional-inject | Optional 注入:依赖不存在时返回 undefined | [打开](https://codesandbox.io/p/github/kaokei/di/main?file=/examples/03-optional-inject/src/index.ts) |
|
|
32
|
-
| 04-hierarchical-di | 层级容器:父子容器创建与依赖查找 | [打开](https://codesandbox.io/p/github/kaokei/di/main?file=/examples/04-hierarchical-di/src/index.ts) |
|
|
33
|
-
| 05-self-skipself | Self 和 SkipSelf:控制依赖查找范围 | [打开](https://codesandbox.io/p/github/kaokei/di/main?file=/examples/05-self-skipself/src/index.ts) |
|
|
34
|
-
| 06-lifecycle-activation | 激活生命周期:onActivation 钩子与执行顺序 | [打开](https://codesandbox.io/p/github/kaokei/di/main?file=/examples/06-lifecycle-activation/src/index.ts) |
|
|
35
|
-
| 07-lifecycle-deactivation | 销毁生命周期:onDeactivation 钩子与执行顺序 | [打开](https://codesandbox.io/p/github/kaokei/di/main?file=/examples/07-lifecycle-deactivation/src/index.ts) |
|
|
36
|
-
| 08-post-construct | PostConstruct:同步/异步初始化与继承行为 | [打开](https://codesandbox.io/p/github/kaokei/di/main?file=/examples/08-post-construct/src/index.ts) |
|
|
37
|
-
| 09-pre-destroy | PreDestroy:服务销毁前的清理钩子 | [打开](https://codesandbox.io/p/github/kaokei/di/main?file=/examples/09-pre-destroy/src/index.ts) |
|
|
38
|
-
| 10-circular-dependency | 循环依赖:属性注入原生支持循环依赖 | [打开](https://codesandbox.io/p/github/kaokei/di/main?file=/examples/10-circular-dependency/src/index.ts) |
|
|
39
|
-
| 11-lazy-inject | LazyInject:延迟注入,首次访问时才从容器解析 | [打开](https://codesandbox.io/p/github/kaokei/di/main?file=/examples/11-lazy-inject/src/index.ts) |
|
|
40
|
-
| 12-inheritance | 继承:子类继承父类的属性注入与 PostConstruct 规则 | [打开](https://codesandbox.io/p/github/kaokei/di/main?file=/examples/12-inheritance/src/index.ts) |
|
|
41
|
-
| 13-to-service | toService 别名:接口 token 映射到实现类 | [打开](https://codesandbox.io/p/github/kaokei/di/main?file=/examples/13-to-service/src/index.ts) |
|
|
42
|
-
| 14-dynamic-value | 动态值:toDynamicValue 工厂函数与条件注入 | [打开](https://codesandbox.io/p/github/kaokei/di/main?file=/examples/14-dynamic-value/src/index.ts) |
|
|
43
|
-
| 15-error-handling | 错误处理:各种错误类型的触发场景与捕获方式 | [打开](https://codesandbox.io/p/github/kaokei/di/main?file=/examples/15-error-handling/src/index.ts) |
|
|
44
|
-
| 16-javascript-usage | JavaScript 用法:使用 decorate 函数手动应用装饰器 | [打开](https://codesandbox.io/p/github/kaokei/di/main?file=/examples/16-javascript-usage/src/index.js) |
|
|
45
|
-
| 17-container-destroy | 容器销毁:destroy 递归销毁子容器与 getContainerOf | [打开](https://codesandbox.io/p/github/kaokei/di/main?file=/examples/17-container-destroy/src/index.ts) |
|
|
46
|
-
| 18-deep-circular-dependency | 深层循环依赖:属性注入支持深层循环链,以及循环依赖检测 | [打开](https://codesandbox.io/p/github/kaokei/di/main?file=/examples/18-deep-circular-dependency/src/index.ts) |
|
|
47
|
-
|
|
48
|
-
每个示例目录包含独立的 `package.json`(依赖已发布的 `@kaokei/di` 版本)和 `tsconfig.json`,与主包构建流程完全隔离,可直接在 CodeSandbox 中运行。
|
|
49
|
-
|
|
50
|
-
## 项目特点
|
|
51
|
-
|
|
52
|
-
本项目只有单例模式,没有inversify中其他模式。
|
|
53
|
-
|
|
54
|
-
本项目中@LazyInject 和 @PostConstruct 只支持class服务。
|
|
55
|
-
|
|
56
|
-
inversify中执行顺序是:
|
|
57
|
-
postConstruct --> binding handler --> container handlers
|
|
58
|
-
container handlers --> binding handler --> preDestroy
|
|
59
|
-
本项目执行顺序:
|
|
60
|
-
binding handler --> container handlers --> postConstruct
|
|
61
|
-
container handlers --> binding handler --> preDestroy
|
|
62
|
-
|
|
63
|
-
@postConstruct装饰器在inversify中,如果A类继承了B类。
|
|
64
|
-
此时如果A类和B类都有 @postConstruct,那么B类不会执行,只有A类会执行。
|
|
65
|
-
如果A类没有@postConstruct,那么会执行B类的。
|
|
66
|
-
如果A继承B继承C,并且A,B都没有@postConstruct,那么会执行C类的。
|
package/dist/cachemap.d.cts
CHANGED
|
@@ -1,25 +1,40 @@
|
|
|
1
1
|
import { CommonToken, PostConstructParam } from './interfaces';
|
|
2
|
-
import { KEYS } from './constants';
|
|
3
|
-
export interface MetadataMap {
|
|
4
|
-
[KEYS.INJECTED_PROPS]: Record<string, Record<string, unknown>>;
|
|
5
|
-
[KEYS.POST_CONSTRUCT]: {
|
|
6
|
-
key: string;
|
|
7
|
-
value?: PostConstructParam;
|
|
8
|
-
};
|
|
9
|
-
[KEYS.PRE_DESTROY]: {
|
|
10
|
-
key: string;
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
export declare function defineMetadata<K extends keyof MetadataMap>(metadataKey: K, metadataValue: MetadataMap[K], target: CommonToken): void;
|
|
14
|
-
export declare function defineMetadata(metadataKey: string, metadataValue: unknown, target: CommonToken): void;
|
|
15
|
-
export declare function getOwnMetadata<K extends keyof MetadataMap>(metadataKey: K, target: CommonToken): MetadataMap[K] | undefined;
|
|
16
|
-
export declare function getOwnMetadata(metadataKey: string, target: CommonToken): unknown | undefined;
|
|
17
2
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* 如果有父类,那么需要合并 getOwnMetadata(target) 和 getMetadata(target 的父类)
|
|
21
|
-
* 统一使用展开运算符合并,返回外层新对象、内层原始引用
|
|
22
|
-
* 不支持 META_KEY_INJECTED_PARAMS 作为 metadataKey
|
|
3
|
+
* 关联 target 和 metadata 对象
|
|
4
|
+
* 由 @Injectable 类装饰器调用,直接存储 context.metadata
|
|
23
5
|
*/
|
|
24
|
-
export declare function
|
|
25
|
-
|
|
6
|
+
export declare function defineMetadata(target: CommonToken, metadata: Record<string, unknown>): void;
|
|
7
|
+
/**
|
|
8
|
+
* 获取 PostConstruct 元数据
|
|
9
|
+
*
|
|
10
|
+
* 如果 target 在 map 中注册了(使用了 @Injectable),
|
|
11
|
+
* 直接读取 metadata[key],原型链自动处理继承。
|
|
12
|
+
* 如果 target 未注册但有父类,递归向上查找。
|
|
13
|
+
*/
|
|
14
|
+
export declare function getPostConstruct(target: CommonToken): {
|
|
15
|
+
key: string;
|
|
16
|
+
value?: PostConstructParam;
|
|
17
|
+
} | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* 获取 PreDestroy 元数据
|
|
20
|
+
*
|
|
21
|
+
* 与 getPostConstruct 同理。
|
|
22
|
+
*/
|
|
23
|
+
export declare function getPreDestroy(target: CommonToken): {
|
|
24
|
+
key: string;
|
|
25
|
+
} | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* 获取属性注入元数据(需要手动处理继承链中嵌套对象的合并)
|
|
28
|
+
*
|
|
29
|
+
* context.metadata 的原型链继承只对第一层属性有效。
|
|
30
|
+
* INJECTED_PROPS 对应的值是一个嵌套对象 { propName: { inject, self, ... } },
|
|
31
|
+
* 原型链无法自动合并嵌套属性。
|
|
32
|
+
*
|
|
33
|
+
* 例如:父类有 { a: {...}, b: {...} },子类有 { a: {...} }
|
|
34
|
+
* 通过原型链读取子类的 INJECTED_PROPS 只能拿到子类自己的 { a: {...} },
|
|
35
|
+
* 无法自动合并父类的 b 属性。
|
|
36
|
+
*
|
|
37
|
+
* 所以需要手动递归处理:合并当前类和父类的 INJECTED_PROPS,
|
|
38
|
+
* 子类同名属性覆盖父类。
|
|
39
|
+
*/
|
|
40
|
+
export declare function getInjectedProps(target: CommonToken): Record<string, Record<string, unknown>> | undefined;
|
package/dist/cachemap.d.ts
CHANGED
|
@@ -1,25 +1,40 @@
|
|
|
1
1
|
import { CommonToken, PostConstructParam } from './interfaces';
|
|
2
|
-
import { KEYS } from './constants';
|
|
3
|
-
export interface MetadataMap {
|
|
4
|
-
[KEYS.INJECTED_PROPS]: Record<string, Record<string, unknown>>;
|
|
5
|
-
[KEYS.POST_CONSTRUCT]: {
|
|
6
|
-
key: string;
|
|
7
|
-
value?: PostConstructParam;
|
|
8
|
-
};
|
|
9
|
-
[KEYS.PRE_DESTROY]: {
|
|
10
|
-
key: string;
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
export declare function defineMetadata<K extends keyof MetadataMap>(metadataKey: K, metadataValue: MetadataMap[K], target: CommonToken): void;
|
|
14
|
-
export declare function defineMetadata(metadataKey: string, metadataValue: unknown, target: CommonToken): void;
|
|
15
|
-
export declare function getOwnMetadata<K extends keyof MetadataMap>(metadataKey: K, target: CommonToken): MetadataMap[K] | undefined;
|
|
16
|
-
export declare function getOwnMetadata(metadataKey: string, target: CommonToken): unknown | undefined;
|
|
17
2
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* 如果有父类,那么需要合并 getOwnMetadata(target) 和 getMetadata(target 的父类)
|
|
21
|
-
* 统一使用展开运算符合并,返回外层新对象、内层原始引用
|
|
22
|
-
* 不支持 META_KEY_INJECTED_PARAMS 作为 metadataKey
|
|
3
|
+
* 关联 target 和 metadata 对象
|
|
4
|
+
* 由 @Injectable 类装饰器调用,直接存储 context.metadata
|
|
23
5
|
*/
|
|
24
|
-
export declare function
|
|
25
|
-
|
|
6
|
+
export declare function defineMetadata(target: CommonToken, metadata: Record<string, unknown>): void;
|
|
7
|
+
/**
|
|
8
|
+
* 获取 PostConstruct 元数据
|
|
9
|
+
*
|
|
10
|
+
* 如果 target 在 map 中注册了(使用了 @Injectable),
|
|
11
|
+
* 直接读取 metadata[key],原型链自动处理继承。
|
|
12
|
+
* 如果 target 未注册但有父类,递归向上查找。
|
|
13
|
+
*/
|
|
14
|
+
export declare function getPostConstruct(target: CommonToken): {
|
|
15
|
+
key: string;
|
|
16
|
+
value?: PostConstructParam;
|
|
17
|
+
} | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* 获取 PreDestroy 元数据
|
|
20
|
+
*
|
|
21
|
+
* 与 getPostConstruct 同理。
|
|
22
|
+
*/
|
|
23
|
+
export declare function getPreDestroy(target: CommonToken): {
|
|
24
|
+
key: string;
|
|
25
|
+
} | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* 获取属性注入元数据(需要手动处理继承链中嵌套对象的合并)
|
|
28
|
+
*
|
|
29
|
+
* context.metadata 的原型链继承只对第一层属性有效。
|
|
30
|
+
* INJECTED_PROPS 对应的值是一个嵌套对象 { propName: { inject, self, ... } },
|
|
31
|
+
* 原型链无法自动合并嵌套属性。
|
|
32
|
+
*
|
|
33
|
+
* 例如:父类有 { a: {...}, b: {...} },子类有 { a: {...} }
|
|
34
|
+
* 通过原型链读取子类的 INJECTED_PROPS 只能拿到子类自己的 { a: {...} },
|
|
35
|
+
* 无法自动合并父类的 b 属性。
|
|
36
|
+
*
|
|
37
|
+
* 所以需要手动递归处理:合并当前类和父类的 INJECTED_PROPS,
|
|
38
|
+
* 子类同名属性覆盖父类。
|
|
39
|
+
*/
|
|
40
|
+
export declare function getInjectedProps(target: CommonToken): Record<string, Record<string, unknown>> | undefined;
|
package/dist/decorator.d.cts
CHANGED
|
@@ -3,8 +3,8 @@ import { InjectFunction, GenericToken } from './interfaces';
|
|
|
3
3
|
/**
|
|
4
4
|
* 创建属性装饰器的高阶函数(Stage 3 Field Decorator)
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* 直接在装饰器执行阶段将元数据写入 context.metadata,
|
|
7
|
+
* 不再使用 context.addInitializer,消除实例化时的重复回调。
|
|
8
8
|
*
|
|
9
9
|
* @param decoratorKey 装饰器名称(如 'inject'、'self' 等)
|
|
10
10
|
* @param defaultValue 装饰器的默认参数值
|
|
@@ -17,6 +17,16 @@ export declare const SkipSelf: (decoratorValue?: any) => (_value: undefined, con
|
|
|
17
17
|
export declare const Optional: (decoratorValue?: any) => (_value: undefined, context: ClassFieldDecoratorContext) => void;
|
|
18
18
|
export declare const PostConstruct: (metaValue?: any) => (_value: Function, context: ClassMethodDecoratorContext) => void;
|
|
19
19
|
export declare const PreDestroy: (metaValue?: any) => (_value: Function, context: ClassMethodDecoratorContext) => void;
|
|
20
|
+
/**
|
|
21
|
+
* 类装饰器:在类定义阶段关联 target(类构造函数)和 context.metadata
|
|
22
|
+
*
|
|
23
|
+
* 当所有成员装饰器(@Inject、@PostConstruct 等)执行完毕后,
|
|
24
|
+
* @Injectable 读取 context.metadata 并通过 defineMetadata 写入 CacheMap,
|
|
25
|
+
* 建立 target → metadata 的映射关系。
|
|
26
|
+
*
|
|
27
|
+
* 使用方式:@Injectable(无参数,直接作为装饰器使用)
|
|
28
|
+
*/
|
|
29
|
+
export declare function Injectable(Ctor: Function, context: ClassDecoratorContext): void;
|
|
20
30
|
/**
|
|
21
31
|
* 延迟注入装饰器,Stage 3 Field Decorator 签名。
|
|
22
32
|
* 通过 context.addInitializer 在实例上定义 getter/setter,
|
package/dist/decorator.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ import { InjectFunction, GenericToken } from './interfaces';
|
|
|
3
3
|
/**
|
|
4
4
|
* 创建属性装饰器的高阶函数(Stage 3 Field Decorator)
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* 直接在装饰器执行阶段将元数据写入 context.metadata,
|
|
7
|
+
* 不再使用 context.addInitializer,消除实例化时的重复回调。
|
|
8
8
|
*
|
|
9
9
|
* @param decoratorKey 装饰器名称(如 'inject'、'self' 等)
|
|
10
10
|
* @param defaultValue 装饰器的默认参数值
|
|
@@ -17,6 +17,16 @@ export declare const SkipSelf: (decoratorValue?: any) => (_value: undefined, con
|
|
|
17
17
|
export declare const Optional: (decoratorValue?: any) => (_value: undefined, context: ClassFieldDecoratorContext) => void;
|
|
18
18
|
export declare const PostConstruct: (metaValue?: any) => (_value: Function, context: ClassMethodDecoratorContext) => void;
|
|
19
19
|
export declare const PreDestroy: (metaValue?: any) => (_value: Function, context: ClassMethodDecoratorContext) => void;
|
|
20
|
+
/**
|
|
21
|
+
* 类装饰器:在类定义阶段关联 target(类构造函数)和 context.metadata
|
|
22
|
+
*
|
|
23
|
+
* 当所有成员装饰器(@Inject、@PostConstruct 等)执行完毕后,
|
|
24
|
+
* @Injectable 读取 context.metadata 并通过 defineMetadata 写入 CacheMap,
|
|
25
|
+
* 建立 target → metadata 的映射关系。
|
|
26
|
+
*
|
|
27
|
+
* 使用方式:@Injectable(无参数,直接作为装饰器使用)
|
|
28
|
+
*/
|
|
29
|
+
export declare function Injectable(Ctor: Function, context: ClassDecoratorContext): void;
|
|
20
30
|
/**
|
|
21
31
|
* 延迟注入装饰器,Stage 3 Field Decorator 签名。
|
|
22
32
|
* 通过 context.addInitializer 在实例上定义 getter/setter,
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var F=Object.defineProperty;var x=(n,t,e)=>t in n?F(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var r=(n,t,e)=>x(n,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l={INJECTED_PROPS:"injected:props",INJECT:"inject",SELF:"self",SKIP_SELF:"skipSelf",OPTIONAL:"optional",POST_CONSTRUCT:"postConstruct",PRE_DESTROY:"preDestroy"},f={DEFAULT:"default",INITING:"initing",ACTIVATED:"activated"},d={Invalid:"Invalid",Instance:"Instance",ConstantValue:"ConstantValue",DynamicValue:"DynamicValue"},T={POST_CONSTRUCT:"Multiple @PostConstruct decorators are not allowed in a single class.",PRE_DESTROY:"Multiple @PreDestroy decorators are not allowed in a single class.",INVALID_TOKEN:"@Inject or @LazyInject requires a valid token, but received null or undefined.",LAZY_INJECT_INVALID_TOKEN:"@LazyInject requires a valid token, but received null or undefined."};function O(n,t){return Object.prototype.hasOwnProperty.call(n,t)}const N=Symbol("UNINITIALIZED"),A=new WeakMap;function U(n){return typeof n=="function"&&Object.getPrototypeOf(n)!==Function.prototype}function V(n,t,e){const i=A.get(e)||{};i[n]=t,A.set(e,i)}function w(n,t){return(A.get(t)||{})[n]}function y(n,t){const e=w(n,t);if(!U(t))return e;const i=y(n,Object.getPrototypeOf(t));if(i||e)return{...i||{},...e||{}}}class J{constructor(t){r(this,"name");this.name=t}}class R{constructor(t){r(this,"_callback");this._callback=t}resolve(){return this._callback()}}function b(n){if(!n)throw new Error(T.INVALID_TOKEN);return n instanceof R?n.resolve():n}class I extends Error{constructor(e,i){const s=(i==null?void 0:i.name)||"<unknown token>";super(`${e}${s}`);r(this,"token");this.name=this.constructor.name,this.token=i}}class m extends I{constructor(t){super("");const e=[];let i=t;for(;i&&i.token;)e.push(i.token),i=i.parent;const s=e.reverse().map(o=>o.name||"<anonymous>").join(" --> ");this.message=`Circular dependency found: ${s}`}}class j extends I{constructor(t){super("Invalid binding: ",t)}}class L extends m{constructor(t){super(t),this.name="CircularDependencyError inside @PostConstruct"}}const E=class E{constructor(t,e){r(this,"container");r(this,"context");r(this,"token");r(this,"type",d.Invalid);r(this,"status",f.DEFAULT);r(this,"classValue");r(this,"constantValue");r(this,"dynamicValue");r(this,"cache");r(this,"postConstructResult",N);r(this,"onActivationHandler");r(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(f.INITING===this.status)throw new m(t);if(f.ACTIVATED===this.status)return this.cache;const e=E._resolvers[this.type];if(e)return this[e](t);throw new j(this.token)}_getAwaitBindings(t,e){return e===!0?t:Array.isArray(e)?t.filter(i=>e.includes(i.token)):typeof e=="function"?t.filter(e):[]}_postConstruct(t,e){if(d.Instance===this.type){const{key:i,value:s}=y(l.POST_CONSTRUCT,this.classValue)||{};if(i)if(s){const o=e.filter(c=>d.Instance===(c==null?void 0:c.type)),a=this._getAwaitBindings(o,s);for(const c of a)if(c&&c.postConstructResult===N)throw new L({token:c.token,parent:t});const u=a.map(c=>c.postConstructResult);this.postConstructResult=Promise.all(u).then(()=>this._execute(i))}else this.postConstructResult=this._execute(i);else this.postConstructResult=void 0}}preDestroy(){if(d.Instance===this.type){const{key:t}=y(l.PRE_DESTROY,this.classValue)||{};t&&this._execute(t)}_._instanceContainerMap.delete(this.cache),this.container=null,this.context=null,this.classValue=void 0,this.constantValue=void 0,this.dynamicValue=void 0,this.cache=void 0,this.postConstructResult=N,this.onActivationHandler=void 0,this.onDeactivationHandler=void 0}_execute(t){const e=this.cache[t];return e==null?void 0:e.call(this.cache)}_resolveInstanceValue(t){this.status=f.INITING;const e=this._createInstance();this.cache=this.activate(e),this.status=f.ACTIVATED,this._registerInstance();const{properties:i,bindings:s}=this._getInjectProperties(t);return this._injectProperties(i),this._postConstruct(t,s),this.cache}_createInstance(){const t=this.classValue;return new t}_registerInstance(){_._instanceContainerMap.set(this.cache,this.container)}_injectProperties(t){Object.assign(this.cache,t)}_resolveConstantValue(){return this.status=f.INITING,this.cache=this.activate(this.constantValue),this.status=f.ACTIVATED,this.cache}_resolveDynamicValue(){this.status=f.INITING;const t=this.dynamicValue(this.context);return this.cache=this.activate(t),this.status=f.ACTIVATED,this.cache}_getInjectProperties(t){const e=y(l.INJECTED_PROPS,this.classValue)||{},i=Object.keys(e),s=Object.create(null),o=[];for(let a=0;a<i.length;a++){const u=i[a],c=e[u],{inject:p,...v}=c;v.parent=t;const h=this.container.get(b(p),v);h===void 0&&c.optional||(s[u]=h),o.push(v.binding)}return{properties:s,bindings:o}}};r(E,"_resolvers",{[d.Instance]:"_resolveInstanceValue",[d.ConstantValue]:"_resolveConstantValue",[d.DynamicValue]:"_resolveDynamicValue"});let C=E;class k extends I{constructor(t){super("No matching binding found for token: ",t)}}class B extends I{constructor(t){super("Cannot bind token multiple times: ",t)}}const g=class g{constructor(){r(this,"parent");r(this,"children");r(this,"_bindings",new Map);r(this,"_onActivationHandler");r(this,"_onDeactivationHandler")}static getContainerOf(t){return g._instanceContainerMap.get(t)}bind(t){if(this._bindings.has(t))throw new B(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.deactivate(),e.preDestroy(),this._bindings.delete(t)}}unbindAll(){const t=Array.from(this._bindings.keys());for(const e of t)this.unbind(e)}isCurrentBound(t){return this._bindings.has(t)}isBound(t){return this.isCurrentBound(t)||!!this.parent&&this.parent.isBound(t)}createChild(){const t=new g;return t.parent=this,this.children||(this.children=new Set),this.children.add(t),t}destroy(){var t,e;if(this.children){const i=Array.from(this.children);for(const s of i)s.destroy()}this.unbindAll(),this._bindings.clear(),(e=(t=this.parent)==null?void 0:t.children)==null||e.delete(this),this.parent=void 0,this.children=void 0,this._onActivationHandler=void 0,this._onDeactivationHandler=void 0}get(t,e={}){return e.skipSelf?this._resolveSkipSelf(t,e):e.self?this._resolveSelf(t,e):this._resolveDefault(t,e)}_resolveSkipSelf(t,e){return this.parent?(e.skipSelf=!1,this.parent.get(t,e)):this._checkBindingNotFoundError(t,e)}_resolveSelf(t,e){const i=this._getBinding(t);return i?(e.token=t,e.binding=i,i.get(e)):this._checkBindingNotFoundError(t,e)}_resolveDefault(t,e){const i=this._getBinding(t);return i?(e.token=t,e.binding=i,i.get(e)):this.parent?this.parent.get(t,e):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)}_buildBinding(t){return new C(t,this)}_getBinding(t){return this._bindings.get(t)}_checkBindingNotFoundError(t,e){if(!e.optional)throw new k(t)}};r(g,"_instanceContainerMap",new WeakMap);let _=g;class H extends I{constructor(t,e){super(`@LazyInject(${t==null?void 0:t.name}) in class ${e.name} requires a registered container but none was found. Token: `,t)}}function D(n,t){return function(e){return function(i,s){s.addInitializer(function(){const o=this.constructor,a=s.name,u=w(l.INJECTED_PROPS,o)||{},c=u[a]||{};c[n]=e===void 0?t:e,u[a]=c,V(l.INJECTED_PROPS,u,o)})}}}function M(n,t){return e=>(i,s)=>{const o=s.name,a=s.metadata;if(O(a,n))throw new Error(t);a[n]=!0,s.addInitializer(function(){const u=this.constructor;V(n,{key:o,value:e},u)})}}const Y=D(l.INJECT),G=D(l.SELF,!0),K=D(l.SKIP_SELF,!0),$=D(l.OPTIONAL,!0),Z=M(l.POST_CONSTRUCT,T.POST_CONSTRUCT),q=M(l.PRE_DESTROY,T.PRE_DESTROY);function W(n,t,e,i){if(e==null)throw new Error(T.LAZY_INJECT_INVALID_TOKEN);const s=Symbol.for(t);Object.defineProperty(n,t,{configurable:!0,enumerable:!0,get(){if(!O(n,s)){const o=i||_.getContainerOf(n),a=n.constructor;if(!o)throw new H(b(e),a);n[s]=o.get(b(e),{parent:{token:a}})}return n[s]},set(o){n[s]=o}})}function z(n,t){return function(e,i){const s=i.name;i.addInitializer(function(){W(this,s,n,t)})}}function Q(n){return function(t){return z(t,n)}}const S=Symbol("decorate.metadata");function X(n,t,e){const i=Array.isArray(n)?n:[n],s=t.prototype,o=typeof s[e]=="function",a=[];O(t,S)||(t[S]={});const u=t[S],c={kind:o?"method":"field",name:e,static:!1,private:!1,addInitializer(h){a.push(h)},metadata:u};let p=o?s[e]:void 0;for(let h=i.length-1;h>=0;h--){const P=i[h](p,c);o&&typeof P=="function"&&(p=P)}o&&p!==s[e]&&(s[e]=p);const v=Object.create(s);for(const h of a)h.call(v)}exports.BaseError=I;exports.Binding=C;exports.BindingNotFoundError=k;exports.BindingNotValidError=j;exports.CircularDependencyError=m;exports.Container=_;exports.ContainerNotFoundError=H;exports.DuplicateBindingError=B;exports.Inject=Y;exports.LazyInject=z;exports.LazyToken=R;exports.Optional=$;exports.PostConstruct=Z;exports.PostConstructError=L;exports.PreDestroy=q;exports.Self=G;exports.SkipSelf=K;exports.Token=J;exports.createLazyInject=Q;exports.decorate=X;
|
|
1
|
+
"use strict";var z=Object.defineProperty;var J=(n,t,e)=>t in n?z(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var r=(n,t,e)=>J(n,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u={INJECTED_PROPS:"injected:props",INJECT:"inject",SELF:"self",SKIP_SELF:"skipSelf",OPTIONAL:"optional",POST_CONSTRUCT:"postConstruct",PRE_DESTROY:"preDestroy"},f={DEFAULT:"default",INITING:"initing",ACTIVATED:"activated"},d={Invalid:"Invalid",Instance:"Instance",ConstantValue:"ConstantValue",DynamicValue:"DynamicValue"},T={POST_CONSTRUCT:"Multiple @PostConstruct decorators are not allowed in a single class.",PRE_DESTROY:"Multiple @PreDestroy decorators are not allowed in a single class.",INVALID_TOKEN:"@Inject or @LazyInject requires a valid token, but received null or undefined.",LAZY_INJECT_INVALID_TOKEN:"@LazyInject requires a valid token, but received null or undefined."};function y(n,t){return Object.prototype.hasOwnProperty.call(n,t)}const m=Symbol("UNINITIALIZED"),D=new WeakMap;function b(n){return typeof n=="function"&&Object.getPrototypeOf(n)!==Function.prototype}function A(n,t){D.set(n,t)}function V(n){const t=D.get(n);if(t)return t[u.POST_CONSTRUCT];if(b(n))return V(Object.getPrototypeOf(n))}function w(n){const t=D.get(n);if(t)return t[u.PRE_DESTROY];if(b(n))return w(Object.getPrototypeOf(n))}function j(n){const t=D.get(n),e=t&&y(t,u.INJECTED_PROPS)?t[u.INJECTED_PROPS]:void 0;if(!b(n))return e;const i=j(Object.getPrototypeOf(n));if(i||e)return{...i||{},...e||{}}}class U{constructor(t){r(this,"name");this.name=t}}class R{constructor(t){r(this,"_callback");this._callback=t}resolve(){return this._callback()}}function P(n){if(!n)throw new Error(T.INVALID_TOKEN);return n instanceof R?n.resolve():n}class I extends Error{constructor(e,i){const s=(i==null?void 0:i.name)||"<unknown token>";super(`${e}${s}`);r(this,"token");this.name=this.constructor.name,this.token=i}}class O extends I{constructor(t){super("");const e=[];let i=t;for(;i&&i.token;)e.push(i.token),i=i.parent;const s=e.reverse().map(o=>o.name||"<anonymous>").join(" --> ");this.message=`Circular dependency found: ${s}`}}class L extends I{constructor(t){super("Invalid binding: ",t)}}class k extends O{constructor(t){super(t),this.name="CircularDependencyError inside @PostConstruct"}}const C=class C{constructor(t,e){r(this,"container");r(this,"context");r(this,"token");r(this,"type",d.Invalid);r(this,"status",f.DEFAULT);r(this,"classValue");r(this,"constantValue");r(this,"dynamicValue");r(this,"cache");r(this,"postConstructResult",m);r(this,"onActivationHandler");r(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(f.INITING===this.status)throw new O(t);if(f.ACTIVATED===this.status)return this.cache;const e=C._resolvers[this.type];if(e)return this[e](t);throw new L(this.token)}_getAwaitBindings(t,e){return e===!0?t:Array.isArray(e)?t.filter(i=>e.includes(i.token)):typeof e=="function"?t.filter(e):[]}_postConstruct(t,e){if(d.Instance===this.type){const{key:i,value:s}=V(this.classValue)||{};if(i)if(s){const o=e.filter(c=>d.Instance===(c==null?void 0:c.type)),a=this._getAwaitBindings(o,s);for(const c of a)if(c&&c.postConstructResult===m)throw new k({token:c.token,parent:t});const l=a.map(c=>c.postConstructResult);this.postConstructResult=Promise.all(l).then(()=>this._execute(i))}else this.postConstructResult=this._execute(i);else this.postConstructResult=void 0}}preDestroy(){if(d.Instance===this.type){const{key:t}=w(this.classValue)||{};t&&this._execute(t)}v._instanceContainerMap.delete(this.cache),this.container=null,this.context=null,this.classValue=void 0,this.constantValue=void 0,this.dynamicValue=void 0,this.cache=void 0,this.postConstructResult=m,this.onActivationHandler=void 0,this.onDeactivationHandler=void 0}_execute(t){const e=this.cache[t];return e==null?void 0:e.call(this.cache)}_resolveInstanceValue(t){this.status=f.INITING;const e=this._createInstance();this.cache=this.activate(e),this.status=f.ACTIVATED,this._registerInstance();const{properties:i,bindings:s}=this._getInjectProperties(t);return this._injectProperties(i),this._postConstruct(t,s),this.cache}_createInstance(){const t=this.classValue;return new t}_registerInstance(){v._instanceContainerMap.set(this.cache,this.container)}_injectProperties(t){Object.assign(this.cache,t)}_resolveConstantValue(){return this.status=f.INITING,this.cache=this.activate(this.constantValue),this.status=f.ACTIVATED,this.cache}_resolveDynamicValue(){this.status=f.INITING;const t=this.dynamicValue(this.context);return this.cache=this.activate(t),this.status=f.ACTIVATED,this.cache}_getInjectProperties(t){const e=j(this.classValue)||{},i=Object.keys(e),s=Object.create(null),o=[];for(let a=0;a<i.length;a++){const l=i[a],c=e[l],{inject:_,...h}=c;h.parent=t;const p=this.container.get(P(_),h);p===void 0&&c.optional||(s[l]=p),o.push(h.binding)}return{properties:s,bindings:o}}};r(C,"_resolvers",{[d.Instance]:"_resolveInstanceValue",[d.ConstantValue]:"_resolveConstantValue",[d.DynamicValue]:"_resolveDynamicValue"});let E=C;class B extends I{constructor(t){super("No matching binding found for token: ",t)}}class H extends I{constructor(t){super("Cannot bind token multiple times: ",t)}}const g=class g{constructor(){r(this,"parent");r(this,"children");r(this,"_bindings",new Map);r(this,"_onActivationHandler");r(this,"_onDeactivationHandler")}static getContainerOf(t){return g._instanceContainerMap.get(t)}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.deactivate(),e.preDestroy(),this._bindings.delete(t)}}unbindAll(){const t=Array.from(this._bindings.keys());for(const e of t)this.unbind(e)}isCurrentBound(t){return this._bindings.has(t)}isBound(t){return this.isCurrentBound(t)||!!this.parent&&this.parent.isBound(t)}createChild(){const t=new g;return t.parent=this,this.children||(this.children=new Set),this.children.add(t),t}destroy(){var t,e;if(this.children){const i=Array.from(this.children);for(const s of i)s.destroy()}this.unbindAll(),this._bindings.clear(),(e=(t=this.parent)==null?void 0:t.children)==null||e.delete(this),this.parent=void 0,this.children=void 0,this._onActivationHandler=void 0,this._onDeactivationHandler=void 0}get(t,e={}){return e.skipSelf?this._resolveSkipSelf(t,e):e.self?this._resolveSelf(t,e):this._resolveDefault(t,e)}_resolveSkipSelf(t,e){return this.parent?(e.skipSelf=!1,this.parent.get(t,e)):this._checkBindingNotFoundError(t,e)}_resolveSelf(t,e){const i=this._getBinding(t);return i?(e.token=t,e.binding=i,i.get(e)):this._checkBindingNotFoundError(t,e)}_resolveDefault(t,e){const i=this._getBinding(t);return i?(e.token=t,e.binding=i,i.get(e)):this.parent?this.parent.get(t,e):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)}_buildBinding(t){return new E(t,this)}_getBinding(t){return this._bindings.get(t)}_checkBindingNotFoundError(t,e){if(!e.optional)throw new B(t)}};r(g,"_instanceContainerMap",new WeakMap);let v=g;class x extends I{constructor(t,e){super(`@LazyInject(${t==null?void 0:t.name}) in class ${e.name} requires a registered container but none was found. Token: `,t)}}function N(n,t){return function(e){return function(i,s){const o=s.name,a=s.metadata;y(a,u.INJECTED_PROPS)||(a[u.INJECTED_PROPS]={});const l=a[u.INJECTED_PROPS];l[o]||(l[o]={}),l[o][n]=e===void 0?t:e}}}function F(n,t){return e=>(i,s)=>{const o=s.name,a=s.metadata;if(y(a,n))throw new Error(t);a[n]={key:o,value:e}}}const K=N(u.INJECT),Y=N(u.SELF,!0),G=N(u.SKIP_SELF,!0),$=N(u.OPTIONAL,!0),Z=F(u.POST_CONSTRUCT,T.POST_CONSTRUCT),q=F(u.PRE_DESTROY,T.PRE_DESTROY);function W(n,t){const e=t.metadata;A(n,e)}function Q(n,t,e,i){if(e==null)throw new Error(T.LAZY_INJECT_INVALID_TOKEN);const s=Symbol.for(t);Object.defineProperty(n,t,{configurable:!0,enumerable:!0,get(){if(!y(n,s)){const o=i||v.getContainerOf(n),a=n.constructor;if(!o)throw new x(P(e),a);n[s]=o.get(P(e),{parent:{token:a}})}return n[s]},set(o){n[s]=o}})}function M(n,t){return function(e,i){const s=i.name;i.addInitializer(function(){Q(this,s,n,t)})}}function X(n){return function(t){return M(t,n)}}const S=Symbol("decorate.metadata");function tt(n,t,e){const i=Array.isArray(n)?n:[n],s=t.prototype,o=typeof s[e]=="function",a=[];y(t,S)||(t[S]={});const l=t[S],c={kind:o?"method":"field",name:e,static:!1,private:!1,addInitializer(h){a.push(h)},metadata:l};let _=o?s[e]:void 0;for(let h=i.length-1;h>=0;h--){const p=i[h](_,c);o&&typeof p=="function"&&(_=p)}if(o&&_!==s[e]&&(s[e]=_),A(t,l),a.length>0){const h=Object.create(s);for(const p of a)p.call(h)}}exports.BaseError=I;exports.Binding=E;exports.BindingNotFoundError=B;exports.BindingNotValidError=L;exports.CircularDependencyError=O;exports.Container=v;exports.ContainerNotFoundError=x;exports.DuplicateBindingError=H;exports.Inject=K;exports.Injectable=W;exports.LazyInject=M;exports.LazyToken=R;exports.Optional=$;exports.PostConstruct=Z;exports.PostConstructError=k;exports.PreDestroy=q;exports.Self=Y;exports.SkipSelf=G;exports.Token=U;exports.createLazyInject=X;exports.decorate=tt;
|
package/dist/index.d.cts
CHANGED
|
@@ -2,7 +2,7 @@ export type { Newable, InjectFunction, CommonToken, TokenType, GenericToken, Laz
|
|
|
2
2
|
export { Container } from './container';
|
|
3
3
|
export { Binding } from './binding';
|
|
4
4
|
export { Token, LazyToken } from './token';
|
|
5
|
-
export { Inject, Self, SkipSelf, Optional, PostConstruct, PreDestroy, decorate, LazyInject, createLazyInject, } from './decorator';
|
|
5
|
+
export { Inject, Self, SkipSelf, Optional, PostConstruct, PreDestroy, Injectable, decorate, LazyInject, createLazyInject, } from './decorator';
|
|
6
6
|
export { BaseError } from './errors/BaseError';
|
|
7
7
|
export { BindingNotFoundError } from './errors/BindingNotFoundError';
|
|
8
8
|
export { BindingNotValidError } from './errors/BindingNotValidError';
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export type { Newable, InjectFunction, CommonToken, TokenType, GenericToken, Laz
|
|
|
2
2
|
export { Container } from './container';
|
|
3
3
|
export { Binding } from './binding';
|
|
4
4
|
export { Token, LazyToken } from './token';
|
|
5
|
-
export { Inject, Self, SkipSelf, Optional, PostConstruct, PreDestroy, decorate, LazyInject, createLazyInject, } from './decorator';
|
|
5
|
+
export { Inject, Self, SkipSelf, Optional, PostConstruct, PreDestroy, Injectable, decorate, LazyInject, createLazyInject, } from './decorator';
|
|
6
6
|
export { BaseError } from './errors/BaseError';
|
|
7
7
|
export { BindingNotFoundError } from './errors/BindingNotFoundError';
|
|
8
8
|
export { BindingNotValidError } from './errors/BindingNotValidError';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
var L = Object.defineProperty;
|
|
2
|
-
var
|
|
3
|
-
var r = (n, t, e) =>
|
|
4
|
-
const
|
|
2
|
+
var k = (n, t, e) => t in n ? L(n, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : n[t] = e;
|
|
3
|
+
var r = (n, t, e) => k(n, typeof t != "symbol" ? t + "" : t, e);
|
|
4
|
+
const u = {
|
|
5
5
|
// 记录实例属性装饰器对应的数据的键
|
|
6
6
|
INJECTED_PROPS: "injected:props",
|
|
7
7
|
// Inject 装饰器的键
|
|
@@ -25,7 +25,7 @@ const l = {
|
|
|
25
25
|
Instance: "Instance",
|
|
26
26
|
ConstantValue: "ConstantValue",
|
|
27
27
|
DynamicValue: "DynamicValue"
|
|
28
|
-
},
|
|
28
|
+
}, E = {
|
|
29
29
|
// 用于 decorator.ts 的 createMetaDecorator —— 重复装饰器检测
|
|
30
30
|
POST_CONSTRUCT: "Multiple @PostConstruct decorators are not allowed in a single class.",
|
|
31
31
|
PRE_DESTROY: "Multiple @PreDestroy decorators are not allowed in a single class.",
|
|
@@ -34,35 +34,42 @@ const l = {
|
|
|
34
34
|
// 用于 decorator.ts 的 defineLazyProperty —— 无效 token
|
|
35
35
|
LAZY_INJECT_INVALID_TOKEN: "@LazyInject requires a valid token, but received null or undefined."
|
|
36
36
|
};
|
|
37
|
-
function
|
|
37
|
+
function g(n, t) {
|
|
38
38
|
return Object.prototype.hasOwnProperty.call(n, t);
|
|
39
39
|
}
|
|
40
|
-
const
|
|
41
|
-
function
|
|
40
|
+
const m = Symbol("UNINITIALIZED"), C = /* @__PURE__ */ new WeakMap();
|
|
41
|
+
function O(n) {
|
|
42
42
|
return typeof n == "function" && Object.getPrototypeOf(n) !== Function.prototype;
|
|
43
43
|
}
|
|
44
|
-
function V(n, t, e) {
|
|
45
|
-
const i = A.get(e) || {};
|
|
46
|
-
i[n] = t, A.set(e, i);
|
|
47
|
-
}
|
|
48
44
|
function P(n, t) {
|
|
49
|
-
|
|
45
|
+
C.set(n, t);
|
|
46
|
+
}
|
|
47
|
+
function S(n) {
|
|
48
|
+
const t = C.get(n);
|
|
49
|
+
if (t)
|
|
50
|
+
return t[u.POST_CONSTRUCT];
|
|
51
|
+
if (O(n))
|
|
52
|
+
return S(Object.getPrototypeOf(n));
|
|
53
|
+
}
|
|
54
|
+
function V(n) {
|
|
55
|
+
const t = C.get(n);
|
|
56
|
+
if (t)
|
|
57
|
+
return t[u.PRE_DESTROY];
|
|
58
|
+
if (O(n))
|
|
59
|
+
return V(Object.getPrototypeOf(n));
|
|
50
60
|
}
|
|
51
|
-
function
|
|
52
|
-
const
|
|
53
|
-
if (!
|
|
61
|
+
function w(n) {
|
|
62
|
+
const t = C.get(n), e = t && g(t, u.INJECTED_PROPS) ? t[u.INJECTED_PROPS] : void 0;
|
|
63
|
+
if (!O(n))
|
|
54
64
|
return e;
|
|
55
|
-
const i =
|
|
56
|
-
n,
|
|
57
|
-
Object.getPrototypeOf(t)
|
|
58
|
-
);
|
|
65
|
+
const i = w(Object.getPrototypeOf(n));
|
|
59
66
|
if (i || e)
|
|
60
67
|
return {
|
|
61
68
|
...i || {},
|
|
62
69
|
...e || {}
|
|
63
70
|
};
|
|
64
71
|
}
|
|
65
|
-
class
|
|
72
|
+
class Y {
|
|
66
73
|
constructor(t) {
|
|
67
74
|
// 仅类型层面存在,无运行时开销
|
|
68
75
|
r(this, "name");
|
|
@@ -78,12 +85,12 @@ class B {
|
|
|
78
85
|
return this._callback();
|
|
79
86
|
}
|
|
80
87
|
}
|
|
81
|
-
function
|
|
88
|
+
function b(n) {
|
|
82
89
|
if (!n)
|
|
83
|
-
throw new Error(
|
|
90
|
+
throw new Error(E.INVALID_TOKEN);
|
|
84
91
|
return n instanceof B ? n.resolve() : n;
|
|
85
92
|
}
|
|
86
|
-
class
|
|
93
|
+
class y extends Error {
|
|
87
94
|
constructor(e, i) {
|
|
88
95
|
const s = (i == null ? void 0 : i.name) || "<unknown token>";
|
|
89
96
|
super(`${e}${s}`);
|
|
@@ -91,28 +98,28 @@ class g extends Error {
|
|
|
91
98
|
this.name = this.constructor.name, this.token = i;
|
|
92
99
|
}
|
|
93
100
|
}
|
|
94
|
-
class
|
|
101
|
+
class R extends y {
|
|
95
102
|
constructor(t) {
|
|
96
103
|
super("");
|
|
97
104
|
const e = [];
|
|
98
105
|
let i = t;
|
|
99
106
|
for (; i && i.token; )
|
|
100
107
|
e.push(i.token), i = i.parent;
|
|
101
|
-
const s = e.reverse().map((
|
|
108
|
+
const s = e.reverse().map((o) => o.name || "<anonymous>").join(" --> ");
|
|
102
109
|
this.message = `Circular dependency found: ${s}`;
|
|
103
110
|
}
|
|
104
111
|
}
|
|
105
|
-
class H extends
|
|
112
|
+
class H extends y {
|
|
106
113
|
constructor(t) {
|
|
107
114
|
super("Invalid binding: ", t);
|
|
108
115
|
}
|
|
109
116
|
}
|
|
110
|
-
class
|
|
117
|
+
class x extends R {
|
|
111
118
|
constructor(t) {
|
|
112
119
|
super(t), this.name = "CircularDependencyError inside @PostConstruct";
|
|
113
120
|
}
|
|
114
121
|
}
|
|
115
|
-
const
|
|
122
|
+
const T = class T {
|
|
116
123
|
constructor(t, e) {
|
|
117
124
|
r(this, "container");
|
|
118
125
|
r(this, "context");
|
|
@@ -123,7 +130,7 @@ const y = class y {
|
|
|
123
130
|
r(this, "constantValue");
|
|
124
131
|
r(this, "dynamicValue");
|
|
125
132
|
r(this, "cache");
|
|
126
|
-
r(this, "postConstructResult",
|
|
133
|
+
r(this, "postConstructResult", m);
|
|
127
134
|
r(this, "onActivationHandler");
|
|
128
135
|
r(this, "onDeactivationHandler");
|
|
129
136
|
this.container = e, this.context = { container: this.container }, this.token = t;
|
|
@@ -160,10 +167,10 @@ const y = class y {
|
|
|
160
167
|
}
|
|
161
168
|
get(t) {
|
|
162
169
|
if (f.INITING === this.status)
|
|
163
|
-
throw new
|
|
170
|
+
throw new R(t);
|
|
164
171
|
if (f.ACTIVATED === this.status)
|
|
165
172
|
return this.cache;
|
|
166
|
-
const e =
|
|
173
|
+
const e = T._resolvers[this.type];
|
|
167
174
|
if (e)
|
|
168
175
|
return this[e](t);
|
|
169
176
|
throw new H(this.token);
|
|
@@ -186,20 +193,20 @@ const y = class y {
|
|
|
186
193
|
*/
|
|
187
194
|
_postConstruct(t, e) {
|
|
188
195
|
if (d.Instance === this.type) {
|
|
189
|
-
const { key: i, value: s } =
|
|
196
|
+
const { key: i, value: s } = S(this.classValue) || {};
|
|
190
197
|
if (i)
|
|
191
198
|
if (s) {
|
|
192
|
-
const
|
|
199
|
+
const o = e.filter(
|
|
193
200
|
(c) => d.Instance === (c == null ? void 0 : c.type)
|
|
194
|
-
),
|
|
195
|
-
for (const c of
|
|
196
|
-
if (c && c.postConstructResult ===
|
|
197
|
-
throw new
|
|
201
|
+
), a = this._getAwaitBindings(o, s);
|
|
202
|
+
for (const c of a)
|
|
203
|
+
if (c && c.postConstructResult === m)
|
|
204
|
+
throw new x({
|
|
198
205
|
token: c.token,
|
|
199
206
|
parent: t
|
|
200
207
|
});
|
|
201
|
-
const
|
|
202
|
-
this.postConstructResult = Promise.all(
|
|
208
|
+
const l = a.map((c) => c.postConstructResult);
|
|
209
|
+
this.postConstructResult = Promise.all(l).then(
|
|
203
210
|
() => this._execute(i)
|
|
204
211
|
);
|
|
205
212
|
} else
|
|
@@ -210,10 +217,10 @@ const y = class y {
|
|
|
210
217
|
}
|
|
211
218
|
preDestroy() {
|
|
212
219
|
if (d.Instance === this.type) {
|
|
213
|
-
const { key: t } =
|
|
220
|
+
const { key: t } = V(this.classValue) || {};
|
|
214
221
|
t && this._execute(t);
|
|
215
222
|
}
|
|
216
|
-
I._instanceContainerMap.delete(this.cache), this.container = null, this.context = null, this.classValue = void 0, this.constantValue = void 0, this.dynamicValue = void 0, this.cache = void 0, this.postConstructResult =
|
|
223
|
+
I._instanceContainerMap.delete(this.cache), this.container = null, this.context = null, this.classValue = void 0, this.constantValue = void 0, this.dynamicValue = void 0, this.cache = void 0, this.postConstructResult = m, this.onActivationHandler = void 0, this.onDeactivationHandler = void 0;
|
|
217
224
|
}
|
|
218
225
|
_execute(t) {
|
|
219
226
|
const e = this.cache[t];
|
|
@@ -248,32 +255,32 @@ const y = class y {
|
|
|
248
255
|
return this.cache = this.activate(t), this.status = f.ACTIVATED, this.cache;
|
|
249
256
|
}
|
|
250
257
|
_getInjectProperties(t) {
|
|
251
|
-
const e =
|
|
252
|
-
for (let
|
|
253
|
-
const
|
|
254
|
-
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
|
|
258
|
+
const e = w(this.classValue) || {}, i = Object.keys(e), s = /* @__PURE__ */ Object.create(null), o = [];
|
|
259
|
+
for (let a = 0; a < i.length; a++) {
|
|
260
|
+
const l = i[a], c = e[l], { inject: _, ...h } = c;
|
|
261
|
+
h.parent = t;
|
|
262
|
+
const p = this.container.get(
|
|
263
|
+
b(_),
|
|
264
|
+
h
|
|
258
265
|
);
|
|
259
|
-
|
|
266
|
+
p === void 0 && c.optional || (s[l] = p), o.push(h.binding);
|
|
260
267
|
}
|
|
261
|
-
return { properties: s, bindings:
|
|
268
|
+
return { properties: s, bindings: o };
|
|
262
269
|
}
|
|
263
270
|
};
|
|
264
271
|
// 类型到解析方法的静态映射表,用于替代 get 方法中的 if-else 链
|
|
265
|
-
r(
|
|
272
|
+
r(T, "_resolvers", {
|
|
266
273
|
[d.Instance]: "_resolveInstanceValue",
|
|
267
274
|
[d.ConstantValue]: "_resolveConstantValue",
|
|
268
275
|
[d.DynamicValue]: "_resolveDynamicValue"
|
|
269
276
|
});
|
|
270
|
-
let
|
|
271
|
-
class
|
|
277
|
+
let A = T;
|
|
278
|
+
class M extends y {
|
|
272
279
|
constructor(t) {
|
|
273
280
|
super("No matching binding found for token: ", t);
|
|
274
281
|
}
|
|
275
282
|
}
|
|
276
|
-
class F extends
|
|
283
|
+
class F extends y {
|
|
277
284
|
constructor(t) {
|
|
278
285
|
super("Cannot bind token multiple times: ", t);
|
|
279
286
|
}
|
|
@@ -356,14 +363,14 @@ const v = class v {
|
|
|
356
363
|
this._onDeactivationHandler && this._onDeactivationHandler(t.cache, t.token);
|
|
357
364
|
}
|
|
358
365
|
_buildBinding(t) {
|
|
359
|
-
return new
|
|
366
|
+
return new A(t, this);
|
|
360
367
|
}
|
|
361
368
|
_getBinding(t) {
|
|
362
369
|
return this._bindings.get(t);
|
|
363
370
|
}
|
|
364
371
|
_checkBindingNotFoundError(t, e) {
|
|
365
372
|
if (!e.optional)
|
|
366
|
-
throw new
|
|
373
|
+
throw new M(t);
|
|
367
374
|
}
|
|
368
375
|
};
|
|
369
376
|
// 实例到容器的映射表,用于 @LazyInject 查找实例所属容器
|
|
@@ -374,7 +381,7 @@ const v = class v {
|
|
|
374
381
|
// 由于 Instance 类型每次都通过 new ClassName() 创建新实例,不存在同一实例被多个容器注册的覆盖风险
|
|
375
382
|
r(v, "_instanceContainerMap", /* @__PURE__ */ new WeakMap());
|
|
376
383
|
let I = v;
|
|
377
|
-
class z extends
|
|
384
|
+
class z extends y {
|
|
378
385
|
constructor(t, e) {
|
|
379
386
|
super(
|
|
380
387
|
`@LazyInject(${t == null ? void 0 : t.name}) in class ${e.name} requires a registered container but none was found. Token: `,
|
|
@@ -382,113 +389,116 @@ class z extends g {
|
|
|
382
389
|
);
|
|
383
390
|
}
|
|
384
391
|
}
|
|
385
|
-
function
|
|
392
|
+
function D(n, t) {
|
|
386
393
|
return function(e) {
|
|
387
394
|
return function(i, s) {
|
|
388
|
-
s.
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
});
|
|
395
|
+
const o = s.name, a = s.metadata;
|
|
396
|
+
g(a, u.INJECTED_PROPS) || (a[u.INJECTED_PROPS] = {});
|
|
397
|
+
const l = a[u.INJECTED_PROPS];
|
|
398
|
+
l[o] || (l[o] = {}), l[o][n] = e === void 0 ? t : e;
|
|
392
399
|
};
|
|
393
400
|
};
|
|
394
401
|
}
|
|
395
|
-
function
|
|
402
|
+
function j(n, t) {
|
|
396
403
|
return (e) => (i, s) => {
|
|
397
|
-
const
|
|
398
|
-
if (
|
|
404
|
+
const o = s.name, a = s.metadata;
|
|
405
|
+
if (g(a, n))
|
|
399
406
|
throw new Error(t);
|
|
400
|
-
|
|
401
|
-
const u = this.constructor;
|
|
402
|
-
V(n, { key: a, value: e }, u);
|
|
403
|
-
});
|
|
407
|
+
a[n] = { key: o, value: e };
|
|
404
408
|
};
|
|
405
409
|
}
|
|
406
|
-
const
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
), Q =
|
|
410
|
-
|
|
411
|
-
|
|
410
|
+
const G = D(u.INJECT), $ = D(u.SELF, !0), Z = D(u.SKIP_SELF, !0), q = D(u.OPTIONAL, !0), W = j(
|
|
411
|
+
u.POST_CONSTRUCT,
|
|
412
|
+
E.POST_CONSTRUCT
|
|
413
|
+
), Q = j(
|
|
414
|
+
u.PRE_DESTROY,
|
|
415
|
+
E.PRE_DESTROY
|
|
412
416
|
);
|
|
413
|
-
function
|
|
417
|
+
function X(n, t) {
|
|
418
|
+
const e = t.metadata;
|
|
419
|
+
P(n, e);
|
|
420
|
+
}
|
|
421
|
+
function J(n, t, e, i) {
|
|
414
422
|
if (e == null)
|
|
415
|
-
throw new Error(
|
|
423
|
+
throw new Error(E.LAZY_INJECT_INVALID_TOKEN);
|
|
416
424
|
const s = Symbol.for(t);
|
|
417
425
|
Object.defineProperty(n, t, {
|
|
418
426
|
configurable: !0,
|
|
419
427
|
enumerable: !0,
|
|
420
428
|
get() {
|
|
421
|
-
if (!
|
|
422
|
-
const
|
|
423
|
-
if (!
|
|
424
|
-
throw new z(
|
|
425
|
-
n[s] =
|
|
426
|
-
parent: { token:
|
|
429
|
+
if (!g(n, s)) {
|
|
430
|
+
const o = i || I.getContainerOf(n), a = n.constructor;
|
|
431
|
+
if (!o)
|
|
432
|
+
throw new z(b(e), a);
|
|
433
|
+
n[s] = o.get(b(e), {
|
|
434
|
+
parent: { token: a }
|
|
427
435
|
});
|
|
428
436
|
}
|
|
429
437
|
return n[s];
|
|
430
438
|
},
|
|
431
|
-
set(
|
|
432
|
-
n[s] =
|
|
439
|
+
set(o) {
|
|
440
|
+
n[s] = o;
|
|
433
441
|
}
|
|
434
442
|
});
|
|
435
443
|
}
|
|
436
|
-
function
|
|
444
|
+
function U(n, t) {
|
|
437
445
|
return function(e, i) {
|
|
438
446
|
const s = i.name;
|
|
439
447
|
i.addInitializer(function() {
|
|
440
|
-
|
|
448
|
+
J(this, s, n, t);
|
|
441
449
|
});
|
|
442
450
|
};
|
|
443
451
|
}
|
|
444
|
-
function
|
|
452
|
+
function tt(n) {
|
|
445
453
|
return function(t) {
|
|
446
|
-
return
|
|
454
|
+
return U(t, n);
|
|
447
455
|
};
|
|
448
456
|
}
|
|
449
457
|
const N = Symbol("decorate.metadata");
|
|
450
|
-
function
|
|
451
|
-
const i = Array.isArray(n) ? n : [n], s = t.prototype,
|
|
452
|
-
|
|
453
|
-
const
|
|
454
|
-
kind:
|
|
458
|
+
function et(n, t, e) {
|
|
459
|
+
const i = Array.isArray(n) ? n : [n], s = t.prototype, o = typeof s[e] == "function", a = [];
|
|
460
|
+
g(t, N) || (t[N] = {});
|
|
461
|
+
const l = t[N], c = {
|
|
462
|
+
kind: o ? "method" : "field",
|
|
455
463
|
name: e,
|
|
456
464
|
static: !1,
|
|
457
465
|
private: !1,
|
|
458
466
|
addInitializer(h) {
|
|
459
|
-
|
|
467
|
+
a.push(h);
|
|
460
468
|
},
|
|
461
|
-
metadata:
|
|
469
|
+
metadata: l
|
|
462
470
|
};
|
|
463
|
-
let
|
|
471
|
+
let _ = o ? s[e] : void 0;
|
|
464
472
|
for (let h = i.length - 1; h >= 0; h--) {
|
|
465
|
-
const
|
|
466
|
-
|
|
473
|
+
const p = i[h](_, c);
|
|
474
|
+
o && typeof p == "function" && (_ = p);
|
|
475
|
+
}
|
|
476
|
+
if (o && _ !== s[e] && (s[e] = _), P(t, l), a.length > 0) {
|
|
477
|
+
const h = Object.create(s);
|
|
478
|
+
for (const p of a)
|
|
479
|
+
p.call(h);
|
|
467
480
|
}
|
|
468
|
-
a && p !== s[e] && (s[e] = p);
|
|
469
|
-
const _ = Object.create(s);
|
|
470
|
-
for (const h of o)
|
|
471
|
-
h.call(_);
|
|
472
481
|
}
|
|
473
482
|
export {
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
483
|
+
y as BaseError,
|
|
484
|
+
A as Binding,
|
|
485
|
+
M as BindingNotFoundError,
|
|
477
486
|
H as BindingNotValidError,
|
|
478
|
-
|
|
487
|
+
R as CircularDependencyError,
|
|
479
488
|
I as Container,
|
|
480
489
|
z as ContainerNotFoundError,
|
|
481
490
|
F as DuplicateBindingError,
|
|
482
|
-
|
|
483
|
-
|
|
491
|
+
G as Inject,
|
|
492
|
+
X as Injectable,
|
|
493
|
+
U as LazyInject,
|
|
484
494
|
B as LazyToken,
|
|
485
495
|
q as Optional,
|
|
486
496
|
W as PostConstruct,
|
|
487
|
-
|
|
497
|
+
x as PostConstructError,
|
|
488
498
|
Q as PreDestroy,
|
|
489
499
|
$ as Self,
|
|
490
500
|
Z as SkipSelf,
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
501
|
+
Y as Token,
|
|
502
|
+
tt as createLazyInject,
|
|
503
|
+
et as decorate
|
|
494
504
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaokei/di",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Tiny di library depends on typescript decorator.",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"reflect-metadata": "^0.2.2",
|
|
63
63
|
"standard-version": "^9.5.0",
|
|
64
64
|
"typescript": "~5.6.3",
|
|
65
|
-
"vite": "^
|
|
65
|
+
"vite": "^6.0.0",
|
|
66
66
|
"vite-plugin-dts": "^4.5.0",
|
|
67
67
|
"vitepress": "^1.6.3",
|
|
68
68
|
"vitest": "^3.1.1",
|