@cartanova/qgrid-cli 1.0.2 → 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.
- package/bundle/dist/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/decorate.js +9 -0
- package/bundle/dist/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/decorateMetadata.js +6 -0
- package/bundle/dist/dist/_virtual/_rolldown/runtime.js +15 -0
- package/bundle/dist/dist/application/qgrid/oauth.js +140 -0
- package/bundle/dist/dist/application/qgrid/pool.js +100 -0
- package/bundle/dist/dist/application/qgrid/qgrid.frame.js +280 -0
- package/bundle/dist/dist/application/qgrid/qgrid.types.js +79 -0
- package/bundle/dist/dist/application/qgrid/worker.js +183 -0
- package/bundle/dist/dist/application/queries.generated.js +31 -0
- package/bundle/dist/dist/application/request-log/request-log.model.js +113 -0
- package/bundle/dist/dist/application/request-log/request-log.types.js +13 -0
- package/bundle/dist/dist/application/sonamu.generated.js +99 -0
- package/bundle/dist/dist/application/sonamu.generated.sso.js +34 -0
- package/bundle/dist/dist/application/token/token.model.js +157 -0
- package/bundle/dist/dist/application/token/token.types.js +22 -0
- package/bundle/dist/dist/i18n/en.js +63 -0
- package/bundle/dist/dist/i18n/ko.js +62 -0
- package/bundle/dist/dist/i18n/sd.generated.js +272 -0
- package/bundle/dist/dist/index.js +11 -0
- package/bundle/dist/dist/migrations/20260410171405_create__request_logs.js +26 -0
- package/bundle/dist/dist/migrations/20260410171406_create__tokens.js +24 -0
- package/bundle/dist/dist/migrations/20260411120624_alter_tokens_alter2.js +16 -0
- package/bundle/dist/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +155 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_expect@4.1.2/node_modules/@vitest/expect/dist/index.js +1484 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_pretty-format@4.1.2/node_modules/@vitest/pretty-format/dist/index.js +887 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_runner@4.1.2/node_modules/@vitest/runner/dist/chunk-artifact.js +2746 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_runner@4.1.2/node_modules/@vitest/runner/dist/index.js +8 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_runner@4.1.2/node_modules/@vitest/runner/dist/utils.js +8 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_snapshot@4.1.2/node_modules/@vitest/snapshot/dist/index.js +662 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_spy@4.1.2/node_modules/@vitest/spy/dist/index.js +386 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +82 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/constants.js +48 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/diff.js +1307 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/display.js +558 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/error.js +33 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/helpers.js +226 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/offset.js +27 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/serialize.js +77 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/source-map.js +374 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/timers.js +37 -0
- package/bundle/dist/dist/node_modules/.pnpm/chai@6.2.2/node_modules/chai/index.js +2886 -0
- package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/branding.js +10 -0
- package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/index.js +109 -0
- package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/messages.js +10 -0
- package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/overloads.js +10 -0
- package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/utils.js +10 -0
- package/bundle/dist/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js +1127 -0
- package/bundle/dist/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/index.js +21 -0
- package/bundle/dist/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js +432 -0
- package/bundle/dist/dist/node_modules/.pnpm/tinybench@2.9.0/node_modules/tinybench/dist/index.js +506 -0
- package/bundle/dist/dist/node_modules/.pnpm/tinyrainbow@3.1.0/node_modules/tinyrainbow/dist/index.js +86 -0
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- package/bundle/dist/dist/sonamu.config.js +196 -0
- package/bundle/dist/dist/testing/fixture.js +8 -0
- package/bundle/dist/dist/testing/global.js +9 -0
- package/bundle/dist/dist/testing/setup-mocks.js +17 -0
- package/bundle/dist/dist/utils/subset-loaders.js +12 -0
- package/bundle/src/src/application/qgrid/oauth.ts +181 -0
- package/bundle/src/src/application/qgrid/pool.ts +132 -0
- package/bundle/src/src/application/qgrid/qgrid.frame.ts +275 -0
- package/bundle/src/src/application/qgrid/qgrid.types.ts +117 -0
- package/bundle/src/src/application/qgrid/worker.ts +234 -0
- package/bundle/src/src/application/queries.generated.ts +59 -0
- package/bundle/src/src/application/request-log/request-log.entity.json +75 -0
- package/bundle/src/src/application/request-log/request-log.model.ts +155 -0
- package/bundle/src/src/application/request-log/request-log.types.ts +15 -0
- package/bundle/src/src/application/sonamu.generated.http +187 -0
- package/bundle/src/src/application/sonamu.generated.sso.ts +66 -0
- package/bundle/src/src/application/sonamu.generated.ts +135 -0
- package/bundle/src/src/application/token/token.entity.json +37 -0
- package/bundle/src/src/application/token/token.model.ts +160 -0
- package/bundle/src/src/application/token/token.types.ts +26 -0
- package/bundle/src/src/i18n/en.ts +59 -0
- package/bundle/src/src/i18n/ko.ts +59 -0
- package/bundle/src/src/i18n/sd.generated.ts +384 -0
- package/bundle/src/src/index.ts +6 -0
- package/bundle/src/src/migrations/20260410171405_create__request_logs.ts +23 -0
- package/bundle/src/src/migrations/20260410171406_create__tokens.ts +21 -0
- package/bundle/src/src/migrations/20260411120624_alter_tokens_alter2.ts +15 -0
- package/bundle/src/src/sonamu.config.ts +248 -0
- package/bundle/src/src/testing/fixture.ts +6 -0
- package/bundle/src/src/testing/global.ts +6 -0
- package/bundle/src/src/testing/setup-mocks.ts +44 -0
- package/bundle/src/src/typings/fastify.d.ts +8 -0
- package/bundle/src/src/typings/sonamu.d.ts +17 -0
- package/bundle/src/src/utils/subset-loaders.ts +11 -0
- package/bundle/web-dist/web-dist/client/assets/index-DlPchHBY.js +116 -0
- package/bundle/web-dist/web-dist/client/assets/index-vZsvyuFn.css +1 -0
- package/bundle/web-dist/web-dist/client/assets/rolldown-runtime-Dw2cE7zH.js +1 -0
- package/bundle/web-dist/web-dist/client/assets/routes-CagDz23B.js +1 -0
- package/bundle/web-dist/web-dist/client/assets/sd.generated-BrQoQXvv.js +47 -0
- package/bundle/web-dist/web-dist/client/assets/services.generated-BspO2L0j.js +1 -0
- package/bundle/web-dist/web-dist/client/assets/show-aXUGa0gm.js +29 -0
- package/bundle/web-dist/web-dist/client/assets/tokens-DRkXtZ3Q.js +1 -0
- package/bundle/web-dist/web-dist/client/assets/vendor-react-DH4kUfK2.js +9 -0
- package/bundle/web-dist/web-dist/client/assets/vendor-tanstack-CUxlo6YN.js +1 -0
- package/bundle/web-dist/web-dist/client/index.html +18 -0
- package/bundle/web-dist/web-dist/server/assets/react-dom-CGIzOSuj.js +335 -0
- package/bundle/web-dist/web-dist/server/assets/routes-ClzReRep.js +490 -0
- package/bundle/web-dist/web-dist/server/assets/sd.generated-BnonqqKr.js +21694 -0
- package/bundle/web-dist/web-dist/server/assets/services.generated-D5ABD5fr.js +836 -0
- package/bundle/web-dist/web-dist/server/assets/show-C9pcdSxc.js +23364 -0
- package/bundle/web-dist/web-dist/server/assets/tokens-JH6FsnWZ.js +860 -0
- package/bundle/web-dist/web-dist/server/entry-server.generated.js +44646 -0
- 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/IHVuZGVmaW5lZDtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXMuYXNzZXJ0KG9wdGlvbnMpO1xuXHR9XG5cdGNsZWFyKCkge1xuXHRcdHRoaXMuc25hcHNob3RTdGF0ZU1hcC5jbGVhcigpO1xuXHR9XG59XG5cbmV4cG9ydCB7IFNuYXBzaG90Q2xpZW50LCBTbmFwc2hvdFN0YXRlLCBhZGRTZXJpYWxpemVyLCBnZXRTZXJpYWxpemVycywgc3RyaXBTbmFwc2hvdEluZGVudGF0aW9uIH07XG4iXSwieF9nb29nbGVfaWdub3JlTGlzdCI6WzBdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFLQSxlQUFlLG9CQUFvQixhQUFhLFdBQVc7Q0FDMUQsTUFBTSxlQUFlLE1BQU0sT0FBTywwRkFBaUI7Q0FDbkQsTUFBTSxRQUFRLElBQUksSUFBSSxVQUFVLEtBQUssTUFBTSxFQUFFLEtBQUssQ0FBQztBQUNuRCxPQUFNLFFBQVEsSUFBSSxNQUFNLEtBQUssTUFBTSxDQUFDLElBQUksT0FBTyxTQUFTO0VBQ3ZELE1BQU0sUUFBUSxVQUFVLFFBQVEsTUFBTSxFQUFFLFNBQVMsS0FBSztFQUN0RCxNQUFNLE9BQU8sTUFBTSxZQUFZLGlCQUFpQixLQUFLO0FBQ3JELE1BQUksUUFBUSxLQUNYLE9BQU0sSUFBSSxNQUFNLGVBQWUsS0FBSyw4QkFBOEI7RUFFbkUsTUFBTSxJQUFJLElBQUksWUFBWSxLQUFLO0FBQy9CLE9BQUssTUFBTSxRQUFRLE1BRWxCLG1CQUFrQixNQUFNLEdBRFYsaUJBQWlCLE1BQU0sS0FBSyxNQUFNLEtBQUssT0FBTyxFQUMxQixLQUFLLFNBQVM7RUFFakQsTUFBTSxjQUFjLEVBQUUsVUFBVTtBQUNoQyxNQUFJLGdCQUFnQixLQUNuQixPQUFNLFlBQVksaUJBQWlCLE1BQU0sWUFBWTtHQUVyRCxDQUFDOztBQUVKLE1BQU0sbUJBQW1CO0FBQ3pCLFNBQVMsa0JBQWtCLE1BQU0sR0FBRyxPQUFPLFNBQVM7Q0FDbkQsSUFBSSxRQUFRLEtBQUssTUFBTSxNQUFNO0NBQzdCLE1BQU0sYUFBYSxpQkFBaUIsS0FBSyxNQUFNO0FBQy9DLEtBQUksQ0FBQyxXQUNKLFFBQU87QUFFUixTQUFRLE1BQU0sTUFBTSxXQUFXLE1BQU07Q0FDckMsSUFBSSxVQUFVLGlCQUFpQixNQUFNO0FBQ3JDLEtBQUksWUFBWSxLQUNmLFFBQU87QUFFUixZQUFXLFFBQVEsV0FBVztDQUU5QixNQUFNLFdBQVcsdUJBQXVCLE1BRHJCLFFBQVEsV0FBVyxRQUFRLFdBQVcsR0FBRyxPQUNIO0NBQ3pELE1BQU0sT0FBTyxLQUFLLGtCQUFrQixTQUFTLE1BQU0sTUFBTTtBQUN6RCxLQUFJLGFBQWEsUUFFaEIsR0FBRSxXQUFXLFNBQVMsS0FBSztLQUczQixHQUFFLFVBQVUsVUFBVSxTQUFTLEtBQUs7QUFFckMsUUFBTzs7QUFFUixTQUFTLHVCQUF1QixNQUFNLE9BQU87Q0FDNUMsSUFBSSxjQUFjO0NBQ2xCLElBQUksWUFBWTtBQUNoQixRQUFPLGdCQUFnQixhQUFhLFFBQVEsS0FBSyxRQUFRO0VBQ3hELE1BQU0sSUFBSSxLQUFLO0FBQ2YsTUFBSSxNQUFNLElBQ1Q7V0FDVSxNQUFNLElBQ2hCOztBQUdGLFFBQU87O0FBRVIsU0FBUyxrQkFBa0IsTUFBTSxRQUFRLE9BQU87Q0FDL0MsTUFBTSxhQUFhLG1CQUFtQixRQUFRLE1BQU07Q0FFcEQsTUFBTSxTQURPLE9BQU8sTUFBTSxZQUFZLENBQUMsYUFBYSxHQUNoQyxNQUFNLE9BQU8sQ0FBQyxNQUFNO0NBQ3hDLE1BQU0sYUFBYSxPQUFPLFNBQVMsSUFBSSxHQUFHLEdBQUcsT0FBTyxNQUFNLEdBQUcsT0FBTztDQUNwRSxNQUFNLFFBQVEsS0FBSyxNQUFNLENBQUMsUUFBUSxPQUFPLE9BQU8sQ0FBQyxNQUFNLE1BQU07Q0FDN0QsTUFBTSxZQUFZLE1BQU0sVUFBVTtDQUNsQyxNQUFNLFFBQVE7QUFDZCxLQUFJLFVBQ0gsUUFBTyxHQUFHLFFBQVEsTUFBTSxLQUFLLEtBQUssQ0FBQyxRQUFRLE1BQU0sTUFBTSxDQUFDLFFBQVEsU0FBUyxPQUFPLEdBQUc7QUFFcEYsUUFBTyxHQUFHLE1BQU0sSUFBSSxNQUFNLEtBQUssTUFBTSxJQUFJLGFBQWEsSUFBSSxHQUFHLENBQUMsS0FBSyxLQUFLLENBQUMsUUFBUSxNQUFNLE1BQU0sQ0FBQyxRQUFRLFNBQVMsT0FBTyxDQUFDLElBQUksU0FBUzs7QUFFckksTUFBTSxvQkFBb0I7QUFDMUIsTUFBTSxpQ0FBaUM7QUFFdkMsU0FBUyx1QkFBdUIsTUFBTSxPQUFPO0NBQzVDLE1BQU0sY0FBYyxRQUFRO0FBQzVCLEtBQUksS0FBSyxNQUFNLGFBQWEsTUFBTSxLQUFLLGtCQUN0QyxRQUFPO0VBQ04sTUFBTSxLQUFLLE1BQU0sWUFBWTtFQUM3QixPQUFPO0VBQ1A7Q0FFRixNQUFNLG1CQUFtQixRQUFRO0FBQ2pDLEtBQUksS0FBSyxNQUFNLFFBQVEsa0JBQWtCLE1BQU0sS0FBSywrQkFDbkQsUUFBTztFQUNOLE1BQU0sS0FBSyxNQUFNLFFBQVEsaUJBQWlCO0VBQzFDLE9BQU8sUUFBUTtFQUNmO0FBRUYsUUFBTztFQUNOLE1BQU0sS0FBSyxNQUFNLE1BQU07RUFDdkI7RUFDQTs7QUFFRixNQUFNLGFBQWE7QUFDbkIsU0FBUyxrQkFBa0IsTUFBTSxHQUFHLGNBQWMsU0FBUztDQUMxRCxNQUFNLEVBQUUsTUFBTSxxQkFBcUIsVUFBVSx1QkFBdUIsTUFBTSxhQUFhO0NBQ3ZGLE1BQU0sYUFBYSxXQUFXLEtBQUssb0JBQW9CO0NBQ3ZELE1BQU0sb0JBQW9CLDJEQUEyRCxLQUFLLG9CQUFvQjtBQUM5RyxLQUFJLENBQUMsY0FBYyxXQUFXLFVBQVUsbUJBQW1CLE1BQzFELFFBQU8sa0JBQWtCLE1BQU0sR0FBRyxPQUFPLFFBQVE7Q0FFbEQsTUFBTSxRQUFRLFdBQVc7Q0FDekIsTUFBTSxhQUFhLFFBQVEsV0FBVyxRQUFRLFdBQVcsR0FBRztDQUM1RCxNQUFNLGFBQWEsa0JBQWtCLFNBQVMsTUFBTSxNQUFNO0FBQzFELEtBQUksVUFBVSxLQUFLO0FBQ2xCLElBQUUsWUFBWSxhQUFhLEdBQUcsV0FBVztBQUN6QyxTQUFPOztDQUdSLE1BQU0sV0FEYSxJQUFJLE9BQU8sZ0JBQWdCLFFBQVEsQ0FDMUIsS0FBSyxLQUFLLE1BQU0sV0FBVyxDQUFDO0FBQ3hELEtBQUksQ0FBQyxTQUNKLFFBQU87Q0FFUixNQUFNLFdBQVcsYUFBYSxTQUFTLFFBQVEsU0FBUyxHQUFHO0FBQzNELEdBQUUsVUFBVSxhQUFhLEdBQUcsVUFBVSxXQUFXO0FBQ2pELFFBQU87O0FBRVIsTUFBTSxvQkFBb0I7QUFDMUIsU0FBUyx5QkFBeUIsZ0JBQWdCO0NBRWpELE1BQU0sUUFBUSxlQUFlLE1BQU0sa0JBQWtCO0FBQ3JELEtBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUVwQixRQUFPO0NBRVIsTUFBTSxjQUFjLE1BQU07Q0FDMUIsTUFBTSxRQUFRLGVBQWUsTUFBTSxNQUFNO0FBQ3pDLEtBQUksTUFBTSxVQUFVLEVBRW5CLFFBQU87QUFFUixLQUFJLE1BQU0sR0FBRyxNQUFNLEtBQUssTUFBTSxNQUFNLEdBQUcsR0FBRyxFQUFFLE1BQU0sS0FBSyxHQUV0RCxRQUFPO0FBRVIsTUFBSyxJQUFJLElBQUksR0FBRyxJQUFJLE1BQU0sU0FBUyxHQUFHLElBQ3JDLEtBQUksTUFBTSxPQUFPLElBQUk7QUFDcEIsTUFBSSxNQUFNLEdBQUcsUUFBUSxZQUFZLEtBQUssRUFJckMsUUFBTztBQUVSLFFBQU0sS0FBSyxNQUFNLEdBQUcsVUFBVSxZQUFZLE9BQU87O0FBS25ELE9BQU0sTUFBTSxTQUFTLEtBQUs7QUFFMUIsa0JBQWlCLE1BQU0sS0FBSyxLQUFLO0FBQ2pDLFFBQU87O0FBR1IsZUFBZSxpQkFBaUIsYUFBYSxXQUFXO0FBQ3ZELE9BQU0sUUFBUSxJQUFJLFVBQVUsSUFBSSxPQUFPLFNBQVM7QUFDL0MsTUFBSSxDQUFDLEtBQUssU0FDVCxPQUFNLFlBQVksaUJBQWlCLEtBQUssTUFBTSxLQUFLLFNBQVM7R0FFNUQsQ0FBQzs7QUFHSixTQUFTLHdCQUF3QixHQUFHO0FBQ25DLFFBQU8sS0FBSyxFQUFFLGNBQWMsT0FBTyxVQUFVLGVBQWUsS0FBSyxHQUFHLFVBQVUsR0FBRyxFQUFFLGFBQWE7O0FBR2pHLElBQUksbUJBQW1CLEVBQUMsU0FBUyxFQUFFLEVBQUM7QUFFcEMsSUFBSTtBQUVKLFNBQVMsd0JBQXlCO0FBQ2pDLEtBQUksMEJBQTJCLFFBQU8saUJBQWlCO0FBQ3ZELDZCQUE0Qjs7Ozs7Ozs7Q0FVNUIsSUFBSSxpQkFBaUIsU0FBUyxHQUFHLEdBQUc7RUFDbkMsSUFBSSxHQUFHLE9BQ0wsUUFBUSxHQUNSLE9BQU8sR0FDUCxPQUFPLEdBQ1AsV0FBVyxPQUFPO0VBRXBCLFNBQVMsUUFBUSxLQUFLLEtBQUssTUFBTTtBQUNoQyxPQUFJLE1BQU07QUFDVCxTQUFLLElBQUksS0FBSyxPQUFPLFFBQVEsS0FBSyxFQUFFLEVBQUUsT0FBTyxNQUFNLE9BQU8sSUFBSyxHQUFFO0FBQ2pFLFdBQU8sQ0FBQyxJQUFJLE1BQU0sTUFBTSxHQUFHLEVBQUU7O0FBRTlCLFVBQU8sWUFBWSxTQUFTLFFBQVEsSUFBSSxPQUFPLElBQUksQ0FBQztBQUNwRCxVQUFPLE9BQU8sS0FBSyxPQUFPLE1BQU8sT0FBTyxJQUFJLFdBQVcsSUFBSSxJQUFJLEdBQUksT0FBTyxNQUFNLE9BQU8sT0FBTyxPQUMzRixPQUFPLEtBQUssS0FDWixPQUFPLEtBQUssT0FBTyxJQUNuQixPQUFPLEtBQUssT0FBTyxLQUNuQixPQUFPLEtBQUssT0FBTyxLQUNuQixPQUFPLEtBQUssT0FBTyxLQUNuQixPQUFPLEtBQUssT0FBTyxLQUNuQixPQUFPLE1BQU0sT0FBTyxJQUNwQixPQUFPOztBQUlYLE9BQUssS0FBRyxRQUFRLEtBQUcsSUFBSyxRQUFNLFFBQVE7QUFDckMsV0FBUSxRQUFRLEdBQUcsT0FBTztBQUMxQixXQUFRLFFBQVEsR0FBRyxPQUFPO0FBRTFCLE9BQUksUUFBUSxNQUFNLFFBQVEsTUFBTSxRQUFRLE1BQU0sUUFBUSxJQUFJO0FBQ3pELFlBQVEsUUFBUSxHQUFHLE1BQU0sS0FBSztBQUM5QixZQUFRLFFBQVEsR0FBRyxNQUFNLE9BQU8sRUFBRTtBQUNsQyxXQUFPOztBQUdSLE9BQUksU0FBUyxNQUFPLFFBQVEsUUFBUSxRQUFTLEtBQUs7O0FBRW5ELFNBQU87O0FBR1IsS0FBSTtBQUNILG1CQUFpQixVQUFVO1VBQ25CLEdBQUc7QUFDWCxTQUFPLGlCQUFpQjs7QUFFekIsUUFBTyxpQkFBaUI7O0FBSXpCLElBQUksaUJBQThCLHdDQUROLHVCQUF1QixDQUM2QjtBQUVoRixNQUFNLGVBQWUsS0FBSyxRQUFRLGFBQWEsT0FBTyxNQUFNLFlBQVk7Q0FFdkUsTUFBTSxPQUFPLElBQUksYUFBYTtDQUM5QixNQUFNLGFBQWEsU0FBUyxZQUFZLEtBQUssSUFBSTtDQUNqRCxJQUFJLGNBQWM7QUFDbEIsS0FBSSxJQUFJLEtBQUssTUFBTSxXQUFXLEdBQUc7RUFDaEMsTUFBTSxrQkFBa0IsY0FBYyxPQUFPO0FBQzdDLGdCQUFjLEtBQUssT0FBTyxlQUFlLGdCQUFnQixXQUFXLFFBQVEsSUFBSSxLQUFLLE9BQU8sUUFBUSxpQkFBaUIsT0FBTyxLQUFLLEdBQUcsT0FBTyxNQUFNLE9BQU8sTUFBTSxPQUFPLGVBQWUsZ0JBQWdCLGFBQWEsUUFBUSxJQUFJLEtBQUssU0FBUyxRQUFRLGlCQUFpQixPQUFPLEtBQUssR0FBRyxPQUFPLE1BQU0sS0FBSyxNQUFNLE9BQU8sZUFBZSxZQUFZOztBQUU5VSxRQUFPLGdCQUFnQixXQUFXLEdBQUc7O0FBRXRDLE1BQU0sUUFBUSxRQUFRLE9BQU8sQ0FBQyxDQUFDLElBQUk7QUFDbkMsTUFBTSxTQUFTO0NBQ2QsV0FBVztDQUNYO0NBQ0E7QUFFRCxNQUFNLEVBQUUsZUFBZSxZQUFZLFdBQVcsY0FBYyxvQkFBb0Isc0JBQXNCO0FBQ3RHLElBQUksVUFBVTtDQUNiO0NBQ0E7Q0FDQTtDQUNBO0NBQ0E7Q0FDQTtDQUNBO0NBQ0E7QUFDRCxTQUFTLGNBQWMsUUFBUTtBQUM5QixXQUFVLENBQUMsT0FBTyxDQUFDLE9BQU8sUUFBUTs7QUFFbkMsU0FBUyxpQkFBaUI7QUFDekIsUUFBTzs7QUFJUixTQUFTLGNBQWMsVUFBVSxPQUFPO0FBQ3ZDLFFBQU8sR0FBRyxTQUFTLEdBQUc7O0FBRXZCLFNBQVMsY0FBYyxLQUFLO0FBQzNCLEtBQUksQ0FBQyxRQUFRLEtBQUssSUFBSSxDQUNyQixPQUFNLElBQUksTUFBTSx3Q0FBd0M7QUFFekQsUUFBTyxJQUFJLFFBQVEsU0FBUyxHQUFHOztBQUVoQyxTQUFTLGdCQUFnQixTQUFTLFNBQVM7Q0FDMUMsTUFBTSxTQUFTLFFBQVE7Q0FDdkIsTUFBTSxPQUFPLE9BQU8sT0FBTyxLQUFLO0NBQ2hDLElBQUksbUJBQW1CO0NBQ3ZCLElBQUksUUFBUTtBQUNaLEtBQUksV0FBVyxLQUNkLEtBQUk7QUFDSCxxQkFBbUI7QUFHbkIsRUFEaUIsSUFBSSxTQUFTLFdBQVcsaUJBQWlCLENBQ2pELEtBQUs7U0FDUDtBQU1ULE1BQUssV0FBVyxTQUFTLFdBQVcsVUFIbEIsaUJBSWpCLFNBQVE7QUFFVCxRQUFPO0VBQ047RUFDQTtFQUNBOztBQUlGLFNBQVMsbUJBQW1CLFFBQVE7QUFDbkMsUUFBTyxPQUFPLFNBQVMsS0FBSyxHQUFHLEtBQUssT0FBTyxNQUFNOztBQUtsRCxTQUFTLHNCQUFzQixRQUFRO0FBQ3RDLFFBQU8sT0FBTyxTQUFTLEtBQUssT0FBTyxPQUFPLFFBQVEsT0FBTyxTQUFTLEtBQUssR0FBRyxPQUFPLE1BQU0sR0FBRyxHQUFHLEdBQUc7O0FBWWpHLE1BQU0sY0FBYztBQUNwQixNQUFNLG9CQUFvQjtBQUMxQixTQUFTLFVBQVUsS0FBSyxTQUFTLEdBQUcsa0JBQWtCLEVBQUUsRUFBRTtBQUN6RCxRQUFPLGtCQUFrQixPQUFPLEtBQUs7RUFDcEM7RUFDQTtFQUNBLFNBQVMsZ0JBQWdCO0VBQ3pCO0VBQ0EsR0FBRztFQUNILENBQUMsQ0FBQzs7QUFFSixTQUFTLHFCQUFxQixLQUFLO0FBQ2xDLFFBQU8sSUFBSSxRQUFRLGNBQWMsT0FBTzs7QUFFekMsU0FBUyxvQkFBb0IsS0FBSztBQUNqQyxRQUFPLEtBQUsscUJBQXFCLElBQUksQ0FBQzs7QUFFdkMsU0FBUyxrQkFBa0IsUUFBUTtBQUNsQyxRQUFPLE9BQU8sUUFBUSxZQUFZLEtBQUs7O0FBRXhDLGVBQWUsaUJBQWlCLGFBQWEsY0FBYyxjQUFjO0NBQ3hFLE1BQU0sWUFBWSxPQUFPLEtBQUssYUFBYSxDQUFDLEtBQUssZUFBZSxDQUFDLEtBQUssUUFBUSxXQUFXLG9CQUFvQixJQUFJLENBQUMsTUFBTSxvQkFBb0Isa0JBQWtCLGFBQWEsS0FBSyxDQUFDLENBQUMsR0FBRztDQUNyTCxNQUFNLFVBQVUsR0FBRyxZQUFZLFdBQVcsQ0FBQyxNQUFNLFVBQVUsS0FBSyxPQUFPLENBQUM7Q0FDeEUsTUFBTSxhQUFhLE1BQU0sWUFBWSxpQkFBaUIsYUFBYTtBQUVuRSxLQURvQixjQUFjLFFBQVEsZUFBZSxRQUV4RDtBQUVELE9BQU0sWUFBWSxpQkFBaUIsY0FBYyxRQUFROztBQUUxRCxTQUFTLGVBQWUsU0FBUyxFQUFFLEVBQUUsU0FBUyxFQUFFLEVBQUU7Q0FDakQsTUFBTSxlQUFlLE1BQU0sS0FBSyxPQUFPO0FBQ3ZDLFFBQU8sU0FBUyxlQUFlLFVBQVU7RUFDeEMsTUFBTSxnQkFBZ0IsYUFBYTtBQUNuQyxNQUFJLE1BQU0sUUFBUSxPQUFPLE9BQU8sQ0FDL0IsY0FBYSxTQUFTLGVBQWUsT0FBTyxRQUFRLGNBQWM7V0FDeEQsU0FBUyxjQUFjLENBQ2pDLGNBQWEsU0FBUyxrQkFBa0IsT0FBTyxRQUFRLGNBQWM7TUFHckUsY0FBYSxTQUFTO0dBRXRCO0FBQ0YsUUFBTzs7Ozs7Ozs7Ozs7Ozs7QUFjUixTQUFTLGtCQUFrQixRQUFRLFFBQVE7QUFDMUMsS0FBSSxTQUFTLE9BQU8sSUFBSSxTQUFTLE9BQU8sRUFBRTtFQUN6QyxNQUFNLGVBQWUsRUFBRSxHQUFHLFFBQVE7QUFDbEMsU0FBTyxLQUFLLE9BQU8sQ0FBQyxTQUFTLFFBQVE7QUFDcEMsT0FBSSxTQUFTLE9BQU8sS0FBSyxJQUFJLENBQUMsT0FBTyxLQUFLLFNBQ3pDLEtBQUksRUFBRSxPQUFPLFFBQ1osUUFBTyxPQUFPLGNBQWMsR0FBRyxNQUFNLE9BQU8sTUFBTSxDQUFDO09BRW5ELGNBQWEsT0FBTyxrQkFBa0IsT0FBTyxNQUFNLE9BQU8sS0FBSztZQUV0RCxNQUFNLFFBQVEsT0FBTyxLQUFLLENBQ3BDLGNBQWEsT0FBTyxlQUFlLE9BQU8sTUFBTSxPQUFPLEtBQUs7T0FFNUQsUUFBTyxPQUFPLGNBQWMsR0FBRyxNQUFNLE9BQU8sTUFBTSxDQUFDO0lBRW5EO0FBQ0YsU0FBTztZQUNHLE1BQU0sUUFBUSxPQUFPLElBQUksTUFBTSxRQUFRLE9BQU8sQ0FDeEQsUUFBTyxlQUFlLFFBQVEsT0FBTztBQUV0QyxRQUFPOztBQUVSLElBQU0sYUFBTixjQUF5QixJQUFJO0NBQzVCLFlBQVksV0FBVyxTQUFTO0FBQy9CLFFBQU0sUUFBUTtBQUNkLE9BQUssWUFBWTs7Q0FFbEIsSUFBSSxLQUFLO0FBQ1IsTUFBSSxDQUFDLEtBQUssSUFBSSxJQUFJLENBQ2pCLE1BQUssSUFBSSxLQUFLLEtBQUssVUFBVSxJQUFJLENBQUM7QUFFbkMsU0FBTyxNQUFNLElBQUksSUFBSTs7O0FBR3ZCLElBQU0sYUFBTixjQUF5QixXQUFXO0NBQ25DLGNBQWM7QUFDYixjQUFZLEVBQUU7O0NBT2Y7Q0FDQSxVQUFVO0FBQ1QsU0FBTyxLQUFLLFNBQVMsS0FBSyxPQUFPOztDQUVsQyxVQUFVLEtBQUs7QUFDZCxNQUFJLE9BQU8sS0FBSyxXQUFXLFlBQzFCLE1BQUs7QUFFTixPQUFLLElBQUksS0FBSyxLQUFLLElBQUksSUFBSSxHQUFHLEVBQUU7O0NBRWpDLFFBQVE7QUFDUCxNQUFJLE9BQU8sS0FBSyxXQUFXLFlBQzFCLFFBQU8sS0FBSztFQUViLElBQUksUUFBUTtBQUNaLE9BQUssTUFBTSxLQUFLLEtBQUssUUFBUSxDQUM1QixVQUFTO0FBRVYsU0FBTzs7O0FBSVQsU0FBUyxvQkFBb0IsR0FBRyxHQUFHO0FBQ2xDLFFBQU8sRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFOztBQUVuRSxJQUFNLGdCQUFOLE1BQU0sY0FBYztDQUNuQixZQUFZLElBQUksWUFBWTtDQUM1QjtDQUNBO0NBQ0E7Q0FDQTtDQUNBO0NBQ0E7Q0FDQSxnQkFBZ0IsSUFBSSxpQkFBaUIsRUFBRSxDQUFDO0NBQ3hDO0NBQ0E7Q0FDQTtDQUNBO0NBQ0E7Q0FDQTtDQUdBLFNBQVMsSUFBSSxZQUFZO0NBQ3pCLFdBQVcsSUFBSSxZQUFZO0NBQzNCLGFBQWEsSUFBSSxZQUFZO0NBQzdCLFdBQVcsSUFBSSxZQUFZO0NBQzNCLElBQUksUUFBUTtBQUNYLFNBQU8sS0FBSzs7Q0FFYixJQUFJLE1BQU0sT0FBTztBQUNoQixPQUFLLE9BQU8sU0FBUzs7Q0FFdEIsSUFBSSxVQUFVO0FBQ2IsU0FBTyxLQUFLOztDQUViLElBQUksUUFBUSxPQUFPO0FBQ2xCLE9BQUssU0FBUyxTQUFTOztDQUV4QixJQUFJLFlBQVk7QUFDZixTQUFPLEtBQUs7O0NBRWIsSUFBSSxVQUFVLE9BQU87QUFDcEIsT0FBSyxXQUFXLFNBQVM7O0NBRTFCLElBQUksVUFBVTtBQUNiLFNBQU8sS0FBSzs7Q0FFYixJQUFJLFFBQVEsT0FBTztBQUNsQixPQUFLLFNBQVMsU0FBUzs7Q0FFeEIsWUFBWSxjQUFjLGNBQWMsaUJBQWlCLFNBQVM7QUFDakUsT0FBSyxlQUFlO0FBQ3BCLE9BQUssZUFBZTtFQUNwQixNQUFNLEVBQUUsTUFBTSxVQUFVLGdCQUFnQixpQkFBaUIsUUFBUTtBQUNqRSxPQUFLLGNBQWMsbUJBQW1CO0FBQ3RDLE9BQUssZUFBZSxFQUFFLEdBQUcsTUFBTTtBQUMvQixPQUFLLGdCQUFnQixFQUFFLEdBQUcsTUFBTTtBQUNoQyxPQUFLLFNBQVM7QUFDZCxPQUFLLG1CQUFtQixFQUFFO0FBQzFCLE9BQUssd0JBQXdCLEVBQUU7QUFDL0IsT0FBSyxnQkFBZ0IsRUFBRTtBQUN2QixPQUFLLGlCQUFpQixJQUFJLElBQUksT0FBTyxLQUFLLEtBQUssY0FBYyxDQUFDO0FBQzlELE9BQUssU0FBUyxRQUFRLFVBQVU7QUFDaEMsT0FBSyxrQkFBa0IsUUFBUTtBQUMvQixPQUFLLGtCQUFrQjtHQUN0QixxQkFBcUI7R0FDckIsY0FBYztHQUNkLEdBQUcsUUFBUTtHQUNYO0FBQ0QsT0FBSyxlQUFlLFFBQVE7O0NBRTdCLGFBQWEsT0FBTyxjQUFjLFNBQVM7RUFDMUMsTUFBTSxlQUFlLE1BQU0sUUFBUSxvQkFBb0IsWUFBWSxhQUFhO0FBRWhGLFNBQU8sSUFBSSxjQUFjLGNBQWMsY0FEdkIsTUFBTSxRQUFRLG9CQUFvQixpQkFBaUIsYUFBYSxFQUNsQixRQUFROztDQUV2RSxJQUFJLGNBQWM7QUFDakIsU0FBTyxLQUFLOztDQUViLDhCQUE4QixVQUFVO0FBQ3ZDLE9BQUssZUFBZSxTQUFTLGlCQUFpQjtBQUk3QyxPQUFJLFlBQVksS0FBSyxhQUFhLE1BQU0sU0FBUyxPQUFPLENBQUMsQ0FDeEQsTUFBSyxlQUFlLE9BQU8sYUFBYTtJQUV4Qzs7Q0FFSCxVQUFVLFFBQVE7QUFFakIsT0FBSyxtQkFBbUIsS0FBSyxpQkFBaUIsUUFBUSxNQUFNLEVBQUUsV0FBVyxPQUFPO0FBQ2hGLE9BQUssd0JBQXdCLEtBQUssc0JBQXNCLFFBQVEsTUFBTSxFQUFFLFdBQVcsT0FBTztBQUUxRixPQUFLLE1BQU0sT0FBTyxLQUFLLGNBQWMsSUFBSSxPQUFPLEVBQUU7R0FDakQsTUFBTSxPQUFPLGNBQWMsSUFBSTtHQUMvQixNQUFNLFFBQVEsS0FBSyxVQUFVLElBQUksS0FBSztBQUN0QyxPQUFJLFFBQVEsR0FBRztBQUNkLFFBQUksT0FBTyxLQUFLLGlCQUFpQixPQUFPLEtBQUssYUFDNUMsTUFBSyxjQUFjLE9BQU8sS0FBSyxhQUFhO0FBRTdDLFNBQUssVUFBVSxJQUFJLE1BQU0sUUFBUSxFQUFFOzs7QUFHckMsT0FBSyxjQUFjLE9BQU8sT0FBTztBQUVqQyxPQUFLLE1BQU0sT0FBTyxPQUFPO0FBQ3pCLE9BQUssUUFBUSxPQUFPLE9BQU87QUFDM0IsT0FBSyxRQUFRLE9BQU8sT0FBTztBQUMzQixPQUFLLFVBQVUsT0FBTyxPQUFPOztDQUU5QiwwQkFBMEIsUUFBUTtFQUVqQyxNQUFNLGVBQWUsT0FBTyxXQUFXLE1BQU0sRUFBRSxPQUFPLE1BQU0sZ0NBQWdDLENBQUM7QUFDN0YsTUFBSSxpQkFBaUIsR0FDcEIsUUFBTyxPQUFPLGVBQWU7QUFJOUIsT0FBSyxJQUFJLElBQUksR0FBRyxJQUFJLE9BQU8sUUFBUSxLQUFLO0dBQ3ZDLE1BQU0sUUFBUSxPQUFPLEdBQUcsT0FBTyxNQUFNLG1DQUFtQztBQUN4RSxPQUFJLE1BQ0gsUUFBTyxPQUFPLElBQUksT0FBTyxNQUFNLEdBQUcsS0FBSzs7RUFLekMsTUFBTSxhQUFhLE9BQU8sV0FBVyxNQUFNLEVBQUUsT0FBTyxTQUFTLHNCQUFzQixDQUFDO0FBQ3BGLFNBQU8sZUFBZSxLQUFLLE9BQU8sYUFBYSxLQUFLOztDQUVyRCxhQUFhLEtBQUssb0JBQW9CLFNBQVM7QUFDOUMsT0FBSyxTQUFTO0FBQ2QsTUFBSSxRQUFRLE1BQ1gsTUFBSyxpQkFBaUIsS0FBSztHQUMxQixVQUFVO0dBQ1YsUUFBUSxRQUFRO0dBQ2hCLEdBQUcsUUFBUTtHQUNYLENBQUM7V0FDUSxRQUFRLFlBQ2xCLE1BQUssY0FBYyxLQUFLO0dBQ3ZCLEdBQUcsUUFBUTtHQUNYLFVBQVU7R0FDVixDQUFDO01BRUYsTUFBSyxjQUFjLE9BQU87O0NBRzVCLE1BQU0sT0FBTztFQUNaLE1BQU0sdUJBQXVCLE9BQU8sS0FBSyxLQUFLLGNBQWMsQ0FBQztFQUM3RCxNQUFNLHFCQUFxQixLQUFLLGlCQUFpQjtFQUNqRCxNQUFNLGtCQUFrQixLQUFLLGNBQWM7RUFDM0MsTUFBTSxVQUFVLENBQUMsd0JBQXdCLENBQUMsc0JBQXNCLENBQUM7RUFDakUsTUFBTSxTQUFTO0dBQ2QsU0FBUztHQUNULE9BQU87R0FDUDtBQUNELE9BQUssS0FBSyxVQUFVLEtBQUssZUFBZSxTQUFTLENBQUMsU0FBUztBQUMxRCxPQUFJLHNCQUFzQjtBQUN6QixVQUFNLGlCQUFpQixLQUFLLGNBQWMsS0FBSyxlQUFlLEtBQUssYUFBYTtBQUNoRixTQUFLLGNBQWM7O0FBRXBCLE9BQUksbUJBQ0gsT0FBTSxvQkFBb0IsS0FBSyxjQUFjLEtBQUssaUJBQWlCO0FBRXBFLE9BQUksZ0JBQ0gsT0FBTSxpQkFBaUIsS0FBSyxjQUFjLEtBQUssY0FBYztBQUU5RCxVQUFPLFFBQVE7YUFDTCxDQUFDLHdCQUF3QixLQUFLLGFBQWE7QUFDckQsT0FBSSxLQUFLLG9CQUFvQixPQUFPO0FBQ25DLFVBQU0sS0FBSyxhQUFhLG1CQUFtQixLQUFLLGFBQWE7QUFDN0QsU0FBSyxjQUFjOztBQUVwQixVQUFPLFVBQVU7O0FBRWxCLFNBQU87O0NBRVIsb0JBQW9CO0FBQ25CLFNBQU8sS0FBSyxlQUFlLFFBQVE7O0NBRXBDLG1CQUFtQjtBQUNsQixTQUFPLE1BQU0sS0FBSyxLQUFLLGVBQWU7O0NBRXZDLHNCQUFzQjtBQUNyQixNQUFJLEtBQUssb0JBQW9CLFNBQVMsS0FBSyxlQUFlLE1BQU07QUFDL0QsUUFBSyxTQUFTO0FBQ2QsUUFBSyxlQUFlLFNBQVMsUUFBUSxPQUFPLEtBQUssY0FBYyxLQUFLO0FBQ3BFLFFBQUssZUFBZSxPQUFPOzs7Q0FHN0IsTUFBTSxFQUFFLFFBQVEsVUFBVSxVQUFVLEtBQUssZ0JBQWdCLFVBQVUsT0FBTyxlQUFlO0FBRXhGLE9BQUssVUFBVSxVQUFVLFNBQVM7RUFDbEMsTUFBTSxRQUFRLEtBQUssVUFBVSxJQUFJLFNBQVM7QUFDMUMsTUFBSSxDQUFDLElBQ0osT0FBTSxjQUFjLFVBQVUsTUFBTTtBQUVyQyxPQUFLLGNBQWMsSUFBSSxPQUFPLENBQUMsS0FBSyxJQUFJO0FBSXhDLE1BQUksRUFBRSxZQUFZLEtBQUssY0FBYyxTQUFTLFFBQzdDLE1BQUssZUFBZSxPQUFPLElBQUk7RUFFaEMsSUFBSSxxQkFBcUIsZUFBZSxPQUFPLGFBQWEsV0FBVyxXQUFXLFVBQVUsVUFBVSxRQUFXLEtBQUssZ0JBQWdCO0FBQ3RJLE1BQUksQ0FBQyxZQUNKLHNCQUFxQixtQkFBbUIsbUJBQW1CO0FBRTVELE1BQUksYUFFSDtPQUFJLFlBQVksV0FBVyxZQUFZLFFBQVEsTUFBTSxPQUFPLElBQUksQ0FBQyxtQkFBbUIsTUFBTSxPQUFPLENBQ2hHLGFBQVksVUFBVSxrQkFBa0IsWUFBWSxRQUFROztFQUc5RCxNQUFNLFdBQVcsV0FBVyxpQkFBaUIsY0FBYyxZQUFZLFVBQVUsS0FBSyxjQUFjO0VBQ3BHLE1BQU0sa0JBQWtCLGNBQWMsV0FBVyxVQUFVLE1BQU07RUFDakUsTUFBTSxPQUFPLHFCQUFxQixjQUFjLHFCQUFxQixtQkFBbUIsTUFBTTtFQUM5RixNQUFNLGNBQWMsYUFBYTtFQUNqQyxNQUFNLHNCQUFzQixZQUFZLEtBQUssZUFBZSxlQUFlLFlBQVksV0FBVztBQUNsRyxNQUFJLFFBQVEsQ0FBQyxZQUFZLENBQUMsWUFPekIsTUFBSyxjQUFjLE9BQU87RUFHM0IsSUFBSTtBQUNKLE1BQUksVUFBVTtHQUNiLE1BQU0sU0FBUyxxQkFBcUIseUJBQVMsSUFBSSxNQUFNLFdBQVcsRUFBRSxFQUFFLG9CQUFvQixFQUFFLEVBQUUsQ0FBQztHQUMvRixNQUFNLFNBQVMsS0FBSywwQkFBMEIsT0FBTztBQUNyRCxPQUFJLENBQUMsT0FDSixPQUFNLElBQUksTUFBTSxzRUFBc0UsS0FBSyxVQUFVLE9BQU8sR0FBRztBQUVoSCxXQUFRLEtBQUssWUFBWSxvQkFBb0IsT0FBTyxJQUFJO0FBSXhELFNBQU07R0FFTixNQUFNLHlCQUF5QixLQUFLLHNCQUFzQixRQUFRLE1BQU0sb0JBQW9CLEdBQUcsTUFBTSxDQUFDO0FBQ3RHLE9BQUksdUJBQXVCLFNBQVMsR0FBRztBQUV0QyxTQUFLLG1CQUFtQixLQUFLLGlCQUFpQixRQUFRLE1BQU0sQ0FBQyxvQkFBb0IsR0FBRyxNQUFNLENBQUM7SUFDM0YsTUFBTSxvQkFBb0IsdUJBQXVCLE1BQU0sTUFBTSxFQUFFLGFBQWEsbUJBQW1CO0FBQy9GLFFBQUksa0JBQ0gsT0FBTSxPQUFPLHVCQUFPLElBQUksTUFBTSx1RkFBdUYsRUFBRTtLQUN0SCxRQUFRO0tBQ1IsVUFBVSxrQkFBa0I7S0FDNUIsQ0FBQzs7QUFHSixRQUFLLHNCQUFzQixLQUFLO0lBQy9CLEdBQUc7SUFDSDtJQUNBLFVBQVU7SUFDVixDQUFDOztBQVNILE1BQUksZUFBZSxLQUFLLG9CQUFvQixVQUFVLENBQUMsZUFBZSxDQUFDLHlCQUF5QixLQUFLLG9CQUFvQixTQUFTLEtBQUssb0JBQW9CLFFBQVE7QUFDbEssT0FBSSxLQUFLLG9CQUFvQixNQUM1QixLQUFJLENBQUMsTUFBTTtBQUNWLFFBQUksWUFDSCxNQUFLLFFBQVEsVUFBVSxPQUFPO1FBRTlCLE1BQUssTUFBTSxVQUFVLE9BQU87QUFFN0IsU0FBSyxhQUFhLEtBQUssb0JBQW9CO0tBQzFDO0tBQ0E7S0FDQTtLQUNBLENBQUM7U0FFRixNQUFLLFFBQVEsVUFBVSxPQUFPO1FBRXpCO0FBQ04sU0FBSyxhQUFhLEtBQUssb0JBQW9CO0tBQzFDO0tBQ0E7S0FDQTtLQUNBLENBQUM7QUFDRixTQUFLLE1BQU0sVUFBVSxPQUFPOztBQUU3QixVQUFPO0lBQ04sUUFBUTtJQUNSO0lBQ0EsVUFBVTtJQUNWO0lBQ0EsTUFBTTtJQUNOO2FBRUcsQ0FBQyxNQUFNO0FBQ1YsUUFBSyxVQUFVLFVBQVUsT0FBTztBQUNoQyxVQUFPO0lBQ04sUUFBUSxjQUFjLHFCQUFxQixzQkFBc0IsbUJBQW1CO0lBQ3BGO0lBQ0EsVUFBVSxvQkFBb0IsU0FBWSxjQUFjLGtCQUFrQixzQkFBc0IsZ0JBQWdCLEdBQUc7SUFDbkg7SUFDQSxNQUFNO0lBQ047U0FDSztBQUNOLFFBQUssUUFBUSxVQUFVLE9BQU87QUFDOUIsVUFBTztJQUNOLFFBQVE7SUFDUjtJQUNBLFVBQVU7SUFDVjtJQUNBLE1BQU07SUFDTjs7O0NBSUosTUFBTSxPQUFPO0VBQ1osTUFBTSxXQUFXO0dBQ2hCLFVBQVUsS0FBSztHQUNmLE9BQU87R0FDUCxhQUFhO0dBQ2IsU0FBUztHQUNULFdBQVc7R0FDWCxlQUFlLEVBQUU7R0FDakIsV0FBVztHQUNYLFNBQVM7R0FDVDtFQUNELE1BQU0saUJBQWlCLEtBQUssbUJBQW1CO0VBQy9DLE1BQU0sZ0JBQWdCLEtBQUssa0JBQWtCO0FBQzdDLE1BQUksZUFDSCxNQUFLLHFCQUFxQjtFQUUzQixNQUFNLFNBQVMsTUFBTSxLQUFLLE1BQU07QUFDaEMsV0FBUyxjQUFjLE9BQU87QUFDOUIsV0FBUyxRQUFRLEtBQUssTUFBTSxPQUFPO0FBQ25DLFdBQVMsVUFBVSxLQUFLLFFBQVEsT0FBTztBQUN2QyxXQUFTLFlBQVksS0FBSyxVQUFVLE9BQU87QUFDM0MsV0FBUyxVQUFVLEtBQUssUUFBUSxPQUFPO0FBQ3ZDLFdBQVMsWUFBWSxDQUFDLE9BQU8sVUFBVSxpQkFBaUI7QUFDeEQsV0FBUyxnQkFBZ0IsTUFBTSxLQUFLLGNBQWM7QUFDbEQsU0FBTzs7O0FBSVQsU0FBUyxvQkFBb0IsU0FBUyxRQUFRLFFBQVEsVUFBVTtDQUMvRCxNQUFNLFFBQVEsSUFBSSxNQUFNLFFBQVE7QUFDaEMsUUFBTyxlQUFlLE9BQU8sVUFBVTtFQUN0QyxPQUFPO0VBQ1AsWUFBWTtFQUNaLGNBQWM7RUFDZCxVQUFVO0VBQ1YsQ0FBQztBQUNGLFFBQU8sZUFBZSxPQUFPLFlBQVk7RUFDeEMsT0FBTztFQUNQLFlBQVk7RUFDWixjQUFjO0VBQ2QsVUFBVTtFQUNWLENBQUM7QUFDRixRQUFPLGVBQWUsT0FBTyxlQUFlLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxDQUFDO0FBQ2xFLFFBQU87O0FBRVIsSUFBTSxpQkFBTixNQUFxQjtDQUNwQixtQ0FBbUIsSUFBSSxLQUFLO0NBQzVCLFlBQVksVUFBVSxFQUFFLEVBQUU7QUFDekIsT0FBSyxVQUFVOztDQUVoQixNQUFNLE1BQU0sVUFBVSxTQUFTO0FBQzlCLE1BQUksS0FBSyxpQkFBaUIsSUFBSSxTQUFTLENBQ3RDO0FBRUQsT0FBSyxpQkFBaUIsSUFBSSxVQUFVLE1BQU0sY0FBYyxPQUFPLFVBQVUsUUFBUSxDQUFDOztDQUVuRixNQUFNLE9BQU8sVUFBVTtFQUV0QixNQUFNLFNBQVMsTUFERCxLQUFLLGlCQUFpQixTQUFTLENBQ2xCLE1BQU07QUFDakMsT0FBSyxpQkFBaUIsT0FBTyxTQUFTO0FBQ3RDLFNBQU87O0NBRVIsU0FBUyxVQUFVLFVBQVU7QUFFNUIsRUFEYyxLQUFLLGlCQUFpQixTQUFTLENBQ3ZDLDhCQUE4QixTQUFTOztDQUU5QyxVQUFVLFVBQVUsUUFBUTtBQUUzQixFQURjLEtBQUssaUJBQWlCLFNBQVMsQ0FDdkMsVUFBVSxPQUFPOztDQUV4QixpQkFBaUIsVUFBVTtFQUMxQixNQUFNLFFBQVEsS0FBSyxpQkFBaUIsSUFBSSxTQUFTO0FBQ2pELE1BQUksQ0FBQyxNQUNKLE9BQU0sSUFBSSxNQUFNLDJCQUEyQixTQUFTLHdEQUF3RDtBQUU3RyxTQUFPOztDQUVSLE9BQU8sU0FBUztFQUNmLE1BQU0sRUFBRSxVQUFVLE1BQU0sU0FBUyxNQUFNLFNBQVMsV0FBVyxPQUFPLFlBQVksZ0JBQWdCLE9BQU8sY0FBYyxnQkFBZ0I7RUFDbkksSUFBSSxFQUFFLGFBQWE7QUFDbkIsTUFBSSxDQUFDLFNBQ0osT0FBTSxJQUFJLE1BQU0sMENBQTBDO0VBRTNELE1BQU0sZ0JBQWdCLEtBQUssaUJBQWlCLFNBQVM7QUFDckQsTUFBSSxPQUFPLGVBQWUsVUFBVTtBQUNuQyxPQUFJLE9BQU8sYUFBYSxZQUFZLENBQUMsU0FDcEMsT0FBTSxJQUFJLE1BQU0sbUVBQW1FO0FBRXBGLE9BQUk7QUFHSCxRQUFJLEVBRlMsS0FBSyxRQUFRLFVBQVUsVUFBVSxXQUFXLElBQUksT0FHNUQsT0FBTSxvQkFBb0Isa0NBQWtDLGNBQWMsUUFBUSxVQUFVLFdBQVc7UUFFdkcsWUFBVyxrQkFBa0IsVUFBVSxXQUFXO1lBRTNDLEtBQUs7QUFDYixRQUFJLFVBQVUsZ0JBQWdCO0FBQzlCLFVBQU07OztFQUdSLE1BQU0sV0FBVyxDQUFDLE1BQU0sR0FBRyxVQUFVLENBQUMsUUFBUSxHQUFHLEVBQUUsQ0FBQyxDQUFDLEtBQUssTUFBTTtFQUNoRSxNQUFNLEVBQUUsUUFBUSxVQUFVLEtBQUssU0FBUyxjQUFjLE1BQU07R0FDM0Q7R0FDQTtHQUNBO0dBQ0E7R0FDQTtHQUNBO0dBQ0E7R0FDQSxDQUFDO0FBQ0YsTUFBSSxDQUFDLEtBQ0osT0FBTSxvQkFBb0IsY0FBYyxPQUFPLFVBQVUsZ0JBQWdCLGNBQWMsUUFBUSxjQUFjLFNBQVMsUUFBUSxNQUFNLEVBQUUsY0FBYyxXQUFXLFVBQVUsTUFBTSxDQUFDOztDQUdsTCxNQUFNLFVBQVUsU0FBUztBQUN4QixNQUFJLENBQUMsUUFBUSxZQUNaLE9BQU0sSUFBSSxNQUFNLDJCQUEyQjtFQUU1QyxNQUFNLEVBQUUsVUFBVSxnQkFBZ0I7QUFDbEMsTUFBSSxZQUFZLFdBQVcsTUFBTTtBQUNoQyxPQUFJLENBQUMsU0FDSixPQUFNLElBQUksTUFBTSwwQ0FBMEM7R0FFM0QsTUFBTSxnQkFBZ0IsS0FBSyxpQkFBaUIsU0FBUztBQUVyRCxXQUFRLGFBQWE7QUFFckIsZUFBWSxPQUFPLE1BQU0sY0FBYyxZQUFZLGVBQWUsVUFBVSxZQUFZLEtBQUs7QUFDN0YsZUFBWSxVQUFVLE1BQU0sY0FBYyxZQUFZLGlCQUFpQixZQUFZLEtBQUssSUFBSTs7QUFFN0YsU0FBTyxLQUFLLE9BQU8sUUFBUTs7Q0FFNUIsUUFBUTtBQUNQLE9BQUssaUJBQWlCLE9BQU8ifQ==
|