@decaf-ts/for-fabric 0.1.48 → 0.1.50

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 (379) hide show
  1. package/dist/for-fabric.cjs +2 -1896
  2. package/dist/for-fabric.cjs.map +1 -0
  3. package/dist/for-fabric.js +2 -2002
  4. package/dist/for-fabric.js.map +1 -0
  5. package/lib/bin/cli.cjs +1 -2
  6. package/lib/bin/cli.js.map +1 -0
  7. package/lib/cli-module.cjs +1 -1
  8. package/lib/cli-module.js.map +1 -0
  9. package/lib/cli-utils.cjs +1 -1
  10. package/lib/cli-utils.js.map +1 -0
  11. package/lib/client/FabricClientAdapter.cjs +1 -1
  12. package/lib/client/FabricClientAdapter.js.map +1 -0
  13. package/lib/client/FabricClientDispatch.cjs +1 -1
  14. package/lib/client/FabricClientDispatch.js.map +1 -0
  15. package/lib/client/FabricClientPaginator.cjs +1 -1
  16. package/lib/client/FabricClientPaginator.js.map +1 -0
  17. package/lib/client/FabricClientRepository.cjs +1 -1
  18. package/lib/client/FabricClientRepository.js.map +1 -0
  19. package/lib/client/FabricClientStatement.cjs +1 -1
  20. package/lib/client/FabricClientStatement.js.map +1 -0
  21. package/lib/client/collections/generation.cjs +1 -1
  22. package/lib/client/collections/generation.js.map +1 -0
  23. package/lib/client/collections/index.cjs +1 -1
  24. package/lib/client/collections/index.js.map +1 -0
  25. package/lib/client/constants.cjs +1 -1
  26. package/lib/client/constants.js.map +1 -0
  27. package/lib/client/erc20/FabricERC20ClientRepository.cjs +1 -1
  28. package/lib/client/erc20/FabricERC20ClientRepository.js.map +1 -0
  29. package/lib/client/erc20/index.cjs +1 -1
  30. package/lib/client/erc20/index.js.map +1 -0
  31. package/lib/client/fabric-fs.cjs +10 -10
  32. package/lib/client/fabric-fs.d.ts +1 -1
  33. package/lib/client/fabric-fs.js.map +1 -0
  34. package/lib/client/fabric-hsm.cjs +1 -1
  35. package/lib/client/fabric-hsm.js.map +1 -0
  36. package/lib/client/index.cjs +1 -1
  37. package/lib/client/index.js.map +1 -0
  38. package/lib/client/indexes/generation.cjs +1 -1
  39. package/lib/client/indexes/generation.js.map +1 -0
  40. package/lib/client/indexes/index.cjs +1 -1
  41. package/lib/client/indexes/index.js.map +1 -0
  42. package/lib/client/logging.cjs +1 -1
  43. package/lib/client/logging.js.map +1 -0
  44. package/lib/client/services/FabricEnrollmentService.cjs +1 -1
  45. package/lib/client/services/FabricEnrollmentService.js.map +1 -0
  46. package/lib/client/services/FabricIdentityService.cjs +1 -1
  47. package/lib/client/services/FabricIdentityService.js.map +1 -0
  48. package/lib/client/services/RegistrationRequestBuilder.cjs +1 -1
  49. package/lib/client/services/RegistrationRequestBuilder.js.map +1 -0
  50. package/lib/client/services/constants.cjs +1 -1
  51. package/lib/client/services/constants.js.map +1 -0
  52. package/lib/client/services/index.cjs +1 -1
  53. package/lib/client/services/index.js.map +1 -0
  54. package/lib/client/types.cjs +1 -1
  55. package/lib/client/types.js.map +1 -0
  56. package/lib/contract/Address.cjs +1 -1
  57. package/lib/contract/Address.js.map +1 -0
  58. package/lib/contract/AddressContract.cjs +1 -1
  59. package/lib/contract/AddressContract.js.map +1 -0
  60. package/lib/contract/BatchContract.cjs +1 -1
  61. package/lib/contract/BatchContract.js.map +1 -0
  62. package/lib/contract/Product.cjs +1 -1
  63. package/lib/contract/Product.js.map +1 -0
  64. package/lib/contract/ProductContract.cjs +1 -1
  65. package/lib/contract/ProductContract.js.map +1 -0
  66. package/lib/contract/User.cjs +1 -1
  67. package/lib/contract/User.js.map +1 -0
  68. package/lib/contract/UserContract.cjs +1 -1
  69. package/lib/contract/UserContract.js.map +1 -0
  70. package/lib/contract/index.cjs +1 -1
  71. package/lib/contract/index.js.map +1 -0
  72. package/lib/contract/models/Audit.cjs +1 -1
  73. package/lib/contract/models/Audit.js.map +1 -0
  74. package/lib/contract/models/BaseIdentifiedModel.cjs +1 -1
  75. package/lib/contract/models/BaseIdentifiedModel.js.map +1 -0
  76. package/lib/contract/models/BaseModel.cjs +1 -1
  77. package/lib/contract/models/BaseModel.js.map +1 -0
  78. package/lib/contract/models/Batch.cjs +1 -1
  79. package/lib/contract/models/Batch.js.map +1 -0
  80. package/lib/contract/models/Leaflet.cjs +1 -1
  81. package/lib/contract/models/Leaflet.js.map +1 -0
  82. package/lib/contract/models/LeafletFile.cjs +1 -1
  83. package/lib/contract/models/LeafletFile.js.map +1 -0
  84. package/lib/contract/models/Market.cjs +1 -1
  85. package/lib/contract/models/Market.js.map +1 -0
  86. package/lib/contract/models/Product.cjs +1 -1
  87. package/lib/contract/models/Product.js.map +1 -0
  88. package/lib/contract/models/ProductStrength.cjs +1 -1
  89. package/lib/contract/models/ProductStrength.js.map +1 -0
  90. package/lib/contract/models/constants.cjs +1 -1
  91. package/lib/contract/models/constants.js.map +1 -0
  92. package/lib/contract/models/decorators.cjs +1 -1
  93. package/lib/contract/models/decorators.js.map +1 -0
  94. package/lib/contract/models/gtin.cjs +1 -1
  95. package/lib/contract/models/gtin.js.map +1 -0
  96. package/lib/contracts/ContractAdapter.cjs +1 -1
  97. package/lib/contracts/ContractAdapter.js.map +1 -0
  98. package/lib/contracts/ContractContext.cjs +1 -1
  99. package/lib/contracts/ContractContext.js.map +1 -0
  100. package/lib/contracts/ContractPrivateDataAdapter.cjs +1 -1
  101. package/lib/contracts/ContractPrivateDataAdapter.js.map +1 -0
  102. package/lib/contracts/FabricConstruction.cjs +1 -1
  103. package/lib/contracts/FabricConstruction.js.map +1 -0
  104. package/lib/contracts/FabricContractPaginator.cjs +1 -1
  105. package/lib/contracts/FabricContractPaginator.js.map +1 -0
  106. package/lib/contracts/FabricContractRepository.cjs +1 -1
  107. package/lib/contracts/FabricContractRepository.js.map +1 -0
  108. package/lib/contracts/FabricContractRepositoryObservableHandler.cjs +1 -1
  109. package/lib/contracts/FabricContractRepositoryObservableHandler.js.map +1 -0
  110. package/lib/contracts/FabricContractSequence.cjs +1 -1
  111. package/lib/contracts/FabricContractSequence.js.map +1 -0
  112. package/lib/contracts/FabricContractStatement.cjs +1 -1
  113. package/lib/contracts/FabricContractStatement.js.map +1 -0
  114. package/lib/contracts/PrivateSequence.cjs +1 -1
  115. package/lib/contracts/PrivateSequence.js.map +1 -0
  116. package/lib/contracts/crud/crud-contract.cjs +1 -1
  117. package/lib/contracts/crud/crud-contract.js.map +1 -0
  118. package/lib/contracts/crud/index.cjs +1 -1
  119. package/lib/contracts/crud/index.js.map +1 -0
  120. package/lib/contracts/crud/serialized-crud-contract.cjs +1 -1
  121. package/lib/contracts/crud/serialized-crud-contract.js.map +1 -0
  122. package/lib/contracts/erc20/erc20contract.cjs +1 -1
  123. package/lib/contracts/erc20/erc20contract.js.map +1 -0
  124. package/lib/contracts/erc20/index.cjs +1 -1
  125. package/lib/contracts/erc20/index.js.map +1 -0
  126. package/lib/contracts/erc20/models.cjs +1 -1
  127. package/lib/contracts/erc20/models.js.map +1 -0
  128. package/lib/contracts/index.cjs +1 -1
  129. package/lib/contracts/index.js.map +1 -0
  130. package/lib/contracts/logging.cjs +1 -1
  131. package/lib/contracts/logging.js.map +1 -0
  132. package/lib/contracts/private-data.cjs +1 -1
  133. package/lib/contracts/private-data.js.map +1 -0
  134. package/lib/contracts/types.cjs +1 -1
  135. package/lib/contracts/types.js.map +1 -0
  136. package/lib/esm/bin/cli.js +1 -1
  137. package/lib/esm/bin/cli.js.map +1 -0
  138. package/lib/esm/cli-module.js +1 -1
  139. package/lib/esm/cli-module.js.map +1 -0
  140. package/lib/esm/cli-utils.js +1 -1
  141. package/lib/esm/cli-utils.js.map +1 -0
  142. package/lib/esm/client/FabricClientAdapter.js +1 -1
  143. package/lib/esm/client/FabricClientAdapter.js.map +1 -0
  144. package/lib/esm/client/FabricClientDispatch.js +1 -1
  145. package/lib/esm/client/FabricClientDispatch.js.map +1 -0
  146. package/lib/esm/client/FabricClientPaginator.js +1 -1
  147. package/lib/esm/client/FabricClientPaginator.js.map +1 -0
  148. package/lib/esm/client/FabricClientRepository.js +1 -1
  149. package/lib/esm/client/FabricClientRepository.js.map +1 -0
  150. package/lib/esm/client/FabricClientStatement.js +1 -1
  151. package/lib/esm/client/FabricClientStatement.js.map +1 -0
  152. package/lib/esm/client/collections/generation.js +1 -1
  153. package/lib/esm/client/collections/generation.js.map +1 -0
  154. package/lib/esm/client/collections/index.js +1 -1
  155. package/lib/esm/client/collections/index.js.map +1 -0
  156. package/lib/esm/client/constants.js +1 -1
  157. package/lib/esm/client/constants.js.map +1 -0
  158. package/lib/esm/client/erc20/FabricERC20ClientRepository.js +1 -1
  159. package/lib/esm/client/erc20/FabricERC20ClientRepository.js.map +1 -0
  160. package/lib/esm/client/erc20/index.js +1 -1
  161. package/lib/esm/client/erc20/index.js.map +1 -0
  162. package/lib/esm/client/fabric-fs.d.ts +1 -1
  163. package/lib/esm/client/fabric-fs.js +2 -2
  164. package/lib/esm/client/fabric-fs.js.map +1 -0
  165. package/lib/esm/client/fabric-hsm.js +1 -1
  166. package/lib/esm/client/fabric-hsm.js.map +1 -0
  167. package/lib/esm/client/index.js +1 -1
  168. package/lib/esm/client/index.js.map +1 -0
  169. package/lib/esm/client/indexes/generation.js +1 -1
  170. package/lib/esm/client/indexes/generation.js.map +1 -0
  171. package/lib/esm/client/indexes/index.js +1 -1
  172. package/lib/esm/client/indexes/index.js.map +1 -0
  173. package/lib/esm/client/logging.js +1 -1
  174. package/lib/esm/client/logging.js.map +1 -0
  175. package/lib/esm/client/services/FabricEnrollmentService.js +1 -1
  176. package/lib/esm/client/services/FabricEnrollmentService.js.map +1 -0
  177. package/lib/esm/client/services/FabricIdentityService.js +1 -1
  178. package/lib/esm/client/services/FabricIdentityService.js.map +1 -0
  179. package/lib/esm/client/services/RegistrationRequestBuilder.js +1 -1
  180. package/lib/esm/client/services/RegistrationRequestBuilder.js.map +1 -0
  181. package/lib/esm/client/services/constants.js +1 -1
  182. package/lib/esm/client/services/constants.js.map +1 -0
  183. package/lib/esm/client/services/index.js +1 -1
  184. package/lib/esm/client/services/index.js.map +1 -0
  185. package/lib/esm/client/types.js +1 -1
  186. package/lib/esm/client/types.js.map +1 -0
  187. package/lib/esm/contract/Address.js +1 -1
  188. package/lib/esm/contract/Address.js.map +1 -0
  189. package/lib/esm/contract/AddressContract.js +1 -1
  190. package/lib/esm/contract/AddressContract.js.map +1 -0
  191. package/lib/esm/contract/BatchContract.js +1 -1
  192. package/lib/esm/contract/BatchContract.js.map +1 -0
  193. package/lib/esm/contract/Product.js +1 -1
  194. package/lib/esm/contract/Product.js.map +1 -0
  195. package/lib/esm/contract/ProductContract.js +1 -1
  196. package/lib/esm/contract/ProductContract.js.map +1 -0
  197. package/lib/esm/contract/User.js +1 -1
  198. package/lib/esm/contract/User.js.map +1 -0
  199. package/lib/esm/contract/UserContract.js +1 -1
  200. package/lib/esm/contract/UserContract.js.map +1 -0
  201. package/lib/esm/contract/index.js +1 -1
  202. package/lib/esm/contract/index.js.map +1 -0
  203. package/lib/esm/contract/models/Audit.js +1 -1
  204. package/lib/esm/contract/models/Audit.js.map +1 -0
  205. package/lib/esm/contract/models/BaseIdentifiedModel.js +1 -1
  206. package/lib/esm/contract/models/BaseIdentifiedModel.js.map +1 -0
  207. package/lib/esm/contract/models/BaseModel.js +1 -1
  208. package/lib/esm/contract/models/BaseModel.js.map +1 -0
  209. package/lib/esm/contract/models/Batch.js +1 -1
  210. package/lib/esm/contract/models/Batch.js.map +1 -0
  211. package/lib/esm/contract/models/Leaflet.js +1 -1
  212. package/lib/esm/contract/models/Leaflet.js.map +1 -0
  213. package/lib/esm/contract/models/LeafletFile.js +1 -1
  214. package/lib/esm/contract/models/LeafletFile.js.map +1 -0
  215. package/lib/esm/contract/models/Market.js +1 -1
  216. package/lib/esm/contract/models/Market.js.map +1 -0
  217. package/lib/esm/contract/models/Product.js +1 -1
  218. package/lib/esm/contract/models/Product.js.map +1 -0
  219. package/lib/esm/contract/models/ProductStrength.js +1 -1
  220. package/lib/esm/contract/models/ProductStrength.js.map +1 -0
  221. package/lib/esm/contract/models/constants.js +1 -1
  222. package/lib/esm/contract/models/constants.js.map +1 -0
  223. package/lib/esm/contract/models/decorators.js +1 -1
  224. package/lib/esm/contract/models/decorators.js.map +1 -0
  225. package/lib/esm/contract/models/gtin.js +1 -1
  226. package/lib/esm/contract/models/gtin.js.map +1 -0
  227. package/lib/esm/contracts/ContractAdapter.js +1 -1
  228. package/lib/esm/contracts/ContractAdapter.js.map +1 -0
  229. package/lib/esm/contracts/ContractContext.js +1 -1
  230. package/lib/esm/contracts/ContractContext.js.map +1 -0
  231. package/lib/esm/contracts/ContractPrivateDataAdapter.js +1 -1
  232. package/lib/esm/contracts/ContractPrivateDataAdapter.js.map +1 -0
  233. package/lib/esm/contracts/FabricConstruction.js +1 -1
  234. package/lib/esm/contracts/FabricConstruction.js.map +1 -0
  235. package/lib/esm/contracts/FabricContractPaginator.js +1 -1
  236. package/lib/esm/contracts/FabricContractPaginator.js.map +1 -0
  237. package/lib/esm/contracts/FabricContractRepository.js +1 -1
  238. package/lib/esm/contracts/FabricContractRepository.js.map +1 -0
  239. package/lib/esm/contracts/FabricContractRepositoryObservableHandler.js +1 -1
  240. package/lib/esm/contracts/FabricContractRepositoryObservableHandler.js.map +1 -0
  241. package/lib/esm/contracts/FabricContractSequence.js +1 -1
  242. package/lib/esm/contracts/FabricContractSequence.js.map +1 -0
  243. package/lib/esm/contracts/FabricContractStatement.js +1 -1
  244. package/lib/esm/contracts/FabricContractStatement.js.map +1 -0
  245. package/lib/esm/contracts/PrivateSequence.js +1 -1
  246. package/lib/esm/contracts/PrivateSequence.js.map +1 -0
  247. package/lib/esm/contracts/crud/crud-contract.js +1 -1
  248. package/lib/esm/contracts/crud/crud-contract.js.map +1 -0
  249. package/lib/esm/contracts/crud/index.js +1 -1
  250. package/lib/esm/contracts/crud/index.js.map +1 -0
  251. package/lib/esm/contracts/crud/serialized-crud-contract.js +1 -1
  252. package/lib/esm/contracts/crud/serialized-crud-contract.js.map +1 -0
  253. package/lib/esm/contracts/erc20/erc20contract.js +1 -1
  254. package/lib/esm/contracts/erc20/erc20contract.js.map +1 -0
  255. package/lib/esm/contracts/erc20/index.js +1 -1
  256. package/lib/esm/contracts/erc20/index.js.map +1 -0
  257. package/lib/esm/contracts/erc20/models.js +1 -1
  258. package/lib/esm/contracts/erc20/models.js.map +1 -0
  259. package/lib/esm/contracts/index.js +1 -1
  260. package/lib/esm/contracts/index.js.map +1 -0
  261. package/lib/esm/contracts/logging.js +1 -1
  262. package/lib/esm/contracts/logging.js.map +1 -0
  263. package/lib/esm/contracts/private-data.js +1 -1
  264. package/lib/esm/contracts/private-data.js.map +1 -0
  265. package/lib/esm/contracts/types.js +1 -1
  266. package/lib/esm/contracts/types.js.map +1 -0
  267. package/lib/esm/index.js +1 -1
  268. package/lib/esm/index.js.map +1 -0
  269. package/lib/esm/shared/ClientSerializer.js +1 -1
  270. package/lib/esm/shared/ClientSerializer.js.map +1 -0
  271. package/lib/esm/shared/DeterministicSerializer.js +1 -1
  272. package/lib/esm/shared/DeterministicSerializer.js.map +1 -0
  273. package/lib/esm/shared/SimpleDeterministicSerializer.js +1 -1
  274. package/lib/esm/shared/SimpleDeterministicSerializer.js.map +1 -0
  275. package/lib/esm/shared/constants.js +1 -1
  276. package/lib/esm/shared/constants.js.map +1 -0
  277. package/lib/esm/shared/crypto.js +1 -1
  278. package/lib/esm/shared/crypto.js.map +1 -0
  279. package/lib/esm/shared/decorators.js +1 -1
  280. package/lib/esm/shared/decorators.js.map +1 -0
  281. package/lib/esm/shared/erc20/erc20-constants.js +1 -1
  282. package/lib/esm/shared/erc20/erc20-constants.js.map +1 -0
  283. package/lib/esm/shared/erc20/index.js +1 -1
  284. package/lib/esm/shared/erc20/index.js.map +1 -0
  285. package/lib/esm/shared/errors.js +1 -1
  286. package/lib/esm/shared/errors.js.map +1 -0
  287. package/lib/esm/shared/events.js +1 -1
  288. package/lib/esm/shared/events.js.map +1 -0
  289. package/lib/esm/shared/fabric-types.js +1 -1
  290. package/lib/esm/shared/fabric-types.js.map +1 -0
  291. package/lib/esm/shared/index.js +1 -1
  292. package/lib/esm/shared/index.js.map +1 -0
  293. package/lib/esm/shared/interfaces/Checkable.js +1 -1
  294. package/lib/esm/shared/interfaces/Checkable.js.map +1 -0
  295. package/lib/esm/shared/interfaces/index.js +1 -1
  296. package/lib/esm/shared/interfaces/index.js.map +1 -0
  297. package/lib/esm/shared/math.js +1 -1
  298. package/lib/esm/shared/math.js.map +1 -0
  299. package/lib/esm/shared/model/FabricBaseModel.js +1 -1
  300. package/lib/esm/shared/model/FabricBaseModel.js.map +1 -0
  301. package/lib/esm/shared/model/FabricIdentifiedBaseModel.js +1 -1
  302. package/lib/esm/shared/model/FabricIdentifiedBaseModel.js.map +1 -0
  303. package/lib/esm/shared/model/Identity.js +1 -1
  304. package/lib/esm/shared/model/Identity.js.map +1 -0
  305. package/lib/esm/shared/model/IdentityCredentials.js +1 -1
  306. package/lib/esm/shared/model/IdentityCredentials.js.map +1 -0
  307. package/lib/esm/shared/model/index.js +1 -1
  308. package/lib/esm/shared/model/index.js.map +1 -0
  309. package/lib/esm/shared/overrides/Model.js +1 -1
  310. package/lib/esm/shared/overrides/Model.js.map +1 -0
  311. package/lib/esm/shared/overrides/index.js +1 -1
  312. package/lib/esm/shared/overrides/index.js.map +1 -0
  313. package/lib/esm/shared/overrides/overrides.js +1 -1
  314. package/lib/esm/shared/overrides/overrides.js.map +1 -0
  315. package/lib/esm/shared/types.js +1 -1
  316. package/lib/esm/shared/types.js.map +1 -0
  317. package/lib/esm/shared/utils.d.ts +0 -13
  318. package/lib/esm/shared/utils.js +2 -17
  319. package/lib/esm/shared/utils.js.map +1 -0
  320. package/lib/esm/version.d.ts +1 -1
  321. package/lib/esm/version.js +2 -2
  322. package/lib/esm/version.js.map +1 -0
  323. package/lib/index.cjs +1 -1
  324. package/lib/index.js.map +1 -0
  325. package/lib/shared/ClientSerializer.cjs +1 -1
  326. package/lib/shared/ClientSerializer.js.map +1 -0
  327. package/lib/shared/DeterministicSerializer.cjs +1 -1
  328. package/lib/shared/DeterministicSerializer.js.map +1 -0
  329. package/lib/shared/SimpleDeterministicSerializer.cjs +1 -1
  330. package/lib/shared/SimpleDeterministicSerializer.js.map +1 -0
  331. package/lib/shared/constants.cjs +1 -1
  332. package/lib/shared/constants.js.map +1 -0
  333. package/lib/shared/crypto.cjs +1 -1
  334. package/lib/shared/crypto.js.map +1 -0
  335. package/lib/shared/decorators.cjs +1 -1
  336. package/lib/shared/decorators.js.map +1 -0
  337. package/lib/shared/erc20/erc20-constants.cjs +1 -1
  338. package/lib/shared/erc20/erc20-constants.js.map +1 -0
  339. package/lib/shared/erc20/index.cjs +1 -1
  340. package/lib/shared/erc20/index.js.map +1 -0
  341. package/lib/shared/errors.cjs +1 -1
  342. package/lib/shared/errors.js.map +1 -0
  343. package/lib/shared/events.cjs +1 -1
  344. package/lib/shared/events.js.map +1 -0
  345. package/lib/shared/fabric-types.cjs +1 -1
  346. package/lib/shared/fabric-types.js.map +1 -0
  347. package/lib/shared/index.cjs +1 -1
  348. package/lib/shared/index.js.map +1 -0
  349. package/lib/shared/interfaces/Checkable.cjs +1 -1
  350. package/lib/shared/interfaces/Checkable.js.map +1 -0
  351. package/lib/shared/interfaces/index.cjs +1 -1
  352. package/lib/shared/interfaces/index.js.map +1 -0
  353. package/lib/shared/math.cjs +1 -1
  354. package/lib/shared/math.js.map +1 -0
  355. package/lib/shared/model/FabricBaseModel.cjs +1 -1
  356. package/lib/shared/model/FabricBaseModel.js.map +1 -0
  357. package/lib/shared/model/FabricIdentifiedBaseModel.cjs +1 -1
  358. package/lib/shared/model/FabricIdentifiedBaseModel.js.map +1 -0
  359. package/lib/shared/model/Identity.cjs +1 -1
  360. package/lib/shared/model/Identity.js.map +1 -0
  361. package/lib/shared/model/IdentityCredentials.cjs +1 -1
  362. package/lib/shared/model/IdentityCredentials.js.map +1 -0
  363. package/lib/shared/model/index.cjs +1 -1
  364. package/lib/shared/model/index.js.map +1 -0
  365. package/lib/shared/overrides/Model.cjs +1 -1
  366. package/lib/shared/overrides/Model.js.map +1 -0
  367. package/lib/shared/overrides/index.cjs +1 -1
  368. package/lib/shared/overrides/index.js.map +1 -0
  369. package/lib/shared/overrides/overrides.cjs +1 -1
  370. package/lib/shared/overrides/overrides.js.map +1 -0
  371. package/lib/shared/types.cjs +1 -1
  372. package/lib/shared/types.js.map +1 -0
  373. package/lib/shared/utils.cjs +12 -28
  374. package/lib/shared/utils.d.ts +0 -13
  375. package/lib/shared/utils.js.map +1 -0
  376. package/lib/version.cjs +2 -2
  377. package/lib/version.d.ts +1 -1
  378. package/lib/version.js.map +1 -0
  379. package/package.json +1 -1
@@ -1,1896 +1,2 @@
1
- (function(global, factory) {
2
- typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("@decaf-ts/for-couchdb"), require("@decaf-ts/decorator-validation"), require("@decaf-ts/core"), require("@decaf-ts/db-decorators"), require("fabric-contract-api"), require("@decaf-ts/decoration"), require("@decaf-ts/logging"), require("tslib")) : typeof define === "function" && define.amd ? define([ "exports", "@decaf-ts/for-couchdb", "@decaf-ts/decorator-validation", "@decaf-ts/core", "@decaf-ts/db-decorators", "fabric-contract-api", "@decaf-ts/decoration", "@decaf-ts/logging", "tslib" ], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self,
3
- factory(global["for-fabric"] = {}, global.decafTsForCouchdb, global.decafTsDecoratorValidation, global.decafTsCore, global.decafTsDbDecorators, global.fabricContractApi, global.decafTsDecoration, global.decafTsLogging, global.tslib));
4
- })(this, function(exports, forCouchdb, decoratorValidation, core, dbDecorators, fabricContractApi, decoration, logging, tslib) {
5
- "use strict";
6
- class FabricContractContext extends core.Context {
7
- constructor() {
8
- super();
9
- }
10
- get stub() {
11
- return this.get("stub");
12
- }
13
- get timestamp() {
14
- return this.stub.getDateTimestamp();
15
- }
16
- get identity() {
17
- return this.get("identity");
18
- }
19
- toString() {
20
- return `fabric ctx${this.stub ? " with stub" : "without stub"}`;
21
- }
22
- }
23
- function generateFabricEventName(table, event, owner) {
24
- const params = [ table, event ];
25
- if (owner) params.push(owner);
26
- return params.join("_");
27
- }
28
- function parseEventName(name) {
29
- const parts = name.split("_");
30
- if (parts.length < 2 || parts.length > 3) return {
31
- table: undefined,
32
- event: name,
33
- owner: undefined
34
- };
35
- return {
36
- table: parts[0],
37
- event: parts[1],
38
- owner: parts[2]
39
- };
40
- }
41
- class FabricContractRepositoryObservableHandler extends core.ObserverHandler {
42
- constructor(supportedEvents = [ dbDecorators.OperationKeys.CREATE, dbDecorators.OperationKeys.UPDATE, dbDecorators.OperationKeys.DELETE, dbDecorators.BulkCrudOperationKeys.CREATE_ALL, dbDecorators.BulkCrudOperationKeys.UPDATE_ALL, dbDecorators.BulkCrudOperationKeys.DELETE_ALL ]) {
43
- super();
44
- this.supportedEvents = supportedEvents;
45
- }
46
- async updateObservers(clazz, event, id, ...args) {
47
- const {log: log, ctx: ctx} = core.Adapter.logCtx(args, this.updateObservers);
48
- const {stub: stub} = ctx;
49
- const [owner, payload] = args;
50
- const table = typeof clazz === "string" ? clazz : clazz.name;
51
- if (this.supportedEvents.indexOf(event) !== -1) {
52
- log.debug(`Emitting ${event} event`);
53
- const eventName = generateFabricEventName(table, event, owner);
54
- stub.setEvent(eventName, Buffer.from(JSON.stringify({
55
- id: id
56
- })));
57
- } else {
58
- stub.setEvent(event, Buffer.from(JSON.stringify(payload)));
59
- }
60
- }
61
- }
62
- class FabricContractRepository extends core.Repository {
63
- constructor(adapter, clazz, trackedEvents) {
64
- super(adapter, clazz);
65
- this.trackedEvents = trackedEvents;
66
- this._overrides = Object.assign({}, super["_overrides"], {
67
- ignoreValidation: false,
68
- ignoreHandlers: false,
69
- allowRawStatements: true,
70
- forcePrepareSimpleQueries: false,
71
- forcePrepareComplexQueries: false
72
- });
73
- }
74
- async paginateBy(key, order, ref = {
75
- offset: 1,
76
- limit: 10
77
- }, ...args) {
78
- let {offset: offset, bookmark: bookmark, limit: limit} = ref;
79
- if (!offset && !bookmark) throw new core.QueryError(`PaginateBy needs a page or a bookmark`);
80
- const contextArgs = await core.Context.args(core.PreparedStatementKeys.PAGE_BY, this.class, args, this.adapter, this._overrides || {});
81
- const {log: log, ctxArgs: ctxArgs} = this.logCtx(contextArgs.args, this.paginateBy);
82
- log.verbose(`paginating ${decoratorValidation.Model.tableName(this.class)} with page size ${limit}`);
83
- let paginator;
84
- if (bookmark) {
85
- paginator = await this.override({
86
- forcePrepareComplexQueries: false,
87
- forcePrepareSimpleQueries: false
88
- }).select().where(this.attr(decoratorValidation.Model.pk(this.class)).gt(bookmark)).orderBy([ key, order ]).paginate(limit, ...ctxArgs);
89
- offset = 1;
90
- } else if (offset) {
91
- paginator = await this.override({
92
- forcePrepareComplexQueries: false,
93
- forcePrepareSimpleQueries: false
94
- }).select().orderBy([ key, order ]).paginate(limit, ...ctxArgs);
95
- } else {
96
- throw new core.QueryError(`PaginateBy needs a page or a bookmark`);
97
- }
98
- const paged = await paginator.page(offset, ...ctxArgs);
99
- return paginator.serialize(paged);
100
- }
101
- async statement(name, ...args) {
102
- if (!core.Repository.statements(this, name)) throw new core.QueryError(`Invalid prepared statement requested ${name}`);
103
- const contextArgs = await core.Context.args(core.PersistenceKeys.STATEMENT, this.class, args, this.adapter, this._overrides || {});
104
- if (contextArgs.context.logger) {
105
- contextArgs.context.logger.info(`Repo statement: ${name} + ${args}`);
106
- }
107
- const {log: log, ctxArgs: ctxArgs} = this.logCtx(contextArgs.args, this.statement);
108
- log.verbose(`Executing prepared statement ${name} with args ${ctxArgs}`);
109
- let result;
110
- try {
111
- result = await this[name](...ctxArgs);
112
- } catch (e) {
113
- if (e instanceof dbDecorators.BaseError) throw e;
114
- throw new dbDecorators.InternalError(`Failed to execute prepared statement ${name} with args ${ctxArgs}: ${e}`);
115
- }
116
- return result;
117
- }
118
- ObserverHandler() {
119
- return new FabricContractRepositoryObservableHandler;
120
- }
121
- async updateObservers(table, event, id, ...args) {
122
- if (!this.trackedEvents || this.trackedEvents.indexOf(event) !== -1) return await super.updateObservers(table, event, id, ...args);
123
- }
124
- }
125
- class FabricStatement extends forCouchdb.CouchDBStatement {
126
- constructor(adapter) {
127
- super(adapter);
128
- }
129
- async raw(rawInput, ...args) {
130
- const {ctx: ctx} = this.logCtx(args, this.raw);
131
- const results = await this.adapter.raw(rawInput, true, ctx);
132
- const pkAttr = decoratorValidation.Model.pk(this.fromSelector);
133
- const type = decoration.Metadata.get(this.fromSelector, decoration.Metadata.key(dbDecorators.DBKeys.ID, pkAttr))?.type;
134
- if (!this.selectSelector) return results.map(r => this.processRecord(r, pkAttr, type, ctx));
135
- return results;
136
- }
137
- build() {
138
- const selectors = {};
139
- selectors[forCouchdb.CouchDBKeys.TABLE] = {};
140
- selectors[forCouchdb.CouchDBKeys.TABLE] = decoratorValidation.Model.tableName(this.fromSelector);
141
- const query = {
142
- selector: selectors
143
- };
144
- if (this.selectSelector) query.fields = this.selectSelector;
145
- if (this.whereCondition) {
146
- const condition = this.parseCondition(core.Condition.and(this.whereCondition, core.Condition.attribute(forCouchdb.CouchDBKeys.TABLE).eq(query.selector[forCouchdb.CouchDBKeys.TABLE]))).selector;
147
- const selectorKeys = Object.keys(condition);
148
- if (selectorKeys.length === 1 && Object.values(forCouchdb.CouchDBGroupOperator).indexOf(selectorKeys[0]) !== -1) switch (selectorKeys[0]) {
149
- case forCouchdb.CouchDBGroupOperator.AND:
150
- condition[forCouchdb.CouchDBGroupOperator.AND] = [ ...Object.values(condition[forCouchdb.CouchDBGroupOperator.AND]).reduce((accum, val) => {
151
- const keys = Object.keys(val);
152
- if (keys.length !== 1) throw new Error("Too many keys in query selector. should be one");
153
- const k = keys[0];
154
- if (k === forCouchdb.CouchDBGroupOperator.AND) accum.push(...val[k]); else accum.push(val);
155
- return accum;
156
- }, []) ];
157
- query.selector = condition;
158
- break;
159
-
160
- case forCouchdb.CouchDBGroupOperator.OR:
161
- {
162
- const s = {};
163
- s[forCouchdb.CouchDBGroupOperator.AND] = [ condition, ...Object.entries(query.selector).map(([key, val]) => {
164
- const result = {};
165
- result[key] = val;
166
- return result;
167
- }) ];
168
- query.selector = s;
169
- break;
170
- }
171
-
172
- default:
173
- throw new Error("This should be impossible");
174
- } else {
175
- Object.entries(condition).forEach(([key, val]) => {
176
- if (query.selector[key]) console.warn(`A ${key} query param is about to be overridden: ${query.selector[key]} by ${val}`);
177
- query.selector[key] = val;
178
- });
179
- }
180
- }
181
- if (this.orderBySelector) {
182
- query.sort = query.sort || [];
183
- query.selector = query.selector || {};
184
- const [selector, value] = this.orderBySelector;
185
- const rec = {};
186
- rec[selector] = value;
187
- query.sort.push(rec);
188
- if (!query.selector[selector]) {
189
- query.selector[selector] = {};
190
- query.selector[selector][forCouchdb.CouchDBOperator.BIGGER] = null;
191
- }
192
- }
193
- if (this.limitSelector) query.limit = this.limitSelector;
194
- if (this.offsetSelector) query.skip = this.offsetSelector;
195
- return query;
196
- }
197
- }
198
- class FabricContractSequence extends core.Sequence {
199
- constructor(options, adapter) {
200
- super(options, adapter);
201
- }
202
- async current(...args) {
203
- const contextArgs = await core.Context.args(dbDecorators.OperationKeys.READ, core.SequenceModel, args, this.adapter);
204
- const ctx = contextArgs.context;
205
- const {name: name, startWith: startWith} = this.options;
206
- try {
207
- const sequence = await this.repo.read(name, ctx);
208
- return this.parse(sequence.current);
209
- } catch (e) {
210
- const log = ctx.logger.for(this.current);
211
- if (e instanceof dbDecorators.NotFoundError) {
212
- let cachedCurrent;
213
- try {
214
- log.debug(`Trying to resolve current sequence ${name} value from context`);
215
- cachedCurrent = ctx.get(name);
216
- log.debug(`Retrieved cached current value for sequence ${name}: ${cachedCurrent}`);
217
- } catch (e) {
218
- log.info(`No cached value for sequence ${name} in context`);
219
- cachedCurrent = startWith;
220
- }
221
- try {
222
- return this.parse(cachedCurrent);
223
- } catch (e) {
224
- throw new dbDecorators.InternalError(`Failed to parse initial value for sequence ${startWith}: ${e}`);
225
- }
226
- }
227
- throw new dbDecorators.InternalError(`Failed to retrieve current value for sequence ${name}: ${e}`);
228
- }
229
- }
230
- async increment(count, ctx) {
231
- const log = ctx.logger.for(this.increment);
232
- const {type: type, incrementBy: incrementBy, name: name} = this.options;
233
- if (!name) throw new dbDecorators.InternalError("Sequence name is required");
234
- log.info(`Obtaining sequence lock for sequence ${name}`);
235
- return FabricContractSequence.lock.execute(async () => {
236
- const toIncrementBy = count || incrementBy;
237
- if (toIncrementBy % incrementBy !== 0) throw new dbDecorators.InternalError(`Value to increment does not consider the incrementBy setting: ${incrementBy}`);
238
- const typeName = typeof type === "function" && type?.name ? type.name : type;
239
- const currentValue = await this.current(ctx);
240
- async function returnAndCache(res) {
241
- if (res instanceof Promise) res = await res;
242
- ctx.logger.for(returnAndCache).info(`Storing new ${name} seq value in cache: ${res.current}`);
243
- ctx.cache.put(name, res.current);
244
- return res;
245
- }
246
- const performUpsert = async next => {
247
- try {
248
- return await returnAndCache(this.repo.update(new core.SequenceModel({
249
- id: name,
250
- current: next
251
- }), ctx));
252
- } catch (e) {
253
- if (e instanceof dbDecorators.NotFoundError) {
254
- log.debug(`Sequence create ${name} current=${currentValue} next=${next}`);
255
- return returnAndCache(this.repo.create(new core.SequenceModel({
256
- id: name,
257
- current: next
258
- }), ctx));
259
- }
260
- throw e;
261
- }
262
- };
263
- const incrementSerial = base => {
264
- switch (typeName) {
265
- case Number.name:
266
- return this.parse(base) + toIncrementBy;
267
-
268
- case BigInt.name:
269
- return this.parse(base) + BigInt(toIncrementBy);
270
-
271
- case String.name:
272
- return this.parse(base);
273
-
274
- case "serial":
275
- return core.Serial.instance.generate(base);
276
-
277
- default:
278
- throw new dbDecorators.InternalError("Should never happen");
279
- }
280
- };
281
- if (typeName === "uuid") {
282
- while (true) {
283
- const next = core.UUID.instance.generate(currentValue);
284
- try {
285
- const result = await performUpsert(next);
286
- log.debug(`Sequence uuid increment ${name} current=${currentValue} next=${next}`);
287
- return result.current;
288
- } catch (e) {
289
- if (e instanceof dbDecorators.ConflictError) continue;
290
- throw e;
291
- }
292
- }
293
- }
294
- const next = incrementSerial(currentValue);
295
- const seq = await performUpsert(next);
296
- log.debug(`Sequence.increment ${name} current=${currentValue} next=${next}`);
297
- return seq.current;
298
- }, name);
299
- }
300
- }
301
- var FabricModelKeys;
302
- (function(FabricModelKeys) {
303
- FabricModelKeys["PRIVATE"] = "private";
304
- FabricModelKeys["SHARED"] = "shared";
305
- FabricModelKeys["FABRIC"] = "fabric.";
306
- FabricModelKeys["OWNEDBY"] = "owned-by";
307
- FabricModelKeys["TRANSACTION_ID"] = "transaction-id";
308
- })(FabricModelKeys || (FabricModelKeys = {}));
309
- var IdentityType;
310
- (function(IdentityType) {
311
- IdentityType["X509"] = "X.509";
312
- })(IdentityType || (IdentityType = {}));
313
- const FabricFlavour = "hlf-fabric";
314
- class SimpleDeterministicSerializer extends decoratorValidation.JSONSerializer {
315
- constructor() {
316
- super();
317
- }
318
- deserialize(str, tableName) {
319
- const deserialization = JSON.parse(str);
320
- return deserialization;
321
- }
322
- serialize(model, putAnchor = true) {
323
- const stringify = require("json-stringify-deterministic");
324
- const sortKeysRecursive = require("sort-keys-recursive");
325
- const preSerialization = this.preSerialize(model, putAnchor);
326
- return stringify(sortKeysRecursive(preSerialization));
327
- }
328
- preSerialize(model, putAnchor = true) {
329
- const toSerialize = Object.assign({}, model);
330
- let metadata;
331
- try {
332
- metadata = decoration.Metadata.modelName(model.constructor);
333
- } catch (error) {
334
- metadata = undefined;
335
- }
336
- if (putAnchor) toSerialize[decoratorValidation.ModelKeys.ANCHOR] = metadata || model.constructor.name;
337
- function preSerialize(obj) {
338
- if (typeof obj !== "object") return obj;
339
- if (Array.isArray(obj)) return obj.map(preSerialize);
340
- return this.preSerialize(obj);
341
- }
342
- decoratorValidation.Model.relations(model).forEach(r => {
343
- toSerialize[r] = preSerialize.call(this, toSerialize[r]);
344
- });
345
- return toSerialize;
346
- }
347
- }
348
- class ContractLogger extends logging.MiniLogger {
349
- constructor(context, conf, ctx) {
350
- super(context, conf);
351
- if (!ctx) {
352
- this.logger = new logging.MiniLogger(context, conf);
353
- } else {
354
- this.logger = ctx.logging.getLogger(context);
355
- }
356
- }
357
- log(level, msg, stack) {
358
- if (logging.NumericLogLevels[this.config("level")] < logging.NumericLogLevels[level]) return;
359
- let method;
360
- switch (level) {
361
- case logging.LogLevel.info:
362
- method = this.logger.info;
363
- break;
364
-
365
- case logging.LogLevel.verbose:
366
- method = this.logger.verbose;
367
- break;
368
-
369
- case logging.LogLevel.debug:
370
- method = this.logger.debug;
371
- break;
372
-
373
- case logging.LogLevel.error:
374
- method = this.logger.error;
375
- break;
376
-
377
- case logging.LogLevel.warn:
378
- method = this.logger.warn;
379
- break;
380
-
381
- case logging.LogLevel.silly:
382
- method = this.logger.silly;
383
- break;
384
-
385
- default:
386
- throw new dbDecorators.InternalError("Invalid log level");
387
- }
388
- method.call(this.logger, this.createLog(level, msg, stack));
389
- }
390
- }
391
- const factory = (object, config, ctx) => new ContractLogger(object || ContractLogger.name, config || {}, ctx);
392
- logging.Logging.setFactory(factory);
393
- class FabricContractPaginator extends forCouchdb.CouchDBPaginator {
394
- constructor(adapter, query, size, clazz) {
395
- super(adapter, query, size, clazz);
396
- }
397
- prepare(rawStatement) {
398
- const query = Object.assign({}, rawStatement);
399
- if (query.limit) this.limit = query.limit;
400
- query.limit = this.size;
401
- return query;
402
- }
403
- async page(page = 1, ...args) {
404
- const {ctxArgs: ctxArgs, ctx: ctx} = this.adapter["logCtx"](args, this.page);
405
- if (this.isPreparedStatement()) return this.pagePrepared(page, ...ctxArgs);
406
- const statement = Object.assign({}, this.statement);
407
- if (!this._recordCount || !this._totalPages) {
408
- this._totalPages = this._recordCount = 0;
409
- const results = await this.adapter.raw({
410
- ...statement,
411
- limit: undefined
412
- }, true, ctx) || [];
413
- this._recordCount = results.length;
414
- if (this._recordCount > 0) {
415
- const size = statement?.limit || this.size;
416
- this._totalPages = Math.ceil(this._recordCount / size);
417
- }
418
- }
419
- this.validatePage(page);
420
- if (page !== 1) {
421
- if (!this._bookmark) throw new core.PagingError("No bookmark. Did you start in the first page?");
422
- statement["bookmark"] = this._bookmark;
423
- }
424
- const docs = await this.adapter.raw(statement, false, ctx);
425
- if (!this.clazz) throw new core.PagingError("No statement target defined");
426
- const id = decoratorValidation.Model.pk(this.clazz);
427
- const type = decoration.Metadata.get(this.clazz, decoration.Metadata.key(dbDecorators.DBKeys.ID, id))?.type;
428
- const results = statement.fields && statement.fields.length ? docs : docs.map(d => this.adapter.revert(d, this.clazz, core.Sequence.parseValue(type, d[id]), undefined, ctx));
429
- const direction = statement.sort?.[0] || core.OrderDirection.DSC;
430
- this._bookmark = results[direction === core.OrderDirection.ASC ? results.length - 1 : 0][id];
431
- this._currentPage = page;
432
- return results;
433
- }
434
- }
435
- class OverflowError extends dbDecorators.InternalError {
436
- constructor(msg) {
437
- super(msg, OverflowError.name);
438
- }
439
- }
440
- class BalanceError extends dbDecorators.InternalError {
441
- constructor(msg) {
442
- super(msg, BalanceError.name);
443
- }
444
- }
445
- class AllowanceError extends dbDecorators.InternalError {
446
- constructor(msg) {
447
- super(msg, AllowanceError.name);
448
- }
449
- }
450
- class RegistrationError extends core.AuthorizationError {
451
- constructor(msg) {
452
- super(msg, RegistrationError.name);
453
- }
454
- }
455
- class MissingContextError extends dbDecorators.InternalError {
456
- constructor(msg) {
457
- super(msg, MissingContextError.name, 500);
458
- }
459
- }
460
- class UnauthorizedPrivateDataAccess extends dbDecorators.BaseError {
461
- constructor(msg = "MISSING_PRIVATE_DATA_ERROR_MESSAGE") {
462
- super(UnauthorizedPrivateDataAccess.name, msg, 403);
463
- }
464
- }
465
- class NotInitializedError extends dbDecorators.BaseError {
466
- constructor(msg) {
467
- super(NotInitializedError.name, msg, 409);
468
- }
469
- }
470
- class MissingPKCSS11Lib extends dbDecorators.InternalError {
471
- constructor(msg) {
472
- super(msg, MissingPKCSS11Lib.name, 500);
473
- }
474
- }
475
- class EndorsementError extends dbDecorators.InternalError {
476
- constructor(message) {
477
- super(message, EndorsementError.name, 500);
478
- }
479
- }
480
- class MvccReadConflictError extends dbDecorators.InternalError {
481
- constructor(message) {
482
- super(message, MvccReadConflictError.name, 500);
483
- }
484
- }
485
- class PhantomReadConflictError extends dbDecorators.InternalError {
486
- constructor(message) {
487
- super(message, PhantomReadConflictError.name, 500);
488
- }
489
- }
490
- class EndorsementPolicyError extends dbDecorators.InternalError {
491
- constructor(message) {
492
- super(message, EndorsementPolicyError.name, 500);
493
- }
494
- }
495
- async function createdByOnFabricCreateUpdate(context, data, key, model) {
496
- try {
497
- const user = context.get("identity");
498
- model[key] = user.getID();
499
- } catch (e) {
500
- throw new core.UnsupportedError("No User found in context. Please provide a user in the context");
501
- }
502
- }
503
- async function pkFabricOnCreate(context, data, key, model) {
504
- if (!data.type || model[key]) {
505
- return;
506
- }
507
- const setPrimaryKeyValue = function(target, propertyKey, value) {
508
- Object.defineProperty(target, propertyKey, {
509
- enumerable: true,
510
- writable: false,
511
- configurable: true,
512
- value: value
513
- });
514
- };
515
- if (!data.name) data.name = decoratorValidation.Model.sequenceName(model, "pk");
516
- let sequence;
517
- try {
518
- sequence = await this.adapter.Sequence(data);
519
- } catch (e) {
520
- throw new dbDecorators.InternalError(`Failed to instantiate Sequence ${data.name}: ${e}`);
521
- }
522
- const next = await sequence.next(context);
523
- setPrimaryKeyValue(model, key, next);
524
- }
525
- class FabricContractAdapter extends forCouchdb.CouchDBAdapter {
526
- getClient() {
527
- throw new core.UnsupportedError("Client is not supported in Fabric contracts");
528
- }
529
- static {
530
- this.textDecoder = new TextDecoder("utf8");
531
- }
532
- static {
533
- this.serializer = new SimpleDeterministicSerializer;
534
- }
535
- repository() {
536
- return FabricContractRepository;
537
- }
538
- Paginator(query, size, clazz) {
539
- return new FabricContractPaginator(this, query, size, clazz);
540
- }
541
- async Sequence(options) {
542
- return new FabricContractSequence(options, this);
543
- }
544
- constructor(scope, alias) {
545
- super(scope, FabricFlavour, alias);
546
- this.Context = FabricContractContext;
547
- }
548
- for(config, ...args) {
549
- return super.for(config, ...args);
550
- }
551
- async create(clazz, id, model, ...args) {
552
- const {ctx: ctx, log: log} = this.logCtx(args, this.create);
553
- log.info(`in ADAPTER create with args ${args}`);
554
- const tableName = decoratorValidation.Model.tableName(clazz);
555
- try {
556
- log.info(`adding entry to ${tableName} table with pk ${id}`);
557
- const composedKey = ctx.stub.createCompositeKey(tableName, [ String(id) ]);
558
- model = await this.putState(composedKey, model, ctx);
559
- } catch (e) {
560
- throw this.parseError(e);
561
- }
562
- return model;
563
- }
564
- async read(clazz, id, ...args) {
565
- const {ctx: ctx, log: log} = this.logCtx(args, this.read);
566
- log.info(`in ADAPTER read with args ${args}`);
567
- const tableName = decoratorValidation.Model.tableName(clazz);
568
- let model;
569
- try {
570
- const composedKey = ctx.stub.createCompositeKey(tableName, [ String(id) ]);
571
- model = await this.readState(composedKey, ctx);
572
- } catch (e) {
573
- throw this.parseError(e);
574
- }
575
- return model;
576
- }
577
- async update(clazz, id, model, ...args) {
578
- const {ctx: ctx, log: log} = this.logCtx(args, this.update);
579
- const tableName = decoratorValidation.Model.tableName(clazz);
580
- try {
581
- log.verbose(`updating entry to ${tableName} table with pk ${id}`);
582
- const composedKey = ctx.stub.createCompositeKey(tableName, [ String(id) ]);
583
- model = await this.putState(composedKey, model, ctx);
584
- } catch (e) {
585
- throw this.parseError(e);
586
- }
587
- return model;
588
- }
589
- async delete(clazz, id, ...args) {
590
- const {ctx: ctx, log: log, ctxArgs: ctxArgs} = this.logCtx(args, this.delete);
591
- const tableName = decoratorValidation.Model.tableName(clazz);
592
- let model;
593
- try {
594
- const composedKey = ctx.stub.createCompositeKey(tableName, [ String(id) ]);
595
- model = await this.read(clazz, id, ...ctxArgs);
596
- log.verbose(`deleting entry with pk ${id} from ${tableName} table`);
597
- await this.deleteState(composedKey, ctx);
598
- } catch (e) {
599
- throw this.parseError(e);
600
- }
601
- return model;
602
- }
603
- async deleteState(id, context) {
604
- const {ctx: ctx} = this.logCtx([ context ], this.deleteState);
605
- await ctx.stub.deleteState(id);
606
- }
607
- forPrivate(collection) {
608
- const toOverride = [ this.putState, this.readState, this.deleteState, this.queryResult, this.queryResultPaginated ].map(fn => fn.name);
609
- return new Proxy(this, {
610
- get(target, prop, receiver) {
611
- if (!toOverride.includes(prop)) return Reflect.get(target, prop, receiver);
612
- return new Proxy(target[prop], {
613
- async apply(fn, thisArg, argsList) {
614
- switch (prop) {
615
- case "putState":
616
- {
617
- const [stub, id, model] = argsList;
618
- await stub.putPrivateData(collection, id.toString(), model);
619
- return model;
620
- }
621
-
622
- case "deleteState":
623
- {
624
- const [stub, id] = argsList;
625
- return stub.deletePrivateData(collection, id);
626
- }
627
-
628
- case "readState":
629
- {
630
- const [stub, id] = argsList;
631
- return stub.getPrivateData(collection, id);
632
- }
633
-
634
- case "queryResult":
635
- {
636
- const [stub, rawInput] = argsList;
637
- return stub.getPrivateDataQueryResult(collection, rawInput);
638
- }
639
-
640
- case "queryResultPaginated":
641
- {
642
- const [stub, rawInput, limit, skip] = argsList;
643
- const iterator = await stub.getPrivateDataQueryResult(collection, rawInput);
644
- const results = [];
645
- let count = 0;
646
- let reachedBookmark = skip ? false : true;
647
- let lastKey = null;
648
- while (true) {
649
- const res = await iterator.next();
650
- if (res.value && res.value.value.toString()) {
651
- const recordKey = res.value.key;
652
- const recordValue = res.value.value.toString("utf8");
653
- if (!reachedBookmark) {
654
- if (recordKey === skip?.toString()) {
655
- reachedBookmark = true;
656
- }
657
- continue;
658
- }
659
- results.push({
660
- Key: recordKey,
661
- Record: JSON.parse(recordValue)
662
- });
663
- lastKey = recordKey;
664
- count++;
665
- if (count >= limit) {
666
- await iterator.close();
667
- return {
668
- iterator: results,
669
- metadata: {
670
- fetchedRecordsCount: results.length,
671
- bookmark: lastKey
672
- }
673
- };
674
- }
675
- }
676
- if (res.done) {
677
- await iterator.close();
678
- return {
679
- iterator: results,
680
- metadata: {
681
- fetchedRecordsCount: results.length,
682
- bookmark: ""
683
- }
684
- };
685
- }
686
- }
687
- }
688
-
689
- default:
690
- throw new dbDecorators.InternalError(`Unsupported method override ${String(prop)}`);
691
- }
692
- }
693
- });
694
- }
695
- });
696
- }
697
- async putState(id, model, ctx) {
698
- let data;
699
- const {log: log} = this.logCtx([ ctx ], this.putState);
700
- try {
701
- data = Buffer.from(FabricContractAdapter.serializer.serialize(model, false));
702
- } catch (e) {
703
- throw new dbDecorators.SerializationError(`Failed to serialize record with id ${id}: ${e}`);
704
- }
705
- const collection = ctx.get("segregated");
706
- if (collection) await ctx.stub.putPrivateData(collection, id.toString(), data); else await ctx.stub.putState(id.toString(), data);
707
- log.silly(`state stored${collection ? ` in ${collection} collection` : ""} under id ${id}`);
708
- return model;
709
- }
710
- async readState(id, ctx) {
711
- let result;
712
- const {log: log} = this.logCtx([ ctx ], this.readState);
713
- let res;
714
- const collection = ctx.get("segregated");
715
- if (collection) res = (await ctx.stub.getPrivateData(collection, id.toString())).toString(); else res = (await ctx.stub.getState(id.toString())).toString();
716
- if (!res) throw new dbDecorators.NotFoundError(`Record with id ${id}${collection ? ` in ${collection} collection` : ""} not found`);
717
- log.silly(`state retrieved from${collection ? ` ${collection} collection` : ""} under id ${id}`);
718
- try {
719
- result = FabricContractAdapter.serializer.deserialize(res.toString());
720
- } catch (e) {
721
- throw new dbDecorators.SerializationError(`Failed to parse record: ${e}`);
722
- }
723
- return result;
724
- }
725
- async queryResult(stub, rawInput, ...args) {
726
- const {ctx: ctx} = this.logCtx(args, this.readState);
727
- let res;
728
- const collection = ctx.get("segregated");
729
- if (collection) res = await ctx.stub.getPrivateDataQueryResult(collection, JSON.stringify(rawInput)); else res = await stub.getQueryResult(JSON.stringify(rawInput));
730
- return res;
731
- }
732
- async queryResultPaginated(stub, rawInput, limit = 250, skip, ...args) {
733
- const {ctx: ctx} = this.logCtx(args, this.readState);
734
- let res;
735
- const collection = ctx.get("segregated");
736
- if (collection) {
737
- rawInput.selector = {
738
- ...rawInput.selector,
739
- _id: skip ? {
740
- $gt: skip.toString()
741
- } : {
742
- $gte: ""
743
- }
744
- };
745
- const it = await stub.getPrivateDataQueryResult(collection, JSON.stringify(rawInput));
746
- res = {
747
- iterator: it,
748
- metadata: {
749
- fetchedRecordsCount: limit,
750
- bookmark: ""
751
- }
752
- };
753
- } else res = await stub.getQueryResultWithPagination(JSON.stringify(rawInput), limit, skip?.toString());
754
- return res;
755
- }
756
- mergeModels(results) {
757
- const extract = model => Object.entries(model).reduce((accum, [key, val]) => {
758
- if (typeof val !== "undefined") accum[key] = val;
759
- return accum;
760
- }, {});
761
- let finalModel = results.pop();
762
- for (const res of results) {
763
- finalModel = Object.assign({}, extract(finalModel), extract(res));
764
- }
765
- return finalModel;
766
- }
767
- decode(buffer) {
768
- return FabricContractAdapter.textDecoder.decode(buffer);
769
- }
770
- async flags(operation, model, flags, ctx, ...args) {
771
- const baseFlags = {
772
- stub: ctx.stub,
773
- segregated: false
774
- };
775
- if (ctx instanceof FabricContractContext) {
776
- Object.assign(baseFlags, {
777
- logger: ctx.logger,
778
- identity: ctx.identity,
779
- correlationId: ctx.stub.getTxID()
780
- });
781
- } else {
782
- Object.assign(baseFlags, {
783
- identity: ctx.clientIdentity,
784
- logger: new ContractLogger(this, undefined, ctx),
785
- correlationId: ctx.stub.getTxID()
786
- });
787
- }
788
- flags = await super.flags(operation, model, baseFlags, ...args);
789
- return flags;
790
- }
791
- index(models) {
792
- return Promise.resolve(undefined);
793
- }
794
- async resultIterator(log, iterator, isHistory = false) {
795
- const allResults = [];
796
- let res = await iterator.next();
797
- while (!res.done) {
798
- if (res.value && res.value.value.toString()) {
799
- let jsonRes = {};
800
- log.debug(res.value.value.toString("utf8"));
801
- if (isHistory) {
802
- jsonRes.TxId = res.value.txId;
803
- jsonRes.Timestamp = res.value.timestamp;
804
- try {
805
- jsonRes.Value = JSON.parse(res.value.value.toString("utf8"));
806
- } catch (err) {
807
- log.error(err);
808
- jsonRes.Value = res.value.value.toString("utf8");
809
- }
810
- } else {
811
- try {
812
- jsonRes = JSON.parse(res.value.value.toString("utf8"));
813
- } catch (err) {
814
- log.error(err);
815
- jsonRes = res.value.value.toString("utf8");
816
- }
817
- }
818
- allResults.push(jsonRes);
819
- }
820
- res = await iterator.next();
821
- }
822
- log.debug(`Closing iterator after ${allResults.length} results`);
823
- iterator.close();
824
- return allResults;
825
- }
826
- async raw(rawInput, docsOnly = true, ...args) {
827
- const {log: log, stub: stub, ctx: ctx} = this.logCtx(args, this.raw);
828
- const {skip: skip, limit: limit} = rawInput;
829
- let iterator;
830
- if (limit || skip) {
831
- delete rawInput["limit"];
832
- delete rawInput["skip"];
833
- log.debug(`Retrieving paginated iterator: limit: ${limit}/ skip: ${skip}`);
834
- const response = await this.queryResultPaginated(stub, rawInput, limit || 250, skip?.toString(), ctx);
835
- iterator = response.iterator;
836
- } else {
837
- log.debug("Retrieving iterator");
838
- iterator = await this.queryResult(stub, rawInput, ctx);
839
- }
840
- log.debug("Iterator acquired");
841
- const results = await this.resultIterator(log, iterator);
842
- log.debug(`returning ${Array.isArray(results) ? results.length : 1} results`);
843
- return results;
844
- }
845
- Statement() {
846
- return new FabricStatement(this);
847
- }
848
- async createAll(tableName, id, model, ...args) {
849
- if (id.length !== model.length) throw new dbDecorators.InternalError("Ids and models must have the same length");
850
- const {log: log, ctxArgs: ctxArgs} = this.logCtx(args, this.createAll);
851
- const tableLabel = decoratorValidation.Model.tableName(tableName);
852
- log.debug(`Creating ${id.length} entries ${tableLabel} table`);
853
- return Promise.all(id.map((i, count) => this.create(tableName, i, model[count], ...ctxArgs)));
854
- }
855
- async updateAll(tableName, id, model, ...args) {
856
- if (id.length !== model.length) throw new dbDecorators.InternalError("Ids and models must have the same length");
857
- const {log: log, ctxArgs: ctxArgs} = this.logCtx(args, this.updateAll);
858
- const tableLabel = decoratorValidation.Model.tableName(tableName);
859
- log.debug(`Updating ${id.length} entries ${tableLabel} table`);
860
- return Promise.all(id.map((i, count) => this.update(tableName, i, model[count], ...ctxArgs)));
861
- }
862
- prepare(model, ...args) {
863
- const {log: log} = this.logCtx(args, this.prepare);
864
- const tableName = decoratorValidation.Model.tableName(model.constructor);
865
- const pk = decoratorValidation.Model.pk(model.constructor);
866
- const split = decoratorValidation.Model.segregate(model);
867
- const result = Object.entries(split.model).reduce((accum, [key, val]) => {
868
- if (typeof val === "undefined") return accum;
869
- const mappedProp = decoratorValidation.Model.columnName(model, key);
870
- if (this.isReserved(mappedProp)) throw new dbDecorators.InternalError(`Property name ${mappedProp} is reserved`);
871
- accum[mappedProp] = val;
872
- return accum;
873
- }, {});
874
- log.silly(`Preparing record for ${tableName} table with pk ${model[pk]}`);
875
- return {
876
- record: result,
877
- id: model[pk],
878
- transient: split.transient
879
- };
880
- }
881
- revert(obj, clazz, id, transient, ...args) {
882
- const {log: log} = this.logCtx(args, this.revert);
883
- const ob = {};
884
- const pk = decoratorValidation.Model.pk(clazz);
885
- ob[pk] = id;
886
- const m = typeof clazz === "string" ? decoratorValidation.Model.build(ob, clazz) : new clazz(ob);
887
- log.silly(`Rebuilding model ${m.constructor.name} id ${id}`);
888
- const result = Object.keys(m).reduce((accum, key) => {
889
- accum[key] = obj[decoratorValidation.Model.columnName(accum, key)];
890
- return accum;
891
- }, m);
892
- if (transient) {
893
- log.debug(`re-adding transient properties: ${Object.keys(transient).join(", ")}`);
894
- Object.entries(transient).forEach(([key, val]) => {
895
- if (key in result && result[key] !== undefined) throw new dbDecorators.InternalError(`Transient property ${key} already exists on model ${m.constructor.name}. should be impossible`);
896
- result[key] = val;
897
- });
898
- }
899
- return result;
900
- }
901
- createPrefix(tableName, id, model, ...args) {
902
- const {ctxArgs: ctxArgs} = this.logCtx(args, this.createPrefix);
903
- const record = {};
904
- record[forCouchdb.CouchDBKeys.TABLE] = decoratorValidation.Model.tableName(tableName);
905
- Object.assign(record, model);
906
- return [ tableName, id, record, ...ctxArgs ];
907
- }
908
- updatePrefix(tableName, id, model, ...args) {
909
- const {ctxArgs: ctxArgs} = this.logCtx(args, this.updatePrefix);
910
- const record = {};
911
- record[forCouchdb.CouchDBKeys.TABLE] = decoratorValidation.Model.tableName(tableName);
912
- Object.assign(record, model);
913
- return [ tableName, id, record, ...ctxArgs ];
914
- }
915
- createAllPrefix(tableName, ids, models, ...args) {
916
- if (ids.length !== models.length) throw new dbDecorators.InternalError("Ids and models must have the same length");
917
- const ctx = args.pop();
918
- const records = ids.map((id, count) => {
919
- const record = {};
920
- record[forCouchdb.CouchDBKeys.TABLE] = decoratorValidation.Model.tableName(tableName);
921
- Object.assign(record, models[count]);
922
- return record;
923
- });
924
- return [ tableName, ids, records, ctx ];
925
- }
926
- updateAllPrefix(tableName, ids, models, ...args) {
927
- if (ids.length !== models.length) throw new dbDecorators.InternalError("Ids and models must have the same length");
928
- const ctx = args.pop();
929
- const records = ids.map((id, count) => {
930
- const record = {};
931
- record[forCouchdb.CouchDBKeys.TABLE] = decoratorValidation.Model.tableName(tableName);
932
- Object.assign(record, models[count]);
933
- return record;
934
- });
935
- return [ tableName, ids, records, ctx ];
936
- }
937
- parseError(err, reason) {
938
- return FabricContractAdapter.parseError(reason || err);
939
- }
940
- logCtx(args, method) {
941
- return FabricContractAdapter.logCtx.call(this, args, method);
942
- }
943
- static logCtx(args, method) {
944
- if (args.length < 1) throw new dbDecorators.InternalError("No context provided");
945
- const ctx = args.pop();
946
- if (!(ctx instanceof core.Context)) throw new dbDecorators.InternalError("No context provided");
947
- if (args.filter(a => a instanceof core.Context).length > 1) throw new Error("here");
948
- const log = this ? ctx.logger.for(this).for(method) : ctx.logger.clear().for(this).for(method);
949
- return {
950
- ctx: ctx,
951
- log: method ? log.for(method) : log,
952
- stub: ctx.stub,
953
- identity: ctx.identity,
954
- ctxArgs: [ ...args, ctx ]
955
- };
956
- }
957
- static parseError(err) {
958
- const msg = typeof err === "string" ? err : err.message;
959
- if (msg.includes(dbDecorators.NotFoundError.name)) return new dbDecorators.NotFoundError(err);
960
- if (msg.includes(dbDecorators.ConflictError.name)) return new dbDecorators.ConflictError(err);
961
- if (msg.includes(dbDecorators.BadRequestError.name)) return new dbDecorators.BadRequestError(err);
962
- if (msg.includes(core.QueryError.name)) return new core.QueryError(err);
963
- if (msg.includes(core.PagingError.name)) return new core.PagingError(err);
964
- if (msg.includes(core.UnsupportedError.name)) return new core.UnsupportedError(err);
965
- if (msg.includes(core.MigrationError.name)) return new core.MigrationError(err);
966
- if (msg.includes(core.ObserverError.name)) return new core.ObserverError(err);
967
- if (msg.includes(core.AuthorizationError.name)) return new core.AuthorizationError(err);
968
- if (msg.includes(core.ForbiddenError.name)) return new core.ForbiddenError(err);
969
- if (msg.includes(core.ConnectionError.name)) return new core.ConnectionError(err);
970
- if (msg.includes(dbDecorators.SerializationError.name)) return new dbDecorators.SerializationError(err);
971
- if (msg.includes("no ledger context")) return new MissingContextError(`No context found. this can be caused by debugging: ${msg}`);
972
- return new dbDecorators.InternalError(err);
973
- }
974
- static decoration() {
975
- super.decoration();
976
- decoration.Decoration.flavouredAs(FabricFlavour).for(core.PersistenceKeys.CREATED_BY).define(dbDecorators.onCreate(createdByOnFabricCreateUpdate), decoration.propMetadata(core.PersistenceKeys.CREATED_BY, {})).apply();
977
- decoration.Decoration.flavouredAs(FabricFlavour).for(core.PersistenceKeys.UPDATED_BY).define(dbDecorators.onCreateUpdate(createdByOnFabricCreateUpdate), decoration.propMetadata(core.PersistenceKeys.UPDATED_BY, {})).apply();
978
- decoration.Decoration.flavouredAs(FabricFlavour).for(core.PersistenceKeys.COLUMN).extend(fabricContractApi.Property()).apply();
979
- decoration.Decoration.flavouredAs(FabricFlavour).for(decoratorValidation.ValidationKeys.DATE).extend(function fabricProperty() {
980
- return (target, prop) => {
981
- fabricContractApi.Property(prop, "string:date")(target, prop);
982
- };
983
- });
984
- decoration.Decoration.flavouredAs(FabricFlavour).for(core.PersistenceKeys.TABLE).extend(function table(obj) {
985
- const chain = [];
986
- let current = typeof obj === "function" ? decoration.Metadata.constr(obj) : decoration.Metadata.constr(obj.constructor);
987
- while (current && current !== Object && current.prototype) {
988
- chain.push(current);
989
- current = Object.getPrototypeOf(current);
990
- }
991
- console.log(chain.map(c => c.name || c));
992
- while (chain.length > 0) {
993
- const constructor = chain.pop();
994
- console.log(`Calling on ${constructor.name}`);
995
- fabricContractApi.Object()(constructor);
996
- }
997
- return fabricContractApi.Object()(obj);
998
- }).apply();
999
- }
1000
- }
1001
- FabricContractAdapter.decoration();
1002
- core.Adapter.setCurrent(FabricFlavour);
1003
- class DeterministicSerializer extends decoratorValidation.JSONSerializer {
1004
- constructor() {
1005
- super();
1006
- }
1007
- preSerialize(model) {
1008
- const toSerialize = Object.assign({}, model);
1009
- let metadata;
1010
- try {
1011
- metadata = decoration.Metadata.modelName(model.constructor);
1012
- } catch (error) {
1013
- metadata = undefined;
1014
- }
1015
- toSerialize[decoratorValidation.ModelKeys.ANCHOR] = metadata || model.constructor.name;
1016
- const preSerialize = function preSerialize(obj) {
1017
- const self = this;
1018
- if (typeof obj !== "object") return obj;
1019
- if (Array.isArray(obj)) return obj.map(o => preSerialize.call(self, o));
1020
- return this.preSerialize.call(this, obj);
1021
- }.bind(this);
1022
- decoratorValidation.Model.relations(model).forEach(r => {
1023
- toSerialize[r] = preSerialize(toSerialize[r]);
1024
- });
1025
- return toSerialize;
1026
- }
1027
- deserialize(str) {
1028
- const deserialization = JSON.parse(str);
1029
- const className = deserialization[decoratorValidation.ModelKeys.ANCHOR];
1030
- if (!className) throw new Error("Could not find class reference in serialized model");
1031
- const model = decoratorValidation.Model.build(deserialization, className);
1032
- return model;
1033
- }
1034
- serialize(model) {
1035
- const stringify = require("json-stringify-deterministic");
1036
- const sortKeysRecursive = require("sort-keys-recursive");
1037
- return stringify(sortKeysRecursive(this.preSerialize(model)));
1038
- }
1039
- }
1040
- fabricContractApi.Object()(Date);
1041
- class FabricCrudContract extends fabricContractApi.Contract {
1042
- static {
1043
- this.adapter = new FabricContractAdapter;
1044
- }
1045
- static {
1046
- this.serializer = new DeterministicSerializer;
1047
- }
1048
- constructor(name, clazz) {
1049
- super(name);
1050
- this.clazz = clazz;
1051
- this.initialized = false;
1052
- this.repo = core.Repository.forModel(clazz);
1053
- }
1054
- async listBy(ctx, key, order, ...args) {
1055
- const {ctxArgs: ctxArgs, log: log} = await this.logCtx([ ...args, ctx ], this.listBy);
1056
- log.info(`Running listBy key ${key}, order ${order} and args ${ctxArgs}`);
1057
- return this.repo.listBy(key, order, ...ctxArgs);
1058
- }
1059
- async paginateBy(ctx, key, order, ref = {
1060
- offset: 1,
1061
- limit: 10
1062
- }, ...args) {
1063
- const {ctxArgs: ctxArgs, log: log} = await this.logCtx([ ...args, ctx ], this.paginateBy);
1064
- log.info(`Running paginateBy key ${key}, order ${order} with size ${ref.limit} and args ${ctxArgs}`);
1065
- return this.repo.paginateBy(key, order, ref, ...ctxArgs);
1066
- }
1067
- async findOneBy(ctx, key, value, ...args) {
1068
- const {ctxArgs: ctxArgs, log: log} = await this.logCtx([ ...args, ctx ], this.findOneBy);
1069
- log.info(`Running findOneBy key ${key}, value: ${value} with args ${ctxArgs}`);
1070
- return this.repo.findOneBy(key, value, ...ctxArgs);
1071
- }
1072
- async statement(ctx, method, ...args) {
1073
- const {ctxArgs: ctxArgs, log: log} = await this.logCtx([ ...args, ctx ], this.statement);
1074
- log.info(`Running statement ${method} with args ${ctxArgs}`);
1075
- return this.repo.statement(method, ...ctxArgs);
1076
- }
1077
- async create(ctx, model, ...args) {
1078
- const {log: log, ctxArgs: ctxArgs} = await this.logCtx([ ...args, ctx ], this.create);
1079
- log.info(`CONTRACT CREATE, ${ctxArgs}`);
1080
- if (typeof model === "string") model = this.deserialize(model);
1081
- log.info(`Creating model: ${JSON.stringify(model)}`);
1082
- const transient = this.getTransientData(ctx);
1083
- log.info(`Merging transient data...`);
1084
- model = decoratorValidation.Model.merge(model, transient, this.clazz);
1085
- return this.repo.create(model, ...ctxArgs);
1086
- }
1087
- async read(ctx, key, ...args) {
1088
- const {log: log, ctxArgs: ctxArgs} = await this.logCtx([ ...args, ctx ], this.read);
1089
- log.info(`reading entry with pk ${key} `);
1090
- return this.repo.read(key, ...ctxArgs);
1091
- }
1092
- getTransientData(ctx) {
1093
- const transientMap = ctx.stub.getTransient();
1094
- let transient = {};
1095
- if (transientMap.has(this.repo.tableName)) {
1096
- transient = JSON.parse(transientMap.get(this.repo.tableName)?.toString("utf8"));
1097
- }
1098
- return transient;
1099
- }
1100
- async update(ctx, model, ...args) {
1101
- const {log: log, ctxArgs: ctxArgs} = await this.logCtx([ ...args, ctx ], this.update);
1102
- if (typeof model === "string") model = this.deserialize(model);
1103
- log.info(`Updating model: ${JSON.stringify(model)}`);
1104
- const transient = this.getTransientData(ctx);
1105
- log.info(`Merging transient data...`);
1106
- model = decoratorValidation.Model.merge(model, transient, this.clazz);
1107
- return this.repo.update(model, ...ctxArgs);
1108
- }
1109
- async delete(ctx, key, ...args) {
1110
- const {log: log, ctxArgs: ctxArgs} = await this.logCtx([ ...args, ctx ], this.delete);
1111
- log.info(`deleting entry with pk ${key} `);
1112
- return this.repo.delete(String(key), ...ctxArgs);
1113
- }
1114
- async deleteAll(ctx, keys, ...args) {
1115
- const {ctxArgs: ctxArgs} = await this.logCtx([ ...args, ctx ], this.readAll);
1116
- if (typeof keys === "string") keys = JSON.parse(keys);
1117
- return this.repo.deleteAll(keys, ...ctxArgs);
1118
- }
1119
- async readAll(ctx, keys, ...args) {
1120
- const {ctxArgs: ctxArgs} = await this.logCtx([ ...args, ctx ], this.readAll);
1121
- if (typeof keys === "string") keys = JSON.parse(keys);
1122
- return this.repo.readAll(keys, ...ctxArgs);
1123
- }
1124
- async updateAll(ctx, models, ...args) {
1125
- const {log: log, ctxArgs: ctxArgs} = await this.logCtx([ ...args, ctx ], this.updateAll);
1126
- if (typeof models === "string") models = JSON.parse(models).map(m => this.deserialize(m)).map(m => new this.clazz(m));
1127
- log.info(`updating ${models.length} entries to the table`);
1128
- return this.repo.updateAll(models, ...ctxArgs);
1129
- }
1130
- async query(context, condition, orderBy, order = core.OrderDirection.ASC, limit, skip, ...args) {
1131
- const {ctxArgs: ctxArgs} = await this.logCtx([ ...args, context ], this.query);
1132
- return this.repo.query(condition, orderBy, order, limit, skip, ...ctxArgs);
1133
- }
1134
- async raw(ctx, rawInput, docsOnly, ...args) {
1135
- const {ctxArgs: ctxArgs} = await this.logCtx([ ...args, ctx ], this.raw);
1136
- return FabricCrudContract.adapter.raw(rawInput, docsOnly, ...ctxArgs);
1137
- }
1138
- serialize(model) {
1139
- return FabricCrudContract.serializer.serialize(model);
1140
- }
1141
- deserialize(str) {
1142
- return FabricCrudContract.serializer.deserialize(str);
1143
- }
1144
- async init(ctx) {
1145
- const {log: log} = await this.logCtx([ ctx ], this.init);
1146
- log.info(`Running contract ${this.getName()} initialization...`);
1147
- this.initialized = true;
1148
- log.info(`Contract initialization completed.`);
1149
- }
1150
- async healthcheck(ctx) {
1151
- const {log: log} = await this.logCtx([ ctx ], this.healthcheck);
1152
- log.info(`Running Healthcheck: ${this.initialized}...`);
1153
- return {
1154
- healthcheck: this.initialized
1155
- };
1156
- }
1157
- async createAll(ctx, models, ...args) {
1158
- const {log: log, ctxArgs: ctxArgs} = await this.logCtx([ ...args, ctx ], this.createAll);
1159
- if (typeof models === "string") models = JSON.parse(models).map(m => this.deserialize(m)).map(m => new this.clazz(m));
1160
- log.info(`adding ${models.length} entries to the table`);
1161
- return this.repo.createAll(models, ...ctxArgs);
1162
- }
1163
- async logCtx(args, method) {
1164
- return FabricCrudContract.logCtx.bind(this)(args, method);
1165
- }
1166
- static async logCtx(args, method) {
1167
- if (args.length < 1) throw new dbDecorators.InternalError("No context provided");
1168
- const ctx = args.pop();
1169
- if (ctx instanceof FabricContractContext) return {
1170
- ctx: ctx,
1171
- log: ctx.logger.clear().for(this).for(method),
1172
- ctxArgs: [ ...args, ctx ],
1173
- stub: ctx.stub,
1174
- identity: ctx.identity
1175
- };
1176
- if (!(ctx instanceof fabricContractApi.Context)) throw new dbDecorators.InternalError("No valid context provided");
1177
- function getOp() {
1178
- if (typeof method === "string") return method;
1179
- switch (method.name) {
1180
- case dbDecorators.OperationKeys.CREATE:
1181
- case dbDecorators.OperationKeys.READ:
1182
- case dbDecorators.OperationKeys.UPDATE:
1183
- case dbDecorators.OperationKeys.DELETE:
1184
- case dbDecorators.BulkCrudOperationKeys.CREATE_ALL:
1185
- case dbDecorators.BulkCrudOperationKeys.READ_ALL:
1186
- case dbDecorators.BulkCrudOperationKeys.UPDATE_ALL:
1187
- case dbDecorators.BulkCrudOperationKeys.DELETE_ALL:
1188
- return method.name;
1189
-
1190
- default:
1191
- return method.name;
1192
- }
1193
- }
1194
- const overrides = {
1195
- correlationId: ctx.stub.getTxID()
1196
- };
1197
- const context = await FabricCrudContract.adapter.context(getOp(), overrides, this.clazz, ctx);
1198
- const log = this ? context.logger.for(this).for(method) : context.logger.clear().for(this).for(method);
1199
- return {
1200
- ctx: context,
1201
- log: log,
1202
- stub: context.stub,
1203
- identity: context.identity,
1204
- ctxArgs: [ ...args, context ]
1205
- };
1206
- }
1207
- }
1208
- class SerializedCrudContract extends FabricCrudContract {
1209
- constructor(name, clazz) {
1210
- super(name, clazz);
1211
- }
1212
- async create(context, model) {
1213
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.create);
1214
- log.info(`Creating model: ${model}`);
1215
- const m = this.deserialize(model);
1216
- log.info(`Model deserialized: ${JSON.stringify(m)}`);
1217
- const result = await super.create(ctx, m);
1218
- const serialized = this.serialize(result);
1219
- log.info(`RESULT: ${JSON.stringify(result)}`);
1220
- log.info(`Retuning: ${serialized}`);
1221
- return serialized;
1222
- }
1223
- async read(context, key) {
1224
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.read);
1225
- log.info(`Reading id: ${key}`);
1226
- return this.serialize(await super.read(ctx, key));
1227
- }
1228
- async update(context, model) {
1229
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.update);
1230
- log.info(`Updating model: ${model}`);
1231
- return this.serialize(await super.update(ctx, model));
1232
- }
1233
- async delete(context, key) {
1234
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.delete);
1235
- log.info(`Deleting id: ${key}`);
1236
- return this.serialize(await super.delete(ctx, key));
1237
- }
1238
- async deleteAll(context, keys) {
1239
- const parsedKeys = JSON.parse(keys);
1240
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.deleteAll);
1241
- log.info(`deleting ${parsedKeys.length} entries from the table`);
1242
- return JSON.stringify((await super.deleteAll(ctx, parsedKeys)).map(m => this.serialize(m)));
1243
- }
1244
- async readAll(context, keys) {
1245
- const parsedKeys = JSON.parse(keys);
1246
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.readAll);
1247
- log.info(`reading ${parsedKeys.length} entries from the table`);
1248
- return JSON.stringify((await super.readAll(ctx, parsedKeys)).map(m => this.serialize(m)));
1249
- }
1250
- async updateAll(context, models) {
1251
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.updateAll);
1252
- const list = JSON.parse(models);
1253
- const modelList = list.map(m => this.deserialize(m)).map(m => new this.clazz(m));
1254
- log.info(`Updating ${modelList.length} entries to the table`);
1255
- return JSON.stringify((await super.updateAll(ctx, modelList)).map(m => this.serialize(m)));
1256
- }
1257
- async statement(context, method, args) {
1258
- const {ctx: ctx, log: log} = await this.logCtx([ context ], this.statement);
1259
- try {
1260
- args = JSON.parse(args);
1261
- } catch (e) {
1262
- throw new dbDecorators.SerializationError(`Invalid args: ${e}`);
1263
- }
1264
- if (!Array.isArray(args)) throw new dbDecorators.SerializationError(`Invalid args: ${JSON.stringify(args)}. must be an array`);
1265
- log.info(`calling prepared statement ${method}`);
1266
- log.info(`with args ${args}`);
1267
- return JSON.stringify(await super.statement(ctx, method, ...args));
1268
- }
1269
- async listBy(context, key, order) {
1270
- const {ctx: ctx, log: log} = await this.logCtx([ context ], this.listBy);
1271
- log.info(`Executing listBy with key ${key} and order ${order}`);
1272
- return JSON.stringify(await super.listBy(ctx, key, order));
1273
- }
1274
- async paginateBy(context, key, order, ref, ...args) {
1275
- const {ctx: ctx, log: log} = await this.logCtx([ ...args, context ], this.paginateBy);
1276
- try {
1277
- ref = JSON.parse(ref);
1278
- } catch (e) {
1279
- throw new dbDecorators.SerializationError(`Failed to deserialize paginateBy reference: ${e}`);
1280
- }
1281
- log.info(`Executing paginateBy with key ${key} and order ${order}`);
1282
- return JSON.stringify(await super.paginateBy(ctx, key, order, ref, ...args));
1283
- }
1284
- async findOneBy(context, key, value, ...args) {
1285
- const {ctx: ctx, log: log} = await this.logCtx([ ...args, context ], this.findOneBy);
1286
- log.info(`Executing findOneBy with key ${key} and value ${value}`);
1287
- return JSON.stringify(await super.findOneBy(ctx, key, value, ...args));
1288
- }
1289
- async query(context, condition, orderBy, order, limit, skip) {
1290
- const {ctx: ctx, log: log} = await this.logCtx([ context ], this.query);
1291
- log.info(`Executing query orderedBy ${orderBy} and order ${order}`);
1292
- let cond;
1293
- try {
1294
- cond = core.Condition.from(JSON.parse(condition));
1295
- } catch (e) {
1296
- throw new dbDecorators.SerializationError(`Invalid condition: ${e}`);
1297
- }
1298
- log.info(`Condition: ${JSON.stringify(cond)}`);
1299
- return JSON.stringify(await super.query(ctx, cond, orderBy, order, limit, skip));
1300
- }
1301
- async init(ctx) {
1302
- await super.init(ctx);
1303
- }
1304
- async healthcheck(context) {
1305
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.updateAll);
1306
- log.debug(`Running Healthcheck: ${this.initialized}...`);
1307
- return JSON.stringify(await super.healthcheck(ctx));
1308
- }
1309
- async createAll(context, models) {
1310
- const {log: log} = await this.logCtx([ context ], this.createAll);
1311
- const list = JSON.parse(models);
1312
- const modelList = list.map(m => this.deserialize(m)).map(m => new this.clazz(m));
1313
- log.info(`Adding ${modelList.length} entries to the table`);
1314
- const result = await super.createAll(context, modelList);
1315
- return JSON.stringify(result.map(m => this.serialize(m)));
1316
- }
1317
- }
1318
- tslib.__decorate([ fabricContractApi.Transaction(), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context, String ]), tslib.__metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "create", null);
1319
- tslib.__decorate([ fabricContractApi.Transaction(false), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context, String ]), tslib.__metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "read", null);
1320
- tslib.__decorate([ fabricContractApi.Transaction(), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context, String ]), tslib.__metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "update", null);
1321
- tslib.__decorate([ fabricContractApi.Transaction(), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context, String ]), tslib.__metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "delete", null);
1322
- tslib.__decorate([ fabricContractApi.Transaction(), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context, String ]), tslib.__metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "deleteAll", null);
1323
- tslib.__decorate([ fabricContractApi.Transaction(false), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context, String ]), tslib.__metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "readAll", null);
1324
- tslib.__decorate([ fabricContractApi.Transaction(), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context, String ]), tslib.__metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "updateAll", null);
1325
- tslib.__decorate([ fabricContractApi.Transaction(false), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context, String, String ]), tslib.__metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "statement", null);
1326
- tslib.__decorate([ fabricContractApi.Transaction(false), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context, String, String ]), tslib.__metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "listBy", null);
1327
- tslib.__decorate([ fabricContractApi.Transaction(false), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context, String, String, String, FabricContractContext ]), tslib.__metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "paginateBy", null);
1328
- tslib.__decorate([ fabricContractApi.Transaction(false), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context, String, String, String ]), tslib.__metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "findOneBy", null);
1329
- tslib.__decorate([ fabricContractApi.Transaction(), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context ]), tslib.__metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "init", null);
1330
- tslib.__decorate([ fabricContractApi.Transaction(false), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context ]), tslib.__metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "healthcheck", null);
1331
- tslib.__decorate([ fabricContractApi.Transaction(), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context, String ]), tslib.__metadata("design:returntype", Promise) ], SerializedCrudContract.prototype, "createAll", null);
1332
- function add(a, b) {
1333
- const c = a + b;
1334
- if (a !== c - b || b !== c - a) {
1335
- throw new OverflowError(`Addition overflow: ${a} + ${b}`);
1336
- }
1337
- return c;
1338
- }
1339
- function sub(a, b) {
1340
- const c = a - b;
1341
- if (a !== c + b || b !== a - c) {
1342
- throw new OverflowError(`Subtraction overflow: ${a} - ${b}`);
1343
- }
1344
- return c;
1345
- }
1346
- function safeParseInt(string) {
1347
- const digitRegex = /^\d+$/;
1348
- if (!digitRegex.test(string)) {
1349
- throw new dbDecorators.ValidationError(decoratorValidation.stringFormat("Failed to parse: {0}", "string contains digits"));
1350
- }
1351
- const parsedint = parseInt(string);
1352
- if (isNaN(parsedint)) {
1353
- throw new dbDecorators.ValidationError(decoratorValidation.stringFormat("Failed to parse: {0}", "string is not a parsable integer"));
1354
- }
1355
- return parsedint;
1356
- }
1357
- let ERC20Token = class ERC20Token extends core.BaseModel {
1358
- constructor(m) {
1359
- super(m);
1360
- }
1361
- };
1362
- tslib.__decorate([ core.pk({
1363
- type: "String"
1364
- }), tslib.__metadata("design:type", String) ], ERC20Token.prototype, "name", void 0);
1365
- tslib.__decorate([ core.column(), decoratorValidation.required(), tslib.__metadata("design:type", String) ], ERC20Token.prototype, "owner", void 0);
1366
- tslib.__decorate([ core.column(), decoratorValidation.required(), tslib.__metadata("design:type", String) ], ERC20Token.prototype, "symbol", void 0);
1367
- tslib.__decorate([ core.column(), decoratorValidation.required(), tslib.__metadata("design:type", Number) ], ERC20Token.prototype, "decimals", void 0);
1368
- ERC20Token = tslib.__decorate([ core.table("erc20_tokens"), decoratorValidation.model(), tslib.__metadata("design:paramtypes", [ Object ]) ], ERC20Token);
1369
- let ERC20Wallet = class ERC20Wallet extends core.BaseModel {
1370
- constructor(m) {
1371
- super(m);
1372
- }
1373
- };
1374
- tslib.__decorate([ core.pk({
1375
- type: "String"
1376
- }), tslib.__metadata("design:type", String) ], ERC20Wallet.prototype, "id", void 0);
1377
- tslib.__decorate([ core.column(), decoratorValidation.required(), tslib.__metadata("design:type", String) ], ERC20Wallet.prototype, "token", void 0);
1378
- tslib.__decorate([ core.column(), decoratorValidation.required(), tslib.__metadata("design:type", Number) ], ERC20Wallet.prototype, "balance", void 0);
1379
- tslib.__decorate([ core.column(), tslib.__metadata("design:type", String) ], ERC20Wallet.prototype, "captive", void 0);
1380
- ERC20Wallet = tslib.__decorate([ core.table("erc20_wallets"), decoratorValidation.model(), tslib.__metadata("design:paramtypes", [ Object ]) ], ERC20Wallet);
1381
- let Allowance = class Allowance extends core.BaseModel {
1382
- constructor(m) {
1383
- super(m);
1384
- }
1385
- };
1386
- tslib.__decorate([ core.pk({
1387
- type: "String"
1388
- }), core.column(), decoratorValidation.required(), tslib.__metadata("design:type", String) ], Allowance.prototype, "owner", void 0);
1389
- tslib.__decorate([ core.column(), decoratorValidation.required(), tslib.__metadata("design:type", String) ], Allowance.prototype, "spender", void 0);
1390
- tslib.__decorate([ core.column(), decoratorValidation.required(), tslib.__metadata("design:type", Number) ], Allowance.prototype, "value", void 0);
1391
- Allowance = tslib.__decorate([ core.table("erc20_allowances"), decoratorValidation.model(), tslib.__metadata("design:paramtypes", [ Object ]) ], Allowance);
1392
- function Owner() {
1393
- return function(target, propertyKey, descriptor) {
1394
- const originalMethod = descriptor.value;
1395
- descriptor.value = async function(...args) {
1396
- const ctx = args[0];
1397
- const acountId = ctx.clientIdentity.getID();
1398
- const select = await this["tokenRepository"].select();
1399
- const tokens = await select.execute(ctx);
1400
- if (tokens.length == 0) {
1401
- throw new dbDecorators.NotFoundError("No tokens avaialble");
1402
- }
1403
- if (tokens.length > 1) {
1404
- throw new dbDecorators.NotFoundError(`To many token available : ${tokens.length}`);
1405
- }
1406
- if (tokens[0].owner != acountId) {
1407
- throw new core.AuthorizationError(`User not authorized to run ${propertyKey} on the token`);
1408
- }
1409
- return await originalMethod.apply(this, args);
1410
- };
1411
- return descriptor;
1412
- };
1413
- }
1414
- async function ownedByOnCreate(context, data, key, model) {
1415
- const {stub: stub} = context;
1416
- const creator = await stub.getCreator();
1417
- const owner = creator.mspid;
1418
- const setOwnedByKeyValue = function(target, propertyKey, value) {
1419
- Object.defineProperty(target, propertyKey, {
1420
- enumerable: true,
1421
- writable: false,
1422
- configurable: true,
1423
- value: value
1424
- });
1425
- };
1426
- setOwnedByKeyValue(model, key, owner);
1427
- }
1428
- function ownedBy() {
1429
- const key = getFabricModelKey(FabricModelKeys.OWNEDBY);
1430
- function ownedBy() {
1431
- return function(obj, attribute) {
1432
- return decoration.apply(decoratorValidation.required(), dbDecorators.readonly(), dbDecorators.onCreate(ownedByOnCreate), decoration.propMetadata(getFabricModelKey(FabricModelKeys.OWNEDBY), attribute))(obj, attribute);
1433
- };
1434
- }
1435
- return decoration.Decoration.for(key).define({
1436
- decorator: ownedBy,
1437
- args: []
1438
- }).apply();
1439
- }
1440
- async function transactionIdOnCreate(context, data, key, model) {
1441
- const {stub: stub} = context;
1442
- model[key] = stub.getTxID();
1443
- }
1444
- function transactionId() {
1445
- function transactionId() {
1446
- return function(obj, attribute) {
1447
- return decoration.apply(decoratorValidation.required(), dbDecorators.readonly(), dbDecorators.onCreate(transactionIdOnCreate), dbDecorators.onUpdate(transactionIdOnCreate), decoration.propMetadata(decoration.Metadata.key(FabricModelKeys.FABRIC, attribute, FabricModelKeys.TRANSACTION_ID), attribute))(obj, attribute);
1448
- };
1449
- }
1450
- return decoration.Decoration.for(FabricModelKeys.TRANSACTION_ID).define({
1451
- decorator: transactionId,
1452
- args: []
1453
- }).apply();
1454
- }
1455
- function getFabricModelKey(key) {
1456
- return decoration.Metadata.key(FabricModelKeys.FABRIC + key);
1457
- }
1458
- const ImplicitPrivateCollection = model => `__${model.constructor.name}PrivateCollection`;
1459
- async function segregatedDataOnCreate(context, data, keys, model) {
1460
- if (keys.length !== data.length) throw new dbDecorators.InternalError(`Segregated data keys and metadata length mismatch`);
1461
- const collectionResolver = data[0].collections;
1462
- const collection = typeof collectionResolver === "string" ? collectionResolver : collectionResolver(model);
1463
- const rebuilt = keys.reduce((acc, k, i) => {
1464
- const c = typeof data[i].collections === "string" ? data[i].collections : data[i].collections(model);
1465
- if (c !== collection) throw new core.UnsupportedError(`Segregated data collection mismatch: ${c} vs ${collection}`);
1466
- acc[k] = model[k];
1467
- return acc;
1468
- }, {});
1469
- const toCreate = new this.class(rebuilt);
1470
- const created = await this.override({
1471
- segregated: collection
1472
- }).create(toCreate, context);
1473
- Object.assign(model, created);
1474
- }
1475
- async function segregatedDataOnRead(context, data, keys, model) {
1476
- if (keys.length !== data.length) throw new dbDecorators.InternalError(`Segregated data keys and metadata length mismatch`);
1477
- const collectionResolver = data[0].collections;
1478
- const collection = typeof collectionResolver === "string" ? collectionResolver : collectionResolver(model);
1479
- const rebuilt = keys.reduce((acc, k, i) => {
1480
- const c = typeof data[i].collections === "string" ? data[i].collections : data[i].collections(model);
1481
- if (c !== collection) throw new core.UnsupportedError(`Segregated data collection mismatch: ${c} vs ${collection}`);
1482
- acc[k] = model[k];
1483
- return acc;
1484
- }, {});
1485
- const toCreate = new this.class(rebuilt);
1486
- const created = await this.override({
1487
- segregated: collection
1488
- }).create(toCreate, context);
1489
- Object.assign(model, created);
1490
- }
1491
- async function segregatedDataOnUpdate(context, data, key, model, oldModel) {}
1492
- async function segregatedDataOnDelete(context, data, key, model) {}
1493
- function segregated(collection, type) {
1494
- return function innerSegregated(target, propertyKey) {
1495
- function segregatedDec(target, propertyKey) {
1496
- if (!propertyKey) {
1497
- const props = decoration.Metadata.properties(target) || [];
1498
- for (const prop of props) segregated(collection, type)(target, prop);
1499
- return target;
1500
- }
1501
- const key = decoration.Metadata.key(type, propertyKey);
1502
- const constr = target.constructor;
1503
- const meta = decoration.Metadata.get(constr, key) || {};
1504
- const collections = new Set(meta.collections || []);
1505
- collections.add(collection);
1506
- meta.collections = [ ...collections ];
1507
- decoration.Metadata.set(constr, key, meta);
1508
- }
1509
- const decs = [];
1510
- if (!propertyKey) {
1511
- decoration.Metadata.properties(target)?.forEach(p => segregated(collection, type)(target, p));
1512
- return decoration.metadata(type, true)(target);
1513
- } else {
1514
- decs.push(dbDecorators.transient(), segregatedDec, dbDecorators.onCreate(segregatedDataOnCreate, {
1515
- collections: collection
1516
- }, {
1517
- priority: 95,
1518
- group: typeof collection === "string" ? collection : collection.toString()
1519
- }), dbDecorators.onRead(segregatedDataOnRead, {
1520
- collections: collection
1521
- }, {
1522
- priority: 95,
1523
- group: typeof collection === "string" ? collection : collection.toString()
1524
- }), dbDecorators.onUpdate(segregatedDataOnUpdate, {
1525
- collections: collection
1526
- }, {
1527
- priority: 95,
1528
- group: typeof collection === "string" ? collection : collection.toString()
1529
- }), dbDecorators.onDelete(segregatedDataOnDelete, {
1530
- collections: collection
1531
- }, {
1532
- priority: 95,
1533
- group: typeof collection === "string" ? collection : collection.toString()
1534
- }));
1535
- }
1536
- return decoration.apply(...decs)(target, propertyKey);
1537
- };
1538
- }
1539
- function privateData(collection = ImplicitPrivateCollection) {
1540
- function privateData(collection) {
1541
- return segregated(collection, FabricModelKeys.PRIVATE);
1542
- }
1543
- return decoration.Decoration.for(FabricModelKeys.PRIVATE).define({
1544
- decorator: privateData,
1545
- args: [ collection ]
1546
- }).apply();
1547
- }
1548
- function sharedData(collection) {
1549
- function sharedData(collection) {
1550
- return segregated(collection, FabricModelKeys.SHARED);
1551
- }
1552
- return decoration.Decoration.for(FabricModelKeys.SHARED).define({
1553
- decorator: sharedData,
1554
- args: [ collection ]
1555
- }).apply();
1556
- }
1557
- var ERC20Events;
1558
- (function(ERC20Events) {
1559
- ERC20Events["TRANSFER"] = "Transfer";
1560
- ERC20Events["APPROVAL"] = "Approval";
1561
- })(ERC20Events || (ERC20Events = {}));
1562
- class FabricERC20Contract extends FabricCrudContract {
1563
- constructor(name) {
1564
- super(name, ERC20Wallet);
1565
- FabricERC20Contract.adapter = FabricERC20Contract.adapter || new FabricContractAdapter;
1566
- this.walletRepository = FabricContractRepository.forModel(ERC20Wallet, FabricERC20Contract.adapter.alias);
1567
- this.tokenRepository = FabricContractRepository.forModel(ERC20Token, FabricERC20Contract.adapter.alias);
1568
- this.allowanceRepository = FabricContractRepository.forModel(Allowance, FabricERC20Contract.adapter.alias);
1569
- }
1570
- async TokenName(context) {
1571
- const {ctx: ctx} = await this.logCtx([ context ], this.TokenName);
1572
- await this.CheckInitialized(ctx);
1573
- const select = this.tokenRepository.select();
1574
- const token = (await select.execute(ctx))[0];
1575
- return token.name;
1576
- }
1577
- async Symbol(context) {
1578
- const {ctx: ctx} = await this.logCtx([ context ], this.TokenName);
1579
- await this.CheckInitialized(ctx);
1580
- const select = this.tokenRepository.select();
1581
- const token = (await select.execute(ctx))[0];
1582
- return token.symbol;
1583
- }
1584
- async Decimals(context) {
1585
- const {ctx: ctx} = await this.logCtx([ context ], this.TokenName);
1586
- await this.CheckInitialized(ctx);
1587
- const select = this.tokenRepository.select();
1588
- const token = (await select.execute(ctx))[0];
1589
- return token.decimals;
1590
- }
1591
- async TotalSupply(context) {
1592
- const {ctx: ctx} = await this.logCtx([ context ], this.TokenName);
1593
- await this.CheckInitialized(ctx);
1594
- const select = this.walletRepository.select();
1595
- const wallets = await select.execute(ctx);
1596
- if (wallets.length == 0) {
1597
- throw new dbDecorators.NotFoundError(`The token ${this.getName()} does not exist`);
1598
- }
1599
- let total = 0;
1600
- wallets.forEach(wallet => {
1601
- total += wallet.balance;
1602
- });
1603
- return total;
1604
- }
1605
- async BalanceOf(context, owner) {
1606
- const {ctx: ctx} = await this.logCtx([ context ], this.TokenName);
1607
- await this.CheckInitialized(ctx);
1608
- const wallet = await this.walletRepository.read(owner, ctx);
1609
- return wallet.balance;
1610
- }
1611
- async Transfer(context, to, value) {
1612
- const {ctx: ctx} = await this.logCtx([ context ], this.Transfer);
1613
- await this.CheckInitialized(ctx);
1614
- const from = ctx.identity.getID();
1615
- const transferResp = await this._transfer(from, to, value, ctx);
1616
- if (!transferResp) {
1617
- throw new dbDecorators.InternalError("Failed to transfer");
1618
- }
1619
- return true;
1620
- }
1621
- async TransferFrom(context, from, to, value) {
1622
- const {ctx: ctx} = await this.logCtx([ context ], this.BurnFrom);
1623
- await this.CheckInitialized(ctx);
1624
- const spender = ctx.identity.getID();
1625
- const allowance = await this._getAllowance(from, spender, ctx);
1626
- if (!allowance || allowance.value < 0) {
1627
- throw new AllowanceError(`spender ${spender} has no allowance from ${from}`);
1628
- }
1629
- const currentAllowance = allowance.value;
1630
- if (currentAllowance < value) {
1631
- throw new BalanceError("The spender does not have enough allowance to spend.");
1632
- }
1633
- const updatedAllowance = sub(currentAllowance, value);
1634
- const newAllowance = Object.assign({}, allowance, {
1635
- value: updatedAllowance
1636
- });
1637
- await this.allowanceRepository.update(newAllowance, ctx);
1638
- const transferResp = await this._transfer(from, to, value, ctx);
1639
- if (!transferResp) {
1640
- throw new dbDecorators.InternalError("Failed to transfer");
1641
- }
1642
- return true;
1643
- }
1644
- async _transfer(from, to, value, ctx) {
1645
- const log = ctx.logger;
1646
- if (from === to) {
1647
- throw new core.AuthorizationError("cannot transfer to and from same client account");
1648
- }
1649
- if (value < 0) {
1650
- throw new BalanceError("transfer amount cannot be negative");
1651
- }
1652
- const fromWallet = await this.walletRepository.read(from, ctx);
1653
- const fromBalance = fromWallet.balance;
1654
- if (fromBalance < value) {
1655
- throw new BalanceError(`client account ${from} has insufficient funds.`);
1656
- }
1657
- let toWallet;
1658
- let newToWallet = false;
1659
- try {
1660
- toWallet = await this.walletRepository.read(to, ctx);
1661
- } catch (e) {
1662
- if (e instanceof dbDecorators.BaseError) {
1663
- if (e.code === 404) {
1664
- toWallet = new ERC20Wallet({
1665
- id: to,
1666
- balance: 0,
1667
- token: await this.TokenName(ctx)
1668
- });
1669
- newToWallet = true;
1670
- } else {
1671
- throw new dbDecorators.InternalError(e.message);
1672
- }
1673
- } else {
1674
- throw new dbDecorators.InternalError(e);
1675
- }
1676
- }
1677
- const toBalance = toWallet.balance;
1678
- const fromUpdatedBalance = sub(fromBalance, value);
1679
- const toUpdatedBalance = add(toBalance, value);
1680
- const updatedFromWallet = Object.assign({}, fromWallet, {
1681
- balance: fromUpdatedBalance
1682
- });
1683
- await this.walletRepository.update(updatedFromWallet, ctx);
1684
- const updatedToWallet = Object.assign({}, toWallet, {
1685
- balance: toUpdatedBalance
1686
- });
1687
- if (newToWallet) {
1688
- await this.walletRepository.create(updatedToWallet, ctx);
1689
- } else {
1690
- await this.walletRepository.update(updatedToWallet, ctx);
1691
- }
1692
- const transferEvent = {
1693
- from: from,
1694
- to: to,
1695
- value: value
1696
- };
1697
- this.repo.refresh(ERC20Token, ERC20Events.TRANSFER, "", transferEvent, ctx).catch(e => log.error(`Failed to notify transfer: ${e}`));
1698
- return true;
1699
- }
1700
- async Approve(context, spender, value) {
1701
- const {ctx: ctx, ctxArgs: ctxArgs} = await this.logCtx([ context ], this.Approve);
1702
- await this.CheckInitialized(ctx);
1703
- const owner = ctx.identity.getID();
1704
- let allowance = await this._getAllowance(owner, spender, ctx);
1705
- const ownerWallet = await this.walletRepository.read(owner, ...ctxArgs);
1706
- if (ownerWallet.balance < value) {
1707
- throw new BalanceError(`client account ${owner} has insufficient funds.`);
1708
- }
1709
- if (allowance) {
1710
- allowance.value = value;
1711
- await this.allowanceRepository.update(allowance, ...ctxArgs);
1712
- } else {
1713
- allowance = new Allowance({
1714
- owner: owner,
1715
- spender: spender,
1716
- value: value
1717
- });
1718
- await this.allowanceRepository.create(allowance, ...ctxArgs);
1719
- }
1720
- const approvalEvent = {
1721
- owner: owner,
1722
- spender: spender,
1723
- value: value
1724
- };
1725
- this.repo.refresh(ERC20Token, ERC20Events.APPROVAL, "", approvalEvent, ctx);
1726
- return true;
1727
- }
1728
- async Allowance(context, owner, spender) {
1729
- const {ctx: ctx} = await this.logCtx([ context ], this.Allowance);
1730
- await this.CheckInitialized(ctx);
1731
- const allowance = await this._getAllowance(owner, spender, ctx);
1732
- if (!allowance) {
1733
- throw new AllowanceError(`spender ${spender} has no allowance from ${owner}`);
1734
- }
1735
- return allowance.value;
1736
- }
1737
- async _getAllowance(owner, spender, ctx) {
1738
- const allowanceCondition = core.Condition.and(core.Condition.attribute("owner").eq(owner), core.Condition.attribute("spender").eq(spender));
1739
- const allowance = await this.allowanceRepository.select().where(allowanceCondition).execute(ctx);
1740
- return allowance?.[0];
1741
- }
1742
- async Initialize(context, token) {
1743
- const {ctx: ctx} = await this.logCtx([ context ], this.Initialize);
1744
- const tokens = await this.tokenRepository.select().execute(ctx);
1745
- if (tokens.length > 0) {
1746
- throw new core.AuthorizationError("contract options are already set, client is not authorized to change them");
1747
- }
1748
- token.owner = ctx.identity.getID();
1749
- await this.tokenRepository.create(token, ctx);
1750
- return true;
1751
- }
1752
- async CheckInitialized(context) {
1753
- const {ctx: ctx} = await this.logCtx([ context ], this.CheckInitialized);
1754
- const tokens = await this.tokenRepository.select().execute(ctx);
1755
- if (tokens.length == 0) {
1756
- throw new NotInitializedError("contract options need to be set before calling any function, call Initialize() to initialize contract");
1757
- }
1758
- }
1759
- async Mint(context, amount) {
1760
- const {ctx: ctx} = await this.logCtx([ context ], this.Mint);
1761
- await this.CheckInitialized(ctx);
1762
- const minter = ctx.identity.getID();
1763
- if (amount <= 0) {
1764
- throw new dbDecorators.ValidationError("mint amount must be a positive integer");
1765
- }
1766
- let minterWallet;
1767
- try {
1768
- minterWallet = await this.walletRepository.read(minter, ctx);
1769
- const currentBalance = minterWallet.balance;
1770
- const updatedBalance = add(currentBalance, amount);
1771
- const updatedminter = Object.assign({}, minterWallet, {
1772
- balance: updatedBalance
1773
- });
1774
- await this.walletRepository.update(updatedminter, ctx);
1775
- } catch (e) {
1776
- if (e instanceof dbDecorators.BaseError) {
1777
- if (e.code === 404) {
1778
- const newWallet = new ERC20Wallet({
1779
- id: minter,
1780
- balance: amount,
1781
- token: await this.TokenName(context)
1782
- });
1783
- await this.walletRepository.create(newWallet, ctx);
1784
- } else {
1785
- throw new dbDecorators.InternalError(e.message);
1786
- }
1787
- } else {
1788
- throw new dbDecorators.InternalError(e);
1789
- }
1790
- }
1791
- const transferEvent = {
1792
- from: "0x0",
1793
- to: minter,
1794
- value: amount
1795
- };
1796
- const eventHandler = this.repo.ObserverHandler();
1797
- eventHandler.updateObservers(ERC20Token, ERC20Events.TRANSFER, "", transferEvent, ctx);
1798
- }
1799
- async Burn(context, amount) {
1800
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.Burn);
1801
- await this.CheckInitialized(ctx);
1802
- const minter = ctx.identity.getID();
1803
- const minterWallet = await this.walletRepository.read(minter, ctx);
1804
- const currentBalance = minterWallet.balance;
1805
- if (currentBalance < amount) {
1806
- throw new BalanceError(`Minter has insufficient funds.`);
1807
- }
1808
- const updatedBalance = sub(currentBalance, amount);
1809
- const updatedminter = Object.assign({}, minterWallet, {
1810
- balance: updatedBalance
1811
- });
1812
- await this.walletRepository.update(updatedminter, ctx);
1813
- log.info(`${amount} tokens were burned`);
1814
- const transferEvent = {
1815
- from: minter,
1816
- to: "0x0",
1817
- value: amount
1818
- };
1819
- const eventHandler = this.repo.ObserverHandler();
1820
- eventHandler.updateObservers(ERC20Token, ERC20Events.TRANSFER, "", transferEvent, ctx);
1821
- }
1822
- async BurnFrom(context, account, amount) {
1823
- const {log: log, ctx: ctx} = await this.logCtx([ context ], this.BurnFrom);
1824
- await this.CheckInitialized(ctx);
1825
- const accountWallet = await this.walletRepository.read(account, ctx);
1826
- const currentBalance = accountWallet.balance;
1827
- if (currentBalance < amount) {
1828
- throw new BalanceError(`${account} has insufficient funds.`);
1829
- }
1830
- const updatedBalance = sub(currentBalance, amount);
1831
- const updatedaccount = Object.assign({}, accountWallet, {
1832
- balance: updatedBalance
1833
- });
1834
- await this.walletRepository.update(updatedaccount, ctx);
1835
- log.info(`${amount} tokens were burned from ${account}`);
1836
- const transferEvent = {
1837
- from: account,
1838
- to: "0x0",
1839
- value: amount
1840
- };
1841
- const eventHandler = this.repo.ObserverHandler();
1842
- eventHandler.updateObservers(ERC20Token, ERC20Events.TRANSFER, "", transferEvent, ctx);
1843
- }
1844
- async ClientAccountBalance(context) {
1845
- const {ctx: ctx} = await this.logCtx([ context ], this.TokenName);
1846
- await this.CheckInitialized(ctx);
1847
- const clientAccountID = ctx.identity.getID();
1848
- const clientWallet = await this.walletRepository.read(clientAccountID, ctx);
1849
- if (!clientWallet) {
1850
- throw new BalanceError(`The account ${clientAccountID} does not exist`);
1851
- }
1852
- return clientWallet.balance;
1853
- }
1854
- async ClientAccountID(context) {
1855
- const {ctx: ctx} = await this.logCtx([ context ], this.ClientAccountID);
1856
- await this.CheckInitialized(ctx);
1857
- const clientAccountID = ctx.identity.getID();
1858
- return clientAccountID;
1859
- }
1860
- }
1861
- tslib.__decorate([ fabricContractApi.Transaction(false), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context ]), tslib.__metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "TokenName", null);
1862
- tslib.__decorate([ fabricContractApi.Transaction(false), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context ]), tslib.__metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Symbol", null);
1863
- tslib.__decorate([ fabricContractApi.Transaction(false), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context ]), tslib.__metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Decimals", null);
1864
- tslib.__decorate([ fabricContractApi.Transaction(false), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context ]), tslib.__metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "TotalSupply", null);
1865
- tslib.__decorate([ fabricContractApi.Transaction(false), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context, String ]), tslib.__metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "BalanceOf", null);
1866
- tslib.__decorate([ fabricContractApi.Transaction(), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context, String, Number ]), tslib.__metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Transfer", null);
1867
- tslib.__decorate([ fabricContractApi.Transaction(), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context, String, String, Number ]), tslib.__metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "TransferFrom", null);
1868
- tslib.__decorate([ fabricContractApi.Transaction(), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context, String, Number ]), tslib.__metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Approve", null);
1869
- tslib.__decorate([ fabricContractApi.Transaction(false), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context, String, String ]), tslib.__metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Allowance", null);
1870
- tslib.__decorate([ fabricContractApi.Transaction(), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context, ERC20Token ]), tslib.__metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Initialize", null);
1871
- tslib.__decorate([ fabricContractApi.Transaction(false), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context ]), tslib.__metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "CheckInitialized", null);
1872
- tslib.__decorate([ Owner(), fabricContractApi.Transaction(), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context, Number ]), tslib.__metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Mint", null);
1873
- tslib.__decorate([ Owner(), fabricContractApi.Transaction(), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context, Number ]), tslib.__metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "Burn", null);
1874
- tslib.__decorate([ Owner(), fabricContractApi.Transaction(), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context, String, Number ]), tslib.__metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "BurnFrom", null);
1875
- tslib.__decorate([ fabricContractApi.Transaction(false), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context ]), tslib.__metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "ClientAccountBalance", null);
1876
- tslib.__decorate([ fabricContractApi.Transaction(false), tslib.__metadata("design:type", Function), tslib.__metadata("design:paramtypes", [ fabricContractApi.Context ]), tslib.__metadata("design:returntype", Promise) ], FabricERC20Contract.prototype, "ClientAccountID", null);
1877
- const contracts = [ FabricERC20Contract ];
1878
- const VERSION = "0.1.48";
1879
- const PACKAGE_NAME = "@decaf-ts/for-fabric";
1880
- decoration.Metadata.registerLibrary(PACKAGE_NAME, VERSION);
1881
- exports.ContractLogger = ContractLogger;
1882
- exports.FabricContractAdapter = FabricContractAdapter;
1883
- exports.FabricContractContext = FabricContractContext;
1884
- exports.FabricContractPaginator = FabricContractPaginator;
1885
- exports.FabricContractRepository = FabricContractRepository;
1886
- exports.FabricContractRepositoryObservableHandler = FabricContractRepositoryObservableHandler;
1887
- exports.FabricCrudContract = FabricCrudContract;
1888
- exports.FabricStatement = FabricStatement;
1889
- exports.PACKAGE_NAME = PACKAGE_NAME;
1890
- exports.SerializedCrudContract = SerializedCrudContract;
1891
- exports.VERSION = VERSION;
1892
- exports.contracts = contracts;
1893
- exports.createdByOnFabricCreateUpdate = createdByOnFabricCreateUpdate;
1894
- exports.pkFabricOnCreate = pkFabricOnCreate;
1895
- });
1896
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yLWZhYnJpYy5janMiLCJzb3VyY2VzIjpbIi4uL3NyYy9jb250cmFjdHMvQ29udHJhY3RDb250ZXh0LnRzIiwiLi4vc3JjL3NoYXJlZC9ldmVudHMudHMiLCIuLi9zcmMvY29udHJhY3RzL0ZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeU9ic2VydmFibGVIYW5kbGVyLnRzIiwiLi4vc3JjL2NvbnRyYWN0cy9GYWJyaWNDb250cmFjdFJlcG9zaXRvcnkudHMiLCIuLi9zcmMvY29udHJhY3RzL0ZhYnJpY0NvbnRyYWN0U3RhdGVtZW50LnRzIiwiLi4vc3JjL2NvbnRyYWN0cy9GYWJyaWNDb250cmFjdFNlcXVlbmNlLnRzIiwiLi4vc3JjL3NoYXJlZC9jb25zdGFudHMudHMiLCIuLi9zcmMvc2hhcmVkL1NpbXBsZURldGVybWluaXN0aWNTZXJpYWxpemVyLnRzIiwiLi4vc3JjL2NvbnRyYWN0cy9sb2dnaW5nLnRzIiwiLi4vc3JjL2NvbnRyYWN0cy9GYWJyaWNDb250cmFjdFBhZ2luYXRvci50cyIsIi4uL3NyYy9zaGFyZWQvZXJyb3JzLnRzIiwiLi4vc3JjL2NvbnRyYWN0cy9Db250cmFjdEFkYXB0ZXIudHMiLCIuLi9zcmMvc2hhcmVkL0RldGVybWluaXN0aWNTZXJpYWxpemVyLnRzIiwiLi4vc3JjL2NvbnRyYWN0cy9jcnVkL2NydWQtY29udHJhY3QudHMiLCIuLi9zcmMvY29udHJhY3RzL2NydWQvc2VyaWFsaXplZC1jcnVkLWNvbnRyYWN0LnRzIiwiLi4vc3JjL3NoYXJlZC9tYXRoLnRzIiwiLi4vc3JjL2NvbnRyYWN0cy9lcmMyMC9tb2RlbHMudHMiLCIuLi9zcmMvc2hhcmVkL2RlY29yYXRvcnMudHMiLCIuLi9zcmMvc2hhcmVkL2VyYzIwL2VyYzIwLWNvbnN0YW50cy50cyIsIi4uL3NyYy9jb250cmFjdHMvZXJjMjAvZXJjMjBjb250cmFjdC50cyIsIi4uL3NyYy9jb250cmFjdHMvZXJjMjAvaW5kZXgudHMiLCIuLi9zcmMvdmVyc2lvbi50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb250ZXh0IH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdEZsYWdzIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IENoYWluY29kZVN0dWIsIENsaWVudElkZW50aXR5IH0gZnJvbSBcImZhYnJpYy1zaGltLWFwaVwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDb250ZXh0IGNsYXNzIGZvciBGYWJyaWMgY2hhaW5jb2RlIG9wZXJhdGlvbnNcbiAqIEBzdW1tYXJ5IFByb3ZpZGVzIGFjY2VzcyB0byBGYWJyaWMtc3BlY2lmaWMgY29udGV4dCBlbGVtZW50cyBsaWtlIHN0dWIsIGlkZW50aXR5LCBhbmQgbG9nZ2VyIHRvIGJlIHVzZWQgYnkgcmVwb3NpdG9yaWVzIGFuZCBhZGFwdGVycyBkdXJpbmcgY29udHJhY3QgZXhlY3V0aW9uLlxuICogQHRlbXBsYXRlIEYgLSBGbGFncyBzcGVjaWZpYyB0byBGYWJyaWMgY29udHJhY3Qgb3BlcmF0aW9uc1xuICogQHBhcmFtIHtvYmplY3R9IFthcmdzXSAtIE9wdGlvbmFsIGluaXRpYWxpemF0aW9uIGFyZ3VtZW50cyBwYXNzZWQgdG8gdGhlIGJhc2UgQ29udGV4dFxuICogQHJldHVybiB7dm9pZH1cbiAqIEBjbGFzcyBGYWJyaWNDb250cmFjdENvbnRleHRcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBJbiBhIEZhYnJpYyBjaGFpbmNvZGUgY29udHJhY3QgbWV0aG9kXG4gKiBjb25zdCBjb250ZXh0ID0gbmV3IEZhYnJpY0NvbnRyYWN0Q29udGV4dCgpO1xuICogLy8gT3B0aW9uYWxseSBzZXQgdmFsdWVzIHZpYSB0aGUgYmFzZSBDb250ZXh0IEFQSVxuICogY29udGV4dC5zZXQoJ3N0dWInLCBjdHguc3R1Yik7XG4gKiBjb250ZXh0LnNldCgnY2xpZW50SWRlbnRpdHknLCBjdHguY2xpZW50SWRlbnRpdHkpO1xuICogY29udGV4dC5zZXQoJ2xvZ2dlcicsIGNvbnRyYWN0TG9nZ2VyKTtcbiAqXG4gKiAvLyBBY2Nlc3MgY29udGV4dCBwcm9wZXJ0aWVzXG4gKiBjb25zdCB0aW1lc3RhbXAgPSBjb250ZXh0LnRpbWVzdGFtcDtcbiAqIGNvbnN0IGNyZWF0b3IgPSBjb250ZXh0LmlkZW50aXR5LmdldElEKCk7XG4gKiBgYGBcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ29udHJhY3RcbiAqICAgcGFydGljaXBhbnQgQ29udGV4dFxuICogICBwYXJ0aWNpcGFudCBMZWRnZXJcbiAqICAgQ29udHJhY3QtPj5Db250ZXh0OiBuZXcgRmFicmljQ29udHJhY3RDb250ZXh0KClcbiAqICAgQ29udHJhY3QtPj5Db250ZXh0OiBzZXQoJ3N0dWInfCdjbGllbnRJZGVudGl0eSd8J2xvZ2dlcicsIC4uLilcbiAqICAgQ29udGV4dC0tPj5Db250cmFjdDogdGltZXN0YW1wLCBpZGVudGl0eSwgbG9nZ2VyXG4gKiAgIENvbnRyYWN0LT4+TGVkZ2VyOiBJbnRlcmFjdCB2aWEgc3R1YlxuICovXG5leHBvcnQgY2xhc3MgRmFicmljQ29udHJhY3RDb250ZXh0IGV4dGVuZHMgQ29udGV4dDxGYWJyaWNDb250cmFjdEZsYWdzPiB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIG5ldyBGYWJyaWNDb250cmFjdENvbnRleHQgaW5zdGFuY2VcbiAgICogQHN1bW1hcnkgSW5pdGlhbGl6ZXMgdGhlIGNvbnRleHQgd2l0aCBGYWJyaWMtc3BlY2lmaWMgZmxhZ3NcbiAgICovXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgdGhlIGNoYWluY29kZSBzdHViXG4gICAqIEBzdW1tYXJ5IFJldHVybnMgdGhlIENoYWluY29kZVN0dWIgaW5zdGFuY2UgZm9yIGludGVyYWN0aW5nIHdpdGggdGhlIGxlZGdlclxuICAgKiBAcmV0dXJuIHtDaGFpbmNvZGVTdHVifSBUaGUgY2hhaW5jb2RlIHN0dWJcbiAgICovXG4gIGdldCBzdHViKCk6IENoYWluY29kZVN0dWIge1xuICAgIHJldHVybiB0aGlzLmdldChcInN0dWJcIik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgdGhlIHRyYW5zYWN0aW9uIHRpbWVzdGFtcFxuICAgKiBAc3VtbWFyeSBPdmVycmlkZXMgdGhlIGJhc2UgdGltZXN0YW1wIGdldHRlciB0byB1c2UgdGhlIHN0dWIncyB0aW1lc3RhbXBcbiAgICogQHJldHVybiB7RGF0ZX0gVGhlIHRyYW5zYWN0aW9uIHRpbWVzdGFtcFxuICAgKi9cbiAgb3ZlcnJpZGUgZ2V0IHRpbWVzdGFtcCgpOiBEYXRlIHtcbiAgICByZXR1cm4gdGhpcy5zdHViLmdldERhdGVUaW1lc3RhbXAoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgY2xpZW50IGlkZW50aXR5XG4gICAqIEBzdW1tYXJ5IFJldHVybnMgdGhlIENsaWVudElkZW50aXR5IGluc3RhbmNlIGZvciB0aGUgdHJhbnNhY3Rpb24gc3VibWl0dGVyXG4gICAqIEByZXR1cm4ge0NsaWVudElkZW50aXR5fSBUaGUgY2xpZW50IGlkZW50aXR5XG4gICAqL1xuICBnZXQgaWRlbnRpdHkoKTogQ2xpZW50SWRlbnRpdHkge1xuICAgIHJldHVybiB0aGlzLmdldChcImlkZW50aXR5XCIpO1xuICB9XG5cbiAgb3ZlcnJpZGUgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIGBmYWJyaWMgY3R4JHt0aGlzLnN0dWIgPyBcIiB3aXRoIHN0dWJcIiA6IFwid2l0aG91dCBzdHViXCJ9YDtcbiAgfVxufVxuIiwiaW1wb3J0IHsgQnVsa0NydWRPcGVyYXRpb25LZXlzLCBPcGVyYXRpb25LZXlzIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEdlbmVyYXRlcyBhIEZhYnJpYyBldmVudCBuYW1lIGZyb20gY29tcG9uZW50c1xuICogQHN1bW1hcnkgQ3JlYXRlcyBhIHN0YW5kYXJkaXplZCBldmVudCBuYW1lIGJ5IGpvaW5pbmcgdGFibGUsIGV2ZW50LCBhbmQgb3B0aW9uYWwgb3duZXIgd2l0aCB1bmRlcnNjb3Jlc1xuICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlIC0gVGhlIHRhYmxlL2NvbGxlY3Rpb24gbmFtZVxuICogQHBhcmFtIHtPcGVyYXRpb25LZXlzIHwgQnVsa0NydWRPcGVyYXRpb25LZXlzIHwgc3RyaW5nfSBldmVudCAtIFRoZSBldmVudCB0eXBlXG4gKiBAcGFyYW0ge3N0cmluZ30gW293bmVyXSAtIE9wdGlvbmFsIG93bmVyIGlkZW50aWZpZXJcbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIGdlbmVyYXRlZCBldmVudCBuYW1lIGluIGZvcm1hdCBcInRhYmxlX2V2ZW50XCIgb3IgXCJ0YWJsZV9ldmVudF9vd25lclwiXG4gKiBAZnVuY3Rpb24gZ2VuZXJhdGVGYWJyaWNFdmVudE5hbWVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5zaGFyZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlRmFicmljRXZlbnROYW1lKFxuICB0YWJsZTogc3RyaW5nLFxuICBldmVudDogT3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZyxcbiAgb3duZXI/OiBzdHJpbmdcbikge1xuICBjb25zdCBwYXJhbXMgPSBbdGFibGUsIGV2ZW50XTtcbiAgaWYgKG93bmVyKSBwYXJhbXMucHVzaChvd25lcik7XG4gIHJldHVybiBwYXJhbXMuam9pbihcIl9cIik7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFBhcnNlcyBhIEZhYnJpYyBldmVudCBuYW1lIGludG8gaXRzIGNvbXBvbmVudHNcbiAqIEBzdW1tYXJ5IFNwbGl0cyBhbiBldmVudCBuYW1lIGJ5IHVuZGVyc2NvcmVzIGFuZCBleHRyYWN0cyB0YWJsZSwgZXZlbnQsIGFuZCBvcHRpb25hbCBvd25lclxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBUaGUgZXZlbnQgbmFtZSB0byBwYXJzZVxuICogQHJldHVybiB7e3RhYmxlOiBzdHJpbmcsIGV2ZW50OiBPcGVyYXRpb25LZXlzIHwgQnVsa0NydWRPcGVyYXRpb25LZXlzIHwgc3RyaW5nLCBvd25lcjogc3RyaW5nfX0gVGhlIHBhcnNlZCBjb21wb25lbnRzIGFzIGEgc3RydWN0dXJlZCBvYmplY3RcbiAqIEB0aHJvd3Mge0ludGVybmFsRXJyb3J9IElmIHRoZSBldmVudCBuYW1lIGZvcm1hdCBpcyBpbnZhbGlkXG4gKiBAZnVuY3Rpb24gcGFyc2VFdmVudE5hbWVcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IFBhcnNlciBhcyBwYXJzZUV2ZW50TmFtZVxuICogICBDYWxsZXItPj5QYXJzZXI6IHBhcnNlRXZlbnROYW1lKG5hbWUpXG4gKiAgIFBhcnNlci0+PlBhcnNlcjogc3BsaXQgbmFtZSBieSBcIl9cIlxuICogICBhbHQgcGFydHMgbGVuZ3RoIGludmFsaWRcbiAqICAgICBQYXJzZXItLT4+Q2FsbGVyOiB0aHJvdyBJbnRlcm5hbEVycm9yXG4gKiAgIGVsc2VcbiAqICAgICBQYXJzZXItLT4+Q2FsbGVyOiB7IHRhYmxlLCBldmVudCwgb3duZXI/IH1cbiAqICAgZW5kXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1mYWJyaWMuc2hhcmVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUV2ZW50TmFtZShuYW1lOiBzdHJpbmcpOiB7XG4gIHRhYmxlPzogc3RyaW5nO1xuICBldmVudDogT3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZztcbiAgb3duZXI/OiBzdHJpbmc7XG59IHtcbiAgY29uc3QgcGFydHMgPSBuYW1lLnNwbGl0KFwiX1wiKTtcbiAgaWYgKHBhcnRzLmxlbmd0aCA8IDIgfHwgcGFydHMubGVuZ3RoID4gMylcbiAgICByZXR1cm4geyB0YWJsZTogdW5kZWZpbmVkLCBldmVudDogbmFtZSwgb3duZXI6IHVuZGVmaW5lZCB9O1xuICByZXR1cm4ge1xuICAgIHRhYmxlOiBwYXJ0c1swXSxcbiAgICBldmVudDogcGFydHNbMV0sXG4gICAgb3duZXI6IHBhcnRzWzJdLFxuICB9IGFzIHtcbiAgICB0YWJsZTogc3RyaW5nO1xuICAgIGV2ZW50OiBPcGVyYXRpb25LZXlzIHwgQnVsa0NydWRPcGVyYXRpb25LZXlzIHwgc3RyaW5nO1xuICAgIG93bmVyPzogc3RyaW5nO1xuICB9O1xufVxuIiwiaW1wb3J0IHsgQnVsa0NydWRPcGVyYXRpb25LZXlzLCBPcGVyYXRpb25LZXlzIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQge1xuICBBZGFwdGVyLFxuICBDb250ZXh0dWFsQXJncyxcbiAgRXZlbnRJZHMsXG4gIE9ic2VydmVySGFuZGxlcixcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBnZW5lcmF0ZUZhYnJpY0V2ZW50TmFtZSB9IGZyb20gXCIuLi9zaGFyZWQvZXZlbnRzXCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdENvbnRleHQgfSBmcm9tIFwiLi9Db250cmFjdENvbnRleHRcIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIE9ic2VydmVyIGhhbmRsZXIgZm9yIEZhYnJpYyBjaGFpbmNvZGUgZXZlbnRzXG4gKiBAc3VtbWFyeSBFbWl0cyBldmVudHMgb24gdGhlIEZhYnJpYyBsZWRnZXIgd2hlbiByZXBvc2l0b3J5IG9wZXJhdGlvbnMgb2NjdXJcbiAqIEBjbGFzcyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnlPYnNlcnZhYmxlSGFuZGxlclxuICogQGV4dGVuZHMge09ic2VydmVySGFuZGxlcn1cbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBJbiBhIEZhYnJpYyBjaGFpbmNvZGUgY29udHJhY3RcbiAqIGltcG9ydCB7IEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeU9ic2VydmFibGVIYW5kbGVyIH0gZnJvbSAnQGRlY2FmLXRzL2Zvci1mYWJyaWMnO1xuICpcbiAqIC8vIENyZWF0ZSBhIGhhbmRsZXIgd2l0aCBkZWZhdWx0IHN1cHBvcnRlZCBldmVudHNcbiAqIGNvbnN0IGhhbmRsZXIgPSBuZXcgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5T2JzZXJ2YWJsZUhhbmRsZXIoKTtcbiAqXG4gKiAvLyBFbWl0IGFuIGV2ZW50XG4gKiBhd2FpdCBoYW5kbGVyLnVwZGF0ZU9ic2VydmVycyhcbiAqICAgbG9nZ2VyLFxuICogICAnYXNzZXRzJyxcbiAqICAgT3BlcmF0aW9uS2V5cy5DUkVBVEUsXG4gKiAgICdhc3NldDEnLFxuICogICBjb250ZXh0XG4gKiApO1xuICogYGBgXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IFJlcG9zaXRvcnlcbiAqICAgcGFydGljaXBhbnQgT2JzZXJ2YWJsZUhhbmRsZXJcbiAqICAgcGFydGljaXBhbnQgU3R1YlxuICogICBwYXJ0aWNpcGFudCBMZWRnZXJcbiAqXG4gKiAgIFJlcG9zaXRvcnktPj5PYnNlcnZhYmxlSGFuZGxlcjogdXBkYXRlT2JzZXJ2ZXJzKGxvZywgdGFibGUsIGV2ZW50LCBpZCwgY3R4KVxuICogICBPYnNlcnZhYmxlSGFuZGxlci0+Pk9ic2VydmFibGVIYW5kbGVyOiBDaGVjayBpZiBldmVudCBpcyBzdXBwb3J0ZWRcbiAqICAgT2JzZXJ2YWJsZUhhbmRsZXItPj5PYnNlcnZhYmxlSGFuZGxlcjogZ2VuZXJhdGVGYWJyaWNFdmVudE5hbWUodGFibGUsIGV2ZW50LCBvd25lcilcbiAqICAgT2JzZXJ2YWJsZUhhbmRsZXItPj5TdHViOiBzZXRFdmVudChldmVudE5hbWUsIHBheWxvYWQpXG4gKiAgIFN0dWItPj5MZWRnZXI6IFJlY29yZCBldmVudFxuICovXG5leHBvcnQgY2xhc3MgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5T2JzZXJ2YWJsZUhhbmRsZXIgZXh0ZW5kcyBPYnNlcnZlckhhbmRsZXIge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBuZXcgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5T2JzZXJ2YWJsZUhhbmRsZXIgaW5zdGFuY2VcbiAgICogQHN1bW1hcnkgSW5pdGlhbGl6ZXMgdGhlIGhhbmRsZXIgd2l0aCBhIGxpc3Qgb2Ygc3VwcG9ydGVkIGV2ZW50c1xuICAgKiBAcGFyYW0ge0FycmF5PE9wZXJhdGlvbktleXMgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMgfCBzdHJpbmc+fSBbc3VwcG9ydGVkRXZlbnRzXSAtIEV2ZW50cyB0aGF0IHdpbGwgdHJpZ2dlciBGYWJyaWMgZXZlbnRzXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHN1cHBvcnRlZEV2ZW50czogKFxuICAgICAgfCBPcGVyYXRpb25LZXlzXG4gICAgICB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5c1xuICAgICAgfCBzdHJpbmdcbiAgICApW10gPSBbXG4gICAgICBPcGVyYXRpb25LZXlzLkNSRUFURSxcbiAgICAgIE9wZXJhdGlvbktleXMuVVBEQVRFLFxuICAgICAgT3BlcmF0aW9uS2V5cy5ERUxFVEUsXG4gICAgICBCdWxrQ3J1ZE9wZXJhdGlvbktleXMuQ1JFQVRFX0FMTCxcbiAgICAgIEJ1bGtDcnVkT3BlcmF0aW9uS2V5cy5VUERBVEVfQUxMLFxuICAgICAgQnVsa0NydWRPcGVyYXRpb25LZXlzLkRFTEVURV9BTEwsXG4gICAgXVxuICApIHtcbiAgICBzdXBlcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBVcGRhdGVzIG9ic2VydmVycyBieSBlbWl0dGluZyBGYWJyaWMgZXZlbnRzXG4gICAqIEBzdW1tYXJ5IEVtaXRzIGV2ZW50cyBvbiB0aGUgRmFicmljIGxlZGdlciBmb3Igc3VwcG9ydGVkIGV2ZW50IHR5cGVzXG4gICAqIEBwYXJhbSB7TG9nZ2VyfSBsb2cgLSBMb2dnZXIgaW5zdGFuY2UgZm9yIGRlYnVnZ2luZ1xuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGUgLSBUaGUgdGFibGUvY29sbGVjdGlvbiBuYW1lXG4gICAqIEBwYXJhbSB7T3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZ30gZXZlbnQgLSBUaGUgZXZlbnQgdHlwZVxuICAgKiBAcGFyYW0ge0V2ZW50SWRzfSBpZCAtIFRoZSBldmVudCBpZGVudGlmaWVyXG4gICAqIEBwYXJhbSB7RmFicmljQ29udHJhY3RDb250ZXh0fSBjdHggLSBUaGUgRmFicmljIGNvbnRyYWN0IGNvbnRleHRcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtvd25lcl0gLSBPcHRpb25hbCBvd25lciBpZGVudGlmaWVyIGZvciB0aGUgZXZlbnRcbiAgICogQHBhcmFtIHtvYmplY3QgfCBzdHJpbmcgfCB1bmRlZmluZWR9IFtvd25lcl0gLSBPcHRpb25hbCBwYXlsb2FkIGZvciB0aGUgZXZlbnRcbiAgICpcbiAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWRcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIHVwZGF0ZU9ic2VydmVycyhcbiAgICBjbGF6ejogc3RyaW5nIHwgQ29uc3RydWN0b3I8YW55PixcbiAgICBldmVudDogT3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZyxcbiAgICBpZDogRXZlbnRJZHMsXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8RmFicmljQ29udHJhY3RDb250ZXh0PlxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4IH0gPSBBZGFwdGVyLmxvZ0N0eDxGYWJyaWNDb250cmFjdENvbnRleHQ+KFxuICAgICAgYXJncyxcbiAgICAgIHRoaXMudXBkYXRlT2JzZXJ2ZXJzXG4gICAgKTtcbiAgICBjb25zdCB7IHN0dWIgfSA9IGN0eDtcbiAgICBjb25zdCBbb3duZXIsIHBheWxvYWRdID0gYXJncztcbiAgICBjb25zdCB0YWJsZSA9IHR5cGVvZiBjbGF6eiA9PT0gXCJzdHJpbmdcIiA/IGNsYXp6IDogY2xhenoubmFtZTtcbiAgICBpZiAodGhpcy5zdXBwb3J0ZWRFdmVudHMuaW5kZXhPZihldmVudCkgIT09IC0xKSB7XG4gICAgICBsb2cuZGVidWcoYEVtaXR0aW5nICR7ZXZlbnR9IGV2ZW50YCk7XG4gICAgICBjb25zdCBldmVudE5hbWUgPSBnZW5lcmF0ZUZhYnJpY0V2ZW50TmFtZSh0YWJsZSwgZXZlbnQsIG93bmVyKTtcbiAgICAgIHN0dWIuc2V0RXZlbnQoZXZlbnROYW1lLCBCdWZmZXIuZnJvbShKU09OLnN0cmluZ2lmeSh7IGlkOiBpZCB9KSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdHViLnNldEV2ZW50KGV2ZW50LCBCdWZmZXIuZnJvbShKU09OLnN0cmluZ2lmeShwYXlsb2FkKSkpO1xuICAgIH1cbiAgfVxufVxuIiwiaW1wb3J0IHtcbiAgUmVwb3NpdG9yeSxcbiAgT2JzZXJ2ZXJIYW5kbGVyLFxuICBFdmVudElkcyxcbiAgQ29udGV4dHVhbEFyZ3MsXG4gIE1heWJlQ29udGV4dHVhbEFyZyxcbiAgUXVlcnlFcnJvcixcbiAgQ29udGV4dCxcbiAgUGVyc2lzdGVuY2VLZXlzLFxuICBQcmVwYXJlZFN0YXRlbWVudEtleXMsXG4gIE9yZGVyRGlyZWN0aW9uLFxuICBTZXJpYWxpemVkUGFnZSxcbiAgUGFnaW5hdG9yLFxuICBEaXJlY3Rpb25MaW1pdE9mZnNldCxcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdENvbnRleHQgfSBmcm9tIFwiLi9Db250cmFjdENvbnRleHRcIjtcbmltcG9ydCB7IE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5T2JzZXJ2YWJsZUhhbmRsZXIgfSBmcm9tIFwiLi9GYWJyaWNDb250cmFjdFJlcG9zaXRvcnlPYnNlcnZhYmxlSGFuZGxlclwiO1xuaW1wb3J0IHtcbiAgQmFzZUVycm9yLFxuICBCdWxrQ3J1ZE9wZXJhdGlvbktleXMsXG4gIEludGVybmFsRXJyb3IsXG4gIE9wZXJhdGlvbktleXMsXG59IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0QWRhcHRlciB9IGZyb20gXCIuL0NvbnRyYWN0QWRhcHRlclwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXBvc2l0b3J5IGZvciBIeXBlcmxlZGdlciBGYWJyaWMgY2hhaW5jb2RlIG1vZGVsc1xuICogQHN1bW1hcnkgUHJvdmlkZXMgQ1JVRCBvcGVyYXRpb25zIGZvciBtb2RlbHMgd2l0aGluIEZhYnJpYyBjaGFpbmNvZGUgY29udHJhY3RzXG4gKiBAdGVtcGxhdGUgTSAtIFR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAdGVtcGxhdGUgTWFuZ29RdWVyeSAtIFF1ZXJ5IHR5cGUgZm9yIENvdWNoREItbGlrZSBxdWVyaWVzXG4gKiBAdGVtcGxhdGUgRmFicmljQ29udHJhY3RBZGFwdGVyIC0gQWRhcHRlciB0eXBlIGZvciBGYWJyaWMgY29udHJhY3Qgb3BlcmF0aW9uc1xuICogQHRlbXBsYXRlIEZhYnJpY0NvbnRyYWN0RmxhZ3MgLSBGbGFncyBzcGVjaWZpYyB0byBGYWJyaWMgY29udHJhY3Qgb3BlcmF0aW9uc1xuICogQHRlbXBsYXRlIEZhYnJpY0NvbnRyYWN0Q29udGV4dCAtIENvbnRleHQgdHlwZSBmb3IgRmFicmljIGNvbnRyYWN0IG9wZXJhdGlvbnNcbiAqXG4gKiBAcGFyYW0ge0ZhYnJpY0NvbnRyYWN0QWRhcHRlcn0gW2FkYXB0ZXJdIC0gVGhlIGFkYXB0ZXIgZm9yIGludGVyYWN0aW5nIHdpdGggdGhlIHN0YXRlIGRhdGFiYXNlXG4gKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBbY2xhenpdIC0gVGhlIG1vZGVsIGNvbnN0cnVjdG9yXG4gKiBAcGFyYW0ge0FycmF5PE9wZXJhdGlvbktleXMgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMgfCBzdHJpbmc+fSBbdHJhY2tlZEV2ZW50c10gLSBFdmVudHMgdG8gdHJhY2sgZm9yIG9ic2VydmVyIG5vdGlmaWNhdGlvbnNcbiAqXG4gKiBAY2xhc3MgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5XG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gSW4gYSBGYWJyaWMgY2hhaW5jb2RlIGNvbnRyYWN0IGNsYXNzXG4gKiBpbXBvcnQgeyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnksIEZhYnJpY0NvbnRyYWN0QWRhcHRlciB9IGZyb20gJ0BkZWNhZi10cy9mb3ItZmFicmljJztcbiAqXG4gKiBAdGFibGUoJ2Fzc2V0cycpXG4gKiBjbGFzcyBBc3NldCBleHRlbmRzIE1vZGVsIHtcbiAqICAgQGlkKClcbiAqICAgaWQ6IHN0cmluZztcbiAqXG4gKiAgIEBwcm9wZXJ0eSgpXG4gKiAgIGRhdGE6IHN0cmluZztcbiAqIH1cbiAqXG4gKiBleHBvcnQgY2xhc3MgTXlDb250cmFjdCBleHRlbmRzIENvbnRyYWN0IHtcbiAqICAgcHJpdmF0ZSBhZGFwdGVyID0gbmV3IEZhYnJpY0NvbnRyYWN0QWRhcHRlcigpO1xuICogICBwcml2YXRlIHJlcG9zaXRvcnk6IEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeTxBc3NldD47XG4gKlxuICogICBjb25zdHJ1Y3RvcigpIHtcbiAqICAgICBzdXBlcignTXlDb250cmFjdCcpO1xuICogICAgIHRoaXMucmVwb3NpdG9yeSA9IG5ldyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnk8QXNzZXQ+KHRoaXMuYWRhcHRlciwgQXNzZXQpO1xuICogICB9XG4gKlxuICogICBAVHJhbnNhY3Rpb24oKVxuICogICBhc3luYyBjcmVhdGVBc3NldChjdHg6IENvbnRleHQsIGlkOiBzdHJpbmcsIGRhdGE6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICogICAgIGNvbnN0IGFzc2V0ID0gbmV3IEFzc2V0KCk7XG4gKiAgICAgYXNzZXQuaWQgPSBpZDtcbiAqICAgICBhc3NldC5kYXRhID0gZGF0YTtcbiAqXG4gKiAgICAgYXdhaXQgdGhpcy5yZXBvc2l0b3J5LmNyZWF0ZShhc3NldCwgeyBzdHViOiBjdHguc3R1YiB9KTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENvbnRyYWN0XG4gKiAgIHBhcnRpY2lwYW50IFJlcG9zaXRvcnlcbiAqICAgcGFydGljaXBhbnQgQWRhcHRlclxuICogICBwYXJ0aWNpcGFudCBTdGF0ZURCXG4gKlxuICogICBDb250cmFjdC0+PlJlcG9zaXRvcnk6IGNyZWF0ZShtb2RlbCwgY3R4KVxuICogICBSZXBvc2l0b3J5LT4+QWRhcHRlcjogcHJlcGFyZShtb2RlbCwgcGspXG4gKiAgIFJlcG9zaXRvcnktPj5BZGFwdGVyOiBjcmVhdGUodGFibGVOYW1lLCBpZCwgcmVjb3JkLCB0cmFuc2llbnQsIGN0eClcbiAqICAgQWRhcHRlci0+PlN0YXRlREI6IHB1dFN0YXRlKGlkLCBzZXJpYWxpemVkRGF0YSlcbiAqICAgU3RhdGVEQi0tPj5BZGFwdGVyOiBTdWNjZXNzXG4gKiAgIEFkYXB0ZXItLT4+UmVwb3NpdG9yeTogcmVjb3JkXG4gKiAgIFJlcG9zaXRvcnktPj5BZGFwdGVyOiByZXZlcnQocmVjb3JkLCBjbGFzcywgcGssIGlkLCB0cmFuc2llbnQpXG4gKiAgIEFkYXB0ZXItLT4+UmVwb3NpdG9yeTogbW9kZWxcbiAqICAgUmVwb3NpdG9yeS0tPj5Db250cmFjdDogbW9kZWxcbiAqL1xuZXhwb3J0IGNsYXNzIEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeTxNIGV4dGVuZHMgTW9kZWw+IGV4dGVuZHMgUmVwb3NpdG9yeTxcbiAgTSxcbiAgRmFicmljQ29udHJhY3RBZGFwdGVyXG4+IHtcbiAgcHJvdGVjdGVkIG92ZXJyaWRlIF9vdmVycmlkZXMgPSBPYmplY3QuYXNzaWduKHt9LCBzdXBlcltcIl9vdmVycmlkZXNcIl0sIHtcbiAgICBpZ25vcmVWYWxpZGF0aW9uOiBmYWxzZSxcbiAgICBpZ25vcmVIYW5kbGVyczogZmFsc2UsXG4gICAgYWxsb3dSYXdTdGF0ZW1lbnRzOiB0cnVlLFxuICAgIGZvcmNlUHJlcGFyZVNpbXBsZVF1ZXJpZXM6IGZhbHNlLFxuICAgIGZvcmNlUHJlcGFyZUNvbXBsZXhRdWVyaWVzOiBmYWxzZSxcbiAgfSk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgYWRhcHRlcj86IEZhYnJpY0NvbnRyYWN0QWRhcHRlcixcbiAgICBjbGF6ej86IENvbnN0cnVjdG9yPE0+LFxuICAgIHByb3RlY3RlZCB0cmFja2VkRXZlbnRzPzogKE9wZXJhdGlvbktleXMgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMgfCBzdHJpbmcpW11cbiAgKSB7XG4gICAgc3VwZXIoYWRhcHRlciwgY2xhenopO1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgcGFnaW5hdGVCeShcbiAgICBrZXk6IGtleW9mIE0sXG4gICAgb3JkZXI6IE9yZGVyRGlyZWN0aW9uLFxuICAgIHJlZjogT21pdDxEaXJlY3Rpb25MaW1pdE9mZnNldCwgXCJkaXJlY3Rpb25cIj4gPSB7XG4gICAgICBvZmZzZXQ6IDEsXG4gICAgICBsaW1pdDogMTAsXG4gICAgfSxcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8RmFicmljQ29udHJhY3RDb250ZXh0PlxuICApOiBQcm9taXNlPFNlcmlhbGl6ZWRQYWdlPE0+PiB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHByZWZlci1jb25zdFxuICAgIGxldCB7IG9mZnNldCwgYm9va21hcmssIGxpbWl0IH0gPSByZWY7XG4gICAgaWYgKCFvZmZzZXQgJiYgIWJvb2ttYXJrKVxuICAgICAgdGhyb3cgbmV3IFF1ZXJ5RXJyb3IoYFBhZ2luYXRlQnkgbmVlZHMgYSBwYWdlIG9yIGEgYm9va21hcmtgKTtcbiAgICBjb25zdCBjb250ZXh0QXJncyA9IGF3YWl0IENvbnRleHQuYXJncyhcbiAgICAgIFByZXBhcmVkU3RhdGVtZW50S2V5cy5QQUdFX0JZLFxuICAgICAgdGhpcy5jbGFzcyxcbiAgICAgIGFyZ3MsXG4gICAgICB0aGlzLmFkYXB0ZXIsXG4gICAgICB0aGlzLl9vdmVycmlkZXMgfHwge31cbiAgICApO1xuICAgIGNvbnN0IHsgbG9nLCBjdHhBcmdzIH0gPSB0aGlzLmxvZ0N0eChjb250ZXh0QXJncy5hcmdzLCB0aGlzLnBhZ2luYXRlQnkpO1xuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYHBhZ2luYXRpbmcgJHtNb2RlbC50YWJsZU5hbWUodGhpcy5jbGFzcyl9IHdpdGggcGFnZSBzaXplICR7bGltaXR9YFxuICAgICk7XG5cbiAgICBsZXQgcGFnaW5hdG9yOiBQYWdpbmF0b3I8TT47XG4gICAgaWYgKGJvb2ttYXJrKSB7XG4gICAgICBwYWdpbmF0b3IgPSBhd2FpdCB0aGlzLm92ZXJyaWRlKHtcbiAgICAgICAgZm9yY2VQcmVwYXJlQ29tcGxleFF1ZXJpZXM6IGZhbHNlLFxuICAgICAgICBmb3JjZVByZXBhcmVTaW1wbGVRdWVyaWVzOiBmYWxzZSxcbiAgICAgIH0gYXMgYW55KVxuICAgICAgICAuc2VsZWN0KClcbiAgICAgICAgLndoZXJlKHRoaXMuYXR0cihNb2RlbC5wayh0aGlzLmNsYXNzKSkuZ3QoYm9va21hcmspKVxuICAgICAgICAub3JkZXJCeShba2V5LCBvcmRlcl0pXG4gICAgICAgIC5wYWdpbmF0ZShsaW1pdCBhcyBudW1iZXIsIC4uLmN0eEFyZ3MpO1xuICAgICAgb2Zmc2V0ID0gMTtcbiAgICB9IGVsc2UgaWYgKG9mZnNldCkge1xuICAgICAgcGFnaW5hdG9yID0gYXdhaXQgdGhpcy5vdmVycmlkZSh7XG4gICAgICAgIGZvcmNlUHJlcGFyZUNvbXBsZXhRdWVyaWVzOiBmYWxzZSxcbiAgICAgICAgZm9yY2VQcmVwYXJlU2ltcGxlUXVlcmllczogZmFsc2UsXG4gICAgICB9IGFzIGFueSlcbiAgICAgICAgLnNlbGVjdCgpXG4gICAgICAgIC5vcmRlckJ5KFtrZXksIG9yZGVyXSlcbiAgICAgICAgLnBhZ2luYXRlKGxpbWl0IGFzIG51bWJlciwgLi4uY3R4QXJncyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBRdWVyeUVycm9yKGBQYWdpbmF0ZUJ5IG5lZWRzIGEgcGFnZSBvciBhIGJvb2ttYXJrYCk7XG4gICAgfVxuICAgIGNvbnN0IHBhZ2VkID0gYXdhaXQgcGFnaW5hdG9yLnBhZ2Uob2Zmc2V0LCAuLi5jdHhBcmdzKTtcbiAgICByZXR1cm4gcGFnaW5hdG9yLnNlcmlhbGl6ZShwYWdlZCkgYXMgU2VyaWFsaXplZFBhZ2U8TT47XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBzdGF0ZW1lbnQoXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxGYWJyaWNDb250cmFjdENvbnRleHQ+XG4gICkge1xuICAgIGlmICghUmVwb3NpdG9yeS5zdGF0ZW1lbnRzKHRoaXMsIG5hbWUgYXMga2V5b2YgdHlwZW9mIHRoaXMpKVxuICAgICAgdGhyb3cgbmV3IFF1ZXJ5RXJyb3IoYEludmFsaWQgcHJlcGFyZWQgc3RhdGVtZW50IHJlcXVlc3RlZCAke25hbWV9YCk7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3MoXG4gICAgICBQZXJzaXN0ZW5jZUtleXMuU1RBVEVNRU5ULFxuICAgICAgdGhpcy5jbGFzcyxcbiAgICAgIGFyZ3MsXG4gICAgICB0aGlzLmFkYXB0ZXIsXG4gICAgICB0aGlzLl9vdmVycmlkZXMgfHwge31cbiAgICApO1xuICAgIGlmIChjb250ZXh0QXJncy5jb250ZXh0LmxvZ2dlcikge1xuICAgICAgY29udGV4dEFyZ3MuY29udGV4dC5sb2dnZXIuaW5mbyhgUmVwbyBzdGF0ZW1lbnQ6ICR7bmFtZX0gKyAke2FyZ3N9YCk7XG4gICAgfVxuICAgIGNvbnN0IHsgbG9nLCBjdHhBcmdzIH0gPSB0aGlzLmxvZ0N0eChjb250ZXh0QXJncy5hcmdzLCB0aGlzLnN0YXRlbWVudCk7XG4gICAgbG9nLnZlcmJvc2UoYEV4ZWN1dGluZyBwcmVwYXJlZCBzdGF0ZW1lbnQgJHtuYW1lfSB3aXRoIGFyZ3MgJHtjdHhBcmdzfWApO1xuXG4gICAgbGV0IHJlc3VsdDogYW55O1xuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBhd2FpdCAodGhpcyBhcyBhbnkpW25hbWVdKC4uLmN0eEFyZ3MpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIGlmIChlIGluc3RhbmNlb2YgQmFzZUVycm9yKSB0aHJvdyBlO1xuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIGBGYWlsZWQgdG8gZXhlY3V0ZSBwcmVwYXJlZCBzdGF0ZW1lbnQgJHtuYW1lfSB3aXRoIGFyZ3MgJHtjdHhBcmdzfTogJHtlfWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgb2JzZXJ2ZXIgaGFuZGxlciBmb3IgdGhpcyByZXBvc2l0b3J5XG4gICAqIEBzdW1tYXJ5IFJldHVybnMgYSBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnlPYnNlcnZhYmxlSGFuZGxlciBpbnN0YW5jZVxuICAgKiBAcmV0dXJuIHtPYnNlcnZlckhhbmRsZXJ9IFRoZSBvYnNlcnZlciBoYW5kbGVyXG4gICAqL1xuICBvdmVycmlkZSBPYnNlcnZlckhhbmRsZXIoKTogT2JzZXJ2ZXJIYW5kbGVyIHtcbiAgICByZXR1cm4gbmV3IEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeU9ic2VydmFibGVIYW5kbGVyKCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgb2JzZXJ2ZXJzIGJhc2VkIG9uIHRyYWNrZWQgZXZlbnRzXG4gICAqIEBzdW1tYXJ5IEZpbHRlcnMgZXZlbnRzIGJhc2VkIG9uIHRyYWNrZWRFdmVudHMgYW5kIGRlbGVnYXRlcyB0byB0aGUgcGFyZW50IG1ldGhvZFxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGUgLSBUaGUgdGFibGUvY29sbGVjdGlvbiBuYW1lXG4gICAqIEBwYXJhbSB7T3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZ30gZXZlbnQgLSBUaGUgZXZlbnQgdHlwZVxuICAgKiBAcGFyYW0ge0V2ZW50SWRzfSBpZCAtIFRoZSBldmVudCBpZGVudGlmaWVyXG4gICAqIEBwYXJhbSB7RmFicmljQ29udHJhY3RDb250ZXh0fSBjdHggLSBUaGUgRmFicmljIGNvbnRyYWN0IGNvbnRleHRcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59IFByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIG9ic2VydmVycyBhcmUgdXBkYXRlZFxuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgdXBkYXRlT2JzZXJ2ZXJzKFxuICAgIHRhYmxlOiBDb25zdHJ1Y3RvcjxNPiB8IHN0cmluZyxcbiAgICBldmVudDogT3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZyxcbiAgICBpZDogRXZlbnRJZHMsXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8RmFicmljQ29udHJhY3RDb250ZXh0PlxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIXRoaXMudHJhY2tlZEV2ZW50cyB8fCB0aGlzLnRyYWNrZWRFdmVudHMuaW5kZXhPZihldmVudCkgIT09IC0xKVxuICAgICAgcmV0dXJuIGF3YWl0IHN1cGVyLnVwZGF0ZU9ic2VydmVycyh0YWJsZSwgZXZlbnQsIGlkLCAuLi5hcmdzKTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQge1xuICBDb3VjaERCQWRhcHRlcixcbiAgQ291Y2hEQkdyb3VwT3BlcmF0b3IsXG4gIENvdWNoREJLZXlzLFxuICBDb3VjaERCT3BlcmF0b3IsXG4gIE1hbmdvT3BlcmF0b3IsXG4gIE1hbmdvUXVlcnksXG4gIE1hbmdvU2VsZWN0b3IsXG59IGZyb20gXCJAZGVjYWYtdHMvZm9yLWNvdWNoZGJcIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0Q29udGV4dCB9IGZyb20gXCIuL0NvbnRyYWN0Q29udGV4dFwiO1xuaW1wb3J0IHsgQ291Y2hEQlN0YXRlbWVudCB9IGZyb20gXCJAZGVjYWYtdHMvZm9yLWNvdWNoZGJcIjtcbmltcG9ydCB7IENvbmRpdGlvbiwgT3JkZXJEaXJlY3Rpb24gfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IE1ldGFkYXRhIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5pbXBvcnQgeyBEQktleXMgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU3RhdGVtZW50IHdyYXBwZXIgZm9yIGV4ZWN1dGluZyBNYW5nbyBxdWVyaWVzIHdpdGhpbiBGYWJyaWMgY29udHJhY3RzXG4gKiBAc3VtbWFyeSBCcmlkZ2VzIENvdWNoREItc3R5bGUgcXVlcmllcyB0byBGYWJyaWMgdmlhIHRoZSBGYWJyaWNDb250cmFjdEFkYXB0ZXIsIGhhbmRsaW5nIGlkZW50aXR5IGFuZCBwcmltYXJ5IGtleSBwcm9qZWN0aW9uIHdoZW4gbmVlZGVkLlxuICogQHRlbXBsYXRlIE0gLSBNb2RlbCB0eXBlIHRoaXMgc3RhdGVtZW50IG9wZXJhdGVzIG9uXG4gKiBAdGVtcGxhdGUgUiAtIFJlc3VsdCB0eXBlIHJldHVybmVkIGJ5IHRoZSBzdGF0ZW1lbnRcbiAqIEBwYXJhbSB7RmFicmljQ29udHJhY3RBZGFwdGVyfSBhZGFwdGVyIC0gVGhlIEZhYnJpYyBjb250cmFjdCBhZGFwdGVyIHVzZWQgZm9yIHJhdyBleGVjdXRpb25cbiAqIEBwYXJhbSB7RmFicmljQ29udHJhY3RDb250ZXh0fSBjdHggLSBUaGUgRmFicmljIGNvbnRyYWN0IGNvbnRleHQgY2Fycnlpbmcgc3R1YiBhbmQgaWRlbnRpdHlcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKiBAY2xhc3MgRmFicmljU3RhdGVtZW50XG4gKiBAZXhhbXBsZVxuICogY29uc3Qgc3RtdCA9IG5ldyBGYWJyaWNTdGF0ZW1lbnQ8TXlNb2RlbCwgTXlNb2RlbFtdPihhZGFwdGVyLCBjdHgpO1xuICogY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RtdC5yYXc8TXlNb2RlbFtdPih7IHNlbGVjdG9yOiB7IHR5cGU6ICdNeU1vZGVsJyB9IH0pO1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBBcHBcbiAqICAgcGFydGljaXBhbnQgU3RhdGVtZW50XG4gKiAgIHBhcnRpY2lwYW50IEFkYXB0ZXJcbiAqICAgcGFydGljaXBhbnQgTGVkZ2VyXG4gKiAgIEFwcC0+PlN0YXRlbWVudDogcmF3KHsgc2VsZWN0b3IgfSlcbiAqICAgU3RhdGVtZW50LT4+QWRhcHRlcjogYWRhcHRlci5yYXcobWFuZ28sIHRydWUsIGN0eClcbiAqICAgQWRhcHRlci0+PkxlZGdlcjogRXZhbHVhdGUgcXVlcnlcbiAqICAgQWRhcHRlci0tPj5TdGF0ZW1lbnQ6IHJvd3NcbiAqICAgU3RhdGVtZW50LS0+PkFwcDogbW9kZWxzXG4gKi9cbmV4cG9ydCBjbGFzcyBGYWJyaWNTdGF0ZW1lbnQ8TSBleHRlbmRzIE1vZGVsLCBSPiBleHRlbmRzIENvdWNoREJTdGF0ZW1lbnQ8XG4gIE0sXG4gIENvdWNoREJBZGFwdGVyPGFueSwgdm9pZCwgRmFicmljQ29udHJhY3RDb250ZXh0PixcbiAgUlxuPiB7XG4gIGNvbnN0cnVjdG9yKGFkYXB0ZXI6IENvdWNoREJBZGFwdGVyPGFueSwgdm9pZCwgRmFicmljQ29udHJhY3RDb250ZXh0Pikge1xuICAgIHN1cGVyKGFkYXB0ZXIpO1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgcmF3PFI+KHJhd0lucHV0OiBNYW5nb1F1ZXJ5LCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8Uj4ge1xuICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLnJhdyk7XG5cbiAgICBjb25zdCByZXN1bHRzOiBhbnlbXSA9IGF3YWl0IHRoaXMuYWRhcHRlci5yYXcocmF3SW5wdXQsIHRydWUsIGN0eCk7XG5cbiAgICBjb25zdCBwa0F0dHIgPSBNb2RlbC5wayh0aGlzLmZyb21TZWxlY3Rvcik7XG4gICAgY29uc3QgdHlwZSA9IE1ldGFkYXRhLmdldChcbiAgICAgIHRoaXMuZnJvbVNlbGVjdG9yLFxuICAgICAgTWV0YWRhdGEua2V5KERCS2V5cy5JRCwgcGtBdHRyIGFzIHN0cmluZylcbiAgICApPy50eXBlO1xuXG4gICAgaWYgKCF0aGlzLnNlbGVjdFNlbGVjdG9yKVxuICAgICAgcmV0dXJuIHJlc3VsdHMubWFwKChyKSA9PiB0aGlzLnByb2Nlc3NSZWNvcmQociwgcGtBdHRyLCB0eXBlLCBjdHgpKSBhcyBSO1xuICAgIHJldHVybiByZXN1bHRzIGFzIFI7XG4gIH1cblxuICBvdmVycmlkZSBidWlsZCgpOiBNYW5nb1F1ZXJ5IHtcbiAgICBjb25zdCBzZWxlY3RvcnM6IE1hbmdvU2VsZWN0b3IgPSB7fTtcbiAgICBzZWxlY3RvcnNbQ291Y2hEQktleXMuVEFCTEVdID0ge307XG4gICAgc2VsZWN0b3JzW0NvdWNoREJLZXlzLlRBQkxFXSA9IE1vZGVsLnRhYmxlTmFtZSh0aGlzLmZyb21TZWxlY3Rvcik7XG4gICAgY29uc3QgcXVlcnk6IE1hbmdvUXVlcnkgPSB7IHNlbGVjdG9yOiBzZWxlY3RvcnMgfTtcbiAgICBpZiAodGhpcy5zZWxlY3RTZWxlY3RvcikgcXVlcnkuZmllbGRzID0gdGhpcy5zZWxlY3RTZWxlY3RvciBhcyBzdHJpbmdbXTtcblxuICAgIGlmICh0aGlzLndoZXJlQ29uZGl0aW9uKSB7XG4gICAgICBjb25zdCBjb25kaXRpb246IE1hbmdvU2VsZWN0b3IgPSB0aGlzLnBhcnNlQ29uZGl0aW9uKFxuICAgICAgICBDb25kaXRpb24uYW5kKFxuICAgICAgICAgIHRoaXMud2hlcmVDb25kaXRpb24sXG4gICAgICAgICAgQ29uZGl0aW9uLmF0dHJpYnV0ZTxNPihDb3VjaERCS2V5cy5UQUJMRSBhcyBrZXlvZiBNKS5lcShcbiAgICAgICAgICAgIHF1ZXJ5LnNlbGVjdG9yW0NvdWNoREJLZXlzLlRBQkxFXVxuICAgICAgICAgIClcbiAgICAgICAgKVxuICAgICAgKS5zZWxlY3RvcjtcbiAgICAgIGNvbnN0IHNlbGVjdG9yS2V5cyA9IE9iamVjdC5rZXlzKGNvbmRpdGlvbikgYXMgTWFuZ29PcGVyYXRvcltdO1xuICAgICAgaWYgKFxuICAgICAgICBzZWxlY3RvcktleXMubGVuZ3RoID09PSAxICYmXG4gICAgICAgIE9iamVjdC52YWx1ZXMoQ291Y2hEQkdyb3VwT3BlcmF0b3IpLmluZGV4T2Yoc2VsZWN0b3JLZXlzWzBdKSAhPT0gLTFcbiAgICAgIClcbiAgICAgICAgc3dpdGNoIChzZWxlY3RvcktleXNbMF0pIHtcbiAgICAgICAgICBjYXNlIENvdWNoREJHcm91cE9wZXJhdG9yLkFORDpcbiAgICAgICAgICAgIGNvbmRpdGlvbltDb3VjaERCR3JvdXBPcGVyYXRvci5BTkRdID0gW1xuICAgICAgICAgICAgICAuLi5PYmplY3QudmFsdWVzKFxuICAgICAgICAgICAgICAgIGNvbmRpdGlvbltDb3VjaERCR3JvdXBPcGVyYXRvci5BTkRdIGFzIE1hbmdvU2VsZWN0b3JcbiAgICAgICAgICAgICAgKS5yZWR1Y2UoKGFjY3VtOiBNYW5nb1NlbGVjdG9yW10sIHZhbDogYW55KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKHZhbCk7XG4gICAgICAgICAgICAgICAgaWYgKGtleXMubGVuZ3RoICE9PSAxKVxuICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgICAgICBcIlRvbyBtYW55IGtleXMgaW4gcXVlcnkgc2VsZWN0b3IuIHNob3VsZCBiZSBvbmVcIlxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBjb25zdCBrID0ga2V5c1swXTtcbiAgICAgICAgICAgICAgICBpZiAoayA9PT0gQ291Y2hEQkdyb3VwT3BlcmF0b3IuQU5EKVxuICAgICAgICAgICAgICAgICAgYWNjdW0ucHVzaCguLi4odmFsW2tdIGFzIGFueVtdKSk7XG4gICAgICAgICAgICAgICAgZWxzZSBhY2N1bS5wdXNoKHZhbCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFjY3VtO1xuICAgICAgICAgICAgICB9LCBbXSksXG4gICAgICAgICAgICBdO1xuICAgICAgICAgICAgcXVlcnkuc2VsZWN0b3IgPSBjb25kaXRpb247XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlIENvdWNoREJHcm91cE9wZXJhdG9yLk9SOiB7XG4gICAgICAgICAgICBjb25zdCBzOiBSZWNvcmQ8YW55LCBhbnk+ID0ge307XG4gICAgICAgICAgICBzW0NvdWNoREJHcm91cE9wZXJhdG9yLkFORF0gPSBbXG4gICAgICAgICAgICAgIGNvbmRpdGlvbixcbiAgICAgICAgICAgICAgLi4uT2JqZWN0LmVudHJpZXMocXVlcnkuc2VsZWN0b3IpLm1hcCgoW2tleSwgdmFsXSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdDogUmVjb3JkPGFueSwgYW55PiA9IHt9O1xuICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdmFsO1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIHF1ZXJ5LnNlbGVjdG9yID0gcztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhpcyBzaG91bGQgYmUgaW1wb3NzaWJsZVwiKTtcbiAgICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIE9iamVjdC5lbnRyaWVzKGNvbmRpdGlvbikuZm9yRWFjaCgoW2tleSwgdmFsXSkgPT4ge1xuICAgICAgICAgIGlmIChxdWVyeS5zZWxlY3RvcltrZXldKVxuICAgICAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICAgICBgQSAke2tleX0gcXVlcnkgcGFyYW0gaXMgYWJvdXQgdG8gYmUgb3ZlcnJpZGRlbjogJHtxdWVyeS5zZWxlY3RvcltrZXldfSBieSAke3ZhbH1gXG4gICAgICAgICAgICApO1xuICAgICAgICAgIHF1ZXJ5LnNlbGVjdG9yW2tleV0gPSB2YWw7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLm9yZGVyQnlTZWxlY3Rvcikge1xuICAgICAgcXVlcnkuc29ydCA9IHF1ZXJ5LnNvcnQgfHwgW107XG4gICAgICBxdWVyeS5zZWxlY3RvciA9IHF1ZXJ5LnNlbGVjdG9yIHx8ICh7fSBhcyBNYW5nb1NlbGVjdG9yKTtcbiAgICAgIGNvbnN0IFtzZWxlY3RvciwgdmFsdWVdID0gdGhpcy5vcmRlckJ5U2VsZWN0b3IgYXMgW1xuICAgICAgICBzdHJpbmcsXG4gICAgICAgIE9yZGVyRGlyZWN0aW9uLFxuICAgICAgXTtcbiAgICAgIGNvbnN0IHJlYzogYW55ID0ge307XG4gICAgICByZWNbc2VsZWN0b3JdID0gdmFsdWU7XG4gICAgICAocXVlcnkuc29ydCBhcyBhbnlbXSkucHVzaChyZWMgYXMgYW55KTtcbiAgICAgIGlmICghcXVlcnkuc2VsZWN0b3Jbc2VsZWN0b3JdKSB7XG4gICAgICAgIHF1ZXJ5LnNlbGVjdG9yW3NlbGVjdG9yXSA9IHt9IGFzIE1hbmdvU2VsZWN0b3I7XG4gICAgICAgIChxdWVyeS5zZWxlY3RvcltzZWxlY3Rvcl0gYXMgTWFuZ29TZWxlY3RvcilbQ291Y2hEQk9wZXJhdG9yLkJJR0dFUl0gPVxuICAgICAgICAgIG51bGw7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRoaXMubGltaXRTZWxlY3RvcikgcXVlcnkubGltaXQgPSB0aGlzLmxpbWl0U2VsZWN0b3I7XG5cbiAgICBpZiAodGhpcy5vZmZzZXRTZWxlY3RvcikgcXVlcnkuc2tpcCA9IHRoaXMub2Zmc2V0U2VsZWN0b3I7XG5cbiAgICByZXR1cm4gcXVlcnk7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIENvbmZsaWN0RXJyb3IsXG4gIEludGVybmFsRXJyb3IsXG4gIE5vdEZvdW5kRXJyb3IsXG4gIE9wZXJhdGlvbktleXMsXG59IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHtcbiAgQWRhcHRlcixcbiAgQ29udGV4dCxcbiAgTWF5YmVDb250ZXh0dWFsQXJnLFxuICBTZXF1ZW5jZSxcbiAgU2VxdWVuY2VNb2RlbCxcbiAgU2VxdWVuY2VPcHRpb25zLFxuICBTZXJpYWwsXG4gIFVuc3VwcG9ydGVkRXJyb3IsXG4gIFVVSUQsXG59IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgc3R5bGUgfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQWJzdHJhY3QgYmFzZSBjbGFzcyBmb3Igc2VxdWVuY2UgZ2VuZXJhdGlvblxuICogQHN1bW1hcnkgUHJvdmlkZXMgYSBmcmFtZXdvcmsgZm9yIGdlbmVyYXRpbmcgc2VxdWVudGlhbCB2YWx1ZXMgKGxpa2UgcHJpbWFyeSBrZXlzKSBpbiB0aGUgcGVyc2lzdGVuY2UgbGF5ZXIuXG4gKiBJbXBsZW1lbnRhdGlvbnMgb2YgdGhpcyBjbGFzcyBoYW5kbGUgdGhlIHNwZWNpZmljcyBvZiBob3cgc2VxdWVuY2VzIGFyZSBzdG9yZWQgYW5kIGluY3JlbWVudGVkIGluIGRpZmZlcmVudFxuICogZGF0YWJhc2Ugc3lzdGVtcy5cbiAqIEBwYXJhbSB7U2VxdWVuY2VPcHRpb25zfSBvcHRpb25zIC0gQ29uZmlndXJhdGlvbiBvcHRpb25zIGZvciB0aGUgc2VxdWVuY2UgZ2VuZXJhdG9yXG4gKiBAY2xhc3MgU2VxdWVuY2VcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBFeGFtcGxlIGltcGxlbWVudGF0aW9uIGZvciBhIHNwZWNpZmljIGRhdGFiYXNlXG4gKiBjbGFzcyBQb3N0Z3Jlc1NlcXVlbmNlIGV4dGVuZHMgU2VxdWVuY2Uge1xuICogICBjb25zdHJ1Y3RvcihvcHRpb25zOiBTZXF1ZW5jZU9wdGlvbnMpIHtcbiAqICAgICBzdXBlcihvcHRpb25zKTtcbiAqICAgfVxuICpcbiAqICAgYXN5bmMgbmV4dCgpOiBQcm9taXNlPG51bWJlcj4ge1xuICogICAgIC8vIEltcGxlbWVudGF0aW9uIHRvIGdldCBuZXh0IHZhbHVlIGZyb20gUG9zdGdyZVNRTCBzZXF1ZW5jZVxuICogICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMub3B0aW9ucy5leGVjdXRvci5yYXcoYFNFTEVDVCBuZXh0dmFsKCcke3RoaXMub3B0aW9ucy5uYW1lfScpYCk7XG4gKiAgICAgcmV0dXJuIHBhcnNlSW50KHJlc3VsdC5yb3dzWzBdLm5leHR2YWwpO1xuICogICB9XG4gKlxuICogICBhc3luYyBjdXJyZW50KCk6IFByb21pc2U8bnVtYmVyPiB7XG4gKiAgICAgLy8gSW1wbGVtZW50YXRpb24gdG8gZ2V0IGN1cnJlbnQgdmFsdWUgZnJvbSBQb3N0Z3JlU1FMIHNlcXVlbmNlXG4gKiAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5vcHRpb25zLmV4ZWN1dG9yLnJhdyhgU0VMRUNUIGN1cnJ2YWwoJyR7dGhpcy5vcHRpb25zLm5hbWV9JylgKTtcbiAqICAgICByZXR1cm4gcGFyc2VJbnQocmVzdWx0LnJvd3NbMF0uY3VycnZhbCk7XG4gKiAgIH1cbiAqXG4gKiAgIGFzeW5jIHJhbmdlKGNvdW50OiBudW1iZXIpOiBQcm9taXNlPG51bWJlcltdPiB7XG4gKiAgICAgLy8gSW1wbGVtZW50YXRpb24gdG8gZ2V0IGEgcmFuZ2Ugb2YgdmFsdWVzXG4gKiAgICAgY29uc3QgdmFsdWVzOiBudW1iZXJbXSA9IFtdO1xuICogICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICogICAgICAgdmFsdWVzLnB1c2goYXdhaXQgdGhpcy5uZXh0KCkpO1xuICogICAgIH1cbiAqICAgICByZXR1cm4gdmFsdWVzO1xuICogICB9XG4gKiB9XG4gKlxuICogLy8gVXNhZ2VcbiAqIGNvbnN0IHNlcXVlbmNlID0gbmV3IFBvc3RncmVzU2VxdWVuY2Uoe1xuICogICBuYW1lOiAndXNlcl9pZF9zZXEnLFxuICogICBleGVjdXRvcjogZGJFeGVjdXRvclxuICogfSk7XG4gKlxuICogY29uc3QgbmV4dElkID0gYXdhaXQgc2VxdWVuY2UubmV4dCgpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBjbGFzcyBGYWJyaWNDb250cmFjdFNlcXVlbmNlIGV4dGVuZHMgU2VxdWVuY2Uge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBuZXcgc2VxdWVuY2UgaW5zdGFuY2VcbiAgICogQHN1bW1hcnkgUHJvdGVjdGVkIGNvbnN0cnVjdG9yIHRoYXQgaW5pdGlhbGl6ZXMgdGhlIHNlcXVlbmNlIHdpdGggdGhlIHByb3ZpZGVkIG9wdGlvbnNcbiAgICovXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IFNlcXVlbmNlT3B0aW9ucywgYWRhcHRlcjogQWRhcHRlcjxhbnksIGFueSwgYW55Pikge1xuICAgIHN1cGVyKG9wdGlvbnMsIGFkYXB0ZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgdGhlIGN1cnJlbnQgdmFsdWUgb2YgdGhlIHNlcXVlbmNlXG4gICAqIEBzdW1tYXJ5IEdldHMgdGhlIGN1cnJlbnQgdmFsdWUgb2YgdGhlIHNlcXVlbmNlIGZyb20gc3RvcmFnZS4gSWYgdGhlIHNlcXVlbmNlXG4gICAqIGRvZXNuJ3QgZXhpc3QgeWV0LCBpdCByZXR1cm5zIHRoZSBjb25maWd1cmVkIHN0YXJ0aW5nIHZhbHVlLlxuICAgKiBAcmV0dXJuIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBjdXJyZW50IHNlcXVlbmNlIHZhbHVlXG4gICAqL1xuICBvdmVycmlkZSBhc3luYyBjdXJyZW50KFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxhbnk+XG4gICk6IFByb21pc2U8c3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50PiB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3M8YW55LCBhbnk+KFxuICAgICAgT3BlcmF0aW9uS2V5cy5SRUFELFxuICAgICAgU2VxdWVuY2VNb2RlbCxcbiAgICAgIGFyZ3MsXG4gICAgICB0aGlzLmFkYXB0ZXJcbiAgICApO1xuICAgIGNvbnN0IGN0eCA9IGNvbnRleHRBcmdzLmNvbnRleHQ7XG4gICAgY29uc3QgeyBuYW1lLCBzdGFydFdpdGggfSA9IHRoaXMub3B0aW9ucztcbiAgICB0cnkge1xuICAgICAgY29uc3Qgc2VxdWVuY2U6IFNlcXVlbmNlTW9kZWwgPSBhd2FpdCB0aGlzLnJlcG8ucmVhZChuYW1lIGFzIHN0cmluZywgY3R4KTtcbiAgICAgIHJldHVybiB0aGlzLnBhcnNlKHNlcXVlbmNlLmN1cnJlbnQgYXMgc3RyaW5nIHwgbnVtYmVyKTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIGNvbnN0IGxvZyA9IGN0eC5sb2dnZXIuZm9yKHRoaXMuY3VycmVudCk7XG4gICAgICBpZiAoZSBpbnN0YW5jZW9mIE5vdEZvdW5kRXJyb3IpIHtcbiAgICAgICAgbGV0IGNhY2hlZEN1cnJlbnQ6IGFueTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBsb2cuZGVidWcoXG4gICAgICAgICAgICBgVHJ5aW5nIHRvIHJlc29sdmUgY3VycmVudCBzZXF1ZW5jZSAke25hbWV9IHZhbHVlIGZyb20gY29udGV4dGBcbiAgICAgICAgICApO1xuICAgICAgICAgIGNhY2hlZEN1cnJlbnQgPSBjdHguZ2V0KG5hbWUpO1xuICAgICAgICAgIGxvZy5kZWJ1ZyhcbiAgICAgICAgICAgIGBSZXRyaWV2ZWQgY2FjaGVkIGN1cnJlbnQgdmFsdWUgZm9yIHNlcXVlbmNlICR7bmFtZX06ICR7Y2FjaGVkQ3VycmVudH1gXG4gICAgICAgICAgKTtcbiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgICAgICBsb2cuaW5mbyhgTm8gY2FjaGVkIHZhbHVlIGZvciBzZXF1ZW5jZSAke25hbWV9IGluIGNvbnRleHRgKTtcbiAgICAgICAgICBjYWNoZWRDdXJyZW50ID0gc3RhcnRXaXRoO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMucGFyc2UoY2FjaGVkQ3VycmVudCk7XG4gICAgICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICAgICAgYEZhaWxlZCB0byBwYXJzZSBpbml0aWFsIHZhbHVlIGZvciBzZXF1ZW5jZSAke3N0YXJ0V2l0aH06ICR7ZX1gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIGBGYWlsZWQgdG8gcmV0cmlldmUgY3VycmVudCB2YWx1ZSBmb3Igc2VxdWVuY2UgJHtuYW1lfTogJHtlfWBcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBJbmNyZW1lbnRzIHRoZSBzZXF1ZW5jZSB2YWx1ZVxuICAgKiBAc3VtbWFyeSBJbmNyZWFzZXMgdGhlIGN1cnJlbnQgc2VxdWVuY2UgdmFsdWUgYnkgdGhlIHNwZWNpZmllZCBhbW91bnQgYW5kIHBlcnNpc3RzXG4gICAqIHRoZSBuZXcgdmFsdWUgdG8gc3RvcmFnZS4gVGhpcyBtZXRob2QgaGFuZGxlcyBib3RoIG51bWVyaWMgYW5kIEJpZ0ludCBzZXF1ZW5jZSB0eXBlcy5cbiAgICogQHBhcmFtIHtzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnR9IGN1cnJlbnQgLSBUaGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgc2VxdWVuY2VcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtjb3VudF0gLSBPcHRpb25hbCBhbW91bnQgdG8gaW5jcmVtZW50IGJ5LCBkZWZhdWx0cyB0byB0aGUgc2VxdWVuY2UncyBpbmNyZW1lbnRCeSB2YWx1ZVxuICAgKiBAcmV0dXJuIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBuZXcgc2VxdWVuY2UgdmFsdWUgYWZ0ZXIgaW5jcmVtZW50aW5nXG4gICAqL1xuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgYXN5bmMgaW5jcmVtZW50KFxuICAgIGNvdW50OiBudW1iZXIgfCB1bmRlZmluZWQsXG4gICAgY3R4OiBDb250ZXh0PGFueT5cbiAgKTogUHJvbWlzZTxzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQ+IHtcbiAgICBjb25zdCBsb2cgPSBjdHgubG9nZ2VyLmZvcih0aGlzLmluY3JlbWVudCk7XG4gICAgY29uc3QgeyB0eXBlLCBpbmNyZW1lbnRCeSwgbmFtZSB9ID0gdGhpcy5vcHRpb25zO1xuICAgIGlmICghbmFtZSkgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJTZXF1ZW5jZSBuYW1lIGlzIHJlcXVpcmVkXCIpO1xuICAgIGxvZy5pbmZvKGBPYnRhaW5pbmcgc2VxdWVuY2UgbG9jayBmb3Igc2VxdWVuY2UgJHtuYW1lfWApO1xuICAgIHJldHVybiBGYWJyaWNDb250cmFjdFNlcXVlbmNlLmxvY2suZXhlY3V0ZShhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0b0luY3JlbWVudEJ5ID0gY291bnQgfHwgaW5jcmVtZW50Qnk7XG4gICAgICBpZiAodG9JbmNyZW1lbnRCeSAlIGluY3JlbWVudEJ5ICE9PSAwKVxuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICBgVmFsdWUgdG8gaW5jcmVtZW50IGRvZXMgbm90IGNvbnNpZGVyIHRoZSBpbmNyZW1lbnRCeSBzZXR0aW5nOiAke2luY3JlbWVudEJ5fWBcbiAgICAgICAgKTtcbiAgICAgIGNvbnN0IHR5cGVOYW1lID1cbiAgICAgICAgdHlwZW9mIHR5cGUgPT09IFwiZnVuY3Rpb25cIiAmJiAodHlwZSBhcyBhbnkpPy5uYW1lXG4gICAgICAgICAgPyAodHlwZSBhcyBhbnkpLm5hbWVcbiAgICAgICAgICA6IHR5cGU7XG4gICAgICBjb25zdCBjdXJyZW50VmFsdWUgPSBhd2FpdCB0aGlzLmN1cnJlbnQoY3R4KTtcblxuICAgICAgYXN5bmMgZnVuY3Rpb24gcmV0dXJuQW5kQ2FjaGUoXG4gICAgICAgIHJlczogU2VxdWVuY2VNb2RlbCB8IFByb21pc2U8U2VxdWVuY2VNb2RlbD5cbiAgICAgICkge1xuICAgICAgICBpZiAocmVzIGluc3RhbmNlb2YgUHJvbWlzZSkgcmVzID0gYXdhaXQgcmVzO1xuICAgICAgICBjdHgubG9nZ2VyXG4gICAgICAgICAgLmZvcihyZXR1cm5BbmRDYWNoZSlcbiAgICAgICAgICAuaW5mbyhgU3RvcmluZyBuZXcgJHtuYW1lfSBzZXEgdmFsdWUgaW4gY2FjaGU6ICR7cmVzLmN1cnJlbnR9YCk7XG4gICAgICAgIGN0eC5jYWNoZS5wdXQobmFtZSBhcyBzdHJpbmcsIHJlcy5jdXJyZW50KTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgIH1cblxuICAgICAgY29uc3QgcGVyZm9ybVVwc2VydCA9IGFzeW5jIChcbiAgICAgICAgbmV4dDogc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50XG4gICAgICApOiBQcm9taXNlPFNlcXVlbmNlTW9kZWw+ID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gYXdhaXQgcmV0dXJuQW5kQ2FjaGUoXG4gICAgICAgICAgICB0aGlzLnJlcG8udXBkYXRlKFxuICAgICAgICAgICAgICBuZXcgU2VxdWVuY2VNb2RlbCh7IGlkOiBuYW1lLCBjdXJyZW50OiBuZXh0IH0pLFxuICAgICAgICAgICAgICBjdHhcbiAgICAgICAgICAgIClcbiAgICAgICAgICApO1xuICAgICAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIE5vdEZvdW5kRXJyb3IpIHtcbiAgICAgICAgICAgIGxvZy5kZWJ1ZyhcbiAgICAgICAgICAgICAgYFNlcXVlbmNlIGNyZWF0ZSAke25hbWV9IGN1cnJlbnQ9JHtjdXJyZW50VmFsdWUgYXMgYW55fSBuZXh0PSR7bmV4dCBhcyBhbnl9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiByZXR1cm5BbmRDYWNoZShcbiAgICAgICAgICAgICAgdGhpcy5yZXBvLmNyZWF0ZShcbiAgICAgICAgICAgICAgICBuZXcgU2VxdWVuY2VNb2RlbCh7IGlkOiBuYW1lLCBjdXJyZW50OiBuZXh0IH0pLFxuICAgICAgICAgICAgICAgIGN0eFxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBjb25zdCBpbmNyZW1lbnRTZXJpYWwgPSAoXG4gICAgICAgIGJhc2U6IHN0cmluZyB8IG51bWJlciB8IGJpZ2ludFxuICAgICAgKTogc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50ID0+IHtcbiAgICAgICAgc3dpdGNoICh0eXBlTmFtZSkge1xuICAgICAgICAgIGNhc2UgTnVtYmVyLm5hbWU6XG4gICAgICAgICAgICByZXR1cm4gKHRoaXMucGFyc2UoYmFzZSkgYXMgbnVtYmVyKSArIHRvSW5jcmVtZW50Qnk7XG4gICAgICAgICAgY2FzZSBCaWdJbnQubmFtZTpcbiAgICAgICAgICAgIHJldHVybiAodGhpcy5wYXJzZShiYXNlKSBhcyBiaWdpbnQpICsgQmlnSW50KHRvSW5jcmVtZW50QnkpO1xuICAgICAgICAgIGNhc2UgU3RyaW5nLm5hbWU6XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wYXJzZShiYXNlKTtcbiAgICAgICAgICBjYXNlIFwic2VyaWFsXCI6XG4gICAgICAgICAgICByZXR1cm4gU2VyaWFsLmluc3RhbmNlLmdlbmVyYXRlKGJhc2UgYXMgc3RyaW5nKTtcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJTaG91bGQgbmV2ZXIgaGFwcGVuXCIpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBpZiAodHlwZU5hbWUgPT09IFwidXVpZFwiKSB7XG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgY29uc3QgbmV4dCA9IFVVSUQuaW5zdGFuY2UuZ2VuZXJhdGUoY3VycmVudFZhbHVlIGFzIHN0cmluZyk7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHBlcmZvcm1VcHNlcnQobmV4dCk7XG4gICAgICAgICAgICBsb2cuZGVidWcoXG4gICAgICAgICAgICAgIGBTZXF1ZW5jZSB1dWlkIGluY3JlbWVudCAke25hbWV9IGN1cnJlbnQ9JHtjdXJyZW50VmFsdWUgYXMgYW55fSBuZXh0PSR7bmV4dCBhcyBhbnl9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQuY3VycmVudCBhcyBzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQ7XG4gICAgICAgICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBDb25mbGljdEVycm9yKSBjb250aW51ZTtcbiAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG5leHQgPSBpbmNyZW1lbnRTZXJpYWwoY3VycmVudFZhbHVlKTtcbiAgICAgIGNvbnN0IHNlcSA9IGF3YWl0IHBlcmZvcm1VcHNlcnQobmV4dCk7XG4gICAgICBsb2cuZGVidWcoXG4gICAgICAgIGBTZXF1ZW5jZS5pbmNyZW1lbnQgJHtuYW1lfSBjdXJyZW50PSR7Y3VycmVudFZhbHVlIGFzIGFueX0gbmV4dD0ke25leHQgYXMgYW55fWBcbiAgICAgICk7XG4gICAgICByZXR1cm4gc2VxLmN1cnJlbnQgYXMgc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50O1xuICAgIH0sIG5hbWUpO1xuICB9XG59XG4iLCIvKipcbiAqIEBkZXNjcmlwdGlvbiBLZXlzIHVzZWQgdG8gbWFyayBGYWJyaWMtc3BlY2lmaWMgbW9kZWwgbWV0YWRhdGFcbiAqIEBzdW1tYXJ5IEVudW1lcmF0aW9uIG9mIHNwZWNpYWwga2V5cyB1c2VkIGJ5IHRoZSBzZXJpYWxpemF0aW9uIGxheWVyIHRvIHBlcnNpc3QgRmFicmljLXJlbGF0ZWQgZmxhZ3Mgb24gbW9kZWxzXG4gKiBAZW51bSB7c3RyaW5nfVxuICogQHJlYWRvbmx5XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1mYWJyaWMuc2hhcmVkXG4gKi9cbmV4cG9ydCBlbnVtIEZhYnJpY01vZGVsS2V5cyB7XG4gIC8qKiBQcml2YXRlIGRhdGEgbWFya2VyIHVzZWQgdG8gdGFnIHByb3BlcnRpZXMgb3IgbW9kZWxzIGZvciBGYWJyaWMgcHJpdmF0ZSBjb2xsZWN0aW9ucyAqL1xuICBQUklWQVRFID0gXCJwcml2YXRlXCIsXG4gIFNIQVJFRCA9IFwic2hhcmVkXCIsXG4gIC8qKiBOYW1lc3BhY2UgcHJlZml4IHVzZWQgZm9yIEZhYnJpYy1zcGVjaWZpYyBtZXRhZGF0YSBrZXlzICovXG4gIEZBQlJJQyA9IFwiZmFicmljLlwiLFxuICBPV05FREJZID0gXCJvd25lZC1ieVwiLFxuICBUUkFOU0FDVElPTl9JRCA9IFwidHJhbnNhY3Rpb24taWRcIixcbn1cbi8qKlxuICogQGRlc2NyaXB0aW9uIFN1cHBvcnRlZCBpZGVudGl0eSB0eXBlcyBmb3IgRmFicmljIGNyZWRlbnRpYWxzXG4gKiBAc3VtbWFyeSBFbnVtZXJhdGlvbiBvZiBpZGVudGl0eSBmb3JtYXRzIHJlY29nbml6ZWQgYnkgdGhpcyBsaWJyYXJ5XG4gKiBAZW51bSB7c3RyaW5nfVxuICogQHJlYWRvbmx5XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1mYWJyaWMuc2hhcmVkXG4gKi9cbmV4cG9ydCBlbnVtIElkZW50aXR5VHlwZSB7XG4gIC8qKiBTdGFuZGFyZCBYLjUwOSBpZGVudGl0eSBmb3JtYXQgdXNlZCBieSBIeXBlcmxlZGdlciBGYWJyaWMgKi9cbiAgWDUwOSA9IFwiWC41MDlcIixcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU3RyaW5nIGlkZW50aWZpZXIgZm9yIHRoZSBGYWJyaWMgYWRhcHRlciBmbGF2b3VyXG4gKiBAc3VtbWFyeSBVc2VkIHRvIHRhZyBhZGFwdGVycy9yZXBvc2l0b3JpZXMgdGhhdCBvcGVyYXRlIGFnYWluc3QgSHlwZXJsZWRnZXIgRmFicmljXG4gKiBAY29uc3QgRmFicmljRmxhdm91clxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLnNoYXJlZFxuICovXG5leHBvcnQgY29uc3QgRmFicmljRmxhdm91ciA9IFwiaGxmLWZhYnJpY1wiO1xuIiwiaW1wb3J0IHtcbiAgSlNPTlNlcmlhbGl6ZXIsXG4gIE1vZGVsLFxuICBNb2RlbEtleXMsXG59IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yLCBNZXRhZGF0YSB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdGlvblwiO1xuXG5leHBvcnQgY2xhc3MgU2ltcGxlRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXI8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbj4gZXh0ZW5kcyBKU09OU2VyaWFsaXplcjxNPiB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG4gIH1cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIG92ZXJyaWRlIGRlc2VyaWFsaXplKHN0cjogc3RyaW5nLCB0YWJsZU5hbWU/OiBzdHJpbmcpOiBNIHtcbiAgICBjb25zdCBkZXNlcmlhbGl6YXRpb24gPSBKU09OLnBhcnNlKHN0cik7XG4gICAgLy8gY29uc3QgY2xhc3NOYW1lID0gdGFibGVOYW1lO1xuICAgIC8vIGlmICghY2xhc3NOYW1lKVxuICAgIC8vICAgdGhyb3cgbmV3IEVycm9yKFwiQ291bGQgbm90IGZpbmQgY2xhc3MgcmVmZXJlbmNlIGluIHNlcmlhbGl6ZWQgbW9kZWxcIik7XG5cbiAgICAvLyAvLyB0aGlzIHdpbGwgcmV0dXJuIHVuZGVmaW5lZCB2YWx1ZXNcbiAgICAvLyBjb25zdCBtb2RlbDogTSA9IE1vZGVsLmJ1aWxkKGRlc2VyaWFsaXphdGlvbiwgY2xhc3NOYW1lKSBhcyB1bmtub3duIGFzIE07XG5cbiAgICAvLyAvLyBQb3B1bGF0ZSBNb2RlbFxuICAgIC8vIGNvbnN0IHByb2Nlc3NlZERlc2VhbGl6YXRpb24gPSBPYmplY3Qua2V5cyhtb2RlbCkucmVkdWNlKFxuICAgIC8vICAgKGFjY3VtOiBNLCBrZXkpID0+IHtcbiAgICAvLyAgICAgKGFjY3VtIGFzIFJlY29yZDxzdHJpbmcsIGFueT4pW2tleV0gPVxuICAgIC8vICAgICAgIGRlc2VyaWFsaXphdGlvbltSZXBvc2l0b3J5LmNvbHVtbihhY2N1bSwga2V5KV07XG4gICAgLy8gICAgIHJldHVybiBhY2N1bTtcbiAgICAvLyAgIH0sXG4gICAgLy8gICBtb2RlbFxuICAgIC8vICk7XG5cbiAgICAvLyBjb25zdCByZXN1bHQgPSBNb2RlbC5idWlsZChcbiAgICAvLyAgIHByb2Nlc3NlZERlc2VhbGl6YXRpb24sXG4gICAgLy8gICBjbGFzc05hbWVcbiAgICAvLyApIGFzIHVua25vd24gYXMgTTtcblxuICAgIC8vIHJldHVybiByZXN1bHQ7XG4gICAgcmV0dXJuIGRlc2VyaWFsaXphdGlvbjtcbiAgfVxuXG4gIG92ZXJyaWRlIHNlcmlhbGl6ZShtb2RlbDogTSwgcHV0QW5jaG9yID0gdHJ1ZSk6IHN0cmluZyB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgICBjb25zdCBzdHJpbmdpZnkgPSByZXF1aXJlKFwianNvbi1zdHJpbmdpZnktZGV0ZXJtaW5pc3RpY1wiKTtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0c1xuICAgIGNvbnN0IHNvcnRLZXlzUmVjdXJzaXZlID0gcmVxdWlyZShcInNvcnQta2V5cy1yZWN1cnNpdmVcIik7XG4gICAgY29uc3QgcHJlU2VyaWFsaXphdGlvbiA9IHRoaXMucHJlU2VyaWFsaXplKG1vZGVsLCBwdXRBbmNob3IpO1xuICAgIHJldHVybiBzdHJpbmdpZnkoc29ydEtleXNSZWN1cnNpdmUocHJlU2VyaWFsaXphdGlvbikpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIHByZVNlcmlhbGl6ZShtb2RlbDogTSwgcHV0QW5jaG9yOiBib29sZWFuID0gdHJ1ZSkge1xuICAgIC8vIFRPRE86IG5lc3RlZCBwcmVzZXJpYWxpemF0aW9uIChzbyBpbmNyZWFzZSBwZXJmb3JtYW5jZSB3aGVuIGRlc2VyaWFsaXppbmcpXG4gICAgLy8gVE9ETzogVmVyaWZ5IHdoeSB0aGVyZSBpcyBubyBtZXRhZGF0YVxuICAgIGNvbnN0IHRvU2VyaWFsaXplOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gT2JqZWN0LmFzc2lnbih7fSwgbW9kZWwpO1xuICAgIGxldCBtZXRhZGF0YTtcbiAgICB0cnkge1xuICAgICAgbWV0YWRhdGEgPSBNZXRhZGF0YS5tb2RlbE5hbWUobW9kZWwuY29uc3RydWN0b3IgYXMgQ29uc3RydWN0b3IpO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICBtZXRhZGF0YSA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgaWYgKHB1dEFuY2hvcilcbiAgICAgIHRvU2VyaWFsaXplW01vZGVsS2V5cy5BTkNIT1JdID0gbWV0YWRhdGEgfHwgbW9kZWwuY29uc3RydWN0b3IubmFtZTtcblxuICAgIGZ1bmN0aW9uIHByZVNlcmlhbGl6ZShcbiAgICAgIHRoaXM6IFNpbXBsZURldGVybWluaXN0aWNTZXJpYWxpemVyPGFueT4sXG4gICAgICBvYmo6IGFueVxuICAgICk6IGFueSB7XG4gICAgICBpZiAodHlwZW9mIG9iaiAhPT0gXCJvYmplY3RcIikgcmV0dXJuIG9iajtcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KG9iaikpIHJldHVybiBvYmoubWFwKHByZVNlcmlhbGl6ZSk7XG4gICAgICByZXR1cm4gdGhpcy5wcmVTZXJpYWxpemUob2JqKTtcbiAgICB9XG4gICAgTW9kZWwucmVsYXRpb25zKG1vZGVsKS5mb3JFYWNoKChyKSA9PiB7XG4gICAgICB0b1NlcmlhbGl6ZVtyXSA9IHByZVNlcmlhbGl6ZS5jYWxsKHRoaXMsIHRvU2VyaWFsaXplW3JdKTtcbiAgICB9KTtcbiAgICByZXR1cm4gdG9TZXJpYWxpemU7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIExvZ2dlckZhY3RvcnksXG4gIExvZ2dpbmcsXG4gIExvZ2dlcixcbiAgTG9nTGV2ZWwsXG4gIE1pbmlMb2dnZXIsXG4gIE51bWVyaWNMb2dMZXZlbHMsXG4gIFN0cmluZ0xpa2UsXG59IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuaW1wb3J0IHsgTG9nZ2luZ0NvbmZpZyB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuaW1wb3J0IHsgQ29udGV4dCBhcyBDdHggfSBmcm9tIFwiZmFicmljLWNvbnRyYWN0LWFwaVwiO1xuaW1wb3J0IHsgSW50ZXJuYWxFcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBMb2dnZXIgaW1wbGVtZW50YXRpb24gZm9yIEZhYnJpYyBjaGFpbmNvZGUgY29udHJhY3RzXG4gKiBAc3VtbWFyeSBBZGFwdHMgdGhlIHN0YW5kYXJkIGxvZ2dpbmcgaW50ZXJmYWNlIHRvIHdvcmsgd2l0aCBGYWJyaWMncyBjaGFpbmNvZGUgY29udGV4dFxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBjb250ZXh0IC0gVGhlIGxvZ2dpbmcgY29udGV4dCBuYW1lXG4gKiBAcGFyYW0ge1BhcnRpYWw8TG9nZ2luZ0NvbmZpZz4gfCB1bmRlZmluZWR9IGNvbmYgLSBPcHRpb25hbCBsb2dnaW5nIGNvbmZpZ3VyYXRpb25cbiAqIEBwYXJhbSB7Q3R4fSBjdHggLSBUaGUgRmFicmljIGNoYWluY29kZSBjb250ZXh0XG4gKlxuICogQGNsYXNzIENvbnRyYWN0TG9nZ2VyXG4gKiBAZXh0ZW5kcyB7TWluaUxvZ2dlcn1cbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBJbiBhIEZhYnJpYyBjaGFpbmNvZGUgY29udHJhY3RcbiAqIGltcG9ydCB7IENvbnRyYWN0TG9nZ2VyIH0gZnJvbSAnQGRlY2FmLXRzL2Zvci1mYWJyaWMnO1xuICpcbiAqIGV4cG9ydCBjbGFzcyBNeUNvbnRyYWN0IGV4dGVuZHMgQ29udHJhY3Qge1xuICogICBAVHJhbnNhY3Rpb24oKVxuICogICBhc3luYyBteUZ1bmN0aW9uKGN0eDogQ29udGV4dCk6IFByb21pc2U8dm9pZD4ge1xuICogICAgIGNvbnN0IGxvZ2dlciA9IG5ldyBDb250cmFjdExvZ2dlcignTXlDb250cmFjdCcsIHsgbGV2ZWw6ICdpbmZvJyB9LCBjdHgpO1xuICpcbiAqICAgICBsb2dnZXIuaW5mbygnUHJvY2Vzc2luZyB0cmFuc2FjdGlvbicpO1xuICogICAgIGxvZ2dlci5kZWJ1ZygnVHJhbnNhY3Rpb24gZGV0YWlsczonLCB7IC4uLiB9KTtcbiAqXG4gKiAgICAgLy8gRG8gc29tZXRoaW5nXG4gKlxuICogICAgIGxvZ2dlci5pbmZvKCdUcmFuc2FjdGlvbiBjb21wbGV0ZScpO1xuICogICB9XG4gKiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNsYXNzIENvbnRyYWN0TG9nZ2VyIGV4dGVuZHMgTWluaUxvZ2dlciB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHVuZGVybHlpbmcgRmFicmljIGxvZ2dlciBpbnN0YW5jZVxuICAgKi9cbiAgcHJvdGVjdGVkIGxvZ2dlciE6IExvZ2dlcjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBjb250ZXh0OiBzdHJpbmcsXG4gICAgY29uZjogUGFydGlhbDxMb2dnaW5nQ29uZmlnPiB8IHVuZGVmaW5lZCxcbiAgICBjdHg/OiBDdHhcbiAgKSB7XG4gICAgc3VwZXIoY29udGV4dCwgY29uZik7XG5cbiAgICBpZiAoIWN0eCkge1xuICAgICAgdGhpcy5sb2dnZXIgPSBuZXcgTWluaUxvZ2dlcihjb250ZXh0LCBjb25mKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5sb2dnZXIgPSBjdHgubG9nZ2luZy5nZXRMb2dnZXIoY29udGV4dCkgYXMgdW5rbm93biBhcyBMb2dnZXI7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMb2dzIGEgbWVzc2FnZSBhdCB0aGUgc3BlY2lmaWVkIGxldmVsXG4gICAqIEBzdW1tYXJ5IE92ZXJyaWRlcyB0aGUgYmFzZSBsb2cgbWV0aG9kIHRvIHVzZSB0aGUgRmFicmljIGNvbnRleHQncyBsb2dnZXJcbiAgICogQHBhcmFtIHtMb2dMZXZlbH0gbGV2ZWwgLSBUaGUgbG9nIGxldmVsXG4gICAqIEBwYXJhbSB7U3RyaW5nTGlrZSB8IEVycm9yfSBtc2cgLSBUaGUgbWVzc2FnZSB0byBsb2dcbiAgICogQHBhcmFtIHtFcnJvcn0gW3N0YWNrXSAtIE9wdGlvbmFsIHN0YWNrIHRyYWNlIGZvciBlcnJvcnNcbiAgICogQHJldHVybiB7dm9pZH1cbiAgICovXG4gIHByb3RlY3RlZCBvdmVycmlkZSBsb2coXG4gICAgbGV2ZWw6IExvZ0xldmVsLFxuICAgIG1zZzogU3RyaW5nTGlrZSB8IEVycm9yLFxuICAgIHN0YWNrPzogRXJyb3JcbiAgKSB7XG4gICAgaWYgKFxuICAgICAgTnVtZXJpY0xvZ0xldmVsc1t0aGlzLmNvbmZpZyhcImxldmVsXCIpIGFzIExvZ0xldmVsXSA8XG4gICAgICBOdW1lcmljTG9nTGV2ZWxzW2xldmVsXVxuICAgIClcbiAgICAgIHJldHVybjtcblxuICAgIGxldCBtZXRob2Q7XG4gICAgc3dpdGNoIChsZXZlbCkge1xuICAgICAgY2FzZSBMb2dMZXZlbC5pbmZvOlxuICAgICAgICBtZXRob2QgPSB0aGlzLmxvZ2dlci5pbmZvO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgTG9nTGV2ZWwudmVyYm9zZTpcbiAgICAgICAgbWV0aG9kID0gdGhpcy5sb2dnZXIudmVyYm9zZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIExvZ0xldmVsLmRlYnVnOlxuICAgICAgICBtZXRob2QgPSB0aGlzLmxvZ2dlci5kZWJ1ZztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIExvZ0xldmVsLmVycm9yOlxuICAgICAgICBtZXRob2QgPSB0aGlzLmxvZ2dlci5lcnJvcjtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIExvZ0xldmVsLndhcm46XG4gICAgICAgIG1ldGhvZCA9IHRoaXMubG9nZ2VyLndhcm47XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBMb2dMZXZlbC5zaWxseTpcbiAgICAgICAgbWV0aG9kID0gdGhpcy5sb2dnZXIuc2lsbHk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJJbnZhbGlkIGxvZyBsZXZlbFwiKTtcbiAgICB9XG4gICAgbWV0aG9kLmNhbGwodGhpcy5sb2dnZXIsIHRoaXMuY3JlYXRlTG9nKGxldmVsLCBtc2csIHN0YWNrKSk7XG4gIH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRmFjdG9yeSBmdW5jdGlvbiBmb3IgY3JlYXRpbmcgQ29udHJhY3RMb2dnZXIgaW5zdGFuY2VzXG4gKiBAc3VtbWFyeSBDcmVhdGVzIGEgbmV3IENvbnRyYWN0TG9nZ2VyIHdpdGggdGhlIGdpdmVuIGNvbnRleHQsIGNvbmZpZywgYW5kIEZhYnJpYyBjb250ZXh0XG4gKiBAcGFyYW0ge3N0cmluZ30gb2JqZWN0IC0gVGhlIGxvZ2dpbmcgY29udGV4dCBuYW1lXG4gKiBAcGFyYW0ge1BhcnRpYWw8TG9nZ2luZ0NvbmZpZz4gfCB1bmRlZmluZWR9IGNvbmZpZyAtIE9wdGlvbmFsIGxvZ2dpbmcgY29uZmlndXJhdGlvblxuICogQHBhcmFtIHtDdHh9IGN0eCAtIFRoZSBGYWJyaWMgY2hhaW5jb2RlIGNvbnRleHRcbiAqIEByZXR1cm4ge0NvbnRyYWN0TG9nZ2VyfSBBIG5ldyBDb250cmFjdExvZ2dlciBpbnN0YW5jZVxuICogQGZ1bmN0aW9uIGZhY3RvcnlcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZmFicmljLmNvbnRyYWN0c1xuICovXG5jb25zdCBmYWN0b3J5OiBMb2dnZXJGYWN0b3J5ID0gKFxuICBvYmplY3Q/OiBzdHJpbmcsXG4gIGNvbmZpZz86IFBhcnRpYWw8TG9nZ2luZ0NvbmZpZz4sXG4gIGN0eD86IEN0eFxuKSA9PiB7XG4gIHJldHVybiBuZXcgQ29udHJhY3RMb2dnZXIoXG4gICAgb2JqZWN0IHx8IENvbnRyYWN0TG9nZ2VyLm5hbWUsXG4gICAgY29uZmlnIHx8IHt9LFxuICAgIGN0eCBhcyBDdHhcbiAgKTtcbn07XG5cbi8vIFNldCB0aGUgZmFjdG9yeSBhcyB0aGUgZGVmYXVsdCBsb2dnZXIgZmFjdG9yeVxuTG9nZ2luZy5zZXRGYWN0b3J5KGZhY3RvcnkpO1xuIiwiaW1wb3J0IHtcbiAgTWF5YmVDb250ZXh0dWFsQXJnLFxuICBPcmRlckRpcmVjdGlvbixcbiAgUGFnaW5nRXJyb3IsXG4gIFNlcXVlbmNlLFxufSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IERCS2V5cyB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciwgTWV0YWRhdGEgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0QWRhcHRlciB9IGZyb20gXCIuL0NvbnRyYWN0QWRhcHRlclwiO1xuaW1wb3J0IHsgQ291Y2hEQlBhZ2luYXRvciwgTWFuZ29RdWVyeSB9IGZyb20gXCJAZGVjYWYtdHMvZm9yLWNvdWNoZGJcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUGFnaW5hdG9yIGZvciBDb3VjaERCIHF1ZXJ5IHJlc3VsdHNcbiAqIEBzdW1tYXJ5IEltcGxlbWVudHMgcGFnaW5hdGlvbiBmb3IgQ291Y2hEQiBxdWVyaWVzIHVzaW5nIGJvb2ttYXJrcyBmb3IgZWZmaWNpZW50IG5hdmlnYXRpb24gdGhyb3VnaCByZXN1bHQgc2V0c1xuICogQHRlbXBsYXRlIE0gLSBUaGUgbW9kZWwgdHlwZSB0aGF0IGV4dGVuZHMgTW9kZWxcbiAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHJlc3VsdCB0eXBlXG4gKiBAcGFyYW0ge0ZhYnJpY0NvPGFueSwgYW55LCBhbnk+fSBhZGFwdGVyIC0gVGhlIENvdWNoREIgYWRhcHRlclxuICogQHBhcmFtIHtNYW5nb1F1ZXJ5fSBxdWVyeSAtIFRoZSBNYW5nbyBxdWVyeSB0byBwYWdpbmF0ZVxuICogQHBhcmFtIHtudW1iZXJ9IHNpemUgLSBUaGUgcGFnZSBzaXplXG4gKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBjbGF6eiAtIFRoZSBtb2RlbCBjb25zdHJ1Y3RvclxuICogQGNsYXNzIENvdWNoREJQYWdpbmF0b3JcbiAqIEBleGFtcGxlXG4gKiAvLyBFeGFtcGxlIG9mIHVzaW5nIENvdWNoREJQYWdpbmF0b3JcbiAqIGNvbnN0IGFkYXB0ZXIgPSBuZXcgTXlDb3VjaERCQWRhcHRlcihzY29wZSk7XG4gKiBjb25zdCBxdWVyeSA9IHsgc2VsZWN0b3I6IHsgdHlwZTogXCJ1c2VyXCIgfSB9O1xuICogY29uc3QgcGFnaW5hdG9yID0gbmV3IENvdWNoREJQYWdpbmF0b3IoYWRhcHRlciwgcXVlcnksIDEwLCBVc2VyKTtcbiAqXG4gKiAvLyBHZXQgdGhlIGZpcnN0IHBhZ2VcbiAqIGNvbnN0IHBhZ2UxID0gYXdhaXQgcGFnaW5hdG9yLnBhZ2UoMSk7XG4gKlxuICogLy8gR2V0IHRoZSBuZXh0IHBhZ2VcbiAqIGNvbnN0IHBhZ2UyID0gYXdhaXQgcGFnaW5hdG9yLnBhZ2UoMik7XG4gKi9cbmV4cG9ydCBjbGFzcyBGYWJyaWNDb250cmFjdFBhZ2luYXRvcjxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBSLFxuPiBleHRlbmRzIENvdWNoREJQYWdpbmF0b3I8TSwgUj4ge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBuZXcgQ291Y2hEQlBhZ2luYXRvciBpbnN0YW5jZVxuICAgKiBAc3VtbWFyeSBJbml0aWFsaXplcyBhIHBhZ2luYXRvciBmb3IgQ291Y2hEQiBxdWVyeSByZXN1bHRzXG4gICAqIEBwYXJhbSB7Q291Y2hEQkFkYXB0ZXI8YW55LCBhbnksIGFueSwgYW55Pn0gYWRhcHRlciAtIFRoZSBDb3VjaERCIGFkYXB0ZXJcbiAgICogQHBhcmFtIHtNYW5nb1F1ZXJ5fSBxdWVyeSAtIFRoZSBNYW5nbyBxdWVyeSB0byBwYWdpbmF0ZVxuICAgKiBAcGFyYW0ge251bWJlcn0gc2l6ZSAtIFRoZSBwYWdlIHNpemVcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gY2xhenogLSBUaGUgbW9kZWwgY29uc3RydWN0b3JcbiAgICovXG4gIGNvbnN0cnVjdG9yKFxuICAgIGFkYXB0ZXI6IEZhYnJpY0NvbnRyYWN0QWRhcHRlcixcbiAgICBxdWVyeTogTWFuZ29RdWVyeSxcbiAgICBzaXplOiBudW1iZXIsXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+XG4gICkge1xuICAgIHN1cGVyKGFkYXB0ZXIsIHF1ZXJ5LCBzaXplLCBjbGF6eik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByZXBhcmVzIGEgcXVlcnkgZm9yIHBhZ2luYXRpb25cbiAgICogQHN1bW1hcnkgTW9kaWZpZXMgdGhlIHJhdyBxdWVyeSB0byBpbmNsdWRlIHBhZ2luYXRpb24gcGFyYW1ldGVyc1xuICAgKiBAcGFyYW0ge01hbmdvUXVlcnl9IHJhd1N0YXRlbWVudCAtIFRoZSBvcmlnaW5hbCBNYW5nbyBxdWVyeVxuICAgKiBAcmV0dXJuIHtNYW5nb1F1ZXJ5fSBUaGUgcHJlcGFyZWQgcXVlcnkgd2l0aCBwYWdpbmF0aW9uIHBhcmFtZXRlcnNcbiAgICovXG4gIHByb3RlY3RlZCBvdmVycmlkZSBwcmVwYXJlKHJhd1N0YXRlbWVudDogTWFuZ29RdWVyeSk6IE1hbmdvUXVlcnkge1xuICAgIGNvbnN0IHF1ZXJ5OiBNYW5nb1F1ZXJ5ID0gT2JqZWN0LmFzc2lnbih7fSwgcmF3U3RhdGVtZW50KTtcbiAgICBpZiAocXVlcnkubGltaXQpIHRoaXMubGltaXQgPSBxdWVyeS5saW1pdDtcblxuICAgIHF1ZXJ5LmxpbWl0ID0gdGhpcy5zaXplO1xuXG4gICAgcmV0dXJuIHF1ZXJ5O1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgYSBzcGVjaWZpYyBwYWdlIG9mIHJlc3VsdHNcbiAgICogQHN1bW1hcnkgRXhlY3V0ZXMgdGhlIHF1ZXJ5IHdpdGggcGFnaW5hdGlvbiBhbmQgcHJvY2Vzc2VzIHRoZSByZXN1bHRzXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbcGFnZT0xXSAtIFRoZSBwYWdlIG51bWJlciB0byByZXRyaWV2ZVxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFJbXT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIGFycmF5IG9mIHJlc3VsdHNcbiAgICogQHRocm93cyB7UGFnaW5nRXJyb3J9IElmIHRyeWluZyB0byBhY2Nlc3MgYSBwYWdlIG90aGVyIHRoYW4gdGhlIGZpcnN0IHdpdGhvdXQgYSBib29rbWFyaywgb3IgaWYgbm8gY2xhc3MgaXMgZGVmaW5lZFxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAgICogICBwYXJ0aWNpcGFudCBDb3VjaERCUGFnaW5hdG9yXG4gICAqICAgcGFydGljaXBhbnQgQWRhcHRlclxuICAgKiAgIHBhcnRpY2lwYW50IENvdWNoREJcbiAgICpcbiAgICogICBDbGllbnQtPj5Db3VjaERCUGFnaW5hdG9yOiBwYWdlKHBhZ2VOdW1iZXIpXG4gICAqICAgTm90ZSBvdmVyIENvdWNoREJQYWdpbmF0b3I6IENsb25lIHN0YXRlbWVudFxuICAgKiAgIENvdWNoREJQYWdpbmF0b3ItPj5Db3VjaERCUGFnaW5hdG9yOiB2YWxpZGF0ZVBhZ2UocGFnZSlcbiAgICpcbiAgICogICBhbHQgcGFnZSAhPT0gMVxuICAgKiAgICAgQ291Y2hEQlBhZ2luYXRvci0+PkNvdWNoREJQYWdpbmF0b3I6IENoZWNrIGJvb2ttYXJrXG4gICAqICAgICBhbHQgTm8gYm9va21hcmtcbiAgICogICAgICAgQ291Y2hEQlBhZ2luYXRvci0tPj5DbGllbnQ6IFRocm93IFBhZ2luZ0Vycm9yXG4gICAqICAgICBlbHNlIEhhcyBib29rbWFya1xuICAgKiAgICAgICBDb3VjaERCUGFnaW5hdG9yLT4+Q291Y2hEQlBhZ2luYXRvcjogQWRkIGJvb2ttYXJrIHRvIHN0YXRlbWVudFxuICAgKiAgICAgZW5kXG4gICAqICAgZW5kXG4gICAqXG4gICAqICAgQ291Y2hEQlBhZ2luYXRvci0+PkFkYXB0ZXI6IHJhdyhzdGF0ZW1lbnQsIGZhbHNlKVxuICAgKiAgIEFkYXB0ZXItPj5Db3VjaERCOiBFeGVjdXRlIHF1ZXJ5XG4gICAqICAgQ291Y2hEQi0tPj5BZGFwdGVyOiBSZXR1cm4gcmVzdWx0c1xuICAgKiAgIEFkYXB0ZXItLT4+Q291Y2hEQlBhZ2luYXRvcjogUmV0dXJuIE1hbmdvUmVzcG9uc2VcbiAgICpcbiAgICogICBOb3RlIG92ZXIgQ291Y2hEQlBhZ2luYXRvcjogUHJvY2VzcyByZXN1bHRzXG4gICAqXG4gICAqICAgYWx0IEhhcyB3YXJuaW5nXG4gICAqICAgICBDb3VjaERCUGFnaW5hdG9yLT4+Q291Y2hEQlBhZ2luYXRvcjogTG9nIHdhcm5pbmdcbiAgICogICBlbmRcbiAgICpcbiAgICogICBDb3VjaERCUGFnaW5hdG9yLT4+Q291Y2hEQlBhZ2luYXRvcjogQ2hlY2sgZm9yIGNsYXp6XG4gICAqXG4gICAqICAgYWx0IE5vIGNsYXp6XG4gICAqICAgICBDb3VjaERCUGFnaW5hdG9yLS0+PkNsaWVudDogVGhyb3cgUGFnaW5nRXJyb3JcbiAgICogICBlbHNlIEhhcyBjbGF6elxuICAgKiAgICAgQ291Y2hEQlBhZ2luYXRvci0+PkNvdWNoREJQYWdpbmF0b3I6IEZpbmQgcHJpbWFyeSBrZXlcbiAgICpcbiAgICogICAgIGFsdCBIYXMgZmllbGRzIGluIHN0YXRlbWVudFxuICAgKiAgICAgICBDb3VjaERCUGFnaW5hdG9yLT4+Q291Y2hEQlBhZ2luYXRvcjogVXNlIGRvY3MgZGlyZWN0bHlcbiAgICogICAgIGVsc2UgTm8gZmllbGRzXG4gICAqICAgICAgIENvdWNoREJQYWdpbmF0b3ItPj5Db3VjaERCUGFnaW5hdG9yOiBQcm9jZXNzIGVhY2ggZG9jdW1lbnRcbiAgICogICAgICAgbG9vcCBGb3IgZWFjaCBkb2N1bWVudFxuICAgKiAgICAgICAgIENvdWNoREJQYWdpbmF0b3ItPj5Db3VjaERCUGFnaW5hdG9yOiBFeHRyYWN0IG9yaWdpbmFsIElEXG4gICAqICAgICAgICAgQ291Y2hEQlBhZ2luYXRvci0+PkFkYXB0ZXI6IHJldmVydChkb2MsIGNsYXp6LCBwa0RlZi5pZCwgcGFyc2VkSWQpXG4gICAqICAgICAgIGVuZFxuICAgKiAgICAgZW5kXG4gICAqXG4gICAqICAgICBDb3VjaERCUGFnaW5hdG9yLT4+Q291Y2hEQlBhZ2luYXRvcjogU3RvcmUgYm9va21hcmtcbiAgICogICAgIENvdWNoREJQYWdpbmF0b3ItPj5Db3VjaERCUGFnaW5hdG9yOiBVcGRhdGUgY3VycmVudFBhZ2VcbiAgICogICAgIENvdWNoREJQYWdpbmF0b3ItLT4+Q2xpZW50OiBSZXR1cm4gcmVzdWx0c1xuICAgKiAgIGVuZFxuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgcGFnZShcbiAgICBwYWdlOiBudW1iZXIgPSAxLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxhbnk+XG4gICk6IFByb21pc2U8TVtdPiB7XG4gICAgY29uc3QgeyBjdHhBcmdzLCBjdHggfSA9IHRoaXMuYWRhcHRlcltcImxvZ0N0eFwiXShhcmdzLCB0aGlzLnBhZ2UpO1xuICAgIGlmICh0aGlzLmlzUHJlcGFyZWRTdGF0ZW1lbnQoKSkgcmV0dXJuIHRoaXMucGFnZVByZXBhcmVkKHBhZ2UsIC4uLmN0eEFyZ3MpO1xuICAgIGNvbnN0IHN0YXRlbWVudCA9IE9iamVjdC5hc3NpZ24oe30sIHRoaXMuc3RhdGVtZW50KTtcblxuICAgIGlmICghdGhpcy5fcmVjb3JkQ291bnQgfHwgIXRoaXMuX3RvdGFsUGFnZXMpIHtcbiAgICAgIHRoaXMuX3RvdGFsUGFnZXMgPSB0aGlzLl9yZWNvcmRDb3VudCA9IDA7XG4gICAgICBjb25zdCByZXN1bHRzOiBSW10gPVxuICAgICAgICAoYXdhaXQgdGhpcy5hZGFwdGVyLnJhdyhcbiAgICAgICAgICB7IC4uLnN0YXRlbWVudCwgbGltaXQ6IHVuZGVmaW5lZCB9LFxuICAgICAgICAgIHRydWUsXG4gICAgICAgICAgY3R4XG4gICAgICAgICkpIHx8IFtdO1xuICAgICAgdGhpcy5fcmVjb3JkQ291bnQgPSByZXN1bHRzLmxlbmd0aDtcbiAgICAgIGlmICh0aGlzLl9yZWNvcmRDb3VudCA+IDApIHtcbiAgICAgICAgY29uc3Qgc2l6ZSA9IHN0YXRlbWVudD8ubGltaXQgfHwgdGhpcy5zaXplO1xuICAgICAgICB0aGlzLl90b3RhbFBhZ2VzID0gTWF0aC5jZWlsKHRoaXMuX3JlY29yZENvdW50IC8gc2l6ZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy52YWxpZGF0ZVBhZ2UocGFnZSk7XG5cbiAgICBpZiAocGFnZSAhPT0gMSkge1xuICAgICAgaWYgKCF0aGlzLl9ib29rbWFyaylcbiAgICAgICAgdGhyb3cgbmV3IFBhZ2luZ0Vycm9yKFwiTm8gYm9va21hcmsuIERpZCB5b3Ugc3RhcnQgaW4gdGhlIGZpcnN0IHBhZ2U/XCIpO1xuICAgICAgc3RhdGVtZW50W1wiYm9va21hcmtcIl0gPSB0aGlzLl9ib29rbWFyayBhcyBzdHJpbmc7XG4gICAgfVxuICAgIGNvbnN0IGRvY3M6IGFueVtdID0gKGF3YWl0IHRoaXMuYWRhcHRlci5yYXcoc3RhdGVtZW50LCBmYWxzZSwgY3R4KSkgYXMgYW55O1xuXG4gICAgaWYgKCF0aGlzLmNsYXp6KSB0aHJvdyBuZXcgUGFnaW5nRXJyb3IoXCJObyBzdGF0ZW1lbnQgdGFyZ2V0IGRlZmluZWRcIik7XG4gICAgY29uc3QgaWQgPSBNb2RlbC5wayh0aGlzLmNsYXp6KTtcbiAgICBjb25zdCB0eXBlID0gTWV0YWRhdGEuZ2V0KFxuICAgICAgdGhpcy5jbGF6eixcbiAgICAgIE1ldGFkYXRhLmtleShEQktleXMuSUQsIGlkIGFzIHN0cmluZylcbiAgICApPy50eXBlO1xuICAgIGNvbnN0IHJlc3VsdHMgPVxuICAgICAgc3RhdGVtZW50LmZpZWxkcyAmJiBzdGF0ZW1lbnQuZmllbGRzLmxlbmd0aFxuICAgICAgICA/IGRvY3MgLy8gaGFzIGZpZWxkcyBtZWFucyBpdHMgbm90IGZ1bGwgbW9kZWxcbiAgICAgICAgOiBkb2NzLm1hcCgoZDogYW55KSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5hZGFwdGVyLnJldmVydChcbiAgICAgICAgICAgICAgZCxcbiAgICAgICAgICAgICAgdGhpcy5jbGF6eixcbiAgICAgICAgICAgICAgU2VxdWVuY2UucGFyc2VWYWx1ZSh0eXBlLCBkW2lkXSksXG4gICAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgY3R4XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pO1xuICAgIGNvbnN0IGRpcmVjdGlvbiA9IHN0YXRlbWVudC5zb3J0Py5bMF0gfHwgT3JkZXJEaXJlY3Rpb24uRFNDO1xuICAgIHRoaXMuX2Jvb2ttYXJrID1cbiAgICAgIHJlc3VsdHNbZGlyZWN0aW9uID09PSBPcmRlckRpcmVjdGlvbi5BU0MgPyByZXN1bHRzLmxlbmd0aCAtIDEgOiAwXVtpZF07XG4gICAgdGhpcy5fY3VycmVudFBhZ2UgPSBwYWdlO1xuICAgIHJldHVybiByZXN1bHRzO1xuICB9XG59XG4iLCJpbXBvcnQgeyBCYXNlRXJyb3IsIEludGVybmFsRXJyb3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IEF1dGhvcml6YXRpb25FcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuLy8gaW1wb3J0IHsgTUlTU0lOR19QUklWQVRFX0RBVEFfRVJST1JfTUVTU0FHRSB9IGZyb20gXCIuLi9jb250cmFjdHMvcHJpdmF0ZS1kYXRhXCI7XG4vKipcbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYW4gb3ZlcmZsb3cgZXJyb3IgaW4gYXJpdGhtZXRpYyBvcGVyYXRpb25zIGluIFNtYXJ0IENvbnRyYWN0c1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtc2cgdGhlIGVycm9yIG1lc3NhZ2VcbiAqXG4gKiBAY2xhc3MgT3ZlcmZsb3dFcnJvclxuICogQGV4dGVuZHMgSW50ZXJuYWxFcnJvclxuICpcbiAqIEBjYXRlZ29yeSBFcnJvcnNcbiAqL1xuZXhwb3J0IGNsYXNzIE92ZXJmbG93RXJyb3IgZXh0ZW5kcyBJbnRlcm5hbEVycm9yIHtcbiAgY29uc3RydWN0b3IobXNnOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKG1zZywgT3ZlcmZsb3dFcnJvci5uYW1lKTtcbiAgfVxufVxuXG4vKipcbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYSBmYWlsdXJlIGluIGJhbGFuY2UgdG8gcGVyZm9ybSBhIHRyYW5zYWN0aW9uIGluIFNtYXJ0IENvbnRyYWN0c1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtc2cgdGhlIGVycm9yIG1lc3NhZ2VcbiAqXG4gKiBAY2xhc3MgQmFsYW5jZUVycm9yXG4gKiBAZXh0ZW5kcyBJbnRlcm5hbEVycm9yXG4gKlxuICogQGNhdGVnb3J5IEVycm9yc1xuICovXG5leHBvcnQgY2xhc3MgQmFsYW5jZUVycm9yIGV4dGVuZHMgSW50ZXJuYWxFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihtc2csIEJhbGFuY2VFcnJvci5uYW1lKTtcbiAgfVxufVxuXG4vKipcbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYSBmYWlsdXJlIGluIGJhbGFuY2UgdG8gcGVyZm9ybSBhIHRyYW5zYWN0aW9uIGluIFNtYXJ0IENvbnRyYWN0c1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtc2cgdGhlIGVycm9yIG1lc3NhZ2VcbiAqXG4gKiBAY2xhc3MgQmFsYW5jZUVycm9yXG4gKiBAZXh0ZW5kcyBJbnRlcm5hbEVycm9yXG4gKlxuICogQGNhdGVnb3J5IEVycm9yc1xuICovXG5leHBvcnQgY2xhc3MgQWxsb3dhbmNlRXJyb3IgZXh0ZW5kcyBJbnRlcm5hbEVycm9yIHtcbiAgY29uc3RydWN0b3IobXNnOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKG1zZywgQWxsb3dhbmNlRXJyb3IubmFtZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBSZXByZXNlbnRzIGEgZmFpbHVyZSByZWdpc3RyYXRpbmcgbmV3IGVudGl0aWVzXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG1zZyB0aGUgZXJyb3IgbWVzc2FnZVxuICpcbiAqIEBjbGFzcyBSZWdpc3RyYXRpb25FcnJvclxuICpcbiAqIEBjYXRlZ29ydCBFcnJvcnNcbiAqL1xuZXhwb3J0IGNsYXNzIFJlZ2lzdHJhdGlvbkVycm9yIGV4dGVuZHMgQXV0aG9yaXphdGlvbkVycm9yIHtcbiAgY29uc3RydWN0b3IobXNnOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKG1zZywgUmVnaXN0cmF0aW9uRXJyb3IubmFtZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRXJyb3IgdGhyb3duIHdoZW4gYW4gdW5zdXBwb3J0ZWQgb3BlcmF0aW9uIGlzIGF0dGVtcHRlZFxuICogQHN1bW1hcnkgVGhpcyBlcnJvciBpcyB0aHJvd24gd2hlbiBhbiBvcGVyYXRpb24gaXMgcmVxdWVzdGVkIHRoYXQgaXMgbm90IHN1cHBvcnRlZCBieSB0aGUgY3VycmVudFxuICogcGVyc2lzdGVuY2UgYWRhcHRlciBvciBjb25maWd1cmF0aW9uLiBJdCBleHRlbmRzIHRoZSBCYXNlRXJyb3IgY2xhc3MgYW5kIHNldHMgYSA1MDAgc3RhdHVzIGNvZGUuXG4gKiBAcGFyYW0ge3N0cmluZ3xFcnJvcn0gbXNnIC0gVGhlIGVycm9yIG1lc3NhZ2Ugb3IgYW4gRXJyb3Igb2JqZWN0IHRvIHdyYXBcbiAqIEBjbGFzcyBVbnN1cHBvcnRlZEVycm9yXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gVGhyb3dpbmcgYW4gVW5zdXBwb3J0ZWRFcnJvclxuICogaWYgKCFhZGFwdGVyLnN1cHBvcnRzVHJhbnNhY3Rpb25zKCkpIHtcbiAqICAgdGhyb3cgbmV3IFVuc3VwcG9ydGVkRXJyb3IoJ1RyYW5zYWN0aW9ucyBhcmUgbm90IHN1cHBvcnRlZCBieSB0aGlzIGFkYXB0ZXInKTtcbiAqIH1cbiAqXG4gKiAvLyBDYXRjaGluZyBhbiBVbnN1cHBvcnRlZEVycm9yXG4gKiB0cnkge1xuICogICBhd2FpdCBhZGFwdGVyLmJlZ2luVHJhbnNhY3Rpb24oKTtcbiAqIH0gY2F0Y2ggKGVycm9yKSB7XG4gKiAgIGlmIChlcnJvciBpbnN0YW5jZW9mIFVuc3VwcG9ydGVkRXJyb3IpIHtcbiAqICAgICBjb25zb2xlLmVycm9yKCdPcGVyYXRpb24gbm90IHN1cHBvcnRlZDonLCBlcnJvci5tZXNzYWdlKTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKlxuICogQGNhdGVnb3J5IEVycm9yc1xuICovXG5leHBvcnQgY2xhc3MgTWlzc2luZ0NvbnRleHRFcnJvciBleHRlbmRzIEludGVybmFsRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIobXNnLCBNaXNzaW5nQ29udGV4dEVycm9yLm5hbWUsIDUwMCk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFVuYXV0aG9yaXplZFByaXZhdGVEYXRhQWNjZXNzIGV4dGVuZHMgQmFzZUVycm9yIHtcbiAgY29uc3RydWN0b3IobXNnOiBzdHJpbmcgfCBFcnJvciA9IFwiTUlTU0lOR19QUklWQVRFX0RBVEFfRVJST1JfTUVTU0FHRVwiKSB7XG4gICAgc3VwZXIoVW5hdXRob3JpemVkUHJpdmF0ZURhdGFBY2Nlc3MubmFtZSwgbXNnLCA0MDMpO1xuICB9XG59XG5cbi8qKlxuICogUmVwcmVzZW50cyBhbiBlcnJvciB0aGF0IG9jY3VycyB3aGVuIGEgcmVxdWlyZWQgaW5pdGlhbGl6YXRpb24gc3RlcCBpcyBub3QgcGVyZm9ybWVkLlxuICpcbiAqIEBjbGFzcyBOb3RJbml0aWFsaXplZEVycm9yXG4gKiBAZXh0ZW5kcyBCYXNlRXJyb3JcbiAqXG4gKiBAY2F0ZWdvcnkgRXJyb3JzXG4gKlxuICogQHBhcmFtIHtzdHJpbmcgfCBFcnJvcn0gbXNnIC0gVGhlIGVycm9yIG1lc3NhZ2Ugb3IgYW4gRXJyb3Igb2JqZWN0IHRvIHdyYXAuXG4gKlxuICogQHRocm93cyB7Tm90SW5pdGlhbGl6ZWRFcnJvcn0gLSBUaHJvd3MgYW4gZXJyb3Igd2hlbiBhIHJlcXVpcmVkIGluaXRpYWxpemF0aW9uIHN0ZXAgaXMgbm90IHBlcmZvcm1lZC5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gSW5pdGlhbGl6ZSB0aGUgYXBwbGljYXRpb25cbiAqIGlmICghaXNJbml0aWFsaXplZCkge1xuICogICB0aHJvdyBuZXcgTm90SW5pdGlhbGl6ZWRFcnJvcignQXBwbGljYXRpb24gaXMgbm90IGluaXRpYWxpemVkJyk7XG4gKiB9XG4gKlxuICogLy8gQ2F0Y2hpbmcgYW4gTm90SW5pdGlhbGl6ZWRFcnJvclxuICogdHJ5IHtcbiAqICAgLy8gUGVyZm9ybSBvcGVyYXRpb25zIHRoYXQgcmVxdWlyZSBpbml0aWFsaXphdGlvblxuICogfSBjYXRjaCAoZXJyb3IpIHtcbiAqICAgaWYgKGVycm9yIGluc3RhbmNlb2YgTm90SW5pdGlhbGl6ZWRFcnJvcikge1xuICogICAgIGNvbnNvbGUuZXJyb3IoJ0luaXRpYWxpemF0aW9uIGVycm9yOicsIGVycm9yLm1lc3NhZ2UpO1xuICogICB9XG4gKiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNsYXNzIE5vdEluaXRpYWxpemVkRXJyb3IgZXh0ZW5kcyBCYXNlRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIoTm90SW5pdGlhbGl6ZWRFcnJvci5uYW1lLCBtc2csIDQwOSk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIE1pc3NpbmdQS0NTUzExTGliIGV4dGVuZHMgSW50ZXJuYWxFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihtc2csIE1pc3NpbmdQS0NTUzExTGliLm5hbWUsIDUwMCk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEVuZG9yc2VtZW50RXJyb3IgZXh0ZW5kcyBJbnRlcm5hbEVycm9yIHtcbiAgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihtZXNzYWdlLCBFbmRvcnNlbWVudEVycm9yLm5hbWUsIDUwMCk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIE12Y2NSZWFkQ29uZmxpY3RFcnJvciBleHRlbmRzIEludGVybmFsRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKG1lc3NhZ2UsIE12Y2NSZWFkQ29uZmxpY3RFcnJvci5uYW1lLCA1MDApO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBQaGFudG9tUmVhZENvbmZsaWN0RXJyb3IgZXh0ZW5kcyBJbnRlcm5hbEVycm9yIHtcbiAgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihtZXNzYWdlLCBQaGFudG9tUmVhZENvbmZsaWN0RXJyb3IubmFtZSwgNTAwKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgRW5kb3JzZW1lbnRQb2xpY3lFcnJvciBleHRlbmRzIEludGVybmFsRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKG1lc3NhZ2UsIEVuZG9yc2VtZW50UG9saWN5RXJyb3IubmFtZSwgNTAwKTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgQ291Y2hEQkFkYXB0ZXIsIENvdWNoREJLZXlzLCBNYW5nb1F1ZXJ5IH0gZnJvbSBcIkBkZWNhZi10cy9mb3ItY291Y2hkYlwiO1xuaW1wb3J0IHsgTW9kZWwsIFZhbGlkYXRpb25LZXlzIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgRmFicmljQ29udHJhY3RGbGFncyB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdENvbnRleHQgfSBmcm9tIFwiLi9Db250cmFjdENvbnRleHRcIjtcbmltcG9ydCB7XG4gIEJhZFJlcXVlc3RFcnJvcixcbiAgQmFzZUVycm9yLFxuICBDb25mbGljdEVycm9yLFxuICBJbnRlcm5hbEVycm9yLFxuICBOb3RGb3VuZEVycm9yLFxuICBvbkNyZWF0ZSxcbiAgb25DcmVhdGVVcGRhdGUsXG4gIE9wZXJhdGlvbktleXMsXG4gIFByaW1hcnlLZXlUeXBlLFxuICBTZXJpYWxpemF0aW9uRXJyb3IsXG59IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHtcbiAgQ29udGV4dCBhcyBDdHgsXG4gIE9iamVjdCBhcyBGYWJyaWNPYmplY3QsXG4gIFByb3BlcnR5LFxuICBQcm9wZXJ0eSBhcyBGYWJyaWNQcm9wZXJ0eSxcbn0gZnJvbSBcImZhYnJpYy1jb250cmFjdC1hcGlcIjtcbmltcG9ydCB7IExvZ2dlciB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuaW1wb3J0IHtcbiAgUGVyc2lzdGVuY2VLZXlzLFxuICBSZWxhdGlvbnNNZXRhZGF0YSxcbiAgU2VxdWVuY2UsXG4gIFNlcXVlbmNlT3B0aW9ucyxcbiAgVW5zdXBwb3J0ZWRFcnJvcixcbiAgQWRhcHRlcixcbiAgUHJlcGFyZWRNb2RlbCxcbiAgUmVwb3NpdG9yeSxcbiAgUXVlcnlFcnJvcixcbiAgUGFnaW5nRXJyb3IsXG4gIE1pZ3JhdGlvbkVycm9yLFxuICBPYnNlcnZlckVycm9yLFxuICBBdXRob3JpemF0aW9uRXJyb3IsXG4gIEZvcmJpZGRlbkVycm9yLFxuICBDb25uZWN0aW9uRXJyb3IsXG4gIENvbnRleHR1YWxpemVkQXJncyxcbiAgTG9nZ2VyT2YsXG4gIENvbnRleHQsXG4gIFJhd1Jlc3VsdCxcbiAgUGFnaW5hdG9yLFxuICBDb250ZXh0dWFsQXJncyxcbiAgTWF5YmVDb250ZXh0dWFsQXJnLFxufSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeSB9IGZyb20gXCIuL0ZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeVwiO1xuaW1wb3J0IHtcbiAgQ2hhaW5jb2RlU3R1YixcbiAgQ2xpZW50SWRlbnRpdHksXG4gIEl0ZXJhdG9ycyxcbiAgU3RhdGVRdWVyeVJlc3BvbnNlLFxufSBmcm9tIFwiZmFicmljLXNoaW0tYXBpXCI7XG5pbXBvcnQgeyBGYWJyaWNTdGF0ZW1lbnQgfSBmcm9tIFwiLi9GYWJyaWNDb250cmFjdFN0YXRlbWVudFwiO1xuaW1wb3J0IHsgRmFicmljQ29udHJhY3RTZXF1ZW5jZSB9IGZyb20gXCIuL0ZhYnJpY0NvbnRyYWN0U2VxdWVuY2VcIjtcbmltcG9ydCB7IEZhYnJpY0ZsYXZvdXIgfSBmcm9tIFwiLi4vc2hhcmVkL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgU2ltcGxlRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXIgfSBmcm9tIFwiLi4vc2hhcmVkL1NpbXBsZURldGVybWluaXN0aWNTZXJpYWxpemVyXCI7XG5pbXBvcnQge1xuICBDb25zdHJ1Y3RvcixcbiAgRGVjb3JhdGlvbixcbiAgTWV0YWRhdGEsXG4gIHByb3BNZXRhZGF0YSxcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5pbXBvcnQgeyBDb250cmFjdExvZ2dlciB9IGZyb20gXCIuL2xvZ2dpbmdcIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0UGFnaW5hdG9yIH0gZnJvbSBcIi4vRmFicmljQ29udHJhY3RQYWdpbmF0b3JcIjtcbmltcG9ydCB7IE1pc3NpbmdDb250ZXh0RXJyb3IgfSBmcm9tIFwiLi4vc2hhcmVkL2Vycm9yc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBjcmVhdG9yIG9yIHVwZGF0ZXIgZmllbGQgaW4gYSBtb2RlbCBiYXNlZCBvbiB0aGUgdXNlciBpbiB0aGUgY29udGV4dFxuICogQHN1bW1hcnkgQ2FsbGJhY2sgZnVuY3Rpb24gdXNlZCBpbiBkZWNvcmF0b3JzIHRvIGF1dG9tYXRpY2FsbHkgc2V0IHRoZSBjcmVhdGVkX2J5IG9yIHVwZGF0ZWRfYnkgZmllbGRzXG4gKiB3aXRoIHRoZSB1c2VybmFtZSBmcm9tIHRoZSBjb250ZXh0IHdoZW4gYSBkb2N1bWVudCBpcyBjcmVhdGVkIG9yIHVwZGF0ZWRcbiAqIEB0ZW1wbGF0ZSBNIC0gVHlwZSBleHRlbmRpbmcgTW9kZWxcbiAqIEB0ZW1wbGF0ZSBSIC0gVHlwZSBleHRlbmRpbmcgTmFub1JlcG9zaXRvcnk8TT5cbiAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBleHRlbmRpbmcgUmVsYXRpb25zTWV0YWRhdGFcbiAqIEBwYXJhbSB7Un0gdGhpcyAtIFRoZSByZXBvc2l0b3J5IGluc3RhbmNlXG4gKiBAcGFyYW0ge0ZhYnJpY0NvbnRyYWN0Q29udGV4dH0gY29udGV4dCAtIFRoZSBvcGVyYXRpb24gY29udGV4dCBjb250YWluaW5nIHVzZXIgaW5mb3JtYXRpb25cbiAqIEBwYXJhbSB7Vn0gZGF0YSAtIFRoZSByZWxhdGlvbiBtZXRhZGF0YVxuICogQHBhcmFtIHtzdHJpbmd9IGtleSAtIFRoZSBwcm9wZXJ0eSBrZXkgdG8gc2V0IHdpdGggdGhlIHVzZXJuYW1lXG4gKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIGJlaW5nIGNyZWF0ZWQgb3IgdXBkYXRlZFxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgb3BlcmF0aW9uIGlzIGNvbXBsZXRlXG4gKiBAZnVuY3Rpb24gY3JlYXRlZEJ5T25GYWJyaWNDcmVhdGVVcGRhdGVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZmFicmljLmNvbnRyYWN0c1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBGIGFzIGNyZWF0ZWRCeU9uTmFub0NyZWF0ZVVwZGF0ZVxuICogICBwYXJ0aWNpcGFudCBDIGFzIENvbnRleHRcbiAqICAgcGFydGljaXBhbnQgTSBhcyBNb2RlbFxuICogICBGLT4+QzogZ2V0KFwidXNlclwiKVxuICogICBDLS0+PkY6IHVzZXIgb2JqZWN0XG4gKiAgIEYtPj5NOiBzZXQga2V5IHRvIHVzZXIubmFtZVxuICogICBOb3RlIG92ZXIgRjogSWYgbm8gdXNlciBpbiBjb250ZXh0XG4gKiAgIEYtLT4+RjogdGhyb3cgVW5zdXBwb3J0ZWRFcnJvclxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlZEJ5T25GYWJyaWNDcmVhdGVVcGRhdGU8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeTxNPixcbiAgViBleHRlbmRzIFJlbGF0aW9uc01ldGFkYXRhLFxuPihcbiAgdGhpczogUixcbiAgY29udGV4dDogQ29udGV4dDxGYWJyaWNDb250cmFjdEZsYWdzPixcbiAgZGF0YTogVixcbiAga2V5OiBrZXlvZiBNLFxuICBtb2RlbDogTVxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIHRyeSB7XG4gICAgY29uc3QgdXNlciA9IGNvbnRleHQuZ2V0KFwiaWRlbnRpdHlcIikgYXMgQ2xpZW50SWRlbnRpdHk7XG4gICAgbW9kZWxba2V5XSA9IHVzZXIuZ2V0SUQoKSBhcyBNW3R5cGVvZiBrZXldO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZEVycm9yKFxuICAgICAgXCJObyBVc2VyIGZvdW5kIGluIGNvbnRleHQuIFBsZWFzZSBwcm92aWRlIGEgdXNlciBpbiB0aGUgY29udGV4dFwiXG4gICAgKTtcbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBQcmltYXJ5IGtleSBhdXRvLWFzc2lnbm1lbnQgY2FsbGJhY2sgZm9yIEZhYnJpYyBtb2RlbHNcbiAqIEBzdW1tYXJ5IEdlbmVyYXRlcyBhbmQgYXNzaWducyBhIHByaW1hcnkga2V5IHZhbHVlIHRvIHRoZSBzcGVjaWZpZWQgbW9kZWwgcHJvcGVydHkgdXNpbmcgYSBGYWJyaWMtYmFja2VkIHNlcXVlbmNlIHdoZW4gdGhlIG1vZGVsIGlzIGNyZWF0ZWQuIElmIHRoZSBzZXF1ZW5jZSBuYW1lIGlzIG5vdCBwcm92aWRlZCBpbiBvcHRpb25zLCBpdCBpcyBkZXJpdmVkIGZyb20gdGhlIG1vZGVsIHZpYSBzZXF1ZW5jZU5hbWVGb3JNb2RlbC4gVGhlIGFzc2lnbmVkIGtleSBpcyBkZWZpbmVkIGFzIG5vbi13cml0YWJsZSBhbmQgZW51bWVyYWJsZS5cbiAqIEB0ZW1wbGF0ZSBNIC0gVHlwZSBleHRlbmRpbmcgTW9kZWwgZm9yIHRoZSB0YXJnZXQgaW5zdGFuY2VcbiAqIEB0ZW1wbGF0ZSBSIC0gVHlwZSBleHRlbmRpbmcgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5IGZvciByZXBvc2l0b3J5IGNvbnRleHRcbiAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBleHRlbmRpbmcgU2VxdWVuY2VPcHRpb25zIHRvIGNvbmZpZ3VyZSBzZXF1ZW5jZSBiZWhhdmlvclxuICogQHRlbXBsYXRlIEYgLSBUeXBlIGV4dGVuZGluZyBGYWJyaWNDb250cmFjdEZsYWdzIGZvciBjb250ZXh0dWFsIGZsYWdzXG4gKiBAcGFyYW0ge1J9IHRoaXMgLSBUaGUgcmVwb3NpdG9yeSBpbnN0YW5jZSBpbnZva2luZyB0aGUgY2FsbGJhY2tcbiAqIEBwYXJhbSB7RmFicmljQ29udHJhY3RDb250ZXh0fSBjb250ZXh0IC0gRmFicmljIGNvbnRyYWN0IGNvbnRleHQgY29udGFpbmluZyBpbnZvY2F0aW9uIG1ldGFkYXRhXG4gKiBAcGFyYW0ge1Z9IGRhdGEgLSBTZXF1ZW5jZSBvcHRpb25zIHVzZWQgdG8gY29uZmlndXJlIG9yIGxvY2F0ZSB0aGUgc2VxdWVuY2VcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgLSBUaGUgcHJpbWFyeSBrZXkgcHJvcGVydHkgbmFtZSB0byBhc3NpZ24gb24gdGhlIG1vZGVsXG4gKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIHRvIHJlY2VpdmUgdGhlIGdlbmVyYXRlZCBwcmltYXJ5IGtleVxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gUmVzb2x2ZXMgd2hlbiB0aGUga2V5IGlzIGFzc2lnbmVkIG9yIHdoZW4gbm8gYWN0aW9uIGlzIHJlcXVpcmVkXG4gKiBAZnVuY3Rpb24gcGtGYWJyaWNPbkNyZWF0ZVxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLmNvbnRyYWN0c1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBSIGFzIFJlcG9zaXRvcnlcbiAqICAgcGFydGljaXBhbnQgQyBhcyBDb250ZXh0PEY+XG4gKiAgIHBhcnRpY2lwYW50IFMgYXMgRmFicmljQ29udHJhY3REQlNlcXVlbmNlXG4gKiAgIHBhcnRpY2lwYW50IE0gYXMgTW9kZWxcbiAqICAgUi0+PlI6IGRlcml2ZSBzZXF1ZW5jZSBuYW1lIGlmIG1pc3NpbmdcbiAqICAgUi0+PlM6IGFkYXB0ZXIuU2VxdWVuY2Uob3B0aW9ucylcbiAqICAgUy0tPj5SOiBzZXF1ZW5jZSBpbnN0YW5jZVxuICogICBSLT4+UzogbmV4dChjb250ZXh0KVxuICogICBTLS0+PlI6IG5leHQgdmFsdWVcbiAqICAgUi0+Pk06IGRlZmluZSBub24td3JpdGFibGUgcHJpbWFyeSBrZXlcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHBrRmFicmljT25DcmVhdGU8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeTxNPixcbj4oXG4gIHRoaXM6IFIsXG4gIGNvbnRleHQ6IEZhYnJpY0NvbnRyYWN0Q29udGV4dCxcbiAgZGF0YTogU2VxdWVuY2VPcHRpb25zLFxuICBrZXk6IGtleW9mIE0sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKCFkYXRhLnR5cGUgfHwgbW9kZWxba2V5XSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IHNldFByaW1hcnlLZXlWYWx1ZSA9IGZ1bmN0aW9uIDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIHRhcmdldDogTSxcbiAgICBwcm9wZXJ0eUtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnRcbiAgKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgcHJvcGVydHlLZXksIHtcbiAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICB2YWx1ZTogdmFsdWUsXG4gICAgfSk7XG4gIH07XG4gIGlmICghZGF0YS5uYW1lKSBkYXRhLm5hbWUgPSBNb2RlbC5zZXF1ZW5jZU5hbWUobW9kZWwsIFwicGtcIik7XG4gIGxldCBzZXF1ZW5jZTogU2VxdWVuY2U7XG4gIHRyeSB7XG4gICAgc2VxdWVuY2UgPSAoYXdhaXQgdGhpcy5hZGFwdGVyLlNlcXVlbmNlKGRhdGEpKSBhcyBTZXF1ZW5jZTtcbiAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBgRmFpbGVkIHRvIGluc3RhbnRpYXRlIFNlcXVlbmNlICR7ZGF0YS5uYW1lfTogJHtlfWBcbiAgICApO1xuICB9XG5cbiAgY29uc3QgbmV4dCA9IGF3YWl0IHNlcXVlbmNlLm5leHQoY29udGV4dCBhcyBGYWJyaWNDb250cmFjdENvbnRleHQpO1xuICBzZXRQcmltYXJ5S2V5VmFsdWUobW9kZWwsIGtleSBhcyBzdHJpbmcsIG5leHQpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBZGFwdGVyIGZvciBIeXBlcmxlZGdlciBGYWJyaWMgY2hhaW5jb2RlIHN0YXRlIGRhdGFiYXNlIG9wZXJhdGlvbnNcbiAqIEBzdW1tYXJ5IFByb3ZpZGVzIGEgQ291Y2hEQi1saWtlIGludGVyZmFjZSBmb3IgaW50ZXJhY3Rpbmcgd2l0aCB0aGUgRmFicmljIHN0YXRlIGRhdGFiYXNlIGZyb20gd2l0aGluIGEgY2hhaW5jb2RlIGNvbnRyYWN0XG4gKiBAdGVtcGxhdGUgdm9pZCAtIE5vIGNvbmZpZ3VyYXRpb24gbmVlZGVkIGZvciBjb250cmFjdCBhZGFwdGVyXG4gKiBAdGVtcGxhdGUgRmFicmljQ29udHJhY3RGbGFncyAtIEZsYWdzIHNwZWNpZmljIHRvIEZhYnJpYyBjb250cmFjdCBvcGVyYXRpb25zXG4gKiBAdGVtcGxhdGUgRmFicmljQ29udHJhY3RDb250ZXh0IC0gQ29udGV4dCB0eXBlIGZvciBGYWJyaWMgY29udHJhY3Qgb3BlcmF0aW9uc1xuICogQGNsYXNzIEZhYnJpY0NvbnRyYWN0QWRhcHRlclxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIEluIGEgRmFicmljIGNoYWluY29kZSBjb250cmFjdCBjbGFzc1xuICogaW1wb3J0IHsgRmFicmljQ29udHJhY3RBZGFwdGVyIH0gZnJvbSAnQGRlY2FmLXRzL2Zvci1mYWJyaWMnO1xuICpcbiAqIGV4cG9ydCBjbGFzcyBNeUNvbnRyYWN0IGV4dGVuZHMgQ29udHJhY3Qge1xuICogICBwcml2YXRlIGFkYXB0ZXIgPSBuZXcgRmFicmljQ29udHJhY3RBZGFwdGVyKCk7XG4gKlxuICogICBAVHJhbnNhY3Rpb24oKVxuICogICBhc3luYyBjcmVhdGVBc3NldChjdHg6IENvbnRleHQsIGlkOiBzdHJpbmcsIGRhdGE6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICogICAgIGNvbnN0IG1vZGVsID0geyBpZCwgZGF0YSwgdGltZXN0YW1wOiBEYXRlLm5vdygpIH07XG4gKiAgICAgYXdhaXQgdGhpcy5hZGFwdGVyLmNyZWF0ZSgnYXNzZXRzJywgaWQsIG1vZGVsLCB7fSwgeyBzdHViOiBjdHguc3R1YiB9KTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENvbnRyYWN0XG4gKiAgIHBhcnRpY2lwYW50IEZhYnJpY0NvbnRyYWN0QWRhcHRlclxuICogICBwYXJ0aWNpcGFudCBTdHViXG4gKiAgIHBhcnRpY2lwYW50IFN0YXRlREJcbiAqXG4gKiAgIENvbnRyYWN0LT4+RmFicmljQ29udHJhY3RBZGFwdGVyOiBjcmVhdGUodGFibGVOYW1lLCBpZCwgbW9kZWwsIHRyYW5zaWVudCwgY3R4KVxuICogICBGYWJyaWNDb250cmFjdEFkYXB0ZXItPj5GYWJyaWNDb250cmFjdEFkYXB0ZXI6IFNlcmlhbGl6ZSBtb2RlbCB0byBKU09OXG4gKiAgIEZhYnJpY0NvbnRyYWN0QWRhcHRlci0+PlN0dWI6IHB1dFN0YXRlKGlkLCBzZXJpYWxpemVkRGF0YSlcbiAqICAgU3R1Yi0+PlN0YXRlREI6IFdyaXRlIGRhdGFcbiAqICAgU3RhdGVEQi0tPj5TdHViOiBTdWNjZXNzXG4gKiAgIFN0dWItLT4+RmFicmljQ29udHJhY3RBZGFwdGVyOiBTdWNjZXNzXG4gKiAgIEZhYnJpY0NvbnRyYWN0QWRhcHRlci0tPj5Db250cmFjdDogbW9kZWxcbiAqL1xuZXhwb3J0IGNsYXNzIEZhYnJpY0NvbnRyYWN0QWRhcHRlciBleHRlbmRzIENvdWNoREJBZGFwdGVyPFxuICBhbnksXG4gIHZvaWQsXG4gIEZhYnJpY0NvbnRyYWN0Q29udGV4dFxuPiB7XG4gIHByb3RlY3RlZCBvdmVycmlkZSBnZXRDbGllbnQoKTogdm9pZCB7XG4gICAgdGhyb3cgbmV3IFVuc3VwcG9ydGVkRXJyb3IoXCJDbGllbnQgaXMgbm90IHN1cHBvcnRlZCBpbiBGYWJyaWMgY29udHJhY3RzXCIpO1xuICB9XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGV4dCBkZWNvZGVyIGZvciBjb252ZXJ0aW5nIGJpbmFyeSBkYXRhIHRvIHN0cmluZ3NcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIHRleHREZWNvZGVyID0gbmV3IFRleHREZWNvZGVyKFwidXRmOFwiKTtcblxuICBwcm90ZWN0ZWQgc3RhdGljIHJlYWRvbmx5IHNlcmlhbGl6ZXIgPSBuZXcgU2ltcGxlRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXIoKTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENvbnRleHQgY29uc3RydWN0b3IgZm9yIHRoaXMgYWRhcHRlclxuICAgKiBAc3VtbWFyeSBPdmVycmlkZXMgdGhlIGJhc2UgQ29udGV4dCBjb25zdHJ1Y3RvciB3aXRoIEZhYnJpY0NvbnRyYWN0Q29udGV4dFxuICAgKi9cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIHJlYWRvbmx5IENvbnRleHQ6IENvbnN0cnVjdG9yPEZhYnJpY0NvbnRyYWN0Q29udGV4dD4gPVxuICAgIEZhYnJpY0NvbnRyYWN0Q29udGV4dDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgdGhlIHJlcG9zaXRvcnkgY29uc3RydWN0b3IgZm9yIHRoaXMgYWRhcHRlclxuICAgKiBAc3VtbWFyeSBSZXR1cm5zIHRoZSBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnkgY29uc3RydWN0b3IgZm9yIGNyZWF0aW5nIHJlcG9zaXRvcmllc1xuICAgKiBAdGVtcGxhdGUgTSAtIFR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gICAqIEByZXR1cm4ge0NvbnN0cnVjdG9yPFJlcG9zaXRvcnk8TSwgTWFuZ29RdWVyeSwgRmFicmljQ29udHJhY3RBZGFwdGVyLCBGYWJyaWNDb250cmFjdEZsYWdzLCBGYWJyaWNDb250cmFjdENvbnRleHQ+Pn0gVGhlIHJlcG9zaXRvcnkgY29uc3RydWN0b3JcbiAgICovXG4gIG92ZXJyaWRlIHJlcG9zaXRvcnk8XG4gICAgUiBleHRlbmRzIFJlcG9zaXRvcnk8XG4gICAgICBhbnksXG4gICAgICBBZGFwdGVyPGFueSwgdm9pZCwgTWFuZ29RdWVyeSwgQ29udGV4dDxGYWJyaWNDb250cmFjdEZsYWdzPj5cbiAgICA+LFxuICA+KCk6IENvbnN0cnVjdG9yPFI+IHtcbiAgICByZXR1cm4gRmFicmljQ29udHJhY3RSZXBvc2l0b3J5IGFzIHVua25vd24gYXMgQ29uc3RydWN0b3I8Uj47XG4gIH1cblxuICBvdmVycmlkZSBQYWdpbmF0b3I8TSBleHRlbmRzIE1vZGVsPihcbiAgICBxdWVyeTogTWFuZ29RdWVyeSxcbiAgICBzaXplOiBudW1iZXIsXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+XG4gICk6IFBhZ2luYXRvcjxNLCBhbnksIE1hbmdvUXVlcnk+IHtcbiAgICByZXR1cm4gbmV3IEZhYnJpY0NvbnRyYWN0UGFnaW5hdG9yKHRoaXMsIHF1ZXJ5LCBzaXplLCBjbGF6eik7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBTZXF1ZW5jZShvcHRpb25zOiBTZXF1ZW5jZU9wdGlvbnMpOiBQcm9taXNlPFNlcXVlbmNlPiB7XG4gICAgcmV0dXJuIG5ldyBGYWJyaWNDb250cmFjdFNlcXVlbmNlKG9wdGlvbnMsIHRoaXMgYXMgYW55KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIG5ldyBGYWJyaWNDb250cmFjdEFkYXB0ZXIgaW5zdGFuY2VcbiAgICogQHN1bW1hcnkgSW5pdGlhbGl6ZXMgYW4gYWRhcHRlciBmb3IgaW50ZXJhY3Rpbmcgd2l0aCB0aGUgRmFicmljIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBwYXJhbSB7dm9pZH0gc2NvcGUgLSBOb3QgdXNlZCBpbiB0aGlzIGFkYXB0ZXJcbiAgICogQHBhcmFtIHtzdHJpbmd9IFthbGlhc10gLSBPcHRpb25hbCBhbGlhcyBmb3IgdGhlIGFkYXB0ZXIgaW5zdGFuY2VcbiAgICovXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiB2b2lkLCBhbGlhcz86IHN0cmluZykge1xuICAgIHN1cGVyKHNjb3BlLCBGYWJyaWNGbGF2b3VyLCBhbGlhcyk7XG4gIH1cblxuICBvdmVycmlkZSBmb3IoY29uZmlnOiBQYXJ0aWFsPGFueT4sIC4uLmFyZ3M6IGFueSk6IHR5cGVvZiB0aGlzIHtcbiAgICByZXR1cm4gc3VwZXIuZm9yKGNvbmZpZywgLi4uYXJncyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSByZWNvcmQgaW4gdGhlIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBzdW1tYXJ5IFNlcmlhbGl6ZXMgYSBtb2RlbCBhbmQgc3RvcmVzIGl0IGluIHRoZSBGYWJyaWMgc3RhdGUgZGF0YWJhc2VcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZS9jb2xsZWN0aW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nIHwgbnVtYmVyfSBpZCAtIFRoZSByZWNvcmQgaWRlbnRpZmllclxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IG1vZGVsIC0gVGhlIHJlY29yZCBkYXRhXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gdHJhbnNpZW50IC0gVHJhbnNpZW50IGRhdGEgKG5vdCB1c2VkIGluIHRoaXMgaW1wbGVtZW50YXRpb24pXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cywgaW5jbHVkaW5nIHRoZSBjaGFpbmNvZGUgc3R1YiBhbmQgbG9nZ2VyXG4gICAqIEByZXR1cm4ge1Byb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBjcmVhdGVkIHJlY29yZFxuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgY3JlYXRlPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+LFxuICAgIGlkOiBQcmltYXJ5S2V5VHlwZSxcbiAgICBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICAuLi5hcmdzOiBDb250ZXh0dWFsQXJnczxDb250ZXh0PEZhYnJpY0NvbnRyYWN0RmxhZ3M+PlxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+IHtcbiAgICBjb25zdCB7IGN0eCwgbG9nIH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLmNyZWF0ZSk7XG4gICAgbG9nLmluZm8oYGluIEFEQVBURVIgY3JlYXRlIHdpdGggYXJncyAke2FyZ3N9YCk7XG4gICAgY29uc3QgdGFibGVOYW1lID0gTW9kZWwudGFibGVOYW1lKGNsYXp6KTtcbiAgICB0cnkge1xuICAgICAgbG9nLmluZm8oYGFkZGluZyBlbnRyeSB0byAke3RhYmxlTmFtZX0gdGFibGUgd2l0aCBwayAke2lkfWApO1xuICAgICAgY29uc3QgY29tcG9zZWRLZXkgPSBjdHguc3R1Yi5jcmVhdGVDb21wb3NpdGVLZXkodGFibGVOYW1lLCBbU3RyaW5nKGlkKV0pO1xuICAgICAgbW9kZWwgPSBhd2FpdCB0aGlzLnB1dFN0YXRlKGNvbXBvc2VkS2V5LCBtb2RlbCwgY3R4KTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1vZGVsO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWFkcyBhIHJlY29yZCBmcm9tIHRoZSBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBSZXRyaWV2ZXMgYW5kIGRlc2VyaWFsaXplcyBhIHJlY29yZCBmcm9tIHRoZSBGYWJyaWMgc3RhdGUgZGF0YWJhc2VcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZS9jb2xsZWN0aW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nIHwgbnVtYmVyfSBpZCAtIFRoZSByZWNvcmQgaWRlbnRpZmllclxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMsIGluY2x1ZGluZyB0aGUgY2hhaW5jb2RlIHN0dWIgYW5kIGxvZ2dlclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgcmV0cmlldmVkIHJlY29yZFxuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgcmVhZDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZDogUHJpbWFyeUtleVR5cGUsXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8Q29udGV4dDxGYWJyaWNDb250cmFjdEZsYWdzPj5cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB7XG4gICAgY29uc3QgeyBjdHgsIGxvZyB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5yZWFkKTtcbiAgICBsb2cuaW5mbyhgaW4gQURBUFRFUiByZWFkIHdpdGggYXJncyAke2FyZ3N9YCk7XG4gICAgY29uc3QgdGFibGVOYW1lID0gTW9kZWwudGFibGVOYW1lKGNsYXp6KTtcblxuICAgIGxldCBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgICB0cnkge1xuICAgICAgY29uc3QgY29tcG9zZWRLZXkgPSBjdHguc3R1Yi5jcmVhdGVDb21wb3NpdGVLZXkodGFibGVOYW1lLCBbU3RyaW5nKGlkKV0pO1xuICAgICAgbW9kZWwgPSBhd2FpdCB0aGlzLnJlYWRTdGF0ZShjb21wb3NlZEtleSwgY3R4KTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1vZGVsO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBVcGRhdGVzIGEgcmVjb3JkIGluIHRoZSBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBTZXJpYWxpemVzIGEgbW9kZWwgYW5kIHVwZGF0ZXMgaXQgaW4gdGhlIEZhYnJpYyBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlL2NvbGxlY3Rpb25cbiAgICogQHBhcmFtIHtzdHJpbmcgfCBudW1iZXJ9IGlkIC0gVGhlIHJlY29yZCBpZGVudGlmaWVyXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gbW9kZWwgLSBUaGUgdXBkYXRlZCByZWNvcmQgZGF0YVxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IHRyYW5zaWVudCAtIFRyYW5zaWVudCBkYXRhIChub3QgdXNlZCBpbiB0aGlzIGltcGxlbWVudGF0aW9uKVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMsIGluY2x1ZGluZyB0aGUgY2hhaW5jb2RlIHN0dWIgYW5kIGxvZ2dlclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgdXBkYXRlZCByZWNvcmRcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIHVwZGF0ZTxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZDogUHJpbWFyeUtleVR5cGUsXG4gICAgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8Q29udGV4dDxGYWJyaWNDb250cmFjdEZsYWdzPj5cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB7XG4gICAgY29uc3QgeyBjdHgsIGxvZyB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy51cGRhdGUpO1xuICAgIGNvbnN0IHRhYmxlTmFtZSA9IE1vZGVsLnRhYmxlTmFtZShjbGF6eik7XG5cbiAgICB0cnkge1xuICAgICAgbG9nLnZlcmJvc2UoYHVwZGF0aW5nIGVudHJ5IHRvICR7dGFibGVOYW1lfSB0YWJsZSB3aXRoIHBrICR7aWR9YCk7XG4gICAgICBjb25zdCBjb21wb3NlZEtleSA9IGN0eC5zdHViLmNyZWF0ZUNvbXBvc2l0ZUtleSh0YWJsZU5hbWUsIFtTdHJpbmcoaWQpXSk7XG4gICAgICBtb2RlbCA9IGF3YWl0IHRoaXMucHV0U3RhdGUoY29tcG9zZWRLZXksIG1vZGVsLCBjdHgpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IHRoaXMucGFyc2VFcnJvcihlIGFzIEVycm9yKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbW9kZWw7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERlbGV0ZXMgYSByZWNvcmQgZnJvbSB0aGUgc3RhdGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgUmV0cmlldmVzIGEgcmVjb3JkIGFuZCB0aGVuIHJlbW92ZXMgaXQgZnJvbSB0aGUgRmFicmljIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGUvY29sbGVjdGlvblxuICAgKiBAcGFyYW0ge3N0cmluZyB8IG51bWJlcn0gaWQgLSBUaGUgcmVjb3JkIGlkZW50aWZpZXIgdG8gZGVsZXRlXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cywgaW5jbHVkaW5nIHRoZSBjaGFpbmNvZGUgc3R1YiBhbmQgbG9nZ2VyXG4gICAqIEByZXR1cm4ge1Byb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBkZWxldGVkIHJlY29yZFxuICAgKi9cbiAgYXN5bmMgZGVsZXRlPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+LFxuICAgIGlkOiBQcmltYXJ5S2V5VHlwZSxcbiAgICAuLi5hcmdzOiBDb250ZXh0dWFsQXJnczxDb250ZXh0PEZhYnJpY0NvbnRyYWN0RmxhZ3M+PlxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+IHtcbiAgICBjb25zdCB7IGN0eCwgbG9nLCBjdHhBcmdzIH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLmRlbGV0ZSk7XG4gICAgY29uc3QgdGFibGVOYW1lID0gTW9kZWwudGFibGVOYW1lKGNsYXp6KTtcbiAgICBsZXQgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT47XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGNvbXBvc2VkS2V5ID0gY3R4LnN0dWIuY3JlYXRlQ29tcG9zaXRlS2V5KHRhYmxlTmFtZSwgW1N0cmluZyhpZCldKTtcbiAgICAgIG1vZGVsID0gYXdhaXQgdGhpcy5yZWFkKGNsYXp6LCBpZCwgLi4uY3R4QXJncyk7XG4gICAgICBsb2cudmVyYm9zZShgZGVsZXRpbmcgZW50cnkgd2l0aCBwayAke2lkfSBmcm9tICR7dGFibGVOYW1lfSB0YWJsZWApO1xuICAgICAgYXdhaXQgdGhpcy5kZWxldGVTdGF0ZShjb21wb3NlZEtleSwgY3R4KTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1vZGVsO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGRlbGV0ZVN0YXRlKGlkOiBzdHJpbmcsIGNvbnRleHQ6IEZhYnJpY0NvbnRyYWN0Q29udGV4dCkge1xuICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMuZGVsZXRlU3RhdGUpO1xuICAgIGF3YWl0IGN0eC5zdHViLmRlbGV0ZVN0YXRlKGlkKTtcbiAgfVxuXG4gIGZvclByaXZhdGUoY29sbGVjdGlvbjogc3RyaW5nKTogRmFicmljQ29udHJhY3RBZGFwdGVyIHtcbiAgICBjb25zdCB0b092ZXJyaWRlID0gW1xuICAgICAgdGhpcy5wdXRTdGF0ZSxcbiAgICAgIHRoaXMucmVhZFN0YXRlLFxuICAgICAgdGhpcy5kZWxldGVTdGF0ZSxcbiAgICAgIHRoaXMucXVlcnlSZXN1bHQsXG4gICAgICB0aGlzLnF1ZXJ5UmVzdWx0UGFnaW5hdGVkLFxuICAgIF0ubWFwKChmbikgPT4gZm4ubmFtZSk7XG4gICAgcmV0dXJuIG5ldyBQcm94eSh0aGlzLCB7XG4gICAgICBnZXQodGFyZ2V0LCBwcm9wLCByZWNlaXZlcikge1xuICAgICAgICBpZiAoIXRvT3ZlcnJpZGUuaW5jbHVkZXMocHJvcCBhcyBzdHJpbmcpKVxuICAgICAgICAgIHJldHVybiBSZWZsZWN0LmdldCh0YXJnZXQsIHByb3AsIHJlY2VpdmVyKTtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm94eSgodGFyZ2V0IGFzIGFueSlbcHJvcF0sIHtcbiAgICAgICAgICBhc3luYyBhcHBseShmbiwgdGhpc0FyZywgYXJnc0xpc3QpIHtcbiAgICAgICAgICAgIHN3aXRjaCAocHJvcCkge1xuICAgICAgICAgICAgICBjYXNlIFwicHV0U3RhdGVcIjoge1xuICAgICAgICAgICAgICAgIGNvbnN0IFtzdHViLCBpZCwgbW9kZWxdID0gYXJnc0xpc3Q7XG4gICAgICAgICAgICAgICAgYXdhaXQgc3R1Yi5wdXRQcml2YXRlRGF0YShjb2xsZWN0aW9uLCBpZC50b1N0cmluZygpLCBtb2RlbCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1vZGVsO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGNhc2UgXCJkZWxldGVTdGF0ZVwiOiB7XG4gICAgICAgICAgICAgICAgY29uc3QgW3N0dWIsIGlkXSA9IGFyZ3NMaXN0O1xuICAgICAgICAgICAgICAgIHJldHVybiAoc3R1YiBhcyBDaGFpbmNvZGVTdHViKS5kZWxldGVQcml2YXRlRGF0YShcbiAgICAgICAgICAgICAgICAgIGNvbGxlY3Rpb24sXG4gICAgICAgICAgICAgICAgICBpZFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgY2FzZSBcInJlYWRTdGF0ZVwiOiB7XG4gICAgICAgICAgICAgICAgY29uc3QgW3N0dWIsIGlkXSA9IGFyZ3NMaXN0O1xuICAgICAgICAgICAgICAgIHJldHVybiBzdHViLmdldFByaXZhdGVEYXRhKGNvbGxlY3Rpb24sIGlkKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBjYXNlIFwicXVlcnlSZXN1bHRcIjoge1xuICAgICAgICAgICAgICAgIGNvbnN0IFtzdHViLCByYXdJbnB1dF0gPSBhcmdzTGlzdDtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3R1Yi5nZXRQcml2YXRlRGF0YVF1ZXJ5UmVzdWx0KGNvbGxlY3Rpb24sIHJhd0lucHV0KTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBjYXNlIFwicXVlcnlSZXN1bHRQYWdpbmF0ZWRcIjoge1xuICAgICAgICAgICAgICAgIGNvbnN0IFtzdHViLCByYXdJbnB1dCwgbGltaXQsIHNraXBdID0gYXJnc0xpc3Q7XG4gICAgICAgICAgICAgICAgY29uc3QgaXRlcmF0b3IgPSBhd2FpdCAoXG4gICAgICAgICAgICAgICAgICBzdHViIGFzIENoYWluY29kZVN0dWJcbiAgICAgICAgICAgICAgICApLmdldFByaXZhdGVEYXRhUXVlcnlSZXN1bHQoY29sbGVjdGlvbiwgcmF3SW5wdXQpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdHM6IGFueVtdID0gW107XG4gICAgICAgICAgICAgICAgbGV0IGNvdW50ID0gMDtcbiAgICAgICAgICAgICAgICBsZXQgcmVhY2hlZEJvb2ttYXJrID0gc2tpcCA/IGZhbHNlIDogdHJ1ZTtcbiAgICAgICAgICAgICAgICBsZXQgbGFzdEtleTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgaXRlcmF0b3IubmV4dCgpO1xuXG4gICAgICAgICAgICAgICAgICBpZiAocmVzLnZhbHVlICYmIHJlcy52YWx1ZS52YWx1ZS50b1N0cmluZygpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlY29yZEtleSA9IHJlcy52YWx1ZS5rZXk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlY29yZFZhbHVlID0gKHJlcy52YWx1ZS52YWx1ZSBhcyBhbnkpLnRvU3RyaW5nKFxuICAgICAgICAgICAgICAgICAgICAgIFwidXRmOFwiXG4gICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgd2UgaGF2ZSBhIHNraXAsIHNraXAgdW50aWwgd2UgcmVhY2ggaXRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFyZWFjaGVkQm9va21hcmspIHtcbiAgICAgICAgICAgICAgICAgICAgICBpZiAocmVjb3JkS2V5ID09PSBza2lwPy50b1N0cmluZygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWFjaGVkQm9va21hcmsgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdHMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgS2V5OiByZWNvcmRLZXksXG4gICAgICAgICAgICAgICAgICAgICAgUmVjb3JkOiBKU09OLnBhcnNlKHJlY29yZFZhbHVlKSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGxhc3RLZXkgPSByZWNvcmRLZXk7XG4gICAgICAgICAgICAgICAgICAgIGNvdW50Kys7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvdW50ID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgYXdhaXQgaXRlcmF0b3IuY2xvc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaXRlcmF0b3I6XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdHMgYXMgdW5rbm93biBhcyBJdGVyYXRvcnMuU3RhdGVRdWVyeUl0ZXJhdG9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZmV0Y2hlZFJlY29yZHNDb3VudDogcmVzdWx0cy5sZW5ndGgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGJvb2ttYXJrOiBsYXN0S2V5LFxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgIGlmIChyZXMuZG9uZSkge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCBpdGVyYXRvci5jbG9zZSgpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgIGl0ZXJhdG9yOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cyBhcyB1bmtub3duIGFzIEl0ZXJhdG9ycy5TdGF0ZVF1ZXJ5SXRlcmF0b3IsXG4gICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZldGNoZWRSZWNvcmRzQ291bnQ6IHJlc3VsdHMubGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICAgICAgYm9va21hcms6IFwiXCIsXG4gICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICAgICAgICAgIGBVbnN1cHBvcnRlZCBtZXRob2Qgb3ZlcnJpZGUgJHtTdHJpbmcocHJvcCl9YFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHB1dFN0YXRlKFxuICAgIGlkOiBzdHJpbmcsXG4gICAgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgY3R4OiBGYWJyaWNDb250cmFjdENvbnRleHRcbiAgKSB7XG4gICAgbGV0IGRhdGE6IEJ1ZmZlcjtcblxuICAgIGNvbnN0IHsgbG9nIH0gPSB0aGlzLmxvZ0N0eChbY3R4XSwgdGhpcy5wdXRTdGF0ZSk7XG4gICAgdHJ5IHtcbiAgICAgIGRhdGEgPSBCdWZmZXIuZnJvbShcbiAgICAgICAgRmFicmljQ29udHJhY3RBZGFwdGVyLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG1vZGVsIGFzIE1vZGVsLCBmYWxzZSlcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihcbiAgICAgICAgYEZhaWxlZCB0byBzZXJpYWxpemUgcmVjb3JkIHdpdGggaWQgJHtpZH06ICR7ZX1gXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IGNvbGxlY3Rpb24gPSBjdHguZ2V0KFwic2VncmVnYXRlZFwiKTtcbiAgICBpZiAoY29sbGVjdGlvbilcbiAgICAgIGF3YWl0IGN0eC5zdHViLnB1dFByaXZhdGVEYXRhKGNvbGxlY3Rpb24sIGlkLnRvU3RyaW5nKCksIGRhdGEpO1xuICAgIGVsc2UgYXdhaXQgY3R4LnN0dWIucHV0U3RhdGUoaWQudG9TdHJpbmcoKSwgZGF0YSk7XG5cbiAgICBsb2cuc2lsbHkoXG4gICAgICBgc3RhdGUgc3RvcmVkJHtjb2xsZWN0aW9uID8gYCBpbiAke2NvbGxlY3Rpb259IGNvbGxlY3Rpb25gIDogXCJcIn0gdW5kZXIgaWQgJHtpZH1gXG4gICAgKTtcbiAgICByZXR1cm4gbW9kZWw7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgcmVhZFN0YXRlKGlkOiBzdHJpbmcsIGN0eDogRmFicmljQ29udHJhY3RDb250ZXh0KSB7XG4gICAgbGV0IHJlc3VsdDogYW55O1xuXG4gICAgY29uc3QgeyBsb2cgfSA9IHRoaXMubG9nQ3R4KFtjdHhdLCB0aGlzLnJlYWRTdGF0ZSk7XG4gICAgbGV0IHJlczogc3RyaW5nO1xuICAgIGNvbnN0IGNvbGxlY3Rpb24gPSBjdHguZ2V0KFwic2VncmVnYXRlZFwiKTtcbiAgICBpZiAoY29sbGVjdGlvbilcbiAgICAgIHJlcyA9IChcbiAgICAgICAgYXdhaXQgY3R4LnN0dWIuZ2V0UHJpdmF0ZURhdGEoY29sbGVjdGlvbiwgaWQudG9TdHJpbmcoKSlcbiAgICAgICkudG9TdHJpbmcoKTtcbiAgICBlbHNlIHJlcyA9IChhd2FpdCBjdHguc3R1Yi5nZXRTdGF0ZShpZC50b1N0cmluZygpKSkudG9TdHJpbmcoKTtcblxuICAgIGlmICghcmVzKVxuICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXJyb3IoXG4gICAgICAgIGBSZWNvcmQgd2l0aCBpZCAke2lkfSR7Y29sbGVjdGlvbiA/IGAgaW4gJHtjb2xsZWN0aW9ufSBjb2xsZWN0aW9uYCA6IFwiXCJ9IG5vdCBmb3VuZGBcbiAgICAgICk7XG4gICAgbG9nLnNpbGx5KFxuICAgICAgYHN0YXRlIHJldHJpZXZlZCBmcm9tJHtjb2xsZWN0aW9uID8gYCAke2NvbGxlY3Rpb259IGNvbGxlY3Rpb25gIDogXCJcIn0gdW5kZXIgaWQgJHtpZH1gXG4gICAgKTtcbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gRmFicmljQ29udHJhY3RBZGFwdGVyLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUocmVzLnRvU3RyaW5nKCkpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoYEZhaWxlZCB0byBwYXJzZSByZWNvcmQ6ICR7ZX1gKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHF1ZXJ5UmVzdWx0KFxuICAgIHN0dWI6IENoYWluY29kZVN0dWIsXG4gICAgcmF3SW5wdXQ6IGFueSxcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPEl0ZXJhdG9ycy5TdGF0ZVF1ZXJ5SXRlcmF0b3I+IHtcbiAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5yZWFkU3RhdGUpO1xuICAgIGxldCByZXM6IEl0ZXJhdG9ycy5TdGF0ZVF1ZXJ5SXRlcmF0b3I7XG4gICAgY29uc3QgY29sbGVjdGlvbiA9IGN0eC5nZXQoXCJzZWdyZWdhdGVkXCIpO1xuICAgIGlmIChjb2xsZWN0aW9uKVxuICAgICAgcmVzID0gYXdhaXQgY3R4LnN0dWIuZ2V0UHJpdmF0ZURhdGFRdWVyeVJlc3VsdChcbiAgICAgICAgY29sbGVjdGlvbixcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkocmF3SW5wdXQpXG4gICAgICApO1xuICAgIGVsc2UgcmVzID0gYXdhaXQgc3R1Yi5nZXRRdWVyeVJlc3VsdChKU09OLnN0cmluZ2lmeShyYXdJbnB1dCkpO1xuXG4gICAgcmV0dXJuIHJlcztcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBxdWVyeVJlc3VsdFBhZ2luYXRlZChcbiAgICBzdHViOiBDaGFpbmNvZGVTdHViLFxuICAgIHJhd0lucHV0OiBhbnksXG4gICAgbGltaXQ6IG51bWJlciA9IDI1MCxcbiAgICBza2lwPzogbnVtYmVyLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8U3RhdGVRdWVyeVJlc3BvbnNlPEl0ZXJhdG9ycy5TdGF0ZVF1ZXJ5SXRlcmF0b3I+PiB7XG4gICAgY29uc3QgeyBjdHggfSA9IHRoaXMubG9nQ3R4KGFyZ3MsIHRoaXMucmVhZFN0YXRlKTtcbiAgICBsZXQgcmVzOiBTdGF0ZVF1ZXJ5UmVzcG9uc2U8SXRlcmF0b3JzLlN0YXRlUXVlcnlJdGVyYXRvcj47XG4gICAgY29uc3QgY29sbGVjdGlvbiA9IGN0eC5nZXQoXCJzZWdyZWdhdGVkXCIpO1xuICAgIGlmIChjb2xsZWN0aW9uKSB7XG4gICAgICByYXdJbnB1dC5zZWxlY3RvciA9IHtcbiAgICAgICAgLi4ucmF3SW5wdXQuc2VsZWN0b3IsXG4gICAgICAgIF9pZDogc2tpcCA/IHsgJGd0OiBza2lwLnRvU3RyaW5nKCkgfSA6IHsgJGd0ZTogXCJcIiB9LFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGl0ID0gYXdhaXQgc3R1Yi5nZXRQcml2YXRlRGF0YVF1ZXJ5UmVzdWx0KFxuICAgICAgICBjb2xsZWN0aW9uLFxuICAgICAgICBKU09OLnN0cmluZ2lmeShyYXdJbnB1dClcbiAgICAgICk7XG4gICAgICByZXMgPSB7XG4gICAgICAgIGl0ZXJhdG9yOiBpdCxcbiAgICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgICBmZXRjaGVkUmVjb3Jkc0NvdW50OiBsaW1pdCxcbiAgICAgICAgICBib29rbWFyazogXCJcIixcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgfSBlbHNlXG4gICAgICByZXMgPSBhd2FpdCBzdHViLmdldFF1ZXJ5UmVzdWx0V2l0aFBhZ2luYXRpb24oXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KHJhd0lucHV0KSxcbiAgICAgICAgbGltaXQsXG4gICAgICAgIHNraXA/LnRvU3RyaW5nKClcbiAgICAgICk7XG5cbiAgICByZXR1cm4gcmVzO1xuICB9XG5cbiAgcHJvdGVjdGVkIG1lcmdlTW9kZWxzKHJlc3VsdHM6IFJlY29yZDxzdHJpbmcsIGFueT5bXSk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuICAgIGNvbnN0IGV4dHJhY3QgPSAobW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT4pID0+XG4gICAgICBPYmplY3QuZW50cmllcyhtb2RlbCkucmVkdWNlKChhY2N1bTogUmVjb3JkPHN0cmluZywgYW55PiwgW2tleSwgdmFsXSkgPT4ge1xuICAgICAgICBpZiAodHlwZW9mIHZhbCAhPT0gXCJ1bmRlZmluZWRcIikgYWNjdW1ba2V5XSA9IHZhbDtcbiAgICAgICAgcmV0dXJuIGFjY3VtO1xuICAgICAgfSwge30pO1xuXG4gICAgbGV0IGZpbmFsTW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT4gPSByZXN1bHRzLnBvcCgpIGFzIFJlY29yZDxzdHJpbmcsIGFueT47XG5cbiAgICBmb3IgKGNvbnN0IHJlcyBvZiByZXN1bHRzKSB7XG4gICAgICBmaW5hbE1vZGVsID0gT2JqZWN0LmFzc2lnbih7fSwgZXh0cmFjdChmaW5hbE1vZGVsKSwgZXh0cmFjdChyZXMpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmluYWxNb2RlbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRGVjb2RlcyBiaW5hcnkgZGF0YSB0byBzdHJpbmdcbiAgICogQHN1bW1hcnkgQ29udmVydHMgYSBVaW50OEFycmF5IHRvIGEgc3RyaW5nIHVzaW5nIFVURi04IGVuY29kaW5nXG4gICAqIEBwYXJhbSB7VWludDhBcnJheX0gYnVmZmVyIC0gVGhlIGJpbmFyeSBkYXRhIHRvIGRlY29kZVxuICAgKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBkZWNvZGVkIHN0cmluZ1xuICAgKi9cbiAgcHJvdGVjdGVkIGRlY29kZShidWZmZXI6IFVpbnQ4QXJyYXkpIHtcbiAgICByZXR1cm4gRmFicmljQ29udHJhY3RBZGFwdGVyLnRleHREZWNvZGVyLmRlY29kZShidWZmZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIG9wZXJhdGlvbiBmbGFncyBmb3IgRmFicmljIGNvbnRyYWN0IG9wZXJhdGlvbnNcbiAgICogQHN1bW1hcnkgTWVyZ2VzIGRlZmF1bHQgZmxhZ3Mgd2l0aCBGYWJyaWMtc3BlY2lmaWMgY29udGV4dCBpbmZvcm1hdGlvblxuICAgKiBAdGVtcGxhdGUgTSAtIFR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gICAqIEBwYXJhbSB7T3BlcmF0aW9uS2V5c30gb3BlcmF0aW9uIC0gVGhlIG9wZXJhdGlvbiBiZWluZyBwZXJmb3JtZWRcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gbW9kZWwgLSBUaGUgbW9kZWwgY29uc3RydWN0b3JcbiAgICogQHBhcmFtIHtQYXJ0aWFsPEZhYnJpY0NvbnRyYWN0RmxhZ3M+fSBmbGFncyAtIFBhcnRpYWwgZmxhZ3MgdG8gbWVyZ2Ugd2l0aCBkZWZhdWx0c1xuICAgKiBAcGFyYW0ge0N0eH0gY3R4IC0gVGhlIEZhYnJpYyBjaGFpbmNvZGUgY29udGV4dFxuICAgKiBAcmV0dXJuIHtGYWJyaWNDb250cmFjdEZsYWdzfSBUaGUgbWVyZ2VkIGZsYWdzXG4gICAqL1xuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgYXN5bmMgZmxhZ3M8TSBleHRlbmRzIE1vZGVsPihcbiAgICBvcGVyYXRpb246IE9wZXJhdGlvbktleXMsXG4gICAgbW9kZWw6IENvbnN0cnVjdG9yPE0+LFxuICAgIGZsYWdzOiBQYXJ0aWFsPEZhYnJpY0NvbnRyYWN0RmxhZ3M+LFxuICAgIGN0eDogQ3R4IHwgRmFicmljQ29udHJhY3RDb250ZXh0LFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8RmFicmljQ29udHJhY3RGbGFncz4ge1xuICAgIGNvbnN0IGJhc2VGbGFncyA9IHtcbiAgICAgIHN0dWI6IGN0eC5zdHViLFxuICAgICAgc2VncmVnYXRlZDogZmFsc2UsXG4gICAgfTtcbiAgICBpZiAoY3R4IGluc3RhbmNlb2YgRmFicmljQ29udHJhY3RDb250ZXh0KSB7XG4gICAgICBPYmplY3QuYXNzaWduKGJhc2VGbGFncywge1xuICAgICAgICBsb2dnZXI6IGN0eC5sb2dnZXIsXG4gICAgICAgIGlkZW50aXR5OiBjdHguaWRlbnRpdHksXG4gICAgICAgIGNvcnJlbGF0aW9uSWQ6IGN0eC5zdHViLmdldFR4SUQoKSxcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBPYmplY3QuYXNzaWduKGJhc2VGbGFncywge1xuICAgICAgICBpZGVudGl0eTogY3R4LmNsaWVudElkZW50aXR5LFxuICAgICAgICBsb2dnZXI6IG5ldyBDb250cmFjdExvZ2dlcih0aGlzIGFzIGFueSwgdW5kZWZpbmVkLCBjdHgpLFxuICAgICAgICBjb3JyZWxhdGlvbklkOiBjdHguc3R1Yi5nZXRUeElEKCksXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBmbGFncyA9IChhd2FpdCBzdXBlci5mbGFncyhcbiAgICAgIG9wZXJhdGlvbixcbiAgICAgIG1vZGVsLFxuICAgICAgYmFzZUZsYWdzIGFzIGFueSxcbiAgICAgIC4uLmFyZ3NcbiAgICApKSBhcyBGYWJyaWNDb250cmFjdEZsYWdzO1xuXG4gICAgcmV0dXJuIGZsYWdzIGFzIEZhYnJpY0NvbnRyYWN0RmxhZ3M7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYW4gaW5kZXggZm9yIGEgbW9kZWxcbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgaXMgbm90IGltcGxlbWVudGVkIGZvciBGYWJyaWMgY29udHJhY3RzIGFuZCByZXR1cm5zIGEgcmVzb2x2ZWQgcHJvbWlzZVxuICAgKiBAdGVtcGxhdGUgTSAtIFR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IG1vZGVscyAtIFRoZSBtb2RlbCBjb25zdHJ1Y3RvclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgaW1tZWRpYXRlbHlcbiAgICovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgcHJvdGVjdGVkIGluZGV4PE0+KG1vZGVsczogQ29uc3RydWN0b3I8TT4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHVuZGVmaW5lZCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByb2Nlc3NlcyByZXN1bHRzIGZyb20gYSBzdGF0ZSBxdWVyeSBpdGVyYXRvclxuICAgKiBAc3VtbWFyeSBJdGVyYXRlcyB0aHJvdWdoIHF1ZXJ5IHJlc3VsdHMgYW5kIGNvbnZlcnRzIHRoZW0gdG8gYSBzdHJ1Y3R1cmVkIGZvcm1hdFxuICAgKiBAcGFyYW0ge0xvZ2dlcn0gbG9nIC0gTG9nZ2VyIGluc3RhbmNlIGZvciBkZWJ1Z2dpbmdcbiAgICogQHBhcmFtIHtJdGVyYXRvcnMuU3RhdGVRdWVyeUl0ZXJhdG9yfSBpdGVyYXRvciAtIFRoZSBzdGF0ZSBxdWVyeSBpdGVyYXRvclxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc0hpc3Rvcnk9ZmFsc2VdIC0gV2hldGhlciB0aGlzIGlzIGEgaGlzdG9yeSBxdWVyeVxuICAgKiBAcmV0dXJuIHtQcm9taXNlPGFueVtdPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gYW4gYXJyYXkgb2YgcHJvY2Vzc2VkIHJlc3VsdHNcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gICAqICAgcGFydGljaXBhbnQgUmVzdWx0SXRlcmF0b3JcbiAgICogICBwYXJ0aWNpcGFudCBJdGVyYXRvclxuICAgKlxuICAgKiAgIENhbGxlci0+PlJlc3VsdEl0ZXJhdG9yOiByZXN1bHRJdGVyYXRvcihsb2csIGl0ZXJhdG9yLCBpc0hpc3RvcnkpXG4gICAqICAgbG9vcCBVbnRpbCBkb25lXG4gICAqICAgICBSZXN1bHRJdGVyYXRvci0+Pkl0ZXJhdG9yOiBuZXh0KClcbiAgICogICAgIEl0ZXJhdG9yLS0+PlJlc3VsdEl0ZXJhdG9yOiB7IHZhbHVlLCBkb25lIH1cbiAgICogICAgIGFsdCBIYXMgdmFsdWVcbiAgICogICAgICAgUmVzdWx0SXRlcmF0b3ItPj5SZXN1bHRJdGVyYXRvcjogUHJvY2VzcyB2YWx1ZSBiYXNlZCBvbiBpc0hpc3RvcnlcbiAgICogICAgICAgUmVzdWx0SXRlcmF0b3ItPj5SZXN1bHRJdGVyYXRvcjogQWRkIHRvIHJlc3VsdHMgYXJyYXlcbiAgICogICAgIGVuZFxuICAgKiAgIGVuZFxuICAgKiAgIFJlc3VsdEl0ZXJhdG9yLT4+SXRlcmF0b3I6IGNsb3NlKClcbiAgICogICBSZXN1bHRJdGVyYXRvci0tPj5DYWxsZXI6IGFsbFJlc3VsdHNcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyByZXN1bHRJdGVyYXRvcihcbiAgICBsb2c6IExvZ2dlcixcbiAgICBpdGVyYXRvcjogSXRlcmF0b3JzLlN0YXRlUXVlcnlJdGVyYXRvcixcbiAgICBpc0hpc3RvcnkgPSBmYWxzZVxuICApIHtcbiAgICBjb25zdCBhbGxSZXN1bHRzID0gW107XG4gICAgbGV0IHJlczogeyB2YWx1ZTogYW55OyBkb25lOiBib29sZWFuIH0gPSBhd2FpdCBpdGVyYXRvci5uZXh0KCk7XG4gICAgd2hpbGUgKCFyZXMuZG9uZSkge1xuICAgICAgaWYgKHJlcy52YWx1ZSAmJiByZXMudmFsdWUudmFsdWUudG9TdHJpbmcoKSkge1xuICAgICAgICBsZXQganNvblJlczogYW55ID0ge307XG4gICAgICAgIGxvZy5kZWJ1ZyhyZXMudmFsdWUudmFsdWUudG9TdHJpbmcoXCJ1dGY4XCIpKTtcbiAgICAgICAgaWYgKGlzSGlzdG9yeSAvKiAmJiBpc0hpc3RvcnkgPT09IHRydWUqLykge1xuICAgICAgICAgIGpzb25SZXMuVHhJZCA9IHJlcy52YWx1ZS50eElkO1xuICAgICAgICAgIGpzb25SZXMuVGltZXN0YW1wID0gcmVzLnZhbHVlLnRpbWVzdGFtcDtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAganNvblJlcy5WYWx1ZSA9IEpTT04ucGFyc2UocmVzLnZhbHVlLnZhbHVlLnRvU3RyaW5nKFwidXRmOFwiKSk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgICAgICAgIGxvZy5lcnJvcihlcnIpO1xuICAgICAgICAgICAganNvblJlcy5WYWx1ZSA9IHJlcy52YWx1ZS52YWx1ZS50b1N0cmluZyhcInV0ZjhcIik7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBqc29uUmVzID0gSlNPTi5wYXJzZShyZXMudmFsdWUudmFsdWUudG9TdHJpbmcoXCJ1dGY4XCIpKTtcbiAgICAgICAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICAgICAgbG9nLmVycm9yKGVycik7XG4gICAgICAgICAgICBqc29uUmVzID0gcmVzLnZhbHVlLnZhbHVlLnRvU3RyaW5nKFwidXRmOFwiKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYWxsUmVzdWx0cy5wdXNoKGpzb25SZXMpO1xuICAgICAgfVxuICAgICAgcmVzID0gYXdhaXQgaXRlcmF0b3IubmV4dCgpO1xuICAgIH1cbiAgICBsb2cuZGVidWcoYENsb3NpbmcgaXRlcmF0b3IgYWZ0ZXIgJHthbGxSZXN1bHRzLmxlbmd0aH0gcmVzdWx0c2ApO1xuICAgIGl0ZXJhdG9yLmNsb3NlKCk7IC8vIHB1cnBvc2VseSBub3QgYXdhaXQuIGxldCBpdGVyYXRvciBjbG9zZSBvbiBpdHMgb3duXG4gICAgcmV0dXJuIGFsbFJlc3VsdHM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEV4ZWN1dGVzIGEgcmF3IHF1ZXJ5IGFnYWluc3QgdGhlIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBzdW1tYXJ5IFBlcmZvcm1zIGEgcmljaCBxdWVyeSB1c2luZyBDb3VjaERCIHN5bnRheCBhZ2FpbnN0IHRoZSBGYWJyaWMgc3RhdGUgZGF0YWJhc2VcbiAgICogQHRlbXBsYXRlIFIgLSBUaGUgcmV0dXJuIHR5cGVcbiAgICogQHBhcmFtIHtNYW5nb1F1ZXJ5fSByYXdJbnB1dCAtIFRoZSBNYW5nbyBRdWVyeSB0byBleGVjdXRlXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gZG9jc09ubHkgLSBXaGV0aGVyIHRvIHJldHVybiBvbmx5IGRvY3VtZW50cyAobm90IHVzZWQgaW4gdGhpcyBpbXBsZW1lbnRhdGlvbilcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzLCBpbmNsdWRpbmcgdGhlIGNoYWluY29kZSBzdHViIGFuZCBsb2dnZXJcbiAgICogQHJldHVybiB7UHJvbWlzZTxSPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHF1ZXJ5IHJlc3VsdHNcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gICAqICAgcGFydGljaXBhbnQgRmFicmljQ29udHJhY3RBZGFwdGVyXG4gICAqICAgcGFydGljaXBhbnQgU3R1YlxuICAgKiAgIHBhcnRpY2lwYW50IFN0YXRlREJcbiAgICpcbiAgICogICBDYWxsZXItPj5GYWJyaWNDb250cmFjdEFkYXB0ZXI6IHJhdyhyYXdJbnB1dCwgZG9jc09ubHksIGN0eClcbiAgICogICBGYWJyaWNDb250cmFjdEFkYXB0ZXItPj5GYWJyaWNDb250cmFjdEFkYXB0ZXI6IEV4dHJhY3QgbGltaXQgYW5kIHNraXBcbiAgICogICBhbHQgV2l0aCBwYWdpbmF0aW9uXG4gICAqICAgICBGYWJyaWNDb250cmFjdEFkYXB0ZXItPj5TdHViOiBnZXRRdWVyeVJlc3VsdFdpdGhQYWdpbmF0aW9uKHF1ZXJ5LCBsaW1pdCwgc2tpcClcbiAgICogICBlbHNlIFdpdGhvdXQgcGFnaW5hdGlvblxuICAgKiAgICAgRmFicmljQ29udHJhY3RBZGFwdGVyLT4+U3R1YjogZ2V0UXVlcnlSZXN1bHQocXVlcnkpXG4gICAqICAgZW5kXG4gICAqICAgU3R1Yi0+PlN0YXRlREI6IEV4ZWN1dGUgcXVlcnlcbiAgICogICBTdGF0ZURCLS0+PlN0dWI6IEl0ZXJhdG9yXG4gICAqICAgU3R1Yi0tPj5GYWJyaWNDb250cmFjdEFkYXB0ZXI6IEl0ZXJhdG9yXG4gICAqICAgRmFicmljQ29udHJhY3RBZGFwdGVyLT4+RmFicmljQ29udHJhY3RBZGFwdGVyOiByZXN1bHRJdGVyYXRvcihsb2csIGl0ZXJhdG9yKVxuICAgKiAgIEZhYnJpY0NvbnRyYWN0QWRhcHRlci0tPj5DYWxsZXI6IHJlc3VsdHNcbiAgICovXG4gIGFzeW5jIHJhdzxSLCBEIGV4dGVuZHMgYm9vbGVhbj4oXG4gICAgcmF3SW5wdXQ6IE1hbmdvUXVlcnksXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIGRvY3NPbmx5OiBEID0gdHJ1ZSBhcyBELFxuICAgIC4uLmFyZ3M6IENvbnRleHR1YWxBcmdzPEZhYnJpY0NvbnRyYWN0Q29udGV4dD5cbiAgKTogUHJvbWlzZTxSYXdSZXN1bHQ8UiwgRD4+IHtcbiAgICBjb25zdCB7IGxvZywgc3R1YiwgY3R4IH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLnJhdyk7XG5cbiAgICBjb25zdCB7IHNraXAsIGxpbWl0IH0gPSByYXdJbnB1dDtcbiAgICBsZXQgaXRlcmF0b3I6IEl0ZXJhdG9ycy5TdGF0ZVF1ZXJ5SXRlcmF0b3I7XG4gICAgaWYgKGxpbWl0IHx8IHNraXApIHtcbiAgICAgIGRlbGV0ZSByYXdJbnB1dFtcImxpbWl0XCJdO1xuICAgICAgZGVsZXRlIHJhd0lucHV0W1wic2tpcFwiXTtcbiAgICAgIGxvZy5kZWJ1ZyhcbiAgICAgICAgYFJldHJpZXZpbmcgcGFnaW5hdGVkIGl0ZXJhdG9yOiBsaW1pdDogJHtsaW1pdH0vIHNraXA6ICR7c2tpcH1gXG4gICAgICApO1xuICAgICAgY29uc3QgcmVzcG9uc2U6IFN0YXRlUXVlcnlSZXNwb25zZTxJdGVyYXRvcnMuU3RhdGVRdWVyeUl0ZXJhdG9yPiA9XG4gICAgICAgIChhd2FpdCB0aGlzLnF1ZXJ5UmVzdWx0UGFnaW5hdGVkKFxuICAgICAgICAgIHN0dWIsXG4gICAgICAgICAgcmF3SW5wdXQsXG4gICAgICAgICAgbGltaXQgfHwgMjUwLFxuICAgICAgICAgIChza2lwIGFzIGFueSk/LnRvU3RyaW5nKCksXG4gICAgICAgICAgY3R4XG4gICAgICAgICkpIGFzIFN0YXRlUXVlcnlSZXNwb25zZTxJdGVyYXRvcnMuU3RhdGVRdWVyeUl0ZXJhdG9yPjtcbiAgICAgIGl0ZXJhdG9yID0gcmVzcG9uc2UuaXRlcmF0b3I7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZy5kZWJ1ZyhcIlJldHJpZXZpbmcgaXRlcmF0b3JcIik7XG4gICAgICBpdGVyYXRvciA9IChhd2FpdCB0aGlzLnF1ZXJ5UmVzdWx0KFxuICAgICAgICBzdHViLFxuICAgICAgICByYXdJbnB1dCxcbiAgICAgICAgY3R4XG4gICAgICApKSBhcyBJdGVyYXRvcnMuU3RhdGVRdWVyeUl0ZXJhdG9yO1xuICAgIH1cbiAgICBsb2cuZGVidWcoXCJJdGVyYXRvciBhY3F1aXJlZFwiKTtcblxuICAgIGNvbnN0IHJlc3VsdHMgPSAoYXdhaXQgdGhpcy5yZXN1bHRJdGVyYXRvcihsb2csIGl0ZXJhdG9yKSkgYXMgUjtcbiAgICBsb2cuZGVidWcoXG4gICAgICBgcmV0dXJuaW5nICR7QXJyYXkuaXNBcnJheShyZXN1bHRzKSA/IHJlc3VsdHMubGVuZ3RoIDogMX0gcmVzdWx0c2BcbiAgICApO1xuICAgIHJldHVybiByZXN1bHRzIGFzIGFueTtcbiAgfVxuXG4gIG92ZXJyaWRlIFN0YXRlbWVudDxNIGV4dGVuZHMgTW9kZWw+KCk6IEZhYnJpY1N0YXRlbWVudDxNLCBhbnk+IHtcbiAgICByZXR1cm4gbmV3IEZhYnJpY1N0YXRlbWVudCh0aGlzIGFzIGFueSk7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBjcmVhdGVBbGw8TSBleHRlbmRzIE1vZGVsPihcbiAgICB0YWJsZU5hbWU6IENvbnN0cnVjdG9yPE0+LFxuICAgIGlkOiBQcmltYXJ5S2V5VHlwZVtdLFxuICAgIG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+W10sXG4gICAgLi4uYXJnczogQ29udGV4dHVhbEFyZ3M8RmFicmljQ29udHJhY3RDb250ZXh0PlxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT5bXT4ge1xuICAgIGlmIChpZC5sZW5ndGggIT09IG1vZGVsLmxlbmd0aClcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiSWRzIGFuZCBtb2RlbHMgbXVzdCBoYXZlIHRoZSBzYW1lIGxlbmd0aFwiKTtcbiAgICBjb25zdCB7IGxvZywgY3R4QXJncyB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy5jcmVhdGVBbGwpO1xuICAgIGNvbnN0IHRhYmxlTGFiZWwgPSBNb2RlbC50YWJsZU5hbWUodGFibGVOYW1lKTtcbiAgICBsb2cuZGVidWcoYENyZWF0aW5nICR7aWQubGVuZ3RofSBlbnRyaWVzICR7dGFibGVMYWJlbH0gdGFibGVgKTtcbiAgICByZXR1cm4gUHJvbWlzZS5hbGwoXG4gICAgICBpZC5tYXAoKGksIGNvdW50KSA9PiB0aGlzLmNyZWF0ZSh0YWJsZU5hbWUsIGksIG1vZGVsW2NvdW50XSwgLi4uY3R4QXJncykpXG4gICAgKTtcbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIHVwZGF0ZUFsbDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIHRhYmxlTmFtZTogQ29uc3RydWN0b3I8TT4sXG4gICAgaWQ6IFByaW1hcnlLZXlUeXBlW10sXG4gICAgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT5bXSxcbiAgICAuLi5hcmdzOiBDb250ZXh0dWFsQXJnczxGYWJyaWNDb250cmFjdENvbnRleHQ+XG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55PltdPiB7XG4gICAgaWYgKGlkLmxlbmd0aCAhPT0gbW9kZWwubGVuZ3RoKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJJZHMgYW5kIG1vZGVscyBtdXN0IGhhdmUgdGhlIHNhbWUgbGVuZ3RoXCIpO1xuICAgIGNvbnN0IHsgbG9nLCBjdHhBcmdzIH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLnVwZGF0ZUFsbCk7XG4gICAgY29uc3QgdGFibGVMYWJlbCA9IE1vZGVsLnRhYmxlTmFtZSh0YWJsZU5hbWUpO1xuICAgIGxvZy5kZWJ1ZyhgVXBkYXRpbmcgJHtpZC5sZW5ndGh9IGVudHJpZXMgJHt0YWJsZUxhYmVsfSB0YWJsZWApO1xuICAgIHJldHVybiBQcm9taXNlLmFsbChcbiAgICAgIGlkLm1hcCgoaSwgY291bnQpID0+IHRoaXMudXBkYXRlKHRhYmxlTmFtZSwgaSwgbW9kZWxbY291bnRdLCAuLi5jdHhBcmdzKSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqXG4gICAqIEBwYXJhbSBtb2RlbFxuICAgKiBAcGFyYW0ge3N0cmluZ30gcGtcbiAgICogQHBhcmFtIGFyZ3NcbiAgICovXG4gIG92ZXJyaWRlIHByZXBhcmU8TSBleHRlbmRzIE1vZGVsPihcbiAgICBtb2RlbDogTSxcbiAgICAuLi5hcmdzOiBDb250ZXh0dWFsQXJnczxGYWJyaWNDb250cmFjdENvbnRleHQ+XG4gICk6IFByZXBhcmVkTW9kZWwge1xuICAgIGNvbnN0IHsgbG9nIH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLnByZXBhcmUpO1xuXG4gICAgY29uc3QgdGFibGVOYW1lID0gTW9kZWwudGFibGVOYW1lKG1vZGVsLmNvbnN0cnVjdG9yIGFzIGFueSk7XG4gICAgY29uc3QgcGsgPSBNb2RlbC5wayhtb2RlbC5jb25zdHJ1Y3RvciBhcyBhbnkpO1xuICAgIGNvbnN0IHNwbGl0ID0gTW9kZWwuc2VncmVnYXRlKG1vZGVsKTtcbiAgICBjb25zdCByZXN1bHQgPSBPYmplY3QuZW50cmllcyhzcGxpdC5tb2RlbCkucmVkdWNlKFxuICAgICAgKGFjY3VtOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBba2V5LCB2YWxdKSA9PiB7XG4gICAgICAgIGlmICh0eXBlb2YgdmFsID09PSBcInVuZGVmaW5lZFwiKSByZXR1cm4gYWNjdW07XG4gICAgICAgIGNvbnN0IG1hcHBlZFByb3AgPSBNb2RlbC5jb2x1bW5OYW1lKG1vZGVsLCBrZXkgYXMgYW55KTtcbiAgICAgICAgaWYgKHRoaXMuaXNSZXNlcnZlZChtYXBwZWRQcm9wKSlcbiAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgUHJvcGVydHkgbmFtZSAke21hcHBlZFByb3B9IGlzIHJlc2VydmVkYCk7XG4gICAgICAgIGFjY3VtW21hcHBlZFByb3BdID0gdmFsO1xuICAgICAgICByZXR1cm4gYWNjdW07XG4gICAgICB9LFxuICAgICAge31cbiAgICApO1xuXG4gICAgbG9nLnNpbGx5KFxuICAgICAgYFByZXBhcmluZyByZWNvcmQgZm9yICR7dGFibGVOYW1lfSB0YWJsZSB3aXRoIHBrICR7KG1vZGVsIGFzIGFueSlbcGtdfWBcbiAgICApO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHJlY29yZDogcmVzdWx0LFxuICAgICAgaWQ6IChtb2RlbCBhcyBhbnkpW3BrXSBhcyBzdHJpbmcsXG4gICAgICB0cmFuc2llbnQ6IHNwbGl0LnRyYW5zaWVudCxcbiAgICB9O1xuICB9XG5cbiAgb3ZlcnJpZGUgcmV2ZXJ0PE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgb2JqOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZDogUHJpbWFyeUtleVR5cGUsXG4gICAgdHJhbnNpZW50PzogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICAuLi5hcmdzOiBDb250ZXh0dWFsQXJnczxGYWJyaWNDb250cmFjdENvbnRleHQ+XG4gICk6IE0ge1xuICAgIGNvbnN0IHsgbG9nIH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLnJldmVydCk7XG4gICAgY29uc3Qgb2I6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcbiAgICBjb25zdCBwayA9IE1vZGVsLnBrKGNsYXp6KTtcbiAgICBvYltwayBhcyBzdHJpbmddID0gaWQ7XG4gICAgY29uc3QgbSA9IChcbiAgICAgIHR5cGVvZiBjbGF6eiA9PT0gXCJzdHJpbmdcIiA/IE1vZGVsLmJ1aWxkKG9iLCBjbGF6eikgOiBuZXcgY2xhenoob2IpXG4gICAgKSBhcyBNO1xuICAgIGxvZy5zaWxseShgUmVidWlsZGluZyBtb2RlbCAke20uY29uc3RydWN0b3IubmFtZX0gaWQgJHtpZH1gKTtcbiAgICBjb25zdCByZXN1bHQgPSBPYmplY3Qua2V5cyhtKS5yZWR1Y2UoKGFjY3VtOiBNLCBrZXkpID0+IHtcbiAgICAgIChhY2N1bSBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+KVtrZXldID1cbiAgICAgICAgb2JqW01vZGVsLmNvbHVtbk5hbWUoYWNjdW0sIGtleSBhcyBhbnkpXTtcbiAgICAgIHJldHVybiBhY2N1bTtcbiAgICB9LCBtKTtcblxuICAgIGlmICh0cmFuc2llbnQpIHtcbiAgICAgIGxvZy5kZWJ1ZyhcbiAgICAgICAgYHJlLWFkZGluZyB0cmFuc2llbnQgcHJvcGVydGllczogJHtPYmplY3Qua2V5cyh0cmFuc2llbnQpLmpvaW4oXCIsIFwiKX1gXG4gICAgICApO1xuICAgICAgT2JqZWN0LmVudHJpZXModHJhbnNpZW50KS5mb3JFYWNoKChba2V5LCB2YWxdKSA9PiB7XG4gICAgICAgIGlmIChrZXkgaW4gcmVzdWx0ICYmIChyZXN1bHQgYXMgYW55KVtrZXldICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgICBgVHJhbnNpZW50IHByb3BlcnR5ICR7a2V5fSBhbHJlYWR5IGV4aXN0cyBvbiBtb2RlbCAke20uY29uc3RydWN0b3IubmFtZX0uIHNob3VsZCBiZSBpbXBvc3NpYmxlYFxuICAgICAgICAgICk7XG4gICAgICAgIHJlc3VsdFtrZXkgYXMga2V5b2YgTV0gPSB2YWw7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgb3ZlcnJpZGUgY3JlYXRlUHJlZml4PE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgdGFibGVOYW1lOiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZDogUHJpbWFyeUtleVR5cGUsXG4gICAgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPEZhYnJpY0NvbnRyYWN0Q29udGV4dD5cbiAgKSB7XG4gICAgY29uc3QgeyBjdHhBcmdzIH0gPSB0aGlzLmxvZ0N0eChhcmdzLCB0aGlzLmNyZWF0ZVByZWZpeCk7XG4gICAgY29uc3QgcmVjb3JkOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG4gICAgcmVjb3JkW0NvdWNoREJLZXlzLlRBQkxFXSA9IE1vZGVsLnRhYmxlTmFtZSh0YWJsZU5hbWUpO1xuICAgIE9iamVjdC5hc3NpZ24ocmVjb3JkLCBtb2RlbCk7XG5cbiAgICByZXR1cm4gW3RhYmxlTmFtZSwgaWQsIHJlY29yZCwgLi4uY3R4QXJnc10gYXMgW1xuICAgICAgQ29uc3RydWN0b3I8TT4sXG4gICAgICBQcmltYXJ5S2V5VHlwZSxcbiAgICAgIFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgICAuLi5hbnlbXSxcbiAgICAgIEZhYnJpY0NvbnRyYWN0Q29udGV4dCxcbiAgICBdO1xuICB9XG5cbiAgb3ZlcnJpZGUgdXBkYXRlUHJlZml4PE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgdGFibGVOYW1lOiBDb25zdHJ1Y3RvcjxNPixcbiAgICBpZDogUHJpbWFyeUtleVR5cGUsXG4gICAgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgLi4uYXJnczogTWF5YmVDb250ZXh0dWFsQXJnPEZhYnJpY0NvbnRyYWN0Q29udGV4dD5cbiAgKTogYW55W10ge1xuICAgIGNvbnN0IHsgY3R4QXJncyB9ID0gdGhpcy5sb2dDdHgoYXJncywgdGhpcy51cGRhdGVQcmVmaXgpO1xuICAgIGNvbnN0IHJlY29yZDogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICAgIHJlY29yZFtDb3VjaERCS2V5cy5UQUJMRV0gPSBNb2RlbC50YWJsZU5hbWUodGFibGVOYW1lKTtcbiAgICBPYmplY3QuYXNzaWduKHJlY29yZCwgbW9kZWwpO1xuXG4gICAgcmV0dXJuIFt0YWJsZU5hbWUsIGlkLCByZWNvcmQsIC4uLmN0eEFyZ3NdIGFzIFtcbiAgICAgIENvbnN0cnVjdG9yPE0+LFxuICAgICAgUHJpbWFyeUtleVR5cGUsXG4gICAgICBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgICAgLi4uYW55W10sXG4gICAgICBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAgXTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBjcmVhdGVBbGxQcmVmaXg8TSBleHRlbmRzIE1vZGVsPihcbiAgICB0YWJsZU5hbWU6IENvbnN0cnVjdG9yPE0+LFxuICAgIGlkczogUHJpbWFyeUtleVR5cGVbXSxcbiAgICBtb2RlbHM6IFJlY29yZDxzdHJpbmcsIGFueT5bXSxcbiAgICAuLi5hcmdzOiBbLi4uYW55LCBGYWJyaWNDb250cmFjdENvbnRleHRdXG4gICk6IChzdHJpbmcgfCBzdHJpbmdbXSB8IG51bWJlcltdIHwgUmVjb3JkPHN0cmluZywgYW55PltdKVtdIHtcbiAgICBpZiAoaWRzLmxlbmd0aCAhPT0gbW9kZWxzLmxlbmd0aClcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiSWRzIGFuZCBtb2RlbHMgbXVzdCBoYXZlIHRoZSBzYW1lIGxlbmd0aFwiKTtcblxuICAgIGNvbnN0IGN0eDogRmFicmljQ29udHJhY3RDb250ZXh0ID0gYXJncy5wb3AoKTtcblxuICAgIGNvbnN0IHJlY29yZHMgPSBpZHMubWFwKChpZCwgY291bnQpID0+IHtcbiAgICAgIGNvbnN0IHJlY29yZDogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICAgICAgcmVjb3JkW0NvdWNoREJLZXlzLlRBQkxFXSA9IE1vZGVsLnRhYmxlTmFtZSh0YWJsZU5hbWUpO1xuICAgICAgT2JqZWN0LmFzc2lnbihyZWNvcmQsIG1vZGVsc1tjb3VudF0pO1xuICAgICAgcmV0dXJuIHJlY29yZDtcbiAgICB9KTtcbiAgICByZXR1cm4gW3RhYmxlTmFtZSwgaWRzLCByZWNvcmRzLCBjdHggYXMgYW55XTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSB1cGRhdGVBbGxQcmVmaXg8TSBleHRlbmRzIE1vZGVsPihcbiAgICB0YWJsZU5hbWU6IENvbnN0cnVjdG9yPE0+LFxuICAgIGlkczogUHJpbWFyeUtleVR5cGVbXSxcbiAgICBtb2RlbHM6IFJlY29yZDxzdHJpbmcsIGFueT5bXSxcbiAgICAuLi5hcmdzOiBbLi4uYW55LCBGYWJyaWNDb250cmFjdENvbnRleHRdXG4gICkge1xuICAgIGlmIChpZHMubGVuZ3RoICE9PSBtb2RlbHMubGVuZ3RoKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJJZHMgYW5kIG1vZGVscyBtdXN0IGhhdmUgdGhlIHNhbWUgbGVuZ3RoXCIpO1xuXG4gICAgY29uc3QgY3R4OiBGYWJyaWNDb250cmFjdENvbnRleHQgPSBhcmdzLnBvcCgpO1xuXG4gICAgY29uc3QgcmVjb3JkcyA9IGlkcy5tYXAoKGlkLCBjb3VudCkgPT4ge1xuICAgICAgY29uc3QgcmVjb3JkOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG4gICAgICByZWNvcmRbQ291Y2hEQktleXMuVEFCTEVdID0gTW9kZWwudGFibGVOYW1lKHRhYmxlTmFtZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHJlY29yZCwgbW9kZWxzW2NvdW50XSk7XG4gICAgICByZXR1cm4gcmVjb3JkO1xuICAgIH0pO1xuICAgIHJldHVybiBbdGFibGVOYW1lLCBpZHMsIHJlY29yZHMsIGN0eCBhcyBhbnldO1xuICB9XG5cbiAgb3ZlcnJpZGUgcGFyc2VFcnJvcjxFIGV4dGVuZHMgQmFzZUVycm9yPihcbiAgICBlcnI6IEVycm9yIHwgc3RyaW5nLFxuICAgIHJlYXNvbj86IHN0cmluZ1xuICApOiBFIHtcbiAgICByZXR1cm4gRmFicmljQ29udHJhY3RBZGFwdGVyLnBhcnNlRXJyb3IocmVhc29uIHx8IGVycik7XG4gIH1cblxuICBvdmVycmlkZSBsb2dDdHg8QVJHUyBleHRlbmRzIGFueVtdPihcbiAgICBhcmdzOiBBUkdTLFxuICAgIG1ldGhvZDogKCguLi5hcmdzOiBhbnlbXSkgPT4gYW55KSB8IHN0cmluZ1xuICApOiBDb250ZXh0dWFsaXplZEFyZ3M8RmFicmljQ29udHJhY3RDb250ZXh0LCBBUkdTPiAmIHtcbiAgICBzdHViOiBDaGFpbmNvZGVTdHViO1xuICAgIGlkZW50aXR5OiBDbGllbnRJZGVudGl0eTtcbiAgfSB7XG4gICAgcmV0dXJuIEZhYnJpY0NvbnRyYWN0QWRhcHRlci5sb2dDdHguY2FsbCh0aGlzLCBhcmdzLCBtZXRob2QgYXMgYW55KSBhcyBhbnk7XG4gIH1cblxuICBzdGF0aWMgb3ZlcnJpZGUgbG9nQ3R4PEFSR1MgZXh0ZW5kcyBhbnlbXT4oXG4gICAgdGhpczogYW55LFxuICAgIGFyZ3M6IEFSR1MsXG4gICAgbWV0aG9kOiBzdHJpbmdcbiAgKTogQ29udGV4dHVhbGl6ZWRBcmdzPEZhYnJpY0NvbnRyYWN0Q29udGV4dCwgQVJHUz4gJiB7XG4gICAgc3R1YjogQ2hhaW5jb2RlU3R1YjtcbiAgICBpZGVudGl0eTogQ2xpZW50SWRlbnRpdHk7XG4gIH07XG4gIHN0YXRpYyBvdmVycmlkZSBsb2dDdHg8QVJHUyBleHRlbmRzIGFueVtdPihcbiAgICB0aGlzOiBhbnksXG4gICAgYXJnczogQVJHUyxcbiAgICBtZXRob2Q6ICguLi5hcmdzOiBhbnlbXSkgPT4gYW55XG4gICk6IENvbnRleHR1YWxpemVkQXJnczxGYWJyaWNDb250cmFjdENvbnRleHQsIEFSR1M+ICYge1xuICAgIHN0dWI6IENoYWluY29kZVN0dWI7XG4gICAgaWRlbnRpdHk6IENsaWVudElkZW50aXR5O1xuICB9O1xuICBzdGF0aWMgb3ZlcnJpZGUgbG9nQ3R4PEFSR1MgZXh0ZW5kcyBhbnlbXT4oXG4gICAgdGhpczogYW55LFxuICAgIGFyZ3M6IEFSR1MsXG4gICAgbWV0aG9kOiAoKC4uLmFyZ3M6IGFueVtdKSA9PiBhbnkpIHwgc3RyaW5nXG4gICk6IENvbnRleHR1YWxpemVkQXJnczxGYWJyaWNDb250cmFjdENvbnRleHQsIEFSR1M+ICYge1xuICAgIHN0dWI6IENoYWluY29kZVN0dWI7XG4gICAgaWRlbnRpdHk6IENsaWVudElkZW50aXR5O1xuICB9IHtcbiAgICBpZiAoYXJncy5sZW5ndGggPCAxKSB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIk5vIGNvbnRleHQgcHJvdmlkZWRcIik7XG4gICAgY29uc3QgY3R4ID0gYXJncy5wb3AoKSBhcyBGYWJyaWNDb250cmFjdENvbnRleHQ7XG5cbiAgICBpZiAoIShjdHggaW5zdGFuY2VvZiBDb250ZXh0KSlcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiTm8gY29udGV4dCBwcm92aWRlZFwiKTtcbiAgICBpZiAoYXJncy5maWx0ZXIoKGEpID0+IGEgaW5zdGFuY2VvZiBDb250ZXh0KS5sZW5ndGggPiAxKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiaGVyZVwiKTtcbiAgICBjb25zdCBsb2cgPSAoXG4gICAgICB0aGlzXG4gICAgICAgID8gY3R4LmxvZ2dlci5mb3IodGhpcykuZm9yKG1ldGhvZClcbiAgICAgICAgOiBjdHgubG9nZ2VyLmNsZWFyKCkuZm9yKHRoaXMpLmZvcihtZXRob2QpXG4gICAgKSBhcyBMb2dnZXJPZjxGYWJyaWNDb250cmFjdENvbnRleHQ+O1xuICAgIHJldHVybiB7XG4gICAgICBjdHg6IGN0eCxcbiAgICAgIGxvZzogbWV0aG9kID8gKGxvZy5mb3IobWV0aG9kKSBhcyBMb2dnZXJPZjxGYWJyaWNDb250cmFjdENvbnRleHQ+KSA6IGxvZyxcbiAgICAgIHN0dWI6IGN0eC5zdHViLFxuICAgICAgaWRlbnRpdHk6IGN0eC5pZGVudGl0eSxcbiAgICAgIGN0eEFyZ3M6IFsuLi5hcmdzLCBjdHhdLFxuICAgIH07XG4gIH1cblxuICBzdGF0aWMgb3ZlcnJpZGUgcGFyc2VFcnJvcjxFIGV4dGVuZHMgQmFzZUVycm9yPihlcnI6IEVycm9yIHwgc3RyaW5nKTogRSB7XG4gICAgLy8gaWYgKFxuICAgIC8vICAgTUlTU0lOR19QUklWQVRFX0RBVEFfUkVHRVgudGVzdChcbiAgICAvLyAgICAgdHlwZW9mIGVyciA9PT0gXCJzdHJpbmdcIiA/IGVyciA6IGVyci5tZXNzYWdlXG4gICAgLy8gICApXG4gICAgLy8gKVxuICAgIC8vICAgcmV0dXJuIG5ldyBVbmF1dGhvcml6ZWRQcml2YXRlRGF0YUFjY2VzcyhlcnIpIGFzIEU7XG4gICAgY29uc3QgbXNnID0gdHlwZW9mIGVyciA9PT0gXCJzdHJpbmdcIiA/IGVyciA6IGVyci5tZXNzYWdlO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoTm90Rm91bmRFcnJvci5uYW1lKSkgcmV0dXJuIG5ldyBOb3RGb3VuZEVycm9yKGVycikgYXMgRTtcbiAgICBpZiAobXNnLmluY2x1ZGVzKENvbmZsaWN0RXJyb3IubmFtZSkpIHJldHVybiBuZXcgQ29uZmxpY3RFcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhCYWRSZXF1ZXN0RXJyb3IubmFtZSkpXG4gICAgICByZXR1cm4gbmV3IEJhZFJlcXVlc3RFcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhRdWVyeUVycm9yLm5hbWUpKSByZXR1cm4gbmV3IFF1ZXJ5RXJyb3IoZXJyKSBhcyBFO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoUGFnaW5nRXJyb3IubmFtZSkpIHJldHVybiBuZXcgUGFnaW5nRXJyb3IoZXJyKSBhcyBFO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoVW5zdXBwb3J0ZWRFcnJvci5uYW1lKSlcbiAgICAgIHJldHVybiBuZXcgVW5zdXBwb3J0ZWRFcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhNaWdyYXRpb25FcnJvci5uYW1lKSkgcmV0dXJuIG5ldyBNaWdyYXRpb25FcnJvcihlcnIpIGFzIEU7XG4gICAgaWYgKG1zZy5pbmNsdWRlcyhPYnNlcnZlckVycm9yLm5hbWUpKSByZXR1cm4gbmV3IE9ic2VydmVyRXJyb3IoZXJyKSBhcyBFO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoQXV0aG9yaXphdGlvbkVycm9yLm5hbWUpKVxuICAgICAgcmV0dXJuIG5ldyBBdXRob3JpemF0aW9uRXJyb3IoZXJyKSBhcyBFO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoRm9yYmlkZGVuRXJyb3IubmFtZSkpIHJldHVybiBuZXcgRm9yYmlkZGVuRXJyb3IoZXJyKSBhcyBFO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoQ29ubmVjdGlvbkVycm9yLm5hbWUpKVxuICAgICAgcmV0dXJuIG5ldyBDb25uZWN0aW9uRXJyb3IoZXJyKSBhcyBFO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoU2VyaWFsaXphdGlvbkVycm9yLm5hbWUpKVxuICAgICAgcmV0dXJuIG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoZXJyKSBhcyBFO1xuICAgIGlmIChtc2cuaW5jbHVkZXMoXCJubyBsZWRnZXIgY29udGV4dFwiKSlcbiAgICAgIHJldHVybiBuZXcgTWlzc2luZ0NvbnRleHRFcnJvcihcbiAgICAgICAgYE5vIGNvbnRleHQgZm91bmQuIHRoaXMgY2FuIGJlIGNhdXNlZCBieSBkZWJ1Z2dpbmc6ICR7bXNnfWBcbiAgICAgICkgYXMgRTtcblxuICAgIHJldHVybiBuZXcgSW50ZXJuYWxFcnJvcihlcnIpIGFzIEU7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFN0YXRpYyBtZXRob2QgZm9yIGRlY29yYXRpb24gb3ZlcnJpZGVzXG4gICAqIEBzdW1tYXJ5IE92ZXJyaWRlcy9leHRlbmRzIGRlY2FmIGRlY29yYXRpb24gd2l0aCBGYWJyaWMtc3BlY2lmaWMgZnVuY3Rpb25hbGl0eVxuICAgKiBAc3RhdGljXG4gICAqIEBvdmVycmlkZVxuICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgKi9cbiAgc3RhdGljIG92ZXJyaWRlIGRlY29yYXRpb24oKTogdm9pZCB7XG4gICAgc3VwZXIuZGVjb3JhdGlvbigpO1xuICAgIERlY29yYXRpb24uZmxhdm91cmVkQXMoRmFicmljRmxhdm91cilcbiAgICAgIC5mb3IoUGVyc2lzdGVuY2VLZXlzLkNSRUFURURfQlkpXG4gICAgICAuZGVmaW5lKFxuICAgICAgICBvbkNyZWF0ZShjcmVhdGVkQnlPbkZhYnJpY0NyZWF0ZVVwZGF0ZSksXG4gICAgICAgIHByb3BNZXRhZGF0YShQZXJzaXN0ZW5jZUtleXMuQ1JFQVRFRF9CWSwge30pXG4gICAgICApXG4gICAgICAuYXBwbHkoKTtcblxuICAgIERlY29yYXRpb24uZmxhdm91cmVkQXMoRmFicmljRmxhdm91cilcbiAgICAgIC5mb3IoUGVyc2lzdGVuY2VLZXlzLlVQREFURURfQlkpXG4gICAgICAuZGVmaW5lKFxuICAgICAgICBvbkNyZWF0ZVVwZGF0ZShjcmVhdGVkQnlPbkZhYnJpY0NyZWF0ZVVwZGF0ZSksXG4gICAgICAgIHByb3BNZXRhZGF0YShQZXJzaXN0ZW5jZUtleXMuVVBEQVRFRF9CWSwge30pXG4gICAgICApXG4gICAgICAuYXBwbHkoKTtcblxuICAgIERlY29yYXRpb24uZmxhdm91cmVkQXMoRmFicmljRmxhdm91cilcbiAgICAgIC5mb3IoUGVyc2lzdGVuY2VLZXlzLkNPTFVNTilcbiAgICAgIC5leHRlbmQoRmFicmljUHJvcGVydHkoKSlcbiAgICAgIC5hcHBseSgpO1xuXG4gICAgRGVjb3JhdGlvbi5mbGF2b3VyZWRBcyhGYWJyaWNGbGF2b3VyKVxuICAgICAgLmZvcihWYWxpZGF0aW9uS2V5cy5EQVRFKVxuICAgICAgLmV4dGVuZChmdW5jdGlvbiBmYWJyaWNQcm9wZXJ0eSgpIHtcbiAgICAgICAgcmV0dXJuICh0YXJnZXQ6IGFueSwgcHJvcD86IGFueSkgPT4ge1xuICAgICAgICAgIFByb3BlcnR5KHByb3AsIFwic3RyaW5nOmRhdGVcIikodGFyZ2V0LCBwcm9wKTtcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuXG4gICAgRGVjb3JhdGlvbi5mbGF2b3VyZWRBcyhGYWJyaWNGbGF2b3VyKVxuICAgICAgLmZvcihQZXJzaXN0ZW5jZUtleXMuVEFCTEUpXG4gICAgICAuZXh0ZW5kKGZ1bmN0aW9uIHRhYmxlKG9iajogYW55KSB7XG4gICAgICAgIGNvbnN0IGNoYWluOiBhbnlbXSA9IFtdO1xuICAgICAgICBsZXQgY3VycmVudCA9XG4gICAgICAgICAgdHlwZW9mIG9iaiA9PT0gXCJmdW5jdGlvblwiXG4gICAgICAgICAgICA/IE1ldGFkYXRhLmNvbnN0cihvYmopXG4gICAgICAgICAgICA6IE1ldGFkYXRhLmNvbnN0cihvYmouY29uc3RydWN0b3IpO1xuXG4gICAgICAgIHdoaWxlIChjdXJyZW50ICYmIGN1cnJlbnQgIT09IE9iamVjdCAmJiBjdXJyZW50LnByb3RvdHlwZSkge1xuICAgICAgICAgIGNoYWluLnB1c2goY3VycmVudCk7XG4gICAgICAgICAgY3VycmVudCA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihjdXJyZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnNvbGUubG9nKGNoYWluLm1hcCgoYykgPT4gYy5uYW1lIHx8IGMpKTtcblxuICAgICAgICAvLyBBcHBseSBmcm9tIHRoZSBiYXNlIGNsYXNzIGRvd24gdG8gdGhlIGRlY29yYXRlZCBjbGFzc1xuICAgICAgICB3aGlsZSAoY2hhaW4ubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGNvbnN0IGNvbnN0cnVjdG9yID0gY2hhaW4ucG9wKCk7XG4gICAgICAgICAgY29uc29sZS5sb2coYENhbGxpbmcgb24gJHtjb25zdHJ1Y3Rvci5uYW1lfWApO1xuICAgICAgICAgIEZhYnJpY09iamVjdCgpKGNvbnN0cnVjdG9yKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBGYWJyaWNPYmplY3QoKShvYmopO1xuICAgICAgfSlcbiAgICAgIC5hcHBseSgpO1xuICB9XG59XG5cbkZhYnJpY0NvbnRyYWN0QWRhcHRlci5kZWNvcmF0aW9uKCk7XG5BZGFwdGVyLnNldEN1cnJlbnQoRmFicmljRmxhdm91cik7XG4iLCIvKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzICovXG5pbXBvcnQgeyBDb25zdHJ1Y3RvciwgTWV0YWRhdGEgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcbmltcG9ydCB7XG4gIEpTT05TZXJpYWxpemVyLFxuICBNb2RlbCxcbiAgTW9kZWxLZXlzLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERldGVybWluaXN0aWMgSlNPTiBzZXJpYWxpemVyIGZvciBGYWJyaWMgbW9kZWxzXG4gKiBAc3VtbWFyeSBFbnN1cmVzIHN0YWJsZSwgZGV0ZXJtaW5pc3RpYyBKU09OIG91dHB1dCBieSBzb3J0aW5nIG9iamVjdCBrZXlzIHJlY3Vyc2l2ZWx5IGJlZm9yZSBzdHJpbmdpZmljYXRpb24sIHdoaWNoIGlzIGltcG9ydGFudCBmb3IgRmFicmljIGVuZG9yc2VtZW50IGFuZCBoYXNoaW5nLiBFeHRlbmRzIEpTT05TZXJpYWxpemVyIHRvIHBsdWcgaW50byBleGlzdGluZyBEZWNhZiBtb2RlbCBzZXJpYWxpemF0aW9uIGZsb3cuXG4gKiBAdGVtcGxhdGUgTSAtIFRoZSBEZWNhZiBNb2RlbCBzdWJ0eXBlIHNlcmlhbGl6ZWQgYnkgdGhpcyBpbnN0YW5jZVxuICogQHBhcmFtIHt2b2lkfSBbY29uc3RydWN0b3JdIE5vIHB1YmxpYyBjb25zdHJ1Y3RvciBhcmd1bWVudHNcbiAqIEBjbGFzcyBEZXRlcm1pbmlzdGljU2VyaWFsaXplclxuICogQGV4YW1wbGVcbiAqIGNvbnN0IHNlcmlhbGl6ZXIgPSBuZXcgRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXI8TXlNb2RlbD4oKTtcbiAqIGNvbnN0IGpzb24gPSBzZXJpYWxpemVyLnNlcmlhbGl6ZShtb2RlbCk7XG4gKiBjb25zdCByZWJ1aWx0ID0gc2VyaWFsaXplci5kZXNlcmlhbGl6ZShqc29uKTtcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IERTIGFzIERldGVybWluaXN0aWNTZXJpYWxpemVyXG4gKiAgIENhbGxlci0+PkRTOiBzZXJpYWxpemUobW9kZWwpXG4gKiAgIERTLT4+RFM6IHByZVNlcmlhbGl6ZShtb2RlbClcbiAqICAgRFMtPj5EUzogc29ydC1rZXlzLXJlY3Vyc2l2ZVxuICogICBEUy0+PkRTOiBqc29uLXN0cmluZ2lmeS1kZXRlcm1pbmlzdGljXG4gKiAgIERTLS0+PkNhbGxlcjogc3RyaW5nXG4gKiAgIENhbGxlci0+PkRTOiBkZXNlcmlhbGl6ZShzdHJpbmcpXG4gKiAgIERTLS0+PkNhbGxlcjogbW9kZWxcbiAqL1xuZXhwb3J0IGNsYXNzIERldGVybWluaXN0aWNTZXJpYWxpemVyPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4+IGV4dGVuZHMgSlNPTlNlcmlhbGl6ZXI8TT4ge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuICB9XG4gIHByb3RlY3RlZCBvdmVycmlkZSBwcmVTZXJpYWxpemUobW9kZWw6IE0pIHtcbiAgICAvLyBUT0RPOiBuZXN0ZWQgcHJlc2VyaWFsaXphdGlvbiAoc28gaW5jcmVhc2UgcGVyZm9ybWFuY2Ugd2hlbiBkZXNlcmlhbGl6aW5nKVxuICAgIC8vIFRPRE86IFZlcmlmeSB3aHkgdGhlcmUgaXMgbm8gbWV0YWRhdGFcbiAgICBjb25zdCB0b1NlcmlhbGl6ZTogUmVjb3JkPHN0cmluZywgYW55PiA9IE9iamVjdC5hc3NpZ24oe30sIG1vZGVsKTtcbiAgICBsZXQgbWV0YWRhdGE7XG4gICAgdHJ5IHtcbiAgICAgIG1ldGFkYXRhID0gTWV0YWRhdGEubW9kZWxOYW1lKG1vZGVsLmNvbnN0cnVjdG9yIGFzIENvbnN0cnVjdG9yKTtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgbWV0YWRhdGEgPSB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHRvU2VyaWFsaXplW01vZGVsS2V5cy5BTkNIT1JdID0gbWV0YWRhdGEgfHwgbW9kZWwuY29uc3RydWN0b3IubmFtZTtcblxuICAgIGNvbnN0IHByZVNlcmlhbGl6ZSA9IGZ1bmN0aW9uIHByZVNlcmlhbGl6ZShcbiAgICAgIHRoaXM6IERldGVybWluaXN0aWNTZXJpYWxpemVyPGFueT4sXG4gICAgICBvYmo6IGFueVxuICAgICk6IGFueSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXRoaXMtYWxpYXNcbiAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgaWYgKHR5cGVvZiBvYmogIT09IFwib2JqZWN0XCIpIHJldHVybiBvYmo7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShvYmopKSByZXR1cm4gb2JqLm1hcCgobykgPT4gcHJlU2VyaWFsaXplLmNhbGwoc2VsZiwgbykpO1xuICAgICAgcmV0dXJuIHRoaXMucHJlU2VyaWFsaXplLmNhbGwodGhpcywgb2JqKTtcbiAgICB9LmJpbmQodGhpcyk7XG5cbiAgICBNb2RlbC5yZWxhdGlvbnMobW9kZWwpLmZvckVhY2goKHIpID0+IHtcbiAgICAgIHRvU2VyaWFsaXplW3JdID0gcHJlU2VyaWFsaXplKHRvU2VyaWFsaXplW3JdKTtcbiAgICB9KTtcbiAgICByZXR1cm4gdG9TZXJpYWxpemU7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgUmVidWlsZHMgYSBtb2RlbCBmcm9tIGEgc2VyaWFsaXphdGlvblxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyXG4gICAqXG4gICAqIEB0aHJvd3Mge0Vycm9yfSBJZiBpdCBmYWlscyB0byBwYXJzZSB0aGUgc3RyaW5nLCBvciB0byBidWlsZCB0aGUgbW9kZWxcbiAgICovXG4gIG92ZXJyaWRlIGRlc2VyaWFsaXplKHN0cjogc3RyaW5nKTogTSB7XG4gICAgY29uc3QgZGVzZXJpYWxpemF0aW9uID0gSlNPTi5wYXJzZShzdHIpO1xuICAgIGNvbnN0IGNsYXNzTmFtZSA9IGRlc2VyaWFsaXphdGlvbltNb2RlbEtleXMuQU5DSE9SXTtcbiAgICBpZiAoIWNsYXNzTmFtZSlcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkNvdWxkIG5vdCBmaW5kIGNsYXNzIHJlZmVyZW5jZSBpbiBzZXJpYWxpemVkIG1vZGVsXCIpO1xuICAgIGNvbnN0IG1vZGVsOiBNID0gTW9kZWwuYnVpbGQoZGVzZXJpYWxpemF0aW9uLCBjbGFzc05hbWUpIGFzIHVua25vd24gYXMgTTtcbiAgICByZXR1cm4gbW9kZWw7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNlcmlhbGl6ZSBhIG1vZGVsIGludG8gYSBkZXRlcm1pbmlzdGljIEpTT04gc3RyaW5nXG4gICAqIEBzdW1tYXJ5IFByZXBhcmVzIHRoZSBtb2RlbCB3aXRoIHByZVNlcmlhbGl6ZSwgc29ydHMga2V5cyByZWN1cnNpdmVseSwgYW5kIHN0cmluZ2lmaWVzIGRldGVybWluaXN0aWNhbGx5IGZvciBzdGFibGUgb3JkZXJpbmdcbiAgICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZSB0byBzZXJpYWxpemVcbiAgICogQHJldHVybiB7c3RyaW5nfSBEZXRlcm1pbmlzdGljIEpTT04gcmVwcmVzZW50YXRpb24gb2YgdGhlIG1vZGVsXG4gICAqL1xuICBvdmVycmlkZSBzZXJpYWxpemUobW9kZWw6IE0pOiBzdHJpbmcge1xuICAgIGNvbnN0IHN0cmluZ2lmeSA9IHJlcXVpcmUoXCJqc29uLXN0cmluZ2lmeS1kZXRlcm1pbmlzdGljXCIpO1xuICAgIGNvbnN0IHNvcnRLZXlzUmVjdXJzaXZlID0gcmVxdWlyZShcInNvcnQta2V5cy1yZWN1cnNpdmVcIik7XG4gICAgcmV0dXJuIHN0cmluZ2lmeShzb3J0S2V5c1JlY3Vyc2l2ZSh0aGlzLnByZVNlcmlhbGl6ZShtb2RlbCkpKTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgRmFicmljQ29udHJhY3RBZGFwdGVyIH0gZnJvbSBcIi4uL0NvbnRyYWN0QWRhcHRlclwiO1xuaW1wb3J0IHsgQ29udHJhY3QsIENvbnRleHQgYXMgQ3R4IH0gZnJvbSBcImZhYnJpYy1jb250cmFjdC1hcGlcIjtcbmltcG9ydCB7IE1vZGVsLCBTZXJpYWxpemVyIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHtcbiAgQ29uZGl0aW9uLFxuICBDb250ZXh0LFxuICBDb250ZXh0dWFsaXplZEFyZ3MsXG4gIERpcmVjdGlvbkxpbWl0T2Zmc2V0LFxuICBMb2dnZXJPZixcbiAgTWF5YmVDb250ZXh0dWFsQXJnLFxuICBPcmRlckRpcmVjdGlvbixcbiAgUmVwb3NpdG9yeSxcbiAgU2VyaWFsaXplZFBhZ2UsXG59IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5IH0gZnJvbSBcIi4uL0ZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeVwiO1xuaW1wb3J0IHsgRGV0ZXJtaW5pc3RpY1NlcmlhbGl6ZXIgfSBmcm9tIFwiLi4vLi4vc2hhcmVkL0RldGVybWluaXN0aWNTZXJpYWxpemVyXCI7XG5pbXBvcnQgeyBNYW5nb1F1ZXJ5IH0gZnJvbSBcIkBkZWNhZi10cy9mb3ItY291Y2hkYlwiO1xuaW1wb3J0IHsgQ2hlY2thYmxlLCBoZWFsdGhjaGVjayB9IGZyb20gXCIuLi8uLi9zaGFyZWQvaW50ZXJmYWNlcy9DaGVja2FibGVcIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdENvbnRleHQgfSBmcm9tIFwiLi4vQ29udHJhY3RDb250ZXh0XCI7XG5pbXBvcnQge1xuICBCdWxrQ3J1ZE9wZXJhdGlvbktleXMsXG4gIEludGVybmFsRXJyb3IsXG4gIE9wZXJhdGlvbktleXMsXG4gIFByaW1hcnlLZXlUeXBlLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IENoYWluY29kZVN0dWIsIENsaWVudElkZW50aXR5IH0gZnJvbSBcImZhYnJpYy1zaGltLWFwaVwiO1xuaW1wb3J0IHsgT2JqZWN0IGFzIEZhYnJpY09iamVjdCB9IGZyb20gXCJmYWJyaWMtY29udHJhY3QtYXBpXCI7XG5cbkZhYnJpY09iamVjdCgpKERhdGUpO1xuLyoqXG4gKiBAZGVzY3JpcHRpb24gQmFzZSBjb250cmFjdCBjbGFzcyBmb3IgQ1JVRCBvcGVyYXRpb25zIGluIEZhYnJpYyBjaGFpbmNvZGVcbiAqIEBzdW1tYXJ5IFByb3ZpZGVzIHN0YW5kYXJkIGNyZWF0ZSwgcmVhZCwgdXBkYXRlLCBhbmQgZGVsZXRlIG9wZXJhdGlvbnMgZm9yIG1vZGVscyBpbiBGYWJyaWMgY2hhaW5jb2RlXG4gKiBAdGVtcGxhdGUgTSAtIFR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAY2xhc3MgRmFicmljQ3J1ZENvbnRyYWN0XG4gKiBAZXh0ZW5kcyB7Q29udHJhY3R9XG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gRGVmaW5lIGEgbW9kZWxcbiAqIEB0YWJsZSgnYXNzZXRzJylcbiAqIGNsYXNzIEFzc2V0IGV4dGVuZHMgTW9kZWwge1xuICogICBAaWQoKVxuICogICBpZDogc3RyaW5nO1xuICpcbiAqICAgQHByb3BlcnR5KClcbiAqICAgZGF0YTogc3RyaW5nO1xuICogfVxuICpcbiAqIC8vIENyZWF0ZSBhIGNvbnRyYWN0IHRoYXQgZXh0ZW5kcyBGYWJyaWNDcnVkQ29udHJhY3RcbiAqIGV4cG9ydCBjbGFzcyBBc3NldENvbnRyYWN0IGV4dGVuZHMgRmFicmljQ3J1ZENvbnRyYWN0PEFzc2V0PiB7XG4gKiAgIGNvbnN0cnVjdG9yKCkge1xuICogICAgIHN1cGVyKCdBc3NldENvbnRyYWN0JywgQXNzZXQpO1xuICogICB9XG4gKlxuICogICAvLyBBZGQgY3VzdG9tIG1ldGhvZHMgYXMgbmVlZGVkXG4gKiAgIGFzeW5jIGdldEFzc2V0SGlzdG9yeShjdHg6IENvbnRleHQsIGlkOiBzdHJpbmcpOiBQcm9taXNlPGFueVtdPiB7XG4gKiAgICAgLy8gQ3VzdG9tIGltcGxlbWVudGF0aW9uXG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAqICAgcGFydGljaXBhbnQgQ29udHJhY3RcbiAqICAgcGFydGljaXBhbnQgUmVwb3NpdG9yeVxuICogICBwYXJ0aWNpcGFudCBBZGFwdGVyXG4gKiAgIHBhcnRpY2lwYW50IFN0YXRlREJcbiAqXG4gKiAgIENsaWVudC0+PkNvbnRyYWN0OiBjcmVhdGUoY3R4LCBtb2RlbClcbiAqICAgQ29udHJhY3QtPj5SZXBvc2l0b3J5OiByZXBvc2l0b3J5KGN0eClcbiAqICAgQ29udHJhY3QtPj5SZXBvc2l0b3J5OiBjcmVhdGUobW9kZWwsIGN0eClcbiAqICAgUmVwb3NpdG9yeS0+PkFkYXB0ZXI6IGNyZWF0ZSh0YWJsZU5hbWUsIGlkLCByZWNvcmQsIHRyYW5zaWVudCwgY3R4KVxuICogICBBZGFwdGVyLT4+U3RhdGVEQjogcHV0U3RhdGUoaWQsIHNlcmlhbGl6ZWREYXRhKVxuICogICBTdGF0ZURCLS0+PkFkYXB0ZXI6IFN1Y2Nlc3NcbiAqICAgQWRhcHRlci0tPj5SZXBvc2l0b3J5OiByZWNvcmRcbiAqICAgUmVwb3NpdG9yeS0tPj5Db250cmFjdDogbW9kZWxcbiAqICAgQ29udHJhY3QtLT4+Q2xpZW50OiBtb2RlbFxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgRmFicmljQ3J1ZENvbnRyYWN0PE0gZXh0ZW5kcyBNb2RlbD5cbiAgZXh0ZW5kcyBDb250cmFjdFxuICBpbXBsZW1lbnRzIENoZWNrYWJsZVxue1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNoYXJlZCBhZGFwdGVyIGluc3RhbmNlIGZvciBhbGwgY29udHJhY3QgaW5zdGFuY2VzXG4gICAqL1xuICBwcm90ZWN0ZWQgc3RhdGljIGFkYXB0ZXI6IEZhYnJpY0NvbnRyYWN0QWRhcHRlciA9IG5ldyBGYWJyaWNDb250cmFjdEFkYXB0ZXIoKTtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcmVwbzogRmFicmljQ29udHJhY3RSZXBvc2l0b3J5PE0+O1xuXG4gIHByb3RlY3RlZCBzdGF0aWMgcmVhZG9ubHkgc2VyaWFsaXplciA9IG5ldyBEZXRlcm1pbmlzdGljU2VyaWFsaXplcigpO1xuXG4gIHByb3RlY3RlZCBpbml0aWFsaXplZDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIG5ldyBGYWJyaWNDcnVkQ29udHJhY3QgaW5zdGFuY2VcbiAgICogQHN1bW1hcnkgSW5pdGlhbGl6ZXMgYSBjb250cmFjdCB3aXRoIGEgbmFtZSBhbmQgbW9kZWwgY2xhc3NcbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgY29udHJhY3RcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gY2xhenogLSBUaGUgbW9kZWwgY29uc3RydWN0b3JcbiAgICovXG4gIHByb3RlY3RlZCBjb25zdHJ1Y3RvcihcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IGNsYXp6OiBDb25zdHJ1Y3RvcjxNPlxuICApIHtcbiAgICBzdXBlcihuYW1lKTtcbiAgICB0aGlzLnJlcG8gPSBSZXBvc2l0b3J5LmZvck1vZGVsKGNsYXp6KTtcbiAgfVxuXG4gIGFzeW5jIGxpc3RCeShcbiAgICBjdHg6IEN0eCB8IEZhYnJpY0NvbnRyYWN0Q29udGV4dCxcbiAgICBrZXk6IHN0cmluZyB8IGtleW9mIE0sXG4gICAgb3JkZXI6IHN0cmluZyxcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPE1bXSB8IHN0cmluZz4ge1xuICAgIGNvbnN0IHsgY3R4QXJncywgbG9nIH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbLi4uYXJncywgY3R4XSwgdGhpcy5saXN0QnkpO1xuICAgIGxvZy5pbmZvKFxuICAgICAgYFJ1bm5pbmcgbGlzdEJ5IGtleSAke2tleSBhcyBzdHJpbmd9LCBvcmRlciAke29yZGVyfSBhbmQgYXJncyAke2N0eEFyZ3N9YFxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMucmVwby5saXN0QnkoXG4gICAgICBrZXkgYXMga2V5b2YgTSxcbiAgICAgIG9yZGVyIGFzIE9yZGVyRGlyZWN0aW9uLFxuICAgICAgLi4uY3R4QXJnc1xuICAgICk7XG4gIH1cblxuICBhc3luYyBwYWdpbmF0ZUJ5KFxuICAgIGN0eDogQ3R4IHwgRmFicmljQ29udHJhY3RDb250ZXh0LFxuICAgIGtleTogc3RyaW5nIHwga2V5b2YgTSxcbiAgICBvcmRlcjogc3RyaW5nLFxuICAgIHJlZjogT21pdDxEaXJlY3Rpb25MaW1pdE9mZnNldCwgXCJkaXJlY3Rpb25cIj4gfCBzdHJpbmcgPSB7XG4gICAgICBvZmZzZXQ6IDEsXG4gICAgICBsaW1pdDogMTAsXG4gICAgfSxcbiAgICAuLi5hcmdzOiBNYXliZUNvbnRleHR1YWxBcmc8RmFicmljQ29udHJhY3RDb250ZXh0PlxuICApOiBQcm9taXNlPFNlcmlhbGl6ZWRQYWdlPE0+IHwgc3RyaW5nPiB7XG4gICAgY29uc3QgeyBjdHhBcmdzLCBsb2cgfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFsuLi5hcmdzLCBjdHhdLCB0aGlzLnBhZ2luYXRlQnkpO1xuICAgIGxvZy5pbmZvKFxuICAgICAgYFJ1bm5pbmcgcGFnaW5hdGVCeSBrZXkgJHtrZXkgYXMgc3RyaW5nfSwgb3JkZXIgJHtvcmRlcn0gd2l0aCBzaXplICR7KHJlZiBhcyBhbnkpLmxpbWl0fSBhbmQgYXJncyAke2N0eEFyZ3N9YFxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMucmVwby5wYWdpbmF0ZUJ5KFxuICAgICAga2V5IGFzIGtleW9mIE0sXG4gICAgICBvcmRlciBhcyBhbnksXG4gICAgICByZWYgYXMgYW55LFxuICAgICAgLi4uY3R4QXJnc1xuICAgICk7XG4gIH1cblxuICBhc3luYyBmaW5kT25lQnkoXG4gICAgY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAga2V5OiBzdHJpbmcgfCBrZXlvZiBNLFxuICAgIHZhbHVlOiBhbnksXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxNIHwgc3RyaW5nPiB7XG4gICAgY29uc3QgeyBjdHhBcmdzLCBsb2cgfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFsuLi5hcmdzLCBjdHhdLCB0aGlzLmZpbmRPbmVCeSk7XG4gICAgbG9nLmluZm8oXG4gICAgICBgUnVubmluZyBmaW5kT25lQnkga2V5ICR7a2V5IGFzIHN0cmluZ30sIHZhbHVlOiAke3ZhbHVlfSB3aXRoIGFyZ3MgJHtjdHhBcmdzfWBcbiAgICApO1xuICAgIHJldHVybiB0aGlzLnJlcG8uZmluZE9uZUJ5KGtleSBhcyBrZXlvZiBNLCB2YWx1ZSwgLi4uY3R4QXJncyk7XG4gIH1cblxuICBhc3luYyBzdGF0ZW1lbnQoXG4gICAgY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAgbWV0aG9kOiBzdHJpbmcsXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCB7IGN0eEFyZ3MsIGxvZyB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGN0eF0sIHRoaXMuc3RhdGVtZW50KTtcbiAgICBsb2cuaW5mbyhgUnVubmluZyBzdGF0ZW1lbnQgJHttZXRob2R9IHdpdGggYXJncyAke2N0eEFyZ3N9YCk7XG4gICAgcmV0dXJuIHRoaXMucmVwby5zdGF0ZW1lbnQobWV0aG9kLCAuLi5jdHhBcmdzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIHNpbmdsZSBtb2RlbCBpbiB0aGUgc3RhdGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgRGVsZWdhdGVzIHRvIHRoZSByZXBvc2l0b3J5J3MgY3JlYXRlIG1ldGhvZFxuICAgKiBAcGFyYW0ge0N0eH0gY3R4IC0gVGhlIEZhYnJpYyBjaGFpbmNvZGUgY29udGV4dFxuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIHRvIGNyZWF0ZVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICogQHJldHVybiB7UHJvbWlzZTxNPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIGNyZWF0ZWQgbW9kZWxcbiAgICovXG4gIGFzeW5jIGNyZWF0ZShcbiAgICBjdHg6IEN0eCB8IEZhYnJpY0NvbnRyYWN0Q29udGV4dCxcbiAgICBtb2RlbDogc3RyaW5nIHwgTSxcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPHN0cmluZyB8IE0+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4QXJncyB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGN0eF0sIHRoaXMuY3JlYXRlKTtcbiAgICBsb2cuaW5mbyhgQ09OVFJBQ1QgQ1JFQVRFLCAke2N0eEFyZ3N9YCk7XG5cbiAgICBpZiAodHlwZW9mIG1vZGVsID09PSBcInN0cmluZ1wiKSBtb2RlbCA9IHRoaXMuZGVzZXJpYWxpemU8TT4obW9kZWwpIGFzIE07XG5cbiAgICBsb2cuaW5mbyhgQ3JlYXRpbmcgbW9kZWw6ICR7SlNPTi5zdHJpbmdpZnkobW9kZWwpfWApO1xuXG4gICAgY29uc3QgdHJhbnNpZW50ID0gdGhpcy5nZXRUcmFuc2llbnREYXRhKGN0eCk7XG5cbiAgICBsb2cuaW5mbyhgTWVyZ2luZyB0cmFuc2llbnQgZGF0YS4uLmApO1xuICAgIG1vZGVsID0gTW9kZWwubWVyZ2UobW9kZWwsIHRyYW5zaWVudCwgdGhpcy5jbGF6eikgYXMgTTtcblxuICAgIHJldHVybiB0aGlzLnJlcG8uY3JlYXRlKG1vZGVsLCAuLi5jdHhBcmdzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVhZHMgYSBzaW5nbGUgbW9kZWwgZnJvbSB0aGUgc3RhdGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgRGVsZWdhdGVzIHRvIHRoZSByZXBvc2l0b3J5J3MgcmVhZCBtZXRob2RcbiAgICogQHBhcmFtIHtDdHh9IGN0eCAtIFRoZSBGYWJyaWMgY2hhaW5jb2RlIGNvbnRleHRcbiAgICogQHBhcmFtIHtzdHJpbmcgfCBudW1iZXJ9IGtleSAtIFRoZSBrZXkgb2YgdGhlIG1vZGVsIHRvIHJlYWRcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TT59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSByZXRyaWV2ZWQgbW9kZWxcbiAgICovXG4gIGFzeW5jIHJlYWQoXG4gICAgY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAga2V5OiBQcmltYXJ5S2V5VHlwZSB8IHN0cmluZyxcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPE0gfCBzdHJpbmc+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4QXJncyB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGN0eF0sIHRoaXMucmVhZCk7XG5cbiAgICBsb2cuaW5mbyhgcmVhZGluZyBlbnRyeSB3aXRoIHBrICR7a2V5fSBgKTtcblxuICAgIHJldHVybiB0aGlzLnJlcG8ucmVhZChrZXksIC4uLmN0eEFyZ3MpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldFRyYW5zaWVudERhdGEoY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQpOiBhbnkge1xuICAgIGNvbnN0IHRyYW5zaWVudE1hcCA9IGN0eC5zdHViLmdldFRyYW5zaWVudCgpO1xuICAgIGxldCB0cmFuc2llbnQ6IGFueSA9IHt9O1xuXG4gICAgaWYgKHRyYW5zaWVudE1hcC5oYXMoKHRoaXMucmVwbyBhcyBhbnkpLnRhYmxlTmFtZSkpIHtcbiAgICAgIHRyYW5zaWVudCA9IEpTT04ucGFyc2UoXG4gICAgICAgICh0cmFuc2llbnRNYXAuZ2V0KCh0aGlzLnJlcG8gYXMgYW55KS50YWJsZU5hbWUpIGFzIEJ1ZmZlcik/LnRvU3RyaW5nKFxuICAgICAgICAgIFwidXRmOFwiXG4gICAgICAgICkgYXMgc3RyaW5nXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiB0cmFuc2llbnQ7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgYSBzaW5nbGUgbW9kZWwgaW4gdGhlIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBzdW1tYXJ5IERlbGVnYXRlcyB0byB0aGUgcmVwb3NpdG9yeSdzIHVwZGF0ZSBtZXRob2RcbiAgICogQHBhcmFtIHtDdHh9IGN0eCAtIFRoZSBGYWJyaWMgY2hhaW5jb2RlIGNvbnRleHRcbiAgICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCB0byB1cGRhdGVcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TT59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSB1cGRhdGVkIG1vZGVsXG4gICAqL1xuICBhc3luYyB1cGRhdGUoXG4gICAgY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAgbW9kZWw6IHN0cmluZyB8IE0sXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxzdHJpbmcgfCBNPiB7XG4gICAgY29uc3QgeyBsb2csIGN0eEFyZ3MgfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFsuLi5hcmdzLCBjdHhdLCB0aGlzLnVwZGF0ZSk7XG5cbiAgICBpZiAodHlwZW9mIG1vZGVsID09PSBcInN0cmluZ1wiKSBtb2RlbCA9IHRoaXMuZGVzZXJpYWxpemU8TT4obW9kZWwpIGFzIE07XG5cbiAgICBsb2cuaW5mbyhgVXBkYXRpbmcgbW9kZWw6ICR7SlNPTi5zdHJpbmdpZnkobW9kZWwpfWApO1xuXG4gICAgY29uc3QgdHJhbnNpZW50ID0gdGhpcy5nZXRUcmFuc2llbnREYXRhKGN0eCk7XG5cbiAgICBsb2cuaW5mbyhgTWVyZ2luZyB0cmFuc2llbnQgZGF0YS4uLmApO1xuICAgIG1vZGVsID0gTW9kZWwubWVyZ2UobW9kZWwsIHRyYW5zaWVudCwgdGhpcy5jbGF6eikgYXMgTTtcbiAgICByZXR1cm4gdGhpcy5yZXBvLnVwZGF0ZShtb2RlbCwgLi4uY3R4QXJncyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERlbGV0ZXMgYSBzaW5nbGUgbW9kZWwgZnJvbSB0aGUgc3RhdGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgRGVsZWdhdGVzIHRvIHRoZSByZXBvc2l0b3J5J3MgZGVsZXRlIG1ldGhvZFxuICAgKiBAcGFyYW0ge0N0eH0gY3R4IC0gVGhlIEZhYnJpYyBjaGFpbmNvZGUgY29udGV4dFxuICAgKiBAcGFyYW0ge3N0cmluZyB8IG51bWJlcn0ga2V5IC0gVGhlIGtleSBvZiB0aGUgbW9kZWwgdG8gZGVsZXRlXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50c1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPE0+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgZGVsZXRlZCBtb2RlbFxuICAgKi9cbiAgYXN5bmMgZGVsZXRlKFxuICAgIGN0eDogQ3R4IHwgRmFicmljQ29udHJhY3RDb250ZXh0LFxuICAgIGtleTogUHJpbWFyeUtleVR5cGUgfCBzdHJpbmcsXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxNIHwgc3RyaW5nPiB7XG4gICAgY29uc3QgeyBsb2csIGN0eEFyZ3MgfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFsuLi5hcmdzLCBjdHhdLCB0aGlzLmRlbGV0ZSk7XG4gICAgbG9nLmluZm8oYGRlbGV0aW5nIGVudHJ5IHdpdGggcGsgJHtrZXl9IGApO1xuICAgIHJldHVybiB0aGlzLnJlcG8uZGVsZXRlKFN0cmluZyhrZXkpLCAuLi5jdHhBcmdzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRGVsZXRlcyBtdWx0aXBsZSBtb2RlbHMgZnJvbSB0aGUgc3RhdGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgRGVsZWdhdGVzIHRvIHRoZSByZXBvc2l0b3J5J3MgZGVsZXRlQWxsIG1ldGhvZFxuICAgKiBAcGFyYW0ge3N0cmluZ1tdIHwgbnVtYmVyW119IGtleXMgLSBUaGUga2V5cyBvZiB0aGUgbW9kZWxzIHRvIGRlbGV0ZVxuICAgKiBAcGFyYW0ge0N0eH0gY3R4IC0gVGhlIEZhYnJpYyBjaGFpbmNvZGUgY29udGV4dFxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICogQHJldHVybiB7UHJvbWlzZTxNW10+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgZGVsZXRlZCBtb2RlbHNcbiAgICovXG4gIGFzeW5jIGRlbGV0ZUFsbChcbiAgICBjdHg6IEN0eCB8IEZhYnJpY0NvbnRyYWN0Q29udGV4dCxcbiAgICBrZXlzOiBQcmltYXJ5S2V5VHlwZVtdIHwgc3RyaW5nLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8TVtdIHwgc3RyaW5nPiB7XG4gICAgY29uc3QgeyBjdHhBcmdzIH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbLi4uYXJncywgY3R4XSwgdGhpcy5yZWFkQWxsKTtcbiAgICBpZiAodHlwZW9mIGtleXMgPT09IFwic3RyaW5nXCIpIGtleXMgPSBKU09OLnBhcnNlKGtleXMpIGFzIHN0cmluZ1tdO1xuICAgIHJldHVybiB0aGlzLnJlcG8uZGVsZXRlQWxsKGtleXMsIC4uLmN0eEFyZ3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWFkcyBtdWx0aXBsZSBtb2RlbHMgZnJvbSB0aGUgc3RhdGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgRGVsZWdhdGVzIHRvIHRoZSByZXBvc2l0b3J5J3MgcmVhZEFsbCBtZXRob2RcbiAgICogQHBhcmFtIHtDdHh9IGN0eCAtIFRoZSBGYWJyaWMgY2hhaW5jb2RlIGNvbnRleHRcbiAgICogQHBhcmFtIHtzdHJpbmdbXSB8IG51bWJlcltdfSBrZXlzIC0gVGhlIGtleXMgb2YgdGhlIG1vZGVscyB0byByZWFkXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50c1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPE1bXT59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSByZXRyaWV2ZWQgbW9kZWxzXG4gICAqL1xuICBhc3luYyByZWFkQWxsKFxuICAgIGN0eDogQ3R4IHwgRmFicmljQ29udHJhY3RDb250ZXh0LFxuICAgIGtleXM6IFByaW1hcnlLZXlUeXBlW10gfCBzdHJpbmcsXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxNW10gfCBzdHJpbmc+IHtcbiAgICBjb25zdCB7IGN0eEFyZ3MgfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFsuLi5hcmdzLCBjdHhdLCB0aGlzLnJlYWRBbGwpO1xuICAgIGlmICh0eXBlb2Yga2V5cyA9PT0gXCJzdHJpbmdcIikga2V5cyA9IEpTT04ucGFyc2Uoa2V5cykgYXMgc3RyaW5nW107XG4gICAgcmV0dXJuIHRoaXMucmVwby5yZWFkQWxsKGtleXMsIC4uLmN0eEFyZ3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBVcGRhdGVzIG11bHRpcGxlIG1vZGVscyBpbiB0aGUgc3RhdGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgRGVsZWdhdGVzIHRvIHRoZSByZXBvc2l0b3J5J3MgdXBkYXRlQWxsIG1ldGhvZFxuICAgKiBAcGFyYW0ge0N0eH0gY3R4IC0gVGhlIEZhYnJpYyBjaGFpbmNvZGUgY29udGV4dFxuICAgKiBAcGFyYW0ge01bXX0gbW9kZWxzIC0gVGhlIG1vZGVscyB0byB1cGRhdGVcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TVtdPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHVwZGF0ZWQgbW9kZWxzXG4gICAqL1xuICBhc3luYyB1cGRhdGVBbGwoXG4gICAgY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAgbW9kZWxzOiBzdHJpbmcgfCBNW10sXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxzdHJpbmcgfCBNW10+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4QXJncyB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGN0eF0sIHRoaXMudXBkYXRlQWxsKTtcbiAgICBpZiAodHlwZW9mIG1vZGVscyA9PT0gXCJzdHJpbmdcIilcbiAgICAgIG1vZGVscyA9IChKU09OLnBhcnNlKG1vZGVscykgYXMgW10pXG4gICAgICAgIC5tYXAoKG0pID0+IHRoaXMuZGVzZXJpYWxpemUobSkpXG4gICAgICAgIC5tYXAoKG0pID0+IG5ldyB0aGlzLmNsYXp6KG0pKSBhcyBhbnk7XG5cbiAgICBsb2cuaW5mbyhgdXBkYXRpbmcgJHttb2RlbHMubGVuZ3RofSBlbnRyaWVzIHRvIHRoZSB0YWJsZWApO1xuICAgIHJldHVybiB0aGlzLnJlcG8udXBkYXRlQWxsKG1vZGVscyBhcyB1bmtub3duIGFzIE1bXSwgLi4uY3R4QXJncyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEV4ZWN1dGVzIGEgcXVlcnkgd2l0aCB0aGUgc3BlY2lmaWVkIGNvbmRpdGlvbnMgYW5kIG9wdGlvbnMuXG4gICAqIEBzdW1tYXJ5IFByb3ZpZGVzIGEgc2ltcGxpZmllZCB3YXkgdG8gcXVlcnkgdGhlIGRhdGFiYXNlIHdpdGggY29tbW9uIHF1ZXJ5IHBhcmFtZXRlcnMuXG4gICAqIEBwYXJhbSB7Q29uZGl0aW9uPE0+fSBjb25kaXRpb24gLSBUaGUgY29uZGl0aW9uIHRvIGZpbHRlciByZWNvcmRzLlxuICAgKiBAcGFyYW0gb3JkZXJCeSAtIFRoZSBmaWVsZCB0byBvcmRlciByZXN1bHRzIGJ5LlxuICAgKiBAcGFyYW0ge09yZGVyRGlyZWN0aW9ufSBbb3JkZXI9T3JkZXJEaXJlY3Rpb24uQVNDXSAtIFRoZSBzb3J0IGRpcmVjdGlvbi5cbiAgICogQHBhcmFtIHtudW1iZXJ9IFtsaW1pdF0gLSBPcHRpb25hbCBtYXhpbXVtIG51bWJlciBvZiByZXN1bHRzIHRvIHJldHVybi5cbiAgICogQHBhcmFtIHtudW1iZXJ9IFtza2lwXSAtIE9wdGlvbmFsIG51bWJlciBvZiByZXN1bHRzIHRvIHNraXAuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TVtdPn0gVGhlIHF1ZXJ5IHJlc3VsdHMgYXMgbW9kZWwgaW5zdGFuY2VzLlxuICAgKi9cbiAgYXN5bmMgcXVlcnkoXG4gICAgY29udGV4dDogQ3R4IHwgRmFicmljQ29udHJhY3RDb250ZXh0LFxuICAgIGNvbmRpdGlvbjogQ29uZGl0aW9uPE0+IHwgc3RyaW5nLFxuICAgIG9yZGVyQnk6IHN0cmluZyB8IGtleW9mIE0sXG4gICAgb3JkZXI6IE9yZGVyRGlyZWN0aW9uIHwgc3RyaW5nID0gT3JkZXJEaXJlY3Rpb24uQVNDLFxuICAgIGxpbWl0PzogbnVtYmVyLFxuICAgIHNraXA/OiBudW1iZXIsXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxNW10gfCBzdHJpbmc+IHtcbiAgICBjb25zdCB7IGN0eEFyZ3MgfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFsuLi5hcmdzLCBjb250ZXh0XSwgdGhpcy5xdWVyeSk7XG4gICAgcmV0dXJuIHRoaXMucmVwby5xdWVyeShcbiAgICAgIGNvbmRpdGlvbiBhcyBDb25kaXRpb248TT4sXG4gICAgICBvcmRlckJ5IGFzIGtleW9mIE0sXG4gICAgICBvcmRlciBhcyBPcmRlckRpcmVjdGlvbixcbiAgICAgIGxpbWl0LFxuICAgICAgc2tpcCxcbiAgICAgIC4uLmN0eEFyZ3NcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBFeGVjdXRlcyBhIHJhdyBxdWVyeSBhZ2FpbnN0IHRoZSBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBEZWxlZ2F0ZXMgdG8gdGhlIHJlcG9zaXRvcnkncyByYXcgbWV0aG9kXG4gICAqIEBwYXJhbSB7Q3R4fSBjdHggLSBUaGUgRmFicmljIGNoYWluY29kZSBjb250ZXh0XG4gICAqIEBwYXJhbSB7YW55fSByYXdJbnB1dCAtIFRoZSBxdWVyeSB0byBleGVjdXRlXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gZG9jc09ubHkgLSBXaGV0aGVyIHRvIHJldHVybiBvbmx5IGRvY3VtZW50c1xuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICogQHJldHVybiB7UHJvbWlzZTxhbnk+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgcXVlcnkgcmVzdWx0c1xuICAgKi9cbiAgYXN5bmMgcmF3KFxuICAgIGN0eDogQ3R4IHwgRmFicmljQ29udHJhY3RDb250ZXh0LFxuICAgIHJhd0lucHV0OiBNYW5nb1F1ZXJ5LFxuICAgIGRvY3NPbmx5OiBib29sZWFuLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8YW55PiB7XG4gICAgY29uc3QgeyBjdHhBcmdzIH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbLi4uYXJncywgY3R4XSwgdGhpcy5yYXcpO1xuICAgIHJldHVybiBGYWJyaWNDcnVkQ29udHJhY3QuYWRhcHRlci5yYXcocmF3SW5wdXQsIGRvY3NPbmx5LCAuLi5jdHhBcmdzKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBzZXJpYWxpemUobW9kZWw6IE0pOiBzdHJpbmcge1xuICAgIHJldHVybiBGYWJyaWNDcnVkQ29udHJhY3Quc2VyaWFsaXplci5zZXJpYWxpemUobW9kZWwpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGRlc2VyaWFsaXplPE0gZXh0ZW5kcyBNb2RlbD4oc3RyOiBzdHJpbmcpOiBNIHtcbiAgICByZXR1cm4gKFxuICAgICAgRmFicmljQ3J1ZENvbnRyYWN0LnNlcmlhbGl6ZXIgYXMgdW5rbm93biBhcyBTZXJpYWxpemVyPE0+XG4gICAgKS5kZXNlcmlhbGl6ZShzdHIpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGluaXQoY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB7IGxvZyB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2N0eF0sIHRoaXMuaW5pdCk7XG4gICAgbG9nLmluZm8oYFJ1bm5pbmcgY29udHJhY3QgJHt0aGlzLmdldE5hbWUoKX0gaW5pdGlhbGl6YXRpb24uLi5gKTtcbiAgICB0aGlzLmluaXRpYWxpemVkID0gdHJ1ZTtcbiAgICBsb2cuaW5mbyhgQ29udHJhY3QgaW5pdGlhbGl6YXRpb24gY29tcGxldGVkLmApO1xuICB9XG5cbiAgYXN5bmMgaGVhbHRoY2hlY2soXG4gICAgY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHRcbiAgKTogUHJvbWlzZTxzdHJpbmcgfCBoZWFsdGhjaGVjaz4ge1xuICAgIGNvbnN0IHsgbG9nIH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY3R4XSwgdGhpcy5oZWFsdGhjaGVjayk7XG4gICAgbG9nLmluZm8oYFJ1bm5pbmcgSGVhbHRoY2hlY2s6ICR7dGhpcy5pbml0aWFsaXplZH0uLi5gKTtcbiAgICByZXR1cm4geyBoZWFsdGhjaGVjazogdGhpcy5pbml0aWFsaXplZCB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIG11bHRpcGxlIG1vZGVscyBpbiB0aGUgc3RhdGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgRGVsZWdhdGVzIHRvIHRoZSByZXBvc2l0b3J5J3MgY3JlYXRlQWxsIG1ldGhvZFxuICAgKiBAcGFyYW0ge0N0eH0gY3R4IC0gVGhlIEZhYnJpYyBjaGFpbmNvZGUgY29udGV4dFxuICAgKiBAcGFyYW0ge01bXX0gbW9kZWxzIC0gVGhlIG1vZGVscyB0byBjcmVhdGVcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TVtdPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIGNyZWF0ZWQgbW9kZWxzXG4gICAqL1xuICBhc3luYyBjcmVhdGVBbGwoXG4gICAgY3R4OiBDdHggfCBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAgbW9kZWxzOiBzdHJpbmcgfCBNW10sXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxzdHJpbmcgfCBNW10+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4QXJncyB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGN0eF0sIHRoaXMuY3JlYXRlQWxsKTtcblxuICAgIGlmICh0eXBlb2YgbW9kZWxzID09PSBcInN0cmluZ1wiKVxuICAgICAgbW9kZWxzID0gKEpTT04ucGFyc2UobW9kZWxzKSBhcyBbXSlcbiAgICAgICAgLm1hcCgobSkgPT4gdGhpcy5kZXNlcmlhbGl6ZShtKSlcbiAgICAgICAgLm1hcCgobSkgPT4gbmV3IHRoaXMuY2xhenoobSkpIGFzIGFueTtcblxuICAgIGxvZy5pbmZvKGBhZGRpbmcgJHttb2RlbHMubGVuZ3RofSBlbnRyaWVzIHRvIHRoZSB0YWJsZWApO1xuICAgIHJldHVybiB0aGlzLnJlcG8uY3JlYXRlQWxsKG1vZGVscyBhcyB1bmtub3duIGFzIE1bXSwgLi4uY3R4QXJncyk7XG4gIH1cblxuICBhc3luYyBsb2dDdHg8QVJHUyBleHRlbmRzIGFueVtdPihcbiAgICBhcmdzOiBBUkdTLFxuICAgIG1ldGhvZDogKCguLi5hcmdzOiBhbnlbXSkgPT4gYW55KSB8IHN0cmluZ1xuICApOiBQcm9taXNlPFxuICAgIENvbnRleHR1YWxpemVkQXJnczxGYWJyaWNDb250cmFjdENvbnRleHQsIEFSR1M+ICYge1xuICAgICAgc3R1YjogQ2hhaW5jb2RlU3R1YjtcbiAgICAgIGlkZW50aXR5OiBDbGllbnRJZGVudGl0eTtcbiAgICB9XG4gID4ge1xuICAgIHJldHVybiBGYWJyaWNDcnVkQ29udHJhY3QubG9nQ3R4LmJpbmQodGhpcykoYXJncywgbWV0aG9kIGFzIGFueSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgc3RhdGljIGFzeW5jIGxvZ0N0eDxBUkdTIGV4dGVuZHMgYW55W10+KFxuICAgIHRoaXM6IGFueSxcbiAgICBhcmdzOiBBUkdTLFxuICAgIG1ldGhvZDogc3RyaW5nXG4gICk6IFByb21pc2U8XG4gICAgQ29udGV4dHVhbGl6ZWRBcmdzPEZhYnJpY0NvbnRyYWN0Q29udGV4dCwgQVJHUz4gJiB7XG4gICAgICBzdHViOiBDaGFpbmNvZGVTdHViO1xuICAgICAgaWRlbnRpdHk6IENsaWVudElkZW50aXR5O1xuICAgIH1cbiAgPjtcbiAgcHJvdGVjdGVkIHN0YXRpYyBhc3luYyBsb2dDdHg8QVJHUyBleHRlbmRzIGFueVtdPihcbiAgICB0aGlzOiBhbnksXG4gICAgYXJnczogQVJHUyxcbiAgICBtZXRob2Q6ICguLi5hcmdzOiBhbnlbXSkgPT4gYW55XG4gICk6IFByb21pc2U8XG4gICAgQ29udGV4dHVhbGl6ZWRBcmdzPEZhYnJpY0NvbnRyYWN0Q29udGV4dCwgQVJHUz4gJiB7XG4gICAgICBzdHViOiBDaGFpbmNvZGVTdHViO1xuICAgICAgaWRlbnRpdHk6IENsaWVudElkZW50aXR5O1xuICAgIH1cbiAgPjtcbiAgcHJvdGVjdGVkIHN0YXRpYyBhc3luYyBsb2dDdHg8QVJHUyBleHRlbmRzIGFueVtdPihcbiAgICB0aGlzOiBhbnksXG4gICAgYXJnczogQVJHUyxcbiAgICBtZXRob2Q6ICgoLi4uYXJnczogYW55W10pID0+IGFueSkgfCBzdHJpbmdcbiAgKTogUHJvbWlzZTxcbiAgICBDb250ZXh0dWFsaXplZEFyZ3M8RmFicmljQ29udHJhY3RDb250ZXh0LCBBUkdTPiAmIHtcbiAgICAgIHN0dWI6IENoYWluY29kZVN0dWI7XG4gICAgICBpZGVudGl0eTogQ2xpZW50SWRlbnRpdHk7XG4gICAgfVxuICA+IHtcbiAgICBpZiAoYXJncy5sZW5ndGggPCAxKSB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIk5vIGNvbnRleHQgcHJvdmlkZWRcIik7XG4gICAgY29uc3QgY3R4ID0gYXJncy5wb3AoKSBhcyBGYWJyaWNDb250cmFjdENvbnRleHQgfCBDb250ZXh0O1xuICAgIGlmIChjdHggaW5zdGFuY2VvZiBGYWJyaWNDb250cmFjdENvbnRleHQpXG4gICAgICByZXR1cm4ge1xuICAgICAgICBjdHgsXG4gICAgICAgIGxvZzogY3R4LmxvZ2dlci5jbGVhcigpLmZvcih0aGlzKS5mb3IobWV0aG9kKSxcbiAgICAgICAgY3R4QXJnczogWy4uLmFyZ3MsIGN0eF0sXG4gICAgICAgIHN0dWI6IGN0eC5zdHViLFxuICAgICAgICBpZGVudGl0eTogY3R4LmlkZW50aXR5LFxuICAgICAgfTtcblxuICAgIGlmICghKGN0eCBpbnN0YW5jZW9mIEN0eCkpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIk5vIHZhbGlkIGNvbnRleHQgcHJvdmlkZWRcIik7XG5cbiAgICBmdW5jdGlvbiBnZXRPcCgpIHtcbiAgICAgIGlmICh0eXBlb2YgbWV0aG9kID09PSBcInN0cmluZ1wiKSByZXR1cm4gbWV0aG9kO1xuICAgICAgc3dpdGNoIChtZXRob2QubmFtZSkge1xuICAgICAgICBjYXNlIE9wZXJhdGlvbktleXMuQ1JFQVRFOlxuICAgICAgICBjYXNlIE9wZXJhdGlvbktleXMuUkVBRDpcbiAgICAgICAgY2FzZSBPcGVyYXRpb25LZXlzLlVQREFURTpcbiAgICAgICAgY2FzZSBPcGVyYXRpb25LZXlzLkRFTEVURTpcbiAgICAgICAgY2FzZSBCdWxrQ3J1ZE9wZXJhdGlvbktleXMuQ1JFQVRFX0FMTDpcbiAgICAgICAgY2FzZSBCdWxrQ3J1ZE9wZXJhdGlvbktleXMuUkVBRF9BTEw6XG4gICAgICAgIGNhc2UgQnVsa0NydWRPcGVyYXRpb25LZXlzLlVQREFURV9BTEw6XG4gICAgICAgIGNhc2UgQnVsa0NydWRPcGVyYXRpb25LZXlzLkRFTEVURV9BTEw6XG4gICAgICAgICAgcmV0dXJuIG1ldGhvZC5uYW1lO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHJldHVybiBtZXRob2QubmFtZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBvdmVycmlkZXMgPSB7XG4gICAgICBjb3JyZWxhdGlvbklkOiBjdHguc3R1Yi5nZXRUeElEKCksXG4gICAgfTtcbiAgICBjb25zdCBjb250ZXh0ID0gYXdhaXQgRmFicmljQ3J1ZENvbnRyYWN0LmFkYXB0ZXIuY29udGV4dChcbiAgICAgIGdldE9wKCksXG4gICAgICBvdmVycmlkZXMgYXMgYW55LFxuICAgICAgdGhpcy5jbGF6eixcbiAgICAgIGN0eFxuICAgICk7XG5cbiAgICBjb25zdCBsb2cgPSAoXG4gICAgICB0aGlzXG4gICAgICAgID8gY29udGV4dC5sb2dnZXIuZm9yKHRoaXMpLmZvcihtZXRob2QpXG4gICAgICAgIDogY29udGV4dC5sb2dnZXIuY2xlYXIoKS5mb3IodGhpcykuZm9yKG1ldGhvZClcbiAgICApIGFzIExvZ2dlck9mPEZhYnJpY0NvbnRyYWN0Q29udGV4dD47XG4gICAgcmV0dXJuIHtcbiAgICAgIGN0eDogY29udGV4dCxcbiAgICAgIGxvZzogbG9nLFxuICAgICAgc3R1YjogY29udGV4dC5zdHViLFxuICAgICAgaWRlbnRpdHk6IGNvbnRleHQuaWRlbnRpdHksXG4gICAgICBjdHhBcmdzOiBbLi4uYXJncywgY29udGV4dF0sXG4gICAgfTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgRmFicmljQ3J1ZENvbnRyYWN0IH0gZnJvbSBcIi4vY3J1ZC1jb250cmFjdFwiO1xuaW1wb3J0IHsgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBDb250ZXh0IGFzIEN0eCwgVHJhbnNhY3Rpb24gfSBmcm9tIFwiZmFicmljLWNvbnRyYWN0LWFwaVwiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcbmltcG9ydCB7IENvbmRpdGlvbiwgTWF5YmVDb250ZXh0dWFsQXJnLCBPcmRlckRpcmVjdGlvbiB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgU2VyaWFsaXphdGlvbkVycm9yIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdENvbnRleHQgfSBmcm9tIFwiLi4vQ29udHJhY3RDb250ZXh0XCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENSVUQgY29udHJhY3QgdmFyaWFudCB0aGF0IHNlcmlhbGl6ZXMvZGVzZXJpYWxpemVzIHBheWxvYWRzXG4gKiBAc3VtbWFyeSBFeHBvc2VzIHRoZSBzYW1lIENSVUQgb3BlcmF0aW9ucyBhcyBGYWJyaWNDcnVkQ29udHJhY3QgYnV0IHRha2VzIGFuZCByZXR1cm5zIEpTT04gc3RyaW5ncyB0byBmYWNpbGl0YXRlIHNpbXBsZSBjbGllbnQgaW50ZXJhY3Rpb25zLlxuICogQHRlbXBsYXRlIE0gLSBNb2RlbCB0eXBlIGhhbmRsZWQgYnkgdGhpcyBjb250cmFjdFxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBUaGUgY29udHJhY3QgbmFtZVxuICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gY2xhenogLSBUaGUgbW9kZWwgY29uc3RydWN0b3IgdXNlZCB0byBpbnN0YW50aWF0ZSBtb2RlbHMgZnJvbSBKU09OXG4gKiBAcmV0dXJuIHt2b2lkfVxuICogQGNsYXNzIFNlcmlhbGl6ZWRDcnVkQ29udHJhY3RcbiAqIEBleGFtcGxlXG4gKiBjb25zdCBjb250cmFjdCA9IG5ldyBTZXJpYWxpemVkQ3J1ZENvbnRyYWN0PE15TW9kZWw+KCdNeU1vZGVsQ29udHJhY3QnLCBNeU1vZGVsKTtcbiAqIC8vIENsaWVudCBzdWJtaXRzIEpTT04gc3RyaW5nIHBheWxvYWRzIGFuZCByZWNlaXZlcyBKU09OIHN0cmluZyByZXNwb25zZXNcbiAqL1xuZXhwb3J0IGNsYXNzIFNlcmlhbGl6ZWRDcnVkQ29udHJhY3Q8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbj4gZXh0ZW5kcyBGYWJyaWNDcnVkQ29udHJhY3Q8TT4ge1xuICBjb25zdHJ1Y3RvcihuYW1lOiBzdHJpbmcsIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPikge1xuICAgIHN1cGVyKG5hbWUsIGNsYXp6KTtcbiAgfVxuXG4gIEBUcmFuc2FjdGlvbigpXG4gIG92ZXJyaWRlIGFzeW5jIGNyZWF0ZShjb250ZXh0OiBDdHgsIG1vZGVsOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHsgbG9nLCBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5jcmVhdGUpO1xuICAgIGxvZy5pbmZvKGBDcmVhdGluZyBtb2RlbDogJHttb2RlbH1gKTtcblxuICAgIGNvbnN0IG0gPSB0aGlzLmRlc2VyaWFsaXplPE0+KG1vZGVsKTtcblxuICAgIGxvZy5pbmZvKGBNb2RlbCBkZXNlcmlhbGl6ZWQ6ICR7SlNPTi5zdHJpbmdpZnkobSl9YCk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3VwZXIuY3JlYXRlKGN0eCBhcyBhbnksIG0pO1xuXG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplKHJlc3VsdCBhcyBNKTtcbiAgICBsb2cuaW5mbyhgUkVTVUxUOiAke0pTT04uc3RyaW5naWZ5KHJlc3VsdCl9YCk7XG4gICAgbG9nLmluZm8oYFJldHVuaW5nOiAke3NlcmlhbGl6ZWR9YCk7XG4gICAgcmV0dXJuIHNlcmlhbGl6ZWQ7XG4gIH1cblxuICBAVHJhbnNhY3Rpb24oZmFsc2UpXG4gIG92ZXJyaWRlIGFzeW5jIHJlYWQoY29udGV4dDogQ3R4LCBrZXk6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgeyBsb2csIGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLnJlYWQpO1xuICAgIGxvZy5pbmZvKGBSZWFkaW5nIGlkOiAke2tleX1gKTtcbiAgICByZXR1cm4gdGhpcy5zZXJpYWxpemUoKGF3YWl0IHN1cGVyLnJlYWQoY3R4IGFzIGFueSwga2V5KSkgYXMgTSk7XG4gIH1cblxuICBAVHJhbnNhY3Rpb24oKVxuICBvdmVycmlkZSBhc3luYyB1cGRhdGUoY29udGV4dDogQ3R4LCBtb2RlbDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMudXBkYXRlKTtcbiAgICBsb2cuaW5mbyhgVXBkYXRpbmcgbW9kZWw6ICR7bW9kZWx9YCk7XG4gICAgcmV0dXJuIHRoaXMuc2VyaWFsaXplKChhd2FpdCBzdXBlci51cGRhdGUoY3R4IGFzIGFueSwgbW9kZWwpKSBhcyBNKTtcbiAgfVxuXG4gIEBUcmFuc2FjdGlvbigpXG4gIG92ZXJyaWRlIGFzeW5jIGRlbGV0ZShjb250ZXh0OiBDdHgsIGtleTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMuZGVsZXRlKTtcbiAgICBsb2cuaW5mbyhgRGVsZXRpbmcgaWQ6ICR7a2V5fWApO1xuICAgIHJldHVybiB0aGlzLnNlcmlhbGl6ZSgoYXdhaXQgc3VwZXIuZGVsZXRlKGN0eCBhcyBhbnksIGtleSkpIGFzIE0pO1xuICB9XG5cbiAgQFRyYW5zYWN0aW9uKClcbiAgb3ZlcnJpZGUgYXN5bmMgZGVsZXRlQWxsKGNvbnRleHQ6IEN0eCwga2V5czogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBwYXJzZWRLZXlzOiBzdHJpbmdbXSA9IEpTT04ucGFyc2Uoa2V5cyk7XG4gICAgY29uc3QgeyBsb2csIGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLmRlbGV0ZUFsbCk7XG5cbiAgICBsb2cuaW5mbyhgZGVsZXRpbmcgJHtwYXJzZWRLZXlzLmxlbmd0aH0gZW50cmllcyBmcm9tIHRoZSB0YWJsZWApO1xuXG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KFxuICAgICAgKChhd2FpdCBzdXBlci5kZWxldGVBbGwoY3R4IGFzIGFueSwgcGFyc2VkS2V5cykpIGFzIE1bXSkubWFwKFxuICAgICAgICAobSkgPT4gdGhpcy5zZXJpYWxpemUobSkgYXMgc3RyaW5nXG4gICAgICApXG4gICAgKTtcbiAgfVxuXG4gIEBUcmFuc2FjdGlvbihmYWxzZSlcbiAgb3ZlcnJpZGUgYXN5bmMgcmVhZEFsbChjb250ZXh0OiBDdHgsIGtleXM6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgcGFyc2VkS2V5czogc3RyaW5nW10gPSBKU09OLnBhcnNlKGtleXMpO1xuXG4gICAgY29uc3QgeyBsb2csIGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLnJlYWRBbGwpO1xuICAgIGxvZy5pbmZvKGByZWFkaW5nICR7cGFyc2VkS2V5cy5sZW5ndGh9IGVudHJpZXMgZnJvbSB0aGUgdGFibGVgKTtcblxuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShcbiAgICAgICgoYXdhaXQgc3VwZXIucmVhZEFsbChjdHggYXMgYW55LCBwYXJzZWRLZXlzKSkgYXMgTVtdKS5tYXAoKG0pID0+XG4gICAgICAgIHRoaXMuc2VyaWFsaXplKG0pXG4gICAgICApXG4gICAgKTtcbiAgfVxuXG4gIEBUcmFuc2FjdGlvbigpXG4gIG92ZXJyaWRlIGFzeW5jIHVwZGF0ZUFsbChjb250ZXh0OiBDdHgsIG1vZGVsczogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCB7IGxvZywgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMudXBkYXRlQWxsKTtcbiAgICBjb25zdCBsaXN0OiBzdHJpbmdbXSA9IEpTT04ucGFyc2UobW9kZWxzKTtcbiAgICBjb25zdCBtb2RlbExpc3Q6IE1bXSA9IGxpc3RcbiAgICAgIC5tYXAoKG0pID0+IHRoaXMuZGVzZXJpYWxpemUobSkpXG4gICAgICAubWFwKChtKSA9PiBuZXcgdGhpcy5jbGF6eihtKSk7XG5cbiAgICBsb2cuaW5mbyhgVXBkYXRpbmcgJHttb2RlbExpc3QubGVuZ3RofSBlbnRyaWVzIHRvIHRoZSB0YWJsZWApO1xuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShcbiAgICAgICgoYXdhaXQgc3VwZXIudXBkYXRlQWxsKGN0eCBhcyBhbnksIG1vZGVsTGlzdCkpIGFzIE1bXSkubWFwKFxuICAgICAgICAobSkgPT4gdGhpcy5zZXJpYWxpemUobSkgYXMgc3RyaW5nXG4gICAgICApXG4gICAgKTtcbiAgfVxuXG4gIEBUcmFuc2FjdGlvbihmYWxzZSlcbiAgb3ZlcnJpZGUgYXN5bmMgc3RhdGVtZW50KGNvbnRleHQ6IEN0eCwgbWV0aG9kOiBzdHJpbmcsIGFyZ3M6IHN0cmluZykge1xuICAgIGNvbnN0IHsgY3R4LCBsb2cgfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5zdGF0ZW1lbnQpO1xuICAgIHRyeSB7XG4gICAgICBhcmdzID0gSlNPTi5wYXJzZShhcmdzKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgU2VyaWFsaXphdGlvbkVycm9yKGBJbnZhbGlkIGFyZ3M6ICR7ZX1gKTtcbiAgICB9XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGFyZ3MpKVxuICAgICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihcbiAgICAgICAgYEludmFsaWQgYXJnczogJHtKU09OLnN0cmluZ2lmeShhcmdzKX0uIG11c3QgYmUgYW4gYXJyYXlgXG4gICAgICApO1xuICAgIGxvZy5pbmZvKGBjYWxsaW5nIHByZXBhcmVkIHN0YXRlbWVudCAke21ldGhvZH1gKTtcbiAgICBsb2cuaW5mbyhgd2l0aCBhcmdzICR7YXJnc31gKTtcbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoYXdhaXQgc3VwZXIuc3RhdGVtZW50KGN0eCwgbWV0aG9kLCAuLi5hcmdzKSk7XG4gIH1cblxuICBAVHJhbnNhY3Rpb24oZmFsc2UpXG4gIG92ZXJyaWRlIGFzeW5jIGxpc3RCeShjb250ZXh0OiBDdHgsIGtleTogc3RyaW5nLCBvcmRlcjogc3RyaW5nKSB7XG4gICAgY29uc3QgeyBjdHgsIGxvZyB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLmxpc3RCeSk7XG4gICAgbG9nLmluZm8oYEV4ZWN1dGluZyBsaXN0Qnkgd2l0aCBrZXkgJHtrZXl9IGFuZCBvcmRlciAke29yZGVyfWApO1xuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShcbiAgICAgIGF3YWl0IHN1cGVyLmxpc3RCeShjdHgsIGtleSBhcyBrZXlvZiBNLCBvcmRlciBhcyBPcmRlckRpcmVjdGlvbilcbiAgICApO1xuICB9XG5cbiAgQFRyYW5zYWN0aW9uKGZhbHNlKVxuICBvdmVycmlkZSBhc3luYyBwYWdpbmF0ZUJ5KFxuICAgIGNvbnRleHQ6IEN0eCxcbiAgICBrZXk6IHN0cmluZyxcbiAgICBvcmRlcjogc3RyaW5nLFxuICAgIHJlZjogc3RyaW5nLFxuICAgIC4uLmFyZ3M6IE1heWJlQ29udGV4dHVhbEFyZzxGYWJyaWNDb250cmFjdENvbnRleHQ+XG4gICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgeyBjdHgsIGxvZyB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoWy4uLmFyZ3MsIGNvbnRleHRdLCB0aGlzLnBhZ2luYXRlQnkpO1xuICAgIHRyeSB7XG4gICAgICByZWYgPSBKU09OLnBhcnNlKHJlZik7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihcbiAgICAgICAgYEZhaWxlZCB0byBkZXNlcmlhbGl6ZSBwYWdpbmF0ZUJ5IHJlZmVyZW5jZTogJHtlfWBcbiAgICAgICk7XG4gICAgfVxuICAgIGxvZy5pbmZvKGBFeGVjdXRpbmcgcGFnaW5hdGVCeSB3aXRoIGtleSAke2tleX0gYW5kIG9yZGVyICR7b3JkZXJ9YCk7XG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KFxuICAgICAgYXdhaXQgc3VwZXIucGFnaW5hdGVCeShjdHgsIGtleSwgb3JkZXIgYXMgYW55LCByZWYgYXMgYW55LCAuLi5hcmdzKVxuICAgICk7XG4gIH1cblxuICBAVHJhbnNhY3Rpb24oZmFsc2UpXG4gIG92ZXJyaWRlIGFzeW5jIGZpbmRPbmVCeShcbiAgICBjb250ZXh0OiBDdHgsXG4gICAga2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IHN0cmluZyxcbiAgICAuLi5hcmdzOiBzdHJpbmdbXVxuICApIHtcbiAgICBjb25zdCB7IGN0eCwgbG9nIH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbLi4uYXJncywgY29udGV4dF0sIHRoaXMuZmluZE9uZUJ5KTtcbiAgICBsb2cuaW5mbyhgRXhlY3V0aW5nIGZpbmRPbmVCeSB3aXRoIGtleSAke2tleX0gYW5kIHZhbHVlICR7dmFsdWV9YCk7XG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGF3YWl0IHN1cGVyLmZpbmRPbmVCeShjdHgsIGtleSwgdmFsdWUsIC4uLmFyZ3MpKTtcbiAgfVxuXG4gIC8vIEBUcmFuc2FjdGlvbihmYWxzZSlcbiAgb3ZlcnJpZGUgYXN5bmMgcXVlcnkoXG4gICAgY29udGV4dDogQ3R4LFxuICAgIGNvbmRpdGlvbjogc3RyaW5nLFxuICAgIG9yZGVyQnk6IHN0cmluZyxcbiAgICBvcmRlcjogc3RyaW5nLFxuICAgIGxpbWl0PzogbnVtYmVyLFxuICAgIHNraXA/OiBudW1iZXJcbiAgKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCB7IGN0eCwgbG9nIH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMucXVlcnkpO1xuXG4gICAgbG9nLmluZm8oYEV4ZWN1dGluZyBxdWVyeSBvcmRlcmVkQnkgJHtvcmRlckJ5fSBhbmQgb3JkZXIgJHtvcmRlcn1gKTtcblxuICAgIGxldCBjb25kOiBDb25kaXRpb248YW55PjtcbiAgICB0cnkge1xuICAgICAgY29uZCA9IENvbmRpdGlvbi5mcm9tKEpTT04ucGFyc2UoY29uZGl0aW9uKSk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihgSW52YWxpZCBjb25kaXRpb246ICR7ZX1gKTtcbiAgICB9XG5cbiAgICBsb2cuaW5mbyhgQ29uZGl0aW9uOiAke0pTT04uc3RyaW5naWZ5KGNvbmQpfWApO1xuXG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KFxuICAgICAgYXdhaXQgc3VwZXIucXVlcnkoY3R4LCBjb25kLCBvcmRlckJ5LCBvcmRlciBhcyBhbnksIGxpbWl0LCBza2lwKVxuICAgICk7XG4gIH1cbiAgLy9cbiAgLy8gLy8gQFRyYW5zYWN0aW9uKGZhbHNlKVxuICAvLyBvdmVycmlkZSBhc3luYyByYXcoXG4gIC8vICAgY29udGV4dDogQ3R4LFxuICAvLyAgIHJhd0lucHV0OiBzdHJpbmcsXG4gIC8vICAgZG9jc09ubHk6IGJvb2xlYW4sXG4gIC8vICAgLi4uYXJnczogc3RyaW5nW11cbiAgLy8gKTogUHJvbWlzZTxhbnk+IHtcbiAgLy8gICBjb25zdCB7IGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLnJhdyk7XG4gIC8vICAgY29uc3QgcGFyc2VkSW5wdXQ6IE1hbmdvUXVlcnkgPSBKU09OLnBhcnNlKHJhd0lucHV0KTtcbiAgLy8gICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoYXdhaXQgc3VwZXIucmF3KGN0eCwgcGFyc2VkSW5wdXQsIGRvY3NPbmx5LCAuLi5hcmdzKSk7XG4gIC8vIH1cblxuICBAVHJhbnNhY3Rpb24oKVxuICBvdmVycmlkZSBhc3luYyBpbml0KGN0eDogQ3R4KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgc3VwZXIuaW5pdChjdHgpO1xuICB9XG5cbiAgQFRyYW5zYWN0aW9uKGZhbHNlKVxuICBvdmVycmlkZSBhc3luYyBoZWFsdGhjaGVjayhjb250ZXh0OiBDdHgpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHsgbG9nLCBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy51cGRhdGVBbGwpO1xuICAgIGxvZy5kZWJ1ZyhgUnVubmluZyBIZWFsdGhjaGVjazogJHt0aGlzLmluaXRpYWxpemVkfS4uLmApO1xuICAgIC8vVE9ETzogVFJJTSBOT1QgV09SS0lORyBDSEVDSyBMQVRFUlxuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShhd2FpdCBzdXBlci5oZWFsdGhjaGVjayhjdHggYXMgYW55KSk7XG4gIH1cblxuICBAVHJhbnNhY3Rpb24oKVxuICBvdmVycmlkZSBhc3luYyBjcmVhdGVBbGwoY29udGV4dDogQ3R4LCBtb2RlbHM6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgeyBsb2cgfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5jcmVhdGVBbGwpO1xuICAgIGNvbnN0IGxpc3Q6IHN0cmluZ1tdID0gSlNPTi5wYXJzZShtb2RlbHMpO1xuICAgIGNvbnN0IG1vZGVsTGlzdDogTVtdID0gbGlzdFxuICAgICAgLm1hcCgobSkgPT4gdGhpcy5kZXNlcmlhbGl6ZShtKSlcbiAgICAgIC5tYXAoKG0pID0+IG5ldyB0aGlzLmNsYXp6KG0pKTtcblxuICAgIGxvZy5pbmZvKGBBZGRpbmcgJHttb2RlbExpc3QubGVuZ3RofSBlbnRyaWVzIHRvIHRoZSB0YWJsZWApO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gKGF3YWl0IHN1cGVyLmNyZWF0ZUFsbChjb250ZXh0LCBtb2RlbExpc3QpKSBhcyBNW107XG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHJlc3VsdC5tYXAoKG0pID0+IHRoaXMuc2VyaWFsaXplKG0pIGFzIHN0cmluZykpO1xuICB9XG59XG4iLCJpbXBvcnQgeyBzdHJpbmdGb3JtYXQgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBPdmVyZmxvd0Vycm9yIH0gZnJvbSBcIi4vZXJyb3JzXCI7XG5pbXBvcnQgeyBWYWxpZGF0aW9uRXJyb3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gT3ZlcmZsb3ctc2FmZSBhZGRpdGlvbiBvcGVyYXRpb25cbiAqIEBzdW1tYXJ5IEFkZHMgdHdvIG51bWJlcnMgYW5kIHZlcmlmaWVzIG5vIG92ZXJmbG93IGJ5IHJldmVyc2UtY2hlY2tpbmcgdGhlIG9wZXJhbmRzXG4gKiBAcGFyYW0ge251bWJlcn0gYSAtIEZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7bnVtYmVyfSBiIC0gU2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm4ge251bWJlcn0gVGhlIHN1bSBvZiBhIGFuZCBiXG4gKiBAZnVuY3Rpb24gYWRkXG4gKiBAdGhyb3dzIHtPdmVyZmxvd0Vycm9yfSBvbiBhZGRpdGlvbiBvdmVyZmxvd1xuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItZmFicmljLnNoYXJlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gYWRkKGE6IG51bWJlciwgYjogbnVtYmVyKTogbnVtYmVyIHtcbiAgY29uc3QgYyA9IGEgKyBiO1xuICBpZiAoYSAhPT0gYyAtIGIgfHwgYiAhPT0gYyAtIGEpIHtcbiAgICB0aHJvdyBuZXcgT3ZlcmZsb3dFcnJvcihgQWRkaXRpb24gb3ZlcmZsb3c6ICR7YX0gKyAke2J9YCk7XG4gIH1cbiAgcmV0dXJuIGM7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIE92ZXJmbG93LXNhZmUgc3VidHJhY3Rpb24gb3BlcmF0aW9uXG4gKiBAc3VtbWFyeSBTdWJ0cmFjdHMgYiBmcm9tIGEgYW5kIHZhbGlkYXRlcyBubyBvdmVyZmxvdyBieSByZXZlcnNlLWNoZWNraW5nIHRoZSBvcGVyYW5kc1xuICogQHBhcmFtIHtudW1iZXJ9IGEgLSBNaW51ZW5kXG4gKiBAcGFyYW0ge251bWJlcn0gYiAtIFN1YnRyYWhlbmRcbiAqIEByZXR1cm4ge251bWJlcn0gVGhlIGRpZmZlcmVuY2UgYSAtIGJcbiAqIEBmdW5jdGlvbiBzdWJcbiAqIEB0aHJvd3Mge092ZXJmbG93RXJyb3J9IG9uIHN1YnRhY3Rpb24gb3ZlcmZsb3dcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5zaGFyZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN1YihhOiBudW1iZXIsIGI6IG51bWJlcik6IG51bWJlciB7XG4gIGNvbnN0IGMgPSBhIC0gYjtcbiAgaWYgKGEgIT09IGMgKyBiIHx8IGIgIT09IGEgLSBjKSB7XG4gICAgdGhyb3cgbmV3IE92ZXJmbG93RXJyb3IoYFN1YnRyYWN0aW9uIG92ZXJmbG93OiAke2F9IC0gJHtifWApO1xuICB9XG4gIHJldHVybiBjO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IFNhZmUgSW50ZWdlciBQYXJzZVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmdcbiAqXG4gKiBAZnVuY3Rpb24gc2FmZVBhcnNlSW50XG4gKlxuICogQHRocm93cyB7VmFsaWRhdGlvbkVycm9yfSBpZiBwYXJzZUludCByZXR1cm5zIE5hTlxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5zaGFyZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNhZmVQYXJzZUludChzdHJpbmc6IHN0cmluZyk6IG51bWJlciB7XG4gIC8vIFJlZ3VsYXIgZXhwcmVzc2lvbiB0byBjaGVjayBpZiBzdHJpbmcgb25seSBoYXZlIGRpZ2l0c1xuICBjb25zdCBkaWdpdFJlZ2V4ID0gL15cXGQrJC87XG4gIGlmICghZGlnaXRSZWdleC50ZXN0KHN0cmluZykpIHtcbiAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgc3RyaW5nRm9ybWF0KFwiRmFpbGVkIHRvIHBhcnNlOiB7MH1cIiwgXCJzdHJpbmcgY29udGFpbnMgZGlnaXRzXCIpXG4gICAgKTtcbiAgfVxuICBjb25zdCBwYXJzZWRpbnQgPSBwYXJzZUludChzdHJpbmcpO1xuICBpZiAoaXNOYU4ocGFyc2VkaW50KSkge1xuICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICBzdHJpbmdGb3JtYXQoXCJGYWlsZWQgdG8gcGFyc2U6IHswfVwiLCBcInN0cmluZyBpcyBub3QgYSBwYXJzYWJsZSBpbnRlZ2VyXCIpXG4gICAgKTtcbiAgfVxuICByZXR1cm4gcGFyc2VkaW50O1xufVxuIiwiaW1wb3J0IHsgQmFzZU1vZGVsLCBjb2x1bW4sIHBrLCB0YWJsZSB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgbW9kZWwsIHR5cGUgTW9kZWxBcmcsIHJlcXVpcmVkIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFUkMyMCB0b2tlbiBtZXRhZGF0YSBtb2RlbFxuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhbiBFUkMyMCB0b2tlbiBkZWZpbml0aW9uIHdpdGhpbiB0aGUgRmFicmljIEVSQzIwIHNhbXBsZSwgaW5jbHVkaW5nIG5hbWUsIHN5bWJvbCwgZGVjaW1hbHMsIGFuZCB0aGUgb3duaW5nIGlkZW50aXR5LiBVc2VkIHRvIGRlZmluZSB0aGUgdW5pcXVlIHRva2VuIG1hbmFnZWQgYnkgdGhlIGNvbnRyYWN0LlxuICogQHBhcmFtIHtNb2RlbEFyZzxFUkMyMFRva2VuPn0gW21dIC0gT3B0aW9uYWwgcGFydGlhbCBkYXRhIG9yIGFub3RoZXIgaW5zdGFuY2UgdG8gaW5pdGlhbGl6ZSB0aGUgbW9kZWxcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKiBAY2xhc3MgRVJDMjBUb2tlblxuICogQGV4YW1wbGVcbiAqIGNvbnN0IHRva2VuID0gbmV3IEVSQzIwVG9rZW4oeyBuYW1lOiBcIk15VG9rZW5cIiwgc3ltYm9sOiBcIk1US1wiLCBkZWNpbWFsczogMTgsIG93bmVyOiBcIng1MDk6Oi4uLlwiIH0pO1xuICogLy8gUGVyc2lzdCB0aHJvdWdoIGEgcmVwb3NpdG9yeTogYXdhaXQgcmVwby5jcmVhdGUodG9rZW4sIGN0eClcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQXBwXG4gKiAgIHBhcnRpY2lwYW50IFJlcG9cbiAqICAgcGFydGljaXBhbnQgQWRhcHRlclxuICogICBBcHAtPj5SZXBvOiBjcmVhdGUobmV3IEVSQzIwVG9rZW4oey4uLn0pLCBjdHgpXG4gKiAgIFJlcG8tPj5BZGFwdGVyOiBjcmVhdGUodGFibGUsIGlkPW5hbWUsIHJlY29yZCwgZmxhZ3MpXG4gKiAgIEFkYXB0ZXItLT4+UmVwbzogc3RvcmVkXG4gKiAgIFJlcG8tLT4+QXBwOiBtb2RlbFxuICovXG5AdGFibGUoXCJlcmMyMF90b2tlbnNcIilcbkBtb2RlbCgpXG5leHBvcnQgY2xhc3MgRVJDMjBUb2tlbiBleHRlbmRzIEJhc2VNb2RlbCB7XG4gIEBwayh7IHR5cGU6IFwiU3RyaW5nXCIgfSlcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUb2tlbiB1bmlxdWUgbmFtZVxuICAgKiBAc3VtbWFyeSBTZXJ2ZXMgYXMgdGhlIHByaW1hcnkga2V5IGZvciB0aGUgRVJDMjAgdG9rZW4gZGVmaW5pdGlvbjsgdHlwaWNhbGx5IGEgaHVtYW4tcmVhZGFibGUgaWRlbnRpZmllclxuICAgKi9cbiAgbmFtZSE6IHN0cmluZztcblxuICBAY29sdW1uKClcbiAgQHJlcXVpcmVkKClcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBPd25pbmcgaWRlbnRpdHkgb2YgdGhlIHRva2VuXG4gICAqIEBzdW1tYXJ5IFguNTA5IHN1YmplY3Qgb3IgTVNQIGlkZW50aXR5IHN0cmluZyB0aGF0IGRlbm90ZXMgd2hvIG93bnMvY29udHJvbHMgdGhlIHRva2VuIGRlZmluaXRpb25cbiAgICovXG4gIG93bmVyITogc3RyaW5nO1xuICBAY29sdW1uKClcbiAgQHJlcXVpcmVkKClcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUb2tlbiBzeW1ib2xcbiAgICogQHN1bW1hcnkgU2hvcnQgdGlja2VyLWxpa2Ugc3ltYm9sIHVzZWQgdG8gcmVwcmVzZW50IHRoZSB0b2tlbiAoZS5nLiwgTVRLKVxuICAgKi9cbiAgc3ltYm9sITogc3RyaW5nO1xuICBAY29sdW1uKClcbiAgQHJlcXVpcmVkKClcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEZWNpbWFsIHByZWNpc2lvbiBmb3IgdG9rZW4gYW1vdW50c1xuICAgKiBAc3VtbWFyeSBOdW1iZXIgb2YgZGlnaXRzIGFmdGVyIHRoZSBkZWNpbWFsIHNlcGFyYXRvciB1c2VkIHdoZW4gZm9ybWF0dGluZyB0b2tlbiBiYWxhbmNlc1xuICAgKi9cbiAgZGVjaW1hbHMhOiBudW1iZXI7XG5cbiAgY29uc3RydWN0b3IobT86IE1vZGVsQXJnPEVSQzIwV2FsbGV0Pikge1xuICAgIHN1cGVyKG0pO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVSQzIwIHdhbGxldCBtb2RlbFxuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhIGhvbGRlciBhY2NvdW50IGZvciBhbiBFUkMyMCB0b2tlbiB3aXRoaW4gdGhlIEZhYnJpYyBuZXR3b3JrLCB0cmFja2luZyBiYWxhbmNlIGFuZCB0b2tlbiBhc3NvY2lhdGlvbi5cbiAqIEBwYXJhbSB7TW9kZWxBcmc8RVJDMjBXYWxsZXQ+fSBbbV0gLSBPcHRpb25hbCBwYXJ0aWFsIGRhdGEgb3IgYW5vdGhlciBpbnN0YW5jZSB0byBpbml0aWFsaXplIHRoZSBtb2RlbFxuICogQHJldHVybiB7dm9pZH1cbiAqIEBjbGFzcyBFUkMyMFdhbGxldFxuICogQGV4YW1wbGVcbiAqIGNvbnN0IHdhbGxldCA9IG5ldyBFUkMyMFdhbGxldCh7IGlkOiBcImFjY3QxXCIsIHRva2VuOiBcIk15VG9rZW5cIiwgYmFsYW5jZTogMTAwMCB9KTtcbiAqIC8vIFVwZGF0ZSBiYWxhbmNlIHZpYSByZXBvc2l0b3J5OiBhd2FpdCByZXBvLnVwZGF0ZSh3YWxsZXQsIGN0eClcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQXBwXG4gKiAgIHBhcnRpY2lwYW50IFJlcG9cbiAqICAgQXBwLT4+UmVwbzogcmVhZChcImFjY3QxXCIsIGN0eClcbiAqICAgUmVwby0tPj5BcHA6IEVSQzIwV2FsbGV0XG4gKi9cbkB0YWJsZShcImVyYzIwX3dhbGxldHNcIilcbkBtb2RlbCgpXG5leHBvcnQgY2xhc3MgRVJDMjBXYWxsZXQgZXh0ZW5kcyBCYXNlTW9kZWwge1xuICBAcGsoeyB0eXBlOiBcIlN0cmluZ1wiIH0pXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gV2FsbGV0IHVuaXF1ZSBpZGVudGlmaWVyXG4gICAqIEBzdW1tYXJ5IFByaW1hcnkga2V5IGZvciB0aGUgd2FsbGV0OyBjb21tb25seSByZWZlcmVuY2VzIGFuIGFjY291bnQgb3IgaWRlbnRpdHlcbiAgICovXG4gIGlkITogc3RyaW5nO1xuXG4gIEBjb2x1bW4oKVxuICBAcmVxdWlyZWQoKVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEFzc29jaWF0ZWQgdG9rZW4gbmFtZVxuICAgKiBAc3VtbWFyeSBSZWZlcmVuY2VzIHRoZSBFUkMyMFRva2VuIHRoaXMgd2FsbGV0IGhvbGRzOyBtYWludGFpbmVkIGFzIGEgcmVsYXRpb25zaGlwIGZvciBjYXNjYWRpbmcgdXBkYXRlcy9kZWxldGVzXG4gICAqL1xuICB0b2tlbiE6IHN0cmluZztcblxuICBAY29sdW1uKClcbiAgQHJlcXVpcmVkKClcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUb2tlbiBiYWxhbmNlIGZvciB0aGlzIHdhbGxldFxuICAgKiBAc3VtbWFyeSBDdXJyZW50IGFtb3VudCBvZiB0aGUgYXNzb2NpYXRlZCB0b2tlbiBoZWxkIGJ5IHRoaXMgd2FsbGV0XG4gICAqL1xuICBiYWxhbmNlITogbnVtYmVyO1xuXG4gIEBjb2x1bW4oKVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENhcHRpdmUgZmxhZyBvciBpZGVudGlmaWVyXG4gICAqIEBzdW1tYXJ5IE9wdGlvbmFsIGZpZWxkIHVzZWQgYnkgc29tZSBmbG93cyB0byBtYXJrIG5vbi10cmFuc2ZlcmFibGUgZnVuZHMgb3IgbWFuYWdlZCBjdXN0b2R5XG4gICAqL1xuICBjYXB0aXZlITogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKG0/OiBNb2RlbEFyZzxFUkMyMFdhbGxldD4pIHtcbiAgICBzdXBlcihtKTtcbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFUkMyMCBhbGxvd2FuY2UgbW9kZWxcbiAqIEBzdW1tYXJ5IENhcHR1cmVzIGFuIGFwcHJvdmFsIHJlbGF0aW9uc2hpcCB3aGVyZSBhbiBvd25lciBhbGxvd3MgYSBzcGVuZGVyIHRvIHRyYW5zZmVyIHVwIHRvIGEgY2VydGFpbiB2YWx1ZSBmcm9tIHRoZSBvd25lcidzIHdhbGxldC5cbiAqIEBwYXJhbSB7TW9kZWxBcmc8QWxsb3dhbmNlPn0gW21dIC0gT3B0aW9uYWwgcGFydGlhbCBkYXRhIG9yIGFub3RoZXIgaW5zdGFuY2UgdG8gaW5pdGlhbGl6ZSB0aGUgbW9kZWxcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKiBAY2xhc3MgQWxsb3dhbmNlXG4gKiBAZXhhbXBsZVxuICogY29uc3QgYWxsb3dhbmNlID0gbmV3IEFsbG93YW5jZSh7IG93bmVyOiBcImFjY3QxXCIsIHNwZW5kZXI6IFwiYWNjdDJcIiwgdmFsdWU6IDUwIH0pO1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBBcHBcbiAqICAgQXBwLT4+QXBwOiBuZXcgQWxsb3dhbmNlKHsgb3duZXIsIHNwZW5kZXIsIHZhbHVlIH0pXG4gKi9cbkB0YWJsZShcImVyYzIwX2FsbG93YW5jZXNcIilcbkBtb2RlbCgpXG5leHBvcnQgY2xhc3MgQWxsb3dhbmNlIGV4dGVuZHMgQmFzZU1vZGVsIHtcbiAgQHBrKHsgdHlwZTogXCJTdHJpbmdcIiB9KVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEFsbG93YW5jZSB1bmlxdWUgaWRlbnRpZmllclxuICAgKiBAc3VtbWFyeSBQcmltYXJ5IGtleSBmb3IgdGhlIGFsbG93YW5jZTsgdHlwaWNhbGx5IGEgdW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSBhcHByb3ZhbCByZWxhdGlvbnNoaXBcbiAgICovXG4gIEBjb2x1bW4oKVxuICBAcmVxdWlyZWQoKVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIE93bmVyIHdhbGxldCBpZGVudGlmaWVyXG4gICAqIEBzdW1tYXJ5IFdhbGxldCB0aGF0IGF1dGhvcml6ZXMgdGhlIGFsbG93YW5jZVxuICAgKi9cbiAgb3duZXIhOiBzdHJpbmc7XG5cbiAgQGNvbHVtbigpXG4gIEByZXF1aXJlZCgpXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU3BlbmRlciB3YWxsZXQgaWRlbnRpZmllclxuICAgKiBAc3VtbWFyeSBXYWxsZXQgYWxsb3dlZCB0byBzcGVuZCB1cCB0byB0aGUgYXBwcm92ZWQgdmFsdWUgZnJvbSB0aGUgb3duZXJcbiAgICovXG4gIHNwZW5kZXIhOiBzdHJpbmc7XG5cbiAgQGNvbHVtbigpXG4gIEByZXF1aXJlZCgpXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXBwcm92ZWQgdmFsdWVcbiAgICogQHN1bW1hcnkgTWF4aW11bSB0b2tlbiBhbW91bnQgdGhlIHNwZW5kZXIgbWF5IHRyYW5zZmVyIG9uIGJlaGFsZiBvZiB0aGUgb3duZXJcbiAgICovXG4gIHZhbHVlITogbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKG0/OiBNb2RlbEFyZzxBbGxvd2FuY2U+KSB7XG4gICAgc3VwZXIobSk7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIEF1dGhvcml6YXRpb25FcnJvcixcbiAgUmVwbyxcbiAgQ29udGV4dCxcbiAgVW5zdXBwb3J0ZWRFcnJvcixcbiAgUmVwb3NpdG9yeSxcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQge1xuICBJbnRlcm5hbEVycm9yLFxuICBOb3RGb3VuZEVycm9yLFxuICBvbkNyZWF0ZSxcbiAgb25EZWxldGUsXG4gIG9uUmVhZCxcbiAgb25VcGRhdGUsXG4gIHJlYWRvbmx5LFxuICB0cmFuc2llbnQsXG59IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgTW9kZWwsIHJlcXVpcmVkIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgRmFicmljTW9kZWxLZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgdHlwZSB7IENvbnRleHQgYXMgSExDb250ZXh0IH0gZnJvbSBcImZhYnJpYy1jb250cmFjdC1hcGlcIjtcbmltcG9ydCB7IEZhYnJpY0VSQzIwQ29udHJhY3QgfSBmcm9tIFwiLi4vY29udHJhY3RzL2VyYzIwL2VyYzIwY29udHJhY3RcIjtcbmltcG9ydCB7XG4gIGFwcGx5LFxuICBDb25zdHJ1Y3RvcixcbiAgRGVjb3JhdGlvbixcbiAgbWV0YWRhdGEsXG4gIE1ldGFkYXRhLFxuICBwcm9wTWV0YWRhdGEsXG59IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdGlvblwiO1xuaW1wb3J0IHsgRmFicmljRmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG4vKipcbiAqIERlY29yYXRvciBmb3IgbWFya2luZyBtZXRob2RzIHRoYXQgcmVxdWlyZSBvd25lcnNoaXAgYXV0aG9yaXphdGlvbi5cbiAqIENoZWNrcyB0aGUgb3duZXIgb2YgdGhlIHRva2VuIGJlZm9yZSBhbGxvd2luZyB0aGUgbWV0aG9kIHRvIGJlIGV4ZWN1dGVkLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjbGFzcyBUb2tlbkNvbnRyYWN0IGV4dGVuZHMgQ29udHJhY3Qge1xuICogICBAT3duZXIoKVxuICogICBhc3luYyBNaW50KGN0eDogQ29udGV4dCwgYW1vdW50OiBudW1iZXIpIHtcbiAqICAgICAvLyBNaW50IHRva2VuIGxvZ2ljXG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICpcbiAqIEByZXR1cm5zIHtNZXRob2REZWNvcmF0b3J9IEEgbWV0aG9kIGRlY29yYXRvciB0aGF0IGNoZWNrcyBvd25lcnNoaXAgYXV0aG9yaXphdGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE93bmVyKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKFxuICAgIHRhcmdldDogYW55LFxuICAgIHByb3BlcnR5S2V5OiBzdHJpbmcsXG4gICAgZGVzY3JpcHRvcjogUHJvcGVydHlEZXNjcmlwdG9yXG4gICkge1xuICAgIGNvbnN0IG9yaWdpbmFsTWV0aG9kID0gZGVzY3JpcHRvci52YWx1ZTtcblxuICAgIGRlc2NyaXB0b3IudmFsdWUgPSBhc3luYyBmdW5jdGlvbiAoXG4gICAgICB0aGlzOiBGYWJyaWNFUkMyMENvbnRyYWN0LFxuICAgICAgLi4uYXJnczogYW55W11cbiAgICApIHtcbiAgICAgIGNvbnN0IGN0eDogSExDb250ZXh0ID0gYXJnc1swXTtcbiAgICAgIGNvbnN0IGFjb3VudElkID0gY3R4LmNsaWVudElkZW50aXR5LmdldElEKCk7XG5cbiAgICAgIGNvbnN0IHNlbGVjdCA9IGF3YWl0ICh0aGlzIGFzIEZhYnJpY0VSQzIwQ29udHJhY3QpW1xuICAgICAgICBcInRva2VuUmVwb3NpdG9yeVwiXG4gICAgICBdLnNlbGVjdCgpO1xuXG4gICAgICBjb25zdCB0b2tlbnMgPSBhd2FpdCBzZWxlY3QuZXhlY3V0ZShjdHgpO1xuXG4gICAgICBpZiAodG9rZW5zLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEVycm9yKFwiTm8gdG9rZW5zIGF2YWlhbGJsZVwiKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRva2Vucy5sZW5ndGggPiAxKSB7XG4gICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEVycm9yKGBUbyBtYW55IHRva2VuIGF2YWlsYWJsZSA6ICR7dG9rZW5zLmxlbmd0aH1gKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRva2Vuc1swXS5vd25lciAhPSBhY291bnRJZCkge1xuICAgICAgICB0aHJvdyBuZXcgQXV0aG9yaXphdGlvbkVycm9yKFxuICAgICAgICAgIGBVc2VyIG5vdCBhdXRob3JpemVkIHRvIHJ1biAke3Byb3BlcnR5S2V5fSBvbiB0aGUgdG9rZW5gXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBhd2FpdCBvcmlnaW5hbE1ldGhvZC5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIGRlc2NyaXB0b3I7XG4gIH07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBvd25lZEJ5T25DcmVhdGU8XG4gIE0gZXh0ZW5kcyBNb2RlbDxib29sZWFuPixcbiAgUiBleHRlbmRzIFJlcG88TT4sXG4gIFYsXG4+KFxuICB0aGlzOiBSLFxuICBjb250ZXh0OiBDb250ZXh0PGFueT4sXG4gIGRhdGE6IFYsXG4gIGtleToga2V5b2YgTSxcbiAgbW9kZWw6IE1cbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCB7IHN0dWIgfSA9IGNvbnRleHQgYXMgYW55O1xuXG4gIGNvbnN0IGNyZWF0b3IgPSBhd2FpdCBzdHViLmdldENyZWF0b3IoKTtcbiAgY29uc3Qgb3duZXIgPSBjcmVhdG9yLm1zcGlkO1xuXG4gIGNvbnN0IHNldE93bmVkQnlLZXlWYWx1ZSA9IGZ1bmN0aW9uIDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIHRhcmdldDogTSxcbiAgICBwcm9wZXJ0eUtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnRcbiAgKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgcHJvcGVydHlLZXksIHtcbiAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICB2YWx1ZTogdmFsdWUsXG4gICAgfSk7XG4gIH07XG5cbiAgc2V0T3duZWRCeUtleVZhbHVlKG1vZGVsLCBrZXkgYXMgc3RyaW5nLCBvd25lcik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvd25lZEJ5KCkge1xuICBjb25zdCBrZXkgPSBnZXRGYWJyaWNNb2RlbEtleShGYWJyaWNNb2RlbEtleXMuT1dORURCWSk7XG5cbiAgZnVuY3Rpb24gb3duZWRCeSgpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKG9iajogYW55LCBhdHRyaWJ1dGU/OiBhbnkpIHtcbiAgICAgIHJldHVybiBhcHBseShcbiAgICAgICAgcmVxdWlyZWQoKSxcbiAgICAgICAgcmVhZG9ubHkoKSxcbiAgICAgICAgb25DcmVhdGUob3duZWRCeU9uQ3JlYXRlKSxcbiAgICAgICAgcHJvcE1ldGFkYXRhKGdldEZhYnJpY01vZGVsS2V5KEZhYnJpY01vZGVsS2V5cy5PV05FREJZKSwgYXR0cmlidXRlKVxuICAgICAgKShvYmosIGF0dHJpYnV0ZSk7XG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBEZWNvcmF0aW9uLmZvcihrZXkpXG4gICAgLmRlZmluZSh7XG4gICAgICBkZWNvcmF0b3I6IG93bmVkQnksXG4gICAgICBhcmdzOiBbXSxcbiAgICB9KVxuICAgIC5hcHBseSgpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdHJhbnNhY3Rpb25JZE9uQ3JlYXRlPFxuICBNIGV4dGVuZHMgTW9kZWw8Ym9vbGVhbj4sXG4gIFIgZXh0ZW5kcyBSZXBvPE0+LFxuICBWLFxuPihcbiAgdGhpczogUixcbiAgY29udGV4dDogQ29udGV4dDxhbnk+LFxuICBkYXRhOiBWLFxuICBrZXk6IGtleW9mIE0sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgeyBzdHViIH0gPSBjb250ZXh0IGFzIGFueTtcbiAgbW9kZWxba2V5XSA9IHN0dWIuZ2V0VHhJRCgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdHJhbnNhY3Rpb25JZCgpIHtcbiAgZnVuY3Rpb24gdHJhbnNhY3Rpb25JZCgpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKG9iajogYW55LCBhdHRyaWJ1dGU/OiBhbnkpIHtcbiAgICAgIHJldHVybiBhcHBseShcbiAgICAgICAgcmVxdWlyZWQoKSxcbiAgICAgICAgcmVhZG9ubHkoKSxcbiAgICAgICAgb25DcmVhdGUodHJhbnNhY3Rpb25JZE9uQ3JlYXRlKSxcbiAgICAgICAgb25VcGRhdGUodHJhbnNhY3Rpb25JZE9uQ3JlYXRlKSxcbiAgICAgICAgcHJvcE1ldGFkYXRhKFxuICAgICAgICAgIE1ldGFkYXRhLmtleShcbiAgICAgICAgICAgIEZhYnJpY01vZGVsS2V5cy5GQUJSSUMsXG4gICAgICAgICAgICBhdHRyaWJ1dGUsXG4gICAgICAgICAgICBGYWJyaWNNb2RlbEtleXMuVFJBTlNBQ1RJT05fSURcbiAgICAgICAgICApLFxuICAgICAgICAgIGF0dHJpYnV0ZVxuICAgICAgICApXG4gICAgICApKG9iaiwgYXR0cmlidXRlKTtcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIERlY29yYXRpb24uZm9yKEZhYnJpY01vZGVsS2V5cy5UUkFOU0FDVElPTl9JRClcbiAgICAuZGVmaW5lKHtcbiAgICAgIGRlY29yYXRvcjogdHJhbnNhY3Rpb25JZCxcbiAgICAgIGFyZ3M6IFtdLFxuICAgIH0pXG4gICAgLmFwcGx5KCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRGYWJyaWNNb2RlbEtleShrZXk6IHN0cmluZykge1xuICByZXR1cm4gTWV0YWRhdGEua2V5KEZhYnJpY01vZGVsS2V5cy5GQUJSSUMgKyBrZXkpO1xufVxuXG5leHBvcnQgdHlwZSBDb2xsZWN0aW9uUmVzb2x2ZXIgPSA8TSBleHRlbmRzIE1vZGVsPihtb2RlbDogTSkgPT4gc3RyaW5nO1xuXG5leHBvcnQgY29uc3QgSW1wbGljaXRQcml2YXRlQ29sbGVjdGlvbjogQ29sbGVjdGlvblJlc29sdmVyID0gPE0gZXh0ZW5kcyBNb2RlbD4oXG4gIG1vZGVsOiBNXG4pID0+IHtcbiAgcmV0dXJuIGBfXyR7bW9kZWwuY29uc3RydWN0b3IubmFtZX1Qcml2YXRlQ29sbGVjdGlvbmA7XG59O1xuXG5leHBvcnQgdHlwZSBTZWdyZWdhdGVkRGF0YU1ldGFkYXRhID0ge1xuICBjb2xsZWN0aW9uczogc3RyaW5nIHwgQ29sbGVjdGlvblJlc29sdmVyO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNlZ3JlZ2F0ZWREYXRhT25DcmVhdGU8TSBleHRlbmRzIE1vZGVsPihcbiAgdGhpczogUmVwb3NpdG9yeTxNLCBhbnk+LFxuICBjb250ZXh0OiBDb250ZXh0PEZhYnJpY0ZsYWdzPixcbiAgZGF0YTogU2VncmVnYXRlZERhdGFNZXRhZGF0YVtdLFxuICBrZXlzOiAoa2V5b2YgTSlbXSxcbiAgbW9kZWw6IE1cbik6IFByb21pc2U8dm9pZD4ge1xuICBpZiAoa2V5cy5sZW5ndGggIT09IGRhdGEubGVuZ3RoKVxuICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgYFNlZ3JlZ2F0ZWQgZGF0YSBrZXlzIGFuZCBtZXRhZGF0YSBsZW5ndGggbWlzbWF0Y2hgXG4gICAgKTtcblxuICBjb25zdCBjb2xsZWN0aW9uUmVzb2x2ZXIgPSBkYXRhWzBdLmNvbGxlY3Rpb25zO1xuICBjb25zdCBjb2xsZWN0aW9uID1cbiAgICB0eXBlb2YgY29sbGVjdGlvblJlc29sdmVyID09PSBcInN0cmluZ1wiXG4gICAgICA/IGNvbGxlY3Rpb25SZXNvbHZlclxuICAgICAgOiBjb2xsZWN0aW9uUmVzb2x2ZXIobW9kZWwpO1xuXG4gIGNvbnN0IHJlYnVpbHQgPSBrZXlzLnJlZHVjZShcbiAgICAoYWNjOiBSZWNvcmQ8a2V5b2YgTSwgYW55PiwgaywgaSkgPT4ge1xuICAgICAgY29uc3QgYyA9XG4gICAgICAgIHR5cGVvZiBkYXRhW2ldLmNvbGxlY3Rpb25zID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgPyBkYXRhW2ldLmNvbGxlY3Rpb25zXG4gICAgICAgICAgOiBkYXRhW2ldLmNvbGxlY3Rpb25zKG1vZGVsKTtcbiAgICAgIGlmIChjICE9PSBjb2xsZWN0aW9uKVxuICAgICAgICB0aHJvdyBuZXcgVW5zdXBwb3J0ZWRFcnJvcihcbiAgICAgICAgICBgU2VncmVnYXRlZCBkYXRhIGNvbGxlY3Rpb24gbWlzbWF0Y2g6ICR7Y30gdnMgJHtjb2xsZWN0aW9ufWBcbiAgICAgICAgKTtcbiAgICAgIGFjY1trXSA9IG1vZGVsW2tdO1xuICAgICAgcmV0dXJuIGFjYztcbiAgICB9LFxuICAgIHt9IGFzIFJlY29yZDxrZXlvZiBNLCBhbnk+XG4gICk7XG5cbiAgY29uc3QgdG9DcmVhdGUgPSBuZXcgdGhpcy5jbGFzcyhyZWJ1aWx0KTtcblxuICAvLyBjb25zdCBzZWdyZWdhdGVkID0gTW9kZWwuc2VncmVnYXRlKG1vZGVsKTtcblxuICBjb25zdCBjcmVhdGVkID0gYXdhaXQgdGhpcy5vdmVycmlkZSh7IHNlZ3JlZ2F0ZWQ6IGNvbGxlY3Rpb24gfSBhcyBhbnkpLmNyZWF0ZShcbiAgICB0b0NyZWF0ZSxcbiAgICBjb250ZXh0XG4gICk7XG4gIE9iamVjdC5hc3NpZ24obW9kZWwsIGNyZWF0ZWQpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VncmVnYXRlZERhdGFPblJlYWQ8TSBleHRlbmRzIE1vZGVsPihcbiAgdGhpczogUmVwb3NpdG9yeTxNLCBhbnk+LFxuICBjb250ZXh0OiBDb250ZXh0PEZhYnJpY0ZsYWdzPixcbiAgZGF0YTogU2VncmVnYXRlZERhdGFNZXRhZGF0YVtdLFxuICBrZXlzOiAoa2V5b2YgTSlbXSxcbiAgbW9kZWw6IE1cbik6IFByb21pc2U8dm9pZD4ge1xuICBpZiAoa2V5cy5sZW5ndGggIT09IGRhdGEubGVuZ3RoKVxuICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgYFNlZ3JlZ2F0ZWQgZGF0YSBrZXlzIGFuZCBtZXRhZGF0YSBsZW5ndGggbWlzbWF0Y2hgXG4gICAgKTtcblxuICBjb25zdCBjb2xsZWN0aW9uUmVzb2x2ZXIgPSBkYXRhWzBdLmNvbGxlY3Rpb25zO1xuICBjb25zdCBjb2xsZWN0aW9uID1cbiAgICB0eXBlb2YgY29sbGVjdGlvblJlc29sdmVyID09PSBcInN0cmluZ1wiXG4gICAgICA/IGNvbGxlY3Rpb25SZXNvbHZlclxuICAgICAgOiBjb2xsZWN0aW9uUmVzb2x2ZXIobW9kZWwpO1xuXG4gIGNvbnN0IHJlYnVpbHQgPSBrZXlzLnJlZHVjZShcbiAgICAoYWNjOiBSZWNvcmQ8a2V5b2YgTSwgYW55PiwgaywgaSkgPT4ge1xuICAgICAgY29uc3QgYyA9XG4gICAgICAgIHR5cGVvZiBkYXRhW2ldLmNvbGxlY3Rpb25zID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgPyBkYXRhW2ldLmNvbGxlY3Rpb25zXG4gICAgICAgICAgOiBkYXRhW2ldLmNvbGxlY3Rpb25zKG1vZGVsKTtcbiAgICAgIGlmIChjICE9PSBjb2xsZWN0aW9uKVxuICAgICAgICB0aHJvdyBuZXcgVW5zdXBwb3J0ZWRFcnJvcihcbiAgICAgICAgICBgU2VncmVnYXRlZCBkYXRhIGNvbGxlY3Rpb24gbWlzbWF0Y2g6ICR7Y30gdnMgJHtjb2xsZWN0aW9ufWBcbiAgICAgICAgKTtcbiAgICAgIGFjY1trXSA9IG1vZGVsW2tdO1xuICAgICAgcmV0dXJuIGFjYztcbiAgICB9LFxuICAgIHt9IGFzIFJlY29yZDxrZXlvZiBNLCBhbnk+XG4gICk7XG5cbiAgY29uc3QgdG9DcmVhdGUgPSBuZXcgdGhpcy5jbGFzcyhyZWJ1aWx0KTtcblxuICAvLyBjb25zdCBzZWdyZWdhdGVkID0gTW9kZWwuc2VncmVnYXRlKG1vZGVsKTtcblxuICBjb25zdCBjcmVhdGVkID0gYXdhaXQgdGhpcy5vdmVycmlkZSh7IHNlZ3JlZ2F0ZWQ6IGNvbGxlY3Rpb24gfSBhcyBhbnkpLmNyZWF0ZShcbiAgICB0b0NyZWF0ZSxcbiAgICBjb250ZXh0XG4gICk7XG4gIE9iamVjdC5hc3NpZ24obW9kZWwsIGNyZWF0ZWQpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VncmVnYXRlZERhdGFPblVwZGF0ZTxNIGV4dGVuZHMgTW9kZWw+KFxuICB0aGlzOiBSZXBvc2l0b3J5PE0sIGFueT4sXG4gIGNvbnRleHQ6IENvbnRleHQ8RmFicmljRmxhZ3M+LFxuICBkYXRhOiBTZWdyZWdhdGVkRGF0YU1ldGFkYXRhW10sXG4gIGtleToga2V5b2YgTVtdLFxuICBtb2RlbDogTSxcbiAgb2xkTW9kZWw6IE1cbik6IFByb21pc2U8dm9pZD4ge31cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNlZ3JlZ2F0ZWREYXRhT25EZWxldGU8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIFJlcG9zaXRvcnk8TSwgYW55PixcbiAgViBleHRlbmRzIFNlZ3JlZ2F0ZWREYXRhTWV0YWRhdGEsXG4+KFxuICB0aGlzOiBSLFxuICBjb250ZXh0OiBDb250ZXh0PEZhYnJpY0ZsYWdzPixcbiAgZGF0YTogVltdLFxuICBrZXk6IGtleW9mIE1bXSxcbiAgbW9kZWw6IE1cbik6IFByb21pc2U8dm9pZD4ge31cblxuZnVuY3Rpb24gc2VncmVnYXRlZChcbiAgY29sbGVjdGlvbjogc3RyaW5nIHwgQ29sbGVjdGlvblJlc29sdmVyLFxuICB0eXBlOiBGYWJyaWNNb2RlbEtleXMuUFJJVkFURSB8IEZhYnJpY01vZGVsS2V5cy5TSEFSRURcbikge1xuICByZXR1cm4gZnVuY3Rpb24gaW5uZXJTZWdyZWdhdGVkKHRhcmdldDogb2JqZWN0LCBwcm9wZXJ0eUtleT86IGFueSkge1xuICAgIGZ1bmN0aW9uIHNlZ3JlZ2F0ZWREZWModGFyZ2V0OiBvYmplY3QsIHByb3BlcnR5S2V5PzogYW55KSB7XG4gICAgICBpZiAoIXByb3BlcnR5S2V5KSB7XG4gICAgICAgIGNvbnN0IHByb3BzID0gTWV0YWRhdGEucHJvcGVydGllcyh0YXJnZXQgYXMgQ29uc3RydWN0b3IpIHx8IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IHByb3Agb2YgcHJvcHMpIHNlZ3JlZ2F0ZWQoY29sbGVjdGlvbiwgdHlwZSkodGFyZ2V0LCBwcm9wKTtcbiAgICAgICAgcmV0dXJuIHRhcmdldDtcbiAgICAgIH1cblxuICAgICAgY29uc3Qga2V5ID0gTWV0YWRhdGEua2V5KHR5cGUsIHByb3BlcnR5S2V5KTtcbiAgICAgIGNvbnN0IGNvbnN0cjogQ29uc3RydWN0b3IgPSB0YXJnZXQuY29uc3RydWN0b3IgYXMgQ29uc3RydWN0b3I7XG5cbiAgICAgIGNvbnN0IG1ldGEgPSBNZXRhZGF0YS5nZXQoY29uc3RyIGFzIENvbnN0cnVjdG9yLCBrZXkpIHx8IHt9O1xuICAgICAgY29uc3QgY29sbGVjdGlvbnMgPSBuZXcgU2V0KG1ldGEuY29sbGVjdGlvbnMgfHwgW10pO1xuICAgICAgY29sbGVjdGlvbnMuYWRkKGNvbGxlY3Rpb24pO1xuICAgICAgbWV0YS5jb2xsZWN0aW9ucyA9IFsuLi5jb2xsZWN0aW9uc107XG4gICAgICBNZXRhZGF0YS5zZXQoY29uc3RyIGFzIENvbnN0cnVjdG9yLCBrZXksIG1ldGEpO1xuICAgIH1cbiAgICBjb25zdCBkZWNzOiBhbnlbXSA9IFtdO1xuICAgIGlmICghcHJvcGVydHlLZXkpIHtcbiAgICAgIC8vIGRlY29yYXRlZCBhdCB0aGUgY2xhc3MgbGV2ZWxcbiAgICAgIE1ldGFkYXRhLnByb3BlcnRpZXModGFyZ2V0IGFzIENvbnN0cnVjdG9yKT8uZm9yRWFjaCgocCkgPT5cbiAgICAgICAgc2VncmVnYXRlZChjb2xsZWN0aW9uLCB0eXBlKSh0YXJnZXQsIHApXG4gICAgICApO1xuICAgICAgcmV0dXJuIG1ldGFkYXRhKHR5cGUsIHRydWUpKHRhcmdldCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRlY3MucHVzaChcbiAgICAgICAgdHJhbnNpZW50KCksXG4gICAgICAgIHNlZ3JlZ2F0ZWREZWMsXG4gICAgICAgIG9uQ3JlYXRlKFxuICAgICAgICAgIHNlZ3JlZ2F0ZWREYXRhT25DcmVhdGUsXG4gICAgICAgICAgeyBjb2xsZWN0aW9uczogY29sbGVjdGlvbiB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHByaW9yaXR5OiA5NSxcbiAgICAgICAgICAgIGdyb3VwOlxuICAgICAgICAgICAgICB0eXBlb2YgY29sbGVjdGlvbiA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgICAgICAgID8gY29sbGVjdGlvblxuICAgICAgICAgICAgICAgIDogY29sbGVjdGlvbi50b1N0cmluZygpLFxuICAgICAgICAgIH1cbiAgICAgICAgKSxcbiAgICAgICAgb25SZWFkKFxuICAgICAgICAgIHNlZ3JlZ2F0ZWREYXRhT25SZWFkIGFzIGFueSxcbiAgICAgICAgICB7IGNvbGxlY3Rpb25zOiBjb2xsZWN0aW9uIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgcHJpb3JpdHk6IDk1LFxuICAgICAgICAgICAgZ3JvdXA6XG4gICAgICAgICAgICAgIHR5cGVvZiBjb2xsZWN0aW9uID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgICAgICAgPyBjb2xsZWN0aW9uXG4gICAgICAgICAgICAgICAgOiBjb2xsZWN0aW9uLnRvU3RyaW5nKCksXG4gICAgICAgICAgfVxuICAgICAgICApLFxuICAgICAgICBvblVwZGF0ZShcbiAgICAgICAgICBzZWdyZWdhdGVkRGF0YU9uVXBkYXRlIGFzIGFueSxcbiAgICAgICAgICB7IGNvbGxlY3Rpb25zOiBjb2xsZWN0aW9uIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgcHJpb3JpdHk6IDk1LFxuICAgICAgICAgICAgZ3JvdXA6XG4gICAgICAgICAgICAgIHR5cGVvZiBjb2xsZWN0aW9uID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgICAgICAgPyBjb2xsZWN0aW9uXG4gICAgICAgICAgICAgICAgOiBjb2xsZWN0aW9uLnRvU3RyaW5nKCksXG4gICAgICAgICAgfVxuICAgICAgICApLFxuICAgICAgICBvbkRlbGV0ZShcbiAgICAgICAgICBzZWdyZWdhdGVkRGF0YU9uRGVsZXRlIGFzIGFueSxcbiAgICAgICAgICB7IGNvbGxlY3Rpb25zOiBjb2xsZWN0aW9uIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgcHJpb3JpdHk6IDk1LFxuICAgICAgICAgICAgZ3JvdXA6XG4gICAgICAgICAgICAgIHR5cGVvZiBjb2xsZWN0aW9uID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgICAgICAgPyBjb2xsZWN0aW9uXG4gICAgICAgICAgICAgICAgOiBjb2xsZWN0aW9uLnRvU3RyaW5nKCksXG4gICAgICAgICAgfVxuICAgICAgICApXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gYXBwbHkoLi4uZGVjcykodGFyZ2V0LCBwcm9wZXJ0eUtleSk7XG4gICAgLy8gcmV0dXJuIGFwcGx5KCkodGFyZ2V0LCBwcm9wZXJ0eUtleSk7XG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwcml2YXRlRGF0YShcbiAgY29sbGVjdGlvbjogc3RyaW5nIHwgQ29sbGVjdGlvblJlc29sdmVyID0gSW1wbGljaXRQcml2YXRlQ29sbGVjdGlvblxuKSB7XG4gIGZ1bmN0aW9uIHByaXZhdGVEYXRhKGNvbGxlY3Rpb246IHN0cmluZyB8IENvbGxlY3Rpb25SZXNvbHZlcikge1xuICAgIHJldHVybiBzZWdyZWdhdGVkKGNvbGxlY3Rpb24sIEZhYnJpY01vZGVsS2V5cy5QUklWQVRFKTtcbiAgfVxuXG4gIHJldHVybiBEZWNvcmF0aW9uLmZvcihGYWJyaWNNb2RlbEtleXMuUFJJVkFURSlcbiAgICAuZGVmaW5lKHtcbiAgICAgIGRlY29yYXRvcjogcHJpdmF0ZURhdGEsXG4gICAgICBhcmdzOiBbY29sbGVjdGlvbl0sXG4gICAgfSlcbiAgICAuYXBwbHkoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNoYXJlZERhdGEoY29sbGVjdGlvbjogc3RyaW5nIHwgQ29sbGVjdGlvblJlc29sdmVyKSB7XG4gIGZ1bmN0aW9uIHNoYXJlZERhdGEoY29sbGVjdGlvbjogc3RyaW5nIHwgQ29sbGVjdGlvblJlc29sdmVyKSB7XG4gICAgcmV0dXJuIHNlZ3JlZ2F0ZWQoY29sbGVjdGlvbiwgRmFicmljTW9kZWxLZXlzLlNIQVJFRCk7XG4gIH1cblxuICByZXR1cm4gRGVjb3JhdGlvbi5mb3IoRmFicmljTW9kZWxLZXlzLlNIQVJFRClcbiAgICAuZGVmaW5lKHtcbiAgICAgIGRlY29yYXRvcjogc2hhcmVkRGF0YSxcbiAgICAgIGFyZ3M6IFtjb2xsZWN0aW9uXSxcbiAgICB9KVxuICAgIC5hcHBseSgpO1xufVxuLy9cbi8vIGV4cG9ydCBmdW5jdGlvbiBwcml2YXRlRGF0YShjb2xsZWN0aW9uPzogc3RyaW5nKSB7XG4vLyAgIGlmICghY29sbGVjdGlvbikge1xuLy8gICAgIHRocm93IG5ldyBFcnJvcihcIkNvbGxlY3Rpb24gbmFtZSBpcyByZXF1aXJlZFwiKTtcbi8vICAgfVxuLy9cbi8vICAgY29uc3Qga2V5OiBzdHJpbmcgPSBGYWJyaWNNb2RlbEtleXMuUFJJVkFURTtcbi8vXG4vLyAgIHJldHVybiBmdW5jdGlvbiBwcml2YXRlRGF0YTxNIGV4dGVuZHMgTW9kZWw+KFxuLy8gICAgIG1vZGVsOiBNIHwgQ29uc3RydWN0b3I8TT4sXG4vLyAgICAgYXR0cmlidXRlPzogYW55XG4vLyAgICkge1xuLy8gICAgIGNvbnN0IGNvbnN0ciA9XG4vLyAgICAgICBtb2RlbCBpbnN0YW5jZW9mIE1vZGVsID8gKG1vZGVsLmNvbnN0cnVjdG9yIGFzIENvbnN0cnVjdG9yKSA6IG1vZGVsO1xuLy9cbi8vICAgICBjb25zdCBtZXRhRGF0YTogYW55ID0gTWV0YWRhdGEuZ2V0KGNvbnN0cik7XG4vLyAgICAgY29uc3QgbW9kZWxkYXRhID0gbWV0YURhdGE/LnByaXZhdGU/LmNvbGxlY3Rpb25zIHx8IFtdO1xuLy9cbi8vICAgICBwcm9wTWV0YWRhdGEoa2V5LCB7XG4vLyAgICAgICAuLi4oIWF0dHJpYnV0ZSAmJiB7XG4vLyAgICAgICAgIGNvbGxlY3Rpb25zOiBtb2RlbGRhdGFcbi8vICAgICAgICAgICA/IFsuLi5uZXcgU2V0KFsuLi5tb2RlbGRhdGEsIGNvbGxlY3Rpb25dKV1cbi8vICAgICAgICAgICA6IFtjb2xsZWN0aW9uXSxcbi8vICAgICAgIH0pLFxuLy8gICAgICAgaXNQcml2YXRlOiAhYXR0cmlidXRlLFxuLy8gICAgIH0pKGF0dHJpYnV0ZSA/IGNvbnN0ciA6IG1vZGVsKTtcbi8vXG4vLyAgICAgaWYgKGF0dHJpYnV0ZSkge1xuLy8gICAgICAgY29uc3QgYXR0cmlidXRlRGF0YSA9XG4vLyAgICAgICAgIChtZXRhRGF0YT8ucHJpdmF0ZT8uW2F0dHJpYnV0ZV0gYXMgYW55KT8uY29sbGVjdGlvbnMgfHwgW107XG4vLyAgICAgICBwcm9wTWV0YWRhdGEoTWV0YWRhdGEua2V5KGtleSwgYXR0cmlidXRlKSwge1xuLy8gICAgICAgICBjb2xsZWN0aW9uczogYXR0cmlidXRlRGF0YVxuLy8gICAgICAgICAgID8gWy4uLm5ldyBTZXQoWy4uLmF0dHJpYnV0ZURhdGEsIGNvbGxlY3Rpb25dKV1cbi8vICAgICAgICAgICA6IFtjb2xsZWN0aW9uXSxcbi8vICAgICAgIH0pKG1vZGVsLCBhdHRyaWJ1dGUpO1xuLy8gICAgICAgdHJhbnNpZW50KCkobW9kZWwsIGF0dHJpYnV0ZSk7XG4vLyAgICAgfVxuLy8gICB9O1xuLy8gfVxuIiwiLyoqXG4gKiBFbnVtIHJlcHJlc2VudGluZyB0aGUgZXZlbnRzIGVtaXR0ZWQgYnkgYW4gRVJDMjAgY29udHJhY3QuXG4gKlxuICogQHJlbWFya3NcbiAqIFRoaXMgZW51bSBpcyB1c2VkIHRvIGlkZW50aWZ5IHRoZSBzcGVjaWZpYyBldmVudHMgdGhhdCBjYW4gYmUgZW1pdHRlZCBieSBhbiBFUkMyMCBjb250cmFjdC5cbiAqIFRoZSBldmVudHMgYXJlIG5hbWVkIGFjY29yZGluZyB0byB0aGUgRUlQLTIwIHN0YW5kYXJkLlxuICovXG5leHBvcnQgZW51bSBFUkMyMEV2ZW50cyB7XG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gYSBgdHJhbnNmZXJgIGZ1bmN0aW9uIGlzIGNhbGxlZCBzdWNjZXNzZnVsbHkuXG4gICAqXG4gICAqIEBwYXJhbSBmcm9tIC0gVGhlIGFkZHJlc3Mgb2YgdGhlIHNlbmRlci5cbiAgICogQHBhcmFtIHRvIC0gVGhlIGFkZHJlc3Mgb2YgdGhlIHJlY2lwaWVudC5cbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIGFtb3VudCBvZiB0b2tlbnMgdHJhbnNmZXJyZWQuXG4gICAqL1xuICBUUkFOU0ZFUiA9IFwiVHJhbnNmZXJcIixcblxuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIGFuIGBhcHByb3ZlYCBmdW5jdGlvbiBpcyBjYWxsZWQgc3VjY2Vzc2Z1bGx5LlxuICAgKlxuICAgKiBAcGFyYW0gb3duZXIgLSBUaGUgYWRkcmVzcyBvZiB0aGUgdG9rZW4gb3duZXIuXG4gICAqIEBwYXJhbSBzcGVuZGVyIC0gVGhlIGFkZHJlc3Mgb2YgdGhlIGFwcHJvdmVkIHNwZW5kZXIuXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBhbW91bnQgb2YgdG9rZW5zIGFwcHJvdmVkIGZvciB0aGUgc3BlbmRlci5cbiAgICovXG4gIEFQUFJPVkFMID0gXCJBcHByb3ZhbFwiLFxufVxuIiwiaW1wb3J0IHsgQXV0aG9yaXphdGlvbkVycm9yLCBDb25kaXRpb24gfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IENvbnRleHQsIFRyYW5zYWN0aW9uIH0gZnJvbSBcImZhYnJpYy1jb250cmFjdC1hcGlcIjtcbmltcG9ydCB7IGFkZCwgc3ViIH0gZnJvbSBcIi4uLy4uL3NoYXJlZC9tYXRoXCI7XG5pbXBvcnQge1xuICBBbGxvd2FuY2VFcnJvcixcbiAgQmFsYW5jZUVycm9yLFxuICBOb3RJbml0aWFsaXplZEVycm9yLFxufSBmcm9tIFwiLi4vLi4vc2hhcmVkL2Vycm9yc1wiO1xuaW1wb3J0IHsgRmFicmljQ29udHJhY3RBZGFwdGVyIH0gZnJvbSBcIi4uL0NvbnRyYWN0QWRhcHRlclwiO1xuaW1wb3J0IHsgQWxsb3dhbmNlLCBFUkMyMFRva2VuLCBFUkMyMFdhbGxldCB9IGZyb20gXCIuL21vZGVsc1wiO1xuaW1wb3J0IHsgT3duZXIgfSBmcm9tIFwiLi4vLi4vc2hhcmVkL2RlY29yYXRvcnNcIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeSB9IGZyb20gXCIuLi9GYWJyaWNDb250cmFjdFJlcG9zaXRvcnlcIjtcbmltcG9ydCB0eXBlIHsgRmFicmljQ29udHJhY3RDb250ZXh0IH0gZnJvbSBcIi4uL0NvbnRyYWN0Q29udGV4dFwiO1xuaW1wb3J0IHtcbiAgQmFzZUVycm9yLFxuICBJbnRlcm5hbEVycm9yLFxuICBOb3RGb3VuZEVycm9yLFxuICBWYWxpZGF0aW9uRXJyb3IsXG59IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgRmFicmljQ3J1ZENvbnRyYWN0IH0gZnJvbSBcIi4uL2NydWQvY3J1ZC1jb250cmFjdFwiO1xuaW1wb3J0IHsgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5T2JzZXJ2YWJsZUhhbmRsZXIgfSBmcm9tIFwiLi4vRmFicmljQ29udHJhY3RSZXBvc2l0b3J5T2JzZXJ2YWJsZUhhbmRsZXJcIjtcbmltcG9ydCB7IEVSQzIwRXZlbnRzIH0gZnJvbSBcIi4uLy4uL3NoYXJlZC9lcmMyMC9lcmMyMC1jb25zdGFudHNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRVJDMjAgdG9rZW4gY29udHJhY3QgYmFzZSBmb3IgSHlwZXJsZWRnZXIgRmFicmljXG4gKiBAc3VtbWFyeSBJbXBsZW1lbnRzIEVSQzIwLWxpa2UgdG9rZW4gbG9naWMgdXNpbmcgcmVwb3NpdG9yaWVzIGFuZCBhZGFwdGVycywgcHJvdmlkaW5nIHN0YW5kYXJkIHRva2VuIG9wZXJhdGlvbnMgc3VjaCBhcyBiYWxhbmNlIHF1ZXJpZXMsIHRyYW5zZmVycywgYXBwcm92YWxzLCBtaW50aW5nIGFuZCBidXJuaW5nLlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBUaGUgY29udHJhY3QgbmFtZSB1c2VkIHRvIHNjb3BlIHRva2VuIGlkZW50aXR5XG4gKiBAbm90ZSBodHRwczovL2VpcHMuZXRoZXJldW0ub3JnL0VJUFMvZWlwLTIwXG4gKiBAcmV0dXJuIHt2b2lkfVxuICogQGNsYXNzIEZhYnJpY0VSQzIwQ29udHJhY3RcbiAqIEBleGFtcGxlXG4gKiBjbGFzcyBNeVRva2VuQ29udHJhY3QgZXh0ZW5kcyBGYWJyaWNFUkMyMENvbnRyYWN0IHtcbiAqICAgY29uc3RydWN0b3IoKSB7IHN1cGVyKCdNeVRva2VuJyk7IH1cbiAqIH1cbiAqIC8vIFRoZSBjb250cmFjdCBleHBvc2VzIG1ldGhvZHMgbGlrZSBUcmFuc2ZlciwgQXBwcm92ZSwgTWludCwgQnVybiwgZXRjLlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAqICAgcGFydGljaXBhbnQgQ29udHJhY3RcbiAqICAgcGFydGljaXBhbnQgV2FsbGV0UmVwb1xuICogICBwYXJ0aWNpcGFudCBUb2tlblJlcG9cbiAqICAgcGFydGljaXBhbnQgTGVkZ2VyXG4gKiAgIENsaWVudC0+PkNvbnRyYWN0OiBUcmFuc2ZlcihjdHgsIHRvLCB2YWx1ZSlcbiAqICAgQ29udHJhY3QtPj5XYWxsZXRSZXBvOiByZWFkKGZyb20pXG4gKiAgIENvbnRyYWN0LT4+V2FsbGV0UmVwbzogcmVhZCh0bylcbiAqICAgQ29udHJhY3QtPj5MZWRnZXI6IHB1dFN0YXRlKHVwZGF0ZWQgYmFsYW5jZXMpXG4gKiAgIENvbnRyYWN0LS0+PkNsaWVudDogc3VjY2Vzc1xuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgRmFicmljRVJDMjBDb250cmFjdCBleHRlbmRzIEZhYnJpY0NydWRDb250cmFjdDxFUkMyMFdhbGxldD4ge1xuICBwcml2YXRlIHdhbGxldFJlcG9zaXRvcnk6IEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeTxFUkMyMFdhbGxldD47XG5cbiAgcHJpdmF0ZSB0b2tlblJlcG9zaXRvcnk6IEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeTxFUkMyMFRva2VuPjtcblxuICBwcml2YXRlIGFsbG93YW5jZVJlcG9zaXRvcnk6IEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeTxBbGxvd2FuY2U+O1xuXG4gIHByb3RlY3RlZCBjb25zdHJ1Y3RvcihuYW1lOiBzdHJpbmcpIHtcbiAgICBzdXBlcihuYW1lLCBFUkMyMFdhbGxldCk7XG5cbiAgICBGYWJyaWNFUkMyMENvbnRyYWN0LmFkYXB0ZXIgPVxuICAgICAgRmFicmljRVJDMjBDb250cmFjdC5hZGFwdGVyIHx8IG5ldyBGYWJyaWNDb250cmFjdEFkYXB0ZXIoKTtcblxuICAgIHRoaXMud2FsbGV0UmVwb3NpdG9yeSA9IEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeS5mb3JNb2RlbChcbiAgICAgIEVSQzIwV2FsbGV0LFxuICAgICAgRmFicmljRVJDMjBDb250cmFjdC5hZGFwdGVyLmFsaWFzXG4gICAgKTtcblxuICAgIHRoaXMudG9rZW5SZXBvc2l0b3J5ID0gRmFicmljQ29udHJhY3RSZXBvc2l0b3J5LmZvck1vZGVsKFxuICAgICAgRVJDMjBUb2tlbixcbiAgICAgIEZhYnJpY0VSQzIwQ29udHJhY3QuYWRhcHRlci5hbGlhc1xuICAgICk7XG5cbiAgICB0aGlzLmFsbG93YW5jZVJlcG9zaXRvcnkgPSBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnkuZm9yTW9kZWwoXG4gICAgICBBbGxvd2FuY2UsXG4gICAgICBGYWJyaWNFUkMyMENvbnRyYWN0LmFkYXB0ZXIuYWxpYXNcbiAgICApO1xuICB9XG5cbiAgQFRyYW5zYWN0aW9uKGZhbHNlKVxuICBhc3luYyBUb2tlbk5hbWUoY29udGV4dDogQ29udGV4dCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5Ub2tlbk5hbWUpO1xuICAgIC8vIENoZWNrIGNvbnRyYWN0IG9wdGlvbnMgYXJlIGFscmVhZHkgc2V0IGZpcnN0IHRvIGV4ZWN1dGUgdGhlIGZ1bmN0aW9uXG4gICAgYXdhaXQgdGhpcy5DaGVja0luaXRpYWxpemVkKGN0eCBhcyBhbnkpO1xuXG4gICAgY29uc3Qgc2VsZWN0ID0gdGhpcy50b2tlblJlcG9zaXRvcnkuc2VsZWN0KCk7XG4gICAgY29uc3QgdG9rZW4gPSAoYXdhaXQgc2VsZWN0LmV4ZWN1dGUoY3R4KSlbMF07XG5cbiAgICByZXR1cm4gdG9rZW4ubmFtZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIHN5bWJvbCBvZiB0aGUgdG9rZW4uIEUuZy4g4oCcSElY4oCdLlxuICAgKlxuICAgKiBAcGFyYW0ge0NvbnRleHR9IGNvbnRleHQgdGhlIHRyYW5zYWN0aW9uIGNvbnRleHRcbiAgICogQHJldHVybnMge1N0cmluZ30gUmV0dXJucyB0aGUgc3ltYm9sIG9mIHRoZSB0b2tlblxuICAgKi9cbiAgQFRyYW5zYWN0aW9uKGZhbHNlKVxuICBhc3luYyBTeW1ib2woY29udGV4dDogQ29udGV4dCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5Ub2tlbk5hbWUpO1xuICAgIC8vIENoZWNrIGNvbnRyYWN0IG9wdGlvbnMgYXJlIGFscmVhZHkgc2V0IGZpcnN0IHRvIGV4ZWN1dGUgdGhlIGZ1bmN0aW9uXG4gICAgYXdhaXQgdGhpcy5DaGVja0luaXRpYWxpemVkKGN0eCBhcyBhbnkpO1xuXG4gICAgY29uc3Qgc2VsZWN0ID0gdGhpcy50b2tlblJlcG9zaXRvcnkuc2VsZWN0KCk7XG4gICAgY29uc3QgdG9rZW4gPSAoYXdhaXQgc2VsZWN0LmV4ZWN1dGUoY3R4KSlbMF07XG5cbiAgICByZXR1cm4gdG9rZW4uc3ltYm9sO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGUgbnVtYmVyIG9mIGRlY2ltYWxzIHRoZSB0b2tlbiB1c2VzXG4gICAqIGUuZy4gOCwgbWVhbnMgdG8gZGl2aWRlIHRoZSB0b2tlbiBhbW91bnQgYnkgMTAwMDAwMDAwIHRvIGdldCBpdHMgdXNlciByZXByZXNlbnRhdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHtDb250ZXh0fSBjb250ZXh0IHRoZSB0cmFuc2FjdGlvbiBjb250ZXh0XG4gICAqIEByZXR1cm5zIHtOdW1iZXJ9IFJldHVybnMgdGhlIG51bWJlciBvZiBkZWNpbWFsc1xuICAgKi9cbiAgQFRyYW5zYWN0aW9uKGZhbHNlKVxuICBhc3luYyBEZWNpbWFscyhjb250ZXh0OiBDb250ZXh0KTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCB7IGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLlRva2VuTmFtZSk7XG4gICAgLy8gQ2hlY2sgY29udHJhY3Qgb3B0aW9ucyBhcmUgYWxyZWFkeSBzZXQgZmlyc3QgdG8gZXhlY3V0ZSB0aGUgZnVuY3Rpb25cbiAgICBhd2FpdCB0aGlzLkNoZWNrSW5pdGlhbGl6ZWQoY3R4IGFzIGFueSk7XG5cbiAgICBjb25zdCBzZWxlY3QgPSB0aGlzLnRva2VuUmVwb3NpdG9yeS5zZWxlY3QoKTtcbiAgICBjb25zdCB0b2tlbiA9IChhd2FpdCBzZWxlY3QuZXhlY3V0ZShjdHgpKVswXTtcblxuICAgIHJldHVybiB0b2tlbi5kZWNpbWFscztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIHRvdGFsIHRva2VuIHN1cHBseS5cbiAgICpcbiAgICogQHBhcmFtIHtDb250ZXh0fSBjb250ZXh0IHRoZSB0cmFuc2FjdGlvbiBjb250ZXh0XG4gICAqIEByZXR1cm5zIHtOdW1iZXJ9IFJldHVybnMgdGhlIHRvdGFsIHRva2VuIHN1cHBseVxuICAgKi9cbiAgQFRyYW5zYWN0aW9uKGZhbHNlKVxuICBhc3luYyBUb3RhbFN1cHBseShjb250ZXh0OiBDb250ZXh0KTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCB7IGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLlRva2VuTmFtZSk7XG4gICAgLy8gQ2hlY2sgY29udHJhY3Qgb3B0aW9ucyBhcmUgYWxyZWFkeSBzZXQgZmlyc3QgdG8gZXhlY3V0ZSB0aGUgZnVuY3Rpb25cbiAgICBhd2FpdCB0aGlzLkNoZWNrSW5pdGlhbGl6ZWQoY3R4IGFzIGFueSk7XG5cbiAgICBjb25zdCBzZWxlY3QgPSB0aGlzLndhbGxldFJlcG9zaXRvcnkuc2VsZWN0KCk7XG4gICAgY29uc3Qgd2FsbGV0cyA9IGF3YWl0IHNlbGVjdC5leGVjdXRlKGN0eCk7XG5cbiAgICBpZiAod2FsbGV0cy5sZW5ndGggPT0gMCkge1xuICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXJyb3IoYFRoZSB0b2tlbiAke3RoaXMuZ2V0TmFtZSgpfSBkb2VzIG5vdCBleGlzdGApO1xuICAgIH1cblxuICAgIGxldCB0b3RhbCA9IDA7XG5cbiAgICB3YWxsZXRzLmZvckVhY2goKHdhbGxldCkgPT4ge1xuICAgICAgdG90YWwgKz0gd2FsbGV0LmJhbGFuY2U7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gdG90YWw7XG4gIH1cblxuICAvKipcbiAgICogQmFsYW5jZU9mIHJldHVybnMgdGhlIGJhbGFuY2Ugb2YgdGhlIGdpdmVuIGFjY291bnQuXG4gICAqXG4gICAqIEBwYXJhbSB7Q29udGV4dH0gY3R4IHRoZSB0cmFuc2FjdGlvbiBjb250ZXh0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBvd25lciBUaGUgb3duZXIgZnJvbSB3aGljaCB0aGUgYmFsYW5jZSB3aWxsIGJlIHJldHJpZXZlZFxuICAgKiBAcmV0dXJucyB7TnVtYmVyfSBSZXR1cm5zIHRoZSBhY2NvdW50IGJhbGFuY2VcbiAgICovXG4gIEBUcmFuc2FjdGlvbihmYWxzZSlcbiAgYXN5bmMgQmFsYW5jZU9mKGNvbnRleHQ6IENvbnRleHQsIG93bmVyOiBzdHJpbmcpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IHsgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMuVG9rZW5OYW1lKTtcbiAgICAvLyBDaGVjayBjb250cmFjdCBvcHRpb25zIGFyZSBhbHJlYWR5IHNldCBmaXJzdCB0byBleGVjdXRlIHRoZSBmdW5jdGlvblxuICAgIGF3YWl0IHRoaXMuQ2hlY2tJbml0aWFsaXplZChjdHggYXMgYW55KTtcblxuICAgIGNvbnN0IHdhbGxldCA9IGF3YWl0IHRoaXMud2FsbGV0UmVwb3NpdG9yeS5yZWFkKG93bmVyLCBjdHgpO1xuXG4gICAgcmV0dXJuIHdhbGxldC5iYWxhbmNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IFRyYW5zZmVyIHRyYW5zZmVycyB0b2tlbnMgZnJvbSBjbGllbnQgYWNjb3VudCB0byByZWNpcGllbnQgYWNjb3VudC5cbiAgICogQGRlc2NyaXB0aW9uIHJlY2lwaWVudCBhY2NvdW50IG11c3QgYmUgYSB2YWxpZCBjbGllbnRJRCBhcyByZXR1cm5lZCBieSB0aGUgQ2xpZW50QWNjb3VudElEKCkgZnVuY3Rpb24uXG4gICAqXG4gICAqIEBwYXJhbSB7Q29udGV4dH0gY29udGV4dCB0aGUgdHJhbnNhY3Rpb24gY29udGV4dFxuICAgKiBAcGFyYW0ge1N0cmluZ30gdG8gVGhlIHJlY2lwaWVudFxuICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVGhlIGFtb3VudCBvZiB0b2tlbiB0byBiZSB0cmFuc2ZlcnJlZFxuICAgKlxuICAgKiBAcmV0dXJucyB7Qm9vbGVhbn0gUmV0dXJuIHdoZXRoZXIgdGhlIHRyYW5zZmVyIHdhcyBzdWNjZXNzZnVsIG9yIG5vdFxuICAgKi9cbiAgQFRyYW5zYWN0aW9uKClcbiAgYXN5bmMgVHJhbnNmZXIoXG4gICAgY29udGV4dDogQ29udGV4dCxcbiAgICB0bzogc3RyaW5nLFxuICAgIHZhbHVlOiBudW1iZXJcbiAgKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gQ2hlY2sgY29udHJhY3Qgb3B0aW9ucyBhcmUgYWxyZWFkeSBzZXQgZmlyc3QgdG8gZXhlY3V0ZSB0aGUgZnVuY3Rpb25cbiAgICBjb25zdCB7IGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLlRyYW5zZmVyKTtcbiAgICBhd2FpdCB0aGlzLkNoZWNrSW5pdGlhbGl6ZWQoY3R4IGFzIGFueSk7XG5cbiAgICBjb25zdCBmcm9tID0gY3R4LmlkZW50aXR5LmdldElEKCk7XG5cbiAgICBjb25zdCB0cmFuc2ZlclJlc3AgPSBhd2FpdCB0aGlzLl90cmFuc2Zlcihmcm9tLCB0bywgdmFsdWUsIGN0eCk7XG4gICAgaWYgKCF0cmFuc2ZlclJlc3ApIHtcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiRmFpbGVkIHRvIHRyYW5zZmVyXCIpO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyYW5zZmVyIGB2YWx1ZWAgYW1vdW50IG9mIHRva2VucyBmcm9tIGBmcm9tYCB0byBgdG9gLlxuICAgKlxuICAgKiBAcGFyYW0ge0NvbnRleHR9IGNvbnRleHQgdGhlIHRyYW5zYWN0aW9uIGNvbnRleHRcbiAgICogQHBhcmFtIHtTdHJpbmd9IGZyb20gVGhlIHNlbmRlclxuICAgKiBAcGFyYW0ge1N0cmluZ30gdG8gVGhlIHJlY2lwaWVudFxuICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVGhlIGFtb3VudCBvZiB0b2tlbiB0byBiZSB0cmFuc2ZlcnJlZFxuICAgKiBAcmV0dXJucyB7Qm9vbGVhbn0gUmV0dXJuIHdoZXRoZXIgdGhlIHRyYW5zZmVyIHdhcyBzdWNjZXNzZnVsIG9yIG5vdFxuICAgKi9cbiAgQFRyYW5zYWN0aW9uKClcbiAgYXN5bmMgVHJhbnNmZXJGcm9tKFxuICAgIGNvbnRleHQ6IENvbnRleHQsXG4gICAgZnJvbTogc3RyaW5nLFxuICAgIHRvOiBzdHJpbmcsXG4gICAgdmFsdWU6IG51bWJlclxuICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBDaGVjayBjb250cmFjdCBvcHRpb25zIGFyZSBhbHJlYWR5IHNldCBmaXJzdCB0byBleGVjdXRlIHRoZSBmdW5jdGlvblxuICAgIGNvbnN0IHsgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMuQnVybkZyb20pO1xuICAgIGF3YWl0IHRoaXMuQ2hlY2tJbml0aWFsaXplZChjdHggYXMgYW55KTtcblxuICAgIC8vIFJldHJpZXZlIHRoZSBhbGxvd2FuY2Ugb2YgdGhlIHNwZW5kZXJcblxuICAgIGNvbnN0IHNwZW5kZXIgPSBjdHguaWRlbnRpdHkuZ2V0SUQoKTtcblxuICAgIGNvbnN0IGFsbG93YW5jZSA9IGF3YWl0IHRoaXMuX2dldEFsbG93YW5jZShmcm9tLCBzcGVuZGVyLCBjdHgpO1xuICAgIGlmICghYWxsb3dhbmNlIHx8IGFsbG93YW5jZS52YWx1ZSA8IDApIHtcbiAgICAgIHRocm93IG5ldyBBbGxvd2FuY2VFcnJvcihcbiAgICAgICAgYHNwZW5kZXIgJHtzcGVuZGVyfSBoYXMgbm8gYWxsb3dhbmNlIGZyb20gJHtmcm9tfWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgY3VycmVudEFsbG93YW5jZSA9IGFsbG93YW5jZS52YWx1ZTtcblxuICAgIC8vIENoZWNrIGlmIHRoZSB0cmFuc2ZlcnJlZCB2YWx1ZSBpcyBsZXNzIHRoYW4gdGhlIGFsbG93YW5jZVxuICAgIGlmIChjdXJyZW50QWxsb3dhbmNlIDwgdmFsdWUpIHtcbiAgICAgIHRocm93IG5ldyBCYWxhbmNlRXJyb3IoXG4gICAgICAgIFwiVGhlIHNwZW5kZXIgZG9lcyBub3QgaGF2ZSBlbm91Z2ggYWxsb3dhbmNlIHRvIHNwZW5kLlwiXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIERlY3JlYXNlIHRoZSBhbGxvd2FuY2VcbiAgICBjb25zdCB1cGRhdGVkQWxsb3dhbmNlID0gc3ViKGN1cnJlbnRBbGxvd2FuY2UsIHZhbHVlKTtcbiAgICBjb25zdCBuZXdBbGxvd2FuY2UgPSBPYmplY3QuYXNzaWduKHt9LCBhbGxvd2FuY2UsIHtcbiAgICAgIHZhbHVlOiB1cGRhdGVkQWxsb3dhbmNlLFxuICAgIH0pO1xuXG4gICAgYXdhaXQgdGhpcy5hbGxvd2FuY2VSZXBvc2l0b3J5LnVwZGF0ZShuZXdBbGxvd2FuY2UsIGN0eCk7XG5cbiAgICAvL1JlYWxpemUgdGhlIHRyYW5zZmVyXG4gICAgY29uc3QgdHJhbnNmZXJSZXNwID0gYXdhaXQgdGhpcy5fdHJhbnNmZXIoZnJvbSwgdG8sIHZhbHVlLCBjdHgpO1xuICAgIGlmICghdHJhbnNmZXJSZXNwKSB7XG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIkZhaWxlZCB0byB0cmFuc2ZlclwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGFzeW5jIF90cmFuc2ZlcihcbiAgICBmcm9tOiBzdHJpbmcsXG4gICAgdG86IHN0cmluZyxcbiAgICB2YWx1ZTogbnVtYmVyLFxuICAgIGN0eDogRmFicmljQ29udHJhY3RDb250ZXh0XG4gICkge1xuICAgIGNvbnN0IGxvZyA9IGN0eC5sb2dnZXI7XG5cbiAgICBpZiAoZnJvbSA9PT0gdG8pIHtcbiAgICAgIHRocm93IG5ldyBBdXRob3JpemF0aW9uRXJyb3IoXG4gICAgICAgIFwiY2Fubm90IHRyYW5zZmVyIHRvIGFuZCBmcm9tIHNhbWUgY2xpZW50IGFjY291bnRcIlxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAodmFsdWUgPCAwKSB7XG4gICAgICAvLyB0cmFuc2ZlciBvZiAwIGlzIGFsbG93ZWQgaW4gRVJDMjAsIHNvIGp1c3QgdmFsaWRhdGUgYWdhaW5zdCBuZWdhdGl2ZSBhbW91bnRzXG4gICAgICB0aHJvdyBuZXcgQmFsYW5jZUVycm9yKFwidHJhbnNmZXIgYW1vdW50IGNhbm5vdCBiZSBuZWdhdGl2ZVwiKTtcbiAgICB9XG5cbiAgICAvLyBSZXRyaWV2ZSB0aGUgY3VycmVudCBiYWxhbmNlIG9mIHRoZSBzZW5kZXJcblxuICAgIGNvbnN0IGZyb21XYWxsZXQgPSBhd2FpdCB0aGlzLndhbGxldFJlcG9zaXRvcnkucmVhZChmcm9tLCBjdHgpO1xuXG4gICAgY29uc3QgZnJvbUJhbGFuY2UgPSBmcm9tV2FsbGV0LmJhbGFuY2U7XG5cbiAgICAvLyBDaGVjayBpZiB0aGUgc2VuZGVyIGhhcyBlbm91Z2ggdG9rZW5zIHRvIHNwZW5kLlxuICAgIGlmIChmcm9tQmFsYW5jZSA8IHZhbHVlKSB7XG4gICAgICB0aHJvdyBuZXcgQmFsYW5jZUVycm9yKGBjbGllbnQgYWNjb3VudCAke2Zyb219IGhhcyBpbnN1ZmZpY2llbnQgZnVuZHMuYCk7XG4gICAgfVxuXG4gICAgLy8gUmV0cmlldmUgdGhlIGN1cnJlbnQgYmFsYW5jZSBvZiB0aGUgcmVjZXBpZW50XG5cbiAgICBsZXQgdG9XYWxsZXQ6IEVSQzIwV2FsbGV0O1xuICAgIGxldCBuZXdUb1dhbGxldDogYm9vbGVhbiA9IGZhbHNlO1xuICAgIHRyeSB7XG4gICAgICB0b1dhbGxldCA9IGF3YWl0IHRoaXMud2FsbGV0UmVwb3NpdG9yeS5yZWFkKHRvLCBjdHgpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIGlmIChlIGluc3RhbmNlb2YgQmFzZUVycm9yKSB7XG4gICAgICAgIGlmIChlLmNvZGUgPT09IDQwNCkge1xuICAgICAgICAgIC8vIENyZWF0ZSBhIG5ldyB3YWxsZXQgZm9yIHRoZSBtaW50ZXJcbiAgICAgICAgICB0b1dhbGxldCA9IG5ldyBFUkMyMFdhbGxldCh7XG4gICAgICAgICAgICBpZDogdG8sXG4gICAgICAgICAgICBiYWxhbmNlOiAwLFxuICAgICAgICAgICAgdG9rZW46IGF3YWl0IHRoaXMuVG9rZW5OYW1lKGN0eCBhcyBhbnkpLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIG5ld1RvV2FsbGV0ID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihlLm1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihlIGFzIHN0cmluZyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgdG9CYWxhbmNlID0gdG9XYWxsZXQuYmFsYW5jZTtcblxuICAgIC8vIFVwZGF0ZSB0aGUgYmFsYW5jZVxuICAgIGNvbnN0IGZyb21VcGRhdGVkQmFsYW5jZSA9IHN1Yihmcm9tQmFsYW5jZSwgdmFsdWUpO1xuICAgIGNvbnN0IHRvVXBkYXRlZEJhbGFuY2UgPSBhZGQodG9CYWxhbmNlLCB2YWx1ZSk7XG5cbiAgICBjb25zdCB1cGRhdGVkRnJvbVdhbGxldCA9IE9iamVjdC5hc3NpZ24oe30sIGZyb21XYWxsZXQsIHtcbiAgICAgIGJhbGFuY2U6IGZyb21VcGRhdGVkQmFsYW5jZSxcbiAgICB9KTtcblxuICAgIGF3YWl0IHRoaXMud2FsbGV0UmVwb3NpdG9yeS51cGRhdGUodXBkYXRlZEZyb21XYWxsZXQsIGN0eCk7XG5cbiAgICBjb25zdCB1cGRhdGVkVG9XYWxsZXQgPSBPYmplY3QuYXNzaWduKHt9LCB0b1dhbGxldCwge1xuICAgICAgYmFsYW5jZTogdG9VcGRhdGVkQmFsYW5jZSxcbiAgICB9KTtcblxuICAgIGlmIChuZXdUb1dhbGxldCkge1xuICAgICAgYXdhaXQgdGhpcy53YWxsZXRSZXBvc2l0b3J5LmNyZWF0ZSh1cGRhdGVkVG9XYWxsZXQsIGN0eCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF3YWl0IHRoaXMud2FsbGV0UmVwb3NpdG9yeS51cGRhdGUodXBkYXRlZFRvV2FsbGV0LCBjdHgpO1xuICAgIH1cblxuICAgIC8vIEVtaXQgdGhlIFRyYW5zZmVyIGV2ZW50XG4gICAgY29uc3QgdHJhbnNmZXJFdmVudCA9IHsgZnJvbSwgdG8sIHZhbHVlOiB2YWx1ZSB9O1xuXG4gICAgdGhpcy5yZXBvXG4gICAgICAucmVmcmVzaChcbiAgICAgICAgRVJDMjBUb2tlbiBhcyBhbnksXG4gICAgICAgIEVSQzIwRXZlbnRzLlRSQU5TRkVSLFxuICAgICAgICBcIlwiLFxuICAgICAgICB0cmFuc2ZlckV2ZW50LFxuICAgICAgICBjdHggYXMgdW5rbm93biBhcyBGYWJyaWNDb250cmFjdENvbnRleHRcbiAgICAgIClcbiAgICAgIC5jYXRjaCgoZSkgPT4gbG9nLmVycm9yKGBGYWlsZWQgdG8gbm90aWZ5IHRyYW5zZmVyOiAke2V9YCkpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogQWxsb3dzIGBzcGVuZGVyYCB0byBzcGVuZCBgdmFsdWVgIGFtb3VudCBvZiB0b2tlbnMgZnJvbSB0aGUgb3duZXIuIE5ldyBBcHByb3ZlIGNhbGxzIG92ZXJyaWRlIHRoZSBwcmV2aW91cyBhbGxvd2FuY2UuXG4gICAqIEBub3RlIGh0dHBzOi8vZWlwcy5ldGhlcmV1bS5vcmcvRUlQUy9laXAtMjBcbiAgICpcbiAgICogQHBhcmFtIHtDb250ZXh0fSBjdHggdGhlIHRyYW5zYWN0aW9uIGNvbnRleHRcbiAgICogQHBhcmFtIHtTdHJpbmd9IHNwZW5kZXIgVGhlIHNwZW5kZXJcbiAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFRoZSBhbW91bnQgb2YgdG9rZW5zIHRvIGJlIGFwcHJvdmVkIGZvciB0cmFuc2ZlclxuICAgKiBAcmV0dXJucyB7Qm9vbGVhbn0gUmV0dXJuIHdoZXRoZXIgdGhlIGFwcHJvdmFsIHdhcyBzdWNjZXNzZnVsIG9yIG5vdFxuICAgKi9cbiAgQFRyYW5zYWN0aW9uKClcbiAgYXN5bmMgQXBwcm92ZShcbiAgICBjb250ZXh0OiBDb250ZXh0LFxuICAgIHNwZW5kZXI6IHN0cmluZyxcbiAgICB2YWx1ZTogbnVtYmVyXG4gICk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IHsgY3R4LCBjdHhBcmdzIH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMuQXBwcm92ZSk7XG4gICAgLy8gQ2hlY2sgY29udHJhY3Qgb3B0aW9ucyBhcmUgYWxyZWFkeSBzZXQgZmlyc3QgdG8gZXhlY3V0ZSB0aGUgZnVuY3Rpb25cbiAgICBhd2FpdCB0aGlzLkNoZWNrSW5pdGlhbGl6ZWQoY3R4IGFzIGFueSk7XG5cbiAgICBjb25zdCBvd25lciA9IGN0eC5pZGVudGl0eS5nZXRJRCgpO1xuXG4gICAgbGV0IGFsbG93YW5jZSA9IGF3YWl0IHRoaXMuX2dldEFsbG93YW5jZShvd25lciwgc3BlbmRlciwgY3R4KTtcblxuICAgIGNvbnN0IG93bmVyV2FsbGV0ID0gYXdhaXQgdGhpcy53YWxsZXRSZXBvc2l0b3J5LnJlYWQob3duZXIsIC4uLmN0eEFyZ3MpO1xuXG4gICAgaWYgKG93bmVyV2FsbGV0LmJhbGFuY2UgPCB2YWx1ZSkge1xuICAgICAgdGhyb3cgbmV3IEJhbGFuY2VFcnJvcihgY2xpZW50IGFjY291bnQgJHtvd25lcn0gaGFzIGluc3VmZmljaWVudCBmdW5kcy5gKTtcbiAgICB9XG5cbiAgICBpZiAoYWxsb3dhbmNlKSB7XG4gICAgICAvLyBPdmVyd3JpdGUgdGhlIGFsbG93YW5jZVxuICAgICAgYWxsb3dhbmNlLnZhbHVlID0gdmFsdWU7XG4gICAgICBhd2FpdCB0aGlzLmFsbG93YW5jZVJlcG9zaXRvcnkudXBkYXRlKGFsbG93YW5jZSwgLi4uY3R4QXJncyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFsbG93YW5jZSA9IG5ldyBBbGxvd2FuY2Uoe1xuICAgICAgICBvd25lcjogb3duZXIsXG4gICAgICAgIHNwZW5kZXI6IHNwZW5kZXIsXG4gICAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICAgIH0pO1xuXG4gICAgICBhd2FpdCB0aGlzLmFsbG93YW5jZVJlcG9zaXRvcnkuY3JlYXRlKGFsbG93YW5jZSwgLi4uY3R4QXJncyk7XG4gICAgfVxuXG4gICAgLy8gRW1pdCB0aGUgQXBwcm92YWwgZXZlbnRcbiAgICBjb25zdCBhcHByb3ZhbEV2ZW50ID0geyBvd25lciwgc3BlbmRlciwgdmFsdWU6IHZhbHVlIH07XG4gICAgdGhpcy5yZXBvLnJlZnJlc2goXG4gICAgICBFUkMyMFRva2VuIGFzIGFueSxcbiAgICAgIEVSQzIwRXZlbnRzLkFQUFJPVkFMLFxuICAgICAgXCJcIixcbiAgICAgIGFwcHJvdmFsRXZlbnQsXG4gICAgICBjdHggYXMgdW5rbm93biBhcyBGYWJyaWNDb250cmFjdENvbnRleHRcbiAgICApO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgYW1vdW50IG9mIHRva2VucyB3aGljaCBgIGAgaXMgYWxsb3dlZCB0byB3aXRoZHJhdyBmcm9tIGBvd25lcmAuXG4gICAqXG4gICAqIEBwYXJhbSB7Q29udGV4dH0gY3R4IHRoZSB0cmFuc2FjdGlvbiBjb250ZXh0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBvd25lciBUaGUgb3duZXIgb2YgdG9rZW5zXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzcGVuZGVyIFRoZSBzcGVuZGVyIHdobyBhcmUgYWJsZSB0byB0cmFuc2ZlciB0aGUgdG9rZW5zXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybiB0aGUgYW1vdW50IG9mIHJlbWFpbmluZyB0b2tlbnMgYWxsb3dlZCB0byBzcGVudFxuICAgKi9cbiAgQFRyYW5zYWN0aW9uKGZhbHNlKVxuICBhc3luYyBBbGxvd2FuY2UoXG4gICAgY29udGV4dDogQ29udGV4dCxcbiAgICBvd25lcjogc3RyaW5nLFxuICAgIHNwZW5kZXI6IHN0cmluZ1xuICApOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IHsgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMuQWxsb3dhbmNlKTtcbiAgICAvLyBDaGVjayBjb250cmFjdCBvcHRpb25zIGFyZSBhbHJlYWR5IHNldCBmaXJzdCB0byBleGVjdXRlIHRoZSBmdW5jdGlvblxuICAgIGF3YWl0IHRoaXMuQ2hlY2tJbml0aWFsaXplZChjdHggYXMgYW55KTtcblxuICAgIGNvbnN0IGFsbG93YW5jZSA9IGF3YWl0IHRoaXMuX2dldEFsbG93YW5jZShvd25lciwgc3BlbmRlciwgY3R4KTtcblxuICAgIGlmICghYWxsb3dhbmNlKSB7XG4gICAgICB0aHJvdyBuZXcgQWxsb3dhbmNlRXJyb3IoXG4gICAgICAgIGBzcGVuZGVyICR7c3BlbmRlcn0gaGFzIG5vIGFsbG93YW5jZSBmcm9tICR7b3duZXJ9YFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGFsbG93YW5jZS52YWx1ZTtcbiAgfVxuXG4gIGFzeW5jIF9nZXRBbGxvd2FuY2UoXG4gICAgb3duZXI6IHN0cmluZyxcbiAgICBzcGVuZGVyOiBzdHJpbmcsXG4gICAgY3R4OiBGYWJyaWNDb250cmFjdENvbnRleHRcbiAgKTogUHJvbWlzZTxBbGxvd2FuY2U+IHtcbiAgICBjb25zdCBhbGxvd2FuY2VDb25kaXRpb24gPSBDb25kaXRpb24uYW5kKFxuICAgICAgQ29uZGl0aW9uLmF0dHJpYnV0ZTxBbGxvd2FuY2U+KFwib3duZXJcIikuZXEob3duZXIpLFxuICAgICAgQ29uZGl0aW9uLmF0dHJpYnV0ZTxBbGxvd2FuY2U+KFwic3BlbmRlclwiKS5lcShzcGVuZGVyKVxuICAgICk7XG5cbiAgICBjb25zdCBhbGxvd2FuY2UgPSBhd2FpdCB0aGlzLmFsbG93YW5jZVJlcG9zaXRvcnlcbiAgICAgIC5zZWxlY3QoKVxuICAgICAgLndoZXJlKGFsbG93YW5jZUNvbmRpdGlvbilcbiAgICAgIC5leGVjdXRlKGN0eCk7XG4gICAgcmV0dXJuIGFsbG93YW5jZT8uWzBdO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09IEV4dGVuZGVkIEZ1bmN0aW9ucyA9PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBTZXQgb3B0aW9uYWwgaW5mb21hdGlvbiBmb3IgYSB0b2tlbi5cbiAgICpcbiAgICogQHBhcmFtIHtDb250ZXh0fSBjdHggdGhlIHRyYW5zYWN0aW9uIGNvbnRleHRcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIHRva2VuXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzeW1ib2wgVGhlIHN5bWJvbCBvZiB0aGUgdG9rZW5cbiAgICogQHBhcmFtIHtTdHJpbmd9IGRlY2ltYWxzIFRoZSBkZWNpbWFscyBvZiB0aGUgdG9rZW5cbiAgICogQHBhcmFtIHtTdHJpbmd9IHRvdGFsU3VwcGx5IFRoZSB0b3RhbFN1cHBseSBvZiB0aGUgdG9rZW5cbiAgICovXG4gIEBUcmFuc2FjdGlvbigpXG4gIGFzeW5jIEluaXRpYWxpemUoY29udGV4dDogQ29udGV4dCwgdG9rZW46IEVSQzIwVG9rZW4pIHtcbiAgICBjb25zdCB7IGN0eCB9ID0gYXdhaXQgdGhpcy5sb2dDdHgoW2NvbnRleHRdLCB0aGlzLkluaXRpYWxpemUpO1xuICAgIC8vIENoZWNrIGNvbnRyYWN0IG9wdGlvbnMgYXJlIG5vdCBhbHJlYWR5IHNldCwgY2xpZW50IGlzIG5vdCBhdXRob3JpemVkIHRvIGNoYW5nZSB0aGVtIG9uY2UgaW50aXRpYWxpemVkXG4gICAgY29uc3QgdG9rZW5zID0gYXdhaXQgdGhpcy50b2tlblJlcG9zaXRvcnkuc2VsZWN0KCkuZXhlY3V0ZShjdHgpO1xuICAgIGlmICh0b2tlbnMubGVuZ3RoID4gMCkge1xuICAgICAgdGhyb3cgbmV3IEF1dGhvcml6YXRpb25FcnJvcihcbiAgICAgICAgXCJjb250cmFjdCBvcHRpb25zIGFyZSBhbHJlYWR5IHNldCwgY2xpZW50IGlzIG5vdCBhdXRob3JpemVkIHRvIGNoYW5nZSB0aGVtXCJcbiAgICAgICk7XG4gICAgfVxuXG4gICAgdG9rZW4ub3duZXIgPSBjdHguaWRlbnRpdHkuZ2V0SUQoKTtcblxuICAgIGF3YWl0IHRoaXMudG9rZW5SZXBvc2l0b3J5LmNyZWF0ZSh0b2tlbiwgY3R4KTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLy8gQ2hlY2tzIHRoYXQgY29udHJhY3Qgb3B0aW9ucyBoYXZlIGJlZW4gYWxyZWFkeSBpbml0aWFsaXplZFxuICBAVHJhbnNhY3Rpb24oZmFsc2UpXG4gIGFzeW5jIENoZWNrSW5pdGlhbGl6ZWQoY29udGV4dDogQ29udGV4dCkge1xuICAgIGNvbnN0IHsgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMuQ2hlY2tJbml0aWFsaXplZCk7XG4gICAgY29uc3QgdG9rZW5zID0gYXdhaXQgdGhpcy50b2tlblJlcG9zaXRvcnkuc2VsZWN0KCkuZXhlY3V0ZShjdHgpO1xuICAgIGlmICh0b2tlbnMubGVuZ3RoID09IDApIHtcbiAgICAgIHRocm93IG5ldyBOb3RJbml0aWFsaXplZEVycm9yKFxuICAgICAgICBcImNvbnRyYWN0IG9wdGlvbnMgbmVlZCB0byBiZSBzZXQgYmVmb3JlIGNhbGxpbmcgYW55IGZ1bmN0aW9uLCBjYWxsIEluaXRpYWxpemUoKSB0byBpbml0aWFsaXplIGNvbnRyYWN0XCJcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1pbnQgY3JlYXRlcyBuZXcgdG9rZW5zIGFuZCBhZGRzIHRoZW0gdG8gbWludGVyJ3MgYWNjb3VudCBiYWxhbmNlXG4gICAqXG4gICAqIEBwYXJhbSB7Q29udGV4dH0gY29udGV4dCB0aGUgdHJhbnNhY3Rpb24gY29udGV4dFxuICAgKiBAcGFyYW0ge251bWJlcn0gYW1vdW50IGFtb3VudCBvZiB0b2tlbnMgdG8gYmUgbWludGVkXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSBiYWxhbmNlXG4gICAqL1xuICBAT3duZXIoKVxuICBAVHJhbnNhY3Rpb24oKVxuICBhc3luYyBNaW50KGNvbnRleHQ6IENvbnRleHQsIGFtb3VudDogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5NaW50KTtcbiAgICAvLyBDaGVjayBjb250cmFjdCBvcHRpb25zIGFyZSBhbHJlYWR5IHNldCBmaXJzdCB0byBleGVjdXRlIHRoZSBmdW5jdGlvblxuICAgIGF3YWl0IHRoaXMuQ2hlY2tJbml0aWFsaXplZChjdHggYXMgYW55KTtcblxuICAgIC8vIEdldCBJRCBvZiBzdWJtaXR0aW5nIGNsaWVudCBpZGVudGl0eVxuICAgIGNvbnN0IG1pbnRlciA9IGN0eC5pZGVudGl0eS5nZXRJRCgpO1xuXG4gICAgaWYgKGFtb3VudCA8PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFwibWludCBhbW91bnQgbXVzdCBiZSBhIHBvc2l0aXZlIGludGVnZXJcIik7XG4gICAgfVxuXG4gICAgbGV0IG1pbnRlcldhbGxldDogRVJDMjBXYWxsZXQ7XG4gICAgdHJ5IHtcbiAgICAgIG1pbnRlcldhbGxldCA9IGF3YWl0IHRoaXMud2FsbGV0UmVwb3NpdG9yeS5yZWFkKG1pbnRlciwgY3R4KTtcblxuICAgICAgY29uc3QgY3VycmVudEJhbGFuY2UgPSBtaW50ZXJXYWxsZXQuYmFsYW5jZTtcblxuICAgICAgY29uc3QgdXBkYXRlZEJhbGFuY2UgPSBhZGQoY3VycmVudEJhbGFuY2UsIGFtb3VudCk7XG5cbiAgICAgIGNvbnN0IHVwZGF0ZWRtaW50ZXIgPSBPYmplY3QuYXNzaWduKHt9LCBtaW50ZXJXYWxsZXQsIHtcbiAgICAgICAgYmFsYW5jZTogdXBkYXRlZEJhbGFuY2UsXG4gICAgICB9KTtcblxuICAgICAgYXdhaXQgdGhpcy53YWxsZXRSZXBvc2l0b3J5LnVwZGF0ZSh1cGRhdGVkbWludGVyLCBjdHgpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIGlmIChlIGluc3RhbmNlb2YgQmFzZUVycm9yKSB7XG4gICAgICAgIGlmIChlLmNvZGUgPT09IDQwNCkge1xuICAgICAgICAgIC8vIENyZWF0ZSBhIG5ldyB3YWxsZXQgZm9yIHRoZSBtaW50ZXJcbiAgICAgICAgICBjb25zdCBuZXdXYWxsZXQgPSBuZXcgRVJDMjBXYWxsZXQoe1xuICAgICAgICAgICAgaWQ6IG1pbnRlcixcbiAgICAgICAgICAgIGJhbGFuY2U6IGFtb3VudCxcbiAgICAgICAgICAgIHRva2VuOiBhd2FpdCB0aGlzLlRva2VuTmFtZShjb250ZXh0KSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBhd2FpdCB0aGlzLndhbGxldFJlcG9zaXRvcnkuY3JlYXRlKG5ld1dhbGxldCwgY3R4KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihlLm1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihlIGFzIHN0cmluZyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRW1pdCB0aGUgVHJhbnNmZXIgZXZlbnRcbiAgICBjb25zdCB0cmFuc2ZlckV2ZW50ID0geyBmcm9tOiBcIjB4MFwiLCB0bzogbWludGVyLCB2YWx1ZTogYW1vdW50IH07XG4gICAgY29uc3QgZXZlbnRIYW5kbGVyID1cbiAgICAgIHRoaXMucmVwby5PYnNlcnZlckhhbmRsZXIoKSBhcyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnlPYnNlcnZhYmxlSGFuZGxlcjtcbiAgICBldmVudEhhbmRsZXIudXBkYXRlT2JzZXJ2ZXJzKFxuICAgICAgRVJDMjBUb2tlbixcbiAgICAgIEVSQzIwRXZlbnRzLlRSQU5TRkVSLFxuICAgICAgXCJcIixcbiAgICAgIHRyYW5zZmVyRXZlbnQsXG4gICAgICBjdHggYXMgdW5rbm93biBhcyBGYWJyaWNDb250cmFjdENvbnRleHRcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1cm4gcmVkZWVtIHRva2VucyBmcm9tIG1pbnRlcidzIGFjY291bnQgYmFsYW5jZVxuICAgKlxuICAgKiBAcGFyYW0ge0NvbnRleHR9IGNvbnRleHQgdGhlIHRyYW5zYWN0aW9uIGNvbnRleHRcbiAgICogQHBhcmFtIHtudW1iZXJ9IGFtb3VudCBhbW91bnQgb2YgdG9rZW5zIHRvIGJlIGJ1cm5lZFxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgYmFsYW5jZVxuICAgKi9cbiAgQE93bmVyKClcbiAgQFRyYW5zYWN0aW9uKClcbiAgYXN5bmMgQnVybihjb250ZXh0OiBDb250ZXh0LCBhbW91bnQ6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgbG9nLCBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5CdXJuKTtcbiAgICAvLyBDaGVjayBjb250cmFjdCBvcHRpb25zIGFyZSBhbHJlYWR5IHNldCBmaXJzdCB0byBleGVjdXRlIHRoZSBmdW5jdGlvblxuICAgIGF3YWl0IHRoaXMuQ2hlY2tJbml0aWFsaXplZChjdHggYXMgYW55KTtcblxuICAgIGNvbnN0IG1pbnRlciA9IGN0eC5pZGVudGl0eS5nZXRJRCgpO1xuXG4gICAgY29uc3QgbWludGVyV2FsbGV0ID0gYXdhaXQgdGhpcy53YWxsZXRSZXBvc2l0b3J5LnJlYWQobWludGVyLCBjdHgpO1xuXG4gICAgY29uc3QgY3VycmVudEJhbGFuY2UgPSBtaW50ZXJXYWxsZXQuYmFsYW5jZTtcblxuICAgIGlmIChjdXJyZW50QmFsYW5jZSA8IGFtb3VudCkge1xuICAgICAgdGhyb3cgbmV3IEJhbGFuY2VFcnJvcihgTWludGVyIGhhcyBpbnN1ZmZpY2llbnQgZnVuZHMuYCk7XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlZEJhbGFuY2UgPSBzdWIoY3VycmVudEJhbGFuY2UsIGFtb3VudCk7XG5cbiAgICBjb25zdCB1cGRhdGVkbWludGVyID0gT2JqZWN0LmFzc2lnbih7fSwgbWludGVyV2FsbGV0LCB7XG4gICAgICBiYWxhbmNlOiB1cGRhdGVkQmFsYW5jZSxcbiAgICB9KTtcblxuICAgIGF3YWl0IHRoaXMud2FsbGV0UmVwb3NpdG9yeS51cGRhdGUodXBkYXRlZG1pbnRlciwgY3R4KTtcblxuICAgIGxvZy5pbmZvKGAke2Ftb3VudH0gdG9rZW5zIHdlcmUgYnVybmVkYCk7XG5cbiAgICAvLyBFbWl0IHRoZSBUcmFuc2ZlciBldmVudFxuICAgIGNvbnN0IHRyYW5zZmVyRXZlbnQgPSB7IGZyb206IG1pbnRlciwgdG86IFwiMHgwXCIsIHZhbHVlOiBhbW91bnQgfTtcbiAgICBjb25zdCBldmVudEhhbmRsZXIgPVxuICAgICAgdGhpcy5yZXBvLk9ic2VydmVySGFuZGxlcigpIGFzIEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeU9ic2VydmFibGVIYW5kbGVyO1xuICAgIGV2ZW50SGFuZGxlci51cGRhdGVPYnNlcnZlcnMoXG4gICAgICBFUkMyMFRva2VuLFxuICAgICAgRVJDMjBFdmVudHMuVFJBTlNGRVIsXG4gICAgICBcIlwiLFxuICAgICAgdHJhbnNmZXJFdmVudCxcbiAgICAgIGN0eCBhcyB1bmtub3duIGFzIEZhYnJpY0NvbnRyYWN0Q29udGV4dFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQnVybkZyb20gcmVkZWVtIHRva2VucyBmcm9tIGFjY291bnQgYWxsb3dlbmNlIGFuZCBiYWxhbmNlXG4gICAqXG4gICAqIEBwYXJhbSB7Q29udGV4dH0gY29udGV4dCB0aGUgdHJhbnNhY3Rpb24gY29udGV4dFxuICAgKiBAcGFyYW0ge251bWJlcn0gYWNjb3VudCBhY2NvdW50IGZyb20gd2hlcmUgdG9rZW5zIHdpbGwgYmUgYnVybmVkXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBhbW91bnQgYW1vdW50IG9mIHRva2VucyB0byBiZSBidXJuZWRcbiAgICogQHJldHVybnMge09iamVjdH0gVGhlIGJhbGFuY2VcbiAgICovXG4gIEBPd25lcigpXG4gIEBUcmFuc2FjdGlvbigpXG4gIGFzeW5jIEJ1cm5Gcm9tKFxuICAgIGNvbnRleHQ6IENvbnRleHQsXG4gICAgYWNjb3VudDogc3RyaW5nLFxuICAgIGFtb3VudDogbnVtYmVyXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgbG9nLCBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5CdXJuRnJvbSk7XG4gICAgLy8gQ2hlY2sgY29udHJhY3Qgb3B0aW9ucyBhcmUgYWxyZWFkeSBzZXQgZmlyc3QgdG8gZXhlY3V0ZSB0aGUgZnVuY3Rpb25cbiAgICBhd2FpdCB0aGlzLkNoZWNrSW5pdGlhbGl6ZWQoY3R4IGFzIGFueSk7XG5cbiAgICBjb25zdCBhY2NvdW50V2FsbGV0ID0gYXdhaXQgdGhpcy53YWxsZXRSZXBvc2l0b3J5LnJlYWQoYWNjb3VudCwgY3R4KTtcblxuICAgIGNvbnN0IGN1cnJlbnRCYWxhbmNlID0gYWNjb3VudFdhbGxldC5iYWxhbmNlO1xuXG4gICAgaWYgKGN1cnJlbnRCYWxhbmNlIDwgYW1vdW50KSB7XG4gICAgICB0aHJvdyBuZXcgQmFsYW5jZUVycm9yKGAke2FjY291bnR9IGhhcyBpbnN1ZmZpY2llbnQgZnVuZHMuYCk7XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlZEJhbGFuY2UgPSBzdWIoY3VycmVudEJhbGFuY2UsIGFtb3VudCk7XG5cbiAgICBjb25zdCB1cGRhdGVkYWNjb3VudCA9IE9iamVjdC5hc3NpZ24oe30sIGFjY291bnRXYWxsZXQsIHtcbiAgICAgIGJhbGFuY2U6IHVwZGF0ZWRCYWxhbmNlLFxuICAgIH0pO1xuXG4gICAgYXdhaXQgdGhpcy53YWxsZXRSZXBvc2l0b3J5LnVwZGF0ZSh1cGRhdGVkYWNjb3VudCwgY3R4KTtcblxuICAgIGxvZy5pbmZvKGAke2Ftb3VudH0gdG9rZW5zIHdlcmUgYnVybmVkIGZyb20gJHthY2NvdW50fWApO1xuXG4gICAgLy8gRW1pdCB0aGUgVHJhbnNmZXIgZXZlbnRcbiAgICBjb25zdCB0cmFuc2ZlckV2ZW50ID0geyBmcm9tOiBhY2NvdW50LCB0bzogXCIweDBcIiwgdmFsdWU6IGFtb3VudCB9O1xuICAgIGNvbnN0IGV2ZW50SGFuZGxlciA9XG4gICAgICB0aGlzLnJlcG8uT2JzZXJ2ZXJIYW5kbGVyKCkgYXMgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5T2JzZXJ2YWJsZUhhbmRsZXI7XG4gICAgZXZlbnRIYW5kbGVyLnVwZGF0ZU9ic2VydmVycyhcbiAgICAgIEVSQzIwVG9rZW4sXG4gICAgICBFUkMyMEV2ZW50cy5UUkFOU0ZFUixcbiAgICAgIFwiXCIsXG4gICAgICB0cmFuc2ZlckV2ZW50LFxuICAgICAgY3R4IGFzIHVua25vd24gYXMgRmFicmljQ29udHJhY3RDb250ZXh0XG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGllbnRBY2NvdW50QmFsYW5jZSByZXR1cm5zIHRoZSBiYWxhbmNlIG9mIHRoZSByZXF1ZXN0aW5nIGNsaWVudCdzIGFjY291bnQuXG4gICAqXG4gICAqIEBwYXJhbSB7Q29udGV4dH0gY29udGV4dCB0aGUgdHJhbnNhY3Rpb24gY29udGV4dFxuICAgKiBAcmV0dXJucyB7TnVtYmVyfSBSZXR1cm5zIHRoZSBhY2NvdW50IGJhbGFuY2VcbiAgICovXG4gIEBUcmFuc2FjdGlvbihmYWxzZSlcbiAgYXN5bmMgQ2xpZW50QWNjb3VudEJhbGFuY2UoY29udGV4dDogQ29udGV4dCk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IHRoaXMubG9nQ3R4KFtjb250ZXh0XSwgdGhpcy5Ub2tlbk5hbWUpO1xuICAgIC8vIENoZWNrIGNvbnRyYWN0IG9wdGlvbnMgYXJlIGFscmVhZHkgc2V0IGZpcnN0IHRvIGV4ZWN1dGUgdGhlIGZ1bmN0aW9uXG4gICAgYXdhaXQgdGhpcy5DaGVja0luaXRpYWxpemVkKGN0eCBhcyBhbnkpO1xuXG4gICAgLy8gR2V0IElEIG9mIHN1Ym1pdHRpbmcgY2xpZW50IGlkZW50aXR5XG4gICAgY29uc3QgY2xpZW50QWNjb3VudElEID0gY3R4LmlkZW50aXR5LmdldElEKCk7XG5cbiAgICBjb25zdCBjbGllbnRXYWxsZXQgPSBhd2FpdCB0aGlzLndhbGxldFJlcG9zaXRvcnkucmVhZChjbGllbnRBY2NvdW50SUQsIGN0eCk7XG5cbiAgICBpZiAoIWNsaWVudFdhbGxldCkge1xuICAgICAgdGhyb3cgbmV3IEJhbGFuY2VFcnJvcihgVGhlIGFjY291bnQgJHtjbGllbnRBY2NvdW50SUR9IGRvZXMgbm90IGV4aXN0YCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNsaWVudFdhbGxldC5iYWxhbmNlO1xuICB9XG5cbiAgLy8gQ2xpZW50QWNjb3VudElEIHJldHVybnMgdGhlIGlkIG9mIHRoZSByZXF1ZXN0aW5nIGNsaWVudCdzIGFjY291bnQuXG4gIC8vIEluIHRoaXMgaW1wbGVtZW50YXRpb24sIHRoZSBjbGllbnQgYWNjb3VudCBJRCBpcyB0aGUgY2xpZW50SWQgaXRzZWxmLlxuICAvLyBVc2VycyBjYW4gdXNlIHRoaXMgZnVuY3Rpb24gdG8gZ2V0IHRoZWlyIG93biBhY2NvdW50IGlkLCB3aGljaCB0aGV5IGNhbiB0aGVuIGdpdmUgdG8gb3RoZXJzIGFzIHRoZSBwYXltZW50IGFkZHJlc3NcbiAgQFRyYW5zYWN0aW9uKGZhbHNlKVxuICBhc3luYyBDbGllbnRBY2NvdW50SUQoY29udGV4dDogQ29udGV4dCkge1xuICAgIGNvbnN0IHsgY3R4IH0gPSBhd2FpdCB0aGlzLmxvZ0N0eChbY29udGV4dF0sIHRoaXMuQ2xpZW50QWNjb3VudElEKTtcbiAgICAvLyBDaGVjayBjb250cmFjdCBvcHRpb25zIGFyZSBhbHJlYWR5IHNldCBmaXJzdCB0byBleGVjdXRlIHRoZSBmdW5jdGlvblxuICAgIGF3YWl0IHRoaXMuQ2hlY2tJbml0aWFsaXplZChjdHggYXMgYW55KTtcblxuICAgIC8vIEdldCBJRCBvZiBzdWJtaXR0aW5nIGNsaWVudCBpZGVudGl0eVxuICAgIGNvbnN0IGNsaWVudEFjY291bnRJRCA9IGN0eC5pZGVudGl0eS5nZXRJRCgpO1xuICAgIHJldHVybiBjbGllbnRBY2NvdW50SUQ7XG4gIH1cbn1cbiIsImltcG9ydCB7IEZhYnJpY0VSQzIwQ29udHJhY3QgfSBmcm9tIFwiLi9lcmMyMGNvbnRyYWN0XCI7XG5cbmV4cG9ydCAqIGZyb20gXCIuLi9GYWJyaWNDb250cmFjdFN0YXRlbWVudFwiO1xuXG5leHBvcnQgY29uc3QgY29udHJhY3RzOiBhbnlbXSA9IFtGYWJyaWNFUkMyMENvbnRyYWN0XTtcbiIsImltcG9ydCB7IE1ldGFkYXRhIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5cbmV4cG9ydCBjb25zdCBWRVJTSU9OID0gXCIjI1ZFUlNJT04jI1wiO1xuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfTkFNRSA9IFwiIyNQQUNLQUdFIyNcIjtcblxuTWV0YWRhdGEucmVnaXN0ZXJMaWJyYXJ5KFBBQ0tBR0VfTkFNRSwgVkVSU0lPTik7XG4iXSwibmFtZXMiOlsiRmFicmljQ29udHJhY3RDb250ZXh0IiwiQ29udGV4dCIsImNvbnN0cnVjdG9yIiwic3VwZXIiLCJzdHViIiwidGhpcyIsImdldCIsInRpbWVzdGFtcCIsImdldERhdGVUaW1lc3RhbXAiLCJpZGVudGl0eSIsInRvU3RyaW5nIiwiZ2VuZXJhdGVGYWJyaWNFdmVudE5hbWUiLCJ0YWJsZSIsImV2ZW50Iiwib3duZXIiLCJwYXJhbXMiLCJwdXNoIiwiam9pbiIsInBhcnNlRXZlbnROYW1lIiwibmFtZSIsInBhcnRzIiwic3BsaXQiLCJsZW5ndGgiLCJ1bmRlZmluZWQiLCJGYWJyaWNDb250cmFjdFJlcG9zaXRvcnlPYnNlcnZhYmxlSGFuZGxlciIsIk9ic2VydmVySGFuZGxlciIsInN1cHBvcnRlZEV2ZW50cyIsIk9wZXJhdGlvbktleXMiLCJDUkVBVEUiLCJVUERBVEUiLCJERUxFVEUiLCJCdWxrQ3J1ZE9wZXJhdGlvbktleXMiLCJDUkVBVEVfQUxMIiwiVVBEQVRFX0FMTCIsIkRFTEVURV9BTEwiLCJ1cGRhdGVPYnNlcnZlcnMiLCJjbGF6eiIsImlkIiwiYXJncyIsImxvZyIsImN0eCIsIkFkYXB0ZXIiLCJsb2dDdHgiLCJwYXlsb2FkIiwiaW5kZXhPZiIsImRlYnVnIiwiZXZlbnROYW1lIiwic2V0RXZlbnQiLCJCdWZmZXIiLCJmcm9tIiwiSlNPTiIsInN0cmluZ2lmeSIsIkZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeSIsIlJlcG9zaXRvcnkiLCJhZGFwdGVyIiwidHJhY2tlZEV2ZW50cyIsIl9vdmVycmlkZXMiLCJPYmplY3QiLCJhc3NpZ24iLCJpZ25vcmVWYWxpZGF0aW9uIiwiaWdub3JlSGFuZGxlcnMiLCJhbGxvd1Jhd1N0YXRlbWVudHMiLCJmb3JjZVByZXBhcmVTaW1wbGVRdWVyaWVzIiwiZm9yY2VQcmVwYXJlQ29tcGxleFF1ZXJpZXMiLCJwYWdpbmF0ZUJ5Iiwia2V5Iiwib3JkZXIiLCJyZWYiLCJvZmZzZXQiLCJsaW1pdCIsImJvb2ttYXJrIiwiUXVlcnlFcnJvciIsImNvbnRleHRBcmdzIiwiUHJlcGFyZWRTdGF0ZW1lbnRLZXlzIiwiUEFHRV9CWSIsImNsYXNzIiwiY3R4QXJncyIsInZlcmJvc2UiLCJNb2RlbCIsInRhYmxlTmFtZSIsInBhZ2luYXRvciIsIm92ZXJyaWRlIiwic2VsZWN0Iiwid2hlcmUiLCJhdHRyIiwicGsiLCJndCIsIm9yZGVyQnkiLCJwYWdpbmF0ZSIsInBhZ2VkIiwicGFnZSIsInNlcmlhbGl6ZSIsInN0YXRlbWVudCIsInN0YXRlbWVudHMiLCJQZXJzaXN0ZW5jZUtleXMiLCJTVEFURU1FTlQiLCJjb250ZXh0IiwibG9nZ2VyIiwiaW5mbyIsInJlc3VsdCIsImUiLCJCYXNlRXJyb3IiLCJJbnRlcm5hbEVycm9yIiwiRmFicmljU3RhdGVtZW50IiwiQ291Y2hEQlN0YXRlbWVudCIsInJhdyIsInJhd0lucHV0IiwicmVzdWx0cyIsInBrQXR0ciIsImZyb21TZWxlY3RvciIsInR5cGUiLCJNZXRhZGF0YSIsIkRCS2V5cyIsIklEIiwic2VsZWN0U2VsZWN0b3IiLCJtYXAiLCJyIiwicHJvY2Vzc1JlY29yZCIsImJ1aWxkIiwic2VsZWN0b3JzIiwiQ291Y2hEQktleXMiLCJUQUJMRSIsInF1ZXJ5Iiwic2VsZWN0b3IiLCJmaWVsZHMiLCJ3aGVyZUNvbmRpdGlvbiIsImNvbmRpdGlvbiIsInBhcnNlQ29uZGl0aW9uIiwiQ29uZGl0aW9uIiwiYW5kIiwiYXR0cmlidXRlIiwiZXEiLCJzZWxlY3RvcktleXMiLCJrZXlzIiwidmFsdWVzIiwiQ291Y2hEQkdyb3VwT3BlcmF0b3IiLCJBTkQiLCJyZWR1Y2UiLCJhY2N1bSIsInZhbCIsIkVycm9yIiwiayIsIk9SIiwicyIsImVudHJpZXMiLCJmb3JFYWNoIiwiY29uc29sZSIsIndhcm4iLCJvcmRlckJ5U2VsZWN0b3IiLCJzb3J0IiwidmFsdWUiLCJyZWMiLCJDb3VjaERCT3BlcmF0b3IiLCJCSUdHRVIiLCJsaW1pdFNlbGVjdG9yIiwib2Zmc2V0U2VsZWN0b3IiLCJza2lwIiwiRmFicmljQ29udHJhY3RTZXF1ZW5jZSIsIlNlcXVlbmNlIiwib3B0aW9ucyIsImN1cnJlbnQiLCJSRUFEIiwiU2VxdWVuY2VNb2RlbCIsInN0YXJ0V2l0aCIsInNlcXVlbmNlIiwicmVwbyIsInJlYWQiLCJwYXJzZSIsImZvciIsIk5vdEZvdW5kRXJyb3IiLCJjYWNoZWRDdXJyZW50IiwiaW5jcmVtZW50IiwiY291bnQiLCJpbmNyZW1lbnRCeSIsImxvY2siLCJleGVjdXRlIiwiYXN5bmMiLCJ0b0luY3JlbWVudEJ5IiwidHlwZU5hbWUiLCJjdXJyZW50VmFsdWUiLCJyZXR1cm5BbmRDYWNoZSIsInJlcyIsIlByb21pc2UiLCJjYWNoZSIsInB1dCIsInBlcmZvcm1VcHNlcnQiLCJuZXh0IiwidXBkYXRlIiwiY3JlYXRlIiwiaW5jcmVtZW50U2VyaWFsIiwiYmFzZSIsIk51bWJlciIsIkJpZ0ludCIsIlN0cmluZyIsIlNlcmlhbCIsImluc3RhbmNlIiwiZ2VuZXJhdGUiLCJVVUlEIiwiQ29uZmxpY3RFcnJvciIsInNlcSIsIkZhYnJpY01vZGVsS2V5cyIsIklkZW50aXR5VHlwZSIsIkZhYnJpY0ZsYXZvdXIiLCJTaW1wbGVEZXRlcm1pbmlzdGljU2VyaWFsaXplciIsIkpTT05TZXJpYWxpemVyIiwiZGVzZXJpYWxpemUiLCJzdHIiLCJkZXNlcmlhbGl6YXRpb24iLCJtb2RlbCIsInB1dEFuY2hvciIsInJlcXVpcmUiLCJzb3J0S2V5c1JlY3Vyc2l2ZSIsInByZVNlcmlhbGl6YXRpb24iLCJwcmVTZXJpYWxpemUiLCJ0b1NlcmlhbGl6ZSIsIm1ldGFkYXRhIiwibW9kZWxOYW1lIiwiZXJyb3IiLCJNb2RlbEtleXMiLCJBTkNIT1IiLCJvYmoiLCJBcnJheSIsImlzQXJyYXkiLCJyZWxhdGlvbnMiLCJjYWxsIiwiQ29udHJhY3RMb2dnZXIiLCJNaW5pTG9nZ2VyIiwiY29uZiIsImxvZ2dpbmciLCJnZXRMb2dnZXIiLCJsZXZlbCIsIm1zZyIsInN0YWNrIiwiTnVtZXJpY0xvZ0xldmVscyIsImNvbmZpZyIsIm1ldGhvZCIsIkxvZ0xldmVsIiwic2lsbHkiLCJjcmVhdGVMb2ciLCJmYWN0b3J5Iiwib2JqZWN0IiwiTG9nZ2luZyIsInNldEZhY3RvcnkiLCJGYWJyaWNDb250cmFjdFBhZ2luYXRvciIsIkNvdWNoREJQYWdpbmF0b3IiLCJzaXplIiwicHJlcGFyZSIsInJhd1N0YXRlbWVudCIsImlzUHJlcGFyZWRTdGF0ZW1lbnQiLCJwYWdlUHJlcGFyZWQiLCJfcmVjb3JkQ291bnQiLCJfdG90YWxQYWdlcyIsIk1hdGgiLCJjZWlsIiwidmFsaWRhdGVQYWdlIiwiX2Jvb2ttYXJrIiwiUGFnaW5nRXJyb3IiLCJkb2NzIiwiZCIsInJldmVydCIsInBhcnNlVmFsdWUiLCJkaXJlY3Rpb24iLCJPcmRlckRpcmVjdGlvbiIsIkRTQyIsIkFTQyIsIl9jdXJyZW50UGFnZSIsIk92ZXJmbG93RXJyb3IiLCJCYWxhbmNlRXJyb3IiLCJBbGxvd2FuY2VFcnJvciIsIlJlZ2lzdHJhdGlvbkVycm9yIiwiQXV0aG9yaXphdGlvbkVycm9yIiwiTWlzc2luZ0NvbnRleHRFcnJvciIsIlVuYXV0aG9yaXplZFByaXZhdGVEYXRhQWNjZXNzIiwiTm90SW5pdGlhbGl6ZWRFcnJvciIsIk1pc3NpbmdQS0NTUzExTGliIiwiRW5kb3JzZW1lbnRFcnJvciIsIm1lc3NhZ2UiLCJNdmNjUmVhZENvbmZsaWN0RXJyb3IiLCJQaGFudG9tUmVhZENvbmZsaWN0RXJyb3IiLCJFbmRvcnNlbWVudFBvbGljeUVycm9yIiwiY3JlYXRlZEJ5T25GYWJyaWNDcmVhdGVVcGRhdGUiLCJkYXRhIiwidXNlciIsImdldElEIiwiVW5zdXBwb3J0ZWRFcnJvciIsInBrRmFicmljT25DcmVhdGUiLCJzZXRQcmltYXJ5S2V5VmFsdWUiLCJ0YXJnZXQiLCJwcm9wZXJ0eUtleSIsImRlZmluZVByb3BlcnR5IiwiZW51bWVyYWJsZSIsIndyaXRhYmxlIiwiY29uZmlndXJhYmxlIiwic2VxdWVuY2VOYW1lIiwiRmFicmljQ29udHJhY3RBZGFwdGVyIiwiQ291Y2hEQkFkYXB0ZXIiLCJnZXRDbGllbnQiLCJ0ZXh0RGVjb2RlciIsIlRleHREZWNvZGVyIiwic2VyaWFsaXplciIsInJlcG9zaXRvcnkiLCJQYWdpbmF0b3IiLCJzY29wZSIsImFsaWFzIiwiY29tcG9zZWRLZXkiLCJjcmVhdGVDb21wb3NpdGVLZXkiLCJwdXRTdGF0ZSIsInBhcnNlRXJyb3IiLCJyZWFkU3RhdGUiLCJkZWxldGUiLCJkZWxldGVTdGF0ZSIsImZvclByaXZhdGUiLCJjb2xsZWN0aW9uIiwidG9PdmVycmlkZSIsInF1ZXJ5UmVzdWx0IiwicXVlcnlSZXN1bHRQYWdpbmF0ZWQiLCJmbiIsIlByb3h5IiwicHJvcCIsInJlY2VpdmVyIiwiaW5jbHVkZXMiLCJSZWZsZWN0IiwiYXBwbHkiLCJ0aGlzQXJnIiwiYXJnc0xpc3QiLCJwdXRQcml2YXRlRGF0YSIsImRlbGV0ZVByaXZhdGVEYXRhIiwiZ2V0UHJpdmF0ZURhdGEiLCJnZXRQcml2YXRlRGF0YVF1ZXJ5UmVzdWx0IiwiaXRlcmF0b3IiLCJyZWFjaGVkQm9va21hcmsiLCJsYXN0S2V5IiwicmVjb3JkS2V5IiwicmVjb3JkVmFsdWUiLCJLZXkiLCJSZWNvcmQiLCJjbG9zZSIsImZldGNoZWRSZWNvcmRzQ291bnQiLCJkb25lIiwiU2VyaWFsaXphdGlvbkVycm9yIiwiZ2V0U3RhdGUiLCJnZXRRdWVyeVJlc3VsdCIsIl9pZCIsIiRndCIsIiRndGUiLCJpdCIsImdldFF1ZXJ5UmVzdWx0V2l0aFBhZ2luYXRpb24iLCJtZXJnZU1vZGVscyIsImV4dHJhY3QiLCJmaW5hbE1vZGVsIiwicG9wIiwiZGVjb2RlIiwiYnVmZmVyIiwiZmxhZ3MiLCJvcGVyYXRpb24iLCJiYXNlRmxhZ3MiLCJzZWdyZWdhdGVkIiwiY29ycmVsYXRpb25JZCIsImdldFR4SUQiLCJjbGllbnRJZGVudGl0eSIsImluZGV4IiwibW9kZWxzIiwicmVzb2x2ZSIsInJlc3VsdEl0ZXJhdG9yIiwiaXNIaXN0b3J5IiwiYWxsUmVzdWx0cyIsImpzb25SZXMiLCJUeElkIiwidHhJZCIsIlRpbWVzdGFtcCIsIlZhbHVlIiwiZXJyIiwiZG9jc09ubHkiLCJyZXNwb25zZSIsIlN0YXRlbWVudCIsImNyZWF0ZUFsbCIsInRhYmxlTGFiZWwiLCJhbGwiLCJpIiwidXBkYXRlQWxsIiwic2VncmVnYXRlIiwibWFwcGVkUHJvcCIsImNvbHVtbk5hbWUiLCJpc1Jlc2VydmVkIiwicmVjb3JkIiwidHJhbnNpZW50Iiwib2IiLCJtIiwiY3JlYXRlUHJlZml4IiwidXBkYXRlUHJlZml4IiwiY3JlYXRlQWxsUHJlZml4IiwiaWRzIiwicmVjb3JkcyIsInVwZGF0ZUFsbFByZWZpeCIsInJlYXNvbiIsImZpbHRlciIsImEiLCJjbGVhciIsIkJhZFJlcXVlc3RFcnJvciIsIk1pZ3JhdGlvbkVycm9yIiwiT2JzZXJ2ZXJFcnJvciIsIkZvcmJpZGRlbkVycm9yIiwiQ29ubmVjdGlvbkVycm9yIiwiZGVjb3JhdGlvbiIsIkRlY29yYXRpb24iLCJmbGF2b3VyZWRBcyIsIkNSRUFURURfQlkiLCJkZWZpbmUiLCJvbkNyZWF0ZSIsInByb3BNZXRhZGF0YSIsIlVQREFURURfQlkiLCJvbkNyZWF0ZVVwZGF0ZSIsIkNPTFVNTiIsImV4dGVuZCIsIkZhYnJpY1Byb3BlcnR5IiwiUHJvcGVydHkiLCJWYWxpZGF0aW9uS2V5cyIsIkRBVEUiLCJmYWJyaWNQcm9wZXJ0eSIsImNoYWluIiwiY29uc3RyIiwicHJvdG90eXBlIiwiZ2V0UHJvdG90eXBlT2YiLCJjIiwiRmFicmljT2JqZWN0Iiwic2V0Q3VycmVudCIsIkRldGVybWluaXN0aWNTZXJpYWxpemVyIiwic2VsZiIsIm8iLCJiaW5kIiwiY2xhc3NOYW1lIiwiRGF0ZSIsIkZhYnJpY0NydWRDb250cmFjdCIsIkNvbnRyYWN0IiwiaW5pdGlhbGl6ZWQiLCJmb3JNb2RlbCIsImxpc3RCeSIsImZpbmRPbmVCeSIsImdldFRyYW5zaWVudERhdGEiLCJtZXJnZSIsInRyYW5zaWVudE1hcCIsImdldFRyYW5zaWVudCIsImhhcyIsImRlbGV0ZUFsbCIsInJlYWRBbGwiLCJpbml0IiwiZ2V0TmFtZSIsImhlYWx0aGNoZWNrIiwiQ3R4IiwiZ2V0T3AiLCJSRUFEX0FMTCIsIm92ZXJyaWRlcyIsIlNlcmlhbGl6ZWRDcnVkQ29udHJhY3QiLCJzZXJpYWxpemVkIiwicGFyc2VkS2V5cyIsImxpc3QiLCJtb2RlbExpc3QiLCJjb25kIiwiX19kZWNvcmF0ZSIsIlRyYW5zYWN0aW9uIiwiX19tZXRhZGF0YSIsImFkZCIsImIiLCJzdWIiLCJzYWZlUGFyc2VJbnQiLCJzdHJpbmciLCJkaWdpdFJlZ2V4IiwidGVzdCIsIlZhbGlkYXRpb25FcnJvciIsInN0cmluZ0Zvcm1hdCIsInBhcnNlZGludCIsInBhcnNlSW50IiwiaXNOYU4iLCJFUkMyMFRva2VuIiwiQmFzZU1vZGVsIiwiY29sdW1uIiwicmVxdWlyZWQiLCJFUkMyMFdhbGxldCIsIkFsbG93YW5jZSIsIk93bmVyIiwiZGVzY3JpcHRvciIsIm9yaWdpbmFsTWV0aG9kIiwiYWNvdW50SWQiLCJ0b2tlbnMiLCJvd25lZEJ5T25DcmVhdGUiLCJjcmVhdG9yIiwiZ2V0Q3JlYXRvciIsIm1zcGlkIiwic2V0T3duZWRCeUtleVZhbHVlIiwib3duZWRCeSIsImdldEZhYnJpY01vZGVsS2V5IiwiT1dORURCWSIsInJlYWRvbmx5IiwiZGVjb3JhdG9yIiwidHJhbnNhY3Rpb25JZE9uQ3JlYXRlIiwidHJhbnNhY3Rpb25JZCIsIm9uVXBkYXRlIiwiRkFCUklDIiwiVFJBTlNBQ1RJT05fSUQiLCJJbXBsaWNpdFByaXZhdGVDb2xsZWN0aW9uIiwic2VncmVnYXRlZERhdGFPbkNyZWF0ZSIsImNvbGxlY3Rpb25SZXNvbHZlciIsImNvbGxlY3Rpb25zIiwicmVidWlsdCIsImFjYyIsInRvQ3JlYXRlIiwiY3JlYXRlZCIsInNlZ3JlZ2F0ZWREYXRhT25SZWFkIiwic2VncmVnYXRlZERhdGFPblVwZGF0ZSIsIm9sZE1vZGVsIiwic2VncmVnYXRlZERhdGFPbkRlbGV0ZSIsImlubmVyU2VncmVnYXRlZCIsInNlZ3JlZ2F0ZWREZWMiLCJwcm9wcyIsInByb3BlcnRpZXMiLCJtZXRhIiwiU2V0Iiwic2V0IiwiZGVjcyIsInAiLCJwcmlvcml0eSIsImdyb3VwIiwib25SZWFkIiwib25EZWxldGUiLCJwcml2YXRlRGF0YSIsIlBSSVZBVEUiLCJzaGFyZWREYXRhIiwiU0hBUkVEIiwiRVJDMjBFdmVudHMiLCJGYWJyaWNFUkMyMENvbnRyYWN0Iiwid2FsbGV0UmVwb3NpdG9yeSIsInRva2VuUmVwb3NpdG9yeSIsImFsbG93YW5jZVJlcG9zaXRvcnkiLCJUb2tlbk5hbWUiLCJDaGVja0luaXRpYWxpemVkIiwidG9rZW4iLCJTeW1ib2wiLCJzeW1ib2wiLCJEZWNpbWFscyIsImRlY2ltYWxzIiwiVG90YWxTdXBwbHkiLCJ3YWxsZXRzIiwidG90YWwiLCJ3YWxsZXQiLCJiYWxhbmNlIiwiQmFsYW5jZU9mIiwiVHJhbnNmZXIiLCJ0byIsInRyYW5zZmVyUmVzcCIsIl90cmFuc2ZlciIsIlRyYW5zZmVyRnJvbSIsIkJ1cm5Gcm9tIiwic3BlbmRlciIsImFsbG93YW5jZSIsIl9nZXRBbGxvd2FuY2UiLCJjdXJyZW50QWxsb3dhbmNlIiwidXBkYXRlZEFsbG93YW5jZSIsIm5ld0FsbG93YW5jZSIsImZyb21XYWxsZXQiLCJmcm9tQmFsYW5jZSIsInRvV2FsbGV0IiwibmV3VG9XYWxsZXQiLCJjb2RlIiwidG9CYWxhbmNlIiwiZnJvbVVwZGF0ZWRCYWxhbmNlIiwidG9VcGRhdGVkQmFsYW5jZSIsInVwZGF0ZWRGcm9tV2FsbGV0IiwidXBkYXRlZFRvV2FsbGV0IiwidHJhbnNmZXJFdmVudCIsInJlZnJlc2giLCJUUkFOU0ZFUiIsImNhdGNoIiwiQXBwcm92ZSIsIm93bmVyV2FsbGV0IiwiYXBwcm92YWxFdmVudCIsIkFQUFJPVkFMIiwiYWxsb3dhbmNlQ29uZGl0aW9uIiwiSW5pdGlhbGl6ZSIsIk1pbnQiLCJhbW91bnQiLCJtaW50ZXIiLCJtaW50ZXJXYWxsZXQiLCJjdXJyZW50QmFsYW5jZSIsInVwZGF0ZWRCYWxhbmNlIiwidXBkYXRlZG1pbnRlciIsIm5ld1dhbGxldCIsImV2ZW50SGFuZGxlciIsIkJ1cm4iLCJhY2NvdW50IiwiYWNjb3VudFdhbGxldCIsInVwZGF0ZWRhY2NvdW50IiwiQ2xpZW50QWNjb3VudEJhbGFuY2UiLCJjbGllbnRBY2NvdW50SUQiLCJjbGllbnRXYWxsZXQiLCJDbGllbnRBY2NvdW50SUQiLCJjb250cmFjdHMiLCJWRVJTSU9OIiwiUEFDS0FHRV9OQU1FIiwicmVnaXN0ZXJMaWJyYXJ5Il0sIm1hcHBpbmdzIjoiOzs7OztJQWtDTSxNQUFPQSw4QkFBOEJDLEtBQUFBO1FBS3pDLFdBQUFDO1lBQ0VDO0FBQ0Q7UUFPRCxRQUFJQztZQUNGLE9BQU9DLEtBQUtDLElBQUk7QUFDakI7UUFPRCxhQUFhQztZQUNYLE9BQU9GLEtBQUtELEtBQUtJO0FBQ2xCO1FBT0QsWUFBSUM7WUFDRixPQUFPSixLQUFLQyxJQUFJ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
1
+ var t,e;t=this,e=function(t,e,r,a,n,i,o,s,c){"use strict";class l extends a.Context{constructor(){super()}get stub(){return this.get("stub")}get timestamp(){return this.stub.getDateTimestamp()}get identity(){return this.get("identity")}toString(){return"fabric ctx"+(this.stub?" with stub":"without stub")}}class d extends a.ObserverHandler{constructor(t=[n.OperationKeys.CREATE,n.OperationKeys.UPDATE,n.OperationKeys.DELETE,n.BulkCrudOperationKeys.CREATE_ALL,n.BulkCrudOperationKeys.UPDATE_ALL,n.BulkCrudOperationKeys.DELETE_ALL]){super(),this.supportedEvents=t}async updateObservers(t,e,r,...n){const{log:i,ctx:o}=a.Adapter.logCtx(n,this.updateObservers),{stub:s}=o,[c,l]=n,d="string"==typeof t?t:t.name;if(-1!==this.supportedEvents.indexOf(e)){i.debug(`Emitting ${e} event`);const t=((t,e,r)=>{const a=[t,e];return r&&a.push(r),a.join("_")})(d,e,c);s.setEvent(t,Buffer.from(JSON.stringify({id:r})))}else s.setEvent(e,Buffer.from(JSON.stringify(l)))}}class u extends a.Repository{constructor(t,e,r){super(t,e),this.trackedEvents=r,this._overrides=Object.assign({},super._overrides,{ignoreValidation:!1,ignoreHandlers:!1,allowRawStatements:!0,forcePrepareSimpleQueries:!1,forcePrepareComplexQueries:!1})}async paginateBy(t,e,n={offset:1,limit:10},...i){let{offset:o,bookmark:s,limit:c}=n;if(!o&&!s)throw new a.QueryError("PaginateBy needs a page or a bookmark");const l=await a.Context.args(a.PreparedStatementKeys.PAGE_BY,this.class,i,this.adapter,this._overrides||{}),{log:d,ctxArgs:u}=this.logCtx(l.args,this.paginateBy);let g;if(d.verbose(`paginating ${r.Model.tableName(this.class)} with page size ${c}`),s)g=await this.override({forcePrepareComplexQueries:!1,forcePrepareSimpleQueries:!1}).select().where(this.attr(r.Model.pk(this.class)).gt(s)).orderBy([t,e]).paginate(c,...u),o=1;else{if(!o)throw new a.QueryError("PaginateBy needs a page or a bookmark");g=await this.override({forcePrepareComplexQueries:!1,forcePrepareSimpleQueries:!1}).select().orderBy([t,e]).paginate(c,...u)}const p=await g.page(o,...u);return g.serialize(p)}async statement(t,...e){if(!a.Repository.statements(this,t))throw new a.QueryError("Invalid prepared statement requested "+t);const r=await a.Context.args(a.PersistenceKeys.STATEMENT,this.class,e,this.adapter,this._overrides||{});r.context.logger&&r.context.logger.info(`Repo statement: ${t} + ${e}`);const{log:i,ctxArgs:o}=this.logCtx(r.args,this.statement);let s;i.verbose(`Executing prepared statement ${t} with args ${o}`);try{s=await this[t](...o)}catch(e){if(e instanceof n.BaseError)throw e;throw new n.InternalError(`Failed to execute prepared statement ${t} with args ${o}: ${e}`)}return s}ObserverHandler(){return new d}async updateObservers(t,e,r,...a){if(!this.trackedEvents||-1!==this.trackedEvents.indexOf(e))return await super.updateObservers(t,e,r,...a)}}class g extends e.CouchDBStatement{constructor(t){super(t)}async raw(t,...e){const{ctx:a}=this.logCtx(e,this.raw),i=await this.adapter.raw(t,!0,a),s=r.Model.pk(this.fromSelector),c=o.Metadata.get(this.fromSelector,o.Metadata.key(n.DBKeys.ID,s))?.type;return this.selectSelector?i:i.map(t=>this.processRecord(t,s,c,a))}build(){const t={};t[e.CouchDBKeys.TABLE]={},t[e.CouchDBKeys.TABLE]=r.Model.tableName(this.fromSelector);const n={selector:t};if(this.selectSelector&&(n.fields=this.selectSelector),this.whereCondition){const t=this.parseCondition(a.Condition.and(this.whereCondition,a.Condition.attribute(e.CouchDBKeys.TABLE).eq(n.selector[e.CouchDBKeys.TABLE]))).selector,r=Object.keys(t);if(1===r.length&&-1!==Object.values(e.CouchDBGroupOperator).indexOf(r[0]))switch(r[0]){case e.CouchDBGroupOperator.AND:t[e.CouchDBGroupOperator.AND]=[...Object.values(t[e.CouchDBGroupOperator.AND]).reduce((t,r)=>{const a=Object.keys(r);if(1!==a.length)throw Error("Too many keys in query selector. should be one");const n=a[0];return n===e.CouchDBGroupOperator.AND?t.push(...r[n]):t.push(r),t},[])],n.selector=t;break;case e.CouchDBGroupOperator.OR:{const r={};r[e.CouchDBGroupOperator.AND]=[t,...Object.entries(n.selector).map(([t,e])=>{const r={};return r[t]=e,r})],n.selector=r;break}default:throw Error("This should be impossible")}else Object.entries(t).forEach(([t,e])=>{n.selector[t],n.selector[t]=e})}if(this.orderBySelector){n.sort=n.sort||[],n.selector=n.selector||{};const[t,r]=this.orderBySelector,a={};a[t]=r,n.sort.push(a),n.selector[t]||(n.selector[t]={},n.selector[t][e.CouchDBOperator.BIGGER]=null)}return this.limitSelector&&(n.limit=this.limitSelector),this.offsetSelector&&(n.skip=this.offsetSelector),n}}class p extends a.Sequence{constructor(t,e){super(t,e)}async current(...t){const e=(await a.Context.args(n.OperationKeys.READ,a.SequenceModel,t,this.adapter)).context,{name:r,startWith:i}=this.options;try{const t=await this.repo.read(r,e);return this.parse(t.current)}catch(t){const a=e.logger.for(this.current);if(t instanceof n.NotFoundError){let t;try{a.debug(`Trying to resolve current sequence ${r} value from context`),t=e.get(r),a.debug(`Retrieved cached current value for sequence ${r}: ${t}`)}catch(e){a.info(`No cached value for sequence ${r} in context`),t=i}try{return this.parse(t)}catch(t){throw new n.InternalError(`Failed to parse initial value for sequence ${i}: ${t}`)}}throw new n.InternalError(`Failed to retrieve current value for sequence ${r}: ${t}`)}}async increment(t,e){const r=e.logger.for(this.increment),{type:i,incrementBy:o,name:s}=this.options;if(!s)throw new n.InternalError("Sequence name is required");return r.info("Obtaining sequence lock for sequence "+s),p.lock.execute(async()=>{const c=t||o;if(c%o!==0)throw new n.InternalError("Value to increment does not consider the incrementBy setting: "+o);const l="function"==typeof i&&i?.name?i.name:i,d=await this.current(e);async function u(t){return t instanceof Promise&&(t=await t),e.logger.for(u).info(`Storing new ${s} seq value in cache: ${t.current}`),e.cache.put(s,t.current),t}const g=async t=>{try{return await u(this.repo.update(new a.SequenceModel({id:s,current:t}),e))}catch(i){if(i instanceof n.NotFoundError)return r.debug(`Sequence create ${s} current=${d} next=${t}`),u(this.repo.create(new a.SequenceModel({id:s,current:t}),e));throw i}};if("uuid"===l)for(;;){const t=a.UUID.instance.generate(d);try{const e=await g(t);return r.debug(`Sequence uuid increment ${s} current=${d} next=${t}`),e.current}catch(t){if(t instanceof n.ConflictError)continue;throw t}}const p=(t=>{switch(l){case Number.name:return this.parse(t)+c;case BigInt.name:return this.parse(t)+BigInt(c);case String.name:return this.parse(t);case"serial":return a.Serial.instance.generate(t);default:throw new n.InternalError("Should never happen")}})(d),h=await g(p);return r.debug(`Sequence.increment ${s} current=${d} next=${p}`),h.current},s)}}var h,y;(t=>{t.PRIVATE="private",t.SHARED="shared",t.FABRIC="fabric.",t.OWNEDBY="owned-by",t.TRANSACTION_ID="transaction-id"})(h||(h={})),(t=>{t.X509="X.509"})(y||(y={}));const m="hlf-fabric";class w extends r.JSONSerializer{constructor(){super()}deserialize(t,e){return JSON.parse(t)}serialize(t,e=!0){return require("json-stringify-deterministic")(require("sort-keys-recursive")(this.preSerialize(t,e)))}preSerialize(t,e=!0){const a=Object.assign({},t);let n;try{n=o.Metadata.modelName(t.constructor)}catch(t){n=void 0}function i(t){return"object"!=typeof t?t:Array.isArray(t)?t.map(i):this.preSerialize(t)}return e&&(a[r.ModelKeys.ANCHOR]=n||t.constructor.name),r.Model.relations(t).forEach(t=>{a[t]=i.call(this,a[t])}),a}}class f extends s.MiniLogger{constructor(t,e,r){super(t,e),this.logger=r?r.logging.getLogger(t):new s.MiniLogger(t,e)}log(t,e,r){if(s.NumericLogLevels[this.config("level")]<s.NumericLogLevels[t])return;let a;switch(t){case s.LogLevel.info:a=this.logger.info;break;case s.LogLevel.verbose:a=this.logger.verbose;break;case s.LogLevel.debug:a=this.logger.debug;break;case s.LogLevel.error:a=this.logger.error;break;case s.LogLevel.warn:a=this.logger.warn;break;case s.LogLevel.silly:a=this.logger.silly;break;default:throw new n.InternalError("Invalid log level")}a.call(this.logger,this.createLog(t,e,r))}}s.Logging.setFactory((t,e,r)=>new f(t||f.name,e||{},r));class _ extends e.CouchDBPaginator{constructor(t,e,r,a){super(t,e,r,a)}prepare(t){const e=Object.assign({},t);return e.limit&&(this.limit=e.limit),e.limit=this.size,e}async page(t=1,...e){const{ctxArgs:i,ctx:s}=this.adapter.logCtx(e,this.page);if(this.isPreparedStatement())return this.pagePrepared(t,...i);const c=Object.assign({},this.statement);if(!this._recordCount||!this._totalPages){this._totalPages=this._recordCount=0;const t=await this.adapter.raw({...c,limit:void 0},!0,s)||[];if(this._recordCount=t.length,this._recordCount>0){const t=c?.limit||this.size;this._totalPages=Math.ceil(this._recordCount/t)}}if(this.validatePage(t),1!==t){if(!this._bookmark)throw new a.PagingError("No bookmark. Did you start in the first page?");c.bookmark=this._bookmark}const l=await this.adapter.raw(c,!1,s);if(!this.clazz)throw new a.PagingError("No statement target defined");const d=r.Model.pk(this.clazz),u=o.Metadata.get(this.clazz,o.Metadata.key(n.DBKeys.ID,d))?.type,g=c.fields&&c.fields.length?l:l.map(t=>this.adapter.revert(t,this.clazz,a.Sequence.parseValue(u,t[d]),void 0,s)),p=c.sort?.[0]||a.OrderDirection.DSC;return this._bookmark=g[p===a.OrderDirection.ASC?g.length-1:0][d],this._currentPage=t,g}}class x extends n.InternalError{constructor(t){super(t,x.name)}}class b extends n.InternalError{constructor(t){super(t,b.name)}}class C extends n.InternalError{constructor(t){super(t,C.name)}}class S extends n.InternalError{constructor(t){super(t,S.name,500)}}class v extends n.BaseError{constructor(t){super(v.name,t,409)}}async function E(t,e,r,n){try{const e=t.get("identity");n[r]=e.getID()}catch(t){throw new a.UnsupportedError("No User found in context. Please provide a user in the context")}}class A extends e.CouchDBAdapter{getClient(){throw new a.UnsupportedError("Client is not supported in Fabric contracts")}static{this.textDecoder=new TextDecoder("utf8")}static{this.serializer=new w}repository(){return u}Paginator(t,e,r){return new _(this,t,e,r)}async Sequence(t){return new p(t,this)}constructor(t,e){super(t,m,e),this.Context=l}for(t,...e){return super.for(t,...e)}async create(t,e,a,...n){const{ctx:i,log:o}=this.logCtx(n,this.create);o.info("in ADAPTER create with args "+n);const s=r.Model.tableName(t);try{o.info(`adding entry to ${s} table with pk ${e}`);const t=i.stub.createCompositeKey(s,[e+""]);a=await this.putState(t,a,i)}catch(t){throw this.parseError(t)}return a}async read(t,e,...a){const{ctx:n,log:i}=this.logCtx(a,this.read);i.info("in ADAPTER read with args "+a);const o=r.Model.tableName(t);let s;try{const t=n.stub.createCompositeKey(o,[e+""]);s=await this.readState(t,n)}catch(t){throw this.parseError(t)}return s}async update(t,e,a,...n){const{ctx:i,log:o}=this.logCtx(n,this.update),s=r.Model.tableName(t);try{o.verbose(`updating entry to ${s} table with pk ${e}`);const t=i.stub.createCompositeKey(s,[e+""]);a=await this.putState(t,a,i)}catch(t){throw this.parseError(t)}return a}async delete(t,e,...a){const{ctx:n,log:i,ctxArgs:o}=this.logCtx(a,this.delete),s=r.Model.tableName(t);let c;try{const r=n.stub.createCompositeKey(s,[e+""]);c=await this.read(t,e,...o),i.verbose(`deleting entry with pk ${e} from ${s} table`),await this.deleteState(r,n)}catch(t){throw this.parseError(t)}return c}async deleteState(t,e){const{ctx:r}=this.logCtx([e],this.deleteState);await r.stub.deleteState(t)}forPrivate(t){const e=[this.putState,this.readState,this.deleteState,this.queryResult,this.queryResultPaginated].map(t=>t.name);return new Proxy(this,{get:(r,a,i)=>e.includes(a)?new Proxy(r[a],{async apply(e,r,i){switch(a){case"putState":{const[e,r,a]=i;return await e.putPrivateData(t,r.toString(),a),a}case"deleteState":{const[e,r]=i;return e.deletePrivateData(t,r)}case"readState":{const[e,r]=i;return e.getPrivateData(t,r)}case"queryResult":{const[e,r]=i;return e.getPrivateDataQueryResult(t,r)}case"queryResultPaginated":{const[e,r,a,n]=i,o=await e.getPrivateDataQueryResult(t,r),s=[];let c=0,l=!n,d=null;for(;;){const t=await o.next();if(t.value&&t.value.value.toString()){const e=t.value.key,r=t.value.value.toString("utf8");if(!l){e===n?.toString()&&(l=!0);continue}if(s.push({Key:e,Record:JSON.parse(r)}),d=e,c++,c>=a)return await o.close(),{iterator:s,metadata:{fetchedRecordsCount:s.length,bookmark:d}}}if(t.done)return await o.close(),{iterator:s,metadata:{fetchedRecordsCount:s.length,bookmark:""}}}}default:throw new n.InternalError("Unsupported method override "+a)}}}):Reflect.get(r,a,i)})}async putState(t,e,r){let a;const{log:i}=this.logCtx([r],this.putState);try{a=Buffer.from(A.serializer.serialize(e,!1))}catch(e){throw new n.SerializationError(`Failed to serialize record with id ${t}: ${e}`)}const o=r.get("segregated");return o?await r.stub.putPrivateData(o,t.toString(),a):await r.stub.putState(t.toString(),a),i.silly(`state stored${o?` in ${o} collection`:""} under id ${t}`),e}async readState(t,e){let r;const{log:a}=this.logCtx([e],this.readState);let i;const o=e.get("segregated");if(i=o?(await e.stub.getPrivateData(o,t.toString())).toString():(await e.stub.getState(t.toString())).toString(),!i)throw new n.NotFoundError(`Record with id ${t}${o?` in ${o} collection`:""} not found`);a.silly(`state retrieved from${o?` ${o} collection`:""} under id ${t}`);try{r=A.serializer.deserialize(i.toString())}catch(t){throw new n.SerializationError("Failed to parse record: "+t)}return r}async queryResult(t,e,...r){const{ctx:a}=this.logCtx(r,this.readState);let n;const i=a.get("segregated");return n=i?await a.stub.getPrivateDataQueryResult(i,JSON.stringify(e)):await t.getQueryResult(JSON.stringify(e)),n}async queryResultPaginated(t,e,r=250,a,...n){const{ctx:i}=this.logCtx(n,this.readState);let o;const s=i.get("segregated");return s?(e.selector={...e.selector,_id:a?{$gt:a.toString()}:{$gte:""}},o={iterator:await t.getPrivateDataQueryResult(s,JSON.stringify(e)),metadata:{fetchedRecordsCount:r,bookmark:""}}):o=await t.getQueryResultWithPagination(JSON.stringify(e),r,a?.toString()),o}mergeModels(t){const e=t=>Object.entries(t).reduce((t,[e,r])=>(void 0!==r&&(t[e]=r),t),{});let r=t.pop();for(const a of t)r=Object.assign({},e(r),e(a));return r}decode(t){return A.textDecoder.decode(t)}async flags(t,e,r,a,...n){const i={stub:a.stub,segregated:!1};return Object.assign(i,a instanceof l?{logger:a.logger,identity:a.identity,correlationId:a.stub.getTxID()}:{identity:a.clientIdentity,logger:new f(this,void 0,a),correlationId:a.stub.getTxID()}),await super.flags(t,e,i,...n)}index(t){return Promise.resolve(void 0)}async resultIterator(t,e,r=!1){const a=[];let n=await e.next();for(;!n.done;){if(n.value&&n.value.value.toString()){let e={};if(t.debug(n.value.value.toString("utf8")),r){e.TxId=n.value.txId,e.Timestamp=n.value.timestamp;try{e.Value=JSON.parse(n.value.value.toString("utf8"))}catch(r){t.error(r),e.Value=n.value.value.toString("utf8")}}else try{e=JSON.parse(n.value.value.toString("utf8"))}catch(r){t.error(r),e=n.value.value.toString("utf8")}a.push(e)}n=await e.next()}return t.debug(`Closing iterator after ${a.length} results`),e.close(),a}async raw(t,e=!0,...r){const{log:a,stub:n,ctx:i}=this.logCtx(r,this.raw),{skip:o,limit:s}=t;let c;s||o?(delete t.limit,delete t.skip,a.debug(`Retrieving paginated iterator: limit: ${s}/ skip: ${o}`),c=(await this.queryResultPaginated(n,t,s||250,o?.toString(),i)).iterator):(a.debug("Retrieving iterator"),c=await this.queryResult(n,t,i)),a.debug("Iterator acquired");const l=await this.resultIterator(a,c);return a.debug(`returning ${Array.isArray(l)?l.length:1} results`),l}Statement(){return new g(this)}async createAll(t,e,a,...i){if(e.length!==a.length)throw new n.InternalError("Ids and models must have the same length");const{log:o,ctxArgs:s}=this.logCtx(i,this.createAll),c=r.Model.tableName(t);return o.debug(`Creating ${e.length} entries ${c} table`),Promise.all(e.map((e,r)=>this.create(t,e,a[r],...s)))}async updateAll(t,e,a,...i){if(e.length!==a.length)throw new n.InternalError("Ids and models must have the same length");const{log:o,ctxArgs:s}=this.logCtx(i,this.updateAll),c=r.Model.tableName(t);return o.debug(`Updating ${e.length} entries ${c} table`),Promise.all(e.map((e,r)=>this.update(t,e,a[r],...s)))}prepare(t,...e){const{log:a}=this.logCtx(e,this.prepare),i=r.Model.tableName(t.constructor),o=r.Model.pk(t.constructor),s=r.Model.segregate(t),c=Object.entries(s.model).reduce((e,[a,i])=>{if(void 0===i)return e;const o=r.Model.columnName(t,a);if(this.isReserved(o))throw new n.InternalError(`Property name ${o} is reserved`);return e[o]=i,e},{});return a.silly(`Preparing record for ${i} table with pk ${t[o]}`),{record:c,id:t[o],transient:s.transient}}revert(t,e,a,i,...o){const{log:s}=this.logCtx(o,this.revert),c={};c[r.Model.pk(e)]=a;const l="string"==typeof e?r.Model.build(c,e):new e(c);s.silly(`Rebuilding model ${l.constructor.name} id ${a}`);const d=Object.keys(l).reduce((e,a)=>(e[a]=t[r.Model.columnName(e,a)],e),l);return i&&(s.debug("re-adding transient properties: "+Object.keys(i).join(", ")),Object.entries(i).forEach(([t,e])=>{if(t in d&&void 0!==d[t])throw new n.InternalError(`Transient property ${t} already exists on model ${l.constructor.name}. should be impossible`);d[t]=e})),d}createPrefix(t,a,n,...i){const{ctxArgs:o}=this.logCtx(i,this.createPrefix),s={};return s[e.CouchDBKeys.TABLE]=r.Model.tableName(t),Object.assign(s,n),[t,a,s,...o]}updatePrefix(t,a,n,...i){const{ctxArgs:o}=this.logCtx(i,this.updatePrefix),s={};return s[e.CouchDBKeys.TABLE]=r.Model.tableName(t),Object.assign(s,n),[t,a,s,...o]}createAllPrefix(t,a,i,...o){if(a.length!==i.length)throw new n.InternalError("Ids and models must have the same length");const s=o.pop(),c=a.map((a,n)=>{const o={};return o[e.CouchDBKeys.TABLE]=r.Model.tableName(t),Object.assign(o,i[n]),o});return[t,a,c,s]}updateAllPrefix(t,a,i,...o){if(a.length!==i.length)throw new n.InternalError("Ids and models must have the same length");const s=o.pop(),c=a.map((a,n)=>{const o={};return o[e.CouchDBKeys.TABLE]=r.Model.tableName(t),Object.assign(o,i[n]),o});return[t,a,c,s]}parseError(t,e){return A.parseError(e||t)}logCtx(t,e){return A.logCtx.call(this,t,e)}static logCtx(t,e){if(1>t.length)throw new n.InternalError("No context provided");const r=t.pop();if(!(r instanceof a.Context))throw new n.InternalError("No context provided");if(t.filter(t=>t instanceof a.Context).length>1)throw Error("here");const i=this?r.logger.for(this).for(e):r.logger.clear().for(this).for(e);return{ctx:r,log:e?i.for(e):i,stub:r.stub,identity:r.identity,ctxArgs:[...t,r]}}static parseError(t){const e="string"==typeof t?t:t.message;return e.includes(n.NotFoundError.name)?new n.NotFoundError(t):e.includes(n.ConflictError.name)?new n.ConflictError(t):e.includes(n.BadRequestError.name)?new n.BadRequestError(t):e.includes(a.QueryError.name)?new a.QueryError(t):e.includes(a.PagingError.name)?new a.PagingError(t):e.includes(a.UnsupportedError.name)?new a.UnsupportedError(t):e.includes(a.MigrationError.name)?new a.MigrationError(t):e.includes(a.ObserverError.name)?new a.ObserverError(t):e.includes(a.AuthorizationError.name)?new a.AuthorizationError(t):e.includes(a.ForbiddenError.name)?new a.ForbiddenError(t):e.includes(a.ConnectionError.name)?new a.ConnectionError(t):e.includes(n.SerializationError.name)?new n.SerializationError(t):e.includes("no ledger context")?new S("No context found. this can be caused by debugging: "+e):new n.InternalError(t)}static decoration(){super.decoration(),o.Decoration.flavouredAs(m).for(a.PersistenceKeys.CREATED_BY).define(n.onCreate(E),o.propMetadata(a.PersistenceKeys.CREATED_BY,{})).apply(),o.Decoration.flavouredAs(m).for(a.PersistenceKeys.UPDATED_BY).define(n.onCreateUpdate(E),o.propMetadata(a.PersistenceKeys.UPDATED_BY,{})).apply(),o.Decoration.flavouredAs(m).for(a.PersistenceKeys.COLUMN).extend(i.Property()).apply(),o.Decoration.flavouredAs(m).for(r.ValidationKeys.DATE).extend(()=>(t,e)=>{i.Property(e,"string:date")(t,e)}),o.Decoration.flavouredAs(m).for(a.PersistenceKeys.TABLE).extend(t=>{const e=[];let r="function"==typeof t?o.Metadata.constr(t):o.Metadata.constr(t.constructor);for(;r&&r!==Object&&r.prototype;)e.push(r),r=Object.getPrototypeOf(r);for(;e.length>0;){const t=e.pop();i.Object()(t)}return i.Object()(t)}).apply()}}A.decoration(),a.Adapter.setCurrent(m);class O extends r.JSONSerializer{constructor(){super()}preSerialize(t){const e=Object.assign({},t);let a;try{a=o.Metadata.modelName(t.constructor)}catch(t){a=void 0}e[r.ModelKeys.ANCHOR]=a||t.constructor.name;const n=function t(e){const r=this;return"object"!=typeof e?e:Array.isArray(e)?e.map(e=>t.call(r,e)):this.preSerialize.call(this,e)}.bind(this);return r.Model.relations(t).forEach(t=>{e[t]=n(e[t])}),e}deserialize(t){const e=JSON.parse(t),a=e[r.ModelKeys.ANCHOR];if(!a)throw Error("Could not find class reference in serialized model");return r.Model.build(e,a)}serialize(t){return require("json-stringify-deterministic")(require("sort-keys-recursive")(this.preSerialize(t)))}}i.Object()(Date);class k extends i.Contract{static{this.adapter=new A}static{this.serializer=new O}constructor(t,e){super(t),this.clazz=e,this.initialized=!1,this.repo=a.Repository.forModel(e)}async listBy(t,e,r,...a){const{ctxArgs:n,log:i}=await this.logCtx([...a,t],this.listBy);return i.info(`Running listBy key ${e}, order ${r} and args ${n}`),this.repo.listBy(e,r,...n)}async paginateBy(t,e,r,a={offset:1,limit:10},...n){const{ctxArgs:i,log:o}=await this.logCtx([...n,t],this.paginateBy);return o.info(`Running paginateBy key ${e}, order ${r} with size ${a.limit} and args ${i}`),this.repo.paginateBy(e,r,a,...i)}async findOneBy(t,e,r,...a){const{ctxArgs:n,log:i}=await this.logCtx([...a,t],this.findOneBy);return i.info(`Running findOneBy key ${e}, value: ${r} with args ${n}`),this.repo.findOneBy(e,r,...n)}async statement(t,e,...r){const{ctxArgs:a,log:n}=await this.logCtx([...r,t],this.statement);return n.info(`Running statement ${e} with args ${a}`),this.repo.statement(e,...a)}async create(t,e,...a){const{log:n,ctxArgs:i}=await this.logCtx([...a,t],this.create);n.info("CONTRACT CREATE, "+i),"string"==typeof e&&(e=this.deserialize(e)),n.info("Creating model: "+JSON.stringify(e));const o=this.getTransientData(t);return n.info("Merging transient data..."),e=r.Model.merge(e,o,this.clazz),this.repo.create(e,...i)}async read(t,e,...r){const{log:a,ctxArgs:n}=await this.logCtx([...r,t],this.read);return a.info(`reading entry with pk ${e} `),this.repo.read(e,...n)}getTransientData(t){const e=t.stub.getTransient();let r={};return e.has(this.repo.tableName)&&(r=JSON.parse(e.get(this.repo.tableName)?.toString("utf8"))),r}async update(t,e,...a){const{log:n,ctxArgs:i}=await this.logCtx([...a,t],this.update);"string"==typeof e&&(e=this.deserialize(e)),n.info("Updating model: "+JSON.stringify(e));const o=this.getTransientData(t);return n.info("Merging transient data..."),e=r.Model.merge(e,o,this.clazz),this.repo.update(e,...i)}async delete(t,e,...r){const{log:a,ctxArgs:n}=await this.logCtx([...r,t],this.delete);return a.info(`deleting entry with pk ${e} `),this.repo.delete(e+"",...n)}async deleteAll(t,e,...r){const{ctxArgs:a}=await this.logCtx([...r,t],this.readAll);return"string"==typeof e&&(e=JSON.parse(e)),this.repo.deleteAll(e,...a)}async readAll(t,e,...r){const{ctxArgs:a}=await this.logCtx([...r,t],this.readAll);return"string"==typeof e&&(e=JSON.parse(e)),this.repo.readAll(e,...a)}async updateAll(t,e,...r){const{log:a,ctxArgs:n}=await this.logCtx([...r,t],this.updateAll);return"string"==typeof e&&(e=JSON.parse(e).map(t=>this.deserialize(t)).map(t=>new this.clazz(t))),a.info(`updating ${e.length} entries to the table`),this.repo.updateAll(e,...n)}async query(t,e,r,n=a.OrderDirection.ASC,i,o,...s){const{ctxArgs:c}=await this.logCtx([...s,t],this.query);return this.repo.query(e,r,n,i,o,...c)}async raw(t,e,r,...a){const{ctxArgs:n}=await this.logCtx([...a,t],this.raw);return k.adapter.raw(e,r,...n)}serialize(t){return k.serializer.serialize(t)}deserialize(t){return k.serializer.deserialize(t)}async init(t){const{log:e}=await this.logCtx([t],this.init);e.info(`Running contract ${this.getName()} initialization...`),this.initialized=!0,e.info("Contract initialization completed.")}async healthcheck(t){const{log:e}=await this.logCtx([t],this.healthcheck);return e.info(`Running Healthcheck: ${this.initialized}...`),{healthcheck:this.initialized}}async createAll(t,e,...r){const{log:a,ctxArgs:n}=await this.logCtx([...r,t],this.createAll);return"string"==typeof e&&(e=JSON.parse(e).map(t=>this.deserialize(t)).map(t=>new this.clazz(t))),a.info(`adding ${e.length} entries to the table`),this.repo.createAll(e,...n)}async logCtx(t,e){return k.logCtx.bind(this)(t,e)}static async logCtx(t,e){if(1>t.length)throw new n.InternalError("No context provided");const r=t.pop();if(r instanceof l)return{ctx:r,log:r.logger.clear().for(this).for(e),ctxArgs:[...t,r],stub:r.stub,identity:r.identity};if(!(r instanceof i.Context))throw new n.InternalError("No valid context provided");const a={correlationId:r.stub.getTxID()},o=await k.adapter.context((()=>{if("string"==typeof e)return e;switch(e.name){case n.OperationKeys.CREATE:case n.OperationKeys.READ:case n.OperationKeys.UPDATE:case n.OperationKeys.DELETE:case n.BulkCrudOperationKeys.CREATE_ALL:case n.BulkCrudOperationKeys.READ_ALL:case n.BulkCrudOperationKeys.UPDATE_ALL:case n.BulkCrudOperationKeys.DELETE_ALL:}return e.name})(),a,this.clazz,r),s=this?o.logger.for(this).for(e):o.logger.clear().for(this).for(e);return{ctx:o,log:s,stub:o.stub,identity:o.identity,ctxArgs:[...t,o]}}}class N extends k{constructor(t,e){super(t,e)}async create(t,e){const{log:r,ctx:a}=await this.logCtx([t],this.create);r.info("Creating model: "+e);const n=this.deserialize(e);r.info("Model deserialized: "+JSON.stringify(n));const i=await super.create(a,n),o=this.serialize(i);return r.info("RESULT: "+JSON.stringify(i)),r.info("Retuning: "+o),o}async read(t,e){const{log:r,ctx:a}=await this.logCtx([t],this.read);return r.info("Reading id: "+e),this.serialize(await super.read(a,e))}async update(t,e){const{log:r,ctx:a}=await this.logCtx([t],this.update);return r.info("Updating model: "+e),this.serialize(await super.update(a,e))}async delete(t,e){const{log:r,ctx:a}=await this.logCtx([t],this.delete);return r.info("Deleting id: "+e),this.serialize(await super.delete(a,e))}async deleteAll(t,e){const r=JSON.parse(e),{log:a,ctx:n}=await this.logCtx([t],this.deleteAll);return a.info(`deleting ${r.length} entries from the table`),JSON.stringify((await super.deleteAll(n,r)).map(t=>this.serialize(t)))}async readAll(t,e){const r=JSON.parse(e),{log:a,ctx:n}=await this.logCtx([t],this.readAll);return a.info(`reading ${r.length} entries from the table`),JSON.stringify((await super.readAll(n,r)).map(t=>this.serialize(t)))}async updateAll(t,e){const{log:r,ctx:a}=await this.logCtx([t],this.updateAll),n=JSON.parse(e).map(t=>this.deserialize(t)).map(t=>new this.clazz(t));return r.info(`Updating ${n.length} entries to the table`),JSON.stringify((await super.updateAll(a,n)).map(t=>this.serialize(t)))}async statement(t,e,r){const{ctx:a,log:i}=await this.logCtx([t],this.statement);try{r=JSON.parse(r)}catch(t){throw new n.SerializationError("Invalid args: "+t)}if(!Array.isArray(r))throw new n.SerializationError(`Invalid args: ${JSON.stringify(r)}. must be an array`);return i.info("calling prepared statement "+e),i.info("with args "+r),JSON.stringify(await super.statement(a,e,...r))}async listBy(t,e,r){const{ctx:a,log:n}=await this.logCtx([t],this.listBy);return n.info(`Executing listBy with key ${e} and order ${r}`),JSON.stringify(await super.listBy(a,e,r))}async paginateBy(t,e,r,a,...i){const{ctx:o,log:s}=await this.logCtx([...i,t],this.paginateBy);try{a=JSON.parse(a)}catch(t){throw new n.SerializationError("Failed to deserialize paginateBy reference: "+t)}return s.info(`Executing paginateBy with key ${e} and order ${r}`),JSON.stringify(await super.paginateBy(o,e,r,a,...i))}async findOneBy(t,e,r,...a){const{ctx:n,log:i}=await this.logCtx([...a,t],this.findOneBy);return i.info(`Executing findOneBy with key ${e} and value ${r}`),JSON.stringify(await super.findOneBy(n,e,r,...a))}async query(t,e,r,i,o,s){const{ctx:c,log:l}=await this.logCtx([t],this.query);let d;l.info(`Executing query orderedBy ${r} and order ${i}`);try{d=a.Condition.from(JSON.parse(e))}catch(t){throw new n.SerializationError("Invalid condition: "+t)}return l.info("Condition: "+JSON.stringify(d)),JSON.stringify(await super.query(c,d,r,i,o,s))}async init(t){await super.init(t)}async healthcheck(t){const{log:e,ctx:r}=await this.logCtx([t],this.updateAll);return e.debug(`Running Healthcheck: ${this.initialized}...`),JSON.stringify(await super.healthcheck(r))}async createAll(t,e){const{log:r}=await this.logCtx([t],this.createAll),a=JSON.parse(e).map(t=>this.deserialize(t)).map(t=>new this.clazz(t));r.info(`Adding ${a.length} entries to the table`);const n=await super.createAll(t,a);return JSON.stringify(n.map(t=>this.serialize(t)))}}function T(t,e){const r=t+e;if(t!==r-e||e!==r-t)throw new x(`Addition overflow: ${t} + ${e}`);return r}function z(t,e){const r=t-e;if(t!==r+e||e!==t-r)throw new x(`Subtraction overflow: ${t} - ${e}`);return r}c.__decorate([i.Transaction(),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context,String]),c.__metadata("design:returntype",Promise)],N.prototype,"create",null),c.__decorate([i.Transaction(!1),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context,String]),c.__metadata("design:returntype",Promise)],N.prototype,"read",null),c.__decorate([i.Transaction(),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context,String]),c.__metadata("design:returntype",Promise)],N.prototype,"update",null),c.__decorate([i.Transaction(),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context,String]),c.__metadata("design:returntype",Promise)],N.prototype,"delete",null),c.__decorate([i.Transaction(),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context,String]),c.__metadata("design:returntype",Promise)],N.prototype,"deleteAll",null),c.__decorate([i.Transaction(!1),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context,String]),c.__metadata("design:returntype",Promise)],N.prototype,"readAll",null),c.__decorate([i.Transaction(),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context,String]),c.__metadata("design:returntype",Promise)],N.prototype,"updateAll",null),c.__decorate([i.Transaction(!1),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context,String,String]),c.__metadata("design:returntype",Promise)],N.prototype,"statement",null),c.__decorate([i.Transaction(!1),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context,String,String]),c.__metadata("design:returntype",Promise)],N.prototype,"listBy",null),c.__decorate([i.Transaction(!1),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context,String,String,String,l]),c.__metadata("design:returntype",Promise)],N.prototype,"paginateBy",null),c.__decorate([i.Transaction(!1),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context,String,String,String]),c.__metadata("design:returntype",Promise)],N.prototype,"findOneBy",null),c.__decorate([i.Transaction(),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context]),c.__metadata("design:returntype",Promise)],N.prototype,"init",null),c.__decorate([i.Transaction(!1),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context]),c.__metadata("design:returntype",Promise)],N.prototype,"healthcheck",null),c.__decorate([i.Transaction(),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context,String]),c.__metadata("design:returntype",Promise)],N.prototype,"createAll",null);let $=class extends a.BaseModel{constructor(t){super(t)}};c.__decorate([a.pk({type:"String"}),c.__metadata("design:type",String)],$.prototype,"name",void 0),c.__decorate([a.column(),r.required(),c.__metadata("design:type",String)],$.prototype,"owner",void 0),c.__decorate([a.column(),r.required(),c.__metadata("design:type",String)],$.prototype,"symbol",void 0),c.__decorate([a.column(),r.required(),c.__metadata("design:type",Number)],$.prototype,"decimals",void 0),$=c.__decorate([a.table("erc20_tokens"),r.model(),c.__metadata("design:paramtypes",[Object])],$);let R=class extends a.BaseModel{constructor(t){super(t)}};c.__decorate([a.pk({type:"String"}),c.__metadata("design:type",String)],R.prototype,"id",void 0),c.__decorate([a.column(),r.required(),c.__metadata("design:type",String)],R.prototype,"token",void 0),c.__decorate([a.column(),r.required(),c.__metadata("design:type",Number)],R.prototype,"balance",void 0),c.__decorate([a.column(),c.__metadata("design:type",String)],R.prototype,"captive",void 0),R=c.__decorate([a.table("erc20_wallets"),r.model(),c.__metadata("design:paramtypes",[Object])],R);let B=class extends a.BaseModel{constructor(t){super(t)}};function P(){return function(t,e,r){const i=r.value;return r.value=async function(...t){const r=t[0],o=r.clientIdentity.getID(),s=await this.tokenRepository.select(),c=await s.execute(r);if(0==c.length)throw new n.NotFoundError("No tokens avaialble");if(c.length>1)throw new n.NotFoundError("To many token available : "+c.length);if(c[0].owner!=o)throw new a.AuthorizationError(`User not authorized to run ${e} on the token`);return await i.apply(this,t)},r}}var D;c.__decorate([a.pk({type:"String"}),a.column(),r.required(),c.__metadata("design:type",String)],B.prototype,"owner",void 0),c.__decorate([a.column(),r.required(),c.__metadata("design:type",String)],B.prototype,"spender",void 0),c.__decorate([a.column(),r.required(),c.__metadata("design:type",Number)],B.prototype,"value",void 0),B=c.__decorate([a.table("erc20_allowances"),r.model(),c.__metadata("design:paramtypes",[Object])],B),(t=>{t.TRANSFER="Transfer",t.APPROVAL="Approval"})(D||(D={}));class I extends k{constructor(t){super(t,R),I.adapter=I.adapter||new A,this.walletRepository=u.forModel(R,I.adapter.alias),this.tokenRepository=u.forModel($,I.adapter.alias),this.allowanceRepository=u.forModel(B,I.adapter.alias)}async TokenName(t){const{ctx:e}=await this.logCtx([t],this.TokenName);await this.CheckInitialized(e);const r=this.tokenRepository.select();return(await r.execute(e))[0].name}async Symbol(t){const{ctx:e}=await this.logCtx([t],this.TokenName);await this.CheckInitialized(e);const r=this.tokenRepository.select();return(await r.execute(e))[0].symbol}async Decimals(t){const{ctx:e}=await this.logCtx([t],this.TokenName);await this.CheckInitialized(e);const r=this.tokenRepository.select();return(await r.execute(e))[0].decimals}async TotalSupply(t){const{ctx:e}=await this.logCtx([t],this.TokenName);await this.CheckInitialized(e);const r=this.walletRepository.select(),a=await r.execute(e);if(0==a.length)throw new n.NotFoundError(`The token ${this.getName()} does not exist`);let i=0;return a.forEach(t=>{i+=t.balance}),i}async BalanceOf(t,e){const{ctx:r}=await this.logCtx([t],this.TokenName);return await this.CheckInitialized(r),(await this.walletRepository.read(e,r)).balance}async Transfer(t,e,r){const{ctx:a}=await this.logCtx([t],this.Transfer);await this.CheckInitialized(a);const i=a.identity.getID();if(!await this._transfer(i,e,r,a))throw new n.InternalError("Failed to transfer");return!0}async TransferFrom(t,e,r,a){const{ctx:i}=await this.logCtx([t],this.BurnFrom);await this.CheckInitialized(i);const o=i.identity.getID(),s=await this._getAllowance(e,o,i);if(!s||0>s.value)throw new C(`spender ${o} has no allowance from ${e}`);const c=s.value;if(a>c)throw new b("The spender does not have enough allowance to spend.");const l=z(c,a),d=Object.assign({},s,{value:l});if(await this.allowanceRepository.update(d,i),!await this._transfer(e,r,a,i))throw new n.InternalError("Failed to transfer");return!0}async _transfer(t,e,r,i){const o=i.logger;if(t===e)throw new a.AuthorizationError("cannot transfer to and from same client account");if(0>r)throw new b("transfer amount cannot be negative");const s=await this.walletRepository.read(t,i),c=s.balance;if(r>c)throw new b(`client account ${t} has insufficient funds.`);let l,d=!1;try{l=await this.walletRepository.read(e,i)}catch(t){if(!(t instanceof n.BaseError))throw new n.InternalError(t);if(404!==t.code)throw new n.InternalError(t.message);l=new R({id:e,balance:0,token:await this.TokenName(i)}),d=!0}const u=l.balance,g=z(c,r),p=T(u,r),h=Object.assign({},s,{balance:g});await this.walletRepository.update(h,i);const y=Object.assign({},l,{balance:p});d?await this.walletRepository.create(y,i):await this.walletRepository.update(y,i);const m={from:t,to:e,value:r};return this.repo.refresh($,D.TRANSFER,"",m,i).catch(t=>o.error("Failed to notify transfer: "+t)),!0}async Approve(t,e,r){const{ctx:a,ctxArgs:n}=await this.logCtx([t],this.Approve);await this.CheckInitialized(a);const i=a.identity.getID();let o=await this._getAllowance(i,e,a);if((await this.walletRepository.read(i,...n)).balance<r)throw new b(`client account ${i} has insufficient funds.`);o?(o.value=r,await this.allowanceRepository.update(o,...n)):(o=new B({owner:i,spender:e,value:r}),await this.allowanceRepository.create(o,...n));const s={owner:i,spender:e,value:r};return this.repo.refresh($,D.APPROVAL,"",s,a),!0}async Allowance(t,e,r){const{ctx:a}=await this.logCtx([t],this.Allowance);await this.CheckInitialized(a);const n=await this._getAllowance(e,r,a);if(!n)throw new C(`spender ${r} has no allowance from ${e}`);return n.value}async _getAllowance(t,e,r){const n=a.Condition.and(a.Condition.attribute("owner").eq(t),a.Condition.attribute("spender").eq(e)),i=await this.allowanceRepository.select().where(n).execute(r);return i?.[0]}async Initialize(t,e){const{ctx:r}=await this.logCtx([t],this.Initialize);if((await this.tokenRepository.select().execute(r)).length>0)throw new a.AuthorizationError("contract options are already set, client is not authorized to change them");return e.owner=r.identity.getID(),await this.tokenRepository.create(e,r),!0}async CheckInitialized(t){const{ctx:e}=await this.logCtx([t],this.CheckInitialized);if(0==(await this.tokenRepository.select().execute(e)).length)throw new v("contract options need to be set before calling any function, call Initialize() to initialize contract")}async Mint(t,e){const{ctx:r}=await this.logCtx([t],this.Mint);await this.CheckInitialized(r);const a=r.identity.getID();if(0>=e)throw new n.ValidationError("mint amount must be a positive integer");let i;try{i=await this.walletRepository.read(a,r);const t=T(i.balance,e),n=Object.assign({},i,{balance:t});await this.walletRepository.update(n,r)}catch(i){if(!(i instanceof n.BaseError))throw new n.InternalError(i);if(404!==i.code)throw new n.InternalError(i.message);{const n=new R({id:a,balance:e,token:await this.TokenName(t)});await this.walletRepository.create(n,r)}}const o={from:"0x0",to:a,value:e};this.repo.ObserverHandler().updateObservers($,D.TRANSFER,"",o,r)}async Burn(t,e){const{log:r,ctx:a}=await this.logCtx([t],this.Burn);await this.CheckInitialized(a);const n=a.identity.getID(),i=await this.walletRepository.read(n,a),o=i.balance;if(e>o)throw new b("Minter has insufficient funds.");const s=z(o,e),c=Object.assign({},i,{balance:s});await this.walletRepository.update(c,a),r.info(e+" tokens were burned");const l={from:n,to:"0x0",value:e};this.repo.ObserverHandler().updateObservers($,D.TRANSFER,"",l,a)}async BurnFrom(t,e,r){const{log:a,ctx:n}=await this.logCtx([t],this.BurnFrom);await this.CheckInitialized(n);const i=await this.walletRepository.read(e,n),o=i.balance;if(r>o)throw new b(e+" has insufficient funds.");const s=z(o,r),c=Object.assign({},i,{balance:s});await this.walletRepository.update(c,n),a.info(`${r} tokens were burned from ${e}`);const l={from:e,to:"0x0",value:r};this.repo.ObserverHandler().updateObservers($,D.TRANSFER,"",l,n)}async ClientAccountBalance(t){const{ctx:e}=await this.logCtx([t],this.TokenName);await this.CheckInitialized(e);const r=e.identity.getID(),a=await this.walletRepository.read(r,e);if(!a)throw new b(`The account ${r} does not exist`);return a.balance}async ClientAccountID(t){const{ctx:e}=await this.logCtx([t],this.ClientAccountID);return await this.CheckInitialized(e),e.identity.getID()}}c.__decorate([i.Transaction(!1),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context]),c.__metadata("design:returntype",Promise)],I.prototype,"TokenName",null),c.__decorate([i.Transaction(!1),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context]),c.__metadata("design:returntype",Promise)],I.prototype,"Symbol",null),c.__decorate([i.Transaction(!1),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context]),c.__metadata("design:returntype",Promise)],I.prototype,"Decimals",null),c.__decorate([i.Transaction(!1),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context]),c.__metadata("design:returntype",Promise)],I.prototype,"TotalSupply",null),c.__decorate([i.Transaction(!1),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context,String]),c.__metadata("design:returntype",Promise)],I.prototype,"BalanceOf",null),c.__decorate([i.Transaction(),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context,String,Number]),c.__metadata("design:returntype",Promise)],I.prototype,"Transfer",null),c.__decorate([i.Transaction(),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context,String,String,Number]),c.__metadata("design:returntype",Promise)],I.prototype,"TransferFrom",null),c.__decorate([i.Transaction(),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context,String,Number]),c.__metadata("design:returntype",Promise)],I.prototype,"Approve",null),c.__decorate([i.Transaction(!1),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context,String,String]),c.__metadata("design:returntype",Promise)],I.prototype,"Allowance",null),c.__decorate([i.Transaction(),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context,$]),c.__metadata("design:returntype",Promise)],I.prototype,"Initialize",null),c.__decorate([i.Transaction(!1),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context]),c.__metadata("design:returntype",Promise)],I.prototype,"CheckInitialized",null),c.__decorate([P(),i.Transaction(),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context,Number]),c.__metadata("design:returntype",Promise)],I.prototype,"Mint",null),c.__decorate([P(),i.Transaction(),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context,Number]),c.__metadata("design:returntype",Promise)],I.prototype,"Burn",null),c.__decorate([P(),i.Transaction(),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context,String,Number]),c.__metadata("design:returntype",Promise)],I.prototype,"BurnFrom",null),c.__decorate([i.Transaction(!1),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context]),c.__metadata("design:returntype",Promise)],I.prototype,"ClientAccountBalance",null),c.__decorate([i.Transaction(!1),c.__metadata("design:type",Function),c.__metadata("design:paramtypes",[i.Context]),c.__metadata("design:returntype",Promise)],I.prototype,"ClientAccountID",null);const F=[I],M="##VERSION##",q="##PACKAGE##";o.Metadata.registerLibrary(q,M),t.ContractLogger=f,t.FabricContractAdapter=A,t.FabricContractContext=l,t.FabricContractPaginator=_,t.FabricContractRepository=u,t.FabricContractRepositoryObservableHandler=d,t.FabricCrudContract=k,t.FabricStatement=g,t.PACKAGE_NAME=q,t.SerializedCrudContract=N,t.VERSION=M,t.contracts=F,t.createdByOnFabricCreateUpdate=E,t.pkFabricOnCreate=async function(t,e,a,i){if(!e.type||i[a])return;let o;e.name||(e.name=r.Model.sequenceName(i,"pk"));try{o=await this.adapter.Sequence(e)}catch(t){throw new n.InternalError(`Failed to instantiate Sequence ${e.name}: ${t}`)}const s=await o.next(t);Object.defineProperty(i,a,{enumerable:!0,writable:!1,configurable:!0,value:s})}},"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("@decaf-ts/for-couchdb"),require("@decaf-ts/decorator-validation"),require("@decaf-ts/core"),require("@decaf-ts/db-decorators"),require("fabric-contract-api"),require("@decaf-ts/decoration"),require("@decaf-ts/logging"),require("tslib")):"function"==typeof define&&define.amd?define(["exports","@decaf-ts/for-couchdb","@decaf-ts/decorator-validation","@decaf-ts/core","@decaf-ts/db-decorators","fabric-contract-api","@decaf-ts/decoration","@decaf-ts/logging","tslib"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self)["for-fabric"]={},t.decafTsForCouchdb,t.decafTsDecoratorValidation,t.decafTsCore,t.decafTsDbDecorators,t.fabricContractApi,t.decafTsDecoration,t.decafTsLogging,t.tslib);
2
+ //# sourceMappingURL=for-fabric.cjs.map