mega-framework 0.1.5 → 0.1.7

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 (236) hide show
  1. package/bin/mega-ws-hub.js +2 -2
  2. package/package.json +32 -8
  3. package/sample/crud/.env +156 -8
  4. package/sample/crud/.env.example +153 -28
  5. package/sample/crud/.mega/journal/history/20260612092543-create-users.json +261 -0
  6. package/sample/crud/.mega/journal/snapshot.json +261 -0
  7. package/sample/crud/apps/main/controllers/auth-controller.js +22 -14
  8. package/sample/crud/apps/main/controllers/web-controller.js +7 -5
  9. package/sample/crud/apps/main/migrations/20260606000001-create-users.js +91 -13
  10. package/sample/crud/apps/main/migrations/20260606000002-create-boards.js +165 -0
  11. package/sample/crud/apps/main/migrations/20260606000003-create-logs.js +107 -0
  12. package/sample/crud/apps/main/models/log-partition-model.js +105 -0
  13. package/sample/crud/apps/main/models/note-model.js +79 -0
  14. package/sample/crud/apps/main/models/user-level-model.js +24 -0
  15. package/sample/crud/apps/main/models/user-model.js +146 -0
  16. package/sample/crud/apps/main/models/user-type-model.js +21 -0
  17. package/sample/crud/apps/main/models/wallet-model.js +24 -0
  18. package/sample/crud/apps/main/routes/users.js +55 -10
  19. package/sample/crud/apps/main/schedules/log-partition-schedule.js +33 -0
  20. package/sample/crud/apps/main/services/auth-service.js +39 -24
  21. package/sample/crud/apps/main/services/log-partition-service.js +101 -0
  22. package/sample/crud/apps/main/services/note-service.js +6 -6
  23. package/sample/crud/apps/main/services/redis-demo-service.js +3 -3
  24. package/sample/crud/apps/main/services/user-service.js +62 -21
  25. package/sample/crud/apps/main/views/auth/login.ejs +6 -6
  26. package/sample/crud/apps/main/views/auth/register.ejs +46 -5
  27. package/sample/crud/apps/main/views/users/edit.ejs +42 -5
  28. package/sample/crud/apps/main/views/users/list.ejs +6 -2
  29. package/sample/crud/apps/main/views/users/new.ejs +56 -4
  30. package/sample/crud/docs/log_partition_design.mm.md +23 -0
  31. package/sample/crud/mega.config.js +63 -3
  32. package/sample/crud/package.json +3 -3
  33. package/sample/crud/scripts/start-ws-hub.sh +2 -2
  34. package/sample/simple/package.json +2 -2
  35. package/src/adapters/adapter-manager.js +2 -1
  36. package/src/adapters/adapter-options.js +30 -0
  37. package/src/adapters/maria-adapter.js +26 -3
  38. package/src/adapters/mega-db-adapter.js +7 -1
  39. package/src/adapters/mongo-adapter.js +19 -1
  40. package/src/adapters/postgres-adapter.js +25 -2
  41. package/src/adapters/sqlite-adapter.js +20 -1
  42. package/src/cli/commands/new.js +13 -3
  43. package/src/cli/commands/scaffold.js +137 -33
  44. package/src/cli/generators/index.js +82 -2
  45. package/src/cli/index.js +478 -104
  46. package/src/core/ajv-mapper.js +27 -2
  47. package/src/core/boot.js +485 -237
  48. package/src/core/cluster-metrics.js +13 -4
  49. package/src/core/config-validator.js +25 -0
  50. package/src/core/ctx-builder.js +6 -2
  51. package/src/core/envelope.js +112 -12
  52. package/src/core/hub-link.js +65 -4
  53. package/src/core/i18n.js +11 -1
  54. package/src/core/index.js +6 -2
  55. package/src/core/mega-app.js +223 -481
  56. package/src/core/mega-cluster.js +54 -13
  57. package/src/core/mega-server.js +40 -9
  58. package/src/core/migration/dialect-registry.js +107 -0
  59. package/src/core/migration/dialects/README.md +62 -0
  60. package/src/core/migration/dialects/maria.js +496 -0
  61. package/src/core/migration/dialects/mongo.js +824 -0
  62. package/src/core/migration/dialects/postgres.js +563 -0
  63. package/src/core/migration/dialects/sqlite.js +476 -0
  64. package/src/core/migration/differ.js +456 -0
  65. package/src/core/migration/generate.js +508 -0
  66. package/src/core/migration/journal.js +167 -0
  67. package/src/core/migration/model-scan.js +84 -0
  68. package/src/core/migration/mongo-migration-db.js +97 -0
  69. package/src/core/migration/schema-builder.js +400 -0
  70. package/src/core/migration/schema-validator.js +315 -0
  71. package/src/core/migration-lock.js +205 -0
  72. package/src/core/migration-runner.js +166 -38
  73. package/src/core/multipart.js +28 -5
  74. package/src/core/pipeline.js +129 -0
  75. package/src/core/router.js +70 -65
  76. package/src/core/scope-registry.js +0 -1
  77. package/src/core/security.js +67 -9
  78. package/src/core/workers-manager.js +12 -1
  79. package/src/core/ws-cluster.js +10 -3
  80. package/src/core/ws-message.js +48 -4
  81. package/src/core/ws-presence.js +624 -0
  82. package/src/core/ws-roster.js +4 -1
  83. package/src/core/ws-upgrade.js +118 -12
  84. package/src/index.js +1 -1
  85. package/src/lib/hub-protocol.js +29 -0
  86. package/src/lib/mega-health.js +25 -4
  87. package/src/lib/mega-job-queue.js +98 -21
  88. package/src/lib/mega-job.js +29 -0
  89. package/src/lib/mega-logger.js +1 -1
  90. package/src/lib/mega-metrics.js +3 -12
  91. package/src/lib/mega-plugin.js +34 -3
  92. package/src/lib/mega-schedule.js +40 -22
  93. package/src/lib/mega-shutdown.js +162 -49
  94. package/src/lib/mega-tracing.js +66 -19
  95. package/src/lib/mega-worker.js +5 -1
  96. package/src/lib/otel-resource.js +36 -0
  97. package/src/{cli → lib}/ws-hub.js +51 -8
  98. package/src/models/crud-sql-builder.js +133 -0
  99. package/src/models/mega-model.js +82 -2
  100. package/src/models/model-crud.js +483 -0
  101. package/src/models/mongo-crud.js +285 -0
  102. package/templates/model/code-mongo.tpl +35 -0
  103. package/templates/model/code.tpl +15 -1
  104. package/templates/model/test-mongo.tpl +38 -0
  105. package/templates/model/test.tpl +4 -0
  106. package/types/adapters/adapter-manager.d.ts +95 -0
  107. package/types/adapters/adapter-options.d.ts +91 -0
  108. package/types/adapters/file-adapter.d.ts +94 -0
  109. package/types/adapters/file-session-adapter.d.ts +101 -0
  110. package/types/adapters/index.d.ts +20 -0
  111. package/types/adapters/maria-adapter.d.ts +115 -0
  112. package/types/adapters/mega-adapter.d.ts +215 -0
  113. package/types/adapters/mega-bus-adapter.d.ts +45 -0
  114. package/types/adapters/mega-cache-adapter.d.ts +47 -0
  115. package/types/adapters/mega-db-adapter.d.ts +47 -0
  116. package/types/adapters/mega-lock-adapter.d.ts +62 -0
  117. package/types/adapters/mega-log-sink-adapter.d.ts +15 -0
  118. package/types/adapters/mega-session-adapter.d.ts +32 -0
  119. package/types/adapters/mongo-adapter.d.ts +139 -0
  120. package/types/adapters/nats-adapter.d.ts +108 -0
  121. package/types/adapters/postgres-adapter.d.ts +139 -0
  122. package/types/adapters/redis-adapter.d.ts +70 -0
  123. package/types/adapters/redis-session-adapter.d.ts +82 -0
  124. package/types/adapters/redlock-adapter.d.ts +149 -0
  125. package/types/adapters/registry.d.ts +46 -0
  126. package/types/adapters/sqlite-adapter.d.ts +106 -0
  127. package/types/auth/index.d.ts +24 -0
  128. package/types/cli/commands/console-cmd.d.ts +37 -0
  129. package/types/cli/commands/new.d.ts +16 -0
  130. package/types/cli/commands/routes.d.ts +36 -0
  131. package/types/cli/commands/scaffold.d.ts +78 -0
  132. package/types/cli/commands/test-cmd.d.ts +14 -0
  133. package/types/cli/generators/index.d.ts +112 -0
  134. package/types/cli/index.d.ts +249 -0
  135. package/types/cli/template-engine.d.ts +40 -0
  136. package/types/core/ajv-mapper.d.ts +27 -0
  137. package/types/core/boot.d.ts +233 -0
  138. package/types/core/cluster-metrics.d.ts +52 -0
  139. package/types/core/config-loader.d.ts +13 -0
  140. package/types/core/config-validator.d.ts +30 -0
  141. package/types/core/ctx-builder.d.ts +80 -0
  142. package/types/core/envelope.d.ts +79 -0
  143. package/types/core/error-mapper.d.ts +17 -0
  144. package/types/core/formbody.d.ts +41 -0
  145. package/types/core/hub-link.d.ts +264 -0
  146. package/types/core/i18n.d.ts +178 -0
  147. package/types/core/index.d.ts +28 -0
  148. package/types/core/mega-app.d.ts +529 -0
  149. package/types/core/mega-cluster.d.ts +104 -0
  150. package/types/core/mega-server.d.ts +91 -0
  151. package/types/core/mega-service.d.ts +31 -0
  152. package/types/core/migration/dialect-registry.d.ts +22 -0
  153. package/types/core/migration/dialects/maria.d.ts +99 -0
  154. package/types/core/migration/dialects/mongo.d.ts +89 -0
  155. package/types/core/migration/dialects/postgres.d.ts +117 -0
  156. package/types/core/migration/dialects/sqlite.d.ts +111 -0
  157. package/types/core/migration/differ.d.ts +47 -0
  158. package/types/core/migration/generate.d.ts +56 -0
  159. package/types/core/migration/journal.d.ts +52 -0
  160. package/types/core/migration/model-scan.d.ts +19 -0
  161. package/types/core/migration/mongo-migration-db.d.ts +7 -0
  162. package/types/core/migration/schema-builder.d.ts +197 -0
  163. package/types/core/migration/schema-validator.d.ts +20 -0
  164. package/types/core/migration-lock.d.ts +33 -0
  165. package/types/core/migration-runner.d.ts +101 -0
  166. package/types/core/multipart.d.ts +86 -0
  167. package/types/core/openapi.d.ts +62 -0
  168. package/types/core/pipeline.d.ts +92 -0
  169. package/types/core/router.d.ts +159 -0
  170. package/types/core/routes-loader.d.ts +21 -0
  171. package/types/core/scope-registry.d.ts +14 -0
  172. package/types/core/security.d.ts +77 -0
  173. package/types/core/services-loader.d.ts +27 -0
  174. package/types/core/session-cleanup-schedule.d.ts +19 -0
  175. package/types/core/session-store.d.ts +18 -0
  176. package/types/core/session.d.ts +77 -0
  177. package/types/core/static-assets.d.ts +73 -0
  178. package/types/core/template.d.ts +106 -0
  179. package/types/core/workers-manager.d.ts +79 -0
  180. package/types/core/ws-cluster.d.ts +208 -0
  181. package/types/core/ws-compression.d.ts +112 -0
  182. package/types/core/ws-controller.d.ts +65 -0
  183. package/types/core/ws-message.d.ts +106 -0
  184. package/types/core/ws-presence.d.ts +273 -0
  185. package/types/core/ws-roster.d.ts +96 -0
  186. package/types/core/ws-upgrade.d.ts +231 -0
  187. package/types/errors/config-error.d.ts +10 -0
  188. package/types/errors/http-errors.d.ts +120 -0
  189. package/types/errors/index.d.ts +3 -0
  190. package/types/errors/mega-error.d.ts +32 -0
  191. package/types/index.d.ts +39 -0
  192. package/types/lib/asp/config.d.ts +49 -0
  193. package/types/lib/asp/crypto.d.ts +43 -0
  194. package/types/lib/asp/errors.d.ts +30 -0
  195. package/types/lib/asp/nonce-cache.d.ts +52 -0
  196. package/types/lib/asp/plugin.d.ts +30 -0
  197. package/types/lib/asp/ws-terminator.d.ts +45 -0
  198. package/types/lib/env-mapper.d.ts +14 -0
  199. package/types/lib/hub-protocol.d.ts +106 -0
  200. package/types/lib/index.d.ts +22 -0
  201. package/types/lib/logger/telegram-core.d.ts +104 -0
  202. package/types/lib/logger/telegram-transport.d.ts +45 -0
  203. package/types/lib/mega-brute-force.d.ts +66 -0
  204. package/types/lib/mega-circuit-breaker.d.ts +241 -0
  205. package/types/lib/mega-cron.d.ts +66 -0
  206. package/types/lib/mega-hash.d.ts +32 -0
  207. package/types/lib/mega-health.d.ts +41 -0
  208. package/types/lib/mega-job-queue.d.ts +176 -0
  209. package/types/lib/mega-job-worker.d.ts +130 -0
  210. package/types/lib/mega-job.d.ts +138 -0
  211. package/types/lib/mega-logger.d.ts +45 -0
  212. package/types/lib/mega-metrics.d.ts +285 -0
  213. package/types/lib/mega-plugin.d.ts +245 -0
  214. package/types/lib/mega-retry.d.ts +85 -0
  215. package/types/lib/mega-schedule.d.ts +260 -0
  216. package/types/lib/mega-shutdown.d.ts +135 -0
  217. package/types/lib/mega-tracing.d.ts +224 -0
  218. package/types/lib/mega-worker.d.ts +127 -0
  219. package/types/lib/otel-resource.d.ts +16 -0
  220. package/types/lib/worker-runner/process-entry.d.ts +1 -0
  221. package/types/lib/worker-runner/task-dispatch.d.ts +28 -0
  222. package/types/lib/worker-runner/thread-entry.d.ts +1 -0
  223. package/types/lib/ws-hub.d.ts +234 -0
  224. package/types/models/crud-sql-builder.d.ts +48 -0
  225. package/types/models/index.d.ts +1 -0
  226. package/types/models/mega-model.d.ts +138 -0
  227. package/types/models/model-crud.d.ts +82 -0
  228. package/types/models/mongo-crud.d.ts +59 -0
  229. package/types/test/index.d.ts +84 -0
  230. package/.env +0 -127
  231. package/sample/crud/apps/main/migrations/20260606000002-add-auth-to-users.js +0 -30
  232. package/sample/crud/apps/main/models/note.js +0 -71
  233. package/sample/crud/apps/main/models/user.js +0 -86
  234. package/sample/crud/package-lock.json +0 -5665
  235. package/sample/crud/yarn.lock +0 -2142
  236. package/sample/simple/package-lock.json +0 -1851
@@ -0,0 +1,56 @@
1
+ /** 14자리 타임스탬프(UTC) — 러너 파일 규약({@link MIGRATION_FILE_RE})의 prefix. @param {Date} [d] @returns {string} */
2
+ export function migrationTimestamp(d?: Date): string;
3
+ /**
4
+ * `mega migrate:generate` 실행.
5
+ *
6
+ * @param {string} projectRoot
7
+ * @typedef {{
8
+ * name?: string,
9
+ * renames?: string,
10
+ * dryRun?: boolean,
11
+ * check?: boolean,
12
+ * concurrent?: boolean,
13
+ * allowDestroyDrops?: boolean,
14
+ * adapter?: string,
15
+ * app?: string,
16
+ * out?: (msg: string) => void,
17
+ * logger?: { debug?: Function, info?: Function, warn?: Function },
18
+ * confirmRenames?: (candidates: Array<{ table: string, dropped: string[], added: string[] }>) => Promise<Record<string, Record<string, string>> | null>,
19
+ * now?: () => Date,
20
+ * }} GenerateOpts
21
+ */
22
+ /**
23
+ * @param {string} projectRoot
24
+ * @param {GenerateOpts} [opts]
25
+ * @returns {Promise<{ changed: boolean, files: string[], adapters: string[] }>}
26
+ */
27
+ export function runMigrateGenerate(projectRoot: string, opts?: GenerateOpts): Promise<{
28
+ changed: boolean;
29
+ files: string[];
30
+ adapters: string[];
31
+ }>;
32
+ /**
33
+ * `mega migrate:generate` 실행.
34
+ */
35
+ export type GenerateOpts = {
36
+ name?: string;
37
+ renames?: string;
38
+ dryRun?: boolean;
39
+ check?: boolean;
40
+ concurrent?: boolean;
41
+ allowDestroyDrops?: boolean;
42
+ adapter?: string;
43
+ app?: string;
44
+ out?: (msg: string) => void;
45
+ logger?: {
46
+ debug?: Function;
47
+ info?: Function;
48
+ warn?: Function;
49
+ };
50
+ confirmRenames?: (candidates: Array<{
51
+ table: string;
52
+ dropped: string[];
53
+ added: string[];
54
+ }>) => Promise<Record<string, Record<string, string>> | null>;
55
+ now?: () => Date;
56
+ };
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @typedef {{ version: number, generatedAt: string | null, adapters: Record<string, { driver: string, models: Array<{ name: string, table: string, record: any }> }> }} Snapshot
3
+ */
4
+ /** 빈 스냅샷(첫 generate — 모든 모델이 신규로 diff 됨). @returns {Snapshot} */
5
+ export function emptySnapshot(): Snapshot;
6
+ /**
7
+ * snapshot.json 로드. 부재 시 빈 스냅샷(정상 — 첫 실행). 손상/버전 불일치는 fail-fast —
8
+ * 잘못된 기준으로 diff 하면 파괴적 SQL 이 잘못 생성된다(P7).
9
+ *
10
+ * @param {string} projectRoot
11
+ * @returns {Snapshot}
12
+ * @throws {MegaConfigError} `migration.journal_corrupt` | `migration.journal_version`
13
+ */
14
+ export function readSnapshot(projectRoot: string): Snapshot;
15
+ /**
16
+ * snapshot.json 기록(+디렉토리 생성). 모델은 이름순 정렬해 직렬화 — diff 노이즈 없는 결정적 출력.
17
+ * @param {string} projectRoot @param {Snapshot} snapshot
18
+ * @returns {string} 기록한 파일 경로.
19
+ */
20
+ export function writeSnapshot(projectRoot: string, snapshot: Snapshot): string;
21
+ /**
22
+ * generate 락 획득 — snapshot 읽기→쓰기 구간(프롬프트 대기 포함)이 길어 동시 generate 가
23
+ * 한쪽 갱신을 유실시킬 수 있다(CI 병렬 잡 등). `wx` 플래그(존재 시 실패)가 원자적 선점.
24
+ *
25
+ * @param {string} projectRoot
26
+ * @returns {() => void} 해제 함수(finally 에서 호출).
27
+ * @throws {MegaConfigError} `migration.generate_locked` - 다른 generate 진행 중(또는 stale lock).
28
+ */
29
+ export function acquireGenerateLock(projectRoot: string): () => void;
30
+ /**
31
+ * history 스냅샷 보존 — 마이그레이션 파일과 같은 base 이름의 .json.
32
+ * @param {string} projectRoot @param {string} baseName - `<ts>-<slug>` (확장자 없이).
33
+ * @param {Snapshot} snapshot
34
+ * @returns {string} 기록한 파일 경로.
35
+ */
36
+ export function appendHistory(projectRoot: string, baseName: string, snapshot: Snapshot): string;
37
+ /** journal 디렉토리 (projectRoot 상대). */
38
+ export const JOURNAL_DIR: string;
39
+ /** snapshot 포맷 버전 — 포맷 변경 시 증가(하위 포맷은 마이그레이션 가이드와 함께 거부). */
40
+ export const SNAPSHOT_VERSION: 1;
41
+ export type Snapshot = {
42
+ version: number;
43
+ generatedAt: string | null;
44
+ adapters: Record<string, {
45
+ driver: string;
46
+ models: Array<{
47
+ name: string;
48
+ table: string;
49
+ record: any;
50
+ }>;
51
+ }>;
52
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * 모든 앱의 models 폴더를 스캔해 schema 모델을 수집한다.
3
+ *
4
+ * @param {{ projectRoot: string, appNames: string[] }} opts
5
+ * @returns {Promise<ScannedModel[]>}
6
+ * @throws {MegaConfigError} `migration.model_load_failed` - 모델 파일 import 실패(문법 오류 등).
7
+ */
8
+ export function scanSchemaModels({ projectRoot, appNames }: {
9
+ projectRoot: string;
10
+ appNames: string[];
11
+ }): Promise<ScannedModel[]>;
12
+ export type ScannedModel = {
13
+ name: string;
14
+ table: string;
15
+ adapter: string;
16
+ app: string;
17
+ file: string;
18
+ Model: any;
19
+ };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * native `Db` → 러너/마이그레이션 파일 공용 db 셈.
3
+ *
4
+ * @param {import('mongodb').Db} nativeDb - 연결된 mongodb `Db` (adapter.native).
5
+ * @returns {any} Proxy — `query(sql)` 은 부기 SQL 번역, 그 외는 native `Db` 위임.
6
+ */
7
+ export function createMongoMigrationDb(nativeDb: import("mongodb").Db): any;
@@ -0,0 +1,197 @@
1
+ /**
2
+ * 모델 클래스(또는 동형 객체)의 `static schema`/`static indexes` 를 실행해 record 를 만든다.
3
+ * 모델 식별은 duck-typing — `schema` 함수 + `table`/`adapter` 문자열(클래스 identity 비의존,
4
+ * 패키지 사본이 달라도 동작). 검증은 {@link module:core/migration/schema-validator} 가 별도 수행.
5
+ *
6
+ * @param {{ name?: string, table?: string, adapter?: string, schema?: Function, indexes?: Function }} Model
7
+ * @returns {{ table: string, adapter: string, columns: Record<string, any>, primaryKey?: string[], indexes: any[], validation?: any }}
8
+ * @throws {MegaConfigError} `migration.schema_invalid` - table/adapter 누락, schema 반환 형태 오류.
9
+ */
10
+ export function buildModelRecord(Model: {
11
+ name?: string;
12
+ table?: string;
13
+ adapter?: string;
14
+ schema?: Function;
15
+ indexes?: Function;
16
+ }): {
17
+ table: string;
18
+ adapter: string;
19
+ columns: Record<string, any>;
20
+ primaryKey?: string[];
21
+ indexes: any[];
22
+ validation?: any;
23
+ };
24
+ /** FK onDelete/onUpdate 허용 동작 (PostgreSQL 참조 동작 5종). */
25
+ export const FK_ACTIONS: string[];
26
+ /**
27
+ * 컬럼 정의 체인 빌더 — 타입 메서드(`t.<type>()`)가 만들고, 제약 메서드를 체인한다.
28
+ * 최종 직렬화는 {@link ColumnBuilder#build} 가 수행한다(플레인 객체 반환).
29
+ */
30
+ export class ColumnBuilder {
31
+ /** @param {Record<string, any>} def - 타입 메서드가 만든 초기 정의(`{ type, ... }`). */
32
+ constructor(def: Record<string, any>);
33
+ /** PRIMARY KEY 지정(단일 컬럼). 복합 PK 는 `t.primary([cols])` 사용. @returns {this} */
34
+ primary(): this;
35
+ /** NOT NULL 지정. @returns {this} */
36
+ notNull(): this;
37
+ /**
38
+ * 명시 null 허용(ADR-210) — SQL 에선 nullable 이 기본이라 no-op(선언적 표시)이고, mongo 에선
39
+ * `bsonType: ['<type>', 'null']` 유니온으로 렌더된다(미선언 시 mongo 는 필드 **생략만** 허용 —
40
+ * 명시 null 은 121 거부, 실측). `.notNull()` 과 동시 사용 불가.
41
+ * @returns {this}
42
+ */
43
+ nullable(): this;
44
+ /**
45
+ * UNIQUE 제약. 이름 미지정 시 dialect 명명 표준(`uniq_<table>_<col>`)을 따른다.
46
+ * @param {{ name?: string }} [opts]
47
+ * @returns {this}
48
+ */
49
+ unique(opts?: {
50
+ name?: string;
51
+ }): this;
52
+ /**
53
+ * DEFAULT 값. literal(string/number/boolean/null) 또는 `{ raw: 'expr' }`(raw SQL 식).
54
+ * @param {string | number | boolean | null | { raw: string }} value
55
+ * @returns {this}
56
+ */
57
+ default(value: string | number | boolean | null | {
58
+ raw: string;
59
+ }): this;
60
+ /** `DEFAULT CURRENT_TIMESTAMP` 단축. @returns {this} */
61
+ defaultNow(): this;
62
+ /**
63
+ * CHECK 제약. 이름 미지정 시 `chk_<table>_<col>`.
64
+ * @param {string} expr - CHECK 식(raw SQL).
65
+ * @param {{ name?: string }} [opts]
66
+ * @returns {this}
67
+ */
68
+ check(expr: string, opts?: {
69
+ name?: string;
70
+ }): this;
71
+ /**
72
+ * FK 참조. 대상은 **모델 이름**(file-scan 결과의 클래스 이름)과 그 컬럼 — 실제 테이블명은
73
+ * 스냅샷 구성 시 해석된다.
74
+ * @param {string} modelName - 대상 모델 이름(예: 'Organization').
75
+ * @param {string} columnName - 대상 컬럼 이름(예: 'id').
76
+ * @param {{ onDelete?: string, onUpdate?: string, name?: string }} [opts]
77
+ * @returns {this}
78
+ */
79
+ references(modelName: string, columnName: string, opts?: {
80
+ onDelete?: string;
81
+ onUpdate?: string;
82
+ name?: string;
83
+ }): this;
84
+ /** 컬럼 코멘트(`COMMENT ON COLUMN`). @param {string} text @returns {this} */
85
+ comment(text: string): this;
86
+ /** 직렬화 — 누적 정의의 플레인 사본 반환. @returns {Record<string, any>} */
87
+ build(): Record<string, any>;
88
+ #private;
89
+ }
90
+ /**
91
+ * 테이블 스키마 빌더 — `schema(t)`/`indexes(t)` 콜백이 받는 `t`.
92
+ * 타입 메서드는 {@link ColumnBuilder} 를, `index()` 는 IndexDef 를 반환한다.
93
+ * `primary([cols])` 는 복합 PK 를 빌더 내부 상태에 기록한다.
94
+ */
95
+ export class SchemaBuilder {
96
+ /** @type {string[] | undefined} 복합 PRIMARY KEY 컬럼 목록 (`t.primary([...])`). */
97
+ compositePrimaryKey: string[] | undefined;
98
+ /** 자동증가 INT (postgres SERIAL). @returns {ColumnBuilder} */
99
+ serial(): ColumnBuilder;
100
+ /** 자동증가 BIGINT (postgres BIGSERIAL). @returns {ColumnBuilder} */
101
+ bigSerial(): ColumnBuilder;
102
+ /** @returns {ColumnBuilder} */
103
+ integer(): ColumnBuilder;
104
+ /** @returns {ColumnBuilder} */
105
+ bigInteger(): ColumnBuilder;
106
+ /** @returns {ColumnBuilder} */
107
+ smallInteger(): ColumnBuilder;
108
+ /** @returns {ColumnBuilder} */
109
+ real(): ColumnBuilder;
110
+ /** @returns {ColumnBuilder} */
111
+ doublePrecision(): ColumnBuilder;
112
+ /**
113
+ * 고정 정밀 십진수 (postgres NUMERIC).
114
+ * @param {number} precision @param {number} scale @returns {ColumnBuilder}
115
+ */
116
+ decimal(precision: number, scale: number): ColumnBuilder;
117
+ /** @param {number} maxLength @returns {ColumnBuilder} */
118
+ varchar(maxLength: number): ColumnBuilder;
119
+ /** @returns {ColumnBuilder} */
120
+ text(): ColumnBuilder;
121
+ /** @param {number} length @returns {ColumnBuilder} */
122
+ char(length: number): ColumnBuilder;
123
+ /** @returns {ColumnBuilder} */
124
+ boolean(): ColumnBuilder;
125
+ /** @returns {ColumnBuilder} */
126
+ timestamp(): ColumnBuilder;
127
+ /** @returns {ColumnBuilder} */
128
+ timestamptz(): ColumnBuilder;
129
+ /** @returns {ColumnBuilder} */
130
+ date(): ColumnBuilder;
131
+ /** @returns {ColumnBuilder} */
132
+ time(): ColumnBuilder;
133
+ /** @returns {ColumnBuilder} */
134
+ uuid(): ColumnBuilder;
135
+ /** @returns {ColumnBuilder} */
136
+ json(): ColumnBuilder;
137
+ /** @returns {ColumnBuilder} */
138
+ jsonb(): ColumnBuilder;
139
+ /** @returns {ColumnBuilder} */
140
+ bytea(): ColumnBuilder;
141
+ /**
142
+ * MongoDB ObjectId (mongo 전용 — SQL dialect 는 렌더 시점에 거부). `_id` 는 생략해도 자동이며,
143
+ * 명시 선언은 `_id: t.objectId().primary()` 형태만 허용된다(ADR-209).
144
+ * @returns {ColumnBuilder}
145
+ */
146
+ objectId(): ColumnBuilder;
147
+ /**
148
+ * 중첩 도큐먼트(embedded object — mongo 전용). shape 미지정 시 자유형 object.
149
+ * 중첩 필드의 제약은 타입·길이·enum·notNull(→required)만 — unique/primary/references/check 는
150
+ * 최상위 전용이다(mongo dialect 가 렌더 시점에 거부).
151
+ * @param {Record<string, ColumnBuilder>} [shape] - { 필드명: t.<type>()… }.
152
+ * @returns {ColumnBuilder}
153
+ * @throws {MegaConfigError} shape 값이 빌더가 아닐 때.
154
+ */
155
+ object(shape?: Record<string, ColumnBuilder>): ColumnBuilder;
156
+ /**
157
+ * 배열(mongo 전용). items 미지정 시 자유형 배열.
158
+ * @param {ColumnBuilder} [items] - 요소 타입(t.<type>()…).
159
+ * @param {{ uniqueItems?: boolean }} [opts]
160
+ * @returns {ColumnBuilder}
161
+ * @throws {MegaConfigError} items 가 빌더가 아닐 때.
162
+ */
163
+ array(items?: ColumnBuilder, opts?: {
164
+ uniqueItems?: boolean;
165
+ }): ColumnBuilder;
166
+ /**
167
+ * 열거형 — postgres 렌더는 `TEXT` + `CHECK (col IN (...))` (native enum 타입 미사용 —
168
+ * 값 추가/삭제가 제약 교체로 단순해짐).
169
+ * @param {string[]} values @param {{ name?: string }} [opts] - name: CHECK 제약 이름 override.
170
+ * @returns {ColumnBuilder}
171
+ */
172
+ enum(values: string[], opts?: {
173
+ name?: string;
174
+ }): ColumnBuilder;
175
+ /**
176
+ * 복합 PRIMARY KEY 선언 — schema 콜백 안에서 `t.primary(['a','b'])` 로 호출(반환값 없음,
177
+ * 컬럼 맵에는 넣지 않는다). 단일 PK 는 컬럼 체인 `.primary()` 사용.
178
+ * @param {string[]} columns
179
+ * @returns {void}
180
+ */
181
+ primary(columns: string[]): void;
182
+ /**
183
+ * 인덱스 정의 — `static indexes = (t) => [t.index(...)]` 에서 사용.
184
+ * @param {string | string[] | { expression: string }} columnsOrExpr - 컬럼(들) 또는 표현식 인덱스.
185
+ * @param {{ name?: string, unique?: boolean, where?: string, using?: string }} [opts]
186
+ * @returns {Record<string, any>} IndexDef.
187
+ */
188
+ index(columnsOrExpr: string | string[] | {
189
+ expression: string;
190
+ }, opts?: {
191
+ name?: string;
192
+ unique?: boolean;
193
+ where?: string;
194
+ using?: string;
195
+ }): Record<string, any>;
196
+ #private;
197
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * 스캔된 모델 record 집합을 검증하고 FK 대상 테이블을 해석(in-place)한다.
3
+ *
4
+ * @param {Array<{ name: string, table: string, adapter: string, record: any, file?: string }>} models - 스캔 결과
5
+ * (name = 모델 이름, file = 출처 파일 경로 — 충돌 메시지에 동반, record =
6
+ * {@link module:core/migration/schema-builder.buildModelRecord} 산출).
7
+ * @param {{ identifierMaxBytesOf?: (adapter: string) => number }} [opts] - adapter 별 식별자 byte 한도
8
+ * 공급자(dialect.identifierMaxBytes — 합성 이름은 dialect 의 quoteIdent 깔때기가 추가 검증).
9
+ * @returns {void}
10
+ * @throws {MegaConfigError} `migration.schema_invalid` | `migration.identifier_too_long`
11
+ */
12
+ export function validateModels(models: Array<{
13
+ name: string;
14
+ table: string;
15
+ adapter: string;
16
+ record: any;
17
+ file?: string;
18
+ }>, { identifierMaxBytesOf }?: {
19
+ identifierMaxBytesOf?: (adapter: string) => number;
20
+ }): void;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @typedef {{ debug?: Function, info?: Function, warn?: Function }} LockLogger
3
+ */
4
+ /**
5
+ * driver 별 마이그레이션 락 안에서 `fn` 을 실행한다. 락 획득/해제는 같은 고정 연결에서 수행하고,
6
+ * 해제 실패는 원본 결과/에러를 가리지 않는다(세션 락은 연결 반납·종료 시 서버가 자동 해제).
7
+ *
8
+ * @template T
9
+ * @param {import('../adapters/mega-adapter.js').MegaAdapter} adapter - 연결된 대상 DB 어댑터.
10
+ * @param {() => Promise<T>} fn - 락 보유 중 실행할 작업(마이그레이션 up/down).
11
+ * @param {{ logger?: LockLogger }} [opts]
12
+ * @returns {Promise<T>}
13
+ * @throws {MegaConfigError} `migrate.lock_timeout` - mariadb GET_LOCK 대기 한도 초과.
14
+ */
15
+ export function withMigrationLock<T>(adapter: import("../adapters/mega-adapter.js").MegaAdapter, fn: () => Promise<T>, { logger }?: {
16
+ logger?: LockLogger;
17
+ }): Promise<T>;
18
+ /** postgres advisory lock 키 — 'mega' ASCII(0x6d656761). 프레임워크 고정값(임의 64-bit 앱 키). */
19
+ export const PG_ADVISORY_LOCK_KEY: 1835362145;
20
+ /** mariadb GET_LOCK 이름. */
21
+ export const MARIA_LOCK_NAME: "mega_migrations";
22
+ /** mariadb GET_LOCK 대기 한도(초) — 초과 시 `migrate.lock_timeout` fail-fast. */
23
+ export const MARIA_LOCK_TIMEOUT_SEC: 60;
24
+ /** mongodb 락 컬렉션 이름. */
25
+ export const MONGO_LOCK_COLLECTION: "mega_migrations_lock";
26
+ /** mongodb 락 대기 한도(ms)·폴링 간격(ms) — 한도 초과 시 `migrate.lock_timeout` fail-fast. */
27
+ export const MONGO_LOCK_TIMEOUT_MS: 60000;
28
+ export const MONGO_LOCK_POLL_MS: 500;
29
+ export type LockLogger = {
30
+ debug?: Function;
31
+ info?: Function;
32
+ warn?: Function;
33
+ };
@@ -0,0 +1,101 @@
1
+ /**
2
+ * @typedef {{ query: (sql: string, params?: any[]) => Promise<any>, withTransaction?: (fn: () => Promise<any>) => Promise<any> }} MigrationDb
3
+ */
4
+ /**
5
+ * @typedef {{ name: string, file: string, app: string, absPath: string }} MigrationFile
6
+ */
7
+ /**
8
+ * 모든 앱의 `migrations/` 폴더를 스캔해 마이그레이션 파일 목록을 **타임스탬프(파일명 prefix) 오름차순**으로
9
+ * 반환한다. 형식(`MIGRATION_FILE_RE`)에 맞지 않는 파일·`*.test.js` 는 건너뛴다. 폴더 부재는 정상.
10
+ *
11
+ * @param {{ projectRoot: string, appNames: string[] }} opts
12
+ * @returns {MigrationFile[]}
13
+ */
14
+ export function collectMigrationFiles({ projectRoot, appNames }: {
15
+ projectRoot: string;
16
+ appNames: string[];
17
+ }): MigrationFile[];
18
+ /**
19
+ * 마이그레이션 모듈 로드 + up/down 검증. `export const transaction = false`(옵트아웃, ADR-205)면
20
+ * 러너가 트랜잭션 래핑을 끈다 — `CREATE INDEX CONCURRENTLY` 처럼 트랜잭션 안에서 실행 불가한
21
+ * 문장을 위한 escape hatch(부분 실패 시 롤백 없음은 파일 작성자 책임 — 생성기가 헤더에 명시).
22
+ * @param {string} absPath
23
+ * @returns {Promise<{ up: Function, down: Function, useTransaction: boolean }>}
24
+ * @throws {MegaConfigError} import 실패 / up·down 누락.
25
+ */
26
+ export function loadMigration(absPath: string): Promise<{
27
+ up: Function;
28
+ down: Function;
29
+ useTransaction: boolean;
30
+ }>;
31
+ /**
32
+ * 미적용(pending) 마이그레이션을 타임스탬프 순으로 모두 적용한다. 각 마이그레이션의 up + 이력 기록
33
+ * (sha-256 checksum 포함, ADR-190)을 한 트랜잭션으로 묶어 원자적으로 처리한다. 이미 적용된 파일이
34
+ * 적용 후 수정됐으면(checksum 불일치) 경고 로그를 남긴다 — 실행된 스키마와 파일이 어긋난 상태.
35
+ *
36
+ * @param {{ db: MigrationDb, projectRoot: string, appNames: string[], now?: () => string, log?: { info?: Function, warn?: Function, debug?: Function } }} opts
37
+ * - now: 적용 시각 ISO 문자열 공급자(테스트 주입용, 기본 `new Date().toISOString()`).
38
+ * @returns {Promise<{ applied: string[] }>}
39
+ */
40
+ export function migrateUp({ db, projectRoot, appNames, now, log }: {
41
+ db: MigrationDb;
42
+ projectRoot: string;
43
+ appNames: string[];
44
+ now?: () => string;
45
+ log?: {
46
+ info?: Function;
47
+ warn?: Function;
48
+ debug?: Function;
49
+ };
50
+ }): Promise<{
51
+ applied: string[];
52
+ }>;
53
+ /**
54
+ * 가장 최근 적용된 마이그레이션 1개를 롤백한다(down + 이력 삭제, 한 트랜잭션). 적용분이 없으면 no-op.
55
+ *
56
+ * 이력상 최신 적용분의 **파일이 사라진 경우 fail-fast** 한다(`migration.history_file_missing`, ADR-190) —
57
+ * 조용히 건너뛰면 더 오래된 마이그레이션이 롤백되어(순서 역전) 이력과 실제 스키마가 어긋난다.
58
+ *
59
+ * @param {{ db: MigrationDb, projectRoot: string, appNames: string[], log?: { info?: Function, warn?: Function } }} opts
60
+ * @returns {Promise<{ rolledBack: string | null }>}
61
+ * @throws {MegaConfigError} `migration.history_file_missing` - 최신 적용 이력의 파일 부재.
62
+ */
63
+ export function migrateDown({ db, projectRoot, appNames, log }: {
64
+ db: MigrationDb;
65
+ projectRoot: string;
66
+ appNames: string[];
67
+ log?: {
68
+ info?: Function;
69
+ warn?: Function;
70
+ };
71
+ }): Promise<{
72
+ rolledBack: string | null;
73
+ }>;
74
+ /**
75
+ * 적용/미적용/드리프트(적용 후 수정) 마이그레이션 목록(타임스탬프 순, ADR-190).
76
+ * @param {{ db: MigrationDb, projectRoot: string, appNames: string[] }} opts
77
+ * @returns {Promise<{ applied: string[], pending: string[], modified: string[] }>}
78
+ */
79
+ export function migrateStatus({ db, projectRoot, appNames }: {
80
+ db: MigrationDb;
81
+ projectRoot: string;
82
+ appNames: string[];
83
+ }): Promise<{
84
+ applied: string[];
85
+ pending: string[];
86
+ modified: string[];
87
+ }>;
88
+ /** 적용 이력 테이블 이름. */
89
+ export const MIGRATIONS_TABLE: "mega_migrations";
90
+ /** 마이그레이션 파일명 형식 — `<YYYYMMDDHHmmss>-<kebab>.js`. generator(ADR-012)가 이 prefix 를 생성. */
91
+ export const MIGRATION_FILE_RE: RegExp;
92
+ export type MigrationDb = {
93
+ query: (sql: string, params?: any[]) => Promise<any>;
94
+ withTransaction?: (fn: () => Promise<any>) => Promise<any>;
95
+ };
96
+ export type MigrationFile = {
97
+ name: string;
98
+ file: string;
99
+ app: string;
100
+ absPath: string;
101
+ };
@@ -0,0 +1,86 @@
1
+ /**
2
+ * 업로드 자동 등록 결과 요약(디버그·테스트용).
3
+ * @typedef {Object} MultipartSummary
4
+ * @property {boolean} enabled - 등록 여부.
5
+ * @property {number} maxFileSize - 적용된 파일 크기 상한(bytes).
6
+ * @property {number|null} maxFiles - 파일 개수 상한(null=무제한).
7
+ * @property {string[]} allowedMimeTypes - 허용 MIME 목록(빈 배열=전부 허용).
8
+ */
9
+ /**
10
+ * 파일명을 안전한 단일 파일명으로 살균한다 (path traversal 차단).
11
+ *
12
+ * `basename` 으로 디렉터리 성분(`../`, `/`, `\`)을 모두 제거하고, 남은 선행 점(`.`/`..`/`.bashrc` 류)과
13
+ * NUL·제어문자를 제거한다. 빈 문자열이 되면 `'upload'` 로 폴백한다 — 빈 파일명이 디렉터리로 해석되는 걸 막는다.
14
+ *
15
+ * @param {unknown} name - 클라가 보낸 원본 파일명(신뢰 불가).
16
+ * @returns {string} 디렉터리 성분 없는 안전한 파일명.
17
+ * @example sanitizeFilename('../../etc/passwd') // 'passwd'
18
+ * @example sanitizeFilename('..') // 'upload'
19
+ */
20
+ export function sanitizeFilename(name: unknown): string;
21
+ /**
22
+ * 살균된 파일명에 타임스탬프+랜덤 접미를 붙여 저장 파일명을 유일화한다.
23
+ *
24
+ * 살균만으로는 **같은 이름의 동시/연속 업로드가 silent 덮어쓰기**된다(두 사용자가 'photo.jpg' 를 올리면
25
+ * 나중 것이 이김, 동시면 스트림 교차 가능). 저장 파일명에 `-<ts36>-<rand8hex>` 를 붙여 충돌을 막는다 —
26
+ * 반환 메타의 `filename`(표시명)은 살균 원본 그대로 유지하고 `savedAs`(실제 경로)만 유일명을 갖는다.
27
+ *
28
+ * @param {string} name - {@link sanitizeFilename} 을 통과한 파일명.
29
+ * @returns {string} 예: 'photo.jpg' → 'photo-mbz3k1x2-9f2ac01b.jpg'.
30
+ * @example uniquifyFilename('report.pdf') // 'report-<ts36>-<rand>.pdf'
31
+ */
32
+ export function uniquifyFilename(name: string): string;
33
+ /**
34
+ * MIME 타입이 화이트리스트에 허용되는지 (Boolean — `is*`). 빈 목록/미지정이면 **전부 허용**(게이트 비활성).
35
+ * 정확 매치 + `type/*` 와일드카드(예: `'image/*'` 는 `'image/png'` 허용)를 지원한다.
36
+ *
37
+ * @param {string} mimetype - 검사할 MIME(part header 선언값).
38
+ * @param {string[]} [allowedMimeTypes] - 허용 목록. 빈 배열/미지정 → 전부 허용.
39
+ * @returns {boolean}
40
+ */
41
+ export function isMimeAllowed(mimetype: string, allowedMimeTypes?: string[]): boolean;
42
+ /**
43
+ * Fastify 인스턴스에 `@fastify/multipart` 를 자동 등록하고 MIME 게이트·안전 저장·관측성을 배선한다.
44
+ *
45
+ * `upload` 가 없으면 **미등록**(옵트인) — multipart 요청은 Fastify 가 415(파서 없음)로 거부한다. session.js
46
+ * 패턴 정합. 호출 순서는 보안 플러그인 등록 이후·라우트 등록 이전 어디든 무방하다(글로벌 onRequest hook +
47
+ * request 데코레이터라 라우트 등록 순서와 무관).
48
+ *
49
+ * @param {import('fastify').FastifyInstance} fastify - 대상 앱 Fastify 인스턴스.
50
+ * @param {Object} opts
51
+ * @param {unknown} opts.upload - `MegaUploadConfig`(maxFileSize/maxFiles/allowedMimeTypes). falsy 면 미등록.
52
+ * @param {string} [opts.appName] - 앱 이름(메트릭 라벨·로그용).
53
+ * @param {{ debug?: Function, warn?: Function }} [opts.logger] - 흐름 길목 debug 로그(선택).
54
+ * @returns {MultipartSummary}
55
+ */
56
+ export function registerMultipart(fastify: import("fastify").FastifyInstance, { upload, appName, logger }?: {
57
+ upload: unknown;
58
+ appName?: string;
59
+ logger?: {
60
+ debug?: Function;
61
+ warn?: Function;
62
+ };
63
+ }): MultipartSummary;
64
+ /** 업로드 파일 크기 디폴트 상한 (10 MB — 02-architecture §1502). */
65
+ export const DEFAULT_MAX_FILE_SIZE: number;
66
+ /**
67
+ * 업로드 자동 등록 결과 요약(디버그·테스트용).
68
+ */
69
+ export type MultipartSummary = {
70
+ /**
71
+ * - 등록 여부.
72
+ */
73
+ enabled: boolean;
74
+ /**
75
+ * - 적용된 파일 크기 상한(bytes).
76
+ */
77
+ maxFileSize: number;
78
+ /**
79
+ * - 파일 개수 상한(null=무제한).
80
+ */
81
+ maxFiles: number | null;
82
+ /**
83
+ * - 허용 MIME 목록(빈 배열=전부 허용).
84
+ */
85
+ allowedMimeTypes: string[];
86
+ };
@@ -0,0 +1,62 @@
1
+ /**
2
+ * OpenAPI 자동 등록 결과 요약(디버그·테스트용).
3
+ * @typedef {Object} OpenapiSummary
4
+ * @property {boolean} enabled - 등록 여부.
5
+ * @property {string|null} path - swagger-ui 경로(미등록 시 null).
6
+ */
7
+ /**
8
+ * `openapi` config 를 정규화한다. `enabled !== true` 면 `null`(미옵트인).
9
+ *
10
+ * @param {unknown} openapi - `MegaOpenApiAppConfig`.
11
+ * @param {string} [appName] - info.title 디폴트용.
12
+ * @returns {{ path: string, info: { title: string, version: string, description?: string }, auth: Function[], theme: Object } | null}
13
+ */
14
+ export function normalizeOpenapi(openapi: unknown, appName?: string): {
15
+ path: string;
16
+ info: {
17
+ title: string;
18
+ version: string;
19
+ description?: string;
20
+ };
21
+ auth: Function[];
22
+ theme: Object;
23
+ } | null;
24
+ /**
25
+ * Fastify 인스턴스에 OpenAPI 명세 수집기 + swagger-ui 를 옵트인 등록한다.
26
+ *
27
+ * `openapi.enabled !== true` 면 **미등록**. `@fastify/swagger` 는 **라우트 등록보다 먼저** 등록돼야 onRoute 로
28
+ * 스키마를 수집하므로 `MegaApp` 생성자(3g, 보안·정적 자산 뒤·`/health` 앞)에서 호출한다. 멀티앱은 각자 Fastify
29
+ * 인스턴스라 docs 경로 충돌 없음(같은 앱 안에서 `path` 가 사용자 라우트와 겹치면 Fastify 가 중복 라우트로 부팅 throw).
30
+ *
31
+ * @param {import('fastify').FastifyInstance} fastify - 대상 앱 Fastify 인스턴스.
32
+ * @param {Object} opts
33
+ * @param {unknown} opts.openapi - `MegaOpenApiAppConfig`. `enabled:true` 일 때만 등록.
34
+ * @param {string} [opts.appName] - 앱 이름(info.title 디폴트·로그).
35
+ * @param {(req: any, reply: any) => any} [opts.buildCtx] - docs auth 미들웨어에 넘길 ctx 팩토리(요청당). 미지정 시 auth 는 `(req, reply)` 로만 호출.
36
+ * @param {{ debug?: Function, warn?: Function }} [opts.logger] - 흐름 길목 debug 로그(선택).
37
+ * @returns {OpenapiSummary}
38
+ */
39
+ export function registerOpenapi(fastify: import("fastify").FastifyInstance, { openapi, appName, buildCtx, logger }?: {
40
+ openapi: unknown;
41
+ appName?: string;
42
+ buildCtx?: (req: any, reply: any) => any;
43
+ logger?: {
44
+ debug?: Function;
45
+ warn?: Function;
46
+ };
47
+ }): OpenapiSummary;
48
+ /** swagger-ui 마운트 경로 디폴트 (04-data-models §2 정본). */
49
+ export const DEFAULT_OPENAPI_PATH: "/docs";
50
+ /**
51
+ * OpenAPI 자동 등록 결과 요약(디버그·테스트용).
52
+ */
53
+ export type OpenapiSummary = {
54
+ /**
55
+ * - 등록 여부.
56
+ */
57
+ enabled: boolean;
58
+ /**
59
+ * - swagger-ui 경로(미등록 시 null).
60
+ */
61
+ path: string | null;
62
+ };