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
@@ -3,17 +3,29 @@ import { describe, expect, it, vi } from "vitest";
3
3
  import { type WebSocket } from "ws";
4
4
  import { z } from "zod";
5
5
 
6
- import { type AnyWebSocketConnection, WebSocketRuntime } from "../../stream/ws";
6
+ import {
7
+ type AnyWebSocketConnection,
8
+ type WebSocketConnection,
9
+ WebSocketRuntime,
10
+ } from "../../stream/ws";
7
11
  import { type WebSocketTelemetryConnectionContext } from "../../stream/ws-telemetry";
8
- import { type SonamuFastifyConfig } from "../config";
12
+ import { type SonamuFastifyConfig } from "../../types/types";
9
13
  import { type WebSocketContext } from "../context";
10
14
  import { type ExtendedApi } from "../decorators";
11
15
  import { Sonamu } from "../sonamu";
12
16
 
17
+ interface TestWebSocketMessage {
18
+ roomId?: string;
19
+ }
20
+
21
+ interface TestWebSocketEvents {
22
+ joinRoom: TestWebSocketMessage;
23
+ }
24
+
13
25
  describe("Sonamu websocket context scoping", () => {
14
26
  it("웹소켓 컨텍스트를 생성한 뒤 해당 컨텍스트 안에서 guard를 실행한다", async () => {
15
27
  const executionOrder: string[] = [];
16
- const rawWs = {
28
+ const rawWs: AnyWebSocketConnection = {
17
29
  id: "ws-guard",
18
30
  namespace: "chat",
19
31
  transport: "ws" as const,
@@ -30,12 +42,12 @@ describe("Sonamu websocket context scoping", () => {
30
42
  leave() {},
31
43
  setUserId() {},
32
44
  clearUserId() {},
33
- } satisfies AnyWebSocketConnection;
45
+ };
34
46
  const runtime = new WebSocketRuntime({ nodeId: "websocket-guard-test" });
35
- const originalRuntime = Reflect.get(Sonamu, "_websocketRuntime");
36
- const originalSyncer = Reflect.get(Sonamu, "_syncer");
47
+ const originalState = Sonamu.captureTestingSnapshot();
37
48
  let contextCreated: WebSocketContext | null = null;
38
49
  let guardContext: WebSocketContext | null = null;
50
+ let guardTransport: WebSocketContext["transport"] | null = null;
39
51
 
40
52
  vi.spyOn(runtime, "registerConnection").mockReturnValue(rawWs);
41
53
  vi.spyOn(runtime, "activateConnection").mockImplementation(() => {
@@ -43,7 +55,7 @@ describe("Sonamu websocket context scoping", () => {
43
55
  });
44
56
  vi.spyOn(Sonamu, "createWebSocketContext").mockImplementation(async (_config, request, ws) => {
45
57
  executionOrder.push("context");
46
- contextCreated = {
58
+ const context: WebSocketContext = {
47
59
  transport: "ws",
48
60
  request,
49
61
  headers: request.headers,
@@ -53,16 +65,21 @@ describe("Sonamu websocket context scoping", () => {
53
65
  user: null,
54
66
  session: null,
55
67
  };
56
- return contextCreated;
68
+ contextCreated = context;
69
+ return context;
57
70
  });
58
71
  vi.spyOn(Sonamu, "invokeModelMethod").mockImplementation(async () => {
59
72
  executionOrder.push("handler");
60
73
  });
61
74
 
62
- const config = {
75
+ const config = /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ {
63
76
  guardHandler() {
64
77
  executionOrder.push("guard");
65
78
  guardContext = Sonamu.getContext<WebSocketContext>();
79
+ guardTransport = guardContext.transport;
80
+ },
81
+ contextProvider(defaultContext) {
82
+ return defaultContext;
66
83
  },
67
84
  } as SonamuFastifyConfig;
68
85
  const api: ExtendedApi = {
@@ -78,28 +95,27 @@ describe("Sonamu websocket context scoping", () => {
78
95
  parameters: [],
79
96
  returnType: "void",
80
97
  };
81
- const request = {
98
+ const request = /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ {
82
99
  headers: {},
83
100
  query: {},
84
101
  } as FastifyRequest;
85
- const createWebSocketHandler: (
86
- api: ExtendedApi,
87
- config: SonamuFastifyConfig,
88
- ) => (connection: { socket: WebSocket }, request: FastifyRequest) => Promise<void> =
89
- Reflect.get(Sonamu, "createWebSocketHandler");
90
-
91
102
  try {
92
103
  Sonamu.websocketRuntime = runtime;
93
- Reflect.set(Sonamu, "_syncer", { types: {} });
104
+ Reflect.set(Sonamu, "syncerValue", { types: {} });
94
105
 
95
- await createWebSocketHandler.call(Sonamu, api, config)({ socket: {} as WebSocket }, request);
106
+ await Sonamu.createWebSocketHandlerForTesting(api, config)(
107
+ {
108
+ socket:
109
+ /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ {} as WebSocket,
110
+ },
111
+ request,
112
+ );
96
113
 
97
114
  expect(executionOrder).toEqual(["context", "guard", "activate", "handler"]);
98
115
  expect(guardContext).toBe(contextCreated);
99
- expect(guardContext?.transport).toBe("ws");
116
+ expect(guardTransport).toBe("ws");
100
117
  } finally {
101
- Reflect.set(Sonamu, "_websocketRuntime", originalRuntime);
102
- Reflect.set(Sonamu, "_syncer", originalSyncer);
118
+ Sonamu.restoreTestingSnapshot(originalState);
103
119
  vi.restoreAllMocks();
104
120
  }
105
121
  });
@@ -108,12 +124,12 @@ describe("Sonamu websocket context scoping", () => {
108
124
  const messageHandlers = new Map<
109
125
  string,
110
126
  (
111
- data: unknown,
127
+ data: TestWebSocketMessage,
112
128
  telemetryContext?: WebSocketTelemetryConnectionContext,
113
129
  ) => void | Promise<void>
114
130
  >();
115
131
 
116
- const rawWs = {
132
+ const rawWs: WebSocketConnection<TestWebSocketEvents, TestWebSocketEvents> = {
117
133
  id: "ws-1",
118
134
  namespace: "chat",
119
135
  transport: "ws" as const,
@@ -132,18 +148,15 @@ describe("Sonamu websocket context scoping", () => {
132
148
  leave() {},
133
149
  setUserId() {},
134
150
  clearUserId() {},
135
- } satisfies AnyWebSocketConnection;
151
+ };
136
152
 
137
- let context: WebSocketContext | null = null;
138
- const createScopedWebSocketConnection: (
139
- ws: AnyWebSocketConnection,
140
- getContext: () => WebSocketContext | null,
141
- ) => AnyWebSocketConnection = Reflect.get(Sonamu, "createScopedWebSocketConnection");
142
- const scopedWs = createScopedWebSocketConnection.call(Sonamu, rawWs, () => context);
153
+ let context: WebSocketContext<TestWebSocketEvents, TestWebSocketEvents> | null = null;
154
+ const scopedWs = Sonamu.createScopedWebSocketConnectionForTesting(rawWs, () => context);
143
155
 
144
156
  context = {
145
157
  transport: "ws",
146
- request: {} as WebSocketContext["request"],
158
+ request:
159
+ /* SAFETY: 테스트는 request 속성을 읽지 않고 websocket 컨텍스트 복원만 검증합니다. */ {} as WebSocketContext["request"],
147
160
  headers: {},
148
161
  ws: scopedWs,
149
162
  naiteStore: new Map(),
@@ -168,12 +181,12 @@ describe("Sonamu websocket context scoping", () => {
168
181
  const messageHandlers = new Map<
169
182
  string,
170
183
  (
171
- data: unknown,
184
+ data: TestWebSocketMessage,
172
185
  telemetryContext?: WebSocketTelemetryConnectionContext,
173
186
  ) => void | Promise<void>
174
187
  >();
175
188
 
176
- const rawWs = {
189
+ const rawWs: WebSocketConnection<TestWebSocketEvents, TestWebSocketEvents> = {
177
190
  id: "ws-1",
178
191
  namespace: "chat",
179
192
  transport: "ws" as const,
@@ -192,18 +205,15 @@ describe("Sonamu websocket context scoping", () => {
192
205
  leave() {},
193
206
  setUserId() {},
194
207
  clearUserId() {},
195
- } satisfies AnyWebSocketConnection;
208
+ };
196
209
 
197
- let context: WebSocketContext | null = null;
198
- const createScopedWebSocketConnection: (
199
- ws: AnyWebSocketConnection,
200
- getContext: () => WebSocketContext | null,
201
- ) => AnyWebSocketConnection = Reflect.get(Sonamu, "createScopedWebSocketConnection");
202
- const scopedWs = createScopedWebSocketConnection.call(Sonamu, rawWs, () => context);
210
+ let context: WebSocketContext<TestWebSocketEvents, TestWebSocketEvents> | null = null;
211
+ const scopedWs = Sonamu.createScopedWebSocketConnectionForTesting(rawWs, () => context);
203
212
 
204
213
  context = {
205
214
  transport: "ws",
206
- request: {} as WebSocketContext["request"],
215
+ request:
216
+ /* SAFETY: 테스트는 request 속성을 읽지 않고 websocket 컨텍스트 복원만 검증합니다. */ {} as WebSocketContext["request"],
207
217
  headers: {},
208
218
  ws: scopedWs,
209
219
  naiteStore: new Map(),
@@ -0,0 +1,95 @@
1
+ import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+
5
+ import { afterEach, describe, expect, it, vi } from "vitest";
6
+
7
+ import { DB } from "../../database/db";
8
+ import { normalizeZodCompilerPolicy } from "../config";
9
+ import { Sonamu } from "../sonamu";
10
+
11
+ describe("zod-compiler 정책 정규화", () => {
12
+ it.each([undefined, false] as const)(
13
+ "미설정 또는 false를 opt-out 정책으로 정규화한다",
14
+ (policy) => {
15
+ expect(normalizeZodCompilerPolicy(policy, ["web", "app"])).toEqual({
16
+ api: false,
17
+ targets: {},
18
+ });
19
+ },
20
+ );
21
+
22
+ it("API JIT 정책을 target registry 없이 정규화한다", () => {
23
+ expect(normalizeZodCompilerPolicy({ api: "jit" }, ["web"])).toEqual({
24
+ api: "jit",
25
+ targets: {},
26
+ });
27
+ });
28
+
29
+ it("API AOT 정책을 target registry 없이 정규화한다", () => {
30
+ expect(normalizeZodCompilerPolicy({ api: "aot" }, ["web"])).toEqual({
31
+ api: "aot",
32
+ targets: {},
33
+ });
34
+ });
35
+
36
+ it("지원하지 않는 target opt-in을 targets 설정 경로에서 거부한다", () => {
37
+ expect(() =>
38
+ normalizeZodCompilerPolicy(
39
+ {
40
+ api: "aot",
41
+ targets: {
42
+ web: "aot",
43
+ },
44
+ },
45
+ ["web"],
46
+ ),
47
+ ).toThrowError(/validation\.zodCompiler\.targets/);
48
+ });
49
+ });
50
+
51
+ describe("zod-compiler 빌드 전용 정책 로딩", () => {
52
+ const tempRoots: string[] = [];
53
+
54
+ afterEach(async () => {
55
+ vi.restoreAllMocks();
56
+ vi.resetModules();
57
+ await Promise.all(
58
+ tempRoots.splice(0).map((rootPath) => rm(rootPath, { recursive: true, force: true })),
59
+ );
60
+ });
61
+
62
+ it("Sonamu와 DB를 초기화하지 않고 source config의 compiler 정책만 읽는다", async () => {
63
+ const rootPath = await mkdtemp(path.join(os.tmpdir(), "sonamu-compiler-policy-test-"));
64
+ tempRoots.push(rootPath);
65
+ await mkdir(path.join(rootPath, "src"), { recursive: true });
66
+ await writeFile(path.join(rootPath, ".env"), "SONAMU_DB_HOST=localhost\n");
67
+ await writeFile(
68
+ path.join(rootPath, "src", "sonamu.config.ts"),
69
+ `
70
+ export default {
71
+ sync: { targets: ["web"] },
72
+ validation: {
73
+ zodCompiler: {
74
+ api: "aot",
75
+ },
76
+ },
77
+ };
78
+ `,
79
+ );
80
+
81
+ const sonamuInit = vi.spyOn(Sonamu, "init");
82
+ const generateDBConfig = vi.spyOn(DB, "generateDBConfig");
83
+ const setDBConfig = vi.spyOn(DB, "setConfig");
84
+
85
+ const { loadBuildCompilerPolicy } = await import("../../bin/compiler-policy");
86
+
87
+ await expect(loadBuildCompilerPolicy(rootPath)).resolves.toEqual({
88
+ api: "aot",
89
+ targets: {},
90
+ });
91
+ expect(sonamuInit).not.toHaveBeenCalled();
92
+ expect(generateDBConfig).not.toHaveBeenCalled();
93
+ expect(setDBConfig).not.toHaveBeenCalled();
94
+ });
95
+ });
package/src/api/caster.ts CHANGED
@@ -3,6 +3,8 @@ import assert from "assert";
3
3
  import { z } from "zod";
4
4
  import { type $ZodType } from "zod/v4/core";
5
5
 
6
+ import { isObjectValue, isStringValue } from "../utils/runtime-value";
7
+
6
8
  function isNumberType(zodType: $ZodType): zodType is z.ZodNumber {
7
9
  return zodType instanceof z.ZodNumber;
8
10
  }
@@ -28,7 +30,7 @@ function isZodNumberAnyway(zodType: $ZodType) {
28
30
  // ZodType을 이용해 raw를 Type Coercing
29
31
  // oxlint-disable-next-line @typescript-eslint/no-explicit-any -- 캐스팅에는 any가 필요함.
30
32
  export function caster(zodType: $ZodType, raw: any): any {
31
- if (isZodNumberAnyway(zodType) && typeof raw === "string") {
33
+ if (isZodNumberAnyway(zodType) && isStringValue(raw)) {
32
34
  // number
33
35
  return Number(raw);
34
36
  } else if (
@@ -51,14 +53,10 @@ export function caster(zodType: $ZodType, raw: any): any {
51
53
  // array
52
54
  // oxlint-disable-next-line @typescript-eslint/no-explicit-any -- 캐스팅에는 any가 필요함.
53
55
  return raw.map((elem: any) => caster(zodType.element, elem));
54
- } else if (zodType instanceof z.ZodObject && typeof raw === "object" && raw !== null) {
56
+ } else if (zodType instanceof z.ZodObject && isObjectValue(raw) && raw !== null) {
55
57
  // object
56
- return Object.keys(raw).reduce(
57
- (r, rawKey) => {
58
- r[rawKey] = caster(zodType.shape[rawKey], raw[rawKey]);
59
- return r;
60
- },
61
- {} as Record<string, unknown>,
58
+ return Object.fromEntries(
59
+ Object.keys(raw).map((rawKey) => [rawKey, caster(zodType["shape"][rawKey], raw[rawKey])]),
62
60
  );
63
61
  } else if (zodType instanceof z.ZodOptional) {
64
62
  // optional
@@ -28,6 +28,76 @@ import { type ExtendedApi } from "./decorators";
28
28
  type AnyZodObject = z.ZodObject;
29
29
  type AnyZodLiteral = z.ZodLiteral;
30
30
 
31
+ const ApiParamTypeSchema: z.ZodType<ApiParamType> = z.lazy(() =>
32
+ z.union([
33
+ z.enum([
34
+ "string",
35
+ "number",
36
+ "boolean",
37
+ "null",
38
+ "undefined",
39
+ "void",
40
+ "any",
41
+ "unknown",
42
+ "true",
43
+ "false",
44
+ ]),
45
+ z.object({ t: z.literal("string-literal"), value: z.string() }),
46
+ z.object({ t: z.literal("numeric-literal"), value: z.number() }),
47
+ z.object({
48
+ t: z.literal("object"),
49
+ props: z.array(
50
+ z.object({
51
+ name: z.string(),
52
+ type: ApiParamTypeSchema,
53
+ optional: z.boolean(),
54
+ defaultDef: z.string().optional(),
55
+ }),
56
+ ),
57
+ }),
58
+ z.object({ t: z.literal("union"), types: z.array(ApiParamTypeSchema) }),
59
+ z.object({ t: z.literal("intersection"), types: z.array(ApiParamTypeSchema) }),
60
+ z.object({ t: z.literal("array"), elementsType: ApiParamTypeSchema }),
61
+ z.object({
62
+ t: z.literal("ref"),
63
+ id: z.string(),
64
+ args: z.array(ApiParamTypeSchema).optional(),
65
+ }),
66
+ z.object({
67
+ t: z.literal("indexed-access"),
68
+ object: ApiParamTypeSchema,
69
+ index: ApiParamTypeSchema,
70
+ }),
71
+ z.object({
72
+ t: z.literal("type-param"),
73
+ id: z.string(),
74
+ constraint: ApiParamTypeSchema.optional(),
75
+ }),
76
+ z.object({ t: z.literal("tuple-type"), elements: z.array(ApiParamTypeSchema) }),
77
+ z.object({
78
+ t: z.literal("function"),
79
+ parameters: z.array(
80
+ z.object({
81
+ name: z.string(),
82
+ type: ApiParamTypeSchema,
83
+ optional: z.boolean(),
84
+ defaultDef: z.string().optional(),
85
+ }),
86
+ ),
87
+ returnType: ApiParamTypeSchema,
88
+ }),
89
+ ]),
90
+ );
91
+
92
+ /** 신뢰할 수 없는 값을 ApiParamType 경계에서 검증합니다. */
93
+ export function parseApiParamType<Input>(input: Input): ApiParamType {
94
+ const result = ApiParamTypeSchema.safeParse(input);
95
+ if (!result.success) {
96
+ throw new Error(`resolve 불가 ApiParamType: ${z.prettifyError(result.error)}`);
97
+ }
98
+ return result.data;
99
+ }
100
+
31
101
  /**
32
102
  * Promise 타입을 한 번 언래핑하여 내부 타입을 반환합니다.
33
103
  * Promise가 아닌 경우 원본 타입을 그대로 반환합니다.
@@ -49,12 +119,13 @@ export function unwrapPromiseOnce(paramType: ApiParamType) {
49
119
  * string, number, array, union 등 모든 ApiParamType을 처리하며,
50
120
  * 순환참조가 발생하는 경우 z.unknown()으로 fallback합니다.
51
121
  */
52
- export function getZodTypeFromApiParamType(
53
- paramType: ApiParamType,
122
+ export function getZodTypeFromApiParamType<Input>(
123
+ input: Input,
54
124
  references: {
55
125
  [id: string]: z.ZodType;
56
126
  },
57
127
  ): z.ZodType {
128
+ const paramType = parseApiParamType(input);
58
129
  switch (paramType) {
59
130
  case "string":
60
131
  return z.string();
@@ -63,28 +134,38 @@ export function getZodTypeFromApiParamType(
63
134
  case "boolean":
64
135
  return z.boolean();
65
136
  default: {
66
- const advType = paramType as { t: string; value?: string | number };
137
+ const advType =
138
+ /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ paramType as {
139
+ t: string;
140
+ value?: string | number;
141
+ };
67
142
  switch (advType.t) {
68
143
  case "string-literal":
69
144
  case "numeric-literal":
70
145
  return z.literal(advType.value);
71
146
  case "object": {
72
- const objType = paramType as { t: string; props: ApiParam[] };
147
+ const objType =
148
+ /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ paramType as {
149
+ t: string;
150
+ props: ApiParam[];
151
+ };
73
152
  return getZodObjectFromApiParams(objType.props);
74
153
  }
75
154
  case "array": {
76
- const arrType = paramType as {
77
- t: string;
78
- elementsType: ApiParamType;
79
- };
155
+ const arrType =
156
+ /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ paramType as {
157
+ t: string;
158
+ elementsType: ApiParamType;
159
+ };
80
160
  return z.array(getZodTypeFromApiParamType(arrType.elementsType, references));
81
161
  }
82
162
  case "ref": {
83
- const refType = paramType as {
84
- t: string;
85
- id: string;
86
- args?: ApiParamType[];
87
- };
163
+ const refType =
164
+ /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ paramType as {
165
+ t: string;
166
+ id: string;
167
+ args?: ApiParamType[];
168
+ };
88
169
  // Date 타입 처리
89
170
  if (refType.id === "Date") {
90
171
  return z.date();
@@ -94,10 +175,10 @@ export function getZodTypeFromApiParamType(
94
175
  if (refType.args?.length !== 2) {
95
176
  throw new Error(`잘못된 ${refType.id}`);
96
177
  }
97
- const [obj, literalOrUnion] = refType.args.map(
98
- (arg) => getZodTypeFromApiParamType(arg, references),
99
- // oxlint-disable-next-line @typescript-eslint/no-explicit-any -- 생성되는 ZodUnion의 타입을 추적하기 어려움
100
- ) as [AnyZodObject, z.ZodUnion<any> | AnyZodLiteral];
178
+ const [obj, literalOrUnion] =
179
+ /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ refType.args.map(
180
+ (arg) => getZodTypeFromApiParamType(arg, references),
181
+ ) as [AnyZodObject, z.ZodUnion<any> | AnyZodLiteral];
101
182
 
102
183
  let keys: string[] = [];
103
184
  if (literalOrUnion instanceof z.ZodUnion) {
@@ -105,18 +186,25 @@ export function getZodTypeFromApiParamType(
105
186
  (option: { def: { values: string[] } }) => option.def.values[0],
106
187
  );
107
188
  } else {
108
- keys = (literalOrUnion as z.ZodLiteral<string>).def.values;
189
+ keys =
190
+ /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ (
191
+ literalOrUnion as z.ZodLiteral<string>
192
+ ).def.values;
109
193
  }
110
194
  const keyRecord = Object.fromEntries(keys.map((key) => [key, true as const]));
111
195
  if (refType.id === "Pick") {
112
196
  if (obj.pick) {
113
197
  // oxlint-disable-next-line @typescript-eslint/no-explicit-any -- Zod 4.3.6 pick 타입 호환성
114
- return obj.pick(keyRecord as any);
198
+ return obj.pick(
199
+ /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ keyRecord as any,
200
+ );
115
201
  }
116
202
  } else {
117
203
  if (obj.omit) {
118
204
  // oxlint-disable-next-line @typescript-eslint/no-explicit-any -- Zod 4.3.6 omit 타입 호환성
119
- return obj.omit(keyRecord as any);
205
+ return obj.omit(
206
+ /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ keyRecord as any,
207
+ );
120
208
  }
121
209
  }
122
210
  }
@@ -126,7 +214,9 @@ export function getZodTypeFromApiParamType(
126
214
  }
127
215
  const obj = getZodTypeFromApiParamType(refType.args[0], references);
128
216
  // oxlint-disable-next-line @typescript-eslint/no-explicit-any -- Partial 인수 타입 캐스팅
129
- return (obj as z.ZodObject<any>).partial();
217
+ return /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ (
218
+ obj as z.ZodObject<any>
219
+ ).partial();
130
220
  }
131
221
  const reference = references[refType.id];
132
222
  if (reference === undefined) {
@@ -136,10 +226,11 @@ export function getZodTypeFromApiParamType(
136
226
  return reference;
137
227
  }
138
228
  case "union": {
139
- const unionType = paramType as {
140
- t: string;
141
- types: ApiParamType[];
142
- };
229
+ const unionType =
230
+ /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ paramType as {
231
+ t: string;
232
+ types: ApiParamType[];
233
+ };
143
234
  // nullable 유니온
144
235
  if (unionType.types.length === 2 && unionType.types.some((type) => type === "null")) {
145
236
  if (unionType.types[0] === "null") {
@@ -154,10 +245,11 @@ export function getZodTypeFromApiParamType(
154
245
  );
155
246
  }
156
247
  case "intersection": {
157
- const intersectionType = paramType as {
158
- t: string;
159
- types: ApiParamType[];
160
- };
248
+ const intersectionType =
249
+ /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ paramType as {
250
+ t: string;
251
+ types: ApiParamType[];
252
+ };
161
253
  return intersectionType.types.reduce((result, type, index) => {
162
254
  const resolvedType = getZodTypeFromApiParamType(type, references);
163
255
  if (index === 0) {
@@ -165,13 +257,16 @@ export function getZodTypeFromApiParamType(
165
257
  } else {
166
258
  return z.intersection(result, resolvedType);
167
259
  }
168
- }, z.unknown() as z.ZodType);
260
+ }, /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ z.unknown() as z.ZodType);
169
261
  }
170
262
  case "tuple-type": {
171
- const tupleType = paramType as ApiParamType.TupleType;
263
+ const tupleType =
264
+ /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ paramType as ApiParamType.TupleType;
172
265
  return z.tuple(
173
266
  // oxlint-disable-next-line @typescript-eslint/no-explicit-any -- 생성되는 ZodTuple의 타입을 추적하기 어려움
174
- tupleType.elements.map((elem) => getZodTypeFromApiParamType(elem, references)) as any,
267
+ /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ tupleType.elements.map(
268
+ (elem) => getZodTypeFromApiParamType(elem, references),
269
+ ) as any,
175
270
  );
176
271
  }
177
272
  }
@@ -221,7 +316,9 @@ export function getZodObjectFromApi(
221
316
 
222
317
  // FIXME: references는 글로벌 오브젝트로, typeParam.id("T" 등)를 key로 이렇게 덮어씌워버리면 loadedTypes가 오염됨.
223
318
  // oxlint-disable-next-line @typescript-eslint/no-explicit-any -- 레퍼런스 타입 캐스팅
224
- (references[typeParam.id] as z.ZodType<any>) = zodType;
319
+ /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ (references[
320
+ typeParam.id
321
+ ] as z.ZodType<any>) = zodType;
225
322
  }
226
323
  }
227
324
  }
@@ -247,7 +344,8 @@ export function getZodObjectFromApi(
247
344
  * union, intersection, array, ref 등 모든 타입을 TS 문법으로 표현하며,
248
345
  * import가 필요한 타입 ID는 injectImportKeys에 수집합니다.
249
346
  */
250
- export function apiParamTypeToTsType(paramType: ApiParamType, injectImportKeys: string[]): string {
347
+ export function apiParamTypeToTsType<Input>(input: Input, injectImportKeys: string[]): string {
348
+ const paramType = parseApiParamType(input);
251
349
  if (
252
350
  [
253
351
  "string",
@@ -260,9 +358,11 @@ export function apiParamTypeToTsType(paramType: ApiParamType, injectImportKeys:
260
358
  "void",
261
359
  "any",
262
360
  "unknown",
263
- ].includes(paramType as string)
361
+ ].includes(
362
+ /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ paramType as string,
363
+ )
264
364
  ) {
265
- return paramType as string;
365
+ return /* SAFETY: API 데코레이터와 Zod 검증기 등록 계약이 이 값의 타입을 보장한다. */ paramType as string;
266
366
  } else if (ApiParamType.isObject(paramType)) {
267
367
  return `{ ${apiParamToTsCode(paramType.props, injectImportKeys)} }`;
268
368
  } else if (ApiParamType.isStringLiteral(paramType)) {