@path-ioc/container 0.1.1 → 0.1.3
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/LICENSE +21 -0
- package/README.md +60 -59
- package/README.zh-CN.md +154 -0
- package/package.json +2 -2
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hanlin Lian
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,123 +1,126 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
<h1>@path-ioc/container</h1>
|
|
3
3
|
<p><b>High-Performance Dual-Engine Container & Subgraph Slice Scheduler for Path-IoC</b></p>
|
|
4
|
-
<p>
|
|
4
|
+
<p>Advanced on-demand container & dual-engine (Async Topological Concurrency / Turbo Synchronous Pass-through) scheduler extension</p>
|
|
5
5
|
|
|
6
6
|
<p>
|
|
7
7
|
<a href="https://www.npmjs.com/package/@path-ioc/container"><img src="https://img.shields.io/npm/v/@path-ioc/container.svg" alt="NPM version"></a>
|
|
8
8
|
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/npm/l/@path-ioc/container.svg" alt="License"></a>
|
|
9
9
|
<a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/TypeScript-5.0+-3178C6?logo=typescript&logoColor=white" alt="TypeScript"></a>
|
|
10
|
+
<a href="https://path-ioc.dev"><img src="https://img.shields.io/badge/docs-path--ioc.dev-8A2BE2.svg" alt="Docs"></a>
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<p>
|
|
14
|
+
<b>English</b> | <a href="./README.zh-CN.md">简体中文</a> | <a href="https://path-ioc.dev/api/container">Official Docs</a>
|
|
10
15
|
</p>
|
|
11
16
|
</div>
|
|
12
17
|
|
|
13
|
-
>
|
|
14
|
-
> `@path-ioc/core`
|
|
15
|
-
> `@path-ioc/container`
|
|
18
|
+
> **Architectural Purpose**:
|
|
19
|
+
> `@path-ioc/core` static graph compilation and native `async/await` topological preheating form the bedrock of Path-IoC.
|
|
20
|
+
> `@path-ioc/container` is the companion extension proving that without TypeScript decorators or `reflect-metadata`, Path-IoC natively accommodates and surpasses traditional JS IoC frameworks in **"On-Demand Subgraph Slicing"** and **"Dynamic Dependency Resolution"**, delivering **4 physically closed-loop scheduling paradigms**.
|
|
16
21
|
|
|
17
22
|
---
|
|
18
23
|
|
|
19
|
-
##
|
|
24
|
+
## Architectural Philosophy: Physical Separation & Subgraph Slicing
|
|
20
25
|
|
|
21
|
-
### 1.
|
|
26
|
+
### 1. Canonical Static Topology vs. Extended On-Demand Proxying
|
|
22
27
|
|
|
23
|
-
|
|
28
|
+
In enterprise production (similar to Java Spring's default `eager-singleton`), full DAG topological preheating at boot time remains the gold standard for system stability, dependency integrity, and runtime throughput:
|
|
24
29
|
|
|
25
|
-
-
|
|
26
|
-
-
|
|
30
|
+
- **Canonical Core (`@path-ioc/core`)**: Strictly rigorous—static graph compilation, DFS Fail-Fast cyclic dependency rejection, and native `async/await` DAG concurrency. Rejects implicit cycle-breaking that masks architectural design flaws.
|
|
31
|
+
- **Extended Container (`@path-ioc/container`)**: Open and versatile—wraps high-order proxy containers to decompose "Loading Scope (`eager` | `demand`)" and "Execution Engine (`async` | `turbo`)" into a **2-dimensional orthogonal matrix**, matching traditional on-demand IoC patterns.
|
|
27
32
|
|
|
28
33
|
---
|
|
29
34
|
|
|
30
|
-
### 2.
|
|
35
|
+
### 2. The Irreconcilable Physical Law: `async` vs. `turbo`
|
|
31
36
|
|
|
32
|
-
|
|
37
|
+
In the JavaScript/TypeScript single-threaded execution model, **"Asynchronous Initialization"** and **"Dynamic Runtime Dependency Sensing"** are physically irreconcilable:
|
|
33
38
|
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
39
|
+
- **Physical Reason**: JavaScript's Proxy dynamic getter (`c.foo`) is purely synchronous; it cannot suspend execution mid-flight to await an asynchronous microtask.
|
|
40
|
+
- If a module requires asynchronous setup (`async main`), its dependencies **must be statically declared beforehand** so the DAG scheduler can orchestrate topological `await` execution.
|
|
41
|
+
- If dynamic sensing without declared dependencies were permitted during `async` execution, accessing an unready node would inevitably yield unhandled dangling Promises or deadlock the event loop.
|
|
37
42
|
|
|
38
|
-
Path-IoC
|
|
39
|
-
- **`async`
|
|
40
|
-
- **`turbo`
|
|
43
|
+
Path-IoC resolves this via physical separation:
|
|
44
|
+
- **`async` mode**: Explicit `dependencies` -> Compiled static DAG -> **100% Native Reactive Topological Concurrency**;
|
|
45
|
+
- **`turbo` mode**: Zero `dependencies` declarations -> Runtime Proxy Dynamic Getters -> **Zero-config pass-through & lock-free cycle unwinding**.
|
|
41
46
|
|
|
42
47
|
---
|
|
43
48
|
|
|
44
|
-
##
|
|
49
|
+
## Selection Matrix
|
|
45
50
|
|
|
46
|
-
|
|
|
51
|
+
| Dimension | **NestJS** | **InversifyJS** | **Awilix** | **TSyringe** | **TypeDI** | **@path-ioc/container** |
|
|
47
52
|
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
|
|
|
53
|
+
| **Core Contract** | `@Injectable()` + TS Decorators + `reflect-metadata` | `@injectable()` + TS Decorators + `reflect-metadata` | Regex `.toString()` or param inspection + Proxy | `@singleton()` + TS Decorators + `reflect-metadata` | `@Service()` + TS Decorators + `reflect-metadata` | **Physical Path Contract + Pure ES Closures + Static Graph** |
|
|
54
|
+
| **Code Intrusion** | High (framework decorators everywhere) | High (bound to `@inject`) | Low (matches parameters) | High (Microsoft decorators) | High (TypeDI decorators) | **Zero** (Pure ES functions; runs independently) |
|
|
55
|
+
| **On-Demand / Lazy Paradigm** | Module-level explicit lazy loading (`LazyModuleLoader`) | Property-level lazy injection (`@lazyInject`) | Proxy-based on-demand instantiation (sync only) | Not supported | Not supported | **Forward Subgraph Slicing** (`extractSubModules` automatically extracts forward dependency slice) |
|
|
56
|
+
| **Cycle Resolution** | `forwardRef()` (breaks easily on async) | `@lazyInject()` deferred lookup | Dynamic Proxy Getter (sync only) | `delay()` with explicit token | `constructMany` deferred | **Turbo Mode Dynamic Getter** (Zero tokens; automatic sync cycle unwinding) |
|
|
57
|
+
| **Async Concurrency** | Serial pipeline; sequential blocking | `getAsync()` without native DAG | Async factory (`container.build()`) | None | None | **Dual Engine Scheduler** (`async` native DAG concurrency / `turbo` synchronous pass-through) |
|
|
53
58
|
|
|
54
59
|
---
|
|
55
60
|
|
|
56
|
-
## 4
|
|
61
|
+
## 4 Scheduling Paradigms Matrix
|
|
57
62
|
|
|
58
|
-
`@path-ioc/container`
|
|
63
|
+
`@path-ioc/container` combines `strategy` (`eager` | `demand`) $\times$ `mode` (`async` | `turbo`) into 4 physical paradigms:
|
|
59
64
|
|
|
60
65
|
```
|
|
61
66
|
┌─────────────────────────┬─────────────────────────┐
|
|
62
67
|
│ mode: "async" │ mode: "turbo" │
|
|
63
|
-
│ (
|
|
68
|
+
│ (Reactive DAG Engine) │ (Zero-Promise Sync) │
|
|
64
69
|
┌───────────────────┼─────────────────────────┼─────────────────────────┤
|
|
65
|
-
│ strategy: "eager" │ ①
|
|
66
|
-
│ (
|
|
70
|
+
│ strategy: "eager" │ ① Full Async Preheat │ ② Sync Preheat + Dynamic│
|
|
71
|
+
│ (Full Load) │ (Mounts $ready handle) │ (Fast sync utilities) │
|
|
67
72
|
├───────────────────┼─────────────────────────┼─────────────────────────┤
|
|
68
|
-
│ strategy: "demand"│ ③
|
|
69
|
-
│ (
|
|
73
|
+
│ strategy: "demand"│ ③ Subgraph On-Demand │ ④ Direct Sync Pass-thru│
|
|
74
|
+
│ (Instant Slice) │ (Large SPA / Fuse Prot)│ (Ultra-fast CLI / Test)│
|
|
70
75
|
└───────────────────┴─────────────────────────┴─────────────────────────┘
|
|
71
76
|
```
|
|
72
77
|
|
|
73
|
-
|
|
|
78
|
+
| Paradigm (`strategy` $\times$ `mode`) | Trigger Mechanism | Key Characteristics | Best Suited For |
|
|
74
79
|
| :--- | :--- | :--- | :--- |
|
|
75
|
-
| **`eager` + `async`** |
|
|
76
|
-
| **`eager` + `turbo`** |
|
|
77
|
-
| **`demand` + `async`** |
|
|
78
|
-
| **`demand` + `turbo`** |
|
|
80
|
+
| **`eager` + `async`** | Container creation | Full DAG topological concurrency preheat; non-enumerable `container.$ready` handle | Standard servers / microservices, preheating pools and caches at startup |
|
|
81
|
+
| **`eager` + `turbo`** | Container creation | Synchronously evaluates modules in topological order; tracks dynamically added modules | Synchronous client applications, complex monolithic toolchains |
|
|
82
|
+
| **`demand` + `async`** | Property access (`container.UserPage`) | Traverses forward dependency tree to extract minimum slice; strict fuse protection | Large SPAs, route-level code splitting, extreme cold-start optimization |
|
|
83
|
+
| **`demand` + `turbo`** | Property access (`container.foo`) | Instant synchronous evaluation without `await`; supports dynamic sensing & unwinding | Ultra-fast CLI tools, synchronous pipelines, unit test isolation |
|
|
79
84
|
|
|
80
85
|
---
|
|
81
86
|
|
|
82
|
-
##
|
|
87
|
+
## Core Mechanism: Subgraph Slice Extraction
|
|
83
88
|
|
|
84
|
-
|
|
89
|
+
In `demand` mode, when accessing `container.UserPage` for the first time, the container does not pull the entire registry. Instead, it calls `extractSubModules(graph, 'UserPage')`:
|
|
85
90
|
|
|
86
|
-
1.
|
|
87
|
-
2.
|
|
88
|
-
3.
|
|
91
|
+
1. **Forward Traversal**: Starting from `UserPage`, performs depth-first recursion over `resolvedDepsMap`;
|
|
92
|
+
2. **Deterministic Isolation**: Strictly collects `UserPage` and its downstream dependencies, pruning unrelated branches;
|
|
93
|
+
3. **Local Compilation**: Compiles the minimal extracted subset into a sub-graph and executes it immediately.
|
|
89
94
|
|
|
90
95
|
```
|
|
91
|
-
|
|
96
|
+
Access container.UserPage
|
|
92
97
|
│
|
|
93
98
|
▼
|
|
94
|
-
[
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
99
|
+
[ Entrypoint Identified ] ───► extractSubModules(graph, "UserPage")
|
|
100
|
+
│
|
|
101
|
+
├── 1. Recursively extract forward dependencies (UserService, UserApi...)
|
|
102
|
+
└── 2. Compile and instantiate local slice immediately
|
|
98
103
|
```
|
|
99
104
|
|
|
100
105
|
---
|
|
101
106
|
|
|
102
|
-
## API
|
|
107
|
+
## API Reference
|
|
103
108
|
|
|
104
109
|
### `createContainer(graph, options)`
|
|
105
110
|
|
|
106
|
-
创建高阶代理容器。
|
|
107
|
-
|
|
108
111
|
```typescript
|
|
109
112
|
export interface CreateContainerOptions {
|
|
110
113
|
/**
|
|
111
|
-
*
|
|
112
|
-
* - "eager":
|
|
113
|
-
* - "demand":
|
|
114
|
+
* Loading Strategy:
|
|
115
|
+
* - "eager": Full preheat (initializes all modules upon container creation)
|
|
116
|
+
* - "demand": On-demand slicing (initializes modules when properties are accessed)
|
|
114
117
|
*/
|
|
115
118
|
strategy: "eager" | "demand";
|
|
116
119
|
|
|
117
120
|
/**
|
|
118
|
-
*
|
|
119
|
-
* - "async":
|
|
120
|
-
* - "turbo":
|
|
121
|
+
* Execution Engine:
|
|
122
|
+
* - "async": Reactive asynchronous DAG topological concurrency
|
|
123
|
+
* - "turbo": Pure synchronous pass-through zero-promise engine
|
|
121
124
|
*/
|
|
122
125
|
mode: "async" | "turbo";
|
|
123
126
|
}
|
|
@@ -132,8 +135,6 @@ export const createContainer: (
|
|
|
132
135
|
|
|
133
136
|
### `extractSubModules(graph, ...entryPoints)`
|
|
134
137
|
|
|
135
|
-
底层正向子图切片提取器工具函数。
|
|
136
|
-
|
|
137
138
|
```typescript
|
|
138
139
|
export const extractSubModules: (
|
|
139
140
|
graph: CompiledModuleGraph,
|
|
@@ -143,7 +144,7 @@ export const extractSubModules: (
|
|
|
143
144
|
|
|
144
145
|
---
|
|
145
146
|
|
|
146
|
-
##
|
|
147
|
+
## License
|
|
147
148
|
|
|
148
149
|
Released under the [MIT License](./LICENSE).
|
|
149
|
-
Copyright © 2026 [Path-IoC Organization](https://github.com/path-ioc) & Lian HanLin.
|
|
150
|
+
Copyright © 2026-present [Path-IoC Organization](https://github.com/path-ioc) & Lian HanLin.
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<h1>@path-ioc/container</h1>
|
|
3
|
+
<p><b>High-Performance Dual-Engine Container & Subgraph Slice Scheduler for Path-IoC</b></p>
|
|
4
|
+
<p>Path-IoC 高阶按需容器与双引擎(Async 拓扑并发 / Turbo 纯同步直通)调度扩展</p>
|
|
5
|
+
|
|
6
|
+
<p>
|
|
7
|
+
<a href="https://www.npmjs.com/package/@path-ioc/container"><img src="https://img.shields.io/npm/v/@path-ioc/container.svg" alt="NPM version"></a>
|
|
8
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/npm/l/@path-ioc/container.svg" alt="License"></a>
|
|
9
|
+
<a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/TypeScript-5.0+-3178C6?logo=typescript&logoColor=white" alt="TypeScript"></a>
|
|
10
|
+
<a href="https://path-ioc.dev/zh/"><img src="https://img.shields.io/badge/文档-path--ioc.dev-8A2BE2.svg" alt="Documentation"></a>
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<p>
|
|
14
|
+
<a href="./README.md">English</a> | <b>简体中文</b> | <a href="https://path-ioc.dev/zh/api/container">官方文档</a>
|
|
15
|
+
</p>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
> **架构定位说明**:
|
|
19
|
+
> `@path-ioc/core` 静态图编译与原生 `async/await` 拓扑并发预热是 Path-IoC 架构的核心基石。
|
|
20
|
+
> `@path-ioc/container` 是 Path-IoC 架构治理开放与包容的对标扩展包。它证明了 Path-IoC 无需引入 TS 装饰器与 `reflect-metadata` 元数据包袱,即可原生兼容并超越传统 JS IoC 框架的 **“按需加载 (Sub-graph Slicing)”** 与 **“动态依赖感知 (Dynamic Resolution)”** 模式,提供物理完备的 **4 种全闭环调度范式**。
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 核心设计哲学:物理分治与按需切片 (Architecture Philosophy)
|
|
25
|
+
|
|
26
|
+
### 1. 正统静态拓扑 vs 扩展按需代理
|
|
27
|
+
|
|
28
|
+
在工业级生产实践中(如 Java Spring 默认 `eager-singleton`),启动期全量 DAG 拓扑预热是保持系统稳定性、依赖完整性与最高运行性能的黄金标准。因此:
|
|
29
|
+
|
|
30
|
+
- **正统 Core (`@path-ioc/core`)**:坚持绝对严谨——静态图编译、DFS 严谨 Fail-Fast 拦截循环依赖、原生 `async/await` 拓扑并发,杜绝隐式解环遮蔽架构漏洞。
|
|
31
|
+
- **扩展 Container (`@path-ioc/container`)**:展现开放包容——通过包装高阶 Proxy 代理容器,将“加载范围 (Eager/Demand)”与“执行引擎 (Async/Turbo)”拆解为 **2 维物理正交矩阵**,以能力降级的方式完美对标传统 IoC 框架的按需与依赖感知模式。
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
### 2. 物理不可调和律与物理分治 (`async` vs `turbo`)
|
|
36
|
+
|
|
37
|
+
在 JavaScript/TypeScript 单线程模型中,**“异步初始化 (Async)”** 与 **“运行期动态依赖感知 (Dynamic Sensing)”** 在物理上是不可调和的:
|
|
38
|
+
|
|
39
|
+
- **物理原因**:JS 的 Proxy Dynamic Getter(`c.foo`)本质上是纯同步的,无法在纯同步代码中间“挂起线程去异步等待”。
|
|
40
|
+
- 如果一个模块需要异步初始化(`async main`),就**必须在唤醒前通过 `dependencies` 构建静态图**,才能编排 DAG 拓扑顺序提前 `await`;
|
|
41
|
+
- 如果允许不写 `dependencies` 靠运行期动态感知,那么在 `async` 模式下一旦访问未就绪的异步节点,就必然会导致返回 `Promise` 未决遗留或微任务死锁。
|
|
42
|
+
|
|
43
|
+
Path-IoC 通过物理分治实现优雅解法:
|
|
44
|
+
- **`async` 模式**:显式声明 `dependencies` -> 编译静态 DAG 图 -> 获得 **100% 原生反应式拓扑并发**;
|
|
45
|
+
- **`turbo` 模式**:免写 `dependencies` -> 运行期 Proxy Dynamic Getter 动态感知 -> 获得 **零配置直通与纯同步无锁解环**。
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 主流 IoC 框架选型对比矩阵 (Selection Matrix)
|
|
50
|
+
|
|
51
|
+
| 对比维度 | **NestJS** | **InversifyJS** | **Awilix** | **TSyringe** | **TypeDI** | **@path-ioc/container** *(Path-IoC 扩展)* |
|
|
52
|
+
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|
|
53
|
+
| **底层依赖契约** | `@Injectable()` + TS 装饰器 + `reflect-metadata` | `@injectable()` + TS 装饰器 + `reflect-metadata` | 正则解析 `.toString()` 或形参匹配 + Proxy | `@singleton()` + TS 装饰器 + `reflect-metadata` | `@Service()` + TS 装饰器 + `reflect-metadata` | **物理路径契约 + 纯 ES 模块闭包 + 静态图** |
|
|
54
|
+
| **代码侵入性** | 强侵入 (强绑定 Nest 框架装饰器与概念) | 强侵入 (强绑定 `@inject` 装饰器) | 低侵入 (按形参匹配,无需装饰器) | 强侵入 (强绑定 Microsoft 装饰器) | 强侵入 (强绑定 TypeDI 装饰器) | **零侵入** (纯 ES 模块导出函数,脱离框架完全独立可跑) |
|
|
55
|
+
| **按需/懒加载范式** | 模块级显式懒加载 (`LazyModuleLoader`) | 属性级懒注入 (`@lazyInject`) | Proxy 模式按需实例化 (纯同步属性访问) | 不支持按需 (创建容器即解析全量 Class) | 不支持按需 (实例化即解析全量 Class) | **正向极简子图按需切片** (`extractSubModules` 触达点自动正向提取子图) |
|
|
56
|
+
| **循环依赖处理** | `forwardRef()` (遇 async 易死锁) | `@lazyInject()` 延迟解析 | Dynamic Proxy Getter (仅支持纯同步) | `delay()` (需显式 Token 包装) | `constructMany` 延迟解析 | **Turbo 模式 Dynamic Getter 无锁解环** (零 Token 包装,纯同步自动解环) |
|
|
57
|
+
| **异步初始化与调度** | 串行主导 (构造函数纯同步,依赖 `onModuleInit` 钩子) | 支持 `getAsync()` (无 native DAG 调度) | 支持异步工厂 (`container.build()`) | 无 native 异步调度 | 无 native 异步调度 | **拓扑并发 / 纯同步直通双引擎** (`async` 原生 DAG 并发 / `turbo` 纯同步直通) |
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 4 大引擎调度范式矩阵 (Evaluation Matrix)
|
|
62
|
+
|
|
63
|
+
`@path-ioc/container` 通过 `strategy` (加载范围: `eager` | `demand`) $\times$ `mode` (执行引擎: `async` | `turbo`) 划分为 4 种物理完备的调度范式:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
┌─────────────────────────┬─────────────────────────┐
|
|
67
|
+
│ mode: "async" │ mode: "turbo" │
|
|
68
|
+
│ (反应式拓扑并发引擎) │ (纯同步直通零Promise) │
|
|
69
|
+
┌───────────────────┼─────────────────────────┼─────────────────────────┤
|
|
70
|
+
│ strategy: "eager" │ ① 全量异步拓扑预热 │ ② 纯同步预热 + 动态感知│
|
|
71
|
+
│ (全量加载) │ (挂载 $ready 句柄) │ (高频同步工具库/APP) │
|
|
72
|
+
├───────────────────┼─────────────────────────┼─────────────────────────┤
|
|
73
|
+
│ strategy: "demand"│ ③ 极简子图按需提取 │ ④ 纯同步直通零延迟 │
|
|
74
|
+
│ (极速按需) │ (大型 SPA/单点熔断防护)│ (极速 CLI/同步工作流) │
|
|
75
|
+
└───────────────────┴─────────────────────────┴─────────────────────────┘
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
| 组合范式 (`strategy` $\times$ `mode`) | 物理触发机制 | 关键物理特性 | 最佳适用场景 |
|
|
79
|
+
| :--- | :--- | :--- | :--- |
|
|
80
|
+
| **`eager` + `async`** | 容器创建时立刻触发 | 全量 DAG 拓扑并发预热,容器挂载非可枚举 `container.$ready` 追踪句柄 | 标准 Server / 后台微服务,启动时即全量预热连接池与缓存 |
|
|
81
|
+
| **`eager` + `turbo`** | 容器创建时立刻触发 | 启动时按拓扑顺序纯同步完成求值预热,保持对运行期动态新增/替换模块的感知 | 纯同步客户端 App、复杂全量初始化的工具库 |
|
|
82
|
+
| **`demand` + `async`** | 外部按需触达触发 (`container.UserPage`) | 触达点顺藤摸瓜提取子图,严格单点熔断防护,彻底杜绝幽灵 Bug | 大型 SPA 单页应用路由按需懒加载、冷启动极致优化 |
|
|
83
|
+
| **`demand` + `turbo`** | 外部按需触达触发 (`container.foo`) | 无需 `await` 属性访问,自动算子图纯同步求值,支持依赖感知与无锁解环 | 极速 CLI 命令行工具、纯同步高性能管线、单测隔离 |
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 核心机制:正向极简子图按需切片提取 (Subgraph Slice Extraction)
|
|
88
|
+
|
|
89
|
+
在 `demand` 按需模式下,当调用方首次访问 `container.UserPage` 时,容器不会拉起全量模块,而是调用 `extractSubModules(graph, 'UserPage')`:
|
|
90
|
+
|
|
91
|
+
1. **顺藤摸瓜**:从触达点 `UserPage` 出发,基于静态图中的 `resolvedDepsMap` 深度优先递归检索其所有正向依赖;
|
|
92
|
+
2. **纯粹确定**:严格仅收集 `UserPage` 及其下游直属与间接依赖模块,排除无关模块,保证 100% 确定性;
|
|
93
|
+
3. **极简编译**:将抽取的极简模块子集重新编译为局部子图,即刻完成装配。
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
访问 container.UserPage
|
|
97
|
+
│
|
|
98
|
+
▼
|
|
99
|
+
[ 触达点识别 ] ───► extractSubModules(graph, "UserPage")
|
|
100
|
+
│
|
|
101
|
+
├── 1. 递归提取 UserPage 正向依赖 (UserService, UserApi...)
|
|
102
|
+
└── 2. 编译极简局部子图并即刻装配
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## API 参考 (API Reference)
|
|
108
|
+
|
|
109
|
+
### `createContainer(graph, options)`
|
|
110
|
+
|
|
111
|
+
创建高阶代理容器。
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
export interface CreateContainerOptions {
|
|
115
|
+
/**
|
|
116
|
+
* 加载策略:
|
|
117
|
+
* - "eager": 全量预热 (容器创建时立刻初始化全量模块)
|
|
118
|
+
* - "demand": 极速按需 (基于 container.prop 属性访问按需切片拉起)
|
|
119
|
+
*/
|
|
120
|
+
strategy: "eager" | "demand";
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* 执行引擎:
|
|
124
|
+
* - "async": 反应式异步拓扑并发引擎
|
|
125
|
+
* - "turbo": 纯同步直通零 Promise 引擎
|
|
126
|
+
*/
|
|
127
|
+
mode: "async" | "turbo";
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export const createContainer: (
|
|
131
|
+
graph: CompiledModuleGraph,
|
|
132
|
+
options: CreateContainerOptions
|
|
133
|
+
) => Record<string, unknown>;
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
### `extractSubModules(graph, ...entryPoints)`
|
|
139
|
+
|
|
140
|
+
底层正向子图切片提取器工具函数。
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
export const extractSubModules: (
|
|
144
|
+
graph: CompiledModuleGraph,
|
|
145
|
+
...entryPoints: string[]
|
|
146
|
+
) => { key: string; module: IOCModule }[];
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 许可证 (License)
|
|
152
|
+
|
|
153
|
+
Released under the [MIT License](./LICENSE).
|
|
154
|
+
Copyright © 2026 [Path-IoC Organization](https://github.com/path-ioc) & Lian HanLin.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@path-ioc/container",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "High-level Container extensions, demand proxy and turbo mode for Path-IoC",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ioc",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"access": "public"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"@path-ioc/core": "0.1.
|
|
41
|
+
"@path-ioc/core": "0.1.3"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"tsup": "^8.0.0",
|