evaengine 0.11.2 → 1.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/.ai/analysis.md +657 -0
- package/.ai/architecture/runtime.md +504 -0
- package/.ai/contracts/public-api.md +447 -0
- package/.ai/external-project-guide.md +248 -0
- package/.ai/vision.md +314 -0
- package/README.md +51 -62
- package/bin/engine +15 -21
- package/index.js +2 -18
- package/package.json +60 -64
- package/src/commands/index.js +12 -0
- package/{lib → src}/commands/interface.js +5 -11
- package/src/commands/make_entity.js +490 -0
- package/src/commands/tramp.js +34 -0
- package/{lib → src}/config/index.js +7 -9
- package/{lib → src}/di.js +11 -26
- package/src/engine.js +551 -0
- package/{lib → src}/entities/index.js +72 -82
- package/{lib → src}/exceptions/index.js +71 -92
- package/src/index.js +57 -0
- package/src/middlewares/auth.js +67 -0
- package/src/middlewares/auth_kong.js +28 -0
- package/src/middlewares/debug.js +88 -0
- package/src/middlewares/index.js +18 -0
- package/src/middlewares/providers.js +73 -0
- package/src/middlewares/session.js +58 -0
- package/{lib → src}/middlewares/trace.js +74 -86
- package/src/middlewares/validator.js +50 -0
- package/src/middlewares/view_cache.js +127 -0
- package/{lib → src}/services/cache.js +45 -56
- package/src/services/config.js +111 -0
- package/src/services/env.js +28 -0
- package/src/services/event_manager.js +84 -0
- package/src/services/http_client.js +160 -0
- package/src/services/index.js +27 -0
- package/src/services/interface.js +5 -0
- package/src/services/joi.js +13 -0
- package/src/services/jwt_token.js +89 -0
- package/src/services/jwt_token_kong.js +75 -0
- package/src/services/logger.js +148 -0
- package/src/services/namespace.js +176 -0
- package/src/services/now.js +49 -0
- package/src/services/providers.js +158 -0
- package/src/services/redis.js +55 -0
- package/src/services/rest_client.js +112 -0
- package/src/swagger/index.js +668 -0
- package/{lib → src}/utils/api_scaffold.js +26 -39
- package/src/utils/case_converter.js +33 -0
- package/src/utils/crc32.js +44 -0
- package/src/utils/datetime.js +13 -0
- package/src/utils/host.js +39 -0
- package/src/utils/index.js +35 -0
- package/{lib → src}/utils/pagination.js +22 -31
- package/src/utils/random.js +23 -0
- package/{lib → src}/utils/smart_query.js +27 -27
- package/src/utils/test.js +48 -0
- package/src/utils/wrapper.js +8 -0
- package/bin/engine-babel +0 -38
- package/lib/commands/index.js +0 -25
- package/lib/commands/index.js.map +0 -1
- package/lib/commands/interface.js.map +0 -1
- package/lib/commands/make_entity.js +0 -549
- package/lib/commands/make_entity.js.map +0 -1
- package/lib/commands/tramp.js +0 -53
- package/lib/commands/tramp.js.map +0 -1
- package/lib/config/index.js.map +0 -1
- package/lib/di.js.map +0 -1
- package/lib/engine.js +0 -558
- package/lib/engine.js.map +0 -1
- package/lib/entities/index.js.map +0 -1
- package/lib/exceptions/index.js.map +0 -1
- package/lib/index.js +0 -105
- package/lib/index.js.map +0 -1
- package/lib/middlewares/auth.js +0 -97
- package/lib/middlewares/auth.js.map +0 -1
- package/lib/middlewares/auth_kong.js +0 -48
- package/lib/middlewares/auth_kong.js.map +0 -1
- package/lib/middlewares/debug.js +0 -68
- package/lib/middlewares/debug.js.map +0 -1
- package/lib/middlewares/index.js +0 -45
- package/lib/middlewares/index.js.map +0 -1
- package/lib/middlewares/providers.js +0 -102
- package/lib/middlewares/providers.js.map +0 -1
- package/lib/middlewares/session.js +0 -76
- package/lib/middlewares/session.js.map +0 -1
- package/lib/middlewares/trace.js.map +0 -1
- package/lib/middlewares/validator.js +0 -71
- package/lib/middlewares/validator.js.map +0 -1
- package/lib/middlewares/view_cache.js +0 -160
- package/lib/middlewares/view_cache.js.map +0 -1
- package/lib/services/cache.js.map +0 -1
- package/lib/services/config.js +0 -140
- package/lib/services/config.js.map +0 -1
- package/lib/services/env.js +0 -40
- package/lib/services/env.js.map +0 -1
- package/lib/services/event_manager.js +0 -110
- package/lib/services/event_manager.js.map +0 -1
- package/lib/services/http_client.js +0 -178
- package/lib/services/http_client.js.map +0 -1
- package/lib/services/index.js +0 -70
- package/lib/services/index.js.map +0 -1
- package/lib/services/interface.js +0 -12
- package/lib/services/interface.js.map +0 -1
- package/lib/services/joi.js +0 -28
- package/lib/services/joi.js.map +0 -1
- package/lib/services/jwt_token.js +0 -120
- package/lib/services/jwt_token.js.map +0 -1
- package/lib/services/jwt_token_kong.js +0 -111
- package/lib/services/jwt_token_kong.js.map +0 -1
- package/lib/services/logger.js +0 -172
- package/lib/services/logger.js.map +0 -1
- package/lib/services/namespace.js +0 -188
- package/lib/services/namespace.js.map +0 -1
- package/lib/services/now.js +0 -69
- package/lib/services/now.js.map +0 -1
- package/lib/services/providers.js +0 -195
- package/lib/services/providers.js.map +0 -1
- package/lib/services/redis.js +0 -77
- package/lib/services/redis.js.map +0 -1
- package/lib/services/rest_client.js +0 -136
- package/lib/services/rest_client.js.map +0 -1
- package/lib/swagger/index.js +0 -684
- package/lib/swagger/index.js.map +0 -1
- package/lib/utils/api_scaffold.js.map +0 -1
- package/lib/utils/case_converter.js +0 -48
- package/lib/utils/case_converter.js.map +0 -1
- package/lib/utils/crc32.js +0 -22
- package/lib/utils/crc32.js.map +0 -1
- package/lib/utils/datetime.js +0 -21
- package/lib/utils/datetime.js.map +0 -1
- package/lib/utils/host.js +0 -48
- package/lib/utils/host.js.map +0 -1
- package/lib/utils/index.js +0 -61
- package/lib/utils/index.js.map +0 -1
- package/lib/utils/pagination.js.map +0 -1
- package/lib/utils/random.js +0 -33
- package/lib/utils/random.js.map +0 -1
- package/lib/utils/smart_query.js.map +0 -1
- package/lib/utils/test.js +0 -62
- package/lib/utils/test.js.map +0 -1
- package/lib/utils/wrapper.js +0 -9
- package/lib/utils/wrapper.js.map +0 -1
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
# EvaEngine Public API Contract
|
|
2
|
+
|
|
3
|
+
**文档类型**: Open Source API Contract
|
|
4
|
+
**目标读者**: AI Coding Agent / EvaEngine Maintainer
|
|
5
|
+
**版本依据**: 当前工作树与 `package.json` 版本 `0.11.2`
|
|
6
|
+
|
|
7
|
+
## 1. Contract Classification
|
|
8
|
+
|
|
9
|
+
本文件使用三个层级:
|
|
10
|
+
|
|
11
|
+
### Public API
|
|
12
|
+
|
|
13
|
+
满足至少一个条件:
|
|
14
|
+
|
|
15
|
+
- 从 package 主入口导出。
|
|
16
|
+
- 在 README、docs 或项目使用示例中直接使用。
|
|
17
|
+
- 被测试作为外部行为调用。
|
|
18
|
+
- 明确承担应用接入或扩展职责。
|
|
19
|
+
|
|
20
|
+
### Stable Internal API
|
|
21
|
+
|
|
22
|
+
不是主要用户入口,但被多个 Runtime 组件、Provider 或测试依赖,修改时可能影响应用内部扩展。它应保持相对稳定,但当前没有独立版本化保证。
|
|
23
|
+
|
|
24
|
+
### Private Implementation
|
|
25
|
+
|
|
26
|
+
只用于实现内部行为,未被主入口或公开文档承诺。可以重构,除非改动间接改变 Public API 行为。
|
|
27
|
+
|
|
28
|
+
> 本项目没有完整的正式 API stability policy。除下文明确标记外,长期兼容承诺为 `UNKNOWN`。
|
|
29
|
+
|
|
30
|
+
## 2. Public API
|
|
31
|
+
|
|
32
|
+
## 2.1 Package Entry
|
|
33
|
+
|
|
34
|
+
入口:`package.json.main` 指向 `src/index.js`,根入口 `index.js` re-export 它。
|
|
35
|
+
|
|
36
|
+
### Default package export / named package exports
|
|
37
|
+
|
|
38
|
+
**Purpose**
|
|
39
|
+
|
|
40
|
+
提供 EvaEngine 的主要接入面,包括 Runtime、Command、DI、Entity、服务、middleware、异常、Provider 和基础依赖。
|
|
41
|
+
|
|
42
|
+
**When to use**
|
|
43
|
+
|
|
44
|
+
应用初始化、创建 Runtime、定义 Command、注册 Provider、访问公开异常或使用框架提供的服务时使用 package 入口。
|
|
45
|
+
|
|
46
|
+
**Constraints**
|
|
47
|
+
|
|
48
|
+
- 当前 package 要求 Node `>=24.0.0`。
|
|
49
|
+
- 当前 package 使用 ESM,调用方必须遵守 Node ESM 模块解析规则。
|
|
50
|
+
- package 入口同时暴露若干第三方依赖对象;这些对象是否属于长期稳定 contract,`UNKNOWN`。
|
|
51
|
+
- 具体导出集合由 `src/index.js` 的 `core` 对象决定。
|
|
52
|
+
|
|
53
|
+
**Compatibility expectation**
|
|
54
|
+
|
|
55
|
+
`EvaEngine`、`Command`、`DI`、`Entities` 和主要集合导出属于高置信度 Public API。第三方依赖转发、`dependencies` 对象以及完整导出对象的字段级长期稳定性为 `UNKNOWN`。
|
|
56
|
+
|
|
57
|
+
## 2.2 EvaEngine
|
|
58
|
+
|
|
59
|
+
**Purpose**
|
|
60
|
+
|
|
61
|
+
提供统一的应用 Runtime,组织 Web、CLI、Cron 等入口的配置、Provider、DI、Middleware、Command 和资源状态。
|
|
62
|
+
|
|
63
|
+
**When to use**
|
|
64
|
+
|
|
65
|
+
应用需要启动 Runtime、注册 Command、配置运行模式、启动 HTTP/HTTPS、执行 CLI 或注册 Cron 时使用。
|
|
66
|
+
|
|
67
|
+
**Constraints**
|
|
68
|
+
|
|
69
|
+
- 构造参数需要提供项目相关 metadata;完整必需字段集合应以 `getMeta()` 和当前 Engine 构造逻辑为准。
|
|
70
|
+
- `mode` 影响 Provider 集合和入口行为。
|
|
71
|
+
- Engine 依赖全局 DI 和部分模块级 Runtime 状态,多个 Engine 并存时的隔离保证为 `UNKNOWN`。
|
|
72
|
+
- `run()`、`runHttps()` 和 Cron 会创建外部资源;调用方必须负责或触发关闭流程。
|
|
73
|
+
- HTTP 行为依赖当前 Express 版本和 middleware 顺序。
|
|
74
|
+
|
|
75
|
+
**Compatibility expectation**
|
|
76
|
+
|
|
77
|
+
构造 Engine、读取 metadata、bootstrap、注册 Command、运行 CLI 是高置信度 Public API。HTTP/HTTPS server 的完整关闭语义、重复 bootstrap 行为和多实例隔离为 `UNKNOWN`。
|
|
78
|
+
|
|
79
|
+
相关公开行为:
|
|
80
|
+
|
|
81
|
+
- `new EvaEngine(meta, mode)`
|
|
82
|
+
- `getMeta()`
|
|
83
|
+
- `getDI()`
|
|
84
|
+
- `bootstrap()`
|
|
85
|
+
- `registerCommands()`
|
|
86
|
+
- `getCommands()`
|
|
87
|
+
- `clearCommands()`
|
|
88
|
+
- `run()`
|
|
89
|
+
- `runHttps()`
|
|
90
|
+
- `runCLI()`
|
|
91
|
+
- `runCommand()`
|
|
92
|
+
- `runCrontab()`
|
|
93
|
+
- `clearCrontabs()`
|
|
94
|
+
- `setDefaultErrorHandler()`
|
|
95
|
+
- `getDefaultErrorHandler()`
|
|
96
|
+
- `getServer()`
|
|
97
|
+
- `getVersion()`
|
|
98
|
+
|
|
99
|
+
## 2.3 Command
|
|
100
|
+
|
|
101
|
+
**Purpose**
|
|
102
|
+
|
|
103
|
+
为 CLI、Cron 以及未来非 HTTP 入口提供统一的应用操作适配器。
|
|
104
|
+
|
|
105
|
+
**When to use**
|
|
106
|
+
|
|
107
|
+
需要将一个可命名、可解析参数、可被 Engine 调度的应用操作暴露给 CLI 或 Cron 时,继承 `Command`。
|
|
108
|
+
|
|
109
|
+
**Constraints**
|
|
110
|
+
|
|
111
|
+
Command 应提供静态 metadata:
|
|
112
|
+
|
|
113
|
+
- `getName()`
|
|
114
|
+
- `getDescription()`
|
|
115
|
+
- `getSpec()`
|
|
116
|
+
|
|
117
|
+
Command 的执行入口是 `run()`。Command 不应依赖 HTTP request/response,也不应把大量领域逻辑放入 Command 本身。
|
|
118
|
+
|
|
119
|
+
`argv` 的具体来源和 yargs 版本行为属于 Runtime 约束;复杂参数类型的兼容性为 `UNKNOWN`。
|
|
120
|
+
|
|
121
|
+
**Compatibility expectation**
|
|
122
|
+
|
|
123
|
+
继承 `Command` 并实现上述静态 metadata 是高置信度 Public API。`getArgv()`、`setArgv()`、`getOptions()` 是已实现并被测试/Command 使用的 API,但其长期稳定级别为 `Stable Internal API`,除非后续文档正式承诺。
|
|
124
|
+
|
|
125
|
+
## 2.4 DI
|
|
126
|
+
|
|
127
|
+
**Purpose**
|
|
128
|
+
|
|
129
|
+
提供运行时依赖绑定、解析、替换和测试注册能力。
|
|
130
|
+
|
|
131
|
+
**When to use**
|
|
132
|
+
|
|
133
|
+
Provider 需要绑定 capability,应用测试需要替换 service,或应用需要解析已注册服务时使用。
|
|
134
|
+
|
|
135
|
+
**Constraints**
|
|
136
|
+
|
|
137
|
+
公开操作包括:
|
|
138
|
+
|
|
139
|
+
- `DI.get(key)`
|
|
140
|
+
- `DI.bindClass(name, Class)`
|
|
141
|
+
- `DI.bindValue(name, value)`
|
|
142
|
+
- `DI.bindMethod(name, method)`
|
|
143
|
+
- `DI.reset()`
|
|
144
|
+
- `DI.registerServiceProviders(providers, engine)`
|
|
145
|
+
- `DI.registerMockedProviders(providers, configPath)`
|
|
146
|
+
|
|
147
|
+
DI key 既可以是字符串也可以是 class/reference,但两者的完整优先级和生命周期行为未由独立文档定义,部分细节为 `UNKNOWN`。
|
|
148
|
+
|
|
149
|
+
DI 不是类型安全容器。字符串名称拼写错误、注册顺序错误和循环依赖会在运行时暴露。
|
|
150
|
+
|
|
151
|
+
**Compatibility expectation**
|
|
152
|
+
|
|
153
|
+
Provider 和测试代码直接依赖这些方法,因此它们属于高置信度 Public/Extension API。底层 `constitute.Container`、`bound` map 的结构以及实例缓存策略属于 Private Implementation。
|
|
154
|
+
|
|
155
|
+
## 2.5 ServiceProvider
|
|
156
|
+
|
|
157
|
+
**Purpose**
|
|
158
|
+
|
|
159
|
+
定义 Runtime capability 的装配扩展点。
|
|
160
|
+
|
|
161
|
+
**When to use**
|
|
162
|
+
|
|
163
|
+
需要新增服务、替换服务、根据配置绑定不同实现,或将能力纳入 Runtime bootstrap 时,继承 `ServiceProvider`。
|
|
164
|
+
|
|
165
|
+
**Constraints**
|
|
166
|
+
|
|
167
|
+
Provider 至少应提供:
|
|
168
|
+
|
|
169
|
+
- `name`
|
|
170
|
+
- `register()`
|
|
171
|
+
- 构造时接收 Runtime/Engine context
|
|
172
|
+
|
|
173
|
+
当前 Provider 生命周期主要只有 `register()`;`boot/start/stop/shutdown` 是否可用为 `UNKNOWN`,不应假设已经存在。
|
|
174
|
+
|
|
175
|
+
Provider 不应承载业务领域逻辑,也不应隐式创建无法关闭的后台资源。
|
|
176
|
+
|
|
177
|
+
**Compatibility expectation**
|
|
178
|
+
|
|
179
|
+
`ServiceProvider`、`name` 和 `register()` 是高置信度扩展契约。Provider 注册顺序是 Stable Internal API,当前没有独立的排序保证;依赖其他 Provider 的新增 Provider 必须明确依赖前置条件。
|
|
180
|
+
|
|
181
|
+
## 2.6 Entity Registry
|
|
182
|
+
|
|
183
|
+
入口:`Entities`。
|
|
184
|
+
|
|
185
|
+
**Purpose**
|
|
186
|
+
|
|
187
|
+
扫描 Entity factory、构造 Sequelize model、维护 entity registry、处理关联,并为查询、事务和 metadata generation 提供入口。
|
|
188
|
+
|
|
189
|
+
**When to use**
|
|
190
|
+
|
|
191
|
+
应用使用 EvaEngine 的 Entity/Sequelize 集成,需要加载 Entity 目录或访问已扫描模型时使用。
|
|
192
|
+
|
|
193
|
+
**Constraints**
|
|
194
|
+
|
|
195
|
+
公开行为包括:
|
|
196
|
+
|
|
197
|
+
- `new Entities(entitiesPath, sequelizeInstance?)`
|
|
198
|
+
- `scan(path, withAssociate?)`
|
|
199
|
+
- `init(withAssociate?)`
|
|
200
|
+
- `getAll()`
|
|
201
|
+
- `getInstance()`
|
|
202
|
+
- `getSequelize()`
|
|
203
|
+
- `query()`
|
|
204
|
+
- `uniqueInsert()`
|
|
205
|
+
- `getTransaction()`
|
|
206
|
+
|
|
207
|
+
Entity 当前与 Sequelize model/persistence 强耦合。Entity file factory 的参数形式、扫描文件约定和 association 行为是已使用的 contract,但长期兼容级别为 `UNKNOWN`。
|
|
208
|
+
|
|
209
|
+
`uniqueInsert()` 的生成 SQL 依赖 Sequelize dialect/query generator,调用方不应把 SQL 细节视为跨数据库稳定行为。
|
|
210
|
+
|
|
211
|
+
**Compatibility expectation**
|
|
212
|
+
|
|
213
|
+
Entity registry 的基本扫描和访问行为是 Public API;具体 Sequelize model 字段、ORM 内部 metadata 和 SQL 生成格式属于 Stable Internal API 或 Private Implementation,不能作为通用稳定 contract。
|
|
214
|
+
|
|
215
|
+
## 2.7 Middleware Provider API
|
|
216
|
+
|
|
217
|
+
包括 Session、Auth、Auth Kong、Debug、Trace、View Cache 和 Validator provider。
|
|
218
|
+
|
|
219
|
+
**Purpose**
|
|
220
|
+
|
|
221
|
+
将 HTTP 横切能力绑定为 Runtime 可解析的 middleware capability。
|
|
222
|
+
|
|
223
|
+
**When to use**
|
|
224
|
+
|
|
225
|
+
应用需要启用、替换或扩展认证、Session、校验、追踪、缓存和调试行为时使用 Provider。
|
|
226
|
+
|
|
227
|
+
**Constraints**
|
|
228
|
+
|
|
229
|
+
Middleware 最终必须符合 Express middleware 形态:
|
|
230
|
+
|
|
231
|
+
```text
|
|
232
|
+
(request, response, next) -> result or next(error)
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Middleware 顺序是重要约束,但当前完整顺序保证为 `UNKNOWN`。Auth、Session、Trace 和 Cache 可能依赖 request/response 已存在的字段或 header。
|
|
236
|
+
|
|
237
|
+
**Compatibility expectation**
|
|
238
|
+
|
|
239
|
+
Provider name 和 middleware factory 形态是高置信度 Public/Extension API。具体 middleware 内部使用的 Express、Redis、JWT 或 request 字段属于 Stable Internal API;未在文档和测试中确认的 header/错误细节为 `UNKNOWN`。
|
|
240
|
+
|
|
241
|
+
## 2.8 Service Capabilities
|
|
242
|
+
|
|
243
|
+
以下 service 从 package service 集合导出,且在 Provider、测试或应用流程中被直接使用。它们属于 Public API 候选,但每个方法的长期语义并未全部正式文档化。
|
|
244
|
+
|
|
245
|
+
### Config
|
|
246
|
+
|
|
247
|
+
**Purpose**: 加载、合并和查询 Runtime 配置。
|
|
248
|
+
|
|
249
|
+
**When to use**: Provider 或应用需要读取配置时使用,不应直接读取环境变量或配置文件。
|
|
250
|
+
|
|
251
|
+
**Constraints**: `setPath()` 应在读取配置前设置;`get()` 会触发加载;`reload()` 重新加载。配置文件格式和 Spring Cloud response 细节为 `UNKNOWN`。
|
|
252
|
+
|
|
253
|
+
**Compatibility expectation**: `setPath/get/reload/getMergedFiles/resolveSpringConfig` 为 Stable Internal API;配置对象字段是否稳定取决于应用配置 contract,不能由 EvaEngine 统一保证。
|
|
254
|
+
|
|
255
|
+
### Logger
|
|
256
|
+
|
|
257
|
+
**Purpose**: 提供统一日志和调试输出。
|
|
258
|
+
|
|
259
|
+
**When to use**: Runtime、Provider、Middleware 和应用服务需要记录结构化或分级日志时使用。
|
|
260
|
+
|
|
261
|
+
**Constraints**: `debug/verbose/info/warn/error/dump` 是主要使用方法;具体 Winston logger instance、transport 和格式不应被业务代码依赖。
|
|
262
|
+
|
|
263
|
+
**Compatibility expectation**: 日志级别方法为 Stable Internal API。日志输出格式、transport 对象和 Winston 兼容性为 `UNKNOWN`。
|
|
264
|
+
|
|
265
|
+
### Redis
|
|
266
|
+
|
|
267
|
+
**Purpose**: 提供 Redis client capability 和连接生命周期管理。
|
|
268
|
+
|
|
269
|
+
**When to use**: Cache、JWT 或应用需要 Redis 操作时,通过 service 使用。
|
|
270
|
+
|
|
271
|
+
**Constraints**: 主要行为包括 `setOptions/getInstance/isConnected/cleanup`。当前底层实现依赖 ioredis 和 Redis 7 可用性;Redis command 细节不是 EvaEngine 自己定义的 contract。
|
|
272
|
+
|
|
273
|
+
**Compatibility expectation**: service lifecycle 方法为 Stable Internal API;返回的具体 ioredis instance API 为 `UNKNOWN`,除非调用方明确接受 ioredis coupling。
|
|
274
|
+
|
|
275
|
+
### Cache
|
|
276
|
+
|
|
277
|
+
**Purpose**: 提供 key/value、namespace、flush 和 Redis/Null store 抽象。
|
|
278
|
+
|
|
279
|
+
**When to use**: 应用需要缓存但不希望直接依赖 Redis 时使用。
|
|
280
|
+
|
|
281
|
+
**Constraints**: 主要操作包括 `get/set/del/has/flush/namespace`。TTL、NX/XX mutex 参数和序列化行为应以当前测试及实现为准;跨 store 的全部语义为 `UNKNOWN`。
|
|
282
|
+
|
|
283
|
+
**Compatibility expectation**: 基本 Cache capability 是 Stable Internal API;`Store`、`RedisStore`、`RedisNamespaceStore` 的具体类和 Redis key layout 属于 Private/Stable Internal API,不是无条件 Public Contract。
|
|
284
|
+
|
|
285
|
+
### HTTP Client / Rest Client
|
|
286
|
+
|
|
287
|
+
**Purpose**: 统一外部 HTTP 调用、错误映射、trace 传播和请求/响应诊断。
|
|
288
|
+
|
|
289
|
+
**When to use**: 应用服务访问外部 HTTP API 时使用,而不是直接在业务代码中创建 request client。
|
|
290
|
+
|
|
291
|
+
**Constraints**: `request()`、错误分类和 tracer integration 是主要行为。底层 request/request-promise-native 已停止维护,其内部 prototype 行为不应成为调用方 contract。
|
|
292
|
+
|
|
293
|
+
**Compatibility expectation**: HTTP client 的基本 request 行为为 Stable Internal API;具体请求对象字段、debug patch、错误对象原型和 TLS 行为为 `UNKNOWN`。
|
|
294
|
+
|
|
295
|
+
### JsonWebToken
|
|
296
|
+
|
|
297
|
+
**Purpose**: 提供 token encode/decode 及 token 保存、查找、清理能力。
|
|
298
|
+
|
|
299
|
+
**When to use**: Auth middleware 或应用需要 local token persistence 时使用。
|
|
300
|
+
|
|
301
|
+
**Constraints**: 主要操作包括 `save/find/clear/encode/decode`。token payload、过期字段、Redis key layout 和 secret 配置必须遵守当前应用配置;不同 provider 实现之间的完整语义一致性为 `UNKNOWN`。
|
|
302
|
+
|
|
303
|
+
**Compatibility expectation**: 基本 token service 方法为 Stable Internal API;payload schema 和 Kong provider 的远程 API 兼容性为 `UNKNOWN`。
|
|
304
|
+
|
|
305
|
+
### EventManager
|
|
306
|
+
|
|
307
|
+
**Purpose**: 提供进程内事件发布和 listener 注册。
|
|
308
|
+
|
|
309
|
+
**When to use**: 同一 Runtime 进程内需要解耦生产者和消费者时使用。
|
|
310
|
+
|
|
311
|
+
**Constraints**: 当前是进程内机制,不保证持久化、跨进程传递、重试、顺序或 dead-letter。
|
|
312
|
+
|
|
313
|
+
**Compatibility expectation**: `addListener/emit/getAllowEvents/getEmitter` 是 Stable Internal API;EventEmitter 实例直接暴露的全部 Node 行为为 `UNKNOWN`。
|
|
314
|
+
|
|
315
|
+
### Now
|
|
316
|
+
|
|
317
|
+
**Purpose**: 统一当前时间和可测试的时间替换。
|
|
318
|
+
|
|
319
|
+
**When to use**: 业务或 service 需要统一读取时间、时间戳或数据库时间格式时使用。
|
|
320
|
+
|
|
321
|
+
**Constraints**: `setNow/clear/getTimestamp/getMoment/getDatabaseDatetime` 的语义由当前实现定义;时区和 Moment formatting 属于配置/依赖行为。
|
|
322
|
+
|
|
323
|
+
**Compatibility expectation**: 时间读取方法为 Stable Internal API;具体 Moment instance 和格式跨版本稳定性为 `UNKNOWN`。
|
|
324
|
+
|
|
325
|
+
## 3. Stable Internal API
|
|
326
|
+
|
|
327
|
+
以下接口被多个内部模块或测试使用,但没有足够证据证明它们是面向所有 package consumers 的长期 Public Contract。
|
|
328
|
+
|
|
329
|
+
### 3.1 `ServiceInterface`
|
|
330
|
+
|
|
331
|
+
**Purpose**: 为 service 提供共同基类和 `getProto()` 约定。
|
|
332
|
+
|
|
333
|
+
**When to use**: 主要用于实现 EvaEngine service,而不是普通应用业务类。
|
|
334
|
+
|
|
335
|
+
**Constraints**: 该接口很薄,实际 service contract 仍由具体 service 定义。
|
|
336
|
+
|
|
337
|
+
**Compatibility expectation**: Stable Internal API。是否支持外部自定义 ServiceInterface implementation 为 `UNKNOWN`。
|
|
338
|
+
|
|
339
|
+
### 3.2 Service Provider 集合
|
|
340
|
+
|
|
341
|
+
`services/providers.js` 和 `middlewares/providers.js` 中的具体 Provider 类被 Runtime 使用并从 package 集合导出。
|
|
342
|
+
|
|
343
|
+
**Purpose**: 提供默认 Runtime 装配方案。
|
|
344
|
+
|
|
345
|
+
**When to use**: 需要复用默认能力绑定或基于现有 Provider 扩展时使用。
|
|
346
|
+
|
|
347
|
+
**Constraints**: Provider 顺序、名称、是否默认注册和不同 mode 下的集合属于 Runtime 组合规则。
|
|
348
|
+
|
|
349
|
+
**Compatibility expectation**: Provider base contract 稳定;具体 Provider 类名和默认集合的长期兼容性为 `UNKNOWN`。
|
|
350
|
+
|
|
351
|
+
### 3.3 Cache Store Classes
|
|
352
|
+
|
|
353
|
+
包括 `Store`、`NullStore`、`RedisStore`、`RedisNamespaceStore`。
|
|
354
|
+
|
|
355
|
+
**Purpose**: 作为 Cache 的内部 store strategy。
|
|
356
|
+
|
|
357
|
+
**When to use**: 仅在需要实现同一 Cache store strategy 时考虑。
|
|
358
|
+
|
|
359
|
+
**Constraints**: 这些类型暴露 Redis-specific behavior,不能被视为跨实现的通用 cache contract。
|
|
360
|
+
|
|
361
|
+
**Compatibility expectation**: Stable Internal API。具体类、构造参数、key layout 和 return values 的长期兼容性为 `UNKNOWN`。
|
|
362
|
+
|
|
363
|
+
### 3.4 Engine Provider Lists and Runtime State
|
|
364
|
+
|
|
365
|
+
包括默认 service provider 列表、web/CLI provider 列表、command registry、server state 和 Cron handler state。
|
|
366
|
+
|
|
367
|
+
**Purpose**: 组成当前 Runtime。
|
|
368
|
+
|
|
369
|
+
**When to use**: 不应由应用直接修改;扩展应通过 Provider、Command 或明确 Engine API 完成。
|
|
370
|
+
|
|
371
|
+
**Constraints**: 修改顺序可能改变依赖图和请求行为。
|
|
372
|
+
|
|
373
|
+
**Compatibility expectation**: Stable Internal API。字段结构、数组顺序和 registry 存储方式为 `UNKNOWN`。
|
|
374
|
+
|
|
375
|
+
## 4. Private Implementation
|
|
376
|
+
|
|
377
|
+
以下内容没有证据显示是外部 API,应视为 Private Implementation:
|
|
378
|
+
|
|
379
|
+
- `constitute.Container` 的具体使用。
|
|
380
|
+
- DI 内部 `bound` map 的数据结构。
|
|
381
|
+
- `Config` 的文件合并方式、动态加载方式和缓存字段。
|
|
382
|
+
- Redis client 的内部缓存字段和连接事件处理。
|
|
383
|
+
- Cache key layout、内部 Store 选择和序列化细节。
|
|
384
|
+
- Engine 的内部 server、app、command registry 和 Cron handler 存储。
|
|
385
|
+
- Middleware 内部包装、trace 实现和 response monkey patch。
|
|
386
|
+
- Entity scanner 的文件过滤、Sequelize model 加载细节和 SQL 生成过程。
|
|
387
|
+
- Swagger 使用的 Glob、Acorn、Doctrine、YAML parser pipeline。
|
|
388
|
+
- HTTP client 对 request 内部 prototype 的 debug patch。
|
|
389
|
+
- `src/config/index.js` 中的默认配置对象字段,除非应用文档另行承诺。
|
|
390
|
+
- `test/`、`coverage/`、生成文件和测试 fixture。
|
|
391
|
+
- 已删除的 Babel 配置、旧构建产物和内部迁移兼容代码。
|
|
392
|
+
|
|
393
|
+
修改这些内容时,维护者仍必须验证 Public API 的行为,但不需要保持内部实现形状。
|
|
394
|
+
|
|
395
|
+
## 5. Compatibility Policy
|
|
396
|
+
|
|
397
|
+
### Confirmed
|
|
398
|
+
|
|
399
|
+
以下兼容性由当前 package、README、测试或实际入口使用明确支持:
|
|
400
|
+
|
|
401
|
+
- Node.js `>=24.0.0`。
|
|
402
|
+
- ESM package entry。
|
|
403
|
+
- `EvaEngine`、`Command`、`DI`、`Entities` 的基本接入方式。
|
|
404
|
+
- Provider 的 `name/register` 扩展方式。
|
|
405
|
+
- Command 的 name/description/spec/run 约定。
|
|
406
|
+
- 当前测试所覆盖的服务、middleware 和 Entity 基本行为。
|
|
407
|
+
|
|
408
|
+
### Not Confirmed
|
|
409
|
+
|
|
410
|
+
以下内容不能从当前代码推断稳定承诺,必须标记为 `UNKNOWN`:
|
|
411
|
+
|
|
412
|
+
- 未导出的类或方法是否可被应用直接使用。
|
|
413
|
+
- 所有 service 方法的跨版本返回值和错误类型。
|
|
414
|
+
- 多个 Engine 同时运行时的隔离。
|
|
415
|
+
- Server/Redis/HTTP client 的完整 graceful shutdown 保证。
|
|
416
|
+
- Sequelize model 与底层 ORM metadata 的长期兼容性。
|
|
417
|
+
- 事件的可靠交付语义。
|
|
418
|
+
- Swagger、metadata 和扫描器的输入格式扩展性。
|
|
419
|
+
- 直接访问第三方依赖对象的兼容性。
|
|
420
|
+
|
|
421
|
+
## 6. Maintainer Rules
|
|
422
|
+
|
|
423
|
+
作为开源库维护者,新增或修改 API 时应:
|
|
424
|
+
|
|
425
|
+
1. 先确认 API 是否从 package entry 导出或被文档公开使用。
|
|
426
|
+
2. 若是 Public API,增加 contract test,而不只增加内部单元测试。
|
|
427
|
+
3. 明确 Purpose、When to use、Constraints 和 Compatibility expectation。
|
|
428
|
+
4. 对无法从代码或测试确认的内容标记 `UNKNOWN`。
|
|
429
|
+
5. 不把第三方库的类型、内部字段或错误对象自动升级为 EvaEngine contract。
|
|
430
|
+
6. 不因内部重构改变 Command、Provider、DI 和核心 service 的已验证行为。
|
|
431
|
+
7. 若需要破坏 Public API,更新版本策略和迁移说明。
|
|
432
|
+
8. 保持 Runtime、Provider、DI、Command 和 capability contract 之间的边界可解释。
|
|
433
|
+
|
|
434
|
+
## 7. Summary
|
|
435
|
+
|
|
436
|
+
EvaEngine 的真正公共 API 不是所有导出的类和方法,而是应用接入时依赖的几组行为契约:
|
|
437
|
+
|
|
438
|
+
```text
|
|
439
|
+
Runtime construction and execution
|
|
440
|
+
Provider-based capability extension
|
|
441
|
+
DI binding and resolution
|
|
442
|
+
Command entry contract
|
|
443
|
+
Entity registry integration
|
|
444
|
+
Selected service capabilities
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
其余代码应默认视为可演进的内部实现,除非文档、示例或测试明确证明它已经成为用户依赖的 contract。
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# EvaEngine 外部项目生成指南(AI 视角)
|
|
2
|
+
|
|
3
|
+
**文档类型**: External Usage Guide
|
|
4
|
+
**读者**: AI Coding Agent / 外部开发者
|
|
5
|
+
**目标**: 基于 EvaEngine 从零生成一个可运行的新项目
|
|
6
|
+
|
|
7
|
+
## 1. 目标
|
|
8
|
+
|
|
9
|
+
给定一个空目录,如何基于 EvaEngine 快速生成一个可运行的外部项目。
|
|
10
|
+
|
|
11
|
+
重点不是“改这个库本身”,而是“用这个库生成一个新的业务项目”。
|
|
12
|
+
|
|
13
|
+
## 2. 适用场景
|
|
14
|
+
|
|
15
|
+
适用于以下类型的项目:
|
|
16
|
+
|
|
17
|
+
- Web 服务项目
|
|
18
|
+
- CLI 工具项目
|
|
19
|
+
- 定时任务项目
|
|
20
|
+
- 带缓存、鉴权、Session、Swagger 的微服务骨架
|
|
21
|
+
|
|
22
|
+
## 3. 生成步骤
|
|
23
|
+
|
|
24
|
+
### Step 1: 初始化项目目录
|
|
25
|
+
|
|
26
|
+
创建一个新的项目根目录,并生成基础文件结构:
|
|
27
|
+
|
|
28
|
+
```text
|
|
29
|
+
project-root/
|
|
30
|
+
package.json
|
|
31
|
+
src/
|
|
32
|
+
app.js
|
|
33
|
+
commands/
|
|
34
|
+
entities/
|
|
35
|
+
middlewares/
|
|
36
|
+
services/
|
|
37
|
+
config/
|
|
38
|
+
test/
|
|
39
|
+
README.md
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Step 2: 初始化 npm 包
|
|
43
|
+
|
|
44
|
+
生成 package.json,至少包含:
|
|
45
|
+
|
|
46
|
+
- 项目名称
|
|
47
|
+
- type: module
|
|
48
|
+
- 依赖:evaengine
|
|
49
|
+
- scripts:lint / build / test
|
|
50
|
+
|
|
51
|
+
推荐的最小配置如下:
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"name": "my-eva-project",
|
|
56
|
+
"version": "1.0.0",
|
|
57
|
+
"type": "module",
|
|
58
|
+
"scripts": {
|
|
59
|
+
"lint": "eslint src test",
|
|
60
|
+
"build": "node --check src/app.js",
|
|
61
|
+
"test": "ava"
|
|
62
|
+
},
|
|
63
|
+
"dependencies": {
|
|
64
|
+
"evaengine": "^0.11.2"
|
|
65
|
+
},
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"ava": "^8.0.1",
|
|
68
|
+
"eslint": "^9.0.0"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Step 3: 安装依赖
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
npm install
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Step 4: 创建入口文件
|
|
80
|
+
|
|
81
|
+
在 src/app.js 中创建一个基础 Web 服务入口:
|
|
82
|
+
|
|
83
|
+
```js
|
|
84
|
+
import { EvaEngine } from 'evaengine';
|
|
85
|
+
|
|
86
|
+
const engine = new EvaEngine({
|
|
87
|
+
projectRoot: process.cwd(),
|
|
88
|
+
port: 3000
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
engine.bootstrap();
|
|
92
|
+
engine.use('/', (req, res) => {
|
|
93
|
+
res.json({ hello: 'world' });
|
|
94
|
+
});
|
|
95
|
+
engine.run();
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Step 5: 创建配置目录
|
|
99
|
+
|
|
100
|
+
创建 config 目录,用于存放配置文件:
|
|
101
|
+
|
|
102
|
+
```text
|
|
103
|
+
config/
|
|
104
|
+
config.default.js
|
|
105
|
+
config.development.js
|
|
106
|
+
config.local.development.js
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
建议配置文件中至少包含:
|
|
110
|
+
|
|
111
|
+
- 端口
|
|
112
|
+
- 日志级别
|
|
113
|
+
- Session / Auth 配置
|
|
114
|
+
- Redis / Cache 配置(如需要)
|
|
115
|
+
|
|
116
|
+
### Step 6: 创建 CLI 命令(可选)
|
|
117
|
+
|
|
118
|
+
如果项目需要命令行能力,可以新增 src/commands 下的命令文件:
|
|
119
|
+
|
|
120
|
+
```js
|
|
121
|
+
export default class HelloCommand {
|
|
122
|
+
static getName() {
|
|
123
|
+
return 'hello:world';
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
static getDescription() {
|
|
127
|
+
return 'Print hello world';
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async run() {
|
|
131
|
+
console.log('hello world');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
然后在入口里注册:
|
|
137
|
+
|
|
138
|
+
```js
|
|
139
|
+
import { EvaEngine } from 'evaengine';
|
|
140
|
+
import HelloCommand from './commands/hello.js';
|
|
141
|
+
|
|
142
|
+
const engine = new EvaEngine({ projectRoot: process.cwd() }, 'cli');
|
|
143
|
+
engine.registerCommands([HelloCommand]);
|
|
144
|
+
await engine.runCLI();
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Step 7: 创建业务实体(可选)
|
|
148
|
+
|
|
149
|
+
如果项目需要数据库/ORM 能力,创建实体目录:
|
|
150
|
+
|
|
151
|
+
```text
|
|
152
|
+
src/entities/
|
|
153
|
+
user.js
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
实体应尽量保持:
|
|
157
|
+
|
|
158
|
+
- 业务语义清晰
|
|
159
|
+
- 配置独立
|
|
160
|
+
- 与外部基础设施解耦
|
|
161
|
+
|
|
162
|
+
### Step 8: 创建测试文件
|
|
163
|
+
|
|
164
|
+
建议为核心功能新增测试:
|
|
165
|
+
|
|
166
|
+
```text
|
|
167
|
+
test/
|
|
168
|
+
app.test.js
|
|
169
|
+
commands/
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
测试应优先覆盖:
|
|
173
|
+
|
|
174
|
+
- 路由是否可访问
|
|
175
|
+
- 命令是否正确执行
|
|
176
|
+
- 错误处理是否正常
|
|
177
|
+
|
|
178
|
+
### Step 9: 运行项目
|
|
179
|
+
|
|
180
|
+
开发环境中可以先启动服务:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
node src/app.js
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
如果是 CLI 模式:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
node src/cli.js
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## 4. 推荐的默认项目结构
|
|
193
|
+
|
|
194
|
+
```text
|
|
195
|
+
my-eva-project/
|
|
196
|
+
config/
|
|
197
|
+
src/
|
|
198
|
+
app.js
|
|
199
|
+
cli.js
|
|
200
|
+
commands/
|
|
201
|
+
entities/
|
|
202
|
+
middlewares/
|
|
203
|
+
services/
|
|
204
|
+
test/
|
|
205
|
+
README.md
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## 5. 生成时的默认约定
|
|
209
|
+
|
|
210
|
+
当 AI 需要基于 EvaEngine 生成一个新项目时,建议默认遵守以下规则:
|
|
211
|
+
|
|
212
|
+
- 先生成一个最小可运行版本,再逐步补业务能力
|
|
213
|
+
- 优先使用 Web 服务入口作为默认入口
|
|
214
|
+
- CLI/Crontab 作为可选扩展能力
|
|
215
|
+
- 使用配置文件而不是把配置硬编码进业务代码
|
|
216
|
+
- 把基础设施能力(Redis、JWT、Cache、Logger)通过框架能力接入,而不是手写重复逻辑
|
|
217
|
+
- 先保证能跑起来,再补复杂功能
|
|
218
|
+
|
|
219
|
+
## 6. 推荐的生成顺序
|
|
220
|
+
|
|
221
|
+
1. 初始化 package.json
|
|
222
|
+
2. 安装 evaengine
|
|
223
|
+
3. 生成 Web 服务入口
|
|
224
|
+
4. 生成 config 目录
|
|
225
|
+
5. 生成一个 hello world 路由
|
|
226
|
+
6. 生成一个 CLI command
|
|
227
|
+
7. 生成测试
|
|
228
|
+
8. 运行 lint / build / test
|
|
229
|
+
|
|
230
|
+
## 7. 生成完成后的验收标准
|
|
231
|
+
|
|
232
|
+
一个“生成成功”的项目应满足:
|
|
233
|
+
|
|
234
|
+
- 能安装依赖
|
|
235
|
+
- 能启动 Web 服务
|
|
236
|
+
- 能返回一个简单响应
|
|
237
|
+
- 能执行最基本的 CLI 命令
|
|
238
|
+
- 能通过基础测试
|
|
239
|
+
|
|
240
|
+
## 8. 结论
|
|
241
|
+
|
|
242
|
+
从零生成一个基于 EvaEngine 的项目,最重要的是先把“运行时骨架”搭起来,再把业务逻辑放进去。
|
|
243
|
+
|
|
244
|
+
优先级顺序建议是:
|
|
245
|
+
|
|
246
|
+
```text
|
|
247
|
+
先能跑起来 -> 再加 CLI -> 再加定时任务 -> 再加数据库/实体 -> 再加复杂中间件
|
|
248
|
+
```
|