velocious 1.0.506 → 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.
- package/build/configuration.js +2 -0
- package/build/database/migration/index.js +67 -0
- package/build/database/record/auditing.js +659 -120
- package/build/database/record/index.js +2 -1
- package/build/database/record/instance-relationships/has-many.js +6 -0
- package/build/src/configuration.d.ts.map +1 -1
- package/build/src/configuration.js +3 -1
- package/build/src/database/migration/index.d.ts +30 -0
- package/build/src/database/migration/index.d.ts.map +1 -1
- package/build/src/database/migration/index.js +58 -1
- package/build/src/database/record/auditing.d.ts +97 -40
- package/build/src/database/record/auditing.d.ts.map +1 -1
- package/build/src/database/record/auditing.js +561 -118
- package/build/src/database/record/index.d.ts.map +1 -1
- package/build/src/database/record/index.js +3 -2
- package/build/src/database/record/instance-relationships/has-many.d.ts.map +1 -1
- package/build/src/database/record/instance-relationships/has-many.js +5 -1
- package/build/src/testing/test-runner.d.ts.map +1 -1
- package/build/src/testing/test-runner.js +19 -6
- package/build/testing/test-runner.js +18 -5
- package/package.json +1 -1
- package/src/configuration.js +2 -0
- package/src/database/migration/index.js +67 -0
- package/src/database/record/auditing.js +659 -120
- package/src/database/record/index.js +2 -1
- package/src/database/record/instance-relationships/has-many.js +6 -0
- package/src/testing/test-runner.js +18 -5
|
@@ -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
|
-
*
|
|
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
|
-
*
|
|
52
|
-
* @param {
|
|
53
|
-
* @param {
|
|
54
|
-
* @
|
|
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
|
|
58
|
-
const
|
|
59
|
-
const
|
|
60
|
-
if (!
|
|
61
|
-
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
*
|
|
74
|
-
* @param {import("./index.js").default}
|
|
75
|
-
* @returns {
|
|
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
|
|
78
|
-
|
|
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
|
-
*
|
|
89
|
-
* @param {
|
|
90
|
-
* @returns {
|
|
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
|
|
93
|
-
|
|
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
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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
|
|
476
|
+
auditId,
|
|
156
477
|
auditedChanges,
|
|
157
478
|
params,
|
|
158
479
|
record
|
|
159
480
|
});
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
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
|
|
180
|
-
* @param {import("./index.js").default & {_pendingCreateAuditChanges?: AuditChanges}} record - Record
|
|
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
|
-
*
|
|
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
|
|
200
|
-
* @param {import("./index.js").default & {_pendingUpdateAuditChanges?: AuditChanges}} record - Record
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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}
|
|
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
|
-
*
|
|
323
|
-
*
|
|
324
|
-
* @
|
|
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
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
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
|
-
*
|
|
337
|
-
* @param {
|
|
338
|
-
* @
|
|
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
|
-
|
|
343
|
-
|
|
344
|
-
|
|
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXVkaXRpbmcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvZGF0YWJhc2UvcmVjb3JkL2F1ZGl0aW5nLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLElBQUksTUFBTSxXQUFXLENBQUE7QUFFNUI7OztHQUdHO0FBRUg7Ozs7Ozs7O0dBUUc7QUFFSDs7O0dBR0c7QUFFSDs7Ozs7O0dBTUc7QUFFSDs7Ozs7O0dBTUc7QUFFSDs7OztHQUlHO0FBQ0gsU0FBUyxnQkFBZ0IsQ0FBQyxVQUFVO0lBQ2xDLElBQUksTUFBTSxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxvQ0FBb0MsQ0FBQyxJQUFJLFVBQVUsQ0FBQyxrQ0FBa0MsRUFBRSxDQUFDO1FBQzVJLE9BQU07SUFDUixDQUFDO0lBRUQsVUFBVSxDQUFDLGtDQUFrQyxHQUFHLElBQUksQ0FBQTtJQUNwRCxVQUFVLENBQUMsWUFBWSxDQUFDLDJCQUEyQixDQUFDLENBQUE7SUFDcEQsVUFBVSxDQUFDLFdBQVcsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFBO0lBQzNDLFVBQVUsQ0FBQyxZQUFZLENBQUMsMkJBQTJCLENBQUMsQ0FBQTtJQUNwRCxVQUFVLENBQUMsV0FBVyxDQUFDLG1CQUFtQixDQUFDLENBQUE7SUFDM0MsVUFBVSxDQUFDLFlBQVksQ0FBQyxvQkFBb0IsQ0FBQyxDQUFBO0FBQy9DLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxTQUFTLHFCQUFxQixDQUFDLFVBQVUsRUFBRSxNQUFNLEVBQUUsUUFBUTtJQUN6RCxNQUFNLGdCQUFnQixHQUFHLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQTtJQUNoRCxNQUFNLFNBQVMsR0FBRywyQkFBMkIsQ0FBQyxVQUFVLENBQUMsQ0FBQTtJQUV6RCxJQUFJLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUFDLEVBQUUsQ0FBQztRQUNqQyxTQUFTLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxFQUFFLENBQUE7SUFDbEMsQ0FBQztJQUVELFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQTtJQUUxQyxPQUFPLEdBQUcsRUFBRTtRQUNWLE1BQU0sZUFBZSxHQUFHLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFBO1FBQ25ELE1BQU0sS0FBSyxHQUFHLGVBQWUsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUE7UUFFL0MsSUFBSSxLQUFLLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDZixlQUFlLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQTtRQUNsQyxDQUFDO0lBQ0gsQ0FBQyxDQUFBO0FBQ0gsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLDZCQUE2QixDQUFDLE1BQU07SUFDM0MsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFBO0lBQ2hDLDJCQUEyQjtJQUMzQixNQUFNLGNBQWMsR0FBRyxFQUFFLENBQUE7SUFDekIsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsYUFBYSxFQUFFLENBQUMsK0JBQStCLEVBQUUsQ0FBQTtJQUUxRixLQUFLLE1BQU0sQ0FBQyxhQUFhLEVBQUUsTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQzlELGNBQWMsQ0FBQyx5QkFBeUIsQ0FBQyxhQUFhLENBQUMsSUFBSSxhQUFhLENBQUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUE7SUFDdkYsQ0FBQztJQUVELE9BQU8sY0FBYyxDQUFBO0FBQ3ZCLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUyxzQkFBc0IsQ0FBQyxNQUFNO0lBQ3BDLE9BQU8sRUFBQyxHQUFHLE1BQU0sQ0FBQyxVQUFVLEVBQUUsRUFBQyxDQUFBO0FBQ2pDLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILEtBQUssVUFBVSxXQUFXLENBQUMsTUFBTSxFQUFFLElBQUk7SUFDckMsTUFBTSxVQUFVLEdBQUcsZ0NBQWdDLENBQUMsQ0FBQyxNQUFNLENBQUMsYUFBYSxFQUFFLENBQUMsQ0FBQTtJQUU1RSxPQUFPLE1BQU0sVUFBVSxDQUFDLGlCQUFpQixFQUFFLENBQUMsaUJBQWlCLENBQUMsRUFBQyxJQUFJLEVBQUUsR0FBRyxVQUFVLENBQUMsWUFBWSxFQUFFLFFBQVEsRUFBQyxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3JILE9BQU8sTUFBTSxnQ0FBZ0MsQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFBO0lBQ3pFLENBQUMsQ0FBQyxDQUFBO0FBQ0osQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILEtBQUssVUFBVSxnQ0FBZ0MsQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLFVBQVU7SUFDdEUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUU7UUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixVQUFVLENBQUMsWUFBWSxFQUFFLFNBQVMsQ0FBQyxDQUFBO0lBRTFHLE1BQU0sTUFBTSxHQUFHLGVBQWUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUE7SUFDM0MsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLGNBQWMsS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQTtJQUNyRixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFBO0lBQzdELE1BQU0sRUFBRSxHQUFHLFVBQVUsQ0FBQyxVQUFVLEVBQUUsQ0FBQTtJQUNsQyxNQUFNLFdBQVcsR0FBRyxJQUFJLElBQUksRUFBRSxDQUFBO0lBQzlCLE1BQU0sYUFBYSxHQUFHLE1BQU0sb0JBQW9CLENBQUM7UUFDL0MsVUFBVSxFQUFFLFFBQVE7UUFDcEIsRUFBRTtRQUNGLFNBQVMsRUFBRSxlQUFlO1FBQzFCLEtBQUssRUFBRSxNQUFNO1FBQ2IsV0FBVztLQUNaLENBQUMsQ0FBQTtJQUNGLE1BQU0sb0JBQW9CLEdBQUcsTUFBTSxvQkFBb0IsQ0FBQztRQUN0RCxVQUFVLEVBQUUsTUFBTTtRQUNsQixFQUFFO1FBQ0YsU0FBUyxFQUFFLHVCQUF1QjtRQUNsQyxLQUFLLEVBQUUsVUFBVSxDQUFDLFlBQVksRUFBRTtRQUNoQyxXQUFXO0tBQ1osQ0FBQyxDQUFBO0lBQ0YsTUFBTSxPQUFPLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUE7SUFFcEMsTUFBTSxZQUFZLEdBQUcsTUFBTSxFQUFFLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUM7UUFDL0MsNkJBQTZCLEVBQUUsQ0FBQyxJQUFJLENBQUM7UUFDckMsU0FBUyxFQUFFLFFBQVE7UUFDbkIsSUFBSSxFQUFFO1lBQ0osRUFBRSxFQUFFLE9BQU87WUFDWCxlQUFlLEVBQUUsYUFBYTtZQUM5Qix1QkFBdUIsRUFBRSxvQkFBb0I7WUFDN0MsWUFBWSxFQUFFLE1BQU0sQ0FBQyxFQUFFLEVBQUU7WUFDekIsY0FBYyxFQUFFLFVBQVUsQ0FBQyxZQUFZLEVBQUU7WUFDekMsZUFBZSxFQUFFLGNBQWM7WUFDL0IsTUFBTTtZQUNOLFVBQVUsRUFBRSxXQUFXO1lBQ3ZCLFVBQVUsRUFBRSxXQUFXO1NBQ3hCO0tBQ0YsQ0FBQyxDQUFDLENBQUE7SUFDSCxNQUFNLGVBQWUsR0FBRyx1QkFBdUIsQ0FBQyxZQUFZLENBQUMsSUFBSSxPQUFPLENBQUE7SUFFeEUsTUFBTSxjQUFjLENBQUMsVUFBVSxFQUFFLE1BQU0sRUFBRTtRQUN2QyxNQUFNO1FBQ04sT0FBTyxFQUFFLGVBQWU7UUFDeEIsY0FBYztRQUNkLE1BQU07UUFDTixNQUFNO0tBQ1AsQ0FBQyxDQUFBO0lBRUYsT0FBTyxlQUFlLENBQUE7QUFDeEIsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLHVCQUF1QixDQUFDLFlBQVk7SUFDM0MsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUE7SUFFN0MsTUFBTSxHQUFHLEdBQUcsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBRTNCLElBQUksQ0FBQyxHQUFHO1FBQUUsT0FBTyxJQUFJLENBQUE7SUFFckIsTUFBTSxFQUFFLEdBQUcsR0FBRyxDQUFDLEVBQUUsQ0FBQTtJQUVqQixJQUFJLE9BQU8sRUFBRSxJQUFJLFFBQVEsSUFBSSxPQUFPLEVBQUUsSUFBSSxRQUFRO1FBQUUsT0FBTyxFQUFFLENBQUE7SUFFN0QsT0FBTyxJQUFJLENBQUE7QUFDYixDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQVMseUJBQXlCLENBQUMsTUFBTTtJQUN2QyxNQUFNLENBQUMsMEJBQTBCLEdBQUcsNkJBQTZCLENBQUMsTUFBTSxDQUFDLENBQUE7QUFDM0UsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxLQUFLLFVBQVUsaUJBQWlCLENBQUMsTUFBTTtJQUNyQyxNQUFNLFdBQVcsQ0FBQyxNQUFNLEVBQUU7UUFDeEIsTUFBTSxFQUFFLFFBQVE7UUFDaEIsY0FBYyxFQUFFLE1BQU0sQ0FBQywwQkFBMEIsSUFBSSxJQUFJO0tBQzFELENBQUMsQ0FBQTtJQUVGLE1BQU0sQ0FBQywwQkFBMEIsR0FBRyxTQUFTLENBQUE7QUFDL0MsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLHlCQUF5QixDQUFDLE1BQU07SUFDdkMsTUFBTSxDQUFDLDBCQUEwQixHQUFHLDZCQUE2QixDQUFDLE1BQU0sQ0FBQyxDQUFBO0FBQzNFLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsS0FBSyxVQUFVLGlCQUFpQixDQUFDLE1BQU07SUFDckMsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLDBCQUEwQixJQUFJLElBQUksQ0FBQTtJQUVoRSxNQUFNLENBQUMsMEJBQTBCLEdBQUcsU0FBUyxDQUFBO0lBRTdDLElBQUksQ0FBQyxjQUFjLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQyxNQUFNLElBQUksQ0FBQztRQUFFLE9BQU07SUFFdEUsTUFBTSxXQUFXLENBQUMsTUFBTSxFQUFFO1FBQ3hCLE1BQU0sRUFBRSxRQUFRO1FBQ2hCLGNBQWM7S0FDZixDQUFDLENBQUE7QUFDSixDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxNQUFNO0lBQ3RDLE1BQU0sV0FBVyxDQUFDLE1BQU0sRUFBRTtRQUN4QixNQUFNLEVBQUUsU0FBUztRQUNqQixjQUFjLEVBQUUsc0JBQXNCLENBQUMsTUFBTSxDQUFDO0tBQy9DLENBQUMsQ0FBQTtBQUNKLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxTQUFTLFlBQVksQ0FBQyxVQUFVLEVBQUUsTUFBTTtJQUN0QyxNQUFNLEVBQUUsR0FBRyxVQUFVLENBQUMsVUFBVSxFQUFFLENBQUE7SUFDbEMsTUFBTSxhQUFhLEdBQUcsRUFBRSxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQTtJQUMzRCxNQUFNLGNBQWMsR0FBRyxFQUFFLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFBO0lBQzlDLE1BQU0sb0JBQW9CLEdBQUcsRUFBRSxDQUFDLFVBQVUsQ0FBQyxlQUFlLENBQUMsQ0FBQTtJQUMzRCxNQUFNLGtCQUFrQixHQUFHLEdBQUcsYUFBYSxJQUFJLEVBQUUsQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLFVBQVUsRUFBRSxDQUFDLEVBQUUsQ0FBQTtJQUN4RixNQUFNLG1CQUFtQixHQUFHLEdBQUcsY0FBYyxJQUFJLEVBQUUsQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQTtJQUNqRixNQUFNLHFCQUFxQixHQUFHLEdBQUcsY0FBYyxJQUFJLEVBQUUsQ0FBQyxXQUFXLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxDQUFBO0lBQ3JGLE1BQU0sZ0JBQWdCLEdBQUcsR0FBRyxjQUFjLElBQUksRUFBRSxDQUFDLFdBQVcsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLENBQUE7SUFDakYsTUFBTSxpQkFBaUIsR0FBRyxHQUFHLG9CQUFvQixJQUFJLEVBQUUsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQTtJQUMzRSxNQUFNLHFCQUFxQixHQUFHLEdBQUcsb0JBQW9CLElBQUksRUFBRSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFBO0lBRW5GLE9BQU8sVUFBVTtTQUNkLEdBQUcsRUFBRTtTQUNMLEtBQUssQ0FBQzs7O2VBR0ksY0FBYztxQkFDUixvQkFBb0I7ZUFDMUIsaUJBQWlCLE1BQU0sZ0JBQWdCO2dCQUN0QyxxQkFBcUIsTUFBTSxFQUFFLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxZQUFZLEVBQUUsQ0FBQztnQkFDOUQsbUJBQW1CLE1BQU0sa0JBQWtCO2dCQUMzQyxxQkFBcUIsTUFBTSxFQUFFLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQzs7S0FFdkUsQ0FBQyxDQUFBO0FBQ04sQ0FBQztBQUVEOzs7Ozs7Ozs7R0FTRztBQUNILEtBQUssVUFBVSxvQkFBb0IsQ0FBQyxFQUFDLFVBQVUsRUFBRSxXQUFXLEVBQUUsRUFBRSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUM7SUFDakYsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDO1FBQ2QsU0FBUztRQUNULGVBQWUsRUFBRSxDQUFDLFVBQVUsQ0FBQztRQUM3QixhQUFhLEVBQUUsQ0FBQyxVQUFVLENBQUM7UUFDM0IsSUFBSSxFQUFFO1lBQ0osRUFBRSxFQUFFLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRTtZQUN4QixDQUFDLFVBQVUsQ0FBQyxFQUFFLEtBQUs7WUFDbkIsVUFBVSxFQUFFLFdBQVc7WUFDdkIsVUFBVSxFQUFFLFdBQVc7U0FDeEI7S0FDRixDQUFDLENBQUE7SUFFRixNQUFNLEVBQUUsR0FBRyxNQUFNLFlBQVksQ0FBQyxFQUFDLFVBQVUsRUFBRSxFQUFFLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBQyxDQUFDLENBQUE7SUFFakUsSUFBSSxFQUFFLEtBQUssSUFBSTtRQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsaUJBQWlCLFNBQVMsSUFBSSxVQUFVLGVBQWUsQ0FBQyxDQUFBO0lBRXpGLE9BQU8sRUFBRSxDQUFBO0FBQ1gsQ0FBQztBQUVEOzs7Ozs7OztHQVFHO0FBQ0gsS0FBSyxVQUFVLFlBQVksQ0FBQyxFQUFDLFVBQVUsRUFBRSxFQUFFLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBQztJQUM1RCxNQUFNLElBQUksR0FBRywyQ0FBMkMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEtBQUssQ0FBQzthQUM5RCxFQUFFLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQztXQUN0QixFQUFFLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQztZQUN2QixFQUFFLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDO0dBQ3hELENBQUMsQ0FBQyxDQUFBO0lBRUgsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFBO0lBRTlCLE9BQU8sSUFBSSxDQUFBO0FBQ2IsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLGVBQWUsQ0FBQyxNQUFNO0lBQzdCLE1BQU0sZ0JBQWdCLEdBQUcsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFBO0lBRXRDLElBQUksQ0FBQyxnQkFBZ0I7UUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLDhCQUE4QixDQUFDLENBQUE7SUFFdEUsT0FBTyxnQkFBZ0IsQ0FBQTtBQUN6QixDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQVMsMkJBQTJCLENBQUMsVUFBVTtJQUM3QyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxpQkFBaUIsQ0FBQyxFQUFFLENBQUM7UUFDekUsVUFBVSxDQUFDLGVBQWUsR0FBRyxFQUFFLENBQUE7SUFDakMsQ0FBQztJQUVELE1BQU0sU0FBUyxHQUFHLFVBQVUsQ0FBQyxlQUFlLENBQUE7SUFFNUMsSUFBSSxDQUFDLFNBQVM7UUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLDJDQUEyQyxVQUFVLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQyxDQUFBO0lBRXZHLE9BQU8sU0FBUyxDQUFBO0FBQ2xCLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxLQUFLLFVBQVUsY0FBYyxDQUFDLFVBQVUsRUFBRSxNQUFNLEVBQUUsT0FBTztJQUN2RCxNQUFNLFNBQVMsR0FBRywyQkFBMkIsQ0FBQyxVQUFVLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUE7SUFFdkUsS0FBSyxNQUFNLFFBQVEsSUFBSSxDQUFDLEdBQUcsU0FBUyxDQUFDLEVBQUUsQ0FBQztRQUN0QyxNQUFNLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQTtJQUN6QixDQUFDO0FBQ0gsQ0FBQztBQUVELE9BQU8sRUFDTCx5QkFBeUIsRUFDekIseUJBQXlCLEVBQ3pCLFdBQVcsRUFDWCxpQkFBaUIsRUFDakIsa0JBQWtCLEVBQ2xCLGlCQUFpQixFQUNqQixxQkFBcUIsRUFDckIsZ0JBQWdCLEVBQ2hCLFlBQVksRUFDYixDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCBVVUlEIGZyb20gXCJwdXJlLXV1aWRcIlxuXG4vKipcbiAqIEF1ZGl0Q2hhbmdlcyB0eXBlLlxuICogQHR5cGVkZWYge1JlY29yZDxzdHJpbmcsID8+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==
|