@nlabs/reaktor 0.10.5 → 0.10.7

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 (535) hide show
  1. package/lib/actions/apps.d.ts +1 -0
  2. package/lib/actions/apps.d.ts.map +1 -0
  3. package/lib/actions/apps.js +221 -0
  4. package/lib/actions/connections.d.ts +1 -0
  5. package/lib/actions/connections.d.ts.map +1 -0
  6. package/lib/actions/connections.js +62 -0
  7. package/lib/actions/content.d.ts +1 -0
  8. package/lib/actions/content.d.ts.map +1 -0
  9. package/lib/actions/content.js +240 -0
  10. package/lib/actions/conversations.d.ts +1 -0
  11. package/lib/actions/conversations.d.ts.map +1 -0
  12. package/lib/actions/conversations.js +335 -0
  13. package/lib/actions/dynamodb.d.ts +1 -0
  14. package/lib/actions/dynamodb.d.ts.map +1 -0
  15. package/lib/actions/dynamodb.js +119 -0
  16. package/lib/actions/email.d.ts +1 -0
  17. package/lib/actions/email.d.ts.map +1 -0
  18. package/lib/actions/email.js +56 -0
  19. package/lib/actions/files.d.ts +1 -0
  20. package/lib/actions/files.d.ts.map +1 -0
  21. package/lib/actions/files.js +226 -0
  22. package/lib/actions/groups.d.ts +1 -0
  23. package/lib/actions/groups.d.ts.map +1 -0
  24. package/lib/actions/groups.js +267 -0
  25. package/lib/actions/images.d.ts +1 -0
  26. package/lib/actions/images.d.ts.map +1 -0
  27. package/lib/actions/images.js +723 -0
  28. package/lib/actions/index.d.ts +1 -0
  29. package/lib/actions/index.d.ts.map +1 -0
  30. package/lib/actions/index.js +29 -0
  31. package/lib/actions/ios.d.ts +1 -0
  32. package/lib/actions/ios.d.ts.map +1 -0
  33. package/lib/actions/ios.js +230 -0
  34. package/lib/actions/locations.d.ts +1 -0
  35. package/lib/actions/locations.d.ts.map +1 -0
  36. package/lib/actions/locations.js +111 -0
  37. package/lib/actions/messages.d.ts +1 -0
  38. package/lib/actions/messages.d.ts.map +1 -0
  39. package/lib/actions/messages.js +167 -0
  40. package/lib/actions/notifications.d.ts +3 -2
  41. package/lib/actions/notifications.d.ts.map +1 -0
  42. package/lib/actions/notifications.js +37 -0
  43. package/lib/actions/payments.d.ts +1 -0
  44. package/lib/actions/payments.d.ts.map +1 -0
  45. package/lib/actions/payments.js +449 -0
  46. package/lib/actions/posts.d.ts +1 -0
  47. package/lib/actions/posts.d.ts.map +1 -0
  48. package/lib/actions/posts.js +608 -0
  49. package/lib/actions/profiles.d.ts +1 -0
  50. package/lib/actions/profiles.d.ts.map +1 -0
  51. package/lib/actions/profiles.js +58 -0
  52. package/lib/actions/reactions.d.ts +1 -0
  53. package/lib/actions/reactions.d.ts.map +1 -0
  54. package/lib/actions/reactions.js +286 -0
  55. package/lib/actions/s3.d.ts +1 -0
  56. package/lib/actions/s3.d.ts.map +1 -0
  57. package/lib/actions/s3.js +102 -0
  58. package/lib/actions/search.d.ts +1 -0
  59. package/lib/actions/search.d.ts.map +1 -0
  60. package/lib/actions/search.js +81 -0
  61. package/lib/actions/sms.d.ts +1 -0
  62. package/lib/actions/sms.d.ts.map +1 -0
  63. package/lib/actions/sms.js +52 -0
  64. package/lib/actions/statistics.d.ts +1 -0
  65. package/lib/actions/statistics.d.ts.map +1 -0
  66. package/lib/actions/statistics.js +43 -0
  67. package/lib/actions/subscriptions.d.ts +1 -0
  68. package/lib/actions/subscriptions.d.ts.map +1 -0
  69. package/lib/actions/subscriptions.js +202 -0
  70. package/lib/actions/tags.d.ts +1 -0
  71. package/lib/actions/tags.d.ts.map +1 -0
  72. package/lib/actions/tags.js +263 -0
  73. package/lib/actions/users.d.ts +1 -0
  74. package/lib/actions/users.d.ts.map +1 -0
  75. package/lib/actions/users.js +802 -0
  76. package/lib/actions/videos.d.ts +1 -0
  77. package/lib/actions/videos.d.ts.map +1 -0
  78. package/lib/actions/videos.js +423 -0
  79. package/lib/actions/websockets.d.ts +1 -0
  80. package/lib/actions/websockets.d.ts.map +1 -0
  81. package/lib/actions/websockets.js +164 -0
  82. package/lib/adapters/arangoAdapter.d.ts +1 -0
  83. package/lib/adapters/arangoAdapter.d.ts.map +1 -0
  84. package/lib/adapters/arangoAdapter.js +70 -0
  85. package/lib/adapters/contentAdapter.d.ts +1 -0
  86. package/lib/adapters/contentAdapter.d.ts.map +1 -0
  87. package/lib/adapters/contentAdapter.js +108 -0
  88. package/lib/adapters/fileAdapter.d.ts +1 -0
  89. package/lib/adapters/fileAdapter.d.ts.map +1 -0
  90. package/lib/adapters/fileAdapter.js +119 -0
  91. package/lib/adapters/imageAdapter.d.ts +1 -0
  92. package/lib/adapters/imageAdapter.d.ts.map +1 -0
  93. package/lib/adapters/imageAdapter.js +112 -0
  94. package/lib/adapters/index.d.ts +1 -0
  95. package/lib/adapters/index.d.ts.map +1 -0
  96. package/lib/adapters/index.js +11 -0
  97. package/lib/adapters/messageAdapter.d.ts +1 -0
  98. package/lib/adapters/messageAdapter.d.ts.map +1 -0
  99. package/lib/adapters/messageAdapter.js +82 -0
  100. package/lib/adapters/postAdapter.d.ts +1 -0
  101. package/lib/adapters/postAdapter.d.ts.map +1 -0
  102. package/lib/adapters/postAdapter.js +117 -0
  103. package/lib/adapters/reaktorAdapter.d.ts +1 -0
  104. package/lib/adapters/reaktorAdapter.d.ts.map +1 -0
  105. package/lib/adapters/reaktorAdapter.js +59 -0
  106. package/lib/adapters/tagAdapter.d.ts +1 -0
  107. package/lib/adapters/tagAdapter.d.ts.map +1 -0
  108. package/lib/adapters/tagAdapter.js +99 -0
  109. package/lib/adapters/userAdapter.d.ts +1 -0
  110. package/lib/adapters/userAdapter.d.ts.map +1 -0
  111. package/lib/adapters/userAdapter.js +264 -0
  112. package/lib/config.d.ts +1 -0
  113. package/lib/config.d.ts.map +1 -0
  114. package/lib/config.js +161 -0
  115. package/lib/handlers/graphqlHandler.d.ts +1 -0
  116. package/lib/handlers/graphqlHandler.d.ts.map +1 -0
  117. package/lib/handlers/graphqlHandler.js +118 -0
  118. package/lib/index.d.ts +1 -0
  119. package/lib/index.d.ts.map +1 -0
  120. package/lib/index.js +18 -0
  121. package/lib/lambdas/actions/websockets.d.ts +1 -0
  122. package/lib/lambdas/actions/websockets.d.ts.map +1 -0
  123. package/lib/lambdas/actions/websockets.js +105 -0
  124. package/lib/lambdas/authorizer.d.ts +1 -0
  125. package/lib/lambdas/authorizer.d.ts.map +1 -0
  126. package/lib/lambdas/authorizer.js +41 -0
  127. package/lib/lambdas/connection.d.ts +1 -0
  128. package/lib/lambdas/connection.d.ts.map +1 -0
  129. package/lib/lambdas/connection.js +85 -0
  130. package/lib/lambdas/utils/message.d.ts +1 -0
  131. package/lib/lambdas/utils/message.d.ts.map +1 -0
  132. package/lib/lambdas/utils/message.js +20 -0
  133. package/lib/lambdas/utils/websocket.d.ts +1 -0
  134. package/lib/lambdas/utils/websocket.d.ts.map +1 -0
  135. package/lib/lambdas/utils/websocket.js +78 -0
  136. package/lib/mocks/conversation.d.ts +1 -0
  137. package/lib/mocks/conversation.d.ts.map +1 -0
  138. package/lib/mocks/conversation.js +10 -0
  139. package/lib/mocks/file.d.ts +1 -0
  140. package/lib/mocks/file.d.ts.map +1 -0
  141. package/lib/mocks/file.js +13 -0
  142. package/lib/mocks/group.d.ts +1 -0
  143. package/lib/mocks/group.d.ts.map +1 -0
  144. package/lib/mocks/group.js +20 -0
  145. package/lib/mocks/image.d.ts +1 -0
  146. package/lib/mocks/image.d.ts.map +1 -0
  147. package/lib/mocks/image.js +17 -0
  148. package/lib/mocks/post.d.ts +1 -0
  149. package/lib/mocks/post.d.ts.map +1 -0
  150. package/lib/mocks/post.js +28 -0
  151. package/lib/mocks/tag.d.ts +1 -0
  152. package/lib/mocks/tag.d.ts.map +1 -0
  153. package/lib/mocks/tag.js +12 -0
  154. package/lib/mocks/user.d.ts +1 -0
  155. package/lib/mocks/user.d.ts.map +1 -0
  156. package/lib/mocks/user.js +61 -0
  157. package/lib/mocks/video.d.ts +1 -0
  158. package/lib/mocks/video.d.ts.map +1 -0
  159. package/lib/mocks/video.js +17 -0
  160. package/lib/mutations/content.d.ts +1 -0
  161. package/lib/mutations/content.d.ts.map +1 -0
  162. package/lib/mutations/content.js +27 -0
  163. package/lib/mutations/index.d.ts +1 -0
  164. package/lib/mutations/index.d.ts.map +1 -0
  165. package/lib/mutations/index.js +29 -0
  166. package/lib/mutations/locations.d.ts +1 -0
  167. package/lib/mutations/locations.d.ts.map +1 -0
  168. package/lib/mutations/locations.js +22 -0
  169. package/lib/mutations/messages.d.ts +1 -0
  170. package/lib/mutations/messages.d.ts.map +1 -0
  171. package/lib/mutations/messages.js +75 -0
  172. package/lib/mutations/posts.d.ts +1 -0
  173. package/lib/mutations/posts.d.ts.map +1 -0
  174. package/lib/mutations/posts.js +31 -0
  175. package/lib/mutations/profiles.d.ts +1 -0
  176. package/lib/mutations/profiles.d.ts.map +1 -0
  177. package/lib/mutations/profiles.js +78 -0
  178. package/lib/mutations/reactions.d.ts +1 -0
  179. package/lib/mutations/reactions.d.ts.map +1 -0
  180. package/lib/mutations/reactions.js +29 -0
  181. package/lib/mutations/statistics.d.ts +1 -0
  182. package/lib/mutations/statistics.d.ts.map +1 -0
  183. package/lib/mutations/statistics.js +17 -0
  184. package/lib/mutations/subscriptions.d.ts +1 -0
  185. package/lib/mutations/subscriptions.d.ts.map +1 -0
  186. package/lib/mutations/subscriptions.js +38 -0
  187. package/lib/mutations/tags.d.ts +1 -0
  188. package/lib/mutations/tags.d.ts.map +1 -0
  189. package/lib/mutations/tags.js +109 -0
  190. package/lib/mutations/users.d.ts +1 -0
  191. package/lib/mutations/users.d.ts.map +1 -0
  192. package/lib/mutations/users.js +129 -0
  193. package/lib/objectTypes/app.d.ts +1 -0
  194. package/lib/objectTypes/app.d.ts.map +1 -0
  195. package/lib/objectTypes/app.js +147 -0
  196. package/lib/objectTypes/bankAccount.d.ts +1 -0
  197. package/lib/objectTypes/bankAccount.d.ts.map +1 -0
  198. package/lib/objectTypes/bankAccount.js +54 -0
  199. package/lib/objectTypes/connection.d.ts +1 -0
  200. package/lib/objectTypes/connection.d.ts.map +1 -0
  201. package/lib/objectTypes/connection.js +26 -0
  202. package/lib/objectTypes/content.d.ts +1 -0
  203. package/lib/objectTypes/content.d.ts.map +1 -0
  204. package/lib/objectTypes/content.js +79 -0
  205. package/lib/objectTypes/conversation.d.ts +1 -0
  206. package/lib/objectTypes/conversation.d.ts.map +1 -0
  207. package/lib/objectTypes/conversation.js +53 -0
  208. package/lib/objectTypes/creditCard.d.ts +1 -0
  209. package/lib/objectTypes/creditCard.d.ts.map +1 -0
  210. package/lib/objectTypes/creditCard.js +64 -0
  211. package/lib/objectTypes/document.d.ts +1 -0
  212. package/lib/objectTypes/document.d.ts.map +1 -0
  213. package/lib/objectTypes/document.js +21 -0
  214. package/lib/objectTypes/error.d.ts +1 -0
  215. package/lib/objectTypes/error.d.ts.map +1 -0
  216. package/lib/objectTypes/error.js +24 -0
  217. package/lib/objectTypes/external.d.ts +1 -0
  218. package/lib/objectTypes/external.d.ts.map +1 -0
  219. package/lib/objectTypes/external.js +52 -0
  220. package/lib/objectTypes/file.d.ts +1 -0
  221. package/lib/objectTypes/file.d.ts.map +1 -0
  222. package/lib/objectTypes/file.js +76 -0
  223. package/lib/objectTypes/filter.d.ts +1 -0
  224. package/lib/objectTypes/filter.d.ts.map +1 -0
  225. package/lib/objectTypes/filter.js +21 -0
  226. package/lib/objectTypes/group.d.ts +1 -0
  227. package/lib/objectTypes/group.d.ts.map +1 -0
  228. package/lib/objectTypes/group.js +97 -0
  229. package/lib/objectTypes/iapSubscription.d.ts +1 -0
  230. package/lib/objectTypes/iapSubscription.d.ts.map +1 -0
  231. package/lib/objectTypes/iapSubscription.js +18 -0
  232. package/lib/objectTypes/image.d.ts +1 -0
  233. package/lib/objectTypes/image.d.ts.map +1 -0
  234. package/lib/objectTypes/image.js +105 -0
  235. package/lib/objectTypes/index.d.ts +1 -0
  236. package/lib/objectTypes/index.d.ts.map +1 -0
  237. package/lib/objectTypes/index.js +28 -0
  238. package/lib/objectTypes/location.d.ts +1 -0
  239. package/lib/objectTypes/location.d.ts.map +1 -0
  240. package/lib/objectTypes/location.js +85 -0
  241. package/lib/objectTypes/message.d.ts +1 -0
  242. package/lib/objectTypes/message.d.ts.map +1 -0
  243. package/lib/objectTypes/message.js +72 -0
  244. package/lib/objectTypes/passcode.d.ts +1 -0
  245. package/lib/objectTypes/passcode.d.ts.map +1 -0
  246. package/lib/objectTypes/passcode.js +20 -0
  247. package/lib/objectTypes/plan.d.ts +1 -0
  248. package/lib/objectTypes/plan.d.ts.map +1 -0
  249. package/lib/objectTypes/plan.js +71 -0
  250. package/lib/objectTypes/post.d.ts +1 -0
  251. package/lib/objectTypes/post.d.ts.map +1 -0
  252. package/lib/objectTypes/post.js +101 -0
  253. package/lib/objectTypes/profile.d.ts +1 -0
  254. package/lib/objectTypes/profile.d.ts.map +1 -0
  255. package/lib/objectTypes/profile.js +68 -0
  256. package/lib/objectTypes/reaction.d.ts +1 -0
  257. package/lib/objectTypes/reaction.d.ts.map +1 -0
  258. package/lib/objectTypes/reaction.js +37 -0
  259. package/lib/objectTypes/relation.d.ts +1 -0
  260. package/lib/objectTypes/relation.d.ts.map +1 -0
  261. package/lib/objectTypes/relation.js +27 -0
  262. package/lib/objectTypes/search.d.ts +1 -0
  263. package/lib/objectTypes/search.d.ts.map +1 -0
  264. package/lib/objectTypes/search.js +50 -0
  265. package/lib/objectTypes/statistics.d.ts +1 -0
  266. package/lib/objectTypes/statistics.d.ts.map +1 -0
  267. package/lib/objectTypes/statistics.js +17 -0
  268. package/lib/objectTypes/subscription.d.ts +1 -0
  269. package/lib/objectTypes/subscription.d.ts.map +1 -0
  270. package/lib/objectTypes/subscription.js +102 -0
  271. package/lib/objectTypes/tag.d.ts +1 -0
  272. package/lib/objectTypes/tag.d.ts.map +1 -0
  273. package/lib/objectTypes/tag.js +41 -0
  274. package/lib/objectTypes/user.d.ts +1 -0
  275. package/lib/objectTypes/user.d.ts.map +1 -0
  276. package/lib/objectTypes/user.js +111 -0
  277. package/lib/queries/content.d.ts +1 -0
  278. package/lib/queries/content.d.ts.map +1 -0
  279. package/lib/queries/content.js +50 -0
  280. package/lib/queries/index.d.ts +1 -0
  281. package/lib/queries/index.d.ts.map +1 -0
  282. package/lib/queries/index.js +27 -0
  283. package/lib/queries/locations.d.ts +1 -0
  284. package/lib/queries/locations.d.ts.map +1 -0
  285. package/lib/queries/locations.js +23 -0
  286. package/lib/queries/messages.d.ts +1 -0
  287. package/lib/queries/messages.d.ts.map +1 -0
  288. package/lib/queries/messages.js +35 -0
  289. package/lib/queries/posts.d.ts +1 -0
  290. package/lib/queries/posts.d.ts.map +1 -0
  291. package/lib/queries/posts.js +154 -0
  292. package/lib/queries/reactions.d.ts +1 -0
  293. package/lib/queries/reactions.d.ts.map +1 -0
  294. package/lib/queries/reactions.js +34 -0
  295. package/lib/queries/statistics.d.ts +1 -0
  296. package/lib/queries/statistics.d.ts.map +1 -0
  297. package/lib/queries/statistics.js +17 -0
  298. package/lib/queries/subscriptions.d.ts +1 -0
  299. package/lib/queries/subscriptions.d.ts.map +1 -0
  300. package/lib/queries/subscriptions.js +21 -0
  301. package/lib/queries/tags.d.ts +1 -0
  302. package/lib/queries/tags.d.ts.map +1 -0
  303. package/lib/queries/tags.js +56 -0
  304. package/lib/queries/users.d.ts +1 -0
  305. package/lib/queries/users.d.ts.map +1 -0
  306. package/lib/queries/users.js +39 -0
  307. package/lib/templates/email/layout.d.ts +1 -0
  308. package/lib/templates/email/layout.d.ts.map +1 -0
  309. package/lib/templates/email/layout.js +281 -0
  310. package/lib/templates/email/passwordForgot.d.ts +1 -0
  311. package/lib/templates/email/passwordForgot.d.ts.map +1 -0
  312. package/lib/templates/email/passwordForgot.js +17 -0
  313. package/lib/templates/email/passwordRecovery.d.ts +1 -0
  314. package/lib/templates/email/passwordRecovery.d.ts.map +1 -0
  315. package/lib/templates/email/passwordRecovery.js +14 -0
  316. package/lib/templates/email/verifyEmail.d.ts +1 -0
  317. package/lib/templates/email/verifyEmail.d.ts.map +1 -0
  318. package/lib/templates/email/verifyEmail.js +17 -0
  319. package/lib/templates/email/welcome.d.ts +1 -0
  320. package/lib/templates/email/welcome.d.ts.map +1 -0
  321. package/lib/templates/email/welcome.js +17 -0
  322. package/lib/templates/sms/passwordForgot.d.ts +1 -0
  323. package/lib/templates/sms/passwordForgot.d.ts.map +1 -0
  324. package/lib/templates/sms/passwordForgot.js +3 -0
  325. package/lib/templates/sms/passwordRecovery.d.ts +1 -0
  326. package/lib/templates/sms/passwordRecovery.d.ts.map +1 -0
  327. package/lib/templates/sms/passwordRecovery.js +3 -0
  328. package/lib/templates/sms/verifyEmail.d.ts +1 -0
  329. package/lib/templates/sms/verifyEmail.d.ts.map +1 -0
  330. package/lib/templates/sms/verifyEmail.js +3 -0
  331. package/lib/templates/sms/verifyPhone.d.ts +1 -0
  332. package/lib/templates/sms/verifyPhone.d.ts.map +1 -0
  333. package/lib/templates/sms/verifyPhone.js +3 -0
  334. package/lib/templates/sms/welcome.d.ts +1 -0
  335. package/lib/templates/sms/welcome.d.ts.map +1 -0
  336. package/lib/templates/sms/welcome.js +3 -0
  337. package/lib/types/apps.types.d.ts +1 -0
  338. package/lib/types/apps.types.d.ts.map +1 -0
  339. package/lib/types/apps.types.js +10 -0
  340. package/lib/types/arangodb.types.d.ts +1 -0
  341. package/lib/types/arangodb.types.d.ts.map +1 -0
  342. package/lib/types/arangodb.types.js +6 -0
  343. package/lib/types/auth.types.d.ts +1 -0
  344. package/lib/types/auth.types.d.ts.map +1 -0
  345. package/lib/types/auth.types.js +6 -0
  346. package/lib/types/connections.types.d.ts +1 -0
  347. package/lib/types/connections.types.d.ts.map +1 -0
  348. package/lib/types/connections.types.js +6 -0
  349. package/lib/types/content.types.d.ts +1 -0
  350. package/lib/types/content.types.d.ts.map +1 -0
  351. package/lib/types/content.types.js +6 -0
  352. package/lib/types/conversations.types.d.ts +1 -0
  353. package/lib/types/conversations.types.d.ts.map +1 -0
  354. package/lib/types/conversations.types.js +6 -0
  355. package/lib/types/email.types.d.ts +1 -0
  356. package/lib/types/email.types.d.ts.map +1 -0
  357. package/lib/types/email.types.js +6 -0
  358. package/lib/types/error.types.d.ts +1 -0
  359. package/lib/types/error.types.d.ts.map +1 -0
  360. package/lib/types/error.types.js +20 -0
  361. package/lib/types/files.types.d.ts +1 -0
  362. package/lib/types/files.types.d.ts.map +1 -0
  363. package/lib/types/files.types.js +6 -0
  364. package/lib/types/google.types.d.ts +1 -0
  365. package/lib/types/google.types.d.ts.map +1 -0
  366. package/lib/types/google.types.js +6 -0
  367. package/lib/types/groups.types.d.ts +1 -0
  368. package/lib/types/groups.types.d.ts.map +1 -0
  369. package/lib/types/groups.types.js +6 -0
  370. package/lib/types/images.types.d.ts +1 -0
  371. package/lib/types/images.types.d.ts.map +1 -0
  372. package/lib/types/images.types.js +6 -0
  373. package/lib/types/index.d.ts +1 -0
  374. package/lib/types/index.d.ts.map +1 -0
  375. package/lib/types/index.js +28 -0
  376. package/lib/types/locations.types.d.ts +1 -0
  377. package/lib/types/locations.types.d.ts.map +1 -0
  378. package/lib/types/locations.types.js +6 -0
  379. package/lib/types/messages.types.d.ts +1 -0
  380. package/lib/types/messages.types.d.ts.map +1 -0
  381. package/lib/types/messages.types.js +6 -0
  382. package/lib/types/notifications.types.d.ts +1 -0
  383. package/lib/types/notifications.types.d.ts.map +1 -0
  384. package/lib/types/notifications.types.js +6 -0
  385. package/lib/types/payments.types.d.ts +1 -0
  386. package/lib/types/payments.types.d.ts.map +1 -0
  387. package/lib/types/payments.types.js +6 -0
  388. package/lib/types/posts.types.d.ts +1 -0
  389. package/lib/types/posts.types.d.ts.map +1 -0
  390. package/lib/types/posts.types.js +6 -0
  391. package/lib/types/profiles.types.d.ts +1 -0
  392. package/lib/types/profiles.types.d.ts.map +1 -0
  393. package/lib/types/profiles.types.js +3 -0
  394. package/lib/types/statistics.types.d.ts +1 -0
  395. package/lib/types/statistics.types.d.ts.map +1 -0
  396. package/lib/types/statistics.types.js +3 -0
  397. package/lib/types/tags.types.d.ts +1 -0
  398. package/lib/types/tags.types.d.ts.map +1 -0
  399. package/lib/types/tags.types.js +6 -0
  400. package/lib/types/users.types.d.ts +1 -0
  401. package/lib/types/users.types.d.ts.map +1 -0
  402. package/lib/types/users.types.js +6 -0
  403. package/lib/types/videos.types.d.ts +1 -0
  404. package/lib/types/videos.types.d.ts.map +1 -0
  405. package/lib/types/videos.types.js +6 -0
  406. package/lib/types/websockets.types.d.ts +1 -0
  407. package/lib/types/websockets.types.d.ts.map +1 -0
  408. package/lib/types/websockets.types.js +6 -0
  409. package/lib/utils/adapterUtils.d.ts +1 -0
  410. package/lib/utils/adapterUtils.d.ts.map +1 -0
  411. package/lib/utils/adapterUtils.js +23 -0
  412. package/lib/utils/analyticsUtils.d.ts +1 -0
  413. package/lib/utils/analyticsUtils.d.ts.map +1 -0
  414. package/lib/utils/analyticsUtils.js +45 -0
  415. package/lib/utils/arangodbUtils.d.ts +1 -0
  416. package/lib/utils/arangodbUtils.d.ts.map +1 -0
  417. package/lib/utils/arangodbUtils.js +130 -0
  418. package/lib/utils/authUtils.d.ts +1 -0
  419. package/lib/utils/authUtils.d.ts.map +1 -0
  420. package/lib/utils/authUtils.js +54 -0
  421. package/lib/utils/contextUtils.d.ts +1 -0
  422. package/lib/utils/contextUtils.d.ts.map +1 -0
  423. package/lib/utils/contextUtils.js +10 -0
  424. package/lib/utils/dbI18n.d.ts +1 -0
  425. package/lib/utils/dbI18n.d.ts.map +1 -0
  426. package/lib/utils/dbI18n.example.d.ts +1 -0
  427. package/lib/utils/dbI18n.example.d.ts.map +1 -0
  428. package/lib/utils/dbI18n.example.js +93 -0
  429. package/lib/utils/dbI18n.js +28 -0
  430. package/lib/utils/googleTranslate.d.ts +1 -0
  431. package/lib/utils/googleTranslate.d.ts.map +1 -0
  432. package/lib/utils/googleTranslate.js +70 -0
  433. package/lib/utils/graphqlUtils.d.ts +1 -0
  434. package/lib/utils/graphqlUtils.d.ts.map +1 -0
  435. package/lib/utils/graphqlUtils.js +11 -0
  436. package/lib/utils/index.d.ts +1 -0
  437. package/lib/utils/index.d.ts.map +1 -0
  438. package/lib/utils/index.js +19 -0
  439. package/lib/utils/languageDetection.d.ts +1 -0
  440. package/lib/utils/languageDetection.d.ts.map +1 -0
  441. package/lib/utils/languageDetection.js +120 -0
  442. package/lib/utils/localeUtils.d.ts +1 -0
  443. package/lib/utils/localeUtils.d.ts.map +1 -0
  444. package/lib/utils/localeUtils.example.d.ts +1 -0
  445. package/lib/utils/localeUtils.example.d.ts.map +1 -0
  446. package/lib/utils/localeUtils.example.js +124 -0
  447. package/lib/utils/localeUtils.js +71 -0
  448. package/lib/utils/middlewareUtils.d.ts +1 -0
  449. package/lib/utils/middlewareUtils.d.ts.map +1 -0
  450. package/lib/utils/middlewareUtils.js +10 -0
  451. package/lib/utils/sessionUtils.d.ts +1 -0
  452. package/lib/utils/sessionUtils.d.ts.map +1 -0
  453. package/lib/utils/sessionUtils.js +26 -0
  454. package/lib/utils/stripeUtils.d.ts +2 -1
  455. package/lib/utils/stripeUtils.d.ts.map +1 -0
  456. package/lib/utils/stripeUtils.js +12 -0
  457. package/lib/utils/templateUtils.d.ts +1 -0
  458. package/lib/utils/templateUtils.d.ts.map +1 -0
  459. package/lib/utils/templateUtils.js +11 -0
  460. package/lib/utils/testUtils.d.ts +1 -0
  461. package/lib/utils/testUtils.d.ts.map +1 -0
  462. package/lib/utils/testUtils.js +292 -0
  463. package/lib/utils/translationQueue.d.ts +1 -0
  464. package/lib/utils/translationQueue.d.ts.map +1 -0
  465. package/lib/utils/translationQueue.example.d.ts +1 -0
  466. package/lib/utils/translationQueue.example.d.ts.map +1 -0
  467. package/lib/utils/translationQueue.example.js +340 -0
  468. package/lib/utils/translationQueue.js +113 -0
  469. package/package.json +54 -24
  470. package/.env +0 -1
  471. package/.env.example +0 -1
  472. package/DATABASE_I18N_GUIDE.md +0 -434
  473. package/TEST_UTILITIES_GUIDE.md +0 -360
  474. package/coverage/actions/groups.ts.html +0 -1039
  475. package/coverage/actions/images.ts.html +0 -2500
  476. package/coverage/actions/index.html +0 -116
  477. package/coverage/actions/notifications.ts.html +0 -223
  478. package/coverage/actions/posts.ts.html +0 -2356
  479. package/coverage/actions/tags.ts.html +0 -1000
  480. package/coverage/adapters/arangoAdapter.ts.html +0 -301
  481. package/coverage/adapters/fileAdapter.ts.html +0 -445
  482. package/coverage/adapters/index.html +0 -176
  483. package/coverage/adapters/postAdapter.ts.html +0 -436
  484. package/coverage/adapters/reaktorAdapter.ts.html +0 -310
  485. package/coverage/adapters/tagAdapter.ts.html +0 -409
  486. package/coverage/adapters/userAdapter.ts.html +0 -829
  487. package/coverage/analyticsUtils.ts.html +0 -286
  488. package/coverage/base.css +0 -224
  489. package/coverage/block-navigation.js +0 -87
  490. package/coverage/clover.xml +0 -6
  491. package/coverage/config.ts.html +0 -766
  492. package/coverage/coverage-final.json +0 -1
  493. package/coverage/favicon.png +0 -0
  494. package/coverage/index.html +0 -221
  495. package/coverage/lcov-report/base.css +0 -224
  496. package/coverage/lcov-report/block-navigation.js +0 -87
  497. package/coverage/lcov-report/favicon.png +0 -0
  498. package/coverage/lcov-report/index.html +0 -101
  499. package/coverage/lcov-report/prettify.css +0 -1
  500. package/coverage/lcov-report/prettify.js +0 -2
  501. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  502. package/coverage/lcov-report/sorter.js +0 -196
  503. package/coverage/lcov.info +0 -0
  504. package/coverage/mocks/file.ts.html +0 -118
  505. package/coverage/mocks/group.ts.html +0 -145
  506. package/coverage/mocks/image.ts.html +0 -142
  507. package/coverage/mocks/index.html +0 -176
  508. package/coverage/mocks/post.ts.html +0 -169
  509. package/coverage/mocks/tag.ts.html +0 -121
  510. package/coverage/mocks/user.ts.html +0 -271
  511. package/coverage/prettify.css +0 -1
  512. package/coverage/prettify.js +0 -2
  513. package/coverage/sort-arrow-sprite.png +0 -0
  514. package/coverage/sorter.js +0 -210
  515. package/coverage/testUtils.ts.html +0 -1309
  516. package/coverage/translationQueue.ts.html +0 -592
  517. package/coverage/types/error.ts.html +0 -145
  518. package/coverage/types/error.types.ts.html +0 -148
  519. package/coverage/types/index.html +0 -116
  520. package/coverage/utils/adapterUtils.ts.html +0 -163
  521. package/coverage/utils/analyticsUtils.ts.html +0 -286
  522. package/coverage/utils/arangodbUtils.ts.html +0 -463
  523. package/coverage/utils/authUtils.ts.html +0 -328
  524. package/coverage/utils/dbI18n.ts.html +0 -280
  525. package/coverage/utils/googleTranslate.ts.html +0 -385
  526. package/coverage/utils/index.html +0 -131
  527. package/coverage/utils/localeUtils.ts.html +0 -193
  528. package/coverage/utils/sessionUtils.ts.html +0 -211
  529. package/coverage/utils/testUtils.ts.html +0 -1309
  530. package/index.js +0 -5
  531. package/jpg:- +0 -0
  532. package/lex.config.mjs +0 -34
  533. package/tsconfig.build.json +0 -21
  534. package/tsconfig.lint.json +0 -33
  535. package/tsconfig.test.json +0 -31
@@ -0,0 +1,723 @@
1
+ /**
2
+ * Copyright (c) 2019-Present, Nitrogen Labs, Inc.
3
+ * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4
+ */ import { get as httpGet } from '@nlabs/rip-hunter';
5
+ import { parseNum } from '@nlabs/utils/parsers/numbers';
6
+ import { createHash, parseArangoId, parseChar, parseId } from '@nlabs/utils/parsers/strings';
7
+ import { aql } from 'arangojs';
8
+ import gm from 'gm';
9
+ import { DateTime } from 'luxon';
10
+ import { Config } from '../config.js';
11
+ import { ErrorTypes } from '../types/error.types.js';
12
+ import { logError, logException } from '../utils/analyticsUtils.js';
13
+ import { getDocId, getLimit, selectReactionCountByType, useDb } from '../utils/arangodbUtils.js';
14
+ import { getGroupDetails, isGrouped } from './groups.js';
15
+ import { s3DeleteList, s3GetSignedUrl, s3Put } from './s3.js';
16
+ import { lowerCaseKeys } from '@nlabs/utils/parsers/objects';
17
+ const eventCategory = 'images';
18
+ gm.subClass({
19
+ imageMagick: '7+'
20
+ });
21
+ export const parseImageOptions = (options = {})=>{
22
+ const { from = 0, to = 30, type = 'default' } = options;
23
+ return {
24
+ limit: getLimit(from, to),
25
+ type: parseChar(type, 32)
26
+ };
27
+ };
28
+ export const getImageOptional = (fields = [])=>fields.reduce((selects, field)=>{
29
+ if (field.includes('Count')) {
30
+ return selectReactionCountByType('images', 'i', field, selects);
31
+ }
32
+ switch(field){
33
+ case 'reactions':
34
+ {
35
+ selects.queries.push(`LET reactions = (
36
+ FOR image, r IN INBOUND i._id reactions
37
+ COLLECT reactionName = r.value INTO reactionItems
38
+ RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
39
+ )`);
40
+ selects.objects.push('reactions:reactions');
41
+ return selects;
42
+ }
43
+ case 'tags':
44
+ {
45
+ selects.queries.push(`LET tags = (
46
+ FOR t, pl IN INBOUND i._id isTagged
47
+ RETURN t
48
+ )`);
49
+ selects.objects.push('tags:tags');
50
+ return selects;
51
+ }
52
+ case 'users':
53
+ {
54
+ selects.queries.push(`LET users = FIRST(
55
+ FOR u IN users
56
+ FILTER i.userId == u._key
57
+ LIMIT 1
58
+ RETURN u
59
+ )`);
60
+ selects.objects.push('users:users');
61
+ return selects;
62
+ }
63
+ default:
64
+ {
65
+ return selects;
66
+ }
67
+ }
68
+ }, {
69
+ objects: [],
70
+ queries: []
71
+ });
72
+ export const getImagesByUser = (context, userId, from = 0, to = 30)=>{
73
+ const action = 'getImagesByUser';
74
+ const { databaseName } = context;
75
+ const formatUserId = parseId(userId);
76
+ const limit = getLimit(from, to);
77
+ const aqlQry = `FOR i IN images
78
+ FILTER i.userId == "${formatUserId}"
79
+ LET user = FIRST(
80
+ FOR u IN users
81
+ FILTER u._key == i.userId
82
+ LIMIT 1
83
+ RETURN u
84
+ )
85
+ ${limit.aql}
86
+ SORT i.added
87
+ RETURN MERGE(i, {user:user})`;
88
+ return useDb(databaseName).query(aqlQry).then((cursor)=>cursor.all()).catch((error)=>{
89
+ logError({
90
+ action,
91
+ category: eventCategory,
92
+ params: {
93
+ from,
94
+ to,
95
+ userId
96
+ },
97
+ value: ErrorTypes.DATABASE_ERROR
98
+ }, error, context);
99
+ return [];
100
+ });
101
+ };
102
+ export const getImageCountByItem = (context, itemId)=>{
103
+ const action = 'getImageCountByItem';
104
+ const { databaseName } = context;
105
+ const formatItemId = parseArangoId(itemId);
106
+ const aqlQry = aql`FOR i IN hasImage
107
+ FILTER i._to == ${formatItemId}
108
+ RETURN {count: COUNT(i)}`;
109
+ return useDb(databaseName).query(aqlQry).then((cursor)=>cursor.next()).then(({ count })=>count).catch((error)=>logError({
110
+ action,
111
+ category: eventCategory,
112
+ params: {
113
+ itemId
114
+ },
115
+ value: ErrorTypes.DATABASE_ERROR
116
+ }, error, context));
117
+ };
118
+ export const getImagesByItem = async (context, itemId, options = {})=>{
119
+ const action = 'getImagesByItem';
120
+ const { databaseName, fields = [] } = context;
121
+ const formatItemId = parseArangoId(itemId);
122
+ const { limit } = parseImageOptions(options);
123
+ const { objects: selectObjects, queries: selectQueries } = getImageOptional(fields);
124
+ const aqlQry = `FOR i, l IN 1..1 OUTBOUND "${formatItemId}" hasImage
125
+ FILTER NOT IS_NULL(i)
126
+ ${selectQueries.join('\n')}
127
+ SORT i.added
128
+ ${limit.aql}
129
+ RETURN MERGE(i, {${selectObjects.join(', ')}})`;
130
+ return useDb(databaseName).query(aqlQry).then((cursor)=>cursor.all()).catch((error)=>{
131
+ logError({
132
+ action,
133
+ category: eventCategory,
134
+ params: {
135
+ itemId,
136
+ options
137
+ },
138
+ value: ErrorTypes.DATABASE_ERROR
139
+ }, error, context);
140
+ return [];
141
+ });
142
+ };
143
+ export const getImagesByGroup = (context, params)=>{
144
+ const action = 'getImagesByGroup';
145
+ const { databaseName, session: { userId: sessionId } } = context;
146
+ const { filters, groupId, from, to } = params;
147
+ const formatGroupId = parseId(groupId);
148
+ const limit = getLimit(from, to);
149
+ filters.map((filter)=>{
150
+ const { conditional, name, value } = filter;
151
+ let formatCond = conditional;
152
+ if (conditional !== '>=' && conditional !== '<=' && conditional !== '>' && conditional !== '<') {
153
+ formatCond = '==';
154
+ }
155
+ switch(name){
156
+ case 'added':
157
+ return `p.added ${formatCond} ${parseNum(value)}`;
158
+ default:
159
+ return '';
160
+ }
161
+ });
162
+ return getGroupDetails(context, formatGroupId).then((group)=>{
163
+ if (group.privacy === 'public') {
164
+ filters.push({
165
+ conditional: '==',
166
+ name: 'groupId',
167
+ value: formatGroupId
168
+ });
169
+ const filterStr = filters.join(' && ');
170
+ const aqlQry = `FOR i IN
171
+ FLATTEN(
172
+ FOR p IN posts
173
+ FILTER ${filterStr}
174
+ LET images = (
175
+ FOR i, e IN INBOUND p._id hasImage
176
+ RETURN i
177
+ )
178
+ SORT p.added DESC
179
+ RETURN images
180
+ )
181
+ SORT i.added DESC
182
+ ${limit.aql}
183
+ RETURN i`;
184
+ return useDb(databaseName).query(aqlQry).then((cursor)=>cursor.all()).catch((error)=>{
185
+ logError({
186
+ action,
187
+ category: eventCategory,
188
+ params: {
189
+ filters,
190
+ from,
191
+ groupId,
192
+ to
193
+ },
194
+ value: ErrorTypes.DATABASE_ERROR
195
+ }, error, context);
196
+ return [];
197
+ });
198
+ }
199
+ return isGrouped(context, sessionId, groupId).then((grouped)=>{
200
+ if (grouped.isValid) {
201
+ filters.push({
202
+ conditional: '==',
203
+ name: 'groupId',
204
+ value: grouped.groupId
205
+ });
206
+ const filterList = filters.join(' && ');
207
+ const aqlQry = `FOR p IN post
208
+ FILTER ${filterList}
209
+ FOR f IN p.files
210
+ FILTER f.type == "image/jpeg" || f.type == "image/png"
211
+ ${limit.aql}
212
+ SORT p.added DESC
213
+ RETURN f`;
214
+ return useDb(databaseName).query(aqlQry).then((cursor)=>cursor.all()).catch((error)=>{
215
+ logError({
216
+ action,
217
+ category: eventCategory,
218
+ params: {
219
+ filters,
220
+ from,
221
+ groupId,
222
+ to
223
+ },
224
+ value: ErrorTypes.DATABASE_ERROR
225
+ }, error, context);
226
+ return [];
227
+ });
228
+ }
229
+ return [];
230
+ });
231
+ });
232
+ };
233
+ export const getImagesByReactions = (context, reactions = [], options)=>{
234
+ const action = 'getUsersByImage';
235
+ const { databaseName, fields = [], session: { userId: sessionId } } = context;
236
+ const { limit } = parseImageOptions(options);
237
+ const { objects: selectObjects, queries: selectQueries } = getImageOptional(fields);
238
+ const formatSessionId = `users/${sessionId}`;
239
+ const formatReactions = reactions.map((reactionName)=>parseChar(reactionName, 32));
240
+ const filterBy = [
241
+ 'r.type == "images"',
242
+ `POSITION(${JSON.stringify(formatReactions)}, LOWER(r.name))`
243
+ ];
244
+ // Get data from database
245
+ const aqlQry = `FOR i, r IN OUTBOUND "${formatSessionId}" hasReaction
246
+ OPTIONS {vertexCollections: "images"}
247
+ ${selectQueries.join('\n')}
248
+ FILTER ${filterBy.join(' && ')}
249
+ ${limit.aql}
250
+ RETURN MERGE(i, {${selectObjects.join(', ')}})`;
251
+ return useDb(databaseName).query(aqlQry).then((cursor)=>cursor.all()).catch((error)=>{
252
+ logError({
253
+ action,
254
+ category: eventCategory,
255
+ params: {
256
+ options,
257
+ reactions
258
+ },
259
+ value: ErrorTypes.DATABASE_ERROR
260
+ }, error, context);
261
+ return [];
262
+ });
263
+ };
264
+ export const getImage = (context, imageId)=>{
265
+ const action = 'getItem';
266
+ const { databaseName } = context;
267
+ const formatImageId = parseId(imageId);
268
+ const aqlQry = aql`FOR i IN images
269
+ FILTER i._key==${formatImageId}
270
+ LIMIT 1
271
+ RETURN i`;
272
+ return useDb(databaseName).query(aqlQry).then((cursor)=>cursor.next()).catch((error)=>logError({
273
+ action,
274
+ category: eventCategory,
275
+ params: {
276
+ imageId
277
+ },
278
+ value: ErrorTypes.DATABASE_ERROR
279
+ }, error, context));
280
+ };
281
+ export const getPathUserImages = (userId, imageId, imageType, dir = 'images')=>{
282
+ let filename = imageId;
283
+ switch(imageType){
284
+ case 'image/png':
285
+ filename = `${imageId}.png`;
286
+ break;
287
+ default:
288
+ filename = `${imageId}.jpg`;
289
+ break;
290
+ }
291
+ return `users/${userId}/${dir}/${filename}`;
292
+ };
293
+ export const getAppImageUrl = ({ bucket, directory = 'images', imageId, imageType = 'jpg', isThumb = false, type, typeId })=>{
294
+ if (!type) {
295
+ return '';
296
+ }
297
+ if (!imageId) {
298
+ if (imageType === 'profile') {
299
+ return `${Config.get('image.defaultUrl')}/users_bk.jpg`;
300
+ }
301
+ return `${Config.get('image.defaultUrl')}/users_wh.jpg`;
302
+ }
303
+ const bucketName = bucket || Config.get('image.bucket') || 'dev.reaktor.io';
304
+ const imageName = isThumb ? `${imageId}-th.${imageType}` : `${imageId}.${imageType === 'profile' || imageType === 'other' ? 'jpg' : imageType}`;
305
+ const imageUrl = Config.get('image.url') || `https://s3.amazonaws.com/${bucketName}`;
306
+ if (type === 'apps') {
307
+ return `${imageUrl}/${type}/${directory}/${imageName}`;
308
+ }
309
+ return `${imageUrl}/${type}/${typeId}/${directory}/${imageName}`;
310
+ };
311
+ export const getImageUrl = async ({ bucket, imageDir = 'images', imageId, imageType = 'jpg', isThumb = false, type, typeId, urlType = 'public' })=>{
312
+ if (!imageId) {
313
+ return '';
314
+ }
315
+ // Always use signed URLs for thumbnails
316
+ if (isThumb) {
317
+ urlType = 'signed';
318
+ }
319
+ const thumbSuffix = isThumb ? '-th' : '';
320
+ const imageKey = `${type}/${typeId}/${imageDir}/${imageId}${thumbSuffix}.${imageType}`;
321
+ switch(urlType){
322
+ case 'signed':
323
+ {
324
+ try {
325
+ const defaultBucket = Config.get('image.bucket') || 'dev.reaktor.io';
326
+ return await s3GetSignedUrl({
327
+ Bucket: bucket || defaultBucket,
328
+ Expires: 900,
329
+ Key: imageKey
330
+ });
331
+ } catch (error) {
332
+ throw error;
333
+ }
334
+ }
335
+ case 'public':
336
+ {
337
+ return `https://box.${Config.get('app.url')}/${imageKey}`;
338
+ }
339
+ case 'dev':
340
+ {
341
+ return `https://s3.amazonaws.com/dev.${Config.get('app.url')}/${imageKey}`;
342
+ }
343
+ default:
344
+ {
345
+ return '';
346
+ }
347
+ }
348
+ };
349
+ export const resizeSaveImage = async (context, imageId, buffer, fileType = 'image/jpeg', s3Options)=>{
350
+ const action = 'resizeSaveImage';
351
+ const { session: { userId: sessionId } } = context;
352
+ const imgW = Config.get('image.imgSize');
353
+ const imgQ = Config.get('image.imgQuality');
354
+ const format = fileType.split('/')[1];
355
+ const imageOptimizedBuffer = await new Promise((resolve, reject)=>{
356
+ gm(buffer, 'img').setFormat(format).quality(imgQ).autoOrient().resize(imgW, imgW, '>').stream((streamError, stdout)=>{
357
+ if (streamError) {
358
+ reject(logError({
359
+ action,
360
+ category: eventCategory,
361
+ params: {
362
+ fileType,
363
+ imageId
364
+ },
365
+ value: ErrorTypes.IMAGE_SAVE
366
+ }, streamError, context));
367
+ return;
368
+ }
369
+ let imageBuffer = Buffer.from('');
370
+ stdout.on('data', (data)=>{
371
+ imageBuffer = Buffer.concat([
372
+ imageBuffer,
373
+ data
374
+ ]);
375
+ });
376
+ stdout.on('end', ()=>resolve(imageBuffer));
377
+ });
378
+ });
379
+ try {
380
+ const imageObj = {
381
+ ACL: 'authenticated-read',
382
+ Body: imageOptimizedBuffer,
383
+ Bucket: null,
384
+ ContentType: fileType,
385
+ ...s3Options || {},
386
+ Key: getPathUserImages(sessionId, imageId, fileType, 'images')
387
+ };
388
+ await s3Put(imageObj);
389
+ } catch (error) {
390
+ return logError({
391
+ action,
392
+ category: eventCategory,
393
+ params: {
394
+ fileType,
395
+ imageId
396
+ },
397
+ value: ErrorTypes.IMAGE_SAVE
398
+ }, error, context);
399
+ }
400
+ const imageIdentity = await new Promise((resolve)=>{
401
+ gm(imageOptimizedBuffer, 'img').identify({
402
+ bufferStream: true
403
+ }, (error, imageData = {})=>{
404
+ if (error) {
405
+ return logError({
406
+ action,
407
+ category: eventCategory,
408
+ value: ErrorTypes.IMAGE_SAVE
409
+ }, error, context);
410
+ }
411
+ const formatValues = lowerCaseKeys(imageData);
412
+ const { make: cameraMake, model: cameraModel, datetimeoriginal: taken } = formatValues;
413
+ const stats = formatValues['channel statistics'];
414
+ let color;
415
+ if (stats) {
416
+ let { red, green, blue, mean } = stats;
417
+ if (red) {
418
+ mean = red['standard deviation'] || red.mean;
419
+ red = mean ? +mean.split(' ')[0].substring(0, 3) : 0;
420
+ } else {
421
+ red = 0;
422
+ }
423
+ if (green) {
424
+ mean = green['standard deviation'] || green.mean;
425
+ green = mean ? +mean.split(' ')[0].substring(0, 3) : 0;
426
+ } else {
427
+ green = 0;
428
+ }
429
+ if (blue) {
430
+ mean = blue['standard deviation'] || blue.mean;
431
+ blue = mean ? +mean.split(' ')[0].substring(0, 3) : 0;
432
+ } else {
433
+ blue = 0;
434
+ }
435
+ const rgb = blue | green << 8 | red << 16;
436
+ const rgbColor = rgb.toString(16);
437
+ color = rgbColor === '0' ? '000000' : rgbColor;
438
+ }
439
+ const { 'JPEG-Quality': quality, Orientation: orientationData, Resolution: resolutionData, size } = imageData;
440
+ let resolution;
441
+ if (resolutionData) {
442
+ const [resolutionNumber, resolutionUnit] = resolutionData.split(' ');
443
+ const resolutionValue = resolutionNumber.split('x')[0];
444
+ const resolutionUnitValue = resolutionUnit === 'pixels/inch' ? 'ppi' : '';
445
+ resolution = `${resolutionValue} ${resolutionUnitValue}`;
446
+ }
447
+ return resolve({
448
+ color,
449
+ fileSize: imageOptimizedBuffer.length,
450
+ fileType: format,
451
+ height: size?.height || 0,
452
+ imageId,
453
+ make: cameraMake,
454
+ model: cameraModel,
455
+ orientation: orientationData === 'Unknown' ? undefined : orientationData?.toLowerCase(),
456
+ quality: quality ? +quality : undefined,
457
+ resolution,
458
+ taken: taken ? DateTime.fromMillis(taken).millisecond : undefined,
459
+ width: size?.width || 0
460
+ });
461
+ });
462
+ });
463
+ const thumbOptimizedBuffer = await new Promise((resolve, reject)=>{
464
+ const thmW = Config.get('image.thmSize');
465
+ const thmQ = Config.get('image.thmQuality');
466
+ gm(imageOptimizedBuffer, 'img').setFormat(format).gravity('Center').resize(thmW, thmW, '^').extent(thmW, thmW).quality(thmQ).stream((streamError, thumbStdout)=>{
467
+ if (streamError) {
468
+ logError({
469
+ action,
470
+ category: eventCategory,
471
+ params: {
472
+ fileType,
473
+ imageId
474
+ },
475
+ value: ErrorTypes.IMAGE_SAVE
476
+ }, streamError, context);
477
+ return;
478
+ }
479
+ let thumbBuffer = Buffer.from('');
480
+ thumbStdout.on('data', (data)=>{
481
+ thumbBuffer = Buffer.concat([
482
+ thumbBuffer,
483
+ data
484
+ ]);
485
+ });
486
+ thumbStdout.on('end', ()=>resolve(thumbBuffer));
487
+ });
488
+ });
489
+ try {
490
+ const thumbObj = {
491
+ ACL: 'authenticated-read',
492
+ Body: thumbOptimizedBuffer,
493
+ Bucket: null,
494
+ ContentType: fileType,
495
+ ...s3Options || {},
496
+ Key: getPathUserImages(sessionId, imageId, fileType, 'thumbs')
497
+ };
498
+ await s3Put(thumbObj);
499
+ } catch (error) {
500
+ return logError({
501
+ action,
502
+ category: eventCategory,
503
+ value: ErrorTypes.IMAGE_SAVE
504
+ }, error, context);
505
+ }
506
+ return imageIdentity;
507
+ };
508
+ export const addImage = (context, image, s3Options)=>{
509
+ const action = 'addImage';
510
+ const { databaseName, session: { userId: sessionId } } = context;
511
+ const { imageId, description, buffer, fileType } = image;
512
+ const now = Date.now();
513
+ return resizeSaveImage(context, imageId, buffer, fileType, s3Options).then((resizedImage)=>{
514
+ const insert = {
515
+ ...resizedImage,
516
+ _key: imageId,
517
+ added: now,
518
+ description,
519
+ fileType,
520
+ modified: now,
521
+ userId: sessionId
522
+ };
523
+ const aqlQry = aql`INSERT ${insert} IN images RETURN NEW`;
524
+ return useDb(databaseName).query(aqlQry).then((cursor)=>cursor.next()).catch((error)=>logError({
525
+ action,
526
+ category: eventCategory,
527
+ params: {
528
+ image,
529
+ s3Options
530
+ },
531
+ value: ErrorTypes.DATABASE_ERROR
532
+ }, error, context));
533
+ }).catch((error)=>logError({
534
+ action,
535
+ category: eventCategory,
536
+ value: ErrorTypes.IMAGE_RESIZE
537
+ }, error, context));
538
+ };
539
+ export const addImageEdge = async (context, imageEdge)=>{
540
+ const action = 'addImageEdge';
541
+ const { databaseName, session: { userId: sessionId } } = context;
542
+ const { imageId, itemId, itemType } = imageEdge;
543
+ const now = Date.now();
544
+ // const edgeCollection: EdgeCollection = useDb(databaseName).collection('hasImage');
545
+ const edgeId = createHash(`hasImage-${imageId}-${itemId}-${sessionId}`);
546
+ const formatItemType = parseChar(itemType).toLowerCase();
547
+ const formatItemId = parseId(itemId);
548
+ const itemDocId = getDocId(formatItemType, {
549
+ _key: formatItemId
550
+ });
551
+ const formatImageId = parseId(imageId);
552
+ const fileDocId = `images/${formatImageId}`;
553
+ const edge = {
554
+ _from: itemDocId,
555
+ _key: edgeId,
556
+ _to: fileDocId,
557
+ added: now,
558
+ itemType
559
+ };
560
+ if (itemDocId) {
561
+ return useDb(databaseName).collection('hasImage').save(edge, {
562
+ returnNew: true
563
+ }).then((fileEdge)=>useDb(databaseName).collection('hasImage').document(fileEdge)).catch((error)=>logError({
564
+ action,
565
+ category: eventCategory,
566
+ params: {
567
+ edge,
568
+ fileDocId,
569
+ imageId,
570
+ itemDocId,
571
+ itemId,
572
+ itemType
573
+ },
574
+ value: ErrorTypes.DATABASE_ERROR
575
+ }, error, context));
576
+ }
577
+ return null;
578
+ };
579
+ export const updateImage = async (context, image, s3Options)=>{
580
+ const action = 'updateImage';
581
+ const { databaseName, session: { userId: sessionId } } = context;
582
+ const { base64 = '', buffer: imageBuffer, description = '', imageId, itemId, itemType, fileType, url = '' } = image;
583
+ const now = Date.now();
584
+ const formatImageId = imageId || createHash(`image-${sessionId}`);
585
+ const formatItemId = parseId(itemId);
586
+ const formatItemType = parseChar(itemType, 16).toLowerCase();
587
+ const customParams = {
588
+ description,
589
+ imageId: formatImageId,
590
+ userId: sessionId
591
+ };
592
+ if (base64 || imageBuffer) {
593
+ let buffer = imageBuffer;
594
+ if (base64) {
595
+ const formatBase64 = base64.substr(base64.indexOf(',') + 1);
596
+ buffer = Buffer.from(formatBase64, 'base64');
597
+ }
598
+ let updatedFileType = fileType;
599
+ if (!fileType) {
600
+ const { fileTypeFromBuffer } = await import('file-type');
601
+ const { mime } = await fileTypeFromBuffer(buffer);
602
+ updatedFileType = mime;
603
+ }
604
+ const imgParams = {
605
+ ...customParams,
606
+ buffer,
607
+ fileType: updatedFileType
608
+ };
609
+ return addImage(context, imgParams, s3Options).then((image)=>{
610
+ if (formatItemId && formatItemType) {
611
+ const imageEdge = {
612
+ imageId: formatImageId,
613
+ itemId: formatItemId,
614
+ itemType: formatItemType
615
+ };
616
+ return addImageEdge(context, imageEdge).then(()=>image);
617
+ }
618
+ return image;
619
+ }).catch((error)=>logError({
620
+ action,
621
+ category: eventCategory,
622
+ value: ErrorTypes.IMAGE_SAVE
623
+ }, error, context));
624
+ } else if (url !== '') {
625
+ let contentType;
626
+ return httpGet(url).then((res)=>{
627
+ if (res.status !== 200) {
628
+ return logException({
629
+ action,
630
+ category: eventCategory,
631
+ value: ErrorTypes.IMAGE_REQUEST
632
+ }, context);
633
+ }
634
+ contentType = res.headers.get('content-type');
635
+ return res;
636
+ }).then((res)=>res.buffer()).then((buffer)=>{
637
+ const imgParams = {
638
+ ...customParams,
639
+ buffer,
640
+ fileType: contentType
641
+ };
642
+ return addImage(context, imgParams, s3Options).then((image)=>{
643
+ if (formatItemId && formatItemType) {
644
+ const imageEdge = {
645
+ imageId: formatImageId,
646
+ itemId: formatItemId,
647
+ itemType: formatItemType
648
+ };
649
+ return addImageEdge(context, imageEdge).then(()=>image);
650
+ }
651
+ return image;
652
+ });
653
+ }).catch((error)=>logError({
654
+ action,
655
+ category: eventCategory,
656
+ value: 'fetch_error'
657
+ }, error, context));
658
+ } else if (imageId !== '') {
659
+ const update = {
660
+ description,
661
+ modified: now
662
+ };
663
+ const aqlQry = aql`UPDATE {_key: ${formatImageId}} WITH ${update} IN images RETURN NEW`;
664
+ return useDb(databaseName).query(aqlQry).then((cursor)=>cursor.next()).catch((error)=>logError({
665
+ action,
666
+ category: eventCategory,
667
+ params: {
668
+ aqlQry,
669
+ formatImageId,
670
+ update
671
+ },
672
+ value: ErrorTypes.DATABASE_ERROR
673
+ }, error, context));
674
+ }
675
+ return null;
676
+ };
677
+ export const deleteImage = async (context, imageId)=>{
678
+ const action = 'delete';
679
+ const { databaseName, session: { userId: sessionId } } = context;
680
+ const formatImageId = parseId(imageId);
681
+ try {
682
+ const removeEdgeQuery = aql`FOR hi IN hasImage
683
+ FILTER hi._from == ${formatImageId}
684
+ REMOVE hi IN hasImage
685
+ RETURN OLD`;
686
+ await useDb(databaseName).query(removeEdgeQuery);
687
+ const aqlQuery = aql`FOR i IN images
688
+ FILTER i._key == ${formatImageId} && i.userId == ${sessionId}
689
+ REMOVE i IN images
690
+ RETURN OLD`;
691
+ const image = await useDb(databaseName).query(aqlQuery).then((cursor)=>cursor.next());
692
+ if (image) {
693
+ const { _key: imageKey } = image;
694
+ const params = {
695
+ Bucket: null,
696
+ Delete: {
697
+ Objects: [
698
+ {
699
+ Key: `users/${sessionId}/images/${imageKey}.jpg`
700
+ },
701
+ {
702
+ Key: `users/${sessionId}/thumbs/${imageKey}.jpg`
703
+ }
704
+ ],
705
+ Quiet: true
706
+ }
707
+ };
708
+ return s3DeleteList(params).then(()=>image);
709
+ }
710
+ return null;
711
+ } catch (error) {
712
+ return logError({
713
+ action,
714
+ category: eventCategory,
715
+ params: {
716
+ imageId
717
+ },
718
+ value: ErrorTypes.DATABASE_ERROR
719
+ }, error, context);
720
+ }
721
+ };
722
+
723
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9uaXRyb2c3L0RldmVsb3BtZW50L3JlYWt0b3Ivc3JjL2FjdGlvbnMvaW1hZ2VzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChjKSAyMDE5LVByZXNlbnQsIE5pdHJvZ2VuIExhYnMsIEluYy5cbiAqIENvcHlyaWdodHMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgdGhlIGFjY29tcGFueWluZyBMSUNFTlNFIGZpbGUgZm9yIHRlcm1zLlxuICovXG5pbXBvcnQge0RlbGV0ZU9iamVjdHNDb21tYW5kSW5wdXQsIFB1dE9iamVjdENvbW1hbmRJbnB1dH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LXMzJztcbmltcG9ydCB7Z2V0IGFzIGh0dHBHZXR9IGZyb20gJ0BubGFicy9yaXAtaHVudGVyJztcbmltcG9ydCB7cGFyc2VOdW19IGZyb20gJ0BubGFicy91dGlscy9wYXJzZXJzL251bWJlcnMnO1xuaW1wb3J0IHtjcmVhdGVIYXNoLCBwYXJzZUFyYW5nb0lkLCBwYXJzZUNoYXIsIHBhcnNlSWR9IGZyb20gJ0BubGFicy91dGlscy9wYXJzZXJzL3N0cmluZ3MnO1xuaW1wb3J0IHthcWx9IGZyb20gJ2FyYW5nb2pzJztcbmltcG9ydCB7QXFsUXVlcnl9IGZyb20gJ2FyYW5nb2pzL2FxbCc7XG5pbXBvcnQgZ20gZnJvbSAnZ20nO1xuaW1wb3J0IHtEYXRlVGltZX0gZnJvbSAnbHV4b24nO1xuXG5pbXBvcnQge0NvbmZpZ30gZnJvbSAnLi4vY29uZmlnLmpzJztcbmltcG9ydCB7RXJyb3JUeXBlc30gZnJvbSAnLi4vdHlwZXMvZXJyb3IudHlwZXMuanMnO1xuaW1wb3J0IHtsb2dFcnJvciwgbG9nRXhjZXB0aW9ufSBmcm9tICcuLi91dGlscy9hbmFseXRpY3NVdGlscy5qcyc7XG5pbXBvcnQge2dldERvY0lkLCBnZXRMaW1pdCwgc2VsZWN0UmVhY3Rpb25Db3VudEJ5VHlwZSwgdXNlRGJ9IGZyb20gJy4uL3V0aWxzL2FyYW5nb2RiVXRpbHMuanMnO1xuaW1wb3J0IHtnZXRHcm91cERldGFpbHMsIGlzR3JvdXBlZH0gZnJvbSAnLi9ncm91cHMuanMnO1xuaW1wb3J0IHtzM0RlbGV0ZUxpc3QsIHMzR2V0U2lnbmVkVXJsLCBzM1B1dH0gZnJvbSAnLi9zMy5qcyc7XG5cbmltcG9ydCB7bG93ZXJDYXNlS2V5c30gZnJvbSAnQG5sYWJzL3V0aWxzL3BhcnNlcnMvb2JqZWN0cyc7XG5pbXBvcnQgdHlwZSB7UXVlcnlGaWx0ZXJ9IGZyb20gJy4uL3R5cGVzL2FwcHMudHlwZXMuanMnO1xuaW1wb3J0IHR5cGUge0FyYW5nb0RiQ29sbGVjdGlvbiwgQXJhbmdvRGJMaW1pdH0gZnJvbSAnLi4vdHlwZXMvYXJhbmdvZGIudHlwZXMuanMnO1xuaW1wb3J0IHR5cGUge0FwaUNvbnRleHR9IGZyb20gJy4uL3R5cGVzL2F1dGgudHlwZXMuanMnO1xuaW1wb3J0IHR5cGUge0dyb3VwVHlwZSwgR3JvdXBVc2VyfSBmcm9tICcuLi90eXBlcy9ncm91cHMudHlwZXMuanMnO1xuaW1wb3J0IHR5cGUge0ltYWdlRWRnZVR5cGUsIEltYWdlSWRlbnRpZnlUeXBlLCBJbWFnZU9wdGlvbnMsIEltYWdlVHlwZSwgSW1hZ2VVcmxEYXRhfSBmcm9tICcuLi90eXBlcy9pbWFnZXMudHlwZXMuanMnO1xuXG4vLyBEZWZpbmUgaW50ZXJmYWNlIGZvciBIVFRQIHJlc3BvbnNlIHdpdGggYnVmZmVyIG1ldGhvZFxuaW50ZXJmYWNlIEh0dHBSZXNwb25zZSBleHRlbmRzIFJlc3BvbnNlIHtcbiAgYnVmZmVyKCk6IFByb21pc2U8QnVmZmVyPjtcbn1cblxuY29uc3QgZXZlbnRDYXRlZ29yeTogc3RyaW5nID0gJ2ltYWdlcyc7XG5nbS5zdWJDbGFzcyh7aW1hZ2VNYWdpY2s6ICc3Kyd9KTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlSW1hZ2VPcHRpb25zID0gKG9wdGlvbnM6IEltYWdlT3B0aW9ucyA9IHt9KSA9PiB7XG4gIGNvbnN0IHtcbiAgICBmcm9tID0gMCxcbiAgICB0byA9IDMwLFxuICAgIHR5cGUgPSAnZGVmYXVsdCdcbiAgfSA9IG9wdGlvbnM7XG5cbiAgcmV0dXJuIHtcbiAgICBsaW1pdDogZ2V0TGltaXQoZnJvbSwgdG8pIGFzIEFyYW5nb0RiTGltaXQsXG4gICAgdHlwZTogcGFyc2VDaGFyKHR5cGUsIDMyKVxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGdldEltYWdlT3B0aW9uYWwgPSAoZmllbGRzOiBzdHJpbmdbXSA9IFtdKSA9PlxuICBmaWVsZHMucmVkdWNlKChzZWxlY3RzLCBmaWVsZDogc3RyaW5nKSA9PiB7XG4gICAgaWYoZmllbGQuaW5jbHVkZXMoJ0NvdW50JykpIHtcbiAgICAgIHJldHVybiBzZWxlY3RSZWFjdGlvbkNvdW50QnlUeXBlKCdpbWFnZXMnLCAnaScsIGZpZWxkLCBzZWxlY3RzKTtcbiAgICB9XG5cbiAgICBzd2l0Y2goZmllbGQpIHtcbiAgICAgIGNhc2UgJ3JlYWN0aW9ucyc6IHtcbiAgICAgICAgc2VsZWN0cy5xdWVyaWVzLnB1c2goYExFVCByZWFjdGlvbnMgPSAoXG4gICAgICAgICAgRk9SIGltYWdlLCByIElOIElOQk9VTkQgaS5faWQgcmVhY3Rpb25zXG4gICAgICAgICAgQ09MTEVDVCByZWFjdGlvbk5hbWUgPSByLnZhbHVlIElOVE8gcmVhY3Rpb25JdGVtc1xuICAgICAgICAgIFJFVFVSTiB7bmFtZTogcmVhY3Rpb25OYW1lLCBjb3VudDogTEVOR1RIKHJlYWN0aW9uSXRlbXNbKl0uci52YWx1ZSl9XG4gICAgICAgIClgKTtcbiAgICAgICAgc2VsZWN0cy5vYmplY3RzLnB1c2goJ3JlYWN0aW9uczpyZWFjdGlvbnMnKTtcbiAgICAgICAgcmV0dXJuIHNlbGVjdHM7XG4gICAgICB9XG4gICAgICBjYXNlICd0YWdzJzoge1xuICAgICAgICBzZWxlY3RzLnF1ZXJpZXMucHVzaChgTEVUIHRhZ3MgPSAoXG4gICAgICAgICAgRk9SIHQsIHBsIElOIElOQk9VTkQgaS5faWQgaXNUYWdnZWRcbiAgICAgICAgICBSRVRVUk4gdFxuICAgICAgICApYCk7XG4gICAgICAgIHNlbGVjdHMub2JqZWN0cy5wdXNoKCd0YWdzOnRhZ3MnKTtcbiAgICAgICAgcmV0dXJuIHNlbGVjdHM7XG4gICAgICB9XG4gICAgICBjYXNlICd1c2Vycyc6IHtcbiAgICAgICAgc2VsZWN0cy5xdWVyaWVzLnB1c2goYExFVCB1c2VycyA9IEZJUlNUKFxuICAgICAgICAgIEZPUiB1IElOIHVzZXJzXG4gICAgICAgICAgRklMVEVSIGkudXNlcklkID09IHUuX2tleVxuICAgICAgICAgIExJTUlUIDFcbiAgICAgICAgICBSRVRVUk4gdVxuICAgICAgICApYCk7XG4gICAgICAgIHNlbGVjdHMub2JqZWN0cy5wdXNoKCd1c2Vyczp1c2VycycpO1xuICAgICAgICByZXR1cm4gc2VsZWN0cztcbiAgICAgIH1cbiAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgcmV0dXJuIHNlbGVjdHM7XG4gICAgICB9XG4gICAgfVxuICB9LCB7b2JqZWN0czogW10sIHF1ZXJpZXM6IFtdfSk7XG5cbmV4cG9ydCBjb25zdCBnZXRJbWFnZXNCeVVzZXIgPSAoXG4gIGNvbnRleHQ6IEFwaUNvbnRleHQsXG4gIHVzZXJJZDogc3RyaW5nLFxuICBmcm9tOiBudW1iZXIgPSAwLFxuICB0bzogbnVtYmVyID0gMzBcbik6IFByb21pc2U8SW1hZ2VUeXBlW10+ID0+IHtcbiAgY29uc3QgYWN0aW9uOiBzdHJpbmcgPSAnZ2V0SW1hZ2VzQnlVc2VyJztcbiAgY29uc3Qge2RhdGFiYXNlTmFtZX0gPSBjb250ZXh0O1xuICBjb25zdCBmb3JtYXRVc2VySWQ6IHN0cmluZyA9IHBhcnNlSWQodXNlcklkKTtcbiAgY29uc3QgbGltaXQ6IEFyYW5nb0RiTGltaXQgPSBnZXRMaW1pdChmcm9tLCB0byk7XG4gIGNvbnN0IGFxbFFyeTogc3RyaW5nID0gYEZPUiBpIElOIGltYWdlc1xuICAgICAgRklMVEVSIGkudXNlcklkID09IFwiJHtmb3JtYXRVc2VySWR9XCJcbiAgICAgIExFVCB1c2VyID0gRklSU1QoXG4gICAgICAgIEZPUiB1IElOIHVzZXJzXG4gICAgICAgIEZJTFRFUiB1Ll9rZXkgPT0gaS51c2VySWRcbiAgICAgICAgTElNSVQgMVxuICAgICAgICBSRVRVUk4gdVxuICAgICAgKVxuICAgICAgJHtsaW1pdC5hcWx9XG4gICAgICBTT1JUIGkuYWRkZWRcbiAgICAgIFJFVFVSTiBNRVJHRShpLCB7dXNlcjp1c2VyfSlgO1xuXG4gIHJldHVybiB1c2VEYihkYXRhYmFzZU5hbWUpLnF1ZXJ5KGFxbFFyeSlcbiAgICAudGhlbigoY3Vyc29yKSA9PiBjdXJzb3IuYWxsKCkgYXMgdW5rbm93biBhcyBJbWFnZVR5cGVbXSlcbiAgICAuY2F0Y2goKGVycm9yOiBFcnJvcikgPT4ge1xuICAgICAgbG9nRXJyb3Ioe1xuICAgICAgICBhY3Rpb24sXG4gICAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgICBwYXJhbXM6IHtmcm9tLCB0bywgdXNlcklkfSxcbiAgICAgICAgdmFsdWU6IEVycm9yVHlwZXMuREFUQUJBU0VfRVJST1JcbiAgICAgIH0sIGVycm9yLCBjb250ZXh0KTtcblxuICAgICAgcmV0dXJuIFtdO1xuICAgIH0pO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldEltYWdlQ291bnRCeUl0ZW0gPSAoY29udGV4dDogQXBpQ29udGV4dCwgaXRlbUlkOiBzdHJpbmcpOiBQcm9taXNlPG51bWJlcj4gPT4ge1xuICBjb25zdCBhY3Rpb246IHN0cmluZyA9ICdnZXRJbWFnZUNvdW50QnlJdGVtJztcbiAgY29uc3Qge2RhdGFiYXNlTmFtZX0gPSBjb250ZXh0O1xuICBjb25zdCBmb3JtYXRJdGVtSWQ6IHN0cmluZyA9IHBhcnNlQXJhbmdvSWQoaXRlbUlkKTtcbiAgY29uc3QgYXFsUXJ5OiBBcWxRdWVyeSA9IGFxbGBGT1IgaSBJTiBoYXNJbWFnZVxuICAgICAgRklMVEVSIGkuX3RvID09ICR7Zm9ybWF0SXRlbUlkfVxuICAgICAgUkVUVVJOIHtjb3VudDogQ09VTlQoaSl9YDtcblxuICByZXR1cm4gdXNlRGIoZGF0YWJhc2VOYW1lKS5xdWVyeShhcWxRcnkpXG4gICAgLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLm5leHQoKSlcbiAgICAudGhlbigoe2NvdW50fSkgPT4gY291bnQpXG4gICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IGxvZ0Vycm9yKHtcbiAgICAgIGFjdGlvbixcbiAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgcGFyYW1zOiB7aXRlbUlkfSxcbiAgICAgIHZhbHVlOiBFcnJvclR5cGVzLkRBVEFCQVNFX0VSUk9SXG4gICAgfSwgZXJyb3IsIGNvbnRleHQpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRJbWFnZXNCeUl0ZW0gPSBhc3luYyAoXG4gIGNvbnRleHQ6IEFwaUNvbnRleHQsXG4gIGl0ZW1JZDogc3RyaW5nLFxuICBvcHRpb25zOiBJbWFnZU9wdGlvbnMgPSB7fVxuKTogUHJvbWlzZTxJbWFnZVR5cGVbXT4gPT4ge1xuICBjb25zdCBhY3Rpb246IHN0cmluZyA9ICdnZXRJbWFnZXNCeUl0ZW0nO1xuICBjb25zdCB7ZGF0YWJhc2VOYW1lLCBmaWVsZHMgPSBbXX0gPSBjb250ZXh0O1xuICBjb25zdCBmb3JtYXRJdGVtSWQ6IHN0cmluZyA9IHBhcnNlQXJhbmdvSWQoaXRlbUlkKTtcbiAgY29uc3Qge2xpbWl0fSA9IHBhcnNlSW1hZ2VPcHRpb25zKG9wdGlvbnMpO1xuICBjb25zdCB7b2JqZWN0czogc2VsZWN0T2JqZWN0cywgcXVlcmllczogc2VsZWN0UXVlcmllc30gPSBnZXRJbWFnZU9wdGlvbmFsKGZpZWxkcyk7XG4gIGNvbnN0IGFxbFFyeTogc3RyaW5nID0gYEZPUiBpLCBsIElOIDEuLjEgT1VUQk9VTkQgXCIke2Zvcm1hdEl0ZW1JZH1cIiBoYXNJbWFnZVxuICAgIEZJTFRFUiBOT1QgSVNfTlVMTChpKVxuICAgICR7c2VsZWN0UXVlcmllcy5qb2luKCdcXG4nKX1cbiAgICBTT1JUIGkuYWRkZWRcbiAgICAke2xpbWl0LmFxbH1cbiAgICBSRVRVUk4gTUVSR0UoaSwgeyR7c2VsZWN0T2JqZWN0cy5qb2luKCcsICcpfX0pYDtcblxuICByZXR1cm4gdXNlRGIoZGF0YWJhc2VOYW1lKS5xdWVyeShhcWxRcnkpXG4gICAgLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLmFsbCgpIGFzIHVua25vd24gYXMgSW1hZ2VUeXBlW10pXG4gICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgIGxvZ0Vycm9yKHtcbiAgICAgICAgYWN0aW9uLFxuICAgICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgICAgcGFyYW1zOiB7aXRlbUlkLCBvcHRpb25zfSxcbiAgICAgICAgdmFsdWU6IEVycm9yVHlwZXMuREFUQUJBU0VfRVJST1JcbiAgICAgIH0sIGVycm9yLCBjb250ZXh0KTtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9KTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRJbWFnZXNCeUdyb3VwID0gKFxuICBjb250ZXh0OiBBcGlDb250ZXh0LFxuICBwYXJhbXM6IHtmaWx0ZXJzOiBRdWVyeUZpbHRlcltdLCBncm91cElkOiBzdHJpbmcsIGZyb206IG51bWJlciwgdG86IG51bWJlcn1cbik6IFByb21pc2U8SW1hZ2VUeXBlW10+ID0+IHtcbiAgY29uc3QgYWN0aW9uOiBzdHJpbmcgPSAnZ2V0SW1hZ2VzQnlHcm91cCc7XG4gIGNvbnN0IHtkYXRhYmFzZU5hbWUsIHNlc3Npb246IHt1c2VySWQ6IHNlc3Npb25JZH19ID0gY29udGV4dDtcbiAgY29uc3Qge2ZpbHRlcnMsIGdyb3VwSWQsIGZyb20sIHRvfSA9IHBhcmFtcztcbiAgY29uc3QgZm9ybWF0R3JvdXBJZDogc3RyaW5nID0gcGFyc2VJZChncm91cElkKTtcbiAgY29uc3QgbGltaXQ6IEFyYW5nb0RiTGltaXQgPSBnZXRMaW1pdChmcm9tLCB0byk7XG5cbiAgZmlsdGVyc1xuICAgIC5tYXAoKGZpbHRlcjogUXVlcnlGaWx0ZXIpID0+IHtcbiAgICAgIGNvbnN0IHtjb25kaXRpb25hbCwgbmFtZSwgdmFsdWV9ID0gZmlsdGVyO1xuICAgICAgbGV0IGZvcm1hdENvbmQ6IHN0cmluZyA9IGNvbmRpdGlvbmFsO1xuXG4gICAgICBpZihjb25kaXRpb25hbCAhPT0gJz49JyAmJiBjb25kaXRpb25hbCAhPT0gJzw9JyAmJiBjb25kaXRpb25hbCAhPT0gJz4nICYmIGNvbmRpdGlvbmFsICE9PSAnPCcpIHtcbiAgICAgICAgZm9ybWF0Q29uZCA9ICc9PSc7XG4gICAgICB9XG5cbiAgICAgIHN3aXRjaChuYW1lKSB7XG4gICAgICAgIGNhc2UgJ2FkZGVkJzpcbiAgICAgICAgICByZXR1cm4gYHAuYWRkZWQgJHtmb3JtYXRDb25kfSAke3BhcnNlTnVtKHZhbHVlKX1gO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHJldHVybiAnJztcbiAgICAgIH1cbiAgICB9KTtcblxuICByZXR1cm4gZ2V0R3JvdXBEZXRhaWxzKGNvbnRleHQsIGZvcm1hdEdyb3VwSWQpXG4gICAgLnRoZW4oKGdyb3VwOiBHcm91cFR5cGUpID0+IHtcbiAgICAgIGlmKGdyb3VwLnByaXZhY3kgPT09ICdwdWJsaWMnKSB7XG4gICAgICAgIGZpbHRlcnMucHVzaCh7Y29uZGl0aW9uYWw6ICc9PScsIG5hbWU6ICdncm91cElkJywgdmFsdWU6IGZvcm1hdEdyb3VwSWR9KTtcbiAgICAgICAgY29uc3QgZmlsdGVyU3RyID0gZmlsdGVycy5qb2luKCcgJiYgJyk7XG4gICAgICAgIGNvbnN0IGFxbFFyeTogc3RyaW5nID0gYEZPUiBpIElOXG4gICAgICAgICAgRkxBVFRFTihcbiAgICAgICAgICAgIEZPUiBwIElOIHBvc3RzXG4gICAgICAgICAgICBGSUxURVIgJHtmaWx0ZXJTdHJ9XG4gICAgICAgICAgICBMRVQgaW1hZ2VzID0gKFxuICAgICAgICAgICAgICBGT1IgaSwgZSBJTiBJTkJPVU5EIHAuX2lkIGhhc0ltYWdlXG4gICAgICAgICAgICAgIFJFVFVSTiBpXG4gICAgICAgICAgICApXG4gICAgICAgICAgICBTT1JUIHAuYWRkZWQgREVTQ1xuICAgICAgICAgICAgUkVUVVJOIGltYWdlc1xuICAgICAgICAgIClcbiAgICAgICAgICBTT1JUIGkuYWRkZWQgREVTQ1xuICAgICAgICAgICR7bGltaXQuYXFsfVxuICAgICAgICAgIFJFVFVSTiBpYDtcblxuICAgICAgICByZXR1cm4gdXNlRGIoZGF0YWJhc2VOYW1lKS5xdWVyeShhcWxRcnkpXG4gICAgICAgICAgLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLmFsbCgpIGFzIHVua25vd24gYXMgSW1hZ2VUeXBlW10pXG4gICAgICAgICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgICAgIGxvZ0Vycm9yKHtcbiAgICAgICAgICAgICAgYWN0aW9uLFxuICAgICAgICAgICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgICAgICAgICAgcGFyYW1zOiB7ZmlsdGVycywgZnJvbSwgZ3JvdXBJZCwgdG99LFxuICAgICAgICAgICAgICB2YWx1ZTogRXJyb3JUeXBlcy5EQVRBQkFTRV9FUlJPUlxuICAgICAgICAgICAgfSwgZXJyb3IsIGNvbnRleHQpO1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGlzR3JvdXBlZChjb250ZXh0LCBzZXNzaW9uSWQsIGdyb3VwSWQpXG4gICAgICAgIC50aGVuKChncm91cGVkOiBHcm91cFVzZXIpID0+IHtcbiAgICAgICAgICBpZihncm91cGVkLmlzVmFsaWQpIHtcbiAgICAgICAgICAgIGZpbHRlcnMucHVzaCh7Y29uZGl0aW9uYWw6ICc9PScsIG5hbWU6ICdncm91cElkJywgdmFsdWU6IGdyb3VwZWQuZ3JvdXBJZH0pO1xuICAgICAgICAgICAgY29uc3QgZmlsdGVyTGlzdDogc3RyaW5nID0gZmlsdGVycy5qb2luKCcgJiYgJyk7XG4gICAgICAgICAgICBjb25zdCBhcWxRcnk6IHN0cmluZyA9IGBGT1IgcCBJTiBwb3N0XG4gICAgICAgICAgICAgICAgRklMVEVSICR7ZmlsdGVyTGlzdH1cbiAgICAgICAgICAgICAgICBGT1IgZiBJTiBwLmZpbGVzXG4gICAgICAgICAgICAgICAgRklMVEVSIGYudHlwZSA9PSBcImltYWdlL2pwZWdcIiB8fCBmLnR5cGUgPT0gXCJpbWFnZS9wbmdcIlxuICAgICAgICAgICAgICAgICR7bGltaXQuYXFsfVxuICAgICAgICAgICAgICAgIFNPUlQgcC5hZGRlZCBERVNDXG4gICAgICAgICAgICAgICAgUkVUVVJOIGZgO1xuXG4gICAgICAgICAgICByZXR1cm4gdXNlRGIoZGF0YWJhc2VOYW1lKS5xdWVyeShhcWxRcnkpXG4gICAgICAgICAgICAgIC50aGVuKChjdXJzb3IpID0+IGN1cnNvci5hbGwoKSBhcyB1bmtub3duIGFzIEltYWdlVHlwZVtdKVxuICAgICAgICAgICAgICAuY2F0Y2goKGVycm9yOiBFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGxvZ0Vycm9yKHtcbiAgICAgICAgICAgICAgICAgIGFjdGlvbixcbiAgICAgICAgICAgICAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgICAgICAgICAgICAgcGFyYW1zOiB7ZmlsdGVycywgZnJvbSwgZ3JvdXBJZCwgdG99LFxuICAgICAgICAgICAgICAgICAgdmFsdWU6IEVycm9yVHlwZXMuREFUQUJBU0VfRVJST1JcbiAgICAgICAgICAgICAgICB9LCBlcnJvciwgY29udGV4dCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRJbWFnZXNCeVJlYWN0aW9ucyA9IChcbiAgY29udGV4dDogQXBpQ29udGV4dCxcbiAgcmVhY3Rpb25zOiBzdHJpbmdbXSA9IFtdLFxuICBvcHRpb25zPzogSW1hZ2VPcHRpb25zXG4pOiBQcm9taXNlPEltYWdlVHlwZVtdPiA9PiB7XG4gIGNvbnN0IGFjdGlvbjogc3RyaW5nID0gJ2dldFVzZXJzQnlJbWFnZSc7XG4gIGNvbnN0IHtkYXRhYmFzZU5hbWUsIGZpZWxkcyA9IFtdLCBzZXNzaW9uOiB7dXNlcklkOiBzZXNzaW9uSWR9fSA9IGNvbnRleHQ7XG4gIGNvbnN0IHtsaW1pdH0gPSBwYXJzZUltYWdlT3B0aW9ucyhvcHRpb25zKTtcbiAgY29uc3Qge29iamVjdHM6IHNlbGVjdE9iamVjdHMsIHF1ZXJpZXM6IHNlbGVjdFF1ZXJpZXN9ID0gZ2V0SW1hZ2VPcHRpb25hbChmaWVsZHMpO1xuICBjb25zdCBmb3JtYXRTZXNzaW9uSWQ6IHN0cmluZyA9IGB1c2Vycy8ke3Nlc3Npb25JZH1gO1xuICBjb25zdCBmb3JtYXRSZWFjdGlvbnM6IHN0cmluZ1tdID0gcmVhY3Rpb25zLm1hcCgocmVhY3Rpb25OYW1lKSA9PiBwYXJzZUNoYXIocmVhY3Rpb25OYW1lLCAzMikpO1xuICBjb25zdCBmaWx0ZXJCeTogc3RyaW5nW10gPSBbXG4gICAgJ3IudHlwZSA9PSBcImltYWdlc1wiJyxcbiAgICBgUE9TSVRJT04oJHtKU09OLnN0cmluZ2lmeShmb3JtYXRSZWFjdGlvbnMpfSwgTE9XRVIoci5uYW1lKSlgXTtcblxuICAvLyBHZXQgZGF0YSBmcm9tIGRhdGFiYXNlXG4gIGNvbnN0IGFxbFFyeTogc3RyaW5nID0gYEZPUiBpLCByIElOIE9VVEJPVU5EIFwiJHtmb3JtYXRTZXNzaW9uSWR9XCIgaGFzUmVhY3Rpb25cbiAgICBPUFRJT05TIHt2ZXJ0ZXhDb2xsZWN0aW9uczogXCJpbWFnZXNcIn1cbiAgICAke3NlbGVjdFF1ZXJpZXMuam9pbignXFxuJyl9XG4gICAgRklMVEVSICR7ZmlsdGVyQnkuam9pbignICYmICcpfVxuICAgICR7bGltaXQuYXFsfVxuICAgIFJFVFVSTiBNRVJHRShpLCB7JHtzZWxlY3RPYmplY3RzLmpvaW4oJywgJyl9fSlgO1xuXG4gIHJldHVybiB1c2VEYihkYXRhYmFzZU5hbWUpLnF1ZXJ5KGFxbFFyeSlcbiAgICAudGhlbigoY3Vyc29yKSA9PiBjdXJzb3IuYWxsKCkgYXMgdW5rbm93biBhcyBJbWFnZVR5cGVbXSlcbiAgICAuY2F0Y2goKGVycm9yOiBFcnJvcikgPT4ge1xuICAgICAgbG9nRXJyb3Ioe1xuICAgICAgICBhY3Rpb24sXG4gICAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgICBwYXJhbXM6IHtvcHRpb25zLCByZWFjdGlvbnN9LFxuICAgICAgICB2YWx1ZTogRXJyb3JUeXBlcy5EQVRBQkFTRV9FUlJPUlxuICAgICAgfSwgZXJyb3IsIGNvbnRleHQpO1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH0pO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldEltYWdlID0gKGNvbnRleHQ6IEFwaUNvbnRleHQsIGltYWdlSWQ6IHN0cmluZyk6IFByb21pc2U8SW1hZ2VUeXBlPiA9PiB7XG4gIGNvbnN0IGFjdGlvbjogc3RyaW5nID0gJ2dldEl0ZW0nO1xuICBjb25zdCB7ZGF0YWJhc2VOYW1lfSA9IGNvbnRleHQ7XG4gIGNvbnN0IGZvcm1hdEltYWdlSWQ6IHN0cmluZyA9IHBhcnNlSWQoaW1hZ2VJZCk7XG4gIGNvbnN0IGFxbFFyeTogQXFsUXVlcnkgPSBhcWxgRk9SIGkgSU4gaW1hZ2VzXG4gICAgRklMVEVSIGkuX2tleT09JHtmb3JtYXRJbWFnZUlkfVxuICAgIExJTUlUIDFcbiAgICBSRVRVUk4gaWA7XG5cbiAgcmV0dXJuIHVzZURiKGRhdGFiYXNlTmFtZSkucXVlcnkoYXFsUXJ5KVxuICAgIC50aGVuKChjdXJzb3IpID0+IGN1cnNvci5uZXh0KCkpXG4gICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IGxvZ0Vycm9yKHtcbiAgICAgIGFjdGlvbixcbiAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgcGFyYW1zOiB7aW1hZ2VJZH0sXG4gICAgICB2YWx1ZTogRXJyb3JUeXBlcy5EQVRBQkFTRV9FUlJPUlxuICAgIH0sIGVycm9yLCBjb250ZXh0KSk7XG59O1xuXG5leHBvcnQgY29uc3QgZ2V0UGF0aFVzZXJJbWFnZXMgPSAodXNlcklkOiBzdHJpbmcsIGltYWdlSWQ6IHN0cmluZywgaW1hZ2VUeXBlOiBzdHJpbmcsIGRpcjogc3RyaW5nID0gJ2ltYWdlcycpOiBzdHJpbmcgPT4ge1xuICBsZXQgZmlsZW5hbWU6IHN0cmluZyA9IGltYWdlSWQ7XG5cbiAgc3dpdGNoKGltYWdlVHlwZSkge1xuICAgIGNhc2UgJ2ltYWdlL3BuZyc6XG4gICAgICBmaWxlbmFtZSA9IGAke2ltYWdlSWR9LnBuZ2A7XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgZmlsZW5hbWUgPSBgJHtpbWFnZUlkfS5qcGdgO1xuICAgICAgYnJlYWs7XG4gIH1cblxuICByZXR1cm4gYHVzZXJzLyR7dXNlcklkfS8ke2Rpcn0vJHtmaWxlbmFtZX1gO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldEFwcEltYWdlVXJsID0gKHtcbiAgYnVja2V0LFxuICBkaXJlY3RvcnkgPSAnaW1hZ2VzJyxcbiAgaW1hZ2VJZCxcbiAgaW1hZ2VUeXBlID0gJ2pwZycsXG4gIGlzVGh1bWIgPSBmYWxzZSxcbiAgdHlwZSxcbiAgdHlwZUlkXG59OiBJbWFnZVVybERhdGEpOiBzdHJpbmcgPT4ge1xuICBpZighdHlwZSkge1xuICAgIHJldHVybiAnJztcbiAgfVxuXG4gIGlmKCFpbWFnZUlkKSB7XG4gICAgaWYoaW1hZ2VUeXBlID09PSAncHJvZmlsZScpIHtcbiAgICAgIHJldHVybiBgJHtDb25maWcuZ2V0KCdpbWFnZS5kZWZhdWx0VXJsJyl9L3VzZXJzX2JrLmpwZ2A7XG4gICAgfVxuICAgIHJldHVybiBgJHtDb25maWcuZ2V0KCdpbWFnZS5kZWZhdWx0VXJsJyl9L3VzZXJzX3doLmpwZ2A7XG4gIH1cblxuICBjb25zdCBidWNrZXROYW1lID0gYnVja2V0IHx8IENvbmZpZy5nZXQoJ2ltYWdlLmJ1Y2tldCcpIHx8ICdkZXYucmVha3Rvci5pbyc7XG4gIGNvbnN0IGltYWdlTmFtZSA9IGlzVGh1bWIgPyBgJHtpbWFnZUlkfS10aC4ke2ltYWdlVHlwZX1gIDogYCR7aW1hZ2VJZH0uJHtpbWFnZVR5cGUgPT09ICdwcm9maWxlJyB8fCBpbWFnZVR5cGUgPT09ICdvdGhlcicgPyAnanBnJyA6IGltYWdlVHlwZX1gO1xuICBjb25zdCBpbWFnZVVybCA9IENvbmZpZy5nZXQoJ2ltYWdlLnVybCcpIHx8IGBodHRwczovL3MzLmFtYXpvbmF3cy5jb20vJHtidWNrZXROYW1lfWA7XG5cbiAgaWYodHlwZSA9PT0gJ2FwcHMnKSB7XG4gICAgcmV0dXJuIGAke2ltYWdlVXJsfS8ke3R5cGV9LyR7ZGlyZWN0b3J5fS8ke2ltYWdlTmFtZX1gO1xuICB9XG5cbiAgcmV0dXJuIGAke2ltYWdlVXJsfS8ke3R5cGV9LyR7dHlwZUlkfS8ke2RpcmVjdG9yeX0vJHtpbWFnZU5hbWV9YDtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRJbWFnZVVybCA9IGFzeW5jICh7XG4gIGJ1Y2tldCxcbiAgaW1hZ2VEaXIgPSAnaW1hZ2VzJyxcbiAgaW1hZ2VJZCxcbiAgaW1hZ2VUeXBlID0gJ2pwZycsXG4gIGlzVGh1bWIgPSBmYWxzZSxcbiAgdHlwZSxcbiAgdHlwZUlkLFxuICB1cmxUeXBlID0gJ3B1YmxpYydcbn06IEltYWdlVXJsRGF0YSk6IFByb21pc2U8c3RyaW5nPiA9PiB7XG4gIGlmKCFpbWFnZUlkKSB7XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgLy8gQWx3YXlzIHVzZSBzaWduZWQgVVJMcyBmb3IgdGh1bWJuYWlsc1xuICBpZihpc1RodW1iKSB7XG4gICAgdXJsVHlwZSA9ICdzaWduZWQnO1xuICB9XG5cbiAgY29uc3QgdGh1bWJTdWZmaXggPSBpc1RodW1iID8gJy10aCcgOiAnJztcbiAgY29uc3QgaW1hZ2VLZXk6IHN0cmluZyA9IGAke3R5cGV9LyR7dHlwZUlkfS8ke2ltYWdlRGlyfS8ke2ltYWdlSWR9JHt0aHVtYlN1ZmZpeH0uJHtpbWFnZVR5cGV9YDtcblxuICBzd2l0Y2godXJsVHlwZSkge1xuICAgIGNhc2UgJ3NpZ25lZCc6IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGRlZmF1bHRCdWNrZXQgPSBDb25maWcuZ2V0KCdpbWFnZS5idWNrZXQnKSB8fCAnZGV2LnJlYWt0b3IuaW8nO1xuICAgICAgICByZXR1cm4gYXdhaXQgczNHZXRTaWduZWRVcmwoe0J1Y2tldDogYnVja2V0IHx8IGRlZmF1bHRCdWNrZXQsIEV4cGlyZXM6IDkwMCwgS2V5OiBpbWFnZUtleX0pO1xuICAgICAgfSBjYXRjaChlcnJvcikge1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH1cbiAgICB9XG4gICAgY2FzZSAncHVibGljJzoge1xuICAgICAgcmV0dXJuIGBodHRwczovL2JveC4ke0NvbmZpZy5nZXQoJ2FwcC51cmwnKX0vJHtpbWFnZUtleX1gO1xuICAgIH1cbiAgICBjYXNlICdkZXYnOiB7XG4gICAgICByZXR1cm4gYGh0dHBzOi8vczMuYW1hem9uYXdzLmNvbS9kZXYuJHtDb25maWcuZ2V0KCdhcHAudXJsJyl9LyR7aW1hZ2VLZXl9YDtcbiAgICB9XG4gICAgZGVmYXVsdDoge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IHJlc2l6ZVNhdmVJbWFnZSA9IGFzeW5jIChcbiAgY29udGV4dDogQXBpQ29udGV4dCxcbiAgaW1hZ2VJZDogc3RyaW5nLFxuICBidWZmZXI6IEJ1ZmZlcixcbiAgZmlsZVR5cGU6IHN0cmluZyA9ICdpbWFnZS9qcGVnJywgczNPcHRpb25zPzogUHV0T2JqZWN0Q29tbWFuZElucHV0XG4pOiBQcm9taXNlPEltYWdlVHlwZT4gPT4ge1xuICBjb25zdCBhY3Rpb246IHN0cmluZyA9ICdyZXNpemVTYXZlSW1hZ2UnO1xuICBjb25zdCB7c2Vzc2lvbjoge3VzZXJJZDogc2Vzc2lvbklkfX0gPSBjb250ZXh0O1xuICBjb25zdCBpbWdXOiBudW1iZXIgPSBDb25maWcuZ2V0KCdpbWFnZS5pbWdTaXplJyk7XG4gIGNvbnN0IGltZ1E6IG51bWJlciA9IENvbmZpZy5nZXQoJ2ltYWdlLmltZ1F1YWxpdHknKTtcbiAgY29uc3QgZm9ybWF0OiBzdHJpbmcgPSAoZmlsZVR5cGUuc3BsaXQoJy8nKSlbMV07XG5cbiAgY29uc3QgaW1hZ2VPcHRpbWl6ZWRCdWZmZXI6IEJ1ZmZlciA9IGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBnbShidWZmZXIsICdpbWcnKVxuICAgICAgLnNldEZvcm1hdChmb3JtYXQpXG4gICAgICAucXVhbGl0eShpbWdRKVxuICAgICAgLmF1dG9PcmllbnQoKVxuICAgICAgLnJlc2l6ZShpbWdXLCBpbWdXLCAnPicpXG4gICAgICAuc3RyZWFtKChzdHJlYW1FcnJvcjogRXJyb3IsIHN0ZG91dCk6IHZvaWQgPT4ge1xuICAgICAgICBpZihzdHJlYW1FcnJvcikge1xuICAgICAgICAgIHJlamVjdChcbiAgICAgICAgICAgIGxvZ0Vycm9yKHtcbiAgICAgICAgICAgICAgYWN0aW9uLFxuICAgICAgICAgICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgICAgICAgICAgcGFyYW1zOiB7ZmlsZVR5cGUsIGltYWdlSWR9LFxuICAgICAgICAgICAgICB2YWx1ZTogRXJyb3JUeXBlcy5JTUFHRV9TQVZFXG4gICAgICAgICAgICB9LCBzdHJlYW1FcnJvciwgY29udGV4dClcbiAgICAgICAgICApO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBpbWFnZUJ1ZmZlcjogQnVmZmVyID0gQnVmZmVyLmZyb20oJycpO1xuXG4gICAgICAgIHN0ZG91dC5vbignZGF0YScsIChkYXRhKSA9PiB7XG4gICAgICAgICAgaW1hZ2VCdWZmZXIgPSBCdWZmZXIuY29uY2F0KFtpbWFnZUJ1ZmZlciwgZGF0YV0pO1xuICAgICAgICB9KTtcblxuICAgICAgICBzdGRvdXQub24oJ2VuZCcsICgpID0+IHJlc29sdmUoaW1hZ2VCdWZmZXIpKTtcbiAgICAgIH0pO1xuICB9KTtcblxuICB0cnkge1xuICAgIGNvbnN0IGltYWdlT2JqOiBQdXRPYmplY3RDb21tYW5kSW5wdXQgPSB7XG4gICAgICBBQ0w6ICdhdXRoZW50aWNhdGVkLXJlYWQnLFxuICAgICAgQm9keTogaW1hZ2VPcHRpbWl6ZWRCdWZmZXIsXG4gICAgICBCdWNrZXQ6IG51bGwsXG4gICAgICBDb250ZW50VHlwZTogZmlsZVR5cGUsXG4gICAgICAuLi4oczNPcHRpb25zIHx8IHt9KSxcbiAgICAgIEtleTogZ2V0UGF0aFVzZXJJbWFnZXMoc2Vzc2lvbklkLCBpbWFnZUlkLCBmaWxlVHlwZSwgJ2ltYWdlcycpXG4gICAgfTtcbiAgICBhd2FpdCBzM1B1dChpbWFnZU9iaik7XG4gIH0gY2F0Y2goZXJyb3IpIHtcbiAgICByZXR1cm4gbG9nRXJyb3Ioe1xuICAgICAgYWN0aW9uLFxuICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICBwYXJhbXM6IHtmaWxlVHlwZSwgaW1hZ2VJZH0sXG4gICAgICB2YWx1ZTogRXJyb3JUeXBlcy5JTUFHRV9TQVZFXG4gICAgfSwgZXJyb3IsIGNvbnRleHQpO1xuICB9XG5cbiAgY29uc3QgaW1hZ2VJZGVudGl0eSA9IGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgZ20oaW1hZ2VPcHRpbWl6ZWRCdWZmZXIsICdpbWcnKVxuICAgICAgLmlkZW50aWZ5KHtidWZmZXJTdHJlYW06IHRydWV9LCAoZXJyb3I6IEVycm9yLCBpbWFnZURhdGE6IEltYWdlSWRlbnRpZnlUeXBlID0ge30pID0+IHtcbiAgICAgICAgaWYoZXJyb3IpIHtcbiAgICAgICAgICByZXR1cm4gbG9nRXJyb3Ioe1xuICAgICAgICAgICAgYWN0aW9uLFxuICAgICAgICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICAgICAgICB2YWx1ZTogRXJyb3JUeXBlcy5JTUFHRV9TQVZFXG4gICAgICAgICAgfSwgZXJyb3IsIGNvbnRleHQpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZm9ybWF0VmFsdWVzID0gbG93ZXJDYXNlS2V5cyhpbWFnZURhdGEpO1xuICAgICAgICBjb25zdCB7bWFrZTogY2FtZXJhTWFrZSwgbW9kZWw6IGNhbWVyYU1vZGVsLCBkYXRldGltZW9yaWdpbmFsOiB0YWtlbn06IEltYWdlSWRlbnRpZnlUeXBlID0gZm9ybWF0VmFsdWVzO1xuICAgICAgICBjb25zdCBzdGF0cyA9IGZvcm1hdFZhbHVlc1snY2hhbm5lbCBzdGF0aXN0aWNzJ107XG4gICAgICAgIGxldCBjb2xvcjogc3RyaW5nO1xuXG4gICAgICAgIGlmKHN0YXRzKSB7XG4gICAgICAgICAgbGV0IHtyZWQsIGdyZWVuLCBibHVlLCBtZWFufSA9IHN0YXRzO1xuXG4gICAgICAgICAgaWYocmVkKSB7XG4gICAgICAgICAgICBtZWFuID0gcmVkWydzdGFuZGFyZCBkZXZpYXRpb24nXSB8fCByZWQubWVhbjtcbiAgICAgICAgICAgIHJlZCA9IG1lYW4gPyArKChtZWFuLnNwbGl0KCcgJylbMF0pLnN1YnN0cmluZygwLCAzKSkgOiAwO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZWQgPSAwO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmKGdyZWVuKSB7XG4gICAgICAgICAgICBtZWFuID0gZ3JlZW5bJ3N0YW5kYXJkIGRldmlhdGlvbiddIHx8IGdyZWVuLm1lYW47XG4gICAgICAgICAgICBncmVlbiA9IG1lYW4gPyArKChtZWFuLnNwbGl0KCcgJylbMF0pLnN1YnN0cmluZygwLCAzKSkgOiAwO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBncmVlbiA9IDA7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYoYmx1ZSkge1xuICAgICAgICAgICAgbWVhbiA9IGJsdWVbJ3N0YW5kYXJkIGRldmlhdGlvbiddIHx8IGJsdWUubWVhbjtcbiAgICAgICAgICAgIGJsdWUgPSBtZWFuID8gKygobWVhbi5zcGxpdCgnICcpWzBdKS5zdWJzdHJpbmcoMCwgMykpIDogMDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYmx1ZSA9IDA7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgcmdiID0gYmx1ZSB8IChncmVlbiA8PCA4KSB8IChyZWQgPDwgMTYpO1xuICAgICAgICAgIGNvbnN0IHJnYkNvbG9yID0gcmdiLnRvU3RyaW5nKDE2KTtcbiAgICAgICAgICBjb2xvciA9IHJnYkNvbG9yID09PSAnMCcgPyAnMDAwMDAwJyA6IHJnYkNvbG9yO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgICdKUEVHLVF1YWxpdHknOiBxdWFsaXR5LFxuICAgICAgICAgIE9yaWVudGF0aW9uOiBvcmllbnRhdGlvbkRhdGEsXG4gICAgICAgICAgUmVzb2x1dGlvbjogcmVzb2x1dGlvbkRhdGEsXG4gICAgICAgICAgc2l6ZVxuICAgICAgICB9ID0gaW1hZ2VEYXRhO1xuICAgICAgICBsZXQgcmVzb2x1dGlvbjtcblxuICAgICAgICBpZihyZXNvbHV0aW9uRGF0YSkge1xuICAgICAgICAgIGNvbnN0IFtyZXNvbHV0aW9uTnVtYmVyLCByZXNvbHV0aW9uVW5pdF0gPSByZXNvbHV0aW9uRGF0YS5zcGxpdCgnICcpO1xuICAgICAgICAgIGNvbnN0IHJlc29sdXRpb25WYWx1ZSA9IHJlc29sdXRpb25OdW1iZXIuc3BsaXQoJ3gnKVswXTtcbiAgICAgICAgICBjb25zdCByZXNvbHV0aW9uVW5pdFZhbHVlID0gcmVzb2x1dGlvblVuaXQgPT09ICdwaXhlbHMvaW5jaCcgPyAncHBpJyA6ICcnO1xuICAgICAgICAgIHJlc29sdXRpb24gPSBgJHtyZXNvbHV0aW9uVmFsdWV9ICR7cmVzb2x1dGlvblVuaXRWYWx1ZX1gO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc29sdmUoe1xuICAgICAgICAgIGNvbG9yLFxuICAgICAgICAgIGZpbGVTaXplOiBpbWFnZU9wdGltaXplZEJ1ZmZlci5sZW5ndGgsXG4gICAgICAgICAgZmlsZVR5cGU6IGZvcm1hdCxcbiAgICAgICAgICBoZWlnaHQ6IHNpemU/LmhlaWdodCB8fCAwLFxuICAgICAgICAgIGltYWdlSWQsXG4gICAgICAgICAgbWFrZTogY2FtZXJhTWFrZSxcbiAgICAgICAgICBtb2RlbDogY2FtZXJhTW9kZWwsXG4gICAgICAgICAgb3JpZW50YXRpb246IG9yaWVudGF0aW9uRGF0YSA9PT0gJ1Vua25vd24nID8gdW5kZWZpbmVkIDogb3JpZW50YXRpb25EYXRhPy50b0xvd2VyQ2FzZSgpLFxuICAgICAgICAgIHF1YWxpdHk6IHF1YWxpdHkgPyArcXVhbGl0eSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICByZXNvbHV0aW9uLFxuICAgICAgICAgIHRha2VuOiB0YWtlbiA/IERhdGVUaW1lLmZyb21NaWxsaXModGFrZW4pLm1pbGxpc2Vjb25kIDogdW5kZWZpbmVkLFxuICAgICAgICAgIHdpZHRoOiBzaXplPy53aWR0aCB8fCAwXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gIH0pO1xuXG4gIGNvbnN0IHRodW1iT3B0aW1pemVkQnVmZmVyOiBCdWZmZXIgPSBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgY29uc3QgdGhtVyA9IENvbmZpZy5nZXQoJ2ltYWdlLnRobVNpemUnKTtcbiAgICBjb25zdCB0aG1RID0gQ29uZmlnLmdldCgnaW1hZ2UudGhtUXVhbGl0eScpO1xuXG4gICAgZ20oaW1hZ2VPcHRpbWl6ZWRCdWZmZXIsICdpbWcnKVxuICAgICAgLnNldEZvcm1hdChmb3JtYXQpXG4gICAgICAuZ3Jhdml0eSgnQ2VudGVyJylcbiAgICAgIC5yZXNpemUodGhtVywgdGhtVywgJ14nKVxuICAgICAgLmV4dGVudCh0aG1XLCB0aG1XKVxuICAgICAgLnF1YWxpdHkodGhtUSlcbiAgICAgIC5zdHJlYW0oKHN0cmVhbUVycm9yOiBFcnJvciwgdGh1bWJTdGRvdXQpOiB2b2lkID0+IHtcbiAgICAgICAgaWYoc3RyZWFtRXJyb3IpIHtcbiAgICAgICAgICBsb2dFcnJvcih7XG4gICAgICAgICAgICBhY3Rpb24sXG4gICAgICAgICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgICAgICAgIHBhcmFtczoge2ZpbGVUeXBlLCBpbWFnZUlkfSxcbiAgICAgICAgICAgIHZhbHVlOiBFcnJvclR5cGVzLklNQUdFX1NBVkVcbiAgICAgICAgICB9LCBzdHJlYW1FcnJvciwgY29udGV4dCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHRodW1iQnVmZmVyOiBCdWZmZXIgPSBCdWZmZXIuZnJvbSgnJyk7XG5cbiAgICAgICAgdGh1bWJTdGRvdXQub24oJ2RhdGEnLCAoZGF0YSkgPT4ge1xuICAgICAgICAgIHRodW1iQnVmZmVyID0gQnVmZmVyLmNvbmNhdChbdGh1bWJCdWZmZXIsIGRhdGFdKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGh1bWJTdGRvdXQub24oJ2VuZCcsICgpID0+IHJlc29sdmUodGh1bWJCdWZmZXIpKTtcbiAgICAgIH0pO1xuICB9KTtcblxuICB0cnkge1xuICAgIGNvbnN0IHRodW1iT2JqOiBQdXRPYmplY3RDb21tYW5kSW5wdXQgPSB7XG4gICAgICBBQ0w6ICdhdXRoZW50aWNhdGVkLXJlYWQnLFxuICAgICAgQm9keTogdGh1bWJPcHRpbWl6ZWRCdWZmZXIsXG4gICAgICBCdWNrZXQ6IG51bGwsXG4gICAgICBDb250ZW50VHlwZTogZmlsZVR5cGUsXG4gICAgICAuLi4oczNPcHRpb25zIHx8IHt9KSxcbiAgICAgIEtleTogZ2V0UGF0aFVzZXJJbWFnZXMoc2Vzc2lvbklkLCBpbWFnZUlkLCBmaWxlVHlwZSwgJ3RodW1icycpXG4gICAgfTtcbiAgICBhd2FpdCBzM1B1dCh0aHVtYk9iaik7XG4gIH0gY2F0Y2goZXJyb3IpIHtcbiAgICByZXR1cm4gbG9nRXJyb3Ioe1xuICAgICAgYWN0aW9uLFxuICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICB2YWx1ZTogRXJyb3JUeXBlcy5JTUFHRV9TQVZFXG4gICAgfSwgZXJyb3IsIGNvbnRleHQpO1xuICB9XG5cbiAgcmV0dXJuIGltYWdlSWRlbnRpdHk7XG59O1xuXG5leHBvcnQgY29uc3QgYWRkSW1hZ2UgPSAoXG4gIGNvbnRleHQ6IEFwaUNvbnRleHQsXG4gIGltYWdlOiBJbWFnZVR5cGUsXG4gIHMzT3B0aW9ucz86IFB1dE9iamVjdENvbW1hbmRJbnB1dFxuKTogUHJvbWlzZTxJbWFnZVR5cGU+ID0+IHtcbiAgY29uc3QgYWN0aW9uOiBzdHJpbmcgPSAnYWRkSW1hZ2UnO1xuICBjb25zdCB7ZGF0YWJhc2VOYW1lLCBzZXNzaW9uOiB7dXNlcklkOiBzZXNzaW9uSWR9fSA9IGNvbnRleHQ7XG4gIGNvbnN0IHtpbWFnZUlkLCBkZXNjcmlwdGlvbiwgYnVmZmVyLCBmaWxlVHlwZX0gPSBpbWFnZTtcbiAgY29uc3Qgbm93OiBudW1iZXIgPSBEYXRlLm5vdygpO1xuXG4gIHJldHVybiByZXNpemVTYXZlSW1hZ2UoY29udGV4dCwgaW1hZ2VJZCwgYnVmZmVyLCBmaWxlVHlwZSwgczNPcHRpb25zKVxuICAgIC50aGVuKChyZXNpemVkSW1hZ2U6IEltYWdlVHlwZSkgPT4ge1xuICAgICAgY29uc3QgaW5zZXJ0OiBJbWFnZVR5cGUgPSB7XG4gICAgICAgIC4uLnJlc2l6ZWRJbWFnZSxcbiAgICAgICAgX2tleTogaW1hZ2VJZCxcbiAgICAgICAgYWRkZWQ6IG5vdyxcbiAgICAgICAgZGVzY3JpcHRpb24sXG4gICAgICAgIGZpbGVUeXBlLFxuICAgICAgICBtb2RpZmllZDogbm93LFxuICAgICAgICB1c2VySWQ6IHNlc3Npb25JZFxuICAgICAgfTtcblxuICAgICAgY29uc3QgYXFsUXJ5OiBBcWxRdWVyeSA9IGFxbGBJTlNFUlQgJHtpbnNlcnR9IElOIGltYWdlcyBSRVRVUk4gTkVXYDtcblxuICAgICAgcmV0dXJuIHVzZURiKGRhdGFiYXNlTmFtZSkucXVlcnkoYXFsUXJ5KVxuICAgICAgICAudGhlbigoY3Vyc29yKSA9PiBjdXJzb3IubmV4dCgpKVxuICAgICAgICAuY2F0Y2goKGVycm9yOiBFcnJvcikgPT4gbG9nRXJyb3Ioe1xuICAgICAgICAgIGFjdGlvbixcbiAgICAgICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgICAgICBwYXJhbXM6IHtpbWFnZSwgczNPcHRpb25zfSxcbiAgICAgICAgICB2YWx1ZTogRXJyb3JUeXBlcy5EQVRBQkFTRV9FUlJPUlxuICAgICAgICB9LCBlcnJvciwgY29udGV4dCkpO1xuICAgIH0pXG4gICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IGxvZ0Vycm9yKHtcbiAgICAgIGFjdGlvbixcbiAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgdmFsdWU6IEVycm9yVHlwZXMuSU1BR0VfUkVTSVpFXG4gICAgfSwgZXJyb3IsIGNvbnRleHQpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBhZGRJbWFnZUVkZ2UgPSBhc3luYyAoY29udGV4dDogQXBpQ29udGV4dCwgaW1hZ2VFZGdlOiBJbWFnZUVkZ2VUeXBlKTogUHJvbWlzZTxvYmplY3Q+ID0+IHtcbiAgY29uc3QgYWN0aW9uOiBzdHJpbmcgPSAnYWRkSW1hZ2VFZGdlJztcbiAgY29uc3Qge2RhdGFiYXNlTmFtZSwgc2Vzc2lvbjoge3VzZXJJZDogc2Vzc2lvbklkfX0gPSBjb250ZXh0O1xuICBjb25zdCB7aW1hZ2VJZCwgaXRlbUlkLCBpdGVtVHlwZX0gPSBpbWFnZUVkZ2U7XG4gIGNvbnN0IG5vdzogbnVtYmVyID0gRGF0ZS5ub3coKTtcbiAgLy8gY29uc3QgZWRnZUNvbGxlY3Rpb246IEVkZ2VDb2xsZWN0aW9uID0gdXNlRGIoZGF0YWJhc2VOYW1lKS5jb2xsZWN0aW9uKCdoYXNJbWFnZScpO1xuICBjb25zdCBlZGdlSWQ6IHN0cmluZyA9IGNyZWF0ZUhhc2goYGhhc0ltYWdlLSR7aW1hZ2VJZH0tJHtpdGVtSWR9LSR7c2Vzc2lvbklkfWApO1xuICBjb25zdCBmb3JtYXRJdGVtVHlwZTogQXJhbmdvRGJDb2xsZWN0aW9uID0gcGFyc2VDaGFyKGl0ZW1UeXBlKS50b0xvd2VyQ2FzZSgpIGFzIEFyYW5nb0RiQ29sbGVjdGlvbjtcbiAgY29uc3QgZm9ybWF0SXRlbUlkOiBzdHJpbmcgPSBwYXJzZUlkKGl0ZW1JZCk7XG4gIGNvbnN0IGl0ZW1Eb2NJZDogc3RyaW5nID0gZ2V0RG9jSWQoZm9ybWF0SXRlbVR5cGUsIHtfa2V5OiBmb3JtYXRJdGVtSWR9KTtcbiAgY29uc3QgZm9ybWF0SW1hZ2VJZDogc3RyaW5nID0gcGFyc2VJZChpbWFnZUlkKTtcbiAgY29uc3QgZmlsZURvY0lkOiBzdHJpbmcgPSBgaW1hZ2VzLyR7Zm9ybWF0SW1hZ2VJZH1gO1xuXG4gIGNvbnN0IGVkZ2U6IEltYWdlRWRnZVR5cGUgPSB7XG4gICAgX2Zyb206IGl0ZW1Eb2NJZCxcbiAgICBfa2V5OiBlZGdlSWQsXG4gICAgX3RvOiBmaWxlRG9jSWQsXG4gICAgYWRkZWQ6IG5vdyxcbiAgICBpdGVtVHlwZVxuICB9O1xuXG4gIGlmKGl0ZW1Eb2NJZCkge1xuICAgIHJldHVybiB1c2VEYihkYXRhYmFzZU5hbWUpLmNvbGxlY3Rpb24oJ2hhc0ltYWdlJykuc2F2ZShlZGdlLCB7cmV0dXJuTmV3OiB0cnVlfSlcbiAgICAgIC50aGVuKChmaWxlRWRnZSkgPT4gdXNlRGIoZGF0YWJhc2VOYW1lKS5jb2xsZWN0aW9uKCdoYXNJbWFnZScpLmRvY3VtZW50KGZpbGVFZGdlKSlcbiAgICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICAgIGFjdGlvbixcbiAgICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICAgIHBhcmFtczoge1xuICAgICAgICAgIGVkZ2UsXG4gICAgICAgICAgZmlsZURvY0lkLFxuICAgICAgICAgIGltYWdlSWQsXG4gICAgICAgICAgaXRlbURvY0lkLFxuICAgICAgICAgIGl0ZW1JZCxcbiAgICAgICAgICBpdGVtVHlwZVxuICAgICAgICB9LFxuICAgICAgICB2YWx1ZTogRXJyb3JUeXBlcy5EQVRBQkFTRV9FUlJPUlxuICAgICAgfSwgZXJyb3IsIGNvbnRleHQpKTtcbiAgfVxuXG4gIHJldHVybiBudWxsO1xufTtcblxuZXhwb3J0IGNvbnN0IHVwZGF0ZUltYWdlID0gYXN5bmMgKFxuICBjb250ZXh0OiBBcGlDb250ZXh0LFxuICBpbWFnZTogSW1hZ2VUeXBlLFxuICBzM09wdGlvbnM/OiBQdXRPYmplY3RDb21tYW5kSW5wdXRcbik6IFByb21pc2U8SW1hZ2VUeXBlPiA9PiB7XG4gIGNvbnN0IGFjdGlvbjogc3RyaW5nID0gJ3VwZGF0ZUltYWdlJztcbiAgY29uc3Qge2RhdGFiYXNlTmFtZSwgc2Vzc2lvbjoge3VzZXJJZDogc2Vzc2lvbklkfX0gPSBjb250ZXh0O1xuICBjb25zdCB7XG4gICAgYmFzZTY0ID0gJycsXG4gICAgYnVmZmVyOiBpbWFnZUJ1ZmZlcixcbiAgICBkZXNjcmlwdGlvbiA9ICcnLFxuICAgIGltYWdlSWQsXG4gICAgaXRlbUlkLFxuICAgIGl0ZW1UeXBlLFxuICAgIGZpbGVUeXBlLFxuICAgIHVybCA9ICcnXG4gIH0gPSBpbWFnZTtcblxuICBjb25zdCBub3c6IG51bWJlciA9IERhdGUubm93KCk7XG4gIGNvbnN0IGZvcm1hdEltYWdlSWQ6IHN0cmluZyA9IGltYWdlSWQgfHwgY3JlYXRlSGFzaChgaW1hZ2UtJHtzZXNzaW9uSWR9YCk7XG4gIGNvbnN0IGZvcm1hdEl0ZW1JZDogc3RyaW5nID0gcGFyc2VJZChpdGVtSWQpO1xuICBjb25zdCBmb3JtYXRJdGVtVHlwZTogQXJhbmdvRGJDb2xsZWN0aW9uID0gcGFyc2VDaGFyKGl0ZW1UeXBlLCAxNikudG9Mb3dlckNhc2UoKSBhcyBBcmFuZ29EYkNvbGxlY3Rpb247XG4gIGNvbnN0IGN1c3RvbVBhcmFtczogSW1hZ2VUeXBlID0ge1xuICAgIGRlc2NyaXB0aW9uLFxuICAgIGltYWdlSWQ6IGZvcm1hdEltYWdlSWQsXG4gICAgdXNlcklkOiBzZXNzaW9uSWRcbiAgfTtcblxuICBpZihiYXNlNjQgfHwgaW1hZ2VCdWZmZXIpIHtcbiAgICBsZXQgYnVmZmVyOiBCdWZmZXIgPSBpbWFnZUJ1ZmZlcjtcblxuICAgIGlmKGJhc2U2NCkge1xuICAgICAgY29uc3QgZm9ybWF0QmFzZTY0OiBzdHJpbmcgPSBiYXNlNjQuc3Vic3RyKGJhc2U2NC5pbmRleE9mKCcsJykgKyAxKTtcbiAgICAgIGJ1ZmZlciA9IEJ1ZmZlci5mcm9tKGZvcm1hdEJhc2U2NCwgJ2Jhc2U2NCcpO1xuICAgIH1cblxuICAgIGxldCB1cGRhdGVkRmlsZVR5cGUgPSBmaWxlVHlwZTtcblxuICAgIGlmKCFmaWxlVHlwZSkge1xuICAgICAgY29uc3Qge2ZpbGVUeXBlRnJvbUJ1ZmZlcn0gPSBhd2FpdCBpbXBvcnQoJ2ZpbGUtdHlwZScpO1xuICAgICAgY29uc3Qge21pbWV9ID0gYXdhaXQgZmlsZVR5cGVGcm9tQnVmZmVyKGJ1ZmZlcik7XG4gICAgICB1cGRhdGVkRmlsZVR5cGUgPSBtaW1lO1xuICAgIH1cblxuICAgIGNvbnN0IGltZ1BhcmFtczogSW1hZ2VUeXBlID0ge1xuICAgICAgLi4uY3VzdG9tUGFyYW1zLFxuICAgICAgYnVmZmVyLFxuICAgICAgZmlsZVR5cGU6IHVwZGF0ZWRGaWxlVHlwZVxuICAgIH07XG5cbiAgICByZXR1cm4gYWRkSW1hZ2UoY29udGV4dCwgaW1nUGFyYW1zLCBzM09wdGlvbnMpXG4gICAgICAudGhlbigoaW1hZ2U6IEltYWdlVHlwZSkgPT4ge1xuICAgICAgICBpZihmb3JtYXRJdGVtSWQgJiYgZm9ybWF0SXRlbVR5cGUpIHtcbiAgICAgICAgICBjb25zdCBpbWFnZUVkZ2U6IEltYWdlRWRnZVR5cGUgPSB7XG4gICAgICAgICAgICBpbWFnZUlkOiBmb3JtYXRJbWFnZUlkLFxuICAgICAgICAgICAgaXRlbUlkOiBmb3JtYXRJdGVtSWQsXG4gICAgICAgICAgICBpdGVtVHlwZTogZm9ybWF0SXRlbVR5cGVcbiAgICAgICAgICB9O1xuICAgICAgICAgIHJldHVybiBhZGRJbWFnZUVkZ2UoY29udGV4dCwgaW1hZ2VFZGdlKS50aGVuKCgpID0+IGltYWdlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBpbWFnZTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goKGVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICAgIGFjdGlvbixcbiAgICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICAgIHZhbHVlOiBFcnJvclR5cGVzLklNQUdFX1NBVkVcbiAgICAgIH0sIGVycm9yLCBjb250ZXh0KSk7XG4gIH0gZWxzZSBpZih1cmwgIT09ICcnKSB7XG4gICAgbGV0IGNvbnRlbnRUeXBlO1xuXG4gICAgcmV0dXJuIGh0dHBHZXQodXJsKVxuICAgICAgLnRoZW4oKHJlczogSHR0cFJlc3BvbnNlKSA9PiB7XG4gICAgICAgIGlmKHJlcy5zdGF0dXMgIT09IDIwMCkge1xuICAgICAgICAgIHJldHVybiBsb2dFeGNlcHRpb24oe1xuICAgICAgICAgICAgYWN0aW9uLFxuICAgICAgICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICAgICAgICB2YWx1ZTogRXJyb3JUeXBlcy5JTUFHRV9SRVFVRVNUXG4gICAgICAgICAgfSwgY29udGV4dCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb250ZW50VHlwZSA9IHJlcy5oZWFkZXJzLmdldCgnY29udGVudC10eXBlJyk7XG5cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgIH0pXG4gICAgICAudGhlbigocmVzKSA9PiAocmVzIGFzIEh0dHBSZXNwb25zZSkuYnVmZmVyKCkpXG4gICAgICAudGhlbigoYnVmZmVyOiBCdWZmZXIpID0+IHtcbiAgICAgICAgY29uc3QgaW1nUGFyYW1zOiBJbWFnZVR5cGUgPSB7XG4gICAgICAgICAgLi4uY3VzdG9tUGFyYW1zLFxuICAgICAgICAgIGJ1ZmZlcixcbiAgICAgICAgICBmaWxlVHlwZTogY29udGVudFR5cGVcbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4gYWRkSW1hZ2UoY29udGV4dCwgaW1nUGFyYW1zLCBzM09wdGlvbnMpXG4gICAgICAgICAgLnRoZW4oKGltYWdlOiBJbWFnZVR5cGUpID0+IHtcbiAgICAgICAgICAgIGlmKGZvcm1hdEl0ZW1JZCAmJiBmb3JtYXRJdGVtVHlwZSkge1xuICAgICAgICAgICAgICBjb25zdCBpbWFnZUVkZ2U6IEltYWdlRWRnZVR5cGUgPSB7aW1hZ2VJZDogZm9ybWF0SW1hZ2VJZCwgaXRlbUlkOiBmb3JtYXRJdGVtSWQsIGl0ZW1UeXBlOiBmb3JtYXRJdGVtVHlwZX07XG4gICAgICAgICAgICAgIHJldHVybiBhZGRJbWFnZUVkZ2UoY29udGV4dCwgaW1hZ2VFZGdlKS50aGVuKCgpID0+IGltYWdlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIGltYWdlO1xuICAgICAgICAgIH0pO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICAgIGFjdGlvbixcbiAgICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICAgIHZhbHVlOiAnZmV0Y2hfZXJyb3InXG4gICAgICB9LCBlcnJvciwgY29udGV4dCkpO1xuICB9IGVsc2UgaWYoaW1hZ2VJZCAhPT0gJycpIHtcbiAgICBjb25zdCB1cGRhdGUgPSB7XG4gICAgICBkZXNjcmlwdGlvbixcbiAgICAgIG1vZGlmaWVkOiBub3dcbiAgICB9O1xuICAgIGNvbnN0IGFxbFFyeTogQXFsUXVlcnkgPSBhcWxgVVBEQVRFIHtfa2V5OiAke2Zvcm1hdEltYWdlSWR9fSBXSVRIICR7dXBkYXRlfSBJTiBpbWFnZXMgUkVUVVJOIE5FV2A7XG5cbiAgICByZXR1cm4gdXNlRGIoZGF0YWJhc2VOYW1lKS5xdWVyeShhcWxRcnkpXG4gICAgICAudGhlbigoY3Vyc29yKSA9PiBjdXJzb3IubmV4dCgpKVxuICAgICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IGxvZ0Vycm9yKHtcbiAgICAgICAgYWN0aW9uLFxuICAgICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgICAgcGFyYW1zOiB7XG4gICAgICAgICAgYXFsUXJ5LFxuICAgICAgICAgIGZvcm1hdEltYWdlSWQsXG4gICAgICAgICAgdXBkYXRlXG4gICAgICAgIH0sXG4gICAgICAgIHZhbHVlOiBFcnJvclR5cGVzLkRBVEFCQVNFX0VSUk9SXG4gICAgICB9LCBlcnJvciwgY29udGV4dCkpO1xuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59O1xuXG5leHBvcnQgY29uc3QgZGVsZXRlSW1hZ2UgPSBhc3luYyAoY29udGV4dDogQXBpQ29udGV4dCwgaW1hZ2VJZDogc3RyaW5nKTogUHJvbWlzZTxJbWFnZVR5cGU+ID0+IHtcbiAgY29uc3QgYWN0aW9uOiBzdHJpbmcgPSAnZGVsZXRlJztcbiAgY29uc3Qge2RhdGFiYXNlTmFtZSwgc2Vzc2lvbjoge3VzZXJJZDogc2Vzc2lvbklkfX0gPSBjb250ZXh0O1xuICBjb25zdCBmb3JtYXRJbWFnZUlkID0gcGFyc2VJZChpbWFnZUlkKTtcblxuICB0cnkge1xuICAgIGNvbnN0IHJlbW92ZUVkZ2VRdWVyeSA9IGFxbGBGT1IgaGkgSU4gaGFzSW1hZ2VcbiAgICBGSUxURVIgaGkuX2Zyb20gPT0gJHtmb3JtYXRJbWFnZUlkfVxuICAgIFJFTU9WRSBoaSBJTiBoYXNJbWFnZVxuICAgIFJFVFVSTiBPTERgO1xuXG4gICAgYXdhaXQgdXNlRGIoZGF0YWJhc2VOYW1lKS5xdWVyeShyZW1vdmVFZGdlUXVlcnkpO1xuXG4gICAgY29uc3QgYXFsUXVlcnkgPSBhcWxgRk9SIGkgSU4gaW1hZ2VzXG4gICAgRklMVEVSIGkuX2tleSA9PSAke2Zvcm1hdEltYWdlSWR9ICYmIGkudXNlcklkID09ICR7c2Vzc2lvbklkfVxuICAgIFJFTU9WRSBpIElOIGltYWdlc1xuICAgIFJFVFVSTiBPTERgO1xuXG4gICAgY29uc3QgaW1hZ2UgPSBhd2FpdCB1c2VEYihkYXRhYmFzZU5hbWUpLnF1ZXJ5KGFxbFF1ZXJ5KS50aGVuKChjdXJzb3IpID0+IGN1cnNvci5uZXh0KCkpO1xuXG4gICAgaWYoaW1hZ2UpIHtcbiAgICAgIGNvbnN0IHtfa2V5OiBpbWFnZUtleX0gPSBpbWFnZTtcbiAgICAgIGNvbnN0IHBhcmFtczogRGVsZXRlT2JqZWN0c0NvbW1hbmRJbnB1dCA9IHtcbiAgICAgICAgQnVja2V0OiBudWxsLFxuICAgICAgICBEZWxldGU6IHtcbiAgICAgICAgICBPYmplY3RzOiBbXG4gICAgICAgICAgICB7S2V5OiBgdXNlcnMvJHtzZXNzaW9uSWR9L2ltYWdlcy8ke2ltYWdlS2V5fS5qcGdgfSxcbiAgICAgICAgICAgIHtLZXk6IGB1c2Vycy8ke3Nlc3Npb25JZH0vdGh1bWJzLyR7aW1hZ2VLZXl9LmpwZ2B9XG4gICAgICAgICAgXSxcbiAgICAgICAgICBRdWlldDogdHJ1ZVxuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICByZXR1cm4gczNEZWxldGVMaXN0KHBhcmFtcykudGhlbigoKSA9PiBpbWFnZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH0gY2F0Y2goZXJyb3IpIHtcbiAgICByZXR1cm4gbG9nRXJyb3Ioe1xuICAgICAgYWN0aW9uLFxuICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICBwYXJhbXM6IHtpbWFnZUlkfSxcbiAgICAgIHZhbHVlOiBFcnJvclR5cGVzLkRBVEFCQVNFX0VSUk9SXG4gICAgfSwgZXJyb3IsIGNvbnRleHQpO1xuICB9XG59O1xuIl0sIm5hbWVzIjpbImdldCIsImh0dHBHZXQiLCJwYXJzZU51bSIsImNyZWF0ZUhhc2giLCJwYXJzZUFyYW5nb0lkIiwicGFyc2VDaGFyIiwicGFyc2VJZCIsImFxbCIsImdtIiwiRGF0ZVRpbWUiLCJDb25maWciLCJFcnJvclR5cGVzIiwibG9nRXJyb3IiLCJsb2dFeGNlcHRpb24iLCJnZXREb2NJZCIsImdldExpbWl0Iiwic2VsZWN0UmVhY3Rpb25Db3VudEJ5VHlwZSIsInVzZURiIiwiZ2V0R3JvdXBEZXRhaWxzIiwiaXNHcm91cGVkIiwiczNEZWxldGVMaXN0IiwiczNHZXRTaWduZWRVcmwiLCJzM1B1dCIsImxvd2VyQ2FzZUtleXMiLCJldmVudENhdGVnb3J5Iiwic3ViQ2xhc3MiLCJpbWFnZU1hZ2ljayIsInBhcnNlSW1hZ2VPcHRpb25zIiwib3B0aW9ucyIsImZyb20iLCJ0byIsInR5cGUiLCJsaW1pdCIsImdldEltYWdlT3B0aW9uYWwiLCJmaWVsZHMiLCJyZWR1Y2UiLCJzZWxlY3RzIiwiZmllbGQiLCJpbmNsdWRlcyIsInF1ZXJpZXMiLCJwdXNoIiwib2JqZWN0cyIsImdldEltYWdlc0J5VXNlciIsImNvbnRleHQiLCJ1c2VySWQiLCJhY3Rpb24iLCJkYXRhYmFzZU5hbWUiLCJmb3JtYXRVc2VySWQiLCJhcWxRcnkiLCJxdWVyeSIsInRoZW4iLCJjdXJzb3IiLCJhbGwiLCJjYXRjaCIsImVycm9yIiwiY2F0ZWdvcnkiLCJwYXJhbXMiLCJ2YWx1ZSIsIkRBVEFCQVNFX0VSUk9SIiwiZ2V0SW1hZ2VDb3VudEJ5SXRlbSIsIml0ZW1JZCIsImZvcm1hdEl0ZW1JZCIsIm5leHQiLCJjb3VudCIsImdldEltYWdlc0J5SXRlbSIsInNlbGVjdE9iamVjdHMiLCJzZWxlY3RRdWVyaWVzIiwiam9pbiIsImdldEltYWdlc0J5R3JvdXAiLCJzZXNzaW9uIiwic2Vzc2lvbklkIiwiZmlsdGVycyIsImdyb3VwSWQiLCJmb3JtYXRHcm91cElkIiwibWFwIiwiZmlsdGVyIiwiY29uZGl0aW9uYWwiLCJuYW1lIiwiZm9ybWF0Q29uZCIsImdyb3VwIiwicHJpdmFjeSIsImZpbHRlclN0ciIsImdyb3VwZWQiLCJpc1ZhbGlkIiwiZmlsdGVyTGlzdCIsImdldEltYWdlc0J5UmVhY3Rpb25zIiwicmVhY3Rpb25zIiwiZm9ybWF0U2Vzc2lvbklkIiwiZm9ybWF0UmVhY3Rpb25zIiwicmVhY3Rpb25OYW1lIiwiZmlsdGVyQnkiLCJKU09OIiwic3RyaW5naWZ5IiwiZ2V0SW1hZ2UiLCJpbWFnZUlkIiwiZm9ybWF0SW1hZ2VJZCIsImdldFBhdGhVc2VySW1hZ2VzIiwiaW1hZ2VUeXBlIiwiZGlyIiwiZmlsZW5hbWUiLCJnZXRBcHBJbWFnZVVybCIsImJ1Y2tldCIsImRpcmVjdG9yeSIsImlzVGh1bWIiLCJ0eXBlSWQiLCJidWNrZXROYW1lIiwiaW1hZ2VOYW1lIiwiaW1hZ2VVcmwiLCJnZXRJbWFnZVVybCIsImltYWdlRGlyIiwidXJsVHlwZSIsInRodW1iU3VmZml4IiwiaW1hZ2VLZXkiLCJkZWZhdWx0QnVja2V0IiwiQnVja2V0IiwiRXhwaXJlcyIsIktleSIsInJlc2l6ZVNhdmVJbWFnZSIsImJ1ZmZlciIsImZpbGVUeXBlIiwiczNPcHRpb25zIiwiaW1nVyIsImltZ1EiLCJmb3JtYXQiLCJzcGxpdCIsImltYWdlT3B0aW1pemVkQnVmZmVyIiwiUHJvbWlzZSIsInJlc29sdmUiLCJyZWplY3QiLCJzZXRGb3JtYXQiLCJxdWFsaXR5IiwiYXV0b09yaWVudCIsInJlc2l6ZSIsInN0cmVhbSIsInN0cmVhbUVycm9yIiwic3Rkb3V0IiwiSU1BR0VfU0FWRSIsImltYWdlQnVmZmVyIiwiQnVmZmVyIiwib24iLCJkYXRhIiwiY29uY2F0IiwiaW1hZ2VPYmoiLCJBQ0wiLCJCb2R5IiwiQ29udGVudFR5cGUiLCJpbWFnZUlkZW50aXR5IiwiaWRlbnRpZnkiLCJidWZmZXJTdHJlYW0iLCJpbWFnZURhdGEiLCJmb3JtYXRWYWx1ZXMiLCJtYWtlIiwiY2FtZXJhTWFrZSIsIm1vZGVsIiwiY2FtZXJhTW9kZWwiLCJkYXRldGltZW9yaWdpbmFsIiwidGFrZW4iLCJzdGF0cyIsImNvbG9yIiwicmVkIiwiZ3JlZW4iLCJibHVlIiwibWVhbiIsInN1YnN0cmluZyIsInJnYiIsInJnYkNvbG9yIiwidG9TdHJpbmciLCJPcmllbnRhdGlvbiIsIm9yaWVudGF0aW9uRGF0YSIsIlJlc29sdXRpb24iLCJyZXNvbHV0aW9uRGF0YSIsInNpemUiLCJyZXNvbHV0aW9uIiwicmVzb2x1dGlvbk51bWJlciIsInJlc29sdXRpb25Vbml0IiwicmVzb2x1dGlvblZhbHVlIiwicmVzb2x1dGlvblVuaXRWYWx1ZSIsImZpbGVTaXplIiwibGVuZ3RoIiwiaGVpZ2h0Iiwib3JpZW50YXRpb24iLCJ1bmRlZmluZWQiLCJ0b0xvd2VyQ2FzZSIsImZyb21NaWxsaXMiLCJtaWxsaXNlY29uZCIsIndpZHRoIiwidGh1bWJPcHRpbWl6ZWRCdWZmZXIiLCJ0aG1XIiwidGhtUSIsImdyYXZpdHkiLCJleHRlbnQiLCJ0aHVtYlN0ZG91dCIsInRodW1iQnVmZmVyIiwidGh1bWJPYmoiLCJhZGRJbWFnZSIsImltYWdlIiwiZGVzY3JpcHRpb24iLCJub3ciLCJEYXRlIiwicmVzaXplZEltYWdlIiwiaW5zZXJ0IiwiX2tleSIsImFkZGVkIiwibW9kaWZpZWQiLCJJTUFHRV9SRVNJWkUiLCJhZGRJbWFnZUVkZ2UiLCJpbWFnZUVkZ2UiLCJpdGVtVHlwZSIsImVkZ2VJZCIsImZvcm1hdEl0ZW1UeXBlIiwiaXRlbURvY0lkIiwiZmlsZURvY0lkIiwiZWRnZSIsIl9mcm9tIiwiX3RvIiwiY29sbGVjdGlvbiIsInNhdmUiLCJyZXR1cm5OZXciLCJmaWxlRWRnZSIsImRvY3VtZW50IiwidXBkYXRlSW1hZ2UiLCJiYXNlNjQiLCJ1cmwiLCJjdXN0b21QYXJhbXMiLCJmb3JtYXRCYXNlNjQiLCJzdWJzdHIiLCJpbmRleE9mIiwidXBkYXRlZEZpbGVUeXBlIiwiZmlsZVR5cGVGcm9tQnVmZmVyIiwibWltZSIsImltZ1BhcmFtcyIsImNvbnRlbnRUeXBlIiwicmVzIiwic3RhdHVzIiwiSU1BR0VfUkVRVUVTVCIsImhlYWRlcnMiLCJ1cGRhdGUiLCJkZWxldGVJbWFnZSIsInJlbW92ZUVkZ2VRdWVyeSIsImFxbFF1ZXJ5IiwiRGVsZXRlIiwiT2JqZWN0cyIsIlF1aWV0Il0sIm1hcHBpbmdzIjoiQUFBQTs7O0NBR0MsR0FFRCxTQUFRQSxPQUFPQyxPQUFPLFFBQU8sb0JBQW9CO0FBQ2pELFNBQVFDLFFBQVEsUUFBTywrQkFBK0I7QUFDdEQsU0FBUUMsVUFBVSxFQUFFQyxhQUFhLEVBQUVDLFNBQVMsRUFBRUMsT0FBTyxRQUFPLCtCQUErQjtBQUMzRixTQUFRQyxHQUFHLFFBQU8sV0FBVztBQUU3QixPQUFPQyxRQUFRLEtBQUs7QUFDcEIsU0FB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