velocious 1.0.493 → 1.0.494
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/build/database/drivers/base.js +6 -0
- package/build/database/query/insert-base.js +1 -1
- package/build/src/database/drivers/base.d.ts +5 -0
- package/build/src/database/drivers/base.d.ts.map +1 -1
- package/build/src/database/drivers/base.js +6 -1
- package/build/src/database/query/insert-base.js +2 -2
- package/build/src/sync/server-sequence-allocator.d.ts +106 -0
- package/build/src/sync/server-sequence-allocator.d.ts.map +1 -0
- package/build/src/sync/server-sequence-allocator.js +220 -0
- package/build/src/sync/sync-attribute-normalizer.d.ts +105 -0
- package/build/src/sync/sync-attribute-normalizer.d.ts.map +1 -0
- package/build/src/sync/sync-attribute-normalizer.js +172 -0
- package/build/src/sync/sync-resource-base.d.ts +48 -0
- package/build/src/sync/sync-resource-base.d.ts.map +1 -1
- package/build/src/sync/sync-resource-base.js +89 -1
- package/build/sync/server-sequence-allocator.js +246 -0
- package/build/sync/sync-attribute-normalizer.js +186 -0
- package/build/sync/sync-resource-base.js +103 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/database/drivers/base.js +6 -0
- package/src/database/query/insert-base.js +1 -1
- package/src/sync/server-sequence-allocator.js +246 -0
- package/src/sync/sync-attribute-normalizer.js +186 -0
- package/src/sync/sync-resource-base.js +103 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { snakeCaseKey } from "typanic";
|
|
3
|
+
/**
|
|
4
|
+
* Builds the error thrown for a failed sync attribute validation.
|
|
5
|
+
* @callback SyncAttributeErrorFactory
|
|
6
|
+
* @param {string} message - Human-readable validation message.
|
|
7
|
+
* @param {{cause?: Error, code: string}} details - Stable machine-readable code and optional cause.
|
|
8
|
+
* @returns {Error} Error to throw.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Declarative validation schema for one writable sync attribute.
|
|
12
|
+
*
|
|
13
|
+
* Keys are camelCase attribute names; each attribute also accepts its
|
|
14
|
+
* snake_case column key on input (the camelCase key wins when both are given)
|
|
15
|
+
* and is written under the snake_case column key on output. Error messages
|
|
16
|
+
* default to `<label> ...` phrasings with `sync-<label>-...` codes, where the
|
|
17
|
+
* label defaults to the camelCase attribute name; apps pin exact messages per
|
|
18
|
+
* attribute through the `*Message` overrides.
|
|
19
|
+
* @typedef {object} SyncAttributeSchemaEntry
|
|
20
|
+
* @property {"date" | "json" | "raw" | "string"} type - Attribute value type.
|
|
21
|
+
* @property {boolean} [required] - Whether present blank/absent values are rejected (strings reject blank-after-trim, dates reject null).
|
|
22
|
+
* @property {number} [maxLength] - Maximum string length, checked after trimming.
|
|
23
|
+
* @property {string} [label] - Label used in derived messages and codes.
|
|
24
|
+
* @property {string} [column] - Output column key. Defaults to the snake_cased attribute name.
|
|
25
|
+
* @property {string} [requiredMessage] - Pinned message for required rejections.
|
|
26
|
+
* @property {string} [tooLongMessage] - Pinned message for too-long rejections.
|
|
27
|
+
* @property {string} [invalidMessage] - Pinned message for invalid dates and non-object/non-string json values.
|
|
28
|
+
* @property {string} [invalidJsonMessage] - Pinned message for unparseable json strings.
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* Normalizes writable sync attributes against a declarative schema.
|
|
32
|
+
*
|
|
33
|
+
* Only present keys are validated, so required attributes may be absent —
|
|
34
|
+
* create defaults own that concern. Input keys not declared in the schema are
|
|
35
|
+
* rejected by default so misspelled or read-only attributes fail loudly
|
|
36
|
+
* instead of being silently discarded (`unknownAttributes: "ignore"` opts
|
|
37
|
+
* out). Validation failures throw through the given error factory so apps
|
|
38
|
+
* control the raised error class.
|
|
39
|
+
* @param {object} args - Options.
|
|
40
|
+
* @param {Record<string, ?>} args.attributes - Raw incoming attributes (camelCase and/or snake_case keys).
|
|
41
|
+
* @param {SyncAttributeErrorFactory} args.errorFactory - Maps validation failures to thrown errors.
|
|
42
|
+
* @param {Record<string, SyncAttributeSchemaEntry>} args.schema - Attribute schema keyed by camelCase attribute name.
|
|
43
|
+
* @param {"error" | "ignore"} [args.unknownAttributes] - Unknown input-key handling. Defaults to "error".
|
|
44
|
+
* @returns {Record<string, ?>} Normalized values keyed by snake_case column names.
|
|
45
|
+
*/
|
|
46
|
+
export default function normalizeAttributesWithSchema({ attributes, errorFactory, schema, unknownAttributes = "error" }) {
|
|
47
|
+
if (!attributes || typeof attributes != "object")
|
|
48
|
+
throw new Error(`normalizeAttributesWithSchema requires an attributes object, got: ${String(attributes)}`);
|
|
49
|
+
if (typeof errorFactory != "function")
|
|
50
|
+
throw new Error("normalizeAttributesWithSchema requires an errorFactory function");
|
|
51
|
+
if (!schema || typeof schema != "object")
|
|
52
|
+
throw new Error(`normalizeAttributesWithSchema requires a schema object, got: ${String(schema)}`);
|
|
53
|
+
if (unknownAttributes != "error" && unknownAttributes != "ignore") {
|
|
54
|
+
throw new Error(`normalizeAttributesWithSchema unknownAttributes must be "error" or "ignore", got: ${String(unknownAttributes)}`);
|
|
55
|
+
}
|
|
56
|
+
/** @type {Record<string, ?>} */
|
|
57
|
+
const normalized = {};
|
|
58
|
+
/** @type {Set<string>} */
|
|
59
|
+
const knownInputKeys = new Set();
|
|
60
|
+
for (const [attributeName, entry] of Object.entries(schema)) {
|
|
61
|
+
const column = entry.column ?? snakeCaseKey(attributeName);
|
|
62
|
+
const inputKeys = column == attributeName ? [attributeName] : [column, attributeName];
|
|
63
|
+
for (const inputKey of inputKeys) {
|
|
64
|
+
knownInputKeys.add(inputKey);
|
|
65
|
+
if (!Object.prototype.hasOwnProperty.call(attributes, inputKey))
|
|
66
|
+
continue;
|
|
67
|
+
normalized[column] = normalizeAttributeValue({ attributeName, entry, errorFactory, value: attributes[inputKey] });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (unknownAttributes == "error") {
|
|
71
|
+
for (const inputKey of Object.keys(attributes)) {
|
|
72
|
+
if (!knownInputKeys.has(inputKey)) {
|
|
73
|
+
throw errorFactory(`Unknown attribute: ${inputKey}.`, { code: "sync-unknown-attribute" });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return normalized;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Normalizes one present attribute value per its schema entry.
|
|
81
|
+
* @param {object} args - Options.
|
|
82
|
+
* @param {string} args.attributeName - camelCase attribute name.
|
|
83
|
+
* @param {SyncAttributeSchemaEntry} args.entry - Schema entry.
|
|
84
|
+
* @param {SyncAttributeErrorFactory} args.errorFactory - Error factory.
|
|
85
|
+
* @param {?} args.value - Raw value.
|
|
86
|
+
* @returns {?} Normalized value.
|
|
87
|
+
*/
|
|
88
|
+
function normalizeAttributeValue({ attributeName, entry, errorFactory, value }) {
|
|
89
|
+
const label = entry.label ?? attributeName;
|
|
90
|
+
if (entry.type == "string")
|
|
91
|
+
return normalizeString({ entry, errorFactory, label, value });
|
|
92
|
+
if (entry.type == "date")
|
|
93
|
+
return normalizeDate({ entry, errorFactory, label, value });
|
|
94
|
+
if (entry.type == "json")
|
|
95
|
+
return normalizeJson({ entry, errorFactory, label, value });
|
|
96
|
+
if (entry.type == "raw")
|
|
97
|
+
return value;
|
|
98
|
+
throw new Error(`Unknown sync attribute schema type for ${attributeName}: ${String(entry.type)}`);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Normalizes a string attribute: trims, rejects blank required values after trimming, maps empty optional values to null and bounds the trimmed length.
|
|
102
|
+
* @param {object} args - Options.
|
|
103
|
+
* @param {SyncAttributeSchemaEntry} args.entry - Schema entry.
|
|
104
|
+
* @param {SyncAttributeErrorFactory} args.errorFactory - Error factory.
|
|
105
|
+
* @param {string} args.label - Message/code label.
|
|
106
|
+
* @param {?} args.value - Raw value.
|
|
107
|
+
* @returns {string | null} Normalized string.
|
|
108
|
+
*/
|
|
109
|
+
function normalizeString({ entry, errorFactory, label, value }) {
|
|
110
|
+
const requiredError = () => errorFactory(entry.requiredMessage ?? `${label} is required.`, { code: `sync-${label}-required` });
|
|
111
|
+
if (value === null || value === undefined || value === "") {
|
|
112
|
+
if (entry.required)
|
|
113
|
+
throw requiredError();
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
const stringValue = String(value).trim();
|
|
117
|
+
if (stringValue === "") {
|
|
118
|
+
if (entry.required)
|
|
119
|
+
throw requiredError();
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
if (entry.maxLength !== undefined && stringValue.length > entry.maxLength) {
|
|
123
|
+
throw errorFactory(entry.tooLongMessage ?? `${label} is too long (maximum is ${entry.maxLength} characters).`, { code: `sync-${label}-too-long` });
|
|
124
|
+
}
|
|
125
|
+
return stringValue;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Normalizes a date attribute: Date instances pass through, strings/numbers are parsed and invalid or missing-required values are rejected.
|
|
129
|
+
* @param {object} args - Options.
|
|
130
|
+
* @param {SyncAttributeSchemaEntry} args.entry - Schema entry.
|
|
131
|
+
* @param {SyncAttributeErrorFactory} args.errorFactory - Error factory.
|
|
132
|
+
* @param {string} args.label - Message/code label.
|
|
133
|
+
* @param {?} args.value - Raw value.
|
|
134
|
+
* @returns {Date | null} Normalized date.
|
|
135
|
+
*/
|
|
136
|
+
function normalizeDate({ entry, errorFactory, label, value }) {
|
|
137
|
+
if (!entry.required && (value === null || value === undefined || value === ""))
|
|
138
|
+
return null;
|
|
139
|
+
const dateValue = value instanceof Date ? value : typeof value == "string" || typeof value == "number" ? new Date(value) : null;
|
|
140
|
+
if (!dateValue || Number.isNaN(dateValue.getTime())) {
|
|
141
|
+
throw errorFactory(entry.invalidMessage ?? `${label} must be a valid datetime.`, { code: `sync-${label}-invalid-datetime` });
|
|
142
|
+
}
|
|
143
|
+
return dateValue;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Normalizes a json attribute: empty values become null, objects pass through, strings must parse as JSON and other types are rejected.
|
|
147
|
+
* @param {object} args - Options.
|
|
148
|
+
* @param {SyncAttributeSchemaEntry} args.entry - Schema entry.
|
|
149
|
+
* @param {SyncAttributeErrorFactory} args.errorFactory - Error factory.
|
|
150
|
+
* @param {string} args.label - Message/code label.
|
|
151
|
+
* @param {?} args.value - Raw value.
|
|
152
|
+
* @returns {?} Normalized json value.
|
|
153
|
+
*/
|
|
154
|
+
function normalizeJson({ entry, errorFactory, label, value }) {
|
|
155
|
+
if (value === null || value === undefined || value === "")
|
|
156
|
+
return null;
|
|
157
|
+
if (typeof value == "object")
|
|
158
|
+
return value;
|
|
159
|
+
if (typeof value == "string") {
|
|
160
|
+
try {
|
|
161
|
+
return JSON.parse(value);
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
throw errorFactory(entry.invalidJsonMessage ?? `${label} must be valid JSON.`, {
|
|
165
|
+
cause: /** @type {Error} */ (error),
|
|
166
|
+
code: `sync-${label}-invalid-json`
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
throw errorFactory(entry.invalidMessage ?? `${label} must be an object or JSON string.`, { code: `sync-${label}-invalid` });
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1hdHRyaWJ1dGUtbm9ybWFsaXplci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zeW5jL3N5bmMtYXR0cmlidXRlLW5vcm1hbGl6ZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxTQUFTLENBQUE7QUFFcEM7Ozs7OztHQU1HO0FBRUg7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtQkc7QUFFSDs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFDSCxNQUFNLENBQUMsT0FBTyxVQUFVLDZCQUE2QixDQUFDLEVBQUMsVUFBVSxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsaUJBQWlCLEdBQUcsT0FBTyxFQUFDO0lBQ25ILElBQUksQ0FBQyxVQUFVLElBQUksT0FBTyxVQUFVLElBQUksUUFBUTtRQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMscUVBQXFFLE1BQU0sQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUE7SUFDNUosSUFBSSxPQUFPLFlBQVksSUFBSSxVQUFVO1FBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxpRUFBaUUsQ0FBQyxDQUFBO0lBQ3pILElBQUksQ0FBQyxNQUFNLElBQUksT0FBTyxNQUFNLElBQUksUUFBUTtRQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0VBQWdFLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUE7SUFDM0ksSUFBSSxpQkFBaUIsSUFBSSxPQUFPLElBQUksaUJBQWlCLElBQUksUUFBUSxFQUFFLENBQUM7UUFDbEUsTUFBTSxJQUFJLEtBQUssQ0FBQyxxRkFBcUYsTUFBTSxDQUFDLGlCQUFpQixDQUFDLEVBQUUsQ0FBQyxDQUFBO0lBQ25JLENBQUM7SUFFRCxnQ0FBZ0M7SUFDaEMsTUFBTSxVQUFVLEdBQUcsRUFBRSxDQUFBO0lBQ3JCLDBCQUEwQjtJQUMxQixNQUFNLGNBQWMsR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFBO0lBRWhDLEtBQUssTUFBTSxDQUFDLGFBQWEsRUFBRSxLQUFLLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7UUFDNUQsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU0sSUFBSSxZQUFZLENBQUMsYUFBYSxDQUFDLENBQUE7UUFDMUQsTUFBTSxTQUFTLEdBQUcsTUFBTSxJQUFJLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsYUFBYSxDQUFDLENBQUE7UUFFckYsS0FBSyxNQUFNLFFBQVEsSUFBSSxTQUFTLEVBQUUsQ0FBQztZQUNqQyxjQUFjLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFBO1lBRTVCLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLFFBQVEsQ0FBQztnQkFBRSxTQUFRO1lBRXpFLFVBQVUsQ0FBQyxNQUFNLENBQUMsR0FBRyx1QkFBdUIsQ0FBQyxFQUFDLGFBQWEsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxVQUFVLENBQUMsUUFBUSxDQUFDLEVBQUMsQ0FBQyxDQUFBO1FBQ2pILENBQUM7SUFDSCxDQUFDO0lBRUQsSUFBSSxpQkFBaUIsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUNqQyxLQUFLLE1BQU0sUUFBUSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztZQUMvQyxJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO2dCQUNsQyxNQUFNLFlBQVksQ0FBQyxzQkFBc0IsUUFBUSxHQUFHLEVBQUUsRUFBQyxJQUFJLEVBQUUsd0JBQXdCLEVBQUMsQ0FBQyxDQUFBO1lBQ3pGLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVELE9BQU8sVUFBVSxDQUFBO0FBQ25CLENBQUM7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILFNBQVMsdUJBQXVCLENBQUMsRUFBQyxhQUFhLEVBQUUsS0FBSyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQUM7SUFDMUUsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUssSUFBSSxhQUFhLENBQUE7SUFFMUMsSUFBSSxLQUFLLENBQUMsSUFBSSxJQUFJLFFBQVE7UUFBRSxPQUFPLGVBQWUsQ0FBQyxFQUFDLEtBQUssRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBQyxDQUFDLENBQUE7SUFDdkYsSUFBSSxLQUFLLENBQUMsSUFBSSxJQUFJLE1BQU07UUFBRSxPQUFPLGFBQWEsQ0FBQyxFQUFDLEtBQUssRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBQyxDQUFDLENBQUE7SUFDbkYsSUFBSSxLQUFLLENBQUMsSUFBSSxJQUFJLE1BQU07UUFBRSxPQUFPLGFBQWEsQ0FBQyxFQUFDLEtBQUssRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBQyxDQUFDLENBQUE7SUFDbkYsSUFBSSxLQUFLLENBQUMsSUFBSSxJQUFJLEtBQUs7UUFBRSxPQUFPLEtBQUssQ0FBQTtJQUVyQyxNQUFNLElBQUksS0FBSyxDQUFDLDBDQUEwQyxhQUFhLEtBQUssTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUE7QUFDbkcsQ0FBQztBQUVEOzs7Ozs7OztHQVFHO0FBQ0gsU0FBUyxlQUFlLENBQUMsRUFBQyxLQUFLLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUM7SUFDMUQsTUFBTSxhQUFhLEdBQUcsR0FBRyxFQUFFLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxlQUFlLElBQUksR0FBRyxLQUFLLGVBQWUsRUFBRSxFQUFDLElBQUksRUFBRSxRQUFRLEtBQUssV0FBVyxFQUFDLENBQUMsQ0FBQTtJQUU1SCxJQUFJLEtBQUssS0FBSyxJQUFJLElBQUksS0FBSyxLQUFLLFNBQVMsSUFBSSxLQUFLLEtBQUssRUFBRSxFQUFFLENBQUM7UUFDMUQsSUFB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LWNoZWNrXG5cbmltcG9ydCB7c25ha2VDYXNlS2V5fSBmcm9tIFwidHlwYW5pY1wiXG5cbi8qKlxuICogQnVpbGRzIHRoZSBlcnJvciB0aHJvd24gZm9yIGEgZmFpbGVkIHN5bmMgYXR0cmlidXRlIHZhbGlkYXRpb24uXG4gKiBAY2FsbGJhY2sgU3luY0F0dHJpYnV0ZUVycm9yRmFjdG9yeVxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBIdW1hbi1yZWFkYWJsZSB2YWxpZGF0aW9uIG1lc3NhZ2UuXG4gKiBAcGFyYW0ge3tjYXVzZT86IEVycm9yLCBjb2RlOiBzdHJpbmd9fSBkZXRhaWxzIC0gU3RhYmxlIG1hY2hpbmUtcmVhZGFibGUgY29kZSBhbmQgb3B0aW9uYWwgY2F1c2UuXG4gKiBAcmV0dXJucyB7RXJyb3J9IEVycm9yIHRvIHRocm93LlxuICovXG5cbi8qKlxuICogRGVjbGFyYXRpdmUgdmFsaWRhdGlvbiBzY2hlbWEgZm9yIG9uZSB3cml0YWJsZSBzeW5jIGF0dHJpYnV0ZS5cbiAqXG4gKiBLZXlzIGFyZSBjYW1lbENhc2UgYXR0cmlidXRlIG5hbWVzOyBlYWNoIGF0dHJpYnV0ZSBhbHNvIGFjY2VwdHMgaXRzXG4gKiBzbmFrZV9jYXNlIGNvbHVtbiBrZXkgb24gaW5wdXQgKHRoZSBjYW1lbENhc2Uga2V5IHdpbnMgd2hlbiBib3RoIGFyZSBnaXZlbilcbiAqIGFuZCBpcyB3cml0dGVuIHVuZGVyIHRoZSBzbmFrZV9jYXNlIGNvbHVtbiBrZXkgb24gb3V0cHV0LiBFcnJvciBtZXNzYWdlc1xuICogZGVmYXVsdCB0byBgPGxhYmVsPiAuLi5gIHBocmFzaW5ncyB3aXRoIGBzeW5jLTxsYWJlbD4tLi4uYCBjb2Rlcywgd2hlcmUgdGhlXG4gKiBsYWJlbCBkZWZhdWx0cyB0byB0aGUgY2FtZWxDYXNlIGF0dHJpYnV0ZSBuYW1lOyBhcHBzIHBpbiBleGFjdCBtZXNzYWdlcyBwZXJcbiAqIGF0dHJpYnV0ZSB0aHJvdWdoIHRoZSBgKk1lc3NhZ2VgIG92ZXJyaWRlcy5cbiAqIEB0eXBlZGVmIHtvYmplY3R9IFN5bmNBdHRyaWJ1dGVTY2hlbWFFbnRyeVxuICogQHByb3BlcnR5IHtcImRhdGVcIiB8IFwianNvblwiIHwgXCJyYXdcIiB8IFwic3RyaW5nXCJ9IHR5cGUgLSBBdHRyaWJ1dGUgdmFsdWUgdHlwZS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW3JlcXVpcmVkXSAtIFdoZXRoZXIgcHJlc2VudCBibGFuay9hYnNlbnQgdmFsdWVzIGFyZSByZWplY3RlZCAoc3RyaW5ncyByZWplY3QgYmxhbmstYWZ0ZXItdHJpbSwgZGF0ZXMgcmVqZWN0IG51bGwpLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFttYXhMZW5ndGhdIC0gTWF4aW11bSBzdHJpbmcgbGVuZ3RoLCBjaGVja2VkIGFmdGVyIHRyaW1taW5nLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtsYWJlbF0gLSBMYWJlbCB1c2VkIGluIGRlcml2ZWQgbWVzc2FnZXMgYW5kIGNvZGVzLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtjb2x1bW5dIC0gT3V0cHV0IGNvbHVtbiBrZXkuIERlZmF1bHRzIHRvIHRoZSBzbmFrZV9jYXNlZCBhdHRyaWJ1dGUgbmFtZS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbcmVxdWlyZWRNZXNzYWdlXSAtIFBpbm5lZCBtZXNzYWdlIGZvciByZXF1aXJlZCByZWplY3Rpb25zLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFt0b29Mb25nTWVzc2FnZV0gLSBQaW5uZWQgbWVzc2FnZSBmb3IgdG9vLWxvbmcgcmVqZWN0aW9ucy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbaW52YWxpZE1lc3NhZ2VdIC0gUGlubmVkIG1lc3NhZ2UgZm9yIGludmFsaWQgZGF0ZXMgYW5kIG5vbi1vYmplY3Qvbm9uLXN0cmluZyBqc29uIHZhbHVlcy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbaW52YWxpZEpzb25NZXNzYWdlXSAtIFBpbm5lZCBtZXNzYWdlIGZvciB1bnBhcnNlYWJsZSBqc29uIHN0cmluZ3MuXG4gKi9cblxuLyoqXG4gKiBOb3JtYWxpemVzIHdyaXRhYmxlIHN5bmMgYXR0cmlidXRlcyBhZ2FpbnN0IGEgZGVjbGFyYXRpdmUgc2NoZW1hLlxuICpcbiAqIE9ubHkgcHJlc2VudCBrZXlzIGFyZSB2YWxpZGF0ZWQsIHNvIHJlcXVpcmVkIGF0dHJpYnV0ZXMgbWF5IGJlIGFic2VudCDigJRcbiAqIGNyZWF0ZSBkZWZhdWx0cyBvd24gdGhhdCBjb25jZXJuLiBJbnB1dCBrZXlzIG5vdCBkZWNsYXJlZCBpbiB0aGUgc2NoZW1hIGFyZVxuICogcmVqZWN0ZWQgYnkgZGVmYXVsdCBzbyBtaXNzcGVsbGVkIG9yIHJlYWQtb25seSBhdHRyaWJ1dGVzIGZhaWwgbG91ZGx5XG4gKiBpbnN0ZWFkIG9mIGJlaW5nIHNpbGVudGx5IGRpc2NhcmRlZCAoYHVua25vd25BdHRyaWJ1dGVzOiBcImlnbm9yZVwiYCBvcHRzXG4gKiBvdXQpLiBWYWxpZGF0aW9uIGZhaWx1cmVzIHRocm93IHRocm91Z2ggdGhlIGdpdmVuIGVycm9yIGZhY3Rvcnkgc28gYXBwc1xuICogY29udHJvbCB0aGUgcmFpc2VkIGVycm9yIGNsYXNzLlxuICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zLlxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gYXJncy5hdHRyaWJ1dGVzIC0gUmF3IGluY29taW5nIGF0dHJpYnV0ZXMgKGNhbWVsQ2FzZSBhbmQvb3Igc25ha2VfY2FzZSBrZXlzKS5cbiAqIEBwYXJhbSB7U3luY0F0dHJpYnV0ZUVycm9yRmFjdG9yeX0gYXJncy5lcnJvckZhY3RvcnkgLSBNYXBzIHZhbGlkYXRpb24gZmFpbHVyZXMgdG8gdGhyb3duIGVycm9ycy5cbiAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgU3luY0F0dHJpYnV0ZVNjaGVtYUVudHJ5Pn0gYXJncy5zY2hlbWEgLSBBdHRyaWJ1dGUgc2NoZW1hIGtleWVkIGJ5IGNhbWVsQ2FzZSBhdHRyaWJ1dGUgbmFtZS5cbiAqIEBwYXJhbSB7XCJlcnJvclwiIHwgXCJpZ25vcmVcIn0gW2FyZ3MudW5rbm93bkF0dHJpYnV0ZXNdIC0gVW5rbm93biBpbnB1dC1rZXkgaGFuZGxpbmcuIERlZmF1bHRzIHRvIFwiZXJyb3JcIi5cbiAqIEByZXR1cm5zIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gTm9ybWFsaXplZCB2YWx1ZXMga2V5ZWQgYnkgc25ha2VfY2FzZSBjb2x1bW4gbmFtZXMuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIG5vcm1hbGl6ZUF0dHJpYnV0ZXNXaXRoU2NoZW1hKHthdHRyaWJ1dGVzLCBlcnJvckZhY3RvcnksIHNjaGVtYSwgdW5rbm93bkF0dHJpYnV0ZXMgPSBcImVycm9yXCJ9KSB7XG4gIGlmICghYXR0cmlidXRlcyB8fCB0eXBlb2YgYXR0cmlidXRlcyAhPSBcIm9iamVjdFwiKSB0aHJvdyBuZXcgRXJyb3IoYG5vcm1hbGl6ZUF0dHJpYnV0ZXNXaXRoU2NoZW1hIHJlcXVpcmVzIGFuIGF0dHJpYnV0ZXMgb2JqZWN0LCBnb3Q6ICR7U3RyaW5nKGF0dHJpYnV0ZXMpfWApXG4gIGlmICh0eXBlb2YgZXJyb3JGYWN0b3J5ICE9IFwiZnVuY3Rpb25cIikgdGhyb3cgbmV3IEVycm9yKFwibm9ybWFsaXplQXR0cmlidXRlc1dpdGhTY2hlbWEgcmVxdWlyZXMgYW4gZXJyb3JGYWN0b3J5IGZ1bmN0aW9uXCIpXG4gIGlmICghc2NoZW1hIHx8IHR5cGVvZiBzY2hlbWEgIT0gXCJvYmplY3RcIikgdGhyb3cgbmV3IEVycm9yKGBub3JtYWxpemVBdHRyaWJ1dGVzV2l0aFNjaGVtYSByZXF1aXJlcyBhIHNjaGVtYSBvYmplY3QsIGdvdDogJHtTdHJpbmcoc2NoZW1hKX1gKVxuICBpZiAodW5rbm93bkF0dHJpYnV0ZXMgIT0gXCJlcnJvclwiICYmIHVua25vd25BdHRyaWJ1dGVzICE9IFwiaWdub3JlXCIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYG5vcm1hbGl6ZUF0dHJpYnV0ZXNXaXRoU2NoZW1hIHVua25vd25BdHRyaWJ1dGVzIG11c3QgYmUgXCJlcnJvclwiIG9yIFwiaWdub3JlXCIsIGdvdDogJHtTdHJpbmcodW5rbm93bkF0dHJpYnV0ZXMpfWApXG4gIH1cblxuICAvKiogQHR5cGUge1JlY29yZDxzdHJpbmcsID8+fSAqL1xuICBjb25zdCBub3JtYWxpemVkID0ge31cbiAgLyoqIEB0eXBlIHtTZXQ8c3RyaW5nPn0gKi9cbiAgY29uc3Qga25vd25JbnB1dEtleXMgPSBuZXcgU2V0KClcblxuICBmb3IgKGNvbnN0IFthdHRyaWJ1dGVOYW1lLCBlbnRyeV0gb2YgT2JqZWN0LmVudHJpZXMoc2NoZW1hKSkge1xuICAgIGNvbnN0IGNvbHVtbiA9IGVudHJ5LmNvbHVtbiA/PyBzbmFrZUNhc2VLZXkoYXR0cmlidXRlTmFtZSlcbiAgICBjb25zdCBpbnB1dEtleXMgPSBjb2x1bW4gPT0gYXR0cmlidXRlTmFtZSA/IFthdHRyaWJ1dGVOYW1lXSA6IFtjb2x1bW4sIGF0dHJpYnV0ZU5hbWVdXG5cbiAgICBmb3IgKGNvbnN0IGlucHV0S2V5IG9mIGlucHV0S2V5cykge1xuICAgICAga25vd25JbnB1dEtleXMuYWRkKGlucHV0S2V5KVxuXG4gICAgICBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChhdHRyaWJ1dGVzLCBpbnB1dEtleSkpIGNvbnRpbnVlXG5cbiAgICAgIG5vcm1hbGl6ZWRbY29sdW1uXSA9IG5vcm1hbGl6ZUF0dHJpYnV0ZVZhbHVlKHthdHRyaWJ1dGVOYW1lLCBlbnRyeSwgZXJyb3JGYWN0b3J5LCB2YWx1ZTogYXR0cmlidXRlc1tpbnB1dEtleV19KVxuICAgIH1cbiAgfVxuXG4gIGlmICh1bmtub3duQXR0cmlidXRlcyA9PSBcImVycm9yXCIpIHtcbiAgICBmb3IgKGNvbnN0IGlucHV0S2V5IG9mIE9iamVjdC5rZXlzKGF0dHJpYnV0ZXMpKSB7XG4gICAgICBpZiAoIWtub3duSW5wdXRLZXlzLmhhcyhpbnB1dEtleSkpIHtcbiAgICAgICAgdGhyb3cgZXJyb3JGYWN0b3J5KGBVbmtub3duIGF0dHJpYnV0ZTogJHtpbnB1dEtleX0uYCwge2NvZGU6IFwic3luYy11bmtub3duLWF0dHJpYnV0ZVwifSlcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gbm9ybWFsaXplZFxufVxuXG4vKipcbiAqIE5vcm1hbGl6ZXMgb25lIHByZXNlbnQgYXR0cmlidXRlIHZhbHVlIHBlciBpdHMgc2NoZW1hIGVudHJ5LlxuICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zLlxuICogQHBhcmFtIHtzdHJpbmd9IGFyZ3MuYXR0cmlidXRlTmFtZSAtIGNhbWVsQ2FzZSBhdHRyaWJ1dGUgbmFtZS5cbiAqIEBwYXJhbSB7U3luY0F0dHJpYnV0ZVNjaGVtYUVudHJ5fSBhcmdzLmVudHJ5IC0gU2NoZW1hIGVudHJ5LlxuICogQHBhcmFtIHtTeW5jQXR0cmlidXRlRXJyb3JGYWN0b3J5fSBhcmdzLmVycm9yRmFjdG9yeSAtIEVycm9yIGZhY3RvcnkuXG4gKiBAcGFyYW0gez99IGFyZ3MudmFsdWUgLSBSYXcgdmFsdWUuXG4gKiBAcmV0dXJucyB7P30gTm9ybWFsaXplZCB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplQXR0cmlidXRlVmFsdWUoe2F0dHJpYnV0ZU5hbWUsIGVudHJ5LCBlcnJvckZhY3RvcnksIHZhbHVlfSkge1xuICBjb25zdCBsYWJlbCA9IGVudHJ5LmxhYmVsID8/IGF0dHJpYnV0ZU5hbWVcblxuICBpZiAoZW50cnkudHlwZSA9PSBcInN0cmluZ1wiKSByZXR1cm4gbm9ybWFsaXplU3RyaW5nKHtlbnRyeSwgZXJyb3JGYWN0b3J5LCBsYWJlbCwgdmFsdWV9KVxuICBpZiAoZW50cnkudHlwZSA9PSBcImRhdGVcIikgcmV0dXJuIG5vcm1hbGl6ZURhdGUoe2VudHJ5LCBlcnJvckZhY3RvcnksIGxhYmVsLCB2YWx1ZX0pXG4gIGlmIChlbnRyeS50eXBlID09IFwianNvblwiKSByZXR1cm4gbm9ybWFsaXplSnNvbih7ZW50cnksIGVycm9yRmFjdG9yeSwgbGFiZWwsIHZhbHVlfSlcbiAgaWYgKGVudHJ5LnR5cGUgPT0gXCJyYXdcIikgcmV0dXJuIHZhbHVlXG5cbiAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIHN5bmMgYXR0cmlidXRlIHNjaGVtYSB0eXBlIGZvciAke2F0dHJpYnV0ZU5hbWV9OiAke1N0cmluZyhlbnRyeS50eXBlKX1gKVxufVxuXG4vKipcbiAqIE5vcm1hbGl6ZXMgYSBzdHJpbmcgYXR0cmlidXRlOiB0cmltcywgcmVqZWN0cyBibGFuayByZXF1aXJlZCB2YWx1ZXMgYWZ0ZXIgdHJpbW1pbmcsIG1hcHMgZW1wdHkgb3B0aW9uYWwgdmFsdWVzIHRvIG51bGwgYW5kIGJvdW5kcyB0aGUgdHJpbW1lZCBsZW5ndGguXG4gKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIE9wdGlvbnMuXG4gKiBAcGFyYW0ge1N5bmNBdHRyaWJ1dGVTY2hlbWFFbnRyeX0gYXJncy5lbnRyeSAtIFNjaGVtYSBlbnRyeS5cbiAqIEBwYXJhbSB7U3luY0F0dHJpYnV0ZUVycm9yRmFjdG9yeX0gYXJncy5lcnJvckZhY3RvcnkgLSBFcnJvciBmYWN0b3J5LlxuICogQHBhcmFtIHtzdHJpbmd9IGFyZ3MubGFiZWwgLSBNZXNzYWdlL2NvZGUgbGFiZWwuXG4gKiBAcGFyYW0gez99IGFyZ3MudmFsdWUgLSBSYXcgdmFsdWUuXG4gKiBAcmV0dXJucyB7c3RyaW5nIHwgbnVsbH0gTm9ybWFsaXplZCBzdHJpbmcuXG4gKi9cbmZ1bmN0aW9uIG5vcm1hbGl6ZVN0cmluZyh7ZW50cnksIGVycm9yRmFjdG9yeSwgbGFiZWwsIHZhbHVlfSkge1xuICBjb25zdCByZXF1aXJlZEVycm9yID0gKCkgPT4gZXJyb3JGYWN0b3J5KGVudHJ5LnJlcXVpcmVkTWVzc2FnZSA/PyBgJHtsYWJlbH0gaXMgcmVxdWlyZWQuYCwge2NvZGU6IGBzeW5jLSR7bGFiZWx9LXJlcXVpcmVkYH0pXG5cbiAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT09IFwiXCIpIHtcbiAgICBpZiAoZW50cnkucmVxdWlyZWQpIHRocm93IHJlcXVpcmVkRXJyb3IoKVxuXG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIGNvbnN0IHN0cmluZ1ZhbHVlID0gU3RyaW5nKHZhbHVlKS50cmltKClcblxuICBpZiAoc3RyaW5nVmFsdWUgPT09IFwiXCIpIHtcbiAgICBpZiAoZW50cnkucmVxdWlyZWQpIHRocm93IHJlcXVpcmVkRXJyb3IoKVxuXG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIGlmIChlbnRyeS5tYXhMZW5ndGggIT09IHVuZGVmaW5lZCAmJiBzdHJpbmdWYWx1ZS5sZW5ndGggPiBlbnRyeS5tYXhMZW5ndGgpIHtcbiAgICB0aHJvdyBlcnJvckZhY3RvcnkoZW50cnkudG9vTG9uZ01lc3NhZ2UgPz8gYCR7bGFiZWx9IGlzIHRvbyBsb25nIChtYXhpbXVtIGlzICR7ZW50cnkubWF4TGVuZ3RofSBjaGFyYWN0ZXJzKS5gLCB7Y29kZTogYHN5bmMtJHtsYWJlbH0tdG9vLWxvbmdgfSlcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdWYWx1ZVxufVxuXG4vKipcbiAqIE5vcm1hbGl6ZXMgYSBkYXRlIGF0dHJpYnV0ZTogRGF0ZSBpbnN0YW5jZXMgcGFzcyB0aHJvdWdoLCBzdHJpbmdzL251bWJlcnMgYXJlIHBhcnNlZCBhbmQgaW52YWxpZCBvciBtaXNzaW5nLXJlcXVpcmVkIHZhbHVlcyBhcmUgcmVqZWN0ZWQuXG4gKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIE9wdGlvbnMuXG4gKiBAcGFyYW0ge1N5bmNBdHRyaWJ1dGVTY2hlbWFFbnRyeX0gYXJncy5lbnRyeSAtIFNjaGVtYSBlbnRyeS5cbiAqIEBwYXJhbSB7U3luY0F0dHJpYnV0ZUVycm9yRmFjdG9yeX0gYXJncy5lcnJvckZhY3RvcnkgLSBFcnJvciBmYWN0b3J5LlxuICogQHBhcmFtIHtzdHJpbmd9IGFyZ3MubGFiZWwgLSBNZXNzYWdlL2NvZGUgbGFiZWwuXG4gKiBAcGFyYW0gez99IGFyZ3MudmFsdWUgLSBSYXcgdmFsdWUuXG4gKiBAcmV0dXJucyB7RGF0ZSB8IG51bGx9IE5vcm1hbGl6ZWQgZGF0ZS5cbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplRGF0ZSh7ZW50cnksIGVycm9yRmFjdG9yeSwgbGFiZWwsIHZhbHVlfSkge1xuICBpZiAoIWVudHJ5LnJlcXVpcmVkICYmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSBcIlwiKSkgcmV0dXJuIG51bGxcblxuICBjb25zdCBkYXRlVmFsdWUgPSB2YWx1ZSBpbnN0YW5jZW9mIERhdGUgPyB2YWx1ZSA6IHR5cGVvZiB2YWx1ZSA9PSBcInN0cmluZ1wiIHx8IHR5cGVvZiB2YWx1ZSA9PSBcIm51bWJlclwiID8gbmV3IERhdGUodmFsdWUpIDogbnVsbFxuXG4gIGlmICghZGF0ZVZhbHVlIHx8IE51bWJlci5pc05hTihkYXRlVmFsdWUuZ2V0VGltZSgpKSkge1xuICAgIHRocm93IGVycm9yRmFjdG9yeShlbnRyeS5pbnZhbGlkTWVzc2FnZSA/PyBgJHtsYWJlbH0gbXVzdCBiZSBhIHZhbGlkIGRhdGV0aW1lLmAsIHtjb2RlOiBgc3luYy0ke2xhYmVsfS1pbnZhbGlkLWRhdGV0aW1lYH0pXG4gIH1cblxuICByZXR1cm4gZGF0ZVZhbHVlXG59XG5cbi8qKlxuICogTm9ybWFsaXplcyBhIGpzb24gYXR0cmlidXRlOiBlbXB0eSB2YWx1ZXMgYmVjb21lIG51bGwsIG9iamVjdHMgcGFzcyB0aHJvdWdoLCBzdHJpbmdzIG11c3QgcGFyc2UgYXMgSlNPTiBhbmQgb3RoZXIgdHlwZXMgYXJlIHJlamVjdGVkLlxuICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zLlxuICogQHBhcmFtIHtTeW5jQXR0cmlidXRlU2NoZW1hRW50cnl9IGFyZ3MuZW50cnkgLSBTY2hlbWEgZW50cnkuXG4gKiBAcGFyYW0ge1N5bmNBdHRyaWJ1dGVFcnJvckZhY3Rvcnl9IGFyZ3MuZXJyb3JGYWN0b3J5IC0gRXJyb3IgZmFjdG9yeS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLmxhYmVsIC0gTWVzc2FnZS9jb2RlIGxhYmVsLlxuICogQHBhcmFtIHs/fSBhcmdzLnZhbHVlIC0gUmF3IHZhbHVlLlxuICogQHJldHVybnMgez99IE5vcm1hbGl6ZWQganNvbiB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplSnNvbih7ZW50cnksIGVycm9yRmFjdG9yeSwgbGFiZWwsIHZhbHVlfSkge1xuICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gXCJcIikgcmV0dXJuIG51bGxcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PSBcIm9iamVjdFwiKSByZXR1cm4gdmFsdWVcblxuICBpZiAodHlwZW9mIHZhbHVlID09IFwic3RyaW5nXCIpIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIEpTT04ucGFyc2UodmFsdWUpXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRocm93IGVycm9yRmFjdG9yeShlbnRyeS5pbnZhbGlkSnNvbk1lc3NhZ2UgPz8gYCR7bGFiZWx9IG11c3QgYmUgdmFsaWQgSlNPTi5gLCB7XG4gICAgICAgIGNhdXNlOiAvKiogQHR5cGUge0Vycm9yfSAqLyAoZXJyb3IpLFxuICAgICAgICBjb2RlOiBgc3luYy0ke2xhYmVsfS1pbnZhbGlkLWpzb25gXG4gICAgICB9KVxuICAgIH1cbiAgfVxuXG4gIHRocm93IGVycm9yRmFjdG9yeShlbnRyeS5pbnZhbGlkTWVzc2FnZSA/PyBgJHtsYWJlbH0gbXVzdCBiZSBhbiBvYmplY3Qgb3IgSlNPTiBzdHJpbmcuYCwge2NvZGU6IGBzeW5jLSR7bGFiZWx9LWludmFsaWRgfSlcbn1cbiJdfQ==
|
|
@@ -14,6 +14,54 @@
|
|
|
14
14
|
* @augments {FrontendModelBaseResource<TModelClass>}
|
|
15
15
|
*/
|
|
16
16
|
export default class SyncResourceBase<TModelClass extends typeof import("../database/record/index.js").default = typeof import("../database/record/index.js").default> extends FrontendModelBaseResource<TModelClass> {
|
|
17
|
+
/**
|
|
18
|
+
* Declarative quick-search text columns. When declared, an index search on
|
|
19
|
+
* the pseudo-column `quickSearch` expands to an OR of LIKE conditions over
|
|
20
|
+
* these root-table columns instead of hitting the controller default.
|
|
21
|
+
* @type {string[] | null} */
|
|
22
|
+
static quickSearchColumns: string[] | null;
|
|
23
|
+
/**
|
|
24
|
+
* Declarative writable-attribute schema consumed by
|
|
25
|
+
* {@link SyncResourceBase#normalizeWritableAttributes}, keyed by camelCase
|
|
26
|
+
* attribute name.
|
|
27
|
+
* @type {Record<string, import("./sync-attribute-normalizer.js").SyncAttributeSchemaEntry> | null} */
|
|
28
|
+
static writableAttributes: Record<string, import("./sync-attribute-normalizer.js").SyncAttributeSchemaEntry> | null;
|
|
29
|
+
/**
|
|
30
|
+
* Expands a `quickSearch` pseudo-column search into an OR of LIKE conditions
|
|
31
|
+
* over the declared {@link SyncResourceBase.quickSearchColumns}.
|
|
32
|
+
* @param {object} args - Search args.
|
|
33
|
+
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceAnyQuery} args.query - Query to filter.
|
|
34
|
+
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceSearch} args.search - Search payload.
|
|
35
|
+
* @returns {boolean} Whether the search was handled as a quick search.
|
|
36
|
+
*/
|
|
37
|
+
applyQuickSearch({ query, search }: {
|
|
38
|
+
query: import("../frontend-model-resource/base-resource.js").FrontendModelResourceAnyQuery;
|
|
39
|
+
search: import("../frontend-model-resource/base-resource.js").FrontendModelResourceSearch;
|
|
40
|
+
}): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Normalizes incoming writable attributes through the declared
|
|
43
|
+
* {@link SyncResourceBase.writableAttributes} schema: camelCase and
|
|
44
|
+
* snake_case input keys are accepted, values are validated per type and the
|
|
45
|
+
* normalized values are written under snake_case column keys. Validation
|
|
46
|
+
* failures throw client-safe errors built by
|
|
47
|
+
* {@link SyncResourceBase#writableAttributeError}.
|
|
48
|
+
* @param {Record<string, ?>} attributes - Raw incoming attributes.
|
|
49
|
+
* @param {{unknownAttributes?: "error" | "ignore"}} [options] - Unknown input-key handling. Defaults to "error".
|
|
50
|
+
* @returns {Record<string, ?>} Normalized attributes keyed by column names.
|
|
51
|
+
*/
|
|
52
|
+
normalizeWritableAttributes(attributes: Record<string, unknown>, options?: {
|
|
53
|
+
unknownAttributes?: "error" | "ignore";
|
|
54
|
+
}): Record<string, unknown>;
|
|
55
|
+
/**
|
|
56
|
+
* Builds the client-safe error thrown for a failed writable-attribute validation.
|
|
57
|
+
* @param {string} message - Human-readable validation message.
|
|
58
|
+
* @param {{cause?: Error, code: string}} details - Stable machine-readable code and optional cause.
|
|
59
|
+
* @returns {Error} Client-safe error.
|
|
60
|
+
*/
|
|
61
|
+
writableAttributeError(message: string, { cause, code }: {
|
|
62
|
+
cause?: Error;
|
|
63
|
+
code: string;
|
|
64
|
+
}): Error;
|
|
17
65
|
/**
|
|
18
66
|
* Returns a stable change-feed page after app authorization.
|
|
19
67
|
* @returns {Promise<Record<string, ?>>} Change-feed page result.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-resource-base.d.ts","sourceRoot":"","sources":["../../../src/sync/sync-resource-base.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sync-resource-base.d.ts","sourceRoot":"","sources":["../../../src/sync/sync-resource-base.js"],"names":[],"mappings":"AAWA;;;;;GAKG;AAEH;;;;;;;;GAQG;AACH,sCAHqE,WAAW,SAAnE,cAAe,6BAA6B,EAAE,OAAQ;IAIjE;;;;iCAI6B;IAC7B,2BADU,MAAM,EAAE,GAAG,IAAI,CACO;IAEhC;;;;0GAIsG;IACtG,2BADU,MAAM,CAAC,MAAM,EAAE,OAAO,gCAAgC,EAAE,wBAAwB,CAAC,GAAG,IAAI,CAClE;IAgBhC;;;;;;;OAOG;IACH,oCAJG;QAAkG,KAAK,EAA/F,OAAO,6CAA6C,EAAE,6BAA6B;QACK,MAAM,EAA9F,OAAO,6CAA6C,EAAE,2BAA2B;KACzF,GAAU,OAAO,CA6BnB;IAED;;;;;;;;;;OAUG;IACH,wCAJW,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,YACjB;QAAC,iBAAiB,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAA;KAAC,GACtC,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAa7B;IAED;;;;;OAKG;IACH,gCAJW,MAAM,mBACN;QAAC,KAAK,CAAC,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,GAC3B,KAAK,CAIjB;IAED;;;OAGG;IACH,WAFa,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAAC,CAStC;IAED;;;OAGG;IACH,UAFa,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAAC,CAQtC;IAED;;;;OAIG;IACH,qBAHW,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,GACf,sBAAsB,GAAG,IAAI,CAoBzC;IAED;;;;OAIG;IACH,qCAHW;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAAC;QAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI,CAAA;KAAC,GAC/D;QAAC,OAAO,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAAC,CAAA;KAAC,CAQvD;IAED;;;OAGG;IACH,sBAFa,OAAO,mCAAmC,EAAE,OAAO,CAM/D;IAED;;;OAGG;IACH,qBAFa,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAI7B;IAED;;;OAGG;IACH,kBAFa,cAAc,6BAA6B,EAAE,OAAO,CAQhE;IAED;;;;OAIG;IACH,wBAHW;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAAC;QAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI,CAAA;KAAC,GAC/D,OAAO,CAAC,IAAI,CAAC,CAIzB;IAED;;;;OAIG;IACH,yBAHW;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAAC;QAAC,KAAK,EAAE,OAAO,wCAAwC,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI,CAAA;KAAC,GAChI,IAAI,CAIhB;IAED;;;OAGG;IACH,sBAFa,cAAc,mCAAmC,EAAE,OAAO,CAItE;CACF;;;;;;;;gBAvOa,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC;;;;kBACjB,MAAM;;sCAXkB,6CAA6C"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import { forcedNonBlankStringParam } from "typanic";
|
|
3
3
|
import FrontendModelBaseResource from "../frontend-model-resource/base-resource.js";
|
|
4
|
+
import normalizeAttributesWithSchema from "./sync-attribute-normalizer.js";
|
|
4
5
|
import SyncModelChangeFeedService from "./sync-model-change-feed-service.js";
|
|
6
|
+
import VelociousError from "../velocious-error.js";
|
|
7
|
+
const QUICK_SEARCH_COLUMN = "quickSearch";
|
|
5
8
|
/**
|
|
6
9
|
* Optional client-declared sync scope carried on a changes request.
|
|
7
10
|
* @typedef {object} SerializedChangesScope
|
|
@@ -18,6 +21,91 @@ import SyncModelChangeFeedService from "./sync-model-change-feed-service.js";
|
|
|
18
21
|
* @augments {FrontendModelBaseResource<TModelClass>}
|
|
19
22
|
*/
|
|
20
23
|
export default class SyncResourceBase extends FrontendModelBaseResource {
|
|
24
|
+
/**
|
|
25
|
+
* Declarative quick-search text columns. When declared, an index search on
|
|
26
|
+
* the pseudo-column `quickSearch` expands to an OR of LIKE conditions over
|
|
27
|
+
* these root-table columns instead of hitting the controller default.
|
|
28
|
+
* @type {string[] | null} */
|
|
29
|
+
static quickSearchColumns = null;
|
|
30
|
+
/**
|
|
31
|
+
* Declarative writable-attribute schema consumed by
|
|
32
|
+
* {@link SyncResourceBase#normalizeWritableAttributes}, keyed by camelCase
|
|
33
|
+
* attribute name.
|
|
34
|
+
* @type {Record<string, import("./sync-attribute-normalizer.js").SyncAttributeSchemaEntry> | null} */
|
|
35
|
+
static writableAttributes = null;
|
|
36
|
+
/**
|
|
37
|
+
* Applies frontend-model index searches, expanding declared quick searches.
|
|
38
|
+
* @param {object} args - Search args.
|
|
39
|
+
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceController} args.controller - Controller handling the query.
|
|
40
|
+
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceAnyQuery} args.query - Query instance.
|
|
41
|
+
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceSearch} args.search - Search params.
|
|
42
|
+
* @returns {void}
|
|
43
|
+
*/
|
|
44
|
+
applyFrontendModelIndexSearch({ controller, query, search }) {
|
|
45
|
+
if (this.applyQuickSearch({ query, search }))
|
|
46
|
+
return;
|
|
47
|
+
super.applyFrontendModelIndexSearch({ controller, query, search });
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Expands a `quickSearch` pseudo-column search into an OR of LIKE conditions
|
|
51
|
+
* over the declared {@link SyncResourceBase.quickSearchColumns}.
|
|
52
|
+
* @param {object} args - Search args.
|
|
53
|
+
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceAnyQuery} args.query - Query to filter.
|
|
54
|
+
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceSearch} args.search - Search payload.
|
|
55
|
+
* @returns {boolean} Whether the search was handled as a quick search.
|
|
56
|
+
*/
|
|
57
|
+
applyQuickSearch({ query, search }) {
|
|
58
|
+
const quickSearchColumns = /** @type {typeof SyncResourceBase} */ (this.constructor).quickSearchColumns;
|
|
59
|
+
if (!quickSearchColumns || quickSearchColumns.length === 0)
|
|
60
|
+
return false;
|
|
61
|
+
if (search.path.length > 0 || search.column !== QUICK_SEARCH_COLUMN)
|
|
62
|
+
return false;
|
|
63
|
+
if (search.operator !== "like") {
|
|
64
|
+
throw VelociousError.safe("Sync quick search must use the like operator.", { code: "sync-invalid-quick-search" });
|
|
65
|
+
}
|
|
66
|
+
if (typeof search.value !== "string") {
|
|
67
|
+
throw VelociousError.safe("Sync quick search must be a string.", { code: "sync-invalid-quick-search" });
|
|
68
|
+
}
|
|
69
|
+
const trimmedValue = search.value.trim();
|
|
70
|
+
if (!trimmedValue)
|
|
71
|
+
return true;
|
|
72
|
+
const tableSql = query.driver.quoteTable(query.getTableReferenceForJoin());
|
|
73
|
+
const likeValue = `%${trimmedValue}%`;
|
|
74
|
+
const conditions = quickSearchColumns.map((columnName) => (`${tableSql}.${query.driver.quoteColumn(columnName)} LIKE ${query.driver.quote(likeValue)}`));
|
|
75
|
+
query.where(`(${conditions.join(" OR ")})`);
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Normalizes incoming writable attributes through the declared
|
|
80
|
+
* {@link SyncResourceBase.writableAttributes} schema: camelCase and
|
|
81
|
+
* snake_case input keys are accepted, values are validated per type and the
|
|
82
|
+
* normalized values are written under snake_case column keys. Validation
|
|
83
|
+
* failures throw client-safe errors built by
|
|
84
|
+
* {@link SyncResourceBase#writableAttributeError}.
|
|
85
|
+
* @param {Record<string, ?>} attributes - Raw incoming attributes.
|
|
86
|
+
* @param {{unknownAttributes?: "error" | "ignore"}} [options] - Unknown input-key handling. Defaults to "error".
|
|
87
|
+
* @returns {Record<string, ?>} Normalized attributes keyed by column names.
|
|
88
|
+
*/
|
|
89
|
+
normalizeWritableAttributes(attributes, options = {}) {
|
|
90
|
+
const schema = /** @type {typeof SyncResourceBase} */ (this.constructor).writableAttributes;
|
|
91
|
+
if (!schema)
|
|
92
|
+
throw new Error(`${this.constructor.name} must define static writableAttributes to use normalizeWritableAttributes`);
|
|
93
|
+
return normalizeAttributesWithSchema({
|
|
94
|
+
attributes,
|
|
95
|
+
errorFactory: (message, details) => this.writableAttributeError(message, details),
|
|
96
|
+
schema,
|
|
97
|
+
unknownAttributes: options.unknownAttributes
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Builds the client-safe error thrown for a failed writable-attribute validation.
|
|
102
|
+
* @param {string} message - Human-readable validation message.
|
|
103
|
+
* @param {{cause?: Error, code: string}} details - Stable machine-readable code and optional cause.
|
|
104
|
+
* @returns {Error} Client-safe error.
|
|
105
|
+
*/
|
|
106
|
+
writableAttributeError(message, { cause, code }) {
|
|
107
|
+
return VelociousError.safe(message, cause ? { cause, code } : { code });
|
|
108
|
+
}
|
|
21
109
|
/**
|
|
22
110
|
* Returns a stable change-feed page after app authorization.
|
|
23
111
|
* @returns {Promise<Record<string, ?>>} Change-feed page result.
|
|
@@ -119,4 +207,4 @@ export default class SyncResourceBase extends FrontendModelBaseResource {
|
|
|
119
207
|
throw new Error("SyncResourceBase#replayServiceClass must be implemented");
|
|
120
208
|
}
|
|
121
209
|
}
|
|
122
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1yZXNvdXJjZS1iYXNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3N5bmMvc3luYy1yZXNvdXJjZS1iYXNlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLEVBQUMseUJBQXlCLEVBQUMsTUFBTSxTQUFTLENBQUE7QUFFakQsT0FBTyx5QkFBeUIsTUFBTSw2Q0FBNkMsQ0FBQTtBQUNuRixPQUFPLDBCQUEwQixNQUFNLHFDQUFxQyxDQUFBO0FBRTVFOzs7OztHQUtHO0FBRUg7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLENBQUMsT0FBTyxPQUFPLGdCQUFpQixTQUFRLHlCQUF5QjtJQUNyRTs7O09BR0c7SUFDSCxLQUFLLENBQUMsT0FBTztRQUNYLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQTtRQUM1QixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBRXZDLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixDQUFDLEVBQUMsTUFBTSxFQUFFLEtBQUssRUFBQyxDQUFDLENBQUE7UUFFNUMsT0FBTyxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxFQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFBO0lBQ2hFLENBQUM7SUFFRDs7O09BR0c7SUFDSCxLQUFLLENBQUMsTUFBTTtRQUNWLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFBO1FBRXBFLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxPQUFPO1lBQUUsT0FBTyxNQUFNLENBQUE7UUFFNUMsT0FBTyxFQUFDLE1BQU0sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxLQUFLLEVBQUMsQ0FBQTtJQUNqRCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILFlBQVksQ0FBQyxNQUFNO1FBQ2pCLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUE7UUFFMUIsSUFBSSxLQUFLLEtBQUssU0FBUyxJQUFJLEtBQUssS0FBSyxJQUFJO1lBQUUsT0FBTyxJQUFJLENBQUE7UUFFdEQsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3RELE1BQU0sSUFBSSxLQUFLLENBQUMsOENBQThDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUE7UUFDaEYsQ0FBQztRQUVELE1BQU0sV0FBVyxHQUFHLGdDQUFnQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDNUQsTUFBTSxZQUFZLEdBQUcseUJBQXlCLENBQUMsV0FBVyxFQUFFLGNBQWMsQ0FBQyxDQUFBO1FBQzNFLE1BQU0sVUFBVSxHQUFHLFdBQVcsQ0FBQyxVQUFVLENBQUE7UUFFekMsSUFBSSxDQUFDLFVBQVUsSUFBSSxPQUFPLFVBQVUsS0FBSyxRQUFRLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1lBQy9FLE1BQU0sSUFBSSxLQUFLLENBQUMseURBQXlELE1BQU0sQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUE7UUFDaEcsQ0FBQztRQUVELE9BQU8sRUFBQyxVQUFVLEVBQUUsZ0NBQWdDLENBQUMsQ0FBQyxVQUFVLENBQUMsRUFBRSxZQUFZLEVBQUMsQ0FBQTtJQUNsRixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILGlCQUFpQixDQUFDLEVBQUMsTUFBTSxFQUFFLEtBQUssRUFBQztRQUMvQixPQUFPLElBQUksMEJBQTBCLENBQUM7WUFDcEMsVUFBVSxFQUFFLElBQUksQ0FBQyxjQUFjLEVBQUU7WUFDakMsTUFBTTtZQUNOLFVBQVUsRUFBRSxDQUFDLEVBQUMsS0FBSyxFQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxFQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFDLENBQUM7U0FDeEUsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUVEOzs7T0FHRztJQUNILGtCQUFrQjtRQUNoQixNQUFNLGtCQUFrQixHQUFHLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFBO1FBRXBELE9BQU8sSUFBSSxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxDQUFBO0lBQ3pELENBQUM7SUFFRDs7O09BR0c7SUFDSCxpQkFBaUI7UUFDZixPQUFPLEVBQUUsQ0FBQTtJQUNYLENBQUM7SUFFRDs7O09BR0c7SUFDSCxjQUFjO1FBQ1osTUFBTSxVQUFVLEdBQUcsc0NBQXNDLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsVUFBVSxDQUFBO1FBRXZGLElBQUksQ0FBQyxVQUFVO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxnQ0FBZ0MsQ0FBQyxDQUFBO1FBRTFGLE9BQU8sVUFBVSxDQUFBO0lBQ25CLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsS0FBSyxDQUFDLGdCQUFnQixDQUFDLEtBQUs7UUFDMUIsTUFBTSxJQUFJLEtBQUssQ0FBQyx1REFBdUQsQ0FBQyxDQUFBO0lBQzFFLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsaUJBQWlCLENBQUMsS0FBSztRQUNyQixNQUFNLElBQUksS0FBSyxDQUFDLHdEQUF3RCxDQUFDLENBQUE7SUFDM0UsQ0FBQztJQUVEOzs7T0FHRztJQUNILGtCQUFrQjtRQUNoQixNQUFNLElBQUksS0FBSyxDQUFDLHlEQUF5RCxDQUFDLENBQUE7SUFDNUUsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCB7Zm9yY2VkTm9uQmxhbmtTdHJpbmdQYXJhbX0gZnJvbSBcInR5cGFuaWNcIlxuXG5pbXBvcnQgRnJvbnRlbmRNb2RlbEJhc2VSZXNvdXJjZSBmcm9tIFwiLi4vZnJvbnRlbmQtbW9kZWwtcmVzb3VyY2UvYmFzZS1yZXNvdXJjZS5qc1wiXG5pbXBvcnQgU3luY01vZGVsQ2hhbmdlRmVlZFNlcnZpY2UgZnJvbSBcIi4vc3luYy1tb2RlbC1jaGFuZ2UtZmVlZC1zZXJ2aWNlLmpzXCJcblxuLyoqXG4gKiBPcHRpb25hbCBjbGllbnQtZGVjbGFyZWQgc3luYyBzY29wZSBjYXJyaWVkIG9uIGEgY2hhbmdlcyByZXF1ZXN0LlxuICogQHR5cGVkZWYge29iamVjdH0gU2VyaWFsaXplZENoYW5nZXNTY29wZVxuICogQHByb3BlcnR5IHtSZWNvcmQ8c3RyaW5nLCA/Pn0gY29uZGl0aW9ucyAtIFBsYWluIGF0dHJpYnV0ZSBjb25kaXRpb25zIGZyb20gdGhlIGNsaWVudCBxdWVyeS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSByZXNvdXJjZVR5cGUgLSBDbGllbnQgcmVzb3VyY2UvbW9kZWwgbmFtZSB0aGUgc2NvcGUgd2FzIGRlY2xhcmVkIGZvci5cbiAqL1xuXG4vKipcbiAqIEJhc2UgcmVzb3VyY2UgZm9yIFZlbG9jaW91cyBzeW5jIGVuZHBvaW50cy5cbiAqXG4gKiBWZWxvY2lvdXMgb3ducyB0aGUgY2hhbmdlcy9yZXBsYXkgb3JjaGVzdHJhdGlvbiAoc2NvcGUgcGFyc2luZywgZmVlZCBwYWdpbmcsXG4gKiByZXBsYXkgZGVsZWdhdGlvbiwgcmVzcG9uc2Ugc2hhcGUpIHdoaWxlIGFwcHMgc3ViY2xhc3MgYW5kIG9ubHkgZGVjbGFyZVxuICogYXV0aG9yaXphdGlvbiwgZmVlZCBzY29waW5nLCBhbmQgdGhlaXIgcmVwbGF5IHNlcnZpY2UuXG4gKiBAdGVtcGxhdGUge3R5cGVvZiBpbXBvcnQoXCIuLi9kYXRhYmFzZS9yZWNvcmQvaW5kZXguanNcIikuZGVmYXVsdH0gW1RNb2RlbENsYXNzPXR5cGVvZiBpbXBvcnQoXCIuLi9kYXRhYmFzZS9yZWNvcmQvaW5kZXguanNcIikuZGVmYXVsdF1cbiAqIEBhdWdtZW50cyB7RnJvbnRlbmRNb2RlbEJhc2VSZXNvdXJjZTxUTW9kZWxDbGFzcz59XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFN5bmNSZXNvdXJjZUJhc2UgZXh0ZW5kcyBGcm9udGVuZE1vZGVsQmFzZVJlc291cmNlIHtcbiAgLyoqXG4gICAqIFJldHVybnMgYSBzdGFibGUgY2hhbmdlLWZlZWQgcGFnZSBhZnRlciBhcHAgYXV0aG9yaXphdGlvbi5cbiAgICogQHJldHVybnMge1Byb21pc2U8UmVjb3JkPHN0cmluZywgPz4+fSBDaGFuZ2UtZmVlZCBwYWdlIHJlc3VsdC5cbiAgICovXG4gIGFzeW5jIGNoYW5nZXMoKSB7XG4gICAgY29uc3QgcGFyYW1zID0gdGhpcy5wYXJhbXMoKVxuICAgIGNvbnN0IHNjb3BlID0gdGhpcy5jaGFuZ2VzU2NvcGUocGFyYW1zKVxuXG4gICAgYXdhaXQgdGhpcy5hdXRob3JpemVDaGFuZ2VzKHtwYXJhbXMsIHNjb3BlfSlcblxuICAgIHJldHVybiBhd2FpdCB0aGlzLmNoYW5nZUZlZWRTZXJ2aWNlKHtwYXJhbXMsIHNjb3BlfSkuY2hhbmdlcygpXG4gIH1cblxuICAvKipcbiAgICogUmVwbGF5cyBjbGllbnQgc3luYyBlbnZlbG9wZXMgdGhyb3VnaCB0aGUgYXBwIHJlcGxheSBzZXJ2aWNlLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCA/Pj59IFJlcGxheSByZXN1bHQgd2l0aCBwZXItc3luYyBzdGF0ZXMuXG4gICAqL1xuICBhc3luYyByZXBsYXkoKSB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5idWlsZFJlcGxheVNlcnZpY2UoKS5yZXBsYXkodGhpcy5wYXJhbXMoKSlcblxuICAgIGlmIChyZXN1bHQuc3RhdHVzID09PSBcImVycm9yXCIpIHJldHVybiByZXN1bHRcblxuICAgIHJldHVybiB7c3RhdHVzOiBcInN1Y2Nlc3NcIiwgc3luY3M6IHJlc3VsdC5zeW5jc31cbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJzZXMgdGhlIG9wdGlvbmFsIGNsaWVudC1kZWNsYXJlZCBzY29wZSBmcm9tIHJlcXVlc3QgcGFyYW1zLlxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsID8+fSBwYXJhbXMgLSBSZXF1ZXN0IHBhcmFtcy5cbiAgICogQHJldHVybnMge1NlcmlhbGl6ZWRDaGFuZ2VzU2NvcGUgfCBudWxsfSBQYXJzZWQgc2NvcGUsIG9yIG51bGwgd2hlbiB0aGUgY2xpZW50IHNlbnQgbm9uZS5cbiAgICovXG4gIGNoYW5nZXNTY29wZShwYXJhbXMpIHtcbiAgICBjb25zdCBzY29wZSA9IHBhcmFtcy5zY29wZVxuXG4gICAgaWYgKHNjb3BlID09PSB1bmRlZmluZWQgfHwgc2NvcGUgPT09IG51bGwpIHJldHVybiBudWxsXG5cbiAgICBpZiAodHlwZW9mIHNjb3BlICE9PSBcIm9iamVjdFwiIHx8IEFycmF5LmlzQXJyYXkoc2NvcGUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFN5bmMgY2hhbmdlcyBzY29wZSBtdXN0IGJlIGFuIG9iamVjdCwgZ290OiAke1N0cmluZyhzY29wZSl9YClcbiAgICB9XG5cbiAgICBjb25zdCBzY29wZVBhcmFtcyA9IC8qKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgPz59ICovIChzY29wZSlcbiAgICBjb25zdCByZXNvdXJjZVR5cGUgPSBmb3JjZWROb25CbGFua1N0cmluZ1BhcmFtKHNjb3BlUGFyYW1zLCBcInJlc291cmNlVHlwZVwiKVxuICAgIGNvbnN0IGNvbmRpdGlvbnMgPSBzY29wZVBhcmFtcy5jb25kaXRpb25zXG5cbiAgICBpZiAoIWNvbmRpdGlvbnMgfHwgdHlwZW9mIGNvbmRpdGlvbnMgIT09IFwib2JqZWN0XCIgfHwgQXJyYXkuaXNBcnJheShjb25kaXRpb25zKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBTeW5jIGNoYW5nZXMgc2NvcGUuY29uZGl0aW9ucyBtdXN0IGJlIGFuIG9iamVjdCwgZ290OiAke1N0cmluZyhjb25kaXRpb25zKX1gKVxuICAgIH1cblxuICAgIHJldHVybiB7Y29uZGl0aW9uczogLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gKi8gKGNvbmRpdGlvbnMpLCByZXNvdXJjZVR5cGV9XG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIHRoZSBjaGFuZ2UtZmVlZCBzZXJ2aWNlIHNlcnZpbmcgdGhpcyBjaGFuZ2VzIHJlcXVlc3QuXG4gICAqIEBwYXJhbSB7e3BhcmFtczogUmVjb3JkPHN0cmluZywgPz4sIHNjb3BlOiBTZXJpYWxpemVkQ2hhbmdlc1Njb3BlIHwgbnVsbH19IGFyZ3MgLSBSZXF1ZXN0IHBhcmFtcyBhbmQgcGFyc2VkIHNjb3BlLlxuICAgKiBAcmV0dXJucyB7e2NoYW5nZXM6ICgpID0+IFByb21pc2U8UmVjb3JkPHN0cmluZywgPz4+fX0gQ2hhbmdlLWZlZWQgc2VydmljZS5cbiAgICovXG4gIGNoYW5nZUZlZWRTZXJ2aWNlKHtwYXJhbXMsIHNjb3BlfSkge1xuICAgIHJldHVybiBuZXcgU3luY01vZGVsQ2hhbmdlRmVlZFNlcnZpY2Uoe1xuICAgICAgbW9kZWxDbGFzczogdGhpcy5zeW5jTW9kZWxDbGFzcygpLFxuICAgICAgcGFyYW1zLFxuICAgICAgc2NvcGVRdWVyeTogKHtxdWVyeX0pID0+IHRoaXMuc2NvcGVDaGFuZ2VzUXVlcnkoe3BhcmFtcywgcXVlcnksIHNjb3BlfSlcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyB0aGUgYXBwIHJlcGxheSBzZXJ2aWNlIGhhbmRsaW5nIHRoaXMgcmVwbGF5IHJlcXVlc3QuXG4gICAqIEByZXR1cm5zIHtpbXBvcnQoXCIuL3N5bmMtZW52ZWxvcGUtcmVwbGF5LXNlcnZpY2UuanNcIikuZGVmYXVsdH0gUmVwbGF5IHNlcnZpY2UgaW5zdGFuY2UuXG4gICAqL1xuICBidWlsZFJlcGxheVNlcnZpY2UoKSB7XG4gICAgY29uc3QgUmVwbGF5U2VydmljZUNsYXNzID0gdGhpcy5yZXBsYXlTZXJ2aWNlQ2xhc3MoKVxuXG4gICAgcmV0dXJuIG5ldyBSZXBsYXlTZXJ2aWNlQ2xhc3ModGhpcy5yZXBsYXlTZXJ2aWNlQXJncygpKVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgY29uc3RydWN0b3IgYXJncyBmb3IgdGhlIGFwcCByZXBsYXkgc2VydmljZS5cbiAgICogQHJldHVybnMge1JlY29yZDxzdHJpbmcsID8+fSBSZXBsYXkgc2VydmljZSBjb25zdHJ1Y3RvciBhcmdzLlxuICAgKi9cbiAgcmVwbGF5U2VydmljZUFyZ3MoKSB7XG4gICAgcmV0dXJuIHt9XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgc3luYyBtb2RlbCBjbGFzcyBiYWNraW5nIHRoZSBjaGFuZ2UgZmVlZC5cbiAgICogQHJldHVybnMge3R5cGVvZiBpbXBvcnQoXCIuLi9kYXRhYmFzZS9yZWNvcmQvaW5kZXguanNcIikuZGVmYXVsdH0gU3luYyBtb2RlbCBjbGFzcy5cbiAgICovXG4gIHN5bmNNb2RlbENsYXNzKCkge1xuICAgIGNvbnN0IG1vZGVsQ2xhc3MgPSAvKiogQHR5cGUge3R5cGVvZiBTeW5jUmVzb3VyY2VCYXNlfSAqLyAodGhpcy5jb25zdHJ1Y3RvcikuTW9kZWxDbGFzc1xuXG4gICAgaWYgKCFtb2RlbENsYXNzKSB0aHJvdyBuZXcgRXJyb3IoYCR7dGhpcy5jb25zdHJ1Y3Rvci5uYW1lfSBtdXN0IGRlZmluZSBzdGF0aWMgTW9kZWxDbGFzc2ApXG5cbiAgICByZXR1cm4gbW9kZWxDbGFzc1xuICB9XG5cbiAgLyoqXG4gICAqIEF1dGhvcml6ZXMgdGhlIGN1cnJlbnQgY29udGV4dCBmb3IgcmVhZGluZyB0aGUgcmVxdWVzdGVkIGNoYW5nZXMuXG4gICAqIEBwYXJhbSB7e3BhcmFtczogUmVjb3JkPHN0cmluZywgPz4sIHNjb3BlOiBTZXJpYWxpemVkQ2hhbmdlc1Njb3BlIHwgbnVsbH19IF9hcmdzIC0gUmVxdWVzdCBwYXJhbXMgYW5kIHBhcnNlZCBzY29wZS5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IFJlc29sdmVzIHdoZW4gYWNjZXNzIGlzIGFsbG93ZWQ7IHRocm93cyBvdGhlcndpc2UuXG4gICAqL1xuICBhc3luYyBhdXRob3JpemVDaGFuZ2VzKF9hcmdzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiU3luY1Jlc291cmNlQmFzZSNhdXRob3JpemVDaGFuZ2VzIG11c3QgYmUgaW1wbGVtZW50ZWRcIilcbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBsaWVzIGFwcCB2aXNpYmlsaXR5IHNjb3Bpbmcgb250byB0aGUgY2hhbmdlLWZlZWQgcXVlcnkuXG4gICAqIEBwYXJhbSB7e3BhcmFtczogUmVjb3JkPHN0cmluZywgPz4sIHF1ZXJ5OiBpbXBvcnQoXCIuLi9kYXRhYmFzZS9xdWVyeS9tb2RlbC1jbGFzcy1xdWVyeS5qc1wiKS5kZWZhdWx0LCBzY29wZTogU2VyaWFsaXplZENoYW5nZXNTY29wZSB8IG51bGx9fSBfYXJncyAtIFJlcXVlc3QgcGFyYW1zLCBmZWVkIHF1ZXJ5LCBhbmQgcGFyc2VkIHNjb3BlLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIHNjb3BlQ2hhbmdlc1F1ZXJ5KF9hcmdzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiU3luY1Jlc291cmNlQmFzZSNzY29wZUNoYW5nZXNRdWVyeSBtdXN0IGJlIGltcGxlbWVudGVkXCIpXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgYXBwIHJlcGxheSBzZXJ2aWNlIGNsYXNzIGhhbmRsaW5nIHJlcGxheSBtdXRhdGlvbnMuXG4gICAqIEByZXR1cm5zIHt0eXBlb2YgaW1wb3J0KFwiLi9zeW5jLWVudmVsb3BlLXJlcGxheS1zZXJ2aWNlLmpzXCIpLmRlZmF1bHR9IFJlcGxheSBzZXJ2aWNlIGNsYXNzLlxuICAgKi9cbiAgcmVwbGF5U2VydmljZUNsYXNzKCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIlN5bmNSZXNvdXJjZUJhc2UjcmVwbGF5U2VydmljZUNsYXNzIG11c3QgYmUgaW1wbGVtZW50ZWRcIilcbiAgfVxufVxuIl19
|
|
210
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1yZXNvdXJjZS1iYXNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3N5bmMvc3luYy1yZXNvdXJjZS1iYXNlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLEVBQUMseUJBQXlCLEVBQUMsTUFBTSxTQUFTLENBQUE7QUFFakQsT0FBTyx5QkFBeUIsTUFBTSw2Q0FBNkMsQ0FBQTtBQUNuRixPQUFPLDZCQUE2QixNQUFNLGdDQUFnQyxDQUFBO0FBQzFFLE9BQU8sMEJBQTBCLE1BQU0scUNBQXFDLENBQUE7QUFDNUUsT0FBTyxjQUFjLE1BQU0sdUJBQXVCLENBQUE7QUFFbEQsTUFBTSxtQkFBbUIsR0FBRyxhQUFhLENBQUE7QUFFekM7Ozs7O0dBS0c7QUFFSDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQU8sZ0JBQWlCLFNBQVEseUJBQXlCO0lBQ3JFOzs7O2lDQUk2QjtJQUM3QixNQUFNLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxDQUFBO0lBRWhDOzs7OzBHQUlzRztJQUN0RyxNQUFNLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxDQUFBO0lBRWhDOzs7Ozs7O09BT0c7SUFDSCw2QkFBNkIsQ0FBQyxFQUFDLFVBQVUsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFDO1FBQ3ZELElBQUksSUFBSSxDQUFDLGdCQUFnQixDQUFDLEVBQUMsS0FBSyxFQUFFLE1BQU0sRUFBQyxDQUFDO1lBQUUsT0FBTTtRQUVsRCxLQUFLLENBQUMsNkJBQTZCLENBQUMsRUFBQyxVQUFVLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBQyxDQUFDLENBQUE7SUFDbEUsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxnQkFBZ0IsQ0FBQyxFQUFDLEtBQUssRUFBRSxNQUFNLEVBQUM7UUFDOUIsTUFBTSxrQkFBa0IsR0FBRyxzQ0FBc0MsQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxrQkFBa0Is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QzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdURBQXVELENBQUMsQ0FBQTtJQUMxRSxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILGlCQUFpQixDQUFDLEtBQUs7UUFDckIsTUFBTSxJQUFJLEtBQUssQ0FBQyx3REFBd0QsQ0FBQyxDQUFBO0lBQzNFLENBQUM7SUFFRDs7O09BR0c7SUFDSCxrQkFBa0I7UUFDaEIsTUFBTSxJQUFJLEtBQUssQ0FBQyx5REFBeUQsQ0FBQyxDQUFBO0lBQzVFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IHtmb3JjZWROb25CbGFua1N0cmluZ1BhcmFtfSBmcm9tIFwidHlwYW5pY1wiXG5cbmltcG9ydCBGcm9udGVuZE1vZGVsQmFzZVJlc291cmNlIGZyb20gXCIuLi9mcm9udGVuZC1tb2RlbC1yZXNvdXJjZS9iYXNlLXJlc291cmNlLmpzXCJcbmltcG9ydCBub3JtYWxpemVBdHRyaWJ1dGVzV2l0aFNjaGVtYSBmcm9tIFwiLi9zeW5jLWF0dHJpYnV0ZS1ub3JtYWxpemVyLmpzXCJcbmltcG9ydCBTeW5jTW9kZWxDaGFuZ2VGZWVkU2VydmljZSBmcm9tIFwiLi9zeW5jLW1vZGVsLWNoYW5nZS1mZWVkLXNlcnZpY2UuanNcIlxuaW1wb3J0IFZlbG9jaW91c0Vycm9yIGZyb20gXCIuLi92ZWxvY2lvdXMtZXJyb3IuanNcIlxuXG5jb25zdCBRVUlDS19TRUFSQ0hfQ09MVU1OID0gXCJxdWlja1NlYXJjaFwiXG5cbi8qKlxuICogT3B0aW9uYWwgY2xpZW50LWRlY2xhcmVkIHN5bmMgc2NvcGUgY2FycmllZCBvbiBhIGNoYW5nZXMgcmVxdWVzdC5cbiAqIEB0eXBlZGVmIHtvYmplY3R9IFNlcmlhbGl6ZWRDaGFuZ2VzU2NvcGVcbiAqIEBwcm9wZXJ0eSB7UmVjb3JkPHN0cmluZywgPz59IGNvbmRpdGlvbnMgLSBQbGFpbiBhdHRyaWJ1dGUgY29uZGl0aW9ucyBmcm9tIHRoZSBjbGllbnQgcXVlcnkuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gcmVzb3VyY2VUeXBlIC0gQ2xpZW50IHJlc291cmNlL21vZGVsIG5hbWUgdGhlIHNjb3BlIHdhcyBkZWNsYXJlZCBmb3IuXG4gKi9cblxuLyoqXG4gKiBCYXNlIHJlc291cmNlIGZvciBWZWxvY2lvdXMgc3luYyBlbmRwb2ludHMuXG4gKlxuICogVmVsb2Npb3VzIG93bnMgdGhlIGNoYW5nZXMvcmVwbGF5IG9yY2hlc3RyYXRpb24gKHNjb3BlIHBhcnNpbmcsIGZlZWQgcGFnaW5nLFxuICogcmVwbGF5IGRlbGVnYXRpb24sIHJlc3BvbnNlIHNoYXBlKSB3aGlsZSBhcHBzIHN1YmNsYXNzIGFuZCBvbmx5IGRlY2xhcmVcbiAqIGF1dGhvcml6YXRpb24sIGZlZWQgc2NvcGluZywgYW5kIHRoZWlyIHJlcGxheSBzZXJ2aWNlLlxuICogQHRlbXBsYXRlIHt0eXBlb2YgaW1wb3J0KFwiLi4vZGF0YWJhc2UvcmVjb3JkL2luZGV4LmpzXCIpLmRlZmF1bHR9IFtUTW9kZWxDbGFzcz10eXBlb2YgaW1wb3J0KFwiLi4vZGF0YWJhc2UvcmVjb3JkL2luZGV4LmpzXCIpLmRlZmF1bHRdXG4gKiBAYXVnbWVudHMge0Zyb250ZW5kTW9kZWxCYXNlUmVzb3VyY2U8VE1vZGVsQ2xhc3M+fVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTeW5jUmVzb3VyY2VCYXNlIGV4dGVuZHMgRnJvbnRlbmRNb2RlbEJhc2VSZXNvdXJjZSB7XG4gIC8qKlxuICAgKiBEZWNsYXJhdGl2ZSBxdWljay1zZWFyY2ggdGV4dCBjb2x1bW5zLiBXaGVuIGRlY2xhcmVkLCBhbiBpbmRleCBzZWFyY2ggb25cbiAgICogdGhlIHBzZXVkby1jb2x1bW4gYHF1aWNrU2VhcmNoYCBleHBhbmRzIHRvIGFuIE9SIG9mIExJS0UgY29uZGl0aW9ucyBvdmVyXG4gICAqIHRoZXNlIHJvb3QtdGFibGUgY29sdW1ucyBpbnN0ZWFkIG9mIGhpdHRpbmcgdGhlIGNvbnRyb2xsZXIgZGVmYXVsdC5cbiAgICogQHR5cGUge3N0cmluZ1tdIHwgbnVsbH0gKi9cbiAgc3RhdGljIHF1aWNrU2VhcmNoQ29sdW1ucyA9IG51bGxcblxuICAvKipcbiAgICogRGVjbGFyYXRpdmUgd3JpdGFibGUtYXR0cmlidXRlIHNjaGVtYSBjb25zdW1lZCBieVxuICAgKiB7QGxpbmsgU3luY1Jlc291cmNlQmFzZSNub3JtYWxpemVXcml0YWJsZUF0dHJpYnV0ZXN9LCBrZXllZCBieSBjYW1lbENhc2VcbiAgICogYXR0cmlidXRlIG5hbWUuXG4gICAqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBpbXBvcnQoXCIuL3N5bmMtYXR0cmlidXRlLW5vcm1hbGl6ZXIuanNcIikuU3luY0F0dHJpYnV0ZVNjaGVtYUVudHJ5PiB8IG51bGx9ICovXG4gIHN0YXRpYyB3cml0YWJsZUF0dHJpYnV0ZXMgPSBudWxsXG5cbiAgLyoqXG4gICAqIEFwcGxpZXMgZnJvbnRlbmQtbW9kZWwgaW5kZXggc2VhcmNoZXMsIGV4cGFuZGluZyBkZWNsYXJlZCBxdWljayBzZWFyY2hlcy5cbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBTZWFyY2ggYXJncy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9mcm9udGVuZC1tb2RlbC1yZXNvdXJjZS9iYXNlLXJlc291cmNlLmpzXCIpLkZyb250ZW5kTW9kZWxSZXNvdXJjZUNvbnRyb2xsZXJ9IGFyZ3MuY29udHJvbGxlciAtIENvbnRyb2xsZXIgaGFuZGxpbmcgdGhlIHF1ZXJ5LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2Zyb250ZW5kLW1vZGVsLXJlc291cmNlL2Jhc2UtcmVzb3VyY2UuanNcIikuRnJvbnRlbmRNb2RlbFJlc291cmNlQW55UXVlcnl9IGFyZ3MucXVlcnkgLSBRdWVyeSBpbnN0YW5jZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9mcm9udGVuZC1tb2RlbC1yZXNvdXJjZS9iYXNlLXJlc291cmNlLmpzXCIpLkZyb250ZW5kTW9kZWxSZXNvdXJjZVNlYXJjaH0gYXJncy5zZWFyY2ggLSBTZWFyY2ggcGFyYW1zLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIGFwcGx5RnJvbnRlbmRNb2RlbEluZGV4U2VhcmNoKHtjb250cm9sbGVyLCBxdWVyeSwgc2VhcmNofSkge1xuICAgIGlmICh0aGlzLmFwcGx5UXVpY2tTZWFyY2goe3F1ZXJ5LCBzZWFyY2h9KSkgcmV0dXJuXG5cbiAgICBzdXBlci5hcHBseUZyb250ZW5kTW9kZWxJbmRleFNlYXJjaCh7Y29udHJvbGxlciwgcXVlcnksIHNlYXJjaH0pXG4gIH1cblxuICAvKipcbiAgICogRXhwYW5kcyBhIGBxdWlja1NlYXJjaGAgcHNldWRvLWNvbHVtbiBzZWFyY2ggaW50byBhbiBPUiBvZiBMSUtFIGNvbmRpdGlvbnNcbiAgICogb3ZlciB0aGUgZGVjbGFyZWQge0BsaW5rIFN5bmNSZXNvdXJjZUJhc2UucXVpY2tTZWFyY2hDb2x1bW5zfS5cbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBTZWFyY2ggYXJncy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9mcm9udGVuZC1tb2RlbC1yZXNvdXJjZS9iYXNlLXJlc291cmNlLmpzXCIpLkZyb250ZW5kTW9kZWxSZXNvdXJjZUFueVF1ZXJ5fSBhcmdzLnF1ZXJ5IC0gUXVlcnkgdG8gZmlsdGVyLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2Zyb250ZW5kLW1vZGVsLXJlc291cmNlL2Jhc2UtcmVzb3VyY2UuanNcIikuRnJvbnRlbmRNb2RlbFJlc291cmNlU2VhcmNofSBhcmdzLnNlYXJjaCAtIFNlYXJjaCBwYXlsb2FkLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUgc2VhcmNoIHdhcyBoYW5kbGVkIGFzIGEgcXVpY2sgc2VhcmNoLlxuICAgKi9cbiAgYXBwbHlRdWlja1NlYXJjaCh7cXVlcnksIHNlYXJjaH0pIHtcbiAgICBjb25zdCBxdWlja1NlYXJjaENvbHVtbnMgPSAvKiogQHR5cGUge3R5cGVvZiBTeW5jUmVzb3VyY2VCYXNlfSAqLyAodGhpcy5jb25zdHJ1Y3RvcikucXVpY2tTZWFyY2hDb2x1bW5zXG5cbiAgICBpZiAoIXF1aWNrU2VhcmNoQ29sdW1ucyB8fCBxdWlja1NlYXJjaENvbHVtbnMubGVuZ3RoID09PSAwKSByZXR1cm4gZmFsc2VcbiAgICBpZiAoc2VhcmNoLnBhdGgubGVuZ3RoID4gMCB8fCBzZWFyY2guY29sdW1uICE9PSBRVUlDS19TRUFSQ0hfQ09MVU1OKSByZXR1cm4gZmFsc2VcblxuICAgIGlmIChzZWFyY2gub3BlcmF0b3IgIT09IFwibGlrZVwiKSB7XG4gICAgICB0aHJvdyBWZWxvY2lvdXNFcnJvci5zYWZlKFwiU3luYyBxdWljayBzZWFyY2ggbXVzdCB1c2UgdGhlIGxpa2Ugb3BlcmF0b3IuXCIsIHtjb2RlOiBcInN5bmMtaW52YWxpZC1xdWljay1zZWFyY2hcIn0pXG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBzZWFyY2gudmFsdWUgIT09IFwic3RyaW5nXCIpIHtcbiAgICAgIHRocm93IFZlbG9jaW91c0Vycm9yLnNhZmUoXCJTeW5jIHF1aWNrIHNlYXJjaCBtdXN0IGJlIGEgc3RyaW5nLlwiLCB7Y29kZTogXCJzeW5jLWludmFsaWQtcXVpY2stc2VhcmNoXCJ9KVxuICAgIH1cblxuICAgIGNvbnN0IHRyaW1tZWRWYWx1ZSA9IHNlYXJjaC52YWx1ZS50cmltKClcblxuICAgIGlmICghdHJpbW1lZFZhbHVlKSByZXR1cm4gdHJ1ZVxuXG4gICAgY29uc3QgdGFibGVTcWwgPSBxdWVyeS5kcml2ZXIucXVvdGVUYWJsZShxdWVyeS5nZXRUYWJsZVJlZmVyZW5jZUZvckpvaW4oKSlcbiAgICBjb25zdCBsaWtlVmFsdWUgPSBgJSR7dHJpbW1lZFZhbHVlfSVgXG4gICAgY29uc3QgY29uZGl0aW9ucyA9IHF1aWNrU2VhcmNoQ29sdW1ucy5tYXAoKGNvbHVtbk5hbWUpID0+IChcbiAgICAgIGAke3RhYmxlU3FsfS4ke3F1ZXJ5LmRyaXZlci5xdW90ZUNvbHVtbihjb2x1bW5OYW1lKX0gTElLRSAke3F1ZXJ5LmRyaXZlci5xdW90ZShsaWtlVmFsdWUpfWBcbiAgICApKVxuXG4gICAgcXVlcnkud2hlcmUoYCgke2NvbmRpdGlvbnMuam9pbihcIiBPUiBcIil9KWApXG5cbiAgICByZXR1cm4gdHJ1ZVxuICB9XG5cbiAgLyoqXG4gICAqIE5vcm1hbGl6ZXMgaW5jb21pbmcgd3JpdGFibGUgYXR0cmlidXRlcyB0aHJvdWdoIHRoZSBkZWNsYXJlZFxuICAgKiB7QGxpbmsgU3luY1Jlc291cmNlQmFzZS53cml0YWJsZUF0dHJpYnV0ZXN9IHNjaGVtYTogY2FtZWxDYXNlIGFuZFxuICAgKiBzbmFrZV9jYXNlIGlucHV0IGtleXMgYXJlIGFjY2VwdGVkLCB2YWx1ZXMgYXJlIHZhbGlkYXRlZCBwZXIgdHlwZSBhbmQgdGhlXG4gICAqIG5vcm1hbGl6ZWQgdmFsdWVzIGFyZSB3cml0dGVuIHVuZGVyIHNuYWtlX2Nhc2UgY29sdW1uIGtleXMuIFZhbGlkYXRpb25cbiAgICogZmFpbHVyZXMgdGhyb3cgY2xpZW50LXNhZmUgZXJyb3JzIGJ1aWx0IGJ5XG4gICAqIHtAbGluayBTeW5jUmVzb3VyY2VCYXNlI3dyaXRhYmxlQXR0cmlidXRlRXJyb3J9LlxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsID8+fSBhdHRyaWJ1dGVzIC0gUmF3IGluY29taW5nIGF0dHJpYnV0ZXMuXG4gICAqIEBwYXJhbSB7e3Vua25vd25BdHRyaWJ1dGVzPzogXCJlcnJvclwiIHwgXCJpZ25vcmVcIn19IFtvcHRpb25zXSAtIFVua25vd24gaW5wdXQta2V5IGhhbmRsaW5nLiBEZWZhdWx0cyB0byBcImVycm9yXCIuXG4gICAqIEByZXR1cm5zIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gTm9ybWFsaXplZCBhdHRyaWJ1dGVzIGtleWVkIGJ5IGNvbHVtbiBuYW1lcy5cbiAgICovXG4gIG5vcm1hbGl6ZVdyaXRhYmxlQXR0cmlidXRlcyhhdHRyaWJ1dGVzLCBvcHRpb25zID0ge30pIHtcbiAgICBjb25zdCBzY2hlbWEgPSAvKiogQHR5cGUge3R5cGVvZiBTeW5jUmVzb3VyY2VCYXNlfSAqLyAodGhpcy5jb25zdHJ1Y3Rvcikud3JpdGFibGVBdHRyaWJ1dGVzXG5cbiAgICBpZiAoIXNjaGVtYSkgdGhyb3cgbmV3IEVycm9yKGAke3RoaXMuY29uc3RydWN0b3IubmFtZX0gbXVzdCBkZWZpbmUgc3RhdGljIHdyaXRhYmxlQXR0cmlidXRlcyB0byB1c2Ugbm9ybWFsaXplV3JpdGFibGVBdHRyaWJ1dGVzYClcblxuICAgIHJldHVybiBub3JtYWxpemVBdHRyaWJ1dGVzV2l0aFNjaGVtYSh7XG4gICAgICBhdHRyaWJ1dGVzLFxuICAgICAgZXJyb3JGYWN0b3J5OiAobWVzc2FnZSwgZGV0YWlscykgPT4gdGhpcy53cml0YWJsZUF0dHJpYnV0ZUVycm9yKG1lc3NhZ2UsIGRldGFpbHMpLFxuICAgICAgc2NoZW1hLFxuICAgICAgdW5rbm93bkF0dHJpYnV0ZXM6IG9wdGlvbnMudW5rbm93bkF0dHJpYnV0ZXNcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyB0aGUgY2xpZW50LXNhZmUgZXJyb3IgdGhyb3duIGZvciBhIGZhaWxlZCB3cml0YWJsZS1hdHRyaWJ1dGUgdmFsaWRhdGlvbi5cbiAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBIdW1hbi1yZWFkYWJsZSB2YWxpZGF0aW9uIG1lc3NhZ2UuXG4gICAqIEBwYXJhbSB7e2NhdXNlPzogRXJyb3IsIGNvZGU6IHN0cmluZ319IGRldGFpbHMgLSBTdGFibGUgbWFjaGluZS1yZWFkYWJsZSBjb2RlIGFuZCBvcHRpb25hbCBjYXVzZS5cbiAgICogQHJldHVybnMge0Vycm9yfSBDbGllbnQtc2FmZSBlcnJvci5cbiAgICovXG4gIHdyaXRhYmxlQXR0cmlidXRlRXJyb3IobWVzc2FnZSwge2NhdXNlLCBjb2RlfSkge1xuICAgIHJldHVybiBWZWxvY2lvdXNFcnJvci5zYWZlKG1lc3NhZ2UsIGNhdXNlID8ge2NhdXNlLCBjb2RlfSA6IHtjb2RlfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgc3RhYmxlIGNoYW5nZS1mZWVkIHBhZ2UgYWZ0ZXIgYXBwIGF1dGhvcml6YXRpb24uXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsID8+Pn0gQ2hhbmdlLWZlZWQgcGFnZSByZXN1bHQuXG4gICAqL1xuICBhc3luYyBjaGFuZ2VzKCkge1xuICAgIGNvbnN0IHBhcmFtcyA9IHRoaXMucGFyYW1zKClcbiAgICBjb25zdCBzY29wZSA9IHRoaXMuY2hhbmdlc1Njb3BlKHBhcmFtcylcblxuICAgIGF3YWl0IHRoaXMuYXV0aG9yaXplQ2hhbmdlcyh7cGFyYW1zLCBzY29wZX0pXG5cbiAgICByZXR1cm4gYXdhaXQgdGhpcy5jaGFuZ2VGZWVkU2VydmljZSh7cGFyYW1zLCBzY29wZX0pLmNoYW5nZXMoKVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxheXMgY2xpZW50IHN5bmMgZW52ZWxvcGVzIHRocm91Z2ggdGhlIGFwcCByZXBsYXkgc2VydmljZS5cbiAgICogQHJldHVybnMge1Byb21pc2U8UmVjb3JkPHN0cmluZywgPz4+fSBSZXBsYXkgcmVzdWx0IHdpdGggcGVyLXN5bmMgc3RhdGVzLlxuICAgKi9cbiAgYXN5bmMgcmVwbGF5KCkge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuYnVpbGRSZXBsYXlTZXJ2aWNlKCkucmVwbGF5KHRoaXMucGFyYW1zKCkpXG5cbiAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gXCJlcnJvclwiKSByZXR1cm4gcmVzdWx0XG5cbiAgICByZXR1cm4ge3N0YXR1czogXCJzdWNjZXNzXCIsIHN5bmNzOiByZXN1bHQuc3luY3N9XG4gIH1cblxuICAvKipcbiAgICogUGFyc2VzIHRoZSBvcHRpb25hbCBjbGllbnQtZGVjbGFyZWQgc2NvcGUgZnJvbSByZXF1ZXN0IHBhcmFtcy5cbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gcGFyYW1zIC0gUmVxdWVzdCBwYXJhbXMuXG4gICAqIEByZXR1cm5zIHtTZXJpYWxpemVkQ2hhbmdlc1Njb3BlIHwgbnVsbH0gUGFyc2VkIHNjb3BlLCBvciBudWxsIHdoZW4gdGhlIGNsaWVudCBzZW50IG5vbmUuXG4gICAqL1xuICBjaGFuZ2VzU2NvcGUocGFyYW1zKSB7XG4gICAgY29uc3Qgc2NvcGUgPSBwYXJhbXMuc2NvcGVcblxuICAgIGlmIChzY29wZSA9PT0gdW5kZWZpbmVkIHx8IHNjb3BlID09PSBudWxsKSByZXR1cm4gbnVsbFxuXG4gICAgaWYgKHR5cGVvZiBzY29wZSAhPT0gXCJvYmplY3RcIiB8fCBBcnJheS5pc0FycmF5KHNjb3BlKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBTeW5jIGNoYW5nZXMgc2NvcGUgbXVzdCBiZSBhbiBvYmplY3QsIGdvdDogJHtTdHJpbmcoc2NvcGUpfWApXG4gICAgfVxuXG4gICAgY29uc3Qgc2NvcGVQYXJhbXMgPSAvKiogQHR5cGUge1JlY29yZDxzdHJpbmcsID8+fSAqLyAoc2NvcGUpXG4gICAgY29uc3QgcmVzb3VyY2VUeXBlID0gZm9yY2VkTm9uQmxhbmtTdHJpbmdQYXJhbShzY29wZVBhcmFtcywgXCJyZXNvdXJjZVR5cGVcIilcbiAgICBjb25zdCBjb25kaXRpb25zID0gc2NvcGVQYXJhbXMuY29uZGl0aW9uc1xuXG4gICAgaWYgKCFjb25kaXRpb25zIHx8IHR5cGVvZiBjb25kaXRpb25zICE9PSBcIm9iamVjdFwiIHx8IEFycmF5LmlzQXJyYXkoY29uZGl0aW9ucykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgU3luYyBjaGFuZ2VzIHNjb3BlLmNvbmRpdGlvbnMgbXVzdCBiZSBhbiBvYmplY3QsIGdvdDogJHtTdHJpbmcoY29uZGl0aW9ucyl9YClcbiAgICB9XG5cbiAgICByZXR1cm4ge2NvbmRpdGlvbnM6IC8qKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgPz59ICovIChjb25kaXRpb25zKSwgcmVzb3VyY2VUeXBlfVxuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyB0aGUgY2hhbmdlLWZlZWQgc2VydmljZSBzZXJ2aW5nIHRoaXMgY2hhbmdlcyByZXF1ZXN0LlxuICAgKiBAcGFyYW0ge3twYXJhbXM6IFJlY29yZDxzdHJpbmcsID8+LCBzY29wZTogU2VyaWFsaXplZENoYW5nZXNTY29wZSB8IG51bGx9fSBhcmdzIC0gUmVxdWVzdCBwYXJhbXMgYW5kIHBhcnNlZCBzY29wZS5cbiAgICogQHJldHVybnMge3tjaGFuZ2VzOiAoKSA9PiBQcm9taXNlPFJlY29yZDxzdHJpbmcsID8+Pn19IENoYW5nZS1mZWVkIHNlcnZpY2UuXG4gICAqL1xuICBjaGFuZ2VGZWVkU2VydmljZSh7cGFyYW1zLCBzY29wZX0pIHtcbiAgICByZXR1cm4gbmV3IFN5bmNNb2RlbENoYW5nZUZlZWRTZXJ2aWNlKHtcbiAgICAgIG1vZGVsQ2xhc3M6IHRoaXMuc3luY01vZGVsQ2xhc3MoKSxcbiAgICAgIHBhcmFtcyxcbiAgICAgIHNjb3BlUXVlcnk6ICh7cXVlcnl9KSA9PiB0aGlzLnNjb3BlQ2hhbmdlc1F1ZXJ5KHtwYXJhbXMsIHF1ZXJ5LCBzY29wZX0pXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgdGhlIGFwcCByZXBsYXkgc2VydmljZSBoYW5kbGluZyB0aGlzIHJlcGxheSByZXF1ZXN0LlxuICAgKiBAcmV0dXJucyB7aW1wb3J0KFwiLi9zeW5jLWVudmVsb3BlLXJlcGxheS1zZXJ2aWNlLmpzXCIpLmRlZmF1bHR9IFJlcGxheSBzZXJ2aWNlIGluc3RhbmNlLlxuICAgKi9cbiAgYnVpbGRSZXBsYXlTZXJ2aWNlKCkge1xuICAgIGNvbnN0IFJlcGxheVNlcnZpY2VDbGFzcyA9IHRoaXMucmVwbGF5U2VydmljZUNsYXNzKClcblxuICAgIHJldHVybiBuZXcgUmVwbGF5U2VydmljZUNsYXNzKHRoaXMucmVwbGF5U2VydmljZUFyZ3MoKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGNvbnN0cnVjdG9yIGFyZ3MgZm9yIHRoZSBhcHAgcmVwbGF5IHNlcnZpY2UuXG4gICAqIEByZXR1cm5zIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gUmVwbGF5IHNlcnZpY2UgY29uc3RydWN0b3IgYXJncy5cbiAgICovXG4gIHJlcGxheVNlcnZpY2VBcmdzKCkge1xuICAgIHJldHVybiB7fVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHN5bmMgbW9kZWwgY2xhc3MgYmFja2luZyB0aGUgY2hhbmdlIGZlZWQuXG4gICAqIEByZXR1cm5zIHt0eXBlb2YgaW1wb3J0KFwiLi4vZGF0YWJhc2UvcmVjb3JkL2luZGV4LmpzXCIpLmRlZmF1bHR9IFN5bmMgbW9kZWwgY2xhc3MuXG4gICAqL1xuICBzeW5jTW9kZWxDbGFzcygpIHtcbiAgICBjb25zdCBtb2RlbENsYXNzID0gLyoqIEB0eXBlIHt0eXBlb2YgU3luY1Jlc291cmNlQmFzZX0gKi8gKHRoaXMuY29uc3RydWN0b3IpLk1vZGVsQ2xhc3NcblxuICAgIGlmICghbW9kZWxDbGFzcykgdGhyb3cgbmV3IEVycm9yKGAke3RoaXMuY29uc3RydWN0b3IubmFtZX0gbXVzdCBkZWZpbmUgc3RhdGljIE1vZGVsQ2xhc3NgKVxuXG4gICAgcmV0dXJuIG1vZGVsQ2xhc3NcbiAgfVxuXG4gIC8qKlxuICAgKiBBdXRob3JpemVzIHRoZSBjdXJyZW50IGNvbnRleHQgZm9yIHJlYWRpbmcgdGhlIHJlcXVlc3RlZCBjaGFuZ2VzLlxuICAgKiBAcGFyYW0ge3twYXJhbXM6IFJlY29yZDxzdHJpbmcsID8+LCBzY29wZTogU2VyaWFsaXplZENoYW5nZXNTY29wZSB8IG51bGx9fSBfYXJncyAtIFJlcXVlc3QgcGFyYW1zIGFuZCBwYXJzZWQgc2NvcGUuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBSZXNvbHZlcyB3aGVuIGFjY2VzcyBpcyBhbGxvd2VkOyB0aHJvd3Mgb3RoZXJ3aXNlLlxuICAgKi9cbiAgYXN5bmMgYXV0aG9yaXplQ2hhbmdlcyhfYXJncykge1xuICAgIHRocm93IG5ldyBFcnJvcihcIlN5bmNSZXNvdXJjZUJhc2UjYXV0aG9yaXplQ2hhbmdlcyBtdXN0IGJlIGltcGxlbWVudGVkXCIpXG4gIH1cblxuICAvKipcbiAgICogQXBwbGllcyBhcHAgdmlzaWJpbGl0eSBzY29waW5nIG9udG8gdGhlIGNoYW5nZS1mZWVkIHF1ZXJ5LlxuICAgKiBAcGFyYW0ge3twYXJhbXM6IFJlY29yZDxzdHJpbmcsID8+LCBxdWVyeTogaW1wb3J0KFwiLi4vZGF0YWJhc2UvcXVlcnkvbW9kZWwtY2xhc3MtcXVlcnkuanNcIikuZGVmYXVsdCwgc2NvcGU6IFNlcmlhbGl6ZWRDaGFuZ2VzU2NvcGUgfCBudWxsfX0gX2FyZ3MgLSBSZXF1ZXN0IHBhcmFtcywgZmVlZCBxdWVyeSwgYW5kIHBhcnNlZCBzY29wZS5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICBzY29wZUNoYW5nZXNRdWVyeShfYXJncykge1xuICAgIHRocm93IG5ldyBFcnJvcihcIlN5bmNSZXNvdXJjZUJhc2Ujc2NvcGVDaGFuZ2VzUXVlcnkgbXVzdCBiZSBpbXBsZW1lbnRlZFwiKVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGFwcCByZXBsYXkgc2VydmljZSBjbGFzcyBoYW5kbGluZyByZXBsYXkgbXV0YXRpb25zLlxuICAgKiBAcmV0dXJucyB7dHlwZW9mIGltcG9ydChcIi4vc3luYy1lbnZlbG9wZS1yZXBsYXktc2VydmljZS5qc1wiKS5kZWZhdWx0fSBSZXBsYXkgc2VydmljZSBjbGFzcy5cbiAgICovXG4gIHJlcGxheVNlcnZpY2VDbGFzcygpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJTeW5jUmVzb3VyY2VCYXNlI3JlcGxheVNlcnZpY2VDbGFzcyBtdXN0IGJlIGltcGxlbWVudGVkXCIpXG4gIH1cbn1cbiJdfQ==
|