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
@@ -10,22 +10,35 @@ export const CompressPresets = {
10
10
  /** 기본 설정 (threshold: 1024, br > gzip > deflate) */
11
11
  default: {
12
12
  threshold: 1024,
13
- encodings: ["br", "gzip", "deflate"] as ("br" | "gzip" | "deflate")[],
13
+ encodings: /* SAFETY: 호출 경계의 선행 검증과 소유 타입 계약이 이 값의 타입을 보장한다. */ [
14
+ "br",
15
+ "gzip",
16
+ "deflate",
17
+ ] as ("br" | "gzip" | "deflate")[],
14
18
  },
15
19
  /** 적극적 압축 (threshold: 256) */
16
20
  aggressive: {
17
21
  threshold: 256,
18
- encodings: ["br", "gzip", "deflate"] as ("br" | "gzip" | "deflate")[],
22
+ encodings: /* SAFETY: 호출 경계의 선행 검증과 소유 타입 계약이 이 값의 타입을 보장한다. */ [
23
+ "br",
24
+ "gzip",
25
+ "deflate",
26
+ ] as ("br" | "gzip" | "deflate")[],
19
27
  },
20
28
  /** 보수적 압축 (threshold: 4096, gzip만) */
21
29
  conservative: {
22
30
  threshold: 4096,
23
- encodings: ["gzip", "deflate"] as ("gzip" | "deflate")[],
31
+ encodings: /* SAFETY: 호출 경계의 선행 검증과 소유 타입 계약이 이 값의 타입을 보장한다. */ [
32
+ "gzip",
33
+ "deflate",
34
+ ] as ("gzip" | "deflate")[],
24
35
  },
25
36
  /** gzip만 사용 */
26
37
  gzipOnly: {
27
38
  threshold: 1024,
28
- encodings: ["gzip"] as ["gzip"],
39
+ encodings: /* SAFETY: 호출 경계의 선행 검증과 소유 타입 계약이 이 값의 타입을 보장한다. */ [
40
+ "gzip",
41
+ ] as ["gzip"],
29
42
  },
30
43
  } as const;
31
44
 
@@ -1,7 +1,10 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
 
4
+ import { type LanguageModel } from "ai";
5
+
4
6
  import { type Cone, type EntityJson } from "../types/types";
7
+ import { isObjectValue } from "../utils/runtime-value";
5
8
 
6
9
  /**
7
10
  * Cone 생성 컨텍스트
@@ -29,16 +32,32 @@ export type ConeGenerationResult = {
29
32
  tokensUsed: number;
30
33
  };
31
34
 
35
+ export type ConeTextGenerator = (request: {
36
+ model: LanguageModel;
37
+ prompt: string;
38
+ }) => Promise<{ text: string; usage?: { totalTokens?: number } }>;
39
+
40
+ export type ConeGeneratorDependencies = {
41
+ generateText?: ConeTextGenerator;
42
+ };
43
+
32
44
  /**
33
45
  * LLM을 사용하여 Entity의 cone 메타데이터를 생성합니다.
34
46
  *
35
47
  * @param context - Entity 정보와 생성 옵션
36
48
  * @returns 생성된 cone 메타데이터
37
49
  */
38
- export async function generateCones(context: ConeGenerationContext): Promise<ConeGenerationResult> {
50
+ export async function generateCones(
51
+ context: ConeGenerationContext,
52
+ dependencies: ConeGeneratorDependencies = {},
53
+ ): Promise<ConeGenerationResult> {
39
54
  const apiKey = getApiKey();
40
55
  const prompt = buildPrompt(context);
41
- const { text: responseText, tokensUsed } = await callAnthropicAPI(prompt, apiKey);
56
+ const { text: responseText, tokensUsed } = await callAnthropicAPI(
57
+ prompt,
58
+ apiKey,
59
+ dependencies.generateText,
60
+ );
42
61
  const result = parseConeResponse(responseText);
43
62
  result.tokensUsed = tokensUsed;
44
63
 
@@ -269,11 +288,17 @@ IMPORTANT: Return pure JSON only. Do NOT wrap in markdown code blocks.`;
269
288
  async function callAnthropicAPI(
270
289
  prompt: string,
271
290
  apiKey: string,
291
+ injectedGenerateText?: ConeTextGenerator,
272
292
  ): Promise<{ text: string; tokensUsed: number }> {
273
293
  try {
274
294
  // @ai-sdk/anthropic과 ai 패키지는 optional dependency이므로 동적 import
275
295
  const { createAnthropic } = await import("@ai-sdk/anthropic");
276
- const { generateText } = await import("ai");
296
+ const generateText: ConeTextGenerator =
297
+ injectedGenerateText ??
298
+ (async (request) => {
299
+ const ai = await import("ai");
300
+ return ai.generateText(request);
301
+ });
277
302
 
278
303
  const anthropic = createAnthropic({
279
304
  apiKey,
@@ -291,8 +316,11 @@ async function callAnthropicAPI(
291
316
 
292
317
  return { text, tokensUsed };
293
318
  } catch (error: unknown) {
294
- if (error && typeof error === "object" && "statusCode" in error) {
295
- const statusCode = (error as { statusCode: number }).statusCode;
319
+ if (error && isObjectValue(error) && "statusCode" in error) {
320
+ const statusCode =
321
+ /* SAFETY: 호출 경계의 선행 검증과 소유 타입 계약이 이 값의 타입을 보장한다. */ (
322
+ error as { statusCode: number }
323
+ ).statusCode;
296
324
  if (statusCode === 429) {
297
325
  throw new Error("Rate limit exceeded. Please try again later.", { cause: error });
298
326
  }
@@ -317,7 +345,7 @@ function parseConeResponse(text: string): ConeGenerationResult {
317
345
  try {
318
346
  const parsed = JSON.parse(jsonText);
319
347
 
320
- if (!parsed.propCones || typeof parsed.propCones !== "object") {
348
+ if (!parsed.propCones || !isObjectValue(parsed.propCones)) {
321
349
  throw new Error("Invalid response: propCones is required and must be an object");
322
350
  }
323
351
 
@@ -75,6 +75,7 @@ describe("DBClass.generateDBConfig", () => {
75
75
  });
76
76
 
77
77
  it("fails fast when legacy database.name or database.environments keys are present", () => {
78
+ // SAFETY: 테스트 입력은 선언된 타입 검증 시나리오에 맞게 고정됩니다.
78
79
  const legacyConfig = {
79
80
  database: "pg",
80
81
  name: "miomock",
@@ -37,6 +37,20 @@ function usersQuery(): Puri<TestSchema, { users: TestSchema["users"] }, TestSche
37
37
  return new Puri(db, "users");
38
38
  }
39
39
 
40
+ function withJsonTableSpec<T>(jsonColumns: string[], callback: () => T): T {
41
+ const tableSpecSpy = vi.spyOn(EntityManager, "getTableSpec").mockReturnValue({
42
+ name: "users",
43
+ uniqueIndexes: [],
44
+ jsonColumns,
45
+ });
46
+
47
+ try {
48
+ return callback();
49
+ } finally {
50
+ tableSpecSpy.mockRestore();
51
+ }
52
+ }
53
+
40
54
  afterAll(async () => {
41
55
  await db.destroy();
42
56
  });
@@ -104,7 +118,8 @@ describe("Puri JSONB containment", () => {
104
118
  ]);
105
119
 
106
120
  const query = usersQuery();
107
- expect(() => Reflect.apply(query.whereJsonSupersetOf, query, ["payload", undefined])).toThrow(
121
+ // SAFETY: 직렬화 실패 경로를 검증하기 위해 타입 계약 밖의 값을 의도적으로 전달합니다.
122
+ expect(() => query.whereJsonSupersetOf("payload", undefined as never)).toThrow(
108
123
  "Puri JSONB containment value must be JSON-serializable; JSON.stringify returned undefined.",
109
124
  );
110
125
  expect(query.rawQuery().toSQL().sql).toBe('select * from "users"');
@@ -112,20 +127,6 @@ describe("Puri JSONB containment", () => {
112
127
  });
113
128
 
114
129
  describe("Puri onConflict JSON 직렬화", () => {
115
- function withJsonTableSpec<T>(jsonColumns: string[], callback: () => T): T {
116
- const tableSpecSpy = vi.spyOn(EntityManager, "getTableSpec").mockReturnValue({
117
- name: "users",
118
- uniqueIndexes: [],
119
- jsonColumns,
120
- });
121
-
122
- try {
123
- return callback();
124
- } finally {
125
- tableSpecSpy.mockRestore();
126
- }
127
- }
128
-
129
130
  it("객체 update의 배열을 JSON 문자열 binding으로 변환한다", () => {
130
131
  const binding = withJsonTableSpec(["tags"], () =>
131
132
  usersQuery()
@@ -14,6 +14,7 @@ type TransactionScopeDB = DBClass & {
14
14
  };
15
15
 
16
16
  function createTransactionWrapper(): PuriTransactionWrapper {
17
+ // SAFETY: 테스트 입력은 선언된 타입 검증 시나리오에 맞게 고정됩니다.
17
18
  return new PuriTransactionWrapper({} as Knex.Transaction, new UpsertBuilder());
18
19
  }
19
20
 
@@ -32,6 +33,7 @@ function expectScopeRunner(db: TransactionScopeDB) {
32
33
 
33
34
  describe("DB.runWithTransactionScope", () => {
34
35
  it("저장소가 없어도 루트 scope를 설치하고 콜백 결과를 반환한 뒤 정리한다", async () => {
36
+ // SAFETY: 테스트 입력은 선언된 타입 검증 시나리오에 맞게 고정됩니다.
35
37
  const db = new DBClass() as TransactionScopeDB;
36
38
  const transaction = createTransactionWrapper();
37
39
  const runScope = expectScopeRunner(db);
@@ -53,6 +55,7 @@ describe("DB.runWithTransactionScope", () => {
53
55
  });
54
56
 
55
57
  it("scope 안에서 생성된 detached descendant가 완료된 자식 트랜잭션을 다시 사용하지 않는다", async () => {
58
+ // SAFETY: 테스트 입력은 선언된 타입 검증 시나리오에 맞게 고정됩니다.
56
59
  const db = new DBClass() as TransactionScopeDB;
57
60
  const parentTransaction = createTransactionWrapper();
58
61
  const childTransaction = createTransactionWrapper();
@@ -119,6 +122,7 @@ describe("DB.runWithTransactionScope", () => {
119
122
  });
120
123
 
121
124
  it("같거나 다른 preset의 중첩 범위를 복원하고 같은 오류를 다시 던진다", async () => {
125
+ // SAFETY: 테스트 입력은 선언된 타입 검증 시나리오에 맞게 고정됩니다.
122
126
  const db = new DBClass() as TransactionScopeDB;
123
127
  const outer = createTransactionWrapper();
124
128
  const samePresetInner = createTransactionWrapper();
@@ -157,6 +161,7 @@ describe("DB.runWithTransactionScope", () => {
157
161
  });
158
162
 
159
163
  it("겹치는 sibling 범위가 완료 순서와 무관하게 서로의 활성 트랜잭션을 보지 않는다", async () => {
164
+ // SAFETY: 테스트 입력은 선언된 타입 검증 시나리오에 맞게 고정됩니다.
160
165
  const db = new DBClass() as TransactionScopeDB;
161
166
  const parentTransaction = createTransactionWrapper();
162
167
  const firstTransaction = createTransactionWrapper();
@@ -97,6 +97,7 @@ function generateBatchUpdateSQL<Id extends string>(
97
97
  const cases: string[] = [];
98
98
 
99
99
  for (const key of keySet) {
100
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
100
101
  if (identifiers.includes(key as Id)) continue;
101
102
 
102
103
  const caseBindings: (string | number | boolean | null)[] = [];
@@ -11,6 +11,7 @@ import { normalizeFilterQuery, validateSonamuFilters } from "../filter/utils";
11
11
  import { convertDomainToCategory } from "../logger/category";
12
12
  import { type DatabaseSchemaExtend, type SonamuQueryMode } from "../types/types";
13
13
  import { type ListResult } from "../utils/model";
14
+ import { isObjectValue } from "../utils/runtime-value";
14
15
  import { getJoinTables, getTableNamesFromWhere } from "../utils/sql-parser";
15
16
  import { type EnhancerMap, type ResolveSubsetIntersection } from "./base-model.types";
16
17
  import { type DBPreset } from "./db";
@@ -25,7 +26,18 @@ import { PuriWrapper } from "./puri-wrapper";
25
26
  import { type UnionExtractedTTables } from "./puri.types";
26
27
  import { UpsertBuilder } from "./upsert-builder";
27
28
 
28
- type UnknownDBRecord = Record<string, unknown>;
29
+ type DatabaseRecordValue =
30
+ | string
31
+ | number
32
+ | boolean
33
+ | bigint
34
+ | Date
35
+ | Buffer
36
+ | Knex.Raw
37
+ | null
38
+ | DatabaseRecordValue[]
39
+ | { [key: string]: DatabaseRecordValue };
40
+ type DatabaseRecord = Record<string, DatabaseRecordValue | undefined>;
29
41
 
30
42
  /**
31
43
  * 모든 Model 클래스의 기본 클래스
@@ -37,7 +49,7 @@ type UnknownDBRecord = Record<string, unknown>;
37
49
  */
38
50
  export class BaseModelClass<
39
51
  TSubsetKey extends string = never,
40
- TSubsetMapping extends Record<string, any> = never,
52
+ TSubsetMapping extends { [K in TSubsetKey]: TSubsetMapping[K] } = never,
41
53
  TSubsetQueries extends Record<TSubsetKey, PuriSubsetFn> = never,
42
54
  TLoaderQueries extends PuriLoaderQueries<TSubsetKey> = never,
43
55
  > {
@@ -82,7 +94,7 @@ export class BaseModelClass<
82
94
 
83
95
  async getInsertedIds(
84
96
  wdb: Knex,
85
- rows: UnknownDBRecord[],
97
+ rows: DatabaseRecord[],
86
98
  tableName: string,
87
99
  unqKeyFields: string[],
88
100
  chunkSize: number = 500,
@@ -102,6 +114,7 @@ export class BaseModelClass<
102
114
  } else {
103
115
  whereInField = unqKeyFields[0];
104
116
  selectField = unqKeyFields[0];
117
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
105
118
  unqKeys = rows.map((row) => row[unqKeyFields[0]] as string);
106
119
  }
107
120
 
@@ -109,9 +122,14 @@ export class BaseModelClass<
109
122
  for (const items of cluster(unqKeys, chunkSize)) {
110
123
  const dbRows = await wdb(tableName)
111
124
  .select("id", wdb.raw(selectField))
112
- .whereIn(whereInField as string, items);
125
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
126
+ .whereIn(
127
+ /* SAFETY: Knex 런타임은 컬럼 위치의 Raw 표현식을 지원하지만 선언 타입에는 누락되어 있습니다. */
128
+ whereInField as string,
129
+ items,
130
+ );
113
131
  resultIds = resultIds.concat(
114
- dbRows.map((dbRow: UnknownDBRecord) => parseInt(String(dbRow.id))),
132
+ dbRows.map((dbRow: DatabaseRecord) => parseInt(String(dbRow.id))),
115
133
  );
116
134
  }
117
135
 
@@ -137,16 +155,18 @@ export class BaseModelClass<
137
155
  NonAllowedAsSingleTable: { __fulltext__: true };
138
156
  };
139
157
 
158
+ function onSubset<S extends TSubsetKey>(subset: S): ReturnType<TSubsetQueries[S]>;
159
+ function onSubset<Arr extends readonly TSubsetKey[]>(
160
+ subsets: [...Arr],
161
+ ): ResolveSubsetIntersection<Arr, TSubsetQueries>;
162
+ function onSubset(_subset: TSubsetKey | readonly TSubsetKey[]) {
163
+ return qb;
164
+ }
165
+
140
166
  return {
141
- qb: qb as unknown as Puri<DatabaseSchemaExtend, QBTables, {}>,
142
- onSubset: ((_subset: TSubsetKey | readonly TSubsetKey[]) => qb) as {
143
- // 단일 키
144
- <S extends TSubsetKey>(subset: S): ReturnType<TSubsetQueries[S]>;
145
- // 키 배열 -> 교집합 반환
146
- <Arr extends readonly TSubsetKey[]>(
147
- subsets: [...Arr],
148
- ): ResolveSubsetIntersection<Arr, TSubsetQueries>;
149
- },
167
+ // SAFETY: 같은 Puri 인스턴스에 단일 테이블 접근 제한용 타입 마커만 추가합니다.
168
+ qb: qb as Puri<DatabaseSchemaExtend, QBTables, {}>,
169
+ onSubset,
150
170
  };
151
171
  }
152
172
 
@@ -177,11 +197,11 @@ export class BaseModelClass<
177
197
  async executeSubsetQuery<
178
198
  T extends TSubsetKey,
179
199
  TComputedResults extends InferAllSubsets<TSubsetQueries, TLoaderQueries>,
200
+ TFilter extends object,
180
201
  LP extends {
181
202
  num?: number;
182
203
  page?: number;
183
204
  queryMode?: SonamuQueryMode;
184
- sonamuFilter?: Record<string, unknown>;
185
205
  },
186
206
  >(
187
207
  params: {
@@ -191,7 +211,7 @@ export class BaseModelClass<
191
211
  num: number;
192
212
  page: number;
193
213
  queryMode?: SonamuQueryMode;
194
- sonamuFilter?: Record<string, unknown>;
214
+ sonamuFilter?: TFilter;
195
215
  };
196
216
  debug?: boolean;
197
217
  optimizeCountQuery?: boolean;
@@ -217,6 +237,7 @@ export class BaseModelClass<
217
237
  const total = await this.executeCountQuery(qb, queryParams, debug, optimizeCountQuery);
218
238
 
219
239
  if (queryParams?.queryMode === "count") {
240
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
220
241
  return { total } as ListResult<LP, TSubsetMapping[T]>;
221
242
  }
222
243
 
@@ -232,7 +253,9 @@ export class BaseModelClass<
232
253
  );
233
254
 
234
255
  // Enhancer 적용
256
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
235
257
  const enhancer = (params as any).enhancers?.[subset];
258
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
236
259
  const enhancedRows = (await Promise.all(
237
260
  computedRows.map((row) => enhancer?.(row) ?? row),
238
261
  )) as TSubsetMapping[T][];
@@ -247,9 +270,11 @@ export class BaseModelClass<
247
270
 
248
271
  if (queryParams.queryMode === "list") {
249
272
  // 리스트만 리턴
273
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
250
274
  return { rows } as ListResult<LP, TSubsetMapping[T]>;
251
275
  } else {
252
276
  // 둘다 리턴
277
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
253
278
  return { rows, total } as ListResult<LP, TSubsetMapping[T]>;
254
279
  }
255
280
  }
@@ -272,7 +297,7 @@ export class BaseModelClass<
272
297
  * @param qb Puri QueryBuilder 인스턴스
273
298
  * @param filters FilterQuery 객체
274
299
  */
275
- protected applySonamuFilters<TEntity = Record<string, unknown>>(
300
+ protected applySonamuFilters<TEntity>(
276
301
  qb: Puri<any, any, any>,
277
302
  filters?: FilterQuery<TEntity>,
278
303
  ): void {
@@ -284,6 +309,7 @@ export class BaseModelClass<
284
309
  validateSonamuFilters(filters, entity);
285
310
 
286
311
  // 2. 검증된 필터 적용
312
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
287
313
  const puri = qb as any;
288
314
 
289
315
  for (const [field, condition] of Object.entries(filters)) {
@@ -293,13 +319,14 @@ export class BaseModelClass<
293
319
  const fullField = entity.getFullFieldName(field);
294
320
 
295
321
  // 직접 값 (eq와 동일)
296
- if (typeof condition !== "object" || Array.isArray(condition)) {
322
+ if (!isObjectValue(condition) || Array.isArray(condition)) {
297
323
  puri.where(fullField, condition);
298
324
  continue;
299
325
  }
300
326
 
301
327
  // 연산자 객체
302
328
  for (const [operator, value] of Object.entries(condition)) {
329
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
303
330
  this.applyOperator(qb, fullField, operator as FilterOperator, value);
304
331
  }
305
332
  }
@@ -308,12 +335,13 @@ export class BaseModelClass<
308
335
  /**
309
336
  * 단일 연산자를 QueryBuilder에 적용
310
337
  */
311
- private applyOperator(
338
+ private applyOperator<Value>(
312
339
  qb: Puri<any, any, any>,
313
340
  field: string,
314
341
  operator: FilterOperator,
315
- value: unknown,
342
+ value: Value,
316
343
  ): void {
344
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
317
345
  const puri = qb as any;
318
346
 
319
347
  switch (operator) {
@@ -394,14 +422,14 @@ export class BaseModelClass<
394
422
  * 중첩 필드 삭제 (배열 내 객체도 처리)
395
423
  */
396
424
  deleteField(obj: any, parts: string[]): void {
397
- if (!obj || typeof obj !== "object") {
425
+ if (!obj || !isObjectValue(obj)) {
398
426
  return;
399
427
  }
400
428
 
401
429
  if (parts.length === 1) {
402
430
  if (Array.isArray(obj)) {
403
431
  obj.forEach((item) => {
404
- if (item && typeof item === "object") {
432
+ if (item && isObjectValue(item)) {
405
433
  delete item[parts[0]];
406
434
  }
407
435
  });
@@ -416,7 +444,7 @@ export class BaseModelClass<
416
444
 
417
445
  if (Array.isArray(next)) {
418
446
  next.map((item) => this.deleteField(item, rest));
419
- } else if (next && typeof next === "object") {
447
+ } else if (next && isObjectValue(next)) {
420
448
  this.deleteField(next, rest);
421
449
  }
422
450
  }
@@ -496,6 +524,7 @@ export class BaseModelClass<
496
524
  }
497
525
 
498
526
  // 로더 처리
527
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
499
528
  const loaders = (this.loaderQueries as any)[subset];
500
529
  if (loaders && Array.isArray(loaders)) {
501
530
  unloadedRows = await this.processLoaders(unloadedRows, loaders, debug, puriWrapper);
@@ -525,6 +554,7 @@ export class BaseModelClass<
525
554
  resolveLoaderQb.debug();
526
555
  }
527
556
 
557
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
528
558
  let loadedRows = (await resolveLoaderQb) as any[];
529
559
 
530
560
  // 중첩 loaders가 있으면 재귀 처리
@@ -549,8 +579,10 @@ export class BaseModelClass<
549
579
  * - `user__name` → `{ user: { name } }`
550
580
  * - nullable relation의 경우 id 필드가 null이면 객체 자체를 null로
551
581
  */
552
- hydrate<T extends UnknownDBRecord>(rows: T[]): T[] {
582
+ hydrate<T extends object>(rows: T[]): T[] {
583
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
553
584
  return rows.map((row: T) => {
585
+ const rowValues = new Map(Object.entries(row));
554
586
  // nullable relation 처리: 그룹의 id 필드가 null이면 객체 전체를 null로
555
587
  const nestedKeys = Object.keys(row).filter((key) => key.includes("__"));
556
588
  const groups = Object.groupBy(nestedKeys, (key) => key.split("__")[0]);
@@ -564,26 +596,27 @@ export class BaseModelClass<
564
596
  const idField = `${groupKey}__id`;
565
597
  if (idField in row) {
566
598
  // id 필드가 null이면 객체 전체가 null
567
- return row[idField] === null;
599
+ return rowValues.get(idField) === null;
568
600
  }
569
601
 
570
602
  // id 필드가 없으면 기존 로직: 모든 필드가 null인지 확인
571
- return fields.every(
572
- (field) =>
573
- row[field] === null || (Array.isArray(row[field]) && row[field].length === 0),
574
- );
603
+ return fields.every((field) => {
604
+ const fieldValue = rowValues.get(field);
605
+ return fieldValue === null || (Array.isArray(fieldValue) && fieldValue.length === 0);
606
+ });
575
607
  })
576
608
  .map(([key]) => key);
577
609
 
578
- const hydrated = Object.keys(row).reduce((r, field) => {
610
+ let hydrated: DatabaseRecord = Object.fromEntries([]);
611
+ for (const field of Object.keys(row)) {
612
+ const fieldValue = rowValues.get(field);
579
613
  if (!field.includes("__")) {
580
- // 일반 필드: 배열 내 객체면 재귀 hydrate
581
- if (Array.isArray(row[field]) && isObject(row[field][0])) {
582
- r[field] = this.hydrate(row[field]);
583
- } else {
584
- r[field] = row[field];
585
- }
586
- return r;
614
+ const hydratedValue =
615
+ Array.isArray(fieldValue) && isObject(fieldValue[0])
616
+ ? this.hydrate(fieldValue)
617
+ : fieldValue;
618
+ Object.assign(hydrated, { [field]: hydratedValue });
619
+ continue;
587
620
  }
588
621
 
589
622
  // 중첩 필드 처리: user__name → user[name]
@@ -595,20 +628,18 @@ export class BaseModelClass<
595
628
  .map((part) => `[${part}]`)
596
629
  .join("");
597
630
 
598
- r = set(
599
- r,
631
+ hydrated = set(
632
+ hydrated,
600
633
  objPath,
601
- row[field] && Array.isArray(row[field]) && isObject(row[field][0])
602
- ? this.hydrate(row[field])
603
- : row[field],
634
+ fieldValue && Array.isArray(fieldValue) && isObject(fieldValue[0])
635
+ ? this.hydrate(fieldValue)
636
+ : fieldValue,
604
637
  );
605
-
606
- return r;
607
- }, {} as UnknownDBRecord);
638
+ }
608
639
 
609
640
  // null relation 처리
610
641
  nullKeys.forEach((nullKey) => {
611
- hydrated[nullKey] = null;
642
+ Object.assign(hydrated, { [nullKey]: null });
612
643
  });
613
644
 
614
645
  return hydrated;
@@ -622,8 +653,8 @@ export class BaseModelClass<
622
653
  */
623
654
  type EnhancerParam<
624
655
  TSubsetKey extends string,
625
- TComputedResults extends Record<TSubsetKey, any>,
626
- TSubsetMapping extends Record<TSubsetKey, any>,
656
+ TComputedResults extends { [K in TSubsetKey]: TComputedResults[K] },
657
+ TSubsetMapping extends { [K in TSubsetKey]: TSubsetMapping[K] },
627
658
  TSubsetQueries extends Record<TSubsetKey, PuriSubsetFn>,
628
659
  > = [RequiredEnhancerKeys<TSubsetKey, TComputedResults, TSubsetMapping>] extends [never]
629
660
  ? { enhancers?: EnhancerMap<TSubsetKey, TComputedResults, TSubsetMapping, TSubsetQueries> }
@@ -631,8 +662,8 @@ type EnhancerParam<
631
662
 
632
663
  type RequiredEnhancerKeys<
633
664
  TSubsetKey extends string,
634
- TComputedResults extends Record<TSubsetKey, any>,
635
- TSubsetMapping extends Record<TSubsetKey, any>,
665
+ TComputedResults extends { [K in TSubsetKey]: TComputedResults[K] },
666
+ TSubsetMapping extends { [K in TSubsetKey]: TSubsetMapping[K] },
636
667
  > = {
637
668
  [K in TSubsetKey]: TComputedResults[K] extends TSubsetMapping[K] ? never : K;
638
669
  }[TSubsetKey];
@@ -77,8 +77,8 @@ type OmitVirtualQueryFromMapping<TMapping, TVirtualQueryKeys> = Omit<
77
77
  */
78
78
  type IsEnhancerOptional<
79
79
  TSubsetKey extends string,
80
- TComputedResults extends Record<TSubsetKey, any>,
81
- TSubsetMapping extends Record<TSubsetKey, any>,
80
+ TComputedResults extends { [K in TSubsetKey]: TComputedResults[K] },
81
+ TSubsetMapping extends { [K in TSubsetKey]: TSubsetMapping[K] },
82
82
  TSubsetQueries extends Record<TSubsetKey, PuriSubsetFn>,
83
83
  K extends TSubsetKey,
84
84
  > =
@@ -106,8 +106,8 @@ type EnhancerFnWithVirtualQuery<TComputed, TMapping, TVirtualQueryKeys> = (
106
106
  */
107
107
  export type RequiredEnhancerKeys<
108
108
  TSubsetKey extends string,
109
- TComputedResults extends Record<TSubsetKey, any>,
110
- TSubsetMapping extends Record<TSubsetKey, any>,
109
+ TComputedResults extends { [K in TSubsetKey]: TComputedResults[K] },
110
+ TSubsetMapping extends { [K in TSubsetKey]: TSubsetMapping[K] },
111
111
  TSubsetQueries extends Record<TSubsetKey, PuriSubsetFn>,
112
112
  > = {
113
113
  [K in TSubsetKey]: IsEnhancerOptional<
@@ -136,8 +136,8 @@ export type RequiredEnhancerKeys<
136
136
  */
137
137
  export type EnhancerMap<
138
138
  TSubsetKey extends string,
139
- TComputedResults extends Record<TSubsetKey, any>,
140
- TSubsetMapping extends Record<TSubsetKey, any>,
139
+ TComputedResults extends { [K in TSubsetKey]: TComputedResults[K] },
140
+ TSubsetMapping extends { [K in TSubsetKey]: TSubsetMapping[K] },
141
141
  TSubsetQueries extends Record<TSubsetKey, PuriSubsetFn>,
142
142
  TRequiredKeys extends TSubsetKey = RequiredEnhancerKeys<
143
143
  TSubsetKey,