@kaokei/di 4.0.0 → 5.0.1

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 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类的。
@@ -17,6 +17,7 @@ export declare class Binding<T = unknown> {
17
17
  dynamicValue?: DynamicValue<T>;
18
18
  cache?: T;
19
19
  postConstructResult: Promise<void> | symbol | undefined;
20
+ transient: boolean;
20
21
  onActivationHandler?: ActivationHandler<T>;
21
22
  onDeactivationHandler?: DeactivationHandler<T>;
22
23
  constructor(token: CommonToken<T>, container: Container);
@@ -28,6 +29,7 @@ export declare class Binding<T = unknown> {
28
29
  toSelf(): this;
29
30
  toConstantValue(value: T): this;
30
31
  toDynamicValue(func: DynamicValue<T>): this;
32
+ inTransientScope(): this;
31
33
  toService(token: CommonToken<T>): this;
32
34
  get(options: Options<T>): any;
33
35
  _getAwaitBindings(bindings: Binding[], filter: PostConstructParam): Binding[];
package/dist/binding.d.ts CHANGED
@@ -17,6 +17,7 @@ export declare class Binding<T = unknown> {
17
17
  dynamicValue?: DynamicValue<T>;
18
18
  cache?: T;
19
19
  postConstructResult: Promise<void> | symbol | undefined;
20
+ transient: boolean;
20
21
  onActivationHandler?: ActivationHandler<T>;
21
22
  onDeactivationHandler?: DeactivationHandler<T>;
22
23
  constructor(token: CommonToken<T>, container: Container);
@@ -28,6 +29,7 @@ export declare class Binding<T = unknown> {
28
29
  toSelf(): this;
29
30
  toConstantValue(value: T): this;
30
31
  toDynamicValue(func: DynamicValue<T>): this;
32
+ inTransientScope(): this;
31
33
  toService(token: CommonToken<T>): this;
32
34
  get(options: Options<T>): any;
33
35
  _getAwaitBindings(bindings: Binding[], filter: PostConstructParam): Binding[];
@@ -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
- * 使用 hasParentClass 判断当前 target 有没有父类
19
- * 如果没有父类直接使用 getOwnMetadata 获取数据
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 getMetadata<K extends keyof MetadataMap>(metadataKey: K, target: CommonToken): MetadataMap[K] | undefined;
25
- export declare function getMetadata(metadataKey: string, target: CommonToken): unknown | undefined;
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;
@@ -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
- * 使用 hasParentClass 判断当前 target 有没有父类
19
- * 如果没有父类直接使用 getOwnMetadata 获取数据
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 getMetadata<K extends keyof MetadataMap>(metadataKey: K, target: CommonToken): MetadataMap[K] | undefined;
25
- export declare function getMetadata(metadataKey: string, target: CommonToken): unknown | undefined;
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;
@@ -13,10 +13,10 @@ export declare const STATUS: {
13
13
  readonly ACTIVATED: "activated";
14
14
  };
15
15
  export declare const BINDING: {
16
- readonly Invalid: "Invalid";
17
- readonly Instance: "Instance";
18
- readonly ConstantValue: "ConstantValue";
19
- readonly DynamicValue: "DynamicValue";
16
+ readonly INVALID: "Invalid";
17
+ readonly INSTANCE: "Instance";
18
+ readonly CONSTANT: "ConstantValue";
19
+ readonly DYNAMIC: "DynamicValue";
20
20
  };
21
21
  /**
22
22
  * 错误消息模板
@@ -13,10 +13,10 @@ export declare const STATUS: {
13
13
  readonly ACTIVATED: "activated";
14
14
  };
15
15
  export declare const BINDING: {
16
- readonly Invalid: "Invalid";
17
- readonly Instance: "Instance";
18
- readonly ConstantValue: "ConstantValue";
19
- readonly DynamicValue: "DynamicValue";
16
+ readonly INVALID: "Invalid";
17
+ readonly INSTANCE: "Instance";
18
+ readonly CONSTANT: "ConstantValue";
19
+ readonly DYNAMIC: "DynamicValue";
20
20
  };
21
21
  /**
22
22
  * 错误消息模板
@@ -22,6 +22,13 @@ export declare class Container {
22
22
  optional?: false;
23
23
  }): T;
24
24
  get<T>(token: CommonToken<T>, options?: Options<T>): T | void;
25
+ getAsync<T>(token: CommonToken<T>, options: Options<T> & {
26
+ optional: true;
27
+ }): Promise<T | void>;
28
+ getAsync<T>(token: CommonToken<T>, options?: Options<T> & {
29
+ optional?: false;
30
+ }): Promise<T>;
31
+ getAsync<T>(token: CommonToken<T>, options?: Options<T>): Promise<T | void>;
25
32
  _resolveSkipSelf<T>(token: CommonToken<T>, options: Options<T>): T | void;
26
33
  _resolveSelf<T>(token: CommonToken<T>, options: Options<T>): T | void;
27
34
  _resolveDefault<T>(token: CommonToken<T>, options: Options<T>): T | void;
@@ -22,6 +22,13 @@ export declare class Container {
22
22
  optional?: false;
23
23
  }): T;
24
24
  get<T>(token: CommonToken<T>, options?: Options<T>): T | void;
25
+ getAsync<T>(token: CommonToken<T>, options: Options<T> & {
26
+ optional: true;
27
+ }): Promise<T | void>;
28
+ getAsync<T>(token: CommonToken<T>, options?: Options<T> & {
29
+ optional?: false;
30
+ }): Promise<T>;
31
+ getAsync<T>(token: CommonToken<T>, options?: Options<T>): Promise<T | void>;
25
32
  _resolveSkipSelf<T>(token: CommonToken<T>, options: Options<T>): T | void;
26
33
  _resolveSelf<T>(token: CommonToken<T>, options: Options<T>): T | void;
27
34
  _resolveDefault<T>(token: CommonToken<T>, options: Options<T>): T | void;
@@ -3,8 +3,8 @@ import { InjectFunction, GenericToken } from './interfaces';
3
3
  /**
4
4
  * 创建属性装饰器的高阶函数(Stage 3 Field Decorator)
5
5
  *
6
- * 通过 context.addInitializer 在实例化时获取构造函数引用,
7
- * 并将装饰器元数据存储到 CacheMap 的 INJECTED_PROPS 分区。
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,
@@ -3,8 +3,8 @@ import { InjectFunction, GenericToken } from './interfaces';
3
3
  /**
4
4
  * 创建属性装饰器的高阶函数(Stage 3 Field Decorator)
5
5
  *
6
- * 通过 context.addInitializer 在实例化时获取构造函数引用,
7
- * 并将装饰器元数据存储到 CacheMap 的 INJECTED_PROPS 分区。
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 U=(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)=>U(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"},d={DEFAULT:"default",INITING:"initing",ACTIVATED:"activated"},f={INVALID:"Invalid",INSTANCE:"Instance",CONSTANT:"ConstantValue",DYNAMIC:"DynamicValue"},g={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 C(n,t){return Object.prototype.hasOwnProperty.call(n,t)}const D=Symbol("UNINITIALIZED"),y=new WeakMap;function P(n){return typeof n=="function"&&Object.getPrototypeOf(n)!==Function.prototype}function m(n,t){y.set(n,t)}function V(n){const t=y.get(n);if(t)return t[u.POST_CONSTRUCT];if(P(n))return V(Object.getPrototypeOf(n))}function w(n){const t=y.get(n);if(t)return t[u.PRE_DESTROY];if(P(n))return w(Object.getPrototypeOf(n))}function R(n){const t=y.get(n),e=t&&C(t,u.INJECTED_PROPS)?t[u.INJECTED_PROPS]:void 0;if(!P(n))return e;const i=R(Object.getPrototypeOf(n));if(i||e)return{...i||{},...e||{}}}class Y{constructor(t){r(this,"name");this.name=t}}class j{constructor(t){r(this,"_callback");this._callback=t}resolve(){return this._callback()}}function O(n){if(!n)throw new Error(g.INVALID_TOKEN);return n instanceof j?n.resolve():n}class v 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 b extends v{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 v{constructor(t){super("Invalid binding: ",t)}}class k extends b{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",f.INVALID);r(this,"status",d.DEFAULT);r(this,"classValue");r(this,"constantValue");r(this,"dynamicValue");r(this,"cache");r(this,"postConstructResult",D);r(this,"transient",!1);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=f.INSTANCE,this.classValue=t,this}toSelf(){return this.to(this.token)}toConstantValue(t){return this.type=f.CONSTANT,this.constantValue=t,this}toDynamicValue(t){return this.type=f.DYNAMIC,this.dynamicValue=t,this}inTransientScope(){return this.transient=!0,this}toService(t){return this.toDynamicValue(e=>e.container.get(t,{parent:{token:this.token}}))}get(t){if(d.INITING===this.status)throw new b(t);if(d.ACTIVATED===this.status)if(this.transient)this.status=d.DEFAULT;else return this.cache;const e=E._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(f.INSTANCE===this.type){const{key:i,value:s}=V(this.classValue)||{};if(i)if(s){const o=e.filter(c=>f.INSTANCE===(c==null?void 0:c.type)),a=this._getAwaitBindings(o,s);for(const c of a)if(c&&c.postConstructResult===D)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(f.INSTANCE===this.type){const{key:t}=w(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=D,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=d.INITING;const e=this._createInstance();this.cache=this.activate(e),this.status=d.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=d.INITING,this.cache=this.activate(this.constantValue),this.status=d.ACTIVATED,this.cache}_resolveDynamicValue(){this.status=d.INITING;const t=this.dynamicValue(this.context);return this.cache=this.activate(t),this.status=d.ACTIVATED,this.cache}_getInjectProperties(t){const e=R(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:I,...h}=c;h.parent=t;const p=this.container.get(O(I),h);p===void 0&&c.optional||(s[l]=p),o.push(h.binding)}return{properties:s,bindings:o}}};r(E,"_resolvers",{[f.INSTANCE]:"_resolveInstanceValue",[f.CONSTANT]:"_resolveConstantValue",[f.DYNAMIC]:"_resolveDynamicValue"});let N=E;class B extends v{constructor(t){super("No matching binding found for token: ",t)}}class H extends v{constructor(t){super("Cannot bind token multiple times: ",t)}}const T=class T{constructor(){r(this,"parent");r(this,"children");r(this,"_bindings",new Map);r(this,"_onActivationHandler");r(this,"_onDeactivationHandler")}static getContainerOf(t){return T._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 T;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)}async getAsync(t,e={}){const i=this.get(t,e),s=e.binding;return(s==null?void 0:s.postConstructResult)instanceof Promise&&await s.postConstructResult,i}_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 N(t,this)}_getBinding(t){return this._bindings.get(t)}_checkBindingNotFoundError(t,e){if(!e.optional)throw new B(t)}};r(T,"_instanceContainerMap",new WeakMap);let _=T;class M extends v{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 A(n,t){return function(e){return function(i,s){const o=s.name,a=s.metadata;C(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(C(a,n))throw new Error(t);a[n]={key:o,value:e}}}const J=A(u.INJECT),K=A(u.SELF,!0),G=A(u.SKIP_SELF,!0),$=A(u.OPTIONAL,!0),Z=F(u.POST_CONSTRUCT,g.POST_CONSTRUCT),q=F(u.PRE_DESTROY,g.PRE_DESTROY);function W(n,t){const e=t.metadata;m(n,e)}function Q(n,t,e,i){if(e==null)throw new Error(g.LAZY_INJECT_INVALID_TOKEN);const s=Symbol.for(t);Object.defineProperty(n,t,{configurable:!0,enumerable:!0,get(){if(!C(n,s)){const o=i||_.getContainerOf(n),a=n.constructor;if(!o)throw new M(O(e),a);n[s]=o.get(O(e),{parent:{token:a}})}return n[s]},set(o){n[s]=o}})}function x(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 x(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=[];C(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 I=o?s[e]:void 0;for(let h=i.length-1;h>=0;h--){const p=i[h](I,c);o&&typeof p=="function"&&(I=p)}if(o&&I!==s[e]&&(s[e]=I),m(t,l),a.length>0){const h=Object.create(s);for(const p of a)p.call(h)}}exports.BaseError=v;exports.Binding=N;exports.BindingNotFoundError=B;exports.BindingNotValidError=L;exports.CircularDependencyError=b;exports.Container=_;exports.ContainerNotFoundError=M;exports.DuplicateBindingError=H;exports.Inject=J;exports.Injectable=W;exports.LazyInject=x;exports.LazyToken=j;exports.Optional=$;exports.PostConstruct=Z;exports.PostConstructError=k;exports.PreDestroy=q;exports.Self=K;exports.SkipSelf=G;exports.Token=Y;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 j = (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) => j(n, typeof t != "symbol" ? t + "" : t, e);
4
- const l = {
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 装饰器的键
@@ -16,16 +16,16 @@ const l = {
16
16
  POST_CONSTRUCT: "postConstruct",
17
17
  // PreDestroy 装饰器的键
18
18
  PRE_DESTROY: "preDestroy"
19
- }, f = {
19
+ }, d = {
20
20
  DEFAULT: "default",
21
21
  INITING: "initing",
22
22
  ACTIVATED: "activated"
23
- }, d = {
24
- Invalid: "Invalid",
25
- Instance: "Instance",
26
- ConstantValue: "ConstantValue",
27
- DynamicValue: "DynamicValue"
28
- }, C = {
23
+ }, f = {
24
+ INVALID: "Invalid",
25
+ INSTANCE: "Instance",
26
+ CONSTANT: "ConstantValue",
27
+ DYNAMIC: "DynamicValue"
28
+ }, g = {
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 m(n, t) {
37
+ function T(n, t) {
38
38
  return Object.prototype.hasOwnProperty.call(n, t);
39
39
  }
40
- const D = Symbol("UNINITIALIZED"), A = /* @__PURE__ */ new WeakMap();
41
- function k(n) {
40
+ const y = Symbol("UNINITIALIZED"), E = /* @__PURE__ */ new WeakMap();
41
+ function m(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
- return (A.get(t) || {})[n];
45
+ E.set(n, t);
50
46
  }
51
- function T(n, t) {
52
- const e = P(n, t);
53
- if (!k(t))
47
+ function b(n) {
48
+ const t = E.get(n);
49
+ if (t)
50
+ return t[u.POST_CONSTRUCT];
51
+ if (m(n))
52
+ return b(Object.getPrototypeOf(n));
53
+ }
54
+ function V(n) {
55
+ const t = E.get(n);
56
+ if (t)
57
+ return t[u.PRE_DESTROY];
58
+ if (m(n))
59
+ return V(Object.getPrototypeOf(n));
60
+ }
61
+ function w(n) {
62
+ const t = E.get(n), e = t && T(t, u.INJECTED_PROPS) ? t[u.INJECTED_PROPS] : void 0;
63
+ if (!m(n))
54
64
  return e;
55
- const i = T(
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 G {
72
+ class K {
66
73
  constructor(t) {
67
74
  // 仅类型层面存在,无运行时开销
68
75
  r(this, "name");
@@ -80,10 +87,10 @@ class B {
80
87
  }
81
88
  function S(n) {
82
89
  if (!n)
83
- throw new Error(C.INVALID_TOKEN);
90
+ throw new Error(g.INVALID_TOKEN);
84
91
  return n instanceof B ? n.resolve() : n;
85
92
  }
86
- class g extends Error {
93
+ class N 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,39 +98,41 @@ class g extends Error {
91
98
  this.name = this.constructor.name, this.token = i;
92
99
  }
93
100
  }
94
- class w extends g {
101
+ class R extends N {
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((a) => a.name || "<anonymous>").join(" --> ");
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 g {
112
+ class H extends N {
106
113
  constructor(t) {
107
114
  super("Invalid binding: ", t);
108
115
  }
109
116
  }
110
- class M extends w {
117
+ class M extends R {
111
118
  constructor(t) {
112
119
  super(t), this.name = "CircularDependencyError inside @PostConstruct";
113
120
  }
114
121
  }
115
- const y = class y {
122
+ const C = class C {
116
123
  constructor(t, e) {
117
124
  r(this, "container");
118
125
  r(this, "context");
119
126
  r(this, "token");
120
- r(this, "type", d.Invalid);
121
- r(this, "status", f.DEFAULT);
127
+ r(this, "type", f.INVALID);
128
+ r(this, "status", d.DEFAULT);
122
129
  r(this, "classValue");
123
130
  r(this, "constantValue");
124
131
  r(this, "dynamicValue");
125
132
  r(this, "cache");
126
- r(this, "postConstructResult", D);
133
+ r(this, "postConstructResult", y);
134
+ // 是否为瞬态作用域,默认 false(单例)
135
+ r(this, "transient", !1);
127
136
  r(this, "onActivationHandler");
128
137
  r(this, "onDeactivationHandler");
129
138
  this.container = e, this.context = { container: this.container }, this.token = t;
@@ -142,16 +151,19 @@ const y = class y {
142
151
  this.onDeactivationHandler && this.onDeactivationHandler(this.cache);
143
152
  }
144
153
  to(t) {
145
- return this.type = d.Instance, this.classValue = t, this;
154
+ return this.type = f.INSTANCE, this.classValue = t, this;
146
155
  }
147
156
  toSelf() {
148
157
  return this.to(this.token);
149
158
  }
150
159
  toConstantValue(t) {
151
- return this.type = d.ConstantValue, this.constantValue = t, this;
160
+ return this.type = f.CONSTANT, this.constantValue = t, this;
152
161
  }
153
162
  toDynamicValue(t) {
154
- return this.type = d.DynamicValue, this.dynamicValue = t, this;
163
+ return this.type = f.DYNAMIC, this.dynamicValue = t, this;
164
+ }
165
+ inTransientScope() {
166
+ return this.transient = !0, this;
155
167
  }
156
168
  toService(t) {
157
169
  return this.toDynamicValue(
@@ -159,11 +171,14 @@ const y = class y {
159
171
  );
160
172
  }
161
173
  get(t) {
162
- if (f.INITING === this.status)
163
- throw new w(t);
164
- if (f.ACTIVATED === this.status)
165
- return this.cache;
166
- const e = y._resolvers[this.type];
174
+ if (d.INITING === this.status)
175
+ throw new R(t);
176
+ if (d.ACTIVATED === this.status)
177
+ if (this.transient)
178
+ this.status = d.DEFAULT;
179
+ else
180
+ return this.cache;
181
+ const e = C._resolvers[this.type];
167
182
  if (e)
168
183
  return this[e](t);
169
184
  throw new H(this.token);
@@ -185,21 +200,21 @@ const y = class y {
185
200
  * - 如果前置服务初始化失败,rejected promise 自然传播,当前服务的 PostConstruct 不执行
186
201
  */
187
202
  _postConstruct(t, e) {
188
- if (d.Instance === this.type) {
189
- const { key: i, value: s } = T(l.POST_CONSTRUCT, this.classValue) || {};
203
+ if (f.INSTANCE === this.type) {
204
+ const { key: i, value: s } = b(this.classValue) || {};
190
205
  if (i)
191
206
  if (s) {
192
- const a = e.filter(
193
- (c) => d.Instance === (c == null ? void 0 : c.type)
194
- ), o = this._getAwaitBindings(a, s);
195
- for (const c of o)
196
- if (c && c.postConstructResult === D)
207
+ const o = e.filter(
208
+ (c) => f.INSTANCE === (c == null ? void 0 : c.type)
209
+ ), a = this._getAwaitBindings(o, s);
210
+ for (const c of a)
211
+ if (c && c.postConstructResult === y)
197
212
  throw new M({
198
213
  token: c.token,
199
214
  parent: t
200
215
  });
201
- const u = o.map((c) => c.postConstructResult);
202
- this.postConstructResult = Promise.all(u).then(
216
+ const l = a.map((c) => c.postConstructResult);
217
+ this.postConstructResult = Promise.all(l).then(
203
218
  () => this._execute(i)
204
219
  );
205
220
  } else
@@ -209,20 +224,20 @@ const y = class y {
209
224
  }
210
225
  }
211
226
  preDestroy() {
212
- if (d.Instance === this.type) {
213
- const { key: t } = T(l.PRE_DESTROY, this.classValue) || {};
227
+ if (f.INSTANCE === this.type) {
228
+ const { key: t } = V(this.classValue) || {};
214
229
  t && this._execute(t);
215
230
  }
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 = D, this.onActivationHandler = void 0, this.onDeactivationHandler = void 0;
231
+ 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 = y, this.onActivationHandler = void 0, this.onDeactivationHandler = void 0;
217
232
  }
218
233
  _execute(t) {
219
234
  const e = this.cache[t];
220
235
  return e == null ? void 0 : e.call(this.cache);
221
236
  }
222
237
  _resolveInstanceValue(t) {
223
- this.status = f.INITING;
238
+ this.status = d.INITING;
224
239
  const e = this._createInstance();
225
- this.cache = this.activate(e), this.status = f.ACTIVATED, this._registerInstance();
240
+ this.cache = this.activate(e), this.status = d.ACTIVATED, this._registerInstance();
226
241
  const { properties: i, bindings: s } = this._getInjectProperties(t);
227
242
  return this._injectProperties(i), this._postConstruct(t, s), this.cache;
228
243
  }
@@ -233,52 +248,52 @@ const y = class y {
233
248
  }
234
249
  // 注册实例与容器的映射关系
235
250
  _registerInstance() {
236
- I._instanceContainerMap.set(this.cache, this.container);
251
+ v._instanceContainerMap.set(this.cache, this.container);
237
252
  }
238
253
  // 将解析后的属性注入到实例上
239
254
  _injectProperties(t) {
240
255
  Object.assign(this.cache, t);
241
256
  }
242
257
  _resolveConstantValue() {
243
- return this.status = f.INITING, this.cache = this.activate(this.constantValue), this.status = f.ACTIVATED, this.cache;
258
+ return this.status = d.INITING, this.cache = this.activate(this.constantValue), this.status = d.ACTIVATED, this.cache;
244
259
  }
245
260
  _resolveDynamicValue() {
246
- this.status = f.INITING;
261
+ this.status = d.INITING;
247
262
  const t = this.dynamicValue(this.context);
248
- return this.cache = this.activate(t), this.status = f.ACTIVATED, this.cache;
263
+ return this.cache = this.activate(t), this.status = d.ACTIVATED, this.cache;
249
264
  }
250
265
  _getInjectProperties(t) {
251
- const e = T(l.INJECTED_PROPS, this.classValue) || {}, i = Object.keys(e), s = /* @__PURE__ */ Object.create(null), a = [];
252
- for (let o = 0; o < i.length; o++) {
253
- const u = i[o], c = e[u], { inject: p, ..._ } = c;
254
- _.parent = t;
255
- const h = this.container.get(
256
- S(p),
257
- _
266
+ const e = w(this.classValue) || {}, i = Object.keys(e), s = /* @__PURE__ */ Object.create(null), o = [];
267
+ for (let a = 0; a < i.length; a++) {
268
+ const l = i[a], c = e[l], { inject: _, ...h } = c;
269
+ h.parent = t;
270
+ const p = this.container.get(
271
+ S(_),
272
+ h
258
273
  );
259
- h === void 0 && c.optional || (s[u] = h), a.push(_.binding);
274
+ p === void 0 && c.optional || (s[l] = p), o.push(h.binding);
260
275
  }
261
- return { properties: s, bindings: a };
276
+ return { properties: s, bindings: o };
262
277
  }
263
278
  };
264
279
  // 类型到解析方法的静态映射表,用于替代 get 方法中的 if-else 链
265
- r(y, "_resolvers", {
266
- [d.Instance]: "_resolveInstanceValue",
267
- [d.ConstantValue]: "_resolveConstantValue",
268
- [d.DynamicValue]: "_resolveDynamicValue"
280
+ r(C, "_resolvers", {
281
+ [f.INSTANCE]: "_resolveInstanceValue",
282
+ [f.CONSTANT]: "_resolveConstantValue",
283
+ [f.DYNAMIC]: "_resolveDynamicValue"
269
284
  });
270
- let b = y;
271
- class x extends g {
285
+ let O = C;
286
+ class x extends N {
272
287
  constructor(t) {
273
288
  super("No matching binding found for token: ", t);
274
289
  }
275
290
  }
276
- class F extends g {
291
+ class F extends N {
277
292
  constructor(t) {
278
293
  super("Cannot bind token multiple times: ", t);
279
294
  }
280
295
  }
281
- const v = class v {
296
+ const I = class I {
282
297
  constructor() {
283
298
  r(this, "parent");
284
299
  r(this, "children");
@@ -288,7 +303,7 @@ const v = class v {
288
303
  }
289
304
  // 查询实例所属的容器
290
305
  static getContainerOf(t) {
291
- return v._instanceContainerMap.get(t);
306
+ return I._instanceContainerMap.get(t);
292
307
  }
293
308
  bind(t) {
294
309
  if (this._bindings.has(t))
@@ -314,7 +329,7 @@ const v = class v {
314
329
  return this.isCurrentBound(t) || !!this.parent && this.parent.isBound(t);
315
330
  }
316
331
  createChild() {
317
- const t = new v();
332
+ const t = new I();
318
333
  return t.parent = this, this.children || (this.children = /* @__PURE__ */ new Set()), this.children.add(t), t;
319
334
  }
320
335
  destroy() {
@@ -329,6 +344,10 @@ const v = class v {
329
344
  get(t, e = {}) {
330
345
  return e.skipSelf ? this._resolveSkipSelf(t, e) : e.self ? this._resolveSelf(t, e) : this._resolveDefault(t, e);
331
346
  }
347
+ async getAsync(t, e = {}) {
348
+ const i = this.get(t, e), s = e.binding;
349
+ return (s == null ? void 0 : s.postConstructResult) instanceof Promise && await s.postConstructResult, i;
350
+ }
332
351
  // 处理 skipSelf 选项:跳过当前容器,委托父容器解析
333
352
  _resolveSkipSelf(t, e) {
334
353
  return this.parent ? (e.skipSelf = !1, this.parent.get(t, e)) : this._checkBindingNotFoundError(t, e);
@@ -356,7 +375,7 @@ const v = class v {
356
375
  this._onDeactivationHandler && this._onDeactivationHandler(t.cache, t.token);
357
376
  }
358
377
  _buildBinding(t) {
359
- return new b(t, this);
378
+ return new O(t, this);
360
379
  }
361
380
  _getBinding(t) {
362
381
  return this._bindings.get(t);
@@ -372,9 +391,9 @@ const v = class v {
372
391
  // 同一对象可能通过 toConstantValue 被绑定到多个容器,WeakMap 只能保留最后一次映射,
373
392
  // 会导致 @LazyInject 从错误的容器解析依赖。
374
393
  // 由于 Instance 类型每次都通过 new ClassName() 创建新实例,不存在同一实例被多个容器注册的覆盖风险
375
- r(v, "_instanceContainerMap", /* @__PURE__ */ new WeakMap());
376
- let I = v;
377
- class z extends g {
394
+ r(I, "_instanceContainerMap", /* @__PURE__ */ new WeakMap());
395
+ let v = I;
396
+ class U extends N {
378
397
  constructor(t, e) {
379
398
  super(
380
399
  `@LazyInject(${t == null ? void 0 : t.name}) in class ${e.name} requires a registered container but none was found. Token: `,
@@ -382,105 +401,108 @@ class z extends g {
382
401
  );
383
402
  }
384
403
  }
385
- function E(n, t) {
404
+ function A(n, t) {
386
405
  return function(e) {
387
406
  return function(i, s) {
388
- s.addInitializer(function() {
389
- const a = this.constructor, o = s.name, u = P(l.INJECTED_PROPS, a) || {}, c = u[o] || {};
390
- c[n] = e === void 0 ? t : e, u[o] = c, V(l.INJECTED_PROPS, u, a);
391
- });
407
+ const o = s.name, a = s.metadata;
408
+ T(a, u.INJECTED_PROPS) || (a[u.INJECTED_PROPS] = {});
409
+ const l = a[u.INJECTED_PROPS];
410
+ l[o] || (l[o] = {}), l[o][n] = e === void 0 ? t : e;
392
411
  };
393
412
  };
394
413
  }
395
- function R(n, t) {
414
+ function j(n, t) {
396
415
  return (e) => (i, s) => {
397
- const a = s.name, o = s.metadata;
398
- if (m(o, n))
416
+ const o = s.name, a = s.metadata;
417
+ if (T(a, n))
399
418
  throw new Error(t);
400
- o[n] = !0, s.addInitializer(function() {
401
- const u = this.constructor;
402
- V(n, { key: a, value: e }, u);
403
- });
419
+ a[n] = { key: o, value: e };
404
420
  };
405
421
  }
406
- const K = E(l.INJECT), $ = E(l.SELF, !0), Z = E(l.SKIP_SELF, !0), q = E(l.OPTIONAL, !0), W = R(
407
- l.POST_CONSTRUCT,
408
- C.POST_CONSTRUCT
409
- ), Q = R(
410
- l.PRE_DESTROY,
411
- C.PRE_DESTROY
422
+ const G = A(u.INJECT), $ = A(u.SELF, !0), Z = A(u.SKIP_SELF, !0), q = A(u.OPTIONAL, !0), W = j(
423
+ u.POST_CONSTRUCT,
424
+ g.POST_CONSTRUCT
425
+ ), Q = j(
426
+ u.PRE_DESTROY,
427
+ g.PRE_DESTROY
412
428
  );
413
- function U(n, t, e, i) {
429
+ function X(n, t) {
430
+ const e = t.metadata;
431
+ P(n, e);
432
+ }
433
+ function Y(n, t, e, i) {
414
434
  if (e == null)
415
- throw new Error(C.LAZY_INJECT_INVALID_TOKEN);
435
+ throw new Error(g.LAZY_INJECT_INVALID_TOKEN);
416
436
  const s = Symbol.for(t);
417
437
  Object.defineProperty(n, t, {
418
438
  configurable: !0,
419
439
  enumerable: !0,
420
440
  get() {
421
- if (!m(n, s)) {
422
- const a = i || I.getContainerOf(n), o = n.constructor;
423
- if (!a)
424
- throw new z(S(e), o);
425
- n[s] = a.get(S(e), {
426
- parent: { token: o }
441
+ if (!T(n, s)) {
442
+ const o = i || v.getContainerOf(n), a = n.constructor;
443
+ if (!o)
444
+ throw new U(S(e), a);
445
+ n[s] = o.get(S(e), {
446
+ parent: { token: a }
427
447
  });
428
448
  }
429
449
  return n[s];
430
450
  },
431
- set(a) {
432
- n[s] = a;
451
+ set(o) {
452
+ n[s] = o;
433
453
  }
434
454
  });
435
455
  }
436
- function J(n, t) {
456
+ function z(n, t) {
437
457
  return function(e, i) {
438
458
  const s = i.name;
439
459
  i.addInitializer(function() {
440
- U(this, s, n, t);
460
+ Y(this, s, n, t);
441
461
  });
442
462
  };
443
463
  }
444
- function X(n) {
464
+ function tt(n) {
445
465
  return function(t) {
446
- return J(t, n);
466
+ return z(t, n);
447
467
  };
448
468
  }
449
- const N = Symbol("decorate.metadata");
450
- function tt(n, t, e) {
451
- const i = Array.isArray(n) ? n : [n], s = t.prototype, a = typeof s[e] == "function", o = [];
452
- m(t, N) || (t[N] = {});
453
- const u = t[N], c = {
454
- kind: a ? "method" : "field",
469
+ const D = Symbol("decorate.metadata");
470
+ function et(n, t, e) {
471
+ const i = Array.isArray(n) ? n : [n], s = t.prototype, o = typeof s[e] == "function", a = [];
472
+ T(t, D) || (t[D] = {});
473
+ const l = t[D], c = {
474
+ kind: o ? "method" : "field",
455
475
  name: e,
456
476
  static: !1,
457
477
  private: !1,
458
478
  addInitializer(h) {
459
- o.push(h);
479
+ a.push(h);
460
480
  },
461
- metadata: u
481
+ metadata: l
462
482
  };
463
- let p = a ? s[e] : void 0;
483
+ let _ = o ? s[e] : void 0;
464
484
  for (let h = i.length - 1; h >= 0; h--) {
465
- const O = i[h](p, c);
466
- a && typeof O == "function" && (p = O);
485
+ const p = i[h](_, c);
486
+ o && typeof p == "function" && (_ = p);
487
+ }
488
+ if (o && _ !== s[e] && (s[e] = _), P(t, l), a.length > 0) {
489
+ const h = Object.create(s);
490
+ for (const p of a)
491
+ p.call(h);
467
492
  }
468
- a && p !== s[e] && (s[e] = p);
469
- const _ = Object.create(s);
470
- for (const h of o)
471
- h.call(_);
472
493
  }
473
494
  export {
474
- g as BaseError,
475
- b as Binding,
495
+ N as BaseError,
496
+ O as Binding,
476
497
  x as BindingNotFoundError,
477
498
  H as BindingNotValidError,
478
- w as CircularDependencyError,
479
- I as Container,
480
- z as ContainerNotFoundError,
499
+ R as CircularDependencyError,
500
+ v as Container,
501
+ U as ContainerNotFoundError,
481
502
  F as DuplicateBindingError,
482
- K as Inject,
483
- J as LazyInject,
503
+ G as Inject,
504
+ X as Injectable,
505
+ z as LazyInject,
484
506
  B as LazyToken,
485
507
  q as Optional,
486
508
  W as PostConstruct,
@@ -488,7 +510,7 @@ export {
488
510
  Q as PreDestroy,
489
511
  $ as Self,
490
512
  Z as SkipSelf,
491
- G as Token,
492
- X as createLazyInject,
493
- tt as decorate
513
+ K as Token,
514
+ tt as createLazyInject,
515
+ et as decorate
494
516
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaokei/di",
3
- "version": "4.0.0",
3
+ "version": "5.0.1",
4
4
  "type": "module",
5
5
  "description": "Tiny di library depends on typescript decorator.",
6
6
  "main": "./dist/index.cjs",
@@ -37,6 +37,7 @@
37
37
  ],
38
38
  "scripts": {
39
39
  "test": "vitest",
40
+ "test:inversify": "vitest run --config vite.config.inversify.ts",
40
41
  "coverage": "vitest run --coverage",
41
42
  "build": "tsc && vite build",
42
43
  "clean": "rm -rf dist/*",
@@ -50,6 +51,7 @@
50
51
  "docs:preview": "vitepress preview docs"
51
52
  },
52
53
  "devDependencies": {
54
+ "@swc/core": "^1.15.21",
53
55
  "@types/fs-extra": "^11.0.4",
54
56
  "@types/node": "^22.13.4",
55
57
  "@vitejs/plugin-vue": "^5.2.1",
@@ -62,7 +64,8 @@
62
64
  "reflect-metadata": "^0.2.2",
63
65
  "standard-version": "^9.5.0",
64
66
  "typescript": "~5.6.3",
65
- "vite": "^5.4.14",
67
+ "unplugin-swc": "^1.5.9",
68
+ "vite": "5.3.0",
66
69
  "vite-plugin-dts": "^4.5.0",
67
70
  "vitepress": "^1.6.3",
68
71
  "vitest": "^3.1.1",