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
@@ -1,12 +1,11 @@
1
1
  import assert from "assert";
2
2
  import { EventEmitter } from "events";
3
- import { unlink } from "fs/promises";
4
3
  import path from "path";
5
4
 
6
5
  import { hot } from "@sonamu-kit/hmr-hook";
7
6
  import chalk from "chalk";
8
7
  import { minimatch } from "minimatch";
9
- import { group, unique } from "radashi";
8
+ import { unique } from "radashi";
10
9
  import { type z } from "zod";
11
10
 
12
11
  import { registeredApis } from "../api/decorators";
@@ -22,20 +21,36 @@ import { type TemplateOptions } from "../types/types";
22
21
  import { mapAsync, reduceAsync } from "../utils/async-utils";
23
22
  import { centerText } from "../utils/console-util";
24
23
  import { isTest } from "../utils/controller";
25
- import { exists } from "../utils/fs-utils";
26
24
  import { type AbsolutePath } from "../utils/path-utils";
27
25
  import { runWithGracefulShutdown } from "../utils/process-utils";
26
+ import { isObjectValue } from "../utils/runtime-value";
28
27
  import { findChangedFilesUsingChecksums, renewChecksums } from "./checksum";
29
28
  import { generateTemplate, renderTemplate } from "./code-generator";
30
29
  import { createEntity, delEntity } from "./entity-operations";
31
30
  import { getChecksumPatternGroup, getChecksumPatternGroupInAbsolutePath } from "./file-patterns";
32
31
  import { type FileType } from "./file-patterns";
32
+ import { syncerFileExists, syncerFilesystem } from "./filesystem-dependencies";
33
33
  import { loadApis, loadModels, loadTypes, loadWorkflows } from "./module-loader";
34
34
  import { type LoadedApis, type LoadedModels, type LoadedTypes } from "./module-loader";
35
35
  import * as SyncerActions from "./syncer-actions";
36
36
 
37
- type DiffGroups = {
38
- [key in FileType]: AbsolutePath[];
37
+ type DiffGroupKey = FileType | "unknown";
38
+ type DiffGroups = Partial<Record<DiffGroupKey, AbsolutePath[]>>;
39
+
40
+ export interface SyncerDependencies {
41
+ actionCopySharedToTargetsIfNotExists: typeof SyncerActions.actionCopySharedToTargetsIfNotExists;
42
+ actionGenerateHttpValidators: typeof SyncerActions.actionGenerateHttpValidators;
43
+ actionGenerateSsrEntryServerIfNotExists: typeof SyncerActions.actionGenerateSsrEntryServerIfNotExists;
44
+ findChangedFilesUsingChecksums: typeof findChangedFilesUsingChecksums;
45
+ renewChecksums: typeof renewChecksums;
46
+ }
47
+
48
+ const defaultSyncerDependencies: SyncerDependencies = {
49
+ actionCopySharedToTargetsIfNotExists: SyncerActions.actionCopySharedToTargetsIfNotExists,
50
+ actionGenerateHttpValidators: SyncerActions.actionGenerateHttpValidators,
51
+ actionGenerateSsrEntryServerIfNotExists: SyncerActions.actionGenerateSsrEntryServerIfNotExists,
52
+ findChangedFilesUsingChecksums,
53
+ renewChecksums,
39
54
  };
40
55
 
41
56
  export class Syncer {
@@ -45,6 +60,8 @@ export class Syncer {
45
60
  workflows: Map<string, WorkflowMetadata[]> = new Map();
46
61
  eventEmitter: EventEmitter = new EventEmitter();
47
62
 
63
+ constructor(private readonly dependencies: SyncerDependencies = defaultSyncerDependencies) {}
64
+
48
65
  /**
49
66
  * 체크섬이 변경된 부분에 대해 싱크를 진행합니다.
50
67
  * dev 서버가 처음 떴을 때, sonamu sync 할 때 실행됩니다. 이후에는 hmrAndSync 경로를 타요.
@@ -54,12 +71,15 @@ export class Syncer {
54
71
  // 초기 부트스트랩! 얘네들은 idempotent하고 가볍기 때문에 무지성 실행해도 됩니다.
55
72
  // 얘네들은 sonamu.lock에 들어가지도 않고 따라서 HMR 경로를 타지도 않는 친구들입니다.
56
73
  // 그래서 아무 때나 그냥 돌려주면 되는데, hmrAndSync에서 매번 하는 것은 낭비이니 여기서 한 번만 합니다.
57
- await SyncerActions.actionCopySharedToTargetsIfNotExists();
58
- await SyncerActions.actionGenerateSsrEntryServerIfNotExists();
74
+ await this.dependencies.actionCopySharedToTargetsIfNotExists();
75
+ await this.dependencies.actionGenerateSsrEntryServerIfNotExists();
59
76
 
60
77
  // 바뀐 것이 없으면 그냥 넘어가요.
61
- const changedFiles = await findChangedFilesUsingChecksums();
78
+ const changedFiles = await this.dependencies.findChangedFilesUsingChecksums();
62
79
  if (changedFiles.length === 0) {
80
+ if (await this.reconcileHttpValidatorRegistry()) {
81
+ await this.dependencies.renewChecksums();
82
+ }
63
83
  console.log(chalk.black.bgGreen(centerText("All files are synced!")));
64
84
  return;
65
85
  }
@@ -71,14 +91,31 @@ export class Syncer {
71
91
  async () => {
72
92
  // 얘가 싱크 작업 수행하는 본체입니다.
73
93
  await this.doSyncActions(changedFiles);
94
+ await this.reconcileHttpValidatorRegistry();
74
95
 
75
96
  // 싱크 액션이 끝나면 항상 체크섬을 다시 갱신합니다.
76
- await renewChecksums();
97
+ await this.dependencies.renewChecksums();
77
98
  },
78
99
  { whenThisHappens: "SIGUSR2", waitForUpTo: 20000 },
79
100
  );
80
101
  }
81
102
 
103
+ private async reconcileHttpValidatorRegistry(): Promise<boolean> {
104
+ const registryPath = path.join(
105
+ Sonamu.apiRootPath,
106
+ "src/application/sonamu.validators.generated.ts",
107
+ );
108
+ const policy = Sonamu.config.validation?.zodCompiler;
109
+ const isAot = isObjectValue(policy) && policy !== null && policy.api === "aot";
110
+ if (isAot === (await syncerFileExists(registryPath))) {
111
+ return false;
112
+ }
113
+
114
+ // 변경 목록이 registry 삭제를 놓쳐도 checksum 갱신 전에 정책과 산출물을 다시 맞춥니다.
115
+ await this.dependencies.actionGenerateHttpValidators();
116
+ return true;
117
+ }
118
+
82
119
  /**
83
120
  * 강제 풀-싱크: lock을 무시하고 처음부터 다시 싱크합니다.
84
121
  *
@@ -88,8 +125,8 @@ export class Syncer {
88
125
  */
89
126
  async forceSync(): Promise<void> {
90
127
  const lockPath = path.join(Sonamu.apiRootPath, "sonamu.lock");
91
- if (await exists(lockPath)) {
92
- await unlink(lockPath);
128
+ if (await syncerFileExists(lockPath)) {
129
+ await syncerFilesystem.unlink(lockPath);
93
130
  }
94
131
  await this.sync();
95
132
  }
@@ -137,6 +174,7 @@ export class Syncer {
137
174
  await this.autoloadApis();
138
175
  await this.autoloadWorkflows();
139
176
  await this.autoloadSsrRoutes();
177
+ await Sonamu.refreshHttpValidators();
140
178
 
141
179
  this.eventEmitter.emit("onHMRCompleted");
142
180
  }
@@ -182,7 +220,11 @@ export class Syncer {
182
220
  // 그러니 안심하고 invalidate 해도 됩니다.
183
221
  // 테스트 환경에서는 hot.invalidateFile시 초기 에러가 발생하기 때문에 invalidate 하지 않습니다.
184
222
  if (!isTest()) {
185
- const invalidatedPaths = (await hot.invalidateFile(diffFilePath, event)) as AbsolutePath[];
223
+ const invalidatedPaths =
224
+ /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ (await hot.invalidateFile(
225
+ diffFilePath,
226
+ event,
227
+ )) as AbsolutePath[];
186
228
 
187
229
  if (invalidatedPaths.length > 0) {
188
230
  console.log(chalk.bold(`🔄 Invalidated:`));
@@ -271,7 +313,7 @@ export class Syncer {
271
313
  clearSSRRoutes();
272
314
 
273
315
  // ssr 폴더 없으면 스킵
274
- if (!(await exists(ssrConfigPath))) {
316
+ if (!(await syncerFileExists(ssrConfigPath))) {
275
317
  return;
276
318
  }
277
319
 
@@ -302,7 +344,10 @@ export class Syncer {
302
344
  */
303
345
  async doSyncActions(diffFilePaths: AbsolutePath[]): Promise<{ diffTypes: FileType[] }> {
304
346
  const diffGroups = this.calculateDiffGroups(diffFilePaths);
305
- const diffTypes = Object.keys(diffGroups) as FileType[];
347
+ const diffTypes =
348
+ /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ Object.keys(
349
+ diffGroups,
350
+ ) as FileType[];
306
351
 
307
352
  // 여기는 별로 중요한 파트는 아닙니다.
308
353
  // 아래의 if 전개를 깔끔하게 하려고 만든 DSL 같은 거라서, 무시하셔도 됩니다.
@@ -324,11 +369,27 @@ export class Syncer {
324
369
  }
325
370
 
326
371
  if (changeMatches("config")) {
327
- await this.handleConfigChanges(diffGroups);
372
+ await this.handleConfigChanges();
328
373
  }
329
374
 
330
375
  if (changeMatches("i18n", "entity" /*레이블*/, "config" /*defaultLocale등*/)) {
331
- await this.handleSonamuDictionaryRelatedChanges(diffGroups);
376
+ await this.handleSonamuDictionaryRelatedChanges();
377
+ }
378
+
379
+ const metadataChanged = diffTypes.some((type) =>
380
+ ["entity", "types", "model", "frame", "config"].includes(type),
381
+ );
382
+ if (changeMatches("httpValidatorsGenerated") && !metadataChanged) {
383
+ // registry 자체 drift는 최신 in-memory metadata로 즉시 덮어써 lock 갱신 전에 정합성을 복구합니다.
384
+ await this.dependencies.actionGenerateHttpValidators();
385
+ }
386
+
387
+ if (metadataChanged) {
388
+ // 모든 생성/복사 액션 뒤 최신 metadata를 다시 읽어 registry를 한 번만 확정합니다.
389
+ await this.autoloadTypes();
390
+ await this.autoloadModels();
391
+ await this.autoloadApis();
392
+ await this.dependencies.actionGenerateHttpValidators();
332
393
  }
333
394
 
334
395
  if (nothingMatches()) {
@@ -343,22 +404,26 @@ export class Syncer {
343
404
  };
344
405
  }
345
406
 
346
- calculateDiffGroups(diffFiles: AbsolutePath[]): DiffGroups {
407
+ calculateDiffGroups(diffFiles: AbsolutePath[]) {
347
408
  const patternGroup = getChecksumPatternGroup();
348
- const fileTypes = Object.keys(patternGroup) as FileType[];
349
-
350
- return group(diffFiles, (filePath) => {
351
- // 절대 경로 → appRoot 기준 상대 경로 (예: "api/src/...", "web/src/...")
409
+ const fileTypes =
410
+ /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ Object.keys(
411
+ patternGroup,
412
+ ) as FileType[];
413
+
414
+ const diffGroups: DiffGroups = {};
415
+ for (const filePath of diffFiles) {
416
+ // 절대 경로를 appRoot 기준 상대 경로로 바꿔 체크섬 패턴과 비교한다.
352
417
  const relativePath = path.relative(Sonamu.appRootPath, filePath);
353
- if (relativePath.startsWith("..")) return "unknown";
354
-
355
- for (const fileType of fileTypes) {
356
- if (minimatch(relativePath, patternGroup[fileType])) {
357
- return fileType;
358
- }
359
- }
360
- return "unknown";
361
- }) as unknown as DiffGroups;
418
+ const fileType = fileTypes.find((candidate) =>
419
+ minimatch(relativePath, patternGroup[candidate]),
420
+ );
421
+ const groupKey: DiffGroupKey = relativePath.startsWith("..")
422
+ ? "unknown"
423
+ : (fileType ?? "unknown");
424
+ (diffGroups[groupKey] ??= []).push(filePath);
425
+ }
426
+ return diffGroups;
362
427
  }
363
428
 
364
429
  private changeMatcher(diffTypes: FileType[], diffGroups: DiffGroups) {
@@ -404,12 +469,13 @@ export class Syncer {
404
469
  const entity = EntityManager.get(entityId);
405
470
 
406
471
  // 프로젝트에 생성되어야 하는 .ts 파일의 경로입니다.
407
- const typeFilePath = path.join(
408
- Sonamu.apiRootPath,
409
- `src/application/${entity.names.fs}/${entity.names.fs}.types.ts`,
410
- ) as AbsolutePath;
472
+ const typeFilePath =
473
+ /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ path.join(
474
+ Sonamu.apiRootPath,
475
+ `src/application/${entity.names.fs}/${entity.names.fs}.types.ts`,
476
+ ) as AbsolutePath;
411
477
 
412
- if (entity.parentId === undefined && !(await exists(typeFilePath))) {
478
+ if (entity.parentId === undefined && !(await syncerFileExists(typeFilePath))) {
413
479
  // *.types.ts가 만들어집니다.
414
480
  const types = await SyncerActions.actionGenerateInitialTypes(entityId);
415
481
 
@@ -464,11 +530,15 @@ export class Syncer {
464
530
  await SyncerActions.actionSyncFilesToTargets(tsPaths);
465
531
  }
466
532
 
467
- async handleConfigChanges(_: DiffGroups): Promise<void> {
533
+ async handleConfigChanges(): Promise<void> {
534
+ if (process.env.HOT === "yes") {
535
+ const { loadConfig } = await import("../api/config");
536
+ Sonamu.config = await loadConfig(Sonamu.apiRootPath);
537
+ }
468
538
  await SyncerActions.actionSyncConfig();
469
539
  }
470
540
 
471
- async handleSonamuDictionaryRelatedChanges(_: DiffGroups): Promise<void> {
541
+ async handleSonamuDictionaryRelatedChanges(): Promise<void> {
472
542
  await SyncerActions.actionSyncSonamuDictionary();
473
543
  }
474
544
 
@@ -508,7 +578,7 @@ export class Syncer {
508
578
  return {
509
579
  subPath,
510
580
  fullPath,
511
- isExists: await exists(fullPath),
581
+ isExists: await syncerFileExists(fullPath),
512
582
  };
513
583
  }
514
584
 
@@ -535,7 +605,7 @@ export class Syncer {
535
605
  if (key.startsWith("view_enums")) {
536
606
  await mapAsync(enumsKeys, async (componentId) => {
537
607
  const { target, path: p } = tpl.getTargetAndPath(names, componentId);
538
- result[`${key}__${componentId}`] = await exists(
608
+ result[`${key}__${componentId}`] = await syncerFileExists(
539
609
  path.join(Sonamu.appRootPath, target, p),
540
610
  );
541
611
  });
@@ -546,17 +616,20 @@ export class Syncer {
546
616
  const { targets } = Sonamu.config.sync;
547
617
  if (target.includes(":target")) {
548
618
  await mapAsync(targets, async (t) => {
549
- result[`${key}__${t}`] = await exists(
619
+ result[`${key}__${t}`] = await syncerFileExists(
550
620
  path.join(Sonamu.appRootPath, target.replace(":target", t), p),
551
621
  );
552
622
  });
553
623
  } else {
554
- result[key] = await exists(path.join(Sonamu.appRootPath, target, p));
624
+ result[key] = await syncerFileExists(path.join(Sonamu.appRootPath, target, p));
555
625
  }
556
626
 
557
627
  return result;
558
628
  },
559
- {} as Record<`${TemplateKey}${string}`, boolean>,
629
+ /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ {} as Record<
630
+ `${TemplateKey}${string}`,
631
+ boolean
632
+ >,
560
633
  );
561
634
  }
562
635
 
@@ -599,6 +672,6 @@ export class Syncer {
599
672
  * 하위호환용 프록시 메소드입니다.
600
673
  */
601
674
  async renewChecksums(): Promise<void> {
602
- return await renewChecksums();
675
+ return await this.dependencies.renewChecksums();
603
676
  }
604
677
  }
@@ -3,7 +3,7 @@ import { type Stats } from "node:fs";
3
3
  import path from "path";
4
4
 
5
5
  import chalk from "chalk";
6
- import chokidar, { type FSWatcher } from "chokidar";
6
+ import { type FSWatcher, watch } from "chokidar";
7
7
  import { minimatch } from "minimatch";
8
8
 
9
9
  import { Sonamu } from "../api";
@@ -22,7 +22,7 @@ export async function setupWatcher(
22
22
  // api 본인뿐 아니라 sync target들의 src도 봅니다.
23
23
  // target 산출물(sonamu.generated, services.generated, i18n copy 등)이 외부에서
24
24
  // 변경되는 경우를 drift로 잡아 워닝을 띄우기 위함입니다.
25
- const watcher = chokidar.watch(apiAndTargetsSrcPaths(), {
25
+ const watcher = watch(apiAndTargetsSrcPaths(), {
26
26
  ignored: ignoreIfExtensionIsNotOneOf(".ts", ".json", ".http"),
27
27
  persistent: true,
28
28
  ignoreInitial: true,
@@ -49,7 +49,8 @@ export async function setupWatcher(
49
49
  });
50
50
 
51
51
  watcher.on("all", (event: string, filePath: string) => {
52
- const absolutePath = filePath as AbsolutePath;
52
+ const absolutePath =
53
+ /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ filePath as AbsolutePath;
53
54
  assert(
54
55
  absolutePath.startsWith(Sonamu.appRootPath),
55
56
  "File path is not within the app root path",
@@ -92,7 +93,10 @@ function apiAndTargetsSrcPaths() {
92
93
  * 따라서 "이 확장자만 허용"을 표현하려면 *다른 확장자에 대해 true*를 반환해야 합니다.
93
94
  */
94
95
  function ignoreIfExtensionIsNotOneOf(...allowedExtensions: `.${string}`[]) {
95
- const isAllowed = (ext: string) => (allowedExtensions as string[]).includes(ext);
96
+ const isAllowed = (ext: string) =>
97
+ /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ (
98
+ allowedExtensions as string[]
99
+ ).includes(ext);
96
100
 
97
101
  return (p: string, stats?: Stats) => !!stats?.isFile() && !isAllowed(path.extname(p));
98
102
  }
@@ -13,18 +13,18 @@ import { type Executable } from "../types/types";
13
13
  import { type WorkflowFunction } from "./workflow-manager";
14
14
 
15
15
  // 워크플로우의 메타데이터 객체
16
- export interface WorkflowMetadata {
16
+ export interface WorkflowMetadata<RawInput = unknown, Input = unknown, Output = unknown> {
17
17
  type: "workflow";
18
18
  id: string;
19
19
  name: string;
20
20
  version: string | null;
21
- schema: StandardSchemaV1<unknown, unknown> | undefined;
21
+ schema: StandardSchemaV1<RawInput, Input> | undefined;
22
22
  schedules: {
23
23
  name: string;
24
24
  expression: string;
25
- input: Executable<SchemaInput<unknown, unknown> | undefined>;
25
+ input: Executable<RawInput | undefined>;
26
26
  }[];
27
- fn: WorkflowFunction<unknown, unknown>;
27
+ fn: WorkflowFunction<Input, Output>;
28
28
  retryPolicy?: RetryPolicy;
29
29
  }
30
30
 
@@ -50,22 +50,30 @@ export type DefineWorkflowOptions<
50
50
  // 이것들은 syncer에서 한번에 load한 다음, WorkflowManager에서 synchronize를 통해 등록됨.
51
51
  export function workflow<Input, Output, TSchema extends StandardSchemaV1 | undefined = undefined>(
52
52
  options: DefineWorkflowOptions<Input, Output, TSchema>,
53
- ): (fn: WorkflowFunction<SchemaOutput<TSchema, Input>, Output>) => WorkflowMetadata;
53
+ ): (
54
+ fn: WorkflowFunction<SchemaOutput<TSchema, Input>, Output>,
55
+ ) => WorkflowMetadata<SchemaInput<TSchema, Input>, SchemaOutput<TSchema, Input>, Output>;
54
56
  export function workflow<Input, Output, TSchema extends StandardSchemaV1 | undefined = undefined>(
55
57
  options: DefineWorkflowOptions<Input, Output, TSchema>,
56
58
  fn: WorkflowFunction<SchemaOutput<TSchema, Input>, Output>,
57
- ): WorkflowMetadata;
59
+ ): WorkflowMetadata<SchemaInput<TSchema, Input>, SchemaOutput<TSchema, Input>, Output>;
58
60
  export function workflow<Input, Output, TSchema extends StandardSchemaV1 | undefined = undefined>(
59
61
  options: DefineWorkflowOptions<Input, Output, TSchema>,
60
62
  fn?: WorkflowFunction<SchemaOutput<TSchema, Input>, Output>,
61
63
  ):
62
- | WorkflowMetadata
63
- | ((fn: WorkflowFunction<SchemaOutput<TSchema, Input>, Output>) => WorkflowMetadata) {
64
- const decorated = (fn: WorkflowFunction<SchemaOutput<TSchema, Input>, Output>) => {
64
+ | WorkflowMetadata<SchemaInput<TSchema, Input>, SchemaOutput<TSchema, Input>, Output>
65
+ | ((
66
+ fn: WorkflowFunction<SchemaOutput<TSchema, Input>, Output>,
67
+ ) => WorkflowMetadata<SchemaInput<TSchema, Input>, SchemaOutput<TSchema, Input>, Output>) {
68
+ const decorated = (workflowFunction: WorkflowFunction<SchemaOutput<TSchema, Input>, Output>) => {
65
69
  const id = randomUUID();
66
- const workflowName = options.name ?? inflection.underscore(fn.name);
70
+ const workflowName = options.name ?? inflection.underscore(workflowFunction.name);
67
71
 
68
- const metadata: WorkflowMetadata = {
72
+ const metadata: WorkflowMetadata<
73
+ SchemaInput<TSchema, Input>,
74
+ SchemaOutput<TSchema, Input>,
75
+ Output
76
+ > = {
69
77
  type: "workflow" as const,
70
78
  id,
71
79
  name: workflowName,
@@ -78,7 +86,7 @@ export function workflow<Input, Output, TSchema extends StandardSchemaV1 | undef
78
86
  input: schedule.input,
79
87
  };
80
88
  }),
81
- fn: fn as WorkflowFunction<unknown, unknown>,
89
+ fn: workflowFunction,
82
90
  retryPolicy: options.retryPolicy,
83
91
  };
84
92
 
@@ -6,6 +6,10 @@ export type RunnableStep<TArgs extends unknown[], TResult> = {
6
6
  run: StepFunction<TArgs, Promise<TResult>>;
7
7
  };
8
8
 
9
+ interface StepConfig {
10
+ name: string;
11
+ }
12
+
9
13
  export type MethodNames<T, TKey extends keyof T> = T[TKey] extends (
10
14
  ...args: infer _TArgs
11
15
  ) => infer _TResult
@@ -14,7 +18,7 @@ export type MethodNames<T, TKey extends keyof T> = T[TKey] extends (
14
18
 
15
19
  export type MethodArguments<T, TKey extends keyof T> = T[TKey] extends (
16
20
  ...args: infer TArgs
17
- ) => unknown
21
+ ) => infer _TResult
18
22
  ? TArgs
19
23
  : never;
20
24
 
@@ -37,7 +41,7 @@ export class StepWrapper {
37
41
  TKey extends keyof T,
38
42
  TArgs extends MethodArguments<T, TKey>,
39
43
  TResult extends MethodReturnType<T, TKey>,
40
- >(config: { name: string }, object: T, name: MethodNames<T, TKey>): RunnableStep<TArgs, TResult>;
44
+ >(config: StepConfig, object: T, name: MethodNames<T, TKey>): RunnableStep<TArgs, TResult>;
41
45
  get<
42
46
  T,
43
47
  TKey extends keyof T,
@@ -50,20 +54,26 @@ export class StepWrapper {
50
54
  TArgs extends MethodArguments<T, TKey>,
51
55
  TResult extends MethodReturnType<T, TKey>,
52
56
  >(
53
- ...args: [{ name: string }, T, MethodNames<T, TKey>] | [T, MethodNames<T, TKey>]
57
+ ...definitionArgs: [StepConfig, T, MethodNames<T, TKey>] | [T, MethodNames<T, TKey>]
54
58
  ): RunnableStep<TArgs, TResult> {
55
- let config: { name: string };
59
+ let config: StepConfig;
56
60
  let fn: StepFunction<TArgs, Exclude<TResult, never>>;
57
61
 
58
- if (args.length === 2) {
59
- const [rawObject, methodName] = args;
60
- const method = rawObject[methodName] as CallableFunction;
62
+ if (definitionArgs.length === 2) {
63
+ const [rawObject, methodName] = definitionArgs;
64
+ const method =
65
+ /* SAFETY: 작업 데코레이터와 워크플로 정의가 이 값의 타입을 보장한다. */ rawObject[
66
+ methodName
67
+ ] as CallableFunction;
61
68
  config = { name: inflection.underscore(methodName.toString()) };
62
69
 
63
70
  fn = (...args: TArgs) => method.bind(rawObject)(...args);
64
71
  } else {
65
- const [rawConfig, rawObject, name] = args;
66
- const method = rawObject[name] as CallableFunction;
72
+ const [rawConfig, rawObject, name] = definitionArgs;
73
+ const method =
74
+ /* SAFETY: 작업 데코레이터와 워크플로 정의가 이 값의 타입을 보장한다. */ rawObject[
75
+ name
76
+ ] as CallableFunction;
67
77
 
68
78
  config = { name: rawConfig.name ?? inflection.underscore(name.toString()) };
69
79
  fn = (...args: TArgs) => method.bind(rawObject)(...args);
@@ -25,6 +25,7 @@ import { convertDomainToCategory } from "../logger/category";
25
25
  import { Naite } from "../naite/naite";
26
26
  import { createMockSSEFactory } from "../stream/sse";
27
27
  import { type Executable } from "../types/types";
28
+ import { isFunctionValue } from "../utils/runtime-value";
28
29
  import { type WorkflowMetadata } from "./decorator";
29
30
  import { StepWrapper } from "./step-wrapper";
30
31
 
@@ -126,7 +127,7 @@ export class WorkflowManager {
126
127
  await Promise.allSettled(
127
128
  Array.from(this.#workflowsMap.entries())
128
129
  .filter(([key]) => !workflowMap.has(key))
129
- .flatMap(([_, workflows]) =>
130
+ .flatMap(([, workflows]) =>
130
131
  workflows.map((workflow) => {
131
132
  return Promise.allSettled([
132
133
  ...workflow.schedules.map((schedule) => this.unscheduleTask(schedule.name)),
@@ -140,7 +141,7 @@ export class WorkflowManager {
140
141
  await Promise.allSettled(
141
142
  Array.from(workflowMap.entries())
142
143
  .filter(([key]) => !this.#workflowsMap.has(key))
143
- .flatMap(([_, workflows]) =>
144
+ .flatMap(([, workflows]) =>
144
145
  workflows.map((workflow) => {
145
146
  this.registerWorkflow({
146
147
  id: workflow.id,
@@ -167,7 +168,7 @@ export class WorkflowManager {
167
168
  assert(previousWorkflows, "previous workflows not found");
168
169
  return [key, [previousWorkflows, newWorkflows]];
169
170
  })
170
- .map(async ([_, [previousWorkflows, newWorkflows]]) => {
171
+ .map(async ([, [previousWorkflows, newWorkflows]]) => {
171
172
  // 기존 것들을 삭제부터 해야함.
172
173
  await Promise.allSettled(
173
174
  previousWorkflows
@@ -237,7 +238,7 @@ export class WorkflowManager {
237
238
  { name, version }: Pick<WorkflowMetadata, "name" | "version">,
238
239
  { input }: WorkflowMetadata["schedules"][number],
239
240
  ) => {
240
- const inputData = await (typeof input === "function"
241
+ const inputData = await (isFunctionValue(input)
241
242
  ? Promise.resolve(input())
242
243
  : Promise.resolve(input));
243
244
 
@@ -287,17 +288,22 @@ export class WorkflowManager {
287
288
  version: string | null;
288
289
  }>,
289
290
  ) => {
290
- const baseContext = {
291
+ const baseContext: Context = {
291
292
  transport: "http" as const,
292
- request: null,
293
- reply: null,
293
+ // 워크플로우에는 HTTP 요청이 없으므로 잘못된 접근을 즉시 드러냅니다.
294
+ get request(): Context["request"] {
295
+ throw new Error("HTTP request is unavailable in workflow context");
296
+ },
297
+ get reply(): Context["reply"] {
298
+ throw new Error("HTTP reply is unavailable in workflow context");
299
+ },
294
300
  headers: {},
295
- createSSE: (schema: ZodObject) => createMockSSEFactory(schema),
301
+ createSSE: <T extends ZodObject>(schema: T) => createMockSSEFactory(schema),
296
302
  naiteStore: Naite.createStore(),
297
303
  locale: "",
298
304
  user: null,
299
305
  session: null,
300
- } as unknown as Context;
306
+ };
301
307
 
302
308
  const contextProvider = Sonamu.config.tasks?.contextProvider;
303
309
  const context: Context = contextProvider