@cartanova/qgrid-cli 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/bundle/dist/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/decorate.js +9 -0
  2. package/bundle/dist/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/decorateMetadata.js +6 -0
  3. package/bundle/dist/dist/_virtual/_rolldown/runtime.js +15 -0
  4. package/bundle/dist/dist/application/qgrid/oauth.js +140 -0
  5. package/bundle/dist/dist/application/qgrid/pool.js +100 -0
  6. package/bundle/dist/dist/application/qgrid/qgrid.frame.js +280 -0
  7. package/bundle/dist/dist/application/qgrid/qgrid.types.js +79 -0
  8. package/bundle/dist/dist/application/qgrid/worker.js +183 -0
  9. package/bundle/dist/dist/application/queries.generated.js +31 -0
  10. package/bundle/dist/dist/application/request-log/request-log.model.js +113 -0
  11. package/bundle/dist/dist/application/request-log/request-log.types.js +13 -0
  12. package/bundle/dist/dist/application/sonamu.generated.js +99 -0
  13. package/bundle/dist/dist/application/sonamu.generated.sso.js +34 -0
  14. package/bundle/dist/dist/application/token/token.model.js +157 -0
  15. package/bundle/dist/dist/application/token/token.types.js +22 -0
  16. package/bundle/dist/dist/i18n/en.js +63 -0
  17. package/bundle/dist/dist/i18n/ko.js +62 -0
  18. package/bundle/dist/dist/i18n/sd.generated.js +272 -0
  19. package/bundle/dist/dist/index.js +11 -0
  20. package/bundle/dist/dist/migrations/20260410171405_create__request_logs.js +26 -0
  21. package/bundle/dist/dist/migrations/20260410171406_create__tokens.js +24 -0
  22. package/bundle/dist/dist/migrations/20260411120624_alter_tokens_alter2.js +16 -0
  23. package/bundle/dist/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +155 -0
  24. package/bundle/dist/dist/node_modules/.pnpm/@vitest_expect@4.1.2/node_modules/@vitest/expect/dist/index.js +1484 -0
  25. package/bundle/dist/dist/node_modules/.pnpm/@vitest_pretty-format@4.1.2/node_modules/@vitest/pretty-format/dist/index.js +887 -0
  26. package/bundle/dist/dist/node_modules/.pnpm/@vitest_runner@4.1.2/node_modules/@vitest/runner/dist/chunk-artifact.js +2746 -0
  27. package/bundle/dist/dist/node_modules/.pnpm/@vitest_runner@4.1.2/node_modules/@vitest/runner/dist/index.js +8 -0
  28. package/bundle/dist/dist/node_modules/.pnpm/@vitest_runner@4.1.2/node_modules/@vitest/runner/dist/utils.js +8 -0
  29. package/bundle/dist/dist/node_modules/.pnpm/@vitest_snapshot@4.1.2/node_modules/@vitest/snapshot/dist/index.js +662 -0
  30. package/bundle/dist/dist/node_modules/.pnpm/@vitest_spy@4.1.2/node_modules/@vitest/spy/dist/index.js +386 -0
  31. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +82 -0
  32. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/constants.js +48 -0
  33. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/diff.js +1307 -0
  34. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/display.js +558 -0
  35. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/error.js +33 -0
  36. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/helpers.js +226 -0
  37. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/offset.js +27 -0
  38. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/serialize.js +77 -0
  39. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/source-map.js +374 -0
  40. package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/timers.js +37 -0
  41. package/bundle/dist/dist/node_modules/.pnpm/chai@6.2.2/node_modules/chai/index.js +2886 -0
  42. package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/branding.js +10 -0
  43. package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/index.js +109 -0
  44. package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/messages.js +10 -0
  45. package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/overloads.js +10 -0
  46. package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/utils.js +10 -0
  47. package/bundle/dist/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js +1127 -0
  48. package/bundle/dist/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/index.js +21 -0
  49. package/bundle/dist/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js +432 -0
  50. package/bundle/dist/dist/node_modules/.pnpm/tinybench@2.9.0/node_modules/tinybench/dist/index.js +506 -0
  51. package/bundle/dist/dist/node_modules/.pnpm/tinyrainbow@3.1.0/node_modules/tinyrainbow/dist/index.js +86 -0
  52. package/bundle/dist/dist/node_modules/.pnpm/vite@8.0.3_@emnapi_core@1.9.2_@emnapi_runtime@1.9.2_@types_node@25.0.7_esbuild@0.27.4_jiti@2.6.1_sass@1.98.0_tsx@4.21.0/node_modules/vite/dist/node/module-runner.js +426 -0
  53. package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.js +6 -0
  54. package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/benchmark.CX_oY03V.js +41 -0
  55. package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/evaluatedModules.Dg1zASAC.js +19 -0
  56. package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/index.Chj8NDwU.js +202 -0
  57. package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/index.DOa3dzoN.js +16 -0
  58. package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/rpc.MzXet3jl.js +59 -0
  59. package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/test.p_J6dB8a.js +2910 -0
  60. package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/utils.BX5Fg8C4.js +44 -0
  61. package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/index.js +28 -0
  62. package/bundle/dist/dist/sonamu.config.js +196 -0
  63. package/bundle/dist/dist/testing/fixture.js +8 -0
  64. package/bundle/dist/dist/testing/global.js +9 -0
  65. package/bundle/dist/dist/testing/setup-mocks.js +17 -0
  66. package/bundle/dist/dist/utils/subset-loaders.js +12 -0
  67. package/bundle/src/application/qgrid/oauth.ts +181 -0
  68. package/bundle/src/application/qgrid/pool.ts +132 -0
  69. package/bundle/src/application/qgrid/qgrid.frame.ts +275 -0
  70. package/bundle/src/application/qgrid/qgrid.types.ts +117 -0
  71. package/bundle/src/application/qgrid/worker.ts +234 -0
  72. package/bundle/src/application/queries.generated.ts +59 -0
  73. package/bundle/src/application/request-log/request-log.model.ts +155 -0
  74. package/bundle/src/application/request-log/request-log.types.ts +15 -0
  75. package/bundle/src/application/sonamu.generated.http +187 -0
  76. package/bundle/src/application/sonamu.generated.sso.ts +66 -0
  77. package/bundle/src/application/sonamu.generated.ts +135 -0
  78. package/bundle/src/application/token/token.model.ts +160 -0
  79. package/bundle/src/application/token/token.types.ts +26 -0
  80. package/bundle/src/i18n/en.ts +59 -0
  81. package/bundle/src/i18n/ko.ts +59 -0
  82. package/bundle/src/i18n/sd.generated.ts +384 -0
  83. package/bundle/src/index.ts +6 -0
  84. package/bundle/src/sonamu.config.ts +248 -0
  85. package/bundle/src/src/application/qgrid/oauth.ts +181 -0
  86. package/bundle/src/src/application/qgrid/pool.ts +132 -0
  87. package/bundle/src/src/application/qgrid/qgrid.frame.ts +275 -0
  88. package/bundle/src/src/application/qgrid/qgrid.types.ts +117 -0
  89. package/bundle/src/src/application/qgrid/worker.ts +234 -0
  90. package/bundle/src/src/application/queries.generated.ts +59 -0
  91. package/bundle/src/src/application/request-log/request-log.entity.json +75 -0
  92. package/bundle/src/src/application/request-log/request-log.model.ts +155 -0
  93. package/bundle/src/src/application/request-log/request-log.types.ts +15 -0
  94. package/bundle/src/src/application/sonamu.generated.http +187 -0
  95. package/bundle/src/src/application/sonamu.generated.sso.ts +66 -0
  96. package/bundle/src/src/application/sonamu.generated.ts +135 -0
  97. package/bundle/src/src/application/token/token.entity.json +37 -0
  98. package/bundle/src/src/application/token/token.model.ts +160 -0
  99. package/bundle/src/src/application/token/token.types.ts +26 -0
  100. package/bundle/src/src/i18n/en.ts +59 -0
  101. package/bundle/src/src/i18n/ko.ts +59 -0
  102. package/bundle/src/src/i18n/sd.generated.ts +384 -0
  103. package/bundle/src/src/index.ts +6 -0
  104. package/bundle/src/src/migrations/20260410171405_create__request_logs.ts +23 -0
  105. package/bundle/src/src/migrations/20260410171406_create__tokens.ts +21 -0
  106. package/bundle/src/src/migrations/20260411120624_alter_tokens_alter2.ts +15 -0
  107. package/bundle/src/src/sonamu.config.ts +248 -0
  108. package/bundle/src/src/testing/fixture.ts +6 -0
  109. package/bundle/src/src/testing/global.ts +6 -0
  110. package/bundle/src/src/testing/setup-mocks.ts +44 -0
  111. package/bundle/src/src/typings/fastify.d.ts +8 -0
  112. package/bundle/src/src/typings/sonamu.d.ts +17 -0
  113. package/bundle/src/src/utils/subset-loaders.ts +11 -0
  114. package/bundle/src/testing/fixture.ts +6 -0
  115. package/bundle/src/testing/global.ts +6 -0
  116. package/bundle/src/testing/setup-mocks.ts +44 -0
  117. package/bundle/src/typings/fastify.d.ts +8 -0
  118. package/bundle/src/typings/sonamu.d.ts +17 -0
  119. package/bundle/src/utils/subset-loaders.ts +11 -0
  120. package/bundle/web-dist/web-dist/client/assets/index-DlPchHBY.js +116 -0
  121. package/bundle/web-dist/web-dist/client/assets/index-vZsvyuFn.css +1 -0
  122. package/bundle/web-dist/web-dist/client/assets/rolldown-runtime-Dw2cE7zH.js +1 -0
  123. package/bundle/web-dist/web-dist/client/assets/routes-CagDz23B.js +1 -0
  124. package/bundle/web-dist/web-dist/client/assets/sd.generated-BrQoQXvv.js +47 -0
  125. package/bundle/web-dist/web-dist/client/assets/services.generated-BspO2L0j.js +1 -0
  126. package/bundle/web-dist/web-dist/client/assets/show-aXUGa0gm.js +29 -0
  127. package/bundle/web-dist/web-dist/client/assets/tokens-DRkXtZ3Q.js +1 -0
  128. package/bundle/web-dist/web-dist/client/assets/vendor-react-DH4kUfK2.js +9 -0
  129. package/bundle/web-dist/web-dist/client/assets/vendor-tanstack-CUxlo6YN.js +1 -0
  130. package/bundle/web-dist/web-dist/client/index.html +18 -0
  131. package/bundle/web-dist/web-dist/server/assets/react-dom-CGIzOSuj.js +335 -0
  132. package/bundle/web-dist/web-dist/server/assets/routes-ClzReRep.js +490 -0
  133. package/bundle/web-dist/web-dist/server/assets/sd.generated-BnonqqKr.js +21694 -0
  134. package/bundle/web-dist/web-dist/server/assets/services.generated-D5ABD5fr.js +836 -0
  135. package/bundle/web-dist/web-dist/server/assets/show-C9pcdSxc.js +23364 -0
  136. package/bundle/web-dist/web-dist/server/assets/tokens-JH6FsnWZ.js +860 -0
  137. package/bundle/web-dist/web-dist/server/entry-server.generated.js +44646 -0
  138. package/package.json +11 -10
@@ -0,0 +1,662 @@
1
+ import { format, plugins } from "../../../../../@vitest_pretty-format@4.1.2/node_modules/@vitest/pretty-format/dist/index.js";
2
+ import { getCallLastIndex, isObject } from "../../../../../@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/helpers.js";
3
+ import { parseErrorStacktrace } from "../../../../../@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/source-map.js";
4
+ import { lineSplitRE, offsetToLineNumber, positionToOffset } from "../../../../../@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/offset.js";
5
+ //#region ../../node_modules/.pnpm/@vitest+snapshot@4.1.2/node_modules/@vitest/snapshot/dist/index.js
6
+ async function saveInlineSnapshots(environment, snapshots) {
7
+ const MagicString = (await import("../../../../../magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js")).default;
8
+ const files = new Set(snapshots.map((i) => i.file));
9
+ await Promise.all(Array.from(files).map(async (file) => {
10
+ const snaps = snapshots.filter((i) => i.file === file);
11
+ const code = await environment.readSnapshotFile(file);
12
+ if (code == null) throw new Error(`cannot read ${file} when saving inline snapshot`);
13
+ const s = new MagicString(code);
14
+ for (const snap of snaps) replaceInlineSnap(code, s, positionToOffset(code, snap.line, snap.column), snap.snapshot);
15
+ const transformed = s.toString();
16
+ if (transformed !== code) await environment.saveSnapshotFile(file, transformed);
17
+ }));
18
+ }
19
+ const startObjectRegex = /(?:toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot)\s*\(\s*(?:\/\*[\s\S]*\*\/\s*|\/\/.*(?:[\n\r\u2028\u2029]\s*|[\t\v\f \xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF]))*\{/;
20
+ function replaceObjectSnap(code, s, index, newSnap) {
21
+ let _code = code.slice(index);
22
+ const startMatch = startObjectRegex.exec(_code);
23
+ if (!startMatch) return false;
24
+ _code = _code.slice(startMatch.index);
25
+ let callEnd = getCallLastIndex(_code);
26
+ if (callEnd === null) return false;
27
+ callEnd += index + startMatch.index;
28
+ const shapeEnd = getObjectShapeEndIndex(code, index + startMatch.index + startMatch[0].length);
29
+ const snap = `, ${prepareSnapString(newSnap, code, index)}`;
30
+ if (shapeEnd === callEnd) s.appendLeft(callEnd, snap);
31
+ else s.overwrite(shapeEnd, callEnd, snap);
32
+ return true;
33
+ }
34
+ function getObjectShapeEndIndex(code, index) {
35
+ let startBraces = 1;
36
+ let endBraces = 0;
37
+ while (startBraces !== endBraces && index < code.length) {
38
+ const s = code[index++];
39
+ if (s === "{") startBraces++;
40
+ else if (s === "}") endBraces++;
41
+ }
42
+ return index;
43
+ }
44
+ function prepareSnapString(snap, source, index) {
45
+ const lineNumber = offsetToLineNumber(source, index);
46
+ const indent = source.split(lineSplitRE)[lineNumber - 1].match(/^\s*/)[0] || "";
47
+ const indentNext = indent.includes(" ") ? `${indent}\t` : `${indent} `;
48
+ const lines = snap.trim().replace(/\\/g, "\\\\").split(/\n/g);
49
+ const isOneline = lines.length <= 1;
50
+ const quote = "`";
51
+ if (isOneline) return `${quote}${lines.join("\n").replace(/`/g, "\\`").replace(/\$\{/g, "\\${")}${quote}`;
52
+ return `${quote}\n${lines.map((i) => i ? indentNext + i : "").join("\n").replace(/`/g, "\\`").replace(/\$\{/g, "\\${")}\n${indent}${quote}`;
53
+ }
54
+ const toMatchInlineName = "toMatchInlineSnapshot";
55
+ const toThrowErrorMatchingInlineName = "toThrowErrorMatchingInlineSnapshot";
56
+ function getCodeStartingAtIndex(code, index) {
57
+ const indexInline = index - 21;
58
+ if (code.slice(indexInline, index) === toMatchInlineName) return {
59
+ code: code.slice(indexInline),
60
+ index: indexInline
61
+ };
62
+ const indexThrowInline = index - 34;
63
+ if (code.slice(index - indexThrowInline, index) === toThrowErrorMatchingInlineName) return {
64
+ code: code.slice(index - indexThrowInline),
65
+ index: index - indexThrowInline
66
+ };
67
+ return {
68
+ code: code.slice(index),
69
+ index
70
+ };
71
+ }
72
+ const startRegex = /(?:toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot)\s*\(\s*(?:\/\*[\s\S]*\*\/\s*|\/\/.*(?:[\n\r\u2028\u2029]\s*|[\t\v\f \xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF]))*[\w$]*(['"`)])/;
73
+ function replaceInlineSnap(code, s, currentIndex, newSnap) {
74
+ const { code: codeStartingAtIndex, index } = getCodeStartingAtIndex(code, currentIndex);
75
+ const startMatch = startRegex.exec(codeStartingAtIndex);
76
+ const firstKeywordMatch = /toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot/.exec(codeStartingAtIndex);
77
+ if (!startMatch || startMatch.index !== firstKeywordMatch?.index) return replaceObjectSnap(code, s, index, newSnap);
78
+ const quote = startMatch[1];
79
+ const startIndex = index + startMatch.index + startMatch[0].length;
80
+ const snapString = prepareSnapString(newSnap, code, index);
81
+ if (quote === ")") {
82
+ s.appendRight(startIndex - 1, snapString);
83
+ return true;
84
+ }
85
+ const endMatch = new RegExp(`(?:^|[^\\\\])${quote}`).exec(code.slice(startIndex));
86
+ if (!endMatch) return false;
87
+ const endIndex = startIndex + endMatch.index + endMatch[0].length;
88
+ s.overwrite(startIndex - 1, endIndex, snapString);
89
+ return true;
90
+ }
91
+ const INDENTATION_REGEX = /^([^\S\n]*)\S/m;
92
+ function stripSnapshotIndentation(inlineSnapshot) {
93
+ const match = inlineSnapshot.match(INDENTATION_REGEX);
94
+ if (!match || !match[1]) return inlineSnapshot;
95
+ const indentation = match[1];
96
+ const lines = inlineSnapshot.split(/\n/g);
97
+ if (lines.length <= 2) return inlineSnapshot;
98
+ if (lines[0].trim() !== "" || lines.at(-1)?.trim() !== "") return inlineSnapshot;
99
+ for (let i = 1; i < lines.length - 1; i++) if (lines[i] !== "") {
100
+ if (lines[i].indexOf(indentation) !== 0) return inlineSnapshot;
101
+ lines[i] = lines[i].substring(indentation.length);
102
+ }
103
+ lines[lines.length - 1] = "";
104
+ inlineSnapshot = lines.join("\n");
105
+ return inlineSnapshot;
106
+ }
107
+ async function saveRawSnapshots(environment, snapshots) {
108
+ await Promise.all(snapshots.map(async (snap) => {
109
+ if (!snap.readonly) await environment.saveSnapshotFile(snap.file, snap.snapshot);
110
+ }));
111
+ }
112
+ function getDefaultExportFromCjs(x) {
113
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
114
+ }
115
+ var naturalCompare$1 = { exports: {} };
116
+ var hasRequiredNaturalCompare;
117
+ function requireNaturalCompare() {
118
+ if (hasRequiredNaturalCompare) return naturalCompare$1.exports;
119
+ hasRequiredNaturalCompare = 1;
120
+ /*
121
+ * @version 1.4.0
122
+ * @date 2015-10-26
123
+ * @stability 3 - Stable
124
+ * @author Lauri Rooden (https://github.com/litejs/natural-compare-lite)
125
+ * @license MIT License
126
+ */
127
+ var naturalCompare = function(a, b) {
128
+ var i, codeA, codeB = 1, posA = 0, posB = 0, alphabet = String.alphabet;
129
+ function getCode(str, pos, code) {
130
+ if (code) {
131
+ for (i = pos; code = getCode(str, i), code < 76 && code > 65;) ++i;
132
+ return +str.slice(pos - 1, i);
133
+ }
134
+ code = alphabet && alphabet.indexOf(str.charAt(pos));
135
+ return code > -1 ? code + 76 : (code = str.charCodeAt(pos) || 0, code < 45 || code > 127) ? code : code < 46 ? 65 : code < 48 ? code - 1 : code < 58 ? code + 18 : code < 65 ? code - 11 : code < 91 ? code + 11 : code < 97 ? code - 37 : code < 123 ? code + 5 : code - 63;
136
+ }
137
+ if ((a += "") != (b += "")) for (; codeB;) {
138
+ codeA = getCode(a, posA++);
139
+ codeB = getCode(b, posB++);
140
+ if (codeA < 76 && codeB < 76 && codeA > 66 && codeB > 66) {
141
+ codeA = getCode(a, posA, posA);
142
+ codeB = getCode(b, posB, posA = i);
143
+ posB = i;
144
+ }
145
+ if (codeA != codeB) return codeA < codeB ? -1 : 1;
146
+ }
147
+ return 0;
148
+ };
149
+ try {
150
+ naturalCompare$1.exports = naturalCompare;
151
+ } catch (e) {
152
+ String.naturalCompare = naturalCompare;
153
+ }
154
+ return naturalCompare$1.exports;
155
+ }
156
+ var naturalCompare = /* @__PURE__ */ getDefaultExportFromCjs(requireNaturalCompare());
157
+ const serialize$1 = (val, config, indentation, depth, refs, printer) => {
158
+ const name = val.getMockName();
159
+ const nameString = name === "vi.fn()" ? "" : ` ${name}`;
160
+ let callsString = "";
161
+ if (val.mock.calls.length !== 0) {
162
+ const indentationNext = indentation + config.indent;
163
+ callsString = ` {${config.spacingOuter}${indentationNext}"calls": ${printer(val.mock.calls, config, indentationNext, depth, refs)}${config.min ? ", " : ","}${config.spacingOuter}${indentationNext}"results": ${printer(val.mock.results, config, indentationNext, depth, refs)}${config.min ? "" : ","}${config.spacingOuter}${indentation}}`;
164
+ }
165
+ return `[MockFunction${nameString}]${callsString}`;
166
+ };
167
+ const test = (val) => val && !!val._isMockFunction;
168
+ const plugin = {
169
+ serialize: serialize$1,
170
+ test
171
+ };
172
+ const { DOMCollection, DOMElement, Immutable, ReactElement, ReactTestComponent, AsymmetricMatcher } = plugins;
173
+ let PLUGINS = [
174
+ ReactTestComponent,
175
+ ReactElement,
176
+ DOMElement,
177
+ DOMCollection,
178
+ Immutable,
179
+ AsymmetricMatcher,
180
+ plugin
181
+ ];
182
+ function addSerializer(plugin) {
183
+ PLUGINS = [plugin].concat(PLUGINS);
184
+ }
185
+ function getSerializers() {
186
+ return PLUGINS;
187
+ }
188
+ function testNameToKey(testName, count) {
189
+ return `${testName} ${count}`;
190
+ }
191
+ function keyToTestName(key) {
192
+ if (!/ \d+$/.test(key)) throw new Error("Snapshot keys must end with a number.");
193
+ return key.replace(/ \d+$/, "");
194
+ }
195
+ function getSnapshotData(content, options) {
196
+ const update = options.updateSnapshot;
197
+ const data = Object.create(null);
198
+ let snapshotContents = "";
199
+ let dirty = false;
200
+ if (content != null) try {
201
+ snapshotContents = content;
202
+ new Function("exports", snapshotContents)(data);
203
+ } catch {}
204
+ if ((update === "all" || update === "new") && snapshotContents) dirty = true;
205
+ return {
206
+ data,
207
+ dirty
208
+ };
209
+ }
210
+ function addExtraLineBreaks(string) {
211
+ return string.includes("\n") ? `\n${string}\n` : string;
212
+ }
213
+ function removeExtraLineBreaks(string) {
214
+ return string.length > 2 && string[0] === "\n" && string.endsWith("\n") ? string.slice(1, -1) : string;
215
+ }
216
+ const escapeRegex = true;
217
+ const printFunctionName = false;
218
+ function serialize(val, indent = 2, formatOverrides = {}) {
219
+ return normalizeNewlines(format(val, {
220
+ escapeRegex,
221
+ indent,
222
+ plugins: getSerializers(),
223
+ printFunctionName,
224
+ ...formatOverrides
225
+ }));
226
+ }
227
+ function escapeBacktickString(str) {
228
+ return str.replace(/`|\\|\$\{/g, "\\$&");
229
+ }
230
+ function printBacktickString(str) {
231
+ return `\`${escapeBacktickString(str)}\``;
232
+ }
233
+ function normalizeNewlines(string) {
234
+ return string.replace(/\r\n|\r/g, "\n");
235
+ }
236
+ async function saveSnapshotFile(environment, snapshotData, snapshotPath) {
237
+ const snapshots = Object.keys(snapshotData).sort(naturalCompare).map((key) => `exports[${printBacktickString(key)}] = ${printBacktickString(normalizeNewlines(snapshotData[key]))};`);
238
+ const content = `${environment.getHeader()}\n\n${snapshots.join("\n\n")}\n`;
239
+ const oldContent = await environment.readSnapshotFile(snapshotPath);
240
+ if (oldContent != null && oldContent === content) return;
241
+ await environment.saveSnapshotFile(snapshotPath, content);
242
+ }
243
+ function deepMergeArray(target = [], source = []) {
244
+ const mergedOutput = Array.from(target);
245
+ source.forEach((sourceElement, index) => {
246
+ const targetElement = mergedOutput[index];
247
+ if (Array.isArray(target[index])) mergedOutput[index] = deepMergeArray(target[index], sourceElement);
248
+ else if (isObject(targetElement)) mergedOutput[index] = deepMergeSnapshot(target[index], sourceElement);
249
+ else mergedOutput[index] = sourceElement;
250
+ });
251
+ return mergedOutput;
252
+ }
253
+ /**
254
+ * Deep merge, but considers asymmetric matchers. Unlike base util's deep merge,
255
+ * will merge any object-like instance.
256
+ * Compatible with Jest's snapshot matcher. Should not be used outside of snapshot.
257
+ *
258
+ * @example
259
+ * ```ts
260
+ * toMatchSnapshot({
261
+ * name: expect.stringContaining('text')
262
+ * })
263
+ * ```
264
+ */
265
+ function deepMergeSnapshot(target, source) {
266
+ if (isObject(target) && isObject(source)) {
267
+ const mergedOutput = { ...target };
268
+ Object.keys(source).forEach((key) => {
269
+ if (isObject(source[key]) && !source[key].$$typeof) if (!(key in target)) Object.assign(mergedOutput, { [key]: source[key] });
270
+ else mergedOutput[key] = deepMergeSnapshot(target[key], source[key]);
271
+ else if (Array.isArray(source[key])) mergedOutput[key] = deepMergeArray(target[key], source[key]);
272
+ else Object.assign(mergedOutput, { [key]: source[key] });
273
+ });
274
+ return mergedOutput;
275
+ } else if (Array.isArray(target) && Array.isArray(source)) return deepMergeArray(target, source);
276
+ return target;
277
+ }
278
+ var DefaultMap = class extends Map {
279
+ constructor(defaultFn, entries) {
280
+ super(entries);
281
+ this.defaultFn = defaultFn;
282
+ }
283
+ get(key) {
284
+ if (!this.has(key)) this.set(key, this.defaultFn(key));
285
+ return super.get(key);
286
+ }
287
+ };
288
+ var CounterMap = class extends DefaultMap {
289
+ constructor() {
290
+ super(() => 0);
291
+ }
292
+ _total;
293
+ valueOf() {
294
+ return this._total = this.total();
295
+ }
296
+ increment(key) {
297
+ if (typeof this._total !== "undefined") this._total++;
298
+ this.set(key, this.get(key) + 1);
299
+ }
300
+ total() {
301
+ if (typeof this._total !== "undefined") return this._total;
302
+ let total = 0;
303
+ for (const x of this.values()) total += x;
304
+ return total;
305
+ }
306
+ };
307
+ function isSameStackPosition(x, y) {
308
+ return x.file === y.file && x.column === y.column && x.line === y.line;
309
+ }
310
+ var SnapshotState = class SnapshotState {
311
+ _counters = new CounterMap();
312
+ _dirty;
313
+ _updateSnapshot;
314
+ _snapshotData;
315
+ _initialData;
316
+ _inlineSnapshots;
317
+ _inlineSnapshotStacks;
318
+ _testIdToKeys = new DefaultMap(() => []);
319
+ _rawSnapshots;
320
+ _uncheckedKeys;
321
+ _snapshotFormat;
322
+ _environment;
323
+ _fileExists;
324
+ expand;
325
+ _added = new CounterMap();
326
+ _matched = new CounterMap();
327
+ _unmatched = new CounterMap();
328
+ _updated = new CounterMap();
329
+ get added() {
330
+ return this._added;
331
+ }
332
+ set added(value) {
333
+ this._added._total = value;
334
+ }
335
+ get matched() {
336
+ return this._matched;
337
+ }
338
+ set matched(value) {
339
+ this._matched._total = value;
340
+ }
341
+ get unmatched() {
342
+ return this._unmatched;
343
+ }
344
+ set unmatched(value) {
345
+ this._unmatched._total = value;
346
+ }
347
+ get updated() {
348
+ return this._updated;
349
+ }
350
+ set updated(value) {
351
+ this._updated._total = value;
352
+ }
353
+ constructor(testFilePath, snapshotPath, snapshotContent, options) {
354
+ this.testFilePath = testFilePath;
355
+ this.snapshotPath = snapshotPath;
356
+ const { data, dirty } = getSnapshotData(snapshotContent, options);
357
+ this._fileExists = snapshotContent != null;
358
+ this._initialData = { ...data };
359
+ this._snapshotData = { ...data };
360
+ this._dirty = dirty;
361
+ this._inlineSnapshots = [];
362
+ this._inlineSnapshotStacks = [];
363
+ this._rawSnapshots = [];
364
+ this._uncheckedKeys = new Set(Object.keys(this._snapshotData));
365
+ this.expand = options.expand || false;
366
+ this._updateSnapshot = options.updateSnapshot;
367
+ this._snapshotFormat = {
368
+ printBasicPrototype: false,
369
+ escapeString: false,
370
+ ...options.snapshotFormat
371
+ };
372
+ this._environment = options.snapshotEnvironment;
373
+ }
374
+ static async create(testFilePath, options) {
375
+ const snapshotPath = await options.snapshotEnvironment.resolvePath(testFilePath);
376
+ return new SnapshotState(testFilePath, snapshotPath, await options.snapshotEnvironment.readSnapshotFile(snapshotPath), options);
377
+ }
378
+ get environment() {
379
+ return this._environment;
380
+ }
381
+ markSnapshotsAsCheckedForTest(testName) {
382
+ this._uncheckedKeys.forEach((uncheckedKey) => {
383
+ if (/ \d+$| > /.test(uncheckedKey.slice(testName.length))) this._uncheckedKeys.delete(uncheckedKey);
384
+ });
385
+ }
386
+ clearTest(testId) {
387
+ this._inlineSnapshots = this._inlineSnapshots.filter((s) => s.testId !== testId);
388
+ this._inlineSnapshotStacks = this._inlineSnapshotStacks.filter((s) => s.testId !== testId);
389
+ for (const key of this._testIdToKeys.get(testId)) {
390
+ const name = keyToTestName(key);
391
+ const count = this._counters.get(name);
392
+ if (count > 0) {
393
+ if (key in this._snapshotData || key in this._initialData) this._snapshotData[key] = this._initialData[key];
394
+ this._counters.set(name, count - 1);
395
+ }
396
+ }
397
+ this._testIdToKeys.delete(testId);
398
+ this.added.delete(testId);
399
+ this.updated.delete(testId);
400
+ this.matched.delete(testId);
401
+ this.unmatched.delete(testId);
402
+ }
403
+ _inferInlineSnapshotStack(stacks) {
404
+ const promiseIndex = stacks.findIndex((i) => i.method.match(/__VITEST_(RESOLVES|REJECTS)__/));
405
+ if (promiseIndex !== -1) return stacks[promiseIndex + 3];
406
+ for (let i = 0; i < stacks.length; i++) {
407
+ const match = stacks[i].method.match(/__INLINE_SNAPSHOT_OFFSET_(\d+)__/);
408
+ if (match) return stacks[i + Number(match[1])] ?? null;
409
+ }
410
+ const stackIndex = stacks.findIndex((i) => i.method.includes("__INLINE_SNAPSHOT__"));
411
+ return stackIndex !== -1 ? stacks[stackIndex + 2] : null;
412
+ }
413
+ _addSnapshot(key, receivedSerialized, options) {
414
+ this._dirty = true;
415
+ if (options.stack) this._inlineSnapshots.push({
416
+ snapshot: receivedSerialized,
417
+ testId: options.testId,
418
+ ...options.stack
419
+ });
420
+ else if (options.rawSnapshot) this._rawSnapshots.push({
421
+ ...options.rawSnapshot,
422
+ snapshot: receivedSerialized
423
+ });
424
+ else this._snapshotData[key] = receivedSerialized;
425
+ }
426
+ async save() {
427
+ const hasExternalSnapshots = Object.keys(this._snapshotData).length;
428
+ const hasInlineSnapshots = this._inlineSnapshots.length;
429
+ const hasRawSnapshots = this._rawSnapshots.length;
430
+ const isEmpty = !hasExternalSnapshots && !hasInlineSnapshots && !hasRawSnapshots;
431
+ const status = {
432
+ deleted: false,
433
+ saved: false
434
+ };
435
+ if ((this._dirty || this._uncheckedKeys.size) && !isEmpty) {
436
+ if (hasExternalSnapshots) {
437
+ await saveSnapshotFile(this._environment, this._snapshotData, this.snapshotPath);
438
+ this._fileExists = true;
439
+ }
440
+ if (hasInlineSnapshots) await saveInlineSnapshots(this._environment, this._inlineSnapshots);
441
+ if (hasRawSnapshots) await saveRawSnapshots(this._environment, this._rawSnapshots);
442
+ status.saved = true;
443
+ } else if (!hasExternalSnapshots && this._fileExists) {
444
+ if (this._updateSnapshot === "all") {
445
+ await this._environment.removeSnapshotFile(this.snapshotPath);
446
+ this._fileExists = false;
447
+ }
448
+ status.deleted = true;
449
+ }
450
+ return status;
451
+ }
452
+ getUncheckedCount() {
453
+ return this._uncheckedKeys.size || 0;
454
+ }
455
+ getUncheckedKeys() {
456
+ return Array.from(this._uncheckedKeys);
457
+ }
458
+ removeUncheckedKeys() {
459
+ if (this._updateSnapshot === "all" && this._uncheckedKeys.size) {
460
+ this._dirty = true;
461
+ this._uncheckedKeys.forEach((key) => delete this._snapshotData[key]);
462
+ this._uncheckedKeys.clear();
463
+ }
464
+ }
465
+ match({ testId, testName, received, key, inlineSnapshot, isInline, error, rawSnapshot }) {
466
+ this._counters.increment(testName);
467
+ const count = this._counters.get(testName);
468
+ if (!key) key = testNameToKey(testName, count);
469
+ this._testIdToKeys.get(testId).push(key);
470
+ if (!(isInline && this._snapshotData[key] !== void 0)) this._uncheckedKeys.delete(key);
471
+ let receivedSerialized = rawSnapshot && typeof received === "string" ? received : serialize(received, void 0, this._snapshotFormat);
472
+ if (!rawSnapshot) receivedSerialized = addExtraLineBreaks(receivedSerialized);
473
+ if (rawSnapshot) {
474
+ if (rawSnapshot.content && rawSnapshot.content.match(/\r\n/) && !receivedSerialized.match(/\r\n/)) rawSnapshot.content = normalizeNewlines(rawSnapshot.content);
475
+ }
476
+ const expected = isInline ? inlineSnapshot : rawSnapshot ? rawSnapshot.content : this._snapshotData[key];
477
+ const expectedTrimmed = rawSnapshot ? expected : expected?.trim();
478
+ const pass = expectedTrimmed === (rawSnapshot ? receivedSerialized : receivedSerialized.trim());
479
+ const hasSnapshot = expected !== void 0;
480
+ const snapshotIsPersisted = isInline || this._fileExists || rawSnapshot && rawSnapshot.content != null;
481
+ if (pass && !isInline && !rawSnapshot) this._snapshotData[key] = receivedSerialized;
482
+ let stack;
483
+ if (isInline) {
484
+ const stacks = parseErrorStacktrace(error || /* @__PURE__ */ new Error("snapshot"), { ignoreStackEntries: [] });
485
+ const _stack = this._inferInlineSnapshotStack(stacks);
486
+ if (!_stack) throw new Error(`@vitest/snapshot: Couldn't infer stack frame for inline snapshot.\n${JSON.stringify(stacks)}`);
487
+ stack = this.environment.processStackTrace?.(_stack) || _stack;
488
+ stack.column--;
489
+ const snapshotsWithSameStack = this._inlineSnapshotStacks.filter((s) => isSameStackPosition(s, stack));
490
+ if (snapshotsWithSameStack.length > 0) {
491
+ this._inlineSnapshots = this._inlineSnapshots.filter((s) => !isSameStackPosition(s, stack));
492
+ const differentSnapshot = snapshotsWithSameStack.find((s) => s.snapshot !== receivedSerialized);
493
+ if (differentSnapshot) throw Object.assign(/* @__PURE__ */ new Error("toMatchInlineSnapshot with different snapshots cannot be called at the same location"), {
494
+ actual: receivedSerialized,
495
+ expected: differentSnapshot.snapshot
496
+ });
497
+ }
498
+ this._inlineSnapshotStacks.push({
499
+ ...stack,
500
+ testId,
501
+ snapshot: receivedSerialized
502
+ });
503
+ }
504
+ if (hasSnapshot && this._updateSnapshot === "all" || (!hasSnapshot || !snapshotIsPersisted) && (this._updateSnapshot === "new" || this._updateSnapshot === "all")) {
505
+ if (this._updateSnapshot === "all") if (!pass) {
506
+ if (hasSnapshot) this.updated.increment(testId);
507
+ else this.added.increment(testId);
508
+ this._addSnapshot(key, receivedSerialized, {
509
+ stack,
510
+ testId,
511
+ rawSnapshot
512
+ });
513
+ } else this.matched.increment(testId);
514
+ else {
515
+ this._addSnapshot(key, receivedSerialized, {
516
+ stack,
517
+ testId,
518
+ rawSnapshot
519
+ });
520
+ this.added.increment(testId);
521
+ }
522
+ return {
523
+ actual: "",
524
+ count,
525
+ expected: "",
526
+ key,
527
+ pass: true
528
+ };
529
+ } else if (!pass) {
530
+ this.unmatched.increment(testId);
531
+ return {
532
+ actual: rawSnapshot ? receivedSerialized : removeExtraLineBreaks(receivedSerialized),
533
+ count,
534
+ expected: expectedTrimmed !== void 0 ? rawSnapshot ? expectedTrimmed : removeExtraLineBreaks(expectedTrimmed) : void 0,
535
+ key,
536
+ pass: false
537
+ };
538
+ } else {
539
+ this.matched.increment(testId);
540
+ return {
541
+ actual: "",
542
+ count,
543
+ expected: "",
544
+ key,
545
+ pass: true
546
+ };
547
+ }
548
+ }
549
+ async pack() {
550
+ const snapshot = {
551
+ filepath: this.testFilePath,
552
+ added: 0,
553
+ fileDeleted: false,
554
+ matched: 0,
555
+ unchecked: 0,
556
+ uncheckedKeys: [],
557
+ unmatched: 0,
558
+ updated: 0
559
+ };
560
+ const uncheckedCount = this.getUncheckedCount();
561
+ const uncheckedKeys = this.getUncheckedKeys();
562
+ if (uncheckedCount) this.removeUncheckedKeys();
563
+ const status = await this.save();
564
+ snapshot.fileDeleted = status.deleted;
565
+ snapshot.added = this.added.total();
566
+ snapshot.matched = this.matched.total();
567
+ snapshot.unmatched = this.unmatched.total();
568
+ snapshot.updated = this.updated.total();
569
+ snapshot.unchecked = !status.deleted ? uncheckedCount : 0;
570
+ snapshot.uncheckedKeys = Array.from(uncheckedKeys);
571
+ return snapshot;
572
+ }
573
+ };
574
+ function createMismatchError(message, expand, actual, expected) {
575
+ const error = new Error(message);
576
+ Object.defineProperty(error, "actual", {
577
+ value: actual,
578
+ enumerable: true,
579
+ configurable: true,
580
+ writable: true
581
+ });
582
+ Object.defineProperty(error, "expected", {
583
+ value: expected,
584
+ enumerable: true,
585
+ configurable: true,
586
+ writable: true
587
+ });
588
+ Object.defineProperty(error, "diffOptions", { value: { expand } });
589
+ return error;
590
+ }
591
+ var SnapshotClient = class {
592
+ snapshotStateMap = /* @__PURE__ */ new Map();
593
+ constructor(options = {}) {
594
+ this.options = options;
595
+ }
596
+ async setup(filepath, options) {
597
+ if (this.snapshotStateMap.has(filepath)) return;
598
+ this.snapshotStateMap.set(filepath, await SnapshotState.create(filepath, options));
599
+ }
600
+ async finish(filepath) {
601
+ const result = await this.getSnapshotState(filepath).pack();
602
+ this.snapshotStateMap.delete(filepath);
603
+ return result;
604
+ }
605
+ skipTest(filepath, testName) {
606
+ this.getSnapshotState(filepath).markSnapshotsAsCheckedForTest(testName);
607
+ }
608
+ clearTest(filepath, testId) {
609
+ this.getSnapshotState(filepath).clearTest(testId);
610
+ }
611
+ getSnapshotState(filepath) {
612
+ const state = this.snapshotStateMap.get(filepath);
613
+ if (!state) throw new Error(`The snapshot state for '${filepath}' is not found. Did you call 'SnapshotClient.setup()'?`);
614
+ return state;
615
+ }
616
+ assert(options) {
617
+ const { filepath, name, testId = name, message, isInline = false, properties, inlineSnapshot, error, errorMessage, rawSnapshot } = options;
618
+ let { received } = options;
619
+ if (!filepath) throw new Error("Snapshot cannot be used outside of test");
620
+ const snapshotState = this.getSnapshotState(filepath);
621
+ if (typeof properties === "object") {
622
+ if (typeof received !== "object" || !received) throw new Error("Received value must be an object when the matcher has properties");
623
+ try {
624
+ if (!(this.options.isEqual?.(received, properties) ?? false)) throw createMismatchError("Snapshot properties mismatched", snapshotState.expand, received, properties);
625
+ else received = deepMergeSnapshot(received, properties);
626
+ } catch (err) {
627
+ err.message = errorMessage || "Snapshot mismatched";
628
+ throw err;
629
+ }
630
+ }
631
+ const testName = [name, ...message ? [message] : []].join(" > ");
632
+ const { actual, expected, key, pass } = snapshotState.match({
633
+ testId,
634
+ testName,
635
+ received,
636
+ isInline,
637
+ error,
638
+ inlineSnapshot,
639
+ rawSnapshot
640
+ });
641
+ if (!pass) throw createMismatchError(`Snapshot \`${key || "unknown"}\` mismatched`, snapshotState.expand, rawSnapshot ? actual : actual?.trim(), rawSnapshot ? expected : expected?.trim());
642
+ }
643
+ async assertRaw(options) {
644
+ if (!options.rawSnapshot) throw new Error("Raw snapshot is required");
645
+ const { filepath, rawSnapshot } = options;
646
+ if (rawSnapshot.content == null) {
647
+ if (!filepath) throw new Error("Snapshot cannot be used outside of test");
648
+ const snapshotState = this.getSnapshotState(filepath);
649
+ options.filepath ||= filepath;
650
+ rawSnapshot.file = await snapshotState.environment.resolveRawPath(filepath, rawSnapshot.file);
651
+ rawSnapshot.content = await snapshotState.environment.readSnapshotFile(rawSnapshot.file) ?? void 0;
652
+ }
653
+ return this.assert(options);
654
+ }
655
+ clear() {
656
+ this.snapshotStateMap.clear();
657
+ }
658
+ };
659
+ //#endregion
660
+ export { SnapshotClient, addSerializer, stripSnapshotIndentation };
661
+
662
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vbm9kZV9tb2R1bGVzLy5wbnBtL0B2aXRlc3Qrc25hcHNob3RANC4xLjIvbm9kZV9tb2R1bGVzL0B2aXRlc3Qvc25hcHNob3QvZGlzdC9pbmRleC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBwYXJzZUVycm9yU3RhY2t0cmFjZSB9IGZyb20gJ0B2aXRlc3QvdXRpbHMvc291cmNlLW1hcCc7XG5pbXBvcnQgeyBnZXRDYWxsTGFzdEluZGV4LCBpc09iamVjdCB9IGZyb20gJ0B2aXRlc3QvdXRpbHMvaGVscGVycyc7XG5pbXBvcnQgeyBwb3NpdGlvblRvT2Zmc2V0LCBvZmZzZXRUb0xpbmVOdW1iZXIsIGxpbmVTcGxpdFJFIH0gZnJvbSAnQHZpdGVzdC91dGlscy9vZmZzZXQnO1xuaW1wb3J0IHsgcGx1Z2lucywgZm9ybWF0IH0gZnJvbSAnQHZpdGVzdC9wcmV0dHktZm9ybWF0JztcblxuYXN5bmMgZnVuY3Rpb24gc2F2ZUlubGluZVNuYXBzaG90cyhlbnZpcm9ubWVudCwgc25hcHNob3RzKSB7XG5cdGNvbnN0IE1hZ2ljU3RyaW5nID0gKGF3YWl0IGltcG9ydCgnbWFnaWMtc3RyaW5nJykpLmRlZmF1bHQ7XG5cdGNvbnN0IGZpbGVzID0gbmV3IFNldChzbmFwc2hvdHMubWFwKChpKSA9PiBpLmZpbGUpKTtcblx0YXdhaXQgUHJvbWlzZS5hbGwoQXJyYXkuZnJvbShmaWxlcykubWFwKGFzeW5jIChmaWxlKSA9PiB7XG5cdFx0Y29uc3Qgc25hcHMgPSBzbmFwc2hvdHMuZmlsdGVyKChpKSA9PiBpLmZpbGUgPT09IGZpbGUpO1xuXHRcdGNvbnN0IGNvZGUgPSBhd2FpdCBlbnZpcm9ubWVudC5yZWFkU25hcHNob3RGaWxlKGZpbGUpO1xuXHRcdGlmIChjb2RlID09IG51bGwpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihgY2Fubm90IHJlYWQgJHtmaWxlfSB3aGVuIHNhdmluZyBpbmxpbmUgc25hcHNob3RgKTtcblx0XHR9XG5cdFx0Y29uc3QgcyA9IG5ldyBNYWdpY1N0cmluZyhjb2RlKTtcblx0XHRmb3IgKGNvbnN0IHNuYXAgb2Ygc25hcHMpIHtcblx0XHRcdGNvbnN0IGluZGV4ID0gcG9zaXRpb25Ub09mZnNldChjb2RlLCBzbmFwLmxpbmUsIHNuYXAuY29sdW1uKTtcblx0XHRcdHJlcGxhY2VJbmxpbmVTbmFwKGNvZGUsIHMsIGluZGV4LCBzbmFwLnNuYXBzaG90KTtcblx0XHR9XG5cdFx0Y29uc3QgdHJhbnNmb3JtZWQgPSBzLnRvU3RyaW5nKCk7XG5cdFx0aWYgKHRyYW5zZm9ybWVkICE9PSBjb2RlKSB7XG5cdFx0XHRhd2FpdCBlbnZpcm9ubWVudC5zYXZlU25hcHNob3RGaWxlKGZpbGUsIHRyYW5zZm9ybWVkKTtcblx0XHR9XG5cdH0pKTtcbn1cbmNvbnN0IHN0YXJ0T2JqZWN0UmVnZXggPSAvKD86dG9NYXRjaElubGluZVNuYXBzaG90fHRvVGhyb3dFcnJvck1hdGNoaW5nSW5saW5lU25hcHNob3QpXFxzKlxcKFxccyooPzpcXC9cXCpbXFxzXFxTXSpcXCpcXC9cXHMqfFxcL1xcLy4qKD86W1xcblxcclxcdTIwMjhcXHUyMDI5XVxccyp8W1xcdFxcdlxcZiBcXHhBMFxcdTE2ODBcXHUyMDAwLVxcdTIwMEFcXHUyMDJGXFx1MjA1RlxcdTMwMDBcXHVGRUZGXSkpKlxcey87XG5mdW5jdGlvbiByZXBsYWNlT2JqZWN0U25hcChjb2RlLCBzLCBpbmRleCwgbmV3U25hcCkge1xuXHRsZXQgX2NvZGUgPSBjb2RlLnNsaWNlKGluZGV4KTtcblx0Y29uc3Qgc3RhcnRNYXRjaCA9IHN0YXJ0T2JqZWN0UmVnZXguZXhlYyhfY29kZSk7XG5cdGlmICghc3RhcnRNYXRjaCkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXHRfY29kZSA9IF9jb2RlLnNsaWNlKHN0YXJ0TWF0Y2guaW5kZXgpO1xuXHRsZXQgY2FsbEVuZCA9IGdldENhbGxMYXN0SW5kZXgoX2NvZGUpO1xuXHRpZiAoY2FsbEVuZCA9PT0gbnVsbCkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXHRjYWxsRW5kICs9IGluZGV4ICsgc3RhcnRNYXRjaC5pbmRleDtcblx0Y29uc3Qgc2hhcGVTdGFydCA9IGluZGV4ICsgc3RhcnRNYXRjaC5pbmRleCArIHN0YXJ0TWF0Y2hbMF0ubGVuZ3RoO1xuXHRjb25zdCBzaGFwZUVuZCA9IGdldE9iamVjdFNoYXBlRW5kSW5kZXgoY29kZSwgc2hhcGVTdGFydCk7XG5cdGNvbnN0IHNuYXAgPSBgLCAke3ByZXBhcmVTbmFwU3RyaW5nKG5ld1NuYXAsIGNvZGUsIGluZGV4KX1gO1xuXHRpZiAoc2hhcGVFbmQgPT09IGNhbGxFbmQpIHtcblx0XHQvLyB0b01hdGNoSW5saW5lU25hcHNob3QoeyBmb286IGV4cGVjdC5hbnkoU3RyaW5nKSB9KVxuXHRcdHMuYXBwZW5kTGVmdChjYWxsRW5kLCBzbmFwKTtcblx0fSBlbHNlIHtcblx0XHQvLyB0b01hdGNoSW5saW5lU25hcHNob3QoeyBmb286IGV4cGVjdC5hbnkoU3RyaW5nKSB9LCBgYClcblx0XHRzLm92ZXJ3cml0ZShzaGFwZUVuZCwgY2FsbEVuZCwgc25hcCk7XG5cdH1cblx0cmV0dXJuIHRydWU7XG59XG5mdW5jdGlvbiBnZXRPYmplY3RTaGFwZUVuZEluZGV4KGNvZGUsIGluZGV4KSB7XG5cdGxldCBzdGFydEJyYWNlcyA9IDE7XG5cdGxldCBlbmRCcmFjZXMgPSAwO1xuXHR3aGlsZSAoc3RhcnRCcmFjZXMgIT09IGVuZEJyYWNlcyAmJiBpbmRleCA8IGNvZGUubGVuZ3RoKSB7XG5cdFx0Y29uc3QgcyA9IGNvZGVbaW5kZXgrK107XG5cdFx0aWYgKHMgPT09IFwie1wiKSB7XG5cdFx0XHRzdGFydEJyYWNlcysrO1xuXHRcdH0gZWxzZSBpZiAocyA9PT0gXCJ9XCIpIHtcblx0XHRcdGVuZEJyYWNlcysrO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gaW5kZXg7XG59XG5mdW5jdGlvbiBwcmVwYXJlU25hcFN0cmluZyhzbmFwLCBzb3VyY2UsIGluZGV4KSB7XG5cdGNvbnN0IGxpbmVOdW1iZXIgPSBvZmZzZXRUb0xpbmVOdW1iZXIoc291cmNlLCBpbmRleCk7XG5cdGNvbnN0IGxpbmUgPSBzb3VyY2Uuc3BsaXQobGluZVNwbGl0UkUpW2xpbmVOdW1iZXIgLSAxXTtcblx0Y29uc3QgaW5kZW50ID0gbGluZS5tYXRjaCgvXlxccyovKVswXSB8fCBcIlwiO1xuXHRjb25zdCBpbmRlbnROZXh0ID0gaW5kZW50LmluY2x1ZGVzKFwiXHRcIikgPyBgJHtpbmRlbnR9XFx0YCA6IGAke2luZGVudH0gIGA7XG5cdGNvbnN0IGxpbmVzID0gc25hcC50cmltKCkucmVwbGFjZSgvXFxcXC9nLCBcIlxcXFxcXFxcXCIpLnNwbGl0KC9cXG4vZyk7XG5cdGNvbnN0IGlzT25lbGluZSA9IGxpbmVzLmxlbmd0aCA8PSAxO1xuXHRjb25zdCBxdW90ZSA9IFwiYFwiO1xuXHRpZiAoaXNPbmVsaW5lKSB7XG5cdFx0cmV0dXJuIGAke3F1b3RlfSR7bGluZXMuam9pbihcIlxcblwiKS5yZXBsYWNlKC9gL2csIFwiXFxcXGBcIikucmVwbGFjZSgvXFwkXFx7L2csIFwiXFxcXCR7XCIpfSR7cXVvdGV9YDtcblx0fVxuXHRyZXR1cm4gYCR7cXVvdGV9XFxuJHtsaW5lcy5tYXAoKGkpID0+IGkgPyBpbmRlbnROZXh0ICsgaSA6IFwiXCIpLmpvaW4oXCJcXG5cIikucmVwbGFjZSgvYC9nLCBcIlxcXFxgXCIpLnJlcGxhY2UoL1xcJFxcey9nLCBcIlxcXFwke1wiKX1cXG4ke2luZGVudH0ke3F1b3RlfWA7XG59XG5jb25zdCB0b01hdGNoSW5saW5lTmFtZSA9IFwidG9NYXRjaElubGluZVNuYXBzaG90XCI7XG5jb25zdCB0b1Rocm93RXJyb3JNYXRjaGluZ0lubGluZU5hbWUgPSBcInRvVGhyb3dFcnJvck1hdGNoaW5nSW5saW5lU25hcHNob3RcIjtcbi8vIG9uIHdlYmtpdCwgdGhlIGxpbmUgbnVtYmVyIGlzIGF0IHRoZSBlbmQgb2YgdGhlIG1ldGhvZCwgbm90IGF0IHRoZSBzdGFydFxuZnVuY3Rpb24gZ2V0Q29kZVN0YXJ0aW5nQXRJbmRleChjb2RlLCBpbmRleCkge1xuXHRjb25zdCBpbmRleElubGluZSA9IGluZGV4IC0gdG9NYXRjaElubGluZU5hbWUubGVuZ3RoO1xuXHRpZiAoY29kZS5zbGljZShpbmRleElubGluZSwgaW5kZXgpID09PSB0b01hdGNoSW5saW5lTmFtZSkge1xuXHRcdHJldHVybiB7XG5cdFx0XHRjb2RlOiBjb2RlLnNsaWNlKGluZGV4SW5saW5lKSxcblx0XHRcdGluZGV4OiBpbmRleElubGluZVxuXHRcdH07XG5cdH1cblx0Y29uc3QgaW5kZXhUaHJvd0lubGluZSA9IGluZGV4IC0gdG9UaHJvd0Vycm9yTWF0Y2hpbmdJbmxpbmVOYW1lLmxlbmd0aDtcblx0aWYgKGNvZGUuc2xpY2UoaW5kZXggLSBpbmRleFRocm93SW5saW5lLCBpbmRleCkgPT09IHRvVGhyb3dFcnJvck1hdGNoaW5nSW5saW5lTmFtZSkge1xuXHRcdHJldHVybiB7XG5cdFx0XHRjb2RlOiBjb2RlLnNsaWNlKGluZGV4IC0gaW5kZXhUaHJvd0lubGluZSksXG5cdFx0XHRpbmRleDogaW5kZXggLSBpbmRleFRocm93SW5saW5lXG5cdFx0fTtcblx0fVxuXHRyZXR1cm4ge1xuXHRcdGNvZGU6IGNvZGUuc2xpY2UoaW5kZXgpLFxuXHRcdGluZGV4XG5cdH07XG59XG5jb25zdCBzdGFydFJlZ2V4ID0gLyg/OnRvTWF0Y2hJbmxpbmVTbmFwc2hvdHx0b1Rocm93RXJyb3JNYXRjaGluZ0lubGluZVNuYXBzaG90KVxccypcXChcXHMqKD86XFwvXFwqW1xcc1xcU10qXFwqXFwvXFxzKnxcXC9cXC8uKig/OltcXG5cXHJcXHUyMDI4XFx1MjAyOV1cXHMqfFtcXHRcXHZcXGYgXFx4QTBcXHUxNjgwXFx1MjAwMC1cXHUyMDBBXFx1MjAyRlxcdTIwNUZcXHUzMDAwXFx1RkVGRl0pKSpbXFx3JF0qKFsnXCJgKV0pLztcbmZ1bmN0aW9uIHJlcGxhY2VJbmxpbmVTbmFwKGNvZGUsIHMsIGN1cnJlbnRJbmRleCwgbmV3U25hcCkge1xuXHRjb25zdCB7IGNvZGU6IGNvZGVTdGFydGluZ0F0SW5kZXgsIGluZGV4IH0gPSBnZXRDb2RlU3RhcnRpbmdBdEluZGV4KGNvZGUsIGN1cnJlbnRJbmRleCk7XG5cdGNvbnN0IHN0YXJ0TWF0Y2ggPSBzdGFydFJlZ2V4LmV4ZWMoY29kZVN0YXJ0aW5nQXRJbmRleCk7XG5cdGNvbnN0IGZpcnN0S2V5d29yZE1hdGNoID0gL3RvTWF0Y2hJbmxpbmVTbmFwc2hvdHx0b1Rocm93RXJyb3JNYXRjaGluZ0lubGluZVNuYXBzaG90Ly5leGVjKGNvZGVTdGFydGluZ0F0SW5kZXgpO1xuXHRpZiAoIXN0YXJ0TWF0Y2ggfHwgc3RhcnRNYXRjaC5pbmRleCAhPT0gZmlyc3RLZXl3b3JkTWF0Y2g/LmluZGV4KSB7XG5cdFx0cmV0dXJuIHJlcGxhY2VPYmplY3RTbmFwKGNvZGUsIHMsIGluZGV4LCBuZXdTbmFwKTtcblx0fVxuXHRjb25zdCBxdW90ZSA9IHN0YXJ0TWF0Y2hbMV07XG5cdGNvbnN0IHN0YXJ0SW5kZXggPSBpbmRleCArIHN0YXJ0TWF0Y2guaW5kZXggKyBzdGFydE1hdGNoWzBdLmxlbmd0aDtcblx0Y29uc3Qgc25hcFN0cmluZyA9IHByZXBhcmVTbmFwU3RyaW5nKG5ld1NuYXAsIGNvZGUsIGluZGV4KTtcblx0aWYgKHF1b3RlID09PSBcIilcIikge1xuXHRcdHMuYXBwZW5kUmlnaHQoc3RhcnRJbmRleCAtIDEsIHNuYXBTdHJpbmcpO1xuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cdGNvbnN0IHF1b3RlRW5kUkUgPSBuZXcgUmVnRXhwKGAoPzpefFteXFxcXFxcXFxdKSR7cXVvdGV9YCk7XG5cdGNvbnN0IGVuZE1hdGNoID0gcXVvdGVFbmRSRS5leGVjKGNvZGUuc2xpY2Uoc3RhcnRJbmRleCkpO1xuXHRpZiAoIWVuZE1hdGNoKSB7XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cdGNvbnN0IGVuZEluZGV4ID0gc3RhcnRJbmRleCArIGVuZE1hdGNoLmluZGV4ICsgZW5kTWF0Y2hbMF0ubGVuZ3RoO1xuXHRzLm92ZXJ3cml0ZShzdGFydEluZGV4IC0gMSwgZW5kSW5kZXgsIHNuYXBTdHJpbmcpO1xuXHRyZXR1cm4gdHJ1ZTtcbn1cbmNvbnN0IElOREVOVEFUSU9OX1JFR0VYID0gL14oW15cXFNcXG5dKilcXFMvbTtcbmZ1bmN0aW9uIHN0cmlwU25hcHNob3RJbmRlbnRhdGlvbihpbmxpbmVTbmFwc2hvdCkge1xuXHQvLyBGaW5kIGluZGVudGF0aW9uIGlmIGV4aXN0cy5cblx0Y29uc3QgbWF0Y2ggPSBpbmxpbmVTbmFwc2hvdC5tYXRjaChJTkRFTlRBVElPTl9SRUdFWCk7XG5cdGlmICghbWF0Y2ggfHwgIW1hdGNoWzFdKSB7XG5cdFx0Ly8gTm8gaW5kZW50YXRpb24uXG5cdFx0cmV0dXJuIGlubGluZVNuYXBzaG90O1xuXHR9XG5cdGNvbnN0IGluZGVudGF0aW9uID0gbWF0Y2hbMV07XG5cdGNvbnN0IGxpbmVzID0gaW5saW5lU25hcHNob3Quc3BsaXQoL1xcbi9nKTtcblx0aWYgKGxpbmVzLmxlbmd0aCA8PSAyKSB7XG5cdFx0Ly8gTXVzdCBiZSBhdCBsZWFzdCAzIGxpbmVzLlxuXHRcdHJldHVybiBpbmxpbmVTbmFwc2hvdDtcblx0fVxuXHRpZiAobGluZXNbMF0udHJpbSgpICE9PSBcIlwiIHx8IGxpbmVzLmF0KC0xKT8udHJpbSgpICE9PSBcIlwiKSB7XG5cdFx0Ly8gSWYgbm90IGJsYW5rIGZpcnN0IGFuZCBsYXN0IGxpbmVzLCBhYm9ydC5cblx0XHRyZXR1cm4gaW5saW5lU25hcHNob3Q7XG5cdH1cblx0Zm9yIChsZXQgaSA9IDE7IGkgPCBsaW5lcy5sZW5ndGggLSAxOyBpKyspIHtcblx0XHRpZiAobGluZXNbaV0gIT09IFwiXCIpIHtcblx0XHRcdGlmIChsaW5lc1tpXS5pbmRleE9mKGluZGVudGF0aW9uKSAhPT0gMCkge1xuXHRcdFx0XHQvLyBBbGwgbGluZXMgZXhjZXB0IGZpcnN0IGFuZCBsYXN0IHNob3VsZCBlaXRoZXIgYmUgYmxhbmsgb3IgaGF2ZSB0aGUgc2FtZVxuXHRcdFx0XHQvLyBpbmRlbnQgYXMgdGhlIGZpcnN0IGxpbmUgKG9yIG1vcmUpLiBJZiB0aGlzIGlzbid0IHRoZSBjYXNlIHdlIGRvbid0XG5cdFx0XHRcdC8vIHdhbnQgdG8gdG91Y2ggdGhlIHNuYXBzaG90IGF0IGFsbC5cblx0XHRcdFx0cmV0dXJuIGlubGluZVNuYXBzaG90O1xuXHRcdFx0fVxuXHRcdFx0bGluZXNbaV0gPSBsaW5lc1tpXS5zdWJzdHJpbmcoaW5kZW50YXRpb24ubGVuZ3RoKTtcblx0XHR9XG5cdH1cblx0Ly8gTGFzdCBsaW5lIGlzIGEgc3BlY2lhbCBjYXNlIGJlY2F1c2UgaXQgd29uJ3QgaGF2ZSB0aGUgc2FtZSBpbmRlbnQgYXMgb3RoZXJzXG5cdC8vIGJ1dCBtYXkgc3RpbGwgaGF2ZSBiZWVuIGdpdmVuIHNvbWUgaW5kZW50IHRvIGxpbmUgdXAuXG5cdGxpbmVzW2xpbmVzLmxlbmd0aCAtIDFdID0gXCJcIjtcblx0Ly8gUmV0dXJuIGlubGluZSBzbmFwc2hvdCwgbm93IGF0IGluZGVudCAwLlxuXHRpbmxpbmVTbmFwc2hvdCA9IGxpbmVzLmpvaW4oXCJcXG5cIik7XG5cdHJldHVybiBpbmxpbmVTbmFwc2hvdDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc2F2ZVJhd1NuYXBzaG90cyhlbnZpcm9ubWVudCwgc25hcHNob3RzKSB7XG5cdGF3YWl0IFByb21pc2UuYWxsKHNuYXBzaG90cy5tYXAoYXN5bmMgKHNuYXApID0+IHtcblx0XHRpZiAoIXNuYXAucmVhZG9ubHkpIHtcblx0XHRcdGF3YWl0IGVudmlyb25tZW50LnNhdmVTbmFwc2hvdEZpbGUoc25hcC5maWxlLCBzbmFwLnNuYXBzaG90KTtcblx0XHR9XG5cdH0pKTtcbn1cblxuZnVuY3Rpb24gZ2V0RGVmYXVsdEV4cG9ydEZyb21DanMoeCkge1xuXHRyZXR1cm4geCAmJiB4Ll9fZXNNb2R1bGUgJiYgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHgsIFwiZGVmYXVsdFwiKSA/IHhbXCJkZWZhdWx0XCJdIDogeDtcbn1cblxudmFyIG5hdHVyYWxDb21wYXJlJDEgPSB7ZXhwb3J0czoge319O1xuXG52YXIgaGFzUmVxdWlyZWROYXR1cmFsQ29tcGFyZTtcblxuZnVuY3Rpb24gcmVxdWlyZU5hdHVyYWxDb21wYXJlICgpIHtcblx0aWYgKGhhc1JlcXVpcmVkTmF0dXJhbENvbXBhcmUpIHJldHVybiBuYXR1cmFsQ29tcGFyZSQxLmV4cG9ydHM7XG5cdGhhc1JlcXVpcmVkTmF0dXJhbENvbXBhcmUgPSAxO1xuXHQvKlxuXHQgKiBAdmVyc2lvbiAgICAxLjQuMFxuXHQgKiBAZGF0ZSAgICAgICAyMDE1LTEwLTI2XG5cdCAqIEBzdGFiaWxpdHkgIDMgLSBTdGFibGVcblx0ICogQGF1dGhvciAgICAgTGF1cmkgUm9vZGVuIChodHRwczovL2dpdGh1Yi5jb20vbGl0ZWpzL25hdHVyYWwtY29tcGFyZS1saXRlKVxuXHQgKiBAbGljZW5zZSAgICBNSVQgTGljZW5zZVxuXHQgKi9cblxuXG5cdHZhciBuYXR1cmFsQ29tcGFyZSA9IGZ1bmN0aW9uKGEsIGIpIHtcblx0XHR2YXIgaSwgY29kZUFcblx0XHQsIGNvZGVCID0gMVxuXHRcdCwgcG9zQSA9IDBcblx0XHQsIHBvc0IgPSAwXG5cdFx0LCBhbHBoYWJldCA9IFN0cmluZy5hbHBoYWJldDtcblxuXHRcdGZ1bmN0aW9uIGdldENvZGUoc3RyLCBwb3MsIGNvZGUpIHtcblx0XHRcdGlmIChjb2RlKSB7XG5cdFx0XHRcdGZvciAoaSA9IHBvczsgY29kZSA9IGdldENvZGUoc3RyLCBpKSwgY29kZSA8IDc2ICYmIGNvZGUgPiA2NTspICsraTtcblx0XHRcdFx0cmV0dXJuICtzdHIuc2xpY2UocG9zIC0gMSwgaSlcblx0XHRcdH1cblx0XHRcdGNvZGUgPSBhbHBoYWJldCAmJiBhbHBoYWJldC5pbmRleE9mKHN0ci5jaGFyQXQocG9zKSk7XG5cdFx0XHRyZXR1cm4gY29kZSA+IC0xID8gY29kZSArIDc2IDogKChjb2RlID0gc3RyLmNoYXJDb2RlQXQocG9zKSB8fCAwKSwgY29kZSA8IDQ1IHx8IGNvZGUgPiAxMjcpID8gY29kZVxuXHRcdFx0XHQ6IGNvZGUgPCA0NiA/IDY1ICAgICAgICAgICAgICAgLy8gLVxuXHRcdFx0XHQ6IGNvZGUgPCA0OCA/IGNvZGUgLSAxXG5cdFx0XHRcdDogY29kZSA8IDU4ID8gY29kZSArIDE4ICAgICAgICAvLyAwLTlcblx0XHRcdFx0OiBjb2RlIDwgNjUgPyBjb2RlIC0gMTFcblx0XHRcdFx0OiBjb2RlIDwgOTEgPyBjb2RlICsgMTEgICAgICAgIC8vIEEtWlxuXHRcdFx0XHQ6IGNvZGUgPCA5NyA/IGNvZGUgLSAzN1xuXHRcdFx0XHQ6IGNvZGUgPCAxMjMgPyBjb2RlICsgNSAgICAgICAgLy8gYS16XG5cdFx0XHRcdDogY29kZSAtIDYzXG5cdFx0fVxuXG5cblx0XHRpZiAoKGErPVwiXCIpICE9IChiKz1cIlwiKSkgZm9yICg7Y29kZUI7KSB7XG5cdFx0XHRjb2RlQSA9IGdldENvZGUoYSwgcG9zQSsrKTtcblx0XHRcdGNvZGVCID0gZ2V0Q29kZShiLCBwb3NCKyspO1xuXG5cdFx0XHRpZiAoY29kZUEgPCA3NiAmJiBjb2RlQiA8IDc2ICYmIGNvZGVBID4gNjYgJiYgY29kZUIgPiA2Nikge1xuXHRcdFx0XHRjb2RlQSA9IGdldENvZGUoYSwgcG9zQSwgcG9zQSk7XG5cdFx0XHRcdGNvZGVCID0gZ2V0Q29kZShiLCBwb3NCLCBwb3NBID0gaSk7XG5cdFx0XHRcdHBvc0IgPSBpO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoY29kZUEgIT0gY29kZUIpIHJldHVybiAoY29kZUEgPCBjb2RlQikgPyAtMSA6IDFcblx0XHR9XG5cdFx0cmV0dXJuIDBcblx0fTtcblxuXHR0cnkge1xuXHRcdG5hdHVyYWxDb21wYXJlJDEuZXhwb3J0cyA9IG5hdHVyYWxDb21wYXJlO1xuXHR9IGNhdGNoIChlKSB7XG5cdFx0U3RyaW5nLm5hdHVyYWxDb21wYXJlID0gbmF0dXJhbENvbXBhcmU7XG5cdH1cblx0cmV0dXJuIG5hdHVyYWxDb21wYXJlJDEuZXhwb3J0cztcbn1cblxudmFyIG5hdHVyYWxDb21wYXJlRXhwb3J0cyA9IHJlcXVpcmVOYXR1cmFsQ29tcGFyZSgpO1xudmFyIG5hdHVyYWxDb21wYXJlID0gLypAX19QVVJFX18qL2dldERlZmF1bHRFeHBvcnRGcm9tQ2pzKG5hdHVyYWxDb21wYXJlRXhwb3J0cyk7XG5cbmNvbnN0IHNlcmlhbGl6ZSQxID0gKHZhbCwgY29uZmlnLCBpbmRlbnRhdGlvbiwgZGVwdGgsIHJlZnMsIHByaW50ZXIpID0+IHtcblx0Ly8gU2VyaWFsaXplIGEgbm9uLWRlZmF1bHQgbmFtZSwgZXZlbiBpZiBjb25maWcucHJpbnRGdW5jdGlvbk5hbWUgaXMgZmFsc2UuXG5cdGNvbnN0IG5hbWUgPSB2YWwuZ2V0TW9ja05hbWUoKTtcblx0Y29uc3QgbmFtZVN0cmluZyA9IG5hbWUgPT09IFwidmkuZm4oKVwiID8gXCJcIiA6IGAgJHtuYW1lfWA7XG5cdGxldCBjYWxsc1N0cmluZyA9IFwiXCI7XG5cdGlmICh2YWwubW9jay5jYWxscy5sZW5ndGggIT09IDApIHtcblx0XHRjb25zdCBpbmRlbnRhdGlvbk5leHQgPSBpbmRlbnRhdGlvbiArIGNvbmZpZy5pbmRlbnQ7XG5cdFx0Y2FsbHNTdHJpbmcgPSBgIHske2NvbmZpZy5zcGFjaW5nT3V0ZXJ9JHtpbmRlbnRhdGlvbk5leHR9XCJjYWxsc1wiOiAke3ByaW50ZXIodmFsLm1vY2suY2FsbHMsIGNvbmZpZywgaW5kZW50YXRpb25OZXh0LCBkZXB0aCwgcmVmcyl9JHtjb25maWcubWluID8gXCIsIFwiIDogXCIsXCJ9JHtjb25maWcuc3BhY2luZ091dGVyfSR7aW5kZW50YXRpb25OZXh0fVwicmVzdWx0c1wiOiAke3ByaW50ZXIodmFsLm1vY2sucmVzdWx0cywgY29uZmlnLCBpbmRlbnRhdGlvbk5leHQsIGRlcHRoLCByZWZzKX0ke2NvbmZpZy5taW4gPyBcIlwiIDogXCIsXCJ9JHtjb25maWcuc3BhY2luZ091dGVyfSR7aW5kZW50YXRpb259fWA7XG5cdH1cblx0cmV0dXJuIGBbTW9ja0Z1bmN0aW9uJHtuYW1lU3RyaW5nfV0ke2NhbGxzU3RyaW5nfWA7XG59O1xuY29uc3QgdGVzdCA9ICh2YWwpID0+IHZhbCAmJiAhIXZhbC5faXNNb2NrRnVuY3Rpb247XG5jb25zdCBwbHVnaW4gPSB7XG5cdHNlcmlhbGl6ZTogc2VyaWFsaXplJDEsXG5cdHRlc3Rcbn07XG5cbmNvbnN0IHsgRE9NQ29sbGVjdGlvbiwgRE9NRWxlbWVudCwgSW1tdXRhYmxlLCBSZWFjdEVsZW1lbnQsIFJlYWN0VGVzdENvbXBvbmVudCwgQXN5bW1ldHJpY01hdGNoZXIgfSA9IHBsdWdpbnM7XG5sZXQgUExVR0lOUyA9IFtcblx0UmVhY3RUZXN0Q29tcG9uZW50LFxuXHRSZWFjdEVsZW1lbnQsXG5cdERPTUVsZW1lbnQsXG5cdERPTUNvbGxlY3Rpb24sXG5cdEltbXV0YWJsZSxcblx0QXN5bW1ldHJpY01hdGNoZXIsXG5cdHBsdWdpblxuXTtcbmZ1bmN0aW9uIGFkZFNlcmlhbGl6ZXIocGx1Z2luKSB7XG5cdFBMVUdJTlMgPSBbcGx1Z2luXS5jb25jYXQoUExVR0lOUyk7XG59XG5mdW5jdGlvbiBnZXRTZXJpYWxpemVycygpIHtcblx0cmV0dXJuIFBMVUdJTlM7XG59XG5cbi8vIFRPRE86IHJld3JpdGUgYW5kIGNsZWFuIHVwXG5mdW5jdGlvbiB0ZXN0TmFtZVRvS2V5KHRlc3ROYW1lLCBjb3VudCkge1xuXHRyZXR1cm4gYCR7dGVzdE5hbWV9ICR7Y291bnR9YDtcbn1cbmZ1bmN0aW9uIGtleVRvVGVzdE5hbWUoa2V5KSB7XG5cdGlmICghLyBcXGQrJC8udGVzdChrZXkpKSB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKFwiU25hcHNob3Qga2V5cyBtdXN0IGVuZCB3aXRoIGEgbnVtYmVyLlwiKTtcblx0fVxuXHRyZXR1cm4ga2V5LnJlcGxhY2UoLyBcXGQrJC8sIFwiXCIpO1xufVxuZnVuY3Rpb24gZ2V0U25hcHNob3REYXRhKGNvbnRlbnQsIG9wdGlvbnMpIHtcblx0Y29uc3QgdXBkYXRlID0gb3B0aW9ucy51cGRhdGVTbmFwc2hvdDtcblx0Y29uc3QgZGF0YSA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG5cdGxldCBzbmFwc2hvdENvbnRlbnRzID0gXCJcIjtcblx0bGV0IGRpcnR5ID0gZmFsc2U7XG5cdGlmIChjb250ZW50ICE9IG51bGwpIHtcblx0XHR0cnkge1xuXHRcdFx0c25hcHNob3RDb250ZW50cyA9IGNvbnRlbnQ7XG5cdFx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tbmV3LWZ1bmNcblx0XHRcdGNvbnN0IHBvcHVsYXRlID0gbmV3IEZ1bmN0aW9uKFwiZXhwb3J0c1wiLCBzbmFwc2hvdENvbnRlbnRzKTtcblx0XHRcdHBvcHVsYXRlKGRhdGEpO1xuXHRcdH0gY2F0Y2gge31cblx0fVxuXHQvLyBjb25zdCB2YWxpZGF0aW9uUmVzdWx0ID0gdmFsaWRhdGVTbmFwc2hvdFZlcnNpb24oc25hcHNob3RDb250ZW50cylcblx0Y29uc3QgaXNJbnZhbGlkID0gc25hcHNob3RDb250ZW50cztcblx0Ly8gaWYgKHVwZGF0ZSA9PT0gJ25vbmUnICYmIGlzSW52YWxpZClcblx0Ly8gICB0aHJvdyB2YWxpZGF0aW9uUmVzdWx0XG5cdGlmICgodXBkYXRlID09PSBcImFsbFwiIHx8IHVwZGF0ZSA9PT0gXCJuZXdcIikgJiYgaXNJbnZhbGlkKSB7XG5cdFx0ZGlydHkgPSB0cnVlO1xuXHR9XG5cdHJldHVybiB7XG5cdFx0ZGF0YSxcblx0XHRkaXJ0eVxuXHR9O1xufVxuLy8gQWRkIGV4dHJhIGxpbmUgYnJlYWtzIGF0IGJlZ2lubmluZyBhbmQgZW5kIG9mIG11bHRpbGluZSBzbmFwc2hvdFxuLy8gdG8gbWFrZSB0aGUgY29udGVudCBlYXNpZXIgdG8gcmVhZC5cbmZ1bmN0aW9uIGFkZEV4dHJhTGluZUJyZWFrcyhzdHJpbmcpIHtcblx0cmV0dXJuIHN0cmluZy5pbmNsdWRlcyhcIlxcblwiKSA/IGBcXG4ke3N0cmluZ31cXG5gIDogc3RyaW5nO1xufVxuLy8gUmVtb3ZlIGV4dHJhIGxpbmUgYnJlYWtzIGF0IGJlZ2lubmluZyBhbmQgZW5kIG9mIG11bHRpbGluZSBzbmFwc2hvdC5cbi8vIEluc3RlYWQgb2YgdHJpbSwgd2hpY2ggY2FuIHJlbW92ZSBhZGRpdGlvbmFsIG5ld2xpbmVzIG9yIHNwYWNlc1xuLy8gYXQgYmVnaW5uaW5nIG9yIGVuZCBvZiB0aGUgY29udGVudCBmcm9tIGEgY3VzdG9tIHNlcmlhbGl6ZXIuXG5mdW5jdGlvbiByZW1vdmVFeHRyYUxpbmVCcmVha3Moc3RyaW5nKSB7XG5cdHJldHVybiBzdHJpbmcubGVuZ3RoID4gMiAmJiBzdHJpbmdbMF0gPT09IFwiXFxuXCIgJiYgc3RyaW5nLmVuZHNXaXRoKFwiXFxuXCIpID8gc3RyaW5nLnNsaWNlKDEsIC0xKSA6IHN0cmluZztcbn1cbi8vIGV4cG9ydCBjb25zdCByZW1vdmVMaW5lc0JlZm9yZUV4dGVybmFsTWF0Y2hlclRyYXAgPSAoc3RhY2s6IHN0cmluZyk6IHN0cmluZyA9PiB7XG4vLyAgIGNvbnN0IGxpbmVzID0gc3RhY2suc3BsaXQoJ1xcbicpXG4vLyAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGluZXMubGVuZ3RoOyBpICs9IDEpIHtcbi8vICAgICAvLyBJdCdzIGEgZnVuY3Rpb24gbmFtZSBzcGVjaWZpZWQgaW4gYHBhY2thZ2VzL2V4cGVjdC9zcmMvaW5kZXgudHNgXG4vLyAgICAgLy8gZm9yIGV4dGVybmFsIGN1c3RvbSBtYXRjaGVycy5cbi8vICAgICBpZiAobGluZXNbaV0uaW5jbHVkZXMoJ19fRVhURVJOQUxfTUFUQ0hFUl9UUkFQX18nKSlcbi8vICAgICAgIHJldHVybiBsaW5lcy5zbGljZShpICsgMSkuam9pbignXFxuJylcbi8vICAgfVxuLy8gICByZXR1cm4gc3RhY2tcbi8vIH1cbmNvbnN0IGVzY2FwZVJlZ2V4ID0gdHJ1ZTtcbmNvbnN0IHByaW50RnVuY3Rpb25OYW1lID0gZmFsc2U7XG5mdW5jdGlvbiBzZXJpYWxpemUodmFsLCBpbmRlbnQgPSAyLCBmb3JtYXRPdmVycmlkZXMgPSB7fSkge1xuXHRyZXR1cm4gbm9ybWFsaXplTmV3bGluZXMoZm9ybWF0KHZhbCwge1xuXHRcdGVzY2FwZVJlZ2V4LFxuXHRcdGluZGVudCxcblx0XHRwbHVnaW5zOiBnZXRTZXJpYWxpemVycygpLFxuXHRcdHByaW50RnVuY3Rpb25OYW1lLFxuXHRcdC4uLmZvcm1hdE92ZXJyaWRlc1xuXHR9KSk7XG59XG5mdW5jdGlvbiBlc2NhcGVCYWNrdGlja1N0cmluZyhzdHIpIHtcblx0cmV0dXJuIHN0ci5yZXBsYWNlKC9gfFxcXFx8XFwkXFx7L2csIFwiXFxcXCQmXCIpO1xufVxuZnVuY3Rpb24gcHJpbnRCYWNrdGlja1N0cmluZyhzdHIpIHtcblx0cmV0dXJuIGBcXGAke2VzY2FwZUJhY2t0aWNrU3RyaW5nKHN0cil9XFxgYDtcbn1cbmZ1bmN0aW9uIG5vcm1hbGl6ZU5ld2xpbmVzKHN0cmluZykge1xuXHRyZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1xcclxcbnxcXHIvZywgXCJcXG5cIik7XG59XG5hc3luYyBmdW5jdGlvbiBzYXZlU25hcHNob3RGaWxlKGVudmlyb25tZW50LCBzbmFwc2hvdERhdGEsIHNuYXBzaG90UGF0aCkge1xuXHRjb25zdCBzbmFwc2hvdHMgPSBPYmplY3Qua2V5cyhzbmFwc2hvdERhdGEpLnNvcnQobmF0dXJhbENvbXBhcmUpLm1hcCgoa2V5KSA9PiBgZXhwb3J0c1ske3ByaW50QmFja3RpY2tTdHJpbmcoa2V5KX1dID0gJHtwcmludEJhY2t0aWNrU3RyaW5nKG5vcm1hbGl6ZU5ld2xpbmVzKHNuYXBzaG90RGF0YVtrZXldKSl9O2ApO1xuXHRjb25zdCBjb250ZW50ID0gYCR7ZW52aXJvbm1lbnQuZ2V0SGVhZGVyKCl9XFxuXFxuJHtzbmFwc2hvdHMuam9pbihcIlxcblxcblwiKX1cXG5gO1xuXHRjb25zdCBvbGRDb250ZW50ID0gYXdhaXQgZW52aXJvbm1lbnQucmVhZFNuYXBzaG90RmlsZShzbmFwc2hvdFBhdGgpO1xuXHRjb25zdCBza2lwV3JpdGluZyA9IG9sZENvbnRlbnQgIT0gbnVsbCAmJiBvbGRDb250ZW50ID09PSBjb250ZW50O1xuXHRpZiAoc2tpcFdyaXRpbmcpIHtcblx0XHRyZXR1cm47XG5cdH1cblx0YXdhaXQgZW52aXJvbm1lbnQuc2F2ZVNuYXBzaG90RmlsZShzbmFwc2hvdFBhdGgsIGNvbnRlbnQpO1xufVxuZnVuY3Rpb24gZGVlcE1lcmdlQXJyYXkodGFyZ2V0ID0gW10sIHNvdXJjZSA9IFtdKSB7XG5cdGNvbnN0IG1lcmdlZE91dHB1dCA9IEFycmF5LmZyb20odGFyZ2V0KTtcblx0c291cmNlLmZvckVhY2goKHNvdXJjZUVsZW1lbnQsIGluZGV4KSA9PiB7XG5cdFx0Y29uc3QgdGFyZ2V0RWxlbWVudCA9IG1lcmdlZE91dHB1dFtpbmRleF07XG5cdFx0aWYgKEFycmF5LmlzQXJyYXkodGFyZ2V0W2luZGV4XSkpIHtcblx0XHRcdG1lcmdlZE91dHB1dFtpbmRleF0gPSBkZWVwTWVyZ2VBcnJheSh0YXJnZXRbaW5kZXhdLCBzb3VyY2VFbGVtZW50KTtcblx0XHR9IGVsc2UgaWYgKGlzT2JqZWN0KHRhcmdldEVsZW1lbnQpKSB7XG5cdFx0XHRtZXJnZWRPdXRwdXRbaW5kZXhdID0gZGVlcE1lcmdlU25hcHNob3QodGFyZ2V0W2luZGV4XSwgc291cmNlRWxlbWVudCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIFNvdXJjZSBkb2VzIG5vdCBleGlzdCBpbiB0YXJnZXQgb3IgdGFyZ2V0IGlzIHByaW1pdGl2ZSBhbmQgY2Fubm90IGJlIGRlZXAgbWVyZ2VkXG5cdFx0XHRtZXJnZWRPdXRwdXRbaW5kZXhdID0gc291cmNlRWxlbWVudDtcblx0XHR9XG5cdH0pO1xuXHRyZXR1cm4gbWVyZ2VkT3V0cHV0O1xufVxuLyoqXG4qIERlZXAgbWVyZ2UsIGJ1dCBjb25zaWRlcnMgYXN5bW1ldHJpYyBtYXRjaGVycy4gVW5saWtlIGJhc2UgdXRpbCdzIGRlZXAgbWVyZ2UsXG4qIHdpbGwgbWVyZ2UgYW55IG9iamVjdC1saWtlIGluc3RhbmNlLlxuKiBDb21wYXRpYmxlIHdpdGggSmVzdCdzIHNuYXBzaG90IG1hdGNoZXIuIFNob3VsZCBub3QgYmUgdXNlZCBvdXRzaWRlIG9mIHNuYXBzaG90LlxuKlxuKiBAZXhhbXBsZVxuKiBgYGB0c1xuKiB0b01hdGNoU25hcHNob3Qoe1xuKiAgIG5hbWU6IGV4cGVjdC5zdHJpbmdDb250YWluaW5nKCd0ZXh0JylcbiogfSlcbiogYGBgXG4qL1xuZnVuY3Rpb24gZGVlcE1lcmdlU25hcHNob3QodGFyZ2V0LCBzb3VyY2UpIHtcblx0aWYgKGlzT2JqZWN0KHRhcmdldCkgJiYgaXNPYmplY3Qoc291cmNlKSkge1xuXHRcdGNvbnN0IG1lcmdlZE91dHB1dCA9IHsgLi4udGFyZ2V0IH07XG5cdFx0T2JqZWN0LmtleXMoc291cmNlKS5mb3JFYWNoKChrZXkpID0+IHtcblx0XHRcdGlmIChpc09iamVjdChzb3VyY2Vba2V5XSkgJiYgIXNvdXJjZVtrZXldLiQkdHlwZW9mKSB7XG5cdFx0XHRcdGlmICghKGtleSBpbiB0YXJnZXQpKSB7XG5cdFx0XHRcdFx0T2JqZWN0LmFzc2lnbihtZXJnZWRPdXRwdXQsIHsgW2tleV06IHNvdXJjZVtrZXldIH0pO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdG1lcmdlZE91dHB1dFtrZXldID0gZGVlcE1lcmdlU25hcHNob3QodGFyZ2V0W2tleV0sIHNvdXJjZVtrZXldKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmIChBcnJheS5pc0FycmF5KHNvdXJjZVtrZXldKSkge1xuXHRcdFx0XHRtZXJnZWRPdXRwdXRba2V5XSA9IGRlZXBNZXJnZUFycmF5KHRhcmdldFtrZXldLCBzb3VyY2Vba2V5XSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRPYmplY3QuYXNzaWduKG1lcmdlZE91dHB1dCwgeyBba2V5XTogc291cmNlW2tleV0gfSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdFx0cmV0dXJuIG1lcmdlZE91dHB1dDtcblx0fSBlbHNlIGlmIChBcnJheS5pc0FycmF5KHRhcmdldCkgJiYgQXJyYXkuaXNBcnJheShzb3VyY2UpKSB7XG5cdFx0cmV0dXJuIGRlZXBNZXJnZUFycmF5KHRhcmdldCwgc291cmNlKTtcblx0fVxuXHRyZXR1cm4gdGFyZ2V0O1xufVxuY2xhc3MgRGVmYXVsdE1hcCBleHRlbmRzIE1hcCB7XG5cdGNvbnN0cnVjdG9yKGRlZmF1bHRGbiwgZW50cmllcykge1xuXHRcdHN1cGVyKGVudHJpZXMpO1xuXHRcdHRoaXMuZGVmYXVsdEZuID0gZGVmYXVsdEZuO1xuXHR9XG5cdGdldChrZXkpIHtcblx0XHRpZiAoIXRoaXMuaGFzKGtleSkpIHtcblx0XHRcdHRoaXMuc2V0KGtleSwgdGhpcy5kZWZhdWx0Rm4oa2V5KSk7XG5cdFx0fVxuXHRcdHJldHVybiBzdXBlci5nZXQoa2V5KTtcblx0fVxufVxuY2xhc3MgQ291bnRlck1hcCBleHRlbmRzIERlZmF1bHRNYXAge1xuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigoKSA9PiAwKTtcblx0fVxuXHQvLyBjb21wYXQgZm9yIGplc3QtaW1hZ2Utc25hcHNob3QgaHR0cHM6Ly9naXRodWIuY29tL3ZpdGVzdC1kZXYvdml0ZXN0L2lzc3Vlcy83MzIyXG5cdC8vIGB2YWx1ZU9mYCBhbmQgYFNuYXBzaG90LmFkZGVkYCBzZXR0ZXIgYWxsb3dzXG5cdC8vICAgc25hcHNob3RTdGF0ZS5hZGRlZCA9IHNuYXBzaG90U3RhdGUuYWRkZWQgKyAxXG5cdC8vIHRvIGZ1bmN0aW9uIGFzXG5cdC8vICAgc25hcHNob3RTdGF0ZS5hZGRlZC50b3RhbF8gPSBzbmFwc2hvdFN0YXRlLmFkZGVkLnRvdGFsKCkgKyAxXG5cdF90b3RhbDtcblx0dmFsdWVPZigpIHtcblx0XHRyZXR1cm4gdGhpcy5fdG90YWwgPSB0aGlzLnRvdGFsKCk7XG5cdH1cblx0aW5jcmVtZW50KGtleSkge1xuXHRcdGlmICh0eXBlb2YgdGhpcy5fdG90YWwgIT09IFwidW5kZWZpbmVkXCIpIHtcblx0XHRcdHRoaXMuX3RvdGFsKys7XG5cdFx0fVxuXHRcdHRoaXMuc2V0KGtleSwgdGhpcy5nZXQoa2V5KSArIDEpO1xuXHR9XG5cdHRvdGFsKCkge1xuXHRcdGlmICh0eXBlb2YgdGhpcy5fdG90YWwgIT09IFwidW5kZWZpbmVkXCIpIHtcblx0XHRcdHJldHVybiB0aGlzLl90b3RhbDtcblx0XHR9XG5cdFx0bGV0IHRvdGFsID0gMDtcblx0XHRmb3IgKGNvbnN0IHggb2YgdGhpcy52YWx1ZXMoKSkge1xuXHRcdFx0dG90YWwgKz0geDtcblx0XHR9XG5cdFx0cmV0dXJuIHRvdGFsO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGlzU2FtZVN0YWNrUG9zaXRpb24oeCwgeSkge1xuXHRyZXR1cm4geC5maWxlID09PSB5LmZpbGUgJiYgeC5jb2x1bW4gPT09IHkuY29sdW1uICYmIHgubGluZSA9PT0geS5saW5lO1xufVxuY2xhc3MgU25hcHNob3RTdGF0ZSB7XG5cdF9jb3VudGVycyA9IG5ldyBDb3VudGVyTWFwKCk7XG5cdF9kaXJ0eTtcblx0X3VwZGF0ZVNuYXBzaG90O1xuXHRfc25hcHNob3REYXRhO1xuXHRfaW5pdGlhbERhdGE7XG5cdF9pbmxpbmVTbmFwc2hvdHM7XG5cdF9pbmxpbmVTbmFwc2hvdFN0YWNrcztcblx0X3Rlc3RJZFRvS2V5cyA9IG5ldyBEZWZhdWx0TWFwKCgpID0+IFtdKTtcblx0X3Jhd1NuYXBzaG90cztcblx0X3VuY2hlY2tlZEtleXM7XG5cdF9zbmFwc2hvdEZvcm1hdDtcblx0X2Vudmlyb25tZW50O1xuXHRfZmlsZUV4aXN0cztcblx0ZXhwYW5kO1xuXHQvLyBnZXR0ZXIvc2V0dGVyIGZvciBqZXN0LWltYWdlLXNuYXBzaG90IGNvbXBhdFxuXHQvLyBodHRwczovL2dpdGh1Yi5jb20vdml0ZXN0LWRldi92aXRlc3QvaXNzdWVzLzczMjJcblx0X2FkZGVkID0gbmV3IENvdW50ZXJNYXAoKTtcblx0X21hdGNoZWQgPSBuZXcgQ291bnRlck1hcCgpO1xuXHRfdW5tYXRjaGVkID0gbmV3IENvdW50ZXJNYXAoKTtcblx0X3VwZGF0ZWQgPSBuZXcgQ291bnRlck1hcCgpO1xuXHRnZXQgYWRkZWQoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2FkZGVkO1xuXHR9XG5cdHNldCBhZGRlZCh2YWx1ZSkge1xuXHRcdHRoaXMuX2FkZGVkLl90b3RhbCA9IHZhbHVlO1xuXHR9XG5cdGdldCBtYXRjaGVkKCkge1xuXHRcdHJldHVybiB0aGlzLl9tYXRjaGVkO1xuXHR9XG5cdHNldCBtYXRjaGVkKHZhbHVlKSB7XG5cdFx0dGhpcy5fbWF0Y2hlZC5fdG90YWwgPSB2YWx1ZTtcblx0fVxuXHRnZXQgdW5tYXRjaGVkKCkge1xuXHRcdHJldHVybiB0aGlzLl91bm1hdGNoZWQ7XG5cdH1cblx0c2V0IHVubWF0Y2hlZCh2YWx1ZSkge1xuXHRcdHRoaXMuX3VubWF0Y2hlZC5fdG90YWwgPSB2YWx1ZTtcblx0fVxuXHRnZXQgdXBkYXRlZCgpIHtcblx0XHRyZXR1cm4gdGhpcy5fdXBkYXRlZDtcblx0fVxuXHRzZXQgdXBkYXRlZCh2YWx1ZSkge1xuXHRcdHRoaXMuX3VwZGF0ZWQuX3RvdGFsID0gdmFsdWU7XG5cdH1cblx0Y29uc3RydWN0b3IodGVzdEZpbGVQYXRoLCBzbmFwc2hvdFBhdGgsIHNuYXBzaG90Q29udGVudCwgb3B0aW9ucykge1xuXHRcdHRoaXMudGVzdEZpbGVQYXRoID0gdGVzdEZpbGVQYXRoO1xuXHRcdHRoaXMuc25hcHNob3RQYXRoID0gc25hcHNob3RQYXRoO1xuXHRcdGNvbnN0IHsgZGF0YSwgZGlydHkgfSA9IGdldFNuYXBzaG90RGF0YShzbmFwc2hvdENvbnRlbnQsIG9wdGlvbnMpO1xuXHRcdHRoaXMuX2ZpbGVFeGlzdHMgPSBzbmFwc2hvdENvbnRlbnQgIT0gbnVsbDtcblx0XHR0aGlzLl9pbml0aWFsRGF0YSA9IHsgLi4uZGF0YSB9O1xuXHRcdHRoaXMuX3NuYXBzaG90RGF0YSA9IHsgLi4uZGF0YSB9O1xuXHRcdHRoaXMuX2RpcnR5ID0gZGlydHk7XG5cdFx0dGhpcy5faW5saW5lU25hcHNob3RzID0gW107XG5cdFx0dGhpcy5faW5saW5lU25hcHNob3RTdGFja3MgPSBbXTtcblx0XHR0aGlzLl9yYXdTbmFwc2hvdHMgPSBbXTtcblx0XHR0aGlzLl91bmNoZWNrZWRLZXlzID0gbmV3IFNldChPYmplY3Qua2V5cyh0aGlzLl9zbmFwc2hvdERhdGEpKTtcblx0XHR0aGlzLmV4cGFuZCA9IG9wdGlvbnMuZXhwYW5kIHx8IGZhbHNlO1xuXHRcdHRoaXMuX3VwZGF0ZVNuYXBzaG90ID0gb3B0aW9ucy51cGRhdGVTbmFwc2hvdDtcblx0XHR0aGlzLl9zbmFwc2hvdEZvcm1hdCA9IHtcblx0XHRcdHByaW50QmFzaWNQcm90b3R5cGU6IGZhbHNlLFxuXHRcdFx0ZXNjYXBlU3RyaW5nOiBmYWxzZSxcblx0XHRcdC4uLm9wdGlvbnMuc25hcHNob3RGb3JtYXRcblx0XHR9O1xuXHRcdHRoaXMuX2Vudmlyb25tZW50ID0gb3B0aW9ucy5zbmFwc2hvdEVudmlyb25tZW50O1xuXHR9XG5cdHN0YXRpYyBhc3luYyBjcmVhdGUodGVzdEZpbGVQYXRoLCBvcHRpb25zKSB7XG5cdFx0Y29uc3Qgc25hcHNob3RQYXRoID0gYXdhaXQgb3B0aW9ucy5zbmFwc2hvdEVudmlyb25tZW50LnJlc29sdmVQYXRoKHRlc3RGaWxlUGF0aCk7XG5cdFx0Y29uc3QgY29udGVudCA9IGF3YWl0IG9wdGlvbnMuc25hcHNob3RFbnZpcm9ubWVudC5yZWFkU25hcHNob3RGaWxlKHNuYXBzaG90UGF0aCk7XG5cdFx0cmV0dXJuIG5ldyBTbmFwc2hvdFN0YXRlKHRlc3RGaWxlUGF0aCwgc25hcHNob3RQYXRoLCBjb250ZW50LCBvcHRpb25zKTtcblx0fVxuXHRnZXQgZW52aXJvbm1lbnQoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2Vudmlyb25tZW50O1xuXHR9XG5cdG1hcmtTbmFwc2hvdHNBc0NoZWNrZWRGb3JUZXN0KHRlc3ROYW1lKSB7XG5cdFx0dGhpcy5fdW5jaGVja2VkS2V5cy5mb3JFYWNoKCh1bmNoZWNrZWRLZXkpID0+IHtcblx0XHRcdC8vIHNraXAgc25hcHNob3RzIHdpdGggZm9sbG93aW5nIGtleXNcblx0XHRcdC8vICAgdGVzdE5hbWUgblxuXHRcdFx0Ly8gICB0ZXN0TmFtZSA+IHh4eCBuICh0aGlzIGlzIGZvciB0b01hdGNoU25hcHNob3QoXCJ4eHhcIikgQVBJKVxuXHRcdFx0aWYgKC8gXFxkKyR8ID4gLy50ZXN0KHVuY2hlY2tlZEtleS5zbGljZSh0ZXN0TmFtZS5sZW5ndGgpKSkge1xuXHRcdFx0XHR0aGlzLl91bmNoZWNrZWRLZXlzLmRlbGV0ZSh1bmNoZWNrZWRLZXkpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cdGNsZWFyVGVzdCh0ZXN0SWQpIHtcblx0XHQvLyBjbGVhciBpbmxpbmVcblx0XHR0aGlzLl9pbmxpbmVTbmFwc2hvdHMgPSB0aGlzLl9pbmxpbmVTbmFwc2hvdHMuZmlsdGVyKChzKSA9PiBzLnRlc3RJZCAhPT0gdGVzdElkKTtcblx0XHR0aGlzLl9pbmxpbmVTbmFwc2hvdFN0YWNrcyA9IHRoaXMuX2lubGluZVNuYXBzaG90U3RhY2tzLmZpbHRlcigocykgPT4gcy50ZXN0SWQgIT09IHRlc3RJZCk7XG5cdFx0Ly8gY2xlYXIgZmlsZVxuXHRcdGZvciAoY29uc3Qga2V5IG9mIHRoaXMuX3Rlc3RJZFRvS2V5cy5nZXQodGVzdElkKSkge1xuXHRcdFx0Y29uc3QgbmFtZSA9IGtleVRvVGVzdE5hbWUoa2V5KTtcblx0XHRcdGNvbnN0IGNvdW50ID0gdGhpcy5fY291bnRlcnMuZ2V0KG5hbWUpO1xuXHRcdFx0aWYgKGNvdW50ID4gMCkge1xuXHRcdFx0XHRpZiAoa2V5IGluIHRoaXMuX3NuYXBzaG90RGF0YSB8fCBrZXkgaW4gdGhpcy5faW5pdGlhbERhdGEpIHtcblx0XHRcdFx0XHR0aGlzLl9zbmFwc2hvdERhdGFba2V5XSA9IHRoaXMuX2luaXRpYWxEYXRhW2tleV07XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy5fY291bnRlcnMuc2V0KG5hbWUsIGNvdW50IC0gMSk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHRoaXMuX3Rlc3RJZFRvS2V5cy5kZWxldGUodGVzdElkKTtcblx0XHQvLyBjbGVhciBzdGF0c1xuXHRcdHRoaXMuYWRkZWQuZGVsZXRlKHRlc3RJZCk7XG5cdFx0dGhpcy51cGRhdGVkLmRlbGV0ZSh0ZXN0SWQpO1xuXHRcdHRoaXMubWF0Y2hlZC5kZWxldGUodGVzdElkKTtcblx0XHR0aGlzLnVubWF0Y2hlZC5kZWxldGUodGVzdElkKTtcblx0fVxuXHRfaW5mZXJJbmxpbmVTbmFwc2hvdFN0YWNrKHN0YWNrcykge1xuXHRcdC8vIGlmIGNhbGxlZCBpbnNpZGUgcmVzb2x2ZXMvcmVqZWN0cywgc3RhY2t0cmFjZSBpcyBkaWZmZXJlbnRcblx0XHRjb25zdCBwcm9taXNlSW5kZXggPSBzdGFja3MuZmluZEluZGV4KChpKSA9PiBpLm1ldGhvZC5tYXRjaCgvX19WSVRFU1RfKFJFU09MVkVTfFJFSkVDVFMpX18vKSk7XG5cdFx0aWYgKHByb21pc2VJbmRleCAhPT0gLTEpIHtcblx0XHRcdHJldHVybiBzdGFja3NbcHJvbWlzZUluZGV4ICsgM107XG5cdFx0fVxuXHRcdC8vIGlubGluZSBzbmFwc2hvdCBmdW5jdGlvbiBjYW4gYmUgbmFtZWQgX19JTkxJTkVfU05BUFNIT1RfT0ZGU0VUXzxuPl9fXG5cdFx0Ly8gdG8gc3BlY2lmeSBhIGN1c3RvbSBzdGFjayBvZmZzZXRcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHN0YWNrcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0Y29uc3QgbWF0Y2ggPSBzdGFja3NbaV0ubWV0aG9kLm1hdGNoKC9fX0lOTElORV9TTkFQU0hPVF9PRkZTRVRfKFxcZCspX18vKTtcblx0XHRcdGlmIChtYXRjaCkge1xuXHRcdFx0XHRyZXR1cm4gc3RhY2tzW2kgKyBOdW1iZXIobWF0Y2hbMV0pXSA/PyBudWxsO1xuXHRcdFx0fVxuXHRcdH1cblx0XHQvLyBpbmxpbmUgc25hcHNob3QgZnVuY3Rpb24gaXMgY2FsbGVkIF9fSU5MSU5FX1NOQVBTSE9UX19cblx0XHQvLyBpbiBpbnRlZ3JhdGlvbnMvc25hcHNob3QvY2hhaS50c1xuXHRcdGNvbnN0IHN0YWNrSW5kZXggPSBzdGFja3MuZmluZEluZGV4KChpKSA9PiBpLm1ldGhvZC5pbmNsdWRlcyhcIl9fSU5MSU5FX1NOQVBTSE9UX19cIikpO1xuXHRcdHJldHVybiBzdGFja0luZGV4ICE9PSAtMSA/IHN0YWNrc1tzdGFja0luZGV4ICsgMl0gOiBudWxsO1xuXHR9XG5cdF9hZGRTbmFwc2hvdChrZXksIHJlY2VpdmVkU2VyaWFsaXplZCwgb3B0aW9ucykge1xuXHRcdHRoaXMuX2RpcnR5ID0gdHJ1ZTtcblx0XHRpZiAob3B0aW9ucy5zdGFjaykge1xuXHRcdFx0dGhpcy5faW5saW5lU25hcHNob3RzLnB1c2goe1xuXHRcdFx0XHRzbmFwc2hvdDogcmVjZWl2ZWRTZXJpYWxpemVkLFxuXHRcdFx0XHR0ZXN0SWQ6IG9wdGlvbnMudGVzdElkLFxuXHRcdFx0XHQuLi5vcHRpb25zLnN0YWNrXG5cdFx0XHR9KTtcblx0XHR9IGVsc2UgaWYgKG9wdGlvbnMucmF3U25hcHNob3QpIHtcblx0XHRcdHRoaXMuX3Jhd1NuYXBzaG90cy5wdXNoKHtcblx0XHRcdFx0Li4ub3B0aW9ucy5yYXdTbmFwc2hvdCxcblx0XHRcdFx0c25hcHNob3Q6IHJlY2VpdmVkU2VyaWFsaXplZFxuXHRcdFx0fSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuX3NuYXBzaG90RGF0YVtrZXldID0gcmVjZWl2ZWRTZXJpYWxpemVkO1xuXHRcdH1cblx0fVxuXHRhc3luYyBzYXZlKCkge1xuXHRcdGNvbnN0IGhhc0V4dGVybmFsU25hcHNob3RzID0gT2JqZWN0LmtleXModGhpcy5fc25hcHNob3REYXRhKS5sZW5ndGg7XG5cdFx0Y29uc3QgaGFzSW5saW5lU25hcHNob3RzID0gdGhpcy5faW5saW5lU25hcHNob3RzLmxlbmd0aDtcblx0XHRjb25zdCBoYXNSYXdTbmFwc2hvdHMgPSB0aGlzLl9yYXdTbmFwc2hvdHMubGVuZ3RoO1xuXHRcdGNvbnN0IGlzRW1wdHkgPSAhaGFzRXh0ZXJuYWxTbmFwc2hvdHMgJiYgIWhhc0lubGluZVNuYXBzaG90cyAmJiAhaGFzUmF3U25hcHNob3RzO1xuXHRcdGNvbnN0IHN0YXR1cyA9IHtcblx0XHRcdGRlbGV0ZWQ6IGZhbHNlLFxuXHRcdFx0c2F2ZWQ6IGZhbHNlXG5cdFx0fTtcblx0XHRpZiAoKHRoaXMuX2RpcnR5IHx8IHRoaXMuX3VuY2hlY2tlZEtleXMuc2l6ZSkgJiYgIWlzRW1wdHkpIHtcblx0XHRcdGlmIChoYXNFeHRlcm5hbFNuYXBzaG90cykge1xuXHRcdFx0XHRhd2FpdCBzYXZlU25hcHNob3RGaWxlKHRoaXMuX2Vudmlyb25tZW50LCB0aGlzLl9zbmFwc2hvdERhdGEsIHRoaXMuc25hcHNob3RQYXRoKTtcblx0XHRcdFx0dGhpcy5fZmlsZUV4aXN0cyA9IHRydWU7XG5cdFx0XHR9XG5cdFx0XHRpZiAoaGFzSW5saW5lU25hcHNob3RzKSB7XG5cdFx0XHRcdGF3YWl0IHNhdmVJbmxpbmVTbmFwc2hvdHModGhpcy5fZW52aXJvbm1lbnQsIHRoaXMuX2lubGluZVNuYXBzaG90cyk7XG5cdFx0XHR9XG5cdFx0XHRpZiAoaGFzUmF3U25hcHNob3RzKSB7XG5cdFx0XHRcdGF3YWl0IHNhdmVSYXdTbmFwc2hvdHModGhpcy5fZW52aXJvbm1lbnQsIHRoaXMuX3Jhd1NuYXBzaG90cyk7XG5cdFx0XHR9XG5cdFx0XHRzdGF0dXMuc2F2ZWQgPSB0cnVlO1xuXHRcdH0gZWxzZSBpZiAoIWhhc0V4dGVybmFsU25hcHNob3RzICYmIHRoaXMuX2ZpbGVFeGlzdHMpIHtcblx0XHRcdGlmICh0aGlzLl91cGRhdGVTbmFwc2hvdCA9PT0gXCJhbGxcIikge1xuXHRcdFx0XHRhd2FpdCB0aGlzLl9lbnZpcm9ubWVudC5yZW1vdmVTbmFwc2hvdEZpbGUodGhpcy5zbmFwc2hvdFBhdGgpO1xuXHRcdFx0XHR0aGlzLl9maWxlRXhpc3RzID0gZmFsc2U7XG5cdFx0XHR9XG5cdFx0XHRzdGF0dXMuZGVsZXRlZCA9IHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiBzdGF0dXM7XG5cdH1cblx0Z2V0VW5jaGVja2VkQ291bnQoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX3VuY2hlY2tlZEtleXMuc2l6ZSB8fCAwO1xuXHR9XG5cdGdldFVuY2hlY2tlZEtleXMoKSB7XG5cdFx0cmV0dXJuIEFycmF5LmZyb20odGhpcy5fdW5jaGVja2VkS2V5cyk7XG5cdH1cblx0cmVtb3ZlVW5jaGVja2VkS2V5cygpIHtcblx0XHRpZiAodGhpcy5fdXBkYXRlU25hcHNob3QgPT09IFwiYWxsXCIgJiYgdGhpcy5fdW5jaGVja2VkS2V5cy5zaXplKSB7XG5cdFx0XHR0aGlzLl9kaXJ0eSA9IHRydWU7XG5cdFx0XHR0aGlzLl91bmNoZWNrZWRLZXlzLmZvckVhY2goKGtleSkgPT4gZGVsZXRlIHRoaXMuX3NuYXBzaG90RGF0YVtrZXldKTtcblx0XHRcdHRoaXMuX3VuY2hlY2tlZEtleXMuY2xlYXIoKTtcblx0XHR9XG5cdH1cblx0bWF0Y2goeyB0ZXN0SWQsIHRlc3ROYW1lLCByZWNlaXZlZCwga2V5LCBpbmxpbmVTbmFwc2hvdCwgaXNJbmxpbmUsIGVycm9yLCByYXdTbmFwc2hvdCB9KSB7XG5cdFx0Ly8gdGhpcyBhbHNvIGluY3JlbWVudHMgY291bnRlciBmb3IgaW5saW5lIHNuYXBzaG90cy4gbWF5YmUgd2Ugc2hvdWxkbid0P1xuXHRcdHRoaXMuX2NvdW50ZXJzLmluY3JlbWVudCh0ZXN0TmFtZSk7XG5cdFx0Y29uc3QgY291bnQgPSB0aGlzLl9jb3VudGVycy5nZXQodGVzdE5hbWUpO1xuXHRcdGlmICgha2V5KSB7XG5cdFx0XHRrZXkgPSB0ZXN0TmFtZVRvS2V5KHRlc3ROYW1lLCBjb3VudCk7XG5cdFx0fVxuXHRcdHRoaXMuX3Rlc3RJZFRvS2V5cy5nZXQodGVzdElkKS5wdXNoKGtleSk7XG5cdFx0Ly8gRG8gbm90IG1hcmsgdGhlIHNuYXBzaG90IGFzIFwiY2hlY2tlZFwiIGlmIHRoZSBzbmFwc2hvdCBpcyBpbmxpbmUgYW5kXG5cdFx0Ly8gdGhlcmUncyBhbiBleHRlcm5hbCBzbmFwc2hvdC4gVGhpcyB3YXkgdGhlIGV4dGVybmFsIHNuYXBzaG90IGNhbiBiZVxuXHRcdC8vIHJlbW92ZWQgd2l0aCBgLS11cGRhdGVTbmFwc2hvdGAuXG5cdFx0aWYgKCEoaXNJbmxpbmUgJiYgdGhpcy5fc25hcHNob3REYXRhW2tleV0gIT09IHVuZGVmaW5lZCkpIHtcblx0XHRcdHRoaXMuX3VuY2hlY2tlZEtleXMuZGVsZXRlKGtleSk7XG5cdFx0fVxuXHRcdGxldCByZWNlaXZlZFNlcmlhbGl6ZWQgPSByYXdTbmFwc2hvdCAmJiB0eXBlb2YgcmVjZWl2ZWQgPT09IFwic3RyaW5nXCIgPyByZWNlaXZlZCA6IHNlcmlhbGl6ZShyZWNlaXZlZCwgdW5kZWZpbmVkLCB0aGlzLl9zbmFwc2hvdEZvcm1hdCk7XG5cdFx0aWYgKCFyYXdTbmFwc2hvdCkge1xuXHRcdFx0cmVjZWl2ZWRTZXJpYWxpemVkID0gYWRkRXh0cmFMaW5lQnJlYWtzKHJlY2VpdmVkU2VyaWFsaXplZCk7XG5cdFx0fVxuXHRcdGlmIChyYXdTbmFwc2hvdCkge1xuXHRcdFx0Ly8gbm9ybWFsaXplIEVPTCB3aGVuIHNuYXBzaG90IGNvbnRhaW5zIENSTEYgYnV0IHJlY2VpdmVkIGlzIExGXG5cdFx0XHRpZiAocmF3U25hcHNob3QuY29udGVudCAmJiByYXdTbmFwc2hvdC5jb250ZW50Lm1hdGNoKC9cXHJcXG4vKSAmJiAhcmVjZWl2ZWRTZXJpYWxpemVkLm1hdGNoKC9cXHJcXG4vKSkge1xuXHRcdFx0XHRyYXdTbmFwc2hvdC5jb250ZW50ID0gbm9ybWFsaXplTmV3bGluZXMocmF3U25hcHNob3QuY29udGVudCk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGNvbnN0IGV4cGVjdGVkID0gaXNJbmxpbmUgPyBpbmxpbmVTbmFwc2hvdCA6IHJhd1NuYXBzaG90ID8gcmF3U25hcHNob3QuY29udGVudCA6IHRoaXMuX3NuYXBzaG90RGF0YVtrZXldO1xuXHRcdGNvbnN0IGV4cGVjdGVkVHJpbW1lZCA9IHJhd1NuYXBzaG90ID8gZXhwZWN0ZWQgOiBleHBlY3RlZD8udHJpbSgpO1xuXHRcdGNvbnN0IHBhc3MgPSBleHBlY3RlZFRyaW1tZWQgPT09IChyYXdTbmFwc2hvdCA/IHJlY2VpdmVkU2VyaWFsaXplZCA6IHJlY2VpdmVkU2VyaWFsaXplZC50cmltKCkpO1xuXHRcdGNvbnN0IGhhc1NuYXBzaG90ID0gZXhwZWN0ZWQgIT09IHVuZGVmaW5lZDtcblx0XHRjb25zdCBzbmFwc2hvdElzUGVyc2lzdGVkID0gaXNJbmxpbmUgfHwgdGhpcy5fZmlsZUV4aXN0cyB8fCByYXdTbmFwc2hvdCAmJiByYXdTbmFwc2hvdC5jb250ZW50ICE9IG51bGw7XG5cdFx0aWYgKHBhc3MgJiYgIWlzSW5saW5lICYmICFyYXdTbmFwc2hvdCkge1xuXHRcdFx0Ly8gRXhlY3V0aW5nIGEgc25hcHNob3QgZmlsZSBhcyBKYXZhU2NyaXB0IGFuZCB3cml0aW5nIHRoZSBzdHJpbmdzIGJhY2tcblx0XHRcdC8vIHdoZW4gb3RoZXIgc25hcHNob3RzIGhhdmUgY2hhbmdlZCBsb3NlcyB0aGUgcHJvcGVyIGVzY2FwaW5nIGZvciBzb21lXG5cdFx0XHQvLyBjaGFyYWN0ZXJzLiBTaW5jZSB3ZSBjaGVjayBldmVyeSBzbmFwc2hvdCBpbiBldmVyeSB0ZXN0LCB1c2UgdGhlIG5ld2x5XG5cdFx0XHQvLyBnZW5lcmF0ZWQgZm9ybWF0dGVkIHN0cmluZy5cblx0XHRcdC8vIE5vdGUgdGhhdCB0aGlzIGlzIG9ubHkgcmVsZXZhbnQgd2hlbiBhIHNuYXBzaG90IGlzIGFkZGVkIGFuZCB0aGUgZGlydHlcblx0XHRcdC8vIGZsYWcgaXMgc2V0LlxuXHRcdFx0dGhpcy5fc25hcHNob3REYXRhW2tleV0gPSByZWNlaXZlZFNlcmlhbGl6ZWQ7XG5cdFx0fVxuXHRcdC8vIGZpbmQgY2FsbCBzaXRlIG9mIHRvTWF0Y2hJbmxpbmVTbmFwc2hvdFxuXHRcdGxldCBzdGFjaztcblx0XHRpZiAoaXNJbmxpbmUpIHtcblx0XHRcdGNvbnN0IHN0YWNrcyA9IHBhcnNlRXJyb3JTdGFja3RyYWNlKGVycm9yIHx8IG5ldyBFcnJvcihcInNuYXBzaG90XCIpLCB7IGlnbm9yZVN0YWNrRW50cmllczogW10gfSk7XG5cdFx0XHRjb25zdCBfc3RhY2sgPSB0aGlzLl9pbmZlcklubGluZVNuYXBzaG90U3RhY2soc3RhY2tzKTtcblx0XHRcdGlmICghX3N0YWNrKSB7XG5cdFx0XHRcdHRocm93IG5ldyBFcnJvcihgQHZpdGVzdC9zbmFwc2hvdDogQ291bGRuJ3QgaW5mZXIgc3RhY2sgZnJhbWUgZm9yIGlubGluZSBzbmFwc2hvdC5cXG4ke0pTT04uc3RyaW5naWZ5KHN0YWNrcyl9YCk7XG5cdFx0XHR9XG5cdFx0XHRzdGFjayA9IHRoaXMuZW52aXJvbm1lbnQucHJvY2Vzc1N0YWNrVHJhY2U/Lihfc3RhY2spIHx8IF9zdGFjaztcblx0XHRcdC8vIHJlbW92aW5nIDEgY29sdW1uLCBiZWNhdXNlIHNvdXJjZSBtYXAgcG9pbnRzIHRvIHRoZSB3cm9uZ1xuXHRcdFx0Ly8gbG9jYXRpb24gZm9yIGpzIGZpbGVzLCBidXQgYGNvbHVtbi0xYCBwb2ludHMgdG8gdGhlIHNhbWUgaW4gYm90aCBqcy90c1xuXHRcdFx0Ly8gaHR0cHM6Ly9naXRodWIuY29tL3ZpdGVqcy92aXRlL2lzc3Vlcy84NjU3XG5cdFx0XHRzdGFjay5jb2x1bW4tLTtcblx0XHRcdC8vIHJlamVjdCBtdWx0aXBsZSBpbmxpbmUgc25hcHNob3RzIGF0IHRoZSBzYW1lIGxvY2F0aW9uIGlmIHNuYXBzaG90IGlzIGRpZmZlcmVudFxuXHRcdFx0Y29uc3Qgc25hcHNob3RzV2l0aFNhbWVTdGFjayA9IHRoaXMuX2lubGluZVNuYXBzaG90U3RhY2tzLmZpbHRlcigocykgPT4gaXNTYW1lU3RhY2tQb3NpdGlvbihzLCBzdGFjaykpO1xuXHRcdFx0aWYgKHNuYXBzaG90c1dpdGhTYW1lU3RhY2subGVuZ3RoID4gMCkge1xuXHRcdFx0XHQvLyBlbnN1cmUgb25seSBvbmUgc25hcHNob3Qgd2lsbCBiZSB3cml0dGVuIGF0IHRoZSBzYW1lIGxvY2F0aW9uXG5cdFx0XHRcdHRoaXMuX2lubGluZVNuYXBzaG90cyA9IHRoaXMuX2lubGluZVNuYXBzaG90cy5maWx0ZXIoKHMpID0+ICFpc1NhbWVTdGFja1Bvc2l0aW9uKHMsIHN0YWNrKSk7XG5cdFx0XHRcdGNvbnN0IGRpZmZlcmVudFNuYXBzaG90ID0gc25hcHNob3RzV2l0aFNhbWVTdGFjay5maW5kKChzKSA9PiBzLnNuYXBzaG90ICE9PSByZWNlaXZlZFNlcmlhbGl6ZWQpO1xuXHRcdFx0XHRpZiAoZGlmZmVyZW50U25hcHNob3QpIHtcblx0XHRcdFx0XHR0aHJvdyBPYmplY3QuYXNzaWduKG5ldyBFcnJvcihcInRvTWF0Y2hJbmxpbmVTbmFwc2hvdCB3aXRoIGRpZmZlcmVudCBzbmFwc2hvdHMgY2Fubm90IGJlIGNhbGxlZCBhdCB0aGUgc2FtZSBsb2NhdGlvblwiKSwge1xuXHRcdFx0XHRcdFx0YWN0dWFsOiByZWNlaXZlZFNlcmlhbGl6ZWQsXG5cdFx0XHRcdFx0XHRleHBlY3RlZDogZGlmZmVyZW50U25hcHNob3Quc25hcHNob3Rcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0dGhpcy5faW5saW5lU25hcHNob3RTdGFja3MucHVzaCh7XG5cdFx0XHRcdC4uLnN0YWNrLFxuXHRcdFx0XHR0ZXN0SWQsXG5cdFx0XHRcdHNuYXBzaG90OiByZWNlaXZlZFNlcmlhbGl6ZWRcblx0XHRcdH0pO1xuXHRcdH1cblx0XHQvLyBUaGVzZSBhcmUgdGhlIGNvbmRpdGlvbnMgb24gd2hlbiB0byB3cml0ZSBzbmFwc2hvdHM6XG5cdFx0Ly8gICogVGhlcmUncyBubyBzbmFwc2hvdCBmaWxlIGluIGEgbm9uLUNJIGVudmlyb25tZW50LlxuXHRcdC8vICAqIFRoZXJlIGlzIGEgc25hcHNob3QgZmlsZSBhbmQgd2UgZGVjaWRlZCB0byB1cGRhdGUgdGhlIHNuYXBzaG90LlxuXHRcdC8vICAqIFRoZXJlIGlzIGEgc25hcHNob3QgZmlsZSwgYnV0IGl0IGRvZXNuJ3QgaGF2ZSB0aGlzIHNuYXBzaG90LlxuXHRcdC8vIFRoZXNlIGFyZSB0aGUgY29uZGl0aW9ucyBvbiB3aGVuIG5vdCB0byB3cml0ZSBzbmFwc2hvdHM6XG5cdFx0Ly8gICogVGhlIHVwZGF0ZSBmbGFnIGlzIHNldCB0byAnbm9uZScuXG5cdFx0Ly8gICogVGhlcmUncyBubyBzbmFwc2hvdCBmaWxlIG9yIGEgZmlsZSB3aXRob3V0IHRoaXMgc25hcHNob3Qgb24gYSBDSSBlbnZpcm9ubWVudC5cblx0XHRpZiAoaGFzU25hcHNob3QgJiYgdGhpcy5fdXBkYXRlU25hcHNob3QgPT09IFwiYWxsXCIgfHwgKCFoYXNTbmFwc2hvdCB8fCAhc25hcHNob3RJc1BlcnNpc3RlZCkgJiYgKHRoaXMuX3VwZGF0ZVNuYXBzaG90ID09PSBcIm5ld1wiIHx8IHRoaXMuX3VwZGF0ZVNuYXBzaG90ID09PSBcImFsbFwiKSkge1xuXHRcdFx0aWYgKHRoaXMuX3VwZGF0ZVNuYXBzaG90ID09PSBcImFsbFwiKSB7XG5cdFx0XHRcdGlmICghcGFzcykge1xuXHRcdFx0XHRcdGlmIChoYXNTbmFwc2hvdCkge1xuXHRcdFx0XHRcdFx0dGhpcy51cGRhdGVkLmluY3JlbWVudCh0ZXN0SWQpO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHR0aGlzLmFkZGVkLmluY3JlbWVudCh0ZXN0SWQpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHR0aGlzLl9hZGRTbmFwc2hvdChrZXksIHJlY2VpdmVkU2VyaWFsaXplZCwge1xuXHRcdFx0XHRcdFx0c3RhY2ssXG5cdFx0XHRcdFx0XHR0ZXN0SWQsXG5cdFx0XHRcdFx0XHRyYXdTbmFwc2hvdFxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHRoaXMubWF0Y2hlZC5pbmNyZW1lbnQodGVzdElkKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5fYWRkU25hcHNob3Qoa2V5LCByZWNlaXZlZFNlcmlhbGl6ZWQsIHtcblx0XHRcdFx0XHRzdGFjayxcblx0XHRcdFx0XHR0ZXN0SWQsXG5cdFx0XHRcdFx0cmF3U25hcHNob3Rcblx0XHRcdFx0fSk7XG5cdFx0XHRcdHRoaXMuYWRkZWQuaW5jcmVtZW50KHRlc3RJZCk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRhY3R1YWw6IFwiXCIsXG5cdFx0XHRcdGNvdW50LFxuXHRcdFx0XHRleHBlY3RlZDogXCJcIixcblx0XHRcdFx0a2V5LFxuXHRcdFx0XHRwYXNzOiB0cnVlXG5cdFx0XHR9O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRpZiAoIXBhc3MpIHtcblx0XHRcdFx0dGhpcy51bm1hdGNoZWQuaW5jcmVtZW50KHRlc3RJZCk7XG5cdFx0XHRcdHJldHVybiB7XG5cdFx0XHRcdFx0YWN0dWFsOiByYXdTbmFwc2hvdCA/IHJlY2VpdmVkU2VyaWFsaXplZCA6IHJlbW92ZUV4dHJhTGluZUJyZWFrcyhyZWNlaXZlZFNlcmlhbGl6ZWQpLFxuXHRcdFx0XHRcdGNvdW50LFxuXHRcdFx0XHRcdGV4cGVjdGVkOiBleHBlY3RlZFRyaW1tZWQgIT09IHVuZGVmaW5lZCA/IHJhd1NuYXBzaG90ID8gZXhwZWN0ZWRUcmltbWVkIDogcmVtb3ZlRXh0cmFMaW5lQnJlYWtzKGV4cGVjdGVkVHJpbW1lZCkgOiB1bmRlZmluZWQsXG5cdFx0XHRcdFx0a2V5LFxuXHRcdFx0XHRcdHBhc3M6IGZhbHNlXG5cdFx0XHRcdH07XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLm1hdGNoZWQuaW5jcmVtZW50KHRlc3RJZCk7XG5cdFx0XHRcdHJldHVybiB7XG5cdFx0XHRcdFx0YWN0dWFsOiBcIlwiLFxuXHRcdFx0XHRcdGNvdW50LFxuXHRcdFx0XHRcdGV4cGVjdGVkOiBcIlwiLFxuXHRcdFx0XHRcdGtleSxcblx0XHRcdFx0XHRwYXNzOiB0cnVlXG5cdFx0XHRcdH07XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cdGFzeW5jIHBhY2soKSB7XG5cdFx0Y29uc3Qgc25hcHNob3QgPSB7XG5cdFx0XHRmaWxlcGF0aDogdGhpcy50ZXN0RmlsZVBhdGgsXG5cdFx0XHRhZGRlZDogMCxcblx0XHRcdGZpbGVEZWxldGVkOiBmYWxzZSxcblx0XHRcdG1hdGNoZWQ6IDAsXG5cdFx0XHR1bmNoZWNrZWQ6IDAsXG5cdFx0XHR1bmNoZWNrZWRLZXlzOiBbXSxcblx0XHRcdHVubWF0Y2hlZDogMCxcblx0XHRcdHVwZGF0ZWQ6IDBcblx0XHR9O1xuXHRcdGNvbnN0IHVuY2hlY2tlZENvdW50ID0gdGhpcy5nZXRVbmNoZWNrZWRDb3VudCgpO1xuXHRcdGNvbnN0IHVuY2hlY2tlZEtleXMgPSB0aGlzLmdldFVuY2hlY2tlZEtleXMoKTtcblx0XHRpZiAodW5jaGVja2VkQ291bnQpIHtcblx0XHRcdHRoaXMucmVtb3ZlVW5jaGVja2VkS2V5cygpO1xuXHRcdH1cblx0XHRjb25zdCBzdGF0dXMgPSBhd2FpdCB0aGlzLnNhdmUoKTtcblx0XHRzbmFwc2hvdC5maWxlRGVsZXRlZCA9IHN0YXR1cy5kZWxldGVkO1xuXHRcdHNuYXBzaG90LmFkZGVkID0gdGhpcy5hZGRlZC50b3RhbCgpO1xuXHRcdHNuYXBzaG90Lm1hdGNoZWQgPSB0aGlzLm1hdGNoZWQudG90YWwoKTtcblx0XHRzbmFwc2hvdC51bm1hdGNoZWQgPSB0aGlzLnVubWF0Y2hlZC50b3RhbCgpO1xuXHRcdHNuYXBzaG90LnVwZGF0ZWQgPSB0aGlzLnVwZGF0ZWQudG90YWwoKTtcblx0XHRzbmFwc2hvdC51bmNoZWNrZWQgPSAhc3RhdHVzLmRlbGV0ZWQgPyB1bmNoZWNrZWRDb3VudCA6IDA7XG5cdFx0c25hcHNob3QudW5jaGVja2VkS2V5cyA9IEFycmF5LmZyb20odW5jaGVja2VkS2V5cyk7XG5cdFx0cmV0dXJuIHNuYXBzaG90O1xuXHR9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZU1pc21hdGNoRXJyb3IobWVzc2FnZSwgZXhwYW5kLCBhY3R1YWwsIGV4cGVjdGVkKSB7XG5cdGNvbnN0IGVycm9yID0gbmV3IEVycm9yKG1lc3NhZ2UpO1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXJyb3IsIFwiYWN0dWFsXCIsIHtcblx0XHR2YWx1ZTogYWN0dWFsLFxuXHRcdGVudW1lcmFibGU6IHRydWUsXG5cdFx0Y29uZmlndXJhYmxlOiB0cnVlLFxuXHRcdHdyaXRhYmxlOiB0cnVlXG5cdH0pO1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXJyb3IsIFwiZXhwZWN0ZWRcIiwge1xuXHRcdHZhbHVlOiBleHBlY3RlZCxcblx0XHRlbnVtZXJhYmxlOiB0cnVlLFxuXHRcdGNvbmZpZ3VyYWJsZTogdHJ1ZSxcblx0XHR3cml0YWJsZTogdHJ1ZVxuXHR9KTtcblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGVycm9yLCBcImRpZmZPcHRpb25zXCIsIHsgdmFsdWU6IHsgZXhwYW5kIH0gfSk7XG5cdHJldHVybiBlcnJvcjtcbn1cbmNsYXNzIFNuYXBzaG90Q2xpZW50IHtcblx0c25hcHNob3RTdGF0ZU1hcCA9IG5ldyBNYXAoKTtcblx0Y29uc3RydWN0b3Iob3B0aW9ucyA9IHt9KSB7XG5cdFx0dGhpcy5vcHRpb25zID0gb3B0aW9ucztcblx0fVxuXHRhc3luYyBzZXR1cChmaWxlcGF0aCwgb3B0aW9ucykge1xuXHRcdGlmICh0aGlzLnNuYXBzaG90U3RhdGVNYXAuaGFzKGZpbGVwYXRoKSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR0aGlzLnNuYXBzaG90U3RhdGVNYXAuc2V0KGZpbGVwYXRoLCBhd2FpdCBTbmFwc2hvdFN0YXRlLmNyZWF0ZShmaWxlcGF0aCwgb3B0aW9ucykpO1xuXHR9XG5cdGFzeW5jIGZpbmlzaChmaWxlcGF0aCkge1xuXHRcdGNvbnN0IHN0YXRlID0gdGhpcy5nZXRTbmFwc2hvdFN0YXRlKGZpbGVwYXRoKTtcblx0XHRjb25zdCByZXN1bHQgPSBhd2FpdCBzdGF0ZS5wYWNrKCk7XG5cdFx0dGhpcy5zbmFwc2hvdFN0YXRlTWFwLmRlbGV0ZShmaWxlcGF0aCk7XG5cdFx0cmV0dXJuIHJlc3VsdDtcblx0fVxuXHRza2lwVGVzdChmaWxlcGF0aCwgdGVzdE5hbWUpIHtcblx0XHRjb25zdCBzdGF0ZSA9IHRoaXMuZ2V0U25hcHNob3RTdGF0ZShmaWxlcGF0aCk7XG5cdFx0c3RhdGUubWFya1NuYXBzaG90c0FzQ2hlY2tlZEZvclRlc3QodGVzdE5hbWUpO1xuXHR9XG5cdGNsZWFyVGVzdChmaWxlcGF0aCwgdGVzdElkKSB7XG5cdFx0Y29uc3Qgc3RhdGUgPSB0aGlzLmdldFNuYXBzaG90U3RhdGUoZmlsZXBhdGgpO1xuXHRcdHN0YXRlLmNsZWFyVGVzdCh0ZXN0SWQpO1xuXHR9XG5cdGdldFNuYXBzaG90U3RhdGUoZmlsZXBhdGgpIHtcblx0XHRjb25zdCBzdGF0ZSA9IHRoaXMuc25hcHNob3RTdGF0ZU1hcC5nZXQoZmlsZXBhdGgpO1xuXHRcdGlmICghc3RhdGUpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihgVGhlIHNuYXBzaG90IHN0YXRlIGZvciAnJHtmaWxlcGF0aH0nIGlzIG5vdCBmb3VuZC4gRGlkIHlvdSBjYWxsICdTbmFwc2hvdENsaWVudC5zZXR1cCgpJz9gKTtcblx0XHR9XG5cdFx0cmV0dXJuIHN0YXRlO1xuXHR9XG5cdGFzc2VydChvcHRpb25zKSB7XG5cdFx0Y29uc3QgeyBmaWxlcGF0aCwgbmFtZSwgdGVzdElkID0gbmFtZSwgbWVzc2FnZSwgaXNJbmxpbmUgPSBmYWxzZSwgcHJvcGVydGllcywgaW5saW5lU25hcHNob3QsIGVycm9yLCBlcnJvck1lc3NhZ2UsIHJhd1NuYXBzaG90IH0gPSBvcHRpb25zO1xuXHRcdGxldCB7IHJlY2VpdmVkIH0gPSBvcHRpb25zO1xuXHRcdGlmICghZmlsZXBhdGgpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihcIlNuYXBzaG90IGNhbm5vdCBiZSB1c2VkIG91dHNpZGUgb2YgdGVzdFwiKTtcblx0XHR9XG5cdFx0Y29uc3Qgc25hcHNob3RTdGF0ZSA9IHRoaXMuZ2V0U25hcHNob3RTdGF0ZShmaWxlcGF0aCk7XG5cdFx0aWYgKHR5cGVvZiBwcm9wZXJ0aWVzID09PSBcIm9iamVjdFwiKSB7XG5cdFx0XHRpZiAodHlwZW9mIHJlY2VpdmVkICE9PSBcIm9iamVjdFwiIHx8ICFyZWNlaXZlZCkge1xuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJSZWNlaXZlZCB2YWx1ZSBtdXN0IGJlIGFuIG9iamVjdCB3aGVuIHRoZSBtYXRjaGVyIGhhcyBwcm9wZXJ0aWVzXCIpO1xuXHRcdFx0fVxuXHRcdFx0dHJ5IHtcblx0XHRcdFx0Y29uc3QgcGFzcyA9IHRoaXMub3B0aW9ucy5pc0VxdWFsPy4ocmVjZWl2ZWQsIHByb3BlcnRpZXMpID8/IGZhbHNlO1xuXHRcdFx0XHQvLyBjb25zdCBwYXNzID0gZXF1YWxzKHJlY2VpdmVkLCBwcm9wZXJ0aWVzLCBbaXRlcmFibGVFcXVhbGl0eSwgc3Vic2V0RXF1YWxpdHldKVxuXHRcdFx0XHRpZiAoIXBhc3MpIHtcblx0XHRcdFx0XHR0aHJvdyBjcmVhdGVNaXNtYXRjaEVycm9yKFwiU25hcHNob3QgcHJvcGVydGllcyBtaXNtYXRjaGVkXCIsIHNuYXBzaG90U3RhdGUuZXhwYW5kLCByZWNlaXZlZCwgcHJvcGVydGllcyk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0cmVjZWl2ZWQgPSBkZWVwTWVyZ2VTbmFwc2hvdChyZWNlaXZlZCwgcHJvcGVydGllcyk7XG5cdFx0XHRcdH1cblx0XHRcdH0gY2F0Y2ggKGVycikge1xuXHRcdFx0XHRlcnIubWVzc2FnZSA9IGVycm9yTWVzc2FnZSB8fCBcIlNuYXBzaG90IG1pc21hdGNoZWRcIjtcblx0XHRcdFx0dGhyb3cgZXJyO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRjb25zdCB0ZXN0TmFtZSA9IFtuYW1lLCAuLi5tZXNzYWdlID8gW21lc3NhZ2VdIDogW11dLmpvaW4oXCIgPiBcIik7XG5cdFx0Y29uc3QgeyBhY3R1YWwsIGV4cGVjdGVkLCBrZXksIHBhc3MgfSA9IHNuYXBzaG90U3RhdGUubWF0Y2goe1xuXHRcdFx0dGVzdElkLFxuXHRcdFx0dGVzdE5hbWUsXG5cdFx0XHRyZWNlaXZlZCxcblx0XHRcdGlzSW5saW5lLFxuXHRcdFx0ZXJyb3IsXG5cdFx0XHRpbmxpbmVTbmFwc2hvdCxcblx0XHRcdHJhd1NuYXBzaG90XG5cdFx0fSk7XG5cdFx0aWYgKCFwYXNzKSB7XG5cdFx0XHR0aHJvdyBjcmVhdGVNaXNtYXRjaEVycm9yKGBTbmFwc2hvdCBcXGAke2tleSB8fCBcInVua25vd25cIn1cXGAgbWlzbWF0Y2hlZGAsIHNuYXBzaG90U3RhdGUuZXhwYW5kLCByYXdTbmFwc2hvdCA/IGFjdHVhbCA6IGFjdHVhbD8udHJpbSgpLCByYXdTbmFwc2hvdCA/IGV4cGVjdGVkIDogZXhwZWN0ZWQ/LnRyaW0oKSk7XG5cdFx0fVxuXHR9XG5cdGFzeW5jIGFzc2VydFJhdyhvcHRpb25zKSB7XG5cdFx0aWYgKCFvcHRpb25zLnJhd1NuYXBzaG90KSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJSYXcgc25hcHNob3QgaXMgcmVxdWlyZWRcIik7XG5cdFx0fVxuXHRcdGNvbnN0IHsgZmlsZXBhdGgsIHJhd1NuYXBzaG90IH0gPSBvcHRpb25zO1xuXHRcdGlmIChyYXdTbmFwc2hvdC5jb250ZW50ID09IG51bGwpIHtcblx0XHRcdGlmICghZmlsZXBhdGgpIHtcblx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKFwiU25hcHNob3QgY2Fubm90IGJlIHVzZWQgb3V0c2lkZSBvZiB0ZXN0XCIpO1xuXHRcdFx0fVxuXHRcdFx0Y29uc3Qgc25hcHNob3RTdGF0ZSA9IHRoaXMuZ2V0U25hcHNob3RTdGF0ZShmaWxlcGF0aCk7XG5cdFx0XHQvLyBzYXZlIHRoZSBmaWxlcGF0aCwgc28gaXQgZG9uJ3QgbG9zZSBldmVuIGlmIHRoZSBhd2FpdCBtYWtlIGl0IG91dC1vZi1jb250ZXh0XG5cdFx0XHRvcHRpb25zLmZpbGVwYXRoIHx8PSBmaWxlcGF0aDtcblx0XHRcdC8vIHJlc29sdmUgYW5kIHJlYWQgdGhlIHJhdyBzbmFwc2hvdCBmaWxlXG5cdFx0XHRyYXdTbmFwc2hvdC5maWxlID0gYXdhaXQgc25hcHNob3RTdGF0ZS5lbnZpcm9ubWVudC5yZXNvbHZlUmF3UGF0aChmaWxlcGF0aCwgcmF3U25hcHNob3QuZmlsZSk7XG5cdFx0XHRyYXdTbmFwc2hvdC5jb250ZW50ID0gYXdhaXQgc25hcHNob3RTdGF0ZS5lbnZpcm9ubWVudC5yZWFkU25hcHNob3RGaWxlKHJhd1NuYXBzaG90LmZpbGUpID8/IHVuZGVmaW5lZDtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXMuYXNzZXJ0KG9wdGlvbnMpO1xuXHR9XG5cdGNsZWFyKCkge1xuXHRcdHRoaXMuc25hcHNob3RTdGF0ZU1hcC5jbGVhcigpO1xuXHR9XG59XG5cbmV4cG9ydCB7IFNuYXBzaG90Q2xpZW50LCBTbmFwc2hvdFN0YXRlLCBhZGRTZXJpYWxpemVyLCBnZXRTZXJpYWxpemVycywgc3RyaXBTbmFwc2hvdEluZGVudGF0aW9uIH07XG4iXSwieF9nb29nbGVfaWdub3JlTGlzdCI6WzBdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFLQSxlQUFlLG9CQUFvQixhQUFhLFdBQVc7Q0FDMUQsTUFBTSxlQUFlLE1BQU0sT0FBTywwRkFBaUI7Q0FDbkQsTUFBTSxRQUFRLElBQUksSUFBSSxVQUFVLEtBQUssTUFBTSxFQUFFLEtBQUssQ0FBQztBQUNuRCxPQUFNLFFBQVEsSUFBSSxNQUFNLEtBQUssTUFBTSxDQUFDLElBQUksT0FBTyxTQUFTO0VBQ3ZELE1BQU0sUUFBUSxVQUFVLFFBQVEsTUFBTSxFQUFFLFNBQVMsS0FBSztFQUN0RCxNQUFNLE9BQU8sTUFBTSxZQUFZLGlCQUFpQixLQUFLO0FBQ3JELE1BQUksUUFBUSxLQUNYLE9BQU0sSUFBSSxNQUFNLGVBQWUsS0FBSyw4QkFBOEI7RUFFbkUsTUFBTSxJQUFJLElBQUksWUFBWSxLQUFLO0FBQy9CLE9BQUssTUFBTSxRQUFRLE1BRWxCLG1CQUFrQixNQUFNLEdBRFYsaUJBQWlCLE1BQU0sS0FBSyxNQUFNLEtBQUssT0FBTyxFQUMxQixLQUFLLFNBQVM7RUFFakQsTUFBTSxjQUFjLEVBQUUsVUFBVTtBQUNoQyxNQUFJLGdCQUFnQixLQUNuQixPQUFNLFlBQVksaUJBQWlCLE1BQU0sWUFBWTtHQUVyRCxDQUFDOztBQUVKLE1BQU0sbUJBQW1CO0FBQ3pCLFNBQVMsa0JBQWtCLE1BQU0sR0FBRyxP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