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
@@ -11,6 +11,8 @@ import {
11
11
  type DatabaseSchemaExtend,
12
12
  type EntityIndex,
13
13
  } from "../types/types";
14
+ import { asArray } from "../utils/model";
15
+ import { isNumberValue, isObjectValue, isStringValue } from "../utils/runtime-value";
14
16
  import { assertDefined, nonNullable } from "../utils/utils";
15
17
  import { batchUpdate } from "./_batch_update";
16
18
  import { type RowWithId } from "./_batch_update";
@@ -27,22 +29,36 @@ export type { DatabaseForeignKeys };
27
29
  type InheritableColumns<TTable extends TableName<DatabaseSchemaExtend>> =
28
30
  TTable extends keyof DatabaseSchemaExtend ? ColumnKeys<DatabaseSchemaExtend[TTable]> : never;
29
31
 
32
+ // 참조 필드 타입
33
+ export type UBRef = {
34
+ uuid: string;
35
+ of: string;
36
+ use?: string;
37
+ };
38
+
39
+ type UpsertValue =
40
+ | string
41
+ | number
42
+ | boolean
43
+ | bigint
44
+ | Date
45
+ | Buffer
46
+ | Knex.Raw
47
+ | UBRef
48
+ | null
49
+ | UpsertValue[]
50
+ | { [key: string]: UpsertValue | undefined };
51
+ type UpsertRow = Record<string, UpsertValue | undefined>;
52
+
30
53
  // 테이블 데이터 타입
31
54
  type TableData = {
32
55
  references: Set<string>;
33
- rows: Record<string, unknown>[];
56
+ rows: UpsertRow[];
34
57
  uniqueIndexes: EntityIndex[];
35
58
  uniquesMap: Map<string, string>;
36
59
  jsonColumns: string[];
37
60
  };
38
61
 
39
- // 참조 필드 타입
40
- export type UBRef = {
41
- uuid: string;
42
- of: string;
43
- use?: string;
44
- };
45
-
46
62
  // upsert 옵션
47
63
  export type UpsertOptions<TTable extends TableName<DatabaseSchemaExtend>> = {
48
64
  chunkSize?: number;
@@ -55,13 +71,8 @@ export type InsertOnlyOptions = {
55
71
  chunkSize?: number;
56
72
  };
57
73
 
58
- export function isRefField(field: unknown): field is UBRef {
59
- return (
60
- field !== undefined &&
61
- field !== null &&
62
- (field as UBRef)?.of !== undefined &&
63
- (field as UBRef)?.uuid !== undefined
64
- );
74
+ export function isRefField<Value>(field: Value): field is Value & UBRef {
75
+ return isObjectValue(field) && "of" in field && "uuid" in field;
65
76
  }
66
77
 
67
78
  export class UpsertBuilder {
@@ -99,22 +110,19 @@ export class UpsertBuilder {
99
110
  return this.tables.has(tableName);
100
111
  }
101
112
 
102
- register<T extends string>(
103
- tableName: string,
104
- row: {
105
- [key in T]?: UBRef | string | number | boolean | bigint | null | object | unknown;
106
- },
107
- ): UBRef {
113
+ register<Row extends object>(tableName: string, row: Row): UBRef {
108
114
  const table = this.getTable(tableName);
109
115
 
110
116
  // 해당 테이블의 unique 인덱스를 순회하며 키 생성
111
117
  const uniqueKeys = table.uniqueIndexes
112
118
  .map((unqIndex) => {
113
119
  const uniqueKeyArray = unqIndex.columns.map((unqCol) => {
120
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
114
121
  const val = row[unqCol.name as keyof typeof row];
115
122
  if (isRefField(val)) {
116
123
  return val.uuid;
117
124
  } else {
125
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
118
126
  return row[unqCol.name as keyof typeof row] ?? randomUUID(); // nullable인 경우 uuid로 랜덤값 삽입
119
127
  }
120
128
  });
@@ -154,32 +162,33 @@ export class UpsertBuilder {
154
162
 
155
163
  // 이 테이블에 사용된 RefField를 순회하여, 현재 테이블 정보에 어떤 필드를 참조하는지 추가
156
164
  // 이 정보를 나중에 치환할 때 사용
157
- row = Object.fromEntries(
165
+ const normalizedRow = Object.fromEntries(
158
166
  Object.entries(row).map(([rowKey, rowValue]) => {
159
167
  if (isRefField(rowValue)) {
160
168
  rowValue.use ??= "id";
161
169
  table.references.add(`${rowValue.of}.${rowValue.use}`);
162
- return [rowKey, rowValue];
170
+ return [rowKey, rowValue] as const;
163
171
  } else if (table.jsonColumns.includes(rowKey) && rowValue !== null) {
164
172
  // JSON 컬럼인 경우 JSON.stringify 처리 (Knex는 JSON 타입을 지원하지 않음)
165
- return [rowKey, JSON.stringify(rowValue)];
173
+ return [rowKey, JSON.stringify(rowValue)] as const;
166
174
  } else if (isArray(rowValue)) {
167
175
  // 배열은 그대로 저장
168
- return [rowKey, rowValue];
176
+ return [rowKey, rowValue] as const;
169
177
  } else {
170
- return [rowKey, rowValue];
178
+ return [rowKey, rowValue] as const;
171
179
  }
172
180
  }),
173
- ) as { [key in T]?: unknown };
181
+ );
174
182
 
175
183
  table.rows.push({
176
184
  uuid,
177
- ...row,
185
+ ...normalizedRow,
178
186
  });
179
187
 
180
188
  const result: UBRef = {
181
189
  of: tableName,
182
- uuid: (row as { uuid?: string }).uuid ?? uuid,
190
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
191
+ uuid: isStringValue(normalizedRow.uuid) ? normalizedRow.uuid : uuid,
183
192
  };
184
193
 
185
194
  Naite.t("puri:ub-register", {
@@ -235,19 +244,21 @@ export class UpsertBuilder {
235
244
 
236
245
  // 전체 테이블 순회하여 현재 테이블 참조하는 모든 테이블 추출
237
246
  const { references, refTables } = Array.from(this.tables).reduce(
238
- (r, [, table]) => {
239
- const reference = Array.from(table.references.values()).find((ref) =>
247
+ (r, [, candidateTable]) => {
248
+ const reference = Array.from(candidateTable.references.values()).find((ref) =>
240
249
  ref.includes(`${tableName}.`),
241
250
  );
242
251
  if (reference) {
243
252
  r.references.push(reference);
244
- r.refTables.push(table);
253
+ r.refTables.push(candidateTable);
245
254
  }
246
255
 
247
256
  return r;
248
257
  },
249
258
  {
259
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
250
260
  references: [] as string[],
261
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
251
262
  refTables: [] as TableData[],
252
263
  },
253
264
  );
@@ -262,7 +273,7 @@ export class UpsertBuilder {
262
273
  throw new Error(`${tableName}에 순환 자기 참조가 있습니다.`);
263
274
  }
264
275
 
265
- const uuidMap = new Map<string, unknown>();
276
+ const uuidMap = new Map<string, UpsertRow & { id: number | string }>();
266
277
  const allIds: (number | string)[] = [];
267
278
 
268
279
  // 레벨별로 순차 처리
@@ -282,7 +293,8 @@ export class UpsertBuilder {
282
293
 
283
294
  if (!parent) throw new Error(`존재하지 않는 uuid ${value.uuid} -- in ${tableName}`);
284
295
 
285
- resolved[key] = (parent as Record<string, unknown>)[value.use ?? "id"];
296
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
297
+ resolved[key] = (parent as UpsertRow)[value.use ?? "id"];
286
298
 
287
299
  Naite.t("puri:ub-ref-resolved", {
288
300
  tableName,
@@ -309,10 +321,15 @@ export class UpsertBuilder {
309
321
  });
310
322
 
311
323
  // uuid를 별도로 보관하고, DB에 저장할 데이터에서 제거
324
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
312
325
  const originalUuids = dataChunk.map((r) => r.uuid as string);
313
- const dataForDb = dataChunk.map(({ uuid: _, ...rest }) => rest);
326
+ const dataForDb = dataChunk.map((row) => {
327
+ const rest = { ...row };
328
+ delete rest.uuid;
329
+ return rest;
330
+ });
314
331
 
315
- let resultRows: { id: number | string; [key: string]: unknown }[];
332
+ let resultRows: (UpsertRow & { id: number | string })[];
316
333
 
317
334
  if (mode === "insert") {
318
335
  // INSERT 모드 - RETURNING 사용
@@ -339,9 +356,11 @@ export class UpsertBuilder {
339
356
  if (conditions.length === 0) continue;
340
357
 
341
358
  // 배치 SELECT
359
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
342
360
  const existingRows = (await wdb(tableName)
343
- .whereIn(columns, conditions as Record<string, unknown>[][])
344
- .select("id", ...columns)) as Record<string, unknown>[];
361
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
362
+ .whereIn(columns, conditions as UpsertRow[][])
363
+ .select("id", ...columns)) as UpsertRow[];
345
364
 
346
365
  // Map 생성: unique 컬럼 조합 → id
347
366
  const existingMap = new Map<string, number | string>();
@@ -350,7 +369,7 @@ export class UpsertBuilder {
350
369
  .map((col) => String(existing[col] ?? ""))
351
370
  .join("---delimiter---");
352
371
  const id = existing.id;
353
- if (typeof id === "number" || typeof id === "string") {
372
+ if (isNumberValue(id) || isStringValue(id)) {
354
373
  existingMap.set(key, id);
355
374
  }
356
375
  }
@@ -377,6 +396,7 @@ export class UpsertBuilder {
377
396
 
378
397
  // inherit 옵션 처리 - inherit 컬럼은 update 대상에서 제외
379
398
  if (options?.inherit?.length) {
399
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
380
400
  const inheritColumns = options.inherit as string[];
381
401
 
382
402
  const excludedFromUpdate = updateColumns.filter((c) => inheritColumns.includes(c));
@@ -415,8 +435,8 @@ export class UpsertBuilder {
415
435
  }
416
436
 
417
437
  // 해당 테이블 참조를 실제 밸류로 변경
418
- for (const table of refTables) {
419
- table.rows = table.rows.map((row) => {
438
+ for (const referencingTable of refTables) {
439
+ referencingTable.rows = referencingTable.rows.map((row) => {
420
440
  for (const key of Object.keys(row)) {
421
441
  const prop = row[key];
422
442
  if (isRefField(prop) && prop.of === tableName) {
@@ -425,7 +445,8 @@ export class UpsertBuilder {
425
445
  console.error(prop);
426
446
  throw new Error(`존재하지 않는 uuid ${prop.uuid} -- in ${tableName}`);
427
447
  }
428
- const resolvedValue = (parent as Record<string, unknown>)[prop.use ?? "id"];
448
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
449
+ const resolvedValue = parent[prop.use ?? "id"];
429
450
  row[key] = resolvedValue;
430
451
 
431
452
  Naite.t("puri:ub-ref-resolved", {
@@ -442,9 +463,7 @@ export class UpsertBuilder {
442
463
 
443
464
  if (options?.cleanOrphans) {
444
465
  const cleanOrphans = options.cleanOrphans;
445
- const fkColumns = isArray(cleanOrphans)
446
- ? (cleanOrphans as ForeignKeyColumns<TTable>[])
447
- : [cleanOrphans as ForeignKeyColumns<TTable>];
466
+ const fkColumns = asArray(cleanOrphans);
448
467
 
449
468
  // 현재 register된 레코드들의 FK 값들 추출
450
469
  const fkConditions = fkColumns.map((fkCol) => {
@@ -458,6 +477,7 @@ export class UpsertBuilder {
458
477
 
459
478
  // 각 FK 컬럼에 대한 WHERE IN 조건 추가
460
479
  for (const { column, values } of fkConditions) {
480
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
461
481
  deleteQuery = deleteQuery.whereIn(column, values as Knex.Value[]);
462
482
  }
463
483
 
@@ -486,6 +506,7 @@ export class UpsertBuilder {
486
506
  returnedIds: allIds,
487
507
  });
488
508
 
509
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
489
510
  return allIds as IdType<DatabaseSchemaExtend, TTable>[];
490
511
  }
491
512
 
@@ -516,6 +537,7 @@ export class UpsertBuilder {
516
537
  const whereColumns = Array.isArray(options.where) ? options.where : [options.where ?? "id"];
517
538
  const rows = table.rows.map((_row) => {
518
539
  const { uuid: _, ...row } = _row; // uuid 제외
540
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
519
541
  return row as RowWithId<string>;
520
542
  });
521
543
 
@@ -542,10 +564,7 @@ export class UpsertBuilder {
542
564
  * - 자기 참조 없는 경우 : 모든 rows가 Level 0
543
565
  * - 자기 참조 있는 경우 : 자기 참조 관계를 위상 정렬하여 레벨별로 그룹화
544
566
  */
545
- private buildInsertLevels(
546
- rows: Record<string, unknown>[],
547
- tableName: string,
548
- ): { levels: Record<string, unknown>[][]; hasCircular: boolean } {
567
+ private buildInsertLevels(rows: UpsertRow[], tableName: string) {
549
568
  // 1. 자기 참조가 없으면 한 레벨로 처리
550
569
  const hasSelfRef = rows
551
570
  .flatMap((row) => Object.values(row))
@@ -553,24 +572,26 @@ export class UpsertBuilder {
553
572
  if (!hasSelfRef) return { levels: [rows], hasCircular: false };
554
573
 
555
574
  // 2. uuid → row 매핑 (중복 uuid 방지)
556
- const rowByUuid = new Map<string, Record<string, unknown>>();
575
+ const rowByUuid = new Map<string, UpsertRow>();
557
576
  for (const row of rows) {
577
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
558
578
  const uuid = row.uuid as string | undefined;
559
579
  if (!uuid) throw new Error(`buildInsertLevels: uuid가 없는 row -- in ${tableName}`);
560
580
  rowByUuid.set(uuid, row);
561
581
  }
562
582
 
563
583
  let pending = Array.from(rowByUuid.values());
564
- const levels: Record<string, unknown>[][] = [];
584
+ const levels: UpsertRow[][] = [];
565
585
  const inserted = new Set<string>();
566
586
 
567
587
  // 3. 레벨별 분류
568
588
  while (pending.length > 0) {
569
- const currentLevel: Record<string, unknown>[] = [];
570
- const nextPending: Record<string, unknown>[] = [];
589
+ const currentLevel: UpsertRow[] = [];
590
+ const nextPending: UpsertRow[] = [];
571
591
 
572
592
  for (const row of pending) {
573
593
  // 이 row가 참조하는 자기 참조들
594
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
574
595
  const selfRefs = Object.values(row).filter(
575
596
  (value) => isRefField(value) && value.of === tableName,
576
597
  ) as UBRef[];
@@ -596,6 +617,7 @@ export class UpsertBuilder {
596
617
  // 레벨 확정 + inserted 갱신
597
618
  levels.push(currentLevel);
598
619
  for (const row of currentLevel) {
620
+ // SAFETY: 쿼리 빌더의 제네릭 계약과 선행 검증이 이 타입을 보장합니다.
599
621
  inserted.add(row.uuid as string);
600
622
  }
601
623
 
package/src/dict/sd.ts CHANGED
@@ -16,7 +16,10 @@ type MergedDictionary = {
16
16
  ? (...args: P) => string
17
17
  : string;
18
18
  };
19
- const dictionaries: Record<string, MergedDictionary> = {
19
+ interface DictionariesByLocale {
20
+ [locale: string]: MergedDictionary;
21
+ }
22
+ const dictionaries: DictionariesByLocale = {
20
23
  ko,
21
24
  en,
22
25
  };
@@ -44,25 +47,32 @@ function getDictValue<K extends DictKey>(key: K, locale: string): SDReturnType<K
44
47
  // 1. 지정된 locale에서 조회
45
48
  const dict = dictionaries[locale];
46
49
  if (dict?.[key] !== undefined) {
47
- return dict[key] as unknown as SDReturnType<K>;
50
+ return /* SAFETY: 동기화된 사전 계약에서 문자열 브랜드만 추가한다. */ dict[
51
+ key
52
+ ] as SDReturnType<K>;
48
53
  }
49
54
 
50
55
  // 2. default locale에서 조회
51
56
  if (locale !== defaultLocale && dictionaries[defaultLocale]?.[key] !== undefined) {
52
- return dictionaries[defaultLocale][key] as unknown as SDReturnType<K>;
57
+ return /* SAFETY: 동기화된 사전 계약에서 문자열 브랜드만 추가한다. */ dictionaries[
58
+ defaultLocale
59
+ ][key] as SDReturnType<K>;
53
60
  }
54
61
 
55
62
  // 3. supported locales 순회
56
63
  for (const supportedLocale of supportedLocales) {
57
64
  if (supportedLocale !== locale && supportedLocale !== defaultLocale) {
58
65
  if (dictionaries[supportedLocale]?.[key] !== undefined) {
59
- return dictionaries[supportedLocale][key] as unknown as SDReturnType<K>;
66
+ return /* SAFETY: 동기화된 사전 계약에서 문자열 브랜드만 추가한다. */ dictionaries[
67
+ supportedLocale
68
+ ][key] as SDReturnType<K>;
60
69
  }
61
70
  }
62
71
  }
63
72
 
64
73
  // 4. 모두 실패 시 key 반환
65
- return key as unknown as SDReturnType<K>;
74
+ const missingValue: MergedDictionary[DictKey] = key;
75
+ return /* SAFETY: 누락 키 문자열에 LocalizedString 브랜드만 추가한다. */ missingValue as SDReturnType<K>;
66
76
  }
67
77
 
68
78
  /**
@@ -303,10 +303,7 @@ export class SonamuDictionary {
303
303
  /**
304
304
  * 함수 값들에서 사용되는 헬퍼 함수를 감지합니다.
305
305
  */
306
- private detectUsedHelpers(entries: DictEntry[]): {
307
- helpers: string[];
308
- usesFormat: boolean;
309
- } {
306
+ private detectUsedHelpers(entries: DictEntry[]) {
310
307
  const functionEntries = entries.filter((e) => e.isFunction);
311
308
  const helpers: string[] = [];
312
309
 
@@ -547,7 +544,7 @@ export class SonamuDictionary {
547
544
  /**
548
545
  * Project dict 파일([locale].ts)에서 딕셔너리 로드
549
546
  */
550
- loadProjectDict(locale: string): { entries: DictEntry[] } {
547
+ loadProjectDict(locale: string) {
551
548
  const dictPath = path.join(Sonamu.apiRootPath, "src", "i18n", `${locale}.ts`);
552
549
  if (!fs.existsSync(dictPath)) {
553
550
  return { entries: [] };
@@ -795,7 +792,10 @@ export class SonamuDictionary {
795
792
  }
796
793
 
797
794
  const key = rowValues.key;
798
- const source = rowValues.source as "entity" | "project";
795
+ const source =
796
+ /* SAFETY: 동기화된 사전 키와 값 계약이 이 값의 타입을 보장한다. */ rowValues.source as
797
+ | "entity"
798
+ | "project";
799
799
 
800
800
  if (!key || !source) continue;
801
801
 
package/src/dict/utils.ts CHANGED
@@ -1,12 +1,20 @@
1
+ import { isFunctionValue } from "../utils/runtime-value";
2
+
1
3
  export type PluralForms = {
2
4
  zero?: string | ((n: number) => string);
3
5
  one?: string | ((n: number) => string);
4
6
  other?: string | ((n: number) => string);
5
7
  };
6
8
 
9
+ type PluralResolver = (n: number) => string;
10
+
11
+ function isPluralResolver(form: PluralForms[keyof PluralForms]): form is PluralResolver {
12
+ return isFunctionValue(form);
13
+ }
14
+
7
15
  export function plural(n: number, forms: PluralForms): string {
8
16
  const form = (n === 0 && forms.zero) || (n === 1 && forms.one) || forms.other;
9
- return typeof form === "function" ? form(n) : (form ?? n.toString());
17
+ return isPluralResolver(form) ? form(n) : (form ?? n.toString());
10
18
  }
11
19
 
12
20
  export function createFormat(locale: string) {
@@ -30,6 +30,19 @@ export type TableSpec = {
30
30
  uniqueIndexes: EntityIndex[];
31
31
  jsonColumns: string[];
32
32
  };
33
+
34
+ function parseEntityJson(source: string) {
35
+ try {
36
+ return JSON.parse(source);
37
+ } catch (cause) {
38
+ // JSON 파서 계약 밖의 오류는 구문 오류로 정규화하고 원인을 보존합니다.
39
+ if (!(cause instanceof SyntaxError)) {
40
+ throw new SyntaxError("entity.json 파싱 중 예기치 않은 오류가 발생했습니다.", { cause });
41
+ }
42
+ throw cause;
43
+ }
44
+ }
45
+
33
46
  class EntityManagerClass {
34
47
  private entities: Map<string, Entity> = new Map();
35
48
  public modulePaths: Map<string, string> = new Map();
@@ -37,23 +50,25 @@ class EntityManagerClass {
37
50
  public isAutoloaded: boolean = false;
38
51
 
39
52
  // 경로 전달받아 모든 entity.json 파일 로드
40
- async autoload(_: boolean = false) {
53
+ async autoload(doSilent: boolean = false) {
41
54
  if (this.isAutoloaded) {
42
55
  return;
43
56
  }
44
57
  const pathPattern = path.join(Sonamu.apiRootPath, "/src/application/**/*.entity.json");
45
58
 
46
59
  for await (const file of glob(path.resolve(pathPattern))) {
47
- const json = JSON.parse((await readFile(file)).toString());
60
+ const json = parseEntityJson((await readFile(file)).toString());
48
61
 
49
62
  // entity.json 스키마 검증
50
63
  const error = this.schemaValidate(json);
51
64
  if (error) {
52
65
  const relativePath = path.relative(Sonamu.apiRootPath, file);
53
66
  const errorMessage = prettifyError(error);
54
- console.error(
55
- chalk.red(`Invalid entity.json schema: ${relativePath}\n${chalk.yellow(errorMessage)}`),
56
- );
67
+ if (!doSilent) {
68
+ console.error(
69
+ chalk.red(`Invalid entity.json schema: ${relativePath}\n${chalk.yellow(errorMessage)}`),
70
+ );
71
+ }
57
72
  }
58
73
 
59
74
  await this.register(json, { deferSearchTextJsonSourceValidation: true });
@@ -65,7 +80,7 @@ class EntityManagerClass {
65
80
  this.isAutoloaded = true;
66
81
  }
67
82
 
68
- schemaValidate(json: unknown) {
83
+ schemaValidate<Value>(json: Value) {
69
84
  const result = EntityJsonSchema.safeParse(json);
70
85
  return result.success ? null : result.error;
71
86
  }
@@ -180,7 +195,9 @@ class EntityManagerClass {
180
195
  }
181
196
 
182
197
  getByTable(table: string): Entity {
183
- const entity = Array.from(this.entities.values()).find((entity) => entity.table === table);
198
+ const entity = Array.from(this.entities.values()).find(
199
+ (candidate) => candidate.table === table,
200
+ );
184
201
  if (entity === undefined) {
185
202
  throw new Error(`존재하지 않는 Entity 요청 ${table}`);
186
203
  }
@@ -242,7 +259,7 @@ class EntityManagerClass {
242
259
  return tableSpec;
243
260
  }
244
261
 
245
- getNamesFromId(entityId: string): EntityNamesRecord {
262
+ getNamesFromId(entityId: string) {
246
263
  // entityId가 단복수 동형 단어인 경우 List 붙여서 생성
247
264
  const pluralized =
248
265
  inflection.pluralize(entityId) === entityId
@@ -258,7 +275,7 @@ class EntityManagerClass {
258
275
  capitalPlural: pluralized,
259
276
  upper: entityId.toUpperCase(),
260
277
  constant: inflection.underscore(entityId).toUpperCase(),
261
- };
278
+ } satisfies EntityNamesRecord;
262
279
  }
263
280
 
264
281
  /**
@@ -14,6 +14,7 @@ import {
14
14
  isRelationProp,
15
15
  isSubsetDefWithCone,
16
16
  } from "../types/types";
17
+ import { isStringValue } from "../utils/runtime-value";
17
18
 
18
19
  /**
19
20
  * Entity의 템플릿 cone을 생성합니다.
@@ -21,15 +22,7 @@ import {
21
22
  * LLM을 사용하지 않고 faker-mappings.ts를 활용하여 기본 cone을 생성합니다.
22
23
  * stub entity 생성 시 자동으로 호출되어 최소한의 cone 메타데이터를 제공합니다.
23
24
  */
24
- export function generateTemplateCones(
25
- entity: EntityJson,
26
- locale: "ko" | "en" | "ja" = "ko",
27
- ): {
28
- entityCone?: Cone;
29
- propCones: Record<string, Cone>;
30
- subsetCones: Record<string, Cone>;
31
- enumCones: Record<string, Cone>;
32
- } {
25
+ export function generateTemplateCones(entity: EntityJson, locale: "ko" | "en" | "ja" = "ko") {
33
26
  const mapping = fakerMappings[locale];
34
27
 
35
28
  if (!mapping) {
@@ -77,6 +70,7 @@ export function generateTemplateCones(
77
70
  };
78
71
  return acc;
79
72
  },
73
+ // SAFETY: 스키마 검증과 메타데이터 계약이 이 타입을 보장합니다.
80
74
  {} as Record<string, { note: string }>,
81
75
  ),
82
76
  };
@@ -188,6 +182,7 @@ function shouldHaveDataSource(prop: EntityProp): boolean {
188
182
 
189
183
  // OneToOne은 hasJoinColumn: true인 경우에만 dataSource 필요
190
184
  if (isOneToOneRelationProp(prop)) {
185
+ // SAFETY: 스키마 검증과 메타데이터 계약이 이 타입을 보장합니다.
191
186
  return (prop as OneToOneRelationProp).hasJoinColumn;
192
187
  }
193
188
 
@@ -199,7 +194,7 @@ function shouldHaveDataSource(prop: EntityProp): boolean {
199
194
  */
200
195
  function getSubsetScale(key: string, subset: SubsetDef, locale: "ko" | "en" | "ja"): string {
201
196
  const fields = isSubsetDefWithCone(subset) ? subset.fields : subset;
202
- const fieldNames = fields.map((f) => (typeof f === "string" ? f : f.field)).join(", ");
197
+ const fieldNames = fields.map((f) => (isStringValue(f) ? f : f.field)).join(", ");
203
198
 
204
199
  const templates = {
205
200
  ko: `${key} 서브셋. 포함된 필드: ${fieldNames}`,