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,16 +1,30 @@
1
- import { DateTime } from "luxon";
2
- import { chunk, groupBy, isObject, omit, set, uniq } from "lodash-es";
3
- import { DB } from "./db.js";
4
- import { isCustomJoinClause } from "../types/types.js";
1
+ import assert from "assert";
5
2
  import inflection from "inflection";
6
- import chalk from "chalk";
7
- import { UpsertBuilder } from "./upsert-builder.js";
8
- import SqlParser from "node-sql-parser";
9
- import { getTableName, getTableNamesFromWhere } from "../utils/sql-parser.js";
3
+ import { group, isObject, omit, set, unique } from "radashi";
4
+ import { Sonamu } from "../api/index.js";
5
+ import { isCustomJoinClause } from "../types/types.js";
6
+ import { getJoinTables, getTableNamesFromWhere } from "../utils/sql-parser.js";
7
+ import { chunk } from "../utils/utils.js";
8
+ import { DB } from "./db.js";
9
+ import { Puri } from "./puri.js";
10
10
  import { PuriWrapper } from "./puri-wrapper.js";
11
- export class BaseModelClass {
11
+ import { UpsertBuilder } from "./upsert-builder.js";
12
+ /**
13
+ * 모든 Model 클래스의 기본 클래스
14
+ *
15
+ * @template TSubsetKey - 서브셋 키 유니온 (예: "A" | "P" | "SS")
16
+ * @template TSubsetMapping - 서브셋별 최종 결과 타입 매핑
17
+ * @template TSubsetQueries - 서브셋 쿼리 함수 객체
18
+ * @template TLoaderQueries - 서브셋별 로더 쿼리 배열 객체
19
+ */ export class BaseModelClass {
20
+ subsetQueries;
21
+ loaderQueries;
12
22
  modelName = "Unknown";
13
- /* DB 인스턴스 get, destroy */ getDB(which) {
23
+ constructor(subsetQueries, loaderQueries){
24
+ this.subsetQueries = subsetQueries;
25
+ this.loaderQueries = loaderQueries;
26
+ }
27
+ getDB(which) {
14
28
  return DB.getDB(which);
15
29
  }
16
30
  getPuri(which) {
@@ -26,16 +40,13 @@ export class BaseModelClass {
26
40
  async destroy() {
27
41
  return DB.destroy();
28
42
  }
29
- myNow(timestamp) {
30
- const dt = timestamp === undefined ? DateTime.local() : DateTime.fromSeconds(timestamp);
31
- return dt.toFormat("yyyy-MM-dd HH:mm:ss");
32
- }
33
43
  async getInsertedIds(wdb, rows, tableName, unqKeyFields, chunkSize = 500) {
34
44
  if (!wdb) {
35
45
  wdb = this.getDB("w");
36
46
  }
37
47
  let unqKeys;
38
- let whereInField, selectField;
48
+ let whereInField;
49
+ let selectField;
39
50
  if (unqKeyFields.length > 1) {
40
51
  whereInField = wdb.raw(`CONCAT_WS('_', '${unqKeyFields.join(",")}')`);
41
52
  selectField = `${whereInField} as tmpUid`;
@@ -45,96 +56,175 @@ export class BaseModelClass {
45
56
  selectField = unqKeyFields[0];
46
57
  unqKeys = rows.map((row)=>row[unqKeyFields[0]]);
47
58
  }
48
- const chunks = chunk(unqKeys, chunkSize);
49
59
  let resultIds = [];
50
- for (let chunk of chunks){
51
- const dbRows = await wdb(tableName).select("id", wdb.raw(selectField)).whereIn(whereInField, chunk);
52
- resultIds = resultIds.concat(dbRows.map((dbRow)=>parseInt(dbRow.id)));
60
+ for (const items of chunk(unqKeys, chunkSize)){
61
+ const dbRows = await wdb(tableName).select("id", wdb.raw(selectField)).whereIn(whereInField, items);
62
+ resultIds = resultIds.concat(dbRows.map((dbRow)=>parseInt(String(dbRow.id))));
53
63
  }
54
64
  return resultIds;
55
65
  }
56
- async useLoaders(db, rows, loaders) {
57
- if (loaders.length === 0) {
58
- return rows;
66
+ /**
67
+ * 특정 서브셋에 대한 쿼리 빌더 획득
68
+ *
69
+ * @returns qb - 쿼리 빌더 (조건 추가용)
70
+ * @returns onSubset - 특정 서브셋 전용 타입이 필요할 때 사용
71
+ */ getSubsetQueries(subset) {
72
+ if (!this.subsetQueries) {
73
+ throw new Error("subsetQueries is not defined");
59
74
  }
60
- for (let loader of loaders){
61
- let subQ;
62
- let subRows;
63
- let toCol;
64
- const fromIds = rows.map((row)=>row[loader.manyJoin.idField]);
65
- if (loader.manyJoin.through === undefined) {
66
- // HasMany
67
- const idColumn = `${loader.manyJoin.toTable}.${loader.manyJoin.toCol}`;
68
- subQ = db(loader.manyJoin.toTable).whereIn(idColumn, fromIds).select([
69
- ...loader.select,
70
- idColumn
71
- ]);
72
- // HasMany에서 OneJoin이 있는 경우
73
- loader.oneJoins.map((join)=>{
74
- if (join.join == "inner") {
75
- subQ.innerJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
76
- } else if (join.join == "outer") {
77
- subQ.leftOuterJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
78
- }
79
- });
80
- toCol = loader.manyJoin.toCol;
81
- } else {
82
- // ManyToMany
83
- const idColumn = `${loader.manyJoin.through.table}.${loader.manyJoin.through.fromCol}`;
84
- subQ = db(loader.manyJoin.through.table).join(loader.manyJoin.toTable, `${loader.manyJoin.through.table}.${loader.manyJoin.through.toCol}`, `${loader.manyJoin.toTable}.${loader.manyJoin.toCol}`).whereIn(idColumn, fromIds).select(uniq([
85
- ...loader.select,
86
- idColumn
87
- ]));
88
- // ManyToMany에서 OneJoin이 있는 경우
89
- loader.oneJoins.map((join)=>{
90
- if (join.join == "inner") {
91
- subQ.innerJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
92
- } else if (join.join == "outer") {
93
- subQ.leftOuterJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
94
- }
95
- });
96
- toCol = loader.manyJoin.through.fromCol;
75
+ const puriWrapper = new PuriWrapper(this.getDB("r"), new UpsertBuilder());
76
+ const qb = this.subsetQueries[subset]?.(puriWrapper);
77
+ return {
78
+ qb: qb,
79
+ onSubset: (_subset)=>qb
80
+ };
81
+ }
82
+ /**
83
+ * Enhancer 객체 생성 헬퍼
84
+ * 타입 검증 및 추론을 도와줌
85
+ */ createEnhancers(enhancers) {
86
+ return enhancers;
87
+ }
88
+ /**
89
+ * 서브셋 쿼리 실행
90
+ *
91
+ * 1. 쿼리 실행 (pagination 적용)
92
+ * 2. 로더 실행 (1:N, N:M 관계 데이터 로딩)
93
+ * 3. Hydrate (flat → 중첩 객체)
94
+ * 4. Enhancer 적용 (virtual 필드 계산)
95
+ */ async executeSubsetQuery(params) {
96
+ const { subset, qb, params: queryParams, debug = false, optimizeCountQuery = false } = params;
97
+ if (!this.loaderQueries) {
98
+ throw new Error("loaderQueries is not defined");
99
+ }
100
+ if (!queryParams.num || !queryParams.page) {
101
+ throw new Error("num and page are required");
102
+ }
103
+ const { num, page } = queryParams;
104
+ // COUNT 쿼리 실행
105
+ const total = await this.executeCountQuery(qb, queryParams, debug, optimizeCountQuery);
106
+ // LIST 쿼리 실행
107
+ const computedRows = await this.executeListQuery(subset, qb, queryParams, num, page, debug);
108
+ // Enhancer 적용
109
+ const enhancer = params.enhancers?.[subset];
110
+ const rows = await Promise.all(computedRows.map((row)=>enhancer?.(row) ?? row));
111
+ return {
112
+ rows,
113
+ total
114
+ };
115
+ }
116
+ /**
117
+ * COUNT 쿼리 실행 (내부 메서드)
118
+ */ async executeCountQuery(qb, params, debug, optimizeCountQuery) {
119
+ if (params.queryMode === "list") {
120
+ return 0;
121
+ }
122
+ const countPuri = qb.clone().clear("order").clear("limit").clear("offset");
123
+ if (optimizeCountQuery) {
124
+ const { default: SqlParser } = await import("node-sql-parser");
125
+ const parser = new SqlParser.Parser();
126
+ const parsedQuery = parser.astify(countPuri.toQuery(), {
127
+ database: Sonamu.config.database.database
128
+ });
129
+ const leftJoinTables = getJoinTables(parsedQuery, [
130
+ "LEFT JOIN"
131
+ ]);
132
+ const whereTables = getTableNamesFromWhere(parsedQuery);
133
+ const tablesToRemove = leftJoinTables.filter((j)=>!whereTables.includes(j));
134
+ tablesToRemove.forEach((table)=>{
135
+ countPuri.clearJoin(table);
136
+ });
137
+ }
138
+ // COUNT(*)로 전체 레코드 수를 계산
139
+ // TODO: qb의 DISTINCT가 있는 경우 처리해야 함
140
+ const countResult = await countPuri.clear("select").select({
141
+ total: Puri.rawNumber(`COUNT(*)::integer`)
142
+ }).first();
143
+ if (debug) {
144
+ countPuri.debug();
145
+ }
146
+ return countResult?.total ?? 0;
147
+ }
148
+ /**
149
+ * LIST 쿼리 실행 (내부 메서드)
150
+ */ async executeListQuery(subset, qb, params, num, page, debug) {
151
+ if (params.queryMode === "count") {
152
+ return [];
153
+ }
154
+ let unloadedRows = await qb.limit(num).offset(num * (page - 1));
155
+ if (debug) {
156
+ qb.debug();
157
+ }
158
+ // 로더 처리
159
+ const loaders = this.loaderQueries[subset];
160
+ if (loaders && Array.isArray(loaders)) {
161
+ unloadedRows = await this.processLoaders(unloadedRows, loaders, debug);
162
+ }
163
+ return this.hydrate(unloadedRows);
164
+ }
165
+ /**
166
+ * 재귀적 로더 처리
167
+ */ async processLoaders(rows, loaders, debug) {
168
+ for (const resolveLoader of loaders){
169
+ const { as, refId, qb: resolveLoaderQbFn, loaders: nestedLoaders } = resolveLoader;
170
+ const resolveLoaderQb = resolveLoaderQbFn(new PuriWrapper(this.getDB("r"), new UpsertBuilder()), rows.map((row)=>row[refId]));
171
+ if (debug) {
172
+ resolveLoaderQb.debug();
97
173
  }
98
- subRows = await subQ;
99
- if (loader.loaders) {
100
- // 추가 -Many 케이스가 있는 경우 recursion 처리
101
- subRows = await this.useLoaders(db, subRows, loader.loaders);
174
+ let loadedRows = await resolveLoaderQb;
175
+ // 중첩 loaders 있으면 재귀 처리
176
+ if (nestedLoaders && nestedLoaders.length > 0) {
177
+ loadedRows = await this.processLoaders(loadedRows, nestedLoaders, debug);
102
178
  }
103
- // 불러온 row들을 참조ID 기준으로 분류 배치
104
- const subRowGroups = groupBy(subRows, toCol);
179
+ const subRowGroups = group(loadedRows, (row)=>row.refId);
105
180
  rows = rows.map((row)=>{
106
- row[loader.as] = (subRowGroups[row[loader.manyJoin.idField]] ?? []).map((r)=>omit(r, toCol));
181
+ row[as] = (subRowGroups[row[refId]] ?? []).map((r)=>omit(r, [
182
+ "refId"
183
+ ]));
107
184
  return row;
108
185
  });
109
186
  }
110
187
  return rows;
111
188
  }
112
- hydrate(rows) {
189
+ /**
190
+ * Flat 레코드를 중첩 객체로 변환
191
+ *
192
+ * - `user__name` → `{ user: { name } }`
193
+ * - nullable relation의 경우 모든 필드가 null이면 객체 자체를 null로
194
+ */ hydrate(rows) {
113
195
  return rows.map((row)=>{
114
- // nullable relation 경우 관련된 필드가 전부 null 생성되는 것 방지하는 코드
196
+ // nullable relation 처리: 관련 필드가 전부 null 경우 방지
115
197
  const nestedKeys = Object.keys(row).filter((key)=>key.includes("__"));
116
- const groups = groupBy(nestedKeys, (key)=>key.split("__")[0]);
117
- const nullKeys = Object.keys(groups).filter((key)=>groups[key].length > 1 && groups[key].every((field)=>row[field] === null || Array.isArray(row[field]) && row[field].length === 0));
198
+ const groups = Object.groupBy(nestedKeys, (key)=>key.split("__")[0]);
199
+ const nullKeys = Object.entries(groups).filter(([_, data])=>data && data.length > 1 && data.every((field)=>row[field] === null || Array.isArray(row[field]) && row[field].length === 0)).map(([key])=>key);
118
200
  const hydrated = Object.keys(row).reduce((r, field)=>{
119
201
  if (!field.includes("__")) {
202
+ // 일반 필드: 배열 내 객체면 재귀 hydrate
120
203
  if (Array.isArray(row[field]) && isObject(row[field][0])) {
121
204
  r[field] = this.hydrate(row[field]);
122
- return r;
123
205
  } else {
124
206
  r[field] = row[field];
125
- return r;
126
207
  }
208
+ return r;
127
209
  }
210
+ // 중첩 필드 처리: user__name → user[name]
128
211
  const parts = field.split("__");
129
212
  const objPath = parts[0] + parts.slice(1).map((part)=>`[${part}]`).join("");
130
- set(r, objPath, row[field] && Array.isArray(row[field]) && isObject(row[field][0]) ? this.hydrate(row[field]) : row[field]);
213
+ r = set(r, objPath, row[field] && Array.isArray(row[field]) && isObject(row[field][0]) ? this.hydrate(row[field]) : row[field]);
131
214
  return r;
132
215
  }, {});
133
- nullKeys.map((nullKey)=>hydrated[nullKey] = null);
216
+ // null relation 처리
217
+ nullKeys.forEach((nullKey)=>{
218
+ hydrated[nullKey] = null;
219
+ });
134
220
  return hydrated;
135
221
  });
136
222
  }
223
+ // Legacy SubsetQuery 실행 (Puri 도입 전 호환용)
137
224
  async runSubsetQuery({ params, baseTable, subset, subsetQuery, build, afterBuild, debug, db: _db, optimizeCountQuery }) {
225
+ const chalk = (await import("chalk")).default;
226
+ const SqlParser = (await import("node-sql-parser")).default;
227
+ const { getTableName, getTableNamesFromWhere } = await import("../utils/sql-parser.js");
138
228
  const db = _db ?? this.getDB(subset.startsWith("A") ? "w" : "r");
139
229
  baseTable = baseTable ?? inflection.pluralize(inflection.underscore(this.modelName));
140
230
  const queryMode = params.queryMode ?? (params.id !== undefined ? "list" : "both");
@@ -147,10 +237,10 @@ export class BaseModelClass {
147
237
  virtual
148
238
  });
149
239
  const applyJoinClause = (qb, joins)=>{
150
- joins.map((join)=>{
151
- if (join.join == "inner") {
240
+ joins.forEach((join)=>{
241
+ if (join.join === "inner") {
152
242
  qb.innerJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
153
- } else if (join.join == "outer") {
243
+ } else if (join.join === "outer") {
154
244
  qb.leftOuterJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
155
245
  }
156
246
  });
@@ -162,12 +252,12 @@ export class BaseModelClass {
162
252
  }
163
253
  const clonedQb = qb.clone().clear("order").clear("offset").clear("limit");
164
254
  const parser = new SqlParser.Parser();
165
- // optmizeCountQuery가 true인 경우 다른 clause에 영향을 주지 않는 모든 join을 제외함
166
255
  if (optimizeCountQuery) {
167
- const parsedQuery = parser.astify(clonedQb.toQuery());
256
+ const parsedQuery = parser.astify(clonedQb.toQuery(), {
257
+ database: Sonamu.config.database.database
258
+ });
168
259
  const tables = getTableNamesFromWhere(parsedQuery);
169
- // where절에 사용되는 테이블의 조인을 위해 사용되는 테이블
170
- const needToJoin = uniq(tables.flatMap((table)=>table.split("__").map((t)=>inflection.pluralize(t))));
260
+ const needToJoin = unique(tables.flatMap((table)=>table.split("__").map((t)=>inflection.pluralize(t))));
171
261
  applyJoinClause(clonedQb, joins.filter((j)=>needToJoin.includes(j.table)));
172
262
  } else {
173
263
  applyJoinClause(clonedQb, joins);
@@ -179,7 +269,9 @@ export class BaseModelClass {
179
269
  joins,
180
270
  virtual
181
271
  }) ?? clonedQb;
182
- const parsedQuery = parser.astify(processedQb.toQuery());
272
+ const parsedQuery = parser.astify(processedQb.toQuery(), {
273
+ database: Sonamu.config.database.database
274
+ });
183
275
  const q = Array.isArray(parsedQuery) ? parsedQuery[0] : parsedQuery;
184
276
  if (q.type !== "select") {
185
277
  throw new Error("Invalid query");
@@ -188,7 +280,6 @@ export class BaseModelClass {
188
280
  as: "total"
189
281
  }).first();
190
282
  const countRow = await countQuery;
191
- // debug: countQuery
192
283
  if (debug === true || debug === "count") {
193
284
  console.debug("DEBUG: count query", chalk.blue(countQuery.toQuery().toString()));
194
285
  }
@@ -199,14 +290,12 @@ export class BaseModelClass {
199
290
  if (queryMode === "count") {
200
291
  return [];
201
292
  }
202
- // limit, offset
203
293
  if (params.num !== 0) {
294
+ assert(params.num);
204
295
  qb.limit(params.num);
205
- qb.offset(params.num * (params.page - 1));
296
+ qb.offset(params.num * ((params.page ?? 1) - 1));
206
297
  }
207
- // select, rows
208
298
  const clonedQb = qb.clone().select(select);
209
- // join
210
299
  applyJoinClause(clonedQb, joins);
211
300
  const listQuery = afterBuild?.({
212
301
  qb: clonedQb,
@@ -216,7 +305,6 @@ export class BaseModelClass {
216
305
  virtual
217
306
  }) ?? clonedQb;
218
307
  let rows = await listQuery;
219
- // debug: listQuery
220
308
  if (debug === true || debug === "list") {
221
309
  console.debug("DEBUG: list query", chalk.blue(listQuery.toQuery().toString()));
222
310
  }
@@ -231,6 +319,61 @@ export class BaseModelClass {
231
319
  qb
232
320
  };
233
321
  }
322
+ // Legacy Loader 처리 (Puri 도입 전 호환용)
323
+ async useLoaders(db, rows, loaders) {
324
+ if (loaders.length === 0) {
325
+ return rows;
326
+ }
327
+ for (const loader of loaders){
328
+ let subQ;
329
+ let subRows;
330
+ let toCol;
331
+ const fromIds = rows.map((row)=>row[loader.manyJoin.idField]);
332
+ if (loader.manyJoin.through === undefined) {
333
+ // HasMany
334
+ const idColumn = `${loader.manyJoin.toTable}.${loader.manyJoin.toCol}`;
335
+ subQ = db(loader.manyJoin.toTable).whereIn(idColumn, fromIds).select([
336
+ ...loader.select,
337
+ idColumn
338
+ ]);
339
+ loader.oneJoins.forEach((join)=>{
340
+ if (join.join === "inner") {
341
+ subQ.innerJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
342
+ } else if (join.join === "outer") {
343
+ subQ.leftOuterJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
344
+ }
345
+ });
346
+ toCol = loader.manyJoin.toCol;
347
+ } else {
348
+ // ManyToMany
349
+ const idColumn = `${loader.manyJoin.through.table}.${loader.manyJoin.through.fromCol}`;
350
+ subQ = db(loader.manyJoin.through.table).join(loader.manyJoin.toTable, `${loader.manyJoin.through.table}.${loader.manyJoin.through.toCol}`, `${loader.manyJoin.toTable}.${loader.manyJoin.toCol}`).whereIn(idColumn, fromIds).select(unique([
351
+ ...loader.select,
352
+ idColumn
353
+ ]));
354
+ loader.oneJoins.forEach((join)=>{
355
+ if (join.join === "inner") {
356
+ subQ.innerJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
357
+ } else if (join.join === "outer") {
358
+ subQ.leftOuterJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
359
+ }
360
+ });
361
+ toCol = loader.manyJoin.through.fromCol;
362
+ }
363
+ subRows = await subQ;
364
+ if (loader.loaders) {
365
+ subRows = await this.useLoaders(db, subRows, loader.loaders);
366
+ }
367
+ const subRowGroups = group(subRows, (row)=>row[toCol]);
368
+ rows = rows.map((row)=>{
369
+ row[loader.as] = (subRowGroups[row[loader.manyJoin.idField]] ?? []).map((r)=>omit(r, [
370
+ toCol
371
+ ]));
372
+ return row;
373
+ });
374
+ }
375
+ return rows;
376
+ }
234
377
  getJoinClause(db, join) {
235
378
  if (!isCustomJoinClause(join)) {
236
379
  return db.raw(`${join.from} = ${join.to}`);
@@ -244,4 +387,4 @@ export class BaseModelClass {
244
387
  }
245
388
  export const BaseModel = new BaseModelClass();
246
389
 
247
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYXRhYmFzZS9iYXNlLW1vZGVsLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERhdGVUaW1lIH0gZnJvbSBcImx1eG9uXCI7XG5pbXBvcnQgeyBLbmV4IH0gZnJvbSBcImtuZXhcIjtcbmltcG9ydCB7IGNodW5rLCBncm91cEJ5LCBpc09iamVjdCwgb21pdCwgc2V0LCB1bmlxIH0gZnJvbSBcImxvZGFzaC1lc1wiO1xuaW1wb3J0IHsgREJQcmVzZXQsIERCIH0gZnJvbSBcIi4vZGJcIjtcbmltcG9ydCB7IGlzQ3VzdG9tSm9pbkNsYXVzZSwgdHlwZSBTdWJzZXRRdWVyeSB9IGZyb20gXCIuLi90eXBlcy90eXBlc1wiO1xuaW1wb3J0IHR5cGUgeyBCYXNlTGlzdFBhcmFtcyB9IGZyb20gXCIuLi91dGlscy9tb2RlbFwiO1xuaW1wb3J0IGluZmxlY3Rpb24gZnJvbSBcImluZmxlY3Rpb25cIjtcbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIjtcbmltcG9ydCB7IFVwc2VydEJ1aWxkZXIgfSBmcm9tIFwiLi91cHNlcnQtYnVpbGRlclwiO1xuaW1wb3J0IFNxbFBhcnNlciBmcm9tIFwibm9kZS1zcWwtcGFyc2VyXCI7XG5pbXBvcnQgeyBnZXRUYWJsZU5hbWUsIGdldFRhYmxlTmFtZXNGcm9tV2hlcmUgfSBmcm9tIFwiLi4vdXRpbHMvc3FsLXBhcnNlclwiO1xuaW1wb3J0IHsgUHVyaVdyYXBwZXIgfSBmcm9tIFwiLi9wdXJpLXdyYXBwZXJcIjtcblxuZXhwb3J0IGNsYXNzIEJhc2VNb2RlbENsYXNzIHtcbiAgcHVibGljIG1vZGVsTmFtZTogc3RyaW5nID0gXCJVbmtub3duXCI7XG5cbiAgLyogREIg7J247Iqk7YS07IqkIGdldCwgZGVzdHJveSAqL1xuICBnZXREQih3aGljaDogREJQcmVzZXQpOiBLbmV4IHtcbiAgICByZXR1cm4gREIuZ2V0REIod2hpY2gpO1xuICB9XG5cbiAgZ2V0UHVyaSh3aGljaDogREJQcmVzZXQpOiBQdXJpV3JhcHBlciB7XG4gICAgLy8g7Yq4656c7J6t7IWYIOy7qO2FjeyKpO2KuOyXkOyEnCDtirjrnpzsnq3shZgg7ZqN65OdXG4gICAgY29uc3QgdHJ4ID0gREIuZ2V0VHJhbnNhY3Rpb25Db250ZXh0KCkuZ2V0VHJhbnNhY3Rpb24od2hpY2gpO1xuICAgIGlmICh0cngpIHtcbiAgICAgIHJldHVybiB0cng7XG4gICAgfVxuXG4gICAgLy8g7Yq4656c7J6t7IWY7J20IOyXhuycvOuptCDsg4jroZzsmrQgUHVyaVdyYXBwZXIg67CY7ZmYXG4gICAgY29uc3QgZGIgPSB0aGlzLmdldERCKHdoaWNoKTtcbiAgICByZXR1cm4gbmV3IFB1cmlXcmFwcGVyKGRiLCB0aGlzLmdldFVwc2VydEJ1aWxkZXIoKSk7XG4gIH1cblxuICBhc3luYyBkZXN0cm95KCkge1xuICAgIHJldHVybiBEQi5kZXN0cm95KCk7XG4gIH1cblxuICBteU5vdyh0aW1lc3RhbXA/OiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGNvbnN0IGR0OiBEYXRlVGltZSA9XG4gICAgICB0aW1lc3RhbXAgPT09IHVuZGVmaW5lZFxuICAgICAgICA/IERhdGVUaW1lLmxvY2FsKClcbiAgICAgICAgOiBEYXRlVGltZS5mcm9tU2Vjb25kcyh0aW1lc3RhbXApO1xuICAgIHJldHVybiBkdC50b0Zvcm1hdChcInl5eXktTU0tZGQgSEg6bW06c3NcIik7XG4gIH1cblxuICBhc3luYyBnZXRJbnNlcnRlZElkcyhcbiAgICB3ZGI6IEtuZXgsXG4gICAgcm93czogYW55W10sXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgdW5xS2V5RmllbGRzOiBzdHJpbmdbXSxcbiAgICBjaHVua1NpemU6IG51bWJlciA9IDUwMFxuICApIHtcbiAgICBpZiAoIXdkYikge1xuICAgICAgd2RiID0gdGhpcy5nZXREQihcIndcIik7XG4gICAgfVxuXG4gICAgbGV0IHVucUtleXM6IHN0cmluZ1tdO1xuICAgIGxldCB3aGVyZUluRmllbGQ6IGFueSwgc2VsZWN0RmllbGQ6IHN0cmluZztcbiAgICBpZiAodW5xS2V5RmllbGRzLmxlbmd0aCA+IDEpIHtcbiAgICAgIHdoZXJlSW5GaWVsZCA9IHdkYi5yYXcoYENPTkNBVF9XUygnXycsICcke3VucUtleUZpZWxkcy5qb2luKFwiLFwiKX0nKWApO1xuICAgICAgc2VsZWN0RmllbGQgPSBgJHt3aGVyZUluRmllbGR9IGFzIHRtcFVpZGA7XG4gICAgICB1bnFLZXlzID0gcm93cy5tYXAoKHJvdykgPT5cbiAgICAgICAgdW5xS2V5RmllbGRzLm1hcCgoZmllbGQpID0+IHJvd1tmaWVsZF0pLmpvaW4oXCJfXCIpXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICB3aGVyZUluRmllbGQgPSB1bnFLZXlGaWVsZHNbMF07XG4gICAgICBzZWxlY3RGaWVsZCA9IHVucUtleUZpZWxkc1swXTtcbiAgICAgIHVucUtleXMgPSByb3dzLm1hcCgocm93KSA9PiByb3dbdW5xS2V5RmllbGRzWzBdXSk7XG4gICAgfVxuICAgIGNvbnN0IGNodW5rcyA9IGNodW5rKHVucUtleXMsIGNodW5rU2l6ZSk7XG5cbiAgICBsZXQgcmVzdWx0SWRzOiBudW1iZXJbXSA9IFtdO1xuICAgIGZvciAobGV0IGNodW5rIG9mIGNodW5rcykge1xuICAgICAgY29uc3QgZGJSb3dzID0gYXdhaXQgd2RiKHRhYmxlTmFtZSlcbiAgICAgICAgLnNlbGVjdChcImlkXCIsIHdkYi5yYXcoc2VsZWN0RmllbGQpKVxuICAgICAgICAud2hlcmVJbih3aGVyZUluRmllbGQsIGNodW5rKTtcbiAgICAgIHJlc3VsdElkcyA9IHJlc3VsdElkcy5jb25jYXQoXG4gICAgICAgIGRiUm93cy5tYXAoKGRiUm93OiBhbnkpID0+IHBhcnNlSW50KGRiUm93LmlkKSlcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdElkcztcbiAgfVxuXG4gIGFzeW5jIHVzZUxvYWRlcnMoZGI6IEtuZXgsIHJvd3M6IGFueVtdLCBsb2FkZXJzOiBTdWJzZXRRdWVyeVtcImxvYWRlcnNcIl0pIHtcbiAgICBpZiAobG9hZGVycy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiByb3dzO1xuICAgIH1cblxuICAgIGZvciAobGV0IGxvYWRlciBvZiBsb2FkZXJzKSB7XG4gICAgICBsZXQgc3ViUTogYW55O1xuICAgICAgbGV0IHN1YlJvd3M6IGFueVtdO1xuICAgICAgbGV0IHRvQ29sOiBzdHJpbmc7XG5cbiAgICAgIGNvbnN0IGZyb21JZHMgPSByb3dzLm1hcCgocm93KSA9PiByb3dbbG9hZGVyLm1hbnlKb2luLmlkRmllbGRdKTtcblxuICAgICAgaWYgKGxvYWRlci5tYW55Sm9pbi50aHJvdWdoID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgLy8gSGFzTWFueVxuICAgICAgICBjb25zdCBpZENvbHVtbiA9IGAke2xvYWRlci5tYW55Sm9pbi50b1RhYmxlfS4ke2xvYWRlci5tYW55Sm9pbi50b0NvbH1gO1xuICAgICAgICBzdWJRID0gZGIobG9hZGVyLm1hbnlKb2luLnRvVGFibGUpXG4gICAgICAgICAgLndoZXJlSW4oaWRDb2x1bW4sIGZyb21JZHMpXG4gICAgICAgICAgLnNlbGVjdChbLi4ubG9hZGVyLnNlbGVjdCwgaWRDb2x1bW5dKTtcblxuICAgICAgICAvLyBIYXNNYW557JeQ7IScIE9uZUpvaW7snbQg7J6I64qUIOqyveyasFxuICAgICAgICBsb2FkZXIub25lSm9pbnMubWFwKChqb2luKSA9PiB7XG4gICAgICAgICAgaWYgKGpvaW4uam9pbiA9PSBcImlubmVyXCIpIHtcbiAgICAgICAgICAgIHN1YlEuaW5uZXJKb2luKFxuICAgICAgICAgICAgICBgJHtqb2luLnRhYmxlfSBhcyAke2pvaW4uYXN9YCxcbiAgICAgICAgICAgICAgdGhpcy5nZXRKb2luQ2xhdXNlKGRiLCBqb2luKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGpvaW4uam9pbiA9PSBcIm91dGVyXCIpIHtcbiAgICAgICAgICAgIHN1YlEubGVmdE91dGVySm9pbihcbiAgICAgICAgICAgICAgYCR7am9pbi50YWJsZX0gYXMgJHtqb2luLmFzfWAsXG4gICAgICAgICAgICAgIHRoaXMuZ2V0Sm9pbkNsYXVzZShkYiwgam9pbilcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdG9Db2wgPSBsb2FkZXIubWFueUpvaW4udG9Db2w7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBNYW55VG9NYW55XG4gICAgICAgIGNvbnN0IGlkQ29sdW1uID0gYCR7bG9hZGVyLm1hbnlKb2luLnRocm91Z2gudGFibGV9LiR7bG9hZGVyLm1hbnlKb2luLnRocm91Z2guZnJvbUNvbH1gO1xuICAgICAgICBzdWJRID0gZGIobG9hZGVyLm1hbnlKb2luLnRocm91Z2gudGFibGUpXG4gICAgICAgICAgLmpvaW4oXG4gICAgICAgICAgICBsb2FkZXIubWFueUpvaW4udG9UYWJsZSxcbiAgICAgICAgICAgIGAke2xvYWRlci5tYW55Sm9pbi50aHJvdWdoLnRhYmxlfS4ke2xvYWRlci5tYW55Sm9pbi50aHJvdWdoLnRvQ29sfWAsXG4gICAgICAgICAgICBgJHtsb2FkZXIubWFueUpvaW4udG9UYWJsZX0uJHtsb2FkZXIubWFueUpvaW4udG9Db2x9YFxuICAgICAgICAgIClcbiAgICAgICAgICAud2hlcmVJbihpZENvbHVtbiwgZnJvbUlkcylcbiAgICAgICAgICAuc2VsZWN0KHVuaXEoWy4uLmxvYWRlci5zZWxlY3QsIGlkQ29sdW1uXSkpO1xuXG4gICAgICAgIC8vIE1hbnlUb01hbnnsl5DshJwgT25lSm9pbuydtCDsnojripQg6rK97JqwXG4gICAgICAgIGxvYWRlci5vbmVKb2lucy5tYXAoKGpvaW4pID0+IHtcbiAgICAgICAgICBpZiAoam9pbi5qb2luID09IFwiaW5uZXJcIikge1xuICAgICAgICAgICAgc3ViUS5pbm5lckpvaW4oXG4gICAgICAgICAgICAgIGAke2pvaW4udGFibGV9IGFzICR7am9pbi5hc31gLFxuICAgICAgICAgICAgICB0aGlzLmdldEpvaW5DbGF1c2UoZGIsIGpvaW4pXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gZWxzZSBpZiAoam9pbi5qb2luID09IFwib3V0ZXJcIikge1xuICAgICAgICAgICAgc3ViUS5sZWZ0T3V0ZXJKb2luKFxuICAgICAgICAgICAgICBgJHtqb2luLnRhYmxlfSBhcyAke2pvaW4uYXN9YCxcbiAgICAgICAgICAgICAgdGhpcy5nZXRKb2luQ2xhdXNlKGRiLCBqb2luKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0b0NvbCA9IGxvYWRlci5tYW55Sm9pbi50aHJvdWdoLmZyb21Db2w7XG4gICAgICB9XG4gICAgICBzdWJSb3dzID0gYXdhaXQgc3ViUTtcblxuICAgICAgaWYgKGxvYWRlci5sb2FkZXJzKSB7XG4gICAgICAgIC8vIOy2lOqwgCAtTWFueSDsvIDsnbTsiqTqsIAg7J6I64qUIOqyveyasCByZWN1cnNpb24g7LKY66asXG4gICAgICAgIHN1YlJvd3MgPSBhd2FpdCB0aGlzLnVzZUxvYWRlcnMoZGIsIHN1YlJvd3MsIGxvYWRlci5sb2FkZXJzKTtcbiAgICAgIH1cblxuICAgICAgLy8g67aI65+s7JioIHJvd+uTpOydhCDssLjsobBJRCDquLDspIDsnLzroZwg67aE66WYIOuwsOy5mFxuICAgICAgY29uc3Qgc3ViUm93R3JvdXBzID0gZ3JvdXBCeShzdWJSb3dzLCB0b0NvbCk7XG4gICAgICByb3dzID0gcm93cy5tYXAoKHJvdykgPT4ge1xuICAgICAgICByb3dbbG9hZGVyLmFzXSA9IChzdWJSb3dHcm91cHNbcm93W2xvYWRlci5tYW55Sm9pbi5pZEZpZWxkXV0gPz8gW10pLm1hcChcbiAgICAgICAgICAocikgPT4gb21pdChyLCB0b0NvbClcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHJvdztcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gcm93cztcbiAgfVxuXG4gIGh5ZHJhdGU8VD4ocm93czogVFtdKTogVFtdIHtcbiAgICByZXR1cm4gcm93cy5tYXAoKHJvdzogYW55KSA9PiB7XG4gICAgICAvLyBudWxsYWJsZSByZWxhdGlvbuyduCDqsr3smrAg6rSA66Co65CcIO2VhOuTnOqwgCDsoITrtoAgbnVsbOuhnCDsg53shLHrkJjripQg6rKDIOuwqeyngO2VmOuKlCDsvZTrk5xcbiAgICAgIGNvbnN0IG5lc3RlZEtleXMgPSBPYmplY3Qua2V5cyhyb3cpLmZpbHRlcigoa2V5KSA9PiBrZXkuaW5jbHVkZXMoXCJfX1wiKSk7XG4gICAgICBjb25zdCBncm91cHMgPSBncm91cEJ5KG5lc3RlZEtleXMsIChrZXkpID0+IGtleS5zcGxpdChcIl9fXCIpWzBdKTtcbiAgICAgIGNvbnN0IG51bGxLZXlzID0gT2JqZWN0LmtleXMoZ3JvdXBzKS5maWx0ZXIoXG4gICAgICAgIChrZXkpID0+XG4gICAgICAgICAgZ3JvdXBzW2tleV0ubGVuZ3RoID4gMSAmJlxuICAgICAgICAgIGdyb3Vwc1trZXldLmV2ZXJ5KFxuICAgICAgICAgICAgKGZpZWxkKSA9PlxuICAgICAgICAgICAgICByb3dbZmllbGRdID09PSBudWxsIHx8XG4gICAgICAgICAgICAgIChBcnJheS5pc0FycmF5KHJvd1tmaWVsZF0pICYmIHJvd1tmaWVsZF0ubGVuZ3RoID09PSAwKVxuICAgICAgICAgIClcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IGh5ZHJhdGVkID0gT2JqZWN0LmtleXMocm93KS5yZWR1Y2UoKHIsIGZpZWxkKSA9PiB7XG4gICAgICAgIGlmICghZmllbGQuaW5jbHVkZXMoXCJfX1wiKSkge1xuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHJvd1tmaWVsZF0pICYmIGlzT2JqZWN0KHJvd1tmaWVsZF1bMF0pKSB7XG4gICAgICAgICAgICByW2ZpZWxkXSA9IHRoaXMuaHlkcmF0ZShyb3dbZmllbGRdKTtcbiAgICAgICAgICAgIHJldHVybiByO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByW2ZpZWxkXSA9IHJvd1tmaWVsZF07XG4gICAgICAgICAgICByZXR1cm4gcjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwYXJ0cyA9IGZpZWxkLnNwbGl0KFwiX19cIik7XG4gICAgICAgIGNvbnN0IG9ialBhdGggPVxuICAgICAgICAgIHBhcnRzWzBdICtcbiAgICAgICAgICBwYXJ0c1xuICAgICAgICAgICAgLnNsaWNlKDEpXG4gICAgICAgICAgICAubWFwKChwYXJ0KSA9PiBgWyR7cGFydH1dYClcbiAgICAgICAgICAgIC5qb2luKFwiXCIpO1xuICAgICAgICBzZXQoXG4gICAgICAgICAgcixcbiAgICAgICAgICBvYmpQYXRoLFxuICAgICAgICAgIHJvd1tmaWVsZF0gJiYgQXJyYXkuaXNBcnJheShyb3dbZmllbGRdKSAmJiBpc09iamVjdChyb3dbZmllbGRdWzBdKVxuICAgICAgICAgICAgPyB0aGlzLmh5ZHJhdGUocm93W2ZpZWxkXSlcbiAgICAgICAgICAgIDogcm93W2ZpZWxkXVxuICAgICAgICApO1xuXG4gICAgICAgIHJldHVybiByO1xuICAgICAgfSwge30gYXMgYW55KTtcbiAgICAgIG51bGxLZXlzLm1hcCgobnVsbEtleSkgPT4gKGh5ZHJhdGVkW251bGxLZXldID0gbnVsbCkpO1xuXG4gICAgICByZXR1cm4gaHlkcmF0ZWQ7XG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBydW5TdWJzZXRRdWVyeTxUIGV4dGVuZHMgQmFzZUxpc3RQYXJhbXMsIFUgZXh0ZW5kcyBzdHJpbmc+KHtcbiAgICBwYXJhbXMsXG4gICAgYmFzZVRhYmxlLFxuICAgIHN1YnNldCxcbiAgICBzdWJzZXRRdWVyeSxcbiAgICBidWlsZCxcbiAgICBhZnRlckJ1aWxkLFxuICAgIGRlYnVnLFxuICAgIGRiOiBfZGIsXG4gICAgb3B0aW1pemVDb3VudFF1ZXJ5LFxuICB9OiB7XG4gICAgc3Vic2V0OiBVO1xuICAgIHBhcmFtczogVDtcbiAgICBzdWJzZXRRdWVyeTogU3Vic2V0UXVlcnk7XG4gICAgYnVpbGQ6IChidWlsZFBhcmFtczoge1xuICAgICAgcWI6IEtuZXguUXVlcnlCdWlsZGVyO1xuICAgICAgZGI6IEtuZXg7XG4gICAgICBzZWxlY3Q6IChzdHJpbmcgfCBLbmV4LlJhdylbXTtcbiAgICAgIGpvaW5zOiBTdWJzZXRRdWVyeVtcImpvaW5zXCJdO1xuICAgICAgdmlydHVhbDogc3RyaW5nW107XG4gICAgfSkgPT4gS25leC5RdWVyeUJ1aWxkZXI7XG4gICAgYWZ0ZXJCdWlsZD86IChidWlsZFBhcmFtczoge1xuICAgICAgcWI6IEtuZXguUXVlcnlCdWlsZGVyO1xuICAgICAgZGI6IEtuZXg7XG4gICAgICBzZWxlY3Q6IChzdHJpbmcgfCBLbmV4LlJhdylbXTtcbiAgICAgIGpvaW5zOiBTdWJzZXRRdWVyeVtcImpvaW5zXCJdO1xuICAgICAgdmlydHVhbDogc3RyaW5nW107XG4gICAgfSkgPT4gS25leC5RdWVyeUJ1aWxkZXI7XG4gICAgYmFzZVRhYmxlPzogc3RyaW5nO1xuICAgIGRlYnVnPzogYm9vbGVhbiB8IFwibGlzdFwiIHwgXCJjb3VudFwiO1xuICAgIGRiPzogS25leDtcbiAgICBvcHRpbWl6ZUNvdW50UXVlcnk/OiBib29sZWFuO1xuICB9KTogUHJvbWlzZTx7XG4gICAgcm93czogYW55W107XG4gICAgdG90YWw/OiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gICAgc3Vic2V0UXVlcnk6IFN1YnNldFF1ZXJ5O1xuICAgIHFiOiBLbmV4LlF1ZXJ5QnVpbGRlcjtcbiAgfT4ge1xuICAgIGNvbnN0IGRiID0gX2RiID8/IHRoaXMuZ2V0REIoc3Vic2V0LnN0YXJ0c1dpdGgoXCJBXCIpID8gXCJ3XCIgOiBcInJcIik7XG4gICAgYmFzZVRhYmxlID1cbiAgICAgIGJhc2VUYWJsZSA/PyBpbmZsZWN0aW9uLnBsdXJhbGl6ZShpbmZsZWN0aW9uLnVuZGVyc2NvcmUodGhpcy5tb2RlbE5hbWUpKTtcbiAgICBjb25zdCBxdWVyeU1vZGUgPVxuICAgICAgcGFyYW1zLnF1ZXJ5TW9kZSA/PyAocGFyYW1zLmlkICE9PSB1bmRlZmluZWQgPyBcImxpc3RcIiA6IFwiYm90aFwiKTtcblxuICAgIGNvbnN0IHsgc2VsZWN0LCB2aXJ0dWFsLCBqb2lucywgbG9hZGVycyB9ID0gc3Vic2V0UXVlcnk7XG4gICAgY29uc3QgcWIgPSBidWlsZCh7XG4gICAgICBxYjogZGIuZnJvbShiYXNlVGFibGUpLFxuICAgICAgZGIsXG4gICAgICBzZWxlY3QsXG4gICAgICBqb2lucyxcbiAgICAgIHZpcnR1YWwsXG4gICAgfSk7XG5cbiAgICBjb25zdCBhcHBseUpvaW5DbGF1c2UgPSAoXG4gICAgICBxYjogS25leC5RdWVyeUJ1aWxkZXIsXG4gICAgICBqb2luczogU3Vic2V0UXVlcnlbXCJqb2luc1wiXVxuICAgICkgPT4ge1xuICAgICAgam9pbnMubWFwKChqb2luKSA9PiB7XG4gICAgICAgIGlmIChqb2luLmpvaW4gPT0gXCJpbm5lclwiKSB7XG4gICAgICAgICAgcWIuaW5uZXJKb2luKFxuICAgICAgICAgICAgYCR7am9pbi50YWJsZX0gYXMgJHtqb2luLmFzfWAsXG4gICAgICAgICAgICB0aGlzLmdldEpvaW5DbGF1c2UoZGIsIGpvaW4pXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIGlmIChqb2luLmpvaW4gPT0gXCJvdXRlclwiKSB7XG4gICAgICAgICAgcWIubGVmdE91dGVySm9pbihcbiAgICAgICAgICAgIGAke2pvaW4udGFibGV9IGFzICR7am9pbi5hc31gLFxuICAgICAgICAgICAgdGhpcy5nZXRKb2luQ2xhdXNlKGRiLCBqb2luKVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvLyBjb3VudFF1ZXJ5XG4gICAgY29uc3QgdG90YWwgPSBhd2FpdCAoYXN5bmMgKCkgPT4ge1xuICAgICAgaWYgKHF1ZXJ5TW9kZSA9PT0gXCJsaXN0XCIpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY2xvbmVkUWIgPSBxYi5jbG9uZSgpLmNsZWFyKFwib3JkZXJcIikuY2xlYXIoXCJvZmZzZXRcIikuY2xlYXIoXCJsaW1pdFwiKTtcbiAgICAgIGNvbnN0IHBhcnNlciA9IG5ldyBTcWxQYXJzZXIuUGFyc2VyKCk7XG5cbiAgICAgIC8vIG9wdG1pemVDb3VudFF1ZXJ56rCAIHRydWXsnbgg6rK97JqwIOuLpOuluCBjbGF1c2Xsl5Ag7JiB7Zal7J2EIOyjvOyngCDslYrripQg66qo65OgIGpvaW7snYQg7KCc7Jm47ZWoXG4gICAgICBpZiAob3B0aW1pemVDb3VudFF1ZXJ5KSB7XG4gICAgICAgIGNvbnN0IHBhcnNlZFF1ZXJ5ID0gcGFyc2VyLmFzdGlmeShjbG9uZWRRYi50b1F1ZXJ5KCkpO1xuICAgICAgICBjb25zdCB0YWJsZXMgPSBnZXRUYWJsZU5hbWVzRnJvbVdoZXJlKHBhcnNlZFF1ZXJ5KTtcbiAgICAgICAgLy8gd2hlcmXsoIjsl5Ag7IKs7Jqp65CY64qUIO2FjOydtOu4lOydmCDsobDsnbjsnYQg7JyE7ZW0IOyCrOyaqeuQmOuKlCDthYzsnbTruJRcbiAgICAgICAgY29uc3QgbmVlZFRvSm9pbiA9IHVuaXEoXG4gICAgICAgICAgdGFibGVzLmZsYXRNYXAoKHRhYmxlKSA9PlxuICAgICAgICAgICAgdGFibGUuc3BsaXQoXCJfX1wiKS5tYXAoKHQpID0+IGluZmxlY3Rpb24ucGx1cmFsaXplKHQpKVxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgICAgYXBwbHlKb2luQ2xhdXNlKFxuICAgICAgICAgIGNsb25lZFFiLFxuICAgICAgICAgIGpvaW5zLmZpbHRlcigoaikgPT4gbmVlZFRvSm9pbi5pbmNsdWRlcyhqLnRhYmxlKSlcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFwcGx5Sm9pbkNsYXVzZShjbG9uZWRRYiwgam9pbnMpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwcm9jZXNzZWRRYiA9XG4gICAgICAgIGFmdGVyQnVpbGQ/Lih7XG4gICAgICAgICAgcWI6IGNsb25lZFFiLFxuICAgICAgICAgIGRiLFxuICAgICAgICAgIHNlbGVjdCxcbiAgICAgICAgICBqb2lucyxcbiAgICAgICAgICB2aXJ0dWFsLFxuICAgICAgICB9KSA/PyBjbG9uZWRRYjtcblxuICAgICAgY29uc3QgcGFyc2VkUXVlcnkgPSBwYXJzZXIuYXN0aWZ5KHByb2Nlc3NlZFFiLnRvUXVlcnkoKSk7XG4gICAgICBjb25zdCBxID0gQXJyYXkuaXNBcnJheShwYXJzZWRRdWVyeSkgPyBwYXJzZWRRdWVyeVswXSA6IHBhcnNlZFF1ZXJ5O1xuICAgICAgaWYgKHEudHlwZSAhPT0gXCJzZWxlY3RcIikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHF1ZXJ5XCIpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjb3VudFF1ZXJ5ID1cbiAgICAgICAgcS5kaXN0aW5jdCAhPT0gbnVsbFxuICAgICAgICAgID8gY2xvbmVkUWJcbiAgICAgICAgICAgICAgLmNsZWFyKFwic2VsZWN0XCIpXG4gICAgICAgICAgICAgIC5zZWxlY3QoXG4gICAgICAgICAgICAgICAgZGIucmF3KFxuICAgICAgICAgICAgICAgICAgYENPVU5UKERJU1RJTkNUIFxcYCR7Z2V0VGFibGVOYW1lKHEuY29sdW1uc1swXS5leHByKX1cXGAuXFxgJHtxLmNvbHVtbnNbMF0uZXhwci5jb2x1bW59XFxgKSBhcyB0b3RhbGBcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgLmZpcnN0KClcbiAgICAgICAgICA6IGNsb25lZFFiLmNsZWFyKFwic2VsZWN0XCIpLmNvdW50KFwiKlwiLCB7IGFzOiBcInRvdGFsXCIgfSkuZmlyc3QoKTtcbiAgICAgIGNvbnN0IGNvdW50Um93OiB7IHRvdGFsPzogbnVtYmVyIH0gPSBhd2FpdCBjb3VudFF1ZXJ5O1xuXG4gICAgICAvLyBkZWJ1ZzogY291bnRRdWVyeVxuICAgICAgaWYgKGRlYnVnID09PSB0cnVlIHx8IGRlYnVnID09PSBcImNvdW50XCIpIHtcbiAgICAgICAgY29uc29sZS5kZWJ1ZyhcbiAgICAgICAgICBcIkRFQlVHOiBjb3VudCBxdWVyeVwiLFxuICAgICAgICAgIGNoYWxrLmJsdWUoY291bnRRdWVyeS50b1F1ZXJ5KCkudG9TdHJpbmcoKSlcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNvdW50Um93Py50b3RhbCA/PyAwO1xuICAgIH0pKCk7XG5cbiAgICAvLyBsaXN0UXVlcnlcbiAgICBjb25zdCByb3dzID0gYXdhaXQgKGFzeW5jICgpID0+IHtcbiAgICAgIGlmIChxdWVyeU1vZGUgPT09IFwiY291bnRcIikge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG5cbiAgICAgIC8vIGxpbWl0LCBvZmZzZXRcbiAgICAgIGlmIChwYXJhbXMubnVtICE9PSAwKSB7XG4gICAgICAgIHFiLmxpbWl0KHBhcmFtcy5udW0hKTtcbiAgICAgICAgcWIub2Zmc2V0KHBhcmFtcy5udW0hICogKHBhcmFtcy5wYWdlISAtIDEpKTtcbiAgICAgIH1cblxuICAgICAgLy8gc2VsZWN0LCByb3dzXG4gICAgICBjb25zdCBjbG9uZWRRYiA9IHFiLmNsb25lKCkuc2VsZWN0KHNlbGVjdCk7XG5cbiAgICAgIC8vIGpvaW5cbiAgICAgIGFwcGx5Sm9pbkNsYXVzZShjbG9uZWRRYiwgam9pbnMpO1xuXG4gICAgICBjb25zdCBsaXN0UXVlcnkgPVxuICAgICAgICBhZnRlckJ1aWxkPy4oe1xuICAgICAgICAgIHFiOiBjbG9uZWRRYixcbiAgICAgICAgICBkYixcbiAgICAgICAgICBzZWxlY3QsXG4gICAgICAgICAgam9pbnMsXG4gICAgICAgICAgdmlydHVhbCxcbiAgICAgICAgfSkgPz8gY2xvbmVkUWI7XG5cbiAgICAgIGxldCByb3dzID0gYXdhaXQgbGlzdFF1ZXJ5O1xuICAgICAgLy8gZGVidWc6IGxpc3RRdWVyeVxuICAgICAgaWYgKGRlYnVnID09PSB0cnVlIHx8IGRlYnVnID09PSBcImxpc3RcIikge1xuICAgICAgICBjb25zb2xlLmRlYnVnKFxuICAgICAgICAgIFwiREVCVUc6IGxpc3QgcXVlcnlcIixcbiAgICAgICAgICBjaGFsay5ibHVlKGxpc3RRdWVyeS50b1F1ZXJ5KCkudG9TdHJpbmcoKSlcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgcm93cyA9IGF3YWl0IHRoaXMudXNlTG9hZGVycyhkYiwgcm93cywgbG9hZGVycyk7XG4gICAgICByb3dzID0gdGhpcy5oeWRyYXRlKHJvd3MpO1xuICAgICAgcmV0dXJuIHJvd3M7XG4gICAgfSkoKTtcblxuICAgIHJldHVybiB7IHJvd3MsIHRvdGFsLCBzdWJzZXRRdWVyeSwgcWIgfTtcbiAgfVxuXG4gIGdldEpvaW5DbGF1c2UoXG4gICAgZGI6IEtuZXg8YW55LCB1bmtub3duPixcbiAgICBqb2luOiBTdWJzZXRRdWVyeVtcImpvaW5zXCJdW251bWJlcl1cbiAgKTogS25leC5SYXc8YW55PiB7XG4gICAgaWYgKCFpc0N1c3RvbUpvaW5DbGF1c2Uoam9pbikpIHtcbiAgICAgIHJldHVybiBkYi5yYXcoYCR7am9pbi5mcm9tfSA9ICR7am9pbi50b31gKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGRiLnJhdyhqb2luLmN1c3RvbSk7XG4gICAgfVxuICB9XG5cbiAgZ2V0VXBzZXJ0QnVpbGRlcigpOiBVcHNlcnRCdWlsZGVyIHtcbiAgICByZXR1cm4gbmV3IFVwc2VydEJ1aWxkZXIoKTtcbiAgfVxufVxuZXhwb3J0IGNvbnN0IEJhc2VNb2RlbCA9IG5ldyBCYXNlTW9kZWxDbGFzcygpO1xuIl0sIm5hbWVzIjpbIkRhdGVUaW1lIiwiY2h1bmsiLCJncm91cEJ5IiwiaXNPYmplY3QiLCJvbWl0Iiwic2V0IiwidW5pcSIsIkRCIiwiaXNDdXN0b21Kb2luQ2xhdXNlIiwiaW5mbGVjdGlvbiIsImNoYWxrIiwiVXBzZXJ0QnVpbGRlciIsIlNxbFBhcnNlciIsImdldFRhYmxlTmFtZSIsImdldFRhYmxlTmFtZXNGcm9tV2hlcmUiLCJQdXJpV3JhcHBlciIsIkJhc2VNb2RlbENsYXNzIiwibW9kZWxOYW1lIiwiZ2V0REIiLCJ3aGljaCIsImdldFB1cmkiLCJ0cngiLCJnZXRUcmFuc2FjdGlvbkNvbnRleHQiLCJnZXRUcmFuc2FjdGlvbiIsImRiIiwiZ2V0VXBzZXJ0QnVpbGRlciIsImRlc3Ryb3kiLCJteU5vdyIsInRpbWVzdGFtcCIsImR0IiwidW5kZWZpbmVkIiwibG9jYWwiLCJmcm9tU2Vjb25kcyIsInRvRm9ybWF0IiwiZ2V0SW5zZXJ0ZWRJZHMiLCJ3ZGIiLCJyb3dzIiwidGFibGVOYW1lIiwidW5xS2V5RmllbGRzIiwiY2h1bmtTaXplIiwidW5xS2V5cyIsIndoZXJlSW5GaWVsZCIsInNlbGVjdEZpZWxkIiwibGVuZ3RoIiwicmF3Iiwiam9pbiIsIm1hcCIsInJvdyIsImZpZWxkIiwiY2h1bmtzIiwicmVzdWx0SWRzIiwiZGJSb3dzIiwic2VsZWN0Iiwid2hlcmVJbiIsImNvbmNhdCIsImRiUm93IiwicGFyc2VJbnQiLCJpZCIsInVzZUxvYWRlcnMiLCJsb2FkZXJzIiwibG9hZGVyIiwic3ViUSIsInN1YlJvd3MiLCJ0b0NvbCIsImZyb21JZHMiLCJtYW55Sm9pbiIsImlkRmllbGQiLCJ0aHJvdWdoIiwiaWRDb2x1bW4iLCJ0b1RhYmxlIiwib25lSm9pbnMiLCJpbm5lckpvaW4iLCJ0YWJsZSIsImFzIiwiZ2V0Sm9pbkNsYXVzZSIsImxlZnRPdXRlckpvaW4iLCJmcm9tQ29sIiwic3ViUm93R3JvdXBzIiwiciIsImh5ZHJhdGUiLCJuZXN0ZWRLZXlzIiwiT2JqZWN0Iiwia2V5cyIsImZpbHRlciIsImtleSIsImluY2x1ZGVzIiwiZ3JvdXBzIiwic3BsaXQiLCJudWxsS2V5cyIsImV2ZXJ5IiwiQXJyYXkiLCJpc0FycmF5IiwiaHlkcmF0ZWQiLCJyZWR1Y2UiLCJwYXJ0cyIsIm9ialBhdGgiLCJzbGljZSIsInBhcnQiLCJudWxsS2V5IiwicnVuU3Vic2V0UXVlcnkiLCJwYXJhbXMiLCJiYXNlVGFibGUiLCJzdWJzZXQiLCJzdWJzZXRRdWVyeSIsImJ1aWxkIiwiYWZ0ZXJCdWlsZCIsImRlYnVnIiwiX2RiIiwib3B0aW1pemVDb3VudFF1ZXJ5Iiwic3RhcnRzV2l0aCIsInBsdXJhbGl6ZSIsInVuZGVyc2NvcmUiLCJxdWVyeU1vZGUiLCJ2aXJ0dWFsIiwiam9pbnMiLCJxYiIsImZyb20iLCJhcHBseUpvaW5DbGF1c2UiLCJ0b3RhbCIsImNsb25lZFFiIiwiY2xvbmUiLCJjbGVhciIsInBhcnNlciIsIlBhcnNlciIsInBhcnNlZFF1ZXJ5IiwiYXN0aWZ5IiwidG9RdWVyeSIsInRhYmxlcyIsIm5lZWRUb0pvaW4iLCJmbGF0TWFwIiwidCIsImoiLCJwcm9jZXNzZWRRYiIsInEiLCJ0eXBlIiwiRXJyb3IiLCJjb3VudFF1ZXJ5IiwiZGlzdGluY3QiLCJjb2x1bW5zIiwiZXhwciIsImNvbHVtbiIsImZpcnN0IiwiY291bnQiLCJjb3VudFJvdyIsImNvbnNvbGUiLCJibHVlIiwidG9TdHJpbmciLCJudW0iLCJsaW1pdCIsIm9mZnNldCIsInBhZ2UiLCJsaXN0UXVlcnkiLCJ0byIsImN1c3RvbSIsIkJhc2VNb2RlbCJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsUUFBUSxRQUFRLFFBQVE7QUFFakMsU0FBU0MsS0FBSyxFQUFFQyxPQUFPLEVBQUVDLFFBQVEsRUFBRUMsSUFBSSxFQUFFQyxHQUFHLEVBQUVDLElBQUksUUFBUSxZQUFZO0FBQ3RFLFNBQW1CQyxFQUFFLFFBQVEsVUFBTztBQUNwQyxTQUFTQyxrQkFBa0IsUUFBMEIsb0JBQWlCO0FBRXRFLE9BQU9DLGdCQUFnQixhQUFhO0FBQ3BDLE9BQU9DLFdBQVcsUUFBUTtBQUMxQixTQUFTQyxhQUFhLFFBQVEsc0JBQW1CO0FBQ2pELE9BQU9DLGVBQWUsa0JBQWtCO0FBQ3hDLFNBQVNDLFlBQVksRUFBRUMsc0JBQXNCLFFBQVEseUJBQXNCO0FBQzNFLFNBQVNDLFdBQVcsUUFBUSxvQkFBaUI7QUFFN0MsT0FBTyxNQUFNQztJQUNKQyxZQUFvQixVQUFVO0lBRXJDLHdCQUF3QixHQUN4QkMsTUFBTUMsS0FBZSxFQUFRO1FBQzNCLE9BQU9aLEdBQUdXLEtBQUssQ0FB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
390
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYXRhYmFzZS9iYXNlLW1vZGVsLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhc3NlcnQgZnJvbSBcImFzc2VydFwiO1xuaW1wb3J0IGluZmxlY3Rpb24gZnJvbSBcImluZmxlY3Rpb25cIjtcbmltcG9ydCB0eXBlIHsgS25leCB9IGZyb20gXCJrbmV4XCI7XG5pbXBvcnQgeyBncm91cCwgaXNPYmplY3QsIG9taXQsIHNldCwgdW5pcXVlIH0gZnJvbSBcInJhZGFzaGlcIjtcbmltcG9ydCB7IFNvbmFtdSB9IGZyb20gXCIuLi9hcGlcIjtcbmltcG9ydCB7IHR5cGUgRGF0YWJhc2VTY2hlbWFFeHRlbmQsIGlzQ3VzdG9tSm9pbkNsYXVzZSwgdHlwZSBTdWJzZXRRdWVyeSB9IGZyb20gXCIuLi90eXBlcy90eXBlc1wiO1xuaW1wb3J0IHR5cGUgeyBCYXNlTGlzdFBhcmFtcyB9IGZyb20gXCIuLi91dGlscy9tb2RlbFwiO1xuaW1wb3J0IHsgZ2V0Sm9pblRhYmxlcywgZ2V0VGFibGVOYW1lc0Zyb21XaGVyZSB9IGZyb20gXCIuLi91dGlscy9zcWwtcGFyc2VyXCI7XG5pbXBvcnQgeyBjaHVuayB9IGZyb20gXCIuLi91dGlscy91dGlsc1wiO1xuaW1wb3J0IHR5cGUge1xuICBFbmhhbmNlck1hcCxcbiAgRXhlY3V0ZVN1YnNldFF1ZXJ5UmVzdWx0LFxuICBSZXNvbHZlU3Vic2V0SW50ZXJzZWN0aW9uLFxuICBVbmlvbkV4dHJhY3RlZFRUYWJsZXMsXG59IGZyb20gXCIuL2Jhc2UtbW9kZWwudHlwZXNcIjtcbmltcG9ydCB0eXBlIHsgREJQcmVzZXQgfSBmcm9tIFwiLi9kYlwiO1xuaW1wb3J0IHsgREIgfSBmcm9tIFwiLi9kYlwiO1xuaW1wb3J0IHsgUHVyaSB9IGZyb20gXCIuL3B1cmlcIjtcbmltcG9ydCB0eXBlIHsgSW5mZXJBbGxTdWJzZXRzLCBQdXJpTG9hZGVyUXVlcmllcywgUHVyaVN1YnNldEZuIH0gZnJvbSBcIi4vcHVyaS1zdWJzZXQudHlwZXNcIjtcbmltcG9ydCB7IFB1cmlXcmFwcGVyIH0gZnJvbSBcIi4vcHVyaS13cmFwcGVyXCI7XG5pbXBvcnQgeyBVcHNlcnRCdWlsZGVyIH0gZnJvbSBcIi4vdXBzZXJ0LWJ1aWxkZXJcIjtcblxudHlwZSBVbmtub3duREJSZWNvcmQgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuLyoqXG4gKiDrqqjrk6AgTW9kZWwg7YG0656Y7Iqk7J2YIOq4sOuzuCDtgbTrnpjsiqRcbiAqXG4gKiBAdGVtcGxhdGUgVFN1YnNldEtleSAtIOyEnOu4jOyFiyDtgqQg7Jyg64uI7JioICjsmIg6IFwiQVwiIHwgXCJQXCIgfCBcIlNTXCIpXG4gKiBAdGVtcGxhdGUgVFN1YnNldE1hcHBpbmcgLSDshJzruIzshYvrs4Qg7LWc7KKFIOqysOqzvCDtg4DsnoUg66ek7ZWRXG4gKiBAdGVtcGxhdGUgVFN1YnNldFF1ZXJpZXMgLSDshJzruIzshYsg7L+866asIO2VqOyImCDqsJ3ssrRcbiAqIEB0ZW1wbGF0ZSBUTG9hZGVyUXVlcmllcyAtIOyEnOu4jOyFi+uzhCDroZzrjZQg7L+866asIOuwsOyXtCDqsJ3ssrRcbiAqL1xuZXhwb3J0IGNsYXNzIEJhc2VNb2RlbENsYXNzPFxuICBUU3Vic2V0S2V5IGV4dGVuZHMgc3RyaW5nID0gbmV2ZXIsXG4gIFRTdWJzZXRNYXBwaW5nIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgYW55PiA9IG5ldmVyLFxuICBUU3Vic2V0UXVlcmllcyBleHRlbmRzIFJlY29yZDxUU3Vic2V0S2V5LCBQdXJpU3Vic2V0Rm4+ID0gbmV2ZXIsXG4gIFRMb2FkZXJRdWVyaWVzIGV4dGVuZHMgUHVyaUxvYWRlclF1ZXJpZXM8VFN1YnNldEtleT4gPSBuZXZlcixcbj4ge1xuICBwdWJsaWMgbW9kZWxOYW1lOiBzdHJpbmcgPSBcIlVua25vd25cIjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcm90ZWN0ZWQgc3Vic2V0UXVlcmllcz86IFRTdWJzZXRRdWVyaWVzLFxuICAgIHByb3RlY3RlZCBsb2FkZXJRdWVyaWVzPzogVExvYWRlclF1ZXJpZXMsXG4gICkge31cblxuICBnZXREQih3aGljaDogREJQcmVzZXQpOiBLbmV4IHtcbiAgICByZXR1cm4gREIuZ2V0REIod2hpY2gpO1xuICB9XG5cbiAgZ2V0UHVyaSh3aGljaDogREJQcmVzZXQpOiBQdXJpV3JhcHBlciB7XG4gICAgLy8g7Yq4656c7J6t7IWYIOy7qO2FjeyKpO2KuOyXkOyEnCDtirjrnpzsnq3shZgg7ZqN65OdXG4gICAgY29uc3QgdHJ4ID0gREIuZ2V0VHJhbnNhY3Rpb25Db250ZXh0KCkuZ2V0VHJhbnNhY3Rpb24od2hpY2gpO1xuICAgIGlmICh0cngpIHtcbiAgICAgIHJldHVybiB0cng7XG4gICAgfVxuXG4gICAgLy8g7Yq4656c7J6t7IWY7J20IOyXhuycvOuptCDsg4jroZzsmrQgUHVyaVdyYXBwZXIg67CY7ZmYXG4gICAgY29uc3QgZGIgPSB0aGlzLmdldERCKHdoaWNoKTtcbiAgICByZXR1cm4gbmV3IFB1cmlXcmFwcGVyKGRiLCB0aGlzLmdldFVwc2VydEJ1aWxkZXIoKSk7XG4gIH1cblxuICBhc3luYyBkZXN0cm95KCkge1xuICAgIHJldHVybiBEQi5kZXN0cm95KCk7XG4gIH1cblxuICBhc3luYyBnZXRJbnNlcnRlZElkcyhcbiAgICB3ZGI6IEtuZXgsXG4gICAgcm93czogVW5rbm93bkRCUmVjb3JkW10sXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgdW5xS2V5RmllbGRzOiBzdHJpbmdbXSxcbiAgICBjaHVua1NpemU6IG51bWJlciA9IDUwMCxcbiAgKSB7XG4gICAgaWYgKCF3ZGIpIHtcbiAgICAgIHdkYiA9IHRoaXMuZ2V0REIoXCJ3XCIpO1xuICAgIH1cblxuICAgIGxldCB1bnFLZXlzOiBzdHJpbmdbXTtcbiAgICBsZXQgd2hlcmVJbkZpZWxkOiBzdHJpbmcgfCBLbmV4LlJhdztcbiAgICBsZXQgc2VsZWN0RmllbGQ6IHN0cmluZztcblxuICAgIGlmICh1bnFLZXlGaWVsZHMubGVuZ3RoID4gMSkge1xuICAgICAgd2hlcmVJbkZpZWxkID0gd2RiLnJhdyhgQ09OQ0FUX1dTKCdfJywgJyR7dW5xS2V5RmllbGRzLmpvaW4oXCIsXCIpfScpYCk7XG4gICAgICBzZWxlY3RGaWVsZCA9IGAke3doZXJlSW5GaWVsZH0gYXMgdG1wVWlkYDtcbiAgICAgIHVucUtleXMgPSByb3dzLm1hcCgocm93KSA9PiB1bnFLZXlGaWVsZHMubWFwKChmaWVsZCkgPT4gcm93W2ZpZWxkXSkuam9pbihcIl9cIikpO1xuICAgIH0gZWxzZSB7XG4gICAgICB3aGVyZUluRmllbGQgPSB1bnFLZXlGaWVsZHNbMF07XG4gICAgICBzZWxlY3RGaWVsZCA9IHVucUtleUZpZWxkc1swXTtcbiAgICAgIHVucUtleXMgPSByb3dzLm1hcCgocm93KSA9PiByb3dbdW5xS2V5RmllbGRzWzBdXSBhcyBzdHJpbmcpO1xuICAgIH1cblxuICAgIGxldCByZXN1bHRJZHM6IG51bWJlcltdID0gW107XG4gICAgZm9yIChjb25zdCBpdGVtcyBvZiBjaHVuayh1bnFLZXlzLCBjaHVua1NpemUpKSB7XG4gICAgICBjb25zdCBkYlJvd3MgPSBhd2FpdCB3ZGIodGFibGVOYW1lKVxuICAgICAgICAuc2VsZWN0KFwiaWRcIiwgd2RiLnJhdyhzZWxlY3RGaWVsZCkpXG4gICAgICAgIC53aGVyZUluKHdoZXJlSW5GaWVsZCBhcyBzdHJpbmcsIGl0ZW1zKTtcbiAgICAgIHJlc3VsdElkcyA9IHJlc3VsdElkcy5jb25jYXQoXG4gICAgICAgIGRiUm93cy5tYXAoKGRiUm93OiBVbmtub3duREJSZWNvcmQpID0+IHBhcnNlSW50KFN0cmluZyhkYlJvdy5pZCkpKSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdElkcztcbiAgfVxuXG4gIC8qKlxuICAgKiDtirnsoJUg7ISc67iM7IWL7JeQIOuMgO2VnCDsv7zrpqwg67mM642UIO2ajeuTnVxuICAgKlxuICAgKiBAcmV0dXJucyBxYiAtIOy/vOumrCDruYzrjZQgKOyhsOqxtCDstpTqsIDsmqkpXG4gICAqIEByZXR1cm5zIG9uU3Vic2V0IC0g7Yq57KCVIOyEnOu4jOyFiyDsoITsmqkg7YOA7J6F7J20IO2VhOyalO2VoCDrlYwg7IKs7JqpXG4gICAqL1xuICBnZXRTdWJzZXRRdWVyaWVzPFQgZXh0ZW5kcyBUU3Vic2V0S2V5PihzdWJzZXQ6IFQpIHtcbiAgICBpZiAoIXRoaXMuc3Vic2V0UXVlcmllcykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwic3Vic2V0UXVlcmllcyBpcyBub3QgZGVmaW5lZFwiKTtcbiAgICB9XG5cbiAgICBjb25zdCBwdXJpV3JhcHBlciA9IG5ldyBQdXJpV3JhcHBlcih0aGlzLmdldERCKFwiclwiKSwgbmV3IFVwc2VydEJ1aWxkZXIoKSk7XG4gICAgY29uc3QgcWIgPSB0aGlzLnN1YnNldFF1ZXJpZXNbc3Vic2V0XT8uKHB1cmlXcmFwcGVyKTtcblxuICAgIC8vIE5vbkFsbG93ZWRBc1NpbmdsZVRhYmxlOiDri6jsnbwg7YWM7J2067iUIOy7rOufvCDsoJHqt7wg67Cp7KeA7JqpIOuniOy7pFxuICAgIHR5cGUgUUJUYWJsZXMgPSBVbmlvbkV4dHJhY3RlZFRUYWJsZXM8VFN1YnNldEtleSwgVFN1YnNldFF1ZXJpZXM+ICYge1xuICAgICAgTm9uQWxsb3dlZEFzU2luZ2xlVGFibGU6IHsgX19mdWxsdGV4dF9fOiB0cnVlIH07XG4gICAgfTtcblxuICAgIHJldHVybiB7XG4gICAgICBxYjogcWIgYXMgdW5rbm93biBhcyBQdXJpPERhdGFiYXNlU2NoZW1hRXh0ZW5kLCBRQlRhYmxlcywge30+LFxuICAgICAgb25TdWJzZXQ6ICgoX3N1YnNldDogVFN1YnNldEtleSB8IHJlYWRvbmx5IFRTdWJzZXRLZXlbXSkgPT4gcWIpIGFzIHtcbiAgICAgICAgLy8g64uo7J28IO2CpFxuICAgICAgICA8UyBleHRlbmRzIFRTdWJzZXRLZXk+KHN1YnNldDogUyk6IFJldHVyblR5cGU8VFN1YnNldFF1ZXJpZXNbU10+O1xuICAgICAgICAvLyDtgqQg67Cw7Je0IC0+IOq1kOynke2VqSDrsJjtmZhcbiAgICAgICAgPEFyciBleHRlbmRzIHJlYWRvbmx5IFRTdWJzZXRLZXlbXT4oXG4gICAgICAgICAgc3Vic2V0czogWy4uLkFycl0sXG4gICAgICAgICk6IFJlc29sdmVTdWJzZXRJbnRlcnNlY3Rpb248QXJyLCBUU3Vic2V0UXVlcmllcz47XG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogRW5oYW5jZXIg6rCd7LK0IOyDneyEsSDtl6ztjbxcbiAgICog7YOA7J6FIOqygOymnSDrsI8g7LaU66Gg7J2EIOuPhOyZgOykjFxuICAgKi9cbiAgY3JlYXRlRW5oYW5jZXJzPFQgZXh0ZW5kcyBUU3Vic2V0S2V5PihcbiAgICBlbmhhbmNlcnM6IEVuaGFuY2VyTWFwPFQsIEluZmVyQWxsU3Vic2V0czxUU3Vic2V0UXVlcmllcywgVExvYWRlclF1ZXJpZXM+LCBUU3Vic2V0TWFwcGluZz4sXG4gICkge1xuICAgIHJldHVybiBlbmhhbmNlcnM7XG4gIH1cblxuICAvKipcbiAgICog7ISc67iM7IWLIOy/vOumrCDsi6TtlolcbiAgICpcbiAgICogMS4g7L+866asIOyLpO2WiSAocGFnaW5hdGlvbiDsoIHsmqkpXG4gICAqIDIuIOuhnOuNlCDsi6TtlokgKDE6TiwgTjpNIOq0gOqzhCDrjbDsnbTthLAg66Gc65SpKVxuICAgKiAzLiBIeWRyYXRlIChmbGF0IOKGkiDspJHssqkg6rCd7LK0KVxuICAgKiA0LiBFbmhhbmNlciDsoIHsmqkgKHZpcnR1YWwg7ZWE65OcIOqzhOyCsClcbiAgICovXG4gIGFzeW5jIGV4ZWN1dGVTdWJzZXRRdWVyeTxcbiAgICBUIGV4dGVuZHMgVFN1YnNldEtleSxcbiAgICBUQ29tcHV0ZWRSZXN1bHRzIGV4dGVuZHMgSW5mZXJBbGxTdWJzZXRzPFRTdWJzZXRRdWVyaWVzLCBUTG9hZGVyUXVlcmllcz4sXG4gID4oXG4gICAgcGFyYW1zOiB7XG4gICAgICBzdWJzZXQ6IFQ7XG4gICAgICBxYjogUHVyaTxhbnksIGFueSwgYW55PjtcbiAgICAgIHBhcmFtczoge1xuICAgICAgICBudW0/OiBudW1iZXI7XG4gICAgICAgIHBhZ2U/OiBudW1iZXI7XG4gICAgICAgIHF1ZXJ5TW9kZT86IFwibGlzdFwiIHwgXCJjb3VudFwiIHwgXCJib3RoXCI7XG4gICAgICB9O1xuICAgICAgZGVidWc/OiBib29sZWFuO1xuICAgICAgb3B0aW1pemVDb3VudFF1ZXJ5PzogYm9vbGVhbjtcbiAgICB9ICYgRW5oYW5jZXJQYXJhbTxUU3Vic2V0S2V5LCBUQ29tcHV0ZWRSZXN1bHRzLCBUU3Vic2V0TWFwcGluZz4sXG4gICk6IFByb21pc2U8RXhlY3V0ZVN1YnNldFF1ZXJ5UmVzdWx0PFRTdWJzZXRNYXBwaW5nLCBUPj4ge1xuICAgIGNvbnN0IHsgc3Vic2V0LCBxYiwgcGFyYW1zOiBxdWVyeVBhcmFtcywgZGVidWcgPSBmYWxzZSwgb3B0aW1pemVDb3VudFF1ZXJ5ID0gZmFsc2UgfSA9IHBhcmFtcztcblxuICAgIGlmICghdGhpcy5sb2FkZXJRdWVyaWVzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJsb2FkZXJRdWVyaWVzIGlzIG5vdCBkZWZpbmVkXCIpO1xuICAgIH1cblxuICAgIGlmICghcXVlcnlQYXJhbXMubnVtIHx8ICFxdWVyeVBhcmFtcy5wYWdlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJudW0gYW5kIHBhZ2UgYXJlIHJlcXVpcmVkXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IHsgbnVtLCBwYWdlIH0gPSBxdWVyeVBhcmFtcztcblxuICAgIC8vIENPVU5UIOy/vOumrCDsi6TtlolcbiAgICBjb25zdCB0b3RhbCA9IGF3YWl0IHRoaXMuZXhlY3V0ZUNvdW50UXVlcnkocWIsIHF1ZXJ5UGFyYW1zLCBkZWJ1Zywgb3B0aW1pemVDb3VudFF1ZXJ5KTtcblxuICAgIC8vIExJU1Qg7L+866asIOyLpO2WiVxuICAgIGNvbnN0IGNvbXB1dGVkUm93cyA9IGF3YWl0IHRoaXMuZXhlY3V0ZUxpc3RRdWVyeShzdWJzZXQsIHFiLCBxdWVyeVBhcmFtcywgbnVtLCBwYWdlLCBkZWJ1Zyk7XG5cbiAgICAvLyBFbmhhbmNlciDsoIHsmqlcbiAgICBjb25zdCBlbmhhbmNlciA9IChwYXJhbXMgYXMgYW55KS5lbmhhbmNlcnM/LltzdWJzZXRdO1xuICAgIGNvbnN0IHJvd3MgPSAoYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBjb21wdXRlZFJvd3MubWFwKChyb3cpID0+IGVuaGFuY2VyPy4ocm93KSA/PyByb3cpLFxuICAgICkpIGFzIFRTdWJzZXRNYXBwaW5nW1RdW107XG5cbiAgICByZXR1cm4geyByb3dzLCB0b3RhbCB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENPVU5UIOy/vOumrCDsi6TtlokgKOuCtOu2gCDrqZTshJzrk5wpXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGV4ZWN1dGVDb3VudFF1ZXJ5KFxuICAgIHFiOiBQdXJpPGFueSwgYW55LCBhbnk+LFxuICAgIHBhcmFtczogeyBxdWVyeU1vZGU/OiBcImxpc3RcIiB8IFwiY291bnRcIiB8IFwiYm90aFwiIH0sXG4gICAgZGVidWc6IGJvb2xlYW4sXG4gICAgb3B0aW1pemVDb3VudFF1ZXJ5OiBib29sZWFuLFxuICApOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGlmIChwYXJhbXMucXVlcnlNb2RlID09PSBcImxpc3RcIikge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgY29uc3QgY291bnRQdXJpID0gcWIuY2xvbmUoKS5jbGVhcihcIm9yZGVyXCIpLmNsZWFyKFwibGltaXRcIikuY2xlYXIoXCJvZmZzZXRcIik7XG5cbiAgICBpZiAob3B0aW1pemVDb3VudFF1ZXJ5KSB7XG4gICAgICBjb25zdCB7IGRlZmF1bHQ6IFNxbFBhcnNlciB9ID0gYXdhaXQgaW1wb3J0KFwibm9kZS1zcWwtcGFyc2VyXCIpO1xuICAgICAgY29uc3QgcGFyc2VyID0gbmV3IFNxbFBhcnNlci5QYXJzZXIoKTtcbiAgICAgIGNvbnN0IHBhcnNlZFF1ZXJ5ID0gcGFyc2VyLmFzdGlmeShjb3VudFB1cmkudG9RdWVyeSgpLCB7XG4gICAgICAgIGRhdGFiYXNlOiBTb25hbXUuY29uZmlnLmRhdGFiYXNlLmRhdGFiYXNlLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGxlZnRKb2luVGFibGVzID0gZ2V0Sm9pblRhYmxlcyhwYXJzZWRRdWVyeSwgW1wiTEVGVCBKT0lOXCJdKTtcbiAgICAgIGNvbnN0IHdoZXJlVGFibGVzID0gZ2V0VGFibGVOYW1lc0Zyb21XaGVyZShwYXJzZWRRdWVyeSk7XG5cbiAgICAgIGNvbnN0IHRhYmxlc1RvUmVtb3ZlID0gbGVmdEpvaW5UYWJsZXMuZmlsdGVyKChqKSA9PiAhd2hlcmVUYWJsZXMuaW5jbHVkZXMoaikpO1xuICAgICAgdGFibGVzVG9SZW1vdmUuZm9yRWFjaCgodGFibGUpID0+IHtcbiAgICAgICAgY291bnRQdXJpLmNsZWFySm9pbih0YWJsZSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBDT1VOVCgqKeuhnCDsoITssrQg66CI7L2U65OcIOyImOulvCDqs4TsgrBcbiAgICAvLyBUT0RPOiBxYuydmCBESVNUSU5DVOqwgCDsnojripQg6rK97JqwIOyymOumrO2VtOyVvCDtlahcbiAgICBjb25zdCBjb3VudFJlc3VsdDogeyB0b3RhbD86IG51bWJlciB9ID0gYXdhaXQgY291bnRQdXJpXG4gICAgICAuY2xlYXIoXCJzZWxlY3RcIilcbiAgICAgIC5zZWxlY3QoeyB0b3RhbDogUHVyaS5yYXdOdW1iZXIoYENPVU5UKCopOjppbnRlZ2VyYCkgfSlcbiAgICAgIC5maXJzdCgpO1xuXG4gICAgaWYgKGRlYnVnKSB7XG4gICAgICBjb3VudFB1cmkuZGVidWcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY291bnRSZXN1bHQ/LnRvdGFsID8/IDA7XG4gIH1cblxuICAvKipcbiAgICogTElTVCDsv7zrpqwg7Iuk7ZaJICjrgrTrtoAg66mU7ISc65OcKVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBleGVjdXRlTGlzdFF1ZXJ5PFQgZXh0ZW5kcyBUU3Vic2V0S2V5PihcbiAgICBzdWJzZXQ6IFQsXG4gICAgcWI6IFB1cmk8YW55LCBhbnksIGFueT4sXG4gICAgcGFyYW1zOiB7IHF1ZXJ5TW9kZT86IFwibGlzdFwiIHwgXCJjb3VudFwiIHwgXCJib3RoXCIgfSxcbiAgICBudW06IG51bWJlcixcbiAgICBwYWdlOiBudW1iZXIsXG4gICAgZGVidWc6IGJvb2xlYW4sXG4gICk6IFByb21pc2U8YW55W10+IHtcbiAgICBpZiAocGFyYW1zLnF1ZXJ5TW9kZSA9PT0gXCJjb3VudFwiKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgbGV0IHVubG9hZGVkUm93cyA9IChhd2FpdCBxYi5saW1pdChudW0pLm9mZnNldChudW0gKiAocGFnZSAtIDEpKSkgYXMgYW55W107XG5cbiAgICBpZiAoZGVidWcpIHtcbiAgICAgIHFiLmRlYnVnKCk7XG4gICAgfVxuXG4gICAgLy8g66Gc642UIOyymOumrFxuICAgIGNvbnN0IGxvYWRlcnMgPSAodGhpcy5sb2FkZXJRdWVyaWVzIGFzIGFueSlbc3Vic2V0XTtcbiAgICBpZiAobG9hZGVycyAmJiBBcnJheS5pc0FycmF5KGxvYWRlcnMpKSB7XG4gICAgICB1bmxvYWRlZFJvd3MgPSBhd2FpdCB0aGlzLnByb2Nlc3NMb2FkZXJzKHVubG9hZGVkUm93cywgbG9hZGVycywgZGVidWcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmh5ZHJhdGUodW5sb2FkZWRSb3dzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDsnqzqt4DsoIEg66Gc642UIOyymOumrFxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBwcm9jZXNzTG9hZGVycyhyb3dzOiBhbnlbXSwgbG9hZGVyczogYW55W10sIGRlYnVnOiBib29sZWFuKTogUHJvbWlzZTxhbnlbXT4ge1xuICAgIGZvciAoY29uc3QgcmVzb2x2ZUxvYWRlciBvZiBsb2FkZXJzKSB7XG4gICAgICBjb25zdCB7IGFzLCByZWZJZCwgcWI6IHJlc29sdmVMb2FkZXJRYkZuLCBsb2FkZXJzOiBuZXN0ZWRMb2FkZXJzIH0gPSByZXNvbHZlTG9hZGVyO1xuXG4gICAgICBjb25zdCByZXNvbHZlTG9hZGVyUWIgPSByZXNvbHZlTG9hZGVyUWJGbihcbiAgICAgICAgbmV3IFB1cmlXcmFwcGVyKHRoaXMuZ2V0REIoXCJyXCIpLCBuZXcgVXBzZXJ0QnVpbGRlcigpKSxcbiAgICAgICAgcm93cy5tYXAoKHJvdykgPT4gcm93W3JlZklkXSksXG4gICAgICApO1xuXG4gICAgICBpZiAoZGVidWcpIHtcbiAgICAgICAgcmVzb2x2ZUxvYWRlclFiLmRlYnVnKCk7XG4gICAgICB9XG5cbiAgICAgIGxldCBsb2FkZWRSb3dzID0gKGF3YWl0IHJlc29sdmVMb2FkZXJRYikgYXMgYW55W107XG5cbiAgICAgIC8vIOykkeyyqSBsb2FkZXJz6rCAIOyeiOycvOuptCDsnqzqt4Ag7LKY66asXG4gICAgICBpZiAobmVzdGVkTG9hZGVycyAmJiBuZXN0ZWRMb2FkZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgbG9hZGVkUm93cyA9IGF3YWl0IHRoaXMucHJvY2Vzc0xvYWRlcnMobG9hZGVkUm93cywgbmVzdGVkTG9hZGVycywgZGVidWcpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzdWJSb3dHcm91cHMgPSBncm91cChsb2FkZWRSb3dzLCAocm93KSA9PiByb3cucmVmSWQpO1xuXG4gICAgICByb3dzID0gcm93cy5tYXAoKHJvdykgPT4ge1xuICAgICAgICByb3dbYXNdID0gKHN1YlJvd0dyb3Vwc1tyb3dbcmVmSWRdXSA/PyBbXSkubWFwKChyKSA9PiBvbWl0KHIsIFtcInJlZklkXCJdKSk7XG4gICAgICAgIHJldHVybiByb3c7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gcm93cztcbiAgfVxuXG4gIC8qKlxuICAgKiBGbGF0IOugiOy9lOuTnOulvCDspJHssqkg6rCd7LK066GcIOuzgO2ZmFxuICAgKlxuICAgKiAtIGB1c2VyX19uYW1lYCDihpIgYHsgdXNlcjogeyBuYW1lIH0gfWBcbiAgICogLSBudWxsYWJsZSByZWxhdGlvbuydmCDqsr3smrAg66qo65OgIO2VhOuTnOqwgCBudWxs7J2066m0IOqwneyytCDsnpDssrTrpbwgbnVsbOuhnFxuICAgKi9cbiAgaHlkcmF0ZTxUIGV4dGVuZHMgVW5rbm93bkRCUmVjb3JkPihyb3dzOiBUW10pOiBUW10ge1xuICAgIHJldHVybiByb3dzLm1hcCgocm93OiBUKSA9PiB7XG4gICAgICAvLyBudWxsYWJsZSByZWxhdGlvbiDsspjrpqw6IOq0gOugqCDtlYTrk5zqsIAg7KCE67aAIG51bGzsnbgg6rK97JqwIOuwqeyngFxuICAgICAgY29uc3QgbmVzdGVkS2V5cyA9IE9iamVjdC5rZXlzKHJvdykuZmlsdGVyKChrZXkpID0+IGtleS5pbmNsdWRlcyhcIl9fXCIpKTtcbiAgICAgIGNvbnN0IGdyb3VwcyA9IE9iamVjdC5ncm91cEJ5KG5lc3RlZEtleXMsIChrZXkpID0+IGtleS5zcGxpdChcIl9fXCIpWzBdKTtcbiAgICAgIGNvbnN0IG51bGxLZXlzID0gT2JqZWN0LmVudHJpZXMoZ3JvdXBzKVxuICAgICAgICAuZmlsdGVyKFxuICAgICAgICAgIChbXywgZGF0YV0pID0+XG4gICAgICAgICAgICBkYXRhICYmXG4gICAgICAgICAgICBkYXRhLmxlbmd0aCA+IDEgJiZcbiAgICAgICAgICAgIGRhdGEuZXZlcnkoXG4gICAgICAgICAgICAgIChmaWVsZCkgPT5cbiAgICAgICAgICAgICAgICByb3dbZmllbGRdID09PSBudWxsIHx8IChBcnJheS5pc0FycmF5KHJvd1tmaWVsZF0pICYmIHJvd1tmaWVsZF0ubGVuZ3RoID09PSAwKSxcbiAgICAgICAgICAgICksXG4gICAgICAgIClcbiAgICAgICAgLm1hcCgoW2tleV0pID0+IGtleSk7XG5cbiAgICAgIGNvbnN0IGh5ZHJhdGVkID0gT2JqZWN0LmtleXMocm93KS5yZWR1Y2UoKHIsIGZpZWxkKSA9PiB7XG4gICAgICAgIGlmICghZmllbGQuaW5jbHVkZXMoXCJfX1wiKSkge1xuICAgICAgICAgIC8vIOydvOuwmCDtlYTrk5w6IOuwsOyXtCDrgrQg6rCd7LK066m0IOyerOq3gCBoeWRyYXRlXG4gICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocm93W2ZpZWxkXSkgJiYgaXNPYmplY3Qocm93W2ZpZWxkXVswXSkpIHtcbiAgICAgICAgICAgIHJbZmllbGRdID0gdGhpcy5oeWRyYXRlKHJvd1tmaWVsZF0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByW2ZpZWxkXSA9IHJvd1tmaWVsZF07XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiByO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8g7KSR7LKpIO2VhOuTnCDsspjrpqw6IHVzZXJfX25hbWUg4oaSIHVzZXJbbmFtZV1cbiAgICAgICAgY29uc3QgcGFydHMgPSBmaWVsZC5zcGxpdChcIl9fXCIpO1xuICAgICAgICBjb25zdCBvYmpQYXRoID1cbiAgICAgICAgICBwYXJ0c1swXSArXG4gICAgICAgICAgcGFydHNcbiAgICAgICAgICAgIC5zbGljZSgxKVxuICAgICAgICAgICAgLm1hcCgocGFydCkgPT4gYFske3BhcnR9XWApXG4gICAgICAgICAgICAuam9pbihcIlwiKTtcblxuICAgICAgICByID0gc2V0KFxuICAgICAgICAgIHIsXG4gICAgICAgICAgb2JqUGF0aCxcbiAgICAgICAgICByb3dbZmllbGRdICYmIEFycmF5LmlzQXJyYXkocm93W2ZpZWxkXSkgJiYgaXNPYmplY3Qocm93W2ZpZWxkXVswXSlcbiAgICAgICAgICAgID8gdGhpcy5oeWRyYXRlKHJvd1tmaWVsZF0pXG4gICAgICAgICAgICA6IHJvd1tmaWVsZF0sXG4gICAgICAgICk7XG5cbiAgICAgICAgcmV0dXJuIHI7XG4gICAgICB9LCB7fSBhcyBVbmtub3duREJSZWNvcmQpO1xuXG4gICAgICAvLyBudWxsIHJlbGF0aW9uIOyymOumrFxuICAgICAgbnVsbEtleXMuZm9yRWFjaCgobnVsbEtleSkgPT4ge1xuICAgICAgICBoeWRyYXRlZFtudWxsS2V5XSA9IG51bGw7XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIGh5ZHJhdGVkO1xuICAgIH0pIGFzIFRbXTtcbiAgfVxuXG4gIC8vIExlZ2FjeSBTdWJzZXRRdWVyeSDsi6TtlokgKFB1cmkg64+E7J6FIOyghCDtmLjtmZjsmqkpXG4gIGFzeW5jIHJ1blN1YnNldFF1ZXJ5PFQgZXh0ZW5kcyBCYXNlTGlzdFBhcmFtcywgVSBleHRlbmRzIHN0cmluZz4oe1xuICAgIHBhcmFtcyxcbiAgICBiYXNlVGFibGUsXG4gICAgc3Vic2V0LFxuICAgIHN1YnNldFF1ZXJ5LFxuICAgIGJ1aWxkLFxuICAgIGFmdGVyQnVpbGQsXG4gICAgZGVidWcsXG4gICAgZGI6IF9kYixcbiAgICBvcHRpbWl6ZUNvdW50UXVlcnksXG4gIH06IHtcbiAgICBzdWJzZXQ6IFU7XG4gICAgcGFyYW1zOiBUO1xuICAgIHN1YnNldFF1ZXJ5OiBTdWJzZXRRdWVyeTtcbiAgICBidWlsZDogKGJ1aWxkUGFyYW1zOiB7XG4gICAgICBxYjogS25leC5RdWVyeUJ1aWxkZXI7XG4gICAgICBkYjogS25leDtcbiAgICAgIHNlbGVjdDogKHN0cmluZyB8IEtuZXguUmF3KVtdO1xuICAgICAgam9pbnM6IFN1YnNldFF1ZXJ5W1wiam9pbnNcIl07XG4gICAgICB2aXJ0dWFsOiBzdHJpbmdbXTtcbiAgICB9KSA9PiBLbmV4LlF1ZXJ5QnVpbGRlcjtcbiAgICBhZnRlckJ1aWxkPzogKGJ1aWxkUGFyYW1zOiB7XG4gICAgICBxYjogS25leC5RdWVyeUJ1aWxkZXI7XG4gICAgICBkYjogS25leDtcbiAgICAgIHNlbGVjdDogKHN0cmluZyB8IEtuZXguUmF3KVtdO1xuICAgICAgam9pbnM6IFN1YnNldFF1ZXJ5W1wiam9pbnNcIl07XG4gICAgICB2aXJ0dWFsOiBzdHJpbmdbXTtcbiAgICB9KSA9PiBLbmV4LlF1ZXJ5QnVpbGRlcjtcbiAgICBiYXNlVGFibGU/OiBzdHJpbmc7XG4gICAgZGVidWc/OiBib29sZWFuIHwgXCJsaXN0XCIgfCBcImNvdW50XCI7XG4gICAgZGI/OiBLbmV4O1xuICAgIG9wdGltaXplQ291bnRRdWVyeT86IGJvb2xlYW47XG4gIH0pOiBQcm9taXNlPHtcbiAgICAvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vRXhwbGljaXRBbnk6IFB1cmkg64+E7J6FIOyghOq5jOyngCBhbnnroZwg7Jyg7KeAXG4gICAgcm93czogYW55W107XG4gICAgdG90YWw/OiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gICAgc3Vic2V0UXVlcnk6IFN1YnNldFF1ZXJ5O1xuICAgIHFiOiBLbmV4LlF1ZXJ5QnVpbGRlcjtcbiAgfT4ge1xuICAgIGNvbnN0IGNoYWxrID0gKGF3YWl0IGltcG9ydChcImNoYWxrXCIpKS5kZWZhdWx0O1xuICAgIGNvbnN0IFNxbFBhcnNlciA9IChhd2FpdCBpbXBvcnQoXCJub2RlLXNxbC1wYXJzZXJcIikpLmRlZmF1bHQ7XG4gICAgY29uc3QgeyBnZXRUYWJsZU5hbWUsIGdldFRhYmxlTmFtZXNGcm9tV2hlcmUgfSA9IGF3YWl0IGltcG9ydChcIi4uL3V0aWxzL3NxbC1wYXJzZXJcIik7XG5cbiAgICBjb25zdCBkYiA9IF9kYiA/PyB0aGlzLmdldERCKHN1YnNldC5zdGFydHNXaXRoKFwiQVwiKSA/IFwid1wiIDogXCJyXCIpO1xuICAgIGJhc2VUYWJsZSA9IGJhc2VUYWJsZSA/PyBpbmZsZWN0aW9uLnBsdXJhbGl6ZShpbmZsZWN0aW9uLnVuZGVyc2NvcmUodGhpcy5tb2RlbE5hbWUpKTtcbiAgICBjb25zdCBxdWVyeU1vZGUgPSBwYXJhbXMucXVlcnlNb2RlID8/IChwYXJhbXMuaWQgIT09IHVuZGVmaW5lZCA/IFwibGlzdFwiIDogXCJib3RoXCIpO1xuXG4gICAgY29uc3QgeyBzZWxlY3QsIHZpcnR1YWwsIGpvaW5zLCBsb2FkZXJzIH0gPSBzdWJzZXRRdWVyeTtcbiAgICBjb25zdCBxYiA9IGJ1aWxkKHtcbiAgICAgIHFiOiBkYi5mcm9tKGJhc2VUYWJsZSksXG4gICAgICBkYixcbiAgICAgIHNlbGVjdCxcbiAgICAgIGpvaW5zLFxuICAgICAgdmlydHVhbCxcbiAgICB9KTtcblxuICAgIGNvbnN0IGFwcGx5Sm9pbkNsYXVzZSA9IChxYjogS25leC5RdWVyeUJ1aWxkZXIsIGpvaW5zOiBTdWJzZXRRdWVyeVtcImpvaW5zXCJdKSA9PiB7XG4gICAgICBqb2lucy5mb3JFYWNoKChqb2luKSA9PiB7XG4gICAgICAgIGlmIChqb2luLmpvaW4gPT09IFwiaW5uZXJcIikge1xuICAgICAgICAgIHFiLmlubmVySm9pbihgJHtqb2luLnRhYmxlfSBhcyAke2pvaW4uYXN9YCwgdGhpcy5nZXRKb2luQ2xhdXNlKGRiLCBqb2luKSk7XG4gICAgICAgIH0gZWxzZSBpZiAoam9pbi5qb2luID09PSBcIm91dGVyXCIpIHtcbiAgICAgICAgICBxYi5sZWZ0T3V0ZXJKb2luKGAke2pvaW4udGFibGV9IGFzICR7am9pbi5hc31gLCB0aGlzLmdldEpvaW5DbGF1c2UoZGIsIGpvaW4pKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8vIGNvdW50UXVlcnlcbiAgICBjb25zdCB0b3RhbCA9IGF3YWl0IChhc3luYyAoKSA9PiB7XG4gICAgICBpZiAocXVlcnlNb2RlID09PSBcImxpc3RcIikge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjbG9uZWRRYiA9IHFiLmNsb25lKCkuY2xlYXIoXCJvcmRlclwiKS5jbGVhcihcIm9mZnNldFwiKS5jbGVhcihcImxpbWl0XCIpO1xuICAgICAgY29uc3QgcGFyc2VyID0gbmV3IFNxbFBhcnNlci5QYXJzZXIoKTtcblxuICAgICAgaWYgKG9wdGltaXplQ291bnRRdWVyeSkge1xuICAgICAgICBjb25zdCBwYXJzZWRRdWVyeSA9IHBhcnNlci5hc3RpZnkoY2xvbmVkUWIudG9RdWVyeSgpLCB7XG4gICAgICAgICAgZGF0YWJhc2U6IFNvbmFtdS5jb25maWcuZGF0YWJhc2UuZGF0YWJhc2UsXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCB0YWJsZXMgPSBnZXRUYWJsZU5hbWVzRnJvbVdoZXJlKHBhcnNlZFF1ZXJ5KTtcbiAgICAgICAgY29uc3QgbmVlZFRvSm9pbiA9IHVuaXF1ZShcbiAgICAgICAgICB0YWJsZXMuZmxhdE1hcCgodGFibGUpID0+IHRhYmxlLnNwbGl0KFwiX19cIikubWFwKCh0KSA9PiBpbmZsZWN0aW9uLnBsdXJhbGl6ZSh0KSkpLFxuICAgICAgICApO1xuICAgICAgICBhcHBseUpvaW5DbGF1c2UoXG4gICAgICAgICAgY2xvbmVkUWIsXG4gICAgICAgICAgam9pbnMuZmlsdGVyKChqKSA9PiBuZWVkVG9Kb2luLmluY2x1ZGVzKGoudGFibGUpKSxcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFwcGx5Sm9pbkNsYXVzZShjbG9uZWRRYiwgam9pbnMpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwcm9jZXNzZWRRYiA9IGFmdGVyQnVpbGQ/Lih7IHFiOiBjbG9uZWRRYiwgZGIsIHNlbGVjdCwgam9pbnMsIHZpcnR1YWwgfSkgPz8gY2xvbmVkUWI7XG5cbiAgICAgIGNvbnN0IHBhcnNlZFF1ZXJ5ID0gcGFyc2VyLmFzdGlmeShwcm9jZXNzZWRRYi50b1F1ZXJ5KCksIHtcbiAgICAgICAgZGF0YWJhc2U6IFNvbmFtdS5jb25maWcuZGF0YWJhc2UuZGF0YWJhc2UsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHEgPSBBcnJheS5pc0FycmF5KHBhcnNlZFF1ZXJ5KSA/IHBhcnNlZFF1ZXJ5WzBdIDogcGFyc2VkUXVlcnk7XG4gICAgICBpZiAocS50eXBlICE9PSBcInNlbGVjdFwiKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgcXVlcnlcIik7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNvdW50UXVlcnkgPVxuICAgICAgICBxLmRpc3RpbmN0ICE9PSBudWxsXG4gICAgICAgICAgPyBjbG9uZWRRYlxuICAgICAgICAgICAgICAuY2xlYXIoXCJzZWxlY3RcIilcbiAgICAgICAgICAgICAgLnNlbGVjdChcbiAgICAgICAgICAgICAgICBkYi5yYXcoXG4gICAgICAgICAgICAgICAgICBgQ09VTlQoRElTVElOQ1QgXFxgJHtnZXRUYWJsZU5hbWUocS5jb2x1bW5zWzBdLmV4cHIpfVxcYC5cXGAke3EuY29sdW1uc1swXS5leHByLmNvbHVtbn1cXGApIGFzIHRvdGFsYCxcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgIC5maXJzdCgpXG4gICAgICAgICAgOiBjbG9uZWRRYi5jbGVhcihcInNlbGVjdFwiKS5jb3VudChcIipcIiwgeyBhczogXCJ0b3RhbFwiIH0pLmZpcnN0KCk7XG4gICAgICBjb25zdCBjb3VudFJvdzogeyB0b3RhbD86IG51bWJlciB9ID0gYXdhaXQgY291bnRRdWVyeTtcblxuICAgICAgaWYgKGRlYnVnID09PSB0cnVlIHx8IGRlYnVnID09PSBcImNvdW50XCIpIHtcbiAgICAgICAgY29uc29sZS5kZWJ1ZyhcIkRFQlVHOiBjb3VudCBxdWVyeVwiLCBjaGFsay5ibHVlKGNvdW50UXVlcnkudG9RdWVyeSgpLnRvU3RyaW5nKCkpKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNvdW50Um93Py50b3RhbCA/PyAwO1xuICAgIH0pKCk7XG5cbiAgICAvLyBsaXN0UXVlcnlcbiAgICBjb25zdCByb3dzID0gYXdhaXQgKGFzeW5jICgpID0+IHtcbiAgICAgIGlmIChxdWVyeU1vZGUgPT09IFwiY291bnRcIikge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG5cbiAgICAgIGlmIChwYXJhbXMubnVtICE9PSAwKSB7XG4gICAgICAgIGFzc2VydChwYXJhbXMubnVtKTtcbiAgICAgICAgcWIubGltaXQocGFyYW1zLm51bSk7XG4gICAgICAgIHFiLm9mZnNldChwYXJhbXMubnVtICogKChwYXJhbXMucGFnZSA/PyAxKSAtIDEpKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY2xvbmVkUWIgPSBxYi5jbG9uZSgpLnNlbGVjdChzZWxlY3QpO1xuICAgICAgYXBwbHlKb2luQ2xhdXNlKGNsb25lZFFiLCBqb2lucyk7XG5cbiAgICAgIGNvbnN0IGxpc3RRdWVyeSA9IGFmdGVyQnVpbGQ/Lih7IHFiOiBjbG9uZWRRYiwgZGIsIHNlbGVjdCwgam9pbnMsIHZpcnR1YWwgfSkgPz8gY2xvbmVkUWI7XG5cbiAgICAgIGxldCByb3dzID0gYXdhaXQgbGlzdFF1ZXJ5O1xuICAgICAgaWYgKGRlYnVnID09PSB0cnVlIHx8IGRlYnVnID09PSBcImxpc3RcIikge1xuICAgICAgICBjb25zb2xlLmRlYnVnKFwiREVCVUc6IGxpc3QgcXVlcnlcIiwgY2hhbGsuYmx1ZShsaXN0UXVlcnkudG9RdWVyeSgpLnRvU3RyaW5nKCkpKTtcbiAgICAgIH1cblxuICAgICAgcm93cyA9IGF3YWl0IHRoaXMudXNlTG9hZGVycyhkYiwgcm93cywgbG9hZGVycyk7XG4gICAgICByb3dzID0gdGhpcy5oeWRyYXRlKHJvd3MpO1xuICAgICAgcmV0dXJuIHJvd3M7XG4gICAgfSkoKTtcblxuICAgIHJldHVybiB7IHJvd3MsIHRvdGFsLCBzdWJzZXRRdWVyeSwgcWIgfTtcbiAgfVxuXG4gIC8vIExlZ2FjeSBMb2FkZXIg7LKY66asIChQdXJpIOuPhOyehSDsoIQg7Zi47ZmY7JqpKVxuICBhc3luYyB1c2VMb2FkZXJzKGRiOiBLbmV4LCByb3dzOiBVbmtub3duREJSZWNvcmRbXSwgbG9hZGVyczogU3Vic2V0UXVlcnlbXCJsb2FkZXJzXCJdKSB7XG4gICAgaWYgKGxvYWRlcnMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gcm93cztcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGxvYWRlciBvZiBsb2FkZXJzKSB7XG4gICAgICBsZXQgc3ViUTogS25leC5RdWVyeUJ1aWxkZXI7XG4gICAgICBsZXQgc3ViUm93czogVW5rbm93bkRCUmVjb3JkW107XG4gICAgICBsZXQgdG9Db2w6IHN0cmluZztcblxuICAgICAgY29uc3QgZnJvbUlkcyA9IHJvd3MubWFwKChyb3cpID0+IHJvd1tsb2FkZXIubWFueUpvaW4uaWRGaWVsZF0pO1xuXG4gICAgICBpZiAobG9hZGVyLm1hbnlKb2luLnRocm91Z2ggPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAvLyBIYXNNYW55XG4gICAgICAgIGNvbnN0IGlkQ29sdW1uID0gYCR7bG9hZGVyLm1hbnlKb2luLnRvVGFibGV9LiR7bG9hZGVyLm1hbnlKb2luLnRvQ29sfWA7XG4gICAgICAgIHN1YlEgPSBkYihsb2FkZXIubWFueUpvaW4udG9UYWJsZSlcbiAgICAgICAgICAud2hlcmVJbihpZENvbHVtbiBhcyBzdHJpbmcsIGZyb21JZHMgYXMgc3RyaW5nW10pXG4gICAgICAgICAgLnNlbGVjdChbLi4ubG9hZGVyLnNlbGVjdCwgaWRDb2x1bW5dKTtcblxuICAgICAgICBsb2FkZXIub25lSm9pbnMuZm9yRWFjaCgoam9pbikgPT4ge1xuICAgICAgICAgIGlmIChqb2luLmpvaW4gPT09IFwiaW5uZXJcIikge1xuICAgICAgICAgICAgc3ViUS5pbm5lckpvaW4oYCR7am9pbi50YWJsZX0gYXMgJHtqb2luLmFzfWAsIHRoaXMuZ2V0Sm9pbkNsYXVzZShkYiwgam9pbikpO1xuICAgICAgICAgIH0gZWxzZSBpZiAoam9pbi5qb2luID09PSBcIm91dGVyXCIpIHtcbiAgICAgICAgICAgIHN1YlEubGVmdE91dGVySm9pbihgJHtqb2luLnRhYmxlfSBhcyAke2pvaW4uYXN9YCwgdGhpcy5nZXRKb2luQ2xhdXNlKGRiLCBqb2luKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdG9Db2wgPSBsb2FkZXIubWFueUpvaW4udG9Db2w7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBNYW55VG9NYW55XG4gICAgICAgIGNvbnN0IGlkQ29sdW1uID0gYCR7bG9hZGVyLm1hbnlKb2luLnRocm91Z2gudGFibGV9LiR7bG9hZGVyLm1hbnlKb2luLnRocm91Z2guZnJvbUNvbH1gO1xuICAgICAgICBzdWJRID0gZGIobG9hZGVyLm1hbnlKb2luLnRocm91Z2gudGFibGUpXG4gICAgICAgICAgLmpvaW4oXG4gICAgICAgICAgICBsb2FkZXIubWFueUpvaW4udG9UYWJsZSxcbiAgICAgICAgICAgIGAke2xvYWRlci5tYW55Sm9pbi50aHJvdWdoLnRhYmxlfS4ke2xvYWRlci5tYW55Sm9pbi50aHJvdWdoLnRvQ29sfWAsXG4gICAgICAgICAgICBgJHtsb2FkZXIubWFueUpvaW4udG9UYWJsZX0uJHtsb2FkZXIubWFueUpvaW4udG9Db2x9YCxcbiAgICAgICAgICApXG4gICAgICAgICAgLndoZXJlSW4oaWRDb2x1bW4gYXMgc3RyaW5nLCBmcm9tSWRzIGFzIHN0cmluZ1tdKVxuICAgICAgICAgIC5zZWxlY3QodW5pcXVlKFsuLi5sb2FkZXIuc2VsZWN0LCBpZENvbHVtbl0pKTtcblxuICAgICAgICBsb2FkZXIub25lSm9pbnMuZm9yRWFjaCgoam9pbikgPT4ge1xuICAgICAgICAgIGlmIChqb2luLmpvaW4gPT09IFwiaW5uZXJcIikge1xuICAgICAgICAgICAgc3ViUS5pbm5lckpvaW4oYCR7am9pbi50YWJsZX0gYXMgJHtqb2luLmFzfWAsIHRoaXMuZ2V0Sm9pbkNsYXVzZShkYiwgam9pbikpO1xuICAgICAgICAgIH0gZWxzZSBpZiAoam9pbi5qb2luID09PSBcIm91dGVyXCIpIHtcbiAgICAgICAgICAgIHN1YlEubGVmdE91dGVySm9pbihgJHtqb2luLnRhYmxlfSBhcyAke2pvaW4uYXN9YCwgdGhpcy5nZXRKb2luQ2xhdXNlKGRiLCBqb2luKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdG9Db2wgPSBsb2FkZXIubWFueUpvaW4udGhyb3VnaC5mcm9tQ29sO1xuICAgICAgfVxuICAgICAgc3ViUm93cyA9IGF3YWl0IHN1YlE7XG5cbiAgICAgIGlmIChsb2FkZXIubG9hZGVycykge1xuICAgICAgICBzdWJSb3dzID0gYXdhaXQgdGhpcy51c2VMb2FkZXJzKGRiLCBzdWJSb3dzLCBsb2FkZXIubG9hZGVycyk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHN1YlJvd0dyb3VwcyA9IGdyb3VwKHN1YlJvd3MsIChyb3cpID0+IHJvd1t0b0NvbF0gYXMgc3RyaW5nKTtcbiAgICAgIHJvd3MgPSByb3dzLm1hcCgocm93KSA9PiB7XG4gICAgICAgIHJvd1tsb2FkZXIuYXNdID0gKHN1YlJvd0dyb3Vwc1tyb3dbbG9hZGVyLm1hbnlKb2luLmlkRmllbGRdIGFzIHN0cmluZ10gPz8gW10pLm1hcCgocikgPT5cbiAgICAgICAgICBvbWl0KHIsIFt0b0NvbF0pLFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gcm93O1xuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiByb3dzO1xuICB9XG5cbiAgZ2V0Sm9pbkNsYXVzZShkYjogS25leDxhbnksIHVua25vd24+LCBqb2luOiBTdWJzZXRRdWVyeVtcImpvaW5zXCJdW251bWJlcl0pOiBLbmV4LlJhdzxhbnk+IHtcbiAgICBpZiAoIWlzQ3VzdG9tSm9pbkNsYXVzZShqb2luKSkge1xuICAgICAgcmV0dXJuIGRiLnJhdyhgJHtqb2luLmZyb219ID0gJHtqb2luLnRvfWApO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZGIucmF3KGpvaW4uY3VzdG9tKTtcbiAgICB9XG4gIH1cblxuICBnZXRVcHNlcnRCdWlsZGVyKCk6IFVwc2VydEJ1aWxkZXIge1xuICAgIHJldHVybiBuZXcgVXBzZXJ0QnVpbGRlcigpO1xuICB9XG59XG5cbi8qKlxuICogRW5oYW5jZXIg7YyM652866+47YSwIOyhsOqxtOu2gCDtg4DsnoVcbiAqIFJlcXVpcmVkRW5oYW5jZXJLZXlz6rCAIOyXhuycvOuptCBlbmhhbmNlcnMg7ISg7YOd7KCBLCDsnojsnLzrqbQg7ZWE7IiYXG4gKi9cbnR5cGUgRW5oYW5jZXJQYXJhbTxcbiAgVFN1YnNldEtleSBleHRlbmRzIHN0cmluZyxcbiAgVENvbXB1dGVkUmVzdWx0cyBleHRlbmRzIFJlY29yZDxUU3Vic2V0S2V5LCBhbnk+LFxuICBUU3Vic2V0TWFwcGluZyBleHRlbmRzIFJlY29yZDxUU3Vic2V0S2V5LCBhbnk+LFxuPiA9IFtSZXF1aXJlZEVuaGFuY2VyS2V5czxUU3Vic2V0S2V5LCBUQ29tcHV0ZWRSZXN1bHRzLCBUU3Vic2V0TWFwcGluZz5dIGV4dGVuZHMgW25ldmVyXVxuICA/IHsgZW5oYW5jZXJzPzogRW5oYW5jZXJNYXA8VFN1YnNldEtleSwgVENvbXB1dGVkUmVzdWx0cywgVFN1YnNldE1hcHBpbmc+IH1cbiAgOiB7IGVuaGFuY2VyczogRW5oYW5jZXJNYXA8VFN1YnNldEtleSwgVENvbXB1dGVkUmVzdWx0cywgVFN1YnNldE1hcHBpbmc+IH07XG5cbnR5cGUgUmVxdWlyZWRFbmhhbmNlcktleXM8XG4gIFRTdWJzZXRLZXkgZXh0ZW5kcyBzdHJpbmcsXG4gIFRDb21wdXRlZFJlc3VsdHMgZXh0ZW5kcyBSZWNvcmQ8VFN1YnNldEtleSwgYW55PixcbiAgVFN1YnNldE1hcHBpbmcgZXh0ZW5kcyBSZWNvcmQ8VFN1YnNldEtleSwgYW55Pixcbj4gPSB7XG4gIFtLIGluIFRTdWJzZXRLZXldOiBUQ29tcHV0ZWRSZXN1bHRzW0tdIGV4dGVuZHMgVFN1YnNldE1hcHBpbmdbS10gPyBuZXZlciA6IEs7XG59W1RTdWJzZXRLZXldO1xuXG5leHBvcnQgY29uc3QgQmFzZU1vZGVsID0gbmV3IEJhc2VNb2RlbENsYXNzKCk7XG4iXSwibmFtZXMiOlsiYXNzZXJ0IiwiaW5mbGVjdGlvbiIsImdyb3VwIiwiaXNPYmplY3QiLCJvbWl0Iiwic2V0IiwidW5pcXVlIiwiU29uYW11IiwiaXNDdXN0b21Kb2luQ2xhdXNlIiwiZ2V0Sm9pblRhYmxlcyIsImdldFRhYmxlTmFtZXNGcm9tV2hlcmUiLCJjaHVuayIsIkRCIiwiUHVyaSIsIlB1cmlXcmFwcGVyIiwiVXBzZXJ0QnVpbGRlciIsIkJhc2VNb2RlbENsYXNzIiwibW9kZWxOYW1lIiwic3Vic2V0UXVlcmllcyIsImxvYWRlclF1ZXJpZXMiLCJnZXREQiIsIndoaWNoIiwiZ2V0UHVyaSIsInRyeCIsImdldFRyYW5zYWN0aW9uQ29udGV4dCIsImdldFRyYW5zYWN0aW9uIiwiZGIiLCJnZXRVcHNlcnRCdWlsZGVyIiwiZGVzdHJveSIsImdldEluc2VydGVkSWRzIiwid2RiIiwicm93cyIsInRhYmxlTmFtZSIsInVucUtleUZpZWxkcyIsImNodW5rU2l6ZSIsInVucUtleXMiLCJ3aGVyZUluRmllbGQiLCJzZWxlY3RGaWVsZCIsImxlbmd0aCIsInJhdyIsImpvaW4iLCJtYXAiLCJyb3ciLCJmaWVsZCIsInJlc3VsdElkcyIsIml0ZW1zIiwiZGJSb3dzIiwic2VsZWN0Iiwid2hlcmVJbiIsImNvbmNhdCIsImRiUm93IiwicGFyc2VJbnQiLCJTdHJpbmciLCJpZCIsImdldFN1YnNldFF1ZXJpZXMiLCJzdWJzZXQiLCJFcnJvciIsInB1cmlXcmFwcGVyIiwicWIiLCJvblN1YnNldCIsIl9zdWJzZXQiLCJjcmVhdGVFbmhhbmNlcnMiLCJlbmhhbmNlcnMiLCJleGVjdXRlU3Vic2V0UXVlcnkiLCJwYXJhbXMiLCJxdWVyeVBhcmFtcyIsImRlYnVnIiwib3B0aW1pemVDb3VudFF1ZXJ5IiwibnVtIiwicGFnZSIsInRvdGFsIiwiZXhlY3V0ZUNvdW50UXVlcnkiLCJjb21wdXRlZFJvd3MiLCJleGVjdXRlTGlzdFF1ZXJ5IiwiZW5oYW5jZXIiLCJQcm9taXNlIiwiYWxsIiwicXVlcnlNb2RlIiwiY291bnRQdXJpIiwiY2xvbmUiLCJjbGVhciIsImRlZmF1bHQiLCJTcWxQYXJzZXIiLCJwYXJzZXIiLCJQYXJzZXIiLCJwYXJzZWRRdWVyeSIsImFzdGlmeSIsInRvUXVlcnkiLCJkYXRhYmFzZSIsImNvbmZpZyIsImxlZnRKb2luVGFibGVzIiwid2hlcmVUYWJsZXMiLCJ0YWJsZXNUb1JlbW92ZSIsImZpbHRlciIsImoiLCJpbmNsdWRlcyIsImZvckVhY2giLCJ0YWJsZSIsImNsZWFySm9pbiIsImNvdW50UmVzdWx0IiwicmF3TnVtYmVyIiwiZmlyc3QiLCJ1bmxvYWRlZFJvd3MiLCJsaW1pdCIsIm9mZnNldCIsImxvYWRlcnMiLCJBcnJheSIsImlzQXJyYXkiLCJwcm9jZXNzTG9hZGVycyIsImh5ZHJhdGUiLCJyZXNvbHZlTG9hZGVyIiwiYXMiLCJyZWZJZCIsInJlc29sdmVMb2FkZXJRYkZuIiwibmVzdGVkTG9hZGVycyIsInJlc29sdmVMb2FkZXJRYiIsImxvYWRlZFJvd3MiLCJzdWJSb3dHcm91cHMiLCJyIiwibmVzdGVkS2V5cyIsIk9iamVjdCIsImtleXMiLCJrZXkiLCJncm91cHMiLCJncm91cEJ5Iiwic3BsaXQiLCJudWxsS2V5cyIsImVudHJpZXMiLCJfIiwiZGF0YSIsImV2ZXJ5IiwiaHlkcmF0ZWQiLCJyZWR1Y2UiLCJwYXJ0cyIsIm9ialBhdGgiLCJzbGljZSIsInBhcnQiLCJudWxsS2V5IiwicnVuU3Vic2V0UXVlcnkiLCJiYXNlVGFibGUiLCJzdWJzZXRRdWVyeSIsImJ1aWxkIiwiYWZ0ZXJCdWlsZCIsIl9kYiIsImNoYWxrIiwiZ2V0VGFibGVOYW1lIiwic3RhcnRzV2l0aCIsInBsdXJhbGl6ZSIsInVuZGVyc2NvcmUiLCJ1bmRlZmluZWQiLCJ2aXJ0dWFsIiwiam9pbnMiLCJmcm9tIiwiYXBwbHlKb2luQ2xhdXNlIiwiaW5uZXJKb2luIiwiZ2V0Sm9pbkNsYXVzZSIsImxlZnRPdXRlckpvaW4iLCJjbG9uZWRRYiIsInRhYmxlcyIsIm5lZWRUb0pvaW4iLCJmbGF0TWFwIiwidCIsInByb2Nlc3NlZFFiIiwicSIsInR5cGUiLCJjb3VudFF1ZXJ5IiwiZGlzdGluY3QiLCJjb2x1bW5zIiwiZXhwciIsImNvbHVtbiIsImNvdW50IiwiY291bnRSb3ciLCJjb25zb2xlIiwiYmx1ZSIsInRvU3RyaW5nIiwibGlzdFF1ZXJ5IiwidXNlTG9hZGVycyIsImxvYWRlciIsInN1YlEiLCJzdWJSb3dzIiwidG9Db2wiLCJmcm9tSWRzIiwibWFueUpvaW4iLCJpZEZpZWxkIiwidGhyb3VnaCIsImlkQ29sdW1uIiwidG9UYWJsZSIsIm9uZUpvaW5zIiwiZnJvbUNvbCIsInRvIiwiY3VzdG9tIiwiQmFzZU1vZGVsIl0sIm1hcHBpbmdzIjoiQUFBQSxPQUFPQSxZQUFZLFNBQVM7QUFD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