semantifold 0.3.0 → 0.5.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 (303) hide show
  1. package/README.md +61 -15
  2. package/build/index.d.ts +52 -2
  3. package/build/index.d.ts.map +1 -1
  4. package/build/index.js +60 -8
  5. package/build/src/artifact-path.d.ts +23 -1
  6. package/build/src/artifact-path.d.ts.map +1 -1
  7. package/build/src/artifact-path.js +45 -3
  8. package/build/src/artifacts.d.ts.map +1 -1
  9. package/build/src/artifacts.js +66 -1
  10. package/build/src/backends/android.d.ts +49 -0
  11. package/build/src/backends/android.d.ts.map +1 -0
  12. package/build/src/backends/android.js +1274 -0
  13. package/build/src/backends/c-validation.d.ts.map +1 -1
  14. package/build/src/backends/c-validation.js +7 -3
  15. package/build/src/backends/cpp-validation.d.ts.map +1 -1
  16. package/build/src/backends/cpp-validation.js +7 -3
  17. package/build/src/backends/csharp.js +7 -1
  18. package/build/src/backends/dart-runtime.d.ts +2 -0
  19. package/build/src/backends/dart-runtime.d.ts.map +1 -0
  20. package/build/src/backends/dart-runtime.js +41 -0
  21. package/build/src/backends/dart.d.ts +20 -0
  22. package/build/src/backends/dart.d.ts.map +1 -0
  23. package/build/src/backends/dart.js +321 -0
  24. package/build/src/backends/effects.d.ts +60 -0
  25. package/build/src/backends/effects.d.ts.map +1 -0
  26. package/build/src/backends/effects.js +746 -0
  27. package/build/src/backends/go.js +18 -4
  28. package/build/src/backends/identifiers.d.ts +36 -4
  29. package/build/src/backends/identifiers.d.ts.map +1 -1
  30. package/build/src/backends/identifiers.js +160 -10
  31. package/build/src/backends/index.d.ts.map +1 -1
  32. package/build/src/backends/index.js +27 -4
  33. package/build/src/backends/ios.d.ts +68 -0
  34. package/build/src/backends/ios.d.ts.map +1 -0
  35. package/build/src/backends/ios.js +1503 -0
  36. package/build/src/backends/java.d.ts.map +1 -1
  37. package/build/src/backends/java.js +429 -36
  38. package/build/src/backends/javascript.d.ts +6 -0
  39. package/build/src/backends/javascript.d.ts.map +1 -1
  40. package/build/src/backends/javascript.js +380 -24
  41. package/build/src/backends/kotlin-runtime.d.ts +3 -0
  42. package/build/src/backends/kotlin-runtime.d.ts.map +1 -0
  43. package/build/src/backends/kotlin-runtime.js +29 -0
  44. package/build/src/backends/kotlin.d.ts +33 -0
  45. package/build/src/backends/kotlin.d.ts.map +1 -0
  46. package/build/src/backends/kotlin.js +138 -0
  47. package/build/src/backends/native-validation.d.ts +2 -2
  48. package/build/src/backends/native-validation.d.ts.map +1 -1
  49. package/build/src/backends/native-validation.js +2 -2
  50. package/build/src/backends/ordered-expressions.d.ts.map +1 -1
  51. package/build/src/backends/ordered-expressions.js +39 -7
  52. package/build/src/backends/php-stdlib-support.d.ts +19 -0
  53. package/build/src/backends/php-stdlib-support.d.ts.map +1 -0
  54. package/build/src/backends/php-stdlib-support.js +227 -0
  55. package/build/src/backends/php.d.ts.map +1 -1
  56. package/build/src/backends/php.js +448 -33
  57. package/build/src/backends/program.d.ts +83 -0
  58. package/build/src/backends/program.d.ts.map +1 -0
  59. package/build/src/backends/program.js +1309 -0
  60. package/build/src/backends/python.js +7 -1
  61. package/build/src/backends/ruby.d.ts.map +1 -1
  62. package/build/src/backends/ruby.js +310 -24
  63. package/build/src/backends/rust-runtime.d.ts +7 -0
  64. package/build/src/backends/rust-runtime.d.ts.map +1 -0
  65. package/build/src/backends/rust-runtime.js +32 -0
  66. package/build/src/backends/rust-validation.d.ts +9 -0
  67. package/build/src/backends/rust-validation.d.ts.map +1 -0
  68. package/build/src/backends/rust-validation.js +78 -0
  69. package/build/src/backends/rust.d.ts +24 -0
  70. package/build/src/backends/rust.d.ts.map +1 -0
  71. package/build/src/backends/rust.js +344 -0
  72. package/build/src/backends/scalars.d.ts +14 -6
  73. package/build/src/backends/scalars.d.ts.map +1 -1
  74. package/build/src/backends/scalars.js +167 -17
  75. package/build/src/backends/shared.d.ts +23 -4
  76. package/build/src/backends/shared.d.ts.map +1 -1
  77. package/build/src/backends/shared.js +2174 -62
  78. package/build/src/backends/stdlib-support.d.ts +14 -0
  79. package/build/src/backends/stdlib-support.d.ts.map +1 -0
  80. package/build/src/backends/stdlib-support.js +237 -0
  81. package/build/src/backends/swift-runtime.d.ts +3 -0
  82. package/build/src/backends/swift-runtime.d.ts.map +1 -0
  83. package/build/src/backends/swift-runtime.js +14 -0
  84. package/build/src/backends/swift.d.ts +8 -0
  85. package/build/src/backends/swift.d.ts.map +1 -0
  86. package/build/src/backends/swift.js +127 -0
  87. package/build/src/backends/typescript.d.ts.map +1 -1
  88. package/build/src/backends/typescript.js +344 -24
  89. package/build/src/backends/wasm.d.ts +43 -0
  90. package/build/src/backends/wasm.d.ts.map +1 -0
  91. package/build/src/backends/wasm.js +2164 -0
  92. package/build/src/backends/writer.d.ts +255 -4
  93. package/build/src/backends/writer.d.ts.map +1 -1
  94. package/build/src/backends/writer.js +491 -3
  95. package/build/src/diagnostic.d.ts +4 -3
  96. package/build/src/diagnostic.d.ts.map +1 -1
  97. package/build/src/diagnostic.js +5 -3
  98. package/build/src/frontends/c.d.ts.map +1 -1
  99. package/build/src/frontends/c.js +5 -3
  100. package/build/src/frontends/cpp.d.ts.map +1 -1
  101. package/build/src/frontends/cpp.js +5 -3
  102. package/build/src/frontends/csharp.d.ts.map +1 -1
  103. package/build/src/frontends/csharp.js +7 -3
  104. package/build/src/frontends/dart.d.ts +10 -0
  105. package/build/src/frontends/dart.d.ts.map +1 -0
  106. package/build/src/frontends/dart.js +913 -0
  107. package/build/src/frontends/index.d.ts +3 -1
  108. package/build/src/frontends/index.d.ts.map +1 -1
  109. package/build/src/frontends/index.js +15 -5
  110. package/build/src/frontends/java.d.ts +110 -1
  111. package/build/src/frontends/java.d.ts.map +1 -1
  112. package/build/src/frontends/java.js +1725 -70
  113. package/build/src/frontends/javascript-typescript.d.ts +69 -1
  114. package/build/src/frontends/javascript-typescript.d.ts.map +1 -1
  115. package/build/src/frontends/javascript-typescript.js +1825 -93
  116. package/build/src/frontends/kotlin.d.ts +10 -0
  117. package/build/src/frontends/kotlin.d.ts.map +1 -0
  118. package/build/src/frontends/kotlin.js +685 -0
  119. package/build/src/frontends/php.d.ts +118 -1
  120. package/build/src/frontends/php.d.ts.map +1 -1
  121. package/build/src/frontends/php.js +1583 -76
  122. package/build/src/frontends/program.d.ts +74 -0
  123. package/build/src/frontends/program.d.ts.map +1 -0
  124. package/build/src/frontends/program.js +989 -0
  125. package/build/src/frontends/ruby.d.ts +68 -1
  126. package/build/src/frontends/ruby.d.ts.map +1 -1
  127. package/build/src/frontends/ruby.js +1446 -101
  128. package/build/src/frontends/rust-parser.d.ts +11 -0
  129. package/build/src/frontends/rust-parser.d.ts.map +1 -0
  130. package/build/src/frontends/rust-parser.js +15 -0
  131. package/build/src/frontends/rust.d.ts +14 -0
  132. package/build/src/frontends/rust.d.ts.map +1 -0
  133. package/build/src/frontends/rust.js +715 -0
  134. package/build/src/frontends/scalars.d.ts +10 -0
  135. package/build/src/frontends/scalars.d.ts.map +1 -1
  136. package/build/src/frontends/scalars.js +28 -2
  137. package/build/src/frontends/swift.d.ts +10 -0
  138. package/build/src/frontends/swift.d.ts.map +1 -0
  139. package/build/src/frontends/swift.js +860 -0
  140. package/build/src/frontends/types.d.ts +186 -0
  141. package/build/src/frontends/types.d.ts.map +1 -0
  142. package/build/src/frontends/types.js +634 -0
  143. package/build/src/language-registry.d.ts +46 -4
  144. package/build/src/language-registry.d.ts.map +1 -1
  145. package/build/src/language-registry.js +177 -13
  146. package/build/src/mapping.d.ts +2 -2
  147. package/build/src/mapping.d.ts.map +1 -1
  148. package/build/src/mapping.js +31 -10
  149. package/build/src/semantic/capabilities.d.ts +66 -0
  150. package/build/src/semantic/capabilities.d.ts.map +1 -0
  151. package/build/src/semantic/capabilities.js +649 -0
  152. package/build/src/semantic/effects.d.ts +26 -0
  153. package/build/src/semantic/effects.d.ts.map +1 -0
  154. package/build/src/semantic/effects.js +764 -0
  155. package/build/src/semantic/generics.d.ts +23 -0
  156. package/build/src/semantic/generics.d.ts.map +1 -0
  157. package/build/src/semantic/generics.js +61 -0
  158. package/build/src/semantic/lifetime.d.ts +37 -0
  159. package/build/src/semantic/lifetime.d.ts.map +1 -0
  160. package/build/src/semantic/lifetime.js +527 -0
  161. package/build/src/semantic/provenance.d.ts +9 -2
  162. package/build/src/semantic/provenance.d.ts.map +1 -1
  163. package/build/src/semantic/provenance.js +462 -20
  164. package/build/src/semantic/scalars.d.ts +11 -0
  165. package/build/src/semantic/scalars.d.ts.map +1 -1
  166. package/build/src/semantic/scalars.js +16 -1
  167. package/build/src/semantic/stdlib.d.ts +254 -0
  168. package/build/src/semantic/stdlib.d.ts.map +1 -0
  169. package/build/src/semantic/stdlib.js +880 -0
  170. package/build/src/semantic/types.d.ts +3108 -178
  171. package/build/src/semantic/types.d.ts.map +1 -1
  172. package/build/src/semantic/types.js +730 -15
  173. package/build/src/semantic/validate.d.ts +85 -5
  174. package/build/src/semantic/validate.d.ts.map +1 -1
  175. package/build/src/semantic/validate.js +2576 -98
  176. package/build/src/stdlib-facades.d.ts +304 -0
  177. package/build/src/stdlib-facades.d.ts.map +1 -0
  178. package/build/src/stdlib-facades.js +1167 -0
  179. package/build/src/stdlib-negotiation.d.ts +69 -0
  180. package/build/src/stdlib-negotiation.d.ts.map +1 -0
  181. package/build/src/stdlib-negotiation.js +403 -0
  182. package/build/src/stdlib-providers.d.ts +72 -0
  183. package/build/src/stdlib-providers.d.ts.map +1 -0
  184. package/build/src/stdlib-providers.js +339 -0
  185. package/build/src/toolchains.d.ts +55 -1
  186. package/build/src/toolchains.d.ts.map +1 -1
  187. package/build/src/toolchains.js +15 -4
  188. package/docs/android.md +79 -0
  189. package/docs/architecture.md +47 -13
  190. package/docs/dart.md +60 -0
  191. package/docs/goals.md +3 -3
  192. package/docs/ios.md +121 -0
  193. package/docs/kotlin.md +42 -0
  194. package/docs/language-support.md +238 -26
  195. package/docs/multi-file-modules.md +52 -0
  196. package/docs/parser-qualification.md +121 -8
  197. package/docs/plans/2026-09-05-standard-library-portability.md +10 -10
  198. package/docs/rust.md +88 -0
  199. package/docs/source-maps.md +17 -7
  200. package/docs/specification.md +5 -0
  201. package/docs/standard-library-portability.md +39 -8
  202. package/docs/swift.md +44 -0
  203. package/docs/testing.md +381 -4
  204. package/docs/webassembly.md +52 -0
  205. package/index.js +66 -8
  206. package/node_modules/semantifold-tree-sitter-legacy-internal/README.md +2 -2
  207. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/LICENSE +21 -0
  208. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/README.md +45 -0
  209. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/binding.gyp +30 -0
  210. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/binding.cc +20 -0
  211. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/binding_test.js +9 -0
  212. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/index.d.ts +28 -0
  213. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/index.js +11 -0
  214. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/grammar.js +1630 -0
  215. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/package.json +64 -0
  216. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/darwin-arm64/tree-sitter-rust.node +0 -0
  217. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/darwin-x64/tree-sitter-rust.node +0 -0
  218. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/linux-arm64/tree-sitter-rust.node +0 -0
  219. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/linux-x64/tree-sitter-rust.node +0 -0
  220. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/win32-arm64/tree-sitter-rust.node +0 -0
  221. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/win32-x64/tree-sitter-rust.node +0 -0
  222. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/highlights.scm +159 -0
  223. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/injections.scm +9 -0
  224. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/tags.scm +60 -0
  225. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/grammar.json +9405 -0
  226. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/node-types.json +5399 -0
  227. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/parser.c +192569 -0
  228. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/scanner.c +393 -0
  229. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/alloc.h +54 -0
  230. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/array.h +290 -0
  231. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/parser.h +266 -0
  232. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/tree-sitter-rust.wasm +0 -0
  233. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/tree-sitter.json +53 -0
  234. package/node_modules/semantifold-tree-sitter-legacy-internal/package.json +3 -2
  235. package/node_modules/semantifold-tree-sitter-legacy-internal/src/c.js +5 -4
  236. package/package.json +5 -2
  237. package/src/artifact-path.js +47 -2
  238. package/src/artifacts.js +67 -0
  239. package/src/backends/android.js +1370 -0
  240. package/src/backends/c-validation.js +6 -1
  241. package/src/backends/cpp-validation.js +6 -1
  242. package/src/backends/csharp.js +3 -0
  243. package/src/backends/dart-runtime.js +41 -0
  244. package/src/backends/dart.js +326 -0
  245. package/src/backends/effects.js +705 -0
  246. package/src/backends/go.js +14 -2
  247. package/src/backends/identifiers.js +166 -9
  248. package/src/backends/index.js +27 -2
  249. package/src/backends/ios.js +1612 -0
  250. package/src/backends/java.js +454 -36
  251. package/src/backends/javascript.js +389 -23
  252. package/src/backends/kotlin-runtime.js +29 -0
  253. package/src/backends/kotlin.js +144 -0
  254. package/src/backends/native-validation.js +1 -1
  255. package/src/backends/ordered-expressions.js +40 -6
  256. package/src/backends/php-stdlib-support.js +239 -0
  257. package/src/backends/php.js +469 -32
  258. package/src/backends/program.js +1408 -0
  259. package/src/backends/python.js +3 -0
  260. package/src/backends/ruby.js +326 -23
  261. package/src/backends/rust-runtime.js +34 -0
  262. package/src/backends/rust-validation.js +75 -0
  263. package/src/backends/rust.js +335 -0
  264. package/src/backends/scalars.js +141 -16
  265. package/src/backends/shared.js +2314 -115
  266. package/src/backends/stdlib-support.js +234 -0
  267. package/src/backends/swift-runtime.js +14 -0
  268. package/src/backends/swift.js +132 -0
  269. package/src/backends/typescript.js +349 -23
  270. package/src/backends/wasm.js +2208 -0
  271. package/src/backends/writer.js +545 -2
  272. package/src/diagnostic.js +4 -2
  273. package/src/frontends/c.js +4 -2
  274. package/src/frontends/cpp.js +4 -2
  275. package/src/frontends/csharp.js +4 -2
  276. package/src/frontends/dart.js +963 -0
  277. package/src/frontends/index.js +14 -4
  278. package/src/frontends/java.js +1977 -69
  279. package/src/frontends/javascript-typescript.js +2046 -102
  280. package/src/frontends/kotlin.js +713 -0
  281. package/src/frontends/php.js +1725 -79
  282. package/src/frontends/program.js +1062 -0
  283. package/src/frontends/ruby.js +1624 -98
  284. package/src/frontends/rust-parser.js +18 -0
  285. package/src/frontends/rust.js +714 -0
  286. package/src/frontends/scalars.js +31 -1
  287. package/src/frontends/swift.js +893 -0
  288. package/src/frontends/types.js +750 -0
  289. package/src/language-registry.js +182 -12
  290. package/src/mapping.js +33 -9
  291. package/src/semantic/capabilities.js +671 -0
  292. package/src/semantic/effects.js +737 -0
  293. package/src/semantic/generics.js +58 -0
  294. package/src/semantic/lifetime.js +517 -0
  295. package/src/semantic/provenance.js +412 -19
  296. package/src/semantic/scalars.js +17 -0
  297. package/src/semantic/stdlib.js +921 -0
  298. package/src/semantic/types.js +810 -14
  299. package/src/semantic/validate.js +2934 -209
  300. package/src/stdlib-facades.js +1211 -0
  301. package/src/stdlib-negotiation.js +446 -0
  302. package/src/stdlib-providers.js +377 -0
  303. package/src/toolchains.js +16 -3
@@ -0,0 +1,1503 @@
1
+ // @ts-check
2
+ import { createHash } from "node:crypto";
3
+ import { isDenseArray } from "../array.js";
4
+ import { findPortableArtifactPathConflict, isSafeArtifactPath } from "../artifact-path.js";
5
+ import { createByteMapping } from "../binary-mapping.js";
6
+ import { SemantifoldDiagnostic, unsupportedCapability } from "../diagnostic.js";
7
+ import { finalizeMapping, toSourceMapV3 } from "../mapping.js";
8
+ import { hasOnlyUnicodeScalars } from "../semantic/scalars.js";
9
+ import { preflightSemanticProgram } from "./program.js";
10
+ import { emitScalarType, emitStringLiteral } from "./scalars.js";
11
+ import { SourceWriter } from "./writer.js";
12
+ /** @type {Readonly<Set<import("../semantic/types.js").SemanticLanguage>>} */
13
+ const iosSourceLanguages = new Set([
14
+ "php", "ruby", "javascript", "typescript", "java", "kotlin", "python", "csharp", "go", "c", "cpp", "rust", "swift", "dart"
15
+ ]);
16
+ const configurationFields = new Set([
17
+ "bundleIdentifier", "capabilities", "deploymentTarget", "displayName", "entitlements", "infoPlist", "lifecycle",
18
+ "moduleName", "organizationPrefix", "permissions", "privacyDeclarations", "productName", "resourceRoot", "sourceRoot"
19
+ ]);
20
+ const assetFields = new Set(["content", "mediaType", "path", "sha256"]);
21
+ const generatorVersion = "0.3.0";
22
+ const excludedPathPatterns = Object.freeze([
23
+ "**/*.xcuserstate",
24
+ "**/xcuserdata/**",
25
+ ".swiftpm/**",
26
+ "DerivedData/**",
27
+ "build/**"
28
+ ]);
29
+ const mediaTypePattern = /^[A-Za-z0-9!#$&^_.+-]+\/[A-Za-z0-9!#$&^_.+-]+(?:;[\u0020-\u007e]+)?$/u;
30
+ const binaryOperations = Object.freeze({
31
+ BooleanAnd: "&&",
32
+ BooleanEqual: "==",
33
+ BooleanNotEqual: "!=",
34
+ BooleanOr: "||",
35
+ IntegerAdd: "+",
36
+ IntegerEqual: "==",
37
+ IntegerGreaterThan: ">",
38
+ IntegerGreaterThanOrEqual: ">=",
39
+ IntegerLessThan: "<",
40
+ IntegerLessThanOrEqual: "<=",
41
+ IntegerMultiply: "*",
42
+ IntegerNotEqual: "!=",
43
+ IntegerSubtract: "-",
44
+ StringConcat: "+",
45
+ StringEqual: "==",
46
+ StringNotEqual: "!="
47
+ });
48
+ const unaryOperations = Object.freeze({ BooleanNot: "!", IntegerNegate: "-" });
49
+ const iosSwiftRuntime = `final class SemantifoldOutputSink {
50
+ private(set) var lines: [String] = []
51
+
52
+ func write(_ value: Int64) {
53
+ lines.append(String(value))
54
+ }
55
+
56
+ func write(_ value: Bool) {
57
+ lines.append(value ? "true" : "false")
58
+ }
59
+
60
+ func write(_ value: String) {
61
+ lines.append(value)
62
+ }
63
+ }
64
+
65
+ func semantifold_string_equal(_ left: String, _ right: String) -> Bool {
66
+ return left.unicodeScalars.elementsEqual(right.unicodeScalars)
67
+ }
68
+
69
+ func semantifold_string_not_equal(_ left: String, _ right: String) -> Bool {
70
+ return !left.unicodeScalars.elementsEqual(right.unicodeScalars)
71
+ }
72
+
73
+ func semantifold_keep_mutable<T>(_ value: inout T) {
74
+ }
75
+ `;
76
+ /** @typedef {{content: string, field: string}} ConfigurationFragment */
77
+ /** @typedef {string | ConfigurationFragment} ConfigurationTextPart */
78
+ /** @typedef {string | readonly ConfigurationTextPart[]} ConfigurationLine */
79
+ /** @typedef {{end: number, field: string, start: number}} ConfigurationSpan */
80
+ /** @typedef {{content: string, configurationSpans: ConfigurationSpan[]}} RenderedConfigurationText */
81
+ /** @typedef {{end: number, field: string, path: string, start: number}} ConfigurationArtifactSpan */
82
+ /** Records configuration causality while an owning renderer emits text. */
83
+ class ConfigurationTextWriter {
84
+ constructor() {
85
+ this.content = "";
86
+ /** @type {ConfigurationSpan[]} */
87
+ this.configurationSpans = [];
88
+ }
89
+ /**
90
+ * Appends literal or field-owned text.
91
+ * @param {ConfigurationTextPart | readonly ConfigurationTextPart[]} value - Ordered output text.
92
+ */
93
+ append(value) {
94
+ const parts = Array.isArray(value) ? value : [value];
95
+ for (const part of parts) {
96
+ if (typeof part == "string") {
97
+ this.content += part;
98
+ }
99
+ else {
100
+ const start = this.content.length;
101
+ this.content += part.content;
102
+ this.configurationSpans.push({ end: this.content.length, field: part.field, start });
103
+ }
104
+ }
105
+ }
106
+ /**
107
+ * Finishes renderer-owned text collection.
108
+ * @returns {RenderedConfigurationText} Finished content and causal spans.
109
+ */
110
+ finish() {
111
+ return { configurationSpans: this.configurationSpans, content: this.content };
112
+ }
113
+ }
114
+ /**
115
+ * Marks text as causally owned by one normalized configuration field.
116
+ * @param {string} field - Configuration field.
117
+ * @param {string} content - Exact rendered token content.
118
+ * @returns {ConfigurationFragment} Tagged token.
119
+ */
120
+ function configurationFragment(field, content) {
121
+ return { content, field };
122
+ }
123
+ /**
124
+ * Preflights one complete project against the delivered Swift Tasks 001-004 profile.
125
+ * @param {object} input - iOS application generation input.
126
+ * @param {import("../semantic/types.js").SemanticModule} [input.module] - Single module to normalize.
127
+ * @param {import("../semantic/types.js").SemanticProgram} [input.program] - Caller-owned Task 010 project.
128
+ * @param {import("../semantic/types.js").IosApplicationConfigurationInput} [input.configuration] - Closed application configuration.
129
+ * @param {import("../semantic/types.js").IosApplicationAssetInput[]} [input.assets] - Exact caller-provided assets.
130
+ * @returns {{assets: import("../semantic/types.js").IosApplicationAssetInput[], configuration: import("../semantic/types.js").IosApplicationConfiguration, modulePaths: Map<string, string>, modules: import("../semantic/types.js").SemanticModule[], program: import("../semantic/types.js").SemanticProgram, sources: {content: string, filename: string, language?: import("../semantic/types.js").SemanticLanguage}[]}} Prepared application program.
131
+ */
132
+ export function preflightIosApplication(input) {
133
+ if (!isPlainObject(input) || Boolean(input.module) == Boolean(input.program)) {
134
+ throw new SemantifoldDiagnostic({
135
+ code: "INVALID_APPLICATION_INPUT",
136
+ language: "ios",
137
+ message: "iOS application generation requires exactly one semantic module or program."
138
+ });
139
+ }
140
+ const configuration = normalizeConfiguration(input.configuration);
141
+ const program = input.program ?? normalizeSingleModule(input.module);
142
+ const prepared = preflightSemanticProgram({
143
+ backendLanguage: "swift",
144
+ diagnosticLanguage: "ios",
145
+ program,
146
+ sourceLanguages: iosSourceLanguages
147
+ });
148
+ const modulePaths = new Map(prepared.modules.map(module => [
149
+ /** @type {string} */ (Reflect.get(module, "id")),
150
+ `${configuration.sourceRoot}/Generated/${moduleName(/** @type {string} */ (Reflect.get(module, "id")))}.swift`
151
+ ]));
152
+ const assets = normalizeAssets(input.assets, configuration.resourceRoot);
153
+ const conflict = findPortableArtifactPathConflict([
154
+ `${configuration.sourceRoot}/Generated/SemantifoldRuntime.swift`,
155
+ ...modulePaths.values(),
156
+ `${configuration.resourceRoot}/Contents.json`,
157
+ ...assets.map(({ path }) => path)
158
+ ]);
159
+ if (conflict)
160
+ invalidPath(`Application artifact path '${conflict.path}' has a ${conflict.kind} conflict${conflict.other ? ` with '${conflict.other}'` : ""}.`);
161
+ return { ...prepared, assets, configuration, modulePaths };
162
+ }
163
+ /**
164
+ * Generates the deterministic semantic Swift portion of one iOS application artifact set.
165
+ * @param {Parameters<typeof preflightIosApplication>[0]} input - iOS generation request.
166
+ * @returns {{artifacts: import("../semantic/types.js").GeneratedSetArtifact[], metadata: {applicationManifest: string, platformQualification: string}, target: "ios"}} Candidate artifact set.
167
+ */
168
+ export function generateIosApplication(input) {
169
+ const prepared = preflightIosApplication(input);
170
+ const semanticArtifacts = renderSemanticArtifacts(prepared);
171
+ const applicationPaths = applicationArtifactPaths(prepared);
172
+ const project = renderPbxProject(prepared, applicationPaths);
173
+ const scheme = renderSharedScheme(prepared);
174
+ const baseConfiguration = renderBaseConfiguration(prepared.configuration);
175
+ const infoPlist = renderInfoPlist(prepared.configuration);
176
+ const unitTests = renderUnitTests(prepared.configuration);
177
+ const uiTests = renderUiTests(prepared.configuration);
178
+ const configuration = prepared.configuration;
179
+ const entryNamespace = `SemantifoldModule${moduleName(prepared.program.entryModule)}`;
180
+ const app = `import SwiftUI
181
+
182
+ @main
183
+ struct SemantifoldApplication: App {
184
+ var body: some Scene {
185
+ WindowGroup {
186
+ SemantifoldOutputView(lines: SemantifoldBridge.run())
187
+ }
188
+ }
189
+ }
190
+ `;
191
+ const bridge = `enum SemantifoldBridge {
192
+ static func run() -> [String] {
193
+ return ${entryNamespace}.semantifoldEntry()
194
+ }
195
+ }
196
+ `;
197
+ const view = `import SwiftUI
198
+
199
+ struct SemantifoldOutputView: View {
200
+ let lines: [String]
201
+
202
+ var body: some View {
203
+ Text(lines.joined(separator: "\\n"))
204
+ .accessibilityIdentifier("semantifold-output")
205
+ }
206
+ }
207
+ `;
208
+ const product = configuration.productName;
209
+ /** @type {ConfigurationArtifactSpan[]} */
210
+ const configurationSpans = [];
211
+ const artifacts = [
212
+ configuredSyntheticText(`${product}.xcodeproj/project.pbxproj`, "manifest", project, configurationSpans, "Canonical deterministic Xcode project structure."),
213
+ configuredSyntheticText(`${product}.xcodeproj/xcshareddata/xcschemes/${product}.xcscheme`, "support", scheme, configurationSpans, "Canonical shared Xcode application/test scheme."),
214
+ configuredSyntheticText("Configuration/Base.xcconfig", "support", baseConfiguration, configurationSpans, "Closed unsigned iOS build configuration."),
215
+ configuredSyntheticText("Configuration/Info.plist", "support", infoPlist, configurationSpans, "Allowlisted iOS application property list."),
216
+ ...semanticArtifacts,
217
+ syntheticText("Sources/Application/App.swift", "entry", app, "Synthetic SwiftUI application lifecycle."),
218
+ syntheticText("Sources/Application/SemantifoldBridge.swift", "support", bridge, "Synthetic bridge from SwiftUI to the semantic entry."),
219
+ syntheticText("Sources/Application/SemantifoldOutputView.swift", "support", view, "Synthetic stable text output view and accessibility identifier."),
220
+ syntheticText("Assets.xcassets/Contents.json", "resource", stringifyCanonicalJson({
221
+ info: { author: "semantifold", version: 1 }
222
+ }), "Base asset-catalog metadata; no application icon is synthesized."),
223
+ ...prepared.assets.map(assetArtifact),
224
+ configuredSyntheticText(`Tests/${product}Tests.swift`, "support", unitTests, configurationSpans, "Synthetic pure-logic determinism XCTest source."),
225
+ configuredSyntheticText(`UITests/${product}UITests.swift`, "support", uiTests, configurationSpans, "Synthetic XCUI accessibility-route test source.")
226
+ ];
227
+ const manifestPath = "semantifold-project.json";
228
+ artifacts.push(syntheticText(manifestPath, "manifest", renderProjectManifest(prepared, artifacts, manifestPath, configurationSpans), "Versioned iOS project ownership and provenance manifest."));
229
+ return {
230
+ artifacts,
231
+ metadata: { applicationManifest: manifestPath, platformQualification: "deferred" },
232
+ target: "ios"
233
+ };
234
+ }
235
+ /**
236
+ * Renders the complete deterministic application ownership and provenance record.
237
+ * @param {ReturnType<typeof preflightIosApplication>} prepared - Fully preflighted application.
238
+ * @param {import("../semantic/types.js").GeneratedSetArtifact[]} artifacts - All non-manifest output artifacts.
239
+ * @param {string} manifestPath - Owned manifest path.
240
+ * @param {ConfigurationArtifactSpan[]} configurationSpans - Renderer-owned configuration ranges.
241
+ * @returns {string} Canonical manifest JSON.
242
+ */
243
+ function renderProjectManifest(prepared, artifacts, manifestPath, configurationSpans) {
244
+ const assetPaths = new Set(prepared.assets.map(({ path }) => path));
245
+ const semanticArtifacts = artifacts.filter(artifact => artifact.provenance.kind == "text");
246
+ const configuration = prepared.configuration;
247
+ return stringifyCanonicalJson({
248
+ configuration,
249
+ generator: { name: "semantifold", version: generatorVersion },
250
+ ownership: {
251
+ excludedPathPatterns,
252
+ ownedPaths: [...artifacts.map(({ path }) => path), manifestPath]
253
+ },
254
+ platformRequirements: {
255
+ appleSdk: { status: "deferred" },
256
+ iosSimulator: { status: "deferred" },
257
+ macosHost: { status: "deferred" },
258
+ swiftc: { status: "deferred" },
259
+ xcode: { status: "deferred" },
260
+ xctest: { status: "deferred" },
261
+ xcuiautomation: { status: "deferred" }
262
+ },
263
+ provenance: {
264
+ assets: prepared.assets.map(asset => ({
265
+ contentKind: typeof asset.content == "string" ? "text" : "binary",
266
+ mediaType: asset.mediaType,
267
+ path: asset.path,
268
+ sha256: asset.sha256
269
+ })),
270
+ configuration: Object.keys(configuration).sort().map(field => ({
271
+ field,
272
+ manifestPointer: `/configuration/${field}`,
273
+ outputs: configurationOutputCitations(configurationSpans, field)
274
+ })),
275
+ semanticSources: prepared.sources.map(source => ({
276
+ artifacts: semanticArtifacts.filter(artifact => artifact.provenance.kind == "text" &&
277
+ artifact.provenance.mapping.spans.some(({ origin }) => originReferencesFilename(origin, source.filename)))
278
+ .map(({ path }) => path),
279
+ filename: source.filename,
280
+ ...(source.language === undefined ? {} : { language: source.language }),
281
+ sha256: createHash("sha256").update(source.content).digest("hex")
282
+ })),
283
+ syntheticScaffolding: [
284
+ ...artifacts.filter(artifact => artifact.provenance.kind == "synthetic" && !assetPaths.has(artifact.path))
285
+ .map(({ path }) => path),
286
+ manifestPath
287
+ ]
288
+ },
289
+ schema: "SemantifoldIosProject",
290
+ semanticProgram: semanticProgramManifest(prepared),
291
+ target: "ios",
292
+ version: 1
293
+ });
294
+ }
295
+ /**
296
+ * Records stable semantic input identities and their generated Swift linkage.
297
+ * @param {ReturnType<typeof preflightIosApplication>} prepared - Fully preflighted application.
298
+ * @returns {Record<string, unknown>} Versioned semantic-program manifest section.
299
+ */
300
+ function semanticProgramManifest(prepared) {
301
+ const moduleIds = new Map(prepared.program.modules.map((module, index) => [module.id, index]));
302
+ const sourceContent = new Map(prepared.sources.map(source => [source.filename, source.content]));
303
+ const modules = prepared.program.modules.map(module => {
304
+ const id = module.id;
305
+ const path = /** @type {string} */ (prepared.modulePaths.get(id));
306
+ const source = prepared.program.sources.find(candidate => candidate.filename == module.sourceFilename);
307
+ const content = sourceContent.get(module.sourceFilename);
308
+ if (!source || content === undefined)
309
+ throw new TypeError(`Preflighted iOS module '${id}' lost its source ownership.`);
310
+ const dependencies = [...new Set(module.imports.map(({ moduleId }) => moduleId))]
311
+ .sort((left, right) => /** @type {number} */ (moduleIds.get(left)) - /** @type {number} */ (moduleIds.get(right)));
312
+ return {
313
+ dependencies,
314
+ generatedArtifacts: [path],
315
+ id,
316
+ namespace: `SemantifoldModule${moduleName(id)}`,
317
+ source: {
318
+ filename: source.filename,
319
+ id: source.id,
320
+ sha256: createHash("sha256").update(content).digest("hex")
321
+ }
322
+ };
323
+ });
324
+ const sources = prepared.program.sources.map(source => {
325
+ const content = sourceContent.get(source.filename);
326
+ if (content === undefined)
327
+ throw new TypeError(`Preflighted iOS source '${source.filename}' lost its content.`);
328
+ return {
329
+ filename: source.filename,
330
+ id: source.id,
331
+ language: source.language,
332
+ moduleIds: modules.filter(module => module.source.filename == source.filename).map(({ id }) => id),
333
+ ownership: source.ownership ?? "application",
334
+ sha256: createHash("sha256").update(content).digest("hex")
335
+ };
336
+ });
337
+ const entryId = prepared.program.entryModule;
338
+ const entryArtifact = /** @type {string} */ (prepared.modulePaths.get(entryId));
339
+ const entryNamespace = `SemantifoldModule${moduleName(entryId)}`;
340
+ return {
341
+ entry: {
342
+ applicationArtifact: `${prepared.configuration.sourceRoot}/Application/App.swift`,
343
+ bridgeArtifact: `${prepared.configuration.sourceRoot}/Application/SemantifoldBridge.swift`,
344
+ generatedArtifact: entryArtifact,
345
+ generatedFunctionIdentity: `${entryNamespace}.semantifoldEntry`,
346
+ moduleId: entryId
347
+ },
348
+ modules,
349
+ schema: "SemantifoldIosSemanticProgram",
350
+ sources,
351
+ version: 1
352
+ };
353
+ }
354
+ /**
355
+ * Determines whether one closed semantic origin cites a source filename.
356
+ * @param {import("../semantic/types.js").SemanticOrigin} origin - Mapped origin.
357
+ * @param {string} filename - Original caller filename.
358
+ * @returns {boolean} Whether the source participates in the origin.
359
+ */
360
+ function originReferencesFilename(origin, filename) {
361
+ if (origin.kind == "source")
362
+ return origin.location.filename == filename;
363
+ if (origin.kind == "derived")
364
+ return origin.origins.some(({ location }) => location.filename == filename);
365
+ return origin.relatedOrigins.some(({ location }) => location.filename == filename);
366
+ }
367
+ /**
368
+ * Groups renderer-recorded configuration ranges without scanning generated text.
369
+ * @param {ConfigurationArtifactSpan[]} spans - Causal artifact spans.
370
+ * @param {string} field - Normalized configuration field.
371
+ * @returns {{path: string, ranges: {end: number, start: number}[]}[]} Stable output citations.
372
+ */
373
+ function configurationOutputCitations(spans, field) {
374
+ /** @type {Map<string, {end: number, start: number}[]>} */
375
+ const byPath = new Map();
376
+ for (const span of spans) {
377
+ if (span.field != field)
378
+ continue;
379
+ const ranges = byPath.get(span.path) ?? [];
380
+ ranges.push({ end: span.end, start: span.start });
381
+ byPath.set(span.path, ranges);
382
+ }
383
+ return [...byPath].map(([path, ranges]) => ({ path, ranges }));
384
+ }
385
+ /**
386
+ * Renders the shared capture runtime and mapped per-module semantic Swift.
387
+ * @param {ReturnType<typeof preflightIosApplication>} prepared - Fully preflighted application.
388
+ * @returns {import("../semantic/types.js").GeneratedSetArtifact[]} Ordered semantic artifacts.
389
+ */
390
+ function renderSemanticArtifacts(prepared) {
391
+ const paths = prepared.modulePaths;
392
+ const declarations = new Map();
393
+ for (const module of prepared.modules) {
394
+ for (const declaration of module.functions)
395
+ declarations.set(declaration.id, {
396
+ declaration,
397
+ moduleId: /** @type {string} */ (Reflect.get(module, "id"))
398
+ });
399
+ }
400
+ /** @type {import("../semantic/types.js").GeneratedSetArtifact[]} */
401
+ const artifacts = [{
402
+ content: iosSwiftRuntime,
403
+ contentKind: "text",
404
+ mediaType: "text/x-swift",
405
+ ownership: "generated",
406
+ path: "Sources/Generated/SemantifoldRuntime.swift",
407
+ provenance: {
408
+ kind: "synthetic",
409
+ reason: "Shared iOS application output capture and exact Swift scalar support.",
410
+ relatedOrigins: []
411
+ },
412
+ role: "support"
413
+ }];
414
+ for (const module of prepared.modules) {
415
+ const moduleId = /** @type {string} */ (Reflect.get(module, "id"));
416
+ const filename = /** @type {string} */ (paths.get(moduleId));
417
+ const writer = new SourceWriter({
418
+ filename,
419
+ language: "swift",
420
+ module,
421
+ program: prepared.program,
422
+ programPaths: paths,
423
+ sources: prepared.sources
424
+ });
425
+ emitSemanticModule(writer, module, moduleId, moduleId == prepared.program.entryModule, declarations);
426
+ const mapping = finalizeMapping(writer.finish());
427
+ artifacts.push({
428
+ content: mapping.generated.content,
429
+ contentKind: "text",
430
+ mediaType: "text/x-swift",
431
+ ownership: "generated",
432
+ path: filename,
433
+ provenance: { kind: "text", mapping, sourceMap: toSourceMapV3(mapping), sourceMapFilename: `${filename}.map` },
434
+ role: "source"
435
+ });
436
+ }
437
+ return artifacts;
438
+ }
439
+ /**
440
+ * Produces all project paths referenced by the Xcode model.
441
+ * @param {ReturnType<typeof preflightIosApplication>} prepared - Prepared application.
442
+ * @returns {{appSources: string[], assets: string[], infoPlist: string, unitTest: string, uiTest: string, xcconfig: string}} Paths.
443
+ */
444
+ function applicationArtifactPaths(prepared) {
445
+ const { productName: product, resourceRoot, sourceRoot } = prepared.configuration;
446
+ return {
447
+ appSources: [
448
+ `${sourceRoot}/Generated/SemantifoldRuntime.swift`,
449
+ ...prepared.modulePaths.values(),
450
+ `${sourceRoot}/Application/App.swift`,
451
+ `${sourceRoot}/Application/SemantifoldBridge.swift`,
452
+ `${sourceRoot}/Application/SemantifoldOutputView.swift`
453
+ ],
454
+ assets: [resourceRoot, ...prepared.assets.map(({ path }) => path)],
455
+ infoPlist: "Configuration/Info.plist",
456
+ unitTest: `Tests/${product}Tests.swift`,
457
+ uiTest: `UITests/${product}UITests.swift`,
458
+ xcconfig: "Configuration/Base.xcconfig"
459
+ };
460
+ }
461
+ /**
462
+ * Derives collision-checked uppercase 24-hex Xcode object IDs from normalized identities.
463
+ * @param {readonly string[]} identities - Complete ordered object identities.
464
+ * @param {(identity: string) => string} [digest] - Test-only digest seam; production uses built-in SHA-256.
465
+ * @returns {Map<string, string>} Object ID by full input identity.
466
+ */
467
+ export function allocateXcodeObjectIds(identities, digest = identity => createHash("sha256").update(identity).digest("hex")) {
468
+ const result = new Map();
469
+ const fullIdentities = new Map();
470
+ for (const identity of identities) {
471
+ if (typeof identity != "string" || identity.length == 0 || result.has(identity)) {
472
+ throw new SemantifoldDiagnostic({ code: "XCODE_ID_COLLISION", language: "ios",
473
+ message: "Xcode object identities must be unique non-empty strings." });
474
+ }
475
+ const normalized = identity.normalize("NFC");
476
+ const fullDigest = digest(normalized);
477
+ if (!/^[0-9a-fA-F]{64}$/u.test(fullDigest)) {
478
+ throw new SemantifoldDiagnostic({ code: "XCODE_ID_COLLISION", language: "ios",
479
+ message: `Xcode object identity '${identity}' did not produce a full SHA-256 digest.` });
480
+ }
481
+ const objectId = fullDigest.slice(0, 24).toUpperCase();
482
+ const previous = fullIdentities.get(objectId);
483
+ if (previous !== undefined && previous != normalized) {
484
+ throw new SemantifoldDiagnostic({ code: "XCODE_ID_COLLISION", language: "ios",
485
+ message: `Xcode object identities '${previous}' and '${normalized}' collide at '${objectId}'.` });
486
+ }
487
+ fullIdentities.set(objectId, normalized);
488
+ result.set(identity, objectId);
489
+ }
490
+ return result;
491
+ }
492
+ /**
493
+ * Renders the smallest deterministic Xcode application/unit/UI-test project model.
494
+ * Platform execution remains deferred until the repository has a qualified Apple lane.
495
+ * @param {ReturnType<typeof preflightIosApplication>} prepared - Prepared application.
496
+ * @param {ReturnType<typeof applicationArtifactPaths>} paths - Complete owned paths.
497
+ * @returns {RenderedConfigurationText} Canonical LF project file and causal configuration spans.
498
+ */
499
+ function renderPbxProject(prepared, paths) {
500
+ const configuration = prepared.configuration;
501
+ const product = configuration.productName;
502
+ const resourceRoot = configuration.resourceRoot;
503
+ const sourceRoot = configuration.sourceRoot;
504
+ const identities = [
505
+ "project", "group:main", "group:sources", "group:generated", "group:application", "group:configuration",
506
+ "group:tests", "group:uitests", "group:products", "target:app", "target:tests", "target:uitests",
507
+ "phase:app:sources", "phase:app:resources", "phase:app:frameworks", "phase:tests:sources", "phase:tests:resources",
508
+ "phase:tests:frameworks", "phase:uitests:sources", "phase:uitests:resources", "phase:uitests:frameworks",
509
+ "product:app", "product:tests", "product:uitests", "proxy:tests:app", "proxy:uitests:app",
510
+ "dependency:tests:app", "dependency:uitests:app",
511
+ "config-list:project", "config-list:app", "config-list:tests", "config-list:uitests",
512
+ "config:project:debug", "config:project:release", "config:app:debug", "config:app:release",
513
+ "config:tests:debug", "config:tests:release", "config:uitests:debug", "config:uitests:release",
514
+ `file:${paths.xcconfig}`, `file:${paths.infoPlist}`, `file:${resourceRoot}`,
515
+ `file:${paths.unitTest}`, `file:${paths.uiTest}`,
516
+ ...paths.appSources.flatMap(path => [`file:${path}`, `build:app:${path}`]),
517
+ `build:app:${resourceRoot}`, `build:tests:${paths.unitTest}`, `build:uitests:${paths.uiTest}`
518
+ ];
519
+ const ids = allocateXcodeObjectIds(identities);
520
+ /**
521
+ * Looks up one planned Xcode identity.
522
+ * @param {string} identity - Planned identity.
523
+ * @returns {string} Allocated object ID.
524
+ */
525
+ const id = identity => {
526
+ const value = ids.get(identity);
527
+ if (!value)
528
+ throw new TypeError(`Missing planned Xcode identity '${identity}'.`);
529
+ return value;
530
+ };
531
+ /** @type {Map<string, {identity: string, body: ConfigurationLine[]}[]>} */
532
+ const sections = new Map();
533
+ /**
534
+ * Adds an object to one PBX section.
535
+ * @param {string} section - PBX section.
536
+ * @param {string} identity - Object identity.
537
+ * @param {ConfigurationLine[]} body - Object fields.
538
+ */
539
+ const add = (section, identity, body) => {
540
+ const entries = sections.get(section) ?? [];
541
+ entries.push({ body, identity });
542
+ sections.set(section, entries);
543
+ };
544
+ /**
545
+ * Renders PBX list values.
546
+ * @param {string[]} values - PBX list values.
547
+ * @returns {string} Rendered list body.
548
+ */
549
+ const list = values => values.map(value => `\t\t\t\t${value},`).join("\n");
550
+ /**
551
+ * Produces a stable sorted copy.
552
+ * @param {string[]} values - Values to sort.
553
+ * @returns {string[]} Stable sorted copy.
554
+ */
555
+ const sorted = values => [...values].sort((left, right) => left < right ? -1 : left > right ? 1 : 0);
556
+ for (const path of paths.appSources) {
557
+ add("PBXBuildFile", `build:app:${path}`, ["isa = PBXBuildFile;", `fileRef = ${id(`file:${path}`)};`]);
558
+ add("PBXFileReference", `file:${path}`, ["isa = PBXFileReference;", "lastKnownFileType = sourcecode.swift;",
559
+ ["path = ", ...pbxConfigurationPath(configuration, path), ";"], "sourceTree = SOURCE_ROOT;"]);
560
+ }
561
+ add("PBXBuildFile", `build:app:${resourceRoot}`, ["isa = PBXBuildFile;", `fileRef = ${id(`file:${resourceRoot}`)};`]);
562
+ add("PBXBuildFile", `build:tests:${paths.unitTest}`, ["isa = PBXBuildFile;", `fileRef = ${id(`file:${paths.unitTest}`)};`]);
563
+ add("PBXBuildFile", `build:uitests:${paths.uiTest}`, ["isa = PBXBuildFile;", `fileRef = ${id(`file:${paths.uiTest}`)};`]);
564
+ add("PBXContainerItemProxy", "proxy:tests:app", ["isa = PBXContainerItemProxy;", `containerPortal = ${id("project")};`,
565
+ "proxyType = 1;", `remoteGlobalIDString = ${id("target:app")};`,
566
+ ["remoteInfo = \"", configurationFragment("productName", product), "\";"]]);
567
+ add("PBXContainerItemProxy", "proxy:uitests:app", ["isa = PBXContainerItemProxy;", `containerPortal = ${id("project")};`,
568
+ "proxyType = 1;", `remoteGlobalIDString = ${id("target:app")};`,
569
+ ["remoteInfo = \"", configurationFragment("productName", product), "\";"]]);
570
+ add("PBXFileReference", `file:${paths.xcconfig}`, ["isa = PBXFileReference;", "lastKnownFileType = text.xcconfig;",
571
+ `path = ${pbxString(paths.xcconfig)};`, "sourceTree = SOURCE_ROOT;"]);
572
+ add("PBXFileReference", `file:${paths.infoPlist}`, ["isa = PBXFileReference;", "lastKnownFileType = text.plist.xml;",
573
+ `path = ${pbxString(paths.infoPlist)};`, "sourceTree = SOURCE_ROOT;"]);
574
+ add("PBXFileReference", `file:${resourceRoot}`, ["isa = PBXFileReference;", "lastKnownFileType = folder.assetcatalog;",
575
+ ["path = ", configurationFragment("resourceRoot", resourceRoot), ";"], "sourceTree = SOURCE_ROOT;"]);
576
+ add("PBXFileReference", `file:${paths.unitTest}`, ["isa = PBXFileReference;", "lastKnownFileType = sourcecode.swift;",
577
+ ["path = ", ...pbxConfigurationPath(configuration, paths.unitTest), ";"], "sourceTree = SOURCE_ROOT;"]);
578
+ add("PBXFileReference", `file:${paths.uiTest}`, ["isa = PBXFileReference;", "lastKnownFileType = sourcecode.swift;",
579
+ ["path = ", ...pbxConfigurationPath(configuration, paths.uiTest), ";"], "sourceTree = SOURCE_ROOT;"]);
580
+ add("PBXFileReference", "product:app", ["isa = PBXFileReference;", "explicitFileType = wrapper.application;", "includeInIndex = 0;",
581
+ ["path = \"", configurationFragment("productName", product), ".app\";"], "sourceTree = BUILT_PRODUCTS_DIR;"]);
582
+ add("PBXFileReference", "product:tests", ["isa = PBXFileReference;", "explicitFileType = wrapper.cfbundle;", "includeInIndex = 0;",
583
+ ["path = \"", configurationFragment("productName", product), "Tests.xctest\";"], "sourceTree = BUILT_PRODUCTS_DIR;"]);
584
+ add("PBXFileReference", "product:uitests", ["isa = PBXFileReference;", "explicitFileType = wrapper.cfbundle;", "includeInIndex = 0;",
585
+ ["path = \"", configurationFragment("productName", product), "UITests.xctest\";"], "sourceTree = BUILT_PRODUCTS_DIR;"]);
586
+ const generatedRefs = sorted(paths.appSources.filter(path => path.startsWith(`${sourceRoot}/Generated/`))).map(path => id(`file:${path}`));
587
+ const applicationRefs = sorted(paths.appSources.filter(path => path.startsWith(`${sourceRoot}/Application/`))).map(path => id(`file:${path}`));
588
+ add("PBXGroup", "group:main", ["isa = PBXGroup;", `children = (\n${list([
589
+ id("group:configuration"), id("group:sources"), id(`file:${resourceRoot}`), id("group:tests"), id("group:uitests"),
590
+ id("group:products")
591
+ ])}\n\t\t\t);`, "sourceTree = \"<group>\";"]);
592
+ add("PBXGroup", "group:sources", ["isa = PBXGroup;", `children = (\n${list([id("group:application"), id("group:generated")])}\n\t\t\t);`,
593
+ ["name = ", configurationFragment("sourceRoot", sourceRoot), ";"], "sourceTree = \"<group>\";"]);
594
+ add("PBXGroup", "group:generated", ["isa = PBXGroup;", `children = (\n${list(generatedRefs)}\n\t\t\t);`,
595
+ "name = Generated;", "sourceTree = \"<group>\";"]);
596
+ add("PBXGroup", "group:application", ["isa = PBXGroup;", `children = (\n${list(applicationRefs)}\n\t\t\t);`,
597
+ "name = Application;", "sourceTree = \"<group>\";"]);
598
+ add("PBXGroup", "group:configuration", ["isa = PBXGroup;", `children = (\n${list([id(`file:${paths.xcconfig}`), id(`file:${paths.infoPlist}`)])}\n\t\t\t);`,
599
+ "name = Configuration;", "sourceTree = \"<group>\";"]);
600
+ add("PBXGroup", "group:tests", ["isa = PBXGroup;", `children = (\n${list([id(`file:${paths.unitTest}`)])}\n\t\t\t);`,
601
+ "name = Tests;", "sourceTree = \"<group>\";"]);
602
+ add("PBXGroup", "group:uitests", ["isa = PBXGroup;", `children = (\n${list([id(`file:${paths.uiTest}`)])}\n\t\t\t);`,
603
+ "name = UITests;", "sourceTree = \"<group>\";"]);
604
+ add("PBXGroup", "group:products", ["isa = PBXGroup;", `children = (\n${list([id("product:app"), id("product:tests"), id("product:uitests")])}\n\t\t\t);`,
605
+ "name = Products;", "sourceTree = \"<group>\";"]);
606
+ addNativeTarget(add, id, configuration, "target:app", "", "com.apple.product-type.application", "product:app", "config-list:app", ["phase:app:sources", "phase:app:frameworks", "phase:app:resources"], []);
607
+ addNativeTarget(add, id, configuration, "target:tests", "Tests", "com.apple.product-type.bundle.unit-test", "product:tests", "config-list:tests", ["phase:tests:sources", "phase:tests:frameworks", "phase:tests:resources"], ["dependency:tests:app"]);
608
+ addNativeTarget(add, id, configuration, "target:uitests", "UITests", "com.apple.product-type.bundle.ui-testing", "product:uitests", "config-list:uitests", ["phase:uitests:sources", "phase:uitests:frameworks", "phase:uitests:resources"], ["dependency:uitests:app"]);
609
+ add("PBXProject", "project", ["isa = PBXProject;", "attributes = { BuildIndependentTargetsInParallel = YES; };",
610
+ `buildConfigurationList = ${id("config-list:project")};`, "developmentRegion = en;", "hasScannedForEncodings = 0;",
611
+ "knownRegions = ( en, Base, );", `mainGroup = ${id("group:main")};`, `productRefGroup = ${id("group:products")};`,
612
+ "projectDirPath = \"\";", "projectRoot = \"\";",
613
+ `targets = (\n${list([id("target:app"), id("target:tests"), id("target:uitests")])}\n\t\t\t);`]);
614
+ addBuildPhase(add, id, "PBXFrameworksBuildPhase", "phase:app:frameworks", []);
615
+ addBuildPhase(add, id, "PBXResourcesBuildPhase", "phase:app:resources", [`build:app:${resourceRoot}`]);
616
+ addBuildPhase(add, id, "PBXSourcesBuildPhase", "phase:app:sources", sorted(paths.appSources).map(path => `build:app:${path}`));
617
+ for (const target of ["tests", "uitests"]) {
618
+ addBuildPhase(add, id, "PBXFrameworksBuildPhase", `phase:${target}:frameworks`, []);
619
+ addBuildPhase(add, id, "PBXResourcesBuildPhase", `phase:${target}:resources`, []);
620
+ }
621
+ addBuildPhase(add, id, "PBXSourcesBuildPhase", "phase:tests:sources", [`build:tests:${paths.unitTest}`]);
622
+ addBuildPhase(add, id, "PBXSourcesBuildPhase", "phase:uitests:sources", [`build:uitests:${paths.uiTest}`]);
623
+ add("PBXTargetDependency", "dependency:tests:app", ["isa = PBXTargetDependency;", `target = ${id("target:app")};`,
624
+ `targetProxy = ${id("proxy:tests:app")};`]);
625
+ add("PBXTargetDependency", "dependency:uitests:app", ["isa = PBXTargetDependency;", `target = ${id("target:app")};`,
626
+ `targetProxy = ${id("proxy:uitests:app")};`]);
627
+ for (const owner of ["project", "app", "tests", "uitests"]) {
628
+ for (const variant of ["debug", "release"]) {
629
+ const settings = buildSettings(owner, variant, configuration, paths);
630
+ add("XCBuildConfiguration", `config:${owner}:${variant}`, ["isa = XCBuildConfiguration;",
631
+ `baseConfigurationReference = ${id(`file:${paths.xcconfig}`)};`, ["buildSettings = {\n", ...settings, "\n\t\t\t};"],
632
+ `name = ${variant == "debug" ? "Debug" : "Release"};`]);
633
+ }
634
+ add("XCConfigurationList", `config-list:${owner}`, ["isa = XCConfigurationList;",
635
+ `buildConfigurations = (\n${list([id(`config:${owner}:debug`), id(`config:${owner}:release`)])}\n\t\t\t);`,
636
+ "defaultConfigurationIsVisible = 0;", "defaultConfigurationName = Release;"]);
637
+ }
638
+ const order = ["PBXBuildFile", "PBXContainerItemProxy", "PBXFileReference", "PBXFrameworksBuildPhase", "PBXGroup",
639
+ "PBXNativeTarget", "PBXProject", "PBXResourcesBuildPhase", "PBXSourcesBuildPhase", "PBXTargetDependency",
640
+ "XCBuildConfiguration", "XCConfigurationList"];
641
+ const writer = new ConfigurationTextWriter();
642
+ writer.append("// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {};\n\tobjectVersion = 56;\n\tobjects = {\n");
643
+ for (const section of order) {
644
+ const entries = (sections.get(section) ?? []).sort((left, right) => left.identity < right.identity ? -1 : 1);
645
+ writer.append(`\n/* Begin ${section} section */\n`);
646
+ for (const entry of entries) {
647
+ writer.append(`\t\t${id(entry.identity)} = {\n`);
648
+ for (const line of entry.body) {
649
+ writer.append("\t\t\t");
650
+ writer.append(line);
651
+ writer.append("\n");
652
+ }
653
+ writer.append("\t\t};\n");
654
+ }
655
+ writer.append(`/* End ${section} section */\n`);
656
+ }
657
+ writer.append(`\t};\n\trootObject = ${id("project")};\n}\n`);
658
+ return writer.finish();
659
+ }
660
+ /**
661
+ * Adds one native target object to the project model.
662
+ * @param {(section: string, identity: string, body: ConfigurationLine[]) => void} add - Object sink.
663
+ * @param {(identity: string) => string} id - ID lookup.
664
+ * @param {import("../semantic/types.js").IosApplicationConfiguration} configuration - Application configuration.
665
+ * @param {string} identity - Target identity.
666
+ * @param {string} nameSuffix - Target suffix after the product name.
667
+ * @param {string} productType - Product type.
668
+ * @param {string} productReference - Product reference identity.
669
+ * @param {string} configurationList - Configuration list identity.
670
+ * @param {string[]} phases - Phase identities.
671
+ * @param {string[]} dependencies - Dependency identities.
672
+ */
673
+ function addNativeTarget(add, id, configuration, identity, nameSuffix, productType, productReference, configurationList, phases, dependencies) {
674
+ /**
675
+ * Renders target identity values.
676
+ * @param {string[]} values - Target identity values.
677
+ * @returns {string} Rendered target list.
678
+ */
679
+ const lines = values => values.map(value => `\t\t\t\t${id(value)},`).join("\n");
680
+ const name = ["\"", configurationFragment("productName", configuration.productName), `${nameSuffix}"`];
681
+ add("PBXNativeTarget", identity, ["isa = PBXNativeTarget;", `buildConfigurationList = ${id(configurationList)};`,
682
+ `buildPhases = (\n${lines(phases)}\n\t\t\t);`, "buildRules = ();", `dependencies = (\n${lines(dependencies)}\n\t\t\t);`,
683
+ ["name = ", ...name, ";"], ["productName = ", ...name, ";"], `productReference = ${id(productReference)};`,
684
+ `productType = ${pbxString(productType)};`]);
685
+ }
686
+ /**
687
+ * Adds one build phase to the project model.
688
+ * @param {(section: string, identity: string, body: ConfigurationLine[]) => void} add - Object sink.
689
+ * @param {(identity: string) => string} id - ID lookup.
690
+ * @param {string} section - Phase ISA.
691
+ * @param {string} identity - Phase identity.
692
+ * @param {string[]} files - Build-file identities.
693
+ */
694
+ function addBuildPhase(add, id, section, identity, files) {
695
+ const lines = files.map(file => `\t\t\t\t${id(file)},`).join("\n");
696
+ add(section, identity, [`isa = ${section};`, "buildActionMask = 2147483647;", `files = (\n${lines}\n\t\t\t);`,
697
+ "runOnlyForDeploymentPostprocessing = 0;"]);
698
+ }
699
+ /**
700
+ * Renders sorted PBX build settings for one owner and variant.
701
+ * @param {string} owner - Configuration owner.
702
+ * @param {string} variant - Debug or release.
703
+ * @param {import("../semantic/types.js").IosApplicationConfiguration} configuration - Application configuration.
704
+ * @param {ReturnType<typeof applicationArtifactPaths>} paths - Planned paths.
705
+ * @returns {ConfigurationTextPart[]} Sorted PBX build settings.
706
+ */
707
+ function buildSettings(owner, variant, configuration, paths) {
708
+ /** @type {Record<string, ConfigurationTextPart | ConfigurationTextPart[]>} */
709
+ const values = owner == "project" ? {
710
+ CODE_SIGNING_ALLOWED: "NO",
711
+ CODE_SIGNING_REQUIRED: "NO"
712
+ } : owner == "app" ? {
713
+ GENERATE_INFOPLIST_FILE: "NO",
714
+ INFOPLIST_FILE: pbxString(paths.infoPlist),
715
+ IPHONEOS_DEPLOYMENT_TARGET: configurationFragment("deploymentTarget", configuration.deploymentTarget),
716
+ PRODUCT_BUNDLE_IDENTIFIER: configurationFragment("bundleIdentifier", configuration.bundleIdentifier),
717
+ PRODUCT_MODULE_NAME: configurationFragment("moduleName", configuration.moduleName),
718
+ PRODUCT_NAME: configurationFragment("productName", configuration.productName),
719
+ SDKROOT: "iphoneos",
720
+ SUPPORTED_PLATFORMS: pbxString("iphoneos iphonesimulator"),
721
+ TARGETED_DEVICE_FAMILY: "1"
722
+ } : owner == "tests" ? {
723
+ BUNDLE_LOADER: pbxString("$(TEST_HOST)"),
724
+ PRODUCT_BUNDLE_IDENTIFIER: [configurationFragment("bundleIdentifier", configuration.bundleIdentifier), ".tests"],
725
+ PRODUCT_MODULE_NAME: [configurationFragment("moduleName", configuration.moduleName), "Tests"],
726
+ PRODUCT_NAME: "$(TARGET_NAME)",
727
+ TEST_HOST: ["\"$(BUILT_PRODUCTS_DIR)/", configurationFragment("productName", configuration.productName),
728
+ ".app/", configurationFragment("productName", configuration.productName), "\""]
729
+ } : {
730
+ PRODUCT_BUNDLE_IDENTIFIER: [configurationFragment("bundleIdentifier", configuration.bundleIdentifier), ".uitests"],
731
+ PRODUCT_MODULE_NAME: [configurationFragment("moduleName", configuration.moduleName), "UITests"],
732
+ PRODUCT_NAME: "$(TARGET_NAME)",
733
+ TEST_TARGET_NAME: configurationFragment("productName", configuration.productName)
734
+ };
735
+ if (variant == "release")
736
+ values.SWIFT_OPTIMIZATION_LEVEL = pbxString("-O");
737
+ /** @type {ConfigurationTextPart[]} */
738
+ const output = [];
739
+ for (const [index, key] of Object.keys(values).sort().entries()) {
740
+ const value = values[key];
741
+ if (index > 0)
742
+ output.push("\n");
743
+ output.push(`\t\t\t\t${key} = `);
744
+ output.push(...(Array.isArray(value) ? value : [value]));
745
+ output.push(";");
746
+ }
747
+ return output;
748
+ }
749
+ /**
750
+ * Quotes one PBX scalar.
751
+ * @param {string} value - PBX scalar.
752
+ * @returns {string} Safely quoted PBX scalar.
753
+ */
754
+ function pbxString(value) {
755
+ return JSON.stringify(value);
756
+ }
757
+ /**
758
+ * Renders a quoted PBX path while retaining causality for its configured component.
759
+ * @param {import("../semantic/types.js").IosApplicationConfiguration} configuration - Application configuration.
760
+ * @param {string} path - Planned artifact path.
761
+ * @returns {ConfigurationTextPart[]} Quoted PBX path fragments.
762
+ */
763
+ function pbxConfigurationPath(configuration, path) {
764
+ if (path.startsWith(`${configuration.sourceRoot}/`)) {
765
+ return ["\"", configurationFragment("sourceRoot", configuration.sourceRoot), path.slice(configuration.sourceRoot.length), "\""];
766
+ }
767
+ if (path == configuration.resourceRoot) {
768
+ return ["\"", configurationFragment("resourceRoot", configuration.resourceRoot), "\""];
769
+ }
770
+ if (path == `Tests/${configuration.productName}Tests.swift`) {
771
+ return ["\"Tests/", configurationFragment("productName", configuration.productName), "Tests.swift\""];
772
+ }
773
+ if (path == `UITests/${configuration.productName}UITests.swift`) {
774
+ return ["\"UITests/", configurationFragment("productName", configuration.productName), "UITests.swift\""];
775
+ }
776
+ return [pbxString(path)];
777
+ }
778
+ /**
779
+ * Renders the shared scheme XML.
780
+ * @param {ReturnType<typeof preflightIosApplication>} prepared - Prepared application.
781
+ * @returns {RenderedConfigurationText} Shared scheme XML and causal configuration spans.
782
+ */
783
+ function renderSharedScheme(prepared) {
784
+ const product = prepared.configuration.productName;
785
+ const appId = allocateXcodeObjectIds(["target:app"]).get("target:app");
786
+ const testId = allocateXcodeObjectIds(["target:tests"]).get("target:tests");
787
+ const uiTestId = allocateXcodeObjectIds(["target:uitests"]).get("target:uitests");
788
+ /**
789
+ * Renders one scheme buildable reference.
790
+ * @param {string} nameSuffix - Blueprint suffix after product name.
791
+ * @param {string} buildableSuffix - Product filename suffix.
792
+ * @param {string | undefined} id - Object ID.
793
+ * @returns {ConfigurationTextPart[]} XML reference.
794
+ */
795
+ const reference = (nameSuffix, buildableSuffix, id) => [`<BuildableReference
796
+ BuildableIdentifier = "primary"
797
+ BlueprintIdentifier = "${id}"
798
+ BuildableName = "`, configurationFragment("productName", product), `${buildableSuffix}"
799
+ BlueprintName = "`, configurationFragment("productName", product), `${nameSuffix}"
800
+ ReferencedContainer = "container:`, configurationFragment("productName", product), `.xcodeproj">
801
+ </BuildableReference>`];
802
+ const writer = new ConfigurationTextWriter();
803
+ writer.append(`<?xml version="1.0" encoding="UTF-8"?>
804
+ <Scheme version="1.7">
805
+ <BuildAction parallelizeBuildables="YES" buildImplicitDependencies="YES">
806
+ <BuildActionEntries>
807
+ <BuildActionEntry buildForTesting="YES" buildForRunning="YES" buildForProfiling="YES" buildForArchiving="YES" buildForAnalyzing="YES">
808
+ `);
809
+ writer.append(reference("", ".app", appId));
810
+ writer.append(`
811
+ </BuildActionEntry>
812
+ </BuildActionEntries>
813
+ </BuildAction>
814
+ <TestAction buildConfiguration="Debug" selectedDebuggerIdentifier="Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier="Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv="YES">
815
+ <Testables>
816
+ <TestableReference skipped="NO">
817
+ `);
818
+ writer.append(reference("Tests", "Tests.xctest", testId));
819
+ writer.append(`
820
+ </TestableReference>
821
+ <TestableReference skipped="NO">
822
+ `);
823
+ writer.append(reference("UITests", "UITests.xctest", uiTestId));
824
+ writer.append(`
825
+ </TestableReference>
826
+ </Testables>
827
+ </TestAction>
828
+ <LaunchAction buildConfiguration="Debug" selectedDebuggerIdentifier="Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier="Xcode.DebuggerFoundation.Launcher.LLDB" launchStyle="0" useCustomWorkingDirectory="NO" ignoresPersistentStateOnLaunch="NO" debugDocumentVersioning="YES" debugServiceExtension="internal" allowLocationSimulation="YES">
829
+ <BuildableProductRunnable runnableDebuggingMode="0">
830
+ `);
831
+ writer.append(reference("", ".app", appId));
832
+ writer.append(`
833
+ </BuildableProductRunnable>
834
+ </LaunchAction>
835
+ <ProfileAction buildConfiguration="Release" shouldUseLaunchSchemeArgsEnv="YES" savedToolIdentifier="" useCustomWorkingDirectory="NO" debugDocumentVersioning="YES">
836
+ <BuildableProductRunnable runnableDebuggingMode="0">
837
+ `);
838
+ writer.append(reference("", ".app", appId));
839
+ writer.append(`
840
+ </BuildableProductRunnable>
841
+ </ProfileAction>
842
+ <AnalyzeAction buildConfiguration="Debug"/>
843
+ <ArchiveAction buildConfiguration="Release" revealArchiveInOrganizer="YES"/>
844
+ </Scheme>
845
+ `);
846
+ return writer.finish();
847
+ }
848
+ /**
849
+ * Renders the closed unsigned base configuration.
850
+ * @param {import("../semantic/types.js").IosApplicationConfiguration} configuration - Application configuration.
851
+ * @returns {RenderedConfigurationText} Base xcconfig and causal configuration spans.
852
+ */
853
+ function renderBaseConfiguration(configuration) {
854
+ const writer = new ConfigurationTextWriter();
855
+ writer.append(`CODE_SIGNING_ALLOWED = NO
856
+ CODE_SIGNING_REQUIRED = NO
857
+ GENERATE_INFOPLIST_FILE = NO
858
+ IPHONEOS_DEPLOYMENT_TARGET = `);
859
+ writer.append(configurationFragment("deploymentTarget", configuration.deploymentTarget));
860
+ writer.append("\nPRODUCT_BUNDLE_IDENTIFIER = ");
861
+ writer.append(configurationFragment("bundleIdentifier", configuration.bundleIdentifier));
862
+ writer.append("\nPRODUCT_MODULE_NAME = ");
863
+ writer.append(configurationFragment("moduleName", configuration.moduleName));
864
+ writer.append("\nPRODUCT_NAME = ");
865
+ writer.append(configurationFragment("productName", configuration.productName));
866
+ writer.append(`
867
+ SDKROOT = iphoneos
868
+ SUPPORTED_PLATFORMS = iphoneos iphonesimulator
869
+ TARGETED_DEVICE_FAMILY = 1
870
+ `);
871
+ return writer.finish();
872
+ }
873
+ /**
874
+ * Renders the allowlisted application property list.
875
+ * @param {import("../semantic/types.js").IosApplicationConfiguration} configuration - Application configuration.
876
+ * @returns {RenderedConfigurationText} Property-list XML and causal configuration spans.
877
+ */
878
+ function renderInfoPlist(configuration) {
879
+ const writer = new ConfigurationTextWriter();
880
+ writer.append(`<?xml version="1.0" encoding="UTF-8"?>
881
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
882
+ <plist version="1.0">
883
+ <dict>
884
+ <key>CFBundleDisplayName</key>
885
+ <string>`);
886
+ writer.append(configurationFragment("displayName", xmlEscape(configuration.displayName)));
887
+ writer.append(`</string>
888
+ <key>CFBundleExecutable</key>
889
+ <string>$(EXECUTABLE_NAME)</string>
890
+ <key>CFBundleIdentifier</key>
891
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
892
+ <key>CFBundleInfoDictionaryVersion</key>
893
+ <string>6.0</string>
894
+ <key>CFBundleName</key>
895
+ <string>$(PRODUCT_NAME)</string>
896
+ <key>CFBundlePackageType</key>
897
+ <string>APPL</string>
898
+ <key>CFBundleShortVersionString</key>
899
+ <string>1.0</string>
900
+ <key>CFBundleVersion</key>
901
+ <string>1</string>
902
+ <key>LSRequiresIPhoneOS</key>
903
+ <true/>
904
+ <key>UILaunchScreen</key>
905
+ <dict/>
906
+ </dict>
907
+ </plist>
908
+ `);
909
+ return writer.finish();
910
+ }
911
+ /**
912
+ * Renders pure-logic XCTest source.
913
+ * @param {import("../semantic/types.js").IosApplicationConfiguration} configuration - Application configuration.
914
+ * @returns {RenderedConfigurationText} XCTest source and causal configuration spans.
915
+ */
916
+ function renderUnitTests(configuration) {
917
+ const writer = new ConfigurationTextWriter();
918
+ writer.append("import XCTest\n@testable import ");
919
+ writer.append(configurationFragment("moduleName", configuration.moduleName));
920
+ writer.append("\n\nfinal class ");
921
+ writer.append(configurationFragment("productName", configuration.productName));
922
+ writer.append(`Tests: XCTestCase {
923
+ func testSemanticOutputIsDeterministic() {
924
+ XCTAssertEqual(SemantifoldBridge.run(), SemantifoldBridge.run())
925
+ }
926
+
927
+ func testOutputSinkPreservesScalarLines() {
928
+ let output = SemantifoldOutputSink()
929
+ output.write(Int64(7))
930
+ output.write(true)
931
+ output.write("é😀")
932
+ XCTAssertEqual(output.lines, ["7", "true", "é😀"])
933
+ }
934
+ }
935
+ `);
936
+ return writer.finish();
937
+ }
938
+ /**
939
+ * Renders the accessibility-route XCUI source.
940
+ * @param {import("../semantic/types.js").IosApplicationConfiguration} configuration - Application configuration.
941
+ * @returns {RenderedConfigurationText} XCUI source and causal configuration spans.
942
+ */
943
+ function renderUiTests(configuration) {
944
+ const writer = new ConfigurationTextWriter();
945
+ writer.append("import XCTest\n\nfinal class ");
946
+ writer.append(configurationFragment("productName", configuration.productName));
947
+ writer.append(`UITests: XCTestCase {
948
+ func testOutputViewIsAccessible() {
949
+ let application = XCUIApplication()
950
+ application.launch()
951
+ XCTAssertTrue(application.staticTexts["semantifold-output"].waitForExistence(timeout: 5))
952
+ }
953
+ }
954
+ `);
955
+ return writer.finish();
956
+ }
957
+ /**
958
+ * Escapes XML text and attribute content.
959
+ * @param {string} value - XML text or attribute value.
960
+ * @returns {string} Escaped value.
961
+ */
962
+ function xmlEscape(value) {
963
+ return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;")
964
+ .replaceAll("\"", "&quot;").replaceAll("'", "&apos;");
965
+ }
966
+ /**
967
+ * Creates one synthetic text artifact candidate.
968
+ * @param {string} path - Artifact path.
969
+ * @param {import("../semantic/types.js").GeneratedArtifactRole} role - Artifact role.
970
+ * @param {string} content - Exact LF content.
971
+ * @param {string} reason - Provenance reason.
972
+ * @returns {import("../semantic/types.js").GeneratedSetArtifact} Artifact candidate.
973
+ */
974
+ function syntheticText(path, role, content, reason) {
975
+ return {
976
+ content,
977
+ contentKind: "text",
978
+ mediaType: path.endsWith(".swift") ? "text/x-swift" : path.endsWith(".json") ? "application/json" :
979
+ path.endsWith(".plist") || path.endsWith(".xcscheme") ? "application/xml" : "text/plain",
980
+ ownership: "generated",
981
+ path,
982
+ provenance: { kind: "synthetic", reason, relatedOrigins: [] },
983
+ role
984
+ };
985
+ }
986
+ /**
987
+ * Creates a synthetic artifact and transfers its renderer-owned configuration spans to the manifest ledger.
988
+ * @param {string} path - Artifact path.
989
+ * @param {import("../semantic/types.js").GeneratedArtifactRole} role - Artifact role.
990
+ * @param {RenderedConfigurationText} rendered - Rendered content and causal spans.
991
+ * @param {ConfigurationArtifactSpan[]} spans - Application-wide causal span ledger.
992
+ * @param {string} reason - Provenance reason.
993
+ * @returns {import("../semantic/types.js").GeneratedSetArtifact} Artifact candidate.
994
+ */
995
+ function configuredSyntheticText(path, role, rendered, spans, reason) {
996
+ spans.push(...rendered.configurationSpans.map(span => ({ ...span, path })));
997
+ return syntheticText(path, role, rendered.content, reason);
998
+ }
999
+ /**
1000
+ * Serializes recursively sorted canonical JSON with an LF.
1001
+ * @param {unknown} value - JSON value.
1002
+ * @returns {string} Canonical JSON with LF.
1003
+ */
1004
+ function stringifyCanonicalJson(value) {
1005
+ return `${JSON.stringify(sortJson(value), null, 2)}\n`;
1006
+ }
1007
+ /**
1008
+ * Recursively sorts JSON object keys without reordering arrays.
1009
+ * @param {unknown} value - JSON value.
1010
+ * @returns {unknown} Recursively key-sorted JSON.
1011
+ */
1012
+ function sortJson(value) {
1013
+ if (Array.isArray(value))
1014
+ return value.map(sortJson);
1015
+ if (!isPlainObject(value))
1016
+ return value;
1017
+ return Object.fromEntries(Object.keys(value).sort().map(key => [key, sortJson(value[key])]));
1018
+ }
1019
+ /**
1020
+ * Validates and snapshots the strict baseline application configuration.
1021
+ * Identity and deployment fields intentionally have no defaults without Apple-lane evidence.
1022
+ * @param {unknown} candidate - Candidate configuration.
1023
+ * @returns {import("../semantic/types.js").IosApplicationConfiguration} Normalized configuration.
1024
+ */
1025
+ function normalizeConfiguration(candidate) {
1026
+ if (!isPlainObject(candidate) || Object.keys(candidate).some(key => !configurationFields.has(key))) {
1027
+ invalidConfiguration("iOS application configuration must be a closed plain object.");
1028
+ }
1029
+ const productName = candidate.productName;
1030
+ const moduleName = candidate.moduleName;
1031
+ const organizationPrefix = candidate.organizationPrefix;
1032
+ const bundleIdentifier = candidate.bundleIdentifier;
1033
+ const deploymentTarget = candidate.deploymentTarget;
1034
+ const displayName = candidate.displayName;
1035
+ if (typeof productName != "string" || !/^[A-Z][A-Za-z0-9]*$/u.test(productName)) {
1036
+ invalidConfiguration("Product name must be an ASCII upper-camel identifier.");
1037
+ }
1038
+ if (typeof moduleName != "string" || !/^[A-Z][A-Za-z0-9]*$/u.test(moduleName)) {
1039
+ invalidConfiguration("Module name must be an ASCII upper-camel identifier.");
1040
+ }
1041
+ if (typeof organizationPrefix != "string" || !isReverseDns(organizationPrefix, 2)) {
1042
+ invalidConfiguration("Organization prefix must be a lowercase reverse-DNS identity with at least two segments.");
1043
+ }
1044
+ if (typeof bundleIdentifier != "string" || !isReverseDns(bundleIdentifier, 3) ||
1045
+ !bundleIdentifier.startsWith(`${organizationPrefix}.`)) {
1046
+ invalidConfiguration("Bundle identifier must extend the exact organization prefix as lowercase reverse DNS.");
1047
+ }
1048
+ if (typeof deploymentTarget != "string" || !/^[1-9][0-9]*\.(?:0|[1-9][0-9]*)$/u.test(deploymentTarget)) {
1049
+ invalidConfiguration("Deployment target must be a caller-supplied canonical major.minor version.");
1050
+ }
1051
+ if (typeof displayName != "string" || displayName.length == 0 || displayName.trim() != displayName ||
1052
+ [...displayName].length > 64 || !hasOnlyUnicodeScalars(displayName) || /\p{Cc}/u.test(displayName)) {
1053
+ invalidConfiguration("Display name must be a non-empty single-line Unicode scalar string of at most 64 characters.");
1054
+ }
1055
+ const sourceRoot = candidate.sourceRoot ?? "Sources";
1056
+ const resourceRoot = candidate.resourceRoot ?? "Assets.xcassets";
1057
+ const lifecycle = candidate.lifecycle ?? "swiftui";
1058
+ if (sourceRoot != "Sources" || !isSafeArtifactPath(sourceRoot))
1059
+ invalidConfiguration("The supported source root is exactly 'Sources'.");
1060
+ if (resourceRoot != "Assets.xcassets" || !isSafeArtifactPath(resourceRoot)) {
1061
+ invalidConfiguration("The supported resource root is exactly 'Assets.xcassets'.");
1062
+ }
1063
+ if (lifecycle != "swiftui")
1064
+ invalidConfiguration("The supported application lifecycle is exactly 'swiftui'.");
1065
+ const infoPlist = candidate.infoPlist ?? {};
1066
+ if (!isPlainObject(infoPlist) || Object.keys(infoPlist).length > 0) {
1067
+ invalidConfiguration("The baseline caller Info.plist extension allowlist is empty.");
1068
+ }
1069
+ const permissions = emptyConfigurationSet(candidate.permissions, "permissions");
1070
+ const entitlements = emptyConfigurationSet(candidate.entitlements, "entitlements");
1071
+ const privacyDeclarations = emptyConfigurationSet(candidate.privacyDeclarations, "privacy declarations");
1072
+ const capabilities = emptyConfigurationSet(candidate.capabilities, "capabilities");
1073
+ return {
1074
+ bundleIdentifier,
1075
+ capabilities,
1076
+ deploymentTarget,
1077
+ displayName,
1078
+ entitlements,
1079
+ infoPlist: {},
1080
+ lifecycle: "swiftui",
1081
+ moduleName,
1082
+ organizationPrefix,
1083
+ permissions,
1084
+ privacyDeclarations,
1085
+ productName,
1086
+ resourceRoot: "Assets.xcassets",
1087
+ sourceRoot: "Sources"
1088
+ };
1089
+ }
1090
+ /**
1091
+ * Validates one optional closed empty configuration set.
1092
+ * @param {unknown} candidate - Optional closed set.
1093
+ * @param {string} label - Diagnostic label.
1094
+ * @returns {never[]} Empty snapshot.
1095
+ */
1096
+ function emptyConfigurationSet(candidate, label) {
1097
+ if (candidate === undefined)
1098
+ return [];
1099
+ if (!isDenseArray(candidate) || candidate.length != 0)
1100
+ invalidConfiguration(`The baseline ${label} set must be empty.`);
1101
+ return [];
1102
+ }
1103
+ /**
1104
+ * Tests one canonical lowercase reverse-DNS identity.
1105
+ * @param {string} value - Candidate identity.
1106
+ * @param {number} segments - Minimum segments.
1107
+ * @returns {boolean} Validity.
1108
+ */
1109
+ function isReverseDns(value, segments) {
1110
+ const parts = value.split(".");
1111
+ return parts.length >= segments && parts.every(part => /^[a-z][a-z0-9-]*$/u.test(part) && !part.endsWith("-"));
1112
+ }
1113
+ /**
1114
+ * Validates, hashes, snapshots, and canonically sorts caller assets.
1115
+ * @param {unknown} candidate - Candidate asset array.
1116
+ * @param {string} resourceRoot - Exact resource root.
1117
+ * @returns {import("../semantic/types.js").IosApplicationAssetInput[]} Normalized assets.
1118
+ */
1119
+ function normalizeAssets(candidate, resourceRoot) {
1120
+ if (candidate === undefined)
1121
+ return [];
1122
+ if (!isDenseArray(candidate))
1123
+ invalidAsset("Application assets must be a dense array.");
1124
+ /** @type {import("../semantic/types.js").IosApplicationAssetInput[]} */
1125
+ const assets = [];
1126
+ for (let index = 0; index < candidate.length; index += 1) {
1127
+ const asset = candidate[index];
1128
+ if (!isPlainObject(asset) || Object.keys(asset).some(key => !assetFields.has(key)) ||
1129
+ Object.keys(asset).length != assetFields.size)
1130
+ invalidAsset(`Asset ${index} must use the closed asset schema.`);
1131
+ const path = asset.path;
1132
+ const content = asset.content;
1133
+ const mediaType = asset.mediaType;
1134
+ const sha256 = asset.sha256;
1135
+ if (!isSafeArtifactPath(path) || !path.startsWith(`${resourceRoot}/`) || path == `${resourceRoot}/Contents.json`) {
1136
+ invalidAsset(`Asset ${index} requires a safe path below '${resourceRoot}'.`);
1137
+ }
1138
+ if (typeof content != "string" && !(content instanceof Uint8Array) ||
1139
+ typeof content == "string" && (content.length == 0 || !hasOnlyUnicodeScalars(content)) ||
1140
+ content instanceof Uint8Array && content.byteLength == 0)
1141
+ invalidAsset(`Asset '${path}' requires non-empty exact content.`);
1142
+ if (typeof mediaType != "string" || !mediaTypePattern.test(mediaType) || /[\r\n]/u.test(mediaType)) {
1143
+ invalidAsset(`Asset '${path}' requires an explicit valid media type.`);
1144
+ }
1145
+ const snapshot = typeof content == "string" ? content : new Uint8Array(content);
1146
+ const actualHash = createHash("sha256").update(snapshot).digest("hex");
1147
+ if (typeof sha256 != "string" || !/^[0-9a-f]{64}$/u.test(sha256) || sha256 != actualHash) {
1148
+ invalidAsset(`Asset '${path}' SHA-256 does not match its exact content.`);
1149
+ }
1150
+ assets.push({ content: snapshot, mediaType, path, sha256 });
1151
+ }
1152
+ assets.sort((left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0);
1153
+ return assets;
1154
+ }
1155
+ /**
1156
+ * Creates an exact text or binary asset artifact.
1157
+ * @param {import("../semantic/types.js").IosApplicationAssetInput} asset - Validated asset.
1158
+ * @returns {import("../semantic/types.js").GeneratedSetArtifact} Artifact candidate.
1159
+ */
1160
+ function assetArtifact(asset) {
1161
+ if (typeof asset.content == "string")
1162
+ return {
1163
+ content: asset.content,
1164
+ contentKind: "text",
1165
+ mediaType: asset.mediaType,
1166
+ ownership: "generated",
1167
+ path: asset.path,
1168
+ provenance: { kind: "synthetic", reason: `Exact caller-provided iOS asset (sha256:${asset.sha256}).`, relatedOrigins: [] },
1169
+ role: "resource"
1170
+ };
1171
+ const content = new Uint8Array(asset.content);
1172
+ return {
1173
+ content,
1174
+ contentKind: "binary",
1175
+ mediaType: asset.mediaType,
1176
+ ownership: "generated",
1177
+ path: asset.path,
1178
+ provenance: { kind: "bytes", mapping: createByteMapping({
1179
+ byteLength: content.byteLength,
1180
+ path: asset.path,
1181
+ ranges: [{
1182
+ generated: { end: content.byteLength, start: 0 },
1183
+ origin: { kind: "synthetic", reason: `Exact caller-provided iOS asset (sha256:${asset.sha256}).`, relatedOrigins: [] },
1184
+ role: "asset"
1185
+ }]
1186
+ }) },
1187
+ role: "resource"
1188
+ };
1189
+ }
1190
+ /**
1191
+ * Throws a configuration diagnostic.
1192
+ * @param {string} message - Failure detail.
1193
+ * @returns {never} Always throws.
1194
+ */
1195
+ function invalidConfiguration(message) {
1196
+ throw new SemantifoldDiagnostic({ code: "INVALID_APPLICATION_CONFIGURATION", language: "ios", message });
1197
+ }
1198
+ /**
1199
+ * Throws an asset diagnostic.
1200
+ * @param {string} message - Failure detail.
1201
+ * @returns {never} Always throws.
1202
+ */
1203
+ function invalidAsset(message) {
1204
+ throw new SemantifoldDiagnostic({ code: "INVALID_APPLICATION_ASSET", language: "ios", message });
1205
+ }
1206
+ /**
1207
+ * Throws an application-path diagnostic.
1208
+ * @param {string} message - Failure detail.
1209
+ * @returns {never} Always throws.
1210
+ */
1211
+ function invalidPath(message) {
1212
+ throw new SemantifoldDiagnostic({ code: "INVALID_APPLICATION_PATH", language: "ios", message });
1213
+ }
1214
+ /**
1215
+ * Emits one backend-namespaced semantic module.
1216
+ * @param {SourceWriter} writer - Source-aware generated Swift writer.
1217
+ * @param {import("../semantic/types.js").SemanticModule} module - Prepared semantic module.
1218
+ * @param {string} moduleId - Stable project module identity.
1219
+ * @param {boolean} entry - Whether this module owns the semantic entry.
1220
+ * @param {Map<string | undefined, {declaration: import("../semantic/types.js").FunctionDeclaration, moduleId: string}>} declarations - Resolved functions.
1221
+ */
1222
+ function emitSemanticModule(writer, module, moduleId, entry, declarations) {
1223
+ const namespace = `SemantifoldModule${moduleName(moduleId)}`;
1224
+ writer.synthetic(`enum ${namespace} {\n`, "iOS semantic module namespace", [module], [""]);
1225
+ module.functions.forEach((declaration, functionIndex) => {
1226
+ const path = `/functions/${functionIndex}`;
1227
+ writer.synthetic(" static ", "iOS namespaced function scaffold", [declaration], [path]);
1228
+ writer.mapped("func", { mappingKind: "anchor", node: declaration, path });
1229
+ writer.synthetic(" ", "declaration spacing", [declaration], [path]);
1230
+ writer.mapped(declaration.name, { mappingKind: "exact", node: declaration, path, role: "name" });
1231
+ writer.synthetic("(", "function parameter scaffold", [declaration], [path]);
1232
+ declaration.parameters.forEach((parameter, parameterIndex) => {
1233
+ const parameterPath = `${path}/parameters/${parameterIndex}`;
1234
+ if (parameterIndex)
1235
+ writer.synthetic(", ", "parameter separator", [parameter], [parameterPath]);
1236
+ writer.synthetic("_ ", "unlabeled Swift parameter scaffold", [parameter], [parameterPath]);
1237
+ writer.mapped(parameter.name, { mappingKind: "exact", node: parameter, path: parameterPath, role: "name" });
1238
+ writer.synthetic(": ", "parameter annotation scaffold", [parameter], [parameterPath]);
1239
+ writer.mapped(emitScalarType("swift", parameter.type), { mappingKind: "exact", node: parameter.type,
1240
+ path: `${parameterPath}/type`, role: "type" });
1241
+ });
1242
+ writer.synthetic(", _ semantifold_output: SemantifoldOutputSink) -> ", "shared iOS output sink parameter", [declaration], [path]);
1243
+ writer.mapped(emitScalarType("swift", declaration.returnType), { mappingKind: "exact", node: declaration.returnType,
1244
+ path: `${path}/returnType`, role: "type" });
1245
+ writer.synthetic(" {\n", "Swift function body scaffold", [declaration], [path]);
1246
+ emitBlock(writer, declaration.body, " ", `${path}/body`, declarations);
1247
+ writer.synthetic(" }\n", "Swift function body scaffold", [declaration], [path]);
1248
+ });
1249
+ if (entry) {
1250
+ writer.synthetic(" static func semantifoldEntry() -> [String] {\n", "iOS semantic entry scaffold", [module.entryPoint], ["/entryPoint"]);
1251
+ writer.synthetic(" let semantifold_output = SemantifoldOutputSink()\n", "shared iOS output sink allocation", [module.entryPoint], ["/entryPoint"]);
1252
+ emitBlock(writer, module.entryPoint.body, " ", "/entryPoint/body", declarations);
1253
+ writer.synthetic(" return semantifold_output.lines\n", "iOS semantic output return", [module.entryPoint], ["/entryPoint"]);
1254
+ writer.synthetic(" }\n", "iOS semantic entry scaffold", [module.entryPoint], ["/entryPoint"]);
1255
+ }
1256
+ writer.synthetic("}\n", "iOS semantic module namespace", [module], [""]);
1257
+ }
1258
+ /**
1259
+ * Emits a validated ordered semantic block.
1260
+ * @param {SourceWriter} writer - Source writer.
1261
+ * @param {import("../semantic/types.js").Block} block - Semantic block.
1262
+ * @param {string} indent - Current indentation.
1263
+ * @param {string} path - Block occurrence path.
1264
+ * @param {Map<string | undefined, {declaration: import("../semantic/types.js").FunctionDeclaration, moduleId: string}>} declarations - Resolved functions.
1265
+ */
1266
+ function emitBlock(writer, block, indent, path, declarations) {
1267
+ block.statements.forEach((statement, index) => emitStatement(writer, statement, indent, `${path}/statements/${index}`, declarations));
1268
+ }
1269
+ /**
1270
+ * Emits one Swift statement through the shared capture sink.
1271
+ * @param {SourceWriter} writer - Source writer.
1272
+ * @param {import("../semantic/types.js").Statement} statement - Validated statement.
1273
+ * @param {string} indent - Current indentation.
1274
+ * @param {string} path - Statement occurrence path.
1275
+ * @param {Map<string | undefined, {declaration: import("../semantic/types.js").FunctionDeclaration, moduleId: string}>} declarations - Resolved functions.
1276
+ */
1277
+ function emitStatement(writer, statement, indent, path, declarations) {
1278
+ writer.synthetic(indent, "indentation", [statement], [path]);
1279
+ if (statement.kind == "LocalDeclaration") {
1280
+ writer.mapped(statement.mutable ? "var" : "let", { mappingKind: "anchor", node: statement, path });
1281
+ writer.synthetic(" ", "declaration spacing", [statement], [path]);
1282
+ writer.mapped(statement.name, { mappingKind: "exact", node: statement, path, role: "name" });
1283
+ writer.synthetic(": ", "local annotation scaffold", [statement], [path]);
1284
+ writer.mapped(emitScalarType("swift", statement.type), { mappingKind: "exact", node: statement.type,
1285
+ path: `${path}/type`, role: "type" });
1286
+ writer.synthetic(" = ", "assignment spacing", [statement], [path]);
1287
+ emitExpression(writer, statement.initializer, `${path}/initializer`, declarations);
1288
+ writer.synthetic("\n", "line break", [statement], [path]);
1289
+ if (statement.mutable)
1290
+ writer.synthetic(`${indent}semantifold_keep_mutable(&${statement.name})\n`, "Swift mutable-local warning marker", [statement], [path]);
1291
+ return;
1292
+ }
1293
+ if (statement.kind == "AssignmentStatement") {
1294
+ writer.mapped(statement.target.name, { mappingKind: "exact", node: statement.target, path: `${path}/target`, role: "name" });
1295
+ writer.synthetic(" = ", "assignment spacing", [statement], [path]);
1296
+ emitExpression(writer, statement.expression, `${path}/expression`, declarations);
1297
+ writer.synthetic("\n", "line break", [statement], [path]);
1298
+ return;
1299
+ }
1300
+ if (statement.kind == "ReturnStatement") {
1301
+ if (!statement.expression)
1302
+ throw new TypeError("iOS Swift bare return reached emission.");
1303
+ writer.mapped("return", { mappingKind: "anchor", node: statement, path });
1304
+ writer.synthetic(" ", "return spacing", [statement], [path]);
1305
+ emitExpression(writer, statement.expression, `${path}/expression`, declarations);
1306
+ writer.synthetic("\n", "line break", [statement], [path]);
1307
+ return;
1308
+ }
1309
+ if (statement.kind == "PrintStatement") {
1310
+ writer.synthetic("semantifold_output.write(", "iOS output capture", [statement], [path]);
1311
+ emitExpression(writer, statement.expression, `${path}/expression`, declarations);
1312
+ writer.synthetic(")\n", "iOS output capture", [statement], [path]);
1313
+ return;
1314
+ }
1315
+ if (statement.kind != "IfStatement")
1316
+ throw new TypeError("Unsupported iOS Swift statement reached emission.");
1317
+ writer.mapped("if", { mappingKind: "anchor", node: statement, path });
1318
+ writer.synthetic(" ", "conditional spacing", [statement], [path]);
1319
+ emitExpression(writer, statement.condition, `${path}/condition`, declarations);
1320
+ writer.synthetic(" {\n", "Swift conditional scaffold", [statement.consequent], [`${path}/consequent`]);
1321
+ emitBlock(writer, statement.consequent, `${indent} `, `${path}/consequent`, declarations);
1322
+ writer.synthetic(`${indent}}`, "Swift conditional scaffold", [statement.consequent], [`${path}/consequent`]);
1323
+ if (statement.alternate) {
1324
+ writer.synthetic(" else {\n", "Swift alternate scaffold", [statement.alternate], [`${path}/alternate`]);
1325
+ emitBlock(writer, statement.alternate, `${indent} `, `${path}/alternate`, declarations);
1326
+ writer.synthetic(`${indent}}`, "Swift alternate scaffold", [statement.alternate], [`${path}/alternate`]);
1327
+ }
1328
+ writer.synthetic("\n", "line break", [statement], [path]);
1329
+ }
1330
+ /**
1331
+ * Emits one validated Tasks 001-004 expression and threads the shared sink through calls.
1332
+ * @param {SourceWriter} writer - Source writer.
1333
+ * @param {import("../semantic/types.js").Expression} expression - Semantic expression.
1334
+ * @param {string} path - Expression occurrence path.
1335
+ * @param {Map<string | undefined, {declaration: import("../semantic/types.js").FunctionDeclaration, moduleId: string}>} declarations - Resolved functions.
1336
+ */
1337
+ function emitExpression(writer, expression, path, declarations) {
1338
+ if (expression.kind == "IdentifierExpression") {
1339
+ writer.mapped(expression.name, { mappingKind: "exact", node: expression, path, role: "name" });
1340
+ return;
1341
+ }
1342
+ if (expression.kind == "IntegerLiteral") {
1343
+ writer.mapped(String(expression.value), { mappingKind: "exact", node: expression, path, role: "literal" });
1344
+ return;
1345
+ }
1346
+ if (expression.kind == "BooleanLiteral") {
1347
+ writer.mapped(expression.value ? "true" : "false", { mappingKind: "exact", node: expression, path, role: "literal" });
1348
+ return;
1349
+ }
1350
+ if (expression.kind == "StringLiteral") {
1351
+ writer.mapped(emitStringLiteral("swift", expression.value), { mappingKind: "exact", node: expression, path, role: "literal" });
1352
+ return;
1353
+ }
1354
+ if (expression.kind == "CallExpression") {
1355
+ const resolved = declarations.get(expression.resolution?.declarationId);
1356
+ if (!resolved)
1357
+ throw new TypeError(`Unknown validated iOS function '${expression.resolution?.declarationId}'.`);
1358
+ writer.mapped(`SemantifoldModule${moduleName(resolved.moduleId)}.${resolved.declaration.name}`, {
1359
+ mappingKind: "exact", name: expression.callee, node: expression, path, role: "callee"
1360
+ });
1361
+ writer.synthetic("(", "iOS semantic function call", [expression], [path]);
1362
+ expression.arguments.forEach((argument, index) => {
1363
+ if (index)
1364
+ writer.synthetic(", ", "argument separator", [expression], [path]);
1365
+ emitExpression(writer, argument, `${path}/arguments/${index}`, declarations);
1366
+ });
1367
+ writer.synthetic(", semantifold_output)", "shared iOS output sink argument", [expression], [path]);
1368
+ return;
1369
+ }
1370
+ if (expression.kind == "UnaryExpression") {
1371
+ writer.mapped("(", { mappingKind: "anchor", node: expression, path });
1372
+ writer.mapped(unaryOperations[expression.operation], { mappingKind: "exact", node: expression, path, role: "operator" });
1373
+ emitExpression(writer, expression.operand, `${path}/operand`, declarations);
1374
+ writer.mapped(")", { mappingKind: "anchor", node: expression, path });
1375
+ return;
1376
+ }
1377
+ if (expression.kind != "BinaryExpression")
1378
+ throw new TypeError("Unsupported iOS Swift expression reached emission.");
1379
+ if (expression.operation == "StringEqual" || expression.operation == "StringNotEqual") {
1380
+ writer.mapped(expression.operation == "StringEqual" ? "semantifold_string_equal" : "semantifold_string_not_equal", { mappingKind: "exact", node: expression, path, role: "operator" });
1381
+ writer.synthetic("(", "Swift scalar-equality helper call", [expression], [path]);
1382
+ emitExpression(writer, expression.left, `${path}/left`, declarations);
1383
+ writer.synthetic(", ", "Swift scalar-equality argument separator", [expression], [path]);
1384
+ emitExpression(writer, expression.right, `${path}/right`, declarations);
1385
+ writer.synthetic(")", "Swift scalar-equality helper call", [expression], [path]);
1386
+ return;
1387
+ }
1388
+ writer.mapped("(", { mappingKind: "anchor", node: expression, path });
1389
+ emitExpression(writer, expression.left, `${path}/left`, declarations);
1390
+ writer.synthetic(" ", "operator spacing", [expression], [path]);
1391
+ writer.mapped(binaryOperations[expression.operation], { mappingKind: "exact", node: expression, path, role: "operator" });
1392
+ writer.synthetic(" ", "operator spacing", [expression], [path]);
1393
+ emitExpression(writer, expression.right, `${path}/right`, declarations);
1394
+ writer.mapped(")", { mappingKind: "anchor", node: expression, path });
1395
+ }
1396
+ /**
1397
+ * Converts a validated logical module identity to its Swift namespace suffix.
1398
+ * @param {string} id - Logical module identity.
1399
+ * @returns {string} Deterministic Swift namespace suffix and filename.
1400
+ */
1401
+ function moduleName(id) {
1402
+ return id.split(/[._-]+/u).map(part => `${part[0].toUpperCase()}${part.slice(1)}`).join("");
1403
+ }
1404
+ /**
1405
+ * Clones and normalizes one provenance-bearing semantic module into a one-module project.
1406
+ * @param {import("../semantic/types.js").SemanticModule | undefined} candidate - Candidate module.
1407
+ * @returns {import("../semantic/types.js").SemanticProgram} Normalized program.
1408
+ */
1409
+ function normalizeSingleModule(candidate) {
1410
+ if (!isPlainObject(candidate))
1411
+ unsupportedCapability("ios", "missing or invalid module", undefined);
1412
+ const module = structuredClone(candidate);
1413
+ const provenanceSources = module.provenance?.sources;
1414
+ if (!Array.isArray(provenanceSources) || provenanceSources.length != 1 || provenanceSources[0].content === null ||
1415
+ provenanceSources[0].filename != module.location?.filename || typeof provenanceSources[0].language != "string") {
1416
+ unsupportedCapability("ios", "single-module source ownership", module.location);
1417
+ }
1418
+ rekeyModuleDeclarations(module, "main");
1419
+ const exports = [
1420
+ ...(module.records ?? []).map(declaration => applicationExport(declaration, "record")),
1421
+ ...(module.classes ?? []).map(declaration => applicationExport(declaration, "class")),
1422
+ ...(module.errors ?? []).map(declaration => applicationExport(declaration, "error")),
1423
+ ...module.functions.map(declaration => applicationExport(declaration, "function"))
1424
+ ];
1425
+ const programModule = /** @type {import("../semantic/types.js").SemanticProgramModule} */ ({
1426
+ ...module,
1427
+ exports,
1428
+ id: "main",
1429
+ imports: [],
1430
+ sourceFilename: provenanceSources[0].filename
1431
+ });
1432
+ return {
1433
+ entryModule: "main",
1434
+ kind: "Program",
1435
+ modules: [programModule],
1436
+ sources: structuredClone(provenanceSources)
1437
+ };
1438
+ }
1439
+ /**
1440
+ * Creates a normalized export for a single-module declaration without inventing a source range.
1441
+ * @param {{id?: string, location: import("../semantic/types.js").SourceLocation, name: string}} declaration - Exported declaration.
1442
+ * @param {import("../semantic/types.js").SemanticDeclarationKind} symbolKind - Declaration namespace.
1443
+ * @returns {import("../semantic/types.js").SemanticExport} Synthetic project edge anchored to its declaration.
1444
+ */
1445
+ function applicationExport(declaration, symbolKind) {
1446
+ return {
1447
+ declarationId: /** @type {string} */ (declaration.id),
1448
+ exportedName: declaration.name,
1449
+ kind: "Export",
1450
+ location: declaration.location,
1451
+ symbolKind
1452
+ };
1453
+ }
1454
+ /**
1455
+ * Prefixes declaration identities and typed references in a cloned single module.
1456
+ * @param {import("../semantic/types.js").SemanticModule} module - Cloned module.
1457
+ * @param {string} moduleId - Normalized module identity.
1458
+ * @returns {void}
1459
+ */
1460
+ function rekeyModuleDeclarations(module, moduleId) {
1461
+ const declarations = [...module.records ?? [], ...module.classes ?? [], ...module.errors ?? [], ...module.functions];
1462
+ const replacements = new Map(declarations
1463
+ .filter(declaration => typeof declaration.id == "string")
1464
+ .map(declaration => [declaration.id, `${moduleId}#${declaration.id}`]));
1465
+ for (const declaration of declarations) {
1466
+ if (typeof declaration.id == "string")
1467
+ declaration.id = replacements.get(declaration.id);
1468
+ }
1469
+ const seen = new Set();
1470
+ const identityFields = new Set(["classId", "declarationId", "field", "method", "parameterId"]);
1471
+ /**
1472
+ * Rewrites declaration identities in one cloned semantic subtree.
1473
+ * @param {unknown} value - Candidate semantic subtree.
1474
+ * @returns {void}
1475
+ */
1476
+ function visit(value) {
1477
+ if (!value || typeof value != "object" || seen.has(value))
1478
+ return;
1479
+ seen.add(value);
1480
+ if (!Array.isArray(value)) {
1481
+ for (const [key, nested] of Object.entries(value)) {
1482
+ if (identityFields.has(key) && typeof nested == "string" && replacements.has(nested)) {
1483
+ Reflect.set(value, key, replacements.get(nested));
1484
+ }
1485
+ else
1486
+ visit(nested);
1487
+ }
1488
+ }
1489
+ else
1490
+ for (const nested of value)
1491
+ visit(nested);
1492
+ }
1493
+ visit(module);
1494
+ }
1495
+ /**
1496
+ * Tests for a plain request object.
1497
+ * @param {unknown} value - Candidate request.
1498
+ * @returns {value is Record<string, unknown>} Whether it is a plain object.
1499
+ */
1500
+ function isPlainObject(value) {
1501
+ return Boolean(value) && typeof value == "object" && !Array.isArray(value) && Object.getPrototypeOf(value) == Object.prototype;
1502
+ }
1503
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW9zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2JhY2tlbmRzL2lvcy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLGFBQWEsQ0FBQTtBQUN0QyxPQUFPLEVBQUMsWUFBWSxFQUFDLE1BQU0sYUFBYSxDQUFBO0FBQ3hDLE9BQU8sRUFBQyxnQ0FBZ0MsRUFBRSxrQkFBa0IsRUFBQyxNQUFNLHFCQUFxQixDQUFBO0FBQ3hGLE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLHNCQUFzQixDQUFBO0FBQ3RELE9BQU8sRUFBQyxxQkFBcUIsRUFBRSxxQkFBcUIsRUFBQyxNQUFNLGtCQUFrQixDQUFBO0FBQzdFLE9BQU8sRUFBQyxlQUFlLEVBQUUsYUFBYSxFQUFDLE1BQU0sZUFBZSxDQUFBO0FBQzVELE9BQU8sRUFBQyxxQkFBcUIsRUFBQyxNQUFNLHdCQUF3QixDQUFBO0FBQzVELE9BQU8sRUFBQyx3QkFBd0IsRUFBQyxNQUFNLGNBQWMsQ0FBQTtBQUNyRCxPQUFPLEVBQUMsY0FBYyxFQUFFLGlCQUFpQixFQUFDLE1BQU0sY0FBYyxDQUFBO0FBQzlELE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxhQUFhLENBQUE7QUFFeEMsNkVBQTZFO0FBQzdFLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxHQUFHLENBQUM7SUFDakMsS0FBSyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLE1BQU07Q0FDM0gsQ0FBQyxDQUFBO0FBQ0YsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLEdBQUcsQ0FBQztJQUNsQyxrQkFBa0IsRUFBRSxjQUFjLEVBQUUsa0JBQWtCLEVBQUUsYUFBYSxFQUFFLGNBQWMsRUFBRSxX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Q0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxZQUFZLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUE7Z0JBQ25ELENBQUM7O29CQUFNLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQTtZQUN0QixDQUFDO1FBQ0gsQ0FBQzs7WUFBTSxLQUFLLE1BQU0sTUFBTSxJQUFJLEtBQUs7Z0JBQUUsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBQ2xELENBQUM7SUFDRCxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUE7QUFDZixDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQVMsYUFBYSxDQUFDLEtBQUs7SUFDMUIsT0FBTyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksT0FBTyxLQUFLLElBQUksUUFBUSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxNQUFNLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FBQyxTQUFTLENBQUE7QUFDaEksQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQge2NyZWF0ZUhhc2h9IGZyb20gXCJub2RlOmNyeXB0b1wiXG5pbXBvcnQge2lzRGVuc2VBcnJheX0gZnJvbSBcIi4uL2FycmF5LmpzXCJcbmltcG9ydCB7ZmluZFBvcnRhYmxlQXJ0aWZhY3RQYXRoQ29uZmxpY3QsIGlzU2FmZUFydGlmYWN0UGF0aH0gZnJvbSBcIi4uL2FydGlmYWN0LXBhdGguanNcIlxuaW1wb3J0IHtjcmVhdGVCeXRlTWFwcGluZ30gZnJvbSBcIi4uL2JpbmFyeS1tYXBwaW5nLmpzXCJcbmltcG9ydCB7U2VtYW50aWZvbGREaWFnbm9zdGljLCB1bnN1cHBvcnRlZENhcGFiaWxpdHl9IGZyb20gXCIuLi9kaWFnbm9zdGljLmpzXCJcbmltcG9ydCB7ZmluYWxpemVNYXBwaW5nLCB0b1NvdXJjZU1hcFYzfSBmcm9tIFwiLi4vbWFwcGluZy5qc1wiXG5pbXBvcnQge2hhc09ubHlVbmljb2RlU2NhbGFyc30gZnJvbSBcIi4uL3NlbWFudGljL3NjYWxhcnMuanNcIlxuaW1wb3J0IHtwcmVmbGlnaHRTZW1hbnRpY1Byb2dyYW19IGZyb20gXCIuL3Byb2dyYW0uanNcIlxuaW1wb3J0IHtlbWl0U2NhbGFyVHlwZSwgZW1pdFN0cmluZ0xpdGVyYWx9IGZyb20gXCIuL3NjYWxhcnMuanNcIlxuaW1wb3J0IHtTb3VyY2VXcml0ZXJ9IGZyb20gXCIuL3dyaXRlci5qc1wiXG5cbi8qKiBAdHlwZSB7UmVhZG9ubHk8U2V0PGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljTGFuZ3VhZ2U+Pn0gKi9cbmNvbnN0IGlvc1NvdXJjZUxhbmd1YWdlcyA9IG5ldyBTZXQoW1xuICBcInBocFwiLCBcInJ1YnlcIiwgXCJqYXZhc2NyaXB0XCIsIFwidHlwZXNjcmlwdFwiLCBcImphdmFcIiwgXCJrb3RsaW5cIiwgXCJweXRob25cIiwgXCJjc2hhcnBcIiwgXCJnb1wiLCBcImNcIiwgXCJjcHBcIiwgXCJydXN0XCIsIFwic3dpZnRcIiwgXCJkYXJ0XCJcbl0pXG5jb25zdCBjb25maWd1cmF0aW9uRmllbGRzID0gbmV3IFNldChbXG4gIFwiYnVuZGxlSWRlbnRpZmllclwiLCBcImNhcGFiaWxpdGllc1wiLCBcImRlcGxveW1lbnRUYXJnZXRcIiwgXCJkaXNwbGF5TmFtZVwiLCBcImVudGl0bGVtZW50c1wiLCBcImluZm9QbGlzdFwiLCBcImxpZmVjeWNsZVwiLFxuICBcIm1vZHVsZU5hbWVcIiwgXCJvcmdhbml6YXRpb25QcmVmaXhcIiwgXCJwZXJtaXNzaW9uc1wiLCBcInByaXZhY3lEZWNsYXJhdGlvbnNcIiwgXCJwcm9kdWN0TmFtZVwiLCBcInJlc291cmNlUm9vdFwiLCBcInNvdXJjZVJvb3RcIlxuXSlcbmNvbnN0IGFzc2V0RmllbGRzID0gbmV3IFNldChbXCJjb250ZW50XCIsIFwibWVkaWFUeXBlXCIsIFwicGF0aFwiLCBcInNoYTI1NlwiXSlcbmNvbnN0IGdlbmVyYXRvclZlcnNpb24gPSBcIjAuMy4wXCJcbmNvbnN0IGV4Y2x1ZGVkUGF0aFBhdHRlcm5zID0gT2JqZWN0LmZyZWV6ZShbXG4gIFwiKiovKi54Y3VzZXJzdGF0ZVwiLFxuICBcIioqL3hjdXNlcmRhdGEvKipcIixcbiAgXCIuc3dpZnRwbS8qKlwiLFxuICBcIkRlcml2ZWREYXRhLyoqXCIsXG4gIFwiYnVpbGQvKipcIlxuXSlcbmNvbnN0IG1lZGlhVHlwZVBhdHRlcm4gPSAvXltBLVphLXowLTkhIyQmXl8uKy1dK1xcL1tBLVphLXowLTkhIyQmXl8uKy1dKyg/OjtbXFx1MDAyMC1cXHUwMDdlXSspPyQvdVxuY29uc3QgYmluYXJ5T3BlcmF0aW9ucyA9IE9iamVjdC5mcmVlemUoe1xuICBCb29sZWFuQW5kOiBcIiYmXCIsXG4gIEJvb2xlYW5FcXVhbDogXCI9PVwiLFxuICBCb29sZWFuTm90RXF1YWw6IFwiIT1cIixcbiAgQm9vbGVhbk9yOiBcInx8XCIsXG4gIEludGVnZXJBZGQ6IFwiK1wiLFxuICBJbnRlZ2VyRXF1YWw6IFwiPT1cIixcbiAgSW50ZWdlckdyZWF0ZXJUaGFuOiBcIj5cIixcbiAgSW50ZWdlckdyZWF0ZXJUaGFuT3JFcXVhbDogXCI+PVwiLFxuICBJbnRlZ2VyTGVzc1RoYW46IFwiPFwiLFxuICBJbnRlZ2VyTGVzc1RoYW5PckVxdWFsOiBcIjw9XCIsXG4gIEludGVnZXJNdWx0aXBseTogXCIqXCIsXG4gIEludGVnZXJOb3RFcXVhbDogXCIhPVwiLFxuICBJbnRlZ2VyU3VidHJhY3Q6IFwiLVwiLFxuICBTdHJpbmdDb25jYXQ6IFwiK1wiLFxuICBTdHJpbmdFcXVhbDogXCI9PVwiLFxuICBTdHJpbmdOb3RFcXVhbDogXCIhPVwiXG59KVxuY29uc3QgdW5hcnlPcGVyYXRpb25zID0gT2JqZWN0LmZyZWV6ZSh7Qm9vbGVhbk5vdDogXCIhXCIsIEludGVnZXJOZWdhdGU6IFwiLVwifSlcbmNvbnN0IGlvc1N3aWZ0UnVudGltZSA9IGBmaW5hbCBjbGFzcyBTZW1hbnRpZm9sZE91dHB1dFNpbmsge1xuICBwcml2YXRlKHNldCkgdmFyIGxpbmVzOiBbU3RyaW5nXSA9IFtdXG5cbiAgZnVuYyB3cml0ZShfIHZhbHVlOiBJbnQ2NCkge1xuICAgIGxpbmVzLmFwcGVuZChTdHJpbmcodmFsdWUpKVxuICB9XG5cbiAgZnVuYyB3cml0ZShfIHZhbHVlOiBCb29sKSB7XG4gICAgbGluZXMuYXBwZW5kKHZhbHVlID8gXCJ0cnVlXCIgOiBcImZhbHNlXCIpXG4gIH1cblxuICBmdW5jIHdyaXRlKF8gdmFsdWU6IFN0cmluZykge1xuICAgIGxpbmVzLmFwcGVuZCh2YWx1ZSlcbiAgfVxufVxuXG5mdW5jIHNlbWFudGlmb2xkX3N0cmluZ19lcXVhbChfIGxlZnQ6IFN0cmluZywgXyByaWdodDogU3RyaW5nKSAtPiBCb29sIHtcbiAgcmV0dXJuIGxlZnQudW5pY29kZVNjYWxhcnMuZWxlbWVudHNFcXVhbChyaWdodC51bmljb2RlU2NhbGFycylcbn1cblxuZnVuYyBzZW1hbnRpZm9sZF9zdHJpbmdfbm90X2VxdWFsKF8gbGVmdDogU3RyaW5nLCBfIHJpZ2h0OiBTdHJpbmcpIC0+IEJvb2wge1xuICByZXR1cm4gIWxlZnQudW5pY29kZVNjYWxhcnMuZWxlbWVudHNFcXVhbChyaWdodC51bmljb2RlU2NhbGFycylcbn1cblxuZnVuYyBzZW1hbnRpZm9sZF9rZWVwX211dGFibGU8VD4oXyB2YWx1ZTogaW5vdXQgVCkge1xufVxuYFxuXG4vKiogQHR5cGVkZWYge3tjb250ZW50OiBzdHJpbmcsIGZpZWxkOiBzdHJpbmd9fSBDb25maWd1cmF0aW9uRnJhZ21lbnQgKi9cbi8qKiBAdHlwZWRlZiB7c3RyaW5nIHwgQ29uZmlndXJhdGlvbkZyYWdtZW50fSBDb25maWd1cmF0aW9uVGV4dFBhcnQgKi9cbi8qKiBAdHlwZWRlZiB7c3RyaW5nIHwgcmVhZG9ubHkgQ29uZmlndXJhdGlvblRleHRQYXJ0W119IENvbmZpZ3VyYXRpb25MaW5lICovXG4vKiogQHR5cGVkZWYge3tlbmQ6IG51bWJlciwgZmllbGQ6IHN0cmluZywgc3RhcnQ6IG51bWJlcn19IENvbmZpZ3VyYXRpb25TcGFuICovXG4vKiogQHR5cGVkZWYge3tjb250ZW50OiBzdHJpbmcsIGNvbmZpZ3VyYXRpb25TcGFuczogQ29uZmlndXJhdGlvblNwYW5bXX19IFJlbmRlcmVkQ29uZmlndXJhdGlvblRleHQgKi9cbi8qKiBAdHlwZWRlZiB7e2VuZDogbnVtYmVyLCBmaWVsZDogc3RyaW5nLCBwYXRoOiBzdHJpbmcsIHN0YXJ0OiBudW1iZXJ9fSBDb25maWd1cmF0aW9uQXJ0aWZhY3RTcGFuICovXG5cbi8qKiBSZWNvcmRzIGNvbmZpZ3VyYXRpb24gY2F1c2FsaXR5IHdoaWxlIGFuIG93bmluZyByZW5kZXJlciBlbWl0cyB0ZXh0LiAqL1xuY2xhc3MgQ29uZmlndXJhdGlvblRleHRXcml0ZXIge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLmNvbnRlbnQgPSBcIlwiXG4gICAgLyoqIEB0eXBlIHtDb25maWd1cmF0aW9uU3BhbltdfSAqL1xuICAgIHRoaXMuY29uZmlndXJhdGlvblNwYW5zID0gW11cbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBlbmRzIGxpdGVyYWwgb3IgZmllbGQtb3duZWQgdGV4dC5cbiAgICogQHBhcmFtIHtDb25maWd1cmF0aW9uVGV4dFBhcnQgfCByZWFkb25seSBDb25maWd1cmF0aW9uVGV4dFBhcnRbXX0gdmFsdWUgLSBPcmRlcmVkIG91dHB1dCB0ZXh0LlxuICAgKi9cbiAgYXBwZW5kKHZhbHVlKSB7XG4gICAgY29uc3QgcGFydHMgPSBBcnJheS5pc0FycmF5KHZhbHVlKSA/IHZhbHVlIDogW3ZhbHVlXVxuXG4gICAgZm9yIChjb25zdCBwYXJ0IG9mIHBhcnRzKSB7XG4gICAgICBpZiAodHlwZW9mIHBhcnQgPT0gXCJzdHJpbmdcIikge1xuICAgICAgICB0aGlzLmNvbnRlbnQgKz0gcGFydFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3Qgc3RhcnQgPSB0aGlzLmNvbnRlbnQubGVuZ3RoXG5cbiAgICAgICAgdGhpcy5jb250ZW50ICs9IHBhcnQuY29udGVudFxuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb25TcGFucy5wdXNoKHtlbmQ6IHRoaXMuY29udGVudC5sZW5ndGgsIGZpZWxkOiBwYXJ0LmZpZWxkLCBzdGFydH0pXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEZpbmlzaGVzIHJlbmRlcmVyLW93bmVkIHRleHQgY29sbGVjdGlvbi5cbiAgICogQHJldHVybnMge1JlbmRlcmVkQ29uZmlndXJhdGlvblRleHR9IEZpbmlzaGVkIGNvbnRlbnQgYW5kIGNhdXNhbCBzcGFucy5cbiAgICovXG4gIGZpbmlzaCgpIHtcbiAgICByZXR1cm4ge2NvbmZpZ3VyYXRpb25TcGFuczogdGhpcy5jb25maWd1cmF0aW9uU3BhbnMsIGNvbnRlbnQ6IHRoaXMuY29udGVudH1cbiAgfVxufVxuXG4vKipcbiAqIE1hcmtzIHRleHQgYXMgY2F1c2FsbHkgb3duZWQgYnkgb25lIG5vcm1hbGl6ZWQgY29uZmlndXJhdGlvbiBmaWVsZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWVsZCAtIENvbmZpZ3VyYXRpb24gZmllbGQuXG4gKiBAcGFyYW0ge3N0cmluZ30gY29udGVudCAtIEV4YWN0IHJlbmRlcmVkIHRva2VuIGNvbnRlbnQuXG4gKiBAcmV0dXJucyB7Q29uZmlndXJhdGlvbkZyYWdtZW50fSBUYWdnZWQgdG9rZW4uXG4gKi9cbmZ1bmN0aW9uIGNvbmZpZ3VyYXRpb25GcmFnbWVudChmaWVsZCwgY29udGVudCkge1xuICByZXR1cm4ge2NvbnRlbnQsIGZpZWxkfVxufVxuXG4vKipcbiAqIFByZWZsaWdodHMgb25lIGNvbXBsZXRlIHByb2plY3QgYWdhaW5zdCB0aGUgZGVsaXZlcmVkIFN3aWZ0IFRhc2tzIDAwMS0wMDQgcHJvZmlsZS5cbiAqIEBwYXJhbSB7b2JqZWN0fSBpbnB1dCAtIGlPUyBhcHBsaWNhdGlvbiBnZW5lcmF0aW9uIGlucHV0LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY01vZHVsZX0gW2lucHV0Lm1vZHVsZV0gLSBTaW5nbGUgbW9kdWxlIHRvIG5vcm1hbGl6ZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU2VtYW50aWNQcm9ncmFtfSBbaW5wdXQucHJvZ3JhbV0gLSBDYWxsZXItb3duZWQgVGFzayAwMTAgcHJvamVjdC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuSW9zQXBwbGljYXRpb25Db25maWd1cmF0aW9uSW5wdXR9IFtpbnB1dC5jb25maWd1cmF0aW9uXSAtIENsb3NlZCBhcHBsaWNhdGlvbiBjb25maWd1cmF0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Jb3NBcHBsaWNhdGlvbkFzc2V0SW5wdXRbXX0gW2lucHV0LmFzc2V0c10gLSBFeGFjdCBjYWxsZXItcHJvdmlkZWQgYXNzZXRzLlxuICogQHJldHVybnMge3thc3NldHM6IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLklvc0FwcGxpY2F0aW9uQXNzZXRJbnB1dFtdLCBjb25maWd1cmF0aW9uOiBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Jb3NBcHBsaWNhdGlvbkNvbmZpZ3VyYXRpb24sIG1vZHVsZVBhdGhzOiBNYXA8c3RyaW5nLCBzdHJpbmc+LCBtb2R1bGVzOiBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY01vZHVsZVtdLCBwcm9ncmFtOiBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY1Byb2dyYW0sIHNvdXJjZXM6IHtjb250ZW50OiBzdHJpbmcsIGZpbGVuYW1lOiBzdHJpbmcsIGxhbmd1YWdlPzogaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU2VtYW50aWNMYW5ndWFnZX1bXX19IFByZXBhcmVkIGFwcGxpY2F0aW9uIHByb2dyYW0uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcmVmbGlnaHRJb3NBcHBsaWNhdGlvbihpbnB1dCkge1xuICBpZiAoIWlzUGxhaW5PYmplY3QoaW5wdXQpIHx8IEJvb2xlYW4oaW5wdXQubW9kdWxlKSA9PSBCb29sZWFuKGlucHV0LnByb2dyYW0pKSB7XG4gICAgdGhyb3cgbmV3IFNlbWFudGlmb2xkRGlhZ25vc3RpYyh7XG4gICAgICBjb2RlOiBcIklOVkFMSURfQVBQTElDQVRJT05fSU5QVVRcIixcbiAgICAgIGxhbmd1YWdlOiBcImlvc1wiLFxuICAgICAgbWVzc2FnZTogXCJpT1MgYXBwbGljYXRpb24gZ2VuZXJhdGlvbiByZXF1aXJlcyBleGFjdGx5IG9uZSBzZW1hbnRpYyBtb2R1bGUgb3IgcHJvZ3JhbS5cIlxuICAgIH0pXG4gIH1cbiAgY29uc3QgY29uZmlndXJhdGlvbiA9IG5vcm1hbGl6ZUNvbmZpZ3VyYXRpb24oaW5wdXQuY29uZmlndXJhdGlvbilcbiAgY29uc3QgcHJvZ3JhbSA9IGlucHV0LnByb2dyYW0gPz8gbm9ybWFsaXplU2luZ2xlTW9kdWxlKGlucHV0Lm1vZHVsZSlcbiAgY29uc3QgcHJlcGFyZWQgPSBwcmVmbGlnaHRTZW1hbnRpY1Byb2dyYW0oe1xuICAgIGJhY2tlbmRMYW5ndWFnZTogXCJzd2lmdFwiLFxuICAgIGRpYWdub3N0aWNMYW5ndWFnZTogXCJpb3NcIixcbiAgICBwcm9ncmFtLFxuICAgIHNvdXJjZUxhbmd1YWdlczogaW9zU291cmNlTGFuZ3VhZ2VzXG4gIH0pXG4gIGNvbnN0IG1vZHVsZVBhdGhzID0gbmV3IE1hcChwcmVwYXJlZC5tb2R1bGVzLm1hcChtb2R1bGUgPT4gW1xuICAgIC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAoUmVmbGVjdC5nZXQobW9kdWxlLCBcImlkXCIpKSxcbiAgICBgJHtjb25maWd1cmF0aW9uLnNvdXJjZVJvb3R9L0dlbmVyYXRlZC8ke21vZHVsZU5hbWUoLyoqIEB0eXBlIHtzdHJpbmd9ICovIChSZWZsZWN0LmdldChtb2R1bGUsIFwiaWRcIikpKX0uc3dpZnRgXG4gIF0pKVxuICBjb25zdCBhc3NldHMgPSBub3JtYWxpemVBc3NldHMoaW5wdXQuYXNzZXRzLCBjb25maWd1cmF0aW9uLnJlc291cmNlUm9vdClcbiAgY29uc3QgY29uZmxpY3QgPSBmaW5kUG9ydGFibGVBcnRpZmFjdFBhdGhDb25mbGljdChbXG4gICAgYCR7Y29uZmlndXJhdGlvbi5zb3VyY2VSb290fS9HZW5lcmF0ZWQvU2VtYW50aWZvbGRSdW50aW1lLnN3aWZ0YCxcbiAgICAuLi5tb2R1bGVQYXRocy52YWx1ZXMoKSxcbiAgICBgJHtjb25maWd1cmF0aW9uLnJlc291cmNlUm9vdH0vQ29udGVudHMuanNvbmAsXG4gICAgLi4uYXNzZXRzLm1hcCgoe3BhdGh9KSA9PiBwYXRoKVxuICBdKVxuXG4gIGlmIChjb25mbGljdCkgaW52YWxpZFBhdGgoYEFwcGxpY2F0aW9uIGFydGlmYWN0IHBhdGggJyR7Y29uZmxpY3QucGF0aH0nIGhhcyBhICR7Y29uZmxpY3Qua2luZH0gY29uZmxpY3Qke2NvbmZsaWN0Lm90aGVyID8gYCB3aXRoICcke2NvbmZsaWN0Lm90aGVyfSdgIDogXCJcIn0uYClcblxuICByZXR1cm4gey4uLnByZXBhcmVkLCBhc3NldHMsIGNvbmZpZ3VyYXRpb24sIG1vZHVsZVBhdGhzfVxufVxuXG4vKipcbiAqIEdlbmVyYXRlcyB0aGUgZGV0ZXJtaW5pc3RpYyBzZW1hbnRpYyBTd2lmdCBwb3J0aW9uIG9mIG9uZSBpT1MgYXBwbGljYXRpb24gYXJ0aWZhY3Qgc2V0LlxuICogQHBhcmFtIHtQYXJhbWV0ZXJzPHR5cGVvZiBwcmVmbGlnaHRJb3NBcHBsaWNhdGlvbj5bMF19IGlucHV0IC0gaU9TIGdlbmVyYXRpb24gcmVxdWVzdC5cbiAqIEByZXR1cm5zIHt7YXJ0aWZhY3RzOiBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5HZW5lcmF0ZWRTZXRBcnRpZmFjdFtdLCBtZXRhZGF0YToge2FwcGxpY2F0aW9uTWFuaWZlc3Q6IHN0cmluZywgcGxhdGZvcm1RdWFsaWZpY2F0aW9uOiBzdHJpbmd9LCB0YXJnZXQ6IFwiaW9zXCJ9fSBDYW5kaWRhdGUgYXJ0aWZhY3Qgc2V0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVJb3NBcHBsaWNhdGlvbihpbnB1dCkge1xuICBjb25zdCBwcmVwYXJlZCA9IHByZWZsaWdodElvc0FwcGxpY2F0aW9uKGlucHV0KVxuICBjb25zdCBzZW1hbnRpY0FydGlmYWN0cyA9IHJlbmRlclNlbWFudGljQXJ0aWZhY3RzKHByZXBhcmVkKVxuICBjb25zdCBhcHBsaWNhdGlvblBhdGhzID0gYXBwbGljYXRpb25BcnRpZmFjdFBhdGhzKHByZXBhcmVkKVxuICBjb25zdCBwcm9qZWN0ID0gcmVuZGVyUGJ4UHJvamVjdChwcmVwYXJlZCwgYXBwbGljYXRpb25QYXRocylcbiAgY29uc3Qgc2NoZW1lID0gcmVuZGVyU2hhcmVkU2NoZW1lKHByZXBhcmVkKVxuICBjb25zdCBiYXNlQ29uZmlndXJhdGlvbiA9IHJlbmRlckJhc2VDb25maWd1cmF0aW9uKHByZXBhcmVkLmNvbmZpZ3VyYXRpb24pXG4gIGNvbnN0IGluZm9QbGlzdCA9IHJlbmRlckluZm9QbGlzdChwcmVwYXJlZC5jb25maWd1cmF0aW9uKVxuICBjb25zdCB1bml0VGVzdHMgPSByZW5kZXJVbml0VGVzdHMocHJlcGFyZWQuY29uZmlndXJhdGlvbilcbiAgY29uc3QgdWlUZXN0cyA9IHJlbmRlclVpVGVzdHMocHJlcGFyZWQuY29uZmlndXJhdGlvbilcbiAgY29uc3QgY29uZmlndXJhdGlvbiA9IHByZXBhcmVkLmNvbmZpZ3VyYXRpb25cbiAgY29uc3QgZW50cnlOYW1lc3BhY2UgPSBgU2VtYW50aWZvbGRNb2R1bGUke21vZHVsZU5hbWUocHJlcGFyZWQucHJvZ3JhbS5lbnRyeU1vZHVsZSl9YFxuICBjb25zdCBhcHAgPSBgaW1wb3J0IFN3aWZ0VUlcblxuQG1haW5cbnN0cnVjdCBTZW1hbnRpZm9sZEFwcGxpY2F0aW9uOiBBcHAge1xuICB2YXIgYm9keTogc29tZSBTY2VuZSB7XG4gICAgV2luZG93R3JvdXAge1xuICAgICAgU2VtYW50aWZvbGRPdXRwdXRWaWV3KGxpbmVzOiBTZW1hbnRpZm9sZEJyaWRnZS5ydW4oKSlcbiAgICB9XG4gIH1cbn1cbmBcbiAgY29uc3QgYnJpZGdlID0gYGVudW0gU2VtYW50aWZvbGRCcmlkZ2Uge1xuICBzdGF0aWMgZnVuYyBydW4oKSAtPiBbU3RyaW5nXSB7XG4gICAgcmV0dXJuICR7ZW50cnlOYW1lc3BhY2V9LnNlbWFudGlmb2xkRW50cnkoKVxuICB9XG59XG5gXG4gIGNvbnN0IHZpZXcgPSBgaW1wb3J0IFN3aWZ0VUlcblxuc3RydWN0IFNlbWFudGlmb2xkT3V0cHV0VmlldzogVmlldyB7XG4gIGxldCBsaW5lczogW1N0cmluZ11cblxuICB2YXIgYm9keTogc29tZSBWaWV3IHtcbiAgICBUZXh0KGxpbmVzLmpvaW5lZChzZXBhcmF0b3I6IFwiXFxcXG5cIikpXG4gICAgICAuYWNjZXNzaWJpbGl0eUlkZW50aWZpZXIoXCJzZW1hbnRpZm9sZC1vdXRwdXRcIilcbiAgfVxufVxuYFxuICBjb25zdCBwcm9kdWN0ID0gY29uZmlndXJhdGlvbi5wcm9kdWN0TmFtZVxuICAvKiogQHR5cGUge0NvbmZpZ3VyYXRpb25BcnRpZmFjdFNwYW5bXX0gKi9cbiAgY29uc3QgY29uZmlndXJhdGlvblNwYW5zID0gW11cbiAgY29uc3QgYXJ0aWZhY3RzID0gW1xuICAgIGNvbmZpZ3VyZWRTeW50aGV0aWNUZXh0KGAke3Byb2R1Y3R9Lnhjb2RlcHJvai9wcm9qZWN0LnBieHByb2pgLCBcIm1hbmlmZXN0XCIsIHByb2plY3QsXG4gICAgICBjb25maWd1cmF0aW9uU3BhbnMsXG4gICAgICBcIkNhbm9uaWNhbCBkZXRlcm1pbmlzdGljIFhjb2RlIHByb2plY3Qgc3RydWN0dXJlLlwiKSxcbiAgICBjb25maWd1cmVkU3ludGhldGljVGV4dChgJHtwcm9kdWN0fS54Y29kZXByb2oveGNzaGFyZWRkYXRhL3hjc2NoZW1lcy8ke3Byb2R1Y3R9Lnhjc2NoZW1lYCwgXCJzdXBwb3J0XCIsXG4gICAgICBzY2hlbWUsIGNvbmZpZ3VyYXRpb25TcGFucywgXCJDYW5vbmljYWwgc2hhcmVkIFhjb2RlIGFwcGxpY2F0aW9uL3Rlc3Qgc2NoZW1lLlwiKSxcbiAgICBjb25maWd1cmVkU3ludGhldGljVGV4dChcIkNvbmZpZ3VyYXRpb24vQmFzZS54Y2NvbmZpZ1wiLCBcInN1cHBvcnRcIiwgYmFzZUNvbmZpZ3VyYXRpb24sIGNvbmZpZ3VyYXRpb25TcGFucyxcbiAgICAgIFwiQ2xvc2VkIHVuc2lnbmVkIGlPUyBidWlsZCBjb25maWd1cmF0aW9uLlwiKSxcbiAgICBjb25maWd1cmVkU3ludGhldGljVGV4dChcIkNvbmZpZ3VyYXRpb24vSW5mby5wbGlzdFwiLCBcInN1cHBvcnRcIiwgaW5mb1BsaXN0LCBjb25maWd1cmF0aW9uU3BhbnMsXG4gICAgICBcIkFsbG93bGlzdGVkIGlPUyBhcHBsaWNhdGlvbiBwcm9wZXJ0eSBsaXN0LlwiKSxcbiAgICAuLi5zZW1hbnRpY0FydGlmYWN0cyxcbiAgICBzeW50aGV0aWNUZXh0KFwiU291cmNlcy9BcHBsaWNhdGlvbi9BcHAuc3dpZnRcIiwgXCJlbnRyeVwiLCBhcHAsIFwiU3ludGhldGljIFN3aWZ0VUkgYXBwbGljYXRpb24gbGlmZWN5Y2xlLlwiKSxcbiAgICBzeW50aGV0aWNUZXh0KFwiU291cmNlcy9BcHBsaWNhdGlvbi9TZW1hbnRpZm9sZEJyaWRnZS5zd2lmdFwiLCBcInN1cHBvcnRcIiwgYnJpZGdlLFxuICAgICAgXCJTeW50aGV0aWMgYnJpZGdlIGZyb20gU3dpZnRVSSB0byB0aGUgc2VtYW50aWMgZW50cnkuXCIpLFxuICAgIHN5bnRoZXRpY1RleHQoXCJTb3VyY2VzL0FwcGxpY2F0aW9uL1NlbWFudGlmb2xkT3V0cHV0Vmlldy5zd2lmdFwiLCBcInN1cHBvcnRcIiwgdmlldyxcbiAgICAgIFwiU3ludGhldGljIHN0YWJsZSB0ZXh0IG91dHB1dCB2aWV3IGFuZCBhY2Nlc3NpYmlsaXR5IGlkZW50aWZpZXIuXCIpLFxuICAgIHN5bnRoZXRpY1RleHQoXCJBc3NldHMueGNhc3NldHMvQ29udGVudHMuanNvblwiLCBcInJlc291cmNlXCIsIHN0cmluZ2lmeUNhbm9uaWNhbEpzb24oe1xuICAgICAgaW5mbzoge2F1dGhvcjogXCJzZW1hbnRpZm9sZFwiLCB2ZXJzaW9uOiAxfVxuICAgIH0pLCBcIkJhc2UgYXNzZXQtY2F0YWxvZyBtZXRhZGF0YTsgbm8gYXBwbGljYXRpb24gaWNvbiBpcyBzeW50aGVzaXplZC5cIiksXG4gICAgLi4ucHJlcGFyZWQuYXNzZXRzLm1hcChhc3NldEFydGlmYWN0KSxcbiAgICBjb25maWd1cmVkU3ludGhldGljVGV4dChgVGVzdHMvJHtwcm9kdWN0fVRlc3RzLnN3aWZ0YCwgXCJzdXBwb3J0XCIsIHVuaXRUZXN0cywgY29uZmlndXJhdGlvblNwYW5zLFxuICAgICAgXCJTeW50aGV0aWMgcHVyZS1sb2dpYyBkZXRlcm1pbmlzbSBYQ1Rlc3Qgc291cmNlLlwiKSxcbiAgICBjb25maWd1cmVkU3ludGhldGljVGV4dChgVUlUZXN0cy8ke3Byb2R1Y3R9VUlUZXN0cy5zd2lmdGAsIFwic3VwcG9ydFwiLCB1aVRlc3RzLCBjb25maWd1cmF0aW9uU3BhbnMsXG4gICAgICBcIlN5bnRoZXRpYyBYQ1VJIGFjY2Vzc2liaWxpdHktcm91dGUgdGVzdCBzb3VyY2UuXCIpXG4gIF1cbiAgY29uc3QgbWFuaWZlc3RQYXRoID0gXCJzZW1hbnRpZm9sZC1wcm9qZWN0Lmpzb25cIlxuXG4gIGFydGlmYWN0cy5wdXNoKHN5bnRoZXRpY1RleHQobWFuaWZlc3RQYXRoLCBcIm1hbmlmZXN0XCIsXG4gICAgcmVuZGVyUHJvamVjdE1hbmlmZXN0KHByZXBhcmVkLCBhcnRpZmFjdHMsIG1hbmlmZXN0UGF0aCwgY29uZmlndXJhdGlvblNwYW5zKSxcbiAgICBcIlZlcnNpb25lZCBpT1MgcHJvamVjdCBvd25lcnNoaXAgYW5kIHByb3ZlbmFuY2UgbWFuaWZlc3QuXCIpKVxuXG4gIHJldHVybiB7XG4gICAgYXJ0aWZhY3RzLFxuICAgIG1ldGFkYXRhOiB7YXBwbGljYXRpb25NYW5pZmVzdDogbWFuaWZlc3RQYXRoLCBwbGF0Zm9ybVF1YWxpZmljYXRpb246IFwiZGVmZXJyZWRcIn0sXG4gICAgdGFyZ2V0OiBcImlvc1wiXG4gIH1cbn1cblxuLyoqXG4gKiBSZW5kZXJzIHRoZSBjb21wbGV0ZSBkZXRlcm1pbmlzdGljIGFwcGxpY2F0aW9uIG93bmVyc2hpcCBhbmQgcHJvdmVuYW5jZSByZWNvcmQuXG4gKiBAcGFyYW0ge1JldHVyblR5cGU8dHlwZW9mIHByZWZsaWdodElvc0FwcGxpY2F0aW9uPn0gcHJlcGFyZWQgLSBGdWxseSBwcmVmbGlnaHRlZCBhcHBsaWNhdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuR2VuZXJhdGVkU2V0QXJ0aWZhY3RbXX0gYXJ0aWZhY3RzIC0gQWxsIG5vbi1tYW5pZmVzdCBvdXRwdXQgYXJ0aWZhY3RzLlxuICogQHBhcmFtIHtzdHJpbmd9IG1hbmlmZXN0UGF0aCAtIE93bmVkIG1hbmlmZXN0IHBhdGguXG4gKiBAcGFyYW0ge0NvbmZpZ3VyYXRpb25BcnRpZmFjdFNwYW5bXX0gY29uZmlndXJhdGlvblNwYW5zIC0gUmVuZGVyZXItb3duZWQgY29uZmlndXJhdGlvbiByYW5nZXMuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBDYW5vbmljYWwgbWFuaWZlc3QgSlNPTi5cbiAqL1xuZnVuY3Rpb24gcmVuZGVyUHJvamVjdE1hbmlmZXN0KHByZXBhcmVkLCBhcnRpZmFjdHMsIG1hbmlmZXN0UGF0aCwgY29uZmlndXJhdGlvblNwYW5zKSB7XG4gIGNvbnN0IGFzc2V0UGF0aHMgPSBuZXcgU2V0KHByZXBhcmVkLmFzc2V0cy5tYXAoKHtwYXRofSkgPT4gcGF0aCkpXG4gIGNvbnN0IHNlbWFudGljQXJ0aWZhY3RzID0gYXJ0aWZhY3RzLmZpbHRlcihhcnRpZmFjdCA9PiBhcnRpZmFjdC5wcm92ZW5hbmNlLmtpbmQgPT0gXCJ0ZXh0XCIpXG4gIGNvbnN0IGNvbmZpZ3VyYXRpb24gPSBwcmVwYXJlZC5jb25maWd1cmF0aW9uXG5cbiAgcmV0dXJuIHN0cmluZ2lmeUNhbm9uaWNhbEpzb24oe1xuICAgIGNvbmZpZ3VyYXRpb24sXG4gICAgZ2VuZXJhdG9yOiB7bmFtZTogXCJzZW1hbnRpZm9sZFwiLCB2ZXJzaW9uOiBnZW5lcmF0b3JWZXJzaW9ufSxcbiAgICBvd25lcnNoaXA6IHtcbiAgICAgIGV4Y2x1ZGVkUGF0aFBhdHRlcm5zLFxuICAgICAgb3duZWRQYXRoczogWy4uLmFydGlmYWN0cy5tYXAoKHtwYXRofSkgPT4gcGF0aCksIG1hbmlmZXN0UGF0aF1cbiAgICB9LFxuICAgIHBsYXRmb3JtUmVxdWlyZW1lbnRzOiB7XG4gICAgICBhcHBsZVNkazoge3N0YXR1czogXCJkZWZlcnJlZFwifSxcbiAgICAgIGlvc1NpbXVsYXRvcjoge3N0YXR1czogXCJkZWZlcnJlZFwifSxcbiAgICAgIG1hY29zSG9zdDoge3N0YXR1czogXCJkZWZlcnJlZFwifSxcbiAgICAgIHN3aWZ0Yzoge3N0YXR1czogXCJkZWZlcnJlZFwifSxcbiAgICAgIHhjb2RlOiB7c3RhdHVzOiBcImRlZmVycmVkXCJ9LFxuICAgICAgeGN0ZXN0OiB7c3RhdHVzOiBcImRlZmVycmVkXCJ9LFxuICAgICAgeGN1aWF1dG9tYXRpb246IHtzdGF0dXM6IFwiZGVmZXJyZWRcIn1cbiAgICB9LFxuICAgIHByb3ZlbmFuY2U6IHtcbiAgICAgIGFzc2V0czogcHJlcGFyZWQuYXNzZXRzLm1hcChhc3NldCA9PiAoe1xuICAgICAgICBjb250ZW50S2luZDogdHlwZW9mIGFzc2V0LmNvbnRlbnQgPT0gXCJzdHJpbmdcIiA/IFwidGV4dFwiIDogXCJiaW5hcnlcIixcbiAgICAgICAgbWVkaWFUeXBlOiBhc3NldC5tZWRpYVR5cGUsXG4gICAgICAgIHBhdGg6IGFzc2V0LnBhdGgsXG4gICAgICAgIHNoYTI1NjogYXNzZXQuc2hhMjU2XG4gICAgICB9KSksXG4gICAgICBjb25maWd1cmF0aW9uOiBPYmplY3Qua2V5cyhjb25maWd1cmF0aW9uKS5zb3J0KCkubWFwKGZpZWxkID0+ICh7XG4gICAgICAgIGZpZWxkLFxuICAgICAgICBtYW5pZmVzdFBvaW50ZXI6IGAvY29uZmlndXJhdGlvbi8ke2ZpZWxkfWAsXG4gICAgICAgIG91dHB1dHM6IGNvbmZpZ3VyYXRpb25PdXRwdXRDaXRhdGlvbnMoY29uZmlndXJhdGlvblNwYW5zLCBmaWVsZClcbiAgICAgIH0pKSxcbiAgICAgIHNlbWFudGljU291cmNlczogcHJlcGFyZWQuc291cmNlcy5tYXAoc291cmNlID0+ICh7XG4gICAgICAgIGFydGlmYWN0czogc2VtYW50aWNBcnRpZmFjdHMuZmlsdGVyKGFydGlmYWN0ID0+IGFydGlmYWN0LnByb3ZlbmFuY2Uua2luZCA9PSBcInRleHRcIiAmJlxuICAgICAgICAgIGFydGlmYWN0LnByb3ZlbmFuY2UubWFwcGluZy5zcGFucy5zb21lKCh7b3JpZ2lufSkgPT4gb3JpZ2luUmVmZXJlbmNlc0ZpbGVuYW1lKG9yaWdpbiwgc291cmNlLmZpbGVuYW1lKSkpXG4gICAgICAgICAgLm1hcCgoe3BhdGh9KSA9PiBwYXRoKSxcbiAgICAgICAgZmlsZW5hbWU6IHNvdXJjZS5maWxlbmFtZSxcbiAgICAgICAgLi4uKHNvdXJjZS5sYW5ndWFnZSA9PT0gdW5kZWZpbmVkID8ge30gOiB7bGFuZ3VhZ2U6IHNvdXJjZS5sYW5ndWFnZX0pLFxuICAgICAgICBzaGEyNTY6IGNyZWF0ZUhhc2goXCJzaGEyNTZcIikudXBkYXRlKHNvdXJjZS5jb250ZW50KS5kaWdlc3QoXCJoZXhcIilcbiAgICAgIH0pKSxcbiAgICAgIHN5bnRoZXRpY1NjYWZmb2xkaW5nOiBbXG4gICAgICAgIC4uLmFydGlmYWN0cy5maWx0ZXIoYXJ0aWZhY3QgPT4gYXJ0aWZhY3QucHJvdmVuYW5jZS5raW5kID09IFwic3ludGhldGljXCIgJiYgIWFzc2V0UGF0aHMuaGFzKGFydGlmYWN0LnBhdGgpKVxuICAgICAgICAgIC5tYXAoKHtwYXRofSkgPT4gcGF0aCksXG4gICAgICAgIG1hbmlmZXN0UGF0aFxuICAgICAgXVxuICAgIH0sXG4gICAgc2NoZW1hOiBcIlNlbWFudGlmb2xkSW9zUHJvamVjdFwiLFxuICAgIHNlbWFudGljUHJvZ3JhbTogc2VtYW50aWNQcm9ncmFtTWFuaWZlc3QocHJlcGFyZWQpLFxuICAgIHRhcmdldDogXCJpb3NcIixcbiAgICB2ZXJzaW9uOiAxXG4gIH0pXG59XG5cbi8qKlxuICogUmVjb3JkcyBzdGFibGUgc2VtYW50aWMgaW5wdXQgaWRlbnRpdGllcyBhbmQgdGhlaXIgZ2VuZXJhdGVkIFN3aWZ0IGxpbmthZ2UuXG4gKiBAcGFyYW0ge1JldHVyblR5cGU8dHlwZW9mIHByZWZsaWdodElvc0FwcGxpY2F0aW9uPn0gcHJlcGFyZWQgLSBGdWxseSBwcmVmbGlnaHRlZCBhcHBsaWNhdGlvbi5cbiAqIEByZXR1cm5zIHtSZWNvcmQ8c3RyaW5nLCB1bmtub3duPn0gVmVyc2lvbmVkIHNlbWFudGljLXByb2dyYW0gbWFuaWZlc3Qgc2VjdGlvbi5cbiAqL1xuZnVuY3Rpb24gc2VtYW50aWNQcm9ncmFtTWFuaWZlc3QocHJlcGFyZWQpIHtcbiAgY29uc3QgbW9kdWxlSWRzID0gbmV3IE1hcChwcmVwYXJlZC5wcm9ncmFtLm1vZHVsZXMubWFwKChtb2R1bGUsIGluZGV4KSA9PiBbbW9kdWxlLmlkLCBpbmRleF0pKVxuICBjb25zdCBzb3VyY2VDb250ZW50ID0gbmV3IE1hcChwcmVwYXJlZC5zb3VyY2VzLm1hcChzb3VyY2UgPT4gW3NvdXJjZS5maWxlbmFtZSwgc291cmNlLmNvbnRlbnRdKSlcbiAgY29uc3QgbW9kdWxlcyA9IHByZXBhcmVkLnByb2dyYW0ubW9kdWxlcy5tYXAobW9kdWxlID0+IHtcbiAgICBjb25zdCBpZCA9IG1vZHVsZS5pZFxuICAgIGNvbnN0IHBhdGggPSAvKiogQHR5cGUge3N0cmluZ30gKi8gKHByZXBhcmVkLm1vZHVsZVBhdGhzLmdldChpZCkpXG4gICAgY29uc3Qgc291cmNlID0gcHJlcGFyZWQucHJvZ3JhbS5zb3VyY2VzLmZpbmQoY2FuZGlkYXRlID0+IGNhbmRpZGF0ZS5maWxlbmFtZSA9PSBtb2R1bGUuc291cmNlRmlsZW5hbWUpXG4gICAgY29uc3QgY29udGVudCA9IHNvdXJjZUNvbnRlbnQuZ2V0KG1vZHVsZS5zb3VyY2VGaWxlbmFtZSlcblxuICAgIGlmICghc291cmNlIHx8IGNvbnRlbnQgPT09IHVuZGVmaW5lZCkgdGhyb3cgbmV3IFR5cGVFcnJvcihgUHJlZmxpZ2h0ZWQgaU9TIG1vZHVsZSAnJHtpZH0nIGxvc3QgaXRzIHNvdXJjZSBvd25lcnNoaXAuYClcbiAgICBjb25zdCBkZXBlbmRlbmNpZXMgPSBbLi4ubmV3IFNldChtb2R1bGUuaW1wb3J0cy5tYXAoKHttb2R1bGVJZH0pID0+IG1vZHVsZUlkKSldXG4gICAgICAuc29ydCgobGVmdCwgcmlnaHQpID0+IC8qKiBAdHlwZSB7bnVtYmVyfSAqLyAobW9kdWxlSWRzLmdldChsZWZ0KSkgLSAvKiogQHR5cGUge251bWJlcn0gKi8gKG1vZHVsZUlkcy5nZXQocmlnaHQpKSlcblxuICAgIHJldHVybiB7XG4gICAgICBkZXBlbmRlbmNpZXMsXG4gICAgICBnZW5lcmF0ZWRBcnRpZmFjdHM6IFtwYXRoXSxcbiAgICAgIGlkLFxuICAgICAgbmFtZXNwYWNlOiBgU2VtYW50aWZvbGRNb2R1bGUke21vZHVsZU5hbWUoaWQpfWAsXG4gICAgICBzb3VyY2U6IHtcbiAgICAgICAgZmlsZW5hbWU6IHNvdXJjZS5maWxlbmFtZSxcbiAgICAgICAgaWQ6IHNvdXJjZS5pZCxcbiAgICAgICAgc2hhMjU2OiBjcmVhdGVIYXNoKFwic2hhMjU2XCIpLnVwZGF0ZShjb250ZW50KS5kaWdlc3QoXCJoZXhcIilcbiAgICAgIH1cbiAgICB9XG4gIH0pXG4gIGNvbnN0IHNvdXJjZXMgPSBwcmVwYXJlZC5wcm9ncmFtLnNvdXJjZXMubWFwKHNvdXJjZSA9PiB7XG4gICAgY29uc3QgY29udGVudCA9IHNvdXJjZUNvbnRlbnQuZ2V0KHNvdXJjZS5maWxlbmFtZSlcblxuICAgIGlmIChjb250ZW50ID09PSB1bmRlZmluZWQpIHRocm93IG5ldyBUeXBlRXJyb3IoYFByZWZsaWdodGVkIGlPUyBzb3VyY2UgJyR7c291cmNlLmZpbGVuYW1lfScgbG9zdCBpdHMgY29udGVudC5gKVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGZpbGVuYW1lOiBzb3VyY2UuZmlsZW5hbWUsXG4gICAgICBpZDogc291cmNlLmlkLFxuICAgICAgbGFuZ3VhZ2U6IHNvdXJjZS5sYW5ndWFnZSxcbiAgICAgIG1vZHVsZUlkczogbW9kdWxlcy5maWx0ZXIobW9kdWxlID0+IG1vZHVsZS5zb3VyY2UuZmlsZW5hbWUgPT0gc291cmNlLmZpbGVuYW1lKS5tYXAoKHtpZH0pID0+IGlkKSxcbiAgICAgIG93bmVyc2hpcDogc291cmNlLm93bmVyc2hpcCA/PyBcImFwcGxpY2F0aW9uXCIsXG4gICAgICBzaGEyNTY6IGNyZWF0ZUhhc2goXCJzaGEyNTZcIikudXBkYXRlKGNvbnRlbnQpLmRpZ2VzdChcImhleFwiKVxuICAgIH1cbiAgfSlcbiAgY29uc3QgZW50cnlJZCA9IHByZXBhcmVkLnByb2dyYW0uZW50cnlNb2R1bGVcbiAgY29uc3QgZW50cnlBcnRpZmFjdCA9IC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAocHJlcGFyZWQubW9kdWxlUGF0aHMuZ2V0KGVudHJ5SWQpKVxuICBjb25zdCBlbnRyeU5hbWVzcGFjZSA9IGBTZW1hbnRpZm9sZE1vZHVsZSR7bW9kdWxlTmFtZShlbnRyeUlkKX1gXG5cbiAgcmV0dXJuIHtcbiAgICBlbnRyeToge1xuICAgICAgYXBwbGljYXRpb25BcnRpZmFjdDogYCR7cHJlcGFyZWQuY29uZmlndXJhdGlvbi5zb3VyY2VSb290fS9BcHBsaWNhdGlvbi9BcHAuc3dpZnRgLFxuICAgICAgYnJpZGdlQXJ0aWZhY3Q6IGAke3ByZXBhcmVkLmNvbmZpZ3VyYXRpb24uc291cmNlUm9vdH0vQXBwbGljYXRpb24vU2VtYW50aWZvbGRCcmlkZ2Uuc3dpZnRgLFxuICAgICAgZ2VuZXJhdGVkQXJ0aWZhY3Q6IGVudHJ5QXJ0aWZhY3QsXG4gICAgICBnZW5lcmF0ZWRGdW5jdGlvbklkZW50aXR5OiBgJHtlbnRyeU5hbWVzcGFjZX0uc2VtYW50aWZvbGRFbnRyeWAsXG4gICAgICBtb2R1bGVJZDogZW50cnlJZFxuICAgIH0sXG4gICAgbW9kdWxlcyxcbiAgICBzY2hlbWE6IFwiU2VtYW50aWZvbGRJb3NTZW1hbnRpY1Byb2dyYW1cIixcbiAgICBzb3VyY2VzLFxuICAgIHZlcnNpb246IDFcbiAgfVxufVxuXG4vKipcbiAqIERldGVybWluZXMgd2hldGhlciBvbmUgY2xvc2VkIHNlbWFudGljIG9yaWdpbiBjaXRlcyBhIHNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU2VtYW50aWNPcmlnaW59IG9yaWdpbiAtIE1hcHBlZCBvcmlnaW4uXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBPcmlnaW5hbCBjYWxsZXIgZmlsZW5hbWUuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUgc291cmNlIHBhcnRpY2lwYXRlcyBpbiB0aGUgb3JpZ2luLlxuICovXG5mdW5jdGlvbiBvcmlnaW5SZWZlcmVuY2VzRmlsZW5hbWUob3JpZ2luLCBmaWxlbmFtZSkge1xuICBpZiAob3JpZ2luLmtpbmQgPT0gXCJzb3VyY2VcIikgcmV0dXJuIG9yaWdpbi5sb2NhdGlvbi5maWxlbmFtZSA9PSBmaWxlbmFtZVxuICBpZiAob3JpZ2luLmtpbmQgPT0gXCJkZXJpdmVkXCIpIHJldHVybiBvcmlnaW4ub3JpZ2lucy5zb21lKCh7bG9jYXRpb259KSA9PiBsb2NhdGlvbi5maWxlbmFtZSA9PSBmaWxlbmFtZSlcblxuICByZXR1cm4gb3JpZ2luLnJlbGF0ZWRPcmlnaW5zLnNvbWUoKHtsb2NhdGlvbn0pID0+IGxvY2F0aW9uLmZpbGVuYW1lID09IGZpbGVuYW1lKVxufVxuXG4vKipcbiAqIEdyb3VwcyByZW5kZXJlci1yZWNvcmRlZCBjb25maWd1cmF0aW9uIHJhbmdlcyB3aXRob3V0IHNjYW5uaW5nIGdlbmVyYXRlZCB0ZXh0LlxuICogQHBhcmFtIHtDb25maWd1cmF0aW9uQXJ0aWZhY3RTcGFuW119IHNwYW5zIC0gQ2F1c2FsIGFydGlmYWN0IHNwYW5zLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpZWxkIC0gTm9ybWFsaXplZCBjb25maWd1cmF0aW9uIGZpZWxkLlxuICogQHJldHVybnMge3twYXRoOiBzdHJpbmcsIHJhbmdlczoge2VuZDogbnVtYmVyLCBzdGFydDogbnVtYmVyfVtdfVtdfSBTdGFibGUgb3V0cHV0IGNpdGF0aW9ucy5cbiAqL1xuZnVuY3Rpb24gY29uZmlndXJhdGlvbk91dHB1dENpdGF0aW9ucyhzcGFucywgZmllbGQpIHtcbiAgLyoqIEB0eXBlIHtNYXA8c3RyaW5nLCB7ZW5kOiBudW1iZXIsIHN0YXJ0OiBudW1iZXJ9W10+fSAqL1xuICBjb25zdCBieVBhdGggPSBuZXcgTWFwKClcblxuICBmb3IgKGNvbnN0IHNwYW4gb2Ygc3BhbnMpIHtcbiAgICBpZiAoc3Bhbi5maWVsZCAhPSBmaWVsZCkgY29udGludWVcbiAgICBjb25zdCByYW5nZXMgPSBieVBhdGguZ2V0KHNwYW4ucGF0aCkgPz8gW11cblxuICAgIHJhbmdlcy5wdXNoKHtlbmQ6IHNwYW4uZW5kLCBzdGFydDogc3Bhbi5zdGFydH0pXG4gICAgYnlQYXRoLnNldChzcGFuLnBhdGgsIHJhbmdlcylcbiAgfVxuXG4gIHJldHVybiBbLi4uYnlQYXRoXS5tYXAoKFtwYXRoLCByYW5nZXNdKSA9PiAoe3BhdGgsIHJhbmdlc30pKVxufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIHNoYXJlZCBjYXB0dXJlIHJ1bnRpbWUgYW5kIG1hcHBlZCBwZXItbW9kdWxlIHNlbWFudGljIFN3aWZ0LlxuICogQHBhcmFtIHtSZXR1cm5UeXBlPHR5cGVvZiBwcmVmbGlnaHRJb3NBcHBsaWNhdGlvbj59IHByZXBhcmVkIC0gRnVsbHkgcHJlZmxpZ2h0ZWQgYXBwbGljYXRpb24uXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuR2VuZXJhdGVkU2V0QXJ0aWZhY3RbXX0gT3JkZXJlZCBzZW1hbnRpYyBhcnRpZmFjdHMuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlclNlbWFudGljQXJ0aWZhY3RzKHByZXBhcmVkKSB7XG4gIGNvbnN0IHBhdGhzID0gcHJlcGFyZWQubW9kdWxlUGF0aHNcbiAgY29uc3QgZGVjbGFyYXRpb25zID0gbmV3IE1hcCgpXG5cbiAgZm9yIChjb25zdCBtb2R1bGUgb2YgcHJlcGFyZWQubW9kdWxlcykge1xuICAgIGZvciAoY29uc3QgZGVjbGFyYXRpb24gb2YgbW9kdWxlLmZ1bmN0aW9ucykgZGVjbGFyYXRpb25zLnNldChkZWNsYXJhdGlvbi5pZCwge1xuICAgICAgZGVjbGFyYXRpb24sXG4gICAgICBtb2R1bGVJZDogLyoqIEB0eXBlIHtzdHJpbmd9ICovIChSZWZsZWN0LmdldChtb2R1bGUsIFwiaWRcIikpXG4gICAgfSlcbiAgfVxuICAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkdlbmVyYXRlZFNldEFydGlmYWN0W119ICovXG4gIGNvbnN0IGFydGlmYWN0cyA9IFt7XG4gICAgY29udGVudDogaW9zU3dpZnRSdW50aW1lLFxuICAgIGNvbnRlbnRLaW5kOiBcInRleHRcIixcbiAgICBtZWRpYVR5cGU6IFwidGV4dC94LXN3aWZ0XCIsXG4gICAgb3duZXJzaGlwOiBcImdlbmVyYXRlZFwiLFxuICAgIHBhdGg6IFwiU291cmNlcy9HZW5lcmF0ZWQvU2VtYW50aWZvbGRSdW50aW1lLnN3aWZ0XCIsXG4gICAgcHJvdmVuYW5jZToge1xuICAgICAga2luZDogXCJzeW50aGV0aWNcIixcbiAgICAgIHJlYXNvbjogXCJTaGFyZWQgaU9TIGFwcGxpY2F0aW9uIG91dHB1dCBjYXB0dXJlIGFuZCBleGFjdCBTd2lmdCBzY2FsYXIgc3VwcG9ydC5cIixcbiAgICAgIHJlbGF0ZWRPcmlnaW5zOiBbXVxuICAgIH0sXG4gICAgcm9sZTogXCJzdXBwb3J0XCJcbiAgfV1cblxuICBmb3IgKGNvbnN0IG1vZHVsZSBvZiBwcmVwYXJlZC5tb2R1bGVzKSB7XG4gICAgY29uc3QgbW9kdWxlSWQgPSAvKiogQHR5cGUge3N0cmluZ30gKi8gKFJlZmxlY3QuZ2V0KG1vZHVsZSwgXCJpZFwiKSlcbiAgICBjb25zdCBmaWxlbmFtZSA9IC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAocGF0aHMuZ2V0KG1vZHVsZUlkKSlcbiAgICBjb25zdCB3cml0ZXIgPSBuZXcgU291cmNlV3JpdGVyKHtcbiAgICAgIGZpbGVuYW1lLFxuICAgICAgbGFuZ3VhZ2U6IFwic3dpZnRcIixcbiAgICAgIG1vZHVsZSxcbiAgICAgIHByb2dyYW06IHByZXBhcmVkLnByb2dyYW0sXG4gICAgICBwcm9ncmFtUGF0aHM6IHBhdGhzLFxuICAgICAgc291cmNlczogcHJlcGFyZWQuc291cmNlc1xuICAgIH0pXG5cbiAgICBlbWl0U2VtYW50aWNNb2R1bGUod3JpdGVyLCBtb2R1bGUsIG1vZHVsZUlkLCBtb2R1bGVJZCA9PSBwcmVwYXJlZC5wcm9ncmFtLmVudHJ5TW9kdWxlLCBkZWNsYXJhdGlvbnMpXG4gICAgY29uc3QgbWFwcGluZyA9IGZpbmFsaXplTWFwcGluZyh3cml0ZXIuZmluaXNoKCkpXG5cbiAgICBhcnRpZmFjdHMucHVzaCh7XG4gICAgICBjb250ZW50OiBtYXBwaW5nLmdlbmVyYXRlZC5jb250ZW50LFxuICAgICAgY29udGVudEtpbmQ6IFwidGV4dFwiLFxuICAgICAgbWVkaWFUeXBlOiBcInRleHQveC1zd2lmdFwiLFxuICAgICAgb3duZXJzaGlwOiBcImdlbmVyYXRlZFwiLFxuICAgICAgcGF0aDogZmlsZW5hbWUsXG4gICAgICBwcm92ZW5hbmNlOiB7a2luZDogXCJ0ZXh0XCIsIG1hcHBpbmcsIHNvdXJjZU1hcDogdG9Tb3VyY2VNYXBWMyhtYXBwaW5nKSwgc291cmNlTWFwRmlsZW5hbWU6IGAke2ZpbGVuYW1lfS5tYXBgfSxcbiAgICAgIHJvbGU6IFwic291cmNlXCJcbiAgICB9KVxuICB9XG5cbiAgcmV0dXJuIGFydGlmYWN0c1xufVxuXG4vKipcbiAqIFByb2R1Y2VzIGFsbCBwcm9qZWN0IHBhdGhzIHJlZmVyZW5jZWQgYnkgdGhlIFhjb2RlIG1vZGVsLlxuICogQHBhcmFtIHtSZXR1cm5UeXBlPHR5cGVvZiBwcmVmbGlnaHRJb3NBcHBsaWNhdGlvbj59IHByZXBhcmVkIC0gUHJlcGFyZWQgYXBwbGljYXRpb24uXG4gKiBAcmV0dXJucyB7e2FwcFNvdXJjZXM6IHN0cmluZ1tdLCBhc3NldHM6IHN0cmluZ1tdLCBpbmZvUGxpc3Q6IHN0cmluZywgdW5pdFRlc3Q6IHN0cmluZywgdWlUZXN0OiBzdHJpbmcsIHhjY29uZmlnOiBzdHJpbmd9fSBQYXRocy5cbiAqL1xuZnVuY3Rpb24gYXBwbGljYXRpb25BcnRpZmFjdFBhdGhzKHByZXBhcmVkKSB7XG4gIGNvbnN0IHtwcm9kdWN0TmFtZTogcHJvZHVjdCwgcmVzb3VyY2VSb290LCBzb3VyY2VSb290fSA9IHByZXBhcmVkLmNvbmZpZ3VyYXRpb25cblxuICByZXR1cm4ge1xuICAgIGFwcFNvdXJjZXM6IFtcbiAgICAgIGAke3NvdXJjZVJvb3R9L0dlbmVyYXRlZC9TZW1hbnRpZm9sZFJ1bnRpbWUuc3dpZnRgLFxuICAgICAgLi4ucHJlcGFyZWQubW9kdWxlUGF0aHMudmFsdWVzKCksXG4gICAgICBgJHtzb3VyY2VSb290fS9BcHBsaWNhdGlvbi9BcHAuc3dpZnRgLFxuICAgICAgYCR7c291cmNlUm9vdH0vQXBwbGljYXRpb24vU2VtYW50aWZvbGRCcmlkZ2Uuc3dpZnRgLFxuICAgICAgYCR7c291cmNlUm9vdH0vQXBwbGljYXRpb24vU2VtYW50aWZvbGRPdXRwdXRWaWV3LnN3aWZ0YFxuICAgIF0sXG4gICAgYXNzZXRzOiBbcmVzb3VyY2VSb290LCAuLi5wcmVwYXJlZC5hc3NldHMubWFwKCh7cGF0aH0pID0+IHBhdGgpXSxcbiAgICBpbmZvUGxpc3Q6IFwiQ29uZmlndXJhdGlvbi9JbmZvLnBsaXN0XCIsXG4gICAgdW5pdFRlc3Q6IGBUZXN0cy8ke3Byb2R1Y3R9VGVzdHMuc3dpZnRgLFxuICAgIHVpVGVzdDogYFVJVGVzdHMvJHtwcm9kdWN0fVVJVGVzdHMuc3dpZnRgLFxuICAgIHhjY29uZmlnOiBcIkNvbmZpZ3VyYXRpb24vQmFzZS54Y2NvbmZpZ1wiXG4gIH1cbn1cblxuLyoqXG4gKiBEZXJpdmVzIGNvbGxpc2lvbi1jaGVja2VkIHVwcGVyY2FzZSAyNC1oZXggWGNvZGUgb2JqZWN0IElEcyBmcm9tIG5vcm1hbGl6ZWQgaWRlbnRpdGllcy5cbiAqIEBwYXJhbSB7cmVhZG9ubHkgc3RyaW5nW119IGlkZW50aXRpZXMgLSBDb21wbGV0ZSBvcmRlcmVkIG9iamVjdCBpZGVudGl0aWVzLlxuICogQHBhcmFtIHsoaWRlbnRpdHk6IHN0cmluZykgPT4gc3RyaW5nfSBbZGlnZXN0XSAtIFRlc3Qtb25seSBkaWdlc3Qgc2VhbTsgcHJvZHVjdGlvbiB1c2VzIGJ1aWx0LWluIFNIQS0yNTYuXG4gKiBAcmV0dXJucyB7TWFwPHN0cmluZywgc3RyaW5nPn0gT2JqZWN0IElEIGJ5IGZ1bGwgaW5wdXQgaWRlbnRpdHkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhbGxvY2F0ZVhjb2RlT2JqZWN0SWRzKGlkZW50aXRpZXMsIGRpZ2VzdCA9IGlkZW50aXR5ID0+IGNyZWF0ZUhhc2goXCJzaGEyNTZcIikudXBkYXRlKGlkZW50aXR5KS5kaWdlc3QoXCJoZXhcIikpIHtcbiAgY29uc3QgcmVzdWx0ID0gbmV3IE1hcCgpXG4gIGNvbnN0IGZ1bGxJZGVudGl0aWVzID0gbmV3IE1hcCgpXG5cbiAgZm9yIChjb25zdCBpZGVudGl0eSBvZiBpZGVudGl0aWVzKSB7XG4gICAgaWYgKHR5cGVvZiBpZGVudGl0eSAhPSBcInN0cmluZ1wiIHx8IGlkZW50aXR5Lmxlbmd0aCA9PSAwIHx8IHJlc3VsdC5oYXMoaWRlbnRpdHkpKSB7XG4gICAgICB0aHJvdyBuZXcgU2VtYW50aWZvbGREaWFnbm9zdGljKHtjb2RlOiBcIlhDT0RFX0lEX0NPTExJU0lPTlwiLCBsYW5ndWFnZTogXCJpb3NcIixcbiAgICAgICAgbWVzc2FnZTogXCJYY29kZSBvYmplY3QgaWRlbnRpdGllcyBtdXN0IGJlIHVuaXF1ZSBub24tZW1wdHkgc3RyaW5ncy5cIn0pXG4gICAgfVxuICAgIGNvbnN0IG5vcm1hbGl6ZWQgPSBpZGVudGl0eS5ub3JtYWxpemUoXCJORkNcIilcbiAgICBjb25zdCBmdWxsRGlnZXN0ID0gZGlnZXN0KG5vcm1hbGl6ZWQpXG5cbiAgICBpZiAoIS9eWzAtOWEtZkEtRl17NjR9JC91LnRlc3QoZnVsbERpZ2VzdCkpIHtcbiAgICAgIHRocm93IG5ldyBTZW1hbnRpZm9sZERpYWdub3N0aWMoe2NvZGU6IFwiWENPREVfSURfQ09MTElTSU9OXCIsIGxhbmd1YWdlOiBcImlvc1wiLFxuICAgICAgICBtZXNzYWdlOiBgWGNvZGUgb2JqZWN0IGlkZW50aXR5ICcke2lkZW50aXR5fScgZGlkIG5vdCBwcm9kdWNlIGEgZnVsbCBTSEEtMjU2IGRpZ2VzdC5gfSlcbiAgICB9XG4gICAgY29uc3Qgb2JqZWN0SWQgPSBmdWxsRGlnZXN0LnNsaWNlKDAsIDI0KS50b1VwcGVyQ2FzZSgpXG4gICAgY29uc3QgcHJldmlvdXMgPSBmdWxsSWRlbnRpdGllcy5nZXQob2JqZWN0SWQpXG5cbiAgICBpZiAocHJldmlvdXMgIT09IHVuZGVmaW5lZCAmJiBwcmV2aW91cyAhPSBub3JtYWxpemVkKSB7XG4gICAgICB0aHJvdyBuZXcgU2VtYW50aWZvbGREaWFnbm9zdGljKHtjb2RlOiBcIlhDT0RFX0lEX0NPTExJU0lPTlwiLCBsYW5ndWFnZTogXCJpb3NcIixcbiAgICAgICAgbWVzc2FnZTogYFhjb2RlIG9iamVjdCBpZGVudGl0aWVzICcke3ByZXZpb3VzfScgYW5kICcke25vcm1hbGl6ZWR9JyBjb2xsaWRlIGF0ICcke29iamVjdElkfScuYH0pXG4gICAgfVxuICAgIGZ1bGxJZGVudGl0aWVzLnNldChvYmplY3RJZCwgbm9ybWFsaXplZClcbiAgICByZXN1bHQuc2V0KGlkZW50aXR5LCBvYmplY3RJZClcbiAgfVxuXG4gIHJldHVybiByZXN1bHRcbn1cblxuLyoqXG4gKiBSZW5kZXJzIHRoZSBzbWFsbGVzdCBkZXRlcm1pbmlzdGljIFhjb2RlIGFwcGxpY2F0aW9uL3VuaXQvVUktdGVzdCBwcm9qZWN0IG1vZGVsLlxuICogUGxhdGZvcm0gZXhlY3V0aW9uIHJlbWFpbnMgZGVmZXJyZWQgdW50aWwgdGhlIHJlcG9zaXRvcnkgaGFzIGEgcXVhbGlmaWVkIEFwcGxlIGxhbmUuXG4gKiBAcGFyYW0ge1JldHVyblR5cGU8dHlwZW9mIHByZWZsaWdodElvc0FwcGxpY2F0aW9uPn0gcHJlcGFyZWQgLSBQcmVwYXJlZCBhcHBsaWNhdGlvbi5cbiAqIEBwYXJhbSB7UmV0dXJuVHlwZTx0eXBlb2YgYXBwbGljYXRpb25BcnRpZmFjdFBhdGhzPn0gcGF0aHMgLSBDb21wbGV0ZSBvd25lZCBwYXRocy5cbiAqIEByZXR1cm5zIHtSZW5kZXJlZENvbmZpZ3VyYXRpb25UZXh0fSBDYW5vbmljYWwgTEYgcHJvamVjdCBmaWxlIGFuZCBjYXVzYWwgY29uZmlndXJhdGlvbiBzcGFucy5cbiAqL1xuZnVuY3Rpb24gcmVuZGVyUGJ4UHJvamVjdChwcmVwYXJlZCwgcGF0aHMpIHtcbiAgY29uc3QgY29uZmlndXJhdGlvbiA9IHByZXBhcmVkLmNvbmZpZ3VyYXRpb25cbiAgY29uc3QgcHJvZHVjdCA9IGNvbmZpZ3VyYXRpb24ucHJvZHVjdE5hbWVcbiAgY29uc3QgcmVzb3VyY2VSb290ID0gY29uZmlndXJhdGlvbi5yZXNvdXJjZVJvb3RcbiAgY29uc3Qgc291cmNlUm9vdCA9IGNvbmZpZ3VyYXRpb24uc291cmNlUm9vdFxuICBjb25zdCBpZGVudGl0aWVzID0gW1xuICAgIFwicHJvamVjdFwiLCBcImdyb3VwOm1haW5cIiwgXCJncm91cDpzb3VyY2VzXCIsIFwiZ3JvdXA6Z2VuZXJhdGVkXCIsIFwiZ3JvdXA6YXBwbGljYXRpb25cIiwgXCJncm91cDpjb25maWd1cmF0aW9uXCIsXG4gICAgXCJncm91cDp0ZXN0c1wiLCBcImdyb3VwOnVpdGVzdHNcIiwgXCJncm91cDpwcm9kdWN0c1wiLCBcInRhcmdldDphcHBcIiwgXCJ0YXJnZXQ6dGVzdHNcIiwgXCJ0YXJnZXQ6dWl0ZXN0c1wiLFxuICAgIFwicGhhc2U6YXBwOnNvdXJjZXNcIiwgXCJwaGFzZTphcHA6cmVzb3VyY2VzXCIsIFwicGhhc2U6YXBwOmZyYW1ld29ya3NcIiwgXCJwaGFzZTp0ZXN0czpzb3VyY2VzXCIsIFwicGhhc2U6dGVzdHM6cmVzb3VyY2VzXCIsXG4gICAgXCJwaGFzZTp0ZXN0czpmcmFtZXdvcmtzXCIsIFwicGhhc2U6dWl0ZXN0czpzb3VyY2VzXCIsIFwicGhhc2U6dWl0ZXN0czpyZXNvdXJjZXNcIiwgXCJwaGFzZTp1aXRlc3RzOmZyYW1ld29ya3NcIixcbiAgICBcInByb2R1Y3Q6YXBwXCIsIFwicHJvZHVjdDp0ZXN0c1wiLCBcInByb2R1Y3Q6dWl0ZXN0c1wiLCBcInByb3h5OnRlc3RzOmFwcFwiLCBcInByb3h5OnVpdGVzdHM6YXBwXCIsXG4gICAgXCJkZXBlbmRlbmN5OnRlc3RzOmFwcFwiLCBcImRlcGVuZGVuY3k6dWl0ZXN0czphcHBcIixcbiAgICBcImNvbmZpZy1saXN0OnByb2plY3RcIiwgXCJjb25maWctbGlzdDphcHBcIiwgXCJjb25maWctbGlzdDp0ZXN0c1wiLCBcImNvbmZpZy1saXN0OnVpdGVzdHNcIixcbiAgICBcImNvbmZpZzpwcm9qZWN0OmRlYnVnXCIsIFwiY29uZmlnOnByb2plY3Q6cmVsZWFzZVwiLCBcImNvbmZpZzphcHA6ZGVidWdcIiwgXCJjb25maWc6YXBwOnJlbGVhc2VcIixcbiAgICBcImNvbmZpZzp0ZXN0czpkZWJ1Z1wiLCBcImNvbmZpZzp0ZXN0czpyZWxlYXNlXCIsIFwiY29uZmlnOnVpdGVzdHM6ZGVidWdcIiwgXCJjb25maWc6dWl0ZXN0czpyZWxlYXNlXCIsXG4gICAgYGZpbGU6JHtwYXRocy54Y2NvbmZpZ31gLCBgZmlsZToke3BhdGhzLmluZm9QbGlzdH1gLCBgZmlsZToke3Jlc291cmNlUm9vdH1gLFxuICAgIGBmaWxlOiR7cGF0aHMudW5pdFRlc3R9YCwgYGZpbGU6JHtwYXRocy51aVRlc3R9YCxcbiAgICAuLi5wYXRocy5hcHBTb3VyY2VzLmZsYXRNYXAocGF0aCA9PiBbYGZpbGU6JHtwYXRofWAsIGBidWlsZDphcHA6JHtwYXRofWBdKSxcbiAgICBgYnVpbGQ6YXBwOiR7cmVzb3VyY2VSb290fWAsIGBidWlsZDp0ZXN0czoke3BhdGhzLnVuaXRUZXN0fWAsIGBidWlsZDp1aXRlc3RzOiR7cGF0aHMudWlUZXN0fWBcbiAgXVxuICBjb25zdCBpZHMgPSBhbGxvY2F0ZVhjb2RlT2JqZWN0SWRzKGlkZW50aXRpZXMpXG4gIC8qKlxuICAgKiBMb29rcyB1cCBvbmUgcGxhbm5lZCBYY29kZSBpZGVudGl0eS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGlkZW50aXR5IC0gUGxhbm5lZCBpZGVudGl0eS5cbiAgICogQHJldHVybnMge3N0cmluZ30gQWxsb2NhdGVkIG9iamVjdCBJRC5cbiAgICovXG4gIGNvbnN0IGlkID0gaWRlbnRpdHkgPT4ge1xuICAgIGNvbnN0IHZhbHVlID0gaWRzLmdldChpZGVudGl0eSlcblxuICAgIGlmICghdmFsdWUpIHRocm93IG5ldyBUeXBlRXJyb3IoYE1pc3NpbmcgcGxhbm5lZCBYY29kZSBpZGVudGl0eSAnJHtpZGVudGl0eX0nLmApXG5cbiAgICByZXR1cm4gdmFsdWVcbiAgfVxuICAvKiogQHR5cGUge01hcDxzdHJpbmcsIHtpZGVudGl0eTogc3RyaW5nLCBib2R5OiBDb25maWd1cmF0aW9uTGluZVtdfVtdPn0gKi9cbiAgY29uc3Qgc2VjdGlvbnMgPSBuZXcgTWFwKClcbiAgLyoqXG4gICAqIEFkZHMgYW4gb2JqZWN0IHRvIG9uZSBQQlggc2VjdGlvbi5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHNlY3Rpb24gLSBQQlggc2VjdGlvbi5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGlkZW50aXR5IC0gT2JqZWN0IGlkZW50aXR5LlxuICAgKiBAcGFyYW0ge0NvbmZpZ3VyYXRpb25MaW5lW119IGJvZHkgLSBPYmplY3QgZmllbGRzLlxuICAgKi9cbiAgY29uc3QgYWRkID0gKHNlY3Rpb24sIGlkZW50aXR5LCBib2R5KSA9PiB7XG4gICAgY29uc3QgZW50cmllcyA9IHNlY3Rpb25zLmdldChzZWN0aW9uKSA/PyBbXVxuXG4gICAgZW50cmllcy5wdXNoKHtib2R5LCBpZGVudGl0eX0pXG4gICAgc2VjdGlvbnMuc2V0KHNlY3Rpb24sIGVudHJpZXMpXG4gIH1cbiAgLyoqXG4gICAqIFJlbmRlcnMgUEJYIGxpc3QgdmFsdWVzLlxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSB2YWx1ZXMgLSBQQlggbGlzdCB2YWx1ZXMuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFJlbmRlcmVkIGxpc3QgYm9keS5cbiAgICovXG4gIGNvbnN0IGxpc3QgPSB2YWx1ZXMgPT4gdmFsdWVzLm1hcCh2YWx1ZSA9PiBgXFx0XFx0XFx0XFx0JHt2YWx1ZX0sYCkuam9pbihcIlxcblwiKVxuICAvKipcbiAgICogUHJvZHVjZXMgYSBzdGFibGUgc29ydGVkIGNvcHkuXG4gICAqIEBwYXJhbSB7c3RyaW5nW119IHZhbHVlcyAtIFZhbHVlcyB0byBzb3J0LlxuICAgKiBAcmV0dXJucyB7c3RyaW5nW119IFN0YWJsZSBzb3J0ZWQgY29weS5cbiAgICovXG4gIGNvbnN0IHNvcnRlZCA9IHZhbHVlcyA9PiBbLi4udmFsdWVzXS5zb3J0KChsZWZ0LCByaWdodCkgPT4gbGVmdCA8IHJpZ2h0ID8gLTEgOiBsZWZ0ID4gcmlnaHQgPyAxIDogMClcblxuICBmb3IgKGNvbnN0IHBhdGggb2YgcGF0aHMuYXBwU291cmNlcykge1xuICAgIGFkZChcIlBCWEJ1aWxkRmlsZVwiLCBgYnVpbGQ6YXBwOiR7cGF0aH1gLCBbXCJpc2EgPSBQQlhCdWlsZEZpbGU7XCIsIGBmaWxlUmVmID0gJHtpZChgZmlsZToke3BhdGh9YCl9O2BdKVxuICAgIGFkZChcIlBCWEZpbGVSZWZlcmVuY2VcIiwgYGZpbGU6JHtwYXRofWAsIFtcImlzYSA9IFBCWEZpbGVSZWZlcmVuY2U7XCIsIFwibGFzdEtub3duRmlsZVR5cGUgPSBzb3VyY2Vjb2RlLnN3aWZ0O1wiLFxuICAgICAgW1wicGF0aCA9IFwiLCAuLi5wYnhDb25maWd1cmF0aW9uUGF0aChjb25maWd1cmF0aW9uLCBwYXRoKSwgXCI7XCJdLCBcInNvdXJjZVRyZWUgPSBTT1VSQ0VfUk9PVDtcIl0pXG4gIH1cbiAgYWRkKFwiUEJYQnVpbGRGaWxlXCIsIGBidWlsZDphcHA6JHtyZXNvdXJjZVJvb3R9YCwgW1wiaXNhID0gUEJYQnVpbGRGaWxlO1wiLCBgZmlsZVJlZiA9ICR7aWQoYGZpbGU6JHtyZXNvdXJjZVJvb3R9YCl9O2BdKVxuICBhZGQoXCJQQlhCdWlsZEZpbGVcIiwgYGJ1aWxkOnRlc3RzOiR7cGF0aHMudW5pdFRlc3R9YCwgW1wiaXNhID0gUEJYQnVpbGRGaWxlO1wiLCBgZmlsZVJlZiA9ICR7aWQoYGZpbGU6JHtwYXRocy51bml0VGVzdH1gKX07YF0pXG4gIGFkZChcIlBCWEJ1aWxkRmlsZVwiLCBgYnVpbGQ6dWl0ZXN0czoke3BhdGhzLnVpVGVzdH1gLCBbXCJpc2EgPSBQQlhCdWlsZEZpbGU7XCIsIGBmaWxlUmVmID0gJHtpZChgZmlsZToke3BhdGhzLnVpVGVzdH1gKX07YF0pXG4gIGFkZChcIlBCWENvbnRhaW5lckl0ZW1Qcm94eVwiLCBcInByb3h5OnRlc3RzOmFwcFwiLCBbXCJpc2EgPSBQQlhDb250YWluZXJJdGVtUHJveHk7XCIsIGBjb250YWluZXJQb3J0YWwgPSAke2lkKFwicHJvamVjdFwiKX07YCxcbiAgICBcInByb3h5VHlwZSA9IDE7XCIsIGByZW1vdGVHbG9iYWxJRFN0cmluZyA9ICR7aWQoXCJ0YXJnZXQ6YXBwXCIpfTtgLFxuICAgIFtcInJlbW90ZUluZm8gPSBcXFwiXCIsIGNvbmZpZ3VyYXRpb25GcmFnbWVudChcInByb2R1Y3ROYW1lXCIsIHByb2R1Y3QpLCBcIlxcXCI7XCJdXSlcbiAgYWRkKFwiUEJYQ29udGFpbmVySXRlbVByb3h5XCIsIFwicHJveHk6dWl0ZXN0czphcHBcIiwgW1wiaXNhID0gUEJYQ29udGFpbmVySXRlbVByb3h5O1wiLCBgY29udGFpbmVyUG9ydGFsID0gJHtpZChcInByb2plY3RcIil9O2AsXG4gICAgXCJwcm94eVR5cGUgPSAxO1wiLCBgcmVtb3RlR2xvYmFsSURTdHJpbmcgPSAke2lkKFwidGFyZ2V0OmFwcFwiKX07YCxcbiAgICBbXCJyZW1vdGVJbmZvID0gXFxcIlwiLCBjb25maWd1cmF0aW9uRnJhZ21lbnQoXCJwcm9kdWN0TmFtZVwiLCBwcm9kdWN0KSwgXCJcXFwiO1wiXV0pXG4gIGFkZChcIlBCWEZpbGVSZWZlcmVuY2VcIiwgYGZpbGU6JHtwYXRocy54Y2NvbmZpZ31gLCBbXCJpc2EgPSBQQlhGaWxlUmVmZXJlbmNlO1wiLCBcImxhc3RLbm93bkZpbGVUeXBlID0gdGV4dC54Y2NvbmZpZztcIixcbiAgICBgcGF0aCA9ICR7cGJ4U3RyaW5nKHBhdGhzLnhjY29uZmlnKX07YCwgXCJzb3VyY2VUcmVlID0gU09VUkNFX1JPT1Q7XCJdKVxuICBhZGQoXCJQQlhGaWxlUmVmZXJlbmNlXCIsIGBmaWxlOiR7cGF0aHMuaW5mb1BsaXN0fWAsIFtcImlzYSA9IFBCWEZpbGVSZWZlcmVuY2U7XCIsIFwibGFzdEtub3duRmlsZVR5cGUgPSB0ZXh0LnBsaXN0LnhtbDtcIixcbiAgICBgcGF0aCA9ICR7cGJ4U3RyaW5nKHBhdGhzLmluZm9QbGlzdCl9O2AsIFwic291cmNlVHJlZSA9IFNPVVJDRV9ST09UO1wiXSlcbiAgYWRkKFwiUEJYRmlsZVJlZmVyZW5jZVwiLCBgZmlsZToke3Jlc291cmNlUm9vdH1gLCBbXCJpc2EgPSBQQlhGaWxlUmVmZXJlbmNlO1wiLCBcImxhc3RLbm93bkZpbGVUeXBlID0gZm9sZGVyLmFzc2V0Y2F0YWxvZztcIixcbiAgICBbXCJwYXRoID0gXCIsIGNvbmZpZ3VyYXRpb25GcmFnbWVudChcInJlc291cmNlUm9vdFwiLCByZXNvdXJjZVJvb3QpLCBcIjtcIl0sIFwic291cmNlVHJlZSA9IFNPVVJDRV9ST09UO1wiXSlcbiAgYWRkKFwiUEJYRmlsZVJlZmVyZW5jZVwiLCBgZmlsZToke3BhdGhzLnVuaXRUZXN0fWAsIFtcImlzYSA9IFBCWEZpbGVSZWZlcmVuY2U7XCIsIFwibGFzdEtub3duRmlsZVR5cGUgPSBzb3VyY2Vjb2RlLnN3aWZ0O1wiLFxuICAgIFtcInBhdGggPSBcIiwgLi4ucGJ4Q29uZmlndXJhdGlvblBhdGgoY29uZmlndXJhdGlvbiwgcGF0aHMudW5pdFRlc3QpLCBcIjtcIl0sIFwic291cmNlVHJlZSA9IFNPVVJDRV9ST09UO1wiXSlcbiAgYWRkKFwiUEJYRmlsZVJlZmVyZW5jZVwiLCBgZmlsZToke3BhdGhzLnVpVGVzdH1gLCBbXCJpc2EgPSBQQlhGaWxlUmVmZXJlbmNlO1wiLCBcImxhc3RLbm93bkZpbGVUeXBlID0gc291cmNlY29kZS5zd2lmdDtcIixcbiAgICBbXCJwYXRoID0gXCIsIC4uLnBieENvbmZpZ3VyYXRpb25QYXRoKGNvbmZpZ3VyYXRpb24sIHBhdGhzLnVpVGVzdCksIFwiO1wiXSwgXCJzb3VyY2VUcmVlID0gU09VUkNFX1JPT1Q7XCJdKVxuICBhZGQoXCJQQlhGaWxlUmVmZXJlbmNlXCIsIFwicHJvZHVjdDphcHBcIiwgW1wiaXNhID0gUEJYRmlsZVJlZmVyZW5jZTtcIiwgXCJleHBsaWNpdEZpbGVUeXBlID0gd3JhcHBlci5hcHBsaWNhdGlvbjtcIiwgXCJpbmNsdWRlSW5JbmRleCA9IDA7XCIsXG4gICAgW1wicGF0aCA9IFxcXCJcIiwgY29uZmlndXJhdGlvbkZyYWdtZW50KFwicHJvZHVjdE5hbWVcIiwgcHJvZHVjdCksIFwiLmFwcFxcXCI7XCJdLCBcInNvdXJjZVRyZWUgPSBCVUlMVF9QUk9EVUNUU19ESVI7XCJdKVxuICBhZGQoXCJQQlhGaWxlUmVmZXJlbmNlXCIsIFwicHJvZHVjdDp0ZXN0c1wiLCBbXCJpc2EgPSBQQlhGaWxlUmVmZXJlbmNlO1wiLCBcImV4cGxpY2l0RmlsZVR5cGUgPSB3cmFwcGVyLmNmYnVuZGxlO1wiLCBcImluY2x1ZGVJbkluZGV4ID0gMDtcIixcbiAgICBbXCJwYXRoID0gXFxcIlwiLCBjb25maWd1cmF0aW9uRnJhZ21lbnQoXCJwcm9kdWN0TmFtZVwiLCBwcm9kdWN0KSwgXCJUZXN0cy54Y3Rlc3RcXFwiO1wiXSwgXCJzb3VyY2VUcmVlID0gQlVJTFRfUFJPRFVDVFNfRElSO1wiXSlcbiAgYWRkKFwiUEJYRmlsZVJlZmVyZW5jZVwiLCBcInByb2R1Y3Q6dWl0ZXN0c1wiLCBbXCJpc2EgPSBQQlhGaWxlUmVmZXJlbmNlO1wiLCBcImV4cGxpY2l0RmlsZVR5cGUgPSB3cmFwcGVyLmNmYnVuZGxlO1wiLCBcImluY2x1ZGVJbkluZGV4ID0gMDtcIixcbiAgICBbXCJwYXRoID0gXFxcIlwiLCBjb25maWd1cmF0aW9uRnJhZ21lbnQoXCJwcm9kdWN0TmFtZVwiLCBwcm9kdWN0KSwgXCJVSVRlc3RzLnhjdGVzdFxcXCI7XCJdLCBcInNvdXJjZVRyZWUgPSBCVUlMVF9QUk9EVUNUU19ESVI7XCJdKVxuXG4gIGNvbnN0IGdlbmVyYXRlZFJlZnMgPSBzb3J0ZWQocGF0aHMuYXBwU291cmNlcy5maWx0ZXIocGF0aCA9PiBwYXRoLnN0YXJ0c1dpdGgoYCR7c291cmNlUm9vdH0vR2VuZXJhdGVkL2ApKSkubWFwKHBhdGggPT4gaWQoYGZpbGU6JHtwYXRofWApKVxuICBjb25zdCBhcHBsaWNhdGlvblJlZnMgPSBzb3J0ZWQocGF0aHMuYXBwU291cmNlcy5maWx0ZXIocGF0aCA9PiBwYXRoLnN0YXJ0c1dpdGgoYCR7c291cmNlUm9vdH0vQXBwbGljYXRpb24vYCkpKS5tYXAocGF0aCA9PiBpZChgZmlsZToke3BhdGh9YCkpXG5cbiAgYWRkKFwiUEJYR3JvdXBcIiwgXCJncm91cDptYWluXCIsIFtcImlzYSA9IFBCWEdyb3VwO1wiLCBgY2hpbGRyZW4gPSAoXFxuJHtsaXN0KFtcbiAgICBpZChcImdyb3VwOmNvbmZpZ3VyYXRpb25cIiksIGlkKFwiZ3JvdXA6c291cmNlc1wiKSwgaWQoYGZpbGU6JHtyZXNvdXJjZVJvb3R9YCksIGlkKFwiZ3JvdXA6dGVzdHNcIiksIGlkKFwiZ3JvdXA6dWl0ZXN0c1wiKSxcbiAgICBpZChcImdyb3VwOnByb2R1Y3RzXCIpXG4gIF0pfVxcblxcdFxcdFxcdCk7YCwgXCJzb3VyY2VUcmVlID0gXFxcIjxncm91cD5cXFwiO1wiXSlcbiAgYWRkKFwiUEJYR3JvdXBcIiwgXCJncm91cDpzb3VyY2VzXCIsIFtcImlzYSA9IFBCWEdyb3VwO1wiLCBgY2hpbGRyZW4gPSAoXFxuJHtsaXN0KFtpZChcImdyb3VwOmFwcGxpY2F0aW9uXCIpLCBpZChcImdyb3VwOmdlbmVyYXRlZFwiKV0pfVxcblxcdFxcdFxcdCk7YCxcbiAgICBbXCJuYW1lID0gXCIsIGNvbmZpZ3VyYXRpb25GcmFnbWVudChcInNvdXJjZVJvb3RcIiwgc291cmNlUm9vdCksIFwiO1wiXSwgXCJzb3VyY2VUcmVlID0gXFxcIjxncm91cD5cXFwiO1wiXSlcbiAgYWRkKFwiUEJYR3JvdXBcIiwgXCJncm91cDpnZW5lcmF0ZWRcIiwgW1wiaXNhID0gUEJYR3JvdXA7XCIsIGBjaGlsZHJlbiA9IChcXG4ke2xpc3QoZ2VuZXJhdGVkUmVmcyl9XFxuXFx0XFx0XFx0KTtgLFxuICAgIFwibmFtZSA9IEdlbmVyYXRlZDtcIiwgXCJzb3VyY2VUcmVlID0gXFxcIjxncm91cD5cXFwiO1wiXSlcbiAgYWRkKFwiUEJYR3JvdXBcIiwgXCJncm91cDphcHBsaWNhdGlvblwiLCBbXCJpc2EgPSBQQlhHcm91cDtcIiwgYGNoaWxkcmVuID0gKFxcbiR7bGlzdChhcHBsaWNhdGlvblJlZnMpfVxcblxcdFxcdFxcdCk7YCxcbiAgICBcIm5hbWUgPSBBcHBsaWNhdGlvbjtcIiwgXCJzb3VyY2VUcmVlID0gXFxcIjxncm91cD5cXFwiO1wiXSlcbiAgYWRkKFwiUEJYR3JvdXBcIiwgXCJncm91cDpjb25maWd1cmF0aW9uXCIsIFtcImlzYSA9IFBCWEdyb3VwO1wiLCBgY2hpbGRyZW4gPSAoXFxuJHtsaXN0KFtpZChgZmlsZToke3BhdGhzLnhjY29uZmlnfWApLCBpZChgZmlsZToke3BhdGhzLmluZm9QbGlzdH1gKV0pfVxcblxcdFxcdFxcdCk7YCxcbiAgICBcIm5hbWUgPSBDb25maWd1cmF0aW9uO1wiLCBcInNvdXJjZVRyZWUgPSBcXFwiPGdyb3VwPlxcXCI7XCJdKVxuICBhZGQoXCJQQlhHcm91cFwiLCBcImdyb3VwOnRlc3RzXCIsIFtcImlzYSA9IFBCWEdyb3VwO1wiLCBgY2hpbGRyZW4gPSAoXFxuJHtsaXN0KFtpZChgZmlsZToke3BhdGhzLnVuaXRUZXN0fWApXSl9XFxuXFx0XFx0XFx0KTtgLFxuICAgIFwibmFtZSA9IFRlc3RzO1wiLCBcInNvdXJjZVRyZWUgPSBcXFwiPGdyb3VwPlxcXCI7XCJdKVxuICBhZGQoXCJQQlhHcm91cFwiLCBcImdyb3VwOnVpdGVzdHNcIiwgW1wiaXNhID0gUEJYR3JvdXA7XCIsIGBjaGlsZHJlbiA9IChcXG4ke2xpc3QoW2lkKGBmaWxlOiR7cGF0aHMudWlUZXN0fWApXSl9XFxuXFx0XFx0XFx0KTtgLFxuICAgIFwibmFtZSA9IFVJVGVzdHM7XCIsIFwic291cmNlVHJlZSA9IFxcXCI8Z3JvdXA+XFxcIjtcIl0pXG4gIGFkZChcIlBCWEdyb3VwXCIsIFwiZ3JvdXA6cHJvZHVjdHNcIiwgW1wiaXNhID0gUEJYR3JvdXA7XCIsIGBjaGlsZHJlbiA9IChcXG4ke2xpc3QoW2lkKFwicHJvZHVjdDphcHBcIiksIGlkKFwicHJvZHVjdDp0ZXN0c1wiKSwgaWQoXCJwcm9kdWN0OnVpdGVzdHNcIildKX1cXG5cXHRcXHRcXHQpO2AsXG4gICAgXCJuYW1lID0gUHJvZHVjdHM7XCIsIFwic291cmNlVHJlZSA9IFxcXCI8Z3JvdXA+XFxcIjtcIl0pXG5cbiAgYWRkTmF0aXZlVGFyZ2V0KGFkZCwgaWQsIGNvbmZpZ3VyYXRpb24sIFwidGFyZ2V0OmFwcFwiLCBcIlwiLCBcImNvbS5hcHBsZS5wcm9kdWN0LXR5cGUuYXBwbGljYXRpb25cIiwgXCJwcm9kdWN0OmFwcFwiLFxuICAgIFwiY29uZmlnLWxpc3Q6YXBwXCIsIFtcInBoYXNlOmFwcDpzb3VyY2VzXCIsIFwicGhhc2U6YXBwOmZyYW1ld29ya3NcIiwgXCJwaGFzZTphcHA6cmVzb3VyY2VzXCJdLCBbXSlcbiAgYWRkTmF0aXZlVGFyZ2V0KGFkZCwgaWQsIGNvbmZpZ3VyYXRpb24sIFwidGFyZ2V0OnRlc3RzXCIsIFwiVGVzdHNcIiwgXCJjb20uYXBwbGUucHJvZHVjdC10eXBlLmJ1bmRsZS51bml0LXRlc3RcIiwgXCJwcm9kdWN0OnRlc3RzXCIsXG4gICAgXCJjb25maWctbGlzdDp0ZXN0c1wiLCBbXCJwaGFzZTp0ZXN0czpzb3VyY2VzXCIsIFwicGhhc2U6dGVzdHM6ZnJhbWV3b3Jrc1wiLCBcInBoYXNlOnRlc3RzOnJlc291cmNlc1wiXSwgW1wiZGVwZW5kZW5jeTp0ZXN0czphcHBcIl0pXG4gIGFkZE5hdGl2ZVRhcmdldChhZGQsIGlkLCBjb25maWd1cmF0aW9uLCBcInRhcmdldDp1aXRlc3RzXCIsIFwiVUlUZXN0c1wiLCBcImNvbS5hcHBsZS5wcm9kdWN0LXR5cGUuYnVuZGxlLnVpLXRlc3RpbmdcIiwgXCJwcm9kdWN0OnVpdGVzdHNcIixcbiAgICBcImNvbmZpZy1saXN0OnVpdGVzdHNcIiwgW1wicGhhc2U6dWl0ZXN0czpzb3VyY2VzXCIsIFwicGhhc2U6dWl0ZXN0czpmcmFtZXdvcmtzXCIsIFwicGhhc2U6dWl0ZXN0czpyZXNvdXJjZXNcIl0sIFtcImRlcGVuZGVuY3k6dWl0ZXN0czphcHBcIl0pXG4gIGFkZChcIlBCWFByb2plY3RcIiwgXCJwcm9qZWN0XCIsIFtcImlzYSA9IFBCWFByb2plY3Q7XCIsIFwiYXR0cmlidXRlcyA9IHsgQnVpbGRJbmRlcGVuZGVudFRhcmdldHNJblBhcmFsbGVsID0gWUVTOyB9O1wiLFxuICAgIGBidWlsZENvbmZpZ3VyYXRpb25MaXN0ID0gJHtpZChcImNvbmZpZy1saXN0OnByb2plY3RcIil9O2AsIFwiZGV2ZWxvcG1lbnRSZWdpb24gPSBlbjtcIiwgXCJoYXNTY2FubmVkRm9yRW5jb2RpbmdzID0gMDtcIixcbiAgICBcImtub3duUmVnaW9ucyA9ICggZW4sIEJhc2UsICk7XCIsIGBtYWluR3JvdXAgPSAke2lkKFwiZ3JvdXA6bWFpblwiKX07YCwgYHByb2R1Y3RSZWZHcm91cCA9ICR7aWQoXCJncm91cDpwcm9kdWN0c1wiKX07YCxcbiAgICBcInByb2plY3REaXJQYXRoID0gXFxcIlxcXCI7XCIsIFwicHJvamVjdFJvb3QgPSBcXFwiXFxcIjtcIixcbiAgICBgdGFyZ2V0cyA9IChcXG4ke2xpc3QoW2lkKFwidGFyZ2V0OmFwcFwiKSwgaWQoXCJ0YXJnZXQ6dGVzdHNcIiksIGlkKFwidGFyZ2V0OnVpdGVzdHNcIildKX1cXG5cXHRcXHRcXHQpO2BdKVxuXG4gIGFkZEJ1aWxkUGhhc2UoYWRkLCBpZCwgXCJQQlhGcmFtZXdvcmtzQnVpbGRQaGFzZVwiLCBcInBoYXNlOmFwcDpmcmFtZXdvcmtzXCIsIFtdKVxuICBhZGRCdWlsZFBoYXNlKGFkZCwgaWQsIFwiUEJYUmVzb3VyY2VzQnVpbGRQaGFzZVwiLCBcInBoYXNlOmFwcDpyZXNvdXJjZXNcIiwgW2BidWlsZDphcHA6JHtyZXNvdXJjZVJvb3R9YF0pXG4gIGFkZEJ1aWxkUGhhc2UoYWRkLCBpZCwgXCJQQlhTb3VyY2VzQnVpbGRQaGFzZVwiLCBcInBoYXNlOmFwcDpzb3VyY2VzXCIsIHNvcnRlZChwYXRocy5hcHBTb3VyY2VzKS5tYXAocGF0aCA9PiBgYnVpbGQ6YXBwOiR7cGF0aH1gKSlcbiAgZm9yIChjb25zdCB0YXJnZXQgb2YgW1widGVzdHNcIiwgXCJ1aXRlc3RzXCJdKSB7XG4gICAgYWRkQnVpbGRQaGFzZShhZGQsIGlkLCBcIlBCWEZyYW1ld29ya3NCdWlsZFBoYXNlXCIsIGBwaGFzZToke3RhcmdldH06ZnJhbWV3b3Jrc2AsIFtdKVxuICAgIGFkZEJ1aWxkUGhhc2UoYWRkLCBpZCwgXCJQQlhSZXNvdXJjZXNCdWlsZFBoYXNlXCIsIGBwaGFzZToke3RhcmdldH06cmVzb3VyY2VzYCwgW10pXG4gIH1cbiAgYWRkQnVpbGRQaGFzZShhZGQsIGlkLCBcIlBCWFNvdXJjZXNCdWlsZFBoYXNlXCIsIFwicGhhc2U6dGVzdHM6c291cmNlc1wiLCBbYGJ1aWxkOnRlc3RzOiR7cGF0aHMudW5pdFRlc3R9YF0pXG4gIGFkZEJ1aWxkUGhhc2UoYWRkLCBpZCwgXCJQQlhTb3VyY2VzQnVpbGRQaGFzZVwiLCBcInBoYXNlOnVpdGVzdHM6c291cmNlc1wiLCBbYGJ1aWxkOnVpdGVzdHM6JHtwYXRocy51aVRlc3R9YF0pXG4gIGFkZChcIlBCWFRhcmdldERlcGVuZGVuY3lcIiwgXCJkZXBlbmRlbmN5OnRlc3RzOmFwcFwiLCBbXCJpc2EgPSBQQlhUYXJnZXREZXBlbmRlbmN5O1wiLCBgdGFyZ2V0ID0gJHtpZChcInRhcmdldDphcHBcIil9O2AsXG4gICAgYHRhcmdldFByb3h5ID0gJHtpZChcInByb3h5OnRlc3RzOmFwcFwiKX07YF0pXG4gIGFkZChcIlBCWFRhcmdldERlcGVuZGVuY3lcIiwgXCJkZXBlbmRlbmN5OnVpdGVzdHM6YXBwXCIsIFtcImlzYSA9IFBCWFRhcmdldERlcGVuZGVuY3k7XCIsIGB0YXJnZXQgPSAke2lkKFwidGFyZ2V0OmFwcFwiKX07YCxcbiAgICBgdGFyZ2V0UHJveHkgPSAke2lkKFwicHJveHk6dWl0ZXN0czphcHBcIil9O2BdKVxuXG4gIGZvciAoY29uc3Qgb3duZXIgb2YgW1wicHJvamVjdFwiLCBcImFwcFwiLCBcInRlc3RzXCIsIFwidWl0ZXN0c1wiXSkge1xuICAgIGZvciAoY29uc3QgdmFyaWFudCBvZiBbXCJkZWJ1Z1wiLCBcInJlbGVhc2VcIl0pIHtcbiAgICAgIGNvbnN0IHNldHRpbmdzID0gYnVpbGRTZXR0aW5ncyhvd25lciwgdmFyaWFudCwgY29uZmlndXJhdGlvbiwgcGF0aHMpXG5cbiAgICAgIGFkZChcIlhDQnVpbGRDb25maWd1cmF0aW9uXCIsIGBjb25maWc6JHtvd25lcn06JHt2YXJpYW50fWAsIFtcImlzYSA9IFhDQnVpbGRDb25maWd1cmF0aW9uO1wiLFxuICAgICAgICBgYmFzZUNvbmZpZ3VyYXRpb25SZWZlcmVuY2UgPSAke2lkKGBmaWxlOiR7cGF0aHMueGNjb25maWd9YCl9O2AsIFtcImJ1aWxkU2V0dGluZ3MgPSB7XFxuXCIsIC4uLnNldHRpbmdzLCBcIlxcblxcdFxcdFxcdH07XCJdLFxuICAgICAgICBgbmFtZSA9ICR7dmFyaWFudCA9PSBcImRlYnVnXCIgPyBcIkRlYnVnXCIgOiBcIlJlbGVhc2VcIn07YF0pXG4gICAgfVxuICAgIGFkZChcIlhDQ29uZmlndXJhdGlvbkxpc3RcIiwgYGNvbmZpZy1saXN0OiR7b3duZXJ9YCwgW1wiaXNhID0gWENDb25maWd1cmF0aW9uTGlzdDtcIixcbiAgICAgIGBidWlsZENvbmZpZ3VyYXRpb25zID0gKFxcbiR7bGlzdChbaWQoYGNvbmZpZzoke293bmVyfTpkZWJ1Z2ApLCBpZChgY29uZmlnOiR7b3duZXJ9OnJlbGVhc2VgKV0pfVxcblxcdFxcdFxcdCk7YCxcbiAgICAgIFwiZGVmYXVsdENvbmZpZ3VyYXRpb25Jc1Zpc2libGUgPSAwO1wiLCBcImRlZmF1bHRDb25maWd1cmF0aW9uTmFtZSA9IFJlbGVhc2U7XCJdKVxuICB9XG5cbiAgY29uc3Qgb3JkZXIgPSBbXCJQQlhCdWlsZEZpbGVcIiwgXCJQQlhDb250YWluZXJJdGVtUHJveHlcIiwgXCJQQlhGaWxlUmVmZXJlbmNlXCIsIFwiUEJYRnJhbWV3b3Jrc0J1aWxkUGhhc2VcIiwgXCJQQlhHcm91cFwiLFxuICAgIFwiUEJYTmF0aXZlVGFyZ2V0XCIsIFwiUEJYUHJvamVjdFwiLCBcIlBCWFJlc291cmNlc0J1aWxkUGhhc2VcIiwgXCJQQlhTb3VyY2VzQnVpbGRQaGFzZVwiLCBcIlBCWFRhcmdldERlcGVuZGVuY3lcIixcbiAgICBcIlhDQnVpbGRDb25maWd1cmF0aW9uXCIsIFwiWENDb25maWd1cmF0aW9uTGlzdFwiXVxuICBjb25zdCB3cml0ZXIgPSBuZXcgQ29uZmlndXJhdGlvblRleHRXcml0ZXIoKVxuXG4gIHdyaXRlci5hcHBlbmQoXCIvLyAhJCpVVEY4KiQhXFxue1xcblxcdGFyY2hpdmVWZXJzaW9uID0gMTtcXG5cXHRjbGFzc2VzID0ge307XFxuXFx0b2JqZWN0VmVyc2lvbiA9IDU2O1xcblxcdG9iamVjdHMgPSB7XFxuXCIpXG5cbiAgZm9yIChjb25zdCBzZWN0aW9uIG9mIG9yZGVyKSB7XG4gICAgY29uc3QgZW50cmllcyA9IChzZWN0aW9ucy5nZXQoc2VjdGlvbikgPz8gW10pLnNvcnQoKGxlZnQsIHJpZ2h0KSA9PiBsZWZ0LmlkZW50aXR5IDwgcmlnaHQuaWRlbnRpdHkgPyAtMSA6IDEpXG5cbiAgICB3cml0ZXIuYXBwZW5kKGBcXG4vKiBCZWdpbiAke3NlY3Rpb259IHNlY3Rpb24gKi9cXG5gKVxuICAgIGZvciAoY29uc3QgZW50cnkgb2YgZW50cmllcykge1xuICAgICAgd3JpdGVyLmFwcGVuZChgXFx0XFx0JHtpZChlbnRyeS5pZGVudGl0eSl9ID0ge1xcbmApXG4gICAgICBmb3IgKGNvbnN0IGxpbmUgb2YgZW50cnkuYm9keSkge1xuICAgICAgICB3cml0ZXIuYXBwZW5kKFwiXFx0XFx0XFx0XCIpXG4gICAgICAgIHdyaXRlci5hcHBlbmQobGluZSlcbiAgICAgICAgd3JpdGVyLmFwcGVuZChcIlxcblwiKVxuICAgICAgfVxuICAgICAgd3JpdGVyLmFwcGVuZChcIlxcdFxcdH07XFxuXCIpXG4gICAgfVxuICAgIHdyaXRlci5hcHBlbmQoYC8qIEVuZCAke3NlY3Rpb259IHNlY3Rpb24gKi9cXG5gKVxuICB9XG4gIHdyaXRlci5hcHBlbmQoYFxcdH07XFxuXFx0cm9vdE9iamVjdCA9ICR7aWQoXCJwcm9qZWN0XCIpfTtcXG59XFxuYClcblxuICByZXR1cm4gd3JpdGVyLmZpbmlzaCgpXG59XG5cbi8qKlxuICogQWRkcyBvbmUgbmF0aXZlIHRhcmdldCBvYmplY3QgdG8gdGhlIHByb2plY3QgbW9kZWwuXG4gKiBAcGFyYW0geyhzZWN0aW9uOiBzdHJpbmcsIGlkZW50aXR5OiBzdHJpbmcsIGJvZHk6IENvbmZpZ3VyYXRpb25MaW5lW10pID0+IHZvaWR9IGFkZCAtIE9iamVjdCBzaW5rLlxuICogQHBhcmFtIHsoaWRlbnRpdHk6IHN0cmluZykgPT4gc3RyaW5nfSBpZCAtIElEIGxvb2t1cC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuSW9zQXBwbGljYXRpb25Db25maWd1cmF0aW9ufSBjb25maWd1cmF0aW9uIC0gQXBwbGljYXRpb24gY29uZmlndXJhdGlvbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBpZGVudGl0eSAtIFRhcmdldCBpZGVudGl0eS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lU3VmZml4IC0gVGFyZ2V0IHN1ZmZpeCBhZnRlciB0aGUgcHJvZHVjdCBuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHByb2R1Y3RUeXBlIC0gUHJvZHVjdCB0eXBlLlxuICogQHBhcmFtIHtzdHJpbmd9IHByb2R1Y3RSZWZlcmVuY2UgLSBQcm9kdWN0IHJlZmVyZW5jZSBpZGVudGl0eS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjb25maWd1cmF0aW9uTGlzdCAtIENvbmZpZ3VyYXRpb24gbGlzdCBpZGVudGl0eS5cbiAqIEBwYXJhbSB7c3RyaW5nW119IHBoYXNlcyAtIFBoYXNlIGlkZW50aXRpZXMuXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBkZXBlbmRlbmNpZXMgLSBEZXBlbmRlbmN5IGlkZW50aXRpZXMuXG4gKi9cbmZ1bmN0aW9uIGFkZE5hdGl2ZVRhcmdldChhZGQsIGlkLCBjb25maWd1cmF0aW9uLCBpZGVudGl0eSwgbmFtZVN1ZmZpeCwgcHJvZHVjdFR5cGUsIHByb2R1Y3RSZWZlcmVuY2UsIGNvbmZpZ3VyYXRpb25MaXN0LFxuICBwaGFzZXMsIGRlcGVuZGVuY2llcykge1xuICAvKipcbiAgICogUmVuZGVycyB0YXJnZXQgaWRlbnRpdHkgdmFsdWVzLlxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSB2YWx1ZXMgLSBUYXJnZXQgaWRlbnRpdHkgdmFsdWVzLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZW5kZXJlZCB0YXJnZXQgbGlzdC5cbiAgICovXG4gIGNvbnN0IGxpbmVzID0gdmFsdWVzID0+IHZhbHVlcy5tYXAodmFsdWUgPT4gYFxcdFxcdFxcdFxcdCR7aWQodmFsdWUpfSxgKS5qb2luKFwiXFxuXCIpXG4gIGNvbnN0IG5hbWUgPSBbXCJcXFwiXCIsIGNvbmZpZ3VyYXRpb25GcmFnbWVudChcInByb2R1Y3ROYW1lXCIsIGNvbmZpZ3VyYXRpb24ucHJvZHVjdE5hbWUpLCBgJHtuYW1lU3VmZml4fVwiYF1cblxuICBhZGQoXCJQQlhOYXRpdmVUYXJnZXRcIiwgaWRlbnRpdHksIFtcImlzYSA9IFBCWE5hdGl2ZVRhcmdldDtcIiwgYGJ1aWxkQ29uZmlndXJhdGlvbkxpc3QgPSAke2lkKGNvbmZpZ3VyYXRpb25MaXN0KX07YCxcbiAgICBgYnVpbGRQaGFzZXMgPSAoXFxuJHtsaW5lcyhwaGFzZXMpfVxcblxcdFxcdFxcdCk7YCwgXCJidWlsZFJ1bGVzID0gKCk7XCIsIGBkZXBlbmRlbmNpZXMgPSAoXFxuJHtsaW5lcyhkZXBlbmRlbmNpZXMpfVxcblxcdFxcdFxcdCk7YCxcbiAgICBbXCJuYW1lID0gXCIsIC4uLm5hbWUsIFwiO1wiXSwgW1wicHJvZHVjdE5hbWUgPSBcIiwgLi4ubmFtZSwgXCI7XCJdLCBgcHJvZHVjdFJlZmVyZW5jZSA9ICR7aWQocHJvZHVjdFJlZmVyZW5jZSl9O2AsXG4gICAgYHByb2R1Y3RUeXBlID0gJHtwYnhTdHJpbmcocHJvZHVjdFR5cGUpfTtgXSlcbn1cblxuLyoqXG4gKiBBZGRzIG9uZSBidWlsZCBwaGFzZSB0byB0aGUgcHJvamVjdCBtb2RlbC5cbiAqIEBwYXJhbSB7KHNlY3Rpb246IHN0cmluZywgaWRlbnRpdHk6IHN0cmluZywgYm9keTogQ29uZmlndXJhdGlvbkxpbmVbXSkgPT4gdm9pZH0gYWRkIC0gT2JqZWN0IHNpbmsuXG4gKiBAcGFyYW0geyhpZGVudGl0eTogc3RyaW5nKSA9PiBzdHJpbmd9IGlkIC0gSUQgbG9va3VwLlxuICogQHBhcmFtIHtzdHJpbmd9IHNlY3Rpb24gLSBQaGFzZSBJU0EuXG4gKiBAcGFyYW0ge3N0cmluZ30gaWRlbnRpdHkgLSBQaGFzZSBpZGVudGl0eS5cbiAqIEBwYXJhbSB7c3RyaW5nW119IGZpbGVzIC0gQnVpbGQtZmlsZSBpZGVudGl0aWVzLlxuICovXG5mdW5jdGlvbiBhZGRCdWlsZFBoYXNlKGFkZCwgaWQsIHNlY3Rpb24sIGlkZW50aXR5LCBmaWxlcykge1xuICBjb25zdCBsaW5lcyA9IGZpbGVzLm1hcChmaWxlID0+IGBcXHRcXHRcXHRcXHQke2lkKGZpbGUpfSxgKS5qb2luKFwiXFxuXCIpXG5cbiAgYWRkKHNlY3Rpb24sIGlkZW50aXR5LCBbYGlzYSA9ICR7c2VjdGlvbn07YCwgXCJidWlsZEFjdGlvbk1hc2sgPSAyMTQ3NDgzNjQ3O1wiLCBgZmlsZXMgPSAoXFxuJHtsaW5lc31cXG5cXHRcXHRcXHQpO2AsXG4gICAgXCJydW5Pbmx5Rm9yRGVwbG95bWVudFBvc3Rwcm9jZXNzaW5nID0gMDtcIl0pXG59XG5cbi8qKlxuICogUmVuZGVycyBzb3J0ZWQgUEJYIGJ1aWxkIHNldHRpbmdzIGZvciBvbmUgb3duZXIgYW5kIHZhcmlhbnQuXG4gKiBAcGFyYW0ge3N0cmluZ30gb3duZXIgLSBDb25maWd1cmF0aW9uIG93bmVyLlxuICogQHBhcmFtIHtzdHJpbmd9IHZhcmlhbnQgLSBEZWJ1ZyBvciByZWxlYXNlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Jb3NBcHBsaWNhdGlvbkNvbmZpZ3VyYXRpb259IGNvbmZpZ3VyYXRpb24gLSBBcHBsaWNhdGlvbiBjb25maWd1cmF0aW9uLlxuICogQHBhcmFtIHtSZXR1cm5UeXBlPHR5cGVvZiBhcHBsaWNhdGlvbkFydGlmYWN0UGF0aHM+fSBwYXRocyAtIFBsYW5uZWQgcGF0aHMuXG4gKiBAcmV0dXJucyB7Q29uZmlndXJhdGlvblRleHRQYXJ0W119IFNvcnRlZCBQQlggYnVpbGQgc2V0dGluZ3MuXG4gKi9cbmZ1bmN0aW9uIGJ1aWxkU2V0dGluZ3Mob3duZXIsIHZhcmlhbnQsIGNvbmZpZ3VyYXRpb24sIHBhdGhzKSB7XG4gIC8qKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgQ29uZmlndXJhdGlvblRleHRQYXJ0IHwgQ29uZmlndXJhdGlvblRleHRQYXJ0W10+fSAqL1xuICBjb25zdCB2YWx1ZXMgPSBvd25lciA9PSBcInByb2plY3RcIiA/IHtcbiAgICBDT0RFX1NJR05JTkdfQUxMT1dFRDogXCJOT1wiLFxuICAgIENPREVfU0lHTklOR19SRVFVSVJFRDogXCJOT1wiXG4gIH0gOiBvd25lciA9PSBcImFwcFwiID8ge1xuICAgIEdFTkVSQVRFX0lORk9QTElTVF9GSUxFOiBcIk5PXCIsXG4gICAgSU5GT1BMSVNUX0ZJTEU6IHBieFN0cmluZyhwYXRocy5pbmZvUGxpc3QpLFxuICAgIElQSE9ORU9TX0RFUExPWU1FTlRfVEFSR0VUOiBjb25maWd1cmF0aW9uRnJhZ21lbnQoXCJkZXBsb3ltZW50VGFyZ2V0XCIsIGNvbmZpZ3VyYXRpb24uZGVwbG95bWVudFRhcmdldCksXG4gICAgUFJPRFVDVF9CVU5ETEVfSURFTlRJRklFUjogY29uZmlndXJhdGlvbkZyYWdtZW50KFwiYnVuZGxlSWRlbnRpZmllclwiLCBjb25maWd1cmF0aW9uLmJ1bmRsZUlkZW50aWZpZXIpLFxuICAgIFBST0RVQ1RfTU9EVUxFX05BTUU6IGNvbmZpZ3VyYXRpb25GcmFnbWVudChcIm1vZHVsZU5hbWVcIiwgY29uZmlndXJhdGlvbi5tb2R1bGVOYW1lKSxcbiAgICBQUk9EVUNUX05BTUU6IGNvbmZpZ3VyYXRpb25GcmFnbWVudChcInByb2R1Y3ROYW1lXCIsIGNvbmZpZ3VyYXRpb24ucHJvZHVjdE5hbWUpLFxuICAgIFNES1JPT1Q6IFwiaXBob25lb3NcIixcbiAgICBTVVBQT1JURURfUExBVEZPUk1TOiBwYnhTdHJpbmcoXCJpcGhvbmVvcyBpcGhvbmVzaW11bGF0b3JcIiksXG4gICAgVEFSR0VURURfREVWSUNFX0ZBTUlMWTogXCIxXCJcbiAgfSA6IG93bmVyID09IFwidGVzdHNcIiA/IHtcbiAgICBCVU5ETEVfTE9BREVSOiBwYnhTdHJpbmcoXCIkKFRFU1RfSE9TVClcIiksXG4gICAgUFJPRFVDVF9CVU5ETEVfSURFTlRJRklFUjogW2NvbmZpZ3VyYXRpb25GcmFnbWVudChcImJ1bmRsZUlkZW50aWZpZXJcIiwgY29uZmlndXJhdGlvbi5idW5kbGVJZGVudGlmaWVyKSwgXCIudGVzdHNcIl0sXG4gICAgUFJPRFVDVF9NT0RVTEVfTkFNRTogW2NvbmZpZ3VyYXRpb25GcmFnbWVudChcIm1vZHVsZU5hbWVcIiwgY29uZmlndXJhdGlvbi5tb2R1bGVOYW1lKSwgXCJUZXN0c1wiXSxcbiAgICBQUk9EVUNUX05BTUU6IFwiJChUQVJHRVRfTkFNRSlcIixcbiAgICBURVNUX0hPU1Q6IFtcIlxcXCIkKEJVSUxUX1BST0RVQ1RTX0RJUikvXCIsIGNvbmZpZ3VyYXRpb25GcmFnbWVudChcInByb2R1Y3ROYW1lXCIsIGNvbmZpZ3VyYXRpb24ucHJvZHVjdE5hbWUpLFxuICAgICAgXCIuYXBwL1wiLCBjb25maWd1cmF0aW9uRnJhZ21lbnQoXCJwcm9kdWN0TmFtZVwiLCBjb25maWd1cmF0aW9uLnByb2R1Y3ROYW1lKSwgXCJcXFwiXCJdXG4gIH0gOiB7XG4gICAgUFJPRFVDVF9CVU5ETEVfSURFTlRJRklFUjogW2NvbmZpZ3VyYXRpb25GcmFnbWVudChcImJ1bmRsZUlkZW50aWZpZXJcIiwgY29uZmlndXJhdGlvbi5idW5kbGVJZGVudGlmaWVyKSwgXCIudWl0ZXN0c1wiXSxcbiAgICBQUk9EVUNUX01PRFVMRV9OQU1FOiBbY29uZmlndXJhdGlvbkZyYWdtZW50KFwibW9kdWxlTmFtZVwiLCBjb25maWd1cmF0aW9uLm1vZHVsZU5hbWUpLCBcIlVJVGVzdHNcIl0sXG4gICAgUFJPRFVDVF9OQU1FOiBcIiQoVEFSR0VUX05BTUUpXCIsXG4gICAgVEVTVF9UQVJHRVRfTkFNRTogY29uZmlndXJhdGlvbkZyYWdtZW50KFwicHJvZHVjdE5hbWVcIiwgY29uZmlndXJhdGlvbi5wcm9kdWN0TmFtZSlcbiAgfVxuXG4gIGlmICh2YXJpYW50ID09IFwicmVsZWFzZVwiKSB2YWx1ZXMuU1dJRlRfT1BUSU1JWkFUSU9OX0xFVkVMID0gcGJ4U3RyaW5nKFwiLU9cIilcblxuICAvKiogQHR5cGUge0NvbmZpZ3VyYXRpb25UZXh0UGFydFtdfSAqL1xuICBjb25zdCBvdXRwdXQgPSBbXVxuXG4gIGZvciAoY29uc3QgW2luZGV4LCBrZXldIG9mIE9iamVjdC5rZXlzKHZhbHVlcykuc29ydCgpLmVudHJpZXMoKSkge1xuICAgIGNvbnN0IHZhbHVlID0gdmFsdWVzW2tleV1cblxuICAgIGlmIChpbmRleCA+IDApIG91dHB1dC5wdXNoKFwiXFxuXCIpXG4gICAgb3V0cHV0LnB1c2goYFxcdFxcdFxcdFxcdCR7a2V5fSA9IGApXG4gICAgb3V0cHV0LnB1c2goLi4uKEFycmF5LmlzQXJyYXkodmFsdWUpID8gdmFsdWUgOiBbdmFsdWVdKSlcbiAgICBvdXRwdXQucHVzaChcIjtcIilcbiAgfVxuXG4gIHJldHVybiBvdXRwdXRcbn1cblxuLyoqXG4gKiBRdW90ZXMgb25lIFBCWCBzY2FsYXIuXG4gKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgLSBQQlggc2NhbGFyLlxuICogQHJldHVybnMge3N0cmluZ30gU2FmZWx5IHF1b3RlZCBQQlggc2NhbGFyLlxuICovXG5mdW5jdGlvbiBwYnhTdHJpbmcodmFsdWUpIHtcbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHZhbHVlKVxufVxuXG4vKipcbiAqIFJlbmRlcnMgYSBxdW90ZWQgUEJYIHBhdGggd2hpbGUgcmV0YWluaW5nIGNhdXNhbGl0eSBmb3IgaXRzIGNvbmZpZ3VyZWQgY29tcG9uZW50LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Jb3NBcHBsaWNhdGlvbkNvbmZpZ3VyYXRpb259IGNvbmZpZ3VyYXRpb24gLSBBcHBsaWNhdGlvbiBjb25maWd1cmF0aW9uLlxuICogQHBhcmFtIHtzdHJpbmd9IHBhdGggLSBQbGFubmVkIGFydGlmYWN0IHBhdGguXG4gKiBAcmV0dXJucyB7Q29uZmlndXJhdGlvblRleHRQYXJ0W119IFF1b3RlZCBQQlggcGF0aCBmcmFnbWVudHMuXG4gKi9cbmZ1bmN0aW9uIHBieENvbmZpZ3VyYXRpb25QYXRoKGNvbmZpZ3VyYXRpb24sIHBhdGgpIHtcbiAgaWYgKHBhdGguc3RhcnRzV2l0aChgJHtjb25maWd1cmF0aW9uLnNvdXJjZVJvb3R9L2ApKSB7XG4gICAgcmV0dXJuIFtcIlxcXCJcIiwgY29uZmlndXJhdGlvbkZyYWdtZW50KFwic291cmNlUm9vdFwiLCBjb25maWd1cmF0aW9uLnNvdXJjZVJvb3QpLCBwYXRoLnNsaWNlKGNvbmZpZ3VyYXRpb24uc291cmNlUm9vdC5sZW5ndGgpLCBcIlxcXCJcIl1cbiAgfVxuICBpZiAocGF0aCA9PSBjb25maWd1cmF0aW9uLnJlc291cmNlUm9vdCkge1xuICAgIHJldHVybiBbXCJcXFwiXCIsIGNvbmZpZ3VyYXRpb25GcmFnbWVudChcInJlc291cmNlUm9vdFwiLCBjb25maWd1cmF0aW9uLnJlc291cmNlUm9vdCksIFwiXFxcIlwiXVxuICB9XG4gIGlmIChwYXRoID09IGBUZXN0cy8ke2NvbmZpZ3VyYXRpb24ucHJvZHVjdE5hbWV9VGVzdHMuc3dpZnRgKSB7XG4gICAgcmV0dXJuIFtcIlxcXCJUZXN0cy9cIiwgY29uZmlndXJhdGlvbkZyYWdtZW50KFwicHJvZHVjdE5hbWVcIiwgY29uZmlndXJhdGlvbi5wcm9kdWN0TmFtZSksIFwiVGVzdHMuc3dpZnRcXFwiXCJdXG4gIH1cbiAgaWYgKHBhdGggPT0gYFVJVGVzdHMvJHtjb25maWd1cmF0aW9uLnByb2R1Y3ROYW1lfVVJVGVzdHMuc3dpZnRgKSB7XG4gICAgcmV0dXJuIFtcIlxcXCJVSVRlc3RzL1wiLCBjb25maWd1cmF0aW9uRnJhZ21lbnQoXCJwcm9kdWN0TmFtZVwiLCBjb25maWd1cmF0aW9uLnByb2R1Y3ROYW1lKSwgXCJVSVRlc3RzLnN3aWZ0XFxcIlwiXVxuICB9XG5cbiAgcmV0dXJuIFtwYnhTdHJpbmcocGF0aCldXG59XG5cbi8qKlxuICogUmVuZGVycyB0aGUgc2hhcmVkIHNjaGVtZSBYTUwuXG4gKiBAcGFyYW0ge1JldHVyblR5cGU8dHlwZW9mIHByZWZsaWdodElvc0FwcGxpY2F0aW9uPn0gcHJlcGFyZWQgLSBQcmVwYXJlZCBhcHBsaWNhdGlvbi5cbiAqIEByZXR1cm5zIHtSZW5kZXJlZENvbmZpZ3VyYXRpb25UZXh0fSBTaGFyZWQgc2NoZW1lIFhNTCBhbmQgY2F1c2FsIGNvbmZpZ3VyYXRpb24gc3BhbnMuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlclNoYXJlZFNjaGVtZShwcmVwYXJlZCkge1xuICBjb25zdCBwcm9kdWN0ID0gcHJlcGFyZWQuY29uZmlndXJhdGlvbi5wcm9kdWN0TmFtZVxuICBjb25zdCBhcHBJZCA9IGFsbG9jYXRlWGNvZGVPYmplY3RJZHMoW1widGFyZ2V0OmFwcFwiXSkuZ2V0KFwidGFyZ2V0OmFwcFwiKVxuICBjb25zdCB0ZXN0SWQgPSBhbGxvY2F0ZVhjb2RlT2JqZWN0SWRzKFtcInRhcmdldDp0ZXN0c1wiXSkuZ2V0KFwidGFyZ2V0OnRlc3RzXCIpXG4gIGNvbnN0IHVpVGVzdElkID0gYWxsb2NhdGVYY29kZU9iamVjdElkcyhbXCJ0YXJnZXQ6dWl0ZXN0c1wiXSkuZ2V0KFwidGFyZ2V0OnVpdGVzdHNcIilcbiAgLyoqXG4gICAqIFJlbmRlcnMgb25lIHNjaGVtZSBidWlsZGFibGUgcmVmZXJlbmNlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVN1ZmZpeCAtIEJsdWVwcmludCBzdWZmaXggYWZ0ZXIgcHJvZHVjdCBuYW1lLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYnVpbGRhYmxlU3VmZml4IC0gUHJvZHVjdCBmaWxlbmFtZSBzdWZmaXguXG4gICAqIEBwYXJhbSB7c3RyaW5nIHwgdW5kZWZpbmVkfSBpZCAtIE9iamVjdCBJRC5cbiAgICogQHJldHVybnMge0NvbmZpZ3VyYXRpb25UZXh0UGFydFtdfSBYTUwgcmVmZXJlbmNlLlxuICAgKi9cbiAgY29uc3QgcmVmZXJlbmNlID0gKG5hbWVTdWZmaXgsIGJ1aWxkYWJsZVN1ZmZpeCwgaWQpID0+IFtgPEJ1aWxkYWJsZVJlZmVyZW5jZVxuICAgICAgICAgICAgICAgQnVpbGRhYmxlSWRlbnRpZmllciA9IFwicHJpbWFyeVwiXG4gICAgICAgICAgICAgICBCbHVlcHJpbnRJZGVudGlmaWVyID0gXCIke2lkfVwiXG4gICAgICAgICAgICAgICBCdWlsZGFibGVOYW1lID0gXCJgLCBjb25maWd1cmF0aW9uRnJhZ21lbnQoXCJwcm9kdWN0TmFtZVwiLCBwcm9kdWN0KSwgYCR7YnVpbGRhYmxlU3VmZml4fVwiXG4gICAgICAgICAgICAgICBCbHVlcHJpbnROYW1lID0gXCJgLCBjb25maWd1cmF0aW9uRnJhZ21lbnQoXCJwcm9kdWN0TmFtZVwiLCBwcm9kdWN0KSwgYCR7bmFtZVN1ZmZpeH1cIlxuICAgICAgICAgICAgICAgUmVmZXJlbmNlZENvbnRhaW5lciA9IFwiY29udGFpbmVyOmAsIGNvbmZpZ3VyYXRpb25GcmFnbWVudChcInByb2R1Y3ROYW1lXCIsIHByb2R1Y3QpLCBgLnhjb2RlcHJvalwiPlxuICAgICAgICAgICAgPC9CdWlsZGFibGVSZWZlcmVuY2U+YF1cbiAgY29uc3Qgd3JpdGVyID0gbmV3IENvbmZpZ3VyYXRpb25UZXh0V3JpdGVyKClcblxuICB3cml0ZXIuYXBwZW5kKGA8P3htbCB2ZXJzaW9uPVwiMS4wXCIgZW5jb2Rpbmc9XCJVVEYtOFwiPz5cbjxTY2hlbWUgdmVyc2lvbj1cIjEuN1wiPlxuICAgPEJ1aWxkQWN0aW9uIHBhcmFsbGVsaXplQnVpbGRhYmxlcz1cIllFU1wiIGJ1aWxkSW1wbGljaXREZXBlbmRlbmNpZXM9XCJZRVNcIj5cbiAgICAgIDxCdWlsZEFjdGlvbkVudHJpZXM+XG4gICAgICAgICA8QnVpbGRBY3Rpb25FbnRyeSBidWlsZEZvclRlc3Rpbmc9XCJZRVNcIiBidWlsZEZvclJ1bm5pbmc9XCJZRVNcIiBidWlsZEZvclByb2ZpbGluZz1cIllFU1wiIGJ1aWxkRm9yQXJjaGl2aW5nPVwiWUVTXCIgYnVpbGRGb3JBbmFseXppbmc9XCJZRVNcIj5cbiAgICAgICAgICAgIGApXG4gIHdyaXRlci5hcHBlbmQocmVmZXJlbmNlKFwiXCIsIFwiLmFwcFwiLCBhcHBJZCkpXG4gIHdyaXRlci5hcHBlbmQoYFxuICAgICAgICAgPC9CdWlsZEFjdGlvbkVudHJ5PlxuICAgICAgPC9CdWlsZEFjdGlvbkVudHJpZXM+XG4gICA8L0J1aWxkQWN0aW9uPlxuICAgPFRlc3RBY3Rpb24gYnVpbGRDb25maWd1cmF0aW9uPVwiRGVidWdcIiBzZWxlY3RlZERlYnVnZ2VySWRlbnRpZmllcj1cIlhjb2RlLkRlYnVnZ2VyRm91bmRhdGlvbi5EZWJ1Z2dlci5MTERCXCIgc2VsZWN0ZWRMYXVuY2hlcklkZW50aWZpZXI9XCJYY29kZS5EZWJ1Z2dlckZvdW5kYXRpb24uTGF1bmNoZXIuTExEQlwiIHNob3VsZFVzZUxhdW5jaFNjaGVtZUFyZ3NFbnY9XCJZRVNcIj5cbiAgICAgIDxUZXN0YWJsZXM+XG4gICAgICAgICA8VGVzdGFibGVSZWZlcmVuY2Ugc2tpcHBlZD1cIk5PXCI+XG4gICAgICAgICAgICBgKVxuICB3cml0ZXIuYXBwZW5kKHJlZmVyZW5jZShcIlRlc3RzXCIsIFwiVGVzdHMueGN0ZXN0XCIsIHRlc3RJZCkpXG4gIHdyaXRlci5hcHBlbmQoYFxuICAgICAgICAgPC9UZXN0YWJsZVJlZmVyZW5jZT5cbiAgICAgICAgIDxUZXN0YWJsZVJlZmVyZW5jZSBza2lwcGVkPVwiTk9cIj5cbiAgICAgICAgICAgIGApXG4gIHdyaXRlci5hcHBlbmQocmVmZXJlbmNlKFwiVUlUZXN0c1wiLCBcIlVJVGVzdHMueGN0ZXN0XCIsIHVpVGVzdElkKSlcbiAgd3JpdGVyLmFwcGVuZChgXG4gICAgICAgICA8L1Rlc3RhYmxlUmVmZXJlbmNlPlxuICAgICAgPC9UZXN0YWJsZXM+XG4gICA8L1Rlc3RBY3Rpb24+XG4gICA8TGF1bmNoQWN0aW9uIGJ1aWxkQ29uZmlndXJhdGlvbj1cIkRlYnVnXCIgc2VsZWN0ZWREZWJ1Z2dlcklkZW50aWZpZXI9XCJYY29kZS5EZWJ1Z2dlckZvdW5kYXRpb24uRGVidWdnZXIuTExEQlwiIHNlbGVjdGVkTGF1bmNoZXJJZGVudGlmaWVyPVwiWGNvZGUuRGVidWdnZXJGb3VuZGF0aW9uLkxhdW5jaGVyLkxMREJcIiBsYXVuY2hTdHlsZT1cIjBcIiB1c2VDdXN0b21Xb3JraW5nRGlyZWN0b3J5PVwiTk9cIiBpZ25vcmVzUGVyc2lzdGVudFN0YXRlT25MYXVuY2g9XCJOT1wiIGRlYnVnRG9jdW1lbnRWZXJzaW9uaW5nPVwiWUVTXCIgZGVidWdTZXJ2aWNlRXh0ZW5zaW9uPVwiaW50ZXJuYWxcIiBhbGxvd0xvY2F0aW9uU2ltdWxhdGlvbj1cIllFU1wiPlxuICAgICAgPEJ1aWxkYWJsZVByb2R1Y3RSdW5uYWJsZSBydW5uYWJsZURlYnVnZ2luZ01vZGU9XCIwXCI+XG4gICAgICAgICBgKVxuICB3cml0ZXIuYXBwZW5kKHJlZmVyZW5jZShcIlwiLCBcIi5hcHBcIiwgYXBwSWQpKVxuICB3cml0ZXIuYXBwZW5kKGBcbiAgICAgIDwvQnVpbGRhYmxlUHJvZHVjdFJ1bm5hYmxlPlxuICAgPC9MYXVuY2hBY3Rpb24+XG4gICA8UHJvZmlsZUFjdGlvbiBidWlsZENvbmZpZ3VyYXRpb249XCJSZWxlYXNlXCIgc2hvdWxkVXNlTGF1bmNoU2NoZW1lQXJnc0Vudj1cIllFU1wiIHNhdmVkVG9vbElkZW50aWZpZXI9XCJcIiB1c2VDdXN0b21Xb3JraW5nRGlyZWN0b3J5PVwiTk9cIiBkZWJ1Z0RvY3VtZW50VmVyc2lvbmluZz1cIllFU1wiPlxuICAgICAgPEJ1aWxkYWJsZVByb2R1Y3RSdW5uYWJsZSBydW5uYWJsZURlYnVnZ2luZ01vZGU9XCIwXCI+XG4gICAgICAgICBgKVxuICB3cml0ZXIuYXBwZW5kKHJlZmVyZW5jZShcIlwiLCBcIi5hcHBcIiwgYXBwSWQpKVxuICB3cml0ZXIuYXBwZW5kKGBcbiAgICAgIDwvQnVpbGRhYmxlUHJvZHVjdFJ1bm5hYmxlPlxuICAgPC9Qcm9maWxlQWN0aW9uPlxuICAgPEFuYWx5emVBY3Rpb24gYnVpbGRDb25maWd1cmF0aW9uPVwiRGVidWdcIi8+XG4gICA8QXJjaGl2ZUFjdGlvbiBidWlsZENvbmZpZ3VyYXRpb249XCJSZWxlYXNlXCIgcmV2ZWFsQXJjaGl2ZUluT3JnYW5pemVyPVwiWUVTXCIvPlxuPC9TY2hlbWU+XG5gKVxuXG4gIHJldHVybiB3cml0ZXIuZmluaXNoKClcbn1cblxuLyoqXG4gKiBSZW5kZXJzIHRoZSBjbG9zZWQgdW5zaWduZWQgYmFzZSBjb25maWd1cmF0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Jb3NBcHBsaWNhdGlvbkNvbmZpZ3VyYXRpb259IGNvbmZpZ3VyYXRpb24gLSBBcHBsaWNhdGlvbiBjb25maWd1cmF0aW9uLlxuICogQHJldHVybnMge1JlbmRlcmVkQ29uZmlndXJhdGlvblRleHR9IEJhc2UgeGNjb25maWcgYW5kIGNhdXNhbCBjb25maWd1cmF0aW9uIHNwYW5zLlxuICovXG5mdW5jdGlvbiByZW5kZXJCYXNlQ29uZmlndXJhdGlvbihjb25maWd1cmF0aW9uKSB7XG4gIGNvbnN0IHdyaXRlciA9IG5ldyBDb25maWd1cmF0aW9uVGV4dFdyaXRlcigpXG5cbiAgd3JpdGVyLmFwcGVuZChgQ09ERV9TSUdOSU5HX0FMTE9XRUQgPSBOT1xuQ09ERV9TSUdOSU5HX1JFUVVJUkVEID0gTk9cbkdFTkVSQVRFX0lORk9QTElTVF9GSUxFID0gTk9cbklQSE9ORU9TX0RFUExPWU1FTlRfVEFSR0VUID0gYClcbiAgd3JpdGVyLmFwcGVuZChjb25maWd1cmF0aW9uRnJhZ21lbnQoXCJkZXBsb3ltZW50VGFyZ2V0XCIsIGNvbmZpZ3VyYXRpb24uZGVwbG95bWVudFRhcmdldCkpXG4gIHdyaXRlci5hcHBlbmQoXCJcXG5QUk9EVUNUX0JVTkRMRV9JREVOVElGSUVSID0gXCIpXG4gIHdyaXRlci5hcHBlbmQoY29uZmlndXJhdGlvbkZyYWdtZW50KFwiYnVuZGxlSWRlbnRpZmllclwiLCBjb25maWd1cmF0aW9uLmJ1bmRsZUlkZW50aWZpZXIpKVxuICB3cml0ZXIuYXBwZW5kKFwiXFxuUFJPRFVDVF9NT0RVTEVfTkFNRSA9IFwiKVxuICB3cml0ZXIuYXBwZW5kKGNvbmZpZ3VyYXRpb25GcmFnbWVudChcIm1vZHVsZU5hbWVcIiwgY29uZmlndXJhdGlvbi5tb2R1bGVOYW1lKSlcbiAgd3JpdGVyLmFwcGVuZChcIlxcblBST0RVQ1RfTkFNRSA9IFwiKVxuICB3cml0ZXIuYXBwZW5kKGNvbmZpZ3VyYXRpb25GcmFnbWVudChcInByb2R1Y3ROYW1lXCIsIGNvbmZpZ3VyYXRpb24ucHJvZHVjdE5hbWUpKVxuICB3cml0ZXIuYXBwZW5kKGBcblNES1JPT1QgPSBpcGhvbmVvc1xuU1VQUE9SVEVEX1BMQVRGT1JNUyA9IGlwaG9uZW9zIGlwaG9uZXNpbXVsYXRvclxuVEFSR0VURURfREVWSUNFX0ZBTUlMWSA9IDFcbmApXG5cbiAgcmV0dXJuIHdyaXRlci5maW5pc2goKVxufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIGFsbG93bGlzdGVkIGFwcGxpY2F0aW9uIHByb3BlcnR5IGxpc3QuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLklvc0FwcGxpY2F0aW9uQ29uZmlndXJhdGlvbn0gY29uZmlndXJhdGlvbiAtIEFwcGxpY2F0aW9uIGNvbmZpZ3VyYXRpb24uXG4gKiBAcmV0dXJucyB7UmVuZGVyZWRDb25maWd1cmF0aW9uVGV4dH0gUHJvcGVydHktbGlzdCBYTUwgYW5kIGNhdXNhbCBjb25maWd1cmF0aW9uIHNwYW5zLlxuICovXG5mdW5jdGlvbiByZW5kZXJJbmZvUGxpc3QoY29uZmlndXJhdGlvbikge1xuICBjb25zdCB3cml0ZXIgPSBuZXcgQ29uZmlndXJhdGlvblRleHRXcml0ZXIoKVxuXG4gIHdyaXRlci5hcHBlbmQoYDw/eG1sIHZlcnNpb249XCIxLjBcIiBlbmNvZGluZz1cIlVURi04XCI/PlxuPCFET0NUWVBFIHBsaXN0IFBVQkxJQyBcIi0vL0FwcGxlLy9EVEQgUExJU1QgMS4wLy9FTlwiIFwiaHR0cDovL3d3dy5hcHBsZS5jb20vRFREcy9Qcm9wZXJ0eUxpc3QtMS4wLmR0ZFwiPlxuPHBsaXN0IHZlcnNpb249XCIxLjBcIj5cbjxkaWN0PlxuICA8a2V5PkNGQnVuZGxlRGlzcGxheU5hbWU8L2tleT5cbiAgPHN0cmluZz5gKVxuICB3cml0ZXIuYXBwZW5kKGNvbmZpZ3VyYXRpb25GcmFnbWVudChcImRpc3BsYXlOYW1lXCIsIHhtbEVzY2FwZShjb25maWd1cmF0aW9uLmRpc3BsYXlOYW1lKSkpXG4gIHdyaXRlci5hcHBlbmQoYDwvc3RyaW5nPlxuICA8a2V5PkNGQnVuZGxlRXhlY3V0YWJsZTwva2V5PlxuICA8c3RyaW5nPiQoRVhFQ1VUQUJMRV9OQU1FKTwvc3RyaW5nPlxuICA8a2V5PkNGQnVuZGxlSWRlbnRpZmllcjwva2V5PlxuICA8c3RyaW5nPiQoUFJPRFVDVF9CVU5ETEVfSURFTlRJRklFUik8L3N0cmluZz5cbiAgPGtleT5DRkJ1bmRsZUluZm9EaWN0aW9uYXJ5VmVyc2lvbjwva2V5PlxuICA8c3RyaW5nPjYuMDwvc3RyaW5nPlxuICA8a2V5PkNGQnVuZGxlTmFtZTwva2V5PlxuICA8c3RyaW5nPiQoUFJPRFVDVF9OQU1FKTwvc3RyaW5nPlxuICA8a2V5PkNGQnVuZGxlUGFja2FnZVR5cGU8L2tleT5cbiAgPHN0cmluZz5BUFBMPC9zdHJpbmc+XG4gIDxrZXk+Q0ZCdW5kbGVTaG9ydFZlcnNpb25TdHJpbmc8L2tleT5cbiAgPHN0cmluZz4xLjA8L3N0cmluZz5cbiAgPGtleT5DRkJ1bmRsZVZlcnNpb248L2tleT5cbiAgPHN0cmluZz4xPC9zdHJpbmc+XG4gIDxrZXk+TFNSZXF1aXJlc0lQaG9uZU9TPC9rZXk+XG4gIDx0cnVlLz5cbiAgPGtleT5VSUxhdW5jaFNjcmVlbjwva2V5PlxuICA8ZGljdC8+XG48L2RpY3Q+XG48L3BsaXN0PlxuYClcblxuICByZXR1cm4gd3JpdGVyLmZpbmlzaCgpXG59XG5cbi8qKlxuICogUmVuZGVycyBwdXJlLWxvZ2ljIFhDVGVzdCBzb3VyY2UuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLklvc0FwcGxpY2F0aW9uQ29uZmlndXJhdGlvbn0gY29uZmlndXJhdGlvbiAtIEFwcGxpY2F0aW9uIGNvbmZpZ3VyYXRpb24uXG4gKiBAcmV0dXJucyB7UmVuZGVyZWRDb25maWd1cmF0aW9uVGV4dH0gWENUZXN0IHNvdXJjZSBhbmQgY2F1c2FsIGNvbmZpZ3VyYXRpb24gc3BhbnMuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlclVuaXRUZXN0cyhjb25maWd1cmF0aW9uKSB7XG4gIGNvbnN0IHdyaXRlciA9IG5ldyBDb25maWd1cmF0aW9uVGV4dFdyaXRlcigpXG5cbiAgd3JpdGVyLmFwcGVuZChcImltcG9ydCBYQ1Rlc3RcXG5AdGVzdGFibGUgaW1wb3J0IFwiKVxuICB3cml0ZXIuYXBwZW5kKGNvbmZpZ3VyYXRpb25GcmFnbWVudChcIm1vZHVsZU5hbWVcIiwgY29uZmlndXJhdGlvbi5tb2R1bGVOYW1lKSlcbiAgd3JpdGVyLmFwcGVuZChcIlxcblxcbmZpbmFsIGNsYXNzIFwiKVxuICB3cml0ZXIuYXBwZW5kKGNvbmZpZ3VyYXRpb25GcmFnbWVudChcInByb2R1Y3ROYW1lXCIsIGNvbmZpZ3VyYXRpb24ucHJvZHVjdE5hbWUpKVxuICB3cml0ZXIuYXBwZW5kKGBUZXN0czogWENUZXN0Q2FzZSB7XG4gIGZ1bmMgdGVzdFNlbWFudGljT3V0cHV0SXNEZXRlcm1pbmlzdGljKCkge1xuICAgIFhDVEFzc2VydEVxdWFsKFNlbWFudGlmb2xkQnJpZGdlLnJ1bigpLCBTZW1hbnRpZm9sZEJyaWRnZS5ydW4oKSlcbiAgfVxuXG4gIGZ1bmMgdGVzdE91dHB1dFNpbmtQcmVzZXJ2ZXNTY2FsYXJMaW5lcygpIHtcbiAgICBsZXQgb3V0cHV0ID0gU2VtYW50aWZvbGRPdXRwdXRTaW5rKClcbiAgICBvdXRwdXQud3JpdGUoSW50NjQoNykpXG4gICAgb3V0cHV0LndyaXRlKHRydWUpXG4gICAgb3V0cHV0LndyaXRlKFwiw6nwn5iAXCIpXG4gICAgWENUQXNzZXJ0RXF1YWwob3V0cHV0LmxpbmVzLCBbXCI3XCIsIFwidHJ1ZVwiLCBcIsOp8J+YgFwiXSlcbiAgfVxufVxuYClcblxuICByZXR1cm4gd3JpdGVyLmZpbmlzaCgpXG59XG5cbi8qKlxuICogUmVuZGVycyB0aGUgYWNjZXNzaWJpbGl0eS1yb3V0ZSBYQ1VJIHNvdXJjZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuSW9zQXBwbGljYXRpb25Db25maWd1cmF0aW9ufSBjb25maWd1cmF0aW9uIC0gQXBwbGljYXRpb24gY29uZmlndXJhdGlvbi5cbiAqIEByZXR1cm5zIHtSZW5kZXJlZENvbmZpZ3VyYXRpb25UZXh0fSBYQ1VJIHNvdXJjZSBhbmQgY2F1c2FsIGNvbmZpZ3VyYXRpb24gc3BhbnMuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlclVpVGVzdHMoY29uZmlndXJhdGlvbikge1xuICBjb25zdCB3cml0ZXIgPSBuZXcgQ29uZmlndXJhdGlvblRleHRXcml0ZXIoKVxuXG4gIHdyaXRlci5hcHBlbmQoXCJpbXBvcnQgWENUZXN0XFxuXFxuZmluYWwgY2xhc3MgXCIpXG4gIHdyaXRlci5hcHBlbmQoY29uZmlndXJhdGlvbkZyYWdtZW50KFwicHJvZHVjdE5hbWVcIiwgY29uZmlndXJhdGlvbi5wcm9kdWN0TmFtZSkpXG4gIHdyaXRlci5hcHBlbmQoYFVJVGVzdHM6IFhDVGVzdENhc2Uge1xuICBmdW5jIHRlc3RPdXRwdXRWaWV3SXNBY2Nlc3NpYmxlKCkge1xuICAgIGxldCBhcHBsaWNhdGlvbiA9IFhDVUlBcHBsaWNhdGlvbigpXG4gICAgYXBwbGljYXRpb24ubGF1bmNoKClcbiAgICBYQ1RBc3NlcnRUcnVlKGFwcGxpY2F0aW9uLnN0YXRpY1RleHRzW1wic2VtYW50aWZvbGQtb3V0cHV0XCJdLndhaXRGb3JFeGlzdGVuY2UodGltZW91dDogNSkpXG4gIH1cbn1cbmApXG5cbiAgcmV0dXJuIHdyaXRlci5maW5pc2goKVxufVxuXG4vKipcbiAqIEVzY2FwZXMgWE1MIHRleHQgYW5kIGF0dHJpYnV0ZSBjb250ZW50LlxuICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlIC0gWE1MIHRleHQgb3IgYXR0cmlidXRlIHZhbHVlLlxuICogQHJldHVybnMge3N0cmluZ30gRXNjYXBlZCB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24geG1sRXNjYXBlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZS5yZXBsYWNlQWxsKFwiJlwiLCBcIiZhbXA7XCIpLnJlcGxhY2VBbGwoXCI8XCIsIFwiJmx0O1wiKS5yZXBsYWNlQWxsKFwiPlwiLCBcIiZndDtcIilcbiAgICAucmVwbGFjZUFsbChcIlxcXCJcIiwgXCImcXVvdDtcIikucmVwbGFjZUFsbChcIidcIiwgXCImYXBvcztcIilcbn1cblxuLyoqXG4gKiBDcmVhdGVzIG9uZSBzeW50aGV0aWMgdGV4dCBhcnRpZmFjdCBjYW5kaWRhdGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aCAtIEFydGlmYWN0IHBhdGguXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkdlbmVyYXRlZEFydGlmYWN0Um9sZX0gcm9sZSAtIEFydGlmYWN0IHJvbGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gY29udGVudCAtIEV4YWN0IExGIGNvbnRlbnQuXG4gKiBAcGFyYW0ge3N0cmluZ30gcmVhc29uIC0gUHJvdmVuYW5jZSByZWFzb24uXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuR2VuZXJhdGVkU2V0QXJ0aWZhY3R9IEFydGlmYWN0IGNhbmRpZGF0ZS5cbiAqL1xuZnVuY3Rpb24gc3ludGhldGljVGV4dChwYXRoLCByb2xlLCBjb250ZW50LCByZWFzb24pIHtcbiAgcmV0dXJuIHtcbiAgICBjb250ZW50LFxuICAgIGNvbnRlbnRLaW5kOiBcInRleHRcIixcbiAgICBtZWRpYVR5cGU6IHBhdGguZW5kc1dpdGgoXCIuc3dpZnRcIikgPyBcInRleHQveC1zd2lmdFwiIDogcGF0aC5lbmRzV2l0aChcIi5qc29uXCIpID8gXCJhcHBsaWNhdGlvbi9qc29uXCIgOlxuICAgICAgcGF0aC5lbmRzV2l0aChcIi5wbGlzdFwiKSB8fCBwYXRoLmVuZHNXaXRoKFwiLnhjc2NoZW1lXCIpID8gXCJhcHBsaWNhdGlvbi94bWxcIiA6IFwidGV4dC9wbGFpblwiLFxuICAgIG93bmVyc2hpcDogXCJnZW5lcmF0ZWRcIixcbiAgICBwYXRoLFxuICAgIHByb3ZlbmFuY2U6IHtraW5kOiBcInN5bnRoZXRpY1wiLCByZWFzb24sIHJlbGF0ZWRPcmlnaW5zOiBbXX0sXG4gICAgcm9sZVxuICB9XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIHN5bnRoZXRpYyBhcnRpZmFjdCBhbmQgdHJhbnNmZXJzIGl0cyByZW5kZXJlci1vd25lZCBjb25maWd1cmF0aW9uIHNwYW5zIHRvIHRoZSBtYW5pZmVzdCBsZWRnZXIuXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aCAtIEFydGlmYWN0IHBhdGguXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkdlbmVyYXRlZEFydGlmYWN0Um9sZX0gcm9sZSAtIEFydGlmYWN0IHJvbGUuXG4gKiBAcGFyYW0ge1JlbmRlcmVkQ29uZmlndXJhdGlvblRleHR9IHJlbmRlcmVkIC0gUmVuZGVyZWQgY29udGVudCBhbmQgY2F1c2FsIHNwYW5zLlxuICogQHBhcmFtIHtDb25maWd1cmF0aW9uQXJ0aWZhY3RTcGFuW119IHNwYW5zIC0gQXBwbGljYXRpb24td2lkZSBjYXVzYWwgc3BhbiBsZWRnZXIuXG4gKiBAcGFyYW0ge3N0cmluZ30gcmVhc29uIC0gUHJvdmVuYW5jZSByZWFzb24uXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuR2VuZXJhdGVkU2V0QXJ0aWZhY3R9IEFydGlmYWN0IGNhbmRpZGF0ZS5cbiAqL1xuZnVuY3Rpb24gY29uZmlndXJlZFN5bnRoZXRpY1RleHQocGF0aCwgcm9sZSwgcmVuZGVyZWQsIHNwYW5zLCByZWFzb24pIHtcbiAgc3BhbnMucHVzaCguLi5yZW5kZXJlZC5jb25maWd1cmF0aW9uU3BhbnMubWFwKHNwYW4gPT4gKHsuLi5zcGFuLCBwYXRofSkpKVxuXG4gIHJldHVybiBzeW50aGV0aWNUZXh0KHBhdGgsIHJvbGUsIHJlbmRlcmVkLmNvbnRlbnQsIHJlYXNvbilcbn1cblxuLyoqXG4gKiBTZXJpYWxpemVzIHJlY3Vyc2l2ZWx5IHNvcnRlZCBjYW5vbmljYWwgSlNPTiB3aXRoIGFuIExGLlxuICogQHBhcmFtIHt1bmtub3dufSB2YWx1ZSAtIEpTT04gdmFsdWUuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBDYW5vbmljYWwgSlNPTiB3aXRoIExGLlxuICovXG5mdW5jdGlvbiBzdHJpbmdpZnlDYW5vbmljYWxKc29uKHZhbHVlKSB7XG4gIHJldHVybiBgJHtKU09OLnN0cmluZ2lmeShzb3J0SnNvbih2YWx1ZSksIG51bGwsIDIpfVxcbmBcbn1cblxuLyoqXG4gKiBSZWN1cnNpdmVseSBzb3J0cyBKU09OIG9iamVjdCBrZXlzIHdpdGhvdXQgcmVvcmRlcmluZyBhcnJheXMuXG4gKiBAcGFyYW0ge3Vua25vd259IHZhbHVlIC0gSlNPTiB2YWx1ZS5cbiAqIEByZXR1cm5zIHt1bmtub3dufSBSZWN1cnNpdmVseSBrZXktc29ydGVkIEpTT04uXG4gKi9cbmZ1bmN0aW9uIHNvcnRKc29uKHZhbHVlKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkgcmV0dXJuIHZhbHVlLm1hcChzb3J0SnNvbilcbiAgaWYgKCFpc1BsYWluT2JqZWN0KHZhbHVlKSkgcmV0dXJuIHZhbHVlXG5cbiAgcmV0dXJuIE9iamVjdC5mcm9tRW50cmllcyhPYmplY3Qua2V5cyh2YWx1ZSkuc29ydCgpLm1hcChrZXkgPT4gW2tleSwgc29ydEpzb24odmFsdWVba2V5XSldKSlcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgYW5kIHNuYXBzaG90cyB0aGUgc3RyaWN0IGJhc2VsaW5lIGFwcGxpY2F0aW9uIGNvbmZpZ3VyYXRpb24uXG4gKiBJZGVudGl0eSBhbmQgZGVwbG95bWVudCBmaWVsZHMgaW50ZW50aW9uYWxseSBoYXZlIG5vIGRlZmF1bHRzIHdpdGhvdXQgQXBwbGUtbGFuZSBldmlkZW5jZS5cbiAqIEBwYXJhbSB7dW5rbm93bn0gY2FuZGlkYXRlIC0gQ2FuZGlkYXRlIGNvbmZpZ3VyYXRpb24uXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuSW9zQXBwbGljYXRpb25Db25maWd1cmF0aW9ufSBOb3JtYWxpemVkIGNvbmZpZ3VyYXRpb24uXG4gKi9cbmZ1bmN0aW9uIG5vcm1hbGl6ZUNvbmZpZ3VyYXRpb24oY2FuZGlkYXRlKSB7XG4gIGlmICghaXNQbGFpbk9iamVjdChjYW5kaWRhdGUpIHx8IE9iamVjdC5rZXlzKGNhbmRpZGF0ZSkuc29tZShrZXkgPT4gIWNvbmZpZ3VyYXRpb25GaWVsZHMuaGFzKGtleSkpKSB7XG4gICAgaW52YWxpZENvbmZpZ3VyYXRpb24oXCJpT1MgYXBwbGljYXRpb24gY29uZmlndXJhdGlvbiBtdXN0IGJlIGEgY2xvc2VkIHBsYWluIG9iamVjdC5cIilcbiAgfVxuICBjb25zdCBwcm9kdWN0TmFtZSA9IGNhbmRpZGF0ZS5wcm9kdWN0TmFtZVxuICBjb25zdCBtb2R1bGVOYW1lID0gY2FuZGlkYXRlLm1vZHVsZU5hbWVcbiAgY29uc3Qgb3JnYW5pemF0aW9uUHJlZml4ID0gY2FuZGlkYXRlLm9yZ2FuaXphdGlvblByZWZpeFxuICBjb25zdCBidW5kbGVJZGVudGlmaWVyID0gY2FuZGlkYXRlLmJ1bmRsZUlkZW50aWZpZXJcbiAgY29uc3QgZGVwbG95bWVudFRhcmdldCA9IGNhbmRpZGF0ZS5kZXBsb3ltZW50VGFyZ2V0XG4gIGNvbnN0IGRpc3BsYXlOYW1lID0gY2FuZGlkYXRlLmRpc3BsYXlOYW1lXG5cbiAgaWYgKHR5cGVvZiBwcm9kdWN0TmFtZSAhPSBcInN0cmluZ1wiIHx8ICEvXltBLVpdW0EtWmEtejAtOV0qJC91LnRlc3QocHJvZHVjdE5hbWUpKSB7XG4gICAgaW52YWxpZENvbmZpZ3VyYXRpb24oXCJQcm9kdWN0IG5hbWUgbXVzdCBiZSBhbiBBU0NJSSB1cHBlci1jYW1lbCBpZGVudGlmaWVyLlwiKVxuICB9XG4gIGlmICh0eXBlb2YgbW9kdWxlTmFtZSAhPSBcInN0cmluZ1wiIHx8ICEvXltBLVpdW0EtWmEtejAtOV0qJC91LnRlc3QobW9kdWxlTmFtZSkpIHtcbiAgICBpbnZhbGlkQ29uZmlndXJhdGlvbihcIk1vZHVsZSBuYW1lIG11c3QgYmUgYW4gQVNDSUkgdXBwZXItY2FtZWwgaWRlbnRpZmllci5cIilcbiAgfVxuICBpZiAodHlwZW9mIG9yZ2FuaXphdGlvblByZWZpeCAhPSBcInN0cmluZ1wiIHx8ICFpc1JldmVyc2VEbnMob3JnYW5pemF0aW9uUHJlZml4LCAyKSkge1xuICAgIGludmFsaWRDb25maWd1cmF0aW9uKFwiT3JnYW5pemF0aW9uIHByZWZpeCBtdXN0IGJlIGEgbG93ZXJjYXNlIHJldmVyc2UtRE5TIGlkZW50aXR5IHdpdGggYXQgbGVhc3QgdHdvIHNlZ21lbnRzLlwiKVxuICB9XG4gIGlmICh0eXBlb2YgYnVuZGxlSWRlbnRpZmllciAhPSBcInN0cmluZ1wiIHx8ICFpc1JldmVyc2VEbnMoYnVuZGxlSWRlbnRpZmllciwgMykgfHxcbiAgICAhYnVuZGxlSWRlbnRpZmllci5zdGFydHNXaXRoKGAke29yZ2FuaXphdGlvblByZWZpeH0uYCkpIHtcbiAgICBpbnZhbGlkQ29uZmlndXJhdGlvbihcIkJ1bmRsZSBpZGVudGlmaWVyIG11c3QgZXh0ZW5kIHRoZSBleGFjdCBvcmdhbml6YXRpb24gcHJlZml4IGFzIGxvd2VyY2FzZSByZXZlcnNlIEROUy5cIilcbiAgfVxuICBpZiAodHlwZW9mIGRlcGxveW1lbnRUYXJnZXQgIT0gXCJzdHJpbmdcIiB8fCAhL15bMS05XVswLTldKlxcLig/OjB8WzEtOV1bMC05XSopJC91LnRlc3QoZGVwbG95bWVudFRhcmdldCkpIHtcbiAgICBpbnZhbGlkQ29uZmlndXJhdGlvbihcIkRlcGxveW1lbnQgdGFyZ2V0IG11c3QgYmUgYSBjYWxsZXItc3VwcGxpZWQgY2Fub25pY2FsIG1ham9yLm1pbm9yIHZlcnNpb24uXCIpXG4gIH1cbiAgaWYgKHR5cGVvZiBkaXNwbGF5TmFtZSAhPSBcInN0cmluZ1wiIHx8IGRpc3BsYXlOYW1lLmxlbmd0aCA9PSAwIHx8IGRpc3BsYXlOYW1lLnRyaW0oKSAhPSBkaXNwbGF5TmFtZSB8fFxuICAgIFsuLi5kaXNwbGF5TmFtZV0ubGVuZ3RoID4gNjQgfHwgIWhhc09ubHlVbmljb2RlU2NhbGFycyhkaXNwbGF5TmFtZSkgfHwgL1xccHtDY30vdS50ZXN0KGRpc3BsYXlOYW1lKSkge1xuICAgIGludmFsaWRDb25maWd1cmF0aW9uKFwiRGlzcGxheSBuYW1lIG11c3QgYmUgYSBub24tZW1wdHkgc2luZ2xlLWxpbmUgVW5pY29kZSBzY2FsYXIgc3RyaW5nIG9mIGF0IG1vc3QgNjQgY2hhcmFjdGVycy5cIilcbiAgfVxuICBjb25zdCBzb3VyY2VSb290ID0gY2FuZGlkYXRlLnNvdXJjZVJvb3QgPz8gXCJTb3VyY2VzXCJcbiAgY29uc3QgcmVzb3VyY2VSb290ID0gY2FuZGlkYXRlLnJlc291cmNlUm9vdCA/PyBcIkFzc2V0cy54Y2Fzc2V0c1wiXG4gIGNvbnN0IGxpZmVjeWNsZSA9IGNhbmRpZGF0ZS5saWZlY3ljbGUgPz8gXCJzd2lmdHVpXCJcblxuICBpZiAoc291cmNlUm9vdCAhPSBcIlNvdXJjZXNcIiB8fCAhaXNTYWZlQXJ0aWZhY3RQYXRoKHNvdXJjZVJvb3QpKSBpbnZhbGlkQ29uZmlndXJhdGlvbihcIlRoZSBzdXBwb3J0ZWQgc291cmNlIHJvb3QgaXMgZXhhY3RseSAnU291cmNlcycuXCIpXG4gIGlmIChyZXNvdXJjZVJvb3QgIT0gXCJBc3NldHMueGNhc3NldHNcIiB8fCAhaXNTYWZlQXJ0aWZhY3RQYXRoKHJlc291cmNlUm9vdCkpIHtcbiAgICBpbnZhbGlkQ29uZmlndXJhdGlvbihcIlRoZSBzdXBwb3J0ZWQgcmVzb3VyY2Ugcm9vdCBpcyBleGFjdGx5ICdBc3NldHMueGNhc3NldHMnLlwiKVxuICB9XG4gIGlmIChsaWZlY3ljbGUgIT0gXCJzd2lmdHVpXCIpIGludmFsaWRDb25maWd1cmF0aW9uKFwiVGhlIHN1cHBvcnRlZCBhcHBsaWNhdGlvbiBsaWZlY3ljbGUgaXMgZXhhY3RseSAnc3dpZnR1aScuXCIpXG4gIGNvbnN0IGluZm9QbGlzdCA9IGNhbmRpZGF0ZS5pbmZvUGxpc3QgPz8ge31cblxuICBpZiAoIWlzUGxhaW5PYmplY3QoaW5mb1BsaXN0KSB8fCBPYmplY3Qua2V5cyhpbmZvUGxpc3QpLmxlbmd0aCA+IDApIHtcbiAgICBpbnZhbGlkQ29uZmlndXJhdGlvbihcIlRoZSBiYXNlbGluZSBjYWxsZXIgSW5mby5wbGlzdCBleHRlbnNpb24gYWxsb3dsaXN0IGlzIGVtcHR5LlwiKVxuICB9XG4gIGNvbnN0IHBlcm1pc3Npb25zID0gZW1wdHlDb25maWd1cmF0aW9uU2V0KGNhbmRpZGF0ZS5wZXJtaXNzaW9ucywgXCJwZXJtaXNzaW9uc1wiKVxuICBjb25zdCBlbnRpdGxlbWVudHMgPSBlbXB0eUNvbmZpZ3VyYXRpb25TZXQoY2FuZGlkYXRlLmVudGl0bGVtZW50cywgXCJlbnRpdGxlbWVudHNcIilcbiAgY29uc3QgcHJpdmFjeURlY2xhcmF0aW9ucyA9IGVtcHR5Q29uZmlndXJhdGlvblNldChjYW5kaWRhdGUucHJpdmFjeURlY2xhcmF0aW9ucywgXCJwcml2YWN5IGRlY2xhcmF0aW9uc1wiKVxuICBjb25zdCBjYXBhYmlsaXRpZXMgPSBlbXB0eUNvbmZpZ3VyYXRpb25TZXQoY2FuZGlkYXRlLmNhcGFiaWxpdGllcywgXCJjYXBhYmlsaXRpZXNcIilcblxuICByZXR1cm4ge1xuICAgIGJ1bmRsZUlkZW50aWZpZXIsXG4gICAgY2FwYWJpbGl0aWVzLFxuICAgIGRlcGxveW1lbnRUYXJnZXQsXG4gICAgZGlzcGxheU5hbWUsXG4gICAgZW50aXRsZW1lbnRzLFxuICAgIGluZm9QbGlzdDoge30sXG4gICAgbGlmZWN5Y2xlOiBcInN3aWZ0dWlcIixcbiAgICBtb2R1bGVOYW1lLFxuICAgIG9yZ2FuaXphdGlvblByZWZpeCxcbiAgICBwZXJtaXNzaW9ucyxcbiAgICBwcml2YWN5RGVjbGFyYXRpb25zLFxuICAgIHByb2R1Y3ROYW1lLFxuICAgIHJlc291cmNlUm9vdDogXCJBc3NldHMueGNhc3NldHNcIixcbiAgICBzb3VyY2VSb290OiBcIlNvdXJjZXNcIlxuICB9XG59XG5cbi8qKlxuICogVmFsaWRhdGVzIG9uZSBvcHRpb25hbCBjbG9zZWQgZW1wdHkgY29uZmlndXJhdGlvbiBzZXQuXG4gKiBAcGFyYW0ge3Vua25vd259IGNhbmRpZGF0ZSAtIE9wdGlvbmFsIGNsb3NlZCBzZXQuXG4gKiBAcGFyYW0ge3N0cmluZ30gbGFiZWwgLSBEaWFnbm9zdGljIGxhYmVsLlxuICogQHJldHVybnMge25ldmVyW119IEVtcHR5IHNuYXBzaG90LlxuICovXG5mdW5jdGlvbiBlbXB0eUNvbmZpZ3VyYXRpb25TZXQoY2FuZGlkYXRlLCBsYWJlbCkge1xuICBpZiAoY2FuZGlkYXRlID09PSB1bmRlZmluZWQpIHJldHVybiBbXVxuICBpZiAoIWlzRGVuc2VBcnJheShjYW5kaWRhdGUpIHx8IGNhbmRpZGF0ZS5sZW5ndGggIT0gMCkgaW52YWxpZENvbmZpZ3VyYXRpb24oYFRoZSBiYXNlbGluZSAke2xhYmVsfSBzZXQgbXVzdCBiZSBlbXB0eS5gKVxuXG4gIHJldHVybiBbXVxufVxuXG4vKipcbiAqIFRlc3RzIG9uZSBjYW5vbmljYWwgbG93ZXJjYXNlIHJldmVyc2UtRE5TIGlkZW50aXR5LlxuICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlIC0gQ2FuZGlkYXRlIGlkZW50aXR5LlxuICogQHBhcmFtIHtudW1iZXJ9IHNlZ21lbnRzIC0gTWluaW11bSBzZWdtZW50cy5cbiAqIEByZXR1cm5zIHtib29sZWFufSBWYWxpZGl0eS5cbiAqL1xuZnVuY3Rpb24gaXNSZXZlcnNlRG5zKHZhbHVlLCBzZWdtZW50cykge1xuICBjb25zdCBwYXJ0cyA9IHZhbHVlLnNwbGl0KFwiLlwiKVxuXG4gIHJldHVybiBwYXJ0cy5sZW5ndGggPj0gc2VnbWVudHMgJiYgcGFydHMuZXZlcnkocGFydCA9PiAvXlthLXpdW2EtejAtOS1dKiQvdS50ZXN0KHBhcnQpICYmICFwYXJ0LmVuZHNXaXRoKFwiLVwiKSlcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMsIGhhc2hlcywgc25hcHNob3RzLCBhbmQgY2Fub25pY2FsbHkgc29ydHMgY2FsbGVyIGFzc2V0cy5cbiAqIEBwYXJhbSB7dW5rbm93bn0gY2FuZGlkYXRlIC0gQ2FuZGlkYXRlIGFzc2V0IGFycmF5LlxuICogQHBhcmFtIHtzdHJpbmd9IHJlc291cmNlUm9vdCAtIEV4YWN0IHJlc291cmNlIHJvb3QuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuSW9zQXBwbGljYXRpb25Bc3NldElucHV0W119IE5vcm1hbGl6ZWQgYXNzZXRzLlxuICovXG5mdW5jdGlvbiBub3JtYWxpemVBc3NldHMoY2FuZGlkYXRlLCByZXNvdXJjZVJvb3QpIHtcbiAgaWYgKGNhbmRpZGF0ZSA9PT0gdW5kZWZpbmVkKSByZXR1cm4gW11cbiAgaWYgKCFpc0RlbnNlQXJyYXkoY2FuZGlkYXRlKSkgaW52YWxpZEFzc2V0KFwiQXBwbGljYXRpb24gYXNzZXRzIG11c3QgYmUgYSBkZW5zZSBhcnJheS5cIilcbiAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Jb3NBcHBsaWNhdGlvbkFzc2V0SW5wdXRbXX0gKi9cbiAgY29uc3QgYXNzZXRzID0gW11cblxuICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgY2FuZGlkYXRlLmxlbmd0aDsgaW5kZXggKz0gMSkge1xuICAgIGNvbnN0IGFzc2V0ID0gY2FuZGlkYXRlW2luZGV4XVxuXG4gICAgaWYgKCFpc1BsYWluT2JqZWN0KGFzc2V0KSB8fCBPYmplY3Qua2V5cyhhc3NldCkuc29tZShrZXkgPT4gIWFzc2V0RmllbGRzLmhhcyhrZXkpKSB8fFxuICAgICAgT2JqZWN0LmtleXMoYXNzZXQpLmxlbmd0aCAhPSBhc3NldEZpZWxkcy5zaXplKSBpbnZhbGlkQXNzZXQoYEFzc2V0ICR7aW5kZXh9IG11c3QgdXNlIHRoZSBjbG9zZWQgYXNzZXQgc2NoZW1hLmApXG4gICAgY29uc3QgcGF0aCA9IGFzc2V0LnBhdGhcbiAgICBjb25zdCBjb250ZW50ID0gYXNzZXQuY29udGVudFxuICAgIGNvbnN0IG1lZGlhVHlwZSA9IGFzc2V0Lm1lZGlhVHlwZVxuICAgIGNvbnN0IHNoYTI1NiA9IGFzc2V0LnNoYTI1NlxuXG4gICAgaWYgKCFpc1NhZmVBcnRpZmFjdFBhdGgocGF0aCkgfHwgIXBhdGguc3RhcnRzV2l0aChgJHtyZXNvdXJjZVJvb3R9L2ApIHx8IHBhdGggPT0gYCR7cmVzb3VyY2VSb290fS9Db250ZW50cy5qc29uYCkge1xuICAgICAgaW52YWxpZEFzc2V0KGBBc3NldCAke2luZGV4fSByZXF1aXJlcyBhIHNhZmUgcGF0aCBiZWxvdyAnJHtyZXNvdXJjZVJvb3R9Jy5gKVxuICAgIH1cbiAgICBpZiAodHlwZW9mIGNvbnRlbnQgIT0gXCJzdHJpbmdcIiAmJiAhKGNvbnRlbnQgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB8fFxuICAgICAgdHlwZW9mIGNvbnRlbnQgPT0gXCJzdHJpbmdcIiAmJiAoY29udGVudC5sZW5ndGggPT0gMCB8fCAhaGFzT25seVVuaWNvZGVTY2FsYXJzKGNvbnRlbnQpKSB8fFxuICAgICAgY29udGVudCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkgJiYgY29udGVudC5ieXRlTGVuZ3RoID09IDApIGludmFsaWRBc3NldChgQXNzZXQgJyR7cGF0aH0nIHJlcXVpcmVzIG5vbi1lbXB0eSBleGFjdCBjb250ZW50LmApXG4gICAgaWYgKHR5cGVvZiBtZWRpYVR5cGUgIT0gXCJzdHJpbmdcIiB8fCAhbWVkaWFUeXBlUGF0dGVybi50ZXN0KG1lZGlhVHlwZSkgfHwgL1tcXHJcXG5dL3UudGVzdChtZWRpYVR5cGUpKSB7XG4gICAgICBpbnZhbGlkQXNzZXQoYEFzc2V0ICcke3BhdGh9JyByZXF1aXJlcyBhbiBleHBsaWNpdCB2YWxpZCBtZWRpYSB0eXBlLmApXG4gICAgfVxuICAgIGNvbnN0IHNuYXBzaG90ID0gdHlwZW9mIGNvbnRlbnQgPT0gXCJzdHJpbmdcIiA/IGNvbnRlbnQgOiBuZXcgVWludDhBcnJheShjb250ZW50KVxuICAgIGNvbnN0IGFjdHVhbEhhc2ggPSBjcmVhdGVIYXNoKFwic2hhMjU2XCIpLnVwZGF0ZShzbmFwc2hvdCkuZGlnZXN0KFwiaGV4XCIpXG5cbiAgICBpZiAodHlwZW9mIHNoYTI1NiAhPSBcInN0cmluZ1wiIHx8ICEvXlswLTlhLWZdezY0fSQvdS50ZXN0KHNoYTI1NikgfHwgc2hhMjU2ICE9IGFjdHVhbEhhc2gpIHtcbiAgICAgIGludmFsaWRBc3NldChgQXNzZXQgJyR7cGF0aH0nIFNIQS0yNTYgZG9lcyBub3QgbWF0Y2ggaXRzIGV4YWN0IGNvbnRlbnQuYClcbiAgICB9XG4gICAgYXNzZXRzLnB1c2goe2NvbnRlbnQ6IHNuYXBzaG90LCBtZWRpYVR5cGUsIHBhdGgsIHNoYTI1Nn0pXG4gIH1cbiAgYXNzZXRzLnNvcnQoKGxlZnQsIHJpZ2h0KSA9PiBsZWZ0LnBhdGggPCByaWdodC5wYXRoID8gLTEgOiBsZWZ0LnBhdGggPiByaWdodC5wYXRoID8gMSA6IDApXG5cbiAgcmV0dXJuIGFzc2V0c1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYW4gZXhhY3QgdGV4dCBvciBiaW5hcnkgYXNzZXQgYXJ0aWZhY3QuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLklvc0FwcGxpY2F0aW9uQXNzZXRJbnB1dH0gYXNzZXQgLSBWYWxpZGF0ZWQgYXNzZXQuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuR2VuZXJhdGVkU2V0QXJ0aWZhY3R9IEFydGlmYWN0IGNhbmRpZGF0ZS5cbiAqL1xuZnVuY3Rpb24gYXNzZXRBcnRpZmFjdChhc3NldCkge1xuICBpZiAodHlwZW9mIGFzc2V0LmNvbnRlbnQgPT0gXCJzdHJpbmdcIikgcmV0dXJuIHtcbiAgICBjb250ZW50OiBhc3NldC5jb250ZW50LFxuICAgIGNvbnRlbnRLaW5kOiBcInRleHRcIixcbiAgICBtZWRpYVR5cGU6IGFzc2V0Lm1lZGlhVHlwZSxcbiAgICBvd25lcnNoaXA6IFwiZ2VuZXJhdGVkXCIsXG4gICAgcGF0aDogYXNzZXQucGF0aCxcbiAgICBwcm92ZW5hbmNlOiB7a2luZDogXCJzeW50aGV0aWNcIiwgcmVhc29uOiBgRXhhY3QgY2FsbGVyLXByb3ZpZGVkIGlPUyBhc3NldCAoc2hhMjU2OiR7YXNzZXQuc2hhMjU2fSkuYCwgcmVsYXRlZE9yaWdpbnM6IFtdfSxcbiAgICByb2xlOiBcInJlc291cmNlXCJcbiAgfVxuICBjb25zdCBjb250ZW50ID0gbmV3IFVpbnQ4QXJyYXkoYXNzZXQuY29udGVudClcblxuICByZXR1cm4ge1xuICAgIGNvbnRlbnQsXG4gICAgY29udGVudEtpbmQ6IFwiYmluYXJ5XCIsXG4gICAgbWVkaWFUeXBlOiBhc3NldC5tZWRpYVR5cGUsXG4gICAgb3duZXJzaGlwOiBcImdlbmVyYXRlZFwiLFxuICAgIHBhdGg6IGFzc2V0LnBhdGgsXG4gICAgcHJvdmVuYW5jZToge2tpbmQ6IFwiYnl0ZXNcIiwgbWFwcGluZzogY3JlYXRlQnl0ZU1hcHBpbmcoe1xuICAgICAgYnl0ZUxlbmd0aDogY29udGVudC5ieXRlTGVuZ3RoLFxuICAgICAgcGF0aDogYXNzZXQucGF0aCxcbiAgICAgIHJhbmdlczogW3tcbiAgICAgICAgZ2VuZXJhdGVkOiB7ZW5kOiBjb250ZW50LmJ5dGVMZW5ndGgsIHN0YXJ0OiAwfSxcbiAgICAgICAgb3JpZ2luOiB7a2luZDogXCJzeW50aGV0aWNcIiwgcmVhc29uOiBgRXhhY3QgY2FsbGVyLXByb3ZpZGVkIGlPUyBhc3NldCAoc2hhMjU2OiR7YXNzZXQuc2hhMjU2fSkuYCwgcmVsYXRlZE9yaWdpbnM6IFtdfSxcbiAgICAgICAgcm9sZTogXCJhc3NldFwiXG4gICAgICB9XVxuICAgIH0pfSxcbiAgICByb2xlOiBcInJlc291cmNlXCJcbiAgfVxufVxuXG4vKipcbiAqIFRocm93cyBhIGNvbmZpZ3VyYXRpb24gZGlhZ25vc3RpYy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gRmFpbHVyZSBkZXRhaWwuXG4gKiBAcmV0dXJucyB7bmV2ZXJ9IEFsd2F5cyB0aHJvd3MuXG4gKi9cbmZ1bmN0aW9uIGludmFsaWRDb25maWd1cmF0aW9uKG1lc3NhZ2UpIHtcbiAgdGhyb3cgbmV3IFNlbWFudGlmb2xkRGlhZ25vc3RpYyh7Y29kZTogXCJJTlZBTElEX0FQUExJQ0FUSU9OX0NPTkZJR1VSQVRJT05cIiwgbGFuZ3VhZ2U6IFwiaW9zXCIsIG1lc3NhZ2V9KVxufVxuXG4vKipcbiAqIFRocm93cyBhbiBhc3NldCBkaWFnbm9zdGljLlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBGYWlsdXJlIGRldGFpbC5cbiAqIEByZXR1cm5zIHtuZXZlcn0gQWx3YXlzIHRocm93cy5cbiAqL1xuZnVuY3Rpb24gaW52YWxpZEFzc2V0KG1lc3NhZ2UpIHtcbiAgdGhyb3cgbmV3IFNlbWFudGlmb2xkRGlhZ25vc3RpYyh7Y29kZTogXCJJTlZBTElEX0FQUExJQ0FUSU9OX0FTU0VUXCIsIGxhbmd1YWdlOiBcImlvc1wiLCBtZXNzYWdlfSlcbn1cblxuLyoqXG4gKiBUaHJvd3MgYW4gYXBwbGljYXRpb24tcGF0aCBkaWFnbm9zdGljLlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBGYWlsdXJlIGRldGFpbC5cbiAqIEByZXR1cm5zIHtuZXZlcn0gQWx3YXlzIHRocm93cy5cbiAqL1xuZnVuY3Rpb24gaW52YWxpZFBhdGgobWVzc2FnZSkge1xuICB0aHJvdyBuZXcgU2VtYW50aWZvbGREaWFnbm9zdGljKHtjb2RlOiBcIklOVkFMSURfQVBQTElDQVRJT05fUEFUSFwiLCBsYW5ndWFnZTogXCJpb3NcIiwgbWVzc2FnZX0pXG59XG5cbi8qKlxuICogRW1pdHMgb25lIGJhY2tlbmQtbmFtZXNwYWNlZCBzZW1hbnRpYyBtb2R1bGUuXG4gKiBAcGFyYW0ge1NvdXJjZVdyaXRlcn0gd3JpdGVyIC0gU291cmNlLWF3YXJlIGdlbmVyYXRlZCBTd2lmdCB3cml0ZXIuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljTW9kdWxlfSBtb2R1bGUgLSBQcmVwYXJlZCBzZW1hbnRpYyBtb2R1bGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gbW9kdWxlSWQgLSBTdGFibGUgcHJvamVjdCBtb2R1bGUgaWRlbnRpdHkuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGVudHJ5IC0gV2hldGhlciB0aGlzIG1vZHVsZSBvd25zIHRoZSBzZW1hbnRpYyBlbnRyeS5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZyB8IHVuZGVmaW5lZCwge2RlY2xhcmF0aW9uOiBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5GdW5jdGlvbkRlY2xhcmF0aW9uLCBtb2R1bGVJZDogc3RyaW5nfT59IGRlY2xhcmF0aW9ucyAtIFJlc29sdmVkIGZ1bmN0aW9ucy5cbiAqL1xuZnVuY3Rpb24gZW1pdFNlbWFudGljTW9kdWxlKHdyaXRlciwgbW9kdWxlLCBtb2R1bGVJZCwgZW50cnksIGRlY2xhcmF0aW9ucykge1xuICBjb25zdCBuYW1lc3BhY2UgPSBgU2VtYW50aWZvbGRNb2R1bGUke21vZHVsZU5hbWUobW9kdWxlSWQpfWBcblxuICB3cml0ZXIuc3ludGhldGljKGBlbnVtICR7bmFtZXNwYWNlfSB7XFxuYCwgXCJpT1Mgc2VtYW50aWMgbW9kdWxlIG5hbWVzcGFjZVwiLCBbbW9kdWxlXSwgW1wiXCJdKVxuICBtb2R1bGUuZnVuY3Rpb25zLmZvckVhY2goKGRlY2xhcmF0aW9uLCBmdW5jdGlvbkluZGV4KSA9PiB7XG4gICAgY29uc3QgcGF0aCA9IGAvZnVuY3Rpb25zLyR7ZnVuY3Rpb25JbmRleH1gXG5cbiAgICB3cml0ZXIuc3ludGhldGljKFwiICBzdGF0aWMgXCIsIFwiaU9TIG5hbWVzcGFjZWQgZnVuY3Rpb24gc2NhZmZvbGRcIiwgW2RlY2xhcmF0aW9uXSwgW3BhdGhdKVxuICAgIHdyaXRlci5tYXBwZWQoXCJmdW5jXCIsIHttYXBwaW5nS2luZDogXCJhbmNob3JcIiwgbm9kZTogZGVjbGFyYXRpb24sIHBhdGh9KVxuICAgIHdyaXRlci5zeW50aGV0aWMoXCIgXCIsIFwiZGVjbGFyYXRpb24gc3BhY2luZ1wiLCBbZGVjbGFyYXRpb25dLCBbcGF0aF0pXG4gICAgd3JpdGVyLm1hcHBlZChkZWNsYXJhdGlvbi5uYW1lLCB7bWFwcGluZ0tpbmQ6IFwiZXhhY3RcIiwgbm9kZTogZGVjbGFyYXRpb24sIHBhdGgsIHJvbGU6IFwibmFtZVwifSlcbiAgICB3cml0ZXIuc3ludGhldGljKFwiKFwiLCBcImZ1bmN0aW9uIHBhcmFtZXRlciBzY2FmZm9sZFwiLCBbZGVjbGFyYXRpb25dLCBbcGF0aF0pXG4gICAgZGVjbGFyYXRpb24ucGFyYW1ldGVycy5mb3JFYWNoKChwYXJhbWV0ZXIsIHBhcmFtZXRlckluZGV4KSA9PiB7XG4gICAgICBjb25zdCBwYXJhbWV0ZXJQYXRoID0gYCR7cGF0aH0vcGFyYW1ldGVycy8ke3BhcmFtZXRlckluZGV4fWBcblxuICAgICAgaWYgKHBhcmFtZXRlckluZGV4KSB3cml0ZXIuc3ludGhldGljKFwiLCBcIiwgXCJwYXJhbWV0ZXIgc2VwYXJhdG9yXCIsIFtwYXJhbWV0ZXJdLCBbcGFyYW1ldGVyUGF0aF0pXG4gICAgICB3cml0ZXIuc3ludGhldGljKFwiXyBcIiwgXCJ1bmxhYmVsZWQgU3dpZnQgcGFyYW1ldGVyIHNjYWZmb2xkXCIsIFtwYXJhbWV0ZXJdLCBbcGFyYW1ldGVyUGF0aF0pXG4gICAgICB3cml0ZXIubWFwcGVkKHBhcmFtZXRlci5uYW1lLCB7bWFwcGluZ0tpbmQ6IFwiZXhhY3RcIiwgbm9kZTogcGFyYW1ldGVyLCBwYXRoOiBwYXJhbWV0ZXJQYXRoLCByb2xlOiBcIm5hbWVcIn0pXG4gICAgICB3cml0ZXIuc3ludGhldGljKFwiOiBcIiwgXCJwYXJhbWV0ZXIgYW5ub3RhdGlvbiBzY2FmZm9sZFwiLCBbcGFyYW1ldGVyXSwgW3BhcmFtZXRlclBhdGhdKVxuICAgICAgd3JpdGVyLm1hcHBlZChlbWl0U2NhbGFyVHlwZShcInN3aWZ0XCIsIHBhcmFtZXRlci50eXBlKSwge21hcHBpbmdLaW5kOiBcImV4YWN0XCIsIG5vZGU6IHBhcmFtZXRlci50eXBlLFxuICAgICAgICBwYXRoOiBgJHtwYXJhbWV0ZXJQYXRofS90eXBlYCwgcm9sZTogXCJ0eXBlXCJ9KVxuICAgIH0pXG4gICAgd3JpdGVyLnN5bnRoZXRpYyhcIiwgXyBzZW1hbnRpZm9sZF9vdXRwdXQ6IFNlbWFudGlmb2xkT3V0cHV0U2luaykgLT4gXCIsIFwic2hhcmVkIGlPUyBvdXRwdXQgc2luayBwYXJhbWV0ZXJcIiwgW2RlY2xhcmF0aW9uXSwgW3BhdGhdKVxuICAgIHdyaXRlci5tYXBwZWQoZW1pdFNjYWxhclR5cGUoXCJzd2lmdFwiLCBkZWNsYXJhdGlvbi5yZXR1cm5UeXBlKSwge21hcHBpbmdLaW5kOiBcImV4YWN0XCIsIG5vZGU6IGRlY2xhcmF0aW9uLnJldHVyblR5cGUsXG4gICAgICBwYXRoOiBgJHtwYXRofS9yZXR1cm5UeXBlYCwgcm9sZTogXCJ0eXBlXCJ9KVxuICAgIHdyaXRlci5zeW50aGV0aWMoXCIge1xcblwiLCBcIlN3aWZ0IGZ1bmN0aW9uIGJvZHkgc2NhZmZvbGRcIiwgW2RlY2xhcmF0aW9uXSwgW3BhdGhdKVxuICAgIGVtaXRCbG9jayh3cml0ZXIsIGRlY2xhcmF0aW9uLmJvZHksIFwiICAgIFwiLCBgJHtwYXRofS9ib2R5YCwgZGVjbGFyYXRpb25zKVxuICAgIHdyaXRlci5zeW50aGV0aWMoXCIgIH1cXG5cIiwgXCJTd2lmdCBmdW5jdGlvbiBib2R5IHNjYWZmb2xkXCIsIFtkZWNsYXJhdGlvbl0sIFtwYXRoXSlcbiAgfSlcbiAgaWYgKGVudHJ5KSB7XG4gICAgd3JpdGVyLnN5bnRoZXRpYyhcIiAgc3RhdGljIGZ1bmMgc2VtYW50aWZvbGRFbnRyeSgpIC0+IFtTdHJpbmddIHtcXG5cIiwgXCJpT1Mgc2VtYW50aWMgZW50cnkgc2NhZmZvbGRcIiwgW21vZHVsZS5lbnRyeVBvaW50XSwgW1wiL2VudHJ5UG9pbnRcIl0pXG4gICAgd3JpdGVyLnN5bnRoZXRpYyhcIiAgICBsZXQgc2VtYW50aWZvbGRfb3V0cHV0ID0gU2VtYW50aWZvbGRPdXRwdXRTaW5rKClcXG5cIiwgXCJzaGFyZWQgaU9TIG91dHB1dCBzaW5rIGFsbG9jYXRpb25cIixcbiAgICAgIFttb2R1bGUuZW50cnlQb2ludF0sIFtcIi9lbnRyeVBvaW50XCJdKVxuICAgIGVtaXRCbG9jayh3cml0ZXIsIG1vZHVsZS5lbnRyeVBvaW50LmJvZHksIFwiICAgIFwiLCBcIi9lbnRyeVBvaW50L2JvZHlcIiwgZGVjbGFyYXRpb25zKVxuICAgIHdyaXRlci5zeW50aGV0aWMoXCIgICAgcmV0dXJuIHNlbWFudGlmb2xkX291dHB1dC5saW5lc1xcblwiLCBcImlPUyBzZW1hbnRpYyBvdXRwdXQgcmV0dXJuXCIsIFttb2R1bGUuZW50cnlQb2ludF0sIFtcIi9lbnRyeVBvaW50XCJdKVxuICAgIHdyaXRlci5zeW50aGV0aWMoXCIgIH1cXG5cIiwgXCJpT1Mgc2VtYW50aWMgZW50cnkgc2NhZmZvbGRcIiwgW21vZHVsZS5lbnRyeVBvaW50XSwgW1wiL2VudHJ5UG9pbnRcIl0pXG4gIH1cbiAgd3JpdGVyLnN5bnRoZXRpYyhcIn1cXG5cIiwgXCJpT1Mgc2VtYW50aWMgbW9kdWxlIG5hbWVzcGFjZVwiLCBbbW9kdWxlXSwgW1wiXCJdKVxufVxuXG4vKipcbiAqIEVtaXRzIGEgdmFsaWRhdGVkIG9yZGVyZWQgc2VtYW50aWMgYmxvY2suXG4gKiBAcGFyYW0ge1NvdXJjZVdyaXRlcn0gd3JpdGVyIC0gU291cmNlIHdyaXRlci5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuQmxvY2t9IGJsb2NrIC0gU2VtYW50aWMgYmxvY2suXG4gKiBAcGFyYW0ge3N0cmluZ30gaW5kZW50IC0gQ3VycmVudCBpbmRlbnRhdGlvbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIC0gQmxvY2sgb2NjdXJyZW5jZSBwYXRoLlxuICogQHBhcmFtIHtNYXA8c3RyaW5nIHwgdW5kZWZpbmVkLCB7ZGVjbGFyYXRpb246IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkZ1bmN0aW9uRGVjbGFyYXRpb24sIG1vZHVsZUlkOiBzdHJpbmd9Pn0gZGVjbGFyYXRpb25zIC0gUmVzb2x2ZWQgZnVuY3Rpb25zLlxuICovXG5mdW5jdGlvbiBlbWl0QmxvY2sod3JpdGVyLCBibG9jaywgaW5kZW50LCBwYXRoLCBkZWNsYXJhdGlvbnMpIHtcbiAgYmxvY2suc3RhdGVtZW50cy5mb3JFYWNoKChzdGF0ZW1lbnQsIGluZGV4KSA9PiBlbWl0U3RhdGVtZW50KHdyaXRlciwgc3RhdGVtZW50LCBpbmRlbnQsIGAke3BhdGh9L3N0YXRlbWVudHMvJHtpbmRleH1gLCBkZWNsYXJhdGlvbnMpKVxufVxuXG4vKipcbiAqIEVtaXRzIG9uZSBTd2lmdCBzdGF0ZW1lbnQgdGhyb3VnaCB0aGUgc2hhcmVkIGNhcHR1cmUgc2luay5cbiAqIEBwYXJhbSB7U291cmNlV3JpdGVyfSB3cml0ZXIgLSBTb3VyY2Ugd3JpdGVyLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TdGF0ZW1lbnR9IHN0YXRlbWVudCAtIFZhbGlkYXRlZCBzdGF0ZW1lbnQuXG4gKiBAcGFyYW0ge3N0cmluZ30gaW5kZW50IC0gQ3VycmVudCBpbmRlbnRhdGlvbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIC0gU3RhdGVtZW50IG9jY3VycmVuY2UgcGF0aC5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZyB8IHVuZGVmaW5lZCwge2RlY2xhcmF0aW9uOiBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5GdW5jdGlvbkRlY2xhcmF0aW9uLCBtb2R1bGVJZDogc3RyaW5nfT59IGRlY2xhcmF0aW9ucyAtIFJlc29sdmVkIGZ1bmN0aW9ucy5cbiAqL1xuZnVuY3Rpb24gZW1pdFN0YXRlbWVudCh3cml0ZXIsIHN0YXRlbWVudCwgaW5kZW50LCBwYXRoLCBkZWNsYXJhdGlvbnMpIHtcbiAgd3JpdGVyLnN5bnRoZXRpYyhpbmRlbnQsIFwiaW5kZW50YXRpb25cIiwgW3N0YXRlbWVudF0sIFtwYXRoXSlcbiAgaWYgKHN0YXRlbWVudC5raW5kID09IFwiTG9jYWxEZWNsYXJhdGlvblwiKSB7XG4gICAgd3JpdGVyLm1hcHBlZChzdGF0ZW1lbnQubXV0YWJsZSA/IFwidmFyXCIgOiBcImxldFwiLCB7bWFwcGluZ0tpbmQ6IFwiYW5jaG9yXCIsIG5vZGU6IHN0YXRlbWVudCwgcGF0aH0pXG4gICAgd3JpdGVyLnN5bnRoZXRpYyhcIiBcIiwgXCJkZWNsYXJhdGlvbiBzcGFjaW5nXCIsIFtzdGF0ZW1lbnRdLCBbcGF0aF0pXG4gICAgd3JpdGVyLm1hcHBlZChzdGF0ZW1lbnQubmFtZSwge21hcHBpbmdLaW5kOiBcImV4YWN0XCIsIG5vZGU6IHN0YXRlbWVudCwgcGF0aCwgcm9sZTogXCJuYW1lXCJ9KVxuICAgIHdyaXRlci5zeW50aGV0aWMoXCI6IFwiLCBcImxvY2FsIGFubm90YXRpb24gc2NhZmZvbGRcIiwgW3N0YXRlbWVudF0sIFtwYXRoXSlcbiAgICB3cml0ZXIubWFwcGVkKGVtaXRTY2FsYXJUeXBlKFwic3dpZnRcIiwgc3RhdGVtZW50LnR5cGUpLCB7bWFwcGluZ0tpbmQ6IFwiZXhhY3RcIiwgbm9kZTogc3RhdGVtZW50LnR5cGUsXG4gICAgICBwYXRoOiBgJHtwYXRofS90eXBlYCwgcm9sZTogXCJ0eXBlXCJ9KVxuICAgIHdyaXRlci5zeW50aGV0aWMoXCIgPSBcIiwgXCJhc3NpZ25tZW50IHNwYWNpbmdcIiwgW3N0YXRlbWVudF0sIFtwYXRoXSlcbiAgICBlbWl0RXhwcmVzc2lvbih3cml0ZXIsIHN0YXRlbWVudC5pbml0aWFsaXplciwgYCR7cGF0aH0vaW5pdGlhbGl6ZXJgLCBkZWNsYXJhdGlvbnMpXG4gICAgd3JpdGVyLnN5bnRoZXRpYyhcIlxcblwiLCBcImxpbmUgYnJlYWtcIiwgW3N0YXRlbWVudF0sIFtwYXRoXSlcbiAgICBpZiAoc3RhdGVtZW50Lm11dGFibGUpIHdyaXRlci5zeW50aGV0aWMoYCR7aW5kZW50fXNlbWFudGlmb2xkX2tlZXBfbXV0YWJsZSgmJHtzdGF0ZW1lbnQubmFtZX0pXFxuYCxcbiAgICAgIFwiU3dpZnQgbXV0YWJsZS1sb2NhbCB3YXJuaW5nIG1hcmtlclwiLCBbc3RhdGVtZW50XSwgW3BhdGhdKVxuICAgIHJldHVyblxuICB9XG4gIGlmIChzdGF0ZW1lbnQua2luZCA9PSBcIkFzc2lnbm1lbnRTdGF0ZW1lbnRcIikge1xuICAgIHdyaXRlci5tYXBwZWQoc3RhdGVtZW50LnRhcmdldC5uYW1lLCB7bWFwcGluZ0tpbmQ6IFwiZXhhY3RcIiwgbm9kZTogc3RhdGVtZW50LnRhcmdldCwgcGF0aDogYCR7cGF0aH0vdGFyZ2V0YCwgcm9sZTogXCJuYW1lXCJ9KVxuICAgIHdyaXRlci5zeW50aGV0aWMoXCIgPSBcIiwgXCJhc3NpZ25tZW50IHNwYWNpbmdcIiwgW3N0YXRlbWVudF0sIFtwYXRoXSlcbiAgICBlbWl0RXhwcmVzc2lvbih3cml0ZXIsIHN0YXRlbWVudC5leHByZXNzaW9uLCBgJHtwYXRofS9leHByZXNzaW9uYCwgZGVjbGFyYXRpb25zKVxuICAgIHdyaXRlci5zeW50aGV0aWMoXCJcXG5cIiwgXCJsaW5lIGJyZWFrXCIsIFtzdGF0ZW1lbnRdLCBbcGF0aF0pXG4gICAgcmV0dXJuXG4gIH1cbiAgaWYgKHN0YXRlbWVudC5raW5kID09IFwiUmV0dXJuU3RhdGVtZW50XCIpIHtcbiAgICBpZiAoIXN0YXRlbWVudC5leHByZXNzaW9uKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiaU9TIFN3aWZ0IGJhcmUgcmV0dXJuIHJlYWNoZWQgZW1pc3Npb24uXCIpXG4gICAgd3JpdGVyLm1hcHBlZChcInJldHVyblwiLCB7bWFwcGluZ0tpbmQ6IFwiYW5jaG9yXCIsIG5vZGU6IHN0YXRlbWVudCwgcGF0aH0pXG4gICAgd3JpdGVyLnN5bnRoZXRpYyhcIiBcIiwgXCJyZXR1cm4gc3BhY2luZ1wiLCBbc3RhdGVtZW50XSwgW3BhdGhdKVxuICAgIGVtaXRFeHByZXNzaW9uKHdyaXRlciwgc3RhdGVtZW50LmV4cHJlc3Npb24sIGAke3BhdGh9L2V4cHJlc3Npb25gLCBkZWNsYXJhdGlvbnMpXG4gICAgd3JpdGVyLnN5bnRoZXRpYyhcIlxcblwiLCBcImxpbmUgYnJlYWtcIiwgW3N0YXRlbWVudF0sIFtwYXRoXSlcbiAgICByZXR1cm5cbiAgfVxuICBpZiAoc3RhdGVtZW50LmtpbmQgPT0gXCJQcmludFN0YXRlbWVudFwiKSB7XG4gICAgd3JpdGVyLnN5bnRoZXRpYyhcInNlbWFudGlmb2xkX291dHB1dC53cml0ZShcIiwgXCJpT1Mgb3V0cHV0IGNhcHR1cmVcIiwgW3N0YXRlbWVudF0sIFtwYXRoXSlcbiAgICBlbWl0RXhwcmVzc2lvbih3cml0ZXIsIHN0YXRlbWVudC5leHByZXNzaW9uLCBgJHtwYXRofS9leHByZXNzaW9uYCwgZGVjbGFyYXRpb25zKVxuICAgIHdyaXRlci5zeW50aGV0aWMoXCIpXFxuXCIsIFwiaU9TIG91dHB1dCBjYXB0dXJlXCIsIFtzdGF0ZW1lbnRdLCBbcGF0aF0pXG4gICAgcmV0dXJuXG4gIH1cbiAgaWYgKHN0YXRlbWVudC5raW5kICE9IFwiSWZTdGF0ZW1lbnRcIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlVuc3VwcG9ydGVkIGlPUyBTd2lmdCBzdGF0ZW1lbnQgcmVhY2hlZCBlbWlzc2lvbi5cIilcbiAgd3JpdGVyLm1hcHBlZChcImlmXCIsIHttYXBwaW5nS2luZDogXCJhbmNob3JcIiwgbm9kZTogc3RhdGVtZW50LCBwYXRofSlcbiAgd3JpdGVyLnN5bnRoZXRpYyhcIiBcIiwgXCJjb25kaXRpb25hbCBzcGFjaW5nXCIsIFtzdGF0ZW1lbnRdLCBbcGF0aF0pXG4gIGVtaXRFeHByZXNzaW9uKHdyaXRlciwgc3RhdGVtZW50LmNvbmRpdGlvbiwgYCR7cGF0aH0vY29uZGl0aW9uYCwgZGVjbGFyYXRpb25zKVxuICB3cml0ZXIuc3ludGhldGljKFwiIHtcXG5cIiwgXCJTd2lmdCBjb25kaXRpb25hbCBzY2FmZm9sZFwiLCBbc3RhdGVtZW50LmNvbnNlcXVlbnRdLCBbYCR7cGF0aH0vY29uc2VxdWVudGBdKVxuICBlbWl0QmxvY2sod3JpdGVyLCBzdGF0ZW1lbnQuY29uc2VxdWVudCwgYCR7aW5kZW50fSAgYCwgYCR7cGF0aH0vY29uc2VxdWVudGAsIGRlY2xhcmF0aW9ucylcbiAgd3JpdGVyLnN5bnRoZXRpYyhgJHtpbmRlbnR9fWAsIFwiU3dpZnQgY29uZGl0aW9uYWwgc2NhZmZvbGRcIiwgW3N0YXRlbWVudC5jb25zZXF1ZW50XSwgW2Ake3BhdGh9L2NvbnNlcXVlbnRgXSlcbiAgaWYgKHN0YXRlbWVudC5hbHRlcm5hdGUpIHtcbiAgICB3cml0ZXIuc3ludGhldGljKFwiIGVsc2Uge1xcblwiLCBcIlN3aWZ0IGFsdGVybmF0ZSBzY2FmZm9sZFwiLCBbc3RhdGVtZW50LmFsdGVybmF0ZV0sIFtgJHtwYXRofS9hbHRlcm5hdGVgXSlcbiAgICBlbWl0QmxvY2sod3JpdGVyLCBzdGF0ZW1lbnQuYWx0ZXJuYXRlLCBgJHtpbmRlbnR9ICBgLCBgJHtwYXRofS9hbHRlcm5hdGVgLCBkZWNsYXJhdGlvbnMpXG4gICAgd3JpdGVyLnN5bnRoZXRpYyhgJHtpbmRlbnR9fWAsIFwiU3dpZnQgYWx0ZXJuYXRlIHNjYWZmb2xkXCIsIFtzdGF0ZW1lbnQuYWx0ZXJuYXRlXSwgW2Ake3BhdGh9L2FsdGVybmF0ZWBdKVxuICB9XG4gIHdyaXRlci5zeW50aGV0aWMoXCJcXG5cIiwgXCJsaW5lIGJyZWFrXCIsIFtzdGF0ZW1lbnRdLCBbcGF0aF0pXG59XG5cbi8qKlxuICogRW1pdHMgb25lIHZhbGlkYXRlZCBUYXNrcyAwMDEtMDA0IGV4cHJlc3Npb24gYW5kIHRocmVhZHMgdGhlIHNoYXJlZCBzaW5rIHRocm91Z2ggY2FsbHMuXG4gKiBAcGFyYW0ge1NvdXJjZVdyaXRlcn0gd3JpdGVyIC0gU291cmNlIHdyaXRlci5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRXhwcmVzc2lvbn0gZXhwcmVzc2lvbiAtIFNlbWFudGljIGV4cHJlc3Npb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aCAtIEV4cHJlc3Npb24gb2NjdXJyZW5jZSBwYXRoLlxuICogQHBhcmFtIHtNYXA8c3RyaW5nIHwgdW5kZWZpbmVkLCB7ZGVjbGFyYXRpb246IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkZ1bmN0aW9uRGVjbGFyYXRpb24sIG1vZHVsZUlkOiBzdHJpbmd9Pn0gZGVjbGFyYXRpb25zIC0gUmVzb2x2ZWQgZnVuY3Rpb25zLlxuICovXG5mdW5jdGlvbiBlbWl0RXhwcmVzc2lvbih3cml0ZXIsIGV4cHJlc3Npb24sIHBhdGgsIGRlY2xhcmF0aW9ucykge1xuICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiSWRlbnRpZmllckV4cHJlc3Npb25cIikge1xuICAgIHdyaXRlci5tYXBwZWQoZXhwcmVzc2lvbi5uYW1lLCB7bWFwcGluZ0tpbmQ6IFwiZXhhY3RcIiwgbm9kZTogZXhwcmVzc2lvbiwgcGF0aCwgcm9sZTogXCJuYW1lXCJ9KVxuICAgIHJldHVyblxuICB9XG4gIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJJbnRlZ2VyTGl0ZXJhbFwiKSB7XG4gICAgd3JpdGVyLm1hcHBlZChTdHJpbmcoZXhwcmVzc2lvbi52YWx1ZSksIHttYXBwaW5nS2luZDogXCJleGFjdFwiLCBub2RlOiBleHByZXNzaW9uLCBwYXRoLCByb2xlOiBcImxpdGVyYWxcIn0pXG4gICAgcmV0dXJuXG4gIH1cbiAgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIkJvb2xlYW5MaXRlcmFsXCIpIHtcbiAgICB3cml0ZXIubWFwcGVkKGV4cHJlc3Npb24udmFsdWUgPyBcInRydWVcIiA6IFwiZmFsc2VcIiwge21hcHBpbmdLaW5kOiBcImV4YWN0XCIsIG5vZGU6IGV4cHJlc3Npb24sIHBhdGgsIHJvbGU6IFwibGl0ZXJhbFwifSlcbiAgICByZXR1cm5cbiAgfVxuICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiU3RyaW5nTGl0ZXJhbFwiKSB7XG4gICAgd3JpdGVyLm1hcHBlZChlbWl0U3RyaW5nTGl0ZXJhbChcInN3aWZ0XCIsIGV4cHJlc3Npb24udmFsdWUpLCB7bWFwcGluZ0tpbmQ6IFwiZXhhY3RcIiwgbm9kZTogZXhwcmVzc2lvbiwgcGF0aCwgcm9sZTogXCJsaXRlcmFsXCJ9KVxuICAgIHJldHVyblxuICB9XG4gIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJDYWxsRXhwcmVzc2lvblwiKSB7XG4gICAgY29uc3QgcmVzb2x2ZWQgPSBkZWNsYXJhdGlvbnMuZ2V0KGV4cHJlc3Npb24ucmVzb2x1dGlvbj8uZGVjbGFyYXRpb25JZClcblxuICAgIGlmICghcmVzb2x2ZWQpIHRocm93IG5ldyBUeXBlRXJyb3IoYFVua25vd24gdmFsaWRhdGVkIGlPUyBmdW5jdGlvbiAnJHtleHByZXNzaW9uLnJlc29sdXRpb24/LmRlY2xhcmF0aW9uSWR9Jy5gKVxuICAgIHdyaXRlci5tYXBwZWQoYFNlbWFudGlmb2xkTW9kdWxlJHttb2R1bGVOYW1lKHJlc29sdmVkLm1vZHVsZUlkKX0uJHtyZXNvbHZlZC5kZWNsYXJhdGlvbi5uYW1lfWAsIHtcbiAgICAgIG1hcHBpbmdLaW5kOiBcImV4YWN0XCIsIG5hbWU6IGV4cHJlc3Npb24uY2FsbGVlLCBub2RlOiBleHByZXNzaW9uLCBwYXRoLCByb2xlOiBcImNhbGxlZVwiXG4gICAgfSlcbiAgICB3cml0ZXIuc3ludGhldGljKFwiKFwiLCBcImlPUyBzZW1hbnRpYyBmdW5jdGlvbiBjYWxsXCIsIFtleHByZXNzaW9uXSwgW3BhdGhdKVxuICAgIGV4cHJlc3Npb24uYXJndW1lbnRzLmZvckVhY2goKGFyZ3VtZW50LCBpbmRleCkgPT4ge1xuICAgICAgaWYgKGluZGV4KSB3cml0ZXIuc3ludGhldGljKFwiLCBcIiwgXCJhcmd1bWVudCBzZXBhcmF0b3JcIiwgW2V4cHJlc3Npb25dLCBbcGF0aF0pXG4gICAgICBlbWl0RXhwcmVzc2lvbih3cml0ZXIsIGFyZ3VtZW50LCBgJHtwYXRofS9hcmd1bWVudHMvJHtpbmRleH1gLCBkZWNsYXJhdGlvbnMpXG4gICAgfSlcbiAgICB3cml0ZXIuc3ludGhldGljKFwiLCBzZW1hbnRpZm9sZF9vdXRwdXQpXCIsIFwic2hhcmVkIGlPUyBvdXRwdXQgc2luayBhcmd1bWVudFwiLCBbZXhwcmVzc2lvbl0sIFtwYXRoXSlcbiAgICByZXR1cm5cbiAgfVxuICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiVW5hcnlFeHByZXNzaW9uXCIpIHtcbiAgICB3cml0ZXIubWFwcGVkKFwiKFwiLCB7bWFwcGluZ0tpbmQ6IFwiYW5jaG9yXCIsIG5vZGU6IGV4cHJlc3Npb24sIHBhdGh9KVxuICAgIHdyaXRlci5tYXBwZWQodW5hcnlPcGVyYXRpb25zW2V4cHJlc3Npb24ub3BlcmF0aW9uXSwge21hcHBpbmdLaW5kOiBcImV4YWN0XCIsIG5vZGU6IGV4cHJlc3Npb24sIHBhdGgsIHJvbGU6IFwib3BlcmF0b3JcIn0pXG4gICAgZW1pdEV4cHJlc3Npb24od3JpdGVyLCBleHByZXNzaW9uLm9wZXJhbmQsIGAke3BhdGh9L29wZXJhbmRgLCBkZWNsYXJhdGlvbnMpXG4gICAgd3JpdGVyLm1hcHBlZChcIilcIiwge21hcHBpbmdLaW5kOiBcImFuY2hvclwiLCBub2RlOiBleHByZXNzaW9uLCBwYXRofSlcbiAgICByZXR1cm5cbiAgfVxuICBpZiAoZXhwcmVzc2lvbi5raW5kICE9IFwiQmluYXJ5RXhwcmVzc2lvblwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiVW5zdXBwb3J0ZWQgaU9TIFN3aWZ0IGV4cHJlc3Npb24gcmVhY2hlZCBlbWlzc2lvbi5cIilcbiAgaWYgKGV4cHJlc3Npb24ub3BlcmF0aW9uID09IFwiU3RyaW5nRXF1YWxcIiB8fCBleHByZXNzaW9uLm9wZXJhdGlvbiA9PSBcIlN0cmluZ05vdEVxdWFsXCIpIHtcbiAgICB3cml0ZXIubWFwcGVkKGV4cHJlc3Npb24ub3BlcmF0aW9uID09IFwiU3RyaW5nRXF1YWxcIiA/IFwic2VtYW50aWZvbGRfc3RyaW5nX2VxdWFsXCIgOiBcInNlbWFudGlmb2xkX3N0cmluZ19ub3RfZXF1YWxcIixcbiAgICAgIHttYXBwaW5nS2luZDogXCJleGFjdFwiLCBub2RlOiBleHByZXNzaW9uLCBwYXRoLCByb2xlOiBcIm9wZXJhdG9yXCJ9KVxuICAgIHdyaXRlci5zeW50aGV0aWMoXCIoXCIsIFwiU3dpZnQgc2NhbGFyLWVxdWFsaXR5IGhlbHBlciBjYWxsXCIsIFtleHByZXNzaW9uXSwgW3BhdGhdKVxuICAgIGVtaXRFeHByZXNzaW9uKHdyaXRlciwgZXhwcmVzc2lvbi5sZWZ0LCBgJHtwYXRofS9sZWZ0YCwgZGVjbGFyYXRpb25zKVxuICAgIHdyaXRlci5zeW50aGV0aWMoXCIsIFwiLCBcIlN3aWZ0IHNjYWxhci1lcXVhbGl0eSBhcmd1bWVudCBzZXBhcmF0b3JcIiwgW2V4cHJlc3Npb25dLCBbcGF0aF0pXG4gICAgZW1pdEV4cHJlc3Npb24od3JpdGVyLCBleHByZXNzaW9uLnJpZ2h0LCBgJHtwYXRofS9yaWdodGAsIGRlY2xhcmF0aW9ucylcbiAgICB3cml0ZXIuc3ludGhldGljKFwiKVwiLCBcIlN3aWZ0IHNjYWxhci1lcXVhbGl0eSBoZWxwZXIgY2FsbFwiLCBbZXhwcmVzc2lvbl0sIFtwYXRoXSlcbiAgICByZXR1cm5cbiAgfVxuICB3cml0ZXIubWFwcGVkKFwiKFwiLCB7bWFwcGluZ0tpbmQ6IFwiYW5jaG9yXCIsIG5vZGU6IGV4cHJlc3Npb24sIHBhdGh9KVxuICBlbWl0RXhwcmVzc2lvbih3cml0ZXIsIGV4cHJlc3Npb24ubGVmdCwgYCR7cGF0aH0vbGVmdGAsIGRlY2xhcmF0aW9ucylcbiAgd3JpdGVyLnN5bnRoZXRpYyhcIiBcIiwgXCJvcGVyYXRvciBzcGFjaW5nXCIsIFtleHByZXNzaW9uXSwgW3BhdGhdKVxuICB3cml0ZXIubWFwcGVkKGJpbmFyeU9wZXJhdGlvbnNbZXhwcmVzc2lvbi5vcGVyYXRpb25dLCB7bWFwcGluZ0tpbmQ6IFwiZXhhY3RcIiwgbm9kZTogZXhwcmVzc2lvbiwgcGF0aCwgcm9sZTogXCJvcGVyYXRvclwifSlcbiAgd3JpdGVyLnN5bnRoZXRpYyhcIiBcIiwgXCJvcGVyYXRvciBzcGFjaW5nXCIsIFtleHByZXNzaW9uXSwgW3BhdGhdKVxuICBlbWl0RXhwcmVzc2lvbih3cml0ZXIsIGV4cHJlc3Npb24ucmlnaHQsIGAke3BhdGh9L3JpZ2h0YCwgZGVjbGFyYXRpb25zKVxuICB3cml0ZXIubWFwcGVkKFwiKVwiLCB7bWFwcGluZ0tpbmQ6IFwiYW5jaG9yXCIsIG5vZGU6IGV4cHJlc3Npb24sIHBhdGh9KVxufVxuXG4vKipcbiAqIENvbnZlcnRzIGEgdmFsaWRhdGVkIGxvZ2ljYWwgbW9kdWxlIGlkZW50aXR5IHRvIGl0cyBTd2lmdCBuYW1lc3BhY2Ugc3VmZml4LlxuICogQHBhcmFtIHtzdHJpbmd9IGlkIC0gTG9naWNhbCBtb2R1bGUgaWRlbnRpdHkuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBEZXRlcm1pbmlzdGljIFN3aWZ0IG5hbWVzcGFjZSBzdWZmaXggYW5kIGZpbGVuYW1lLlxuICovXG5mdW5jdGlvbiBtb2R1bGVOYW1lKGlkKSB7XG4gIHJldHVybiBpZC5zcGxpdCgvWy5fLV0rL3UpLm1hcChwYXJ0ID0+IGAke3BhcnRbMF0udG9VcHBlckNhc2UoKX0ke3BhcnQuc2xpY2UoMSl9YCkuam9pbihcIlwiKVxufVxuXG4vKipcbiAqIENsb25lcyBhbmQgbm9ybWFsaXplcyBvbmUgcHJvdmVuYW5jZS1iZWFyaW5nIHNlbWFudGljIG1vZHVsZSBpbnRvIGEgb25lLW1vZHVsZSBwcm9qZWN0LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY01vZHVsZSB8IHVuZGVmaW5lZH0gY2FuZGlkYXRlIC0gQ2FuZGlkYXRlIG1vZHVsZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY1Byb2dyYW19IE5vcm1hbGl6ZWQgcHJvZ3JhbS5cbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplU2luZ2xlTW9kdWxlKGNhbmRpZGF0ZSkge1xuICBpZiAoIWlzUGxhaW5PYmplY3QoY2FuZGlkYXRlKSkgdW5zdXBwb3J0ZWRDYXBhYmlsaXR5KFwiaW9zXCIsIFwibWlzc2luZyBvciBpbnZhbGlkIG1vZHVsZVwiLCB1bmRlZmluZWQpXG4gIGNvbnN0IG1vZHVsZSA9IHN0cnVjdHVyZWRDbG9uZShjYW5kaWRhdGUpXG4gIGNvbnN0IHByb3ZlbmFuY2VTb3VyY2VzID0gbW9kdWxlLnByb3ZlbmFuY2U/LnNvdXJjZXNcblxuICBpZiAoIUFycmF5LmlzQXJyYXkocHJvdmVuYW5jZVNvdXJjZXMpIHx8IHByb3ZlbmFuY2VTb3VyY2VzLmxlbmd0aCAhPSAxIHx8IHByb3ZlbmFuY2VTb3VyY2VzWzBdLmNvbnRlbnQgPT09IG51bGwgfHxcbiAgICBwcm92ZW5hbmNlU291cmNlc1swXS5maWxlbmFtZSAhPSBtb2R1bGUubG9jYXRpb24/LmZpbGVuYW1lIHx8IHR5cGVvZiBwcm92ZW5hbmNlU291cmNlc1swXS5sYW5ndWFnZSAhPSBcInN0cmluZ1wiKSB7XG4gICAgdW5zdXBwb3J0ZWRDYXBhYmlsaXR5KFwiaW9zXCIsIFwic2luZ2xlLW1vZHVsZSBzb3VyY2Ugb3duZXJzaGlwXCIsIG1vZHVsZS5sb2NhdGlvbilcbiAgfVxuICByZWtleU1vZHVsZURlY2xhcmF0aW9ucyhtb2R1bGUsIFwibWFpblwiKVxuICBjb25zdCBleHBvcnRzID0gW1xuICAgIC4uLihtb2R1bGUucmVjb3JkcyA/PyBbXSkubWFwKGRlY2xhcmF0aW9uID0+IGFwcGxpY2F0aW9uRXhwb3J0KGRlY2xhcmF0aW9uLCBcInJlY29yZFwiKSksXG4gICAgLi4uKG1vZHVsZS5jbGFzc2VzID8/IFtdKS5tYXAoZGVjbGFyYXRpb24gPT4gYXBwbGljYXRpb25FeHBvcnQoZGVjbGFyYXRpb24sIFwiY2xhc3NcIikpLFxuICAgIC4uLihtb2R1bGUuZXJyb3JzID8/IFtdKS5tYXAoZGVjbGFyYXRpb24gPT4gYXBwbGljYXRpb25FeHBvcnQoZGVjbGFyYXRpb24sIFwiZXJyb3JcIikpLFxuICAgIC4uLm1vZHVsZS5mdW5jdGlvbnMubWFwKGRlY2xhcmF0aW9uID0+IGFwcGxpY2F0aW9uRXhwb3J0KGRlY2xhcmF0aW9uLCBcImZ1bmN0aW9uXCIpKVxuICBdXG4gIGNvbnN0IHByb2dyYW1Nb2R1bGUgPSAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljUHJvZ3JhbU1vZHVsZX0gKi8gKHtcbiAgICAuLi5tb2R1bGUsXG4gICAgZXhwb3J0cyxcbiAgICBpZDogXCJtYWluXCIsXG4gICAgaW1wb3J0czogW10sXG4gICAgc291cmNlRmlsZW5hbWU6IHByb3ZlbmFuY2VTb3VyY2VzWzBdLmZpbGVuYW1lXG4gIH0pXG5cbiAgcmV0dXJuIHtcbiAgICBlbnRyeU1vZHVsZTogXCJtYWluXCIsXG4gICAga2luZDogXCJQcm9ncmFtXCIsXG4gICAgbW9kdWxlczogW3Byb2dyYW1Nb2R1bGVdLFxuICAgIHNvdXJjZXM6IHN0cnVjdHVyZWRDbG9uZShwcm92ZW5hbmNlU291cmNlcylcbiAgfVxufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBub3JtYWxpemVkIGV4cG9ydCBmb3IgYSBzaW5nbGUtbW9kdWxlIGRlY2xhcmF0aW9uIHdpdGhvdXQgaW52ZW50aW5nIGEgc291cmNlIHJhbmdlLlxuICogQHBhcmFtIHt7aWQ/OiBzdHJpbmcsIGxvY2F0aW9uOiBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbiwgbmFtZTogc3RyaW5nfX0gZGVjbGFyYXRpb24gLSBFeHBvcnRlZCBkZWNsYXJhdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU2VtYW50aWNEZWNsYXJhdGlvbktpbmR9IHN5bWJvbEtpbmQgLSBEZWNsYXJhdGlvbiBuYW1lc3BhY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU2VtYW50aWNFeHBvcnR9IFN5bnRoZXRpYyBwcm9qZWN0IGVkZ2UgYW5jaG9yZWQgdG8gaXRzIGRlY2xhcmF0aW9uLlxuICovXG5mdW5jdGlvbiBhcHBsaWNhdGlvbkV4cG9ydChkZWNsYXJhdGlvbiwgc3ltYm9sS2luZCkge1xuICByZXR1cm4ge1xuICAgIGRlY2xhcmF0aW9uSWQ6IC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAoZGVjbGFyYXRpb24uaWQpLFxuICAgIGV4cG9ydGVkTmFtZTogZGVjbGFyYXRpb24ubmFtZSxcbiAgICBraW5kOiBcIkV4cG9ydFwiLFxuICAgIGxvY2F0aW9uOiBkZWNsYXJhdGlvbi5sb2NhdGlvbixcbiAgICBzeW1ib2xLaW5kXG4gIH1cbn1cblxuLyoqXG4gKiBQcmVmaXhlcyBkZWNsYXJhdGlvbiBpZGVudGl0aWVzIGFuZCB0eXBlZCByZWZlcmVuY2VzIGluIGEgY2xvbmVkIHNpbmdsZSBtb2R1bGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljTW9kdWxlfSBtb2R1bGUgLSBDbG9uZWQgbW9kdWxlLlxuICogQHBhcmFtIHtzdHJpbmd9IG1vZHVsZUlkIC0gTm9ybWFsaXplZCBtb2R1bGUgaWRlbnRpdHkuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gcmVrZXlNb2R1bGVEZWNsYXJhdGlvbnMobW9kdWxlLCBtb2R1bGVJZCkge1xuICBjb25zdCBkZWNsYXJhdGlvbnMgPSBbLi4ubW9kdWxlLnJlY29yZHMgPz8gW10sIC4uLm1vZHVsZS5jbGFzc2VzID8/IFtdLCAuLi5tb2R1bGUuZXJyb3JzID8/IFtdLCAuLi5tb2R1bGUuZnVuY3Rpb25zXVxuICBjb25zdCByZXBsYWNlbWVudHMgPSBuZXcgTWFwKGRlY2xhcmF0aW9uc1xuICAgIC5maWx0ZXIoZGVjbGFyYXRpb24gPT4gdHlwZW9mIGRlY2xhcmF0aW9uLmlkID09IFwic3RyaW5nXCIpXG4gICAgLm1hcChkZWNsYXJhdGlvbiA9PiBbZGVjbGFyYXRpb24uaWQsIGAke21vZHVsZUlkfSMke2RlY2xhcmF0aW9uLmlkfWBdKSlcblxuICBmb3IgKGNvbnN0IGRlY2xhcmF0aW9uIG9mIGRlY2xhcmF0aW9ucykge1xuICAgIGlmICh0eXBlb2YgZGVjbGFyYXRpb24uaWQgPT0gXCJzdHJpbmdcIikgZGVjbGFyYXRpb24uaWQgPSByZXBsYWNlbWVudHMuZ2V0KGRlY2xhcmF0aW9uLmlkKVxuICB9XG4gIGNvbnN0IHNlZW4gPSBuZXcgU2V0KClcbiAgY29uc3QgaWRlbnRpdHlGaWVsZHMgPSBuZXcgU2V0KFtcImNsYXNzSWRcIiwgXCJkZWNsYXJhdGlvbklkXCIsIFwiZmllbGRcIiwgXCJtZXRob2RcIiwgXCJwYXJhbWV0ZXJJZFwiXSlcbiAgLyoqXG4gICAqIFJld3JpdGVzIGRlY2xhcmF0aW9uIGlkZW50aXRpZXMgaW4gb25lIGNsb25lZCBzZW1hbnRpYyBzdWJ0cmVlLlxuICAgKiBAcGFyYW0ge3Vua25vd259IHZhbHVlIC0gQ2FuZGlkYXRlIHNlbWFudGljIHN1YnRyZWUuXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgZnVuY3Rpb24gdmlzaXQodmFsdWUpIHtcbiAgICBpZiAoIXZhbHVlIHx8IHR5cGVvZiB2YWx1ZSAhPSBcIm9iamVjdFwiIHx8IHNlZW4uaGFzKHZhbHVlKSkgcmV0dXJuXG4gICAgc2Vlbi5hZGQodmFsdWUpXG4gICAgaWYgKCFBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgZm9yIChjb25zdCBba2V5LCBuZXN0ZWRdIG9mIE9iamVjdC5lbnRyaWVzKHZhbHVlKSkge1xuICAgICAgICBpZiAoaWRlbnRpdHlGaWVsZHMuaGFzKGtleSkgJiYgdHlwZW9mIG5lc3RlZCA9PSBcInN0cmluZ1wiICYmIHJlcGxhY2VtZW50cy5oYXMobmVzdGVkKSkge1xuICAgICAgICAgIFJlZmxlY3Quc2V0KHZhbHVlLCBrZXksIHJlcGxhY2VtZW50cy5nZXQobmVzdGVkKSlcbiAgICAgICAgfSBlbHNlIHZpc2l0KG5lc3RlZClcbiAgICAgIH1cbiAgICB9IGVsc2UgZm9yIChjb25zdCBuZXN0ZWQgb2YgdmFsdWUpIHZpc2l0KG5lc3RlZClcbiAgfVxuICB2aXNpdChtb2R1bGUpXG59XG5cbi8qKlxuICogVGVzdHMgZm9yIGEgcGxhaW4gcmVxdWVzdCBvYmplY3QuXG4gKiBAcGFyYW0ge3Vua25vd259IHZhbHVlIC0gQ2FuZGlkYXRlIHJlcXVlc3QuXG4gKiBAcmV0dXJucyB7dmFsdWUgaXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj59IFdoZXRoZXIgaXQgaXMgYSBwbGFpbiBvYmplY3QuXG4gKi9cbmZ1bmN0aW9uIGlzUGxhaW5PYmplY3QodmFsdWUpIHtcbiAgcmV0dXJuIEJvb2xlYW4odmFsdWUpICYmIHR5cGVvZiB2YWx1ZSA9PSBcIm9iamVjdFwiICYmICFBcnJheS5pc0FycmF5KHZhbHVlKSAmJiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpID09IE9iamVjdC5wcm90b3R5cGVcbn1cbiJdfQ==