sonamu 0.5.7 → 0.7.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 (529) 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 +13 -2
  39. package/dist/api/caster.d.ts.map +1 -1
  40. package/dist/api/caster.js +71 -2
  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 +258 -2
  44. package/dist/api/config.d.ts +90 -0
  45. package/dist/api/config.d.ts.map +1 -0
  46. package/dist/api/config.js +25 -0
  47. package/dist/api/context.d.ts +4 -2
  48. package/dist/api/context.d.ts.map +1 -1
  49. package/dist/api/context.js +3 -2
  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 +235 -2
  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 +9 -2
  56. package/dist/api/sonamu.d.ts +10 -24
  57. package/dist/api/sonamu.d.ts.map +1 -1
  58. package/dist/api/sonamu.js +514 -2
  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 +6 -1
  63. package/dist/bin/build-config.d.ts.map +1 -1
  64. package/dist/bin/build-config.js +15 -2
  65. package/dist/bin/cli.js +519 -2
  66. package/dist/bin/hot-hook-register.d.ts +11 -0
  67. package/dist/bin/hot-hook-register.d.ts.map +1 -0
  68. package/dist/bin/hot-hook-register.js +21 -0
  69. package/dist/bin/loader-register.d.ts +2 -0
  70. package/dist/bin/loader-register.d.ts.map +1 -0
  71. package/dist/bin/loader-register.js +34 -0
  72. package/dist/database/_batch_update.d.ts +5 -3
  73. package/dist/database/_batch_update.d.ts.map +1 -1
  74. package/dist/database/_batch_update.js +95 -2
  75. package/dist/database/base-model.d.ts +96 -10
  76. package/dist/database/base-model.d.ts.map +1 -1
  77. package/dist/database/base-model.js +390 -2
  78. package/dist/database/base-model.types.d.ts +93 -0
  79. package/dist/database/base-model.types.d.ts.map +1 -0
  80. package/dist/database/base-model.types.js +10 -0
  81. package/dist/database/code-generator.d.ts +1 -1
  82. package/dist/database/code-generator.d.ts.map +1 -1
  83. package/dist/database/code-generator.js +54 -2
  84. package/dist/database/db.d.ts +6 -21
  85. package/dist/database/db.d.ts.map +1 -1
  86. package/dist/database/db.js +129 -2
  87. package/dist/database/puri-subset.test-d.js +81 -0
  88. package/dist/database/puri-subset.types.d.ts +123 -0
  89. package/dist/database/puri-subset.types.d.ts.map +1 -0
  90. package/dist/database/puri-subset.types.js +16 -0
  91. package/dist/database/puri-wrapper.d.ts +13 -11
  92. package/dist/database/puri-wrapper.d.ts.map +1 -1
  93. package/dist/database/puri-wrapper.js +109 -2
  94. package/dist/database/puri.d.ts +41 -23
  95. package/dist/database/puri.d.ts.map +1 -1
  96. package/dist/database/puri.js +601 -2
  97. package/dist/database/puri.types.d.ts +25 -6
  98. package/dist/database/puri.types.d.ts.map +1 -1
  99. package/dist/database/puri.types.js +6 -2
  100. package/dist/database/transaction-context.d.ts +1 -1
  101. package/dist/database/transaction-context.d.ts.map +1 -1
  102. package/dist/database/transaction-context.js +14 -2
  103. package/dist/database/upsert-builder.d.ts +9 -3
  104. package/dist/database/upsert-builder.d.ts.map +1 -1
  105. package/dist/database/upsert-builder.js +365 -2
  106. package/dist/entity/entity-manager.d.ts +167 -2
  107. package/dist/entity/entity-manager.d.ts.map +1 -1
  108. package/dist/entity/entity-manager.js +130 -2
  109. package/dist/entity/entity.d.ts +5 -3
  110. package/dist/entity/entity.d.ts.map +1 -1
  111. package/dist/entity/entity.js +750 -2
  112. package/dist/exceptions/error-handler.d.ts +1 -1
  113. package/dist/exceptions/error-handler.d.ts.map +1 -1
  114. package/dist/exceptions/error-handler.js +29 -2
  115. package/dist/exceptions/so-exceptions.d.ts +1 -1
  116. package/dist/exceptions/so-exceptions.d.ts.map +1 -1
  117. package/dist/exceptions/so-exceptions.js +85 -2
  118. package/dist/file-storage/driver.d.ts +1 -1
  119. package/dist/file-storage/driver.d.ts.map +1 -1
  120. package/dist/file-storage/driver.js +79 -2
  121. package/dist/file-storage/file-storage.js +75 -2
  122. package/dist/index.d.ts +18 -9
  123. package/dist/index.d.ts.map +1 -1
  124. package/dist/index.js +34 -2
  125. package/dist/migration/code-generation.d.ts +1 -1
  126. package/dist/migration/code-generation.d.ts.map +1 -1
  127. package/dist/migration/code-generation.js +614 -2
  128. package/dist/migration/migration-set.d.ts +2 -10
  129. package/dist/migration/migration-set.d.ts.map +1 -1
  130. package/dist/migration/migration-set.js +213 -2
  131. package/dist/migration/migrator.d.ts +24 -82
  132. package/dist/migration/migrator.d.ts.map +1 -1
  133. package/dist/migration/migrator.js +330 -2
  134. package/dist/migration/postgresql-schema-reader.d.ts +51 -0
  135. package/dist/migration/postgresql-schema-reader.d.ts.map +1 -0
  136. package/dist/migration/postgresql-schema-reader.js +245 -0
  137. package/dist/migration/types.d.ts +6 -38
  138. package/dist/migration/types.d.ts.map +1 -1
  139. package/dist/migration/types.js +3 -2
  140. package/dist/naite/messaging-types.d.ts +43 -0
  141. package/dist/naite/messaging-types.d.ts.map +1 -0
  142. package/dist/naite/messaging-types.js +7 -0
  143. package/dist/naite/naite-reporter.d.ts +41 -0
  144. package/dist/naite/naite-reporter.d.ts.map +1 -0
  145. package/dist/naite/naite-reporter.js +102 -0
  146. package/dist/naite/naite.d.ts +95 -0
  147. package/dist/naite/naite.d.ts.map +1 -0
  148. package/dist/naite/naite.js +316 -0
  149. package/dist/stream/index.js +3 -2
  150. package/dist/stream/sse.d.ts +2 -2
  151. package/dist/stream/sse.d.ts.map +1 -1
  152. package/dist/stream/sse.js +38 -2
  153. package/dist/syncer/api-parser.d.ts +10 -0
  154. package/dist/syncer/api-parser.d.ts.map +1 -0
  155. package/dist/syncer/api-parser.js +240 -0
  156. package/dist/syncer/checksum.d.ts +21 -0
  157. package/dist/syncer/checksum.d.ts.map +1 -0
  158. package/dist/syncer/checksum.js +98 -0
  159. package/dist/syncer/code-generator.d.ts +20 -0
  160. package/dist/syncer/code-generator.d.ts.map +1 -0
  161. package/dist/syncer/code-generator.js +161 -0
  162. package/dist/syncer/entity-operations.d.ts +17 -0
  163. package/dist/syncer/entity-operations.d.ts.map +1 -0
  164. package/dist/syncer/entity-operations.js +59 -0
  165. package/dist/syncer/file-patterns.d.ts +29 -0
  166. package/dist/syncer/file-patterns.d.ts.map +1 -0
  167. package/dist/syncer/file-patterns.js +38 -0
  168. package/dist/syncer/index.d.ts +6 -0
  169. package/dist/syncer/index.d.ts.map +1 -1
  170. package/dist/syncer/index.js +9 -2
  171. package/dist/syncer/module-loader.d.ts +35 -0
  172. package/dist/syncer/module-loader.d.ts.map +1 -0
  173. package/dist/syncer/module-loader.js +87 -0
  174. package/dist/syncer/syncer.d.ts +98 -106
  175. package/dist/syncer/syncer.d.ts.map +1 -1
  176. package/dist/syncer/syncer.js +422 -2
  177. package/dist/template/entity-converter.d.ts +14 -0
  178. package/dist/template/entity-converter.d.ts.map +1 -0
  179. package/dist/template/entity-converter.js +108 -0
  180. package/dist/template/helpers.d.ts +23 -0
  181. package/dist/template/helpers.d.ts.map +1 -0
  182. package/dist/template/helpers.js +64 -0
  183. package/dist/{templates → template/implementations}/entity.template.d.ts +3 -3
  184. package/dist/template/implementations/entity.template.d.ts.map +1 -0
  185. package/dist/template/implementations/entity.template.js +86 -0
  186. package/dist/{templates → template/implementations}/generated.template.d.ts +3 -4
  187. package/dist/template/implementations/generated.template.d.ts.map +1 -0
  188. package/dist/template/implementations/generated.template.js +249 -0
  189. package/dist/{templates → template/implementations}/generated_http.template.d.ts +3 -4
  190. package/dist/template/implementations/generated_http.template.d.ts.map +1 -0
  191. package/dist/template/implementations/generated_http.template.js +131 -0
  192. package/dist/{templates → template/implementations}/generated_sso.template.d.ts +4 -5
  193. package/dist/template/implementations/generated_sso.template.d.ts.map +1 -0
  194. package/dist/template/implementations/generated_sso.template.js +134 -0
  195. package/dist/{templates → template/implementations}/init_types.template.d.ts +3 -3
  196. package/dist/template/implementations/init_types.template.d.ts.map +1 -0
  197. package/dist/template/implementations/init_types.template.js +38 -0
  198. package/dist/template/implementations/model.template.d.ts +17 -0
  199. package/dist/template/implementations/model.template.d.ts.map +1 -0
  200. package/dist/template/implementations/model.template.js +181 -0
  201. package/dist/{templates → template/implementations}/model_test.template.d.ts +3 -3
  202. package/dist/template/implementations/model_test.template.d.ts.map +1 -0
  203. package/dist/template/implementations/model_test.template.js +35 -0
  204. package/dist/{templates → template/implementations}/service.template.d.ts +6 -6
  205. package/dist/template/implementations/service.template.d.ts.map +1 -0
  206. package/dist/template/implementations/service.template.js +201 -0
  207. package/dist/{templates → template/implementations}/view_enums_buttonset.template.d.ts +3 -3
  208. package/dist/template/implementations/view_enums_buttonset.template.d.ts.map +1 -0
  209. package/dist/template/implementations/view_enums_buttonset.template.js +31 -0
  210. package/dist/{templates → template/implementations}/view_enums_dropdown.template.d.ts +3 -4
  211. package/dist/template/implementations/view_enums_dropdown.template.d.ts.map +1 -0
  212. package/dist/template/implementations/view_enums_dropdown.template.js +50 -0
  213. package/dist/{templates → template/implementations}/view_enums_select.template.d.ts +3 -3
  214. package/dist/template/implementations/view_enums_select.template.d.ts.map +1 -0
  215. package/dist/template/implementations/view_enums_select.template.js +55 -0
  216. package/dist/{templates → template/implementations}/view_form.template.d.ts +5 -5
  217. package/dist/template/implementations/view_form.template.d.ts.map +1 -0
  218. package/dist/template/implementations/view_form.template.js +337 -0
  219. package/dist/{templates → template/implementations}/view_id_all_select.template.d.ts +3 -3
  220. package/dist/template/implementations/view_id_all_select.template.d.ts.map +1 -0
  221. package/dist/template/implementations/view_id_all_select.template.js +31 -0
  222. package/dist/{templates → template/implementations}/view_id_async_select.template.d.ts +3 -3
  223. package/dist/template/implementations/view_id_async_select.template.d.ts.map +1 -0
  224. package/dist/template/implementations/view_id_async_select.template.js +105 -0
  225. package/dist/{templates → template/implementations}/view_list.template.d.ts +5 -13
  226. package/dist/template/implementations/view_list.template.d.ts.map +1 -0
  227. package/dist/template/implementations/view_list.template.js +475 -0
  228. package/dist/template/implementations/view_list_columns.template.d.ts +17 -0
  229. package/dist/template/implementations/view_list_columns.template.d.ts.map +1 -0
  230. package/dist/template/implementations/view_list_columns.template.js +49 -0
  231. package/dist/{templates → template/implementations}/view_search_input.template.d.ts +3 -3
  232. package/dist/template/implementations/view_search_input.template.d.ts.map +1 -0
  233. package/dist/template/implementations/view_search_input.template.js +64 -0
  234. package/dist/template/index.d.ts +7 -0
  235. package/dist/template/index.d.ts.map +1 -0
  236. package/dist/template/index.js +8 -0
  237. package/dist/template/template-manager.d.ts +56 -0
  238. package/dist/template/template-manager.d.ts.map +1 -0
  239. package/dist/template/template-manager.js +125 -0
  240. package/dist/template/template-types.d.ts +16 -0
  241. package/dist/template/template-types.d.ts.map +1 -0
  242. package/dist/template/template-types.js +7 -0
  243. package/dist/template/template.d.ts +49 -0
  244. package/dist/template/template.d.ts.map +1 -0
  245. package/dist/template/template.js +60 -0
  246. package/dist/template/zod-converter.d.ts +51 -0
  247. package/dist/template/zod-converter.d.ts.map +1 -0
  248. package/dist/template/zod-converter.js +449 -0
  249. package/dist/testing/_relation-graph.d.ts +1 -1
  250. package/dist/testing/_relation-graph.d.ts.map +1 -1
  251. package/dist/testing/_relation-graph.js +89 -2
  252. package/dist/testing/fixture-manager.d.ts +42 -11
  253. package/dist/testing/fixture-manager.d.ts.map +1 -1
  254. package/dist/testing/fixture-manager.js +623 -2
  255. package/dist/types/types.d.ts +747 -143
  256. package/dist/types/types.d.ts.map +1 -1
  257. package/dist/types/types.js +546 -2
  258. package/dist/typings/knex.d.js +3 -2
  259. package/dist/utils/async-utils.d.ts +7 -0
  260. package/dist/utils/async-utils.d.ts.map +1 -1
  261. package/dist/utils/async-utils.js +57 -2
  262. package/dist/utils/console-util.d.ts +2 -0
  263. package/dist/utils/console-util.d.ts.map +1 -0
  264. package/dist/utils/console-util.js +6 -0
  265. package/dist/utils/controller.d.ts +1 -0
  266. package/dist/utils/controller.d.ts.map +1 -1
  267. package/dist/utils/controller.js +29 -2
  268. package/dist/utils/esm-utils.d.ts +39 -0
  269. package/dist/utils/esm-utils.d.ts.map +1 -0
  270. package/dist/utils/esm-utils.js +49 -0
  271. package/dist/utils/formatter.d.ts +3 -0
  272. package/dist/utils/formatter.d.ts.map +1 -0
  273. package/dist/utils/formatter.js +110 -0
  274. package/dist/utils/fs-utils.d.ts +1 -1
  275. package/dist/utils/fs-utils.d.ts.map +1 -1
  276. package/dist/utils/fs-utils.js +17 -2
  277. package/dist/utils/lodash-able.d.ts.map +1 -1
  278. package/dist/utils/lodash-able.js +6 -2
  279. package/dist/utils/model.js +22 -2
  280. package/dist/utils/object-utils.d.ts +44 -0
  281. package/dist/utils/object-utils.d.ts.map +1 -0
  282. package/dist/utils/object-utils.js +191 -0
  283. package/dist/utils/path-utils.d.ts +89 -0
  284. package/dist/utils/path-utils.d.ts.map +1 -0
  285. package/dist/utils/path-utils.js +60 -0
  286. package/dist/utils/process-utils.d.ts +13 -0
  287. package/dist/utils/process-utils.d.ts.map +1 -0
  288. package/dist/utils/process-utils.js +36 -0
  289. package/dist/utils/sql-parser.d.ts +5 -1
  290. package/dist/utils/sql-parser.d.ts.map +1 -1
  291. package/dist/utils/sql-parser.js +46 -2
  292. package/dist/utils/type-utils.d.ts +23 -0
  293. package/dist/utils/type-utils.d.ts.map +1 -0
  294. package/dist/utils/type-utils.js +45 -0
  295. package/dist/utils/utils.d.ts +10 -7
  296. package/dist/utils/utils.d.ts.map +1 -1
  297. package/dist/utils/utils.js +72 -2
  298. package/dist/utils/zod-error.d.ts +1 -1
  299. package/dist/utils/zod-error.d.ts.map +1 -1
  300. package/dist/utils/zod-error.js +19 -2
  301. package/package.json +65 -27
  302. package/src/ai/agents/agent.ts +87 -0
  303. package/src/ai/agents/index.ts +2 -0
  304. package/src/ai/agents/types.ts +47 -0
  305. package/src/ai/index.ts +1 -0
  306. package/src/ai/providers/rtzr/api.ts +37 -0
  307. package/src/ai/providers/rtzr/error.ts +34 -0
  308. package/src/ai/providers/rtzr/index.ts +4 -0
  309. package/src/ai/providers/rtzr/model.ts +201 -0
  310. package/src/ai/providers/rtzr/options.ts +49 -0
  311. package/src/ai/providers/rtzr/provider.ts +91 -0
  312. package/src/ai/providers/rtzr/utils.ts +127 -0
  313. package/src/api/base-frame.ts +4 -2
  314. package/src/api/caster.ts +17 -23
  315. package/src/api/code-converters.ts +178 -535
  316. package/src/api/config.ts +125 -0
  317. package/src/api/context.ts +7 -17
  318. package/src/api/decorators.ts +176 -46
  319. package/src/api/index.ts +2 -2
  320. package/src/api/sonamu.ts +190 -167
  321. package/src/api/validator.ts +83 -0
  322. package/src/bin/build-config.ts +8 -1
  323. package/src/bin/cli.ts +258 -124
  324. package/src/bin/hot-hook-register.ts +22 -0
  325. package/src/bin/loader-register.ts +38 -0
  326. package/src/database/_batch_update.ts +46 -31
  327. package/src/database/base-model.ts +390 -182
  328. package/src/database/base-model.types.ts +155 -0
  329. package/src/database/code-generator.ts +13 -32
  330. package/src/database/db.ts +40 -96
  331. package/src/database/puri-subset.test-d.ts +471 -0
  332. package/src/database/puri-subset.types.ts +195 -0
  333. package/src/database/puri-wrapper.ts +58 -67
  334. package/src/database/puri.ts +229 -148
  335. package/src/database/puri.types.ts +76 -30
  336. package/src/database/transaction-context.ts +1 -1
  337. package/src/database/upsert-builder.ts +262 -132
  338. package/src/entity/entity-manager.ts +48 -36
  339. package/src/entity/entity.ts +330 -248
  340. package/src/exceptions/error-handler.ts +3 -3
  341. package/src/exceptions/so-exceptions.ts +11 -11
  342. package/src/file-storage/driver.ts +5 -5
  343. package/src/file-storage/file-storage.ts +2 -2
  344. package/src/index.ts +18 -10
  345. package/src/migration/code-generation.ts +185 -172
  346. package/src/migration/migration-set.ts +80 -293
  347. package/src/migration/migrator.ts +199 -571
  348. package/src/migration/mysql-schema-reader.ts.txt +272 -0
  349. package/src/migration/postgresql-schema-reader.ts +310 -0
  350. package/src/migration/types.ts +6 -39
  351. package/src/naite/messaging-types.ts +51 -0
  352. package/src/naite/naite-reporter.ts +128 -0
  353. package/src/naite/naite.ts +415 -0
  354. package/src/shared/web.shared.ts.txt +20 -24
  355. package/src/stream/sse.ts +5 -5
  356. package/src/syncer/api-parser.ts +282 -0
  357. package/src/syncer/checksum.ts +140 -0
  358. package/src/syncer/code-generator.ts +198 -0
  359. package/src/syncer/entity-operations.ts +65 -0
  360. package/src/syncer/file-patterns.ts +56 -0
  361. package/src/syncer/index.ts +6 -0
  362. package/src/syncer/module-loader.ts +128 -0
  363. package/src/syncer/syncer.ts +389 -1453
  364. package/src/template/entity-converter.ts +114 -0
  365. package/src/template/helpers.ts +81 -0
  366. package/src/{templates → template/implementations}/entity.template.ts +7 -7
  367. package/src/{templates → template/implementations}/generated.template.ts +101 -101
  368. package/src/{templates → template/implementations}/generated_http.template.ts +27 -57
  369. package/src/template/implementations/generated_sso.template.ts +151 -0
  370. package/src/{templates → template/implementations}/init_types.template.ts +5 -7
  371. package/src/{templates → template/implementations}/model.template.ts +52 -43
  372. package/src/{templates → template/implementations}/model_test.template.ts +5 -5
  373. package/src/{templates → template/implementations}/service.template.ts +66 -82
  374. package/src/{templates → template/implementations}/view_enums_buttonset.template.ts +3 -3
  375. package/src/{templates → template/implementations}/view_enums_dropdown.template.ts +4 -20
  376. package/src/{templates → template/implementations}/view_enums_select.template.ts +4 -4
  377. package/src/{templates → template/implementations}/view_form.template.ts +40 -83
  378. package/src/{templates → template/implementations}/view_id_all_select.template.ts +3 -3
  379. package/src/{templates → template/implementations}/view_id_async_select.template.ts +10 -24
  380. package/src/{templates → template/implementations}/view_list.template.ts +60 -152
  381. package/src/{templates → template/implementations}/view_list_columns.template.ts +5 -11
  382. package/src/{templates → template/implementations}/view_search_input.template.ts +3 -3
  383. package/src/template/index.ts +6 -0
  384. package/src/template/template-manager.ts +166 -0
  385. package/src/template/template-types.ts +16 -0
  386. package/src/template/template.ts +105 -0
  387. package/src/template/zod-converter.ts +525 -0
  388. package/src/testing/_relation-graph.ts +18 -11
  389. package/src/testing/fixture-manager.ts +472 -359
  390. package/src/types/types.ts +553 -308
  391. package/src/typings/knex.d.ts +7 -9
  392. package/src/utils/async-utils.ts +23 -10
  393. package/src/utils/console-util.ts +4 -0
  394. package/src/utils/controller.ts +3 -0
  395. package/src/utils/esm-utils.ts +59 -0
  396. package/src/utils/formatter.ts +109 -0
  397. package/src/utils/fs-utils.ts +1 -1
  398. package/src/utils/lodash-able.ts +1 -4
  399. package/src/utils/object-utils.ts +217 -0
  400. package/src/utils/path-utils.ts +99 -0
  401. package/src/utils/process-utils.ts +46 -0
  402. package/src/utils/sql-parser.ts +23 -5
  403. package/src/utils/type-utils.ts +83 -0
  404. package/src/utils/utils.ts +66 -43
  405. package/src/utils/zod-error.ts +3 -4
  406. package/dist/api/base-frame.js.map +0 -1
  407. package/dist/api/caster.js.map +0 -1
  408. package/dist/api/code-converters.js.map +0 -1
  409. package/dist/api/context.js.map +0 -1
  410. package/dist/api/decorators.js.map +0 -1
  411. package/dist/api/index.js.map +0 -1
  412. package/dist/api/sonamu.js.map +0 -1
  413. package/dist/bin/build-config.js.map +0 -1
  414. package/dist/bin/cli-wrapper.d.ts +0 -3
  415. package/dist/bin/cli-wrapper.d.ts.map +0 -1
  416. package/dist/bin/cli-wrapper.js +0 -3
  417. package/dist/bin/cli-wrapper.js.map +0 -1
  418. package/dist/bin/cli.js.map +0 -1
  419. package/dist/database/_batch_update.js.map +0 -1
  420. package/dist/database/base-model.js.map +0 -1
  421. package/dist/database/code-generator.js.map +0 -1
  422. package/dist/database/db.js.map +0 -1
  423. package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts +0 -2
  424. package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts.map +0 -1
  425. package/dist/database/knex-plugins/knex-on-duplicate-update.js +0 -2
  426. package/dist/database/knex-plugins/knex-on-duplicate-update.js.map +0 -1
  427. package/dist/database/puri-wrapper.js.map +0 -1
  428. package/dist/database/puri.js.map +0 -1
  429. package/dist/database/puri.types.js.map +0 -1
  430. package/dist/database/transaction-context.js.map +0 -1
  431. package/dist/database/upsert-builder.js.map +0 -1
  432. package/dist/entity/entity-manager.js.map +0 -1
  433. package/dist/entity/entity-utils.d.ts +0 -61
  434. package/dist/entity/entity-utils.d.ts.map +0 -1
  435. package/dist/entity/entity-utils.js +0 -2
  436. package/dist/entity/entity-utils.js.map +0 -1
  437. package/dist/entity/entity.js.map +0 -1
  438. package/dist/exceptions/error-handler.js.map +0 -1
  439. package/dist/exceptions/so-exceptions.js.map +0 -1
  440. package/dist/file-storage/driver.js.map +0 -1
  441. package/dist/file-storage/file-storage.js.map +0 -1
  442. package/dist/index.js.map +0 -1
  443. package/dist/migration/code-generation.js.map +0 -1
  444. package/dist/migration/migration-set.js.map +0 -1
  445. package/dist/migration/migrator.js.map +0 -1
  446. package/dist/migration/types.js.map +0 -1
  447. package/dist/stream/index.js.map +0 -1
  448. package/dist/stream/sse.js.map +0 -1
  449. package/dist/syncer/index.js.map +0 -1
  450. package/dist/syncer/syncer.js.map +0 -1
  451. package/dist/templates/base-template.d.ts +0 -13
  452. package/dist/templates/base-template.d.ts.map +0 -1
  453. package/dist/templates/base-template.js +0 -2
  454. package/dist/templates/base-template.js.map +0 -1
  455. package/dist/templates/entity.template.d.ts.map +0 -1
  456. package/dist/templates/entity.template.js +0 -2
  457. package/dist/templates/entity.template.js.map +0 -1
  458. package/dist/templates/generated.template.d.ts.map +0 -1
  459. package/dist/templates/generated.template.js +0 -2
  460. package/dist/templates/generated.template.js.map +0 -1
  461. package/dist/templates/generated_http.template.d.ts.map +0 -1
  462. package/dist/templates/generated_http.template.js +0 -2
  463. package/dist/templates/generated_http.template.js.map +0 -1
  464. package/dist/templates/generated_sso.template.d.ts.map +0 -1
  465. package/dist/templates/generated_sso.template.js +0 -2
  466. package/dist/templates/generated_sso.template.js.map +0 -1
  467. package/dist/templates/index.d.ts +0 -2
  468. package/dist/templates/index.d.ts.map +0 -1
  469. package/dist/templates/index.js +0 -2
  470. package/dist/templates/index.js.map +0 -1
  471. package/dist/templates/init_types.template.d.ts.map +0 -1
  472. package/dist/templates/init_types.template.js +0 -2
  473. package/dist/templates/init_types.template.js.map +0 -1
  474. package/dist/templates/model.template.d.ts +0 -17
  475. package/dist/templates/model.template.d.ts.map +0 -1
  476. package/dist/templates/model.template.js +0 -2
  477. package/dist/templates/model.template.js.map +0 -1
  478. package/dist/templates/model_test.template.d.ts.map +0 -1
  479. package/dist/templates/model_test.template.js +0 -2
  480. package/dist/templates/model_test.template.js.map +0 -1
  481. package/dist/templates/service.template.d.ts.map +0 -1
  482. package/dist/templates/service.template.js +0 -2
  483. package/dist/templates/service.template.js.map +0 -1
  484. package/dist/templates/view_enums_buttonset.template.d.ts.map +0 -1
  485. package/dist/templates/view_enums_buttonset.template.js +0 -2
  486. package/dist/templates/view_enums_buttonset.template.js.map +0 -1
  487. package/dist/templates/view_enums_dropdown.template.d.ts.map +0 -1
  488. package/dist/templates/view_enums_dropdown.template.js +0 -2
  489. package/dist/templates/view_enums_dropdown.template.js.map +0 -1
  490. package/dist/templates/view_enums_select.template.d.ts.map +0 -1
  491. package/dist/templates/view_enums_select.template.js +0 -2
  492. package/dist/templates/view_enums_select.template.js.map +0 -1
  493. package/dist/templates/view_form.template.d.ts.map +0 -1
  494. package/dist/templates/view_form.template.js +0 -2
  495. package/dist/templates/view_form.template.js.map +0 -1
  496. package/dist/templates/view_id_all_select.template.d.ts.map +0 -1
  497. package/dist/templates/view_id_all_select.template.js +0 -2
  498. package/dist/templates/view_id_all_select.template.js.map +0 -1
  499. package/dist/templates/view_id_async_select.template.d.ts.map +0 -1
  500. package/dist/templates/view_id_async_select.template.js +0 -2
  501. package/dist/templates/view_id_async_select.template.js.map +0 -1
  502. package/dist/templates/view_list.template.d.ts.map +0 -1
  503. package/dist/templates/view_list.template.js +0 -2
  504. package/dist/templates/view_list.template.js.map +0 -1
  505. package/dist/templates/view_list_columns.template.d.ts +0 -17
  506. package/dist/templates/view_list_columns.template.d.ts.map +0 -1
  507. package/dist/templates/view_list_columns.template.js +0 -2
  508. package/dist/templates/view_list_columns.template.js.map +0 -1
  509. package/dist/templates/view_search_input.template.d.ts.map +0 -1
  510. package/dist/templates/view_search_input.template.js +0 -2
  511. package/dist/templates/view_search_input.template.js.map +0 -1
  512. package/dist/testing/_relation-graph.js.map +0 -1
  513. package/dist/testing/fixture-manager.js.map +0 -1
  514. package/dist/types/types.js.map +0 -1
  515. package/dist/typings/knex.d.js.map +0 -1
  516. package/dist/utils/async-utils.js.map +0 -1
  517. package/dist/utils/controller.js.map +0 -1
  518. package/dist/utils/fs-utils.js.map +0 -1
  519. package/dist/utils/lodash-able.js.map +0 -1
  520. package/dist/utils/model.js.map +0 -1
  521. package/dist/utils/sql-parser.js.map +0 -1
  522. package/dist/utils/utils.js.map +0 -1
  523. package/dist/utils/zod-error.js.map +0 -1
  524. package/src/bin/cli-wrapper.ts +0 -75
  525. package/src/database/knex-plugins/knex-on-duplicate-update.ts +0 -45
  526. package/src/entity/entity-utils.ts +0 -291
  527. package/src/templates/base-template.ts +0 -19
  528. package/src/templates/generated_sso.template.ts +0 -138
  529. package/src/templates/index.ts +0 -1
@@ -1,19 +1,17 @@
1
- import { Knex } from "knex";
1
+ /** biome-ignore-all lint/correctness/noUnusedImports: d.ts */
2
+ /** biome-ignore-all lint/suspicious/noExplicitAny: d.ts */
3
+ /** biome-ignore-all lint/correctness/noUnusedVariables: d.ts */
4
+
5
+ import type { Knex } from "knex";
2
6
 
3
7
  declare module "knex" {
4
8
  namespace Knex {
5
9
  interface QueryBuilder {
6
- onDuplicateUpdate<TRecord extends {}, TResult>(
7
- ...columns: string[]
8
- ): Knex.QueryBuilder<TRecord, TResult>;
9
-
10
- columnInfo<TRecord>(
11
- column?: keyof TRecord
12
- ): Promise<Knex.ColumnInfo | ColumnInfosObj>;
10
+ columnInfo<TRecord>(column?: keyof TRecord): Promise<Knex.ColumnInfo | ColumnInfosObj>;
13
11
 
14
12
  whereBetween<TRecord, TResult>(
15
13
  columnName: string,
16
- range: readonly [any, any]
14
+ range: readonly [any, any],
17
15
  ): Knex.QueryBuilder;
18
16
  }
19
17
 
@@ -1,3 +1,6 @@
1
+ import { glob } from "fs/promises";
2
+ import path from "path";
3
+
1
4
  /**
2
5
  * 비동기 조건으로 배열을 필터링합니다
3
6
  * @example
@@ -5,12 +8,10 @@
5
8
  */
6
9
  export async function filterAsync<T>(
7
10
  arr: T[],
8
- predicate: (item: T, index: number, array: T[]) => Promise<boolean>
11
+ predicate: (item: T, index: number, array: T[]) => Promise<boolean>,
9
12
  ): Promise<T[]> {
10
13
  const results = await Promise.all(
11
- arr.map((item, index) =>
12
- predicate(item, index, arr).then((keep) => ({ item, keep }))
13
- )
14
+ arr.map((item, index) => predicate(item, index, arr).then((keep) => ({ item, keep }))),
14
15
  );
15
16
  return results.filter((r) => r.keep).map((r) => r.item);
16
17
  }
@@ -22,7 +23,7 @@ export async function filterAsync<T>(
22
23
  */
23
24
  export async function everyAsync<T>(
24
25
  arr: T[],
25
- predicate: (item: T, index: number, array: T[]) => Promise<boolean>
26
+ predicate: (item: T, index: number, array: T[]) => Promise<boolean>,
26
27
  ): Promise<boolean> {
27
28
  for (let i = 0; i < arr.length; i++) {
28
29
  if (!(await predicate(arr[i], i, arr))) {
@@ -39,11 +40,9 @@ export async function everyAsync<T>(
39
40
  */
40
41
  export async function mapAsync<T, U>(
41
42
  arr: T[],
42
- mapper: (item: T, index: number, array: T[]) => Promise<U>
43
+ mapper: (item: T, index: number, array: T[]) => Promise<U>,
43
44
  ): Promise<U[]> {
44
- return Promise.all(
45
- arr.map((item, index) => mapper(item, index, arr))
46
- );
45
+ return Promise.all(arr.map((item, index) => mapper(item, index, arr)));
47
46
  }
48
47
 
49
48
  /**
@@ -54,7 +53,7 @@ export async function mapAsync<T, U>(
54
53
  export async function reduceAsync<T, U>(
55
54
  arr: T[],
56
55
  reducer: (accumulator: U, currentValue: T, index: number, array: T[]) => Promise<U>,
57
- initialValue: U
56
+ initialValue: U,
58
57
  ): Promise<U> {
59
58
  let accumulator = initialValue;
60
59
  for (let i = 0; i < arr.length; i++) {
@@ -62,3 +61,17 @@ export async function reduceAsync<T, U>(
62
61
  }
63
62
  return accumulator;
64
63
  }
64
+
65
+ /**
66
+ * 비동기 glob 함수입니다.
67
+ * AsyncIterableIterator로 날아오는 glob의 반환을 받아 끝까지 돌아서 배열로 반환합니다.
68
+ * @param pathPattern
69
+ * @returns
70
+ */
71
+ export async function globAsync(pathPattern: string): Promise<string[]> {
72
+ const files: string[] = [];
73
+ for await (const file of glob(path.resolve(pathPattern))) {
74
+ files.push(file);
75
+ }
76
+ return files;
77
+ }
@@ -0,0 +1,4 @@
1
+ export function centerText(text: string): string {
2
+ const margin = (process.stdout.columns - text.length) / 2;
3
+ return " ".repeat(margin) + text + " ".repeat(margin);
4
+ }
@@ -22,3 +22,6 @@ export function isProduction(): boolean {
22
22
  export function isTest(): boolean {
23
23
  return isLocal() && process.env.NODE_ENV === "test";
24
24
  }
25
+ export function isHotReloadServer(): boolean {
26
+ return process.env.HOT === "yes";
27
+ }
@@ -0,0 +1,59 @@
1
+ import { dirname } from "path";
2
+ import { fileURLToPath, pathToFileURL } from "url";
3
+
4
+ /**
5
+ * import.meta.url로부터 __filename 생성
6
+ *
7
+ * @example
8
+ * const __filename = getFilename(import.meta.url);
9
+ */
10
+ export function getFilename(metaUrl: string): string {
11
+ return fileURLToPath(metaUrl);
12
+ }
13
+
14
+ /**
15
+ * import.meta.url로부터 __dirname 생성
16
+ *
17
+ * @example
18
+ * const __dirname = getDirname(import.meta.url);
19
+ */
20
+ export function getDirname(metaUrl: string): string {
21
+ return dirname(fileURLToPath(metaUrl));
22
+ }
23
+
24
+ /**
25
+ * 절대 경로를 file:// URL로 변환 (동적 임포트용)
26
+ *
27
+ * @param absolutePath - 절대 파일 경로
28
+ * @returns file:// URL 문자열
29
+ *
30
+ * @example
31
+ * const url = createImportUrl('/path/to/file.js');
32
+ * await import(url);
33
+ */
34
+ export function createImportUrl(absolutePath: string): string {
35
+ const fileUrl = pathToFileURL(absolutePath).href;
36
+ return fileUrl;
37
+ }
38
+
39
+ /**
40
+ * 캐시를 무시하고 새로 임포트(cache busting)하는데, 이때 가져온 모듈의 exported members들을 배열로 가져옵니다.
41
+ *
42
+ * 가령 모듈에서 `export const user = { id: number; name: string; }` 이렇게 정의했다면,
43
+ * 이 함수는 `[{ name: "user", value: { id: number; name: string; } }]` 이렇게 반환합니다.
44
+ *
45
+ * @param filePath
46
+ * @returns { name: string; value: ExportedMemberT }[]
47
+ */
48
+ export async function importMembers<ExportedMemberT>(
49
+ filePath: string,
50
+ ): Promise<{ name: string; value: ExportedMemberT }[]> {
51
+ const imported = await import(createImportUrl(filePath));
52
+
53
+ const allExportedMembers = Object.entries<ExportedMemberT>(imported).map(([name, value]) => ({
54
+ name,
55
+ value,
56
+ }));
57
+
58
+ return allExportedMembers;
59
+ }
@@ -0,0 +1,109 @@
1
+ import { Biome } from "@biomejs/js-api/nodejs";
2
+ import { Naite } from "../naite/naite";
3
+ import { isTest } from "./controller";
4
+
5
+ const biome = new Biome();
6
+ let projectKey: number = -1;
7
+
8
+ export function setupBiome(path: string) {
9
+ if (projectKey !== -1) {
10
+ return;
11
+ }
12
+
13
+ projectKey = biome.openProject(path).projectKey;
14
+ biome.applyConfiguration(projectKey, {
15
+ formatter: {
16
+ enabled: true,
17
+ formatWithErrors: false,
18
+ indentStyle: "space",
19
+ indentWidth: 2,
20
+ lineEnding: "lf",
21
+ lineWidth: 100,
22
+ attributePosition: "auto",
23
+ },
24
+ linter: {
25
+ enabled: true,
26
+ rules: {
27
+ recommended: true,
28
+ style: {
29
+ useNodejsImportProtocol: "off",
30
+ },
31
+ correctness: {
32
+ useParseIntRadix: "off",
33
+ noEmptyPattern: "off",
34
+ noUnusedImports: {
35
+ level: "warn",
36
+ fix: "safe",
37
+ },
38
+ },
39
+ a11y: {
40
+ noLabelWithoutControl: "off",
41
+ },
42
+ complexity: {
43
+ noBannedTypes: "off",
44
+ },
45
+ suspicious: {
46
+ noArrayIndexKey: "off",
47
+ },
48
+ },
49
+ },
50
+ javascript: {
51
+ formatter: {
52
+ jsxQuoteStyle: "double",
53
+ quoteProperties: "asNeeded",
54
+ trailingCommas: "all",
55
+ semicolons: "always",
56
+ arrowParentheses: "always",
57
+ bracketSpacing: true,
58
+ bracketSameLine: false,
59
+ quoteStyle: "double",
60
+ attributePosition: "auto",
61
+ },
62
+ },
63
+ json: {
64
+ formatter: {
65
+ indentWidth: 2,
66
+ },
67
+ },
68
+ assist: {
69
+ enabled: true,
70
+ actions: {
71
+ source: {
72
+ organizeImports: "on",
73
+ },
74
+ },
75
+ },
76
+ });
77
+ }
78
+
79
+ export function formatCode(code: string, parser: "typescript" | "json", filePath: string) {
80
+ Naite.t("formatCode", { code, parser });
81
+
82
+ if (projectKey === -1) {
83
+ console.warn("Biome is not setup. Please call setupBiome first.");
84
+ return code;
85
+ }
86
+
87
+ // 포맷팅을 먼저 해야함
88
+ const formatted = biome.formatContent(projectKey, code, { filePath });
89
+ Naite.t("formatCode:formatted", formatted);
90
+ if (formatted.diagnostics.filter((d) => d.severity === "error").length > 0) {
91
+ console.error(formatted.diagnostics);
92
+ throw new Error("Biome format error");
93
+ }
94
+
95
+ // 린팅을 그 다음에
96
+ const linted = biome.lintContent(projectKey, formatted.content, {
97
+ filePath,
98
+ fixFileMode: "safeAndUnsafeFixes",
99
+ });
100
+ if (linted.diagnostics.filter((d) => d.severity === "error").length > 0) {
101
+ Naite.t("formatCode:linted:content", linted.content);
102
+ Naite.t("formatCode:linted:diagnostics", linted.diagnostics);
103
+ !isTest() && console.dir(linted.diagnostics, { depth: null });
104
+ throw new Error("Biome lint error");
105
+ }
106
+ Naite.t("formatCode:linted", linted);
107
+
108
+ return linted.content;
109
+ }
@@ -1,4 +1,4 @@
1
- import { PathLike, constants } from "fs";
1
+ import { constants, type PathLike } from "fs";
2
2
  import { access } from "fs/promises";
3
3
 
4
4
  /**
@@ -1,7 +1,4 @@
1
- export function wrapIf(
2
- source: string,
3
- predicate: (str: string) => [boolean, string]
4
- ): string {
1
+ export function wrapIf(source: string, predicate: (str: string) => [boolean, string]): string {
5
2
  const [ok, wrapped] = predicate(source);
6
3
  return ok ? wrapped : source;
7
4
  }
@@ -0,0 +1,217 @@
1
+ type Primitive = string | number | boolean | null | undefined;
2
+
3
+ type TypedArray =
4
+ | Int8Array
5
+ | Uint8Array
6
+ | Uint8ClampedArray
7
+ | Int16Array
8
+ | Uint16Array
9
+ | Int32Array
10
+ | Uint32Array
11
+ | Float32Array
12
+ | Float64Array
13
+ | BigInt64Array
14
+ | BigUint64Array;
15
+
16
+ type StructuredCloneable = Date | ArrayBuffer | TypedArray;
17
+
18
+ /** 직렬화 불가 타입 (명시적 제외용) */
19
+ type NonSerializable =
20
+ | Function
21
+ | Promise<unknown>
22
+ | RegExp
23
+ | symbol
24
+ // biome-ignore lint/suspicious/noExplicitAny: WeakMap의 제네릭 파라미터
25
+ | WeakMap<any, any>
26
+ // biome-ignore lint/suspicious/noExplicitAny: WeakSet의 제네릭 파라미터
27
+ | WeakSet<any>
28
+ // biome-ignore lint/suspicious/noExplicitAny: WeakRef의 제네릭 파라미터
29
+ | WeakRef<any>;
30
+
31
+ /** 재귀적 직렬화 가능 타입 */
32
+ export type Serializable =
33
+ | Primitive
34
+ | StructuredCloneable
35
+ | SerializableArray
36
+ | SerializableMap
37
+ | SerializableSet
38
+ | SerializableObject;
39
+
40
+ interface SerializableArray extends Array<Serializable> {}
41
+
42
+ interface SerializableMap extends Map<Serializable, Serializable> {}
43
+
44
+ interface SerializableSet extends Set<Serializable> {}
45
+
46
+ interface SerializableObject {
47
+ [key: string]: Serializable;
48
+ }
49
+
50
+ /**
51
+ * 주어진 타입 T가 직렬화 가능한지 검증하는 조건부 타입
52
+ * 직렬화 불가한 값이 포함되어 있으면 never를 반환하여 타입 에러가 발생합니다
53
+ */
54
+ export type AssertSerializable<T> = T extends NonSerializable
55
+ ? never
56
+ : T extends Primitive | StructuredCloneable
57
+ ? T
58
+ : T extends Map<infer K, infer V>
59
+ ? Map<AssertSerializable<K>, AssertSerializable<V>>
60
+ : T extends Set<infer U>
61
+ ? Set<AssertSerializable<U>>
62
+ : T extends Array<infer U>
63
+ ? AssertSerializable<U>[]
64
+ : T extends object
65
+ ? { [K in keyof T]: AssertSerializable<T[K]> }
66
+ : T;
67
+
68
+ export interface SerializableCheckResult {
69
+ valid: boolean;
70
+ reason?: string;
71
+ }
72
+
73
+ /**
74
+ * 값이 Vitest worker/process 간 전달 가능한지 검증합니다.
75
+ * Serializable하다는 것은 결국 message port와 process.send를 통해 전달 가능한 것을 의미합니다.
76
+ *
77
+ * @param value - 검증할 값
78
+ * @param path - 현재 경로 (에러 메시지용, 내부 재귀에서 사용)
79
+ * @param seen - 순환 참조 감지용 WeakSet (내부 재귀에서 사용)
80
+ * @returns 검증 결과 { valid: boolean, reason?: string }
81
+ *
82
+ * @example
83
+ * isSerializable({ a: 1, b: "hello" }) // { valid: true }
84
+ * isSerializable({ fn: () => {} }) // { valid: false, reason: "Function at fn" }
85
+ * isSerializable({ deep: { nested: Promise.resolve() } }) // { valid: false, reason: "Promise at deep.nested" }
86
+ */
87
+ export function isSerializable(
88
+ value: unknown,
89
+ path: string[] = [],
90
+ seen: WeakSet<object> = new WeakSet(),
91
+ ): SerializableCheckResult {
92
+ // typeof null === 'object'이므로 먼저 처리
93
+ if (value === null) {
94
+ return { valid: true };
95
+ }
96
+
97
+ const type = typeof value;
98
+ if (type === "string" || type === "number" || type === "boolean" || type === "undefined") {
99
+ return { valid: true };
100
+ }
101
+ if (type === "bigint") {
102
+ return { valid: true };
103
+ }
104
+
105
+ if (type === "function") {
106
+ return { valid: false, reason: `Function at ${formatPath(path)}` };
107
+ }
108
+ if (type === "symbol") {
109
+ return { valid: false, reason: `Symbol at ${formatPath(path)}` };
110
+ }
111
+
112
+ if (type === "object") {
113
+ const obj = value as object;
114
+
115
+ if (obj instanceof Promise) {
116
+ return { valid: false, reason: `Promise at ${formatPath(path)}` };
117
+ }
118
+
119
+ if (obj instanceof RegExp) {
120
+ return { valid: false, reason: `RegExp at ${formatPath(path)}` };
121
+ }
122
+
123
+ if (obj instanceof WeakMap) {
124
+ return { valid: false, reason: `WeakMap at ${formatPath(path)}` };
125
+ }
126
+ if (obj instanceof WeakSet) {
127
+ return { valid: false, reason: `WeakSet at ${formatPath(path)}` };
128
+ }
129
+ if (typeof WeakRef !== "undefined" && obj instanceof WeakRef) {
130
+ return { valid: false, reason: `WeakRef at ${formatPath(path)}` };
131
+ }
132
+
133
+ // 순환 참조 허용하되 무한루프 방지
134
+ if (seen.has(obj)) {
135
+ return { valid: true };
136
+ }
137
+ seen.add(obj);
138
+
139
+ if (obj instanceof Date) {
140
+ return { valid: true };
141
+ }
142
+ if (obj instanceof ArrayBuffer) {
143
+ return { valid: true };
144
+ }
145
+ if (ArrayBuffer.isView(obj)) {
146
+ return { valid: true };
147
+ }
148
+
149
+ if (obj instanceof Map) {
150
+ let i = 0;
151
+ for (const [k, v] of obj) {
152
+ const keyResult = isSerializable(k, [...path, `Map.key[${i}]`], seen);
153
+ if (!keyResult.valid) return keyResult;
154
+
155
+ const valResult = isSerializable(v, [...path, `Map.value[${i}]`], seen);
156
+ if (!valResult.valid) return valResult;
157
+ i++;
158
+ }
159
+ return { valid: true };
160
+ }
161
+
162
+ if (obj instanceof Set) {
163
+ let i = 0;
164
+ for (const item of obj) {
165
+ const result = isSerializable(item, [...path, `Set[${i}]`], seen);
166
+ if (!result.valid) return result;
167
+ i++;
168
+ }
169
+ return { valid: true };
170
+ }
171
+
172
+ if (Array.isArray(obj)) {
173
+ for (let i = 0; i < obj.length; i++) {
174
+ const result = isSerializable(obj[i], [...path, `[${i}]`], seen);
175
+ if (!result.valid) return result;
176
+ }
177
+ return { valid: true };
178
+ }
179
+
180
+ // Vitest는 Error를 허용하지만 속성은 직렬화 필요
181
+ if (obj instanceof Error) {
182
+ const errorProps = Object.keys(obj).filter((k) => !["name", "message", "stack"].includes(k));
183
+ for (const key of errorProps) {
184
+ const result = isSerializable(
185
+ (obj as unknown as Record<string, unknown>)[key],
186
+ [...path, key],
187
+ seen,
188
+ );
189
+ if (!result.valid) return result;
190
+ }
191
+ return { valid: true };
192
+ }
193
+
194
+ // Object.prototype 또는 null을 프로토타입으로 가지는 경우만 plain object
195
+ const proto = Object.getPrototypeOf(obj);
196
+ if (proto !== Object.prototype && proto !== null) {
197
+ const constructorName = obj.constructor?.name ?? "Unknown";
198
+ return {
199
+ valid: false,
200
+ reason: `Class instance (${constructorName}) at ${formatPath(path)}`,
201
+ };
202
+ }
203
+
204
+ for (const key of Object.keys(obj)) {
205
+ const result = isSerializable((obj as Record<string, unknown>)[key], [...path, key], seen);
206
+ if (!result.valid) return result;
207
+ }
208
+ return { valid: true };
209
+ }
210
+
211
+ return { valid: false, reason: `Unknown type (${type}) at ${formatPath(path)}` };
212
+ }
213
+
214
+ function formatPath(path: string[]): string {
215
+ if (path.length === 0) return "(root)";
216
+ return path.join(".");
217
+ }
@@ -0,0 +1,99 @@
1
+ import { isHotReloadServer, isTest } from "./controller.js";
2
+
3
+ /**
4
+ * API 패키지 내부 상대 경로 (src/ 또는 dist/로 시작)
5
+ *
6
+ * **사용 위치**: API 패키지 내부 파일 참조
7
+ * **예시**:
8
+ * - `"src/application/user/user.model.ts"`
9
+ * - `"dist/application/user/user.model.js"`
10
+ *
11
+ * **기준점**: `Sonamu.apiRootPath` (일반적으로 프로젝트의 `/api` 디렉토리)
12
+ */
13
+ export type ApiRelativePath = `${"src" | "dist"}/${string}` | "sonamu.config.ts";
14
+
15
+ /**
16
+ * 앱 루트 기준 상대 경로 (api/, web/ 등 타겟 디렉토리로 시작)
17
+ *
18
+ * **사용 위치**: 다른 타겟(api, web 등)의 파일 참조
19
+ * **예시**:
20
+ * - `"api/src/application/user/user.model.ts"`
21
+ * - `"web/src/pages/admin/users/index.tsx"`
22
+ * - `"app/dist/index.js"`
23
+ *
24
+ * **기준점**: `Sonamu.appRootPath` (일반적으로 모노레포 루트)
25
+ */
26
+ export type AppRelativePath = `${string}/${"src" | "dist"}/${string}`;
27
+
28
+ /**
29
+ * 시스템 절대 경로 (루트 / 부터 시작)
30
+ *
31
+ * **사용 위치**: 파일시스템 직접 접근, glob 패턴
32
+ * **예시**: `"/Users/potados/Projects/sonamu/api/src/application/user/user.model.ts"`
33
+ *
34
+ * **중요**:
35
+ * - import 시에는 로더가 알아서 src/dist 변환해주므로 어느 경로든 가능
36
+ * - fs 직접 접근 시에는 실제 존재하는 경로를 사용해야 함
37
+ * - Dev: src/*.ts 경로 사용
38
+ * - Prod: dist/*.js 경로 사용
39
+ */
40
+ export type AbsolutePath = `/${string}`;
41
+
42
+ /**
43
+ * 어떤 경로가 들어오든, 현재 실행 환경에 맞는 경로로 바꿔줍니다.
44
+ *
45
+ * "src/application/user/user.model.ts"가 들어왔을 때 개발 모드라면?
46
+ * -> "src/application/user/user.model.ts"
47
+ * "src/application/user/user.model.ts"가 들어왔을 때 배포 모드라면?
48
+ * -> "dist/application/user/user.model.js"
49
+ * "dist/application/user/user.model.js"가 들어왔을 때 개발 모드라면?
50
+ * -> "src/application/user/user.model.ts"
51
+ * "dist/application/user/user.model.js"가 들어왔을 때 배포 모드라면?
52
+ * -> "dist/application/user/user.model.js"
53
+ *
54
+ * "/src/application/user/user.model.ts"가 들어왔을 때 개발 모드라면?
55
+ * -> "/src/application/user/user.model.ts"
56
+ * "/src/application/user/user.model.ts"가 들어왔을 때 배포 모드라면?
57
+ * -> "/dist/application/user/user.model.js"
58
+ * "/dist/application/user/user.model.js"가 들어왔을 때 개발 모드라면?
59
+ * -> "/dist/application/user/user.model.js"
60
+ * "/dist/application/user/user.model.js"가 들어왔을 때 배포 모드라면?
61
+ * -> "/dist/application/user/user.model.js"
62
+ *
63
+ * "/Users/potados/Projects/sonamu/api/src/application/user/user.model.ts"가 들어왔을 때 개발 모드라면?
64
+ * -> "/Users/potados/Projects/sonamu/api/src/application/user/user.model.ts"
65
+ * "/Users/potados/Projects/sonamu/api/src/application/user/user.model.ts"가 들어왔을 때 배포 모드라면?
66
+ * -> "/Users/potados/Projects/sonamu/api/dist/application/user/user.model.js"
67
+ * "/Users/potados/Projects/sonamu/api/dist/application/user/user.model.js"가 들어왔을 때 개발 모드라면?
68
+ * -> "/Users/potados/Projects/sonamu/api/src/application/user/user.model.ts"
69
+ * "/Users/potados/Projects/sonamu/api/dist/application/user/user.model.js"가 들어왔을 때 배포 모드라면?
70
+ * -> "/Users/potados/Projects/sonamu/api/dist/application/user/user.model.js"
71
+ *
72
+ * "src/application/user/user.model.ts?hot=1234567890"가 들어왔을 때 개발 모드라면?
73
+ * -> "src/application/user/user.model.ts?hot=1234567890"
74
+ * "src/application/user/user.model.ts?hot=1234567890"가 들어왔을 때 배포 모드라면?
75
+ * -> "dist/application/user/user.model.js?hot=1234567890"
76
+ * "dist/application/user/user.model.js?hot=1234567890"가 들어왔을 때 개발 모드라면?
77
+ * -> "src/application/user/user.model.ts?hot=1234567890"
78
+ * "dist/application/user/user.model.js?hot=1234567890"가 들어왔을 때 배포 모드라면?
79
+ * -> "dist/application/user/user.model.js?hot=1234567890"
80
+ *
81
+ * "/Users/potados/Projects/sonamu/api/src/application/user/user.model.ts?hot=1234567890"가 들어왔을 때 개발 모드라면?
82
+ * -> "/Users/potados/Projects/sonamu/api/src/application/user/user.model.ts?hot=1234567890"
83
+ * "/Users/potados/Projects/sonamu/api/src/application/user/user.model.ts?hot=1234567890"가 들어왔을 때 배포 모드라면?
84
+ * -> "/Users/potados/Projects/sonamu/api/dist/application/user/user.model.js?hot=1234567890"
85
+ * "/Users/potados/Projects/sonamu/api/dist/application/user/user.model.js?hot=1234567890"가 들어왔을 때 개발 모드라면?
86
+ * -> "/Users/potados/Projects/sonamu/api/src/application/user/user.model.ts?hot=1234567890"
87
+ * "/Users/potados/Projects/sonamu/api/dist/application/user/user.model.js?hot=1234567890"가 들어왔을 때 배포 모드라면?
88
+ * -> "/Users/potados/Projects/sonamu/api/dist/application/user/user.model.js?hot=1234567890"
89
+ *
90
+ * @param anyPath
91
+ * @returns
92
+ */
93
+ export function runtimePath(anyPath: string, isDev: boolean = isHotReloadServer() || isTest()): string {
94
+ if (isDev) {
95
+ return anyPath.replace(/dist\//, "src/").replace(/\.js/, ".ts");
96
+ } else {
97
+ return anyPath.replace(/src\//, "dist/").replace(/\.ts/, ".js");
98
+ }
99
+ }
@@ -0,0 +1,46 @@
1
+ import chalk from "chalk";
2
+ import { setTimeout as setTimeoutPromises } from "timers/promises";
3
+
4
+ /**
5
+ * 주어진 작업을 실행합니다.
6
+ * 주어진 프로세스 이벤트(=시그널)가 발생하였을 때에도 최대 한계(delayBeforeShutdown) 동안 작업을 기다린 후 종료합니다.
7
+ * @param {() => Promise<void>} job - 실행할 작업
8
+ * @param {event: NodeJS.Signals; delayBeforeShutdown: number} options - 옵션
9
+ * @param {NodeJS.Signals} options.event - 프로세스 이벤트
10
+ * @param {number} options.delayBeforeShutdown - 최대 한계 시간
11
+ */
12
+ export async function runWithGracefulShutdown(
13
+ job: () => Promise<void>,
14
+ {
15
+ whenThisHappens: event,
16
+ waitForUpTo: delayBeforeShutdown,
17
+ }: { whenThisHappens: NodeJS.Signals; waitForUpTo: number } = {
18
+ whenThisHappens: "SIGUSR2",
19
+ waitForUpTo: 20000,
20
+ },
21
+ ): Promise<void> {
22
+ let isRunning = true as boolean;
23
+
24
+ const abortController = new AbortController();
25
+ const onEvent = async () => {
26
+ if (!isRunning) {
27
+ process.exit(0);
28
+ }
29
+ console.log(chalk.magentaBright(`wait for syncing done....`));
30
+
31
+ try {
32
+ await setTimeoutPromises(delayBeforeShutdown, "waiting-sync", {
33
+ signal: abortController.signal,
34
+ });
35
+ } catch {}
36
+ console.log(chalk.magentaBright(`Syncing DONE!`));
37
+ process.exit(0);
38
+ };
39
+ process.on(event, onEvent);
40
+
41
+ await job();
42
+
43
+ isRunning = false;
44
+ abortController.abort();
45
+ process.off(event, onEvent);
46
+ }