sonamu 0.6.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (406) hide show
  1. package/.swcrc.project-default +18 -0
  2. package/bin/cli.js +24 -0
  3. package/dist/ai/agents/agent.d.ts +11 -0
  4. package/dist/ai/agents/agent.d.ts.map +1 -0
  5. package/dist/ai/agents/agent.js +65 -0
  6. package/dist/ai/agents/index.d.ts +3 -0
  7. package/dist/ai/agents/index.d.ts.map +1 -0
  8. package/dist/ai/agents/index.js +4 -0
  9. package/dist/ai/agents/types.d.ts +43 -0
  10. package/dist/ai/agents/types.d.ts.map +1 -0
  11. package/dist/ai/agents/types.js +3 -0
  12. package/dist/ai/index.d.ts +2 -0
  13. package/dist/ai/index.d.ts.map +1 -0
  14. package/dist/ai/index.js +3 -0
  15. package/dist/ai/providers/rtzr/api.d.ts +22 -0
  16. package/dist/ai/providers/rtzr/api.d.ts.map +1 -0
  17. package/dist/ai/providers/rtzr/api.js +28 -0
  18. package/dist/ai/providers/rtzr/error.d.ts +18 -0
  19. package/dist/ai/providers/rtzr/error.d.ts.map +1 -0
  20. package/dist/ai/providers/rtzr/error.js +29 -0
  21. package/dist/ai/providers/rtzr/index.d.ts +5 -0
  22. package/dist/ai/providers/rtzr/index.d.ts.map +1 -0
  23. package/dist/ai/providers/rtzr/index.js +6 -0
  24. package/dist/ai/providers/rtzr/model.d.ts +52 -0
  25. package/dist/ai/providers/rtzr/model.d.ts.map +1 -0
  26. package/dist/ai/providers/rtzr/model.js +137 -0
  27. package/dist/ai/providers/rtzr/options.d.ts +7 -0
  28. package/dist/ai/providers/rtzr/options.d.ts.map +1 -0
  29. package/dist/ai/providers/rtzr/options.js +47 -0
  30. package/dist/ai/providers/rtzr/provider.d.ts +18 -0
  31. package/dist/ai/providers/rtzr/provider.d.ts.map +1 -0
  32. package/dist/ai/providers/rtzr/provider.js +54 -0
  33. package/dist/ai/providers/rtzr/utils.d.ts +19 -0
  34. package/dist/ai/providers/rtzr/utils.d.ts.map +1 -0
  35. package/dist/ai/providers/rtzr/utils.js +88 -0
  36. package/dist/api/base-frame.d.ts +2 -2
  37. package/dist/api/base-frame.d.ts.map +1 -1
  38. package/dist/api/base-frame.js +2 -1
  39. package/dist/api/caster.d.ts.map +1 -1
  40. package/dist/api/caster.js +6 -1
  41. package/dist/api/code-converters.d.ts +58 -14
  42. package/dist/api/code-converters.d.ts.map +1 -1
  43. package/dist/api/code-converters.js +178 -409
  44. package/dist/api/config.d.ts +27 -13
  45. package/dist/api/config.d.ts.map +1 -1
  46. package/dist/api/config.js +19 -26
  47. package/dist/api/context.d.ts +4 -3
  48. package/dist/api/context.d.ts.map +1 -1
  49. package/dist/api/context.js +1 -1
  50. package/dist/api/decorators.d.ts +20 -6
  51. package/dist/api/decorators.d.ts.map +1 -1
  52. package/dist/api/decorators.js +111 -18
  53. package/dist/api/index.d.ts +2 -2
  54. package/dist/api/index.d.ts.map +1 -1
  55. package/dist/api/index.js +3 -3
  56. package/dist/api/sonamu.d.ts +7 -7
  57. package/dist/api/sonamu.d.ts.map +1 -1
  58. package/dist/api/sonamu.js +83 -51
  59. package/dist/api/validator.d.ts +6 -0
  60. package/dist/api/validator.d.ts.map +1 -0
  61. package/dist/api/validator.js +81 -0
  62. package/dist/bin/build-config.d.ts +5 -1
  63. package/dist/bin/build-config.d.ts.map +1 -1
  64. package/dist/bin/build-config.js +5 -2
  65. package/dist/bin/cli.js +165 -64
  66. package/dist/bin/loader-register.d.ts +2 -0
  67. package/dist/bin/loader-register.d.ts.map +1 -0
  68. package/dist/bin/loader-register.js +34 -0
  69. package/dist/database/_batch_update.d.ts +5 -3
  70. package/dist/database/_batch_update.d.ts.map +1 -1
  71. package/dist/database/_batch_update.js +30 -13
  72. package/dist/database/base-model.d.ts +96 -10
  73. package/dist/database/base-model.d.ts.map +1 -1
  74. package/dist/database/base-model.js +232 -89
  75. package/dist/database/base-model.types.d.ts +93 -0
  76. package/dist/database/base-model.types.d.ts.map +1 -0
  77. package/dist/database/base-model.types.js +10 -0
  78. package/dist/database/code-generator.d.ts +1 -1
  79. package/dist/database/code-generator.d.ts.map +1 -1
  80. package/dist/database/code-generator.js +11 -10
  81. package/dist/database/db.d.ts +5 -6
  82. package/dist/database/db.d.ts.map +1 -1
  83. package/dist/database/db.js +22 -25
  84. package/dist/database/puri-subset.test-d.js +81 -0
  85. package/dist/database/puri-subset.types.d.ts +123 -0
  86. package/dist/database/puri-subset.types.d.ts.map +1 -0
  87. package/dist/database/puri-subset.types.js +16 -0
  88. package/dist/database/puri-wrapper.d.ts +13 -11
  89. package/dist/database/puri-wrapper.d.ts.map +1 -1
  90. package/dist/database/puri-wrapper.js +2 -2
  91. package/dist/database/puri.d.ts +25 -14
  92. package/dist/database/puri.d.ts.map +1 -1
  93. package/dist/database/puri.js +83 -21
  94. package/dist/database/puri.types.d.ts +21 -7
  95. package/dist/database/puri.types.d.ts.map +1 -1
  96. package/dist/database/puri.types.js +4 -1
  97. package/dist/database/transaction-context.d.ts +1 -1
  98. package/dist/database/transaction-context.d.ts.map +1 -1
  99. package/dist/database/transaction-context.js +1 -1
  100. package/dist/database/upsert-builder.d.ts +9 -3
  101. package/dist/database/upsert-builder.d.ts.map +1 -1
  102. package/dist/database/upsert-builder.js +227 -78
  103. package/dist/entity/entity-manager.d.ts +165 -2
  104. package/dist/entity/entity-manager.d.ts.map +1 -1
  105. package/dist/entity/entity-manager.js +26 -10
  106. package/dist/entity/entity.d.ts +5 -3
  107. package/dist/entity/entity.d.ts.map +1 -1
  108. package/dist/entity/entity.js +153 -54
  109. package/dist/exceptions/error-handler.d.ts +1 -1
  110. package/dist/exceptions/error-handler.d.ts.map +1 -1
  111. package/dist/exceptions/error-handler.js +1 -1
  112. package/dist/exceptions/so-exceptions.d.ts +1 -1
  113. package/dist/exceptions/so-exceptions.d.ts.map +1 -1
  114. package/dist/exceptions/so-exceptions.js +1 -1
  115. package/dist/file-storage/driver.d.ts +1 -1
  116. package/dist/file-storage/driver.d.ts.map +1 -1
  117. package/dist/file-storage/driver.js +1 -1
  118. package/dist/file-storage/file-storage.js +2 -2
  119. package/dist/index.d.ts +18 -11
  120. package/dist/index.d.ts.map +1 -1
  121. package/dist/index.js +19 -13
  122. package/dist/migration/code-generation.d.ts +1 -1
  123. package/dist/migration/code-generation.d.ts.map +1 -1
  124. package/dist/migration/code-generation.js +123 -67
  125. package/dist/migration/migration-set.d.ts +2 -10
  126. package/dist/migration/migration-set.d.ts.map +1 -1
  127. package/dist/migration/migration-set.js +67 -218
  128. package/dist/migration/migrator.d.ts +24 -73
  129. package/dist/migration/migrator.d.ts.map +1 -1
  130. package/dist/migration/migrator.js +121 -301
  131. package/dist/migration/postgresql-schema-reader.d.ts +51 -0
  132. package/dist/migration/postgresql-schema-reader.d.ts.map +1 -0
  133. package/dist/migration/postgresql-schema-reader.js +245 -0
  134. package/dist/migration/types.d.ts +6 -38
  135. package/dist/migration/types.d.ts.map +1 -1
  136. package/dist/migration/types.js +1 -1
  137. package/dist/naite/messaging-types.d.ts +43 -0
  138. package/dist/naite/messaging-types.d.ts.map +1 -0
  139. package/dist/naite/messaging-types.js +7 -0
  140. package/dist/naite/naite-reporter.d.ts +41 -0
  141. package/dist/naite/naite-reporter.d.ts.map +1 -0
  142. package/dist/naite/naite-reporter.js +102 -0
  143. package/dist/naite/naite.d.ts +91 -8
  144. package/dist/naite/naite.d.ts.map +1 -1
  145. package/dist/naite/naite.js +285 -41
  146. package/dist/stream/sse.d.ts +2 -2
  147. package/dist/stream/sse.d.ts.map +1 -1
  148. package/dist/stream/sse.js +1 -1
  149. package/dist/syncer/api-parser.d.ts +3 -13
  150. package/dist/syncer/api-parser.d.ts.map +1 -1
  151. package/dist/syncer/api-parser.js +67 -56
  152. package/dist/syncer/checksum.d.ts +2 -2
  153. package/dist/syncer/checksum.d.ts.map +1 -1
  154. package/dist/syncer/checksum.js +11 -11
  155. package/dist/syncer/code-generator.d.ts +3 -3
  156. package/dist/syncer/code-generator.d.ts.map +1 -1
  157. package/dist/syncer/code-generator.js +37 -17
  158. package/dist/syncer/entity-operations.d.ts +2 -2
  159. package/dist/syncer/entity-operations.d.ts.map +1 -1
  160. package/dist/syncer/entity-operations.js +9 -8
  161. package/dist/syncer/file-patterns.d.ts +1 -1
  162. package/dist/syncer/file-patterns.d.ts.map +1 -1
  163. package/dist/syncer/file-patterns.js +1 -1
  164. package/dist/syncer/index.d.ts +4 -4
  165. package/dist/syncer/index.d.ts.map +1 -1
  166. package/dist/syncer/index.js +5 -5
  167. package/dist/syncer/module-loader.d.ts +4 -4
  168. package/dist/syncer/module-loader.d.ts.map +1 -1
  169. package/dist/syncer/module-loader.js +17 -12
  170. package/dist/syncer/syncer.d.ts +31 -24
  171. package/dist/syncer/syncer.d.ts.map +1 -1
  172. package/dist/syncer/syncer.js +92 -45
  173. package/dist/template/entity-converter.d.ts +1 -1
  174. package/dist/template/entity-converter.d.ts.map +1 -1
  175. package/dist/template/entity-converter.js +15 -8
  176. package/dist/template/helpers.d.ts +2 -2
  177. package/dist/template/helpers.d.ts.map +1 -1
  178. package/dist/template/helpers.js +3 -3
  179. package/dist/template/implementations/entity.template.d.ts +2 -2
  180. package/dist/template/implementations/entity.template.d.ts.map +1 -1
  181. package/dist/template/implementations/entity.template.js +4 -5
  182. package/dist/template/implementations/generated.template.d.ts +2 -3
  183. package/dist/template/implementations/generated.template.d.ts.map +1 -1
  184. package/dist/template/implementations/generated.template.js +46 -29
  185. package/dist/template/implementations/generated_http.template.d.ts +2 -3
  186. package/dist/template/implementations/generated_http.template.d.ts.map +1 -1
  187. package/dist/template/implementations/generated_http.template.js +9 -9
  188. package/dist/template/implementations/generated_sso.template.d.ts +3 -4
  189. package/dist/template/implementations/generated_sso.template.d.ts.map +1 -1
  190. package/dist/template/implementations/generated_sso.template.js +54 -25
  191. package/dist/template/implementations/init_types.template.d.ts +2 -2
  192. package/dist/template/implementations/init_types.template.d.ts.map +1 -1
  193. package/dist/template/implementations/init_types.template.js +2 -2
  194. package/dist/template/implementations/model.template.d.ts +2 -2
  195. package/dist/template/implementations/model.template.d.ts.map +1 -1
  196. package/dist/template/implementations/model.template.js +47 -37
  197. package/dist/template/implementations/model_test.template.d.ts +2 -2
  198. package/dist/template/implementations/model_test.template.d.ts.map +1 -1
  199. package/dist/template/implementations/model_test.template.js +2 -2
  200. package/dist/template/implementations/service.template.d.ts +4 -4
  201. package/dist/template/implementations/service.template.d.ts.map +1 -1
  202. package/dist/template/implementations/service.template.js +24 -16
  203. package/dist/template/implementations/view_enums_buttonset.template.d.ts +2 -2
  204. package/dist/template/implementations/view_enums_buttonset.template.d.ts.map +1 -1
  205. package/dist/template/implementations/view_enums_buttonset.template.js +1 -1
  206. package/dist/template/implementations/view_enums_dropdown.template.d.ts +2 -2
  207. package/dist/template/implementations/view_enums_dropdown.template.d.ts.map +1 -1
  208. package/dist/template/implementations/view_enums_dropdown.template.js +2 -2
  209. package/dist/template/implementations/view_enums_select.template.d.ts +2 -2
  210. package/dist/template/implementations/view_enums_select.template.d.ts.map +1 -1
  211. package/dist/template/implementations/view_enums_select.template.js +2 -2
  212. package/dist/template/implementations/view_form.template.d.ts +2 -2
  213. package/dist/template/implementations/view_form.template.d.ts.map +1 -1
  214. package/dist/template/implementations/view_form.template.js +4 -4
  215. package/dist/template/implementations/view_id_all_select.template.d.ts +2 -2
  216. package/dist/template/implementations/view_id_all_select.template.d.ts.map +1 -1
  217. package/dist/template/implementations/view_id_all_select.template.js +1 -1
  218. package/dist/template/implementations/view_id_async_select.template.d.ts +2 -2
  219. package/dist/template/implementations/view_id_async_select.template.d.ts.map +1 -1
  220. package/dist/template/implementations/view_id_async_select.template.js +1 -1
  221. package/dist/template/implementations/view_list.template.d.ts +2 -2
  222. package/dist/template/implementations/view_list.template.d.ts.map +1 -1
  223. package/dist/template/implementations/view_list.template.js +29 -19
  224. package/dist/template/implementations/view_list_columns.template.d.ts +3 -3
  225. package/dist/template/implementations/view_list_columns.template.d.ts.map +1 -1
  226. package/dist/template/implementations/view_list_columns.template.js +1 -1
  227. package/dist/template/implementations/view_search_input.template.d.ts +2 -2
  228. package/dist/template/implementations/view_search_input.template.d.ts.map +1 -1
  229. package/dist/template/implementations/view_search_input.template.js +1 -1
  230. package/dist/template/index.d.ts +4 -2
  231. package/dist/template/index.d.ts.map +1 -1
  232. package/dist/template/index.js +5 -3
  233. package/dist/template/template-manager.d.ts +56 -0
  234. package/dist/template/template-manager.d.ts.map +1 -0
  235. package/dist/template/template-manager.js +125 -0
  236. package/dist/template/template-types.d.ts +16 -0
  237. package/dist/template/template-types.d.ts.map +1 -0
  238. package/dist/template/template-types.js +7 -0
  239. package/dist/template/template.d.ts +12 -2
  240. package/dist/template/template.d.ts.map +1 -1
  241. package/dist/template/template.js +19 -6
  242. package/dist/template/zod-converter.d.ts +40 -7
  243. package/dist/template/zod-converter.d.ts.map +1 -1
  244. package/dist/template/zod-converter.js +386 -58
  245. package/dist/testing/_relation-graph.d.ts +1 -1
  246. package/dist/testing/_relation-graph.d.ts.map +1 -1
  247. package/dist/testing/_relation-graph.js +12 -3
  248. package/dist/testing/fixture-manager.d.ts +42 -11
  249. package/dist/testing/fixture-manager.d.ts.map +1 -1
  250. package/dist/testing/fixture-manager.js +338 -236
  251. package/dist/types/types.d.ts +709 -104
  252. package/dist/types/types.d.ts.map +1 -1
  253. package/dist/types/types.js +309 -52
  254. package/dist/typings/knex.d.js +2 -2
  255. package/dist/utils/async-utils.d.ts.map +1 -1
  256. package/dist/utils/async-utils.js +3 -3
  257. package/dist/utils/console-util.js +1 -1
  258. package/dist/utils/controller.d.ts +1 -0
  259. package/dist/utils/controller.d.ts.map +1 -1
  260. package/dist/utils/controller.js +4 -1
  261. package/dist/utils/esm-utils.d.ts +0 -6
  262. package/dist/utils/esm-utils.d.ts.map +1 -1
  263. package/dist/utils/esm-utils.js +2 -9
  264. package/dist/utils/formatter.d.ts +3 -0
  265. package/dist/utils/formatter.d.ts.map +1 -0
  266. package/dist/utils/formatter.js +110 -0
  267. package/dist/utils/fs-utils.d.ts +1 -1
  268. package/dist/utils/fs-utils.d.ts.map +1 -1
  269. package/dist/utils/fs-utils.js +1 -1
  270. package/dist/utils/lodash-able.d.ts.map +1 -1
  271. package/dist/utils/lodash-able.js +1 -1
  272. package/dist/utils/object-utils.d.ts +44 -0
  273. package/dist/utils/object-utils.d.ts.map +1 -0
  274. package/dist/utils/object-utils.js +191 -0
  275. package/dist/utils/path-utils.d.ts +1 -1
  276. package/dist/utils/path-utils.d.ts.map +1 -1
  277. package/dist/utils/path-utils.js +3 -3
  278. package/dist/utils/process-utils.js +1 -1
  279. package/dist/utils/sql-parser.d.ts +5 -1
  280. package/dist/utils/sql-parser.d.ts.map +1 -1
  281. package/dist/utils/sql-parser.js +14 -3
  282. package/dist/utils/type-utils.d.ts +23 -0
  283. package/dist/utils/type-utils.d.ts.map +1 -0
  284. package/dist/utils/type-utils.js +45 -0
  285. package/dist/utils/utils.d.ts +7 -1
  286. package/dist/utils/utils.d.ts.map +1 -1
  287. package/dist/utils/utils.js +44 -5
  288. package/dist/utils/zod-error.d.ts +1 -1
  289. package/dist/utils/zod-error.d.ts.map +1 -1
  290. package/dist/utils/zod-error.js +1 -1
  291. package/package.json +55 -30
  292. package/src/ai/agents/agent.ts +87 -0
  293. package/src/ai/agents/index.ts +2 -0
  294. package/src/ai/agents/types.ts +47 -0
  295. package/src/ai/index.ts +1 -0
  296. package/src/ai/providers/rtzr/api.ts +37 -0
  297. package/src/ai/providers/rtzr/error.ts +34 -0
  298. package/src/ai/providers/rtzr/index.ts +4 -0
  299. package/src/ai/providers/rtzr/model.ts +201 -0
  300. package/src/ai/providers/rtzr/options.ts +49 -0
  301. package/src/ai/providers/rtzr/provider.ts +91 -0
  302. package/src/ai/providers/rtzr/utils.ts +127 -0
  303. package/src/api/base-frame.ts +4 -2
  304. package/src/api/caster.ts +17 -23
  305. package/src/api/code-converters.ts +176 -533
  306. package/src/api/config.ts +39 -56
  307. package/src/api/context.ts +7 -18
  308. package/src/api/decorators.ts +175 -46
  309. package/src/api/index.ts +2 -2
  310. package/src/api/sonamu.ts +133 -124
  311. package/src/api/validator.ts +83 -0
  312. package/src/bin/build-config.ts +7 -1
  313. package/src/bin/cli.ts +192 -110
  314. package/src/bin/loader-register.ts +38 -0
  315. package/src/database/_batch_update.ts +46 -31
  316. package/src/database/base-model.ts +390 -182
  317. package/src/database/base-model.types.ts +155 -0
  318. package/src/database/code-generator.ts +13 -32
  319. package/src/database/db.ts +36 -50
  320. package/src/database/puri-subset.test-d.ts +471 -0
  321. package/src/database/puri-subset.types.ts +195 -0
  322. package/src/database/puri-wrapper.ts +58 -67
  323. package/src/database/puri.ts +182 -126
  324. package/src/database/puri.types.ts +64 -31
  325. package/src/database/transaction-context.ts +1 -1
  326. package/src/database/upsert-builder.ts +261 -132
  327. package/src/entity/entity-manager.ts +36 -28
  328. package/src/entity/entity.ts +330 -249
  329. package/src/exceptions/error-handler.ts +3 -3
  330. package/src/exceptions/so-exceptions.ts +11 -11
  331. package/src/file-storage/driver.ts +5 -5
  332. package/src/file-storage/file-storage.ts +2 -2
  333. package/src/index.ts +18 -12
  334. package/src/migration/code-generation.ts +185 -172
  335. package/src/migration/migration-set.ts +80 -293
  336. package/src/migration/migrator.ts +182 -425
  337. package/src/migration/mysql-schema-reader.ts.txt +272 -0
  338. package/src/migration/postgresql-schema-reader.ts +310 -0
  339. package/src/migration/types.ts +6 -39
  340. package/src/naite/messaging-types.ts +51 -0
  341. package/src/naite/naite-reporter.ts +128 -0
  342. package/src/naite/naite.ts +378 -33
  343. package/src/shared/web.shared.ts.txt +20 -24
  344. package/src/stream/sse.ts +5 -5
  345. package/src/syncer/api-parser.ts +52 -69
  346. package/src/syncer/checksum.ts +25 -37
  347. package/src/syncer/code-generator.ts +58 -62
  348. package/src/syncer/entity-operations.ts +12 -15
  349. package/src/syncer/file-patterns.ts +2 -2
  350. package/src/syncer/index.ts +4 -4
  351. package/src/syncer/module-loader.ts +28 -25
  352. package/src/syncer/syncer.ts +155 -162
  353. package/src/template/entity-converter.ts +18 -27
  354. package/src/template/helpers.ts +8 -11
  355. package/src/template/implementations/entity.template.ts +6 -6
  356. package/src/template/implementations/generated.template.ts +99 -99
  357. package/src/template/implementations/generated_http.template.ts +21 -54
  358. package/src/template/implementations/generated_sso.template.ts +78 -65
  359. package/src/template/implementations/init_types.template.ts +4 -6
  360. package/src/template/implementations/model.template.ts +47 -38
  361. package/src/template/implementations/model_test.template.ts +3 -3
  362. package/src/template/implementations/service.template.ts +56 -80
  363. package/src/template/implementations/view_enums_buttonset.template.ts +2 -2
  364. package/src/template/implementations/view_enums_dropdown.template.ts +4 -4
  365. package/src/template/implementations/view_enums_select.template.ts +3 -3
  366. package/src/template/implementations/view_form.template.ts +34 -75
  367. package/src/template/implementations/view_id_all_select.template.ts +2 -2
  368. package/src/template/implementations/view_id_async_select.template.ts +9 -23
  369. package/src/template/implementations/view_list.template.ts +54 -95
  370. package/src/template/implementations/view_list_columns.template.ts +4 -10
  371. package/src/template/implementations/view_search_input.template.ts +2 -2
  372. package/src/template/index.ts +4 -2
  373. package/src/template/template-manager.ts +166 -0
  374. package/src/template/template-types.ts +16 -0
  375. package/src/template/template.ts +29 -10
  376. package/src/template/zod-converter.ts +459 -101
  377. package/src/testing/_relation-graph.ts +18 -11
  378. package/src/testing/fixture-manager.ts +468 -362
  379. package/src/types/types.ts +516 -248
  380. package/src/typings/knex.d.ts +7 -9
  381. package/src/utils/async-utils.ts +8 -12
  382. package/src/utils/console-util.ts +1 -1
  383. package/src/utils/controller.ts +3 -0
  384. package/src/utils/esm-utils.ts +8 -18
  385. package/src/utils/formatter.ts +109 -0
  386. package/src/utils/fs-utils.ts +1 -1
  387. package/src/utils/lodash-able.ts +1 -4
  388. package/src/utils/object-utils.ts +217 -0
  389. package/src/utils/path-utils.ts +3 -6
  390. package/src/utils/process-utils.ts +1 -1
  391. package/src/utils/sql-parser.ts +23 -5
  392. package/src/utils/type-utils.ts +83 -0
  393. package/src/utils/utils.ts +58 -9
  394. package/src/utils/zod-error.ts +3 -3
  395. package/dist/bin/cli-wrapper.d.ts +0 -3
  396. package/dist/bin/cli-wrapper.d.ts.map +0 -1
  397. package/dist/bin/cli-wrapper.js +0 -72
  398. package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts +0 -2
  399. package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts.map +0 -1
  400. package/dist/database/knex-plugins/knex-on-duplicate-update.js +0 -39
  401. package/dist/entity/entity-utils.d.ts +0 -61
  402. package/dist/entity/entity-utils.d.ts.map +0 -1
  403. package/dist/entity/entity-utils.js +0 -210
  404. package/src/bin/cli-wrapper.ts +0 -82
  405. package/src/database/knex-plugins/knex-on-duplicate-update.ts +0 -45
  406. package/src/entity/entity-utils.ts +0 -291
@@ -1,5 +1,5 @@
1
- import { TemplateOptions } from "../../types/types";
2
- import { EntityManager, EntityNamesRecord } from "../../entity/entity-manager";
1
+ import { EntityManager, type EntityNamesRecord } from "../../entity/entity-manager";
2
+ import type { TemplateOptions } from "../../types/types";
3
3
  import { Template } from "../template";
4
4
 
5
5
  export class Template__view_id_async_select extends Template {
@@ -19,15 +19,11 @@ export class Template__view_id_async_select extends Template {
19
19
 
20
20
  const entity = EntityManager.get(entityId);
21
21
  if (!textField) {
22
- const pickedProp = entity.props.find((prop) =>
23
- ["name", "title"].includes(prop.name)
24
- );
22
+ const pickedProp = entity.props.find((prop) => ["name", "title"].includes(prop.name));
25
23
  if (pickedProp) {
26
24
  textField = pickedProp.name;
27
25
  } else {
28
- const candidateProp = entity.props.find(
29
- (prop) => prop.type === "string"
30
- );
26
+ const candidateProp = entity.props.find((prop) => prop.type === "string");
31
27
  if (candidateProp) {
32
28
  textField = candidateProp.name;
33
29
  } else {
@@ -44,16 +40,10 @@ import { DropdownProps, DropdownItemProps, DropdownOnSearchChangeData, Dropdown
44
40
  import { ${names.capital}SubsetKey, ${
45
41
  names.capital
46
42
  }SubsetMapping } from "src/services/sonamu.generated";
47
- import { ${names.capital}Service } from "src/services/${names.fs}/${
48
- names.fs
49
- }.service";
50
- import { ${names.capital}ListParams } from "src/services/${names.fs}/${
51
- names.fs
52
- }.types";
43
+ import { ${names.capital}Service } from "src/services/${names.fs}/${names.fs}.service";
44
+ import { ${names.capital}ListParams } from "src/services/${names.fs}/${names.fs}.types";
53
45
 
54
- export function ${names.capital}IdAsyncSelect<T extends ${
55
- names.capital
56
- }SubsetKey>(
46
+ export function ${names.capital}IdAsyncSelect<T extends ${names.capital}SubsetKey>(
57
47
  { subset, baseListParams, textField, valueField, ...props }: DropdownProps & {
58
48
  subset: T;
59
49
  baseListParams?: ${names.capital}ListParams;
@@ -66,9 +56,7 @@ export function ${names.capital}IdAsyncSelect<T extends ${
66
56
  baseListParams ?? {},
67
57
  );
68
58
 
69
- const { data, error } = ${names.capital}Service.use${
70
- names.capitalPlural
71
- }(subset, listParams);
59
+ const { data, error } = ${names.capital}Service.use${names.capitalPlural}(subset, listParams);
72
60
  const { rows: ${names.camelPlural}, total } = data ?? {};
73
61
 
74
62
  useEffect(() => {
@@ -77,9 +65,7 @@ export function ${names.capital}IdAsyncSelect<T extends ${
77
65
  return {
78
66
  key: ${names.camel}.id,
79
67
  value: ${names.camel}[valueField ?? 'id'] as string | number,
80
- text: String(${names.camel}[textField${
81
- textField ? ` ?? '${textField}'` : ""
82
- }]),
68
+ text: String(${names.camel}[textField${textField ? ` ?? '${textField}'` : ""}]),
83
69
  };
84
70
  }),
85
71
  );
@@ -1,13 +1,14 @@
1
+ import assert from "assert";
1
2
  import inflection from "inflection";
2
- import * as _ from "lodash-es";
3
+ import { flat, unique } from "radashi";
3
4
  import { z } from "zod";
4
- import { RenderingNode, TemplateKey, TemplateOptions } from "../../types/types";
5
- import { EntityManager, EntityNamesRecord } from "../../entity/entity-manager";
6
- import { getRelationPropFromColName, getEnumInfoFromColName } from "../helpers";
7
- import { RenderedTemplate } from "../template";
8
- import { Template } from "../template";
9
- import { zodTypeToRenderingNode, getZodTypeById } from "../zod-converter";
5
+ import { EntityManager, type EntityNamesRecord } from "../../entity/entity-manager";
6
+ import type { RenderingNode, TemplateKey, TemplateOptions } from "../../types/types";
10
7
  import { getColumnsNode } from "../entity-converter";
8
+ import { getEnumInfoFromColName, getRelationPropFromColName } from "../helpers";
9
+ import type { RenderedTemplate } from "../template";
10
+ import { Template } from "../template";
11
+ import { getZodTypeById, zodTypeToRenderingNode } from "../zod-converter";
11
12
 
12
13
  export class Template__view_list extends Template {
13
14
  constructor() {
@@ -21,12 +22,7 @@ export class Template__view_list extends Template {
21
22
  };
22
23
  }
23
24
 
24
- wrapTc(
25
- body: string,
26
- key: string,
27
- collapsing: boolean = true,
28
- className: string = ""
29
- ) {
25
+ wrapTc(body: string, key: string, collapsing: boolean = true, className: string = "") {
30
26
  return `<Table.Cell key="${key}"${collapsing ? " collapsing" : ""}${
31
27
  className ? ` className={\`${className}\`}` : ""
32
28
  }>${body}</Table.Cell>`;
@@ -37,7 +33,7 @@ export class Template__view_list extends Template {
37
33
  col: RenderingNode,
38
34
  names: EntityNamesRecord,
39
35
  parentObj: string = "row",
40
- withoutName: boolean = false
36
+ withoutName: boolean = false,
41
37
  ): string {
42
38
  const colName = withoutName ? `${parentObj}` : `${parentObj}.${col.name}`;
43
39
 
@@ -46,16 +42,12 @@ export class Template__view_list extends Template {
46
42
  case "string-date":
47
43
  case "number-id":
48
44
  return `<>{${colName}}</>`;
49
- case "number-fk_id":
50
- const relPropFk = getRelationPropFromColName(
51
- entityId,
52
- col.name.replace("_id", "")
53
- );
45
+ case "number-fk_id": {
46
+ const relPropFk = getRelationPropFromColName(entityId, col.name.replace("_id", ""));
54
47
  return `<>${relPropFk.with}#{${colName}}</>`;
48
+ }
55
49
  case "string-image":
56
- return `<>{${
57
- col.nullable ? `${colName} && ` : ""
58
- }<img src={${colName}} />}</>`;
50
+ return `<>{${col.nullable ? `${colName} && ` : ""}<img src={${colName}} />}</>`;
59
51
  case "datetime":
60
52
  if (col.nullable) {
61
53
  return `<span className="text-tiny">{${colName} === null ? '-' : formatDateTime(${colName})}</span>`;
@@ -70,23 +62,18 @@ export class Template__view_list extends Template {
70
62
  }
71
63
  case "boolean":
72
64
  return `<>{${colName} ? <Label color='green' circular>O</Label> : <Label color='grey' circular>X</Label> }</>`;
73
- case "enums":
65
+ case "enums": {
74
66
  const { id: enumId } = getEnumInfoFromColName(entityId, col.name);
75
- return `<>{${
76
- col.nullable ? `${colName} && ` : ""
77
- }${enumId}Label[${colName}]}</>`;
67
+ return `<>{${col.nullable ? `${colName} && ` : ""}${enumId}Label[${colName}]}</>`;
68
+ }
78
69
  case "array-images":
79
- return `<>{ ${colName}.map(r => ${
80
- col.nullable ? `r && ` : ""
81
- }<img src={r} />) }</>`;
70
+ return `<>{ ${colName}.map(r => ${col.nullable ? `r && ` : ""}<img src={r} />) }</>`;
82
71
  case "number-plain":
83
72
  return `<>{${col.nullable ? `${colName} && ` : ""}numF(${colName})}</>`;
84
73
  case "object":
85
74
  return `<>{/* object ${colName} */}</>`;
86
- case "object-pick":
87
- const pickedChild = col.children!.find(
88
- (child) => child.name === col.config?.picked
89
- );
75
+ case "object-pick": {
76
+ const pickedChild = col.children?.find((child) => child.name === col.config?.picked);
90
77
  if (!pickedChild) {
91
78
  throw new Error(`object-pick 선택 실패 (오브젝트: ${col.name})`);
92
79
  }
@@ -94,8 +81,9 @@ export class Template__view_list extends Template {
94
81
  entityId,
95
82
  pickedChild,
96
83
  names,
97
- `${colName}${col.nullable ? "?" : ""}`
84
+ `${colName}${col.nullable ? "?" : ""}`,
98
85
  );
86
+ }
99
87
  case "array":
100
88
  return `<>{ /* array ${colName} */ }</>`;
101
89
  default:
@@ -106,49 +94,44 @@ export class Template__view_list extends Template {
106
94
  renderColumnImport(
107
95
  entityId: string,
108
96
  col: RenderingNode,
109
- names: EntityNamesRecord
97
+ names: EntityNamesRecord,
110
98
  ): (string | null)[] {
111
99
  if (col.renderType === "enums") {
112
100
  const { id: enumId } = getEnumInfoFromColName(names.capital, col.name);
113
- return [
114
- `import { ${enumId}Label } from 'src/services/sonamu.generated';`,
115
- ];
101
+ return [`import { ${enumId}Label } from 'src/services/sonamu.generated';`];
116
102
  } else if (col.renderType === "object") {
117
103
  try {
118
104
  const relProp = getRelationPropFromColName(entityId, col.name);
119
- const result = col.children!.map((child) => {
105
+ const result = col.children?.map((child) => {
120
106
  entityId = relProp.with;
121
107
  names = EntityManager.getNamesFromId(relProp.with);
122
108
  return this.renderColumnImport(entityId, child, names);
123
109
  });
124
- return _.flattenDeep(result);
110
+ return flat(result ?? []);
125
111
  } catch {
126
112
  return [null];
127
113
  }
128
114
  } else if (col.renderType === "array") {
129
- return this.renderColumnImport(entityId, col.element!, names);
115
+ assert(col.element);
116
+ return this.renderColumnImport(entityId, col.element, names);
130
117
  }
131
118
 
132
119
  return [null];
133
120
  }
134
121
 
135
- renderFilterImport(
136
- entityId: string,
137
- col: RenderingNode,
138
- names: EntityNamesRecord
139
- ) {
122
+ renderFilterImport(entityId: string, col: RenderingNode, names: EntityNamesRecord) {
140
123
  if (col.name === "search") {
141
124
  return `import { ${names.capital}SearchInput } from "src/components/${names.fs}/${names.capital}SearchInput";`;
142
125
  } else if (col.renderType === "enums") {
143
126
  if (col.name === "orderBy") {
144
- const componentId = `${names.capital}${inflection.camelize(
145
- col.name
146
- )}Select`;
127
+ const componentId = `${names.capital}${inflection.camelize(col.name)}Select`;
147
128
  return `import { ${componentId} } from "src/components/${names.fs}/${componentId}";`;
148
129
  } else {
149
130
  try {
150
- const { id, targetEntityNames: targetMDNames } =
151
- getEnumInfoFromColName(entityId, col.name);
131
+ const { id, targetEntityNames: targetMDNames } = getEnumInfoFromColName(
132
+ entityId,
133
+ col.name,
134
+ );
152
135
  const componentId = `${id}Select`;
153
136
  return `import { ${componentId} } from "src/components/${targetMDNames.fs}/${componentId}";`;
154
137
  } catch {
@@ -157,10 +140,7 @@ export class Template__view_list extends Template {
157
140
  }
158
141
  } else if (col.renderType === "number-fk_id") {
159
142
  try {
160
- const relProp = getRelationPropFromColName(
161
- entityId,
162
- col.name.replace("_id", "")
163
- );
143
+ const relProp = getRelationPropFromColName(entityId, col.name.replace("_id", ""));
164
144
  const targetNames = EntityManager.getNamesFromId(relProp.with);
165
145
  const componentId = `${relProp.with}IdAsyncSelect`;
166
146
  return `import { ${componentId} } from "src/components/${targetNames.fs}/${componentId}";`;
@@ -168,9 +148,7 @@ export class Template__view_list extends Template {
168
148
  return "";
169
149
  }
170
150
  } else {
171
- throw new Error(
172
- `렌더 불가능한 필터 임포트 ${col.name} ${col.renderType}`
173
- );
151
+ throw new Error(`렌더 불가능한 필터 임포트 ${col.name} ${col.renderType}`);
174
152
  }
175
153
  }
176
154
 
@@ -192,15 +170,10 @@ export class Template__view_list extends Template {
192
170
  return "";
193
171
  }
194
172
  }
195
- return `<${componentId} {...register('${col.name}')} ${
196
- isClearable ? "clearable" : ""
197
- } />`;
173
+ return `<${componentId} {...register('${col.name}')} ${isClearable ? "clearable" : ""} />`;
198
174
  } else if (col.renderType === "number-fk_id") {
199
175
  try {
200
- const relProp = getRelationPropFromColName(
201
- entityId,
202
- col.name.replace("_id", "")
203
- );
176
+ const relProp = getRelationPropFromColName(entityId, col.name.replace("_id", ""));
204
177
  componentId = `${relProp.with}IdAsyncSelect`;
205
178
  return `<${componentId} {...register('${col.name}')} ${
206
179
  isClearable ? "clearable" : ""
@@ -209,9 +182,7 @@ export class Template__view_list extends Template {
209
182
  return "";
210
183
  }
211
184
  } else {
212
- throw new Error(
213
- `렌더 불가능한 필터 임포트 ${col.name} ${col.renderType}`
214
- );
185
+ throw new Error(`렌더 불가능한 필터 임포트 ${col.name} ${col.renderType}`);
215
186
  }
216
187
  }
217
188
 
@@ -223,9 +194,7 @@ export class Template__view_list extends Template {
223
194
  orderBy: "id-desc",
224
195
  search: "title",
225
196
  };
226
- const orderByZodType = columns.find(
227
- (col) => col.name === "orderBy"
228
- )?.zodType;
197
+ const orderByZodType = columns.find((col) => col.name === "orderBy")?.zodType;
229
198
  if (orderByZodType && orderByZodType instanceof z.ZodEnum) {
230
199
  def.orderBy = orderByZodType.options[0].toString();
231
200
  }
@@ -262,17 +231,16 @@ export class Template__view_list extends Template {
262
231
  (col) =>
263
232
  col.name !== "id" &&
264
233
  col.name !== "queryMode" &&
265
- (["enums", "number-id"].includes(col.renderType) ||
266
- col.name.endsWith("_id"))
234
+ (["enums", "number-id"].includes(col.renderType) || col.name.endsWith("_id")),
267
235
  )
268
236
  // orderBy가 가장 뒤로 오게 순서 조정
269
237
  .sort((a) => {
270
- return a.name == "orderBy" ? 1 : -1;
238
+ return a.name === "orderBy" ? 1 : -1;
271
239
  });
272
240
 
273
241
  // 필터 컬럼을 프리 템플릿으로 설정
274
242
  const preTemplates: RenderedTemplate["preTemplates"] = [];
275
- for (let col of filterColumns) {
243
+ for (const col of filterColumns) {
276
244
  let key: TemplateKey;
277
245
  let targetEntityId = entityId;
278
246
  let enumId: string | undefined;
@@ -285,10 +253,7 @@ export class Template__view_list extends Template {
285
253
  } else {
286
254
  key = "view_enums_select";
287
255
  try {
288
- const { targetEntityNames, id } = getEnumInfoFromColName(
289
- entityId,
290
- col.name
291
- );
256
+ const { targetEntityNames, id } = getEnumInfoFromColName(entityId, col.name);
292
257
  targetEntityId = targetEntityNames.capital;
293
258
  enumId = id;
294
259
  } catch {
@@ -298,10 +263,7 @@ export class Template__view_list extends Template {
298
263
  } else {
299
264
  key = "view_id_async_select";
300
265
  try {
301
- const relProp = getRelationPropFromColName(
302
- entityId,
303
- col.name.replace("_id", "")
304
- );
266
+ const relProp = getRelationPropFromColName(entityId, col.name.replace("_id", ""));
305
267
  targetEntityId = relProp.with;
306
268
  } catch {
307
269
  continue;
@@ -318,17 +280,18 @@ export class Template__view_list extends Template {
318
280
  }
319
281
 
320
282
  // 리스트 컬럼
321
- const columnImports = _.uniq(
322
- columnsNode
323
- .children!.map((col) => {
283
+ assert(columnsNode.children);
284
+ const columnImports = unique(
285
+ columnsNode.children
286
+ .flatMap((col) => {
324
287
  return this.renderColumnImport(entityId, col, names);
325
288
  })
326
- .flat()
327
- .filter((col) => col !== null)
289
+ .filter((col) => col !== null),
328
290
  ).join("\n");
329
291
 
330
292
  // SearchInput
331
- preTemplates!.push({
293
+ assert(preTemplates);
294
+ preTemplates.push({
332
295
  key: "view_search_input",
333
296
  options: {
334
297
  entityId,
@@ -360,12 +323,8 @@ import { DateTime } from "luxon";
360
323
  import { DelButton, EditButton, AppBreadcrumbs, AddButton, useSelection, useListParams, SonamuCol, numF, formatDate, formatDateTime } from '@sonamu-kit/react-sui';
361
324
 
362
325
  import { ${names.capital}SubsetA } from "src/services/sonamu.generated";
363
- import { ${names.capital}Service } from 'src/services/${names.fs}/${
364
- names.fs
365
- }.service';
366
- import { ${names.capital}ListParams } from 'src/services/${names.fs}/${
367
- names.fs
368
- }.types';
326
+ import { ${names.capital}Service } from 'src/services/${names.fs}/${names.fs}.service';
327
+ import { ${names.capital}ListParams } from 'src/services/${names.fs}/${names.fs}.types';
369
328
  ${columnImports}
370
329
  ${filterColumns
371
330
  .map((col) => {
@@ -1,5 +1,5 @@
1
- import { TemplateOptions } from "../../types/types";
2
- import { EntityManager, EntityNamesRecord } from "../../entity/entity-manager";
1
+ import { EntityManager, type EntityNamesRecord } from "../../entity/entity-manager";
2
+ import type { TemplateOptions } from "../../types/types";
3
3
  import { Template } from "../template";
4
4
 
5
5
  export class Template__view_list_columns extends Template {
@@ -15,11 +15,7 @@ export class Template__view_list_columns extends Template {
15
15
  }
16
16
 
17
17
  // 컬럼
18
- render({
19
- entityId,
20
- columns,
21
- columnImports,
22
- }: TemplateOptions["view_list_columns"]) {
18
+ render({ entityId, columns, columnImports }: TemplateOptions["view_list_columns"]) {
23
19
  const names = EntityManager.getNamesFromId(entityId);
24
20
 
25
21
  return {
@@ -35,9 +31,7 @@ import {
35
31
  } from 'semantic-ui-react';
36
32
  import { DateTime } from "luxon";
37
33
  import { TFColumn } from "src/typeframe/iso-types";
38
- import { ${names.capital}SubsetA } from "src/services/${names.fs}/${
39
- names.fs
40
- }.generated";
34
+ import { ${names.capital}SubsetA } from "src/services/${names.fs}/${names.fs}.generated";
41
35
  ${columnImports}
42
36
 
43
37
  const columns: { [key in Exclude<keyof ${
@@ -1,5 +1,5 @@
1
- import { TemplateOptions } from "../../types/types";
2
- import { EntityManager, EntityNamesRecord } from "../../entity/entity-manager";
1
+ import { EntityManager, type EntityNamesRecord } from "../../entity/entity-manager";
2
+ import type { TemplateOptions } from "../../types/types";
3
3
  import { Template } from "../template";
4
4
 
5
5
  export class Template__view_search_input extends Template {
@@ -1,4 +1,6 @@
1
- export * from "./template";
2
- export * from "./helpers";
3
1
  export * from "./entity-converter";
2
+ export * from "./helpers";
3
+ export * from "./template";
4
+ export * from "./template-manager";
5
+ export * from "./template-types";
4
6
  export * from "./zod-converter";
@@ -0,0 +1,166 @@
1
+ import path from "path";
2
+ import type { TemplateKey } from "../types/types";
3
+ import { globAsync } from "../utils/async-utils";
4
+ import { importMembers } from "../utils/esm-utils";
5
+ import { Template } from "./template";
6
+
7
+ class TemplateManagerClass {
8
+ private templates: Map<TemplateKey | string, Template> = new Map();
9
+ isAutoloaded: boolean = false;
10
+
11
+ // ================================
12
+ // 기본 메서드
13
+ // ================================
14
+
15
+ /**
16
+ * 빌트인 템플릿 로드 (implementations/*.template.js)
17
+ */
18
+ async autoload(): Promise<void> {
19
+ if (this.isAutoloaded) {
20
+ return;
21
+ }
22
+ const templateFiles = await globAsync(
23
+ path.join(import.meta.dirname, "implementations/*.template.js"),
24
+ );
25
+
26
+ for (const templateFile of templateFiles) {
27
+ const templates = await importMembers<unknown>(templateFile);
28
+ if (
29
+ templates.length === 1 &&
30
+ typeof templates[0].value === "function" &&
31
+ templates[0].value.prototype instanceof Template
32
+ ) {
33
+ const instance = new (templates[0].value as new () => Template)();
34
+ this.templates.set(instance.key, instance);
35
+ } else {
36
+ throw new Error(
37
+ `Template ${templateFile} should export only one class that extends Template`,
38
+ );
39
+ }
40
+ }
41
+
42
+ for (const [key, template] of this.templates) {
43
+ Template._getTemplatesMap().set(key as TemplateKey, template);
44
+ }
45
+
46
+ this.isAutoloaded = true;
47
+ }
48
+
49
+ /**
50
+ * 템플릿 다시 로드
51
+ */
52
+ async reload(): Promise<void> {
53
+ this.templates.clear();
54
+ Template._clearTemplates();
55
+ this.isAutoloaded = false;
56
+ await this.autoload();
57
+ }
58
+
59
+ /**
60
+ * 프로젝트 디렉토리에서 커스텀 템플릿 로드
61
+ */
62
+ async loadFromDirectory(dir: string): Promise<number> {
63
+ const templateFiles = await globAsync(path.join(dir, "*.template.{ts,js}"));
64
+ let count = 0;
65
+
66
+ for (const file of templateFiles) {
67
+ const templates = await importMembers<unknown>(file);
68
+ for (const { value } of templates) {
69
+ if (this.isTemplateClass(value)) {
70
+ const instance = new (value as new () => Template)();
71
+ this.register(instance);
72
+ count++;
73
+ }
74
+ }
75
+ }
76
+
77
+ return count;
78
+ }
79
+
80
+ private isTemplateClass(value: unknown): boolean {
81
+ return typeof value === "function" && value.prototype instanceof Template;
82
+ }
83
+
84
+ // ================================
85
+ // 템플릿 등록
86
+ // ================================
87
+
88
+ /**
89
+ * 템플릿 등록
90
+ */
91
+ register(template: Template): void {
92
+ this.templates.set(template.key, template);
93
+ // 하위 호환
94
+ Template._getTemplatesMap().set(template.key as TemplateKey, template);
95
+ }
96
+
97
+ /**
98
+ * 여러 템플릿 등록
99
+ */
100
+ registerAll(templates: Template[]): void {
101
+ for (const template of templates) {
102
+ this.register(template);
103
+ }
104
+ }
105
+
106
+ // ================================
107
+ // 템플릿 조회
108
+ // ================================
109
+
110
+ /**
111
+ * 템플릿 조회
112
+ * 빌트인 : 자동완성 지원
113
+ * 커스텀 : 임의 문자열 지원
114
+ */
115
+ get(key: TemplateKey | (string & {})): Template {
116
+ const template = this.templates.get(key);
117
+ if (!template) {
118
+ throw new Error(`Template '${key}' not found. Available: [${this.getAllKeys().join(", ")}]`);
119
+ }
120
+ return template;
121
+ }
122
+
123
+ /**
124
+ * 템플릿 존재 여부
125
+ */
126
+ exists(key: string): boolean {
127
+ return this.templates.has(key);
128
+ }
129
+
130
+ /**
131
+ * 모든 템플릿 키 목록
132
+ */
133
+ getAllKeys(): string[] {
134
+ return Array.from(this.templates.keys()).sort();
135
+ }
136
+
137
+ /**
138
+ * 등록된 템플릿 개수
139
+ */
140
+ get size(): number {
141
+ return this.templates.size;
142
+ }
143
+
144
+ // ================================
145
+ // 테스트 유틸리티
146
+ // ================================
147
+
148
+ /**
149
+ * 모든 상태 초기화 (테스트용)
150
+ */
151
+ reset(): void {
152
+ this.templates.clear();
153
+ this.isAutoloaded = false;
154
+ Template._clearTemplates();
155
+ }
156
+
157
+ /**
158
+ * 격리된 인스턴스 생성 (테스트용)
159
+ */
160
+ static createInstance(): TemplateManagerClass {
161
+ return new TemplateManagerClass();
162
+ }
163
+ }
164
+
165
+ export const TemplateManager = new TemplateManagerClass();
166
+ export { TemplateManagerClass };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * 템플릿 그룹 (관련 템플릿 묶음 실행)
3
+ */
4
+ export type TemplateGroup = {
5
+ name: string;
6
+ description?: string;
7
+ templates: Array<{
8
+ key: string;
9
+ getOptions: (baseOptions: Record<string, unknown>) => Record<string, unknown>;
10
+ }>;
11
+ };
12
+
13
+ /**
14
+ * 템플릿 프리셋 (템플릿별 기본 옵션)
15
+ */
16
+ export type TemplatePreset = Record<string, Record<string, unknown>>;