sonamu 0.10.12 → 0.10.13

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 (513) hide show
  1. package/dist/ai/agents/agent.d.ts +1 -1
  2. package/dist/ai/agents/agent.d.ts.map +1 -1
  3. package/dist/ai/agents/agent.js +5 -6
  4. package/dist/ai/agents/types.d.ts +1 -1
  5. package/dist/ai/agents/types.d.ts.map +1 -1
  6. package/dist/ai/providers/rtzr/api.js +18 -18
  7. package/dist/ai/providers/rtzr/error.d.ts.map +1 -1
  8. package/dist/ai/providers/rtzr/error.js +17 -15
  9. package/dist/ai/providers/rtzr/model.d.ts.map +1 -1
  10. package/dist/ai/providers/rtzr/model.js +3 -2
  11. package/dist/ai/providers/rtzr/options.d.ts.map +1 -1
  12. package/dist/ai/providers/rtzr/options.js +16 -16
  13. package/dist/ai/providers/rtzr/provider.d.ts.map +1 -1
  14. package/dist/ai/providers/rtzr/provider.js +9 -9
  15. package/dist/ai/providers/rtzr/utils.d.ts.map +1 -1
  16. package/dist/ai/providers/rtzr/utils.js +1 -1
  17. package/dist/api/caster.d.ts.map +1 -1
  18. package/dist/api/caster.js +17 -17
  19. package/dist/api/code-converters.d.ts +4 -2
  20. package/dist/api/code-converters.d.ts.map +1 -1
  21. package/dist/api/code-converters.js +100 -19
  22. package/dist/api/config.d.ts +16 -1
  23. package/dist/api/config.d.ts.map +1 -1
  24. package/dist/api/config.js +28 -21
  25. package/dist/api/context.d.ts +2 -2
  26. package/dist/api/context.d.ts.map +1 -1
  27. package/dist/api/context.js +1 -1
  28. package/dist/api/decorators.d.ts.map +1 -1
  29. package/dist/api/decorators.js +18 -11
  30. package/dist/api/http-validator.d.ts +36 -0
  31. package/dist/api/http-validator.d.ts.map +1 -0
  32. package/dist/api/http-validator.js +72 -0
  33. package/dist/api/index.js +6 -4
  34. package/dist/api/sonamu.d.ts +59 -20
  35. package/dist/api/sonamu.d.ts.map +1 -1
  36. package/dist/api/sonamu.js +250 -106
  37. package/dist/api/websocket-helpers.d.ts +7 -5
  38. package/dist/api/websocket-helpers.d.ts.map +1 -1
  39. package/dist/api/websocket-helpers.js +6 -6
  40. package/dist/auth/audit-log/builders.d.ts.map +1 -1
  41. package/dist/auth/audit-log/builders.js +1 -1
  42. package/dist/auth/audit-log/client-ip.d.ts +1 -1
  43. package/dist/auth/audit-log/client-ip.d.ts.map +1 -1
  44. package/dist/auth/audit-log/client-ip.js +4 -2
  45. package/dist/auth/audit-log/events.d.ts +5 -1
  46. package/dist/auth/audit-log/events.d.ts.map +1 -1
  47. package/dist/auth/audit-log/events.js +1 -1
  48. package/dist/auth/audit-log/plugin.d.ts +0 -8
  49. package/dist/auth/audit-log/plugin.d.ts.map +1 -1
  50. package/dist/auth/audit-log/plugin.js +48 -52
  51. package/dist/auth/audit-log-ingestor.d.ts.map +1 -1
  52. package/dist/auth/audit-log-ingestor.js +16 -12
  53. package/dist/auth/auth-generator.d.ts.map +1 -1
  54. package/dist/auth/auth-generator.js +1 -1
  55. package/dist/auth/better-auth-request.d.ts.map +1 -1
  56. package/dist/auth/better-auth-request.js +6 -5
  57. package/dist/auth/knex-adapter.js +1 -1
  58. package/dist/auth/plugins/entity-definitions/index.d.ts +13 -1
  59. package/dist/auth/plugins/entity-definitions/index.d.ts.map +1 -1
  60. package/dist/auth/plugins/entity-definitions/index.js +1 -1
  61. package/dist/auth/plugins/wrappers/admin.d.ts +1 -1
  62. package/dist/bin/build-config.d.ts +25 -0
  63. package/dist/bin/build-config.d.ts.map +1 -1
  64. package/dist/bin/build-config.js +105 -2
  65. package/dist/bin/cli.js +131 -27
  66. package/dist/bin/compiler-policy.d.ts +3 -0
  67. package/dist/bin/compiler-policy.d.ts.map +1 -0
  68. package/dist/bin/compiler-policy.js +24 -0
  69. package/dist/bin/fixture.d.ts.map +1 -1
  70. package/dist/bin/fixture.js +5 -3
  71. package/dist/bin/test-command.d.ts +22 -1
  72. package/dist/bin/test-command.d.ts.map +1 -1
  73. package/dist/bin/test-command.js +18 -10
  74. package/dist/bin/ts-loader-registration.d.ts +7 -1
  75. package/dist/bin/ts-loader-registration.d.ts.map +1 -1
  76. package/dist/bin/ts-loader-registration.js +13 -4
  77. package/dist/cache/decorator.d.ts.map +1 -1
  78. package/dist/cache/decorator.js +11 -4
  79. package/dist/compress/compress.d.ts.map +1 -1
  80. package/dist/compress/compress.js +1 -1
  81. package/dist/cone/cone-generator.d.ts +14 -1
  82. package/dist/cone/cone-generator.d.ts.map +1 -1
  83. package/dist/cone/cone-generator.js +13 -9
  84. package/dist/database/_batch_update.js +1 -1
  85. package/dist/database/base-model.d.ts +22 -10
  86. package/dist/database/base-model.d.ts.map +1 -1
  87. package/dist/database/base-model.js +26 -16
  88. package/dist/database/base-model.types.d.ts +15 -3
  89. package/dist/database/base-model.types.d.ts.map +1 -1
  90. package/dist/database/db.d.ts +12 -2
  91. package/dist/database/db.d.ts.map +1 -1
  92. package/dist/database/db.js +10 -7
  93. package/dist/database/knex.d.ts.map +1 -1
  94. package/dist/database/knex.js +17 -14
  95. package/dist/database/puri.d.ts +11 -9
  96. package/dist/database/puri.d.ts.map +1 -1
  97. package/dist/database/puri.js +93 -79
  98. package/dist/database/puri.types.d.ts +21 -21
  99. package/dist/database/puri.types.d.ts.map +1 -1
  100. package/dist/database/puri.types.js +1 -1
  101. package/dist/database/upsert-builder.d.ts +12 -10
  102. package/dist/database/upsert-builder.d.ts.map +1 -1
  103. package/dist/database/upsert-builder.js +20 -12
  104. package/dist/dict/sd.d.ts.map +1 -1
  105. package/dist/dict/sd.js +1 -1
  106. package/dist/dict/sonamu-dictionary.d.ts.map +1 -1
  107. package/dist/dict/sonamu-dictionary.js +1 -1
  108. package/dist/dict/utils.d.ts.map +1 -1
  109. package/dist/dict/utils.js +7 -2
  110. package/dist/entity/entity-manager.d.ts +13 -4
  111. package/dist/entity/entity-manager.d.ts.map +1 -1
  112. package/dist/entity/entity-manager.js +19 -11
  113. package/dist/entity/entity-template-cone.d.ts +73 -5
  114. package/dist/entity/entity-template-cone.d.ts.map +1 -1
  115. package/dist/entity/entity-template-cone.js +4 -2
  116. package/dist/entity/entity.d.ts +6 -2
  117. package/dist/entity/entity.d.ts.map +1 -1
  118. package/dist/entity/entity.js +30 -28
  119. package/dist/env.d.ts +3 -1
  120. package/dist/env.d.ts.map +1 -1
  121. package/dist/env.js +1 -1
  122. package/dist/exceptions/error-handler.d.ts.map +1 -1
  123. package/dist/exceptions/error-handler.js +7 -2
  124. package/dist/exceptions/so-exceptions.d.ts +24 -20
  125. package/dist/exceptions/so-exceptions.d.ts.map +1 -1
  126. package/dist/exceptions/so-exceptions.js +4 -2
  127. package/dist/filter/utils.d.ts +7 -2
  128. package/dist/filter/utils.d.ts.map +1 -1
  129. package/dist/filter/utils.js +8 -6
  130. package/dist/index.d.ts +3 -0
  131. package/dist/index.d.ts.map +1 -1
  132. package/dist/index.js +12 -6
  133. package/dist/logger/configure.d.ts.map +1 -1
  134. package/dist/logger/configure.js +10 -10
  135. package/dist/migration/code-generation.d.ts.map +1 -1
  136. package/dist/migration/code-generation.js +50 -46
  137. package/dist/migration/index-where-predicate.d.ts.map +1 -1
  138. package/dist/migration/index-where-predicate.js +22 -8
  139. package/dist/migration/migration-set.d.ts.map +1 -1
  140. package/dist/migration/migration-set.js +1 -1
  141. package/dist/migration/migrator.d.ts +3 -2
  142. package/dist/migration/migrator.d.ts.map +1 -1
  143. package/dist/migration/migrator.js +27 -21
  144. package/dist/migration/postgresql-schema-reader.d.ts.map +1 -1
  145. package/dist/migration/postgresql-schema-reader.js +51 -36
  146. package/dist/migration/slack-confirm.d.ts.map +1 -1
  147. package/dist/migration/slack-confirm.js +1 -1
  148. package/dist/naite/naite-reporter.js +2 -2
  149. package/dist/naite/naite.d.ts +74 -15
  150. package/dist/naite/naite.d.ts.map +1 -1
  151. package/dist/naite/naite.js +5 -19
  152. package/dist/runtime-type.d.ts +6 -0
  153. package/dist/runtime-type.d.ts.map +1 -0
  154. package/dist/runtime-type.js +26 -0
  155. package/dist/ssr/hmr-opt-out.d.ts +26 -0
  156. package/dist/ssr/hmr-opt-out.d.ts.map +1 -0
  157. package/dist/ssr/hmr-opt-out.js +59 -0
  158. package/dist/ssr/renderer.d.ts.map +1 -1
  159. package/dist/ssr/renderer.js +4 -1
  160. package/dist/storage/base-file.js +14 -14
  161. package/dist/storage/buffered-file.d.ts +2 -2
  162. package/dist/storage/buffered-file.d.ts.map +1 -1
  163. package/dist/storage/buffered-file.js +12 -12
  164. package/dist/storage/s3-driver.d.ts.map +1 -1
  165. package/dist/storage/s3-driver.js +1 -1
  166. package/dist/storage/uploaded-file.d.ts +2 -2
  167. package/dist/storage/uploaded-file.d.ts.map +1 -1
  168. package/dist/storage/uploaded-file.js +8 -8
  169. package/dist/stream/sse.js +11 -11
  170. package/dist/stream/ws-core.d.ts +1 -1
  171. package/dist/stream/ws-core.d.ts.map +1 -1
  172. package/dist/stream/ws-delivery.d.ts +1 -1
  173. package/dist/stream/ws-delivery.d.ts.map +1 -1
  174. package/dist/stream/ws-delivery.js +6 -4
  175. package/dist/stream/ws-local-connection-store.d.ts.map +1 -1
  176. package/dist/stream/ws-local-connection-store.js +4 -2
  177. package/dist/stream/ws-presence-store.js +1 -1
  178. package/dist/stream/ws-registry.d.ts +4 -4
  179. package/dist/stream/ws-registry.d.ts.map +1 -1
  180. package/dist/stream/ws-registry.js +4 -2
  181. package/dist/stream/ws-telemetry.d.ts +16 -12
  182. package/dist/stream/ws-telemetry.d.ts.map +1 -1
  183. package/dist/stream/ws-telemetry.js +22 -18
  184. package/dist/stream/ws.d.ts +18 -12
  185. package/dist/stream/ws.d.ts.map +1 -1
  186. package/dist/stream/ws.js +26 -22
  187. package/dist/syncer/api-parser.js +1 -1
  188. package/dist/syncer/checksum.d.ts.map +1 -1
  189. package/dist/syncer/checksum.js +7 -8
  190. package/dist/syncer/code-generator.d.ts.map +1 -1
  191. package/dist/syncer/code-generator.js +13 -14
  192. package/dist/syncer/entity-operations.d.ts.map +1 -1
  193. package/dist/syncer/entity-operations.js +5 -6
  194. package/dist/syncer/file-copy.d.ts +5 -0
  195. package/dist/syncer/file-copy.d.ts.map +1 -0
  196. package/dist/syncer/file-copy.js +36 -0
  197. package/dist/syncer/file-patterns.d.ts +1 -0
  198. package/dist/syncer/file-patterns.d.ts.map +1 -1
  199. package/dist/syncer/file-patterns.js +5 -2
  200. package/dist/syncer/file-tracking.d.ts.map +1 -1
  201. package/dist/syncer/file-tracking.js +5 -4
  202. package/dist/syncer/filesystem-dependencies.d.ts +15 -0
  203. package/dist/syncer/filesystem-dependencies.d.ts.map +1 -0
  204. package/dist/syncer/filesystem-dependencies.js +53 -0
  205. package/dist/syncer/module-loader.d.ts +1 -1
  206. package/dist/syncer/module-loader.d.ts.map +1 -1
  207. package/dist/syncer/module-loader.js +6 -4
  208. package/dist/syncer/syncer-actions.d.ts +4 -0
  209. package/dist/syncer/syncer-actions.d.ts.map +1 -1
  210. package/dist/syncer/syncer-actions.js +34 -17
  211. package/dist/syncer/syncer.d.ts +17 -6
  212. package/dist/syncer/syncer.d.ts.map +1 -1
  213. package/dist/syncer/syncer.js +71 -29
  214. package/dist/syncer/watcher.d.ts.map +1 -1
  215. package/dist/syncer/watcher.js +3 -3
  216. package/dist/tasks/decorator.d.ts +6 -6
  217. package/dist/tasks/decorator.d.ts.map +1 -1
  218. package/dist/tasks/decorator.js +4 -4
  219. package/dist/tasks/step-wrapper.d.ts +6 -4
  220. package/dist/tasks/step-wrapper.d.ts.map +1 -1
  221. package/dist/tasks/step-wrapper.js +5 -5
  222. package/dist/tasks/workflow-manager.d.ts.map +1 -1
  223. package/dist/tasks/workflow-manager.js +13 -7
  224. package/dist/template/entity-converter.d.ts +1 -1
  225. package/dist/template/entity-converter.d.ts.map +1 -1
  226. package/dist/template/entity-converter.js +2 -2
  227. package/dist/template/helpers.d.ts +8 -6
  228. package/dist/template/helpers.d.ts.map +1 -1
  229. package/dist/template/helpers.js +1 -1
  230. package/dist/template/implementations/generated.template.d.ts.map +1 -1
  231. package/dist/template/implementations/generated.template.js +4 -4
  232. package/dist/template/implementations/generated_http.template.d.ts +7 -4
  233. package/dist/template/implementations/generated_http.template.d.ts.map +1 -1
  234. package/dist/template/implementations/generated_http.template.js +21 -21
  235. package/dist/template/implementations/generated_sso.template.d.ts.map +1 -1
  236. package/dist/template/implementations/generated_sso.template.js +6 -3
  237. package/dist/template/implementations/http_validators.template.d.ts +18 -0
  238. package/dist/template/implementations/http_validators.template.d.ts.map +1 -0
  239. package/dist/template/implementations/http_validators.template.js +127 -0
  240. package/dist/template/implementations/model.template.d.ts.map +1 -1
  241. package/dist/template/implementations/model.template.js +1 -1
  242. package/dist/template/implementations/queries.template.js +1 -1
  243. package/dist/template/implementations/sd.template.d.ts.map +1 -1
  244. package/dist/template/implementations/sd.template.js +79 -39
  245. package/dist/template/implementations/services.template.d.ts.map +1 -1
  246. package/dist/template/implementations/services.template.js +6 -4
  247. package/dist/template/implementations/view_form.template.d.ts +6 -1
  248. package/dist/template/implementations/view_form.template.d.ts.map +1 -1
  249. package/dist/template/implementations/view_form.template.js +23 -15
  250. package/dist/template/implementations/view_list.template.d.ts.map +1 -1
  251. package/dist/template/implementations/view_list.template.js +11 -6
  252. package/dist/template/template-manager.d.ts.map +1 -1
  253. package/dist/template/template-manager.js +9 -7
  254. package/dist/template/template-types.d.ts +12 -5
  255. package/dist/template/template-types.d.ts.map +1 -1
  256. package/dist/template/template-types.js +1 -1
  257. package/dist/template/template.d.ts +2 -2
  258. package/dist/template/template.d.ts.map +1 -1
  259. package/dist/template/template.js +6 -4
  260. package/dist/template/zod-converter.d.ts +0 -19
  261. package/dist/template/zod-converter.d.ts.map +1 -1
  262. package/dist/template/zod-converter.js +100 -84
  263. package/dist/testing/_relation-graph.d.ts.map +1 -1
  264. package/dist/testing/_relation-graph.js +2 -1
  265. package/dist/testing/bootstrap.d.ts.map +1 -1
  266. package/dist/testing/bootstrap.js +9 -6
  267. package/dist/testing/data-explorer.d.ts +32 -7
  268. package/dist/testing/data-explorer.d.ts.map +1 -1
  269. package/dist/testing/data-explorer.js +77 -31
  270. package/dist/testing/dev-test-routes.d.ts +8 -1
  271. package/dist/testing/dev-test-routes.d.ts.map +1 -1
  272. package/dist/testing/dev-test-routes.js +125 -108
  273. package/dist/testing/dev-vitest-manager.d.ts +54 -8
  274. package/dist/testing/dev-vitest-manager.d.ts.map +1 -1
  275. package/dist/testing/dev-vitest-manager.js +24 -9
  276. package/dist/testing/faker-mappings.d.ts +412 -1
  277. package/dist/testing/faker-mappings.d.ts.map +1 -1
  278. package/dist/testing/faker-mappings.js +1 -1
  279. package/dist/testing/filesystem.d.ts +2 -0
  280. package/dist/testing/filesystem.d.ts.map +1 -0
  281. package/dist/testing/filesystem.js +7 -0
  282. package/dist/testing/fixture-generator.d.ts +25 -8
  283. package/dist/testing/fixture-generator.d.ts.map +1 -1
  284. package/dist/testing/fixture-generator.js +132 -73
  285. package/dist/testing/fixture-loader.d.ts +3 -1
  286. package/dist/testing/fixture-loader.d.ts.map +1 -1
  287. package/dist/testing/fixture-loader.js +1 -20
  288. package/dist/testing/fixture-manager.d.ts +8 -7
  289. package/dist/testing/fixture-manager.d.ts.map +1 -1
  290. package/dist/testing/fixture-manager.js +91 -59
  291. package/dist/testing/global-setup.d.ts.map +1 -1
  292. package/dist/testing/global-setup.js +5 -2
  293. package/dist/testing/index.d.ts +2 -0
  294. package/dist/testing/index.d.ts.map +1 -1
  295. package/dist/testing/index.js +6 -3
  296. package/dist/types/types.d.ts +101 -99
  297. package/dist/types/types.d.ts.map +1 -1
  298. package/dist/types/types.js +234 -225
  299. package/dist/ui/ai-api.d.ts.map +1 -1
  300. package/dist/ui/ai-api.js +1 -1
  301. package/dist/ui/ai-client.d.ts.map +1 -1
  302. package/dist/ui/ai-client.js +28 -18
  303. package/dist/ui/api.d.ts.map +1 -1
  304. package/dist/ui/api.js +135 -128
  305. package/dist/ui/async-route.d.ts +3 -0
  306. package/dist/ui/async-route.d.ts.map +1 -0
  307. package/dist/ui/async-route.js +12 -0
  308. package/dist/ui/cdd-service.d.ts +9 -7
  309. package/dist/ui/cdd-service.d.ts.map +1 -1
  310. package/dist/ui/cdd-service.js +7 -5
  311. package/dist/ui/migrations-api.d.ts.map +1 -1
  312. package/dist/ui/migrations-api.js +17 -15
  313. package/dist/ui-web/assets/index-DV1AAq6W.js +178 -0
  314. package/dist/ui-web/index.html +1 -1
  315. package/dist/utils/formatter.d.ts.map +1 -1
  316. package/dist/utils/formatter.js +7 -5
  317. package/dist/utils/fs-utils.d.ts +3 -3
  318. package/dist/utils/fs-utils.d.ts.map +1 -1
  319. package/dist/utils/fs-utils.js +6 -6
  320. package/dist/utils/model.d.ts +3 -5
  321. package/dist/utils/model.d.ts.map +1 -1
  322. package/dist/utils/model.js +1 -1
  323. package/dist/utils/object-utils.d.ts +1 -1
  324. package/dist/utils/object-utils.d.ts.map +1 -1
  325. package/dist/utils/object-utils.js +17 -16
  326. package/dist/utils/process-utils.d.ts.map +1 -1
  327. package/dist/utils/process-utils.js +4 -2
  328. package/dist/utils/runtime-value.d.ts +13 -0
  329. package/dist/utils/runtime-value.d.ts.map +1 -0
  330. package/dist/utils/runtime-value.js +40 -0
  331. package/dist/utils/sql-parser.d.ts +8 -1
  332. package/dist/utils/sql-parser.d.ts.map +1 -1
  333. package/dist/utils/sql-parser.js +6 -3
  334. package/dist/utils/type-utils.d.ts.map +1 -1
  335. package/dist/utils/type-utils.js +10 -8
  336. package/dist/utils/utils.d.ts +2 -2
  337. package/dist/utils/utils.d.ts.map +1 -1
  338. package/dist/utils/utils.js +11 -8
  339. package/dist/utils/zod-error.d.ts.map +1 -1
  340. package/dist/utils/zod-error.js +7 -4
  341. package/dist/vector/chunking.d.ts.map +1 -1
  342. package/dist/vector/chunking.js +1 -1
  343. package/dist/vector/embedding.d.ts.map +1 -1
  344. package/dist/vector/embedding.js +1 -1
  345. package/dist/vector/types.d.ts +3 -2
  346. package/dist/vector/types.d.ts.map +1 -1
  347. package/package.json +5 -3
  348. package/src/ai/agents/agent.ts +5 -5
  349. package/src/ai/agents/types.ts +1 -1
  350. package/src/ai/providers/rtzr/__tests__/model.test.ts +2 -2
  351. package/src/ai/providers/rtzr/error.ts +5 -3
  352. package/src/ai/providers/rtzr/model.ts +3 -2
  353. package/src/ai/providers/rtzr/options.ts +10 -5
  354. package/src/ai/providers/rtzr/provider.ts +10 -10
  355. package/src/ai/providers/rtzr/utils.ts +3 -1
  356. package/src/api/__tests__/config.test.ts +11 -21
  357. package/src/api/__tests__/sonamu.http-validator.test.ts +512 -0
  358. package/src/api/__tests__/sonamu.websocket.test.ts +51 -41
  359. package/src/api/__tests__/zod-compiler-policy.test.ts +95 -0
  360. package/src/api/caster.ts +6 -8
  361. package/src/api/code-converters.ts +136 -36
  362. package/src/api/config.ts +62 -4
  363. package/src/api/context.ts +3 -3
  364. package/src/api/decorators.ts +28 -17
  365. package/src/api/http-validator.ts +149 -0
  366. package/src/api/sonamu.ts +459 -152
  367. package/src/api/websocket-helpers.ts +24 -17
  368. package/src/auth/audit-log/builders.ts +3 -2
  369. package/src/auth/audit-log/client-ip.ts +4 -2
  370. package/src/auth/audit-log/events.ts +15 -1
  371. package/src/auth/audit-log/plugin.ts +129 -200
  372. package/src/auth/audit-log-ingestor.ts +19 -15
  373. package/src/auth/auth-generator.ts +10 -5
  374. package/src/auth/better-auth-request.ts +4 -3
  375. package/src/auth/knex-adapter.ts +8 -2
  376. package/src/auth/plugins/entity-definitions/index.ts +6 -5
  377. package/src/bin/__tests__/http-validator-benchmark.test.ts +94 -0
  378. package/src/bin/__tests__/test-command.test.ts +9 -15
  379. package/src/bin/__tests__/ts-loader-register.test.ts +15 -17
  380. package/src/bin/__tests__/zod-compiler-build.test.ts +307 -0
  381. package/src/bin/build-config.ts +167 -0
  382. package/src/bin/cli.ts +153 -36
  383. package/src/bin/compiler-policy.ts +35 -0
  384. package/src/bin/fixture.ts +14 -3
  385. package/src/bin/test-command.ts +74 -29
  386. package/src/bin/ts-loader-registration.ts +22 -4
  387. package/src/cache/decorator.ts +10 -3
  388. package/src/compress/compress.ts +17 -4
  389. package/src/cone/cone-generator.ts +34 -6
  390. package/src/database/__tests__/db.test.ts +1 -0
  391. package/src/database/__tests__/puri.test.ts +16 -15
  392. package/src/database/__tests__/transaction-scope.test.ts +5 -0
  393. package/src/database/_batch_update.ts +1 -0
  394. package/src/database/base-model.ts +81 -50
  395. package/src/database/base-model.types.ts +6 -6
  396. package/src/database/db.ts +29 -19
  397. package/src/database/knex.ts +30 -17
  398. package/src/database/puri-subset.test-d.ts +17 -0
  399. package/src/database/puri.ts +181 -143
  400. package/src/database/puri.types.test-d.ts +31 -1
  401. package/src/database/puri.types.ts +23 -21
  402. package/src/database/upsert-builder.ts +75 -53
  403. package/src/dict/sd.ts +15 -5
  404. package/src/dict/sonamu-dictionary.ts +6 -6
  405. package/src/dict/utils.ts +9 -1
  406. package/src/entity/entity-manager.ts +26 -9
  407. package/src/entity/entity-template-cone.ts +5 -10
  408. package/src/entity/entity.ts +50 -34
  409. package/src/env.ts +7 -3
  410. package/src/exceptions/error-handler.ts +17 -2
  411. package/src/exceptions/so-exceptions.ts +26 -20
  412. package/src/filter/utils.ts +21 -11
  413. package/src/index.ts +3 -0
  414. package/src/logger/configure.ts +26 -18
  415. package/src/migration/__tests__/migrator.test.ts +50 -57
  416. package/src/migration/code-generation.ts +132 -104
  417. package/src/migration/index-where-predicate.ts +51 -24
  418. package/src/migration/migration-set.ts +11 -5
  419. package/src/migration/migrator.ts +68 -41
  420. package/src/migration/postgresql-schema-reader.ts +52 -47
  421. package/src/migration/slack-confirm.ts +17 -15
  422. package/src/naite/naite-reporter.ts +1 -1
  423. package/src/naite/naite.ts +97 -24
  424. package/src/runtime-type.ts +34 -0
  425. package/src/ssr/hmr-opt-out.ts +78 -0
  426. package/src/ssr/renderer.ts +6 -0
  427. package/src/storage/base-file.ts +13 -13
  428. package/src/storage/buffered-file.ts +11 -11
  429. package/src/storage/s3-driver.ts +4 -1
  430. package/src/storage/uploaded-file.ts +8 -8
  431. package/src/stream/__tests__/ws-contracts.test.ts +4 -2
  432. package/src/stream/__tests__/ws-telemetry.test.ts +1 -1
  433. package/src/stream/__tests__/ws.test.ts +30 -6
  434. package/src/stream/sse.ts +12 -11
  435. package/src/stream/ws-core.ts +1 -1
  436. package/src/stream/ws-delivery.ts +16 -7
  437. package/src/stream/ws-local-connection-store.ts +2 -3
  438. package/src/stream/ws-presence-store.ts +6 -1
  439. package/src/stream/ws-registry.ts +16 -7
  440. package/src/stream/ws-telemetry.ts +66 -43
  441. package/src/stream/ws.ts +73 -39
  442. package/src/syncer/__tests__/api-parser.websocket-type-ref.test.ts +3 -2
  443. package/src/syncer/__tests__/http-validator-registry.test.ts +137 -0
  444. package/src/syncer/api-parser.ts +67 -27
  445. package/src/syncer/checksum.ts +17 -11
  446. package/src/syncer/code-generator.ts +25 -17
  447. package/src/syncer/entity-operations.ts +3 -5
  448. package/src/syncer/file-copy.ts +46 -0
  449. package/src/syncer/file-patterns.ts +11 -8
  450. package/src/syncer/file-tracking.ts +3 -4
  451. package/src/syncer/filesystem-dependencies.ts +73 -0
  452. package/src/syncer/module-loader.ts +8 -4
  453. package/src/syncer/syncer-actions.ts +56 -18
  454. package/src/syncer/syncer.ts +116 -43
  455. package/src/syncer/watcher.ts +8 -4
  456. package/src/tasks/decorator.ts +20 -12
  457. package/src/tasks/step-wrapper.ts +19 -9
  458. package/src/tasks/workflow-manager.ts +15 -9
  459. package/src/template/__tests__/http_validators.template.test.ts +160 -0
  460. package/src/template/__tests__/services.template.mutation.test.ts +24 -23
  461. package/src/template/__tests__/services.template.websocket.test.ts +21 -25
  462. package/src/template/entity-converter.ts +5 -2
  463. package/src/template/helpers.ts +8 -9
  464. package/src/template/implementations/generated.template.ts +5 -4
  465. package/src/template/implementations/generated_http.template.ts +61 -15
  466. package/src/template/implementations/generated_sso.template.ts +15 -4
  467. package/src/template/implementations/http_validators.template.ts +175 -0
  468. package/src/template/implementations/model.template.ts +3 -1
  469. package/src/template/implementations/sd.template.ts +81 -41
  470. package/src/template/implementations/services.template.ts +2 -2
  471. package/src/template/implementations/view_form.template.ts +56 -39
  472. package/src/template/implementations/view_list.template.ts +31 -23
  473. package/src/template/template-manager.ts +15 -13
  474. package/src/template/template-types.ts +13 -5
  475. package/src/template/template.ts +4 -3
  476. package/src/template/zod-converter.ts +206 -91
  477. package/src/testing/__tests__/dev-test-routes.test.ts +85 -25
  478. package/src/testing/__tests__/dev-vitest-manager.test.ts +15 -15
  479. package/src/testing/_relation-graph.ts +4 -1
  480. package/src/testing/bootstrap.ts +12 -5
  481. package/src/testing/data-explorer.ts +102 -53
  482. package/src/testing/dev-test-routes.ts +87 -50
  483. package/src/testing/dev-vitest-manager.ts +88 -32
  484. package/src/testing/faker-mappings.ts +2 -2
  485. package/src/testing/filesystem.ts +1 -0
  486. package/src/testing/fixture-generator.ts +191 -131
  487. package/src/testing/fixture-loader.ts +5 -1
  488. package/src/testing/fixture-manager.ts +129 -90
  489. package/src/testing/global-setup.ts +7 -3
  490. package/src/testing/index.ts +5 -0
  491. package/src/types/__tests__/entity-json-schema-search-text.test.ts +9 -3
  492. package/src/types/types.ts +184 -158
  493. package/src/ui/ai-api.ts +9 -7
  494. package/src/ui/ai-client.ts +61 -56
  495. package/src/ui/api.ts +727 -616
  496. package/src/ui/async-route.ts +4 -0
  497. package/src/ui/cdd-service.ts +35 -12
  498. package/src/ui/migrations-api.ts +63 -51
  499. package/src/utils/formatter.ts +7 -3
  500. package/src/utils/fs-utils.ts +5 -5
  501. package/src/utils/model.ts +4 -5
  502. package/src/utils/object-utils.ts +32 -22
  503. package/src/utils/process-utils.ts +4 -1
  504. package/src/utils/runtime-value.ts +43 -0
  505. package/src/utils/sql-parser.ts +13 -6
  506. package/src/utils/type-utils.ts +9 -7
  507. package/src/utils/utils.ts +19 -21
  508. package/src/utils/zod-error.ts +4 -2
  509. package/src/vector/chunking.ts +6 -1
  510. package/src/vector/embedding.ts +2 -1
  511. package/src/vector/types.ts +4 -2
  512. package/tsdown.api.config.ts +5 -2
  513. package/dist/ui-web/assets/index-C0m1pk6K.js +0 -177
@@ -27,38 +27,45 @@ export type SonamuLoggingOptions<TSinkId extends string, TFilterId extends strin
27
27
 
28
28
  // fastify에 대한 기본 sink 설정
29
29
  function defaultFastifySink(fastifyCategory: readonly string[]): Sink {
30
- const formatter = ((formatter: TextFormatter, record: LogRecord) => {
30
+ const fastifyFormatter = ((formatRecord: TextFormatter, record: LogRecord) => {
31
31
  // Fastify API Route에 대한 Logger의 경우, 응답 코드와 요청 URL을 추가
32
- const filterFastify = (request: FastifyRequest, record: LogRecord, responseCode?: number) => {
32
+ const filterFastify = (
33
+ request: FastifyRequest,
34
+ requestRecord: LogRecord,
35
+ responseCode?: number,
36
+ ) => {
33
37
  if (!request.url.startsWith("/api")) {
34
- return formatter(record);
38
+ return formatRecord(requestRecord);
35
39
  }
36
40
 
37
- const lastItem = record.message[record.message.length - 1] as string;
38
- return formatter({
39
- ...record,
41
+ const lastItem = /* SAFETY: LogTape 구성 스키마가 이 값의 타입을 보장한다. */ requestRecord
42
+ .message[requestRecord.message.length - 1] as string;
43
+ return formatRecord({
44
+ ...requestRecord,
40
45
  message: [
41
- ...record.message.slice(0, -1),
46
+ ...requestRecord.message.slice(0, -1),
42
47
  `[${request.method}${responseCode ? `:${responseCode}` : ""}] ${request.originalUrl} - ${lastItem}`,
43
48
  ],
44
49
  });
45
50
  };
46
51
 
47
52
  if (!isSameCategory(fastifyCategory, [...record.category])) {
48
- return formatter(record);
53
+ return formatRecord(record);
49
54
  }
50
55
 
51
56
  if ("req" in record.properties && record.properties.req !== null) {
52
- const request = record.properties.req as FastifyRequest;
57
+ const request = /* SAFETY: LogTape 구성 스키마가 이 값의 타입을 보장한다. */ record.properties
58
+ .req as FastifyRequest;
53
59
  return filterFastify(request, record);
54
60
  }
55
61
 
56
62
  if ("res" in record.properties && record.properties.res !== null) {
57
- const reply = record.properties.res as FastifyReply;
63
+ const reply = /* SAFETY: LogTape 구성 스키마가 이 값의 타입을 보장한다. */ record.properties
64
+ .res as FastifyReply;
58
65
  return filterFastify(reply.request, record, reply.statusCode);
59
66
  }
60
67
 
61
- return formatter(record);
68
+ return formatRecord(record);
62
69
  }).bind(
63
70
  null,
64
71
  getPrettyFormatter({
@@ -69,7 +76,7 @@ function defaultFastifySink(fastifyCategory: readonly string[]): Sink {
69
76
  );
70
77
 
71
78
  return getConsoleSink({
72
- formatter,
79
+ formatter: fastifyFormatter,
73
80
  });
74
81
  }
75
82
 
@@ -81,12 +88,14 @@ function defaultFastifyFilter(fastifyCategory: readonly string[]): Filter {
81
88
  }
82
89
 
83
90
  if ("req" in record.properties && record.properties.req !== null) {
84
- const request = record.properties.req as FastifyRequest;
91
+ const request = /* SAFETY: LogTape 구성 스키마가 이 값의 타입을 보장한다. */ record.properties
92
+ .req as FastifyRequest;
85
93
  return request.url.startsWith("/api") && request.url !== "/api/healthcheck";
86
94
  }
87
95
 
88
96
  if ("res" in record.properties && record.properties.res !== null) {
89
- const reply = record.properties.res as FastifyReply;
97
+ const reply = /* SAFETY: LogTape 구성 스키마가 이 값의 타입을 보장한다. */ record.properties
98
+ .res as FastifyReply;
90
99
  return reply.request.url.startsWith("/api") && reply.request.url !== "/api/healthcheck";
91
100
  }
92
101
 
@@ -103,15 +112,14 @@ export async function configureLogTape<TSinkId extends string, TFilterId extends
103
112
  const sinks = {
104
113
  "fastify-console": defaultFastifySink(fastifyCategory),
105
114
  ...options.sinks,
106
- } as Record<TSinkId | "fastify-console", Sink>;
115
+ };
107
116
 
108
117
  const filters = {
109
118
  "fastify-console": defaultFastifyFilter(fastifyCategory),
110
119
  ...options.filters,
111
- } as Record<TFilterId | "fastify-console", FilterLike>;
120
+ };
112
121
 
113
- const loggers: Set<LoggerConfig<TSinkId | "fastify-console", TFilterId | "fastify-console">> =
114
- new Set(options.loggers ?? []);
122
+ const loggers = new Set<LoggerConfig<string, string>>(options.loggers ?? []);
115
123
 
116
124
  // logtape의 meta logger 표시를 비활성화
117
125
  loggers.add({
@@ -7,6 +7,27 @@ import { setSDConfig } from "../../dict/sd";
7
7
  import { Migrator } from "../migrator";
8
8
  import { SlackConfirm } from "../slack-confirm";
9
9
 
10
+ function createConfig(targets: NonNullable<SonamuConfig["slackConfirm"]>["targets"]): SonamuConfig {
11
+ return {
12
+ projectName: "sonamu-test",
13
+ api: { dir: "src", route: { prefix: "/api" } },
14
+ i18n: { defaultLocale: "ko", supportedLocales: ["ko", "en"] },
15
+ sync: { targets: [] },
16
+ database: {},
17
+ server: {
18
+ apiConfig: {
19
+ contextProvider: (defaultContext) => defaultContext,
20
+ guardHandler: () => undefined,
21
+ },
22
+ },
23
+ slackConfirm: {
24
+ targets,
25
+ botToken: "xoxb-test",
26
+ channelId: "C123",
27
+ },
28
+ };
29
+ }
30
+
10
31
  describe("Migrator environment target filtering", () => {
11
32
  const originalEnv = { ...process.env };
12
33
  const presets: SonamuDBPreset[] = [
@@ -21,18 +42,19 @@ describe("Migrator environment target filtering", () => {
21
42
  "production_readonly",
22
43
  ];
23
44
 
24
- const dbConfig = Object.fromEntries(
25
- presets.map((preset) => [
26
- preset,
27
- {
28
- client: "postgresql",
29
- connection: {
30
- host: "localhost",
31
- database: preset,
45
+ const dbConfig =
46
+ /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ Object.fromEntries(
47
+ presets.map((preset) => [
48
+ preset,
49
+ {
50
+ client: "postgresql",
51
+ connection: {
52
+ host: "localhost",
53
+ database: preset,
54
+ },
32
55
  },
33
- },
34
- ]),
35
- ) as SonamuDBConfig;
56
+ ]),
57
+ ) as SonamuDBConfig;
36
58
 
37
59
  afterEach(() => {
38
60
  for (const key of Object.keys(process.env)) {
@@ -45,11 +67,7 @@ describe("Migrator environment target filtering", () => {
45
67
 
46
68
  const getMigrationTargetKeys = () => {
47
69
  Sonamu.dbConfig = dbConfig;
48
- return (
49
- new Migrator() as unknown as {
50
- getMigrationTargetKeys(): (keyof SonamuDBConfig)[];
51
- }
52
- ).getMigrationTargetKeys();
70
+ return new Migrator().getMigrationTargetKeys();
53
71
  };
54
72
 
55
73
  it("limits migration targets to production on a production server runtime", () => {
@@ -84,51 +102,26 @@ describe("SlackConfirm target validation", () => {
84
102
  "production_readonly",
85
103
  ];
86
104
 
87
- const dbConfig = Object.fromEntries(
88
- presets.map((preset) => [
89
- preset,
90
- {
91
- client: "postgresql",
92
- connection: {
93
- host: "localhost",
94
- database: preset,
95
- },
96
- },
97
- ]),
98
- ) as SonamuDBConfig;
99
-
100
- const createConfig = (targets: string[]): SonamuConfig =>
101
- ({
102
- projectName: "sonamu-test",
103
- api: {
104
- dir: "src",
105
- route: {
106
- prefix: "/api",
105
+ const dbConfig =
106
+ /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ Object.fromEntries(
107
+ presets.map((preset) => [
108
+ preset,
109
+ {
110
+ client: "postgresql",
111
+ connection: {
112
+ host: "localhost",
113
+ database: preset,
114
+ },
107
115
  },
108
- },
109
- i18n: {
110
- defaultLocale: "ko",
111
- supportedLocales: ["ko", "en"],
112
- },
113
- sync: {
114
- targets: [],
115
- },
116
- database: {},
117
- server: {},
118
- apiConfig: {
119
- contextProvider: (defaultContext) => defaultContext,
120
- guardHandler: () => undefined,
121
- },
122
- slackConfirm: {
123
- targets,
124
- botToken: "xoxb-test",
125
- channelId: "C123",
126
- },
127
- }) as SonamuConfig;
116
+ ]),
117
+ ) as SonamuDBConfig;
128
118
 
129
119
  it("fails fast when slackConfirm.targets contains an unknown DB key", () => {
130
120
  Sonamu.dbConfig = dbConfig;
131
- Sonamu.config = createConfig(["production_old"]);
121
+ Sonamu.config = createConfig(["production"]);
122
+ Object.defineProperty(Sonamu.config.slackConfirm, "targets", {
123
+ value: ["production_old"],
124
+ });
132
125
  setSDConfig(Sonamu.config.i18n);
133
126
 
134
127
  expect(() => new SlackConfirm().isTargetRequiresApproval("production")).toThrow(
@@ -14,6 +14,7 @@ import {
14
14
  } from "../types/types";
15
15
  import { isSearchTextProp } from "../types/types";
16
16
  import { formatCode } from "../utils/formatter";
17
+ import { isStringValue } from "../utils/runtime-value";
17
18
  import { differenceWith, intersectionBy } from "../utils/utils";
18
19
  import {
19
20
  normalizeIndexWherePredicate,
@@ -49,7 +50,7 @@ type SearchTextExpressionNode =
49
50
  | { type: "collate"; expr: SearchTextExpressionNode; collation: string; quoted: boolean }
50
51
  | { type: "cast"; expr: SearchTextExpressionNode; targetType: string };
51
52
 
52
- const SEARCH_TEXT_HELPER_DEFINITIONS: Record<SearchTextHelperKind, string> = {
53
+ const SEARCH_TEXT_HELPER_DEFINITIONS = {
53
54
  "text-array": `await knex.raw(\`CREATE OR REPLACE FUNCTION sonamu_text_array_agg(arr text[], ci boolean DEFAULT true)
54
55
  RETURNS text
55
56
  LANGUAGE sql IMMUTABLE PARALLEL SAFE RETURNS NULL ON NULL INPUT
@@ -70,7 +71,7 @@ AS $$
70
71
  )
71
72
  FROM jsonb_array_elements_text(arr)
72
73
  $$\`);`,
73
- };
74
+ } satisfies Record<SearchTextHelperKind, string>;
74
75
 
75
76
  class SearchTextExpressionParser {
76
77
  private index = 0;
@@ -883,9 +884,9 @@ function genNormalColumnDefinition(column: MigrationColumn): string {
883
884
 
884
885
  // defaultTo
885
886
  if (column.defaultTo !== undefined) {
886
- if (typeof column.defaultTo === "string" && column.defaultTo.startsWith(`"`)) {
887
+ if (isStringValue(column.defaultTo) && column.defaultTo.startsWith(`"`)) {
887
888
  chains.push(`defaultTo(${column.defaultTo})`);
888
- } else if (column.type === "json" && typeof column.defaultTo === "string") {
889
+ } else if (column.type === "json" && isStringValue(column.defaultTo)) {
889
890
  chains.push(`defaultTo(knex.raw("${column.defaultTo.replaceAll('"', "'")}::jsonb"))`);
890
891
  } else {
891
892
  chains.push(`defaultTo(knex.raw('${column.defaultTo}'))`);
@@ -1133,8 +1134,8 @@ function genForeignDefinitions(
1133
1134
  return r;
1134
1135
  },
1135
1136
  {
1136
- up: [] as string[],
1137
- down: [] as string[],
1137
+ up: /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as string[],
1138
+ down: /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as string[],
1138
1139
  },
1139
1140
  );
1140
1141
  }
@@ -1382,9 +1383,10 @@ function getAlterColumnsTo(
1382
1383
  searchTextColumnNames: Set<string>,
1383
1384
  ) {
1384
1385
  const columnsTo = {
1385
- add: [] as MigrationColumn[],
1386
- drop: [] as MigrationColumn[],
1387
- alter: [] as MigrationColumn[],
1386
+ add: /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as MigrationColumn[],
1387
+ drop: /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as MigrationColumn[],
1388
+ alter:
1389
+ /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as MigrationColumn[],
1388
1390
  };
1389
1391
 
1390
1392
  // 컬럼명 기준 비교
@@ -1424,16 +1426,40 @@ function getAlterColumnLinesTo(
1424
1426
  const searchTextColumnNames = getSearchTextColumnNames(table);
1425
1427
  const linesTo = {
1426
1428
  add: {
1427
- up: { builder: [] as string[], raw: [] as string[] },
1428
- down: { builder: [] as string[], raw: [] as string[] },
1429
+ up: {
1430
+ builder:
1431
+ /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as string[],
1432
+ raw: /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as string[],
1433
+ },
1434
+ down: {
1435
+ builder:
1436
+ /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as string[],
1437
+ raw: /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as string[],
1438
+ },
1429
1439
  },
1430
1440
  drop: {
1431
- up: { builder: [] as string[], raw: [] as string[] },
1432
- down: { builder: [] as string[], raw: [] as string[] },
1441
+ up: {
1442
+ builder:
1443
+ /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as string[],
1444
+ raw: /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as string[],
1445
+ },
1446
+ down: {
1447
+ builder:
1448
+ /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as string[],
1449
+ raw: /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as string[],
1450
+ },
1433
1451
  },
1434
1452
  alter: {
1435
- up: { builder: [] as string[], raw: [] as string[] },
1436
- down: { builder: [] as string[], raw: [] as string[] },
1453
+ up: {
1454
+ builder:
1455
+ /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as string[],
1456
+ raw: /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as string[],
1457
+ },
1458
+ down: {
1459
+ builder:
1460
+ /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as string[],
1461
+ raw: /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as string[],
1462
+ },
1437
1463
  },
1438
1464
  };
1439
1465
 
@@ -1572,46 +1598,57 @@ function getAlterColumnLinesTo(
1572
1598
  return r;
1573
1599
  },
1574
1600
  {
1575
- up: { builder: [] as string[], raw: [] as string[] },
1576
- down: { builder: [] as string[], raw: [] as string[] },
1601
+ up: {
1602
+ builder:
1603
+ /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as string[],
1604
+ raw: /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as string[],
1605
+ },
1606
+ down: {
1607
+ builder:
1608
+ /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as string[],
1609
+ raw: /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as string[],
1610
+ },
1577
1611
  },
1578
1612
  );
1579
1613
 
1580
1614
  return linesTo;
1581
1615
  }
1582
1616
 
1617
+ // 인덱스 고유 식별자 생성 (name을 제외한 모든 필드를 문자열로 변환하여 조합)
1618
+ function migrationIndexIdentity(index: MigrationIndex): string {
1619
+ const keys = Object.keys(index)
1620
+ .filter((key) => key !== "name")
1621
+ .toSorted();
1622
+
1623
+ return keys
1624
+ .map((key) => {
1625
+ if (key === "name") return undefined;
1626
+ if (key === "columns") {
1627
+ return /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ (
1628
+ index[key] as MigrationIndex["columns"]
1629
+ ).map((col) =>
1630
+ Object.keys(col)
1631
+ .toSorted()
1632
+ .map(
1633
+ (columnKey) =>
1634
+ `${columnKey}=${col[/* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ columnKey as keyof typeof col]}`,
1635
+ )
1636
+ .join("//"),
1637
+ );
1638
+ }
1639
+ return `${key}=${index[/* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ key as keyof MigrationIndex]}`;
1640
+ })
1641
+ .join("//");
1642
+ }
1643
+
1583
1644
  /**
1584
1645
  * 인덱스의 add, drop 여부 확인
1585
1646
  */
1586
1647
  export function getAlterIndexesTo(entityIndexes: MigrationIndex[], dbIndexes: MigrationIndex[]) {
1587
1648
  // 인덱스 비교
1588
1649
  const indexesTo = {
1589
- add: [] as MigrationIndex[],
1590
- drop: [] as MigrationIndex[],
1591
- };
1592
-
1593
- // 인덱스 고유 식별자 생성 (name을 제외한 모든 필드를 문자열로 변환하여 조합)
1594
- const identity = <T extends Record<string, unknown>>(index: T): string => {
1595
- const keys = Object.keys(index)
1596
- .filter((key) => key !== "name")
1597
- .toSorted();
1598
-
1599
- return keys
1600
- .map((key) => {
1601
- if (key === "name") {
1602
- return undefined;
1603
- }
1604
- if (key === "columns") {
1605
- return (index[key] as MigrationIndex["columns"]).map((col) => {
1606
- return Object.keys(col)
1607
- .toSorted()
1608
- .map((k) => `${k}=${col[k as keyof typeof col]}`)
1609
- .join("//");
1610
- });
1611
- }
1612
- return `${key}=${index[key as keyof MigrationIndex]}`;
1613
- })
1614
- .join("//");
1650
+ add: /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as MigrationIndex[],
1651
+ drop: /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as MigrationIndex[],
1615
1652
  };
1616
1653
 
1617
1654
  const normalizedEntityIndexes = entityIndexes.map(setMigrationIndexDefaults);
@@ -1620,22 +1657,22 @@ export function getAlterIndexesTo(entityIndexes: MigrationIndex[], dbIndexes: Mi
1620
1657
  const comparisonEntityIndexes = entityIndexes.map(setMigrationIndexComparisonDefaults);
1621
1658
  const comparisonDbIndexes = dbIndexes.map(setMigrationIndexComparisonDefaults);
1622
1659
  const extraIndexes = {
1623
- db: diff(comparisonDbIndexes, comparisonEntityIndexes, identity),
1624
- entity: diff(comparisonEntityIndexes, comparisonDbIndexes, identity),
1660
+ db: diff(comparisonDbIndexes, comparisonEntityIndexes, migrationIndexIdentity),
1661
+ entity: diff(comparisonEntityIndexes, comparisonDbIndexes, migrationIndexIdentity),
1625
1662
  };
1626
1663
  if (extraIndexes.entity.length > 0) {
1627
- const addIdentities = new Set(extraIndexes.entity.map(identity));
1664
+ const addIdentities = new Set(extraIndexes.entity.map(migrationIndexIdentity));
1628
1665
  indexesTo.add = indexesTo.add.concat(
1629
1666
  normalizedEntityIndexes.filter((_, index) =>
1630
- addIdentities.has(identity(comparisonEntityIndexes[index])),
1667
+ addIdentities.has(migrationIndexIdentity(comparisonEntityIndexes[index])),
1631
1668
  ),
1632
1669
  );
1633
1670
  }
1634
1671
  if (extraIndexes.db.length > 0) {
1635
- const dropIdentities = new Set(extraIndexes.db.map(identity));
1672
+ const dropIdentities = new Set(extraIndexes.db.map(migrationIndexIdentity));
1636
1673
  indexesTo.drop = indexesTo.drop.concat(
1637
1674
  normalizedDbIndexes.filter((_, index) =>
1638
- dropIdentities.has(identity(comparisonDbIndexes[index])),
1675
+ dropIdentities.has(migrationIndexIdentity(comparisonDbIndexes[index])),
1639
1676
  ),
1640
1677
  );
1641
1678
  }
@@ -1675,22 +1712,28 @@ function setMigrationIndexDefaultsBase(
1675
1712
  ? normalizeIndexWherePredicateForComparison(index.where)
1676
1713
  : normalizeIndexWherePredicate(index.where);
1677
1714
 
1678
- return {
1715
+ const columns = index.columns.map((col) => {
1716
+ const column: MigrationIndex["columns"][number] = { name: col.name };
1717
+ const opclass = getIndexColumnOpclass(col);
1718
+ if (opclass) column.opclass = opclass;
1719
+ if (supportsOrdering) {
1720
+ column.sortOrder = col.sortOrder ?? "ASC";
1721
+ column.nullsFirst = col.nullsFirst ?? col.sortOrder === "DESC";
1722
+ }
1723
+ return column;
1724
+ });
1725
+ const normalizedIndex: MigrationIndex = {
1679
1726
  ...index,
1680
- columns: index.columns.map((col) => ({
1681
- name: col.name,
1682
- ...(getIndexColumnOpclass(col) ? { opclass: getIndexColumnOpclass(col) } : {}),
1683
- ...(supportsOrdering
1684
- ? {
1685
- sortOrder: col.sortOrder ?? "ASC",
1686
- nullsFirst: col.nullsFirst ?? col.sortOrder === "DESC",
1687
- }
1688
- : {}),
1689
- })),
1727
+ columns,
1690
1728
  nullsNotDistinct: index.nullsNotDistinct ?? false,
1691
- ...(normalizedUsing ? { using: normalizedUsing } : {}),
1692
- ...(normalizedWhere ? { where: normalizedWhere } : {}),
1693
1729
  };
1730
+ if (normalizedUsing) normalizedIndex.using = normalizedUsing;
1731
+ if (normalizedWhere) normalizedIndex.where = normalizedWhere;
1732
+ return normalizedIndex;
1733
+ }
1734
+
1735
+ function migrationForeignKey(migrationForeign: MigrationForeign): string {
1736
+ return [migrationForeign.columns.join("-"), migrationForeign.to].join("///");
1694
1737
  }
1695
1738
 
1696
1739
  /**
@@ -1704,16 +1747,14 @@ async function generateAlterCode_Foreigns(
1704
1747
  ): Promise<GenMigrationCode[]> {
1705
1748
  // console.log({ entityForeigns, dbForeigns });
1706
1749
 
1707
- const getKey = (mf: MigrationForeign): string => {
1708
- return [mf.columns.join("-"), mf.to].join("///");
1709
- };
1710
-
1711
1750
  // 삭제될 컬럼명 목록
1712
1751
  const droppingColumnNames = droppingColumns.map((col) => col.name);
1713
1752
 
1714
1753
  const fkTo = entityForeigns.reduce(
1715
1754
  (result, entityF) => {
1716
- const matchingDbF = dbForeigns.find((dbF) => getKey(entityF) === getKey(dbF));
1755
+ const matchingDbF = dbForeigns.find(
1756
+ (dbF) => migrationForeignKey(entityF) === migrationForeignKey(dbF),
1757
+ );
1717
1758
  if (!matchingDbF) {
1718
1759
  result.add.push(entityF);
1719
1760
  return result;
@@ -1727,17 +1768,21 @@ async function generateAlterCode_Foreigns(
1727
1768
  return result;
1728
1769
  },
1729
1770
  {
1730
- add: [] as MigrationForeign[],
1731
- drop: [] as MigrationForeign[],
1732
- alterSrc: [] as MigrationForeign[],
1733
- alterDst: [] as MigrationForeign[],
1771
+ add: /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as MigrationForeign[],
1772
+ drop: /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as MigrationForeign[],
1773
+ alterSrc:
1774
+ /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as MigrationForeign[],
1775
+ alterDst:
1776
+ /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as MigrationForeign[],
1734
1777
  },
1735
1778
  );
1736
1779
 
1737
1780
  // dbForeigns에는 있지만 entityForeigns에는 없는 경우 (삭제된 FK)
1738
1781
  // 단, 삭제될 컬럼의 FK는 제외 (generateAlterCode_ColumnAndIndexes에서 처리)
1739
1782
  dbForeigns.forEach((dbF) => {
1740
- const matchingEntityF = entityForeigns.find((entityF) => getKey(entityF) === getKey(dbF));
1783
+ const matchingEntityF = entityForeigns.find(
1784
+ (entityF) => migrationForeignKey(entityF) === migrationForeignKey(dbF),
1785
+ );
1741
1786
  if (!matchingEntityF) {
1742
1787
  // 이 FK의 컬럼이 삭제될 컬럼 목록에 있는지 확인
1743
1788
  const isColumnDropping = dbF.columns.some((col) => droppingColumnNames.includes(col));
@@ -1826,6 +1871,21 @@ export async function generateCreateCode(entitySet: MigrationSet): Promise<GenMi
1826
1871
  ];
1827
1872
  }
1828
1873
 
1874
+ function replaceColumnDefaultTo(column: MigrationColumn) {
1875
+ // FIXME: 일단 MySQL 상황에서 발생했던 이슈의 workaround 이므로 Pg에서 재확인 후 대응 추가
1876
+ return column;
1877
+ }
1878
+
1879
+ function replaceNoActionOnMySQL(foreign: MigrationForeign) {
1880
+ // MySQL에서 RESTRICT와 NO ACTION은 동일함
1881
+ const { onDelete, onUpdate } = foreign;
1882
+ return {
1883
+ ...foreign,
1884
+ onUpdate: onUpdate === "RESTRICT" ? "NO ACTION" : onUpdate,
1885
+ onDelete: onDelete === "RESTRICT" ? "NO ACTION" : onDelete,
1886
+ };
1887
+ }
1888
+
1829
1889
  /**
1830
1890
  * 주어진 entitySet을 목표로, dbSet을 현 상황으로 하여 테이블 ALTER 마이그레이션 코드를 생성합니다.
1831
1891
  * @param entitySet 현 상황의 MigrationSet
@@ -1838,28 +1898,6 @@ export async function generateAlterCode(
1838
1898
  dbSet: MigrationSet,
1839
1899
  compareDB?: Knex,
1840
1900
  ): Promise<GenMigrationCode[]> {
1841
- const replaceColumnDefaultTo = (col: MigrationColumn) => {
1842
- // float인 경우 기본값을 0으로 지정하는 경우 "0.00"으로 변환되는 케이스 대응
1843
- // if (col.type === "float" && col.defaultTo && String(col.defaultTo).includes('"') === false) {
1844
- // col.defaultTo = `"${Number(col.defaultTo).toFixed(col.scale ?? 2)}"`;
1845
- // }
1846
- // // string인 경우 기본값이 빈 스트링인 경우 대응
1847
- // if (col.type === "string" && col.defaultTo === "") {
1848
- // col.defaultTo = '""';
1849
- // }
1850
- // // boolean인 경우 기본값 정규화 (MySQL에서는 TINYINT(1)로 저장되므로 0 또는 1로 정규화)
1851
- // // TODO: db.ts에 typeCase 설정 확인하여 처리하도록 수정 필요
1852
- // if (col.type === "boolean" && col.defaultTo !== undefined) {
1853
- // if (col.defaultTo === "0" || col.defaultTo.toLowerCase() === "false") {
1854
- // col.defaultTo = "0";
1855
- // } else if (col.defaultTo === "1" || col.defaultTo.toLowerCase() === "true") {
1856
- // col.defaultTo = "1";
1857
- // }
1858
- // }
1859
-
1860
- // FIXME: 일단 MySQL 상황에서 발생했던 이슈의 workaround 이므로 Pg에서 재확인 후 대응 추가
1861
- return col;
1862
- };
1863
1901
  const entityColumns = alphabetical(entitySet.columns, (a) => a.name).map(replaceColumnDefaultTo);
1864
1902
  const dbColumns = alphabetical(dbSet.columns, (a) => a.name).map(replaceColumnDefaultTo);
1865
1903
 
@@ -1880,16 +1918,6 @@ export async function generateAlterCode(
1880
1918
  [a.type, ...a.columns.map((c) => c.name)].join("-"),
1881
1919
  );
1882
1920
 
1883
- const replaceNoActionOnMySQL = (f: MigrationForeign) => {
1884
- // MySQL에서 RESTRICT와 NO ACTION은 동일함
1885
- const { onDelete, onUpdate } = f;
1886
- return {
1887
- ...f,
1888
- onUpdate: onUpdate === "RESTRICT" ? "NO ACTION" : onUpdate,
1889
- onDelete: onDelete === "RESTRICT" ? "NO ACTION" : onDelete,
1890
- };
1891
- };
1892
-
1893
1921
  const entityForeigns = alphabetical(entitySet.foreigns, (a) =>
1894
1922
  [a.to, ...a.columns].join("-"),
1895
1923
  ).map((f) => replaceNoActionOnMySQL(f));