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
@@ -0,0 +1,175 @@
1
+ import { type ExtendedApi } from "../../api/decorators";
2
+ import {
3
+ getHttpValidatorFingerprint,
4
+ getHttpValidatorRouteIdentifier,
5
+ getHttpValidatorRouteKey,
6
+ } from "../../api/http-validator";
7
+ import { Sonamu } from "../../api/sonamu";
8
+ import { type ApiParamType } from "../../types/types";
9
+ import { isObjectValue, isStringValue } from "../../utils/runtime-value";
10
+ import { Template } from "../template";
11
+
12
+ function collectReferencedTypes(type: ApiParamType, result: Set<string>): void {
13
+ if (isStringValue(type)) {
14
+ return;
15
+ }
16
+ switch (type.t) {
17
+ case "ref":
18
+ result.add(type.id);
19
+ for (const argument of type.args ?? []) {
20
+ collectReferencedTypes(argument, result);
21
+ }
22
+ return;
23
+ case "array":
24
+ collectReferencedTypes(type.elementsType, result);
25
+ return;
26
+ case "object":
27
+ for (const prop of type.props) {
28
+ collectReferencedTypes(prop.type, result);
29
+ }
30
+ return;
31
+ case "union":
32
+ case "intersection":
33
+ for (const member of type.types) {
34
+ collectReferencedTypes(member, result);
35
+ }
36
+ return;
37
+ case "tuple-type":
38
+ for (const element of type.elements) {
39
+ collectReferencedTypes(element, result);
40
+ }
41
+ return;
42
+ case "indexed-access":
43
+ collectReferencedTypes(type.object, result);
44
+ collectReferencedTypes(type.index, result);
45
+ return;
46
+ case "type-param":
47
+ if (type.constraint !== undefined) {
48
+ collectReferencedTypes(type.constraint, result);
49
+ }
50
+ return;
51
+ case "function":
52
+ for (const parameter of type.parameters) {
53
+ collectReferencedTypes(parameter.type, result);
54
+ }
55
+ collectReferencedTypes(type.returnType, result);
56
+ return;
57
+ case "string-literal":
58
+ case "numeric-literal":
59
+ return;
60
+ }
61
+ }
62
+
63
+ export class Template__http_validators extends Template {
64
+ constructor() {
65
+ super("http_validators");
66
+ }
67
+
68
+ getTargetAndPath() {
69
+ return {
70
+ target: `${Sonamu.config.api.dir}/src/application`,
71
+ path: "sonamu.validators.generated.ts",
72
+ };
73
+ }
74
+
75
+ render() {
76
+ const apis = [...Sonamu.syncer.apis]
77
+ .filter((api) => api.websocketOptions === undefined)
78
+ .toSorted((left, right) =>
79
+ getHttpValidatorRouteKey(left).localeCompare(getHttpValidatorRouteKey(right)),
80
+ );
81
+ const routeKeys = apis.map(getHttpValidatorRouteKey);
82
+ const duplicateKey = routeKeys.find((key, index) => routeKeys.indexOf(key) !== index);
83
+ if (duplicateKey !== undefined) {
84
+ throw new Error(`중복된 HTTP validator route key: ${duplicateKey}`);
85
+ }
86
+
87
+ const fingerprint = getHttpValidatorFingerprint(apis);
88
+ const policy = Sonamu.config.validation?.zodCompiler;
89
+ const isAot = isObjectValue(policy) && policy !== null && policy.api === "aot";
90
+ const hasAotValidators = isAot && apis.length > 0;
91
+ const referencedTypes = new Set<string>();
92
+ for (const api of apis) {
93
+ for (const typeParameter of api.typeParameters) {
94
+ collectReferencedTypes(typeParameter, referencedTypes);
95
+ }
96
+ for (const parameter of api.parameters) {
97
+ collectReferencedTypes(parameter.type, referencedTypes);
98
+ }
99
+ }
100
+ const importKeys = [...referencedTypes]
101
+ .filter((typeName) => Sonamu.syncer.types[typeName] !== undefined)
102
+ .toSorted();
103
+ const body = isAot
104
+ ? this.renderAotRegistry(apis, fingerprint, importKeys)
105
+ : this.renderPlainStub(apis, fingerprint);
106
+
107
+ return {
108
+ ...this.getTargetAndPath(),
109
+ body,
110
+ importKeys,
111
+ customHeaders: [
112
+ "/**",
113
+ " * @generated",
114
+ " * 직접 수정하지 마세요.",
115
+ " */",
116
+ "",
117
+ "/* oxlint-disable */",
118
+ "",
119
+ ...(hasAotValidators
120
+ ? [
121
+ `import { compile } from "zod-compiler";`,
122
+ `import { fastifyCaster, getZodObjectFromApi } from "sonamu";`,
123
+ ]
124
+ : []),
125
+ ],
126
+ };
127
+ }
128
+
129
+ private renderAotRegistry(
130
+ apis: ExtendedApi[],
131
+ fingerprint: string,
132
+ importKeys: string[],
133
+ ): string {
134
+ const declarations = apis.map((api) => {
135
+ const identifier = `validator_${getHttpValidatorRouteIdentifier(api)}`;
136
+ const schemaApi = {
137
+ modelName: api.modelName,
138
+ methodName: api.methodName,
139
+ path: api.path,
140
+ options: { httpMethod: api.options.httpMethod ?? "GET" },
141
+ typeParameters: api.typeParameters,
142
+ parameters: api.parameters,
143
+ returnType: "unknown",
144
+ } satisfies ExtendedApi;
145
+ return `export const ${identifier} = compile(fastifyCaster(getZodObjectFromApi(${JSON.stringify(schemaApi)}, { ...types })));`;
146
+ });
147
+ const routeIds = Object.fromEntries(
148
+ apis.map((api) => [getHttpValidatorRouteKey(api), getHttpValidatorRouteIdentifier(api)]),
149
+ );
150
+
151
+ return [
152
+ `export const fingerprint = ${JSON.stringify(fingerprint)};`,
153
+ `export const routeIds = ${JSON.stringify(routeIds)};`,
154
+ `const types = { ${importKeys.join(", ")} };`,
155
+ ...declarations,
156
+ `export const validators = new Map([`,
157
+ ...apis.map((api) => {
158
+ const routeKey = getHttpValidatorRouteKey(api);
159
+ return ` [${JSON.stringify(routeKey)}, validator_${getHttpValidatorRouteIdentifier(api)}],`;
160
+ }),
161
+ `]);`,
162
+ ].join("\n");
163
+ }
164
+
165
+ private renderPlainStub(apis: ExtendedApi[], fingerprint: string): string {
166
+ const routeIds = Object.fromEntries(
167
+ apis.map((api) => [getHttpValidatorRouteKey(api), getHttpValidatorRouteIdentifier(api)]),
168
+ );
169
+ return [
170
+ `export const fingerprint = ${JSON.stringify(fingerprint)};`,
171
+ `export const routeIds = ${JSON.stringify(routeIds)};`,
172
+ `export const validators = new Map();`,
173
+ ].join("\n");
174
+ }
175
+ }
@@ -33,7 +33,9 @@ export class Template__model extends Template {
33
33
  const listParamsNode = zodTypeToRenderingNode(listParamsZodType);
34
34
 
35
35
  const subsetKeyZodType = await getZodTypeById(`${entityId}SubsetKey`);
36
- const subsetKeys = (subsetKeyZodType as z.ZodEnum).enum;
36
+ const subsetKeys =
37
+ /* SAFETY: 생성된 *SubsetKey 타입은 enum 스키마로 등록된다. */ (subsetKeyZodType as z.ZodEnum)
38
+ .enum;
37
39
 
38
40
  const names = EntityManager.getNamesFromId(entityId);
39
41
  const entity = EntityManager.get(entityId);
@@ -52,8 +52,9 @@ const SUPPORTED_LOCALES = ${JSON.stringify(supportedLocales)} as const;
52
52
  function getCurrentLocale(): (typeof SUPPORTED_LOCALES)[number] {
53
53
  try {
54
54
  const ctx = Sonamu.getContext();
55
- return ctx.locale as (typeof SUPPORTED_LOCALES)[number] ?? DEFAULT_LOCALE;
56
- } catch (_) {
55
+ const locale = ctx.locale;
56
+ return SUPPORTED_LOCALES.find((supportedLocale) => supportedLocale === locale) ?? DEFAULT_LOCALE;
57
+ } catch {
57
58
  return DEFAULT_LOCALE;
58
59
  }
59
60
  }
@@ -61,14 +62,14 @@ function getCurrentLocale(): (typeof SUPPORTED_LOCALES)[number] {
61
62
  : `
62
63
  const DEFAULT_LOCALE = "${defaultLocale}" as const;
63
64
  export const SUPPORTED_LOCALES = ${JSON.stringify(supportedLocales)} as const;
64
- let _currentLocale: (typeof SUPPORTED_LOCALES)[number] = DEFAULT_LOCALE;
65
+ let currentLocale: (typeof SUPPORTED_LOCALES)[number] = DEFAULT_LOCALE;
65
66
 
66
67
  export function setLocale(locale: (typeof SUPPORTED_LOCALES)[number]) {
67
- _currentLocale = locale;
68
+ currentLocale = locale;
68
69
  }
69
70
 
70
71
  export function getCurrentLocale(): (typeof SUPPORTED_LOCALES)[number] {
71
- return _currentLocale;
72
+ return currentLocale;
72
73
  }
73
74
  `.trim();
74
75
 
@@ -126,7 +127,10 @@ export function defineLocale(dict: Partial<MergedDictionary>) {
126
127
  }
127
128
 
128
129
  // 각 locale별로 rc-keys + entity labels + 프로젝트 dict 합침
129
- const dictionaries: Record<string, Partial<MergedDictionary>> = {
130
+ type DictionaryRegistry = {
131
+ [L in (typeof SUPPORTED_LOCALES)[number]]: Partial<MergedDictionary>;
132
+ };
133
+ const dictionaries: DictionaryRegistry = {
130
134
  ${defaultLocale}: { ...${getRCKeysVarName(defaultLocale)}, ...entityLabels, ...${defaultLocale} },
131
135
  ${supportedLocales
132
136
  .filter((locale) => locale !== defaultLocale)
@@ -138,29 +142,33 @@ type SDReturnType<K extends DictKey> = MergedDictionary[K] extends (...args: inf
138
142
  ? (...args: P) => LocalizedString
139
143
  : LocalizedString;
140
144
 
141
- function getDictValue<K extends DictKey>(key: K, locale: string): SDReturnType<K> {
145
+ function getDictValue<K extends DictKey>(key: K, locale: (typeof SUPPORTED_LOCALES)[number]): SDReturnType<K> {
142
146
  // 1. 지정된 locale에서 조회
143
147
  const dict = dictionaries[locale];
144
148
  if (dict?.[key] !== undefined) {
145
- return dict[key] as unknown as SDReturnType<K>;
149
+ // SAFETY: 요청 locale의 같은 키는 MergedDictionary가 정한 반환 종류를 유지합니다.
150
+ return dict[key] as SDReturnType<K>;
146
151
  }
147
152
 
148
153
  // 2. default locale에서 조회
149
154
  if (locale !== DEFAULT_LOCALE && dictionaries[DEFAULT_LOCALE]?.[key] !== undefined) {
150
- return dictionaries[DEFAULT_LOCALE][key] as unknown as SDReturnType<K>;
155
+ // SAFETY: 기본 locale의 같은 키는 MergedDictionary가 정한 반환 종류를 유지합니다.
156
+ return dictionaries[DEFAULT_LOCALE][key] as SDReturnType<K>;
151
157
  }
152
158
 
153
159
  // 3. supported locales 순회
154
160
  for (const supportedLocale of SUPPORTED_LOCALES) {
155
161
  if (supportedLocale !== locale && supportedLocale !== DEFAULT_LOCALE) {
156
162
  if (dictionaries[supportedLocale]?.[key] !== undefined) {
157
- return dictionaries[supportedLocale][key] as unknown as SDReturnType<K>;
163
+ // SAFETY: 대체 locale의 같은 키는 MergedDictionary가 정한 반환 종류를 유지합니다.
164
+ return dictionaries[supportedLocale][key] as SDReturnType<K>;
158
165
  }
159
166
  }
160
167
  }
161
168
 
162
- // 4. 모두 실패 시 key 반환
163
- return key as unknown as SDReturnType<K>;
169
+ // 모든 locale에 값이 없으면 동적으로 조합된 키를 그대로 노출합니다.
170
+ // SAFETY: 누락된 사전 키의 문자열 표현은 LocalizedString fallback 규약을 따릅니다.
171
+ return String(key) as SDReturnType<K>;
164
172
  }
165
173
 
166
174
  /**
@@ -226,58 +234,85 @@ type LocalizedColumnCandidate<T, K extends string> =
226
234
  type LocalizedColumnReturn<T, K extends string> =
227
235
  | LocalizedColumnValueFrom<LocalizedColumnCandidate<T, K>>
228
236
  | undefined;
229
- type LocaleValueMap = Partial<Record<(typeof SUPPORTED_LOCALES)[number], unknown>>;
237
+ type LocaleValueMap = {
238
+ [L in (typeof SUPPORTED_LOCALES)[number]]?: LocalizedColumnValue;
239
+ };
240
+ function isString<V>(value: V): value is V & string {
241
+ return Object.prototype.toString.call(value) === "[object String]";
242
+ }
230
243
 
231
- function isLocalizedColumnValue(value: unknown): value is LocalizedColumnValue {
232
- return typeof value === "string" || (Array.isArray(value) && value.every((item) => typeof item === "string"));
244
+ function isLocalizedColumnValue<V>(value: V): value is V & LocalizedColumnValue {
245
+ return isString(value) || (Array.isArray(value) && value.every(isString));
233
246
  }
234
247
 
235
- function isLocalizedColumnScalarValue(value: unknown): value is LocalizedColumnScalarValue {
236
- return ["string", "number", "boolean", "bigint"].includes(typeof value);
248
+ function isLocalizedColumnScalarValue<V>(value: V): value is V & LocalizedColumnScalarValue {
249
+ return ["[object String]", "[object Number]", "[object Boolean]", "[object BigInt]"].includes(
250
+ Object.prototype.toString.call(value),
251
+ );
237
252
  }
238
253
 
239
- function isEmptyLocalizedColumnValue(value: unknown): value is null | undefined | "" {
254
+ function isEmptyLocalizedColumnValue<V>(value: V): value is V & (null | undefined | "") {
240
255
  return value === null || value === undefined || value === "";
241
256
  }
242
257
 
243
- function getNestedLocaleValue<T extends Record<string, unknown>, K extends LocalizedBaseColumn<T>>(
258
+ type PropertyValue<T, K extends PropertyKey> = K extends keyof T ? T[K] : undefined;
259
+
260
+ function getProperty<T extends object, K extends PropertyKey>(row: T, key: K): PropertyValue<T, K> {
261
+ if (!(key in row)) {
262
+ // SAFETY: 존재하지 않는 후보 키는 조건부 속성 타입에서도 undefined입니다.
263
+ return undefined as PropertyValue<T, K>;
264
+ }
265
+
266
+ // SAFETY: own/inherited 키 존재를 확인했으므로 해당 키의 조건부 속성 타입으로 좁힐 수 있습니다.
267
+ return (row as T & Record<K, PropertyValue<T, K>>)[key];
268
+ }
269
+
270
+ function getNestedLocaleValue<T extends object, K extends LocalizedBaseColumn<T>>(
244
271
  row: T,
245
272
  column: K,
246
273
  locale: (typeof SUPPORTED_LOCALES)[number],
247
- ): unknown {
248
- const columnValue = row[column];
249
- if (columnValue === null || typeof columnValue !== "object" || Array.isArray(columnValue)) {
274
+ ): LocalizedColumnValue | undefined {
275
+ const columnValue = getProperty(row, column);
276
+ if (columnValue === null || Object.prototype.toString.call(columnValue) !== "[object Object]") {
250
277
  return undefined;
251
278
  }
252
279
 
280
+ // SAFETY: 일반 객체 검사를 통과한 값만 locale별 값 맵으로 조회합니다.
253
281
  return (columnValue as LocaleValueMap)[locale];
254
282
  }
255
283
 
256
- export function localizedColumn<T extends Record<string, unknown>, K extends LocalizedBaseColumn<T>>(
284
+ function localizedKey<K extends string>(columnName: K, localeName: (typeof SUPPORTED_LOCALES)[number]) {
285
+ return \`\${columnName}_\${localeName}\`;
286
+ }
287
+
288
+ export function localizedColumn<T extends object, K extends LocalizedBaseColumn<T>>(
257
289
  row: T,
258
290
  column: K,
259
291
  ): LocalizedColumnReturn<T, K> {
260
- const currentLocale = getCurrentLocale();
261
- const locale = SUPPORTED_LOCALES.includes(currentLocale) ? currentLocale : DEFAULT_LOCALE;
262
- const otherLocales = SUPPORTED_LOCALES.filter((l: string) => l !== locale && l !== DEFAULT_LOCALE);
263
- const localizedKey = (column: K, locale: (typeof SUPPORTED_LOCALES)[number]) => \`\${column}_\${locale}\`;
292
+ const requestedLocale = getCurrentLocale();
293
+ const locale = SUPPORTED_LOCALES.includes(requestedLocale) ? requestedLocale : DEFAULT_LOCALE;
294
+ const otherLocales = SUPPORTED_LOCALES.filter(
295
+ (candidateLocale) => candidateLocale !== locale && candidateLocale !== DEFAULT_LOCALE,
296
+ );
264
297
  const values = [
265
- { value: row[localizedKey(column, locale)], source: "direct" },
298
+ { value: getProperty(row, localizedKey(column, locale)), source: "direct" },
266
299
  { value: getNestedLocaleValue(row, column, locale), source: "nested" },
267
- { value: row[column], source: "direct" },
268
- { value: row[localizedKey(column, DEFAULT_LOCALE)], source: "direct" },
300
+ { value: getProperty(row, column), source: "direct" },
301
+ { value: getProperty(row, localizedKey(column, DEFAULT_LOCALE)), source: "direct" },
269
302
  { value: getNestedLocaleValue(row, column, DEFAULT_LOCALE), source: "nested" },
270
303
  ...otherLocales.flatMap((l) => [
271
- { value: row[localizedKey(column, l)], source: "direct" },
304
+ { value: getProperty(row, localizedKey(column, l)), source: "direct" },
272
305
  { value: getNestedLocaleValue(row, column, l), source: "nested" },
273
306
  ]),
274
307
  ];
275
308
 
276
309
  for (const { value, source } of values) {
277
310
  if (!isEmptyLocalizedColumnValue(value) && isLocalizedColumnValue(value)) {
311
+ // SAFETY: 값 가드가 선택한 컬럼의 문자열 또는 문자열 배열임을 확인했습니다.
278
312
  return value as LocalizedColumnReturn<T, K>;
279
313
  }
280
314
  if (source === "direct" && !isEmptyLocalizedColumnValue(value) && isLocalizedColumnScalarValue(value)) {
315
+ // SAFETY: 직접 컬럼의 스칼라 값은 문자열로 변환해 지역화 반환 타입을 충족합니다.
281
316
  return String(value) as LocalizedColumnReturn<T, K>;
282
317
  }
283
318
  }
@@ -292,14 +327,19 @@ export function localizedColumn<T extends Record<string, unknown>, K extends Loc
292
327
  * @example
293
328
  * SD.enumLabels("TagOrderBy")[key] // → 현재 locale의 라벨
294
329
  */
295
- SD.enumLabels = (enumName: string): Record<string, LocalizedString> => {
296
- return new Proxy({} as Record<string, LocalizedString>, {
330
+ interface EnumLabels {
331
+ [key: string]: LocalizedString;
332
+ }
333
+
334
+ SD.enumLabels = (enumName: string): EnumLabels => {
335
+ return new Proxy<EnumLabels>({}, {
297
336
  get(_, key: string | symbol) {
298
- if (typeof key === "symbol") {
337
+ if (Object.prototype.toString.call(key) === "[object Symbol]") {
299
338
  return undefined;
300
339
  }
301
340
 
302
- const dictKey = \`enum.\${enumName}.\${key}\` as DictKey;
341
+ // SAFETY: 생성된 enum 이름과 값의 조합은 enum 사전 키 형식을 따릅니다.
342
+ const dictKey = \`enum.\${enumName}.\${String(key)}\` as DictKey;
303
343
  return getDictValue(dictKey, getCurrentLocale());
304
344
  }
305
345
  });
@@ -318,16 +358,16 @@ SD.enumLabels = (enumName: string): Record<string, LocalizedString> => {
318
358
  * react-components의 rc-keys를 추출합
319
359
  * sonamu/src/dict/rc-keys.ts 파일의 소스 코드를 직접 읽어서 반환
320
360
  */
321
- private extractRCKeysSourceCode(): { ko: string; en: string } {
361
+ private extractRCKeysSourceCode() {
322
362
  try {
323
363
  // rc-keys.ts 파일 경로
324
- const __filename = fileURLToPath(import.meta.url);
325
- const __dirname = path.dirname(__filename);
364
+ const currentFilename = fileURLToPath(import.meta.url);
365
+ const currentDirectory = path.dirname(currentFilename);
326
366
 
327
367
  // dist에서 실행될 때는 src로 경로 변경
328
- const basePath = __dirname.includes("/dist/")
329
- ? __dirname.replace("/dist/", "/src/")
330
- : __dirname;
368
+ const basePath = currentDirectory.includes("/dist/")
369
+ ? currentDirectory.replace("/dist/", "/src/")
370
+ : currentDirectory;
331
371
 
332
372
  const rcKeysPath = path.join(basePath, "../../dict/rc-keys.ts");
333
373
 
@@ -11,6 +11,7 @@ import { Sonamu } from "../../api/sonamu";
11
11
  import { EntityManager } from "../../entity/entity-manager";
12
12
  import { type TemplateOptions } from "../../types/types";
13
13
  import { ApiParamType } from "../../types/types";
14
+ import { isStringValue } from "../../utils/runtime-value";
14
15
  import { assertDefined } from "../../utils/utils";
15
16
  import { Template } from "../template";
16
17
  import { BUILT_IN_TYPES, zodTypeToTsTypeDef } from "../zod-converter";
@@ -197,8 +198,7 @@ export function ${methodNameWebSocketCamelized}(
197
198
  .map((param) => {
198
199
  // primitive 타입인지 체크
199
200
  const isPrimitive =
200
- typeof param.type === "string" &&
201
- ["string", "number", "boolean"].includes(param.type);
201
+ isStringValue(param.type) && ["string", "number", "boolean"].includes(param.type);
202
202
 
203
203
  if (isPrimitive) {
204
204
  // primitive: 직접 formData.append
@@ -11,6 +11,18 @@ import {
11
11
  } from "../helpers";
12
12
  import { Template } from "../template";
13
13
 
14
+ type FormDefaultValue =
15
+ | null
16
+ | undefined
17
+ | boolean
18
+ | number
19
+ | string
20
+ | never[]
21
+ | Record<string, never>;
22
+ interface FormDefaults {
23
+ [columnName: string]: FormDefaultValue;
24
+ }
25
+
14
26
  export class Template__view_form extends Template {
15
27
  constructor() {
16
28
  super("view_form");
@@ -149,41 +161,38 @@ export class Template__view_form extends Template {
149
161
  }
150
162
  }
151
163
 
152
- resolveDefaultValue(columns: RenderingNode[]): object {
153
- return columns.reduce(
154
- (result, col) => {
155
- if (col.optional) {
156
- return result;
157
- }
164
+ resolveDefaultValue(columns: RenderingNode[]): FormDefaults {
165
+ return columns.reduce<FormDefaults>((result, col) => {
166
+ if (col.optional) {
167
+ return result;
168
+ }
158
169
 
159
- let value: unknown;
160
- if (col.nullable === true) {
161
- value = null;
162
- } else if (col.zodType instanceof z.ZodNumber) {
163
- value = 0;
164
- } else if (col.zodType instanceof z.ZodEnum) {
165
- value = Object.keys(col.zodType.enum)[0];
166
- } else if (col.zodType instanceof z.ZodBoolean) {
167
- value = false;
168
- } else if (col.zodType instanceof z.core.$ZodString) {
169
- // NOTE: z.ZodString으로 비교하면 z.url(), z.email() 등의 타입에서 문제가 생기므로 z.core.$ZodString으로 비교함
170
- // FIXME: email이나 url 타입 등에 대한 처리가 필요함
171
- if (col.renderType === "string-datetime") {
172
- value = "now()";
173
- } else {
174
- value = "";
175
- }
176
- } else if (col.zodType instanceof z.ZodArray) {
177
- value = [];
178
- } else if (col.zodType instanceof z.ZodObject) {
179
- value = {};
170
+ let value: FormDefaultValue;
171
+ if (col.nullable === true) {
172
+ value = null;
173
+ } else if (col.zodType instanceof z.ZodNumber) {
174
+ value = 0;
175
+ } else if (col.zodType instanceof z.ZodEnum) {
176
+ value = Object.keys(col.zodType.enum)[0];
177
+ } else if (col.zodType instanceof z.ZodBoolean) {
178
+ value = false;
179
+ } else if (col.zodType instanceof z.core.$ZodString) {
180
+ // NOTE: z.ZodString으로 비교하면 z.url(), z.email() 등의 타입에서 문제가 생기므로 z.core.$ZodString으로 비교함
181
+ // FIXME: email이나 url 타입 등에 대한 처리가 필요함
182
+ if (col.renderType === "string-datetime") {
183
+ value = "now()";
184
+ } else {
185
+ value = "";
180
186
  }
187
+ } else if (col.zodType instanceof z.ZodArray) {
188
+ value = [];
189
+ } else if (col.zodType instanceof z.ZodObject) {
190
+ value = {};
191
+ }
181
192
 
182
- result[col.name] = value;
183
- return result;
184
- },
185
- {} as { [key: string]: unknown },
186
- );
193
+ result[col.name] = value;
194
+ return result;
195
+ }, {});
187
196
  }
188
197
 
189
198
  async render({ entityId }: TemplateOptions["view_form"]) {
@@ -228,12 +237,16 @@ export class Template__view_form extends Template {
228
237
  try {
229
238
  const { id } = getEnumInfoFromColName(entityId, col.name);
230
239
  enumImports.add(id);
231
- } catch {}
240
+ } catch {
241
+ return;
242
+ }
232
243
  } else if (col.renderType === "number-fk_id" || col.renderType === "string-fk_id") {
233
244
  try {
234
245
  const relProp = getRelationPropFromColName(entityId, col.name.replace("_id", ""));
235
246
  fkConfigImports.add(relProp.with);
236
- } catch {}
247
+ } catch {
248
+ return;
249
+ }
237
250
  } else if (
238
251
  col.renderType === "string-plain" &&
239
252
  col.name.endsWith("_id") &&
@@ -243,14 +256,18 @@ export class Template__view_form extends Template {
243
256
  try {
244
257
  const relProp = getRelationPropFromColName(entityId, col.name.replace("_id", ""));
245
258
  fkConfigImports.add(relProp.with);
246
- } catch {}
259
+ } catch {
260
+ return;
261
+ }
247
262
  } else if (col.renderType === "array" && col.name.endsWith("_ids")) {
248
263
  // ManyToMany relation의 FK 배열
249
264
  try {
250
265
  const baseName = col.name.replace(/_ids$/, "");
251
266
  const relProp = getRelationPropFromColName(entityId, baseName);
252
267
  fkConfigImports.add(relProp.with);
253
- } catch {}
268
+ } catch {
269
+ return;
270
+ }
254
271
  }
255
272
  });
256
273
 
@@ -295,7 +312,7 @@ import { defaultCatch } from "@/services/sonamu.shared";
295
312
  import { ${names.capital}SaveParams } from "@/services/${names.fs}/${names.fs}.types";${
296
313
  fkConfigImports.size > 0
297
314
  ? `\nimport { ${Array.from(fkConfigImports)
298
- .map((entity) => `${entity}AsyncIdConfig`)
315
+ .map((relatedEntityId) => `${relatedEntityId}AsyncIdConfig`)
299
316
  .join(", ")} } from "@/services/services.generated";`
300
317
  : ""
301
318
  }
@@ -487,8 +504,8 @@ ${columns
487
504
  const label = (() => {
488
505
  if (col.label.endsWith("Id")) {
489
506
  try {
490
- const entity = EntityManager.get(col.label.replace("Id", ""));
491
- return entity.title ?? col.label;
507
+ const relatedEntity = EntityManager.get(col.label.replace("Id", ""));
508
+ return relatedEntity.title ?? col.label;
492
509
  } catch {
493
510
  return col.label;
494
511
  }