@ng-formworks/core 16.3.0 → 17.3.0
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/esm2022/lib/framework-library/framework-library.service.mjs +174 -174
- package/esm2022/lib/framework-library/framework.mjs +14 -14
- package/esm2022/lib/framework-library/no-framework.component.mjs +17 -17
- package/esm2022/lib/framework-library/no-framework.module.mjs +26 -26
- package/esm2022/lib/framework-library/no.framework.mjs +18 -18
- package/esm2022/lib/json-schema-form.component.mjs +765 -765
- package/esm2022/lib/json-schema-form.module.mjs +25 -25
- package/esm2022/lib/json-schema-form.service.mjs +675 -675
- package/esm2022/lib/locale/de-validation-messages.mjs +59 -59
- package/esm2022/lib/locale/en-validation-messages.mjs +59 -59
- package/esm2022/lib/locale/es-validation-messages.mjs +56 -56
- package/esm2022/lib/locale/fr-validation-messages.mjs +59 -59
- package/esm2022/lib/locale/index.mjs +7 -7
- package/esm2022/lib/locale/it-validation-messages.mjs +59 -59
- package/esm2022/lib/locale/pt-validation-messages.mjs +59 -59
- package/esm2022/lib/locale/zh-validation-messages.mjs +59 -59
- package/esm2022/lib/shared/convert-schema-to-draft6.function.mjs +299 -299
- package/esm2022/lib/shared/form-group.functions.mjs +441 -441
- package/esm2022/lib/shared/format-regex.constants.mjs +53 -53
- package/esm2022/lib/shared/index.mjs +11 -11
- package/esm2022/lib/shared/json-schema.functions.mjs +783 -783
- package/esm2022/lib/shared/json.validators.mjs +883 -883
- package/esm2022/lib/shared/jsonpointer.functions.mjs +1025 -1025
- package/esm2022/lib/shared/layout.functions.mjs +1153 -1153
- package/esm2022/lib/shared/merge-schemas.function.mjs +344 -344
- package/esm2022/lib/shared/utility.functions.mjs +379 -379
- package/esm2022/lib/shared/validator.functions.mjs +583 -583
- package/esm2022/lib/widget-library/add-reference.component.mjs +48 -48
- package/esm2022/lib/widget-library/button.component.mjs +41 -41
- package/esm2022/lib/widget-library/checkbox.component.mjs +46 -46
- package/esm2022/lib/widget-library/checkboxes.component.mjs +52 -52
- package/esm2022/lib/widget-library/file.component.mjs +35 -35
- package/esm2022/lib/widget-library/hidden.component.mjs +33 -33
- package/esm2022/lib/widget-library/index.mjs +54 -54
- package/esm2022/lib/widget-library/input.component.mjs +38 -38
- package/esm2022/lib/widget-library/message.component.mjs +33 -33
- package/esm2022/lib/widget-library/none.component.mjs +20 -20
- package/esm2022/lib/widget-library/number.component.mjs +44 -44
- package/esm2022/lib/widget-library/one-of.component.mjs +35 -35
- package/esm2022/lib/widget-library/orderable.directive.mjs +123 -123
- package/esm2022/lib/widget-library/radios.component.mjs +44 -44
- package/esm2022/lib/widget-library/root.component.mjs +44 -44
- package/esm2022/lib/widget-library/section.component.mjs +78 -78
- package/esm2022/lib/widget-library/select-framework.component.mjs +51 -51
- package/esm2022/lib/widget-library/select-widget.component.mjs +46 -46
- package/esm2022/lib/widget-library/select.component.mjs +41 -41
- package/esm2022/lib/widget-library/submit.component.mjs +55 -55
- package/esm2022/lib/widget-library/tab.component.mjs +30 -30
- package/esm2022/lib/widget-library/tabs.component.mjs +53 -53
- package/esm2022/lib/widget-library/template.component.mjs +46 -46
- package/esm2022/lib/widget-library/textarea.component.mjs +37 -37
- package/esm2022/lib/widget-library/widget-library.module.mjs +41 -41
- package/esm2022/lib/widget-library/widget-library.service.mjs +225 -225
- package/esm2022/ng-formworks-core.mjs +4 -4
- package/esm2022/public_api.mjs +12 -12
- package/fesm2022/ng-formworks-core.mjs +9103 -9103
- package/fesm2022/ng-formworks-core.mjs.map +1 -1
- package/index.d.ts +5 -5
- package/lib/framework-library/framework-library.service.d.ts +55 -55
- package/lib/framework-library/framework.d.ts +13 -13
- package/lib/framework-library/no-framework.component.d.ts +8 -8
- package/lib/framework-library/no-framework.module.d.ts +9 -9
- package/lib/framework-library/no.framework.d.ts +10 -10
- package/lib/json-schema-form.component.d.ts +218 -218
- package/lib/json-schema-form.module.d.ts +11 -11
- package/lib/json-schema-form.service.d.ts +115 -115
- package/lib/locale/de-validation-messages.d.ts +1 -1
- package/lib/locale/en-validation-messages.d.ts +1 -1
- package/lib/locale/es-validation-messages.d.ts +1 -1
- package/lib/locale/fr-validation-messages.d.ts +1 -1
- package/lib/locale/index.d.ts +7 -7
- package/lib/locale/it-validation-messages.d.ts +1 -1
- package/lib/locale/pt-validation-messages.d.ts +1 -1
- package/lib/locale/zh-validation-messages.d.ts +1 -1
- package/lib/shared/convert-schema-to-draft6.function.d.ts +21 -21
- package/lib/shared/form-group.functions.d.ts +100 -100
- package/lib/shared/format-regex.constants.d.ts +19 -19
- package/lib/shared/index.d.ts +9 -9
- package/lib/shared/json-schema.functions.d.ts +193 -193
- package/lib/shared/json.validators.d.ts +441 -441
- package/lib/shared/jsonpointer.functions.d.ts +416 -416
- package/lib/shared/layout.functions.d.ts +83 -83
- package/lib/shared/merge-schemas.function.d.ts +19 -19
- package/lib/shared/utility.functions.d.ts +165 -165
- package/lib/shared/validator.functions.d.ts +364 -364
- package/lib/widget-library/add-reference.component.d.ts +20 -20
- package/lib/widget-library/button.component.d.ts +21 -21
- package/lib/widget-library/checkbox.component.d.ts +24 -24
- package/lib/widget-library/checkboxes.component.d.ts +24 -24
- package/lib/widget-library/file.component.d.ts +21 -21
- package/lib/widget-library/hidden.component.d.ts +19 -19
- package/lib/widget-library/index.d.ts +47 -47
- package/lib/widget-library/input.component.d.ts +22 -22
- package/lib/widget-library/message.component.d.ts +15 -15
- package/lib/widget-library/none.component.d.ts +8 -8
- package/lib/widget-library/number.component.d.ts +25 -25
- package/lib/widget-library/one-of.component.d.ts +21 -21
- package/lib/widget-library/orderable.directive.d.ts +41 -41
- package/lib/widget-library/radios.component.d.ts +23 -23
- package/lib/widget-library/root.component.d.ts +17 -17
- package/lib/widget-library/section.component.d.ts +19 -19
- package/lib/widget-library/select-framework.component.d.ts +18 -18
- package/lib/widget-library/select-widget.component.d.ts +18 -18
- package/lib/widget-library/select.component.d.ts +24 -24
- package/lib/widget-library/submit.component.d.ts +24 -24
- package/lib/widget-library/tab.component.d.ts +14 -14
- package/lib/widget-library/tabs.component.d.ts +20 -20
- package/lib/widget-library/template.component.d.ts +18 -18
- package/lib/widget-library/textarea.component.d.ts +21 -21
- package/lib/widget-library/widget-library.module.d.ts +31 -31
- package/lib/widget-library/widget-library.service.d.ts +22 -22
- package/package.json +5 -5
- package/public_api.d.ts +9 -9
|
@@ -1,345 +1,345 @@
|
|
|
1
|
-
import isEqual from 'lodash/isEqual';
|
|
2
|
-
import { isArray, isEmpty, isNumber, isObject, isString } from './validator.functions';
|
|
3
|
-
import { hasOwn, uniqueItems, commonItems } from './utility.functions';
|
|
4
|
-
/**
|
|
5
|
-
* 'mergeSchemas' function
|
|
6
|
-
*
|
|
7
|
-
* Merges multiple JSON schemas into a single schema with combined rules.
|
|
8
|
-
*
|
|
9
|
-
* If able to logically merge properties from all schemas,
|
|
10
|
-
* returns a single schema object containing all merged properties.
|
|
11
|
-
*
|
|
12
|
-
* Example: ({ a: b, max: 1 }, { c: d, max: 2 }) => { a: b, c: d, max: 1 }
|
|
13
|
-
*
|
|
14
|
-
* If unable to logically merge, returns an allOf schema object containing
|
|
15
|
-
* an array of the original schemas;
|
|
16
|
-
*
|
|
17
|
-
* Example: ({ a: b }, { a: d }) => { allOf: [ { a: b }, { a: d } ] }
|
|
18
|
-
*
|
|
19
|
-
* // schemas - one or more input schemas
|
|
20
|
-
* // - merged schema
|
|
21
|
-
*/
|
|
22
|
-
export function mergeSchemas(...schemas) {
|
|
23
|
-
schemas = schemas.filter(schema => !isEmpty(schema));
|
|
24
|
-
if (schemas.some(schema => !isObject(schema))) {
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
const combinedSchema = {};
|
|
28
|
-
for (const schema of schemas) {
|
|
29
|
-
for (const key of Object.keys(schema)) {
|
|
30
|
-
const combinedValue = combinedSchema[key];
|
|
31
|
-
const schemaValue = schema[key];
|
|
32
|
-
if (!hasOwn(combinedSchema, key) || isEqual(combinedValue, schemaValue)) {
|
|
33
|
-
combinedSchema[key] = schemaValue;
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
switch (key) {
|
|
37
|
-
case 'allOf':
|
|
38
|
-
// Combine all items from both arrays
|
|
39
|
-
if (isArray(combinedValue) && isArray(schemaValue)) {
|
|
40
|
-
combinedSchema.allOf = mergeSchemas(...combinedValue, ...schemaValue);
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
return { allOf: [...schemas] };
|
|
44
|
-
}
|
|
45
|
-
break;
|
|
46
|
-
case 'additionalItems':
|
|
47
|
-
case 'additionalProperties':
|
|
48
|
-
case 'contains':
|
|
49
|
-
case 'propertyNames':
|
|
50
|
-
// Merge schema objects
|
|
51
|
-
if (isObject(combinedValue) && isObject(schemaValue)) {
|
|
52
|
-
combinedSchema[key] = mergeSchemas(combinedValue, schemaValue);
|
|
53
|
-
// additionalProperties == false in any schema overrides all other values
|
|
54
|
-
}
|
|
55
|
-
else if (key === 'additionalProperties' &&
|
|
56
|
-
(combinedValue === false || schemaValue === false)) {
|
|
57
|
-
combinedSchema.combinedSchema = false;
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
return { allOf: [...schemas] };
|
|
61
|
-
}
|
|
62
|
-
break;
|
|
63
|
-
case 'anyOf':
|
|
64
|
-
case 'oneOf':
|
|
65
|
-
case 'enum':
|
|
66
|
-
// Keep only items that appear in both arrays
|
|
67
|
-
if (isArray(combinedValue) && isArray(schemaValue)) {
|
|
68
|
-
combinedSchema[key] = combinedValue.filter(item1 => schemaValue.findIndex(item2 => isEqual(item1, item2)) > -1);
|
|
69
|
-
if (!combinedSchema[key].length) {
|
|
70
|
-
return { allOf: [...schemas] };
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
return { allOf: [...schemas] };
|
|
75
|
-
}
|
|
76
|
-
break;
|
|
77
|
-
case 'definitions':
|
|
78
|
-
// Combine keys from both objects
|
|
79
|
-
if (isObject(combinedValue) && isObject(schemaValue)) {
|
|
80
|
-
const combinedObject = { ...combinedValue };
|
|
81
|
-
for (const subKey of Object.keys(schemaValue)) {
|
|
82
|
-
if (!hasOwn(combinedObject, subKey) ||
|
|
83
|
-
isEqual(combinedObject[subKey], schemaValue[subKey])) {
|
|
84
|
-
combinedObject[subKey] = schemaValue[subKey];
|
|
85
|
-
// Don't combine matching keys with different values
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
return { allOf: [...schemas] };
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
combinedSchema.definitions = combinedObject;
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
return { allOf: [...schemas] };
|
|
95
|
-
}
|
|
96
|
-
break;
|
|
97
|
-
case 'dependencies':
|
|
98
|
-
// Combine all keys from both objects
|
|
99
|
-
// and merge schemas on matching keys,
|
|
100
|
-
// converting from arrays to objects if necessary
|
|
101
|
-
if (isObject(combinedValue) && isObject(schemaValue)) {
|
|
102
|
-
const combinedObject = { ...combinedValue };
|
|
103
|
-
for (const subKey of Object.keys(schemaValue)) {
|
|
104
|
-
if (!hasOwn(combinedObject, subKey) ||
|
|
105
|
-
isEqual(combinedObject[subKey], schemaValue[subKey])) {
|
|
106
|
-
combinedObject[subKey] = schemaValue[subKey];
|
|
107
|
-
// If both keys are arrays, include all items from both arrays,
|
|
108
|
-
// excluding duplicates
|
|
109
|
-
}
|
|
110
|
-
else if (isArray(schemaValue[subKey]) && isArray(combinedObject[subKey])) {
|
|
111
|
-
combinedObject[subKey] =
|
|
112
|
-
uniqueItems(...combinedObject[subKey], ...schemaValue[subKey]);
|
|
113
|
-
// If either key is an object, merge the schemas
|
|
114
|
-
}
|
|
115
|
-
else if ((isArray(schemaValue[subKey]) || isObject(schemaValue[subKey])) &&
|
|
116
|
-
(isArray(combinedObject[subKey]) || isObject(combinedObject[subKey]))) {
|
|
117
|
-
// If either key is an array, convert it to an object first
|
|
118
|
-
const required = isArray(combinedSchema.required) ?
|
|
119
|
-
combinedSchema.required : [];
|
|
120
|
-
const combinedDependency = isArray(combinedObject[subKey]) ?
|
|
121
|
-
{ required: uniqueItems(...required, combinedObject[subKey]) } :
|
|
122
|
-
combinedObject[subKey];
|
|
123
|
-
const schemaDependency = isArray(schemaValue[subKey]) ?
|
|
124
|
-
{ required: uniqueItems(...required, schemaValue[subKey]) } :
|
|
125
|
-
schemaValue[subKey];
|
|
126
|
-
combinedObject[subKey] =
|
|
127
|
-
mergeSchemas(combinedDependency, schemaDependency);
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
return { allOf: [...schemas] };
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
combinedSchema.dependencies = combinedObject;
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
return { allOf: [...schemas] };
|
|
137
|
-
}
|
|
138
|
-
break;
|
|
139
|
-
case 'items':
|
|
140
|
-
// If arrays, keep only items that appear in both arrays
|
|
141
|
-
if (isArray(combinedValue) && isArray(schemaValue)) {
|
|
142
|
-
combinedSchema.items = combinedValue.filter(item1 => schemaValue.findIndex(item2 => isEqual(item1, item2)) > -1);
|
|
143
|
-
if (!combinedSchema.items.length) {
|
|
144
|
-
return { allOf: [...schemas] };
|
|
145
|
-
}
|
|
146
|
-
// If both keys are objects, merge them
|
|
147
|
-
}
|
|
148
|
-
else if (isObject(combinedValue) && isObject(schemaValue)) {
|
|
149
|
-
combinedSchema.items = mergeSchemas(combinedValue, schemaValue);
|
|
150
|
-
// If object + array, combine object with each array item
|
|
151
|
-
}
|
|
152
|
-
else if (isArray(combinedValue) && isObject(schemaValue)) {
|
|
153
|
-
combinedSchema.items =
|
|
154
|
-
combinedValue.map(item => mergeSchemas(item, schemaValue));
|
|
155
|
-
}
|
|
156
|
-
else if (isObject(combinedValue) && isArray(schemaValue)) {
|
|
157
|
-
combinedSchema.items =
|
|
158
|
-
schemaValue.map(item => mergeSchemas(item, combinedValue));
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
return { allOf: [...schemas] };
|
|
162
|
-
}
|
|
163
|
-
break;
|
|
164
|
-
case 'multipleOf':
|
|
165
|
-
// TODO: Adjust to correctly handle decimal values
|
|
166
|
-
// If numbers, set to least common multiple
|
|
167
|
-
if (isNumber(combinedValue) && isNumber(schemaValue)) {
|
|
168
|
-
const gcd = (x, y) => !y ? x : gcd(y, x % y);
|
|
169
|
-
const lcm = (x, y) => (x * y) / gcd(x, y);
|
|
170
|
-
combinedSchema.multipleOf = lcm(combinedValue, schemaValue);
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
return { allOf: [...schemas] };
|
|
174
|
-
}
|
|
175
|
-
break;
|
|
176
|
-
case 'maximum':
|
|
177
|
-
case 'exclusiveMaximum':
|
|
178
|
-
case 'maxLength':
|
|
179
|
-
case 'maxItems':
|
|
180
|
-
case 'maxProperties':
|
|
181
|
-
// If numbers, set to lowest value
|
|
182
|
-
if (isNumber(combinedValue) && isNumber(schemaValue)) {
|
|
183
|
-
combinedSchema[key] = Math.min(combinedValue, schemaValue);
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
return { allOf: [...schemas] };
|
|
187
|
-
}
|
|
188
|
-
break;
|
|
189
|
-
case 'minimum':
|
|
190
|
-
case 'exclusiveMinimum':
|
|
191
|
-
case 'minLength':
|
|
192
|
-
case 'minItems':
|
|
193
|
-
case 'minProperties':
|
|
194
|
-
// If numbers, set to highest value
|
|
195
|
-
if (isNumber(combinedValue) && isNumber(schemaValue)) {
|
|
196
|
-
combinedSchema[key] = Math.max(combinedValue, schemaValue);
|
|
197
|
-
}
|
|
198
|
-
else {
|
|
199
|
-
return { allOf: [...schemas] };
|
|
200
|
-
}
|
|
201
|
-
break;
|
|
202
|
-
case 'not':
|
|
203
|
-
// Combine not values into anyOf array
|
|
204
|
-
if (isObject(combinedValue) && isObject(schemaValue)) {
|
|
205
|
-
const notAnyOf = [combinedValue, schemaValue]
|
|
206
|
-
.reduce((notAnyOfArray, notSchema) => isArray(notSchema.anyOf) &&
|
|
207
|
-
Object.keys(notSchema).length === 1 ?
|
|
208
|
-
[...notAnyOfArray, ...notSchema.anyOf] :
|
|
209
|
-
[...notAnyOfArray, notSchema], []);
|
|
210
|
-
// TODO: Remove duplicate items from array
|
|
211
|
-
combinedSchema.not = { anyOf: notAnyOf };
|
|
212
|
-
}
|
|
213
|
-
else {
|
|
214
|
-
return { allOf: [...schemas] };
|
|
215
|
-
}
|
|
216
|
-
break;
|
|
217
|
-
case 'patternProperties':
|
|
218
|
-
// Combine all keys from both objects
|
|
219
|
-
// and merge schemas on matching keys
|
|
220
|
-
if (isObject(combinedValue) && isObject(schemaValue)) {
|
|
221
|
-
const combinedObject = { ...combinedValue };
|
|
222
|
-
for (const subKey of Object.keys(schemaValue)) {
|
|
223
|
-
if (!hasOwn(combinedObject, subKey) ||
|
|
224
|
-
isEqual(combinedObject[subKey], schemaValue[subKey])) {
|
|
225
|
-
combinedObject[subKey] = schemaValue[subKey];
|
|
226
|
-
// If both keys are objects, merge them
|
|
227
|
-
}
|
|
228
|
-
else if (isObject(schemaValue[subKey]) && isObject(combinedObject[subKey])) {
|
|
229
|
-
combinedObject[subKey] =
|
|
230
|
-
mergeSchemas(combinedObject[subKey], schemaValue[subKey]);
|
|
231
|
-
}
|
|
232
|
-
else {
|
|
233
|
-
return { allOf: [...schemas] };
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
combinedSchema.patternProperties = combinedObject;
|
|
237
|
-
}
|
|
238
|
-
else {
|
|
239
|
-
return { allOf: [...schemas] };
|
|
240
|
-
}
|
|
241
|
-
break;
|
|
242
|
-
case 'properties':
|
|
243
|
-
// Combine all keys from both objects
|
|
244
|
-
// unless additionalProperties === false
|
|
245
|
-
// and merge schemas on matching keys
|
|
246
|
-
if (isObject(combinedValue) && isObject(schemaValue)) {
|
|
247
|
-
const combinedObject = { ...combinedValue };
|
|
248
|
-
// If new schema has additionalProperties,
|
|
249
|
-
// merge or remove non-matching property keys in combined schema
|
|
250
|
-
if (hasOwn(schemaValue, 'additionalProperties')) {
|
|
251
|
-
Object.keys(combinedValue)
|
|
252
|
-
.filter(combinedKey => !Object.keys(schemaValue).includes(combinedKey))
|
|
253
|
-
.forEach(nonMatchingKey => {
|
|
254
|
-
if (schemaValue.additionalProperties === false) {
|
|
255
|
-
delete combinedObject[nonMatchingKey];
|
|
256
|
-
}
|
|
257
|
-
else if (isObject(schemaValue.additionalProperties)) {
|
|
258
|
-
combinedObject[nonMatchingKey] = mergeSchemas(combinedObject[nonMatchingKey], schemaValue.additionalProperties);
|
|
259
|
-
}
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
for (const subKey of Object.keys(schemaValue)) {
|
|
263
|
-
if (isEqual(combinedObject[subKey], schemaValue[subKey]) || (!hasOwn(combinedObject, subKey) &&
|
|
264
|
-
!hasOwn(combinedObject, 'additionalProperties'))) {
|
|
265
|
-
combinedObject[subKey] = schemaValue[subKey];
|
|
266
|
-
// If combined schema has additionalProperties,
|
|
267
|
-
// merge or ignore non-matching property keys in new schema
|
|
268
|
-
}
|
|
269
|
-
else if (!hasOwn(combinedObject, subKey) &&
|
|
270
|
-
hasOwn(combinedObject, 'additionalProperties')) {
|
|
271
|
-
// If combinedObject.additionalProperties === false,
|
|
272
|
-
// do nothing (don't set key)
|
|
273
|
-
// If additionalProperties is object, merge with new key
|
|
274
|
-
if (isObject(combinedObject.additionalProperties)) {
|
|
275
|
-
combinedObject[subKey] = mergeSchemas(combinedObject.additionalProperties, schemaValue[subKey]);
|
|
276
|
-
}
|
|
277
|
-
// If both keys are objects, merge them
|
|
278
|
-
}
|
|
279
|
-
else if (isObject(schemaValue[subKey]) &&
|
|
280
|
-
isObject(combinedObject[subKey])) {
|
|
281
|
-
combinedObject[subKey] =
|
|
282
|
-
mergeSchemas(combinedObject[subKey], schemaValue[subKey]);
|
|
283
|
-
}
|
|
284
|
-
else {
|
|
285
|
-
return { allOf: [...schemas] };
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
combinedSchema.properties = combinedObject;
|
|
289
|
-
}
|
|
290
|
-
else {
|
|
291
|
-
return { allOf: [...schemas] };
|
|
292
|
-
}
|
|
293
|
-
break;
|
|
294
|
-
case 'required':
|
|
295
|
-
// If arrays, include all items from both arrays, excluding duplicates
|
|
296
|
-
if (isArray(combinedValue) && isArray(schemaValue)) {
|
|
297
|
-
combinedSchema.required = uniqueItems(...combinedValue, ...schemaValue);
|
|
298
|
-
// If booleans, aet true if either true
|
|
299
|
-
}
|
|
300
|
-
else if (typeof schemaValue === 'boolean' &&
|
|
301
|
-
typeof combinedValue === 'boolean') {
|
|
302
|
-
combinedSchema.required = !!combinedValue || !!schemaValue;
|
|
303
|
-
}
|
|
304
|
-
else {
|
|
305
|
-
return { allOf: [...schemas] };
|
|
306
|
-
}
|
|
307
|
-
break;
|
|
308
|
-
case '$schema':
|
|
309
|
-
case '$id':
|
|
310
|
-
case 'id':
|
|
311
|
-
// Don't combine these keys
|
|
312
|
-
break;
|
|
313
|
-
case 'title':
|
|
314
|
-
case 'description':
|
|
315
|
-
case '$comment':
|
|
316
|
-
// Return the last value, overwriting any previous one
|
|
317
|
-
// These properties are not used for validation, so conflicts don't matter
|
|
318
|
-
combinedSchema[key] = schemaValue;
|
|
319
|
-
break;
|
|
320
|
-
case 'type':
|
|
321
|
-
if ((isArray(schemaValue) || isString(schemaValue)) &&
|
|
322
|
-
(isArray(combinedValue) || isString(combinedValue))) {
|
|
323
|
-
const combinedTypes = commonItems(combinedValue, schemaValue);
|
|
324
|
-
if (!combinedTypes.length) {
|
|
325
|
-
return { allOf: [...schemas] };
|
|
326
|
-
}
|
|
327
|
-
combinedSchema.type = combinedTypes.length > 1 ? combinedTypes : combinedTypes[0];
|
|
328
|
-
}
|
|
329
|
-
else {
|
|
330
|
-
return { allOf: [...schemas] };
|
|
331
|
-
}
|
|
332
|
-
break;
|
|
333
|
-
case 'uniqueItems':
|
|
334
|
-
// Set true if either true
|
|
335
|
-
combinedSchema.uniqueItems = !!combinedValue || !!schemaValue;
|
|
336
|
-
break;
|
|
337
|
-
default:
|
|
338
|
-
return { allOf: [...schemas] };
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
return combinedSchema;
|
|
344
|
-
}
|
|
1
|
+
import isEqual from 'lodash/isEqual';
|
|
2
|
+
import { isArray, isEmpty, isNumber, isObject, isString } from './validator.functions';
|
|
3
|
+
import { hasOwn, uniqueItems, commonItems } from './utility.functions';
|
|
4
|
+
/**
|
|
5
|
+
* 'mergeSchemas' function
|
|
6
|
+
*
|
|
7
|
+
* Merges multiple JSON schemas into a single schema with combined rules.
|
|
8
|
+
*
|
|
9
|
+
* If able to logically merge properties from all schemas,
|
|
10
|
+
* returns a single schema object containing all merged properties.
|
|
11
|
+
*
|
|
12
|
+
* Example: ({ a: b, max: 1 }, { c: d, max: 2 }) => { a: b, c: d, max: 1 }
|
|
13
|
+
*
|
|
14
|
+
* If unable to logically merge, returns an allOf schema object containing
|
|
15
|
+
* an array of the original schemas;
|
|
16
|
+
*
|
|
17
|
+
* Example: ({ a: b }, { a: d }) => { allOf: [ { a: b }, { a: d } ] }
|
|
18
|
+
*
|
|
19
|
+
* // schemas - one or more input schemas
|
|
20
|
+
* // - merged schema
|
|
21
|
+
*/
|
|
22
|
+
export function mergeSchemas(...schemas) {
|
|
23
|
+
schemas = schemas.filter(schema => !isEmpty(schema));
|
|
24
|
+
if (schemas.some(schema => !isObject(schema))) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
const combinedSchema = {};
|
|
28
|
+
for (const schema of schemas) {
|
|
29
|
+
for (const key of Object.keys(schema)) {
|
|
30
|
+
const combinedValue = combinedSchema[key];
|
|
31
|
+
const schemaValue = schema[key];
|
|
32
|
+
if (!hasOwn(combinedSchema, key) || isEqual(combinedValue, schemaValue)) {
|
|
33
|
+
combinedSchema[key] = schemaValue;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
switch (key) {
|
|
37
|
+
case 'allOf':
|
|
38
|
+
// Combine all items from both arrays
|
|
39
|
+
if (isArray(combinedValue) && isArray(schemaValue)) {
|
|
40
|
+
combinedSchema.allOf = mergeSchemas(...combinedValue, ...schemaValue);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
return { allOf: [...schemas] };
|
|
44
|
+
}
|
|
45
|
+
break;
|
|
46
|
+
case 'additionalItems':
|
|
47
|
+
case 'additionalProperties':
|
|
48
|
+
case 'contains':
|
|
49
|
+
case 'propertyNames':
|
|
50
|
+
// Merge schema objects
|
|
51
|
+
if (isObject(combinedValue) && isObject(schemaValue)) {
|
|
52
|
+
combinedSchema[key] = mergeSchemas(combinedValue, schemaValue);
|
|
53
|
+
// additionalProperties == false in any schema overrides all other values
|
|
54
|
+
}
|
|
55
|
+
else if (key === 'additionalProperties' &&
|
|
56
|
+
(combinedValue === false || schemaValue === false)) {
|
|
57
|
+
combinedSchema.combinedSchema = false;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
return { allOf: [...schemas] };
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
case 'anyOf':
|
|
64
|
+
case 'oneOf':
|
|
65
|
+
case 'enum':
|
|
66
|
+
// Keep only items that appear in both arrays
|
|
67
|
+
if (isArray(combinedValue) && isArray(schemaValue)) {
|
|
68
|
+
combinedSchema[key] = combinedValue.filter(item1 => schemaValue.findIndex(item2 => isEqual(item1, item2)) > -1);
|
|
69
|
+
if (!combinedSchema[key].length) {
|
|
70
|
+
return { allOf: [...schemas] };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
return { allOf: [...schemas] };
|
|
75
|
+
}
|
|
76
|
+
break;
|
|
77
|
+
case 'definitions':
|
|
78
|
+
// Combine keys from both objects
|
|
79
|
+
if (isObject(combinedValue) && isObject(schemaValue)) {
|
|
80
|
+
const combinedObject = { ...combinedValue };
|
|
81
|
+
for (const subKey of Object.keys(schemaValue)) {
|
|
82
|
+
if (!hasOwn(combinedObject, subKey) ||
|
|
83
|
+
isEqual(combinedObject[subKey], schemaValue[subKey])) {
|
|
84
|
+
combinedObject[subKey] = schemaValue[subKey];
|
|
85
|
+
// Don't combine matching keys with different values
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
return { allOf: [...schemas] };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
combinedSchema.definitions = combinedObject;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
return { allOf: [...schemas] };
|
|
95
|
+
}
|
|
96
|
+
break;
|
|
97
|
+
case 'dependencies':
|
|
98
|
+
// Combine all keys from both objects
|
|
99
|
+
// and merge schemas on matching keys,
|
|
100
|
+
// converting from arrays to objects if necessary
|
|
101
|
+
if (isObject(combinedValue) && isObject(schemaValue)) {
|
|
102
|
+
const combinedObject = { ...combinedValue };
|
|
103
|
+
for (const subKey of Object.keys(schemaValue)) {
|
|
104
|
+
if (!hasOwn(combinedObject, subKey) ||
|
|
105
|
+
isEqual(combinedObject[subKey], schemaValue[subKey])) {
|
|
106
|
+
combinedObject[subKey] = schemaValue[subKey];
|
|
107
|
+
// If both keys are arrays, include all items from both arrays,
|
|
108
|
+
// excluding duplicates
|
|
109
|
+
}
|
|
110
|
+
else if (isArray(schemaValue[subKey]) && isArray(combinedObject[subKey])) {
|
|
111
|
+
combinedObject[subKey] =
|
|
112
|
+
uniqueItems(...combinedObject[subKey], ...schemaValue[subKey]);
|
|
113
|
+
// If either key is an object, merge the schemas
|
|
114
|
+
}
|
|
115
|
+
else if ((isArray(schemaValue[subKey]) || isObject(schemaValue[subKey])) &&
|
|
116
|
+
(isArray(combinedObject[subKey]) || isObject(combinedObject[subKey]))) {
|
|
117
|
+
// If either key is an array, convert it to an object first
|
|
118
|
+
const required = isArray(combinedSchema.required) ?
|
|
119
|
+
combinedSchema.required : [];
|
|
120
|
+
const combinedDependency = isArray(combinedObject[subKey]) ?
|
|
121
|
+
{ required: uniqueItems(...required, combinedObject[subKey]) } :
|
|
122
|
+
combinedObject[subKey];
|
|
123
|
+
const schemaDependency = isArray(schemaValue[subKey]) ?
|
|
124
|
+
{ required: uniqueItems(...required, schemaValue[subKey]) } :
|
|
125
|
+
schemaValue[subKey];
|
|
126
|
+
combinedObject[subKey] =
|
|
127
|
+
mergeSchemas(combinedDependency, schemaDependency);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
return { allOf: [...schemas] };
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
combinedSchema.dependencies = combinedObject;
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
return { allOf: [...schemas] };
|
|
137
|
+
}
|
|
138
|
+
break;
|
|
139
|
+
case 'items':
|
|
140
|
+
// If arrays, keep only items that appear in both arrays
|
|
141
|
+
if (isArray(combinedValue) && isArray(schemaValue)) {
|
|
142
|
+
combinedSchema.items = combinedValue.filter(item1 => schemaValue.findIndex(item2 => isEqual(item1, item2)) > -1);
|
|
143
|
+
if (!combinedSchema.items.length) {
|
|
144
|
+
return { allOf: [...schemas] };
|
|
145
|
+
}
|
|
146
|
+
// If both keys are objects, merge them
|
|
147
|
+
}
|
|
148
|
+
else if (isObject(combinedValue) && isObject(schemaValue)) {
|
|
149
|
+
combinedSchema.items = mergeSchemas(combinedValue, schemaValue);
|
|
150
|
+
// If object + array, combine object with each array item
|
|
151
|
+
}
|
|
152
|
+
else if (isArray(combinedValue) && isObject(schemaValue)) {
|
|
153
|
+
combinedSchema.items =
|
|
154
|
+
combinedValue.map(item => mergeSchemas(item, schemaValue));
|
|
155
|
+
}
|
|
156
|
+
else if (isObject(combinedValue) && isArray(schemaValue)) {
|
|
157
|
+
combinedSchema.items =
|
|
158
|
+
schemaValue.map(item => mergeSchemas(item, combinedValue));
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
return { allOf: [...schemas] };
|
|
162
|
+
}
|
|
163
|
+
break;
|
|
164
|
+
case 'multipleOf':
|
|
165
|
+
// TODO: Adjust to correctly handle decimal values
|
|
166
|
+
// If numbers, set to least common multiple
|
|
167
|
+
if (isNumber(combinedValue) && isNumber(schemaValue)) {
|
|
168
|
+
const gcd = (x, y) => !y ? x : gcd(y, x % y);
|
|
169
|
+
const lcm = (x, y) => (x * y) / gcd(x, y);
|
|
170
|
+
combinedSchema.multipleOf = lcm(combinedValue, schemaValue);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
return { allOf: [...schemas] };
|
|
174
|
+
}
|
|
175
|
+
break;
|
|
176
|
+
case 'maximum':
|
|
177
|
+
case 'exclusiveMaximum':
|
|
178
|
+
case 'maxLength':
|
|
179
|
+
case 'maxItems':
|
|
180
|
+
case 'maxProperties':
|
|
181
|
+
// If numbers, set to lowest value
|
|
182
|
+
if (isNumber(combinedValue) && isNumber(schemaValue)) {
|
|
183
|
+
combinedSchema[key] = Math.min(combinedValue, schemaValue);
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
return { allOf: [...schemas] };
|
|
187
|
+
}
|
|
188
|
+
break;
|
|
189
|
+
case 'minimum':
|
|
190
|
+
case 'exclusiveMinimum':
|
|
191
|
+
case 'minLength':
|
|
192
|
+
case 'minItems':
|
|
193
|
+
case 'minProperties':
|
|
194
|
+
// If numbers, set to highest value
|
|
195
|
+
if (isNumber(combinedValue) && isNumber(schemaValue)) {
|
|
196
|
+
combinedSchema[key] = Math.max(combinedValue, schemaValue);
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
return { allOf: [...schemas] };
|
|
200
|
+
}
|
|
201
|
+
break;
|
|
202
|
+
case 'not':
|
|
203
|
+
// Combine not values into anyOf array
|
|
204
|
+
if (isObject(combinedValue) && isObject(schemaValue)) {
|
|
205
|
+
const notAnyOf = [combinedValue, schemaValue]
|
|
206
|
+
.reduce((notAnyOfArray, notSchema) => isArray(notSchema.anyOf) &&
|
|
207
|
+
Object.keys(notSchema).length === 1 ?
|
|
208
|
+
[...notAnyOfArray, ...notSchema.anyOf] :
|
|
209
|
+
[...notAnyOfArray, notSchema], []);
|
|
210
|
+
// TODO: Remove duplicate items from array
|
|
211
|
+
combinedSchema.not = { anyOf: notAnyOf };
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
return { allOf: [...schemas] };
|
|
215
|
+
}
|
|
216
|
+
break;
|
|
217
|
+
case 'patternProperties':
|
|
218
|
+
// Combine all keys from both objects
|
|
219
|
+
// and merge schemas on matching keys
|
|
220
|
+
if (isObject(combinedValue) && isObject(schemaValue)) {
|
|
221
|
+
const combinedObject = { ...combinedValue };
|
|
222
|
+
for (const subKey of Object.keys(schemaValue)) {
|
|
223
|
+
if (!hasOwn(combinedObject, subKey) ||
|
|
224
|
+
isEqual(combinedObject[subKey], schemaValue[subKey])) {
|
|
225
|
+
combinedObject[subKey] = schemaValue[subKey];
|
|
226
|
+
// If both keys are objects, merge them
|
|
227
|
+
}
|
|
228
|
+
else if (isObject(schemaValue[subKey]) && isObject(combinedObject[subKey])) {
|
|
229
|
+
combinedObject[subKey] =
|
|
230
|
+
mergeSchemas(combinedObject[subKey], schemaValue[subKey]);
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
return { allOf: [...schemas] };
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
combinedSchema.patternProperties = combinedObject;
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
return { allOf: [...schemas] };
|
|
240
|
+
}
|
|
241
|
+
break;
|
|
242
|
+
case 'properties':
|
|
243
|
+
// Combine all keys from both objects
|
|
244
|
+
// unless additionalProperties === false
|
|
245
|
+
// and merge schemas on matching keys
|
|
246
|
+
if (isObject(combinedValue) && isObject(schemaValue)) {
|
|
247
|
+
const combinedObject = { ...combinedValue };
|
|
248
|
+
// If new schema has additionalProperties,
|
|
249
|
+
// merge or remove non-matching property keys in combined schema
|
|
250
|
+
if (hasOwn(schemaValue, 'additionalProperties')) {
|
|
251
|
+
Object.keys(combinedValue)
|
|
252
|
+
.filter(combinedKey => !Object.keys(schemaValue).includes(combinedKey))
|
|
253
|
+
.forEach(nonMatchingKey => {
|
|
254
|
+
if (schemaValue.additionalProperties === false) {
|
|
255
|
+
delete combinedObject[nonMatchingKey];
|
|
256
|
+
}
|
|
257
|
+
else if (isObject(schemaValue.additionalProperties)) {
|
|
258
|
+
combinedObject[nonMatchingKey] = mergeSchemas(combinedObject[nonMatchingKey], schemaValue.additionalProperties);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
for (const subKey of Object.keys(schemaValue)) {
|
|
263
|
+
if (isEqual(combinedObject[subKey], schemaValue[subKey]) || (!hasOwn(combinedObject, subKey) &&
|
|
264
|
+
!hasOwn(combinedObject, 'additionalProperties'))) {
|
|
265
|
+
combinedObject[subKey] = schemaValue[subKey];
|
|
266
|
+
// If combined schema has additionalProperties,
|
|
267
|
+
// merge or ignore non-matching property keys in new schema
|
|
268
|
+
}
|
|
269
|
+
else if (!hasOwn(combinedObject, subKey) &&
|
|
270
|
+
hasOwn(combinedObject, 'additionalProperties')) {
|
|
271
|
+
// If combinedObject.additionalProperties === false,
|
|
272
|
+
// do nothing (don't set key)
|
|
273
|
+
// If additionalProperties is object, merge with new key
|
|
274
|
+
if (isObject(combinedObject.additionalProperties)) {
|
|
275
|
+
combinedObject[subKey] = mergeSchemas(combinedObject.additionalProperties, schemaValue[subKey]);
|
|
276
|
+
}
|
|
277
|
+
// If both keys are objects, merge them
|
|
278
|
+
}
|
|
279
|
+
else if (isObject(schemaValue[subKey]) &&
|
|
280
|
+
isObject(combinedObject[subKey])) {
|
|
281
|
+
combinedObject[subKey] =
|
|
282
|
+
mergeSchemas(combinedObject[subKey], schemaValue[subKey]);
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
return { allOf: [...schemas] };
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
combinedSchema.properties = combinedObject;
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
return { allOf: [...schemas] };
|
|
292
|
+
}
|
|
293
|
+
break;
|
|
294
|
+
case 'required':
|
|
295
|
+
// If arrays, include all items from both arrays, excluding duplicates
|
|
296
|
+
if (isArray(combinedValue) && isArray(schemaValue)) {
|
|
297
|
+
combinedSchema.required = uniqueItems(...combinedValue, ...schemaValue);
|
|
298
|
+
// If booleans, aet true if either true
|
|
299
|
+
}
|
|
300
|
+
else if (typeof schemaValue === 'boolean' &&
|
|
301
|
+
typeof combinedValue === 'boolean') {
|
|
302
|
+
combinedSchema.required = !!combinedValue || !!schemaValue;
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
return { allOf: [...schemas] };
|
|
306
|
+
}
|
|
307
|
+
break;
|
|
308
|
+
case '$schema':
|
|
309
|
+
case '$id':
|
|
310
|
+
case 'id':
|
|
311
|
+
// Don't combine these keys
|
|
312
|
+
break;
|
|
313
|
+
case 'title':
|
|
314
|
+
case 'description':
|
|
315
|
+
case '$comment':
|
|
316
|
+
// Return the last value, overwriting any previous one
|
|
317
|
+
// These properties are not used for validation, so conflicts don't matter
|
|
318
|
+
combinedSchema[key] = schemaValue;
|
|
319
|
+
break;
|
|
320
|
+
case 'type':
|
|
321
|
+
if ((isArray(schemaValue) || isString(schemaValue)) &&
|
|
322
|
+
(isArray(combinedValue) || isString(combinedValue))) {
|
|
323
|
+
const combinedTypes = commonItems(combinedValue, schemaValue);
|
|
324
|
+
if (!combinedTypes.length) {
|
|
325
|
+
return { allOf: [...schemas] };
|
|
326
|
+
}
|
|
327
|
+
combinedSchema.type = combinedTypes.length > 1 ? combinedTypes : combinedTypes[0];
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
return { allOf: [...schemas] };
|
|
331
|
+
}
|
|
332
|
+
break;
|
|
333
|
+
case 'uniqueItems':
|
|
334
|
+
// Set true if either true
|
|
335
|
+
combinedSchema.uniqueItems = !!combinedValue || !!schemaValue;
|
|
336
|
+
break;
|
|
337
|
+
default:
|
|
338
|
+
return { allOf: [...schemas] };
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return combinedSchema;
|
|
344
|
+
}
|
|
345
345
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVyZ2Utc2NoZW1hcy5mdW5jdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25nLWZvcm13b3Jrcy1jb3JlL3NyYy9saWIvc2hhcmVkL21lcmdlLXNjaGVtYXMuZnVuY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxPQUFPLE1BQU0sZ0JBQWdCLENBQUM7QUFFckMsT0FBTyxFQUNMLE9BQU8sRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQy9DLE1BQU0sdUJBQXVCLENBQUM7QUFDL0IsT0FBTyxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFHdkU7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUJHO0FBQ0gsTUFBTSxVQUFVLFlBQVksQ0FBQyxHQUFHLE9BQU87SUFDckMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JELElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUU7UUFBRSxPQUFPLElBQUksQ0FBQztLQUFFO0lBQy9ELE1BQU0sY0FBYyxHQUFRLEVBQUUsQ0FBQztJQUMvQixLQUFLLE1BQU0sTUFBTSxJQUFJLE9BQU8sRUFBRTtRQUM1QixLQUFLLE1BQU0sR0FBRyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDckMsTUFBTSxhQUFhLEdBQUcsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQzFDLE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNoQyxJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsRUFBRSxHQUFHLENBQUMsSUFB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RyxPQUFPLENBQUUsRUFBRSxDQUFDO3lCQUNsQzt3QkFDSCxNQUFNO29CQUNOLEtBQUssYUFBYTt3QkFDaEIsMEJBQTBCO3dCQUMxQixjQUFjLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQyxhQUFhLElBQUksQ0FBQyxDQUFDLFdBQVcsQ0FBQzt3QkFDaEUsTUFBTTtvQkFDTjt3QkFDRSxPQUFPLEVBQUUsS0FBSyxFQUFFLENBQUUsR0FBRyxPQUFPLENBQUUsRUFBRSxDQUFDO2lCQUNwQzthQUNGO1NBQ0Y7S0FDRjtJQUNELE9BQU8sY0FBYyxDQUFDO0FBQ3hCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgaXNFcXVhbCBmcm9tICdsb2Rhc2gvaXNFcXVhbCc7XHJcblxyXG5pbXBvcnQge1xyXG4gIGlzQXJyYXksIGlzRW1wdHksIGlzTnVtYmVyLCBpc09iamVjdCwgaXNTdHJpbmdcclxufSBmcm9tICcuL3ZhbGlkYXRvci5mdW5jdGlvbnMnO1xyXG5pbXBvcnQgeyBoYXNPd24sIHVuaXF1ZUl0ZW1zLCBjb21tb25JdGVtcyB9IGZyb20gJy4vdXRpbGl0eS5mdW5jdGlvbnMnO1xyXG5pbXBvcnQgeyBKc29uUG9pbnRlciwgUG9pbnRlciB9IGZyb20gJy4vanNvbnBvaW50ZXIuZnVuY3Rpb25zJztcclxuXHJcbi8qKlxyXG4gKiAnbWVyZ2VTY2hlbWFzJyBmdW5jdGlvblxyXG4gKlxyXG4gKiBNZXJnZXMgbXVsdGlwbGUgSlNPTiBzY2hlbWFzIGludG8gYSBzaW5nbGUgc2NoZW1hIHdpdGggY29tYmluZWQgcnVsZXMuXHJcbiAqXHJcbiAqIElmIGFibGUgdG8gbG9naWNhbGx5IG1lcmdlIHByb3BlcnRpZXMgZnJvbSBhbGwgc2NoZW1hcyxcclxuICogcmV0dXJucyBhIHNpbmdsZSBzY2hlbWEgb2JqZWN0IGNvbnRhaW5pbmcgYWxsIG1lcmdlZCBwcm9wZXJ0aWVzLlxyXG4gKlxyXG4gKiBFeGFtcGxlOiAoeyBhOiBiLCBtYXg6IDEgfSwgeyBjOiBkLCBtYXg6IDIgfSkgPT4geyBhOiBiLCBjOiBkLCBtYXg6IDEgfVxyXG4gKlxyXG4gKiBJZiB1bmFibGUgdG8gbG9naWNhbGx5IG1lcmdlLCByZXR1cm5zIGFuIGFsbE9mIHNjaGVtYSBvYmplY3QgY29udGFpbmluZ1xyXG4gKiBhbiBhcnJheSBvZiB0aGUgb3JpZ2luYWwgc2NoZW1hcztcclxuICpcclxuICogRXhhbXBsZTogKHsgYTogYiB9LCB7IGE6IGQgfSkgPT4geyBhbGxPZjogWyB7IGE6IGIgfSwgeyBhOiBkIH0gXSB9XHJcbiAqXHJcbiAqIC8vICAgc2NoZW1hcyAtIG9uZSBvciBtb3JlIGlucHV0IHNjaGVtYXNcclxuICogLy8gIC0gbWVyZ2VkIHNjaGVtYVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIG1lcmdlU2NoZW1hcyguLi5zY2hlbWFzKSB7XHJcbiAgc2NoZW1hcyA9IHNjaGVtYXMuZmlsdGVyKHNjaGVtYSA9PiAhaXNFbXB0eShzY2hlbWEpKTtcclxuICBpZiAoc2NoZW1hcy5zb21lKHNjaGVtYSA9PiAhaXNPYmplY3Qoc2NoZW1hKSkpIHsgcmV0dXJuIG51bGw7IH1cclxuICBjb25zdCBjb21iaW5lZFNjaGVtYTogYW55ID0ge307XHJcbiAgZm9yIChjb25zdCBzY2hlbWEgb2Ygc2NoZW1hcykge1xyXG4gICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoc2NoZW1hKSkge1xyXG4gICAgICBjb25zdCBjb21iaW5lZFZhbHVlID0gY29tYmluZWRTY2hlbWFba2V5XTtcclxuICAgICAgY29uc3Qgc2NoZW1hVmFsdWUgPSBzY2hlbWFba2V5XTtcclxuICAgICAgaWYgKCFoYXNPd24oY29tYmluZWRTY2hlbWEsIGtleSkgfHwgaXNFcXVhbChjb21iaW5lZFZhbHVlLCBzY2hlbWFWYWx1ZSkpIHtcclxuICAgICAgICBjb21iaW5lZFNjaGVtYVtrZXldID0gc2NoZW1hVmFsdWU7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgc3dpdGNoIChrZXkpIHtcclxuICAgICAgICAgIGNhc2UgJ2FsbE9mJzpcclxuICAgICAgICAgICAgLy8gQ29tYmluZSBhbGwgaXRlbXMgZnJvbSBib3RoIGFycmF5c1xyXG4gICAgICAgICAgICBpZiAoaXNBcnJheShjb21iaW5lZFZhbHVlKSAmJiBpc0FycmF5KHNjaGVtYVZhbHVlKSkge1xyXG4gICAgICAgICAgICAgIGNvbWJpbmVkU2NoZW1hLmFsbE9mID0gbWVyZ2VTY2hlbWFzKC4uLmNvbWJpbmVkVmFsdWUsIC4uLnNjaGVtYVZhbHVlKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICByZXR1cm4geyBhbGxPZjogWyAuLi5zY2hlbWFzIF0gfTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICBjYXNlICdhZGRpdGlvbmFsSXRlbXMnOiBjYXNlICdhZGRpdGlvbmFsUHJvcGVydGllcyc6XHJcbiAgICAgICAgICBjYXNlICdjb250YWlucyc6IGNhc2UgJ3Byb3BlcnR5TmFtZXMnOlxyXG4gICAgICAgICAgICAvLyBNZXJnZSBzY2hlbWEgb2JqZWN0c1xyXG4gICAgICAgICAgICBpZiAoaXNPYmplY3QoY29tYmluZWRWYWx1ZSkgJiYgaXNPYmplY3Qoc2NoZW1hVmFsdWUpKSB7XHJcbiAgICAgICAgICAgICAgY29tYmluZWRTY2hlbWFba2V5XSA9IG1lcmdlU2NoZW1hcyhjb21iaW5lZFZhbHVlLCBzY2hlbWFWYWx1ZSk7XHJcbiAgICAgICAgICAgIC8vIGFkZGl0aW9uYWxQcm9wZXJ0aWVzID09IGZhbHNlIGluIGFueSBzY2hlbWEgb3ZlcnJpZGVzIGFsbCBvdGhlciB2YWx1ZXNcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChcclxuICAgICAgICAgICAgICBrZXkgPT09ICdhZGRpdGlvbmFsUHJvcGVydGllcycgJiZcclxuICAgICAgICAgICAgICAoY29tYmluZWRWYWx1ZSA9PT0gZmFsc2UgfHwgc2NoZW1hVmFsdWUgPT09IGZhbHNlKVxyXG4gICAgICAgICAgICApIHtcclxuICAgICAgICAgICAgICBjb21iaW5lZFNjaGVtYS5jb21iaW5lZFNjaGVtYSA9IGZhbHNlO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgIHJldHVybiB7IGFsbE9mOiBbIC4uLnNjaGVtYXMgXSB9O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICAgIGNhc2UgJ2FueU9mJzogY2FzZSAnb25lT2YnOiBjYXNlICdlbnVtJzpcclxuICAgICAgICAgICAgLy8gS2VlcCBvbmx5IGl0ZW1zIHRoYXQgYXBwZWFyIGluIGJvdGggYXJyYXlzXHJcbiAgICAgICAgICAgIGlmIChpc0FycmF5KGNvbWJpbmVkVmFsdWUpICYmIGlzQXJyYXkoc2NoZW1hVmFsdWUpKSB7XHJcbiAgICAgICAgICAgICAgY29tYmluZWRTY2hlbWFba2V5XSA9IGNvbWJpbmVkVmFsdWUuZmlsdGVyKGl0ZW0xID0+XHJcbiAgICAgICAgICAgICAgICBzY2hlbWFWYWx1ZS5maW5kSW5kZXgoaXRlbTIgPT4gaXNFcXVhbChpdGVtMSwgaXRlbTIpKSA+IC0xXHJcbiAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICBpZiAoIWNvbWJpbmVkU2NoZW1hW2tleV0ubGVuZ3RoKSB7IHJldHVybiB7IGFsbE9mOiBbIC4uLnNjaGVtYXMgXSB9OyB9XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgcmV0dXJuIHsgYWxsT2Y6IFsgLi4uc2NoZW1hcyBdIH07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgY2FzZSAnZGVmaW5pdGlvbnMnOlxyXG4gICAgICAgICAgICAvLyBDb21iaW5lIGtleXMgZnJvbSBib3RoIG9iamVjdHNcclxuICAgICAgICAgICAgaWYgKGlzT2JqZWN0KGNvbWJpbmVkVmFsdWUpICYmIGlzT2JqZWN0KHNjaGVtYVZhbHVlKSkge1xyXG4gICAgICAgICAgICAgIGNvbnN0IGNvbWJpbmVkT2JqZWN0ID0geyAuLi5jb21iaW5lZFZhbHVlIH07XHJcbiAgICAgICAgICAgICAgZm9yIChjb25zdCBzdWJLZXkgb2YgT2JqZWN0LmtleXMoc2NoZW1hVmFsdWUpKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoIWhhc093bihjb21iaW5lZE9iamVjdCwgc3ViS2V5KSB8fFxyXG4gICAgICAgICAgICAgICAgICBpc0VxdWFsKGNvbWJpbmVkT2JqZWN0W3N1YktleV0sIHNjaGVtYVZhbHVlW3N1YktleV0pXHJcbiAgICAgICAgICAgICAgICApIHtcclxuICAgICAgICAgICAgICAgICAgY29tYmluZWRPYmplY3Rbc3ViS2V5XSA9IHNjaGVtYVZhbHVlW3N1YktleV07XHJcbiAgICAgICAgICAgICAgICAvLyBEb24ndCBjb21iaW5lIG1hdGNoaW5nIGtleXMgd2l0aCBkaWZmZXJlbnQgdmFsdWVzXHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICByZXR1cm4geyBhbGxPZjogWyAuLi5zY2hlbWFzIF0gfTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgY29tYmluZWRTY2hlbWEuZGVmaW5pdGlvbnMgPSBjb21iaW5lZE9iamVjdDtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICByZXR1cm4geyBhbGxPZjogWyAuLi5zY2hlbWFzIF0gfTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICBjYXNlICdkZXBlbmRlbmNpZXMnOlxyXG4gICAgICAgICAgICAvLyBDb21iaW5lIGFsbCBrZXlzIGZyb20gYm90aCBvYmplY3RzXHJcbiAgICAgICAgICAgIC8vIGFuZCBtZXJnZSBzY2hlbWFzIG9uIG1hdGNoaW5nIGtleXMsXHJcbiAgICAgICAgICAgIC8vIGNvbnZlcnRpbmcgZnJvbSBhcnJheXMgdG8gb2JqZWN0cyBpZiBuZWNlc3NhcnlcclxuICAgICAgICAgICAgaWYgKGlzT2JqZWN0KGNvbWJpbmVkVmFsdWUpICYmIGlzT2JqZWN0KHNjaGVtYVZhbHVlKSkge1xyXG4gICAgICAgICAgICAgIGNvbnN0IGNvbWJpbmVkT2JqZWN0ID0geyAuLi5jb21iaW5lZFZhbHVlIH07XHJcbiAgICAgICAgICAgICAgZm9yIChjb25zdCBzdWJLZXkgb2YgT2JqZWN0LmtleXMoc2NoZW1hVmFsdWUpKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoIWhhc093bihjb21iaW5lZE9iamVjdCwgc3ViS2V5KSB8fFxyXG4gICAgICAgICAgICAgICAgICBpc0VxdWFsKGNvbWJpbmVkT2JqZWN0W3N1YktleV0sIHNjaGVtYVZhbHVlW3N1YktleV0pXHJcbiAgICAgICAgICAgICAgICApIHtcclxuICAgICAgICAgICAgICAgICAgY29tYmluZWRPYmplY3Rbc3ViS2V5XSA9IHNjaGVtYVZhbHVlW3N1YktleV07XHJcbiAgICAgICAgICAgICAgICAvLyBJZiBib3RoIGtleXMgYXJlIGFycmF5cywgaW5jbHVkZSBhbGwgaXRlbXMgZnJvbSBib3RoIGFycmF5cyxcclxuICAgICAgICAgICAgICAgIC8vIGV4Y2x1ZGluZyBkdXBsaWNhdGVzXHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKFxyXG4gICAgICAgICAgICAgICAgICBpc0FycmF5KHNjaGVtYVZhbHVlW3N1YktleV0pICYmIGlzQXJyYXkoY29tYmluZWRPYmplY3Rbc3ViS2V5XSlcclxuICAgICAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgICAgICBjb21iaW5lZE9iamVjdFtzdWJLZXldID1cclxuICAgICAgICAgICAgICAgICAgICB1bmlxdWVJdGVtcyguLi5jb21iaW5lZE9iamVjdFtzdWJLZXldLCAuLi5zY2hlbWFWYWx1ZVtzdWJLZXldKTtcclxuICAgICAgICAgICAgICAgIC8vIElmIGVpdGhlciBrZXkgaXMgYW4gb2JqZWN0LCBtZXJnZSB0aGUgc2NoZW1hc1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChcclxuICAgICAgICAgICAgICAgICAgKGlzQXJyYXkoc2NoZW1hVmFsdWVbc3ViS2V5XSkgfHwgaXNPYmplY3Qoc2NoZW1hVmFsdWVbc3ViS2V5XSkpICYmXHJcbiAgICAgICAgICAgICAgICAgIChpc0FycmF5KGNvbWJpbmVkT2JqZWN0W3N1YktleV0pIHx8IGlzT2JqZWN0KGNvbWJpbmVkT2JqZWN0W3N1YktleV0pKVxyXG4gICAgICAgICAgICAgICAgKSB7XHJcbiAgICAgICAgICAgICAgICAgIC8vIElmIGVpdGhlciBrZXkgaXMgYW4gYXJyYXksIGNvbnZlcnQgaXQgdG8gYW4gb2JqZWN0IGZpcnN0XHJcbiAgICAgICAgICAgICAgICAgIGNvbnN0IHJlcXVpcmVkID0gaXNBcnJheShjb21iaW5lZFNjaGVtYS5yZXF1aXJlZCkgP1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbWJpbmVkU2NoZW1hLnJlcXVpcmVkIDogW107XHJcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbWJpbmVkRGVwZW5kZW5jeSA9IGlzQXJyYXkoY29tYmluZWRPYmplY3Rbc3ViS2V5XSkgP1xyXG4gICAgICAgICAgICAgICAgICAgIHsgcmVxdWlyZWQ6IHVuaXF1ZUl0ZW1zKC4uLnJlcXVpcmVkLCBjb21iaW5lZE9iamVjdFtzdWJLZXldKSB9IDpcclxuICAgICAgICAgICAgICAgICAgICBjb21iaW5lZE9iamVjdFtzdWJLZXldO1xyXG4gICAgICAgICAgICAgICAgICBjb25zdCBzY2hlbWFEZXBlbmRlbmN5ID0gaXNBcnJheShzY2hlbWFWYWx1ZVtzdWJLZXldKSA/XHJcbiAgICAgICAgICAgICAgICAgICAgeyByZXF1aXJlZDogdW5pcXVlSXRlbXMoLi4ucmVxdWlyZWQsIHNjaGVtYVZhbHVlW3N1YktleV0pIH0gOlxyXG4gICAgICAgICAgICAgICAgICAgIHNjaGVtYVZhbHVlW3N1YktleV07XHJcbiAgICAgICAgICAgICAgICAgIGNvbWJpbmVkT2JqZWN0W3N1YktleV0gPVxyXG4gICAgICAgICAgICAgICAgICAgIG1lcmdlU2NoZW1hcyhjb21iaW5lZERlcGVuZGVuY3ksIHNjaGVtYURlcGVuZGVuY3kpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgYWxsT2Y6IFsgLi4uc2NoZW1hcyBdIH07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIGNvbWJpbmVkU2NoZW1hLmRlcGVuZGVuY2llcyA9IGNvbWJpbmVkT2JqZWN0O1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgIHJldHVybiB7IGFsbE9mOiBbIC4uLnNjaGVtYXMgXSB9O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICAgIGNhc2UgJ2l0ZW1zJzpcclxuICAgICAgICAgICAgLy8gSWYgYXJyYXlzLCBrZWVwIG9ubHkgaXRlbXMgdGhhdCBhcHBlYXIgaW4gYm90aCBhcnJheXNcclxuICAgICAgICAgICAgaWYgKGlzQXJyYXkoY29tYmluZWRWYWx1ZSkgJiYgaXNBcnJheShzY2hlbWFWYWx1ZSkpIHtcclxuICAgICAgICAgICAgICBjb21iaW5lZFNjaGVtYS5pdGVtcyA9IGNvbWJpbmVkVmFsdWUuZmlsdGVyKGl0ZW0xID0+XHJcbiAgICAgICAgICAgICAgICBzY2hlbWFWYWx1ZS5maW5kSW5kZXgoaXRlbTIgPT4gaXNFcXVhbChpdGVtMSwgaXRlbTIpKSA+IC0xXHJcbiAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICBpZiAoIWNvbWJpbmVkU2NoZW1hLml0ZW1zLmxlbmd0aCkgeyByZXR1cm4geyBhbGxPZjogWyAuLi5zY2hlbWFzIF0gfTsgfVxyXG4gICAgICAgICAgICAvLyBJZiBib3RoIGtleXMgYXJlIG9iamVjdHMsIG1lcmdlIHRoZW1cclxuICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChjb21iaW5lZFZhbHVlKSAmJiBpc09iamVjdChzY2hlbWFWYWx1ZSkpIHtcclxuICAgICAgICAgICAgICBjb21iaW5lZFNjaGVtYS5pdGVtcyA9IG1lcmdlU2NoZW1hcyhjb21iaW5lZFZhbHVlLCBzY2hlbWFWYWx1ZSk7XHJcbiAgICAgICAgICAgIC8vIElmIG9iamVjdCArIGFycmF5LCBjb21iaW5lIG9iamVjdCB3aXRoIGVhY2ggYXJyYXkgaXRlbVxyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGlzQXJyYXkoY29tYmluZWRWYWx1ZSkgJiYgaXNPYmplY3Qoc2NoZW1hVmFsdWUpKSB7XHJcbiAgICAgICAgICAgICAgY29tYmluZWRTY2hlbWEuaXRlbXMgPVxyXG4gICAgICAgICAgICAgICAgY29tYmluZWRWYWx1ZS5tYXAoaXRlbSA9PiBtZXJnZVNjaGVtYXMoaXRlbSwgc2NoZW1hVmFsdWUpKTtcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChjb21iaW5lZFZhbHVlKSAmJiBpc0FycmF5KHNjaGVtYVZhbHVlKSkge1xyXG4gICAgICAgICAgICAgIGNvbWJpbmVkU2NoZW1hLml0ZW1zID1cclxuICAgICAgICAgICAgICAgIHNjaGVtYVZhbHVlLm1hcChpdGVtID0+IG1lcmdlU2NoZW1hcyhpdGVtLCBjb21iaW5lZFZhbHVlKSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgcmV0dXJuIHsgYWxsT2Y6IFsgLi4uc2NoZW1hcyBdIH07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgY2FzZSAnbXVsdGlwbGVPZic6XHJcbiAgICAgICAgICAgIC8vIFRPRE86IEFkanVzdCB0byBjb3JyZWN0bHkgaGFuZGxlIGRlY2ltYWwgdmFsdWVzXHJcbiAgICAgICAgICAgIC8vIElmIG51bWJlcnMsIHNldCB0byBsZWFzdCBjb21tb24gbXVsdGlwbGVcclxuICAgICAgICAgICAgaWYgKGlzTnVtYmVyKGNvbWJpbmVkVmFsdWUpICYmIGlzTnVtYmVyKHNjaGVtYVZhbHVlKSkge1xyXG4gICAgICAgICAgICAgIGNvbnN0IGdjZCA9ICh4LCB5KSA9PiAheSA/IHggOiBnY2QoeSwgeCAlIHkpO1xyXG4gICAgICAgICAgICAgIGNvbnN0IGxjbSA9ICh4LCB5KSA9PiAoeCAqIHkpIC8gZ2NkKHgsIHkpO1xyXG4gICAgICAgICAgICAgIGNvbWJpbmVkU2NoZW1hLm11bHRpcGxlT2YgPSBsY20oY29tYmluZWRWYWx1ZSwgc2NoZW1hVmFsdWUpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgIHJldHVybiB7IGFsbE9mOiBbIC4uLnNjaGVtYXMgXSB9O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICAgIGNhc2UgJ21heGltdW0nOiBjYXNlICdleGNsdXNpdmVNYXhpbXVtJzogY2FzZSAnbWF4TGVuZ3RoJzpcclxuICAgICAgICAgIGNhc2UgJ21heEl0ZW1zJzogY2FzZSAnbWF4UHJvcGVydGllcyc6XHJcbiAgICAgICAgICAgIC8vIElmIG51bWJlcnMsIHNldCB0byBsb3dlc3QgdmFsdWVcclxuICAgICAgICAgICAgaWYgKGlzTnVtYmVyKGNvbWJpbmVkVmFsdWUpICYmIGlzTnVtYmVyKHNjaGVtYVZhbHVlKSkge1xyXG4gICAgICAgICAgICAgIGNvbWJpbmVkU2NoZW1hW2tleV0gPSBNYXRoLm1pbihjb21iaW5lZFZhbHVlLCBzY2hlbWFWYWx1ZSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgcmV0dXJuIHsgYWxsT2Y6IFsgLi4uc2NoZW1hcyBdIH07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgY2FzZSAnbWluaW11bSc6IGNhc2UgJ2V4Y2x1c2l2ZU1pbmltdW0nOiBjYXNlICdtaW5MZW5ndGgnOlxyXG4gICAgICAgICAgY2FzZSAnbWluSXRlbXMnOiBjYXNlICdtaW5Qcm9wZXJ0aWVzJzpcclxuICAgICAgICAgICAgLy8gSWYgbnVtYmVycywgc2V0IHRvIGhpZ2hlc3QgdmFsdWVcclxuICAgICAgICAgICAgaWYgKGlzTnVtYmVyKGNvbWJpbmVkVmFsdWUpICYmIGlzTnVtYmVyKHNjaGVtYVZhbHVlKSkge1xyXG4gICAgICAgICAgICAgIGNvbWJpbmVkU2NoZW1hW2tleV0gPSBNYXRoLm1heChjb21iaW5lZFZhbHVlLCBzY2hlbWFWYWx1ZSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgcmV0dXJuIHsgYWxsT2Y6IFsgLi4uc2NoZW1hcyBdIH07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgY2FzZSAnbm90JzpcclxuICAgICAgICAgICAgLy8gQ29tYmluZSBub3QgdmFsdWVzIGludG8gYW55T2YgYXJyYXlcclxuICAgICAgICAgICAgaWYgKGlzT2JqZWN0KGNvbWJpbmVkVmFsdWUpICYmIGlzT2JqZWN0KHNjaGVtYVZhbHVlKSkge1xyXG4gICAgICAgICAgICAgIGNvbnN0IG5vdEFueU9mID0gW2NvbWJpbmVkVmFsdWUsIHNjaGVtYVZhbHVlXVxyXG4gICAgICAgICAgICAgICAgLnJlZHVjZSgobm90QW55T2ZBcnJheSwgbm90U2NoZW1hKSA9PlxyXG4gICAgICAgICAgICAgICAgICBpc0FycmF5KG5vdFNjaGVtYS5hbnlPZikgJiZcclxuICAgICAgICAgICAgICAgICAgT2JqZWN0LmtleXMobm90U2NoZW1hKS5sZW5ndGggPT09IDEgP1xyXG4gICAgICAgICAgICAgICAgICAgIFsgLi4ubm90QW55T2ZBcnJheSwgLi4ubm90U2NoZW1hLmFueU9mIF0gOlxyXG4gICAgICAgICAgICAgICAgICAgIFsgLi4ubm90QW55T2ZBcnJheSwgbm90U2NoZW1hIF1cclxuICAgICAgICAgICAgICAgICwgW10pO1xyXG4gICAgICAgICAgICAgIC8vIFRPRE86IFJlbW92ZSBkdXBsaWNhdGUgaXRlbXMgZnJvbSBhcnJheVxyXG4gICAgICAgICAgICAgIGNvbWJpbmVkU2NoZW1hLm5vdCA9IHsgYW55T2Y6IG5vdEFueU9mIH07XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgcmV0dXJuIHsgYWxsT2Y6IFsgLi4uc2NoZW1hcyBdIH07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgY2FzZSAncGF0dGVyblByb3BlcnRpZXMnOlxyXG4gICAgICAgICAgICAvLyBDb21iaW5lIGFsbCBrZXlzIGZyb20gYm90aCBvYmplY3RzXHJcbiAgICAgICAgICAgIC8vIGFuZCBtZXJnZSBzY2hlbWFzIG9uIG1hdGNoaW5nIGtleXNcclxuICAgICAgICAgICAgaWYgKGlzT2JqZWN0KGNvbWJpbmVkVmFsdWUpICYmIGlzT2JqZWN0KHNjaGVtYVZhbHVlKSkge1xyXG4gICAgICAgICAgICAgIGNvbnN0IGNvbWJpbmVkT2JqZWN0ID0geyAuLi5jb21iaW5lZFZhbHVlIH07XHJcbiAgICAgICAgICAgICAgZm9yIChjb25zdCBzdWJLZXkgb2YgT2JqZWN0LmtleXMoc2NoZW1hVmFsdWUpKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoIWhhc093bihjb21iaW5lZE9iamVjdCwgc3ViS2V5KSB8fFxyXG4gICAgICAgICAgICAgICAgICBpc0VxdWFsKGNvbWJpbmVkT2JqZWN0W3N1YktleV0sIHNjaGVtYVZhbHVlW3N1YktleV0pXHJcbiAgICAgICAgICAgICAgICApIHtcclxuICAgICAgICAgICAgICAgICAgY29tYmluZWRPYmplY3Rbc3ViS2V5XSA9IHNjaGVtYVZhbHVlW3N1YktleV07XHJcbiAgICAgICAgICAgICAgICAvLyBJZiBib3RoIGtleXMgYXJlIG9iamVjdHMsIG1lcmdlIHRoZW1cclxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoXHJcbiAgICAgICAgICAgICAgICAgIGlzT2JqZWN0KHNjaGVtYVZhbHVlW3N1YktleV0pICYmIGlzT2JqZWN0KGNvbWJpbmVkT2JqZWN0W3N1YktleV0pXHJcbiAgICAgICAgICAgICAgICApIHtcclxuICAgICAgICAgICAgICAgICAgY29tYmluZWRPYmplY3Rbc3ViS2V5XSA9XHJcbiAgICAgICAgICAgICAgICAgICAgbWVyZ2VTY2hlbWFzKGNvbWJpbmVkT2JqZWN0W3N1YktleV0sIHNjaGVtYVZhbHVlW3N1YktleV0pO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgYWxsT2Y6IFsgLi4uc2NoZW1hcyBdIH07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIGNvbWJpbmVkU2NoZW1hLnBhdHRlcm5Qcm9wZXJ0aWVzID0gY29tYmluZWRPYmplY3Q7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgcmV0dXJuIHsgYWxsT2Y6IFsgLi4uc2NoZW1hcyBdIH07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgY2FzZSAncHJvcGVydGllcyc6XHJcbiAgICAgICAgICAgIC8vIENvbWJpbmUgYWxsIGtleXMgZnJvbSBib3RoIG9iamVjdHNcclxuICAgICAgICAgICAgLy8gdW5sZXNzIGFkZGl0aW9uYWxQcm9wZXJ0aWVzID09PSBmYWxzZVxyXG4gICAgICAgICAgICAvLyBhbmQgbWVyZ2Ugc2NoZW1hcyBvbiBtYXRjaGluZyBrZXlzXHJcbiAgICAgICAgICAgIGlmIChpc09iamVjdChjb21iaW5lZFZhbHVlKSAmJiBpc09iamVjdChzY2hlbWFWYWx1ZSkpIHtcclxuICAgICAgICAgICAgICBjb25zdCBjb21iaW5lZE9iamVjdCA9IHsgLi4uY29tYmluZWRWYWx1ZSB9O1xyXG4gICAgICAgICAgICAgIC8vIElmIG5ldyBzY2hlbWEgaGFzIGFkZGl0aW9uYWxQcm9wZXJ0aWVzLFxyXG4gICAgICAgICAgICAgIC8vIG1lcmdlIG9yIHJlbW92ZSBub24tbWF0Y2hpbmcgcHJvcGVydHkga2V5cyBpbiBjb21iaW5lZCBzY2hlbWFcclxuICAgICAgICAgICAgICBpZiAoaGFzT3duKHNjaGVtYVZhbHVlLCAnYWRkaXRpb25hbFByb3BlcnRpZXMnKSkge1xyXG4gICAgICAgICAgICAgICAgT2JqZWN0LmtleXMoY29tYmluZWRWYWx1ZSlcclxuICAgICAgICAgICAgICAgICAgLmZpbHRlcihjb21iaW5lZEtleSA9PiAhT2JqZWN0LmtleXMoc2NoZW1hVmFsdWUpLmluY2x1ZGVzKGNvbWJpbmVkS2V5KSlcclxuICAgICAgICAgICAgICAgICAgLmZvckVhY2gobm9uTWF0Y2hpbmdLZXkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChzY2hlbWFWYWx1ZS5hZGRpdGlvbmFsUHJvcGVydGllcyA9PT0gZmFsc2UpIHtcclxuICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBjb21iaW5lZE9iamVjdFtub25NYXRjaGluZ0tleV07XHJcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChzY2hlbWFWYWx1ZS5hZGRpdGlvbmFsUHJvcGVydGllcykpIHtcclxuICAgICAgICAgICAgICAgICAgICAgIGNvbWJpbmVkT2JqZWN0W25vbk1hdGNoaW5nS2V5XSA9IG1lcmdlU2NoZW1hcyhcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29tYmluZWRPYmplY3Rbbm9uTWF0Y2hpbmdLZXldLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBzY2hlbWFWYWx1ZS5hZGRpdGlvbmFsUHJvcGVydGllc1xyXG4gICAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICBmb3IgKGNvbnN0IHN1YktleSBvZiBPYmplY3Qua2V5cyhzY2hlbWFWYWx1ZSkpIHtcclxuICAgICAgICAgICAgICAgIGlmIChpc0VxdWFsKGNvbWJpbmVkT2JqZWN0W3N1YktleV0sIHNjaGVtYVZhbHVlW3N1YktleV0pIHx8IChcclxuICAgICAgICAgICAgICAgICAgIWhhc093bihjb21iaW5lZE9iamVjdCwgc3ViS2V5KSAmJlxyXG4gICAgICAgICAgICAgICAgICAhaGFzT3duKGNvbWJpbmVkT2JqZWN0LCAnYWRkaXRpb25hbFByb3BlcnRpZXMnKVxyXG4gICAgICAgICAgICAgICAgKSkge1xyXG4gICAgICAgICAgICAgICAgICBjb21iaW5lZE9iamVjdFtzdWJLZXldID0gc2NoZW1hVmFsdWVbc3ViS2V5XTtcclxuICAgICAgICAgICAgICAgIC8vIElmIGNvbWJpbmVkIHNjaGVtYSBoYXMgYWRkaXRpb25hbFByb3BlcnRpZXMsXHJcbiAgICAgICAgICAgICAgICAvLyBtZXJnZSBvciBpZ25vcmUgbm9uLW1hdGNoaW5nIHByb3BlcnR5IGtleXMgaW4gbmV3IHNjaGVtYVxyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChcclxuICAgICAgICAgICAgICAgICAgIWhhc093bihjb21iaW5lZE9iamVjdCwgc3ViS2V5KSAmJlxyXG4gICAgICAgICAgICAgICAgICBoYXNPd24oY29tYmluZWRPYmplY3QsICdhZGRpdGlvbmFsUHJvcGVydGllcycpXHJcbiAgICAgICAgICAgICAgICApIHtcclxuICAgICAgICAgICAgICAgICAgLy8gSWYgY29tYmluZWRPYmplY3QuYWRkaXRpb25hbFByb3BlcnRpZXMgPT09IGZhbHNlLFxyXG4gICAgICAgICAgICAgICAgICAvLyBkbyBub3RoaW5nIChkb24ndCBzZXQga2V5KVxyXG4gICAgICAgICAgICAgICAgICAvLyBJZiBhZGRpdGlvbmFsUHJvcGVydGllcyBpcyBvYmplY3QsIG1lcmdlIHdpdGggbmV3IGtleVxyXG4gICAgICAgICAgICAgICAgICBpZiAoaXNPYmplY3QoY29tYmluZWRPYmplY3QuYWRkaXRpb25hbFByb3BlcnRpZXMpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29tYmluZWRPYmplY3Rbc3ViS2V5XSA9IG1lcmdlU2NoZW1hcyhcclxuICAgICAgICAgICAgICAgICAgICAgIGNvbWJpbmVkT2JqZWN0LmFkZGl0aW9uYWxQcm9wZXJ0aWVzLCBzY2hlbWFWYWx1ZVtzdWJLZXldXHJcbiAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgLy8gSWYgYm90aCBrZXlzIGFyZSBvYmplY3RzLCBtZXJnZSB0aGVtXHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKFxyXG4gICAgICAgICAgICAgICAgICBpc09iamVjdChzY2hlbWFWYWx1ZVtzdWJLZXldKSAmJlxyXG4gICAgICAgICAgICAgICAgICBpc09iamVjdChjb21iaW5lZE9iamVjdFtzdWJLZXldKVxyXG4gICAgICAgICAgICAgICAgKSB7XHJcbiAgICAgICAgICAgICAgICAgIGNvbWJpbmVkT2JqZWN0W3N1YktleV0gPVxyXG4gICAgICAgICAgICAgICAgICAgIG1lcmdlU2NoZW1hcyhjb21iaW5lZE9iamVjdFtzdWJLZXldLCBzY2hlbWFWYWx1ZVtzdWJLZXldKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgIHJldHVybiB7IGFsbE9mOiBbIC4uLnNjaGVtYXMgXSB9O1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICBjb21iaW5lZFNjaGVtYS5wcm9wZXJ0aWVzID0gY29tYmluZWRPYmplY3Q7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgcmV0dXJuIHsgYWxsT2Y6IFsgLi4uc2NoZW1hcyBdIH07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgY2FzZSAncmVxdWlyZWQnOlxyXG4gICAgICAgICAgICAvLyBJZiBhcnJheXMsIGluY2x1ZGUgYWxsIGl0ZW1zIGZyb20gYm90aCBhcnJheXMsIGV4Y2x1ZGluZyBkdXBsaWNhdGVzXHJcbiAgICAgICAgICAgIGlmIChpc0FycmF5KGNvbWJpbmVkVmFsdWUpICYmIGlzQXJyYXkoc2NoZW1hVmFsdWUpKSB7XHJcbiAgICAgICAgICAgICAgY29tYmluZWRTY2hlbWEucmVxdWlyZWQgPSB1bmlxdWVJdGVtcyguLi5jb21iaW5lZFZhbHVlLCAuLi5zY2hlbWFWYWx1ZSk7XHJcbiAgICAgICAgICAgIC8vIElmIGJvb2xlYW5zLCBhZXQgdHJ1ZSBpZiBlaXRoZXIgdHJ1ZVxyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKFxyXG4gICAgICAgICAgICAgIHR5cGVvZiBzY2hlbWFWYWx1ZSA9PT0gJ2Jvb2xlYW4nICYmXHJcbiAgICAgICAgICAgICAgdHlwZW9mIGNvbWJpbmVkVmFsdWUgPT09ICdib29sZWFuJ1xyXG4gICAgICAgICAgICApIHtcclxuICAgICAgICAgICAgICBjb21iaW5lZFNjaGVtYS5yZXF1aXJlZCA9ICEhY29tYmluZWRWYWx1ZSB8fCAhIXNjaGVtYVZhbHVlO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgIHJldHVybiB7IGFsbE9mOiBbIC4uLnNjaGVtYXMgXSB9O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICAgIGNhc2UgJyRzY2hlbWEnOiBjYXNlICckaWQnOiBjYXNlICdpZCc6XHJcbiAgICAgICAgICAgIC8vIERvbid0IGNvbWJpbmUgdGhlc2Uga2V5c1xyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICBjYXNlICd0aXRsZSc6IGNhc2UgJ2Rlc2NyaXB0aW9uJzogY2FzZSAnJGNvbW1lbnQnOlxyXG4gICAgICAgICAgICAvLyBSZXR1cm4gdGhlIGxhc3QgdmFsdWUsIG92ZXJ3cml0aW5nIGFueSBwcmV2aW91cyBvbmVcclxuICAgICAgICAgICAgLy8gVGhlc2UgcHJvcGVydGllcyBhcmUgbm90IHVzZWQgZm9yIHZhbGlkYXRpb24sIHNvIGNvbmZsaWN0cyBkb24ndCBtYXR0ZXJcclxuICAgICAgICAgICAgY29tYmluZWRTY2hlbWFba2V5XSA9IHNjaGVtYVZhbHVlO1xyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICBjYXNlICd0eXBlJzpcclxuICAgICAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICAgIChpc0FycmF5KHNjaGVtYVZhbHVlKSB8fCBpc1N0cmluZyhzY2hlbWFWYWx1ZSkpICYmXHJcbiAgICAgICAgICAgICAgKGlzQXJyYXkoY29tYmluZWRWYWx1ZSkgfHwgaXNTdHJpbmcoY29tYmluZWRWYWx1ZSkpXHJcbiAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgIGNvbnN0IGNvbWJpbmVkVHlwZXMgPSBjb21tb25JdGVtcyhjb21iaW5lZFZhbHVlLCBzY2hlbWFWYWx1ZSk7XHJcbiAgICAgICAgICAgICAgaWYgKCFjb21iaW5lZFR5cGVzLmxlbmd0aCkgeyByZXR1cm4geyBhbGxPZjogWyAuLi5zY2hlbWFzIF0gfTsgfVxyXG4gICAgICAgICAgICAgIGNvbWJpbmVkU2NoZW1hLnR5cGUgPSBjb21iaW5lZFR5cGVzLmxlbmd0aCA+IDEgPyBjb21iaW5lZFR5cGVzIDogY29tYmluZWRUeXBlc1swXTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICByZXR1cm4geyBhbGxPZjogWyAuLi5zY2hlbWFzIF0gfTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICBjYXNlICd1bmlxdWVJdGVtcyc6XHJcbiAgICAgICAgICAgIC8vIFNldCB0cnVlIGlmIGVpdGhlciB0cnVlXHJcbiAgICAgICAgICAgIGNvbWJpbmVkU2NoZW1hLnVuaXF1ZUl0ZW1zID0gISFjb21iaW5lZFZhbHVlIHx8ICEhc2NoZW1hVmFsdWU7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgIHJldHVybiB7IGFsbE9mOiBbIC4uLnNjaGVtYXMgXSB9O1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuICByZXR1cm4gY29tYmluZWRTY2hlbWE7XHJcbn1cclxuIl19
|