@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.
Files changed (62) hide show
  1. package/README.ko.md +7 -2
  2. package/README.md +7 -2
  3. package/bundle/dist/application/monit/monit.frame.js +3 -3
  4. package/bundle/dist/application/qgrid/oauth.js +1 -1
  5. package/bundle/dist/application/qgrid/qgrid.dispatcher.js +36 -14
  6. package/bundle/dist/application/qgrid/qgrid.frame.js +19 -5
  7. package/bundle/dist/application/qgrid/tool-emulation-schema.js +121 -0
  8. package/bundle/dist/application/qgrid/tool-emulation.js +116 -96
  9. package/bundle/dist/application/request-log/request-log.model.js +3 -3
  10. package/bundle/dist/application/request-log-step/request-log-step.model.js +2 -2
  11. package/bundle/dist/application/token/token.model.js +2 -2
  12. package/bundle/dist/server-error-handler.js +15 -0
  13. package/bundle/dist/sonamu.config.js +4 -7
  14. package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +4 -3
  15. package/bundle/dist/utils/providers/anthropic/claude-session.js +7 -5
  16. package/bundle/dist/utils/providers/common/schema-validation.js +178 -0
  17. package/bundle/dist/utils/providers/common/strictifier.js +329 -42
  18. package/bundle/dist/utils/providers/openai/codex-worker.js +16 -8
  19. package/bundle/dist/utils/providers/openai/openai-dispatcher.js +5 -37
  20. package/bundle/dist/utils/providers/openai/openai-worker-pool-config.js +37 -0
  21. package/bundle/src/application/monit/monit.frame.ts +1 -1
  22. package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +103 -0
  23. package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +337 -0
  24. package/bundle/src/application/qgrid/qgrid.dispatcher.ts +45 -25
  25. package/bundle/src/application/qgrid/qgrid.frame.test.ts +580 -8
  26. package/bundle/src/application/qgrid/qgrid.frame.ts +28 -1
  27. package/bundle/src/application/qgrid/tool-emulation-schema.test.ts +188 -0
  28. package/bundle/src/application/qgrid/tool-emulation-schema.ts +176 -0
  29. package/bundle/src/application/qgrid/tool-emulation.test.ts +285 -67
  30. package/bundle/src/application/qgrid/tool-emulation.ts +199 -102
  31. package/bundle/src/server-error-handler.ts +22 -0
  32. package/bundle/src/sonamu.config.test.ts +37 -0
  33. package/bundle/src/sonamu.config.ts +2 -5
  34. package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.test.ts +44 -0
  35. package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +2 -2
  36. package/bundle/src/utils/providers/anthropic/claude-session.test.ts +10 -0
  37. package/bundle/src/utils/providers/anthropic/claude-session.ts +6 -1
  38. package/bundle/src/utils/providers/common/schema-validation.test.ts +284 -0
  39. package/bundle/src/utils/providers/common/schema-validation.ts +308 -0
  40. package/bundle/src/utils/providers/common/strictifier.test.ts +746 -0
  41. package/bundle/src/utils/providers/common/strictifier.ts +513 -52
  42. package/bundle/src/utils/providers/openai/codex-worker.test.ts +31 -0
  43. package/bundle/src/utils/providers/openai/codex-worker.ts +12 -4
  44. package/bundle/src/utils/providers/openai/openai-dispatcher.test.ts +6 -4
  45. package/bundle/src/utils/providers/openai/openai-dispatcher.ts +6 -79
  46. package/bundle/src/utils/providers/openai/openai-worker-pool-config.ts +80 -0
  47. package/bundle/web-dist/client/assets/{index-DXdGBfB8.js → index-DiY5V2e3.js} +3 -3
  48. package/bundle/web-dist/client/assets/{logs-D_j1yxC4.js → logs-UZ4Cvdmc.js} +1 -1
  49. package/bundle/web-dist/client/assets/{monit-CIToyoxW.js → monit-C5cJo-HD.js} +1 -1
  50. package/bundle/web-dist/client/assets/{routes-Dd21A-wi.js → routes-DEKEmoQN.js} +1 -1
  51. package/bundle/web-dist/client/assets/{show-DfePWRbc.js → show-DnX6b8KG.js} +1 -1
  52. package/bundle/web-dist/client/assets/{tokens-B4MV2fdk.js → tokens-Ct0FGD4b.js} +1 -1
  53. package/bundle/web-dist/client/index.html +1 -1
  54. package/bundle/web-dist/server/entry-server.generated.js +1 -1
  55. package/package.json +1 -1
  56. package/skills/qgrid/references/ai-sdk-provider-contract.md +34 -2
  57. package/skills/qgrid/references/anthropic-claude-code-runtime.md +3 -0
  58. package/skills/qgrid/references/cli-env-and-server-boot.md +1 -1
  59. package/skills/qgrid/references/decision-rationale.md +10 -1
  60. package/skills/qgrid/references/repo-map.md +2 -1
  61. package/skills/qgrid/references/tool-calling-and-multiturn.md +33 -6
  62. 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
- return strictifyNode(schema, "$");
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
- function strictifyNode(node, path) {
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
- const type = node.type;
16
- if (type === "object" || node.properties) return strictifyObject(node, path);
17
- if (type === "array") return strictifyArray(node, path);
18
- if (node.anyOf) return {
19
- ...node,
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
- function strictifyObject(node, path) {
34
- const properties = node.properties;
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.required ?? []);
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
- if (!existingRequired.has(key)) strictProps[key] = makeNullable(strictProp);
46
- else strictProps[key] = strictProp;
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
- function strictifyArray(node, path) {
57
- const items = node.items;
58
- if (!items) return { ...node };
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
- items: strictifyNode(items, `${path}.items`)
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.type === "null") return schema;
66
- if (schema.anyOf) {
67
- const variants = schema.anyOf;
68
- if (variants.some((v) => v.type === "null")) return schema;
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
- if (schema.oneOf) {
72
- const variants = schema.oneOf;
73
- if (variants.some((v) => v.type === "null")) return schema;
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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