sonamu 0.7.53 → 0.8.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 (271) hide show
  1. package/dist/api/config.d.ts +9 -1
  2. package/dist/api/config.d.ts.map +1 -1
  3. package/dist/api/config.js +1 -1
  4. package/dist/api/sonamu.d.ts +21 -1
  5. package/dist/api/sonamu.d.ts.map +1 -1
  6. package/dist/api/sonamu.js +159 -65
  7. package/dist/auth/plugins/entity-definitions/anonymous.d.ts +10 -0
  8. package/dist/auth/plugins/entity-definitions/anonymous.d.ts.map +1 -0
  9. package/dist/auth/plugins/entity-definitions/anonymous.js +23 -0
  10. package/dist/auth/plugins/entity-definitions/api-key.d.ts +9 -0
  11. package/dist/auth/plugins/entity-definitions/api-key.d.ts.map +1 -0
  12. package/dist/auth/plugins/entity-definitions/api-key.js +199 -0
  13. package/dist/auth/plugins/entity-definitions/index.d.ts +6 -0
  14. package/dist/auth/plugins/entity-definitions/index.d.ts.map +1 -1
  15. package/dist/auth/plugins/entity-definitions/index.js +20 -2
  16. package/dist/auth/plugins/entity-definitions/jwt.d.ts +9 -0
  17. package/dist/auth/plugins/entity-definitions/jwt.d.ts.map +1 -0
  18. package/dist/auth/plugins/entity-definitions/jwt.js +67 -0
  19. package/dist/auth/plugins/entity-definitions/organization.d.ts +9 -0
  20. package/dist/auth/plugins/entity-definitions/organization.d.ts.map +1 -0
  21. package/dist/auth/plugins/entity-definitions/organization.js +424 -0
  22. package/dist/auth/plugins/entity-definitions/passkey.d.ts +10 -0
  23. package/dist/auth/plugins/entity-definitions/passkey.d.ts.map +1 -0
  24. package/dist/auth/plugins/entity-definitions/passkey.js +129 -0
  25. package/dist/auth/plugins/entity-definitions/sso.d.ts +10 -0
  26. package/dist/auth/plugins/entity-definitions/sso.d.ts.map +1 -0
  27. package/dist/auth/plugins/entity-definitions/sso.js +110 -0
  28. package/dist/auth/plugins/entity-definitions/types.d.ts +1 -1
  29. package/dist/auth/plugins/entity-definitions/types.d.ts.map +1 -1
  30. package/dist/auth/plugins/entity-definitions/types.js +1 -1
  31. package/dist/auth/plugins/wrappers/admin.d.ts.map +1 -1
  32. package/dist/auth/plugins/wrappers/admin.js +2 -4
  33. package/dist/auth/plugins/wrappers/anonymous.d.ts +18 -0
  34. package/dist/auth/plugins/wrappers/anonymous.d.ts.map +1 -0
  35. package/dist/auth/plugins/wrappers/anonymous.js +26 -0
  36. package/dist/auth/plugins/wrappers/api-key.d.ts +18 -0
  37. package/dist/auth/plugins/wrappers/api-key.d.ts.map +1 -0
  38. package/dist/auth/plugins/wrappers/api-key.js +38 -0
  39. package/dist/auth/plugins/wrappers/index.d.ts +6 -0
  40. package/dist/auth/plugins/wrappers/index.d.ts.map +1 -1
  41. package/dist/auth/plugins/wrappers/index.js +7 -1
  42. package/dist/auth/plugins/wrappers/jwt.d.ts +18 -0
  43. package/dist/auth/plugins/wrappers/jwt.d.ts.map +1 -0
  44. package/dist/auth/plugins/wrappers/jwt.js +30 -0
  45. package/dist/auth/plugins/wrappers/organization.d.ts +18 -0
  46. package/dist/auth/plugins/wrappers/organization.d.ts.map +1 -0
  47. package/dist/auth/plugins/wrappers/organization.js +67 -0
  48. package/dist/auth/plugins/wrappers/passkey.d.ts +18 -0
  49. package/dist/auth/plugins/wrappers/passkey.d.ts.map +1 -0
  50. package/dist/auth/plugins/wrappers/passkey.js +32 -0
  51. package/dist/auth/plugins/wrappers/phone-number.d.ts.map +1 -1
  52. package/dist/auth/plugins/wrappers/phone-number.js +2 -4
  53. package/dist/auth/plugins/wrappers/sso.d.ts +853 -0
  54. package/dist/auth/plugins/wrappers/sso.d.ts.map +1 -0
  55. package/dist/auth/plugins/wrappers/sso.js +36 -0
  56. package/dist/auth/plugins/wrappers/two-factor.d.ts.map +1 -1
  57. package/dist/auth/plugins/wrappers/two-factor.js +2 -4
  58. package/dist/auth/plugins/wrappers/username.d.ts.map +1 -1
  59. package/dist/auth/plugins/wrappers/username.js +2 -4
  60. package/dist/bin/build-config.d.ts +2 -2
  61. package/dist/bin/build-config.js +6 -7
  62. package/dist/bin/cli.js +417 -32
  63. package/dist/bin/fixture.d.ts +27 -0
  64. package/dist/bin/fixture.d.ts.map +1 -0
  65. package/dist/bin/fixture.js +245 -0
  66. package/dist/cache/decorator.d.ts +4 -3
  67. package/dist/cache/decorator.d.ts.map +1 -1
  68. package/dist/cache/decorator.js +5 -4
  69. package/dist/cone/cone-generator.d.ts +33 -0
  70. package/dist/cone/cone-generator.d.ts.map +1 -0
  71. package/dist/cone/cone-generator.js +286 -0
  72. package/dist/database/_batch_update.d.ts.map +1 -1
  73. package/dist/database/_batch_update.js +16 -2
  74. package/dist/database/puri-subset.test-d.js +1 -1
  75. package/dist/database/puri-subset.types.d.ts +1 -1
  76. package/dist/database/puri-subset.types.d.ts.map +1 -1
  77. package/dist/database/puri-subset.types.js +1 -1
  78. package/dist/database/puri.d.ts +4 -0
  79. package/dist/database/puri.d.ts.map +1 -1
  80. package/dist/database/puri.js +20 -2
  81. package/dist/database/upsert-builder.d.ts.map +1 -1
  82. package/dist/database/upsert-builder.js +19 -3
  83. package/dist/dict/en.d.ts +15 -0
  84. package/dist/dict/en.d.ts.map +1 -1
  85. package/dist/dict/en.js +2 -1
  86. package/dist/dict/ko.d.ts +15 -0
  87. package/dist/dict/ko.d.ts.map +1 -1
  88. package/dist/dict/ko.js +2 -1
  89. package/dist/dict/rc-keys.d.ts +28 -0
  90. package/dist/dict/rc-keys.d.ts.map +1 -1
  91. package/dist/dict/rc-keys.js +31 -1
  92. package/dist/dict/sd.d.ts.map +1 -1
  93. package/dist/dict/sd.js +20 -4
  94. package/dist/entity/entity-manager.d.ts +298 -2
  95. package/dist/entity/entity-manager.d.ts.map +1 -1
  96. package/dist/entity/entity-manager.js +4 -1
  97. package/dist/entity/entity-template-cone.d.ts +14 -0
  98. package/dist/entity/entity-template-cone.d.ts.map +1 -0
  99. package/dist/entity/entity-template-cone.js +222 -0
  100. package/dist/entity/entity.d.ts +47 -2
  101. package/dist/entity/entity.d.ts.map +1 -1
  102. package/dist/entity/entity.js +161 -14
  103. package/dist/ssr/renderer.js +3 -3
  104. package/dist/syncer/api-parser.js +12 -1
  105. package/dist/syncer/checksum.d.ts +0 -14
  106. package/dist/syncer/checksum.d.ts.map +1 -1
  107. package/dist/syncer/checksum.js +1 -23
  108. package/dist/syncer/syncer-actions.d.ts.map +1 -1
  109. package/dist/syncer/syncer-actions.js +8 -2
  110. package/dist/syncer/syncer.d.ts +1 -1
  111. package/dist/syncer/syncer.d.ts.map +1 -1
  112. package/dist/syncer/syncer.js +17 -10
  113. package/dist/tasks/workflow-manager.d.ts +13 -1
  114. package/dist/tasks/workflow-manager.d.ts.map +1 -1
  115. package/dist/tasks/workflow-manager.js +18 -1
  116. package/dist/template/entity-converter.js +4 -4
  117. package/dist/template/helpers.d.ts +10 -0
  118. package/dist/template/helpers.d.ts.map +1 -1
  119. package/dist/template/helpers.js +48 -1
  120. package/dist/template/implementations/entry-server.template.d.ts +1 -1
  121. package/dist/template/implementations/entry-server.template.js +7 -2
  122. package/dist/template/implementations/generated.template.d.ts.map +1 -1
  123. package/dist/template/implementations/generated.template.js +5 -1
  124. package/dist/template/implementations/generated_http.template.d.ts +1 -0
  125. package/dist/template/implementations/generated_http.template.d.ts.map +1 -1
  126. package/dist/template/implementations/generated_http.template.js +6 -2
  127. package/dist/template/implementations/generated_sso.template.d.ts.map +1 -1
  128. package/dist/template/implementations/generated_sso.template.js +29 -8
  129. package/dist/template/implementations/queries.template.d.ts.map +1 -1
  130. package/dist/template/implementations/queries.template.js +9 -1
  131. package/dist/template/implementations/sd.template.d.ts +1 -1
  132. package/dist/template/implementations/sd.template.d.ts.map +1 -1
  133. package/dist/template/implementations/sd.template.js +28 -4
  134. package/dist/template/implementations/services.template.d.ts.map +1 -1
  135. package/dist/template/implementations/services.template.js +12 -12
  136. package/dist/template/implementations/view_form.template.d.ts +11 -7
  137. package/dist/template/implementations/view_form.template.d.ts.map +1 -1
  138. package/dist/template/implementations/view_form.template.js +97 -87
  139. package/dist/template/implementations/view_list.template.d.ts +3 -3
  140. package/dist/template/implementations/view_list.template.d.ts.map +1 -1
  141. package/dist/template/implementations/view_list.template.js +115 -109
  142. package/dist/template/implementations/view_search_input.template.d.ts.map +1 -1
  143. package/dist/template/implementations/view_search_input.template.js +18 -14
  144. package/dist/template/zod-converter.d.ts.map +1 -1
  145. package/dist/template/zod-converter.js +95 -7
  146. package/dist/testing/_relation-graph.js +1 -1
  147. package/dist/testing/data-explorer.d.ts +61 -0
  148. package/dist/testing/data-explorer.d.ts.map +1 -0
  149. package/dist/testing/data-explorer.js +274 -0
  150. package/dist/testing/faker-mappings.d.ts +20 -0
  151. package/dist/testing/faker-mappings.d.ts.map +1 -0
  152. package/dist/testing/faker-mappings.js +421 -0
  153. package/dist/testing/fixture-generator.d.ts +161 -0
  154. package/dist/testing/fixture-generator.d.ts.map +1 -0
  155. package/dist/testing/fixture-generator.js +954 -0
  156. package/dist/testing/fixture-manager.d.ts +6 -1
  157. package/dist/testing/fixture-manager.d.ts.map +1 -1
  158. package/dist/testing/fixture-manager.js +72 -4
  159. package/dist/testing/index.d.ts +3 -0
  160. package/dist/testing/index.d.ts.map +1 -1
  161. package/dist/testing/index.js +4 -1
  162. package/dist/types/types.d.ts +1520 -26
  163. package/dist/types/types.d.ts.map +1 -1
  164. package/dist/types/types.js +136 -22
  165. package/dist/ui/ai-client.d.ts.map +1 -1
  166. package/dist/ui/ai-client.js +9 -4
  167. package/dist/ui/api.d.ts.map +1 -1
  168. package/dist/ui/api.js +303 -24
  169. package/dist/ui-web/assets/index-CsUr-_pV.js +254 -0
  170. package/dist/ui-web/assets/index-T42zzs1K.css +1 -0
  171. package/dist/ui-web/index.html +2 -2
  172. package/dist/utils/fs-utils.d.ts +2 -1
  173. package/dist/utils/fs-utils.d.ts.map +1 -1
  174. package/dist/utils/fs-utils.js +14 -3
  175. package/package.json +19 -11
  176. package/src/api/config.ts +12 -1
  177. package/src/api/sonamu.ts +179 -65
  178. package/src/auth/plugins/entity-definitions/anonymous.ts +17 -0
  179. package/src/auth/plugins/entity-definitions/api-key.ts +93 -0
  180. package/src/auth/plugins/entity-definitions/index.ts +18 -0
  181. package/src/auth/plugins/entity-definitions/jwt.ts +35 -0
  182. package/src/auth/plugins/entity-definitions/organization.ts +215 -0
  183. package/src/auth/plugins/entity-definitions/passkey.ts +64 -0
  184. package/src/auth/plugins/entity-definitions/sso.ts +62 -0
  185. package/src/auth/plugins/entity-definitions/types.ts +11 -1
  186. package/src/auth/plugins/wrappers/admin.ts +1 -3
  187. package/src/auth/plugins/wrappers/anonymous.ts +30 -0
  188. package/src/auth/plugins/wrappers/api-key.ts +42 -0
  189. package/src/auth/plugins/wrappers/index.ts +6 -0
  190. package/src/auth/plugins/wrappers/jwt.ts +34 -0
  191. package/src/auth/plugins/wrappers/organization.ts +73 -0
  192. package/src/auth/plugins/wrappers/passkey.ts +36 -0
  193. package/src/auth/plugins/wrappers/phone-number.ts +1 -3
  194. package/src/auth/plugins/wrappers/sso.ts +40 -0
  195. package/src/auth/plugins/wrappers/two-factor.ts +1 -3
  196. package/src/auth/plugins/wrappers/username.ts +1 -3
  197. package/src/bin/build-config.ts +6 -6
  198. package/src/bin/cli.ts +452 -31
  199. package/src/bin/fixture.ts +302 -0
  200. package/src/cache/decorator.ts +4 -3
  201. package/src/cone/cone-generator.ts +363 -0
  202. package/src/database/_batch_update.ts +11 -0
  203. package/src/database/puri-subset.test-d.ts +13 -13
  204. package/src/database/puri-subset.types.ts +1 -1
  205. package/src/database/puri.ts +43 -1
  206. package/src/database/upsert-builder.ts +16 -2
  207. package/src/dict/en.ts +1 -0
  208. package/src/dict/ko.ts +1 -0
  209. package/src/dict/rc-keys.ts +32 -0
  210. package/src/dict/sd.ts +23 -3
  211. package/src/entity/entity-manager.ts +4 -0
  212. package/src/entity/entity-template-cone.ts +298 -0
  213. package/src/entity/entity.ts +189 -13
  214. package/src/shared/app.shared.ts.txt +5 -0
  215. package/src/shared/web.shared.ts.txt +9 -5
  216. package/src/skills/project/README.md +21 -0
  217. package/src/skills/project/architecture.md +373 -0
  218. package/src/skills/project/business-logic.md +270 -0
  219. package/src/skills/project/requirements.md +160 -0
  220. package/src/skills/sonamu/SKILL.md +168 -3
  221. package/src/skills/sonamu/api.md +102 -0
  222. package/src/skills/sonamu/database.md +220 -1
  223. package/src/skills/sonamu/entity-relations.md +89 -1
  224. package/src/skills/sonamu/fixture-cli.md +501 -0
  225. package/src/skills/sonamu/frontend.md +214 -0
  226. package/src/skills/sonamu/i18n.md +95 -0
  227. package/src/skills/sonamu/model.md +153 -0
  228. package/src/skills/sonamu/project-init.md +178 -8
  229. package/src/skills/sonamu/scaffolding.md +112 -0
  230. package/src/skills/sonamu/subset.md +9 -3
  231. package/src/skills/sonamu/testing.md +287 -2
  232. package/src/skills/sonamu/workflow.md +70 -5
  233. package/src/ssr/renderer.ts +2 -2
  234. package/src/syncer/api-parser.ts +12 -0
  235. package/src/syncer/checksum.ts +0 -38
  236. package/src/syncer/syncer-actions.ts +7 -1
  237. package/src/syncer/syncer.ts +16 -5
  238. package/src/tasks/workflow-manager.ts +29 -8
  239. package/src/template/entity-converter.ts +3 -3
  240. package/src/template/helpers.ts +49 -0
  241. package/src/template/implementations/entry-server.template.ts +1 -1
  242. package/src/template/implementations/generated.template.ts +4 -0
  243. package/src/template/implementations/generated_http.template.ts +1 -0
  244. package/src/template/implementations/generated_sso.template.ts +40 -11
  245. package/src/template/implementations/queries.template.ts +8 -0
  246. package/src/template/implementations/sd.template.ts +22 -3
  247. package/src/template/implementations/services.template.ts +11 -10
  248. package/src/template/implementations/view_form.template.ts +111 -101
  249. package/src/template/implementations/view_list.template.ts +120 -119
  250. package/src/template/implementations/view_search_input.template.ts +17 -13
  251. package/src/template/zod-converter.ts +103 -6
  252. package/src/testing/_relation-graph.ts +1 -1
  253. package/src/testing/data-explorer.ts +427 -0
  254. package/src/testing/faker-mappings.ts +434 -0
  255. package/src/testing/fixture-generator.ts +1166 -0
  256. package/src/testing/fixture-manager.ts +91 -6
  257. package/src/testing/index.ts +3 -0
  258. package/src/types/types.ts +222 -26
  259. package/src/ui/ai-client.ts +9 -1
  260. package/src/ui/api.ts +429 -23
  261. package/src/utils/fs-utils.ts +14 -1
  262. package/dist/template/implementations/view_enums_select.template.d.ts +0 -17
  263. package/dist/template/implementations/view_enums_select.template.d.ts.map +0 -1
  264. package/dist/template/implementations/view_enums_select.template.js +0 -62
  265. package/dist/template/implementations/view_id_async_select.template.d.ts +0 -17
  266. package/dist/template/implementations/view_id_async_select.template.d.ts.map +0 -1
  267. package/dist/template/implementations/view_id_async_select.template.js +0 -125
  268. package/dist/ui-web/assets/index-Bd_2AkLb.css +0 -1
  269. package/dist/ui-web/assets/index-BpSbhQWo.js +0 -225
  270. package/src/template/implementations/view_enums_select.template.ts +0 -65
  271. package/src/template/implementations/view_id_async_select.template.ts +0 -139
@@ -0,0 +1,27 @@
1
+ import { type DataExplorerStrategy } from "../testing/data-explorer";
2
+ interface FixtureCommandOptions {
3
+ _?: string[];
4
+ all?: boolean;
5
+ include?: string;
6
+ exclude?: string;
7
+ count?: string;
8
+ "save-to"?: string;
9
+ strategy?: DataExplorerStrategy;
10
+ limit?: string;
11
+ }
12
+ /**
13
+ * fixture gen 명령어 - cone 메타데이터를 활용하여 자동으로 fixture를 생성합니다.
14
+ */
15
+ export declare function fixtureGenCommand(options: FixtureCommandOptions): Promise<void>;
16
+ /**
17
+ * fixture fetch 명령어 - 실제 운영 DB에서 데이터를 가져와 fixture로 저장합니다.
18
+ * 관계된 데이터도 함께 가져오므로 현실적인 테스트 데이터를 확보할 수 있습니다.
19
+ */
20
+ export declare function fixtureFetchCommand(options: FixtureCommandOptions): Promise<void>;
21
+ /**
22
+ * fixture explore 명령어 - DB의 실제 데이터를 조회하여 확인합니다.
23
+ * 저장하지 않고 조회만 하므로 데이터를 빠르게 확인할 때 유용합니다.
24
+ */
25
+ export declare function fixtureExploreCommand(options: FixtureCommandOptions): Promise<void>;
26
+ export {};
27
+ //# sourceMappingURL=fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixture.d.ts","sourceRoot":"","sources":["../../src/bin/fixture.ts"],"names":[],"mappings":"AAMA,OAAO,EAAgB,KAAK,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAGnF,UAAU,qBAAqB;IAC7B,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;IACb,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,qBAAqB,iBA0JrE;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,qBAAqB,iBAgEvE;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,qBAAqB,iBAgDzE"}
@@ -0,0 +1,245 @@
1
+ import chalk from "chalk";
2
+ import prompts from "prompts";
3
+ import { Sonamu } from "../api/index.js";
4
+ import { DB } from "../database/db.js";
5
+ import { createKnexInstance } from "../database/knex.js";
6
+ import { EntityManager } from "../entity/entity-manager.js";
7
+ import { DataExplorer } from "../testing/data-explorer.js";
8
+ import { FixtureGenerator } from "../testing/fixture-generator.js";
9
+ /**
10
+ * fixture gen 명령어 - cone 메타데이터를 활용하여 자동으로 fixture를 생성합니다.
11
+ */ export async function fixtureGenCommand(options) {
12
+ try {
13
+ if (!EntityManager.isAutoloaded) {
14
+ await EntityManager.autoload();
15
+ }
16
+ let entityNames;
17
+ if (options.all) {
18
+ entityNames = EntityManager.getAllIds();
19
+ if (options.exclude) {
20
+ const excludeList = options.exclude.split(",").map((s)=>s.trim());
21
+ entityNames = entityNames.filter((name)=>!excludeList.includes(name));
22
+ }
23
+ } else if (options.include) {
24
+ entityNames = options.include.split(",").map((s)=>s.trim());
25
+ } else {
26
+ const result = await prompts({
27
+ type: "multiselect",
28
+ name: "entities",
29
+ message: "Fixture를 생성할 Entity를 선택하세요:",
30
+ choices: EntityManager.getAllIds().map((id)=>({
31
+ title: id,
32
+ value: id
33
+ })),
34
+ min: 1
35
+ });
36
+ if (!result.entities || result.entities.length === 0) {
37
+ console.log(chalk.yellow("취소되었습니다."));
38
+ return;
39
+ }
40
+ entityNames = result.entities;
41
+ }
42
+ let count = options.count ? Number.parseInt(options.count, 10) : 5;
43
+ if (!options.count) {
44
+ const result = await prompts({
45
+ type: "number",
46
+ name: "count",
47
+ message: "각 Entity별 생성 개수:",
48
+ initial: 5,
49
+ min: 1
50
+ });
51
+ if (!result.count) {
52
+ console.log(chalk.yellow("취소되었습니다."));
53
+ return;
54
+ }
55
+ count = result.count;
56
+ }
57
+ let saveTarget = options["save-to"] || "db";
58
+ if (!options["save-to"]) {
59
+ const result = await prompts({
60
+ type: "select",
61
+ name: "saveTarget",
62
+ message: "저장 방식:",
63
+ choices: [
64
+ {
65
+ title: "Fixture DB에 저장",
66
+ value: "db"
67
+ },
68
+ {
69
+ title: "파일로 저장 (자동 파일명)",
70
+ value: "file"
71
+ },
72
+ {
73
+ title: "파일로 저장 (파일명 지정)",
74
+ value: "file:custom"
75
+ },
76
+ {
77
+ title: "저장 안 함 (출력만)",
78
+ value: "none"
79
+ }
80
+ ]
81
+ });
82
+ saveTarget = result.saveTarget;
83
+ if (saveTarget === "file:custom") {
84
+ const filenameResult = await prompts({
85
+ type: "text",
86
+ name: "filename",
87
+ message: "파일명:",
88
+ initial: "fixtures.json"
89
+ });
90
+ if (!filenameResult.filename) {
91
+ console.log(chalk.yellow("취소되었습니다."));
92
+ return;
93
+ }
94
+ saveTarget = `file:${filenameResult.filename}`;
95
+ }
96
+ }
97
+ // fixture gen: fixture DB 내에서 참조 관계를 해결하고 저장합니다
98
+ const fixtureDb = createKnexInstance(Sonamu.dbConfig.fixture);
99
+ const generator = new FixtureGenerator(fixtureDb, fixtureDb, "fixture", EntityManager);
100
+ console.log(chalk.cyan(`\n${entityNames.join(", ")} 생성 중...`));
101
+ const specs = entityNames.map((entityName)=>({
102
+ entity: entityName,
103
+ count,
104
+ overrides: {}
105
+ }));
106
+ const results = await generator.generateBatch(specs);
107
+ console.log(chalk.green(`\n✅ ${results.length}개 fixture 생성 완료`));
108
+ if (saveTarget === "none") {
109
+ console.log(JSON.stringify(results, null, 2));
110
+ } else if (saveTarget === "db") {
111
+ // generateBatch가 이미 DB에 저장했으므로 별도 저장이 불필요합니다.
112
+ console.log(chalk.green("Fixture DB에 저장되었습니다."));
113
+ } else if (saveTarget.startsWith("file")) {
114
+ const fs = await import("node:fs/promises");
115
+ const path = await import("node:path");
116
+ const fixturesDir = path.join(process.cwd(), "test", "fixtures");
117
+ try {
118
+ await fs.access(fixturesDir);
119
+ } catch {
120
+ await fs.mkdir(fixturesDir, {
121
+ recursive: true
122
+ });
123
+ }
124
+ for (const entityName of entityNames){
125
+ const entityResults = results.filter((r)=>r.entityId === entityName);
126
+ if (entityResults.length === 0) {
127
+ continue;
128
+ }
129
+ let filename;
130
+ if (saveTarget === "file") {
131
+ const entity = EntityManager.get(entityName);
132
+ filename = `${entity.table}.json`;
133
+ } else {
134
+ filename = saveTarget.replace("file:", "");
135
+ }
136
+ const filepath = path.join(fixturesDir, filename);
137
+ await fs.writeFile(filepath, JSON.stringify(entityResults.map((r)=>r.data), null, 2));
138
+ console.log(chalk.green(`✅ ${filepath} 저장 완료`));
139
+ }
140
+ }
141
+ } catch (error) {
142
+ console.error(chalk.red("Fixture 생성 중 오류가 발생했습니다.\n" + "원인: Entity 정의나 DB 연결을 확인해주세요.\n" + "자세한 내용:"), error);
143
+ throw error;
144
+ }
145
+ }
146
+ /**
147
+ * fixture fetch 명령어 - 실제 운영 DB에서 데이터를 가져와 fixture로 저장합니다.
148
+ * 관계된 데이터도 함께 가져오므로 현실적인 테스트 데이터를 확보할 수 있습니다.
149
+ */ export async function fixtureFetchCommand(options) {
150
+ try {
151
+ if (!EntityManager.isAutoloaded) {
152
+ await EntityManager.autoload();
153
+ }
154
+ let entityNames;
155
+ if (options.all) {
156
+ entityNames = EntityManager.getAllIds();
157
+ if (options.exclude) {
158
+ const excludeList = options.exclude.split(",").map((s)=>s.trim());
159
+ entityNames = entityNames.filter((name)=>!excludeList.includes(name));
160
+ }
161
+ } else if (options.include) {
162
+ entityNames = options.include.split(",").map((s)=>s.trim());
163
+ } else {
164
+ const result = await prompts({
165
+ type: "multiselect",
166
+ name: "entities",
167
+ message: "Import할 Entity를 선택하세요:",
168
+ choices: EntityManager.getAllIds().map((id)=>({
169
+ title: id,
170
+ value: id
171
+ })),
172
+ min: 1
173
+ });
174
+ if (!result.entities || result.entities.length === 0) {
175
+ console.log(chalk.yellow("취소되었습니다."));
176
+ return;
177
+ }
178
+ entityNames = result.entities;
179
+ }
180
+ const strategy = options.strategy ?? "recent";
181
+ const limit = options.limit ? Number.parseInt(options.limit, 10) : 10;
182
+ // fixture fetch: production 데이터를 fixture DB로 import합니다
183
+ const sourceDb = DB.getDB("r"); // production_master (또는 development_master)
184
+ const fixtureDb = createKnexInstance(Sonamu.dbConfig.fixture);
185
+ const generator = new FixtureGenerator(sourceDb, fixtureDb, "fixture", EntityManager);
186
+ console.log(chalk.cyan(`\n${entityNames.join(", ")} import 중...`));
187
+ for (const entityName of entityNames){
188
+ const results = await generator.importFromSource(entityName, {
189
+ strategy,
190
+ limit,
191
+ includeRelations: true,
192
+ maxDepth: 2
193
+ });
194
+ console.log(chalk.green(`✅ ${entityName}: ${results.length}개 import 완료`));
195
+ }
196
+ } catch (error) {
197
+ console.error(chalk.red("실제 DB에서 데이터를 가져오는 중 오류가 발생했습니다.\n" + "원인: 소스 DB 연결 설정(sonamu.config.ts)이나 Entity 관계 정의를 확인해주세요.\n" + "자세한 내용:"), error);
198
+ throw error;
199
+ }
200
+ }
201
+ /**
202
+ * fixture explore 명령어 - DB의 실제 데이터를 조회하여 확인합니다.
203
+ * 저장하지 않고 조회만 하므로 데이터를 빠르게 확인할 때 유용합니다.
204
+ */ export async function fixtureExploreCommand(options) {
205
+ try {
206
+ if (!EntityManager.isAutoloaded) {
207
+ await EntityManager.autoload();
208
+ }
209
+ let entityName = options.include;
210
+ if (!entityName) {
211
+ const result = await prompts({
212
+ type: "select",
213
+ name: "entity",
214
+ message: "탐색할 Entity:",
215
+ choices: EntityManager.getAllIds().map((id)=>({
216
+ title: id,
217
+ value: id
218
+ }))
219
+ });
220
+ if (!result.entity) {
221
+ console.log(chalk.yellow("취소되었습니다."));
222
+ return;
223
+ }
224
+ entityName = result.entity;
225
+ }
226
+ if (!entityName) {
227
+ throw new Error("Entity name is required");
228
+ }
229
+ const strategy = options.strategy ?? "sample";
230
+ const limit = options.limit ? Number.parseInt(options.limit, 10) : 10;
231
+ const db = DB.getDB("r");
232
+ const explorer = new DataExplorer(db, EntityManager);
233
+ const data = await explorer.explore(entityName, {
234
+ strategy,
235
+ limit
236
+ });
237
+ console.log(chalk.cyan(`\n${entityName} ${data.length}개 조회 완료:`));
238
+ console.table(data);
239
+ } catch (error) {
240
+ console.error(chalk.red("데이터 조회 중 오류가 발생했습니다.\n" + "원인: DB 연결이나 Entity 정의를 확인해주세요.\n" + "자세한 내용:"), error);
241
+ throw error;
242
+ }
243
+ }
244
+
245
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9iaW4vZml4dHVyZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgY2hhbGsgZnJvbSBcImNoYWxrXCI7XG5pbXBvcnQgcHJvbXB0cyBmcm9tIFwicHJvbXB0c1wiO1xuaW1wb3J0IHsgU29uYW11IH0gZnJvbSBcIi4uL2FwaVwiO1xuaW1wb3J0IHsgREIgfSBmcm9tIFwiLi4vZGF0YWJhc2UvZGJcIjtcbmltcG9ydCB7IGNyZWF0ZUtuZXhJbnN0YW5jZSB9IGZyb20gXCIuLi9kYXRhYmFzZS9rbmV4XCI7XG5pbXBvcnQgeyBFbnRpdHlNYW5hZ2VyIH0gZnJvbSBcIi4uL2VudGl0eS9lbnRpdHktbWFuYWdlclwiO1xuaW1wb3J0IHsgRGF0YUV4cGxvcmVyLCB0eXBlIERhdGFFeHBsb3JlclN0cmF0ZWd5IH0gZnJvbSBcIi4uL3Rlc3RpbmcvZGF0YS1leHBsb3JlclwiO1xuaW1wb3J0IHsgRml4dHVyZUdlbmVyYXRvciB9IGZyb20gXCIuLi90ZXN0aW5nL2ZpeHR1cmUtZ2VuZXJhdG9yXCI7XG5cbmludGVyZmFjZSBGaXh0dXJlQ29tbWFuZE9wdGlvbnMge1xuICBfPzogc3RyaW5nW107XG4gIGFsbD86IGJvb2xlYW47XG4gIGluY2x1ZGU/OiBzdHJpbmc7XG4gIGV4Y2x1ZGU/OiBzdHJpbmc7XG4gIGNvdW50Pzogc3RyaW5nO1xuICBcInNhdmUtdG9cIj86IHN0cmluZztcbiAgc3RyYXRlZ3k/OiBEYXRhRXhwbG9yZXJTdHJhdGVneTtcbiAgbGltaXQ/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogZml4dHVyZSBnZW4g66qF66C57Ja0IC0gY29uZSDrqZTtg4DrjbDsnbTthLDrpbwg7Zmc7Jqp7ZWY7JesIOyekOuPmeycvOuhnCBmaXh0dXJl66W8IOyDneyEse2VqeuLiOuLpC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGZpeHR1cmVHZW5Db21tYW5kKG9wdGlvbnM6IEZpeHR1cmVDb21tYW5kT3B0aW9ucykge1xuICB0cnkge1xuICAgIGlmICghRW50aXR5TWFuYWdlci5pc0F1dG9sb2FkZWQpIHtcbiAgICAgIGF3YWl0IEVudGl0eU1hbmFnZXIuYXV0b2xvYWQoKTtcbiAgICB9XG5cbiAgICBsZXQgZW50aXR5TmFtZXM6IHN0cmluZ1tdO1xuXG4gICAgaWYgKG9wdGlvbnMuYWxsKSB7XG4gICAgICBlbnRpdHlOYW1lcyA9IEVudGl0eU1hbmFnZXIuZ2V0QWxsSWRzKCk7XG4gICAgICBpZiAob3B0aW9ucy5leGNsdWRlKSB7XG4gICAgICAgIGNvbnN0IGV4Y2x1ZGVMaXN0ID0gb3B0aW9ucy5leGNsdWRlLnNwbGl0KFwiLFwiKS5tYXAoKHM6IHN0cmluZykgPT4gcy50cmltKCkpO1xuICAgICAgICBlbnRpdHlOYW1lcyA9IGVudGl0eU5hbWVzLmZpbHRlcigobmFtZSkgPT4gIWV4Y2x1ZGVMaXN0LmluY2x1ZGVzKG5hbWUpKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKG9wdGlvbnMuaW5jbHVkZSkge1xuICAgICAgZW50aXR5TmFtZXMgPSBvcHRpb25zLmluY2x1ZGUuc3BsaXQoXCIsXCIpLm1hcCgoczogc3RyaW5nKSA9PiBzLnRyaW0oKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHByb21wdHMoe1xuICAgICAgICB0eXBlOiBcIm11bHRpc2VsZWN0XCIsXG4gICAgICAgIG5hbWU6IFwiZW50aXRpZXNcIixcbiAgICAgICAgbWVzc2FnZTogXCJGaXh0dXJl66W8IOyDneyEse2VoCBFbnRpdHnrpbwg7ISg7YOd7ZWY7IS47JqUOlwiLFxuICAgICAgICBjaG9pY2VzOiBFbnRpdHlNYW5hZ2VyLmdldEFsbElkcygpLm1hcCgoaWQpID0+ICh7IHRpdGxlOiBpZCwgdmFsdWU6IGlkIH0pKSxcbiAgICAgICAgbWluOiAxLFxuICAgICAgfSk7XG5cbiAgICAgIGlmICghcmVzdWx0LmVudGl0aWVzIHx8IHJlc3VsdC5lbnRpdGllcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgY29uc29sZS5sb2coY2hhbGsueWVsbG93KFwi7Leo7IaM65CY7JeI7Iq164uI64ukLlwiKSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgZW50aXR5TmFtZXMgPSByZXN1bHQuZW50aXRpZXM7XG4gICAgfVxuXG4gICAgbGV0IGNvdW50ID0gb3B0aW9ucy5jb3VudCA/IE51bWJlci5wYXJzZUludChvcHRpb25zLmNvdW50LCAxMCkgOiA1O1xuICAgIGlmICghb3B0aW9ucy5jb3VudCkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcHJvbXB0cyh7XG4gICAgICAgIHR5cGU6IFwibnVtYmVyXCIsXG4gICAgICAgIG5hbWU6IFwiY291bnRcIixcbiAgICAgICAgbWVzc2FnZTogXCLqsIEgRW50aXR567OEIOyDneyEsSDqsJzsiJg6XCIsXG4gICAgICAgIGluaXRpYWw6IDUsXG4gICAgICAgIG1pbjogMSxcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoIXJlc3VsdC5jb3VudCkge1xuICAgICAgICBjb25zb2xlLmxvZyhjaGFsay55ZWxsb3coXCLst6jshozrkJjsl4jsirXri4jri6QuXCIpKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb3VudCA9IHJlc3VsdC5jb3VudDtcbiAgICB9XG5cbiAgICBsZXQgc2F2ZVRhcmdldCA9IG9wdGlvbnNbXCJzYXZlLXRvXCJdIHx8IFwiZGJcIjtcbiAgICBpZiAoIW9wdGlvbnNbXCJzYXZlLXRvXCJdKSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBwcm9tcHRzKHtcbiAgICAgICAgdHlwZTogXCJzZWxlY3RcIixcbiAgICAgICAgbmFtZTogXCJzYXZlVGFyZ2V0XCIsXG4gICAgICAgIG1lc3NhZ2U6IFwi7KCA7J6lIOuwqeyLnTpcIixcbiAgICAgICAgY2hvaWNlczogW1xuICAgICAgICAgIHsgdGl0bGU6IFwiRml4dHVyZSBEQuyXkCDsoIDsnqVcIiwgdmFsdWU6IFwiZGJcIiB9LFxuICAgICAgICAgIHsgdGl0bGU6IFwi7YyM7J2866GcIOyggOyepSAo7J6Q64+ZIO2MjOydvOuqhSlcIiwgdmFsdWU6IFwiZmlsZVwiIH0sXG4gICAgICAgICAgeyB0aXRsZTogXCLtjIzsnbzroZwg7KCA7J6lICjtjIzsnbzrqoUg7KeA7KCVKVwiLCB2YWx1ZTogXCJmaWxlOmN1c3RvbVwiIH0sXG4gICAgICAgICAgeyB0aXRsZTogXCLsoIDsnqUg7JWIIO2VqCAo7Lac66Cl66eMKVwiLCB2YWx1ZTogXCJub25lXCIgfSxcbiAgICAgICAgXSxcbiAgICAgIH0pO1xuXG4gICAgICBzYXZlVGFyZ2V0ID0gcmVzdWx0LnNhdmVUYXJnZXQ7XG5cbiAgICAgIGlmIChzYXZlVGFyZ2V0ID09PSBcImZpbGU6Y3VzdG9tXCIpIHtcbiAgICAgICAgY29uc3QgZmlsZW5hbWVSZXN1bHQgPSBhd2FpdCBwcm9tcHRzKHtcbiAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICBuYW1lOiBcImZpbGVuYW1lXCIsXG4gICAgICAgICAgbWVzc2FnZTogXCLtjIzsnbzrqoU6XCIsXG4gICAgICAgICAgaW5pdGlhbDogXCJmaXh0dXJlcy5qc29uXCIsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICghZmlsZW5hbWVSZXN1bHQuZmlsZW5hbWUpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhjaGFsay55ZWxsb3coXCLst6jshozrkJjsl4jsirXri4jri6QuXCIpKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBzYXZlVGFyZ2V0ID0gYGZpbGU6JHtmaWxlbmFtZVJlc3VsdC5maWxlbmFtZX1gO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGZpeHR1cmUgZ2VuOiBmaXh0dXJlIERCIOuCtOyXkOyEnCDssLjsobAg6rSA6rOE66W8IO2VtOqysO2VmOqzoCDsoIDsnqXtlanri4jri6RcbiAgICBjb25zdCBmaXh0dXJlRGIgPSBjcmVhdGVLbmV4SW5zdGFuY2UoU29uYW11LmRiQ29uZmlnLmZpeHR1cmUpO1xuICAgIGNvbnN0IGdlbmVyYXRvciA9IG5ldyBGaXh0dXJlR2VuZXJhdG9yKGZpeHR1cmVEYiwgZml4dHVyZURiLCBcImZpeHR1cmVcIiwgRW50aXR5TWFuYWdlcik7XG5cbiAgICBjb25zb2xlLmxvZyhjaGFsay5jeWFuKGBcXG4ke2VudGl0eU5hbWVzLmpvaW4oXCIsIFwiKX0g7IOd7ISxIOykkS4uLmApKTtcblxuICAgIGNvbnN0IHNwZWNzID0gZW50aXR5TmFtZXMubWFwKChlbnRpdHlOYW1lKSA9PiAoe1xuICAgICAgZW50aXR5OiBlbnRpdHlOYW1lLFxuICAgICAgY291bnQsXG4gICAgICBvdmVycmlkZXM6IHt9LFxuICAgIH0pKTtcblxuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBnZW5lcmF0b3IuZ2VuZXJhdGVCYXRjaChzcGVjcyk7XG5cbiAgICBjb25zb2xlLmxvZyhjaGFsay5ncmVlbihgXFxu4pyFICR7cmVzdWx0cy5sZW5ndGh96rCcIGZpeHR1cmUg7IOd7ISxIOyZhOujjGApKTtcblxuICAgIGlmIChzYXZlVGFyZ2V0ID09PSBcIm5vbmVcIikge1xuICAgICAgY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkocmVzdWx0cywgbnVsbCwgMikpO1xuICAgIH0gZWxzZSBpZiAoc2F2ZVRhcmdldCA9PT0gXCJkYlwiKSB7XG4gICAgICAvLyBnZW5lcmF0ZUJhdGNo6rCAIOydtOuvuCBEQuyXkCDsoIDsnqXtlojsnLzrr4DroZwg67OE64+EIOyggOyepeydtCDrtojtlYTsmpTtlanri4jri6QuXG4gICAgICBjb25zb2xlLmxvZyhjaGFsay5ncmVlbihcIkZpeHR1cmUgRELsl5Ag7KCA7J6l65CY7JeI7Iq164uI64ukLlwiKSk7XG4gICAgfSBlbHNlIGlmIChzYXZlVGFyZ2V0LnN0YXJ0c1dpdGgoXCJmaWxlXCIpKSB7XG4gICAgICBjb25zdCBmcyA9IGF3YWl0IGltcG9ydChcIm5vZGU6ZnMvcHJvbWlzZXNcIik7XG4gICAgICBjb25zdCBwYXRoID0gYXdhaXQgaW1wb3J0KFwibm9kZTpwYXRoXCIpO1xuXG4gICAgICBjb25zdCBmaXh0dXJlc0RpciA9IHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLCBcInRlc3RcIiwgXCJmaXh0dXJlc1wiKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGZzLmFjY2VzcyhmaXh0dXJlc0Rpcik7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgYXdhaXQgZnMubWtkaXIoZml4dHVyZXNEaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IGVudGl0eU5hbWUgb2YgZW50aXR5TmFtZXMpIHtcbiAgICAgICAgY29uc3QgZW50aXR5UmVzdWx0cyA9IHJlc3VsdHMuZmlsdGVyKChyKSA9PiByLmVudGl0eUlkID09PSBlbnRpdHlOYW1lKTtcblxuICAgICAgICBpZiAoZW50aXR5UmVzdWx0cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBmaWxlbmFtZTogc3RyaW5nO1xuICAgICAgICBpZiAoc2F2ZVRhcmdldCA9PT0gXCJmaWxlXCIpIHtcbiAgICAgICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlOYW1lKTtcbiAgICAgICAgICBmaWxlbmFtZSA9IGAke2VudGl0eS50YWJsZX0uanNvbmA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZmlsZW5hbWUgPSBzYXZlVGFyZ2V0LnJlcGxhY2UoXCJmaWxlOlwiLCBcIlwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGZpbGVwYXRoID0gcGF0aC5qb2luKGZpeHR1cmVzRGlyLCBmaWxlbmFtZSk7XG4gICAgICAgIGF3YWl0IGZzLndyaXRlRmlsZShcbiAgICAgICAgICBmaWxlcGF0aCxcbiAgICAgICAgICBKU09OLnN0cmluZ2lmeShcbiAgICAgICAgICAgIGVudGl0eVJlc3VsdHMubWFwKChyKSA9PiByLmRhdGEpLFxuICAgICAgICAgICAgbnVsbCxcbiAgICAgICAgICAgIDIsXG4gICAgICAgICAgKSxcbiAgICAgICAgKTtcbiAgICAgICAgY29uc29sZS5sb2coY2hhbGsuZ3JlZW4oYOKchSAke2ZpbGVwYXRofSDsoIDsnqUg7JmE66OMYCkpO1xuICAgICAgfVxuICAgIH1cbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBjb25zb2xlLmVycm9yKFxuICAgICAgY2hhbGsucmVkKFxuICAgICAgICBcIkZpeHR1cmUg7IOd7ISxIOykkSDsmKTrpZjqsIAg67Cc7IOd7ZaI7Iq164uI64ukLlxcblwiICtcbiAgICAgICAgICBcIuybkOyduDogRW50aXR5IOygleydmOuCmCBEQiDsl7DqsrDsnYQg7ZmV7J247ZW07KO87IS47JqULlxcblwiICtcbiAgICAgICAgICBcIuyekOyEuO2VnCDrgrTsmqk6XCIsXG4gICAgICApLFxuICAgICAgZXJyb3IsXG4gICAgKTtcbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufVxuXG4vKipcbiAqIGZpeHR1cmUgZmV0Y2gg66qF66C57Ja0IC0g7Iuk7KCcIOyatOyYgSBEQuyXkOyEnCDrjbDsnbTthLDrpbwg6rCA7KC47JmAIGZpeHR1cmXroZwg7KCA7J6l7ZWp64uI64ukLlxuICog6rSA6rOE65CcIOuNsOydtO2EsOuPhCDtlajqu5gg6rCA7KC47Jik66+A66GcIO2YhOyLpOyggeyduCDthYzsiqTtirgg642w7J207YSw66W8IO2ZleuztO2VoCDsiJgg7J6I7Iq164uI64ukLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZml4dHVyZUZldGNoQ29tbWFuZChvcHRpb25zOiBGaXh0dXJlQ29tbWFuZE9wdGlvbnMpIHtcbiAgdHJ5IHtcbiAgICBpZiAoIUVudGl0eU1hbmFnZXIuaXNBdXRvbG9hZGVkKSB7XG4gICAgICBhd2FpdCBFbnRpdHlNYW5hZ2VyLmF1dG9sb2FkKCk7XG4gICAgfVxuXG4gICAgbGV0IGVudGl0eU5hbWVzOiBzdHJpbmdbXTtcblxuICAgIGlmIChvcHRpb25zLmFsbCkge1xuICAgICAgZW50aXR5TmFtZXMgPSBFbnRpdHlNYW5hZ2VyLmdldEFsbElkcygpO1xuICAgICAgaWYgKG9wdGlvbnMuZXhjbHVkZSkge1xuICAgICAgICBjb25zdCBleGNsdWRlTGlzdCA9IG9wdGlvbnMuZXhjbHVkZS5zcGxpdChcIixcIikubWFwKChzOiBzdHJpbmcpID0+IHMudHJpbSgpKTtcbiAgICAgICAgZW50aXR5TmFtZXMgPSBlbnRpdHlOYW1lcy5maWx0ZXIoKG5hbWUpID0+ICFleGNsdWRlTGlzdC5pbmNsdWRlcyhuYW1lKSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChvcHRpb25zLmluY2x1ZGUpIHtcbiAgICAgIGVudGl0eU5hbWVzID0gb3B0aW9ucy5pbmNsdWRlLnNwbGl0KFwiLFwiKS5tYXAoKHM6IHN0cmluZykgPT4gcy50cmltKCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBwcm9tcHRzKHtcbiAgICAgICAgdHlwZTogXCJtdWx0aXNlbGVjdFwiLFxuICAgICAgICBuYW1lOiBcImVudGl0aWVzXCIsXG4gICAgICAgIG1lc3NhZ2U6IFwiSW1wb3J07ZWgIEVudGl0eeulvCDshKDtg53tlZjshLjsmpQ6XCIsXG4gICAgICAgIGNob2ljZXM6IEVudGl0eU1hbmFnZXIuZ2V0QWxsSWRzKCkubWFwKChpZCkgPT4gKHsgdGl0bGU6IGlkLCB2YWx1ZTogaWQgfSkpLFxuICAgICAgICBtaW46IDEsXG4gICAgICB9KTtcblxuICAgICAgaWYgKCFyZXN1bHQuZW50aXRpZXMgfHwgcmVzdWx0LmVudGl0aWVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBjb25zb2xlLmxvZyhjaGFsay55ZWxsb3coXCLst6jshozrkJjsl4jsirXri4jri6QuXCIpKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBlbnRpdHlOYW1lcyA9IHJlc3VsdC5lbnRpdGllcztcbiAgICB9XG5cbiAgICBjb25zdCBzdHJhdGVneTogRGF0YUV4cGxvcmVyU3RyYXRlZ3kgPSBvcHRpb25zLnN0cmF0ZWd5ID8/IFwicmVjZW50XCI7XG4gICAgY29uc3QgbGltaXQgPSBvcHRpb25zLmxpbWl0ID8gTnVtYmVyLnBhcnNlSW50KG9wdGlvbnMubGltaXQsIDEwKSA6IDEwO1xuXG4gICAgLy8gZml4dHVyZSBmZXRjaDogcHJvZHVjdGlvbiDrjbDsnbTthLDrpbwgZml4dHVyZSBEQuuhnCBpbXBvcnTtlanri4jri6RcbiAgICBjb25zdCBzb3VyY2VEYiA9IERCLmdldERCKFwiclwiKTsgLy8gcHJvZHVjdGlvbl9tYXN0ZXIgKOuYkOuKlCBkZXZlbG9wbWVudF9tYXN0ZXIpXG4gICAgY29uc3QgZml4dHVyZURiID0gY3JlYXRlS25leEluc3RhbmNlKFNvbmFtdS5kYkNvbmZpZy5maXh0dXJlKTtcbiAgICBjb25zdCBnZW5lcmF0b3IgPSBuZXcgRml4dHVyZUdlbmVyYXRvcihzb3VyY2VEYiwgZml4dHVyZURiLCBcImZpeHR1cmVcIiwgRW50aXR5TWFuYWdlcik7XG5cbiAgICBjb25zb2xlLmxvZyhjaGFsay5jeWFuKGBcXG4ke2VudGl0eU5hbWVzLmpvaW4oXCIsIFwiKX0gaW1wb3J0IOykkS4uLmApKTtcblxuICAgIGZvciAoY29uc3QgZW50aXR5TmFtZSBvZiBlbnRpdHlOYW1lcykge1xuICAgICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IGdlbmVyYXRvci5pbXBvcnRGcm9tU291cmNlKGVudGl0eU5hbWUsIHtcbiAgICAgICAgc3RyYXRlZ3ksXG4gICAgICAgIGxpbWl0LFxuICAgICAgICBpbmNsdWRlUmVsYXRpb25zOiB0cnVlLFxuICAgICAgICBtYXhEZXB0aDogMixcbiAgICAgIH0pO1xuXG4gICAgICBjb25zb2xlLmxvZyhjaGFsay5ncmVlbihg4pyFICR7ZW50aXR5TmFtZX06ICR7cmVzdWx0cy5sZW5ndGh96rCcIGltcG9ydCDsmYTro4xgKSk7XG4gICAgfVxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICBjaGFsay5yZWQoXG4gICAgICAgIFwi7Iuk7KCcIERC7JeQ7IScIOuNsOydtO2EsOulvCDqsIDsoLjsmKTripQg7KSRIOyYpOulmOqwgCDrsJzsg53tlojsirXri4jri6QuXFxuXCIgK1xuICAgICAgICAgIFwi7JuQ7J24OiDshozsiqQgREIg7Jew6rKwIOyEpOyglShzb25hbXUuY29uZmlnLnRzKeydtOuCmCBFbnRpdHkg6rSA6rOEIOygleydmOulvCDtmZXsnbjtlbTso7zshLjsmpQuXFxuXCIgK1xuICAgICAgICAgIFwi7J6Q7IS47ZWcIOuCtOyaqTpcIixcbiAgICAgICksXG4gICAgICBlcnJvcixcbiAgICApO1xuICAgIHRocm93IGVycm9yO1xuICB9XG59XG5cbi8qKlxuICogZml4dHVyZSBleHBsb3JlIOuqheugueyWtCAtIERC7J2YIOyLpOygnCDrjbDsnbTthLDrpbwg7KGw7ZqM7ZWY7JesIO2ZleyduO2VqeuLiOuLpC5cbiAqIOyggOyepe2VmOyngCDslYrqs6Ag7KGw7ZqM66eMIO2VmOuvgOuhnCDrjbDsnbTthLDrpbwg67mg66W06rKMIO2ZleyduO2VoCDrlYwg7Jyg7Jqp7ZWp64uI64ukLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZml4dHVyZUV4cGxvcmVDb21tYW5kKG9wdGlvbnM6IEZpeHR1cmVDb21tYW5kT3B0aW9ucykge1xuICB0cnkge1xuICAgIGlmICghRW50aXR5TWFuYWdlci5pc0F1dG9sb2FkZWQpIHtcbiAgICAgIGF3YWl0IEVudGl0eU1hbmFnZXIuYXV0b2xvYWQoKTtcbiAgICB9XG5cbiAgICBsZXQgZW50aXR5TmFtZSA9IG9wdGlvbnMuaW5jbHVkZTtcblxuICAgIGlmICghZW50aXR5TmFtZSkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcHJvbXB0cyh7XG4gICAgICAgIHR5cGU6IFwic2VsZWN0XCIsXG4gICAgICAgIG5hbWU6IFwiZW50aXR5XCIsXG4gICAgICAgIG1lc3NhZ2U6IFwi7YOQ7IOJ7ZWgIEVudGl0eTpcIixcbiAgICAgICAgY2hvaWNlczogRW50aXR5TWFuYWdlci5nZXRBbGxJZHMoKS5tYXAoKGlkKSA9PiAoeyB0aXRsZTogaWQsIHZhbHVlOiBpZCB9KSksXG4gICAgICB9KTtcblxuICAgICAgaWYgKCFyZXN1bHQuZW50aXR5KSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGNoYWxrLnllbGxvdyhcIuy3qOyGjOuQmOyXiOyKteuLiOuLpC5cIikpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGVudGl0eU5hbWUgPSByZXN1bHQuZW50aXR5O1xuICAgIH1cblxuICAgIGlmICghZW50aXR5TmFtZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRW50aXR5IG5hbWUgaXMgcmVxdWlyZWRcIik7XG4gICAgfVxuXG4gICAgY29uc3Qgc3RyYXRlZ3k6IERhdGFFeHBsb3JlclN0cmF0ZWd5ID0gb3B0aW9ucy5zdHJhdGVneSA/PyBcInNhbXBsZVwiO1xuICAgIGNvbnN0IGxpbWl0ID0gb3B0aW9ucy5saW1pdCA/IE51bWJlci5wYXJzZUludChvcHRpb25zLmxpbWl0LCAxMCkgOiAxMDtcblxuICAgIGNvbnN0IGRiID0gREIuZ2V0REIoXCJyXCIpO1xuICAgIGNvbnN0IGV4cGxvcmVyID0gbmV3IERhdGFFeHBsb3JlcihkYiwgRW50aXR5TWFuYWdlcik7XG4gICAgY29uc3QgZGF0YSA9IGF3YWl0IGV4cGxvcmVyLmV4cGxvcmUoZW50aXR5TmFtZSwgeyBzdHJhdGVneSwgbGltaXQgfSk7XG5cbiAgICBjb25zb2xlLmxvZyhjaGFsay5jeWFuKGBcXG4ke2VudGl0eU5hbWV9ICR7ZGF0YS5sZW5ndGh96rCcIOyhsO2ajCDsmYTro4w6YCkpO1xuICAgIGNvbnNvbGUudGFibGUoZGF0YSk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgY29uc29sZS5lcnJvcihcbiAgICAgIGNoYWxrLnJlZChcbiAgICAgICAgXCLrjbDsnbTthLAg7KGw7ZqMIOykkSDsmKTrpZjqsIAg67Cc7IOd7ZaI7Iq164uI64ukLlxcblwiICtcbiAgICAgICAgICBcIuybkOyduDogREIg7Jew6rKw7J2064KYIEVudGl0eSDsoJXsnZjrpbwg7ZmV7J247ZW07KO87IS47JqULlxcblwiICtcbiAgICAgICAgICBcIuyekOyEuO2VnCDrgrTsmqk6XCIsXG4gICAgICApLFxuICAgICAgZXJyb3IsXG4gICAgKTtcbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufVxuIl0sIm5hbWVzIjpbImNoYWxrIiwicHJvbXB0cyIsIlNvbmFtdSIsIkRCIiwiY3JlYXRlS25leEluc3RhbmNlIiwiRW50aXR5TWFuYWdlciIsIkRhdGFFeHBsb3JlciIsIkZpeHR1cmVHZW5lcmF0b3IiLCJmaXh0dXJlR2VuQ29tbWFuZCIsIm9wdGlvbnMiLCJpc0F1dG9sb2FkZWQiLCJhdXRvbG9hZCIsImVudGl0eU5hbWVzIiwiYWxsIiwiZ2V0QWxsSWRzIiwiZXhjbHVkZSIsImV4Y2x1ZGVMaXN0Iiwic3BsaXQiLCJtYXAiLCJzIiwidHJpbSIsImZpbHRlciIsIm5hbWUiLCJpbmNsdWRlcyIsImluY2x1ZGUiLCJyZXN1bHQiLCJ0eXBlIiwibWVzc2FnZSIsImNob2ljZXMiLCJpZCIsInRpdGxlIiwidmFsdWUiLCJtaW4iLCJlbnRpdGllcyIsImxlbmd0aCIsImNvbnNvbGUiLCJsb2ciLCJ5ZWxsb3ciLCJjb3VudCIsIk51bWJlciIsInBhcnNlSW50IiwiaW5pdGlhbCIsInNhdmVUYXJnZXQiLCJmaWxlbmFtZVJlc3VsdCIsImZpbGVuYW1lIiwiZml4dHVyZURiIiwiZGJDb25maWciLCJmaXh0dXJlIiwiZ2VuZXJhdG9yIiwiY3lhbiIsImpvaW4iLCJzcGVjcyIsImVudGl0eU5hbWUiLCJlbnRpdHkiLCJvdmVycmlkZXMiLCJyZXN1bHRzIiwiZ2VuZXJhdGVCYXRjaCIsImdyZWVuIiwiSlNPTiIsInN0cmluZ2lmeSIsInN0YXJ0c1dpdGgiLCJmcyIsInBhdGgiLCJmaXh0dXJlc0RpciIsInByb2Nlc3MiLCJjd2QiLCJhY2Nlc3MiLCJta2RpciIsInJlY3Vyc2l2ZSIsImVudGl0eVJlc3VsdHMiLCJyIiwiZW50aXR5SWQiLCJnZXQiLCJ0YWJsZSIsInJlcGxhY2UiLCJmaWxlcGF0aCIsIndyaXRlRmlsZSIsImRhdGEiLCJlcnJvciIsInJlZCIsImZpeHR1cmVGZXRjaENvbW1hbmQiLCJzdHJhdGVneSIsImxpbWl0Iiwic291cmNlRGIiLCJnZXREQiIsImltcG9ydEZyb21Tb3VyY2UiLCJpbmNsdWRlUmVsYXRpb25zIiwibWF4RGVwdGgiLCJmaXh0dXJlRXhwbG9yZUNvbW1hbmQiLCJFcnJvciIsImRiIiwiZXhwbG9yZXIiLCJleHBsb3JlIl0sIm1hcHBpbmdzIjoiQUFBQSxPQUFPQSxXQUFXLFFBQVE7QUFDMUIsT0FBT0MsYUFBYSxVQUFVO0FBQzlCLFNBQVNDLE1BQU0sUUFBUSxrQkFBUztBQUNoQyxTQUFTQyxFQUFFLFFBQVEsb0JBQWlCO0FBQ3BDLFNBQVNDLGtCQUFrQixRQUFRLHNCQUFtQjtBQUN0RCxTQUFTQyxhQUFhLFFBQVEsOEJBQTJCO0FBQ3pELFNBQVNDLFlBQVksUUFBbUMsOEJBQTJCO0FBQ25GLFNBQVNDLGdCQUFnQixRQUFRLGtDQUErQjtBQWFoRTs7Q0FFQyxHQUNELE9BQU8sZUFBZUMsa0JBQWtCQyxPQUE4QjtJQUNwRSxJQUFJO1FBQ0YsSUFBSSxDQUFDSixjQUFjSyxZQUFZLEVBQUU7WUFDL0IsTUFBTUwsY0FBY00sUUFBUTtRQUM5QjtRQUVBLElBQUlDO1FBRUosSUFBSUgsUUFBUUksR0FBRyxFQUFFO1lBQ2ZELGNBQWNQLGNBQWNTLFNBQVM7WUFDckMsSUFBSUwsUUFBUU0sT0FBTyxFQUFFO2dCQUNuQixNQUFNQyxjQUFjUCxRQUFRTSxPQUFPLENBQUNFLEtBQUssQ0FBQyxLQUFLQyxHQUFHLENBQUMsQ0FBQ0MsSUFBY0EsRUFBRUMsSUFBSTtnQkFDeEVSLGNBQWNBLFlBQVlTLE1BQU0sQ0FBQyxDQUFDQyxPQUFTLENBQUNOLFlBQVlPLFFBQVEsQ0FBQ0Q7WUFDbkU7UUFDRixPQUFPLElBQUliLFFBQVFlLE9BQU8sRUFBRTtZQUMxQlosY0FBY0gsUUFBUWUsT0FBTyxDQUFDUCxLQUFLLENBQUMsS0FBS0MsR0FBRyxDQUFDLENB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
@@ -18,11 +18,12 @@ export declare function getCacheManagerRef(): CacheManager | null;
18
18
  * 메서드의 결과를 캐싱합니다.
19
19
  *
20
20
  * @example
21
- * class UserModelClass extends BaseModel {
21
+ * class UserModelClass extends BaseModelClass<...> {
22
22
  * @cache({ ttl: '10m', tags: ['user'] })
23
23
  * @api()
24
- * async findById(id: number) {
25
- * return this.findOne(['id', id]);
24
+ * async findById(subset: UserSubsetKey, id: string) {
25
+ * const { rows } = await this.findMany(subset, { id, num: 1, page: 1 });
26
+ * return rows[0];
26
27
  * }
27
28
  * }
28
29
  */
@@ -1 +1 @@
1
- {"version":3,"file":"decorator.d.ts","sourceRoot":"","sources":["../../src/cache/decorator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEnE,KAAK,eAAe,GAAG;IAAE,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAKzD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI,CAErE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,YAAY,GAAG,IAAI,CAExD;AAoDD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,KAAK,CAAC,OAAO,GAAE,qBAA0B,IAC/C,SAAS,eAAe,EAAE,aAAa,MAAM,EAAE,YAAY,kBAAkB,wBA2BtF"}
1
+ {"version":3,"file":"decorator.d.ts","sourceRoot":"","sources":["../../src/cache/decorator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEnE,KAAK,eAAe,GAAG;IAAE,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAKzD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI,CAErE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,YAAY,GAAG,IAAI,CAExD;AAoDD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,KAAK,CAAC,OAAO,GAAE,qBAA0B,IAC/C,SAAS,eAAe,EAAE,aAAa,MAAM,EAAE,YAAY,kBAAkB,wBA2BtF"}
@@ -54,11 +54,12 @@ let cacheManagerRef = null;
54
54
  * 메서드의 결과를 캐싱합니다.
55
55
  *
56
56
  * @example
57
- * class UserModelClass extends BaseModel {
57
+ * class UserModelClass extends BaseModelClass<...> {
58
58
  * @cache({ ttl: '10m', tags: ['user'] })
59
59
  * @api()
60
- * async findById(id: number) {
61
- * return this.findOne(['id', id]);
60
+ * async findById(subset: UserSubsetKey, id: string) {
61
+ * const { rows } = await this.findMany(subset, { id, num: 1, page: 1 });
62
+ * return rows[0];
62
63
  * }
63
64
  * }
64
65
  */ export function cache(options = {}) {
@@ -83,4 +84,4 @@ let cacheManagerRef = null;
83
84
  };
84
85
  }
85
86
 
86
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jYWNoZS9kZWNvcmF0b3IudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBCYXNlRnJhbWVDbGFzcyB9IGZyb20gXCIuLi9hcGkvYmFzZS1mcmFtZVwiO1xuaW1wb3J0IHsgQmFzZU1vZGVsQ2xhc3MgfSBmcm9tIFwiLi4vZGF0YWJhc2UvYmFzZS1tb2RlbFwiO1xuaW1wb3J0IHR5cGUgeyBDYWNoZURlY29yYXRvck9wdGlvbnMsIENhY2hlTWFuYWdlciB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbnR5cGUgRGVjb3JhdG9yVGFyZ2V0ID0geyBjb25zdHJ1Y3RvcjogeyBuYW1lOiBzdHJpbmcgfSB9O1xuXG4vLyDsupDsi5wg66ek64uI7KCAIOywuOyhsCAoU29uYW11LmluaXTsl5DshJwg7ISk7KCV65CoKVxubGV0IGNhY2hlTWFuYWdlclJlZjogQ2FjaGVNYW5hZ2VyIHwgbnVsbCA9IG51bGw7XG5cbi8qKlxuICog7LqQ7IucIOunpOuLiOyggCDssLjsobAg7ISk7KCVICjrgrTrtoAg7IKs7JqpKVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0Q2FjaGVNYW5hZ2VyUmVmKG1hbmFnZXI6IENhY2hlTWFuYWdlciB8IG51bGwpOiB2b2lkIHtcbiAgY2FjaGVNYW5hZ2VyUmVmID0gbWFuYWdlcjtcbn1cblxuLyoqXG4gKiDsupDsi5wg66ek64uI7KCAIOywuOyhsCDqsIDsoLjsmKTquLAgKOuCtOu2gCDsgqzsmqkpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRDYWNoZU1hbmFnZXJSZWYoKTogQ2FjaGVNYW5hZ2VyIHwgbnVsbCB7XG4gIHJldHVybiBjYWNoZU1hbmFnZXJSZWY7XG59XG5cbi8qKlxuICog7LqQ7IucIO2CpCDsg53shLFcbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVDYWNoZUtleShcbiAgbW9kZWxOYW1lOiBzdHJpbmcsXG4gIG1ldGhvZE5hbWU6IHN0cmluZyxcbiAgYXJnczogdW5rbm93bltdLFxuICBrZXlPcHRpb24/OiBDYWNoZURlY29yYXRvck9wdGlvbnNbXCJrZXlcIl0sXG4pOiBzdHJpbmcge1xuICAvLyDsu6TsiqTthYAg7YKkIO2VqOyImCDsgqzsmqlcbiAgaWYgKHR5cGVvZiBrZXlPcHRpb24gPT09IFwiZnVuY3Rpb25cIikge1xuICAgIHJldHVybiBrZXlPcHRpb24oLi4uYXJncyk7XG4gIH1cblxuICAvLyDrrLjsnpDsl7Qg7YKkICsgYXJncyBzdWZmaXhcbiAgaWYgKHR5cGVvZiBrZXlPcHRpb24gPT09IFwic3RyaW5nXCIpIHtcbiAgICBjb25zdCBhcmdzU3VmZml4ID0gc2VyaWFsaXplQXJncyhhcmdzKTtcbiAgICByZXR1cm4gYXJnc1N1ZmZpeCA/IGAke2tleU9wdGlvbn06JHthcmdzU3VmZml4fWAgOiBrZXlPcHRpb247XG4gIH1cblxuICAvLyDsnpDrj5kg7IOd7ISxOiBNb2RlbE5hbWUubWV0aG9kTmFtZTpzZXJpYWxpemVkQXJnc1xuICBjb25zdCBiYXNlS2V5ID0gYCR7bW9kZWxOYW1lfS4ke21ldGhvZE5hbWV9YDtcbiAgY29uc3QgYXJnc1N1ZmZpeCA9IHNlcmlhbGl6ZUFyZ3MoYXJncyk7XG4gIHJldHVybiBhcmdzU3VmZml4ID8gYCR7YmFzZUtleX06JHthcmdzU3VmZml4fWAgOiBiYXNlS2V5O1xufVxuXG4vKipcbiAqIOyduOyekCDsp4HroKztmZRcbiAqL1xuZnVuY3Rpb24gc2VyaWFsaXplQXJncyhhcmdzOiB1bmtub3duW10pOiBzdHJpbmcge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDApIHJldHVybiBcIlwiO1xuXG4gIC8vIOuLqOydvCBwcmltaXRpdmUg6rCSXG4gIGlmIChhcmdzLmxlbmd0aCA9PT0gMSkge1xuICAgIGNvbnN0IGFyZyA9IGFyZ3NbMF07XG4gICAgaWYgKGFyZyA9PT0gbnVsbCB8fCBhcmcgPT09IHVuZGVmaW5lZCkgcmV0dXJuIFwiXCI7XG4gICAgaWYgKHR5cGVvZiBhcmcgPT09IFwic3RyaW5nXCIgfHwgdHlwZW9mIGFyZyA9PT0gXCJudW1iZXJcIiB8fCB0eXBlb2YgYXJnID09PSBcImJvb2xlYW5cIikge1xuICAgICAgcmV0dXJuIFN0cmluZyhhcmcpO1xuICAgIH1cbiAgfVxuXG4gIC8vIOuzteyeoe2VnCDqsJLsnYAgSlNPTiDsp4HroKztmZRcbiAgdHJ5IHtcbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoYXJncyk7XG4gIH0gY2F0Y2gge1xuICAgIC8vIOyngeugrO2ZlCDsi6TtjKgg7IucIHRvU3RyaW5nIOyCrOyaqVxuICAgIHJldHVybiBhcmdzLm1hcCgoYXJnKSA9PiBTdHJpbmcoYXJnKSkuam9pbihcIjpcIik7XG4gIH1cbn1cblxuLyoqXG4gKiBAY2FjaGUg642w7L2U66CI7J207YSwXG4gKlxuICog66mU7ISc65Oc7J2YIOqysOqzvOulvCDsupDsi7Htlanri4jri6QuXG4gKlxuICogQGV4YW1wbGVcbiAqIGNsYXNzIFVzZXJNb2RlbENsYXNzIGV4dGVuZHMgQmFzZU1vZGVsIHtcbiAqICAgQGNhY2hlKHsgdHRsOiAnMTBtJywgdGFnczogWyd1c2VyJ10gfSlcbiAqICAgQGFwaSgpXG4gKiAgIGFzeW5jIGZpbmRCeUlkKGlkOiBudW1iZXIpIHtcbiAqICAgICByZXR1cm4gdGhpcy5maW5kT25lKFsnaWQnLCBpZF0pO1xuICogICB9XG4gKiB9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjYWNoZShvcHRpb25zOiBDYWNoZURlY29yYXRvck9wdGlvbnMgPSB7fSkge1xuICByZXR1cm4gKF90YXJnZXQ6IERlY29yYXRvclRhcmdldCwgcHJvcGVydHlLZXk6IHN0cmluZywgZGVzY3JpcHRvcjogUHJvcGVydHlEZXNjcmlwdG9yKSA9PiB7XG4gICAgY29uc3Qgb3JpZ2luYWxNZXRob2QgPSBkZXNjcmlwdG9yLnZhbHVlO1xuXG4gICAgZGVzY3JpcHRvci52YWx1ZSA9IGFzeW5jIGZ1bmN0aW9uICh0aGlzOiBCYXNlTW9kZWxDbGFzcyB8IEJhc2VGcmFtZUNsYXNzLCAuLi5hcmdzOiB1bmtub3duW10pIHtcbiAgICAgIGNvbnN0IG1hbmFnZXIgPSBjYWNoZU1hbmFnZXJSZWY7XG5cbiAgICAgIGlmICghbWFuYWdlcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgXCJDYWNoZU1hbmFnZXIgaXMgbm90IGluaXRpYWxpemVkLiBQbGVhc2UgY29uZmlndXJlICdjYWNoZScgaW4gc29uYW11LmNvbmZpZy50cy5cIixcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbW9kZWxOYW1lID0gdGhpcyBpbnN0YW5jZW9mIEJhc2VNb2RlbENsYXNzID8gdGhpcy5tb2RlbE5hbWUgOiB0aGlzLmZyYW1lTmFtZTtcbiAgICAgIGNvbnN0IG1ldGhvZE5hbWUgPSBwcm9wZXJ0eUtleTtcblxuICAgICAgY29uc3QgY2FjaGVLZXkgPSBnZW5lcmF0ZUNhY2hlS2V5KG1vZGVsTmFtZSwgbWV0aG9kTmFtZSwgYXJncywgb3B0aW9ucy5rZXkpO1xuICAgICAgY29uc3Qgc3RvcmUgPSBvcHRpb25zLnN0b3JlID8gbWFuYWdlci51c2Uob3B0aW9ucy5zdG9yZSkgOiBtYW5hZ2VyO1xuXG4gICAgICByZXR1cm4gc3RvcmUuZ2V0T3JTZXQoe1xuICAgICAgICAuLi5vcHRpb25zLFxuICAgICAgICBrZXk6IGNhY2hlS2V5LFxuICAgICAgICBmYWN0b3J5OiAoKSA9PiBvcmlnaW5hbE1ldGhvZC5hcHBseSh0aGlzLCBhcmdzKSxcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICByZXR1cm4gZGVzY3JpcHRvcjtcbiAgfTtcbn1cbiJdLCJuYW1lcyI6WyJCYXNlTW9kZWxDbGFzcyIsImNhY2hlTWFuYWdlclJlZiIsInNldENhY2hlTWFuYWdlclJlZiIsIm1hbmFnZXIiLCJnZXRDYWNoZU1hbmFnZXJSZWYiLCJnZW5lcmF0ZUNhY2hlS2V5IiwibW9kZWxOYW1lIiwibWV0aG9kTmFtZSIsImFyZ3MiLCJrZXlPcHRpb24iLCJhcmdzU3VmZml4Iiwic2VyaWFsaXplQXJncyIsImJhc2VLZXkiLCJsZW5ndGgiLCJhcmciLCJ1bmRlZmluZWQiLCJTdHJpbmciLCJKU09OIiwic3RyaW5naWZ5IiwibWFwIiwiam9pbiIsImNhY2hlIiwib3B0aW9ucyIsIl90YXJnZXQiLCJwcm9wZXJ0eUtleSIsImRlc2NyaXB0b3IiLCJvcmlnaW5hbE1ldGhvZCIsInZhbHVlIiwiRXJyb3IiLCJmcmFtZU5hbWUiLCJjYWNoZUtleSIsImtleSIsInN0b3JlIiwidXNlIiwiZ2V0T3JTZXQiLCJmYWN0b3J5IiwiYXBwbHkiXSwibWFwcGluZ3MiOiJBQUNBLFNBQVNBLGNBQWMsUUFBUSw0QkFBeUI7QUFLeEQsZ0NBQWdDO0FBQ2hDLElBQUlDLGtCQUF1QztBQUUzQzs7Q0FFQyxHQUNELE9BQU8sU0FBU0MsbUJBQW1CQyxPQUE0QjtJQUM3REYsa0JBQWtCRTtBQUNwQjtBQUVBOztDQUVDLEdBQ0QsT0FBTyxTQUFTQztJQUNkLE9BQU9IO0FBQ1Q7QUFFQTs7Q0FFQyxHQUNELFNBQVNJLGlCQUNQQyxTQUFpQixFQUNqQkMsVUFBa0IsRUFDbEJDLElBQWUsRUFDZkMsU0FBd0M7SUFFeEMsY0FBYztJQUNkLElBQUksT0FBT0EsY0FBYyxZQUFZO1FBQ25DLE9BQU9BLGFBQWFEO0lBQ3RCO0lBRUEsc0JBQXNCO0lBQ3RCLElBQUksT0FBT0MsY0FBYyxVQUFVO1FBQ2pDLE1BQU1DLGFBQWFDLGNBQWNIO1FBQ2pDLE9BQU9FLGFBQWEsR0FBR0QsVUFBVSxDQUFDLEVBQUVDLFlBQVksR0FBR0Q7SUFDckQ7SUFFQSw2Q0FBNkM7SUFDN0MsTUFBTUcsVUFBVSxHQUFHTixVQUFVLENBQUMsRUFBRUMsWUFBWTtJQUM1QyxNQUFNRyxhQUFhQyxjQUFjSDtJQUNqQyxPQUFPRSxhQUFhLEdBQUdFLFFBQVEsQ0FBQyxFQUFFRixZQUFZLEdBQUdFO0FBQ25EO0FBRUE7O0NBRUMsR0FDRCxTQUFTRCxjQUFjSCxJQUFlO0lBQ3BDLElBQUlBLEtBQUtLLE1BQU0sS0FBSyxHQUFHLE9BQU87SUFFOUIsaUJBQWlCO0lBQ2pCLElBQUlMLEtBQUtLLE1BQU0sS0FBSyxHQUFHO1FBQ3JCLE1BQU1DLE1BQU1OLElBQUksQ0FBQyxFQUFFO1FBQ25CLElBQUlNLFFBQVEsUUFBUUEsUUFBUUMsV0FBVyxPQUFPO1FBQzlDLElBQUksT0FBT0QsUUFBUSxZQUFZLE9BQU9BLFFBQVEsWUFBWSxPQUFPQSxRQUFRLFdBQVc7WUFDbEYsT0FBT0UsT0FBT0Y7UUFDaEI7SUFDRjtJQUVBLGtCQUFrQjtJQUNsQixJQUFJO1FBQ0YsT0FBT0csS0FBS0MsU0FBUyxDQUFDVjtJQUN4QixFQUFFLE9BQU07UUFDTix1QkFBdUI7UUFDdkIsT0FBT0EsS0FBS1csR0FBRyxDQUFDLENBQUNMLE1BQVFFLE9BQU9GLE1BQU1NLElBQUksQ0FBQztJQUM3QztBQUNGO0FBRUE7Ozs7Ozs7Ozs7Ozs7Q0FhQyxHQUNELE9BQU8sU0FBU0MsTUFBTUMsVUFBaUMsQ0FBQyxDQUFDO0lBQ3ZELE9BQU8sQ0FBQ0MsU0FBMEJDLGFBQXFCQztRQUNyRCxNQUFNQyxpQkFBaUJELFdBQVdFLEtBQUs7UUFFdkNGLFdBQVdFLEtBQUssR0FBRyxlQUF1RCxHQUFHbkIsSUFBZTtZQUMxRixNQUFNTCxVQUFVRjtZQUVoQixJQUFJLENBQUNFLFNBQVM7Z0JBQ1osTUFBTSxJQUFJeUIsTUFDUjtZQUVKO1lBRUEsTUFBTXRCLFlBQVksSUFBSSxZQUFZTixpQkFBaUIsSUFBSSxDQUFDTSxTQUFTLEdBQUcsSUFBSSxDQUFDdUIsU0FBUztZQUNsRixNQUFNdEIsYUFBYWlCO1lBRW5CLE1BQU1NLFdBQVd6QixpQkFBaUJDLFdBQVdDLFlBQVlDLE1BQU1jLFFBQVFTLEdBQUc7WUFDMUUsTUFBTUMsUUFBUVYsUUFBUVUsS0FBSyxHQUFHN0IsUUFBUThCLEdBQUcsQ0FBQ1gsUUFBUVUsS0FBSyxJQUFJN0I7WUFFM0QsT0FBTzZCLE1BQU1FLFFBQVEsQ0FBQztnQkFDcEIsR0FBR1osT0FBTztnQkFDVlMsS0FBS0Q7Z0JBQ0xLLFNBQVMsSUFBTVQsZUFBZVUsS0FBSyxDQUFDLElBQUksRUFBRTVCO1lBQzVDO1FBQ0Y7UUFFQSxPQUFPaUI7SUFDVDtBQUNGIn0=
87
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jYWNoZS9kZWNvcmF0b3IudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBCYXNlRnJhbWVDbGFzcyB9IGZyb20gXCIuLi9hcGkvYmFzZS1mcmFtZVwiO1xuaW1wb3J0IHsgQmFzZU1vZGVsQ2xhc3MgfSBmcm9tIFwiLi4vZGF0YWJhc2UvYmFzZS1tb2RlbFwiO1xuaW1wb3J0IHR5cGUgeyBDYWNoZURlY29yYXRvck9wdGlvbnMsIENhY2hlTWFuYWdlciB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbnR5cGUgRGVjb3JhdG9yVGFyZ2V0ID0geyBjb25zdHJ1Y3RvcjogeyBuYW1lOiBzdHJpbmcgfSB9O1xuXG4vLyDsupDsi5wg66ek64uI7KCAIOywuOyhsCAoU29uYW11LmluaXTsl5DshJwg7ISk7KCV65CoKVxubGV0IGNhY2hlTWFuYWdlclJlZjogQ2FjaGVNYW5hZ2VyIHwgbnVsbCA9IG51bGw7XG5cbi8qKlxuICog7LqQ7IucIOunpOuLiOyggCDssLjsobAg7ISk7KCVICjrgrTrtoAg7IKs7JqpKVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0Q2FjaGVNYW5hZ2VyUmVmKG1hbmFnZXI6IENhY2hlTWFuYWdlciB8IG51bGwpOiB2b2lkIHtcbiAgY2FjaGVNYW5hZ2VyUmVmID0gbWFuYWdlcjtcbn1cblxuLyoqXG4gKiDsupDsi5wg66ek64uI7KCAIOywuOyhsCDqsIDsoLjsmKTquLAgKOuCtOu2gCDsgqzsmqkpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRDYWNoZU1hbmFnZXJSZWYoKTogQ2FjaGVNYW5hZ2VyIHwgbnVsbCB7XG4gIHJldHVybiBjYWNoZU1hbmFnZXJSZWY7XG59XG5cbi8qKlxuICog7LqQ7IucIO2CpCDsg53shLFcbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVDYWNoZUtleShcbiAgbW9kZWxOYW1lOiBzdHJpbmcsXG4gIG1ldGhvZE5hbWU6IHN0cmluZyxcbiAgYXJnczogdW5rbm93bltdLFxuICBrZXlPcHRpb24/OiBDYWNoZURlY29yYXRvck9wdGlvbnNbXCJrZXlcIl0sXG4pOiBzdHJpbmcge1xuICAvLyDsu6TsiqTthYAg7YKkIO2VqOyImCDsgqzsmqlcbiAgaWYgKHR5cGVvZiBrZXlPcHRpb24gPT09IFwiZnVuY3Rpb25cIikge1xuICAgIHJldHVybiBrZXlPcHRpb24oLi4uYXJncyk7XG4gIH1cblxuICAvLyDrrLjsnpDsl7Qg7YKkICsgYXJncyBzdWZmaXhcbiAgaWYgKHR5cGVvZiBrZXlPcHRpb24gPT09IFwic3RyaW5nXCIpIHtcbiAgICBjb25zdCBhcmdzU3VmZml4ID0gc2VyaWFsaXplQXJncyhhcmdzKTtcbiAgICByZXR1cm4gYXJnc1N1ZmZpeCA/IGAke2tleU9wdGlvbn06JHthcmdzU3VmZml4fWAgOiBrZXlPcHRpb247XG4gIH1cblxuICAvLyDsnpDrj5kg7IOd7ISxOiBNb2RlbE5hbWUubWV0aG9kTmFtZTpzZXJpYWxpemVkQXJnc1xuICBjb25zdCBiYXNlS2V5ID0gYCR7bW9kZWxOYW1lfS4ke21ldGhvZE5hbWV9YDtcbiAgY29uc3QgYXJnc1N1ZmZpeCA9IHNlcmlhbGl6ZUFyZ3MoYXJncyk7XG4gIHJldHVybiBhcmdzU3VmZml4ID8gYCR7YmFzZUtleX06JHthcmdzU3VmZml4fWAgOiBiYXNlS2V5O1xufVxuXG4vKipcbiAqIOyduOyekCDsp4HroKztmZRcbiAqL1xuZnVuY3Rpb24gc2VyaWFsaXplQXJncyhhcmdzOiB1bmtub3duW10pOiBzdHJpbmcge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDApIHJldHVybiBcIlwiO1xuXG4gIC8vIOuLqOydvCBwcmltaXRpdmUg6rCSXG4gIGlmIChhcmdzLmxlbmd0aCA9PT0gMSkge1xuICAgIGNvbnN0IGFyZyA9IGFyZ3NbMF07XG4gICAgaWYgKGFyZyA9PT0gbnVsbCB8fCBhcmcgPT09IHVuZGVmaW5lZCkgcmV0dXJuIFwiXCI7XG4gICAgaWYgKHR5cGVvZiBhcmcgPT09IFwic3RyaW5nXCIgfHwgdHlwZW9mIGFyZyA9PT0gXCJudW1iZXJcIiB8fCB0eXBlb2YgYXJnID09PSBcImJvb2xlYW5cIikge1xuICAgICAgcmV0dXJuIFN0cmluZyhhcmcpO1xuICAgIH1cbiAgfVxuXG4gIC8vIOuzteyeoe2VnCDqsJLsnYAgSlNPTiDsp4HroKztmZRcbiAgdHJ5IHtcbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoYXJncyk7XG4gIH0gY2F0Y2gge1xuICAgIC8vIOyngeugrO2ZlCDsi6TtjKgg7IucIHRvU3RyaW5nIOyCrOyaqVxuICAgIHJldHVybiBhcmdzLm1hcCgoYXJnKSA9PiBTdHJpbmcoYXJnKSkuam9pbihcIjpcIik7XG4gIH1cbn1cblxuLyoqXG4gKiBAY2FjaGUg642w7L2U66CI7J207YSwXG4gKlxuICog66mU7ISc65Oc7J2YIOqysOqzvOulvCDsupDsi7Htlanri4jri6QuXG4gKlxuICogQGV4YW1wbGVcbiAqIGNsYXNzIFVzZXJNb2RlbENsYXNzIGV4dGVuZHMgQmFzZU1vZGVsQ2xhc3M8Li4uPiB7XG4gKiAgIEBjYWNoZSh7IHR0bDogJzEwbScsIHRhZ3M6IFsndXNlciddIH0pXG4gKiAgIEBhcGkoKVxuICogICBhc3luYyBmaW5kQnlJZChzdWJzZXQ6IFVzZXJTdWJzZXRLZXksIGlkOiBzdHJpbmcpIHtcbiAqICAgICBjb25zdCB7IHJvd3MgfSA9IGF3YWl0IHRoaXMuZmluZE1hbnkoc3Vic2V0LCB7IGlkLCBudW06IDEsIHBhZ2U6IDEgfSk7XG4gKiAgICAgcmV0dXJuIHJvd3NbMF07XG4gKiAgIH1cbiAqIH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNhY2hlKG9wdGlvbnM6IENhY2hlRGVjb3JhdG9yT3B0aW9ucyA9IHt9KSB7XG4gIHJldHVybiAoX3RhcmdldDogRGVjb3JhdG9yVGFyZ2V0LCBwcm9wZXJ0eUtleTogc3RyaW5nLCBkZXNjcmlwdG9yOiBQcm9wZXJ0eURlc2NyaXB0b3IpID0+IHtcbiAgICBjb25zdCBvcmlnaW5hbE1ldGhvZCA9IGRlc2NyaXB0b3IudmFsdWU7XG5cbiAgICBkZXNjcmlwdG9yLnZhbHVlID0gYXN5bmMgZnVuY3Rpb24gKHRoaXM6IEJhc2VNb2RlbENsYXNzIHwgQmFzZUZyYW1lQ2xhc3MsIC4uLmFyZ3M6IHVua25vd25bXSkge1xuICAgICAgY29uc3QgbWFuYWdlciA9IGNhY2hlTWFuYWdlclJlZjtcblxuICAgICAgaWYgKCFtYW5hZ2VyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBcIkNhY2hlTWFuYWdlciBpcyBub3QgaW5pdGlhbGl6ZWQuIFBsZWFzZSBjb25maWd1cmUgJ2NhY2hlJyBpbiBzb25hbXUuY29uZmlnLnRzLlwiLFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBtb2RlbE5hbWUgPSB0aGlzIGluc3RhbmNlb2YgQmFzZU1vZGVsQ2xhc3MgPyB0aGlzLm1vZGVsTmFtZSA6IHRoaXMuZnJhbWVOYW1lO1xuICAgICAgY29uc3QgbWV0aG9kTmFtZSA9IHByb3BlcnR5S2V5O1xuXG4gICAgICBjb25zdCBjYWNoZUtleSA9IGdlbmVyYXRlQ2FjaGVLZXkobW9kZWxOYW1lLCBtZXRob2ROYW1lLCBhcmdzLCBvcHRpb25zLmtleSk7XG4gICAgICBjb25zdCBzdG9yZSA9IG9wdGlvbnMuc3RvcmUgPyBtYW5hZ2VyLnVzZShvcHRpb25zLnN0b3JlKSA6IG1hbmFnZXI7XG5cbiAgICAgIHJldHVybiBzdG9yZS5nZXRPclNldCh7XG4gICAgICAgIC4uLm9wdGlvbnMsXG4gICAgICAgIGtleTogY2FjaGVLZXksXG4gICAgICAgIGZhY3Rvcnk6ICgpID0+IG9yaWdpbmFsTWV0aG9kLmFwcGx5KHRoaXMsIGFyZ3MpLFxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIHJldHVybiBkZXNjcmlwdG9yO1xuICB9O1xufVxuIl0sIm5hbWVzIjpbIkJhc2VNb2RlbENsYXNzIiwiY2FjaGVNYW5hZ2VyUmVmIiwic2V0Q2FjaGVNYW5hZ2VyUmVmIiwibWFuYWdlciIsImdldENhY2hlTWFuYWdlclJlZiIsImdlbmVyYXRlQ2FjaGVLZXkiLCJtb2RlbE5hbWUiLCJtZXRob2ROYW1lIiwiYXJncyIsImtleU9wdGlvbiIsImFyZ3NTdWZmaXgiLCJzZXJpYWxpemVBcmdzIiwiYmFzZUtleSIsImxlbmd0aCIsImFyZyIsInVuZGVmaW5lZCIsIlN0cmluZyIsIkpTT04iLCJzdHJpbmdpZnkiLCJtYXAiLCJqb2luIiwiY2FjaGUiLCJvcHRpb25zIiwiX3RhcmdldCIsInByb3BlcnR5S2V5IiwiZGVzY3JpcHRvciIsIm9yaWdpbmFsTWV0aG9kIiwidmFsdWUiLCJFcnJvciIsImZyYW1lTmFtZSIsImNhY2hlS2V5Iiwia2V5Iiwic3RvcmUiLCJ1c2UiLCJnZXRPclNldCIsImZhY3RvcnkiLCJhcHBseSJdLCJtYXBwaW5ncyI6IkFBQ0EsU0FBU0EsY0FBYyxRQUFRLDRCQUF5QjtBQUt4RCxnQ0FBZ0M7QUFDaEMsSUFBSUMsa0JBQXVDO0FBRTNDOztDQUVDLEdBQ0QsT0FBTyxTQUFTQyxtQkFBbUJDLE9BQTRCO0lBQzdERixrQkFBa0JFO0FBQ3BCO0FBRUE7O0NBRUMsR0FDRCxPQUFPLFNBQVNDO0lBQ2QsT0FBT0g7QUFDVDtBQUVBOztDQUVDLEdBQ0QsU0FBU0ksaUJBQ1BDLFNBQWlCLEVBQ2pCQyxVQUFrQixFQUNsQkMsSUFBZSxFQUNmQyxTQUF3QztJQUV4QyxjQUFjO0lBQ2QsSUFBSSxPQUFPQSxjQUFjLFlBQVk7UUFDbkMsT0FBT0EsYUFBYUQ7SUFDdEI7SUFFQSxzQkFBc0I7SUFDdEIsSUFBSSxPQUFPQyxjQUFjLFVBQVU7UUFDakMsTUFBTUMsYUFBYUMsY0FBY0g7UUFDakMsT0FBT0UsYUFBYSxHQUFHRCxVQUFVLENBQUMsRUFBRUMsWUFBWSxHQUFHRDtJQUNyRDtJQUVBLDZDQUE2QztJQUM3QyxNQUFNRyxVQUFVLEdBQUdOLFVBQVUsQ0FBQyxFQUFFQyxZQUFZO0lBQzVDLE1BQU1HLGFBQWFDLGNBQWNIO0lBQ2pDLE9BQU9FLGFBQWEsR0FBR0UsUUFBUSxDQUFDLEVBQUVGLFlBQVksR0FBR0U7QUFDbkQ7QUFFQTs7Q0FFQyxHQUNELFNBQVNELGNBQWNILElBQWU7SUFDcEMsSUFBSUEsS0FBS0ssTUFBTSxLQUFLLEdBQUcsT0FBTztJQUU5QixpQkFBaUI7SUFDakIsSUFBSUwsS0FBS0ssTUFBTSxLQUFLLEdBQUc7UUFDckIsTUFBTUMsTUFBTU4sSUFBSSxDQUFDLEVBQUU7UUFDbkIsSUFBSU0sUUFBUSxRQUFRQSxRQUFRQyxXQUFXLE9BQU87UUFDOUMsSUFBSSxPQUFPRCxRQUFRLFlBQVksT0FBT0EsUUFBUSxZQUFZLE9BQU9BLFFBQVEsV0FBVztZQUNsRixPQUFPRSxPQUFPRjtRQUNoQjtJQUNGO0lBRUEsa0JBQWtCO0lBQ2xCLElBQUk7UUFDRixPQUFPRyxLQUFLQyxTQUFTLENBQUNWO0lBQ3hCLEVBQUUsT0FBTTtRQUNOLHVCQUF1QjtRQUN2QixPQUFPQSxLQUFLVyxHQUFHLENBQUMsQ0FBQ0wsTUFBUUUsT0FBT0YsTUFBTU0sSUFBSSxDQUFDO0lBQzdDO0FBQ0Y7QUFFQTs7Ozs7Ozs7Ozs7Ozs7Q0FjQyxHQUNELE9BQU8sU0FBU0MsTUFBTUMsVUFBaUMsQ0FBQyxDQUFDO0lBQ3ZELE9BQU8sQ0FBQ0MsU0FBMEJDLGFBQXFCQztRQUNyRCxNQUFNQyxpQkFBaUJELFdBQVdFLEtBQUs7UUFFdkNGLFdBQVdFLEtBQUssR0FBRyxlQUF1RCxHQUFHbkIsSUFBZTtZQUMxRixNQUFNTCxVQUFVRjtZQUVoQixJQUFJLENBQUNFLFNBQVM7Z0JBQ1osTUFBTSxJQUFJeUIsTUFDUjtZQUVKO1lBRUEsTUFBTXRCLFlBQVksSUFBSSxZQUFZTixpQkFBaUIsSUFBSSxDQUFDTSxTQUFTLEdBQUcsSUFBSSxDQUFDdUIsU0FBUztZQUNsRixNQUFNdEIsYUFBYWlCO1lBRW5CLE1BQU1NLFdBQVd6QixpQkFBaUJDLFdBQVdDLFlBQVlDLE1BQU1jLFFBQVFTLEdBQUc7WUFDMUUsTUFBTUMsUUFBUVYsUUFBUVUsS0FBSyxHQUFHN0IsUUFBUThCLEdBQUcsQ0FBQ1gsUUFBUVUsS0FBSyxJQUFJN0I7WUFFM0QsT0FBTzZCLE1BQU1FLFFBQVEsQ0FBQztnQkFDcEIsR0FBR1osT0FBTztnQkFDVlMsS0FBS0Q7Z0JBQ0xLLFNBQVMsSUFBTVQsZUFBZVUsS0FBSyxDQUFDLElBQUksRUFBRTVCO1lBQzVDO1FBQ0Y7UUFFQSxPQUFPaUI7SUFDVDtBQUNGIn0=
@@ -0,0 +1,33 @@
1
+ import type { Cone, EntityJson } from "../types/types";
2
+ /**
3
+ * Cone 생성 컨텍스트
4
+ *
5
+ * Entity 정보와 생성 옵션을 담고 있습니다.
6
+ */
7
+ export type ConeGenerationContext = {
8
+ entity: EntityJson;
9
+ locale?: "ko" | "en" | "ja";
10
+ existingCones?: Record<string, Cone>;
11
+ /** true인 경우 fixtureHint가 없는 cone만 생성 */
12
+ onlyEmpty?: boolean;
13
+ };
14
+ /**
15
+ * Cone 생성 결과
16
+ *
17
+ * Entity, Props, Subsets, Enums의 cone 메타데이터를 담고 있습니다.
18
+ */
19
+ export type ConeGenerationResult = {
20
+ entityCone?: Cone;
21
+ propCones: Record<string, Cone>;
22
+ subsetCones: Record<string, Cone>;
23
+ enumCones: Record<string, Cone>;
24
+ tokensUsed: number;
25
+ };
26
+ /**
27
+ * LLM을 사용하여 Entity의 cone 메타데이터를 생성합니다.
28
+ *
29
+ * @param context - Entity 정보와 생성 옵션
30
+ * @returns 생성된 cone 메타데이터
31
+ */
32
+ export declare function generateCones(context: ConeGenerationContext): Promise<ConeGenerationResult>;
33
+ //# sourceMappingURL=cone-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cone-generator.d.ts","sourceRoot":"","sources":["../../src/cone/cone-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEvD;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACrC,wCAAwC;IACxC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,UAAU,CAAC,EAAE,IAAI,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAejG"}