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
@@ -0,0 +1,125 @@
1
+ import type { FastifyCorsOptions } from "@fastify/cors";
2
+ import type { FastifyFormbodyOptions } from "@fastify/formbody";
3
+ import type { FastifyMultipartOptions } from "@fastify/multipart";
4
+ import type { DeserializeFunction, SerializeFunction } from "@fastify/passport/dist/Authenticator";
5
+ import type { SecureSessionPluginOptions } from "@fastify/secure-session";
6
+ import type { FastifyStaticOptions } from "@fastify/static";
7
+ import type { FastifyInstance, FastifyReply, FastifyRequest, FastifyServerOptions } from "fastify";
8
+ import type { QsPluginOptions } from "fastify-qs";
9
+ import type { SsePluginOptions } from "fastify-sse-v2/lib/types";
10
+ import type { Knex } from "knex";
11
+ import type { Driver } from "../file-storage/driver";
12
+ import type { SonamuFastifyConfig } from "../types/types";
13
+
14
+ export type DatabaseConfig = Omit<Knex.Config, "connection"> & {
15
+ connection?: Knex.PgConnectionConfig;
16
+ };
17
+
18
+ export type SonamuConfig = {
19
+ projectName?: string;
20
+
21
+ api: {
22
+ dir: string;
23
+ route: {
24
+ prefix: string;
25
+ };
26
+ timezone?: string;
27
+ };
28
+ sync: {
29
+ targets: string[]; // "web", "app" 등
30
+ };
31
+ ui?: {
32
+ port: number;
33
+ };
34
+
35
+ database: {
36
+ // 데이터베이스
37
+ database?: "postgresql";
38
+ // 기본 데이터베이스 이름
39
+ name: string;
40
+ // 모든 환경에 적용될 기본 Knex 옵션
41
+ defaultOptions: DatabaseConfig;
42
+ // 환경별 설정
43
+ environments?: {
44
+ development?: DatabaseConfig;
45
+ development_slave?: DatabaseConfig;
46
+ production?: DatabaseConfig;
47
+ production_slave?: DatabaseConfig;
48
+ remote_fixture?: DatabaseConfig;
49
+ };
50
+ };
51
+
52
+ server: SonamuServerOptions;
53
+ };
54
+
55
+ export type SonamuServerOptions = {
56
+ fastify?: FastifyServerOptions;
57
+
58
+ listen?: {
59
+ port: number;
60
+ host?: string;
61
+ };
62
+
63
+ plugins?: {
64
+ cors?: boolean | FastifyCorsOptions;
65
+ formbody?: boolean | FastifyFormbodyOptions;
66
+ multipart?: boolean | FastifyMultipartOptions;
67
+ qs?: boolean | QsPluginOptions;
68
+ sse?: boolean | SsePluginOptions;
69
+ static?: boolean | FastifyStaticOptions;
70
+ session?: boolean | SecureSessionPluginOptions;
71
+
72
+ custom?: (server: FastifyInstance) => void;
73
+ };
74
+
75
+ auth?:
76
+ | boolean
77
+ | {
78
+ userSerializer: SerializeFunction<unknown, unknown>;
79
+ userDeserializer: DeserializeFunction<unknown, unknown>;
80
+ };
81
+
82
+ apiConfig: SonamuFastifyConfig;
83
+
84
+ storage?: Driver;
85
+
86
+ lifecycle?: {
87
+ onStart?: (server: FastifyInstance) => Promise<void> | void;
88
+ onShutdown?: (server: FastifyInstance) => Promise<void> | void;
89
+ onError?: (error: Error, request: FastifyRequest, reply: FastifyReply) => Promise<void> | void;
90
+ };
91
+ };
92
+
93
+ export type SonamuConfigExport = SonamuConfig | Promise<SonamuConfig>;
94
+
95
+ export function defineConfig(config: SonamuConfig): SonamuConfig;
96
+ export function defineConfig(config: Promise<SonamuConfig>): Promise<SonamuConfig>;
97
+ export function defineConfig(config: SonamuConfigExport): SonamuConfigExport {
98
+ return config;
99
+ }
100
+
101
+ /**
102
+ * sonamu.config.ts 파일을 로드합니다.
103
+ * 이 설정 파일은 환경에 따라 다른 경로에 있을 수 있습니다.
104
+ * dist를 빌드하는 환경이라면 dist 바로 아래에 있을 것이고(cli-wrapper.ts에서 빌드),
105
+ * 그렇지 않은 환경이라면 프로젝트 루트에 있을 것입니다.
106
+ *
107
+ * 이 함수는 의도적으로 다른 의존성의 사용을 최대한 배제하였습니다.
108
+ * 이는 실행 초기에 최대한 빠르게 설정을 읽어올 수 있도록 하기 위함입니다.
109
+ * 따라서 경로 concat과 URL scheme 추가도 단순한 문자열 조작으로 처리하였습니다.
110
+ *
111
+ * @param rootPath
112
+ * @returns
113
+ */
114
+ export async function loadConfig(rootPath: string): Promise<SonamuConfig> {
115
+ const start = performance.now();
116
+ const configPath =
117
+ process.env.HOT === "yes" || process.env.VITEST === "true"
118
+ ? `${rootPath}/sonamu.config.ts`
119
+ : `${rootPath}/dist/sonamu.config.js`;
120
+ const { default: config } = await import(`file://${configPath}`);
121
+ const importTime = performance.now() - start;
122
+ process.env.NODE_ENV !== "test" &&
123
+ console.log(`[TIMING] loadConfig took ${importTime.toFixed(2)}ms`);
124
+ return config;
125
+ }
@@ -1,29 +1,19 @@
1
1
  import type { FastifyReply, FastifyRequest, PassportUser } from "fastify";
2
2
  import type { RouteGenericInterface } from "fastify/types/route";
3
- import type {
4
- Server,
5
- IncomingMessage,
6
- ServerResponse,
7
- IncomingHttpHeaders,
8
- } from "http";
9
- import type { FileStorage } from "../file-storage/file-storage";
3
+ import type { IncomingHttpHeaders, IncomingMessage, Server, ServerResponse } from "http";
10
4
  import type { ZodObject } from "zod";
5
+ import type { FileStorage } from "../file-storage/file-storage";
6
+ import type { NaiteStore } from "../naite/naite";
11
7
  import type { createSSEFactory } from "../stream/sse";
12
8
 
9
+ // biome-ignore lint/suspicious/noEmptyInterface: Context 확장 타입
13
10
  export interface ContextExtend {}
14
11
  export type Context = {
15
12
  request: FastifyRequest;
16
- reply: FastifyReply<
17
- Server,
18
- IncomingMessage,
19
- ServerResponse,
20
- RouteGenericInterface,
21
- unknown
22
- >;
13
+ reply: FastifyReply<Server, IncomingMessage, ServerResponse, RouteGenericInterface, unknown>;
23
14
  headers: IncomingHttpHeaders;
24
- createSSE: <T extends ZodObject>(
25
- events: T
26
- ) => ReturnType<typeof createSSEFactory<T>>;
15
+ createSSE: <T extends ZodObject>(events: T) => ReturnType<typeof createSSEFactory<T>>;
16
+ naiteStore: NaiteStore;
27
17
  } & AuthContext &
28
18
  ContextExtend;
29
19
 
@@ -1,15 +1,18 @@
1
+ import assert from "assert";
1
2
  import type { HTTPMethods } from "fastify";
2
3
  import inflection from "inflection";
3
- import type { ApiParam, ApiParamType } from "../types/types";
4
- import { z } from "zod";
4
+ import { isEqual } from "radashi";
5
+ import type { z } from "zod";
6
+ import type { BaseModelClass } from "../database/base-model";
7
+ import { DB } from "../database/db";
5
8
  import {
6
9
  PuriTransactionWrapper,
7
- PuriWrapper,
8
- TransactionalOptions,
10
+ type PuriWrapper,
11
+ type TransactionalOptions,
9
12
  } from "../database/puri-wrapper";
10
- import { DB } from "../database/db";
11
- import { Sonamu } from "./sonamu";
13
+ import type { ApiParam, ApiParamType } from "../types/types";
12
14
  import type { UploadContext } from "./context";
15
+ import { Sonamu } from "./sonamu";
13
16
 
14
17
  export interface GuardKeys {
15
18
  query: true;
@@ -17,11 +20,7 @@ export interface GuardKeys {
17
20
  user: true;
18
21
  }
19
22
  export type GuardKey = keyof GuardKeys;
20
- export type ServiceClient =
21
- | "axios"
22
- | "axios-multipart"
23
- | "swr"
24
- | "window-fetch";
23
+ export type ServiceClient = "axios" | "axios-multipart" | "swr" | "window-fetch";
25
24
  export type ApiDecoratorOptions = {
26
25
  httpMethod?: HTTPMethods;
27
26
  contentType?:
@@ -39,6 +38,7 @@ export type ApiDecoratorOptions = {
39
38
  };
40
39
  export type StreamDecoratorOptions = {
41
40
  type: "sse"; // | 'ws
41
+ // biome-ignore lint/suspicious/noExplicitAny: 이벤트 키별로 넘겨주는 값이므로 어떤 타입이든 상관없음
42
42
  events: z.ZodObject<any>;
43
43
  path?: string;
44
44
  resourceName?: string;
@@ -49,6 +49,9 @@ export type UploadDecoratorOptions = {
49
49
  mode?: "single" | "multiple";
50
50
  };
51
51
  export const registeredApis: {
52
+ /**
53
+ * modelName은 모델 클래스 이름입니다. (ex. "UserModel")
54
+ */
52
55
  modelName: string;
53
56
  methodName: string;
54
57
  path: string;
@@ -67,6 +70,23 @@ export type ExtendedApi = {
67
70
  parameters: ApiParam[];
68
71
  returnType: ApiParamType;
69
72
  };
73
+ type DecoratorTarget = { constructor: { name: string } };
74
+
75
+ const DECORATOR_TYPES = {
76
+ API: Symbol("api"),
77
+ STREAM: Symbol("stream"),
78
+ } as const;
79
+
80
+ function checkSingleDecorator(target: DecoratorTarget, propertyKey: string, decoratorType: symbol) {
81
+ const method = target[propertyKey as keyof typeof target] as { __decoratorType?: symbol };
82
+ if (method?.__decoratorType && method?.__decoratorType !== decoratorType) {
83
+ throw new Error(
84
+ `@${String(decoratorType)} decorator can only be used once on ${target.constructor.name}.${propertyKey}. You can use only one of @api or @stream decorator on the same method.`,
85
+ );
86
+ } else {
87
+ method.__decoratorType = decoratorType;
88
+ }
89
+ }
70
90
 
71
91
  export function api(options: ApiDecoratorOptions = {}) {
72
92
  options = {
@@ -76,26 +96,43 @@ export function api(options: ApiDecoratorOptions = {}) {
76
96
  ...options,
77
97
  };
78
98
 
79
- return function (target: Object, propertyKey: string) {
80
- const modelName = target.constructor.name.match(/(.+)Class$/)![1];
99
+ return (target: DecoratorTarget, propertyKey: string) => {
100
+ const modelName = target.constructor.name.match(/(.+)Class$/)?.[1];
101
+ assert(
102
+ modelName,
103
+ `modelName is required on @api decorator on ${target.constructor.name}.${propertyKey}`,
104
+ );
81
105
  const methodName = propertyKey;
82
106
 
107
+ // 메서드에 걸린 데코레이터 중복 체크
108
+ checkSingleDecorator(target, propertyKey, DECORATOR_TYPES.API);
109
+
83
110
  const defaultPath = `/${inflection.camelize(
84
111
  modelName.replace(/Model$/, "").replace(/Frame$/, ""),
85
- true
112
+ true,
86
113
  )}/${inflection.camelize(propertyKey, true)}`;
114
+ const path = options.path ?? defaultPath;
87
115
 
88
116
  // 기존 동일한 메서드가 있는지 확인 후 있는 경우 override
89
117
  const existingApi = registeredApis.find(
90
- (api) => api.modelName === modelName && api.methodName === methodName
118
+ (api) => api.modelName === modelName && api.methodName === methodName,
91
119
  );
92
120
  if (existingApi) {
93
- existingApi.options = options;
121
+ // 기존의 path와 새로운 path가 다르다면(=빈 스트링이 아니었는데 다른 스트링으로 바뀌게 된다면) 에러를 터뜨려줍니다.
122
+ assertNoConflictingPath("api", modelName, methodName, existingApi.path, path);
123
+ existingApi.path = path;
124
+
125
+ // 기존의 옵션과 새로운 옵션이 겹치는 부분이 있다면 에러를 터뜨려줍니다.
126
+ assertNoConflictingOptions("api", modelName, methodName, existingApi.options, options);
127
+ existingApi.options = {
128
+ ...existingApi.options, // 기존의 옵션을 존중하되
129
+ ...options, // @api 데코레이터의 옵션을 추가합니다.
130
+ };
94
131
  } else {
95
132
  registeredApis.push({
96
133
  modelName,
97
134
  methodName,
98
- path: options.path ?? defaultPath,
135
+ path,
99
136
  options,
100
137
  });
101
138
  }
@@ -103,29 +140,55 @@ export function api(options: ApiDecoratorOptions = {}) {
103
140
  }
104
141
 
105
142
  export function stream(options: StreamDecoratorOptions) {
106
- return function (target: Object, propertyKey: string) {
107
- const modelName = target.constructor.name.match(/(.+)Class$/)![1];
143
+ return (target: DecoratorTarget, propertyKey: string) => {
144
+ const modelName = target.constructor.name.match(/(.+)Class$/)?.[1];
145
+ assert(
146
+ modelName,
147
+ `modelName is required on @stream decorator on ${target.constructor.name}.${propertyKey}`,
148
+ );
108
149
  const methodName = propertyKey;
109
150
 
151
+ // 메서드에 걸린 데코레이터 중복 체크
152
+ checkSingleDecorator(target, propertyKey, DECORATOR_TYPES.STREAM);
153
+
110
154
  const defaultPath = `/${inflection.camelize(
111
155
  modelName.replace(/Model$/, "").replace(/Frame$/, ""),
112
- true
156
+ true,
113
157
  )}/${inflection.camelize(propertyKey, true)}`;
158
+ const path = options.path ?? defaultPath;
159
+ const optionsWithDefaults = {
160
+ ...options,
161
+ httpMethod: "GET" as HTTPMethods,
162
+ };
114
163
 
115
164
  const existingApi = registeredApis.find(
116
- (api) => api.modelName === modelName && api.methodName === methodName
165
+ (api) => api.modelName === modelName && api.methodName === methodName,
117
166
  );
118
167
  if (existingApi) {
119
- existingApi.options = options;
168
+ // 기존의 path와 새로운 path가 다르다면(=빈 스트링이 아니었는데 다른 스트링으로 바뀌게 된다면) 에러를 터뜨려줍니다.
169
+ assertNoConflictingPath("stream", modelName, methodName, existingApi.path, path);
170
+ existingApi.path = path;
171
+
172
+ // 기존의 옵션과 새로운 옵션이 겹치는 부분이 있다면 에러를 터뜨려줍니다.
173
+ assertNoConflictingOptions(
174
+ "stream",
175
+ modelName,
176
+ methodName,
177
+ existingApi.options,
178
+ optionsWithDefaults,
179
+ );
180
+ existingApi.options = {
181
+ ...existingApi.options, // 기존의 옵션을 존중하되
182
+ ...optionsWithDefaults, // @stream 데코레이터의 옵션을 추가합니다.
183
+ };
184
+
185
+ existingApi.streamOptions = options;
120
186
  } else {
121
187
  registeredApis.push({
122
188
  modelName,
123
189
  methodName,
124
- path: options.path ?? defaultPath,
125
- options: {
126
- ...options,
127
- httpMethod: "GET",
128
- },
190
+ path,
191
+ options: optionsWithDefaults,
129
192
  streamOptions: options,
130
193
  });
131
194
  }
@@ -135,14 +198,10 @@ export function stream(options: StreamDecoratorOptions) {
135
198
  export function transactional(options: TransactionalOptions = {}) {
136
199
  const { isolation, readOnly, dbPreset = "w" } = options;
137
200
 
138
- return function (
139
- _target: Object,
140
- _propertyKey: string,
141
- descriptor: PropertyDescriptor
142
- ) {
201
+ return (_target: DecoratorTarget, _propertyKey: string, descriptor: PropertyDescriptor) => {
143
202
  const originalMethod = descriptor.value;
144
203
 
145
- descriptor.value = async function (this: any, ...args: any[]) {
204
+ descriptor.value = async function (this: BaseModelClass, ...args: unknown[]) {
146
205
  const existingContext = DB.transactionStorage.getStore();
147
206
 
148
207
  // 이미 AsyncLocalStorage 컨텍스트 안에 있는지 확인
@@ -159,10 +218,7 @@ export function transactional(options: TransactionalOptions = {}) {
159
218
 
160
219
  return puri.knex.transaction(
161
220
  async (trx) => {
162
- const trxWrapper = new PuriTransactionWrapper(
163
- trx,
164
- this.getUpsertBuilder()
165
- );
221
+ const trxWrapper = new PuriTransactionWrapper(trx, this.getUpsertBuilder());
166
222
  // TransactionContext에 트랜잭션 저장
167
223
  DB.getTransactionContext().setTransaction(dbPreset, trxWrapper);
168
224
 
@@ -173,7 +229,7 @@ export function transactional(options: TransactionalOptions = {}) {
173
229
  DB.getTransactionContext().deleteTransaction(dbPreset);
174
230
  }
175
231
  },
176
- { isolationLevel: isolation, readOnly }
232
+ { isolationLevel: isolation, readOnly },
177
233
  );
178
234
  };
179
235
 
@@ -190,25 +246,42 @@ export function transactional(options: TransactionalOptions = {}) {
190
246
  };
191
247
  }
192
248
 
249
+ /**
250
+ * api 데코레이터와 함께 사용할 수 있습니다.
251
+ * @param options
252
+ * @returns
253
+ */
193
254
  export function upload(options: UploadDecoratorOptions = {}) {
194
- return function (
195
- _target: Object,
196
- _propertyKey: string,
197
- descriptor: PropertyDescriptor
198
- ) {
255
+ return (_target: DecoratorTarget, _propertyKey: string, descriptor: PropertyDescriptor) => {
199
256
  const originalMethod = descriptor.value;
200
- const modelName = _target.constructor.name.match(/(.+)Class$/)![1];
257
+ const modelName = _target.constructor.name.match(/(.+)Class$/)?.[1];
258
+ assert(
259
+ modelName,
260
+ `modelName is required on @upload decorator on ${_target.constructor.name}.${_propertyKey}`,
261
+ );
201
262
  const methodName = _propertyKey;
202
263
 
203
264
  // registeredApis에서 해당 API 찾아서 uploadOptions 추가
204
265
  const existingApi = registeredApis.find(
205
- (api) => api.modelName === modelName && api.methodName === methodName
266
+ (api) => api.modelName === modelName && api.methodName === methodName,
206
267
  );
207
268
  if (existingApi) {
208
269
  existingApi.uploadOptions = options;
270
+ } else {
271
+ // 이 메소드에 붙은 @api 데코레이터가 아직 eval되지 않은 상황입니다. (만약 @api가 안 붙어 있었다면 심각한 상황입니다..!)
272
+ // 여기에서 최초로 modelName과 methodName에 대해 registeredApis에 하나를 추가해주어야 합니다.
273
+ // uploadOptions는 그대로 추가하고, path는 빈 스트링으로 추가해줍니다.
274
+ // 이후 @api 데코레이터가 eval되면 실제 path로 덮어씌워지고, options가 추가됩니다.
275
+ registeredApis.push({
276
+ modelName,
277
+ methodName,
278
+ path: "",
279
+ options: {},
280
+ uploadOptions: options,
281
+ });
209
282
  }
210
283
 
211
- descriptor.value = async function (this: any, ...args: any[]) {
284
+ descriptor.value = async function (this: BaseModelClass, ...args: unknown[]) {
212
285
  const { request } = Sonamu.getContext();
213
286
  const uploadContext: UploadContext = {
214
287
  file: undefined,
@@ -225,6 +298,7 @@ export function upload(options: UploadDecoratorOptions = {}) {
225
298
  const rawFilesIterator = request.files();
226
299
  for await (const rawFile of rawFilesIterator) {
227
300
  if (rawFile) {
301
+ await rawFile.toBuffer();
228
302
  uploadContext.files.push(new FileStorage(rawFile, storage));
229
303
  }
230
304
  }
@@ -243,3 +317,59 @@ export function upload(options: UploadDecoratorOptions = {}) {
243
317
  return descriptor;
244
318
  };
245
319
  }
320
+
321
+ /**
322
+ * 기존의 path와 새로운 path가 다르다면(=값이 있던 스트링이 다른 값이 있는 스트링으로 바뀌게 된다면) 에러를 터뜨려줍니다.
323
+ * @param decoratorName 데코레이터 이름
324
+ * @param modelName 모델 이름
325
+ * @param methodName 메서드 이름
326
+ * @param existingPath 기존의 path
327
+ * @param newPath 새로운 path
328
+ */
329
+ function assertNoConflictingPath(
330
+ decoratorName: string,
331
+ modelName: string,
332
+ methodName: string,
333
+ existingPath: string,
334
+ newPath: string,
335
+ ) {
336
+ if (existingPath !== "" && newPath !== "" && existingPath !== newPath) {
337
+ // 이것이 무슨 상황이냐면요, api.path가 덮어씌워지는 상황입니다.
338
+ // 가령 @api({ path: "/api/v1/users" }) 데코레이터가 붙어있는 메서드에
339
+ // @stream({ path: "/api/v1/users/stream" }) 같은 것이 붙어 있는 상황입니다.
340
+ // 이렇게 되면 두 데코레이터가 같은 api의 path 필드를 건드리게 되므로, 에러를 터뜨려줍니다.
341
+ throw new Error(
342
+ `@${decoratorName} decorator on ${modelName}.${methodName} has conflicting path: ${newPath}. The decorator is trying to override the existing path(${existingPath}) with the new path(${newPath}).`,
343
+ );
344
+ }
345
+ }
346
+
347
+ /**
348
+ * 기존의 옵션과 새로운 옵션이 겹치는 부분이 있다면 에러를 터뜨려줍니다.
349
+ * @param decoratorName 데코레이터 이름
350
+ * @param modelName 모델 이름
351
+ * @param methodName 메서드 이름
352
+ * @param existingOptions 기존의 옵션
353
+ * @param newOptions 새로운 옵션
354
+ */
355
+ function assertNoConflictingOptions(
356
+ decoratorName: string,
357
+ modelName: string,
358
+ methodName: string,
359
+ // biome-ignore lint/suspicious/noExplicitAny: <아 쉽게쉽게 좀 갑시다>
360
+ existingOptions: Record<string, any>,
361
+ // biome-ignore lint/suspicious/noExplicitAny: <이럴 때 아니면 any 언제 씁니까>
362
+ newOptions: Record<string, any>,
363
+ ) {
364
+ Object.keys(newOptions).forEach((key) => {
365
+ if (existingOptions[key] && !isEqual(existingOptions[key], newOptions[key])) {
366
+ // 이것이 무슨 상황이냐면요, api.options가 덮어씌워지는 상황입니다.
367
+ // 가령 @api({ resourceName: "Users" }) 데코레이터가 붙어있는 메서드에
368
+ // @stream({ resourceName: "Posts" }) 같은 것이 붙어 있는 상황입니다.
369
+ // 이렇게 되면 두 데코레이터가 같은 api의 options 속 같은 필드를 건드리게 되므로, 에러를 터뜨려줍니다.
370
+ throw new Error(
371
+ `@${decoratorName} decorator on ${modelName}.${methodName} has conflicting options: ${key}. The decorator is trying to override the existing option(${JSON.stringify(existingOptions[key])}) with the new option(${JSON.stringify(newOptions[key])}).`,
372
+ );
373
+ }
374
+ });
375
+ }
package/src/api/index.ts CHANGED
@@ -1,7 +1,7 @@
1
+ export * from "../file-storage/driver";
2
+ export * from "../file-storage/file-storage";
1
3
  export * from "./caster";
2
4
  export * from "./code-converters";
3
5
  export * from "./context";
4
6
  export * from "./decorators";
5
- export * from "../file-storage/driver";
6
- export * from "../file-storage/file-storage";
7
7
  export * from "./sonamu";