velocious 1.0.507 → 1.0.508

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.
@@ -28,11 +28,265 @@ import UUID from "pure-uuid";
28
28
  * AuditedModelClass type.
29
29
  * @typedef {typeof import("./index.js").default & {
30
30
  * _auditCallbacks?: Record<string, AuditCallback[]>,
31
- * _auditLifecycleCallbacksRegistered?: boolean
31
+ * _auditLifecycleCallbacksRegistered?: boolean,
32
+ * _auditTableResolved?: boolean,
33
+ * _auditTableData?: AuditTableData
32
34
  * }} AuditedModelClass
33
35
  */
34
36
  /**
35
- * Adds automatic create/update/destroy auditing callbacks to a model class.
37
+ * AuditTableData type.
38
+ * @typedef {object} AuditTableData
39
+ * @property {boolean} dedicated - Whether a dedicated audit table exists.
40
+ * @property {string} tableName - Name of the audit table.
41
+ * @property {string} foreignKey - Column name that references the audited model.
42
+ * @property {typeof import("./index.js").default} auditClass - The audit model class to use.
43
+ */
44
+ /** @type {Map<string, boolean>} */
45
+ const dedicatedTableCache = new Map();
46
+ /** @type {Map<string, typeof import("./index.js").default>} */
47
+ const auditClassCache = new Map();
48
+ const generatedAuditRelationships = new WeakSet();
49
+ // ---------------------------------------------------------------------------
50
+ // Global event bus (like ActiveRecordAuditable::Events)
51
+ // ---------------------------------------------------------------------------
52
+ /** @type {Record<string, Record<string, Array<(args: AuditEventPayload) => void>>>} */
53
+ let globalEventConnections = {};
54
+ /**
55
+ * Global audit event bus matching ActiveRecordAuditable::Events.
56
+ * @typedef {object} AuditEventsType
57
+ * @property {(type: string, action: string, args: AuditEventPayload) => void} call - Fire all callbacks for a model type + action.
58
+ * @property {(type: string, action: string, callback: (args: AuditEventPayload) => void) => () => void} connect - Register a callback for a model type + action. Returns an unsubscribe function.
59
+ * @property {() => void} reset - Clear all registered callbacks.
60
+ */
61
+ /** @type {AuditEventsType} */
62
+ const AuditEvents = {
63
+ /** Fire all registered callbacks for a model type + action. @param {string} type @param {string} action @param {AuditEventPayload} args */
64
+ call(type, action, args) {
65
+ const actions = globalEventConnections[type] || {};
66
+ const callbacks = actions[action] || [];
67
+ for (const callback of [...callbacks]) {
68
+ callback(args);
69
+ }
70
+ },
71
+ /** Register a callback for a model type + action. Returns an unsubscribe function. @param {string} type @param {string} action @param {(args: AuditEventPayload) => void} callback @returns {() => void} */
72
+ connect(type, action, callback) {
73
+ if (!globalEventConnections[type]) {
74
+ globalEventConnections[type] = {};
75
+ }
76
+ if (!globalEventConnections[type][action]) {
77
+ globalEventConnections[type][action] = [];
78
+ }
79
+ globalEventConnections[type][action].push(callback);
80
+ return () => {
81
+ const list = globalEventConnections[type]?.[action];
82
+ if (list) {
83
+ const index = list.indexOf(callback);
84
+ if (index >= 0) {
85
+ list.splice(index, 1);
86
+ }
87
+ }
88
+ };
89
+ },
90
+ /** Clear all registered callbacks. @returns {void} */
91
+ reset() {
92
+ globalEventConnections = {};
93
+ }
94
+ };
95
+ // ---------------------------------------------------------------------------
96
+ // Table detection
97
+ // ---------------------------------------------------------------------------
98
+ /**
99
+ * Returns the dedicated audit table name for a model class.
100
+ * @param {AuditedModelClass} modelClass - Audited model class.
101
+ * @returns {string} e.g. "project_audits" for a "projects" table.
102
+ */
103
+ function dedicatedAuditTableName(modelClass) {
104
+ const table = modelClass.tableName();
105
+ if (table.endsWith("s")) {
106
+ return `${table.slice(0, -1)}_audits`;
107
+ }
108
+ return `${table}_audits`;
109
+ }
110
+ /**
111
+ * Resolves audit table data for a model class. Cached per model.
112
+ * Called lazily on first createAudit / withoutAudit / relationship usage.
113
+ * @param {AuditedModelClass} modelClass - Audited model class.
114
+ * @returns {Promise<AuditTableData>} Resolved audit table metadata.
115
+ */
116
+ async function resolveAuditTableData(modelClass) {
117
+ if (modelClass._auditTableResolved && modelClass._auditTableData) {
118
+ return modelClass._auditTableData;
119
+ }
120
+ const tableData = await buildAuditTableData(modelClass);
121
+ const configuration = modelClass._getConfiguration();
122
+ tableData.auditClass.registerRecordClass({ configuration });
123
+ await tableData.auditClass.initializeRecord({ configuration });
124
+ modelClass._auditTableData = tableData;
125
+ modelClass._auditTableResolved = true;
126
+ registerAuditRelationship(modelClass, tableData);
127
+ return tableData;
128
+ }
129
+ /**
130
+ * Builds audit table metadata for a model class. Prefers the consumer's
131
+ * registered Audit model for shared tables; falls back to a framework-owned
132
+ * dynamic class.
133
+ * @param {AuditedModelClass} modelClass - Audited model class.
134
+ * @returns {Promise<AuditTableData>} Audit table metadata.
135
+ */
136
+ async function buildAuditTableData(modelClass) {
137
+ const dedicatedTable = dedicatedAuditTableName(modelClass);
138
+ const dedicatedExists = await dedicatedTableExistsForConnection(modelClass, dedicatedTable);
139
+ if (dedicatedExists) {
140
+ const auditClass = dedicatedAuditClass(modelClass, dedicatedTable);
141
+ const modelKey = modelParamKey(modelClass);
142
+ return {
143
+ auditClass,
144
+ dedicated: true,
145
+ foreignKey: `${modelKey}_id`,
146
+ tableName: dedicatedTable
147
+ };
148
+ }
149
+ const configuration = modelClass._getConfiguration();
150
+ const consumerAuditClass = configuration.getModelClasses().Audit;
151
+ if (consumerAuditClass) {
152
+ return {
153
+ auditClass: consumerAuditClass,
154
+ dedicated: false,
155
+ foreignKey: "auditable_id",
156
+ tableName: "audits"
157
+ };
158
+ }
159
+ return {
160
+ auditClass: cachedSharedAuditClass(modelClass),
161
+ dedicated: false,
162
+ foreignKey: "auditable_id",
163
+ tableName: "audits"
164
+ };
165
+ }
166
+ /**
167
+ * Checks whether a dedicated audit table exists for a model's connection.
168
+ * @param {AuditedModelClass} modelClass - Audited model class.
169
+ * @param {string} tableName - Dedicated audit table name to check.
170
+ * @returns {Promise<boolean>} Whether the table exists.
171
+ */
172
+ async function dedicatedTableExistsForConnection(modelClass, tableName) {
173
+ const databaseIdentifier = modelClass.getDatabaseIdentifier();
174
+ const cacheKey = `${databaseIdentifier}:${tableName}`;
175
+ const cached = dedicatedTableCache.get(cacheKey);
176
+ if (typeof cached === "boolean") {
177
+ return cached;
178
+ }
179
+ const connection = modelClass.connection();
180
+ const table = await connection.getTableByName(tableName, { throwError: false });
181
+ const exists = Boolean(table);
182
+ dedicatedTableCache.set(cacheKey, exists);
183
+ return exists;
184
+ }
185
+ // ---------------------------------------------------------------------------
186
+ // Dynamic audit classes
187
+ // ---------------------------------------------------------------------------
188
+ /**
189
+ * Returns a framework-owned shared Audit class for the `audits` table.
190
+ * This is only used when no consumer-registered Audit model exists.
191
+ * @param {AuditedModelClass} modelClass - Any audited model class (used to locate DatabaseRecord).
192
+ * @returns {typeof import("./index.js").default} Shared Audit model class.
193
+ */
194
+ function sharedAuditClass(modelClass) {
195
+ const dbRecordClass = findDatabaseRecordClass(modelClass);
196
+ /**
197
+ * Framework-owned Audit model for the shared `audits` table.
198
+ */
199
+ class Audit extends dbRecordClass {
200
+ /** Returns the backing table name. @returns {string} */
201
+ static tableName() {
202
+ return "audits";
203
+ }
204
+ }
205
+ Object.defineProperty(Audit, "modelName", { value: "Audit", writable: false });
206
+ applyAuditClassDatabaseRouting(modelClass, Audit);
207
+ return /** @type {typeof import("./index.js").default} */ (Audit);
208
+ }
209
+ /**
210
+ * Returns the cached framework-owned shared Audit class for a database.
211
+ * @param {AuditedModelClass} modelClass - Any audited model class.
212
+ * @returns {typeof import("./index.js").default} Shared Audit model class.
213
+ */
214
+ function cachedSharedAuditClass(modelClass) {
215
+ const routingKey = modelClass.hasTenantDatabaseIdentifierResolver()
216
+ ? `tenant:${modelClass.getModelName()}`
217
+ : `database:${modelClass.getConfiguredDatabaseIdentifier()}`;
218
+ const cacheKey = `shared:${routingKey}`;
219
+ let auditClass = auditClassCache.get(cacheKey);
220
+ if (!auditClass) {
221
+ auditClass = sharedAuditClass(modelClass);
222
+ auditClassCache.set(cacheKey, auditClass);
223
+ }
224
+ return auditClass;
225
+ }
226
+ /**
227
+ * Returns a dynamic per-model audit class for a dedicated table.
228
+ * @param {AuditedModelClass} modelClass - Audited model class.
229
+ * @param {string} tableName - Dedicated audit table name (e.g. "project_audits").
230
+ * @returns {typeof import("./index.js").default} Dedicated audit model class.
231
+ */
232
+ function dedicatedAuditClass(modelClass, tableName) {
233
+ const dbRecordClass = findDatabaseRecordClass(modelClass);
234
+ const modelName = modelClass.getModelName();
235
+ const modelKey = modelParamKey(modelClass);
236
+ /**
237
+ * Framework-owned per-model Audit class.
238
+ */
239
+ class ModelAudit extends dbRecordClass {
240
+ /** Returns the backing table name. @returns {string} */
241
+ static tableName() {
242
+ return tableName;
243
+ }
244
+ }
245
+ Object.defineProperty(ModelAudit, "modelName", { value: `${modelName}Audit`, writable: false });
246
+ applyAuditClassDatabaseRouting(modelClass, ModelAudit);
247
+ ModelAudit.belongsTo(modelKey, { className: modelName });
248
+ return /** @type {typeof import("./index.js").default} */ (ModelAudit);
249
+ }
250
+ /**
251
+ * Makes framework-owned audit classes read the same database as the audited model.
252
+ * @param {AuditedModelClass} modelClass - Audited source model class.
253
+ * @param {typeof import("./index.js").default} auditClass - Generated audit class.
254
+ * @returns {void}
255
+ */
256
+ function applyAuditClassDatabaseRouting(modelClass, auditClass) {
257
+ auditClass.setDatabaseIdentifier(modelClass.getConfiguredDatabaseIdentifier());
258
+ if (modelClass.hasTenantDatabaseIdentifierResolver()) {
259
+ auditClass.switchesTenantDatabase(({ tenant }) => modelClass.getTenantDatabaseIdentifier(tenant));
260
+ }
261
+ }
262
+ /**
263
+ * Walks the prototype chain to find the root DatabaseRecord class.
264
+ * @param {AuditedModelClass} modelClass - Audited model class.
265
+ * @returns {typeof import("./index.js").default} Root DatabaseRecord class.
266
+ */
267
+ function findDatabaseRecordClass(modelClass) {
268
+ let recordClass = Object.getPrototypeOf(modelClass);
269
+ while (recordClass && Object.getPrototypeOf(recordClass) !== Function.prototype) {
270
+ recordClass = Object.getPrototypeOf(recordClass);
271
+ }
272
+ return /** @type {typeof import("./index.js").default} */ (recordClass);
273
+ }
274
+ /**
275
+ * Returns the parameter-key name for a model class.
276
+ * @param {AuditedModelClass} modelClass - Audited model class.
277
+ * @returns {string} e.g. "project" for "Project".
278
+ */
279
+ function modelParamKey(modelClass) {
280
+ const name = modelClass.getModelName();
281
+ return name.charAt(0).toLowerCase() + name.slice(1);
282
+ }
283
+ // ---------------------------------------------------------------------------
284
+ // Registration (sync — callbacks only; table detection deferred)
285
+ // ---------------------------------------------------------------------------
286
+ /**
287
+ * Registers lifecycle callbacks for automatic create/update/destroy auditing.
288
+ * Table detection and relationship registration happen lazily on first usage.
289
+ * Called synchronously from Model.audited() at module-load time.
36
290
  * @param {AuditedModelClass} modelClass - Model class to audit.
37
291
  * @returns {void}
38
292
  */
@@ -41,6 +295,7 @@ function registerAuditing(modelClass) {
41
295
  return;
42
296
  }
43
297
  modelClass._auditLifecycleCallbacksRegistered = true;
298
+ registerAuditRelationship(modelClass);
44
299
  modelClass.beforeCreate("captureCreateAuditChanges");
45
300
  modelClass.afterCreate("createCreateAudit");
46
301
  modelClass.beforeUpdate("captureUpdateAuditChanges");
@@ -48,54 +303,101 @@ function registerAuditing(modelClass) {
48
303
  modelClass.afterDestroy("createDestroyAudit");
49
304
  }
50
305
  /**
51
- * Registers an audit event callback for a model/action pair.
52
- * @param {AuditedModelClass} modelClass - Model class to observe.
53
- * @param {string} action - Audit action name.
54
- * @param {AuditCallback} callback - Callback invoked after matching audit rows are created.
55
- * @returns {() => void} Unsubscribe function.
306
+ * Initializes audit metadata for audited model classes.
307
+ * @param {typeof import("./index.js").default} modelClass - Model class to initialize.
308
+ * @param {{resolveTableData?: boolean}} [args] - Initialization options.
309
+ * @returns {Promise<void>}
56
310
  */
57
- function registerAuditCallback(modelClass, action, callback) {
58
- const normalizedAction = normalizeAction(action);
59
- const callbacks = auditCallbacksForModelClass(modelClass);
60
- if (!callbacks[normalizedAction]) {
61
- callbacks[normalizedAction] = [];
311
+ async function initializeAuditing(modelClass, args = {}) {
312
+ const { resolveTableData = false } = args;
313
+ const auditedModelClass = /** @type {AuditedModelClass} */ (modelClass);
314
+ if (!auditedModelClass._auditLifecycleCallbacksRegistered) {
315
+ return;
62
316
  }
63
- callbacks[normalizedAction].push(callback);
64
- return () => {
65
- const actionCallbacks = callbacks[normalizedAction];
66
- const index = actionCallbacks.indexOf(callback);
67
- if (index >= 0) {
68
- actionCallbacks.splice(index, 1);
317
+ registerAuditRelationship(auditedModelClass);
318
+ if (resolveTableData && auditedModelClass._initialized && canResolveAuditTableData(auditedModelClass)) {
319
+ await resolveAuditTableData(auditedModelClass);
320
+ }
321
+ }
322
+ /**
323
+ * Resolves audit metadata after application and package model classes are registered.
324
+ * @param {import("../../configuration.js").default} configuration - Configuration whose models should be finalized.
325
+ * @returns {Promise<void>}
326
+ */
327
+ async function initializeAuditedModelRelationships(configuration) {
328
+ for (const modelClass of Object.values(configuration.getModelClasses())) {
329
+ await initializeAuditing(modelClass, { resolveTableData: true });
330
+ }
331
+ }
332
+ /**
333
+ * Registers the audits relationship without forcing audit table detection.
334
+ * @param {AuditedModelClass} modelClass - Model class to audit.
335
+ * @param {AuditTableData} [tableData] - Resolved audit table data when available.
336
+ * @returns {void}
337
+ */
338
+ function registerAuditRelationship(modelClass, tableData = defaultAuditRelationshipTableData(modelClass)) {
339
+ if (modelClass._relationshipExists("audits")) {
340
+ const relationship = modelClass.getRelationshipByName("audits");
341
+ if (generatedAuditRelationships.has(relationship)) {
342
+ relationship.className = undefined;
343
+ relationship.klass = tableData.auditClass;
344
+ relationship.foreignKey = tableData.foreignKey;
345
+ relationship._explicitForeignKey = tableData.foreignKey;
346
+ relationship._polymorphic = !tableData.dedicated;
347
+ relationship._polymorphicTypeColumn = undefined;
69
348
  }
349
+ return;
350
+ }
351
+ modelClass.hasMany("audits", auditRelationshipScope, {
352
+ foreignKey: tableData.foreignKey,
353
+ klass: tableData.auditClass,
354
+ polymorphic: !tableData.dedicated
355
+ });
356
+ generatedAuditRelationships.add(modelClass.getRelationshipByName("audits"));
357
+ }
358
+ /**
359
+ * Returns unresolved shared-audit defaults for early relationship registration.
360
+ * @param {AuditedModelClass} modelClass - Model class to audit.
361
+ * @returns {AuditTableData} Shared audit relationship defaults.
362
+ */
363
+ function defaultAuditRelationshipTableData(modelClass) {
364
+ return {
365
+ auditClass: cachedSharedAuditClass(modelClass),
366
+ dedicated: false,
367
+ foreignKey: "auditable_id",
368
+ tableName: "audits"
70
369
  };
71
370
  }
72
371
  /**
73
- * Captures the new values for fields changed on a record.
74
- * @param {import("./index.js").default} record - Record whose pending changes should be captured.
75
- * @returns {AuditChanges} New values keyed by attribute name.
372
+ * Applies default audit ordering to generated audit relationships.
373
+ * @param {import("../query/model-class-query.js").default<typeof import("./index.js").default>} query - Audit query.
374
+ * @returns {import("../query/model-class-query.js").default<typeof import("./index.js").default>} Ordered audit query.
76
375
  */
77
- function auditChangesForCurrentChanges(record) {
78
- const changes = record.changes();
79
- /** @type {AuditChanges} */
80
- const auditedChanges = {};
81
- const columnNameToAttributeName = record.getModelClass().getColumnNameToAttributeNameMap();
82
- for (const [attributeName, change] of Object.entries(changes)) {
83
- auditedChanges[columnNameToAttributeName[attributeName] || attributeName] = change[1];
84
- }
85
- return auditedChanges;
376
+ function auditRelationshipScope(query) {
377
+ return query.order({ column: "created_at", direction: "DESC" });
86
378
  }
87
379
  /**
88
- * Captures the current attributes for a destroy audit.
89
- * @param {import("./index.js").default} record - Record being destroyed.
90
- * @returns {AuditChanges} Current attributes keyed by attribute name.
380
+ * Checks whether the current tenant context can resolve audit table data.
381
+ * @param {AuditedModelClass} modelClass - Model class to inspect.
382
+ * @returns {boolean} Whether audit table data can be resolved in the current scope.
91
383
  */
92
- function auditChangesForDestroy(record) {
93
- return { ...record.attributes() };
384
+ function canResolveAuditTableData(modelClass) {
385
+ if (!modelClass.hasTenantDatabaseIdentifierResolver()) {
386
+ return true;
387
+ }
388
+ const tenantDatabaseIdentifier = modelClass.getTenantDatabaseIdentifier();
389
+ if (!tenantDatabaseIdentifier) {
390
+ return false;
391
+ }
392
+ return modelClass._getConfiguration().isDatabaseIdentifierActive(tenantDatabaseIdentifier);
94
393
  }
394
+ // ---------------------------------------------------------------------------
395
+ // Creating audits
396
+ // ---------------------------------------------------------------------------
95
397
  /**
96
398
  * Creates an audit row for a record.
97
399
  * @param {import("./index.js").default} record - Record to audit.
98
- * @param {CreateAuditArgs} args - Audit row options.
400
+ * @param {CreateAuditArgs} args - Audit row options (action, auditedChanges, params).
99
401
  * @returns {Promise<number | string>} Created audit row id.
100
402
  */
101
403
  async function createAudit(record, args) {
@@ -106,14 +408,16 @@ async function createAudit(record, args) {
106
408
  }
107
409
  /**
108
410
  * Creates an audit row using the current model database connection.
411
+ * Routes to shared table or dedicated table based on resolved audit table data.
109
412
  * @param {import("./index.js").default} record - Record to audit.
110
- * @param {CreateAuditArgs} args - Audit row options.
413
+ * @param {CreateAuditArgs} args - Audit row options (action, auditedChanges, params).
111
414
  * @param {AuditedModelClass} modelClass - Audited model class.
112
415
  * @returns {Promise<number | string>} Created audit row id.
113
416
  */
114
417
  async function createAuditWithCurrentConnection(record, args, modelClass) {
115
418
  if (!record.isPersisted())
116
419
  throw new Error(`Cannot audit unpersisted ${modelClass.getModelName()} record`);
420
+ const tableData = await resolveAuditTableData(modelClass);
117
421
  const action = normalizeAction(args.action);
118
422
  const auditedChanges = args.auditedChanges === undefined ? null : args.auditedChanges;
119
423
  const params = args.params === undefined ? null : args.params;
@@ -121,70 +425,81 @@ async function createAuditWithCurrentConnection(record, args, modelClass) {
121
425
  const currentDate = new Date();
122
426
  const auditActionId = await findOrCreateLookupId({
123
427
  columnName: "action",
428
+ currentDate,
124
429
  db,
125
430
  tableName: "audit_actions",
126
- value: action,
127
- currentDate
128
- });
129
- const auditAuditableTypeId = await findOrCreateLookupId({
130
- columnName: "name",
131
- db,
132
- tableName: "audit_auditable_types",
133
- value: modelClass.getModelName(),
134
- currentDate
431
+ value: action
135
432
  });
136
433
  const auditId = new UUID(4).format();
137
- const insertResult = await db.query(db.insertSql({
138
- returnLastInsertedColumnNames: ["id"],
139
- tableName: "audits",
140
- data: {
141
- id: auditId,
142
- audit_action_id: auditActionId,
143
- audit_auditable_type_id: auditAuditableTypeId,
144
- auditable_id: record.id(),
145
- auditable_type: modelClass.getModelName(),
146
- audited_changes: auditedChanges,
147
- params,
148
- created_at: currentDate,
149
- updated_at: currentDate
150
- }
151
- }));
152
- const insertedAuditId = auditIdFromInsertResult(insertResult) ?? auditId;
434
+ if (tableData.dedicated) {
435
+ const modelKey = modelParamKey(modelClass);
436
+ await db.query(db.insertSql({
437
+ returnLastInsertedColumnNames: ["id"],
438
+ tableName: tableData.tableName,
439
+ data: {
440
+ id: auditId,
441
+ [`${modelKey}_id`]: record.id(),
442
+ audit_action_id: auditActionId,
443
+ audited_changes: auditedChanges,
444
+ params,
445
+ created_at: currentDate,
446
+ updated_at: currentDate
447
+ }
448
+ }));
449
+ }
450
+ else {
451
+ const auditAuditableTypeId = await findOrCreateLookupId({
452
+ columnName: "name",
453
+ currentDate,
454
+ db,
455
+ tableName: "audit_auditable_types",
456
+ value: modelClass.getModelName()
457
+ });
458
+ await db.query(db.insertSql({
459
+ returnLastInsertedColumnNames: ["id"],
460
+ tableName: "audits",
461
+ data: {
462
+ id: auditId,
463
+ audit_action_id: auditActionId,
464
+ audit_auditable_type_id: auditAuditableTypeId,
465
+ auditable_id: record.id(),
466
+ auditable_type: modelClass.getModelName(),
467
+ audited_changes: auditedChanges,
468
+ params,
469
+ created_at: currentDate,
470
+ updated_at: currentDate
471
+ }
472
+ }));
473
+ }
153
474
  await emitAuditEvent(modelClass, action, {
154
475
  action,
155
- auditId: insertedAuditId,
476
+ auditId,
156
477
  auditedChanges,
157
478
  params,
158
479
  record
159
480
  });
160
- return insertedAuditId;
161
- }
162
- /**
163
- * Reads an audit id returned by INSERT ... RETURNING / OUTPUT.
164
- * @param {Array<Record<string, ?>> | null | undefined} insertResult - Insert query result.
165
- * @returns {number | string | null} Created audit id when the driver returned it.
166
- */
167
- function auditIdFromInsertResult(insertResult) {
168
- if (!Array.isArray(insertResult))
169
- return null;
170
- const row = insertResult[0];
171
- if (!row)
172
- return null;
173
- const id = row.id;
174
- if (typeof id == "number" || typeof id == "string")
175
- return id;
176
- return null;
481
+ AuditEvents.call(modelClass.getModelName(), action, {
482
+ action,
483
+ auditId,
484
+ auditedChanges,
485
+ params,
486
+ record
487
+ });
488
+ return auditId;
177
489
  }
490
+ // ---------------------------------------------------------------------------
491
+ // Lifecycle callbacks
492
+ // ---------------------------------------------------------------------------
178
493
  /**
179
- * Captures create changes on a model instance.
180
- * @param {import("./index.js").default & {_pendingCreateAuditChanges?: AuditChanges}} record - Record to capture.
494
+ * Captures create changes before persistence clears the change set.
495
+ * @param {import("./index.js").default & {_pendingCreateAuditChanges?: AuditChanges}} record - Record whose pending changes should be captured.
181
496
  * @returns {void}
182
497
  */
183
498
  function captureCreateAuditChanges(record) {
184
499
  record._pendingCreateAuditChanges = auditChangesForCurrentChanges(record);
185
500
  }
186
501
  /**
187
- * Creates the create audit row for a model instance.
502
+ * Writes the create audit row for a model instance.
188
503
  * @param {import("./index.js").default & {_pendingCreateAuditChanges?: AuditChanges}} record - Record to audit.
189
504
  * @returns {Promise<void>}
190
505
  */
@@ -196,15 +511,15 @@ async function createCreateAudit(record) {
196
511
  record._pendingCreateAuditChanges = undefined;
197
512
  }
198
513
  /**
199
- * Captures update changes on a model instance.
200
- * @param {import("./index.js").default & {_pendingUpdateAuditChanges?: AuditChanges}} record - Record to capture.
514
+ * Captures update changes before persistence clears the change set.
515
+ * @param {import("./index.js").default & {_pendingUpdateAuditChanges?: AuditChanges}} record - Record whose pending changes should be captured.
201
516
  * @returns {void}
202
517
  */
203
518
  function captureUpdateAuditChanges(record) {
204
519
  record._pendingUpdateAuditChanges = auditChangesForCurrentChanges(record);
205
520
  }
206
521
  /**
207
- * Creates the update audit row for a model instance.
522
+ * Writes the update audit row for a model instance.
208
523
  * @param {import("./index.js").default & {_pendingUpdateAuditChanges?: AuditChanges}} record - Record to audit.
209
524
  * @returns {Promise<void>}
210
525
  */
@@ -219,7 +534,7 @@ async function createUpdateAudit(record) {
219
534
  });
220
535
  }
221
536
  /**
222
- * Creates the destroy audit row for a model instance.
537
+ * Writes the destroy audit row for a model instance.
223
538
  * @param {import("./index.js").default} record - Record to audit.
224
539
  * @returns {Promise<void>}
225
540
  */
@@ -229,8 +544,39 @@ async function createDestroyAudit(record) {
229
544
  auditedChanges: auditChangesForDestroy(record)
230
545
  });
231
546
  }
547
+ // ---------------------------------------------------------------------------
548
+ // Changes helpers
549
+ // ---------------------------------------------------------------------------
550
+ /**
551
+ * Captures the new values for fields changed on a record.
552
+ * @param {import("./index.js").default} record - Record whose pending changes should be captured.
553
+ * @returns {AuditChanges} New values keyed by attribute name.
554
+ */
555
+ function auditChangesForCurrentChanges(record) {
556
+ const changes = record.changes();
557
+ /** @type {AuditChanges} */
558
+ const auditedChanges = {};
559
+ const columnNameToAttributeName = record.getModelClass().getColumnNameToAttributeNameMap();
560
+ for (const [attributeName, change] of Object.entries(changes)) {
561
+ auditedChanges[columnNameToAttributeName[attributeName] || attributeName] = change[1];
562
+ }
563
+ return auditedChanges;
564
+ }
565
+ /**
566
+ * Captures the current attributes for a destroy audit.
567
+ * @param {import("./index.js").default} record - Record being destroyed.
568
+ * @returns {AuditChanges} Current attributes keyed by attribute name.
569
+ */
570
+ function auditChangesForDestroy(record) {
571
+ return { ...record.attributes() };
572
+ }
573
+ // ---------------------------------------------------------------------------
574
+ // withoutAudit
575
+ // ---------------------------------------------------------------------------
232
576
  /**
233
577
  * Returns records without an audit row for the given action.
578
+ * Uses shared-table defaults when table data is not yet resolved;
579
+ * switches to the dedicated table path once resolved.
234
580
  * @template {AuditedModelClass} MC
235
581
  * @param {MC} modelClass - Model class to scope.
236
582
  * @param {string} action - Audit action to exclude.
@@ -239,14 +585,33 @@ async function createDestroyAudit(record) {
239
585
  function withoutAudit(modelClass, action) {
240
586
  const db = modelClass.connection();
241
587
  const modelTableSql = db.quoteTable(modelClass.tableName());
242
- const auditsTableSql = db.quoteTable("audits");
243
588
  const auditActionsTableSql = db.quoteTable("audit_actions");
244
589
  const modelPrimaryKeySql = `${modelTableSql}.${db.quoteColumn(modelClass.primaryKey())}`;
590
+ const auditActionsIdSql = `${auditActionsTableSql}.${db.quoteColumn("id")}`;
591
+ const auditActionsActionSql = `${auditActionsTableSql}.${db.quoteColumn("action")}`;
592
+ if (modelClass._auditTableResolved && modelClass._auditTableData?.dedicated) {
593
+ const tableData = modelClass._auditTableData;
594
+ const modelKey = modelParamKey(modelClass);
595
+ const auditsTableSql = db.quoteTable(tableData.tableName);
596
+ const auditActionIdSql = `${auditsTableSql}.${db.quoteColumn("audit_action_id")}`;
597
+ const modelIdSql = `${auditsTableSql}.${db.quoteColumn(`${modelKey}_id`)}`;
598
+ return modelClass
599
+ .all()
600
+ .where(`
601
+ NOT EXISTS (
602
+ SELECT 1
603
+ FROM ${auditsTableSql}
604
+ INNER JOIN ${auditActionsTableSql}
605
+ ON ${auditActionsIdSql} = ${auditActionIdSql}
606
+ WHERE ${modelIdSql} = ${modelPrimaryKeySql}
607
+ AND ${auditActionsActionSql} = ${db.quote(normalizeAction(action))}
608
+ )
609
+ `);
610
+ }
611
+ const auditsTableSql = db.quoteTable("audits");
245
612
  const auditAuditableIdSql = `${auditsTableSql}.${db.quoteColumn("auditable_id")}`;
246
613
  const auditAuditableTypeSql = `${auditsTableSql}.${db.quoteColumn("auditable_type")}`;
247
614
  const auditActionIdSql = `${auditsTableSql}.${db.quoteColumn("audit_action_id")}`;
248
- const auditActionsIdSql = `${auditActionsTableSql}.${db.quoteColumn("id")}`;
249
- const auditActionsActionSql = `${auditActionsTableSql}.${db.quoteColumn("action")}`;
250
615
  return modelClass
251
616
  .all()
252
617
  .where(`
@@ -261,13 +626,68 @@ function withoutAudit(modelClass, action) {
261
626
  )
262
627
  `);
263
628
  }
629
+ // ---------------------------------------------------------------------------
630
+ // Event callbacks
631
+ // ---------------------------------------------------------------------------
632
+ /**
633
+ * Registers a per-model callback fired after an audit row is created.
634
+ * @param {AuditedModelClass} modelClass - Model class to observe.
635
+ * @param {string} action - Audit action name (e.g. "create").
636
+ * @param {AuditCallback} callback - Callback invoked after matching audit rows are created.
637
+ * @returns {() => void} Unsubscribe function.
638
+ */
639
+ function registerAuditCallback(modelClass, action, callback) {
640
+ const normalizedAction = normalizeAction(action);
641
+ const callbacks = auditCallbacksForModelClass(modelClass);
642
+ if (!callbacks[normalizedAction]) {
643
+ callbacks[normalizedAction] = [];
644
+ }
645
+ callbacks[normalizedAction].push(callback);
646
+ return () => {
647
+ const actionCallbacks = callbacks[normalizedAction];
648
+ const index = actionCallbacks.indexOf(callback);
649
+ if (index >= 0) {
650
+ actionCallbacks.splice(index, 1);
651
+ }
652
+ };
653
+ }
654
+ /**
655
+ * Emits per-model audit callbacks for a model/action pair.
656
+ * @param {AuditedModelClass} modelClass - Model class.
657
+ * @param {string} action - Audit action.
658
+ * @param {AuditEventPayload} payload - Event payload.
659
+ * @returns {Promise<void>}
660
+ */
661
+ async function emitAuditEvent(modelClass, action, payload) {
662
+ const callbacks = auditCallbacksForModelClass(modelClass)[action] || [];
663
+ for (const callback of [...callbacks]) {
664
+ await callback(payload);
665
+ }
666
+ }
667
+ /**
668
+ * Returns the per-model callback map.
669
+ * @param {AuditedModelClass} modelClass - Model class.
670
+ * @returns {Record<string, AuditCallback[]>} Callback map keyed by action.
671
+ */
672
+ function auditCallbacksForModelClass(modelClass) {
673
+ if (!Object.prototype.hasOwnProperty.call(modelClass, "_auditCallbacks")) {
674
+ modelClass._auditCallbacks = {};
675
+ }
676
+ const callbacks = modelClass._auditCallbacks;
677
+ if (!callbacks)
678
+ throw new Error(`Audit callbacks weren't initialized for ${modelClass.getModelName()}`);
679
+ return callbacks;
680
+ }
681
+ // ---------------------------------------------------------------------------
682
+ // Lookup helpers
683
+ // ---------------------------------------------------------------------------
264
684
  /**
265
685
  * Finds or creates a lookup row and returns its id.
266
686
  * @param {object} args - Options object.
267
- * @param {string} args.columnName - Lookup value column.
687
+ * @param {string} args.columnName - Lookup value column name.
268
688
  * @param {Date} args.currentDate - Timestamp to write when inserting.
269
689
  * @param {import("../drivers/base.js").default} args.db - Database driver.
270
- * @param {string} args.tableName - Lookup table.
690
+ * @param {string} args.tableName - Lookup table name.
271
691
  * @param {string} args.value - Lookup value.
272
692
  * @returns {Promise<number | string>} Lookup row id.
273
693
  */
@@ -291,9 +711,9 @@ async function findOrCreateLookupId({ columnName, currentDate, db, tableName, va
291
711
  /**
292
712
  * Finds a lookup id by value.
293
713
  * @param {object} args - Options object.
294
- * @param {string} args.columnName - Lookup value column.
714
+ * @param {string} args.columnName - Lookup value column name.
295
715
  * @param {import("../drivers/base.js").default} args.db - Database driver.
296
- * @param {string} args.tableName - Lookup table.
716
+ * @param {string} args.tableName - Lookup table name.
297
717
  * @param {string} args.value - Lookup value.
298
718
  * @returns {Promise<number | string | null>} Lookup row id or null.
299
719
  */
@@ -308,9 +728,9 @@ async function findLookupId({ columnName, db, tableName, value }) {
308
728
  return null;
309
729
  }
310
730
  /**
311
- * Normalizes an audit action.
731
+ * Normalizes an audit action string.
312
732
  * @param {string} action - Action name.
313
- * @returns {string} Normalized action.
733
+ * @returns {string} Trimmed, non-empty action name.
314
734
  */
315
735
  function normalizeAction(action) {
316
736
  const normalizedAction = action.trim();
@@ -318,32 +738,55 @@ function normalizeAction(action) {
318
738
  throw new Error("Audit action must be present");
319
739
  return normalizedAction;
320
740
  }
741
+ // ---------------------------------------------------------------------------
742
+ // Migration helpers
743
+ // ---------------------------------------------------------------------------
321
744
  /**
322
- * Returns the callback map owned by a model class.
323
- * @param {AuditedModelClass} modelClass - Model class.
324
- * @returns {Record<string, AuditCallback[]>} Callback map.
745
+ * Creates the shared audit tables migration up/down callbacks for use inside
746
+ * a Migration class. The `table` parameter is a Migration instance.
747
+ * @param {{id?: {type: string}}} [options] - ID column options.
748
+ * @returns {{down: (table: import("../migration/index.js").default) => Promise<void>, up: (table: import("../migration/index.js").default) => Promise<void>}}
325
749
  */
326
- function auditCallbacksForModelClass(modelClass) {
327
- if (!Object.prototype.hasOwnProperty.call(modelClass, "_auditCallbacks")) {
328
- modelClass._auditCallbacks = {};
329
- }
330
- const callbacks = modelClass._auditCallbacks;
331
- if (!callbacks)
332
- throw new Error(`Audit callbacks weren't initialized for ${modelClass.getModelName()}`);
333
- return callbacks;
750
+ function createSharedAuditTablesMigration(options = {}) {
751
+ const opts = /** @type {{id?: {type: string}}} */ (options);
752
+ const idOptions = /** @type {{type?: string}} */ (opts.id || {});
753
+ const type = idOptions.type;
754
+ return {
755
+ async up(table) {
756
+ await table.createTable("audit_actions", { id: /** @type {{type?: string}} */ (opts.id || {}) }, (/** @type {{string(name: string, options: Record<string, unknown>): void, timestamps(): void}} */ t) => {
757
+ t.string("action", { index: { unique: true }, null: false });
758
+ t.timestamps();
759
+ });
760
+ await table.createTable("audit_auditable_types", { id: /** @type {{type?: string}} */ (opts.id || {}) }, (/** @type {{string(name: string, options: Record<string, unknown>): void, timestamps(): void}} */ t) => {
761
+ t.string("name", { index: { unique: true }, null: false });
762
+ t.timestamps();
763
+ });
764
+ await table.createTable("audits", { id: /** @type {{type?: string}} */ (opts.id || {}) }, (/** @type {{json(name: string): void, references(name: string, options: Record<string, unknown>): void, timestamps(): void}} */ t) => {
765
+ t.references("audit_action", { foreignKey: true, null: false, type });
766
+ t.references("audit_auditable_type", { foreignKey: true, null: false, type });
767
+ t.references("auditable", { null: false, polymorphic: true, type });
768
+ t.json("audited_changes");
769
+ t.json("params");
770
+ t.timestamps();
771
+ });
772
+ },
773
+ async down(table) {
774
+ await table.dropTable("audits");
775
+ await table.dropTable("audit_auditable_types");
776
+ await table.dropTable("audit_actions");
777
+ }
778
+ };
334
779
  }
335
780
  /**
336
- * Emits audit callbacks for a model/action pair.
337
- * @param {AuditedModelClass} modelClass - Model class.
338
- * @param {string} action - Audit action.
339
- * @param {AuditEventPayload} payload - Event payload.
340
- * @returns {Promise<void>}
781
+ * Returns the dedicated audit table name for a given model table name.
782
+ * @param {string} modelTableName - Model table name (e.g. "projects").
783
+ * @returns {string} Dedicated audit table name (e.g. "project_audits").
341
784
  */
342
- async function emitAuditEvent(modelClass, action, payload) {
343
- const callbacks = auditCallbacksForModelClass(modelClass)[action] || [];
344
- for (const callback of [...callbacks]) {
345
- await callback(payload);
785
+ function dedicatedAuditTableNameForTable(modelTableName) {
786
+ if (modelTableName.endsWith("s")) {
787
+ return `${modelTableName.slice(0, -1)}_audits`;
346
788
  }
789
+ return `${modelTableName}_audits`;
347
790
  }
348
- export { captureCreateAuditChanges, captureUpdateAuditChanges, createAudit, createCreateAudit, createDestroyAudit, createUpdateAudit, registerAuditCallback, registerAuditing, withoutAudit };
349
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXVkaXRpbmcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvZGF0YWJhc2UvcmVjb3JkL2F1ZGl0aW5nLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLElBQUksTUFBTSxXQUFXLENBQUE7QUFFNUI7OztHQUdHO0FBRUg7Ozs7Ozs7O0dBUUc7QUFFSDs7O0dBR0c7QUFFSDs7Ozs7O0dBTUc7QUFFSDs7Ozs7O0dBTUc7QUFFSDs7OztHQUlHO0FBQ0gsU0FBUyxnQkFBZ0IsQ0FBQyxVQUFVO0lBQ2xDLElBQUksTUFBTSxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxvQ0FBb0MsQ0FBQyxJQUFJLFVBQVUsQ0FBQyxrQ0FBa0MsRUFBRSxDQUFDO1FBQzVJLE9BQU07SUFDUixDQUFDO0lBRUQsVUFBVSxDQUFDLGtDQUFrQyxHQUFHLElBQUksQ0FBQTtJQUNwRCxVQUFVLENBQUMsWUFBWSxDQUFDLDJCQUEyQixDQUFDLENBQUE7SUFDcEQsVUFBVSxDQUFDLFdBQVcsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFBO0lBQzNDLFVBQVUsQ0FBQyxZQUFZLENBQUMsMkJBQTJCLENBQUMsQ0FBQTtJQUNwRCxVQUFVLENBQUMsV0FBVyxDQUFDLG1CQUFtQixDQUFDLENBQUE7SUFDM0MsVUFBVSxDQUFDLFlBQVksQ0FBQyxvQkFBb0IsQ0FBQyxDQUFBO0FBQy9DLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxTQUFTLHFCQUFxQixDQUFDLFVBQVUsRUFBRSxNQUFNLEVBQUUsUUFBUTtJQUN6RCxNQUFNLGdCQUFnQixHQUFHLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQTtJQUNoRCxNQUFNLFNBQVMsR0FBRywyQkFBMkIsQ0FBQyxVQUFVLENBQUMsQ0FBQTtJQUV6RCxJQUFJLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUFDLEVBQUUsQ0FBQztRQUNqQyxTQUFTLENBQUMsZ0JBQWdC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LENBQUE7SUFFNUMsSUFBSSxDQUFDLFNBQVM7UUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLDJDQUEyQyxVQUFVLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQyxDQUFBO0lBRXZHLE9BQU8sU0FBUyxDQUFBO0FBQ2xCLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxLQUFLLFVBQVUsY0FBYyxDQUFDLFVBQVUsRUFBRSxNQUFNLEVBQUUsT0FBTztJQUN2RCxNQUFNLFNBQVMsR0FBRywyQkFBMkIsQ0FBQyxVQUFVLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUE7SUFFdkUsS0FBSyxNQUFNLFFBQVEsSUFBSSxDQUFDLEdBQUcsU0FBUyxDQUFDLEVBQUUsQ0FBQztRQUN0QyxNQUFNLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQTtJQUN6QixDQUFDO0FBQ0gsQ0FBQztBQUVELE9BQU8sRUFDTCx5QkFBeUIsRUFDekIseUJBQXlCLEVBQ3pCLFdBQVcsRUFDWCxpQkFBaUIsRUFDakIsa0JBQWtCLEVBQ2xCLGlCQUFpQixFQUNqQixxQkFBcUIsRUFDckIsZ0JBQWdCLEVBQ2hCLFlBQVksRUFDYixDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCBVVUlEIGZyb20gXCJwdXJlLXV1aWRcIlxuXG4vKipcbiAqIEF1ZGl0Q2hhbmdlcyB0eXBlLlxuICogQHR5cGVkZWYge1JlY29yZDxzdHJpbmcsID8+fSBBdWRpdENoYW5nZXNcbiAqL1xuXG4vKipcbiAqIEF1ZGl0RXZlbnRQYXlsb2FkIHR5cGUuXG4gKiBAdHlwZWRlZiB7b2JqZWN0fSBBdWRpdEV2ZW50UGF5bG9hZFxuICogQHByb3BlcnR5IHtzdHJpbmd9IGFjdGlvbiAtIEF1ZGl0IGFjdGlvbiBuYW1lLlxuICogQHByb3BlcnR5IHtudW1iZXIgfCBzdHJpbmd9IGF1ZGl0SWQgLSBDcmVhdGVkIGF1ZGl0IHJvdyBpZC5cbiAqIEBwcm9wZXJ0eSB7QXVkaXRDaGFuZ2VzIHwgbnVsbH0gYXVkaXRlZENoYW5nZXMgLSBDaGFuZ2VzIGNhcHR1cmVkIGZvciB0aGUgYXVkaXQuXG4gKiBAcHJvcGVydHkge1JlY29yZDxzdHJpbmcsID8+IHwgbnVsbH0gcGFyYW1zIC0gT3B0aW9uYWwgY2FsbGVyLXN1cHBsaWVkIGF1ZGl0IHBhcmFtcy5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0fSByZWNvcmQgLSBBdWRpdGVkIHJlY29yZC5cbiAqL1xuXG4vKipcbiAqIEF1ZGl0Q2FsbGJhY2sgdHlwZS5cbiAqIEB0eXBlZGVmIHsocGF5bG9hZDogQXVkaXRFdmVudFBheWxvYWQpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+fSBBdWRpdENhbGxiYWNrXG4gKi9cblxuLyoqXG4gKiBDcmVhdGVBdWRpdEFyZ3MgdHlwZS5cbiAqIEB0eXBlZGVmIHtvYmplY3R9IENyZWF0ZUF1ZGl0QXJnc1xuICogQHByb3BlcnR5IHtzdHJpbmd9IGFjdGlvbiAtIEF1ZGl0IGFjdGlvbiBuYW1lLlxuICogQHByb3BlcnR5IHtBdWRpdENoYW5nZXMgfCBudWxsfSBbYXVkaXRlZENoYW5nZXNdIC0gRXhwbGljaXQgY2hhbmdlcyB0byBwZXJzaXN0LlxuICogQHByb3BlcnR5IHtSZWNvcmQ8c3RyaW5nLCA/PiB8IG51bGx9IFtwYXJhbXNdIC0gT3B0aW9uYWwgbWV0YWRhdGEgdG8gc3RvcmUgd2l0aCB0aGUgYXVkaXQuXG4gKi9cblxuLyoqXG4gKiBBdWRpdGVkTW9kZWxDbGFzcyB0eXBlLlxuICogQHR5cGVkZWYge3R5cGVvZiBpbXBvcnQoXCIuL2luZGV4LmpzXCIpLmRlZmF1bHQgJiB7XG4gKiAgIF9hdWRpdENhbGxiYWNrcz86IFJlY29yZDxzdHJpbmcsIEF1ZGl0Q2FsbGJhY2tbXT4sXG4gKiAgIF9hdWRpdExpZmVjeWNsZUNhbGxiYWNrc1JlZ2lzdGVyZWQ/OiBib29sZWFuXG4gKiB9fSBBdWRpdGVkTW9kZWxDbGFzc1xuICovXG5cbi8qKlxuICogQWRkcyBhdXRvbWF0aWMgY3JlYXRlL3VwZGF0ZS9kZXN0cm95IGF1ZGl0aW5nIGNhbGxiYWNrcyB0byBhIG1vZGVsIGNsYXNzLlxuICogQHBhcmFtIHtBdWRpdGVkTW9kZWxDbGFzc30gbW9kZWxDbGFzcyAtIE1vZGVsIGNsYXNzIHRvIGF1ZGl0LlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIHJlZ2lzdGVyQXVkaXRpbmcobW9kZWxDbGFzcykge1xuICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG1vZGVsQ2xhc3MsIFwiX2F1ZGl0TGlmZWN5Y2xlQ2FsbGJhY2tzUmVnaXN0ZXJlZFwiKSAmJiBtb2RlbENsYXNzLl9hdWRpdExpZmVjeWNsZUNhbGxiYWNrc1JlZ2lzdGVyZWQpIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIG1vZGVsQ2xhc3MuX2F1ZGl0TGlmZWN5Y2xlQ2FsbGJhY2tzUmVnaXN0ZXJlZCA9IHRydWVcbiAgbW9kZWxDbGFzcy5iZWZvcmVDcmVhdGUoXCJjYXB0dXJlQ3JlYXRlQXVkaXRDaGFuZ2VzXCIpXG4gIG1vZGVsQ2xhc3MuYWZ0ZXJDcmVhdGUoXCJjcmVhdGVDcmVhdGVBdWRpdFwiKVxuICBtb2RlbENsYXNzLmJlZm9yZVVwZGF0ZShcImNhcHR1cmVVcGRhdGVBdWRpdENoYW5nZXNcIilcbiAgbW9kZWxDbGFzcy5hZnRlclVwZGF0ZShcImNyZWF0ZVVwZGF0ZUF1ZGl0XCIpXG4gIG1vZGVsQ2xhc3MuYWZ0ZXJEZXN0cm95KFwiY3JlYXRlRGVzdHJveUF1ZGl0XCIpXG59XG5cbi8qKlxuICogUmVnaXN0ZXJzIGFuIGF1ZGl0IGV2ZW50IGNhbGxiYWNrIGZvciBhIG1vZGVsL2FjdGlvbiBwYWlyLlxuICogQHBhcmFtIHtBdWRpdGVkTW9kZWxDbGFzc30gbW9kZWxDbGFzcyAtIE1vZGVsIGNsYXNzIHRvIG9ic2VydmUuXG4gKiBAcGFyYW0ge3N0cmluZ30gYWN0aW9uIC0gQXVkaXQgYWN0aW9uIG5hbWUuXG4gKiBAcGFyYW0ge0F1ZGl0Q2FsbGJhY2t9IGNhbGxiYWNrIC0gQ2FsbGJhY2sgaW52b2tlZCBhZnRlciBtYXRjaGluZyBhdWRpdCByb3dzIGFyZSBjcmVhdGVkLlxuICogQHJldHVybnMgeygpID0+IHZvaWR9IFVuc3Vic2NyaWJlIGZ1bmN0aW9uLlxuICovXG5mdW5jdGlvbiByZWdpc3RlckF1ZGl0Q2FsbGJhY2sobW9kZWxDbGFzcywgYWN0aW9uLCBjYWxsYmFjaykge1xuICBjb25zdCBub3JtYWxpemVkQWN0aW9uID0gbm9ybWFsaXplQWN0aW9uKGFjdGlvbilcbiAgY29uc3QgY2FsbGJhY2tzID0gYXVkaXRDYWxsYmFja3NGb3JNb2RlbENsYXNzKG1vZGVsQ2xhc3MpXG5cbiAgaWYgKCFjYWxsYmFja3Nbbm9ybWFsaXplZEFjdGlvbl0pIHtcbiAgICBjYWxsYmFja3Nbbm9ybWFsaXplZEFjdGlvbl0gPSBbXVxuICB9XG5cbiAgY2FsbGJhY2tzW25vcm1hbGl6ZWRBY3Rpb25dLnB1c2goY2FsbGJhY2spXG5cbiAgcmV0dXJuICgpID0+IHtcbiAgICBjb25zdCBhY3Rpb25DYWxsYmFja3MgPSBjYWxsYmFja3Nbbm9ybWFsaXplZEFjdGlvbl1cbiAgICBjb25zdCBpbmRleCA9IGFjdGlvbkNhbGxiYWNrcy5pbmRleE9mKGNhbGxiYWNrKVxuXG4gICAgaWYgKGluZGV4ID49IDApIHtcbiAgICAgIGFjdGlvbkNhbGxiYWNrcy5zcGxpY2UoaW5kZXgsIDEpXG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQ2FwdHVyZXMgdGhlIG5ldyB2YWx1ZXMgZm9yIGZpZWxkcyBjaGFuZ2VkIG9uIGEgcmVjb3JkLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2luZGV4LmpzXCIpLmRlZmF1bHR9IHJlY29yZCAtIFJlY29yZCB3aG9zZSBwZW5kaW5nIGNoYW5nZXMgc2hvdWxkIGJlIGNhcHR1cmVkLlxuICogQHJldHVybnMge0F1ZGl0Q2hhbmdlc30gTmV3IHZhbHVlcyBrZXllZCBieSBhdHRyaWJ1dGUgbmFtZS5cbiAqL1xuZnVuY3Rpb24gYXVkaXRDaGFuZ2VzRm9yQ3VycmVudENoYW5nZXMocmVjb3JkKSB7XG4gIGNvbnN0IGNoYW5nZXMgPSByZWNvcmQuY2hhbmdlcygpXG4gIC8qKiBAdHlwZSB7QXVkaXRDaGFuZ2VzfSAqL1xuICBjb25zdCBhdWRpdGVkQ2hhbmdlcyA9IHt9XG4gIGNvbnN0IGNvbHVtbk5hbWVUb0F0dHJpYnV0ZU5hbWUgPSByZWNvcmQuZ2V0TW9kZWxDbGFzcygpLmdldENvbHVtbk5hbWVUb0F0dHJpYnV0ZU5hbWVNYXAoKVxuXG4gIGZvciAoY29uc3QgW2F0dHJpYnV0ZU5hbWUsIGNoYW5nZV0gb2YgT2JqZWN0LmVudHJpZXMoY2hhbmdlcykpIHtcbiAgICBhdWRpdGVkQ2hhbmdlc1tjb2x1bW5OYW1lVG9BdHRyaWJ1dGVOYW1lW2F0dHJpYnV0ZU5hbWVdIHx8IGF0dHJpYnV0ZU5hbWVdID0gY2hhbmdlWzFdXG4gIH1cblxuICByZXR1cm4gYXVkaXRlZENoYW5nZXNcbn1cblxuLyoqXG4gKiBDYXB0dXJlcyB0aGUgY3VycmVudCBhdHRyaWJ1dGVzIGZvciBhIGRlc3Ryb3kgYXVkaXQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vaW5kZXguanNcIikuZGVmYXVsdH0gcmVjb3JkIC0gUmVjb3JkIGJlaW5nIGRlc3Ryb3llZC5cbiAqIEByZXR1cm5zIHtBdWRpdENoYW5nZXN9IEN1cnJlbnQgYXR0cmlidXRlcyBrZXllZCBieSBhdHRyaWJ1dGUgbmFtZS5cbiAqL1xuZnVuY3Rpb24gYXVkaXRDaGFuZ2VzRm9yRGVzdHJveShyZWNvcmQpIHtcbiAgcmV0dXJuIHsuLi5yZWNvcmQuYXR0cmlidXRlcygpfVxufVxuXG4vKipcbiAqIENyZWF0ZXMgYW4gYXVkaXQgcm93IGZvciBhIHJlY29yZC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0fSByZWNvcmQgLSBSZWNvcmQgdG8gYXVkaXQuXG4gKiBAcGFyYW0ge0NyZWF0ZUF1ZGl0QXJnc30gYXJncyAtIEF1ZGl0IHJvdyBvcHRpb25zLlxuICogQHJldHVybnMge1Byb21pc2U8bnVtYmVyIHwgc3RyaW5nPn0gQ3JlYXRlZCBhdWRpdCByb3cgaWQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUF1ZGl0KHJlY29yZCwgYXJncykge1xuICBjb25zdCBtb2RlbENsYXNzID0gLyoqIEB0eXBlIHtBdWRpdGVkTW9kZWxDbGFzc30gKi8gKHJlY29yZC5nZXRNb2RlbENsYXNzKCkpXG5cbiAgcmV0dXJuIGF3YWl0IG1vZGVsQ2xhc3MuX2dldENvbmZpZ3VyYXRpb24oKS5lbnN1cmVDb25uZWN0aW9ucyh7bmFtZTogYCR7bW9kZWxDbGFzcy5nZXRNb2RlbE5hbWUoKX0gYXVkaXRgfSwgYXN5bmMgKCkgPT4ge1xuICAgIHJldHVybiBhd2FpdCBjcmVhdGVBdWRpdFdpdGhDdXJyZW50Q29ubmVjdGlvbihyZWNvcmQsIGFyZ3MsIG1vZGVsQ2xhc3MpXG4gIH0pXG59XG5cbi8qKlxuICogQ3JlYXRlcyBhbiBhdWRpdCByb3cgdXNpbmcgdGhlIGN1cnJlbnQgbW9kZWwgZGF0YWJhc2UgY29ubmVjdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0fSByZWNvcmQgLSBSZWNvcmQgdG8gYXVkaXQuXG4gKiBAcGFyYW0ge0NyZWF0ZUF1ZGl0QXJnc30gYXJncyAtIEF1ZGl0IHJvdyBvcHRpb25zLlxuICogQHBhcmFtIHtBdWRpdGVkTW9kZWxDbGFzc30gbW9kZWxDbGFzcyAtIEF1ZGl0ZWQgbW9kZWwgY2xhc3MuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxudW1iZXIgfCBzdHJpbmc+fSBDcmVhdGVkIGF1ZGl0IHJvdyBpZC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gY3JlYXRlQXVkaXRXaXRoQ3VycmVudENvbm5lY3Rpb24ocmVjb3JkLCBhcmdzLCBtb2RlbENsYXNzKSB7XG4gIGlmICghcmVjb3JkLmlzUGVyc2lzdGVkKCkpIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IGF1ZGl0IHVucGVyc2lzdGVkICR7bW9kZWxDbGFzcy5nZXRNb2RlbE5hbWUoKX0gcmVjb3JkYClcblxuICBjb25zdCBhY3Rpb24gPSBub3JtYWxpemVBY3Rpb24oYXJncy5hY3Rpb24pXG4gIGNvbnN0IGF1ZGl0ZWRDaGFuZ2VzID0gYXJncy5hdWRpdGVkQ2hhbmdlcyA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3MuYXVkaXRlZENoYW5nZXNcbiAgY29uc3QgcGFyYW1zID0gYXJncy5wYXJhbXMgPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmdzLnBhcmFtc1xuICBjb25zdCBkYiA9IG1vZGVsQ2xhc3MuY29ubmVjdGlvbigpXG4gIGNvbnN0IGN1cnJlbnREYXRlID0gbmV3IERhdGUoKVxuICBjb25zdCBhdWRpdEFjdGlvbklkID0gYXdhaXQgZmluZE9yQ3JlYXRlTG9va3VwSWQoe1xuICAgIGNvbHVtbk5hbWU6IFwiYWN0aW9uXCIsXG4gICAgZGIsXG4gICAgdGFibGVOYW1lOiBcImF1ZGl0X2FjdGlvbnNcIixcbiAgICB2YWx1ZTogYWN0aW9uLFxuICAgIGN1cnJlbnREYXRlXG4gIH0pXG4gIGNvbnN0IGF1ZGl0QXVkaXRhYmxlVHlwZUlkID0gYXdhaXQgZmluZE9yQ3JlYXRlTG9va3VwSWQoe1xuICAgIGNvbHVtbk5hbWU6IFwibmFtZVwiLFxuICAgIGRiLFxuICAgIHRhYmxlTmFtZTogXCJhdWRpdF9hdWRpdGFibGVfdHlwZXNcIixcbiAgICB2YWx1ZTogbW9kZWxDbGFzcy5nZXRNb2RlbE5hbWUoKSxcbiAgICBjdXJyZW50RGF0ZVxuICB9KVxuICBjb25zdCBhdWRpdElkID0gbmV3IFVVSUQoNCkuZm9ybWF0KClcblxuICBjb25zdCBpbnNlcnRSZXN1bHQgPSBhd2FpdCBkYi5xdWVyeShkYi5pbnNlcnRTcWwoe1xuICAgIHJldHVybkxhc3RJbnNlcnRlZENvbHVtbk5hbWVzOiBbXCJpZFwiXSxcbiAgICB0YWJsZU5hbWU6IFwiYXVkaXRzXCIsXG4gICAgZGF0YToge1xuICAgICAgaWQ6IGF1ZGl0SWQsXG4gICAgICBhdWRpdF9hY3Rpb25faWQ6IGF1ZGl0QWN0aW9uSWQsXG4gICAgICBhdWRpdF9hdWRpdGFibGVfdHlwZV9pZDogYXVkaXRBdWRpdGFibGVUeXBlSWQsXG4gICAgICBhdWRpdGFibGVfaWQ6IHJlY29yZC5pZCgpLFxuICAgICAgYXVkaXRhYmxlX3R5cGU6IG1vZGVsQ2xhc3MuZ2V0TW9kZWxOYW1lKCksXG4gICAgICBhdWRpdGVkX2NoYW5nZXM6IGF1ZGl0ZWRDaGFuZ2VzLFxuICAgICAgcGFyYW1zLFxuICAgICAgY3JlYXRlZF9hdDogY3VycmVudERhdGUsXG4gICAgICB1cGRhdGVkX2F0OiBjdXJyZW50RGF0ZVxuICAgIH1cbiAgfSkpXG4gIGNvbnN0IGluc2VydGVkQXVkaXRJZCA9IGF1ZGl0SWRGcm9tSW5zZXJ0UmVzdWx0KGluc2VydFJlc3VsdCkgPz8gYXVkaXRJZFxuXG4gIGF3YWl0IGVtaXRBdWRpdEV2ZW50KG1vZGVsQ2xhc3MsIGFjdGlvbiwge1xuICAgIGFjdGlvbixcbiAgICBhdWRpdElkOiBpbnNlcnRlZEF1ZGl0SWQsXG4gICAgYXVkaXRlZENoYW5nZXMsXG4gICAgcGFyYW1zLFxuICAgIHJlY29yZFxuICB9KVxuXG4gIHJldHVybiBpbnNlcnRlZEF1ZGl0SWRcbn1cblxuLyoqXG4gKiBSZWFkcyBhbiBhdWRpdCBpZCByZXR1cm5lZCBieSBJTlNFUlQgLi4uIFJFVFVSTklORyAvIE9VVFBVVC5cbiAqIEBwYXJhbSB7QXJyYXk8UmVjb3JkPHN0cmluZywgPz4+IHwgbnVsbCB8IHVuZGVmaW5lZH0gaW5zZXJ0UmVzdWx0IC0gSW5zZXJ0IHF1ZXJ5IHJlc3VsdC5cbiAqIEByZXR1cm5zIHtudW1iZXIgfCBzdHJpbmcgfCBudWxsfSBDcmVhdGVkIGF1ZGl0IGlkIHdoZW4gdGhlIGRyaXZlciByZXR1cm5lZCBpdC5cbiAqL1xuZnVuY3Rpb24gYXVkaXRJZEZyb21JbnNlcnRSZXN1bHQoaW5zZXJ0UmVzdWx0KSB7XG4gIGlmICghQXJyYXkuaXNBcnJheShpbnNlcnRSZXN1bHQpKSByZXR1cm4gbnVsbFxuXG4gIGNvbnN0IHJvdyA9IGluc2VydFJlc3VsdFswXVxuXG4gIGlmICghcm93KSByZXR1cm4gbnVsbFxuXG4gIGNvbnN0IGlkID0gcm93LmlkXG5cbiAgaWYgKHR5cGVvZiBpZCA9PSBcIm51bWJlclwiIHx8IHR5cGVvZiBpZCA9PSBcInN0cmluZ1wiKSByZXR1cm4gaWRcblxuICByZXR1cm4gbnVsbFxufVxuXG4vKipcbiAqIENhcHR1cmVzIGNyZWF0ZSBjaGFuZ2VzIG9uIGEgbW9kZWwgaW5zdGFuY2UuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vaW5kZXguanNcIikuZGVmYXVsdCAmIHtfcGVuZGluZ0NyZWF0ZUF1ZGl0Q2hhbmdlcz86IEF1ZGl0Q2hhbmdlc319IHJlY29yZCAtIFJlY29yZCB0byBjYXB0dXJlLlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIGNhcHR1cmVDcmVhdGVBdWRpdENoYW5nZXMocmVjb3JkKSB7XG4gIHJlY29yZC5fcGVuZGluZ0NyZWF0ZUF1ZGl0Q2hhbmdlcyA9IGF1ZGl0Q2hhbmdlc0ZvckN1cnJlbnRDaGFuZ2VzKHJlY29yZClcbn1cblxuLyoqXG4gKiBDcmVhdGVzIHRoZSBjcmVhdGUgYXVkaXQgcm93IGZvciBhIG1vZGVsIGluc3RhbmNlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2luZGV4LmpzXCIpLmRlZmF1bHQgJiB7X3BlbmRpbmdDcmVhdGVBdWRpdENoYW5nZXM/OiBBdWRpdENoYW5nZXN9fSByZWNvcmQgLSBSZWNvcmQgdG8gYXVkaXQuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAqL1xuYXN5bmMgZnVuY3Rpb24gY3JlYXRlQ3JlYXRlQXVkaXQocmVjb3JkKSB7XG4gIGF3YWl0IGNyZWF0ZUF1ZGl0KHJlY29yZCwge1xuICAgIGFjdGlvbjogXCJjcmVhdGVcIixcbiAgICBhdWRpdGVkQ2hhbmdlczogcmVjb3JkLl9wZW5kaW5nQ3JlYXRlQXVkaXRDaGFuZ2VzIHx8IG51bGxcbiAgfSlcblxuICByZWNvcmQuX3BlbmRpbmdDcmVhdGVBdWRpdENoYW5nZXMgPSB1bmRlZmluZWRcbn1cblxuLyoqXG4gKiBDYXB0dXJlcyB1cGRhdGUgY2hhbmdlcyBvbiBhIG1vZGVsIGluc3RhbmNlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2luZGV4LmpzXCIpLmRlZmF1bHQgJiB7X3BlbmRpbmdVcGRhdGVBdWRpdENoYW5nZXM/OiBBdWRpdENoYW5nZXN9fSByZWNvcmQgLSBSZWNvcmQgdG8gY2FwdHVyZS5cbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5mdW5jdGlvbiBjYXB0dXJlVXBkYXRlQXVkaXRDaGFuZ2VzKHJlY29yZCkge1xuICByZWNvcmQuX3BlbmRpbmdVcGRhdGVBdWRpdENoYW5nZXMgPSBhdWRpdENoYW5nZXNGb3JDdXJyZW50Q2hhbmdlcyhyZWNvcmQpXG59XG5cbi8qKlxuICogQ3JlYXRlcyB0aGUgdXBkYXRlIGF1ZGl0IHJvdyBmb3IgYSBtb2RlbCBpbnN0YW5jZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0ICYge19wZW5kaW5nVXBkYXRlQXVkaXRDaGFuZ2VzPzogQXVkaXRDaGFuZ2VzfX0gcmVjb3JkIC0gUmVjb3JkIHRvIGF1ZGl0LlxuICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVVwZGF0ZUF1ZGl0KHJlY29yZCkge1xuICBjb25zdCBhdWRpdGVkQ2hhbmdlcyA9IHJlY29yZC5fcGVuZGluZ1VwZGF0ZUF1ZGl0Q2hhbmdlcyB8fCBudWxsXG5cbiAgcmVjb3JkLl9wZW5kaW5nVXBkYXRlQXVkaXRDaGFuZ2VzID0gdW5kZWZpbmVkXG5cbiAgaWYgKCFhdWRpdGVkQ2hhbmdlcyB8fCBPYmplY3Qua2V5cyhhdWRpdGVkQ2hhbmdlcykubGVuZ3RoIDw9IDApIHJldHVyblxuXG4gIGF3YWl0IGNyZWF0ZUF1ZGl0KHJlY29yZCwge1xuICAgIGFjdGlvbjogXCJ1cGRhdGVcIixcbiAgICBhdWRpdGVkQ2hhbmdlc1xuICB9KVxufVxuXG4vKipcbiAqIENyZWF0ZXMgdGhlIGRlc3Ryb3kgYXVkaXQgcm93IGZvciBhIG1vZGVsIGluc3RhbmNlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2luZGV4LmpzXCIpLmRlZmF1bHR9IHJlY29yZCAtIFJlY29yZCB0byBhdWRpdC5cbiAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICovXG5hc3luYyBmdW5jdGlvbiBjcmVhdGVEZXN0cm95QXVkaXQocmVjb3JkKSB7XG4gIGF3YWl0IGNyZWF0ZUF1ZGl0KHJlY29yZCwge1xuICAgIGFjdGlvbjogXCJkZXN0cm95XCIsXG4gICAgYXVkaXRlZENoYW5nZXM6IGF1ZGl0Q2hhbmdlc0ZvckRlc3Ryb3kocmVjb3JkKVxuICB9KVxufVxuXG4vKipcbiAqIFJldHVybnMgcmVjb3JkcyB3aXRob3V0IGFuIGF1ZGl0IHJvdyBmb3IgdGhlIGdpdmVuIGFjdGlvbi5cbiAqIEB0ZW1wbGF0ZSB7QXVkaXRlZE1vZGVsQ2xhc3N9IE1DXG4gKiBAcGFyYW0ge01DfSBtb2RlbENsYXNzIC0gTW9kZWwgY2xhc3MgdG8gc2NvcGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gYWN0aW9uIC0gQXVkaXQgYWN0aW9uIHRvIGV4Y2x1ZGUuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vcXVlcnkvbW9kZWwtY2xhc3MtcXVlcnkuanNcIikuZGVmYXVsdDxNQz59IFF1ZXJ5IHNjb3BlZCB0byByZWNvcmRzIHdpdGhvdXQgdGhhdCBhdWRpdCBhY3Rpb24uXG4gKi9cbmZ1bmN0aW9uIHdpdGhvdXRBdWRpdChtb2RlbENsYXNzLCBhY3Rpb24pIHtcbiAgY29uc3QgZGIgPSBtb2RlbENsYXNzLmNvbm5lY3Rpb24oKVxuICBjb25zdCBtb2RlbFRhYmxlU3FsID0gZGIucXVvdGVUYWJsZShtb2RlbENsYXNzLnRhYmxlTmFtZSgpKVxuICBjb25zdCBhdWRpdHNUYWJsZVNxbCA9IGRiLnF1b3RlVGFibGUoXCJhdWRpdHNcIilcbiAgY29uc3QgYXVkaXRBY3Rpb25zVGFibGVTcWwgPSBkYi5xdW90ZVRhYmxlKFwiYXVkaXRfYWN0aW9uc1wiKVxuICBjb25zdCBtb2RlbFByaW1hcnlLZXlTcWwgPSBgJHttb2RlbFRhYmxlU3FsfS4ke2RiLnF1b3RlQ29sdW1uKG1vZGVsQ2xhc3MucHJpbWFyeUtleSgpKX1gXG4gIGNvbnN0IGF1ZGl0QXVkaXRhYmxlSWRTcWwgPSBgJHthdWRpdHNUYWJsZVNxbH0uJHtkYi5xdW90ZUNvbHVtbihcImF1ZGl0YWJsZV9pZFwiKX1gXG4gIGNvbnN0IGF1ZGl0QXVkaXRhYmxlVHlwZVNxbCA9IGAke2F1ZGl0c1RhYmxlU3FsfS4ke2RiLnF1b3RlQ29sdW1uKFwiYXVkaXRhYmxlX3R5cGVcIil9YFxuICBjb25zdCBhdWRpdEFjdGlvbklkU3FsID0gYCR7YXVkaXRzVGFibGVTcWx9LiR7ZGIucXVvdGVDb2x1bW4oXCJhdWRpdF9hY3Rpb25faWRcIil9YFxuICBjb25zdCBhdWRpdEFjdGlvbnNJZFNxbCA9IGAke2F1ZGl0QWN0aW9uc1RhYmxlU3FsfS4ke2RiLnF1b3RlQ29sdW1uKFwiaWRcIil9YFxuICBjb25zdCBhdWRpdEFjdGlvbnNBY3Rpb25TcWwgPSBgJHthdWRpdEFjdGlvbnNUYWJsZVNxbH0uJHtkYi5xdW90ZUNvbHVtbihcImFjdGlvblwiKX1gXG5cbiAgcmV0dXJuIG1vZGVsQ2xhc3NcbiAgICAuYWxsKClcbiAgICAud2hlcmUoYFxuICAgICAgTk9UIEVYSVNUUyAoXG4gICAgICAgIFNFTEVDVCAxXG4gICAgICAgIEZST00gJHthdWRpdHNUYWJsZVNxbH1cbiAgICAgICAgSU5ORVIgSk9JTiAke2F1ZGl0QWN0aW9uc1RhYmxlU3FsfVxuICAgICAgICAgIE9OICR7YXVkaXRBY3Rpb25zSWRTcWx9ID0gJHthdWRpdEFjdGlvbklkU3FsfVxuICAgICAgICBXSEVSRSAke2F1ZGl0QXVkaXRhYmxlVHlwZVNxbH0gPSAke2RiLnF1b3RlKG1vZGVsQ2xhc3MuZ2V0TW9kZWxOYW1lKCkpfVxuICAgICAgICAgIEFORCAke2F1ZGl0QXVkaXRhYmxlSWRTcWx9ID0gJHttb2RlbFByaW1hcnlLZXlTcWx9XG4gICAgICAgICAgQU5EICR7YXVkaXRBY3Rpb25zQWN0aW9uU3FsfSA9ICR7ZGIucXVvdGUobm9ybWFsaXplQWN0aW9uKGFjdGlvbikpfVxuICAgICAgKVxuICAgIGApXG59XG5cbi8qKlxuICogRmluZHMgb3IgY3JlYXRlcyBhIGxvb2t1cCByb3cgYW5kIHJldHVybnMgaXRzIGlkLlxuICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zIG9iamVjdC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLmNvbHVtbk5hbWUgLSBMb29rdXAgdmFsdWUgY29sdW1uLlxuICogQHBhcmFtIHtEYXRlfSBhcmdzLmN1cnJlbnREYXRlIC0gVGltZXN0YW1wIHRvIHdyaXRlIHdoZW4gaW5zZXJ0aW5nLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9kcml2ZXJzL2Jhc2UuanNcIikuZGVmYXVsdH0gYXJncy5kYiAtIERhdGFiYXNlIGRyaXZlci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLnRhYmxlTmFtZSAtIExvb2t1cCB0YWJsZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLnZhbHVlIC0gTG9va3VwIHZhbHVlLlxuICogQHJldHVybnMge1Byb21pc2U8bnVtYmVyIHwgc3RyaW5nPn0gTG9va3VwIHJvdyBpZC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZmluZE9yQ3JlYXRlTG9va3VwSWQoe2NvbHVtbk5hbWUsIGN1cnJlbnREYXRlLCBkYiwgdGFibGVOYW1lLCB2YWx1ZX0pIHtcbiAgYXdhaXQgZGIudXBzZXJ0KHtcbiAgICB0YWJsZU5hbWUsXG4gICAgY29uZmxpY3RDb2x1bW5zOiBbY29sdW1uTmFtZV0sXG4gICAgdXBkYXRlQ29sdW1uczogW2NvbHVtbk5hbWVdLFxuICAgIGRhdGE6IHtcbiAgICAgIGlkOiBuZXcgVVVJRCg0KS5mb3JtYXQoKSxcbiAgICAgIFtjb2x1bW5OYW1lXTogdmFsdWUsXG4gICAgICBjcmVhdGVkX2F0OiBjdXJyZW50RGF0ZSxcbiAgICAgIHVwZGF0ZWRfYXQ6IGN1cnJlbnREYXRlXG4gICAgfVxuICB9KVxuXG4gIGNvbnN0IGlkID0gYXdhaXQgZmluZExvb2t1cElkKHtjb2x1bW5OYW1lLCBkYiwgdGFibGVOYW1lLCB2YWx1ZX0pXG5cbiAgaWYgKGlkID09PSBudWxsKSB0aHJvdyBuZXcgRXJyb3IoYENvdWxkbid0IGZpbmQgJHt0YWJsZU5hbWV9LiR7Y29sdW1uTmFtZX0gYWZ0ZXIgdXBzZXJ0YClcblxuICByZXR1cm4gaWRcbn1cblxuLyoqXG4gKiBGaW5kcyBhIGxvb2t1cCBpZCBieSB2YWx1ZS5cbiAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucyBvYmplY3QuXG4gKiBAcGFyYW0ge3N0cmluZ30gYXJncy5jb2x1bW5OYW1lIC0gTG9va3VwIHZhbHVlIGNvbHVtbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZHJpdmVycy9iYXNlLmpzXCIpLmRlZmF1bHR9IGFyZ3MuZGIgLSBEYXRhYmFzZSBkcml2ZXIuXG4gKiBAcGFyYW0ge3N0cmluZ30gYXJncy50YWJsZU5hbWUgLSBMb29rdXAgdGFibGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gYXJncy52YWx1ZSAtIExvb2t1cCB2YWx1ZS5cbiAqIEByZXR1cm5zIHtQcm9taXNlPG51bWJlciB8IHN0cmluZyB8IG51bGw+fSBMb29rdXAgcm93IGlkIG9yIG51bGwuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGZpbmRMb29rdXBJZCh7Y29sdW1uTmFtZSwgZGIsIHRhYmxlTmFtZSwgdmFsdWV9KSB7XG4gIGNvbnN0IHJvd3MgPSAvKiogQHR5cGUge0FycmF5PHtpZDogbnVtYmVyIHwgc3RyaW5nfT59ICovIChhd2FpdCBkYi5xdWVyeShgXG4gICAgU0VMRUNUICR7ZGIucXVvdGVDb2x1bW4oXCJpZFwiKX0gQVMgaWRcbiAgICBGUk9NICR7ZGIucXVvdGVUYWJsZSh0YWJsZU5hbWUpfVxuICAgIFdIRVJFICR7ZGIucXVvdGVDb2x1bW4oY29sdW1uTmFtZSl9ID0gJHtkYi5xdW90ZSh2YWx1ZSl9XG4gIGApKVxuXG4gIGlmIChyb3dzWzBdKSByZXR1cm4gcm93c1swXS5pZFxuXG4gIHJldHVybiBudWxsXG59XG5cbi8qKlxuICogTm9ybWFsaXplcyBhbiBhdWRpdCBhY3Rpb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gYWN0aW9uIC0gQWN0aW9uIG5hbWUuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBOb3JtYWxpemVkIGFjdGlvbi5cbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplQWN0aW9uKGFjdGlvbikge1xuICBjb25zdCBub3JtYWxpemVkQWN0aW9uID0gYWN0aW9uLnRyaW0oKVxuXG4gIGlmICghbm9ybWFsaXplZEFjdGlvbikgdGhyb3cgbmV3IEVycm9yKFwiQXVkaXQgYWN0aW9uIG11c3QgYmUgcHJlc2VudFwiKVxuXG4gIHJldHVybiBub3JtYWxpemVkQWN0aW9uXG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgY2FsbGJhY2sgbWFwIG93bmVkIGJ5IGEgbW9kZWwgY2xhc3MuXG4gKiBAcGFyYW0ge0F1ZGl0ZWRNb2RlbENsYXNzfSBtb2RlbENsYXNzIC0gTW9kZWwgY2xhc3MuXG4gKiBAcmV0dXJucyB7UmVjb3JkPHN0cmluZywgQXVkaXRDYWxsYmFja1tdPn0gQ2FsbGJhY2sgbWFwLlxuICovXG5mdW5jdGlvbiBhdWRpdENhbGxiYWNrc0Zvck1vZGVsQ2xhc3MobW9kZWxDbGFzcykge1xuICBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChtb2RlbENsYXNzLCBcIl9hdWRpdENhbGxiYWNrc1wiKSkge1xuICAgIG1vZGVsQ2xhc3MuX2F1ZGl0Q2FsbGJhY2tzID0ge31cbiAgfVxuXG4gIGNvbnN0IGNhbGxiYWNrcyA9IG1vZGVsQ2xhc3MuX2F1ZGl0Q2FsbGJhY2tzXG5cbiAgaWYgKCFjYWxsYmFja3MpIHRocm93IG5ldyBFcnJvcihgQXVkaXQgY2FsbGJhY2tzIHdlcmVuJ3QgaW5pdGlhbGl6ZWQgZm9yICR7bW9kZWxDbGFzcy5nZXRNb2RlbE5hbWUoKX1gKVxuXG4gIHJldHVybiBjYWxsYmFja3Ncbn1cblxuLyoqXG4gKiBFbWl0cyBhdWRpdCBjYWxsYmFja3MgZm9yIGEgbW9kZWwvYWN0aW9uIHBhaXIuXG4gKiBAcGFyYW0ge0F1ZGl0ZWRNb2RlbENsYXNzfSBtb2RlbENsYXNzIC0gTW9kZWwgY2xhc3MuXG4gKiBAcGFyYW0ge3N0cmluZ30gYWN0aW9uIC0gQXVkaXQgYWN0aW9uLlxuICogQHBhcmFtIHtBdWRpdEV2ZW50UGF5bG9hZH0gcGF5bG9hZCAtIEV2ZW50IHBheWxvYWQuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZW1pdEF1ZGl0RXZlbnQobW9kZWxDbGFzcywgYWN0aW9uLCBwYXlsb2FkKSB7XG4gIGNvbnN0IGNhbGxiYWNrcyA9IGF1ZGl0Q2FsbGJhY2tzRm9yTW9kZWxDbGFzcyhtb2RlbENsYXNzKVthY3Rpb25dIHx8IFtdXG5cbiAgZm9yIChjb25zdCBjYWxsYmFjayBvZiBbLi4uY2FsbGJhY2tzXSkge1xuICAgIGF3YWl0IGNhbGxiYWNrKHBheWxvYWQpXG4gIH1cbn1cblxuZXhwb3J0IHtcbiAgY2FwdHVyZUNyZWF0ZUF1ZGl0Q2hhbmdlcyxcbiAgY2FwdHVyZVVwZGF0ZUF1ZGl0Q2hhbmdlcyxcbiAgY3JlYXRlQXVkaXQsXG4gIGNyZWF0ZUNyZWF0ZUF1ZGl0LFxuICBjcmVhdGVEZXN0cm95QXVkaXQsXG4gIGNyZWF0ZVVwZGF0ZUF1ZGl0LFxuICByZWdpc3RlckF1ZGl0Q2FsbGJhY2ssXG4gIHJlZ2lzdGVyQXVkaXRpbmcsXG4gIHdpdGhvdXRBdWRpdFxufVxuIl19
791
+ export { AuditEvents, captureCreateAuditChanges, captureUpdateAuditChanges, createAudit, createCreateAudit, createDestroyAudit, createUpdateAudit, createSharedAuditTablesMigration, dedicatedAuditTableNameForTable, initializeAuditedModelRelationships, initializeAuditing, registerAuditCallback, registerAuditing, withoutAudit };
792
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXVkaXRpbmcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvZGF0YWJhc2UvcmVjb3JkL2F1ZGl0aW5nLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLElBQUksTUFBTSxXQUFXLENBQUE7QUFFNUI7OztHQUdHO0FBRUg7Ozs7Ozs7O0dBUUc7QUFFSDs7O0dBR0c7QUFFSDs7Ozs7O0dBTUc7QUFFSDs7Ozs7Ozs7R0FRRztBQUVIOzs7Ozs7O0dBT0c7QUFFSCxtQ0FBbUM7QUFDbkMsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFBO0FBRXJDLCtEQUErRDtBQUMvRCxNQUFNLGVBQWUsR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFBO0FBRWpDLE1BQU0sMkJBQTJCLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQTtBQUVqRCw4RUFBOEU7QUFDOUUsd0RBQXdEO0FBQ3hELDhFQUE4RTtBQUU5RSx1RkFBdUY7QUFDdkYsSUFBSSxzQkFBc0IsR0FBRyxFQUFFLENBQUE7QUFFL0I7Ozs7OztHQU1HO0FBRUgsOEJBQThCO0FBQzlCLE1BQU0sV0FBVyxHQUFHO0lBQ2xCLDJJQUEySTtJQUMzSSxJQUFJLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxJQUFJO1FBQ3JCLE1BQU0sT0FBTyxHQUFHLHNCQUFzQixDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQTtRQUNsRCxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFBO1FBRXZDLEtBQUssTUFBTSxRQUFRLElBQUksQ0FBQyxHQUFHLFNBQVMsQ0FBQyxFQUFFLENBQUM7WUFDdEMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQ2hCLENBQUM7SUFDSCxDQUFDO0lBRUQsNE1BQTRNO0lBQzVNLE9BQU8sQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLFFBQVE7UUFDNUIsSUFBSSxDQUFDLHNCQUFzQixD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LENBQUE7WUFDL0IsTUFBTSxLQUFLLENBQUMsU0FBUyxDQUFDLHVCQUF1QixDQUFDLENBQUE7WUFDOUMsTUFBTSxLQUFLLENBQUMsU0FBUyxDQUFDLGVBQWUsQ0FBQyxDQUFBO1FBQ3hDLENBQUM7S0FDRixDQUFBO0FBQ0gsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLCtCQUErQixDQUFDLGNBQWM7SUFDckQsSUFBSSxjQUFjLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDakMsT0FBTyxHQUFHLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQTtJQUNoRCxDQUFDO0lBRUQsT0FBTyxHQUFHLGNBQWMsU0FBUyxDQUFBO0FBQ25DLENBQUM7QUFFRCxPQUFPLEVBQ0wsV0FBVyxFQUNYLHlCQUF5QixFQUN6Qix5QkFBeUIsRUFDekIsV0FBVyxFQUNYLGlCQUFpQixFQUNqQixrQkFBa0IsRUFDbEIsaUJBQWlCLEVBQ2pCLGdDQUFnQyxFQUNoQywrQkFBK0IsRUFDL0IsbUNBQW1DLEVBQ25DLGtCQUFrQixFQUNsQixxQkFBcUIsRUFDckIsZ0JBQWdCLEVBQ2hCLFlBQVksRUFDYixDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCBVVUlEIGZyb20gXCJwdXJlLXV1aWRcIlxuXG4vKipcbiAqIEF1ZGl0Q2hhbmdlcyB0eXBlLlxuICogQHR5cGVkZWYge1JlY29yZDxzdHJpbmcsID8+fSBBdWRpdENoYW5nZXNcbiAqL1xuXG4vKipcbiAqIEF1ZGl0RXZlbnRQYXlsb2FkIHR5cGUuXG4gKiBAdHlwZWRlZiB7b2JqZWN0fSBBdWRpdEV2ZW50UGF5bG9hZFxuICogQHByb3BlcnR5IHtzdHJpbmd9IGFjdGlvbiAtIEF1ZGl0IGFjdGlvbiBuYW1lLlxuICogQHByb3BlcnR5IHtudW1iZXIgfCBzdHJpbmd9IGF1ZGl0SWQgLSBDcmVhdGVkIGF1ZGl0IHJvdyBpZC5cbiAqIEBwcm9wZXJ0eSB7QXVkaXRDaGFuZ2VzIHwgbnVsbH0gYXVkaXRlZENoYW5nZXMgLSBDaGFuZ2VzIGNhcHR1cmVkIGZvciB0aGUgYXVkaXQuXG4gKiBAcHJvcGVydHkge1JlY29yZDxzdHJpbmcsID8+IHwgbnVsbH0gcGFyYW1zIC0gT3B0aW9uYWwgY2FsbGVyLXN1cHBsaWVkIGF1ZGl0IHBhcmFtcy5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0fSByZWNvcmQgLSBBdWRpdGVkIHJlY29yZC5cbiAqL1xuXG4vKipcbiAqIEF1ZGl0Q2FsbGJhY2sgdHlwZS5cbiAqIEB0eXBlZGVmIHsocGF5bG9hZDogQXVkaXRFdmVudFBheWxvYWQpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+fSBBdWRpdENhbGxiYWNrXG4gKi9cblxuLyoqXG4gKiBDcmVhdGVBdWRpdEFyZ3MgdHlwZS5cbiAqIEB0eXBlZGVmIHtvYmplY3R9IENyZWF0ZUF1ZGl0QXJnc1xuICogQHByb3BlcnR5IHtzdHJpbmd9IGFjdGlvbiAtIEF1ZGl0IGFjdGlvbiBuYW1lLlxuICogQHByb3BlcnR5IHtBdWRpdENoYW5nZXMgfCBudWxsfSBbYXVkaXRlZENoYW5nZXNdIC0gRXhwbGljaXQgY2hhbmdlcyB0byBwZXJzaXN0LlxuICogQHByb3BlcnR5IHtSZWNvcmQ8c3RyaW5nLCA/PiB8IG51bGx9IFtwYXJhbXNdIC0gT3B0aW9uYWwgbWV0YWRhdGEgdG8gc3RvcmUgd2l0aCB0aGUgYXVkaXQuXG4gKi9cblxuLyoqXG4gKiBBdWRpdGVkTW9kZWxDbGFzcyB0eXBlLlxuICogQHR5cGVkZWYge3R5cGVvZiBpbXBvcnQoXCIuL2luZGV4LmpzXCIpLmRlZmF1bHQgJiB7XG4gKiAgIF9hdWRpdENhbGxiYWNrcz86IFJlY29yZDxzdHJpbmcsIEF1ZGl0Q2FsbGJhY2tbXT4sXG4gKiAgIF9hdWRpdExpZmVjeWNsZUNhbGxiYWNrc1JlZ2lzdGVyZWQ/OiBib29sZWFuLFxuICogICBfYXVkaXRUYWJsZVJlc29sdmVkPzogYm9vbGVhbixcbiAqICAgX2F1ZGl0VGFibGVEYXRhPzogQXVkaXRUYWJsZURhdGFcbiAqIH19IEF1ZGl0ZWRNb2RlbENsYXNzXG4gKi9cblxuLyoqXG4gKiBBdWRpdFRhYmxlRGF0YSB0eXBlLlxuICogQHR5cGVkZWYge29iamVjdH0gQXVkaXRUYWJsZURhdGFcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gZGVkaWNhdGVkIC0gV2hldGhlciBhIGRlZGljYXRlZCBhdWRpdCB0YWJsZSBleGlzdHMuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gdGFibGVOYW1lIC0gTmFtZSBvZiB0aGUgYXVkaXQgdGFibGUuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gZm9yZWlnbktleSAtIENvbHVtbiBuYW1lIHRoYXQgcmVmZXJlbmNlcyB0aGUgYXVkaXRlZCBtb2RlbC5cbiAqIEBwcm9wZXJ0eSB7dHlwZW9mIGltcG9ydChcIi4vaW5kZXguanNcIikuZGVmYXVsdH0gYXVkaXRDbGFzcyAtIFRoZSBhdWRpdCBtb2RlbCBjbGFzcyB0byB1c2UuXG4gKi9cblxuLyoqIEB0eXBlIHtNYXA8c3RyaW5nLCBib29sZWFuPn0gKi9cbmNvbnN0IGRlZGljYXRlZFRhYmxlQ2FjaGUgPSBuZXcgTWFwKClcblxuLyoqIEB0eXBlIHtNYXA8c3RyaW5nLCB0eXBlb2YgaW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0Pn0gKi9cbmNvbnN0IGF1ZGl0Q2xhc3NDYWNoZSA9IG5ldyBNYXAoKVxuXG5jb25zdCBnZW5lcmF0ZWRBdWRpdFJlbGF0aW9uc2hpcHMgPSBuZXcgV2Vha1NldCgpXG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gR2xvYmFsIGV2ZW50IGJ1cyAobGlrZSBBY3RpdmVSZWNvcmRBdWRpdGFibGU6OkV2ZW50cylcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKiogQHR5cGUge1JlY29yZDxzdHJpbmcsIFJlY29yZDxzdHJpbmcsIEFycmF5PChhcmdzOiBBdWRpdEV2ZW50UGF5bG9hZCkgPT4gdm9pZD4+Pn0gKi9cbmxldCBnbG9iYWxFdmVudENvbm5lY3Rpb25zID0ge31cblxuLyoqXG4gKiBHbG9iYWwgYXVkaXQgZXZlbnQgYnVzIG1hdGNoaW5nIEFjdGl2ZVJlY29yZEF1ZGl0YWJsZTo6RXZlbnRzLlxuICogQHR5cGVkZWYge29iamVjdH0gQXVkaXRFdmVudHNUeXBlXG4gKiBAcHJvcGVydHkgeyh0eXBlOiBzdHJpbmcsIGFjdGlvbjogc3RyaW5nLCBhcmdzOiBBdWRpdEV2ZW50UGF5bG9hZCkgPT4gdm9pZH0gY2FsbCAtIEZpcmUgYWxsIGNhbGxiYWNrcyBmb3IgYSBtb2RlbCB0eXBlICsgYWN0aW9uLlxuICogQHByb3BlcnR5IHsodHlwZTogc3RyaW5nLCBhY3Rpb246IHN0cmluZywgY2FsbGJhY2s6IChhcmdzOiBBdWRpdEV2ZW50UGF5bG9hZCkgPT4gdm9pZCkgPT4gKCkgPT4gdm9pZH0gY29ubmVjdCAtIFJlZ2lzdGVyIGEgY2FsbGJhY2sgZm9yIGEgbW9kZWwgdHlwZSArIGFjdGlvbi4gUmV0dXJucyBhbiB1bnN1YnNjcmliZSBmdW5jdGlvbi5cbiAqIEBwcm9wZXJ0eSB7KCkgPT4gdm9pZH0gcmVzZXQgLSBDbGVhciBhbGwgcmVnaXN0ZXJlZCBjYWxsYmFja3MuXG4gKi9cblxuLyoqIEB0eXBlIHtBdWRpdEV2ZW50c1R5cGV9ICovXG5jb25zdCBBdWRpdEV2ZW50cyA9IHtcbiAgLyoqIEZpcmUgYWxsIHJlZ2lzdGVyZWQgY2FsbGJhY2tzIGZvciBhIG1vZGVsIHR5cGUgKyBhY3Rpb24uIEBwYXJhbSB7c3RyaW5nfSB0eXBlIEBwYXJhbSB7c3RyaW5nfSBhY3Rpb24gQHBhcmFtIHtBdWRpdEV2ZW50UGF5bG9hZH0gYXJncyAqL1xuICBjYWxsKHR5cGUsIGFjdGlvbiwgYXJncykge1xuICAgIGNvbnN0IGFjdGlvbnMgPSBnbG9iYWxFdmVudENvbm5lY3Rpb25zW3R5cGVdIHx8IHt9XG4gICAgY29uc3QgY2FsbGJhY2tzID0gYWN0aW9uc1thY3Rpb25dIHx8IFtdXG5cbiAgICBmb3IgKGNvbnN0IGNhbGxiYWNrIG9mIFsuLi5jYWxsYmFja3NdKSB7XG4gICAgICBjYWxsYmFjayhhcmdzKVxuICAgIH1cbiAgfSxcblxuICAvKiogUmVnaXN0ZXIgYSBjYWxsYmFjayBmb3IgYSBtb2RlbCB0eXBlICsgYWN0aW9uLiBSZXR1cm5zIGFuIHVuc3Vic2NyaWJlIGZ1bmN0aW9uLiBAcGFyYW0ge3N0cmluZ30gdHlwZSBAcGFyYW0ge3N0cmluZ30gYWN0aW9uIEBwYXJhbSB7KGFyZ3M6IEF1ZGl0RXZlbnRQYXlsb2FkKSA9PiB2b2lkfSBjYWxsYmFjayBAcmV0dXJucyB7KCkgPT4gdm9pZH0gKi9cbiAgY29ubmVjdCh0eXBlLCBhY3Rpb24sIGNhbGxiYWNrKSB7XG4gICAgaWYgKCFnbG9iYWxFdmVudENvbm5lY3Rpb25zW3R5cGVdKSB7XG4gICAgICBnbG9iYWxFdmVudENvbm5lY3Rpb25zW3R5cGVdID0ge31cbiAgICB9XG5cbiAgICBpZiAoIWdsb2JhbEV2ZW50Q29ubmVjdGlvbnNbdHlwZV1bYWN0aW9uXSkge1xuICAgICAgZ2xvYmFsRXZlbnRDb25uZWN0aW9uc1t0eXBlXVthY3Rpb25dID0gW11cbiAgICB9XG5cbiAgICBnbG9iYWxFdmVudENvbm5lY3Rpb25zW3R5cGVdW2FjdGlvbl0ucHVzaChjYWxsYmFjaylcblxuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBjb25zdCBsaXN0ID0gZ2xvYmFsRXZlbnRDb25uZWN0aW9uc1t0eXBlXT8uW2FjdGlvbl1cblxuICAgICAgaWYgKGxpc3QpIHtcbiAgICAgICAgY29uc3QgaW5kZXggPSBsaXN0LmluZGV4T2YoY2FsbGJhY2spXG5cbiAgICAgICAgaWYgKGluZGV4ID49IDApIHtcbiAgICAgICAgICBsaXN0LnNwbGljZShpbmRleCwgMSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfSxcblxuICAvKiogQ2xlYXIgYWxsIHJlZ2lzdGVyZWQgY2FsbGJhY2tzLiBAcmV0dXJucyB7dm9pZH0gKi9cbiAgcmVzZXQoKSB7XG4gICAgZ2xvYmFsRXZlbnRDb25uZWN0aW9ucyA9IHt9XG4gIH1cbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBUYWJsZSBkZXRlY3Rpb25cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGRlZGljYXRlZCBhdWRpdCB0YWJsZSBuYW1lIGZvciBhIG1vZGVsIGNsYXNzLlxuICogQHBhcmFtIHtBdWRpdGVkTW9kZWxDbGFzc30gbW9kZWxDbGFzcyAtIEF1ZGl0ZWQgbW9kZWwgY2xhc3MuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBlLmcuIFwicHJvamVjdF9hdWRpdHNcIiBmb3IgYSBcInByb2plY3RzXCIgdGFibGUuXG4gKi9cbmZ1bmN0aW9uIGRlZGljYXRlZEF1ZGl0VGFibGVOYW1lKG1vZGVsQ2xhc3MpIHtcbiAgY29uc3QgdGFibGUgPSBtb2RlbENsYXNzLnRhYmxlTmFtZSgpXG5cbiAgaWYgKHRhYmxlLmVuZHNXaXRoKFwic1wiKSkge1xuICAgIHJldHVybiBgJHt0YWJsZS5zbGljZSgwLCAtMSl9X2F1ZGl0c2BcbiAgfVxuXG4gIHJldHVybiBgJHt0YWJsZX1fYXVkaXRzYFxufVxuXG4vKipcbiAqIFJlc29sdmVzIGF1ZGl0IHRhYmxlIGRhdGEgZm9yIGEgbW9kZWwgY2xhc3MuIENhY2hlZCBwZXIgbW9kZWwuXG4gKiBDYWxsZWQgbGF6aWx5IG9uIGZpcnN0IGNyZWF0ZUF1ZGl0IC8gd2l0aG91dEF1ZGl0IC8gcmVsYXRpb25zaGlwIHVzYWdlLlxuICogQHBhcmFtIHtBdWRpdGVkTW9kZWxDbGFzc30gbW9kZWxDbGFzcyAtIEF1ZGl0ZWQgbW9kZWwgY2xhc3MuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxBdWRpdFRhYmxlRGF0YT59IFJlc29sdmVkIGF1ZGl0IHRhYmxlIG1ldGFkYXRhLlxuICovXG5hc3luYyBmdW5jdGlvbiByZXNvbHZlQXVkaXRUYWJsZURhdGEobW9kZWxDbGFzcykge1xuICBpZiAobW9kZWxDbGFzcy5fYXVkaXRUYWJsZVJlc29sdmVkICYmIG1vZGVsQ2xhc3MuX2F1ZGl0VGFibGVEYXRhKSB7XG4gICAgcmV0dXJuIG1vZGVsQ2xhc3MuX2F1ZGl0VGFibGVEYXRhXG4gIH1cblxuICBjb25zdCB0YWJsZURhdGEgPSBhd2FpdCBidWlsZEF1ZGl0VGFibGVEYXRhKG1vZGVsQ2xhc3MpXG4gIGNvbnN0IGNvbmZpZ3VyYXRpb24gPSBtb2RlbENsYXNzLl9nZXRDb25maWd1cmF0aW9uKClcblxuICB0YWJsZURhdGEuYXVkaXRDbGFzcy5yZWdpc3RlclJlY29yZENsYXNzKHtjb25maWd1cmF0aW9ufSlcbiAgYXdhaXQgdGFibGVEYXRhLmF1ZGl0Q2xhc3MuaW5pdGlhbGl6ZVJlY29yZCh7Y29uZmlndXJhdGlvbn0pXG5cbiAgbW9kZWxDbGFzcy5fYXVkaXRUYWJsZURhdGEgPSB0YWJsZURhdGFcbiAgbW9kZWxDbGFzcy5fYXVkaXRUYWJsZVJlc29sdmVkID0gdHJ1ZVxuXG4gIHJlZ2lzdGVyQXVkaXRSZWxhdGlvbnNoaXAobW9kZWxDbGFzcywgdGFibGVEYXRhKVxuXG4gIHJldHVybiB0YWJsZURhdGFcbn1cblxuLyoqXG4gKiBCdWlsZHMgYXVkaXQgdGFibGUgbWV0YWRhdGEgZm9yIGEgbW9kZWwgY2xhc3MuIFByZWZlcnMgdGhlIGNvbnN1bWVyJ3NcbiAqIHJlZ2lzdGVyZWQgQXVkaXQgbW9kZWwgZm9yIHNoYXJlZCB0YWJsZXM7IGZhbGxzIGJhY2sgdG8gYSBmcmFtZXdvcmstb3duZWRcbiAqIGR5bmFtaWMgY2xhc3MuXG4gKiBAcGFyYW0ge0F1ZGl0ZWRNb2RlbENsYXNzfSBtb2RlbENsYXNzIC0gQXVkaXRlZCBtb2RlbCBjbGFzcy5cbiAqIEByZXR1cm5zIHtQcm9taXNlPEF1ZGl0VGFibGVEYXRhPn0gQXVkaXQgdGFibGUgbWV0YWRhdGEuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGJ1aWxkQXVkaXRUYWJsZURhdGEobW9kZWxDbGFzcykge1xuICBjb25zdCBkZWRpY2F0ZWRUYWJsZSA9IGRlZGljYXRlZEF1ZGl0VGFibGVOYW1lKG1vZGVsQ2xhc3MpXG4gIGNvbnN0IGRlZGljYXRlZEV4aXN0cyA9IGF3YWl0IGRlZGljYXRlZFRhYmxlRXhpc3RzRm9yQ29ubmVjdGlvbihtb2RlbENsYXNzLCBkZWRpY2F0ZWRUYWJsZSlcblxuICBpZiAoZGVkaWNhdGVkRXhpc3RzKSB7XG4gICAgY29uc3QgYXVkaXRDbGFzcyA9IGRlZGljYXRlZEF1ZGl0Q2xhc3MobW9kZWxDbGFzcywgZGVkaWNhdGVkVGFibGUpXG4gICAgY29uc3QgbW9kZWxLZXkgPSBtb2RlbFBhcmFtS2V5KG1vZGVsQ2xhc3MpXG5cbiAgICByZXR1cm4ge1xuICAgICAgYXVkaXRDbGFzcyxcbiAgICAgIGRlZGljYXRlZDogdHJ1ZSxcbiAgICAgIGZvcmVpZ25LZXk6IGAke21vZGVsS2V5fV9pZGAsXG4gICAgICB0YWJsZU5hbWU6IGRlZGljYXRlZFRhYmxlXG4gICAgfVxuICB9XG5cbiAgY29uc3QgY29uZmlndXJhdGlvbiA9IG1vZGVsQ2xhc3MuX2dldENvbmZpZ3VyYXRpb24oKVxuXG4gIGNvbnN0IGNvbnN1bWVyQXVkaXRDbGFzcyA9IGNvbmZpZ3VyYXRpb24uZ2V0TW9kZWxDbGFzc2VzKCkuQXVkaXRcblxuICBpZiAoY29uc3VtZXJBdWRpdENsYXNzKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGF1ZGl0Q2xhc3M6IGNvbnN1bWVyQXVkaXRDbGFzcyxcbiAgICAgIGRlZGljYXRlZDogZmFsc2UsXG4gICAgICBmb3JlaWduS2V5OiBcImF1ZGl0YWJsZV9pZFwiLFxuICAgICAgdGFibGVOYW1lOiBcImF1ZGl0c1wiXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBhdWRpdENsYXNzOiBjYWNoZWRTaGFyZWRBdWRpdENsYXNzKG1vZGVsQ2xhc3MpLFxuICAgIGRlZGljYXRlZDogZmFsc2UsXG4gICAgZm9yZWlnbktleTogXCJhdWRpdGFibGVfaWRcIixcbiAgICB0YWJsZU5hbWU6IFwiYXVkaXRzXCJcbiAgfVxufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIGEgZGVkaWNhdGVkIGF1ZGl0IHRhYmxlIGV4aXN0cyBmb3IgYSBtb2RlbCdzIGNvbm5lY3Rpb24uXG4gKiBAcGFyYW0ge0F1ZGl0ZWRNb2RlbENsYXNzfSBtb2RlbENsYXNzIC0gQXVkaXRlZCBtb2RlbCBjbGFzcy5cbiAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBEZWRpY2F0ZWQgYXVkaXQgdGFibGUgbmFtZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtQcm9taXNlPGJvb2xlYW4+fSBXaGV0aGVyIHRoZSB0YWJsZSBleGlzdHMuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGRlZGljYXRlZFRhYmxlRXhpc3RzRm9yQ29ubmVjdGlvbihtb2RlbENsYXNzLCB0YWJsZU5hbWUpIHtcbiAgY29uc3QgZGF0YWJhc2VJZGVudGlmaWVyID0gbW9kZWxDbGFzcy5nZXREYXRhYmFzZUlkZW50aWZpZXIoKVxuICBjb25zdCBjYWNoZUtleSA9IGAke2RhdGFiYXNlSWRlbnRpZmllcn06JHt0YWJsZU5hbWV9YFxuICBjb25zdCBjYWNoZWQgPSBkZWRpY2F0ZWRUYWJsZUNhY2hlLmdldChjYWNoZUtleSlcblxuICBpZiAodHlwZW9mIGNhY2hlZCA9PT0gXCJib29sZWFuXCIpIHtcbiAgICByZXR1cm4gY2FjaGVkXG4gIH1cblxuICBjb25zdCBjb25uZWN0aW9uID0gbW9kZWxDbGFzcy5jb25uZWN0aW9uKClcbiAgY29uc3QgdGFibGUgPSBhd2FpdCBjb25uZWN0aW9uLmdldFRhYmxlQnlOYW1lKHRhYmxlTmFtZSwge3Rocm93RXJyb3I6IGZhbHNlfSlcbiAgY29uc3QgZXhpc3RzID0gQm9vbGVhbih0YWJsZSlcblxuICBkZWRpY2F0ZWRUYWJsZUNhY2hlLnNldChjYWNoZUtleSwgZXhpc3RzKVxuXG4gIHJldHVybiBleGlzdHNcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBEeW5hbWljIGF1ZGl0IGNsYXNzZXNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIFJldHVybnMgYSBmcmFtZXdvcmstb3duZWQgc2hhcmVkIEF1ZGl0IGNsYXNzIGZvciB0aGUgYGF1ZGl0c2AgdGFibGUuXG4gKiBUaGlzIGlzIG9ubHkgdXNlZCB3aGVuIG5vIGNvbnN1bWVyLXJlZ2lzdGVyZWQgQXVkaXQgbW9kZWwgZXhpc3RzLlxuICogQHBhcmFtIHtBdWRpdGVkTW9kZWxDbGFzc30gbW9kZWxDbGFzcyAtIEFueSBhdWRpdGVkIG1vZGVsIGNsYXNzICh1c2VkIHRvIGxvY2F0ZSBEYXRhYmFzZVJlY29yZCkuXG4gKiBAcmV0dXJucyB7dHlwZW9mIGltcG9ydChcIi4vaW5kZXguanNcIikuZGVmYXVsdH0gU2hhcmVkIEF1ZGl0IG1vZGVsIGNsYXNzLlxuICovXG5mdW5jdGlvbiBzaGFyZWRBdWRpdENsYXNzKG1vZGVsQ2xhc3MpIHtcbiAgY29uc3QgZGJSZWNvcmRDbGFzcyA9IGZpbmREYXRhYmFzZVJlY29yZENsYXNzKG1vZGVsQ2xhc3MpXG5cbiAgLyoqXG4gICAqIEZyYW1ld29yay1vd25lZCBBdWRpdCBtb2RlbCBmb3IgdGhlIHNoYXJlZCBgYXVkaXRzYCB0YWJsZS5cbiAgICovXG4gIGNsYXNzIEF1ZGl0IGV4dGVuZHMgZGJSZWNvcmRDbGFzcyB7XG4gICAgLyoqIFJldHVybnMgdGhlIGJhY2tpbmcgdGFibGUgbmFtZS4gQHJldHVybnMge3N0cmluZ30gKi9cbiAgICBzdGF0aWMgdGFibGVOYW1lKCkge1xuICAgICAgcmV0dXJuIFwiYXVkaXRzXCJcbiAgICB9XG4gIH1cblxuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQXVkaXQsIFwibW9kZWxOYW1lXCIsIHt2YWx1ZTogXCJBdWRpdFwiLCB3cml0YWJsZTogZmFsc2V9KVxuICBhcHBseUF1ZGl0Q2xhc3NEYXRhYmFzZVJvdXRpbmcobW9kZWxDbGFzcywgQXVkaXQpXG5cbiAgcmV0dXJuIC8qKiBAdHlwZSB7dHlwZW9mIGltcG9ydChcIi4vaW5kZXguanNcIikuZGVmYXVsdH0gKi8gKEF1ZGl0KVxufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGNhY2hlZCBmcmFtZXdvcmstb3duZWQgc2hhcmVkIEF1ZGl0IGNsYXNzIGZvciBhIGRhdGFiYXNlLlxuICogQHBhcmFtIHtBdWRpdGVkTW9kZWxDbGFzc30gbW9kZWxDbGFzcyAtIEFueSBhdWRpdGVkIG1vZGVsIGNsYXNzLlxuICogQHJldHVybnMge3R5cGVvZiBpbXBvcnQoXCIuL2luZGV4LmpzXCIpLmRlZmF1bHR9IFNoYXJlZCBBdWRpdCBtb2RlbCBjbGFzcy5cbiAqL1xuZnVuY3Rpb24gY2FjaGVkU2hhcmVkQXVkaXRDbGFzcyhtb2RlbENsYXNzKSB7XG4gIGNvbnN0IHJvdXRpbmdLZXkgPSBtb2RlbENsYXNzLmhhc1RlbmFudERhdGFiYXNlSWRlbnRpZmllclJlc29sdmVyKClcbiAgICA/IGB0ZW5hbnQ6JHttb2RlbENsYXNzLmdldE1vZGVsTmFtZSgpfWBcbiAgICA6IGBkYXRhYmFzZToke21vZGVsQ2xhc3MuZ2V0Q29uZmlndXJlZERhdGFiYXNlSWRlbnRpZmllcigpfWBcbiAgY29uc3QgY2FjaGVLZXkgPSBgc2hhcmVkOiR7cm91dGluZ0tleX1gXG4gIGxldCBhdWRpdENsYXNzID0gYXVkaXRDbGFzc0NhY2hlLmdldChjYWNoZUtleSlcblxuICBpZiAoIWF1ZGl0Q2xhc3MpIHtcbiAgICBhdWRpdENsYXNzID0gc2hhcmVkQXVkaXRDbGFzcyhtb2RlbENsYXNzKVxuICAgIGF1ZGl0Q2xhc3NDYWNoZS5zZXQoY2FjaGVLZXksIGF1ZGl0Q2xhc3MpXG4gIH1cblxuICByZXR1cm4gYXVkaXRDbGFzc1xufVxuXG4vKipcbiAqIFJldHVybnMgYSBkeW5hbWljIHBlci1tb2RlbCBhdWRpdCBjbGFzcyBmb3IgYSBkZWRpY2F0ZWQgdGFibGUuXG4gKiBAcGFyYW0ge0F1ZGl0ZWRNb2RlbENsYXNzfSBtb2RlbENsYXNzIC0gQXVkaXRlZCBtb2RlbCBjbGFzcy5cbiAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBEZWRpY2F0ZWQgYXVkaXQgdGFibGUgbmFtZSAoZS5nLiBcInByb2plY3RfYXVkaXRzXCIpLlxuICogQHJldHVybnMge3R5cGVvZiBpbXBvcnQoXCIuL2luZGV4LmpzXCIpLmRlZmF1bHR9IERlZGljYXRlZCBhdWRpdCBtb2RlbCBjbGFzcy5cbiAqL1xuZnVuY3Rpb24gZGVkaWNhdGVkQXVkaXRDbGFzcyhtb2RlbENsYXNzLCB0YWJsZU5hbWUpIHtcbiAgY29uc3QgZGJSZWNvcmRDbGFzcyA9IGZpbmREYXRhYmFzZVJlY29yZENsYXNzKG1vZGVsQ2xhc3MpXG4gIGNvbnN0IG1vZGVsTmFtZSA9IG1vZGVsQ2xhc3MuZ2V0TW9kZWxOYW1lKClcbiAgY29uc3QgbW9kZWxLZXkgPSBtb2RlbFBhcmFtS2V5KG1vZGVsQ2xhc3MpXG5cbiAgLyoqXG4gICAqIEZyYW1ld29yay1vd25lZCBwZXItbW9kZWwgQXVkaXQgY2xhc3MuXG4gICAqL1xuICBjbGFzcyBNb2RlbEF1ZGl0IGV4dGVuZHMgZGJSZWNvcmRDbGFzcyB7XG4gICAgLyoqIFJldHVybnMgdGhlIGJhY2tpbmcgdGFibGUgbmFtZS4gQHJldHVybnMge3N0cmluZ30gKi9cbiAgICBzdGF0aWMgdGFibGVOYW1lKCkge1xuICAgICAgcmV0dXJuIHRhYmxlTmFtZVxuICAgIH1cbiAgfVxuXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShNb2RlbEF1ZGl0LCBcIm1vZGVsTmFtZVwiLCB7dmFsdWU6IGAke21vZGVsTmFtZX1BdWRpdGAsIHdyaXRhYmxlOiBmYWxzZX0pXG4gIGFwcGx5QXVkaXRDbGFzc0RhdGFiYXNlUm91dGluZyhtb2RlbENsYXNzLCBNb2RlbEF1ZGl0KVxuICBNb2RlbEF1ZGl0LmJlbG9uZ3NUbyhtb2RlbEtleSwge2NsYXNzTmFtZTogbW9kZWxOYW1lfSlcblxuICByZXR1cm4gLyoqIEB0eXBlIHt0eXBlb2YgaW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0fSAqLyAoTW9kZWxBdWRpdClcbn1cblxuLyoqXG4gKiBNYWtlcyBmcmFtZXdvcmstb3duZWQgYXVkaXQgY2xhc3NlcyByZWFkIHRoZSBzYW1lIGRhdGFiYXNlIGFzIHRoZSBhdWRpdGVkIG1vZGVsLlxuICogQHBhcmFtIHtBdWRpdGVkTW9kZWxDbGFzc30gbW9kZWxDbGFzcyAtIEF1ZGl0ZWQgc291cmNlIG1vZGVsIGNsYXNzLlxuICogQHBhcmFtIHt0eXBlb2YgaW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0fSBhdWRpdENsYXNzIC0gR2VuZXJhdGVkIGF1ZGl0IGNsYXNzLlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIGFwcGx5QXVkaXRDbGFzc0RhdGFiYXNlUm91dGluZyhtb2RlbENsYXNzLCBhdWRpdENsYXNzKSB7XG4gIGF1ZGl0Q2xhc3Muc2V0RGF0YWJhc2VJZGVudGlmaWVyKG1vZGVsQ2xhc3MuZ2V0Q29uZmlndXJlZERhdGFiYXNlSWRlbnRpZmllcigpKVxuXG4gIGlmIChtb2RlbENsYXNzLmhhc1RlbmFudERhdGFiYXNlSWRlbnRpZmllclJlc29sdmVyKCkpIHtcbiAgICBhdWRpdENsYXNzLnN3aXRjaGVzVGVuYW50RGF0YWJhc2UoKHt0ZW5hbnR9KSA9PiBtb2RlbENsYXNzLmdldFRlbmFudERhdGFiYXNlSWRlbnRpZmllcih0ZW5hbnQpKVxuICB9XG59XG5cbi8qKlxuICogV2Fsa3MgdGhlIHByb3RvdHlwZSBjaGFpbiB0byBmaW5kIHRoZSByb290IERhdGFiYXNlUmVjb3JkIGNsYXNzLlxuICogQHBhcmFtIHtBdWRpdGVkTW9kZWxDbGFzc30gbW9kZWxDbGFzcyAtIEF1ZGl0ZWQgbW9kZWwgY2xhc3MuXG4gKiBAcmV0dXJucyB7dHlwZW9mIGltcG9ydChcIi4vaW5kZXguanNcIikuZGVmYXVsdH0gUm9vdCBEYXRhYmFzZVJlY29yZCBjbGFzcy5cbiAqL1xuZnVuY3Rpb24gZmluZERhdGFiYXNlUmVjb3JkQ2xhc3MobW9kZWxDbGFzcykge1xuICBsZXQgcmVjb3JkQ2xhc3MgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YobW9kZWxDbGFzcylcblxuICB3aGlsZSAocmVjb3JkQ2xhc3MgJiYgT2JqZWN0LmdldFByb3RvdHlwZU9mKHJlY29yZENsYXNzKSAhPT0gRnVuY3Rpb24ucHJvdG90eXBlKSB7XG4gICAgcmVjb3JkQ2xhc3MgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YocmVjb3JkQ2xhc3MpXG4gIH1cblxuICByZXR1cm4gLyoqIEB0eXBlIHt0eXBlb2YgaW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0fSAqLyAocmVjb3JkQ2xhc3MpXG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgcGFyYW1ldGVyLWtleSBuYW1lIGZvciBhIG1vZGVsIGNsYXNzLlxuICogQHBhcmFtIHtBdWRpdGVkTW9kZWxDbGFzc30gbW9kZWxDbGFzcyAtIEF1ZGl0ZWQgbW9kZWwgY2xhc3MuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBlLmcuIFwicHJvamVjdFwiIGZvciBcIlByb2plY3RcIi5cbiAqL1xuZnVuY3Rpb24gbW9kZWxQYXJhbUtleShtb2RlbENsYXNzKSB7XG4gIGNvbnN0IG5hbWUgPSBtb2RlbENsYXNzLmdldE1vZGVsTmFtZSgpXG5cbiAgcmV0dXJuIG5hbWUuY2hhckF0KDApLnRvTG93ZXJDYXNlKCkgKyBuYW1lLnNsaWNlKDEpXG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gUmVnaXN0cmF0aW9uIChzeW5jIOKAlCBjYWxsYmFja3Mgb25seTsgdGFibGUgZGV0ZWN0aW9uIGRlZmVycmVkKVxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogUmVnaXN0ZXJzIGxpZmVjeWNsZSBjYWxsYmFja3MgZm9yIGF1dG9tYXRpYyBjcmVhdGUvdXBkYXRlL2Rlc3Ryb3kgYXVkaXRpbmcuXG4gKiBUYWJsZSBkZXRlY3Rpb24gYW5kIHJlbGF0aW9uc2hpcCByZWdpc3RyYXRpb24gaGFwcGVuIGxhemlseSBvbiBmaXJzdCB1c2FnZS5cbiAqIENhbGxlZCBzeW5jaHJvbm91c2x5IGZyb20gTW9kZWwuYXVkaXRlZCgpIGF0IG1vZHVsZS1sb2FkIHRpbWUuXG4gKiBAcGFyYW0ge0F1ZGl0ZWRNb2RlbENsYXNzfSBtb2RlbENsYXNzIC0gTW9kZWwgY2xhc3MgdG8gYXVkaXQuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gcmVnaXN0ZXJBdWRpdGluZyhtb2RlbENsYXNzKSB7XG4gIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobW9kZWxDbGFzcywgXCJfYXVkaXRMaWZlY3ljbGVDYWxsYmFja3NSZWdpc3RlcmVkXCIpICYmIG1vZGVsQ2xhc3MuX2F1ZGl0TGlmZWN5Y2xlQ2FsbGJhY2tzUmVnaXN0ZXJlZCkge1xuICAgIHJldHVyblxuICB9XG5cbiAgbW9kZWxDbGFzcy5fYXVkaXRMaWZlY3ljbGVDYWxsYmFja3NSZWdpc3RlcmVkID0gdHJ1ZVxuICByZWdpc3RlckF1ZGl0UmVsYXRpb25zaGlwKG1vZGVsQ2xhc3MpXG4gIG1vZGVsQ2xhc3MuYmVmb3JlQ3JlYXRlKFwiY2FwdHVyZUNyZWF0ZUF1ZGl0Q2hhbmdlc1wiKVxuICBtb2RlbENsYXNzLmFmdGVyQ3JlYXRlKFwiY3JlYXRlQ3JlYXRlQXVkaXRcIilcbiAgbW9kZWxDbGFzcy5iZWZvcmVVcGRhdGUoXCJjYXB0dXJlVXBkYXRlQXVkaXRDaGFuZ2VzXCIpXG4gIG1vZGVsQ2xhc3MuYWZ0ZXJVcGRhdGUoXCJjcmVhdGVVcGRhdGVBdWRpdFwiKVxuICBtb2RlbENsYXNzLmFmdGVyRGVzdHJveShcImNyZWF0ZURlc3Ryb3lBdWRpdFwiKVxufVxuXG4vKipcbiAqIEluaXRpYWxpemVzIGF1ZGl0IG1ldGFkYXRhIGZvciBhdWRpdGVkIG1vZGVsIGNsYXNzZXMuXG4gKiBAcGFyYW0ge3R5cGVvZiBpbXBvcnQoXCIuL2luZGV4LmpzXCIpLmRlZmF1bHR9IG1vZGVsQ2xhc3MgLSBNb2RlbCBjbGFzcyB0byBpbml0aWFsaXplLlxuICogQHBhcmFtIHt7cmVzb2x2ZVRhYmxlRGF0YT86IGJvb2xlYW59fSBbYXJnc10gLSBJbml0aWFsaXphdGlvbiBvcHRpb25zLlxuICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGluaXRpYWxpemVBdWRpdGluZyhtb2RlbENsYXNzLCBhcmdzID0ge30pIHtcbiAgY29uc3Qge3Jlc29sdmVUYWJsZURhdGEgPSBmYWxzZX0gPSBhcmdzXG4gIGNvbnN0IGF1ZGl0ZWRNb2RlbENsYXNzID0gLyoqIEB0eXBlIHtBdWRpdGVkTW9kZWxDbGFzc30gKi8gKG1vZGVsQ2xhc3MpXG5cbiAgaWYgKCFhdWRpdGVkTW9kZWxDbGFzcy5fYXVkaXRMaWZlY3ljbGVDYWxsYmFja3NSZWdpc3RlcmVkKSB7XG4gICAgcmV0dXJuXG4gIH1cblxuICByZWdpc3RlckF1ZGl0UmVsYXRpb25zaGlwKGF1ZGl0ZWRNb2RlbENsYXNzKVxuXG4gIGlmIChyZXNvbHZlVGFibGVEYXRhICYmIGF1ZGl0ZWRNb2RlbENsYXNzLl9pbml0aWFsaXplZCAmJiBjYW5SZXNvbHZlQXVkaXRUYWJsZURhdGEoYXVkaXRlZE1vZGVsQ2xhc3MpKSB7XG4gICAgYXdhaXQgcmVzb2x2ZUF1ZGl0VGFibGVEYXRhKGF1ZGl0ZWRNb2RlbENsYXNzKVxuICB9XG59XG5cbi8qKlxuICogUmVzb2x2ZXMgYXVkaXQgbWV0YWRhdGEgYWZ0ZXIgYXBwbGljYXRpb24gYW5kIHBhY2thZ2UgbW9kZWwgY2xhc3NlcyBhcmUgcmVnaXN0ZXJlZC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vY29uZmlndXJhdGlvbi5qc1wiKS5kZWZhdWx0fSBjb25maWd1cmF0aW9uIC0gQ29uZmlndXJhdGlvbiB3aG9zZSBtb2RlbHMgc2hvdWxkIGJlIGZpbmFsaXplZC5cbiAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICovXG5hc3luYyBmdW5jdGlvbiBpbml0aWFsaXplQXVkaXRlZE1vZGVsUmVsYXRpb25zaGlwcyhjb25maWd1cmF0aW9uKSB7XG4gIGZvciAoY29uc3QgbW9kZWxDbGFzcyBvZiBPYmplY3QudmFsdWVzKGNvbmZpZ3VyYXRpb24uZ2V0TW9kZWxDbGFzc2VzKCkpKSB7XG4gICAgYXdhaXQgaW5pdGlhbGl6ZUF1ZGl0aW5nKG1vZGVsQ2xhc3MsIHtyZXNvbHZlVGFibGVEYXRhOiB0cnVlfSlcbiAgfVxufVxuXG4vKipcbiAqIFJlZ2lzdGVycyB0aGUgYXVkaXRzIHJlbGF0aW9uc2hpcCB3aXRob3V0IGZvcmNpbmcgYXVkaXQgdGFibGUgZGV0ZWN0aW9uLlxuICogQHBhcmFtIHtBdWRpdGVkTW9kZWxDbGFzc30gbW9kZWxDbGFzcyAtIE1vZGVsIGNsYXNzIHRvIGF1ZGl0LlxuICogQHBhcmFtIHtBdWRpdFRhYmxlRGF0YX0gW3RhYmxlRGF0YV0gLSBSZXNvbHZlZCBhdWRpdCB0YWJsZSBkYXRhIHdoZW4gYXZhaWxhYmxlLlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIHJlZ2lzdGVyQXVkaXRSZWxhdGlvbnNoaXAobW9kZWxDbGFzcywgdGFibGVEYXRhID0gZGVmYXVsdEF1ZGl0UmVsYXRpb25zaGlwVGFibGVEYXRhKG1vZGVsQ2xhc3MpKSB7XG4gIGlmIChtb2RlbENsYXNzLl9yZWxhdGlvbnNoaXBFeGlzdHMoXCJhdWRpdHNcIikpIHtcbiAgICBjb25zdCByZWxhdGlvbnNoaXAgPSBtb2RlbENsYXNzLmdldFJlbGF0aW9uc2hpcEJ5TmFtZShcImF1ZGl0c1wiKVxuXG4gICAgaWYgKGdlbmVyYXRlZEF1ZGl0UmVsYXRpb25zaGlwcy5oYXMocmVsYXRpb25zaGlwKSkge1xuICAgICAgcmVsYXRpb25zaGlwLmNsYXNzTmFtZSA9IHVuZGVmaW5lZFxuICAgICAgcmVsYXRpb25zaGlwLmtsYXNzID0gdGFibGVEYXRhLmF1ZGl0Q2xhc3NcbiAgICAgIHJlbGF0aW9uc2hpcC5mb3JlaWduS2V5ID0gdGFibGVEYXRhLmZvcmVpZ25LZXlcbiAgICAgIHJlbGF0aW9uc2hpcC5fZXhwbGljaXRGb3JlaWduS2V5ID0gdGFibGVEYXRhLmZvcmVpZ25LZXlcbiAgICAgIHJlbGF0aW9uc2hpcC5fcG9seW1vcnBoaWMgPSAhdGFibGVEYXRhLmRlZGljYXRlZFxuICAgICAgcmVsYXRpb25zaGlwLl9wb2x5bW9ycGhpY1R5cGVDb2x1bW4gPSB1bmRlZmluZWRcbiAgICB9XG5cbiAgICByZXR1cm5cbiAgfVxuXG4gIG1vZGVsQ2xhc3MuaGFzTWFueShcImF1ZGl0c1wiLCBhdWRpdFJlbGF0aW9uc2hpcFNjb3BlLCB7XG4gICAgZm9yZWlnbktleTogdGFibGVEYXRhLmZvcmVpZ25LZXksXG4gICAga2xhc3M6IHRhYmxlRGF0YS5hdWRpdENsYXNzLFxuICAgIHBvbHltb3JwaGljOiAhdGFibGVEYXRhLmRlZGljYXRlZFxuICB9KVxuICBnZW5lcmF0ZWRBdWRpdFJlbGF0aW9uc2hpcHMuYWRkKG1vZGVsQ2xhc3MuZ2V0UmVsYXRpb25zaGlwQnlOYW1lKFwiYXVkaXRzXCIpKVxufVxuXG4vKipcbiAqIFJldHVybnMgdW5yZXNvbHZlZCBzaGFyZWQtYXVkaXQgZGVmYXVsdHMgZm9yIGVhcmx5IHJlbGF0aW9uc2hpcCByZWdpc3RyYXRpb24uXG4gKiBAcGFyYW0ge0F1ZGl0ZWRNb2RlbENsYXNzfSBtb2RlbENsYXNzIC0gTW9kZWwgY2xhc3MgdG8gYXVkaXQuXG4gKiBAcmV0dXJucyB7QXVkaXRUYWJsZURhdGF9IFNoYXJlZCBhdWRpdCByZWxhdGlvbnNoaXAgZGVmYXVsdHMuXG4gKi9cbmZ1bmN0aW9uIGRlZmF1bHRBdWRpdFJlbGF0aW9uc2hpcFRhYmxlRGF0YShtb2RlbENsYXNzKSB7XG4gIHJldHVybiB7XG4gICAgYXVkaXRDbGFzczogY2FjaGVkU2hhcmVkQXVkaXRDbGFzcyhtb2RlbENsYXNzKSxcbiAgICBkZWRpY2F0ZWQ6IGZhbHNlLFxuICAgIGZvcmVpZ25LZXk6IFwiYXVkaXRhYmxlX2lkXCIsXG4gICAgdGFibGVOYW1lOiBcImF1ZGl0c1wiXG4gIH1cbn1cblxuLyoqXG4gKiBBcHBsaWVzIGRlZmF1bHQgYXVkaXQgb3JkZXJpbmcgdG8gZ2VuZXJhdGVkIGF1ZGl0IHJlbGF0aW9uc2hpcHMuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3F1ZXJ5L21vZGVsLWNsYXNzLXF1ZXJ5LmpzXCIpLmRlZmF1bHQ8dHlwZW9mIGltcG9ydChcIi4vaW5kZXguanNcIikuZGVmYXVsdD59IHF1ZXJ5IC0gQXVkaXQgcXVlcnkuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vcXVlcnkvbW9kZWwtY2xhc3MtcXVlcnkuanNcIikuZGVmYXVsdDx0eXBlb2YgaW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0Pn0gT3JkZXJlZCBhdWRpdCBxdWVyeS5cbiAqL1xuZnVuY3Rpb24gYXVkaXRSZWxhdGlvbnNoaXBTY29wZShxdWVyeSkge1xuICByZXR1cm4gcXVlcnkub3JkZXIoe2NvbHVtbjogXCJjcmVhdGVkX2F0XCIsIGRpcmVjdGlvbjogXCJERVNDXCJ9KVxufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIHRoZSBjdXJyZW50IHRlbmFudCBjb250ZXh0IGNhbiByZXNvbHZlIGF1ZGl0IHRhYmxlIGRhdGEuXG4gKiBAcGFyYW0ge0F1ZGl0ZWRNb2RlbENsYXNzfSBtb2RlbENsYXNzIC0gTW9kZWwgY2xhc3MgdG8gaW5zcGVjdC5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIGF1ZGl0IHRhYmxlIGRhdGEgY2FuIGJlIHJlc29sdmVkIGluIHRoZSBjdXJyZW50IHNjb3BlLlxuICovXG5mdW5jdGlvbiBjYW5SZXNvbHZlQXVkaXRUYWJsZURhdGEobW9kZWxDbGFzcykge1xuICBpZiAoIW1vZGVsQ2xhc3MuaGFzVGVuYW50RGF0YWJhc2VJZGVudGlmaWVyUmVzb2x2ZXIoKSkge1xuICAgIHJldHVybiB0cnVlXG4gIH1cblxuICBjb25zdCB0ZW5hbnREYXRhYmFzZUlkZW50aWZpZXIgPSBtb2RlbENsYXNzLmdldFRlbmFudERhdGFiYXNlSWRlbnRpZmllcigpXG5cbiAgaWYgKCF0ZW5hbnREYXRhYmFzZUlkZW50aWZpZXIpIHtcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuXG4gIHJldHVybiBtb2RlbENsYXNzLl9nZXRDb25maWd1cmF0aW9uKCkuaXNEYXRhYmFzZUlkZW50aWZpZXJBY3RpdmUodGVuYW50RGF0YWJhc2VJZGVudGlmaWVyKVxufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIENyZWF0aW5nIGF1ZGl0c1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogQ3JlYXRlcyBhbiBhdWRpdCByb3cgZm9yIGEgcmVjb3JkLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2luZGV4LmpzXCIpLmRlZmF1bHR9IHJlY29yZCAtIFJlY29yZCB0byBhdWRpdC5cbiAqIEBwYXJhbSB7Q3JlYXRlQXVkaXRBcmdzfSBhcmdzIC0gQXVkaXQgcm93IG9wdGlvbnMgKGFjdGlvbiwgYXVkaXRlZENoYW5nZXMsIHBhcmFtcykuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxudW1iZXIgfCBzdHJpbmc+fSBDcmVhdGVkIGF1ZGl0IHJvdyBpZC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gY3JlYXRlQXVkaXQocmVjb3JkLCBhcmdzKSB7XG4gIGNvbnN0IG1vZGVsQ2xhc3MgPSAvKiogQHR5cGUge0F1ZGl0ZWRNb2RlbENsYXNzfSAqLyAocmVjb3JkLmdldE1vZGVsQ2xhc3MoKSlcblxuICByZXR1cm4gYXdhaXQgbW9kZWxDbGFzcy5fZ2V0Q29uZmlndXJhdGlvbigpLmVuc3VyZUNvbm5lY3Rpb25zKHtuYW1lOiBgJHttb2RlbENsYXNzLmdldE1vZGVsTmFtZSgpfSBhdWRpdGB9LCBhc3luYyAoKSA9PiB7XG4gICAgcmV0dXJuIGF3YWl0IGNyZWF0ZUF1ZGl0V2l0aEN1cnJlbnRDb25uZWN0aW9uKHJlY29yZCwgYXJncywgbW9kZWxDbGFzcylcbiAgfSlcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGFuIGF1ZGl0IHJvdyB1c2luZyB0aGUgY3VycmVudCBtb2RlbCBkYXRhYmFzZSBjb25uZWN0aW9uLlxuICogUm91dGVzIHRvIHNoYXJlZCB0YWJsZSBvciBkZWRpY2F0ZWQgdGFibGUgYmFzZWQgb24gcmVzb2x2ZWQgYXVkaXQgdGFibGUgZGF0YS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0fSByZWNvcmQgLSBSZWNvcmQgdG8gYXVkaXQuXG4gKiBAcGFyYW0ge0NyZWF0ZUF1ZGl0QXJnc30gYXJncyAtIEF1ZGl0IHJvdyBvcHRpb25zIChhY3Rpb24sIGF1ZGl0ZWRDaGFuZ2VzLCBwYXJhbXMpLlxuICogQHBhcmFtIHtBdWRpdGVkTW9kZWxDbGFzc30gbW9kZWxDbGFzcyAtIEF1ZGl0ZWQgbW9kZWwgY2xhc3MuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxudW1iZXIgfCBzdHJpbmc+fSBDcmVhdGVkIGF1ZGl0IHJvdyBpZC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gY3JlYXRlQXVkaXRXaXRoQ3VycmVudENvbm5lY3Rpb24ocmVjb3JkLCBhcmdzLCBtb2RlbENsYXNzKSB7XG4gIGlmICghcmVjb3JkLmlzUGVyc2lzdGVkKCkpIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IGF1ZGl0IHVucGVyc2lzdGVkICR7bW9kZWxDbGFzcy5nZXRNb2RlbE5hbWUoKX0gcmVjb3JkYClcblxuICBjb25zdCB0YWJsZURhdGEgPSBhd2FpdCByZXNvbHZlQXVkaXRUYWJsZURhdGEobW9kZWxDbGFzcylcbiAgY29uc3QgYWN0aW9uID0gbm9ybWFsaXplQWN0aW9uKGFyZ3MuYWN0aW9uKVxuICBjb25zdCBhdWRpdGVkQ2hhbmdlcyA9IGFyZ3MuYXVkaXRlZENoYW5nZXMgPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmdzLmF1ZGl0ZWRDaGFuZ2VzXG4gIGNvbnN0IHBhcmFtcyA9IGFyZ3MucGFyYW1zID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJncy5wYXJhbXNcbiAgY29uc3QgZGIgPSBtb2RlbENsYXNzLmNvbm5lY3Rpb24oKVxuICBjb25zdCBjdXJyZW50RGF0ZSA9IG5ldyBEYXRlKClcblxuICBjb25zdCBhdWRpdEFjdGlvbklkID0gYXdhaXQgZmluZE9yQ3JlYXRlTG9va3VwSWQoe1xuICAgIGNvbHVtbk5hbWU6IFwiYWN0aW9uXCIsXG4gICAgY3VycmVudERhdGUsXG4gICAgZGIsXG4gICAgdGFibGVOYW1lOiBcImF1ZGl0X2FjdGlvbnNcIixcbiAgICB2YWx1ZTogYWN0aW9uXG4gIH0pXG5cbiAgY29uc3QgYXVkaXRJZCA9IG5ldyBVVUlEKDQpLmZvcm1hdCgpXG5cbiAgaWYgKHRhYmxlRGF0YS5kZWRpY2F0ZWQpIHtcbiAgICBjb25zdCBtb2RlbEtleSA9IG1vZGVsUGFyYW1LZXkobW9kZWxDbGFzcylcblxuICAgIGF3YWl0IGRiLnF1ZXJ5KGRiLmluc2VydFNxbCh7XG4gICAgICByZXR1cm5MYXN0SW5zZXJ0ZWRDb2x1bW5OYW1lczogW1wiaWRcIl0sXG4gICAgICB0YWJsZU5hbWU6IHRhYmxlRGF0YS50YWJsZU5hbWUsXG4gICAgICBkYXRhOiB7XG4gICAgICAgIGlkOiBhdWRpdElkLFxuICAgICAgICBbYCR7bW9kZWxLZXl9X2lkYF06IHJlY29yZC5pZCgpLFxuICAgICAgICBhdWRpdF9hY3Rpb25faWQ6IGF1ZGl0QWN0aW9uSWQsXG4gICAgICAgIGF1ZGl0ZWRfY2hhbmdlczogYXVkaXRlZENoYW5nZXMsXG4gICAgICAgIHBhcmFtcyxcbiAgICAgICAgY3JlYXRlZF9hdDogY3VycmVudERhdGUsXG4gICAgICAgIHVwZGF0ZWRfYXQ6IGN1cnJlbnREYXRlXG4gICAgICB9XG4gICAgfSkpXG4gIH0gZWxzZSB7XG4gICAgY29uc3QgYXVkaXRBdWRpdGFibGVUeXBlSWQgPSBhd2FpdCBmaW5kT3JDcmVhdGVMb29rdXBJZCh7XG4gICAgICBjb2x1bW5OYW1lOiBcIm5hbWVcIixcbiAgICAgIGN1cnJlbnREYXRlLFxuICAgICAgZGIsXG4gICAgICB0YWJsZU5hbWU6IFwiYXVkaXRfYXVkaXRhYmxlX3R5cGVzXCIsXG4gICAgICB2YWx1ZTogbW9kZWxDbGFzcy5nZXRNb2RlbE5hbWUoKVxuICAgIH0pXG5cbiAgICBhd2FpdCBkYi5xdWVyeShkYi5pbnNlcnRTcWwoe1xuICAgICAgcmV0dXJuTGFzdEluc2VydGVkQ29sdW1uTmFtZXM6IFtcImlkXCJdLFxuICAgICAgdGFibGVOYW1lOiBcImF1ZGl0c1wiLFxuICAgICAgZGF0YToge1xuICAgICAgICBpZDogYXVkaXRJZCxcbiAgICAgICAgYXVkaXRfYWN0aW9uX2lkOiBhdWRpdEFjdGlvbklkLFxuICAgICAgICBhdWRpdF9hdWRpdGFibGVfdHlwZV9pZDogYXVkaXRBdWRpdGFibGVUeXBlSWQsXG4gICAgICAgIGF1ZGl0YWJsZV9pZDogcmVjb3JkLmlkKCksXG4gICAgICAgIGF1ZGl0YWJsZV90eXBlOiBtb2RlbENsYXNzLmdldE1vZGVsTmFtZSgpLFxuICAgICAgICBhdWRpdGVkX2NoYW5nZXM6IGF1ZGl0ZWRDaGFuZ2VzLFxuICAgICAgICBwYXJhbXMsXG4gICAgICAgIGNyZWF0ZWRfYXQ6IGN1cnJlbnREYXRlLFxuICAgICAgICB1cGRhdGVkX2F0OiBjdXJyZW50RGF0ZVxuICAgICAgfVxuICAgIH0pKVxuICB9XG5cbiAgYXdhaXQgZW1pdEF1ZGl0RXZlbnQobW9kZWxDbGFzcywgYWN0aW9uLCB7XG4gICAgYWN0aW9uLFxuICAgIGF1ZGl0SWQsXG4gICAgYXVkaXRlZENoYW5nZXMsXG4gICAgcGFyYW1zLFxuICAgIHJlY29yZFxuICB9KVxuXG4gIEF1ZGl0RXZlbnRzLmNhbGwobW9kZWxDbGFzcy5nZXRNb2RlbE5hbWUoKSwgYWN0aW9uLCB7XG4gICAgYWN0aW9uLFxuICAgIGF1ZGl0SWQsXG4gICAgYXVkaXRlZENoYW5nZXMsXG4gICAgcGFyYW1zLFxuICAgIHJlY29yZFxuICB9KVxuXG4gIHJldHVybiBhdWRpdElkXG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gTGlmZWN5Y2xlIGNhbGxiYWNrc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogQ2FwdHVyZXMgY3JlYXRlIGNoYW5nZXMgYmVmb3JlIHBlcnNpc3RlbmNlIGNsZWFycyB0aGUgY2hhbmdlIHNldC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0ICYge19wZW5kaW5nQ3JlYXRlQXVkaXRDaGFuZ2VzPzogQXVkaXRDaGFuZ2VzfX0gcmVjb3JkIC0gUmVjb3JkIHdob3NlIHBlbmRpbmcgY2hhbmdlcyBzaG91bGQgYmUgY2FwdHVyZWQuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gY2FwdHVyZUNyZWF0ZUF1ZGl0Q2hhbmdlcyhyZWNvcmQpIHtcbiAgcmVjb3JkLl9wZW5kaW5nQ3JlYXRlQXVkaXRDaGFuZ2VzID0gYXVkaXRDaGFuZ2VzRm9yQ3VycmVudENoYW5nZXMocmVjb3JkKVxufVxuXG4vKipcbiAqIFdyaXRlcyB0aGUgY3JlYXRlIGF1ZGl0IHJvdyBmb3IgYSBtb2RlbCBpbnN0YW5jZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0ICYge19wZW5kaW5nQ3JlYXRlQXVkaXRDaGFuZ2VzPzogQXVkaXRDaGFuZ2VzfX0gcmVjb3JkIC0gUmVjb3JkIHRvIGF1ZGl0LlxuICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUNyZWF0ZUF1ZGl0KHJlY29yZCkge1xuICBhd2FpdCBjcmVhdGVBdWRpdChyZWNvcmQsIHtcbiAgICBhY3Rpb246IFwiY3JlYXRlXCIsXG4gICAgYXVkaXRlZENoYW5nZXM6IHJlY29yZC5fcGVuZGluZ0NyZWF0ZUF1ZGl0Q2hhbmdlcyB8fCBudWxsXG4gIH0pXG5cbiAgcmVjb3JkLl9wZW5kaW5nQ3JlYXRlQXVkaXRDaGFuZ2VzID0gdW5kZWZpbmVkXG59XG5cbi8qKlxuICogQ2FwdHVyZXMgdXBkYXRlIGNoYW5nZXMgYmVmb3JlIHBlcnNpc3RlbmNlIGNsZWFycyB0aGUgY2hhbmdlIHNldC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0ICYge19wZW5kaW5nVXBkYXRlQXVkaXRDaGFuZ2VzPzogQXVkaXRDaGFuZ2VzfX0gcmVjb3JkIC0gUmVjb3JkIHdob3NlIHBlbmRpbmcgY2hhbmdlcyBzaG91bGQgYmUgY2FwdHVyZWQuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gY2FwdHVyZVVwZGF0ZUF1ZGl0Q2hhbmdlcyhyZWNvcmQpIHtcbiAgcmVjb3JkLl9wZW5kaW5nVXBkYXRlQXVkaXRDaGFuZ2VzID0gYXVkaXRDaGFuZ2VzRm9yQ3VycmVudENoYW5nZXMocmVjb3JkKVxufVxuXG4vKipcbiAqIFdyaXRlcyB0aGUgdXBkYXRlIGF1ZGl0IHJvdyBmb3IgYSBtb2RlbCBpbnN0YW5jZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0ICYge19wZW5kaW5nVXBkYXRlQXVkaXRDaGFuZ2VzPzogQXVkaXRDaGFuZ2VzfX0gcmVjb3JkIC0gUmVjb3JkIHRvIGF1ZGl0LlxuICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVVwZGF0ZUF1ZGl0KHJlY29yZCkge1xuICBjb25zdCBhdWRpdGVkQ2hhbmdlcyA9IHJlY29yZC5fcGVuZGluZ1VwZGF0ZUF1ZGl0Q2hhbmdlcyB8fCBudWxsXG5cbiAgcmVjb3JkLl9wZW5kaW5nVXBkYXRlQXVkaXRDaGFuZ2VzID0gdW5kZWZpbmVkXG5cbiAgaWYgKCFhdWRpdGVkQ2hhbmdlcyB8fCBPYmplY3Qua2V5cyhhdWRpdGVkQ2hhbmdlcykubGVuZ3RoIDw9IDApIHJldHVyblxuXG4gIGF3YWl0IGNyZWF0ZUF1ZGl0KHJlY29yZCwge1xuICAgIGFjdGlvbjogXCJ1cGRhdGVcIixcbiAgICBhdWRpdGVkQ2hhbmdlc1xuICB9KVxufVxuXG4vKipcbiAqIFdyaXRlcyB0aGUgZGVzdHJveSBhdWRpdCByb3cgZm9yIGEgbW9kZWwgaW5zdGFuY2UuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vaW5kZXguanNcIikuZGVmYXVsdH0gcmVjb3JkIC0gUmVjb3JkIHRvIGF1ZGl0LlxuICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGNyZWF0ZURlc3Ryb3lBdWRpdChyZWNvcmQpIHtcbiAgYXdhaXQgY3JlYXRlQXVkaXQocmVjb3JkLCB7XG4gICAgYWN0aW9uOiBcImRlc3Ryb3lcIixcbiAgICBhdWRpdGVkQ2hhbmdlczogYXVkaXRDaGFuZ2VzRm9yRGVzdHJveShyZWNvcmQpXG4gIH0pXG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gQ2hhbmdlcyBoZWxwZXJzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBDYXB0dXJlcyB0aGUgbmV3IHZhbHVlcyBmb3IgZmllbGRzIGNoYW5nZWQgb24gYSByZWNvcmQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vaW5kZXguanNcIikuZGVmYXVsdH0gcmVjb3JkIC0gUmVjb3JkIHdob3NlIHBlbmRpbmcgY2hhbmdlcyBzaG91bGQgYmUgY2FwdHVyZWQuXG4gKiBAcmV0dXJucyB7QXVkaXRDaGFuZ2VzfSBOZXcgdmFsdWVzIGtleWVkIGJ5IGF0dHJpYnV0ZSBuYW1lLlxuICovXG5mdW5jdGlvbiBhdWRpdENoYW5nZXNGb3JDdXJyZW50Q2hhbmdlcyhyZWNvcmQpIHtcbiAgY29uc3QgY2hhbmdlcyA9IHJlY29yZC5jaGFuZ2VzKClcbiAgLyoqIEB0eXBlIHtBdWRpdENoYW5nZXN9ICovXG4gIGNvbnN0IGF1ZGl0ZWRDaGFuZ2VzID0ge31cbiAgY29uc3QgY29sdW1uTmFtZVRvQXR0cmlidXRlTmFtZSA9IHJlY29yZC5nZXRNb2RlbENsYXNzKCkuZ2V0Q29sdW1uTmFtZVRvQXR0cmlidXRlTmFtZU1hcCgpXG5cbiAgZm9yIChjb25zdCBbYXR0cmlidXRlTmFtZSwgY2hhbmdlXSBvZiBPYmplY3QuZW50cmllcyhjaGFuZ2VzKSkge1xuICAgIGF1ZGl0ZWRDaGFuZ2VzW2NvbHVtbk5hbWVUb0F0dHJpYnV0ZU5hbWVbYXR0cmlidXRlTmFtZV0gfHwgYXR0cmlidXRlTmFtZV0gPSBjaGFuZ2VbMV1cbiAgfVxuXG4gIHJldHVybiBhdWRpdGVkQ2hhbmdlc1xufVxuXG4vKipcbiAqIENhcHR1cmVzIHRoZSBjdXJyZW50IGF0dHJpYnV0ZXMgZm9yIGEgZGVzdHJveSBhdWRpdC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0fSByZWNvcmQgLSBSZWNvcmQgYmVpbmcgZGVzdHJveWVkLlxuICogQHJldHVybnMge0F1ZGl0Q2hhbmdlc30gQ3VycmVudCBhdHRyaWJ1dGVzIGtleWVkIGJ5IGF0dHJpYnV0ZSBuYW1lLlxuICovXG5mdW5jdGlvbiBhdWRpdENoYW5nZXNGb3JEZXN0cm95KHJlY29yZCkge1xuICByZXR1cm4gey4uLnJlY29yZC5hdHRyaWJ1dGVzKCl9XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gd2l0aG91dEF1ZGl0XG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBSZXR1cm5zIHJlY29yZHMgd2l0aG91dCBhbiBhdWRpdCByb3cgZm9yIHRoZSBnaXZlbiBhY3Rpb24uXG4gKiBVc2VzIHNoYXJlZC10YWJsZSBkZWZhdWx0cyB3aGVuIHRhYmxlIGRhdGEgaXMgbm90IHlldCByZXNvbHZlZDtcbiAqIHN3aXRjaGVzIHRvIHRoZSBkZWRpY2F0ZWQgdGFibGUgcGF0aCBvbmNlIHJlc29sdmVkLlxuICogQHRlbXBsYXRlIHtBdWRpdGVkTW9kZWxDbGFzc30gTUNcbiAqIEBwYXJhbSB7TUN9IG1vZGVsQ2xhc3MgLSBNb2RlbCBjbGFzcyB0byBzY29wZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBhY3Rpb24gLSBBdWRpdCBhY3Rpb24gdG8gZXhjbHVkZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9xdWVyeS9tb2RlbC1jbGFzcy1xdWVyeS5qc1wiKS5kZWZhdWx0PE1DPn0gUXVlcnkgc2NvcGVkIHRvIHJlY29yZHMgd2l0aG91dCB0aGF0IGF1ZGl0IGFjdGlvbi5cbiAqL1xuZnVuY3Rpb24gd2l0aG91dEF1ZGl0KG1vZGVsQ2xhc3MsIGFjdGlvbikge1xuICBjb25zdCBkYiA9IG1vZGVsQ2xhc3MuY29ubmVjdGlvbigpXG4gIGNvbnN0IG1vZGVsVGFibGVTcWwgPSBkYi5xdW90ZVRhYmxlKG1vZGVsQ2xhc3MudGFibGVOYW1lKCkpXG4gIGNvbnN0IGF1ZGl0QWN0aW9uc1RhYmxlU3FsID0gZGIucXVvdGVUYWJsZShcImF1ZGl0X2FjdGlvbnNcIilcbiAgY29uc3QgbW9kZWxQcmltYXJ5S2V5U3FsID0gYCR7bW9kZWxUYWJsZVNxbH0uJHtkYi5xdW90ZUNvbHVtbihtb2RlbENsYXNzLnByaW1hcnlLZXkoKSl9YFxuICBjb25zdCBhdWRpdEFjdGlvbnNJZFNxbCA9IGAke2F1ZGl0QWN0aW9uc1RhYmxlU3FsfS4ke2RiLnF1b3RlQ29sdW1uKFwiaWRcIil9YFxuICBjb25zdCBhdWRpdEFjdGlvbnNBY3Rpb25TcWwgPSBgJHthdWRpdEFjdGlvbnNUYWJsZVNxbH0uJHtkYi5xdW90ZUNvbHVtbihcImFjdGlvblwiKX1gXG5cbiAgaWYgKG1vZGVsQ2xhc3MuX2F1ZGl0VGFibGVSZXNvbHZlZCAmJiBtb2RlbENsYXNzLl9hdWRpdFRhYmxlRGF0YT8uZGVkaWNhdGVkKSB7XG4gICAgY29uc3QgdGFibGVEYXRhID0gbW9kZWxDbGFzcy5fYXVkaXRUYWJsZURhdGFcbiAgICBjb25zdCBtb2RlbEtleSA9IG1vZGVsUGFyYW1LZXkobW9kZWxDbGFzcylcbiAgICBjb25zdCBhdWRpdHNUYWJsZVNxbCA9IGRiLnF1b3RlVGFibGUodGFibGVEYXRhLnRhYmxlTmFtZSlcbiAgICBjb25zdCBhdWRpdEFjdGlvbklkU3FsID0gYCR7YXVkaXRzVGFibGVTcWx9LiR7ZGIucXVvdGVDb2x1bW4oXCJhdWRpdF9hY3Rpb25faWRcIil9YFxuICAgIGNvbnN0IG1vZGVsSWRTcWwgPSBgJHthdWRpdHNUYWJsZVNxbH0uJHtkYi5xdW90ZUNvbHVtbihgJHttb2RlbEtleX1faWRgKX1gXG5cbiAgICByZXR1cm4gbW9kZWxDbGFzc1xuICAgICAgLmFsbCgpXG4gICAgICAud2hlcmUoYFxuICAgICAgICBOT1QgRVhJU1RTIChcbiAgICAgICAgICBTRUxFQ1QgMVxuICAgICAgICAgIEZST00gJHthdWRpdHNUYWJsZVNxbH1cbiAgICAgICAgICBJTk5FUiBKT0lOICR7YXVkaXRBY3Rpb25zVGFibGVTcWx9XG4gICAgICAgICAgICBPTiAke2F1ZGl0QWN0aW9uc0lkU3FsfSA9ICR7YXVkaXRBY3Rpb25JZFNxbH1cbiAgICAgICAgICBXSEVSRSAke21vZGVsSWRTcWx9ID0gJHttb2RlbFByaW1hcnlLZXlTcWx9XG4gICAgICAgICAgICBBTkQgJHthdWRpdEFjdGlvbnNBY3Rpb25TcWx9ID0gJHtkYi5xdW90ZShub3JtYWxpemVBY3Rpb24oYWN0aW9uKSl9XG4gICAgICAgIClcbiAgICAgIGApXG4gIH1cblxuICBjb25zdCBhdWRpdHNUYWJsZVNxbCA9IGRiLnF1b3RlVGFibGUoXCJhdWRpdHNcIilcbiAgY29uc3QgYXVkaXRBdWRpdGFibGVJZFNxbCA9IGAke2F1ZGl0c1RhYmxlU3FsfS4ke2RiLnF1b3RlQ29sdW1uKFwiYXVkaXRhYmxlX2lkXCIpfWBcbiAgY29uc3QgYXVkaXRBdWRpdGFibGVUeXBlU3FsID0gYCR7YXVkaXRzVGFibGVTcWx9LiR7ZGIucXVvdGVDb2x1bW4oXCJhdWRpdGFibGVfdHlwZVwiKX1gXG4gIGNvbnN0IGF1ZGl0QWN0aW9uSWRTcWwgPSBgJHthdWRpdHNUYWJsZVNxbH0uJHtkYi5xdW90ZUNvbHVtbihcImF1ZGl0X2FjdGlvbl9pZFwiKX1gXG5cbiAgcmV0dXJuIG1vZGVsQ2xhc3NcbiAgICAuYWxsKClcbiAgICAud2hlcmUoYFxuICAgICAgTk9UIEVYSVNUUyAoXG4gICAgICAgIFNFTEVDVCAxXG4gICAgICAgIEZST00gJHthdWRpdHNUYWJsZVNxbH1cbiAgICAgICAgSU5ORVIgSk9JTiAke2F1ZGl0QWN0aW9uc1RhYmxlU3FsfVxuICAgICAgICAgIE9OICR7YXVkaXRBY3Rpb25zSWRTcWx9ID0gJHthdWRpdEFjdGlvbklkU3FsfVxuICAgICAgICBXSEVSRSAke2F1ZGl0QXVkaXRhYmxlVHlwZVNxbH0gPSAke2RiLnF1b3RlKG1vZGVsQ2xhc3MuZ2V0TW9kZWxOYW1lKCkpfVxuICAgICAgICAgIEFORCAke2F1ZGl0QXVkaXRhYmxlSWRTcWx9ID0gJHttb2RlbFByaW1hcnlLZXlTcWx9XG4gICAgICAgICAgQU5EICR7YXVkaXRBY3Rpb25zQWN0aW9uU3FsfSA9ICR7ZGIucXVvdGUobm9ybWFsaXplQWN0aW9uKGFjdGlvbikpfVxuICAgICAgKVxuICAgIGApXG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gRXZlbnQgY2FsbGJhY2tzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBwZXItbW9kZWwgY2FsbGJhY2sgZmlyZWQgYWZ0ZXIgYW4gYXVkaXQgcm93IGlzIGNyZWF0ZWQuXG4gKiBAcGFyYW0ge0F1ZGl0ZWRNb2RlbENsYXNzfSBtb2RlbENsYXNzIC0gTW9kZWwgY2xhc3MgdG8gb2JzZXJ2ZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBhY3Rpb24gLSBBdWRpdCBhY3Rpb24gbmFtZSAoZS5nLiBcImNyZWF0ZVwiKS5cbiAqIEBwYXJhbSB7QXVkaXRDYWxsYmFja30gY2FsbGJhY2sgLSBDYWxsYmFjayBpbnZva2VkIGFmdGVyIG1hdGNoaW5nIGF1ZGl0IHJvd3MgYXJlIGNyZWF0ZWQuXG4gKiBAcmV0dXJucyB7KCkgPT4gdm9pZH0gVW5zdWJzY3JpYmUgZnVuY3Rpb24uXG4gKi9cbmZ1bmN0aW9uIHJlZ2lzdGVyQXVkaXRDYWxsYmFjayhtb2RlbENsYXNzLCBhY3Rpb24sIGNhbGxiYWNrKSB7XG4gIGNvbnN0IG5vcm1hbGl6ZWRBY3Rpb24gPSBub3JtYWxpemVBY3Rpb24oYWN0aW9uKVxuICBjb25zdCBjYWxsYmFja3MgPSBhdWRpdENhbGxiYWNrc0Zvck1vZGVsQ2xhc3MobW9kZWxDbGFzcylcblxuICBpZiAoIWNhbGxiYWNrc1tub3JtYWxpemVkQWN0aW9uXSkge1xuICAgIGNhbGxiYWNrc1tub3JtYWxpemVkQWN0aW9uXSA9IFtdXG4gIH1cblxuICBjYWxsYmFja3Nbbm9ybWFsaXplZEFjdGlvbl0ucHVzaChjYWxsYmFjaylcblxuICByZXR1cm4gKCkgPT4ge1xuICAgIGNvbnN0IGFjdGlvbkNhbGxiYWNrcyA9IGNhbGxiYWNrc1tub3JtYWxpemVkQWN0aW9uXVxuICAgIGNvbnN0IGluZGV4ID0gYWN0aW9uQ2FsbGJhY2tzLmluZGV4T2YoY2FsbGJhY2spXG5cbiAgICBpZiAoaW5kZXggPj0gMCkge1xuICAgICAgYWN0aW9uQ2FsbGJhY2tzLnNwbGljZShpbmRleCwgMSlcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBFbWl0cyBwZXItbW9kZWwgYXVkaXQgY2FsbGJhY2tzIGZvciBhIG1vZGVsL2FjdGlvbiBwYWlyLlxuICogQHBhcmFtIHtBdWRpdGVkTW9kZWxDbGFzc30gbW9kZWxDbGFzcyAtIE1vZGVsIGNsYXNzLlxuICogQHBhcmFtIHtzdHJpbmd9IGFjdGlvbiAtIEF1ZGl0IGFjdGlvbi5cbiAqIEBwYXJhbSB7QXVkaXRFdmVudFBheWxvYWR9IHBheWxvYWQgLSBFdmVudCBwYXlsb2FkLlxuICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGVtaXRBdWRpdEV2ZW50KG1vZGVsQ2xhc3MsIGFjdGlvbiwgcGF5bG9hZCkge1xuICBjb25zdCBjYWxsYmFja3MgPSBhdWRpdENhbGxiYWNrc0Zvck1vZGVsQ2xhc3MobW9kZWxDbGFzcylbYWN0aW9uXSB8fCBbXVxuXG4gIGZvciAoY29uc3QgY2FsbGJhY2sgb2YgWy4uLmNhbGxiYWNrc10pIHtcbiAgICBhd2FpdCBjYWxsYmFjayhwYXlsb2FkKVxuICB9XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgcGVyLW1vZGVsIGNhbGxiYWNrIG1hcC5cbiAqIEBwYXJhbSB7QXVkaXRlZE1vZGVsQ2xhc3N9IG1vZGVsQ2xhc3MgLSBNb2RlbCBjbGFzcy5cbiAqIEByZXR1cm5zIHtSZWNvcmQ8c3RyaW5nLCBBdWRpdENhbGxiYWNrW10+fSBDYWxsYmFjayBtYXAga2V5ZWQgYnkgYWN0aW9uLlxuICovXG5mdW5jdGlvbiBhdWRpdENhbGxiYWNrc0Zvck1vZGVsQ2xhc3MobW9kZWxDbGFzcykge1xuICBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChtb2RlbENsYXNzLCBcIl9hdWRpdENhbGxiYWNrc1wiKSkge1xuICAgIG1vZGVsQ2xhc3MuX2F1ZGl0Q2FsbGJhY2tzID0ge31cbiAgfVxuXG4gIGNvbnN0IGNhbGxiYWNrcyA9IG1vZGVsQ2xhc3MuX2F1ZGl0Q2FsbGJhY2tzXG5cbiAgaWYgKCFjYWxsYmFja3MpIHRocm93IG5ldyBFcnJvcihgQXVkaXQgY2FsbGJhY2tzIHdlcmVuJ3QgaW5pdGlhbGl6ZWQgZm9yICR7bW9kZWxDbGFzcy5nZXRNb2RlbE5hbWUoKX1gKVxuXG4gIHJldHVybiBjYWxsYmFja3Ncbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBMb29rdXAgaGVscGVyc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogRmluZHMgb3IgY3JlYXRlcyBhIGxvb2t1cCByb3cgYW5kIHJldHVybnMgaXRzIGlkLlxuICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zIG9iamVjdC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLmNvbHVtbk5hbWUgLSBMb29rdXAgdmFsdWUgY29sdW1uIG5hbWUuXG4gKiBAcGFyYW0ge0RhdGV9IGFyZ3MuY3VycmVudERhdGUgLSBUaW1lc3RhbXAgdG8gd3JpdGUgd2hlbiBpbnNlcnRpbmcuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL2RyaXZlcnMvYmFzZS5qc1wiKS5kZWZhdWx0fSBhcmdzLmRiIC0gRGF0YWJhc2UgZHJpdmVyLlxuICogQHBhcmFtIHtzdHJpbmd9IGFyZ3MudGFibGVOYW1lIC0gTG9va3VwIHRhYmxlIG5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gYXJncy52YWx1ZSAtIExvb2t1cCB2YWx1ZS5cbiAqIEByZXR1cm5zIHtQcm9taXNlPG51bWJlciB8IHN0cmluZz59IExvb2t1cCByb3cgaWQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGZpbmRPckNyZWF0ZUxvb2t1cElkKHtjb2x1bW5OYW1lLCBjdXJyZW50RGF0ZSwgZGIsIHRhYmxlTmFtZSwgdmFsdWV9KSB7XG4gIGF3YWl0IGRiLnVwc2VydCh7XG4gICAgdGFibGVOYW1lLFxuICAgIGNvbmZsaWN0Q29sdW1uczogW2NvbHVtbk5hbWVdLFxuICAgIHVwZGF0ZUNvbHVtbnM6IFtjb2x1bW5OYW1lXSxcbiAgICBkYXRhOiB7XG4gICAgICBpZDogbmV3IFVVSUQoNCkuZm9ybWF0KCksXG4gICAgICBbY29sdW1uTmFtZV06IHZhbHVlLFxuICAgICAgY3JlYXRlZF9hdDogY3VycmVudERhdGUsXG4gICAgICB1cGRhdGVkX2F0OiBjdXJyZW50RGF0ZVxuICAgIH1cbiAgfSlcblxuICBjb25zdCBpZCA9IGF3YWl0IGZpbmRMb29rdXBJZCh7Y29sdW1uTmFtZSwgZGIsIHRhYmxlTmFtZSwgdmFsdWV9KVxuXG4gIGlmIChpZCA9PT0gbnVsbCkgdGhyb3cgbmV3IEVycm9yKGBDb3VsZG4ndCBmaW5kICR7dGFibGVOYW1lfS4ke2NvbHVtbk5hbWV9IGFmdGVyIHVwc2VydGApXG5cbiAgcmV0dXJuIGlkXG59XG5cbi8qKlxuICogRmluZHMgYSBsb29rdXAgaWQgYnkgdmFsdWUuXG4gKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIE9wdGlvbnMgb2JqZWN0LlxuICogQHBhcmFtIHtzdHJpbmd9IGFyZ3MuY29sdW1uTmFtZSAtIExvb2t1cCB2YWx1ZSBjb2x1bW4gbmFtZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZHJpdmVycy9iYXNlLmpzXCIpLmRlZmF1bHR9IGFyZ3MuZGIgLSBEYXRhYmFzZSBkcml2ZXIuXG4gKiBAcGFyYW0ge3N0cmluZ30gYXJncy50YWJsZU5hbWUgLSBMb29rdXAgdGFibGUgbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLnZhbHVlIC0gTG9va3VwIHZhbHVlLlxuICogQHJldHVybnMge1Byb21pc2U8bnVtYmVyIHwgc3RyaW5nIHwgbnVsbD59IExvb2t1cCByb3cgaWQgb3IgbnVsbC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZmluZExvb2t1cElkKHtjb2x1bW5OYW1lLCBkYiwgdGFibGVOYW1lLCB2YWx1ZX0pIHtcbiAgY29uc3Qgcm93cyA9IC8qKiBAdHlwZSB7QXJyYXk8e2lkOiBudW1iZXIgfCBzdHJpbmd9Pn0gKi8gKGF3YWl0IGRiLnF1ZXJ5KGBcbiAgICBTRUxFQ1QgJHtkYi5xdW90ZUNvbHVtbihcImlkXCIpfSBBUyBpZFxuICAgIEZST00gJHtkYi5xdW90ZVRhYmxlKHRhYmxlTmFtZSl9XG4gICAgV0hFUkUgJHtkYi5xdW90ZUNvbHVtbihjb2x1bW5OYW1lKX0gPSAke2RiLnF1b3RlKHZhbHVlKX1cbiAgYCkpXG5cbiAgaWYgKHJvd3NbMF0pIHJldHVybiByb3dzWzBdLmlkXG5cbiAgcmV0dXJuIG51bGxcbn1cblxuLyoqXG4gKiBOb3JtYWxpemVzIGFuIGF1ZGl0IGFjdGlvbiBzdHJpbmcuXG4gKiBAcGFyYW0ge3N0cmluZ30gYWN0aW9uIC0gQWN0aW9uIG5hbWUuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBUcmltbWVkLCBub24tZW1wdHkgYWN0aW9uIG5hbWUuXG4gKi9cbmZ1bmN0aW9uIG5vcm1hbGl6ZUFjdGlvbihhY3Rpb24pIHtcbiAgY29uc3Qgbm9ybWFsaXplZEFjdGlvbiA9IGFjdGlvbi50cmltKClcblxuICBpZiAoIW5vcm1hbGl6ZWRBY3Rpb24pIHRocm93IG5ldyBFcnJvcihcIkF1ZGl0IGFjdGlvbiBtdXN0IGJlIHByZXNlbnRcIilcblxuICByZXR1cm4gbm9ybWFsaXplZEFjdGlvblxufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIE1pZ3JhdGlvbiBoZWxwZXJzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBDcmVhdGVzIHRoZSBzaGFyZWQgYXVkaXQgdGFibGVzIG1pZ3JhdGlvbiB1cC9kb3duIGNhbGxiYWNrcyBmb3IgdXNlIGluc2lkZVxuICogYSBNaWdyYXRpb24gY2xhc3MuIFRoZSBgdGFibGVgIHBhcmFtZXRlciBpcyBhIE1pZ3JhdGlvbiBpbnN0YW5jZS5cbiAqIEBwYXJhbSB7e2lkPzoge3R5cGU6IHN0cmluZ319fSBbb3B0aW9uc10gLSBJRCBjb2x1bW4gb3B0aW9ucy5cbiAqIEByZXR1cm5zIHt7ZG93bjogKHRhYmxlOiBpbXBvcnQoXCIuLi9taWdyYXRpb24vaW5kZXguanNcIikuZGVmYXVsdCkgPT4gUHJvbWlzZTx2b2lkPiwgdXA6ICh0YWJsZTogaW1wb3J0KFwiLi4vbWlncmF0aW9uL2luZGV4LmpzXCIpLmRlZmF1bHQpID0+IFByb21pc2U8dm9pZD59fVxuICovXG5mdW5jdGlvbiBjcmVhdGVTaGFyZWRBdWRpdFRhYmxlc01pZ3JhdGlvbihvcHRpb25zID0ge30pIHtcbiAgY29uc3Qgb3B0cyA9IC8qKiBAdHlwZSB7e2lkPzoge3R5cGU6IHN0cmluZ319fSAqLyAob3B0aW9ucylcbiAgY29uc3QgaWRPcHRpb25zID0gLyoqIEB0eXBlIHt7dHlwZT86IHN0cmluZ319ICovIChvcHRzLmlkIHx8IHt9KVxuICBjb25zdCB0eXBlID0gaWRPcHRpb25zLnR5cGVcblxuICByZXR1cm4ge1xuICAgIGFzeW5jIHVwKHRhYmxlKSB7XG4gICAgICBhd2FpdCB0YWJsZS5jcmVhdGVUYWJsZShcImF1ZGl0X2FjdGlvbnNcIiwge2lkOiAvKiogQHR5cGUge3t0eXBlPzogc3RyaW5nfX0gKi8gKG9wdHMuaWQgfHwge30pfSwgKC8qKiBAdHlwZSB7e3N0cmluZyhuYW1lOiBzdHJpbmcsIG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogdm9pZCwgdGltZXN0YW1wcygpOiB2b2lkfX0gKi8gdCkgPT4ge1xuICAgICAgICB0LnN0cmluZyhcImFjdGlvblwiLCB7aW5kZXg6IHt1bmlxdWU6IHRydWV9LCBudWxsOiBmYWxzZX0pXG4gICAgICAgIHQudGltZXN0YW1wcygpXG4gICAgICB9KVxuXG4gICAgICBhd2FpdCB0YWJsZS5jcmVhdGVUYWJsZShcImF1ZGl0X2F1ZGl0YWJsZV90eXBlc1wiLCB7aWQ6IC8qKiBAdHlwZSB7e3R5cGU/OiBzdHJpbmd9fSAqLyAob3B0cy5pZCB8fCB7fSl9LCAoLyoqIEB0eXBlIHt7c3RyaW5nKG5hbWU6IHN0cmluZywgb3B0aW9uczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiB2b2lkLCB0aW1lc3RhbXBzKCk6IHZvaWR9fSAqLyB0KSA9PiB7XG4gICAgICAgIHQuc3RyaW5nKFwibmFtZVwiLCB7aW5kZXg6IHt1bmlxdWU6IHRydWV9LCBudWxsOiBmYWxzZX0pXG4gICAgICAgIHQudGltZXN0YW1wcygpXG4gICAgICB9KVxuXG4gICAgICBhd2FpdCB0YWJsZS5jcmVhdGVUYWJsZShcImF1ZGl0c1wiLCB7aWQ6IC8qKiBAdHlwZSB7e3R5cGU/OiBzdHJpbmd9fSAqLyAob3B0cy5pZCB8fCB7fSl9LCAoLyoqIEB0eXBlIHt7anNvbihuYW1lOiBzdHJpbmcpOiB2b2lkLCByZWZlcmVuY2VzKG5hbWU6IHN0cmluZywgb3B0aW9uczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiB2b2lkLCB0aW1lc3RhbXBzKCk6IHZvaWR9fSAqLyB0KSA9PiB7XG4gICAgICAgIHQucmVmZXJlbmNlcyhcImF1ZGl0X2FjdGlvblwiLCB7Zm9yZWlnbktleTogdHJ1ZSwgbnVsbDogZmFsc2UsIHR5cGV9KVxuICAgICAgICB0LnJlZmVyZW5jZXMoXCJhdWRpdF9hdWRpdGFibGVfdHlwZVwiLCB7Zm9yZWlnbktleTogdHJ1ZSwgbnVsbDogZmFsc2UsIHR5cGV9KVxuICAgICAgICB0LnJlZmVyZW5jZXMoXCJhdWRpdGFibGVcIiwge251bGw6IGZhbHNlLCBwb2x5bW9ycGhpYzogdHJ1ZSwgdHlwZX0pXG4gICAgICAgIHQuanNvbihcImF1ZGl0ZWRfY2hhbmdlc1wiKVxuICAgICAgICB0Lmpzb24oXCJwYXJhbXNcIilcbiAgICAgICAgdC50aW1lc3RhbXBzKClcbiAgICAgIH0pXG4gICAgfSxcblxuICAgIGFzeW5jIGRvd24odGFibGUpIHtcbiAgICAgIGF3YWl0IHRhYmxlLmRyb3BUYWJsZShcImF1ZGl0c1wiKVxuICAgICAgYXdhaXQgdGFibGUuZHJvcFRhYmxlKFwiYXVkaXRfYXVkaXRhYmxlX3R5cGVzXCIpXG4gICAgICBhd2FpdCB0YWJsZS5kcm9wVGFibGUoXCJhdWRpdF9hY3Rpb25zXCIpXG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgZGVkaWNhdGVkIGF1ZGl0IHRhYmxlIG5hbWUgZm9yIGEgZ2l2ZW4gbW9kZWwgdGFibGUgbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtb2RlbFRhYmxlTmFtZSAtIE1vZGVsIHRhYmxlIG5hbWUgKGUuZy4gXCJwcm9qZWN0c1wiKS5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IERlZGljYXRlZCBhdWRpdCB0YWJsZSBuYW1lIChlLmcuIFwicHJvamVjdF9hdWRpdHNcIikuXG4gKi9cbmZ1bmN0aW9uIGRlZGljYXRlZEF1ZGl0VGFibGVOYW1lRm9yVGFibGUobW9kZWxUYWJsZU5hbWUpIHtcbiAgaWYgKG1vZGVsVGFibGVOYW1lLmVuZHNXaXRoKFwic1wiKSkge1xuICAgIHJldHVybiBgJHttb2RlbFRhYmxlTmFtZS5zbGljZSgwLCAtMSl9X2F1ZGl0c2BcbiAgfVxuXG4gIHJldHVybiBgJHttb2RlbFRhYmxlTmFtZX1fYXVkaXRzYFxufVxuXG5leHBvcnQge1xuICBBdWRpdEV2ZW50cyxcbiAgY2FwdHVyZUNyZWF0ZUF1ZGl0Q2hhbmdlcyxcbiAgY2FwdHVyZVVwZGF0ZUF1ZGl0Q2hhbmdlcyxcbiAgY3JlYXRlQXVkaXQsXG4gIGNyZWF0ZUNyZWF0ZUF1ZGl0LFxuICBjcmVhdGVEZXN0cm95QXVkaXQsXG4gIGNyZWF0ZVVwZGF0ZUF1ZGl0LFxuICBjcmVhdGVTaGFyZWRBdWRpdFRhYmxlc01pZ3JhdGlvbixcbiAgZGVkaWNhdGVkQXVkaXRUYWJsZU5hbWVGb3JUYWJsZSxcbiAgaW5pdGlhbGl6ZUF1ZGl0ZWRNb2RlbFJlbGF0aW9uc2hpcHMsXG4gIGluaXRpYWxpemVBdWRpdGluZyxcbiAgcmVnaXN0ZXJBdWRpdENhbGxiYWNrLFxuICByZWdpc3RlckF1ZGl0aW5nLFxuICB3aXRob3V0QXVkaXRcbn1cbiJdfQ==