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.
- package/README.md +61 -15
- package/build/index.d.ts +52 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +60 -8
- package/build/src/artifact-path.d.ts +23 -1
- package/build/src/artifact-path.d.ts.map +1 -1
- package/build/src/artifact-path.js +45 -3
- package/build/src/artifacts.d.ts.map +1 -1
- package/build/src/artifacts.js +66 -1
- package/build/src/backends/android.d.ts +49 -0
- package/build/src/backends/android.d.ts.map +1 -0
- package/build/src/backends/android.js +1274 -0
- package/build/src/backends/c-validation.d.ts.map +1 -1
- package/build/src/backends/c-validation.js +7 -3
- package/build/src/backends/cpp-validation.d.ts.map +1 -1
- package/build/src/backends/cpp-validation.js +7 -3
- package/build/src/backends/csharp.js +7 -1
- package/build/src/backends/dart-runtime.d.ts +2 -0
- package/build/src/backends/dart-runtime.d.ts.map +1 -0
- package/build/src/backends/dart-runtime.js +41 -0
- package/build/src/backends/dart.d.ts +20 -0
- package/build/src/backends/dart.d.ts.map +1 -0
- package/build/src/backends/dart.js +321 -0
- package/build/src/backends/effects.d.ts +60 -0
- package/build/src/backends/effects.d.ts.map +1 -0
- package/build/src/backends/effects.js +746 -0
- package/build/src/backends/go.js +18 -4
- package/build/src/backends/identifiers.d.ts +36 -4
- package/build/src/backends/identifiers.d.ts.map +1 -1
- package/build/src/backends/identifiers.js +160 -10
- package/build/src/backends/index.d.ts.map +1 -1
- package/build/src/backends/index.js +27 -4
- package/build/src/backends/ios.d.ts +68 -0
- package/build/src/backends/ios.d.ts.map +1 -0
- package/build/src/backends/ios.js +1503 -0
- package/build/src/backends/java.d.ts.map +1 -1
- package/build/src/backends/java.js +429 -36
- package/build/src/backends/javascript.d.ts +6 -0
- package/build/src/backends/javascript.d.ts.map +1 -1
- package/build/src/backends/javascript.js +380 -24
- package/build/src/backends/kotlin-runtime.d.ts +3 -0
- package/build/src/backends/kotlin-runtime.d.ts.map +1 -0
- package/build/src/backends/kotlin-runtime.js +29 -0
- package/build/src/backends/kotlin.d.ts +33 -0
- package/build/src/backends/kotlin.d.ts.map +1 -0
- package/build/src/backends/kotlin.js +138 -0
- package/build/src/backends/native-validation.d.ts +2 -2
- package/build/src/backends/native-validation.d.ts.map +1 -1
- package/build/src/backends/native-validation.js +2 -2
- package/build/src/backends/ordered-expressions.d.ts.map +1 -1
- package/build/src/backends/ordered-expressions.js +39 -7
- package/build/src/backends/php-stdlib-support.d.ts +19 -0
- package/build/src/backends/php-stdlib-support.d.ts.map +1 -0
- package/build/src/backends/php-stdlib-support.js +227 -0
- package/build/src/backends/php.d.ts.map +1 -1
- package/build/src/backends/php.js +448 -33
- package/build/src/backends/program.d.ts +83 -0
- package/build/src/backends/program.d.ts.map +1 -0
- package/build/src/backends/program.js +1309 -0
- package/build/src/backends/python.js +7 -1
- package/build/src/backends/ruby.d.ts.map +1 -1
- package/build/src/backends/ruby.js +310 -24
- package/build/src/backends/rust-runtime.d.ts +7 -0
- package/build/src/backends/rust-runtime.d.ts.map +1 -0
- package/build/src/backends/rust-runtime.js +32 -0
- package/build/src/backends/rust-validation.d.ts +9 -0
- package/build/src/backends/rust-validation.d.ts.map +1 -0
- package/build/src/backends/rust-validation.js +78 -0
- package/build/src/backends/rust.d.ts +24 -0
- package/build/src/backends/rust.d.ts.map +1 -0
- package/build/src/backends/rust.js +344 -0
- package/build/src/backends/scalars.d.ts +14 -6
- package/build/src/backends/scalars.d.ts.map +1 -1
- package/build/src/backends/scalars.js +167 -17
- package/build/src/backends/shared.d.ts +23 -4
- package/build/src/backends/shared.d.ts.map +1 -1
- package/build/src/backends/shared.js +2174 -62
- package/build/src/backends/stdlib-support.d.ts +14 -0
- package/build/src/backends/stdlib-support.d.ts.map +1 -0
- package/build/src/backends/stdlib-support.js +237 -0
- package/build/src/backends/swift-runtime.d.ts +3 -0
- package/build/src/backends/swift-runtime.d.ts.map +1 -0
- package/build/src/backends/swift-runtime.js +14 -0
- package/build/src/backends/swift.d.ts +8 -0
- package/build/src/backends/swift.d.ts.map +1 -0
- package/build/src/backends/swift.js +127 -0
- package/build/src/backends/typescript.d.ts.map +1 -1
- package/build/src/backends/typescript.js +344 -24
- package/build/src/backends/wasm.d.ts +43 -0
- package/build/src/backends/wasm.d.ts.map +1 -0
- package/build/src/backends/wasm.js +2164 -0
- package/build/src/backends/writer.d.ts +255 -4
- package/build/src/backends/writer.d.ts.map +1 -1
- package/build/src/backends/writer.js +491 -3
- package/build/src/diagnostic.d.ts +4 -3
- package/build/src/diagnostic.d.ts.map +1 -1
- package/build/src/diagnostic.js +5 -3
- package/build/src/frontends/c.d.ts.map +1 -1
- package/build/src/frontends/c.js +5 -3
- package/build/src/frontends/cpp.d.ts.map +1 -1
- package/build/src/frontends/cpp.js +5 -3
- package/build/src/frontends/csharp.d.ts.map +1 -1
- package/build/src/frontends/csharp.js +7 -3
- package/build/src/frontends/dart.d.ts +10 -0
- package/build/src/frontends/dart.d.ts.map +1 -0
- package/build/src/frontends/dart.js +913 -0
- package/build/src/frontends/index.d.ts +3 -1
- package/build/src/frontends/index.d.ts.map +1 -1
- package/build/src/frontends/index.js +15 -5
- package/build/src/frontends/java.d.ts +110 -1
- package/build/src/frontends/java.d.ts.map +1 -1
- package/build/src/frontends/java.js +1725 -70
- package/build/src/frontends/javascript-typescript.d.ts +69 -1
- package/build/src/frontends/javascript-typescript.d.ts.map +1 -1
- package/build/src/frontends/javascript-typescript.js +1825 -93
- package/build/src/frontends/kotlin.d.ts +10 -0
- package/build/src/frontends/kotlin.d.ts.map +1 -0
- package/build/src/frontends/kotlin.js +685 -0
- package/build/src/frontends/php.d.ts +118 -1
- package/build/src/frontends/php.d.ts.map +1 -1
- package/build/src/frontends/php.js +1583 -76
- package/build/src/frontends/program.d.ts +74 -0
- package/build/src/frontends/program.d.ts.map +1 -0
- package/build/src/frontends/program.js +989 -0
- package/build/src/frontends/ruby.d.ts +68 -1
- package/build/src/frontends/ruby.d.ts.map +1 -1
- package/build/src/frontends/ruby.js +1446 -101
- package/build/src/frontends/rust-parser.d.ts +11 -0
- package/build/src/frontends/rust-parser.d.ts.map +1 -0
- package/build/src/frontends/rust-parser.js +15 -0
- package/build/src/frontends/rust.d.ts +14 -0
- package/build/src/frontends/rust.d.ts.map +1 -0
- package/build/src/frontends/rust.js +715 -0
- package/build/src/frontends/scalars.d.ts +10 -0
- package/build/src/frontends/scalars.d.ts.map +1 -1
- package/build/src/frontends/scalars.js +28 -2
- package/build/src/frontends/swift.d.ts +10 -0
- package/build/src/frontends/swift.d.ts.map +1 -0
- package/build/src/frontends/swift.js +860 -0
- package/build/src/frontends/types.d.ts +186 -0
- package/build/src/frontends/types.d.ts.map +1 -0
- package/build/src/frontends/types.js +634 -0
- package/build/src/language-registry.d.ts +46 -4
- package/build/src/language-registry.d.ts.map +1 -1
- package/build/src/language-registry.js +177 -13
- package/build/src/mapping.d.ts +2 -2
- package/build/src/mapping.d.ts.map +1 -1
- package/build/src/mapping.js +31 -10
- package/build/src/semantic/capabilities.d.ts +66 -0
- package/build/src/semantic/capabilities.d.ts.map +1 -0
- package/build/src/semantic/capabilities.js +649 -0
- package/build/src/semantic/effects.d.ts +26 -0
- package/build/src/semantic/effects.d.ts.map +1 -0
- package/build/src/semantic/effects.js +764 -0
- package/build/src/semantic/generics.d.ts +23 -0
- package/build/src/semantic/generics.d.ts.map +1 -0
- package/build/src/semantic/generics.js +61 -0
- package/build/src/semantic/lifetime.d.ts +37 -0
- package/build/src/semantic/lifetime.d.ts.map +1 -0
- package/build/src/semantic/lifetime.js +527 -0
- package/build/src/semantic/provenance.d.ts +9 -2
- package/build/src/semantic/provenance.d.ts.map +1 -1
- package/build/src/semantic/provenance.js +462 -20
- package/build/src/semantic/scalars.d.ts +11 -0
- package/build/src/semantic/scalars.d.ts.map +1 -1
- package/build/src/semantic/scalars.js +16 -1
- package/build/src/semantic/stdlib.d.ts +254 -0
- package/build/src/semantic/stdlib.d.ts.map +1 -0
- package/build/src/semantic/stdlib.js +880 -0
- package/build/src/semantic/types.d.ts +3108 -178
- package/build/src/semantic/types.d.ts.map +1 -1
- package/build/src/semantic/types.js +730 -15
- package/build/src/semantic/validate.d.ts +85 -5
- package/build/src/semantic/validate.d.ts.map +1 -1
- package/build/src/semantic/validate.js +2576 -98
- package/build/src/stdlib-facades.d.ts +304 -0
- package/build/src/stdlib-facades.d.ts.map +1 -0
- package/build/src/stdlib-facades.js +1167 -0
- package/build/src/stdlib-negotiation.d.ts +69 -0
- package/build/src/stdlib-negotiation.d.ts.map +1 -0
- package/build/src/stdlib-negotiation.js +403 -0
- package/build/src/stdlib-providers.d.ts +72 -0
- package/build/src/stdlib-providers.d.ts.map +1 -0
- package/build/src/stdlib-providers.js +339 -0
- package/build/src/toolchains.d.ts +55 -1
- package/build/src/toolchains.d.ts.map +1 -1
- package/build/src/toolchains.js +15 -4
- package/docs/android.md +79 -0
- package/docs/architecture.md +47 -13
- package/docs/dart.md +60 -0
- package/docs/goals.md +3 -3
- package/docs/ios.md +121 -0
- package/docs/kotlin.md +42 -0
- package/docs/language-support.md +238 -26
- package/docs/multi-file-modules.md +52 -0
- package/docs/parser-qualification.md +121 -8
- package/docs/plans/2026-09-05-standard-library-portability.md +10 -10
- package/docs/rust.md +88 -0
- package/docs/source-maps.md +17 -7
- package/docs/specification.md +5 -0
- package/docs/standard-library-portability.md +39 -8
- package/docs/swift.md +44 -0
- package/docs/testing.md +381 -4
- package/docs/webassembly.md +52 -0
- package/index.js +66 -8
- package/node_modules/semantifold-tree-sitter-legacy-internal/README.md +2 -2
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/LICENSE +21 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/README.md +45 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/binding.gyp +30 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/binding.cc +20 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/binding_test.js +9 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/index.d.ts +28 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/index.js +11 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/grammar.js +1630 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/package.json +64 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/darwin-arm64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/darwin-x64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/linux-arm64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/linux-x64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/win32-arm64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/win32-x64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/highlights.scm +159 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/injections.scm +9 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/tags.scm +60 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/grammar.json +9405 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/node-types.json +5399 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/parser.c +192569 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/scanner.c +393 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/alloc.h +54 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/array.h +290 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/parser.h +266 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/tree-sitter-rust.wasm +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/tree-sitter.json +53 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/package.json +3 -2
- package/node_modules/semantifold-tree-sitter-legacy-internal/src/c.js +5 -4
- package/package.json +5 -2
- package/src/artifact-path.js +47 -2
- package/src/artifacts.js +67 -0
- package/src/backends/android.js +1370 -0
- package/src/backends/c-validation.js +6 -1
- package/src/backends/cpp-validation.js +6 -1
- package/src/backends/csharp.js +3 -0
- package/src/backends/dart-runtime.js +41 -0
- package/src/backends/dart.js +326 -0
- package/src/backends/effects.js +705 -0
- package/src/backends/go.js +14 -2
- package/src/backends/identifiers.js +166 -9
- package/src/backends/index.js +27 -2
- package/src/backends/ios.js +1612 -0
- package/src/backends/java.js +454 -36
- package/src/backends/javascript.js +389 -23
- package/src/backends/kotlin-runtime.js +29 -0
- package/src/backends/kotlin.js +144 -0
- package/src/backends/native-validation.js +1 -1
- package/src/backends/ordered-expressions.js +40 -6
- package/src/backends/php-stdlib-support.js +239 -0
- package/src/backends/php.js +469 -32
- package/src/backends/program.js +1408 -0
- package/src/backends/python.js +3 -0
- package/src/backends/ruby.js +326 -23
- package/src/backends/rust-runtime.js +34 -0
- package/src/backends/rust-validation.js +75 -0
- package/src/backends/rust.js +335 -0
- package/src/backends/scalars.js +141 -16
- package/src/backends/shared.js +2314 -115
- package/src/backends/stdlib-support.js +234 -0
- package/src/backends/swift-runtime.js +14 -0
- package/src/backends/swift.js +132 -0
- package/src/backends/typescript.js +349 -23
- package/src/backends/wasm.js +2208 -0
- package/src/backends/writer.js +545 -2
- package/src/diagnostic.js +4 -2
- package/src/frontends/c.js +4 -2
- package/src/frontends/cpp.js +4 -2
- package/src/frontends/csharp.js +4 -2
- package/src/frontends/dart.js +963 -0
- package/src/frontends/index.js +14 -4
- package/src/frontends/java.js +1977 -69
- package/src/frontends/javascript-typescript.js +2046 -102
- package/src/frontends/kotlin.js +713 -0
- package/src/frontends/php.js +1725 -79
- package/src/frontends/program.js +1062 -0
- package/src/frontends/ruby.js +1624 -98
- package/src/frontends/rust-parser.js +18 -0
- package/src/frontends/rust.js +714 -0
- package/src/frontends/scalars.js +31 -1
- package/src/frontends/swift.js +893 -0
- package/src/frontends/types.js +750 -0
- package/src/language-registry.js +182 -12
- package/src/mapping.js +33 -9
- package/src/semantic/capabilities.js +671 -0
- package/src/semantic/effects.js +737 -0
- package/src/semantic/generics.js +58 -0
- package/src/semantic/lifetime.js +517 -0
- package/src/semantic/provenance.js +412 -19
- package/src/semantic/scalars.js +17 -0
- package/src/semantic/stdlib.js +921 -0
- package/src/semantic/types.js +810 -14
- package/src/semantic/validate.js +2934 -209
- package/src/stdlib-facades.js +1211 -0
- package/src/stdlib-negotiation.js +446 -0
- package/src/stdlib-providers.js +377 -0
- 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("&", "&").replaceAll("<", "<").replaceAll(">", ">")
|
|
964
|
+
.replaceAll("\"", """).replaceAll("'", "'");
|
|
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==
|