sonamu 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 +228 -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 +341 -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 +54 -29
  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 +262 -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 +407 -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,7 +1,7 @@
1
- import { Knex } from "knex";
1
+ import type { Knex } from "knex";
2
2
  type TableData = {
3
3
  references: Set<string>;
4
- rows: any[];
4
+ rows: Record<string, unknown>[];
5
5
  uniqueIndexes: {
6
6
  name?: string;
7
7
  columns: string[];
@@ -13,7 +13,7 @@ export type UBRef = {
13
13
  of: string;
14
14
  use?: string;
15
15
  };
16
- export declare function isRefField(field: any): field is UBRef;
16
+ export declare function isRefField(field: unknown): field is UBRef;
17
17
  export declare class UpsertBuilder {
18
18
  tables: Map<string, TableData>;
19
19
  constructor();
@@ -29,6 +29,12 @@ export declare class UpsertBuilder {
29
29
  chunkSize?: number;
30
30
  where?: string | string[];
31
31
  }): Promise<void>;
32
+ /**
33
+ * rows를 의존성 순서에 따라 레벨별로 그룹화
34
+ * - 자기 참조 없는 경우 : 모든 rows가 Level 0
35
+ * - 자기 참조 있는 경우 : 자기 참조 관계를 위상 정렬하여 레벨별로 그룹화
36
+ */
37
+ private buildInsertLevels;
32
38
  }
33
39
  export {};
34
40
  //# sourceMappingURL=upsert-builder.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"upsert-builder.d.ts","sourceRoot":"","sources":["../../src/database/upsert-builder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAK5B,KAAK,SAAS,GAAG;IACf,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACxB,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,aAAa,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;IACtD,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC,CAAC;AACF,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AACF,wBAAgB,UAAU,CAAC,KAAK,EAAE,GAAG,GAAG,KAAK,IAAI,KAAK,CAOrD;AAED,qBAAa,aAAa;IACxB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;;IAK/B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS;IAsBtC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAIpC,QAAQ,CAAC,CAAC,SAAS,MAAM,EACvB,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE;SACF,GAAG,IAAI,CAAC,CAAC,CAAC,EACP,KAAK,GACL,MAAM,GACN,MAAM,GACN,OAAO,GACP,MAAM,GACN,IAAI,GACJ,MAAM,GACN,OAAO;KACZ,GACA,KAAK;IA0EF,MAAM,CACV,GAAG,EAAE,IAAI,EACT,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,EAAE,CAAC;IAGd,UAAU,CACd,GAAG,EAAE,IAAI,EACT,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,EAAE,CAAC;IAId,cAAc,CAClB,GAAG,EAAE,IAAI,EACT,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,QAAQ,GAAG,QAAQ,EACzB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,EAAE,CAAC;IAgHd,WAAW,CACf,GAAG,EAAE,IAAI,EACT,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;KAC3B,GACA,OAAO,CAAC,IAAI,CAAC;CA6BjB"}
1
+ {"version":3,"file":"upsert-builder.d.ts","sourceRoot":"","sources":["../../src/database/upsert-builder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAOjC,KAAK,SAAS,GAAG;IACf,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAChC,aAAa,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;IACtD,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC,CAAC;AACF,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AACF,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,KAAK,CAOzD;AAED,qBAAa,aAAa;IACxB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;;IAK/B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS;IAwBtC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAIpC,QAAQ,CAAC,CAAC,SAAS,MAAM,EACvB,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE;SACF,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,OAAO;KAClF,GACA,KAAK;IAqFF,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAG3E,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAI/E,cAAc,CAClB,GAAG,EAAE,IAAI,EACT,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,QAAQ,GAAG,QAAQ,EACzB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,EAAE,CAAC;IAqKd,WAAW,CACf,GAAG,EAAE,IAAI,EACT,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;KAC3B,GACA,OAAO,CAAC,IAAI,CAAC;IAyChB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;CA8D1B"}
@@ -1,10 +1,11 @@
1
1
  import { randomUUID } from "crypto";
2
- import * as _ from "lodash-es";
2
+ import { unique } from "radashi";
3
3
  import { EntityManager } from "../entity/entity-manager.js";
4
- import { nonNullable } from "../utils/utils.js";
4
+ import { Naite } from "../naite/naite.js";
5
+ import { assertDefined, chunk, nonNullable } from "../utils/utils.js";
5
6
  import { batchUpdate } from "./_batch_update.js";
6
7
  export function isRefField(field) {
7
- return field !== undefined && field !== null && field.of !== undefined && field.uuid !== undefined;
8
+ return field !== undefined && field !== null && field?.of !== undefined && field?.uuid !== undefined;
8
9
  }
9
10
  export class UpsertBuilder {
10
11
  tables;
@@ -13,22 +14,24 @@ export class UpsertBuilder {
13
14
  }
14
15
  getTable(tableName) {
15
16
  const table = this.tables.get(tableName);
16
- if (table === undefined) {
17
- const tableSpec = (()=>{
18
- try {
19
- return EntityManager.getTableSpec(tableName);
20
- } catch {
21
- return null;
22
- }
23
- })();
24
- this.tables.set(tableName, {
25
- references: new Set(),
26
- rows: [],
27
- uniqueIndexes: tableSpec?.uniqueIndexes ?? [],
28
- uniquesMap: new Map()
29
- });
17
+ if (table) {
18
+ return table;
30
19
  }
31
- return this.tables.get(tableName);
20
+ const tableSpec = (()=>{
21
+ try {
22
+ return EntityManager.getTableSpec(tableName);
23
+ } catch {
24
+ return null;
25
+ }
26
+ })();
27
+ const tableData = {
28
+ references: new Set(),
29
+ rows: [],
30
+ uniqueIndexes: tableSpec?.uniqueIndexes ?? [],
31
+ uniquesMap: new Map()
32
+ };
33
+ this.tables.set(tableName, tableData);
34
+ return tableData;
32
35
  }
33
36
  hasTable(tableName) {
34
37
  return this.tables.has(tableName);
@@ -52,17 +55,23 @@ export class UpsertBuilder {
52
55
  return uniqueKeyArray.join("---delimiter--");
53
56
  }).filter(nonNullable);
54
57
  // uuid 생성 로직
55
- const uuid = (()=>{
58
+ const { uuid, isReused } = (()=>{
56
59
  // 키를 순회하여 이미 존재하는 키가 있는지 확인
57
60
  if (uniqueKeys.length > 0) {
58
61
  for (const uniqueKey of uniqueKeys){
59
62
  if (table.uniquesMap.has(uniqueKey)) {
60
- return table.uniquesMap.get(uniqueKey); // 이미 has 체크를 했으므로 undefined 불가능
63
+ return {
64
+ uuid: assertDefined(table.uniquesMap.get(uniqueKey), "Unique key not found"),
65
+ isReused: true
66
+ };
61
67
  }
62
68
  }
63
69
  }
64
70
  // 찾을 수 없는 경우 생성
65
- return randomUUID();
71
+ return {
72
+ uuid: randomUUID(),
73
+ isReused: false
74
+ };
66
75
  })();
67
76
  // 모든 유니크키에 대해 유니크맵에 uuid 저장
68
77
  if (uniqueKeys.length > 0) {
@@ -72,28 +81,42 @@ export class UpsertBuilder {
72
81
  }
73
82
  // 이 테이블에 사용된 RefField를 순회하여, 현재 테이블 정보에 어떤 필드를 참조하는지 추가
74
83
  // 이 정보를 나중에 치환할 때 사용
75
- row = Object.keys(row).reduce((r, rowKey)=>{
76
- const rowValue = row[rowKey];
84
+ row = Object.fromEntries(Object.entries(row).map(([rowKey, rowValue])=>{
77
85
  if (isRefField(rowValue)) {
78
86
  rowValue.use ??= "id";
79
- table.references.add(rowValue.of + "." + rowValue.use);
80
- r[rowKey] = rowValue;
87
+ table.references.add(`${rowValue.of}.${rowValue.use}`);
88
+ return [
89
+ rowKey,
90
+ rowValue
91
+ ];
81
92
  } else if (typeof rowValue === "object" && !(rowValue instanceof Date)) {
82
93
  // object인 경우 JSON으로 변환
83
- r[rowKey] = rowValue === null ? null : JSON.stringify(rowValue);
94
+ return [
95
+ rowKey,
96
+ rowValue === null ? null : JSON.stringify(rowValue)
97
+ ];
84
98
  } else {
85
- r[rowKey] = rowValue;
99
+ return [
100
+ rowKey,
101
+ rowValue
102
+ ];
86
103
  }
87
- return r;
88
- }, {});
104
+ }));
89
105
  table.rows.push({
90
106
  uuid,
91
107
  ...row
92
108
  });
93
- return {
109
+ const result = {
94
110
  of: tableName,
95
111
  uuid: row.uuid ?? uuid
96
112
  };
113
+ Naite.t("puri:ub-register", {
114
+ tableName,
115
+ uuid: result.uuid,
116
+ isUuidReused: isReused,
117
+ row
118
+ });
119
+ return result;
97
120
  }
98
121
  async upsert(wdb, tableName, chunkSize) {
99
122
  return this.upsertOrInsert(wdb, tableName, "upsert", chunkSize);
@@ -116,7 +139,7 @@ export class UpsertBuilder {
116
139
  }
117
140
  // 전체 테이블 순회하여 현재 테이블 참조하는 모든 테이블 추출
118
141
  const { references, refTables } = Array.from(this.tables).reduce((r, [, table])=>{
119
- const reference = Array.from(table.references.values()).find((ref)=>ref.includes(tableName + "."));
142
+ const reference = Array.from(table.references.values()).find((ref)=>ref.includes(`${tableName}.`));
120
143
  if (reference) {
121
144
  r.references.push(reference);
122
145
  r.refTables.push(table);
@@ -126,90 +149,217 @@ export class UpsertBuilder {
126
149
  references: [],
127
150
  refTables: []
128
151
  });
129
- const extractFields = _.uniq(references).map((reference)=>reference.split(".")[1]);
130
- // 내부 참조 있는 경우 필터하여 분리
131
- const groups = _.groupBy(table.rows, (row)=>Object.entries(row).some(([, value])=>isRefField(value)) ? "selfRef" : "normal");
132
- const normalRows = groups.normal ?? [];
133
- const selfRefRows = groups.selfRef ?? [];
134
- const chunks = chunkSize ? _.chunk(normalRows, chunkSize) : [
135
- normalRows
136
- ];
152
+ const extractFields = unique(references).map((reference)=>reference.split(".")[1]).filter((field)=>field !== undefined);
153
+ // 의존성 순서에 따라 레벨별 그룹화 (자기 참조가 없으면 Level 0 하나)
154
+ const { levels, hasCircular } = this.buildInsertLevels(table.rows, tableName);
155
+ if (hasCircular) {
156
+ throw new Error(`${tableName}에 순환 자기 참조가 있습니다.`);
157
+ }
158
+ // upsert 모드일 때 유니크 인덱스가 없으면 에러
159
+ if (mode === "upsert" && table.uniqueIndexes.length === 0) {
160
+ throw new Error(`${tableName}에 unique index가 정의되지 않아 upsert를 할 수 없습니다.`);
161
+ }
137
162
  const uuidMap = new Map();
138
- for (const chunk of chunks){
139
- const q = wdb.insert(chunk).into(tableName);
140
- if (mode === "insert") {
141
- await q;
142
- } else if (mode === "upsert") {
143
- await q.onDuplicateUpdate.apply(q, Object.keys(normalRows[0]));
144
- }
145
- // upsert된 row들을 다시 조회하여 uuidMap에 저장
146
- const uuids = chunk.map((row)=>row.uuid);
147
- const upsertedRows = await wdb(tableName).select(_.uniq([
163
+ const allIds = [];
164
+ // 레벨별로 순차 처리
165
+ for (const levelRows of levels){
166
+ // 이전 레벨에서 얻은 ID로 자기 참조 해결
167
+ const resolvedRows = levelRows.map((row)=>{
168
+ const resolved = {
169
+ ...row
170
+ };
171
+ for (const [key, value] of Object.entries(row)){
172
+ if (isRefField(value) && value.of === tableName) {
173
+ const parent = uuidMap.get(value.uuid);
174
+ if (!parent) throw new Error(`존재하지 않는 uuid ${value.uuid} -- in ${tableName}`);
175
+ resolved[key] = parent[value.use ?? "id"];
176
+ Naite.t("puri:ub-ref-resolved", {
177
+ tableName,
178
+ field: key,
179
+ from: {
180
+ of: value.of,
181
+ uuid: value.uuid,
182
+ use: value.use ?? "id"
183
+ },
184
+ to: resolved[key]
185
+ });
186
+ }
187
+ }
188
+ return resolved;
189
+ });
190
+ // 현재 레벨 upsert
191
+ const levelChunks = chunkSize ? chunk(resolvedRows, chunkSize) : [
192
+ resolvedRows
193
+ ];
194
+ const selectFields = unique([
148
195
  "uuid",
149
196
  "id",
150
197
  ...extractFields
151
- ])).whereIn("uuid", uuids);
152
- upsertedRows.forEach((row)=>{
153
- uuidMap.set(row.uuid, row);
154
- });
198
+ ]);
199
+ for (const dataChunk of levelChunks){
200
+ if (dataChunk.length === 0) continue;
201
+ let resultRows;
202
+ if (mode === "insert") {
203
+ // INSERT 모드
204
+ await wdb.insert(dataChunk).into(tableName);
205
+ const uuids = dataChunk.map((r)=>r.uuid);
206
+ resultRows = await wdb(tableName).select(selectFields).whereIn("uuid", uuids);
207
+ } else {
208
+ // UPSERT 모드 (uniqueIndexes 이미 체크됨)
209
+ const conflictColumns = table.uniqueIndexes[0].columns;
210
+ const updateColumns = Object.keys(dataChunk[0]).filter((col)=>col !== "uuid" && !conflictColumns.includes(col));
211
+ // RETURNING으로 결과 받기
212
+ const query = wdb.insert(dataChunk).into(tableName).onConflict(conflictColumns);
213
+ // updateColumns가 비어있으면 ignore(), 아니면 merge()
214
+ if (updateColumns.length === 0) {
215
+ resultRows = await query.ignore().returning(selectFields);
216
+ } else {
217
+ resultRows = await query.merge(updateColumns).returning(selectFields);
218
+ }
219
+ }
220
+ // 양쪽 모드 공통 처리
221
+ for (const row of resultRows){
222
+ uuidMap.set(row.uuid, row);
223
+ allIds.push(row.id);
224
+ }
225
+ }
155
226
  }
156
227
  // 해당 테이블 참조를 실제 밸류로 변경
157
- refTables.map((table)=>{
228
+ for (const table of refTables){
158
229
  table.rows = table.rows.map((row)=>{
159
- Object.keys(row).map((key)=>{
230
+ for (const key of Object.keys(row)){
160
231
  const prop = row[key];
161
232
  if (isRefField(prop) && prop.of === tableName) {
162
233
  const parent = uuidMap.get(prop.uuid);
163
- if (parent === undefined) {
234
+ if (!parent) {
164
235
  console.error(prop);
165
236
  throw new Error(`존재하지 않는 uuid ${prop.uuid} -- in ${tableName}`);
166
237
  }
167
- row[key] = parent[prop.use ?? "id"];
238
+ const resolvedValue = parent[prop.use ?? "id"];
239
+ row[key] = resolvedValue;
240
+ Naite.t("puri:ub-ref-resolved", {
241
+ tableName,
242
+ field: key,
243
+ from: {
244
+ of: prop.of,
245
+ uuid: prop.uuid,
246
+ use: prop.use ?? "id"
247
+ },
248
+ to: resolvedValue
249
+ });
168
250
  }
169
- });
251
+ }
170
252
  return row;
171
253
  });
172
- });
173
- const allIds = Array.from(uuidMap.values()).map((row)=>row.id);
174
- // 자기 참조가 있는 경우 재귀적으로 upsert
175
- if (selfRefRows.length > 0) {
176
- // 처리된 데이터를 제외하고 다시 upsert
177
- table.rows = selfRefRows;
178
- const selfRefIds = await this.upsert(wdb, tableName, chunkSize);
179
- allIds.push(...selfRefIds);
180
- } else {
181
- // 자기 참조가 없으면 해당 테이블의 데이터 초기화
182
- table.rows = [];
183
- table.references.clear();
184
- table.uniquesMap.clear();
185
254
  }
255
+ // 해당 테이블의 데이터 초기화
256
+ table.rows = [];
257
+ table.references.clear();
258
+ table.uniquesMap.clear();
259
+ Naite.t("puri:ub-upserted", {
260
+ tableName,
261
+ mode,
262
+ rowCount: allIds.length,
263
+ returnedIds: allIds
264
+ });
186
265
  return allIds;
187
266
  }
188
267
  async updateBatch(wdb, tableName, options) {
189
- options = _.defaults(options, {
190
- chunkSize: 500,
191
- where: "id"
192
- });
268
+ options = {
269
+ ...options,
270
+ chunkSize: options?.chunkSize ?? 500,
271
+ where: options?.where ?? "id"
272
+ };
193
273
  if (this.hasTable(tableName) === false) {
194
274
  return;
195
275
  }
196
276
  const table = this.tables.get(tableName);
197
- if (table.rows.length === 0) {
277
+ if (!table) {
278
+ throw new Error(`등록되지 않은 테이블 ${tableName}에 updateBatch 요청`);
279
+ } else if (table.rows.length === 0) {
198
280
  return;
199
281
  }
200
282
  const whereColumns = Array.isArray(options.where) ? options.where : [
201
283
  options.where ?? "id"
202
284
  ];
203
285
  const rows = table.rows.map((_row)=>{
204
- const { uuid, ...row } = _row;
286
+ const { uuid: _, ...row } = _row; // uuid 제외
205
287
  return row;
206
288
  });
207
289
  await batchUpdate(wdb, tableName, whereColumns, rows, options.chunkSize);
290
+ Naite.t("puri:ub-batch-updated", {
291
+ tableName,
292
+ rowCount: rows.length,
293
+ whereColumns
294
+ });
208
295
  // updateBatch 완료 후 처리된 데이터 제거
209
296
  table.rows = [];
210
297
  table.references.clear();
211
298
  table.uniquesMap.clear();
212
299
  }
300
+ // ============================================================================
301
+ // Private Helpers
302
+ // ============================================================================
303
+ /**
304
+ * rows를 의존성 순서에 따라 레벨별로 그룹화
305
+ * - 자기 참조 없는 경우 : 모든 rows가 Level 0
306
+ * - 자기 참조 있는 경우 : 자기 참조 관계를 위상 정렬하여 레벨별로 그룹화
307
+ */ buildInsertLevels(rows, tableName) {
308
+ // 1. 자기 참조가 없으면 한 레벨로 처리
309
+ const hasSelfRef = rows.flatMap((row)=>Object.values(row)).some((value)=>isRefField(value) && value.of === tableName);
310
+ if (!hasSelfRef) return {
311
+ levels: [
312
+ rows
313
+ ],
314
+ hasCircular: false
315
+ };
316
+ // 2. uuid → row 매핑 (중복 uuid 방지)
317
+ const rowByUuid = new Map();
318
+ for (const row of rows){
319
+ const uuid = row.uuid;
320
+ if (!uuid) throw new Error(`buildInsertLevels: uuid가 없는 row -- in ${tableName}`);
321
+ rowByUuid.set(uuid, row);
322
+ }
323
+ let pending = Array.from(rowByUuid.values());
324
+ const levels = [];
325
+ const inserted = new Set();
326
+ // 3. 레벨별 분류
327
+ while(pending.length > 0){
328
+ const currentLevel = [];
329
+ const nextPending = [];
330
+ for (const row of pending){
331
+ // 이 row가 참조하는 자기 참조들
332
+ const selfRefs = Object.values(row).filter((value)=>isRefField(value) && value.of === tableName);
333
+ // 참조하는 모든 uuid가 이미 inserted에 있어야 이번 레벨에 포함
334
+ const canInsert = selfRefs.every((ref)=>{
335
+ if (!rowByUuid.has(ref.uuid)) {
336
+ throw new Error(`존재하지 않는 uuid ${ref.uuid} -- in ${tableName}`);
337
+ }
338
+ return inserted.has(ref.uuid);
339
+ });
340
+ if (canInsert) {
341
+ currentLevel.push(row);
342
+ } else {
343
+ nextPending.push(row);
344
+ }
345
+ }
346
+ // 순환 참조 감지
347
+ if (currentLevel.length === 0) return {
348
+ levels: [],
349
+ hasCircular: true
350
+ };
351
+ // 레벨 확정 + inserted 갱신
352
+ levels.push(currentLevel);
353
+ for (const row of currentLevel){
354
+ inserted.add(row.uuid);
355
+ }
356
+ pending = nextPending;
357
+ }
358
+ return {
359
+ levels,
360
+ hasCircular: false
361
+ };
362
+ }
213
363
  }
214
364
 
215
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYXRhYmFzZS91cHNlcnQtYnVpbGRlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyByYW5kb21VVUlEIH0gZnJvbSBcImNyeXB0b1wiO1xuaW1wb3J0ICogYXMgXyBmcm9tIFwibG9kYXNoLWVzXCI7XG5pbXBvcnQgeyBLbmV4IH0gZnJvbSBcImtuZXhcIjtcbmltcG9ydCB7IEVudGl0eU1hbmFnZXIgfSBmcm9tIFwiLi4vZW50aXR5L2VudGl0eS1tYW5hZ2VyXCI7XG5pbXBvcnQgeyBub25OdWxsYWJsZSB9IGZyb20gXCIuLi91dGlscy91dGlsc1wiO1xuaW1wb3J0IHsgUm93V2l0aElkLCBiYXRjaFVwZGF0ZSB9IGZyb20gXCIuL19iYXRjaF91cGRhdGVcIjtcblxudHlwZSBUYWJsZURhdGEgPSB7XG4gIHJlZmVyZW5jZXM6IFNldDxzdHJpbmc+O1xuICByb3dzOiBhbnlbXTtcbiAgdW5pcXVlSW5kZXhlczogeyBuYW1lPzogc3RyaW5nOyBjb2x1bW5zOiBzdHJpbmdbXSB9W107XG4gIHVuaXF1ZXNNYXA6IE1hcDxzdHJpbmcsIHN0cmluZz47XG59O1xuZXhwb3J0IHR5cGUgVUJSZWYgPSB7XG4gIHV1aWQ6IHN0cmluZztcbiAgb2Y6IHN0cmluZztcbiAgdXNlPzogc3RyaW5nO1xufTtcbmV4cG9ydCBmdW5jdGlvbiBpc1JlZkZpZWxkKGZpZWxkOiBhbnkpOiBmaWVsZCBpcyBVQlJlZiB7XG4gIHJldHVybiAoXG4gICAgZmllbGQgIT09IHVuZGVmaW5lZCAmJlxuICAgIGZpZWxkICE9PSBudWxsICYmXG4gICAgZmllbGQub2YgIT09IHVuZGVmaW5lZCAmJlxuICAgIGZpZWxkLnV1aWQgIT09IHVuZGVmaW5lZFxuICApO1xufVxuXG5leHBvcnQgY2xhc3MgVXBzZXJ0QnVpbGRlciB7XG4gIHRhYmxlczogTWFwPHN0cmluZywgVGFibGVEYXRhPjtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy50YWJsZXMgPSBuZXcgTWFwKCk7XG4gIH1cblxuICBnZXRUYWJsZSh0YWJsZU5hbWU6IHN0cmluZyk6IFRhYmxlRGF0YSB7XG4gICAgY29uc3QgdGFibGUgPSB0aGlzLnRhYmxlcy5nZXQodGFibGVOYW1lKTtcbiAgICBpZiAodGFibGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgdGFibGVTcGVjID0gKCgpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gRW50aXR5TWFuYWdlci5nZXRUYWJsZVNwZWModGFibGVOYW1lKTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgIH0pKCk7XG5cbiAgICAgIHRoaXMudGFibGVzLnNldCh0YWJsZU5hbWUsIHtcbiAgICAgICAgcmVmZXJlbmNlczogbmV3IFNldCgpLFxuICAgICAgICByb3dzOiBbXSxcbiAgICAgICAgdW5pcXVlSW5kZXhlczogdGFibGVTcGVjPy51bmlxdWVJbmRleGVzID8/IFtdLFxuICAgICAgICB1bmlxdWVzTWFwOiBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMudGFibGVzLmdldCh0YWJsZU5hbWUpITtcbiAgfVxuXG4gIGhhc1RhYmxlKHRhYmxlTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMudGFibGVzLmhhcyh0YWJsZU5hbWUpO1xuICB9XG5cbiAgcmVnaXN0ZXI8VCBleHRlbmRzIHN0cmluZz4oXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgcm93OiB7XG4gICAgICBba2V5IGluIFRdPzpcbiAgICAgICAgfCBVQlJlZlxuICAgICAgICB8IHN0cmluZ1xuICAgICAgICB8IG51bWJlclxuICAgICAgICB8IGJvb2xlYW5cbiAgICAgICAgfCBiaWdpbnRcbiAgICAgICAgfCBudWxsXG4gICAgICAgIHwgb2JqZWN0XG4gICAgICAgIHwgdW5rbm93bjtcbiAgICB9XG4gICk6IFVCUmVmIHtcbiAgICBjb25zdCB0YWJsZSA9IHRoaXMuZ2V0VGFibGUodGFibGVOYW1lKTtcblxuICAgIC8vIO2VtOuLuSDthYzsnbTruJTsnZggdW5pcXVlIOyduOuNseyKpOulvCDsiJztmoztlZjrqbAg7YKkIOyDneyEsVxuICAgIGNvbnN0IHVuaXF1ZUtleXMgPSB0YWJsZS51bmlxdWVJbmRleGVzXG4gICAgICAubWFwKCh1bnFJbmRleCkgPT4ge1xuICAgICAgICBjb25zdCB1bmlxdWVLZXlBcnJheSA9IHVucUluZGV4LmNvbHVtbnMubWFwKCh1bnFDb2wpID0+IHtcbiAgICAgICAgICBjb25zdCB2YWwgPSByb3dbdW5xQ29sIGFzIGtleW9mIHR5cGVvZiByb3ddO1xuICAgICAgICAgIGlmIChpc1JlZkZpZWxkKHZhbCkpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWwudXVpZDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHJvd1t1bnFDb2wgYXMga2V5b2YgdHlwZW9mIHJvd10gPz8gcmFuZG9tVVVJRCgpOyAvLyBudWxsYWJsZeyduCDqsr3smrAgdXVpZOuhnCDrnpzrjaTqsJIg7IK97J6FXG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyDqsJLsnbQg66qo65GQIG51bGzsnbgg6rK97JqwIO2CpCDsg53shLEg7Yyo7IqkXG4gICAgICAgIGlmICh1bmlxdWVLZXlBcnJheS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdW5pcXVlS2V5QXJyYXkuam9pbihcIi0tLWRlbGltaXRlci0tXCIpO1xuICAgICAgfSlcbiAgICAgIC5maWx0ZXIobm9uTnVsbGFibGUpO1xuXG4gICAgLy8gdXVpZCDsg53shLEg66Gc7KeBXG4gICAgY29uc3QgdXVpZDogc3RyaW5nID0gKCgpID0+IHtcbiAgICAgIC8vIO2CpOulvCDsiJztmoztlZjsl6wg7J2066+4IOyhtOyerO2VmOuKlCDtgqTqsIAg7J6I64qU7KeAIO2ZleyduFxuICAgICAgaWYgKHVuaXF1ZUtleXMubGVuZ3RoID4gMCkge1xuICAgICAgICBmb3IgKGNvbnN0IHVuaXF1ZUtleSBvZiB1bmlxdWVLZXlzKSB7XG4gICAgICAgICAgaWYgKHRhYmxlLnVuaXF1ZXNNYXAuaGFzKHVuaXF1ZUtleSkpIHtcbiAgICAgICAgICAgIHJldHVybiB0YWJsZS51bmlxdWVzTWFwLmdldCh1bmlxdWVLZXkpITsgLy8g7J2066+4IGhhcyDssrTtgazrpbwg7ZaI7Jy866+A66GcIHVuZGVmaW5lZCDrtojqsIDriqVcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8g7LC+7J2EIOyImCDsl4bripQg6rK97JqwIOyDneyEsVxuICAgICAgcmV0dXJuIHJhbmRvbVVVSUQoKTtcbiAgICB9KSgpO1xuXG4gICAgLy8g66qo65OgIOycoOuLiO2BrO2CpOyXkCDrjIDtlbQg7Jyg64uI7YGs66e17JeQIHV1aWQg7KCA7J6lXG4gICAgaWYgKHVuaXF1ZUtleXMubGVuZ3RoID4gMCkge1xuICAgICAgZm9yIChjb25zdCB1bmlxdWVLZXkgb2YgdW5pcXVlS2V5cykge1xuICAgICAgICB0YWJsZS51bmlxdWVzTWFwLnNldCh1bmlxdWVLZXksIHV1aWQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIOydtCDthYzsnbTruJTsl5Ag7IKs7Jqp65CcIFJlZkZpZWxk66W8IOyInO2ajO2VmOyXrCwg7ZiE7J6sIO2FjOydtOu4lCDsoJXrs7Tsl5Ag7Ja065akIO2VhOuTnOulvCDssLjsobDtlZjripTsp4Ag7LaU6rCAXG4gICAgLy8g7J20IOygleuztOulvCDrgpjspJHsl5Ag7LmY7ZmY7ZWgIOuVjCDsgqzsmqlcbiAgICByb3cgPSBPYmplY3Qua2V5cyhyb3cpLnJlZHVjZSgociwgcm93S2V5KSA9PiB7XG4gICAgICBjb25zdCByb3dWYWx1ZSA9IHJvd1tyb3dLZXkgYXMga2V5b2YgdHlwZW9mIHJvd107XG5cbiAgICAgIGlmIChpc1JlZkZpZWxkKHJvd1ZhbHVlKSkge1xuICAgICAgICByb3dWYWx1ZS51c2UgPz89IFwiaWRcIjtcbiAgICAgICAgdGFibGUucmVmZXJlbmNlcy5hZGQocm93VmFsdWUub2YgKyBcIi5cIiArIHJvd1ZhbHVlLnVzZSk7XG4gICAgICAgIHJbcm93S2V5XSA9IHJvd1ZhbHVlO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygcm93VmFsdWUgPT09IFwib2JqZWN0XCIgJiYgIShyb3dWYWx1ZSBpbnN0YW5jZW9mIERhdGUpKSB7XG4gICAgICAgIC8vIG9iamVjdOyduCDqsr3smrAgSlNPTuycvOuhnCDrs4DtmZhcbiAgICAgICAgcltyb3dLZXldID0gcm93VmFsdWUgPT09IG51bGwgPyBudWxsIDogSlNPTi5zdHJpbmdpZnkocm93VmFsdWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcltyb3dLZXldID0gcm93VmFsdWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gcjtcbiAgICB9LCB7fSBhcyBhbnkpO1xuXG4gICAgdGFibGUucm93cy5wdXNoKHtcbiAgICAgIHV1aWQsXG4gICAgICAuLi5yb3csXG4gICAgfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgb2Y6IHRhYmxlTmFtZSxcbiAgICAgIHV1aWQ6IChyb3cgYXMgeyB1dWlkPzogc3RyaW5nIH0pLnV1aWQgPz8gdXVpZCxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgdXBzZXJ0KFxuICAgIHdkYjogS25leCxcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBjaHVua1NpemU/OiBudW1iZXJcbiAgKTogUHJvbWlzZTxudW1iZXJbXT4ge1xuICAgIHJldHVybiB0aGlzLnVwc2VydE9ySW5zZXJ0KHdkYiwgdGFibGVOYW1lLCBcInVwc2VydFwiLCBjaHVua1NpemUpO1xuICB9XG4gIGFzeW5jIGluc2VydE9ubHkoXG4gICAgd2RiOiBLbmV4LFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIGNodW5rU2l6ZT86IG51bWJlclxuICApOiBQcm9taXNlPG51bWJlcltdPiB7XG4gICAgcmV0dXJuIHRoaXMudXBzZXJ0T3JJbnNlcnQod2RiLCB0YWJsZU5hbWUsIFwiaW5zZXJ0XCIsIGNodW5rU2l6ZSk7XG4gIH1cblxuICBhc3luYyB1cHNlcnRPckluc2VydChcbiAgICB3ZGI6IEtuZXgsXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgbW9kZTogXCJ1cHNlcnRcIiB8IFwiaW5zZXJ0XCIsXG4gICAgY2h1bmtTaXplPzogbnVtYmVyXG4gICk6IFByb21pc2U8bnVtYmVyW10+IHtcbiAgICBpZiAodGhpcy5oYXNUYWJsZSh0YWJsZU5hbWUpID09PSBmYWxzZSkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIGNvbnN0IHRhYmxlID0gdGhpcy50YWJsZXMuZ2V0KHRhYmxlTmFtZSk7XG4gICAgaWYgKHRhYmxlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihg7KG07J6s7ZWY7KeAIOyViuuKlCDthYzsnbTruJQgJHt0YWJsZU5hbWV97JeQIHVwc2VydCDsmpTssq1gKTtcbiAgICB9IGVsc2UgaWYgKHRhYmxlLnJvd3MubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7dGFibGVOYW1lfeyXkCB1cHNlcnQg7ZWgIOuNsOydtO2EsOqwgCDsl4bsirXri4jri6QuYCk7XG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgdGFibGUucm93cy5zb21lKChyb3cpID0+XG4gICAgICAgIE9iamVjdC5lbnRyaWVzKHJvdykuc29tZShcbiAgICAgICAgICAoWywgdmFsdWVdKSA9PiBpc1JlZkZpZWxkKHZhbHVlKSAmJiB2YWx1ZS5vZiAhPT0gdGFibGVOYW1lXG4gICAgICAgIClcbiAgICAgIClcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHt0YWJsZU5hbWV9IO2VtOqysOuQmOyngCDslYrsnYAg7LC47KGw6rCAIOyeiOyKteuLiOuLpC5gKTtcbiAgICB9XG5cbiAgICAvLyDsoITssrQg7YWM7J2067iUIOyInO2ajO2VmOyXrCDtmITsnqwg7YWM7J2067iUIOywuOyhsO2VmOuKlCDrqqjrk6Ag7YWM7J2067iUIOy2lOy2nFxuICAgIGNvbnN0IHsgcmVmZXJlbmNlcywgcmVmVGFibGVzIH0gPSBBcnJheS5mcm9tKHRoaXMudGFibGVzKS5yZWR1Y2UoXG4gICAgICAociwgWywgdGFibGVdKSA9PiB7XG4gICAgICAgIGNvbnN0IHJlZmVyZW5jZSA9IEFycmF5LmZyb20odGFibGUucmVmZXJlbmNlcy52YWx1ZXMoKSkuZmluZCgocmVmKSA9PlxuICAgICAgICAgIHJlZi5pbmNsdWRlcyh0YWJsZU5hbWUgKyBcIi5cIilcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKHJlZmVyZW5jZSkge1xuICAgICAgICAgIHIucmVmZXJlbmNlcy5wdXNoKHJlZmVyZW5jZSk7XG4gICAgICAgICAgci5yZWZUYWJsZXMucHVzaCh0YWJsZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcjtcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIHJlZmVyZW5jZXM6IFtdIGFzIHN0cmluZ1tdLFxuICAgICAgICByZWZUYWJsZXM6IFtdIGFzIFRhYmxlRGF0YVtdLFxuICAgICAgfVxuICAgICk7XG4gICAgY29uc3QgZXh0cmFjdEZpZWxkcyA9IF8udW5pcShyZWZlcmVuY2VzKS5tYXAoXG4gICAgICAocmVmZXJlbmNlKSA9PiByZWZlcmVuY2Uuc3BsaXQoXCIuXCIpWzFdXG4gICAgKTtcblxuICAgIC8vIOuCtOu2gCDssLjsobAg7J6I64qUIOqyveyasCDtlYTthLDtlZjsl6wg67aE66asXG4gICAgY29uc3QgZ3JvdXBzID0gXy5ncm91cEJ5KHRhYmxlLnJvd3MsIChyb3cpID0+XG4gICAgICBPYmplY3QuZW50cmllcyhyb3cpLnNvbWUoKFssIHZhbHVlXSkgPT4gaXNSZWZGaWVsZCh2YWx1ZSkpXG4gICAgICAgID8gXCJzZWxmUmVmXCJcbiAgICAgICAgOiBcIm5vcm1hbFwiXG4gICAgKTtcbiAgICBjb25zdCBub3JtYWxSb3dzID0gZ3JvdXBzLm5vcm1hbCA/PyBbXTtcbiAgICBjb25zdCBzZWxmUmVmUm93cyA9IGdyb3Vwcy5zZWxmUmVmID8/IFtdO1xuXG4gICAgY29uc3QgY2h1bmtzID0gY2h1bmtTaXplID8gXy5jaHVuayhub3JtYWxSb3dzLCBjaHVua1NpemUpIDogW25vcm1hbFJvd3NdO1xuICAgIGNvbnN0IHV1aWRNYXAgPSBuZXcgTWFwPHN0cmluZywgYW55PigpO1xuXG4gICAgZm9yIChjb25zdCBjaHVuayBvZiBjaHVua3MpIHtcbiAgICAgIGNvbnN0IHEgPSB3ZGIuaW5zZXJ0KGNodW5rKS5pbnRvKHRhYmxlTmFtZSk7XG4gICAgICBpZiAobW9kZSA9PT0gXCJpbnNlcnRcIikge1xuICAgICAgICBhd2FpdCBxO1xuICAgICAgfSBlbHNlIGlmIChtb2RlID09PSBcInVwc2VydFwiKSB7XG4gICAgICAgIGF3YWl0IHEub25EdXBsaWNhdGVVcGRhdGUuYXBwbHkocSwgT2JqZWN0LmtleXMobm9ybWFsUm93c1swXSkpO1xuICAgICAgfVxuXG4gICAgICAvLyB1cHNlcnTrkJwgcm9365Ok7J2EIOuLpOyLnCDsobDtmoztlZjsl6wgdXVpZE1hcOyXkCDsoIDsnqVcbiAgICAgIGNvbnN0IHV1aWRzID0gY2h1bmsubWFwKChyb3cpID0+IHJvdy51dWlkKTtcbiAgICAgIGNvbnN0IHVwc2VydGVkUm93cyA9IGF3YWl0IHdkYih0YWJsZU5hbWUpXG4gICAgICAgIC5zZWxlY3QoXy51bmlxKFtcInV1aWRcIiwgXCJpZFwiLCAuLi5leHRyYWN0RmllbGRzXSkpXG4gICAgICAgIC53aGVyZUluKFwidXVpZFwiLCB1dWlkcyk7XG4gICAgICB1cHNlcnRlZFJvd3MuZm9yRWFjaCgocm93OiBhbnkpID0+IHtcbiAgICAgICAgdXVpZE1hcC5zZXQocm93LnV1aWQsIHJvdyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyDtlbTri7kg7YWM7J2067iUIOywuOyhsOulvCDsi6TsoJwg67C466WY66GcIOuzgOqyvVxuICAgIHJlZlRhYmxlcy5tYXAoKHRhYmxlKSA9PiB7XG4gICAgICB0YWJsZS5yb3dzID0gdGFibGUucm93cy5tYXAoKHJvdykgPT4ge1xuICAgICAgICBPYmplY3Qua2V5cyhyb3cpLm1hcCgoa2V5KSA9PiB7XG4gICAgICAgICAgY29uc3QgcHJvcCA9IHJvd1trZXldO1xuICAgICAgICAgIGlmIChpc1JlZkZpZWxkKHByb3ApICYmIHByb3Aub2YgPT09IHRhYmxlTmFtZSkge1xuICAgICAgICAgICAgY29uc3QgcGFyZW50ID0gdXVpZE1hcC5nZXQocHJvcC51dWlkKTtcbiAgICAgICAgICAgIGlmIChwYXJlbnQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKHByb3ApO1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgYOyhtOyerO2VmOyngCDslYrripQgdXVpZCAke3Byb3AudXVpZH0gLS0gaW4gJHt0YWJsZU5hbWV9YFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcm93W2tleV0gPSBwYXJlbnRbcHJvcC51c2UgPz8gXCJpZFwiXTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcm93O1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBjb25zdCBhbGxJZHMgPSBBcnJheS5mcm9tKHV1aWRNYXAudmFsdWVzKCkpLm1hcCgocm93KSA9PiByb3cuaWQpO1xuXG4gICAgLy8g7J6Q6riwIOywuOyhsOqwgCDsnojripQg6rK97JqwIOyerOq3gOyggeycvOuhnCB1cHNlcnRcbiAgICBpZiAoc2VsZlJlZlJvd3MubGVuZ3RoID4gMCkge1xuICAgICAgLy8g7LKY66as65CcIOuNsOydtO2EsOulvCDsoJzsmbjtlZjqs6Ag64uk7IucIHVwc2VydFxuICAgICAgdGFibGUucm93cyA9IHNlbGZSZWZSb3dzO1xuICAgICAgY29uc3Qgc2VsZlJlZklkcyA9IGF3YWl0IHRoaXMudXBzZXJ0KHdkYiwgdGFibGVOYW1lLCBjaHVua1NpemUpO1xuICAgICAgYWxsSWRzLnB1c2goLi4uc2VsZlJlZklkcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIOyekOq4sCDssLjsobDqsIAg7JeG7Jy866m0IO2VtOuLuSDthYzsnbTruJTsnZgg642w7J207YSwIOy0iOq4sO2ZlFxuICAgICAgdGFibGUucm93cyA9IFtdO1xuICAgICAgdGFibGUucmVmZXJlbmNlcy5jbGVhcigpO1xuICAgICAgdGFibGUudW5pcXVlc01hcC5jbGVhcigpO1xuICAgIH1cblxuICAgIHJldHVybiBhbGxJZHM7XG4gIH1cblxuICBhc3luYyB1cGRhdGVCYXRjaChcbiAgICB3ZGI6IEtuZXgsXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgb3B0aW9ucz86IHtcbiAgICAgIGNodW5rU2l6ZT86IG51bWJlcjtcbiAgICAgIHdoZXJlPzogc3RyaW5nIHwgc3RyaW5nW107XG4gICAgfVxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBvcHRpb25zID0gXy5kZWZhdWx0cyhvcHRpb25zLCB7XG4gICAgICBjaHVua1NpemU6IDUwMCxcbiAgICAgIHdoZXJlOiBcImlkXCIsXG4gICAgfSk7XG5cbiAgICBpZiAodGhpcy5oYXNUYWJsZSh0YWJsZU5hbWUpID09PSBmYWxzZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCB0YWJsZSA9IHRoaXMudGFibGVzLmdldCh0YWJsZU5hbWUpITtcbiAgICBpZiAodGFibGUucm93cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB3aGVyZUNvbHVtbnMgPSBBcnJheS5pc0FycmF5KG9wdGlvbnMud2hlcmUpXG4gICAgICA/IG9wdGlvbnMud2hlcmVcbiAgICAgIDogW29wdGlvbnMud2hlcmUgPz8gXCJpZFwiXTtcbiAgICBjb25zdCByb3dzID0gdGFibGUucm93cy5tYXAoKF9yb3cpID0+IHtcbiAgICAgIGNvbnN0IHsgdXVpZCwgLi4ucm93IH0gPSBfcm93O1xuICAgICAgcmV0dXJuIHJvdyBhcyBSb3dXaXRoSWQ8c3RyaW5nPjtcbiAgICB9KTtcblxuICAgIGF3YWl0IGJhdGNoVXBkYXRlKHdkYiwgdGFibGVOYW1lLCB3aGVyZUNvbHVtbnMsIHJvd3MsIG9wdGlvbnMuY2h1bmtTaXplKTtcblxuICAgIC8vIHVwZGF0ZUJhdGNoIOyZhOujjCDtm4Qg7LKY66as65CcIOuNsOydtO2EsCDsoJzqsbBcbiAgICB0YWJsZS5yb3dzID0gW107XG4gICAgdGFibGUucmVmZXJlbmNlcy5jbGVhcigpO1xuICAgIHRhYmxlLnVuaXF1ZXNNYXAuY2xlYXIoKTtcbiAgfVxufVxuIl0sIm5hbWVzIjpbInJhbmRvbVVVSUQiLCJfIiwiRW50aXR5TWFuYWdlciIsIm5vbk51bGxhYmxlIiwiYmF0Y2hVcGRhdGUiLCJpc1JlZkZpZWxkIiwiZmllbGQiLCJ1bmRlZmluZWQiLCJvZiIsInV1aWQiLCJVcHNlcnRCdWlsZGVyIiwidGFibGVzIiwiTWFwIiwiZ2V0VGFibGUiLCJ0YWJsZU5hbWUiLCJ0YWJsZSIsImdldCIsInRhYmxlU3BlYyIsImdldFRhYmxlU3BlYyIsInNldCIsInJlZmVyZW5jZXMiLCJTZXQiLCJyb3dzIiwidW5pcXVlSW5kZXhlcyIsInVuaXF1ZXNNYXAiLCJoYXNUYWJsZSIsImhhcyIsInJlZ2lzdGVyIiwicm93IiwidW5pcXVlS2V5cyIsIm1hcCIsInVucUluZGV4IiwidW5pcXVlS2V5QXJyYXkiLCJjb2x1bW5zIiwidW5xQ29sIiwidmFsIiwibGVuZ3RoIiwiam9pbiIsImZpbHRlciIsInVuaXF1ZUtleSIsIk9iamVjdCIsImtleXMiLCJyZWR1Y2UiLCJyIiwicm93S2V5Iiwicm93VmFsdWUiLCJ1c2UiLCJhZGQiLCJEYXRlIiwiSlNPTiIsInN0cmluZ2lmeSIsInB1c2giLCJ1cHNlcnQiLCJ3ZGIiLCJjaHVua1NpemUiLCJ1cHNlcnRPckluc2VydCIsImluc2VydE9ubHkiLCJtb2RlIiwiRXJyb3IiLCJzb21lIiwiZW50cmllcyIsInZhbHVlIiwicmVmVGFibGVzIiwiQXJyYXkiLCJmcm9tIiwicmVmZXJlbmNlIiwidmFsdWVzIiwiZmluZCIsInJlZiIsImluY2x1ZGVzIiwiZXh0cmFjdEZpZWxkcyIsInVuaXEiLCJzcGxpdCIsImdyb3VwcyIsImdyb3VwQnkiLCJub3JtYWxSb3dzIiwibm9ybWFsIiwic2VsZlJlZlJvd3MiLCJzZWxmUmVmIiwiY2h1bmtzIiwiY2h1bmsiLCJ1dWlkTWFwIiwicSIsImluc2VydCIsImludG8iLCJvbkR1cGxpY2F0ZVVwZGF0ZSIsImFwcGx5IiwidXVpZHMiLCJ1cHNlcnRlZFJvd3MiLCJzZWxlY3QiLCJ3aGVyZUluIiwiZm9yRWFjaCIsImtleSIsInByb3AiLCJwYXJlbnQiLCJjb25zb2xlIiwiZXJyb3IiLCJhbGxJZHMiLCJpZCIsInNlbGZSZWZJZHMiLCJjbGVhciIsInVwZGF0ZUJhdGNoIiwib3B0aW9ucyIsImRlZmF1bHRzIiwid2hlcmUiLCJ3aGVyZUNvbHVtbnMiLCJpc0FycmF5IiwiX3JvdyJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsVUFBVSxRQUFRLFNBQVM7QUFDcEMsWUFBWUMsT0FBTyxZQUFZO0FBRS9CLFNBQVNDLGFBQWEsUUFBUSw4QkFBMkI7QUFDekQsU0FBU0MsV0FBVyxRQUFRLG9CQUFpQjtBQUM3QyxTQUFvQkMsV0FBVyxRQUFRLHFCQUFrQjtBQWF6RCxPQUFPLFNBQVNDLFdBQVdDLEtBQVU7SUFDbkMsT0FDRUEsVUFBVUMsYUFDVkQsVUFBVSxRQUNWQSxNQUFNRSxFQUFFLEtBQUtELGFBQ2JELE1BQU1HLElBQUksS0FBS0Y7QUFFbkI7QUFFQSxPQUFPLE1BQU1HO0lBQ1hDLE9BQStCO0lBQy9CLGFBQWM7UUFDWixJQUFJLENBQUNBLE1BQU0sR0FBRyxJQUFJQztJQUNwQjtJQUVBQyxTQUFTQyxTQUFpQixFQUFhO1FBQ3JDLE1BQU1DLFFBQVEsSUFBSSxDQUFDSixNQUFNLENBQUNLLEdBQUcsQ0FBQ0Y7UUFDOUIsSUFBSUMsVUFBVVIsV0FB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
365
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYXRhYmFzZS91cHNlcnQtYnVpbGRlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyByYW5kb21VVUlEIH0gZnJvbSBcImNyeXB0b1wiO1xuaW1wb3J0IHR5cGUgeyBLbmV4IH0gZnJvbSBcImtuZXhcIjtcbmltcG9ydCB7IHVuaXF1ZSB9IGZyb20gXCJyYWRhc2hpXCI7XG5pbXBvcnQgeyBFbnRpdHlNYW5hZ2VyIH0gZnJvbSBcIi4uL2VudGl0eS9lbnRpdHktbWFuYWdlclwiO1xuaW1wb3J0IHsgTmFpdGUgfSBmcm9tIFwiLi4vbmFpdGUvbmFpdGVcIjtcbmltcG9ydCB7IGFzc2VydERlZmluZWQsIGNodW5rLCBub25OdWxsYWJsZSB9IGZyb20gXCIuLi91dGlscy91dGlsc1wiO1xuaW1wb3J0IHsgYmF0Y2hVcGRhdGUsIHR5cGUgUm93V2l0aElkIH0gZnJvbSBcIi4vX2JhdGNoX3VwZGF0ZVwiO1xuXG50eXBlIFRhYmxlRGF0YSA9IHtcbiAgcmVmZXJlbmNlczogU2V0PHN0cmluZz47XG4gIHJvd3M6IFJlY29yZDxzdHJpbmcsIHVua25vd24+W107XG4gIHVuaXF1ZUluZGV4ZXM6IHsgbmFtZT86IHN0cmluZzsgY29sdW1uczogc3RyaW5nW10gfVtdO1xuICB1bmlxdWVzTWFwOiBNYXA8c3RyaW5nLCBzdHJpbmc+O1xufTtcbmV4cG9ydCB0eXBlIFVCUmVmID0ge1xuICB1dWlkOiBzdHJpbmc7XG4gIG9mOiBzdHJpbmc7XG4gIHVzZT86IHN0cmluZztcbn07XG5leHBvcnQgZnVuY3Rpb24gaXNSZWZGaWVsZChmaWVsZDogdW5rbm93bik6IGZpZWxkIGlzIFVCUmVmIHtcbiAgcmV0dXJuIChcbiAgICBmaWVsZCAhPT0gdW5kZWZpbmVkICYmXG4gICAgZmllbGQgIT09IG51bGwgJiZcbiAgICAoZmllbGQgYXMgVUJSZWYpPy5vZiAhPT0gdW5kZWZpbmVkICYmXG4gICAgKGZpZWxkIGFzIFVCUmVmKT8udXVpZCAhPT0gdW5kZWZpbmVkXG4gICk7XG59XG5cbmV4cG9ydCBjbGFzcyBVcHNlcnRCdWlsZGVyIHtcbiAgdGFibGVzOiBNYXA8c3RyaW5nLCBUYWJsZURhdGE+O1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnRhYmxlcyA9IG5ldyBNYXAoKTtcbiAgfVxuXG4gIGdldFRhYmxlKHRhYmxlTmFtZTogc3RyaW5nKTogVGFibGVEYXRhIHtcbiAgICBjb25zdCB0YWJsZSA9IHRoaXMudGFibGVzLmdldCh0YWJsZU5hbWUpO1xuICAgIGlmICh0YWJsZSkge1xuICAgICAgcmV0dXJuIHRhYmxlO1xuICAgIH1cblxuICAgIGNvbnN0IHRhYmxlU3BlYyA9ICgoKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gRW50aXR5TWFuYWdlci5nZXRUYWJsZVNwZWModGFibGVOYW1lKTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICB9KSgpO1xuXG4gICAgY29uc3QgdGFibGVEYXRhID0ge1xuICAgICAgcmVmZXJlbmNlczogbmV3IFNldDxzdHJpbmc+KCksXG4gICAgICByb3dzOiBbXSxcbiAgICAgIHVuaXF1ZUluZGV4ZXM6IHRhYmxlU3BlYz8udW5pcXVlSW5kZXhlcyA/PyBbXSxcbiAgICAgIHVuaXF1ZXNNYXA6IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCksXG4gICAgfTtcbiAgICB0aGlzLnRhYmxlcy5zZXQodGFibGVOYW1lLCB0YWJsZURhdGEpO1xuICAgIHJldHVybiB0YWJsZURhdGE7XG4gIH1cblxuICBoYXNUYWJsZSh0YWJsZU5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnRhYmxlcy5oYXModGFibGVOYW1lKTtcbiAgfVxuXG4gIHJlZ2lzdGVyPFQgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIHJvdzoge1xuICAgICAgW2tleSBpbiBUXT86IFVCUmVmIHwgc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IGJpZ2ludCB8IG51bGwgfCBvYmplY3QgfCB1bmtub3duO1xuICAgIH0sXG4gICk6IFVCUmVmIHtcbiAgICBjb25zdCB0YWJsZSA9IHRoaXMuZ2V0VGFibGUodGFibGVOYW1lKTtcblxuICAgIC8vIO2VtOuLuSDthYzsnbTruJTsnZggdW5pcXVlIOyduOuNseyKpOulvCDsiJztmoztlZjrqbAg7YKkIOyDneyEsVxuICAgIGNvbnN0IHVuaXF1ZUtleXMgPSB0YWJsZS51bmlxdWVJbmRleGVzXG4gICAgICAubWFwKCh1bnFJbmRleCkgPT4ge1xuICAgICAgICBjb25zdCB1bmlxdWVLZXlBcnJheSA9IHVucUluZGV4LmNvbHVtbnMubWFwKCh1bnFDb2wpID0+IHtcbiAgICAgICAgICBjb25zdCB2YWwgPSByb3dbdW5xQ29sIGFzIGtleW9mIHR5cGVvZiByb3ddO1xuICAgICAgICAgIGlmIChpc1JlZkZpZWxkKHZhbCkpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWwudXVpZDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHJvd1t1bnFDb2wgYXMga2V5b2YgdHlwZW9mIHJvd10gPz8gcmFuZG9tVVVJRCgpOyAvLyBudWxsYWJsZeyduCDqsr3smrAgdXVpZOuhnCDrnpzrjaTqsJIg7IK97J6FXG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyDqsJLsnbQg66qo65GQIG51bGzsnbgg6rK97JqwIO2CpCDsg53shLEg7Yyo7IqkXG4gICAgICAgIGlmICh1bmlxdWVLZXlBcnJheS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdW5pcXVlS2V5QXJyYXkuam9pbihcIi0tLWRlbGltaXRlci0tXCIpO1xuICAgICAgfSlcbiAgICAgIC5maWx0ZXIobm9uTnVsbGFibGUpO1xuXG4gICAgLy8gdXVpZCDsg53shLEg66Gc7KeBXG4gICAgY29uc3QgeyB1dWlkLCBpc1JldXNlZCB9ID0gKCgpID0+IHtcbiAgICAgIC8vIO2CpOulvCDsiJztmoztlZjsl6wg7J2066+4IOyhtOyerO2VmOuKlCDtgqTqsIAg7J6I64qU7KeAIO2ZleyduFxuICAgICAgaWYgKHVuaXF1ZUtleXMubGVuZ3RoID4gMCkge1xuICAgICAgICBmb3IgKGNvbnN0IHVuaXF1ZUtleSBvZiB1bmlxdWVLZXlzKSB7XG4gICAgICAgICAgaWYgKHRhYmxlLnVuaXF1ZXNNYXAuaGFzKHVuaXF1ZUtleSkpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIHV1aWQ6IGFzc2VydERlZmluZWQodGFibGUudW5pcXVlc01hcC5nZXQodW5pcXVlS2V5KSwgXCJVbmlxdWUga2V5IG5vdCBmb3VuZFwiKSxcbiAgICAgICAgICAgICAgaXNSZXVzZWQ6IHRydWUsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyDssL7snYQg7IiYIOyXhuuKlCDqsr3smrAg7IOd7ISxXG4gICAgICByZXR1cm4geyB1dWlkOiByYW5kb21VVUlEKCksIGlzUmV1c2VkOiBmYWxzZSB9O1xuICAgIH0pKCk7XG5cbiAgICAvLyDrqqjrk6Ag7Jyg64uI7YGs7YKk7JeQIOuMgO2VtCDsnKDri4jtgazrp7Xsl5AgdXVpZCDsoIDsnqVcbiAgICBpZiAodW5pcXVlS2V5cy5sZW5ndGggPiAwKSB7XG4gICAgICBmb3IgKGNvbnN0IHVuaXF1ZUtleSBvZiB1bmlxdWVLZXlzKSB7XG4gICAgICAgIHRhYmxlLnVuaXF1ZXNNYXAuc2V0KHVuaXF1ZUtleSwgdXVpZCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8g7J20IO2FjOydtOu4lOyXkCDsgqzsmqnrkJwgUmVmRmllbGTrpbwg7Iic7ZqM7ZWY7JesLCDtmITsnqwg7YWM7J2067iUIOygleuztOyXkCDslrTrlqQg7ZWE65Oc66W8IOywuOyhsO2VmOuKlOyngCDstpTqsIBcbiAgICAvLyDsnbQg7KCV67O066W8IOuCmOykkeyXkCDsuZjtmZjtlaAg65WMIOyCrOyaqVxuICAgIHJvdyA9IE9iamVjdC5mcm9tRW50cmllcyhcbiAgICAgIE9iamVjdC5lbnRyaWVzKHJvdykubWFwKChbcm93S2V5LCByb3dWYWx1ZV0pID0+IHtcbiAgICAgICAgaWYgKGlzUmVmRmllbGQocm93VmFsdWUpKSB7XG4gICAgICAgICAgcm93VmFsdWUudXNlID8/PSBcImlkXCI7XG4gICAgICAgICAgdGFibGUucmVmZXJlbmNlcy5hZGQoYCR7cm93VmFsdWUub2Z9LiR7cm93VmFsdWUudXNlfWApO1xuICAgICAgICAgIHJldHVybiBbcm93S2V5LCByb3dWYWx1ZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHJvd1ZhbHVlID09PSBcIm9iamVjdFwiICYmICEocm93VmFsdWUgaW5zdGFuY2VvZiBEYXRlKSkge1xuICAgICAgICAgIC8vIG9iamVjdOyduCDqsr3smrAgSlNPTuycvOuhnCDrs4DtmZhcbiAgICAgICAgICByZXR1cm4gW3Jvd0tleSwgcm93VmFsdWUgPT09IG51bGwgPyBudWxsIDogSlNPTi5zdHJpbmdpZnkocm93VmFsdWUpXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gW3Jvd0tleSwgcm93VmFsdWVdO1xuICAgICAgICB9XG4gICAgICB9KSxcbiAgICApIGFzIHsgW2tleSBpbiBUXT86IHVua25vd24gfTtcblxuICAgIHRhYmxlLnJvd3MucHVzaCh7XG4gICAgICB1dWlkLFxuICAgICAgLi4ucm93LFxuICAgIH0pO1xuXG4gICAgY29uc3QgcmVzdWx0OiBVQlJlZiA9IHtcbiAgICAgIG9mOiB0YWJsZU5hbWUsXG4gICAgICB1dWlkOiAocm93IGFzIHsgdXVpZD86IHN0cmluZyB9KS51dWlkID8/IHV1aWQsXG4gICAgfTtcblxuICAgIE5haXRlLnQoXCJwdXJpOnViLXJlZ2lzdGVyXCIsIHtcbiAgICAgIHRhYmxlTmFtZSxcbiAgICAgIHV1aWQ6IHJlc3VsdC51dWlkLFxuICAgICAgaXNVdWlkUmV1c2VkOiBpc1JldXNlZCxcbiAgICAgIHJvdyxcbiAgICB9KTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBhc3luYyB1cHNlcnQod2RiOiBLbmV4LCB0YWJsZU5hbWU6IHN0cmluZywgY2h1bmtTaXplPzogbnVtYmVyKTogUHJvbWlzZTxudW1iZXJbXT4ge1xuICAgIHJldHVybiB0aGlzLnVwc2VydE9ySW5zZXJ0KHdkYiwgdGFibGVOYW1lLCBcInVwc2VydFwiLCBjaHVua1NpemUpO1xuICB9XG4gIGFzeW5jIGluc2VydE9ubHkod2RiOiBLbmV4LCB0YWJsZU5hbWU6IHN0cmluZywgY2h1bmtTaXplPzogbnVtYmVyKTogUHJvbWlzZTxudW1iZXJbXT4ge1xuICAgIHJldHVybiB0aGlzLnVwc2VydE9ySW5zZXJ0KHdkYiwgdGFibGVOYW1lLCBcImluc2VydFwiLCBjaHVua1NpemUpO1xuICB9XG5cbiAgYXN5bmMgdXBzZXJ0T3JJbnNlcnQoXG4gICAgd2RiOiBLbmV4LFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIG1vZGU6IFwidXBzZXJ0XCIgfCBcImluc2VydFwiLFxuICAgIGNodW5rU2l6ZT86IG51bWJlcixcbiAgKTogUHJvbWlzZTxudW1iZXJbXT4ge1xuICAgIGlmICh0aGlzLmhhc1RhYmxlKHRhYmxlTmFtZSkgPT09IGZhbHNlKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgY29uc3QgdGFibGUgPSB0aGlzLnRhYmxlcy5nZXQodGFibGVOYW1lKTtcbiAgICBpZiAodGFibGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGDsobTsnqztlZjsp4Ag7JWK64qUIO2FjOydtOu4lCAke3RhYmxlTmFtZX3sl5AgdXBzZXJ0IOyalOyyrWApO1xuICAgIH0gZWxzZSBpZiAodGFibGUucm93cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHt0YWJsZU5hbWV97JeQIHVwc2VydCDtlaAg642w7J207YSw6rCAIOyXhuyKteuLiOuLpC5gKTtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICB0YWJsZS5yb3dzLnNvbWUoKHJvdykgPT5cbiAgICAgICAgT2JqZWN0LmVudHJpZXMocm93KS5zb21lKChbLCB2YWx1ZV0pID0+IGlzUmVmRmllbGQodmFsdWUpICYmIHZhbHVlLm9mICE9PSB0YWJsZU5hbWUpLFxuICAgICAgKVxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGAke3RhYmxlTmFtZX0g7ZW06rKw65CY7KeAIOyViuydgCDssLjsobDqsIAg7J6I7Iq164uI64ukLmApO1xuICAgIH1cblxuICAgIC8vIOyghOyytCDthYzsnbTruJQg7Iic7ZqM7ZWY7JesIO2YhOyerCDthYzsnbTruJQg7LC47KGw7ZWY64qUIOuqqOuToCDthYzsnbTruJQg7LaU7LacXG4gICAgY29uc3QgeyByZWZlcmVuY2VzLCByZWZUYWJsZXMgfSA9IEFycmF5LmZyb20odGhpcy50YWJsZXMpLnJlZHVjZShcbiAgICAgIChyLCBbLCB0YWJsZV0pID0+IHtcbiAgICAgICAgY29uc3QgcmVmZXJlbmNlID0gQXJyYXkuZnJvbSh0YWJsZS5yZWZlcmVuY2VzLnZhbHVlcygpKS5maW5kKChyZWYpID0+XG4gICAgICAgICAgcmVmLmluY2x1ZGVzKGAke3RhYmxlTmFtZX0uYCksXG4gICAgICAgICk7XG4gICAgICAgIGlmIChyZWZlcmVuY2UpIHtcbiAgICAgICAgICByLnJlZmVyZW5jZXMucHVzaChyZWZlcmVuY2UpO1xuICAgICAgICAgIHIucmVmVGFibGVzLnB1c2godGFibGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHI7XG4gICAgICB9LFxuICAgICAge1xuICAgICAgICByZWZlcmVuY2VzOiBbXSBhcyBzdHJpbmdbXSxcbiAgICAgICAgcmVmVGFibGVzOiBbXSBhcyBUYWJsZURhdGFbXSxcbiAgICAgIH0sXG4gICAgKTtcbiAgICBjb25zdCBleHRyYWN0RmllbGRzID0gdW5pcXVlKHJlZmVyZW5jZXMpXG4gICAgICAubWFwKChyZWZlcmVuY2UpID0+IHJlZmVyZW5jZS5zcGxpdChcIi5cIilbMV0pXG4gICAgICAuZmlsdGVyKChmaWVsZCk6IGZpZWxkIGlzIHN0cmluZyA9PiBmaWVsZCAhPT0gdW5kZWZpbmVkKTtcblxuICAgIC8vIOydmOyhtOyEsSDsiJzshJzsl5Ag65Sw6528IOugiOuyqOuzhCDqt7jro7ntmZQgKOyekOq4sCDssLjsobDqsIAg7JeG7Jy866m0IExldmVsIDAg7ZWY64KYKVxuICAgIGNvbnN0IHsgbGV2ZWxzLCBoYXNDaXJjdWxhciB9ID0gdGhpcy5idWlsZEluc2VydExldmVscyh0YWJsZS5yb3dzLCB0YWJsZU5hbWUpO1xuXG4gICAgaWYgKGhhc0NpcmN1bGFyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7dGFibGVOYW1lfeyXkCDsiJztmZgg7J6Q6riwIOywuOyhsOqwgCDsnojsirXri4jri6QuYCk7XG4gICAgfVxuXG4gICAgLy8gdXBzZXJ0IOuqqOuTnOydvCDrlYwg7Jyg64uI7YGsIOyduOuNseyKpOqwgCDsl4bsnLzrqbQg7JeQ65+sXG4gICAgaWYgKG1vZGUgPT09IFwidXBzZXJ0XCIgJiYgdGFibGUudW5pcXVlSW5kZXhlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHt0YWJsZU5hbWV97JeQIHVuaXF1ZSBpbmRleOqwgCDsoJXsnZjrkJjsp4Ag7JWK7JWEIHVwc2VydOulvCDtlaAg7IiYIOyXhuyKteuLiOuLpC5gKTtcbiAgICB9XG5cbiAgICBjb25zdCB1dWlkTWFwID0gbmV3IE1hcDxzdHJpbmcsIHVua25vd24+KCk7XG4gICAgY29uc3QgYWxsSWRzOiBudW1iZXJbXSA9IFtdO1xuXG4gICAgLy8g66CI67Ko67OE66GcIOyInOywqCDsspjrpqxcbiAgICBmb3IgKGNvbnN0IGxldmVsUm93cyBvZiBsZXZlbHMpIHtcbiAgICAgIC8vIOydtOyghCDroIjrsqjsl5DshJwg7Ja77J2AIElE66GcIOyekOq4sCDssLjsobAg7ZW06rKwXG4gICAgICBjb25zdCByZXNvbHZlZFJvd3MgPSBsZXZlbFJvd3MubWFwKChyb3cpID0+IHtcbiAgICAgICAgY29uc3QgcmVzb2x2ZWQgPSB7IC4uLnJvdyB9O1xuICAgICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhyb3cpKSB7XG4gICAgICAgICAgaWYgKGlzUmVmRmllbGQodmFsdWUpICYmIHZhbHVlLm9mID09PSB0YWJsZU5hbWUpIHtcbiAgICAgICAgICAgIGNvbnN0IHBhcmVudCA9IHV1aWRNYXAuZ2V0KHZhbHVlLnV1aWQpO1xuXG4gICAgICAgICAgICBpZiAoIXBhcmVudCkgdGhyb3cgbmV3IEVycm9yKGDsobTsnqztlZjsp4Ag7JWK64qUIHV1aWQgJHt2YWx1ZS51dWlkfSAtLSBpbiAke3RhYmxlTmFtZX1gKTtcblxuICAgICAgICAgICAgcmVzb2x2ZWRba2V5XSA9IChwYXJlbnQgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW3ZhbHVlLnVzZSA/PyBcImlkXCJdO1xuXG4gICAgICAgICAgICBOYWl0ZS50KFwicHVyaTp1Yi1yZWYtcmVzb2x2ZWRcIiwge1xuICAgICAgICAgICAgICB0YWJsZU5hbWUsXG4gICAgICAgICAgICAgIGZpZWxkOiBrZXksXG4gICAgICAgICAgICAgIGZyb206IHsgb2Y6IHZhbHVlLm9mLCB1dWlkOiB2YWx1ZS51dWlkLCB1c2U6IHZhbHVlLnVzZSA/PyBcImlkXCIgfSxcbiAgICAgICAgICAgICAgdG86IHJlc29sdmVkW2tleV0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc29sdmVkO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIO2YhOyerCDroIjrsqggdXBzZXJ0XG4gICAgICBjb25zdCBsZXZlbENodW5rcyA9IGNodW5rU2l6ZSA/IGNodW5rKHJlc29sdmVkUm93cywgY2h1bmtTaXplKSA6IFtyZXNvbHZlZFJvd3NdO1xuICAgICAgY29uc3Qgc2VsZWN0RmllbGRzID0gdW5pcXVlKFtcInV1aWRcIiwgXCJpZFwiLCAuLi5leHRyYWN0RmllbGRzXSk7XG5cbiAgICAgIGZvciAoY29uc3QgZGF0YUNodW5rIG9mIGxldmVsQ2h1bmtzKSB7XG4gICAgICAgIGlmIChkYXRhQ2h1bmsubGVuZ3RoID09PSAwKSBjb250aW51ZTtcblxuICAgICAgICBsZXQgcmVzdWx0Um93czogeyB1dWlkOiBzdHJpbmc7IGlkOiBudW1iZXI7IFtrZXk6IHN0cmluZ106IHVua25vd24gfVtdO1xuXG4gICAgICAgIGlmIChtb2RlID09PSBcImluc2VydFwiKSB7XG4gICAgICAgICAgLy8gSU5TRVJUIOuqqOuTnFxuICAgICAgICAgIGF3YWl0IHdkYi5pbnNlcnQoZGF0YUNodW5rKS5pbnRvKHRhYmxlTmFtZSk7XG5cbiAgICAgICAgICBjb25zdCB1dWlkcyA9IGRhdGFDaHVuay5tYXAoKHIpID0+IHIudXVpZCk7XG4gICAgICAgICAgcmVzdWx0Um93cyA9IGF3YWl0IHdkYih0YWJsZU5hbWUpXG4gICAgICAgICAgICAuc2VsZWN0KHNlbGVjdEZpZWxkcylcbiAgICAgICAgICAgIC53aGVyZUluKFwidXVpZFwiLCB1dWlkcyBhcyByZWFkb25seSBzdHJpbmdbXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gVVBTRVJUIOuqqOuTnCAodW5pcXVlSW5kZXhlcyDsnbTrr7gg7LK07YGs65CoKVxuICAgICAgICAgIGNvbnN0IGNvbmZsaWN0Q29sdW1ucyA9IHRhYmxlLnVuaXF1ZUluZGV4ZXNbMF0uY29sdW1ucztcbiAgICAgICAgICBjb25zdCB1cGRhdGVDb2x1bW5zID0gT2JqZWN0LmtleXMoZGF0YUNodW5rWzBdKS5maWx0ZXIoXG4gICAgICAgICAgICAoY29sKSA9PiBjb2wgIT09IFwidXVpZFwiICYmICFjb25mbGljdENvbHVtbnMuaW5jbHVkZXMoY29sKSxcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgLy8gUkVUVVJOSU5H7Jy866GcIOqysOqzvCDrsJvquLBcbiAgICAgICAgICBjb25zdCBxdWVyeSA9IHdkYi5pbnNlcnQoZGF0YUNodW5rKS5pbnRvKHRhYmxlTmFtZSkub25Db25mbGljdChjb25mbGljdENvbHVtbnMpO1xuXG4gICAgICAgICAgLy8gdXBkYXRlQ29sdW1uc+qwgCDruYTslrTsnojsnLzrqbQgaWdub3JlKCksIOyVhOuLiOuptCBtZXJnZSgpXG4gICAgICAgICAgaWYgKHVwZGF0ZUNvbHVtbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXN1bHRSb3dzID0gYXdhaXQgcXVlcnkuaWdub3JlKCkucmV0dXJuaW5nKHNlbGVjdEZpZWxkcyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdFJvd3MgPSBhd2FpdCBxdWVyeS5tZXJnZSh1cGRhdGVDb2x1bW5zKS5yZXR1cm5pbmcoc2VsZWN0RmllbGRzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyDslpHsqr0g66qo65OcIOqzte2GtSDsspjrpqxcbiAgICAgICAgZm9yIChjb25zdCByb3cgb2YgcmVzdWx0Um93cykge1xuICAgICAgICAgIHV1aWRNYXAuc2V0KHJvdy51dWlkLCByb3cpO1xuICAgICAgICAgIGFsbElkcy5wdXNoKHJvdy5pZCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyDtlbTri7kg7YWM7J2067iUIOywuOyhsOulvCDsi6TsoJwg67C466WY66GcIOuzgOqyvVxuICAgIGZvciAoY29uc3QgdGFibGUgb2YgcmVmVGFibGVzKSB7XG4gICAgICB0YWJsZS5yb3dzID0gdGFibGUucm93cy5tYXAoKHJvdykgPT4ge1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhyb3cpKSB7XG4gICAgICAgICAgY29uc3QgcHJvcCA9IHJvd1trZXldO1xuICAgICAgICAgIGlmIChpc1JlZkZpZWxkKHByb3ApICYmIHByb3Aub2YgPT09IHRhYmxlTmFtZSkge1xuICAgICAgICAgICAgY29uc3QgcGFyZW50ID0gdXVpZE1hcC5nZXQocHJvcC51dWlkKTtcbiAgICAgICAgICAgIGlmICghcGFyZW50KSB7XG4gICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IocHJvcCk7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihg7KG07J6s7ZWY7KeAIOyViuuKlCB1dWlkICR7cHJvcC51dWlkfSAtLSBpbiAke3RhYmxlTmFtZX1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJlc29sdmVkVmFsdWUgPSAocGFyZW50IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KVtwcm9wLnVzZSA/PyBcImlkXCJdO1xuICAgICAgICAgICAgcm93W2tleV0gPSByZXNvbHZlZFZhbHVlO1xuXG4gICAgICAgICAgICBOYWl0ZS50KFwicHVyaTp1Yi1yZWYtcmVzb2x2ZWRcIiwge1xuICAgICAgICAgICAgICB0YWJsZU5hbWUsXG4gICAgICAgICAgICAgIGZpZWxkOiBrZXksXG4gICAgICAgICAgICAgIGZyb206IHsgb2Y6IHByb3Aub2YsIHV1aWQ6IHByb3AudXVpZCwgdXNlOiBwcm9wLnVzZSA/PyBcImlkXCIgfSxcbiAgICAgICAgICAgICAgdG86IHJlc29sdmVkVmFsdWUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJvdztcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIO2VtOuLuSDthYzsnbTruJTsnZgg642w7J207YSwIOy0iOq4sO2ZlFxuICAgIHRhYmxlLnJvd3MgPSBbXTtcbiAgICB0YWJsZS5yZWZlcmVuY2VzLmNsZWFyKCk7XG4gICAgdGFibGUudW5pcXVlc01hcC5jbGVhcigpO1xuXG4gICAgTmFpdGUudChcInB1cmk6dWItdXBzZXJ0ZWRcIiwge1xuICAgICAgdGFibGVOYW1lLFxuICAgICAgbW9kZSxcbiAgICAgIHJvd0NvdW50OiBhbGxJZHMubGVuZ3RoLFxuICAgICAgcmV0dXJuZWRJZHM6IGFsbElkcyxcbiAgICB9KTtcblxuICAgIHJldHVybiBhbGxJZHM7XG4gIH1cblxuICBhc3luYyB1cGRhdGVCYXRjaChcbiAgICB3ZGI6IEtuZXgsXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgb3B0aW9ucz86IHtcbiAgICAgIGNodW5rU2l6ZT86IG51bWJlcjtcbiAgICAgIHdoZXJlPzogc3RyaW5nIHwgc3RyaW5nW107XG4gICAgfSxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgb3B0aW9ucyA9IHtcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgICBjaHVua1NpemU6IG9wdGlvbnM/LmNodW5rU2l6ZSA/PyA1MDAsXG4gICAgICB3aGVyZTogb3B0aW9ucz8ud2hlcmUgPz8gXCJpZFwiLFxuICAgIH07XG5cbiAgICBpZiAodGhpcy5oYXNUYWJsZSh0YWJsZU5hbWUpID09PSBmYWxzZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCB0YWJsZSA9IHRoaXMudGFibGVzLmdldCh0YWJsZU5hbWUpO1xuICAgIGlmICghdGFibGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihg65Ox66Gd65CY7KeAIOyViuydgCDthYzsnbTruJQgJHt0YWJsZU5hbWV97JeQIHVwZGF0ZUJhdGNoIOyalOyyrWApO1xuICAgIH0gZWxzZSBpZiAodGFibGUucm93cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB3aGVyZUNvbHVtbnMgPSBBcnJheS5pc0FycmF5KG9wdGlvbnMud2hlcmUpID8gb3B0aW9ucy53aGVyZSA6IFtvcHRpb25zLndoZXJlID8/IFwiaWRcIl07XG4gICAgY29uc3Qgcm93cyA9IHRhYmxlLnJvd3MubWFwKChfcm93KSA9PiB7XG4gICAgICBjb25zdCB7IHV1aWQ6IF8sIC4uLnJvdyB9ID0gX3JvdzsgLy8gdXVpZCDsoJzsmbhcbiAgICAgIHJldHVybiByb3cgYXMgUm93V2l0aElkPHN0cmluZz47XG4gICAgfSk7XG5cbiAgICBhd2FpdCBiYXRjaFVwZGF0ZSh3ZGIsIHRhYmxlTmFtZSwgd2hlcmVDb2x1bW5zLCByb3dzLCBvcHRpb25zLmNodW5rU2l6ZSk7XG5cbiAgICBOYWl0ZS50KFwicHVyaTp1Yi1iYXRjaC11cGRhdGVkXCIsIHtcbiAgICAgIHRhYmxlTmFtZSxcbiAgICAgIHJvd0NvdW50OiByb3dzLmxlbmd0aCxcbiAgICAgIHdoZXJlQ29sdW1ucyxcbiAgICB9KTtcblxuICAgIC8vIHVwZGF0ZUJhdGNoIOyZhOujjCDtm4Qg7LKY66as65CcIOuNsOydtO2EsCDsoJzqsbBcbiAgICB0YWJsZS5yb3dzID0gW107XG4gICAgdGFibGUucmVmZXJlbmNlcy5jbGVhcigpO1xuICAgIHRhYmxlLnVuaXF1ZXNNYXAuY2xlYXIoKTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gUHJpdmF0ZSBIZWxwZXJzXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogcm93c+ulvCDsnZjsobTshLEg7Iic7ISc7JeQIOuUsOudvCDroIjrsqjrs4TroZwg6re466O57ZmUXG4gICAqIC0g7J6Q6riwIOywuOyhsCDsl4bripQg6rK97JqwIDog66qo65OgIHJvd3PqsIAgTGV2ZWwgMFxuICAgKiAtIOyekOq4sCDssLjsobAg7J6I64qUIOqyveyasCA6IOyekOq4sCDssLjsobAg6rSA6rOE66W8IOychOyDgSDsoJXroKztlZjsl6wg66CI67Ko67OE66GcIOq3uOujue2ZlFxuICAgKi9cbiAgcHJpdmF0ZSBidWlsZEluc2VydExldmVscyhcbiAgICByb3dzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPltdLFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICApOiB7IGxldmVsczogUmVjb3JkPHN0cmluZywgdW5rbm93bj5bXVtdOyBoYXNDaXJjdWxhcjogYm9vbGVhbiB9IHtcbiAgICAvLyAxLiDsnpDquLAg7LC47KGw6rCAIOyXhuycvOuptCDtlZwg66CI67Ko66GcIOyymOumrFxuICAgIGNvbnN0IGhhc1NlbGZSZWYgPSByb3dzXG4gICAgICAuZmxhdE1hcCgocm93KSA9PiBPYmplY3QudmFsdWVzKHJvdykpXG4gICAgICAuc29tZSgodmFsdWUpID0+IGlzUmVmRmllbGQodmFsdWUpICYmIHZhbHVlLm9mID09PSB0YWJsZU5hbWUpO1xuICAgIGlmICghaGFzU2VsZlJlZikgcmV0dXJuIHsgbGV2ZWxzOiBbcm93c10sIGhhc0NpcmN1bGFyOiBmYWxzZSB9O1xuXG4gICAgLy8gMi4gdXVpZCDihpIgcm93IOunpO2VkSAo7KSR67O1IHV1aWQg67Cp7KeAKVxuICAgIGNvbnN0IHJvd0J5VXVpZCA9IG5ldyBNYXA8c3RyaW5nLCBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4oKTtcbiAgICBmb3IgKGNvbnN0IHJvdyBvZiByb3dzKSB7XG4gICAgICBjb25zdCB1dWlkID0gcm93LnV1aWQgYXMgc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgICAgaWYgKCF1dWlkKSB0aHJvdyBuZXcgRXJyb3IoYGJ1aWxkSW5zZXJ0TGV2ZWxzOiB1dWlk6rCAIOyXhuuKlCByb3cgLS0gaW4gJHt0YWJsZU5hbWV9YCk7XG4gICAgICByb3dCeVV1aWQuc2V0KHV1aWQsIHJvdyk7XG4gICAgfVxuXG4gICAgbGV0IHBlbmRpbmcgPSBBcnJheS5mcm9tKHJvd0J5VXVpZC52YWx1ZXMoKSk7XG4gICAgY29uc3QgbGV2ZWxzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPltdW10gPSBbXTtcbiAgICBjb25zdCBpbnNlcnRlZCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gICAgLy8gMy4g66CI67Ko67OEIOu2hOulmFxuICAgIHdoaWxlIChwZW5kaW5nLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IGN1cnJlbnRMZXZlbDogUmVjb3JkPHN0cmluZywgdW5rbm93bj5bXSA9IFtdO1xuICAgICAgY29uc3QgbmV4dFBlbmRpbmc6IFJlY29yZDxzdHJpbmcsIHVua25vd24+W10gPSBbXTtcblxuICAgICAgZm9yIChjb25zdCByb3cgb2YgcGVuZGluZykge1xuICAgICAgICAvLyDsnbQgcm936rCAIOywuOyhsO2VmOuKlCDsnpDquLAg7LC47KGw65OkXG4gICAgICAgIGNvbnN0IHNlbGZSZWZzID0gT2JqZWN0LnZhbHVlcyhyb3cpLmZpbHRlcihcbiAgICAgICAgICAodmFsdWUpID0+IGlzUmVmRmllbGQodmFsdWUpICYmIHZhbHVlLm9mID09PSB0YWJsZU5hbWUsXG4gICAgICAgICkgYXMgVUJSZWZbXTtcblxuICAgICAgICAvLyDssLjsobDtlZjripQg66qo65OgIHV1aWTqsIAg7J2066+4IGluc2VydGVk7JeQIOyeiOyWtOyVvCDsnbTrsogg66CI67Ko7JeQIO2PrO2VqFxuICAgICAgICBjb25zdCBjYW5JbnNlcnQgPSBzZWxmUmVmcy5ldmVyeSgocmVmKSA9PiB7XG4gICAgICAgICAgaWYgKCFyb3dCeVV1aWQuaGFzKHJlZi51dWlkKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGDsobTsnqztlZjsp4Ag7JWK64qUIHV1aWQgJHtyZWYudXVpZH0gLS0gaW4gJHt0YWJsZU5hbWV9YCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBpbnNlcnRlZC5oYXMocmVmLnV1aWQpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoY2FuSW5zZXJ0KSB7XG4gICAgICAgICAgY3VycmVudExldmVsLnB1c2gocm93KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBuZXh0UGVuZGluZy5wdXNoKHJvdyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8g7Iic7ZmYIOywuOyhsCDqsJDsp4BcbiAgICAgIGlmIChjdXJyZW50TGV2ZWwubGVuZ3RoID09PSAwKSByZXR1cm4geyBsZXZlbHM6IFtdLCBoYXNDaXJjdWxhcjogdHJ1ZSB9O1xuXG4gICAgICAvLyDroIjrsqgg7ZmV7KCVICsgaW5zZXJ0ZWQg6rCx7IugXG4gICAgICBsZXZlbHMucHVzaChjdXJyZW50TGV2ZWwpO1xuICAgICAgZm9yIChjb25zdCByb3cgb2YgY3VycmVudExldmVsKSB7XG4gICAgICAgIGluc2VydGVkLmFkZChyb3cudXVpZCBhcyBzdHJpbmcpO1xuICAgICAgfVxuXG4gICAgICBwZW5kaW5nID0gbmV4dFBlbmRpbmc7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgbGV2ZWxzLCBoYXNDaXJjdWxhcjogZmFsc2UgfTtcbiAgfVxufVxuIl0sIm5hbWVzIjpbInJhbmRvbVVVSUQiLCJ1bmlxdWUiLCJFbnRpdHlNYW5hZ2VyIiwiTmFpdGUiLCJhc3NlcnREZWZpbmVkIiwiY2h1bmsiLCJub25OdWxsYWJsZSIsImJhdGNoVXBkYXRlIiwiaXNSZWZGaWVsZCIsImZpZWxkIiwidW5kZWZpbmVkIiwib2YiLCJ1dWlkIiwiVXBzZXJ0QnVpbGRlciIsInRhYmxlcyIsIk1hcCIsImdldFRhYmxlIiwidGFibGVOYW1lIiwidGFibGUiLCJnZXQiLCJ0YWJsZVNwZWMiLCJnZXRUYWJsZVNwZWMiLCJ0YWJsZURhdGEiLCJyZWZlcmVuY2VzIiwiU2V0Iiwicm93cyIsInVuaXF1ZUluZGV4ZXMiLCJ1bmlxdWVzTWFwIiwic2V0IiwiaGFzVGFibGUiLCJoYXMiLCJyZWdpc3RlciIsInJvdyIsInVuaXF1ZUtleXMiLCJtYXAiLCJ1bnFJbmRleCIsInVuaXF1ZUtleUFycmF5IiwiY29sdW1ucyIsInVucUNvbCIsInZhbCIsImxlbmd0aCIsImpvaW4iLCJmaWx0ZXIiLCJpc1JldXNlZCIsInVuaXF1ZUtleSIsIk9iamVjdCIsImZyb21FbnRyaWVzIiwiZW50cmllcyIsInJvd0tleSIsInJvd1ZhbHVlIiwidXNlIiwiYWRkIiwiRGF0ZSIsIkpTT04iLCJzdHJpbmdpZnkiLCJwdXNoIiwicmVzdWx0IiwidCIsImlzVXVpZFJldXNlZCIsInVwc2VydCIsIndkYiIsImNodW5rU2l6ZSIsInVwc2VydE9ySW5zZXJ0IiwiaW5zZXJ0T25seSIsIm1vZGUiLCJFcnJvciIsInNvbWUiLCJ2YWx1ZSIsInJlZlRhYmxlcyIsIkFycmF5IiwiZnJvbSIsInJlZHVjZSIsInIiLCJyZWZlcmVuY2UiLCJ2YWx1ZXMiLCJmaW5kIiwicmVmIiwiaW5jbHVkZXMiLCJleHRyYWN0RmllbGRzIiwic3BsaXQiLCJsZXZlbHMiLCJoYXNDaXJjdWxhciIsImJ1aWxkSW5zZXJ0TGV2ZWxzIiwidXVpZE1hcCIsImFsbElkcyIsImxldmVsUm93cyIsInJlc29sdmVkUm93cyIsInJlc29sdmVkIiwia2V5IiwicGFyZW50IiwidG8iLCJsZXZlbENodW5rcyIsInNlbGVjdEZpZWxkcyIsImRhdGFDaHVuayIsInJlc3VsdFJvd3MiLCJpbnNlcnQiLCJpbnRvIiwidXVpZHMiLCJzZWxlY3QiLCJ3aGVyZUluIiwiY29uZmxpY3RDb2x1bW5zIiwidXBkYXRlQ29sdW1ucyIsImtleXMiLCJjb2wiLCJxdWVyeSIsIm9uQ29uZmxpY3QiLCJpZ25vcmUiLCJyZXR1cm5pbmciLCJtZXJnZSIsImlkIiwicHJvcCIsImNvbnNvbGUiLCJlcnJvciIsInJlc29sdmVkVmFsdWUiLCJjbGVhciIsInJvd0NvdW50IiwicmV0dXJuZWRJZHMiLCJ1cGRhdGVCYXRjaCIsIm9wdGlvbnMiLCJ3aGVyZSIsIndoZXJlQ29sdW1ucyIsImlzQXJyYXkiLCJfcm93IiwiXyIsImhhc1NlbGZSZWYiLCJmbGF0TWFwIiwicm93QnlVdWlkIiwicGVuZGluZyIsImluc2VydGVkIiwiY3VycmVudExldmVsIiwibmV4dFBlbmRpbmciLCJzZWxmUmVmcyIsImNhbkluc2VydCIsImV2ZXJ5Il0sIm1hcHBpbmdzIjoiQUFBQSxTQUFTQSxVQUFVLFFBQVEsU0FBUztBQUVwQyxTQUFTQyxNQUFNLFFBQVEsVUFBVTtBQUNqQyxTQUFTQyxhQUFhLFFBQVEsOEJBQTJCO0FBQ3pELFNBQVNDLEtBQUssUUFBUSxvQkFBaUI7QUFDdkMsU0FBU0MsYUFBYSxFQUFFQyxLQUFLLEVBQUVDLFdBQVcsUUFBUSxvQkFBaUI7QUFD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