sonamu 0.8.26 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (684) hide show
  1. package/bin/cli.js +60 -13
  2. package/dist/_virtual/rolldown_runtime.js +39 -0
  3. package/dist/ai/agents/agent.d.ts +3 -3
  4. package/dist/ai/agents/agent.d.ts.map +1 -1
  5. package/dist/ai/agents/agent.js +76 -73
  6. package/dist/ai/agents/index.js +3 -3
  7. package/dist/ai/agents/types.d.ts +3 -3
  8. package/dist/ai/agents/types.d.ts.map +1 -1
  9. package/dist/ai/agents/types.js +1 -3
  10. package/dist/ai/index.js +3 -2
  11. package/dist/ai/providers/rtzr/api.js +25 -25
  12. package/dist/ai/providers/rtzr/error.js +25 -26
  13. package/dist/ai/providers/rtzr/index.js +5 -5
  14. package/dist/ai/providers/rtzr/model.d.ts +1 -1
  15. package/dist/ai/providers/rtzr/model.d.ts.map +1 -1
  16. package/dist/ai/providers/rtzr/model.js +117 -133
  17. package/dist/ai/providers/rtzr/options.d.ts.map +1 -1
  18. package/dist/ai/providers/rtzr/options.js +35 -41
  19. package/dist/ai/providers/rtzr/provider.d.ts +1 -1
  20. package/dist/ai/providers/rtzr/provider.d.ts.map +1 -1
  21. package/dist/ai/providers/rtzr/provider.js +53 -51
  22. package/dist/ai/providers/rtzr/utils.d.ts.map +1 -1
  23. package/dist/ai/providers/rtzr/utils.js +84 -84
  24. package/dist/api/base-frame.d.ts +2 -2
  25. package/dist/api/base-frame.d.ts.map +1 -1
  26. package/dist/api/base-frame.js +29 -19
  27. package/dist/api/caster.d.ts +1 -1
  28. package/dist/api/caster.d.ts.map +1 -1
  29. package/dist/api/caster.js +51 -61
  30. package/dist/api/code-converters.d.ts +4 -3
  31. package/dist/api/code-converters.d.ts.map +1 -1
  32. package/dist/api/code-converters.js +226 -249
  33. package/dist/api/config.d.ts +17 -17
  34. package/dist/api/config.d.ts.map +1 -1
  35. package/dist/api/config.js +37 -30
  36. package/dist/api/context.d.ts +10 -10
  37. package/dist/api/context.d.ts.map +1 -1
  38. package/dist/api/context.js +8 -2
  39. package/dist/api/decorators.d.ts +8 -8
  40. package/dist/api/decorators.d.ts.map +1 -1
  41. package/dist/api/decorators.js +245 -268
  42. package/dist/api/index.js +39 -7
  43. package/dist/api/secret.js +22 -15
  44. package/dist/api/sonamu.d.ts +15 -15
  45. package/dist/api/sonamu.d.ts.map +1 -1
  46. package/dist/api/sonamu.js +1012 -1131
  47. package/dist/api/validator.js +88 -79
  48. package/dist/auth/auth-generator.d.ts.map +1 -1
  49. package/dist/auth/auth-generator.js +203 -200
  50. package/dist/auth/better-auth-entities.d.ts +2 -2
  51. package/dist/auth/better-auth-entities.d.ts.map +1 -1
  52. package/dist/auth/better-auth-entities.js +369 -429
  53. package/dist/auth/index.js +21 -6
  54. package/dist/auth/knex-adapter.d.ts +2 -2
  55. package/dist/auth/knex-adapter.d.ts.map +1 -1
  56. package/dist/auth/knex-adapter.js +153 -157
  57. package/dist/auth/plugins/entity-definitions/admin.d.ts +1 -1
  58. package/dist/auth/plugins/entity-definitions/admin.d.ts.map +1 -1
  59. package/dist/auth/plugins/entity-definitions/admin.js +58 -56
  60. package/dist/auth/plugins/entity-definitions/anonymous.d.ts +1 -1
  61. package/dist/auth/plugins/entity-definitions/anonymous.d.ts.map +1 -1
  62. package/dist/auth/plugins/entity-definitions/anonymous.js +20 -20
  63. package/dist/auth/plugins/entity-definitions/api-key.d.ts +1 -1
  64. package/dist/auth/plugins/entity-definitions/api-key.d.ts.map +1 -1
  65. package/dist/auth/plugins/entity-definitions/api-key.js +185 -196
  66. package/dist/auth/plugins/entity-definitions/index.d.ts +1 -1
  67. package/dist/auth/plugins/entity-definitions/index.d.ts.map +1 -1
  68. package/dist/auth/plugins/entity-definitions/index.js +26 -29
  69. package/dist/auth/plugins/entity-definitions/jwt.d.ts +1 -1
  70. package/dist/auth/plugins/entity-definitions/jwt.d.ts.map +1 -1
  71. package/dist/auth/plugins/entity-definitions/jwt.js +62 -64
  72. package/dist/auth/plugins/entity-definitions/organization.d.ts +1 -1
  73. package/dist/auth/plugins/entity-definitions/organization.d.ts.map +1 -1
  74. package/dist/auth/plugins/entity-definitions/organization.js +362 -421
  75. package/dist/auth/plugins/entity-definitions/passkey.d.ts +1 -1
  76. package/dist/auth/plugins/entity-definitions/passkey.d.ts.map +1 -1
  77. package/dist/auth/plugins/entity-definitions/passkey.js +115 -126
  78. package/dist/auth/plugins/entity-definitions/phone-number.d.ts +1 -1
  79. package/dist/auth/plugins/entity-definitions/phone-number.d.ts.map +1 -1
  80. package/dist/auth/plugins/entity-definitions/phone-number.js +31 -40
  81. package/dist/auth/plugins/entity-definitions/sso.d.ts +1 -1
  82. package/dist/auth/plugins/entity-definitions/sso.d.ts.map +1 -1
  83. package/dist/auth/plugins/entity-definitions/sso.js +94 -107
  84. package/dist/auth/plugins/entity-definitions/two-factor.d.ts +1 -1
  85. package/dist/auth/plugins/entity-definitions/two-factor.d.ts.map +1 -1
  86. package/dist/auth/plugins/entity-definitions/two-factor.js +78 -92
  87. package/dist/auth/plugins/entity-definitions/types.d.ts +1 -1
  88. package/dist/auth/plugins/entity-definitions/types.d.ts.map +1 -1
  89. package/dist/auth/plugins/entity-definitions/types.js +1 -10
  90. package/dist/auth/plugins/entity-definitions/username.d.ts +1 -1
  91. package/dist/auth/plugins/entity-definitions/username.d.ts.map +1 -1
  92. package/dist/auth/plugins/entity-definitions/username.js +31 -40
  93. package/dist/auth/plugins/index.js +12 -3
  94. package/dist/auth/plugins/wrappers/admin.d.ts +2 -2
  95. package/dist/auth/plugins/wrappers/admin.d.ts.map +1 -1
  96. package/dist/auth/plugins/wrappers/admin.js +28 -29
  97. package/dist/auth/plugins/wrappers/anonymous.d.ts +2 -1
  98. package/dist/auth/plugins/wrappers/anonymous.d.ts.map +1 -1
  99. package/dist/auth/plugins/wrappers/anonymous.js +23 -22
  100. package/dist/auth/plugins/wrappers/api-key.d.ts +2 -1
  101. package/dist/auth/plugins/wrappers/api-key.d.ts.map +1 -1
  102. package/dist/auth/plugins/wrappers/api-key.js +39 -34
  103. package/dist/auth/plugins/wrappers/index.js +11 -11
  104. package/dist/auth/plugins/wrappers/jwt.d.ts +2 -1
  105. package/dist/auth/plugins/wrappers/jwt.d.ts.map +1 -1
  106. package/dist/auth/plugins/wrappers/jwt.js +31 -26
  107. package/dist/auth/plugins/wrappers/organization.d.ts +2 -1
  108. package/dist/auth/plugins/wrappers/organization.d.ts.map +1 -1
  109. package/dist/auth/plugins/wrappers/organization.js +65 -62
  110. package/dist/auth/plugins/wrappers/passkey.d.ts +2 -1
  111. package/dist/auth/plugins/wrappers/passkey.d.ts.map +1 -1
  112. package/dist/auth/plugins/wrappers/passkey.js +33 -28
  113. package/dist/auth/plugins/wrappers/phone-number.d.ts.map +1 -1
  114. package/dist/auth/plugins/wrappers/phone-number.js +26 -23
  115. package/dist/auth/plugins/wrappers/sso.d.ts.map +1 -1
  116. package/dist/auth/plugins/wrappers/sso.js +37 -31
  117. package/dist/auth/plugins/wrappers/two-factor.d.ts.map +1 -1
  118. package/dist/auth/plugins/wrappers/two-factor.js +31 -28
  119. package/dist/auth/plugins/wrappers/username.d.ts.map +1 -1
  120. package/dist/auth/plugins/wrappers/username.js +23 -23
  121. package/dist/bin/build-config.js +31 -31
  122. package/dist/bin/cli.js +1063 -1204
  123. package/dist/bin/fixture.d.ts.map +1 -1
  124. package/dist/bin/fixture.js +266 -259
  125. package/dist/bin/hmr-hook-register.d.ts.map +1 -1
  126. package/dist/bin/hmr-hook-register.js +19 -18
  127. package/dist/bin/test-command.d.ts.map +1 -1
  128. package/dist/bin/test-command.js +180 -177
  129. package/dist/bin/ts-loader-register.js +13 -6
  130. package/dist/bin/ts-loader-registration.d.ts.map +1 -1
  131. package/dist/bin/ts-loader-registration.js +28 -38
  132. package/dist/cache/cache-manager.d.ts +1 -1
  133. package/dist/cache/cache-manager.d.ts.map +1 -1
  134. package/dist/cache/cache-manager.js +20 -15
  135. package/dist/cache/decorator.d.ts +1 -1
  136. package/dist/cache/decorator.d.ts.map +1 -1
  137. package/dist/cache/decorator.js +84 -76
  138. package/dist/cache/drivers.js +21 -34
  139. package/dist/cache/index.js +10 -7
  140. package/dist/cache/types.d.ts +2 -2
  141. package/dist/cache/types.d.ts.map +1 -1
  142. package/dist/cache/types.js +1 -6
  143. package/dist/cache-control/cache-control.d.ts +2 -2
  144. package/dist/cache-control/cache-control.d.ts.map +1 -1
  145. package/dist/cache-control/cache-control.js +106 -122
  146. package/dist/cache-control/types.d.ts +2 -2
  147. package/dist/cache-control/types.d.ts.map +1 -1
  148. package/dist/cache-control/types.js +1 -19
  149. package/dist/compress/compress.d.ts +1 -1
  150. package/dist/compress/compress.d.ts.map +1 -1
  151. package/dist/compress/compress.js +58 -56
  152. package/dist/compress/index.js +7 -2
  153. package/dist/compress/types.js +1 -11
  154. package/dist/cone/cone-generator.d.ts +1 -1
  155. package/dist/cone/cone-generator.d.ts.map +1 -1
  156. package/dist/cone/cone-generator.js +216 -219
  157. package/dist/database/_batch_update.d.ts +1 -1
  158. package/dist/database/_batch_update.d.ts.map +1 -1
  159. package/dist/database/_batch_update.js +107 -102
  160. package/dist/database/base-model.d.ts +8 -9
  161. package/dist/database/base-model.d.ts.map +1 -1
  162. package/dist/database/base-model.js +371 -392
  163. package/dist/database/base-model.types.d.ts +5 -5
  164. package/dist/database/base-model.types.d.ts.map +1 -1
  165. package/dist/database/base-model.types.js +1 -20
  166. package/dist/database/db.d.ts +5 -2
  167. package/dist/database/db.d.ts.map +1 -1
  168. package/dist/database/db.js +185 -171
  169. package/dist/database/knex.d.ts +1 -1
  170. package/dist/database/knex.d.ts.map +1 -1
  171. package/dist/database/knex.js +48 -42
  172. package/dist/database/puri-subset.types.d.ts +6 -7
  173. package/dist/database/puri-subset.types.d.ts.map +1 -1
  174. package/dist/database/puri-subset.types.js +1 -16
  175. package/dist/database/puri-wrapper.d.ts +6 -6
  176. package/dist/database/puri-wrapper.d.ts.map +1 -1
  177. package/dist/database/puri-wrapper.js +99 -101
  178. package/dist/database/puri.d.ts +4 -5
  179. package/dist/database/puri.d.ts.map +1 -1
  180. package/dist/database/puri.js +1021 -1227
  181. package/dist/database/puri.types.d.ts +6 -6
  182. package/dist/database/puri.types.d.ts.map +1 -1
  183. package/dist/database/puri.types.js +15 -6
  184. package/dist/database/transaction-context.d.ts +2 -2
  185. package/dist/database/transaction-context.d.ts.map +1 -1
  186. package/dist/database/transaction-context.js +22 -13
  187. package/dist/database/upsert-builder.d.ts +3 -3
  188. package/dist/database/upsert-builder.d.ts.map +1 -1
  189. package/dist/database/upsert-builder.js +405 -465
  190. package/dist/dict/en.js +72 -74
  191. package/dist/dict/index.js +13 -13
  192. package/dist/dict/ko.js +72 -74
  193. package/dist/dict/rc-keys.js +150 -168
  194. package/dist/dict/sd.d.ts +3 -1
  195. package/dist/dict/sd.d.ts.map +1 -1
  196. package/dist/dict/sd.js +54 -40
  197. package/dist/dict/sonamu-dictionary.d.ts +1 -1
  198. package/dist/dict/sonamu-dictionary.d.ts.map +1 -1
  199. package/dist/dict/sonamu-dictionary.js +887 -955
  200. package/dist/dict/types.js +1 -7
  201. package/dist/dict/utils.js +26 -24
  202. package/dist/entity/entity-manager.d.ts +9 -9
  203. package/dist/entity/entity-manager.d.ts.map +1 -1
  204. package/dist/entity/entity-manager.js +226 -223
  205. package/dist/entity/entity-template-cone.d.ts +1 -1
  206. package/dist/entity/entity-template-cone.d.ts.map +1 -1
  207. package/dist/entity/entity-template-cone.js +152 -151
  208. package/dist/entity/entity.d.ts.map +1 -1
  209. package/dist/entity/entity.js +952 -1089
  210. package/dist/exceptions/error-handler.d.ts +1 -1
  211. package/dist/exceptions/error-handler.d.ts.map +1 -1
  212. package/dist/exceptions/error-handler.js +32 -27
  213. package/dist/exceptions/so-exceptions.d.ts +1 -1
  214. package/dist/exceptions/so-exceptions.d.ts.map +1 -1
  215. package/dist/exceptions/so-exceptions.js +61 -68
  216. package/dist/filter/index.js +9 -3
  217. package/dist/filter/types.js +92 -88
  218. package/dist/filter/utils.d.ts +1 -1
  219. package/dist/filter/utils.d.ts.map +1 -1
  220. package/dist/filter/utils.js +147 -161
  221. package/dist/index.js +87 -40
  222. package/dist/logger/category.d.ts.map +1 -1
  223. package/dist/logger/category.js +30 -29
  224. package/dist/logger/configure.d.ts.map +1 -1
  225. package/dist/logger/configure.js +83 -107
  226. package/dist/migration/code-generation.d.ts +2 -2
  227. package/dist/migration/code-generation.d.ts.map +1 -1
  228. package/dist/migration/code-generation.js +1385 -1578
  229. package/dist/migration/migration-set.d.ts +1 -1
  230. package/dist/migration/migration-set.d.ts.map +1 -1
  231. package/dist/migration/migration-set.js +177 -227
  232. package/dist/migration/migrator.d.ts +4 -3
  233. package/dist/migration/migrator.d.ts.map +1 -1
  234. package/dist/migration/migrator.js +340 -345
  235. package/dist/migration/postgresql-schema-reader.d.ts +2 -2
  236. package/dist/migration/postgresql-schema-reader.d.ts.map +1 -1
  237. package/dist/migration/postgresql-schema-reader.js +506 -564
  238. package/dist/migration/slack-confirm.d.ts +2 -2
  239. package/dist/migration/slack-confirm.d.ts.map +1 -1
  240. package/dist/migration/slack-confirm.js +205 -193
  241. package/dist/migration/types.d.ts +2 -2
  242. package/dist/migration/types.d.ts.map +1 -1
  243. package/dist/migration/types.js +1 -3
  244. package/dist/naite/messaging-types.d.ts +1 -0
  245. package/dist/naite/messaging-types.d.ts.map +1 -1
  246. package/dist/naite/messaging-types.js +1 -7
  247. package/dist/naite/naite-reporter.d.ts +2 -2
  248. package/dist/naite/naite-reporter.d.ts.map +1 -1
  249. package/dist/naite/naite-reporter.js +127 -120
  250. package/dist/naite/naite.d.ts +3 -2
  251. package/dist/naite/naite.d.ts.map +1 -1
  252. package/dist/naite/naite.js +266 -300
  253. package/dist/ssr/index.d.ts +2 -2
  254. package/dist/ssr/index.d.ts.map +1 -1
  255. package/dist/ssr/index.js +13 -3
  256. package/dist/ssr/registry.d.ts +1 -1
  257. package/dist/ssr/registry.d.ts.map +1 -1
  258. package/dist/ssr/registry.js +45 -37
  259. package/dist/ssr/renderer.d.ts +4 -4
  260. package/dist/ssr/renderer.d.ts.map +1 -1
  261. package/dist/ssr/renderer.js +84 -91
  262. package/dist/ssr/types.d.ts +2 -2
  263. package/dist/ssr/types.d.ts.map +1 -1
  264. package/dist/ssr/types.js +1 -3
  265. package/dist/storage/base-file.js +54 -41
  266. package/dist/storage/buffered-file.d.ts +2 -2
  267. package/dist/storage/buffered-file.d.ts.map +1 -1
  268. package/dist/storage/buffered-file.js +51 -44
  269. package/dist/storage/drivers.d.ts +2 -2
  270. package/dist/storage/drivers.d.ts.map +1 -1
  271. package/dist/storage/drivers.js +12 -7
  272. package/dist/storage/index.js +14 -7
  273. package/dist/storage/s3-driver.d.ts +2 -2
  274. package/dist/storage/s3-driver.d.ts.map +1 -1
  275. package/dist/storage/s3-driver.js +52 -48
  276. package/dist/storage/storage-manager.d.ts +2 -2
  277. package/dist/storage/storage-manager.d.ts.map +1 -1
  278. package/dist/storage/storage-manager.js +33 -25
  279. package/dist/storage/types.d.ts +2 -2
  280. package/dist/storage/types.d.ts.map +1 -1
  281. package/dist/storage/types.js +1 -5
  282. package/dist/storage/uploaded-file.d.ts +1 -1
  283. package/dist/storage/uploaded-file.d.ts.map +1 -1
  284. package/dist/storage/uploaded-file.js +45 -35
  285. package/dist/stream/index.js +7 -2
  286. package/dist/stream/sse.d.ts +2 -2
  287. package/dist/stream/sse.d.ts.map +1 -1
  288. package/dist/stream/sse.js +72 -67
  289. package/dist/syncer/api-parser.d.ts +1 -1
  290. package/dist/syncer/api-parser.d.ts.map +1 -1
  291. package/dist/syncer/api-parser.js +224 -245
  292. package/dist/syncer/checksum.d.ts +1 -1
  293. package/dist/syncer/checksum.d.ts.map +1 -1
  294. package/dist/syncer/checksum.js +86 -72
  295. package/dist/syncer/code-generator.d.ts +2 -2
  296. package/dist/syncer/code-generator.d.ts.map +1 -1
  297. package/dist/syncer/code-generator.js +154 -160
  298. package/dist/syncer/entity-operations.d.ts +1 -1
  299. package/dist/syncer/entity-operations.d.ts.map +1 -1
  300. package/dist/syncer/entity-operations.js +63 -54
  301. package/dist/syncer/file-patterns.d.ts +1 -1
  302. package/dist/syncer/file-patterns.d.ts.map +1 -1
  303. package/dist/syncer/file-patterns.js +38 -38
  304. package/dist/syncer/index.js +19 -8
  305. package/dist/syncer/module-loader.d.ts +5 -5
  306. package/dist/syncer/module-loader.d.ts.map +1 -1
  307. package/dist/syncer/module-loader.js +83 -78
  308. package/dist/syncer/syncer-actions.d.ts +2 -2
  309. package/dist/syncer/syncer-actions.d.ts.map +1 -1
  310. package/dist/syncer/syncer-actions.js +76 -91
  311. package/dist/syncer/syncer.d.ts +7 -6
  312. package/dist/syncer/syncer.d.ts.map +1 -1
  313. package/dist/syncer/syncer.js +426 -492
  314. package/dist/tasks/decorator.d.ts +3 -3
  315. package/dist/tasks/decorator.d.ts.map +1 -1
  316. package/dist/tasks/decorator.js +32 -28
  317. package/dist/tasks/step-wrapper.d.ts +1 -1
  318. package/dist/tasks/step-wrapper.d.ts.map +1 -1
  319. package/dist/tasks/step-wrapper.js +42 -41
  320. package/dist/tasks/workflow-manager.d.ts +2 -2
  321. package/dist/tasks/workflow-manager.d.ts.map +1 -1
  322. package/dist/tasks/workflow-manager.js +192 -221
  323. package/dist/template/entity-converter.d.ts +1 -1
  324. package/dist/template/entity-converter.d.ts.map +1 -1
  325. package/dist/template/entity-converter.js +103 -103
  326. package/dist/template/helpers.d.ts.map +1 -1
  327. package/dist/template/helpers.js +163 -163
  328. package/dist/template/implementations/entity.template.d.ts +1 -1
  329. package/dist/template/implementations/entity.template.d.ts.map +1 -1
  330. package/dist/template/implementations/entity.template.js +76 -85
  331. package/dist/template/implementations/entry-server.template.d.ts +1 -1
  332. package/dist/template/implementations/entry-server.template.d.ts.map +1 -1
  333. package/dist/template/implementations/entry-server.template.js +32 -27
  334. package/dist/template/implementations/generated.template.d.ts +1 -1
  335. package/dist/template/implementations/generated.template.d.ts.map +1 -1
  336. package/dist/template/implementations/generated.template.js +254 -275
  337. package/dist/template/implementations/generated_http.template.d.ts +2 -2
  338. package/dist/template/implementations/generated_http.template.d.ts.map +1 -1
  339. package/dist/template/implementations/generated_http.template.js +114 -133
  340. package/dist/template/implementations/generated_sso.template.d.ts.map +1 -1
  341. package/dist/template/implementations/generated_sso.template.js +249 -275
  342. package/dist/template/implementations/init_types.template.d.ts +1 -1
  343. package/dist/template/implementations/init_types.template.d.ts.map +1 -1
  344. package/dist/template/implementations/init_types.template.js +40 -34
  345. package/dist/template/implementations/model.template.d.ts +1 -1
  346. package/dist/template/implementations/model.template.d.ts.map +1 -1
  347. package/dist/template/implementations/model.template.js +56 -53
  348. package/dist/template/implementations/model_test.template.d.ts +1 -1
  349. package/dist/template/implementations/model_test.template.d.ts.map +1 -1
  350. package/dist/template/implementations/model_test.template.js +32 -24
  351. package/dist/template/implementations/queries.template.d.ts +1 -1
  352. package/dist/template/implementations/queries.template.d.ts.map +1 -1
  353. package/dist/template/implementations/queries.template.js +84 -89
  354. package/dist/template/implementations/sd.template.d.ts +1 -1
  355. package/dist/template/implementations/sd.template.d.ts.map +1 -1
  356. package/dist/template/implementations/sd.template.js +137 -144
  357. package/dist/template/implementations/services.template.d.ts +1 -1
  358. package/dist/template/implementations/services.template.d.ts.map +1 -1
  359. package/dist/template/implementations/services.template.js +164 -189
  360. package/dist/template/implementations/view_form.template.d.ts +1 -1
  361. package/dist/template/implementations/view_form.template.d.ts.map +1 -1
  362. package/dist/template/implementations/view_form.template.js +258 -285
  363. package/dist/template/implementations/view_id_all_select.template.d.ts +1 -1
  364. package/dist/template/implementations/view_id_all_select.template.d.ts.map +1 -1
  365. package/dist/template/implementations/view_id_all_select.template.js +31 -25
  366. package/dist/template/implementations/view_list.template.d.ts +1 -1
  367. package/dist/template/implementations/view_list.template.d.ts.map +1 -1
  368. package/dist/template/implementations/view_list.template.js +304 -355
  369. package/dist/template/implementations/view_search_input.template.d.ts +1 -1
  370. package/dist/template/implementations/view_search_input.template.d.ts.map +1 -1
  371. package/dist/template/implementations/view_search_input.template.js +31 -27
  372. package/dist/template/index.js +21 -7
  373. package/dist/template/template-manager.d.ts +1 -1
  374. package/dist/template/template-manager.d.ts.map +1 -1
  375. package/dist/template/template-manager.js +132 -123
  376. package/dist/template/template-types.js +8 -6
  377. package/dist/template/template.d.ts +2 -2
  378. package/dist/template/template.d.ts.map +1 -1
  379. package/dist/template/template.js +73 -68
  380. package/dist/template/zod-converter.d.ts.map +1 -1
  381. package/dist/template/zod-converter.js +603 -657
  382. package/dist/testing/_relation-graph.d.ts +1 -1
  383. package/dist/testing/_relation-graph.d.ts.map +1 -1
  384. package/dist/testing/_relation-graph.js +93 -88
  385. package/dist/testing/bootstrap.d.ts +22 -13
  386. package/dist/testing/bootstrap.d.ts.map +1 -1
  387. package/dist/testing/bootstrap.js +114 -114
  388. package/dist/testing/data-explorer.d.ts +3 -3
  389. package/dist/testing/data-explorer.d.ts.map +1 -1
  390. package/dist/testing/data-explorer.js +237 -265
  391. package/dist/testing/dev-test-routes.d.ts +2 -2
  392. package/dist/testing/dev-test-routes.d.ts.map +1 -1
  393. package/dist/testing/dev-test-routes.js +258 -249
  394. package/dist/testing/dev-vitest-manager.d.ts +1 -1
  395. package/dist/testing/dev-vitest-manager.d.ts.map +1 -1
  396. package/dist/testing/dev-vitest-manager.js +514 -539
  397. package/dist/testing/faker-mappings.js +422 -420
  398. package/dist/testing/fixture-generator.d.ts +3 -3
  399. package/dist/testing/fixture-generator.d.ts.map +1 -1
  400. package/dist/testing/fixture-generator.js +1216 -1346
  401. package/dist/testing/fixture-loader.js +26 -25
  402. package/dist/testing/fixture-manager.d.ts +3 -3
  403. package/dist/testing/fixture-manager.d.ts.map +1 -1
  404. package/dist/testing/fixture-manager.js +706 -776
  405. package/dist/testing/global-setup.js +53 -49
  406. package/dist/testing/index.js +19 -11
  407. package/dist/testing/naite-vitest-reporter.js +18 -13
  408. package/dist/testing/parallel-db-manager.d.ts +1 -1
  409. package/dist/testing/parallel-db-manager.d.ts.map +1 -1
  410. package/dist/testing/parallel-db-manager.js +63 -78
  411. package/dist/testing/vitest-helpers.d.ts +1 -1
  412. package/dist/testing/vitest-helpers.d.ts.map +1 -1
  413. package/dist/testing/vitest-helpers.js +37 -33
  414. package/dist/types/types.d.ts +28 -28
  415. package/dist/types/types.d.ts.map +1 -1
  416. package/dist/types/types.js +764 -890
  417. package/dist/ui/ai-api.d.ts +1 -1
  418. package/dist/ui/ai-api.d.ts.map +1 -1
  419. package/dist/ui/ai-api.js +52 -42
  420. package/dist/ui/ai-client.d.ts +1 -2
  421. package/dist/ui/ai-client.d.ts.map +1 -1
  422. package/dist/ui/ai-client.js +353 -388
  423. package/dist/ui/api.d.ts +1 -1
  424. package/dist/ui/api.d.ts.map +1 -1
  425. package/dist/ui/api.js +903 -1145
  426. package/dist/ui/cdd-service.d.ts +1 -1
  427. package/dist/ui/cdd-service.d.ts.map +1 -1
  428. package/dist/ui/cdd-service.js +406 -407
  429. package/dist/ui/cdd-types.js +1 -3
  430. package/dist/ui-web/assets/index-C-Zz-wYg.css +1 -0
  431. package/dist/ui-web/assets/index-DejDON8K.js +238 -0
  432. package/dist/ui-web/index.html +3 -3
  433. package/dist/utils/async-utils.js +57 -45
  434. package/dist/utils/console-util.d.ts.map +1 -1
  435. package/dist/utils/console-util.js +104 -87
  436. package/dist/utils/controller.js +26 -19
  437. package/dist/utils/esm-utils.js +49 -38
  438. package/dist/utils/formatter.d.ts +1 -2
  439. package/dist/utils/formatter.d.ts.map +1 -1
  440. package/dist/utils/formatter.js +89 -115
  441. package/dist/utils/fs-utils.d.ts.map +1 -1
  442. package/dist/utils/fs-utils.js +68 -65
  443. package/dist/utils/lodash-able.js +11 -4
  444. package/dist/utils/model.d.ts +1 -1
  445. package/dist/utils/model.d.ts.map +1 -1
  446. package/dist/utils/model.js +21 -19
  447. package/dist/utils/object-utils.js +148 -186
  448. package/dist/utils/path-utils.js +67 -57
  449. package/dist/utils/process-utils.d.ts.map +1 -1
  450. package/dist/utils/process-utils.js +37 -31
  451. package/dist/utils/sql-parser.d.ts +1 -1
  452. package/dist/utils/sql-parser.d.ts.map +1 -1
  453. package/dist/utils/sql-parser.js +40 -40
  454. package/dist/utils/type-utils.js +44 -43
  455. package/dist/utils/utils.d.ts +2 -3
  456. package/dist/utils/utils.d.ts.map +1 -1
  457. package/dist/utils/utils.js +81 -93
  458. package/dist/utils/zod-error.d.ts +1 -1
  459. package/dist/utils/zod-error.d.ts.map +1 -1
  460. package/dist/utils/zod-error.js +24 -17
  461. package/dist/vector/chunking.d.ts +1 -1
  462. package/dist/vector/chunking.d.ts.map +1 -1
  463. package/dist/vector/chunking.js +100 -94
  464. package/dist/vector/config.d.ts +1 -1
  465. package/dist/vector/config.d.ts.map +1 -1
  466. package/dist/vector/config.js +76 -78
  467. package/dist/vector/embedding.d.ts +1 -1
  468. package/dist/vector/embedding.d.ts.map +1 -1
  469. package/dist/vector/embedding.js +128 -125
  470. package/dist/vector/index.js +5 -5
  471. package/dist/vector/types.js +1 -5
  472. package/package.json +31 -36
  473. package/src/ai/agents/agent.ts +12 -5
  474. package/src/ai/agents/types.ts +5 -5
  475. package/src/ai/providers/rtzr/model.ts +8 -10
  476. package/src/ai/providers/rtzr/options.ts +2 -1
  477. package/src/ai/providers/rtzr/provider.ts +5 -3
  478. package/src/ai/providers/rtzr/utils.ts +2 -7
  479. package/src/api/__tests__/config.test.ts +15 -8
  480. package/src/api/base-frame.ts +5 -3
  481. package/src/api/caster.ts +7 -6
  482. package/src/api/code-converters.ts +23 -26
  483. package/src/api/config.ts +23 -17
  484. package/src/api/context.ts +18 -11
  485. package/src/api/decorators.ts +17 -18
  486. package/src/api/sonamu.ts +44 -49
  487. package/src/auth/auth-generator.ts +4 -6
  488. package/src/auth/better-auth-entities.ts +3 -2
  489. package/src/auth/knex-adapter.ts +6 -5
  490. package/src/auth/plugins/entity-definitions/admin.ts +1 -1
  491. package/src/auth/plugins/entity-definitions/anonymous.ts +1 -1
  492. package/src/auth/plugins/entity-definitions/api-key.ts +1 -1
  493. package/src/auth/plugins/entity-definitions/index.ts +1 -1
  494. package/src/auth/plugins/entity-definitions/jwt.ts +1 -1
  495. package/src/auth/plugins/entity-definitions/organization.ts +1 -1
  496. package/src/auth/plugins/entity-definitions/passkey.ts +1 -1
  497. package/src/auth/plugins/entity-definitions/phone-number.ts +1 -1
  498. package/src/auth/plugins/entity-definitions/sso.ts +1 -1
  499. package/src/auth/plugins/entity-definitions/two-factor.ts +1 -1
  500. package/src/auth/plugins/entity-definitions/types.ts +1 -1
  501. package/src/auth/plugins/entity-definitions/username.ts +1 -1
  502. package/src/auth/plugins/wrappers/admin.ts +3 -1
  503. package/src/auth/plugins/wrappers/anonymous.ts +3 -1
  504. package/src/auth/plugins/wrappers/api-key.ts +3 -1
  505. package/src/auth/plugins/wrappers/jwt.ts +3 -1
  506. package/src/auth/plugins/wrappers/organization.ts +3 -1
  507. package/src/auth/plugins/wrappers/passkey.ts +3 -1
  508. package/src/auth/plugins/wrappers/phone-number.ts +3 -1
  509. package/src/auth/plugins/wrappers/sso.ts +2 -1
  510. package/src/auth/plugins/wrappers/two-factor.ts +3 -1
  511. package/src/auth/plugins/wrappers/username.ts +3 -1
  512. package/src/bin/__tests__/ts-loader-register.test.ts +7 -12
  513. package/src/bin/build-config.ts +3 -3
  514. package/src/bin/cli.ts +27 -25
  515. package/src/bin/fixture.ts +4 -2
  516. package/src/bin/hmr-hook-register.ts +1 -0
  517. package/src/bin/test-command.ts +4 -2
  518. package/src/bin/ts-loader-registration.ts +6 -22
  519. package/src/cache/cache-manager.ts +2 -1
  520. package/src/cache/decorator.ts +2 -2
  521. package/src/cache/types.ts +3 -3
  522. package/src/cache-control/cache-control.ts +3 -2
  523. package/src/cache-control/types.ts +2 -2
  524. package/src/compress/compress.ts +1 -1
  525. package/src/cone/cone-generator.ts +5 -3
  526. package/src/database/_batch_update.ts +1 -1
  527. package/src/database/base-model.ts +20 -14
  528. package/src/database/base-model.types.ts +12 -11
  529. package/src/database/db.ts +56 -21
  530. package/src/database/knex.ts +2 -2
  531. package/src/database/puri-subset.test-d.ts +33 -32
  532. package/src/database/puri-subset.types.ts +6 -7
  533. package/src/database/puri-wrapper.ts +29 -26
  534. package/src/database/puri.ts +36 -34
  535. package/src/database/puri.types.test-d.ts +6 -5
  536. package/src/database/puri.types.ts +9 -12
  537. package/src/database/transaction-context.ts +2 -2
  538. package/src/database/upsert-builder.ts +17 -10
  539. package/src/dict/sd.ts +17 -4
  540. package/src/dict/sonamu-dictionary.ts +23 -17
  541. package/src/entity/entity-manager.ts +9 -7
  542. package/src/entity/entity-template-cone.ts +10 -3
  543. package/src/entity/entity.ts +20 -16
  544. package/src/exceptions/error-handler.ts +2 -1
  545. package/src/exceptions/so-exceptions.ts +1 -1
  546. package/src/filter/utils.ts +3 -2
  547. package/src/logger/category.ts +1 -0
  548. package/src/logger/configure.ts +5 -5
  549. package/src/migration/__tests__/code-generation.search-text.test.ts +2 -3
  550. package/src/migration/code-generation.ts +26 -25
  551. package/src/migration/migration-set.ts +16 -18
  552. package/src/migration/migrator.ts +38 -33
  553. package/src/migration/postgresql-schema-reader.ts +12 -12
  554. package/src/migration/slack-confirm.ts +5 -4
  555. package/src/migration/types.ts +2 -2
  556. package/src/naite/messaging-types.ts +1 -1
  557. package/src/naite/naite-reporter.ts +5 -3
  558. package/src/naite/naite.ts +12 -7
  559. package/src/shared/app.shared.ts.txt +2 -2
  560. package/src/shared/web.shared.ts.txt +2 -2
  561. package/src/skills/AGENTS.md +19 -18
  562. package/src/skills/commands/sonamu-skills.md +9 -9
  563. package/src/skills/sonamu/SKILL.md +111 -104
  564. package/src/skills/sonamu/ai-agents.md +27 -26
  565. package/src/skills/sonamu/api.md +81 -69
  566. package/src/skills/sonamu/auth-migration.md +13 -27
  567. package/src/skills/sonamu/auth-plugins.md +41 -31
  568. package/src/skills/sonamu/auth.md +30 -24
  569. package/src/skills/sonamu/cdd.md +26 -17
  570. package/src/skills/sonamu/cone.md +50 -50
  571. package/src/skills/sonamu/config.md +74 -51
  572. package/src/skills/sonamu/create-sonamu.md +31 -19
  573. package/src/skills/sonamu/database.md +43 -26
  574. package/src/skills/sonamu/entity-basic.md +61 -61
  575. package/src/skills/sonamu/entity-relations.md +84 -80
  576. package/src/skills/sonamu/entity-validation-checklist.md +19 -15
  577. package/src/skills/sonamu/fixture-cli.md +52 -30
  578. package/src/skills/sonamu/framework-change.md +9 -7
  579. package/src/skills/sonamu/frontend.md +64 -82
  580. package/src/skills/sonamu/i18n.md +45 -37
  581. package/src/skills/sonamu/migration.md +54 -31
  582. package/src/skills/sonamu/model.md +98 -66
  583. package/src/skills/sonamu/naite.md +34 -32
  584. package/src/skills/sonamu/project-init.md +28 -8
  585. package/src/skills/sonamu/puri.md +82 -91
  586. package/src/skills/sonamu/scaffolding.md +44 -32
  587. package/src/skills/sonamu/skill-contribution.md +50 -45
  588. package/src/skills/sonamu/subset.md +13 -13
  589. package/src/skills/sonamu/tasks.md +73 -58
  590. package/src/skills/sonamu/testing-devrunner.md +56 -36
  591. package/src/skills/sonamu/testing.md +23 -58
  592. package/src/skills/sonamu/upsert.md +32 -31
  593. package/src/skills/sonamu/vector.md +37 -36
  594. package/src/ssr/index.ts +2 -12
  595. package/src/ssr/registry.ts +1 -1
  596. package/src/ssr/renderer.ts +7 -5
  597. package/src/ssr/types.ts +2 -2
  598. package/src/storage/buffered-file.ts +4 -2
  599. package/src/storage/drivers.ts +3 -2
  600. package/src/storage/s3-driver.ts +7 -4
  601. package/src/storage/storage-manager.ts +3 -2
  602. package/src/storage/types.ts +3 -2
  603. package/src/storage/uploaded-file.ts +1 -1
  604. package/src/stream/sse.ts +2 -2
  605. package/src/syncer/api-parser.ts +8 -5
  606. package/src/syncer/checksum.ts +9 -5
  607. package/src/syncer/code-generator.ts +16 -8
  608. package/src/syncer/entity-operations.ts +5 -3
  609. package/src/syncer/file-patterns.ts +2 -1
  610. package/src/syncer/module-loader.ts +9 -6
  611. package/src/syncer/syncer-actions.ts +5 -3
  612. package/src/syncer/syncer.ts +18 -24
  613. package/src/tasks/decorator.ts +10 -8
  614. package/src/tasks/step-wrapper.ts +1 -1
  615. package/src/tasks/workflow-manager.ts +18 -15
  616. package/src/template/__tests__/generated.template.search-text.test.ts +1 -0
  617. package/src/template/entity-converter.ts +4 -2
  618. package/src/template/generated.template.test-d.ts +2 -1
  619. package/src/template/helpers.ts +5 -2
  620. package/src/template/implementations/entity.template.ts +9 -8
  621. package/src/template/implementations/entry-server.template.ts +1 -1
  622. package/src/template/implementations/generated.template.ts +21 -29
  623. package/src/template/implementations/generated_http.template.ts +9 -6
  624. package/src/template/implementations/generated_sso.template.ts +6 -4
  625. package/src/template/implementations/init_types.template.ts +3 -2
  626. package/src/template/implementations/model.template.ts +4 -2
  627. package/src/template/implementations/model_test.template.ts +3 -2
  628. package/src/template/implementations/queries.template.ts +6 -14
  629. package/src/template/implementations/sd.template.ts +4 -2
  630. package/src/template/implementations/services.template.ts +7 -11
  631. package/src/template/implementations/view_form.template.ts +5 -3
  632. package/src/template/implementations/view_id_all_select.template.ts +3 -2
  633. package/src/template/implementations/view_list.template.ts +7 -5
  634. package/src/template/implementations/view_search_input.template.ts +3 -2
  635. package/src/template/template-manager.ts +4 -3
  636. package/src/template/template.ts +4 -3
  637. package/src/template/zod-converter.ts +10 -7
  638. package/src/testing/__tests__/dev-test-routes.test.ts +3 -2
  639. package/src/testing/__tests__/dev-vitest-manager.test.ts +1 -0
  640. package/src/testing/_relation-graph.ts +2 -2
  641. package/src/testing/bootstrap.ts +55 -27
  642. package/src/testing/data-explorer.ts +5 -4
  643. package/src/testing/dev-test-routes.ts +8 -5
  644. package/src/testing/dev-vitest-manager.ts +13 -12
  645. package/src/testing/fixture-generator.ts +11 -17
  646. package/src/testing/fixture-manager.ts +21 -17
  647. package/src/testing/parallel-db-manager.ts +2 -1
  648. package/src/testing/vitest-helpers.ts +2 -1
  649. package/src/types/__tests__/entity-json-schema-search-text.test.ts +1 -0
  650. package/src/types/types.ts +8 -8
  651. package/src/typings/knex.d.ts +4 -4
  652. package/src/ui/ai-api.ts +5 -3
  653. package/src/ui/ai-client.ts +6 -5
  654. package/src/ui/api.ts +25 -23
  655. package/src/ui/cdd-service.ts +12 -11
  656. package/src/utils/console-util.ts +3 -1
  657. package/src/utils/formatter.ts +94 -102
  658. package/src/utils/fs-utils.ts +2 -1
  659. package/src/utils/model.ts +2 -2
  660. package/src/utils/object-utils.ts +3 -3
  661. package/src/utils/process-utils.ts +2 -1
  662. package/src/utils/sql-parser.ts +10 -1
  663. package/src/utils/type-utils.ts +3 -3
  664. package/src/utils/utils.ts +9 -7
  665. package/src/utils/zod-error.ts +1 -1
  666. package/src/vector/chunking.ts +1 -1
  667. package/src/vector/config.ts +1 -1
  668. package/src/vector/embedding.ts +11 -9
  669. package/tsdown.api.config.ts +50 -0
  670. package/.swcrc.project-default +0 -18
  671. package/dist/api/__tests__/config.test.js +0 -189
  672. package/dist/bin/__tests__/test-command.test.js +0 -112
  673. package/dist/bin/__tests__/ts-loader-register.test.js +0 -45
  674. package/dist/database/puri-subset.test-d.js +0 -89
  675. package/dist/database/puri.types.test-d.js +0 -129
  676. package/dist/migration/__tests__/code-generation.search-text.test.js +0 -435
  677. package/dist/template/__tests__/generated.template.search-text.test.js +0 -99
  678. package/dist/template/generated.template.test-d.js +0 -24
  679. package/dist/testing/__tests__/dev-test-routes.test.js +0 -144
  680. package/dist/testing/__tests__/dev-vitest-manager.test.js +0 -152
  681. package/dist/types/__tests__/entity-json-schema-search-text.test.js +0 -256
  682. package/dist/typings/knex.d.js +0 -3
  683. package/dist/ui-web/assets/index-CKo0Z2Iu.css +0 -1
  684. package/dist/ui-web/assets/index-DK-2aacv.js +0 -257
package/dist/ui/api.js CHANGED
@@ -1,1149 +1,907 @@
1
- import { execSync } from "child_process";
2
- import fs from "fs";
1
+ import { __esmMin } from "../_virtual/rolldown_runtime.js";
2
+ import { createKnexInstance, init_knex } from "../database/knex.js";
3
+ import { DB, init_db } from "../database/db.js";
4
+ import { SD, init_sd } from "../dict/sd.js";
5
+ import { BadRequestException, ServiceUnavailableException, init_so_exceptions, isSoException } from "../exceptions/so-exceptions.js";
6
+ import { init_utils, nonNullable } from "../utils/utils.js";
7
+ import { Sonamu, init_sonamu } from "../api/sonamu.js";
8
+ import { BUILT_IN_TYPE_IDS, TemplateKey, init_types } from "../types/types.js";
9
+ import { EntityManager, init_entity_manager } from "../entity/entity-manager.js";
10
+ import { Migrator, init_migrator } from "../migration/migrator.js";
11
+ import { FixtureManager, init_fixture_manager } from "../testing/fixture-manager.js";
12
+ import { DataExplorer, init_data_explorer } from "../testing/data-explorer.js";
13
+ import { FixtureGenerator, init_fixture_generator } from "../testing/fixture-generator.js";
14
+ import { init_sonamu_dictionary, sonamuDictionary } from "../dict/sonamu-dictionary.js";
15
+ import { TemplateManager, init_template_manager } from "../template/template-manager.js";
16
+ import { SlackConfirm, init_slack_confirm } from "../migration/slack-confirm.js";
17
+ import { init_ai_api, setAiApi } from "./ai-api.js";
18
+ import { addRule, editContent, getAcList, getCddTree, init_cdd_service, listRules, openSourceFile, readContent, readRule } from "./cdd-service.js";
3
19
  import inflection from "inflection";
4
- import path from "path";
5
20
  import { range } from "radashi";
6
- import { Sonamu } from "../api/sonamu.js";
7
- import { DB } from "../database/db.js";
8
- import { createKnexInstance } from "../database/knex.js";
9
- import { SD } from "../dict/sd.js";
10
- import { sonamuDictionary } from "../dict/sonamu-dictionary.js";
11
- import { EntityManager } from "../entity/entity-manager.js";
12
- import { BadRequestException, isSoException, ServiceUnavailableException } from "../exceptions/so-exceptions.js";
13
- import { Migrator } from "../migration/migrator.js";
14
- import { SlackConfirm } from "../migration/slack-confirm.js";
15
- import { TemplateManager } from "../template/template-manager.js";
16
- import { DataExplorer } from "../testing/data-explorer.js";
17
- import { FixtureGenerator } from "../testing/fixture-generator.js";
18
- import { FixtureManager } from "../testing/fixture-manager.js";
19
- import { BUILT_IN_TYPE_IDS, TemplateKey } from "../types/types.js";
20
- import { nonNullable } from "../utils/utils.js";
21
- import { setAiApi } from "./ai-api.js";
22
- import { addRule, editContent, getAcList, getCddTree, listRules, openSourceFile, readContent, readRule } from "./cdd-service.js";
23
- export async function sonamuUIApiPlugin(fastify) {
24
- fastify.register(async (server)=>{
25
- // migrator
26
- const migrator = new Migrator();
27
- // waitForHMRCompleted
28
- async function waitForHMRCompleted(fn) {
29
- const waitPromise = new Promise((resolve)=>{
30
- const handler = ()=>{
31
- clearTimeout(timeout);
32
- resolve();
33
- };
34
- const timeout = setTimeout(()=>{
35
- Sonamu.syncer.eventEmitter.off("onHMRCompleted", handler);
36
- resolve();
37
- }, 1500);
38
- Sonamu.syncer.eventEmitter.once("onHMRCompleted", handler);
39
- });
40
- const result = await fn();
41
- await waitPromise;
42
- return result;
43
- }
44
- await setAiApi(server);
45
- server.get("/api/sonamu/config", async ()=>{
46
- return Sonamu.config;
47
- });
48
- server.get("/api/tools/openVscode", async (request)=>{
49
- const { entityId, preset, absPath } = request.query;
50
- const targetPath = (()=>{
51
- if (entityId && preset) {
52
- const entity = EntityManager.get(entityId);
53
- const { names } = entity;
54
- const { apiRootPath } = Sonamu;
55
- const filename = (()=>{
56
- switch(preset){
57
- case "types":
58
- return `${names.fs}.types.ts`;
59
- case "entity.json":
60
- return `${names.fs}.entity.json`;
61
- case "generated":
62
- return `${names.fs}.generated.ts`;
63
- }
64
- })();
65
- return `${apiRootPath}/src/application/${entity.names.parentFs}/${filename}`;
66
- } else {
67
- if (!absPath) {
68
- throw new BadRequestException(SD("sonamu.error.presetOrAbsPathRequired"));
69
- }
70
- return absPath;
71
- }
72
- })();
73
- execSync(`code ${targetPath}`);
74
- });
75
- server.get("/api/tools/getSuggestion", async (request)=>{
76
- const { origin, entityId } = request.query;
77
- // 치환 용어집
78
- const glossary = new Map([
79
- [
80
- "status",
81
- "상태"
82
- ],
83
- [
84
- "type",
85
- "타입"
86
- ],
87
- [
88
- "image",
89
- "이미지"
90
- ],
91
- [
92
- "images",
93
- "이미지리스트"
94
- ],
95
- [
96
- "url",
97
- "URL"
98
- ],
99
- [
100
- "id",
101
- "ID"
102
- ],
103
- [
104
- "name",
105
- `{EntityID}명`
106
- ],
107
- [
108
- "title",
109
- "{EntityID}명"
110
- ],
111
- [
112
- "parent",
113
- "상위{EntityID}"
114
- ],
115
- [
116
- "desc",
117
- "설명"
118
- ],
119
- [
120
- "at",
121
- "일시"
122
- ],
123
- [
124
- "created",
125
- "등록"
126
- ],
127
- [
128
- "updated",
129
- "수정"
130
- ],
131
- [
132
- "deleted",
133
- "삭제"
134
- ],
135
- [
136
- "by",
137
- "유저"
138
- ],
139
- [
140
- "date",
141
- "일자"
142
- ],
143
- [
144
- "time",
145
- "시간"
146
- ],
147
- [
148
- "ko",
149
- "(한글)"
150
- ],
151
- [
152
- "en",
153
- "(영문)"
154
- ],
155
- [
156
- "krw",
157
- "(원)"
158
- ],
159
- [
160
- "usd",
161
- "(USD)"
162
- ],
163
- [
164
- "color",
165
- "컬러"
166
- ],
167
- [
168
- "code",
169
- "코드"
170
- ],
171
- [
172
- "x",
173
- "X좌표"
174
- ],
175
- [
176
- "y",
177
- "Y좌표"
178
- ],
179
- [
180
- "current",
181
- "현재"
182
- ],
183
- [
184
- "stock",
185
- "재고"
186
- ],
187
- [
188
- "total",
189
- "총"
190
- ],
191
- [
192
- "admin",
193
- "관리자"
194
- ],
195
- [
196
- "group",
197
- "그룹"
198
- ],
199
- [
200
- "item",
201
- "아이템"
202
- ],
203
- [
204
- "cnt",
205
- "수량"
206
- ],
207
- [
208
- "price",
209
- "가격"
210
- ],
211
- [
212
- "preset",
213
- "프리셋"
214
- ],
215
- [
216
- "acct",
217
- "계좌"
218
- ],
219
- [
220
- "tel",
221
- "전화번호"
222
- ],
223
- [
224
- "no",
225
- "번호"
226
- ],
227
- [
228
- "body",
229
- "내용"
230
- ],
231
- [
232
- "content",
233
- "내용"
234
- ],
235
- [
236
- "orderno",
237
- "정렬순서"
238
- ],
239
- [
240
- "priority",
241
- "우선순위"
242
- ],
243
- [
244
- "text",
245
- "텍스트"
246
- ],
247
- [
248
- "key",
249
- "키"
250
- ],
251
- [
252
- "sum",
253
- "합산"
254
- ],
255
- [
256
- "expected",
257
- "예상"
258
- ],
259
- [
260
- "actual",
261
- "실제"
262
- ]
263
- ]);
264
- // 전체 엔티티 순회하며, 엔티티 타이틀과 프롭 설명을 치환 용어집에 추가
265
- for (const entityId of EntityManager.getAllIds()){
266
- const entity = EntityManager.get(entityId);
267
- if ((entity.title ?? "") !== "") {
268
- glossary.set(inflection.underscore(entity.id), entity.title);
269
- glossary.set(inflection.underscore(inflection.pluralize(entity.id)), `${entity.title}리스트`);
270
- }
271
- entity.props.forEach((prop)=>{
272
- if (glossary.has(prop.name)) {
273
- return;
274
- }
275
- if (prop.desc) {
276
- glossary.set(prop.name, prop.desc.replace(entity.title ?? "", "{EntityID}"));
277
- }
278
- });
279
- }
280
- const suggested = (()=>{
281
- // 단어 분리, 가능한 조합 생성
282
- const words = origin.split("_");
283
- const combinations = [
284
- ...range(words.length, 0, -1)
285
- ].flatMap((len)=>{
286
- return [
287
- ...range(0, words.length - len + 1, (idx)=>{
288
- return {
289
- len,
290
- w: words.slice(idx, idx + len).join("_")
291
- };
292
- })
293
- ];
294
- });
295
- // 조합을 순회하며, 치환 용어집에 있는 단어가 포함된 경우, 치환 용어로 치환
296
- const REPLACED_PREFIX = "#REPLACED//"; // 치환된 단어를 join 이후에도 식별하기 위해 prefix 추가
297
- let remainArr = [
298
- ...words
299
- ];
300
- for (const comb of combinations){
301
- const remainStr = remainArr.join("_");
302
- if (remainStr.includes(comb.w) && glossary.has(comb.w)) {
303
- remainArr = remainStr.replace(comb.w, REPLACED_PREFIX + glossary.get(comb.w)).split("_");
304
- }
305
- }
306
- return remainArr.map((r)=>{
307
- if (r.startsWith(REPLACED_PREFIX)) {
308
- return r.replace(REPLACED_PREFIX, "");
309
- } else {
310
- return r.toUpperCase();
311
- }
312
- }).join("").replace(/{EntityID}/g, entityId ? EntityManager.get(entityId).title : "");
313
- })();
314
- return {
315
- suggested
316
- };
317
- });
318
- server.get("/api/entity/findMany", async ()=>{
319
- const entityIds = EntityManager.getAllIds();
320
- function flattenSubsetRows(subsetRows) {
321
- return subsetRows.flatMap((subsetRow)=>{
322
- const { children, ...sRow } = subsetRow;
323
- return [
324
- sRow,
325
- ...flattenSubsetRows(children)
326
- ];
327
- });
328
- }
329
- const entities = await Promise.all(entityIds.map((entityId)=>{
330
- const entity = EntityManager.get(entityId);
331
- const subsetRows = entity.getSubsetRows();
332
- return {
333
- ...entity,
334
- flattenSubsetRows: flattenSubsetRows(subsetRows)
335
- };
336
- }));
337
- entities.sort((a, b)=>{
338
- const aId = a.parentId ?? a.id;
339
- const bId = b.parentId ?? b.id;
340
- if (aId < bId) return -1;
341
- if (aId > bId) return 1;
342
- if (aId === bId) {
343
- if (a.parentId === undefined) return -1;
344
- if (b.parentId === undefined) return 1;
345
- return 0;
346
- }
347
- return 0;
348
- });
349
- return {
350
- entities
351
- };
352
- });
353
- server.get("/api/entity/typeIds", async (request)=>{
354
- const { filter, reload } = request.query;
355
- if (reload === "1") {
356
- await Sonamu.syncer.autoloadTypes();
357
- }
358
- const typeIds = (()=>{
359
- // 프로젝트에서 정의한 타입들
360
- const projectTypeIds = Object.entries(Sonamu.syncer.types).filter(([_typeId, zodType])=>zodType._zod.def.type !== "enum").map(([typeId, _zodType])=>typeId);
361
- // 내장 타입들 (sonamu 코어에서 제공)
362
- const builtInTypeIds = [
363
- ...BUILT_IN_TYPE_IDS
364
- ];
365
- // 모든 타입 병합
366
- const allTypeIds = [
367
- ...builtInTypeIds,
368
- ...projectTypeIds
369
- ];
370
- if (filter === "types") {
371
- return allTypeIds;
372
- }
373
- const enumIds = EntityManager.getAllIds().flatMap((entityId)=>{
374
- const entity = EntityManager.get(entityId);
375
- return Object.keys(entity.enumLabels);
376
- });
377
- if (filter === "enums") {
378
- return enumIds;
379
- } else {
380
- return [
381
- ...allTypeIds,
382
- ...enumIds
383
- ];
384
- }
385
- })();
386
- return {
387
- typeIds
388
- };
389
- });
390
- server.post("/api/entity/create", async (request)=>{
391
- return await waitForHMRCompleted(async ()=>{
392
- const { form } = request.body;
393
- await Sonamu.syncer.createEntity({
394
- ...form,
395
- entityId: form.id
396
- });
397
- return 1;
398
- });
399
- });
400
- server.post("/api/entity/del", async (request)=>{
401
- return await waitForHMRCompleted(async ()=>{
402
- const { entityId } = request.body;
403
- return await Sonamu.syncer.delEntity(entityId);
404
- });
405
- });
406
- server.post("/api/entity/modifyEntityBase", async (request)=>{
407
- return await waitForHMRCompleted(async ()=>{
408
- const { entityId, newValues } = request.body;
409
- const entity = EntityManager.get(entityId);
410
- entity.title = newValues.title;
411
- entity.table = newValues.table;
412
- entity.parentId = newValues.parentId;
413
- await entity.save();
414
- return 1;
415
- });
416
- });
417
- server.post("/api/entity/modifySubset", async (request)=>{
418
- return await waitForHMRCompleted(async ()=>{
419
- const { entityId, subsetKey, fields, fieldsInternal } = request.body;
420
- const entity = EntityManager.get(entityId);
421
- entity.subsets[subsetKey] = fields;
422
- if (fieldsInternal !== undefined) {
423
- if (fieldsInternal.length > 0) {
424
- entity.subsetsInternal[subsetKey] = fieldsInternal;
425
- } else {
426
- delete entity.subsetsInternal[subsetKey];
427
- }
428
- }
429
- await entity.save();
430
- return {
431
- updated: fields,
432
- updatedInternal: fieldsInternal
433
- };
434
- });
435
- });
436
- server.post("/api/entity/delSubset", async (request)=>{
437
- return await waitForHMRCompleted(async ()=>{
438
- const { entityId, subsetKey } = request.body;
439
- const entity = EntityManager.get(entityId);
440
- delete entity.subsets[subsetKey];
441
- delete entity.subsetsInternal[subsetKey];
442
- await entity.save();
443
- return 1;
444
- });
445
- });
446
- server.post("/api/entity/createProp", async (request)=>{
447
- return await waitForHMRCompleted(async ()=>{
448
- const { entityId, at, newProp } = request.body;
449
- const entity = EntityManager.get(entityId);
450
- await entity.createProp(newProp, at);
451
- return true;
452
- });
453
- });
454
- server.post("/api/entity/modifyProp", async (request)=>{
455
- return await waitForHMRCompleted(async ()=>{
456
- const { entityId, at, newProp } = request.body;
457
- const entity = EntityManager.get(entityId);
458
- entity.modifyProp(newProp, at);
459
- return true;
460
- });
461
- });
462
- server.post("/api/entity/delProp", async (request)=>{
463
- return await waitForHMRCompleted(async ()=>{
464
- const { entityId, at } = request.body;
465
- const entity = EntityManager.get(entityId);
466
- entity.delProp(at);
467
- return true;
468
- });
469
- });
470
- server.post("/api/entity/moveProp", async (request)=>{
471
- return await waitForHMRCompleted(async ()=>{
472
- const { entityId, at, to } = request.body;
473
- const entity = EntityManager.get(entityId);
474
- entity.moveProp(at, to);
475
- return true;
476
- });
477
- });
478
- server.post("/api/entity/modifyIndexes", async (request)=>{
479
- return await waitForHMRCompleted(async ()=>{
480
- const { entityId, indexes } = request.body;
481
- const entity = EntityManager.get(entityId);
482
- entity.indexes = indexes;
483
- await entity.save();
484
- return {
485
- updated: indexes
486
- };
487
- });
488
- });
489
- server.post("/api/entity/modifyEnumLabels", async (request)=>{
490
- return await waitForHMRCompleted(async ()=>{
491
- const { entityId, enumLabels } = request.body;
492
- const entity = EntityManager.get(entityId);
493
- entity.enumLabels = enumLabels;
494
- await entity.save();
495
- return {
496
- updated: enumLabels
497
- };
498
- });
499
- });
500
- server.post("/api/entity/createEnumId", async (request)=>{
501
- return await waitForHMRCompleted(async ()=>{
502
- const { entityId, newEnumId } = request.body;
503
- const entity = EntityManager.get(entityId);
504
- if (entity.enumLabels[newEnumId]) {
505
- throw new Error(`이미 존재하는 enumId입니다: ${newEnumId}`);
506
- }
507
- entity.enumLabels[newEnumId] = {
508
- ...newEnumId.endsWith("Status") ? {
509
- active: "노출",
510
- hidden: "숨김"
511
- } : {
512
- "": ""
513
- }
514
- };
515
- await entity.save();
516
- return 1;
517
- });
518
- });
519
- server.post("/api/entity/modifyEnumId", async (request)=>{
520
- return await waitForHMRCompleted(async ()=>{
521
- const { entityId, enumId } = request.body;
522
- const entityIds = EntityManager.getAllIds();
523
- const isExists = entityIds.some((entityId)=>{
524
- const entity = EntityManager.get(entityId);
525
- return Object.keys(entity.enumLabels).includes(enumId.after);
526
- });
527
- if (isExists) {
528
- throw new Error(`이미 존재하는 EnumId입니다: ${enumId.after}`);
529
- }
530
- const entity = EntityManager.get(entityId);
531
- entity.enumLabels[enumId.after] = entity.enumLabels[enumId.before];
532
- delete entity.enumLabels[enumId.before];
533
- await entity.save();
534
- for (const entityId of entityIds){
535
- const entity = EntityManager.get(entityId);
536
- for (const prop of entity.props){
537
- if (prop.type === "enum" && prop.id === enumId.before) {
538
- prop.id = enumId.after;
539
- }
540
- }
541
- await entity.save();
542
- }
543
- });
544
- });
545
- server.post("/api/entity/deleteEnumId", async (request)=>{
546
- return await waitForHMRCompleted(async ()=>{
547
- const { entityId, enumId } = request.body;
548
- const entityIds = EntityManager.getAllIds();
549
- const isReferenced = entityIds.flatMap((entityId)=>EntityManager.get(entityId).props).some((prop)=>prop.type === "enum" && prop.id === enumId);
550
- if (isReferenced) {
551
- throw new Error(`${enumId}를 참조하는 프로퍼티가 존재합니다.`);
552
- }
553
- const entity = EntityManager.get(entityId);
554
- delete entity.enumLabels[enumId];
555
- await entity.save();
556
- });
557
- });
558
- server.post("/api/entity/updateCone", async (request)=>{
559
- return await waitForHMRCompleted(async ()=>{
560
- const { entityId, target, propName, enumId, subsetKey, cone } = request.body;
561
- const entity = EntityManager.get(entityId);
562
- if (target === "entity") {
563
- entity.cone = cone;
564
- } else if (target === "prop" && propName) {
565
- const prop = entity.props.find((p)=>p.name === propName);
566
- if (prop) {
567
- prop.cone = cone;
568
- }
569
- } else if (target === "enum" && enumId) {
570
- entity.enumCones[enumId] = cone;
571
- } else if (target === "subset" && subsetKey) {
572
- entity.subsetCones[subsetKey] = cone;
573
- }
574
- await entity.save();
575
- return true;
576
- });
577
- });
578
- server.post("/api/entity/generateCones", async (request, reply)=>{
579
- return await waitForHMRCompleted(async ()=>{
580
- const { entityId, preserveExisting, onlyEmpty, locale } = request.body;
581
- try {
582
- // Entity 존재 여부 확인
583
- const entity = EntityManager.get(entityId);
584
- // locale 기본값: Sonamu.config.i18n.defaultLocale 사용
585
- const effectiveLocale = locale ?? Sonamu.config.i18n.defaultLocale;
586
- // Cone 생성
587
- const result = await entity.generateCones({
588
- preserveExisting: preserveExisting ?? true,
589
- onlyEmpty: onlyEmpty ?? false,
590
- locale: effectiveLocale
591
- });
592
- return result;
593
- } catch (error) {
594
- const message = error instanceof Error ? error.message : String(error);
595
- // Entity not found
596
- if (message.includes("존재하지 않는 Entity")) {
597
- reply.status(404);
598
- return {
599
- success: false,
600
- error: `Entity not found: ${entityId}`
601
- };
602
- }
603
- // API 키 없음
604
- if (message.includes("ANTHROPIC_API_KEY not found")) {
605
- reply.status(500);
606
- return {
607
- success: false,
608
- error: "API key not configured"
609
- };
610
- }
611
- // Rate limit
612
- if (message.includes("Rate limit exceeded")) {
613
- reply.status(429);
614
- return {
615
- success: false,
616
- error: "Rate limit exceeded. Please try again later."
617
- };
618
- }
619
- // 기타 에러
620
- reply.status(500);
621
- return {
622
- success: false,
623
- error: `Cone generation failed: ${message}`
624
- };
625
- }
626
- });
627
- });
628
- server.get("/api/entity/getTableColumns", async (request)=>{
629
- const { entityId } = request.query;
630
- const entity = EntityManager.get(entityId);
631
- const columns = entity.getTableColumns();
632
- return {
633
- columns
634
- };
635
- });
636
- server.get("/api/migrations/status", async ()=>{
637
- const status = await migrator.getStatus();
638
- return {
639
- status
640
- };
641
- });
642
- server.post("/api/migrations/runAction", async (request)=>{
643
- const { action, targets, force, forceReason, requestor } = request.body;
644
- if (action === "shadow") {
645
- return migrator.runShadowTest();
646
- }
647
- // Slack 승인 체크 (apply 시에만)
648
- if (action === "apply") {
649
- const slackConfirm = new SlackConfirm();
650
- const requiresApproval = targets.some((t)=>slackConfirm.isTargetRequiresApproval(t));
651
- // 로컬 DB인 경우 승인 스킵
652
- const localHosts = [
653
- "localhost",
654
- "127.0.0.1",
655
- "0.0.0.0",
656
- "::1"
657
- ];
658
- const isLocalTarget = targets.every((target)=>{
659
- const targetConfig = Sonamu.dbConfig[target];
660
- const host = targetConfig?.connection?.host ?? "localhost";
661
- return localHosts.includes(host.toLowerCase());
662
- });
663
- if (requiresApproval && slackConfirm.isConfigured() && !isLocalTarget) {
664
- const { conns } = await migrator.getStatus();
665
- // 모든 타겟 DB에서 pending인 마이그레이션의 합집합을 구합니다.
666
- const pendingMigrations = [
667
- ...new Set(conns.filter((conn)=>targets.includes(conn.connKey)).flatMap((conn)=>conn.pending))
668
- ];
669
- if (pendingMigrations.length > 0) {
670
- // 기존 승인 요청 확인
671
- const existing = await slackConfirm.getExistingRequest(pendingMigrations);
672
- if (existing) {
673
- // 기존 요청이 있으면 승인 상태 확인
674
- const { approved, rejected } = await slackConfirm.checkApproval(existing.channel, existing.ts);
675
- if (approved) {
676
- // 승인됨 실행
677
- const result = await migrator.runAction(action, targets);
678
- if (result.length > 0) {
679
- await slackConfirm.logExecution(existing.channel, existing.ts, result, requestor);
680
- }
681
- return result;
682
- } else if (rejected) {
683
- throw new BadRequestException(SD("sonamu.error.migrationRejected"));
684
- } else if (force) {
685
- // Force 진행
686
- await slackConfirm.forceApproval(existing.channel, existing.ts, forceReason ?? "사유 없음", requestor);
687
- const result = await migrator.runAction(action, targets);
688
- if (result.length > 0) {
689
- await slackConfirm.logExecution(existing.channel, existing.ts, result, requestor);
690
- }
691
- return result;
692
- } else {
693
- // 대기중
694
- return {
695
- type: "pending",
696
- channel: existing.channel,
697
- ts: existing.ts
698
- };
699
- }
700
- } else {
701
- // 승인 요청 발송
702
- const { channel, ts } = await slackConfirm.postApprovalRequest(pendingMigrations, targets, requestor);
703
- await slackConfirm.saveRequest(pendingMigrations, channel, ts);
704
- return {
705
- type: "pending",
706
- channel,
707
- ts
708
- };
709
- }
710
- }
711
- }
712
- }
713
- return migrator.runAction(action, targets);
714
- });
715
- server.post("/api/migrations/checkApproval", async (request)=>{
716
- const { channel, ts } = request.body;
717
- const slackConfirm = new SlackConfirm();
718
- if (!slackConfirm.isConfigured()) {
719
- return {
720
- approved: true,
721
- rejected: false
722
- };
723
- }
724
- return slackConfirm.checkApproval(channel, ts);
725
- });
726
- server.post("/api/migrations/forceApproval", async (request)=>{
727
- const { channel, ts, reason, requestor } = request.body;
728
- const slackConfirm = new SlackConfirm();
729
- if (!slackConfirm.isConfigured()) {
730
- throw new BadRequestException(SD("sonamu.error.slackConfirmNotConfigured"));
731
- }
732
- await slackConfirm.forceApproval(channel, ts, reason, requestor);
733
- return {
734
- success: true
735
- };
736
- });
737
- server.post("/api/migrations/delCodes", async (request)=>{
738
- const { codeNames } = request.body;
739
- return await migrator.delCodes(codeNames);
740
- });
741
- server.post("/api/migrations/generatePreparedCodes", async (_requestt)=>{
742
- return await migrator.generatePreparedCodes();
743
- });
744
- server.post("/api/scaffolding/getStatus", async (request)=>{
745
- const { entityIds, templateKeys: _templateKeys } = request.body;
746
- if ((entityIds ?? []).length === 0) {
747
- throw new BadRequestException(SD("sonamu.error.entityIdsRequired"));
748
- } else if ((_templateKeys ?? []).length === 0) {
749
- throw new BadRequestException(SD("sonamu.error.templateKeysRequired"));
750
- }
751
- // sorting
752
- entityIds.sort((a, b)=>a < b ? -1 : a > b ? 1 : 0);
753
- const templateKeys = TemplateKey.options.filter((tk)=>_templateKeys.includes(tk));
754
- const combinations = entityIds.flatMap((entityId)=>{
755
- return templateKeys.map((templateKey)=>[
756
- entityId,
757
- templateKey
758
- ]);
759
- });
760
- const statuses = await Promise.all(combinations.map(async ([entityId, templateKey])=>{
761
- const { subPath, fullPath, isExists } = await Sonamu.syncer.checkExistsGenCode(entityId, templateKey);
762
- return {
763
- entityId,
764
- templateKey,
765
- subPath,
766
- fullPath,
767
- isExists
768
- };
769
- }));
770
- return {
771
- statuses
772
- };
773
- });
774
- server.post("/api/scaffolding/generate", async (request)=>{
775
- const { options } = request.body;
776
- if (options.length === 0) {
777
- throw new BadRequestException(SD("sonamu.error.optionsRequired"));
778
- }
779
- // 1. 모든 템플릿에서 필요한 dict 키를 수집
780
- const keys = options.flatMap(({ templateKey })=>{
781
- const template = TemplateManager.get(templateKey);
782
- return template.getRequiredDictKeys() ?? [];
783
- });
784
- // 2. target별로 ensureDictKeys 호출 (순차 처리)
785
- await sonamuDictionary.ensureDictKeys([
786
- ...new Set(keys)
787
- ]);
788
- // 3. 템플릿 생성 (병렬 처리)
789
- const result = await Promise.all(options.map(async ({ entityId, templateKey, enumId, overwrite })=>{
790
- try {
791
- return await Sonamu.syncer.generateTemplate(templateKey, {
792
- entityId,
793
- enumId
794
- }, {
795
- overwrite
796
- });
797
- } catch (e) {
798
- if (isSoException(e) && e.statusCode === 541) {
799
- return null;
800
- } else {
801
- console.error(e);
802
- throw e;
803
- }
804
- }
805
- }));
806
- if (result.filter(nonNullable).length === 0) {
807
- throw new ServiceUnavailableException(SD("sonamu.error.allFilesGenerated"));
808
- }
809
- return result;
810
- });
811
- server.post("/api/scaffolding/preview", async (request)=>{
812
- const { option } = request.body;
813
- try {
814
- const { templateKey, ...templateOptions } = option;
815
- const pathAndCodes = await Sonamu.syncer.renderTemplate(templateKey, templateOptions);
816
- return {
817
- pathAndCodes
818
- };
819
- } catch (e) {
820
- console.error(e);
821
- throw e;
822
- }
823
- });
824
- server.post("/api/fixture", async (request)=>{
825
- const { sourceDB, targetDB, search, duplicateCheck } = request.body;
826
- return FixtureManager.getFixtures(sourceDB, targetDB, search, duplicateCheck);
827
- });
828
- server.post("/api/fixture/import", async (request)=>{
829
- const { db, fixtures } = request.body;
830
- return FixtureManager.insertFixtures(db, fixtures);
831
- });
832
- server.post("/api/fixture/addFixtureLoader", async (request)=>{
833
- const { code } = request.body;
834
- return FixtureManager.addFixtureLoader(code);
835
- });
836
- server.get("/api/i18n/dictionary", async ()=>{
837
- return sonamuDictionary.getDictionary();
838
- });
839
- server.get("/api/i18n/export", async (_request, reply)=>{
840
- const { filename, buffer } = await sonamuDictionary.exportToExcel();
841
- reply.header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet").header("Content-Disposition", `attachment; filename="${filename}"`).send(buffer);
842
- });
843
- server.post("/api/i18n/import", async (request)=>{
844
- const data = await request.file();
845
- if (!data) {
846
- throw new BadRequestException(SD("sonamu.error.fileNotUploaded"));
847
- }
848
- const buffer = await data.toBuffer();
849
- return sonamuDictionary.importFromExcel(buffer);
850
- });
851
- server.post("/api/i18n/update", async (request)=>{
852
- await sonamuDictionary.updateEntry(request.body);
853
- return {
854
- success: true
855
- };
856
- });
857
- server.post("/api/i18n/create", async (request)=>{
858
- await sonamuDictionary.createEntry(request.body);
859
- return {
860
- success: true
861
- };
862
- });
863
- server.post("/api/i18n/delete", async (request)=>{
864
- await sonamuDictionary.deleteEntry(request.body.key);
865
- return {
866
- success: true
867
- };
868
- });
869
- server.post("/api/i18n/checkUsage", async (request)=>{
870
- return sonamuDictionary.checkUsage(request.body.keys);
871
- });
872
- // Tasks API
873
- server.get("/api/tasks/status", async ()=>{
874
- try {
875
- Sonamu.workflows;
876
- return {
877
- active: true
878
- };
879
- } catch {
880
- return {
881
- active: false
882
- };
883
- }
884
- });
885
- server.get("/api/tasks/workflowDefinitions", async ()=>{
886
- const definitions = Sonamu.workflows.workflowDefinitions;
887
- return {
888
- definitions
889
- };
890
- });
891
- server.get("/api/tasks/workflowRuns", async (request)=>{
892
- const backend = Sonamu.workflows.backend;
893
- const { limit, after, before, order, status, workflowName, createdAfter, createdBefore } = request.query;
894
- return backend.listWorkflowRuns({
895
- limit: limit ? Number.parseInt(limit, 10) : undefined,
896
- after,
897
- before,
898
- order,
899
- status: status ? status.split(",") : undefined,
900
- workflowName: workflowName || undefined,
901
- createdAfter: createdAfter ? new Date(createdAfter) : undefined,
902
- createdBefore: createdBefore ? new Date(createdBefore) : undefined
903
- });
904
- });
905
- server.get("/api/tasks/workflowRuns/:id", async (request)=>{
906
- const backend = Sonamu.workflows.backend;
907
- const workflowRun = await backend.getWorkflowRun({
908
- workflowRunId: request.params.id
909
- });
910
- if (!workflowRun) {
911
- throw new Error(`Workflow run not found: ${request.params.id}`);
912
- }
913
- return workflowRun;
914
- });
915
- server.post("/api/tasks/workflowRuns/:id/cancel", async (request)=>{
916
- const backend = Sonamu.workflows.backend;
917
- return backend.cancelWorkflowRun({
918
- workflowRunId: request.params.id
919
- });
920
- });
921
- server.post("/api/tasks/workflowRuns/:id/pause", async (request)=>{
922
- const backend = Sonamu.workflows.backend;
923
- return backend.pauseWorkflowRun({
924
- workflowRunId: request.params.id
925
- });
926
- });
927
- server.post("/api/tasks/workflowRuns/:id/resume", async (request)=>{
928
- const backend = Sonamu.workflows.backend;
929
- return backend.resumeWorkflowRun({
930
- workflowRunId: request.params.id
931
- });
932
- });
933
- server.get("/api/tasks/workflowRuns/:id/steps", async (request)=>{
934
- const backend = Sonamu.workflows.backend;
935
- const { limit, after, before } = request.query;
936
- return backend.listStepAttempts({
937
- workflowRunId: request.params.id,
938
- limit: limit ? Number.parseInt(limit, 10) : undefined,
939
- after,
940
- before
941
- });
942
- });
943
- /**
944
- * Health Check API
945
- * MCP 도구가 Sonamu 서버를 자동 감지하기 위한 엔드포인트
946
- */ server.get("/api/sonamu/health", async (request)=>{
947
- const address = request.server.server.address();
948
- const port = address && typeof address === "object" ? address.port : 0;
949
- return {
950
- ok: true,
951
- project: process.cwd().split("/").pop() || "unknown",
952
- port,
953
- timestamp: new Date().toISOString()
954
- };
955
- });
956
- /**
957
- * Fixture 생성 API
958
- */ server.post("/api/sonamu/fixture/generate", async (request, reply)=>{
959
- const { entity, count = 1, overrides, targetDb = "fixture" } = request.body;
960
- // 타겟 DB 설정 가져오기
961
- const dbConfig = targetDb === "fixture" ? Sonamu.dbConfig.fixture : Sonamu.dbConfig.test;
962
- // Knex 인스턴스 생성
963
- const db = createKnexInstance(dbConfig);
964
- try {
965
- // FixtureGenerator 생성
966
- const generator = new FixtureGenerator(db, db, targetDb, EntityManager);
967
- // 단일 Entity 배치 생성
968
- const fixtures = await generator.generateBatch([
969
- {
970
- entity,
971
- count,
972
- overrides: overrides ?? {}
973
- }
974
- ]);
975
- return {
976
- success: true,
977
- entity,
978
- count: fixtures.length,
979
- fixtures,
980
- targetDb
981
- };
982
- } catch (error) {
983
- reply.status(400);
984
- return {
985
- success: false,
986
- error: error instanceof Error ? error.message : String(error)
987
- };
988
- } finally{
989
- await db.destroy();
990
- }
991
- });
992
- /**
993
- * Fixture 데이터 탐색 API
994
- */ server.post("/api/sonamu/fixture/explore", async (request, reply)=>{
995
- const { entity, strategy, limit = 10, where } = request.body;
996
- // Fixture DB 설정 가져오기
997
- const fixtureDbConfig = Sonamu.dbConfig.fixture;
998
- // Knex 인스턴스 생성
999
- const fixtureDb = createKnexInstance(fixtureDbConfig);
1000
- try {
1001
- // DataExplorer 생성
1002
- const explorer = new DataExplorer(fixtureDb, EntityManager);
1003
- const data = await explorer.explore(entity, {
1004
- strategy,
1005
- limit,
1006
- where
1007
- });
1008
- return {
1009
- success: true,
1010
- entity,
1011
- strategy,
1012
- count: data.length,
1013
- data
1014
- };
1015
- } catch (error) {
1016
- reply.status(400);
1017
- return {
1018
- success: false,
1019
- error: error instanceof Error ? error.message : String(error)
1020
- };
1021
- } finally{
1022
- await fixtureDb.destroy();
1023
- }
1024
- });
1025
- /**
1026
- * Fixture 데이터 가져오기 (fetch) API
1027
- * production/development DB에서 실제 데이터를 fixture DB로 import
1028
- */ server.post("/api/sonamu/fixture/fetch", async (request, reply)=>{
1029
- const { entity, strategy = "recent", limit = 10, includeRelations = true, maxDepth = 2 } = request.body;
1030
- // Source DB (production/development) - 읽기 전용
1031
- const sourceDb = DB.getDB("r");
1032
- // Target DB (fixture)
1033
- const fixtureDb = createKnexInstance(Sonamu.dbConfig.fixture);
1034
- try {
1035
- // FixtureGenerator 생성
1036
- const generator = new FixtureGenerator(sourceDb, fixtureDb, "fixture", EntityManager);
1037
- // production 데이터를 fixture DB로 import
1038
- const results = await generator.importFromSource(entity, {
1039
- strategy,
1040
- limit,
1041
- includeRelations,
1042
- maxDepth
1043
- });
1044
- return {
1045
- success: true,
1046
- entity,
1047
- strategy,
1048
- count: results.length,
1049
- imported: results
1050
- };
1051
- } catch (error) {
1052
- reply.status(400);
1053
- return {
1054
- success: false,
1055
- error: error instanceof Error ? error.message : String(error)
1056
- };
1057
- } finally{
1058
- // sourceDb는 Sonamu가 관리하므로 destroy하지 않음
1059
- await fixtureDb.destroy();
1060
- }
1061
- });
1062
- /**
1063
- * Fixture 데이터 삭제 (clean) API
1064
- * FK 순서를 고려하여 안전하게 삭제
1065
- */ server.post("/api/sonamu/fixture/clean", async (request, reply)=>{
1066
- const { entities } = request.body;
1067
- // Fixture DB 연결
1068
- const fixtureDb = createKnexInstance(Sonamu.dbConfig.fixture);
1069
- try {
1070
- // 삭제할 Entity 목록 결정
1071
- const targetEntities = entities && entities.length > 0 ? entities : EntityManager.getAllIds();
1072
- // Entity ID를 테이블명으로 변환 (snake_case 복수형)
1073
- const tableNames = targetEntities.map((entityId)=>{
1074
- const entity = EntityManager.get(entityId);
1075
- return entity.table;
1076
- });
1077
- // PostgreSQL: TRUNCATE CASCADE로 FK 순서 무관하게 안전하게 삭제
1078
- // CASCADE 옵션으로 의존성 있는 데이터도 함께 삭제
1079
- await fixtureDb.raw(`TRUNCATE TABLE ${tableNames.map((t)=>`"${t}"`).join(", ")} RESTART IDENTITY CASCADE`);
1080
- return {
1081
- success: true,
1082
- cleaned: tableNames,
1083
- count: tableNames.length
1084
- };
1085
- } catch (error) {
1086
- reply.status(400);
1087
- return {
1088
- success: false,
1089
- error: error instanceof Error ? error.message : String(error)
1090
- };
1091
- } finally{
1092
- await fixtureDb.destroy();
1093
- }
1094
- });
1095
- // CDD API
1096
- server.get("/api/cdd/tree", async ()=>{
1097
- return getCddTree();
1098
- });
1099
- server.post("/api/cdd/readContent", async (request)=>{
1100
- const { filePath } = request.body;
1101
- return readContent(filePath);
1102
- });
1103
- server.post("/api/cdd/editContent", async (request)=>{
1104
- const { filePath } = request.body;
1105
- return editContent(filePath);
1106
- });
1107
- server.post("/api/cdd/openSource", async (request)=>{
1108
- const { filePath } = request.body;
1109
- openSourceFile(filePath);
1110
- return {
1111
- success: true
1112
- };
1113
- });
1114
- // CDD Rules API
1115
- server.get("/api/cdd/rules", async ()=>{
1116
- return listRules();
1117
- });
1118
- server.post("/api/cdd/readRule", async (request)=>{
1119
- const { ruleKey } = request.body;
1120
- return readRule(ruleKey);
1121
- });
1122
- server.post("/api/cdd/addRule", async (request)=>{
1123
- return addRule(request.body);
1124
- });
1125
- // CDD AC API
1126
- server.get("/api/cdd/ac", async ()=>{
1127
- return getAcList();
1128
- });
1129
- // ui-web 빌드 파일 서빙
1130
- const uiDistPath = path.resolve(import.meta.dirname, "../ui-web");
1131
- // 정적 파일 서빙: 루트 폴더 전체 (assets, setting.svg 등)
1132
- server.register(await import("@fastify/static"), {
1133
- root: uiDistPath,
1134
- prefix: "/",
1135
- decorateReply: false,
1136
- wildcard: false
1137
- });
1138
- // SPA fallback - 정적 파일이 없는 모든 경로는 index.html로
1139
- server.get("*", async (_request, reply)=>{
1140
- reply.headers({
1141
- "Content-type": "text/html"
1142
- }).send(fs.readFileSync(path.resolve(uiDistPath, "index.html")).toString().replace("{{projectName}}", Sonamu.config.projectName ?? "UnknownSonamuProject"));
1143
- });
1144
- }, {
1145
- prefix: "/sonamu-ui"
1146
- });
21
+ import path from "path";
22
+ import fs from "fs";
23
+ import { execSync } from "child_process";
24
+
25
+ //#region src/ui/api.ts
26
+ async function sonamuUIApiPlugin(fastify) {
27
+ fastify.register(async (server) => {
28
+ const migrator = new Migrator();
29
+ async function waitForHMRCompleted(fn) {
30
+ const waitPromise = new Promise((resolve) => {
31
+ const handler = () => {
32
+ clearTimeout(timeout);
33
+ resolve();
34
+ };
35
+ const timeout = setTimeout(() => {
36
+ Sonamu.syncer.eventEmitter.off("onHMRCompleted", handler);
37
+ resolve();
38
+ }, 1500);
39
+ Sonamu.syncer.eventEmitter.once("onHMRCompleted", handler);
40
+ });
41
+ const result = await fn();
42
+ await waitPromise;
43
+ return result;
44
+ }
45
+ await setAiApi(server);
46
+ server.get("/api/sonamu/config", async () => {
47
+ return Sonamu.config;
48
+ });
49
+ server.get("/api/tools/openVscode", async (request) => {
50
+ const { entityId, preset, absPath } = request.query;
51
+ const targetPath = (() => {
52
+ if (entityId && preset) {
53
+ const entity = EntityManager.get(entityId);
54
+ const { names } = entity;
55
+ const { apiRootPath } = Sonamu;
56
+ const filename = (() => {
57
+ switch (preset) {
58
+ case "types": return `${names.fs}.types.ts`;
59
+ case "entity.json": return `${names.fs}.entity.json`;
60
+ case "generated": return `${names.fs}.generated.ts`;
61
+ }
62
+ })();
63
+ return `${apiRootPath}/src/application/${entity.names.parentFs}/${filename}`;
64
+ } else {
65
+ if (!absPath) {
66
+ throw new BadRequestException(SD("sonamu.error.presetOrAbsPathRequired"));
67
+ }
68
+ return absPath;
69
+ }
70
+ })();
71
+ execSync(`code ${targetPath}`);
72
+ });
73
+ server.get("/api/tools/getSuggestion", async (request) => {
74
+ const { origin, entityId } = request.query;
75
+ const glossary = new Map([
76
+ ["status", "상태"],
77
+ ["type", "타입"],
78
+ ["image", "이미지"],
79
+ ["images", "이미지리스트"],
80
+ ["url", "URL"],
81
+ ["id", "ID"],
82
+ ["name", `{EntityID}명`],
83
+ ["title", "{EntityID}명"],
84
+ ["parent", "상위{EntityID}"],
85
+ ["desc", "설명"],
86
+ ["at", "일시"],
87
+ ["created", "등록"],
88
+ ["updated", "수정"],
89
+ ["deleted", "삭제"],
90
+ ["by", "유저"],
91
+ ["date", "일자"],
92
+ ["time", "시간"],
93
+ ["ko", "(한글)"],
94
+ ["en", "(영문)"],
95
+ ["krw", "(원)"],
96
+ ["usd", "(USD)"],
97
+ ["color", "컬러"],
98
+ ["code", "코드"],
99
+ ["x", "X좌표"],
100
+ ["y", "Y좌표"],
101
+ ["current", "현재"],
102
+ ["stock", "재고"],
103
+ ["total", "총"],
104
+ ["admin", "관리자"],
105
+ ["group", "그룹"],
106
+ ["item", "아이템"],
107
+ ["cnt", "수량"],
108
+ ["price", "가격"],
109
+ ["preset", "프리셋"],
110
+ ["acct", "계좌"],
111
+ ["tel", "전화번호"],
112
+ ["no", "번호"],
113
+ ["body", "내용"],
114
+ ["content", "내용"],
115
+ ["orderno", "정렬순서"],
116
+ ["priority", "우선순위"],
117
+ ["text", "텍스트"],
118
+ ["key", "키"],
119
+ ["sum", "합산"],
120
+ ["expected", "예상"],
121
+ ["actual", "실제"]
122
+ ]);
123
+ for (const entityId$1 of EntityManager.getAllIds()) {
124
+ const entity = EntityManager.get(entityId$1);
125
+ if ((entity.title ?? "") !== "") {
126
+ glossary.set(inflection.underscore(entity.id), entity.title);
127
+ glossary.set(inflection.underscore(inflection.pluralize(entity.id)), `${entity.title}리스트`);
128
+ }
129
+ entity.props.forEach((prop) => {
130
+ if (glossary.has(prop.name)) {
131
+ return;
132
+ }
133
+ if (prop.desc) {
134
+ glossary.set(prop.name, prop.desc.replace(entity.title ?? "", "{EntityID}"));
135
+ }
136
+ });
137
+ }
138
+ const suggested = (() => {
139
+ const words = origin.split("_");
140
+ const combinations = [...range(words.length, 0, -1)].flatMap((len) => {
141
+ return [...range(0, words.length - len + 1, (idx) => {
142
+ return {
143
+ len,
144
+ w: words.slice(idx, idx + len).join("_")
145
+ };
146
+ })];
147
+ });
148
+ const REPLACED_PREFIX = "#REPLACED//";
149
+ let remainArr = [...words];
150
+ for (const comb of combinations) {
151
+ const remainStr = remainArr.join("_");
152
+ if (remainStr.includes(comb.w) && glossary.has(comb.w)) {
153
+ remainArr = remainStr.replace(comb.w, REPLACED_PREFIX + glossary.get(comb.w)).split("_");
154
+ }
155
+ }
156
+ return remainArr.map((r) => {
157
+ if (r.startsWith(REPLACED_PREFIX)) {
158
+ return r.replace(REPLACED_PREFIX, "");
159
+ } else {
160
+ return r.toUpperCase();
161
+ }
162
+ }).join("").replace(/{EntityID}/g, entityId ? EntityManager.get(entityId).title : "");
163
+ })();
164
+ return { suggested };
165
+ });
166
+ server.get("/api/entity/findMany", async () => {
167
+ const entityIds = EntityManager.getAllIds();
168
+ function flattenSubsetRows(subsetRows) {
169
+ return subsetRows.flatMap((subsetRow) => {
170
+ const { children, ...sRow } = subsetRow;
171
+ return [sRow, ...flattenSubsetRows(children)];
172
+ });
173
+ }
174
+ const entities = await Promise.all(entityIds.map((entityId) => {
175
+ const entity = EntityManager.get(entityId);
176
+ const subsetRows = entity.getSubsetRows();
177
+ return {
178
+ ...entity,
179
+ flattenSubsetRows: flattenSubsetRows(subsetRows)
180
+ };
181
+ }));
182
+ entities.sort((a, b) => {
183
+ const aId = a.parentId ?? a.id;
184
+ const bId = b.parentId ?? b.id;
185
+ if (aId < bId) return -1;
186
+ if (aId > bId) return 1;
187
+ if (aId === bId) {
188
+ if (a.parentId === undefined) return -1;
189
+ if (b.parentId === undefined) return 1;
190
+ return 0;
191
+ }
192
+ return 0;
193
+ });
194
+ return { entities };
195
+ });
196
+ server.get("/api/entity/typeIds", async (request) => {
197
+ const { filter, reload } = request.query;
198
+ if (reload === "1") {
199
+ await Sonamu.syncer.autoloadTypes();
200
+ }
201
+ const typeIds = (() => {
202
+ const projectTypeIds = Object.entries(Sonamu.syncer.types).filter(([_typeId, zodType]) => zodType._zod.def.type !== "enum").map(([typeId, _zodType]) => typeId);
203
+ const builtInTypeIds = [...BUILT_IN_TYPE_IDS];
204
+ const allTypeIds = [...builtInTypeIds, ...projectTypeIds];
205
+ if (filter === "types") {
206
+ return allTypeIds;
207
+ }
208
+ const enumIds = EntityManager.getAllIds().flatMap((entityId) => {
209
+ const entity = EntityManager.get(entityId);
210
+ return Object.keys(entity.enumLabels);
211
+ });
212
+ if (filter === "enums") {
213
+ return enumIds;
214
+ } else {
215
+ return [...allTypeIds, ...enumIds];
216
+ }
217
+ })();
218
+ return { typeIds };
219
+ });
220
+ server.post("/api/entity/create", async (request) => {
221
+ return await waitForHMRCompleted(async () => {
222
+ const { form } = request.body;
223
+ await Sonamu.syncer.createEntity({
224
+ ...form,
225
+ entityId: form.id
226
+ });
227
+ return 1;
228
+ });
229
+ });
230
+ server.post("/api/entity/del", async (request) => {
231
+ return await waitForHMRCompleted(async () => {
232
+ const { entityId } = request.body;
233
+ return await Sonamu.syncer.delEntity(entityId);
234
+ });
235
+ });
236
+ server.post("/api/entity/modifyEntityBase", async (request) => {
237
+ return await waitForHMRCompleted(async () => {
238
+ const { entityId, newValues } = request.body;
239
+ const entity = EntityManager.get(entityId);
240
+ entity.title = newValues.title;
241
+ entity.table = newValues.table;
242
+ entity.parentId = newValues.parentId;
243
+ await entity.save();
244
+ return 1;
245
+ });
246
+ });
247
+ server.post("/api/entity/modifySubset", async (request) => {
248
+ return await waitForHMRCompleted(async () => {
249
+ const { entityId, subsetKey, fields, fieldsInternal } = request.body;
250
+ const entity = EntityManager.get(entityId);
251
+ entity.subsets[subsetKey] = fields;
252
+ if (fieldsInternal !== undefined) {
253
+ if (fieldsInternal.length > 0) {
254
+ entity.subsetsInternal[subsetKey] = fieldsInternal;
255
+ } else {
256
+ delete entity.subsetsInternal[subsetKey];
257
+ }
258
+ }
259
+ await entity.save();
260
+ return {
261
+ updated: fields,
262
+ updatedInternal: fieldsInternal
263
+ };
264
+ });
265
+ });
266
+ server.post("/api/entity/delSubset", async (request) => {
267
+ return await waitForHMRCompleted(async () => {
268
+ const { entityId, subsetKey } = request.body;
269
+ const entity = EntityManager.get(entityId);
270
+ delete entity.subsets[subsetKey];
271
+ delete entity.subsetsInternal[subsetKey];
272
+ await entity.save();
273
+ return 1;
274
+ });
275
+ });
276
+ server.post("/api/entity/createProp", async (request) => {
277
+ return await waitForHMRCompleted(async () => {
278
+ const { entityId, at, newProp } = request.body;
279
+ const entity = EntityManager.get(entityId);
280
+ await entity.createProp(newProp, at);
281
+ return true;
282
+ });
283
+ });
284
+ server.post("/api/entity/modifyProp", async (request) => {
285
+ return await waitForHMRCompleted(async () => {
286
+ const { entityId, at, newProp } = request.body;
287
+ const entity = EntityManager.get(entityId);
288
+ entity.modifyProp(newProp, at);
289
+ return true;
290
+ });
291
+ });
292
+ server.post("/api/entity/delProp", async (request) => {
293
+ return await waitForHMRCompleted(async () => {
294
+ const { entityId, at } = request.body;
295
+ const entity = EntityManager.get(entityId);
296
+ entity.delProp(at);
297
+ return true;
298
+ });
299
+ });
300
+ server.post("/api/entity/moveProp", async (request) => {
301
+ return await waitForHMRCompleted(async () => {
302
+ const { entityId, at, to } = request.body;
303
+ const entity = EntityManager.get(entityId);
304
+ entity.moveProp(at, to);
305
+ return true;
306
+ });
307
+ });
308
+ server.post("/api/entity/modifyIndexes", async (request) => {
309
+ return await waitForHMRCompleted(async () => {
310
+ const { entityId, indexes } = request.body;
311
+ const entity = EntityManager.get(entityId);
312
+ entity.indexes = indexes;
313
+ await entity.save();
314
+ return { updated: indexes };
315
+ });
316
+ });
317
+ server.post("/api/entity/modifyEnumLabels", async (request) => {
318
+ return await waitForHMRCompleted(async () => {
319
+ const { entityId, enumLabels } = request.body;
320
+ const entity = EntityManager.get(entityId);
321
+ entity.enumLabels = enumLabels;
322
+ await entity.save();
323
+ return { updated: enumLabels };
324
+ });
325
+ });
326
+ server.post("/api/entity/createEnumId", async (request) => {
327
+ return await waitForHMRCompleted(async () => {
328
+ const { entityId, newEnumId } = request.body;
329
+ const entity = EntityManager.get(entityId);
330
+ if (entity.enumLabels[newEnumId]) {
331
+ throw new Error(`이미 존재하는 enumId입니다: ${newEnumId}`);
332
+ }
333
+ entity.enumLabels[newEnumId] = newEnumId.endsWith("Status") ? {
334
+ active: "노출",
335
+ hidden: "숨김"
336
+ } : { "": "" };
337
+ await entity.save();
338
+ return 1;
339
+ });
340
+ });
341
+ server.post("/api/entity/modifyEnumId", async (request) => {
342
+ return await waitForHMRCompleted(async () => {
343
+ const { entityId, enumId } = request.body;
344
+ const entityIds = EntityManager.getAllIds();
345
+ const isExists = entityIds.some((entityId$1) => {
346
+ const entity$1 = EntityManager.get(entityId$1);
347
+ return Object.keys(entity$1.enumLabels).includes(enumId.after);
348
+ });
349
+ if (isExists) {
350
+ throw new Error(`이미 존재하는 EnumId입니다: ${enumId.after}`);
351
+ }
352
+ const entity = EntityManager.get(entityId);
353
+ entity.enumLabels[enumId.after] = entity.enumLabels[enumId.before];
354
+ delete entity.enumLabels[enumId.before];
355
+ await entity.save();
356
+ for (const entityId$1 of entityIds) {
357
+ const entity$1 = EntityManager.get(entityId$1);
358
+ for (const prop of entity$1.props) {
359
+ if (prop.type === "enum" && prop.id === enumId.before) {
360
+ prop.id = enumId.after;
361
+ }
362
+ }
363
+ await entity$1.save();
364
+ }
365
+ });
366
+ });
367
+ server.post("/api/entity/deleteEnumId", async (request) => {
368
+ return await waitForHMRCompleted(async () => {
369
+ const { entityId, enumId } = request.body;
370
+ const entityIds = EntityManager.getAllIds();
371
+ const isReferenced = entityIds.flatMap((entityId$1) => EntityManager.get(entityId$1).props).some((prop) => prop.type === "enum" && prop.id === enumId);
372
+ if (isReferenced) {
373
+ throw new Error(`${enumId}를 참조하는 프로퍼티가 존재합니다.`);
374
+ }
375
+ const entity = EntityManager.get(entityId);
376
+ delete entity.enumLabels[enumId];
377
+ await entity.save();
378
+ });
379
+ });
380
+ server.post("/api/entity/updateCone", async (request) => {
381
+ return await waitForHMRCompleted(async () => {
382
+ const { entityId, target, propName, enumId, subsetKey, cone } = request.body;
383
+ const entity = EntityManager.get(entityId);
384
+ if (target === "entity") {
385
+ entity.cone = cone;
386
+ } else if (target === "prop" && propName) {
387
+ const prop = entity.props.find((p) => p.name === propName);
388
+ if (prop) {
389
+ prop.cone = cone;
390
+ }
391
+ } else if (target === "enum" && enumId) {
392
+ entity.enumCones[enumId] = cone;
393
+ } else if (target === "subset" && subsetKey) {
394
+ entity.subsetCones[subsetKey] = cone;
395
+ }
396
+ await entity.save();
397
+ return true;
398
+ });
399
+ });
400
+ server.post("/api/entity/generateCones", async (request, reply) => {
401
+ return await waitForHMRCompleted(async () => {
402
+ const { entityId, preserveExisting, onlyEmpty, locale } = request.body;
403
+ try {
404
+ const entity = EntityManager.get(entityId);
405
+ const effectiveLocale = locale ?? Sonamu.config.i18n.defaultLocale;
406
+ const result = await entity.generateCones({
407
+ preserveExisting: preserveExisting ?? true,
408
+ onlyEmpty: onlyEmpty ?? false,
409
+ locale: effectiveLocale
410
+ });
411
+ return result;
412
+ } catch (error) {
413
+ const message = error instanceof Error ? error.message : String(error);
414
+ if (message.includes("존재하지 않는 Entity")) {
415
+ reply.status(404);
416
+ return {
417
+ success: false,
418
+ error: `Entity not found: ${entityId}`
419
+ };
420
+ }
421
+ if (message.includes("ANTHROPIC_API_KEY not found")) {
422
+ reply.status(500);
423
+ return {
424
+ success: false,
425
+ error: "API key not configured"
426
+ };
427
+ }
428
+ if (message.includes("Rate limit exceeded")) {
429
+ reply.status(429);
430
+ return {
431
+ success: false,
432
+ error: "Rate limit exceeded. Please try again later."
433
+ };
434
+ }
435
+ reply.status(500);
436
+ return {
437
+ success: false,
438
+ error: `Cone generation failed: ${message}`
439
+ };
440
+ }
441
+ });
442
+ });
443
+ server.get("/api/entity/getTableColumns", async (request) => {
444
+ const { entityId } = request.query;
445
+ const entity = EntityManager.get(entityId);
446
+ const columns = entity.getTableColumns();
447
+ return { columns };
448
+ });
449
+ server.get("/api/migrations/status", async () => {
450
+ const status = await migrator.getStatus();
451
+ return { status };
452
+ });
453
+ server.post("/api/migrations/runAction", async (request) => {
454
+ const { action, targets, force, forceReason, requestor } = request.body;
455
+ if (action === "shadow") {
456
+ return migrator.runShadowTest();
457
+ }
458
+ if (action === "apply") {
459
+ const slackConfirm = new SlackConfirm();
460
+ const requiresApproval = targets.some((t) => slackConfirm.isTargetRequiresApproval(t));
461
+ const localHosts = [
462
+ "localhost",
463
+ "127.0.0.1",
464
+ "0.0.0.0",
465
+ "::1"
466
+ ];
467
+ const isLocalTarget = targets.every((target) => {
468
+ const targetConfig = Sonamu.dbConfig[target];
469
+ const host = (targetConfig?.connection)?.host ?? "localhost";
470
+ return localHosts.includes(host.toLowerCase());
471
+ });
472
+ if (requiresApproval && slackConfirm.isConfigured() && !isLocalTarget) {
473
+ const { conns } = await migrator.getStatus();
474
+ const pendingMigrations = [...new Set(conns.filter((conn) => targets.includes(conn.connKey)).flatMap((conn) => conn.pending))];
475
+ if (pendingMigrations.length > 0) {
476
+ const existing = await slackConfirm.getExistingRequest(pendingMigrations);
477
+ if (existing) {
478
+ const { approved, rejected } = await slackConfirm.checkApproval(existing.channel, existing.ts);
479
+ if (approved) {
480
+ const result = await migrator.runAction(action, targets);
481
+ if (result.length > 0) {
482
+ await slackConfirm.logExecution(existing.channel, existing.ts, result, requestor);
483
+ }
484
+ return result;
485
+ } else if (rejected) {
486
+ throw new BadRequestException(SD("sonamu.error.migrationRejected"));
487
+ } else if (force) {
488
+ await slackConfirm.forceApproval(existing.channel, existing.ts, forceReason ?? "사유 없음", requestor);
489
+ const result = await migrator.runAction(action, targets);
490
+ if (result.length > 0) {
491
+ await slackConfirm.logExecution(existing.channel, existing.ts, result, requestor);
492
+ }
493
+ return result;
494
+ } else {
495
+ return {
496
+ type: "pending",
497
+ channel: existing.channel,
498
+ ts: existing.ts
499
+ };
500
+ }
501
+ } else {
502
+ const { channel, ts } = await slackConfirm.postApprovalRequest(pendingMigrations, targets, requestor);
503
+ await slackConfirm.saveRequest(pendingMigrations, channel, ts);
504
+ return {
505
+ type: "pending",
506
+ channel,
507
+ ts
508
+ };
509
+ }
510
+ }
511
+ }
512
+ }
513
+ return migrator.runAction(action, targets);
514
+ });
515
+ server.post("/api/migrations/checkApproval", async (request) => {
516
+ const { channel, ts } = request.body;
517
+ const slackConfirm = new SlackConfirm();
518
+ if (!slackConfirm.isConfigured()) {
519
+ return {
520
+ approved: true,
521
+ rejected: false
522
+ };
523
+ }
524
+ return slackConfirm.checkApproval(channel, ts);
525
+ });
526
+ server.post("/api/migrations/forceApproval", async (request) => {
527
+ const { channel, ts, reason, requestor } = request.body;
528
+ const slackConfirm = new SlackConfirm();
529
+ if (!slackConfirm.isConfigured()) {
530
+ throw new BadRequestException(SD("sonamu.error.slackConfirmNotConfigured"));
531
+ }
532
+ await slackConfirm.forceApproval(channel, ts, reason, requestor);
533
+ return { success: true };
534
+ });
535
+ server.post("/api/migrations/delCodes", async (request) => {
536
+ const { codeNames } = request.body;
537
+ return await migrator.delCodes(codeNames);
538
+ });
539
+ server.post("/api/migrations/generatePreparedCodes", async (_requestt) => {
540
+ return await migrator.generatePreparedCodes();
541
+ });
542
+ server.post("/api/scaffolding/getStatus", async (request) => {
543
+ const { entityIds, templateKeys: _templateKeys } = request.body;
544
+ if ((entityIds ?? []).length === 0) {
545
+ throw new BadRequestException(SD("sonamu.error.entityIdsRequired"));
546
+ } else if ((_templateKeys ?? []).length === 0) {
547
+ throw new BadRequestException(SD("sonamu.error.templateKeysRequired"));
548
+ }
549
+ entityIds.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
550
+ const templateKeys = TemplateKey.options.filter((tk) => _templateKeys.includes(tk));
551
+ const combinations = entityIds.flatMap((entityId) => {
552
+ return templateKeys.map((templateKey) => [entityId, templateKey]);
553
+ });
554
+ const statuses = await Promise.all(combinations.map(async ([entityId, templateKey]) => {
555
+ const { subPath, fullPath, isExists } = await Sonamu.syncer.checkExistsGenCode(entityId, templateKey);
556
+ return {
557
+ entityId,
558
+ templateKey,
559
+ subPath,
560
+ fullPath,
561
+ isExists
562
+ };
563
+ }));
564
+ return { statuses };
565
+ });
566
+ server.post("/api/scaffolding/generate", async (request) => {
567
+ const { options } = request.body;
568
+ if (options.length === 0) {
569
+ throw new BadRequestException(SD("sonamu.error.optionsRequired"));
570
+ }
571
+ const keys = options.flatMap(({ templateKey }) => {
572
+ const template = TemplateManager.get(templateKey);
573
+ return template.getRequiredDictKeys() ?? [];
574
+ });
575
+ await sonamuDictionary.ensureDictKeys([...new Set(keys)]);
576
+ const result = await Promise.all(options.map(async ({ entityId, templateKey, enumId, overwrite }) => {
577
+ try {
578
+ return await Sonamu.syncer.generateTemplate(templateKey, {
579
+ entityId,
580
+ enumId
581
+ }, { overwrite });
582
+ } catch (e) {
583
+ if (isSoException(e) && e.statusCode === 541) {
584
+ return null;
585
+ } else {
586
+ console.error(e);
587
+ throw e;
588
+ }
589
+ }
590
+ }));
591
+ if (result.filter(nonNullable).length === 0) {
592
+ throw new ServiceUnavailableException(SD("sonamu.error.allFilesGenerated"));
593
+ }
594
+ return result;
595
+ });
596
+ server.post("/api/scaffolding/preview", async (request) => {
597
+ const { option } = request.body;
598
+ try {
599
+ const { templateKey, ...templateOptions } = option;
600
+ const pathAndCodes = await Sonamu.syncer.renderTemplate(templateKey, templateOptions);
601
+ return { pathAndCodes };
602
+ } catch (e) {
603
+ console.error(e);
604
+ throw e;
605
+ }
606
+ });
607
+ server.post("/api/fixture", async (request) => {
608
+ const { sourceDB, targetDB, search, duplicateCheck } = request.body;
609
+ return FixtureManager.getFixtures(sourceDB, targetDB, search, duplicateCheck);
610
+ });
611
+ server.post("/api/fixture/import", async (request) => {
612
+ const { db, fixtures } = request.body;
613
+ return FixtureManager.insertFixtures(db, fixtures);
614
+ });
615
+ server.post("/api/fixture/addFixtureLoader", async (request) => {
616
+ const { code } = request.body;
617
+ return FixtureManager.addFixtureLoader(code);
618
+ });
619
+ server.get("/api/i18n/dictionary", async () => {
620
+ return sonamuDictionary.getDictionary();
621
+ });
622
+ server.get("/api/i18n/export", async (_request, reply) => {
623
+ const { filename, buffer } = await sonamuDictionary.exportToExcel();
624
+ reply.header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet").header("Content-Disposition", `attachment; filename="${filename}"`).send(buffer);
625
+ });
626
+ server.post("/api/i18n/import", async (request) => {
627
+ const data = await request.file();
628
+ if (!data) {
629
+ throw new BadRequestException(SD("sonamu.error.fileNotUploaded"));
630
+ }
631
+ const buffer = await data.toBuffer();
632
+ return sonamuDictionary.importFromExcel(buffer);
633
+ });
634
+ server.post("/api/i18n/update", async (request) => {
635
+ await sonamuDictionary.updateEntry(request.body);
636
+ return { success: true };
637
+ });
638
+ server.post("/api/i18n/create", async (request) => {
639
+ await sonamuDictionary.createEntry(request.body);
640
+ return { success: true };
641
+ });
642
+ server.post("/api/i18n/delete", async (request) => {
643
+ await sonamuDictionary.deleteEntry(request.body.key);
644
+ return { success: true };
645
+ });
646
+ server.post("/api/i18n/checkUsage", async (request) => {
647
+ return sonamuDictionary.checkUsage(request.body.keys);
648
+ });
649
+ server.get("/api/tasks/status", async () => {
650
+ try {
651
+ Sonamu.workflows;
652
+ return { active: true };
653
+ } catch {
654
+ return { active: false };
655
+ }
656
+ });
657
+ server.get("/api/tasks/workflowDefinitions", async () => {
658
+ const definitions = Sonamu.workflows.workflowDefinitions;
659
+ return { definitions };
660
+ });
661
+ server.get("/api/tasks/workflowRuns", async (request) => {
662
+ const backend = Sonamu.workflows.backend;
663
+ const { limit, after, before, order, status, workflowName, createdAfter, createdBefore } = request.query;
664
+ return backend.listWorkflowRuns({
665
+ limit: limit ? Number.parseInt(limit, 10) : undefined,
666
+ after,
667
+ before,
668
+ order,
669
+ status: status ? status.split(",") : undefined,
670
+ workflowName: workflowName || undefined,
671
+ createdAfter: createdAfter ? new Date(createdAfter) : undefined,
672
+ createdBefore: createdBefore ? new Date(createdBefore) : undefined
673
+ });
674
+ });
675
+ server.get("/api/tasks/workflowRuns/:id", async (request) => {
676
+ const backend = Sonamu.workflows.backend;
677
+ const workflowRun = await backend.getWorkflowRun({ workflowRunId: request.params.id });
678
+ if (!workflowRun) {
679
+ throw new Error(`Workflow run not found: ${request.params.id}`);
680
+ }
681
+ return workflowRun;
682
+ });
683
+ server.post("/api/tasks/workflowRuns/:id/cancel", async (request) => {
684
+ const backend = Sonamu.workflows.backend;
685
+ return backend.cancelWorkflowRun({ workflowRunId: request.params.id });
686
+ });
687
+ server.post("/api/tasks/workflowRuns/:id/pause", async (request) => {
688
+ const backend = Sonamu.workflows.backend;
689
+ return backend.pauseWorkflowRun({ workflowRunId: request.params.id });
690
+ });
691
+ server.post("/api/tasks/workflowRuns/:id/resume", async (request) => {
692
+ const backend = Sonamu.workflows.backend;
693
+ return backend.resumeWorkflowRun({ workflowRunId: request.params.id });
694
+ });
695
+ server.get("/api/tasks/workflowRuns/:id/steps", async (request) => {
696
+ const backend = Sonamu.workflows.backend;
697
+ const { limit, after, before } = request.query;
698
+ return backend.listStepAttempts({
699
+ workflowRunId: request.params.id,
700
+ limit: limit ? Number.parseInt(limit, 10) : undefined,
701
+ after,
702
+ before
703
+ });
704
+ });
705
+ /**
706
+ * Health Check API
707
+ * MCP 도구가 Sonamu 서버를 자동 감지하기 위한 엔드포인트
708
+ */
709
+ server.get("/api/sonamu/health", async (request) => {
710
+ const address = request.server.server.address();
711
+ const port = address && typeof address === "object" ? address.port : 0;
712
+ return {
713
+ ok: true,
714
+ project: process.cwd().split("/").pop() || "unknown",
715
+ port,
716
+ timestamp: new Date().toISOString()
717
+ };
718
+ });
719
+ /**
720
+ * Fixture 생성 API
721
+ */
722
+ server.post("/api/sonamu/fixture/generate", async (request, reply) => {
723
+ const { entity, count = 1, overrides, targetDb = "fixture" } = request.body;
724
+ const dbConfig = targetDb === "fixture" ? Sonamu.dbConfig.fixture : Sonamu.dbConfig.test;
725
+ const db = createKnexInstance(dbConfig);
726
+ try {
727
+ const generator = new FixtureGenerator(db, db, targetDb, EntityManager);
728
+ const fixtures = await generator.generateBatch([{
729
+ entity,
730
+ count,
731
+ overrides: overrides ?? {}
732
+ }]);
733
+ return {
734
+ success: true,
735
+ entity,
736
+ count: fixtures.length,
737
+ fixtures,
738
+ targetDb
739
+ };
740
+ } catch (error) {
741
+ reply.status(400);
742
+ return {
743
+ success: false,
744
+ error: error instanceof Error ? error.message : String(error)
745
+ };
746
+ } finally {
747
+ await db.destroy();
748
+ }
749
+ });
750
+ /**
751
+ * Fixture 데이터 탐색 API
752
+ */
753
+ server.post("/api/sonamu/fixture/explore", async (request, reply) => {
754
+ const { entity, strategy, limit = 10, where } = request.body;
755
+ const fixtureDbConfig = Sonamu.dbConfig.fixture;
756
+ const fixtureDb = createKnexInstance(fixtureDbConfig);
757
+ try {
758
+ const explorer = new DataExplorer(fixtureDb, EntityManager);
759
+ const data = await explorer.explore(entity, {
760
+ strategy,
761
+ limit,
762
+ where
763
+ });
764
+ return {
765
+ success: true,
766
+ entity,
767
+ strategy,
768
+ count: data.length,
769
+ data
770
+ };
771
+ } catch (error) {
772
+ reply.status(400);
773
+ return {
774
+ success: false,
775
+ error: error instanceof Error ? error.message : String(error)
776
+ };
777
+ } finally {
778
+ await fixtureDb.destroy();
779
+ }
780
+ });
781
+ /**
782
+ * Fixture 데이터 가져오기 (fetch) API
783
+ * production/development DB에서 실제 데이터를 fixture DB로 import
784
+ */
785
+ server.post("/api/sonamu/fixture/fetch", async (request, reply) => {
786
+ const { entity, strategy = "recent", limit = 10, includeRelations = true, maxDepth = 2 } = request.body;
787
+ const sourceDb = DB.getDB("r");
788
+ const fixtureDb = createKnexInstance(Sonamu.dbConfig.fixture);
789
+ try {
790
+ const generator = new FixtureGenerator(sourceDb, fixtureDb, "fixture", EntityManager);
791
+ const results = await generator.importFromSource(entity, {
792
+ strategy,
793
+ limit,
794
+ includeRelations,
795
+ maxDepth
796
+ });
797
+ return {
798
+ success: true,
799
+ entity,
800
+ strategy,
801
+ count: results.length,
802
+ imported: results
803
+ };
804
+ } catch (error) {
805
+ reply.status(400);
806
+ return {
807
+ success: false,
808
+ error: error instanceof Error ? error.message : String(error)
809
+ };
810
+ } finally {
811
+ await fixtureDb.destroy();
812
+ }
813
+ });
814
+ /**
815
+ * Fixture 데이터 삭제 (clean) API
816
+ * FK 순서를 고려하여 안전하게 삭제
817
+ */
818
+ server.post("/api/sonamu/fixture/clean", async (request, reply) => {
819
+ const { entities } = request.body;
820
+ const fixtureDb = createKnexInstance(Sonamu.dbConfig.fixture);
821
+ try {
822
+ const targetEntities = entities && entities.length > 0 ? entities : EntityManager.getAllIds();
823
+ const tableNames = targetEntities.map((entityId) => {
824
+ const entity = EntityManager.get(entityId);
825
+ return entity.table;
826
+ });
827
+ await fixtureDb.raw(`TRUNCATE TABLE ${tableNames.map((t) => `"${t}"`).join(", ")} RESTART IDENTITY CASCADE`);
828
+ return {
829
+ success: true,
830
+ cleaned: tableNames,
831
+ count: tableNames.length
832
+ };
833
+ } catch (error) {
834
+ reply.status(400);
835
+ return {
836
+ success: false,
837
+ error: error instanceof Error ? error.message : String(error)
838
+ };
839
+ } finally {
840
+ await fixtureDb.destroy();
841
+ }
842
+ });
843
+ server.get("/api/cdd/tree", async () => {
844
+ return getCddTree();
845
+ });
846
+ server.post("/api/cdd/readContent", async (request) => {
847
+ const { filePath } = request.body;
848
+ return readContent(filePath);
849
+ });
850
+ server.post("/api/cdd/editContent", async (request) => {
851
+ const { filePath } = request.body;
852
+ return editContent(filePath);
853
+ });
854
+ server.post("/api/cdd/openSource", async (request) => {
855
+ const { filePath } = request.body;
856
+ openSourceFile(filePath);
857
+ return { success: true };
858
+ });
859
+ server.get("/api/cdd/rules", async () => {
860
+ return listRules();
861
+ });
862
+ server.post("/api/cdd/readRule", async (request) => {
863
+ const { ruleKey } = request.body;
864
+ return readRule(ruleKey);
865
+ });
866
+ server.post("/api/cdd/addRule", async (request) => {
867
+ return addRule(request.body);
868
+ });
869
+ server.get("/api/cdd/ac", async () => {
870
+ return getAcList();
871
+ });
872
+ const uiDistPath = path.resolve(import.meta.dirname, "../ui-web");
873
+ server.register(await import("@fastify/static"), {
874
+ root: uiDistPath,
875
+ prefix: "/",
876
+ decorateReply: false,
877
+ wildcard: false
878
+ });
879
+ server.get("*", async (_request, reply) => {
880
+ reply.headers({ "Content-type": "text/html" }).send(fs.readFileSync(path.resolve(uiDistPath, "index.html")).toString().replace("{{projectName}}", Sonamu.config.projectName ?? "UnknownSonamuProject"));
881
+ });
882
+ }, { prefix: "/sonamu-ui" });
1147
883
  }
884
+ var init_api = __esmMin((() => {
885
+ init_sonamu();
886
+ init_db();
887
+ init_knex();
888
+ init_sd();
889
+ init_sonamu_dictionary();
890
+ init_entity_manager();
891
+ init_so_exceptions();
892
+ init_migrator();
893
+ init_slack_confirm();
894
+ init_template_manager();
895
+ init_data_explorer();
896
+ init_fixture_generator();
897
+ init_fixture_manager();
898
+ init_types();
899
+ init_utils();
900
+ init_ai_api();
901
+ init_cdd_service();
902
+ }));
1148
903
 
1149
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91aS9hcGkudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZXhlY1N5bmMgfSBmcm9tIFwiY2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0IHR5cGUgeyBGYXN0aWZ5SW5zdGFuY2UgfSBmcm9tIFwiZmFzdGlmeVwiO1xuaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IGluZmxlY3Rpb24gZnJvbSBcImluZmxlY3Rpb25cIjtcbmltcG9ydCB0eXBlIHsgQWRkcmVzc0luZm8gfSBmcm9tIFwibmV0XCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHsgcmFuZ2UgfSBmcm9tIFwicmFkYXNoaVwiO1xuaW1wb3J0IHsgU29uYW11IH0gZnJvbSBcIi4uL2FwaS9zb25hbXVcIjtcbmltcG9ydCB7IERCLCB0eXBlIFNvbmFtdURCQ29uZmlnIH0gZnJvbSBcIi4uL2RhdGFiYXNlL2RiXCI7XG5pbXBvcnQgeyBjcmVhdGVLbmV4SW5zdGFuY2UgfSBmcm9tIFwiLi4vZGF0YWJhc2Uva25leFwiO1xuaW1wb3J0IHsgU0QgfSBmcm9tIFwiLi4vZGljdC9zZFwiO1xuaW1wb3J0IHsgc29uYW11RGljdGlvbmFyeSB9IGZyb20gXCIuLi9kaWN0L3NvbmFtdS1kaWN0aW9uYXJ5XCI7XG5pbXBvcnQgdHlwZSB7IEVudGl0eSB9IGZyb20gXCIuLi9lbnRpdHkvZW50aXR5XCI7XG5pbXBvcnQgeyBFbnRpdHlNYW5hZ2VyIH0gZnJvbSBcIi4uL2VudGl0eS9lbnRpdHktbWFuYWdlclwiO1xuaW1wb3J0IHtcbiAgQmFkUmVxdWVzdEV4Y2VwdGlvbixcbiAgaXNTb0V4Y2VwdGlvbixcbiAgU2VydmljZVVuYXZhaWxhYmxlRXhjZXB0aW9uLFxufSBmcm9tIFwiLi4vZXhjZXB0aW9ucy9zby1leGNlcHRpb25zXCI7XG5pbXBvcnQgeyB0eXBlIE1pZ3JhdGlvblJlc3VsdCwgTWlncmF0b3IgfSBmcm9tIFwiLi4vbWlncmF0aW9uL21pZ3JhdG9yXCI7XG5pbXBvcnQgeyBTbGFja0NvbmZpcm0sIHR5cGUgU2xhY2tDb25maXJtUGVuZGluZ1Jlc3VsdCB9IGZyb20gXCIuLi9taWdyYXRpb24vc2xhY2stY29uZmlybVwiO1xuaW1wb3J0IHsgVGVtcGxhdGVNYW5hZ2VyIH0gZnJvbSBcIi4uL3RlbXBsYXRlL3RlbXBsYXRlLW1hbmFnZXJcIjtcbmltcG9ydCB7IERhdGFFeHBsb3JlciB9IGZyb20gXCIuLi90ZXN0aW5nL2RhdGEtZXhwbG9yZXJcIjtcbmltcG9ydCB7IEZpeHR1cmVHZW5lcmF0b3IgfSBmcm9tIFwiLi4vdGVzdGluZy9maXh0dXJlLWdlbmVyYXRvclwiO1xuaW1wb3J0IHsgdHlwZSBEdXBsaWNhdGVDaGVja09wdGlvbnMsIEZpeHR1cmVNYW5hZ2VyIH0gZnJvbSBcIi4uL3Rlc3RpbmcvZml4dHVyZS1tYW5hZ2VyXCI7XG5pbXBvcnQge1xuICBCVUlMVF9JTl9UWVBFX0lEUyxcbiAgdHlwZSBDb25lLFxuICB0eXBlIEVudGl0eUluZGV4LFxuICB0eXBlIEVudGl0eVByb3AsXG4gIHR5cGUgRW50aXR5U3Vic2V0Um93LFxuICB0eXBlIEZpeHR1cmVSZWNvcmQsXG4gIHR5cGUgRml4dHVyZVNlYXJjaE9wdGlvbnMsXG4gIHR5cGUgRmxhdHRlblN1YnNldFJvdyxcbiAgdHlwZSBQYXRoQW5kQ29kZSxcbiAgVGVtcGxhdGVLZXksXG59IGZyb20gXCIuLi90eXBlcy90eXBlc1wiO1xuaW1wb3J0IHsgbm9uTnVsbGFibGUgfSBmcm9tIFwiLi4vdXRpbHMvdXRpbHNcIjtcbmltcG9ydCB7IHNldEFpQXBpIH0gZnJvbSBcIi4vYWktYXBpXCI7XG5pbXBvcnQgdHlwZSB7IENkZEFkZFJ1bGVSZXF1ZXN0IH0gZnJvbSBcIi4vY2RkLXNlcnZpY2VcIjtcbmltcG9ydCB7XG4gIGFkZFJ1bGUsXG4gIGVkaXRDb250ZW50LFxuICBnZXRBY0xpc3QsXG4gIGdldENkZFRyZWUsXG4gIGxpc3RSdWxlcyxcbiAgb3BlblNvdXJjZUZpbGUsXG4gIHJlYWRDb250ZW50LFxuICByZWFkUnVsZSxcbn0gZnJvbSBcIi4vY2RkLXNlcnZpY2VcIjtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNvbmFtdVVJQXBpUGx1Z2luKGZhc3RpZnk6IEZhc3RpZnlJbnN0YW5jZSkge1xuICBmYXN0aWZ5LnJlZ2lzdGVyKFxuICAgIGFzeW5jIChzZXJ2ZXIpID0+IHtcbiAgICAgIC8vIG1pZ3JhdG9yXG4gICAgICBjb25zdCBtaWdyYXRvciA9IG5ldyBNaWdyYXRvcigpO1xuXG4gICAgICAvLyB3YWl0Rm9ySE1SQ29tcGxldGVkXG4gICAgICBhc3luYyBmdW5jdGlvbiB3YWl0Rm9ySE1SQ29tcGxldGVkPFQ+KGZuOiAoKSA9PiBQcm9taXNlPFQ+KTogUHJvbWlzZTxUPiB7XG4gICAgICAgIGNvbnN0IHdhaXRQcm9taXNlID0gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHtcbiAgICAgICAgICBjb25zdCBoYW5kbGVyID0gKCkgPT4ge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgIH07XG5cbiAgICAgICAgICBjb25zdCB0aW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICBTb25hbXUuc3luY2VyLmV2ZW50RW1pdHRlci5vZmYoXCJvbkhNUkNvbXBsZXRlZFwiLCBoYW5kbGVyKTtcbiAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICB9LCAxNTAwKTtcblxuICAgICAgICAgIFNvbmFtdS5zeW5jZXIuZXZlbnRFbWl0dGVyLm9uY2UoXCJvbkhNUkNvbXBsZXRlZFwiLCBoYW5kbGVyKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZm4oKTtcbiAgICAgICAgYXdhaXQgd2FpdFByb21pc2U7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IHNldEFpQXBpKHNlcnZlcik7XG5cbiAgICAgIHNlcnZlci5nZXQoXCIvYXBpL3NvbmFtdS9jb25maWdcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgICByZXR1cm4gU29uYW11LmNvbmZpZztcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIuZ2V0PHtcbiAgICAgICAgUXVlcnlzdHJpbmc6IHtcbiAgICAgICAgICBlbnRpdHlJZD86IHN0cmluZztcbiAgICAgICAgICBwcmVzZXQ/OiBcInR5cGVzXCIgfCBcImVudGl0eS5qc29uXCIgfCBcImdlbmVyYXRlZFwiO1xuICAgICAgICAgIGFic1BhdGg/OiBzdHJpbmc7XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvdG9vbHMvb3BlblZzY29kZVwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICBjb25zdCB7IGVudGl0eUlkLCBwcmVzZXQsIGFic1BhdGggfSA9IHJlcXVlc3QucXVlcnk7XG5cbiAgICAgICAgY29uc3QgdGFyZ2V0UGF0aCA9ICgoKSA9PiB7XG4gICAgICAgICAgaWYgKGVudGl0eUlkICYmIHByZXNldCkge1xuICAgICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgICAgY29uc3QgeyBuYW1lcyB9ID0gZW50aXR5O1xuXG4gICAgICAgICAgICBjb25zdCB7IGFwaVJvb3RQYXRoIH0gPSBTb25hbXU7XG4gICAgICAgICAgICBjb25zdCBmaWxlbmFtZSA9ICgoKSA9PiB7XG4gICAgICAgICAgICAgIHN3aXRjaCAocHJlc2V0KSB7XG4gICAgICAgICAgICAgICAgY2FzZSBcInR5cGVzXCI6XG4gICAgICAgICAgICAgICAgICByZXR1cm4gYCR7bmFtZXMuZnN9LnR5cGVzLnRzYDtcbiAgICAgICAgICAgICAgICBjYXNlIFwiZW50aXR5Lmpzb25cIjpcbiAgICAgICAgICAgICAgICAgIHJldHVybiBgJHtuYW1lcy5mc30uZW50aXR5Lmpzb25gO1xuICAgICAgICAgICAgICAgIGNhc2UgXCJnZW5lcmF0ZWRcIjpcbiAgICAgICAgICAgICAgICAgIHJldHVybiBgJHtuYW1lcy5mc30uZ2VuZXJhdGVkLnRzYDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgICAgIHJldHVybiBgJHthcGlSb290UGF0aH0vc3JjL2FwcGxpY2F0aW9uLyR7ZW50aXR5Lm5hbWVzLnBhcmVudEZzfS8ke2ZpbGVuYW1lfWA7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICghYWJzUGF0aCkge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihTRChcInNvbmFtdS5lcnJvci5wcmVzZXRPckFic1BhdGhSZXF1aXJlZFwiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gYWJzUGF0aDtcbiAgICAgICAgICB9XG4gICAgICAgIH0pKCk7XG4gICAgICAgIGV4ZWNTeW5jKGBjb2RlICR7dGFyZ2V0UGF0aH1gKTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIuZ2V0PHtcbiAgICAgICAgUXVlcnlzdHJpbmc6IHtcbiAgICAgICAgICBvcmlnaW46IHN0cmluZztcbiAgICAgICAgICBlbnRpdHlJZD86IHN0cmluZztcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS90b29scy9nZXRTdWdnZXN0aW9uXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgb3JpZ2luLCBlbnRpdHlJZCB9ID0gcmVxdWVzdC5xdWVyeTtcblxuICAgICAgICAvLyDsuZjtmZgg7Jqp7Ja07KeRXG4gICAgICAgIGNvbnN0IGdsb3NzYXJ5ID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oW1xuICAgICAgICAgIFtcInN0YXR1c1wiLCBcIuyDge2DnFwiXSxcbiAgICAgICAgICBbXCJ0eXBlXCIsIFwi7YOA7J6FXCJdLFxuICAgICAgICAgIFtcImltYWdlXCIsIFwi7J2066+47KeAXCJdLFxuICAgICAgICAgIFtcImltYWdlc1wiLCBcIuydtOuvuOyngOumrOyKpO2KuFwiXSxcbiAgICAgICAgICBbXCJ1cmxcIiwgXCJVUkxcIl0sXG4gICAgICAgICAgW1wiaWRcIiwgXCJJRFwiXSxcbiAgICAgICAgICBbXCJuYW1lXCIsIGB7RW50aXR5SUR966qFYF0sXG4gICAgICAgICAgW1widGl0bGVcIiwgXCJ7RW50aXR5SUR966qFXCJdLFxuICAgICAgICAgIFtcInBhcmVudFwiLCBcIuyDgeychHtFbnRpdHlJRH1cIl0sXG4gICAgICAgICAgW1wiZGVzY1wiLCBcIuyEpOuqhVwiXSxcbiAgICAgICAgICBbXCJhdFwiLCBcIuydvOyLnFwiXSxcbiAgICAgICAgICBbXCJjcmVhdGVkXCIsIFwi65Ox66GdXCJdLFxuICAgICAgICAgIFtcInVwZGF0ZWRcIiwgXCLsiJjsoJVcIl0sXG4gICAgICAgICAgW1wiZGVsZXRlZFwiLCBcIuyCreygnFwiXSxcbiAgICAgICAgICBbXCJieVwiLCBcIuycoOyggFwiXSxcbiAgICAgICAgICBbXCJkYXRlXCIsIFwi7J287J6QXCJdLFxuICAgICAgICAgIFtcInRpbWVcIiwgXCLsi5zqsIRcIl0sXG4gICAgICAgICAgW1wia29cIiwgXCIo7ZWc6riAKVwiXSxcbiAgICAgICAgICBbXCJlblwiLCBcIijsmIHrrLgpXCJdLFxuICAgICAgICAgIFtcImtyd1wiLCBcIijsm5ApXCJdLFxuICAgICAgICAgIFtcInVzZFwiLCBcIihVU0QpXCJdLFxuICAgICAgICAgIFtcImNvbG9yXCIsIFwi7Lus65+sXCJdLFxuICAgICAgICAgIFtcImNvZGVcIiwgXCLsvZTrk5xcIl0sXG4gICAgICAgICAgW1wieFwiLCBcIljsooztkZxcIl0sXG4gICAgICAgICAgW1wieVwiLCBcIlnsooztkZxcIl0sXG4gICAgICAgICAgW1wiY3VycmVudFwiLCBcIu2YhOyerFwiXSxcbiAgICAgICAgICBbXCJzdG9ja1wiLCBcIuyerOqzoFwiXSxcbiAgICAgICAgICBbXCJ0b3RhbFwiLCBcIuy0nVwiXSxcbiAgICAgICAgICBbXCJhZG1pblwiLCBcIuq0gOumrOyekFwiXSxcbiAgICAgICAgICBbXCJncm91cFwiLCBcIuq3uOujuVwiXSxcbiAgICAgICAgICBbXCJpdGVtXCIsIFwi7JWE7J207YWcXCJdLFxuICAgICAgICAgIFtcImNudFwiLCBcIuyImOufiVwiXSxcbiAgICAgICAgICBbXCJwcmljZVwiLCBcIuqwgOqyqVwiXSxcbiAgICAgICAgICBbXCJwcmVzZXRcIiwgXCLtlITrpqzshYtcIl0sXG4gICAgICAgICAgW1wiYWNjdFwiLCBcIuqzhOyijFwiXSxcbiAgICAgICAgICBbXCJ0ZWxcIiwgXCLsoITtmZTrsojtmLhcIl0sXG4gICAgICAgICAgW1wibm9cIiwgXCLrsojtmLhcIl0sXG4gICAgICAgICAgW1wiYm9keVwiLCBcIuuCtOyaqVwiXSxcbiAgICAgICAgICBbXCJjb250ZW50XCIsIFwi64K07JqpXCJdLFxuICAgICAgICAgIFtcIm9yZGVybm9cIiwgXCLsoJXroKzsiJzshJxcIl0sXG4gICAgICAgICAgW1wicHJpb3JpdHlcIiwgXCLsmrDshKDsiJzsnIRcIl0sXG4gICAgICAgICAgW1widGV4dFwiLCBcIu2FjeyKpO2KuFwiXSxcbiAgICAgICAgICBbXCJrZXlcIiwgXCLtgqRcIl0sXG4gICAgICAgICAgW1wic3VtXCIsIFwi7ZWp7IKwXCJdLFxuICAgICAgICAgIFtcImV4cGVjdGVkXCIsIFwi7JiI7IOBXCJdLFxuICAgICAgICAgIFtcImFjdHVhbFwiLCBcIuyLpOygnFwiXSxcbiAgICAgICAgXSk7XG4gICAgICAgIC8vIOyghOyytCDsl5Tti7Dti7Ag7Iic7ZqM7ZWY66mwLCDsl5Tti7Dti7Ag7YOA7J207YuA6rO8IO2UhOuhrSDshKTrqoXsnYQg7LmY7ZmYIOyaqeyWtOynkeyXkCDstpTqsIBcbiAgICAgICAgZm9yIChjb25zdCBlbnRpdHlJZCBvZiBFbnRpdHlNYW5hZ2VyLmdldEFsbElkcygpKSB7XG4gICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgIGlmICgoZW50aXR5LnRpdGxlID8/IFwiXCIpICE9PSBcIlwiKSB7XG4gICAgICAgICAgICBnbG9zc2FyeS5zZXQoaW5mbGVjdGlvbi51bmRlcnNjb3JlKGVudGl0eS5pZCksIGVudGl0eS50aXRsZSk7XG4gICAgICAgICAgICBnbG9zc2FyeS5zZXQoXG4gICAgICAgICAgICAgIGluZmxlY3Rpb24udW5kZXJzY29yZShpbmZsZWN0aW9uLnBsdXJhbGl6ZShlbnRpdHkuaWQpKSxcbiAgICAgICAgICAgICAgYCR7ZW50aXR5LnRpdGxlfeumrOyKpO2KuGAsXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGVudGl0eS5wcm9wcy5mb3JFYWNoKChwcm9wKSA9PiB7XG4gICAgICAgICAgICBpZiAoZ2xvc3NhcnkuaGFzKHByb3AubmFtZSkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHByb3AuZGVzYykge1xuICAgICAgICAgICAgICBnbG9zc2FyeS5zZXQocHJvcC5uYW1lLCBwcm9wLmRlc2MucmVwbGFjZShlbnRpdHkudGl0bGUgPz8gXCJcIiwgXCJ7RW50aXR5SUR9XCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHN1Z2dlc3RlZCA9ICgoKSA9PiB7XG4gICAgICAgICAgLy8g64uo7Ja0IOu2hOumrCwg6rCA64ql7ZWcIOyhsO2VqSDsg53shLFcbiAgICAgICAgICBjb25zdCB3b3JkcyA9IG9yaWdpbi5zcGxpdChcIl9cIik7XG4gICAgICAgICAgY29uc3QgY29tYmluYXRpb25zID0gWy4uLnJhbmdlKHdvcmRzLmxlbmd0aCwgMCwgLTEpXS5mbGF0TWFwKChsZW4pID0+IHtcbiAgICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAgIC4uLnJhbmdlKDAsIHdvcmRzLmxlbmd0aCAtIGxlbiArIDEsIChpZHgpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgbGVuLFxuICAgICAgICAgICAgICAgICAgdzogd29yZHMuc2xpY2UoaWR4LCBpZHggKyBsZW4pLmpvaW4oXCJfXCIpLFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgXTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIC8vIOyhsO2VqeydhCDsiJztmoztlZjrqbAsIOy5mO2ZmCDsmqnslrTsp5Hsl5Ag7J6I64qUIOuLqOyWtOqwgCDtj6ztlajrkJwg6rK97JqwLCDsuZjtmZgg7Jqp7Ja066GcIOy5mO2ZmFxuICAgICAgICAgIGNvbnN0IFJFUExBQ0VEX1BSRUZJWCA9IFwiI1JFUExBQ0VELy9cIjsgLy8g7LmY7ZmY65CcIOuLqOyWtOulvCBqb2luIOydtO2bhOyXkOuPhCDsi53rs4TtlZjquLAg7JyE7ZW0IHByZWZpeCDstpTqsIBcbiAgICAgICAgICBsZXQgcmVtYWluQXJyOiBzdHJpbmdbXSA9IFsuLi53b3Jkc107XG4gICAgICAgICAgZm9yIChjb25zdCBjb21iIG9mIGNvbWJpbmF0aW9ucykge1xuICAgICAgICAgICAgY29uc3QgcmVtYWluU3RyID0gcmVtYWluQXJyLmpvaW4oXCJfXCIpO1xuICAgICAgICAgICAgaWYgKHJlbWFpblN0ci5pbmNsdWRlcyhjb21iLncpICYmIGdsb3NzYXJ5Lmhhcyhjb21iLncpKSB7XG4gICAgICAgICAgICAgIHJlbWFpbkFyciA9IHJlbWFpblN0clxuICAgICAgICAgICAgICAgIC5yZXBsYWNlKGNvbWIudywgUkVQTEFDRURfUFJFRklYICsgZ2xvc3NhcnkuZ2V0KGNvbWIudykpXG4gICAgICAgICAgICAgICAgLnNwbGl0KFwiX1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gcmVtYWluQXJyXG4gICAgICAgICAgICAubWFwKChyKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChyLnN0YXJ0c1dpdGgoUkVQTEFDRURfUFJFRklYKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiByLnJlcGxhY2UoUkVQTEFDRURfUFJFRklYLCBcIlwiKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gci50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmpvaW4oXCJcIilcbiAgICAgICAgICAgIC5yZXBsYWNlKC97RW50aXR5SUR9L2csIGVudGl0eUlkID8gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpLnRpdGxlIDogXCJcIik7XG4gICAgICAgIH0pKCk7XG5cbiAgICAgICAgcmV0dXJuIHsgc3VnZ2VzdGVkIH07XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLmdldChcIi9hcGkvZW50aXR5L2ZpbmRNYW55XCIsIGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3QgZW50aXR5SWRzID0gRW50aXR5TWFuYWdlci5nZXRBbGxJZHMoKTtcblxuICAgICAgICBmdW5jdGlvbiBmbGF0dGVuU3Vic2V0Um93cyhzdWJzZXRSb3dzOiBFbnRpdHlTdWJzZXRSb3dbXSk6IEZsYXR0ZW5TdWJzZXRSb3dbXSB7XG4gICAgICAgICAgcmV0dXJuIHN1YnNldFJvd3MuZmxhdE1hcCgoc3Vic2V0Um93KSA9PiB7XG4gICAgICAgICAgICBjb25zdCB7IGNoaWxkcmVuLCAuLi5zUm93IH0gPSBzdWJzZXRSb3c7XG4gICAgICAgICAgICByZXR1cm4gW3NSb3csIC4uLmZsYXR0ZW5TdWJzZXRSb3dzKGNoaWxkcmVuKV07XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBlbnRpdGllcyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICAgIGVudGl0eUlkcy5tYXAoKGVudGl0eUlkKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgICAgICAgICBjb25zdCBzdWJzZXRSb3dzID0gZW50aXR5LmdldFN1YnNldFJvd3MoKTtcblxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgLi4uZW50aXR5LFxuICAgICAgICAgICAgICBmbGF0dGVuU3Vic2V0Um93czogZmxhdHRlblN1YnNldFJvd3Moc3Vic2V0Um93cyksXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH0pLFxuICAgICAgICApO1xuXG4gICAgICAgIGVudGl0aWVzLnNvcnQoKGEsIGIpID0+IHtcbiAgICAgICAgICBjb25zdCBhSWQgPSBhLnBhcmVudElkID8/IGEuaWQ7XG4gICAgICAgICAgY29uc3QgYklkID0gYi5wYXJlbnRJZCA/PyBiLmlkO1xuICAgICAgICAgIGlmIChhSWQgPCBiSWQpIHJldHVybiAtMTtcbiAgICAgICAgICBpZiAoYUlkID4gYklkKSByZXR1cm4gMTtcbiAgICAgICAgICBpZiAoYUlkID09PSBiSWQpIHtcbiAgICAgICAgICAgIGlmIChhLnBhcmVudElkID09PSB1bmRlZmluZWQpIHJldHVybiAtMTtcbiAgICAgICAgICAgIGlmIChiLnBhcmVudElkID09PSB1bmRlZmluZWQpIHJldHVybiAxO1xuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHsgZW50aXRpZXMgfTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIuZ2V0PHtcbiAgICAgICAgUXVlcnlzdHJpbmc6IHtcbiAgICAgICAgICBmaWx0ZXI/OiBcImVudW1zXCIgfCBcInR5cGVzXCI7XG4gICAgICAgICAgcmVsb2FkPzogXCIxXCI7XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvZW50aXR5L3R5cGVJZHNcIiwgYXN5bmMgKHJlcXVlc3QpOiBQcm9taXNlPHsgdHlwZUlkczogc3RyaW5nW10gfT4gPT4ge1xuICAgICAgICBjb25zdCB7IGZpbHRlciwgcmVsb2FkIH0gPSByZXF1ZXN0LnF1ZXJ5O1xuXG4gICAgICAgIGlmIChyZWxvYWQgPT09IFwiMVwiKSB7XG4gICAgICAgICAgYXdhaXQgU29uYW11LnN5bmNlci5hdXRvbG9hZFR5cGVzKCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB0eXBlSWRzID0gKCgpID0+IHtcbiAgICAgICAgICAvLyDtlITroZzsoJ3tirjsl5DshJwg7KCV7J2Y7ZWcIO2DgOyeheuTpFxuICAgICAgICAgIGNvbnN0IHByb2plY3RUeXBlSWRzID0gT2JqZWN0LmVudHJpZXMoU29uYW11LnN5bmNlci50eXBlcylcbiAgICAgICAgICAgIC5maWx0ZXIoKFtfdHlwZUlkLCB6b2RUeXBlXSkgPT4gKHpvZFR5cGUuX3pvZC5kZWYudHlwZSBhcyBzdHJpbmcpICE9PSBcImVudW1cIilcbiAgICAgICAgICAgIC5tYXAoKFt0eXBlSWQsIF96b2RUeXBlXSkgPT4gdHlwZUlkKTtcblxuICAgICAgICAgIC8vIOuCtOyepSDtg4DsnoXrk6QgKHNvbmFtdSDsvZTslrTsl5DshJwg7KCc6rO1KVxuICAgICAgICAgIGNvbnN0IGJ1aWx0SW5UeXBlSWRzID0gWy4uLkJVSUxUX0lOX1RZUEVfSURTXTtcblxuICAgICAgICAgIC8vIOuqqOuToCDtg4DsnoUg67OR7ZWpXG4gICAgICAgICAgY29uc3QgYWxsVHlwZUlkcyA9IFsuLi5idWlsdEluVHlwZUlkcywgLi4ucHJvamVjdFR5cGVJZHNdO1xuXG4gICAgICAgICAgaWYgKGZpbHRlciA9PT0gXCJ0eXBlc1wiKSB7XG4gICAgICAgICAgICByZXR1cm4gYWxsVHlwZUlkcztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBlbnVtSWRzID0gRW50aXR5TWFuYWdlci5nZXRBbGxJZHMoKS5mbGF0TWFwKChlbnRpdHlJZCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKGVudGl0eS5lbnVtTGFiZWxzKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGlmIChmaWx0ZXIgPT09IFwiZW51bXNcIikge1xuICAgICAgICAgICAgcmV0dXJuIGVudW1JZHM7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBbLi4uYWxsVHlwZUlkcywgLi4uZW51bUlkc107XG4gICAgICAgICAgfVxuICAgICAgICB9KSgpO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdHlwZUlkcyxcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBmb3JtOiB7XG4gICAgICAgICAgICBpZDogc3RyaW5nO1xuICAgICAgICAgICAgdGl0bGU6IHN0cmluZztcbiAgICAgICAgICAgIHRhYmxlOiBzdHJpbmc7XG4gICAgICAgICAgICBwYXJlbnRJZD86IHN0cmluZztcbiAgICAgICAgICB9O1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2VudGl0eS9jcmVhdGVcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHdhaXRGb3JITVJDb21wbGV0ZWQoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgZm9ybSB9ID0gcmVxdWVzdC5ib2R5O1xuICAgICAgICAgIGF3YWl0IFNvbmFtdS5zeW5jZXIuY3JlYXRlRW50aXR5KHsgLi4uZm9ybSwgZW50aXR5SWQ6IGZvcm0uaWQgfSk7XG5cbiAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5SWQ6IHN0cmluZztcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9lbnRpdHkvZGVsXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIHJldHVybiBhd2FpdCB3YWl0Rm9ySE1SQ29tcGxldGVkKGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCB7IGVudGl0eUlkIH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgICAgcmV0dXJuIGF3YWl0IFNvbmFtdS5zeW5jZXIuZGVsRW50aXR5KGVudGl0eUlkKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5SWQ6IHN0cmluZztcbiAgICAgICAgICBuZXdWYWx1ZXM6IHtcbiAgICAgICAgICAgIHRpdGxlOiBzdHJpbmc7XG4gICAgICAgICAgICB0YWJsZTogc3RyaW5nO1xuICAgICAgICAgICAgcGFyZW50SWQ/OiBzdHJpbmc7XG4gICAgICAgICAgfTtcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9lbnRpdHkvbW9kaWZ5RW50aXR5QmFzZVwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICByZXR1cm4gYXdhaXQgd2FpdEZvckhNUkNvbXBsZXRlZChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgeyBlbnRpdHlJZCwgbmV3VmFsdWVzIH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgIGVudGl0eS50aXRsZSA9IG5ld1ZhbHVlcy50aXRsZTtcbiAgICAgICAgICBlbnRpdHkudGFibGUgPSBuZXdWYWx1ZXMudGFibGU7XG4gICAgICAgICAgZW50aXR5LnBhcmVudElkID0gbmV3VmFsdWVzLnBhcmVudElkO1xuICAgICAgICAgIGF3YWl0IGVudGl0eS5zYXZlKCk7XG5cbiAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5SWQ6IHN0cmluZztcbiAgICAgICAgICBzdWJzZXRLZXk6IHN0cmluZztcbiAgICAgICAgICBmaWVsZHM6IHN0cmluZ1tdO1xuICAgICAgICAgIGZpZWxkc0ludGVybmFsPzogc3RyaW5nW107XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvZW50aXR5L21vZGlmeVN1YnNldFwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICByZXR1cm4gYXdhaXQgd2FpdEZvckhNUkNvbXBsZXRlZChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgeyBlbnRpdHlJZCwgc3Vic2V0S2V5LCBmaWVsZHMsIGZpZWxkc0ludGVybmFsIH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgIGVudGl0eS5zdWJzZXRzW3N1YnNldEtleV0gPSBmaWVsZHM7XG4gICAgICAgICAgaWYgKGZpZWxkc0ludGVybmFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGlmIChmaWVsZHNJbnRlcm5hbC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgIGVudGl0eS5zdWJzZXRzSW50ZXJuYWxbc3Vic2V0S2V5XSA9IGZpZWxkc0ludGVybmFsO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgZGVsZXRlIGVudGl0eS5zdWJzZXRzSW50ZXJuYWxbc3Vic2V0S2V5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYXdhaXQgZW50aXR5LnNhdmUoKTtcblxuICAgICAgICAgIHJldHVybiB7IHVwZGF0ZWQ6IGZpZWxkcywgdXBkYXRlZEludGVybmFsOiBmaWVsZHNJbnRlcm5hbCB9O1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBlbnRpdHlJZDogc3RyaW5nO1xuICAgICAgICAgIHN1YnNldEtleTogc3RyaW5nO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2VudGl0eS9kZWxTdWJzZXRcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHdhaXRGb3JITVJDb21wbGV0ZWQoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgZW50aXR5SWQsIHN1YnNldEtleSB9ID0gcmVxdWVzdC5ib2R5O1xuICAgICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKTtcbiAgICAgICAgICBkZWxldGUgZW50aXR5LnN1YnNldHNbc3Vic2V0S2V5XTtcbiAgICAgICAgICBkZWxldGUgZW50aXR5LnN1YnNldHNJbnRlcm5hbFtzdWJzZXRLZXldO1xuICAgICAgICAgIGF3YWl0IGVudGl0eS5zYXZlKCk7XG5cbiAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5SWQ6IHN0cmluZztcbiAgICAgICAgICBuZXdQcm9wOiBFbnRpdHlQcm9wO1xuICAgICAgICAgIGF0PzogbnVtYmVyO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2VudGl0eS9jcmVhdGVQcm9wXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIHJldHVybiBhd2FpdCB3YWl0Rm9ySE1SQ29tcGxldGVkKGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCB7IGVudGl0eUlkLCBhdCwgbmV3UHJvcCB9ID0gcmVxdWVzdC5ib2R5O1xuICAgICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKTtcbiAgICAgICAgICBhd2FpdCBlbnRpdHkuY3JlYXRlUHJvcChuZXdQcm9wLCBhdCk7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIGVudGl0eUlkOiBzdHJpbmc7XG4gICAgICAgICAgbmV3UHJvcDogRW50aXR5UHJvcDtcbiAgICAgICAgICBhdDogbnVtYmVyO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2VudGl0eS9tb2RpZnlQcm9wXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIHJldHVybiBhd2FpdCB3YWl0Rm9ySE1SQ29tcGxldGVkKGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCB7IGVudGl0eUlkLCBhdCwgbmV3UHJvcCB9ID0gcmVxdWVzdC5ib2R5O1xuXG4gICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgIGVudGl0eS5tb2RpZnlQcm9wKG5ld1Byb3AsIGF0KTtcblxuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBlbnRpdHlJZDogc3RyaW5nO1xuICAgICAgICAgIGF0OiBudW1iZXI7XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvZW50aXR5L2RlbFByb3BcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHdhaXRGb3JITVJDb21wbGV0ZWQoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgZW50aXR5SWQsIGF0IH0gPSByZXF1ZXN0LmJvZHk7XG5cbiAgICAgICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgICAgICAgZW50aXR5LmRlbFByb3AoYXQpO1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBlbnRpdHlJZDogc3RyaW5nO1xuICAgICAgICAgIGF0OiBudW1iZXI7XG4gICAgICAgICAgdG86IG51bWJlcjtcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9lbnRpdHkvbW92ZVByb3BcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHdhaXRGb3JITVJDb21wbGV0ZWQoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgZW50aXR5SWQsIGF0LCB0byB9ID0gcmVxdWVzdC5ib2R5O1xuXG4gICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgIGVudGl0eS5tb3ZlUHJvcChhdCwgdG8pO1xuXG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIGVudGl0eUlkOiBzdHJpbmc7XG4gICAgICAgICAgaW5kZXhlczogRW50aXR5SW5kZXhbXTtcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9lbnRpdHkvbW9kaWZ5SW5kZXhlc1wiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICByZXR1cm4gYXdhaXQgd2FpdEZvckhNUkNvbXBsZXRlZChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgeyBlbnRpdHlJZCwgaW5kZXhlcyB9ID0gcmVxdWVzdC5ib2R5O1xuICAgICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKTtcbiAgICAgICAgICBlbnRpdHkuaW5kZXhlcyA9IGluZGV4ZXM7XG4gICAgICAgICAgYXdhaXQgZW50aXR5LnNhdmUoKTtcblxuICAgICAgICAgIHJldHVybiB7IHVwZGF0ZWQ6IGluZGV4ZXMgfTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5SWQ6IHN0cmluZztcbiAgICAgICAgICBlbnVtTGFiZWxzOiBFbnRpdHlbXCJlbnVtTGFiZWxzXCJdO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2VudGl0eS9tb2RpZnlFbnVtTGFiZWxzXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIHJldHVybiBhd2FpdCB3YWl0Rm9ySE1SQ29tcGxldGVkKGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCB7IGVudGl0eUlkLCBlbnVtTGFiZWxzIH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgIGVudGl0eS5lbnVtTGFiZWxzID0gZW51bUxhYmVscztcbiAgICAgICAgICBhd2FpdCBlbnRpdHkuc2F2ZSgpO1xuXG4gICAgICAgICAgcmV0dXJuIHsgdXBkYXRlZDogZW51bUxhYmVscyB9O1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBlbnRpdHlJZDogc3RyaW5nO1xuICAgICAgICAgIG5ld0VudW1JZDogc3RyaW5nO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2VudGl0eS9jcmVhdGVFbnVtSWRcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHdhaXRGb3JITVJDb21wbGV0ZWQoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgZW50aXR5SWQsIG5ld0VudW1JZCB9ID0gcmVxdWVzdC5ib2R5O1xuICAgICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKTtcblxuICAgICAgICAgIGlmIChlbnRpdHkuZW51bUxhYmVsc1tuZXdFbnVtSWRdKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYOydtOuvuCDsobTsnqztlZjripQgZW51bUlk7J6F64uI64ukOiAke25ld0VudW1JZH1gKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBlbnRpdHkuZW51bUxhYmVsc1tuZXdFbnVtSWRdID0ge1xuICAgICAgICAgICAgLi4uKG5ld0VudW1JZC5lbmRzV2l0aChcIlN0YXR1c1wiKVxuICAgICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICAgIGFjdGl2ZTogXCLrhbjstpxcIixcbiAgICAgICAgICAgICAgICAgIGhpZGRlbjogXCLsiKjquYBcIixcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgICAgXCJcIjogXCJcIixcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICB9O1xuICAgICAgICAgIGF3YWl0IGVudGl0eS5zYXZlKCk7XG5cbiAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5SWQ6IHN0cmluZztcbiAgICAgICAgICBlbnVtSWQ6IHtcbiAgICAgICAgICAgIGJlZm9yZTogc3RyaW5nO1xuICAgICAgICAgICAgYWZ0ZXI6IHN0cmluZztcbiAgICAgICAgICB9O1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2VudGl0eS9tb2RpZnlFbnVtSWRcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHdhaXRGb3JITVJDb21wbGV0ZWQoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgZW50aXR5SWQsIGVudW1JZCB9ID0gcmVxdWVzdC5ib2R5O1xuICAgICAgICAgIGNvbnN0IGVudGl0eUlkcyA9IEVudGl0eU1hbmFnZXIuZ2V0QWxsSWRzKCk7XG4gICAgICAgICAgY29uc3QgaXNFeGlzdHMgPSBlbnRpdHlJZHMuc29tZSgoZW50aXR5SWQpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKTtcbiAgICAgICAgICAgIHJldHVybiBPYmplY3Qua2V5cyhlbnRpdHkuZW51bUxhYmVscykuaW5jbHVkZXMoZW51bUlkLmFmdGVyKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBpZiAoaXNFeGlzdHMpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihg7J2066+4IOyhtOyerO2VmOuKlCBFbnVtSWTsnoXri4jri6Q6ICR7ZW51bUlkLmFmdGVyfWApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKTtcbiAgICAgICAgICBlbnRpdHkuZW51bUxhYmVsc1tlbnVtSWQuYWZ0ZXJdID0gZW50aXR5LmVudW1MYWJlbHNbZW51bUlkLmJlZm9yZV07XG4gICAgICAgICAgZGVsZXRlIGVudGl0eS5lbnVtTGFiZWxzW2VudW1JZC5iZWZvcmVdO1xuXG4gICAgICAgICAgYXdhaXQgZW50aXR5LnNhdmUoKTtcblxuICAgICAgICAgIGZvciAoY29uc3QgZW50aXR5SWQgb2YgZW50aXR5SWRzKSB7XG4gICAgICAgICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHByb3Agb2YgZW50aXR5LnByb3BzKSB7XG4gICAgICAgICAgICAgIGlmIChwcm9wLnR5cGUgPT09IFwiZW51bVwiICYmIHByb3AuaWQgPT09IGVudW1JZC5iZWZvcmUpIHtcbiAgICAgICAgICAgICAgICBwcm9wLmlkID0gZW51bUlkLmFmdGVyO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhd2FpdCBlbnRpdHkuc2F2ZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5SWQ6IHN0cmluZztcbiAgICAgICAgICBlbnVtSWQ6IHN0cmluZztcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9lbnRpdHkvZGVsZXRlRW51bUlkXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIHJldHVybiBhd2FpdCB3YWl0Rm9ySE1SQ29tcGxldGVkKGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCB7IGVudGl0eUlkLCBlbnVtSWQgfSA9IHJlcXVlc3QuYm9keTtcblxuICAgICAgICAgIGNvbnN0IGVudGl0eUlkcyA9IEVudGl0eU1hbmFnZXIuZ2V0QWxsSWRzKCk7XG4gICAgICAgICAgY29uc3QgaXNSZWZlcmVuY2VkID0gZW50aXR5SWRzXG4gICAgICAgICAgICAuZmxhdE1hcCgoZW50aXR5SWQpID0+IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKS5wcm9wcylcbiAgICAgICAgICAgIC5zb21lKChwcm9wKSA9PiBwcm9wLnR5cGUgPT09IFwiZW51bVwiICYmIHByb3AuaWQgPT09IGVudW1JZCk7XG4gICAgICAgICAgaWYgKGlzUmVmZXJlbmNlZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2VudW1JZH3rpbwg7LC47KGw7ZWY64qUIO2UhOuhnO2NvO2LsOqwgCDsobTsnqztlanri4jri6QuYCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgIGRlbGV0ZSBlbnRpdHkuZW51bUxhYmVsc1tlbnVtSWRdO1xuICAgICAgICAgIGF3YWl0IGVudGl0eS5zYXZlKCk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIGVudGl0eUlkOiBzdHJpbmc7XG4gICAgICAgICAgdGFyZ2V0OiBcImVudGl0eVwiIHwgXCJwcm9wXCIgfCBcImVudW1cIiB8IFwic3Vic2V0XCI7XG4gICAgICAgICAgcHJvcE5hbWU/OiBzdHJpbmc7XG4gICAgICAgICAgZW51bUlkPzogc3RyaW5nO1xuICAgICAgICAgIHN1YnNldEtleT86IHN0cmluZztcbiAgICAgICAgICBjb25lOiBDb25lO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2VudGl0eS91cGRhdGVDb25lXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIHJldHVybiBhd2FpdCB3YWl0Rm9ySE1SQ29tcGxldGVkKGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCB7IGVudGl0eUlkLCB0YXJnZXQsIHByb3BOYW1lLCBlbnVtSWQsIHN1YnNldEtleSwgY29uZSB9ID0gcmVxdWVzdC5ib2R5O1xuICAgICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKTtcblxuICAgICAgICAgIGlmICh0YXJnZXQgPT09IFwiZW50aXR5XCIpIHtcbiAgICAgICAgICAgIGVudGl0eS5jb25lID0gY29uZTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHRhcmdldCA9PT0gXCJwcm9wXCIgJiYgcHJvcE5hbWUpIHtcbiAgICAgICAgICAgIGNvbnN0IHByb3AgPSBlbnRpdHkucHJvcHMuZmluZCgocCkgPT4gcC5uYW1lID09PSBwcm9wTmFtZSk7XG4gICAgICAgICAgICBpZiAocHJvcCkge1xuICAgICAgICAgICAgICAocHJvcCBhcyB7IGNvbmU/OiBDb25lIH0pLmNvbmUgPSBjb25lO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSBpZiAodGFyZ2V0ID09PSBcImVudW1cIiAmJiBlbnVtSWQpIHtcbiAgICAgICAgICAgIGVudGl0eS5lbnVtQ29uZXNbZW51bUlkXSA9IGNvbmU7XG4gICAgICAgICAgfSBlbHNlIGlmICh0YXJnZXQgPT09IFwic3Vic2V0XCIgJiYgc3Vic2V0S2V5KSB7XG4gICAgICAgICAgICBlbnRpdHkuc3Vic2V0Q29uZXNbc3Vic2V0S2V5XSA9IGNvbmU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYXdhaXQgZW50aXR5LnNhdmUoKTtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5SWQ6IHN0cmluZztcbiAgICAgICAgICBwcmVzZXJ2ZUV4aXN0aW5nPzogYm9vbGVhbjtcbiAgICAgICAgICBvbmx5RW1wdHk/OiBib29sZWFuO1xuICAgICAgICAgIGxvY2FsZT86IFwia29cIiB8IFwiZW5cIiB8IFwiamFcIjtcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9lbnRpdHkvZ2VuZXJhdGVDb25lc1wiLCBhc3luYyAocmVxdWVzdCwgcmVwbHkpID0+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHdhaXRGb3JITVJDb21wbGV0ZWQoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgZW50aXR5SWQsIHByZXNlcnZlRXhpc3RpbmcsIG9ubHlFbXB0eSwgbG9jYWxlIH0gPSByZXF1ZXN0LmJvZHk7XG5cbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gRW50aXR5IOyhtOyerCDsl6zrtoAg7ZmV7J24XG4gICAgICAgICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG5cbiAgICAgICAgICAgIC8vIGxvY2FsZSDquLDrs7jqsJI6IFNvbmFtdS5jb25maWcuaTE4bi5kZWZhdWx0TG9jYWxlIOyCrOyaqVxuICAgICAgICAgICAgY29uc3QgZWZmZWN0aXZlTG9jYWxlID1cbiAgICAgICAgICAgICAgbG9jYWxlID8/IChTb25hbXUuY29uZmlnLmkxOG4uZGVmYXVsdExvY2FsZSBhcyBcImtvXCIgfCBcImVuXCIgfCBcImphXCIpO1xuXG4gICAgICAgICAgICAvLyBDb25lIOyDneyEsVxuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZW50aXR5LmdlbmVyYXRlQ29uZXMoe1xuICAgICAgICAgICAgICBwcmVzZXJ2ZUV4aXN0aW5nOiBwcmVzZXJ2ZUV4aXN0aW5nID8/IHRydWUsXG4gICAgICAgICAgICAgIG9ubHlFbXB0eTogb25seUVtcHR5ID8/IGZhbHNlLFxuICAgICAgICAgICAgICBsb2NhbGU6IGVmZmVjdGl2ZUxvY2FsZSxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICAgICAgICBjb25zdCBtZXNzYWdlID0gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpO1xuXG4gICAgICAgICAgICAvLyBFbnRpdHkgbm90IGZvdW5kXG4gICAgICAgICAgICBpZiAobWVzc2FnZS5pbmNsdWRlcyhcIuyhtOyerO2VmOyngCDslYrripQgRW50aXR5XCIpKSB7XG4gICAgICAgICAgICAgIHJlcGx5LnN0YXR1cyg0MDQpO1xuICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGVycm9yOiBgRW50aXR5IG5vdCBmb3VuZDogJHtlbnRpdHlJZH1gLFxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBBUEkg7YKkIOyXhuydjFxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuaW5jbHVkZXMoXCJBTlRIUk9QSUNfQVBJX0tFWSBub3QgZm91bmRcIikpIHtcbiAgICAgICAgICAgICAgcmVwbHkuc3RhdHVzKDUwMCk7XG4gICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgICAgICAgICAgZXJyb3I6IFwiQVBJIGtleSBub3QgY29uZmlndXJlZFwiLFxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBSYXRlIGxpbWl0XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5pbmNsdWRlcyhcIlJhdGUgbGltaXQgZXhjZWVkZWRcIikpIHtcbiAgICAgICAgICAgICAgcmVwbHkuc3RhdHVzKDQyOSk7XG4gICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgICAgICAgICAgZXJyb3I6IFwiUmF0ZSBsaW1pdCBleGNlZWRlZC4gUGxlYXNlIHRyeSBhZ2FpbiBsYXRlci5cIixcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8g6riw7YOAIOyXkOufrFxuICAgICAgICAgICAgcmVwbHkuc3RhdHVzKDUwMCk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgICAgICAgICAgZXJyb3I6IGBDb25lIGdlbmVyYXRpb24gZmFpbGVkOiAke21lc3NhZ2V9YCxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIuZ2V0PHtcbiAgICAgICAgUXVlcnlzdHJpbmc6IHtcbiAgICAgICAgICBlbnRpdHlJZDogc3RyaW5nO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2VudGl0eS9nZXRUYWJsZUNvbHVtbnNcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgeyBlbnRpdHlJZCB9ID0gcmVxdWVzdC5xdWVyeTtcbiAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICBjb25zdCBjb2x1bW5zID0gZW50aXR5LmdldFRhYmxlQ29sdW1ucygpO1xuICAgICAgICByZXR1cm4geyBjb2x1bW5zIH07XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLmdldChcIi9hcGkvbWlncmF0aW9ucy9zdGF0dXNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBzdGF0dXMgPSBhd2FpdCBtaWdyYXRvci5nZXRTdGF0dXMoKTtcblxuICAgICAgICByZXR1cm4geyBzdGF0dXMgfTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBhY3Rpb246IFwiYXBwbHlcIiB8IFwicm9sbGJhY2tcIiB8IFwic2hhZG93XCI7XG4gICAgICAgICAgdGFyZ2V0czogKGtleW9mIFNvbmFtdURCQ29uZmlnKVtdO1xuICAgICAgICAgIGZvcmNlPzogYm9vbGVhbjtcbiAgICAgICAgICBmb3JjZVJlYXNvbj86IHN0cmluZztcbiAgICAgICAgICByZXF1ZXN0b3I/OiBzdHJpbmc7XG4gICAgICAgIH07XG4gICAgICB9PihcbiAgICAgICAgXCIvYXBpL21pZ3JhdGlvbnMvcnVuQWN0aW9uXCIsXG4gICAgICAgIGFzeW5jIChyZXF1ZXN0KTogUHJvbWlzZTxNaWdyYXRpb25SZXN1bHQgfCBTbGFja0NvbmZpcm1QZW5kaW5nUmVzdWx0PiA9PiB7XG4gICAgICAgICAgY29uc3QgeyBhY3Rpb24sIHRhcmdldHMsIGZvcmNlLCBmb3JjZVJlYXNvbiwgcmVxdWVzdG9yIH0gPSByZXF1ZXN0LmJvZHk7XG5cbiAgICAgICAgICBpZiAoYWN0aW9uID09PSBcInNoYWRvd1wiKSB7XG4gICAgICAgICAgICByZXR1cm4gbWlncmF0b3IucnVuU2hhZG93VGVzdCgpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIFNsYWNrIOyKueyduCDssrTtgawgKGFwcGx5IOyLnOyXkOunjClcbiAgICAgICAgICBpZiAoYWN0aW9uID09PSBcImFwcGx5XCIpIHtcbiAgICAgICAgICAgIGNvbnN0IHNsYWNrQ29uZmlybSA9IG5ldyBTbGFja0NvbmZpcm0oKTtcbiAgICAgICAgICAgIGNvbnN0IHJlcXVpcmVzQXBwcm92YWwgPSB0YXJnZXRzLnNvbWUoKHQpID0+IHNsYWNrQ29uZmlybS5pc1RhcmdldFJlcXVpcmVzQXBwcm92YWwodCkpO1xuXG4gICAgICAgICAgICAvLyDroZzsu6wgRELsnbgg6rK97JqwIOyKueyduCDsiqTtgrVcbiAgICAgICAgICAgIGNvbnN0IGxvY2FsSG9zdHMgPSBbXCJsb2NhbGhvc3RcIiwgXCIxMjcuMC4wLjFcIiwgXCIwLjAuMC4wXCIsIFwiOjoxXCJdO1xuICAgICAgICAgICAgY29uc3QgaXNMb2NhbFRhcmdldCA9IHRhcmdldHMuZXZlcnkoKHRhcmdldCkgPT4ge1xuICAgICAgICAgICAgICBjb25zdCB0YXJnZXRDb25maWcgPSBTb25hbXUuZGJDb25maWdbdGFyZ2V0XTtcbiAgICAgICAgICAgICAgY29uc3QgaG9zdCA9ICh0YXJnZXRDb25maWc/LmNvbm5lY3Rpb24gYXMgeyBob3N0Pzogc3RyaW5nIH0pPy5ob3N0ID8/IFwibG9jYWxob3N0XCI7XG4gICAgICAgICAgICAgIHJldHVybiBsb2NhbEhvc3RzLmluY2x1ZGVzKGhvc3QudG9Mb3dlckNhc2UoKSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYgKHJlcXVpcmVzQXBwcm92YWwgJiYgc2xhY2tDb25maXJtLmlzQ29uZmlndXJlZCgpICYmICFpc0xvY2FsVGFyZ2V0KSB7XG4gICAgICAgICAgICAgIGNvbnN0IHsgY29ubnMgfSA9IGF3YWl0IG1pZ3JhdG9yLmdldFN0YXR1cygpO1xuXG4gICAgICAgICAgICAgIC8vIOuqqOuToCDtg4Dqsp8gRELsl5DshJwgcGVuZGluZ+yduCDrp4jsnbTqt7jroIjsnbTshZjsnZgg7ZWp7KeR7ZWp7J2EIOq1rO2VqeuLiOuLpC5cbiAgICAgICAgICAgICAgY29uc3QgcGVuZGluZ01pZ3JhdGlvbnMgPSBbXG4gICAgICAgICAgICAgICAgLi4ubmV3IFNldChcbiAgICAgICAgICAgICAgICAgIGNvbm5zXG4gICAgICAgICAgICAgICAgICAgIC5maWx0ZXIoKGNvbm4pID0+IHRhcmdldHMuaW5jbHVkZXMoY29ubi5jb25uS2V5IGFzIGtleW9mIFNvbmFtdURCQ29uZmlnKSlcbiAgICAgICAgICAgICAgICAgICAgLmZsYXRNYXAoKGNvbm4pID0+IGNvbm4ucGVuZGluZyksXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgXTtcblxuICAgICAgICAgICAgICBpZiAocGVuZGluZ01pZ3JhdGlvbnMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIC8vIOq4sOyhtCDsirnsnbgg7JqU7LKtIO2ZleyduFxuICAgICAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nID0gYXdhaXQgc2xhY2tDb25maXJtLmdldEV4aXN0aW5nUmVxdWVzdChwZW5kaW5nTWlncmF0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgICAgICAgICAgICAgIC8vIOq4sOyhtCDsmpTssq3snbQg7J6I7Jy866m0IOyKueyduCDsg4Htg5wg7ZmV7J24XG4gICAgICAgICAgICAgICAgICBjb25zdCB7IGFwcHJvdmVkLCByZWplY3RlZCB9ID0gYXdhaXQgc2xhY2tDb25maXJtLmNoZWNrQXBwcm92YWwoXG4gICAgICAgICAgICAgICAgICAgIGV4aXN0aW5nLmNoYW5uZWwsXG4gICAgICAgICAgICAgICAgICAgIGV4aXN0aW5nLnRzLFxuICAgICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgICAgaWYgKGFwcHJvdmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIOyKueyduOuQqCDihpIg7Iuk7ZaJXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IG1pZ3JhdG9yLnJ1bkFjdGlvbihhY3Rpb24sIHRhcmdldHMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBzbGFja0NvbmZpcm0ubG9nRXhlY3V0aW9uKFxuICAgICAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmcuY2hhbm5lbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4aXN0aW5nLnRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdG9yLFxuICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocmVqZWN0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oU0QoXCJzb25hbXUuZXJyb3IubWlncmF0aW9uUmVqZWN0ZWRcIikpO1xuICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChmb3JjZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBGb3JjZSDsp4TtlolcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgc2xhY2tDb25maXJtLmZvcmNlQXBwcm92YWwoXG4gICAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmcuY2hhbm5lbCxcbiAgICAgICAgICAgICAgICAgICAgICBleGlzdGluZy50cyxcbiAgICAgICAgICAgICAgICAgICAgICBmb3JjZVJlYXNvbiA/PyBcIuyCrOycoCDsl4bsnYxcIixcbiAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0b3IsXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IG1pZ3JhdG9yLnJ1bkFjdGlvbihhY3Rpb24sIHRhcmdldHMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBzbGFja0NvbmZpcm0ubG9nRXhlY3V0aW9uKFxuICAgICAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmcuY2hhbm5lbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4aXN0aW5nLnRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdG9yLFxuICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIOuMgOq4sOykkVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwicGVuZGluZ1wiLFxuICAgICAgICAgICAgICAgICAgICAgIGNoYW5uZWw6IGV4aXN0aW5nLmNoYW5uZWwsXG4gICAgICAgICAgICAgICAgICAgICAgdHM6IGV4aXN0aW5nLnRzLFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAvLyDsg4gg7Iq57J24IOyalOyyrSDrsJzshqFcbiAgICAgICAgICAgICAgICAgIGNvbnN0IHsgY2hhbm5lbCwgdHMgfSA9IGF3YWl0IHNsYWNrQ29uZmlybS5wb3N0QXBwcm92YWxSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICAgICBwZW5kaW5nTWlncmF0aW9ucyxcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0cyxcbiAgICAgICAgICAgICAgICAgICAgcmVxdWVzdG9yLFxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIGF3YWl0IHNsYWNrQ29uZmlybS5zYXZlUmVxdWVzdChwZW5kaW5nTWlncmF0aW9ucywgY2hhbm5lbCwgdHMpO1xuXG4gICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiBcInBlbmRpbmdcIixcbiAgICAgICAgICAgICAgICAgICAgY2hhbm5lbCxcbiAgICAgICAgICAgICAgICAgICAgdHMsXG4gICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBtaWdyYXRvci5ydW5BY3Rpb24oYWN0aW9uLCB0YXJnZXRzKTtcbiAgICAgICAgfSxcbiAgICAgICk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIGNoYW5uZWw6IHN0cmluZztcbiAgICAgICAgICB0czogc3RyaW5nO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL21pZ3JhdGlvbnMvY2hlY2tBcHByb3ZhbFwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICBjb25zdCB7IGNoYW5uZWwsIHRzIH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgIGNvbnN0IHNsYWNrQ29uZmlybSA9IG5ldyBTbGFja0NvbmZpcm0oKTtcblxuICAgICAgICBpZiAoIXNsYWNrQ29uZmlybS5pc0NvbmZpZ3VyZWQoKSkge1xuICAgICAgICAgIHJldHVybiB7IGFwcHJvdmVkOiB0cnVlLCByZWplY3RlZDogZmFsc2UgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzbGFja0NvbmZpcm0uY2hlY2tBcHByb3ZhbChjaGFubmVsLCB0cyk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgY2hhbm5lbDogc3RyaW5nO1xuICAgICAgICAgIHRzOiBzdHJpbmc7XG4gICAgICAgICAgcmVhc29uOiBzdHJpbmc7XG4gICAgICAgICAgcmVxdWVzdG9yPzogc3RyaW5nO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL21pZ3JhdGlvbnMvZm9yY2VBcHByb3ZhbFwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICBjb25zdCB7IGNoYW5uZWwsIHRzLCByZWFzb24sIHJlcXVlc3RvciB9ID0gcmVxdWVzdC5ib2R5O1xuICAgICAgICBjb25zdCBzbGFja0NvbmZpcm0gPSBuZXcgU2xhY2tDb25maXJtKCk7XG5cbiAgICAgICAgaWYgKCFzbGFja0NvbmZpcm0uaXNDb25maWd1cmVkKCkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihTRChcInNvbmFtdS5lcnJvci5zbGFja0NvbmZpcm1Ob3RDb25maWd1cmVkXCIpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGF3YWl0IHNsYWNrQ29uZmlybS5mb3JjZUFwcHJvdmFsKGNoYW5uZWwsIHRzLCByZWFzb24sIHJlcXVlc3Rvcik7XG4gICAgICAgIHJldHVybiB7IHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBjb2RlTmFtZXM6IHN0cmluZ1tdO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL21pZ3JhdGlvbnMvZGVsQ29kZXNcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgeyBjb2RlTmFtZXMgfSA9IHJlcXVlc3QuYm9keTtcbiAgICAgICAgcmV0dXJuIGF3YWl0IG1pZ3JhdG9yLmRlbENvZGVzKGNvZGVOYW1lcyk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3QoXCIvYXBpL21pZ3JhdGlvbnMvZ2VuZXJhdGVQcmVwYXJlZENvZGVzXCIsIGFzeW5jIChfcmVxdWVzdHQpID0+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IG1pZ3JhdG9yLmdlbmVyYXRlUHJlcGFyZWRDb2RlcygpO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIGVudGl0eUlkczogc3RyaW5nW107XG4gICAgICAgICAgdGVtcGxhdGVLZXlzOiBzdHJpbmdbXTtcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9zY2FmZm9sZGluZy9nZXRTdGF0dXNcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgeyBlbnRpdHlJZHMsIHRlbXBsYXRlS2V5czogX3RlbXBsYXRlS2V5cyB9ID0gcmVxdWVzdC5ib2R5O1xuICAgICAgICBpZiAoKGVudGl0eUlkcyA/PyBbXSkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oU0QoXCJzb25hbXUuZXJyb3IuZW50aXR5SWRzUmVxdWlyZWRcIikpO1xuICAgICAgICB9IGVsc2UgaWYgKChfdGVtcGxhdGVLZXlzID8/IFtdKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihTRChcInNvbmFtdS5lcnJvci50ZW1wbGF0ZUtleXNSZXF1aXJlZFwiKSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzb3J0aW5nXG4gICAgICAgIGVudGl0eUlkcy5zb3J0KChhLCBiKSA9PiAoYSA8IGIgPyAtMSA6IGEgPiBiID8gMSA6IDApKTtcbiAgICAgICAgY29uc3QgdGVtcGxhdGVLZXlzID0gVGVtcGxhdGVLZXkub3B0aW9ucy5maWx0ZXIoKHRrKSA9PiBfdGVtcGxhdGVLZXlzLmluY2x1ZGVzKHRrKSk7XG5cbiAgICAgICAgY29uc3QgY29tYmluYXRpb25zID0gZW50aXR5SWRzLmZsYXRNYXAoKGVudGl0eUlkKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHRlbXBsYXRlS2V5cy5tYXAoKHRlbXBsYXRlS2V5KSA9PiBbZW50aXR5SWQsIHRlbXBsYXRlS2V5XSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHN0YXR1c2VzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgY29tYmluYXRpb25zLm1hcChhc3luYyAoW2VudGl0eUlkLCB0ZW1wbGF0ZUtleV0pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHsgc3ViUGF0aCwgZnVsbFBhdGgsIGlzRXhpc3RzIH0gPSBhd2FpdCBTb25hbXUuc3luY2VyLmNoZWNrRXhpc3RzR2VuQ29kZShcbiAgICAgICAgICAgICAgZW50aXR5SWQsXG4gICAgICAgICAgICAgIHRlbXBsYXRlS2V5IGFzIFRlbXBsYXRlS2V5LFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIGVudGl0eUlkLFxuICAgICAgICAgICAgICB0ZW1wbGF0ZUtleSxcbiAgICAgICAgICAgICAgc3ViUGF0aCxcbiAgICAgICAgICAgICAgZnVsbFBhdGgsXG4gICAgICAgICAgICAgIGlzRXhpc3RzLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9KSxcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHsgc3RhdHVzZXMgfTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICBlbnRpdHlJZDogc3RyaW5nO1xuICAgICAgICAgICAgdGVtcGxhdGVLZXk6IHN0cmluZztcbiAgICAgICAgICAgIGVudW1JZD86IHN0cmluZztcbiAgICAgICAgICAgIG92ZXJ3cml0ZT86IGJvb2xlYW47XG4gICAgICAgICAgfVtdO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL3NjYWZmb2xkaW5nL2dlbmVyYXRlXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgb3B0aW9ucyB9ID0gcmVxdWVzdC5ib2R5O1xuICAgICAgICBpZiAob3B0aW9ucy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihTRChcInNvbmFtdS5lcnJvci5vcHRpb25zUmVxdWlyZWRcIikpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gMS4g66qo65OgIO2FnO2UjOumv+yXkOyEnCDtlYTsmpTtlZwgZGljdCDtgqTrpbwg7IiY7KeRXG4gICAgICAgIGNvbnN0IGtleXMgPSBvcHRpb25zLmZsYXRNYXAoKHsgdGVtcGxhdGVLZXkgfSkgPT4ge1xuICAgICAgICAgIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGVNYW5hZ2VyLmdldCh0ZW1wbGF0ZUtleSk7XG4gICAgICAgICAgcmV0dXJuIHRlbXBsYXRlLmdldFJlcXVpcmVkRGljdEtleXMoKSA/PyBbXTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gMi4gdGFyZ2V067OE66GcIGVuc3VyZURpY3RLZXlzIO2YuOy2nCAo7Iic7LCoIOyymOumrClcbiAgICAgICAgYXdhaXQgc29uYW11RGljdGlvbmFyeS5lbnN1cmVEaWN0S2V5cyhbLi4ubmV3IFNldChrZXlzKV0pO1xuXG4gICAgICAgIC8vIDMuIO2FnO2UjOumvyDsg53shLEgKOuzkeugrCDsspjrpqwpXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICAgIG9wdGlvbnMubWFwKGFzeW5jICh7IGVudGl0eUlkLCB0ZW1wbGF0ZUtleSwgZW51bUlkLCBvdmVyd3JpdGUgfSkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgcmV0dXJuIGF3YWl0IFNvbmFtdS5zeW5jZXIuZ2VuZXJhdGVUZW1wbGF0ZShcbiAgICAgICAgICAgICAgICB0ZW1wbGF0ZUtleSBhcyBUZW1wbGF0ZUtleSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBlbnRpdHlJZCxcbiAgICAgICAgICAgICAgICAgIGVudW1JZCxcbiAgICAgICAgICAgICAgICB9IGFzIHtcbiAgICAgICAgICAgICAgICAgIGVudGl0eUlkOiBzdHJpbmc7XG4gICAgICAgICAgICAgICAgICBlbnVtSWQ/OiBzdHJpbmc7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBvdmVyd3JpdGUsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgaWYgKGlzU29FeGNlcHRpb24oZSkgJiYgZS5zdGF0dXNDb2RlID09PSA1NDEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KSxcbiAgICAgICAgKTtcblxuICAgICAgICBpZiAocmVzdWx0LmZpbHRlcihub25OdWxsYWJsZSkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFNlcnZpY2VVbmF2YWlsYWJsZUV4Y2VwdGlvbihTRChcInNvbmFtdS5lcnJvci5hbGxGaWxlc0dlbmVyYXRlZFwiKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBvcHRpb246IHtcbiAgICAgICAgICAgIGVudGl0eUlkOiBzdHJpbmc7XG4gICAgICAgICAgICB0ZW1wbGF0ZUtleTogc3RyaW5nO1xuICAgICAgICAgICAgZW51bUlkPzogc3RyaW5nO1xuICAgICAgICAgIH07XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvc2NhZmZvbGRpbmcvcHJldmlld1wiLCBhc3luYyAocmVxdWVzdCk6IFByb21pc2U8eyBwYXRoQW5kQ29kZXM6IFBhdGhBbmRDb2RlW10gfT4gPT4ge1xuICAgICAgICBjb25zdCB7IG9wdGlvbiB9ID0gcmVxdWVzdC5ib2R5O1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgeyB0ZW1wbGF0ZUtleSwgLi4udGVtcGxhdGVPcHRpb25zIH0gPSBvcHRpb247XG4gICAgICAgICAgY29uc3QgcGF0aEFuZENvZGVzID0gYXdhaXQgU29uYW11LnN5bmNlci5yZW5kZXJUZW1wbGF0ZShcbiAgICAgICAgICAgIHRlbXBsYXRlS2V5IGFzIFRlbXBsYXRlS2V5LFxuICAgICAgICAgICAgdGVtcGxhdGVPcHRpb25zLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICByZXR1cm4geyBwYXRoQW5kQ29kZXMgfTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0KFwiL2FwaS9maXh0dXJlXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgc291cmNlREIsIHRhcmdldERCLCBzZWFyY2gsIGR1cGxpY2F0ZUNoZWNrIH0gPSByZXF1ZXN0LmJvZHkgYXMge1xuICAgICAgICAgIHNvdXJjZURCOiBrZXlvZiBTb25hbXVEQkNvbmZpZztcbiAgICAgICAgICB0YXJnZXREQjoga2V5b2YgU29uYW11REJDb25maWc7XG4gICAgICAgICAgc2VhcmNoOiBGaXh0dXJlU2VhcmNoT3B0aW9ucztcbiAgICAgICAgICBkdXBsaWNhdGVDaGVjaz86IER1cGxpY2F0ZUNoZWNrT3B0aW9ucztcbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4gRml4dHVyZU1hbmFnZXIuZ2V0Rml4dHVyZXMoc291cmNlREIsIHRhcmdldERCLCBzZWFyY2gsIGR1cGxpY2F0ZUNoZWNrKTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdChcIi9hcGkvZml4dHVyZS9pbXBvcnRcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgeyBkYiwgZml4dHVyZXMgfSA9IHJlcXVlc3QuYm9keSBhcyB7XG4gICAgICAgICAgZGI6IGtleW9mIFNvbmFtdURCQ29uZmlnO1xuICAgICAgICAgIGZpeHR1cmVzOiBGaXh0dXJlUmVjb3JkW107XG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIEZpeHR1cmVNYW5hZ2VyLmluc2VydEZpeHR1cmVzKGRiLCBmaXh0dXJlcyk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3QoXCIvYXBpL2ZpeHR1cmUvYWRkRml4dHVyZUxvYWRlclwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICBjb25zdCB7IGNvZGUgfSA9IHJlcXVlc3QuYm9keSBhcyB7IGNvZGU6IHN0cmluZyB9O1xuXG4gICAgICAgIHJldHVybiBGaXh0dXJlTWFuYWdlci5hZGRGaXh0dXJlTG9hZGVyKGNvZGUpO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5nZXQoXCIvYXBpL2kxOG4vZGljdGlvbmFyeVwiLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIHJldHVybiBzb25hbXVEaWN0aW9uYXJ5LmdldERpY3Rpb25hcnkoKTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIuZ2V0KFwiL2FwaS9pMThuL2V4cG9ydFwiLCBhc3luYyAoX3JlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgZmlsZW5hbWUsIGJ1ZmZlciB9ID0gYXdhaXQgc29uYW11RGljdGlvbmFyeS5leHBvcnRUb0V4Y2VsKCk7XG4gICAgICAgIHJlcGx5XG4gICAgICAgICAgLmhlYWRlcihcbiAgICAgICAgICAgIFwiQ29udGVudC1UeXBlXCIsXG4gICAgICAgICAgICBcImFwcGxpY2F0aW9uL3ZuZC5vcGVueG1sZm9ybWF0cy1vZmZpY2Vkb2N1bWVudC5zcHJlYWRzaGVldG1sLnNoZWV0XCIsXG4gICAgICAgICAgKVxuICAgICAgICAgIC5oZWFkZXIoXCJDb250ZW50LURpc3Bvc2l0aW9uXCIsIGBhdHRhY2htZW50OyBmaWxlbmFtZT1cIiR7ZmlsZW5hbWV9XCJgKVxuICAgICAgICAgIC5zZW5kKGJ1ZmZlcik7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3QoXCIvYXBpL2kxOG4vaW1wb3J0XCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCByZXF1ZXN0LmZpbGUoKTtcbiAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oU0QoXCJzb25hbXUuZXJyb3IuZmlsZU5vdFVwbG9hZGVkXCIpKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBidWZmZXIgPSBhd2FpdCBkYXRhLnRvQnVmZmVyKCk7XG4gICAgICAgIHJldHVybiBzb25hbXVEaWN0aW9uYXJ5LmltcG9ydEZyb21FeGNlbChidWZmZXIpO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIG9sZEtleTogc3RyaW5nO1xuICAgICAgICAgIG5ld0tleTogc3RyaW5nO1xuICAgICAgICAgIHNvdXJjZTogXCJlbnRpdHlcIiB8IFwicHJvamVjdFwiIHwgXCJzb25hbXVcIjtcbiAgICAgICAgICB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvaTE4bi91cGRhdGVcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgYXdhaXQgc29uYW11RGljdGlvbmFyeS51cGRhdGVFbnRyeShyZXF1ZXN0LmJvZHkpO1xuICAgICAgICByZXR1cm4geyBzdWNjZXNzOiB0cnVlIH07XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAga2V5OiBzdHJpbmc7XG4gICAgICAgICAgdmFsdWVzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2kxOG4vY3JlYXRlXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGF3YWl0IHNvbmFtdURpY3Rpb25hcnkuY3JlYXRlRW50cnkocmVxdWVzdC5ib2R5KTtcbiAgICAgICAgcmV0dXJuIHsgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIGtleTogc3RyaW5nO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2kxOG4vZGVsZXRlXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGF3YWl0IHNvbmFtdURpY3Rpb25hcnkuZGVsZXRlRW50cnkocmVxdWVzdC5ib2R5LmtleSk7XG4gICAgICAgIHJldHVybiB7IHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7IEJvZHk6IHsga2V5czogc3RyaW5nW10gfSB9PihcIi9hcGkvaTE4bi9jaGVja1VzYWdlXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIHJldHVybiBzb25hbXVEaWN0aW9uYXJ5LmNoZWNrVXNhZ2UocmVxdWVzdC5ib2R5LmtleXMpO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIFRhc2tzIEFQSVxuICAgICAgc2VydmVyLmdldChcIi9hcGkvdGFza3Mvc3RhdHVzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBTb25hbXUud29ya2Zsb3dzO1xuICAgICAgICAgIHJldHVybiB7IGFjdGl2ZTogdHJ1ZSB9O1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICByZXR1cm4geyBhY3RpdmU6IGZhbHNlIH07XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIuZ2V0KFwiL2FwaS90YXNrcy93b3JrZmxvd0RlZmluaXRpb25zXCIsIGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3QgZGVmaW5pdGlvbnMgPSBTb25hbXUud29ya2Zsb3dzLndvcmtmbG93RGVmaW5pdGlvbnM7XG4gICAgICAgIHJldHVybiB7IGRlZmluaXRpb25zIH07XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLmdldDx7XG4gICAgICAgIFF1ZXJ5c3RyaW5nOiB7XG4gICAgICAgICAgbGltaXQ/OiBzdHJpbmc7XG4gICAgICAgICAgYWZ0ZXI/OiBzdHJpbmc7XG4gICAgICAgICAgYmVmb3JlPzogc3RyaW5nO1xuICAgICAgICAgIG9yZGVyPzogXCJhc2NcIiB8IFwiZGVzY1wiO1xuICAgICAgICAgIHN0YXR1cz86IHN0cmluZztcbiAgICAgICAgICB3b3JrZmxvd05hbWU/OiBzdHJpbmc7XG4gICAgICAgICAgY3JlYXRlZEFmdGVyPzogc3RyaW5nO1xuICAgICAgICAgIGNyZWF0ZWRCZWZvcmU/OiBzdHJpbmc7XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvdGFza3Mvd29ya2Zsb3dSdW5zXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGNvbnN0IGJhY2tlbmQgPSBTb25hbXUud29ya2Zsb3dzLmJhY2tlbmQ7XG4gICAgICAgIGNvbnN0IHsgbGltaXQsIGFmdGVyLCBiZWZvcmUsIG9yZGVyLCBzdGF0dXMsIHdvcmtmbG93TmFtZSwgY3JlYXRlZEFmdGVyLCBjcmVhdGVkQmVmb3JlIH0gPVxuICAgICAgICAgIHJlcXVlc3QucXVlcnk7XG4gICAgICAgIHJldHVybiBiYWNrZW5kLmxpc3RXb3JrZmxvd1J1bnMoe1xuICAgICAgICAgIGxpbWl0OiBsaW1pdCA/IE51bWJlci5wYXJzZUludChsaW1pdCwgMTApIDogdW5kZWZpbmVkLFxuICAgICAgICAgIGFmdGVyLFxuICAgICAgICAgIGJlZm9yZSxcbiAgICAgICAgICBvcmRlcixcbiAgICAgICAgICBzdGF0dXM6IHN0YXR1cyA/IHN0YXR1cy5zcGxpdChcIixcIikgOiB1bmRlZmluZWQsXG4gICAgICAgICAgd29ya2Zsb3dOYW1lOiB3b3JrZmxvd05hbWUgfHwgdW5kZWZpbmVkLFxuICAgICAgICAgIGNyZWF0ZWRBZnRlcjogY3JlYXRlZEFmdGVyID8gbmV3IERhdGUoY3JlYXRlZEFmdGVyKSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICBjcmVhdGVkQmVmb3JlOiBjcmVhdGVkQmVmb3JlID8gbmV3IERhdGUoY3JlYXRlZEJlZm9yZSkgOiB1bmRlZmluZWQsXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5nZXQ8e1xuICAgICAgICBQYXJhbXM6IHsgaWQ6IHN0cmluZyB9O1xuICAgICAgfT4oXCIvYXBpL3Rhc2tzL3dvcmtmbG93UnVucy86aWRcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgYmFja2VuZCA9IFNvbmFtdS53b3JrZmxvd3MuYmFja2VuZDtcbiAgICAgICAgY29uc3Qgd29ya2Zsb3dSdW4gPSBhd2FpdCBiYWNrZW5kLmdldFdvcmtmbG93UnVuKHtcbiAgICAgICAgICB3b3JrZmxvd1J1bklkOiByZXF1ZXN0LnBhcmFtcy5pZCxcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICghd29ya2Zsb3dSdW4pIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFdvcmtmbG93IHJ1biBub3QgZm91bmQ6ICR7cmVxdWVzdC5wYXJhbXMuaWR9YCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHdvcmtmbG93UnVuO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgUGFyYW1zOiB7IGlkOiBzdHJpbmcgfTtcbiAgICAgIH0+KFwiL2FwaS90YXNrcy93b3JrZmxvd1J1bnMvOmlkL2NhbmNlbFwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICBjb25zdCBiYWNrZW5kID0gU29uYW11LndvcmtmbG93cy5iYWNrZW5kO1xuICAgICAgICByZXR1cm4gYmFja2VuZC5jYW5jZWxXb3JrZmxvd1J1bih7XG4gICAgICAgICAgd29ya2Zsb3dSdW5JZDogcmVxdWVzdC5wYXJhbXMuaWQsXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgUGFyYW1zOiB7IGlkOiBzdHJpbmcgfTtcbiAgICAgIH0+KFwiL2FwaS90YXNrcy93b3JrZmxvd1J1bnMvOmlkL3BhdXNlXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGNvbnN0IGJhY2tlbmQgPSBTb25hbXUud29ya2Zsb3dzLmJhY2tlbmQ7XG4gICAgICAgIHJldHVybiBiYWNrZW5kLnBhdXNlV29ya2Zsb3dSdW4oe1xuICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJlcXVlc3QucGFyYW1zLmlkLFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIFBhcmFtczogeyBpZDogc3RyaW5nIH07XG4gICAgICB9PihcIi9hcGkvdGFza3Mvd29ya2Zsb3dSdW5zLzppZC9yZXN1bWVcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgYmFja2VuZCA9IFNvbmFtdS53b3JrZmxvd3MuYmFja2VuZDtcbiAgICAgICAgcmV0dXJuIGJhY2tlbmQucmVzdW1lV29ya2Zsb3dSdW4oe1xuICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJlcXVlc3QucGFyYW1zLmlkLFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIuZ2V0PHtcbiAgICAgICAgUGFyYW1zOiB7IGlkOiBzdHJpbmcgfTtcbiAgICAgICAgUXVlcnlzdHJpbmc6IHtcbiAgICAgICAgICBsaW1pdD86IHN0cmluZztcbiAgICAgICAgICBhZnRlcj86IHN0cmluZztcbiAgICAgICAgICBiZWZvcmU/OiBzdHJpbmc7XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvdGFza3Mvd29ya2Zsb3dSdW5zLzppZC9zdGVwc1wiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICBjb25zdCBiYWNrZW5kID0gU29uYW11LndvcmtmbG93cy5iYWNrZW5kO1xuICAgICAgICBjb25zdCB7IGxpbWl0LCBhZnRlciwgYmVmb3JlIH0gPSByZXF1ZXN0LnF1ZXJ5O1xuICAgICAgICByZXR1cm4gYmFja2VuZC5saXN0U3RlcEF0dGVtcHRzKHtcbiAgICAgICAgICB3b3JrZmxvd1J1bklkOiByZXF1ZXN0LnBhcmFtcy5pZCxcbiAgICAgICAgICBsaW1pdDogbGltaXQgPyBOdW1iZXIucGFyc2VJbnQobGltaXQsIDEwKSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICBhZnRlcixcbiAgICAgICAgICBiZWZvcmUsXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIC8qKlxuICAgICAgICogSGVhbHRoIENoZWNrIEFQSVxuICAgICAgICogTUNQIOuPhOq1rOqwgCBTb25hbXUg7ISc67KE66W8IOyekOuPmSDqsJDsp4DtlZjquLAg7JyE7ZWcIOyXlOuTnO2PrOyduO2KuFxuICAgICAgICovXG4gICAgICBzZXJ2ZXIuZ2V0KFwiL2FwaS9zb25hbXUvaGVhbHRoXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGNvbnN0IGFkZHJlc3MgPSByZXF1ZXN0LnNlcnZlci5zZXJ2ZXIuYWRkcmVzcygpO1xuICAgICAgICBjb25zdCBwb3J0ID0gYWRkcmVzcyAmJiB0eXBlb2YgYWRkcmVzcyA9PT0gXCJvYmplY3RcIiA/IChhZGRyZXNzIGFzIEFkZHJlc3NJbmZvKS5wb3J0IDogMDtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIG9rOiB0cnVlLFxuICAgICAgICAgIHByb2plY3Q6IHByb2Nlc3MuY3dkKCkuc3BsaXQoXCIvXCIpLnBvcCgpIHx8IFwidW5rbm93blwiLFxuICAgICAgICAgIHBvcnQsXG4gICAgICAgICAgdGltZXN0YW1wOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICAgIH07XG4gICAgICB9KTtcblxuICAgICAgLyoqXG4gICAgICAgKiBGaXh0dXJlIOyDneyEsSBBUElcbiAgICAgICAqL1xuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5OiBzdHJpbmc7XG4gICAgICAgICAgY291bnQ/OiBudW1iZXI7XG4gICAgICAgICAgb3ZlcnJpZGVzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgICAgICAgdGFyZ2V0RGI/OiBcImZpeHR1cmVcIiB8IFwidGVzdFwiO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL3NvbmFtdS9maXh0dXJlL2dlbmVyYXRlXCIsIGFzeW5jIChyZXF1ZXN0LCByZXBseSkgPT4ge1xuICAgICAgICBjb25zdCB7IGVudGl0eSwgY291bnQgPSAxLCBvdmVycmlkZXMsIHRhcmdldERiID0gXCJmaXh0dXJlXCIgfSA9IHJlcXVlc3QuYm9keTtcblxuICAgICAgICAvLyDtg4Dqsp8gREIg7ISk7KCVIOqwgOyguOyYpOq4sFxuICAgICAgICBjb25zdCBkYkNvbmZpZyA9IHRhcmdldERiID09PSBcImZpeHR1cmVcIiA/IFNvbmFtdS5kYkNvbmZpZy5maXh0dXJlIDogU29uYW11LmRiQ29uZmlnLnRlc3Q7XG5cbiAgICAgICAgLy8gS25leCDsnbjsiqTthLTsiqQg7IOd7ISxXG4gICAgICAgIGNvbnN0IGRiID0gY3JlYXRlS25leEluc3RhbmNlKGRiQ29uZmlnKTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIC8vIEZpeHR1cmVHZW5lcmF0b3Ig7IOd7ISxXG4gICAgICAgICAgY29uc3QgZ2VuZXJhdG9yID0gbmV3IEZpeHR1cmVHZW5lcmF0b3IoZGIsIGRiLCB0YXJnZXREYiwgRW50aXR5TWFuYWdlcik7XG5cbiAgICAgICAgICAvLyDri6jsnbwgRW50aXR5IOuwsOy5mCDsg53shLFcbiAgICAgICAgICBjb25zdCBmaXh0dXJlcyA9IGF3YWl0IGdlbmVyYXRvci5nZW5lcmF0ZUJhdGNoKFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZW50aXR5LFxuICAgICAgICAgICAgICBjb3VudCxcbiAgICAgICAgICAgICAgb3ZlcnJpZGVzOiBvdmVycmlkZXMgPz8ge30sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0pO1xuXG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgICAgICAgICBlbnRpdHksXG4gICAgICAgICAgICBjb3VudDogZml4dHVyZXMubGVuZ3RoLFxuICAgICAgICAgICAgZml4dHVyZXMsXG4gICAgICAgICAgICB0YXJnZXREYixcbiAgICAgICAgICB9O1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIHJlcGx5LnN0YXR1cyg0MDApO1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgICAgICAgIGVycm9yOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvciksXG4gICAgICAgICAgfTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICBhd2FpdCBkYi5kZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICAvKipcbiAgICAgICAqIEZpeHR1cmUg642w7J207YSwIO2DkOyDiSBBUElcbiAgICAgICAqL1xuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5OiBzdHJpbmc7XG4gICAgICAgICAgc3RyYXRlZ3k6IFwic2FtcGxlXCIgfCBcInJlY2VudFwiIHwgXCJyYW5kb21cIiB8IFwicXVlcnlcIjtcbiAgICAgICAgICBsaW1pdD86IG51bWJlcjtcbiAgICAgICAgICB3aGVyZT86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL3NvbmFtdS9maXh0dXJlL2V4cGxvcmVcIiwgYXN5bmMgKHJlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgZW50aXR5LCBzdHJhdGVneSwgbGltaXQgPSAxMCwgd2hlcmUgfSA9IHJlcXVlc3QuYm9keTtcblxuICAgICAgICAvLyBGaXh0dXJlIERCIOyEpOyglSDqsIDsoLjsmKTquLBcbiAgICAgICAgY29uc3QgZml4dHVyZURiQ29uZmlnID0gU29uYW11LmRiQ29uZmlnLmZpeHR1cmU7XG5cbiAgICAgICAgLy8gS25leCDsnbjsiqTthLTsiqQg7IOd7ISxXG4gICAgICAgIGNvbnN0IGZpeHR1cmVEYiA9IGNyZWF0ZUtuZXhJbnN0YW5jZShmaXh0dXJlRGJDb25maWcpO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gRGF0YUV4cGxvcmVyIOyDneyEsVxuICAgICAgICAgIGNvbnN0IGV4cGxvcmVyID0gbmV3IERhdGFFeHBsb3JlcihmaXh0dXJlRGIsIEVudGl0eU1hbmFnZXIpO1xuXG4gICAgICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IGV4cGxvcmVyLmV4cGxvcmUoZW50aXR5LCB7XG4gICAgICAgICAgICBzdHJhdGVneSxcbiAgICAgICAgICAgIGxpbWl0LFxuICAgICAgICAgICAgd2hlcmUsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgICAgICAgIGVudGl0eSxcbiAgICAgICAgICAgIHN0cmF0ZWd5LFxuICAgICAgICAgICAgY291bnQ6IGRhdGEubGVuZ3RoLFxuICAgICAgICAgICAgZGF0YSxcbiAgICAgICAgICB9O1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIHJlcGx5LnN0YXR1cyg0MDApO1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgICAgICAgIGVycm9yOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvciksXG4gICAgICAgICAgfTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICBhd2FpdCBmaXh0dXJlRGIuZGVzdHJveSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgLyoqXG4gICAgICAgKiBGaXh0dXJlIOuNsOydtO2EsCDqsIDsoLjsmKTquLAgKGZldGNoKSBBUElcbiAgICAgICAqIHByb2R1Y3Rpb24vZGV2ZWxvcG1lbnQgRELsl5DshJwg7Iuk7KCcIOuNsOydtO2EsOulvCBmaXh0dXJlIERC66GcIGltcG9ydFxuICAgICAgICovXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBlbnRpdHk6IHN0cmluZztcbiAgICAgICAgICBzdHJhdGVneT86IFwic2FtcGxlXCIgfCBcInJlY2VudFwiIHwgXCJyYW5kb21cIiB8IFwicXVlcnlcIjtcbiAgICAgICAgICBsaW1pdD86IG51bWJlcjtcbiAgICAgICAgICBpbmNsdWRlUmVsYXRpb25zPzogYm9vbGVhbjtcbiAgICAgICAgICBtYXhEZXB0aD86IG51bWJlcjtcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9zb25hbXUvZml4dHVyZS9mZXRjaFwiLCBhc3luYyAocmVxdWVzdCwgcmVwbHkpID0+IHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIGVudGl0eSxcbiAgICAgICAgICBzdHJhdGVneSA9IFwicmVjZW50XCIsXG4gICAgICAgICAgbGltaXQgPSAxMCxcbiAgICAgICAgICBpbmNsdWRlUmVsYXRpb25zID0gdHJ1ZSxcbiAgICAgICAgICBtYXhEZXB0aCA9IDIsXG4gICAgICAgIH0gPSByZXF1ZXN0LmJvZHk7XG5cbiAgICAgICAgLy8gU291cmNlIERCIChwcm9kdWN0aW9uL2RldmVsb3BtZW50KSAtIOydveq4sCDsoITsmqlcbiAgICAgICAgY29uc3Qgc291cmNlRGIgPSBEQi5nZXREQihcInJcIik7XG5cbiAgICAgICAgLy8gVGFyZ2V0IERCIChmaXh0dXJlKVxuICAgICAgICBjb25zdCBmaXh0dXJlRGIgPSBjcmVhdGVLbmV4SW5zdGFuY2UoU29uYW11LmRiQ29uZmlnLmZpeHR1cmUpO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gRml4dHVyZUdlbmVyYXRvciDsg53shLFcbiAgICAgICAgICBjb25zdCBnZW5lcmF0b3IgPSBuZXcgRml4dHVyZUdlbmVyYXRvcihzb3VyY2VEYiwgZml4dHVyZURiLCBcImZpeHR1cmVcIiwgRW50aXR5TWFuYWdlcik7XG5cbiAgICAgICAgICAvLyBwcm9kdWN0aW9uIOuNsOydtO2EsOulvCBmaXh0dXJlIERC66GcIGltcG9ydFxuICAgICAgICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBnZW5lcmF0b3IuaW1wb3J0RnJvbVNvdXJjZShlbnRpdHksIHtcbiAgICAgICAgICAgIHN0cmF0ZWd5LFxuICAgICAgICAgICAgbGltaXQsXG4gICAgICAgICAgICBpbmNsdWRlUmVsYXRpb25zLFxuICAgICAgICAgICAgbWF4RGVwdGgsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgICAgICAgIGVudGl0eSxcbiAgICAgICAgICAgIHN0cmF0ZWd5LFxuICAgICAgICAgICAgY291bnQ6IHJlc3VsdHMubGVuZ3RoLFxuICAgICAgICAgICAgaW1wb3J0ZWQ6IHJlc3VsdHMsXG4gICAgICAgICAgfTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICByZXBseS5zdGF0dXMoNDAwKTtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgICAgICBlcnJvcjogZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpLFxuICAgICAgICAgIH07XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgLy8gc291cmNlRGLripQgU29uYW116rCAIOq0gOumrO2VmOuvgOuhnCBkZXN0cm957ZWY7KeAIOyViuydjFxuICAgICAgICAgIGF3YWl0IGZpeHR1cmVEYi5kZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICAvKipcbiAgICAgICAqIEZpeHR1cmUg642w7J207YSwIOyCreygnCAoY2xlYW4pIEFQSVxuICAgICAgICogRksg7Iic7ISc66W8IOqzoOugpO2VmOyXrCDslYjsoITtlZjqsowg7IKt7KCcXG4gICAgICAgKi9cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIGVudGl0aWVzPzogc3RyaW5nW107XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvc29uYW11L2ZpeHR1cmUvY2xlYW5cIiwgYXN5bmMgKHJlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgZW50aXRpZXMgfSA9IHJlcXVlc3QuYm9keTtcblxuICAgICAgICAvLyBGaXh0dXJlIERCIOyXsOqysFxuICAgICAgICBjb25zdCBmaXh0dXJlRGIgPSBjcmVhdGVLbmV4SW5zdGFuY2UoU29uYW11LmRiQ29uZmlnLmZpeHR1cmUpO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8g7IKt7KCc7ZWgIEVudGl0eSDrqqnroZ0g6rKw7KCVXG4gICAgICAgICAgY29uc3QgdGFyZ2V0RW50aXRpZXMgPVxuICAgICAgICAgICAgZW50aXRpZXMgJiYgZW50aXRpZXMubGVuZ3RoID4gMCA/IGVudGl0aWVzIDogRW50aXR5TWFuYWdlci5nZXRBbGxJZHMoKTtcblxuICAgICAgICAgIC8vIEVudGl0eSBJROulvCDthYzsnbTruJTrqoXsnLzroZwg67OA7ZmYIChzbmFrZV9jYXNlIOuzteyImO2YlSlcbiAgICAgICAgICBjb25zdCB0YWJsZU5hbWVzID0gdGFyZ2V0RW50aXRpZXMubWFwKChlbnRpdHlJZCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgICAgcmV0dXJuIGVudGl0eS50YWJsZTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIC8vIFBvc3RncmVTUUw6IFRSVU5DQVRFIENBU0NBREXroZwgRksg7Iic7IScIOustOq0gO2VmOqyjCDslYjsoITtlZjqsowg7IKt7KCcXG4gICAgICAgICAgLy8gQ0FTQ0FERSDsmLXshZjsnLzroZwg7J2Y7KG07ISxIOyeiOuKlCDrjbDsnbTthLDrj4Qg7ZWo6ruYIOyCreygnFxuICAgICAgICAgIGF3YWl0IGZpeHR1cmVEYi5yYXcoXG4gICAgICAgICAgICBgVFJVTkNBVEUgVEFCTEUgJHt0YWJsZU5hbWVzLm1hcCgodCkgPT4gYFwiJHt0fVwiYCkuam9pbihcIiwgXCIpfSBSRVNUQVJUIElERU5USVRZIENBU0NBREVgLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgICAgICAgIGNsZWFuZWQ6IHRhYmxlTmFtZXMsXG4gICAgICAgICAgICBjb3VudDogdGFibGVOYW1lcy5sZW5ndGgsXG4gICAgICAgICAgfTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICByZXBseS5zdGF0dXMoNDAwKTtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgICAgICBlcnJvcjogZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpLFxuICAgICAgICAgIH07XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgYXdhaXQgZml4dHVyZURiLmRlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIC8vIENERCBBUElcbiAgICAgIHNlcnZlci5nZXQoXCIvYXBpL2NkZC90cmVlXCIsIGFzeW5jICgpID0+IHtcbiAgICAgICAgcmV0dXJuIGdldENkZFRyZWUoKTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7IEJvZHk6IHsgZmlsZVBhdGg6IHN0cmluZyB9IH0+KFwiL2FwaS9jZGQvcmVhZENvbnRlbnRcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgeyBmaWxlUGF0aCB9ID0gcmVxdWVzdC5ib2R5O1xuICAgICAgICByZXR1cm4gcmVhZENvbnRlbnQoZmlsZVBhdGgpO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHsgQm9keTogeyBmaWxlUGF0aDogc3RyaW5nIH0gfT4oXCIvYXBpL2NkZC9lZGl0Q29udGVudFwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICBjb25zdCB7IGZpbGVQYXRoIH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgIHJldHVybiBlZGl0Q29udGVudChmaWxlUGF0aCk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8eyBCb2R5OiB7IGZpbGVQYXRoOiBzdHJpbmcgfSB9PihcIi9hcGkvY2RkL29wZW5Tb3VyY2VcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgeyBmaWxlUGF0aCB9ID0gcmVxdWVzdC5ib2R5O1xuICAgICAgICBvcGVuU291cmNlRmlsZShmaWxlUGF0aCk7XG4gICAgICAgIHJldHVybiB7IHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBDREQgUnVsZXMgQVBJXG4gICAgICBzZXJ2ZXIuZ2V0KFwiL2FwaS9jZGQvcnVsZXNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgICByZXR1cm4gbGlzdFJ1bGVzKCk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8eyBCb2R5OiB7IHJ1bGVLZXk6IHN0cmluZyB9IH0+KFwiL2FwaS9jZGQvcmVhZFJ1bGVcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgeyBydWxlS2V5IH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgIHJldHVybiByZWFkUnVsZShydWxlS2V5KTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7IEJvZHk6IENkZEFkZFJ1bGVSZXF1ZXN0IH0+KFwiL2FwaS9jZGQvYWRkUnVsZVwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICByZXR1cm4gYWRkUnVsZShyZXF1ZXN0LmJvZHkpO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIENERCBBQyBBUElcbiAgICAgIHNlcnZlci5nZXQoXCIvYXBpL2NkZC9hY1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIHJldHVybiBnZXRBY0xpc3QoKTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyB1aS13ZWIg67mM65OcIO2MjOydvCDshJzruZlcbiAgICAgIGNvbnN0IHVpRGlzdFBhdGggPSBwYXRoLnJlc29sdmUoaW1wb3J0Lm1ldGEuZGlybmFtZSwgXCIuLi91aS13ZWJcIik7XG5cbiAgICAgIC8vIOygleyggSDtjIzsnbwg7ISc67mZOiDro6jtirgg7Y+0642UIOyghOyytCAoYXNzZXRzLCBzZXR0aW5nLnN2ZyDrk7EpXG4gICAgICBzZXJ2ZXIucmVnaXN0ZXIoYXdhaXQgaW1wb3J0KFwiQGZhc3RpZnkvc3RhdGljXCIpLCB7XG4gICAgICAgIHJvb3Q6IHVpRGlzdFBhdGgsXG4gICAgICAgIHByZWZpeDogXCIvXCIsXG4gICAgICAgIGRlY29yYXRlUmVwbHk6IGZhbHNlLFxuICAgICAgICB3aWxkY2FyZDogZmFsc2UsXG4gICAgICB9KTtcblxuICAgICAgLy8gU1BBIGZhbGxiYWNrIC0g7KCV7KCBIO2MjOydvOydtCDsl4bripQg66qo65OgIOqyveuhnOuKlCBpbmRleC5odG1s66GcXG4gICAgICBzZXJ2ZXIuZ2V0KFwiKlwiLCBhc3luYyAoX3JlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICAgIHJlcGx5LmhlYWRlcnMoeyBcIkNvbnRlbnQtdHlwZVwiOiBcInRleHQvaHRtbFwiIH0pLnNlbmQoXG4gICAgICAgICAgZnNcbiAgICAgICAgICAgIC5yZWFkRmlsZVN5bmMocGF0aC5yZXNvbHZlKHVpRGlzdFBhdGgsIFwiaW5kZXguaHRtbFwiKSlcbiAgICAgICAgICAgIC50b1N0cmluZygpXG4gICAgICAgICAgICAucmVwbGFjZShcInt7cHJvamVjdE5hbWV9fVwiLCBTb25hbXUuY29uZmlnLnByb2plY3ROYW1lID8/IFwiVW5rbm93blNvbmFtdVByb2plY3RcIiksXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICB9LFxuICAgIHsgcHJlZml4OiBcIi9zb25hbXUtdWlcIiB9LFxuICApO1xufVxuIl0sIm5hbWVzIjpbImV4ZWNTeW5jIiwiZnMiLCJpbmZsZWN0aW9uIiwicGF0aCIsInJhbmdlIiwiU29uYW11IiwiREIiLCJjcmVhdGVLbmV4SW5zdGFuY2UiLCJTRCIsInNvbmFtdURpY3Rpb25hcnkiLCJFbnRpdHlNYW5hZ2VyIiwiQmFkUmVxdWVzdEV4Y2VwdGlvbiIsImlzU29FeGNlcHRpb24iLCJTZXJ2aWNlVW5hdmFpbGFibGVFeGNlcHRpb24iLCJNaWdyYXRvciIsIlNsYWNrQ29uZmlybSIsIlRlbXBsYXRlTWFuYWdlciIsIkRhdGFFeHBsb3JlciIsIkZpeHR1cmVHZW5lcmF0b3IiLCJGaXh0dXJlTWFuYWdlciIsIkJVSUxUX0lOX1RZUEVfSURTIiwiVGVtcGxhdGVLZXkiLCJub25OdWxsYWJsZSIsInNldEFpQXBpIiwiYWRkUnVsZSIsImVkaXRDb250ZW50IiwiZ2V0QWNMaXN0IiwiZ2V0Q2RkVHJlZSIsImxpc3RSdWxlcyIsIm9wZW5Tb3VyY2VGaWxlIiwicmVhZENvbnRlbnQiLCJyZWFkUnVsZSIsInNvbmFtdVVJQXBpUGx1Z2luIiwiZmFzdGlmeSIsInJlZ2lzdGVyIiwic2VydmVyIiwibWlncmF0b3IiLCJ3YWl0Rm9ySE1SQ29tcGxldGVkIiwiZm4iLCJ3YWl0UHJvbWlzZSIsIlByb21pc2UiLCJyZXNvbHZlIiwiaGFuZGxlciIsImNsZWFyVGltZW91dCIsInRpbWVvdXQiLCJzZXRUaW1lb3V0Iiwic3luY2VyIiwiZXZlbnRFbWl0dGVyIiwib2ZmIiwib25jZSIsInJlc3VsdCIsImdldCIsImNvbmZpZyIsInJlcXVlc3QiLCJlbnRpdHlJZCIsInByZXNldCIsImFic1BhdGgiLCJxdWVyeSIsInRhcmdldFBhdGgiLCJlbnRpdHkiLCJuYW1lcyIsImFwaVJvb3RQYXRoIiwiZmlsZW5hbWUiLCJwYXJlbnRGcyIsIm9yaWdpbiIsImdsb3NzYXJ5IiwiTWFwIiwiZ2V0QWxsSWRzIiwidGl0bGUiLCJzZXQiLCJ1bmRlcnNjb3JlIiwiaWQiLCJwbHVyYWxpemUiLCJwcm9wcyIsImZvckVhY2giLCJwcm9wIiwiaGFzIiwibmFtZSIsImRlc2MiLCJyZXBsYWNlIiwic3VnZ2VzdGVkIiwid29yZHMiLCJzcGxpdCIsImNvbWJpbmF0aW9ucyIsImxlbmd0aCIsImZsYXRNYXAiLCJsZW4iLCJpZHgiLCJ3Iiwic2xpY2UiLCJqb2luIiwiUkVQTEFDRURfUFJFRklYIiwicmVtYWluQXJyIiwiY29tYiIsInJlbWFpblN0ciIsImluY2x1ZGVzIiwibWFwIiwiciIsInN0YXJ0c1dpdGgiLCJ0b1VwcGVyQ2FzZSIsImVudGl0eUlkcyIsImZsYXR0ZW5TdWJzZXRSb3dzIiwic3Vic2V0Um93cyIsInN1YnNldFJvdyIsImNoaWxkcmVuIiwic1JvdyIsImVudGl0aWVzIiwiYWxsIiwiZ2V0U3Vic2V0Um93cyIsInNvcnQiLCJhIiwiYiIsImFJZCIsInBhcmVudElkIiwiYklkIiwidW5kZWZpbmVkIiwiZmlsdGVyIiwicmVsb2FkIiwiYXV0b2xvYWRUeXBlcyIsInR5cGVJZHMiLCJwcm9qZWN0VHlwZUlkcyIsIk9iamVjdCIsImVudHJpZXMiLCJ0eXBlcyIsIl90eXBlSWQiLCJ6b2RUeXBlIiwiX3pvZCIsImRlZiIsInR5cGUiLCJ0eXBlSWQiLCJfem9kVHlwZSIsImJ1aWx0SW5UeXBlSWRzIiwiYWxsVHlwZUlkcyIsImVudW1JZHMiLCJrZXlzIiwiZW51bUxhYmVscyIsInBvc3QiLCJmb3JtIiwiYm9keSIsImNyZWF0ZUVudGl0eSIsImRlbEVudGl0eSIsIm5ld1ZhbHVlcyIsInRhYmxlIiwic2F2ZSIsInN1YnNldEtleSIsImZpZWxkcyIsImZpZWxkc0ludGVybmFsIiwic3Vic2V0cyIsInN1YnNldHNJbnRlcm5hbCIsInVwZGF0ZWQiLCJ1cGRhdGVkSW50ZXJuYWwiLCJhdCIsIm5ld1Byb3AiLCJjcmVhdGVQcm9wIiwibW9kaWZ5UHJvcCIsImRlbFByb3AiLCJ0byIsIm1vdmVQcm9wIiwiaW5kZXhlcyIsIm5ld0VudW1JZCIsIkVycm9yIiwiZW5kc1dpdGgiLCJhY3RpdmUiLCJoaWRkZW4iLCJlbnVtSWQiLCJpc0V4aXN0cyIsInNvbWUiLCJhZnRlciIsImJlZm9yZSIsImlzUmVmZXJlbmNlZCIsInRhcmdldCIsInByb3BOYW1lIiwiY29uZSIsImZpbmQiLCJwIiwiZW51bUNvbmVzIiwic3Vic2V0Q29uZXMiLCJyZXBseSIsInByZXNlcnZlRXhpc3RpbmciLCJvbmx5RW1wdHkiLCJsb2NhbGUiLCJlZmZlY3RpdmVMb2NhbGUiLCJpMThuIiwiZGVmYXVsdExvY2FsZSIsImdlbmVyYXRlQ29uZXMiLCJlcnJvciIsIm1lc3NhZ2UiLCJTdHJpbmciLCJzdGF0dXMiLCJzdWNjZXNzIiwiY29sdW1ucyIsImdldFRhYmxlQ29sdW1ucyIsImdldFN0YXR1cyIsImFjdGlvbiIsInRhcmdldHMiLCJmb3JjZSIsImZvcmNlUmVhc29uIiwicmVxdWVzdG9yIiwicnVuU2hhZG93VGVzdCIsInNsYWNrQ29uZmlybSIsInJlcXVpcmVzQXBwcm92YWwiLCJ0IiwiaXNUYXJnZXRSZXF1aXJlc0FwcHJvdmFsIiwibG9jYWxIb3N0cyIsImlzTG9jYWxUYXJnZXQiLCJldmVyeSIsInRhcmdldENvbmZpZyIsImRiQ29uZmlnIiwiaG9zdCIsImNvbm5lY3Rpb24iLCJ0b0xvd2VyQ2FzZSIsImlzQ29uZmlndXJlZCIsImNvbm5zIiwicGVuZGluZ01pZ3JhdGlvbnMiLCJTZXQiLCJjb25uIiwiY29ubktleSIsInBlbmRpbmciLCJleGlzdGluZyIsImdldEV4aXN0aW5nUmVxdWVzdCIsImFwcHJvdmVkIiwicmVqZWN0ZWQiLCJjaGVja0FwcHJvdmFsIiwiY2hhbm5lbCIsInRzIiwicnVuQWN0aW9uIiwibG9nRXhlY3V0aW9uIiwiZm9yY2VBcHByb3ZhbCIsInBvc3RBcHByb3ZhbFJlcXVlc3QiLCJzYXZlUmVxdWVzdCIsInJlYXNvbiIsImNvZGVOYW1lcyIsImRlbENvZGVzIiwiX3JlcXVlc3R0IiwiZ2VuZXJhdGVQcmVwYXJlZENvZGVzIiwidGVtcGxhdGVLZXlzIiwiX3RlbXBsYXRlS2V5cyIsIm9wdGlvbnMiLCJ0ayIsInRlbXBsYXRlS2V5Iiwic3RhdHVzZXMiLCJzdWJQYXRoIiwiZnVsbFBhdGgiLCJjaGVja0V4aXN0c0dlbkNvZGUiLCJ0ZW1wbGF0ZSIsImdldFJlcXVpcmVkRGljdEtleXMiLCJlbnN1cmVEaWN0S2V5cyIsIm92ZXJ3cml0ZSIsImdlbmVyYXRlVGVtcGxhdGUiLCJlIiwic3RhdHVzQ29kZSIsImNvbnNvbGUiLCJvcHRpb24iLCJ0ZW1wbGF0ZU9wdGlvbnMiLCJwYXRoQW5kQ29kZXMiLCJyZW5kZXJUZW1wbGF0ZSIsInNvdXJjZURCIiwidGFyZ2V0REIiLCJzZWFyY2giLCJkdXBsaWNhdGVDaGVjayIsImdldEZpeHR1cmVzIiwiZGIiLCJmaXh0dXJlcyIsImluc2VydEZpeHR1cmVzIiwiY29kZSIsImFkZEZpeHR1cmVMb2FkZXIiLCJnZXREaWN0aW9uYXJ5IiwiX3JlcXVlc3QiLCJidWZmZXIiLCJleHBvcnRUb0V4Y2VsIiwiaGVhZGVyIiwic2VuZCIsImRhdGEiLCJmaWxlIiwidG9CdWZmZXIiLCJpbXBvcnRGcm9tRXhjZWwiLCJ1cGRhdGVFbnRyeSIsImNyZWF0ZUVudHJ5IiwiZGVsZXRlRW50cnkiLCJrZXkiLCJjaGVja1VzYWdlIiwid29ya2Zsb3dzIiwiZGVmaW5pdGlvbnMiLCJ3b3JrZmxvd0RlZmluaXRpb25zIiwiYmFja2VuZCIsImxpbWl0Iiwib3JkZXIiLCJ3b3JrZmxvd05hbWUiLCJjcmVhdGVkQWZ0ZXIiLCJjcmVhdGVkQmVmb3JlIiwibGlzdFdvcmtmbG93UnVucyIsIk51bWJlciIsInBhcnNlSW50IiwiRGF0ZSIsIndvcmtmbG93UnVuIiwiZ2V0V29ya2Zsb3dSdW4iLCJ3b3JrZmxvd1J1bklkIiwicGFyYW1zIiwiY2FuY2VsV29ya2Zsb3dSdW4iLCJwYXVzZVdvcmtmbG93UnVuIiwicmVzdW1lV29ya2Zsb3dSdW4iLCJsaXN0U3RlcEF0dGVtcHRzIiwiYWRkcmVzcyIsInBvcnQiLCJvayIsInByb2plY3QiLCJwcm9jZXNzIiwiY3dkIiwicG9wIiwidGltZXN0YW1wIiwidG9JU09TdHJpbmciLCJjb3VudCIsIm92ZXJyaWRlcyIsInRhcmdldERiIiwiZml4dHVyZSIsInRlc3QiLCJnZW5lcmF0b3IiLCJnZW5lcmF0ZUJhdGNoIiwiZGVzdHJveSIsInN0cmF0ZWd5Iiwid2hlcmUiLCJmaXh0dXJlRGJDb25maWciLCJmaXh0dXJlRGIiLCJleHBsb3JlciIsImV4cGxvcmUiLCJpbmNsdWRlUmVsYXRpb25zIiwibWF4RGVwdGgiLCJzb3VyY2VEYiIsImdldERCIiwicmVzdWx0cyIsImltcG9ydEZyb21Tb3VyY2UiLCJpbXBvcnRlZCIsInRhcmdldEVudGl0aWVzIiwidGFibGVOYW1lcyIsInJhdyIsImNsZWFuZWQiLCJmaWxlUGF0aCIsInJ1bGVLZXkiLCJ1aURpc3RQYXRoIiwiZGlybmFtZSIsInJvb3QiLCJwcmVmaXgiLCJkZWNvcmF0ZVJlcGx5Iiwid2lsZGNhcmQiLCJoZWFkZXJzIiwicmVhZEZpbGVTeW5jIiwidG9TdHJpbmciLCJwcm9qZWN0TmFtZSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsUUFBUSxRQUFRLGdCQUFnQjtBQUV6QyxPQUFPQyxRQUFRLEtBQUs7QUFDcEIsT0FBT0MsZ0JBQWdCLGFBQWE7QUFFcEMsT0FBT0MsVUFBVSxPQUFPO0FBQ3hCLFNBQVNDLEtBQUssUUFBUSxVQUFVO0FBQ2hDLFNBQVNDLE1BQU0sUUFBUSxtQkFBZ0I7QUFDdkMsU0FBU0MsRUFBRSxRQUE2QixvQkFBaUI7QUFDekQsU0FBU0Msa0JBQWtCLFFBQVEsc0JBQW1CO0FBQ3RELFNBQVNDLEVBQUUsUUFBUSxnQkFBYTtBQUNoQyxTQUFTQyxnQkFBZ0IsUUFBUSwrQkFBNEI7QUFFN0QsU0FBU0MsYUFBYSxRQUFRLDhCQUEyQjtBQUN6RCxTQUNFQyxtQkFBbUIsRUFDbkJDLGFBQWEsRUFDYkMsMkJBQTJCLFFBQ3RCLGlDQUE4QjtBQUNyQyxTQUErQkMsUUFBUSxRQUFRLDJCQUF3QjtBQUN2RSxTQUFTQyxZQUFZLFFBQXdDLGdDQUE2QjtBQUMxRixTQUFTQyxlQUFlLFFBQVEsa0NBQStCO0FBQy9ELFNBQVNDLFlBQVksUUFBUSw4QkFBMkI7QUFDeEQsU0FBU0MsZ0JBQWdCLFFBQVEsa0NBQStCO0FBQ2hFLFNBQXFDQyxjQUFjLFFBQVEsZ0NBQTZCO0FBQ3hGLFNBQ0VDLGlCQUFp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
904
+ //#endregion
905
+ init_api();
906
+ export { sonamuUIApiPlugin };
907
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBpLmpzIiwibmFtZXMiOlsiZW50aXR5SWQiLCJyZW1haW5BcnI6IHN0cmluZ1tdIiwiZW50aXR5IiwiZXJyb3I6IHVua25vd24iXSwic291cmNlcyI6WyIuLi8uLi9zcmMvdWkvYXBpLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGV4ZWNTeW5jIH0gZnJvbSBcImNoaWxkX3Byb2Nlc3NcIjtcbmltcG9ydCBmcyBmcm9tIFwiZnNcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5cbmltcG9ydCB7IHR5cGUgRmFzdGlmeUluc3RhbmNlIH0gZnJvbSBcImZhc3RpZnlcIjtcbmltcG9ydCBpbmZsZWN0aW9uIGZyb20gXCJpbmZsZWN0aW9uXCI7XG5pbXBvcnQgeyByYW5nZSB9IGZyb20gXCJyYWRhc2hpXCI7XG5cbmltcG9ydCB7IFNvbmFtdSB9IGZyb20gXCIuLi9hcGkvc29uYW11XCI7XG5pbXBvcnQgeyBEQiB9IGZyb20gXCIuLi9kYXRhYmFzZS9kYlwiO1xuaW1wb3J0IHsgdHlwZSBTb25hbXVEQkNvbmZpZyB9IGZyb20gXCIuLi9kYXRhYmFzZS9kYlwiO1xuaW1wb3J0IHsgY3JlYXRlS25leEluc3RhbmNlIH0gZnJvbSBcIi4uL2RhdGFiYXNlL2tuZXhcIjtcbmltcG9ydCB7IFNEIH0gZnJvbSBcIi4uL2RpY3Qvc2RcIjtcbmltcG9ydCB7IHNvbmFtdURpY3Rpb25hcnkgfSBmcm9tIFwiLi4vZGljdC9zb25hbXUtZGljdGlvbmFyeVwiO1xuaW1wb3J0IHsgdHlwZSBFbnRpdHkgfSBmcm9tIFwiLi4vZW50aXR5L2VudGl0eVwiO1xuaW1wb3J0IHsgRW50aXR5TWFuYWdlciB9IGZyb20gXCIuLi9lbnRpdHkvZW50aXR5LW1hbmFnZXJcIjtcbmltcG9ydCB7XG4gIEJhZFJlcXVlc3RFeGNlcHRpb24sXG4gIGlzU29FeGNlcHRpb24sXG4gIFNlcnZpY2VVbmF2YWlsYWJsZUV4Y2VwdGlvbixcbn0gZnJvbSBcIi4uL2V4Y2VwdGlvbnMvc28tZXhjZXB0aW9uc1wiO1xuaW1wb3J0IHsgTWlncmF0b3IgfSBmcm9tIFwiLi4vbWlncmF0aW9uL21pZ3JhdG9yXCI7XG5pbXBvcnQgeyB0eXBlIE1pZ3JhdGlvblJlc3VsdCB9IGZyb20gXCIuLi9taWdyYXRpb24vbWlncmF0b3JcIjtcbmltcG9ydCB7IFNsYWNrQ29uZmlybSB9IGZyb20gXCIuLi9taWdyYXRpb24vc2xhY2stY29uZmlybVwiO1xuaW1wb3J0IHsgdHlwZSBTbGFja0NvbmZpcm1QZW5kaW5nUmVzdWx0IH0gZnJvbSBcIi4uL21pZ3JhdGlvbi9zbGFjay1jb25maXJtXCI7XG5pbXBvcnQgeyBUZW1wbGF0ZU1hbmFnZXIgfSBmcm9tIFwiLi4vdGVtcGxhdGUvdGVtcGxhdGUtbWFuYWdlclwiO1xuaW1wb3J0IHsgRGF0YUV4cGxvcmVyIH0gZnJvbSBcIi4uL3Rlc3RpbmcvZGF0YS1leHBsb3JlclwiO1xuaW1wb3J0IHsgRml4dHVyZUdlbmVyYXRvciB9IGZyb20gXCIuLi90ZXN0aW5nL2ZpeHR1cmUtZ2VuZXJhdG9yXCI7XG5pbXBvcnQgeyBGaXh0dXJlTWFuYWdlciB9IGZyb20gXCIuLi90ZXN0aW5nL2ZpeHR1cmUtbWFuYWdlclwiO1xuaW1wb3J0IHsgdHlwZSBEdXBsaWNhdGVDaGVja09wdGlvbnMgfSBmcm9tIFwiLi4vdGVzdGluZy9maXh0dXJlLW1hbmFnZXJcIjtcbmltcG9ydCB7IEJVSUxUX0lOX1RZUEVfSURTLCBUZW1wbGF0ZUtleSB9IGZyb20gXCIuLi90eXBlcy90eXBlc1wiO1xuaW1wb3J0IHtcbiAgdHlwZSBDb25lLFxuICB0eXBlIEVudGl0eUluZGV4LFxuICB0eXBlIEVudGl0eVByb3AsXG4gIHR5cGUgRW50aXR5U3Vic2V0Um93LFxuICB0eXBlIEZpeHR1cmVSZWNvcmQsXG4gIHR5cGUgRml4dHVyZVNlYXJjaE9wdGlvbnMsXG4gIHR5cGUgRmxhdHRlblN1YnNldFJvdyxcbiAgdHlwZSBQYXRoQW5kQ29kZSxcbn0gZnJvbSBcIi4uL3R5cGVzL3R5cGVzXCI7XG5pbXBvcnQgeyBub25OdWxsYWJsZSB9IGZyb20gXCIuLi91dGlscy91dGlsc1wiO1xuaW1wb3J0IHsgc2V0QWlBcGkgfSBmcm9tIFwiLi9haS1hcGlcIjtcbmltcG9ydCB7IHR5cGUgQ2RkQWRkUnVsZVJlcXVlc3QgfSBmcm9tIFwiLi9jZGQtc2VydmljZVwiO1xuaW1wb3J0IHtcbiAgYWRkUnVsZSxcbiAgZWRpdENvbnRlbnQsXG4gIGdldEFjTGlzdCxcbiAgZ2V0Q2RkVHJlZSxcbiAgbGlzdFJ1bGVzLFxuICBvcGVuU291cmNlRmlsZSxcbiAgcmVhZENvbnRlbnQsXG4gIHJlYWRSdWxlLFxufSBmcm9tIFwiLi9jZGQtc2VydmljZVwiO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc29uYW11VUlBcGlQbHVnaW4oZmFzdGlmeTogRmFzdGlmeUluc3RhbmNlKSB7XG4gIGZhc3RpZnkucmVnaXN0ZXIoXG4gICAgYXN5bmMgKHNlcnZlcikgPT4ge1xuICAgICAgLy8gbWlncmF0b3JcbiAgICAgIGNvbnN0IG1pZ3JhdG9yID0gbmV3IE1pZ3JhdG9yKCk7XG5cbiAgICAgIC8vIHdhaXRGb3JITVJDb21wbGV0ZWRcbiAgICAgIGFzeW5jIGZ1bmN0aW9uIHdhaXRGb3JITVJDb21wbGV0ZWQ8VD4oZm46ICgpID0+IFByb21pc2U8VD4pOiBQcm9taXNlPFQ+IHtcbiAgICAgICAgY29uc3Qgd2FpdFByb21pc2UgPSBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgIGNvbnN0IGhhbmRsZXIgPSAoKSA9PiB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgfTtcblxuICAgICAgICAgIGNvbnN0IHRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIFNvbmFtdS5zeW5jZXIuZXZlbnRFbWl0dGVyLm9mZihcIm9uSE1SQ29tcGxldGVkXCIsIGhhbmRsZXIpO1xuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgIH0sIDE1MDApO1xuXG4gICAgICAgICAgU29uYW11LnN5bmNlci5ldmVudEVtaXR0ZXIub25jZShcIm9uSE1SQ29tcGxldGVkXCIsIGhhbmRsZXIpO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBmbigpO1xuICAgICAgICBhd2FpdCB3YWl0UHJvbWlzZTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cblxuICAgICAgYXdhaXQgc2V0QWlBcGkoc2VydmVyKTtcblxuICAgICAgc2VydmVyLmdldChcIi9hcGkvc29uYW11L2NvbmZpZ1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIHJldHVybiBTb25hbXUuY29uZmlnO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5nZXQ8e1xuICAgICAgICBRdWVyeXN0cmluZzoge1xuICAgICAgICAgIGVudGl0eUlkPzogc3RyaW5nO1xuICAgICAgICAgIHByZXNldD86IFwidHlwZXNcIiB8IFwiZW50aXR5Lmpzb25cIiB8IFwiZ2VuZXJhdGVkXCI7XG4gICAgICAgICAgYWJzUGF0aD86IHN0cmluZztcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS90b29scy9vcGVuVnNjb2RlXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgZW50aXR5SWQsIHByZXNldCwgYWJzUGF0aCB9ID0gcmVxdWVzdC5xdWVyeTtcblxuICAgICAgICBjb25zdCB0YXJnZXRQYXRoID0gKCgpID0+IHtcbiAgICAgICAgICBpZiAoZW50aXR5SWQgJiYgcHJlc2V0KSB7XG4gICAgICAgICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgICAgICAgICBjb25zdCB7IG5hbWVzIH0gPSBlbnRpdHk7XG5cbiAgICAgICAgICAgIGNvbnN0IHsgYXBpUm9vdFBhdGggfSA9IFNvbmFtdTtcbiAgICAgICAgICAgIGNvbnN0IGZpbGVuYW1lID0gKCgpID0+IHtcbiAgICAgICAgICAgICAgc3dpdGNoIChwcmVzZXQpIHtcbiAgICAgICAgICAgICAgICBjYXNlIFwidHlwZXNcIjpcbiAgICAgICAgICAgICAgICAgIHJldHVybiBgJHtuYW1lcy5mc30udHlwZXMudHNgO1xuICAgICAgICAgICAgICAgIGNhc2UgXCJlbnRpdHkuanNvblwiOlxuICAgICAgICAgICAgICAgICAgcmV0dXJuIGAke25hbWVzLmZzfS5lbnRpdHkuanNvbmA7XG4gICAgICAgICAgICAgICAgY2FzZSBcImdlbmVyYXRlZFwiOlxuICAgICAgICAgICAgICAgICAgcmV0dXJuIGAke25hbWVzLmZzfS5nZW5lcmF0ZWQudHNgO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICAgICAgcmV0dXJuIGAke2FwaVJvb3RQYXRofS9zcmMvYXBwbGljYXRpb24vJHtlbnRpdHkubmFtZXMucGFyZW50RnN9LyR7ZmlsZW5hbWV9YDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKCFhYnNQYXRoKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFNEKFwic29uYW11LmVycm9yLnByZXNldE9yQWJzUGF0aFJlcXVpcmVkXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBhYnNQYXRoO1xuICAgICAgICAgIH1cbiAgICAgICAgfSkoKTtcbiAgICAgICAgZXhlY1N5bmMoYGNvZGUgJHt0YXJnZXRQYXRofWApO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5nZXQ8e1xuICAgICAgICBRdWVyeXN0cmluZzoge1xuICAgICAgICAgIG9yaWdpbjogc3RyaW5nO1xuICAgICAgICAgIGVudGl0eUlkPzogc3RyaW5nO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL3Rvb2xzL2dldFN1Z2dlc3Rpb25cIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgeyBvcmlnaW4sIGVudGl0eUlkIH0gPSByZXF1ZXN0LnF1ZXJ5O1xuXG4gICAgICAgIC8vIOy5mO2ZmCDsmqnslrTsp5FcbiAgICAgICAgY29uc3QgZ2xvc3NhcnkgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPihbXG4gICAgICAgICAgW1wic3RhdHVzXCIsIFwi7IOB7YOcXCJdLFxuICAgICAgICAgIFtcInR5cGVcIiwgXCLtg4DsnoVcIl0sXG4gICAgICAgICAgW1wiaW1hZ2VcIiwgXCLsnbTrr7jsp4BcIl0sXG4gICAgICAgICAgW1wiaW1hZ2VzXCIsIFwi7J2066+47KeA66as7Iqk7Yq4XCJdLFxuICAgICAgICAgIFtcInVybFwiLCBcIlVSTFwiXSxcbiAgICAgICAgICBbXCJpZFwiLCBcIklEXCJdLFxuICAgICAgICAgIFtcIm5hbWVcIiwgYHtFbnRpdHlJRH3rqoVgXSxcbiAgICAgICAgICBbXCJ0aXRsZVwiLCBcIntFbnRpdHlJRH3rqoVcIl0sXG4gICAgICAgICAgW1wicGFyZW50XCIsIFwi7IOB7JyEe0VudGl0eUlEfVwiXSxcbiAgICAgICAgICBbXCJkZXNjXCIsIFwi7ISk66qFXCJdLFxuICAgICAgICAgIFtcImF0XCIsIFwi7J287IucXCJdLFxuICAgICAgICAgIFtcImNyZWF0ZWRcIiwgXCLrk7HroZ1cIl0sXG4gICAgICAgICAgW1widXBkYXRlZFwiLCBcIuyImOyglVwiXSxcbiAgICAgICAgICBbXCJkZWxldGVkXCIsIFwi7IKt7KCcXCJdLFxuICAgICAgICAgIFtcImJ5XCIsIFwi7Jyg7KCAXCJdLFxuICAgICAgICAgIFtcImRhdGVcIiwgXCLsnbzsnpBcIl0sXG4gICAgICAgICAgW1widGltZVwiLCBcIuyLnOqwhFwiXSxcbiAgICAgICAgICBbXCJrb1wiLCBcIijtlZzquIApXCJdLFxuICAgICAgICAgIFtcImVuXCIsIFwiKOyYgeusuClcIl0sXG4gICAgICAgICAgW1wia3J3XCIsIFwiKOybkClcIl0sXG4gICAgICAgICAgW1widXNkXCIsIFwiKFVTRClcIl0sXG4gICAgICAgICAgW1wiY29sb3JcIiwgXCLsu6zrn6xcIl0sXG4gICAgICAgICAgW1wiY29kZVwiLCBcIuy9lOuTnFwiXSxcbiAgICAgICAgICBbXCJ4XCIsIFwiWOyijO2RnFwiXSxcbiAgICAgICAgICBbXCJ5XCIsIFwiWeyijO2RnFwiXSxcbiAgICAgICAgICBbXCJjdXJyZW50XCIsIFwi7ZiE7J6sXCJdLFxuICAgICAgICAgIFtcInN0b2NrXCIsIFwi7J6s6rOgXCJdLFxuICAgICAgICAgIFtcInRvdGFsXCIsIFwi7LSdXCJdLFxuICAgICAgICAgIFtcImFkbWluXCIsIFwi6rSA66as7J6QXCJdLFxuICAgICAgICAgIFtcImdyb3VwXCIsIFwi6re466O5XCJdLFxuICAgICAgICAgIFtcIml0ZW1cIiwgXCLslYTsnbTthZxcIl0sXG4gICAgICAgICAgW1wiY250XCIsIFwi7IiY65+JXCJdLFxuICAgICAgICAgIFtcInByaWNlXCIsIFwi6rCA6rKpXCJdLFxuICAgICAgICAgIFtcInByZXNldFwiLCBcIu2UhOumrOyFi1wiXSxcbiAgICAgICAgICBbXCJhY2N0XCIsIFwi6rOE7KKMXCJdLFxuICAgICAgICAgIFtcInRlbFwiLCBcIuyghO2ZlOuyiO2YuFwiXSxcbiAgICAgICAgICBbXCJub1wiLCBcIuuyiO2YuFwiXSxcbiAgICAgICAgICBbXCJib2R5XCIsIFwi64K07JqpXCJdLFxuICAgICAgICAgIFtcImNvbnRlbnRcIiwgXCLrgrTsmqlcIl0sXG4gICAgICAgICAgW1wib3JkZXJub1wiLCBcIuygleugrOyInOyEnFwiXSxcbiAgICAgICAgICBbXCJwcmlvcml0eVwiLCBcIuyasOyEoOyInOychFwiXSxcbiAgICAgICAgICBbXCJ0ZXh0XCIsIFwi7YWN7Iqk7Yq4XCJdLFxuICAgICAgICAgIFtcImtleVwiLCBcIu2CpFwiXSxcbiAgICAgICAgICBbXCJzdW1cIiwgXCLtlansgrBcIl0sXG4gICAgICAgICAgW1wiZXhwZWN0ZWRcIiwgXCLsmIjsg4FcIl0sXG4gICAgICAgICAgW1wiYWN0dWFsXCIsIFwi7Iuk7KCcXCJdLFxuICAgICAgICBdKTtcbiAgICAgICAgLy8g7KCE7LK0IOyXlO2LsO2LsCDsiJztmoztlZjrqbAsIOyXlO2LsO2LsCDtg4DsnbTti4Dqs7wg7ZSE66GtIOyEpOuqheydhCDsuZjtmZgg7Jqp7Ja07KeR7JeQIOy2lOqwgFxuICAgICAgICBmb3IgKGNvbnN0IGVudGl0eUlkIG9mIEVudGl0eU1hbmFnZXIuZ2V0QWxsSWRzKCkpIHtcbiAgICAgICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgICAgICAgaWYgKChlbnRpdHkudGl0bGUgPz8gXCJcIikgIT09IFwiXCIpIHtcbiAgICAgICAgICAgIGdsb3NzYXJ5LnNldChpbmZsZWN0aW9uLnVuZGVyc2NvcmUoZW50aXR5LmlkKSwgZW50aXR5LnRpdGxlKTtcbiAgICAgICAgICAgIGdsb3NzYXJ5LnNldChcbiAgICAgICAgICAgICAgaW5mbGVjdGlvbi51bmRlcnNjb3JlKGluZmxlY3Rpb24ucGx1cmFsaXplKGVudGl0eS5pZCkpLFxuICAgICAgICAgICAgICBgJHtlbnRpdHkudGl0bGV966as7Iqk7Yq4YCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZW50aXR5LnByb3BzLmZvckVhY2goKHByb3ApID0+IHtcbiAgICAgICAgICAgIGlmIChnbG9zc2FyeS5oYXMocHJvcC5uYW1lKSkge1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocHJvcC5kZXNjKSB7XG4gICAgICAgICAgICAgIGdsb3NzYXJ5LnNldChwcm9wLm5hbWUsIHByb3AuZGVzYy5yZXBsYWNlKGVudGl0eS50aXRsZSA/PyBcIlwiLCBcIntFbnRpdHlJRH1cIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgc3VnZ2VzdGVkID0gKCgpID0+IHtcbiAgICAgICAgICAvLyDri6jslrQg67aE66asLCDqsIDriqXtlZwg7KGw7ZWpIOyDneyEsVxuICAgICAgICAgIGNvbnN0IHdvcmRzID0gb3JpZ2luLnNwbGl0KFwiX1wiKTtcbiAgICAgICAgICBjb25zdCBjb21iaW5hdGlvbnMgPSBbLi4ucmFuZ2Uod29yZHMubGVuZ3RoLCAwLCAtMSldLmZsYXRNYXAoKGxlbikgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgLi4ucmFuZ2UoMCwgd29yZHMubGVuZ3RoIC0gbGVuICsgMSwgKGlkeCkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICBsZW4sXG4gICAgICAgICAgICAgICAgICB3OiB3b3Jkcy5zbGljZShpZHgsIGlkeCArIGxlbikuam9pbihcIl9cIiksXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBdO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8g7KGw7ZWp7J2EIOyInO2ajO2VmOupsCwg7LmY7ZmYIOyaqeyWtOynkeyXkCDsnojripQg64uo7Ja06rCAIO2PrO2VqOuQnCDqsr3smrAsIOy5mO2ZmCDsmqnslrTroZwg7LmY7ZmYXG4gICAgICAgICAgY29uc3QgUkVQTEFDRURfUFJFRklYID0gXCIjUkVQTEFDRUQvL1wiOyAvLyDsuZjtmZjrkJwg64uo7Ja066W8IGpvaW4g7J207ZuE7JeQ64+EIOyLneuzhO2VmOq4sCDsnITtlbQgcHJlZml4IOy2lOqwgFxuICAgICAgICAgIGxldCByZW1haW5BcnI6IHN0cmluZ1tdID0gWy4uLndvcmRzXTtcbiAgICAgICAgICBmb3IgKGNvbnN0IGNvbWIgb2YgY29tYmluYXRpb25zKSB7XG4gICAgICAgICAgICBjb25zdCByZW1haW5TdHIgPSByZW1haW5BcnIuam9pbihcIl9cIik7XG4gICAgICAgICAgICBpZiAocmVtYWluU3RyLmluY2x1ZGVzKGNvbWIudykgJiYgZ2xvc3NhcnkuaGFzKGNvbWIudykpIHtcbiAgICAgICAgICAgICAgcmVtYWluQXJyID0gcmVtYWluU3RyXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoY29tYi53LCBSRVBMQUNFRF9QUkVGSVggKyBnbG9zc2FyeS5nZXQoY29tYi53KSlcbiAgICAgICAgICAgICAgICAuc3BsaXQoXCJfXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiByZW1haW5BcnJcbiAgICAgICAgICAgIC5tYXAoKHIpID0+IHtcbiAgICAgICAgICAgICAgaWYgKHIuc3RhcnRzV2l0aChSRVBMQUNFRF9QUkVGSVgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHIucmVwbGFjZShSRVBMQUNFRF9QUkVGSVgsIFwiXCIpO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiByLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuam9pbihcIlwiKVxuICAgICAgICAgICAgLnJlcGxhY2UoL3tFbnRpdHlJRH0vZywgZW50aXR5SWQgPyBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCkudGl0bGUgOiBcIlwiKTtcbiAgICAgICAgfSkoKTtcblxuICAgICAgICByZXR1cm4geyBzdWdnZXN0ZWQgfTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIuZ2V0KFwiL2FwaS9lbnRpdHkvZmluZE1hbnlcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBlbnRpdHlJZHMgPSBFbnRpdHlNYW5hZ2VyLmdldEFsbElkcygpO1xuXG4gICAgICAgIGZ1bmN0aW9uIGZsYXR0ZW5TdWJzZXRSb3dzKHN1YnNldFJvd3M6IEVudGl0eVN1YnNldFJvd1tdKTogRmxhdHRlblN1YnNldFJvd1tdIHtcbiAgICAgICAgICByZXR1cm4gc3Vic2V0Um93cy5mbGF0TWFwKChzdWJzZXRSb3cpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHsgY2hpbGRyZW4sIC4uLnNSb3cgfSA9IHN1YnNldFJvdztcbiAgICAgICAgICAgIHJldHVybiBbc1JvdywgLi4uZmxhdHRlblN1YnNldFJvd3MoY2hpbGRyZW4pXTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGVudGl0aWVzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgZW50aXR5SWRzLm1hcCgoZW50aXR5SWQpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKTtcbiAgICAgICAgICAgIGNvbnN0IHN1YnNldFJvd3MgPSBlbnRpdHkuZ2V0U3Vic2V0Um93cygpO1xuXG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAuLi5lbnRpdHksXG4gICAgICAgICAgICAgIGZsYXR0ZW5TdWJzZXRSb3dzOiBmbGF0dGVuU3Vic2V0Um93cyhzdWJzZXRSb3dzKSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfSksXG4gICAgICAgICk7XG5cbiAgICAgICAgZW50aXRpZXMuc29ydCgoYSwgYikgPT4ge1xuICAgICAgICAgIGNvbnN0IGFJZCA9IGEucGFyZW50SWQgPz8gYS5pZDtcbiAgICAgICAgICBjb25zdCBiSWQgPSBiLnBhcmVudElkID8/IGIuaWQ7XG4gICAgICAgICAgaWYgKGFJZCA8IGJJZCkgcmV0dXJuIC0xO1xuICAgICAgICAgIGlmIChhSWQgPiBiSWQpIHJldHVybiAxO1xuICAgICAgICAgIGlmIChhSWQgPT09IGJJZCkge1xuICAgICAgICAgICAgaWYgKGEucGFyZW50SWQgPT09IHVuZGVmaW5lZCkgcmV0dXJuIC0xO1xuICAgICAgICAgICAgaWYgKGIucGFyZW50SWQgPT09IHVuZGVmaW5lZCkgcmV0dXJuIDE7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4geyBlbnRpdGllcyB9O1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5nZXQ8e1xuICAgICAgICBRdWVyeXN0cmluZzoge1xuICAgICAgICAgIGZpbHRlcj86IFwiZW51bXNcIiB8IFwidHlwZXNcIjtcbiAgICAgICAgICByZWxvYWQ/OiBcIjFcIjtcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9lbnRpdHkvdHlwZUlkc1wiLCBhc3luYyAocmVxdWVzdCk6IFByb21pc2U8eyB0eXBlSWRzOiBzdHJpbmdbXSB9PiA9PiB7XG4gICAgICAgIGNvbnN0IHsgZmlsdGVyLCByZWxvYWQgfSA9IHJlcXVlc3QucXVlcnk7XG5cbiAgICAgICAgaWYgKHJlbG9hZCA9PT0gXCIxXCIpIHtcbiAgICAgICAgICBhd2FpdCBTb25hbXUuc3luY2VyLmF1dG9sb2FkVHlwZXMoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHR5cGVJZHMgPSAoKCkgPT4ge1xuICAgICAgICAgIC8vIO2UhOuhnOygne2KuOyXkOyEnCDsoJXsnZjtlZwg7YOA7J6F65OkXG4gICAgICAgICAgY29uc3QgcHJvamVjdFR5cGVJZHMgPSBPYmplY3QuZW50cmllcyhTb25hbXUuc3luY2VyLnR5cGVzKVxuICAgICAgICAgICAgLmZpbHRlcigoW190eXBlSWQsIHpvZFR5cGVdKSA9PiAoem9kVHlwZS5fem9kLmRlZi50eXBlIGFzIHN0cmluZykgIT09IFwiZW51bVwiKVxuICAgICAgICAgICAgLm1hcCgoW3R5cGVJZCwgX3pvZFR5cGVdKSA9PiB0eXBlSWQpO1xuXG4gICAgICAgICAgLy8g64K07J6lIO2DgOyeheuTpCAoc29uYW11IOy9lOyWtOyXkOyEnCDsoJzqs7UpXG4gICAgICAgICAgY29uc3QgYnVpbHRJblR5cGVJZHMgPSBbLi4uQlVJTFRfSU5fVFlQRV9JRFNdO1xuXG4gICAgICAgICAgLy8g66qo65OgIO2DgOyehSDrs5HtlalcbiAgICAgICAgICBjb25zdCBhbGxUeXBlSWRzID0gWy4uLmJ1aWx0SW5UeXBlSWRzLCAuLi5wcm9qZWN0VHlwZUlkc107XG5cbiAgICAgICAgICBpZiAoZmlsdGVyID09PSBcInR5cGVzXCIpIHtcbiAgICAgICAgICAgIHJldHVybiBhbGxUeXBlSWRzO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGVudW1JZHMgPSBFbnRpdHlNYW5hZ2VyLmdldEFsbElkcygpLmZsYXRNYXAoKGVudGl0eUlkKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgICAgICAgICByZXR1cm4gT2JqZWN0LmtleXMoZW50aXR5LmVudW1MYWJlbHMpO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgaWYgKGZpbHRlciA9PT0gXCJlbnVtc1wiKSB7XG4gICAgICAgICAgICByZXR1cm4gZW51bUlkcztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIFsuLi5hbGxUeXBlSWRzLCAuLi5lbnVtSWRzXTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pKCk7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0eXBlSWRzLFxuICAgICAgICB9O1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIGZvcm06IHtcbiAgICAgICAgICAgIGlkOiBzdHJpbmc7XG4gICAgICAgICAgICB0aXRsZTogc3RyaW5nO1xuICAgICAgICAgICAgdGFibGU6IHN0cmluZztcbiAgICAgICAgICAgIHBhcmVudElkPzogc3RyaW5nO1xuICAgICAgICAgIH07XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvZW50aXR5L2NyZWF0ZVwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICByZXR1cm4gYXdhaXQgd2FpdEZvckhNUkNvbXBsZXRlZChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgeyBmb3JtIH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgICAgYXdhaXQgU29uYW11LnN5bmNlci5jcmVhdGVFbnRpdHkoeyAuLi5mb3JtLCBlbnRpdHlJZDogZm9ybS5pZCB9KTtcblxuICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBlbnRpdHlJZDogc3RyaW5nO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2VudGl0eS9kZWxcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHdhaXRGb3JITVJDb21wbGV0ZWQoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgZW50aXR5SWQgfSA9IHJlcXVlc3QuYm9keTtcbiAgICAgICAgICByZXR1cm4gYXdhaXQgU29uYW11LnN5bmNlci5kZWxFbnRpdHkoZW50aXR5SWQpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBlbnRpdHlJZDogc3RyaW5nO1xuICAgICAgICAgIG5ld1ZhbHVlczoge1xuICAgICAgICAgICAgdGl0bGU6IHN0cmluZztcbiAgICAgICAgICAgIHRhYmxlOiBzdHJpbmc7XG4gICAgICAgICAgICBwYXJlbnRJZD86IHN0cmluZztcbiAgICAgICAgICB9O1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2VudGl0eS9tb2RpZnlFbnRpdHlCYXNlXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIHJldHVybiBhd2FpdCB3YWl0Rm9ySE1SQ29tcGxldGVkKGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCB7IGVudGl0eUlkLCBuZXdWYWx1ZXMgfSA9IHJlcXVlc3QuYm9keTtcbiAgICAgICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgICAgICAgZW50aXR5LnRpdGxlID0gbmV3VmFsdWVzLnRpdGxlO1xuICAgICAgICAgIGVudGl0eS50YWJsZSA9IG5ld1ZhbHVlcy50YWJsZTtcbiAgICAgICAgICBlbnRpdHkucGFyZW50SWQgPSBuZXdWYWx1ZXMucGFyZW50SWQ7XG4gICAgICAgICAgYXdhaXQgZW50aXR5LnNhdmUoKTtcblxuICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBlbnRpdHlJZDogc3RyaW5nO1xuICAgICAgICAgIHN1YnNldEtleTogc3RyaW5nO1xuICAgICAgICAgIGZpZWxkczogc3RyaW5nW107XG4gICAgICAgICAgZmllbGRzSW50ZXJuYWw/OiBzdHJpbmdbXTtcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9lbnRpdHkvbW9kaWZ5U3Vic2V0XCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIHJldHVybiBhd2FpdCB3YWl0Rm9ySE1SQ29tcGxldGVkKGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCB7IGVudGl0eUlkLCBzdWJzZXRLZXksIGZpZWxkcywgZmllbGRzSW50ZXJuYWwgfSA9IHJlcXVlc3QuYm9keTtcbiAgICAgICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgICAgICAgZW50aXR5LnN1YnNldHNbc3Vic2V0S2V5XSA9IGZpZWxkcztcbiAgICAgICAgICBpZiAoZmllbGRzSW50ZXJuYWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaWYgKGZpZWxkc0ludGVybmFsLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgZW50aXR5LnN1YnNldHNJbnRlcm5hbFtzdWJzZXRLZXldID0gZmllbGRzSW50ZXJuYWw7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBkZWxldGUgZW50aXR5LnN1YnNldHNJbnRlcm5hbFtzdWJzZXRLZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBhd2FpdCBlbnRpdHkuc2F2ZSgpO1xuXG4gICAgICAgICAgcmV0dXJuIHsgdXBkYXRlZDogZmllbGRzLCB1cGRhdGVkSW50ZXJuYWw6IGZpZWxkc0ludGVybmFsIH07XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIGVudGl0eUlkOiBzdHJpbmc7XG4gICAgICAgICAgc3Vic2V0S2V5OiBzdHJpbmc7XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvZW50aXR5L2RlbFN1YnNldFwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICByZXR1cm4gYXdhaXQgd2FpdEZvckhNUkNvbXBsZXRlZChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgeyBlbnRpdHlJZCwgc3Vic2V0S2V5IH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgIGRlbGV0ZSBlbnRpdHkuc3Vic2V0c1tzdWJzZXRLZXldO1xuICAgICAgICAgIGRlbGV0ZSBlbnRpdHkuc3Vic2V0c0ludGVybmFsW3N1YnNldEtleV07XG4gICAgICAgICAgYXdhaXQgZW50aXR5LnNhdmUoKTtcblxuICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBlbnRpdHlJZDogc3RyaW5nO1xuICAgICAgICAgIG5ld1Byb3A6IEVudGl0eVByb3A7XG4gICAgICAgICAgYXQ/OiBudW1iZXI7XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvZW50aXR5L2NyZWF0ZVByb3BcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHdhaXRGb3JITVJDb21wbGV0ZWQoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgZW50aXR5SWQsIGF0LCBuZXdQcm9wIH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgIGF3YWl0IGVudGl0eS5jcmVhdGVQcm9wKG5ld1Byb3AsIGF0KTtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5SWQ6IHN0cmluZztcbiAgICAgICAgICBuZXdQcm9wOiBFbnRpdHlQcm9wO1xuICAgICAgICAgIGF0OiBudW1iZXI7XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvZW50aXR5L21vZGlmeVByb3BcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHdhaXRGb3JITVJDb21wbGV0ZWQoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgZW50aXR5SWQsIGF0LCBuZXdQcm9wIH0gPSByZXF1ZXN0LmJvZHk7XG5cbiAgICAgICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgICAgICAgZW50aXR5Lm1vZGlmeVByb3AobmV3UHJvcCwgYXQpO1xuXG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIGVudGl0eUlkOiBzdHJpbmc7XG4gICAgICAgICAgYXQ6IG51bWJlcjtcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9lbnRpdHkvZGVsUHJvcFwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICByZXR1cm4gYXdhaXQgd2FpdEZvckhNUkNvbXBsZXRlZChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgeyBlbnRpdHlJZCwgYXQgfSA9IHJlcXVlc3QuYm9keTtcblxuICAgICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKTtcbiAgICAgICAgICBlbnRpdHkuZGVsUHJvcChhdCk7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIGVudGl0eUlkOiBzdHJpbmc7XG4gICAgICAgICAgYXQ6IG51bWJlcjtcbiAgICAgICAgICB0bzogbnVtYmVyO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2VudGl0eS9tb3ZlUHJvcFwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICByZXR1cm4gYXdhaXQgd2FpdEZvckhNUkNvbXBsZXRlZChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgeyBlbnRpdHlJZCwgYXQsIHRvIH0gPSByZXF1ZXN0LmJvZHk7XG5cbiAgICAgICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgICAgICAgZW50aXR5Lm1vdmVQcm9wKGF0LCB0byk7XG5cbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5SWQ6IHN0cmluZztcbiAgICAgICAgICBpbmRleGVzOiBFbnRpdHlJbmRleFtdO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2VudGl0eS9tb2RpZnlJbmRleGVzXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIHJldHVybiBhd2FpdCB3YWl0Rm9ySE1SQ29tcGxldGVkKGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCB7IGVudGl0eUlkLCBpbmRleGVzIH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgIGVudGl0eS5pbmRleGVzID0gaW5kZXhlcztcbiAgICAgICAgICBhd2FpdCBlbnRpdHkuc2F2ZSgpO1xuXG4gICAgICAgICAgcmV0dXJuIHsgdXBkYXRlZDogaW5kZXhlcyB9O1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBlbnRpdHlJZDogc3RyaW5nO1xuICAgICAgICAgIGVudW1MYWJlbHM6IEVudGl0eVtcImVudW1MYWJlbHNcIl07XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvZW50aXR5L21vZGlmeUVudW1MYWJlbHNcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHdhaXRGb3JITVJDb21wbGV0ZWQoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgZW50aXR5SWQsIGVudW1MYWJlbHMgfSA9IHJlcXVlc3QuYm9keTtcbiAgICAgICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgICAgICAgZW50aXR5LmVudW1MYWJlbHMgPSBlbnVtTGFiZWxzO1xuICAgICAgICAgIGF3YWl0IGVudGl0eS5zYXZlKCk7XG5cbiAgICAgICAgICByZXR1cm4geyB1cGRhdGVkOiBlbnVtTGFiZWxzIH07XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIGVudGl0eUlkOiBzdHJpbmc7XG4gICAgICAgICAgbmV3RW51bUlkOiBzdHJpbmc7XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvZW50aXR5L2NyZWF0ZUVudW1JZFwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICByZXR1cm4gYXdhaXQgd2FpdEZvckhNUkNvbXBsZXRlZChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgeyBlbnRpdHlJZCwgbmV3RW51bUlkIH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuXG4gICAgICAgICAgaWYgKGVudGl0eS5lbnVtTGFiZWxzW25ld0VudW1JZF0pIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihg7J2066+4IOyhtOyerO2VmOuKlCBlbnVtSWTsnoXri4jri6Q6ICR7bmV3RW51bUlkfWApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGVudGl0eS5lbnVtTGFiZWxzW25ld0VudW1JZF0gPSBuZXdFbnVtSWQuZW5kc1dpdGgoXCJTdGF0dXNcIilcbiAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgIGFjdGl2ZTogXCLrhbjstpxcIixcbiAgICAgICAgICAgICAgICBoaWRkZW46IFwi7Iio6rmAXCIsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgIFwiXCI6IFwiXCIsXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgYXdhaXQgZW50aXR5LnNhdmUoKTtcblxuICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBlbnRpdHlJZDogc3RyaW5nO1xuICAgICAgICAgIGVudW1JZDoge1xuICAgICAgICAgICAgYmVmb3JlOiBzdHJpbmc7XG4gICAgICAgICAgICBhZnRlcjogc3RyaW5nO1xuICAgICAgICAgIH07XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvZW50aXR5L21vZGlmeUVudW1JZFwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICByZXR1cm4gYXdhaXQgd2FpdEZvckhNUkNvbXBsZXRlZChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgeyBlbnRpdHlJZCwgZW51bUlkIH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgICAgY29uc3QgZW50aXR5SWRzID0gRW50aXR5TWFuYWdlci5nZXRBbGxJZHMoKTtcbiAgICAgICAgICBjb25zdCBpc0V4aXN0cyA9IGVudGl0eUlkcy5zb21lKChlbnRpdHlJZCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKGVudGl0eS5lbnVtTGFiZWxzKS5pbmNsdWRlcyhlbnVtSWQuYWZ0ZXIpO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIGlmIChpc0V4aXN0cykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGDsnbTrr7gg7KG07J6s7ZWY64qUIEVudW1JZOyeheuLiOuLpDogJHtlbnVtSWQuYWZ0ZXJ9YCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgIGVudGl0eS5lbnVtTGFiZWxzW2VudW1JZC5hZnRlcl0gPSBlbnRpdHkuZW51bUxhYmVsc1tlbnVtSWQuYmVmb3JlXTtcbiAgICAgICAgICBkZWxldGUgZW50aXR5LmVudW1MYWJlbHNbZW51bUlkLmJlZm9yZV07XG5cbiAgICAgICAgICBhd2FpdCBlbnRpdHkuc2F2ZSgpO1xuXG4gICAgICAgICAgZm9yIChjb25zdCBlbnRpdHlJZCBvZiBlbnRpdHlJZHMpIHtcbiAgICAgICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgcHJvcCBvZiBlbnRpdHkucHJvcHMpIHtcbiAgICAgICAgICAgICAgaWYgKHByb3AudHlwZSA9PT0gXCJlbnVtXCIgJiYgcHJvcC5pZCA9PT0gZW51bUlkLmJlZm9yZSkge1xuICAgICAgICAgICAgICAgIHByb3AuaWQgPSBlbnVtSWQuYWZ0ZXI7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGF3YWl0IGVudGl0eS5zYXZlKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBlbnRpdHlJZDogc3RyaW5nO1xuICAgICAgICAgIGVudW1JZDogc3RyaW5nO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2VudGl0eS9kZWxldGVFbnVtSWRcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHdhaXRGb3JITVJDb21wbGV0ZWQoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgZW50aXR5SWQsIGVudW1JZCB9ID0gcmVxdWVzdC5ib2R5O1xuXG4gICAgICAgICAgY29uc3QgZW50aXR5SWRzID0gRW50aXR5TWFuYWdlci5nZXRBbGxJZHMoKTtcbiAgICAgICAgICBjb25zdCBpc1JlZmVyZW5jZWQgPSBlbnRpdHlJZHNcbiAgICAgICAgICAgIC5mbGF0TWFwKChlbnRpdHlJZCkgPT4gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpLnByb3BzKVxuICAgICAgICAgICAgLnNvbWUoKHByb3ApID0+IHByb3AudHlwZSA9PT0gXCJlbnVtXCIgJiYgcHJvcC5pZCA9PT0gZW51bUlkKTtcbiAgICAgICAgICBpZiAoaXNSZWZlcmVuY2VkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7ZW51bUlkfeulvCDssLjsobDtlZjripQg7ZSE66Gc7Y287Yuw6rCAIOyhtOyerO2VqeuLiOuLpC5gKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgICAgICAgZGVsZXRlIGVudGl0eS5lbnVtTGFiZWxzW2VudW1JZF07XG4gICAgICAgICAgYXdhaXQgZW50aXR5LnNhdmUoKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5SWQ6IHN0cmluZztcbiAgICAgICAgICB0YXJnZXQ6IFwiZW50aXR5XCIgfCBcInByb3BcIiB8IFwiZW51bVwiIHwgXCJzdWJzZXRcIjtcbiAgICAgICAgICBwcm9wTmFtZT86IHN0cmluZztcbiAgICAgICAgICBlbnVtSWQ/OiBzdHJpbmc7XG4gICAgICAgICAgc3Vic2V0S2V5Pzogc3RyaW5nO1xuICAgICAgICAgIGNvbmU6IENvbmU7XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvZW50aXR5L3VwZGF0ZUNvbmVcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHdhaXRGb3JITVJDb21wbGV0ZWQoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgZW50aXR5SWQsIHRhcmdldCwgcHJvcE5hbWUsIGVudW1JZCwgc3Vic2V0S2V5LCBjb25lIH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuXG4gICAgICAgICAgaWYgKHRhcmdldCA9PT0gXCJlbnRpdHlcIikge1xuICAgICAgICAgICAgZW50aXR5LmNvbmUgPSBjb25lO1xuICAgICAgICAgIH0gZWxzZSBpZiAodGFyZ2V0ID09PSBcInByb3BcIiAmJiBwcm9wTmFtZSkge1xuICAgICAgICAgICAgY29uc3QgcHJvcCA9IGVudGl0eS5wcm9wcy5maW5kKChwKSA9PiBwLm5hbWUgPT09IHByb3BOYW1lKTtcbiAgICAgICAgICAgIGlmIChwcm9wKSB7XG4gICAgICAgICAgICAgIChwcm9wIGFzIHsgY29uZT86IENvbmUgfSkuY29uZSA9IGNvbmU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIGlmICh0YXJnZXQgPT09IFwiZW51bVwiICYmIGVudW1JZCkge1xuICAgICAgICAgICAgZW50aXR5LmVudW1Db25lc1tlbnVtSWRdID0gY29uZTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHRhcmdldCA9PT0gXCJzdWJzZXRcIiAmJiBzdWJzZXRLZXkpIHtcbiAgICAgICAgICAgIGVudGl0eS5zdWJzZXRDb25lc1tzdWJzZXRLZXldID0gY29uZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBhd2FpdCBlbnRpdHkuc2F2ZSgpO1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBlbnRpdHlJZDogc3RyaW5nO1xuICAgICAgICAgIHByZXNlcnZlRXhpc3Rpbmc/OiBib29sZWFuO1xuICAgICAgICAgIG9ubHlFbXB0eT86IGJvb2xlYW47XG4gICAgICAgICAgbG9jYWxlPzogXCJrb1wiIHwgXCJlblwiIHwgXCJqYVwiO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2VudGl0eS9nZW5lcmF0ZUNvbmVzXCIsIGFzeW5jIChyZXF1ZXN0LCByZXBseSkgPT4ge1xuICAgICAgICByZXR1cm4gYXdhaXQgd2FpdEZvckhNUkNvbXBsZXRlZChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgeyBlbnRpdHlJZCwgcHJlc2VydmVFeGlzdGluZywgb25seUVtcHR5LCBsb2NhbGUgfSA9IHJlcXVlc3QuYm9keTtcblxuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBFbnRpdHkg7KG07J6sIOyXrOu2gCDtmZXsnbhcbiAgICAgICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKTtcblxuICAgICAgICAgICAgLy8gbG9jYWxlIOq4sOuzuOqwkjogU29uYW11LmNvbmZpZy5pMThuLmRlZmF1bHRMb2NhbGUg7IKs7JqpXG4gICAgICAgICAgICBjb25zdCBlZmZlY3RpdmVMb2NhbGUgPVxuICAgICAgICAgICAgICBsb2NhbGUgPz8gKFNvbmFtdS5jb25maWcuaTE4bi5kZWZhdWx0TG9jYWxlIGFzIFwia29cIiB8IFwiZW5cIiB8IFwiamFcIik7XG5cbiAgICAgICAgICAgIC8vIENvbmUg7IOd7ISxXG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBlbnRpdHkuZ2VuZXJhdGVDb25lcyh7XG4gICAgICAgICAgICAgIHByZXNlcnZlRXhpc3Rpbmc6IHByZXNlcnZlRXhpc3RpbmcgPz8gdHJ1ZSxcbiAgICAgICAgICAgICAgb25seUVtcHR5OiBvbmx5RW1wdHkgPz8gZmFsc2UsXG4gICAgICAgICAgICAgIGxvY2FsZTogZWZmZWN0aXZlTG9jYWxlLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcik7XG5cbiAgICAgICAgICAgIC8vIEVudGl0eSBub3QgZm91bmRcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmluY2x1ZGVzKFwi7KG07J6s7ZWY7KeAIOyViuuKlCBFbnRpdHlcIikpIHtcbiAgICAgICAgICAgICAgcmVwbHkuc3RhdHVzKDQwNCk7XG4gICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgICAgICAgICAgZXJyb3I6IGBFbnRpdHkgbm90IGZvdW5kOiAke2VudGl0eUlkfWAsXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEFQSSDtgqQg7JeG7J2MXG4gICAgICAgICAgICBpZiAobWVzc2FnZS5pbmNsdWRlcyhcIkFOVEhST1BJQ19BUElfS0VZIG5vdCBmb3VuZFwiKSkge1xuICAgICAgICAgICAgICByZXBseS5zdGF0dXMoNTAwKTtcbiAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBlcnJvcjogXCJBUEkga2V5IG5vdCBjb25maWd1cmVkXCIsXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFJhdGUgbGltaXRcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmluY2x1ZGVzKFwiUmF0ZSBsaW1pdCBleGNlZWRlZFwiKSkge1xuICAgICAgICAgICAgICByZXBseS5zdGF0dXMoNDI5KTtcbiAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBlcnJvcjogXCJSYXRlIGxpbWl0IGV4Y2VlZGVkLiBQbGVhc2UgdHJ5IGFnYWluIGxhdGVyLlwiLFxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyDquLDtg4Ag7JeQ65+sXG4gICAgICAgICAgICByZXBseS5zdGF0dXMoNTAwKTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgICAgICAgICBlcnJvcjogYENvbmUgZ2VuZXJhdGlvbiBmYWlsZWQ6ICR7bWVzc2FnZX1gLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5nZXQ8e1xuICAgICAgICBRdWVyeXN0cmluZzoge1xuICAgICAgICAgIGVudGl0eUlkOiBzdHJpbmc7XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvZW50aXR5L2dldFRhYmxlQ29sdW1uc1wiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICBjb25zdCB7IGVudGl0eUlkIH0gPSByZXF1ZXN0LnF1ZXJ5O1xuICAgICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgICAgIGNvbnN0IGNvbHVtbnMgPSBlbnRpdHkuZ2V0VGFibGVDb2x1bW5zKCk7XG4gICAgICAgIHJldHVybiB7IGNvbHVtbnMgfTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIuZ2V0KFwiL2FwaS9taWdyYXRpb25zL3N0YXR1c1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHN0YXR1cyA9IGF3YWl0IG1pZ3JhdG9yLmdldFN0YXR1cygpO1xuXG4gICAgICAgIHJldHVybiB7IHN0YXR1cyB9O1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIGFjdGlvbjogXCJhcHBseVwiIHwgXCJyb2xsYmFja1wiIHwgXCJzaGFkb3dcIjtcbiAgICAgICAgICB0YXJnZXRzOiAoa2V5b2YgU29uYW11REJDb25maWcpW107XG4gICAgICAgICAgZm9yY2U/OiBib29sZWFuO1xuICAgICAgICAgIGZvcmNlUmVhc29uPzogc3RyaW5nO1xuICAgICAgICAgIHJlcXVlc3Rvcj86IHN0cmluZztcbiAgICAgICAgfTtcbiAgICAgIH0+KFxuICAgICAgICBcIi9hcGkvbWlncmF0aW9ucy9ydW5BY3Rpb25cIixcbiAgICAgICAgYXN5bmMgKHJlcXVlc3QpOiBQcm9taXNlPE1pZ3JhdGlvblJlc3VsdCB8IFNsYWNrQ29uZmlybVBlbmRpbmdSZXN1bHQ+ID0+IHtcbiAgICAgICAgICBjb25zdCB7IGFjdGlvbiwgdGFyZ2V0cywgZm9yY2UsIGZvcmNlUmVhc29uLCByZXF1ZXN0b3IgfSA9IHJlcXVlc3QuYm9keTtcblxuICAgICAgICAgIGlmIChhY3Rpb24gPT09IFwic2hhZG93XCIpIHtcbiAgICAgICAgICAgIHJldHVybiBtaWdyYXRvci5ydW5TaGFkb3dUZXN0KCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gU2xhY2sg7Iq57J24IOyytO2BrCAoYXBwbHkg7Iuc7JeQ66eMKVxuICAgICAgICAgIGlmIChhY3Rpb24gPT09IFwiYXBwbHlcIikge1xuICAgICAgICAgICAgY29uc3Qgc2xhY2tDb25maXJtID0gbmV3IFNsYWNrQ29uZmlybSgpO1xuICAgICAgICAgICAgY29uc3QgcmVxdWlyZXNBcHByb3ZhbCA9IHRhcmdldHMuc29tZSgodCkgPT4gc2xhY2tDb25maXJtLmlzVGFyZ2V0UmVxdWlyZXNBcHByb3ZhbCh0KSk7XG5cbiAgICAgICAgICAgIC8vIOuhnOy7rCBEQuyduCDqsr3smrAg7Iq57J24IOyKpO2CtVxuICAgICAgICAgICAgY29uc3QgbG9jYWxIb3N0cyA9IFtcImxvY2FsaG9zdFwiLCBcIjEyNy4wLjAuMVwiLCBcIjAuMC4wLjBcIiwgXCI6OjFcIl07XG4gICAgICAgICAgICBjb25zdCBpc0xvY2FsVGFyZ2V0ID0gdGFyZ2V0cy5ldmVyeSgodGFyZ2V0KSA9PiB7XG4gICAgICAgICAgICAgIGNvbnN0IHRhcmdldENvbmZpZyA9IFNvbmFtdS5kYkNvbmZpZ1t0YXJnZXRdO1xuICAgICAgICAgICAgICBjb25zdCBob3N0ID0gKHRhcmdldENvbmZpZz8uY29ubmVjdGlvbiBhcyB7IGhvc3Q/OiBzdHJpbmcgfSk/Lmhvc3QgPz8gXCJsb2NhbGhvc3RcIjtcbiAgICAgICAgICAgICAgcmV0dXJuIGxvY2FsSG9zdHMuaW5jbHVkZXMoaG9zdC50b0xvd2VyQ2FzZSgpKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZiAocmVxdWlyZXNBcHByb3ZhbCAmJiBzbGFja0NvbmZpcm0uaXNDb25maWd1cmVkKCkgJiYgIWlzTG9jYWxUYXJnZXQpIHtcbiAgICAgICAgICAgICAgY29uc3QgeyBjb25ucyB9ID0gYXdhaXQgbWlncmF0b3IuZ2V0U3RhdHVzKCk7XG5cbiAgICAgICAgICAgICAgLy8g66qo65OgIO2DgOqynyBEQuyXkOyEnCBwZW5kaW5n7J24IOuniOydtOq3uOugiOydtOyFmOydmCDtlansp5HtlansnYQg6rWs7ZWp64uI64ukLlxuICAgICAgICAgICAgICBjb25zdCBwZW5kaW5nTWlncmF0aW9ucyA9IFtcbiAgICAgICAgICAgICAgICAuLi5uZXcgU2V0KFxuICAgICAgICAgICAgICAgICAgY29ubnNcbiAgICAgICAgICAgICAgICAgICAgLmZpbHRlcigoY29ubikgPT4gdGFyZ2V0cy5pbmNsdWRlcyhjb25uLmNvbm5LZXkpKVxuICAgICAgICAgICAgICAgICAgICAuZmxhdE1hcCgoY29ubikgPT4gY29ubi5wZW5kaW5nKSxcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICBdO1xuXG4gICAgICAgICAgICAgIGlmIChwZW5kaW5nTWlncmF0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgLy8g6riw7KG0IOyKueyduCDsmpTssq0g7ZmV7J24XG4gICAgICAgICAgICAgICAgY29uc3QgZXhpc3RpbmcgPSBhd2FpdCBzbGFja0NvbmZpcm0uZ2V0RXhpc3RpbmdSZXF1ZXN0KHBlbmRpbmdNaWdyYXRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChleGlzdGluZykge1xuICAgICAgICAgICAgICAgICAgLy8g6riw7KG0IOyalOyyreydtCDsnojsnLzrqbQg7Iq57J24IOyDge2DnCDtmZXsnbhcbiAgICAgICAgICAgICAgICAgIGNvbnN0IHsgYXBwcm92ZWQsIHJlamVjdGVkIH0gPSBhd2FpdCBzbGFja0NvbmZpcm0uY2hlY2tBcHByb3ZhbChcbiAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmcuY2hhbm5lbCxcbiAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmcudHMsXG4gICAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgICBpZiAoYXBwcm92ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8g7Iq57J2465CoIOKGkiDsi6TtlolcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgbWlncmF0b3IucnVuQWN0aW9uKGFjdGlvbiwgdGFyZ2V0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHNsYWNrQ29uZmlybS5sb2dFeGVjdXRpb24oXG4gICAgICAgICAgICAgICAgICAgICAgICBleGlzdGluZy5jaGFubmVsLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmcudHMsXG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQsXG4gICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0b3IsXG4gICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChyZWplY3RlZCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihTRChcInNvbmFtdS5lcnJvci5taWdyYXRpb25SZWplY3RlZFwiKSk7XG4gICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGZvcmNlKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEZvcmNlIOynhO2WiVxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBzbGFja0NvbmZpcm0uZm9yY2VBcHByb3ZhbChcbiAgICAgICAgICAgICAgICAgICAgICBleGlzdGluZy5jaGFubmVsLFxuICAgICAgICAgICAgICAgICAgICAgIGV4aXN0aW5nLnRzLFxuICAgICAgICAgICAgICAgICAgICAgIGZvcmNlUmVhc29uID8/IFwi7IKs7JygIOyXhuydjFwiLFxuICAgICAgICAgICAgICAgICAgICAgIHJlcXVlc3RvcixcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgbWlncmF0b3IucnVuQWN0aW9uKGFjdGlvbiwgdGFyZ2V0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHNsYWNrQ29uZmlybS5sb2dFeGVjdXRpb24oXG4gICAgICAgICAgICAgICAgICAgICAgICBleGlzdGluZy5jaGFubmVsLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmcudHMsXG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQsXG4gICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0b3IsXG4gICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8g64yA6riw7KSRXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJwZW5kaW5nXCIsXG4gICAgICAgICAgICAgICAgICAgICAgY2hhbm5lbDogZXhpc3RpbmcuY2hhbm5lbCxcbiAgICAgICAgICAgICAgICAgICAgICB0czogZXhpc3RpbmcudHMsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIC8vIOyDiCDsirnsnbgg7JqU7LKtIOuwnOyGoVxuICAgICAgICAgICAgICAgICAgY29uc3QgeyBjaGFubmVsLCB0cyB9ID0gYXdhaXQgc2xhY2tDb25maXJtLnBvc3RBcHByb3ZhbFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAgIHBlbmRpbmdNaWdyYXRpb25zLFxuICAgICAgICAgICAgICAgICAgICB0YXJnZXRzLFxuICAgICAgICAgICAgICAgICAgICByZXF1ZXN0b3IsXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgYXdhaXQgc2xhY2tDb25maXJtLnNhdmVSZXF1ZXN0KHBlbmRpbmdNaWdyYXRpb25zLCBjaGFubmVsLCB0cyk7XG5cbiAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IFwicGVuZGluZ1wiLFxuICAgICAgICAgICAgICAgICAgICBjaGFubmVsLFxuICAgICAgICAgICAgICAgICAgICB0cyxcbiAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIG1pZ3JhdG9yLnJ1bkFjdGlvbihhY3Rpb24sIHRhcmdldHMpO1xuICAgICAgICB9LFxuICAgICAgKTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgY2hhbm5lbDogc3RyaW5nO1xuICAgICAgICAgIHRzOiBzdHJpbmc7XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvbWlncmF0aW9ucy9jaGVja0FwcHJvdmFsXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgY2hhbm5lbCwgdHMgfSA9IHJlcXVlc3QuYm9keTtcbiAgICAgICAgY29uc3Qgc2xhY2tDb25maXJtID0gbmV3IFNsYWNrQ29uZmlybSgpO1xuXG4gICAgICAgIGlmICghc2xhY2tDb25maXJtLmlzQ29uZmlndXJlZCgpKSB7XG4gICAgICAgICAgcmV0dXJuIHsgYXBwcm92ZWQ6IHRydWUsIHJlamVjdGVkOiBmYWxzZSB9O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHNsYWNrQ29uZmlybS5jaGVja0FwcHJvdmFsKGNoYW5uZWwsIHRzKTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBjaGFubmVsOiBzdHJpbmc7XG4gICAgICAgICAgdHM6IHN0cmluZztcbiAgICAgICAgICByZWFzb246IHN0cmluZztcbiAgICAgICAgICByZXF1ZXN0b3I/OiBzdHJpbmc7XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvbWlncmF0aW9ucy9mb3JjZUFwcHJvdmFsXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgY2hhbm5lbCwgdHMsIHJlYXNvbiwgcmVxdWVzdG9yIH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgIGNvbnN0IHNsYWNrQ29uZmlybSA9IG5ldyBTbGFja0NvbmZpcm0oKTtcblxuICAgICAgICBpZiAoIXNsYWNrQ29uZmlybS5pc0NvbmZpZ3VyZWQoKSkge1xuICAgICAgICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFNEKFwic29uYW11LmVycm9yLnNsYWNrQ29uZmlybU5vdENvbmZpZ3VyZWRcIikpO1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgc2xhY2tDb25maXJtLmZvcmNlQXBwcm92YWwoY2hhbm5lbCwgdHMsIHJlYXNvbiwgcmVxdWVzdG9yKTtcbiAgICAgICAgcmV0dXJuIHsgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIGNvZGVOYW1lczogc3RyaW5nW107XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvbWlncmF0aW9ucy9kZWxDb2Rlc1wiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICBjb25zdCB7IGNvZGVOYW1lcyB9ID0gcmVxdWVzdC5ib2R5O1xuICAgICAgICByZXR1cm4gYXdhaXQgbWlncmF0b3IuZGVsQ29kZXMoY29kZU5hbWVzKTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdChcIi9hcGkvbWlncmF0aW9ucy9nZW5lcmF0ZVByZXBhcmVkQ29kZXNcIiwgYXN5bmMgKF9yZXF1ZXN0dCkgPT4ge1xuICAgICAgICByZXR1cm4gYXdhaXQgbWlncmF0b3IuZ2VuZXJhdGVQcmVwYXJlZENvZGVzKCk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5SWRzOiBzdHJpbmdbXTtcbiAgICAgICAgICB0ZW1wbGF0ZUtleXM6IHN0cmluZ1tdO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL3NjYWZmb2xkaW5nL2dldFN0YXR1c1wiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICBjb25zdCB7IGVudGl0eUlkcywgdGVtcGxhdGVLZXlzOiBfdGVtcGxhdGVLZXlzIH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgIGlmICgoZW50aXR5SWRzID8/IFtdKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihTRChcInNvbmFtdS5lcnJvci5lbnRpdHlJZHNSZXF1aXJlZFwiKSk7XG4gICAgICAgIH0gZWxzZSBpZiAoKF90ZW1wbGF0ZUtleXMgPz8gW10pLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFNEKFwic29uYW11LmVycm9yLnRlbXBsYXRlS2V5c1JlcXVpcmVkXCIpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHNvcnRpbmdcbiAgICAgICAgZW50aXR5SWRzLnNvcnQoKGEsIGIpID0+IChhIDwgYiA/IC0xIDogYSA+IGIgPyAxIDogMCkpO1xuICAgICAgICBjb25zdCB0ZW1wbGF0ZUtleXMgPSBUZW1wbGF0ZUtleS5vcHRpb25zLmZpbHRlcigodGspID0+IF90ZW1wbGF0ZUtleXMuaW5jbHVkZXModGspKTtcblxuICAgICAgICBjb25zdCBjb21iaW5hdGlvbnMgPSBlbnRpdHlJZHMuZmxhdE1hcCgoZW50aXR5SWQpID0+IHtcbiAgICAgICAgICByZXR1cm4gdGVtcGxhdGVLZXlzLm1hcCgodGVtcGxhdGVLZXkpID0+IFtlbnRpdHlJZCwgdGVtcGxhdGVLZXldKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3Qgc3RhdHVzZXMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgICBjb21iaW5hdGlvbnMubWFwKGFzeW5jIChbZW50aXR5SWQsIHRlbXBsYXRlS2V5XSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgeyBzdWJQYXRoLCBmdWxsUGF0aCwgaXNFeGlzdHMgfSA9IGF3YWl0IFNvbmFtdS5zeW5jZXIuY2hlY2tFeGlzdHNHZW5Db2RlKFxuICAgICAgICAgICAgICBlbnRpdHlJZCxcbiAgICAgICAgICAgICAgdGVtcGxhdGVLZXkgYXMgVGVtcGxhdGVLZXksXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgZW50aXR5SWQsXG4gICAgICAgICAgICAgIHRlbXBsYXRlS2V5LFxuICAgICAgICAgICAgICBzdWJQYXRoLFxuICAgICAgICAgICAgICBmdWxsUGF0aCxcbiAgICAgICAgICAgICAgaXNFeGlzdHMsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4geyBzdGF0dXNlcyB9O1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgIGVudGl0eUlkOiBzdHJpbmc7XG4gICAgICAgICAgICB0ZW1wbGF0ZUtleTogc3RyaW5nO1xuICAgICAgICAgICAgZW51bUlkPzogc3RyaW5nO1xuICAgICAgICAgICAgb3ZlcndyaXRlPzogYm9vbGVhbjtcbiAgICAgICAgICB9W107XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvc2NhZmZvbGRpbmcvZ2VuZXJhdGVcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgeyBvcHRpb25zIH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgIGlmIChvcHRpb25zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFNEKFwic29uYW11LmVycm9yLm9wdGlvbnNSZXF1aXJlZFwiKSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyAxLiDrqqjrk6Ag7YWc7ZSM66a/7JeQ7IScIO2VhOyalO2VnCBkaWN0IO2CpOulvCDsiJjsp5FcbiAgICAgICAgY29uc3Qga2V5cyA9IG9wdGlvbnMuZmxhdE1hcCgoeyB0ZW1wbGF0ZUtleSB9KSA9PiB7XG4gICAgICAgICAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZU1hbmFnZXIuZ2V0KHRlbXBsYXRlS2V5KTtcbiAgICAgICAgICByZXR1cm4gdGVtcGxhdGUuZ2V0UmVxdWlyZWREaWN0S2V5cygpID8/IFtdO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyAyLiB0YXJnZXTrs4TroZwgZW5zdXJlRGljdEtleXMg7Zi47LacICjsiJzssKgg7LKY66asKVxuICAgICAgICBhd2FpdCBzb25hbXVEaWN0aW9uYXJ5LmVuc3VyZURpY3RLZXlzKFsuLi5uZXcgU2V0KGtleXMpXSk7XG5cbiAgICAgICAgLy8gMy4g7YWc7ZSM66a/IOyDneyEsSAo67OR66CsIOyymOumrClcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgb3B0aW9ucy5tYXAoYXN5bmMgKHsgZW50aXR5SWQsIHRlbXBsYXRlS2V5LCBlbnVtSWQsIG92ZXJ3cml0ZSB9KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICByZXR1cm4gYXdhaXQgU29uYW11LnN5bmNlci5nZW5lcmF0ZVRlbXBsYXRlKFxuICAgICAgICAgICAgICAgIHRlbXBsYXRlS2V5IGFzIFRlbXBsYXRlS2V5LFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIGVudGl0eUlkLFxuICAgICAgICAgICAgICAgICAgZW51bUlkLFxuICAgICAgICAgICAgICAgIH0gYXMge1xuICAgICAgICAgICAgICAgICAgZW50aXR5SWQ6IHN0cmluZztcbiAgICAgICAgICAgICAgICAgIGVudW1JZD86IHN0cmluZztcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIG92ZXJ3cml0ZSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICBpZiAoaXNTb0V4Y2VwdGlvbihlKSAmJiBlLnN0YXR1c0NvZGUgPT09IDU0MSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pLFxuICAgICAgICApO1xuXG4gICAgICAgIGlmIChyZXN1bHQuZmlsdGVyKG5vbk51bGxhYmxlKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgU2VydmljZVVuYXZhaWxhYmxlRXhjZXB0aW9uKFNEKFwic29uYW11LmVycm9yLmFsbEZpbGVzR2VuZXJhdGVkXCIpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIG9wdGlvbjoge1xuICAgICAgICAgICAgZW50aXR5SWQ6IHN0cmluZztcbiAgICAgICAgICAgIHRlbXBsYXRlS2V5OiBzdHJpbmc7XG4gICAgICAgICAgICBlbnVtSWQ/OiBzdHJpbmc7XG4gICAgICAgICAgfTtcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9zY2FmZm9sZGluZy9wcmV2aWV3XCIsIGFzeW5jIChyZXF1ZXN0KTogUHJvbWlzZTx7IHBhdGhBbmRDb2RlczogUGF0aEFuZENvZGVbXSB9PiA9PiB7XG4gICAgICAgIGNvbnN0IHsgb3B0aW9uIH0gPSByZXF1ZXN0LmJvZHk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB7IHRlbXBsYXRlS2V5LCAuLi50ZW1wbGF0ZU9wdGlvbnMgfSA9IG9wdGlvbjtcbiAgICAgICAgICBjb25zdCBwYXRoQW5kQ29kZXMgPSBhd2FpdCBTb25hbXUuc3luY2VyLnJlbmRlclRlbXBsYXRlKFxuICAgICAgICAgICAgdGVtcGxhdGVLZXkgYXMgVGVtcGxhdGVLZXksXG4gICAgICAgICAgICB0ZW1wbGF0ZU9wdGlvbnMsXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIHJldHVybiB7IHBhdGhBbmRDb2RlcyB9O1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3QoXCIvYXBpL2ZpeHR1cmVcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgeyBzb3VyY2VEQiwgdGFyZ2V0REIsIHNlYXJjaCwgZHVwbGljYXRlQ2hlY2sgfSA9IHJlcXVlc3QuYm9keSBhcyB7XG4gICAgICAgICAgc291cmNlREI6IGtleW9mIFNvbmFtdURCQ29uZmlnO1xuICAgICAgICAgIHRhcmdldERCOiBrZXlvZiBTb25hbXVEQkNvbmZpZztcbiAgICAgICAgICBzZWFyY2g6IEZpeHR1cmVTZWFyY2hPcHRpb25zO1xuICAgICAgICAgIGR1cGxpY2F0ZUNoZWNrPzogRHVwbGljYXRlQ2hlY2tPcHRpb25zO1xuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiBGaXh0dXJlTWFuYWdlci5nZXRGaXh0dXJlcyhzb3VyY2VEQiwgdGFyZ2V0REIsIHNlYXJjaCwgZHVwbGljYXRlQ2hlY2spO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0KFwiL2FwaS9maXh0dXJlL2ltcG9ydFwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICBjb25zdCB7IGRiLCBmaXh0dXJlcyB9ID0gcmVxdWVzdC5ib2R5IGFzIHtcbiAgICAgICAgICBkYjoga2V5b2YgU29uYW11REJDb25maWc7XG4gICAgICAgICAgZml4dHVyZXM6IEZpeHR1cmVSZWNvcmRbXTtcbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4gRml4dHVyZU1hbmFnZXIuaW5zZXJ0Rml4dHVyZXMoZGIsIGZpeHR1cmVzKTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdChcIi9hcGkvZml4dHVyZS9hZGRGaXh0dXJlTG9hZGVyXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgY29kZSB9ID0gcmVxdWVzdC5ib2R5IGFzIHsgY29kZTogc3RyaW5nIH07XG5cbiAgICAgICAgcmV0dXJuIEZpeHR1cmVNYW5hZ2VyLmFkZEZpeHR1cmVMb2FkZXIoY29kZSk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLmdldChcIi9hcGkvaTE4bi9kaWN0aW9uYXJ5XCIsIGFzeW5jICgpID0+IHtcbiAgICAgICAgcmV0dXJuIHNvbmFtdURpY3Rpb25hcnkuZ2V0RGljdGlvbmFyeSgpO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5nZXQoXCIvYXBpL2kxOG4vZXhwb3J0XCIsIGFzeW5jIChfcmVxdWVzdCwgcmVwbHkpID0+IHtcbiAgICAgICAgY29uc3QgeyBmaWxlbmFtZSwgYnVmZmVyIH0gPSBhd2FpdCBzb25hbXVEaWN0aW9uYXJ5LmV4cG9ydFRvRXhjZWwoKTtcbiAgICAgICAgcmVwbHlcbiAgICAgICAgICAuaGVhZGVyKFxuICAgICAgICAgICAgXCJDb250ZW50LVR5cGVcIixcbiAgICAgICAgICAgIFwiYXBwbGljYXRpb24vdm5kLm9wZW54bWxmb3JtYXRzLW9mZmljZWRvY3VtZW50LnNwcmVhZHNoZWV0bWwuc2hlZXRcIixcbiAgICAgICAgICApXG4gICAgICAgICAgLmhlYWRlcihcIkNvbnRlbnQtRGlzcG9zaXRpb25cIiwgYGF0dGFjaG1lbnQ7IGZpbGVuYW1lPVwiJHtmaWxlbmFtZX1cImApXG4gICAgICAgICAgLnNlbmQoYnVmZmVyKTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdChcIi9hcGkvaTE4bi9pbXBvcnRcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IHJlcXVlc3QuZmlsZSgpO1xuICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihTRChcInNvbmFtdS5lcnJvci5maWxlTm90VXBsb2FkZWRcIikpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGJ1ZmZlciA9IGF3YWl0IGRhdGEudG9CdWZmZXIoKTtcbiAgICAgICAgcmV0dXJuIHNvbmFtdURpY3Rpb25hcnkuaW1wb3J0RnJvbUV4Y2VsKGJ1ZmZlcik7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgb2xkS2V5OiBzdHJpbmc7XG4gICAgICAgICAgbmV3S2V5OiBzdHJpbmc7XG4gICAgICAgICAgc291cmNlOiBcImVudGl0eVwiIHwgXCJwcm9qZWN0XCIgfCBcInNvbmFtdVwiO1xuICAgICAgICAgIHZhbHVlczogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9pMThuL3VwZGF0ZVwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICBhd2FpdCBzb25hbXVEaWN0aW9uYXJ5LnVwZGF0ZUVudHJ5KHJlcXVlc3QuYm9keSk7XG4gICAgICAgIHJldHVybiB7IHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBrZXk6IHN0cmluZztcbiAgICAgICAgICB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvaTE4bi9jcmVhdGVcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgYXdhaXQgc29uYW11RGljdGlvbmFyeS5jcmVhdGVFbnRyeShyZXF1ZXN0LmJvZHkpO1xuICAgICAgICByZXR1cm4geyBzdWNjZXNzOiB0cnVlIH07XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAga2V5OiBzdHJpbmc7XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvaTE4bi9kZWxldGVcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgYXdhaXQgc29uYW11RGljdGlvbmFyeS5kZWxldGVFbnRyeShyZXF1ZXN0LmJvZHkua2V5KTtcbiAgICAgICAgcmV0dXJuIHsgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHsgQm9keTogeyBrZXlzOiBzdHJpbmdbXSB9IH0+KFwiL2FwaS9pMThuL2NoZWNrVXNhZ2VcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgcmV0dXJuIHNvbmFtdURpY3Rpb25hcnkuY2hlY2tVc2FnZShyZXF1ZXN0LmJvZHkua2V5cyk7XG4gICAgICB9KTtcblxuICAgICAgLy8gVGFza3MgQVBJXG4gICAgICBzZXJ2ZXIuZ2V0KFwiL2FwaS90YXNrcy9zdGF0dXNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIFNvbmFtdS53b3JrZmxvd3M7XG4gICAgICAgICAgcmV0dXJuIHsgYWN0aXZlOiB0cnVlIH07XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIHJldHVybiB7IGFjdGl2ZTogZmFsc2UgfTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5nZXQoXCIvYXBpL3Rhc2tzL3dvcmtmbG93RGVmaW5pdGlvbnNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBkZWZpbml0aW9ucyA9IFNvbmFtdS53b3JrZmxvd3Mud29ya2Zsb3dEZWZpbml0aW9ucztcbiAgICAgICAgcmV0dXJuIHsgZGVmaW5pdGlvbnMgfTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIuZ2V0PHtcbiAgICAgICAgUXVlcnlzdHJpbmc6IHtcbiAgICAgICAgICBsaW1pdD86IHN0cmluZztcbiAgICAgICAgICBhZnRlcj86IHN0cmluZztcbiAgICAgICAgICBiZWZvcmU/OiBzdHJpbmc7XG4gICAgICAgICAgb3JkZXI/OiBcImFzY1wiIHwgXCJkZXNjXCI7XG4gICAgICAgICAgc3RhdHVzPzogc3RyaW5nO1xuICAgICAgICAgIHdvcmtmbG93TmFtZT86IHN0cmluZztcbiAgICAgICAgICBjcmVhdGVkQWZ0ZXI/OiBzdHJpbmc7XG4gICAgICAgICAgY3JlYXRlZEJlZm9yZT86IHN0cmluZztcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS90YXNrcy93b3JrZmxvd1J1bnNcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgYmFja2VuZCA9IFNvbmFtdS53b3JrZmxvd3MuYmFja2VuZDtcbiAgICAgICAgY29uc3QgeyBsaW1pdCwgYWZ0ZXIsIGJlZm9yZSwgb3JkZXIsIHN0YXR1cywgd29ya2Zsb3dOYW1lLCBjcmVhdGVkQWZ0ZXIsIGNyZWF0ZWRCZWZvcmUgfSA9XG4gICAgICAgICAgcmVxdWVzdC5xdWVyeTtcbiAgICAgICAgcmV0dXJuIGJhY2tlbmQubGlzdFdvcmtmbG93UnVucyh7XG4gICAgICAgICAgbGltaXQ6IGxpbWl0ID8gTnVtYmVyLnBhcnNlSW50KGxpbWl0LCAxMCkgOiB1bmRlZmluZWQsXG4gICAgICAgICAgYWZ0ZXIsXG4gICAgICAgICAgYmVmb3JlLFxuICAgICAgICAgIG9yZGVyLFxuICAgICAgICAgIHN0YXR1czogc3RhdHVzID8gc3RhdHVzLnNwbGl0KFwiLFwiKSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICB3b3JrZmxvd05hbWU6IHdvcmtmbG93TmFtZSB8fCB1bmRlZmluZWQsXG4gICAgICAgICAgY3JlYXRlZEFmdGVyOiBjcmVhdGVkQWZ0ZXIgPyBuZXcgRGF0ZShjcmVhdGVkQWZ0ZXIpIDogdW5kZWZpbmVkLFxuICAgICAgICAgIGNyZWF0ZWRCZWZvcmU6IGNyZWF0ZWRCZWZvcmUgPyBuZXcgRGF0ZShjcmVhdGVkQmVmb3JlKSA6IHVuZGVmaW5lZCxcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLmdldDx7XG4gICAgICAgIFBhcmFtczogeyBpZDogc3RyaW5nIH07XG4gICAgICB9PihcIi9hcGkvdGFza3Mvd29ya2Zsb3dSdW5zLzppZFwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICBjb25zdCBiYWNrZW5kID0gU29uYW11LndvcmtmbG93cy5iYWNrZW5kO1xuICAgICAgICBjb25zdCB3b3JrZmxvd1J1biA9IGF3YWl0IGJhY2tlbmQuZ2V0V29ya2Zsb3dSdW4oe1xuICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJlcXVlc3QucGFyYW1zLmlkLFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKCF3b3JrZmxvd1J1bikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgV29ya2Zsb3cgcnVuIG5vdCBmb3VuZDogJHtyZXF1ZXN0LnBhcmFtcy5pZH1gKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gd29ya2Zsb3dSdW47XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBQYXJhbXM6IHsgaWQ6IHN0cmluZyB9O1xuICAgICAgfT4oXCIvYXBpL3Rhc2tzL3dvcmtmbG93UnVucy86aWQvY2FuY2VsXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGNvbnN0IGJhY2tlbmQgPSBTb25hbXUud29ya2Zsb3dzLmJhY2tlbmQ7XG4gICAgICAgIHJldHVybiBiYWNrZW5kLmNhbmNlbFdvcmtmbG93UnVuKHtcbiAgICAgICAgICB3b3JrZmxvd1J1bklkOiByZXF1ZXN0LnBhcmFtcy5pZCxcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBQYXJhbXM6IHsgaWQ6IHN0cmluZyB9O1xuICAgICAgfT4oXCIvYXBpL3Rhc2tzL3dvcmtmbG93UnVucy86aWQvcGF1c2VcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgYmFja2VuZCA9IFNvbmFtdS53b3JrZmxvd3MuYmFja2VuZDtcbiAgICAgICAgcmV0dXJuIGJhY2tlbmQucGF1c2VXb3JrZmxvd1J1bih7XG4gICAgICAgICAgd29ya2Zsb3dSdW5JZDogcmVxdWVzdC5wYXJhbXMuaWQsXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgUGFyYW1zOiB7IGlkOiBzdHJpbmcgfTtcbiAgICAgIH0+KFwiL2FwaS90YXNrcy93b3JrZmxvd1J1bnMvOmlkL3Jlc3VtZVwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICBjb25zdCBiYWNrZW5kID0gU29uYW11LndvcmtmbG93cy5iYWNrZW5kO1xuICAgICAgICByZXR1cm4gYmFja2VuZC5yZXN1bWVXb3JrZmxvd1J1bih7XG4gICAgICAgICAgd29ya2Zsb3dSdW5JZDogcmVxdWVzdC5wYXJhbXMuaWQsXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5nZXQ8e1xuICAgICAgICBQYXJhbXM6IHsgaWQ6IHN0cmluZyB9O1xuICAgICAgICBRdWVyeXN0cmluZzoge1xuICAgICAgICAgIGxpbWl0Pzogc3RyaW5nO1xuICAgICAgICAgIGFmdGVyPzogc3RyaW5nO1xuICAgICAgICAgIGJlZm9yZT86IHN0cmluZztcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS90YXNrcy93b3JrZmxvd1J1bnMvOmlkL3N0ZXBzXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGNvbnN0IGJhY2tlbmQgPSBTb25hbXUud29ya2Zsb3dzLmJhY2tlbmQ7XG4gICAgICAgIGNvbnN0IHsgbGltaXQsIGFmdGVyLCBiZWZvcmUgfSA9IHJlcXVlc3QucXVlcnk7XG4gICAgICAgIHJldHVybiBiYWNrZW5kLmxpc3RTdGVwQXR0ZW1wdHMoe1xuICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJlcXVlc3QucGFyYW1zLmlkLFxuICAgICAgICAgIGxpbWl0OiBsaW1pdCA/IE51bWJlci5wYXJzZUludChsaW1pdCwgMTApIDogdW5kZWZpbmVkLFxuICAgICAgICAgIGFmdGVyLFxuICAgICAgICAgIGJlZm9yZSxcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgLyoqXG4gICAgICAgKiBIZWFsdGggQ2hlY2sgQVBJXG4gICAgICAgKiBNQ1Ag64+E6rWs6rCAIFNvbmFtdSDshJzrsoTrpbwg7J6Q64+ZIOqwkOyngO2VmOq4sCDsnITtlZwg7JeU65Oc7Y+s7J247Yq4XG4gICAgICAgKi9cbiAgICAgIHNlcnZlci5nZXQoXCIvYXBpL3NvbmFtdS9oZWFsdGhcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgYWRkcmVzcyA9IHJlcXVlc3Quc2VydmVyLnNlcnZlci5hZGRyZXNzKCk7XG4gICAgICAgIGNvbnN0IHBvcnQgPSBhZGRyZXNzICYmIHR5cGVvZiBhZGRyZXNzID09PSBcIm9iamVjdFwiID8gYWRkcmVzcy5wb3J0IDogMDtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIG9rOiB0cnVlLFxuICAgICAgICAgIHByb2plY3Q6IHByb2Nlc3MuY3dkKCkuc3BsaXQoXCIvXCIpLnBvcCgpIHx8IFwidW5rbm93blwiLFxuICAgICAgICAgIHBvcnQsXG4gICAgICAgICAgdGltZXN0YW1wOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICAgIH07XG4gICAgICB9KTtcblxuICAgICAgLyoqXG4gICAgICAgKiBGaXh0dXJlIOyDneyEsSBBUElcbiAgICAgICAqL1xuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5OiBzdHJpbmc7XG4gICAgICAgICAgY291bnQ/OiBudW1iZXI7XG4gICAgICAgICAgb3ZlcnJpZGVzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgICAgICAgdGFyZ2V0RGI/OiBcImZpeHR1cmVcIiB8IFwidGVzdFwiO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL3NvbmFtdS9maXh0dXJlL2dlbmVyYXRlXCIsIGFzeW5jIChyZXF1ZXN0LCByZXBseSkgPT4ge1xuICAgICAgICBjb25zdCB7IGVudGl0eSwgY291bnQgPSAxLCBvdmVycmlkZXMsIHRhcmdldERiID0gXCJmaXh0dXJlXCIgfSA9IHJlcXVlc3QuYm9keTtcblxuICAgICAgICAvLyDtg4Dqsp8gREIg7ISk7KCVIOqwgOyguOyYpOq4sFxuICAgICAgICBjb25zdCBkYkNvbmZpZyA9IHRhcmdldERiID09PSBcImZpeHR1cmVcIiA/IFNvbmFtdS5kYkNvbmZpZy5maXh0dXJlIDogU29uYW11LmRiQ29uZmlnLnRlc3Q7XG5cbiAgICAgICAgLy8gS25leCDsnbjsiqTthLTsiqQg7IOd7ISxXG4gICAgICAgIGNvbnN0IGRiID0gY3JlYXRlS25leEluc3RhbmNlKGRiQ29uZmlnKTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIC8vIEZpeHR1cmVHZW5lcmF0b3Ig7IOd7ISxXG4gICAgICAgICAgY29uc3QgZ2VuZXJhdG9yID0gbmV3IEZpeHR1cmVHZW5lcmF0b3IoZGIsIGRiLCB0YXJnZXREYiwgRW50aXR5TWFuYWdlcik7XG5cbiAgICAgICAgICAvLyDri6jsnbwgRW50aXR5IOuwsOy5mCDsg53shLFcbiAgICAgICAgICBjb25zdCBmaXh0dXJlcyA9IGF3YWl0IGdlbmVyYXRvci5nZW5lcmF0ZUJhdGNoKFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZW50aXR5LFxuICAgICAgICAgICAgICBjb3VudCxcbiAgICAgICAgICAgICAgb3ZlcnJpZGVzOiBvdmVycmlkZXMgPz8ge30sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0pO1xuXG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgICAgICAgICBlbnRpdHksXG4gICAgICAgICAgICBjb3VudDogZml4dHVyZXMubGVuZ3RoLFxuICAgICAgICAgICAgZml4dHVyZXMsXG4gICAgICAgICAgICB0YXJnZXREYixcbiAgICAgICAgICB9O1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIHJlcGx5LnN0YXR1cyg0MDApO1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgICAgICAgIGVycm9yOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvciksXG4gICAgICAgICAgfTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICBhd2FpdCBkYi5kZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICAvKipcbiAgICAgICAqIEZpeHR1cmUg642w7J207YSwIO2DkOyDiSBBUElcbiAgICAgICAqL1xuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5OiBzdHJpbmc7XG4gICAgICAgICAgc3RyYXRlZ3k6IFwic2FtcGxlXCIgfCBcInJlY2VudFwiIHwgXCJyYW5kb21cIiB8IFwicXVlcnlcIjtcbiAgICAgICAgICBsaW1pdD86IG51bWJlcjtcbiAgICAgICAgICB3aGVyZT86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL3NvbmFtdS9maXh0dXJlL2V4cGxvcmVcIiwgYXN5bmMgKHJlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgZW50aXR5LCBzdHJhdGVneSwgbGltaXQgPSAxMCwgd2hlcmUgfSA9IHJlcXVlc3QuYm9keTtcblxuICAgICAgICAvLyBGaXh0dXJlIERCIOyEpOyglSDqsIDsoLjsmKTquLBcbiAgICAgICAgY29uc3QgZml4dHVyZURiQ29uZmlnID0gU29uYW11LmRiQ29uZmlnLmZpeHR1cmU7XG5cbiAgICAgICAgLy8gS25leCDsnbjsiqTthLTsiqQg7IOd7ISxXG4gICAgICAgIGNvbnN0IGZpeHR1cmVEYiA9IGNyZWF0ZUtuZXhJbnN0YW5jZShmaXh0dXJlRGJDb25maWcpO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gRGF0YUV4cGxvcmVyIOyDneyEsVxuICAgICAgICAgIGNvbnN0IGV4cGxvcmVyID0gbmV3IERhdGFFeHBsb3JlcihmaXh0dXJlRGIsIEVudGl0eU1hbmFnZXIpO1xuXG4gICAgICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IGV4cGxvcmVyLmV4cGxvcmUoZW50aXR5LCB7XG4gICAgICAgICAgICBzdHJhdGVneSxcbiAgICAgICAgICAgIGxpbWl0LFxuICAgICAgICAgICAgd2hlcmUsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgICAgICAgIGVudGl0eSxcbiAgICAgICAgICAgIHN0cmF0ZWd5LFxuICAgICAgICAgICAgY291bnQ6IGRhdGEubGVuZ3RoLFxuICAgICAgICAgICAgZGF0YSxcbiAgICAgICAgICB9O1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIHJlcGx5LnN0YXR1cyg0MDApO1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgICAgICAgIGVycm9yOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvciksXG4gICAgICAgICAgfTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICBhd2FpdCBmaXh0dXJlRGIuZGVzdHJveSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgLyoqXG4gICAgICAgKiBGaXh0dXJlIOuNsOydtO2EsCDqsIDsoLjsmKTquLAgKGZldGNoKSBBUElcbiAgICAgICAqIHByb2R1Y3Rpb24vZGV2ZWxvcG1lbnQgRELsl5DshJwg7Iuk7KCcIOuNsOydtO2EsOulvCBmaXh0dXJlIERC66GcIGltcG9ydFxuICAgICAgICovXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBlbnRpdHk6IHN0cmluZztcbiAgICAgICAgICBzdHJhdGVneT86IFwic2FtcGxlXCIgfCBcInJlY2VudFwiIHwgXCJyYW5kb21cIiB8IFwicXVlcnlcIjtcbiAgICAgICAgICBsaW1pdD86IG51bWJlcjtcbiAgICAgICAgICBpbmNsdWRlUmVsYXRpb25zPzogYm9vbGVhbjtcbiAgICAgICAgICBtYXhEZXB0aD86IG51bWJlcjtcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9zb25hbXUvZml4dHVyZS9mZXRjaFwiLCBhc3luYyAocmVxdWVzdCwgcmVwbHkpID0+IHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIGVudGl0eSxcbiAgICAgICAgICBzdHJhdGVneSA9IFwicmVjZW50XCIsXG4gICAgICAgICAgbGltaXQgPSAxMCxcbiAgICAgICAgICBpbmNsdWRlUmVsYXRpb25zID0gdHJ1ZSxcbiAgICAgICAgICBtYXhEZXB0aCA9IDIsXG4gICAgICAgIH0gPSByZXF1ZXN0LmJvZHk7XG5cbiAgICAgICAgLy8gU291cmNlIERCIChwcm9kdWN0aW9uL2RldmVsb3BtZW50KSAtIOydveq4sCDsoITsmqlcbiAgICAgICAgY29uc3Qgc291cmNlRGIgPSBEQi5nZXREQihcInJcIik7XG5cbiAgICAgICAgLy8gVGFyZ2V0IERCIChmaXh0dXJlKVxuICAgICAgICBjb25zdCBmaXh0dXJlRGIgPSBjcmVhdGVLbmV4SW5zdGFuY2UoU29uYW11LmRiQ29uZmlnLmZpeHR1cmUpO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gRml4dHVyZUdlbmVyYXRvciDsg53shLFcbiAgICAgICAgICBjb25zdCBnZW5lcmF0b3IgPSBuZXcgRml4dHVyZUdlbmVyYXRvcihzb3VyY2VEYiwgZml4dHVyZURiLCBcImZpeHR1cmVcIiwgRW50aXR5TWFuYWdlcik7XG5cbiAgICAgICAgICAvLyBwcm9kdWN0aW9uIOuNsOydtO2EsOulvCBmaXh0dXJlIERC66GcIGltcG9ydFxuICAgICAgICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBnZW5lcmF0b3IuaW1wb3J0RnJvbVNvdXJjZShlbnRpdHksIHtcbiAgICAgICAgICAgIHN0cmF0ZWd5LFxuICAgICAgICAgICAgbGltaXQsXG4gICAgICAgICAgICBpbmNsdWRlUmVsYXRpb25zLFxuICAgICAgICAgICAgbWF4RGVwdGgsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgICAgICAgIGVudGl0eSxcbiAgICAgICAgICAgIHN0cmF0ZWd5LFxuICAgICAgICAgICAgY291bnQ6IHJlc3VsdHMubGVuZ3RoLFxuICAgICAgICAgICAgaW1wb3J0ZWQ6IHJlc3VsdHMsXG4gICAgICAgICAgfTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICByZXBseS5zdGF0dXMoNDAwKTtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgICAgICBlcnJvcjogZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpLFxuICAgICAgICAgIH07XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgLy8gc291cmNlRGLripQgU29uYW116rCAIOq0gOumrO2VmOuvgOuhnCBkZXN0cm957ZWY7KeAIOyViuydjFxuICAgICAgICAgIGF3YWl0IGZpeHR1cmVEYi5kZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICAvKipcbiAgICAgICAqIEZpeHR1cmUg642w7J207YSwIOyCreygnCAoY2xlYW4pIEFQSVxuICAgICAgICogRksg7Iic7ISc66W8IOqzoOugpO2VmOyXrCDslYjsoITtlZjqsowg7IKt7KCcXG4gICAgICAgKi9cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIGVudGl0aWVzPzogc3RyaW5nW107XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvc29uYW11L2ZpeHR1cmUvY2xlYW5cIiwgYXN5bmMgKHJlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgZW50aXRpZXMgfSA9IHJlcXVlc3QuYm9keTtcblxuICAgICAgICAvLyBGaXh0dXJlIERCIOyXsOqysFxuICAgICAgICBjb25zdCBmaXh0dXJlRGIgPSBjcmVhdGVLbmV4SW5zdGFuY2UoU29uYW11LmRiQ29uZmlnLmZpeHR1cmUpO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8g7IKt7KCc7ZWgIEVudGl0eSDrqqnroZ0g6rKw7KCVXG4gICAgICAgICAgY29uc3QgdGFyZ2V0RW50aXRpZXMgPVxuICAgICAgICAgICAgZW50aXRpZXMgJiYgZW50aXRpZXMubGVuZ3RoID4gMCA/IGVudGl0aWVzIDogRW50aXR5TWFuYWdlci5nZXRBbGxJZHMoKTtcblxuICAgICAgICAgIC8vIEVudGl0eSBJROulvCDthYzsnbTruJTrqoXsnLzroZwg67OA7ZmYIChzbmFrZV9jYXNlIOuzteyImO2YlSlcbiAgICAgICAgICBjb25zdCB0YWJsZU5hbWVzID0gdGFyZ2V0RW50aXRpZXMubWFwKChlbnRpdHlJZCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgICAgcmV0dXJuIGVudGl0eS50YWJsZTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIC8vIFBvc3RncmVTUUw6IFRSVU5DQVRFIENBU0NBREXroZwgRksg7Iic7IScIOustOq0gO2VmOqyjCDslYjsoITtlZjqsowg7IKt7KCcXG4gICAgICAgICAgLy8gQ0FTQ0FERSDsmLXshZjsnLzroZwg7J2Y7KG07ISxIOyeiOuKlCDrjbDsnbTthLDrj4Qg7ZWo6ruYIOyCreygnFxuICAgICAgICAgIGF3YWl0IGZpeHR1cmVEYi5yYXcoXG4gICAgICAgICAgICBgVFJVTkNBVEUgVEFCTEUgJHt0YWJsZU5hbWVzLm1hcCgodCkgPT4gYFwiJHt0fVwiYCkuam9pbihcIiwgXCIpfSBSRVNUQVJUIElERU5USVRZIENBU0NBREVgLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgICAgICAgIGNsZWFuZWQ6IHRhYmxlTmFtZXMsXG4gICAgICAgICAgICBjb3VudDogdGFibGVOYW1lcy5sZW5ndGgsXG4gICAgICAgICAgfTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICByZXBseS5zdGF0dXMoNDAwKTtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgICAgICBlcnJvcjogZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpLFxuICAgICAgICAgIH07XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgYXdhaXQgZml4dHVyZURiLmRlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIC8vIENERCBBUElcbiAgICAgIHNlcnZlci5nZXQoXCIvYXBpL2NkZC90cmVlXCIsIGFzeW5jICgpID0+IHtcbiAgICAgICAgcmV0dXJuIGdldENkZFRyZWUoKTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7IEJvZHk6IHsgZmlsZVBhdGg6IHN0cmluZyB9IH0+KFwiL2FwaS9jZGQvcmVhZENvbnRlbnRcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgeyBmaWxlUGF0aCB9ID0gcmVxdWVzdC5ib2R5O1xuICAgICAgICByZXR1cm4gcmVhZENvbnRlbnQoZmlsZVBhdGgpO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHsgQm9keTogeyBmaWxlUGF0aDogc3RyaW5nIH0gfT4oXCIvYXBpL2NkZC9lZGl0Q29udGVudFwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICBjb25zdCB7IGZpbGVQYXRoIH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgIHJldHVybiBlZGl0Q29udGVudChmaWxlUGF0aCk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8eyBCb2R5OiB7IGZpbGVQYXRoOiBzdHJpbmcgfSB9PihcIi9hcGkvY2RkL29wZW5Tb3VyY2VcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgeyBmaWxlUGF0aCB9ID0gcmVxdWVzdC5ib2R5O1xuICAgICAgICBvcGVuU291cmNlRmlsZShmaWxlUGF0aCk7XG4gICAgICAgIHJldHVybiB7IHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBDREQgUnVsZXMgQVBJXG4gICAgICBzZXJ2ZXIuZ2V0KFwiL2FwaS9jZGQvcnVsZXNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgICByZXR1cm4gbGlzdFJ1bGVzKCk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8eyBCb2R5OiB7IHJ1bGVLZXk6IHN0cmluZyB9IH0+KFwiL2FwaS9jZGQvcmVhZFJ1bGVcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgeyBydWxlS2V5IH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgIHJldHVybiByZWFkUnVsZShydWxlS2V5KTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7IEJvZHk6IENkZEFkZFJ1bGVSZXF1ZXN0IH0+KFwiL2FwaS9jZGQvYWRkUnVsZVwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICByZXR1cm4gYWRkUnVsZShyZXF1ZXN0LmJvZHkpO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIENERCBBQyBBUElcbiAgICAgIHNlcnZlci5nZXQoXCIvYXBpL2NkZC9hY1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIHJldHVybiBnZXRBY0xpc3QoKTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyB1aS13ZWIg67mM65OcIO2MjOydvCDshJzruZlcbiAgICAgIGNvbnN0IHVpRGlzdFBhdGggPSBwYXRoLnJlc29sdmUoaW1wb3J0Lm1ldGEuZGlybmFtZSwgXCIuLi91aS13ZWJcIik7XG5cbiAgICAgIC8vIOygleyggSDtjIzsnbwg7ISc67mZOiDro6jtirgg7Y+0642UIOyghOyytCAoYXNzZXRzLCBzZXR0aW5nLnN2ZyDrk7EpXG4gICAgICBzZXJ2ZXIucmVnaXN0ZXIoYXdhaXQgaW1wb3J0KFwiQGZhc3RpZnkvc3RhdGljXCIpLCB7XG4gICAgICAgIHJvb3Q6IHVpRGlzdFBhdGgsXG4gICAgICAgIHByZWZpeDogXCIvXCIsXG4gICAgICAgIGRlY29yYXRlUmVwbHk6IGZhbHNlLFxuICAgICAgICB3aWxkY2FyZDogZmFsc2UsXG4gICAgICB9KTtcblxuICAgICAgLy8gU1BBIGZhbGxiYWNrIC0g7KCV7KCBIO2MjOydvOydtCDsl4bripQg66qo65OgIOqyveuhnOuKlCBpbmRleC5odG1s66GcXG4gICAgICBzZXJ2ZXIuZ2V0KFwiKlwiLCBhc3luYyAoX3JlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICAgIHJlcGx5LmhlYWRlcnMoeyBcIkNvbnRlbnQtdHlwZVwiOiBcInRleHQvaHRtbFwiIH0pLnNlbmQoXG4gICAgICAgICAgZnNcbiAgICAgICAgICAgIC5yZWFkRmlsZVN5bmMocGF0aC5yZXNvbHZlKHVpRGlzdFBhdGgsIFwiaW5kZXguaHRtbFwiKSlcbiAgICAgICAgICAgIC50b1N0cmluZygpXG4gICAgICAgICAgICAucmVwbGFjZShcInt7cHJvamVjdE5hbWV9fVwiLCBTb25hbXUuY29uZmlnLnByb2plY3ROYW1lID8/IFwiVW5rbm93blNvbmFtdVByb2plY3RcIiksXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICB9LFxuICAgIHsgcHJlZml4OiBcIi9zb25hbXUtdWlcIiB9LFxuICApO1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBdURBLGVBQXNCLGtCQUFrQixTQUEwQjtBQUNoRSxTQUFRLFNBQ04sT0FBTyxXQUFXO0VBRWhCLE1BQU0sV0FBVyxJQUFJLFVBQVU7RUFHL0IsZUFBZSxvQkFBdUIsSUFBa0M7R0FDdEUsTUFBTSxjQUFjLElBQUksU0FBZSxZQUFZO0lBQ2pELE1BQU0sZ0JBQWdCO0FBQ3BCLGtCQUFhLFFBQVE7QUFDckIsY0FBUzs7SUFHWCxNQUFNLFVBQVUsaUJBQWlCO0FBQy9CLFlBQU8sT0FBTyxhQUFhLElBQUksa0JBQWtCLFFBQVE7QUFDekQsY0FBUztPQUNSLEtBQUs7QUFFUixXQUFPLE9BQU8sYUFBYSxLQUFLLGtCQUFrQixRQUFRO0tBQzFEO0dBRUYsTUFBTSxTQUFTLE1BQU0sSUFBSTtBQUN6QixTQUFNO0FBQ04sVUFBTzs7QUFHVCxRQUFNLFNBQVMsT0FBTztBQUV0QixTQUFPLElBQUksc0JBQXNCLFlBQVk7QUFDM0MsVUFBTyxPQUFPO0lBQ2Q7QUFFRixTQUFPLElBTUoseUJBQXlCLE9BQU8sWUFBWTtHQUM3QyxNQUFNLEVBQUUsVUFBVSxRQUFRLFlBQVksUUFBUTtHQUU5QyxNQUFNLG9CQUFvQjtBQUN4QixRQUFJLFlBQVksUUFBUTtLQUN0QixNQUFNLFNBQVMsY0FBYyxJQUFJLFNBQVM7S0FDMUMsTUFBTSxFQUFFLFVBQVU7S0FFbEIsTUFBTSxFQUFFLGdCQUFnQjtLQUN4QixNQUFNLGtCQUFrQjtBQUN0QixjQUFRLFFBQVI7T0FDRSxLQUFLLFFBQ0gsUUFBTyxHQUFHLE1BQU0sR0FBRztPQUNyQixLQUFLLGNBQ0gsUUFBTyxHQUFHLE1BQU0sR0FBRztPQUNyQixLQUFLLFlBQ0gsUUFBTyxHQUFHLE1BQU0sR0FBRzs7U0FFckI7QUFDSixZQUFPLEdBQUcsWUFBWSxtQkFBbUIsT0FBTyxNQUFNLFNBQVMsR0FBRztXQUM3RDtBQUNMLFNBQUksQ0FBQyxTQUFTO0FBQ1osWUFBTSxJQUFJLG9CQUFvQixHQUFHLHVDQUF1QyxDQUFDOztBQUUzRSxZQUFPOztPQUVQO0FBQ0osWUFBUyxRQUFRLGFBQWE7SUFDOUI7QUFFRixTQUFPLElBS0osNEJBQTRCLE9BQU8sWUFBWTtHQUNoRCxNQUFNLEVBQUUsUUFBUSxhQUFhLFFBQVE7R0FHckMsTUFBTSxXQUFXLElBQUksSUFBb0I7SUFDdkMsQ0FBQyxVQUFVLEtBQUs7SUFDaEIsQ0FBQyxRQUFRLEtBQUs7SUFDZCxDQUFDLFNBQVMsTUFBTTtJQUNoQixDQUFDLFVBQVUsU0FBUztJQUNwQixDQUFDLE9BQU8sTUFBTTtJQUNkLENBQUMsTUFBTSxLQUFLO0lBQ1osQ0FBQyxRQUFRLGNBQWM7SUFDdkIsQ0FBQyxTQUFTLGNBQWM7SUFDeEIsQ0FBQyxVQUFVLGVBQWU7SUFDMUIsQ0FBQyxRQUFRLEtBQUs7SUFDZCxDQUFDLE1BQU0sS0FBSztJQUNaLENBQUMsV0FBVyxLQUFLO0lBQ2pCLENBQUMsV0FBVyxLQUFLO0lBQ2pCLENBQUMsV0FBVyxLQUFLO0lBQ2pCLENBQUMsTUFBTSxLQUFLO0lBQ1osQ0FBQyxRQUFRLEtBQUs7SUFDZCxDQUFDLFFBQVEsS0FBSztJQUNkLENBQUMsTUFBTSxPQUFPO0lBQ2QsQ0FBQyxNQUFNLE9BQU87SUFDZCxDQUFDLE9BQU8sTUFBTTtJQUNkLENBQUMsT0FBTyxRQUFRO0lBQ2hCLENBQUMsU0FBUyxLQUFLO0lBQ2YsQ0FBQyxRQUFRLEtBQUs7SUFDZCxDQUFDLEtBQUssTUFBTTtJQUNaLENBQUMsS0FBSyxNQUFNO0lBQ1osQ0FBQyxXQUFXLEtBQUs7SUFDakIsQ0FBQyxTQUFTLEtBQUs7SUFDZixDQUFDLFNBQVMsSUFBSTtJQUNkLENBQUMsU0FBUyxNQUFNO0lBQ2hCLENBQUMsU0FBUyxLQUFLO0lBQ2YsQ0FBQyxRQUFRLE1BQU07SUFDZixDQUFDLE9BQU8sS0FBSztJQUNiLENBQUMsU0FBUyxLQUFLO0lBQ2YsQ0FBQyxVQUFVLE1BQU07SUFDakIsQ0FBQyxRQUFRLEtBQUs7SUFDZCxDQUFDLE9BQU8sT0FBTztJQUNmLENBQUMsTUFBTSxLQUFLO0lBQ1osQ0FBQyxRQUFRLEtBQUs7SUFDZCxDQUFDLFdBQVcsS0FBSztJQUNqQixDQUFDLFdBQVcsT0FBTztJQUNuQixDQUFDLFlBQVksT0FBTztJQUNwQixDQUFDLFFBQVEsTUFBTTtJQUNmLENBQUMsT0FBTyxJQUFJO0lBQ1osQ0FBQyxPQUFPLEtBQUs7SUFDYixDQUFDLFlBQVksS0FBSztJQUNsQixDQUFDLFVBQVUsS0FBSztJQUNqQixDQUFDO0FBRUYsUUFBSyxNQUFNQSxjQUFZLGNBQWMsV0FBVyxFQUFFO0lBQ2hELE1BQU0sU0FBUyxjQUFjLElBQUlBLFdBQVM7QUFDMUMsU0FBSyxPQUFPLFNBQVMsUUFBUSxJQUFJO0FBQy9CLGNBQVMsSUFBSSxXQUFXLFdBQVcsT0FBTyxHQUFHLEVBQUUsT0FBTyxNQUFNO0FBQzVELGNBQVMsSUFDUCxXQUFXLFdBQVcsV0FBVyxVQUFVLE9BQU8sR0FBRyxDQUFDLEVBQ3RELEdBQUcsT0FBTyxNQUFNLEtBQ2pCOztBQUdILFdBQU8sTUFBTSxTQUFTLFNBQVM7QUFDN0IsU0FBSSxTQUFTLElBQUksS0FBSyxLQUFLLEVBQUU7QUFDM0I7O0FBRUYsU0FBSSxLQUFLLE1BQU07QUFDYixlQUFTLElBQUksS0FBSyxNQUFNLEtBQUssS0FBSyxRQUFRLE9BQU8sU0FBUyxJQUFJLGFBQWEsQ0FBQzs7TUFFOUU7O0dBR0osTUFBTSxtQkFBbUI7SUFFdkIsTUFBTSxRQUFRLE9BQU8sTUFBTSxJQUFJO0lBQy9CLE1BQU0sZUFBZSxDQUFDLEdBQUcsTUFBTSxNQUFNLFFBQVEsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsUUFBUTtBQUNwRSxZQUFPLENBQ0wsR0FBRyxNQUFNLEdBQUcsTUFBTSxTQUFTLE1BQU0sSUFBSSxRQUFRO0FBQzNDLGFBQU87T0FDTDtPQUNBLEdBQUcsTUFBTSxNQUFNLEtBQUssTUFBTSxJQUFJLENBQUMsS0FBSyxJQUFJO09BQ3pDO09BQ0QsQ0FDSDtNQUNEO0lBR0YsTUFBTSxrQkFBa0I7SUFDeEIsSUFBSUMsWUFBc0IsQ0FBQyxHQUFHLE1BQU07QUFDcEMsU0FBSyxNQUFNLFFBQVEsY0FBYztLQUMvQixNQUFNLFlBQVksVUFBVSxLQUFLLElBQUk7QUFDckMsU0FBSSxVQUFVLFNBQVMsS0FBSyxFQUFFLElBQUksU0FBUyxJQUFJLEtBQUssRUFBRSxFQUFFO0FBQ3RELGtCQUFZLFVBQ1QsUUFBUSxLQUFLLEdBQUcsa0JBQWtCLFNBQVMsSUFBSSxLQUFLLEVBQUUsQ0FBQyxDQUN2RCxNQUFNLElBQUk7OztBQUlqQixXQUFPLFVBQ0osS0FBSyxNQUFNO0FBQ1YsU0FBSSxFQUFFLFdBQVcsZ0JBQWdCLEVBQUU7QUFDakMsYUFBTyxFQUFFLFFBQVEsaUJBQWlCLEdBQUc7WUFDaEM7QUFDTCxhQUFPLEVBQUUsYUFBYTs7TUFFeEIsQ0FDRCxLQUFLLEdBQUcsQ0FDUixRQUFRLGVBQWUsV0FBVyxjQUFjLElBQUksU0FBUyxDQUFDLFFBQVEsR0FBRztPQUMxRTtBQUVKLFVBQU8sRUFBRSxXQUFXO0lBQ3BCO0FBRUYsU0FBTyxJQUFJLHdCQUF3QixZQUFZO0dBQzdDLE1BQU0sWUFBWSxjQUFjLFdBQVc7R0FFM0MsU0FBUyxrQkFBa0IsWUFBbUQ7QUFDNUUsV0FBTyxXQUFXLFNBQVMsY0FBYztLQUN2QyxNQUFNLEVBQUUsVUFBVSxHQUFHLFNBQVM7QUFDOUIsWUFBTyxDQUFDLE1BQU0sR0FBRyxrQkFBa0IsU0FBUyxDQUFDO01BQzdDOztHQUdKLE1BQU0sV0FBVyxNQUFNLFFBQVEsSUFDN0IsVUFBVSxLQUFLLGFBQWE7SUFDMUIsTUFBTSxTQUFTLGNBQWMsSUFBSSxTQUFTO0lBQzFDLE1BQU0sYUFBYSxPQUFPLGVBQWU7QUFFekMsV0FBTztLQUNMLEdBQUc7S0FDSCxtQkFBbUIsa0JBQWtCLFdBQVc7S0FDakQ7S0FDRCxDQUNIO0FBRUQsWUFBUyxNQUFNLEdBQUcsTUFBTTtJQUN0QixNQUFNLE1BQU0sRUFBRSxZQUFZLEVBQUU7SUFDNUIsTUFBTSxNQUFNLEVBQUUsWUFBWSxFQUFFO0FBQzVCLFFBQUksTUFBTSxJQUFLLFFBQU8sQ0FBQztBQUN2QixRQUFJLE1BQU0sSUFBSyxRQUFPO0FBQ3RCLFFBQUksUUFBUSxLQUFLO0FBQ2YsU0FBSSxFQUFFLGFBQWEsVUFBVyxRQUFPLENBQUM7QUFDdEMsU0FBSSxFQUFFLGFBQWEsVUFBVyxRQUFPO0FBQ3JDLFlBQU87O0FBRVQsV0FBTztLQUNQO0FBQ0YsVUFBTyxFQUFFLFVBQVU7SUFDbkI7QUFFRixTQUFPLElBS0osdUJBQXVCLE9BQU8sWUFBNEM7R0FDM0UsTUFBTSxFQUFFLFFBQVEsV0FBVyxRQUFRO0FBRW5DLE9BQUksV0FBVyxLQUFLO0FBQ2xCLFVBQU0sT0FBTyxPQUFPLGVBQWU7O0dBR3JDLE1BQU0saUJBQWlCO0lBRXJCLE1BQU0saUJBQWlCLE9BQU8sUUFBUSxPQUFPLE9BQU8sTUFBTSxDQUN2RCxRQUFRLENBQUMsU0FBUyxhQUFjLFFBQVEsS0FBSyxJQUFJLFNBQW9CLE9BQU8sQ0FDNUUsS0FBSyxDQUFDLFFBQVEsY0FBYyxPQUFPO0lBR3RDLE1BQU0saUJBQWlCLENBQUMsR0FBRyxrQkFBa0I7SUFHN0MsTUFBTSxhQUFhLENBQUMsR0FBRyxnQkFBZ0IsR0FBRyxlQUFlO0FBRXpELFFBQUksV0FBVyxTQUFTO0FBQ3RCLFlBQU87O0lBR1QsTUFBTSxVQUFVLGNBQWMsV0FBVyxDQUFDLFNBQVMsYUFBYTtLQUM5RCxNQUFNLFNBQVMsY0FBYyxJQUFJLFNBQVM7QUFDMUMsWUFBTyxPQUFPLEtBQUssT0FBTyxXQUFXO01BQ3JDO0FBRUYsUUFBSSxXQUFXLFNBQVM7QUFDdEIsWUFBTztXQUNGO0FBQ0wsWUFBTyxDQUFDLEdBQUcsWUFBWSxHQUFHLFFBQVE7O09BRWxDO0FBRUosVUFBTyxFQUNMLFNBQ0Q7SUFDRDtBQUVGLFNBQU8sS0FTSixzQkFBc0IsT0FBTyxZQUFZO0FBQzFDLFVBQU8sTUFBTSxvQkFBb0IsWUFBWTtJQUMzQyxNQUFNLEVBQUUsU0FBUyxRQUFRO0FBQ3pCLFVBQU0sT0FBTyxPQUFPLGFBQWE7S0FBRSxHQUFHO0tBQU0sVUFBVSxLQUFLO0tBQUksQ0FBQztBQUVoRSxXQUFPO0tBQ1A7SUFDRjtBQUVGLFNBQU8sS0FJSixtQkFBbUIsT0FBTyxZQUFZO0FBQ3ZDLFVBQU8sTUFBTSxvQkFBb0IsWUFBWTtJQUMzQyxNQUFNLEVBQUUsYUFBYSxRQUFRO0FBQzdCLFdBQU8sTUFBTSxPQUFPLE9BQU8sVUFBVSxTQUFTO0tBQzlDO0lBQ0Y7QUFFRixTQUFPLEtBU0osZ0NBQWdDLE9BQU8sWUFBWTtBQUNwRCxVQUFPLE1BQU0sb0JBQW9CLFlBQVk7SUFDM0MsTUFBTSxFQUFFLFVBQVUsY0FBYyxRQUFRO0lBQ3hDLE1BQU0sU0FBUyxjQUFjLElBQUksU0FBUztBQUMxQyxXQUFPLFFBQVEsVUFBVTtBQUN6QixXQUFPLFFBQVEsVUFBVTtBQUN6QixXQUFPLFdBQVcsVUFBVTtBQUM1QixVQUFNLE9BQU8sTUFBTTtBQUVuQixXQUFPO0tBQ1A7SUFDRjtBQUVGLFNBQU8sS0FPSiw0QkFBNEIsT0FBTyxZQUFZO0FBQ2hELFVBQU8sTUFBTSxvQkFBb0IsWUFBWTtJQUMzQyxNQUFNLEVBQUUsVUFBVSxXQUFXLFFBQVEsbUJBQW1CLFFBQVE7SUFDaEUsTUFBTSxTQUFTLGNBQWMsSUFBSSxTQUFTO0FBQzFDLFdBQU8sUUFBUSxhQUFhO0FBQzVCLFFBQUksbUJBQW1CLFdBQVc7QUFDaEMsU0FBSSxlQUFlLFNBQVMsR0FBRztBQUM3QixhQUFPLGdCQUFnQixhQUFhO1lBQy9CO0FBQ0wsYUFBTyxPQUFPLGdCQUFnQjs7O0FBR2xDLFVBQU0sT0FBTyxNQUFNO0FBRW5CLFdBQU87S0FBRSxTQUFTO0tBQVEsaUJBQWlCO0tBQWdCO0tBQzNEO0lBQ0Y7QUFFRixTQUFPLEtBS0oseUJBQXlCLE9BQU8sWUFBWTtBQUM3QyxVQUFPLE1BQU0sb0JBQW9CLFlBQVk7SUFDM0MsTUFBTSxFQUFFLFVBQVUsY0FBYyxRQUFRO0lBQ3hDLE1BQU0sU0FBUyxjQUFjLElBQUksU0FBUztBQUMxQyxXQUFPLE9BQU8sUUFBUTtBQUN0QixXQUFPLE9BQU8sZ0JBQWdCO0FBQzlCLFVBQU0sT0FBTyxNQUFNO0FBRW5CLFdBQU87S0FDUDtJQUNGO0FBRUYsU0FBTyxLQU1KLDBCQUEwQixPQUFPLFlBQVk7QUFDOUMsVUFBTyxNQUFNLG9CQUFvQixZQUFZO0lBQzNDLE1BQU0sRUFBRSxVQUFVLElBQUksWUFBWSxRQUFRO0lBQzFDLE1BQU0sU0FBUyxjQUFjLElBQUksU0FBUztBQUMxQyxVQUFNLE9BQU8sV0FBVyxTQUFTLEdBQUc7QUFDcEMsV0FBTztLQUNQO0lBQ0Y7QUFFRixTQUFPLEtBTUosMEJBQTBCLE9BQU8sWUFBWTtBQUM5QyxVQUFPLE1BQU0sb0JBQW9CLFlBQVk7SUFDM0MsTUFBTSxFQUFFLFVBQVUsSUFBSSxZQUFZLFFBQVE7SUFFMUMsTUFBTSxTQUFTLGNBQWMsSUFBSSxTQUFTO0FBQzFDLFdBQU8sV0FBVyxTQUFTLEdBQUc7QUFFOUIsV0FBTztLQUNQO0lBQ0Y7QUFFRixTQUFPLEtBS0osdUJBQXVCLE9BQU8sWUFBWTtBQUMzQyxVQUFPLE1BQU0sb0JBQW9CLFlBQVk7SUFDM0MsTUFBTSxFQUFFLFVBQVUsT0FBTyxRQUFRO0lBRWpDLE1BQU0sU0FBUyxjQUFjLElBQUksU0FBUztBQUMxQyxXQUFPLFFBQVEsR0FBRztBQUNsQixXQUFPO0tBQ1A7SUFDRjtBQUVGLFNBQU8sS0FNSix3QkFBd0IsT0FBTyxZQUFZO0FBQzVDLFVBQU8sTUFBTSxvQkFBb0IsWUFBWTtJQUMzQyxNQUFNLEVBQUUsVUFBVSxJQUFJLE9BQU8sUUFBUTtJQUVyQyxNQUFNLFNBQVMsY0FBYyxJQUFJLFNBQVM7QUFDMUMsV0FBTyxTQUFTLElBQUksR0FBRztBQUV2QixXQUFPO0tBQ1A7SUFDRjtBQUVGLFNBQU8sS0FLSiw2QkFBNkIsT0FBTyxZQUFZO0FBQ2pELFVBQU8sTUFBTSxvQkFBb0IsWUFBWTtJQUMzQyxNQUFNLEVBQUUsVUFBVSxZQUFZLFFBQVE7SUFDdEMsTUFBTSxTQUFTLGNBQWMsSUFBSSxTQUFTO0FBQzFDLFdBQU8sVUFBVTtBQUNqQixVQUFNLE9BQU8sTUFBTTtBQUVuQixXQUFPLEVBQUUsU0FBUyxTQUFTO0tBQzNCO0lBQ0Y7QUFFRixTQUFPLEtBS0osZ0NBQWdDLE9BQU8sWUFBWTtBQUNwRCxVQUFPLE1BQU0sb0JBQW9CLFlBQVk7SUFDM0MsTUFBTSxFQUFFLFVBQVUsZUFBZSxRQUFRO0lBQ3pDLE1BQU0sU0FBUyxjQUFjLElBQUksU0FBUztBQUMxQyxXQUFPLGFBQWE7QUFDcEIsVUFBTSxPQUFPLE1BQU07QUFFbkIsV0FBTyxFQUFFLFNBQVMsWUFBWTtLQUM5QjtJQUNGO0FBRUYsU0FBTyxLQUtKLDRCQUE0QixPQUFPLFlBQVk7QUFDaEQsVUFBTyxNQUFNLG9CQUFvQixZQUFZO0lBQzNDLE1BQU0sRUFBRSxVQUFVLGNBQWMsUUFBUTtJQUN4QyxNQUFNLFNBQVMsY0FBYyxJQUFJLFNBQVM7QUFFMUMsUUFBSSxPQUFPLFdBQVcsWUFBWTtBQUNoQyxXQUFNLElBQUksTUFBTSxzQkFBc0IsWUFBWTs7QUFHcEQsV0FBTyxXQUFXLGFBQWEsVUFBVSxTQUFTLFNBQVMsR0FDdkQ7S0FDRSxRQUFRO0tBQ1IsUUFBUTtLQUNULEdBQ0QsRUFDRSxJQUFJLElBQ0w7QUFDTCxVQUFNLE9BQU8sTUFBTTtBQUVuQixXQUFPO0tBQ1A7SUFDRjtBQUVGLFNBQU8sS0FRSiw0QkFBNEIsT0FBTyxZQUFZO0FBQ2hELFVBQU8sTUFBTSxvQkFBb0IsWUFBWTtJQUMzQyxNQUFNLEVBQUUsVUFBVSxXQUFXLFFBQVE7SUFDckMsTUFBTSxZQUFZLGNBQWMsV0FBVztJQUMzQyxNQUFNLFdBQVcsVUFBVSxNQUFNLGVBQWE7S0FDNUMsTUFBTUMsV0FBUyxjQUFjLElBQUlGLFdBQVM7QUFDMUMsWUFBTyxPQUFPLEtBQUtFLFNBQU8sV0FBVyxDQUFDLFNBQVMsT0FBTyxNQUFNO01BQzVEO0FBQ0YsUUFBSSxVQUFVO0FBQ1osV0FBTSxJQUFJLE1BQU0sc0JBQXNCLE9BQU8sUUFBUTs7SUFHdkQsTUFBTSxTQUFTLGNBQWMsSUFBSSxTQUFTO0FBQzFDLFdBQU8sV0FBVyxPQUFPLFNBQVMsT0FBTyxXQUFXLE9BQU87QUFDM0QsV0FBTyxPQUFPLFdBQVcsT0FBTztBQUVoQyxVQUFNLE9BQU8sTUFBTTtBQUVuQixTQUFLLE1BQU1GLGNBQVksV0FBVztLQUNoQyxNQUFNRSxXQUFTLGNBQWMsSUFBSUYsV0FBUztBQUMxQyxVQUFLLE1BQU0sUUFBUUUsU0FBTyxPQUFPO0FBQy9CLFVBQUksS0FBSyxTQUFTLFVBQVUsS0FBSyxPQUFPLE9BQU8sUUFBUTtBQUNyRCxZQUFLLEtBQUssT0FBTzs7O0FBR3JCLFdBQU1BLFNBQU8sTUFBTTs7S0FFckI7SUFDRjtBQUVGLFNBQU8sS0FLSiw0QkFBNEIsT0FBTyxZQUFZO0FBQ2hELFVBQU8sTUFBTSxvQkFBb0IsWUFBWTtJQUMzQyxNQUFNLEVBQUUsVUFBVSxXQUFXLFFBQVE7SUFFckMsTUFBTSxZQUFZLGNBQWMsV0FBVztJQUMzQyxNQUFNLGVBQWUsVUFDbEIsU0FBUyxlQUFhLGNBQWMsSUFBSUYsV0FBUyxDQUFDLE1BQU0sQ0FDeEQsTUFBTSxTQUFTLEtBQUssU0FBUyxVQUFVLEtBQUssT0FBTyxPQUFPO0FBQzdELFFBQUksY0FBYztBQUNoQixXQUFNLElBQUksTUFBTSxHQUFHLE9BQU8scUJBQXFCOztJQUdqRCxNQUFNLFNBQVMsY0FBYyxJQUFJLFNBQVM7QUFDMUMsV0FBTyxPQUFPLFdBQVc7QUFDekIsVUFBTSxPQUFPLE1BQU07S0FDbkI7SUFDRjtBQUVGLFNBQU8sS0FTSiwwQkFBMEIsT0FBTyxZQUFZO0FBQzlDLFVBQU8sTUFBTSxvQkFBb0IsWUFBWTtJQUMzQyxNQUFNLEVBQUUsVUFBVSxRQUFRLFVBQVUsUUFBUSxXQUFXLFNBQVMsUUFBUTtJQUN4RSxNQUFNLFNBQVMsY0FBYyxJQUFJLFNBQVM7QUFFMUMsUUFBSSxXQUFXLFVBQVU7QUFDdkIsWUFBTyxPQUFPO2VBQ0wsV0FBVyxVQUFVLFVBQVU7S0FDeEMsTUFBTSxPQUFPLE9BQU8sTUFBTSxNQUFNLE1BQU0sRUFBRSxTQUFTLFNBQVM7QUFDMUQsU0FBSSxNQUFNO0FBQ1IsTUFBQyxLQUF5QixPQUFPOztlQUUxQixXQUFXLFVBQVUsUUFBUTtBQUN0QyxZQUFPLFVBQVUsVUFBVTtlQUNsQixXQUFXLFlBQVksV0FBVztBQUMzQyxZQUFPLFlBQVksYUFBYTs7QUFHbEMsVUFBTSxPQUFPLE1BQU07QUFDbkIsV0FBTztLQUNQO0lBQ0Y7QUFFRixTQUFPLEtBT0osNkJBQTZCLE9BQU8sU0FBUyxVQUFVO0FBQ3hELFVBQU8sTUFBTSxvQkFBb0IsWUFBWTtJQUMzQyxNQUFNLEVBQUUsVUFBVSxrQkFBa0IsV0FBVyxXQUFXLFFBQVE7QUFFbEUsUUFBSTtLQUVGLE1BQU0sU0FBUyxjQUFjLElBQUksU0FBUztLQUcxQyxNQUFNLGtCQUNKLFVBQVcsT0FBTyxPQUFPLEtBQUs7S0FHaEMsTUFBTSxTQUFTLE1BQU0sT0FBTyxjQUFjO01BQ3hDLGtCQUFrQixvQkFBb0I7TUFDdEMsV0FBVyxhQUFhO01BQ3hCLFFBQVE7TUFDVCxDQUFDO0FBRUYsWUFBTzthQUNBRyxPQUFnQjtLQUN2QixNQUFNLFVBQVUsaUJBQWlCLFFBQVEsTUFBTSxVQUFVLE9BQU8sTUFBTTtBQUd0RSxTQUFJLFFBQVEsU0FBUyxpQkFBaUIsRUFBRTtBQUN0QyxZQUFNLE9BQU8sSUFBSTtBQUNqQixhQUFPO09BQ0wsU0FBUztPQUNULE9BQU8scUJBQXFCO09BQzdCOztBQUlILFNBQUksUUFBUSxTQUFTLDhCQUE4QixFQUFFO0FBQ25ELFlBQU0sT0FBTyxJQUFJO0FBQ2pCLGFBQU87T0FDTCxTQUFTO09BQ1QsT0FBTztPQUNSOztBQUlILFNBQUksUUFBUSxTQUFTLHNCQUFzQixFQUFFO0FBQzNDLFlBQU0sT0FBTyxJQUFJO0FBQ2pCLGFBQU87T0FDTCxTQUFTO09BQ1QsT0FBTztPQUNSOztBQUlILFdBQU0sT0FBTyxJQUFJO0FBQ2pCLFlBQU87TUFDTCxTQUFTO01BQ1QsT0FBTywyQkFBMkI7TUFDbkM7O0tBRUg7SUFDRjtBQUVGLFNBQU8sSUFJSiwrQkFBK0IsT0FBTyxZQUFZO0dBQ25ELE1BQU0sRUFBRSxhQUFhLFFBQVE7R0FDN0IsTUFBTSxTQUFTLGNBQWMsSUFBSSxTQUFTO0dBQzFDLE1BQU0sVUFBVSxPQUFPLGlCQUFpQjtBQUN4QyxVQUFPLEVBQUUsU0FBUztJQUNsQjtBQUVGLFNBQU8sSUFBSSwwQkFBMEIsWUFBWTtHQUMvQyxNQUFNLFNBQVMsTUFBTSxTQUFTLFdBQVc7QUFFekMsVUFBTyxFQUFFLFFBQVE7SUFDakI7QUFFRixTQUFPLEtBU0wsNkJBQ0EsT0FBTyxZQUFrRTtHQUN2RSxNQUFNLEVBQUUsUUFBUSxTQUFTLE9BQU8sYUFBYSxjQUFjLFFBQVE7QUFFbkUsT0FBSSxXQUFXLFVBQVU7QUFDdkIsV0FBTyxTQUFTLGVBQWU7O0FBSWpDLE9BQUksV0FBVyxTQUFTO0lBQ3RCLE1BQU0sZUFBZSxJQUFJLGNBQWM7SUFDdkMsTUFBTSxtQkFBbUIsUUFBUSxNQUFNLE1BQU0sYUFBYSx5QkFBeUIsRUFBRSxDQUFDO0lBR3RGLE1BQU0sYUFBYTtLQUFDO0tBQWE7S0FBYTtLQUFXO0tBQU07SUFDL0QsTUFBTSxnQkFBZ0IsUUFBUSxPQUFPLFdBQVc7S0FDOUMsTUFBTSxlQUFlLE9BQU8sU0FBUztLQUNyQyxNQUFNLFFBQVEsY0FBYyxhQUFrQyxRQUFRO0FBQ3RFLFlBQU8sV0FBVyxTQUFTLEtBQUssYUFBYSxDQUFDO01BQzlDO0FBRUYsUUFBSSxvQkFBb0IsYUFBYSxjQUFjLElBQUksQ0FBQyxlQUFlO0tBQ3JFLE1BQU0sRUFBRSxVQUFVLE1BQU0sU0FBUyxXQUFXO0tBRzVDLE1BQU0sb0JBQW9CLENBQ3hCLEdBQUcsSUFBSSxJQUNMLE1BQ0csUUFBUSxTQUFTLFFBQVEsU0FBUyxLQUFLLFFBQVEsQ0FBQyxDQUNoRCxTQUFTLFNBQVMsS0FBSyxRQUFRLENBQ25DLENBQ0Y7QUFFRCxTQUFJLGtCQUFrQixTQUFTLEdBQUc7TUFFaEMsTUFBTSxXQUFXLE1BQU0sYUFBYSxtQkFBbUIsa0JBQWtCO0FBRXpFLFVBQUksVUFBVTtPQUVaLE1BQU0sRUFBRSxVQUFVLGFBQWEsTUFBTSxhQUFhLGNBQ2hELFNBQVMsU0FDVCxTQUFTLEdBQ1Y7QUFFRCxXQUFJLFVBQVU7UUFFWixNQUFNLFNBQVMsTUFBTSxTQUFTLFVBQVUsUUFBUSxRQUFRO0FBQ3hELFlBQUksT0FBTyxTQUFTLEdBQUc7QUFDckIsZUFBTSxhQUFhLGFBQ2pCLFNBQVMsU0FDVCxTQUFTLElBQ1QsUUFDQSxVQUNEOztBQUVILGVBQU87a0JBQ0UsVUFBVTtBQUNuQixjQUFNLElBQUksb0JBQW9CLEdBQUcsaUNBQWlDLENBQUM7a0JBQzFELE9BQU87QUFFaEIsY0FBTSxhQUFhLGNBQ2pCLFNBQVMsU0FDVCxTQUFTLElBQ1QsZUFBZSxTQUNmLFVBQ0Q7UUFDRCxNQUFNLFNBQVMsTUFBTSxTQUFTLFVBQVUsUUFBUSxRQUFRO0FBQ3hELFlBQUksT0FBTyxTQUFTLEdBQUc7QUFDckIsZUFBTSxhQUFhLGFBQ2pCLFNBQVMsU0FDVCxTQUFTLElBQ1QsUUFDQSxVQUNEOztBQUVILGVBQU87Y0FDRjtBQUVMLGVBQU87U0FDTCxNQUFNO1NBQ04sU0FBUyxTQUFTO1NBQ2xCLElBQUksU0FBUztTQUNkOzthQUVFO09BRUwsTUFBTSxFQUFFLFNBQVMsT0FBTyxNQUFNLGFBQWEsb0JBQ3pDLG1CQUNBLFNBQ0EsVUFDRDtBQUNELGFBQU0sYUFBYSxZQUFZLG1CQUFtQixTQUFTLEdBQUc7QUFFOUQsY0FBTztRQUNMLE1BQU07UUFDTjtRQUNBO1FBQ0Q7Ozs7O0FBTVQsVUFBTyxTQUFTLFVBQVUsUUFBUSxRQUFRO0lBRTdDO0FBRUQsU0FBTyxLQUtKLGlDQUFpQyxPQUFPLFlBQVk7R0FDckQsTUFBTSxFQUFFLFNBQVMsT0FBTyxRQUFRO0dBQ2hDLE1BQU0sZUFBZSxJQUFJLGNBQWM7QUFFdkMsT0FBSSxDQUFDLGFBQWEsY0FBYyxFQUFFO0FBQ2hDLFdBQU87S0FBRSxVQUFVO0tBQU0sVUFBVTtLQUFPOztBQUc1QyxVQUFPLGFBQWEsY0FBYyxTQUFTLEdBQUc7SUFDOUM7QUFFRixTQUFPLEtBT0osaUNBQWlDLE9BQU8sWUFBWTtHQUNyRCxNQUFNLEVBQUUsU0FBUyxJQUFJLFFBQVEsY0FBYyxRQUFRO0dBQ25ELE1BQU0sZUFBZSxJQUFJLGNBQWM7QUFFdkMsT0FBSSxDQUFDLGFBQWEsY0FBYyxFQUFFO0FBQ2hDLFVBQU0sSUFBSSxvQkFBb0IsR0FBRyx5Q0FBeUMsQ0FBQzs7QUFHN0UsU0FBTSxhQUFhLGNBQWMsU0FBUyxJQUFJLFFBQVEsVUFBVTtBQUNoRSxVQUFPLEVBQUUsU0FBUyxNQUFNO0lBQ3hCO0FBRUYsU0FBTyxLQUlKLDRCQUE0QixPQUFPLFlBQVk7R0FDaEQsTUFBTSxFQUFFLGNBQWMsUUFBUTtBQUM5QixVQUFPLE1BQU0sU0FBUyxTQUFTLFVBQVU7SUFDekM7QUFFRixTQUFPLEtBQUsseUNBQXlDLE9BQU8sY0FBYztBQUN4RSxVQUFPLE1BQU0sU0FBUyx1QkFBdUI7SUFDN0M7QUFFRixTQUFPLEtBS0osOEJBQThCLE9BQU8sWUFBWTtHQUNsRCxNQUFNLEVBQUUsV0FBVyxjQUFjLGtCQUFrQixRQUFRO0FBQzNELFFBQUssYUFBYSxFQUFFLEVBQUUsV0FBVyxHQUFHO0FBQ2xDLFVBQU0sSUFBSSxvQkFBb0IsR0FBRyxpQ0FBaUMsQ0FBQztlQUN6RCxpQkFBaUIsRUFBRSxFQUFFLFdBQVcsR0FBRztBQUM3QyxVQUFNLElBQUksb0JBQW9CLEdBQUcsb0NBQW9DLENBQUM7O0FBSXhFLGFBQVUsTUFBTSxHQUFHLE1BQU8sSUFBSSxJQUFJLENBQUMsSUFBSSxJQUFJLElBQUksSUFBSSxFQUFHO0dBQ3RELE1BQU0sZUFBZSxZQUFZLFFBQVEsUUFBUSxPQUFPLGNBQWMsU0FBUyxHQUFHLENBQUM7R0FFbkYsTUFBTSxlQUFlLFVBQVUsU0FBUyxhQUFhO0FBQ25ELFdBQU8sYUFBYSxLQUFLLGdCQUFnQixDQUFDLFVBQVUsWUFBWSxDQUFDO0tBQ2pFO0dBRUYsTUFBTSxXQUFXLE1BQU0sUUFBUSxJQUM3QixhQUFhLElBQUksT0FBTyxDQUFDLFVBQVUsaUJBQWlCO0lBQ2xELE1BQU0sRUFBRSxTQUFTLFVBQVUsYUFBYSxNQUFNLE9BQU8sT0FBTyxtQkFDMUQsVUFDQSxZQUNEO0FBQ0QsV0FBTztLQUNMO0tBQ0E7S0FDQTtLQUNBO0tBQ0E7S0FDRDtLQUNELENBQ0g7QUFDRCxVQUFPLEVBQUUsVUFBVTtJQUNuQjtBQUVGLFNBQU8sS0FTSiw2QkFBNkIsT0FBTyxZQUFZO0dBQ2pELE1BQU0sRUFBRSxZQUFZLFFBQVE7QUFDNUIsT0FBSSxRQUFRLFdBQVcsR0FBRztBQUN4QixVQUFNLElBQUksb0JBQW9CLEdBQUcsK0JBQStCLENBQUM7O0dBSW5FLE1BQU0sT0FBTyxRQUFRLFNBQVMsRUFBRSxrQkFBa0I7SUFDaEQsTUFBTSxXQUFXLGdCQUFnQixJQUFJLFlBQVk7QUFDakQsV0FBTyxTQUFTLHFCQUFxQixJQUFJLEVBQUU7S0FDM0M7QUFHRixTQUFNLGlCQUFpQixlQUFlLENBQUMsR0FBRyxJQUFJLElBQUksS0FBSyxDQUFDLENBQUM7R0FHekQsTUFBTSxTQUFTLE1BQU0sUUFBUSxJQUMzQixRQUFRLElBQUksT0FBTyxFQUFFLFVBQVUsYUFBYSxRQUFRLGdCQUFnQjtBQUNsRSxRQUFJO0FBQ0YsWUFBTyxNQUFNLE9BQU8sT0FBTyxpQkFDekIsYUFDQTtNQUNFO01BQ0E7TUFDRCxFQUlELEVBQ0UsV0FDRCxDQUNGO2FBQ00sR0FBRztBQUNWLFNBQUksY0FBYyxFQUFFLElBQUksRUFBRSxlQUFlLEtBQUs7QUFDNUMsYUFBTztZQUNGO0FBQ0wsY0FBUSxNQUFNLEVBQUU7QUFDaEIsWUFBTTs7O0tBR1YsQ0FDSDtBQUVELE9BQUksT0FBTyxPQUFPLFlBQVksQ0FBQyxXQUFXLEdBQUc7QUFDM0MsVUFBTSxJQUFJLDRCQUE0QixHQUFHLGlDQUFpQyxDQUFDOztBQUU3RSxVQUFPO0lBQ1A7QUFFRixTQUFPLEtBUUosNEJBQTRCLE9BQU8sWUFBc0Q7R0FDMUYsTUFBTSxFQUFFLFdBQVcsUUFBUTtBQUUzQixPQUFJO0lBQ0YsTUFBTSxFQUFFLGFBQWEsR0FBRyxvQkFBb0I7SUFDNUMsTUFBTSxlQUFlLE1BQU0sT0FBTyxPQUFPLGVBQ3ZDLGFBQ0EsZ0JBQ0Q7QUFFRCxXQUFPLEVBQUUsY0FBYztZQUNoQixHQUFHO0FBQ1YsWUFBUSxNQUFNLEVBQUU7QUFDaEIsVUFBTTs7SUFFUjtBQUVGLFNBQU8sS0FBSyxnQkFBZ0IsT0FBTyxZQUFZO0dBQzdDLE1BQU0sRUFBRSxVQUFVLFVBQVUsUUFBUSxtQkFBbUIsUUFBUTtBQU8vRCxVQUFPLGVBQWUsWUFBWSxVQUFVLFVBQVUsUUFBUSxlQUFlO0lBQzdFO0FBRUYsU0FBTyxLQUFLLHVCQUF1QixPQUFPLFlBQVk7R0FDcEQsTUFBTSxFQUFFLElBQUksYUFBYSxRQUFRO0FBS2pDLFVBQU8sZUFBZSxlQUFlLElBQUksU0FBUztJQUNsRDtBQUVGLFNBQU8sS0FBSyxpQ0FBaUMsT0FBTyxZQUFZO0dBQzlELE1BQU0sRUFBRSxTQUFTLFFBQVE7QUFFekIsVUFBTyxlQUFlLGlCQUFpQixLQUFLO0lBQzVDO0FBRUYsU0FBTyxJQUFJLHdCQUF3QixZQUFZO0FBQzdDLFVBQU8saUJBQWlCLGVBQWU7SUFDdkM7QUFFRixTQUFPLElBQUksb0JBQW9CLE9BQU8sVUFBVSxVQUFVO0dBQ3hELE1BQU0sRUFBRSxVQUFVLFdBQVcsTUFBTSxpQkFBaUIsZUFBZTtBQUNuRSxTQUNHLE9BQ0MsZ0JBQ0Esb0VBQ0QsQ0FDQSxPQUFPLHVCQUF1Qix5QkFBeUIsU0FBUyxHQUFHLENBQ25FLEtBQUssT0FBTztJQUNmO0FBRUYsU0FBTyxLQUFLLG9CQUFvQixPQUFPLFlBQVk7R0FDakQsTUFBTSxPQUFPLE1BQU0sUUFBUSxNQUFNO0FBQ2pDLE9BQUksQ0FBQyxNQUFNO0FBQ1QsVUFBTSxJQUFJLG9CQUFvQixHQUFHLCtCQUErQixDQUFDOztHQUVuRSxNQUFNLFNBQVMsTUFBTSxLQUFLLFVBQVU7QUFDcEMsVUFBTyxpQkFBaUIsZ0JBQWdCLE9BQU87SUFDL0M7QUFFRixTQUFPLEtBT0osb0JBQW9CLE9BQU8sWUFBWTtBQUN4QyxTQUFNLGlCQUFpQixZQUFZLFFBQVEsS0FBSztBQUNoRCxVQUFPLEVBQUUsU0FBUyxNQUFNO0lBQ3hCO0FBRUYsU0FBTyxLQUtKLG9CQUFvQixPQUFPLFlBQVk7QUFDeEMsU0FBTSxpQkFBaUIsWUFBWSxRQUFRLEtBQUs7QUFDaEQsVUFBTyxFQUFFLFNBQVMsTUFBTTtJQUN4QjtBQUVGLFNBQU8sS0FJSixvQkFBb0IsT0FBTyxZQUFZO0FBQ3hDLFNBQU0saUJBQWlCLFlBQVksUUFBUSxLQUFLLElBQUk7QUFDcEQsVUFBTyxFQUFFLFNBQVMsTUFBTTtJQUN4QjtBQUVGLFNBQU8sS0FBbUMsd0JBQXdCLE9BQU8sWUFBWTtBQUNuRixVQUFPLGlCQUFpQixXQUFXLFFBQVEsS0FBSyxLQUFLO0lBQ3JEO0FBR0YsU0FBTyxJQUFJLHFCQUFxQixZQUFZO0FBQzFDLE9BQUk7QUFDRixXQUFPO0FBQ1AsV0FBTyxFQUFFLFFBQVEsTUFBTTtXQUNqQjtBQUNOLFdBQU8sRUFBRSxRQUFRLE9BQU87O0lBRTFCO0FBRUYsU0FBTyxJQUFJLGtDQUFrQyxZQUFZO0dBQ3ZELE1BQU0sY0FBYyxPQUFPLFVBQVU7QUFDckMsVUFBTyxFQUFFLGFBQWE7SUFDdEI7QUFFRixTQUFPLElBV0osMkJBQTJCLE9BQU8sWUFBWTtHQUMvQyxNQUFNLFVBQVUsT0FBTyxVQUFVO0dBQ2pDLE1BQU0sRUFBRSxPQUFPLE9BQU8sUUFBUSxPQUFPLFFBQVEsY0FBYyxjQUFjLGtCQUN2RSxRQUFRO0FBQ1YsVUFBTyxRQUFRLGlCQUFpQjtJQUM5QixPQUFPLFFBQVEsT0FBTyxTQUFTLE9BQU8sR0FBRyxHQUFHO0lBQzVDO0lBQ0E7SUFDQTtJQUNBLFFBQVEsU0FBUyxPQUFPLE1BQU0sSUFBSSxHQUFHO0lBQ3JDLGNBQWMsZ0JBQWdCO0lBQzlCLGNBQWMsZUFBZSxJQUFJLEtBQUssYUFBYSxHQUFHO0lBQ3RELGVBQWUsZ0JBQWdCLElBQUksS0FBSyxjQUFjLEdBQUc7SUFDMUQsQ0FBQztJQUNGO0FBRUYsU0FBTyxJQUVKLCtCQUErQixPQUFPLFlBQVk7R0FDbkQsTUFBTSxVQUFVLE9BQU8sVUFBVTtHQUNqQyxNQUFNLGNBQWMsTUFBTSxRQUFRLGVBQWUsRUFDL0MsZUFBZSxRQUFRLE9BQU8sSUFDL0IsQ0FBQztBQUNGLE9BQUksQ0FBQyxhQUFhO0FBQ2hCLFVBQU0sSUFBSSxNQUFNLDJCQUEyQixRQUFRLE9BQU8sS0FBSzs7QUFFakUsVUFBTztJQUNQO0FBRUYsU0FBTyxLQUVKLHNDQUFzQyxPQUFPLFlBQVk7R0FDMUQsTUFBTSxVQUFVLE9BQU8sVUFBVTtBQUNqQyxVQUFPLFFBQVEsa0JBQWtCLEVBQy9CLGVBQWUsUUFBUSxPQUFPLElBQy9CLENBQUM7SUFDRjtBQUVGLFNBQU8sS0FFSixxQ0FBcUMsT0FBTyxZQUFZO0dBQ3pELE1BQU0sVUFBVSxPQUFPLFVBQVU7QUFDakMsVUFBTyxRQUFRLGlCQUFpQixFQUM5QixlQUFlLFFBQVEsT0FBTyxJQUMvQixDQUFDO0lBQ0Y7QUFFRixTQUFPLEtBRUosc0NBQXNDLE9BQU8sWUFBWTtHQUMxRCxNQUFNLFVBQVUsT0FBTyxVQUFVO0FBQ2pDLFVBQU8sUUFBUSxrQkFBa0IsRUFDL0IsZUFBZSxRQUFRLE9BQU8sSUFDL0IsQ0FBQztJQUNGO0FBRUYsU0FBTyxJQU9KLHFDQUFxQyxPQUFPLFlBQVk7R0FDekQsTUFBTSxVQUFVLE9BQU8sVUFBVTtHQUNqQyxNQUFNLEVBQUUsT0FBTyxPQUFPLFdBQVcsUUFBUTtBQUN6QyxVQUFPLFFBQVEsaUJBQWlCO0lBQzlCLGVBQWUsUUFBUSxPQUFPO0lBQzlCLE9BQU8sUUFBUSxPQUFPLFNBQVMsT0FBTyxHQUFHLEdBQUc7SUFDNUM7SUFDQTtJQUNELENBQUM7SUFDRjs7Ozs7QUFNRixTQUFPLElBQUksc0JBQXNCLE9BQU8sWUFBWTtHQUNsRCxNQUFNLFVBQVUsUUFBUSxPQUFPLE9BQU8sU0FBUztHQUMvQyxNQUFNLE9BQU8sV0FBVyxPQUFPLFlBQVksV0FBVyxRQUFRLE9BQU87QUFFckUsVUFBTztJQUNMLElBQUk7SUFDSixTQUFTLFFBQVEsS0FBSyxDQUFDLE1BQU0sSUFBSSxDQUFDLEtBQUssSUFBSTtJQUMzQztJQUNBLFdBQVcsSUFBSSxNQUFNLENBQUMsYUFBYTtJQUNwQztJQUNEOzs7O0FBS0YsU0FBTyxLQU9KLGdDQUFnQyxPQUFPLFNBQVMsVUFBVTtHQUMzRCxNQUFNLEVBQUUsUUFBUSxRQUFRLEdBQUcsV0FBVyxXQUFXLGNBQWMsUUFBUTtHQUd2RSxNQUFNLFdBQVcsYUFBYSxZQUFZLE9BQU8sU0FBUyxVQUFVLE9BQU8sU0FBUztHQUdwRixNQUFNLEtBQUssbUJBQW1CLFNBQVM7QUFFdkMsT0FBSTtJQUVGLE1BQU0sWUFBWSxJQUFJLGlCQUFpQixJQUFJLElBQUksVUFBVSxjQUFjO0lBR3ZFLE1BQU0sV0FBVyxNQUFNLFVBQVUsY0FBYyxDQUM3QztLQUNFO0tBQ0E7S0FDQSxXQUFXLGFBQWEsRUFBRTtLQUMzQixDQUNGLENBQUM7QUFFRixXQUFPO0tBQ0wsU0FBUztLQUNUO0tBQ0EsT0FBTyxTQUFTO0tBQ2hCO0tBQ0E7S0FDRDtZQUNNLE9BQU87QUFDZCxVQUFNLE9BQU8sSUFBSTtBQUNqQixXQUFPO0tBQ0wsU0FBUztLQUNULE9BQU8saUJBQWlCLFFBQVEsTUFBTSxVQUFVLE9BQU8sTUFBTTtLQUM5RDthQUNPO0FBQ1IsVUFBTSxHQUFHLFNBQVM7O0lBRXBCOzs7O0FBS0YsU0FBTyxLQU9KLCtCQUErQixPQUFPLFNBQVMsVUFBVTtHQUMxRCxNQUFNLEVBQUUsUUFBUSxVQUFVLFFBQVEsSUFBSSxVQUFVLFFBQVE7R0FHeEQsTUFBTSxrQkFBa0IsT0FBTyxTQUFTO0dBR3hDLE1BQU0sWUFBWSxtQkFBbUIsZ0JBQWdCO0FBRXJELE9BQUk7SUFFRixNQUFNLFdBQVcsSUFBSSxhQUFhLFdBQVcsY0FBYztJQUUzRCxNQUFNLE9BQU8sTUFBTSxTQUFTLFFBQVEsUUFBUTtLQUMxQztLQUNBO0tBQ0E7S0FDRCxDQUFDO0FBRUYsV0FBTztLQUNMLFNBQVM7S0FDVDtLQUNBO0tBQ0EsT0FBTyxLQUFLO0tBQ1o7S0FDRDtZQUNNLE9BQU87QUFDZCxVQUFNLE9BQU8sSUFBSTtBQUNqQixXQUFPO0tBQ0wsU0FBUztLQUNULE9BQU8saUJBQWlCLFFBQVEsTUFBTSxVQUFVLE9BQU8sTUFBTTtLQUM5RDthQUNPO0FBQ1IsVUFBTSxVQUFVLFNBQVM7O0lBRTNCOzs7OztBQU1GLFNBQU8sS0FRSiw2QkFBNkIsT0FBTyxTQUFTLFVBQVU7R0FDeEQsTUFBTSxFQUNKLFFBQ0EsV0FBVyxVQUNYLFFBQVEsSUFDUixtQkFBbUIsTUFDbkIsV0FBVyxNQUNULFFBQVE7R0FHWixNQUFNLFdBQVcsR0FBRyxNQUFNLElBQUk7R0FHOUIsTUFBTSxZQUFZLG1CQUFtQixPQUFPLFNBQVMsUUFBUTtBQUU3RCxPQUFJO0lBRUYsTUFBTSxZQUFZLElBQUksaUJBQWlCLFVBQVUsV0FBVyxXQUFXLGNBQWM7SUFHckYsTUFBTSxVQUFVLE1BQU0sVUFBVSxpQkFBaUIsUUFBUTtLQUN2RDtLQUNBO0tBQ0E7S0FDQTtLQUNELENBQUM7QUFFRixXQUFPO0tBQ0wsU0FBUztLQUNUO0tBQ0E7S0FDQSxPQUFPLFFBQVE7S0FDZixVQUFVO0tBQ1g7WUFDTSxPQUFPO0FBQ2QsVUFBTSxPQUFPLElBQUk7QUFDakIsV0FBTztLQUNMLFNBQVM7S0FDVCxPQUFPLGlCQUFpQixRQUFRLE1BQU0sVUFBVSxPQUFPLE1BQU07S0FDOUQ7YUFDTztBQUVSLFVBQU0sVUFBVSxTQUFTOztJQUUzQjs7Ozs7QUFNRixTQUFPLEtBSUosNkJBQTZCLE9BQU8sU0FBUyxVQUFVO0dBQ3hELE1BQU0sRUFBRSxhQUFhLFFBQVE7R0FHN0IsTUFBTSxZQUFZLG1CQUFtQixPQUFPLFNBQVMsUUFBUTtBQUU3RCxPQUFJO0lBRUYsTUFBTSxpQkFDSixZQUFZLFNBQVMsU0FBUyxJQUFJLFdBQVcsY0FBYyxXQUFXO0lBR3hFLE1BQU0sYUFBYSxlQUFlLEtBQUssYUFBYTtLQUNsRCxNQUFNLFNBQVMsY0FBYyxJQUFJLFNBQVM7QUFDMUMsWUFBTyxPQUFPO01BQ2Q7QUFJRixVQUFNLFVBQVUsSUFDZCxrQkFBa0IsV0FBVyxLQUFLLE1BQU0sSUFBSSxFQUFFLEdBQUcsQ0FBQyxLQUFLLEtBQUssQ0FBQywyQkFDOUQ7QUFFRCxXQUFPO0tBQ0wsU0FBUztLQUNULFNBQVM7S0FDVCxPQUFPLFdBQVc7S0FDbkI7WUFDTSxPQUFPO0FBQ2QsVUFBTSxPQUFPLElBQUk7QUFDakIsV0FBTztLQUNMLFNBQVM7S0FDVCxPQUFPLGlCQUFpQixRQUFRLE1BQU0sVUFBVSxPQUFPLE1BQU07S0FDOUQ7YUFDTztBQUNSLFVBQU0sVUFBVSxTQUFTOztJQUUzQjtBQUdGLFNBQU8sSUFBSSxpQkFBaUIsWUFBWTtBQUN0QyxVQUFPLFlBQVk7SUFDbkI7QUFFRixTQUFPLEtBQXFDLHdCQUF3QixPQUFPLFlBQVk7R0FDckYsTUFBTSxFQUFFLGFBQWEsUUFBUTtBQUM3QixVQUFPLFlBQVksU0FBUztJQUM1QjtBQUVGLFNBQU8sS0FBcUMsd0JBQXdCLE9BQU8sWUFBWTtHQUNyRixNQUFNLEVBQUUsYUFBYSxRQUFRO0FBQzdCLFVBQU8sWUFBWSxTQUFTO0lBQzVCO0FBRUYsU0FBTyxLQUFxQyx1QkFBdUIsT0FBTyxZQUFZO0dBQ3BGLE1BQU0sRUFBRSxhQUFhLFFBQVE7QUFDN0Isa0JBQWUsU0FBUztBQUN4QixVQUFPLEVBQUUsU0FBUyxNQUFNO0lBQ3hCO0FBR0YsU0FBTyxJQUFJLGtCQUFrQixZQUFZO0FBQ3ZDLFVBQU8sV0FBVztJQUNsQjtBQUVGLFNBQU8sS0FBb0MscUJBQXFCLE9BQU8sWUFBWTtHQUNqRixNQUFNLEVBQUUsWUFBWSxRQUFRO0FBQzVCLFVBQU8sU0FBUyxRQUFRO0lBQ3hCO0FBRUYsU0FBTyxLQUFrQyxvQkFBb0IsT0FBTyxZQUFZO0FBQzlFLFVBQU8sUUFBUSxRQUFRLEtBQUs7SUFDNUI7QUFHRixTQUFPLElBQUksZUFBZSxZQUFZO0FBQ3BDLFVBQU8sV0FBVztJQUNsQjtFQUdGLE1BQU0sYUFBYSxLQUFLLFFBQVEsT0FBTyxLQUFLLFNBQVMsWUFBWTtBQUdqRSxTQUFPLFNBQVMsTUFBTSxPQUFPLG9CQUFvQjtHQUMvQyxNQUFNO0dBQ04sUUFBUTtHQUNSLGVBQWU7R0FDZixVQUFVO0dBQ1gsQ0FBQztBQUdGLFNBQU8sSUFBSSxLQUFLLE9BQU8sVUFBVSxVQUFVO0FBQ3pDLFNBQU0sUUFBUSxFQUFFLGdCQUFnQixhQUFhLENBQUMsQ0FBQyxLQUM3QyxHQUNHLGFBQWEsS0FBSyxRQUFRLFlBQVksYUFBYSxDQUFDLENBQ3BELFVBQVUsQ0FDVixRQUFRLG1CQUFtQixPQUFPLE9BQU8sZUFBZSx1QkFBdUIsQ0FDbkY7SUFDRDtJQUVKLEVBQUUsUUFBUSxjQUFjLENBQ3pCOzs7Y0F0N0NvQztVQUNIO1lBRWtCO1VBQ3RCO3lCQUM2QjtzQkFFSjtxQkFLcEI7Z0JBQ1k7cUJBRVM7d0JBRUs7cUJBQ1A7eUJBQ1E7dUJBQ0o7YUFFSTthQVduQjtjQUNUO21CQVdiIn0=