sonamu 0.5.6 → 0.6.0

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 (365) hide show
  1. package/dist/api/base-frame.js +12 -2
  2. package/dist/api/caster.js +66 -2
  3. package/dist/api/code-converters.js +489 -2
  4. package/dist/api/config.d.ts +76 -0
  5. package/dist/api/config.d.ts.map +1 -0
  6. package/dist/api/config.js +32 -0
  7. package/dist/api/context.d.ts +1 -0
  8. package/dist/api/context.d.ts.map +1 -1
  9. package/dist/api/context.js +3 -2
  10. package/dist/api/decorators.d.ts +1 -0
  11. package/dist/api/decorators.d.ts.map +1 -1
  12. package/dist/api/decorators.js +142 -2
  13. package/dist/api/index.js +9 -2
  14. package/dist/api/sonamu.d.ts +8 -22
  15. package/dist/api/sonamu.d.ts.map +1 -1
  16. package/dist/api/sonamu.js +482 -2
  17. package/dist/bin/build-config.d.ts +2 -1
  18. package/dist/bin/build-config.d.ts.map +1 -1
  19. package/dist/bin/build-config.js +12 -2
  20. package/dist/bin/cli-wrapper.js +71 -2
  21. package/dist/bin/cli.js +418 -2
  22. package/dist/bin/hot-hook-register.d.ts +11 -0
  23. package/dist/bin/hot-hook-register.d.ts.map +1 -0
  24. package/dist/bin/hot-hook-register.js +21 -0
  25. package/dist/database/_batch_update.js +78 -2
  26. package/dist/database/base-model.js +247 -2
  27. package/dist/database/code-generator.js +53 -2
  28. package/dist/database/db.d.ts +5 -16
  29. package/dist/database/db.d.ts.map +1 -1
  30. package/dist/database/db.js +132 -2
  31. package/dist/database/knex-plugins/knex-on-duplicate-update.js +39 -2
  32. package/dist/database/puri-wrapper.d.ts +22 -10
  33. package/dist/database/puri-wrapper.d.ts.map +1 -1
  34. package/dist/database/puri-wrapper.js +109 -2
  35. package/dist/database/puri.d.ts +105 -73
  36. package/dist/database/puri.d.ts.map +1 -1
  37. package/dist/database/puri.js +539 -2
  38. package/dist/database/puri.types.d.ts +33 -42
  39. package/dist/database/puri.types.d.ts.map +1 -1
  40. package/dist/database/puri.types.js +3 -2
  41. package/dist/database/transaction-context.d.ts +3 -3
  42. package/dist/database/transaction-context.d.ts.map +1 -1
  43. package/dist/database/transaction-context.js +14 -2
  44. package/dist/database/upsert-builder.js +215 -2
  45. package/dist/entity/entity-manager.d.ts +3 -1
  46. package/dist/entity/entity-manager.d.ts.map +1 -1
  47. package/dist/entity/entity-manager.js +114 -2
  48. package/dist/entity/entity-utils.js +210 -2
  49. package/dist/entity/entity.d.ts.map +1 -1
  50. package/dist/entity/entity.js +651 -2
  51. package/dist/exceptions/error-handler.js +29 -2
  52. package/dist/exceptions/so-exceptions.js +85 -2
  53. package/dist/file-storage/driver.js +79 -2
  54. package/dist/file-storage/file-storage.js +75 -2
  55. package/dist/index.d.ts +2 -0
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +28 -2
  58. package/dist/migration/code-generation.js +558 -2
  59. package/dist/migration/migration-set.js +364 -2
  60. package/dist/migration/migrator.d.ts +0 -9
  61. package/dist/migration/migrator.d.ts.map +1 -1
  62. package/dist/migration/migrator.js +510 -2
  63. package/dist/migration/types.js +3 -2
  64. package/dist/naite/naite.d.ts +12 -0
  65. package/dist/naite/naite.d.ts.map +1 -0
  66. package/dist/naite/naite.js +72 -0
  67. package/dist/stream/index.js +3 -2
  68. package/dist/stream/sse.js +38 -2
  69. package/dist/syncer/api-parser.d.ts +20 -0
  70. package/dist/syncer/api-parser.d.ts.map +1 -0
  71. package/dist/syncer/api-parser.js +229 -0
  72. package/dist/syncer/checksum.d.ts +21 -0
  73. package/dist/syncer/checksum.d.ts.map +1 -0
  74. package/dist/syncer/checksum.js +98 -0
  75. package/dist/syncer/code-generator.d.ts +20 -0
  76. package/dist/syncer/code-generator.d.ts.map +1 -0
  77. package/dist/syncer/code-generator.js +141 -0
  78. package/dist/syncer/entity-operations.d.ts +17 -0
  79. package/dist/syncer/entity-operations.d.ts.map +1 -0
  80. package/dist/syncer/entity-operations.js +58 -0
  81. package/dist/syncer/file-patterns.d.ts +29 -0
  82. package/dist/syncer/file-patterns.d.ts.map +1 -0
  83. package/dist/syncer/file-patterns.js +38 -0
  84. package/dist/syncer/index.d.ts +6 -0
  85. package/dist/syncer/index.d.ts.map +1 -1
  86. package/dist/syncer/index.js +9 -2
  87. package/dist/syncer/module-loader.d.ts +35 -0
  88. package/dist/syncer/module-loader.d.ts.map +1 -0
  89. package/dist/syncer/module-loader.js +82 -0
  90. package/dist/syncer/syncer.d.ts +93 -108
  91. package/dist/syncer/syncer.d.ts.map +1 -1
  92. package/dist/syncer/syncer.js +375 -2
  93. package/dist/template/entity-converter.d.ts +14 -0
  94. package/dist/template/entity-converter.d.ts.map +1 -0
  95. package/dist/template/entity-converter.js +101 -0
  96. package/dist/template/helpers.d.ts +23 -0
  97. package/dist/template/helpers.d.ts.map +1 -0
  98. package/dist/template/helpers.js +64 -0
  99. package/dist/{templates → template/implementations}/entity.template.d.ts +3 -3
  100. package/dist/template/implementations/entity.template.d.ts.map +1 -0
  101. package/dist/template/implementations/entity.template.js +87 -0
  102. package/dist/{templates → template/implementations}/generated.template.d.ts +3 -3
  103. package/dist/template/implementations/generated.template.d.ts.map +1 -0
  104. package/dist/template/implementations/generated.template.js +232 -0
  105. package/dist/{templates → template/implementations}/generated_http.template.d.ts +3 -3
  106. package/dist/template/implementations/generated_http.template.d.ts.map +1 -0
  107. package/dist/template/implementations/generated_http.template.js +131 -0
  108. package/dist/{templates → template/implementations}/generated_sso.template.d.ts +3 -3
  109. package/dist/template/implementations/generated_sso.template.d.ts.map +1 -0
  110. package/dist/template/implementations/generated_sso.template.js +105 -0
  111. package/dist/{templates → template/implementations}/init_types.template.d.ts +3 -3
  112. package/dist/template/implementations/init_types.template.d.ts.map +1 -0
  113. package/dist/template/implementations/init_types.template.js +38 -0
  114. package/dist/template/implementations/model.template.d.ts +17 -0
  115. package/dist/template/implementations/model.template.d.ts.map +1 -0
  116. package/dist/template/implementations/model.template.js +171 -0
  117. package/dist/{templates → template/implementations}/model_test.template.d.ts +3 -3
  118. package/dist/template/implementations/model_test.template.d.ts.map +1 -0
  119. package/dist/template/implementations/model_test.template.js +35 -0
  120. package/dist/{templates → template/implementations}/service.template.d.ts +6 -6
  121. package/dist/template/implementations/service.template.d.ts.map +1 -0
  122. package/dist/template/implementations/service.template.js +193 -0
  123. package/dist/{templates → template/implementations}/view_enums_buttonset.template.d.ts +3 -3
  124. package/dist/template/implementations/view_enums_buttonset.template.d.ts.map +1 -0
  125. package/dist/template/implementations/view_enums_buttonset.template.js +31 -0
  126. package/dist/{templates → template/implementations}/view_enums_dropdown.template.d.ts +3 -4
  127. package/dist/template/implementations/view_enums_dropdown.template.d.ts.map +1 -0
  128. package/dist/template/implementations/view_enums_dropdown.template.js +50 -0
  129. package/dist/{templates → template/implementations}/view_enums_select.template.d.ts +3 -3
  130. package/dist/template/implementations/view_enums_select.template.d.ts.map +1 -0
  131. package/dist/template/implementations/view_enums_select.template.js +55 -0
  132. package/dist/{templates → template/implementations}/view_form.template.d.ts +5 -5
  133. package/dist/template/implementations/view_form.template.d.ts.map +1 -0
  134. package/dist/template/implementations/view_form.template.js +337 -0
  135. package/dist/{templates → template/implementations}/view_id_all_select.template.d.ts +3 -3
  136. package/dist/template/implementations/view_id_all_select.template.d.ts.map +1 -0
  137. package/dist/template/implementations/view_id_all_select.template.js +31 -0
  138. package/dist/{templates → template/implementations}/view_id_async_select.template.d.ts +3 -3
  139. package/dist/template/implementations/view_id_async_select.template.d.ts.map +1 -0
  140. package/dist/template/implementations/view_id_async_select.template.js +105 -0
  141. package/dist/{templates → template/implementations}/view_list.template.d.ts +5 -13
  142. package/dist/template/implementations/view_list.template.d.ts.map +1 -0
  143. package/dist/template/implementations/view_list.template.js +465 -0
  144. package/dist/{templates → template/implementations}/view_list_columns.template.d.ts +3 -3
  145. package/dist/template/implementations/view_list_columns.template.d.ts.map +1 -0
  146. package/dist/template/implementations/view_list_columns.template.js +49 -0
  147. package/dist/{templates → template/implementations}/view_search_input.template.d.ts +3 -3
  148. package/dist/template/implementations/view_search_input.template.d.ts.map +1 -0
  149. package/dist/template/implementations/view_search_input.template.js +64 -0
  150. package/dist/template/index.d.ts +5 -0
  151. package/dist/template/index.d.ts.map +1 -0
  152. package/dist/template/index.js +6 -0
  153. package/dist/template/template.d.ts +39 -0
  154. package/dist/template/template.d.ts.map +1 -0
  155. package/dist/template/template.js +47 -0
  156. package/dist/template/zod-converter.d.ts +18 -0
  157. package/dist/template/zod-converter.d.ts.map +1 -0
  158. package/dist/template/zod-converter.js +166 -0
  159. package/dist/testing/_relation-graph.js +80 -2
  160. package/dist/testing/fixture-manager.d.ts.map +1 -1
  161. package/dist/testing/fixture-manager.js +521 -2
  162. package/dist/types/types.d.ts +39 -40
  163. package/dist/types/types.d.ts.map +1 -1
  164. package/dist/types/types.js +289 -2
  165. package/dist/typings/knex.d.js +3 -2
  166. package/dist/utils/async-utils.d.ts +7 -0
  167. package/dist/utils/async-utils.d.ts.map +1 -1
  168. package/dist/utils/async-utils.js +57 -2
  169. package/dist/utils/console-util.d.ts +2 -0
  170. package/dist/utils/console-util.d.ts.map +1 -0
  171. package/dist/utils/console-util.js +6 -0
  172. package/dist/utils/controller.js +26 -2
  173. package/dist/utils/esm-utils.d.ts +45 -0
  174. package/dist/utils/esm-utils.d.ts.map +1 -0
  175. package/dist/utils/esm-utils.js +56 -0
  176. package/dist/utils/fs-utils.js +17 -2
  177. package/dist/utils/lodash-able.js +6 -2
  178. package/dist/utils/model.js +22 -2
  179. package/dist/utils/path-utils.d.ts +89 -0
  180. package/dist/utils/path-utils.d.ts.map +1 -0
  181. package/dist/utils/path-utils.js +60 -0
  182. package/dist/utils/process-utils.d.ts +13 -0
  183. package/dist/utils/process-utils.d.ts.map +1 -0
  184. package/dist/utils/process-utils.js +36 -0
  185. package/dist/utils/sql-parser.js +35 -2
  186. package/dist/utils/utils.d.ts +4 -7
  187. package/dist/utils/utils.d.ts.map +1 -1
  188. package/dist/utils/utils.js +33 -2
  189. package/dist/utils/zod-error.d.ts.map +1 -1
  190. package/dist/utils/zod-error.js +19 -2
  191. package/package.json +21 -9
  192. package/src/api/code-converters.ts +2 -2
  193. package/src/api/config.ts +142 -0
  194. package/src/api/context.ts +1 -0
  195. package/src/api/decorators.ts +15 -5
  196. package/src/api/sonamu.ts +102 -87
  197. package/src/bin/build-config.ts +2 -1
  198. package/src/bin/cli-wrapper.ts +10 -3
  199. package/src/bin/cli.ts +108 -56
  200. package/src/bin/hot-hook-register.ts +22 -0
  201. package/src/database/base-model.ts +1 -1
  202. package/src/database/code-generator.ts +1 -1
  203. package/src/database/db.ts +53 -60
  204. package/src/database/puri-wrapper.ts +104 -26
  205. package/src/database/puri.ts +477 -580
  206. package/src/database/puri.types.ts +111 -201
  207. package/src/database/transaction-context.ts +4 -4
  208. package/src/database/upsert-builder.ts +1 -1
  209. package/src/entity/entity-manager.ts +19 -15
  210. package/src/entity/entity.ts +4 -3
  211. package/src/index.ts +2 -0
  212. package/src/migration/code-generation.ts +1 -1
  213. package/src/migration/migration-set.ts +1 -1
  214. package/src/migration/migrator.ts +23 -152
  215. package/src/naite/naite.ts +70 -0
  216. package/src/syncer/api-parser.ts +299 -0
  217. package/src/syncer/checksum.ts +152 -0
  218. package/src/syncer/code-generator.ts +202 -0
  219. package/src/syncer/entity-operations.ts +68 -0
  220. package/src/syncer/file-patterns.ts +56 -0
  221. package/src/syncer/index.ts +6 -0
  222. package/src/syncer/module-loader.ts +125 -0
  223. package/src/syncer/syncer.ts +363 -1420
  224. package/src/template/entity-converter.ts +123 -0
  225. package/src/template/helpers.ts +84 -0
  226. package/src/{templates → template/implementations}/entity.template.ts +4 -4
  227. package/src/{templates → template/implementations}/generated.template.ts +9 -9
  228. package/src/{templates → template/implementations}/generated_http.template.ts +9 -6
  229. package/src/{templates → template/implementations}/generated_sso.template.ts +7 -7
  230. package/src/{templates → template/implementations}/init_types.template.ts +4 -4
  231. package/src/{templates → template/implementations}/model.template.ts +9 -9
  232. package/src/{templates → template/implementations}/model_test.template.ts +5 -5
  233. package/src/{templates → template/implementations}/service.template.ts +29 -12
  234. package/src/{templates → template/implementations}/view_enums_buttonset.template.ts +3 -3
  235. package/src/{templates → template/implementations}/view_enums_dropdown.template.ts +5 -21
  236. package/src/{templates → template/implementations}/view_enums_select.template.ts +4 -4
  237. package/src/{templates → template/implementations}/view_form.template.ts +11 -13
  238. package/src/{templates → template/implementations}/view_id_all_select.template.ts +3 -3
  239. package/src/{templates → template/implementations}/view_id_async_select.template.ts +3 -3
  240. package/src/{templates → template/implementations}/view_list.template.ts +13 -64
  241. package/src/{templates → template/implementations}/view_list_columns.template.ts +3 -3
  242. package/src/{templates → template/implementations}/view_search_input.template.ts +3 -3
  243. package/src/template/index.ts +4 -0
  244. package/src/template/template.ts +86 -0
  245. package/src/template/zod-converter.ts +219 -0
  246. package/src/testing/fixture-manager.ts +8 -1
  247. package/src/types/types.ts +39 -62
  248. package/src/utils/async-utils.ts +17 -0
  249. package/src/utils/console-util.ts +4 -0
  250. package/src/utils/esm-utils.ts +69 -0
  251. package/src/utils/path-utils.ts +102 -0
  252. package/src/utils/process-utils.ts +46 -0
  253. package/src/utils/sql-parser.ts +1 -1
  254. package/src/utils/utils.ts +14 -40
  255. package/src/utils/zod-error.ts +0 -1
  256. package/dist/api/base-frame.js.map +0 -1
  257. package/dist/api/caster.js.map +0 -1
  258. package/dist/api/code-converters.js.map +0 -1
  259. package/dist/api/context.js.map +0 -1
  260. package/dist/api/decorators.js.map +0 -1
  261. package/dist/api/index.js.map +0 -1
  262. package/dist/api/sonamu.js.map +0 -1
  263. package/dist/bin/build-config.js.map +0 -1
  264. package/dist/bin/cli-wrapper.js.map +0 -1
  265. package/dist/bin/cli.js.map +0 -1
  266. package/dist/database/_batch_update.js.map +0 -1
  267. package/dist/database/base-model.js.map +0 -1
  268. package/dist/database/code-generator.js.map +0 -1
  269. package/dist/database/db.js.map +0 -1
  270. package/dist/database/knex-plugins/knex-on-duplicate-update.js.map +0 -1
  271. package/dist/database/puri-wrapper.js.map +0 -1
  272. package/dist/database/puri.js.map +0 -1
  273. package/dist/database/puri.types.js.map +0 -1
  274. package/dist/database/transaction-context.js.map +0 -1
  275. package/dist/database/upsert-builder.js.map +0 -1
  276. package/dist/entity/entity-manager.js.map +0 -1
  277. package/dist/entity/entity-utils.js.map +0 -1
  278. package/dist/entity/entity.js.map +0 -1
  279. package/dist/exceptions/error-handler.js.map +0 -1
  280. package/dist/exceptions/so-exceptions.js.map +0 -1
  281. package/dist/file-storage/driver.js.map +0 -1
  282. package/dist/file-storage/file-storage.js.map +0 -1
  283. package/dist/index.js.map +0 -1
  284. package/dist/migration/code-generation.js.map +0 -1
  285. package/dist/migration/migration-set.js.map +0 -1
  286. package/dist/migration/migrator.js.map +0 -1
  287. package/dist/migration/types.js.map +0 -1
  288. package/dist/stream/index.js.map +0 -1
  289. package/dist/stream/sse.js.map +0 -1
  290. package/dist/syncer/index.js.map +0 -1
  291. package/dist/syncer/syncer.js.map +0 -1
  292. package/dist/templates/base-template.d.ts +0 -13
  293. package/dist/templates/base-template.d.ts.map +0 -1
  294. package/dist/templates/base-template.js +0 -2
  295. package/dist/templates/base-template.js.map +0 -1
  296. package/dist/templates/entity.template.d.ts.map +0 -1
  297. package/dist/templates/entity.template.js +0 -2
  298. package/dist/templates/entity.template.js.map +0 -1
  299. package/dist/templates/generated.template.d.ts.map +0 -1
  300. package/dist/templates/generated.template.js +0 -2
  301. package/dist/templates/generated.template.js.map +0 -1
  302. package/dist/templates/generated_http.template.d.ts.map +0 -1
  303. package/dist/templates/generated_http.template.js +0 -2
  304. package/dist/templates/generated_http.template.js.map +0 -1
  305. package/dist/templates/generated_sso.template.d.ts.map +0 -1
  306. package/dist/templates/generated_sso.template.js +0 -2
  307. package/dist/templates/generated_sso.template.js.map +0 -1
  308. package/dist/templates/index.d.ts +0 -2
  309. package/dist/templates/index.d.ts.map +0 -1
  310. package/dist/templates/index.js +0 -2
  311. package/dist/templates/index.js.map +0 -1
  312. package/dist/templates/init_types.template.d.ts.map +0 -1
  313. package/dist/templates/init_types.template.js +0 -2
  314. package/dist/templates/init_types.template.js.map +0 -1
  315. package/dist/templates/model.template.d.ts +0 -17
  316. package/dist/templates/model.template.d.ts.map +0 -1
  317. package/dist/templates/model.template.js +0 -2
  318. package/dist/templates/model.template.js.map +0 -1
  319. package/dist/templates/model_test.template.d.ts.map +0 -1
  320. package/dist/templates/model_test.template.js +0 -2
  321. package/dist/templates/model_test.template.js.map +0 -1
  322. package/dist/templates/service.template.d.ts.map +0 -1
  323. package/dist/templates/service.template.js +0 -2
  324. package/dist/templates/service.template.js.map +0 -1
  325. package/dist/templates/view_enums_buttonset.template.d.ts.map +0 -1
  326. package/dist/templates/view_enums_buttonset.template.js +0 -2
  327. package/dist/templates/view_enums_buttonset.template.js.map +0 -1
  328. package/dist/templates/view_enums_dropdown.template.d.ts.map +0 -1
  329. package/dist/templates/view_enums_dropdown.template.js +0 -2
  330. package/dist/templates/view_enums_dropdown.template.js.map +0 -1
  331. package/dist/templates/view_enums_select.template.d.ts.map +0 -1
  332. package/dist/templates/view_enums_select.template.js +0 -2
  333. package/dist/templates/view_enums_select.template.js.map +0 -1
  334. package/dist/templates/view_form.template.d.ts.map +0 -1
  335. package/dist/templates/view_form.template.js +0 -2
  336. package/dist/templates/view_form.template.js.map +0 -1
  337. package/dist/templates/view_id_all_select.template.d.ts.map +0 -1
  338. package/dist/templates/view_id_all_select.template.js +0 -2
  339. package/dist/templates/view_id_all_select.template.js.map +0 -1
  340. package/dist/templates/view_id_async_select.template.d.ts.map +0 -1
  341. package/dist/templates/view_id_async_select.template.js +0 -2
  342. package/dist/templates/view_id_async_select.template.js.map +0 -1
  343. package/dist/templates/view_list.template.d.ts.map +0 -1
  344. package/dist/templates/view_list.template.js +0 -2
  345. package/dist/templates/view_list.template.js.map +0 -1
  346. package/dist/templates/view_list_columns.template.d.ts.map +0 -1
  347. package/dist/templates/view_list_columns.template.js +0 -2
  348. package/dist/templates/view_list_columns.template.js.map +0 -1
  349. package/dist/templates/view_search_input.template.d.ts.map +0 -1
  350. package/dist/templates/view_search_input.template.js +0 -2
  351. package/dist/templates/view_search_input.template.js.map +0 -1
  352. package/dist/testing/_relation-graph.js.map +0 -1
  353. package/dist/testing/fixture-manager.js.map +0 -1
  354. package/dist/types/types.js.map +0 -1
  355. package/dist/typings/knex.d.js.map +0 -1
  356. package/dist/utils/async-utils.js.map +0 -1
  357. package/dist/utils/controller.js.map +0 -1
  358. package/dist/utils/fs-utils.js.map +0 -1
  359. package/dist/utils/lodash-able.js.map +0 -1
  360. package/dist/utils/model.js.map +0 -1
  361. package/dist/utils/sql-parser.js.map +0 -1
  362. package/dist/utils/utils.js.map +0 -1
  363. package/dist/utils/zod-error.js.map +0 -1
  364. package/src/templates/base-template.ts +0 -19
  365. package/src/templates/index.ts +0 -1
package/src/api/sonamu.ts CHANGED
@@ -4,8 +4,7 @@ import fastify from "fastify";
4
4
  import { readFile } from "fs/promises";
5
5
  import path from "path";
6
6
  import { exists } from "../utils/fs-utils";
7
-
8
- import type { FSWatcher } from "chokidar";
7
+ import chokidar, { type FSWatcher } from "chokidar";
9
8
  import { formatInTimeZone } from "date-fns-tz";
10
9
  import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
11
10
  import type { IncomingMessage, Server, ServerResponse } from "http";
@@ -19,11 +18,7 @@ import {
19
18
  import type { Driver } from "../file-storage/driver";
20
19
  import { createSSEFactory } from "../stream/sse";
21
20
  import type { Syncer } from "../syncer/syncer";
22
- import {
23
- ApiParamType,
24
- SonamuFastifyConfig,
25
- SonamuServerOptions,
26
- } from "../types/types";
21
+ import { ApiParamType, SonamuFastifyConfig } from "../types/types";
27
22
  import { isLocal, isTest } from "../utils/controller";
28
23
  import { findApiRootPath } from "../utils/utils";
29
24
  import { humanizeZodError } from "../utils/zod-error";
@@ -32,23 +27,14 @@ import { getZodObjectFromApi } from "./code-converters";
32
27
  import type { AuthContext, Context, UploadContext } from "./context";
33
28
  import type { ExtendedApi } from "./decorators";
34
29
  import fastifyPassport from "@fastify/passport";
30
+ import { loadConfig, SonamuConfig, SonamuServerOptions } from "./config";
31
+ import { AbsolutePath } from "../utils/path-utils";
32
+ import { isHotReloadServer } from "../utils/esm-utils";
33
+ import { Template } from "../template";
34
+ import assert from "assert";
35
+ import { centerText } from "../utils/console-util";
36
+ import { BaseModel } from "../database/base-model";
35
37
 
36
- export type SonamuConfig = {
37
- projectName?: string;
38
- api: {
39
- dir: string;
40
- };
41
- sync: {
42
- targets: string[];
43
- };
44
- route: {
45
- prefix: string;
46
- };
47
- timezone?: string;
48
- ui?: {
49
- port: number;
50
- };
51
- };
52
38
  export type SonamuSecrets = {
53
39
  [key: string]: string;
54
40
  };
@@ -67,7 +53,19 @@ class SonamuClass {
67
53
  if (store?.context) {
68
54
  return store.context;
69
55
  }
70
- throw new Error("Sonamu cannot find context");
56
+
57
+ if (process.env.NODE_ENV === "test") {
58
+ // 테스팅 환경에서 컨텍스트가 주입되지 않은 경우 빈 컨텍스트 리턴
59
+ return {
60
+ request: null,
61
+ reply: null,
62
+ headers: {},
63
+ createSSE: () => {},
64
+ naiteStore: new Map<string, any>(),
65
+ } as unknown as Context;
66
+ } else {
67
+ throw new Error("Sonamu cannot find context");
68
+ }
71
69
  }
72
70
 
73
71
  public getUploadContext(): UploadContext {
@@ -80,11 +78,11 @@ class SonamuClass {
80
78
  );
81
79
  }
82
80
 
83
- private _apiRootPath: string | null = null;
84
- set apiRootPath(apiRootPath: string) {
81
+ private _apiRootPath: AbsolutePath | null = null;
82
+ set apiRootPath(apiRootPath: AbsolutePath) {
85
83
  this._apiRootPath = apiRootPath;
86
84
  }
87
- get apiRootPath(): string {
85
+ get apiRootPath(): AbsolutePath {
88
86
  if (this._apiRootPath === null) {
89
87
  throw new Error("Sonamu has not been initialized");
90
88
  }
@@ -157,7 +155,7 @@ class SonamuClass {
157
155
  async init(
158
156
  doSilent: boolean = false,
159
157
  enableSync: boolean = true,
160
- apiRootPath?: string,
158
+ apiRootPath?: AbsolutePath,
161
159
  forTesting: boolean = false
162
160
  ) {
163
161
  if (this.isInitialized) {
@@ -170,14 +168,8 @@ class SonamuClass {
170
168
 
171
169
  // API 루트 패스
172
170
  this.apiRootPath = apiRootPath ?? findApiRootPath();
173
- const configPath = path.join(this.apiRootPath, "sonamu.config.json");
171
+ this.config = await loadConfig(this.apiRootPath);
174
172
  const secretsPath = path.join(this.apiRootPath, "sonamu.secrets.json");
175
- if (!(await exists(configPath))) {
176
- throw new Error(`Cannot find sonamu.config.json in ${configPath}`);
177
- }
178
- this.config = JSON.parse(
179
- (await readFile(configPath)).toString()
180
- ) as SonamuConfig;
181
173
  if (await exists(secretsPath)) {
182
174
  this.secrets = JSON.parse(
183
175
  (await readFile(secretsPath)).toString()
@@ -185,7 +177,7 @@ class SonamuClass {
185
177
  }
186
178
 
187
179
  // DB 로드
188
- this.dbConfig = await DB.readKnexfile();
180
+ this.dbConfig = DB.generateDBConfig(this.config.database);
189
181
  !doSilent && console.log(chalk.green("DB Config Loaded!"));
190
182
  attachOnDuplicateUpdate();
191
183
 
@@ -204,14 +196,15 @@ class SonamuClass {
204
196
  this.syncer = new Syncer();
205
197
 
206
198
  // Autoload: Models / Types / APIs
207
- await this.syncer.autoloadModels();
208
199
  await this.syncer.autoloadTypes();
200
+ await this.syncer.autoloadModels();
209
201
  await this.syncer.autoloadApis();
210
202
 
211
- if (isLocal() && !isTest() && enableSync) {
203
+ await Template.autoload();
204
+
205
+ if (isLocal() && !isTest() && isHotReloadServer() && enableSync) {
212
206
  await this.syncer.sync();
213
207
 
214
- // FIXME: hmr 설정된 경우만 워처 시작
215
208
  this.startWatcher();
216
209
 
217
210
  this.syncer.syncUI();
@@ -221,13 +214,15 @@ class SonamuClass {
221
214
  !doSilent && console.timeEnd(chalk.cyan("Sonamu.init"));
222
215
  }
223
216
 
224
- async createServer(
225
- options: SonamuServerOptions,
226
- initOptions?: {
227
- enableSync?: boolean;
228
- doSilent?: boolean;
217
+ async createServer(initOptions?: {
218
+ enableSync?: boolean;
219
+ doSilent?: boolean;
220
+ }) {
221
+ if (this.isInitialized === false) {
222
+ await this.init(initOptions?.doSilent, initOptions?.enableSync);
229
223
  }
230
- ) {
224
+
225
+ const options = this.config.server;
231
226
  const server = fastify(options.fastify);
232
227
  this.server = server;
233
228
 
@@ -278,7 +273,7 @@ class SonamuClass {
278
273
  this.server = server;
279
274
 
280
275
  // timezone 설정
281
- const timezone = this.config.timezone;
276
+ const timezone = this.config.api.timezone;
282
277
  if (timezone) {
283
278
  const DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssXXX";
284
279
  // ISO 8601 날짜 형식 정규식 (예: 2024-01-15T09:30:00.000Z)
@@ -298,7 +293,7 @@ class SonamuClass {
298
293
 
299
294
  // 전체 라우팅 리스트
300
295
  server.get(
301
- `${this.config.route.prefix}/routes`,
296
+ `${this.config.api.route.prefix}/routes`,
302
297
  async (_request, _reply): Promise<any> => {
303
298
  return this.syncer.apis;
304
299
  }
@@ -306,7 +301,7 @@ class SonamuClass {
306
301
 
307
302
  // Healthcheck API
308
303
  server.get(
309
- `${this.config.route.prefix}/healthcheck`,
304
+ `${this.config.api.route.prefix}/healthcheck`,
310
305
  async (_request, _reply): Promise<string> => {
311
306
  return "ok";
312
307
  }
@@ -317,7 +312,8 @@ class SonamuClass {
317
312
  server.all("*", (request, reply) => {
318
313
  const found = this.syncer.apis.find(
319
314
  (api) =>
320
- this.config.route.prefix + api.path === request.url.split("?")[0] &&
315
+ this.config.api.route.prefix + api.path ===
316
+ request.url.split("?")[0] &&
321
317
  (api.options.httpMethod ?? "GET") === request.method.toUpperCase()
322
318
  );
323
319
  if (found) {
@@ -335,7 +331,7 @@ class SonamuClass {
335
331
  // route
336
332
  server.route({
337
333
  method: api.options.httpMethod!,
338
- url: this.config.route.prefix + api.path,
334
+ url: this.config.api.route.prefix + api.path,
339
335
  handler: this.getApiHandler(api, config),
340
336
  }); // END server.route
341
337
  });
@@ -413,27 +409,29 @@ class SonamuClass {
413
409
  );
414
410
 
415
411
  const context: Context = {
416
- ...config.contextProvider(
417
- {
418
- request,
419
- reply,
420
- headers: request.headers,
421
- createSSE,
422
-
423
- // auth
424
- user: request.user ?? null,
425
- passport: {
426
- login: request.login.bind(
427
- request
428
- ) as AuthContext["passport"]["login"],
429
- logout: request.logout.bind(
430
- request
431
- ) as AuthContext["passport"]["logout"],
412
+ ...(await Promise.resolve(
413
+ config.contextProvider(
414
+ {
415
+ request,
416
+ reply,
417
+ headers: request.headers,
418
+ createSSE,
419
+ naiteStore: new Map<string, any>(),
420
+ // auth
421
+ user: request.user ?? null,
422
+ passport: {
423
+ login: request.login.bind(
424
+ request
425
+ ) as AuthContext["passport"]["login"],
426
+ logout: request.logout.bind(
427
+ request
428
+ ) as AuthContext["passport"]["logout"],
429
+ },
432
430
  },
433
- },
434
- request,
435
- reply
436
- ),
431
+ request,
432
+ reply
433
+ )
434
+ )),
437
435
  };
438
436
 
439
437
  const model = this.syncer.models[api.modelName];
@@ -461,24 +459,46 @@ class SonamuClass {
461
459
  }
462
460
 
463
461
  startWatcher(): void {
464
- const watchPath = path.join(this.apiRootPath, "src");
465
- const chokidar = require("chokidar") as typeof import("chokidar");
462
+ const watchPath = [
463
+ path.join(this.apiRootPath, "src"),
464
+ path.join(this.apiRootPath, "sonamu.config.ts"),
465
+ ];
466
+
466
467
  this.watcher = chokidar.watch(watchPath, {
467
468
  ignored: (path, stats) =>
468
- (!!stats?.isFile() &&
469
- !path.endsWith(".ts") &&
470
- !path.endsWith(".json")) ||
471
- path.endsWith("src/index.ts"),
469
+ !!stats?.isFile() && !path.endsWith(".ts") && !path.endsWith(".json"),
472
470
  persistent: true,
473
471
  ignoreInitial: true,
474
472
  });
473
+
475
474
  this.watcher.on("all", async (event: string, filePath: string) => {
475
+ const absolutePath = filePath as AbsolutePath;
476
+ assert(
477
+ absolutePath.startsWith(this.apiRootPath),
478
+ "File path is not within the API root path"
479
+ );
480
+
476
481
  if (event !== "change" && event !== "add") {
477
482
  return;
478
483
  }
479
484
 
480
485
  try {
481
- await this.handleFileChange(event, filePath);
486
+ // sonamu.config.ts 변경 시 재시작
487
+ const isConfigTs =
488
+ filePath === path.join(this.apiRootPath, "sonamu.config.ts");
489
+
490
+ if (isConfigTs) {
491
+ const relativePath = filePath.replace(this.apiRootPath, "api");
492
+ console.log(
493
+ chalk.bold(
494
+ `Detected(${event}): ${chalk.blue(relativePath)} - Restarting...`
495
+ )
496
+ );
497
+ process.kill(process.pid, "SIGUSR2");
498
+ return;
499
+ }
500
+
501
+ await this.handleFileChange(event, absolutePath);
482
502
  } catch (e) {
483
503
  console.error(e);
484
504
  }
@@ -595,19 +615,18 @@ class SonamuClass {
595
615
 
596
616
  private async handleFileChange(
597
617
  event: string,
598
- filePath: string
618
+ filePath: AbsolutePath
599
619
  ): Promise<void> {
600
620
  // 첫 번째 파일이면 HMR 시작 시간 기록
601
621
  if (this.pendingFiles.length === 0) {
602
622
  this.hmrStartTime = Date.now();
603
623
  }
604
-
605
624
  this.pendingFiles.push(filePath);
606
625
 
607
- const relativePath = filePath.replace(this.apiRootPath, "api");
626
+ const relativePath = path.relative(this.apiRootPath, filePath);
608
627
  console.log(chalk.bold(`Detected(${event}): ${chalk.blue(relativePath)}`));
609
628
 
610
- await this.syncer.syncFromWatcher([filePath]);
629
+ await this.syncer.syncFromWatcher(event, filePath);
611
630
 
612
631
  // 처리 완료된 파일을 대기 목록에서 제거
613
632
  this.pendingFiles = this.pendingFiles.slice(1);
@@ -619,20 +638,16 @@ class SonamuClass {
619
638
  }
620
639
 
621
640
  private async finishHMR(): Promise<void> {
622
- await this.syncer.saveChecksums(await this.syncer.getCurrentChecksums());
641
+ await this.syncer.renewChecksums();
623
642
 
624
643
  const endTime = Date.now();
625
644
  const totalTime = endTime - this.hmrStartTime;
626
645
  const msg = `HMR Done! ${chalk.bold.white(`${totalTime}ms`)}`;
627
- const margin = Math.max(0, (process.stdout.columns - msg.length) / 2);
628
646
 
629
- console.log(
630
- chalk.black.bgGreen(" ".repeat(margin) + msg + " ".repeat(margin))
631
- );
647
+ console.log(chalk.black.bgGreen(centerText(msg)));
632
648
  }
633
649
 
634
650
  async destroy(): Promise<void> {
635
- const { BaseModel } = require("../database/base-model");
636
651
  await BaseModel.destroy();
637
652
  await this.watcher?.close();
638
653
  this.storage?.destroy();
@@ -5,8 +5,9 @@ export const BUILD_DIR = "dist";
5
5
 
6
6
  /**
7
7
  * SWC 빌드 명령어
8
+ * .swcrc 설정 사용
8
9
  */
9
- export const SWC_BUILD_COMMAND = `swc src -d ${BUILD_DIR} --strip-leading-paths --source-maps -C module.type=commonjs -C jsc.parser.syntax=typescript -C jsc.parser.decorators=true -C jsc.target=es5`;
10
+ export const SWC_BUILD_COMMAND = `swc src -d ${BUILD_DIR} --strip-leading-paths`;
10
11
 
11
12
  /**
12
13
  * TSC 타입 체크 명령어
@@ -10,7 +10,7 @@ import {
10
10
  TSC_TYPE_CHECK_COMMAND,
11
11
  } from "./build-config";
12
12
 
13
- const scriptPath = resolve(__dirname, "cli.js");
13
+ const scriptPath = resolve(import.meta.dirname, "cli.js");
14
14
  const args = process.argv.slice(2);
15
15
 
16
16
  // build 명령어는 dist 없이도 실행 가능하도록 cli.ts 외부에서 처리(Sonamu.init에서 dist 필요)
@@ -56,7 +56,7 @@ if (args[0] === "build") {
56
56
  }
57
57
 
58
58
  if (args[0] === "dev:serve") {
59
- build();
59
+ // build();
60
60
  }
61
61
 
62
62
  if (!existsSync(scriptPath)) {
@@ -66,7 +66,14 @@ if (!existsSync(scriptPath)) {
66
66
 
67
67
  const result = spawnSync(
68
68
  process.execPath,
69
- ["-r", "source-map-support/register", "--no-warnings", scriptPath, ...args],
69
+ [
70
+ "--import",
71
+ "@sonamu-kit/loader", // Sonamu UI도 syncer를 다루므로, ts 로드 능력이 필요합니다.
72
+ "--enable-source-maps",
73
+ "--no-warnings",
74
+ scriptPath,
75
+ ...args
76
+ ],
70
77
  {
71
78
  stdio: "inherit",
72
79
  }
package/src/bin/cli.ts CHANGED
@@ -3,25 +3,24 @@ import dotenv from "dotenv";
3
3
  dotenv.config();
4
4
 
5
5
  import path from "path";
6
+ import { fileURLToPath } from "url";
6
7
  import { tsicli } from "tsicli";
7
- import { execSync } from "child_process";
8
- import { mkdir, readdir, readFile, writeFile } from "fs/promises";
8
+ import { execSync, spawn } from "child_process";
9
+ import { mkdir, readdir, writeFile } from "fs/promises";
9
10
  import { exists } from "../utils/fs-utils";
10
11
  import process from "process";
11
12
  import { Sonamu } from "../api";
12
13
  import knex, { Knex } from "knex";
13
- import { findApiRootPath } from "../utils/utils";
14
14
  import { EntityManager } from "../entity/entity-manager";
15
15
  import { Migrator } from "../migration/migrator";
16
16
  import { FixtureManager } from "../testing/fixture-manager";
17
- // import { SWC_BUILD_COMMAND } from "./build-config";
18
- import { NodemonSettings } from "nodemon";
17
+ import { findApiRootPath } from "../utils/utils";
19
18
 
20
19
  let migrator: Migrator;
21
20
 
22
21
  async function bootstrap() {
23
- // dev:serve 명령어가 아닌 경우에만 Sonamu 초기화
24
- if (process.argv[2] !== "dev:serve") {
22
+ // dev 명령어가 아닌 경우에만 Sonamu 초기화
23
+ if (process.argv[2] !== "dev") {
25
24
  await Sonamu.init(false, false);
26
25
  }
27
26
 
@@ -56,8 +55,8 @@ async function bootstrap() {
56
55
  ["scaffold", "view_list", "#entityId"],
57
56
  ["scaffold", "view_form", "#entityId"],
58
57
  ["ui"],
59
- ["dev:serve"],
60
- ["serve"],
58
+ ["dev"],
59
+ ["start"],
61
60
  ],
62
61
  runners: {
63
62
  migrate_run,
@@ -76,8 +75,8 @@ async function bootstrap() {
76
75
  ui,
77
76
  // scaffold_view_list,
78
77
  // scaffold_view_form,
79
- "dev:serve": dev_serve,
80
- serve,
78
+ dev,
79
+ start,
81
80
  },
82
81
  });
83
82
  }
@@ -88,45 +87,57 @@ bootstrap().finally(async () => {
88
87
  await FixtureManager.destroy();
89
88
  });
90
89
 
91
- async function dev_serve() {
92
- const nodemon = await import("nodemon");
90
+ async function dev() {
91
+ const apiRoot = findApiRootPath();
92
+ const entryPoint = 'src/index.ts';
93
93
 
94
- const nodemonConfig = await (async () => {
95
- const projectNodemonPath = path.join(findApiRootPath(), "nodemon.json");
96
- const hasProjectNodemon = await exists(projectNodemonPath);
94
+ console.log(chalk.yellow.bold('🚀 Starting Sonamu dev server...\n'));
97
95
 
98
- if (hasProjectNodemon) {
99
- return JSON.parse(await readFile(projectNodemonPath, "utf8"));
96
+ const serverProcess = spawn(
97
+ "hot-runner",
98
+ [
99
+ "--clear-screen=false",
100
+ "--node-args=--import=@sonamu-kit/loader",
101
+ "--node-args=--import=sonamu/hot-hook-register",
102
+ "--node-args=--enable-source-maps",
103
+ entryPoint,
104
+ ],
105
+ {
106
+ cwd: apiRoot,
107
+ stdio: "inherit",
108
+ env: {
109
+ ...process.env,
110
+ NODE_ENV: "development",
111
+ HOT: "yes",
112
+ API_ROOT_PATH: apiRoot,
113
+ },
100
114
  }
115
+ );
101
116
 
102
- return {
103
- watch: ["src/index.ts"],
104
- ignore: ["dist/**", "**/*.js", "**/*.d.ts"],
105
- exec: [
106
- // SWC_BUILD_COMMAND,
107
- "node --no-warnings -r source-map-support/register -r dotenv/config dist/index.js",
108
- ].join(" && "),
109
- } as NodemonSettings;
110
- })();
111
- nodemon.default(nodemonConfig);
112
-
113
- // 프로세스 종료 처리
114
- const cleanup = async () => {
115
- await Sonamu.server?.close();
117
+ // 종료 처리
118
+ const cleanup = () => {
119
+ console.log(chalk.yellow('\n\n👋 Shutting down...'));
120
+ serverProcess.kill('SIGTERM');
116
121
  process.exit(0);
117
122
  };
118
123
 
119
- process.on("SIGINT", cleanup);
120
- process.on("SIGTERM", cleanup);
121
- process.on("SIGUSR2", cleanup);
124
+ process.on('SIGINT', cleanup);
125
+ process.on('SIGTERM', cleanup);
126
+
127
+ serverProcess.on('exit', (code) => {
128
+ if (code !== 0) {
129
+ console.error(chalk.red(`❌ Server exited with code ${code}`));
130
+ process.exit(code || 1);
131
+ }
132
+ });
122
133
  }
123
134
 
124
- async function serve() {
125
- const distIndexPath = path.join(Sonamu.apiRootPath, "dist", "index.js");
135
+ async function start() {
136
+ const entryPoint = 'dist/index.js';
126
137
 
127
- if (!(await exists(distIndexPath))) {
138
+ if (!(await exists(entryPoint))) {
128
139
  console.log(
129
- chalk.red("dist/index.js not found. Please build your project first.")
140
+ chalk.red(`${entryPoint} not found. Please build your project first.`)
130
141
  );
131
142
  console.log(chalk.blue("Run: yarn sonamu build"));
132
143
  return;
@@ -135,7 +146,7 @@ async function serve() {
135
146
  const { spawn } = await import("child_process");
136
147
  const serverProcess = spawn(
137
148
  "node",
138
- ["-r", "source-map-support/register", "-r", "dotenv/config", distIndexPath],
149
+ ["--enable-source-maps", "-r", "dotenv/config", entryPoint],
139
150
  {
140
151
  cwd: Sonamu.apiRootPath,
141
152
  stdio: "inherit",
@@ -162,14 +173,12 @@ async function setupFixtureManager() {
162
173
  async function migrate_run() {
163
174
  await setupMigrator();
164
175
 
165
- await migrator.cleanUpDist();
166
176
  await migrator.run();
167
177
  }
168
178
 
169
179
  async function migrate_check() {
170
180
  await setupMigrator();
171
181
 
172
- await migrator.cleanUpDist();
173
182
  await migrator.check();
174
183
  }
175
184
 
@@ -347,7 +356,7 @@ async function stub_practice(name: string) {
347
356
 
348
357
  execSync(`code ${dstPath}`);
349
358
 
350
- const runCode = `yarn node -r dotenv/config -r source-map-support/register dist/practices/${fileName.replace(
359
+ const runCode = `yarn node -r dotenv/config --enable-source-maps dist/practices/${fileName.replace(
351
360
  ".ts",
352
361
  ".js"
353
362
  )}`;
@@ -373,23 +382,66 @@ async function scaffold_model_test(entityId: string) {
373
382
 
374
383
  async function ui() {
375
384
  try {
376
- type StartServersOptions = {
377
- projectName: string;
378
- apiRootPath: string;
379
- port: number;
385
+ // @sonamu-kit/ui의 run-ui.ts 스크립트 경로 찾기
386
+ const uiModulePath = await import.meta.resolve("@sonamu-kit/ui");
387
+ const uiNodePath = path.join(
388
+ path.dirname(fileURLToPath(uiModulePath)),
389
+ "run-ui.js"
390
+ );
391
+
392
+ if (!(await exists(uiNodePath))) {
393
+ console.log(
394
+ chalk.red(
395
+ `UI runner script not found at ${uiNodePath}. Please rebuild @sonamu-kit/ui.`
396
+ )
397
+ );
398
+ return;
399
+ }
400
+
401
+ // UI를 별도 프로세스로 실행 (hot-hook 활성화)
402
+ const uiProcess = spawn(
403
+ process.execPath,
404
+ [
405
+ "--import", "@sonamu-kit/loader",
406
+ "--import", "sonamu/hot-hook-register",
407
+ "--enable-source-maps",
408
+ "--no-warnings",
409
+ uiNodePath,
410
+ ],
411
+ {
412
+ stdio: "inherit",
413
+ env: {
414
+ ...process.env,
415
+ HOT: "yes",
416
+ PROJECT_NAME:
417
+ Sonamu.config.projectName ?? path.basename(Sonamu.apiRootPath),
418
+ API_ROOT_PATH: Sonamu.apiRootPath,
419
+ UI_PORT: (Sonamu.config.ui?.port ?? 57000).toString(),
420
+ },
421
+ }
422
+ );
423
+
424
+ // 종료 처리
425
+ const cleanup = () => {
426
+ console.log(chalk.yellow("\n\n👋 Shutting down UI server..."));
427
+ uiProcess.kill("SIGTERM");
428
+ process.exit(0);
380
429
  };
381
- const sonamuUI: {
382
- startServers: (options: StartServersOptions) => void;
383
- } = await import("@sonamu-kit/ui" as string);
384
- sonamuUI.startServers({
385
- projectName:
386
- Sonamu.config.projectName ?? path.basename(Sonamu.apiRootPath),
387
- apiRootPath: Sonamu.apiRootPath,
388
- port: Sonamu.config.ui?.port ?? 57000,
430
+
431
+ process.on("SIGINT", cleanup);
432
+ process.on("SIGTERM", cleanup);
433
+
434
+ uiProcess.on("exit", (code) => {
435
+ if (code !== 0) {
436
+ console.error(chalk.red(`❌ UI server exited with code ${code}`));
437
+ process.exit(code || 1);
438
+ }
389
439
  });
390
440
  } catch (e: unknown) {
391
441
  if (e instanceof Error && e.message.includes("isn't declared")) {
392
- console.log(`You need to install ${chalk.blue(`@sonamu-kit/ui`)} first.`);
442
+ console.log(
443
+ `You need to install ${chalk.blue(`@sonamu-kit/ui`)} first.`
444
+ );
393
445
  return;
394
446
  }
395
447
  throw e;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * hot-hook 초기화하는 모듈입니다.
3
+ *
4
+ * 이 파일은 --import 플래그로 프로세스 시작 시 로드되어야 합니다.
5
+ *
6
+ * 환경변수:
7
+ * - API_ROOT_PATH: 사용자 프로젝트의 API 루트 경로
8
+ * - HOT: 'yes'일 때만 hot-hook 활성화
9
+ */
10
+
11
+ if (process.env.HOT === "yes" && process.env.API_ROOT_PATH) {
12
+ const { hot } = await import("@sonamu-kit/hot-hook");
13
+
14
+ await hot.init({
15
+ rootDirectory: process.env.API_ROOT_PATH, // 이 친구가 프로젝트 API 경로로 잘 설정되어야 아래 바운더리가 작동합니다.
16
+ boundaries: [`./src/**/*.ts`], // 프로젝트의 이 친구들이 바운더리가 됩니다.
17
+ });
18
+
19
+ console.log("🔥 Hot-hook initialized");
20
+ }
21
+
22
+ export {};
@@ -1,6 +1,6 @@
1
1
  import { DateTime } from "luxon";
2
2
  import { Knex } from "knex";
3
- import { chunk, groupBy, isObject, omit, set, uniq } from "lodash";
3
+ import { chunk, groupBy, isObject, omit, set, uniq } from "lodash-es";
4
4
  import { DBPreset, DB } from "./db";
5
5
  import { isCustomJoinClause, type SubsetQuery } from "../types/types";
6
6
  import type { BaseListParams } from "../utils/model";