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,91 @@
1
+ /**
2
+ * Host 헤더에서 hostname 만 추출한다 (소문자 정규화). IPv6 리터럴(`[::1]:3000`)은 hostname 자체가
3
+ * 콜론을 포함하므로 단순 `split(':')` 으로는 `'['` 가 나와 vhost 매칭이 전부 깨진다 — 대괄호 형식이면
4
+ * 괄호 안(`::1`)을, 아니면 첫 콜론 앞(포트 제거)을 취한다.
5
+ * @param {unknown} hostHeader - `req.headers.host` 원본.
6
+ * @returns {string}
7
+ */
8
+ export function hostnameOf(hostHeader: unknown): string;
9
+ /**
10
+ * MegaServer — 여러 MegaApp 을 하나의 HTTP 서버에서 호스트네임 기반으로 라우팅.
11
+ *
12
+ * 단일 HTTP 서버 + Host 헤더 분기. ADR-003 (도메인 기반 멀티앱).
13
+ * WS hub·cluster master 의 토대.
14
+ *
15
+ * 동작:
16
+ * 1. mount(app) 으로 MegaApp 등록 (hosts 배열의 각 host 가 등록됨)
17
+ * 2. listen() → Node http.Server 생성, 매 요청마다 hostname 확인 → 해당 MegaApp 의
18
+ * Fastify routing 함수에 위임
19
+ *
20
+ * vhost 매칭은 ADR-003 + ADR-067 (호스트 충돌 부팅 검증) 이미 처리됨.
21
+ */
22
+ export class MegaServer {
23
+ /**
24
+ * @param {{ port?: number, host?: string, logger?: { debug?: Function, warn?: Function } }} [opts] -
25
+ * listen 기본값 (listen() 인자로 override 가능). `logger` 는 pino 호환 로거(선택) — 미매핑 host
26
+ * 404·upgrade 소켓 에러 같은 비치명 이벤트를 구조적으로 남긴다(미주입 시 console 폴백).
27
+ */
28
+ constructor(opts?: {
29
+ port?: number;
30
+ host?: string;
31
+ logger?: {
32
+ debug?: Function;
33
+ warn?: Function;
34
+ };
35
+ });
36
+ /** @type {Map<string, import('./mega-app.js').MegaApp>} */
37
+ _hostMap: Map<string, import("./mega-app.js").MegaApp>;
38
+ /** @type {import('./mega-app.js').MegaApp[]} */
39
+ _apps: import("./mega-app.js").MegaApp[];
40
+ /** @type {import('node:http').Server | null} */
41
+ _httpServer: import("node:http").Server | null;
42
+ /** @type {{ debug?: Function, warn?: Function } | null} */
43
+ _log: {
44
+ debug?: Function;
45
+ warn?: Function;
46
+ } | null;
47
+ _opts: {
48
+ port?: number;
49
+ host?: string;
50
+ logger?: {
51
+ debug?: Function;
52
+ warn?: Function;
53
+ };
54
+ };
55
+ /**
56
+ * MegaApp 마운트. 같은 host 가 두 앱에 매핑되면 throw (ADR-067 정합).
57
+ *
58
+ * WHY 2-pass: 충돌 검사를 **전체 host 에 대해 먼저 끝낸 뒤** `#hostMap` 을 변경한다. 한 번에 섞으면
59
+ * `hosts=['y','x']` 에서 'y' 를 등록한 직후 'x' 충돌로 throw 했을 때, 'y'→app 만 남고 app 은
60
+ * `_apps` 에 미등록되는 **부분 상태**가 생긴다(`#hostMap`↔`_apps` 불변식 깨짐 → 'y' 요청이 ready 안
61
+ * 된 Fastify 로 라우팅). 사전검증으로 mutate 전에 전부 막아 throw 시 상태를 원자적으로 보존한다.
62
+ *
63
+ * @param {import('./mega-app.js').MegaApp} app
64
+ */
65
+ mount(app: import("./mega-app.js").MegaApp): void;
66
+ /**
67
+ * @returns {boolean}
68
+ */
69
+ isListening(): boolean;
70
+ /**
71
+ * 모든 마운트된 MegaApp 의 Fastify 인스턴스 ready + HTTP 서버 listen.
72
+ * @param {{ port?: number, host?: string }} [opts]
73
+ */
74
+ listen(opts?: {
75
+ port?: number;
76
+ host?: string;
77
+ }): Promise<void>;
78
+ /**
79
+ * 모든 마운트된 MegaApp close (역순 — 마지막 mount 부터) → HTTP 서버 종료.
80
+ * graceful 처리는 MegaCluster + MegaShutdown 에서 강화.
81
+ *
82
+ * # 종료 순서 (M1)
83
+ * 각 app 의 WS 클라이언트를 **먼저** close(1001) 한 뒤 httpServer 를 닫는다. Node 의
84
+ * `http.Server.close` 콜백은 업그레이드된 WS 소켓을 포함한 모든 연결이 닫혀야 발생하므로,
85
+ * httpServer 를 먼저 await 하면 활성 WS 연결이 있을 때 영원히 끝나지 않는다(hang). single
86
+ * 모드(MegaApp.close)와 동일하게 WS → HTTP 순으로 닫아 일관성을 맞춘다.
87
+ */
88
+ close(): Promise<void>;
89
+ /** 등록된 호스트 목록 (디버그·테스트용). */
90
+ get hosts(): string[];
91
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * MegaService — 도메인 비즈니스 로직 베이스.
3
+ *
4
+ * 라우트 핸들러(인라인 함수 또는 정적 메서드 ref)는 직접 모델을 호출하지 않고 항상 서비스를 거쳐야
5
+ * 한다(ADR-022). ESLint custom rule `mega/no-direct-model-import`(`mega-framework/eslint-plugin`,
6
+ * eslint.config.js 에 배선)가 lint 시점에 routes/controllers → models 직접 import 를 차단한다.
7
+ *
8
+ * 서비스는 요청 컨텍스트 ctx 와 함께 인스턴스화되며, this.ctx / this.app / this.log /
9
+ * this.services 로 접근. 다른 서비스 호출은 this.services.<name> 으로 합성.
10
+ *
11
+ * 자동 DI(ADR-148): `apps/<app>/services/<name>-service.js` 를 부팅 시 로드해 두면 핸들러·다른 서비스가
12
+ * `ctx.services.<name>` / `this.services.<name>` 로 요청별 인스턴스를 받는다(첫 접근 시 lazy 생성·요청 내 캐시).
13
+ */
14
+ export class MegaService {
15
+ /**
16
+ * @param {Record<string, any>} ctx - 요청 컨텍스트 (req·log·services·db·cache·bus 등)
17
+ * @param {Object} [opts]
18
+ * @param {Object} [opts.app] - MegaApp 인스턴스 (옵션)
19
+ */
20
+ constructor(ctx: Record<string, any>, opts?: {
21
+ app?: Object;
22
+ });
23
+ /** @type {Record<string, any>} */
24
+ ctx: Record<string, any>;
25
+ /** @type {Object | null} */
26
+ app: Object | null;
27
+ /** 요청·인스턴스 로거. ctx.log 가 없으면 console fallback. */
28
+ get log(): any;
29
+ /** 다른 서비스 호출용. ctx.services 가 없으면 빈 객체. */
30
+ get services(): any;
31
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * dialect 의 contract 충족 검증 — 미구현 멤버 목록을 모아 한 번에 보고.
3
+ * @param {string} driver @param {Record<string, any>} dialect
4
+ * @throws {MegaConfigError} `migration.dialect_contract`
5
+ */
6
+ export function assertDialectContract(driver: string, dialect: Record<string, any>): void;
7
+ /**
8
+ * driver 의 dialect 조회(+contract 검증).
9
+ * @param {string} driver - services.databases.<key>.driver 값.
10
+ * @returns {Record<string, any>}
11
+ * @throws {MegaConfigError} `migration.dialect_unsupported` | `migration.dialect_contract`
12
+ */
13
+ export function getDialect(driver: string): Record<string, any>;
14
+ /**
15
+ * dialect 가 DML facet 을 충족하는지 — **누락 멤버 배열**(빈 배열=충족)을 반환한다(throw 아님 — 호출부
16
+ * model-crud 가 `model.*` 에러로 표면화). mongo 등 DML facet 미구현 dialect 는 비어있지 않은 배열을 돌려준다.
17
+ * @param {Record<string, any>} dialect
18
+ * @returns {string[]}
19
+ */
20
+ export function dmlFacetMissing(dialect: Record<string, any>): string[];
21
+ /** 자동 생성을 지원하는 driver 목록. */
22
+ export const SUPPORTED_DRIVERS: string[];
@@ -0,0 +1,99 @@
1
+ /**
2
+ * SQL 식별자 인용 — 백틱. 한도 초과는 fail-fast(절단 충돌 방지 — postgres 와 동일 정책).
3
+ * @param {string} name @returns {string}
4
+ * @throws {MegaConfigError} `migration.identifier_too_long`
5
+ */
6
+ export function quoteIdent(name: string): string;
7
+ /**
8
+ * 값 literal 인용 — MariaDB 는 기본 sql_mode 에서 백슬래시가 escape 문자라 `\` 도 이스케이프한다
9
+ * (postgres 의 standard_conforming_strings 와 다른 지점).
10
+ * @param {unknown} value @returns {string}
11
+ */
12
+ export function quoteLiteral(value: unknown): string;
13
+ /**
14
+ * 컬럼 타입 → MariaDB SQL 타입.
15
+ * @param {Record<string, any>} def @returns {string}
16
+ */
17
+ export function typeSql(def: Record<string, any>): string;
18
+ /** @param {string} table @param {string[]} cols @param {boolean} [unique] @returns {string} */
19
+ export function indexName(table: string, cols: string[], unique?: boolean): string;
20
+ /** @param {string} table @param {Record<string, any>} ix @returns {string} */
21
+ export function resolveIndexName(table: string, ix: Record<string, any>): string;
22
+ /** @param {string} table @param {string} col @returns {string} */
23
+ export function uniqueName(table: string, col: string): string;
24
+ /** @param {string} table @param {string} col @param {string} refTable @returns {string} */
25
+ export function fkName(table: string, col: string, refTable: string): string;
26
+ /** @param {string} table @param {string} col @returns {string} */
27
+ export function checkName(table: string, col: string): string;
28
+ /** MariaDB 의 PRIMARY KEY 이름은 항상 'PRIMARY' — 명시 이름을 줘도 서버가 무시한다. @returns {string} */
29
+ export function pkName(): string;
30
+ /** @returns {string} */
31
+ export function inlinePkName(): string;
32
+ /**
33
+ * enum 의 CHECK 식 — contract 필수 멤버. maria 는 enum-type 전략이라 diff 경로에서는 쓰이지
34
+ * 않지만, 명시 .check() 렌더와 동형 표면을 유지한다.
35
+ * @param {string} col @param {string[]} values @returns {string}
36
+ */
37
+ export function enumCheckExpr(col: string, values: string[]): string;
38
+ /**
39
+ * 같은 타입의 길이/정밀도/enum 값 **축소** — 위배 데이터가 있으면 적용 실패·잘림 위험(경고 주석).
40
+ * enum 값 제거는 enum-type 전략에서 alterType 으로 오므로 여기서 함께 잡는다.
41
+ * @param {Record<string, any>} from @param {Record<string, any>} to @returns {boolean}
42
+ */
43
+ export function isNarrowing(from: Record<string, any>, to: Record<string, any>): boolean;
44
+ /**
45
+ * 변경 연산(op) 1개 → `{ up: string[], down: string[] }`. op 종류·필드는 differ 가 정본.
46
+ * @param {Record<string, any>} op
47
+ * @returns {{ up: string[], down: string[] }}
48
+ */
49
+ export function renderOp(op: Record<string, any>): {
50
+ up: string[];
51
+ down: string[];
52
+ };
53
+ /**
54
+ * 연산 목록 → `{ up, down }` (down 은 역순). DDL 암묵 COMMIT 특성상 다단 변경의 중간 실패는
55
+ * 부분 적용으로 남는다 — 러너 락(ADR-190)·생성 파일 헤더가 그 한계를 명시한다.
56
+ * @param {Array<Record<string, any>>} ops
57
+ * @returns {{ up: string[], down: string[] }}
58
+ */
59
+ export function renderOps(ops: Array<Record<string, any>>): {
60
+ up: string[];
61
+ down: string[];
62
+ };
63
+ /** maria 는 위치식 `?`(인덱스 무시). @returns {string} */
64
+ export function placeholder(): string;
65
+ /** SELECT native(rows 배열) → record[]. @param {any} res @returns {any[]} */
66
+ export function parseReadResult(res: any): any[];
67
+ /** write native(`{ affectedRows, insertId }`) → 정규화. @param {any} res */
68
+ export function parseWriteResult(res: any): {
69
+ count: any;
70
+ insertId: any;
71
+ };
72
+ /** upsert 절 — `ON DUPLICATE KEY UPDATE col = VALUES(col)`. maria 는 conflict target 미사용(자동 unique 매칭). @param {{ updateCols: string[] }} o */
73
+ export function upsertClause({ updateCols }: {
74
+ updateCols: string[];
75
+ }): string;
76
+ /** MariaDB 식별자 한도 — **64자**(chars, utf8 멀티바이트 식별자도 자수 기준). contract 멤버명은
77
+ * 역사적으로 *MaxBytes 지만 maria 검증은 자수로 한다(비ASCII 과잉 거부 방지 — ADR-208 L-3). */
78
+ export const identifierMaxBytes: 64;
79
+ /** 온라인 인덱스 추가 — `ALGORITHM=INPLACE, LOCK=NONE` (--concurrent 옵트인). */
80
+ export const supportsConcurrentIndex: true;
81
+ /** enum 표현 전략 — native ENUM 타입(값 변경 = MODIFY COLUMN). */
82
+ export const enumStrategy: "enum-type";
83
+ /** RENAME COLUMN 자체는 지원(10.5+)하나 DDL 암묵 COMMIT 이라 트랜잭션 내 원자성은 없다. */
84
+ export const supportsRenameInTx: false;
85
+ /** DDL 암묵 COMMIT — DROP COLUMN 을 트랜잭션으로 롤백할 수 없다(ADR-190 기존 인지). */
86
+ export const canDropColumnInTx: false;
87
+ /** ALTER 가 대부분의 변경을 표현 — 테이블 재생성 불요. */
88
+ export const dependsOnRebuild: false;
89
+ /** `ALTER TABLE … RENAME CONSTRAINT` 미지원 — MariaDB 11.8 실측(구문 에러). DROP+ADD 로 대체. */
90
+ export const supportsRenameConstraint: false;
91
+ /** ALTER 로 FK 추가/삭제 가능(`ADD CONSTRAINT … FOREIGN KEY` / `DROP CONSTRAINT` — 11.8 실측). */
92
+ export const supportsAlterAddFk: true;
93
+ /** InnoDB 는 FK 가 걸린 컬럼의 DROP 을 거부(1553 — FK 인덱스 요구, 11.8 실측) — dropFk 선행 필수. */
94
+ export const requiresDropFkBeforeDropColumn: true;
95
+ /** SQL DDL 렌더 dialect — 생성 파일이 `db.query(sql)` 계약을 쓴다(mongo 와 분기, ADR-209). */
96
+ export const usesSqlDdl: true;
97
+ export const paramStyle: "positional";
98
+ export const supportsReturning: false;
99
+ export const supportsBulkReturning: false;
@@ -0,0 +1,89 @@
1
+ /**
2
+ * collection/필드 이름 검증 — mongo 는 SQL 인용이 없어서 quoteIdent 는 검증 깔때기 + 원형 반환.
3
+ * `$` 시작(연산자 충돌), `.`(경로 구분자), `system.` prefix(예약), 빈 문자열, NUL 을 거부한다.
4
+ * @param {string} name @returns {string}
5
+ */
6
+ export function quoteIdent(name: string): string;
7
+ /** JS 코드에 박는 값 literal — JSON 직렬화(따옴표·escape 안전). @param {unknown} value @returns {string} */
8
+ export function quoteLiteral(value: unknown): string;
9
+ /**
10
+ * contract 형식 충족용 — mongo 에는 CHECK 가 없다. enum 은 `$jsonSchema` 의 enum 키워드로
11
+ * 렌더되므로 이 함수가 정상 흐름에서 호출되면 통합 결함이다(silent 우회 금지).
12
+ * @param {string} col @param {string[]} values @returns {string}
13
+ */
14
+ export function enumCheckExpr(col: string, values: string[]): string;
15
+ /** @param {string} table @param {string[]} cols @param {boolean} [unique] @returns {string} */
16
+ export function indexName(table: string, cols: string[], unique?: boolean): string;
17
+ /** @param {string} table @param {Record<string, any>} ix @returns {string} */
18
+ export function resolveIndexName(table: string, ix: Record<string, any>): string;
19
+ /** @param {string} table @param {string} col @returns {string} */
20
+ export function uniqueName(table: string, col: string): string;
21
+ /** @param {string} table @param {string} col @param {string} refTable @returns {string} */
22
+ export function fkName(table: string, col: string, refTable: string): string;
23
+ /** @param {string} table @param {string} col @returns {string} */
24
+ export function checkName(table: string, col: string): string;
25
+ /** mongo PK 는 _id 단일 — diff 정규화용 합성 명칭. @param {string} table @returns {string} */
26
+ export function pkName(table: string): string;
27
+ /** @param {string} table @returns {string} */
28
+ export function inlinePkName(table: string): string;
29
+ /**
30
+ * record → collection `$jsonSchema`. `additionalProperties: false`(strict) 라 `_id` 를 항상
31
+ * properties 에 포함한다(_id 는 모든 도큐먼트에 존재 — 누락 시 insert 전부 거부되는 함정).
32
+ * @param {Record<string, any>} record
33
+ * @returns {Record<string, any>}
34
+ */
35
+ export function jsonSchemaOf(record: Record<string, any>): Record<string, any>;
36
+ /**
37
+ * 인덱스 컬럼 항목 파싱 — `'field'`(asc) | `'field:desc'`. 필드 존재 검증은 schema-validator 가
38
+ * suffix 제거 후 수행한다.
39
+ * @param {string} entry @returns {{ field: string, dir: 1 | -1 }}
40
+ */
41
+ export function parseIndexColumn(entry: string): {
42
+ field: string;
43
+ dir: 1 | -1;
44
+ };
45
+ /**
46
+ * 변경 연산(op) 1개 → `{ up: string[], down: string[] }` (mongo command JS 문).
47
+ * 컬럼 수준 op 는 differ 가 rebuildTable 로 수렴하므로 도달하지 않는다(도달 시 명시 에러).
48
+ * @param {Record<string, any>} op
49
+ * @returns {{ up: string[], down: string[] }}
50
+ */
51
+ export function renderOp(op: Record<string, any>): {
52
+ up: string[];
53
+ down: string[];
54
+ };
55
+ /**
56
+ * ops 배열 → { up, down } (down 은 역순 — 적용의 정확한 역).
57
+ * @param {Array<Record<string, any>>} ops
58
+ * @returns {{ up: string[], down: string[] }}
59
+ */
60
+ export function renderOps(ops: Array<Record<string, any>>): {
61
+ up: string[];
62
+ down: string[];
63
+ };
64
+ /** mongo namespace 한도(db 포함 120byte)에서 db 명을 제외한 보수적 collection/필드 한도. */
65
+ export const identifierMaxBytes: 64;
66
+ /** mongo 4.2+ 인덱스 빌드는 항상 online(hybrid build) — --concurrent 는 의미 변화 없이 허용. */
67
+ export const supportsConcurrentIndex: true;
68
+ /** enum 은 `$jsonSchema` 의 enum 키워드 — CHECK 도 native enum 타입도 아니다. */
69
+ export const enumStrategy: "jsonschema-enum";
70
+ /** renameCollection 은 트랜잭션 안에서 불가(공식 문서). */
71
+ export const supportsRenameInTx: false;
72
+ /** validator 교체(collMod)는 즉시 적용 — 단 본 dialect 는 트랜잭션 자체를 쓰지 않는다. */
73
+ export const canDropColumnInTx: false;
74
+ /** 컬럼 수준 변경을 rebuildTable(=validator 교체) 1 op 로 수렴한다. */
75
+ export const dependsOnRebuild: true;
76
+ /** constraint 개념이 없다. */
77
+ export const supportsRenameConstraint: false;
78
+ /** FK 자체가 없다 — differ 의 FK 분리/동기화 경로 전부 비활성. */
79
+ export const supportsAlterAddFk: false;
80
+ /** FK 가 없으니 해당 없음. */
81
+ export const requiresDropFkBeforeDropColumn: false;
82
+ /** SQL 이 아니라 mongo command JS 문을 렌더한다 — generate 가 파일 템플릿을 분기한다. */
83
+ export const usesSqlDdl: false;
84
+ /**
85
+ * differ 의 수렴 트리거 확장 — mongo 는 validator 가 통짜라 **모든 컬럼 수준 변경**이 수렴 대상이다
86
+ * (sqlite 기본 집합 + addColumn/renameColumn/setComment). 인덱스/UNIQUE 변경은 collMod 와 무관한
87
+ * 개별 op 로 남는다.
88
+ */
89
+ export const rebuildTriggerKinds: Set<string>;
@@ -0,0 +1,117 @@
1
+ /**
2
+ * SQL 식별자 인용 — 필요할 때만 `"..."`. **모든 식별자가 지나는 단일 깔때기**라 여기서
3
+ * 63byte 초과를 fail-fast 한다 — postgres 는 NOTICE 와 함께 조용히 절단해 이름 충돌·
4
+ * `migrate:status` 표기 불일치를 만들기 때문(자동 축약 없이 거부, 정책 2).
5
+ *
6
+ * @param {string} name @returns {string}
7
+ * @throws {MegaConfigError} `migration.identifier_too_long` - 63byte 초과(합성 이름 포함).
8
+ */
9
+ export function quoteIdent(name: string): string;
10
+ /**
11
+ * DEFAULT/CHECK 용 literal 렌더 — 문자열은 단일따옴표 escape, `{ raw }` 는 검증된 식 그대로.
12
+ * @param {unknown} value @returns {string}
13
+ */
14
+ export function renderLiteral(value: unknown): string;
15
+ /**
16
+ * 컬럼 타입 → postgres SQL 타입.
17
+ * @param {Record<string, any>} def @param {{ forAlter?: boolean }} [opts] - forAlter: ALTER TYPE 대상
18
+ * (SERIAL 은 타입이 아니라 시퀀스 단축문법이라 INTEGER/BIGINT 로 강등).
19
+ * @returns {string}
20
+ */
21
+ export function typeSql(def: Record<string, any>, { forAlter }?: {
22
+ forAlter?: boolean;
23
+ }): string;
24
+ /** @param {string} table @param {string[]} cols @param {boolean} [unique] @returns {string} */
25
+ export function indexName(table: string, cols: string[], unique?: boolean): string;
26
+ /** @param {string} table @param {Record<string, any>} ix @returns {string} 인덱스 정의의 유효 이름. */
27
+ export function resolveIndexName(table: string, ix: Record<string, any>): string;
28
+ /** @param {string} table @param {string} col @returns {string} */
29
+ export function uniqueName(table: string, col: string): string;
30
+ /** @param {string} table @param {string} col @param {string} refTable @returns {string} */
31
+ export function fkName(table: string, col: string, refTable: string): string;
32
+ /** @param {string} table @param {string} col @returns {string} */
33
+ export function checkName(table: string, col: string): string;
34
+ /** @param {string} table @returns {string} */
35
+ export function pkName(table: string): string;
36
+ /** CREATE TABLE 인라인 단일 PK 의 서버 자동 명명. @param {string} table @returns {string} */
37
+ export function inlinePkName(table: string): string;
38
+ /**
39
+ * enum 컬럼의 CHECK 식 — **유일한 enum CHECK 렌더 지점**(differ 는 values 만 전달, ADR-205 H-1).
40
+ * @param {string} col @param {string[]} values @returns {string}
41
+ */
42
+ export function enumCheckExpr(col: string, values: string[]): string;
43
+ /**
44
+ * ALTER TYPE 시 implicit cast 가 보장되지 않아 USING 식 검토가 필요한지. 안전 목록(정수 확장·
45
+ * varchar↔text·decimal 정밀도·timestamp↔timestamptz·길이 변경) 밖이면 true.
46
+ * @param {Record<string, any>} from @param {Record<string, any>} to @returns {boolean}
47
+ */
48
+ export function isRiskyCast(from: Record<string, any>, to: Record<string, any>): boolean;
49
+ /**
50
+ * 같은 타입의 길이/정밀도 **축소** 인지 — varchar(200→50)·decimal(12,2→8,2) 등. implicit cast 는
51
+ * 존재해 isRiskyCast 로는 안 잡히지만, 기존 데이터가 한도를 넘으면 적용이 실패하거나(varchar)
52
+ * 반올림·잘림이 생긴다 — 경고 주석 대상.
53
+ * @param {Record<string, any>} from @param {Record<string, any>} to @returns {boolean}
54
+ */
55
+ export function isNarrowing(from: Record<string, any>, to: Record<string, any>): boolean;
56
+ /**
57
+ * 변경 연산(op) 1개 → `{ up: string[], down: string[] }`.
58
+ * op 종류·필드는 {@link module:core/migration/differ} 가 정본.
59
+ *
60
+ * @param {Record<string, any>} op
61
+ * @returns {{ up: string[], down: string[] }}
62
+ */
63
+ export function renderOp(op: Record<string, any>): {
64
+ up: string[];
65
+ down: string[];
66
+ };
67
+ /**
68
+ * 연산 목록 → `{ up: string[], down: string[] }`. down 은 **역순**(가장 마지막 변경부터 되돌림).
69
+ * @param {Array<Record<string, any>>} ops
70
+ * @returns {{ up: string[], down: string[] }}
71
+ */
72
+ export function renderOps(ops: Array<Record<string, any>>): {
73
+ up: string[];
74
+ down: string[];
75
+ };
76
+ /** @param {number} i - 1-base placeholder 인덱스. @returns {string} */
77
+ export function placeholder(i: number): string;
78
+ /** SELECT native 결과(pg `{ rows }`) → record[]. @param {any} res @returns {any[]} */
79
+ export function parseReadResult(res: any): any[];
80
+ /** write native 결과(pg `{ rowCount, rows }`) → 정규화. @param {any} res @returns {{ count: number, rows?: any[] }} */
81
+ export function parseWriteResult(res: any): {
82
+ count: number;
83
+ rows?: any[];
84
+ };
85
+ /** upsert 절 — `ON CONFLICT (...) DO UPDATE SET ...`. @param {{ conflictCols: string[], updateCols: string[] }} o @returns {string} */
86
+ export function upsertClause({ conflictCols, updateCols }: {
87
+ conflictCols: string[];
88
+ updateCols: string[];
89
+ }): string;
90
+ /** 식별자 최대 길이(byte) — postgres NAMEDATALEN-1. 초과는 절단·충돌 위험이라 fail-fast(정책 2). */
91
+ export const identifierMaxBytes: 63;
92
+ /** CREATE INDEX CONCURRENTLY 지원(트랜잭션 밖 실행 필요 — generate --concurrent 옵트인). */
93
+ export const supportsConcurrentIndex: true;
94
+ /** enum 표현 전략 — 'check' = TEXT + CHECK(col IN (...)). (maria 는 'enum-type' 예정.) */
95
+ export const enumStrategy: "check";
96
+ /** RENAME COLUMN 의 트랜잭션 내 실행 지원. */
97
+ export const supportsRenameInTx: true;
98
+ /** DROP COLUMN 의 트랜잭션 내 롤백 가능(maria 는 DDL 암묵 commit 으로 false 예정). */
99
+ export const canDropColumnInTx: true;
100
+ /** 일부 ALTER 가 테이블 재생성을 요구하는지(sqlite true 예정). */
101
+ export const dependsOnRebuild: false;
102
+ /** ALTER TABLE ... RENAME CONSTRAINT 지원(postgres 9.2+). 미지원 dialect 는 DROP+ADD 로 대체. */
103
+ export const supportsRenameConstraint: true;
104
+ /** ALTER 로 FK 추가/삭제 가능 — false(sqlite)면 FK 는 CREATE TABLE 인라인 + 변경은 rebuild. */
105
+ export const supportsAlterAddFk: true;
106
+ /** FK 걸린 컬럼 DROP 전 dropFk 선행 필요 여부 — postgres 는 의존 객체 cascade 라 불필요. */
107
+ export const requiresDropFkBeforeDropColumn: false;
108
+ /** SQL DDL 렌더 dialect — 생성 파일이 `db.query(sql)` 계약을 쓴다(mongo 와 분기, ADR-209). */
109
+ export const usesSqlDdl: true;
110
+ /** dialect 표준 인터페이스 별칭 — 값 인용(SQL injection 방지 깔때기). @type {typeof renderLiteral} */
111
+ export const quoteLiteral: typeof renderLiteral;
112
+ /** placeholder 스타일 — postgres 는 번호식 `$1`. */
113
+ export const paramStyle: "numbered";
114
+ /** RETURNING 지원(insert/upsert 레코드 반환). */
115
+ export const supportsReturning: true;
116
+ /** insertMany RETURNING 지원. */
117
+ export const supportsBulkReturning: true;
@@ -0,0 +1,111 @@
1
+ /**
2
+ * SQL 식별자 인용 — postgres 와 동일한 더블쿼트(필요 시만).
3
+ * @param {string} name @returns {string}
4
+ */
5
+ export function quoteIdent(name: string): string;
6
+ /**
7
+ * 값 literal 인용 — '' 이스케이프(sqlite 는 백슬래시 escape 없음). boolean 은 INTEGER 0/1.
8
+ * @param {unknown} value @returns {string}
9
+ */
10
+ export function quoteLiteral(value: unknown): string;
11
+ /**
12
+ * 컬럼 타입 → sqlite 타입(affinity).
13
+ * @param {Record<string, any>} def @returns {string}
14
+ */
15
+ export function typeSql(def: Record<string, any>): string;
16
+ /** @param {string} table @param {string[]} cols @param {boolean} [unique] @returns {string} */
17
+ export function indexName(table: string, cols: string[], unique?: boolean): string;
18
+ /** @param {string} table @param {Record<string, any>} ix @returns {string} */
19
+ export function resolveIndexName(table: string, ix: Record<string, any>): string;
20
+ /** @param {string} table @param {string} col @returns {string} */
21
+ export function uniqueName(table: string, col: string): string;
22
+ /** @param {string} table @param {string} col @param {string} refTable @returns {string} */
23
+ export function fkName(table: string, col: string, refTable: string): string;
24
+ /** @param {string} table @param {string} col @returns {string} */
25
+ export function checkName(table: string, col: string): string;
26
+ /** @param {string} table @returns {string} */
27
+ export function pkName(table: string): string;
28
+ /** sqlite 인라인 PK 는 별도 제약 이름이 없다 — diff 정규화용 합성 명칭. @param {string} table @returns {string} */
29
+ export function inlinePkName(table: string): string;
30
+ /**
31
+ * enum 의 CHECK 식 — 유일한 enum 렌더 지점(differ 는 values 만 전달).
32
+ * @param {string} col @param {string[]} values @returns {string}
33
+ */
34
+ export function enumCheckExpr(col: string, values: string[]): string;
35
+ /**
36
+ * rebuild 위험 요소 검사(best-effort) — 대상 DB 파일이 있으면 읽기 전용으로 열어 sqlite_master 에서
37
+ * 재생성 테이블의 **트리거**(DROP TABLE 과 함께 소실 — 사용자 재생성 필요)와 테이블을 참조하는
38
+ * **뷰**(3.25+ 가 RENAME 시점에 뷰를 재파싱해 rebuild 가 통째 실패)를 찾는다. generate 는 원래
39
+ * DB 무연결 설계지만 sqlite 는 "서버" 가 아니라 파일이라 이 검사가 유일한 사전 방어선이다.
40
+ * 파일 부재(첫 generate 등)·열기 실패는 빈 결과 — 헤더의 일반 경고가 잔여 방어선.
41
+ *
42
+ * @param {string} filename - sqlite DB 파일 경로(':memory:' 면 검사 불가).
43
+ * @param {string[]} tables - rebuild 대상 테이블들.
44
+ * @returns {Promise<{ triggers: string[], conflictViews: string[] }>}
45
+ */
46
+ export function inspectRebuildHazards(filename: string, tables: string[]): Promise<{
47
+ triggers: string[];
48
+ conflictViews: string[];
49
+ }>;
50
+ /**
51
+ * 변경 연산(op) 1개 → `{ up: string[], down: string[] }`.
52
+ * setNotNull/setDefault/addCheck/addFk/… 류는 differ 가 rebuildTable 로 수렴하므로 도달하지 않는다
53
+ * (도달 시 명시 에러 — silent 누락 금지).
54
+ * @param {Record<string, any>} op
55
+ * @returns {{ up: string[], down: string[] }}
56
+ */
57
+ export function renderOp(op: Record<string, any>): {
58
+ up: string[];
59
+ down: string[];
60
+ };
61
+ /**
62
+ * 연산 목록 → `{ up, down }` (down 은 역순).
63
+ * @param {Array<Record<string, any>>} ops
64
+ * @returns {{ up: string[], down: string[] }}
65
+ */
66
+ export function renderOps(ops: Array<Record<string, any>>): {
67
+ up: string[];
68
+ down: string[];
69
+ };
70
+ /** sqlite 는 위치식 `?`(인덱스 무시). @returns {string} */
71
+ export function placeholder(): string;
72
+ /** SELECT native(stmt.all 배열) → record[]. @param {any} res @returns {any[]} */
73
+ export function parseReadResult(res: any): any[];
74
+ /** write native → 정규화. RETURNING 이면 stmt.all 배열, 아니면 `{ changes, lastInsertRowid }`. @param {any} res */
75
+ export function parseWriteResult(res: any): {
76
+ count: number;
77
+ rows: any[];
78
+ lastInsertRowid?: undefined;
79
+ } | {
80
+ count: number;
81
+ lastInsertRowid: any;
82
+ rows?: undefined;
83
+ };
84
+ /** upsert 절 — `ON CONFLICT (...) DO UPDATE SET col = excluded.col`. @param {{ conflictCols: string[], updateCols: string[] }} o */
85
+ export function upsertClause({ conflictCols, updateCols }: {
86
+ conflictCols: string[];
87
+ updateCols: string[];
88
+ }): string;
89
+ /** sqlite 는 식별자 길이 제한이 사실상 없다. */
90
+ export const identifierMaxBytes: number;
91
+ /** CONCURRENTLY 동등물 없음 — --concurrent 는 generate 가 명시 거부. */
92
+ export const supportsConcurrentIndex: false;
93
+ /** enum 표현 전략 — TEXT + CHECK(col IN (...)). */
94
+ export const enumStrategy: "check";
95
+ /** RENAME COLUMN(3.25+)은 트랜잭션 내 정상 동작. */
96
+ export const supportsRenameInTx: true;
97
+ /** 단순 DROP COLUMN(3.35+)도 트랜잭션 대상 — 단 본 dialect 는 호환 위해 rebuild 로 처리. */
98
+ export const canDropColumnInTx: true;
99
+ /** 핵심 — 다수 ALTER 미지원이라 테이블 재생성(12-step) 패턴 사용. */
100
+ export const dependsOnRebuild: true;
101
+ /** RENAME CONSTRAINT 없음. (FK 는 인라인이라 이름 동기화 자체가 불필요.) */
102
+ export const supportsRenameConstraint: false;
103
+ /** ALTER 로 FK 추가/삭제 불가 — CREATE TABLE 인라인 + 변경은 rebuild. */
104
+ export const supportsAlterAddFk: false;
105
+ /** 컬럼/FK 변경은 rebuild 로 수렴 — dropFk 선행 발행 자체가 없다. */
106
+ export const requiresDropFkBeforeDropColumn: false;
107
+ /** SQL DDL 렌더 dialect — 생성 파일이 `db.query(sql)` 계약을 쓴다(mongo 와 분기, ADR-209). */
108
+ export const usesSqlDdl: true;
109
+ export const paramStyle: "positional";
110
+ export const supportsReturning: true;
111
+ export const supportsBulkReturning: true;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * 한 adapter 그룹의 모델 목록 diff.
3
+ *
4
+ * @param {Array<{ name: string, table: string, record: any }>} prevModels - 직전 snapshot 의 모델.
5
+ * @param {Array<{ name: string, table: string, record: any }>} currModels - 현재 스캔 모델.
6
+ * @param {{ renames?: Record<string, Record<string, string>>, dialect?: Record<string, any> }} [opts]
7
+ * - renames: `{ [table]: { old: new } }` 확정 rename 매핑(미지정 시 drop+add 로 두고 후보만 보고).
8
+ * - dialect: 명명·능력 contract(기본 postgres — 호출자는 driver 별 dialect 를 주입).
9
+ * @returns {{ ops: Array<Record<string, any>>, renameCandidates: Array<{ table: string, dropped: string[], added: string[] }> }}
10
+ */
11
+ export function diffModels(prevModels: Array<{
12
+ name: string;
13
+ table: string;
14
+ record: any;
15
+ }>, currModels: Array<{
16
+ name: string;
17
+ table: string;
18
+ record: any;
19
+ }>, { renames, dialect }?: {
20
+ renames?: Record<string, Record<string, string>>;
21
+ dialect?: Record<string, any>;
22
+ }): {
23
+ ops: Array<Record<string, any>>;
24
+ renameCandidates: Array<{
25
+ table: string;
26
+ dropped: string[];
27
+ added: string[];
28
+ }>;
29
+ };
30
+ /**
31
+ * `--renames "old:new,old2:new2"` 문자열을 테이블별 매핑으로 펼친다 — 후보 테이블의 dropped/added
32
+ * 에 해당 쌍이 있을 때만 그 테이블에 적용(테이블 간 동명 컬럼 오적용 방지).
33
+ *
34
+ * **어떤 후보와도 매치되지 않는 쌍은 fail-fast** 한다(`migration.rename_unmatched`) — 오타를
35
+ * 조용히 버리면 사용자는 rename 을 명시했다고 믿는 채 무경고 DROP COLUMN(데이터 손실) 마이그레이션이
36
+ * 생성된다(P1 보호의 입구).
37
+ *
38
+ * @param {string} spec - `old:new[,old:new...]`.
39
+ * @param {Array<{ table: string, dropped: string[], added: string[] }>} candidates
40
+ * @returns {Record<string, Record<string, string>>}
41
+ * @throws {MegaConfigError} `migration.rename_invalid` - 형식 오류. `migration.rename_unmatched` - 후보 불일치.
42
+ */
43
+ export function parseRenamesSpec(spec: string, candidates: Array<{
44
+ table: string;
45
+ dropped: string[];
46
+ added: string[];
47
+ }>): Record<string, Record<string, string>>;