@cartanova/qgrid-cli 2.5.3 → 2.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +7 -2
- package/README.md +7 -2
- package/bundle/dist/application/monit/monit.frame.js +3 -3
- package/bundle/dist/application/qgrid/oauth.js +1 -1
- package/bundle/dist/application/qgrid/qgrid.dispatcher.js +36 -14
- package/bundle/dist/application/qgrid/qgrid.frame.js +19 -5
- package/bundle/dist/application/qgrid/tool-emulation-schema.js +121 -0
- package/bundle/dist/application/qgrid/tool-emulation.js +116 -96
- package/bundle/dist/application/request-log/request-log.model.js +3 -3
- package/bundle/dist/application/request-log-step/request-log-step.model.js +2 -2
- package/bundle/dist/application/token/token.model.js +2 -2
- package/bundle/dist/server-error-handler.js +15 -0
- package/bundle/dist/sonamu.config.js +4 -7
- package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +4 -3
- package/bundle/dist/utils/providers/anthropic/claude-session.js +7 -5
- package/bundle/dist/utils/providers/common/schema-validation.js +178 -0
- package/bundle/dist/utils/providers/common/strictifier.js +329 -42
- package/bundle/dist/utils/providers/openai/codex-worker.js +16 -8
- package/bundle/dist/utils/providers/openai/openai-dispatcher.js +5 -37
- package/bundle/dist/utils/providers/openai/openai-worker-pool-config.js +37 -0
- package/bundle/src/application/monit/monit.frame.ts +1 -1
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +103 -0
- package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +337 -0
- package/bundle/src/application/qgrid/qgrid.dispatcher.ts +45 -25
- package/bundle/src/application/qgrid/qgrid.frame.test.ts +580 -8
- package/bundle/src/application/qgrid/qgrid.frame.ts +28 -1
- package/bundle/src/application/qgrid/tool-emulation-schema.test.ts +188 -0
- package/bundle/src/application/qgrid/tool-emulation-schema.ts +176 -0
- package/bundle/src/application/qgrid/tool-emulation.test.ts +285 -67
- package/bundle/src/application/qgrid/tool-emulation.ts +199 -102
- package/bundle/src/server-error-handler.ts +22 -0
- package/bundle/src/sonamu.config.test.ts +37 -0
- package/bundle/src/sonamu.config.ts +2 -5
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.test.ts +44 -0
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +2 -2
- package/bundle/src/utils/providers/anthropic/claude-session.test.ts +10 -0
- package/bundle/src/utils/providers/anthropic/claude-session.ts +6 -1
- package/bundle/src/utils/providers/common/schema-validation.test.ts +284 -0
- package/bundle/src/utils/providers/common/schema-validation.ts +308 -0
- package/bundle/src/utils/providers/common/strictifier.test.ts +746 -0
- package/bundle/src/utils/providers/common/strictifier.ts +513 -52
- package/bundle/src/utils/providers/openai/codex-worker.test.ts +31 -0
- package/bundle/src/utils/providers/openai/codex-worker.ts +12 -4
- package/bundle/src/utils/providers/openai/openai-dispatcher.test.ts +6 -4
- package/bundle/src/utils/providers/openai/openai-dispatcher.ts +6 -79
- package/bundle/src/utils/providers/openai/openai-worker-pool-config.ts +80 -0
- package/bundle/web-dist/client/assets/{index-DXdGBfB8.js → index-DiY5V2e3.js} +3 -3
- package/bundle/web-dist/client/assets/{logs-D_j1yxC4.js → logs-UZ4Cvdmc.js} +1 -1
- package/bundle/web-dist/client/assets/{monit-CIToyoxW.js → monit-C5cJo-HD.js} +1 -1
- package/bundle/web-dist/client/assets/{routes-Dd21A-wi.js → routes-DEKEmoQN.js} +1 -1
- package/bundle/web-dist/client/assets/{show-DfePWRbc.js → show-DnX6b8KG.js} +1 -1
- package/bundle/web-dist/client/assets/{tokens-B4MV2fdk.js → tokens-Ct0FGD4b.js} +1 -1
- package/bundle/web-dist/client/index.html +1 -1
- package/bundle/web-dist/server/entry-server.generated.js +1 -1
- package/package.json +1 -1
- package/skills/qgrid/references/ai-sdk-provider-contract.md +34 -2
- package/skills/qgrid/references/anthropic-claude-code-runtime.md +3 -0
- package/skills/qgrid/references/cli-env-and-server-boot.md +1 -1
- package/skills/qgrid/references/decision-rationale.md +10 -1
- package/skills/qgrid/references/repo-map.md +2 -1
- package/skills/qgrid/references/tool-calling-and-multiturn.md +33 -6
- package/skills/qgrid/references/verification-and-debugging.md +16 -1
|
@@ -7,44 +7,252 @@ var StrictifierError = class extends Error {
|
|
|
7
7
|
this.name = "StrictifierError";
|
|
8
8
|
}
|
|
9
9
|
};
|
|
10
|
-
function strictify(schema) {
|
|
11
|
-
|
|
10
|
+
function strictify(schema, options = {}) {
|
|
11
|
+
if (options.provider === "openai" || options.provider === "anthropic") assertNormalizationCompatibility(schema, options.provider);
|
|
12
|
+
const result = strictifyNode(schema, "$", options.provider);
|
|
13
|
+
if (options.provider === "openai" || options.provider === "anthropic") assertNormalizationCompatibility(result, options.provider);
|
|
14
|
+
return result;
|
|
12
15
|
}
|
|
13
|
-
|
|
16
|
+
const SCHEMA_SCAN_MAP_KEYWORDS = [
|
|
17
|
+
["$defs", true],
|
|
18
|
+
["definitions", true],
|
|
19
|
+
["properties", true],
|
|
20
|
+
["dependentSchemas", false],
|
|
21
|
+
["patternProperties", false]
|
|
22
|
+
];
|
|
23
|
+
const SCHEMA_SCAN_ARRAY_KEYWORDS = [
|
|
24
|
+
["allOf", true],
|
|
25
|
+
["anyOf", true],
|
|
26
|
+
["oneOf", true],
|
|
27
|
+
["prefixItems", true]
|
|
28
|
+
];
|
|
29
|
+
const SCHEMA_SCAN_SINGLE_KEYWORDS = [
|
|
30
|
+
["additionalProperties", false],
|
|
31
|
+
["contains", false],
|
|
32
|
+
["contentSchema", false],
|
|
33
|
+
["else", false],
|
|
34
|
+
["if", false],
|
|
35
|
+
["not", false],
|
|
36
|
+
["propertyNames", false],
|
|
37
|
+
["then", false],
|
|
38
|
+
["unevaluatedItems", false],
|
|
39
|
+
["unevaluatedProperties", false]
|
|
40
|
+
];
|
|
41
|
+
/**
|
|
42
|
+
* Inspect every JSON Schema-bearing position without rewriting it.
|
|
43
|
+
*
|
|
44
|
+
* Positive positions already traversed by strictifyNode may normalize OpenAI tuples. Positions
|
|
45
|
+
* such as `not` and `if` cannot be tightened without changing caller semantics, so positional
|
|
46
|
+
* tuples there fail explicitly instead of leaking an unsupported provider schema. References
|
|
47
|
+
* from those positions also fail because their definitions are normalized globally.
|
|
48
|
+
*/
|
|
49
|
+
function assertNormalizationCompatibility(schema, provider) {
|
|
50
|
+
const references = [];
|
|
51
|
+
const stack = [{
|
|
52
|
+
node: schema,
|
|
53
|
+
path: "$",
|
|
54
|
+
normalizable: true
|
|
55
|
+
}];
|
|
56
|
+
while (stack.length > 0) {
|
|
57
|
+
const current = stack.pop();
|
|
58
|
+
const itemsValue = ownValue(current.node, "items");
|
|
59
|
+
const prefixItemsValue = ownValue(current.node, "prefixItems");
|
|
60
|
+
const legacyTuple = Array.isArray(itemsValue);
|
|
61
|
+
const prefixTuple = Array.isArray(prefixItemsValue);
|
|
62
|
+
assertUnsupportedReferenceKeywords(current.node, current.path);
|
|
63
|
+
collectSchemaReference(current, references);
|
|
64
|
+
if (legacyTuple || prefixTuple) {
|
|
65
|
+
if (provider === "anthropic" && (legacyTuple ? itemsValue : prefixItemsValue).length > 0) throw new StrictifierError("positional tuple schemas are not supported on Anthropic because Claude Code cannot preserve item positions", current.path);
|
|
66
|
+
if (!current.normalizable) throw new StrictifierError("positional tuple schemas are not supported in this schema position", current.path);
|
|
67
|
+
if (ownValue(current.node, "type") !== "array") throw new StrictifierError("positional tuple schemas must declare type \"array\"; express nullable tuples with anyOf", `${current.path}.type`);
|
|
68
|
+
}
|
|
69
|
+
for (const [keyword, keywordNormalizable] of SCHEMA_SCAN_MAP_KEYWORDS) {
|
|
70
|
+
const schemas = ownValue(current.node, keyword);
|
|
71
|
+
if (!isSchemaObject(schemas)) continue;
|
|
72
|
+
for (const [name, child] of Object.entries(schemas)) {
|
|
73
|
+
if (!isSchemaObject(child)) continue;
|
|
74
|
+
stack.push({
|
|
75
|
+
node: child,
|
|
76
|
+
path: `${current.path}.${keyword}.${name}`,
|
|
77
|
+
normalizable: current.normalizable && keywordNormalizable
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const dependencies = ownValue(current.node, "dependencies");
|
|
82
|
+
if (isSchemaObject(dependencies)) for (const [name, child] of Object.entries(dependencies)) {
|
|
83
|
+
if (!isSchemaObject(child)) continue;
|
|
84
|
+
stack.push({
|
|
85
|
+
node: child,
|
|
86
|
+
path: `${current.path}.dependencies.${name}`,
|
|
87
|
+
normalizable: false
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
for (const [keyword, keywordNormalizable] of SCHEMA_SCAN_ARRAY_KEYWORDS) {
|
|
91
|
+
const schemas = ownValue(current.node, keyword);
|
|
92
|
+
if (!Array.isArray(schemas)) continue;
|
|
93
|
+
for (let index = 0; index < schemas.length; index += 1) {
|
|
94
|
+
const child = schemas[index];
|
|
95
|
+
if (!isSchemaObject(child)) continue;
|
|
96
|
+
stack.push({
|
|
97
|
+
node: child,
|
|
98
|
+
path: `${current.path}.${keyword}[${index}]`,
|
|
99
|
+
normalizable: current.normalizable && keywordNormalizable
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const items = ownValue(current.node, "items");
|
|
104
|
+
if (isSchemaObject(items)) stack.push({
|
|
105
|
+
node: items,
|
|
106
|
+
path: `${current.path}.items`,
|
|
107
|
+
normalizable: current.normalizable
|
|
108
|
+
});
|
|
109
|
+
else if (Array.isArray(items)) for (let index = 0; index < items.length; index += 1) {
|
|
110
|
+
const child = items[index];
|
|
111
|
+
if (!isSchemaObject(child)) continue;
|
|
112
|
+
stack.push({
|
|
113
|
+
node: child,
|
|
114
|
+
path: `${current.path}.items[${index}]`,
|
|
115
|
+
normalizable: current.normalizable
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
const additionalItems = ownValue(current.node, "additionalItems");
|
|
119
|
+
if (isSchemaObject(additionalItems)) stack.push({
|
|
120
|
+
node: additionalItems,
|
|
121
|
+
path: `${current.path}.additionalItems`,
|
|
122
|
+
normalizable: current.normalizable && legacyTuple
|
|
123
|
+
});
|
|
124
|
+
for (const [keyword, keywordNormalizable] of SCHEMA_SCAN_SINGLE_KEYWORDS) {
|
|
125
|
+
const child = ownValue(current.node, keyword);
|
|
126
|
+
if (!isSchemaObject(child)) continue;
|
|
127
|
+
stack.push({
|
|
128
|
+
node: child,
|
|
129
|
+
path: `${current.path}.${keyword}`,
|
|
130
|
+
normalizable: current.normalizable && keywordNormalizable
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
assertReferenceTargets(schema, references);
|
|
135
|
+
}
|
|
136
|
+
const UNSUPPORTED_REFERENCE_KEYWORDS = [
|
|
137
|
+
"$id",
|
|
138
|
+
"id",
|
|
139
|
+
"$anchor",
|
|
140
|
+
"$dynamicAnchor",
|
|
141
|
+
"$recursiveAnchor",
|
|
142
|
+
"$dynamicRef",
|
|
143
|
+
"$recursiveRef"
|
|
144
|
+
];
|
|
145
|
+
function assertUnsupportedReferenceKeywords(schema, path) {
|
|
146
|
+
for (const keyword of UNSUPPORTED_REFERENCE_KEYWORDS) if (Object.hasOwn(schema, keyword)) throw new StrictifierError(`${keyword} is not supported`, `${path}.${keyword}`);
|
|
147
|
+
}
|
|
148
|
+
function collectSchemaReference(current, references) {
|
|
149
|
+
if (!Object.hasOwn(current.node, "$ref")) return;
|
|
150
|
+
const reference = current.node.$ref;
|
|
151
|
+
if (typeof reference !== "string") throw new StrictifierError("$ref must be a string", `${current.path}.$ref`);
|
|
152
|
+
if (!current.normalizable) throw new StrictifierError("schema references are not supported in this schema position", current.path);
|
|
153
|
+
references.push({
|
|
154
|
+
value: reference,
|
|
155
|
+
path: `${current.path}.$ref`
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
function assertReferenceTargets(root, references) {
|
|
159
|
+
for (const reference of references) {
|
|
160
|
+
const tokens = parseLocalJsonPointer(reference.value, reference.path);
|
|
161
|
+
if (!isDefinitionRootPointer(tokens)) throw new StrictifierError("$ref target must be the document root or a definition root", reference.path);
|
|
162
|
+
resolveDefinitionRoot(root, tokens, reference.path);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function isDefinitionRootPointer(tokens) {
|
|
166
|
+
if (tokens.length === 0) return true;
|
|
167
|
+
if (tokens.length % 2 !== 0) return false;
|
|
168
|
+
for (let index = 0; index < tokens.length; index += 2) if (tokens[index] !== "$defs" && tokens[index] !== "definitions") return false;
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
function parseLocalJsonPointer(reference, path) {
|
|
172
|
+
if (reference === "#") return [];
|
|
173
|
+
if (!reference.startsWith("#/")) throw new StrictifierError("only local root-relative JSON Pointer $ref values are supported", path);
|
|
174
|
+
let fragment;
|
|
175
|
+
try {
|
|
176
|
+
fragment = decodeURIComponent(reference.slice(1));
|
|
177
|
+
} catch {
|
|
178
|
+
throw new StrictifierError("$ref contains invalid percent encoding", path);
|
|
179
|
+
}
|
|
180
|
+
if (!fragment.startsWith("/")) throw new StrictifierError("only local root-relative JSON Pointer $ref values are supported", path);
|
|
181
|
+
return fragment.slice(1).split("/").map((token) => decodeJsonPointerToken(token, path));
|
|
182
|
+
}
|
|
183
|
+
function resolveDefinitionRoot(root, tokens, path) {
|
|
184
|
+
let current = root;
|
|
185
|
+
for (let index = 0; index < tokens.length; index += 2) {
|
|
186
|
+
const keyword = tokens[index];
|
|
187
|
+
const name = tokens[index + 1];
|
|
188
|
+
const definitions = ownValue(current, keyword);
|
|
189
|
+
if (!isSchemaObject(definitions) || !Object.hasOwn(definitions, name)) throw new StrictifierError("$ref does not resolve inside the caller schema", path);
|
|
190
|
+
const target = definitions[name];
|
|
191
|
+
if (!isSchemaObject(target)) throw new StrictifierError("$ref target must be an object schema", path);
|
|
192
|
+
current = target;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
function decodeJsonPointerToken(rawToken, path) {
|
|
196
|
+
let token = "";
|
|
197
|
+
for (let index = 0; index < rawToken.length; index += 1) {
|
|
198
|
+
const character = rawToken[index];
|
|
199
|
+
if (character !== "~") {
|
|
200
|
+
token += character;
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
const escaped = rawToken[index + 1];
|
|
204
|
+
if (escaped === "0") token += "~";
|
|
205
|
+
else if (escaped === "1") token += "/";
|
|
206
|
+
else throw new StrictifierError("$ref contains an invalid JSON Pointer escape", path);
|
|
207
|
+
index += 1;
|
|
208
|
+
}
|
|
209
|
+
return token;
|
|
210
|
+
}
|
|
211
|
+
function strictifyNode(node, path, provider) {
|
|
14
212
|
if (typeof node !== "object" || node === null) return node;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if (type === "
|
|
18
|
-
if (
|
|
19
|
-
|
|
20
|
-
anyOf: node.anyOf.map((s, i) => strictifyNode(s, `${path}.anyOf[${i}]`))
|
|
21
|
-
};
|
|
22
|
-
if (node.oneOf) return {
|
|
23
|
-
...node,
|
|
24
|
-
oneOf: node.oneOf.map((s, i) => strictifyNode(s, `${path}.oneOf[${i}]`))
|
|
25
|
-
};
|
|
26
|
-
if (node.allOf) return {
|
|
27
|
-
...node,
|
|
28
|
-
allOf: node.allOf.map((s, i) => strictifyNode(s, `${path}.allOf[${i}]`))
|
|
29
|
-
};
|
|
30
|
-
if (node.$ref) return { ...node };
|
|
31
|
-
return { ...node };
|
|
213
|
+
let result = strictifySchemaMaps(provider === "openai" ? omitKeys(node, ["$schema"]) : node, path, provider);
|
|
214
|
+
const type = ownValue(result, "type");
|
|
215
|
+
if (type === "object" || Object.hasOwn(result, "properties")) result = strictifyObject(result, path, provider);
|
|
216
|
+
if (type === "array" || Object.hasOwn(result, "items") || Object.hasOwn(result, "prefixItems")) result = strictifyArray(result, path, provider);
|
|
217
|
+
return strictifySchemaArrays(result, path, provider);
|
|
32
218
|
}
|
|
33
|
-
|
|
34
|
-
|
|
219
|
+
const SCHEMA_MAP_KEYWORDS = ["$defs", "definitions"];
|
|
220
|
+
function strictifySchemaMaps(node, path, provider) {
|
|
221
|
+
const result = { ...node };
|
|
222
|
+
for (const keyword of SCHEMA_MAP_KEYWORDS) {
|
|
223
|
+
const schemas = ownValue(node, keyword);
|
|
224
|
+
if (!isSchemaObject(schemas)) continue;
|
|
225
|
+
result[keyword] = Object.fromEntries(Object.entries(schemas).map(([name, schema]) => [name, isSchemaObject(schema) ? strictifyNode(schema, `${path}.${keyword}.${name}`, provider) : schema]));
|
|
226
|
+
}
|
|
227
|
+
return result;
|
|
228
|
+
}
|
|
229
|
+
const SCHEMA_ARRAY_KEYWORDS = [
|
|
230
|
+
"anyOf",
|
|
231
|
+
"oneOf",
|
|
232
|
+
"allOf"
|
|
233
|
+
];
|
|
234
|
+
function strictifySchemaArrays(node, path, provider) {
|
|
235
|
+
const result = { ...node };
|
|
236
|
+
for (const keyword of SCHEMA_ARRAY_KEYWORDS) {
|
|
237
|
+
const schemas = ownValue(node, keyword);
|
|
238
|
+
if (!schemas) continue;
|
|
239
|
+
result[keyword] = schemas.map((schema, index) => strictifyNode(schema, `${path}.${keyword}[${index}]`, provider));
|
|
240
|
+
}
|
|
241
|
+
return result;
|
|
242
|
+
}
|
|
243
|
+
function strictifyObject(node, path, provider) {
|
|
244
|
+
const properties = ownValue(node, "properties");
|
|
35
245
|
if (!properties) return {
|
|
36
246
|
...node,
|
|
37
247
|
additionalProperties: false
|
|
38
248
|
};
|
|
39
|
-
const existingRequired = new Set(node
|
|
249
|
+
const existingRequired = new Set(ownValue(node, "required") ?? []);
|
|
40
250
|
const allKeys = Object.keys(properties);
|
|
41
|
-
const strictProps = {
|
|
42
|
-
for (const key of allKeys) {
|
|
251
|
+
const strictProps = Object.fromEntries(allKeys.map((key) => {
|
|
43
252
|
const prop = properties[key];
|
|
44
|
-
const strictProp = strictifyNode(prop, `${path}.${key}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
253
|
+
const strictProp = strictifyNode(prop, `${path}.${key}`, provider);
|
|
254
|
+
return [key, existingRequired.has(key) ? strictProp : makeNullable(strictProp)];
|
|
255
|
+
}));
|
|
48
256
|
return {
|
|
49
257
|
...node,
|
|
50
258
|
type: "object",
|
|
@@ -53,24 +261,103 @@ function strictifyObject(node, path) {
|
|
|
53
261
|
additionalProperties: false
|
|
54
262
|
};
|
|
55
263
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (
|
|
264
|
+
const UNREACHABLE_TUPLE_TAIL_SCHEMA = { type: "string" };
|
|
265
|
+
function strictifyArray(node, path, provider) {
|
|
266
|
+
if ((provider === "openai" || provider === "anthropic") && (Array.isArray(ownValue(node, "items")) || Array.isArray(ownValue(node, "prefixItems")))) return normalizeTuple(node, path, provider);
|
|
267
|
+
const result = { ...node };
|
|
268
|
+
const items = ownValue(node, "items");
|
|
269
|
+
if (Array.isArray(items)) result.items = items.map((schema, index) => strictifyNode(schema, `${path}.items[${index}]`, provider));
|
|
270
|
+
else if (items !== void 0) result.items = strictifyNode(items, `${path}.items`, provider);
|
|
271
|
+
const prefixItems = ownValue(node, "prefixItems");
|
|
272
|
+
if (Array.isArray(prefixItems)) result.prefixItems = prefixItems.map((schema, index) => strictifyNode(schema, `${path}.prefixItems[${index}]`, provider));
|
|
273
|
+
return result;
|
|
274
|
+
}
|
|
275
|
+
function normalizeTuple(node, path, provider) {
|
|
276
|
+
const items = ownValue(node, "items");
|
|
277
|
+
const prefixItems = ownValue(node, "prefixItems");
|
|
278
|
+
const legacyTuple = Array.isArray(items);
|
|
279
|
+
const prefixTuple = Array.isArray(prefixItems);
|
|
280
|
+
if (legacyTuple && prefixTuple) throw new StrictifierError("items and prefixItems tuple forms cannot be combined", path);
|
|
281
|
+
if (prefixTuple && Object.hasOwn(node, "additionalItems")) throw new StrictifierError("additionalItems cannot be combined with prefixItems", path);
|
|
282
|
+
const rawTuple = legacyTuple ? items : prefixItems;
|
|
283
|
+
const tuplePath = legacyTuple ? `${path}.items` : `${path}.prefixItems`;
|
|
284
|
+
const tuple = rawTuple.map((schema, index) => {
|
|
285
|
+
if (!isSchemaObject(schema)) throw new StrictifierError("boolean and non-object tuple member schemas are not supported", `${tuplePath}[${index}]`);
|
|
286
|
+
const memberPath = `${tuplePath}[${index}]`;
|
|
287
|
+
const member = strictifyNode(schema, memberPath, provider);
|
|
288
|
+
if (!hasProviderSchemaEntryPoint(member)) throw new StrictifierError("tuple member must define a provider-representable schema", memberPath);
|
|
289
|
+
return member;
|
|
290
|
+
});
|
|
291
|
+
const rawTail = legacyTuple ? ownValue(node, "additionalItems") : items;
|
|
292
|
+
if (rawTail === true) throw new StrictifierError("an unrestricted tuple rest is not supported", path);
|
|
293
|
+
if (rawTail !== void 0 && rawTail !== false && !isSchemaObject(rawTail)) throw new StrictifierError("tuple rest must be an object schema or false", path);
|
|
294
|
+
const tail = isSchemaObject(rawTail) ? strictifyNode(rawTail, legacyTuple ? `${path}.additionalItems` : `${path}.items`, provider) : void 0;
|
|
295
|
+
if (tail !== void 0 && !hasProviderSchemaEntryPoint(tail)) throw new StrictifierError("an unrestricted tuple rest is not supported", path);
|
|
296
|
+
const tailMode = tail !== void 0 ? "typed" : rawTail === false ? "closed" : "implicit";
|
|
297
|
+
const bounds = normalizeTupleBounds(node, tuple.length, tailMode, path);
|
|
59
298
|
return {
|
|
60
|
-
...node,
|
|
61
|
-
|
|
299
|
+
...omitKeys(node, [
|
|
300
|
+
"items",
|
|
301
|
+
"prefixItems",
|
|
302
|
+
"additionalItems",
|
|
303
|
+
"minItems",
|
|
304
|
+
"maxItems"
|
|
305
|
+
]),
|
|
306
|
+
...tuple.length > 0 ? { prefixItems: tuple } : {},
|
|
307
|
+
items: tail ?? UNREACHABLE_TUPLE_TAIL_SCHEMA,
|
|
308
|
+
...bounds
|
|
62
309
|
};
|
|
63
310
|
}
|
|
311
|
+
function normalizeTupleBounds(node, tupleLength, tailMode, path) {
|
|
312
|
+
const callerMinItems = integerBound(ownValue(node, "minItems"), "minItems", path);
|
|
313
|
+
const callerMaxItems = integerBound(ownValue(node, "maxItems"), "maxItems", path);
|
|
314
|
+
if (tailMode === "implicit" && callerMaxItems !== void 0 && callerMaxItems > tupleLength) throw new StrictifierError("implicit tuple rest cannot be represented when maxItems exceeds the tuple length", path);
|
|
315
|
+
const minItems = callerMinItems ?? (callerMaxItems === void 0 ? tupleLength : 0);
|
|
316
|
+
const maxItems = tailMode === "typed" ? callerMaxItems : Math.min(callerMaxItems ?? tupleLength, tupleLength);
|
|
317
|
+
if (maxItems !== void 0 && minItems > maxItems) throw new StrictifierError("tuple minItems cannot exceed maxItems", path);
|
|
318
|
+
return {
|
|
319
|
+
minItems,
|
|
320
|
+
...maxItems !== void 0 ? { maxItems } : {}
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
function integerBound(value, keyword, path) {
|
|
324
|
+
if (value === void 0) return void 0;
|
|
325
|
+
if (!Number.isSafeInteger(value) || value < 0) throw new StrictifierError(`${keyword} must be a non-negative safe integer`, path);
|
|
326
|
+
return value;
|
|
327
|
+
}
|
|
328
|
+
function isSchemaObject(value) {
|
|
329
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
330
|
+
}
|
|
331
|
+
function ownValue(schema, keyword) {
|
|
332
|
+
return Object.hasOwn(schema, keyword) ? schema[keyword] : void 0;
|
|
333
|
+
}
|
|
334
|
+
const PROVIDER_SCHEMA_ENTRY_POINT_KEYWORDS = /* @__PURE__ */ new Set([
|
|
335
|
+
"type",
|
|
336
|
+
"$ref",
|
|
337
|
+
"properties",
|
|
338
|
+
"anyOf",
|
|
339
|
+
"oneOf",
|
|
340
|
+
"allOf"
|
|
341
|
+
]);
|
|
342
|
+
function hasProviderSchemaEntryPoint(schema) {
|
|
343
|
+
return Object.keys(schema).some((key) => PROVIDER_SCHEMA_ENTRY_POINT_KEYWORDS.has(key));
|
|
344
|
+
}
|
|
345
|
+
function omitKeys(node, keys) {
|
|
346
|
+
const omitted = new Set(keys);
|
|
347
|
+
return Object.fromEntries(Object.entries(node).filter(([key]) => !omitted.has(key)));
|
|
348
|
+
}
|
|
64
349
|
function makeNullable(schema) {
|
|
65
|
-
if (schema
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
350
|
+
if (ownValue(schema, "type") === "null") return schema;
|
|
351
|
+
const anyOf = ownValue(schema, "anyOf");
|
|
352
|
+
if (anyOf) {
|
|
353
|
+
const variants = anyOf;
|
|
354
|
+
if (variants.some((v) => ownValue(v, "type") === "null")) return schema;
|
|
69
355
|
return { anyOf: [...variants, { type: "null" }] };
|
|
70
356
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
357
|
+
const oneOf = ownValue(schema, "oneOf");
|
|
358
|
+
if (oneOf) {
|
|
359
|
+
const variants = oneOf;
|
|
360
|
+
if (variants.some((v) => ownValue(v, "type") === "null")) return schema;
|
|
74
361
|
return { oneOf: [...variants, { type: "null" }] };
|
|
75
362
|
}
|
|
76
363
|
return { anyOf: [schema, { type: "null" }] };
|
|
@@ -78,4 +365,4 @@ function makeNullable(schema) {
|
|
|
78
365
|
//#endregion
|
|
79
366
|
export { StrictifierError, strictify };
|
|
80
367
|
|
|
81
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RyaWN0aWZpZXIuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb3ZpZGVycy9jb21tb24vc3RyaWN0aWZpZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBKU09OIFNjaGVtYSDihpIgT3BlbkFJIHN0cmljdCBKU09OIFNjaGVtYSDrs4DtmZguXG4gKlxuICogT3BlbkFJIFJlc3BvbnNlcyBBUEkgc3RyaWN0IOuqqOuTnCDsmpTqtazsgqztla06XG4gKiAgLSDrqqjrk6Agb2JqZWN0IOyXkCBhZGRpdGlvbmFsUHJvcGVydGllczogZmFsc2VcbiAqICAtIOuqqOuToCBvYmplY3QgcHJvcGVydGllcyDrpbwgcmVxdWlyZWQg7JeQIO2PrO2VqFxuICogIC0gb3B0aW9uYWwg7ZWE65OcIOKGkiBhbnlPZiBbb3JpZ2luYWwsIHsgdHlwZTogJ251bGwnIH1dIOuhnCByZXF1aXJlZCDsnKDsp4BcbiAqICAtIHJlY3Vyc2l2ZSDsspjrpqwgKG5lc3RlZCBvYmplY3RzLCBhcnJheXMsIGFsbE9mL2FueU9mL29uZU9mKVxuICovXG5cbmV4cG9ydCB0eXBlIEpzb25TY2hlbWEgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuZXhwb3J0IGNsYXNzIFN0cmljdGlmaWVyRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIG1lc3NhZ2U6IHN0cmluZyxcbiAgICBwdWJsaWMgcGF0aDogc3RyaW5nLFxuICApIHtcbiAgICBzdXBlcihgc3RyaWN0aWZpZXI6ICR7bWVzc2FnZX0gKGF0ICR7cGF0aH0pYCk7XG4gICAgdGhpcy5uYW1lID0gXCJTdHJpY3RpZmllckVycm9yXCI7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHN0cmljdGlmeShzY2hlbWE6IEpzb25TY2hlbWEpOiBKc29uU2NoZW1hIHtcbiAgcmV0dXJuIHN0cmljdGlmeU5vZGUoc2NoZW1hLCBcIiRcIik7XG59XG5cbmZ1bmN0aW9uIHN0cmljdGlmeU5vZGUobm9kZTogSnNvblNjaGVtYSwgcGF0aDogc3RyaW5nKTogSnNvblNjaGVtYSB7XG4gIGlmICh0eXBlb2Ygbm9kZSAhPT0gXCJvYmplY3RcIiB8fCBub2RlID09PSBudWxsKSByZXR1cm4gbm9kZTtcblxuICBjb25zdCB0eXBlID0gbm9kZS50eXBlIGFzIHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICBpZiAodHlwZSA9PT0gXCJvYmplY3RcIiB8fCBub2RlLnByb3BlcnRpZXMpIHtcbiAgICByZXR1cm4gc3RyaWN0aWZ5T2JqZWN0KG5vZGUsIHBhdGgpO1xuICB9XG5cbiAgaWYgKHR5cGUgPT09IFwiYXJyYXlcIikge1xuICAgIHJldHVybiBzdHJpY3RpZnlBcnJheShub2RlLCBwYXRoKTtcbiAgfVxuXG4gIGlmIChub2RlLmFueU9mKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLm5vZGUsXG4gICAgICBhbnlPZjogKG5vZGUuYW55T2YgYXMgSnNvblNjaGVtYVtdKS5tYXAoKHMsIGkpID0+IHN0cmljdGlmeU5vZGUocywgYCR7cGF0aH0uYW55T2ZbJHtpfV1gKSksXG4gICAgfTtcbiAgfVxuXG4gIGlmIChub2RlLm9uZU9mKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLm5vZGUsXG4gICAgICBvbmVPZjogKG5vZGUub25lT2YgYXMgSnNvblNjaGVtYVtdKS5tYXAoKHMsIGkpID0+IHN0cmljdGlmeU5vZGUocywgYCR7cGF0aH0ub25lT2ZbJHtpfV1gKSksXG4gICAgfTtcbiAgfVxuXG4gIGlmIChub2RlLmFsbE9mKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLm5vZGUsXG4gICAgICBhbGxPZjogKG5vZGUuYWxsT2YgYXMgSnNvblNjaGVtYVtdKS5tYXAoKHMsIGkpID0+IHN0cmljdGlmeU5vZGUocywgYCR7cGF0aH0uYWxsT2ZbJHtpfV1gKSksXG4gICAgfTtcbiAgfVxuXG4gIGlmIChub2RlLiRyZWYpIHtcbiAgICByZXR1cm4geyAuLi5ub2RlIH07XG4gIH1cblxuICByZXR1cm4geyAuLi5ub2RlIH07XG59XG5cbmZ1bmN0aW9uIHN0cmljdGlmeU9iamVjdChub2RlOiBKc29uU2NoZW1hLCBwYXRoOiBzdHJpbmcpOiBKc29uU2NoZW1hIHtcbiAgY29uc3QgcHJvcGVydGllcyA9IG5vZGUucHJvcGVydGllcyBhcyBSZWNvcmQ8c3RyaW5nLCBKc29uU2NoZW1hPiB8IHVuZGVmaW5lZDtcbiAgaWYgKCFwcm9wZXJ0aWVzKSB7XG4gICAgcmV0dXJuIHsgLi4ubm9kZSwgYWRkaXRpb25hbFByb3BlcnRpZXM6IGZhbHNlIH07XG4gIH1cblxuICBjb25zdCBleGlzdGluZ1JlcXVpcmVkID0gbmV3IFNldCgobm9kZS5yZXF1aXJlZCBhcyBzdHJpbmdbXSB8IHVuZGVmaW5lZCkgPz8gW10pO1xuICBjb25zdCBhbGxLZXlzID0gT2JqZWN0LmtleXMocHJvcGVydGllcyk7XG5cbiAgY29uc3Qgc3RyaWN0UHJvcHM6IFJlY29yZDxzdHJpbmcsIEpzb25TY2hlbWE+ID0ge307XG4gIGZvciAoY29uc3Qga2V5IG9mIGFsbEtleXMpIHtcbiAgICBjb25zdCBwcm9wID0gcHJvcGVydGllc1trZXldITtcbiAgICBjb25zdCBzdHJpY3RQcm9wID0gc3RyaWN0aWZ5Tm9kZShwcm9wLCBgJHtwYXRofS4ke2tleX1gKTtcblxuICAgIGlmICghZXhpc3RpbmdSZXF1aXJlZC5oYXMoa2V5KSkge1xuICAgICAgc3RyaWN0UHJvcHNba2V5XSA9IG1ha2VOdWxsYWJsZShzdHJpY3RQcm9wKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3RyaWN0UHJvcHNba2V5XSA9IHN0cmljdFByb3A7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgcmVzdWx0OiBKc29uU2NoZW1hID0ge1xuICAgIC4uLm5vZGUsXG4gICAgdHlwZTogXCJvYmplY3RcIixcbiAgICBwcm9wZXJ0aWVzOiBzdHJpY3RQcm9wcyxcbiAgICByZXF1aXJlZDogYWxsS2V5cyxcbiAgICBhZGRpdGlvbmFsUHJvcGVydGllczogZmFsc2UsXG4gIH07XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gc3RyaWN0aWZ5QXJyYXkobm9kZTogSnNvblNjaGVtYSwgcGF0aDogc3RyaW5nKTogSnNvblNjaGVtYSB7XG4gIGNvbnN0IGl0ZW1zID0gbm9kZS5pdGVtcyBhcyBKc29uU2NoZW1hIHwgdW5kZWZpbmVkO1xuICBpZiAoIWl0ZW1zKSByZXR1cm4geyAuLi5ub2RlIH07XG5cbiAgcmV0dXJuIHtcbiAgICAuLi5ub2RlLFxuICAgIGl0ZW1zOiBzdHJpY3RpZnlOb2RlKGl0ZW1zLCBgJHtwYXRofS5pdGVtc2ApLFxuICB9O1xufVxuXG5mdW5jdGlvbiBtYWtlTnVsbGFibGUoc2NoZW1hOiBKc29uU2NoZW1hKTogSnNvblNjaGVtYSB7XG4gIGlmIChzY2hlbWEudHlwZSA9PT0gXCJudWxsXCIpIHJldHVybiBzY2hlbWE7XG5cbiAgaWYgKHNjaGVtYS5hbnlPZikge1xuICAgIGNvbnN0IHZhcmlhbnRzID0gc2NoZW1hLmFueU9mIGFzIEpzb25TY2hlbWFbXTtcbiAgICBjb25zdCBoYXNOdWxsID0gdmFyaWFudHMuc29tZSgodikgPT4gdi50eXBlID09PSBcIm51bGxcIik7XG4gICAgaWYgKGhhc051bGwpIHJldHVybiBzY2hlbWE7XG4gICAgcmV0dXJuIHsgYW55T2Y6IFsuLi52YXJpYW50cywgeyB0eXBlOiBcIm51bGxcIiB9XSB9O1xuICB9XG5cbiAgaWYgKHNjaGVtYS5vbmVPZikge1xuICAgIGNvbnN0IHZhcmlhbnRzID0gc2NoZW1hLm9uZU9mIGFzIEpzb25TY2hlbWFbXTtcbiAgICBjb25zdCBoYXNOdWxsID0gdmFyaWFudHMuc29tZSgodikgPT4gdi50eXBlID09PSBcIm51bGxcIik7XG4gICAgaWYgKGhhc051bGwpIHJldHVybiBzY2hlbWE7XG4gICAgcmV0dXJuIHsgb25lT2Y6IFsuLi52YXJpYW50cywgeyB0eXBlOiBcIm51bGxcIiB9XSB9O1xuICB9XG5cbiAgcmV0dXJuIHsgYW55T2Y6IFtzY2hlbWEsIHsgdHlwZTogXCJu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
|
|
368
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RyaWN0aWZpZXIuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb3ZpZGVycy9jb21tb24vc3RyaWN0aWZpZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBKU09OIFNjaGVtYSDihpIgT3BlbkFJIHN0cmljdCBKU09OIFNjaGVtYSDrs4DtmZguXG4gKlxuICogT3BlbkFJIFJlc3BvbnNlcyBBUEkgc3RyaWN0IOuqqOuTnCDsmpTqtazsgqztla06XG4gKiAgLSDrqqjrk6Agb2JqZWN0IOyXkCBhZGRpdGlvbmFsUHJvcGVydGllczogZmFsc2VcbiAqICAtIOuqqOuToCBvYmplY3QgcHJvcGVydGllcyDrpbwgcmVxdWlyZWQg7JeQIO2PrO2VqFxuICogIC0gb3B0aW9uYWwg7ZWE65OcIOKGkiBhbnlPZiBbb3JpZ2luYWwsIHsgdHlwZTogJ251bGwnIH1dIOuhnCByZXF1aXJlZCDsnKDsp4BcbiAqICAtIHJlY3Vyc2l2ZSDsspjrpqwgKG5lc3RlZCBvYmplY3RzLCBhcnJheXMsIGFsbE9mL2FueU9mL29uZU9mKVxuICovXG5cbmV4cG9ydCB0eXBlIEpzb25TY2hlbWEgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuZXhwb3J0IGludGVyZmFjZSBTdHJpY3RpZmllck9wdGlvbnMge1xuICBwcm92aWRlcj86IHN0cmluZztcbn1cblxuZXhwb3J0IGNsYXNzIFN0cmljdGlmaWVyRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIG1lc3NhZ2U6IHN0cmluZyxcbiAgICBwdWJsaWMgcGF0aDogc3RyaW5nLFxuICApIHtcbiAgICBzdXBlcihgc3RyaWN0aWZpZXI6ICR7bWVzc2FnZX0gKGF0ICR7cGF0aH0pYCk7XG4gICAgdGhpcy5uYW1lID0gXCJTdHJpY3RpZmllckVycm9yXCI7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHN0cmljdGlmeShzY2hlbWE6IEpzb25TY2hlbWEsIG9wdGlvbnM6IFN0cmljdGlmaWVyT3B0aW9ucyA9IHt9KTogSnNvblNjaGVtYSB7XG4gIGlmIChvcHRpb25zLnByb3ZpZGVyID09PSBcIm9wZW5haVwiIHx8IG9wdGlvbnMucHJvdmlkZXIgPT09IFwiYW50aHJvcGljXCIpIHtcbiAgICBhc3NlcnROb3JtYWxpemF0aW9uQ29tcGF0aWJpbGl0eShzY2hlbWEsIG9wdGlvbnMucHJvdmlkZXIpO1xuICB9XG4gIGNvbnN0IHJlc3VsdCA9IHN0cmljdGlmeU5vZGUoc2NoZW1hLCBcIiRcIiwgb3B0aW9ucy5wcm92aWRlcik7XG4gIGlmIChvcHRpb25zLnByb3ZpZGVyID09PSBcIm9wZW5haVwiIHx8IG9wdGlvbnMucHJvdmlkZXIgPT09IFwiYW50aHJvcGljXCIpIHtcbiAgICBhc3NlcnROb3JtYWxpemF0aW9uQ29tcGF0aWJpbGl0eShyZXN1bHQsIG9wdGlvbnMucHJvdmlkZXIpO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmNvbnN0IFNDSEVNQV9TQ0FOX01BUF9LRVlXT1JEUyA9IFtcbiAgW1wiJGRlZnNcIiwgdHJ1ZV0sXG4gIFtcImRlZmluaXRpb25zXCIsIHRydWVdLFxuICBbXCJwcm9wZXJ0aWVzXCIsIHRydWVdLFxuICBbXCJkZXBlbmRlbnRTY2hlbWFzXCIsIGZhbHNlXSxcbiAgW1wicGF0dGVyblByb3BlcnRpZXNcIiwgZmFsc2VdLFxuXSBhcyBjb25zdDtcbmNvbnN0IFNDSEVNQV9TQ0FOX0FSUkFZX0tFWVdPUkRTID0gW1xuICBbXCJhbGxPZlwiLCB0cnVlXSxcbiAgW1wiYW55T2ZcIiwgdHJ1ZV0sXG4gIFtcIm9uZU9mXCIsIHRydWVdLFxuICBbXCJwcmVmaXhJdGVtc1wiLCB0cnVlXSxcbl0gYXMgY29uc3Q7XG5jb25zdCBTQ0hFTUFfU0NBTl9TSU5HTEVfS0VZV09SRFMgPSBbXG4gIFtcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCIsIGZhbHNlXSxcbiAgW1wiY29udGFpbnNcIiwgZmFsc2VdLFxuICBbXCJjb250ZW50U2NoZW1hXCIsIGZhbHNlXSxcbiAgW1wiZWxzZVwiLCBmYWxzZV0sXG4gIFtcImlmXCIsIGZhbHNlXSxcbiAgW1wibm90XCIsIGZhbHNlXSxcbiAgW1wicHJvcGVydHlOYW1lc1wiLCBmYWxzZV0sXG4gIFtcInRoZW5cIiwgZmFsc2VdLFxuICBbXCJ1bmV2YWx1YXRlZEl0ZW1zXCIsIGZhbHNlXSxcbiAgW1widW5ldmFsdWF0ZWRQcm9wZXJ0aWVzXCIsIGZhbHNlXSxcbl0gYXMgY29uc3Q7XG5cbi8qKlxuICogSW5zcGVjdCBldmVyeSBKU09OIFNjaGVtYS1iZWFyaW5nIHBvc2l0aW9uIHdpdGhvdXQgcmV3cml0aW5nIGl0LlxuICpcbiAqIFBvc2l0aXZlIHBvc2l0aW9ucyBhbHJlYWR5IHRyYXZlcnNlZCBieSBzdHJpY3RpZnlOb2RlIG1heSBub3JtYWxpemUgT3BlbkFJIHR1cGxlcy4gUG9zaXRpb25zXG4gKiBzdWNoIGFzIGBub3RgIGFuZCBgaWZgIGNhbm5vdCBiZSB0aWdodGVuZWQgd2l0aG91dCBjaGFuZ2luZyBjYWxsZXIgc2VtYW50aWNzLCBzbyBwb3NpdGlvbmFsXG4gKiB0dXBsZXMgdGhlcmUgZmFpbCBleHBsaWNpdGx5IGluc3RlYWQgb2YgbGVha2luZyBhbiB1bnN1cHBvcnRlZCBwcm92aWRlciBzY2hlbWEuIFJlZmVyZW5jZXNcbiAqIGZyb20gdGhvc2UgcG9zaXRpb25zIGFsc28gZmFpbCBiZWNhdXNlIHRoZWlyIGRlZmluaXRpb25zIGFyZSBub3JtYWxpemVkIGdsb2JhbGx5LlxuICovXG5mdW5jdGlvbiBhc3NlcnROb3JtYWxpemF0aW9uQ29tcGF0aWJpbGl0eShcbiAgc2NoZW1hOiBKc29uU2NoZW1hLFxuICBwcm92aWRlcjogXCJvcGVuYWlcIiB8IFwiYW50aHJvcGljXCIsXG4pOiB2b2lkIHtcbiAgY29uc3QgcmVmZXJlbmNlczogQXJyYXk8eyB2YWx1ZTogc3RyaW5nOyBwYXRoOiBzdHJpbmcgfT4gPSBbXTtcbiAgY29uc3Qgc3RhY2s6IEFycmF5PHsgbm9kZTogSnNvblNjaGVtYTsgcGF0aDogc3RyaW5nOyBub3JtYWxpemFibGU6IGJvb2xlYW4gfT4gPSBbXG4gICAgeyBub2RlOiBzY2hlbWEsIHBhdGg6IFwiJFwiLCBub3JtYWxpemFibGU6IHRydWUgfSxcbiAgXTtcblxuICB3aGlsZSAoc3RhY2subGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IGN1cnJlbnQgPSBzdGFjay5wb3AoKSE7XG4gICAgY29uc3QgaXRlbXNWYWx1ZSA9IG93blZhbHVlKGN1cnJlbnQubm9kZSwgXCJpdGVtc1wiKTtcbiAgICBjb25zdCBwcmVmaXhJdGVtc1ZhbHVlID0gb3duVmFsdWUoY3VycmVudC5ub2RlLCBcInByZWZpeEl0ZW1zXCIpO1xuICAgIGNvbnN0IGxlZ2FjeVR1cGxlID0gQXJyYXkuaXNBcnJheShpdGVtc1ZhbHVlKTtcbiAgICBjb25zdCBwcmVmaXhUdXBsZSA9IEFycmF5LmlzQXJyYXkocHJlZml4SXRlbXNWYWx1ZSk7XG5cbiAgICBhc3NlcnRVbnN1cHBvcnRlZFJlZmVyZW5jZUtleXdvcmRzKGN1cnJlbnQubm9kZSwgY3VycmVudC5wYXRoKTtcbiAgICBjb2xsZWN0U2NoZW1hUmVmZXJlbmNlKGN1cnJlbnQsIHJlZmVyZW5jZXMpO1xuXG4gICAgaWYgKGxlZ2FjeVR1cGxlIHx8IHByZWZpeFR1cGxlKSB7XG4gICAgICBjb25zdCB0dXBsZSA9IChsZWdhY3lUdXBsZSA/IGl0ZW1zVmFsdWUgOiBwcmVmaXhJdGVtc1ZhbHVlKSBhcyB1bmtub3duW107XG4gICAgICBpZiAocHJvdmlkZXIgPT09IFwiYW50aHJvcGljXCIgJiYgdHVwbGUubGVuZ3RoID4gMCkge1xuICAgICAgICB0aHJvdyBuZXcgU3RyaWN0aWZpZXJFcnJvcihcbiAgICAgICAgICBcInBvc2l0aW9uYWwgdHVwbGUgc2NoZW1hcyBhcmUgbm90IHN1cHBvcnRlZCBvbiBBbnRocm9waWMgYmVjYXVzZSBDbGF1ZGUgQ29kZSBjYW5ub3QgcHJlc2VydmUgaXRlbSBwb3NpdGlvbnNcIixcbiAgICAgICAgICBjdXJyZW50LnBhdGgsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoIWN1cnJlbnQubm9ybWFsaXphYmxlKSB7XG4gICAgICAgIHRocm93IG5ldyBTdHJpY3RpZmllckVycm9yKFxuICAgICAgICAgIFwicG9zaXRpb25hbCB0dXBsZSBzY2hlbWFzIGFyZSBub3Qgc3VwcG9ydGVkIGluIHRoaXMgc2NoZW1hIHBvc2l0aW9uXCIsXG4gICAgICAgICAgY3VycmVudC5wYXRoLFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKG93blZhbHVlKGN1cnJlbnQubm9kZSwgXCJ0eXBlXCIpICE9PSBcImFycmF5XCIpIHtcbiAgICAgICAgdGhyb3cgbmV3IFN0cmljdGlmaWVyRXJyb3IoXG4gICAgICAgICAgJ3Bvc2l0aW9uYWwgdHVwbGUgc2NoZW1hcyBtdXN0IGRlY2xhcmUgdHlwZSBcImFycmF5XCI7IGV4cHJlc3MgbnVsbGFibGUgdHVwbGVzIHdpdGggYW55T2YnLFxuICAgICAgICAgIGAke2N1cnJlbnQucGF0aH0udHlwZWAsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBba2V5d29yZCwga2V5d29yZE5vcm1hbGl6YWJsZV0gb2YgU0NIRU1BX1NDQU5fTUFQX0tFWVdPUkRTKSB7XG4gICAgICBjb25zdCBzY2hlbWFzID0gb3duVmFsdWUoY3VycmVudC5ub2RlLCBrZXl3b3JkKTtcbiAgICAgIGlmICghaXNTY2hlbWFPYmplY3Qoc2NoZW1hcykpIGNvbnRpbnVlO1xuICAgICAgZm9yIChjb25zdCBbbmFtZSwgY2hpbGRdIG9mIE9iamVjdC5lbnRyaWVzKHNjaGVtYXMpKSB7XG4gICAgICAgIGlmICghaXNTY2hlbWFPYmplY3QoY2hpbGQpKSBjb250aW51ZTtcbiAgICAgICAgc3RhY2sucHVzaCh7XG4gICAgICAgICAgbm9kZTogY2hpbGQsXG4gICAgICAgICAgcGF0aDogYCR7Y3VycmVudC5wYXRofS4ke2tleXdvcmR9LiR7bmFtZX1gLFxuICAgICAgICAgIG5vcm1hbGl6YWJsZTogY3VycmVudC5ub3JtYWxpemFibGUgJiYga2V5d29yZE5vcm1hbGl6YWJsZSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgZGVwZW5kZW5jaWVzID0gb3duVmFsdWUoY3VycmVudC5ub2RlLCBcImRlcGVuZGVuY2llc1wiKTtcbiAgICBpZiAoaXNTY2hlbWFPYmplY3QoZGVwZW5kZW5jaWVzKSkge1xuICAgICAgZm9yIChjb25zdCBbbmFtZSwgY2hpbGRdIG9mIE9iamVjdC5lbnRyaWVzKGRlcGVuZGVuY2llcykpIHtcbiAgICAgICAgaWYgKCFpc1NjaGVtYU9iamVjdChjaGlsZCkpIGNvbnRpbnVlO1xuICAgICAgICBzdGFjay5wdXNoKHtcbiAgICAgICAgICBub2RlOiBjaGlsZCxcbiAgICAgICAgICBwYXRoOiBgJHtjdXJyZW50LnBhdGh9LmRlcGVuZGVuY2llcy4ke25hbWV9YCxcbiAgICAgICAgICBub3JtYWxpemFibGU6IGZhbHNlLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IFtrZXl3b3JkLCBrZXl3b3JkTm9ybWFsaXphYmxlXSBvZiBTQ0hFTUFfU0NBTl9BUlJBWV9LRVlXT1JEUykge1xuICAgICAgY29uc3Qgc2NoZW1hcyA9IG93blZhbHVlKGN1cnJlbnQubm9kZSwga2V5d29yZCk7XG4gICAgICBpZiAoIUFycmF5LmlzQXJyYXkoc2NoZW1hcykpIGNvbnRpbnVlO1xuICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHNjaGVtYXMubGVuZ3RoOyBpbmRleCArPSAxKSB7XG4gICAgICAgIGNvbnN0IGNoaWxkID0gc2NoZW1hc1tpbmRleF07XG4gICAgICAgIGlmICghaXNTY2hlbWFPYmplY3QoY2hpbGQpKSBjb250aW51ZTtcbiAgICAgICAgc3RhY2sucHVzaCh7XG4gICAgICAgICAgbm9kZTogY2hpbGQsXG4gICAgICAgICAgcGF0aDogYCR7Y3VycmVudC5wYXRofS4ke2tleXdvcmR9WyR7aW5kZXh9XWAsXG4gICAgICAgICAgbm9ybWFsaXphYmxlOiBjdXJyZW50Lm5vcm1hbGl6YWJsZSAmJiBrZXl3b3JkTm9ybWFsaXphYmxlLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBpdGVtcyA9IG93blZhbHVlKGN1cnJlbnQubm9kZSwgXCJpdGVtc1wiKTtcbiAgICBpZiAoaXNTY2hlbWFPYmplY3QoaXRlbXMpKSB7XG4gICAgICBzdGFjay5wdXNoKHtcbiAgICAgICAgbm9kZTogaXRlbXMsXG4gICAgICAgIHBhdGg6IGAke2N1cnJlbnQucGF0aH0uaXRlbXNgLFxuICAgICAgICBub3JtYWxpemFibGU6IGN1cnJlbnQubm9ybWFsaXphYmxlLFxuICAgICAgfSk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGl0ZW1zKSkge1xuICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGl0ZW1zLmxlbmd0aDsgaW5kZXggKz0gMSkge1xuICAgICAgICBjb25zdCBjaGlsZCA9IGl0ZW1zW2luZGV4XTtcbiAgICAgICAgaWYgKCFpc1NjaGVtYU9iamVjdChjaGlsZCkpIGNvbnRpbnVlO1xuICAgICAgICBzdGFjay5wdXNoKHtcbiAgICAgICAgICBub2RlOiBjaGlsZCxcbiAgICAgICAgICBwYXRoOiBgJHtjdXJyZW50LnBhdGh9Lml0ZW1zWyR7aW5kZXh9XWAsXG4gICAgICAgICAgbm9ybWFsaXphYmxlOiBjdXJyZW50Lm5vcm1hbGl6YWJsZSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgYWRkaXRpb25hbEl0ZW1zID0gb3duVmFsdWUoY3VycmVudC5ub2RlLCBcImFkZGl0aW9uYWxJdGVtc1wiKTtcbiAgICBpZiAoaXNTY2hlbWFPYmplY3QoYWRkaXRpb25hbEl0ZW1zKSkge1xuICAgICAgc3RhY2sucHVzaCh7XG4gICAgICAgIG5vZGU6IGFkZGl0aW9uYWxJdGVtcyxcbiAgICAgICAgcGF0aDogYCR7Y3VycmVudC5wYXRofS5hZGRpdGlvbmFsSXRlbXNgLFxuICAgICAgICBub3JtYWxpemFibGU6IGN1cnJlbnQubm9ybWFsaXphYmxlICYmIGxlZ2FjeVR1cGxlLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBba2V5d29yZCwga2V5d29yZE5vcm1hbGl6YWJsZV0gb2YgU0NIRU1BX1NDQU5fU0lOR0xFX0tFWVdPUkRTKSB7XG4gICAgICBjb25zdCBjaGlsZCA9IG93blZhbHVlKGN1cnJlbnQubm9kZSwga2V5d29yZCk7XG4gICAgICBpZiAoIWlzU2NoZW1hT2JqZWN0KGNoaWxkKSkgY29udGludWU7XG4gICAgICBzdGFjay5wdXNoKHtcbiAgICAgICAgbm9kZTogY2hpbGQsXG4gICAgICAgIHBhdGg6IGAke2N1cnJlbnQucGF0aH0uJHtrZXl3b3JkfWAsXG4gICAgICAgIG5vcm1hbGl6YWJsZTogY3VycmVudC5ub3JtYWxpemFibGUgJiYga2V5d29yZE5vcm1hbGl6YWJsZSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGFzc2VydFJlZmVyZW5jZVRhcmdldHMoc2NoZW1hLCByZWZlcmVuY2VzKTtcbn1cblxuY29uc3QgVU5TVVBQT1JURURfUkVGRVJFTkNFX0tFWVdPUkRTID0gW1xuICBcIiRpZFwiLFxuICBcImlkXCIsXG4gIFwiJGFuY2hvclwiLFxuICBcIiRkeW5hbWljQW5jaG9yXCIsXG4gIFwiJHJlY3Vyc2l2ZUFuY2hvclwiLFxuICBcIiRkeW5hbWljUmVmXCIsXG4gIFwiJHJlY3Vyc2l2ZVJlZlwiLFxuXSBhcyBjb25zdDtcblxuZnVuY3Rpb24gYXNzZXJ0VW5zdXBwb3J0ZWRSZWZlcmVuY2VLZXl3b3JkcyhzY2hlbWE6IEpzb25TY2hlbWEsIHBhdGg6IHN0cmluZyk6IHZvaWQge1xuICBmb3IgKGNvbnN0IGtleXdvcmQgb2YgVU5TVVBQT1JURURfUkVGRVJFTkNFX0tFWVdPUkRTKSB7XG4gICAgaWYgKE9iamVjdC5oYXNPd24oc2NoZW1hLCBrZXl3b3JkKSkge1xuICAgICAgdGhyb3cgbmV3IFN0cmljdGlmaWVyRXJyb3IoYCR7a2V5d29yZH0gaXMgbm90IHN1cHBvcnRlZGAsIGAke3BhdGh9LiR7a2V5d29yZH1gKTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gY29sbGVjdFNjaGVtYVJlZmVyZW5jZShcbiAgY3VycmVudDogeyBub2RlOiBKc29uU2NoZW1hOyBwYXRoOiBzdHJpbmc7IG5vcm1hbGl6YWJsZTogYm9vbGVhbiB9LFxuICByZWZlcmVuY2VzOiBBcnJheTx7IHZhbHVlOiBzdHJpbmc7IHBhdGg6IHN0cmluZyB9Pixcbik6IHZvaWQge1xuICBpZiAoIU9iamVjdC5oYXNPd24oY3VycmVudC5ub2RlLCBcIiRyZWZcIikpIHJldHVybjtcblxuICBjb25zdCByZWZlcmVuY2UgPSBjdXJyZW50Lm5vZGUuJHJlZjtcbiAgaWYgKHR5cGVvZiByZWZlcmVuY2UgIT09IFwic3RyaW5nXCIpIHtcbiAgICB0aHJvdyBuZXcgU3RyaWN0aWZpZXJFcnJvcihcIiRyZWYgbXVzdCBiZSBhIHN0cmluZ1wiLCBgJHtjdXJyZW50LnBhdGh9LiRyZWZgKTtcbiAgfVxuICBpZiAoIWN1cnJlbnQubm9ybWFsaXphYmxlKSB7XG4gICAgdGhyb3cgbmV3IFN0cmljdGlmaWVyRXJyb3IoXG4gICAgICBcInNjaGVtYSByZWZlcmVuY2VzIGFyZSBub3Qgc3VwcG9ydGVkIGluIHRoaXMgc2NoZW1hIHBvc2l0aW9uXCIsXG4gICAgICBjdXJyZW50LnBhdGgsXG4gICAgKTtcbiAgfVxuXG4gIHJlZmVyZW5jZXMucHVzaCh7IHZhbHVlOiByZWZlcmVuY2UsIHBhdGg6IGAke2N1cnJlbnQucGF0aH0uJHJlZmAgfSk7XG59XG5cbmZ1bmN0aW9uIGFzc2VydFJlZmVyZW5jZVRhcmdldHMoXG4gIHJvb3Q6IEpzb25TY2hlbWEsXG4gIHJlZmVyZW5jZXM6IEFycmF5PHsgdmFsdWU6IHN0cmluZzsgcGF0aDogc3RyaW5nIH0+LFxuKTogdm9pZCB7XG4gIGZvciAoY29uc3QgcmVmZXJlbmNlIG9mIHJlZmVyZW5jZXMpIHtcbiAgICBjb25zdCB0b2tlbnMgPSBwYXJzZUxvY2FsSnNvblBvaW50ZXIocmVmZXJlbmNlLnZhbHVlLCByZWZlcmVuY2UucGF0aCk7XG4gICAgaWYgKCFpc0RlZmluaXRpb25Sb290UG9pbnRlcih0b2tlbnMpKSB7XG4gICAgICB0aHJvdyBuZXcgU3RyaWN0aWZpZXJFcnJvcihcbiAgICAgICAgXCIkcmVmIHRhcmdldCBtdXN0IGJlIHRoZSBkb2N1bWVudCByb290IG9yIGEgZGVmaW5pdGlvbiByb290XCIsXG4gICAgICAgIHJlZmVyZW5jZS5wYXRoLFxuICAgICAgKTtcbiAgICB9XG4gICAgcmVzb2x2ZURlZmluaXRpb25Sb290KHJvb3QsIHRva2VucywgcmVmZXJlbmNlLnBhdGgpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGlzRGVmaW5pdGlvblJvb3RQb2ludGVyKHRva2Vuczogc3RyaW5nW10pOiBib29sZWFuIHtcbiAgaWYgKHRva2Vucy5sZW5ndGggPT09IDApIHJldHVybiB0cnVlO1xuICBpZiAodG9rZW5zLmxlbmd0aCAlIDIgIT09IDApIHJldHVybiBmYWxzZTtcblxuICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgdG9rZW5zLmxlbmd0aDsgaW5kZXggKz0gMikge1xuICAgIGlmICh0b2tlbnNbaW5kZXhdICE9PSBcIiRkZWZzXCIgJiYgdG9rZW5zW2luZGV4XSAhPT0gXCJkZWZpbml0aW9uc1wiKSByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIHBhcnNlTG9jYWxKc29uUG9pbnRlcihyZWZlcmVuY2U6IHN0cmluZywgcGF0aDogc3RyaW5nKTogc3RyaW5nW10ge1xuICBpZiAocmVmZXJlbmNlID09PSBcIiNcIikgcmV0dXJuIFtdO1xuICBpZiAoIXJlZmVyZW5jZS5zdGFydHNXaXRoKFwiIy9cIikpIHtcbiAgICB0aHJvdyBuZXcgU3RyaWN0aWZpZXJFcnJvcihcbiAgICAgIFwib25seSBsb2NhbCByb290LXJlbGF0aXZlIEpTT04gUG9pbnRlciAkcmVmIHZhbHVlcyBhcmUgc3VwcG9ydGVkXCIsXG4gICAgICBwYXRoLFxuICAgICk7XG4gIH1cblxuICBsZXQgZnJhZ21lbnQ6IHN0cmluZztcbiAgdHJ5IHtcbiAgICBmcmFnbWVudCA9IGRlY29kZVVSSUNvbXBvbmVudChyZWZlcmVuY2Uuc2xpY2UoMSkpO1xuICB9IGNhdGNoIHtcbiAgICB0aHJvdyBuZXcgU3RyaWN0aWZpZXJFcnJvcihcIiRyZWYgY29udGFpbnMgaW52YWxpZCBwZXJjZW50IGVuY29kaW5nXCIsIHBhdGgpO1xuICB9XG4gIGlmICghZnJhZ21lbnQuc3RhcnRzV2l0aChcIi9cIikpIHtcbiAgICB0aHJvdyBuZXcgU3RyaWN0aWZpZXJFcnJvcihcbiAgICAgIFwib25seSBsb2NhbCByb290LXJlbGF0aXZlIEpTT04gUG9pbnRlciAkcmVmIHZhbHVlcyBhcmUgc3VwcG9ydGVkXCIsXG4gICAgICBwYXRoLFxuICAgICk7XG4gIH1cblxuICByZXR1cm4gZnJhZ21lbnRcbiAgICAuc2xpY2UoMSlcbiAgICAuc3BsaXQoXCIvXCIpXG4gICAgLm1hcCgodG9rZW4pID0+IGRlY29kZUpzb25Qb2ludGVyVG9rZW4odG9rZW4sIHBhdGgpKTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZURlZmluaXRpb25Sb290KHJvb3Q6IEpzb25TY2hlbWEsIHRva2Vuczogc3RyaW5nW10sIHBhdGg6IHN0cmluZyk6IHZvaWQge1xuICBsZXQgY3VycmVudCA9IHJvb3Q7XG4gIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCB0b2tlbnMubGVuZ3RoOyBpbmRleCArPSAyKSB7XG4gICAgY29uc3Qga2V5d29yZCA9IHRva2Vuc1tpbmRleF0hO1xuICAgIGNvbnN0IG5hbWUgPSB0b2tlbnNbaW5kZXggKyAxXSE7XG4gICAgY29uc3QgZGVmaW5pdGlvbnMgPSBvd25WYWx1ZShjdXJyZW50LCBrZXl3b3JkKTtcbiAgICBpZiAoIWlzU2NoZW1hT2JqZWN0KGRlZmluaXRpb25zKSB8fCAhT2JqZWN0Lmhhc093bihkZWZpbml0aW9ucywgbmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBTdHJpY3RpZmllckVycm9yKFwiJHJlZiBkb2VzIG5vdCByZXNvbHZlIGluc2lkZSB0aGUgY2FsbGVyIHNjaGVtYVwiLCBwYXRoKTtcbiAgICB9XG4gICAgY29uc3QgdGFyZ2V0ID0gZGVmaW5pdGlvbnNbbmFtZV07XG4gICAgaWYgKCFpc1NjaGVtYU9iamVjdCh0YXJnZXQpKSB7XG4gICAgICB0aHJvdyBuZXcgU3RyaWN0aWZpZXJFcnJvcihcIiRyZWYgdGFyZ2V0IG11c3QgYmUgYW4gb2JqZWN0IHNjaGVtYVwiLCBwYXRoKTtcbiAgICB9XG4gICAgY3VycmVudCA9IHRhcmdldDtcbiAgfVxufVxuXG5mdW5jdGlvbiBkZWNvZGVKc29uUG9pbnRlclRva2VuKHJhd1Rva2VuOiBzdHJpbmcsIHBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gIGxldCB0b2tlbiA9IFwiXCI7XG4gIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCByYXdUb2tlbi5sZW5ndGg7IGluZGV4ICs9IDEpIHtcbiAgICBjb25zdCBjaGFyYWN0ZXIgPSByYXdUb2tlbltpbmRleF0hO1xuICAgIGlmIChjaGFyYWN0ZXIgIT09IFwiflwiKSB7XG4gICAgICB0b2tlbiArPSBjaGFyYWN0ZXI7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBjb25zdCBlc2NhcGVkID0gcmF3VG9rZW5baW5kZXggKyAxXTtcbiAgICBpZiAoZXNjYXBlZCA9PT0gXCIwXCIpIHtcbiAgICAgIHRva2VuICs9IFwiflwiO1xuICAgIH0gZWxzZSBpZiAoZXNjYXBlZCA9PT0gXCIxXCIpIHtcbiAgICAgIHRva2VuICs9IFwiL1wiO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgU3RyaWN0aWZpZXJFcnJvcihcIiRyZWYgY29udGFpbnMgYW4gaW52YWxpZCBKU09OIFBvaW50ZXIgZXNjYXBlXCIsIHBhdGgpO1xuICAgIH1cbiAgICBpbmRleCArPSAxO1xuICB9XG4gIHJldHVybiB0b2tlbjtcbn1cblxuZnVuY3Rpb24gc3RyaWN0aWZ5Tm9kZShub2RlOiBKc29uU2NoZW1hLCBwYXRoOiBzdHJpbmcsIHByb3ZpZGVyPzogc3RyaW5nKTogSnNvblNjaGVtYSB7XG4gIGlmICh0eXBlb2Ygbm9kZSAhPT0gXCJvYmplY3RcIiB8fCBub2RlID09PSBudWxsKSByZXR1cm4gbm9kZTtcblxuICBjb25zdCBkaWFsZWN0TmV1dHJhbE5vZGUgPSBwcm92aWRlciA9PT0gXCJvcGVuYWlcIiA/IG9taXRLZXlzKG5vZGUsIFtcIiRzY2hlbWFcIl0pIDogbm9kZTtcbiAgbGV0IHJlc3VsdCA9IHN0cmljdGlmeVNjaGVtYU1hcHMoZGlhbGVjdE5ldXRyYWxOb2RlLCBwYXRoLCBwcm92aWRlcik7XG4gIGNvbnN0IHR5cGUgPSBvd25WYWx1ZShyZXN1bHQsIFwidHlwZVwiKSBhcyBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgaWYgKHR5cGUgPT09IFwib2JqZWN0XCIgfHwgT2JqZWN0Lmhhc093bihyZXN1bHQsIFwicHJvcGVydGllc1wiKSkge1xuICAgIHJlc3VsdCA9IHN0cmljdGlmeU9iamVjdChyZXN1bHQsIHBhdGgsIHByb3ZpZGVyKTtcbiAgfVxuXG4gIGlmICh0eXBlID09PSBcImFycmF5XCIgfHwgT2JqZWN0Lmhhc093bihyZXN1bHQsIFwiaXRlbXNcIikgfHwgT2JqZWN0Lmhhc093bihyZXN1bHQsIFwicHJlZml4SXRlbXNcIikpIHtcbiAgICByZXN1bHQgPSBzdHJpY3RpZnlBcnJheShyZXN1bHQsIHBhdGgsIHByb3ZpZGVyKTtcbiAgfVxuXG4gIHJldHVybiBzdHJpY3RpZnlTY2hlbWFBcnJheXMocmVzdWx0LCBwYXRoLCBwcm92aWRlcik7XG59XG5cbmNvbnN0IFNDSEVNQV9NQVBfS0VZV09SRFMgPSBbXCIkZGVmc1wiLCBcImRlZmluaXRpb25zXCJdIGFzIGNvbnN0O1xuXG5mdW5jdGlvbiBzdHJpY3RpZnlTY2hlbWFNYXBzKG5vZGU6IEpzb25TY2hlbWEsIHBhdGg6IHN0cmluZywgcHJvdmlkZXI/OiBzdHJpbmcpOiBKc29uU2NoZW1hIHtcbiAgY29uc3QgcmVzdWx0ID0geyAuLi5ub2RlIH07XG5cbiAgZm9yIChjb25zdCBrZXl3b3JkIG9mIFNDSEVNQV9NQVBfS0VZV09SRFMpIHtcbiAgICBjb25zdCBzY2hlbWFzID0gb3duVmFsdWUobm9kZSwga2V5d29yZCk7XG4gICAgaWYgKCFpc1NjaGVtYU9iamVjdChzY2hlbWFzKSkgY29udGludWU7XG5cbiAgICByZXN1bHRba2V5d29yZF0gPSBPYmplY3QuZnJvbUVudHJpZXMoXG4gICAgICBPYmplY3QuZW50cmllcyhzY2hlbWFzKS5tYXAoKFtuYW1lLCBzY2hlbWFdKSA9PiBbXG4gICAgICAgIG5hbWUsXG4gICAgICAgIGlzU2NoZW1hT2JqZWN0KHNjaGVtYSlcbiAgICAgICAgICA/IHN0cmljdGlmeU5vZGUoc2NoZW1hLCBgJHtwYXRofS4ke2tleXdvcmR9LiR7bmFtZX1gLCBwcm92aWRlcilcbiAgICAgICAgICA6IHNjaGVtYSxcbiAgICAgIF0pLFxuICAgICk7XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5jb25zdCBTQ0hFTUFfQVJSQVlfS0VZV09SRFMgPSBbXCJhbnlPZlwiLCBcIm9uZU9mXCIsIFwiYWxsT2ZcIl0gYXMgY29uc3Q7XG5cbmZ1bmN0aW9uIHN0cmljdGlmeVNjaGVtYUFycmF5cyhub2RlOiBKc29uU2NoZW1hLCBwYXRoOiBzdHJpbmcsIHByb3ZpZGVyPzogc3RyaW5nKTogSnNvblNjaGVtYSB7XG4gIGNvbnN0IHJlc3VsdCA9IHsgLi4ubm9kZSB9O1xuXG4gIGZvciAoY29uc3Qga2V5d29yZCBvZiBTQ0hFTUFfQVJSQVlfS0VZV09SRFMpIHtcbiAgICBjb25zdCBzY2hlbWFzID0gb3duVmFsdWUobm9kZSwga2V5d29yZCk7XG4gICAgaWYgKCFzY2hlbWFzKSBjb250aW51ZTtcbiAgICByZXN1bHRba2V5d29yZF0gPSAoc2NoZW1hcyBhcyBKc29uU2NoZW1hW10pLm1hcCgoc2NoZW1hLCBpbmRleCkgPT5cbiAgICAgIHN0cmljdGlmeU5vZGUoc2NoZW1hLCBgJHtwYXRofS4ke2tleXdvcmR9WyR7aW5kZXh9XWAsIHByb3ZpZGVyKSxcbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gc3RyaWN0aWZ5T2JqZWN0KG5vZGU6IEpzb25TY2hlbWEsIHBhdGg6IHN0cmluZywgcHJvdmlkZXI/OiBzdHJpbmcpOiBKc29uU2NoZW1hIHtcbiAgY29uc3QgcHJvcGVydGllcyA9IG93blZhbHVlKG5vZGUsIFwicHJvcGVydGllc1wiKSBhcyBSZWNvcmQ8c3RyaW5nLCBKc29uU2NoZW1hPiB8IHVuZGVmaW5lZDtcbiAgaWYgKCFwcm9wZXJ0aWVzKSB7XG4gICAgcmV0dXJuIHsgLi4ubm9kZSwgYWRkaXRpb25hbFByb3BlcnRpZXM6IGZhbHNlIH07XG4gIH1cblxuICBjb25zdCBleGlzdGluZ1JlcXVpcmVkID0gbmV3IFNldCgob3duVmFsdWUobm9kZSwgXCJyZXF1aXJlZFwiKSBhcyBzdHJpbmdbXSB8IHVuZGVmaW5lZCkgPz8gW10pO1xuICBjb25zdCBhbGxLZXlzID0gT2JqZWN0LmtleXMocHJvcGVydGllcyk7XG5cbiAgY29uc3Qgc3RyaWN0UHJvcHMgPSBPYmplY3QuZnJvbUVudHJpZXMoXG4gICAgYWxsS2V5cy5tYXAoKGtleSkgPT4ge1xuICAgICAgY29uc3QgcHJvcCA9IHByb3BlcnRpZXNba2V5XSE7XG4gICAgICBjb25zdCBzdHJpY3RQcm9wID0gc3RyaWN0aWZ5Tm9kZShwcm9wLCBgJHtwYXRofS4ke2tleX1gLCBwcm92aWRlcik7XG5cbiAgICAgIHJldHVybiBba2V5LCBleGlzdGluZ1JlcXVpcmVkLmhhcyhrZXkpID8gc3RyaWN0UHJvcCA6IG1ha2VOdWxsYWJsZShzdHJpY3RQcm9wKV07XG4gICAgfSksXG4gICkgYXMgUmVjb3JkPHN0cmluZywgSnNvblNjaGVtYT47XG5cbiAgY29uc3QgcmVzdWx0OiBKc29uU2NoZW1hID0ge1xuICAgIC4uLm5vZGUsXG4gICAgdHlwZTogXCJvYmplY3RcIixcbiAgICBwcm9wZXJ0aWVzOiBzdHJpY3RQcm9wcyxcbiAgICByZXF1aXJlZDogYWxsS2V5cyxcbiAgICBhZGRpdGlvbmFsUHJvcGVydGllczogZmFsc2UsXG4gIH07XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuY29uc3QgVU5SRUFDSEFCTEVfVFVQTEVfVEFJTF9TQ0hFTUE6IEpzb25TY2hlbWEgPSB7IHR5cGU6IFwic3RyaW5nXCIgfTtcblxuZnVuY3Rpb24gc3RyaWN0aWZ5QXJyYXkobm9kZTogSnNvblNjaGVtYSwgcGF0aDogc3RyaW5nLCBwcm92aWRlcj86IHN0cmluZyk6IEpzb25TY2hlbWEge1xuICBpZiAoXG4gICAgKHByb3ZpZGVyID09PSBcIm9wZW5haVwiIHx8IHByb3ZpZGVyID09PSBcImFudGhyb3BpY1wiKSAmJlxuICAgIChBcnJheS5pc0FycmF5KG93blZhbHVlKG5vZGUsIFwiaXRlbXNcIikpIHx8IEFycmF5LmlzQXJyYXkob3duVmFsdWUobm9kZSwgXCJwcmVmaXhJdGVtc1wiKSkpXG4gICkge1xuICAgIHJldHVybiBub3JtYWxpemVUdXBsZShub2RlLCBwYXRoLCBwcm92aWRlcik7XG4gIH1cblxuICBjb25zdCByZXN1bHQgPSB7IC4uLm5vZGUgfTtcbiAgY29uc3QgaXRlbXMgPSBvd25WYWx1ZShub2RlLCBcIml0ZW1zXCIpIGFzIEpzb25TY2hlbWEgfCBKc29uU2NoZW1hW10gfCB1bmRlZmluZWQ7XG5cbiAgaWYgKEFycmF5LmlzQXJyYXkoaXRlbXMpKSB7XG4gICAgcmVzdWx0Lml0ZW1zID0gaXRlbXMubWFwKChzY2hlbWEsIGluZGV4KSA9PlxuICAgICAgc3RyaWN0aWZ5Tm9kZShzY2hlbWEsIGAke3BhdGh9Lml0ZW1zWyR7aW5kZXh9XWAsIHByb3ZpZGVyKSxcbiAgICApO1xuICB9IGVsc2UgaWYgKGl0ZW1zICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXN1bHQuaXRlbXMgPSBzdHJpY3RpZnlOb2RlKGl0ZW1zLCBgJHtwYXRofS5pdGVtc2AsIHByb3ZpZGVyKTtcbiAgfVxuXG4gIGNvbnN0IHByZWZpeEl0ZW1zID0gb3duVmFsdWUobm9kZSwgXCJwcmVmaXhJdGVtc1wiKSBhcyBKc29uU2NoZW1hW10gfCB1bmRlZmluZWQ7XG4gIGlmIChBcnJheS5pc0FycmF5KHByZWZpeEl0ZW1zKSkge1xuICAgIHJlc3VsdC5wcmVmaXhJdGVtcyA9IHByZWZpeEl0ZW1zLm1hcCgoc2NoZW1hLCBpbmRleCkgPT5cbiAgICAgIHN0cmljdGlmeU5vZGUoc2NoZW1hLCBgJHtwYXRofS5wcmVmaXhJdGVtc1ske2luZGV4fV1gLCBwcm92aWRlciksXG4gICAgKTtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZVR1cGxlKFxuICBub2RlOiBKc29uU2NoZW1hLFxuICBwYXRoOiBzdHJpbmcsXG4gIHByb3ZpZGVyOiBcIm9wZW5haVwiIHwgXCJhbnRocm9waWNcIixcbik6IEpzb25TY2hlbWEge1xuICBjb25zdCBpdGVtcyA9IG93blZhbHVlKG5vZGUsIFwiaXRlbXNcIik7XG4gIGNvbnN0IHByZWZpeEl0ZW1zID0gb3duVmFsdWUobm9kZSwgXCJwcmVmaXhJdGVtc1wiKTtcbiAgY29uc3QgbGVnYWN5VHVwbGUgPSBBcnJheS5pc0FycmF5KGl0ZW1zKTtcbiAgY29uc3QgcHJlZml4VHVwbGUgPSBBcnJheS5pc0FycmF5KHByZWZpeEl0ZW1zKTtcbiAgaWYgKGxlZ2FjeVR1cGxlICYmIHByZWZpeFR1cGxlKSB7XG4gICAgdGhyb3cgbmV3IFN0cmljdGlmaWVyRXJyb3IoXCJpdGVtcyBhbmQgcHJlZml4SXRlbXMgdHVwbGUgZm9ybXMgY2Fubm90IGJlIGNvbWJpbmVkXCIsIHBhdGgpO1xuICB9XG4gIGlmIChwcmVmaXhUdXBsZSAmJiBPYmplY3QuaGFzT3duKG5vZGUsIFwiYWRkaXRpb25hbEl0ZW1zXCIpKSB7XG4gICAgdGhyb3cgbmV3IFN0cmljdGlmaWVyRXJyb3IoXCJhZGRpdGlvbmFsSXRlbXMgY2Fubm90IGJlIGNvbWJpbmVkIHdpdGggcHJlZml4SXRlbXNcIiwgcGF0aCk7XG4gIH1cblxuICBjb25zdCByYXdUdXBsZSA9IChsZWdhY3lUdXBsZSA/IGl0ZW1zIDogcHJlZml4SXRlbXMpIGFzIHVua25vd25bXTtcbiAgY29uc3QgdHVwbGVQYXRoID0gbGVnYWN5VHVwbGUgPyBgJHtwYXRofS5pdGVtc2AgOiBgJHtwYXRofS5wcmVmaXhJdGVtc2A7XG4gIGNvbnN0IHR1cGxlID0gcmF3VHVwbGUubWFwKChzY2hlbWEsIGluZGV4KSA9PiB7XG4gICAgaWYgKCFpc1NjaGVtYU9iamVjdChzY2hlbWEpKSB7XG4gICAgICB0aHJvdyBuZXcgU3RyaWN0aWZpZXJFcnJvcihcbiAgICAgICAgXCJib29sZWFuIGFuZCBub24tb2JqZWN0IHR1cGxlIG1lbWJlciBzY2hlbWFzIGFyZSBub3Qgc3VwcG9ydGVkXCIsXG4gICAgICAgIGAke3R1cGxlUGF0aH1bJHtpbmRleH1dYCxcbiAgICAgICk7XG4gICAgfVxuICAgIGNvbnN0IG1lbWJlclBhdGggPSBgJHt0dXBsZVBhdGh9WyR7aW5kZXh9XWA7XG4gICAgY29uc3QgbWVtYmVyID0gc3RyaWN0aWZ5Tm9kZShzY2hlbWEsIG1lbWJlclBhdGgsIHByb3ZpZGVyKTtcbiAgICBpZiAoIWhhc1Byb3ZpZGVyU2NoZW1hRW50cnlQb2ludChtZW1iZXIpKSB7XG4gICAgICB0aHJvdyBuZXcgU3RyaWN0aWZpZXJFcnJvcihcbiAgICAgICAgXCJ0dXBsZSBtZW1iZXIgbXVzdCBkZWZpbmUgYSBwcm92aWRlci1yZXByZXNlbnRhYmxlIHNjaGVtYVwiLFxuICAgICAgICBtZW1iZXJQYXRoLFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIG1lbWJlcjtcbiAgfSk7XG5cbiAgY29uc3QgcmF3VGFpbCA9IGxlZ2FjeVR1cGxlID8gb3duVmFsdWUobm9kZSwgXCJhZGRpdGlvbmFsSXRlbXNcIikgOiBpdGVtcztcbiAgaWYgKHJhd1RhaWwgPT09IHRydWUpIHtcbiAgICB0aHJvdyBuZXcgU3RyaWN0aWZpZXJFcnJvcihcImFuIHVucmVzdHJpY3RlZCB0dXBsZSByZXN0IGlzIG5vdCBzdXBwb3J0ZWRcIiwgcGF0aCk7XG4gIH1cbiAgaWYgKHJhd1RhaWwgIT09IHVuZGVmaW5lZCAmJiByYXdUYWlsICE9PSBmYWxzZSAmJiAhaXNTY2hlbWFPYmplY3QocmF3VGFpbCkpIHtcbiAgICB0aHJvdyBuZXcgU3RyaWN0aWZpZXJFcnJvcihcInR1cGxlIHJlc3QgbXVzdCBiZSBhbiBvYmplY3Qgc2NoZW1hIG9yIGZhbHNlXCIsIHBhdGgpO1xuICB9XG5cbiAgY29uc3QgdGFpbCA9IGlzU2NoZW1hT2JqZWN0KHJhd1RhaWwpXG4gICAgPyBzdHJpY3RpZnlOb2RlKHJhd1RhaWwsIGxlZ2FjeVR1cGxlID8gYCR7cGF0aH0uYWRkaXRpb25hbEl0ZW1zYCA6IGAke3BhdGh9Lml0ZW1zYCwgcHJvdmlkZXIpXG4gICAgOiB1bmRlZmluZWQ7XG4gIGlmICh0YWlsICE9PSB1bmRlZmluZWQgJiYgIWhhc1Byb3ZpZGVyU2NoZW1hRW50cnlQb2ludCh0YWlsKSkge1xuICAgIHRocm93IG5ldyBTdHJpY3RpZmllckVycm9yKFwiYW4gdW5yZXN0cmljdGVkIHR1cGxlIHJlc3QgaXMgbm90IHN1cHBvcnRlZFwiLCBwYXRoKTtcbiAgfVxuICBjb25zdCB0YWlsTW9kZSA9IHRhaWwgIT09IHVuZGVmaW5lZCA/IFwidHlwZWRcIiA6IHJhd1RhaWwgPT09IGZhbHNlID8gXCJjbG9zZWRcIiA6IFwiaW1wbGljaXRcIjtcbiAgY29uc3QgYm91bmRzID0gbm9ybWFsaXplVHVwbGVCb3VuZHMobm9kZSwgdHVwbGUubGVuZ3RoLCB0YWlsTW9kZSwgcGF0aCk7XG4gIGNvbnN0IGJhc2UgPSBvbWl0S2V5cyhub2RlLCBbXCJpdGVtc1wiLCBcInByZWZpeEl0ZW1zXCIsIFwiYWRkaXRpb25hbEl0ZW1zXCIsIFwibWluSXRlbXNcIiwgXCJtYXhJdGVtc1wiXSk7XG5cbiAgLy8gQW50aHJvcGljIOydgCBhc3NlcnROb3JtYWxpemF0aW9uQ29tcGF0aWJpbGl0eSDqsIAg67mE7Ja0IOyeiOyngCDslYrsnYAgdHVwbGUg7J2EIOydtOuvuCDqsbDrtoDtlojsnLzrr4DroZxcbiAgLy8g7Jes6riwIOuPhOuLrO2VmOuKlCB0dXBsZSDsnYAg67mIIHR1cGxlIOu/kOydtOqzoCwg6re4IOqyveyasCBwcmVmaXhJdGVtcyBzcHJlYWQg64qUIOyekOyXsO2eiCDsg53rnrXrkJzri6Qg4oCUXG4gIC8vIHByb3ZpZGVyIOu2hOq4sCDsl4bsnbQg7ZWcIO2Yle2DnOuhnCDrkZAgcHJvdmlkZXIg66qo65GQ66W8IO2RnO2YhO2VnOuLpC5cbiAgcmV0dXJuIHtcbiAgICAuLi5iYXNlLFxuICAgIC4uLih0dXBsZS5sZW5ndGggPiAwID8geyBwcmVmaXhJdGVtczogdHVwbGUgfSA6IHt9KSxcbiAgICBpdGVtczogdGFpbCA/PyBVTlJFQUNIQUJMRV9UVVBMRV9UQUlMX1NDSEVNQSxcbiAgICAuLi5ib3VuZHMsXG4gIH07XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZVR1cGxlQm91bmRzKFxuICBub2RlOiBKc29uU2NoZW1hLFxuICB0dXBsZUxlbmd0aDogbnVtYmVyLFxuICB0YWlsTW9kZTogXCJ0eXBlZFwiIHwgXCJjbG9zZWRcIiB8IFwiaW1wbGljaXRcIixcbiAgcGF0aDogc3RyaW5nLFxuKTogeyBtaW5JdGVtczogbnVtYmVyOyBtYXhJdGVtcz86IG51bWJlciB9IHtcbiAgY29uc3QgY2FsbGVyTWluSXRlbXMgPSBpbnRlZ2VyQm91bmQob3duVmFsdWUobm9kZSwgXCJtaW5JdGVtc1wiKSwgXCJtaW5JdGVtc1wiLCBwYXRoKTtcbiAgY29uc3QgY2FsbGVyTWF4SXRlbXMgPSBpbnRlZ2VyQm91bmQob3duVmFsdWUobm9kZSwgXCJtYXhJdGVtc1wiKSwgXCJtYXhJdGVtc1wiLCBwYXRoKTtcbiAgaWYgKHRhaWxNb2RlID09PSBcImltcGxpY2l0XCIgJiYgY2FsbGVyTWF4SXRlbXMgIT09IHVuZGVmaW5lZCAmJiBjYWxsZXJNYXhJdGVtcyA+IHR1cGxlTGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IFN0cmljdGlmaWVyRXJyb3IoXG4gICAgICBcImltcGxpY2l0IHR1cGxlIHJlc3QgY2Fubm90IGJlIHJlcHJlc2VudGVkIHdoZW4gbWF4SXRlbXMgZXhjZWVkcyB0aGUgdHVwbGUgbGVuZ3RoXCIsXG4gICAgICBwYXRoLFxuICAgICk7XG4gIH1cblxuICBjb25zdCBtaW5JdGVtcyA9IGNhbGxlck1pbkl0ZW1zID8/IChjYWxsZXJNYXhJdGVtcyA9PT0gdW5kZWZpbmVkID8gdHVwbGVMZW5ndGggOiAwKTtcbiAgY29uc3QgbWF4SXRlbXMgPVxuICAgIHRhaWxNb2RlID09PSBcInR5cGVkXCIgPyBjYWxsZXJNYXhJdGVtcyA6IE1hdGgubWluKGNhbGxlck1heEl0ZW1zID8/IHR1cGxlTGVuZ3RoLCB0dXBsZUxlbmd0aCk7XG5cbiAgaWYgKG1heEl0ZW1zICE9PSB1bmRlZmluZWQgJiYgbWluSXRlbXMgPiBtYXhJdGVtcykge1xuICAgIHRocm93IG5ldyBTdHJpY3RpZmllckVycm9yKFwidHVwbGUgbWluSXRlbXMgY2Fubm90IGV4Y2VlZCBtYXhJdGVtc1wiLCBwYXRoKTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgbWluSXRlbXMsXG4gICAgLi4uKG1heEl0ZW1zICE9PSB1bmRlZmluZWQgPyB7IG1heEl0ZW1zIH0gOiB7fSksXG4gIH07XG59XG5cbmZ1bmN0aW9uIGludGVnZXJCb3VuZCh2YWx1ZTogdW5rbm93biwga2V5d29yZDogc3RyaW5nLCBwYXRoOiBzdHJpbmcpOiBudW1iZXIgfCB1bmRlZmluZWQge1xuICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcih2YWx1ZSkgfHwgKHZhbHVlIGFzIG51bWJlcikgPCAwKSB7XG4gICAgdGhyb3cgbmV3IFN0cmljdGlmaWVyRXJyb3IoYCR7a2V5d29yZH0gbXVzdCBiZSBhIG5vbi1uZWdhdGl2ZSBzYWZlIGludGVnZXJgLCBwYXRoKTtcbiAgfVxuICByZXR1cm4gdmFsdWUgYXMgbnVtYmVyO1xufVxuXG5mdW5jdGlvbiBpc1NjaGVtYU9iamVjdCh2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIEpzb25TY2hlbWEge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiICYmIHZhbHVlICE9PSBudWxsICYmICFBcnJheS5pc0FycmF5KHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gb3duVmFsdWUoc2NoZW1hOiBKc29uU2NoZW1hLCBrZXl3b3JkOiBzdHJpbmcpOiB1bmtub3duIHtcbiAgcmV0dXJuIE9iamVjdC5oYXNPd24oc2NoZW1hLCBrZXl3b3JkKSA/IHNjaGVtYVtrZXl3b3JkXSA6IHVuZGVmaW5lZDtcbn1cblxuY29uc3QgUFJPVklERVJfU0NIRU1BX0VOVFJZX1BPSU5UX0tFWVdPUkRTID0gbmV3IFNldChbXG4gIFwidHlwZVwiLFxuICBcIiRyZWZcIixcbiAgXCJwcm9wZXJ0aWVzXCIsXG4gIFwiYW55T2ZcIixcbiAgXCJvbmVPZlwiLFxuICBcImFsbE9mXCIsXG5dKTtcblxuZnVuY3Rpb24gaGFzUHJvdmlkZXJTY2hlbWFFbnRyeVBvaW50KHNjaGVtYTogSnNvblNjaGVtYSk6IGJvb2xlYW4ge1xuICByZXR1cm4gT2JqZWN0LmtleXMoc2NoZW1hKS5zb21lKChrZXkpID0+IFBST1ZJREVSX1NDSEVNQV9FTlRSWV9QT0lOVF9LRVlXT1JEUy5oYXMoa2V5KSk7XG59XG5cbmZ1bmN0aW9uIG9taXRLZXlzKG5vZGU6IEpzb25TY2hlbWEsIGtleXM6IHJlYWRvbmx5IHN0cmluZ1tdKTogSnNvblNjaGVtYSB7XG4gIGNvbnN0IG9taXR0ZWQgPSBuZXcgU2V0KGtleXMpO1xuICByZXR1cm4gT2JqZWN0LmZyb21FbnRyaWVzKE9iamVjdC5lbnRyaWVzKG5vZGUpLmZpbHRlcigoW2tleV0pID0+ICFvbWl0dGVkLmhhcyhrZXkpKSk7XG59XG5cbmZ1bmN0aW9uIG1ha2VOdWxsYWJsZShzY2hlbWE6IEpzb25TY2hlbWEpOiBKc29uU2NoZW1hIHtcbiAgaWYgKG93blZhbHVlKHNjaGVtYSwgXCJ0eXBlXCIpID09PSBcIm51bGxcIikgcmV0dXJuIHNjaGVtYTtcblxuICBjb25zdCBhbnlPZiA9IG93blZhbHVlKHNjaGVtYSwgXCJhbnlPZlwiKTtcbiAgaWYgKGFueU9mKSB7XG4gICAgY29uc3QgdmFyaWFudHMgPSBhbnlPZiBhcyBKc29uU2NoZW1hW107XG4gICAgY29uc3QgaGFzTnVsbCA9IHZhcmlhbnRzLnNvbWUoKHYpID0+IG93blZhbHVlKHYsIFwidHlwZVwiKSA9PT0gXCJudWxsXCIpO1xuICAgIGlmIChoYXNOdWxsKSByZXR1cm4gc2NoZW1hO1xuICAgIHJldHVybiB7IGFueU9mOiBbLi4udmFyaWFudHMsIHsgdHlwZTogXCJudWxsXCIgfV0gfTtcbiAgfVxuXG4gIGNvbnN0IG9uZU9mID0gb3duVmFsdWUoc2NoZW1hLCBcIm9uZU9mXCIpO1xuICBpZiAob25lT2YpIHtcbiAgICBjb25zdCB2YXJpYW50cyA9IG9uZU9mIGFzIEpzb25TY2hlbWFbXTtcbiAgICBjb25zdCBoYXNOdWxsID0gdmFyaWFudHMuc29tZSgodikgPT4gb3duVmFsdWUodiwgXCJ0eXBlXCIpID09PSBcIm51bGxcIik7XG4gICAgaWYgKGhhc051bGwpIHJldHVybiBzY2hlbWE7XG4gICAgcmV0dXJuIHsgb25lT2Y6IFsuLi52YXJpYW50cywgeyB0eXBlOiBcIm51bGxcIiB9XSB9O1xuICB9XG5cbiAgcmV0dXJuIHsgYW55T2Y6IFtzY2hlbWEsIHsgdHlwZTogXCJudWxsXCIgfV0gfTtcbn1cbiJdLCJtYXBwaW5ncyI6IjtBQWdCQSxJQUFhLG1CQUFiLGNBQXNDLE1BQU07Q0FHakM7Q0FGVCxZQUNFLFNBQ0EsTUFDQTtFQUNBLE1BQU0sZ0JBQWdCLFFBQVEsT0FBTyxLQUFLLEVBQUU7RUFGckMsS0FBQSxPQUFBO0VBR1AsS0FBSyxPQUFPO0NBQ2Q7QUFDRjtBQUVBLFNBQWdCLFVBQVUsUUFBb0IsVUFBOEIsQ0FBQyxHQUFlO0NBQzFGLElBQUksUUFBUSxhQUFhLFlB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
|