payload-auth 1.4.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. package/dist/better-auth/adapter/index.d.ts +10 -0
  2. package/dist/better-auth/adapter/index.d.ts.map +1 -1
  3. package/dist/better-auth/adapter/index.js +151 -125
  4. package/dist/better-auth/adapter/transform/index.d.ts +2 -4
  5. package/dist/better-auth/adapter/transform/index.d.ts.map +1 -1
  6. package/dist/better-auth/adapter/transform/index.js +433 -309
  7. package/dist/better-auth/plugin/constants.d.ts +1 -0
  8. package/dist/better-auth/plugin/constants.d.ts.map +1 -1
  9. package/dist/better-auth/plugin/constants.js +2 -1
  10. package/dist/better-auth/plugin/helpers/prepare-session-data.d.ts +52 -6
  11. package/dist/better-auth/plugin/helpers/prepare-session-data.d.ts.map +1 -1
  12. package/dist/better-auth/plugin/helpers/prepare-session-data.js +52 -35
  13. package/dist/better-auth/plugin/lib/build-collections/sessions.d.ts.map +1 -1
  14. package/dist/better-auth/plugin/lib/build-collections/sessions.js +3 -1
  15. package/dist/better-auth/plugin/lib/build-collections/users/better-auth-strategy.d.ts.map +1 -1
  16. package/dist/better-auth/plugin/lib/build-collections/users/better-auth-strategy.js +2 -2
  17. package/dist/better-auth/plugin/lib/build-collections/users/hooks/after-login.d.ts.map +1 -1
  18. package/dist/better-auth/plugin/lib/build-collections/users/hooks/after-login.js +6 -4
  19. package/dist/better-auth/plugin/lib/sanitize-better-auth-options/utils/save-to-jwt-middleware.d.ts +1 -1
  20. package/dist/better-auth/plugin/lib/sanitize-better-auth-options/utils/save-to-jwt-middleware.d.ts.map +1 -1
  21. package/dist/better-auth/plugin/lib/sanitize-better-auth-options/utils/save-to-jwt-middleware.js +16 -14
  22. package/package.json +9 -4
@@ -1,4 +1,3 @@
1
- import { BetterAuthError } from "better-auth";
2
1
  import { getAuthTables } from "better-auth/db";
3
2
  export const createTransform = (options, enableDebugLogs)=>{
4
3
  const schema = getAuthTables(options);
@@ -7,19 +6,82 @@ export const createTransform = (options, enableDebugLogs)=>{
7
6
  console.log(`[payload-db-adapter]`, ...message);
8
7
  }
9
8
  }
10
- function getModelName(model) {
9
+ /**
10
+ * Maps a BetterAuth schema model name to its corresponding Payload CMS collection slug.
11
+ *
12
+ * This function resolves the appropriate collection slug by:
13
+ * 1. Looking up the model in the BetterAuth schema to find its configured modelName
14
+ * 2. Falling back to the original model name if no mapping exists
15
+ *
16
+ * Collection slug resolution follows these rules:
17
+ * - For base collections: The sanitizeBetterAuthOptions function ensures the collection slug
18
+ * from plugin options is set as the model name in the schema
19
+ * - For plugins: The betterAuthPluginSlugs constant is used as the modelName
20
+ *
21
+ * @param model - The BetterAuth model name to resolve
22
+ * @returns The corresponding Payload CMS collection slug
23
+ *
24
+ * @example
25
+ * // If schema['user'].modelName is 'users'
26
+ * getCollectionSlug('user') // Returns 'users'
27
+ *
28
+ * @example
29
+ * // If model doesn't exist in schema
30
+ * getCollectionSlug('custom') // Returns 'custom'
31
+ *
32
+ * @warning If a collection is overridden using the collectionOverride option
33
+ * without updating the schema mapping, this function may return incorrect slugs
34
+ */ function getCollectionSlug(model) {
35
+ // First try to get the modelName from schema, otherwise fall back to the original model name
11
36
  const collection = schema[model]?.modelName || model;
12
- if (!collection) {
13
- throw new BetterAuthError(`Model ${model} does not exist in the database.`);
14
- }
37
+ debugLog([
38
+ 'getCollectionSlug:',
39
+ {
40
+ model,
41
+ resolvedSlug: collection
42
+ }
43
+ ]);
15
44
  return collection;
16
45
  }
17
- function getFieldName(model, field) {
18
- if (field === 'id') {
46
+ /**
47
+ * Maps a BetterAuth schema field to its corresponding Payload CMS field name.
48
+ *
49
+ * This function resolves the appropriate field name by:
50
+ * 1. Preserving 'id' or '_id' fields as-is (special case handling)
51
+ * 2. Looking up the field in the BetterAuth schema to find its configured fieldName
52
+ * 3. Falling back to the original field name if no mapping exists
53
+ *
54
+ * @param model - The BetterAuth model name containing the field
55
+ * @param field - The original field name to resolve
56
+ * @returns The corresponding Payload CMS field name
57
+ *
58
+ * @example
59
+ * // If schema['user'].fields['email'].fieldName is 'emailAddress'
60
+ * getFieldName('user', 'email') // Returns 'emailAddress'
61
+ *
62
+ * @example
63
+ * // Special case for ID fields
64
+ * getFieldName('user', 'id') // Always returns 'id'
65
+ *
66
+ * @example
67
+ * // If field doesn't exist in schema or has no fieldName mapping
68
+ * getFieldName('user', 'custom') // Returns 'custom'
69
+ *
70
+ * @warning If a fieldName is overridden in the payload collection config using the collectionOverride option
71
+ * without updating the schema mapping, this function may return incorrect field names
72
+ */ function getFieldName(model, field) {
73
+ // Special case: 'id' or '_id' is always preserved as-is
74
+ if ([
75
+ 'id',
76
+ '_id'
77
+ ].includes(field)) {
19
78
  return field;
20
79
  }
21
- const f = schema[model]?.fields[field];
22
- const fieldName = f?.fieldName || field;
80
+ // Look up the field in the schema
81
+ const fieldDefinition = schema[model]?.fields[field];
82
+ // Use the configured fieldName if available, otherwise fall back to original
83
+ const fieldName = fieldDefinition?.fieldName || field;
84
+ // Log the field resolution for debugging
23
85
  debugLog([
24
86
  'getField: ',
25
87
  {
@@ -30,372 +92,350 @@ export const createTransform = (options, enableDebugLogs)=>{
30
92
  ]);
31
93
  return fieldName;
32
94
  }
33
- function isRelationshipField(fieldKey) {
34
- return fieldKey.endsWith('Id') || fieldKey.endsWith('By');
95
+ /**
96
+ * Determines if a field is a relationship field by checking for a references property.
97
+ *
98
+ * Relationship fields in the schema have a 'references' property that points to another model.
99
+ * This function checks if this property exists to identify relationship fields.
100
+ *
101
+ * @param fieldKey - The key of the field to check in the schema
102
+ * @param schemaFields - Object containing all fields from the schema for a specific model
103
+ * @returns True if the field is a relationship field (has references), false otherwise
104
+ *
105
+ * @example
106
+ * // If schema.user.fields.posts has { references: {} }
107
+ * isRelationshipField('posts', schema.user.fields) // Returns true
108
+ *
109
+ * @example
110
+ * // If schema.user.fields.email has no references property
111
+ * isRelationshipField('email', schema.user.fields) // Returns false
112
+ */ function isRelationshipField(fieldKey, schemaFields) {
113
+ // A field is a relationship field if it has a 'references' property defined
114
+ return schemaFields[fieldKey]?.references !== undefined;
35
115
  }
36
- function isDateField({ key, value }) {
37
- if (key) {
38
- return (key.endsWith('At') || key.endsWith('Date') || key === 'date') && typeof value === 'string' && !isNaN(Date.parse(value));
39
- } else {
40
- return typeof value === 'string' && !isNaN(Date.parse(value));
41
- }
116
+ /**
117
+ * Determines if a value is a valid date string that can be parsed into a Date object.
118
+ *
119
+ * This utility function checks if a value is a string and can be successfully parsed
120
+ * into a JavaScript Date object using Date.parse(). It's used to identify date fields
121
+ * during data transformation processes.
122
+ *
123
+ * @param value - The value to check if it's a valid date string
124
+ * @returns True if the value is a string that can be parsed as a date, false otherwise
125
+ *
126
+ * @example
127
+ * // Returns true for ISO date strings
128
+ * isDateField('2023-01-01T12:00:00Z') // true
129
+ *
130
+ * @example
131
+ * // Returns false for non-date strings or other types
132
+ * isDateField('not a date') // false
133
+ * isDateField(123) // false
134
+ */ function isDateField(value) {
135
+ // Check if value is a string and can be parsed as a valid date
136
+ return typeof value === 'string' && !isNaN(Date.parse(value));
42
137
  }
43
- function singleIdQuery(where) {
138
+ /**
139
+ * Extracts a single ID value from a Payload where clause if it represents a simple ID query.
140
+ *
141
+ * This function analyzes a Payload where clause to determine if it's a simple query for a
142
+ * single document by ID. It supports both 'id' and '_id' fields with 'equals' or 'contains'
143
+ * operators. This is useful for optimizing queries when we only need to fetch a single document.
144
+ *
145
+ * @param where - The Payload where clause to analyze
146
+ * @returns The ID value (string or number) if the where clause is a simple ID query, null otherwise
147
+ *
148
+ * @example
149
+ * // Returns '123' for a simple equals query
150
+ * singleIdQuery({ id: { equals: '123' } }) // '123'
151
+ *
152
+ * @example
153
+ * // Returns 456 for a simple equals query with number ID
154
+ * singleIdQuery({ _id: { equals: 456 } }) // 456
155
+ *
156
+ * @example
157
+ * // Returns '789' for a contains query with a single value
158
+ * singleIdQuery({ id: { contains: ['789'] } }) // '789'
159
+ *
160
+ * @example
161
+ * // Returns null for complex queries
162
+ * singleIdQuery({ and: [{ id: { equals: '123' } }] }) // null
163
+ */ function singleIdQuery(where) {
164
+ // Return null for empty where clauses or complex queries with 'and'/'or' operators
44
165
  if (!where || 'and' in where || 'or' in where) return null;
45
- // For a single id query like { id: { equals: 15 } }
46
- // First, check if there's an id field in the where clause
47
- if ('id' in where || '_id' in where) {
166
+ // Check if the where clause contains either 'id' or '_id' field
167
+ if ([
168
+ 'id',
169
+ '_id'
170
+ ].some((field)=>field in where)) {
171
+ // Determine which ID field is being used (support both 'id' and '_id')
48
172
  const idField = 'id' in where ? 'id' : '_id';
49
173
  const condition = where[idField];
50
- // Check if condition is an object with equals operator
174
+ // Process the equals operator case
51
175
  if (condition && typeof condition === 'object' && !Array.isArray(condition) && 'equals' in condition) {
52
176
  const value = condition.equals;
177
+ // Only return string or number ID values
53
178
  if (typeof value === 'string' || typeof value === 'number') {
54
179
  return value;
55
180
  }
56
181
  }
57
- // Check for contains operator with single value
182
+ // Process the contains operator case with a single value
58
183
  if (condition && typeof condition === 'object' && !Array.isArray(condition) && 'contains' in condition && Array.isArray(condition.contains) && condition.contains.length === 1) {
59
184
  const value = condition.contains[0];
185
+ // Only return string or number ID values
60
186
  if (typeof value === 'string' || typeof value === 'number') {
61
187
  return value;
62
188
  }
63
189
  }
64
190
  }
191
+ // Return null if no valid ID query was found
65
192
  return null;
66
193
  }
67
- function multipleIdsQuery(where) {
68
- if (!where || 'and' in where || 'or' in where) return null;
69
- if ('id' in where || '_id' in where) {
70
- const idField = 'id' in where ? 'id' : '_id';
71
- const condition = where[idField];
72
- // Check if this is an 'in' operator with id field and array of values
73
- if (condition && typeof condition === 'object' && !Array.isArray(condition) && 'in' in condition && Array.isArray(condition.in) && condition.in.length > 1 && condition.in.every((id)=>typeof id === 'string' || typeof id === 'number')) {
74
- return condition.in;
75
- }
76
- // Also check for contains operator with array of IDs
77
- if (condition && typeof condition === 'object' && !Array.isArray(condition) && 'contains' in condition && Array.isArray(condition.contains) && condition.contains.length > 1 && condition.contains.every((id)=>typeof id === 'string' || typeof id === 'number')) {
78
- return condition.contains;
79
- }
80
- }
81
- return null;
82
- }
83
- function normalizeData({ fieldKey, incomingValue, schemaFields, relationshipField, idType }) {
84
- // Early return for null/undefined values
85
- if (incomingValue === null || incomingValue === undefined) {
86
- return incomingValue;
87
- }
88
- //special case for accountId field in accounts collection
89
- if (fieldKey === 'accountId') {
90
- return String(incomingValue);
194
+ /**
195
+ * Normalizes data values based on field type and required ID type
196
+ *
197
+ * This function handles type conversion for relationship fields to ensure
198
+ * IDs are in the correct format (string or number) based on the configuration.
199
+ *
200
+ * @param key - The field key/name
201
+ * @param value - The value to normalize
202
+ * @param isRelatedField - Whether this field is a relationship field
203
+ * @param idType - The expected ID type ('number' or 'text')
204
+ * @returns The normalized value
205
+ */ function normalizeData({ key, value, isRelatedField, idType }) {
206
+ // Skip processing for null/undefined values
207
+ if (value === null || value === undefined) {
208
+ return value;
91
209
  }
92
- // Handle relationship fields (IDs) based on idType
93
- if (relationshipField) {
94
- if (idType === 'number' && typeof incomingValue === 'string') {
95
- const parsed = parseInt(incomingValue, 10);
210
+ if ([
211
+ 'id',
212
+ '_id'
213
+ ].includes(key)) {
214
+ if (typeof value === 'string' && idType === 'number') {
215
+ const parsed = parseInt(value, 10);
96
216
  if (!isNaN(parsed)) {
97
217
  debugLog([
98
- `ID conversion: ${fieldKey} converting string ID to number`,
218
+ `ID conversion: ${key} converting string ID to number`,
99
219
  {
100
- original: incomingValue,
220
+ original: value,
101
221
  converted: parsed
102
222
  }
103
223
  ]);
104
224
  return parsed;
105
225
  }
106
- } else if (idType === 'text' && typeof incomingValue === 'number') {
107
- const stringId = String(incomingValue);
226
+ }
227
+ if (typeof value === 'number' && idType === 'text') {
228
+ const stringId = String(value);
108
229
  debugLog([
109
- `ID conversion: ${fieldKey} converting number ID to string`,
230
+ `ID conversion: ${key} converting number ID to string`,
110
231
  {
111
- original: incomingValue,
232
+ original: value,
112
233
  converted: stringId
113
234
  }
114
235
  ]);
115
236
  return stringId;
116
237
  }
117
- // Handle array of IDs
118
- if (Array.isArray(incomingValue)) {
119
- return incomingValue.map((id)=>{
120
- if (idType === 'number' && typeof id === 'string') {
121
- const parsed = parseInt(id, 10);
122
- return !isNaN(parsed) ? parsed : id;
123
- } else if (idType === 'text' && typeof id === 'number') {
124
- return String(id);
125
- }
126
- return id;
127
- });
128
- }
129
- return incomingValue;
130
238
  }
131
- const schemaField = schemaFields[fieldKey];
132
- // If no schema field exists, return as is
133
- if (!schemaField) {
134
- return incomingValue;
135
- }
136
- const fieldType = schemaField.type;
137
- // Handle string type
138
- if (fieldType === 'string') {
139
- if (typeof incomingValue !== 'string') {
140
- if (incomingValue instanceof Date) {
141
- const converted = incomingValue.toISOString();
142
- debugLog([
143
- `Type conversion: ${fieldKey} expected string but got Date`,
144
- {
145
- original: incomingValue,
146
- converted
147
- }
148
- ]);
149
- return converted;
150
- }
151
- const converted = String(incomingValue);
152
- debugLog([
153
- `Type conversion: ${fieldKey} expected string but got ${typeof incomingValue}`,
154
- {
155
- original: incomingValue,
156
- converted
157
- }
158
- ]);
159
- return converted;
160
- }
161
- return incomingValue;
162
- }
163
- // Handle number type
164
- if (fieldType === 'number') {
165
- if (typeof incomingValue !== 'number') {
166
- if (incomingValue instanceof Date) {
167
- const converted = incomingValue.getTime();
168
- debugLog([
169
- `Type conversion: ${fieldKey} expected number but got Date`,
170
- {
171
- original: incomingValue,
172
- converted
173
- }
174
- ]);
175
- return converted;
176
- }
177
- if (typeof incomingValue === 'boolean') {
178
- const converted = incomingValue ? 1 : 0;
239
+ // Only process relationship fields that need type conversion
240
+ if (isRelatedField) {
241
+ // Handle single ID value conversion
242
+ if (typeof value === 'string' && idType === 'number') {
243
+ const parsed = parseInt(value, 10);
244
+ if (!isNaN(parsed)) {
179
245
  debugLog([
180
- `Type conversion: ${fieldKey} expected number but got boolean`,
246
+ `ID conversion: ${key} converting string ID to number`,
181
247
  {
182
- original: incomingValue,
183
- converted
248
+ original: value,
249
+ converted: parsed
184
250
  }
185
251
  ]);
186
- return converted;
187
- }
188
- if (typeof incomingValue === 'string') {
189
- const parsed = parseFloat(incomingValue);
190
- if (!isNaN(parsed)) {
191
- debugLog([
192
- `Type conversion: ${fieldKey} expected number but got string`,
193
- {
194
- original: incomingValue,
195
- converted: parsed
196
- }
197
- ]);
198
- return parsed;
199
- }
200
- }
201
- }
202
- return incomingValue;
203
- }
204
- // Handle boolean type
205
- if (fieldType === 'boolean') {
206
- if (typeof incomingValue !== 'boolean') {
207
- let converted;
208
- if (typeof incomingValue === 'string') {
209
- converted = incomingValue.toLowerCase() === 'true' || incomingValue === '1';
210
- } else if (typeof incomingValue === 'number') {
211
- converted = incomingValue !== 0;
212
- } else {
213
- converted = !!incomingValue;
252
+ return parsed;
214
253
  }
254
+ } else if (typeof value === 'number' && idType === 'text') {
255
+ const stringId = String(value);
215
256
  debugLog([
216
- `Type conversion: ${fieldKey} expected boolean but got ${typeof incomingValue}`,
257
+ `ID conversion: ${key} converting number ID to string`,
217
258
  {
218
- original: incomingValue,
219
- converted
259
+ original: value,
260
+ converted: stringId
220
261
  }
221
262
  ]);
222
- return converted;
263
+ return stringId;
223
264
  }
224
- return incomingValue;
225
- }
226
- // Handle date type
227
- if (fieldType === 'date') {
228
- if (!(incomingValue instanceof Date)) {
229
- let converted;
230
- if (typeof incomingValue === 'string' || typeof incomingValue === 'number') {
231
- converted = new Date(incomingValue);
232
- if (!isNaN(converted.getTime())) {
233
- debugLog([
234
- `Type conversion: ${fieldKey} expected Date but got ${typeof incomingValue}`,
235
- {
236
- original: incomingValue,
237
- converted
238
- }
239
- ]);
240
- return converted;
265
+ // Handle array of IDs - map each value to the correct type
266
+ if (Array.isArray(value)) {
267
+ return value.map((id)=>{
268
+ // Skip null/undefined values in arrays
269
+ if (id === null || id === undefined) return id;
270
+ if (idType === 'number' && typeof id === 'string') {
271
+ const parsed = parseInt(id, 10);
272
+ return !isNaN(parsed) ? parsed : id;
273
+ } else if (idType === 'text' && typeof id === 'number') {
274
+ return String(id);
241
275
  }
242
- }
276
+ return id;
277
+ });
243
278
  }
244
- return incomingValue;
245
279
  }
246
- // Handle array types (string[] or number[] or LiteralString[])
247
- if (typeof fieldType === 'string' && fieldType.endsWith('[]')) {
248
- const baseType = fieldType.slice(0, -2);
249
- // Convert to array if not already
250
- let arrayValue = incomingValue;
251
- if (!Array.isArray(incomingValue)) {
252
- if (typeof incomingValue === 'string') {
253
- try {
254
- // Try to parse as JSON array
255
- const parsed = JSON.parse(incomingValue);
256
- if (Array.isArray(parsed)) {
257
- debugLog([
258
- `Type conversion: ${fieldKey} parsed JSON string to array`,
259
- {
260
- original: incomingValue,
261
- converted: parsed
262
- }
263
- ]);
264
- arrayValue = parsed;
265
- } else {
266
- arrayValue = [
267
- incomingValue
268
- ];
269
- }
270
- } catch (e) {
271
- // If parsing fails, wrap in array
272
- arrayValue = [
273
- incomingValue
274
- ];
275
- }
276
- } else {
277
- // Wrap non-array values in array
278
- arrayValue = [
279
- incomingValue
280
- ];
281
- }
282
- debugLog([
283
- `Type conversion: ${fieldKey} converted to array`,
284
- {
285
- original: incomingValue,
286
- converted: arrayValue
287
- }
288
- ]);
289
- }
290
- // Normalize each array element based on the base type
291
- return arrayValue.map((item, index)=>{
292
- if (baseType === 'string' && typeof item !== 'string') {
293
- const converted = String(item);
294
- debugLog([
295
- `Type conversion: ${fieldKey}[${index}] expected string but got ${typeof item}`,
296
- {
297
- original: item,
298
- converted
299
- }
300
- ]);
301
- return converted;
302
- }
303
- if (baseType === 'number' && typeof item !== 'number') {
304
- if (typeof item === 'string') {
305
- const parsed = parseFloat(item);
306
- if (!isNaN(parsed)) {
307
- debugLog([
308
- `Type conversion: ${fieldKey}[${index}] expected number but got string`,
309
- {
310
- original: item,
311
- converted: parsed
312
- }
313
- ]);
314
- return parsed;
315
- }
316
- } else if (typeof item === 'boolean') {
317
- return item ? 1 : 0;
318
- }
319
- }
320
- return item;
321
- });
322
- }
323
- // For any other types or if no conversion needed, return as is
324
- return incomingValue;
280
+ // Return original value if no conversion was needed or applicable
281
+ return value;
325
282
  }
326
- function transformInput({ data, model, idType, action }) {
283
+ /**
284
+ * Transforms input data from better-auth to Payload CMS format
285
+ *
286
+ * This function handles:
287
+ * 1. Field name mapping according to schema definitions
288
+ * 2. ID type conversion for relationship fields
289
+ * 3. Proper data normalization based on field types
290
+ *
291
+ * @param data - The input data from better-auth
292
+ * @param model - The model name in the schema
293
+ * @param idType - The expected ID type ('number' or 'text')
294
+ * @returns Transformed data compatible with Payload CMS
295
+ */ function transformInput({ data, model, idType }) {
327
296
  const transformedData = {};
328
297
  const schemaFields = schema[model].fields;
329
- for(const fieldKey in data){
330
- if (data[fieldKey] === undefined && action === 'update') {
331
- continue;
298
+ // Process each field in the input data
299
+ Object.entries(data).forEach(([key, value])=>{
300
+ // Skip null/undefined values
301
+ if (value === null || value === undefined) {
302
+ return;
332
303
  }
333
- const relationshipField = isRelationshipField(fieldKey);
334
- const schemaFieldName = schemaFields[fieldKey]?.fieldName;
304
+ // Determine if this is a relationship field
305
+ const isRelatedField = isRelationshipField(key, schemaFields);
306
+ // Get the mapped field name from schema (if any)
307
+ const schemaFieldName = schemaFields[key]?.fieldName;
308
+ // Normalize the data value based on field type and ID type
335
309
  const normalizedData = normalizeData({
336
310
  idType,
337
- fieldKey,
338
- incomingValue: data[fieldKey],
339
- schemaFields,
340
- relationshipField
311
+ key,
312
+ value,
313
+ isRelatedField
341
314
  });
342
- if (schemaFieldName) {
343
- transformedData[schemaFieldName] = normalizedData;
344
- } else {
345
- transformedData[fieldKey] = normalizedData;
346
- }
347
- }
315
+ // Use the schema-defined field name if available, otherwise use original key
316
+ const targetFieldName = schemaFieldName || key;
317
+ transformedData[targetFieldName] = normalizedData;
318
+ });
348
319
  return transformedData;
349
320
  }
350
- function transformOutput({ doc, model }) {
351
- if (doc === null || doc === undefined || typeof doc !== 'object') return doc;
321
+ /**
322
+ * Transforms Payload CMS document output to match BetterAuth schema expectations.
323
+ *
324
+ * This function handles several critical transformations:
325
+ *
326
+ * 1. ID Conversion: Ensures all ID fields are strings as required by BetterAuth
327
+ * (see: https://github.com/better-auth/better-auth/blob/main/packages/better-auth/src/db/schema.ts#L125)
328
+ *
329
+ * 2. Relationship Field Mapping: Aligns relationship fields with BetterAuth schema naming conventions
330
+ * and ensures proper ID type handling
331
+ *
332
+ * 3. Date Conversion: Transforms date strings from Payload into Date objects for BetterAuth
333
+ *
334
+ * Note: While setting depth: 1 in Payload operations simplifies this process by avoiding
335
+ * deeply nested objects, we maintain comprehensive checks for robustness.
336
+ *
337
+ * @param doc - The document returned from Payload CMS
338
+ * @param model - The model name in the BetterAuth schema
339
+ * @returns The transformed document compatible with BetterAuth
340
+ */ function transformOutput({ doc, model }) {
341
+ if (!doc || typeof doc !== 'object') return doc;
352
342
  const result = {
353
343
  ...doc
354
344
  };
355
345
  const schemaFields = schema[model].fields;
356
- const relationshipFields = Object.entries(schemaFields).filter(([key])=>isRelationshipField(key)).reduce((acc, [key, value])=>({
357
- ...acc,
358
- [key]: value
359
- }), {});
346
+ // Identify relationship fields with custom field name mappings
347
+ const relationshipFields = Object.fromEntries(Object.entries(schemaFields).filter(([key])=>isRelationshipField(key, schemaFields)));
360
348
  Object.entries(doc).forEach(([key, value])=>{
361
349
  if (value === null || value === undefined) return;
362
- const originalKey = findRelationshipOriginalKey(key, relationshipFields);
363
- if (originalKey) {
364
- processRelationshipField(result, originalKey, key, value);
350
+ // Convert ID fields to strings for BetterAuth compatibility
351
+ if ([
352
+ 'id',
353
+ '_id'
354
+ ].includes(key)) {
355
+ result[key] = String(value);
356
+ return;
365
357
  }
366
- if (isDateField({
367
- key,
368
- value
369
- })) {
358
+ // Handle relationship fields with renamed fieldNames
359
+ const originalRelatedFieldKey = Object.keys(relationshipFields).find((k)=>relationshipFields[k].fieldName === key);
360
+ if (originalRelatedFieldKey) {
361
+ normalizeDocumentIds(result, originalRelatedFieldKey, key, value);
362
+ return;
363
+ }
364
+ // Convert ISO date strings to Date objects for BetterAuth
365
+ if (isDateField(value)) {
370
366
  result[key] = new Date(value);
367
+ return;
371
368
  }
372
369
  });
373
370
  return result;
374
371
  }
375
- function findRelationshipOriginalKey(fieldName, relationshipFields) {
376
- return Object.keys(relationshipFields).find((key)=>relationshipFields[key].fieldName === fieldName);
377
- }
378
- function processRelationshipField(result, originalKey, fieldName, value) {
379
- // Simple ID value (string or number)
372
+ /**
373
+ * Normalizes ID fields for both primary and relationship documents.
374
+ *
375
+ * This function ensures consistent ID handling between BetterAuth and Payload CMS by:
376
+ * 1. Converting all IDs to strings for BetterAuth (stored in originalKey)
377
+ * 2. Preserving original ID types for Payload CMS (stored in fieldName)
378
+ *
379
+ * The function handles various ID formats:
380
+ * - Primitive values (string/number IDs)
381
+ * - Object references with ID properties
382
+ * - Arrays of either primitive IDs or object references
383
+ *
384
+ * @param result - The result object being transformed
385
+ * @param originalKey - The original field key from BetterAuth schema
386
+ * @param fieldName - The renamed field as used in Payload CMS
387
+ * @param value - The ID value to normalize (primitive, object, or array)
388
+ */ function normalizeDocumentIds(result, originalKey, fieldName, value) {
389
+ // Case 1: Primitive ID value (string or number)
380
390
  if (typeof value === 'string' || typeof value === 'number') {
381
- result[originalKey] = value;
391
+ // For BetterAuth: Always use string IDs
392
+ result[originalKey] = String(value);
393
+ // For Payload: Keep original type
394
+ result[fieldName] = value;
395
+ return;
396
+ }
397
+ // Case 2: Object with ID property
398
+ if (typeof value === 'object' && value !== null && 'id' in value) {
399
+ // For BetterAuth: Extract and stringify the ID
400
+ result[originalKey] = String(value.id);
401
+ // For Payload: Extract ID but preserve type
402
+ result[fieldName] = value.id;
382
403
  return;
383
404
  }
384
- // Array of relationships
405
+ // Case 3: Array of IDs or references
385
406
  if (Array.isArray(value) && value.length > 0) {
386
- if (value.every((item)=>typeof item === 'object' && 'id' in item)) {
387
- result[originalKey] = value.map((item)=>item.id);
407
+ // Check if array contains objects with ID properties
408
+ if (value.every((item)=>typeof item === 'object' && item !== null && 'id' in item)) {
409
+ // Array of objects with IDs
410
+ result[originalKey] = value.map((item)=>String(item.id));
388
411
  result[fieldName] = value.map((item)=>item.id);
412
+ } else {
413
+ // Array of primitive IDs
414
+ result[originalKey] = value.map((item)=>String(item));
415
+ result[fieldName] = value.map((item)=>item);
389
416
  }
390
417
  return;
391
418
  }
392
- // Single relationship object with ID
393
- if (typeof value === 'object' && 'id' in value) {
394
- result[originalKey] = value.id;
395
- result[fieldName] = value.id;
396
- }
419
+ // Note: If value doesn't match any expected format, no changes are made
397
420
  }
398
- function operatorToPayload(operator, value) {
421
+ /**
422
+ * Converts a BetterAuth operator to the equivalent Payload CMS query operator
423
+ *
424
+ * This function maps standard query operators from BetterAuth's format to
425
+ * the specific format expected by Payload CMS's query engine.
426
+ *
427
+ * @param operator - The BetterAuth operator string (e.g., 'eq', 'gt', 'contains')
428
+ * @param value - The value to be used with the operator
429
+ * @returns An object with the Payload-compatible operator and value
430
+ *
431
+ * @example
432
+ * // Returns { equals: 'test@example.com' }
433
+ * operatorToPayload('eq', 'test@example.com')
434
+ *
435
+ * @example
436
+ * // Returns { greater_than: 100 }
437
+ * operatorToPayload('gt', 100)
438
+ */ function operatorToPayload(operator, value) {
399
439
  switch(operator){
400
440
  case 'eq':
401
441
  return {
@@ -438,24 +478,45 @@ export const createTransform = (options, enableDebugLogs)=>{
438
478
  like: `%${value}`
439
479
  };
440
480
  default:
481
+ // Fall back to equals for unrecognized operators
441
482
  return {
442
483
  equals: value
443
484
  };
444
485
  }
445
486
  }
446
- function convertWhereValue({ value, fieldName, idType }) {
447
- if (fieldName === 'id' || fieldName === '_id') {
487
+ /**
488
+ * Converts a where clause value to the appropriate type based on field name and ID type configuration
489
+ *
490
+ * This function handles two main scenarios:
491
+ * 1. ID field conversion - ensures IDs match the database's expected type (number or string)
492
+ * 2. Object with embedded ID - extracts and converts the ID property from objects
493
+ *
494
+ * @param value - The value to convert (can be primitive, object with ID, or array)
495
+ * @param fieldName - The name of the field being queried
496
+ * @param idType - The expected ID type in the database
497
+ * @returns The converted value appropriate for the database query
498
+ */ function convertWhereValue({ value, fieldName, idType }) {
499
+ // Check if field is an ID field (supporting both MongoDB-style _id and standard id)
500
+ if ([
501
+ 'id',
502
+ '_id'
503
+ ].includes(fieldName)) {
504
+ // Case 1: Value is an object containing an ID property
448
505
  if (typeof value === 'object' && value !== null && 'id' in value) {
449
- // Extract ID from object and ensure it matches the expected type
506
+ // Extract ID from object
450
507
  const id = value.id;
451
- if (idType === 'number' && typeof id === 'string' && !isNaN(Number(id))) {
452
- return Number(id);
453
- } else if (idType === 'text' && typeof id === 'number') {
508
+ // Use type conversion based on database configuration
509
+ if (idType === 'number' && typeof id === 'string') {
510
+ const numId = Number(id);
511
+ return !isNaN(numId) ? numId : id;
512
+ }
513
+ if (idType === 'text' && typeof id === 'number') {
454
514
  return String(id);
455
515
  }
456
516
  return id;
457
517
  }
458
- // Convert standalone ID value to match expected type
518
+ // Case 2: Value is a standalone ID that needs type conversion
519
+ // Convert string ID to number if database expects numeric IDs
459
520
  if (idType === 'number' && typeof value === 'string' && !isNaN(Number(value))) {
460
521
  return Number(value);
461
522
  } else if (idType === 'text' && typeof value === 'number') {
@@ -463,28 +524,51 @@ export const createTransform = (options, enableDebugLogs)=>{
463
524
  }
464
525
  return value;
465
526
  }
527
+ // For non-ID fields, return the value unchanged
466
528
  return value;
467
529
  }
468
- function convertWhereClause({ idType, model, where }) {
530
+ /**
531
+ * Converts Better Auth where clauses to Payload CMS compatible where conditions
532
+ *
533
+ * This function transforms the Better Auth query format into Payload's query format,
534
+ * handling field name mapping, value type conversion, and logical operators (AND/OR).
535
+ *
536
+ * The function handles three main cases:
537
+ * 1. Empty or undefined where clause - returns empty object
538
+ * 2. Single condition - converts to a simple field-value pair
539
+ * 3. Multiple conditions - groups by AND/OR connectors and builds a complex query
540
+ *
541
+ * @param idType - The database ID type ('number' or 'text')
542
+ * @param model - The model/collection name to query
543
+ * @param where - Array of Better Auth where conditions
544
+ * @returns A Payload-compatible where clause object
545
+ */ function convertWhereClause({ idType, model, where }) {
546
+ // Handle empty where clause
469
547
  if (!where) return {};
548
+ // Handle single condition case for optimization
470
549
  if (where.length === 1) {
471
550
  const w = where[0];
472
551
  if (!w) {
473
552
  return {};
474
553
  }
554
+ // Map field name according to schema and convert value to appropriate type
475
555
  const fieldName = getFieldName(model, w.field);
476
556
  const value = convertWhereValue({
477
557
  value: w.value,
478
558
  fieldName,
479
559
  idType
480
560
  });
561
+ // Create the Payload where condition with proper operator
481
562
  const res = {
482
563
  [fieldName]: operatorToPayload(w.operator ?? '', value)
483
564
  };
484
565
  return res;
485
566
  }
567
+ // Handle multiple conditions by separating AND/OR clauses
568
+ // Default to AND if no connector is specified
486
569
  const and = where.filter((w)=>w.connector === 'AND' || !w.connector);
487
570
  const or = where.filter((w)=>w.connector === 'OR');
571
+ // Process AND conditions
488
572
  const andClause = and.map((w)=>{
489
573
  const fieldName = getFieldName(model, w.field);
490
574
  const value = convertWhereValue({
@@ -496,6 +580,7 @@ export const createTransform = (options, enableDebugLogs)=>{
496
580
  [fieldName]: operatorToPayload(w.operator ?? '', value)
497
581
  };
498
582
  });
583
+ // Process OR conditions
499
584
  const orClause = or.map((w)=>{
500
585
  const fieldName = getFieldName(model, w.field);
501
586
  const value = convertWhereValue({
@@ -507,6 +592,8 @@ export const createTransform = (options, enableDebugLogs)=>{
507
592
  [fieldName]: operatorToPayload(w.operator ?? '', value)
508
593
  };
509
594
  });
595
+ // Combine AND and OR clauses into final Payload where object
596
+ // Only include non-empty clause arrays
510
597
  return {
511
598
  ...andClause.length ? {
512
599
  AND: andClause
@@ -516,22 +603,59 @@ export const createTransform = (options, enableDebugLogs)=>{
516
603
  } : {}
517
604
  };
518
605
  }
519
- function convertSelect(model, select) {
606
+ /**
607
+ * Converts a better-auth select array to a Payload select object
608
+ *
609
+ * This function transforms the better-auth select array (which contains field names)
610
+ * into the format expected by Payload CMS's query API (an object with field names as keys
611
+ * and boolean true as values).
612
+ *
613
+ * It also handles field name mapping between better-auth schema and Payload collections
614
+ * by using the getFieldName helper to resolve the correct field names.
615
+ *
616
+ * @param model - The model/collection name to get field mappings from
617
+ * @param select - Optional array of field names to select
618
+ * @returns A Payload-compatible select object or undefined if no fields to select
619
+ * @example
620
+ * // Input: ['email', 'name']
621
+ * // Output: { email: true, name: true }
622
+ */ function convertSelect(model, select) {
623
+ // Return undefined if select is empty or not provided
520
624
  if (!select || select.length === 0) return undefined;
625
+ // Transform the array of field names into a Payload select object
626
+ // while also mapping any field names that might be different in Payload
521
627
  return select.reduce((acc, field)=>({
522
628
  ...acc,
523
629
  [getFieldName(model, field)]: true
524
630
  }), {});
525
631
  }
526
- function convertSort(model, sortBy) {
632
+ /**
633
+ * Converts a better-auth sort object to a Payload sort string
634
+ *
635
+ * This function transforms the better-auth sort object (which contains field name and direction)
636
+ * into the format expected by Payload CMS's query API (a string with optional '-' prefix for descending order).
637
+ *
638
+ * It also handles field name mapping between better-auth schema and Payload collections
639
+ * by using the getFieldName helper to resolve the correct field names.
640
+ *
641
+ * @param model - The model/collection name to get field mappings from
642
+ * @param sortBy - Optional object containing field name and sort direction
643
+ * @returns A Payload-compatible sort string or undefined if no sort specified
644
+ * @example
645
+ * // Input: { field: 'email', direction: 'desc' }
646
+ * // Output: '-email'
647
+ * // Input: { field: 'createdAt', direction: 'asc' }
648
+ * // Output: 'createdAt'
649
+ */ function convertSort(model, sortBy) {
527
650
  if (!sortBy) return undefined;
528
- return `${sortBy.direction === 'desc' ? '-' : ''}${getFieldName(model, sortBy.field)}`;
651
+ const fieldName = getFieldName(model, sortBy.field);
652
+ const prefix = sortBy.direction === 'desc' ? '-' : '';
653
+ return `${prefix}${fieldName}`;
529
654
  }
530
655
  return {
531
656
  getFieldName,
532
- getModelName,
657
+ getCollectionSlug,
533
658
  singleIdQuery,
534
- multipleIdsQuery,
535
659
  transformInput,
536
660
  transformOutput,
537
661
  convertWhereClause,
@@ -540,4 +664,4 @@ export const createTransform = (options, enableDebugLogs)=>{
540
664
  };
541
665
  };
542
666
 
543
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9iZXR0ZXItYXV0aC9hZGFwdGVyL3RyYW5zZm9ybS9pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBCZXR0ZXJBdXRoRXJyb3IgfSBmcm9tICdiZXR0ZXItYXV0aCdcbmltcG9ydCB7IEZpZWxkQXR0cmlidXRlLCBGaWVsZFR5cGUsIGdldEF1dGhUYWJsZXMgfSBmcm9tICdiZXR0ZXItYXV0aC9kYidcbmltcG9ydCB0eXBlIHsgQmV0dGVyQXV0aE9wdGlvbnMsIFdoZXJlIH0gZnJvbSAnYmV0dGVyLWF1dGgnXG5pbXBvcnQgdHlwZSB7IENvbGxlY3Rpb25TbHVnLCBXaGVyZSBhcyBQYXlsb2FkV2hlcmUgfSBmcm9tICdwYXlsb2FkJ1xuXG5leHBvcnQgY29uc3QgY3JlYXRlVHJhbnNmb3JtID0gKG9wdGlvbnM6IEJldHRlckF1dGhPcHRpb25zLCBlbmFibGVEZWJ1Z0xvZ3M6IGJvb2xlYW4pID0+IHtcbiAgY29uc3Qgc2NoZW1hID0gZ2V0QXV0aFRhYmxlcyhvcHRpb25zKVxuXG4gIGZ1bmN0aW9uIGRlYnVnTG9nKG1lc3NhZ2U6IGFueVtdKSB7XG4gICAgaWYgKGVuYWJsZURlYnVnTG9ncykge1xuICAgICAgY29uc29sZS5sb2coYFtwYXlsb2FkLWRiLWFkYXB0ZXJdYCwgLi4ubWVzc2FnZSlcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBnZXRNb2RlbE5hbWUobW9kZWw6IHN0cmluZyk6IENvbGxlY3Rpb25TbHVnIHtcbiAgICBjb25zdCBjb2xsZWN0aW9uID0gKHNjaGVtYSBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+KVttb2RlbF0/Lm1vZGVsTmFtZSB8fCBtb2RlbFxuICAgIGlmICghY29sbGVjdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEJldHRlckF1dGhFcnJvcihgTW9kZWwgJHttb2RlbH0gZG9lcyBub3QgZXhpc3QgaW4gdGhlIGRhdGFiYXNlLmApXG4gICAgfVxuICAgIHJldHVybiBjb2xsZWN0aW9uIGFzIENvbGxlY3Rpb25TbHVnXG4gIH1cblxuICBmdW5jdGlvbiBnZXRGaWVsZE5hbWUobW9kZWw6IHN0cmluZywgZmllbGQ6IHN0cmluZykge1xuICAgIGlmIChmaWVsZCA9PT0gJ2lkJykge1xuICAgICAgcmV0dXJuIGZpZWxkXG4gICAgfVxuICAgIGNvbnN0IGYgPSBzY2hlbWFbbW9kZWxdPy5maWVsZHNbZmllbGRdXG4gICAgY29uc3QgZmllbGROYW1lID0gZj8uZmllbGROYW1lIHx8IGZpZWxkXG4gICAgZGVidWdMb2coWydnZXRGaWVsZDogJywgeyBtb2RlbCwgb3JpZ2luYWxGaWVsZDogZmllbGQsIGZpZWxkTmFtZSB9XSlcbiAgICByZXR1cm4gZmllbGROYW1lXG4gIH1cblxuICBmdW5jdGlvbiBpc1JlbGF0aW9uc2hpcEZpZWxkKGZpZWxkS2V5OiBzdHJpbmcpIHtcbiAgICByZXR1cm4gZmllbGRLZXkuZW5kc1dpdGgoJ0lkJykgfHwgZmllbGRLZXkuZW5kc1dpdGgoJ0J5JylcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzRGF0ZUZpZWxkKHsga2V5LCB2YWx1ZSB9OiB7IGtleT86IHN0cmluZzsgdmFsdWU6IGFueSB9KSB7XG4gICAgaWYgKGtleSkge1xuICAgICAgcmV0dXJuIChrZXkuZW5kc1dpdGgoJ0F0JykgfHwga2V5LmVuZHNXaXRoKCdEYXRlJykgfHwga2V5ID09PSAnZGF0ZScpICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgIWlzTmFOKERhdGUucGFyc2UodmFsdWUpKVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiAhaXNOYU4oRGF0ZS5wYXJzZSh2YWx1ZSkpXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gc2luZ2xlSWRRdWVyeSh3aGVyZTogUGF5bG9hZFdoZXJlKSB7XG4gICAgaWYgKCF3aGVyZSB8fCAnYW5kJyBpbiB3aGVyZSB8fCAnb3InIGluIHdoZXJlKSByZXR1cm4gbnVsbFxuXG4gICAgLy8gRm9yIGEgc2luZ2xlIGlkIHF1ZXJ5IGxpa2UgeyBpZDogeyBlcXVhbHM6IDE1IH0gfVxuICAgIC8vIEZpcnN0LCBjaGVjayBpZiB0aGVyZSdzIGFuIGlkIGZpZWxkIGluIHRoZSB3aGVyZSBjbGF1c2VcbiAgICBpZiAoJ2lkJyBpbiB3aGVyZSB8fCAnX2lkJyBpbiB3aGVyZSkge1xuICAgICAgY29uc3QgaWRGaWVsZCA9ICdpZCcgaW4gd2hlcmUgPyAnaWQnIDogJ19pZCdcbiAgICAgIGNvbnN0IGNvbmRpdGlvbiA9IHdoZXJlW2lkRmllbGRdXG5cbiAgICAgIC8vIENoZWNrIGlmIGNvbmRpdGlvbiBpcyBhbiBvYmplY3Qgd2l0aCBlcXVhbHMgb3BlcmF0b3JcbiAgICAgIGlmIChjb25kaXRpb24gJiYgdHlwZW9mIGNvbmRpdGlvbiA9PT0gJ29iamVjdCcgJiYgIUFycmF5LmlzQXJyYXkoY29uZGl0aW9uKSAmJiAnZXF1YWxzJyBpbiBjb25kaXRpb24pIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBjb25kaXRpb24uZXF1YWxzXG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICByZXR1cm4gdmFsdWVcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBDaGVjayBmb3IgY29udGFpbnMgb3BlcmF0b3Igd2l0aCBzaW5nbGUgdmFsdWVcbiAgICAgIGlmIChcbiAgICAgICAgY29uZGl0aW9uICYmXG4gICAgICAgIHR5cGVvZiBjb25kaXRpb24gPT09ICdvYmplY3QnICYmXG4gICAgICAgICFBcnJheS5pc0FycmF5KGNvbmRpdGlvbikgJiZcbiAgICAgICAgJ2NvbnRhaW5zJyBpbiBjb25kaXRpb24gJiZcbiAgICAgICAgQXJyYXkuaXNBcnJheShjb25kaXRpb24uY29udGFpbnMpICYmXG4gICAgICAgIGNvbmRpdGlvbi5jb250YWlucy5sZW5ndGggPT09IDFcbiAgICAgICkge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGNvbmRpdGlvbi5jb250YWluc1swXVxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgcmV0dXJuIHZhbHVlXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgZnVuY3Rpb24gbXVsdGlwbGVJZHNRdWVyeSh3aGVyZTogUGF5bG9hZFdoZXJlKSB7XG4gICAgaWYgKCF3aGVyZSB8fCAnYW5kJyBpbiB3aGVyZSB8fCAnb3InIGluIHdoZXJlKSByZXR1cm4gbnVsbFxuICAgIGlmICgnaWQnIGluIHdoZXJlIHx8ICdfaWQnIGluIHdoZXJlKSB7XG4gICAgICBjb25zdCBpZEZpZWxkID0gJ2lkJyBpbiB3aGVyZSA/ICdpZCcgOiAnX2lkJ1xuICAgICAgY29uc3QgY29uZGl0aW9uID0gd2hlcmVbaWRGaWVsZF1cblxuICAgICAgLy8gQ2hlY2sgaWYgdGhpcyBpcyBhbiAnaW4nIG9wZXJhdG9yIHdpdGggaWQgZmllbGQgYW5kIGFycmF5IG9mIHZhbHVlc1xuICAgICAgaWYgKFxuICAgICAgICBjb25kaXRpb24gJiZcbiAgICAgICAgdHlwZW9mIGNvbmRpdGlvbiA9PT0gJ29iamVjdCcgJiZcbiAgICAgICAgIUFycmF5LmlzQXJyYXkoY29uZGl0aW9uKSAmJlxuICAgICAgICAnaW4nIGluIGNvbmRpdGlvbiAmJlxuICAgICAgICBBcnJheS5pc0FycmF5KGNvbmRpdGlvbi5pbikgJiZcbiAgICAgICAgY29uZGl0aW9uLmluLmxlbmd0aCA+IDEgJiZcbiAgICAgICAgY29uZGl0aW9uLmluLmV2ZXJ5KChpZDogdW5rbm93bikgPT4gdHlwZW9mIGlkID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgaWQgPT09ICdudW1iZXInKVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiBjb25kaXRpb24uaW4gYXMgKG51bWJlciB8IHN0cmluZylbXVxuICAgICAgfVxuXG4gICAgICAvLyBBbHNvIGNoZWNrIGZvciBjb250YWlucyBvcGVyYXRvciB3aXRoIGFycmF5IG9mIElEc1xuICAgICAgaWYgKFxuICAgICAgICBjb25kaXRpb24gJiZcbiAgICAgICAgdHlwZW9mIGNvbmRpdGlvbiA9PT0gJ29iamVjdCcgJiZcbiAgICAgICAgIUFycmF5LmlzQXJyYXkoY29uZGl0aW9uKSAmJlxuICAgICAgICAnY29udGFpbnMnIGluIGNvbmRpdGlvbiAmJlxuICAgICAgICBBcnJheS5pc0FycmF5KGNvbmRpdGlvbi5jb250YWlucykgJiZcbiAgICAgICAgY29uZGl0aW9uLmNvbnRhaW5zLmxlbmd0aCA+IDEgJiZcbiAgICAgICAgY29uZGl0aW9uLmNvbnRhaW5zLmV2ZXJ5KChpZDogdW5rbm93bikgPT4gdHlwZW9mIGlkID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgaWQgPT09ICdudW1iZXInKVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiBjb25kaXRpb24uY29udGFpbnMgYXMgKG51bWJlciB8IHN0cmluZylbXVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgZnVuY3Rpb24gbm9ybWFsaXplRGF0YSh7XG4gICAgZmllbGRLZXksXG4gICAgaW5jb21pbmdWYWx1ZSxcbiAgICBzY2hlbWFGaWVsZHMsXG4gICAgcmVsYXRpb25zaGlwRmllbGQsXG4gICAgaWRUeXBlXG4gIH06IHtcbiAgICBmaWVsZEtleTogc3RyaW5nXG4gICAgaW5jb21pbmdWYWx1ZTogYW55XG4gICAgc2NoZW1hRmllbGRzOiBSZWNvcmQ8c3RyaW5nLCBGaWVsZEF0dHJpYnV0ZTxGaWVsZFR5cGU+PlxuICAgIHJlbGF0aW9uc2hpcEZpZWxkOiBib29sZWFuXG4gICAgaWRUeXBlOiAnbnVtYmVyJyB8ICd0ZXh0J1xuICB9KSB7XG4gICAgLy8gRWFybHkgcmV0dXJuIGZvciBudWxsL3VuZGVmaW5lZCB2YWx1ZXNcbiAgICBpZiAoaW5jb21pbmdWYWx1ZSA9PT0gbnVsbCB8fCBpbmNvbWluZ1ZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBpbmNvbWluZ1ZhbHVlXG4gICAgfVxuXG4gICAgLy9zcGVjaWFsIGNhc2UgZm9yIGFjY291bnRJZCBmaWVsZCBpbiBhY2NvdW50cyBjb2xsZWN0aW9uXG4gICAgaWYgKGZpZWxkS2V5ID09PSAnYWNjb3VudElkJykge1xuICAgICAgcmV0dXJuIFN0cmluZyhpbmNvbWluZ1ZhbHVlKVxuICAgIH1cblxuICAgIC8vIEhhbmRsZSByZWxhdGlvbnNoaXAgZmllbGRzIChJRHMpIGJhc2VkIG9uIGlkVHlwZVxuICAgIGlmIChyZWxhdGlvbnNoaXBGaWVsZCkge1xuICAgICAgaWYgKGlkVHlwZSA9PT0gJ251bWJlcicgJiYgdHlwZW9mIGluY29taW5nVmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlSW50KGluY29taW5nVmFsdWUsIDEwKVxuICAgICAgICBpZiAoIWlzTmFOKHBhcnNlZCkpIHtcbiAgICAgICAgICBkZWJ1Z0xvZyhbYElEIGNvbnZlcnNpb246ICR7ZmllbGRLZXl9IGNvbnZlcnRpbmcgc3RyaW5nIElEIHRvIG51bWJlcmAsIHsgb3JpZ2luYWw6IGluY29taW5nVmFsdWUsIGNvbnZlcnRlZDogcGFyc2VkIH1dKVxuICAgICAgICAgIHJldHVybiBwYXJzZWRcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChpZFR5cGUgPT09ICd0ZXh0JyAmJiB0eXBlb2YgaW5jb21pbmdWYWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgY29uc3Qgc3RyaW5nSWQgPSBTdHJpbmcoaW5jb21pbmdWYWx1ZSlcbiAgICAgICAgZGVidWdMb2coW2BJRCBjb252ZXJzaW9uOiAke2ZpZWxkS2V5fSBjb252ZXJ0aW5nIG51bWJlciBJRCB0byBzdHJpbmdgLCB7IG9yaWdpbmFsOiBpbmNvbWluZ1ZhbHVlLCBjb252ZXJ0ZWQ6IHN0cmluZ0lkIH1dKVxuICAgICAgICByZXR1cm4gc3RyaW5nSWRcbiAgICAgIH1cblxuICAgICAgLy8gSGFuZGxlIGFycmF5IG9mIElEc1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoaW5jb21pbmdWYWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIGluY29taW5nVmFsdWUubWFwKChpZCkgPT4ge1xuICAgICAgICAgIGlmIChpZFR5cGUgPT09ICdudW1iZXInICYmIHR5cGVvZiBpZCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlSW50KGlkLCAxMClcbiAgICAgICAgICAgIHJldHVybiAhaXNOYU4ocGFyc2VkKSA/IHBhcnNlZCA6IGlkXG4gICAgICAgICAgfSBlbHNlIGlmIChpZFR5cGUgPT09ICd0ZXh0JyAmJiB0eXBlb2YgaWQgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICByZXR1cm4gU3RyaW5nKGlkKVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gaWRcbiAgICAgICAgfSlcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGluY29taW5nVmFsdWVcbiAgICB9XG5cbiAgICBjb25zdCBzY2hlbWFGaWVsZCA9IHNjaGVtYUZpZWxkc1tmaWVsZEtleV1cblxuICAgIC8vIElmIG5vIHNjaGVtYSBmaWVsZCBleGlzdHMsIHJldHVybiBhcyBpc1xuICAgIGlmICghc2NoZW1hRmllbGQpIHtcbiAgICAgIHJldHVybiBpbmNvbWluZ1ZhbHVlXG4gICAgfVxuXG4gICAgY29uc3QgZmllbGRUeXBlID0gc2NoZW1hRmllbGQudHlwZVxuXG4gICAgLy8gSGFuZGxlIHN0cmluZyB0eXBlXG4gICAgaWYgKGZpZWxkVHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGlmICh0eXBlb2YgaW5jb21pbmdWYWx1ZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgaWYgKGluY29taW5nVmFsdWUgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgICAgICAgY29uc3QgY29udmVydGVkID0gaW5jb21pbmdWYWx1ZS50b0lTT1N0cmluZygpXG4gICAgICAgICAgZGVidWdMb2coW2BUeXBlIGNvbnZlcnNpb246ICR7ZmllbGRLZXl9IGV4cGVjdGVkIHN0cmluZyBidXQgZ290IERhdGVgLCB7IG9yaWdpbmFsOiBpbmNvbWluZ1ZhbHVlLCBjb252ZXJ0ZWQgfV0pXG4gICAgICAgICAgcmV0dXJuIGNvbnZlcnRlZFxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY29udmVydGVkID0gU3RyaW5nKGluY29taW5nVmFsdWUpXG4gICAgICAgIGRlYnVnTG9nKFtgVHlwZSBjb252ZXJzaW9uOiAke2ZpZWxkS2V5fSBleHBlY3RlZCBzdHJpbmcgYnV0IGdvdCAke3R5cGVvZiBpbmNvbWluZ1ZhbHVlfWAsIHsgb3JpZ2luYWw6IGluY29taW5nVmFsdWUsIGNvbnZlcnRlZCB9XSlcbiAgICAgICAgcmV0dXJuIGNvbnZlcnRlZFxuICAgICAgfVxuICAgICAgcmV0dXJuIGluY29taW5nVmFsdWVcbiAgICB9XG5cbiAgICAvLyBIYW5kbGUgbnVtYmVyIHR5cGVcbiAgICBpZiAoZmllbGRUeXBlID09PSAnbnVtYmVyJykge1xuICAgICAgaWYgKHR5cGVvZiBpbmNvbWluZ1ZhbHVlICE9PSAnbnVtYmVyJykge1xuICAgICAgICBpZiAoaW5jb21pbmdWYWx1ZSBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgICAgICBjb25zdCBjb252ZXJ0ZWQgPSBpbmNvbWluZ1ZhbHVlLmdldFRpbWUoKVxuICAgICAgICAgIGRlYnVnTG9nKFtgVHlwZSBjb252ZXJzaW9uOiAke2ZpZWxkS2V5fSBleHBlY3RlZCBudW1iZXIgYnV0IGdvdCBEYXRlYCwgeyBvcmlnaW5hbDogaW5jb21pbmdWYWx1ZSwgY29udmVydGVkIH1dKVxuICAgICAgICAgIHJldHVybiBjb252ZXJ0ZWRcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgaW5jb21pbmdWYWx1ZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgY29uc3QgY29udmVydGVkID0gaW5jb21pbmdWYWx1ZSA/IDEgOiAwXG4gICAgICAgICAgZGVidWdMb2coW2BUeXBlIGNvbnZlcnNpb246ICR7ZmllbGRLZXl9IGV4cGVjdGVkIG51bWJlciBidXQgZ290IGJvb2xlYW5gLCB7IG9yaWdpbmFsOiBpbmNvbWluZ1ZhbHVlLCBjb252ZXJ0ZWQgfV0pXG4gICAgICAgICAgcmV0dXJuIGNvbnZlcnRlZFxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBpbmNvbWluZ1ZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlRmxvYXQoaW5jb21pbmdWYWx1ZSlcbiAgICAgICAgICBpZiAoIWlzTmFOKHBhcnNlZCkpIHtcbiAgICAgICAgICAgIGRlYnVnTG9nKFtgVHlwZSBjb252ZXJzaW9uOiAke2ZpZWxkS2V5fSBleHBlY3RlZCBudW1iZXIgYnV0IGdvdCBzdHJpbmdgLCB7IG9yaWdpbmFsOiBpbmNvbWluZ1ZhbHVlLCBjb252ZXJ0ZWQ6IHBhcnNlZCB9XSlcbiAgICAgICAgICAgIHJldHVybiBwYXJzZWRcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBpbmNvbWluZ1ZhbHVlXG4gICAgfVxuXG4gICAgLy8gSGFuZGxlIGJvb2xlYW4gdHlwZVxuICAgIGlmIChmaWVsZFR5cGUgPT09ICdib29sZWFuJykge1xuICAgICAgaWYgKHR5cGVvZiBpbmNvbWluZ1ZhbHVlICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgbGV0IGNvbnZlcnRlZFxuXG4gICAgICAgIGlmICh0eXBlb2YgaW5jb21pbmdWYWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBjb252ZXJ0ZWQgPSBpbmNvbWluZ1ZhbHVlLnRvTG93ZXJDYXNlKCkgPT09ICd0cnVlJyB8fCBpbmNvbWluZ1ZhbHVlID09PSAnMSdcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgaW5jb21pbmdWYWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICBjb252ZXJ0ZWQgPSBpbmNvbWluZ1ZhbHVlICE9PSAwXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29udmVydGVkID0gISFpbmNvbWluZ1ZhbHVlXG4gICAgICAgIH1cblxuICAgICAgICBkZWJ1Z0xvZyhbYFR5cGUgY29udmVyc2lvbjogJHtmaWVsZEtleX0gZXhwZWN0ZWQgYm9vbGVhbiBidXQgZ290ICR7dHlwZW9mIGluY29taW5nVmFsdWV9YCwgeyBvcmlnaW5hbDogaW5jb21pbmdWYWx1ZSwgY29udmVydGVkIH1dKVxuICAgICAgICByZXR1cm4gY29udmVydGVkXG4gICAgICB9XG4gICAgICByZXR1cm4gaW5jb21pbmdWYWx1ZVxuICAgIH1cblxuICAgIC8vIEhhbmRsZSBkYXRlIHR5cGVcbiAgICBpZiAoZmllbGRUeXBlID09PSAnZGF0ZScpIHtcbiAgICAgIGlmICghKGluY29taW5nVmFsdWUgaW5zdGFuY2VvZiBEYXRlKSkge1xuICAgICAgICBsZXQgY29udmVydGVkXG5cbiAgICAgICAgaWYgKHR5cGVvZiBpbmNvbWluZ1ZhbHVlID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgaW5jb21pbmdWYWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICBjb252ZXJ0ZWQgPSBuZXcgRGF0ZShpbmNvbWluZ1ZhbHVlKVxuICAgICAgICAgIGlmICghaXNOYU4oY29udmVydGVkLmdldFRpbWUoKSkpIHtcbiAgICAgICAgICAgIGRlYnVnTG9nKFtgVHlwZSBjb252ZXJzaW9uOiAke2ZpZWxkS2V5fSBleHBlY3RlZCBEYXRlIGJ1dCBnb3QgJHt0eXBlb2YgaW5jb21pbmdWYWx1ZX1gLCB7IG9yaWdpbmFsOiBpbmNvbWluZ1ZhbHVlLCBjb252ZXJ0ZWQgfV0pXG4gICAgICAgICAgICByZXR1cm4gY29udmVydGVkXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gaW5jb21pbmdWYWx1ZVxuICAgIH1cblxuICAgIC8vIEhhbmRsZSBhcnJheSB0eXBlcyAoc3RyaW5nW10gb3IgbnVtYmVyW10gb3IgTGl0ZXJhbFN0cmluZ1tdKVxuICAgIGlmICh0eXBlb2YgZmllbGRUeXBlID09PSAnc3RyaW5nJyAmJiBmaWVsZFR5cGUuZW5kc1dpdGgoJ1tdJykpIHtcbiAgICAgIGNvbnN0IGJhc2VUeXBlID0gZmllbGRUeXBlLnNsaWNlKDAsIC0yKVxuXG4gICAgICAvLyBDb252ZXJ0IHRvIGFycmF5IGlmIG5vdCBhbHJlYWR5XG4gICAgICBsZXQgYXJyYXlWYWx1ZSA9IGluY29taW5nVmFsdWVcbiAgICAgIGlmICghQXJyYXkuaXNBcnJheShpbmNvbWluZ1ZhbHVlKSkge1xuICAgICAgICBpZiAodHlwZW9mIGluY29taW5nVmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIFRyeSB0byBwYXJzZSBhcyBKU09OIGFycmF5XG4gICAgICAgICAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKGluY29taW5nVmFsdWUpXG4gICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShwYXJzZWQpKSB7XG4gICAgICAgICAgICAgIGRlYnVnTG9nKFtgVHlwZSBjb252ZXJzaW9uOiAke2ZpZWxkS2V5fSBwYXJzZWQgSlNPTiBzdHJpbmcgdG8gYXJyYXlgLCB7IG9yaWdpbmFsOiBpbmNvbWluZ1ZhbHVlLCBjb252ZXJ0ZWQ6IHBhcnNlZCB9XSlcbiAgICAgICAgICAgICAgYXJyYXlWYWx1ZSA9IHBhcnNlZFxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgYXJyYXlWYWx1ZSA9IFtpbmNvbWluZ1ZhbHVlXVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIC8vIElmIHBhcnNpbmcgZmFpbHMsIHdyYXAgaW4gYXJyYXlcbiAgICAgICAgICAgIGFycmF5VmFsdWUgPSBbaW5jb21pbmdWYWx1ZV1cbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gV3JhcCBub24tYXJyYXkgdmFsdWVzIGluIGFycmF5XG4gICAgICAgICAgYXJyYXlWYWx1ZSA9IFtpbmNvbWluZ1ZhbHVlXVxuICAgICAgICB9XG5cbiAgICAgICAgZGVidWdMb2coW2BUeXBlIGNvbnZlcnNpb246ICR7ZmllbGRLZXl9IGNvbnZlcnRlZCB0byBhcnJheWAsIHsgb3JpZ2luYWw6IGluY29taW5nVmFsdWUsIGNvbnZlcnRlZDogYXJyYXlWYWx1ZSB9XSlcbiAgICAgIH1cblxuICAgICAgLy8gTm9ybWFsaXplIGVhY2ggYXJyYXkgZWxlbWVudCBiYXNlZCBvbiB0aGUgYmFzZSB0eXBlXG4gICAgICByZXR1cm4gYXJyYXlWYWx1ZS5tYXAoKGl0ZW06IGFueSwgaW5kZXg6IG51bWJlcikgPT4ge1xuICAgICAgICBpZiAoYmFzZVR5cGUgPT09ICdzdHJpbmcnICYmIHR5cGVvZiBpdGVtICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgIGNvbnN0IGNvbnZlcnRlZCA9IFN0cmluZyhpdGVtKVxuICAgICAgICAgIGRlYnVnTG9nKFtgVHlwZSBjb252ZXJzaW9uOiAke2ZpZWxkS2V5fVske2luZGV4fV0gZXhwZWN0ZWQgc3RyaW5nIGJ1dCBnb3QgJHt0eXBlb2YgaXRlbX1gLCB7IG9yaWdpbmFsOiBpdGVtLCBjb252ZXJ0ZWQgfV0pXG4gICAgICAgICAgcmV0dXJuIGNvbnZlcnRlZFxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGJhc2VUeXBlID09PSAnbnVtYmVyJyAmJiB0eXBlb2YgaXRlbSAhPT0gJ251bWJlcicpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGl0ZW0gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBjb25zdCBwYXJzZWQgPSBwYXJzZUZsb2F0KGl0ZW0pXG4gICAgICAgICAgICBpZiAoIWlzTmFOKHBhcnNlZCkpIHtcbiAgICAgICAgICAgICAgZGVidWdMb2coW2BUeXBlIGNvbnZlcnNpb246ICR7ZmllbGRLZXl9WyR7aW5kZXh9XSBleHBlY3RlZCBudW1iZXIgYnV0IGdvdCBzdHJpbmdgLCB7IG9yaWdpbmFsOiBpdGVtLCBjb252ZXJ0ZWQ6IHBhcnNlZCB9XSlcbiAgICAgICAgICAgICAgcmV0dXJuIHBhcnNlZFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGl0ZW0gPT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgcmV0dXJuIGl0ZW0gPyAxIDogMFxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaXRlbVxuICAgICAgfSlcbiAgICB9XG5cbiAgICAvLyBGb3IgYW55IG90aGVyIHR5cGVzIG9yIGlmIG5vIGNvbnZlcnNpb24gbmVlZGVkLCByZXR1cm4gYXMgaXNcbiAgICByZXR1cm4gaW5jb21pbmdWYWx1ZVxuICB9XG5cbiAgZnVuY3Rpb24gdHJhbnNmb3JtSW5wdXQoe1xuICAgIGRhdGEsXG4gICAgbW9kZWwsXG4gICAgaWRUeXBlLFxuICAgIGFjdGlvblxuICB9OiB7XG4gICAgZGF0YTogUmVjb3JkPHN0cmluZywgYW55PlxuICAgIG1vZGVsOiBzdHJpbmdcbiAgICBpZFR5cGU6ICdudW1iZXInIHwgJ3RleHQnXG4gICAgYWN0aW9uOiAnY3JlYXRlJyB8ICd1cGRhdGUnXG4gIH0pIHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZERhdGE6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fVxuICAgIGNvbnN0IHNjaGVtYUZpZWxkcyA9IHNjaGVtYVttb2RlbF0uZmllbGRzXG4gICAgZm9yIChjb25zdCBmaWVsZEtleSBpbiBkYXRhKSB7XG4gICAgICBpZiAoZGF0YVtmaWVsZEtleV0gPT09IHVuZGVmaW5lZCAmJiBhY3Rpb24gPT09ICd1cGRhdGUnKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBjb25zdCByZWxhdGlvbnNoaXBGaWVsZCA9IGlzUmVsYXRpb25zaGlwRmllbGQoZmllbGRLZXkpXG4gICAgICBjb25zdCBzY2hlbWFGaWVsZE5hbWUgPSBzY2hlbWFGaWVsZHNbZmllbGRLZXldPy5maWVsZE5hbWVcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWREYXRhID0gbm9ybWFsaXplRGF0YSh7XG4gICAgICAgIGlkVHlwZSxcbiAgICAgICAgZmllbGRLZXksXG4gICAgICAgIGluY29taW5nVmFsdWU6IGRhdGFbZmllbGRLZXldLFxuICAgICAgICBzY2hlbWFGaWVsZHMsXG4gICAgICAgIHJlbGF0aW9uc2hpcEZpZWxkXG4gICAgICB9KVxuICAgICAgaWYgKHNjaGVtYUZpZWxkTmFtZSkge1xuICAgICAgICB0cmFuc2Zvcm1lZERhdGFbc2NoZW1hRmllbGROYW1lXSA9IG5vcm1hbGl6ZWREYXRhXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0cmFuc2Zvcm1lZERhdGFbZmllbGRLZXldID0gbm9ybWFsaXplZERhdGFcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJhbnNmb3JtZWREYXRhXG4gIH1cblxuICBmdW5jdGlvbiB0cmFuc2Zvcm1PdXRwdXQ8VCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIGFueT4gfCBudWxsPih7IGRvYywgbW9kZWwgfTogeyBkb2M6IFQ7IG1vZGVsOiBzdHJpbmcgfSk6IFQge1xuICAgIGlmIChkb2MgPT09IG51bGwgfHwgZG9jID09PSB1bmRlZmluZWQgfHwgdHlwZW9mIGRvYyAhPT0gJ29iamVjdCcpIHJldHVybiBkb2NcblxuICAgIGNvbnN0IHJlc3VsdCA9IHsgLi4uZG9jIH0gYXMgYW55XG4gICAgY29uc3Qgc2NoZW1hRmllbGRzID0gc2NoZW1hW21vZGVsXS5maWVsZHNcbiAgICBjb25zdCByZWxhdGlvbnNoaXBGaWVsZHMgPSBPYmplY3QuZW50cmllcyhzY2hlbWFGaWVsZHMpXG4gICAgICAuZmlsdGVyKChba2V5XSkgPT4gaXNSZWxhdGlvbnNoaXBGaWVsZChrZXkpKVxuICAgICAgLnJlZHVjZSgoYWNjLCBba2V5LCB2YWx1ZV0pID0+ICh7IC4uLmFjYywgW2tleV06IHZhbHVlIH0pLCB7fSBhcyBSZWNvcmQ8c3RyaW5nLCBGaWVsZEF0dHJpYnV0ZTxGaWVsZFR5cGU+PilcblxuICAgIE9iamVjdC5lbnRyaWVzKGRvYykuZm9yRWFjaCgoW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkgcmV0dXJuXG5cbiAgICAgIGNvbnN0IG9yaWdpbmFsS2V5ID0gZmluZFJlbGF0aW9uc2hpcE9yaWdpbmFsS2V5KGtleSwgcmVsYXRpb25zaGlwRmllbGRzKVxuICAgICAgaWYgKG9yaWdpbmFsS2V5KSB7XG4gICAgICAgIHByb2Nlc3NSZWxhdGlvbnNoaXBGaWVsZChyZXN1bHQsIG9yaWdpbmFsS2V5LCBrZXksIHZhbHVlKVxuICAgICAgfVxuXG4gICAgICBpZiAoaXNEYXRlRmllbGQoeyBrZXksIHZhbHVlIH0pKSB7XG4gICAgICAgIHJlc3VsdFtrZXldID0gbmV3IERhdGUodmFsdWUpXG4gICAgICB9XG4gICAgfSlcblxuICAgIHJldHVybiByZXN1bHQgYXMgVFxuICB9XG5cbiAgZnVuY3Rpb24gZmluZFJlbGF0aW9uc2hpcE9yaWdpbmFsS2V5KFxuICAgIGZpZWxkTmFtZTogc3RyaW5nLFxuICAgIHJlbGF0aW9uc2hpcEZpZWxkczogUmVjb3JkPHN0cmluZywgRmllbGRBdHRyaWJ1dGU8RmllbGRUeXBlPj5cbiAgKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gT2JqZWN0LmtleXMocmVsYXRpb25zaGlwRmllbGRzKS5maW5kKChrZXkpID0+IHJlbGF0aW9uc2hpcEZpZWxkc1trZXldLmZpZWxkTmFtZSA9PT0gZmllbGROYW1lKVxuICB9XG5cbiAgZnVuY3Rpb24gcHJvY2Vzc1JlbGF0aW9uc2hpcEZpZWxkKHJlc3VsdDogUmVjb3JkPHN0cmluZywgYW55Piwgb3JpZ2luYWxLZXk6IHN0cmluZywgZmllbGROYW1lOiBzdHJpbmcsIHZhbHVlOiBhbnkpOiB2b2lkIHtcbiAgICAvLyBTaW1wbGUgSUQgdmFsdWUgKHN0cmluZyBvciBudW1iZXIpXG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgcmVzdWx0W29yaWdpbmFsS2V5XSA9IHZhbHVlXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICAvLyBBcnJheSBvZiByZWxhdGlvbnNoaXBzXG4gICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpICYmIHZhbHVlLmxlbmd0aCA+IDApIHtcbiAgICAgIGlmICh2YWx1ZS5ldmVyeSgoaXRlbSkgPT4gdHlwZW9mIGl0ZW0gPT09ICdvYmplY3QnICYmICdpZCcgaW4gaXRlbSkpIHtcbiAgICAgICAgcmVzdWx0W29yaWdpbmFsS2V5XSA9IHZhbHVlLm1hcCgoaXRlbSkgPT4gaXRlbS5pZClcbiAgICAgICAgcmVzdWx0W2ZpZWxkTmFtZV0gPSB2YWx1ZS5tYXAoKGl0ZW0pID0+IGl0ZW0uaWQpXG4gICAgICB9XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICAvLyBTaW5nbGUgcmVsYXRpb25zaGlwIG9iamVjdCB3aXRoIElEXG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgJ2lkJyBpbiB2YWx1ZSkge1xuICAgICAgcmVzdWx0W29yaWdpbmFsS2V5XSA9IHZhbHVlLmlkXG4gICAgICByZXN1bHRbZmllbGROYW1lXSA9IHZhbHVlLmlkXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gb3BlcmF0b3JUb1BheWxvYWQob3BlcmF0b3I6IHN0cmluZywgdmFsdWU6IGFueSkge1xuICAgIHN3aXRjaCAob3BlcmF0b3IpIHtcbiAgICAgIGNhc2UgJ2VxJzpcbiAgICAgICAgcmV0dXJuIHsgZXF1YWxzOiB2YWx1ZSB9XG4gICAgICBjYXNlICduZSc6XG4gICAgICAgIHJldHVybiB7IG5vdF9lcXVhbHM6IHZhbHVlIH1cbiAgICAgIGNhc2UgJ2d0JzpcbiAgICAgICAgcmV0dXJuIHsgZ3JlYXRlcl90aGFuOiB2YWx1ZSB9XG4gICAgICBjYXNlICdndGUnOlxuICAgICAgICByZXR1cm4geyBncmVhdGVyX3RoYW5fZXF1YWw6IHZhbHVlIH1cbiAgICAgIGNhc2UgJ2x0JzpcbiAgICAgICAgcmV0dXJuIHsgbGVzc190aGFuOiB2YWx1ZSB9XG4gICAgICBjYXNlICdsdGUnOlxuICAgICAgICByZXR1cm4geyBsZXNzX3RoYW5fZXF1YWw6IHZhbHVlIH1cbiAgICAgIGNhc2UgJ2NvbnRhaW5zJzpcbiAgICAgICAgcmV0dXJuIHsgY29udGFpbnM6IHZhbHVlIH1cbiAgICAgIGNhc2UgJ2luJzpcbiAgICAgICAgcmV0dXJuIHsgaW46IHZhbHVlIH1cbiAgICAgIGNhc2UgJ3N0YXJ0c193aXRoJzpcbiAgICAgICAgcmV0dXJuIHsgbGlrZTogYCR7dmFsdWV9JWAgfVxuICAgICAgY2FzZSAnZW5kc193aXRoJzpcbiAgICAgICAgcmV0dXJuIHsgbGlrZTogYCUke3ZhbHVlfWAgfVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIHsgZXF1YWxzOiB2YWx1ZSB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gY29udmVydFdoZXJlVmFsdWUoeyB2YWx1ZSwgZmllbGROYW1lLCBpZFR5cGUgfTogeyB2YWx1ZTogYW55OyBmaWVsZE5hbWU6IHN0cmluZzsgaWRUeXBlOiAnbnVtYmVyJyB8ICd0ZXh0JyB9KSB7XG4gICAgaWYgKGZpZWxkTmFtZSA9PT0gJ2lkJyB8fCBmaWVsZE5hbWUgPT09ICdfaWQnKSB7XG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZSAhPT0gbnVsbCAmJiAnaWQnIGluIHZhbHVlKSB7XG4gICAgICAgIC8vIEV4dHJhY3QgSUQgZnJvbSBvYmplY3QgYW5kIGVuc3VyZSBpdCBtYXRjaGVzIHRoZSBleHBlY3RlZCB0eXBlXG4gICAgICAgIGNvbnN0IGlkID0gdmFsdWUuaWRcbiAgICAgICAgaWYgKGlkVHlwZSA9PT0gJ251bWJlcicgJiYgdHlwZW9mIGlkID09PSAnc3RyaW5nJyAmJiAhaXNOYU4oTnVtYmVyKGlkKSkpIHtcbiAgICAgICAgICByZXR1cm4gTnVtYmVyKGlkKVxuICAgICAgICB9IGVsc2UgaWYgKGlkVHlwZSA9PT0gJ3RleHQnICYmIHR5cGVvZiBpZCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICByZXR1cm4gU3RyaW5nKGlkKVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpZFxuICAgICAgfVxuICAgICAgLy8gQ29udmVydCBzdGFuZGFsb25lIElEIHZhbHVlIHRvIG1hdGNoIGV4cGVjdGVkIHR5cGVcbiAgICAgIGlmIChpZFR5cGUgPT09ICdudW1iZXInICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgIWlzTmFOKE51bWJlcih2YWx1ZSkpKSB7XG4gICAgICAgIHJldHVybiBOdW1iZXIodmFsdWUpXG4gICAgICB9IGVsc2UgaWYgKGlkVHlwZSA9PT0gJ3RleHQnICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgcmV0dXJuIFN0cmluZyh2YWx1ZSlcbiAgICAgIH1cbiAgICAgIHJldHVybiB2YWx1ZVxuICAgIH1cbiAgICByZXR1cm4gdmFsdWVcbiAgfVxuXG4gIGZ1bmN0aW9uIGNvbnZlcnRXaGVyZUNsYXVzZSh7IGlkVHlwZSwgbW9kZWwsIHdoZXJlIH06IHsgaWRUeXBlOiAnbnVtYmVyJyB8ICd0ZXh0JzsgbW9kZWw6IHN0cmluZzsgd2hlcmU/OiBXaGVyZVtdIH0pOiBQYXlsb2FkV2hlcmUge1xuICAgIGlmICghd2hlcmUpIHJldHVybiB7fVxuICAgIGlmICh3aGVyZS5sZW5ndGggPT09IDEpIHtcbiAgICAgIGNvbnN0IHcgPSB3aGVyZVswXVxuICAgICAgaWYgKCF3KSB7XG4gICAgICAgIHJldHVybiB7fVxuICAgICAgfVxuXG4gICAgICBjb25zdCBmaWVsZE5hbWUgPSBnZXRGaWVsZE5hbWUobW9kZWwsIHcuZmllbGQpXG4gICAgICBjb25zdCB2YWx1ZSA9IGNvbnZlcnRXaGVyZVZhbHVlKHtcbiAgICAgICAgdmFsdWU6IHcudmFsdWUsXG4gICAgICAgIGZpZWxkTmFtZSxcbiAgICAgICAgaWRUeXBlXG4gICAgICB9KVxuXG4gICAgICBjb25zdCByZXMgPSB7XG4gICAgICAgIFtmaWVsZE5hbWVdOiBvcGVyYXRvclRvUGF5bG9hZCh3Lm9wZXJhdG9yID8/ICcnLCB2YWx1ZSlcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJlc1xuICAgIH1cbiAgICBjb25zdCBhbmQgPSB3aGVyZS5maWx0ZXIoKHcpID0+IHcuY29ubmVjdG9yID09PSAnQU5EJyB8fCAhdy5jb25uZWN0b3IpXG4gICAgY29uc3Qgb3IgPSB3aGVyZS5maWx0ZXIoKHcpID0+IHcuY29ubmVjdG9yID09PSAnT1InKVxuICAgIGNvbnN0IGFuZENsYXVzZSA9IGFuZC5tYXAoKHcpID0+IHtcbiAgICAgIGNvbnN0IGZpZWxkTmFtZSA9IGdldEZpZWxkTmFtZShtb2RlbCwgdy5maWVsZClcbiAgICAgIGNvbnN0IHZhbHVlID0gY29udmVydFdoZXJlVmFsdWUoe1xuICAgICAgICB2YWx1ZTogdy52YWx1ZSxcbiAgICAgICAgZmllbGROYW1lLFxuICAgICAgICBpZFR5cGVcbiAgICAgIH0pXG4gICAgICByZXR1cm4ge1xuICAgICAgICBbZmllbGROYW1lXTogb3BlcmF0b3JUb1BheWxvYWQody5vcGVyYXRvciA/PyAnJywgdmFsdWUpXG4gICAgICB9XG4gICAgfSlcbiAgICBjb25zdCBvckNsYXVzZSA9IG9yLm1hcCgodykgPT4ge1xuICAgICAgY29uc3QgZmllbGROYW1lID0gZ2V0RmllbGROYW1lKG1vZGVsLCB3LmZpZWxkKVxuICAgICAgY29uc3QgdmFsdWUgPSBjb252ZXJ0V2hlcmVWYWx1ZSh7XG4gICAgICAgIHZhbHVlOiB3LnZhbHVlLFxuICAgICAgICBmaWVsZE5hbWUsXG4gICAgICAgIGlkVHlwZVxuICAgICAgfSlcbiAgICAgIHJldHVybiB7XG4gICAgICAgIFtmaWVsZE5hbWVdOiBvcGVyYXRvclRvUGF5bG9hZCh3Lm9wZXJhdG9yID8/ICcnLCB2YWx1ZSlcbiAgICAgIH1cbiAgICB9KVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLihhbmRDbGF1c2UubGVuZ3RoID8geyBBTkQ6IGFuZENsYXVzZSB9IDoge30pLFxuICAgICAgLi4uKG9yQ2xhdXNlLmxlbmd0aCA/IHsgT1I6IG9yQ2xhdXNlIH0gOiB7fSlcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBjb252ZXJ0U2VsZWN0KG1vZGVsOiBzdHJpbmcsIHNlbGVjdD86IHN0cmluZ1tdKSB7XG4gICAgaWYgKCFzZWxlY3QgfHwgc2VsZWN0Lmxlbmd0aCA9PT0gMCkgcmV0dXJuIHVuZGVmaW5lZFxuICAgIHJldHVybiBzZWxlY3QucmVkdWNlKChhY2MsIGZpZWxkKSA9PiAoeyAuLi5hY2MsIFtnZXRGaWVsZE5hbWUobW9kZWwsIGZpZWxkKV06IHRydWUgfSksIHt9KVxuICB9XG5cbiAgZnVuY3Rpb24gY29udmVydFNvcnQobW9kZWw6IHN0cmluZywgc29ydEJ5PzogeyBmaWVsZDogc3RyaW5nOyBkaXJlY3Rpb246ICdhc2MnIHwgJ2Rlc2MnIH0pIHtcbiAgICBpZiAoIXNvcnRCeSkgcmV0dXJuIHVuZGVmaW5lZFxuICAgIHJldHVybiBgJHtzb3J0QnkuZGlyZWN0aW9uID09PSAnZGVzYycgPyAnLScgOiAnJ30ke2dldEZpZWxkTmFtZShtb2RlbCwgc29ydEJ5LmZpZWxkKX1gXG4gIH1cblxuICByZXR1cm4ge1xuICAgIGdldEZpZWxkTmFtZSxcbiAgICBnZXRNb2RlbE5hbWUsXG4gICAgc2luZ2xlSWRRdWVyeSxcbiAgICBtdWx0aXBsZUlkc1F1ZXJ5LFxuICAgIHRyYW5zZm9ybUlucHV0LFxuICAgIHRyYW5zZm9ybU91dHB1dCxcbiAgICBjb252ZXJ0V2hlcmVDbGF1c2UsXG4gICAgY29udmVydFNlbGVjdCxcbiAgICBjb252ZXJ0U29ydFxuICB9XG59XG4iXSwibmFtZXMiOlsiQmV0dGVyQXV0aEVycm9yIiwiZ2V0QXV0aFRhYmxlcyIsImNyZWF0ZVRyYW5zZm9ybSIsIm9wdGlvbnMiLCJlbmFibGVEZWJ1Z0xvZ3MiLCJzY2hlbWEiLCJkZWJ1Z0xvZyIsIm1lc3NhZ2UiLCJjb25zb2xlIiwibG9nIiwiZ2V0TW9kZWxOYW1lIiwibW9kZWwiLCJjb2xsZWN0aW9uIiwibW9kZWxOYW1lIiwiZ2V0RmllbGROYW1lIiwiZmllbGQiLCJmIiwiZmllbGRzIiwiZmllbGROYW1lIiwib3JpZ2luYWxGaWVsZCIsImlzUmVsYXRpb25zaGlwRmllbGQiLCJmaWVsZEtleSIsImVuZHNXaXRoIiwiaXNEYXRlRmllbGQiLCJrZXkiLCJ2YWx1ZSIsImlzTmFOIiwiRGF0ZSIsInBhcnNlIiwic2luZ2xlSWRRdWVyeSIsIndoZXJlIiwiaWRGaWVsZCIsImNvbmRpdGlvbiIsIkFycmF5IiwiaXNBcnJheSIsImVxdWFscyIsImNvbnRhaW5zIiwibGVuZ3RoIiwibXVsdGlwbGVJZHNRdWVyeSIsImluIiwiZXZlcnkiLCJpZCIsIm5vcm1hbGl6ZURhdGEiLCJpbmNvbWluZ1ZhbHVlIiwic2NoZW1hRmllbGRzIiwicmVsYXRpb25zaGlwRmllbGQiLCJpZFR5cGUiLCJ1bmRlZmluZWQiLCJTdHJpbmciLCJwYXJzZWQiLCJwYXJzZUludCIsIm9yaWdpbmFsIiwiY29udmVydGVkIiwic3RyaW5nSWQiLCJtYXAiLCJzY2hlbWFGaWVsZCIsImZpZWxkVHlwZSIsInR5cGUiLCJ0b0lTT1N0cmluZyIsImdldFRpbWUiLCJwYXJzZUZsb2F0IiwidG9Mb3dlckNhc2UiLCJiYXNlVHlwZSIsInNsaWNlIiwiYXJyYXlWYWx1ZSIsIkpTT04iLCJlIiwiaXRlbSIsImluZGV4IiwidHJhbnNmb3JtSW5wdXQiLCJkYXRhIiwiYWN0aW9uIiwidHJhbnNmb3JtZWREYXRhIiwic2NoZW1hRmllbGROYW1lIiwibm9ybWFsaXplZERhdGEiLCJ0cmFuc2Zvcm1PdXRwdXQiLCJkb2MiLCJyZXN1bHQiLCJyZWxhdGlvbnNoaXBGaWVsZHMiLCJPYmplY3QiLCJlbnRyaWVzIiwiZmlsdGVyIiwicmVkdWNlIiwiYWNjIiwiZm9yRWFjaCIsIm9yaWdpbmFsS2V5IiwiZmluZFJlbGF0aW9uc2hpcE9yaWdpbmFsS2V5IiwicHJvY2Vzc1JlbGF0aW9uc2hpcEZpZWxkIiwia2V5cyIsImZpbmQiLCJvcGVyYXRvclRvUGF5bG9hZCIsIm9wZXJhdG9yIiwibm90X2VxdWFscyIsImdyZWF0ZXJfdGhhbiIsImdyZWF0ZXJfdGhhbl9lcXVhbCIsImxlc3NfdGhhbiIsImxlc3NfdGhhbl9lcXVhbCIsImxpa2UiLCJjb252ZXJ0V2hlcmVWYWx1ZSIsIk51bWJlciIsImNvbnZlcnRXaGVyZUNsYXVzZSIsInciLCJyZXMiLCJhbmQiLCJjb25uZWN0b3IiLCJvciIsImFuZENsYXVzZSIsIm9yQ2xhdXNlIiwiQU5EIiwiT1IiLCJjb252ZXJ0U2VsZWN0Iiwic2VsZWN0IiwiY29udmVydFNvcnQiLCJzb3J0QnkiLCJkaXJlY3Rpb24iXSwibWFwcGluZ3MiOiJBQUFBLFNBQVNBLGVBQWUsUUFBUSxjQUFhO0FBQzdDLFNBQW9DQyxhQUFhLFFBQVEsaUJBQWdCO0FBSXpFLE9BQU8sTUFBTUMsa0JBQWtCLENBQUNDLFNBQTRCQztJQUMxRCxNQUFNQyxTQUFTSixjQUFjRTtJQUU3QixTQUFTRyxTQUFTQyxPQUFjO1FBQzlCLElBQUlILGlCQUFpQjtZQUNuQkksUUFBUUMsR0FBRyxDQUFDLENBQUMsb0JBQW9CLENBQUMsS0FBS0Y7UUFDekM7SUFDRjtJQUVBLFNBQVNHLGFBQWFDLEtBQWE7UUFDakMsTUFBTUMsYUFBYSxBQUFDUCxNQUE4QixDQUFDTSxNQUFNLEVBQUVFLGFBQWFGO1FBQ3hFLElBQUksQ0FBQ0MsWUFBWTtZQUNmLE1BQU0sSUFBSVosZ0JBQWdCLENBQUMsTUFBTSxFQUFFVyxNQUFNLGdDQUFnQyxDQUFDO1FBQzVFO1FBQ0EsT0FBT0M7SUFDVDtJQUVBLFNBQVNFLGFBQWFILEtBQWEsRUFBRUksS0FBYTtRQUNoRCxJQUFJQSxVQUFVLE1BQU07WUFDbEIsT0FBT0E7UUFDVDtRQUNBLE1BQU1DLElBQUlYLE1BQU0sQ0FBQ00sTUFBTSxFQUFFTSxNQUFNLENBQUNGLE1BQU07UUFDdEMsTUFBTUcsWUFBWUYsR0FBR0UsYUFBYUg7UUFDbENULFNBQVM7WUFBQztZQUFjO2dCQUFFSztnQkFBT1EsZUFBZUo7Z0JBQU9HO1lBQVU7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
667
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9iZXR0ZXItYXV0aC9hZGFwdGVyL3RyYW5zZm9ybS9pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBGaWVsZEF0dHJpYnV0ZSwgRmllbGRUeXBlLCBnZXRBdXRoVGFibGVzIH0gZnJvbSAnYmV0dGVyLWF1dGgvZGInXG5pbXBvcnQgdHlwZSB7IEJldHRlckF1dGhPcHRpb25zLCBXaGVyZSB9IGZyb20gJ2JldHRlci1hdXRoJ1xuaW1wb3J0IHR5cGUgeyBDb2xsZWN0aW9uU2x1ZywgV2hlcmUgYXMgUGF5bG9hZFdoZXJlIH0gZnJvbSAncGF5bG9hZCdcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVRyYW5zZm9ybSA9IChvcHRpb25zOiBCZXR0ZXJBdXRoT3B0aW9ucywgZW5hYmxlRGVidWdMb2dzOiBib29sZWFuKSA9PiB7XG4gIGNvbnN0IHNjaGVtYSA9IGdldEF1dGhUYWJsZXMob3B0aW9ucylcblxuICBmdW5jdGlvbiBkZWJ1Z0xvZyhtZXNzYWdlOiBhbnlbXSkge1xuICAgIGlmIChlbmFibGVEZWJ1Z0xvZ3MpIHtcbiAgICAgIGNvbnNvbGUubG9nKGBbcGF5bG9hZC1kYi1hZGFwdGVyXWAsIC4uLm1lc3NhZ2UpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1hcHMgYSBCZXR0ZXJBdXRoIHNjaGVtYSBtb2RlbCBuYW1lIHRvIGl0cyBjb3JyZXNwb25kaW5nIFBheWxvYWQgQ01TIGNvbGxlY3Rpb24gc2x1Zy5cbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiByZXNvbHZlcyB0aGUgYXBwcm9wcmlhdGUgY29sbGVjdGlvbiBzbHVnIGJ5OlxuICAgKiAxLiBMb29raW5nIHVwIHRoZSBtb2RlbCBpbiB0aGUgQmV0dGVyQXV0aCBzY2hlbWEgdG8gZmluZCBpdHMgY29uZmlndXJlZCBtb2RlbE5hbWVcbiAgICogMi4gRmFsbGluZyBiYWNrIHRvIHRoZSBvcmlnaW5hbCBtb2RlbCBuYW1lIGlmIG5vIG1hcHBpbmcgZXhpc3RzXG4gICAqXG4gICAqIENvbGxlY3Rpb24gc2x1ZyByZXNvbHV0aW9uIGZvbGxvd3MgdGhlc2UgcnVsZXM6XG4gICAqIC0gRm9yIGJhc2UgY29sbGVjdGlvbnM6IFRoZSBzYW5pdGl6ZUJldHRlckF1dGhPcHRpb25zIGZ1bmN0aW9uIGVuc3VyZXMgdGhlIGNvbGxlY3Rpb24gc2x1Z1xuICAgKiAgIGZyb20gcGx1Z2luIG9wdGlvbnMgaXMgc2V0IGFzIHRoZSBtb2RlbCBuYW1lIGluIHRoZSBzY2hlbWFcbiAgICogLSBGb3IgcGx1Z2luczogVGhlIGJldHRlckF1dGhQbHVnaW5TbHVncyBjb25zdGFudCBpcyB1c2VkIGFzIHRoZSBtb2RlbE5hbWVcbiAgICpcbiAgICogQHBhcmFtIG1vZGVsIC0gVGhlIEJldHRlckF1dGggbW9kZWwgbmFtZSB0byByZXNvbHZlXG4gICAqIEByZXR1cm5zIFRoZSBjb3JyZXNwb25kaW5nIFBheWxvYWQgQ01TIGNvbGxlY3Rpb24gc2x1Z1xuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiAvLyBJZiBzY2hlbWFbJ3VzZXInXS5tb2RlbE5hbWUgaXMgJ3VzZXJzJ1xuICAgKiBnZXRDb2xsZWN0aW9uU2x1ZygndXNlcicpIC8vIFJldHVybnMgJ3VzZXJzJ1xuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiAvLyBJZiBtb2RlbCBkb2Vzbid0IGV4aXN0IGluIHNjaGVtYVxuICAgKiBnZXRDb2xsZWN0aW9uU2x1ZygnY3VzdG9tJykgLy8gUmV0dXJucyAnY3VzdG9tJ1xuICAgKlxuICAgKiBAd2FybmluZyBJZiBhIGNvbGxlY3Rpb24gaXMgb3ZlcnJpZGRlbiB1c2luZyB0aGUgY29sbGVjdGlvbk92ZXJyaWRlIG9wdGlvblxuICAgKiB3aXRob3V0IHVwZGF0aW5nIHRoZSBzY2hlbWEgbWFwcGluZywgdGhpcyBmdW5jdGlvbiBtYXkgcmV0dXJuIGluY29ycmVjdCBzbHVnc1xuICAgKi9cbiAgZnVuY3Rpb24gZ2V0Q29sbGVjdGlvblNsdWcobW9kZWw6IHN0cmluZyk6IENvbGxlY3Rpb25TbHVnIHtcbiAgICAvLyBGaXJzdCB0cnkgdG8gZ2V0IHRoZSBtb2RlbE5hbWUgZnJvbSBzY2hlbWEsIG90aGVyd2lzZSBmYWxsIGJhY2sgdG8gdGhlIG9yaWdpbmFsIG1vZGVsIG5hbWVcbiAgICBjb25zdCBjb2xsZWN0aW9uID0gc2NoZW1hW21vZGVsXT8ubW9kZWxOYW1lIHx8IG1vZGVsXG4gICAgZGVidWdMb2coWydnZXRDb2xsZWN0aW9uU2x1ZzonLCB7IG1vZGVsLCByZXNvbHZlZFNsdWc6IGNvbGxlY3Rpb24gfV0pXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24gYXMgQ29sbGVjdGlvblNsdWdcbiAgfVxuXG4gIC8qKlxuICAgKiBNYXBzIGEgQmV0dGVyQXV0aCBzY2hlbWEgZmllbGQgdG8gaXRzIGNvcnJlc3BvbmRpbmcgUGF5bG9hZCBDTVMgZmllbGQgbmFtZS5cbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiByZXNvbHZlcyB0aGUgYXBwcm9wcmlhdGUgZmllbGQgbmFtZSBieTpcbiAgICogMS4gUHJlc2VydmluZyAnaWQnIG9yICdfaWQnIGZpZWxkcyBhcy1pcyAoc3BlY2lhbCBjYXNlIGhhbmRsaW5nKVxuICAgKiAyLiBMb29raW5nIHVwIHRoZSBmaWVsZCBpbiB0aGUgQmV0dGVyQXV0aCBzY2hlbWEgdG8gZmluZCBpdHMgY29uZmlndXJlZCBmaWVsZE5hbWVcbiAgICogMy4gRmFsbGluZyBiYWNrIHRvIHRoZSBvcmlnaW5hbCBmaWVsZCBuYW1lIGlmIG5vIG1hcHBpbmcgZXhpc3RzXG4gICAqXG4gICAqIEBwYXJhbSBtb2RlbCAtIFRoZSBCZXR0ZXJBdXRoIG1vZGVsIG5hbWUgY29udGFpbmluZyB0aGUgZmllbGRcbiAgICogQHBhcmFtIGZpZWxkIC0gVGhlIG9yaWdpbmFsIGZpZWxkIG5hbWUgdG8gcmVzb2x2ZVxuICAgKiBAcmV0dXJucyBUaGUgY29ycmVzcG9uZGluZyBQYXlsb2FkIENNUyBmaWVsZCBuYW1lXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIC8vIElmIHNjaGVtYVsndXNlciddLmZpZWxkc1snZW1haWwnXS5maWVsZE5hbWUgaXMgJ2VtYWlsQWRkcmVzcydcbiAgICogZ2V0RmllbGROYW1lKCd1c2VyJywgJ2VtYWlsJykgLy8gUmV0dXJucyAnZW1haWxBZGRyZXNzJ1xuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiAvLyBTcGVjaWFsIGNhc2UgZm9yIElEIGZpZWxkc1xuICAgKiBnZXRGaWVsZE5hbWUoJ3VzZXInLCAnaWQnKSAvLyBBbHdheXMgcmV0dXJucyAnaWQnXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIC8vIElmIGZpZWxkIGRvZXNuJ3QgZXhpc3QgaW4gc2NoZW1hIG9yIGhhcyBubyBmaWVsZE5hbWUgbWFwcGluZ1xuICAgKiBnZXRGaWVsZE5hbWUoJ3VzZXInLCAnY3VzdG9tJykgLy8gUmV0dXJucyAnY3VzdG9tJ1xuICAgKlxuICAgKiBAd2FybmluZyBJZiBhIGZpZWxkTmFtZSBpcyBvdmVycmlkZGVuIGluIHRoZSBwYXlsb2FkIGNvbGxlY3Rpb24gY29uZmlnIHVzaW5nIHRoZSBjb2xsZWN0aW9uT3ZlcnJpZGUgb3B0aW9uXG4gICAqIHdpdGhvdXQgdXBkYXRpbmcgdGhlIHNjaGVtYSBtYXBwaW5nLCB0aGlzIGZ1bmN0aW9uIG1heSByZXR1cm4gaW5jb3JyZWN0IGZpZWxkIG5hbWVzXG4gICAqL1xuICBmdW5jdGlvbiBnZXRGaWVsZE5hbWUobW9kZWw6IHN0cmluZywgZmllbGQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgLy8gU3BlY2lhbCBjYXNlOiAnaWQnIG9yICdfaWQnIGlzIGFsd2F5cyBwcmVzZXJ2ZWQgYXMtaXNcbiAgICBpZiAoWydpZCcsICdfaWQnXS5pbmNsdWRlcyhmaWVsZCkpIHtcbiAgICAgIHJldHVybiBmaWVsZFxuICAgIH1cblxuICAgIC8vIExvb2sgdXAgdGhlIGZpZWxkIGluIHRoZSBzY2hlbWFcbiAgICBjb25zdCBmaWVsZERlZmluaXRpb24gPSBzY2hlbWFbbW9kZWxdPy5maWVsZHNbZmllbGRdXG5cbiAgICAvLyBVc2UgdGhlIGNvbmZpZ3VyZWQgZmllbGROYW1lIGlmIGF2YWlsYWJsZSwgb3RoZXJ3aXNlIGZhbGwgYmFjayB0byBvcmlnaW5hbFxuICAgIGNvbnN0IGZpZWxkTmFtZSA9IGZpZWxkRGVmaW5pdGlvbj8uZmllbGROYW1lIHx8IGZpZWxkXG5cbiAgICAvLyBMb2cgdGhlIGZpZWxkIHJlc29sdXRpb24gZm9yIGRlYnVnZ2luZ1xuICAgIGRlYnVnTG9nKFsnZ2V0RmllbGQ6ICcsIHsgbW9kZWwsIG9yaWdpbmFsRmllbGQ6IGZpZWxkLCBmaWVsZE5hbWUgfV0pXG5cbiAgICByZXR1cm4gZmllbGROYW1lXG4gIH1cblxuICAvKipcbiAgICogRGV0ZXJtaW5lcyBpZiBhIGZpZWxkIGlzIGEgcmVsYXRpb25zaGlwIGZpZWxkIGJ5IGNoZWNraW5nIGZvciBhIHJlZmVyZW5jZXMgcHJvcGVydHkuXG4gICAqXG4gICAqIFJlbGF0aW9uc2hpcCBmaWVsZHMgaW4gdGhlIHNjaGVtYSBoYXZlIGEgJ3JlZmVyZW5jZXMnIHByb3BlcnR5IHRoYXQgcG9pbnRzIHRvIGFub3RoZXIgbW9kZWwuXG4gICAqIFRoaXMgZnVuY3Rpb24gY2hlY2tzIGlmIHRoaXMgcHJvcGVydHkgZXhpc3RzIHRvIGlkZW50aWZ5IHJlbGF0aW9uc2hpcCBmaWVsZHMuXG4gICAqXG4gICAqIEBwYXJhbSBmaWVsZEtleSAtIFRoZSBrZXkgb2YgdGhlIGZpZWxkIHRvIGNoZWNrIGluIHRoZSBzY2hlbWFcbiAgICogQHBhcmFtIHNjaGVtYUZpZWxkcyAtIE9iamVjdCBjb250YWluaW5nIGFsbCBmaWVsZHMgZnJvbSB0aGUgc2NoZW1hIGZvciBhIHNwZWNpZmljIG1vZGVsXG4gICAqIEByZXR1cm5zIFRydWUgaWYgdGhlIGZpZWxkIGlzIGEgcmVsYXRpb25zaGlwIGZpZWxkIChoYXMgcmVmZXJlbmNlcyksIGZhbHNlIG90aGVyd2lzZVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiAvLyBJZiBzY2hlbWEudXNlci5maWVsZHMucG9zdHMgaGFzIHsgcmVmZXJlbmNlczoge30gfVxuICAgKiBpc1JlbGF0aW9uc2hpcEZpZWxkKCdwb3N0cycsIHNjaGVtYS51c2VyLmZpZWxkcykgLy8gUmV0dXJucyB0cnVlXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIC8vIElmIHNjaGVtYS51c2VyLmZpZWxkcy5lbWFpbCBoYXMgbm8gcmVmZXJlbmNlcyBwcm9wZXJ0eVxuICAgKiBpc1JlbGF0aW9uc2hpcEZpZWxkKCdlbWFpbCcsIHNjaGVtYS51c2VyLmZpZWxkcykgLy8gUmV0dXJucyBmYWxzZVxuICAgKi9cbiAgZnVuY3Rpb24gaXNSZWxhdGlvbnNoaXBGaWVsZChmaWVsZEtleTogc3RyaW5nLCBzY2hlbWFGaWVsZHM6IFJlY29yZDxzdHJpbmcsIEZpZWxkQXR0cmlidXRlPEZpZWxkVHlwZT4+KTogYm9vbGVhbiB7XG4gICAgLy8gQSBmaWVsZCBpcyBhIHJlbGF0aW9uc2hpcCBmaWVsZCBpZiBpdCBoYXMgYSAncmVmZXJlbmNlcycgcHJvcGVydHkgZGVmaW5lZFxuICAgIHJldHVybiBzY2hlbWFGaWVsZHNbZmllbGRLZXldPy5yZWZlcmVuY2VzICE9PSB1bmRlZmluZWRcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIGlmIGEgdmFsdWUgaXMgYSB2YWxpZCBkYXRlIHN0cmluZyB0aGF0IGNhbiBiZSBwYXJzZWQgaW50byBhIERhdGUgb2JqZWN0LlxuICAgKlxuICAgKiBUaGlzIHV0aWxpdHkgZnVuY3Rpb24gY2hlY2tzIGlmIGEgdmFsdWUgaXMgYSBzdHJpbmcgYW5kIGNhbiBiZSBzdWNjZXNzZnVsbHkgcGFyc2VkXG4gICAqIGludG8gYSBKYXZhU2NyaXB0IERhdGUgb2JqZWN0IHVzaW5nIERhdGUucGFyc2UoKS4gSXQncyB1c2VkIHRvIGlkZW50aWZ5IGRhdGUgZmllbGRzXG4gICAqIGR1cmluZyBkYXRhIHRyYW5zZm9ybWF0aW9uIHByb2Nlc3Nlcy5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIHRvIGNoZWNrIGlmIGl0J3MgYSB2YWxpZCBkYXRlIHN0cmluZ1xuICAgKiBAcmV0dXJucyBUcnVlIGlmIHRoZSB2YWx1ZSBpcyBhIHN0cmluZyB0aGF0IGNhbiBiZSBwYXJzZWQgYXMgYSBkYXRlLCBmYWxzZSBvdGhlcndpc2VcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogLy8gUmV0dXJucyB0cnVlIGZvciBJU08gZGF0ZSBzdHJpbmdzXG4gICAqIGlzRGF0ZUZpZWxkKCcyMDIzLTAxLTAxVDEyOjAwOjAwWicpIC8vIHRydWVcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogLy8gUmV0dXJucyBmYWxzZSBmb3Igbm9uLWRhdGUgc3RyaW5ncyBvciBvdGhlciB0eXBlc1xuICAgKiBpc0RhdGVGaWVsZCgnbm90IGEgZGF0ZScpIC8vIGZhbHNlXG4gICAqIGlzRGF0ZUZpZWxkKDEyMykgLy8gZmFsc2VcbiAgICovXG4gIGZ1bmN0aW9uIGlzRGF0ZUZpZWxkKHZhbHVlOiBhbnkpOiBib29sZWFuIHtcbiAgICAvLyBDaGVjayBpZiB2YWx1ZSBpcyBhIHN0cmluZyBhbmQgY2FuIGJlIHBhcnNlZCBhcyBhIHZhbGlkIGRhdGVcbiAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiAhaXNOYU4oRGF0ZS5wYXJzZSh2YWx1ZSkpXG4gIH1cblxuICAvKipcbiAgICogRXh0cmFjdHMgYSBzaW5nbGUgSUQgdmFsdWUgZnJvbSBhIFBheWxvYWQgd2hlcmUgY2xhdXNlIGlmIGl0IHJlcHJlc2VudHMgYSBzaW1wbGUgSUQgcXVlcnkuXG4gICAqXG4gICAqIFRoaXMgZnVuY3Rpb24gYW5hbHl6ZXMgYSBQYXlsb2FkIHdoZXJlIGNsYXVzZSB0byBkZXRlcm1pbmUgaWYgaXQncyBhIHNpbXBsZSBxdWVyeSBmb3IgYVxuICAgKiBzaW5nbGUgZG9jdW1lbnQgYnkgSUQuIEl0IHN1cHBvcnRzIGJvdGggJ2lkJyBhbmQgJ19pZCcgZmllbGRzIHdpdGggJ2VxdWFscycgb3IgJ2NvbnRhaW5zJ1xuICAgKiBvcGVyYXRvcnMuIFRoaXMgaXMgdXNlZnVsIGZvciBvcHRpbWl6aW5nIHF1ZXJpZXMgd2hlbiB3ZSBvbmx5IG5lZWQgdG8gZmV0Y2ggYSBzaW5nbGUgZG9jdW1lbnQuXG4gICAqXG4gICAqIEBwYXJhbSB3aGVyZSAtIFRoZSBQYXlsb2FkIHdoZXJlIGNsYXVzZSB0byBhbmFseXplXG4gICAqIEByZXR1cm5zIFRoZSBJRCB2YWx1ZSAoc3RyaW5nIG9yIG51bWJlcikgaWYgdGhlIHdoZXJlIGNsYXVzZSBpcyBhIHNpbXBsZSBJRCBxdWVyeSwgbnVsbCBvdGhlcndpc2VcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogLy8gUmV0dXJucyAnMTIzJyBmb3IgYSBzaW1wbGUgZXF1YWxzIHF1ZXJ5XG4gICAqIHNpbmdsZUlkUXVlcnkoeyBpZDogeyBlcXVhbHM6ICcxMjMnIH0gfSkgLy8gJzEyMydcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogLy8gUmV0dXJucyA0NTYgZm9yIGEgc2ltcGxlIGVxdWFscyBxdWVyeSB3aXRoIG51bWJlciBJRFxuICAgKiBzaW5nbGVJZFF1ZXJ5KHsgX2lkOiB7IGVxdWFsczogNDU2IH0gfSkgLy8gNDU2XG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIC8vIFJldHVybnMgJzc4OScgZm9yIGEgY29udGFpbnMgcXVlcnkgd2l0aCBhIHNpbmdsZSB2YWx1ZVxuICAgKiBzaW5nbGVJZFF1ZXJ5KHsgaWQ6IHsgY29udGFpbnM6IFsnNzg5J10gfSB9KSAvLyAnNzg5J1xuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiAvLyBSZXR1cm5zIG51bGwgZm9yIGNvbXBsZXggcXVlcmllc1xuICAgKiBzaW5nbGVJZFF1ZXJ5KHsgYW5kOiBbeyBpZDogeyBlcXVhbHM6ICcxMjMnIH0gfV0gfSkgLy8gbnVsbFxuICAgKi9cbiAgZnVuY3Rpb24gc2luZ2xlSWRRdWVyeSh3aGVyZTogUGF5bG9hZFdoZXJlKSB7XG4gICAgLy8gUmV0dXJuIG51bGwgZm9yIGVtcHR5IHdoZXJlIGNsYXVzZXMgb3IgY29tcGxleCBxdWVyaWVzIHdpdGggJ2FuZCcvJ29yJyBvcGVyYXRvcnNcbiAgICBpZiAoIXdoZXJlIHx8ICdhbmQnIGluIHdoZXJlIHx8ICdvcicgaW4gd2hlcmUpIHJldHVybiBudWxsXG5cbiAgICAvLyBDaGVjayBpZiB0aGUgd2hlcmUgY2xhdXNlIGNvbnRhaW5zIGVpdGhlciAnaWQnIG9yICdfaWQnIGZpZWxkXG4gICAgaWYgKFsnaWQnLCAnX2lkJ10uc29tZSgoZmllbGQpID0+IGZpZWxkIGluIHdoZXJlKSkge1xuICAgICAgLy8gRGV0ZXJtaW5lIHdoaWNoIElEIGZpZWxkIGlzIGJlaW5nIHVzZWQgKHN1cHBvcnQgYm90aCAnaWQnIGFuZCAnX2lkJylcbiAgICAgIGNvbnN0IGlkRmllbGQgPSAnaWQnIGluIHdoZXJlID8gJ2lkJyA6ICdfaWQnXG4gICAgICBjb25zdCBjb25kaXRpb24gPSB3aGVyZVtpZEZpZWxkXVxuXG4gICAgICAvLyBQcm9jZXNzIHRoZSBlcXVhbHMgb3BlcmF0b3IgY2FzZVxuICAgICAgaWYgKGNvbmRpdGlvbiAmJiB0eXBlb2YgY29uZGl0aW9uID09PSAnb2JqZWN0JyAmJiAhQXJyYXkuaXNBcnJheShjb25kaXRpb24pICYmICdlcXVhbHMnIGluIGNvbmRpdGlvbikge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGNvbmRpdGlvbi5lcXVhbHNcbiAgICAgICAgLy8gT25seSByZXR1cm4gc3RyaW5nIG9yIG51bWJlciBJRCB2YWx1ZXNcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgICAgIHJldHVybiB2YWx1ZVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIFByb2Nlc3MgdGhlIGNvbnRhaW5zIG9wZXJhdG9yIGNhc2Ugd2l0aCBhIHNpbmdsZSB2YWx1ZVxuICAgICAgaWYgKFxuICAgICAgICBjb25kaXRpb24gJiZcbiAgICAgICAgdHlwZW9mIGNvbmRpdGlvbiA9PT0gJ29iamVjdCcgJiZcbiAgICAgICAgIUFycmF5LmlzQXJyYXkoY29uZGl0aW9uKSAmJlxuICAgICAgICAnY29udGFpbnMnIGluIGNvbmRpdGlvbiAmJlxuICAgICAgICBBcnJheS5pc0FycmF5KGNvbmRpdGlvbi5jb250YWlucykgJiZcbiAgICAgICAgY29uZGl0aW9uLmNvbnRhaW5zLmxlbmd0aCA9PT0gMVxuICAgICAgKSB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gY29uZGl0aW9uLmNvbnRhaW5zWzBdXG4gICAgICAgIC8vIE9ubHkgcmV0dXJuIHN0cmluZyBvciBudW1iZXIgSUQgdmFsdWVzXG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICByZXR1cm4gdmFsdWVcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFJldHVybiBudWxsIGlmIG5vIHZhbGlkIElEIHF1ZXJ5IHdhcyBmb3VuZFxuICAgIHJldHVybiBudWxsXG4gIH1cblxuICAvKipcbiAgICogTm9ybWFsaXplcyBkYXRhIHZhbHVlcyBiYXNlZCBvbiBmaWVsZCB0eXBlIGFuZCByZXF1aXJlZCBJRCB0eXBlXG4gICAqXG4gICAqIFRoaXMgZnVuY3Rpb24gaGFuZGxlcyB0eXBlIGNvbnZlcnNpb24gZm9yIHJlbGF0aW9uc2hpcCBmaWVsZHMgdG8gZW5zdXJlXG4gICAqIElEcyBhcmUgaW4gdGhlIGNvcnJlY3QgZm9ybWF0IChzdHJpbmcgb3IgbnVtYmVyKSBiYXNlZCBvbiB0aGUgY29uZmlndXJhdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIGtleSAtIFRoZSBmaWVsZCBrZXkvbmFtZVxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgdG8gbm9ybWFsaXplXG4gICAqIEBwYXJhbSBpc1JlbGF0ZWRGaWVsZCAtIFdoZXRoZXIgdGhpcyBmaWVsZCBpcyBhIHJlbGF0aW9uc2hpcCBmaWVsZFxuICAgKiBAcGFyYW0gaWRUeXBlIC0gVGhlIGV4cGVjdGVkIElEIHR5cGUgKCdudW1iZXInIG9yICd0ZXh0JylcbiAgICogQHJldHVybnMgVGhlIG5vcm1hbGl6ZWQgdmFsdWVcbiAgICovXG4gIGZ1bmN0aW9uIG5vcm1hbGl6ZURhdGEoe1xuICAgIGtleSxcbiAgICB2YWx1ZSxcbiAgICBpc1JlbGF0ZWRGaWVsZCxcbiAgICBpZFR5cGVcbiAgfToge1xuICAgIGtleTogc3RyaW5nXG4gICAgdmFsdWU6IGFueVxuICAgIGlzUmVsYXRlZEZpZWxkOiBib29sZWFuXG4gICAgaWRUeXBlOiAnbnVtYmVyJyB8ICd0ZXh0J1xuICB9KSB7XG4gICAgLy8gU2tpcCBwcm9jZXNzaW5nIGZvciBudWxsL3VuZGVmaW5lZCB2YWx1ZXNcbiAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHZhbHVlXG4gICAgfVxuXG4gICAgaWYgKFsnaWQnLCAnX2lkJ10uaW5jbHVkZXMoa2V5KSkge1xuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgaWRUeXBlID09PSAnbnVtYmVyJykge1xuICAgICAgICBjb25zdCBwYXJzZWQgPSBwYXJzZUludCh2YWx1ZSwgMTApXG4gICAgICAgIGlmICghaXNOYU4ocGFyc2VkKSkge1xuICAgICAgICAgIGRlYnVnTG9nKFtgSUQgY29udmVyc2lvbjogJHtrZXl9IGNvbnZlcnRpbmcgc3RyaW5nIElEIHRvIG51bWJlcmAsIHsgb3JpZ2luYWw6IHZhbHVlLCBjb252ZXJ0ZWQ6IHBhcnNlZCB9XSlcbiAgICAgICAgICByZXR1cm4gcGFyc2VkXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInICYmIGlkVHlwZSA9PT0gJ3RleHQnKSB7XG4gICAgICAgIGNvbnN0IHN0cmluZ0lkID0gU3RyaW5nKHZhbHVlKVxuICAgICAgICBkZWJ1Z0xvZyhbYElEIGNvbnZlcnNpb246ICR7a2V5fSBjb252ZXJ0aW5nIG51bWJlciBJRCB0byBzdHJpbmdgLCB7IG9yaWdpbmFsOiB2YWx1ZSwgY29udmVydGVkOiBzdHJpbmdJZCB9XSlcbiAgICAgICAgcmV0dXJuIHN0cmluZ0lkXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gT25seSBwcm9jZXNzIHJlbGF0aW9uc2hpcCBmaWVsZHMgdGhhdCBuZWVkIHR5cGUgY29udmVyc2lvblxuICAgIGlmIChpc1JlbGF0ZWRGaWVsZCkge1xuICAgICAgLy8gSGFuZGxlIHNpbmdsZSBJRCB2YWx1ZSBjb252ZXJzaW9uXG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiBpZFR5cGUgPT09ICdudW1iZXInKSB7XG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlSW50KHZhbHVlLCAxMClcbiAgICAgICAgaWYgKCFpc05hTihwYXJzZWQpKSB7XG4gICAgICAgICAgZGVidWdMb2coW2BJRCBjb252ZXJzaW9uOiAke2tleX0gY29udmVydGluZyBzdHJpbmcgSUQgdG8gbnVtYmVyYCwgeyBvcmlnaW5hbDogdmFsdWUsIGNvbnZlcnRlZDogcGFyc2VkIH1dKVxuICAgICAgICAgIHJldHVybiBwYXJzZWRcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInICYmIGlkVHlwZSA9PT0gJ3RleHQnKSB7XG4gICAgICAgIGNvbnN0IHN0cmluZ0lkID0gU3RyaW5nKHZhbHVlKVxuICAgICAgICBkZWJ1Z0xvZyhbYElEIGNvbnZlcnNpb246ICR7a2V5fSBjb252ZXJ0aW5nIG51bWJlciBJRCB0byBzdHJpbmdgLCB7IG9yaWdpbmFsOiB2YWx1ZSwgY29udmVydGVkOiBzdHJpbmdJZCB9XSlcbiAgICAgICAgcmV0dXJuIHN0cmluZ0lkXG4gICAgICB9XG5cbiAgICAgIC8vIEhhbmRsZSBhcnJheSBvZiBJRHMgLSBtYXAgZWFjaCB2YWx1ZSB0byB0aGUgY29ycmVjdCB0eXBlXG4gICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlLm1hcCgoaWQpID0+IHtcbiAgICAgICAgICAvLyBTa2lwIG51bGwvdW5kZWZpbmVkIHZhbHVlcyBpbiBhcnJheXNcbiAgICAgICAgICBpZiAoaWQgPT09IG51bGwgfHwgaWQgPT09IHVuZGVmaW5lZCkgcmV0dXJuIGlkXG5cbiAgICAgICAgICBpZiAoaWRUeXBlID09PSAnbnVtYmVyJyAmJiB0eXBlb2YgaWQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBjb25zdCBwYXJzZWQgPSBwYXJzZUludChpZCwgMTApXG4gICAgICAgICAgICByZXR1cm4gIWlzTmFOKHBhcnNlZCkgPyBwYXJzZWQgOiBpZFxuICAgICAgICAgIH0gZWxzZSBpZiAoaWRUeXBlID09PSAndGV4dCcgJiYgdHlwZW9mIGlkID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgcmV0dXJuIFN0cmluZyhpZClcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGlkXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gUmV0dXJuIG9yaWdpbmFsIHZhbHVlIGlmIG5vIGNvbnZlcnNpb24gd2FzIG5lZWRlZCBvciBhcHBsaWNhYmxlXG4gICAgcmV0dXJuIHZhbHVlXG4gIH1cblxuICAvKipcbiAgICogVHJhbnNmb3JtcyBpbnB1dCBkYXRhIGZyb20gYmV0dGVyLWF1dGggdG8gUGF5bG9hZCBDTVMgZm9ybWF0XG4gICAqXG4gICAqIFRoaXMgZnVuY3Rpb24gaGFuZGxlczpcbiAgICogMS4gRmllbGQgbmFtZSBtYXBwaW5nIGFjY29yZGluZyB0byBzY2hlbWEgZGVmaW5pdGlvbnNcbiAgICogMi4gSUQgdHlwZSBjb252ZXJzaW9uIGZvciByZWxhdGlvbnNoaXAgZmllbGRzXG4gICAqIDMuIFByb3BlciBkYXRhIG5vcm1hbGl6YXRpb24gYmFzZWQgb24gZmllbGQgdHlwZXNcbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBUaGUgaW5wdXQgZGF0YSBmcm9tIGJldHRlci1hdXRoXG4gICAqIEBwYXJhbSBtb2RlbCAtIFRoZSBtb2RlbCBuYW1lIGluIHRoZSBzY2hlbWFcbiAgICogQHBhcmFtIGlkVHlwZSAtIFRoZSBleHBlY3RlZCBJRCB0eXBlICgnbnVtYmVyJyBvciAndGV4dCcpXG4gICAqIEByZXR1cm5zIFRyYW5zZm9ybWVkIGRhdGEgY29tcGF0aWJsZSB3aXRoIFBheWxvYWQgQ01TXG4gICAqL1xuICBmdW5jdGlvbiB0cmFuc2Zvcm1JbnB1dCh7XG4gICAgZGF0YSxcbiAgICBtb2RlbCxcbiAgICBpZFR5cGVcbiAgfToge1xuICAgIGRhdGE6IFJlY29yZDxzdHJpbmcsIGFueT5cbiAgICBtb2RlbDogc3RyaW5nXG4gICAgaWRUeXBlOiAnbnVtYmVyJyB8ICd0ZXh0J1xuICB9KTogUmVjb3JkPHN0cmluZywgYW55PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWREYXRhOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge31cbiAgICBjb25zdCBzY2hlbWFGaWVsZHMgPSBzY2hlbWFbbW9kZWxdLmZpZWxkc1xuXG4gICAgLy8gUHJvY2VzcyBlYWNoIGZpZWxkIGluIHRoZSBpbnB1dCBkYXRhXG4gICAgT2JqZWN0LmVudHJpZXMoZGF0YSkuZm9yRWFjaCgoW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgICAvLyBTa2lwIG51bGwvdW5kZWZpbmVkIHZhbHVlc1xuICAgICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG5cbiAgICAgIC8vIERldGVybWluZSBpZiB0aGlzIGlzIGEgcmVsYXRpb25zaGlwIGZpZWxkXG4gICAgICBjb25zdCBpc1JlbGF0ZWRGaWVsZCA9IGlzUmVsYXRpb25zaGlwRmllbGQoa2V5LCBzY2hlbWFGaWVsZHMpXG5cbiAgICAgIC8vIEdldCB0aGUgbWFwcGVkIGZpZWxkIG5hbWUgZnJvbSBzY2hlbWEgKGlmIGFueSlcbiAgICAgIGNvbnN0IHNjaGVtYUZpZWxkTmFtZSA9IHNjaGVtYUZpZWxkc1trZXldPy5maWVsZE5hbWVcblxuICAgICAgLy8gTm9ybWFsaXplIHRoZSBkYXRhIHZhbHVlIGJhc2VkIG9uIGZpZWxkIHR5cGUgYW5kIElEIHR5cGVcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWREYXRhID0gbm9ybWFsaXplRGF0YSh7XG4gICAgICAgIGlkVHlwZSxcbiAgICAgICAga2V5LFxuICAgICAgICB2YWx1ZSxcbiAgICAgICAgaXNSZWxhdGVkRmllbGRcbiAgICAgIH0pXG5cbiAgICAgIC8vIFVzZSB0aGUgc2NoZW1hLWRlZmluZWQgZmllbGQgbmFtZSBpZiBhdmFpbGFibGUsIG90aGVyd2lzZSB1c2Ugb3JpZ2luYWwga2V5XG4gICAgICBjb25zdCB0YXJnZXRGaWVsZE5hbWUgPSBzY2hlbWFGaWVsZE5hbWUgfHwga2V5XG4gICAgICB0cmFuc2Zvcm1lZERhdGFbdGFyZ2V0RmllbGROYW1lXSA9IG5vcm1hbGl6ZWREYXRhXG4gICAgfSlcblxuICAgIHJldHVybiB0cmFuc2Zvcm1lZERhdGFcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmFuc2Zvcm1zIFBheWxvYWQgQ01TIGRvY3VtZW50IG91dHB1dCB0byBtYXRjaCBCZXR0ZXJBdXRoIHNjaGVtYSBleHBlY3RhdGlvbnMuXG4gICAqXG4gICAqIFRoaXMgZnVuY3Rpb24gaGFuZGxlcyBzZXZlcmFsIGNyaXRpY2FsIHRyYW5zZm9ybWF0aW9uczpcbiAgICpcbiAgICogMS4gSUQgQ29udmVyc2lvbjogRW5zdXJlcyBhbGwgSUQgZmllbGRzIGFyZSBzdHJpbmdzIGFzIHJlcXVpcmVkIGJ5IEJldHRlckF1dGhcbiAgICogICAgKHNlZTogaHR0cHM6Ly9naXRodWIuY29tL2JldHRlci1hdXRoL2JldHRlci1hdXRoL2Jsb2IvbWFpbi9wYWNrYWdlcy9iZXR0ZXItYXV0aC9zcmMvZGIvc2NoZW1hLnRzI0wxMjUpXG4gICAqXG4gICAqIDIuIFJlbGF0aW9uc2hpcCBGaWVsZCBNYXBwaW5nOiBBbGlnbnMgcmVsYXRpb25zaGlwIGZpZWxkcyB3aXRoIEJldHRlckF1dGggc2NoZW1hIG5hbWluZyBjb252ZW50aW9uc1xuICAgKiAgICBhbmQgZW5zdXJlcyBwcm9wZXIgSUQgdHlwZSBoYW5kbGluZ1xuICAgKlxuICAgKiAzLiBEYXRlIENvbnZlcnNpb246IFRyYW5zZm9ybXMgZGF0ZSBzdHJpbmdzIGZyb20gUGF5bG9hZCBpbnRvIERhdGUgb2JqZWN0cyBmb3IgQmV0dGVyQXV0aFxuICAgKlxuICAgKiBOb3RlOiBXaGlsZSBzZXR0aW5nIGRlcHRoOiAxIGluIFBheWxvYWQgb3BlcmF0aW9ucyBzaW1wbGlmaWVzIHRoaXMgcHJvY2VzcyBieSBhdm9pZGluZ1xuICAgKiBkZWVwbHkgbmVzdGVkIG9iamVjdHMsIHdlIG1haW50YWluIGNvbXByZWhlbnNpdmUgY2hlY2tzIGZvciByb2J1c3RuZXNzLlxuICAgKlxuICAgKiBAcGFyYW0gZG9jIC0gVGhlIGRvY3VtZW50IHJldHVybmVkIGZyb20gUGF5bG9hZCBDTVNcbiAgICogQHBhcmFtIG1vZGVsIC0gVGhlIG1vZGVsIG5hbWUgaW4gdGhlIEJldHRlckF1dGggc2NoZW1hXG4gICAqIEByZXR1cm5zIFRoZSB0cmFuc2Zvcm1lZCBkb2N1bWVudCBjb21wYXRpYmxlIHdpdGggQmV0dGVyQXV0aFxuICAgKi9cbiAgZnVuY3Rpb24gdHJhbnNmb3JtT3V0cHV0PFQgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCBhbnk+IHwgbnVsbD4oeyBkb2MsIG1vZGVsIH06IHsgZG9jOiBUOyBtb2RlbDogc3RyaW5nIH0pOiBUIHtcbiAgICBpZiAoIWRvYyB8fCB0eXBlb2YgZG9jICE9PSAnb2JqZWN0JykgcmV0dXJuIGRvY1xuXG4gICAgY29uc3QgcmVzdWx0ID0geyAuLi5kb2MgfVxuICAgIGNvbnN0IHNjaGVtYUZpZWxkcyA9IHNjaGVtYVttb2RlbF0uZmllbGRzXG5cbiAgICAvLyBJZGVudGlmeSByZWxhdGlvbnNoaXAgZmllbGRzIHdpdGggY3VzdG9tIGZpZWxkIG5hbWUgbWFwcGluZ3NcbiAgICBjb25zdCByZWxhdGlvbnNoaXBGaWVsZHMgPSBPYmplY3QuZnJvbUVudHJpZXMoT2JqZWN0LmVudHJpZXMoc2NoZW1hRmllbGRzKS5maWx0ZXIoKFtrZXldKSA9PiBpc1JlbGF0aW9uc2hpcEZpZWxkKGtleSwgc2NoZW1hRmllbGRzKSkpXG5cbiAgICBPYmplY3QuZW50cmllcyhkb2MpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4ge1xuICAgICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQpIHJldHVyblxuXG4gICAgICAvLyBDb252ZXJ0IElEIGZpZWxkcyB0byBzdHJpbmdzIGZvciBCZXR0ZXJBdXRoIGNvbXBhdGliaWxpdHlcbiAgICAgIGlmIChbJ2lkJywgJ19pZCddLmluY2x1ZGVzKGtleSkpIHtcbiAgICAgICAgcmVzdWx0W2tleV0gPSBTdHJpbmcodmFsdWUpXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICAvLyBIYW5kbGUgcmVsYXRpb25zaGlwIGZpZWxkcyB3aXRoIHJlbmFtZWQgZmllbGROYW1lc1xuICAgICAgY29uc3Qgb3JpZ2luYWxSZWxhdGVkRmllbGRLZXkgPSBPYmplY3Qua2V5cyhyZWxhdGlvbnNoaXBGaWVsZHMpLmZpbmQoKGspID0+IHJlbGF0aW9uc2hpcEZpZWxkc1trXS5maWVsZE5hbWUgPT09IGtleSlcbiAgICAgIGlmIChvcmlnaW5hbFJlbGF0ZWRGaWVsZEtleSkge1xuICAgICAgICBub3JtYWxpemVEb2N1bWVudElkcyhyZXN1bHQsIG9yaWdpbmFsUmVsYXRlZEZpZWxkS2V5LCBrZXksIHZhbHVlKVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgLy8gQ29udmVydCBJU08gZGF0ZSBzdHJpbmdzIHRvIERhdGUgb2JqZWN0cyBmb3IgQmV0dGVyQXV0aFxuICAgICAgaWYgKGlzRGF0ZUZpZWxkKHZhbHVlKSkge1xuICAgICAgICByZXN1bHRba2V5XSA9IG5ldyBEYXRlKHZhbHVlKVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cbiAgICB9KVxuXG4gICAgcmV0dXJuIHJlc3VsdCBhcyBUXG4gIH1cblxuICAvKipcbiAgICogTm9ybWFsaXplcyBJRCBmaWVsZHMgZm9yIGJvdGggcHJpbWFyeSBhbmQgcmVsYXRpb25zaGlwIGRvY3VtZW50cy5cbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiBlbnN1cmVzIGNvbnNpc3RlbnQgSUQgaGFuZGxpbmcgYmV0d2VlbiBCZXR0ZXJBdXRoIGFuZCBQYXlsb2FkIENNUyBieTpcbiAgICogMS4gQ29udmVydGluZyBhbGwgSURzIHRvIHN0cmluZ3MgZm9yIEJldHRlckF1dGggKHN0b3JlZCBpbiBvcmlnaW5hbEtleSlcbiAgICogMi4gUHJlc2VydmluZyBvcmlnaW5hbCBJRCB0eXBlcyBmb3IgUGF5bG9hZCBDTVMgKHN0b3JlZCBpbiBmaWVsZE5hbWUpXG4gICAqXG4gICAqIFRoZSBmdW5jdGlvbiBoYW5kbGVzIHZhcmlvdXMgSUQgZm9ybWF0czpcbiAgICogLSBQcmltaXRpdmUgdmFsdWVzIChzdHJpbmcvbnVtYmVyIElEcylcbiAgICogLSBPYmplY3QgcmVmZXJlbmNlcyB3aXRoIElEIHByb3BlcnRpZXNcbiAgICogLSBBcnJheXMgb2YgZWl0aGVyIHByaW1pdGl2ZSBJRHMgb3Igb2JqZWN0IHJlZmVyZW5jZXNcbiAgICpcbiAgICogQHBhcmFtIHJlc3VsdCAtIFRoZSByZXN1bHQgb2JqZWN0IGJlaW5nIHRyYW5zZm9ybWVkXG4gICAqIEBwYXJhbSBvcmlnaW5hbEtleSAtIFRoZSBvcmlnaW5hbCBmaWVsZCBrZXkgZnJvbSBCZXR0ZXJBdXRoIHNjaGVtYVxuICAgKiBAcGFyYW0gZmllbGROYW1lIC0gVGhlIHJlbmFtZWQgZmllbGQgYXMgdXNlZCBpbiBQYXlsb2FkIENNU1xuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgSUQgdmFsdWUgdG8gbm9ybWFsaXplIChwcmltaXRpdmUsIG9iamVjdCwgb3IgYXJyYXkpXG4gICAqL1xuICBmdW5jdGlvbiBub3JtYWxpemVEb2N1bWVudElkcyhyZXN1bHQ6IFJlY29yZDxzdHJpbmcsIGFueT4sIG9yaWdpbmFsS2V5OiBzdHJpbmcsIGZpZWxkTmFtZTogc3RyaW5nLCB2YWx1ZTogYW55KTogdm9pZCB7XG4gICAgLy8gQ2FzZSAxOiBQcmltaXRpdmUgSUQgdmFsdWUgKHN0cmluZyBvciBudW1iZXIpXG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgLy8gRm9yIEJldHRlckF1dGg6IEFsd2F5cyB1c2Ugc3RyaW5nIElEc1xuICAgICAgcmVzdWx0W29yaWdpbmFsS2V5XSA9IFN0cmluZyh2YWx1ZSlcbiAgICAgIC8vIEZvciBQYXlsb2FkOiBLZWVwIG9yaWdpbmFsIHR5cGVcbiAgICAgIHJlc3VsdFtmaWVsZE5hbWVdID0gdmFsdWVcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIC8vIENhc2UgMjogT2JqZWN0IHdpdGggSUQgcHJvcGVydHlcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZSAhPT0gbnVsbCAmJiAnaWQnIGluIHZhbHVlKSB7XG4gICAgICAvLyBGb3IgQmV0dGVyQXV0aDogRXh0cmFjdCBhbmQgc3RyaW5naWZ5IHRoZSBJRFxuICAgICAgcmVzdWx0W29yaWdpbmFsS2V5XSA9IFN0cmluZyh2YWx1ZS5pZClcbiAgICAgIC8vIEZvciBQYXlsb2FkOiBFeHRyYWN0IElEIGJ1dCBwcmVzZXJ2ZSB0eXBlXG4gICAgICByZXN1bHRbZmllbGROYW1lXSA9IHZhbHVlLmlkXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICAvLyBDYXNlIDM6IEFycmF5IG9mIElEcyBvciByZWZlcmVuY2VzXG4gICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpICYmIHZhbHVlLmxlbmd0aCA+IDApIHtcbiAgICAgIC8vIENoZWNrIGlmIGFycmF5IGNvbnRhaW5zIG9iamVjdHMgd2l0aCBJRCBwcm9wZXJ0aWVzXG4gICAgICBpZiAodmFsdWUuZXZlcnkoKGl0ZW0pID0+IHR5cGVvZiBpdGVtID09PSAnb2JqZWN0JyAmJiBpdGVtICE9PSBudWxsICYmICdpZCcgaW4gaXRlbSkpIHtcbiAgICAgICAgLy8gQXJyYXkgb2Ygb2JqZWN0cyB3aXRoIElEc1xuICAgICAgICByZXN1bHRbb3JpZ2luYWxLZXldID0gdmFsdWUubWFwKChpdGVtKSA9PiBTdHJpbmcoaXRlbS5pZCkpXG4gICAgICAgIHJlc3VsdFtmaWVsZE5hbWVdID0gdmFsdWUubWFwKChpdGVtKSA9PiBpdGVtLmlkKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gQXJyYXkgb2YgcHJpbWl0aXZlIElEc1xuICAgICAgICByZXN1bHRbb3JpZ2luYWxLZXldID0gdmFsdWUubWFwKChpdGVtKSA9PiBTdHJpbmcoaXRlbSkpXG4gICAgICAgIHJlc3VsdFtmaWVsZE5hbWVdID0gdmFsdWUubWFwKChpdGVtKSA9PiBpdGVtKVxuICAgICAgfVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgLy8gTm90ZTogSWYgdmFsdWUgZG9lc24ndCBtYXRjaCBhbnkgZXhwZWN0ZWQgZm9ybWF0LCBubyBjaGFuZ2VzIGFyZSBtYWRlXG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgYSBCZXR0ZXJBdXRoIG9wZXJhdG9yIHRvIHRoZSBlcXVpdmFsZW50IFBheWxvYWQgQ01TIHF1ZXJ5IG9wZXJhdG9yXG4gICAqXG4gICAqIFRoaXMgZnVuY3Rpb24gbWFwcyBzdGFuZGFyZCBxdWVyeSBvcGVyYXRvcnMgZnJvbSBCZXR0ZXJBdXRoJ3MgZm9ybWF0IHRvXG4gICAqIHRoZSBzcGVjaWZpYyBmb3JtYXQgZXhwZWN0ZWQgYnkgUGF5bG9hZCBDTVMncyBxdWVyeSBlbmdpbmUuXG4gICAqXG4gICAqIEBwYXJhbSBvcGVyYXRvciAtIFRoZSBCZXR0ZXJBdXRoIG9wZXJhdG9yIHN0cmluZyAoZS5nLiwgJ2VxJywgJ2d0JywgJ2NvbnRhaW5zJylcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIHRvIGJlIHVzZWQgd2l0aCB0aGUgb3BlcmF0b3JcbiAgICogQHJldHVybnMgQW4gb2JqZWN0IHdpdGggdGhlIFBheWxvYWQtY29tcGF0aWJsZSBvcGVyYXRvciBhbmQgdmFsdWVcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogLy8gUmV0dXJucyB7IGVxdWFsczogJ3Rlc3RAZXhhbXBsZS5jb20nIH1cbiAgICogb3BlcmF0b3JUb1BheWxvYWQoJ2VxJywgJ3Rlc3RAZXhhbXBsZS5jb20nKVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiAvLyBSZXR1cm5zIHsgZ3JlYXRlcl90aGFuOiAxMDAgfVxuICAgKiBvcGVyYXRvclRvUGF5bG9hZCgnZ3QnLCAxMDApXG4gICAqL1xuICBmdW5jdGlvbiBvcGVyYXRvclRvUGF5bG9hZChvcGVyYXRvcjogc3RyaW5nLCB2YWx1ZTogYW55KTogUmVjb3JkPHN0cmluZywgYW55PiB7XG4gICAgc3dpdGNoIChvcGVyYXRvcikge1xuICAgICAgY2FzZSAnZXEnOlxuICAgICAgICByZXR1cm4geyBlcXVhbHM6IHZhbHVlIH1cbiAgICAgIGNhc2UgJ25lJzpcbiAgICAgICAgcmV0dXJuIHsgbm90X2VxdWFsczogdmFsdWUgfVxuICAgICAgY2FzZSAnZ3QnOlxuICAgICAgICByZXR1cm4geyBncmVhdGVyX3RoYW46IHZhbHVlIH1cbiAgICAgIGNhc2UgJ2d0ZSc6XG4gICAgICAgIHJldHVybiB7IGdyZWF0ZXJfdGhhbl9lcXVhbDogdmFsdWUgfVxuICAgICAgY2FzZSAnbHQnOlxuICAgICAgICByZXR1cm4geyBsZXNzX3RoYW46IHZhbHVlIH1cbiAgICAgIGNhc2UgJ2x0ZSc6XG4gICAgICAgIHJldHVybiB7IGxlc3NfdGhhbl9lcXVhbDogdmFsdWUgfVxuICAgICAgY2FzZSAnY29udGFpbnMnOlxuICAgICAgICByZXR1cm4geyBjb250YWluczogdmFsdWUgfVxuICAgICAgY2FzZSAnaW4nOlxuICAgICAgICByZXR1cm4geyBpbjogdmFsdWUgfVxuICAgICAgY2FzZSAnc3RhcnRzX3dpdGgnOlxuICAgICAgICByZXR1cm4geyBsaWtlOiBgJHt2YWx1ZX0lYCB9XG4gICAgICBjYXNlICdlbmRzX3dpdGgnOlxuICAgICAgICByZXR1cm4geyBsaWtlOiBgJSR7dmFsdWV9YCB9XG4gICAgICBkZWZhdWx0OlxuICAgICAgICAvLyBGYWxsIGJhY2sgdG8gZXF1YWxzIGZvciB1bnJlY29nbml6ZWQgb3BlcmF0b3JzXG4gICAgICAgIHJldHVybiB7IGVxdWFsczogdmFsdWUgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhIHdoZXJlIGNsYXVzZSB2YWx1ZSB0byB0aGUgYXBwcm9wcmlhdGUgdHlwZSBiYXNlZCBvbiBmaWVsZCBuYW1lIGFuZCBJRCB0eXBlIGNvbmZpZ3VyYXRpb25cbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiBoYW5kbGVzIHR3byBtYWluIHNjZW5hcmlvczpcbiAgICogMS4gSUQgZmllbGQgY29udmVyc2lvbiAtIGVuc3VyZXMgSURzIG1hdGNoIHRoZSBkYXRhYmFzZSdzIGV4cGVjdGVkIHR5cGUgKG51bWJlciBvciBzdHJpbmcpXG4gICAqIDIuIE9iamVjdCB3aXRoIGVtYmVkZGVkIElEIC0gZXh0cmFjdHMgYW5kIGNvbnZlcnRzIHRoZSBJRCBwcm9wZXJ0eSBmcm9tIG9iamVjdHNcbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIHRvIGNvbnZlcnQgKGNhbiBiZSBwcmltaXRpdmUsIG9iamVjdCB3aXRoIElELCBvciBhcnJheSlcbiAgICogQHBhcmFtIGZpZWxkTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBmaWVsZCBiZWluZyBxdWVyaWVkXG4gICAqIEBwYXJhbSBpZFR5cGUgLSBUaGUgZXhwZWN0ZWQgSUQgdHlwZSBpbiB0aGUgZGF0YWJhc2VcbiAgICogQHJldHVybnMgVGhlIGNvbnZlcnRlZCB2YWx1ZSBhcHByb3ByaWF0ZSBmb3IgdGhlIGRhdGFiYXNlIHF1ZXJ5XG4gICAqL1xuICBmdW5jdGlvbiBjb252ZXJ0V2hlcmVWYWx1ZSh7IHZhbHVlLCBmaWVsZE5hbWUsIGlkVHlwZSB9OiB7IHZhbHVlOiBhbnk7IGZpZWxkTmFtZTogc3RyaW5nOyBpZFR5cGU6ICdudW1iZXInIHwgJ3RleHQnIH0pIHtcbiAgICAvLyBDaGVjayBpZiBmaWVsZCBpcyBhbiBJRCBmaWVsZCAoc3VwcG9ydGluZyBib3RoIE1vbmdvREItc3R5bGUgX2lkIGFuZCBzdGFuZGFyZCBpZClcbiAgICBpZiAoWydpZCcsICdfaWQnXS5pbmNsdWRlcyhmaWVsZE5hbWUpKSB7XG4gICAgICAvLyBDYXNlIDE6IFZhbHVlIGlzIGFuIG9iamVjdCBjb250YWluaW5nIGFuIElEIHByb3BlcnR5XG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZSAhPT0gbnVsbCAmJiAnaWQnIGluIHZhbHVlKSB7XG4gICAgICAgIC8vIEV4dHJhY3QgSUQgZnJvbSBvYmplY3RcbiAgICAgICAgY29uc3QgaWQgPSB2YWx1ZS5pZFxuXG4gICAgICAgIC8vIFVzZSB0eXBlIGNvbnZlcnNpb24gYmFzZWQgb24gZGF0YWJhc2UgY29uZmlndXJhdGlvblxuICAgICAgICBpZiAoaWRUeXBlID09PSAnbnVtYmVyJyAmJiB0eXBlb2YgaWQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgY29uc3QgbnVtSWQgPSBOdW1iZXIoaWQpXG4gICAgICAgICAgcmV0dXJuICFpc05hTihudW1JZCkgPyBudW1JZCA6IGlkXG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaWRUeXBlID09PSAndGV4dCcgJiYgdHlwZW9mIGlkID09PSAnbnVtYmVyJykge1xuICAgICAgICAgIHJldHVybiBTdHJpbmcoaWQpXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gaWRcbiAgICAgIH1cbiAgICAgIC8vIENhc2UgMjogVmFsdWUgaXMgYSBzdGFuZGFsb25lIElEIHRoYXQgbmVlZHMgdHlwZSBjb252ZXJzaW9uXG4gICAgICAvLyBDb252ZXJ0IHN0cmluZyBJRCB0byBudW1iZXIgaWYgZGF0YWJhc2UgZXhwZWN0cyBudW1lcmljIElEc1xuICAgICAgaWYgKGlkVHlwZSA9PT0gJ251bWJlcicgJiYgdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiAhaXNOYU4oTnVtYmVyKHZhbHVlKSkpIHtcbiAgICAgICAgcmV0dXJuIE51bWJlcih2YWx1ZSlcbiAgICAgIH1cbiAgICAgIC8vIENvbnZlcnQgbnVtZXJpYyBJRCB0byBzdHJpbmcgaWYgZGF0YWJhc2UgZXhwZWN0cyB0ZXh0IElEc1xuICAgICAgZWxzZSBpZiAoaWRUeXBlID09PSAndGV4dCcgJiYgdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgICByZXR1cm4gU3RyaW5nKHZhbHVlKVxuICAgICAgfVxuICAgICAgcmV0dXJuIHZhbHVlXG4gICAgfVxuXG4gICAgLy8gRm9yIG5vbi1JRCBmaWVsZHMsIHJldHVybiB0aGUgdmFsdWUgdW5jaGFuZ2VkXG4gICAgcmV0dXJuIHZhbHVlXG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgQmV0dGVyIEF1dGggd2hlcmUgY2xhdXNlcyB0byBQYXlsb2FkIENNUyBjb21wYXRpYmxlIHdoZXJlIGNvbmRpdGlvbnNcbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiB0cmFuc2Zvcm1zIHRoZSBCZXR0ZXIgQXV0aCBxdWVyeSBmb3JtYXQgaW50byBQYXlsb2FkJ3MgcXVlcnkgZm9ybWF0LFxuICAgKiBoYW5kbGluZyBmaWVsZCBuYW1lIG1hcHBpbmcsIHZhbHVlIHR5cGUgY29udmVyc2lvbiwgYW5kIGxvZ2ljYWwgb3BlcmF0b3JzIChBTkQvT1IpLlxuICAgKlxuICAgKiBUaGUgZnVuY3Rpb24gaGFuZGxlcyB0aHJlZSBtYWluIGNhc2VzOlxuICAgKiAxLiBFbXB0eSBvciB1bmRlZmluZWQgd2hlcmUgY2xhdXNlIC0gcmV0dXJucyBlbXB0eSBvYmplY3RcbiAgICogMi4gU2luZ2xlIGNvbmRpdGlvbiAtIGNvbnZlcnRzIHRvIGEgc2ltcGxlIGZpZWxkLXZhbHVlIHBhaXJcbiAgICogMy4gTXVsdGlwbGUgY29uZGl0aW9ucyAtIGdyb3VwcyBieSBBTkQvT1IgY29ubmVjdG9ycyBhbmQgYnVpbGRzIGEgY29tcGxleCBxdWVyeVxuICAgKlxuICAgKiBAcGFyYW0gaWRUeXBlIC0gVGhlIGRhdGFiYXNlIElEIHR5cGUgKCdudW1iZXInIG9yICd0ZXh0JylcbiAgICogQHBhcmFtIG1vZGVsIC0gVGhlIG1vZGVsL2NvbGxlY3Rpb24gbmFtZSB0byBxdWVyeVxuICAgKiBAcGFyYW0gd2hlcmUgLSBBcnJheSBvZiBCZXR0ZXIgQXV0aCB3aGVyZSBjb25kaXRpb25zXG4gICAqIEByZXR1cm5zIEEgUGF5bG9hZC1jb21wYXRpYmxlIHdoZXJlIGNsYXVzZSBvYmplY3RcbiAgICovXG4gIGZ1bmN0aW9uIGNvbnZlcnRXaGVyZUNsYXVzZSh7IGlkVHlwZSwgbW9kZWwsIHdoZXJlIH06IHsgaWRUeXBlOiAnbnVtYmVyJyB8ICd0ZXh0JzsgbW9kZWw6IHN0cmluZzsgd2hlcmU/OiBXaGVyZVtdIH0pOiBQYXlsb2FkV2hlcmUge1xuICAgIC8vIEhhbmRsZSBlbXB0eSB3aGVyZSBjbGF1c2VcbiAgICBpZiAoIXdoZXJlKSByZXR1cm4ge31cblxuICAgIC8vIEhhbmRsZSBzaW5nbGUgY29uZGl0aW9uIGNhc2UgZm9yIG9wdGltaXphdGlvblxuICAgIGlmICh3aGVyZS5sZW5ndGggPT09IDEpIHtcbiAgICAgIGNvbnN0IHcgPSB3aGVyZVswXVxuICAgICAgaWYgKCF3KSB7XG4gICAgICAgIHJldHVybiB7fVxuICAgICAgfVxuXG4gICAgICAvLyBNYXAgZmllbGQgbmFtZSBhY2NvcmRpbmcgdG8gc2NoZW1hIGFuZCBjb252ZXJ0IHZhbHVlIHRvIGFwcHJvcHJpYXRlIHR5cGVcbiAgICAgIGNvbnN0IGZpZWxkTmFtZSA9IGdldEZpZWxkTmFtZShtb2RlbCwgdy5maWVsZClcbiAgICAgIGNvbnN0IHZhbHVlID0gY29udmVydFdoZXJlVmFsdWUoe1xuICAgICAgICB2YWx1ZTogdy52YWx1ZSxcbiAgICAgICAgZmllbGROYW1lLFxuICAgICAgICBpZFR5cGVcbiAgICAgIH0pXG5cbiAgICAgIC8vIENyZWF0ZSB0aGUgUGF5bG9hZCB3aGVyZSBjb25kaXRpb24gd2l0aCBwcm9wZXIgb3BlcmF0b3JcbiAgICAgIGNvbnN0IHJlcyA9IHtcbiAgICAgICAgW2ZpZWxkTmFtZV06IG9wZXJhdG9yVG9QYXlsb2FkKHcub3BlcmF0b3IgPz8gJycsIHZhbHVlKVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzXG4gICAgfVxuXG4gICAgLy8gSGFuZGxlIG11bHRpcGxlIGNvbmRpdGlvbnMgYnkgc2VwYXJhdGluZyBBTkQvT1IgY2xhdXNlc1xuICAgIC8vIERlZmF1bHQgdG8gQU5EIGlmIG5vIGNvbm5lY3RvciBpcyBzcGVjaWZpZWRcbiAgICBjb25zdCBhbmQgPSB3aGVyZS5maWx0ZXIoKHcpID0+IHcuY29ubmVjdG9yID09PSAnQU5EJyB8fCAhdy5jb25uZWN0b3IpXG4gICAgY29uc3Qgb3IgPSB3aGVyZS5maWx0ZXIoKHcpID0+IHcuY29ubmVjdG9yID09PSAnT1InKVxuXG4gICAgLy8gUHJvY2VzcyBBTkQgY29uZGl0aW9uc1xuICAgIGNvbnN0IGFuZENsYXVzZSA9IGFuZC5tYXAoKHcpID0+IHtcbiAgICAgIGNvbnN0IGZpZWxkTmFtZSA9IGdldEZpZWxkTmFtZShtb2RlbCwgdy5maWVsZClcbiAgICAgIGNvbnN0IHZhbHVlID0gY29udmVydFdoZXJlVmFsdWUoe1xuICAgICAgICB2YWx1ZTogdy52YWx1ZSxcbiAgICAgICAgZmllbGROYW1lLFxuICAgICAgICBpZFR5cGVcbiAgICAgIH0pXG4gICAgICByZXR1cm4ge1xuICAgICAgICBbZmllbGROYW1lXTogb3BlcmF0b3JUb1BheWxvYWQody5vcGVyYXRvciA/PyAnJywgdmFsdWUpXG4gICAgICB9XG4gICAgfSlcblxuICAgIC8vIFByb2Nlc3MgT1IgY29uZGl0aW9uc1xuICAgIGNvbnN0IG9yQ2xhdXNlID0gb3IubWFwKCh3KSA9PiB7XG4gICAgICBjb25zdCBmaWVsZE5hbWUgPSBnZXRGaWVsZE5hbWUobW9kZWwsIHcuZmllbGQpXG4gICAgICBjb25zdCB2YWx1ZSA9IGNvbnZlcnRXaGVyZVZhbHVlKHtcbiAgICAgICAgdmFsdWU6IHcudmFsdWUsXG4gICAgICAgIGZpZWxkTmFtZSxcbiAgICAgICAgaWRUeXBlXG4gICAgICB9KVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgW2ZpZWxkTmFtZV06IG9wZXJhdG9yVG9QYXlsb2FkKHcub3BlcmF0b3IgPz8gJycsIHZhbHVlKVxuICAgICAgfVxuICAgIH0pXG5cbiAgICAvLyBDb21iaW5lIEFORCBhbmQgT1IgY2xhdXNlcyBpbnRvIGZpbmFsIFBheWxvYWQgd2hlcmUgb2JqZWN0XG4gICAgLy8gT25seSBpbmNsdWRlIG5vbi1lbXB0eSBjbGF1c2UgYXJyYXlzXG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLihhbmRDbGF1c2UubGVuZ3RoID8geyBBTkQ6IGFuZENsYXVzZSB9IDoge30pLFxuICAgICAgLi4uKG9yQ2xhdXNlLmxlbmd0aCA/IHsgT1I6IG9yQ2xhdXNlIH0gOiB7fSlcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgYSBiZXR0ZXItYXV0aCBzZWxlY3QgYXJyYXkgdG8gYSBQYXlsb2FkIHNlbGVjdCBvYmplY3RcbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiB0cmFuc2Zvcm1zIHRoZSBiZXR0ZXItYXV0aCBzZWxlY3QgYXJyYXkgKHdoaWNoIGNvbnRhaW5zIGZpZWxkIG5hbWVzKVxuICAgKiBpbnRvIHRoZSBmb3JtYXQgZXhwZWN0ZWQgYnkgUGF5bG9hZCBDTVMncyBxdWVyeSBBUEkgKGFuIG9iamVjdCB3aXRoIGZpZWxkIG5hbWVzIGFzIGtleXNcbiAgICogYW5kIGJvb2xlYW4gdHJ1ZSBhcyB2YWx1ZXMpLlxuICAgKlxuICAgKiBJdCBhbHNvIGhhbmRsZXMgZmllbGQgbmFtZSBtYXBwaW5nIGJldHdlZW4gYmV0dGVyLWF1dGggc2NoZW1hIGFuZCBQYXlsb2FkIGNvbGxlY3Rpb25zXG4gICAqIGJ5IHVzaW5nIHRoZSBnZXRGaWVsZE5hbWUgaGVscGVyIHRvIHJlc29sdmUgdGhlIGNvcnJlY3QgZmllbGQgbmFtZXMuXG4gICAqXG4gICAqIEBwYXJhbSBtb2RlbCAtIFRoZSBtb2RlbC9jb2xsZWN0aW9uIG5hbWUgdG8gZ2V0IGZpZWxkIG1hcHBpbmdzIGZyb21cbiAgICogQHBhcmFtIHNlbGVjdCAtIE9wdGlvbmFsIGFycmF5IG9mIGZpZWxkIG5hbWVzIHRvIHNlbGVjdFxuICAgKiBAcmV0dXJucyBBIFBheWxvYWQtY29tcGF0aWJsZSBzZWxlY3Qgb2JqZWN0IG9yIHVuZGVmaW5lZCBpZiBubyBmaWVsZHMgdG8gc2VsZWN0XG4gICAqIEBleGFtcGxlXG4gICAqIC8vIElucHV0OiBbJ2VtYWlsJywgJ25hbWUnXVxuICAgKiAvLyBPdXRwdXQ6IHsgZW1haWw6IHRydWUsIG5hbWU6IHRydWUgfVxuICAgKi9cbiAgZnVuY3Rpb24gY29udmVydFNlbGVjdChtb2RlbDogc3RyaW5nLCBzZWxlY3Q/OiBzdHJpbmdbXSkge1xuICAgIC8vIFJldHVybiB1bmRlZmluZWQgaWYgc2VsZWN0IGlzIGVtcHR5IG9yIG5vdCBwcm92aWRlZFxuICAgIGlmICghc2VsZWN0IHx8IHNlbGVjdC5sZW5ndGggPT09IDApIHJldHVybiB1bmRlZmluZWRcblxuICAgIC8vIFRyYW5zZm9ybSB0aGUgYXJyYXkgb2YgZmllbGQgbmFtZXMgaW50byBhIFBheWxvYWQgc2VsZWN0IG9iamVjdFxuICAgIC8vIHdoaWxlIGFsc28gbWFwcGluZyBhbnkgZmllbGQgbmFtZXMgdGhhdCBtaWdodCBiZSBkaWZmZXJlbnQgaW4gUGF5bG9hZFxuICAgIHJldHVybiBzZWxlY3QucmVkdWNlKChhY2MsIGZpZWxkKSA9PiAoeyAuLi5hY2MsIFtnZXRGaWVsZE5hbWUobW9kZWwsIGZpZWxkKV06IHRydWUgfSksIHt9KVxuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIGEgYmV0dGVyLWF1dGggc29ydCBvYmplY3QgdG8gYSBQYXlsb2FkIHNvcnQgc3RyaW5nXG4gICAqXG4gICAqIFRoaXMgZnVuY3Rpb24gdHJhbnNmb3JtcyB0aGUgYmV0dGVyLWF1dGggc29ydCBvYmplY3QgKHdoaWNoIGNvbnRhaW5zIGZpZWxkIG5hbWUgYW5kIGRpcmVjdGlvbilcbiAgICogaW50byB0aGUgZm9ybWF0IGV4cGVjdGVkIGJ5IFBheWxvYWQgQ01TJ3MgcXVlcnkgQVBJIChhIHN0cmluZyB3aXRoIG9wdGlvbmFsICctJyBwcmVmaXggZm9yIGRlc2NlbmRpbmcgb3JkZXIpLlxuICAgKlxuICAgKiBJdCBhbHNvIGhhbmRsZXMgZmllbGQgbmFtZSBtYXBwaW5nIGJldHdlZW4gYmV0dGVyLWF1dGggc2NoZW1hIGFuZCBQYXlsb2FkIGNvbGxlY3Rpb25zXG4gICAqIGJ5IHVzaW5nIHRoZSBnZXRGaWVsZE5hbWUgaGVscGVyIHRvIHJlc29sdmUgdGhlIGNvcnJlY3QgZmllbGQgbmFtZXMuXG4gICAqXG4gICAqIEBwYXJhbSBtb2RlbCAtIFRoZSBtb2RlbC9jb2xsZWN0aW9uIG5hbWUgdG8gZ2V0IGZpZWxkIG1hcHBpbmdzIGZyb21cbiAgICogQHBhcmFtIHNvcnRCeSAtIE9wdGlvbmFsIG9iamVjdCBjb250YWluaW5nIGZpZWxkIG5hbWUgYW5kIHNvcnQgZGlyZWN0aW9uXG4gICAqIEByZXR1cm5zIEEgUGF5bG9hZC1jb21wYXRpYmxlIHNvcnQgc3RyaW5nIG9yIHVuZGVmaW5lZCBpZiBubyBzb3J0IHNwZWNpZmllZFxuICAgKiBAZXhhbXBsZVxuICAgKiAvLyBJbnB1dDogeyBmaWVsZDogJ2VtYWlsJywgZGlyZWN0aW9uOiAnZGVzYycgfVxuICAgKiAvLyBPdXRwdXQ6ICctZW1haWwnXG4gICAqIC8vIElucHV0OiB7IGZpZWxkOiAnY3JlYXRlZEF0JywgZGlyZWN0aW9uOiAnYXNjJyB9XG4gICAqIC8vIE91dHB1dDogJ2NyZWF0ZWRBdCdcbiAgICovXG4gIGZ1bmN0aW9uIGNvbnZlcnRTb3J0KG1vZGVsOiBzdHJpbmcsIHNvcnRCeT86IHsgZmllbGQ6IHN0cmluZzsgZGlyZWN0aW9uOiAnYXNjJyB8ICdkZXNjJyB9KTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIXNvcnRCeSkgcmV0dXJuIHVuZGVmaW5lZFxuICAgIGNvbnN0IGZpZWxkTmFtZSA9IGdldEZpZWxkTmFtZShtb2RlbCwgc29ydEJ5LmZpZWxkKVxuICAgIGNvbnN0IHByZWZpeCA9IHNvcnRCeS5kaXJlY3Rpb24gPT09ICdkZXNjJyA/ICctJyA6ICcnXG4gICAgcmV0dXJuIGAke3ByZWZpeH0ke2ZpZWxkTmFtZX1gXG4gIH1cblxuICByZXR1cm4ge1xuICAgIGdldEZpZWxkTmFtZSxcbiAgICBnZXRDb2xsZWN0aW9uU2x1ZyxcbiAgICBzaW5nbGVJZFF1ZXJ5LFxuICAgIHRyYW5zZm9ybUlucHV0LFxuICAgIHRyYW5zZm9ybU91dHB1dCxcbiAgICBjb252ZXJ0V2hlcmVDbGF1c2UsXG4gICAgY29udmVydFNlbGVjdCxcbiAgICBjb252ZXJ0U29ydFxuICB9XG59XG4iXSwibmFtZXMiOlsiZ2V0QXV0aFRhYmxlcyIsImNyZWF0ZVRyYW5zZm9ybSIsIm9wdGlvbnMiLCJlbmFibGVEZWJ1Z0xvZ3MiLCJzY2hlbWEiLCJkZWJ1Z0xvZyIsIm1lc3NhZ2UiLCJjb25zb2xlIiwibG9nIiwiZ2V0Q29sbGVjdGlvblNsdWciLCJtb2RlbCIsImNvbGxlY3Rpb24iLCJtb2RlbE5hbWUiLCJyZXNvbHZlZFNsdWciLCJnZXRGaWVsZE5hbWUiLCJmaWVsZCIsImluY2x1ZGVzIiwiZmllbGREZWZpbml0aW9uIiwiZmllbGRzIiwiZmllbGROYW1lIiwib3JpZ2luYWxGaWVsZCIsImlzUmVsYXRpb25zaGlwRmllbGQiLCJmaWVsZEtleSIsInNjaGVtYUZpZWxkcyIsInJlZmVyZW5jZXMiLCJ1bmRlZmluZWQiLCJpc0RhdGVGaWVsZCIsInZhbHVlIiwiaXNOYU4iLCJEYXRlIiwicGFyc2UiLCJzaW5nbGVJZFF1ZXJ5Iiwid2hlcmUiLCJzb21lIiwiaWRGaWVsZCIsImNvbmRpdGlvbiIsIkFycmF5IiwiaXNBcnJheSIsImVxdWFscyIsImNvbnRhaW5zIiwibGVuZ3RoIiwibm9ybWFsaXplRGF0YSIsImtleSIsImlzUmVsYXRlZEZpZWxkIiwiaWRUeXBlIiwicGFyc2VkIiwicGFyc2VJbnQiLCJvcmlnaW5hbCIsImNvbnZlcnRlZCIsInN0cmluZ0lkIiwiU3RyaW5nIiwibWFwIiwiaWQiLCJ0cmFuc2Zvcm1JbnB1dCIsImRhdGEiLCJ0cmFuc2Zvcm1lZERhdGEiLCJPYmplY3QiLCJlbnRyaWVzIiwiZm9yRWFjaCIsInNjaGVtYUZpZWxkTmFtZSIsIm5vcm1hbGl6ZWREYXRhIiwidGFyZ2V0RmllbGROYW1lIiwidHJhbnNmb3JtT3V0cHV0IiwiZG9jIiwicmVzdWx0IiwicmVsYXRpb25zaGlwRmllbGRzIiwiZnJvbUVudHJpZXMiLCJmaWx0ZXIiLCJvcmlnaW5hbFJlbGF0ZWRGaWVsZEtleSIsImtleXMiLCJmaW5kIiwiayIsIm5vcm1hbGl6ZURvY3VtZW50SWRzIiwib3JpZ2luYWxLZXkiLCJldmVyeSIsIml0ZW0iLCJvcGVyYXRvclRvUGF5bG9hZCIsIm9wZXJhdG9yIiwibm90X2VxdWFscyIsImdyZWF0ZXJfdGhhbiIsImdyZWF0ZXJfdGhhbl9lcXVhbCIsImxlc3NfdGhhbiIsImxlc3NfdGhhbl9lcXVhbCIsImluIiwibGlrZSIsImNvbnZlcnRXaGVyZVZhbHVlIiwibnVtSWQiLCJOdW1iZXIiLCJjb252ZXJ0V2hlcmVDbGF1c2UiLCJ3IiwicmVzIiwiYW5kIiwiY29ubmVjdG9yIiwib3IiLCJhbmRDbGF1c2UiLCJvckNsYXVzZSIsIkFORCIsIk9SIiwiY29udmVydFNlbGVjdCIsInNlbGVjdCIsInJlZHVjZSIsImFjYyIsImNvbnZlcnRTb3J0Iiwic29ydEJ5IiwicHJlZml4IiwiZGlyZWN0aW9uIl0sIm1hcHBpbmdzIjoiQUFBQSxTQUFvQ0EsYUFBYSxRQUFRLGlCQUFnQjtBQUl6RSxPQUFPLE1BQU1DLGtCQUFrQixDQUFDQyxTQUE0QkM7SUFDMUQsTUFBTUMsU0FBU0osY0FBY0U7SUFFN0IsU0FBU0csU0FBU0MsT0FBYztRQUM5QixJQUFJSCxpQkFBaUI7WUFDbkJJLFFBQVFD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