@taicode/common-server 4.0.0-beta.2 → 4.0.0-beta.4

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.
Files changed (276) hide show
  1. package/output/app/index.d.ts +13 -15
  2. package/output/app/index.d.ts.map +1 -1
  3. package/output/app/index.js +256 -18
  4. package/output/auth/index.d.ts +72 -0
  5. package/output/auth/index.d.ts.map +1 -0
  6. package/output/auth/index.js +176 -0
  7. package/output/core/assemble.d.ts +64 -0
  8. package/output/core/assemble.d.ts.map +1 -0
  9. package/output/core/assemble.js +88 -0
  10. package/output/core/boot/context.d.ts +89 -0
  11. package/output/core/boot/context.d.ts.map +1 -0
  12. package/output/core/boot/context.js +106 -0
  13. package/output/core/boot/lifecycle.d.ts +94 -0
  14. package/output/core/boot/lifecycle.d.ts.map +1 -0
  15. package/output/{app → core/boot}/lifecycle.js +45 -14
  16. package/output/core/boot/shutdown.d.ts +30 -0
  17. package/output/core/boot/shutdown.d.ts.map +1 -0
  18. package/output/core/boot/shutdown.js +45 -0
  19. package/output/core/boot/signal.d.ts +13 -0
  20. package/output/core/boot/signal.d.ts.map +1 -0
  21. package/output/{app → core/boot}/signal.js +3 -2
  22. package/output/core/boot/steps.d.ts +107 -0
  23. package/output/core/boot/steps.d.ts.map +1 -0
  24. package/output/core/boot/steps.js +200 -0
  25. package/output/core/entries.d.ts +123 -0
  26. package/output/core/entries.d.ts.map +1 -0
  27. package/output/core/entries.js +193 -0
  28. package/output/core/entries.test.d.ts +2 -0
  29. package/output/core/entries.test.d.ts.map +1 -0
  30. package/output/core/entries.test.js +217 -0
  31. package/output/core/env.d.ts +62 -0
  32. package/output/core/env.d.ts.map +1 -0
  33. package/output/core/env.js +96 -0
  34. package/output/{app → core}/env.test.d.ts.map +1 -1
  35. package/output/core/env.test.js +105 -0
  36. package/output/core/modules/auth-provider/index.d.ts +10 -0
  37. package/output/core/modules/auth-provider/index.d.ts.map +1 -0
  38. package/output/core/modules/auth-provider/index.js +9 -0
  39. package/output/core/modules/auth-provider/types.d.ts +71 -0
  40. package/output/core/modules/auth-provider/types.d.ts.map +1 -0
  41. package/output/core/modules/context/index.d.ts +18 -0
  42. package/output/core/modules/context/index.d.ts.map +1 -0
  43. package/output/core/modules/context/index.js +23 -0
  44. package/output/core/modules/context/index.test.d.ts.map +1 -0
  45. package/output/core/modules/cookie/index.d.ts +21 -0
  46. package/output/core/modules/cookie/index.d.ts.map +1 -0
  47. package/output/{app/core/cookie.js → core/modules/cookie/index.js} +1 -6
  48. package/output/core/modules/identity/index.d.ts +4 -0
  49. package/output/core/modules/identity/index.d.ts.map +1 -0
  50. package/output/{app/core/identity.js → core/modules/identity/index.js} +1 -1
  51. package/output/core/modules/logging/index.d.ts +5 -0
  52. package/output/core/modules/logging/index.d.ts.map +1 -0
  53. package/output/{app/core/logging.js → core/modules/logging/index.js} +2 -2
  54. package/output/core/modules/openapi/index.d.ts +7 -0
  55. package/output/core/modules/openapi/index.d.ts.map +1 -0
  56. package/output/{app/core/openapi.js → core/modules/openapi/index.js} +11 -12
  57. package/output/core/modules/permission-operations/index.d.ts +26 -0
  58. package/output/core/modules/permission-operations/index.d.ts.map +1 -0
  59. package/output/core/modules/permission-operations/index.js +36 -0
  60. package/output/core/modules/permission-operations/index.test.d.ts +2 -0
  61. package/output/core/modules/permission-operations/index.test.d.ts.map +1 -0
  62. package/output/core/modules/permission-operations/index.test.js +45 -0
  63. package/output/{app/core/request-id.d.ts → core/modules/request-id/index.d.ts} +1 -4
  64. package/output/core/modules/request-id/index.d.ts.map +1 -0
  65. package/output/{app/core/request-id.js → core/modules/request-id/index.js} +2 -2
  66. package/output/core/modules/response/index.d.ts +22 -0
  67. package/output/core/modules/response/index.d.ts.map +1 -0
  68. package/output/{app/core/response.js → core/modules/response/index.js} +22 -11
  69. package/output/{schema/index.d.ts → core/modules/schema/builders.d.ts} +8 -1
  70. package/output/core/modules/schema/builders.d.ts.map +1 -0
  71. package/output/{schema/index.js → core/modules/schema/builders.js} +7 -4
  72. package/output/core/modules/schema/index.d.ts +34 -0
  73. package/output/core/modules/schema/index.d.ts.map +1 -0
  74. package/output/core/modules/schema/index.js +62 -0
  75. package/output/core/modules/schema/index.test.d.ts +2 -0
  76. package/output/core/modules/schema/index.test.d.ts.map +1 -0
  77. package/output/core/modules/schema/index.test.js +55 -0
  78. package/output/core/modules/system-routes/index.d.ts +15 -0
  79. package/output/core/modules/system-routes/index.d.ts.map +1 -0
  80. package/output/core/modules/system-routes/index.js +171 -0
  81. package/output/core/test-support/database.d.ts +96 -0
  82. package/output/core/test-support/database.d.ts.map +1 -0
  83. package/output/core/test-support/database.js +144 -0
  84. package/output/core/test-support/database.test.d.ts +2 -0
  85. package/output/core/test-support/database.test.d.ts.map +1 -0
  86. package/output/core/test-support/database.test.js +110 -0
  87. package/output/core/test-support/environment.d.ts +33 -0
  88. package/output/core/test-support/environment.d.ts.map +1 -0
  89. package/output/core/test-support/environment.js +42 -0
  90. package/output/core/test-support/test-server.d.ts +94 -0
  91. package/output/core/test-support/test-server.d.ts.map +1 -0
  92. package/output/core/test-support/test-server.js +60 -0
  93. package/output/core/test-support/test-server.test.d.ts +2 -0
  94. package/output/core/test-support/test-server.test.d.ts.map +1 -0
  95. package/output/core/test-support/test-server.test.js +162 -0
  96. package/output/{app → core}/type-augment.d.ts +2 -2
  97. package/output/core/type-augment.d.ts.map +1 -0
  98. package/output/core/types.d.ts +338 -0
  99. package/output/core/types.d.ts.map +1 -0
  100. package/output/cors/index.d.ts +3 -0
  101. package/output/cors/index.d.ts.map +1 -0
  102. package/output/cors/index.js +27 -0
  103. package/output/index.d.ts +8 -4
  104. package/output/index.d.ts.map +1 -1
  105. package/output/index.js +24 -5
  106. package/output/rate-limit/index.d.ts +23 -0
  107. package/output/rate-limit/index.d.ts.map +1 -0
  108. package/output/rate-limit/index.js +42 -0
  109. package/output/{rate-limiter/rate-limiter.d.ts → rate-limit/limiter.d.ts} +1 -1
  110. package/output/rate-limit/limiter.d.ts.map +1 -0
  111. package/output/rate-limit/memory-store.d.ts.map +1 -0
  112. package/output/rate-limit/redis-store.d.ts.map +1 -0
  113. package/output/rate-limit/redis-store.test.d.ts.map +1 -0
  114. package/output/{rate-limiter → rate-limit}/redis-store.test.js +2 -2
  115. package/output/{rate-limiter → rate-limit}/types.d.ts +0 -1
  116. package/output/rate-limit/types.d.ts.map +1 -0
  117. package/output/rate-limit/types.js +1 -0
  118. package/output/{redis-cache/redis-cache.d.ts → redis/cache.d.ts} +1 -1
  119. package/output/redis/cache.d.ts.map +1 -0
  120. package/output/redis/cache.test.d.ts +2 -0
  121. package/output/redis/cache.test.d.ts.map +1 -0
  122. package/output/{redis-cache/redis-cache.test.js → redis/cache.test.js} +1 -1
  123. package/output/{app/redis.d.ts → redis/index.d.ts} +12 -7
  124. package/output/redis/index.d.ts.map +1 -0
  125. package/output/{app/redis.js → redis/index.js} +15 -5
  126. package/output/redis/index.test.d.ts +2 -0
  127. package/output/{context → redis}/index.test.d.ts.map +1 -1
  128. package/output/redis/index.test.js +55 -0
  129. package/output/redis-queue/index.js +1 -1
  130. package/output/redis-queue/test-helpers.d.ts +1 -1
  131. package/output/redis-queue/test-helpers.js +1 -1
  132. package/output/redis-queue/types.d.ts +3 -12
  133. package/output/redis-queue/types.d.ts.map +1 -1
  134. package/package.json +16 -15
  135. package/LICENSE +0 -21
  136. package/output/app/auth.test.d.ts +0 -2
  137. package/output/app/auth.test.d.ts.map +0 -1
  138. package/output/app/auth.test.js +0 -148
  139. package/output/app/boot.d.ts +0 -39
  140. package/output/app/boot.d.ts.map +0 -1
  141. package/output/app/boot.js +0 -140
  142. package/output/app/config.test.d.ts +0 -2
  143. package/output/app/config.test.d.ts.map +0 -1
  144. package/output/app/config.test.js +0 -132
  145. package/output/app/context.d.ts +0 -70
  146. package/output/app/context.d.ts.map +0 -1
  147. package/output/app/context.js +0 -73
  148. package/output/app/core/cookie.d.ts +0 -25
  149. package/output/app/core/cookie.d.ts.map +0 -1
  150. package/output/app/core/identity.d.ts +0 -12
  151. package/output/app/core/identity.d.ts.map +0 -1
  152. package/output/app/core/index.d.ts +0 -44
  153. package/output/app/core/index.d.ts.map +0 -1
  154. package/output/app/core/index.js +0 -57
  155. package/output/app/core/logging.d.ts +0 -13
  156. package/output/app/core/logging.d.ts.map +0 -1
  157. package/output/app/core/openapi.d.ts +0 -17
  158. package/output/app/core/openapi.d.ts.map +0 -1
  159. package/output/app/core/request-id.d.ts.map +0 -1
  160. package/output/app/core/response.d.ts +0 -41
  161. package/output/app/core/response.d.ts.map +0 -1
  162. package/output/app/define-server.negative-cases.d.ts +0 -40
  163. package/output/app/define-server.negative-cases.d.ts.map +0 -1
  164. package/output/app/define-server.negative-cases.js +0 -268
  165. package/output/app/define-server.test.d.ts +0 -2
  166. package/output/app/define-server.test.d.ts.map +0 -1
  167. package/output/app/define-server.test.js +0 -97
  168. package/output/app/entries.d.ts +0 -29
  169. package/output/app/entries.d.ts.map +0 -1
  170. package/output/app/entries.js +0 -64
  171. package/output/app/env.d.ts +0 -59
  172. package/output/app/env.d.ts.map +0 -1
  173. package/output/app/env.js +0 -66
  174. package/output/app/env.test.js +0 -124
  175. package/output/app/error-contract.test.d.ts +0 -2
  176. package/output/app/error-contract.test.d.ts.map +0 -1
  177. package/output/app/error-contract.test.js +0 -227
  178. package/output/app/errors.d.ts +0 -20
  179. package/output/app/errors.d.ts.map +0 -1
  180. package/output/app/errors.js +0 -51
  181. package/output/app/generate-openapi.test.d.ts +0 -2
  182. package/output/app/generate-openapi.test.d.ts.map +0 -1
  183. package/output/app/generate-openapi.test.js +0 -123
  184. package/output/app/lifecycle-logging.test.d.ts +0 -2
  185. package/output/app/lifecycle-logging.test.d.ts.map +0 -1
  186. package/output/app/lifecycle-logging.test.js +0 -155
  187. package/output/app/lifecycle.d.ts +0 -70
  188. package/output/app/lifecycle.d.ts.map +0 -1
  189. package/output/app/lifecycle.test.d.ts +0 -2
  190. package/output/app/lifecycle.test.d.ts.map +0 -1
  191. package/output/app/lifecycle.test.js +0 -152
  192. package/output/app/middleware/auth.d.ts +0 -71
  193. package/output/app/middleware/auth.d.ts.map +0 -1
  194. package/output/app/middleware/auth.js +0 -190
  195. package/output/app/middleware/context.d.ts +0 -13
  196. package/output/app/middleware/context.d.ts.map +0 -1
  197. package/output/app/middleware/context.js +0 -15
  198. package/output/app/middleware/cors.d.ts +0 -14
  199. package/output/app/middleware/cors.d.ts.map +0 -1
  200. package/output/app/middleware/cors.js +0 -30
  201. package/output/app/middleware/index.d.ts +0 -17
  202. package/output/app/middleware/index.d.ts.map +0 -1
  203. package/output/app/middleware/index.js +0 -16
  204. package/output/app/middleware/rate-limit.d.ts +0 -24
  205. package/output/app/middleware/rate-limit.d.ts.map +0 -1
  206. package/output/app/middleware/rate-limit.js +0 -46
  207. package/output/app/middleware-order.test.d.ts +0 -2
  208. package/output/app/middleware-order.test.d.ts.map +0 -1
  209. package/output/app/middleware-order.test.js +0 -148
  210. package/output/app/permission-operations.d.ts +0 -48
  211. package/output/app/permission-operations.d.ts.map +0 -1
  212. package/output/app/permission-operations.js +0 -77
  213. package/output/app/permission-operations.test.d.ts +0 -2
  214. package/output/app/permission-operations.test.d.ts.map +0 -1
  215. package/output/app/permission-operations.test.js +0 -72
  216. package/output/app/permission-registration.test.d.ts +0 -2
  217. package/output/app/permission-registration.test.d.ts.map +0 -1
  218. package/output/app/permission-registration.test.js +0 -138
  219. package/output/app/redis.d.ts.map +0 -1
  220. package/output/app/registered-operations.test.d.ts +0 -2
  221. package/output/app/registered-operations.test.d.ts.map +0 -1
  222. package/output/app/registered-operations.test.js +0 -57
  223. package/output/app/request-id.test.d.ts +0 -2
  224. package/output/app/request-id.test.d.ts.map +0 -1
  225. package/output/app/request-id.test.js +0 -130
  226. package/output/app/resources.test.d.ts +0 -2
  227. package/output/app/resources.test.d.ts.map +0 -1
  228. package/output/app/resources.test.js +0 -199
  229. package/output/app/shutdown.d.ts +0 -22
  230. package/output/app/shutdown.d.ts.map +0 -1
  231. package/output/app/shutdown.js +0 -30
  232. package/output/app/shutdown.test.d.ts +0 -2
  233. package/output/app/shutdown.test.d.ts.map +0 -1
  234. package/output/app/shutdown.test.js +0 -103
  235. package/output/app/signal.d.ts +0 -12
  236. package/output/app/signal.d.ts.map +0 -1
  237. package/output/app/smoke.test.d.ts +0 -2
  238. package/output/app/smoke.test.d.ts.map +0 -1
  239. package/output/app/smoke.test.js +0 -210
  240. package/output/app/test-support.d.ts +0 -21
  241. package/output/app/test-support.d.ts.map +0 -1
  242. package/output/app/test-support.js +0 -24
  243. package/output/app/type-augment.d.ts.map +0 -1
  244. package/output/app/types.d.ts +0 -228
  245. package/output/app/types.d.ts.map +0 -1
  246. package/output/context/index.d.ts +0 -6
  247. package/output/context/index.d.ts.map +0 -1
  248. package/output/context/index.js +0 -14
  249. package/output/rate-limiter/index.d.ts +0 -5
  250. package/output/rate-limiter/index.d.ts.map +0 -1
  251. package/output/rate-limiter/index.js +0 -4
  252. package/output/rate-limiter/memory-store.d.ts.map +0 -1
  253. package/output/rate-limiter/rate-limiter.d.ts.map +0 -1
  254. package/output/rate-limiter/redis-store.d.ts.map +0 -1
  255. package/output/rate-limiter/redis-store.test.d.ts.map +0 -1
  256. package/output/rate-limiter/types.d.ts.map +0 -1
  257. package/output/redis-cache/index.d.ts +0 -4
  258. package/output/redis-cache/index.d.ts.map +0 -1
  259. package/output/redis-cache/index.js +0 -1
  260. package/output/redis-cache/redis-cache.d.ts.map +0 -1
  261. package/output/redis-cache/redis-cache.test.d.ts +0 -2
  262. package/output/redis-cache/redis-cache.test.d.ts.map +0 -1
  263. package/output/schema/index.d.ts.map +0 -1
  264. /package/output/{app → core}/env.test.d.ts +0 -0
  265. /package/output/{rate-limiter → core/modules/auth-provider}/types.js +0 -0
  266. /package/output/{context → core/modules/context}/index.test.d.ts +0 -0
  267. /package/output/{context → core/modules/context}/index.test.js +0 -0
  268. /package/output/{app → core}/type-augment.js +0 -0
  269. /package/output/{app → core}/types.js +0 -0
  270. /package/output/{rate-limiter/rate-limiter.js → rate-limit/limiter.js} +0 -0
  271. /package/output/{rate-limiter → rate-limit}/memory-store.d.ts +0 -0
  272. /package/output/{rate-limiter → rate-limit}/memory-store.js +0 -0
  273. /package/output/{rate-limiter → rate-limit}/redis-store.d.ts +0 -0
  274. /package/output/{rate-limiter → rate-limit}/redis-store.js +0 -0
  275. /package/output/{rate-limiter → rate-limit}/redis-store.test.d.ts +0 -0
  276. /package/output/{redis-cache/redis-cache.js → redis/cache.js} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assemble.d.ts","sourceRoot":"","sources":["../../source/core/assemble.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAE9C;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,SAAS,GAAG,eAAe,CAM7D;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,IAAI,eAAe,CAEvD;AAED,gBAAgB;AAChB,MAAM,WAAW,uBAAuB;IACtC,8DAA8D;IAC9D,QAAQ,EAAE,WAAW,CAAA;IACrB,GAAG,EAAE,SAAS,CAAA;IACd,yEAAyE;IACzE,qBAAqB,CAAC,EAAE,eAAe,CAAA;IACvC,2DAA2D;IAC3D,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAA;CACrC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,eAAe,EAAE,OAAO,EAAE,IAAI,CAAC,uBAAuB,EAAE,UAAU,CAAC,GAAG,IAAI,CAIrH;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,eAAe,EAAE,OAAO,EAAE,IAAI,CAAC,uBAAuB,EAAE,UAAU,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAOlI;AAED;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,eAAe,EAAE,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAWxG"}
@@ -0,0 +1,88 @@
1
+ import Fastify from 'fastify';
2
+ import { registerCookie } from './modules/cookie/index.js';
3
+ import { registerRequestContext } from './modules/context/index.js';
4
+ import { attachServerIdentity } from './modules/identity/index.js';
5
+ import { createLoggerOptions } from './modules/logging/index.js';
6
+ import { registerOpenApi } from './modules/openapi/index.js';
7
+ import { createRequestIdOptions, registerRequestId } from './modules/request-id/index.js';
8
+ import { registerResponse } from './modules/response/index.js';
9
+ import { installRouteSchemaGuard, registerSchema } from './modules/schema/index.js';
10
+ /**
11
+ * core 步骤 `createFastify`(`prepare`)。
12
+ *
13
+ * **总是**建 pino logger(level = `LOG_LEVEL`,默认 `info`) + 内置 `requestId`(入站 `x-request-id`
14
+ * 复用 / `randomUUID`,日志字段 `requestId`)。`trustProxy: true` 与四家现状一致。
15
+ *
16
+ * 固定装配,**不从包对外导出**:对外入口只有 `defineServer` / `startServer` / `generateOpenApi`。
17
+ */
18
+ export function createFastify(env) {
19
+ return Fastify({
20
+ trustProxy: true,
21
+ logger: createLoggerOptions(env),
22
+ ...createRequestIdOptions(),
23
+ });
24
+ }
25
+ /**
26
+ * 出文档用的**最小实例**(`generateOpenApi` 专用)。
27
+ *
28
+ * 没有 logger、没有 `requestId`、没有 `trustProxy`——这些只在**有请求**时才有意义,
29
+ * 而构建期一条请求都不会发。`logger: false` 下 `app.log` 仍是 `abstract-logging` 的
30
+ * 空实现,满足 `LoggerLike`,因此下游单元拿到的 `ctx.log` 调用不会炸,也不会产生输出。
31
+ */
32
+ export function createDocumentFastify() {
33
+ return Fastify({ logger: false });
34
+ }
35
+ /**
36
+ * **schema 契约**(固定序,不可替换):`identity` → `schema`(zod compiler)→ 路由契约守卫。
37
+ *
38
+ * 两个入口都必须有它:
39
+ * - `startServer` 要让 zod 真的校验/序列化请求,并让「路由缺 `schema`」在注册处就失败;
40
+ * - `generateOpenApi` 要把 zod 转成 JSON Schema 出文档,也要同一个守卫——**文档就是权限目录**,
41
+ * 构建期放过的路由会在线上变成「接口永远判不过」。
42
+ *
43
+ * 单独成函数是为了让「运行期 core」与「文档 core」两条装配路径共用同一段契约,
44
+ * 而不用把整段运行期能力拖进出文档路径。
45
+ */
46
+ export function registerSchemaContract(app, options) {
47
+ attachServerIdentity(app, options.identity);
48
+ registerSchema(app); // schema → zod compiler
49
+ installRouteSchemaGuard(app); // 强制所有路由声明 schema(含 operationId / summary / description / tags)
50
+ }
51
+ /**
52
+ * **文档 core**(`generateOpenApi` 专用):schema 契约 + swagger。
53
+ *
54
+ * 只有这三件事与「把 zod schema 转成 OpenAPI 文档」有关:身份(`info.title` /
55
+ * `info.version`)、zod compiler(转换前得能读懂 zod)、守卫(不让文档缺条目)、swagger(转换器)。
56
+ * `requestContext` / `cookie` / `response` / `requestId` 全部**不装**——它们只影响
57
+ * 请求怎么被处理,而构建期一条请求都不会发。
58
+ */
59
+ export async function registerDocumentCore(app, options) {
60
+ registerSchemaContract(app, options);
61
+ // await:确定性冲刷插件队列,保证 swagger 的 root `onRoute` 钩子在路由注册之前就位
62
+ await registerOpenApi(app, {
63
+ title: options.identity.title,
64
+ version: options.identity.version,
65
+ });
66
+ }
67
+ /**
68
+ * core 装配(固定序,不可替换):`identity` → `schema`(+ 路由契约守卫)→ `requestContext`
69
+ * → `cookie` → `response` → `openapi` → `requestId` 回吐。
70
+ *
71
+ * 全部为框架内置能力,**不暴露选项面**;`request.ctx` 的装配也在这一步完成(`type-augment` 的
72
+ * 类型承诺因此总有运行期对应物)。**构造期不读配置**(`cookie` 的 domain 在请求期惰性读取),
73
+ * 故出 spec 路径(`readConfig` 不可用)不会触发。
74
+ *
75
+ * 这里**不建路由注册表**:权限目录直接由 `app.swagger()` 生成的文档派生(OpenAPI 是唯一来源)。
76
+ */
77
+ export async function registerCore(app, options) {
78
+ registerSchemaContract(app, options);
79
+ registerRequestContext(app); // request.ctx(type-augment 承诺的运行期对应物)
80
+ registerCookie(app, { env: options.env, readConfig: options.readConfig });
81
+ registerResponse(app, { classifyResourceError: options.classifyResourceError });
82
+ // await:确定性冲刷插件队列,保证 swagger 的 root `onRoute` 钩子在路由注册之前就位
83
+ await registerOpenApi(app, {
84
+ title: options.identity.title,
85
+ version: options.identity.version,
86
+ });
87
+ registerRequestId(app); // 响应回吐 x-request-id
88
+ }
@@ -0,0 +1,89 @@
1
+ import type { Disposer } from '@taicode/common-base';
2
+ import type { ConfigEnv } from '../env.js';
3
+ import type { AppInstance, ClientsContext, ClientsView, ConfigContext, ErrorClassifier, LoggerLike, MiddlewareContext, ResourcesContext, ResourcesView, RouterContext, ServiceContext } from '../types.js';
4
+ /**
5
+ * 分阶段 ctx 的运行时构造(N1 §2)。
6
+ *
7
+ * 每个槽位拿到的是**字段最小集合**的普通对象;`config` 用 getter 暴露,出 spec 路径
8
+ * (`generateOpenApi` 不跑 `config` 槽位)读到它时抛 `SystemError('CONFIG_UNAVAILABLE')`
9
+ * —— 让「构造期不得读配置」有运行期护栏,而不仅是文档规则。
10
+ */
11
+ /** 运行时镜像 `Live<T>`:剔除值为 `false` 的键(编译期静态关闭) */
12
+ export declare function liveResources(resources: object): Record<string, unknown>;
13
+ /** 客户端包的运行时镜像(口径与 `liveResources` 完全一致,另立一名只为调用处可读) */
14
+ export declare function liveClients(clients: object): Record<string, unknown>;
15
+ /**
16
+ * `config` 槽位的**读取能力**(不是容器)。
17
+ *
18
+ * 装配期各单元需要的是「能不能读、读到什么」,不是「一个有 `current` 字段的箱子」——
19
+ * 后者把**写入**也一并交给了每个拿到 `BootContext` 的步骤,绕开 `buildConfig` 就能改配置。
20
+ * 因此这里只暴露读:`available`(有没有产出)+ `read()`(读,未产出即抛)。
21
+ *
22
+ * 写入通道是**私有 Symbol**(本文件内、不导出):调用方连键名都写不出来,只能通过
23
+ * `provideConfig()` 写,而它只被 `buildConfig` 调用。
24
+ */
25
+ export interface ConfigAccess<C> {
26
+ /** `config` 槽位是否已产出(出 spec 路径恒为 `false`) */
27
+ readonly available: boolean;
28
+ /** 读配置;未产出时抛 `SystemError('CONFIG_UNAVAILABLE')` */
29
+ read(): Awaited<C>;
30
+ }
31
+ export declare function createConfigAccess<C>(): ConfigAccess<C>;
32
+ /** 写入 `config` 产物(唯一的写入口:由 `buildConfig` 调用,不在 `BootContext` 上暴露) */
33
+ export declare function provideConfig<C>(access: ConfigAccess<C>, value: Awaited<C>): void;
34
+ /** 按**已知键**从配置值里取字段(框架内置单元消费配置的单一入口;不做形状校验) */
35
+ export declare function readConfigKey(config: unknown, key: string): unknown;
36
+ /** `resources(ctx)` 入参 */
37
+ export interface ResourcesContextParams {
38
+ env: ConfigEnv;
39
+ log: LoggerLike;
40
+ disposer: Disposer;
41
+ /** 收集器:`buildResources` 注入,把各资源注册的分类器按注册顺序收起来 */
42
+ registerClassifyError: (classifier: ErrorClassifier) => void;
43
+ }
44
+ export declare function createResourcesContext(params: ResourcesContextParams): ResourcesContext;
45
+ /** `config(ctx)` 入参 */
46
+ export interface ConfigContextParams<R> {
47
+ env: ConfigEnv;
48
+ log: LoggerLike;
49
+ disposer: Disposer;
50
+ resources: ResourcesView<R>;
51
+ }
52
+ export declare function createConfigContext<R>(params: ConfigContextParams<R>): ConfigContext<R>;
53
+ /** `clients(ctx)` 入参(与 `services` 同依赖集:`resources` + `config`) */
54
+ export interface ClientsContextParams<R, C> {
55
+ log: LoggerLike;
56
+ disposer: Disposer;
57
+ resources: ResourcesView<R>;
58
+ configAccess: ConfigAccess<C>;
59
+ }
60
+ export declare function createClientsContext<R, C>(params: ClientsContextParams<R, C>): ClientsContext<R, C>;
61
+ /** `services(ctx)` 入参 */
62
+ export interface ServiceContextParams<R, C, CL> {
63
+ log: LoggerLike;
64
+ disposer: Disposer;
65
+ resources: ResourcesView<R>;
66
+ configAccess: ConfigAccess<C>;
67
+ clients: ClientsView<CL>;
68
+ }
69
+ export declare function createServiceContext<R, C, CL>(params: ServiceContextParams<R, C, CL>): ServiceContext<R, C, CL>;
70
+ /** `middlewares(ctx)` 入参 */
71
+ export interface MiddlewareContextParams<C, S, CL> {
72
+ app: AppInstance;
73
+ log: LoggerLike;
74
+ disposer: Disposer;
75
+ services: Awaited<S>;
76
+ configAccess: ConfigAccess<C>;
77
+ clients: ClientsView<CL>;
78
+ }
79
+ export declare function createMiddlewareContext<C, S, CL>(params: MiddlewareContextParams<C, S, CL>): MiddlewareContext<C, S, CL>;
80
+ /** `routers(ctx)` 入参 */
81
+ export interface RouterContextParams<S, CL> {
82
+ app: AppInstance;
83
+ log: LoggerLike;
84
+ disposer: Disposer;
85
+ services: Awaited<S>;
86
+ clients: ClientsView<CL>;
87
+ }
88
+ export declare function createRouterContext<S, CL>(params: RouterContextParams<S, CL>): RouterContext<S, CL>;
89
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../source/core/boot/context.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,WAAW,EACX,aAAa,EACb,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,cAAc,EACf,MAAM,aAAa,CAAA;AAEpB;;;;;;GAMG;AAEH,+CAA+C;AAC/C,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQxE;AAED,uDAAuD;AACvD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEpE;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,4CAA4C;IAC5C,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,oDAAoD;IACpD,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC,CAAA;CACnB;AAQD,wBAAgB,kBAAkB,CAAC,CAAC,KAAK,YAAY,CAAC,CAAC,CAAC,CAuBvD;AAED,qEAAqE;AACrE,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAMjF;AAED,+CAA+C;AAC/C,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAEnE;AAED,0BAA0B;AAC1B,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,SAAS,CAAA;IACd,GAAG,EAAE,UAAU,CAAA;IACf,QAAQ,EAAE,QAAQ,CAAA;IAClB,iDAAiD;IACjD,qBAAqB,EAAE,CAAC,UAAU,EAAE,eAAe,KAAK,IAAI,CAAA;CAC7D;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,sBAAsB,GAAG,gBAAgB,CAOvF;AAED,uBAAuB;AACvB,MAAM,WAAW,mBAAmB,CAAC,CAAC;IACpC,GAAG,EAAE,SAAS,CAAA;IACd,GAAG,EAAE,UAAU,CAAA;IACf,QAAQ,EAAE,QAAQ,CAAA;IAClB,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;CAC5B;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAEvF;AAED,kEAAkE;AAClE,MAAM,WAAW,oBAAoB,CAAC,CAAC,EAAE,CAAC;IACxC,GAAG,EAAE,UAAU,CAAA;IACf,QAAQ,EAAE,QAAQ,CAAA;IAClB,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;IAC3B,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,CAAA;CAC9B;AAED,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CASnG;AAED,yBAAyB;AACzB,MAAM,WAAW,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;IAC5C,GAAG,EAAE,UAAU,CAAA;IACf,QAAQ,EAAE,QAAQ,CAAA;IAClB,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;IAC3B,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,CAAA;IAC7B,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC,CAAA;CACzB;AAED,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,cAAc,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAU/G;AAED,4BAA4B;AAC5B,MAAM,WAAW,uBAAuB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;IAC/C,GAAG,EAAE,WAAW,CAAA;IAChB,GAAG,EAAE,UAAU,CAAA;IACf,QAAQ,EAAE,QAAQ,CAAA;IAClB,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IACpB,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,CAAA;IAC7B,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC,CAAA;CACzB;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,uBAAuB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAWxH;AAED,wBAAwB;AACxB,MAAM,WAAW,mBAAmB,CAAC,CAAC,EAAE,EAAE;IACxC,GAAG,EAAE,WAAW,CAAA;IAChB,GAAG,EAAE,UAAU,CAAA;IACf,QAAQ,EAAE,QAAQ,CAAA;IAClB,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IACpB,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC,CAAA;CACzB;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,mBAAmB,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,aAAa,CAAC,CAAC,EAAE,EAAE,CAAC,CAQnG"}
@@ -0,0 +1,106 @@
1
+ import { SystemError } from '@taicode/common-base';
2
+ /**
3
+ * 分阶段 ctx 的运行时构造(N1 §2)。
4
+ *
5
+ * 每个槽位拿到的是**字段最小集合**的普通对象;`config` 用 getter 暴露,出 spec 路径
6
+ * (`generateOpenApi` 不跑 `config` 槽位)读到它时抛 `SystemError('CONFIG_UNAVAILABLE')`
7
+ * —— 让「构造期不得读配置」有运行期护栏,而不仅是文档规则。
8
+ */
9
+ /** 运行时镜像 `Live<T>`:剔除值为 `false` 的键(编译期静态关闭) */
10
+ export function liveResources(resources) {
11
+ const result = {};
12
+ for (const [key, value] of Object.entries(resources)) {
13
+ if (value !== false) {
14
+ result[key] = value;
15
+ }
16
+ }
17
+ return result;
18
+ }
19
+ /** 客户端包的运行时镜像(口径与 `liveResources` 完全一致,另立一名只为调用处可读) */
20
+ export function liveClients(clients) {
21
+ return liveResources(clients);
22
+ }
23
+ const CONFIG_WRITE = Symbol('config.write');
24
+ export function createConfigAccess() {
25
+ let value;
26
+ const access = {
27
+ get available() {
28
+ return value !== undefined;
29
+ },
30
+ read() {
31
+ if (value === undefined) {
32
+ throw new SystemError('CONFIG_UNAVAILABLE', undefined, '配置尚未就绪(generateOpenApi 路径不跑 config 槽位):任何单元不得在构造期读配置');
33
+ }
34
+ return value;
35
+ },
36
+ [CONFIG_WRITE](next) {
37
+ value = next;
38
+ },
39
+ };
40
+ return access;
41
+ }
42
+ /** 写入 `config` 产物(唯一的写入口:由 `buildConfig` 调用,不在 `BootContext` 上暴露) */
43
+ export function provideConfig(access, value) {
44
+ const write = access[CONFIG_WRITE];
45
+ if (write === undefined) {
46
+ throw new Error('[config] 非法写入:`ConfigAccess` 只能由 `createConfigAccess()` 产出');
47
+ }
48
+ write(value);
49
+ }
50
+ /** 按**已知键**从配置值里取字段(框架内置单元消费配置的单一入口;不做形状校验) */
51
+ export function readConfigKey(config, key) {
52
+ return config?.[key];
53
+ }
54
+ export function createResourcesContext(params) {
55
+ return {
56
+ env: params.env,
57
+ log: params.log,
58
+ disposer: params.disposer,
59
+ registerClassifyError: params.registerClassifyError,
60
+ };
61
+ }
62
+ export function createConfigContext(params) {
63
+ return { env: params.env, log: params.log, disposer: params.disposer, resources: params.resources };
64
+ }
65
+ export function createClientsContext(params) {
66
+ return {
67
+ log: params.log,
68
+ disposer: params.disposer,
69
+ resources: params.resources,
70
+ get config() {
71
+ return params.configAccess.read();
72
+ },
73
+ };
74
+ }
75
+ export function createServiceContext(params) {
76
+ return {
77
+ log: params.log,
78
+ disposer: params.disposer,
79
+ resources: params.resources,
80
+ clients: params.clients,
81
+ get config() {
82
+ return params.configAccess.read();
83
+ },
84
+ };
85
+ }
86
+ export function createMiddlewareContext(params) {
87
+ return {
88
+ app: params.app,
89
+ log: params.log,
90
+ disposer: params.disposer,
91
+ services: params.services,
92
+ clients: params.clients,
93
+ get config() {
94
+ return params.configAccess.read();
95
+ },
96
+ };
97
+ }
98
+ export function createRouterContext(params) {
99
+ return {
100
+ app: params.app,
101
+ log: params.log,
102
+ disposer: params.disposer,
103
+ services: params.services,
104
+ clients: params.clients,
105
+ };
106
+ }
@@ -0,0 +1,94 @@
1
+ import type { Disposer } from '@taicode/common-base';
2
+ import type { LoggerLike } from '../types.js';
3
+ /**
4
+ * 生命周期序(N1 §4 / N2 §2.5)。
5
+ *
6
+ * **每个阶段一个 `Disposer`**(`ctx.disposer`,所有槽位都有):在创建某个东西的地方当场
7
+ * `ctx.disposer.add(() => 释放它)` —— 创建与释放同处一地。
8
+ *
9
+ * 关闭时按阶段**逆序 flush**:`routers → middlewares → services → clients → config → resources`
10
+ * (后创建的先销毁;Prisma / Redis 这类资源最后才断)。
11
+ *
12
+ * **`clients` 为什么排在 `services` 之后关**:服务单元 `dispose()` 时可能还要落一次外部调用
13
+ * (落库、通知、上报),客户端必须先活着。
14
+ *
15
+ * **`services` 额外有逐单元生命周期**:
16
+ * - 单元之间**不得相互依赖**(`services` 的 ctx 没有 `services` 字段,编译期禁止);
17
+ * - `init` 按**对象声明序**,`dispose` **逆序**;
18
+ * - services 阶段内部**先 flush `ctx.disposer`**(构造期注册的清理),再逐单元 `dispose`。
19
+ *
20
+ * `middlewares` 按**对象键序**注册;它只有 `disposer`,没有逐单元生命周期。
21
+ */
22
+ export declare const RESOURCES_STAGE = "resources";
23
+ export declare const CONFIG_STAGE = "config";
24
+ export declare const CLIENTS_STAGE = "clients";
25
+ export declare const SERVICES_STAGE = "services";
26
+ export declare const MIDDLEWARES_STAGE = "middlewares";
27
+ export declare const ROUTERS_STAGE = "routers";
28
+ /** `middlewares` 的**注册期日志**阶段标签(与生命周期阶段同名) */
29
+ export declare const MIDDLEWARES_LOG_STAGE = "middlewares";
30
+ /** 生命周期相位(逐单元日志字段 `phase`) */
31
+ export declare const LIFECYCLE_PHASE_INIT = "init";
32
+ export declare const LIFECYCLE_PHASE_DISPOSE = "dispose";
33
+ export type LifecyclePhase = typeof LIFECYCLE_PHASE_INIT | typeof LIFECYCLE_PHASE_DISPOSE;
34
+ /**
35
+ * 逐单元生命周期日志上下文。
36
+ *
37
+ * `log` / `service` 缺省时**不打日志**(纯单测可直接调用生命周期函数,不注入假 logger)。
38
+ * 字段名固定为全拼:`service` + `unit` + `stage` + `phase`。
39
+ */
40
+ export interface LifecycleLogContext {
41
+ /** 日志标签(`defineServer({ app: { service } })`);缺省时退路名字失去前缀 */
42
+ service?: string;
43
+ /** 记录型 logger(`ctx.log`);缺省 = 不打日志 */
44
+ log?: LoggerLike;
45
+ }
46
+ /** 逐单元日志字段(全拼):`unit` = 有效名字(阶段 flush 时为阶段名),`stage` = 阶段名 */
47
+ export interface LifecycleUnitLogFields {
48
+ service: string;
49
+ unit: string;
50
+ stage: string;
51
+ phase: LifecyclePhase;
52
+ }
53
+ /**
54
+ * `middlewares` 日志名字:**对象键即单元名**(与 `services` 同口径)。
55
+ *
56
+ * 键为空串时退路 `<service>:middleware`(仅用于注册期日志,不影响注册序)。
57
+ */
58
+ export declare function middlewareUnitName(service: string, key: string): string;
59
+ /** `initServiceUnits` 入参(参数签名内联对象类型已按 lint 规则外提) */
60
+ export interface InitServiceUnitsParams extends LifecycleLogContext {
61
+ /** `services(ctx)` 返回的对象(**对象键即单元名**) */
62
+ services?: Record<string, unknown>;
63
+ }
64
+ /**
65
+ * 启动序:`services` 按**对象声明序**逐项 `await init?.()`;逐项打日志。
66
+ */
67
+ export declare function initServiceUnits(params: InitServiceUnitsParams): Promise<void>;
68
+ /** `buildDisposeOrder` / `disposeServiceUnits` 入参(参数签名内联对象类型已按 lint 规则外提) */
69
+ export interface DisposeServiceUnitsParams extends LifecycleLogContext {
70
+ /** `services(ctx)` 返回的对象(**对象键即单元名**) */
71
+ services?: Record<string, unknown>;
72
+ }
73
+ /**
74
+ * 关闭步 `disposeServices`:`services` 声明序逆序释放。
75
+ *
76
+ * 单元级失败已在 `runLifecycleUnit` 内 `log.error`(带 service / unit / stage / phase);
77
+ * 此处仅保证单步不阻断后续。
78
+ */
79
+ export declare function disposeServices(params: DisposeServiceUnitsParams): Promise<void>;
80
+ /** `disposeStage` 入参(参数签名内联对象类型已按 lint 规则外提) */
81
+ export interface DisposeStageParams extends LifecycleLogContext {
82
+ /** 阶段名(`routers` / `middlewares` / `services` / `config` / `resources`) */
83
+ stage: string;
84
+ /** 该阶段的 `Disposer`(构造期注册的清理函数,**逆注册序**执行) */
85
+ disposer: Disposer;
86
+ }
87
+ /**
88
+ * 关闭步:flush 某个阶段的 `disposer`。
89
+ *
90
+ * 单元名 = 阶段名(一个阶段一个 `Disposer`,不逐注册项打日志);`phase` 固定 `dispose`。
91
+ * 单个清理函数失败由 `Disposer` 自己捕获记录,不影响同阶段其它函数。
92
+ */
93
+ export declare function disposeStage(params: DisposeStageParams): Promise<void>;
94
+ //# sourceMappingURL=lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../../source/core/boot/lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE7C;;;;;;;;;;;;;;;;;;GAkBG;AAEH,eAAO,MAAM,eAAe,cAAc,CAAA;AAC1C,eAAO,MAAM,YAAY,WAAW,CAAA;AACpC,eAAO,MAAM,aAAa,YAAY,CAAA;AACtC,eAAO,MAAM,cAAc,aAAa,CAAA;AACxC,eAAO,MAAM,iBAAiB,gBAAgB,CAAA;AAC9C,eAAO,MAAM,aAAa,YAAY,CAAA;AACtC,8CAA8C;AAC9C,eAAO,MAAM,qBAAqB,gBAAoB,CAAA;AAEtD,8BAA8B;AAC9B,eAAO,MAAM,oBAAoB,SAAS,CAAA;AAC1C,eAAO,MAAM,uBAAuB,YAAY,CAAA;AAChD,MAAM,MAAM,cAAc,GAAG,OAAO,oBAAoB,GAAG,OAAO,uBAAuB,CAAA;AAEzF;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sCAAsC;IACtC,GAAG,CAAC,EAAE,UAAU,CAAA;CACjB;AAED,8DAA8D;AAC9D,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,cAAc,CAAA;CACtB;AAaD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEvE;AAED,oDAAoD;AACpD,MAAM,WAAW,sBAAuB,SAAQ,mBAAmB;IACjE,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC;AAmCD;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAIpF;AAED,6EAA6E;AAC7E,MAAM,WAAW,yBAA0B,SAAQ,mBAAmB;IACpE,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC;AAaD;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAQtF;AAED,gDAAgD;AAChD,MAAM,WAAW,kBAAmB,SAAQ,mBAAmB;IAC7D,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAA;IACb,6CAA6C;IAC7C,QAAQ,EAAE,QAAQ,CAAA;CACnB;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAU5E"}
@@ -1,15 +1,30 @@
1
1
  /**
2
2
  * 生命周期序(N1 §4 / N2 §2.5)。
3
3
  *
4
- * **只有 `services` 参与生命周期**:
4
+ * **每个阶段一个 `Disposer`**(`ctx.disposer`,所有槽位都有):在创建某个东西的地方当场
5
+ * `ctx.disposer.add(() => 释放它)` —— 创建与释放同处一地。
6
+ *
7
+ * 关闭时按阶段**逆序 flush**:`routers → middlewares → services → clients → config → resources`
8
+ * (后创建的先销毁;Prisma / Redis 这类资源最后才断)。
9
+ *
10
+ * **`clients` 为什么排在 `services` 之后关**:服务单元 `dispose()` 时可能还要落一次外部调用
11
+ * (落库、通知、上报),客户端必须先活着。
12
+ *
13
+ * **`services` 额外有逐单元生命周期**:
5
14
  * - 单元之间**不得相互依赖**(`services` 的 ctx 没有 `services` 字段,编译期禁止);
6
- * - 顺序语义只有一条:按**对象声明序** `init`、**逆序** `dispose`;
7
- * - `middlewares` 按数组序注册,**不参与生命周期**(要常驻资源就放 `services`);
8
- * - `resources` 只是惰性包装(构造不建连),框架不替它们做生命周期。
15
+ * - `init` 按**对象声明序**,`dispose` **逆序**;
16
+ * - services 阶段内部**先 flush `ctx.disposer`**(构造期注册的清理),再逐单元 `dispose`。
17
+ *
18
+ * `middlewares` 按**对象键序**注册;它只有 `disposer`,没有逐单元生命周期。
9
19
  */
20
+ export const RESOURCES_STAGE = 'resources';
21
+ export const CONFIG_STAGE = 'config';
22
+ export const CLIENTS_STAGE = 'clients';
10
23
  export const SERVICES_STAGE = 'services';
11
- /** `middlewares` 的**注册期日志**阶段标签(中间件不参与生命周期,只用于注册日志) */
12
- export const MIDDLEWARES_LOG_STAGE = 'middlewares';
24
+ export const MIDDLEWARES_STAGE = 'middlewares';
25
+ export const ROUTERS_STAGE = 'routers';
26
+ /** `middlewares` 的**注册期日志**阶段标签(与生命周期阶段同名) */
27
+ export const MIDDLEWARES_LOG_STAGE = MIDDLEWARES_STAGE;
13
28
  /** 生命周期相位(逐单元日志字段 `phase`) */
14
29
  export const LIFECYCLE_PHASE_INIT = 'init';
15
30
  export const LIFECYCLE_PHASE_DISPOSE = 'dispose';
@@ -19,17 +34,16 @@ function isObject(value) {
19
34
  /**
20
35
  * `services` 有效名字:**对象键即单元名**(N1 §4:没有 `name` 字段)。
21
36
  */
22
- export function serviceUnitName(key) {
37
+ function serviceUnitName(key) {
23
38
  return key;
24
39
  }
25
40
  /**
26
- * `middlewares` 日志名字:`unit.name ?? '<service>:middleware[<index>]'`(仅用于注册期日志)。
41
+ * `middlewares` 日志名字:**对象键即单元名**(与 `services` 同口径)。
42
+ *
43
+ * 键为空串时退路 `<service>:middleware`(仅用于注册期日志,不影响注册序)。
27
44
  */
28
- export function middlewareUnitName(service, unit, index) {
29
- if (isObject(unit) && typeof unit.name === 'string' && unit.name.length > 0) {
30
- return unit.name;
31
- }
32
- return `${service}:middleware[${index}]`;
45
+ export function middlewareUnitName(service, key) {
46
+ return key.length > 0 ? key : `${service}:middleware`;
33
47
  }
34
48
  async function callInit(unit) {
35
49
  if (isObject(unit) && typeof unit.init === 'function') {
@@ -74,7 +88,7 @@ export async function initServiceUnits(params) {
74
88
  /**
75
89
  * 关闭序:`services` 按声明序**逆序**逐项 `dispose?.()`。
76
90
  */
77
- export function buildDisposeOrder(params) {
91
+ function buildDisposeOrder(params) {
78
92
  const steps = [];
79
93
  for (const key of Object.keys(params.services ?? {}).reverse()) {
80
94
  steps.push(() => runLifecycleUnit(params, serviceUnitName(key), params.services?.[key], LIFECYCLE_PHASE_DISPOSE));
@@ -97,3 +111,20 @@ export async function disposeServices(params) {
97
111
  }
98
112
  }
99
113
  }
114
+ /**
115
+ * 关闭步:flush 某个阶段的 `disposer`。
116
+ *
117
+ * 单元名 = 阶段名(一个阶段一个 `Disposer`,不逐注册项打日志);`phase` 固定 `dispose`。
118
+ * 单个清理函数失败由 `Disposer` 自己捕获记录,不影响同阶段其它函数。
119
+ */
120
+ export async function disposeStage(params) {
121
+ const fields = {
122
+ service: params.service ?? '',
123
+ unit: params.stage,
124
+ stage: params.stage,
125
+ phase: LIFECYCLE_PHASE_DISPOSE,
126
+ };
127
+ params.log?.debug(fields, `[lifecycle] ${LIFECYCLE_PHASE_DISPOSE} "${params.stage}" start`);
128
+ await params.disposer.dispose();
129
+ params.log?.debug(fields, `[lifecycle] ${LIFECYCLE_PHASE_DISPOSE} "${params.stage}" done`);
130
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * 固定关闭步(N1 §5)——**顺序写死在数组里**。
3
+ *
4
+ * `disposer` 是所有槽位 ctx 的标配:每个阶段一个 `Disposer`,在**创建处**注册释放。
5
+ * 关闭时按阶段**逆序 flush**:`routers → middlewares → services → clients → config → resources`
6
+ * (后创建的先销毁;Prisma / Redis 这类资源**最后**才断)。
7
+ *
8
+ * `services` 阶段内部保持既有语义:先 flush 自己的 `disposer`(原 `stopProducers`),
9
+ * 再 `disposeServices`(单元**逆序** `dispose`)。配置失效通道已删除,故没有 `unsubscribeConfig` 步。
10
+ *
11
+ * `clients` 排在 `services` **之后**:服务单元 `dispose()` 时可能还要落一次外部调用。
12
+ *
13
+ * 固定七步:`flushRouters` → `flushMiddlewares` → `flushServices` → `disposeServices`
14
+ * → `flushClients` → `flushConfig` → `flushResources`。
15
+ *
16
+ * 每步失败记日志、不阻断后续,最后聚合上报。
17
+ */
18
+ declare const SHUTDOWN_ORDER: readonly ["flushRouters", "flushMiddlewares", "flushServices", "disposeServices", "flushClients", "flushConfig", "flushResources"];
19
+ type ShutdownStepName = (typeof SHUTDOWN_ORDER)[number];
20
+ type ShutdownHandles = Record<ShutdownStepName, () => void | Promise<void>>;
21
+ export interface ShutdownLogger {
22
+ error: (obj: unknown, msg?: string) => void;
23
+ }
24
+ /**
25
+ * 顺序执行关闭步骤;单步抛错记录后**继续**后续步骤,最后聚合上报
26
+ * (避免「一步报错导致后面资源没关」)。
27
+ */
28
+ export declare function runShutdown(handles: ShutdownHandles, log: ShutdownLogger): Promise<void>;
29
+ export {};
30
+ //# sourceMappingURL=shutdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shutdown.d.ts","sourceRoot":"","sources":["../../../source/core/boot/shutdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,QAAA,MAAM,cAAc,oIAQV,CAAA;AAEV,KAAK,gBAAgB,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAA;AAEvD,KAAK,eAAe,GAAG,MAAM,CAAC,gBAAgB,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;AAE3E,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;CAC5C;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAe9F"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * 固定关闭步(N1 §5)——**顺序写死在数组里**。
3
+ *
4
+ * `disposer` 是所有槽位 ctx 的标配:每个阶段一个 `Disposer`,在**创建处**注册释放。
5
+ * 关闭时按阶段**逆序 flush**:`routers → middlewares → services → clients → config → resources`
6
+ * (后创建的先销毁;Prisma / Redis 这类资源**最后**才断)。
7
+ *
8
+ * `services` 阶段内部保持既有语义:先 flush 自己的 `disposer`(原 `stopProducers`),
9
+ * 再 `disposeServices`(单元**逆序** `dispose`)。配置失效通道已删除,故没有 `unsubscribeConfig` 步。
10
+ *
11
+ * `clients` 排在 `services` **之后**:服务单元 `dispose()` 时可能还要落一次外部调用。
12
+ *
13
+ * 固定七步:`flushRouters` → `flushMiddlewares` → `flushServices` → `disposeServices`
14
+ * → `flushClients` → `flushConfig` → `flushResources`。
15
+ *
16
+ * 每步失败记日志、不阻断后续,最后聚合上报。
17
+ */
18
+ const SHUTDOWN_ORDER = [
19
+ 'flushRouters',
20
+ 'flushMiddlewares',
21
+ 'flushServices',
22
+ 'disposeServices',
23
+ 'flushClients',
24
+ 'flushConfig',
25
+ 'flushResources',
26
+ ];
27
+ /**
28
+ * 顺序执行关闭步骤;单步抛错记录后**继续**后续步骤,最后聚合上报
29
+ * (避免「一步报错导致后面资源没关」)。
30
+ */
31
+ export async function runShutdown(handles, log) {
32
+ const errors = [];
33
+ for (const step of SHUTDOWN_ORDER) {
34
+ try {
35
+ await handles[step]();
36
+ }
37
+ catch (error) {
38
+ errors.push(error);
39
+ log.error({ error, step }, '[shutdown] step failed');
40
+ }
41
+ }
42
+ if (errors.length > 0) {
43
+ log.error({ errors, count: errors.length }, '[shutdown] completed with errors');
44
+ }
45
+ }
@@ -0,0 +1,13 @@
1
+ import type { LoggerLike } from '../types.js';
2
+ import type { FastifyInstance } from 'fastify';
3
+ /**
4
+ * 内置信号处理(设计 §7.1 `activate` 尾部 / §7.2)。
5
+ *
6
+ * `SIGTERM` / `SIGINT` / `uncaughtException` / `unhandledRejection` ⇒ `app.close()`(触发 `onClose`
7
+ * 的关闭 6 步)⇒ `process.exit(0/1)`。**只有 `startServer` 装信号处理**(它一定 `listen`);
8
+ * `createTestServer` 不装——它跑在测试进程里,退出由测试框架决定。
9
+ *
10
+ * @returns detach 函数(移除本次注册的监听器);`startServer` 已把它挂到 `onClose` 上
11
+ */
12
+ export declare function attachSignalHandlers(app: FastifyInstance, log: LoggerLike): () => void;
13
+ //# sourceMappingURL=signal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signal.d.ts","sourceRoot":"","sources":["../../../source/core/boot/signal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAE9C;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,UAAU,GAAG,MAAM,IAAI,CA2CtF"}
@@ -2,9 +2,10 @@
2
2
  * 内置信号处理(设计 §7.1 `activate` 尾部 / §7.2)。
3
3
  *
4
4
  * `SIGTERM` / `SIGINT` / `uncaughtException` / `unhandledRejection` ⇒ `app.close()`(触发 `onClose`
5
- * 的关闭 6 步)⇒ `process.exit(0/1)`。**仅 `listen: true` 时装信号处理**。
5
+ * 的关闭 6 步)⇒ `process.exit(0/1)`。**只有 `startServer` 装信号处理**(它一定 `listen`);
6
+ * `createTestServer` 不装——它跑在测试进程里,退出由测试框架决定。
6
7
  *
7
- * @returns detach 函数(移除本次注册的监听器)
8
+ * @returns detach 函数(移除本次注册的监听器);`startServer` 已把它挂到 `onClose` 上
8
9
  */
9
10
  export function attachSignalHandlers(app, log) {
10
11
  let closing = false;