mega-framework 0.1.6 → 0.1.8

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 (248) hide show
  1. package/README.md +9 -0
  2. package/bin/mega-ws-hub.js +2 -2
  3. package/package.json +33 -9
  4. package/sample/crud/.env +10 -1
  5. package/sample/crud/.env.example +10 -1
  6. package/sample/crud/.mega/journal/history/20260612092543-create-users.json +261 -0
  7. package/sample/crud/.mega/journal/snapshot.json +261 -0
  8. package/sample/crud/apps/main/controllers/auth-controller.js +22 -14
  9. package/sample/crud/apps/main/controllers/web-controller.js +7 -5
  10. package/sample/crud/apps/main/locales/server/en.json +12 -1
  11. package/sample/crud/apps/main/locales/server/ko.json +12 -1
  12. package/sample/crud/apps/main/migrations/20260606000001-create-users.js +91 -13
  13. package/sample/crud/apps/main/migrations/20260606000002-create-boards.js +165 -0
  14. package/sample/crud/apps/main/migrations/20260606000003-create-logs.js +107 -0
  15. package/sample/crud/apps/main/models/log-partition-model.js +105 -0
  16. package/sample/crud/apps/main/models/note-model.js +79 -0
  17. package/sample/crud/apps/main/models/user-level-model.js +24 -0
  18. package/sample/crud/apps/main/models/user-model.js +146 -0
  19. package/sample/crud/apps/main/models/user-type-model.js +21 -0
  20. package/sample/crud/apps/main/models/wallet-model.js +24 -0
  21. package/sample/crud/apps/main/routes/users.js +55 -10
  22. package/sample/crud/apps/main/schedules/log-partition-schedule.js +33 -0
  23. package/sample/crud/apps/main/services/auth-service.js +39 -24
  24. package/sample/crud/apps/main/services/log-partition-service.js +101 -0
  25. package/sample/crud/apps/main/services/note-service.js +6 -6
  26. package/sample/crud/apps/main/services/redis-demo-service.js +3 -3
  27. package/sample/crud/apps/main/services/user-service.js +62 -21
  28. package/sample/crud/apps/main/views/auth/login.ejs +6 -6
  29. package/sample/crud/apps/main/views/auth/register.ejs +46 -5
  30. package/sample/crud/apps/main/views/users/edit.ejs +42 -5
  31. package/sample/crud/apps/main/views/users/list.ejs +6 -2
  32. package/sample/crud/apps/main/views/users/new.ejs +56 -4
  33. package/sample/crud/docs/log_partition_design.mm.md +23 -0
  34. package/sample/crud/mega.config.js +10 -2
  35. package/sample/crud/package.json +3 -3
  36. package/sample/crud/scripts/start-ws-hub.sh +20 -6
  37. package/sample/simple/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  38. package/sample/simple/package.json +2 -2
  39. package/src/adapters/adapter-manager.js +2 -1
  40. package/src/adapters/adapter-options.js +44 -3
  41. package/src/adapters/file-adapter.js +9 -5
  42. package/src/adapters/file-session-adapter.js +4 -3
  43. package/src/adapters/maria-adapter.js +33 -7
  44. package/src/adapters/mega-cache-adapter.js +83 -6
  45. package/src/adapters/mega-db-adapter.js +10 -1
  46. package/src/adapters/mongo-adapter.js +40 -8
  47. package/src/adapters/postgres-adapter.js +33 -6
  48. package/src/adapters/redis-adapter.js +7 -3
  49. package/src/adapters/sqlite-adapter.js +26 -3
  50. package/src/cli/commands/console-cmd.js +3 -1
  51. package/src/cli/commands/new.js +13 -3
  52. package/src/cli/commands/scaffold.js +173 -33
  53. package/src/cli/generators/index.js +140 -3
  54. package/src/cli/index.js +437 -155
  55. package/src/cli/watch.js +188 -0
  56. package/src/core/ajv-mapper.js +30 -3
  57. package/src/core/boot.js +464 -245
  58. package/src/core/cluster-metrics.js +13 -4
  59. package/src/core/ctx-builder.js +65 -3
  60. package/src/core/envelope.js +119 -12
  61. package/src/core/hub-link.js +89 -18
  62. package/src/core/i18n.js +11 -1
  63. package/src/core/index.js +7 -3
  64. package/src/core/mega-app.js +253 -505
  65. package/src/core/mega-cluster.js +4 -1
  66. package/src/core/mega-server.js +40 -9
  67. package/src/core/migration/dialect-registry.js +107 -0
  68. package/src/core/migration/dialects/README.md +62 -0
  69. package/src/core/migration/dialects/maria.js +496 -0
  70. package/src/core/migration/dialects/mongo.js +824 -0
  71. package/src/core/migration/dialects/postgres.js +563 -0
  72. package/src/core/migration/dialects/sqlite.js +476 -0
  73. package/src/core/migration/differ.js +456 -0
  74. package/src/core/migration/generate.js +508 -0
  75. package/src/core/migration/journal.js +167 -0
  76. package/src/core/migration/model-scan.js +84 -0
  77. package/src/core/migration/mongo-migration-db.js +97 -0
  78. package/src/core/migration/schema-builder.js +400 -0
  79. package/src/core/migration/schema-validator.js +315 -0
  80. package/src/core/migration-lock.js +205 -0
  81. package/src/core/migration-runner.js +166 -38
  82. package/src/core/multipart.js +28 -5
  83. package/src/core/pipeline.js +131 -0
  84. package/src/core/router.js +70 -65
  85. package/src/core/scope-registry.js +1 -0
  86. package/src/core/security.js +70 -12
  87. package/src/core/session-store.js +14 -1
  88. package/src/core/workers-manager.js +12 -1
  89. package/src/core/ws-cluster.js +10 -3
  90. package/src/core/ws-message.js +48 -4
  91. package/src/core/ws-presence.js +636 -0
  92. package/src/core/ws-roster.js +50 -8
  93. package/src/core/ws-upgrade.js +223 -12
  94. package/src/index.js +1 -1
  95. package/src/lib/hub-protocol.js +29 -0
  96. package/src/lib/mega-circuit-breaker.js +5 -3
  97. package/src/lib/mega-health.js +35 -4
  98. package/src/lib/mega-job-queue.js +151 -34
  99. package/src/lib/mega-job.js +37 -1
  100. package/src/lib/mega-metrics.js +31 -13
  101. package/src/lib/mega-plugin.js +34 -3
  102. package/src/lib/mega-schedule.js +40 -22
  103. package/src/lib/mega-shutdown.js +114 -39
  104. package/src/lib/mega-tracing.js +66 -19
  105. package/src/lib/mega-worker.js +33 -6
  106. package/src/lib/otel-resource.js +36 -0
  107. package/src/{cli → lib}/ws-hub.js +139 -15
  108. package/src/models/crud-sql-builder.js +133 -0
  109. package/src/models/mega-model.js +82 -2
  110. package/src/models/model-crud.js +483 -0
  111. package/src/models/mongo-crud.js +285 -0
  112. package/templates/adr/code.tpl +23 -0
  113. package/templates/model/code-mongo.tpl +35 -0
  114. package/templates/model/code.tpl +15 -1
  115. package/templates/model/test-mongo.tpl +38 -0
  116. package/templates/model/test.tpl +4 -0
  117. package/types/adapters/adapter-manager.d.ts +95 -0
  118. package/types/adapters/adapter-options.d.ts +93 -0
  119. package/types/adapters/file-adapter.d.ts +105 -0
  120. package/types/adapters/file-session-adapter.d.ts +103 -0
  121. package/types/adapters/index.d.ts +20 -0
  122. package/types/adapters/maria-adapter.d.ts +117 -0
  123. package/types/adapters/mega-adapter.d.ts +215 -0
  124. package/types/adapters/mega-bus-adapter.d.ts +45 -0
  125. package/types/adapters/mega-cache-adapter.d.ts +73 -0
  126. package/types/adapters/mega-db-adapter.d.ts +50 -0
  127. package/types/adapters/mega-lock-adapter.d.ts +62 -0
  128. package/types/adapters/mega-log-sink-adapter.d.ts +15 -0
  129. package/types/adapters/mega-session-adapter.d.ts +32 -0
  130. package/types/adapters/mongo-adapter.d.ts +150 -0
  131. package/types/adapters/nats-adapter.d.ts +108 -0
  132. package/types/adapters/postgres-adapter.d.ts +141 -0
  133. package/types/adapters/redis-adapter.d.ts +78 -0
  134. package/types/adapters/redis-session-adapter.d.ts +82 -0
  135. package/types/adapters/redlock-adapter.d.ts +149 -0
  136. package/types/adapters/registry.d.ts +46 -0
  137. package/types/adapters/sqlite-adapter.d.ts +112 -0
  138. package/types/auth/index.d.ts +24 -0
  139. package/types/cli/commands/console-cmd.d.ts +37 -0
  140. package/types/cli/commands/new.d.ts +16 -0
  141. package/types/cli/commands/routes.d.ts +36 -0
  142. package/types/cli/commands/scaffold.d.ts +78 -0
  143. package/types/cli/commands/test-cmd.d.ts +14 -0
  144. package/types/cli/generators/index.d.ts +122 -0
  145. package/types/cli/index.d.ts +234 -0
  146. package/types/cli/template-engine.d.ts +40 -0
  147. package/types/cli/watch.d.ts +59 -0
  148. package/types/core/ajv-mapper.d.ts +27 -0
  149. package/types/core/boot.d.ts +233 -0
  150. package/types/core/cluster-metrics.d.ts +52 -0
  151. package/types/core/config-loader.d.ts +13 -0
  152. package/types/core/config-validator.d.ts +30 -0
  153. package/types/core/ctx-builder.d.ts +103 -0
  154. package/types/core/envelope.d.ts +79 -0
  155. package/types/core/error-mapper.d.ts +17 -0
  156. package/types/core/formbody.d.ts +41 -0
  157. package/types/core/hub-link.d.ts +266 -0
  158. package/types/core/i18n.d.ts +178 -0
  159. package/types/core/index.d.ts +28 -0
  160. package/types/core/mega-app.d.ts +529 -0
  161. package/types/core/mega-cluster.d.ts +104 -0
  162. package/types/core/mega-server.d.ts +91 -0
  163. package/types/core/mega-service.d.ts +31 -0
  164. package/types/core/migration/dialect-registry.d.ts +22 -0
  165. package/types/core/migration/dialects/maria.d.ts +99 -0
  166. package/types/core/migration/dialects/mongo.d.ts +89 -0
  167. package/types/core/migration/dialects/postgres.d.ts +117 -0
  168. package/types/core/migration/dialects/sqlite.d.ts +111 -0
  169. package/types/core/migration/differ.d.ts +47 -0
  170. package/types/core/migration/generate.d.ts +56 -0
  171. package/types/core/migration/journal.d.ts +52 -0
  172. package/types/core/migration/model-scan.d.ts +19 -0
  173. package/types/core/migration/mongo-migration-db.d.ts +7 -0
  174. package/types/core/migration/schema-builder.d.ts +197 -0
  175. package/types/core/migration/schema-validator.d.ts +20 -0
  176. package/types/core/migration-lock.d.ts +33 -0
  177. package/types/core/migration-runner.d.ts +101 -0
  178. package/types/core/multipart.d.ts +86 -0
  179. package/types/core/openapi.d.ts +62 -0
  180. package/types/core/pipeline.d.ts +93 -0
  181. package/types/core/router.d.ts +159 -0
  182. package/types/core/routes-loader.d.ts +21 -0
  183. package/types/core/scope-registry.d.ts +14 -0
  184. package/types/core/security.d.ts +77 -0
  185. package/types/core/services-loader.d.ts +27 -0
  186. package/types/core/session-cleanup-schedule.d.ts +19 -0
  187. package/types/core/session-store.d.ts +25 -0
  188. package/types/core/session.d.ts +77 -0
  189. package/types/core/static-assets.d.ts +73 -0
  190. package/types/core/template.d.ts +106 -0
  191. package/types/core/workers-manager.d.ts +79 -0
  192. package/types/core/ws-cluster.d.ts +208 -0
  193. package/types/core/ws-compression.d.ts +112 -0
  194. package/types/core/ws-controller.d.ts +65 -0
  195. package/types/core/ws-message.d.ts +106 -0
  196. package/types/core/ws-presence.d.ts +273 -0
  197. package/types/core/ws-roster.d.ts +108 -0
  198. package/types/core/ws-upgrade.d.ts +260 -0
  199. package/types/errors/config-error.d.ts +10 -0
  200. package/types/errors/http-errors.d.ts +120 -0
  201. package/types/errors/index.d.ts +3 -0
  202. package/types/errors/mega-error.d.ts +32 -0
  203. package/types/index.d.ts +39 -0
  204. package/types/lib/asp/config.d.ts +49 -0
  205. package/types/lib/asp/crypto.d.ts +43 -0
  206. package/types/lib/asp/errors.d.ts +30 -0
  207. package/types/lib/asp/nonce-cache.d.ts +52 -0
  208. package/types/lib/asp/plugin.d.ts +30 -0
  209. package/types/lib/asp/ws-terminator.d.ts +45 -0
  210. package/types/lib/env-mapper.d.ts +14 -0
  211. package/types/lib/hub-protocol.d.ts +106 -0
  212. package/types/lib/index.d.ts +22 -0
  213. package/types/lib/logger/telegram-core.d.ts +104 -0
  214. package/types/lib/logger/telegram-transport.d.ts +45 -0
  215. package/types/lib/mega-brute-force.d.ts +66 -0
  216. package/types/lib/mega-circuit-breaker.d.ts +243 -0
  217. package/types/lib/mega-cron.d.ts +66 -0
  218. package/types/lib/mega-hash.d.ts +32 -0
  219. package/types/lib/mega-health.d.ts +48 -0
  220. package/types/lib/mega-job-queue.d.ts +188 -0
  221. package/types/lib/mega-job-worker.d.ts +130 -0
  222. package/types/lib/mega-job.d.ts +145 -0
  223. package/types/lib/mega-logger.d.ts +45 -0
  224. package/types/lib/mega-metrics.d.ts +285 -0
  225. package/types/lib/mega-plugin.d.ts +245 -0
  226. package/types/lib/mega-retry.d.ts +85 -0
  227. package/types/lib/mega-schedule.d.ts +260 -0
  228. package/types/lib/mega-shutdown.d.ts +135 -0
  229. package/types/lib/mega-tracing.d.ts +224 -0
  230. package/types/lib/mega-worker.d.ts +129 -0
  231. package/types/lib/otel-resource.d.ts +16 -0
  232. package/types/lib/worker-runner/process-entry.d.ts +1 -0
  233. package/types/lib/worker-runner/task-dispatch.d.ts +28 -0
  234. package/types/lib/worker-runner/thread-entry.d.ts +1 -0
  235. package/types/lib/ws-hub.d.ts +259 -0
  236. package/types/models/crud-sql-builder.d.ts +48 -0
  237. package/types/models/index.d.ts +1 -0
  238. package/types/models/mega-model.d.ts +138 -0
  239. package/types/models/model-crud.d.ts +82 -0
  240. package/types/models/mongo-crud.d.ts +59 -0
  241. package/types/test/index.d.ts +84 -0
  242. package/.env +0 -127
  243. package/sample/crud/apps/main/migrations/20260606000002-add-auth-to-users.js +0 -30
  244. package/sample/crud/apps/main/models/note.js +0 -71
  245. package/sample/crud/apps/main/models/user.js +0 -86
  246. package/sample/crud/package-lock.json +0 -5665
  247. package/sample/crud/yarn.lock +0 -2142
  248. package/sample/simple/package-lock.json +0 -1851
@@ -0,0 +1,233 @@
1
+ /**
2
+ * boot/CLI 컨텍스트 — `db/cache/bus/lock` 을 글로벌 키로 직접 조회하고, `workers` 는 `static name` 으로
3
+ * lookup 한다(앱 별명 변환 없음 — 둘 다 글로벌 자원). worker/scheduler CLI 도 같은 형태를 재사용한다
4
+ * (잡/스케줄의 `static bus`/`static lock` = 글로벌 키; 잡이 CPU 작업을 `ctx.workers` 로 오프로드 가능).
5
+ * @param {Object} global - global config.
6
+ * @param {{ debug?: Function, info?: Function, warn?: Function }} [logger]
7
+ * @returns {BootContext}
8
+ */
9
+ export function buildBootContext(global: Object, logger?: {
10
+ debug?: Function;
11
+ info?: Function;
12
+ warn?: Function;
13
+ }): BootContext;
14
+ /**
15
+ * 공유 어댑터 전수의 `healthCheck()` 를 `MegaHealth` 에 `<domain>:<globalKey>` 이름으로 등록한다.
16
+ * `/health/ready` 가 어댑터 생사를 실제로 반영하게 하는 배선 — `prepareRuntime` 이 connect 직후
17
+ * 호출한다(`health.autoChecks:false` 옵트아웃). 등록은 이름 기준 덮어쓰기라 재부팅(테스트)에도 멱등.
18
+ *
19
+ * @param {Array<{ domain: string, key: string, adapter: { healthCheck: () => Promise<{ ok: boolean }> } }>} [entries] -
20
+ * 대상 어댑터 엔트리(기본: 어댑터 매니저의 전체 등록분). 테스트 주입용.
21
+ * @returns {string[]} 등록한 체크 이름 목록.
22
+ */
23
+ export function registerAdapterHealthChecks(entries?: Array<{
24
+ domain: string;
25
+ key: string;
26
+ adapter: {
27
+ healthCheck: () => Promise<{
28
+ ok: boolean;
29
+ }>;
30
+ };
31
+ }>): string[];
32
+ /**
33
+ * 부트 step 정의 — 부팅 시퀀스의 한 단계.
34
+ * @typedef {Object} BootStep
35
+ * @property {string} name - step 이름(로그·prerequisite 에러 식별자).
36
+ * @property {string[]} [needs] - 선행 step 이 state 에 만들어 둬야 하는 키(prerequisite). 누락 시
37
+ * `boot.step_prerequisite` throw — step 순서 변경·누락 같은 배선 실수를 즉시 드러낸다.
38
+ * @property {'abort'|'warn'} [onFail] - 실패 정책. `'abort'`(기본) = fail-fast throw(M-1 정리 경로),
39
+ * `'warn'` = best-effort(warn 로그 후 다음 step 계속 — 부팅을 막으면 안 되는 부가 단계용).
40
+ * @property {(state: Record<string, any>) => Promise<void>|void} run - 단계 본체. 산출물은 state 에 쓴다.
41
+ */
42
+ /**
43
+ * step 배열 실행기 — 각 step 의 prerequisite 검증 → 실행 → 길목 debug 로그(start/done/tookMs).
44
+ * 실패는 step 의 `onFail` 정책을 따른다(기본 abort — 현재 부트 시퀀스 전 단계가 fail-fast).
45
+ *
46
+ * @param {BootStep[]} steps - 실행할 step 정의(순서 = 시퀀스 정본).
47
+ * @param {Record<string, any>} state - step 간 공유 상태(산출물 버스).
48
+ * @param {{ debug?: Function, warn?: Function }} [logger]
49
+ * @returns {Promise<void>}
50
+ * @throws {MegaConfigError} prerequisite 누락(`boot.step_prerequisite`) — 배선 오류는 즉시 abort.
51
+ */
52
+ export function runBootSteps(steps: BootStep[], state: Record<string, any>, logger?: {
53
+ debug?: Function;
54
+ warn?: Function;
55
+ }): Promise<void>;
56
+ /**
57
+ * 런타임 공통 준비 — {@link PREPARE_STEPS}(config → plugins → adapters → health-auto-checks →
58
+ * metrics → tracing → workers → ws-hub → boot-context)를 {@link runBootSteps} 로 실행한다.
59
+ * `bootApp`(서버)·`mega worker`/`mega scheduler`(CLI 호스트)가 **같은 순서**를 공유한다.
60
+ *
61
+ * @param {string} projectRoot
62
+ * @param {{ ping?: boolean, logger?: { debug?: Function, info?: Function, warn?: Function } }} [opts]
63
+ * @returns {Promise<{ global: Object, apps: Array<{ name: string, config: Object }>, host: MegaPluginHost, ctx: BootContext, wsHub: (MegaWsHub | null) }>}
64
+ */
65
+ export function prepareRuntime(projectRoot: string, { ping, logger }?: {
66
+ ping?: boolean;
67
+ logger?: {
68
+ debug?: Function;
69
+ info?: Function;
70
+ warn?: Function;
71
+ };
72
+ }): Promise<{
73
+ global: Object;
74
+ apps: Array<{
75
+ name: string;
76
+ config: Object;
77
+ }>;
78
+ host: MegaPluginHost;
79
+ ctx: BootContext;
80
+ wsHub: (MegaWsHub | null);
81
+ }>;
82
+ /**
83
+ * `global.server` 의 운영 옵션을 각 앱 Fastify 인스턴스 옵션으로 매핑한다(ADR-181, 04-data-models
84
+ * §MegaServerConfig). 미지정 키는 생략해 Fastify 기본값을 따른다. boot 가 모든 MegaApp 에 동일 주입한다
85
+ * (port/host 는 MegaServer.listen 이, 아래 런타임 옵션은 Fastify 인스턴스가 소비).
86
+ * - trustProxy / trustedProxies → Fastify `trustProxy`(프록시/LB 뒤 req.ip·X-Forwarded-* 신뢰).
87
+ * trustedProxies(목록)가 있으면 그것을, 없으면 trustProxy(boolean/number/string)를 그대로 넘긴다.
88
+ * - timeouts.requestMs → Fastify `requestTimeout`(요청 수신 제한, slow-loris 보호).
89
+ * - keepAliveMs → Fastify `keepAliveTimeout`(keep-alive 소켓 idle 제한, ALB 정합).
90
+ *
91
+ * 프로덕션(`NODE_ENV==='production'`)에서 trustProxy/trustedProxies 미설정이면 **부팅 warn 1회**(ADR-186).
92
+ * 프록시/LB 뒤에서 미설정 시 `req.protocol`/`req.ip` 가 프록시 기준으로 잡혀 secure 쿠키 누락·rate-limit
93
+ * 키 왜곡·CSRF Origin 오판으로 번진다 — 직접 listen 배포면 무시해도 되는 안내성 경고다.
94
+ *
95
+ * @param {any} server - `global.server` config(없으면 빈 객체).
96
+ * @param {{ logger?: { warn?: Function }, env?: Record<string, string|undefined> }} [opts] - warn 출력용
97
+ * logger 와 환경(테스트 주입용, 기본 `process.env`).
98
+ * @returns {{ trustProxy?: any, requestTimeout?: number, keepAliveTimeout?: number }}
99
+ */
100
+ export function serverFastifyOptions(server: any, { logger, env }?: {
101
+ logger?: {
102
+ warn?: Function;
103
+ };
104
+ env?: Record<string, string | undefined>;
105
+ }): {
106
+ trustProxy?: any;
107
+ requestTimeout?: number;
108
+ keepAliveTimeout?: number;
109
+ };
110
+ /**
111
+ * 프로젝트를 부팅한다 — {@link BOOT_STEPS}(runtime → before-boot-hook → logger → server → apps →
112
+ * cluster-transport → listen → after-boot-hook → shutdown-bridge)를 {@link runBootSteps} 로 실행한다.
113
+ *
114
+ * 어느 step 이든 실패하면 그대로 throw(fail-fast, 전 step onFail='abort'). 어댑터 connect 실패는
115
+ * 매니저가 LIFO cleanup 하고, 그 외 단계 실패(예: server.listen EADDRINUSE, beforeBoot hook throw)는
116
+ * 어댑터가 이미 connect 돼 `'adapters:disconnect'` MegaShutdown hook 이 등록된 상태라, 호출자가
117
+ * `MegaShutdown.now` 로 그 hook 을 실행해 정리해야 한다 — `bin/mega.js` 의 catch 가 이 정리 경로를
118
+ * 배선한다(M-1). 그러지 않으면 연결된 어댑터가 이벤트루프를 살려 프로세스가 hang 한다.
119
+ *
120
+ * @param {string} projectRoot - 프로젝트 루트 절대 경로(mega.config.js 가 있는 곳).
121
+ * @param {Object} [opts]
122
+ * @param {boolean} [opts.listen=true] - false 면 mount 까지만(테스트·검증용).
123
+ * @param {number} [opts.port] - listen 포트(미지정 시 server/global 기본).
124
+ * @param {string} [opts.host] - listen 호스트.
125
+ * @param {boolean} [opts.ping=false] - connectAll 시 healthCheck 까지 검증.
126
+ * @param {{ debug?: Function, info?: Function, warn?: Function }} [opts.logger] - 길목 debug 로그(선택).
127
+ * @returns {Promise<BootResult>}
128
+ */
129
+ export function bootApp(projectRoot: string, { listen, port, host: listenHost, ping, logger }?: {
130
+ listen?: boolean;
131
+ port?: number;
132
+ host?: string;
133
+ ping?: boolean;
134
+ logger?: {
135
+ debug?: Function;
136
+ info?: Function;
137
+ warn?: Function;
138
+ };
139
+ }): Promise<BootResult>;
140
+ /** prepareRuntime step 이름 시퀀스(정본) — introspection·테스트용. */
141
+ export const PREPARE_STEP_NAMES: readonly string[];
142
+ /** bootApp step 이름 시퀀스(정본) — introspection·테스트용. */
143
+ export const BOOT_STEP_NAMES: readonly string[];
144
+ /**
145
+ * 부팅 결과 핸들.
146
+ */
147
+ export type BootResult = {
148
+ /**
149
+ * - mount 된 MegaServer(listen=false 면 미-listen 상태).
150
+ */
151
+ server: MegaServer;
152
+ /**
153
+ * - 플러그인 호스트(install 완료, queryable).
154
+ */
155
+ host: MegaPluginHost;
156
+ /**
157
+ * - mega.config.js default export(global).
158
+ */
159
+ config: Object;
160
+ /**
161
+ * - 로드된 앱 config 목록.
162
+ */
163
+ apps: Array<{
164
+ name: string;
165
+ config: Object;
166
+ }>;
167
+ /**
168
+ * - 생성된 MegaApp 인스턴스(등록 순서).
169
+ */
170
+ megaApps: MegaApp[];
171
+ /**
172
+ * - lifecycle hook 에 넘긴 boot context.
173
+ */
174
+ ctx: BootContext;
175
+ /**
176
+ * - embedded wsHub(ADR-137, `wsHub.enabled` OFF 면 null).
177
+ */
178
+ wsHub: import("../lib/ws-hub.js").MegaWsHub | null;
179
+ /**
180
+ * - 공유 pino 로거(ADR-141, logger 비활성이면 null). CLI 시작 메시지 등에 재사용.
181
+ */
182
+ appLogger: import("pino").Logger | null;
183
+ };
184
+ /**
185
+ * lifecycle hook(beforeBoot/afterBoot/beforeShutdown)이 받는 boot context (L-2/ADR-123).
186
+ * `db/cache/bus/lock` 은 **글로벌 키 직접 lookup**(앱 별명 변환 없음 — boot 레벨은 별명 스코프 밖).
187
+ */
188
+ export type BootContext = {
189
+ /**
190
+ * - global config.
191
+ */
192
+ config: Object;
193
+ log?: {
194
+ debug?: Function;
195
+ info?: Function;
196
+ warn?: Function;
197
+ };
198
+ db: (globalKey: string) => import("../adapters/mega-adapter.js").MegaAdapter;
199
+ cache: (globalKey: string) => import("../adapters/mega-adapter.js").MegaAdapter;
200
+ bus: (globalKey: string) => import("../adapters/mega-adapter.js").MegaAdapter;
201
+ lock: (globalKey: string) => import("../adapters/mega-adapter.js").MegaAdapter;
202
+ /**
203
+ * - `ctx.workers.<name>.run(task)` (ADR-124).
204
+ */
205
+ workers: Record<string, import("../lib/mega-worker.js").MegaWorker>;
206
+ };
207
+ /**
208
+ * 부트 step 정의 — 부팅 시퀀스의 한 단계.
209
+ */
210
+ export type BootStep = {
211
+ /**
212
+ * - step 이름(로그·prerequisite 에러 식별자).
213
+ */
214
+ name: string;
215
+ /**
216
+ * - 선행 step 이 state 에 만들어 둬야 하는 키(prerequisite). 누락 시
217
+ * `boot.step_prerequisite` throw — step 순서 변경·누락 같은 배선 실수를 즉시 드러낸다.
218
+ */
219
+ needs?: string[];
220
+ /**
221
+ * - 실패 정책. `'abort'`(기본) = fail-fast throw(M-1 정리 경로),
222
+ * `'warn'` = best-effort(warn 로그 후 다음 step 계속 — 부팅을 막으면 안 되는 부가 단계용).
223
+ */
224
+ onFail?: "abort" | "warn";
225
+ /**
226
+ * - 단계 본체. 산출물은 state 에 쓴다.
227
+ */
228
+ run: (state: Record<string, any>) => Promise<void> | void;
229
+ };
230
+ import { MegaPluginHost } from '../lib/mega-plugin.js';
231
+ import { MegaWsHub } from '../lib/ws-hub.js';
232
+ import { MegaServer } from './mega-server.js';
233
+ import { MegaApp } from './mega-app.js';
@@ -0,0 +1,52 @@
1
+ /**
2
+ * 여러 워커의 Prometheus exposition 텍스트를 하나로 합산한다(순수 — 테스트 가능).
3
+ *
4
+ * - **counter / histogram(_bucket/_sum/_count)**: 동일 `name{labels}` 끼리 값 **합산**(클러스터 누적).
5
+ * - **gauge**: 합산(메모리·CPU 는 클러스터 합이 유의미). 단 프로세스별 gauge(uptime 등)는 합이 N배가 되는
6
+ * 문서화된 한계 — prom-client 기본도 gauge=sum. `_info`/`target_info` 메타는 합산 대신 **첫 값 유지**(=1).
7
+ * - `# HELP`/`# TYPE` 는 패밀리별 1줄로 dedupe 하고, 패밀리(TYPE 이름) 단위로 묶어 재출력한다.
8
+ *
9
+ * @param {string[]} texts - 각 워커 `collect()` 결과(빈 문자열 허용).
10
+ * @returns {string} 합산된 exposition 텍스트(끝 개행 포함). 입력이 모두 비면 빈 문자열.
11
+ */
12
+ export function mergeExposition(texts: string[]): string;
13
+ /**
14
+ * 워커 프로세스에 collect 응답기를 설치한다 — 마스터의 `collect` 요청에 자기 `MegaMetrics.collect()` 로 회신.
15
+ * 클러스터 워커가 아니면 no-op. `process.on('message')` 다중 리스너라 MegaCluster shutdown 핸들러와 공존한다.
16
+ *
17
+ * IPC 경로는 fork 워커 안에서만 실행돼 부모 v8 커버리지로 측정 불가다. cluster/process 를 주입 seam 으로
18
+ * 분리해 fake 로 in-process 단위 검증한다(per ADR-165 — `MegaCluster` 와 동일 패턴). 프로덕션 호출부는
19
+ * 인자를 안 넘겨 실 전역을 쓴다.
20
+ * @param {{ _cluster?: import('node:cluster').Cluster, _proc?: NodeJS.Process }} [opts]
21
+ * @returns {void}
22
+ */
23
+ export function installWorkerResponder({ _cluster, _proc }?: {
24
+ _cluster?: import("node:cluster").Cluster;
25
+ _proc?: NodeJS.Process;
26
+ }): void;
27
+ /**
28
+ * 마스터 프로세스에 집계기를 설치한다 — 워커의 `request` 를 받아 전 워커에 fan-out, 회신을 모아 합산해 회신.
29
+ * 마스터가 아니면 no-op. `cluster.on('message')` 로 모든 워커 메시지를 한 핸들러로 받는다.
30
+ *
31
+ * IPC 경로는 마스터 안에서만 실행돼 부모 v8 커버리지로 측정 불가다 — cluster 를 주입 seam 으로 분리해
32
+ * fake 로 in-process 단위 검증한다(per ADR-165).
33
+ * @param {{ timeoutMs?: number, _cluster?: import('node:cluster').Cluster }} [opts] - 라운드 수집 timeout(전원 미응답 시 부분 합산). 기본 2000ms.
34
+ * @returns {void}
35
+ */
36
+ export function installPrimaryAggregator({ timeoutMs, _cluster }?: {
37
+ timeoutMs?: number;
38
+ _cluster?: import("node:cluster").Cluster;
39
+ }): void;
40
+ /**
41
+ * 현재 프로세스 기준 메트릭을 수집한다 — 클러스터 워커면 마스터를 통해 **전 워커 합산**, 단일 프로세스면 로컬.
42
+ * `/metrics` 라우트와 `/demo/metrics` 가 쓴다. timeout/마스터 부재 시 로컬 `collect()` 로 폴백(스크레이프가 안
43
+ * 멈추도록).
44
+ * cluster/process 는 주입 seam(테스트용 — per ADR-165). 프로덕션 호출부는 인자를 안 넘겨 실 전역을 쓴다.
45
+ * @param {{ timeoutMs?: number, _cluster?: import('node:cluster').Cluster, _proc?: NodeJS.Process }} [opts] - 응답 대기 timeout(라운드 timeout 보다 넉넉히). 기본 2500ms.
46
+ * @returns {Promise<string>} Prometheus exposition 텍스트.
47
+ */
48
+ export function collectCluster({ timeoutMs, _cluster, _proc }?: {
49
+ timeoutMs?: number;
50
+ _cluster?: import("node:cluster").Cluster;
51
+ _proc?: NodeJS.Process;
52
+ }): Promise<string>;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * 프로젝트 루트에서 mega.config.js + 활성 앱 config 들 로드 + 검증.
3
+ * @param {string} projectRoot - 프로젝트 루트 절대 경로
4
+ * @returns {Promise<{global: Object, apps: Array<{name: string, config: Object}>}>}
5
+ * @throws {MegaConfigError}
6
+ */
7
+ export function loadAndValidateConfig(projectRoot: string): Promise<{
8
+ global: Object;
9
+ apps: Array<{
10
+ name: string;
11
+ config: Object;
12
+ }>;
13
+ }>;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * 메인 config 검증.
3
+ * @param {Record<string, any>} globalConfig - mega.config.js export 객체
4
+ * @throws {MegaConfigError}
5
+ */
6
+ export function validateGlobalConfig(globalConfig: Record<string, any>): void;
7
+ /**
8
+ * 앱 config 검증.
9
+ * @param {Record<string, any>} appConfig - apps/<name>/app.config.js export 객체
10
+ * @param {string} expectedFolderName - 폴더명 (apps/<name>)
11
+ * @param {Record<string, any>} globalConfig - 메인 (Shared-Reference 키 cross-check 용)
12
+ * @throws {MegaConfigError}
13
+ */
14
+ export function validateAppConfig(appConfig: Record<string, any>, expectedFolderName: string, globalConfig: Record<string, any>): void;
15
+ /**
16
+ * 모든 앱 cross-validate: 호스트 충돌 감지 (ADR-067).
17
+ * @param {Array<{ name: string, config: Record<string, any> }>} apps
18
+ * @throws {MegaConfigError}
19
+ */
20
+ export function validateHostCollisions(apps: Array<{
21
+ name: string;
22
+ config: Record<string, any>;
23
+ }>): void;
24
+ /**
25
+ * 가까운 키 추천 (Levenshtein 거리 기반).
26
+ * @param {string} input
27
+ * @param {readonly string[]} known
28
+ * @returns {string | undefined}
29
+ */
30
+ export function suggestKey(input: string, known: readonly string[]): string | undefined;
@@ -0,0 +1,103 @@
1
+ /**
2
+ * @typedef {object} AdapterAliasMaps - 앱의 `app.config.js` 별명 선언 (alias → globalKey).
3
+ * @property {Record<string, string>} [databases]
4
+ * @property {Record<string, string>} [caches]
5
+ * @property {Record<string, string>} [buses]
6
+ * @property {Record<string, string>} [locks]
7
+ */
8
+ /**
9
+ * @typedef {object} AdapterAccessors
10
+ * @property {(alias: string) => import('../adapters/mega-adapter.js').MegaAdapter} db
11
+ * @property {(alias: string) => import('../adapters/mega-adapter.js').MegaAdapter} cache
12
+ * @property {(alias: string) => import('../adapters/mega-adapter.js').MegaAdapter} bus
13
+ * @property {(alias: string) => import('../adapters/mega-adapter.js').MegaAdapter} lock
14
+ */
15
+ /**
16
+ * 앱의 별명 맵으로 `db/cache/bus/lock` 접근자 4종을 만든다. 접근자는 요청과 무관하게 안정적이므로
17
+ * **앱당 한 번** 만들어 재사용한다(MegaApp 생성자). 각 접근자는 호출 시 별명→globalKey→공유
18
+ * 인스턴스로 해석하고, 미선언 별명이면 throw.
19
+ *
20
+ * @param {AdapterAliasMaps} [aliasMaps] - 앱 별명 선언. 없으면 모든 접근자가 미선언 throw.
21
+ * @param {string} [appName] - 에러 메시지용 앱 이름.
22
+ * @returns {AdapterAccessors}
23
+ */
24
+ export function buildAdapterAccessors(aliasMaps?: AdapterAliasMaps, appName?: string): AdapterAccessors;
25
+ /**
26
+ * HTTP 요청 단위 ctx 를 만든다 (canonical handler 시그니처 `(req, res, ctx)`, ADR-074/docs/03).
27
+ *
28
+ * canonical ctx 표면: `app / log / requestId / req / reply` + `db/cache/bus` 접근자 +
29
+ * `workers`(CPU 워커 풀, ADR-124) + `tracer`(사용자 직접 span — `ctx.tracer.span`,
30
+ * ADR-126). (i18n `t`, `session` 객체, `services` 자동 DI 등 나머지 canonical 필드도 같은 방식으로 추가된다.)
31
+ *
32
+ * `app` 이 null(standalone Router — 앱에 바인딩 안 된 테스트 경로)이면 `db/cache/bus` 접근자는
33
+ * 생략된다(해당 ctx 로는 어댑터 lookup 불가). `workers` 는 글로벌 자원이라 app 무관하게 항상 노출한다
34
+ * (미등록 이름 접근 시 worker.not_registered fail-fast — 워커 0개면 접근 자체가 없어 무해).
35
+ *
36
+ * @param {object} args
37
+ * @param {import('./mega-app.js').MegaApp | null} args.app
38
+ * @param {import('fastify').FastifyRequest} args.req
39
+ * @param {import('fastify').FastifyReply} args.reply
40
+ * @returns {Record<string, any>}
41
+ */
42
+ export function buildHttpCtx({ app, req, reply }: {
43
+ app: import("./mega-app.js").MegaApp | null;
44
+ req: import("fastify").FastifyRequest;
45
+ reply: import("fastify").FastifyReply;
46
+ }): Record<string, any>;
47
+ /**
48
+ * 요청당 ctx 를 **한 번만** 만들고 `req` 에 캐싱해 재사용한다(ADR-134). 글로벌 미들웨어(preHandler)와
49
+ * 라우트 핸들러가 같은 요청에서 호출하면 **동일 ctx 객체**를 받으므로, 미들웨어가 ctx 에 심은 값
50
+ * (예: `ctx.user`)을 핸들러가 그대로 본다. 첫 호출이 build, 이후 호출은 캐시 반환.
51
+ *
52
+ * 캐시 키는 비열거 Symbol 이라 `{...ctx}`/`Object.keys(req)` 에 노출되지 않는다. `req` 는 Fastify 가
53
+ * 요청마다 새로 만드는 객체라 요청 스코프로 자연히 격리된다(요청 종료 시 GC).
54
+ *
55
+ * @param {object} args
56
+ * @param {import('./mega-app.js').MegaApp | null} args.app
57
+ * @param {import('fastify').FastifyRequest} args.req
58
+ * @param {import('fastify').FastifyReply} args.reply
59
+ * @returns {Record<string, any>}
60
+ */
61
+ export function getHttpCtx({ app, req, reply }: {
62
+ app: import("./mega-app.js").MegaApp | null;
63
+ req: import("fastify").FastifyRequest;
64
+ reply: import("fastify").FastifyReply;
65
+ }): Record<string, any>;
66
+ /**
67
+ * **lazy** HTTP ctx — 실제 ctx 빌드를 첫 속성 접근 시점까지 미루는 요청당 프록시 (G1 H-1, ADR-214).
68
+ *
69
+ * hot path 단일 최대 프레임워크 비용이 "핸들러가 ctx 를 안 써도 매 요청 무조건 buildHttpCtx"
70
+ * (1,615 B + ≈0.7 µs/req, CPU 2.3% — audit-G1 실측)였다. 이 프록시는 생성 비용이 객체 1개 수준이고,
71
+ * 핸들러·미들웨어가 ctx 의 속성을 **처음 만질 때만** {@link getHttpCtx} 로 실 ctx 를 만든다(이후 캐시).
72
+ *
73
+ * 호환성: canonical 시그니처 `(req, reply, ctx)` 는 그대로 — 모든 핸들러가 여전히 3번째 인자를 받고,
74
+ * 참조하는 순간부터는 기존과 동일한 실 ctx 표면(ADR-134 요청당 공유 포함)이다. 프록시 자체도 요청당
75
+ * 1개로 캐시되어 미들웨어와 핸들러가 **동일 객체**(`===`)를 받는다. 모든 트랩이 실 ctx 로 위임되므로
76
+ * `in`/spread/`Object.keys`/getter·setter(`ctx.user=`) 동작이 보존된다.
77
+ *
78
+ * @param {object} args
79
+ * @param {import('./mega-app.js').MegaApp | null} args.app
80
+ * @param {import('fastify').FastifyRequest} args.req
81
+ * @param {import('fastify').FastifyReply} args.reply
82
+ * @returns {Record<string, any>}
83
+ */
84
+ export function getLazyHttpCtx({ app, req, reply }: {
85
+ app: import("./mega-app.js").MegaApp | null;
86
+ req: import("fastify").FastifyRequest;
87
+ reply: import("fastify").FastifyReply;
88
+ }): Record<string, any>;
89
+ /**
90
+ * - 앱의 `app.config.js` 별명 선언 (alias → globalKey).
91
+ */
92
+ export type AdapterAliasMaps = {
93
+ databases?: Record<string, string>;
94
+ caches?: Record<string, string>;
95
+ buses?: Record<string, string>;
96
+ locks?: Record<string, string>;
97
+ };
98
+ export type AdapterAccessors = {
99
+ db: (alias: string) => import("../adapters/mega-adapter.js").MegaAdapter;
100
+ cache: (alias: string) => import("../adapters/mega-adapter.js").MegaAdapter;
101
+ bus: (alias: string) => import("../adapters/mega-adapter.js").MegaAdapter;
102
+ lock: (alias: string) => import("../adapters/mega-adapter.js").MegaAdapter;
103
+ };
@@ -0,0 +1,79 @@
1
+ /**
2
+ * 자동 envelope (ADR-018). preSerialization 훅의 마지막 단계에서 호출되어
3
+ * raw data → `{ ok:true, data, meta }`.
4
+ *
5
+ * transform 미들웨어(ADR-091)가 먼저 raw data 를 변환했으면, 그 변환 결과 위에 envelope 만 감쌈
6
+ * (실행 순서: transform → wrap, ADR-076 / ADR-091).
7
+ *
8
+ * 이미 envelope 형태로 보낸 경우(`{ ok:false, error: ... }` 등 명시) 는 그대로 통과 —
9
+ * 글로벌 에러 핸들러가 만든 error envelope 의 이중 wrap 을 방지.
10
+ *
11
+ * @param {Record<string, any>} req - Fastify request
12
+ * @param {Record<string | symbol, any>} reply - Fastify reply
13
+ * @param {any} payload - 핸들러/transform 이 만든 raw data 또는 이미 만들어진 envelope
14
+ * @returns {Object | any} envelope 또는 (이미 envelope 면) 원본 payload
15
+ */
16
+ export function wrapEnvelope(req: Record<string, any>, reply: Record<string | symbol, any>, payload: any): Object | any;
17
+ /**
18
+ * 에러 envelope (ADR-014). 글로벌 에러 핸들러가 사용.
19
+ * @param {Record<string, any>} req
20
+ * @param {Record<string | symbol, any>} reply
21
+ * @param {{ code: string, message?: string, details?: any }} error
22
+ * @returns {{ ok: false, error: { code: string, message: string, details?: any }, meta: Object }}
23
+ */
24
+ export function errorEnvelope(req: Record<string, any>, reply: Record<string | symbol, any>, error: {
25
+ code: string;
26
+ message?: string;
27
+ details?: any;
28
+ }): {
29
+ ok: false;
30
+ error: {
31
+ code: string;
32
+ message: string;
33
+ details?: any;
34
+ };
35
+ meta: Object;
36
+ };
37
+ /**
38
+ * 라우트 `schema.response` 를 envelope 모양으로 합성한다.
39
+ *
40
+ * 배경: 자동 envelope(ADR-018)는 preSerialization 마지막에 raw data 를 `{ ok, data, meta }` 로
41
+ * 감싸는데, 사용자가 raw data 모양의 response schema 를 선언하면 Fastify 직렬화기가 **envelope 를
42
+ * 그 raw 스키마로 직렬화해 ok/data/meta 가 통째로 제거**된다(silent 데이터 소실). 그래서 등록
43
+ * 시점(onRoute)에 각 상태코드 스키마를 `{ ok, data: <사용자 스키마>, error, meta }` 로 재작성한다 —
44
+ * 사용자는 계속 raw data 모양만 선언하고(ADR-091), strict 직렬화(ADR-020: 선언 외 필드 제거)는
45
+ * data 안에서 그대로 동작하며, OpenAPI 명세(@fastify/swagger 가 schema 수집)도 실제 와이어 모양과
46
+ * 일치하게 된다.
47
+ *
48
+ * 합성 제외(원본 유지) 3종:
49
+ * - `type: 'string'` 스키마 — 문자열 payload 는 Fastify 가 preSerialization(envelope wrap) 자체를
50
+ * 건너뛰므로(raw 전송, 예: /metrics) envelope 모양으로 바꾸면 오히려 직렬화가 깨진다.
51
+ * - 이미 envelope 모양(`properties.ok` 보유) — 사용자가 envelope 전체를 직접 선언한 경우.
52
+ * - 스키마가 object 가 아닌 항목 — 알 수 없는 형식은 건드리지 않는다(fail-safe).
53
+ *
54
+ * Fastify v5 의 media-type 형식(`{ content: { 'application/json': { schema } } }`)은 내부 schema
55
+ * 에 같은 규칙을 적용한다.
56
+ *
57
+ * @param {Record<string, any>} response - 라우트 `schema.response` (상태코드/패턴 → JSON Schema).
58
+ * @returns {Record<string, any>} envelope 모양으로 합성된 새 response 객체 (원본 불변).
59
+ */
60
+ export function synthesizeEnvelopeResponseSchema(response: Record<string, any>): Record<string, any>;
61
+ /**
62
+ * 응답 envelope 헬퍼 (ADR-014, ADR-018).
63
+ *
64
+ * 모든 HTTP 응답은 `{ ok, data|error, meta }` 형태로 통일된다.
65
+ * wrapEnvelope 는 preSerialization 의 마지막 단계에서 raw data 를 감싸고,
66
+ * errorEnvelope 는 글로벌 에러 핸들러에서 에러를 감싼다.
67
+ *
68
+ * @module core/envelope
69
+ */
70
+ /** request 시작 시간 기록용 symbol (meta.took_ms 계산). reply 객체에 부착. */
71
+ export const REPLY_START_SYMBOL: unique symbol;
72
+ /**
73
+ * 프레임워크가 만든 envelope 임을 표시하는 비열거 마킹 symbol.
74
+ *
75
+ * 이중 wrap 방지 판별을 키 모양 추측(duck-typing)이 아니라 이 마킹으로 한다 — 핸들러가 우연히
76
+ * `{ ok, data }` 모양의 도메인 데이터(예: 외부 API 프록시 응답)를 반환해도 정상적으로 data 로
77
+ * 감싸진다. 비열거라 JSON 직렬화·spread 에는 나타나지 않는다.
78
+ */
79
+ export const ENVELOPE_MARK: unique symbol;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Fastify setErrorHandler 에 등록할 핸들러 빌더.
3
+ *
4
+ * 우선순위:
5
+ * 1) AJV validation 에러 → MegaValidationError 변환 (ADR-090)
6
+ * 2) MegaHttpError → 그대로 envelope (status/code/message/details 보존)
7
+ * 3) MegaError → 500 + code/message 보존 (도메인 에러지만 HTTP status 없음)
8
+ * 4) 그 외 일반 Error → MegaInternalError (스택·메시지는 로그만, envelope 엔 마스킹)
9
+ *
10
+ * @param {{ exposeInternalDetails?: boolean }} [opts]
11
+ * - exposeInternalDetails: true 면 일반 Error 의 message 를 envelope 에 노출.
12
+ * 기본 false (보안 — 내부 구현 누출 방지).
13
+ * @returns {(error: Error, req: any, reply: any) => any}
14
+ */
15
+ export function buildErrorHandler({ exposeInternalDetails }?: {
16
+ exposeInternalDetails?: boolean;
17
+ }): (error: Error, req: any, reply: any) => any;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * 폼 바디 파서 자동 등록 결과 요약(디버그·테스트용).
3
+ * @typedef {Object} FormbodySummary
4
+ * @property {boolean} enabled - 등록 여부.
5
+ */
6
+ /**
7
+ * views 설정이 서버사이드 렌더를 켰는지 (Boolean — `has*`). `views.dir` 가 비지 않은 문자열일 때만 true.
8
+ * registerTemplate 의 옵트인 판정과 같은 기준이라 폼 파싱이 뷰 등록과 정확히 짝을 이룬다.
9
+ * @param {unknown} views
10
+ * @returns {boolean}
11
+ */
12
+ export function hasServerViews(views: unknown): boolean;
13
+ /**
14
+ * Fastify 인스턴스에 `@fastify/formbody` 를 등록한다 — 서버사이드 뷰를 켠 앱에 한해 옵트인.
15
+ *
16
+ * `views` 가 없으면 **미등록**(JSON·text 만 파싱, 기존 동작 유지). 호출 시점은 라우트 등록 이전이어야
17
+ * 한다(content-type 파서는 글로벌이라 등록 후 도착하는 모든 요청에 적용) — MegaApp 생성자가 그 지점이다.
18
+ *
19
+ * @param {import('fastify').FastifyInstance} fastify - 대상 앱 Fastify 인스턴스.
20
+ * @param {Object} opts
21
+ * @param {unknown} opts.views - `MegaViewsConfig`(dir/layoutDir/...). 서버 뷰 옵트인 판정에 쓴다.
22
+ * @param {string} [opts.appName] - 앱 이름(로그용).
23
+ * @param {{ debug?: Function }} [opts.logger] - 흐름 길목 debug 로그(선택).
24
+ * @returns {FormbodySummary}
25
+ */
26
+ export function registerFormbody(fastify: import("fastify").FastifyInstance, { views, appName, logger }?: {
27
+ views: unknown;
28
+ appName?: string;
29
+ logger?: {
30
+ debug?: Function;
31
+ };
32
+ }): FormbodySummary;
33
+ /**
34
+ * 폼 바디 파서 자동 등록 결과 요약(디버그·테스트용).
35
+ */
36
+ export type FormbodySummary = {
37
+ /**
38
+ * - 등록 여부.
39
+ */
40
+ enabled: boolean;
41
+ };