sonamu 0.6.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (406) hide show
  1. package/.swcrc.project-default +18 -0
  2. package/bin/cli.js +24 -0
  3. package/dist/ai/agents/agent.d.ts +11 -0
  4. package/dist/ai/agents/agent.d.ts.map +1 -0
  5. package/dist/ai/agents/agent.js +65 -0
  6. package/dist/ai/agents/index.d.ts +3 -0
  7. package/dist/ai/agents/index.d.ts.map +1 -0
  8. package/dist/ai/agents/index.js +4 -0
  9. package/dist/ai/agents/types.d.ts +43 -0
  10. package/dist/ai/agents/types.d.ts.map +1 -0
  11. package/dist/ai/agents/types.js +3 -0
  12. package/dist/ai/index.d.ts +2 -0
  13. package/dist/ai/index.d.ts.map +1 -0
  14. package/dist/ai/index.js +3 -0
  15. package/dist/ai/providers/rtzr/api.d.ts +22 -0
  16. package/dist/ai/providers/rtzr/api.d.ts.map +1 -0
  17. package/dist/ai/providers/rtzr/api.js +28 -0
  18. package/dist/ai/providers/rtzr/error.d.ts +18 -0
  19. package/dist/ai/providers/rtzr/error.d.ts.map +1 -0
  20. package/dist/ai/providers/rtzr/error.js +29 -0
  21. package/dist/ai/providers/rtzr/index.d.ts +5 -0
  22. package/dist/ai/providers/rtzr/index.d.ts.map +1 -0
  23. package/dist/ai/providers/rtzr/index.js +6 -0
  24. package/dist/ai/providers/rtzr/model.d.ts +52 -0
  25. package/dist/ai/providers/rtzr/model.d.ts.map +1 -0
  26. package/dist/ai/providers/rtzr/model.js +137 -0
  27. package/dist/ai/providers/rtzr/options.d.ts +7 -0
  28. package/dist/ai/providers/rtzr/options.d.ts.map +1 -0
  29. package/dist/ai/providers/rtzr/options.js +47 -0
  30. package/dist/ai/providers/rtzr/provider.d.ts +18 -0
  31. package/dist/ai/providers/rtzr/provider.d.ts.map +1 -0
  32. package/dist/ai/providers/rtzr/provider.js +54 -0
  33. package/dist/ai/providers/rtzr/utils.d.ts +19 -0
  34. package/dist/ai/providers/rtzr/utils.d.ts.map +1 -0
  35. package/dist/ai/providers/rtzr/utils.js +88 -0
  36. package/dist/api/base-frame.d.ts +2 -2
  37. package/dist/api/base-frame.d.ts.map +1 -1
  38. package/dist/api/base-frame.js +2 -1
  39. package/dist/api/caster.d.ts.map +1 -1
  40. package/dist/api/caster.js +6 -1
  41. package/dist/api/code-converters.d.ts +58 -14
  42. package/dist/api/code-converters.d.ts.map +1 -1
  43. package/dist/api/code-converters.js +178 -409
  44. package/dist/api/config.d.ts +27 -13
  45. package/dist/api/config.d.ts.map +1 -1
  46. package/dist/api/config.js +19 -26
  47. package/dist/api/context.d.ts +4 -3
  48. package/dist/api/context.d.ts.map +1 -1
  49. package/dist/api/context.js +1 -1
  50. package/dist/api/decorators.d.ts +20 -6
  51. package/dist/api/decorators.d.ts.map +1 -1
  52. package/dist/api/decorators.js +111 -18
  53. package/dist/api/index.d.ts +2 -2
  54. package/dist/api/index.d.ts.map +1 -1
  55. package/dist/api/index.js +3 -3
  56. package/dist/api/sonamu.d.ts +7 -7
  57. package/dist/api/sonamu.d.ts.map +1 -1
  58. package/dist/api/sonamu.js +83 -51
  59. package/dist/api/validator.d.ts +6 -0
  60. package/dist/api/validator.d.ts.map +1 -0
  61. package/dist/api/validator.js +81 -0
  62. package/dist/bin/build-config.d.ts +5 -1
  63. package/dist/bin/build-config.d.ts.map +1 -1
  64. package/dist/bin/build-config.js +5 -2
  65. package/dist/bin/cli.js +165 -64
  66. package/dist/bin/loader-register.d.ts +2 -0
  67. package/dist/bin/loader-register.d.ts.map +1 -0
  68. package/dist/bin/loader-register.js +34 -0
  69. package/dist/database/_batch_update.d.ts +5 -3
  70. package/dist/database/_batch_update.d.ts.map +1 -1
  71. package/dist/database/_batch_update.js +30 -13
  72. package/dist/database/base-model.d.ts +96 -10
  73. package/dist/database/base-model.d.ts.map +1 -1
  74. package/dist/database/base-model.js +232 -89
  75. package/dist/database/base-model.types.d.ts +93 -0
  76. package/dist/database/base-model.types.d.ts.map +1 -0
  77. package/dist/database/base-model.types.js +10 -0
  78. package/dist/database/code-generator.d.ts +1 -1
  79. package/dist/database/code-generator.d.ts.map +1 -1
  80. package/dist/database/code-generator.js +11 -10
  81. package/dist/database/db.d.ts +5 -6
  82. package/dist/database/db.d.ts.map +1 -1
  83. package/dist/database/db.js +22 -25
  84. package/dist/database/puri-subset.test-d.js +81 -0
  85. package/dist/database/puri-subset.types.d.ts +123 -0
  86. package/dist/database/puri-subset.types.d.ts.map +1 -0
  87. package/dist/database/puri-subset.types.js +16 -0
  88. package/dist/database/puri-wrapper.d.ts +13 -11
  89. package/dist/database/puri-wrapper.d.ts.map +1 -1
  90. package/dist/database/puri-wrapper.js +2 -2
  91. package/dist/database/puri.d.ts +25 -14
  92. package/dist/database/puri.d.ts.map +1 -1
  93. package/dist/database/puri.js +83 -21
  94. package/dist/database/puri.types.d.ts +21 -7
  95. package/dist/database/puri.types.d.ts.map +1 -1
  96. package/dist/database/puri.types.js +4 -1
  97. package/dist/database/transaction-context.d.ts +1 -1
  98. package/dist/database/transaction-context.d.ts.map +1 -1
  99. package/dist/database/transaction-context.js +1 -1
  100. package/dist/database/upsert-builder.d.ts +9 -3
  101. package/dist/database/upsert-builder.d.ts.map +1 -1
  102. package/dist/database/upsert-builder.js +227 -78
  103. package/dist/entity/entity-manager.d.ts +165 -2
  104. package/dist/entity/entity-manager.d.ts.map +1 -1
  105. package/dist/entity/entity-manager.js +26 -10
  106. package/dist/entity/entity.d.ts +5 -3
  107. package/dist/entity/entity.d.ts.map +1 -1
  108. package/dist/entity/entity.js +153 -54
  109. package/dist/exceptions/error-handler.d.ts +1 -1
  110. package/dist/exceptions/error-handler.d.ts.map +1 -1
  111. package/dist/exceptions/error-handler.js +1 -1
  112. package/dist/exceptions/so-exceptions.d.ts +1 -1
  113. package/dist/exceptions/so-exceptions.d.ts.map +1 -1
  114. package/dist/exceptions/so-exceptions.js +1 -1
  115. package/dist/file-storage/driver.d.ts +1 -1
  116. package/dist/file-storage/driver.d.ts.map +1 -1
  117. package/dist/file-storage/driver.js +1 -1
  118. package/dist/file-storage/file-storage.js +2 -2
  119. package/dist/index.d.ts +18 -11
  120. package/dist/index.d.ts.map +1 -1
  121. package/dist/index.js +19 -13
  122. package/dist/migration/code-generation.d.ts +1 -1
  123. package/dist/migration/code-generation.d.ts.map +1 -1
  124. package/dist/migration/code-generation.js +123 -67
  125. package/dist/migration/migration-set.d.ts +2 -10
  126. package/dist/migration/migration-set.d.ts.map +1 -1
  127. package/dist/migration/migration-set.js +67 -218
  128. package/dist/migration/migrator.d.ts +24 -73
  129. package/dist/migration/migrator.d.ts.map +1 -1
  130. package/dist/migration/migrator.js +121 -301
  131. package/dist/migration/postgresql-schema-reader.d.ts +51 -0
  132. package/dist/migration/postgresql-schema-reader.d.ts.map +1 -0
  133. package/dist/migration/postgresql-schema-reader.js +245 -0
  134. package/dist/migration/types.d.ts +6 -38
  135. package/dist/migration/types.d.ts.map +1 -1
  136. package/dist/migration/types.js +1 -1
  137. package/dist/naite/messaging-types.d.ts +43 -0
  138. package/dist/naite/messaging-types.d.ts.map +1 -0
  139. package/dist/naite/messaging-types.js +7 -0
  140. package/dist/naite/naite-reporter.d.ts +41 -0
  141. package/dist/naite/naite-reporter.d.ts.map +1 -0
  142. package/dist/naite/naite-reporter.js +102 -0
  143. package/dist/naite/naite.d.ts +91 -8
  144. package/dist/naite/naite.d.ts.map +1 -1
  145. package/dist/naite/naite.js +285 -41
  146. package/dist/stream/sse.d.ts +2 -2
  147. package/dist/stream/sse.d.ts.map +1 -1
  148. package/dist/stream/sse.js +1 -1
  149. package/dist/syncer/api-parser.d.ts +3 -13
  150. package/dist/syncer/api-parser.d.ts.map +1 -1
  151. package/dist/syncer/api-parser.js +67 -56
  152. package/dist/syncer/checksum.d.ts +2 -2
  153. package/dist/syncer/checksum.d.ts.map +1 -1
  154. package/dist/syncer/checksum.js +11 -11
  155. package/dist/syncer/code-generator.d.ts +3 -3
  156. package/dist/syncer/code-generator.d.ts.map +1 -1
  157. package/dist/syncer/code-generator.js +37 -17
  158. package/dist/syncer/entity-operations.d.ts +2 -2
  159. package/dist/syncer/entity-operations.d.ts.map +1 -1
  160. package/dist/syncer/entity-operations.js +9 -8
  161. package/dist/syncer/file-patterns.d.ts +1 -1
  162. package/dist/syncer/file-patterns.d.ts.map +1 -1
  163. package/dist/syncer/file-patterns.js +1 -1
  164. package/dist/syncer/index.d.ts +4 -4
  165. package/dist/syncer/index.d.ts.map +1 -1
  166. package/dist/syncer/index.js +5 -5
  167. package/dist/syncer/module-loader.d.ts +4 -4
  168. package/dist/syncer/module-loader.d.ts.map +1 -1
  169. package/dist/syncer/module-loader.js +17 -12
  170. package/dist/syncer/syncer.d.ts +31 -24
  171. package/dist/syncer/syncer.d.ts.map +1 -1
  172. package/dist/syncer/syncer.js +92 -45
  173. package/dist/template/entity-converter.d.ts +1 -1
  174. package/dist/template/entity-converter.d.ts.map +1 -1
  175. package/dist/template/entity-converter.js +15 -8
  176. package/dist/template/helpers.d.ts +2 -2
  177. package/dist/template/helpers.d.ts.map +1 -1
  178. package/dist/template/helpers.js +3 -3
  179. package/dist/template/implementations/entity.template.d.ts +2 -2
  180. package/dist/template/implementations/entity.template.d.ts.map +1 -1
  181. package/dist/template/implementations/entity.template.js +4 -5
  182. package/dist/template/implementations/generated.template.d.ts +2 -3
  183. package/dist/template/implementations/generated.template.d.ts.map +1 -1
  184. package/dist/template/implementations/generated.template.js +46 -29
  185. package/dist/template/implementations/generated_http.template.d.ts +2 -3
  186. package/dist/template/implementations/generated_http.template.d.ts.map +1 -1
  187. package/dist/template/implementations/generated_http.template.js +9 -9
  188. package/dist/template/implementations/generated_sso.template.d.ts +3 -4
  189. package/dist/template/implementations/generated_sso.template.d.ts.map +1 -1
  190. package/dist/template/implementations/generated_sso.template.js +54 -25
  191. package/dist/template/implementations/init_types.template.d.ts +2 -2
  192. package/dist/template/implementations/init_types.template.d.ts.map +1 -1
  193. package/dist/template/implementations/init_types.template.js +2 -2
  194. package/dist/template/implementations/model.template.d.ts +2 -2
  195. package/dist/template/implementations/model.template.d.ts.map +1 -1
  196. package/dist/template/implementations/model.template.js +47 -37
  197. package/dist/template/implementations/model_test.template.d.ts +2 -2
  198. package/dist/template/implementations/model_test.template.d.ts.map +1 -1
  199. package/dist/template/implementations/model_test.template.js +2 -2
  200. package/dist/template/implementations/service.template.d.ts +4 -4
  201. package/dist/template/implementations/service.template.d.ts.map +1 -1
  202. package/dist/template/implementations/service.template.js +24 -16
  203. package/dist/template/implementations/view_enums_buttonset.template.d.ts +2 -2
  204. package/dist/template/implementations/view_enums_buttonset.template.d.ts.map +1 -1
  205. package/dist/template/implementations/view_enums_buttonset.template.js +1 -1
  206. package/dist/template/implementations/view_enums_dropdown.template.d.ts +2 -2
  207. package/dist/template/implementations/view_enums_dropdown.template.d.ts.map +1 -1
  208. package/dist/template/implementations/view_enums_dropdown.template.js +2 -2
  209. package/dist/template/implementations/view_enums_select.template.d.ts +2 -2
  210. package/dist/template/implementations/view_enums_select.template.d.ts.map +1 -1
  211. package/dist/template/implementations/view_enums_select.template.js +2 -2
  212. package/dist/template/implementations/view_form.template.d.ts +2 -2
  213. package/dist/template/implementations/view_form.template.d.ts.map +1 -1
  214. package/dist/template/implementations/view_form.template.js +4 -4
  215. package/dist/template/implementations/view_id_all_select.template.d.ts +2 -2
  216. package/dist/template/implementations/view_id_all_select.template.d.ts.map +1 -1
  217. package/dist/template/implementations/view_id_all_select.template.js +1 -1
  218. package/dist/template/implementations/view_id_async_select.template.d.ts +2 -2
  219. package/dist/template/implementations/view_id_async_select.template.d.ts.map +1 -1
  220. package/dist/template/implementations/view_id_async_select.template.js +1 -1
  221. package/dist/template/implementations/view_list.template.d.ts +2 -2
  222. package/dist/template/implementations/view_list.template.d.ts.map +1 -1
  223. package/dist/template/implementations/view_list.template.js +29 -19
  224. package/dist/template/implementations/view_list_columns.template.d.ts +3 -3
  225. package/dist/template/implementations/view_list_columns.template.d.ts.map +1 -1
  226. package/dist/template/implementations/view_list_columns.template.js +1 -1
  227. package/dist/template/implementations/view_search_input.template.d.ts +2 -2
  228. package/dist/template/implementations/view_search_input.template.d.ts.map +1 -1
  229. package/dist/template/implementations/view_search_input.template.js +1 -1
  230. package/dist/template/index.d.ts +4 -2
  231. package/dist/template/index.d.ts.map +1 -1
  232. package/dist/template/index.js +5 -3
  233. package/dist/template/template-manager.d.ts +56 -0
  234. package/dist/template/template-manager.d.ts.map +1 -0
  235. package/dist/template/template-manager.js +125 -0
  236. package/dist/template/template-types.d.ts +16 -0
  237. package/dist/template/template-types.d.ts.map +1 -0
  238. package/dist/template/template-types.js +7 -0
  239. package/dist/template/template.d.ts +12 -2
  240. package/dist/template/template.d.ts.map +1 -1
  241. package/dist/template/template.js +19 -6
  242. package/dist/template/zod-converter.d.ts +40 -7
  243. package/dist/template/zod-converter.d.ts.map +1 -1
  244. package/dist/template/zod-converter.js +386 -58
  245. package/dist/testing/_relation-graph.d.ts +1 -1
  246. package/dist/testing/_relation-graph.d.ts.map +1 -1
  247. package/dist/testing/_relation-graph.js +12 -3
  248. package/dist/testing/fixture-manager.d.ts +42 -11
  249. package/dist/testing/fixture-manager.d.ts.map +1 -1
  250. package/dist/testing/fixture-manager.js +338 -236
  251. package/dist/types/types.d.ts +709 -104
  252. package/dist/types/types.d.ts.map +1 -1
  253. package/dist/types/types.js +309 -52
  254. package/dist/typings/knex.d.js +2 -2
  255. package/dist/utils/async-utils.d.ts.map +1 -1
  256. package/dist/utils/async-utils.js +3 -3
  257. package/dist/utils/console-util.js +1 -1
  258. package/dist/utils/controller.d.ts +1 -0
  259. package/dist/utils/controller.d.ts.map +1 -1
  260. package/dist/utils/controller.js +4 -1
  261. package/dist/utils/esm-utils.d.ts +0 -6
  262. package/dist/utils/esm-utils.d.ts.map +1 -1
  263. package/dist/utils/esm-utils.js +2 -9
  264. package/dist/utils/formatter.d.ts +3 -0
  265. package/dist/utils/formatter.d.ts.map +1 -0
  266. package/dist/utils/formatter.js +110 -0
  267. package/dist/utils/fs-utils.d.ts +1 -1
  268. package/dist/utils/fs-utils.d.ts.map +1 -1
  269. package/dist/utils/fs-utils.js +1 -1
  270. package/dist/utils/lodash-able.d.ts.map +1 -1
  271. package/dist/utils/lodash-able.js +1 -1
  272. package/dist/utils/object-utils.d.ts +44 -0
  273. package/dist/utils/object-utils.d.ts.map +1 -0
  274. package/dist/utils/object-utils.js +191 -0
  275. package/dist/utils/path-utils.d.ts +1 -1
  276. package/dist/utils/path-utils.d.ts.map +1 -1
  277. package/dist/utils/path-utils.js +3 -3
  278. package/dist/utils/process-utils.js +1 -1
  279. package/dist/utils/sql-parser.d.ts +5 -1
  280. package/dist/utils/sql-parser.d.ts.map +1 -1
  281. package/dist/utils/sql-parser.js +14 -3
  282. package/dist/utils/type-utils.d.ts +23 -0
  283. package/dist/utils/type-utils.d.ts.map +1 -0
  284. package/dist/utils/type-utils.js +45 -0
  285. package/dist/utils/utils.d.ts +7 -1
  286. package/dist/utils/utils.d.ts.map +1 -1
  287. package/dist/utils/utils.js +44 -5
  288. package/dist/utils/zod-error.d.ts +1 -1
  289. package/dist/utils/zod-error.d.ts.map +1 -1
  290. package/dist/utils/zod-error.js +1 -1
  291. package/package.json +55 -30
  292. package/src/ai/agents/agent.ts +87 -0
  293. package/src/ai/agents/index.ts +2 -0
  294. package/src/ai/agents/types.ts +47 -0
  295. package/src/ai/index.ts +1 -0
  296. package/src/ai/providers/rtzr/api.ts +37 -0
  297. package/src/ai/providers/rtzr/error.ts +34 -0
  298. package/src/ai/providers/rtzr/index.ts +4 -0
  299. package/src/ai/providers/rtzr/model.ts +201 -0
  300. package/src/ai/providers/rtzr/options.ts +49 -0
  301. package/src/ai/providers/rtzr/provider.ts +91 -0
  302. package/src/ai/providers/rtzr/utils.ts +127 -0
  303. package/src/api/base-frame.ts +4 -2
  304. package/src/api/caster.ts +17 -23
  305. package/src/api/code-converters.ts +176 -533
  306. package/src/api/config.ts +39 -56
  307. package/src/api/context.ts +7 -18
  308. package/src/api/decorators.ts +175 -46
  309. package/src/api/index.ts +2 -2
  310. package/src/api/sonamu.ts +133 -124
  311. package/src/api/validator.ts +83 -0
  312. package/src/bin/build-config.ts +7 -1
  313. package/src/bin/cli.ts +192 -110
  314. package/src/bin/loader-register.ts +38 -0
  315. package/src/database/_batch_update.ts +46 -31
  316. package/src/database/base-model.ts +390 -182
  317. package/src/database/base-model.types.ts +155 -0
  318. package/src/database/code-generator.ts +13 -32
  319. package/src/database/db.ts +36 -50
  320. package/src/database/puri-subset.test-d.ts +471 -0
  321. package/src/database/puri-subset.types.ts +195 -0
  322. package/src/database/puri-wrapper.ts +58 -67
  323. package/src/database/puri.ts +182 -126
  324. package/src/database/puri.types.ts +64 -31
  325. package/src/database/transaction-context.ts +1 -1
  326. package/src/database/upsert-builder.ts +261 -132
  327. package/src/entity/entity-manager.ts +36 -28
  328. package/src/entity/entity.ts +330 -249
  329. package/src/exceptions/error-handler.ts +3 -3
  330. package/src/exceptions/so-exceptions.ts +11 -11
  331. package/src/file-storage/driver.ts +5 -5
  332. package/src/file-storage/file-storage.ts +2 -2
  333. package/src/index.ts +18 -12
  334. package/src/migration/code-generation.ts +185 -172
  335. package/src/migration/migration-set.ts +80 -293
  336. package/src/migration/migrator.ts +182 -425
  337. package/src/migration/mysql-schema-reader.ts.txt +272 -0
  338. package/src/migration/postgresql-schema-reader.ts +310 -0
  339. package/src/migration/types.ts +6 -39
  340. package/src/naite/messaging-types.ts +51 -0
  341. package/src/naite/naite-reporter.ts +128 -0
  342. package/src/naite/naite.ts +378 -33
  343. package/src/shared/web.shared.ts.txt +20 -24
  344. package/src/stream/sse.ts +5 -5
  345. package/src/syncer/api-parser.ts +52 -69
  346. package/src/syncer/checksum.ts +25 -37
  347. package/src/syncer/code-generator.ts +58 -62
  348. package/src/syncer/entity-operations.ts +12 -15
  349. package/src/syncer/file-patterns.ts +2 -2
  350. package/src/syncer/index.ts +4 -4
  351. package/src/syncer/module-loader.ts +28 -25
  352. package/src/syncer/syncer.ts +155 -162
  353. package/src/template/entity-converter.ts +18 -27
  354. package/src/template/helpers.ts +8 -11
  355. package/src/template/implementations/entity.template.ts +6 -6
  356. package/src/template/implementations/generated.template.ts +99 -99
  357. package/src/template/implementations/generated_http.template.ts +21 -54
  358. package/src/template/implementations/generated_sso.template.ts +78 -65
  359. package/src/template/implementations/init_types.template.ts +4 -6
  360. package/src/template/implementations/model.template.ts +47 -38
  361. package/src/template/implementations/model_test.template.ts +3 -3
  362. package/src/template/implementations/service.template.ts +56 -80
  363. package/src/template/implementations/view_enums_buttonset.template.ts +2 -2
  364. package/src/template/implementations/view_enums_dropdown.template.ts +4 -4
  365. package/src/template/implementations/view_enums_select.template.ts +3 -3
  366. package/src/template/implementations/view_form.template.ts +34 -75
  367. package/src/template/implementations/view_id_all_select.template.ts +2 -2
  368. package/src/template/implementations/view_id_async_select.template.ts +9 -23
  369. package/src/template/implementations/view_list.template.ts +54 -95
  370. package/src/template/implementations/view_list_columns.template.ts +4 -10
  371. package/src/template/implementations/view_search_input.template.ts +2 -2
  372. package/src/template/index.ts +4 -2
  373. package/src/template/template-manager.ts +166 -0
  374. package/src/template/template-types.ts +16 -0
  375. package/src/template/template.ts +29 -10
  376. package/src/template/zod-converter.ts +459 -101
  377. package/src/testing/_relation-graph.ts +18 -11
  378. package/src/testing/fixture-manager.ts +468 -362
  379. package/src/types/types.ts +516 -248
  380. package/src/typings/knex.d.ts +7 -9
  381. package/src/utils/async-utils.ts +8 -12
  382. package/src/utils/console-util.ts +1 -1
  383. package/src/utils/controller.ts +3 -0
  384. package/src/utils/esm-utils.ts +8 -18
  385. package/src/utils/formatter.ts +109 -0
  386. package/src/utils/fs-utils.ts +1 -1
  387. package/src/utils/lodash-able.ts +1 -4
  388. package/src/utils/object-utils.ts +217 -0
  389. package/src/utils/path-utils.ts +3 -6
  390. package/src/utils/process-utils.ts +1 -1
  391. package/src/utils/sql-parser.ts +23 -5
  392. package/src/utils/type-utils.ts +83 -0
  393. package/src/utils/utils.ts +58 -9
  394. package/src/utils/zod-error.ts +3 -3
  395. package/dist/bin/cli-wrapper.d.ts +0 -3
  396. package/dist/bin/cli-wrapper.d.ts.map +0 -1
  397. package/dist/bin/cli-wrapper.js +0 -72
  398. package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts +0 -2
  399. package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts.map +0 -1
  400. package/dist/database/knex-plugins/knex-on-duplicate-update.js +0 -39
  401. package/dist/entity/entity-utils.d.ts +0 -61
  402. package/dist/entity/entity-utils.d.ts.map +0 -1
  403. package/dist/entity/entity-utils.js +0 -210
  404. package/src/bin/cli-wrapper.ts +0 -82
  405. package/src/database/knex-plugins/knex-on-duplicate-update.ts +0 -45
  406. package/src/entity/entity-utils.ts +0 -291
@@ -1,13 +1,17 @@
1
+ import assert from "assert";
1
2
  import chalk from "chalk";
2
- import * as _ from "lodash-es";
3
+ import { execSync } from "child_process";
4
+ import { readFileSync, writeFileSync } from "fs";
5
+ import inflection from "inflection";
6
+ import knex from "knex";
7
+ import { unique } from "radashi";
8
+ import { inspect } from "util";
3
9
  import { Sonamu } from "../api/index.js";
10
+ import { BaseModel } from "../database/base-model.js";
11
+ import { UpsertBuilder } from "../database/upsert-builder.js";
4
12
  import { EntityManager } from "../entity/entity-manager.js";
5
13
  import { isBelongsToOneRelationProp, isHasManyRelationProp, isManyToManyRelationProp, isOneToOneRelationProp, isRelationProp, isVirtualProp } from "../types/types.js";
6
- import inflection from "inflection";
7
- import { readFileSync, writeFileSync } from "fs";
8
14
  import { RelationGraph } from "./_relation-graph.js";
9
- import knex from "knex";
10
- import { BaseModel } from "../database/base-model.js";
11
15
  export class FixtureManagerClass {
12
16
  _tdb = null;
13
17
  set tdb(tdb) {
@@ -31,6 +35,11 @@ export class FixtureManagerClass {
31
35
  }
32
36
  cachedTableNames = null;
33
37
  relationGraph = new RelationGraph();
38
+ // UpsertBuilder 기반 import를 위한 상태
39
+ builder = new UpsertBuilder();
40
+ fixtureRefMap = new Map();
41
+ uuidToFixtureId = new Map();
42
+ skippedFixtures = new Map();
34
43
  init() {
35
44
  if (this._tdb !== null) {
36
45
  return;
@@ -38,122 +47,77 @@ export class FixtureManagerClass {
38
47
  if (Sonamu.dbConfig.test && Sonamu.dbConfig.production_master) {
39
48
  const tConn = Sonamu.dbConfig.test.connection;
40
49
  const pConn = Sonamu.dbConfig.production_master.connection;
41
- if (`${tConn.host ?? "localhost"}:${tConn.port ?? 3306}/${tConn.database}` === `${pConn.host ?? "localhost"}:${pConn.port ?? 3306}/${pConn.database}`) {
50
+ if (`${tConn.host ?? "localhost"}:${tConn.port ?? 5432}/${tConn.database}` === `${pConn.host ?? "localhost"}:${pConn.port ?? 5432}/${pConn.database}`) {
42
51
  throw new Error(`테스트DB와 프로덕션DB에 동일한 데이터베이스가 사용되었습니다.`);
43
52
  }
44
53
  }
45
54
  this.tdb = knex(Sonamu.dbConfig.test);
46
- this.fdb = knex(Sonamu.dbConfig.fixture_local);
47
- }
48
- async cleanAndSeed(usingTables) {
49
- const tableNames = await (async ()=>{
50
- if (usingTables) {
51
- return usingTables;
52
- }
53
- if (this.cachedTableNames) {
54
- return this.cachedTableNames;
55
- }
56
- const [tables] = await this.tdb.raw(`SHOW TABLE STATUS WHERE Engine IS NOT NULL AND Name != 'migrations'`);
57
- const tableNames = tables.map((tableInfo)=>tableInfo["Name"]);
58
- this.cachedTableNames = tableNames;
59
- return tableNames;
60
- })();
61
- // migrations 제외한 테이블 목록
62
- const tableListStr = tableNames.join(", ");
63
- // 한 번에 모든 테이블 체크섬 확인
64
- const [fdbChecksumRows] = await this.fdb.raw(`CHECKSUM TABLE ${tableListStr}`);
65
- const [tdbChecksumRows] = await this.tdb.raw(`CHECKSUM TABLE ${tableListStr}`);
66
- // 체크섬 맵 생성
67
- const fdbChecksums = new Map(fdbChecksumRows.map((row)=>[
68
- row.Table.split(".").pop(),
69
- row.Checksum
70
- ]));
71
- const tdbChecksums = new Map(tdbChecksumRows.map((row)=>[
72
- row.Table.split(".").pop(),
73
- row.Checksum
74
- ]));
75
- // 변경된 테이블들만 처리
76
- const changedTables = tableNames.filter((tableName)=>fdbChecksums.get(tableName) !== tdbChecksums.get(tableName));
77
- // 병렬로 truncate + insert 실행
78
- await this.tdb.transaction(async (trx)=>{
79
- await trx.raw(`SET FOREIGN_KEY_CHECKS = 0`);
80
- await Promise.all(changedTables.map(async (tableName)=>{
81
- await trx.raw(`SET FOREIGN_KEY_CHECKS = 0`);
82
- await trx(tableName).truncate();
83
- const rawQuery = `INSERT INTO ${Sonamu.dbConfig.test.connection.database}.${tableName}
84
- SELECT * FROM ${Sonamu.dbConfig.fixture_local.connection.database}.${tableName}`;
85
- await trx.raw(rawQuery);
86
- }));
87
- await trx.raw(`SET FOREIGN_KEY_CHECKS = 1`);
88
- });
89
- // console.timeEnd("FIXTURE-CleanAndSeed");
55
+ this.fdb = knex(Sonamu.dbConfig.fixture_remote);
90
56
  }
91
57
  async getChecksum(db, tableName) {
92
58
  const [[checksumRow]] = await db.raw(`CHECKSUM TABLE ${tableName}`);
93
59
  return checksumRow.Checksum;
94
60
  }
95
- async sync() {
96
- const frdb = knex(Sonamu.dbConfig.fixture_remote);
97
- const [tables] = await this.fdb.raw("SHOW TABLE STATUS WHERE Engine IS NOT NULL");
98
- const tableNames = tables.map((table)=>table.Name);
99
- console.log(chalk.magenta("SYNC..."));
100
- await Promise.all(tableNames.map(async (tableName)=>{
101
- if (tableName.startsWith("knex_migrations")) {
102
- return;
61
+ /**
62
+ 이제 FixtureManager.sync() checksum 비교 없이 create database template 으로 수행합니다.
63
+ */ async sync() {
64
+ const fixtureConn = Sonamu.dbConfig.fixture_remote.connection;
65
+ const testConn = Sonamu.dbConfig.test.connection;
66
+ // PostgreSQL 패스워드 환경변수 설정
67
+ const pgEnv = {
68
+ PGPASSWORD: testConn.password || ""
69
+ };
70
+ // 1. 연결 강제 종료
71
+ execSync(`psql -h ${testConn.host} -p ${testConn.port ?? 5432} -U ${testConn.user} -d postgres -c "
72
+ SELECT pg_terminate_backend(pg_stat_activity.pid)
73
+ FROM pg_stat_activity
74
+ WHERE datname = '${testConn.database}'
75
+ AND pid <> pg_backend_pid();
76
+ "`, {
77
+ stdio: "inherit",
78
+ env: {
79
+ ...process.env,
80
+ ...pgEnv
103
81
  }
104
- const remoteChecksum = await this.getChecksum(frdb, tableName);
105
- const localChecksum = await this.getChecksum(this.fdb, tableName);
106
- if (remoteChecksum !== localChecksum) {
107
- await this.fdb.transaction(async (transaction)=>{
108
- await transaction.raw(`SET FOREIGN_KEY_CHECKS = 0`);
109
- await transaction(tableName).truncate();
110
- const rows = await frdb(tableName);
111
- if (rows.length === 0) {
112
- return;
113
- }
114
- console.log(chalk.blue(tableName), rows.length);
115
- await transaction.insert(rows.map((row)=>{
116
- return Object.fromEntries(Object.entries(row).map(([key, value])=>{
117
- if (value === null) {
118
- return [
119
- key,
120
- null
121
- ];
122
- } else if (typeof value === "boolean") {
123
- return [
124
- key,
125
- value ? 1 : 0
126
- ];
127
- } else if (typeof value === "object" && !(value instanceof Date)) {
128
- return [
129
- key,
130
- JSON.stringify(value)
131
- ];
132
- } else {
133
- return [
134
- key,
135
- value
136
- ];
137
- }
138
- }));
139
- })).into(tableName);
140
- console.log("OK");
141
- await transaction.raw(`SET FOREIGN_KEY_CHECKS = 1`);
142
- });
82
+ });
83
+ execSync(`psql -h ${fixtureConn.host} -p ${fixtureConn.port ?? 5432} -U ${fixtureConn.user} -d postgres -c "
84
+ SELECT pg_terminate_backend(pg_stat_activity.pid)
85
+ FROM pg_stat_activity
86
+ WHERE datname = '${fixtureConn.database}'
87
+ AND pid <> pg_backend_pid();
88
+ "`, {
89
+ stdio: "inherit",
90
+ env: {
91
+ ...process.env,
92
+ ...pgEnv
143
93
  }
144
- }));
145
- console.log(chalk.magenta("DONE!"));
146
- await frdb.destroy();
94
+ });
95
+ // 2. DROP DATABASE (별도 실행!)
96
+ execSync(`psql -h ${testConn.host} -p ${testConn.port ?? 5432} -U ${testConn.user} -d postgres -c "DROP DATABASE IF EXISTS \\"${testConn.database}\\""`, {
97
+ stdio: "inherit",
98
+ env: {
99
+ ...process.env,
100
+ ...pgEnv
101
+ }
102
+ });
103
+ // 3. CREATE DATABASE
104
+ execSync(`psql -h ${testConn.host} -p ${testConn.port ?? 5432} -U ${testConn.user} -d postgres -c "CREATE DATABASE \\"${testConn.database}\\" TEMPLATE \\"${fixtureConn.database}\\""`, {
105
+ stdio: "inherit",
106
+ env: {
107
+ ...process.env,
108
+ ...pgEnv
109
+ }
110
+ });
147
111
  }
148
112
  visitedRecords = new Set();
149
113
  async importFixture(entityId, ids) {
150
114
  // 방문 기록 초기화 (새로운 import 작업 시작)
151
115
  this.visitedRecords.clear();
152
- const queries = _.uniq((await Promise.all(ids.map(async (id)=>{
116
+ const queries = unique((await Promise.all(ids.map(async (id)=>{
153
117
  return await this.getImportQueries(entityId, "id", id);
154
118
  }))).flat());
155
119
  const wdb = BaseModel.getDB("w");
156
- for (let query of queries){
120
+ for (const query of queries){
157
121
  const [rsh] = await wdb.raw(query);
158
122
  console.log({
159
123
  query,
@@ -201,7 +165,7 @@ export class FixtureManagerClass {
201
165
  throw new Error(`${relatedEntity.id}의 ${entity.id} 관계 프롭을 찾을 수 없습니다.`);
202
166
  }
203
167
  field = `${relatedIdColumnName}_id`;
204
- id = row["id"];
168
+ id = row.id;
205
169
  } else {
206
170
  field = "id";
207
171
  id = row[`${relation.name}_id`];
@@ -216,7 +180,7 @@ export class FixtureManagerClass {
216
180
  return this.getImportQueries(args.entityId, args.field, args.id);
217
181
  }));
218
182
  return [
219
- ..._.uniq(relQueries.reverse().flat()),
183
+ ...unique(relQueries.reverse().flat()),
220
184
  selfQuery
221
185
  ];
222
186
  }
@@ -231,7 +195,7 @@ export class FixtureManagerClass {
231
195
  }
232
196
  await BaseModel.destroy();
233
197
  }
234
- async getFixtures(sourceDBName, targetDBName, searchOptions) {
198
+ async getFixtures(sourceDBName, targetDBName, searchOptions, duplicateCheck) {
235
199
  const sourceDB = knex(Sonamu.dbConfig[sourceDBName]);
236
200
  const targetDB = knex(Sonamu.dbConfig[targetDBName]);
237
201
  const { entityId, field, value, searchType } = searchOptions;
@@ -250,7 +214,9 @@ export class FixtureManagerClass {
250
214
  const fixtures = [];
251
215
  for (const row of rows){
252
216
  const initialRecordsLength = fixtures.length;
253
- const newRecords = await this.createFixtureRecord(entity, row);
217
+ const newRecords = await this.createFixtureRecord(entity, row, {
218
+ _db: sourceDB
219
+ });
254
220
  fixtures.push(...newRecords);
255
221
  const currentFixtureRecord = fixtures.find((r)=>r.fixtureId === `${entityId}#${row.id}`);
256
222
  if (currentFixtureRecord) {
@@ -260,17 +226,19 @@ export class FixtureManagerClass {
260
226
  }
261
227
  for await (const fixture of fixtures){
262
228
  const entity = EntityManager.get(fixture.entityId);
263
- // ID를 이용하여 targetDB에 레코드가 존재하는지 확인
264
- const row = await targetDB(entity.table).where("id", fixture.id).first();
265
- if (row) {
266
- const [record] = await this.createFixtureRecord(entity, row, {
267
- singleRecord: true,
268
- _db: targetDB
269
- });
270
- fixture.target = record;
271
- continue;
229
+ // 사용자 지정 컬럼 기준 중복 확인 → target
230
+ const customColumns = duplicateCheck?.columns?.[fixture.entityId];
231
+ if (customColumns && customColumns.length > 0) {
232
+ const customDuplicateRow = await this.checkDuplicateByColumns(targetDB, entity, fixture, customColumns);
233
+ if (customDuplicateRow) {
234
+ const [record] = await this.createFixtureRecord(entity, customDuplicateRow, {
235
+ singleRecord: true,
236
+ _db: targetDB
237
+ });
238
+ fixture.target = record;
239
+ }
272
240
  }
273
- // ID를 이용하여 targetDB에서 조회되지 않는 경우, unique 제약을 위반하는지 확인
241
+ // Unique index 기준 중복 확인 fixture.unique
274
242
  const uniqueRow = await this.checkUniqueViolation(targetDB, entity, fixture);
275
243
  if (uniqueRow) {
276
244
  const [record] = await this.createFixtureRecord(entity, uniqueRow, {
@@ -282,7 +250,7 @@ export class FixtureManagerClass {
282
250
  }
283
251
  await targetDB.destroy();
284
252
  await sourceDB.destroy();
285
- return _.uniqBy(fixtures, (f)=>f.fixtureId);
253
+ return unique(fixtures, (f)=>f.fixtureId);
286
254
  }
287
255
  async createFixtureRecord(entity, row, options) {
288
256
  const records = [];
@@ -348,174 +316,308 @@ export class FixtureManagerClass {
348
316
  await create(entity, row);
349
317
  return records;
350
318
  }
351
- async insertFixtures(dbName, _fixtures) {
352
- const fixtures = _.uniqBy(_fixtures, (f)=>f.fixtureId);
353
- this.relationGraph.buildGraph(fixtures);
354
- const insertionOrder = this.relationGraph.getInsertionOrder();
319
+ /**
320
+ * 1. RelationGraph로 fixture 단위 삽입 순서 계산 (self-reference 포함)
321
+ * 2. 순서대로 UpsertBuilder에 등록 (UBRef로 참조 관계 표현)
322
+ * 3. 테이블별 upsert 실행 (ID는 DB가 자동 할당)
323
+ */ async insertFixtures(dbName, _fixtures) {
324
+ const fixtures = unique(_fixtures, (f)=>f.fixtureId);
325
+ // 초기화
326
+ this.builder = new UpsertBuilder();
327
+ this.fixtureRefMap = new Map();
328
+ this.uuidToFixtureId = new Map();
329
+ this.skippedFixtures = new Map();
355
330
  const db = knex(Sonamu.dbConfig[dbName]);
356
- await db.transaction(async (trx)=>{
357
- await trx.raw(`SET FOREIGN_KEY_CHECKS = 0`);
331
+ const results = [];
332
+ try {
333
+ // 1. RelationGraph로 fixture 단위 삽입 순서 계산
334
+ this.relationGraph.buildGraph(fixtures);
335
+ const insertionOrder = this.relationGraph.getInsertionOrder();
336
+ // 2. 순서대로 UpsertBuilder에 등록 (override 체크)
358
337
  for (const fixtureId of insertionOrder){
359
338
  const fixture = fixtures.find((f)=>f.fixtureId === fixtureId);
360
- const result = await this.insertFixture(trx, fixture);
361
- if (result.id !== fixture.id) {
362
- // ID가 변경된 경우, 다른 fixture에서 참조하는 경우가 찾아서 수정
363
- console.log(chalk.yellow(`Unique constraint violation: ${fixture.entityId}#${fixture.id} -> ${fixture.entityId}#${result.id}`));
364
- fixtures.forEach((f)=>{
365
- Object.values(f.columns).forEach((column)=>{
366
- if (column.prop.type === "relation" && column.prop.with === result.entityId && column.value === fixture.id) {
367
- column.value = result.id;
368
- }
369
- });
339
+ if (!fixture) continue;
340
+ const hasTarget = !!fixture.target;
341
+ const hasUnique = !!fixture.unique;
342
+ const hasDuplicate = hasTarget || hasUnique;
343
+ // 중복이 있고 override=false인 경우: 스킵
344
+ if (hasDuplicate && !fixture.override) {
345
+ // 기존 레코드 ID 저장 (unique 우선, 없으면 target)
346
+ const existingId = fixture.unique?.id ?? fixture.target?.id;
347
+ assert(existingId);
348
+ this.skippedFixtures.set(fixtureId, {
349
+ entityId: fixture.entityId,
350
+ existingId
370
351
  });
371
- fixture.id = result.id;
352
+ console.log(chalk.yellow(`Skipped ${fixture.entityId}#${fixture.id} (existing: #${existingId}, override: false)`));
353
+ continue;
372
354
  }
355
+ this.registerFixture(fixture);
356
+ console.log(chalk.blue(`Registered ${fixture.entityId}#${fixture.id}${fixture.override ? ` (override existing: #${fixture.target?.id})` : ""}`));
373
357
  }
374
- for (const fixtureId of insertionOrder){
375
- const fixture = fixtures.find((f)=>f.fixtureId === fixtureId);
376
- await this.handleManyToManyRelations(trx, fixture, fixtures);
377
- }
378
- await trx.raw(`SET FOREIGN_KEY_CHECKS = 1`);
379
- });
380
- const records = [];
381
- for await (const r of fixtures){
382
- const entity = EntityManager.get(r.entityId);
383
- const record = await db(entity.table).where("id", r.id).first();
384
- records.push({
385
- entityId: r.entityId,
386
- data: record
358
+ // 3. 테이블별 upsert 실행
359
+ const tableOrder = this.getTableOrder(fixtures);
360
+ await db.transaction(async (trx)=>{
361
+ const insertedIdsByTable = new Map();
362
+ for (const tableName of tableOrder){
363
+ if (!this.builder.hasTable(tableName)) continue;
364
+ // upsert 실행 전 uuid 목록 저장
365
+ const table = this.builder.getTable(tableName);
366
+ const uuids = table.rows.map((row)=>row.uuid);
367
+ console.log(chalk.blue(`Upserting ${tableName} with ${uuids.length} rows`));
368
+ await this.builder.upsert(trx, tableName);
369
+ // upsert된 row들의 uuid -> id 매핑 구축
370
+ if (uuids.length > 0) {
371
+ const uuidToId = new Map();
372
+ const rows = await trx(tableName).select("uuid", "id").whereIn("uuid", uuids);
373
+ for (const row of rows){
374
+ uuidToId.set(row.uuid, row.id);
375
+ }
376
+ insertedIdsByTable.set(tableName, uuidToId);
377
+ }
378
+ }
379
+ // 4. ManyToMany 관계 처리
380
+ await this.processManyToManyRelations(trx, fixtures, insertedIdsByTable);
381
+ // 5. 결과 수집
382
+ for (const fixture of fixtures){
383
+ const entity = EntityManager.get(fixture.entityId);
384
+ // 스킵된 fixture는 기존 레코드 정보로 결과 추가
385
+ const skipped = this.skippedFixtures.get(fixture.fixtureId);
386
+ if (skipped) {
387
+ results.push({
388
+ entityId: fixture.entityId,
389
+ data: await trx(entity.table).where("id", skipped.existingId).first()
390
+ });
391
+ continue;
392
+ }
393
+ const ref = this.fixtureRefMap.get(fixture.fixtureId);
394
+ if (ref) {
395
+ const uuidToId = insertedIdsByTable.get(entity.table);
396
+ const insertedId = uuidToId?.get(ref.uuid);
397
+ if (insertedId !== undefined) {
398
+ results.push({
399
+ entityId: fixture.entityId,
400
+ data: await trx(entity.table).where("id", insertedId).first()
401
+ });
402
+ console.log(chalk.green(`Inserted into ${entity.table}: #${fixture.id} -> #${insertedId}`));
403
+ }
404
+ }
405
+ }
387
406
  });
407
+ } finally{
408
+ await db.destroy();
388
409
  }
389
- await db.destroy();
390
- return _.uniqBy(records, (r)=>`${r.entityId}#${r.data.id}`);
410
+ return unique(results, (r)=>`${r.entityId}#${r.data.id}`);
391
411
  }
392
- prepareInsertData(fixture) {
393
- const insertData = {};
412
+ /**
413
+ * FixtureRecord를 UpsertBuilder에 등록
414
+ */ registerFixture(fixture) {
415
+ const entity = EntityManager.get(fixture.entityId);
416
+ const row = {};
417
+ // Override 모드 판단: target 또는 unique가 있고 override=true인 경우
418
+ const existingRecord = fixture.target ?? fixture.unique;
419
+ const isOverrideMode = fixture.override && existingRecord;
394
420
  for (const [propName, column] of Object.entries(fixture.columns)){
395
- if (isVirtualProp(column.prop)) {
421
+ const prop = column.prop;
422
+ if (isVirtualProp(prop)) {
396
423
  continue;
397
424
  }
398
- const prop = column.prop;
399
- if (!isRelationProp(prop)) {
400
- if (prop.type === "json") {
401
- insertData[propName] = JSON.stringify(column.value);
402
- } else if (prop.type === "timestamp" || prop.type === "datetime") {
403
- insertData[propName] = new Date(column.value);
404
- } else {
405
- insertData[propName] = column.value;
425
+ // id/uuid 처리: Override 모드일 때만 기존 값 사용
426
+ if (propName === "id" || propName === "uuid") {
427
+ if (isOverrideMode && existingRecord) {
428
+ // Override: 기존 레코드의 값 사용 → UPDATE
429
+ row[propName] = existingRecord.columns[propName]?.value;
430
+ }
431
+ continue;
432
+ }
433
+ if (isRelationProp(prop)) {
434
+ if (isBelongsToOneRelationProp(prop) || isOneToOneRelationProp(prop) && prop.hasJoinColumn) {
435
+ const relatedId = column.value;
436
+ if (relatedId !== null && relatedId !== undefined) {
437
+ const relatedFixtureId = `${prop.with}#${relatedId}`;
438
+ // 먼저 skip된 fixture인지 확인
439
+ const skippedExistingId = this.skippedFixtures.get(relatedFixtureId)?.existingId;
440
+ if (skippedExistingId !== undefined) {
441
+ // skip된 fixture → target DB의 기존 레코드 id 사용
442
+ row[`${propName}_id`] = skippedExistingId;
443
+ } else {
444
+ const relatedRef = this.fixtureRefMap.get(relatedFixtureId);
445
+ if (relatedRef) {
446
+ // 이미 등록된 fixture 참조 → UBRef 사용
447
+ row[`${propName}_id`] = relatedRef;
448
+ } else {
449
+ // fixtures에 포함되지 않은 레코드 → ID 그대로 사용
450
+ row[`${propName}_id`] = relatedId;
451
+ }
452
+ }
453
+ } else {
454
+ row[`${propName}_id`] = null;
455
+ }
406
456
  }
407
- } else if (isBelongsToOneRelationProp(prop) || isOneToOneRelationProp(prop) && prop.hasJoinColumn) {
408
- insertData[`${propName}_id`] = column.value;
457
+ // HasMany, ManyToMany는 별도 처리
458
+ } else {
459
+ // 일반 컬럼
460
+ row[propName] = this.convertColumnValue(prop, column.value);
409
461
  }
410
462
  }
411
- return insertData;
463
+ console.log(chalk.blue(`Registering ${entity.table} - ${inspect(row, false, null, true)}`));
464
+ const ref = this.builder.register(entity.table, row);
465
+ this.fixtureRefMap.set(fixture.fixtureId, ref);
466
+ this.uuidToFixtureId.set(ref.uuid, fixture.fixtureId);
467
+ return ref;
412
468
  }
413
- async insertFixture(db, fixture) {
414
- const insertData = this.prepareInsertData(fixture);
415
- const entity = EntityManager.get(fixture.entityId);
416
- try {
417
- const uniqueFound = await this.checkUniqueViolation(db, entity, fixture);
418
- if (uniqueFound) {
419
- return {
420
- entityId: fixture.entityId,
421
- id: uniqueFound.id
422
- };
423
- }
424
- const found = await db(entity.table).where("id", fixture.id).first();
425
- if (found && !fixture.override) {
426
- return {
427
- entityId: fixture.entityId,
428
- id: found.id
429
- };
469
+ /**
470
+ * 컬럼 변환
471
+ */ convertColumnValue(prop, value) {
472
+ if (value === null || value === undefined) {
473
+ return null;
474
+ }
475
+ switch(prop.type){
476
+ case "json":
477
+ // UpsertBuilder.register에서 JSON.stringify 처리하므로 object 그대로 전달
478
+ return value;
479
+ case "date":
480
+ if (typeof value === "string" || typeof value === "number") {
481
+ return new Date(value);
482
+ }
483
+ return value;
484
+ default:
485
+ return value;
486
+ }
487
+ }
488
+ /**
489
+ * 테이블 순서 추출 (fixtures에 포함된 테이블만)
490
+ */ getTableOrder(fixtures) {
491
+ const tables = [];
492
+ const seen = new Set();
493
+ for (const fixture of fixtures){
494
+ const entity = EntityManager.get(fixture.entityId);
495
+ if (!seen.has(entity.table)) {
496
+ seen.add(entity.table);
497
+ tables.push(entity.table);
430
498
  }
431
- const q = db.insert(insertData).into(entity.table);
432
- await q.onDuplicateUpdate.apply(q, Object.keys(insertData));
433
- console.log(chalk.green(`Inserted into ${entity.table}: #${fixture.id}`));
434
- return {
435
- entityId: fixture.entityId,
436
- id: fixture.id
437
- };
438
- } catch (err) {
439
- console.log(err);
440
- throw err;
441
499
  }
500
+ return tables;
442
501
  }
443
- async handleManyToManyRelations(db, fixture, fixtures) {
444
- for (const [, column] of Object.entries(fixture.columns)){
445
- const prop = column.prop;
446
- if (isManyToManyRelationProp(prop)) {
447
- const joinTable = prop.joinTable;
448
- const relatedIds = column.value;
449
- for (const relatedId of relatedIds){
450
- if (!fixtures.find((f)=>f.fixtureId === `${prop.with}#${relatedId}`)) {
451
- continue;
452
- }
453
- const entity = EntityManager.get(fixture.entityId);
502
+ async processManyToManyRelations(trx, fixtures, insertedIdsByTable) {
503
+ for (const fixture of fixtures){
504
+ const entity = EntityManager.get(fixture.entityId);
505
+ const sourceRef = this.fixtureRefMap.get(fixture.fixtureId);
506
+ if (!sourceRef) continue;
507
+ const sourceUuidToId = insertedIdsByTable.get(entity.table);
508
+ const sourceId = sourceUuidToId?.get(sourceRef.uuid);
509
+ if (sourceId === undefined) continue;
510
+ for (const [, column] of Object.entries(fixture.columns)){
511
+ const prop = column.prop;
512
+ if (isManyToManyRelationProp(prop) && Array.isArray(column.value)) {
513
+ // 선택되지 않은 ManyToMany 관계는 저장하지 않음
514
+ const targetTable = EntityManager.get(prop.with);
515
+ if (this.builder.hasTable(targetTable.table) === false) continue;
516
+ const relatedIds = column.value;
517
+ if (relatedIds.length === 0) continue;
518
+ const joinTable = prop.joinTable;
454
519
  const relatedEntity = EntityManager.get(prop.with);
455
- if (!entity || !relatedEntity) {
456
- throw new Error(`Entity not found: ${fixture.entityId}, ${prop.with}`);
457
- }
458
- const [found] = await db(joinTable).where({
459
- [`${inflection.singularize(entity.table)}_id`]: fixture.id,
460
- [`${inflection.singularize(relatedEntity.table)}_id`]: relatedId
461
- }).limit(1);
462
- if (found) {
463
- continue;
520
+ const sourceColumn = `${inflection.singularize(entity.table)}_id`;
521
+ const targetColumn = `${inflection.singularize(relatedEntity.table)}_id`;
522
+ for (const relatedId of relatedIds){
523
+ const relatedFixtureId = `${prop.with}#${relatedId}`;
524
+ const relatedRef = this.fixtureRefMap.get(relatedFixtureId);
525
+ let targetId;
526
+ if (relatedRef) {
527
+ const relatedUuidToId = insertedIdsByTable.get(relatedEntity.table);
528
+ const resolvedId = relatedUuidToId?.get(relatedRef.uuid);
529
+ if (resolvedId === undefined) {
530
+ console.warn(`Related fixture ${relatedFixtureId} not found in insertedIds, skipping`);
531
+ continue;
532
+ }
533
+ targetId = resolvedId;
534
+ } else {
535
+ targetId = relatedId;
536
+ }
537
+ // JoinTable에 삽입
538
+ const [found] = await trx(joinTable).where({
539
+ [sourceColumn]: sourceId,
540
+ [targetColumn]: targetId
541
+ }).limit(1);
542
+ if (!found) {
543
+ await trx(joinTable).insert({
544
+ [sourceColumn]: sourceId,
545
+ [targetColumn]: targetId
546
+ });
547
+ console.log(chalk.green(`Inserted into ${joinTable}: ${entity.table}(${sourceId}) - ${relatedEntity.table}(${targetId})`));
548
+ }
464
549
  }
465
- const newIds = await db(joinTable).insert({
466
- [`${inflection.singularize(entity.table)}_id`]: fixture.id,
467
- [`${inflection.singularize(relatedEntity.table)}_id`]: relatedId
468
- });
469
- console.log(chalk.green(`Inserted into ${joinTable}: ${entity.table}(${fixture.id}) - ${relatedEntity.table}(${relatedId}) ID: ${newIds}`));
470
550
  }
471
551
  }
472
552
  }
473
553
  }
474
- async addFixtureLoader(code) {
475
- const path = Sonamu.apiRootPath + "/src/testing/fixture.ts";
476
- let content = readFileSync(path).toString();
477
- const fixtureLoaderStart = content.indexOf("const fixtureLoader = {");
478
- const fixtureLoaderEnd = content.indexOf("};", fixtureLoaderStart);
479
- if (fixtureLoaderStart !== -1 && fixtureLoaderEnd !== -1) {
480
- const newContent = content.slice(0, fixtureLoaderEnd) + " " + code + "\n" + content.slice(fixtureLoaderEnd);
481
- writeFileSync(path, newContent);
482
- } else {
483
- throw new Error("Failed to find fixtureLoader in fixture.ts");
484
- }
485
- }
486
- // 해당 픽스쳐의 값으로 유니크 제약에 위배되는 레코드가 있는지 확인
487
554
  async checkUniqueViolation(db, entity, fixture) {
488
- const _uniqueIndexes = entity.indexes.filter((i)=>i.type === "unique");
489
- // ManyToMany 관계 테이블의 유니크 제약은 제외
555
+ const _uniqueIndexes = entity.indexes?.filter((i)=>i.type === "unique") ?? [];
490
556
  const uniqueIndexes = _uniqueIndexes.filter((index)=>index.columns.every((column)=>!column.startsWith(`${entity.table}__`)));
491
557
  if (uniqueIndexes.length === 0) {
492
558
  return null;
493
559
  }
494
560
  let uniqueQuery = db(entity.table);
561
+ let hasCondition = false;
495
562
  for (const index of uniqueIndexes){
496
563
  // 컬럼 중 하나라도 null이면 유니크 제약을 위반하지 않기 때문에 해당 인덱스는 무시
497
564
  const containsNull = index.columns.some((column)=>{
498
- const field = column.split("_id")[0];
499
- return fixture.columns[field].value === null;
565
+ const field = column.replace(/_id$/, "");
566
+ return fixture.columns[field]?.value === null;
500
567
  });
501
568
  if (containsNull) {
502
569
  continue;
503
570
  }
504
571
  uniqueQuery = uniqueQuery.orWhere((qb)=>{
505
572
  for (const column of index.columns){
506
- const field = column.split("_id")[0];
507
- if (Array.isArray(fixture.columns[field].value)) {
573
+ const field = column.replace(/_id$/, "");
574
+ if (Array.isArray(fixture.columns[field]?.value)) {
508
575
  qb.whereIn(column, fixture.columns[field].value);
509
576
  } else {
510
- qb.andWhere(column, fixture.columns[field].value);
577
+ qb.andWhere(column, fixture.columns[field]?.value);
511
578
  }
512
579
  }
513
580
  });
581
+ hasCondition = true;
582
+ }
583
+ if (!hasCondition) {
584
+ return null;
514
585
  }
515
586
  const [uniqueFound] = await uniqueQuery;
516
587
  return uniqueFound;
517
588
  }
589
+ async checkDuplicateByColumns(db, entity, fixture, columns) {
590
+ if (columns.length === 0) {
591
+ return null;
592
+ }
593
+ const whereClause = {};
594
+ for (const column of columns){
595
+ // relation 필드인 경우 _id 붙이기
596
+ const prop = entity.props.find((p)=>p.name === column);
597
+ const dbColumn = prop && isRelationProp(prop) ? `${column}_id` : column;
598
+ const value = fixture.columns[column]?.value;
599
+ // null 값이 포함된 경우 중복 확인 스킵
600
+ if (value === null || value === undefined) {
601
+ return null;
602
+ }
603
+ whereClause[dbColumn] = value;
604
+ }
605
+ const [found] = await db(entity.table).where(whereClause).limit(1);
606
+ return found;
607
+ }
608
+ async addFixtureLoader(code) {
609
+ const path = `${Sonamu.apiRootPath}/src/testing/fixture.ts`;
610
+ const content = readFileSync(path).toString();
611
+ const fixtureLoaderStart = content.indexOf("const fixtureLoader = {");
612
+ const fixtureLoaderEnd = content.indexOf("};", fixtureLoaderStart);
613
+ if (fixtureLoaderStart !== -1 && fixtureLoaderEnd !== -1) {
614
+ const newContent = `${content.slice(0, fixtureLoaderEnd)} ${code}\n${content.slice(fixtureLoaderEnd)}`;
615
+ writeFileSync(path, newContent);
616
+ } else {
617
+ throw new Error("Failed to find fixtureLoader in fixture.ts");
618
+ }
619
+ }
518
620
  }
519
621
  export const FixtureManager = new FixtureManagerClass();
520
622
 
521
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0aW5nL2ZpeHR1cmUtbWFuYWdlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgY2hhbGsgZnJvbSBcImNoYWxrXCI7XG5pbXBvcnQgKiBhcyBfIGZyb20gXCJsb2Rhc2gtZXNcIjtcbmltcG9ydCB7IFNvbmFtdSB9IGZyb20gXCIuLi9hcGlcIjtcbmltcG9ydCB7IEVudGl0eU1hbmFnZXIgfSBmcm9tIFwiLi4vZW50aXR5L2VudGl0eS1tYW5hZ2VyXCI7XG5pbXBvcnQge1xuICBFbnRpdHlQcm9wLFxuICBGaXh0dXJlSW1wb3J0UmVzdWx0LFxuICBGaXh0dXJlUmVjb3JkLFxuICBGaXh0dXJlU2VhcmNoT3B0aW9ucyxcbiAgTWFueVRvTWFueVJlbGF0aW9uUHJvcCxcbiAgaXNCZWxvbmdzVG9PbmVSZWxhdGlvblByb3AsXG4gIGlzSGFzTWFueVJlbGF0aW9uUHJvcCxcbiAgaXNNYW55VG9NYW55UmVsYXRpb25Qcm9wLFxuICBpc09uZVRvT25lUmVsYXRpb25Qcm9wLFxuICBpc1JlbGF0aW9uUHJvcCxcbiAgaXNWaXJ0dWFsUHJvcCxcbn0gZnJvbSBcIi4uL3R5cGVzL3R5cGVzXCI7XG5pbXBvcnQgeyBFbnRpdHkgfSBmcm9tIFwiLi4vZW50aXR5L2VudGl0eVwiO1xuaW1wb3J0IGluZmxlY3Rpb24gZnJvbSBcImluZmxlY3Rpb25cIjtcbmltcG9ydCB7IHJlYWRGaWxlU3luYywgd3JpdGVGaWxlU3luYyB9IGZyb20gXCJmc1wiO1xuaW1wb3J0IHsgUmVsYXRpb25HcmFwaCB9IGZyb20gXCIuL19yZWxhdGlvbi1ncmFwaFwiO1xuaW1wb3J0IGtuZXgsIHsgS25leCB9IGZyb20gXCJrbmV4XCI7XG5pbXBvcnQgeyBCYXNlTW9kZWwgfSBmcm9tIFwiLi4vZGF0YWJhc2UvYmFzZS1tb2RlbFwiO1xuaW1wb3J0IHsgU29uYW11REJDb25maWcgfSBmcm9tIFwiLi4vZGF0YWJhc2UvZGJcIjtcblxuZXhwb3J0IGNsYXNzIEZpeHR1cmVNYW5hZ2VyQ2xhc3Mge1xuICBwcml2YXRlIF90ZGI6IEtuZXggfCBudWxsID0gbnVsbDtcbiAgc2V0IHRkYih0ZGI6IEtuZXgpIHtcbiAgICB0aGlzLl90ZGIgPSB0ZGI7XG4gIH1cbiAgZ2V0IHRkYigpOiBLbmV4IHtcbiAgICBpZiAodGhpcy5fdGRiID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJGaXh0dXJlTWFuYWdlciBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWRcIik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl90ZGI7XG4gIH1cblxuICBwcml2YXRlIF9mZGI6IEtuZXggfCBudWxsID0gbnVsbDtcbiAgc2V0IGZkYihmZGI6IEtuZXgpIHtcbiAgICB0aGlzLl9mZGIgPSBmZGI7XG4gIH1cbiAgZ2V0IGZkYigpOiBLbmV4IHtcbiAgICBpZiAodGhpcy5fZmRiID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJGaXh0dXJlTWFuYWdlciBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWRcIik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9mZGI7XG4gIH1cbiAgY2FjaGVkVGFibGVOYW1lczogc3RyaW5nW10gfCBudWxsID0gbnVsbDtcblxuICBwcml2YXRlIHJlbGF0aW9uR3JhcGggPSBuZXcgUmVsYXRpb25HcmFwaCgpO1xuXG4gIGluaXQoKSB7XG4gICAgaWYgKHRoaXMuX3RkYiAhPT0gbnVsbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoU29uYW11LmRiQ29uZmlnLnRlc3QgJiYgU29uYW11LmRiQ29uZmlnLnByb2R1Y3Rpb25fbWFzdGVyKSB7XG4gICAgICBjb25zdCB0Q29ubiA9IFNvbmFtdS5kYkNvbmZpZy50ZXN0LmNvbm5lY3Rpb24gYXMgS25leC5Db25uZWN0aW9uQ29uZmlnICYge1xuICAgICAgICBwb3J0PzogbnVtYmVyO1xuICAgICAgfTtcbiAgICAgIGNvbnN0IHBDb25uID0gU29uYW11LmRiQ29uZmlnLnByb2R1Y3Rpb25fbWFzdGVyXG4gICAgICAgIC5jb25uZWN0aW9uIGFzIEtuZXguQ29ubmVjdGlvbkNvbmZpZyAmIHsgcG9ydD86IG51bWJlciB9O1xuICAgICAgaWYgKFxuICAgICAgICBgJHt0Q29ubi5ob3N0ID8/IFwibG9jYWxob3N0XCJ9OiR7dENvbm4ucG9ydCA/PyAzMzA2fS8ke1xuICAgICAgICAgIHRDb25uLmRhdGFiYXNlXG4gICAgICAgIH1gID09PVxuICAgICAgICBgJHtwQ29ubi5ob3N0ID8/IFwibG9jYWxob3N0XCJ9OiR7cENvbm4ucG9ydCA/PyAzMzA2fS8ke3BDb25uLmRhdGFiYXNlfWBcbiAgICAgICkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYO2FjOyKpO2KuERC7JmAIO2UhOuhnOuNleyFmERC7JeQIOuPmeydvO2VnCDrjbDsnbTthLDrsqDsnbTsiqTqsIAg7IKs7Jqp65CY7JeI7Iq164uI64ukLmBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLnRkYiA9IGtuZXgoU29uYW11LmRiQ29uZmlnLnRlc3QpO1xuICAgIHRoaXMuZmRiID0ga25leChTb25hbXUuZGJDb25maWcuZml4dHVyZV9sb2NhbCk7XG4gIH1cblxuICBhc3luYyBjbGVhbkFuZFNlZWQodXNpbmdUYWJsZXM/OiBzdHJpbmdbXSkge1xuICAgIGNvbnN0IHRhYmxlTmFtZXM6IHN0cmluZ1tdID0gYXdhaXQgKGFzeW5jICgpID0+IHtcbiAgICAgIGlmICh1c2luZ1RhYmxlcykge1xuICAgICAgICByZXR1cm4gdXNpbmdUYWJsZXM7XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5jYWNoZWRUYWJsZU5hbWVzKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhY2hlZFRhYmxlTmFtZXM7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IFt0YWJsZXNdID0gYXdhaXQgdGhpcy50ZGIucmF3KFxuICAgICAgICBgU0hPVyBUQUJMRSBTVEFUVVMgV0hFUkUgRW5naW5lIElTIE5PVCBOVUxMIEFORCBOYW1lICE9ICdtaWdyYXRpb25zJ2BcbiAgICAgICk7XG4gICAgICBjb25zdCB0YWJsZU5hbWVzID0gdGFibGVzLm1hcChcbiAgICAgICAgKHRhYmxlSW5mbzogeyBOYW1lOiBzdHJpbmcgfSkgPT4gdGFibGVJbmZvW1wiTmFtZVwiXVxuICAgICAgKTtcbiAgICAgIHRoaXMuY2FjaGVkVGFibGVOYW1lcyA9IHRhYmxlTmFtZXM7XG4gICAgICByZXR1cm4gdGFibGVOYW1lcztcbiAgICB9KSgpO1xuXG4gICAgLy8gbWlncmF0aW9ucyDsoJzsmbjtlZwg7YWM7J2067iUIOuqqeuhnVxuICAgIGNvbnN0IHRhYmxlTGlzdFN0ciA9IHRhYmxlTmFtZXMuam9pbihcIiwgXCIpO1xuXG4gICAgLy8g7ZWcIOuyiOyXkCDrqqjrk6Ag7YWM7J2067iUIOyytO2BrOyErCDtmZXsnbhcbiAgICBjb25zdCBbZmRiQ2hlY2tzdW1Sb3dzXSA9IGF3YWl0IHRoaXMuZmRiLnJhdzxcbiAgICAgIFt7IFRhYmxlOiBzdHJpbmc7IENoZWNrc3VtOiBudW1iZXIgfVtdXVxuICAgID4oYENIRUNLU1VNIFRBQkxFICR7dGFibGVMaXN0U3RyfWApO1xuICAgIGNvbnN0IFt0ZGJDaGVja3N1bVJvd3NdID0gYXdhaXQgdGhpcy50ZGIucmF3PFxuICAgICAgW3sgVGFibGU6IHN0cmluZzsgQ2hlY2tzdW06IG51bWJlciB9W11dXG4gICAgPihgQ0hFQ0tTVU0gVEFCTEUgJHt0YWJsZUxpc3RTdHJ9YCk7XG5cbiAgICAvLyDssrTtgazshKwg66e1IOyDneyEsVxuICAgIGNvbnN0IGZkYkNoZWNrc3VtcyA9IG5ldyBNYXAoXG4gICAgICBmZGJDaGVja3N1bVJvd3MubWFwKChyb3cpID0+IFtyb3cuVGFibGUuc3BsaXQoXCIuXCIpLnBvcCgpISwgcm93LkNoZWNrc3VtXSlcbiAgICApO1xuICAgIGNvbnN0IHRkYkNoZWNrc3VtcyA9IG5ldyBNYXAoXG4gICAgICB0ZGJDaGVja3N1bVJvd3MubWFwKChyb3cpID0+IFtyb3cuVGFibGUuc3BsaXQoXCIuXCIpLnBvcCgpISwgcm93LkNoZWNrc3VtXSlcbiAgICApO1xuXG4gICAgLy8g67OA6rK965CcIO2FjOydtOu4lOuTpOunjCDsspjrpqxcbiAgICBjb25zdCBjaGFuZ2VkVGFibGVzID0gdGFibGVOYW1lcy5maWx0ZXIoXG4gICAgICAodGFibGVOYW1lKSA9PiBmZGJDaGVja3N1bXMuZ2V0KHRhYmxlTmFtZSkgIT09IHRkYkNoZWNrc3Vtcy5nZXQodGFibGVOYW1lKVxuICAgICk7XG5cbiAgICAvLyDrs5HroKzroZwgdHJ1bmNhdGUgKyBpbnNlcnQg7Iuk7ZaJXG4gICAgYXdhaXQgdGhpcy50ZGIudHJhbnNhY3Rpb24oYXN5bmMgKHRyeCkgPT4ge1xuICAgICAgYXdhaXQgdHJ4LnJhdyhgU0VUIEZPUkVJR05fS0VZX0NIRUNLUyA9IDBgKTtcblxuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIGNoYW5nZWRUYWJsZXMubWFwKGFzeW5jICh0YWJsZU5hbWUpID0+IHtcbiAgICAgICAgICBhd2FpdCB0cngucmF3KGBTRVQgRk9SRUlHTl9LRVlfQ0hFQ0tTID0gMGApO1xuICAgICAgICAgIGF3YWl0IHRyeCh0YWJsZU5hbWUpLnRydW5jYXRlKCk7XG4gICAgICAgICAgY29uc3QgcmF3UXVlcnkgPSBgSU5TRVJUIElOVE8gJHtcbiAgICAgICAgICAgIChTb25hbXUuZGJDb25maWcudGVzdC5jb25uZWN0aW9uIGFzIEtuZXguQ29ubmVjdGlvbkNvbmZpZykuZGF0YWJhc2VcbiAgICAgICAgICB9LiR7dGFibGVOYW1lfVxuICAgICAgICBTRUxFQ1QgKiBGUk9NICR7XG4gICAgICAgICAgKFNvbmFtdS5kYkNvbmZpZy5maXh0dXJlX2xvY2FsLmNvbm5lY3Rpb24gYXMgS25leC5Db25uZWN0aW9uQ29uZmlnKVxuICAgICAgICAgICAgLmRhdGFiYXNlXG4gICAgICAgIH0uJHt0YWJsZU5hbWV9YDtcbiAgICAgICAgICBhd2FpdCB0cngucmF3KHJhd1F1ZXJ5KTtcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgICBhd2FpdCB0cngucmF3KGBTRVQgRk9SRUlHTl9LRVlfQ0hFQ0tTID0gMWApO1xuICAgIH0pO1xuXG4gICAgLy8gY29uc29sZS50aW1lRW5kKFwiRklYVFVSRS1DbGVhbkFuZFNlZWRcIik7XG4gIH1cblxuICBhc3luYyBnZXRDaGVja3N1bShkYjogS25leCwgdGFibGVOYW1lOiBzdHJpbmcpIHtcbiAgICBjb25zdCBbW2NoZWNrc3VtUm93XV0gPSBhd2FpdCBkYi5yYXcoYENIRUNLU1VNIFRBQkxFICR7dGFibGVOYW1lfWApO1xuICAgIHJldHVybiBjaGVja3N1bVJvdy5DaGVja3N1bTtcbiAgfVxuXG4gIGFzeW5jIHN5bmMoKSB7XG4gICAgY29uc3QgZnJkYiA9IGtuZXgoU29uYW11LmRiQ29uZmlnLmZpeHR1cmVfcmVtb3RlKTtcblxuICAgIGNvbnN0IFt0YWJsZXNdID0gYXdhaXQgdGhpcy5mZGIucmF3KFxuICAgICAgXCJTSE9XIFRBQkxFIFNUQVRVUyBXSEVSRSBFbmdpbmUgSVMgTk9UIE5VTExcIlxuICAgICk7XG4gICAgY29uc3QgdGFibGVOYW1lczogc3RyaW5nW10gPSB0YWJsZXMubWFwKFxuICAgICAgKHRhYmxlOiBhbnkpID0+IHRhYmxlLk5hbWUgYXMgc3RyaW5nXG4gICAgKTtcblxuICAgIGNvbnNvbGUubG9nKGNoYWxrLm1hZ2VudGEoXCJTWU5DLi4uXCIpKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHRhYmxlTmFtZXMubWFwKGFzeW5jICh0YWJsZU5hbWUpID0+IHtcbiAgICAgICAgaWYgKHRhYmxlTmFtZS5zdGFydHNXaXRoKFwia25leF9taWdyYXRpb25zXCIpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVtb3RlQ2hlY2tzdW0gPSBhd2FpdCB0aGlzLmdldENoZWNrc3VtKGZyZGIsIHRhYmxlTmFtZSk7XG4gICAgICAgIGNvbnN0IGxvY2FsQ2hlY2tzdW0gPSBhd2FpdCB0aGlzLmdldENoZWNrc3VtKHRoaXMuZmRiLCB0YWJsZU5hbWUpO1xuXG4gICAgICAgIGlmIChyZW1vdGVDaGVja3N1bSAhPT0gbG9jYWxDaGVja3N1bSkge1xuICAgICAgICAgIGF3YWl0IHRoaXMuZmRiLnRyYW5zYWN0aW9uKGFzeW5jICh0cmFuc2FjdGlvbikgPT4ge1xuICAgICAgICAgICAgYXdhaXQgdHJhbnNhY3Rpb24ucmF3KGBTRVQgRk9SRUlHTl9LRVlfQ0hFQ0tTID0gMGApO1xuICAgICAgICAgICAgYXdhaXQgdHJhbnNhY3Rpb24odGFibGVOYW1lKS50cnVuY2F0ZSgpO1xuXG4gICAgICAgICAgICBjb25zdCByb3dzID0gYXdhaXQgZnJkYih0YWJsZU5hbWUpO1xuICAgICAgICAgICAgaWYgKHJvd3MubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc29sZS5sb2coY2hhbGsuYmx1ZSh0YWJsZU5hbWUpLCByb3dzLmxlbmd0aCk7XG4gICAgICAgICAgICBhd2FpdCB0cmFuc2FjdGlvblxuICAgICAgICAgICAgICAuaW5zZXJ0KFxuICAgICAgICAgICAgICAgIHJvd3MubWFwKChyb3c6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5mcm9tRW50cmllcyhcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmVudHJpZXMocm93KS5tYXAoKFtrZXksIHZhbHVlXSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtrZXksIG51bGxdO1xuICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSBcImJvb2xlYW5cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtrZXksIHZhbHVlID8gMSA6IDBdO1xuICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlb2YgdmFsdWUgPT09IFwib2JqZWN0XCIgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICEodmFsdWUgaW5zdGFuY2VvZiBEYXRlKVxuICAgICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtrZXksIEpTT04uc3RyaW5naWZ5KHZhbHVlKV07XG4gICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBba2V5LCB2YWx1ZV07XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgIC5pbnRvKHRhYmxlTmFtZSk7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIk9LXCIpO1xuICAgICAgICAgICAgYXdhaXQgdHJhbnNhY3Rpb24ucmF3KGBTRVQgRk9SRUlHTl9LRVlfQ0hFQ0tTID0gMWApO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG4gICAgY29uc29sZS5sb2coY2hhbGsubWFnZW50YShcIkRPTkUhXCIpKTtcblxuICAgIGF3YWl0IGZyZGIuZGVzdHJveSgpO1xuICB9XG5cbiAgcHJpdmF0ZSB2aXNpdGVkUmVjb3JkcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBhc3luYyBpbXBvcnRGaXh0dXJlKGVudGl0eUlkOiBzdHJpbmcsIGlkczogbnVtYmVyW10pIHtcbiAgICAvLyDrsKnrrLgg6riw66GdIOy0iOq4sO2ZlCAo7IOI66Gc7Jq0IGltcG9ydCDsnpHsl4Ug7Iuc7J6RKVxuICAgIHRoaXMudmlzaXRlZFJlY29yZHMuY2xlYXIoKTtcblxuICAgIGNvbnN0IHF1ZXJpZXMgPSBfLnVuaXEoXG4gICAgICAoXG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICAgIGlkcy5tYXAoYXN5bmMgKGlkKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5nZXRJbXBvcnRRdWVyaWVzKGVudGl0eUlkLCBcImlkXCIsIGlkKTtcbiAgICAgICAgICB9KVxuICAgICAgICApXG4gICAgICApLmZsYXQoKVxuICAgICk7XG5cbiAgICBjb25zdCB3ZGIgPSBCYXNlTW9kZWwuZ2V0REIoXCJ3XCIpO1xuICAgIGZvciAobGV0IHF1ZXJ5IG9mIHF1ZXJpZXMpIHtcbiAgICAgIGNvbnN0IFtyc2hdID0gYXdhaXQgd2RiLnJhdyhxdWVyeSk7XG4gICAgICBjb25zb2xlLmxvZyh7XG4gICAgICAgIHF1ZXJ5LFxuICAgICAgICBpbmZvOiByc2guaW5mbyxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGdldEltcG9ydFF1ZXJpZXMoXG4gICAgZW50aXR5SWQ6IHN0cmluZyxcbiAgICBmaWVsZDogc3RyaW5nLFxuICAgIGlkOiBudW1iZXJcbiAgKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIGNvbnN0IHJlY29yZEtleSA9IGAke2VudGl0eUlkfSMke2ZpZWxkfSMke2lkfWA7XG5cbiAgICAvLyDsiJztmZgg7LC47KGwIOuwqeyngDog7J2066+4IOuwqeusuO2VnCDroIjsvZTrk5zripQg7Iqk7YK1XG4gICAgaWYgKHRoaXMudmlzaXRlZFJlY29yZHMuaGFzKHJlY29yZEtleSkpIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgdGhpcy52aXNpdGVkUmVjb3Jkcy5hZGQocmVjb3JkS2V5KTtcblxuICAgIGNvbnNvbGUubG9nKHsgZW50aXR5SWQsIGZpZWxkLCBpZCB9KTtcbiAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgY29uc3Qgd2RiID0gQmFzZU1vZGVsLmdldERCKFwid1wiKTtcblxuICAgIC8vIOyXrOq4sOyEnCDsi6REQuydmCByb3cg6rCA7KC47Ji0XG4gICAgY29uc3QgW3Jvd10gPSBhd2FpdCB3ZGIoZW50aXR5LnRhYmxlKS53aGVyZShmaWVsZCwgaWQpLmxpbWl0KDEpO1xuICAgIGlmIChyb3cgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2VudGl0eUlkfSMke2lkfSByb3frpbwg7LC+7J2EIOyImCDsl4bsirXri4jri6QuYCk7XG4gICAgfVxuXG4gICAgLy8g7ZS97Iqk7LOQREIsIOyLpERCXG4gICAgY29uc3QgZml4dHVyZURhdGFiYXNlID0gKFNvbmFtdS5kYkNvbmZpZy5maXh0dXJlX3JlbW90ZS5jb25uZWN0aW9uIGFzIGFueSlcbiAgICAgIC5kYXRhYmFzZTtcbiAgICBjb25zdCByZWFsRGF0YWJhc2UgPSAoU29uYW11LmRiQ29uZmlnLnByb2R1Y3Rpb25fbWFzdGVyLmNvbm5lY3Rpb24gYXMgYW55KVxuICAgICAgLmRhdGFiYXNlO1xuXG4gICAgY29uc3Qgc2VsZlF1ZXJ5ID0gYElOU0VSVCBJR05PUkUgSU5UTyBcXGAke2ZpeHR1cmVEYXRhYmFzZX1cXGAuXFxgJHtlbnRpdHkudGFibGV9XFxgIChTRUxFQ1QgKiBGUk9NIFxcYCR7cmVhbERhdGFiYXNlfVxcYC5cXGAke2VudGl0eS50YWJsZX1cXGAgV0hFUkUgXFxgaWRcXGAgPSAke2lkfSlgO1xuXG4gICAgY29uc3QgYXJncyA9IE9iamVjdC5lbnRyaWVzKGVudGl0eS5yZWxhdGlvbnMpXG4gICAgICAuZmlsdGVyKFxuICAgICAgICAoWywgcmVsYXRpb25dKSA9PlxuICAgICAgICAgIGlzQmVsb25nc1RvT25lUmVsYXRpb25Qcm9wKHJlbGF0aW9uKSB8fFxuICAgICAgICAgIChpc09uZVRvT25lUmVsYXRpb25Qcm9wKHJlbGF0aW9uKSAmJlxuICAgICAgICAgICAgcmVsYXRpb24uY3VzdG9tSm9pbkNsYXVzZSA9PT0gdW5kZWZpbmVkKVxuICAgICAgKVxuICAgICAgLm1hcCgoWywgcmVsYXRpb25dKSA9PiB7XG4gICAgICAgIC8qXG4gICAgICAgIEJlbG9uZ3NUb09uZeyduCDqsr3smrBcbiAgICAgICAgICBDYXRlZ29yeSAvICdpZCcgLyByb3dbY2F0ZWdvcnlfaWRdIO2YuOy2nFxuICAgICAgICBPbmVUb09uZeyXkCBqb2luQ29sdW1uID09PSB0cnVlIOyduCDqsr3smrBcbiAgICAgICAgICBQcm9maWxlIC8gJ2lkJyAvIHJvd1twcm9maWxlX2lkXSDtmLjstpxcbiAgICAgICAgT25lVG9PbmXsl5Agam9pbkNvbHVtbiA9PT0gZmFsc2Ug7J24IOqyveyasFxuICAgICAgICAgIFByb2ZpbGUgLyAncHJvZmlsZV9pZCcgLyByb3dbJ2lkJ10g7Zi47LacXG4gICAgICAgICovXG4gICAgICAgIGxldCBmaWVsZDogc3RyaW5nO1xuICAgICAgICBsZXQgaWQ6IG51bWJlcjtcbiAgICAgICAgaWYgKGlzT25lVG9PbmVSZWxhdGlvblByb3AocmVsYXRpb24pICYmICFyZWxhdGlvbi5oYXNKb2luQ29sdW1uKSB7XG4gICAgICAgICAgY29uc3QgcmVsYXRlZEVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KHJlbGF0aW9uLndpdGgpO1xuICAgICAgICAgIGNvbnN0IHJlbGF0ZWRJZENvbHVtbk5hbWUgPSByZWxhdGVkRW50aXR5LnByb3BzLmZpbmQoXG4gICAgICAgICAgICAocCkgPT4gaXNSZWxhdGlvblByb3AocCkgJiYgcC53aXRoID09PSBlbnRpdHkuaWRcbiAgICAgICAgICApPy5uYW1lO1xuICAgICAgICAgIGlmICghcmVsYXRlZElkQ29sdW1uTmFtZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICBgJHtyZWxhdGVkRW50aXR5LmlkfeydmCAke2VudGl0eS5pZH0g6rSA6rOEIO2UhOuhreydhCDssL7snYQg7IiYIOyXhuyKteuLiOuLpC5gXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBmaWVsZCA9IGAke3JlbGF0ZWRJZENvbHVtbk5hbWV9X2lkYDtcbiAgICAgICAgICBpZCA9IHJvd1tcImlkXCJdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGZpZWxkID0gXCJpZFwiO1xuICAgICAgICAgIGlkID0gcm93W2Ake3JlbGF0aW9uLm5hbWV9X2lkYF07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBlbnRpdHlJZDogcmVsYXRpb24ud2l0aCxcbiAgICAgICAgICBmaWVsZCxcbiAgICAgICAgICBpZCxcbiAgICAgICAgfTtcbiAgICAgIH0pXG4gICAgICAuZmlsdGVyKChhcmcpID0+IGFyZy5pZCAhPT0gbnVsbCk7XG5cbiAgICBjb25zdCByZWxRdWVyaWVzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBhcmdzLm1hcChhc3luYyAoYXJncykgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRJbXBvcnRRdWVyaWVzKGFyZ3MuZW50aXR5SWQsIGFyZ3MuZmllbGQsIGFyZ3MuaWQpO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIFsuLi5fLnVuaXEocmVsUXVlcmllcy5yZXZlcnNlKCkuZmxhdCgpKSwgc2VsZlF1ZXJ5XTtcbiAgfVxuXG4gIGFzeW5jIGRlc3Ryb3koKSB7XG4gICAgaWYgKHRoaXMuX3RkYikge1xuICAgICAgYXdhaXQgdGhpcy5fdGRiLmRlc3Ryb3koKTtcbiAgICAgIHRoaXMuX3RkYiA9IG51bGw7XG4gICAgfVxuICAgIGlmICh0aGlzLl9mZGIpIHtcbiAgICAgIGF3YWl0IHRoaXMuX2ZkYi5kZXN0cm95KCk7XG4gICAgICB0aGlzLl9mZGIgPSBudWxsO1xuICAgIH1cbiAgICBhd2FpdCBCYXNlTW9kZWwuZGVzdHJveSgpO1xuICB9XG5cbiAgYXN5bmMgZ2V0Rml4dHVyZXMoXG4gICAgc291cmNlREJOYW1lOiBrZXlvZiBTb25hbXVEQkNvbmZpZyxcbiAgICB0YXJnZXREQk5hbWU6IGtleW9mIFNvbmFtdURCQ29uZmlnLFxuICAgIHNlYXJjaE9wdGlvbnM6IEZpeHR1cmVTZWFyY2hPcHRpb25zXG4gICkge1xuICAgIGNvbnN0IHNvdXJjZURCID0ga25leChTb25hbXUuZGJDb25maWdbc291cmNlREJOYW1lXSk7XG4gICAgY29uc3QgdGFyZ2V0REIgPSBrbmV4KFNvbmFtdS5kYkNvbmZpZ1t0YXJnZXREQk5hbWVdKTtcbiAgICBjb25zdCB7IGVudGl0eUlkLCBmaWVsZCwgdmFsdWUsIHNlYXJjaFR5cGUgfSA9IHNlYXJjaE9wdGlvbnM7XG5cbiAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgY29uc3QgY29sdW1uID1cbiAgICAgIGVudGl0eS5wcm9wcy5maW5kKChwcm9wKSA9PiBwcm9wLm5hbWUgPT09IGZpZWxkKT8udHlwZSA9PT0gXCJyZWxhdGlvblwiXG4gICAgICAgID8gYCR7ZmllbGR9X2lkYFxuICAgICAgICA6IGZpZWxkO1xuXG4gICAgbGV0IHF1ZXJ5ID0gc291cmNlREIoZW50aXR5LnRhYmxlKTtcbiAgICBpZiAoc2VhcmNoVHlwZSA9PT0gXCJlcXVhbHNcIikge1xuICAgICAgcXVlcnkgPSBxdWVyeS53aGVyZShjb2x1bW4sIHZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHNlYXJjaFR5cGUgPT09IFwibGlrZVwiKSB7XG4gICAgICBxdWVyeSA9IHF1ZXJ5LndoZXJlKGNvbHVtbiwgXCJsaWtlXCIsIGAlJHt2YWx1ZX0lYCk7XG4gICAgfVxuXG4gICAgY29uc3Qgcm93cyA9IGF3YWl0IHF1ZXJ5O1xuICAgIGlmIChyb3dzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gcmVjb3JkcyBmb3VuZFwiKTtcbiAgICB9XG5cbiAgICBjb25zdCBmaXh0dXJlczogRml4dHVyZVJlY29yZFtdID0gW107XG4gICAgZm9yIChjb25zdCByb3cgb2Ygcm93cykge1xuICAgICAgY29uc3QgaW5pdGlhbFJlY29yZHNMZW5ndGggPSBmaXh0dXJlcy5sZW5ndGg7XG4gICAgICBjb25zdCBuZXdSZWNvcmRzID0gYXdhaXQgdGhpcy5jcmVhdGVGaXh0dXJlUmVjb3JkKGVudGl0eSwgcm93KTtcbiAgICAgIGZpeHR1cmVzLnB1c2goLi4ubmV3UmVjb3Jkcyk7XG4gICAgICBjb25zdCBjdXJyZW50Rml4dHVyZVJlY29yZCA9IGZpeHR1cmVzLmZpbmQoXG4gICAgICAgIChyKSA9PiByLmZpeHR1cmVJZCA9PT0gYCR7ZW50aXR5SWR9IyR7cm93LmlkfWBcbiAgICAgICk7XG5cbiAgICAgIGlmIChjdXJyZW50Rml4dHVyZVJlY29yZCkge1xuICAgICAgICAvLyDtmITsnqwgZml4dHVyZeuhnOu2gO2EsCDsg53shLHrkJwgZmV0Y2hlZFJlY29yZHMg7ISk7KCVXG4gICAgICAgIGN1cnJlbnRGaXh0dXJlUmVjb3JkLmZldGNoZWRSZWNvcmRzID0gZml4dHVyZXNcbiAgICAgICAgICAuZmlsdGVyKChyKSA9PiByLmZpeHR1cmVJZCAhPT0gY3VycmVudEZpeHR1cmVSZWNvcmQuZml4dHVyZUlkKVxuICAgICAgICAgIC5zbGljZShpbml0aWFsUmVjb3Jkc0xlbmd0aClcbiAgICAgICAgICAubWFwKChyKSA9PiByLmZpeHR1cmVJZCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yIGF3YWl0IChjb25zdCBmaXh0dXJlIG9mIGZpeHR1cmVzKSB7XG4gICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChmaXh0dXJlLmVudGl0eUlkKTtcblxuICAgICAgLy8gSUTrpbwg7J207Jqp7ZWY7JesIHRhcmdldERC7JeQIOugiOy9lOuTnOqwgCDsobTsnqztlZjripTsp4Ag7ZmV7J24XG4gICAgICBjb25zdCByb3cgPSBhd2FpdCB0YXJnZXREQihlbnRpdHkudGFibGUpLndoZXJlKFwiaWRcIiwgZml4dHVyZS5pZCkuZmlyc3QoKTtcbiAgICAgIGlmIChyb3cpIHtcbiAgICAgICAgY29uc3QgW3JlY29yZF0gPSBhd2FpdCB0aGlzLmNyZWF0ZUZpeHR1cmVSZWNvcmQoZW50aXR5LCByb3csIHtcbiAgICAgICAgICBzaW5nbGVSZWNvcmQ6IHRydWUsXG4gICAgICAgICAgX2RiOiB0YXJnZXREQixcbiAgICAgICAgfSk7XG4gICAgICAgIGZpeHR1cmUudGFyZ2V0ID0gcmVjb3JkO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gSUTrpbwg7J207Jqp7ZWY7JesIHRhcmdldERC7JeQ7IScIOyhsO2ajOuQmOyngCDslYrripQg6rK97JqwLCB1bmlxdWUg7KCc7JW97J2EIOychOuwmO2VmOuKlOyngCDtmZXsnbhcbiAgICAgIGNvbnN0IHVuaXF1ZVJvdyA9IGF3YWl0IHRoaXMuY2hlY2tVbmlxdWVWaW9sYXRpb24oXG4gICAgICAgIHRhcmdldERCLFxuICAgICAgICBlbnRpdHksXG4gICAgICAgIGZpeHR1cmVcbiAgICAgICk7XG4gICAgICBpZiAodW5pcXVlUm93KSB7XG4gICAgICAgIGNvbnN0IFtyZWNvcmRdID0gYXdhaXQgdGhpcy5jcmVhdGVGaXh0dXJlUmVjb3JkKGVudGl0eSwgdW5pcXVlUm93LCB7XG4gICAgICAgICAgc2luZ2xlUmVjb3JkOiB0cnVlLFxuICAgICAgICAgIF9kYjogdGFyZ2V0REIsXG4gICAgICAgIH0pO1xuICAgICAgICBmaXh0dXJlLnVuaXF1ZSA9IHJlY29yZDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBhd2FpdCB0YXJnZXREQi5kZXN0cm95KCk7XG4gICAgYXdhaXQgc291cmNlREIuZGVzdHJveSgpO1xuXG4gICAgcmV0dXJuIF8udW5pcUJ5KGZpeHR1cmVzLCAoZikgPT4gZi5maXh0dXJlSWQpO1xuICB9XG5cbiAgYXN5bmMgY3JlYXRlRml4dHVyZVJlY29yZChcbiAgICBlbnRpdHk6IEVudGl0eSxcbiAgICByb3c6IGFueSxcbiAgICBvcHRpb25zPzoge1xuICAgICAgc2luZ2xlUmVjb3JkPzogYm9vbGVhbjtcbiAgICAgIF9kYj86IEtuZXg7XG4gICAgfVxuICApOiBQcm9taXNlPEZpeHR1cmVSZWNvcmRbXT4ge1xuICAgIGNvbnN0IHJlY29yZHM6IEZpeHR1cmVSZWNvcmRbXSA9IFtdO1xuICAgIGNvbnN0IHZpc2l0ZWRFbnRpdGllcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gICAgY29uc3QgY3JlYXRlID0gYXN5bmMgKGVudGl0eTogRW50aXR5LCByb3c6IGFueSkgPT4ge1xuICAgICAgY29uc3QgZml4dHVyZUlkID0gYCR7ZW50aXR5LmlkfSMke3Jvdy5pZH1gO1xuICAgICAgaWYgKHZpc2l0ZWRFbnRpdGllcy5oYXMoZml4dHVyZUlkKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB2aXNpdGVkRW50aXRpZXMuYWRkKGZpeHR1cmVJZCk7XG5cbiAgICAgIGNvbnN0IHJlY29yZDogRml4dHVyZVJlY29yZCA9IHtcbiAgICAgICAgZml4dHVyZUlkLFxuICAgICAgICBlbnRpdHlJZDogZW50aXR5LmlkLFxuICAgICAgICBpZDogcm93LmlkLFxuICAgICAgICBjb2x1bW5zOiB7fSxcbiAgICAgICAgZmV0Y2hlZFJlY29yZHM6IFtdLFxuICAgICAgICBiZWxvbmdzUmVjb3JkczogW10sXG4gICAgICB9O1xuXG4gICAgICBmb3IgKGNvbnN0IHByb3Agb2YgZW50aXR5LnByb3BzKSB7XG4gICAgICAgIGlmIChpc1ZpcnR1YWxQcm9wKHByb3ApKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICByZWNvcmQuY29sdW1uc1twcm9wLm5hbWVdID0ge1xuICAgICAgICAgIHByb3A6IHByb3AsXG4gICAgICAgICAgdmFsdWU6IHJvd1twcm9wLm5hbWVdLFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IGRiID0gb3B0aW9ucz8uX2RiID8/IEJhc2VNb2RlbC5nZXREQihcIndcIik7XG4gICAgICAgIGlmIChpc01hbnlUb01hbnlSZWxhdGlvblByb3AocHJvcCkpIHtcbiAgICAgICAgICBjb25zdCByZWxhdGVkRW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQocHJvcC53aXRoKTtcbiAgICAgICAgICBjb25zdCB0aHJvdWdoVGFibGUgPSBwcm9wLmpvaW5UYWJsZTtcbiAgICAgICAgICBjb25zdCBmcm9tQ29sdW1uID0gYCR7aW5mbGVjdGlvbi5zaW5ndWxhcml6ZShlbnRpdHkudGFibGUpfV9pZGA7XG4gICAgICAgICAgY29uc3QgdG9Db2x1bW4gPSBgJHtpbmZsZWN0aW9uLnNpbmd1bGFyaXplKHJlbGF0ZWRFbnRpdHkudGFibGUpfV9pZGA7XG5cbiAgICAgICAgICBjb25zdCByZWxhdGVkSWRzID0gYXdhaXQgZGIodGhyb3VnaFRhYmxlKVxuICAgICAgICAgICAgLndoZXJlKGZyb21Db2x1bW4sIHJvdy5pZClcbiAgICAgICAgICAgIC5wbHVjayh0b0NvbHVtbik7XG4gICAgICAgICAgcmVjb3JkLmNvbHVtbnNbcHJvcC5uYW1lXS52YWx1ZSA9IHJlbGF0ZWRJZHM7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNIYXNNYW55UmVsYXRpb25Qcm9wKHByb3ApKSB7XG4gICAgICAgICAgY29uc3QgcmVsYXRlZEVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KHByb3Aud2l0aCk7XG4gICAgICAgICAgY29uc3QgcmVsYXRlZElkcyA9IGF3YWl0IGRiKHJlbGF0ZWRFbnRpdHkudGFibGUpXG4gICAgICAgICAgICAud2hlcmUocHJvcC5qb2luQ29sdW1uLCByb3cuaWQpXG4gICAgICAgICAgICAucGx1Y2soXCJpZFwiKTtcbiAgICAgICAgICByZWNvcmQuY29sdW1uc1twcm9wLm5hbWVdLnZhbHVlID0gcmVsYXRlZElkcztcbiAgICAgICAgfSBlbHNlIGlmIChpc09uZVRvT25lUmVsYXRpb25Qcm9wKHByb3ApICYmICFwcm9wLmhhc0pvaW5Db2x1bW4pIHtcbiAgICAgICAgICBjb25zdCByZWxhdGVkRW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQocHJvcC53aXRoKTtcbiAgICAgICAgICBjb25zdCByZWxhdGVkUHJvcCA9IHJlbGF0ZWRFbnRpdHkucHJvcHMuZmluZChcbiAgICAgICAgICAgIChwKSA9PiBpc1JlbGF0aW9uUHJvcChwKSAmJiBwLndpdGggPT09IGVudGl0eS5pZFxuICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKHJlbGF0ZWRQcm9wKSB7XG4gICAgICAgICAgICBjb25zdCByZWxhdGVkUm93ID0gYXdhaXQgZGIocmVsYXRlZEVudGl0eS50YWJsZSlcbiAgICAgICAgICAgICAgLndoZXJlKFwiaWRcIiwgcm93LmlkKVxuICAgICAgICAgICAgICAuZmlyc3QoKTtcbiAgICAgICAgICAgIHJlY29yZC5jb2x1bW5zW3Byb3AubmFtZV0udmFsdWUgPSByZWxhdGVkUm93Py5pZDtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoaXNSZWxhdGlvblByb3AocHJvcCkpIHtcbiAgICAgICAgICBjb25zdCByZWxhdGVkSWQgPSByb3dbYCR7cHJvcC5uYW1lfV9pZGBdO1xuICAgICAgICAgIHJlY29yZC5jb2x1bW5zW3Byb3AubmFtZV0udmFsdWUgPSByZWxhdGVkSWQ7XG4gICAgICAgICAgaWYgKHJlbGF0ZWRJZCkge1xuICAgICAgICAgICAgcmVjb3JkLmJlbG9uZ3NSZWNvcmRzLnB1c2goYCR7cHJvcC53aXRofSMke3JlbGF0ZWRJZH1gKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFvcHRpb25zPy5zaW5nbGVSZWNvcmQgJiYgcmVsYXRlZElkKSB7XG4gICAgICAgICAgICBjb25zdCByZWxhdGVkRW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQocHJvcC53aXRoKTtcbiAgICAgICAgICAgIGNvbnN0IHJlbGF0ZWRSb3cgPSBhd2FpdCBkYihyZWxhdGVkRW50aXR5LnRhYmxlKVxuICAgICAgICAgICAgICAud2hlcmUoXCJpZFwiLCByZWxhdGVkSWQpXG4gICAgICAgICAgICAgIC5maXJzdCgpO1xuICAgICAgICAgICAgaWYgKHJlbGF0ZWRSb3cpIHtcbiAgICAgICAgICAgICAgYXdhaXQgY3JlYXRlKHJlbGF0ZWRFbnRpdHksIHJlbGF0ZWRSb3cpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZWNvcmRzLnB1c2gocmVjb3JkKTtcbiAgICB9O1xuXG4gICAgYXdhaXQgY3JlYXRlKGVudGl0eSwgcm93KTtcblxuICAgIHJldHVybiByZWNvcmRzO1xuICB9XG5cbiAgYXN5bmMgaW5zZXJ0Rml4dHVyZXMoXG4gICAgZGJOYW1lOiBrZXlvZiBTb25hbXVEQkNvbmZpZyxcbiAgICBfZml4dHVyZXM6IEZpeHR1cmVSZWNvcmRbXVxuICApIHtcbiAgICBjb25zdCBmaXh0dXJlcyA9IF8udW5pcUJ5KF9maXh0dXJlcywgKGYpID0+IGYuZml4dHVyZUlkKTtcblxuICAgIHRoaXMucmVsYXRpb25HcmFwaC5idWlsZEdyYXBoKGZpeHR1cmVzKTtcbiAgICBjb25zdCBpbnNlcnRpb25PcmRlciA9IHRoaXMucmVsYXRpb25HcmFwaC5nZXRJbnNlcnRpb25PcmRlcigpO1xuICAgIGNvbnN0IGRiID0ga25leChTb25hbXUuZGJDb25maWdbZGJOYW1lXSk7XG5cbiAgICBhd2FpdCBkYi50cmFuc2FjdGlvbihhc3luYyAodHJ4KSA9PiB7XG4gICAgICBhd2FpdCB0cngucmF3KGBTRVQgRk9SRUlHTl9LRVlfQ0hFQ0tTID0gMGApO1xuXG4gICAgICBmb3IgKGNvbnN0IGZpeHR1cmVJZCBvZiBpbnNlcnRpb25PcmRlcikge1xuICAgICAgICBjb25zdCBmaXh0dXJlID0gZml4dHVyZXMuZmluZCgoZikgPT4gZi5maXh0dXJlSWQgPT09IGZpeHR1cmVJZCkhO1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmluc2VydEZpeHR1cmUodHJ4IGFzIGFueSwgZml4dHVyZSk7XG4gICAgICAgIGlmIChyZXN1bHQuaWQgIT09IGZpeHR1cmUuaWQpIHtcbiAgICAgICAgICAvLyBJROqwgCDrs4Dqsr3rkJwg6rK97JqwLCDri6TrpbggZml4dHVyZeyXkOyEnCDssLjsobDtlZjripQg6rK97Jqw6rCAIOywvuyVhOyEnCDsiJjsoJVcbiAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgIGNoYWxrLnllbGxvdyhcbiAgICAgICAgICAgICAgYFVuaXF1ZSBjb25zdHJhaW50IHZpb2xhdGlvbjogJHtmaXh0dXJlLmVudGl0eUlkfSMke2ZpeHR1cmUuaWR9IC0+ICR7Zml4dHVyZS5lbnRpdHlJZH0jJHtyZXN1bHQuaWR9YFxuICAgICAgICAgICAgKVxuICAgICAgICAgICk7XG4gICAgICAgICAgZml4dHVyZXMuZm9yRWFjaCgoZikgPT4ge1xuICAgICAgICAgICAgT2JqZWN0LnZhbHVlcyhmLmNvbHVtbnMpLmZvckVhY2goKGNvbHVtbikgPT4ge1xuICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgY29sdW1uLnByb3AudHlwZSA9PT0gXCJyZWxhdGlvblwiICYmXG4gICAgICAgICAgICAgICAgY29sdW1uLnByb3Aud2l0aCA9PT0gcmVzdWx0LmVudGl0eUlkICYmXG4gICAgICAgICAgICAgICAgY29sdW1uLnZhbHVlID09PSBmaXh0dXJlLmlkXG4gICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIGNvbHVtbi52YWx1ZSA9IHJlc3VsdC5pZDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgZml4dHVyZS5pZCA9IHJlc3VsdC5pZDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IGZpeHR1cmVJZCBvZiBpbnNlcnRpb25PcmRlcikge1xuICAgICAgICBjb25zdCBmaXh0dXJlID0gZml4dHVyZXMuZmluZCgoZikgPT4gZi5maXh0dXJlSWQgPT09IGZpeHR1cmVJZCkhO1xuICAgICAgICBhd2FpdCB0aGlzLmhhbmRsZU1hbnlUb01hbnlSZWxhdGlvbnModHJ4IGFzIGFueSwgZml4dHVyZSwgZml4dHVyZXMpO1xuICAgICAgfVxuICAgICAgYXdhaXQgdHJ4LnJhdyhgU0VUIEZPUkVJR05fS0VZX0NIRUNLUyA9IDFgKTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHJlY29yZHM6IEZpeHR1cmVJbXBvcnRSZXN1bHRbXSA9IFtdO1xuXG4gICAgZm9yIGF3YWl0IChjb25zdCByIG9mIGZpeHR1cmVzKSB7XG4gICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChyLmVudGl0eUlkKTtcbiAgICAgIGNvbnN0IHJlY29yZCA9IGF3YWl0IGRiKGVudGl0eS50YWJsZSkud2hlcmUoXCJpZFwiLCByLmlkKS5maXJzdCgpO1xuICAgICAgcmVjb3Jkcy5wdXNoKHtcbiAgICAgICAgZW50aXR5SWQ6IHIuZW50aXR5SWQsXG4gICAgICAgIGRhdGE6IHJlY29yZCxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGF3YWl0IGRiLmRlc3Ryb3koKTtcblxuICAgIHJldHVybiBfLnVuaXFCeShyZWNvcmRzLCAocikgPT4gYCR7ci5lbnRpdHlJZH0jJHtyLmRhdGEuaWR9YCk7XG4gIH1cblxuICBwcml2YXRlIHByZXBhcmVJbnNlcnREYXRhKGZpeHR1cmU6IEZpeHR1cmVSZWNvcmQpIHtcbiAgICBjb25zdCBpbnNlcnREYXRhOiBhbnkgPSB7fTtcbiAgICBmb3IgKGNvbnN0IFtwcm9wTmFtZSwgY29sdW1uXSBvZiBPYmplY3QuZW50cmllcyhmaXh0dXJlLmNvbHVtbnMpKSB7XG4gICAgICBpZiAoaXNWaXJ0dWFsUHJvcChjb2x1bW4ucHJvcCkpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHByb3AgPSBjb2x1bW4ucHJvcCBhcyBFbnRpdHlQcm9wO1xuICAgICAgaWYgKCFpc1JlbGF0aW9uUHJvcChwcm9wKSkge1xuICAgICAgICBpZiAocHJvcC50eXBlID09PSBcImpzb25cIikge1xuICAgICAgICAgIGluc2VydERhdGFbcHJvcE5hbWVdID0gSlNPTi5zdHJpbmdpZnkoY29sdW1uLnZhbHVlKTtcbiAgICAgICAgfSBlbHNlIGlmIChwcm9wLnR5cGUgPT09IFwidGltZXN0YW1wXCIgfHwgcHJvcC50eXBlID09PSBcImRhdGV0aW1lXCIpIHtcbiAgICAgICAgICBpbnNlcnREYXRhW3Byb3BOYW1lXSA9IG5ldyBEYXRlKGNvbHVtbi52YWx1ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaW5zZXJ0RGF0YVtwcm9wTmFtZV0gPSBjb2x1bW4udmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIGlzQmVsb25nc1RvT25lUmVsYXRpb25Qcm9wKHByb3ApIHx8XG4gICAgICAgIChpc09uZVRvT25lUmVsYXRpb25Qcm9wKHByb3ApICYmIHByb3AuaGFzSm9pbkNvbHVtbilcbiAgICAgICkge1xuICAgICAgICBpbnNlcnREYXRhW2Ake3Byb3BOYW1lfV9pZGBdID0gY29sdW1uLnZhbHVlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gaW5zZXJ0RGF0YTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaW5zZXJ0Rml4dHVyZShkYjogS25leCwgZml4dHVyZTogRml4dHVyZVJlY29yZCkge1xuICAgIGNvbnN0IGluc2VydERhdGEgPSB0aGlzLnByZXBhcmVJbnNlcnREYXRhKGZpeHR1cmUpO1xuICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGZpeHR1cmUuZW50aXR5SWQpO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHVuaXF1ZUZvdW5kID0gYXdhaXQgdGhpcy5jaGVja1VuaXF1ZVZpb2xhdGlvbihkYiwgZW50aXR5LCBmaXh0dXJlKTtcbiAgICAgIGlmICh1bmlxdWVGb3VuZCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGVudGl0eUlkOiBmaXh0dXJlLmVudGl0eUlkLFxuICAgICAgICAgIGlkOiB1bmlxdWVGb3VuZC5pZCxcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZm91bmQgPSBhd2FpdCBkYihlbnRpdHkudGFibGUpLndoZXJlKFwiaWRcIiwgZml4dHVyZS5pZCkuZmlyc3QoKTtcbiAgICAgIGlmIChmb3VuZCAmJiAhZml4dHVyZS5vdmVycmlkZSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGVudGl0eUlkOiBmaXh0dXJlLmVudGl0eUlkLFxuICAgICAgICAgIGlkOiBmb3VuZC5pZCxcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcSA9IGRiLmluc2VydChpbnNlcnREYXRhKS5pbnRvKGVudGl0eS50YWJsZSk7XG4gICAgICBhd2FpdCBxLm9uRHVwbGljYXRlVXBkYXRlLmFwcGx5KHEsIE9iamVjdC5rZXlzKGluc2VydERhdGEpKTtcbiAgICAgIGNvbnNvbGUubG9nKGNoYWxrLmdyZWVuKGBJbnNlcnRlZCBpbnRvICR7ZW50aXR5LnRhYmxlfTogIyR7Zml4dHVyZS5pZH1gKSk7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGVudGl0eUlkOiBmaXh0dXJlLmVudGl0eUlkLFxuICAgICAgICBpZDogZml4dHVyZS5pZCxcbiAgICAgIH07XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zb2xlLmxvZyhlcnIpO1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaGFuZGxlTWFueVRvTWFueVJlbGF0aW9ucyhcbiAgICBkYjogS25leCxcbiAgICBmaXh0dXJlOiBGaXh0dXJlUmVjb3JkLFxuICAgIGZpeHR1cmVzOiBGaXh0dXJlUmVjb3JkW11cbiAgKSB7XG4gICAgZm9yIChjb25zdCBbLCBjb2x1bW5dIG9mIE9iamVjdC5lbnRyaWVzKGZpeHR1cmUuY29sdW1ucykpIHtcbiAgICAgIGNvbnN0IHByb3AgPSBjb2x1bW4ucHJvcCBhcyBFbnRpdHlQcm9wO1xuICAgICAgaWYgKGlzTWFueVRvTWFueVJlbGF0aW9uUHJvcChwcm9wKSkge1xuICAgICAgICBjb25zdCBqb2luVGFibGUgPSAocHJvcCBhcyBNYW55VG9NYW55UmVsYXRpb25Qcm9wKS5qb2luVGFibGU7XG4gICAgICAgIGNvbnN0IHJlbGF0ZWRJZHMgPSBjb2x1bW4udmFsdWUgYXMgbnVtYmVyW107XG5cbiAgICAgICAgZm9yIChjb25zdCByZWxhdGVkSWQgb2YgcmVsYXRlZElkcykge1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICFmaXh0dXJlcy5maW5kKChmKSA9PiBmLmZpeHR1cmVJZCA9PT0gYCR7cHJvcC53aXRofSMke3JlbGF0ZWRJZH1gKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZml4dHVyZS5lbnRpdHlJZCk7XG4gICAgICAgICAgY29uc3QgcmVsYXRlZEVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KHByb3Aud2l0aCk7XG4gICAgICAgICAgaWYgKCFlbnRpdHkgfHwgIXJlbGF0ZWRFbnRpdHkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgYEVudGl0eSBub3QgZm91bmQ6ICR7Zml4dHVyZS5lbnRpdHlJZH0sICR7cHJvcC53aXRofWBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgW2ZvdW5kXSA9IGF3YWl0IGRiKGpvaW5UYWJsZSlcbiAgICAgICAgICAgIC53aGVyZSh7XG4gICAgICAgICAgICAgIFtgJHtpbmZsZWN0aW9uLnNpbmd1bGFyaXplKGVudGl0eS50YWJsZSl9X2lkYF06IGZpeHR1cmUuaWQsXG4gICAgICAgICAgICAgIFtgJHtpbmZsZWN0aW9uLnNpbmd1bGFyaXplKHJlbGF0ZWRFbnRpdHkudGFibGUpfV9pZGBdOiByZWxhdGVkSWQsXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmxpbWl0KDEpO1xuICAgICAgICAgIGlmIChmb3VuZCkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgbmV3SWRzID0gYXdhaXQgZGIoam9pblRhYmxlKS5pbnNlcnQoe1xuICAgICAgICAgICAgW2Ake2luZmxlY3Rpb24uc2luZ3VsYXJpemUoZW50aXR5LnRhYmxlKX1faWRgXTogZml4dHVyZS5pZCxcbiAgICAgICAgICAgIFtgJHtpbmZsZWN0aW9uLnNpbmd1bGFyaXplKHJlbGF0ZWRFbnRpdHkudGFibGUpfV9pZGBdOiByZWxhdGVkSWQsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgICBjaGFsay5ncmVlbihcbiAgICAgICAgICAgICAgYEluc2VydGVkIGludG8gJHtqb2luVGFibGV9OiAke2VudGl0eS50YWJsZX0oJHtmaXh0dXJlLmlkfSkgLSAke3JlbGF0ZWRFbnRpdHkudGFibGV9KCR7cmVsYXRlZElkfSkgSUQ6ICR7bmV3SWRzfWBcbiAgICAgICAgICAgIClcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgYWRkRml4dHVyZUxvYWRlcihjb2RlOiBzdHJpbmcpIHtcbiAgICBjb25zdCBwYXRoID0gU29uYW11LmFwaVJvb3RQYXRoICsgXCIvc3JjL3Rlc3RpbmcvZml4dHVyZS50c1wiO1xuICAgIGxldCBjb250ZW50ID0gcmVhZEZpbGVTeW5jKHBhdGgpLnRvU3RyaW5nKCk7XG5cbiAgICBjb25zdCBmaXh0dXJlTG9hZGVyU3RhcnQgPSBjb250ZW50LmluZGV4T2YoXCJjb25zdCBmaXh0dXJlTG9hZGVyID0ge1wiKTtcbiAgICBjb25zdCBmaXh0dXJlTG9hZGVyRW5kID0gY29udGVudC5pbmRleE9mKFwifTtcIiwgZml4dHVyZUxvYWRlclN0YXJ0KTtcblxuICAgIGlmIChmaXh0dXJlTG9hZGVyU3RhcnQgIT09IC0xICYmIGZpeHR1cmVMb2FkZXJFbmQgIT09IC0xKSB7XG4gICAgICBjb25zdCBuZXdDb250ZW50ID1cbiAgICAgICAgY29udGVudC5zbGljZSgwLCBmaXh0dXJlTG9hZGVyRW5kKSArXG4gICAgICAgIFwiICBcIiArXG4gICAgICAgIGNvZGUgK1xuICAgICAgICBcIlxcblwiICtcbiAgICAgICAgY29udGVudC5zbGljZShmaXh0dXJlTG9hZGVyRW5kKTtcblxuICAgICAgd3JpdGVGaWxlU3luYyhwYXRoLCBuZXdDb250ZW50KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRmFpbGVkIHRvIGZpbmQgZml4dHVyZUxvYWRlciBpbiBmaXh0dXJlLnRzXCIpO1xuICAgIH1cbiAgfVxuXG4gIC8vIO2VtOuLuSDtlL3siqTss5DsnZgg6rCS7Jy866GcIOycoOuLiO2BrCDsoJzslb3sl5Ag7JyE67Cw65CY64qUIOugiOy9lOuTnOqwgCDsnojripTsp4Ag7ZmV7J24XG4gIHByaXZhdGUgYXN5bmMgY2hlY2tVbmlxdWVWaW9sYXRpb24oXG4gICAgZGI6IEtuZXgsXG4gICAgZW50aXR5OiBFbnRpdHksXG4gICAgZml4dHVyZTogRml4dHVyZVJlY29yZFxuICApIHtcbiAgICBjb25zdCBfdW5pcXVlSW5kZXhlcyA9IGVudGl0eS5pbmRleGVzLmZpbHRlcigoaSkgPT4gaS50eXBlID09PSBcInVuaXF1ZVwiKTtcblxuICAgIC8vIE1hbnlUb01hbnkg6rSA6rOEIO2FjOydtOu4lOydmCDsnKDri4jtgawg7KCc7JW97J2AIOygnOyZuFxuICAgIGNvbnN0IHVuaXF1ZUluZGV4ZXMgPSBfdW5pcXVlSW5kZXhlcy5maWx0ZXIoKGluZGV4KSA9PlxuICAgICAgaW5kZXguY29sdW1ucy5ldmVyeSgoY29sdW1uKSA9PiAhY29sdW1uLnN0YXJ0c1dpdGgoYCR7ZW50aXR5LnRhYmxlfV9fYCkpXG4gICAgKTtcbiAgICBpZiAodW5pcXVlSW5kZXhlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGxldCB1bmlxdWVRdWVyeSA9IGRiKGVudGl0eS50YWJsZSk7XG4gICAgZm9yIChjb25zdCBpbmRleCBvZiB1bmlxdWVJbmRleGVzKSB7XG4gICAgICAvLyDsu6zrn7wg7KSRIO2VmOuCmOudvOuPhCBudWxs7J2066m0IOycoOuLiO2BrCDsoJzslb3snYQg7JyE67CY7ZWY7KeAIOyViuq4sCDrlYzrrLjsl5Ag7ZW064u5IOyduOuNseyKpOuKlCDrrLTsi5xcbiAgICAgIGNvbnN0IGNvbnRhaW5zTnVsbCA9IGluZGV4LmNvbHVtbnMuc29tZSgoY29sdW1uKSA9PiB7XG4gICAgICAgIGNvbnN0IGZpZWxkID0gY29sdW1uLnNwbGl0KFwiX2lkXCIpWzBdO1xuICAgICAgICByZXR1cm4gZml4dHVyZS5jb2x1bW5zW2ZpZWxkXS52YWx1ZSA9PT0gbnVsbDtcbiAgICAgIH0pO1xuICAgICAgaWYgKGNvbnRhaW5zTnVsbCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgdW5pcXVlUXVlcnkgPSB1bmlxdWVRdWVyeS5vcldoZXJlKChxYikgPT4ge1xuICAgICAgICBmb3IgKGNvbnN0IGNvbHVtbiBvZiBpbmRleC5jb2x1bW5zKSB7XG4gICAgICAgICAgY29uc3QgZmllbGQgPSBjb2x1bW4uc3BsaXQoXCJfaWRcIilbMF07XG5cbiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShmaXh0dXJlLmNvbHVtbnNbZmllbGRdLnZhbHVlKSkge1xuICAgICAgICAgICAgcWIud2hlcmVJbihjb2x1bW4sIGZpeHR1cmUuY29sdW1uc1tmaWVsZF0udmFsdWUpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBxYi5hbmRXaGVyZShjb2x1bW4sIGZpeHR1cmUuY29sdW1uc1tmaWVsZF0udmFsdWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICAgIGNvbnN0IFt1bmlxdWVGb3VuZF0gPSBhd2FpdCB1bmlxdWVRdWVyeTtcbiAgICByZXR1cm4gdW5pcXVlRm91bmQ7XG4gIH1cbn1cbmV4cG9ydCBjb25zdCBGaXh0dXJlTWFuYWdlciA9IG5ldyBGaXh0dXJlTWFuYWdlckNsYXNzKCk7XG4iXSwibmFtZXMiOlsiY2hhbGsiLCJfIiwiU29uYW11IiwiRW50aXR5TWFuYWdlciIsImlzQmVsb25nc1RvT25lUmVsYXRpb25Qcm9wIiwiaXNIYXNNYW55UmVsYXRpb25Qcm9wIiwiaXNNYW55VG9NYW55UmVsYXRpb25Qcm9wIiwiaXNPbmVUb09uZVJlbGF0aW9uUHJvcCIsImlzUmVsYXRpb25Qcm9wIiwiaXNWaXJ0dWFsUHJvcCIsImluZmxlY3Rpb24iLCJyZWFkRmlsZVN5bmMiLCJ3cml0ZUZpbGVTeW5jIiwiUmVsYXRpb25HcmFwaCIsImtuZXgiLCJCYXNlTW9kZWwiLCJGaXh0dXJlTWFuYWdlckNsYXNzIiwiX3RkYiIsInRkYiIsIkVycm9yIiwiX2ZkYiIsImZkYiIsImNhY2hlZFRhYmxlTmFtZXMiLCJyZWxhdGlvbkdyYXBoIiwiaW5pdCIsImRiQ29uZmlnIiwidGVzdCIsInByb2R1Y3Rpb25fbWFzdGVyIiwidENvbm4iLCJjb25uZWN0aW9uIiwicENvbm4iLCJob3N0IiwicG9ydCIsImRhdGFiYXNlIiwiZml4dHVyZV9sb2NhbCIsImNsZWFuQW5kU2VlZCIsInVzaW5nVGFibGVzIiwidGFibGVOYW1lcyIsInRhYmxlcyIsInJhdyIsIm1hcCIsInRhYmxlSW5mbyIsInRhYmxlTGlzdFN0ciIsImpvaW4iLCJmZGJDaGVja3N1bVJvd3MiLCJ0ZGJDaGVja3N1bVJvd3MiLCJmZGJDaGVja3N1bXMiLCJNYXAiLCJyb3ciLCJUYWJsZSIsInNwbGl0IiwicG9wIiwiQ2hlY2tzdW0iLCJ0ZGJDaGVja3N1bXMiLCJjaGFuZ2VkVGFibGVzIiwiZmlsdGVyIiwidGFibGVOYW1lIiwiZ2V0IiwidHJhbnNhY3Rpb24iLCJ0cngiLCJQcm9taXNlIiwiYWxsIiwidHJ1bmNhdGUiLCJyYXdRdWVyeSIsImdldENoZWNrc3VtIiwiZGIiLCJjaGVja3N1bVJvdyIsInN5bmMiLCJmcmRiIiwiZml4dHVyZV9yZW1vdGUiLCJ0YWJsZSIsIk5hbWUiLCJjb25zb2xlIiwibG9nIiwibWFnZW50YSIsInN0YXJ0c1dpdGgiLCJyZW1vdGVDaGVja3N1bSIsImxvY2FsQ2hlY2tzdW0iLCJyb3dzIiwibGVuZ3RoIiwiYmx1ZSIsImluc2VydCIsIk9iamVjdCIsImZyb21FbnRyaWVzIiwiZW50cmllcyIsImtleSIsInZhbHVlIiwiRGF0ZSIsIkpTT04iLCJzdHJpbmdpZnkiLCJpbnRvIiwiZGVzdHJveSIsInZpc2l0ZWRSZWNvcmRzIiwiU2V0IiwiaW1wb3J0Rml4dHVyZSIsImVudGl0eUlkIiwiaWRzIiwiY2xlYXIiLCJxdWVyaWVzIiwidW5pcSIsImlkIiwiZ2V0SW1wb3J0UXVlcmllcyIsImZsYXQiLCJ3ZGIiLCJnZXREQiIsInF1ZXJ5IiwicnNoIiwiaW5mbyIsImZpZWxkIiwicmVjb3JkS2V5IiwiaGFzIiwiYWRkIiwiZW50aXR5Iiwid2hlcmUiLCJsaW1pdCIsInVuZGVmaW5lZCIsImZpeHR1cmVEYXRhYmFzZSIsInJlYWxEYXRhYmFzZSIsInNlbGZRdWVyeSIsImFyZ3MiLCJyZWxhdGlvbnMiLCJyZWxhdGlvbiIsImN1c3RvbUpvaW5DbGF1c2UiLCJoYXNKb2luQ29sdW1uIiwicmVsYXRlZEVudGl0eSIsIndpdGgiLCJyZWxhdGVkSWRDb2x1bW5OYW1lIiwicHJvcHMiLCJmaW5kIiwicCIsIm5hbWUiLCJhcmciLCJyZWxRdWVyaWVzIiwicmV2ZXJzZSIsImdldEZpeHR1cmVzIiwic291cmNlREJOYW1lIiwidGFyZ2V0REJOYW1lIiwic2VhcmNoT3B0aW9ucyIsInNvdXJjZURCIiwidGFyZ2V0REIiLCJzZWFyY2hUeXBlIiwiY29sdW1uIiwicHJvcCIsInR5cGUiLCJmaXh0dXJlcyIsImluaXRpYWxSZWNvcmRzTGVuZ3RoIiwibmV3UmVjb3JkcyIsImNyZWF0ZUZpeHR1cmVSZWNvcmQiLCJwdXNoIiwiY3VycmVudEZpeHR1cmVSZWNvcmQiLCJyIiwiZml4dHVyZUlkIiwiZmV0Y2hlZFJlY29yZHMiLCJzbGljZSIsImZpeHR1cmUiLCJmaXJzdCIsInJlY29yZCIsInNpbmdsZVJlY29yZCIsIl9kYiIsInRhcmdldCIsInVuaXF1ZVJvdyIsImNoZWNrVW5pcXVlVmlvbGF0aW9uIiwidW5pcXVlIiwidW5pcUJ5IiwiZiIsIm9wdGlvbnMiLCJyZWNvcmRzIiwidmlzaXRlZEVudGl0aWVzIiwiY3JlYXRlIiwiY29sdW1ucyIsImJlbG9uZ3NSZWNvcmRzIiwidGhyb3VnaFRhYmxlIiwiam9pblRhYmxlIiwiZnJvbUNvbHVtbiIsInNpbmd1bGFyaXplIiwidG9Db2x1bW4iLCJyZWxhdGVkSWRzIiwicGx1Y2siLCJqb2luQ29sdW1uIiwicmVsYXRlZFByb3AiLCJyZWxhdGVkUm93IiwicmVsYXRlZElkIiwiaW5zZXJ0Rml4dHVyZXMiLCJkYk5hbWUiLCJfZml4dHVyZXMiLCJidWlsZEdyYXBoIiwiaW5zZXJ0aW9uT3JkZXIiLCJnZXRJbnNlcnRpb25PcmRlciIsInJlc3VsdCIsImluc2VydEZpeHR1cmUiLCJ5ZWxsb3ciLCJmb3JFYWNoIiwidmFsdWVzIiwiaGFuZGxlTWFueVRvTWFueVJlbGF0aW9ucyIsImRhdGEiLCJwcmVwYXJlSW5zZXJ0RGF0YSIsImluc2VydERhdGEiLCJwcm9wTmFtZSIsInVuaXF1ZUZvdW5kIiwiZm91bmQiLCJvdmVycmlkZSIsInEiLCJvbkR1cGxpY2F0ZVVwZGF0ZSIsImFwcGx5Iiwia2V5cyIsImdyZWVuIiwiZXJyIiwibmV3SWRzIiwiYWRkRml4dHVyZUxvYWRlciIsImNvZGUiLCJwYXRoIiwiYXBpUm9vdFBhdGgiLCJjb250ZW50IiwidG9TdHJpbmciLCJmaXh0dXJlTG9hZGVyU3RhcnQiLCJpbmRleE9mIiwiZml4dHVyZUxvYWRlckVuZCIsIm5ld0NvbnRlbnQiLCJfdW5pcXVlSW5kZXhlcyIsImluZGV4ZXMiLCJpIiwidW5pcXVlSW5kZXhlcyIsImluZGV4IiwiZXZlcnkiLCJ1bmlxdWVRdWVyeSIsImNvbnRhaW5zTnVsbCIsInNvbWUiLCJvcldoZXJlIiwicWIiLCJBcnJheSIsImlzQXJyYXkiLCJ3aGVyZUluIiwiYW5kV2hlcmUiLCJGaXh0dXJlTWFuYWdlciJdLCJtYXBwaW5ncyI6IkFBQUEsT0FBT0EsV0FBVyxRQUFRO0FBQzFCLFlBQVlDLE9BQU8sWUFBWTtBQUMvQixTQUFTQyxNQUFNLFFBQVEsa0JBQVM7QUFDaEMsU0FBU0MsYUFBYSxRQUFR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
623
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0aW5nL2ZpeHR1cmUtbWFuYWdlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgYXNzZXJ0IGZyb20gXCJhc3NlcnRcIjtcbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIjtcbmltcG9ydCB7IGV4ZWNTeW5jIH0gZnJvbSBcImNoaWxkX3Byb2Nlc3NcIjtcbmltcG9ydCB7IHJlYWRGaWxlU3luYywgd3JpdGVGaWxlU3luYyB9IGZyb20gXCJmc1wiO1xuaW1wb3J0IGluZmxlY3Rpb24gZnJvbSBcImluZmxlY3Rpb25cIjtcbmltcG9ydCBrbmV4LCB7IHR5cGUgS25leCB9IGZyb20gXCJrbmV4XCI7XG5pbXBvcnQgeyB1bmlxdWUgfSBmcm9tIFwicmFkYXNoaVwiO1xuaW1wb3J0IHsgaW5zcGVjdCB9IGZyb20gXCJ1dGlsXCI7XG5pbXBvcnQgeyBTb25hbXUgfSBmcm9tIFwiLi4vYXBpXCI7XG5pbXBvcnQgeyBCYXNlTW9kZWwgfSBmcm9tIFwiLi4vZGF0YWJhc2UvYmFzZS1tb2RlbFwiO1xuaW1wb3J0IHR5cGUgeyBTb25hbXVEQkNvbmZpZyB9IGZyb20gXCIuLi9kYXRhYmFzZS9kYlwiO1xuaW1wb3J0IHsgdHlwZSBVQlJlZiwgVXBzZXJ0QnVpbGRlciB9IGZyb20gXCIuLi9kYXRhYmFzZS91cHNlcnQtYnVpbGRlclwiO1xuaW1wb3J0IHR5cGUgeyBFbnRpdHkgfSBmcm9tIFwiLi4vZW50aXR5L2VudGl0eVwiO1xuaW1wb3J0IHsgRW50aXR5TWFuYWdlciB9IGZyb20gXCIuLi9lbnRpdHkvZW50aXR5LW1hbmFnZXJcIjtcbmltcG9ydCB7XG4gIHR5cGUgRW50aXR5UHJvcCxcbiAgdHlwZSBGaXh0dXJlSW1wb3J0UmVzdWx0LFxuICB0eXBlIEZpeHR1cmVSZWNvcmQsXG4gIHR5cGUgRml4dHVyZVNlYXJjaE9wdGlvbnMsXG4gIGlzQmVsb25nc1RvT25lUmVsYXRpb25Qcm9wLFxuICBpc0hhc01hbnlSZWxhdGlvblByb3AsXG4gIGlzTWFueVRvTWFueVJlbGF0aW9uUHJvcCxcbiAgaXNPbmVUb09uZVJlbGF0aW9uUHJvcCxcbiAgaXNSZWxhdGlvblByb3AsXG4gIGlzVmlydHVhbFByb3AsXG4gIHR5cGUgTWFueVRvTWFueVJlbGF0aW9uUHJvcCxcbn0gZnJvbSBcIi4uL3R5cGVzL3R5cGVzXCI7XG5pbXBvcnQgeyBSZWxhdGlvbkdyYXBoIH0gZnJvbSBcIi4vX3JlbGF0aW9uLWdyYXBoXCI7XG5cbi8qKiDsgqzsmqnsnpAg7KeA7KCVIOykkeuztSDtmZXsnbgg7Lus65+8IChlbnRpdHlJZOuzhOuhnCDsp4DsoJUpICovXG5leHBvcnQgaW50ZXJmYWNlIER1cGxpY2F0ZUNoZWNrT3B0aW9ucyB7XG4gIGNvbHVtbnM/OiB7XG4gICAgW2VudGl0eUlkOiBzdHJpbmddOiBzdHJpbmdbXTtcbiAgfTtcbn1cblxuZXhwb3J0IGNsYXNzIEZpeHR1cmVNYW5hZ2VyQ2xhc3Mge1xuICBwcml2YXRlIF90ZGI6IEtuZXggfCBudWxsID0gbnVsbDtcbiAgc2V0IHRkYih0ZGI6IEtuZXgpIHtcbiAgICB0aGlzLl90ZGIgPSB0ZGI7XG4gIH1cbiAgZ2V0IHRkYigpOiBLbmV4IHtcbiAgICBpZiAodGhpcy5fdGRiID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJGaXh0dXJlTWFuYWdlciBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWRcIik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl90ZGI7XG4gIH1cblxuICBwcml2YXRlIF9mZGI6IEtuZXggfCBudWxsID0gbnVsbDtcbiAgc2V0IGZkYihmZGI6IEtuZXgpIHtcbiAgICB0aGlzLl9mZGIgPSBmZGI7XG4gIH1cbiAgZ2V0IGZkYigpOiBLbmV4IHtcbiAgICBpZiAodGhpcy5fZmRiID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJGaXh0dXJlTWFuYWdlciBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWRcIik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9mZGI7XG4gIH1cbiAgY2FjaGVkVGFibGVOYW1lczogc3RyaW5nW10gfCBudWxsID0gbnVsbDtcblxuICBwcml2YXRlIHJlbGF0aW9uR3JhcGggPSBuZXcgUmVsYXRpb25HcmFwaCgpO1xuXG4gIC8vIFVwc2VydEJ1aWxkZXIg6riw67CYIGltcG9ydOulvCDsnITtlZwg7IOB7YOcXG4gIHByaXZhdGUgYnVpbGRlcjogVXBzZXJ0QnVpbGRlciA9IG5ldyBVcHNlcnRCdWlsZGVyKCk7XG4gIHByaXZhdGUgZml4dHVyZVJlZk1hcDogTWFwPHN0cmluZywgVUJSZWY+ID0gbmV3IE1hcCgpO1xuICBwcml2YXRlIHV1aWRUb0ZpeHR1cmVJZDogTWFwPHN0cmluZywgc3RyaW5nPiA9IG5ldyBNYXAoKTtcbiAgcHJpdmF0ZSBza2lwcGVkRml4dHVyZXM6IE1hcDxzdHJpbmcsIHsgZW50aXR5SWQ6IHN0cmluZzsgZXhpc3RpbmdJZDogbnVtYmVyIH0+ID0gbmV3IE1hcCgpO1xuXG4gIGluaXQoKSB7XG4gICAgaWYgKHRoaXMuX3RkYiAhPT0gbnVsbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoU29uYW11LmRiQ29uZmlnLnRlc3QgJiYgU29uYW11LmRiQ29uZmlnLnByb2R1Y3Rpb25fbWFzdGVyKSB7XG4gICAgICBjb25zdCB0Q29ubiA9IFNvbmFtdS5kYkNvbmZpZy50ZXN0LmNvbm5lY3Rpb24gYXMgS25leC5Db25uZWN0aW9uQ29uZmlnICYge1xuICAgICAgICBwb3J0PzogbnVtYmVyO1xuICAgICAgfTtcbiAgICAgIGNvbnN0IHBDb25uID0gU29uYW11LmRiQ29uZmlnLnByb2R1Y3Rpb25fbWFzdGVyLmNvbm5lY3Rpb24gYXMgS25leC5Db25uZWN0aW9uQ29uZmlnICYge1xuICAgICAgICBwb3J0PzogbnVtYmVyO1xuICAgICAgfTtcbiAgICAgIGlmIChcbiAgICAgICAgYCR7dENvbm4uaG9zdCA/PyBcImxvY2FsaG9zdFwifToke3RDb25uLnBvcnQgPz8gNTQzMn0vJHt0Q29ubi5kYXRhYmFzZX1gID09PVxuICAgICAgICBgJHtwQ29ubi5ob3N0ID8/IFwibG9jYWxob3N0XCJ9OiR7cENvbm4ucG9ydCA/PyA1NDMyfS8ke3BDb25uLmRhdGFiYXNlfWBcbiAgICAgICkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYO2FjOyKpO2KuERC7JmAIO2UhOuhnOuNleyFmERC7JeQIOuPmeydvO2VnCDrjbDsnbTthLDrsqDsnbTsiqTqsIAg7IKs7Jqp65CY7JeI7Iq164uI64ukLmApO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMudGRiID0ga25leChTb25hbXUuZGJDb25maWcudGVzdCk7XG4gICAgdGhpcy5mZGIgPSBrbmV4KFNvbmFtdS5kYkNvbmZpZy5maXh0dXJlX3JlbW90ZSk7XG4gIH1cblxuICBhc3luYyBnZXRDaGVja3N1bShkYjogS25leCwgdGFibGVOYW1lOiBzdHJpbmcpIHtcbiAgICBjb25zdCBbW2NoZWNrc3VtUm93XV0gPSBhd2FpdCBkYi5yYXcoYENIRUNLU1VNIFRBQkxFICR7dGFibGVOYW1lfWApO1xuICAgIHJldHVybiBjaGVja3N1bVJvdy5DaGVja3N1bTtcbiAgfVxuXG4gIC8qKlxuICAgIOydtOygnCBGaXh0dXJlTWFuYWdlci5zeW5jKCkg64qUIGNoZWNrc3VtIOu5hOq1kCDsl4bsnbQgY3JlYXRlIGRhdGFiYXNlIHRlbXBsYXRlIOycvOuhnCDsiJjtlontlanri4jri6QuXG4gICovXG4gIGFzeW5jIHN5bmMoKSB7XG4gICAgY29uc3QgZml4dHVyZUNvbm4gPSBTb25hbXUuZGJDb25maWcuZml4dHVyZV9yZW1vdGUuY29ubmVjdGlvbiBhcyBLbmV4LlBnQ29ubmVjdGlvbkNvbmZpZztcbiAgICBjb25zdCB0ZXN0Q29ubiA9IFNvbmFtdS5kYkNvbmZpZy50ZXN0LmNvbm5lY3Rpb24gYXMgS25leC5QZ0Nvbm5lY3Rpb25Db25maWc7XG5cbiAgICAvLyBQb3N0Z3JlU1FMIO2MqOyKpOybjOuTnCDtmZjqsr3rs4DsiJgg7ISk7KCVXG4gICAgY29uc3QgcGdFbnYgPSB7IFBHUEFTU1dPUkQ6IHRlc3RDb25uLnBhc3N3b3JkIHx8IFwiXCIgfTtcblxuICAgIC8vIDEuIOyXsOqysCDqsJXsoJwg7KKF66OMXG4gICAgZXhlY1N5bmMoXG4gICAgICBgcHNxbCAtaCAke3Rlc3RDb25uLmhvc3R9IC1wICR7dGVzdENvbm4ucG9ydCA/PyA1NDMyfSAtVSAke3Rlc3RDb25uLnVzZXJ9IC1kIHBvc3RncmVzIC1jIFwiXG4gICAgICBTRUxFQ1QgcGdfdGVybWluYXRlX2JhY2tlbmQocGdfc3RhdF9hY3Rpdml0eS5waWQpXG4gICAgICBGUk9NIHBnX3N0YXRfYWN0aXZpdHlcbiAgICAgIFdIRVJFIGRhdG5hbWUgPSAnJHt0ZXN0Q29ubi5kYXRhYmFzZX0nXG4gICAgICAgIEFORCBwaWQgPD4gcGdfYmFja2VuZF9waWQoKTtcbiAgICBcImAsXG4gICAgICB7IHN0ZGlvOiBcImluaGVyaXRcIiwgZW52OiB7IC4uLnByb2Nlc3MuZW52LCAuLi5wZ0VudiB9IGFzIE5vZGVKUy5Qcm9jZXNzRW52IH0sXG4gICAgKTtcblxuICAgIGV4ZWNTeW5jKFxuICAgICAgYHBzcWwgLWggJHtmaXh0dXJlQ29ubi5ob3N0fSAtcCAke2ZpeHR1cmVDb25uLnBvcnQgPz8gNTQzMn0gLVUgJHtmaXh0dXJlQ29ubi51c2VyfSAtZCBwb3N0Z3JlcyAtYyBcIlxuICAgICAgICBTRUxFQ1QgcGdfdGVybWluYXRlX2JhY2tlbmQocGdfc3RhdF9hY3Rpdml0eS5waWQpXG4gICAgICAgIEZST00gcGdfc3RhdF9hY3Rpdml0eVxuICAgICAgICBXSEVSRSBkYXRuYW1lID0gJyR7Zml4dHVyZUNvbm4uZGF0YWJhc2V9J1xuICAgICAgICAgIEFORCBwaWQgPD4gcGdfYmFja2VuZF9waWQoKTtcbiAgICAgIFwiYCxcbiAgICAgIHsgc3RkaW86IFwiaW5oZXJpdFwiLCBlbnY6IHsgLi4ucHJvY2Vzcy5lbnYsIC4uLnBnRW52IH0gYXMgTm9kZUpTLlByb2Nlc3NFbnYgfSxcbiAgICApO1xuXG4gICAgLy8gMi4gRFJPUCBEQVRBQkFTRSAo67OE64+EIOyLpO2WiSEpXG4gICAgZXhlY1N5bmMoXG4gICAgICBgcHNxbCAtaCAke3Rlc3RDb25uLmhvc3R9IC1wICR7dGVzdENvbm4ucG9ydCA/PyA1NDMyfSAtVSAke3Rlc3RDb25uLnVzZXJ9IC1kIHBvc3RncmVzIC1jIFwiRFJPUCBEQVRBQkFTRSBJRiBFWElTVFMgXFxcXFwiJHt0ZXN0Q29ubi5kYXRhYmFzZX1cXFxcXCJcImAsXG4gICAgICB7IHN0ZGlvOiBcImluaGVyaXRcIiwgZW52OiB7IC4uLnByb2Nlc3MuZW52LCAuLi5wZ0VudiB9IGFzIE5vZGVKUy5Qcm9jZXNzRW52IH0sXG4gICAgKTtcblxuICAgIC8vIDMuIENSRUFURSBEQVRBQkFTRVxuICAgIGV4ZWNTeW5jKFxuICAgICAgYHBzcWwgLWggJHt0ZXN0Q29ubi5ob3N0fSAtcCAke3Rlc3RDb25uLnBvcnQgPz8gNTQzMn0gLVUgJHt0ZXN0Q29ubi51c2VyfSAtZCBwb3N0Z3JlcyAtYyBcIkNSRUFURSBEQVRBQkFTRSBcXFxcXCIke3Rlc3RDb25uLmRhdGFiYXNlfVxcXFxcIiBURU1QTEFURSBcXFxcXCIke2ZpeHR1cmVDb25uLmRhdGFiYXNlfVxcXFxcIlwiYCxcbiAgICAgIHsgc3RkaW86IFwiaW5oZXJpdFwiLCBlbnY6IHsgLi4ucHJvY2Vzcy5lbnYsIC4uLnBnRW52IH0gYXMgTm9kZUpTLlByb2Nlc3NFbnYgfSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSB2aXNpdGVkUmVjb3JkcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBhc3luYyBpbXBvcnRGaXh0dXJlKGVudGl0eUlkOiBzdHJpbmcsIGlkczogbnVtYmVyW10pIHtcbiAgICAvLyDrsKnrrLgg6riw66GdIOy0iOq4sO2ZlCAo7IOI66Gc7Jq0IGltcG9ydCDsnpHsl4Ug7Iuc7J6RKVxuICAgIHRoaXMudmlzaXRlZFJlY29yZHMuY2xlYXIoKTtcblxuICAgIGNvbnN0IHF1ZXJpZXMgPSB1bmlxdWUoXG4gICAgICAoXG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICAgIGlkcy5tYXAoYXN5bmMgKGlkKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5nZXRJbXBvcnRRdWVyaWVzKGVudGl0eUlkLCBcImlkXCIsIGlkKTtcbiAgICAgICAgICB9KSxcbiAgICAgICAgKVxuICAgICAgKS5mbGF0KCksXG4gICAgKTtcblxuICAgIGNvbnN0IHdkYiA9IEJhc2VNb2RlbC5nZXREQihcIndcIik7XG4gICAgZm9yIChjb25zdCBxdWVyeSBvZiBxdWVyaWVzKSB7XG4gICAgICBjb25zdCBbcnNoXSA9IGF3YWl0IHdkYi5yYXcocXVlcnkpO1xuICAgICAgY29uc29sZS5sb2coe1xuICAgICAgICBxdWVyeSxcbiAgICAgICAgaW5mbzogcnNoLmluZm8sXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBnZXRJbXBvcnRRdWVyaWVzKGVudGl0eUlkOiBzdHJpbmcsIGZpZWxkOiBzdHJpbmcsIGlkOiBudW1iZXIpOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgY29uc3QgcmVjb3JkS2V5ID0gYCR7ZW50aXR5SWR9IyR7ZmllbGR9IyR7aWR9YDtcblxuICAgIC8vIOyInO2ZmCDssLjsobAg67Cp7KeAOiDsnbTrr7gg67Cp66y47ZWcIOugiOy9lOuTnOuKlCDsiqTtgrVcbiAgICBpZiAodGhpcy52aXNpdGVkUmVjb3Jkcy5oYXMocmVjb3JkS2V5KSkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICB0aGlzLnZpc2l0ZWRSZWNvcmRzLmFkZChyZWNvcmRLZXkpO1xuXG4gICAgY29uc29sZS5sb2coeyBlbnRpdHlJZCwgZmllbGQsIGlkIH0pO1xuICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKTtcbiAgICBjb25zdCB3ZGIgPSBCYXNlTW9kZWwuZ2V0REIoXCJ3XCIpO1xuXG4gICAgLy8g7Jes6riw7IScIOyLpERC7J2YIHJvdyDqsIDsoLjsmLRcbiAgICBjb25zdCBbcm93XSA9IGF3YWl0IHdkYihlbnRpdHkudGFibGUpLndoZXJlKGZpZWxkLCBpZCkubGltaXQoMSk7XG4gICAgaWYgKHJvdyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7ZW50aXR5SWR9IyR7aWR9IHJvd+ulvCDssL7snYQg7IiYIOyXhuyKteuLiOuLpC5gKTtcbiAgICB9XG5cbiAgICAvLyDtlL3siqTss5BEQiwg7IukREJcbiAgICBjb25zdCBmaXh0dXJlRGF0YWJhc2UgPSAoU29uYW11LmRiQ29uZmlnLmZpeHR1cmVfcmVtb3RlLmNvbm5lY3Rpb24gYXMgS25leC5Db25uZWN0aW9uQ29uZmlnKVxuICAgICAgLmRhdGFiYXNlO1xuICAgIGNvbnN0IHJlYWxEYXRhYmFzZSA9IChTb25hbXUuZGJDb25maWcucHJvZHVjdGlvbl9tYXN0ZXIuY29ubmVjdGlvbiBhcyBLbmV4LkNvbm5lY3Rpb25Db25maWcpXG4gICAgICAuZGF0YWJhc2U7XG5cbiAgICBjb25zdCBzZWxmUXVlcnkgPSBgSU5TRVJUIElHTk9SRSBJTlRPIFxcYCR7Zml4dHVyZURhdGFiYXNlfVxcYC5cXGAke2VudGl0eS50YWJsZX1cXGAgKFNFTEVDVCAqIEZST00gXFxgJHtyZWFsRGF0YWJhc2V9XFxgLlxcYCR7ZW50aXR5LnRhYmxlfVxcYCBXSEVSRSBcXGBpZFxcYCA9ICR7aWR9KWA7XG5cbiAgICBjb25zdCBhcmdzID0gT2JqZWN0LmVudHJpZXMoZW50aXR5LnJlbGF0aW9ucylcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgIChbLCByZWxhdGlvbl0pID0+XG4gICAgICAgICAgaXNCZWxvbmdzVG9PbmVSZWxhdGlvblByb3AocmVsYXRpb24pIHx8XG4gICAgICAgICAgKGlzT25lVG9PbmVSZWxhdGlvblByb3AocmVsYXRpb24pICYmIHJlbGF0aW9uLmN1c3RvbUpvaW5DbGF1c2UgPT09IHVuZGVmaW5lZCksXG4gICAgICApXG4gICAgICAubWFwKChbLCByZWxhdGlvbl0pID0+IHtcbiAgICAgICAgLypcbiAgICAgICAgQmVsb25nc1RvT25l7J24IOqyveyasFxuICAgICAgICAgIENhdGVnb3J5IC8gJ2lkJyAvIHJvd1tjYXRlZ29yeV9pZF0g7Zi47LacXG4gICAgICAgIE9uZVRvT25l7JeQIGpvaW5Db2x1bW4gPT09IHRydWUg7J24IOqyveyasFxuICAgICAgICAgIFByb2ZpbGUgLyAnaWQnIC8gcm93W3Byb2ZpbGVfaWRdIO2YuOy2nFxuICAgICAgICBPbmVUb09uZeyXkCBqb2luQ29sdW1uID09PSBmYWxzZSDsnbgg6rK97JqwXG4gICAgICAgICAgUHJvZmlsZSAvICdwcm9maWxlX2lkJyAvIHJvd1snaWQnXSDtmLjstpxcbiAgICAgICAgKi9cbiAgICAgICAgbGV0IGZpZWxkOiBzdHJpbmc7XG4gICAgICAgIGxldCBpZDogbnVtYmVyO1xuICAgICAgICBpZiAoaXNPbmVUb09uZVJlbGF0aW9uUHJvcChyZWxhdGlvbikgJiYgIXJlbGF0aW9uLmhhc0pvaW5Db2x1bW4pIHtcbiAgICAgICAgICBjb25zdCByZWxhdGVkRW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQocmVsYXRpb24ud2l0aCk7XG4gICAgICAgICAgY29uc3QgcmVsYXRlZElkQ29sdW1uTmFtZSA9IHJlbGF0ZWRFbnRpdHkucHJvcHMuZmluZChcbiAgICAgICAgICAgIChwKSA9PiBpc1JlbGF0aW9uUHJvcChwKSAmJiBwLndpdGggPT09IGVudGl0eS5pZCxcbiAgICAgICAgICApPy5uYW1lO1xuICAgICAgICAgIGlmICghcmVsYXRlZElkQ29sdW1uTmFtZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke3JlbGF0ZWRFbnRpdHkuaWR97J2YICR7ZW50aXR5LmlkfSDqtIDqs4Qg7ZSE66Gt7J2EIOywvuydhCDsiJgg7JeG7Iq164uI64ukLmApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBmaWVsZCA9IGAke3JlbGF0ZWRJZENvbHVtbk5hbWV9X2lkYDtcbiAgICAgICAgICBpZCA9IHJvdy5pZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBmaWVsZCA9IFwiaWRcIjtcbiAgICAgICAgICBpZCA9IHJvd1tgJHtyZWxhdGlvbi5uYW1lfV9pZGBdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgZW50aXR5SWQ6IHJlbGF0aW9uLndpdGgsXG4gICAgICAgICAgZmllbGQsXG4gICAgICAgICAgaWQsXG4gICAgICAgIH07XG4gICAgICB9KVxuICAgICAgLmZpbHRlcigoYXJnKSA9PiBhcmcuaWQgIT09IG51bGwpO1xuXG4gICAgY29uc3QgcmVsUXVlcmllcyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgYXJncy5tYXAoYXN5bmMgKGFyZ3MpID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0SW1wb3J0UXVlcmllcyhhcmdzLmVudGl0eUlkLCBhcmdzLmZpZWxkLCBhcmdzLmlkKTtcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICByZXR1cm4gWy4uLnVuaXF1ZShyZWxRdWVyaWVzLnJldmVyc2UoKS5mbGF0KCkpLCBzZWxmUXVlcnldO1xuICB9XG5cbiAgYXN5bmMgZGVzdHJveSgpIHtcbiAgICBpZiAodGhpcy5fdGRiKSB7XG4gICAgICBhd2FpdCB0aGlzLl90ZGIuZGVzdHJveSgpO1xuICAgICAgdGhpcy5fdGRiID0gbnVsbDtcbiAgICB9XG4gICAgaWYgKHRoaXMuX2ZkYikge1xuICAgICAgYXdhaXQgdGhpcy5fZmRiLmRlc3Ryb3koKTtcbiAgICAgIHRoaXMuX2ZkYiA9IG51bGw7XG4gICAgfVxuICAgIGF3YWl0IEJhc2VNb2RlbC5kZXN0cm95KCk7XG4gIH1cblxuICBhc3luYyBnZXRGaXh0dXJlcyhcbiAgICBzb3VyY2VEQk5hbWU6IGtleW9mIFNvbmFtdURCQ29uZmlnLFxuICAgIHRhcmdldERCTmFtZToga2V5b2YgU29uYW11REJDb25maWcsXG4gICAgc2VhcmNoT3B0aW9uczogRml4dHVyZVNlYXJjaE9wdGlvbnMsXG4gICAgZHVwbGljYXRlQ2hlY2s/OiBEdXBsaWNhdGVDaGVja09wdGlvbnMsXG4gICkge1xuICAgIGNvbnN0IHNvdXJjZURCID0ga25leChTb25hbXUuZGJDb25maWdbc291cmNlREJOYW1lXSk7XG4gICAgY29uc3QgdGFyZ2V0REIgPSBrbmV4KFNvbmFtdS5kYkNvbmZpZ1t0YXJnZXREQk5hbWVdKTtcblxuICAgIGNvbnN0IHsgZW50aXR5SWQsIGZpZWxkLCB2YWx1ZSwgc2VhcmNoVHlwZSB9ID0gc2VhcmNoT3B0aW9ucztcblxuICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKTtcbiAgICBjb25zdCBjb2x1bW4gPVxuICAgICAgZW50aXR5LnByb3BzLmZpbmQoKHByb3ApID0+IHByb3AubmFtZSA9PT0gZmllbGQpPy50eXBlID09PSBcInJlbGF0aW9uXCIgPyBgJHtmaWVsZH1faWRgIDogZmllbGQ7XG5cbiAgICBsZXQgcXVlcnkgPSBzb3VyY2VEQihlbnRpdHkudGFibGUpO1xuICAgIGlmIChzZWFyY2hUeXBlID09PSBcImVxdWFsc1wiKSB7XG4gICAgICBxdWVyeSA9IHF1ZXJ5LndoZXJlKGNvbHVtbiwgdmFsdWUpO1xuICAgIH0gZWxzZSBpZiAoc2VhcmNoVHlwZSA9PT0gXCJsaWtlXCIpIHtcbiAgICAgIHF1ZXJ5ID0gcXVlcnkud2hlcmUoY29sdW1uLCBcImxpa2VcIiwgYCUke3ZhbHVlfSVgKTtcbiAgICB9XG5cbiAgICBjb25zdCByb3dzID0gYXdhaXQgcXVlcnk7XG4gICAgaWYgKHJvd3MubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyByZWNvcmRzIGZvdW5kXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IGZpeHR1cmVzOiBGaXh0dXJlUmVjb3JkW10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IHJvdyBvZiByb3dzKSB7XG4gICAgICBjb25zdCBpbml0aWFsUmVjb3Jkc0xlbmd0aCA9IGZpeHR1cmVzLmxlbmd0aDtcbiAgICAgIGNvbnN0IG5ld1JlY29yZHMgPSBhd2FpdCB0aGlzLmNyZWF0ZUZpeHR1cmVSZWNvcmQoZW50aXR5LCByb3csIHtcbiAgICAgICAgX2RiOiBzb3VyY2VEQixcbiAgICAgIH0pO1xuICAgICAgZml4dHVyZXMucHVzaCguLi5uZXdSZWNvcmRzKTtcbiAgICAgIGNvbnN0IGN1cnJlbnRGaXh0dXJlUmVjb3JkID0gZml4dHVyZXMuZmluZCgocikgPT4gci5maXh0dXJlSWQgPT09IGAke2VudGl0eUlkfSMke3Jvdy5pZH1gKTtcblxuICAgICAgaWYgKGN1cnJlbnRGaXh0dXJlUmVjb3JkKSB7XG4gICAgICAgIC8vIO2YhOyerCBmaXh0dXJl66Gc67aA7YSwIOyDneyEseuQnCBmZXRjaGVkUmVjb3JkcyDshKTsoJVcbiAgICAgICAgY3VycmVudEZpeHR1cmVSZWNvcmQuZmV0Y2hlZFJlY29yZHMgPSBmaXh0dXJlc1xuICAgICAgICAgIC5maWx0ZXIoKHIpID0+IHIuZml4dHVyZUlkICE9PSBjdXJyZW50Rml4dHVyZVJlY29yZC5maXh0dXJlSWQpXG4gICAgICAgICAgLnNsaWNlKGluaXRpYWxSZWNvcmRzTGVuZ3RoKVxuICAgICAgICAgIC5tYXAoKHIpID0+IHIuZml4dHVyZUlkKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgYXdhaXQgKGNvbnN0IGZpeHR1cmUgb2YgZml4dHVyZXMpIHtcbiAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGZpeHR1cmUuZW50aXR5SWQpO1xuXG4gICAgICAvLyDsgqzsmqnsnpAg7KeA7KCVIOy7rOufvCDquLDspIAg7KSR67O1IO2ZleyduCDihpIgdGFyZ2V0XG4gICAgICBjb25zdCBjdXN0b21Db2x1bW5zID0gZHVwbGljYXRlQ2hlY2s/LmNvbHVtbnM/LltmaXh0dXJlLmVudGl0eUlkXTtcbiAgICAgIGlmIChjdXN0b21Db2x1bW5zICYmIGN1c3RvbUNvbHVtbnMubGVuZ3RoID4gMCkge1xuICAgICAgICBjb25zdCBjdXN0b21EdXBsaWNhdGVSb3cgPSBhd2FpdCB0aGlzLmNoZWNrRHVwbGljYXRlQnlDb2x1bW5zKFxuICAgICAgICAgIHRhcmdldERCLFxuICAgICAgICAgIGVudGl0eSxcbiAgICAgICAgICBmaXh0dXJlLFxuICAgICAgICAgIGN1c3RvbUNvbHVtbnMsXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjdXN0b21EdXBsaWNhdGVSb3cpIHtcbiAgICAgICAgICBjb25zdCBbcmVjb3JkXSA9IGF3YWl0IHRoaXMuY3JlYXRlRml4dHVyZVJlY29yZChlbnRpdHksIGN1c3RvbUR1cGxpY2F0ZVJvdywge1xuICAgICAgICAgICAgc2luZ2xlUmVjb3JkOiB0cnVlLFxuICAgICAgICAgICAgX2RiOiB0YXJnZXREQixcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBmaXh0dXJlLnRhcmdldCA9IHJlY29yZDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBVbmlxdWUgaW5kZXgg6riw7KSAIOykkeuztSDtmZXsnbgg4oaSIGZpeHR1cmUudW5pcXVlXG4gICAgICBjb25zdCB1bmlxdWVSb3cgPSBhd2FpdCB0aGlzLmNoZWNrVW5pcXVlVmlvbGF0aW9uKHRhcmdldERCLCBlbnRpdHksIGZpeHR1cmUpO1xuICAgICAgaWYgKHVuaXF1ZVJvdykge1xuICAgICAgICBjb25zdCBbcmVjb3JkXSA9IGF3YWl0IHRoaXMuY3JlYXRlRml4dHVyZVJlY29yZChlbnRpdHksIHVuaXF1ZVJvdywge1xuICAgICAgICAgIHNpbmdsZVJlY29yZDogdHJ1ZSxcbiAgICAgICAgICBfZGI6IHRhcmdldERCLFxuICAgICAgICB9KTtcbiAgICAgICAgZml4dHVyZS51bmlxdWUgPSByZWNvcmQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgYXdhaXQgdGFyZ2V0REIuZGVzdHJveSgpO1xuICAgIGF3YWl0IHNvdXJjZURCLmRlc3Ryb3koKTtcblxuICAgIHJldHVybiB1bmlxdWUoZml4dHVyZXMsIChmKSA9PiBmLmZpeHR1cmVJZCk7XG4gIH1cblxuICBhc3luYyBjcmVhdGVGaXh0dXJlUmVjb3JkKFxuICAgIGVudGl0eTogRW50aXR5LFxuICAgIHJvdzoge1xuICAgICAgaWQ6IG51bWJlcjtcbiAgICAgIFtrZXk6IHN0cmluZ106IHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4gfCBudWxsO1xuICAgIH0sXG4gICAgb3B0aW9ucz86IHtcbiAgICAgIHNpbmdsZVJlY29yZD86IGJvb2xlYW47XG4gICAgICBfZGI/OiBLbmV4O1xuICAgIH0sXG4gICk6IFByb21pc2U8Rml4dHVyZVJlY29yZFtdPiB7XG4gICAgY29uc3QgcmVjb3JkczogRml4dHVyZVJlY29yZFtdID0gW107XG4gICAgY29uc3QgdmlzaXRlZEVudGl0aWVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgICBjb25zdCBjcmVhdGUgPSBhc3luYyAoXG4gICAgICBlbnRpdHk6IEVudGl0eSxcbiAgICAgIHJvdzoge1xuICAgICAgICBpZDogbnVtYmVyO1xuICAgICAgICBba2V5OiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgbnVsbDtcbiAgICAgIH0sXG4gICAgKSA9PiB7XG4gICAgICBjb25zdCBmaXh0dXJlSWQgPSBgJHtlbnRpdHkuaWR9IyR7cm93LmlkfWA7XG4gICAgICBpZiAodmlzaXRlZEVudGl0aWVzLmhhcyhmaXh0dXJlSWQpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHZpc2l0ZWRFbnRpdGllcy5hZGQoZml4dHVyZUlkKTtcblxuICAgICAgY29uc3QgcmVjb3JkOiBGaXh0dXJlUmVjb3JkID0ge1xuICAgICAgICBmaXh0dXJlSWQsXG4gICAgICAgIGVudGl0eUlkOiBlbnRpdHkuaWQsXG4gICAgICAgIGlkOiByb3cuaWQsXG4gICAgICAgIGNvbHVtbnM6IHt9LFxuICAgICAgICBmZXRjaGVkUmVjb3JkczogW10sXG4gICAgICAgIGJlbG9uZ3NSZWNvcmRzOiBbXSxcbiAgICAgIH07XG5cbiAgICAgIGZvciAoY29uc3QgcHJvcCBvZiBlbnRpdHkucHJvcHMpIHtcbiAgICAgICAgaWYgKGlzVmlydHVhbFByb3AocHJvcCkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlY29yZC5jb2x1bW5zW3Byb3AubmFtZV0gPSB7XG4gICAgICAgICAgcHJvcDogcHJvcCxcbiAgICAgICAgICB2YWx1ZTogcm93W3Byb3AubmFtZV0sXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgZGIgPSBvcHRpb25zPy5fZGIgPz8gQmFzZU1vZGVsLmdldERCKFwid1wiKTtcbiAgICAgICAgaWYgKGlzTWFueVRvTWFueVJlbGF0aW9uUHJvcChwcm9wKSkge1xuICAgICAgICAgIGNvbnN0IHJlbGF0ZWRFbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChwcm9wLndpdGgpO1xuICAgICAgICAgIGNvbnN0IHRocm91Z2hUYWJsZSA9IHByb3Auam9pblRhYmxlO1xuICAgICAgICAgIGNvbnN0IGZyb21Db2x1bW4gPSBgJHtpbmZsZWN0aW9uLnNpbmd1bGFyaXplKGVudGl0eS50YWJsZSl9X2lkYDtcbiAgICAgICAgICBjb25zdCB0b0NvbHVtbiA9IGAke2luZmxlY3Rpb24uc2luZ3VsYXJpemUocmVsYXRlZEVudGl0eS50YWJsZSl9X2lkYDtcblxuICAgICAgICAgIGNvbnN0IHJlbGF0ZWRJZHMgPSBhd2FpdCBkYih0aHJvdWdoVGFibGUpLndoZXJlKGZyb21Db2x1bW4sIHJvdy5pZCkucGx1Y2sodG9Db2x1bW4pO1xuICAgICAgICAgIHJlY29yZC5jb2x1bW5zW3Byb3AubmFtZV0udmFsdWUgPSByZWxhdGVkSWRzO1xuICAgICAgICB9IGVsc2UgaWYgKGlzSGFzTWFueVJlbGF0aW9uUHJvcChwcm9wKSkge1xuICAgICAgICAgIGNvbnN0IHJlbGF0ZWRFbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChwcm9wLndpdGgpO1xuICAgICAgICAgIGNvbnN0IHJlbGF0ZWRJZHMgPSBhd2FpdCBkYihyZWxhdGVkRW50aXR5LnRhYmxlKVxuICAgICAgICAgICAgLndoZXJlKHByb3Auam9pbkNvbHVtbiwgcm93LmlkKVxuICAgICAgICAgICAgLnBsdWNrKFwiaWRcIik7XG4gICAgICAgICAgcmVjb3JkLmNvbHVtbnNbcHJvcC5uYW1lXS52YWx1ZSA9IHJlbGF0ZWRJZHM7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNPbmVUb09uZVJlbGF0aW9uUHJvcChwcm9wKSAmJiAhcHJvcC5oYXNKb2luQ29sdW1uKSB7XG4gICAgICAgICAgY29uc3QgcmVsYXRlZEVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KHByb3Aud2l0aCk7XG4gICAgICAgICAgY29uc3QgcmVsYXRlZFByb3AgPSByZWxhdGVkRW50aXR5LnByb3BzLmZpbmQoXG4gICAgICAgICAgICAocCkgPT4gaXNSZWxhdGlvblByb3AocCkgJiYgcC53aXRoID09PSBlbnRpdHkuaWQsXG4gICAgICAgICAgKTtcbiAgICAgICAgICBpZiAocmVsYXRlZFByb3ApIHtcbiAgICAgICAgICAgIGNvbnN0IHJlbGF0ZWRSb3cgPSBhd2FpdCBkYihyZWxhdGVkRW50aXR5LnRhYmxlKS53aGVyZShcImlkXCIsIHJvdy5pZCkuZmlyc3QoKTtcbiAgICAgICAgICAgIHJlY29yZC5jb2x1bW5zW3Byb3AubmFtZV0udmFsdWUgPSByZWxhdGVkUm93Py5pZDtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoaXNSZWxhdGlvblByb3AocHJvcCkpIHtcbiAgICAgICAgICBjb25zdCByZWxhdGVkSWQgPSByb3dbYCR7cHJvcC5uYW1lfV9pZGBdO1xuICAgICAgICAgIHJlY29yZC5jb2x1bW5zW3Byb3AubmFtZV0udmFsdWUgPSByZWxhdGVkSWQ7XG4gICAgICAgICAgaWYgKHJlbGF0ZWRJZCkge1xuICAgICAgICAgICAgcmVjb3JkLmJlbG9uZ3NSZWNvcmRzLnB1c2goYCR7cHJvcC53aXRofSMke3JlbGF0ZWRJZH1gKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFvcHRpb25zPy5zaW5nbGVSZWNvcmQgJiYgcmVsYXRlZElkKSB7XG4gICAgICAgICAgICBjb25zdCByZWxhdGVkRW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQocHJvcC53aXRoKTtcbiAgICAgICAgICAgIGNvbnN0IHJlbGF0ZWRSb3cgPSBhd2FpdCBkYihyZWxhdGVkRW50aXR5LnRhYmxlKS53aGVyZShcImlkXCIsIHJlbGF0ZWRJZCkuZmlyc3QoKTtcbiAgICAgICAgICAgIGlmIChyZWxhdGVkUm93KSB7XG4gICAgICAgICAgICAgIGF3YWl0IGNyZWF0ZShyZWxhdGVkRW50aXR5LCByZWxhdGVkUm93KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmVjb3Jkcy5wdXNoKHJlY29yZCk7XG4gICAgfTtcblxuICAgIGF3YWl0IGNyZWF0ZShlbnRpdHksIHJvdyk7XG5cbiAgICByZXR1cm4gcmVjb3JkcztcbiAgfVxuXG4gIC8qKlxuICAgKiAxLiBSZWxhdGlvbkdyYXBo66GcIGZpeHR1cmUg64uo7JyEIOyCveyehSDsiJzshJwg6rOE7IKwIChzZWxmLXJlZmVyZW5jZSDtj6ztlagpXG4gICAqIDIuIOyInOyEnOuMgOuhnCBVcHNlcnRCdWlsZGVy7JeQIOuTseuhnSAoVUJSZWbroZwg7LC47KGwIOq0gOqzhCDtkZztmIQpXG4gICAqIDMuIO2FjOydtOu4lOuzhCB1cHNlcnQg7Iuk7ZaJIChJROuKlCBEQuqwgCDsnpDrj5kg7ZWg64u5KVxuICAgKi9cbiAgYXN5bmMgaW5zZXJ0Rml4dHVyZXMoXG4gICAgZGJOYW1lOiBrZXlvZiBTb25hbXVEQkNvbmZpZyxcbiAgICBfZml4dHVyZXM6IEZpeHR1cmVSZWNvcmRbXSxcbiAgKTogUHJvbWlzZTxGaXh0dXJlSW1wb3J0UmVzdWx0W10+IHtcbiAgICBjb25zdCBmaXh0dXJlcyA9IHVuaXF1ZShfZml4dHVyZXMsIChmKSA9PiBmLmZpeHR1cmVJZCk7XG5cbiAgICAvLyDstIjquLDtmZRcbiAgICB0aGlzLmJ1aWxkZXIgPSBuZXcgVXBzZXJ0QnVpbGRlcigpO1xuICAgIHRoaXMuZml4dHVyZVJlZk1hcCA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLnV1aWRUb0ZpeHR1cmVJZCA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLnNraXBwZWRGaXh0dXJlcyA9IG5ldyBNYXAoKTtcblxuICAgIGNvbnN0IGRiID0ga25leChTb25hbXUuZGJDb25maWdbZGJOYW1lXSk7XG4gICAgY29uc3QgcmVzdWx0czogRml4dHVyZUltcG9ydFJlc3VsdFtdID0gW107XG5cbiAgICB0cnkge1xuICAgICAgLy8gMS4gUmVsYXRpb25HcmFwaOuhnCBmaXh0dXJlIOuLqOychCDsgr3snoUg7Iic7IScIOqzhOyCsFxuICAgICAgdGhpcy5yZWxhdGlvbkdyYXBoLmJ1aWxkR3JhcGgoZml4dHVyZXMpO1xuICAgICAgY29uc3QgaW5zZXJ0aW9uT3JkZXIgPSB0aGlzLnJlbGF0aW9uR3JhcGguZ2V0SW5zZXJ0aW9uT3JkZXIoKTtcblxuICAgICAgLy8gMi4g7Iic7ISc64yA66GcIFVwc2VydEJ1aWxkZXLsl5Ag65Ox66GdIChvdmVycmlkZSDssrTtgawpXG4gICAgICBmb3IgKGNvbnN0IGZpeHR1cmVJZCBvZiBpbnNlcnRpb25PcmRlcikge1xuICAgICAgICBjb25zdCBmaXh0dXJlID0gZml4dHVyZXMuZmluZCgoZikgPT4gZi5maXh0dXJlSWQgPT09IGZpeHR1cmVJZCk7XG4gICAgICAgIGlmICghZml4dHVyZSkgY29udGludWU7XG5cbiAgICAgICAgY29uc3QgaGFzVGFyZ2V0ID0gISFmaXh0dXJlLnRhcmdldDtcbiAgICAgICAgY29uc3QgaGFzVW5pcXVlID0gISFmaXh0dXJlLnVuaXF1ZTtcbiAgICAgICAgY29uc3QgaGFzRHVwbGljYXRlID0gaGFzVGFyZ2V0IHx8IGhhc1VuaXF1ZTtcblxuICAgICAgICAvLyDspJHrs7XsnbQg7J6I6rOgIG92ZXJyaWRlPWZhbHNl7J24IOqyveyasDog7Iqk7YK1XG4gICAgICAgIGlmIChoYXNEdXBsaWNhdGUgJiYgIWZpeHR1cmUub3ZlcnJpZGUpIHtcbiAgICAgICAgICAvLyDquLDsobQg66CI7L2U65OcIElEIOyggOyepSAodW5pcXVlIOyasOyEoCwg7JeG7Jy866m0IHRhcmdldClcbiAgICAgICAgICBjb25zdCBleGlzdGluZ0lkID0gZml4dHVyZS51bmlxdWU/LmlkID8/IGZpeHR1cmUudGFyZ2V0Py5pZDtcbiAgICAgICAgICBhc3NlcnQoZXhpc3RpbmdJZCk7XG4gICAgICAgICAgdGhpcy5za2lwcGVkRml4dHVyZXMuc2V0KGZpeHR1cmVJZCwge1xuICAgICAgICAgICAgZW50aXR5SWQ6IGZpeHR1cmUuZW50aXR5SWQsXG4gICAgICAgICAgICBleGlzdGluZ0lkLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgICBjaGFsay55ZWxsb3coXG4gICAgICAgICAgICAgIGBTa2lwcGVkICR7Zml4dHVyZS5lbnRpdHlJZH0jJHtmaXh0dXJlLmlkfSAoZXhpc3Rpbmc6ICMke2V4aXN0aW5nSWR9LCBvdmVycmlkZTogZmFsc2UpYCxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucmVnaXN0ZXJGaXh0dXJlKGZpeHR1cmUpO1xuICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICBjaGFsay5ibHVlKFxuICAgICAgICAgICAgYFJlZ2lzdGVyZWQgJHtmaXh0dXJlLmVudGl0eUlkfSMke2ZpeHR1cmUuaWR9JHtmaXh0dXJlLm92ZXJyaWRlID8gYCAob3ZlcnJpZGUgZXhpc3Rpbmc6ICMke2ZpeHR1cmUudGFyZ2V0Py5pZH0pYCA6IFwiXCJ9YCxcbiAgICAgICAgICApLFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICAvLyAzLiDthYzsnbTruJTrs4QgdXBzZXJ0IOyLpO2WiVxuICAgICAgY29uc3QgdGFibGVPcmRlciA9IHRoaXMuZ2V0VGFibGVPcmRlcihmaXh0dXJlcyk7XG5cbiAgICAgIGF3YWl0IGRiLnRyYW5zYWN0aW9uKGFzeW5jICh0cngpID0+IHtcbiAgICAgICAgY29uc3QgaW5zZXJ0ZWRJZHNCeVRhYmxlID0gbmV3IE1hcDxzdHJpbmcsIE1hcDxzdHJpbmcsIG51bWJlcj4+KCk7XG5cbiAgICAgICAgZm9yIChjb25zdCB0YWJsZU5hbWUgb2YgdGFibGVPcmRlcikge1xuICAgICAgICAgIGlmICghdGhpcy5idWlsZGVyLmhhc1RhYmxlKHRhYmxlTmFtZSkpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgLy8gdXBzZXJ0IOyLpO2WiSDsoIQgdXVpZCDrqqnroZ0g7KCA7J6lXG4gICAgICAgICAgY29uc3QgdGFibGUgPSB0aGlzLmJ1aWxkZXIuZ2V0VGFibGUodGFibGVOYW1lKTtcbiAgICAgICAgICBjb25zdCB1dWlkcyA9IHRhYmxlLnJvd3MubWFwKChyb3cpID0+IHJvdy51dWlkIGFzIHN0cmluZyk7XG5cbiAgICAgICAgICBjb25zb2xlLmxvZyhjaGFsay5ibHVlKGBVcHNlcnRpbmcgJHt0YWJsZU5hbWV9IHdpdGggJHt1dWlkcy5sZW5ndGh9IHJvd3NgKSk7XG4gICAgICAgICAgYXdhaXQgdGhpcy5idWlsZGVyLnVwc2VydCh0cngsIHRhYmxlTmFtZSk7XG5cbiAgICAgICAgICAvLyB1cHNlcnTrkJwgcm9365Ok7J2YIHV1aWQgLT4gaWQg66ek7ZWRIOq1rOy2lVxuICAgICAgICAgIGlmICh1dWlkcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBjb25zdCB1dWlkVG9JZCA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCk7XG4gICAgICAgICAgICBjb25zdCByb3dzID0gYXdhaXQgdHJ4KHRhYmxlTmFtZSkuc2VsZWN0KFwidXVpZFwiLCBcImlkXCIpLndoZXJlSW4oXCJ1dWlkXCIsIHV1aWRzKTtcblxuICAgICAgICAgICAgZm9yIChjb25zdCByb3cgb2Ygcm93cykge1xuICAgICAgICAgICAgICB1dWlkVG9JZC5zZXQocm93LnV1aWQsIHJvdy5pZCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGluc2VydGVkSWRzQnlUYWJsZS5zZXQodGFibGVOYW1lLCB1dWlkVG9JZCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gNC4gTWFueVRvTWFueSDqtIDqs4Qg7LKY66asXG4gICAgICAgIGF3YWl0IHRoaXMucHJvY2Vzc01hbnlUb01hbnlSZWxhdGlvbnModHJ4LCBmaXh0dXJlcywgaW5zZXJ0ZWRJZHNCeVRhYmxlKTtcblxuICAgICAgICAvLyA1LiDqsrDqs7wg7IiY7KeRXG4gICAgICAgIGZvciAoY29uc3QgZml4dHVyZSBvZiBmaXh0dXJlcykge1xuICAgICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGZpeHR1cmUuZW50aXR5SWQpO1xuXG4gICAgICAgICAgLy8g7Iqk7YK165CcIGZpeHR1cmXripQg6riw7KG0IOugiOy9lOuTnCDsoJXrs7TroZwg6rKw6rO8IOy2lOqwgFxuICAgICAgICAgIGNvbnN0IHNraXBwZWQgPSB0aGlzLnNraXBwZWRGaXh0dXJlcy5nZXQoZml4dHVyZS5maXh0dXJlSWQpO1xuICAgICAgICAgIGlmIChza2lwcGVkKSB7XG4gICAgICAgICAgICByZXN1bHRzLnB1c2goe1xuICAgICAgICAgICAgICBlbnRpdHlJZDogZml4dHVyZS5lbnRpdHlJZCxcbiAgICAgICAgICAgICAgZGF0YTogYXdhaXQgdHJ4KGVudGl0eS50YWJsZSkud2hlcmUoXCJpZFwiLCBza2lwcGVkLmV4aXN0aW5nSWQpLmZpcnN0KCksXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHJlZiA9IHRoaXMuZml4dHVyZVJlZk1hcC5nZXQoZml4dHVyZS5maXh0dXJlSWQpO1xuICAgICAgICAgIGlmIChyZWYpIHtcbiAgICAgICAgICAgIGNvbnN0IHV1aWRUb0lkID0gaW5zZXJ0ZWRJZHNCeVRhYmxlLmdldChlbnRpdHkudGFibGUpO1xuICAgICAgICAgICAgY29uc3QgaW5zZXJ0ZWRJZCA9IHV1aWRUb0lkPy5nZXQocmVmLnV1aWQpO1xuXG4gICAgICAgICAgICBpZiAoaW5zZXJ0ZWRJZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgIHJlc3VsdHMucHVzaCh7XG4gICAgICAgICAgICAgICAgZW50aXR5SWQ6IGZpeHR1cmUuZW50aXR5SWQsXG4gICAgICAgICAgICAgICAgZGF0YTogYXdhaXQgdHJ4KGVudGl0eS50YWJsZSkud2hlcmUoXCJpZFwiLCBpbnNlcnRlZElkKS5maXJzdCgpLFxuICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgICAgICBjaGFsay5ncmVlbihgSW5zZXJ0ZWQgaW50byAke2VudGl0eS50YWJsZX06ICMke2ZpeHR1cmUuaWR9IC0+ICMke2luc2VydGVkSWR9YCksXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXdhaXQgZGIuZGVzdHJveSgpO1xuICAgIH1cblxuICAgIHJldHVybiB1bmlxdWUocmVzdWx0cywgKHIpID0+IGAke3IuZW50aXR5SWR9IyR7ci5kYXRhLmlkfWApO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpeHR1cmVSZWNvcmTrpbwgVXBzZXJ0QnVpbGRlcuyXkCDrk7HroZ1cbiAgICovXG4gIHByaXZhdGUgcmVnaXN0ZXJGaXh0dXJlKGZpeHR1cmU6IEZpeHR1cmVSZWNvcmQpOiBVQlJlZiB7XG4gICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZml4dHVyZS5lbnRpdHlJZCk7XG4gICAgY29uc3Qgcm93OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9O1xuXG4gICAgLy8gT3ZlcnJpZGUg66qo65OcIO2MkOuLqDogdGFyZ2V0IOuYkOuKlCB1bmlxdWXqsIAg7J6I6rOgIG92ZXJyaWRlPXRydWXsnbgg6rK97JqwXG4gICAgY29uc3QgZXhpc3RpbmdSZWNvcmQgPSBmaXh0dXJlLnRhcmdldCA/PyBmaXh0dXJlLnVuaXF1ZTtcbiAgICBjb25zdCBpc092ZXJyaWRlTW9kZSA9IGZpeHR1cmUub3ZlcnJpZGUgJiYgZXhpc3RpbmdSZWNvcmQ7XG5cbiAgICBmb3IgKGNvbnN0IFtwcm9wTmFtZSwgY29sdW1uXSBvZiBPYmplY3QuZW50cmllcyhmaXh0dXJlLmNvbHVtbnMpKSB7XG4gICAgICBjb25zdCBwcm9wID0gY29sdW1uLnByb3A7XG5cbiAgICAgIGlmIChpc1ZpcnR1YWxQcm9wKHByb3ApKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBpZC91dWlkIOyymOumrDogT3ZlcnJpZGUg66qo65Oc7J28IOuVjOunjCDquLDsobQg6rCSIOyCrOyaqVxuICAgICAgaWYgKHByb3BOYW1lID09PSBcImlkXCIgfHwgcHJvcE5hbWUgPT09IFwidXVpZFwiKSB7XG4gICAgICAgIGlmIChpc092ZXJyaWRlTW9kZSAmJiBleGlzdGluZ1JlY29yZCkge1xuICAgICAgICAgIC8vIE92ZXJyaWRlOiDquLDsobQg66CI7L2U65Oc7J2YIOqwkiDsgqzsmqkg4oaSIFVQREFURVxuICAgICAgICAgIHJvd1twcm9wTmFtZV0gPSBleGlzdGluZ1JlY29yZC5jb2x1bW5zW3Byb3BOYW1lXT8udmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgLy8g7IOIIOugiOy9lOuTnDog7KCc7Jm4IOKGkiBJTlNFUlQgKERCL1Vwc2VydEJ1aWxkZXLqsIAg7IOd7ISxKVxuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzUmVsYXRpb25Qcm9wKHByb3ApKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBpc0JlbG9uZ3NUb09uZVJlbGF0aW9uUHJvcChwcm9wKSB8fFxuICAgICAgICAgIChpc09uZVRvT25lUmVsYXRpb25Qcm9wKHByb3ApICYmIHByb3AuaGFzSm9pbkNvbHVtbilcbiAgICAgICAgKSB7XG4gICAgICAgICAgY29uc3QgcmVsYXRlZElkID0gY29sdW1uLnZhbHVlIGFzIG51bWJlciB8IG51bGw7XG4gICAgICAgICAgaWYgKHJlbGF0ZWRJZCAhPT0gbnVsbCAmJiByZWxhdGVkSWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgY29uc3QgcmVsYXRlZEZpeHR1cmVJZCA9IGAke3Byb3Aud2l0aH0jJHtyZWxhdGVkSWR9YDtcblxuICAgICAgICAgICAgLy8g66i87KCAIHNraXDrkJwgZml4dHVyZeyduOyngCDtmZXsnbhcbiAgICAgICAgICAgIGNvbnN0IHNraXBwZWRFeGlzdGluZ0lkID0gdGhpcy5za2lwcGVkRml4dHVyZXMuZ2V0KHJlbGF0ZWRGaXh0dXJlSWQpPy5leGlzdGluZ0lkO1xuICAgICAgICAgICAgaWYgKHNraXBwZWRFeGlzdGluZ0lkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgLy8gc2tpcOuQnCBmaXh0dXJlIOKGkiB0YXJnZXQgRELsnZgg6riw7KG0IOugiOy9lOuTnCBpZCDsgqzsmqlcbiAgICAgICAgICAgICAgcm93W2Ake3Byb3BOYW1lfV9pZGBdID0gc2tpcHBlZEV4aXN0aW5nSWQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjb25zdCByZWxhdGVkUmVmID0gdGhpcy5maXh0dXJlUmVmTWFwLmdldChyZWxhdGVkRml4dHVyZUlkKTtcbiAgICAgICAgICAgICAgaWYgKHJlbGF0ZWRSZWYpIHtcbiAgICAgICAgICAgICAgICAvLyDsnbTrr7gg65Ox66Gd65CcIGZpeHR1cmUg7LC47KGwIOKGkiBVQlJlZiDsgqzsmqlcbiAgICAgICAgICAgICAgICByb3dbYCR7cHJvcE5hbWV9X2lkYF0gPSByZWxhdGVkUmVmO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIGZpeHR1cmVz7JeQIO2PrO2VqOuQmOyngCDslYrsnYAg66CI7L2U65OcIOKGkiBJRCDqt7jrjIDroZwg7IKs7JqpXG4gICAgICAgICAgICAgICAgcm93W2Ake3Byb3BOYW1lfV9pZGBdID0gcmVsYXRlZElkO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJvd1tgJHtwcm9wTmFtZX1faWRgXSA9IG51bGw7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIEhhc01hbnksIE1hbnlUb01hbnnripQg67OE64+EIOyymOumrFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8g7J2867CYIOy7rOufvFxuICAgICAgICByb3dbcHJvcE5hbWVdID0gdGhpcy5jb252ZXJ0Q29sdW1uVmFsdWUocHJvcCBhcyBFbnRpdHlQcm9wLCBjb2x1bW4udmFsdWUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnNvbGUubG9nKGNoYWxrLmJsdWUoYFJlZ2lzdGVyaW5nICR7ZW50aXR5LnRhYmxlfSAtICR7aW5zcGVjdChyb3csIGZhbHNlLCBudWxsLCB0cnVlKX1gKSk7XG4gICAgY29uc3QgcmVmID0gdGhpcy5idWlsZGVyLnJlZ2lzdGVyKGVudGl0eS50YWJsZSwgcm93KTtcbiAgICB0aGlzLmZpeHR1cmVSZWZNYXAuc2V0KGZpeHR1cmUuZml4dHVyZUlkLCByZWYpO1xuICAgIHRoaXMudXVpZFRvRml4dHVyZUlkLnNldChyZWYudXVpZCwgZml4dHVyZS5maXh0dXJlSWQpO1xuXG4gICAgcmV0dXJuIHJlZjtcbiAgfVxuXG4gIC8qKlxuICAgKiDsu6zrn7wg6rCSIOuzgO2ZmFxuICAgKi9cbiAgcHJpdmF0ZSBjb252ZXJ0Q29sdW1uVmFsdWUocHJvcDogRW50aXR5UHJvcCwgdmFsdWU6IHVua25vd24pOiB1bmtub3duIHtcbiAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgc3dpdGNoIChwcm9wLnR5cGUpIHtcbiAgICAgIGNhc2UgXCJqc29uXCI6XG4gICAgICAgIC8vIFVwc2VydEJ1aWxkZXIucmVnaXN0ZXLsl5DshJwgSlNPTi5zdHJpbmdpZnkg7LKY66as7ZWY66+A66GcIG9iamVjdCDqt7jrjIDroZwg7KCE64usXG4gICAgICAgIHJldHVybiB2YWx1ZTtcblxuICAgICAgY2FzZSBcImRhdGVcIjpcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiB8fCB0eXBlb2YgdmFsdWUgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICByZXR1cm4gbmV3IERhdGUodmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2YWx1ZTtcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiDthYzsnbTruJQg7Iic7IScIOy2lOy2nCAoZml4dHVyZXPsl5Ag7Y+s7ZWo65CcIO2FjOydtOu4lOunjClcbiAgICovXG4gIHByaXZhdGUgZ2V0VGFibGVPcmRlcihmaXh0dXJlczogRml4dHVyZVJlY29yZFtdKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IHRhYmxlczogc3RyaW5nW10gPSBbXTtcbiAgICBjb25zdCBzZWVuID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgICBmb3IgKGNvbnN0IGZpeHR1cmUgb2YgZml4dHVyZXMpIHtcbiAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGZpeHR1cmUuZW50aXR5SWQpO1xuICAgICAgaWYgKCFzZWVuLmhhcyhlbnRpdHkudGFibGUpKSB7XG4gICAgICAgIHNlZW4uYWRkKGVudGl0eS50YWJsZSk7XG4gICAgICAgIHRhYmxlcy5wdXNoKGVudGl0eS50YWJsZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRhYmxlcztcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgcHJvY2Vzc01hbnlUb01hbnlSZWxhdGlvbnMoXG4gICAgdHJ4OiBLbmV4LlRyYW5zYWN0aW9uLFxuICAgIGZpeHR1cmVzOiBGaXh0dXJlUmVjb3JkW10sXG4gICAgaW5zZXJ0ZWRJZHNCeVRhYmxlOiBNYXA8c3RyaW5nLCBNYXA8c3RyaW5nLCBudW1iZXI+PixcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgZm9yIChjb25zdCBmaXh0dXJlIG9mIGZpeHR1cmVzKSB7XG4gICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChmaXh0dXJlLmVudGl0eUlkKTtcbiAgICAgIGNvbnN0IHNvdXJjZVJlZiA9IHRoaXMuZml4dHVyZVJlZk1hcC5nZXQoZml4dHVyZS5maXh0dXJlSWQpO1xuXG4gICAgICBpZiAoIXNvdXJjZVJlZikgY29udGludWU7XG5cbiAgICAgIGNvbnN0IHNvdXJjZVV1aWRUb0lkID0gaW5zZXJ0ZWRJZHNCeVRhYmxlLmdldChlbnRpdHkudGFibGUpO1xuICAgICAgY29uc3Qgc291cmNlSWQgPSBzb3VyY2VVdWlkVG9JZD8uZ2V0KHNvdXJjZVJlZi51dWlkKTtcblxuICAgICAgaWYgKHNvdXJjZUlkID09PSB1bmRlZmluZWQpIGNvbnRpbnVlO1xuXG4gICAgICBmb3IgKGNvbnN0IFssIGNvbHVtbl0gb2YgT2JqZWN0LmVudHJpZXMoZml4dHVyZS5jb2x1bW5zKSkge1xuICAgICAgICBjb25zdCBwcm9wID0gY29sdW1uLnByb3A7XG5cbiAgICAgICAgaWYgKGlzTWFueVRvTWFueVJlbGF0aW9uUHJvcChwcm9wKSAmJiBBcnJheS5pc0FycmF5KGNvbHVtbi52YWx1ZSkpIHtcbiAgICAgICAgICAvLyDshKDtg53rkJjsp4Ag7JWK7J2AIE1hbnlUb01hbnkg6rSA6rOE64qUIOyggOyepe2VmOyngCDslYrsnYxcbiAgICAgICAgICBjb25zdCB0YXJnZXRUYWJsZSA9IEVudGl0eU1hbmFnZXIuZ2V0KHByb3Aud2l0aCk7XG4gICAgICAgICAgaWYgKHRoaXMuYnVpbGRlci5oYXNUYWJsZSh0YXJnZXRUYWJsZS50YWJsZSkgPT09IGZhbHNlKSBjb250aW51ZTtcblxuICAgICAgICAgIGNvbnN0IHJlbGF0ZWRJZHMgPSBjb2x1bW4udmFsdWUgYXMgbnVtYmVyW107XG4gICAgICAgICAgaWYgKHJlbGF0ZWRJZHMubGVuZ3RoID09PSAwKSBjb250aW51ZTtcblxuICAgICAgICAgIGNvbnN0IGpvaW5UYWJsZSA9IChwcm9wIGFzIE1hbnlUb01hbnlSZWxhdGlvblByb3ApLmpvaW5UYWJsZTtcbiAgICAgICAgICBjb25zdCByZWxhdGVkRW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQocHJvcC53aXRoKTtcblxuICAgICAgICAgIGNvbnN0IHNvdXJjZUNvbHVtbiA9IGAke2luZmxlY3Rpb24uc2luZ3VsYXJpemUoZW50aXR5LnRhYmxlKX1faWRgO1xuICAgICAgICAgIGNvbnN0IHRhcmdldENvbHVtbiA9IGAke2luZmxlY3Rpb24uc2luZ3VsYXJpemUocmVsYXRlZEVudGl0eS50YWJsZSl9X2lkYDtcblxuICAgICAgICAgIGZvciAoY29uc3QgcmVsYXRlZElkIG9mIHJlbGF0ZWRJZHMpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlbGF0ZWRGaXh0dXJlSWQgPSBgJHtwcm9wLndpdGh9IyR7cmVsYXRlZElkfWA7XG4gICAgICAgICAgICBjb25zdCByZWxhdGVkUmVmID0gdGhpcy5maXh0dXJlUmVmTWFwLmdldChyZWxhdGVkRml4dHVyZUlkKTtcblxuICAgICAgICAgICAgbGV0IHRhcmdldElkOiBudW1iZXI7XG5cbiAgICAgICAgICAgIGlmIChyZWxhdGVkUmVmKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHJlbGF0ZWRVdWlkVG9JZCA9IGluc2VydGVkSWRzQnlUYWJsZS5nZXQocmVsYXRlZEVudGl0eS50YWJsZSk7XG4gICAgICAgICAgICAgIGNvbnN0IHJlc29sdmVkSWQgPSByZWxhdGVkVXVpZFRvSWQ/LmdldChyZWxhdGVkUmVmLnV1aWQpO1xuXG4gICAgICAgICAgICAgIGlmIChyZXNvbHZlZElkID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICAgICAgICBgUmVsYXRlZCBmaXh0dXJlICR7cmVsYXRlZEZpeHR1cmVJZH0gbm90IGZvdW5kIGluIGluc2VydGVkSWRzLCBza2lwcGluZ2AsXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB0YXJnZXRJZCA9IHJlc29sdmVkSWQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0YXJnZXRJZCA9IHJlbGF0ZWRJZDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSm9pblRhYmxl7JeQIOyCveyehVxuICAgICAgICAgICAgY29uc3QgW2ZvdW5kXSA9IGF3YWl0IHRyeChqb2luVGFibGUpXG4gICAgICAgICAgICAgIC53aGVyZSh7XG4gICAgICAgICAgICAgICAgW3NvdXJjZUNvbHVtbl06IHNvdXJjZUlkLFxuICAgICAgICAgICAgICAgIFt0YXJnZXRDb2x1bW5dOiB0YXJnZXRJZCxcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgLmxpbWl0KDEpO1xuXG4gICAgICAgICAgICBpZiAoIWZvdW5kKSB7XG4gICAgICAgICAgICAgIGF3YWl0IHRyeChqb2luVGFibGUpLmluc2VydCh7XG4gICAgICAgICAgICAgICAgW3NvdXJjZUNvbHVtbl06IHNvdXJjZUlkLFxuICAgICAgICAgICAgICAgIFt0YXJnZXRDb2x1bW5dOiB0YXJnZXRJZCxcbiAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgICAgICAgY2hhbGsuZ3JlZW4oXG4gICAgICAgICAgICAgICAgICBgSW5zZXJ0ZWQgaW50byAke2pvaW5UYWJsZX06ICR7ZW50aXR5LnRhYmxlfSgke3NvdXJjZUlkfSkgLSAke3JlbGF0ZWRFbnRpdHkudGFibGV9KCR7dGFyZ2V0SWR9KWAsXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNoZWNrVW5pcXVlVmlvbGF0aW9uKGRiOiBLbmV4LCBlbnRpdHk6IEVudGl0eSwgZml4dHVyZTogRml4dHVyZVJlY29yZCkge1xuICAgIGNvbnN0IF91bmlxdWVJbmRleGVzID0gZW50aXR5LmluZGV4ZXM/LmZpbHRlcigoaSkgPT4gaS50eXBlID09PSBcInVuaXF1ZVwiKSA/PyBbXTtcblxuICAgIGNvbnN0IHVuaXF1ZUluZGV4ZXMgPSBfdW5pcXVlSW5kZXhlcy5maWx0ZXIoKGluZGV4KSA9PlxuICAgICAgaW5kZXguY29sdW1ucy5ldmVyeSgoY29sdW1uKSA9PiAhY29sdW1uLnN0YXJ0c1dpdGgoYCR7ZW50aXR5LnRhYmxlfV9fYCkpLFxuICAgICk7XG4gICAgaWYgKHVuaXF1ZUluZGV4ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBsZXQgdW5pcXVlUXVlcnkgPSBkYihlbnRpdHkudGFibGUpO1xuICAgIGxldCBoYXNDb25kaXRpb24gPSBmYWxzZTtcblxuICAgIGZvciAoY29uc3QgaW5kZXggb2YgdW5pcXVlSW5kZXhlcykge1xuICAgICAgLy8g7Lus65+8IOykkSDtlZjrgpjrnbzrj4QgbnVsbOydtOuptCDsnKDri4jtgawg7KCc7JW97J2EIOychOuwmO2VmOyngCDslYrquLAg65WM66y47JeQIO2VtOuLuSDsnbjrjbHsiqTripQg66y07IucXG4gICAgICBjb25zdCBjb250YWluc051bGwgPSBpbmRleC5jb2x1bW5zLnNvbWUoKGNvbHVtbikgPT4ge1xuICAgICAgICBjb25zdCBmaWVsZCA9IGNvbHVtbi5yZXBsYWNlKC9faWQkLywgXCJcIik7XG4gICAgICAgIHJldHVybiBmaXh0dXJlLmNvbHVtbnNbZmllbGRdPy52YWx1ZSA9PT0gbnVsbDtcbiAgICAgIH0pO1xuICAgICAgaWYgKGNvbnRhaW5zTnVsbCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgdW5pcXVlUXVlcnkgPSB1bmlxdWVRdWVyeS5vcldoZXJlKChxYikgPT4ge1xuICAgICAgICBmb3IgKGNvbnN0IGNvbHVtbiBvZiBpbmRleC5jb2x1bW5zKSB7XG4gICAgICAgICAgY29uc3QgZmllbGQgPSBjb2x1bW4ucmVwbGFjZSgvX2lkJC8sIFwiXCIpO1xuXG4gICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZml4dHVyZS5jb2x1bW5zW2ZpZWxkXT8udmFsdWUpKSB7XG4gICAgICAgICAgICBxYi53aGVyZUluKGNvbHVtbiwgZml4dHVyZS5jb2x1bW5zW2ZpZWxkXS52YWx1ZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHFiLmFuZFdoZXJlKGNvbHVtbiwgZml4dHVyZS5jb2x1bW5zW2ZpZWxkXT8udmFsdWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBoYXNDb25kaXRpb24gPSB0cnVlO1xuICAgIH1cblxuICAgIGlmICghaGFzQ29uZGl0aW9uKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCBbdW5pcXVlRm91bmRdID0gYXdhaXQgdW5pcXVlUXVlcnk7XG4gICAgcmV0dXJuIHVuaXF1ZUZvdW5kO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBjaGVja0R1cGxpY2F0ZUJ5Q29sdW1ucyhcbiAgICBkYjogS25leCxcbiAgICBlbnRpdHk6IEVudGl0eSxcbiAgICBmaXh0dXJlOiBGaXh0dXJlUmVjb3JkLFxuICAgIGNvbHVtbnM6IHN0cmluZ1tdLFxuICApIHtcbiAgICBpZiAoY29sdW1ucy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IHdoZXJlQ2xhdXNlOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9O1xuXG4gICAgZm9yIChjb25zdCBjb2x1bW4gb2YgY29sdW1ucykge1xuICAgICAgLy8gcmVsYXRpb24g7ZWE65Oc7J24IOqyveyasCBfaWQg67aZ7J206riwXG4gICAgICBjb25zdCBwcm9wID0gZW50aXR5LnByb3BzLmZpbmQoKHApID0+IHAubmFtZSA9PT0gY29sdW1uKTtcbiAgICAgIGNvbnN0IGRiQ29sdW1uID0gcHJvcCAmJiBpc1JlbGF0aW9uUHJvcChwcm9wKSA/IGAke2NvbHVtbn1faWRgIDogY29sdW1uO1xuICAgICAgY29uc3QgdmFsdWUgPSBmaXh0dXJlLmNvbHVtbnNbY29sdW1uXT8udmFsdWU7XG5cbiAgICAgIC8vIG51bGwg6rCS7J20IO2PrO2VqOuQnCDqsr3smrAg7KSR67O1IO2ZleyduCDsiqTtgrVcbiAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuXG4gICAgICB3aGVyZUNsYXVzZVtkYkNvbHVtbl0gPSB2YWx1ZTtcbiAgICB9XG5cbiAgICBjb25zdCBbZm91bmRdID0gYXdhaXQgZGIoZW50aXR5LnRhYmxlKS53aGVyZSh3aGVyZUNsYXVzZSkubGltaXQoMSk7XG4gICAgcmV0dXJuIGZvdW5kO1xuICB9XG5cbiAgYXN5bmMgYWRkRml4dHVyZUxvYWRlcihjb2RlOiBzdHJpbmcpIHtcbiAgICBjb25zdCBwYXRoID0gYCR7U29uYW11LmFwaVJvb3RQYXRofS9zcmMvdGVzdGluZy9maXh0dXJlLnRzYDtcbiAgICBjb25zdCBjb250ZW50ID0gcmVhZEZpbGVTeW5jKHBhdGgpLnRvU3RyaW5nKCk7XG5cbiAgICBjb25zdCBmaXh0dXJlTG9hZGVyU3RhcnQgPSBjb250ZW50LmluZGV4T2YoXCJjb25zdCBmaXh0dXJlTG9hZGVyID0ge1wiKTtcbiAgICBjb25zdCBmaXh0dXJlTG9hZGVyRW5kID0gY29udGVudC5pbmRleE9mKFwifTtcIiwgZml4dHVyZUxvYWRlclN0YXJ0KTtcblxuICAgIGlmIChmaXh0dXJlTG9hZGVyU3RhcnQgIT09IC0xICYmIGZpeHR1cmVMb2FkZXJFbmQgIT09IC0xKSB7XG4gICAgICBjb25zdCBuZXdDb250ZW50ID0gYCR7Y29udGVudC5zbGljZSgwLCBmaXh0dXJlTG9hZGVyRW5kKX0gICR7Y29kZX1cXG4ke2NvbnRlbnQuc2xpY2UoZml4dHVyZUxvYWRlckVuZCl9YDtcblxuICAgICAgd3JpdGVGaWxlU3luYyhwYXRoLCBuZXdDb250ZW50KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRmFpbGVkIHRvIGZpbmQgZml4dHVyZUxvYWRlciBpbiBmaXh0dXJlLnRzXCIpO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgY29uc3QgRml4dHVyZU1hbmFnZXIgPSBuZXcgRml4dHVyZU1hbmFnZXJDbGFzcygpO1xuIl0sIm5hbWVzIjpbImFzc2VydCIsImNoYWxrIiwiZXhlY1N5bmMiLCJyZWFkRmlsZVN5bmMiLCJ3cml0ZUZpbGVTeW5jIiwiaW5mbGVjdGlvbiIsImtuZXgiLCJ1bmlxdWUiLCJpbnNwZWN0IiwiU29uYW11IiwiQmFzZU1vZGVsIiwiVXBzZXJ0QnVpbGRlciIsIkVudGl0eU1hbmFnZXIiLCJpc0JlbG9uZ3NUb09uZVJlbGF0aW9uUHJvcCIsImlzSGFzTWFueVJlbGF0aW9uUHJvcCIsImlzTWFueVRvTWFueVJlbGF0aW9uUHJvcCIsImlzT25lVG9PbmVSZWxhdGlvblByb3AiLCJpc1JlbGF0aW9uUHJvcCIsImlzVmlydHVhbFByb3AiLCJSZWxhdGlvbkdyYXBoIiwiRml4dHVyZU1hbmFnZXJDbGFzcyIsIl90ZGIiLCJ0ZGIiLCJFcnJvciIsIl9mZGIiLCJmZGIiLCJjYWNoZWRUYWJsZU5hbWVzIiwicmVsYXRpb25HcmFwaCIsImJ1aWxkZXIiLCJmaXh0dXJlUmVmTWFwIiwiTWFwIiwidXVpZFRvRml4dHVyZUlkIiwic2tpcHBlZEZpeHR1cmVzIiwiaW5pdCIsImRiQ29uZmlnIiwidGVzdCIsInByb2R1Y3Rpb25fbWFzdGVyIiwidENvbm4iLCJjb25uZWN0aW9uIiwicENvbm4iLCJob3N0IiwicG9ydCIsImRhdGFiYXNlIiwiZml4dHVyZV9yZW1vdGUiLCJnZXRDaGVja3N1bSIsImRiIiwidGFibGVOYW1lIiwiY2hlY2tzdW1Sb3ciLCJyYXciLCJDaGVja3N1bSIsInN5bmMiLCJmaXh0dXJlQ29ubiIsInRlc3RDb25uIiwicGdFbnYiLCJQR1BBU1NXT1JEIiwicGFzc3dvcmQiLCJ1c2VyIiwic3RkaW8iLCJlbnYiLCJwcm9jZXNzIiwidmlzaXRlZFJlY29yZHMiLCJTZXQiLCJpbXBvcnRGaXh0dXJlIiwiZW50aXR5SWQiLCJpZHMiLCJjbGVhciIsInF1ZXJpZXMiLCJQcm9taXNlIiwiYWxsIiwibWFwIiwiaWQiLCJnZXRJbXBvcnRRdWVyaWVzIiwiZmxhdCIsIndkYiIsImdldERCIiwicXVlcnkiLCJyc2giLCJjb25zb2xlIiwibG9nIiwiaW5mbyIsImZpZWxkIiwicmVjb3JkS2V5IiwiaGFzIiwiYWRkIiwiZW50aXR5IiwiZ2V0Iiwicm93IiwidGFibGUiLCJ3aGVyZSIsImxpbWl0IiwidW5kZWZpbmVkIiwiZml4dHVyZURhdGFiYXNlIiwicmVhbERhdGFiYXNlIiwic2VsZlF1ZXJ5IiwiYXJncyIsIk9iamVjdCIsImVudHJpZXMiLCJyZWxhdGlvbnMiLCJmaWx0ZXIiLCJyZWxhdGlvbiIsImN1c3RvbUpvaW5DbGF1c2UiLCJoYXNKb2luQ29sdW1uIiwicmVsYXRlZEVudGl0eSIsIndpdGgiLCJyZWxhdGVkSWRDb2x1bW5OYW1lIiwicHJvcHMiLCJmaW5kIiwicCIsIm5hbWUiLCJhcmciLCJyZWxRdWVyaWVzIiwicmV2ZXJzZSIsImRlc3Ryb3kiLCJnZXRGaXh0dXJlcyIsInNvdXJjZURCTmFtZSIsInRhcmdldERCTmFtZSIsInNlYXJjaE9wdGlvbnMiLCJkdXBsaWNhdGVDaGVjayIsInNvdXJjZURCIiwidGFyZ2V0REIiLCJ2YWx1ZSIsInNlYXJjaFR5cGUiLCJjb2x1bW4iLCJwcm9wIiwidHlwZSIsInJvd3MiLCJsZW5ndGgiLCJmaXh0dXJlcyIsImluaXRpYWxSZWNvcmRzTGVuZ3RoIiwibmV3UmVjb3JkcyIsImNyZWF0ZUZpeHR1cmVSZWNvcmQiLCJfZGIiLCJwdXNoIiwiY3VycmVudEZpeHR1cmVSZWNvcmQiLCJyIiwiZml4dHVyZUlkIiwiZmV0Y2hlZFJlY29yZHMiLCJzbGljZSIsImZpeHR1cmUiLCJjdXN0b21Db2x1bW5zIiwiY29sdW1ucyIsImN1c3RvbUR1cGxpY2F0ZVJvdyIsImNoZWNrRHVwbGljYXRlQnlDb2x1bW5zIiwicmVjb3JkIiwic2luZ2xlUmVjb3JkIiwidGFyZ2V0IiwidW5pcXVlUm93IiwiY2hlY2tVbmlxdWVWaW9sYXRpb24iLCJmIiwib3B0aW9ucyIsInJlY29yZHMiLCJ2aXNpdGVkRW50aXRpZXMiLCJjcmVhdGUiLCJiZWxvbmdzUmVjb3JkcyIsInRocm91Z2hUYWJsZSIsImpvaW5UYWJsZSIsImZyb21Db2x1bW4iLCJzaW5ndWxhcml6ZSIsInRvQ29sdW1uIiwicmVsYXRlZElkcyIsInBsdWNrIiwiam9pbkNvbHVtbiIsInJlbGF0ZWRQcm9wIiwicmVsYXRlZFJvdyIsImZpcnN0IiwicmVsYXRlZElkIiwiaW5zZXJ0Rml4dHVyZXMiLCJkYk5hbWUiLCJfZml4dHVyZXMiLCJyZXN1bHRzIiwiYnVpbGRHcmFwaCIsImluc2VydGlvbk9yZGVyIiwiZ2V0SW5zZXJ0aW9uT3JkZXIiLCJoYXNUYXJnZXQiLCJoYXNVbmlxdWUiLCJoYXNEdXBsaWNhdGUiLCJvdmVycmlkZSIsImV4aXN0aW5nSWQiLCJzZXQiLCJ5ZWxsb3ciLCJyZWdpc3RlckZpeHR1cmUiLCJibHVlIiwidGFibGVPcmRlciIsImdldFRhYmxlT3JkZXIiLCJ0cmFuc2FjdGlvbiIsInRyeCIsImluc2VydGVkSWRzQnlUYWJsZSIsImhhc1RhYmxlIiwiZ2V0VGFibGUiLCJ1dWlkcyIsInV1aWQiLCJ1cHNlcnQiLCJ1dWlkVG9JZCIsInNlbGVjdCIsIndoZXJlSW4iLCJwcm9jZXNzTWFueVRvTWFueVJlbGF0aW9ucyIsInNraXBwZWQiLCJkYXRhIiwicmVmIiwiaW5zZXJ0ZWRJZCIsImdyZWVuIiwiZXhpc3RpbmdSZWNvcmQiLCJpc092ZXJyaWRlTW9kZSIsInByb3BOYW1lIiwicmVsYXRlZEZpeHR1cmVJZCIsInNraXBwZWRFeGlzdGluZ0lkIiwicmVsYXRlZFJlZiIsImNvbnZlcnRDb2x1bW5WYWx1ZSIsInJlZ2lzdGVyIiwiRGF0ZSIsInRhYmxlcyIsInNlZW4iLCJzb3VyY2VSZWYiLCJzb3VyY2VVdWlkVG9JZCIsInNvdXJjZUlkIiwiQXJyYXkiLCJpc0FycmF5IiwidGFyZ2V0VGFibGUiLCJzb3VyY2VDb2x1bW4iLCJ0YXJnZXRDb2x1bW4iLCJ0YXJnZXRJZCIsInJlbGF0ZWRVdWlkVG9JZCIsInJlc29sdmVkSWQiLCJ3YXJuIiwiZm91bmQiLCJpbnNlcnQiLCJfdW5pcXVlSW5kZXhlcyIsImluZGV4ZXMiLCJpIiwidW5pcXVlSW5kZXhlcyIsImluZGV4IiwiZXZlcnkiLCJzdGFydHNXaXRoIiwidW5pcXVlUXVlcnkiLCJoYXNDb25kaXRpb24iLCJjb250YWluc051bGwiLCJzb21lIiwicmVwbGFjZSIsIm9yV2hlcmUiLCJxYiIsImFuZFdoZXJlIiwidW5pcXVlRm91bmQiLCJ3aGVyZUNsYXVzZSIsImRiQ29sdW1uIiwiYWRkRml4dHVyZUxvYWRlciIsImNvZGUiLCJwYXRoIiwiYXBpUm9vdFBhdGgiLCJjb250ZW50IiwidG9TdHJpbmciLCJmaXh0dXJlTG9hZGVyU3RhcnQiLCJpbmRleE9mIiwiZml4dHVyZUxvYWRlckVuZCIsIm5ld0NvbnRlbnQiLCJGaXh0dXJlTWFuYWdlciJdLCJtYXBwaW5ncyI6IkFBQUEsT0FBT0EsWUFBWSxTQUFTO0FBQzVCLE9BQU9DLFdBQVcsUUFBUTtBQUMxQixTQUFTQyxRQUFRLFFBQVEsZ0JBQWdCO0FBQ3pDLFNBQVNDLFlBQVksRUFBRUMsYUFBYSxRQUFRLEtBQUs7QUFDakQsT0FBT0MsZ0JBQWdCLGFBQWE7QUFDcEMsT0FBT0MsVUFBeUIsT0FBTztBQUN2QyxTQUFTQyxNQUFNLFFBQVEsVUFBVTtBQUNqQyxTQUFTQyxPQUFPLFFBQVEsT0FBTztBQUMvQixTQUFTQyxNQUFNLFFBQVEsa0JBQVM7QUFDaEMsU0FBU0MsU0FBUyxRQUFRLDRCQUF5QjtBQUVuRCxTQUFxQkMsYUFBYSxRQUFR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