sonamu 0.6.0 → 0.7.1

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 (406) hide show
  1. package/.swcrc.project-default +18 -0
  2. package/bin/cli.js +24 -0
  3. package/dist/ai/agents/agent.d.ts +11 -0
  4. package/dist/ai/agents/agent.d.ts.map +1 -0
  5. package/dist/ai/agents/agent.js +65 -0
  6. package/dist/ai/agents/index.d.ts +3 -0
  7. package/dist/ai/agents/index.d.ts.map +1 -0
  8. package/dist/ai/agents/index.js +4 -0
  9. package/dist/ai/agents/types.d.ts +43 -0
  10. package/dist/ai/agents/types.d.ts.map +1 -0
  11. package/dist/ai/agents/types.js +3 -0
  12. package/dist/ai/index.d.ts +2 -0
  13. package/dist/ai/index.d.ts.map +1 -0
  14. package/dist/ai/index.js +3 -0
  15. package/dist/ai/providers/rtzr/api.d.ts +22 -0
  16. package/dist/ai/providers/rtzr/api.d.ts.map +1 -0
  17. package/dist/ai/providers/rtzr/api.js +28 -0
  18. package/dist/ai/providers/rtzr/error.d.ts +18 -0
  19. package/dist/ai/providers/rtzr/error.d.ts.map +1 -0
  20. package/dist/ai/providers/rtzr/error.js +29 -0
  21. package/dist/ai/providers/rtzr/index.d.ts +5 -0
  22. package/dist/ai/providers/rtzr/index.d.ts.map +1 -0
  23. package/dist/ai/providers/rtzr/index.js +6 -0
  24. package/dist/ai/providers/rtzr/model.d.ts +52 -0
  25. package/dist/ai/providers/rtzr/model.d.ts.map +1 -0
  26. package/dist/ai/providers/rtzr/model.js +137 -0
  27. package/dist/ai/providers/rtzr/options.d.ts +7 -0
  28. package/dist/ai/providers/rtzr/options.d.ts.map +1 -0
  29. package/dist/ai/providers/rtzr/options.js +47 -0
  30. package/dist/ai/providers/rtzr/provider.d.ts +18 -0
  31. package/dist/ai/providers/rtzr/provider.d.ts.map +1 -0
  32. package/dist/ai/providers/rtzr/provider.js +54 -0
  33. package/dist/ai/providers/rtzr/utils.d.ts +19 -0
  34. package/dist/ai/providers/rtzr/utils.d.ts.map +1 -0
  35. package/dist/ai/providers/rtzr/utils.js +88 -0
  36. package/dist/api/base-frame.d.ts +2 -2
  37. package/dist/api/base-frame.d.ts.map +1 -1
  38. package/dist/api/base-frame.js +2 -1
  39. package/dist/api/caster.d.ts.map +1 -1
  40. package/dist/api/caster.js +6 -1
  41. package/dist/api/code-converters.d.ts +58 -14
  42. package/dist/api/code-converters.d.ts.map +1 -1
  43. package/dist/api/code-converters.js +178 -409
  44. package/dist/api/config.d.ts +27 -13
  45. package/dist/api/config.d.ts.map +1 -1
  46. package/dist/api/config.js +19 -26
  47. package/dist/api/context.d.ts +4 -3
  48. package/dist/api/context.d.ts.map +1 -1
  49. package/dist/api/context.js +1 -1
  50. package/dist/api/decorators.d.ts +20 -6
  51. package/dist/api/decorators.d.ts.map +1 -1
  52. package/dist/api/decorators.js +111 -18
  53. package/dist/api/index.d.ts +2 -2
  54. package/dist/api/index.d.ts.map +1 -1
  55. package/dist/api/index.js +3 -3
  56. package/dist/api/sonamu.d.ts +7 -7
  57. package/dist/api/sonamu.d.ts.map +1 -1
  58. package/dist/api/sonamu.js +83 -51
  59. package/dist/api/validator.d.ts +6 -0
  60. package/dist/api/validator.d.ts.map +1 -0
  61. package/dist/api/validator.js +81 -0
  62. package/dist/bin/build-config.d.ts +5 -1
  63. package/dist/bin/build-config.d.ts.map +1 -1
  64. package/dist/bin/build-config.js +5 -2
  65. package/dist/bin/cli.js +165 -64
  66. package/dist/bin/loader-register.d.ts +2 -0
  67. package/dist/bin/loader-register.d.ts.map +1 -0
  68. package/dist/bin/loader-register.js +34 -0
  69. package/dist/database/_batch_update.d.ts +5 -3
  70. package/dist/database/_batch_update.d.ts.map +1 -1
  71. package/dist/database/_batch_update.js +30 -13
  72. package/dist/database/base-model.d.ts +96 -10
  73. package/dist/database/base-model.d.ts.map +1 -1
  74. package/dist/database/base-model.js +232 -89
  75. package/dist/database/base-model.types.d.ts +93 -0
  76. package/dist/database/base-model.types.d.ts.map +1 -0
  77. package/dist/database/base-model.types.js +10 -0
  78. package/dist/database/code-generator.d.ts +1 -1
  79. package/dist/database/code-generator.d.ts.map +1 -1
  80. package/dist/database/code-generator.js +11 -10
  81. package/dist/database/db.d.ts +5 -6
  82. package/dist/database/db.d.ts.map +1 -1
  83. package/dist/database/db.js +22 -25
  84. package/dist/database/puri-subset.test-d.js +81 -0
  85. package/dist/database/puri-subset.types.d.ts +123 -0
  86. package/dist/database/puri-subset.types.d.ts.map +1 -0
  87. package/dist/database/puri-subset.types.js +16 -0
  88. package/dist/database/puri-wrapper.d.ts +13 -11
  89. package/dist/database/puri-wrapper.d.ts.map +1 -1
  90. package/dist/database/puri-wrapper.js +2 -2
  91. package/dist/database/puri.d.ts +25 -14
  92. package/dist/database/puri.d.ts.map +1 -1
  93. package/dist/database/puri.js +83 -21
  94. package/dist/database/puri.types.d.ts +21 -7
  95. package/dist/database/puri.types.d.ts.map +1 -1
  96. package/dist/database/puri.types.js +4 -1
  97. package/dist/database/transaction-context.d.ts +1 -1
  98. package/dist/database/transaction-context.d.ts.map +1 -1
  99. package/dist/database/transaction-context.js +1 -1
  100. package/dist/database/upsert-builder.d.ts +9 -3
  101. package/dist/database/upsert-builder.d.ts.map +1 -1
  102. package/dist/database/upsert-builder.js +227 -78
  103. package/dist/entity/entity-manager.d.ts +165 -2
  104. package/dist/entity/entity-manager.d.ts.map +1 -1
  105. package/dist/entity/entity-manager.js +26 -10
  106. package/dist/entity/entity.d.ts +5 -3
  107. package/dist/entity/entity.d.ts.map +1 -1
  108. package/dist/entity/entity.js +153 -54
  109. package/dist/exceptions/error-handler.d.ts +1 -1
  110. package/dist/exceptions/error-handler.d.ts.map +1 -1
  111. package/dist/exceptions/error-handler.js +1 -1
  112. package/dist/exceptions/so-exceptions.d.ts +1 -1
  113. package/dist/exceptions/so-exceptions.d.ts.map +1 -1
  114. package/dist/exceptions/so-exceptions.js +1 -1
  115. package/dist/file-storage/driver.d.ts +1 -1
  116. package/dist/file-storage/driver.d.ts.map +1 -1
  117. package/dist/file-storage/driver.js +1 -1
  118. package/dist/file-storage/file-storage.js +2 -2
  119. package/dist/index.d.ts +18 -11
  120. package/dist/index.d.ts.map +1 -1
  121. package/dist/index.js +19 -13
  122. package/dist/migration/code-generation.d.ts +1 -1
  123. package/dist/migration/code-generation.d.ts.map +1 -1
  124. package/dist/migration/code-generation.js +123 -67
  125. package/dist/migration/migration-set.d.ts +2 -10
  126. package/dist/migration/migration-set.d.ts.map +1 -1
  127. package/dist/migration/migration-set.js +67 -218
  128. package/dist/migration/migrator.d.ts +24 -73
  129. package/dist/migration/migrator.d.ts.map +1 -1
  130. package/dist/migration/migrator.js +121 -301
  131. package/dist/migration/postgresql-schema-reader.d.ts +51 -0
  132. package/dist/migration/postgresql-schema-reader.d.ts.map +1 -0
  133. package/dist/migration/postgresql-schema-reader.js +245 -0
  134. package/dist/migration/types.d.ts +6 -38
  135. package/dist/migration/types.d.ts.map +1 -1
  136. package/dist/migration/types.js +1 -1
  137. package/dist/naite/messaging-types.d.ts +43 -0
  138. package/dist/naite/messaging-types.d.ts.map +1 -0
  139. package/dist/naite/messaging-types.js +7 -0
  140. package/dist/naite/naite-reporter.d.ts +41 -0
  141. package/dist/naite/naite-reporter.d.ts.map +1 -0
  142. package/dist/naite/naite-reporter.js +102 -0
  143. package/dist/naite/naite.d.ts +91 -8
  144. package/dist/naite/naite.d.ts.map +1 -1
  145. package/dist/naite/naite.js +285 -41
  146. package/dist/stream/sse.d.ts +2 -2
  147. package/dist/stream/sse.d.ts.map +1 -1
  148. package/dist/stream/sse.js +1 -1
  149. package/dist/syncer/api-parser.d.ts +3 -13
  150. package/dist/syncer/api-parser.d.ts.map +1 -1
  151. package/dist/syncer/api-parser.js +67 -56
  152. package/dist/syncer/checksum.d.ts +2 -2
  153. package/dist/syncer/checksum.d.ts.map +1 -1
  154. package/dist/syncer/checksum.js +11 -11
  155. package/dist/syncer/code-generator.d.ts +3 -3
  156. package/dist/syncer/code-generator.d.ts.map +1 -1
  157. package/dist/syncer/code-generator.js +37 -17
  158. package/dist/syncer/entity-operations.d.ts +2 -2
  159. package/dist/syncer/entity-operations.d.ts.map +1 -1
  160. package/dist/syncer/entity-operations.js +9 -8
  161. package/dist/syncer/file-patterns.d.ts +1 -1
  162. package/dist/syncer/file-patterns.d.ts.map +1 -1
  163. package/dist/syncer/file-patterns.js +1 -1
  164. package/dist/syncer/index.d.ts +4 -4
  165. package/dist/syncer/index.d.ts.map +1 -1
  166. package/dist/syncer/index.js +5 -5
  167. package/dist/syncer/module-loader.d.ts +4 -4
  168. package/dist/syncer/module-loader.d.ts.map +1 -1
  169. package/dist/syncer/module-loader.js +17 -12
  170. package/dist/syncer/syncer.d.ts +31 -24
  171. package/dist/syncer/syncer.d.ts.map +1 -1
  172. package/dist/syncer/syncer.js +92 -45
  173. package/dist/template/entity-converter.d.ts +1 -1
  174. package/dist/template/entity-converter.d.ts.map +1 -1
  175. package/dist/template/entity-converter.js +15 -8
  176. package/dist/template/helpers.d.ts +2 -2
  177. package/dist/template/helpers.d.ts.map +1 -1
  178. package/dist/template/helpers.js +3 -3
  179. package/dist/template/implementations/entity.template.d.ts +2 -2
  180. package/dist/template/implementations/entity.template.d.ts.map +1 -1
  181. package/dist/template/implementations/entity.template.js +4 -5
  182. package/dist/template/implementations/generated.template.d.ts +2 -3
  183. package/dist/template/implementations/generated.template.d.ts.map +1 -1
  184. package/dist/template/implementations/generated.template.js +46 -29
  185. package/dist/template/implementations/generated_http.template.d.ts +2 -3
  186. package/dist/template/implementations/generated_http.template.d.ts.map +1 -1
  187. package/dist/template/implementations/generated_http.template.js +9 -9
  188. package/dist/template/implementations/generated_sso.template.d.ts +3 -4
  189. package/dist/template/implementations/generated_sso.template.d.ts.map +1 -1
  190. package/dist/template/implementations/generated_sso.template.js +54 -25
  191. package/dist/template/implementations/init_types.template.d.ts +2 -2
  192. package/dist/template/implementations/init_types.template.d.ts.map +1 -1
  193. package/dist/template/implementations/init_types.template.js +2 -2
  194. package/dist/template/implementations/model.template.d.ts +2 -2
  195. package/dist/template/implementations/model.template.d.ts.map +1 -1
  196. package/dist/template/implementations/model.template.js +47 -37
  197. package/dist/template/implementations/model_test.template.d.ts +2 -2
  198. package/dist/template/implementations/model_test.template.d.ts.map +1 -1
  199. package/dist/template/implementations/model_test.template.js +2 -2
  200. package/dist/template/implementations/service.template.d.ts +4 -4
  201. package/dist/template/implementations/service.template.d.ts.map +1 -1
  202. package/dist/template/implementations/service.template.js +24 -16
  203. package/dist/template/implementations/view_enums_buttonset.template.d.ts +2 -2
  204. package/dist/template/implementations/view_enums_buttonset.template.d.ts.map +1 -1
  205. package/dist/template/implementations/view_enums_buttonset.template.js +1 -1
  206. package/dist/template/implementations/view_enums_dropdown.template.d.ts +2 -2
  207. package/dist/template/implementations/view_enums_dropdown.template.d.ts.map +1 -1
  208. package/dist/template/implementations/view_enums_dropdown.template.js +2 -2
  209. package/dist/template/implementations/view_enums_select.template.d.ts +2 -2
  210. package/dist/template/implementations/view_enums_select.template.d.ts.map +1 -1
  211. package/dist/template/implementations/view_enums_select.template.js +2 -2
  212. package/dist/template/implementations/view_form.template.d.ts +2 -2
  213. package/dist/template/implementations/view_form.template.d.ts.map +1 -1
  214. package/dist/template/implementations/view_form.template.js +4 -4
  215. package/dist/template/implementations/view_id_all_select.template.d.ts +2 -2
  216. package/dist/template/implementations/view_id_all_select.template.d.ts.map +1 -1
  217. package/dist/template/implementations/view_id_all_select.template.js +1 -1
  218. package/dist/template/implementations/view_id_async_select.template.d.ts +2 -2
  219. package/dist/template/implementations/view_id_async_select.template.d.ts.map +1 -1
  220. package/dist/template/implementations/view_id_async_select.template.js +1 -1
  221. package/dist/template/implementations/view_list.template.d.ts +2 -2
  222. package/dist/template/implementations/view_list.template.d.ts.map +1 -1
  223. package/dist/template/implementations/view_list.template.js +29 -19
  224. package/dist/template/implementations/view_list_columns.template.d.ts +3 -3
  225. package/dist/template/implementations/view_list_columns.template.d.ts.map +1 -1
  226. package/dist/template/implementations/view_list_columns.template.js +1 -1
  227. package/dist/template/implementations/view_search_input.template.d.ts +2 -2
  228. package/dist/template/implementations/view_search_input.template.d.ts.map +1 -1
  229. package/dist/template/implementations/view_search_input.template.js +1 -1
  230. package/dist/template/index.d.ts +4 -2
  231. package/dist/template/index.d.ts.map +1 -1
  232. package/dist/template/index.js +5 -3
  233. package/dist/template/template-manager.d.ts +56 -0
  234. package/dist/template/template-manager.d.ts.map +1 -0
  235. package/dist/template/template-manager.js +125 -0
  236. package/dist/template/template-types.d.ts +16 -0
  237. package/dist/template/template-types.d.ts.map +1 -0
  238. package/dist/template/template-types.js +7 -0
  239. package/dist/template/template.d.ts +12 -2
  240. package/dist/template/template.d.ts.map +1 -1
  241. package/dist/template/template.js +19 -6
  242. package/dist/template/zod-converter.d.ts +40 -7
  243. package/dist/template/zod-converter.d.ts.map +1 -1
  244. package/dist/template/zod-converter.js +386 -58
  245. package/dist/testing/_relation-graph.d.ts +1 -1
  246. package/dist/testing/_relation-graph.d.ts.map +1 -1
  247. package/dist/testing/_relation-graph.js +12 -3
  248. package/dist/testing/fixture-manager.d.ts +42 -11
  249. package/dist/testing/fixture-manager.d.ts.map +1 -1
  250. package/dist/testing/fixture-manager.js +338 -236
  251. package/dist/types/types.d.ts +709 -104
  252. package/dist/types/types.d.ts.map +1 -1
  253. package/dist/types/types.js +309 -52
  254. package/dist/typings/knex.d.js +2 -2
  255. package/dist/utils/async-utils.d.ts.map +1 -1
  256. package/dist/utils/async-utils.js +3 -3
  257. package/dist/utils/console-util.js +1 -1
  258. package/dist/utils/controller.d.ts +1 -0
  259. package/dist/utils/controller.d.ts.map +1 -1
  260. package/dist/utils/controller.js +4 -1
  261. package/dist/utils/esm-utils.d.ts +0 -6
  262. package/dist/utils/esm-utils.d.ts.map +1 -1
  263. package/dist/utils/esm-utils.js +2 -9
  264. package/dist/utils/formatter.d.ts +3 -0
  265. package/dist/utils/formatter.d.ts.map +1 -0
  266. package/dist/utils/formatter.js +110 -0
  267. package/dist/utils/fs-utils.d.ts +1 -1
  268. package/dist/utils/fs-utils.d.ts.map +1 -1
  269. package/dist/utils/fs-utils.js +1 -1
  270. package/dist/utils/lodash-able.d.ts.map +1 -1
  271. package/dist/utils/lodash-able.js +1 -1
  272. package/dist/utils/object-utils.d.ts +44 -0
  273. package/dist/utils/object-utils.d.ts.map +1 -0
  274. package/dist/utils/object-utils.js +191 -0
  275. package/dist/utils/path-utils.d.ts +1 -1
  276. package/dist/utils/path-utils.d.ts.map +1 -1
  277. package/dist/utils/path-utils.js +3 -3
  278. package/dist/utils/process-utils.js +1 -1
  279. package/dist/utils/sql-parser.d.ts +5 -1
  280. package/dist/utils/sql-parser.d.ts.map +1 -1
  281. package/dist/utils/sql-parser.js +14 -3
  282. package/dist/utils/type-utils.d.ts +23 -0
  283. package/dist/utils/type-utils.d.ts.map +1 -0
  284. package/dist/utils/type-utils.js +45 -0
  285. package/dist/utils/utils.d.ts +7 -1
  286. package/dist/utils/utils.d.ts.map +1 -1
  287. package/dist/utils/utils.js +44 -5
  288. package/dist/utils/zod-error.d.ts +1 -1
  289. package/dist/utils/zod-error.d.ts.map +1 -1
  290. package/dist/utils/zod-error.js +1 -1
  291. package/package.json +55 -30
  292. package/src/ai/agents/agent.ts +87 -0
  293. package/src/ai/agents/index.ts +2 -0
  294. package/src/ai/agents/types.ts +47 -0
  295. package/src/ai/index.ts +1 -0
  296. package/src/ai/providers/rtzr/api.ts +37 -0
  297. package/src/ai/providers/rtzr/error.ts +34 -0
  298. package/src/ai/providers/rtzr/index.ts +4 -0
  299. package/src/ai/providers/rtzr/model.ts +201 -0
  300. package/src/ai/providers/rtzr/options.ts +49 -0
  301. package/src/ai/providers/rtzr/provider.ts +91 -0
  302. package/src/ai/providers/rtzr/utils.ts +127 -0
  303. package/src/api/base-frame.ts +4 -2
  304. package/src/api/caster.ts +17 -23
  305. package/src/api/code-converters.ts +176 -533
  306. package/src/api/config.ts +39 -56
  307. package/src/api/context.ts +7 -18
  308. package/src/api/decorators.ts +175 -46
  309. package/src/api/index.ts +2 -2
  310. package/src/api/sonamu.ts +133 -124
  311. package/src/api/validator.ts +83 -0
  312. package/src/bin/build-config.ts +7 -1
  313. package/src/bin/cli.ts +192 -110
  314. package/src/bin/loader-register.ts +38 -0
  315. package/src/database/_batch_update.ts +46 -31
  316. package/src/database/base-model.ts +390 -182
  317. package/src/database/base-model.types.ts +155 -0
  318. package/src/database/code-generator.ts +13 -32
  319. package/src/database/db.ts +36 -50
  320. package/src/database/puri-subset.test-d.ts +471 -0
  321. package/src/database/puri-subset.types.ts +195 -0
  322. package/src/database/puri-wrapper.ts +58 -67
  323. package/src/database/puri.ts +182 -126
  324. package/src/database/puri.types.ts +64 -31
  325. package/src/database/transaction-context.ts +1 -1
  326. package/src/database/upsert-builder.ts +261 -132
  327. package/src/entity/entity-manager.ts +36 -28
  328. package/src/entity/entity.ts +330 -249
  329. package/src/exceptions/error-handler.ts +3 -3
  330. package/src/exceptions/so-exceptions.ts +11 -11
  331. package/src/file-storage/driver.ts +5 -5
  332. package/src/file-storage/file-storage.ts +2 -2
  333. package/src/index.ts +18 -12
  334. package/src/migration/code-generation.ts +185 -172
  335. package/src/migration/migration-set.ts +80 -293
  336. package/src/migration/migrator.ts +182 -425
  337. package/src/migration/mysql-schema-reader.ts.txt +272 -0
  338. package/src/migration/postgresql-schema-reader.ts +310 -0
  339. package/src/migration/types.ts +6 -39
  340. package/src/naite/messaging-types.ts +51 -0
  341. package/src/naite/naite-reporter.ts +128 -0
  342. package/src/naite/naite.ts +378 -33
  343. package/src/shared/web.shared.ts.txt +20 -24
  344. package/src/stream/sse.ts +5 -5
  345. package/src/syncer/api-parser.ts +52 -69
  346. package/src/syncer/checksum.ts +25 -37
  347. package/src/syncer/code-generator.ts +58 -62
  348. package/src/syncer/entity-operations.ts +12 -15
  349. package/src/syncer/file-patterns.ts +2 -2
  350. package/src/syncer/index.ts +4 -4
  351. package/src/syncer/module-loader.ts +28 -25
  352. package/src/syncer/syncer.ts +155 -162
  353. package/src/template/entity-converter.ts +18 -27
  354. package/src/template/helpers.ts +8 -11
  355. package/src/template/implementations/entity.template.ts +6 -6
  356. package/src/template/implementations/generated.template.ts +99 -99
  357. package/src/template/implementations/generated_http.template.ts +21 -54
  358. package/src/template/implementations/generated_sso.template.ts +78 -65
  359. package/src/template/implementations/init_types.template.ts +4 -6
  360. package/src/template/implementations/model.template.ts +47 -38
  361. package/src/template/implementations/model_test.template.ts +3 -3
  362. package/src/template/implementations/service.template.ts +56 -80
  363. package/src/template/implementations/view_enums_buttonset.template.ts +2 -2
  364. package/src/template/implementations/view_enums_dropdown.template.ts +4 -4
  365. package/src/template/implementations/view_enums_select.template.ts +3 -3
  366. package/src/template/implementations/view_form.template.ts +34 -75
  367. package/src/template/implementations/view_id_all_select.template.ts +2 -2
  368. package/src/template/implementations/view_id_async_select.template.ts +9 -23
  369. package/src/template/implementations/view_list.template.ts +54 -95
  370. package/src/template/implementations/view_list_columns.template.ts +4 -10
  371. package/src/template/implementations/view_search_input.template.ts +2 -2
  372. package/src/template/index.ts +4 -2
  373. package/src/template/template-manager.ts +166 -0
  374. package/src/template/template-types.ts +16 -0
  375. package/src/template/template.ts +29 -10
  376. package/src/template/zod-converter.ts +459 -101
  377. package/src/testing/_relation-graph.ts +18 -11
  378. package/src/testing/fixture-manager.ts +468 -362
  379. package/src/types/types.ts +516 -248
  380. package/src/typings/knex.d.ts +7 -9
  381. package/src/utils/async-utils.ts +8 -12
  382. package/src/utils/console-util.ts +1 -1
  383. package/src/utils/controller.ts +3 -0
  384. package/src/utils/esm-utils.ts +8 -18
  385. package/src/utils/formatter.ts +109 -0
  386. package/src/utils/fs-utils.ts +1 -1
  387. package/src/utils/lodash-able.ts +1 -4
  388. package/src/utils/object-utils.ts +217 -0
  389. package/src/utils/path-utils.ts +3 -6
  390. package/src/utils/process-utils.ts +1 -1
  391. package/src/utils/sql-parser.ts +23 -5
  392. package/src/utils/type-utils.ts +83 -0
  393. package/src/utils/utils.ts +58 -9
  394. package/src/utils/zod-error.ts +3 -3
  395. package/dist/bin/cli-wrapper.d.ts +0 -3
  396. package/dist/bin/cli-wrapper.d.ts.map +0 -1
  397. package/dist/bin/cli-wrapper.js +0 -72
  398. package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts +0 -2
  399. package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts.map +0 -1
  400. package/dist/database/knex-plugins/knex-on-duplicate-update.js +0 -39
  401. package/dist/entity/entity-utils.d.ts +0 -61
  402. package/dist/entity/entity-utils.d.ts.map +0 -1
  403. package/dist/entity/entity-utils.js +0 -210
  404. package/src/bin/cli-wrapper.ts +0 -82
  405. package/src/database/knex-plugins/knex-on-duplicate-update.ts +0 -45
  406. package/src/entity/entity-utils.ts +0 -291
@@ -1,40 +1,36 @@
1
- import path, { dirname } from "path";
2
- import { mkdir, readFile, writeFile } from "fs/promises";
3
- import { exists } from "../utils/fs-utils";
4
- import * as _ from "lodash-es";
5
- import { EntityManager, EntityNamesRecord } from "../entity/entity-manager";
6
- import { GenerateOptions } from "../types/types";
7
- import chalk from "chalk";
8
- import { TemplateKey, TemplateOptions } from "../types/types";
9
- import { Sonamu } from "../api/sonamu";
1
+ import { hot } from "@sonamu-kit/hot-hook";
10
2
  import assert from "assert";
3
+ import chalk from "chalk";
4
+ import { mkdir, readFile, writeFile } from "fs/promises";
11
5
  import { minimatch } from "minimatch";
6
+ import path, { dirname } from "path";
7
+ import { group, unique } from "radashi";
8
+ import type { z } from "zod";
9
+ import { registeredApis } from "../api/decorators";
10
+ import { Sonamu } from "../api/sonamu";
11
+ import { EntityManager, type EntityNamesRecord } from "../entity/entity-manager";
12
+ import { Naite } from "../naite/naite";
13
+ import { TemplateManager } from "../template/template-manager";
14
+ import type { GenerateOptions, PathAndCode } from "../types/types";
15
+ import { TemplateKey, type TemplateOptions } from "../types/types";
12
16
  import { mapAsync, reduceAsync } from "../utils/async-utils";
13
17
  import { centerText } from "../utils/console-util";
18
+ import { isTest } from "../utils/controller";
19
+ import { exists } from "../utils/fs-utils";
20
+ import type { AbsolutePath } from "../utils/path-utils";
14
21
  import { runWithGracefulShutdown } from "../utils/process-utils";
15
- import { AbsolutePath } from "../utils/path-utils";
22
+ import { areFilesSame, findChangedFilesUsingChecksums, renewChecksums } from "./checksum";
16
23
  import { generateTemplate, renderTemplate } from "./code-generator";
17
- import { Template } from "../template";
18
- import {
19
- FileType,
20
- getChecksumPatternGroupInAbsolutePath,
21
- } from "./file-patterns";
22
- import {
23
- findChangedFilesUsingChecksums,
24
- renewChecksums,
25
- areFilesSame,
26
- } from "./checksum";
24
+ import { createEntity, delEntity } from "./entity-operations";
25
+ import { type FileType, getChecksumPatternGroupInAbsolutePath } from "./file-patterns";
27
26
  import {
27
+ type LoadedApis,
28
+ type LoadedModels,
29
+ type LoadedTypes,
28
30
  loadApis,
29
31
  loadModels,
30
32
  loadTypes,
31
- LoadedApis,
32
- LoadedModels,
33
- LoadedTypes,
34
33
  } from "./module-loader";
35
- import { createEntity, delEntity } from "./entity-operations";
36
- import { z } from "zod";
37
- import { hot } from "@sonamu-kit/hot-hook";
38
34
 
39
35
  type DiffGroups = {
40
36
  [key in FileType]: AbsolutePath[];
@@ -74,7 +70,7 @@ export class Syncer {
74
70
  // 싱크 액션이 끝나면 항상 체크섬을 다시 갱신합니다.
75
71
  await renewChecksums();
76
72
  },
77
- { whenThisHappens: "SIGUSR2", waitForUpTo: 20000 }
73
+ { whenThisHappens: "SIGUSR2", waitForUpTo: 20000 },
78
74
  );
79
75
  }
80
76
 
@@ -84,10 +80,7 @@ export class Syncer {
84
80
  * 체크섬 파일 업데이트는 여기에서 하지 않습니다. 호출자가 합니다.
85
81
  * @param diffFilePath - 변경 파일들. 프로젝트 루트부터 "src/" 또는 "dist/"로 시작하는 상대 경로입니다. 예시: "src/application/user/user.model.ts"
86
82
  */
87
- async syncFromWatcher(
88
- event: string,
89
- diffFilePath: AbsolutePath
90
- ): Promise<void> {
83
+ async syncFromWatcher(event: string, diffFilePath: AbsolutePath): Promise<void> {
91
84
  if (event !== "change" && event !== "add" && event !== "unlink") {
92
85
  return;
93
86
  }
@@ -95,18 +88,33 @@ export class Syncer {
95
88
  // 일단 변경된 파일과 dependent 파일들을 invalidate 합니다.
96
89
  // 한 번 이상 import된 친구들에 대해서만 실제 작업이 일어납니다.
97
90
  // 그러니 안심하고 invalidate 해도 됩니다.
98
- const invalidatedPaths = await hot.invalidateFile(diffFilePath, event);
99
- if (invalidatedPaths.length > 0) {
100
- console.log(
101
- chalk.bold(
102
- `🔄 Invalidated:\n${chalk.blue(invalidatedPaths.map((p) => `- ${path.relative(Sonamu.apiRootPath, p)}`).join("\n"))}`
103
- )
104
- );
91
+ // 테스트 환경에서는 hot.invalidateFile 초기 에러가 발생하기 때문에 invalidate 하지 않습니다.
92
+ if (!isTest()) {
93
+ const invalidatedPaths = (await hot.invalidateFile(diffFilePath, event)) as AbsolutePath[];
94
+
95
+ if (invalidatedPaths.length > 0) {
96
+ console.log(chalk.bold(`🔄 Invalidated:`));
97
+
98
+ for (const invalidatedPath of invalidatedPaths) {
99
+ // 만약 model.ts 파일이 변경(invalidate)되었다? 그러면 registeredApis 중에서 이 모델에 해당하는 api들은 지워줘요.
100
+ // registeredApis는 통으로 다 날려버릴 수 없습니다. registeredApis에 올라오는 친구들은 초기 로드시 또는 HMR시에만 등록되기 때문입니다.
101
+ // 따라서 model.ts 파일의 변경으로 다음번 새로운 eval이 예상되는 이 시점에서만, 이 모델에서 나온 registeredApis들을 지워줄 수 있습니다.
102
+ const removedApis = this.removeInvalidatedRegisteredApis(invalidatedPath);
103
+ if (removedApis.length > 0) {
104
+ console.log(
105
+ chalk.blue(`- ${path.relative(Sonamu.apiRootPath, invalidatedPath)}`),
106
+ chalk.gray(`(with ${removedApis.length} APIs)`),
107
+ );
108
+ } else {
109
+ console.log(chalk.blue(`- ${path.relative(Sonamu.apiRootPath, invalidatedPath)}`));
110
+ }
111
+ }
112
+ }
105
113
  }
106
114
 
107
- const isInCheckPatternGroup = Object.values(
108
- getChecksumPatternGroupInAbsolutePath()
109
- ).some((pattern) => minimatch(diffFilePath, pattern));
115
+ const isInCheckPatternGroup = Object.values(getChecksumPatternGroupInAbsolutePath()).some(
116
+ (pattern) => minimatch(diffFilePath, pattern),
117
+ );
110
118
 
111
119
  // 할 일(sync)이 있으면 합니다.
112
120
  if (isInCheckPatternGroup) {
@@ -122,25 +130,48 @@ export class Syncer {
122
130
  this.syncUI();
123
131
  }
124
132
 
125
- private async copySharedToTargets(targets: string[]): Promise<void> {
133
+ removeInvalidatedRegisteredApis(
134
+ invalidatedPath: AbsolutePath,
135
+ ): (typeof registeredApis)[number][] {
136
+ if (!invalidatedPath.endsWith(".model.ts" /*소스 코드를 다루는 상황이니 .ts 경로로 봅니다.*/)) {
137
+ return [];
138
+ }
139
+
140
+ const entityId = EntityManager.getEntityIdFromPath(invalidatedPath);
141
+ const toRemove = registeredApis.filter((api) => api.modelName === `${entityId}Model`);
142
+ for (const api of toRemove) {
143
+ registeredApis.splice(registeredApis.indexOf(api), 1);
144
+ }
145
+
146
+ return toRemove;
147
+ }
148
+
149
+ async copySharedToTargets(targets: string[]): Promise<void> {
126
150
  for (const target of targets) {
127
151
  // 지금 가져가려는 이 파일은 Sonamu 코드베이스의 일부입니다.
128
152
  // 그런데 dist 속 빌드된 소스 코드 파일이 필요한 것이 아니고, src에만 있는 텍스트 파일이 필요합니다.
129
153
  // 따라서 /src/에서 찾습니다.
130
154
  const srcPath = path.join(
131
155
  import.meta.dirname.replace("/dist/", "/src/"),
132
- `../shared/${target}.shared.ts.txt`
156
+ `../shared/${target}.shared.ts.txt`,
133
157
  );
134
158
  if (!(await exists(srcPath))) {
135
159
  return;
136
160
  }
161
+ if (!(await exists(path.join(Sonamu.appRootPath, target)))) {
162
+ throw new Error(
163
+ `Tried to copy sonamu.shared.ts to target '${target}' but the target directory does not exist. Please check your project directory structure.`,
164
+ );
165
+ }
137
166
 
138
167
  // 이건 프로젝트에 .ts 소스 코드 파일을 생성하는 것이므로 src의 .ts 경로로 갑니다.
139
- const destPath = path.join(
140
- Sonamu.appRootPath,
141
- target,
142
- "src/services/sonamu.shared.ts"
143
- );
168
+ const destPath = path.join(Sonamu.appRootPath, target, "./sonamu.shared.ts");
169
+
170
+ // 정말 혹시나지만 target 디렉토리는 있어도 src/services 디렉토리는 없을 수 있으므로 미리 생성해줍니다.
171
+ if (!(await exists(path.dirname(destPath)))) {
172
+ await mkdir(path.dirname(destPath), { recursive: true });
173
+ console.warn(`Created directory '${path.dirname(destPath)}' because it did not exist.`);
174
+ }
144
175
 
145
176
  if (await areFilesSame(srcPath, destPath)) {
146
177
  return;
@@ -148,10 +179,10 @@ export class Syncer {
148
179
 
149
180
  await writeFile(destPath, await readFile(srcPath));
150
181
 
151
- console.log(
152
- chalk.bold("Copied: ") +
153
- chalk.blue(path.relative(Sonamu.appRootPath, destPath))
154
- );
182
+ !isTest() &&
183
+ console.log(
184
+ chalk.bold("Copied: ") + chalk.blue(path.relative(Sonamu.appRootPath, destPath)),
185
+ );
155
186
  }
156
187
  }
157
188
 
@@ -173,9 +204,7 @@ export class Syncer {
173
204
  * @param diffFilePaths - 변경된 파일들의 절대 경로 목록
174
205
  * @returns diffTypes - 변경된 파일의 타입 목록 (entity, types, model 등)
175
206
  */
176
- private async doSyncActions(
177
- diffFilePaths: AbsolutePath[]
178
- ): Promise<{ diffTypes: string[] }> {
207
+ async doSyncActions(diffFilePaths: AbsolutePath[]): Promise<{ diffTypes: string[] }> {
179
208
  const diffGroups = this.calculateDiffGroups(diffFilePaths);
180
209
  const diffTypes = Object.keys(diffGroups);
181
210
 
@@ -210,39 +239,28 @@ export class Syncer {
210
239
  };
211
240
  }
212
241
 
213
- private calculateDiffGroups(diffFiles: AbsolutePath[]): DiffGroups {
214
- return _.groupBy(diffFiles, (r) => {
215
- const matched = r.match(
216
- /\.(model|types|functions|entity|generated|frame|config)\.[tj]s/
217
- );
242
+ calculateDiffGroups(diffFiles: AbsolutePath[]): DiffGroups {
243
+ return group(diffFiles, (r) => {
244
+ const matched = r.match(/\.(model|types|functions|entity|generated|frame|config)\.[tj]s/);
218
245
  return matched?.[1] ?? "unknown";
219
246
  }) as unknown as DiffGroups;
220
247
  }
221
248
 
222
- private async handleEntityChange(
223
- diffGroups: DiffGroups,
224
- diffTypes: string[]
225
- ): Promise<void> {
226
- // console.log(
227
- // chalk.gray(
228
- // `[Processing] Handling entity changes: ${diffGroups["entity"]?.map((p) => path.relative(Sonamu.apiRootPath, p)).join(", ")}`
229
- // )
230
- // );
249
+ async handleEntityChange(diffGroups: DiffGroups, diffTypes: string[]): Promise<void> {
250
+ Naite.t("handleEntityChange", { diffGroups, diffTypes });
231
251
 
232
252
  await EntityManager.reload();
233
253
 
234
254
  // types 생성(entity 새로 추가된 경우)
235
255
  // parentId가 없고, types가 없는 경우에만 생성
236
- const entityId = EntityManager.getEntityIdFromPath(
237
- diffGroups["entity"]?.[0]
238
- );
256
+ const entityId = EntityManager.getEntityIdFromPath(diffGroups.entity?.[0]);
239
257
 
240
258
  if (entityId) {
241
259
  const entity = EntityManager.get(entityId);
242
260
  // 프로젝트에 생성되어야 하는 .ts 파일의 경로입니다.
243
261
  const typeFilePath = path.join(
244
262
  Sonamu.apiRootPath,
245
- `src/application/${entity.names.fs}/${entity.names.fs}.types.ts`
263
+ `src/application/${entity.names.fs}/${entity.names.fs}.types.ts`,
246
264
  );
247
265
  if (entity.parentId === undefined && !(await exists(typeFilePath))) {
248
266
  await generateTemplate("init_types", { entityId });
@@ -251,24 +269,20 @@ export class Syncer {
251
269
 
252
270
  await this.actionGenerateSchemas();
253
271
 
254
- diffGroups["generated"] = _.uniq([
255
- ...(diffGroups["generated"] ?? []),
256
- path.join(
257
- Sonamu.apiRootPath,
258
- "src/application/sonamu.generated.ts"
259
- ) as AbsolutePath,
272
+ diffGroups.generated = unique([
273
+ ...(diffGroups.generated ?? []),
274
+ path.join(Sonamu.apiRootPath, "src/application/sonamu.generated.ts") as AbsolutePath,
260
275
  ]);
261
276
  diffTypes.push("generated");
262
277
  }
263
278
 
264
- private async handleTypesOrFunctionsOrGeneratedChange(
265
- diffGroups: DiffGroups
266
- ): Promise<FileType[]> {
267
- const tsPaths = _.uniq([
268
- ...(diffGroups["types"] ?? []),
269
- ...(diffGroups["functions"] ?? []),
270
- ...(diffGroups["generated"] ?? []),
279
+ async handleTypesOrFunctionsOrGeneratedChange(diffGroups: DiffGroups): Promise<FileType[]> {
280
+ const tsPaths = unique([
281
+ ...(diffGroups.types ?? []),
282
+ ...(diffGroups.functions ?? []),
283
+ ...(diffGroups.generated ?? []),
271
284
  ]);
285
+ Naite.t("handleTypesOrFunctionsOrGeneratedChange", { diffGroups });
272
286
 
273
287
  // console.log(
274
288
  // chalk.gray(
@@ -281,13 +295,9 @@ export class Syncer {
281
295
  return [];
282
296
  }
283
297
 
284
- private async handleModelOrFrameChange(
285
- diffGroups: DiffGroups
286
- ): Promise<void> {
287
- const mergedGroup = [
288
- ...(diffGroups["model"] ?? []),
289
- ...(diffGroups["frame"] ?? []),
290
- ];
298
+ async handleModelOrFrameChange(diffGroups: DiffGroups): Promise<void> {
299
+ Naite.t("handleModelOrFrameChange", { diffGroups });
300
+ const mergedGroup = [...(diffGroups.model ?? []), ...(diffGroups.frame ?? [])];
291
301
 
292
302
  // console.log(
293
303
  // chalk.gray(
@@ -330,13 +340,11 @@ export class Syncer {
330
340
  const { host, port } = Sonamu.config.server.listen ?? {};
331
341
  const content = `API_HOST=${host ?? "localhost"}\nAPI_PORT=${port ?? 3000}`;
332
342
 
343
+ Naite.t("actionSyncConfig", { content });
333
344
  await Promise.all(
334
345
  Sonamu.config.sync.targets.map(async (target) => {
335
- await writeFile(
336
- path.join(Sonamu.appRootPath, target, ".sonamu.env"),
337
- content
338
- );
339
- })
346
+ await writeFile(path.join(Sonamu.appRootPath, target, ".sonamu.env"), content);
347
+ }),
340
348
  );
341
349
  }
342
350
 
@@ -344,7 +352,7 @@ export class Syncer {
344
352
  * sonamu.generated.ts와 sonamu.generated.sso.ts를 생성합니다.
345
353
  * @returns 생성된 파일 경로 배열.
346
354
  */
347
- private async actionGenerateSchemas(): Promise<AbsolutePath[]> {
355
+ async actionGenerateSchemas(): Promise<AbsolutePath[]> {
348
356
  return (
349
357
  await Promise.all([
350
358
  generateTemplate("generated_sso", {}, { overwrite: true }),
@@ -360,18 +368,19 @@ export class Syncer {
360
368
  * @param paramsArray
361
369
  * @returns 생성된 파일 경로 배열.
362
370
  */
363
- private async actionGenerateServices(
371
+ async actionGenerateServices(
364
372
  paramsArray: {
365
373
  namesRecord: EntityNamesRecord;
366
- }[]
374
+ }[],
367
375
  ): Promise<string[]> {
376
+ Naite.t("actionGenerateServices", paramsArray);
368
377
  return (
369
378
  await Promise.all(
370
379
  paramsArray.map(async (params) =>
371
- generateTemplate("service", params, {
380
+ generateTemplate("service", params as TemplateOptions["service"], {
372
381
  overwrite: true,
373
- })
374
- )
382
+ }),
383
+ ),
375
384
  )
376
385
  )
377
386
  .flat()
@@ -382,11 +391,11 @@ export class Syncer {
382
391
  * sonamu.generated.http를 생성합니다.
383
392
  * @returns 생성된 파일 경로.
384
393
  */
385
- private async actionGenerateHttps(): Promise<AbsolutePath> {
394
+ async actionGenerateHttps(): Promise<AbsolutePath> {
386
395
  const [res] = await generateTemplate(
387
396
  "generated_http",
388
- {},
389
- { overwrite: true }
397
+ { entityId: "dummy" },
398
+ { overwrite: true },
390
399
  );
391
400
  assert(res);
392
401
  return res;
@@ -397,9 +406,7 @@ export class Syncer {
397
406
  * @param tsPaths
398
407
  * @returns 복사된 파일 경로 배열.
399
408
  */
400
- private async actionSyncFilesToTargets(
401
- tsPaths: AbsolutePath[]
402
- ): Promise<string[]> {
409
+ async actionSyncFilesToTargets(tsPaths: AbsolutePath[]): Promise<string[]> {
403
410
  const { targets } = Sonamu.config.sync;
404
411
  const { dir: apiDir } = Sonamu.config.api;
405
412
 
@@ -415,23 +422,20 @@ export class Syncer {
415
422
  if (!(await exists(dir))) {
416
423
  await mkdir(dir, { recursive: true });
417
424
  }
418
- console.log(
419
- chalk.bold("Copied: ") +
420
- chalk.blue(dst.replace(Sonamu.appRootPath + "/", ""))
421
- );
425
+ !isTest() &&
426
+ console.log(
427
+ chalk.bold("Copied: ") + chalk.blue(dst.replace(`${Sonamu.appRootPath}/`, "")),
428
+ );
422
429
  await this.copyFileWithReplaceCoreToShared(realSrc, dst);
423
430
  return dst;
424
- })
425
- )
426
- )
431
+ }),
432
+ ),
433
+ ),
427
434
  )
428
435
  ).flat();
429
436
  }
430
437
 
431
- private async copyFileWithReplaceCoreToShared(
432
- fromPath: string,
433
- toPath: string
434
- ) {
438
+ private async copyFileWithReplaceCoreToShared(fromPath: string, toPath: string) {
435
439
  if (!(await exists(fromPath))) {
436
440
  return;
437
441
  }
@@ -439,16 +443,8 @@ export class Syncer {
439
443
  const oldFileContent = (await readFile(fromPath)).toString();
440
444
 
441
445
  const newFileContent = (() => {
442
- const nfc = oldFileContent.replace(
443
- /from "sonamu"/g,
444
- `from "src/services/sonamu.shared"`
445
- );
446
-
447
- if (toPath.includes("/web/")) {
448
- return nfc; // .replace(/from "lodash";/g, `from "lodash-es";`); // TODO 흠? 필요없을듯.
449
- } else {
450
- return nfc;
451
- }
446
+ const nfc = oldFileContent.replace(/from "sonamu"/g, `from "./sonamu.shared"`);
447
+ return nfc;
452
448
  })();
453
449
  return writeFile(toPath, newFileContent);
454
450
  }
@@ -463,11 +459,12 @@ export class Syncer {
463
459
  async checkExistsGenCode(
464
460
  entityId: string,
465
461
  templateKey: TemplateKey,
466
- enumId?: string
462
+ enumId?: string,
467
463
  ): Promise<{ subPath: string; fullPath: string; isExists: boolean }> {
468
- const { target, path: genPath } = Template.find(
469
- templateKey
470
- ).getTargetAndPath(EntityManager.getNamesFromId(entityId), enumId);
464
+ const { target, path: genPath } = TemplateManager.get(templateKey).getTargetAndPath(
465
+ EntityManager.getNamesFromId(entityId),
466
+ enumId,
467
+ );
471
468
 
472
469
  const subPath = path.join(target, genPath);
473
470
  const fullPath = path.join(Sonamu.appRootPath, subPath);
@@ -487,27 +484,22 @@ export class Syncer {
487
484
  async checkExists(
488
485
  entityId: string,
489
486
  enums: {
490
- [name: string]: z.ZodEnum<any>;
491
- }
487
+ [name: string]: z.ZodEnum<Readonly<Record<string, string | number>>>;
488
+ },
492
489
  ): Promise<Record<`${TemplateKey}${string}`, boolean>> {
493
490
  const keys: TemplateKey[] = TemplateKey.options;
494
491
  const names = EntityManager.getNamesFromId(entityId);
495
- const enumsKeys = Object.keys(enums).filter(
496
- (name) => name !== names.constant
497
- );
492
+ const enumsKeys = Object.keys(enums).filter((name) => name !== names.constant);
498
493
 
499
494
  return await reduceAsync(
500
495
  keys,
501
496
  async (result, key) => {
502
- const tpl = Template.find(key);
497
+ const tpl = TemplateManager.get(key);
503
498
  if (key.startsWith("view_enums")) {
504
499
  await mapAsync(enumsKeys, async (componentId) => {
505
- const { target, path: p } = tpl.getTargetAndPath(
506
- names,
507
- componentId
508
- );
500
+ const { target, path: p } = tpl.getTargetAndPath(names, componentId);
509
501
  result[`${key}__${componentId}`] = await exists(
510
- path.join(Sonamu.appRootPath, target, p)
502
+ path.join(Sonamu.appRootPath, target, p),
511
503
  );
512
504
  });
513
505
  return result;
@@ -518,7 +510,7 @@ export class Syncer {
518
510
  if (target.includes(":target")) {
519
511
  await mapAsync(targets, async (t) => {
520
512
  result[`${key}__${t}`] = await exists(
521
- path.join(Sonamu.appRootPath, target.replace(":target", t), p)
513
+ path.join(Sonamu.appRootPath, target.replace(":target", t), p),
522
514
  );
523
515
  });
524
516
  } else {
@@ -527,26 +519,24 @@ export class Syncer {
527
519
 
528
520
  return result;
529
521
  },
530
- {} as Record<`${TemplateKey}${string}`, boolean>
522
+ {} as Record<`${TemplateKey}${string}`, boolean>,
531
523
  );
532
524
  }
533
525
 
534
526
  syncUI() {
535
527
  const uiPort = Sonamu.config.ui?.port ?? 57000;
536
528
 
537
- fetch(`http://127.0.0.1:${uiPort}/api/reload`, {
538
- method: "GET",
539
- }).catch((e) =>
540
- console.log(chalk.dim(`Failed to reload Sonamu UI: ${e.message}`))
541
- );
529
+ if (!isTest()) {
530
+ fetch(`http://127.0.0.1:${uiPort}/api/reload`, {
531
+ method: "GET",
532
+ }).catch((e) => console.log(chalk.dim(`Failed to reload Sonamu UI: ${e.message}`)));
533
+ }
542
534
  }
543
535
 
544
536
  /**
545
537
  * 하위호환용 프록시 메소드입니다.
546
538
  */
547
- async createEntity(
548
- form: Omit<TemplateOptions["entity"], "title"> & { title?: string }
549
- ) {
539
+ async createEntity(form: TemplateOptions["entity"]) {
550
540
  return await createEntity(form);
551
541
  }
552
542
 
@@ -560,18 +550,21 @@ export class Syncer {
560
550
  /**
561
551
  * 하위호환용 프록시 메소드입니다.
562
552
  */
563
- async generateTemplate(
564
- key: TemplateKey,
565
- templateOptions: any,
566
- _generateOptions?: GenerateOptions
567
- ) {
553
+ async generateTemplate<T extends TemplateKey>(
554
+ key: T,
555
+ templateOptions: TemplateOptions[T],
556
+ _generateOptions?: GenerateOptions,
557
+ ): Promise<AbsolutePath[]> {
568
558
  return await generateTemplate(key, templateOptions, _generateOptions);
569
559
  }
570
560
 
571
561
  /**
572
562
  * 하위호환용 프록시 메소드입니다.
573
563
  */
574
- async renderTemplate(key: TemplateKey, templateOptions: any) {
564
+ async renderTemplate<T extends keyof TemplateOptions>(
565
+ key: T,
566
+ templateOptions: TemplateOptions[T],
567
+ ): Promise<PathAndCode[]> {
575
568
  return await renderTemplate(key, templateOptions);
576
569
  }
577
570
 
@@ -1,18 +1,16 @@
1
+ import assert from "assert";
1
2
  import z from "zod";
2
3
  import { EntityManager } from "../entity/entity-manager";
3
4
  import { ServiceUnavailableException } from "../exceptions/so-exceptions";
4
- import { EntityPropNode, RenderingNode } from "../types/types";
5
- import { zodTypeToRenderingNode, propToZodType } from "./zod-converter";
5
+ import type { EntityPropNode, RenderingNode } from "../types/types";
6
+ import { propToZodType, zodTypeToRenderingNode } from "./zod-converter";
6
7
 
7
8
  /**
8
9
  * 엔티티의 특정 subset을 RenderingNode로 변환합니다.
9
10
  * subset의 필드들을 Zod 타입으로 변환한 후 UI 렌더링용 노드로 만듭니다.
10
11
  * object와 array의 경우 적절한 pick 필드를 자동으로 선택합니다.
11
12
  */
12
- export async function getColumnsNode(
13
- entityId: string,
14
- subsetKey: string
15
- ): Promise<RenderingNode> {
13
+ export async function getColumnsNode(entityId: string, subsetKey: string): Promise<RenderingNode> {
16
14
  const entity = EntityManager.get(entityId);
17
15
  const subset = entity.subsets[subsetKey];
18
16
  if (subset === undefined) {
@@ -24,16 +22,15 @@ export async function getColumnsNode(
24
22
  children: propNodes,
25
23
  };
26
24
 
27
- const columnsZodType = (await propNodeToZodType(
28
- rootPropNode
29
- )) as z.ZodObject<any>;
25
+ // biome-ignore lint/suspicious/noExplicitAny: zod 스키마를 로드할 때 사용하는 타입
26
+ const columnsZodType = (await propNodeToZodType(rootPropNode)) as z.ZodObject<any>;
30
27
 
31
28
  const columnsNode = zodTypeToRenderingNode(columnsZodType);
32
- columnsNode.children = columnsNode.children!.map((child) => {
29
+ assert(columnsNode.children !== undefined, "columnsNode.children is undefined");
30
+ columnsNode.children = columnsNode.children.map((child) => {
33
31
  if (child.renderType === "object") {
34
- const pickedCol = child.children!.find((cc) =>
35
- ["title", "name"].includes(cc.name)
36
- );
32
+ assert(child.children !== undefined, "child.children is undefined");
33
+ const pickedCol = child.children.find((cc) => ["title", "name"].includes(cc.name));
37
34
  if (pickedCol) {
38
35
  return {
39
36
  ...child,
@@ -50,9 +47,7 @@ export async function getColumnsNode(
50
47
  child.element &&
51
48
  child.element.renderType === "object"
52
49
  ) {
53
- const pickedCol = child.element!.children!.find((cc) =>
54
- ["title", "name"].includes(cc.name)
55
- );
50
+ const pickedCol = child.element?.children?.find((cc) => ["title", "name"].includes(cc.name));
56
51
  if (pickedCol) {
57
52
  return {
58
53
  ...child,
@@ -78,9 +73,7 @@ export async function getColumnsNode(
78
73
  * EntityPropNode를 Zod 타입으로 변환합니다.
79
74
  * plain, array, object 세 가지 nodeType을 재귀적으로 처리합니다.
80
75
  */
81
- export async function propNodeToZodType(
82
- propNode: EntityPropNode
83
- ): Promise<z.ZodTypeAny> {
76
+ export async function propNodeToZodType(propNode: EntityPropNode): Promise<z.ZodTypeAny> {
84
77
  if (propNode.nodeType === "plain") {
85
78
  return propToZodType(propNode.prop);
86
79
  } else if (propNode.nodeType === "array") {
@@ -102,15 +95,13 @@ export async function propNodeToZodType(
102
95
  }
103
96
  }
104
97
  } else if (propNode.nodeType === "object") {
105
- const obj = await propNode.children.reduce(
106
- async (promise, childPropNode) => {
107
- const result = await promise;
108
- result[childPropNode.prop!.name] =
109
- await propNodeToZodType(childPropNode);
110
- return result;
111
- },
112
- {} as any
98
+ const entries = await Promise.all(
99
+ propNode.children.map(async (childPropNode) => {
100
+ assert(childPropNode.prop?.name !== undefined, "childPropNode.prop.name is undefined");
101
+ return [childPropNode.prop.name, await propNodeToZodType(childPropNode)] as const;
102
+ }),
113
103
  );
104
+ const obj = Object.fromEntries(entries);
114
105
 
115
106
  if (propNode.prop?.nullable === true) {
116
107
  return z.object(obj).nullable();