velocious 1.0.664 → 1.0.665
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/README.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* Controllers and views for HTTP endpoints
|
|
16
16
|
* Frontend-model transport for creating, updating, querying, and subscribing to query-filtered lifecycle events over HTTP/WebSocket, including committed counter-cache parent updates, structured per-attribute validation error responses, immutable per-operation remote request context, registration-local tenant subscription partitioning, and one-budget WebSocket startup controls (see [docs/frontend-models.md](docs/frontend-models.md), [docs/remote-request-context.md](docs/remote-request-context.md), and [docs/websocket-channels.md](docs/websocket-channels.md))
|
|
17
17
|
* Client-side offline sync mutation logs and frontend-model optimistic queueing primitives (see the [shared-resource sync developer guide](docs/shared-resource-sync-guide.md) and [offline sync architecture](docs/offline-sync.md))
|
|
18
|
-
* Declarative client sync scopes with per-scope cursors, generation-fenced identity replacement and selected-scope cache reset, automatic mutation tracking, opt-in durable base-version conflict replay, realtime delivery and reconnect gap closure, computed server-publish scope metadata, and immutable-handle project clients whose local database state plus remote pull/replay/realtime request context stay tenant-bound through reconnect (see [docs/sync-client.md](docs/sync-client.md), [docs/remote-request-context.md](docs/remote-request-context.md), and [docs/offline-sync.md](docs/offline-sync.md))
|
|
18
|
+
* Declarative client sync scopes with per-scope cursors, generation-fenced identity replacement and selected-scope cache reset, automatic mutation tracking, opt-in durable base-version conflict replay, realtime delivery and reconnect gap closure, computed server-publish scope metadata with atomic null-safe publisher row identities and legacy-duplicate reconciliation, and immutable-handle project clients whose local database state plus remote pull/replay/realtime request context stay tenant-bound through reconnect (see [docs/sync-client.md](docs/sync-client.md), [docs/remote-request-context.md](docs/remote-request-context.md), and [docs/offline-sync.md](docs/offline-sync.md))
|
|
19
19
|
* Reactive `useLiveQuery(Model.where(...))` queries for default databases plus immutable-handle tenant live-query sources whose committed events and refreshes stay on the captured physical tenant (see [docs/live-queries.md](docs/live-queries.md))
|
|
20
20
|
* Server-side sync envelope replay orchestration for app-owned sync receivers, including allowlisted authoritative conflict snapshots that retain submitted aliases in conflict metadata while keying `serverModel` by canonical model attributes (see [docs/sync-envelope-replay-service.md](docs/sync-envelope-replay-service.md))
|
|
21
21
|
* Self-sustaining sync feeds: upstream imports triggered by the changes pull itself, with framework-owned coalescing and throttling (see [docs/sync-upstream-imports.md](docs/sync-upstream-imports.md))
|
|
@@ -153,13 +153,20 @@ export default class SyncPublisher {
|
|
|
153
153
|
/**
|
|
154
154
|
* Upserts the published server-origin sync row for a resource identity:
|
|
155
155
|
* server-origin rows carry a null actor column (no device to echo the
|
|
156
|
-
* change back to), so repeated server changes to one resource
|
|
157
|
-
* re-sequence one feed row.
|
|
156
|
+
* change back to), so repeated server changes to one complete resource and
|
|
157
|
+
* scope identity reuse and re-sequence one feed row. A database advisory
|
|
158
|
+
* lock serializes reconciliation plus the shared upsert because unique
|
|
159
|
+
* constraints containing nullable actor/scope columns do not enforce this
|
|
160
|
+
* identity portably across supported databases. Reconciliation retains the
|
|
161
|
+
* row with the newest feed sequence (then lowest id for a deterministic tie)
|
|
162
|
+
* and removes older matching server-origin rows before applying the current
|
|
163
|
+
* mutation.
|
|
158
164
|
* @param {Record<string, ReturnType<typeof JSON.parse>>} attributes - Snapshotted sync row attributes.
|
|
159
165
|
* @param {ReturnType<typeof JSON.parse>} syncModel - Operation-bound or static Sync model interface.
|
|
166
|
+
* @param {string[]} scopeColumnNames - Persisted scope columns participating in the complete identity.
|
|
160
167
|
* @returns {Promise<ReturnType<typeof JSON.parse>>} Upserted sync row.
|
|
161
168
|
*/
|
|
162
|
-
upsertPublishedSyncRow(attributes: Record<string, ReturnType<typeof JSON.parse>>, syncModel?: ReturnType<typeof JSON.parse
|
|
169
|
+
upsertPublishedSyncRow(attributes: Record<string, ReturnType<typeof JSON.parse>>, syncModel?: ReturnType<typeof JSON.parse>, scopeColumnNames?: string[]): Promise<ReturnType<typeof JSON.parse>>;
|
|
163
170
|
/**
|
|
164
171
|
* Returns the broadcaster delivering declared broadcasts: the injected one,
|
|
165
172
|
* or the configuration's channel broadcast awaited through the pending
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-publisher.d.ts","sourceRoot":"","sources":["../../../src/sync/sync-publisher.js"],"names":[],"mappings":"AAEA,OAAO,aAAa,MAAM,qBAAqB,CAAA;AAC/C,OAAO,MAAM,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"sync-publisher.d.ts","sourceRoot":"","sources":["../../../src/sync/sync-publisher.js"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,8 @@ import Configuration from "../configuration.js";
|
|
|
3
3
|
import Logger from "../logger.js";
|
|
4
4
|
import { scalarModelPrimaryKeyValue } from "../utils/model-primary-key.js";
|
|
5
5
|
import restArgsError from "../utils/rest-args-error.js";
|
|
6
|
+
import sha256Hex from "../utils/sha256-hex.js";
|
|
7
|
+
import stableJsonStringify from "../utils/stable-json.js";
|
|
6
8
|
import { declaredSyncScopeAttributes } from "./sync-scope-attributes.js";
|
|
7
9
|
import { deliverDeclaredBroadcasts, upsertSyncRow } from "./sync-change-fanout.js";
|
|
8
10
|
import { isPublishingSuppressed } from "./sync-publish-suppression.js";
|
|
@@ -184,7 +186,8 @@ export default class SyncPublisher {
|
|
|
184
186
|
: this.config.syncModel;
|
|
185
187
|
await record.connection().afterCommit(async () => {
|
|
186
188
|
try {
|
|
187
|
-
const
|
|
189
|
+
const scopeColumnNames = resourceConfig.scopePlan.map(({ columnName }) => columnName);
|
|
190
|
+
const syncRow = await this.upsertPublishedSyncRow(attributes, operationScope, scopeColumnNames);
|
|
188
191
|
await this.broadcaster()({
|
|
189
192
|
body: {
|
|
190
193
|
echoOrigin: null,
|
|
@@ -315,21 +318,43 @@ export default class SyncPublisher {
|
|
|
315
318
|
/**
|
|
316
319
|
* Upserts the published server-origin sync row for a resource identity:
|
|
317
320
|
* server-origin rows carry a null actor column (no device to echo the
|
|
318
|
-
* change back to), so repeated server changes to one resource
|
|
319
|
-
* re-sequence one feed row.
|
|
321
|
+
* change back to), so repeated server changes to one complete resource and
|
|
322
|
+
* scope identity reuse and re-sequence one feed row. A database advisory
|
|
323
|
+
* lock serializes reconciliation plus the shared upsert because unique
|
|
324
|
+
* constraints containing nullable actor/scope columns do not enforce this
|
|
325
|
+
* identity portably across supported databases. Reconciliation retains the
|
|
326
|
+
* row with the newest feed sequence (then lowest id for a deterministic tie)
|
|
327
|
+
* and removes older matching server-origin rows before applying the current
|
|
328
|
+
* mutation.
|
|
320
329
|
* @param {Record<string, ReturnType<typeof JSON.parse>>} attributes - Snapshotted sync row attributes.
|
|
321
330
|
* @param {ReturnType<typeof JSON.parse>} syncModel - Operation-bound or static Sync model interface.
|
|
331
|
+
* @param {string[]} scopeColumnNames - Persisted scope columns participating in the complete identity.
|
|
322
332
|
* @returns {Promise<ReturnType<typeof JSON.parse>>} Upserted sync row.
|
|
323
333
|
*/
|
|
324
|
-
async upsertPublishedSyncRow(attributes, syncModel = this.config.syncModel) {
|
|
325
|
-
|
|
326
|
-
|
|
334
|
+
async upsertPublishedSyncRow(attributes, syncModel = this.config.syncModel, scopeColumnNames = []) {
|
|
335
|
+
/** @type {Record<string, ReturnType<typeof JSON.parse>>} */
|
|
336
|
+
const identity = {
|
|
327
337
|
[this.config.actorForeignKeyColumn]: null,
|
|
328
338
|
resource_id: attributes.resource_id,
|
|
329
339
|
resource_type: attributes.resource_type
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
|
|
340
|
+
};
|
|
341
|
+
for (const columnName of scopeColumnNames) {
|
|
342
|
+
if (!Object.hasOwn(attributes, columnName)) {
|
|
343
|
+
throw new Error(`Published sync row identity is missing the scope column ${columnName}`);
|
|
344
|
+
}
|
|
345
|
+
identity[columnName] = attributes[columnName];
|
|
346
|
+
}
|
|
347
|
+
return await this.config.syncModel.withAdvisoryLock(syncPublisherIdentityLockName(identity), async () => {
|
|
348
|
+
const matchingSyncs = await syncModel
|
|
349
|
+
.where(identity)
|
|
350
|
+
.toArray();
|
|
351
|
+
matchingSyncs.sort(comparePublishedSyncRowsByRecency);
|
|
352
|
+
const [existingSync, ...duplicateSyncs] = matchingSyncs;
|
|
353
|
+
for (const duplicateSync of duplicateSyncs) {
|
|
354
|
+
await duplicateSync.destroy();
|
|
355
|
+
}
|
|
356
|
+
return await upsertSyncRow({ attributes, existingSync, syncModel });
|
|
357
|
+
}, { dedicatedConnection: true });
|
|
333
358
|
}
|
|
334
359
|
/**
|
|
335
360
|
* Returns the broadcaster delivering declared broadcasts: the injected one,
|
|
@@ -377,6 +402,38 @@ export default class SyncPublisher {
|
|
|
377
402
|
return this._logger;
|
|
378
403
|
}
|
|
379
404
|
}
|
|
405
|
+
/**
|
|
406
|
+
* Returns a deterministic, MySQL-safe advisory-lock name for one complete
|
|
407
|
+
* server-origin publisher identity. Stable JSON preserves null actor/scope
|
|
408
|
+
* components distinctly from strings, and the truncated SHA-256 digest keeps
|
|
409
|
+
* the final name below MySQL/MariaDB's 64-character `GET_LOCK` limit.
|
|
410
|
+
* @param {Record<string, ReturnType<typeof JSON.parse>>} identity - Complete sync-row identity in column form.
|
|
411
|
+
* @returns {string} Advisory-lock name.
|
|
412
|
+
*/
|
|
413
|
+
function syncPublisherIdentityLockName(identity) {
|
|
414
|
+
const hash = sha256Hex(stableJsonStringify(identity)).slice(0, 32);
|
|
415
|
+
return `vsp:${hash}`;
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Orders matching published rows by the feed's public recency contract so
|
|
419
|
+
* legacy duplicates have one deterministic survivor. Server sequences are
|
|
420
|
+
* positive and monotonic; a legacy null sequence is older than any assigned
|
|
421
|
+
* sequence, and the immutable row id breaks otherwise-equal ties.
|
|
422
|
+
* @param {ReturnType<typeof JSON.parse>} left - First matching sync row.
|
|
423
|
+
* @param {ReturnType<typeof JSON.parse>} right - Second matching sync row.
|
|
424
|
+
* @returns {number} Sort comparison with the canonical survivor first.
|
|
425
|
+
*/
|
|
426
|
+
function comparePublishedSyncRowsByRecency(left, right) {
|
|
427
|
+
const leftSequence = left.serverSequence();
|
|
428
|
+
const rightSequence = right.serverSequence();
|
|
429
|
+
if (leftSequence === null && rightSequence !== null)
|
|
430
|
+
return 1;
|
|
431
|
+
if (leftSequence !== null && rightSequence === null)
|
|
432
|
+
return -1;
|
|
433
|
+
if (leftSequence !== rightSequence)
|
|
434
|
+
return rightSequence - leftSequence;
|
|
435
|
+
return left.id().localeCompare(right.id());
|
|
436
|
+
}
|
|
380
437
|
/**
|
|
381
438
|
* Resolves a model class's active publish declaration from `static sync`.
|
|
382
439
|
* Opted-out (`publish: false`) and undeclared models resolve to null; every
|
|
@@ -548,4 +605,4 @@ function isoDate(value) {
|
|
|
548
605
|
}
|
|
549
606
|
return value.toISOString();
|
|
550
607
|
}
|
|
551
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1wdWJsaXNoZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc3luYy9zeW5jLXB1Ymxpc2hlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxhQUFhLE1BQU0scUJBQXFCLENBQUE7QUFDL0MsT0FBTyxNQUFNLE1BQU0sY0FBYyxDQUFBO0FBQ2pDLE9BQU8sRUFBQywwQkFBMEIsRUFBQyxNQUFNLCtCQUErQixDQUFBO0FBQ3hFLE9BQU8sYUFBYSxNQUFNLDZCQUE2QixDQUFBO0FBRXZELE9BQU8sRUFBQywyQkFBMkIsRUFBQyxNQUFNLDRCQUE0QixDQUFBO0FBQ3RFLE9BQU8sRUFBQyx5QkFBeUIsRUFBRSxhQUFhLEVBQUMsTUFBTSx5QkFBeUIsQ0FBQTtBQUNoRixPQUFPLEVBQUMsc0JBQXNCLEVBQUMsTUFBTSwrQkFBK0IsQ0FBQTtBQUNwRSxPQUFPLEVBQUMsc0JBQXNCLEVBQUMsTUFBTSx3QkFBd0IsQ0FBQTtBQUU3RCxzRkFBc0Y7QUFDdEYsTUFBTSx3QkFBd0IsR0FBRyxFQUFDLE1BQU0sRUFBRSxhQUFhLEVBQUUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLEVBQUUsYUFBYSxFQUFDLENBQUE7QUFFeEc7Ozs7OztvREFNb0Q7QUFDcEQsTUFBTSw0QkFBNEIsR0FBRyxDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUMsQ0FBQTtBQUV6RCxvREFBb0Q7QUFDcEQsTUFBTSxnQ0FBZ0MsR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFBO0FBRXREOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTZCRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQU8sYUFBYTtJQUNoQzs7Ozs7Ozs7T0FRRztJQUNILFlBQVksT0FBTyxHQUFHLEVBQUU7UUFDdEIsTUFBTSxFQUFDLHFCQUFxQixHQUFHLHlCQUF5QixFQUFFLFdBQVcsRUFBRSxhQUFhLEdBQUcsYUFBYSxDQUFDLE9BQU8sRUFBRSxFQUFF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aGVja1xuXG5pbXBvcnQgQ29uZmlndXJhdGlvbiBmcm9tIFwiLi4vY29uZmlndXJhdGlvbi5qc1wiXG5pbXBvcnQgTG9nZ2VyIGZyb20gXCIuLi9sb2dnZXIuanNcIlxuaW1wb3J0IHtzY2FsYXJNb2RlbFByaW1hcnlLZXlWYWx1ZX0gZnJvbSBcIi4uL3V0aWxzL21vZGVsLXByaW1hcnkta2V5LmpzXCJcbmltcG9ydCByZXN0QXJnc0Vycm9yIGZyb20gXCIuLi91dGlscy9yZXN0LWFyZ3MtZXJyb3IuanNcIlxuXG5pbXBvcnQge2RlY2xhcmVkU3luY1Njb3BlQXR0cmlidXRlc30gZnJvbSBcIi4vc3luYy1zY29wZS1hdHRyaWJ1dGVzLmpzXCJcbmltcG9ydCB7ZGVsaXZlckRlY2xhcmVkQnJvYWRjYXN0cywgdXBzZXJ0U3luY1Jvd30gZnJvbSBcIi4vc3luYy1jaGFuZ2UtZmFub3V0LmpzXCJcbmltcG9ydCB7aXNQdWJsaXNoaW5nU3VwcHJlc3NlZH0gZnJvbSBcIi4vc3luYy1wdWJsaXNoLXN1cHByZXNzaW9uLmpzXCJcbmltcG9ydCB7VkVMT0NJT1VTX1NZTkNfQ0hBTk5FTH0gZnJvbSBcIi4vc3luYy1jaGFubmVsLW5hbWUuanNcIlxuXG4vKiogQHR5cGUge3tjcmVhdGU6IFwiYWZ0ZXJDcmVhdGVcIiwgdXBkYXRlOiBcImFmdGVyVXBkYXRlXCIsIGRlc3Ryb3k6IFwiYWZ0ZXJEZXN0cm95XCJ9fSAqL1xuY29uc3QgUFVCTElTSEVEX0NBTExCQUNLX05BTUVTID0ge2NyZWF0ZTogXCJhZnRlckNyZWF0ZVwiLCBkZXN0cm95OiBcImFmdGVyRGVzdHJveVwiLCB1cGRhdGU6IFwiYWZ0ZXJVcGRhdGVcIn1cblxuLyoqXG4gKiBPcGVyYXRpb25zIHB1Ymxpc2hlZCBieSBkZWZhdWx0IGZvciBtb2RlbHMgZGVjbGFyaW5nIGBzdGF0aWMgc3luY2AgcHVibGlzaFxuICogd2l0aG91dCBhbiBgb3BlcmF0aW9uc2Aga2V5OiBzZXJ2ZXItc2lkZSBjcmVhdGVzIGFuZCB1cGRhdGVzIHB1Ymxpc2hcbiAqIGF1dG9tYXRpY2FsbHkuIERlc3Ryb3lzIGFyZSBub3QgcHVibGlzaGVkIGJ5IGRlZmF1bHQgYmVjYXVzZSBhIHNlcnZlclxuICogZGVzdHJveSBpcyBvZnRlbiBjbGVhbnVwIHJhdGhlciB0aGFuIGEgc3luY2VkIGRlbGV0ZTsgb3B0IGluIHdpdGggYW5cbiAqIG9wZXJhdGlvbnMgbGlzdC5cbiAqIEB0eXBlIHtBcnJheTxcImNyZWF0ZVwiIHwgXCJ1cGRhdGVcIiB8IFwiZGVzdHJveVwiPn0gKi9cbmNvbnN0IERFRkFVTFRfUFVCTElTSEVEX09QRVJBVElPTlMgPSBbXCJjcmVhdGVcIiwgXCJ1cGRhdGVcIl1cblxuLyoqIEB0eXBlIHtXZWFrTWFwPENvbmZpZ3VyYXRpb24sIFN5bmNQdWJsaXNoZXI+fSAqL1xuY29uc3Qgc3RhcnRlZFB1Ymxpc2hlcnNCeUNvbmZpZ3VyYXRpb24gPSBuZXcgV2Vha01hcCgpXG5cbi8qKlxuICogRGVjbGFyYXRpdmUgc2VydmVyLXNpZGUgc3luYyBwdWJsaXNoZXIg4oCUIHRoZSBzZXJ2ZXIgbWlycm9yIG9mIHRoZSBjbGllbnQnc1xuICogdHJhY2stYnktZGVmYXVsdCBtdXRhdGlvbiB0cmFja2luZy5cbiAqXG4gKiBTZXJ2ZXIgbW9kZWxzIGRlY2xhcmUgd2hhdCB0byBwdWJsaXNoIHRocm91Z2ggYHN0YXRpYyBzeW5jYCdzIGBwdWJsaXNoYFxuICoga2V5LCBhbmQgVmVsb2Npb3VzIHdyaXRlcyBldmVyeSBjb21taXR0ZWQgc2VydmVyLXNpZGUgY2hhbmdlIHRvIHRoZSBzeW5jXG4gKiBjaGFuZ2UgZmVlZCAobW9kZWwtYmFja2VkIFN5bmMtcm93IHVwc2VydCB3aXRoIHNlcnZlciByZS1zZXF1ZW5jaW5nKSBhbmRcbiAqIGJyb2FkY2FzdHMgdGhlIHN0YW5kYXJkIHN5bmMgZW52ZWxvcGUgKGB7ZWNob09yaWdpbiwgc3luY3M6IFsuLi5dfWApIG9uIHRoZVxuICogZnJhbWV3b3JrIHN5bmMgY2hhbm5lbCAoe0BsaW5rIFZFTE9DSU9VU19TWU5DX0NIQU5ORUx9KSBzY29wZWQgYnkgdGhlXG4gKiBjaGFuZ2UncyBkZXJpdmVkIHNjb3BlLXBhcnRpdGlvbiB2YWx1ZXMsIHNvIGRldmljZXMgcmVjZWl2ZSBzZXJ2ZXItb3JpZ2luXG4gKiBjaGFuZ2VzIHdpdGhvdXQgYXBwIGNvZGUgZGVjbGFyaW5nIGNoYW5uZWxzIG9yIGNhbGxpbmcgbWFudWFsXG4gKiB1cHNlcnQvYnJvYWRjYXN0IGhlbHBlcnM6XG4gKlxuICogICAgIHN0YXRpYyBzeW5jID0ge3B1Ymxpc2g6IHRydWV9IC8vIGRlZmF1bHQgcGF5bG9hZCAoYXR0cmlidXRlcykgKyBkZWZhdWx0IHNjb3BlIHBhcnRpdGlvblxuICogICAgIHN0YXRpYyBzeW5jID0ge3B1Ymxpc2g6IHtzZXJpYWxpemU6IChyZWNvcmQpID0+ICh7aWQ6IHJlY29yZC5pZCgpLCBwaW46IHJlY29yZC5waW4oKX0pfX1cbiAqXG4gKiBUaGUgc2NvcGUgcGFydGl0aW9uIGNvbWVzIGZyb20gdGhlIHN5bmMgbW9kZWwncyBgc3RhdGljXG4gKiBzeW5jU2NvcGVBdHRyaWJ1dGVzYCBkZWNsYXJhdGlvbiAoZm9yIGV4YW1wbGUgYFtcImV2ZW50SWRcIl1gIG9yXG4gKiBgW1wiYWNjb3VudElkXCJdYCDigJQgVmVsb2Npb3VzIGhhcyBubyBidWlsdC1pbiBwYXJ0aXRpb24gbmFtZSk6IGVhY2ggZGVjbGFyZWRcbiAqIHNjb3BlIGF0dHJpYnV0ZSByZWFkcyB0aGUgcmVjb3JkJ3MgYXR0cmlidXRlIG9mIHRoZSBzYW1lIG5hbWUgd2hlbiB0aGVcbiAqIG1vZGVsIGhhcyBvbmUsIGVsc2UgdGhlIHJlY29yZCdzIG93biBpZCAoc2NvcGUtcm9vdCBtb2RlbHMpLCBvdmVycmlkYWJsZVxuICogcGVyIG1vZGVsIHRocm91Z2ggYHB1Ymxpc2g6IHtzY29wZUF0dHJpYnV0ZXM6IHthY2NvdW50SWQ6IFwib3duZXJJZFwifX1gLlxuICogVGhlIHByZS1mcmFtZXdvcmstY2hhbm5lbCBgYnJvYWRjYXN0c2AgbGlzdCBhbmQgdGhlIGBldmVudElkYFxuICogc3RyaW5nL3Jlc29sdmVyLWZ1bmN0aW9uIGRlY2xhcmF0aW9uIGZvcm1zIGtlZXAgd29ya2luZyBidXQgYXJlIGRlcHJlY2F0ZWQuXG4gKlxuICogUmVwbGF5ZWQgZGV2aWNlIG11dGF0aW9ucyBuZXZlciBkb3VibGUtcHVibGlzaDogdGhlIGZyYW1ld29yaydzIHJvdXRlZFxuICogcmVwbGF5IGFwcGx5IG1hcmtzIGl0cyB3cml0dGVuIHJlY29yZHMgdGhyb3VnaCBgbWFya1NlcnZlckFwcGx5KHJlY29yZClgXG4gKiAoc2VlIHN5bmMtcHVibGlzaC1zdXBwcmVzc2lvbi5qcyksIGFuZCBhcHAgY29kZSBhcHBseWluZyBhbHJlYWR5LXN5bmNlZFxuICogZGF0YSBjYW4gdXNlIGBtYXJrU2VydmVyQXBwbHlgL2B3aXRob3V0UHVibGlzaGluZ2AgdGhlIHNhbWUgd2F5LlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTeW5jUHVibGlzaGVyIHtcbiAgLyoqXG4gICAqIEJ1aWxkcyB0aGUgc3luYyBwdWJsaXNoZXIgYnkgZGVyaXZpbmcgcHVibGlzaGVkIHJlc291cmNlcyBmcm9tIHRoZVxuICAgKiBjb25maWd1cmF0aW9uJ3MgcmVnaXN0ZXJlZCBtb2RlbHM6IGV2ZXJ5IG1vZGVsIGRlY2xhcmluZyBgc3RhdGljIHN5bmNgXG4gICAqIHdpdGggYSBgcHVibGlzaGAgZGVjbGFyYXRpb24gYmVjb21lcyBhIHB1Ymxpc2hlZCByZXNvdXJjZVxuICAgKiAoYHB1Ymxpc2g6IGZhbHNlYCBvcHRzIG91dCkuIFRoZSBzeW5jL2NoYW5nZSBtb2RlbCBpcyB0aGUgcmVnaXN0ZXJlZFxuICAgKiBcIlN5bmNcIiBtb2RlbCBhbmQgYnJvYWRjYXN0cyBkZWZhdWx0IHRvIHRoZSBjb25maWd1cmF0aW9uJ3MgY2hhbm5lbFxuICAgKiBicm9hZGNhc3QuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaGVyT3B0aW9uc30gW29wdGlvbnNdIC0gT3B0aW9uYWwgb3ZlcnJpZGVzLlxuICAgKi9cbiAgY29uc3RydWN0b3Iob3B0aW9ucyA9IHt9KSB7XG4gICAgY29uc3Qge2FjdG9yRm9yZWlnbktleUNvbHVtbiA9IFwiYXV0aGVudGljYXRpb25fdG9rZW5faWRcIiwgYnJvYWRjYXN0ZXIsIGNvbmZpZ3VyYXRpb24gPSBDb25maWd1cmF0aW9uLmN1cnJlbnQoKSwgb25FcnJvciwgc3luY01vZGVsLCAuLi5yZXN0T3B0aW9uc30gPSBvcHRpb25zXG5cbiAgICByZXN0QXJnc0Vycm9yKHJlc3RPcHRpb25zKVxuXG4gICAgY29uc3QgbW9kZWxDbGFzc2VzID0gY29uZmlndXJhdGlvbi5nZXRNb2RlbENsYXNzZXMoKVxuICAgIGNvbnN0IHB1Ymxpc2hpbmdNb2RlbENsYXNzZXMgPSBPYmplY3QudmFsdWVzKG1vZGVsQ2xhc3NlcykuZmlsdGVyKChtb2RlbENsYXNzKSA9PiBwdWJsaXNoRGVjbGFyYXRpb25Gb3IobW9kZWxDbGFzcykpXG5cbiAgICBpZiAocHVibGlzaGluZ01vZGVsQ2xhc3Nlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlN5bmNQdWJsaXNoZXIgZm91bmQgbm8gcmVnaXN0ZXJlZCBtb2RlbHMgZGVjbGFyaW5nIHN0YXRpYyBzeW5jIHB1Ymxpc2ggLSBkZWNsYXJlIGBzdGF0aWMgc3luYyA9IHtwdWJsaXNoOiB7c2VyaWFsaXplfX1gIG9uIHRoZSBtb2RlbHMgd2hvc2Ugc2VydmVyLXNpZGUgY2hhbmdlcyBzaG91bGQgcHVibGlzaCB0byB0aGUgc3luYyBmZWVkXCIpXG4gICAgfVxuXG4gICAgY29uc3QgcmVzb2x2ZWRTeW5jTW9kZWwgPSBzeW5jTW9kZWwgfHwgbW9kZWxDbGFzc2VzLlN5bmNcblxuICAgIGlmICghcmVzb2x2ZWRTeW5jTW9kZWwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlN5bmNQdWJsaXNoZXIgcmVxdWlyZXMgYSByZWdpc3RlcmVkIFxcXCJTeW5jXFxcIiBtb2RlbCBmb3IgcHVibGlzaGVkIHN5bmMgY2hhbmdlIHJvd3MgKG9yIHBhc3Mgb3B0aW9ucy5zeW5jTW9kZWwpXCIpXG4gICAgfVxuXG4gICAgY29uc3Qgc2NvcGVBdHRyaWJ1dGVzID0gZGVjbGFyZWRTeW5jU2NvcGVBdHRyaWJ1dGVzKHJlc29sdmVkU3luY01vZGVsKVxuICAgIC8qKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgaW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaGVyUmVzb3VyY2VDb25maWc+fSAqL1xuICAgIGNvbnN0IHJlc291cmNlcyA9IHt9XG5cbiAgICBmb3IgKGNvbnN0IG1vZGVsQ2xhc3Mgb2YgcHVibGlzaGluZ01vZGVsQ2xhc3Nlcykge1xuICAgICAgY29uc3QgcHVibGlzaCA9IHB1Ymxpc2hEZWNsYXJhdGlvbkZvcihtb2RlbENsYXNzKVxuICAgICAgY29uc3QgcmVzb3VyY2VDb25maWcgPSByZXNvdXJjZUNvbmZpZ0Zyb21QdWJsaXNoRGVjbGFyYXRpb24oe21vZGVsQ2xhc3MsIHB1Ymxpc2gsIHNjb3BlQXR0cmlidXRlcywgc3luY01vZGVsOiByZXNvbHZlZFN5bmNNb2RlbH0pXG5cbiAgICAgIHJlc291cmNlc1tyZXNvdXJjZUNvbmZpZy5yZXNvdXJjZVR5cGVdID0gcmVzb3VyY2VDb25maWdcbiAgICB9XG5cbiAgICAvKiogQHR5cGUge3thY3RvckZvcmVpZ25LZXlDb2x1bW46IHN0cmluZywgYnJvYWRjYXN0ZXI6IGltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hlck9wdGlvbnNbXCJicm9hZGNhc3RlclwiXSwgY29uZmlndXJhdGlvbjogQ29uZmlndXJhdGlvbiwgb25FcnJvcjogaW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaGVyT3B0aW9uc1tcIm9uRXJyb3JcIl0sIHJlc291cmNlczogUmVjb3JkPHN0cmluZywgaW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaGVyUmVzb3VyY2VDb25maWc+LCBzeW5jTW9kZWw6IFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+fX0gKi9cbiAgICB0aGlzLmNvbmZpZyA9IHthY3RvckZvcmVpZ25LZXlDb2x1bW4sIGJyb2FkY2FzdGVyLCBjb25maWd1cmF0aW9uLCBvbkVycm9yLCByZXNvdXJjZXMsIHN5bmNNb2RlbDogcmVzb2x2ZWRTeW5jTW9kZWx9XG4gICAgLyoqIEB0eXBlIHtBcnJheTx7Y2FsbGJhY2s6IChyZWNvcmQ6IFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+KSA9PiBQcm9taXNlPHZvaWQ+LCBjYWxsYmFja05hbWU6IFwiYWZ0ZXJDcmVhdGVcIiB8IFwiYWZ0ZXJVcGRhdGVcIiB8IFwiYWZ0ZXJEZXN0cm95XCIsIG1vZGVsQ2xhc3M6IFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+fT59ICovXG4gICAgdGhpcy5fcHVibGlzaGVkQ2FsbGJhY2tzID0gW11cbiAgICAvKiogQHR5cGUge0xvZ2dlciB8IG51bGx9ICovXG4gICAgdGhpcy5fbG9nZ2VyID0gbnVsbFxuICAgIHRoaXMuX3N0YXJ0ZWQgPSBmYWxzZVxuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyBhIHN5bmMgcHVibGlzaGVyIGRlcml2ZWQgZnJvbSB0aGUgZ2l2ZW4gY29uZmlndXJhdGlvbi4gQWxpYXMgZm9yXG4gICAqIGBuZXcgU3luY1B1Ymxpc2hlcih7Y29uZmlndXJhdGlvbiwgLi4ub3B0aW9uc30pYC5cbiAgICogQHBhcmFtIHtDb25maWd1cmF0aW9ufSBbY29uZmlndXJhdGlvbl0gLSBDb25maWd1cmF0aW9uIG93bmluZyB0aGUgcmVnaXN0ZXJlZCBtb2RlbHMuIERlZmF1bHRzIHRvIHRoZSBjdXJyZW50IGNvbmZpZ3VyYXRpb24uXG4gICAqIEBwYXJhbSB7T21pdDxpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoZXJPcHRpb25zLCBcImNvbmZpZ3VyYXRpb25cIj59IFtvcHRpb25zXSAtIE9wdGlvbmFsIG92ZXJyaWRlcy5cbiAgICogQHJldHVybnMge1N5bmNQdWJsaXNoZXJ9IFN5bmMgcHVibGlzaGVyIGRlcml2ZWQgZnJvbSB0aGUgY29uZmlndXJhdGlvbi5cbiAgICovXG4gIHN0YXRpYyBmcm9tQ29uZmlndXJhdGlvbihjb25maWd1cmF0aW9uID0gQ29uZmlndXJhdGlvbi5jdXJyZW50KCksIG9wdGlvbnMgPSB7fSkge1xuICAgIHJldHVybiBuZXcgU3luY1B1Ymxpc2hlcih7Li4ub3B0aW9ucywgY29uZmlndXJhdGlvbn0pXG4gIH1cblxuICAvKipcbiAgICogU3RhcnRzIChhbmQgbWVtb2l6ZXMgcGVyIGNvbmZpZ3VyYXRpb24pIHRoZSBzeW5jIHB1Ymxpc2hlciBmb3IgYSBzZXJ2ZXJcbiAgICogYm9vdDogbm8tb3Agd2hlbiBubyByZWdpc3RlcmVkIG1vZGVsIGRlY2xhcmVzIGEgcHVibGlzaCBjb25maWcsIGd1YXJkZWQgc29cbiAgICogcmVwZWF0ZWQgYm9vdHMgd2l0aCB0aGUgc2FtZSBjb25maWd1cmF0aW9uIHJlZ2lzdGVyIHRoZSBwdWJsaXNoIGNhbGxiYWNrc1xuICAgKiBvbmx5IG9uY2UuXG4gICAqIEBwYXJhbSB7Q29uZmlndXJhdGlvbn0gY29uZmlndXJhdGlvbiAtIENvbmZpZ3VyYXRpb24gb3duaW5nIHRoZSByZWdpc3RlcmVkIG1vZGVscy5cbiAgICogQHJldHVybnMge1Byb21pc2U8U3luY1B1Ymxpc2hlciB8IG51bGw+fSBTdGFydGVkIHB1Ymxpc2hlciwgb3IgbnVsbCB3aGVuIG5vIG1vZGVscyBkZWNsYXJlIHB1Ymxpc2guXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgc3RhcnRGcm9tQ29uZmlndXJhdGlvbihjb25maWd1cmF0aW9uKSB7XG4gICAgY29uc3Qgc3RhcnRlZFB1Ymxpc2hlciA9IHN0YXJ0ZWRQdWJsaXNoZXJzQnlDb25maWd1cmF0aW9uLmdldChjb25maWd1cmF0aW9uKVxuXG4gICAgaWYgKHN0YXJ0ZWRQdWJsaXNoZXIpIHJldHVybiBzdGFydGVkUHVibGlzaGVyXG5cbiAgICBpZiAoIU9iamVjdC52YWx1ZXMoY29uZmlndXJhdGlvbi5nZXRNb2RlbENsYXNzZXMoKSkuc29tZSgobW9kZWxDbGFzcykgPT4gcHVibGlzaERlY2xhcmF0aW9uRm9yKG1vZGVsQ2xhc3MpKSkgcmV0dXJuIG51bGxcblxuICAgIGNvbnN0IHB1Ymxpc2hlciA9IG5ldyBTeW5jUHVibGlzaGVyKHtjb25maWd1cmF0aW9ufSlcblxuICAgIHN0YXJ0ZWRQdWJsaXNoZXJzQnlDb25maWd1cmF0aW9uLnNldChjb25maWd1cmF0aW9uLCBwdWJsaXNoZXIpXG4gICAgYXdhaXQgcHVibGlzaGVyLnN0YXJ0KClcblxuICAgIHJldHVybiBwdWJsaXNoZXJcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgdGhlIHB1Ymxpc2ggY2FsbGJhY2tzIGZvciBldmVyeSBwdWJsaXNoZWQgcmVzb3VyY2U6IHNlcnZlci1zaWRlXG4gICAqIGNyZWF0ZXMgYW5kIHVwZGF0ZXMgKGRlc3Ryb3lzIHdoZW4gb3B0ZWQgaW4pIHVwc2VydCBhIHN5bmMgY2hhbmdlIHJvdyBhbmRcbiAgICogZmFuIG91dCB0aGUgZGVjbGFyZWQgYnJvYWRjYXN0cyBvbmNlIHRoZWlyIHRyYW5zYWN0aW9uIGNvbW1pdHMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgc3RhcnQoKSB7XG4gICAgaWYgKHRoaXMuX3N0YXJ0ZWQpIHJldHVyblxuXG4gICAgdGhpcy5fc3RhcnRlZCA9IHRydWVcblxuICAgIGZvciAoY29uc3QgcmVzb3VyY2VDb25maWcgb2YgT2JqZWN0LnZhbHVlcyh0aGlzLmNvbmZpZy5yZXNvdXJjZXMpKSB7XG4gICAgICBmb3IgKGNvbnN0IG9wZXJhdGlvbiBvZiByZXNvdXJjZUNvbmZpZy5vcGVyYXRpb25zKSB7XG4gICAgICAgIGNvbnN0IGNhbGxiYWNrTmFtZSA9IFBVQkxJU0hFRF9DQUxMQkFDS19OQU1FU1tvcGVyYXRpb25dXG4gICAgICAgIGNvbnN0IGNhbGxiYWNrID0gdGhpcy5wdWJsaXNoZWRNdXRhdGlvbkNhbGxiYWNrKHtvcGVyYXRpb24sIHJlc291cmNlQ29uZmlnfSlcblxuICAgICAgICByZXNvdXJjZUNvbmZpZy5tb2RlbENsYXNzW2NhbGxiYWNrTmFtZV0oY2FsbGJhY2spXG4gICAgICAgIHRoaXMuX3B1Ymxpc2hlZENhbGxiYWNrcy5wdXNoKHtjYWxsYmFjaywgY2FsbGJhY2tOYW1lLCBtb2RlbENsYXNzOiByZXNvdXJjZUNvbmZpZy5tb2RlbENsYXNzfSlcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVW5yZWdpc3RlcnMgYWxsIHB1Ymxpc2ggY2FsbGJhY2tzICh0ZXN0cywgc2h1dGRvd24pLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIHN0b3AoKSB7XG4gICAgZm9yIChjb25zdCB7Y2FsbGJhY2ssIGNhbGxiYWNrTmFtZSwgbW9kZWxDbGFzc30gb2YgdGhpcy5fcHVibGlzaGVkQ2FsbGJhY2tzKSB7XG4gICAgICBtb2RlbENsYXNzLnVucmVnaXN0ZXJMaWZlY3ljbGVDYWxsYmFjayhjYWxsYmFja05hbWUsIGNhbGxiYWNrKVxuICAgIH1cblxuICAgIHRoaXMuX3B1Ymxpc2hlZENhbGxiYWNrcyA9IFtdXG4gICAgdGhpcy5fc3RhcnRlZCA9IGZhbHNlXG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIHRoZSBsaWZlY3ljbGUgY2FsbGJhY2sgcHVibGlzaGluZyBvbmUgc2VydmVyLXNpZGUgbXV0YXRpb24uIFRoZVxuICAgKiBwdWJsaXNoZWQgcGF5bG9hZCAoZGVjbGFyYXRpb24gYHNlcmlhbGl6ZWApLCBldmVudCBzY29wZSwgYW5kIHN5bmMgdHlwZVxuICAgKiBhcmUgc25hcHNob3R0ZWQgYXQgbXV0YXRpb24tY2FsbGJhY2sgdGltZSwgc28gYWZ0ZXJTYXZlIGhvb2tzIGFzc2lnbmluZ1xuICAgKiB1bnNhdmVkIGF0dHJpYnV0ZXMgKG9yIGFueSBsYXRlciBkcmlmdCBvbiB0aGUgcmVjb3JkKSBjYW5ub3QgY2hhbmdlIHdoYXRcbiAgICogZ2V0cyBwdWJsaXNoZWQgdnMgd2hhdCB3YXMgY29tbWl0dGVkLiBQZXJzaXN0aW5nIGFuZCBicm9hZGNhc3RpbmcgYXJlXG4gICAqIGRlZmVycmVkIHRocm91Z2ggdGhlIG1vZGVsIGNvbm5lY3Rpb24ncyBhZnRlckNvbW1pdCBob29rIHNvIHRoZXkgb25seSBydW5cbiAgICogb25jZSB0aGUgbXV0YXRpb24ncyB0cmFuc2FjdGlvbiBoYXMgY29tbWl0dGVkIChpbW1lZGlhdGVseSB3aGVuIG5vXG4gICAqIHRyYW5zYWN0aW9uIGlzIG9wZW4pIC0gcm9sbGVkLWJhY2sgbXV0YXRpb25zIG5ldmVyIHB1Ymxpc2guIFBvc3QtY29tbWl0XG4gICAqIHB1Ymxpc2ggZmFpbHVyZXMgYXJlIHJlcG9ydGVkIHdpdGhvdXQgcmV0aHJvd2luZyBpbnRvIHRoZSBkcml2ZXInc1xuICAgKiBhZnRlckNvbW1pdCBjaGFpbiAoc2VlIHJlcG9ydEFmdGVyQ29tbWl0RXJyb3IpLlxuICAgKiBAcGFyYW0ge3tvcGVyYXRpb246IFwiY3JlYXRlXCIgfCBcInVwZGF0ZVwiIHwgXCJkZXN0cm95XCIsIHJlc291cmNlQ29uZmlnOiBpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoZXJSZXNvdXJjZUNvbmZpZ319IGFyZ3MgLSBPcGVyYXRpb24gYW5kIHJlc291cmNlIGNvbmZpZy5cbiAgICogQHJldHVybnMgeyhyZWNvcmQ6IFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+KSA9PiBQcm9taXNlPHZvaWQ+fSBMaWZlY3ljbGUgY2FsbGJhY2suXG4gICAqL1xuICBwdWJsaXNoZWRNdXRhdGlvbkNhbGxiYWNrKHtvcGVyYXRpb24sIHJlc291cmNlQ29uZmlnfSkge1xuICAgIHJldHVybiBhc3luYyAocmVjb3JkKSA9PiB7XG4gICAgICBpZiAoaXNQdWJsaXNoaW5nU3VwcHJlc3NlZChyZWNvcmQpKSByZXR1cm5cblxuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IHJlc291cmNlQ29uZmlnLnNlcmlhbGl6ZShyZWNvcmQpXG4gICAgICBjb25zdCByZXNvdXJjZUlkID0gU3RyaW5nKHNjYWxhck1vZGVsUHJpbWFyeUtleVZhbHVlKHJlY29yZC5pZCgpLCBgU3luYyBwdWJsaXNoaW5nIGZvciAke3Jlc291cmNlQ29uZmlnLnJlc291cmNlVHlwZX1gKSlcbiAgICAgIGNvbnN0IHN5bmNUeXBlID0gb3BlcmF0aW9uID09PSBcImRlc3Ryb3lcIiA/IFwiZGVsZXRlXCIgOiBcInVwZGF0ZVwiXG4gICAgICBjb25zdCBzY29wZVZhbHVlcyA9IGF3YWl0IHRoaXMucHVibGlzaGVkU2NvcGVWYWx1ZXMoe3JlY29yZCwgcmVzb3VyY2VDb25maWd9KVxuICAgICAgLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj59ICovXG4gICAgICBjb25zdCBhdHRyaWJ1dGVzID0ge1xuICAgICAgICBbdGhpcy5jb25maWcuYWN0b3JGb3JlaWduS2V5Q29sdW1uXTogbnVsbCxcbiAgICAgICAgY2xpZW50X3VwZGF0ZWRfYXQ6IG5ldyBEYXRlKCksXG4gICAgICAgIGRhdGE6IEpTT04uc3RyaW5naWZ5KGRhdGEpLFxuICAgICAgICByZXNvdXJjZV9pZDogcmVzb3VyY2VJZCxcbiAgICAgICAgcmVzb3VyY2VfdHlwZTogcmVzb3VyY2VDb25maWcucmVzb3VyY2VUeXBlLFxuICAgICAgICBzeW5jX3R5cGU6IHN5bmNUeXBlLFxuICAgICAgICAuLi5zY29wZVZhbHVlcy5jb2x1bW5zXG4gICAgICB9XG4gICAgICBjb25zdCBkYXRhYmFzZU9wZXJhdGlvbiA9IHJlY29yZC5kYXRhYmFzZU9wZXJhdGlvbigpXG4gICAgICBjb25zdCBvcGVyYXRpb25TY29wZSA9IGRhdGFiYXNlT3BlcmF0aW9uXG4gICAgICAgID8gZGF0YWJhc2VPcGVyYXRpb24uZm9yTW9kZWwodGhpcy5jb25maWcuc3luY01vZGVsKVxuICAgICAgICA6IHRoaXMuY29uZmlnLnN5bmNNb2RlbFxuXG4gICAgICBhd2FpdCByZWNvcmQuY29ubmVjdGlvbigpLmFmdGVyQ29tbWl0KGFzeW5jICgpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBzeW5jUm93ID0gYXdhaXQgdGhpcy51cHNlcnRQdWJsaXNoZWRTeW5jUm93KGF0dHJpYnV0ZXMsIG9wZXJhdGlvblNjb3BlKVxuXG4gICAgICAgICAgYXdhaXQgdGhpcy5icm9hZGNhc3RlcigpKHtcbiAgICAgICAgICAgIGJvZHk6IHtcbiAgICAgICAgICAgICAgZWNob09yaWdpbjogbnVsbCxcbiAgICAgICAgICAgICAgc3luY3M6IFt0aGlzLnB1Ymxpc2hlZFN5bmNFbnRyeSh7ZGF0YSwgcmVzb3VyY2VDb25maWcsIHJlc291cmNlSWQsIHN5bmNSb3csIHN5bmNUeXBlfSldXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY2hhbm5lbDogVkVMT0NJT1VTX1NZTkNfQ0hBTk5FTCxcbiAgICAgICAgICAgIHBhcmFtczogey4uLnNjb3BlVmFsdWVzLnBhcmFtcywgcmVzb3VyY2VUeXBlOiByZXNvdXJjZUNvbmZpZy5yZXNvdXJjZVR5cGV9XG4gICAgICAgICAgfSlcblxuICAgICAgICAgIGlmIChyZXNvdXJjZUNvbmZpZy5icm9hZGNhc3RzKSB7XG4gICAgICAgICAgICBhd2FpdCBkZWxpdmVyRGVjbGFyZWRCcm9hZGNhc3RzKHtcbiAgICAgICAgICAgICAgYXJnczoge2RhdGEsIG9wZXJhdGlvbiwgcmVjb3JkLCByZXNvdXJjZUlkLCByZXNvdXJjZVR5cGU6IHJlc291cmNlQ29uZmlnLnJlc291cmNlVHlwZSwgc3luY1Jvdywgc3luY1R5cGV9LFxuICAgICAgICAgICAgICBicm9hZGNhc3RlcjogdGhpcy5icm9hZGNhc3RlcigpLFxuICAgICAgICAgICAgICBicm9hZGNhc3RzOiByZXNvdXJjZUNvbmZpZy5icm9hZGNhc3RzXG4gICAgICAgICAgICB9KVxuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLnJlcG9ydEFmdGVyQ29tbWl0RXJyb3IoLyoqIEB0eXBlIHtFcnJvcn0gKi8gKGVycm9yKSlcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZXMgdGhlIHNjb3BlLXBhcnRpdGlvbiB2YWx1ZXMgZm9yIG9uZSBwdWJsaXNoZWQgbXV0YXRpb24gZnJvbSB0aGVcbiAgICogcmVzb3VyY2UncyBkZXJpdmVkIHNjb3BlIHBsYW46IGVhY2ggZW50cnkgcmVhZHMgaXRzIHJlY29yZCBhdHRyaWJ1dGUgKG9yXG4gICAqIHRoZSByZWNvcmQncyBvd24gaWQgZm9yIHNjb3BlLXJvb3QgbW9kZWxzLCBvciB0aGUgZGVwcmVjYXRlZCByZXNvbHZlclxuICAgKiBmdW5jdGlvbikuIFRoZSB2YWx1ZXMgYXJlIHBlcnNpc3RlZCBvbnRvIHRoZSBzeW5jIHJvdydzIHBhcnRpdGlvbiBjb2x1bW5zXG4gICAqIGFuZCBicm9hZGNhc3QgYXMgdGhlIGZyYW1ld29yayBzeW5jIGNoYW5uZWwncyBzY29waW5nIHBhcmFtcy5cbiAgICogQHBhcmFtIHt7cmVjb3JkOiBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPiwgcmVzb3VyY2VDb25maWc6IGltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hlclJlc291cmNlQ29uZmlnfX0gYXJncyAtIE11dGF0ZWQgcmVjb3JkIGFuZCByZXNvdXJjZSBjb25maWcuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHtjb2x1bW5zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCBudWxsPiwgcGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCBudWxsPn0+fSBTY29wZSB2YWx1ZXMga2V5ZWQgYnkgc3luYy1yb3cgY29sdW1uIGFuZCBieSBzY29wZSBhdHRyaWJ1dGUuXG4gICAqL1xuICBhc3luYyBwdWJsaXNoZWRTY29wZVZhbHVlcyh7cmVjb3JkLCByZXNvdXJjZUNvbmZpZ30pIHtcbiAgICAvKiogQHR5cGUge1JlY29yZDxzdHJpbmcsIHN0cmluZyB8IG51bGw+fSAqL1xuICAgIGNvbnN0IGNvbHVtbnMgPSB7fVxuICAgIC8qKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgc3RyaW5nIHwgbnVsbD59ICovXG4gICAgY29uc3QgcGFyYW1zID0ge31cbiAgICBjb25zdCBjb21wdXRlZFNjb3BlQXR0cmlidXRlcyA9IHJlc291cmNlQ29uZmlnLnNjb3BlQXR0cmlidXRlc1Jlc29sdmVyXG4gICAgICA/IGF3YWl0IHRoaXMucmVzb2x2ZUNvbXB1dGVkU2NvcGVBdHRyaWJ1dGVzKHtyZWNvcmQsIHJlc291cmNlQ29uZmlnfSlcbiAgICAgIDogbnVsbFxuXG4gICAgZm9yIChjb25zdCBzY29wZVBsYW5FbnRyeSBvZiByZXNvdXJjZUNvbmZpZy5zY29wZVBsYW4pIHtcbiAgICAgIC8qKiBAdHlwZSB7UmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT59ICovXG4gICAgICBsZXQgcmF3VmFsdWVcblxuICAgICAgaWYgKGNvbXB1dGVkU2NvcGVBdHRyaWJ1dGVzKSB7XG4gICAgICAgIHJhd1ZhbHVlID0gY29tcHV0ZWRTY29wZUF0dHJpYnV0ZXNbc2NvcGVQbGFuRW50cnkuc2NvcGVBdHRyaWJ1dGVdXG4gICAgICB9IGVsc2UgaWYgKHNjb3BlUGxhbkVudHJ5LnJlc29sdmVyKSB7XG4gICAgICAgIHJhd1ZhbHVlID0gYXdhaXQgc2NvcGVQbGFuRW50cnkucmVzb2x2ZXIocmVjb3JkKVxuICAgICAgfSBlbHNlIGlmIChzY29wZVBsYW5FbnRyeS5yZWNvcmRBdHRyaWJ1dGUpIHtcbiAgICAgICAgcmF3VmFsdWUgPSByZWNvcmQucmVhZEF0dHJpYnV0ZShzY29wZVBsYW5FbnRyeS5yZWNvcmRBdHRyaWJ1dGUpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByYXdWYWx1ZSA9IHNjYWxhck1vZGVsUHJpbWFyeUtleVZhbHVlKHJlY29yZC5pZCgpLCBgU3luYyBzY29wZSBwdWJsaXNoaW5nIGZvciAke3Jlc291cmNlQ29uZmlnLnJlc291cmNlVHlwZX1gKVxuICAgICAgfVxuXG4gICAgICBjb25zdCB2YWx1ZSA9IHJhd1ZhbHVlID09PSB1bmRlZmluZWQgfHwgcmF3VmFsdWUgPT09IG51bGwgPyBudWxsIDogU3RyaW5nKHJhd1ZhbHVlKVxuXG4gICAgICBjb2x1bW5zW3Njb3BlUGxhbkVudHJ5LmNvbHVtbk5hbWVdID0gdmFsdWVcbiAgICAgIHBhcmFtc1tzY29wZVBsYW5FbnRyeS5zY29wZUF0dHJpYnV0ZV0gPSB2YWx1ZVxuICAgIH1cblxuICAgIHJldHVybiB7Y29sdW1ucywgcGFyYW1zfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmVzIGFuZCB2YWxpZGF0ZXMgb25lIGNvbXB1dGVkIHNjb3BlLWF0dHJpYnV0ZXMgZGVjbGFyYXRpb24uIFRoZVxuICAgKiByZXNvbHZlciBydW5zIG9uY2UgcGVyIHB1Ymxpc2hlZCBtdXRhdGlvbiB3aXRoIHRoZSBleGFjdCBjb25uZWN0aW9uIHRoYXRcbiAgICogb3ducyB0aGF0IG11dGF0aW9uOyBldmVyeSBkZWNsYXJlZCBzY29wZSB2YWx1ZSBpcyB0aGVuIHJldXNlZCBmb3Igcm93XG4gICAqIHBlcnNpc3RlbmNlIGFuZCBicm9hZGNhc3Qgcm91dGluZyBzbyB0aG9zZSB0d28gaWRlbnRpdGllcyBjYW5ub3QgZHJpZnQuXG4gICAqIEBwYXJhbSB7e3JlY29yZDogUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4sIHJlc291cmNlQ29uZmlnOiBpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoZXJSZXNvdXJjZUNvbmZpZ319IGFyZ3MgLSBSZWNvcmQgYW5kIHJlc291cmNlIGNvbmZpZ3VyYXRpb24uXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IG51bWJlciB8IG51bGw+Pn0gQ29tcGxldGUgY29tcHV0ZWQgc2NvcGUgdmFsdWVzLlxuICAgKi9cbiAgYXN5bmMgcmVzb2x2ZUNvbXB1dGVkU2NvcGVBdHRyaWJ1dGVzKHtyZWNvcmQsIHJlc291cmNlQ29uZmlnfSkge1xuICAgIGNvbnN0IHJlc29sdmVyID0gcmVzb3VyY2VDb25maWcuc2NvcGVBdHRyaWJ1dGVzUmVzb2x2ZXJcblxuICAgIGlmICghcmVzb2x2ZXIpIHRocm93IG5ldyBFcnJvcihgTm8gY29tcHV0ZWQgc2NvcGUtYXR0cmlidXRlcyByZXNvbHZlciBjb25maWd1cmVkIGZvciAke3Jlc291cmNlQ29uZmlnLnJlc291cmNlVHlwZX1gKVxuXG4gICAgY29uc3QgcmVzb2x2ZWQgPSBhd2FpdCByZXNvbHZlcih7XG4gICAgICBjb25maWd1cmF0aW9uOiB0aGlzLmNvbmZpZy5jb25maWd1cmF0aW9uLFxuICAgICAgY29ubmVjdGlvbjogcmVjb3JkLmNvbm5lY3Rpb24oKSxcbiAgICAgIHJlY29yZFxuICAgIH0pXG5cbiAgICBpZiAoIWlzUGxhaW5PYmplY3QocmVzb2x2ZWQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7cmVzb3VyY2VDb25maWcucmVzb3VyY2VUeXBlfSBzdGF0aWMgc3luYyBwdWJsaXNoIHNjb3BlQXR0cmlidXRlcyByZXNvbHZlciBtdXN0IHJlc29sdmUgdG8gYSBwbGFpbiBvYmplY3RgKVxuICAgIH1cblxuICAgIGNvbnN0IGRlY2xhcmVkQXR0cmlidXRlcyA9IHJlc291cmNlQ29uZmlnLnNjb3BlUGxhbi5tYXAoKHtzY29wZUF0dHJpYnV0ZX0pID0+IHNjb3BlQXR0cmlidXRlKVxuXG4gICAgZm9yIChjb25zdCBzY29wZUF0dHJpYnV0ZSBvZiBPYmplY3Qua2V5cyhyZXNvbHZlZCkpIHtcbiAgICAgIGlmICghZGVjbGFyZWRBdHRyaWJ1dGVzLmluY2x1ZGVzKHNjb3BlQXR0cmlidXRlKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7cmVzb3VyY2VDb25maWcucmVzb3VyY2VUeXBlfSBzdGF0aWMgc3luYyBwdWJsaXNoIHNjb3BlQXR0cmlidXRlcyByZXNvbHZlciByZXR1cm5lZCB1bmtub3duIHNjb3BlIGF0dHJpYnV0ZTogJHtzY29wZUF0dHJpYnV0ZX0gKHRoZSBzeW5jIG1vZGVsIGRlY2xhcmVzOiAke2RlY2xhcmVkQXR0cmlidXRlcy5qb2luKFwiLCBcIil9KWApXG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBzY29wZUF0dHJpYnV0ZSBvZiBkZWNsYXJlZEF0dHJpYnV0ZXMpIHtcbiAgICAgIGlmICghT2JqZWN0Lmhhc093bihyZXNvbHZlZCwgc2NvcGVBdHRyaWJ1dGUpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtyZXNvdXJjZUNvbmZpZy5yZXNvdXJjZVR5cGV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggc2NvcGVBdHRyaWJ1dGVzIHJlc29sdmVyIG11c3QgcmVzb2x2ZSB0aGUgZGVjbGFyZWQgc2NvcGUgYXR0cmlidXRlICR7c2NvcGVBdHRyaWJ1dGV9YClcbiAgICAgIH1cblxuICAgICAgY29uc3QgdmFsdWUgPSByZXNvbHZlZFtzY29wZUF0dHJpYnV0ZV1cblxuICAgICAgaWYgKHZhbHVlICE9PSBudWxsICYmIHR5cGVvZiB2YWx1ZSAhPT0gXCJzdHJpbmdcIiAmJiB0eXBlb2YgdmFsdWUgIT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke3Jlc291cmNlQ29uZmlnLnJlc291cmNlVHlwZX0gc3RhdGljIHN5bmMgcHVibGlzaCBzY29wZSBhdHRyaWJ1dGUgJHtzY29wZUF0dHJpYnV0ZX0gbXVzdCBiZSBhIHN0cmluZywgbnVtYmVyLCBvciBudWxsYClcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCBudW1iZXIgfCBudWxsPn0gKi8gKHJlc29sdmVkKVxuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyB0aGUgZnJhbWV3b3JrIHN5bmMgY2hhbm5lbCBlbnRyeSBmb3Igb25lIHB1Ymxpc2hlZCBjaGFuZ2U6IHRoZVxuICAgKiBzbmFwc2hvdHRlZCBwYXlsb2FkIHBsdXMgdGhlIHBlcnNpc3RlZCBzeW5jIHJvdydzIHB1YmxpYyBleGFjdC1yb3cgbWV0YWRhdGFcbiAgICogKGlkLCBzZXJ2ZXIgc2VxdWVuY2UsIHVwZGF0ZWQtYXQsIGFuZCBkZWNsYXJlZCBzY29wZS1wYXJ0aXRpb24gYXR0cmlidXRlcykuXG4gICAqIFVzZXMgdGhlIHN5bmMgbW9kZWwncyBnZW5lcmF0ZWQgdHlwZWQgYWNjZXNzb3JzIGFuZCBmb2xsb3dzIHRoZVxuICAgKiBjaGFuZ2UtZmVlZCBzZXJpYWxpemVyJ3MgcHVibGljIGZpZWxkIGNvbnZlbnRpb24uXG4gICAqIEBwYXJhbSB7e2RhdGE6IFJlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+PiwgcmVzb3VyY2VDb25maWc6IGltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hlclJlc291cmNlQ29uZmlnLCByZXNvdXJjZUlkOiBzdHJpbmcsIHN5bmNSb3c6IFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+LCBzeW5jVHlwZTogc3RyaW5nfX0gYXJncyAtIFB1Ymxpc2ggYXJncy5cbiAgICogQHJldHVybnMge1JlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pn0gQnJvYWRjYXN0IHN5bmMgZW50cnkuXG4gICAqL1xuICBwdWJsaXNoZWRTeW5jRW50cnkoe2RhdGEsIHJlc291cmNlQ29uZmlnLCByZXNvdXJjZUlkLCBzeW5jUm93LCBzeW5jVHlwZX0pIHtcbiAgICAvKiogQHR5cGUge1JlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pn0gKi9cbiAgICBjb25zdCBlbnRyeSA9IHtcbiAgICAgIGRhdGEsXG4gICAgICBpZDogc3luY1Jvdy5pZCgpLFxuICAgICAgcmVzb3VyY2VJZCxcbiAgICAgIHJlc291cmNlVHlwZTogcmVzb3VyY2VDb25maWcucmVzb3VyY2VUeXBlLFxuICAgICAgc2VydmVyU2VxdWVuY2U6IHN5bmNSb3cuc2VydmVyU2VxdWVuY2UoKSxcbiAgICAgIHN5bmNUeXBlLFxuICAgICAgdXBkYXRlZEF0OiBpc29EYXRlKHN5bmNSb3cudXBkYXRlZEF0KCkpXG4gICAgfVxuXG4gICAgY29uc3Qgc2NvcGVBdHRyaWJ1dGVzID0gZGVjbGFyZWRTeW5jU2NvcGVBdHRyaWJ1dGVzKHRoaXMuY29uZmlnLnN5bmNNb2RlbClcblxuICAgIGZvciAoY29uc3Qgc2NvcGVBdHRyaWJ1dGUgb2Ygc2NvcGVBdHRyaWJ1dGVzIHx8IFtdKSB7XG4gICAgICBjb25zdCBzY29wZUFjY2Vzc29yID0gc3luY1Jvd1tzY29wZUF0dHJpYnV0ZV1cblxuICAgICAgaWYgKHR5cGVvZiBzY29wZUFjY2Vzc29yICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBQdWJsaXNoZWQgc3luYyByb3cgaXMgbWlzc2luZyB0aGUgZGVjbGFyZWQgc2NvcGUgYWNjZXNzb3IgJHtzY29wZUF0dHJpYnV0ZX0oKS5gKVxuICAgICAgfVxuXG4gICAgICBlbnRyeVtzY29wZUF0dHJpYnV0ZV0gPSBzY29wZUFjY2Vzc29yLmNhbGwoc3luY1JvdylcbiAgICB9XG5cbiAgICByZXR1cm4gZW50cnlcbiAgfVxuXG4gIC8qKlxuICAgKiBVcHNlcnRzIHRoZSBwdWJsaXNoZWQgc2VydmVyLW9yaWdpbiBzeW5jIHJvdyBmb3IgYSByZXNvdXJjZSBpZGVudGl0eTpcbiAgICogc2VydmVyLW9yaWdpbiByb3dzIGNhcnJ5IGEgbnVsbCBhY3RvciBjb2x1bW4gKG5vIGRldmljZSB0byBlY2hvIHRoZVxuICAgKiBjaGFuZ2UgYmFjayB0byksIHNvIHJlcGVhdGVkIHNlcnZlciBjaGFuZ2VzIHRvIG9uZSByZXNvdXJjZSByZXVzZSBhbmRcbiAgICogcmUtc2VxdWVuY2Ugb25lIGZlZWQgcm93LlxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pn0gYXR0cmlidXRlcyAtIFNuYXBzaG90dGVkIHN5bmMgcm93IGF0dHJpYnV0ZXMuXG4gICAqIEBwYXJhbSB7UmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT59IHN5bmNNb2RlbCAtIE9wZXJhdGlvbi1ib3VuZCBvciBzdGF0aWMgU3luYyBtb2RlbCBpbnRlcmZhY2UuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pn0gVXBzZXJ0ZWQgc3luYyByb3cuXG4gICAqL1xuICBhc3luYyB1cHNlcnRQdWJsaXNoZWRTeW5jUm93KGF0dHJpYnV0ZXMsIHN5bmNNb2RlbCA9IHRoaXMuY29uZmlnLnN5bmNNb2RlbCkge1xuICAgIGNvbnN0IGV4aXN0aW5nU3luYyA9IGF3YWl0IHN5bmNNb2RlbFxuICAgICAgLndoZXJlKHtcbiAgICAgICAgW3RoaXMuY29uZmlnLmFjdG9yRm9yZWlnbktleUNvbHVtbl06IG51bGwsXG4gICAgICAgIHJlc291cmNlX2lkOiBhdHRyaWJ1dGVzLnJlc291cmNlX2lkLFxuICAgICAgICByZXNvdXJjZV90eXBlOiBhdHRyaWJ1dGVzLnJlc291cmNlX3R5cGVcbiAgICAgIH0pXG4gICAgICAuZmlyc3QoKVxuXG4gICAgcmV0dXJuIGF3YWl0IHVwc2VydFN5bmNSb3coe2F0dHJpYnV0ZXMsIGV4aXN0aW5nU3luYywgc3luY01vZGVsfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBicm9hZGNhc3RlciBkZWxpdmVyaW5nIGRlY2xhcmVkIGJyb2FkY2FzdHM6IHRoZSBpbmplY3RlZCBvbmUsXG4gICAqIG9yIHRoZSBjb25maWd1cmF0aW9uJ3MgY2hhbm5lbCBicm9hZGNhc3QgYXdhaXRlZCB0aHJvdWdoIHRoZSBwZW5kaW5nXG4gICAqIGJyb2FkY2FzdCBxdWV1ZS5cbiAgICogQHJldHVybnMge05vbk51bGxhYmxlPGltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hlck9wdGlvbnNbXCJicm9hZGNhc3RlclwiXT59IEJyb2FkY2FzdCBkZWxpdmVyZXIuXG4gICAqL1xuICBicm9hZGNhc3RlcigpIHtcbiAgICBpZiAodGhpcy5jb25maWcuYnJvYWRjYXN0ZXIpIHJldHVybiB0aGlzLmNvbmZpZy5icm9hZGNhc3RlclxuXG4gICAgcmV0dXJuIGFzeW5jICh7Ym9keSwgY2hhbm5lbCwgcGFyYW1zfSkgPT4ge1xuICAgICAgdGhpcy5jb25maWcuY29uZmlndXJhdGlvbi5icm9hZGNhc3RUb0NoYW5uZWwoY2hhbm5lbCwgcGFyYW1zLCBib2R5KVxuICAgICAgYXdhaXQgdGhpcy5jb25maWcuY29uZmlndXJhdGlvbi5hd2FpdFBlbmRpbmdCcm9hZGNhc3RzKClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVwb3J0cyBhIHBvc3QtY29tbWl0IHB1Ymxpc2ggZmFpbHVyZS4gVGhlIHRyYW5zYWN0aW9uIGhhcyBhbHJlYWR5XG4gICAqIGNvbW1pdHRlZCB3aGVuIGFmdGVyQ29tbWl0IGNhbGxiYWNrcyBydW4sIHNvIHJldGhyb3dpbmcgaGVyZSB3b3VsZCBwb2lzb25cbiAgICogdGhlIGRyaXZlcidzIGF3YWl0ZWQgYWZ0ZXJDb21taXQgY2hhaW4gKGJyZWFraW5nIHVucmVsYXRlZCBjYWxsYmFja3MpIC1cbiAgICogaW5zdGVhZCB0aGUgZmFpbHVyZSBnb2VzIHRvIHRoZSBjb25maWd1cmVkIG9uRXJyb3IgaG9vaywgb3IgaXMgZW1pdHRlZCBvblxuICAgKiB0aGUgY29uZmlndXJhdGlvbidzIGZyYW1ld29yay1lcnJvci9hbGwtZXJyb3IgY2hhbm5lbHMgKHNvIHByb2R1Y3Rpb24gYnVnXG4gICAqIHJlcG9ydGluZyB2aWEgYGNvbmZpZ3VyYXRpb24uZ2V0RXJyb3JFdmVudHMoKWAgc2VlcyBhIGJyb2tlbiBwdWJsaXNoXG4gICAqIHBhdGgpIGFuZCBsb2dnZWQgbG91ZGx5IHRocm91Z2ggdGhlIHB1Ymxpc2hlcidzIGxvZ2dlciB3aGVuIG5vbmUgaXNcbiAgICogY29uZmlndXJlZC5cbiAgICogQHBhcmFtIHtFcnJvcn0gZXJyb3IgLSBQb3N0LWNvbW1pdCBwdWJsaXNoIGZhaWx1cmUuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgcmVwb3J0QWZ0ZXJDb21taXRFcnJvcihlcnJvcikge1xuICAgIGlmICh0aGlzLmNvbmZpZy5vbkVycm9yKSB7XG4gICAgICB0aGlzLmNvbmZpZy5vbkVycm9yKGVycm9yKVxuXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBjb25zdCBlcnJvckV2ZW50cyA9IHRoaXMuY29uZmlnLmNvbmZpZ3VyYXRpb24uZ2V0RXJyb3JFdmVudHMoKVxuICAgIGNvbnN0IHBheWxvYWQgPSB7Y29udGV4dDoge3N0YWdlOiBcInN5bmMtcHVibGlzaC1hZnRlci1jb21taXRcIn0sIGVycm9yfVxuXG4gICAgZXJyb3JFdmVudHMuZW1pdChcImZyYW1ld29yay1lcnJvclwiLCBwYXlsb2FkKVxuICAgIGVycm9yRXZlbnRzLmVtaXQoXCJhbGwtZXJyb3JcIiwgey4uLnBheWxvYWQsIGVycm9yVHlwZTogXCJmcmFtZXdvcmstZXJyb3JcIn0pXG5cbiAgICBhd2FpdCB0aGlzLmxvZ2dlcigpLmVycm9yKFwiU3luY1B1Ymxpc2hlciBmYWlsZWQgdG8gcHVibGlzaCBhIHNlcnZlci1zaWRlIHN5bmMgY2hhbmdlIGFmdGVyIGNvbW1pdFwiLCBlcnJvcilcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBsYXppbHkgYnVpbHQgcHVibGlzaGVyIGxvZ2dlci5cbiAgICogQHJldHVybnMge0xvZ2dlcn0gUHVibGlzaGVyIGxvZ2dlci5cbiAgICovXG4gIGxvZ2dlcigpIHtcbiAgICB0aGlzLl9sb2dnZXIgfHw9IG5ldyBMb2dnZXIoXCJTeW5jUHVibGlzaGVyXCIsIHtjb25maWd1cmF0aW9uOiB0aGlzLmNvbmZpZy5jb25maWd1cmF0aW9ufSlcblxuICAgIHJldHVybiB0aGlzLl9sb2dnZXJcbiAgfVxufVxuXG4vKipcbiAqIFJlc29sdmVzIGEgbW9kZWwgY2xhc3MncyBhY3RpdmUgcHVibGlzaCBkZWNsYXJhdGlvbiBmcm9tIGBzdGF0aWMgc3luY2AuXG4gKiBPcHRlZC1vdXQgKGBwdWJsaXNoOiBmYWxzZWApIGFuZCB1bmRlY2xhcmVkIG1vZGVscyByZXNvbHZlIHRvIG51bGw7IGV2ZXJ5XG4gKiBvdGhlciBkZWNsYXJlZCB2YWx1ZSBmbG93cyBpbnRvIGxvdWQgZGVjbGFyYXRpb24gdmFsaWRhdGlvbi5cbiAqIEBwYXJhbSB7UmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT59IG1vZGVsQ2xhc3MgLSBSZWdpc3RlcmVkIG1vZGVsIGNsYXNzLlxuICogQHJldHVybnMge2ltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hEZWNsYXJhdGlvbiB8IG51bGx9IEFjdGl2ZSBwdWJsaXNoIGRlY2xhcmF0aW9uLCBvciBudWxsLlxuICovXG5mdW5jdGlvbiBwdWJsaXNoRGVjbGFyYXRpb25Gb3IobW9kZWxDbGFzcykge1xuICBjb25zdCBkZWNsYXJhdGlvbiA9IG1vZGVsQ2xhc3Muc3luY1xuXG4gIGlmICghZGVjbGFyYXRpb24gfHwgdHlwZW9mIGRlY2xhcmF0aW9uICE9PSBcIm9iamVjdFwiIHx8IGRlY2xhcmF0aW9uLnB1Ymxpc2ggPT09IHVuZGVmaW5lZCB8fCBkZWNsYXJhdGlvbi5wdWJsaXNoID09PSBmYWxzZSkgcmV0dXJuIG51bGxcblxuICByZXR1cm4gZGVjbGFyYXRpb24ucHVibGlzaFxufVxuXG4vKipcbiAqIEJ1aWxkcyBvbmUgcHVibGlzaGVkIHJlc291cmNlIGNvbmZpZyBmcm9tIGEgbW9kZWwncyBgc3RhdGljIHN5bmNgIHB1Ymxpc2hcbiAqIGRlY2xhcmF0aW9uLiBgcHVibGlzaDogdHJ1ZWAgb3B0cyBpbiB3aXRoIGFsbCBkZWZhdWx0cyAoYXR0cmlidXRlIHBheWxvYWQsXG4gKiBkZXJpdmVkIHNjb3BlIHBhcnRpdGlvbiwgY3JlYXRlZC91cGRhdGVkIG9wZXJhdGlvbnMpLlxuICogQHBhcmFtIHt7bW9kZWxDbGFzczogUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4sIHB1Ymxpc2g6IGltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hEZWNsYXJhdGlvbiB8IG51bGwsIHNjb3BlQXR0cmlidXRlczogc3RyaW5nW10gfCBudWxsLCBzeW5jTW9kZWw6IFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+fX0gYXJncyAtIERlY2xhcmF0aW9uIGFyZ3MgcGx1cyB0aGUgc3luYyBtb2RlbCdzIGRlY2xhcmVkIHNjb3BlIGF0dHJpYnV0ZXMuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaGVyUmVzb3VyY2VDb25maWd9IERlcml2ZWQgcmVzb3VyY2UgY29uZmlnLlxuICovXG5mdW5jdGlvbiByZXNvdXJjZUNvbmZpZ0Zyb21QdWJsaXNoRGVjbGFyYXRpb24oe21vZGVsQ2xhc3MsIHB1Ymxpc2gsIHNjb3BlQXR0cmlidXRlczogc3luY1Njb3BlQXR0cmlidXRlcywgc3luY01vZGVsfSkge1xuICBjb25zdCBtb2RlbE5hbWUgPSBtb2RlbENsYXNzLmdldE1vZGVsTmFtZSgpXG4gIGNvbnN0IG5vcm1hbGl6ZWRQdWJsaXNoID0gcHVibGlzaCA9PT0gdHJ1ZSA/IHt9IDogcHVibGlzaFxuXG4gIGlmICghbm9ybWFsaXplZFB1Ymxpc2ggfHwgdHlwZW9mIG5vcm1hbGl6ZWRQdWJsaXNoICE9PSBcIm9iamVjdFwiIHx8IEFycmF5LmlzQXJyYXkobm9ybWFsaXplZFB1Ymxpc2gpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGAke21vZGVsTmFtZX0gc3RhdGljIHN5bmMgcHVibGlzaCBtdXN0IGJlIHRydWUsIGZhbHNlIG9yIGEgcHVibGlzaCBkZWNsYXJhdGlvbiBvYmplY3QsIGdvdDogJHtTdHJpbmcocHVibGlzaCl9YClcbiAgfVxuXG4gIGNvbnN0IHticm9hZGNhc3RzLCBldmVudElkLCBvcGVyYXRpb25zLCByZXNvdXJjZVR5cGUsIHNjb3BlQXR0cmlidXRlcywgc2VyaWFsaXplLCAuLi5yZXN0RGVjbGFyYXRpb259ID0gbm9ybWFsaXplZFB1Ymxpc2hcbiAgY29uc3QgdW5rbm93bktleXMgPSBPYmplY3Qua2V5cyhyZXN0RGVjbGFyYXRpb24pXG5cbiAgaWYgKHVua25vd25LZXlzLmxlbmd0aCA+IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bW9kZWxOYW1lfSBzdGF0aWMgc3luYyBwdWJsaXNoIHJlY2VpdmVkIHVua25vd24ga2V5czogJHt1bmtub3duS2V5cy5qb2luKFwiLCBcIil9IChzdXBwb3J0ZWQ6IGJyb2FkY2FzdHMsIGV2ZW50SWQgKGRlcHJlY2F0ZWQpLCBvcGVyYXRpb25zLCByZXNvdXJjZVR5cGUsIHNjb3BlQXR0cmlidXRlcywgc2VyaWFsaXplKWApXG4gIH1cbiAgaWYgKHNlcmlhbGl6ZSAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBzZXJpYWxpemUgIT09IFwiZnVuY3Rpb25cIikge1xuICAgIHRocm93IG5ldyBFcnJvcihgJHttb2RlbE5hbWV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggc2VyaWFsaXplIG11c3QgYmUgYSBmdW5jdGlvbiBidWlsZGluZyB0aGUgcHVibGlzaGVkIHBheWxvYWQsIGdvdDogJHtTdHJpbmcoc2VyaWFsaXplKX1gKVxuICB9XG4gIGlmIChvcGVyYXRpb25zICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkob3BlcmF0aW9ucykgfHwgb3BlcmF0aW9ucy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHttb2RlbE5hbWV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggb3BlcmF0aW9ucyBtdXN0IGJlIGEgbm9uLWVtcHR5IGFycmF5IG9mIGNyZWF0ZS91cGRhdGUvZGVzdHJveWApXG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBvcGVyYXRpb24gb2Ygb3BlcmF0aW9ucykge1xuICAgICAgaWYgKCEob3BlcmF0aW9uIGluIFBVQkxJU0hFRF9DQUxMQkFDS19OQU1FUykpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke21vZGVsTmFtZX0gc3RhdGljIHN5bmMgcHVibGlzaCBvcGVyYXRpb25zIG11c3QgYmUgY3JlYXRlL3VwZGF0ZS9kZXN0cm95LCBnb3Q6ICR7U3RyaW5nKG9wZXJhdGlvbil9YClcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjb25zdCBzY29wZVBsYW4gPSBzY29wZVBsYW5Gb3Ioe2V2ZW50SWQsIG1vZGVsQ2xhc3MsIG1vZGVsTmFtZSwgc2NvcGVBdHRyaWJ1dGVzLCBzeW5jTW9kZWwsIHN5bmNTY29wZUF0dHJpYnV0ZXN9KVxuXG4gIHJldHVybiB7XG4gICAgYnJvYWRjYXN0cyxcbiAgICBtb2RlbENsYXNzLFxuICAgIG9wZXJhdGlvbnM6IG9wZXJhdGlvbnMgPT09IHVuZGVmaW5lZCA/IERFRkFVTFRfUFVCTElTSEVEX09QRVJBVElPTlMgOiBvcGVyYXRpb25zLFxuICAgIHJlc291cmNlVHlwZTogcmVzb3VyY2VUeXBlID09PSB1bmRlZmluZWQgPyBtb2RlbE5hbWUgOiByZXNvdXJjZVR5cGUsXG4gICAgc2NvcGVBdHRyaWJ1dGVzUmVzb2x2ZXI6IHR5cGVvZiBzY29wZUF0dHJpYnV0ZXMgPT09IFwiZnVuY3Rpb25cIiA/IHNjb3BlQXR0cmlidXRlcyA6IHVuZGVmaW5lZCxcbiAgICBzY29wZVBsYW4sXG4gICAgc2VyaWFsaXplOiBzZXJpYWxpemUgPT09IHVuZGVmaW5lZCA/IGRlZmF1bHRTZXJpYWxpemVkQXR0cmlidXRlcyA6IHNlcmlhbGl6ZVxuICB9XG59XG5cbi8qKlxuICogRGVyaXZlcyB0aGUgc2NvcGUgcGxhbiBwYXJ0aXRpb25pbmcgYSBwdWJsaXNoZWQgbW9kZWwncyBjaGFuZ2VzOiBvbmUgZW50cnlcbiAqIHBlciBzY29wZSBhdHRyaWJ1dGUgZGVjbGFyZWQgb24gdGhlIHN5bmMgbW9kZWwgKGBzdGF0aWNcbiAqIHN5bmNTY29wZUF0dHJpYnV0ZXNgKSwgZWFjaCByZWFkaW5nIHRoZSByZWNvcmQgYXR0cmlidXRlIG5hbWVkIGxpa2UgdGhlXG4gKiBzY29wZSBhdHRyaWJ1dGUgKG92ZXJyaWRhYmxlIHRocm91Z2ggdGhlIGRlY2xhcmF0aW9uJ3MgYHNjb3BlQXR0cmlidXRlc2BcbiAqIG5hbWUgbWFwKSwgb3IgdGhlIHJlY29yZCdzIG93biBpZCB3aGVuIHRoZSBtb2RlbCBoYXMgbm8gc3VjaCBhdHRyaWJ1dGVcbiAqIChzY29wZS1yb290IG1vZGVscykuIFRoZSBkZXByZWNhdGVkIGBldmVudElkYCBkZWNsYXJhdGlvbiBmb3JtcyBtYXAgdG8gYVxuICogZml4ZWQgYGV2ZW50SWRgL2BldmVudF9pZGAgcGxhbiBmb3IgMS4wLjUwMyBjb21wYXRpYmlsaXR5LlxuICogQHBhcmFtIHt7ZXZlbnRJZDogaW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaERlY2xhcmF0aW9uQ29uZmlnW1wiZXZlbnRJZFwiXSwgbW9kZWxDbGFzczogUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4sIG1vZGVsTmFtZTogc3RyaW5nLCBzY29wZUF0dHJpYnV0ZXM6IGltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hEZWNsYXJhdGlvbkNvbmZpZ1tcInNjb3BlQXR0cmlidXRlc1wiXSwgc3luY01vZGVsOiBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPiwgc3luY1Njb3BlQXR0cmlidXRlczogc3RyaW5nW10gfCBudWxsfX0gYXJncyAtIERlY2xhcmF0aW9uIGFuZCBzeW5jLW1vZGVsIHNjb3BlIGFyZ3MuXG4gKiBAcmV0dXJucyB7QXJyYXk8aW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaGVyU2NvcGVQbGFuRW50cnk+fSBEZXJpdmVkIHNjb3BlIHBsYW4uXG4gKi9cbmZ1bmN0aW9uIHNjb3BlUGxhbkZvcih7ZXZlbnRJZCwgbW9kZWxDbGFzcywgbW9kZWxOYW1lLCBzY29wZUF0dHJpYnV0ZXMsIHN5bmNNb2RlbCwgc3luY1Njb3BlQXR0cmlidXRlc30pIHtcbiAgY29uc3QgYXR0cmlidXRlTmFtZXMgPSBPYmplY3QudmFsdWVzKG1vZGVsQ2xhc3MuZ2V0Q29sdW1uTmFtZVRvQXR0cmlidXRlTmFtZU1hcCgpKVxuXG4gIGlmIChldmVudElkICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAoc2NvcGVBdHRyaWJ1dGVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHttb2RlbE5hbWV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggY2FuJ3QgZGVjbGFyZSBib3RoIHNjb3BlQXR0cmlidXRlcyBhbmQgdGhlIGRlcHJlY2F0ZWQgZXZlbnRJZCBmb3JtYClcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBldmVudElkID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIHJldHVybiBbe2NvbHVtbk5hbWU6IFwiZXZlbnRfaWRcIiwgcmVjb3JkQXR0cmlidXRlOiBudWxsLCByZXNvbHZlcjogZXZlbnRJZCwgc2NvcGVBdHRyaWJ1dGU6IFwiZXZlbnRJZFwifV1cbiAgICB9XG4gICAgaWYgKHR5cGVvZiBldmVudElkICE9PSBcInN0cmluZ1wiKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bW9kZWxOYW1lfSBzdGF0aWMgc3luYyBwdWJsaXNoIGV2ZW50SWQgbXVzdCBiZSBhbiBhdHRyaWJ1dGUtbmFtZSBzdHJpbmcgKG9yIGEgZGVwcmVjYXRlZCByZXNvbHZlciBmdW5jdGlvbiksIGdvdDogJHtTdHJpbmcoZXZlbnRJZCl9YClcbiAgICB9XG4gICAgaWYgKCFhdHRyaWJ1dGVOYW1lcy5pbmNsdWRlcyhldmVudElkKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGAke21vZGVsTmFtZX0gc3RhdGljIHN5bmMgcHVibGlzaCBldmVudElkIGF0dHJpYnV0ZSBkb2Vzbid0IGV4aXN0IG9uIHRoZSBtb2RlbDogJHtldmVudElkfWApXG4gICAgfVxuXG4gICAgcmV0dXJuIFt7Y29sdW1uTmFtZTogXCJldmVudF9pZFwiLCByZWNvcmRBdHRyaWJ1dGU6IGV2ZW50SWQsIHJlc29sdmVyOiB1bmRlZmluZWQsIHNjb3BlQXR0cmlidXRlOiBcImV2ZW50SWRcIn1dXG4gIH1cblxuICBpZiAoc2NvcGVBdHRyaWJ1dGVzICE9PSB1bmRlZmluZWQgJiYgIXN5bmNTY29wZUF0dHJpYnV0ZXMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bW9kZWxOYW1lfSBzdGF0aWMgc3luYyBwdWJsaXNoIGRlY2xhcmVzIHNjb3BlQXR0cmlidXRlcyBidXQgdGhlIHN5bmMgbW9kZWwgZGVjbGFyZXMgbm8gc3RhdGljIHN5bmNTY29wZUF0dHJpYnV0ZXNgKVxuICB9XG5cbiAgaWYgKCFzeW5jU2NvcGVBdHRyaWJ1dGVzKSByZXR1cm4gW11cblxuICBpZiAodHlwZW9mIHNjb3BlQXR0cmlidXRlcyA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgcmV0dXJuIHN5bmNTY29wZUF0dHJpYnV0ZXMubWFwKChzY29wZUF0dHJpYnV0ZSkgPT4gKHtcbiAgICAgIGNvbHVtbk5hbWU6IHN5bmNTY29wZUNvbHVtbk5hbWUoe3Njb3BlQXR0cmlidXRlLCBzeW5jTW9kZWx9KSxcbiAgICAgIHJlY29yZEF0dHJpYnV0ZTogbnVsbCxcbiAgICAgIHJlc29sdmVyOiB1bmRlZmluZWQsXG4gICAgICBzY29wZUF0dHJpYnV0ZVxuICAgIH0pKVxuICB9XG5cbiAgaWYgKHNjb3BlQXR0cmlidXRlcyAhPT0gdW5kZWZpbmVkICYmICh0eXBlb2Ygc2NvcGVBdHRyaWJ1dGVzICE9PSBcIm9iamVjdFwiIHx8IEFycmF5LmlzQXJyYXkoc2NvcGVBdHRyaWJ1dGVzKSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bW9kZWxOYW1lfSBzdGF0aWMgc3luYyBwdWJsaXNoIHNjb3BlQXR0cmlidXRlcyBtdXN0IGJlIGFuIG9iamVjdCBtYXBwaW5nIHNjb3BlIGF0dHJpYnV0ZXMgdG8gcmVjb3JkIGF0dHJpYnV0ZSBuYW1lcywgZ290OiAke1N0cmluZyhzY29wZUF0dHJpYnV0ZXMpfWApXG4gIH1cblxuICBmb3IgKGNvbnN0IHNjb3BlQXR0cmlidXRlIG9mIE9iamVjdC5rZXlzKHNjb3BlQXR0cmlidXRlcyB8fCB7fSkpIHtcbiAgICBpZiAoIXN5bmNTY29wZUF0dHJpYnV0ZXMuaW5jbHVkZXMoc2NvcGVBdHRyaWJ1dGUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bW9kZWxOYW1lfSBzdGF0aWMgc3luYyBwdWJsaXNoIHNjb3BlQXR0cmlidXRlcyByZWNlaXZlZCB1bmtub3duIHNjb3BlIGF0dHJpYnV0ZTogJHtzY29wZUF0dHJpYnV0ZX0gKHRoZSBzeW5jIG1vZGVsIGRlY2xhcmVzOiAke3N5bmNTY29wZUF0dHJpYnV0ZXMuam9pbihcIiwgXCIpfSlgKVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBzeW5jU2NvcGVBdHRyaWJ1dGVzLm1hcCgoc2NvcGVBdHRyaWJ1dGUpID0+IHtcbiAgICBjb25zdCBkZWNsYXJlZFJlY29yZEF0dHJpYnV0ZSA9IHNjb3BlQXR0cmlidXRlcz8uW3Njb3BlQXR0cmlidXRlXVxuXG4gICAgaWYgKGRlY2xhcmVkUmVjb3JkQXR0cmlidXRlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmICh0eXBlb2YgZGVjbGFyZWRSZWNvcmRBdHRyaWJ1dGUgIT09IFwic3RyaW5nXCIgfHwgIWF0dHJpYnV0ZU5hbWVzLmluY2x1ZGVzKGRlY2xhcmVkUmVjb3JkQXR0cmlidXRlKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bW9kZWxOYW1lfSBzdGF0aWMgc3luYyBwdWJsaXNoIHNjb3BlQXR0cmlidXRlcy4ke3Njb3BlQXR0cmlidXRlfSBtdXN0IG5hbWUgYW4gZXhpc3RpbmcgcmVjb3JkIGF0dHJpYnV0ZSwgZ290OiAke1N0cmluZyhkZWNsYXJlZFJlY29yZEF0dHJpYnV0ZSl9YClcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtjb2x1bW5OYW1lOiBzeW5jU2NvcGVDb2x1bW5OYW1lKHtzY29wZUF0dHJpYnV0ZSwgc3luY01vZGVsfSksIHJlY29yZEF0dHJpYnV0ZTogZGVjbGFyZWRSZWNvcmRBdHRyaWJ1dGUsIHJlc29sdmVyOiB1bmRlZmluZWQsIHNjb3BlQXR0cmlidXRlfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBjb2x1bW5OYW1lOiBzeW5jU2NvcGVDb2x1bW5OYW1lKHtzY29wZUF0dHJpYnV0ZSwgc3luY01vZGVsfSksXG4gICAgICByZWNvcmRBdHRyaWJ1dGU6IGF0dHJpYnV0ZU5hbWVzLmluY2x1ZGVzKHNjb3BlQXR0cmlidXRlKSA/IHNjb3BlQXR0cmlidXRlIDogbnVsbCxcbiAgICAgIHJlc29sdmVyOiB1bmRlZmluZWQsXG4gICAgICBzY29wZUF0dHJpYnV0ZVxuICAgIH1cbiAgfSlcbn1cblxuLyoqXG4gKiBDaGVja3MgdGhhdCBhIGNvbXB1dGVkIGRlY2xhcmF0aW9uIHJldHVybmVkIGFuIG9yZGluYXJ5IGtleS92YWx1ZSBvYmplY3QuXG4gKiBAcGFyYW0ge3Vua25vd259IHZhbHVlIC0gUmVzb2x2ZXIgcmVzdWx0LlxuICogQHJldHVybnMge3ZhbHVlIGlzIFJlY29yZDxzdHJpbmcsIHVua25vd24+fSBXaGV0aGVyIHRoZSB2YWx1ZSBpcyBhIHBsYWluIG9iamVjdC5cbiAqL1xuZnVuY3Rpb24gaXNQbGFpbk9iamVjdCh2YWx1ZSkge1xuICBpZiAoIXZhbHVlIHx8IHR5cGVvZiB2YWx1ZSAhPT0gXCJvYmplY3RcIiB8fCBBcnJheS5pc0FycmF5KHZhbHVlKSkgcmV0dXJuIGZhbHNlXG5cbiAgY29uc3QgcHJvdG90eXBlID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKVxuXG4gIHJldHVybiBwcm90b3R5cGUgPT09IE9iamVjdC5wcm90b3R5cGUgfHwgcHJvdG90eXBlID09PSBudWxsXG59XG5cbi8qKlxuICogUmVzb2x2ZXMgdGhlIHN5bmMtcm93IGNvbHVtbiBwZXJzaXN0aW5nIGEgZGVjbGFyZWQgc2NvcGUgYXR0cmlidXRlLlxuICogQHBhcmFtIHt7c2NvcGVBdHRyaWJ1dGU6IHN0cmluZywgc3luY01vZGVsOiBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPn19IGFyZ3MgLSBTY29wZSBhdHRyaWJ1dGUgYW5kIHN5bmMgbW9kZWwuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBTeW5jLXJvdyBjb2x1bW4gbmFtZS5cbiAqL1xuZnVuY3Rpb24gc3luY1Njb3BlQ29sdW1uTmFtZSh7c2NvcGVBdHRyaWJ1dGUsIHN5bmNNb2RlbH0pIHtcbiAgY29uc3QgY29sdW1uTmFtZSA9IHN5bmNNb2RlbC5nZXRBdHRyaWJ1dGVOYW1lVG9Db2x1bW5OYW1lTWFwKClbc2NvcGVBdHRyaWJ1dGVdXG5cbiAgaWYgKCFjb2x1bW5OYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGAke3N5bmNNb2RlbC5uYW1lfSBkZWNsYXJlcyB0aGUgc3luYyBzY29wZSBhdHRyaWJ1dGUgJHtzY29wZUF0dHJpYnV0ZX0gYnV0IGhhcyBubyBtYXRjaGluZyBjb2x1bW4gZm9yIGl0YClcbiAgfVxuXG4gIHJldHVybiBjb2x1bW5OYW1lXG59XG5cbi8qKlxuICogRGVmYXVsdCBwdWJsaXNoIHNlcmlhbGl6ZXI6IHRoZSByZWNvcmQncyBhdHRyaWJ1dGVzIHdpdGggRGF0ZSB2YWx1ZXNcbiAqIHNlcmlhbGl6ZWQgdG8gSVNPIHN0cmluZ3MuXG4gKiBAcGFyYW0ge1JldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+fSByZWNvcmQgLSBNdXRhdGVkIHNlcnZlciBtb2RlbCByZWNvcmQuXG4gKiBAcmV0dXJucyB7UmVjb3JkPHN0cmluZywgUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4+fSBTZXJpYWxpemVkIGF0dHJpYnV0ZXMgcGF5bG9hZC5cbiAqL1xuZnVuY3Rpb24gZGVmYXVsdFNlcmlhbGl6ZWRBdHRyaWJ1dGVzKHJlY29yZCkge1xuICAvKiogQHR5cGUge1JlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pn0gKi9cbiAgY29uc3QgYXR0cmlidXRlcyA9IHsuLi5yZWNvcmQuYXR0cmlidXRlcygpfVxuXG4gIGZvciAoY29uc3QgW2F0dHJpYnV0ZU5hbWUsIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhhdHRyaWJ1dGVzKSkge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERhdGUpIGF0dHJpYnV0ZXNbYXR0cmlidXRlTmFtZV0gPSB2YWx1ZS50b0lTT1N0cmluZygpXG4gIH1cblxuICByZXR1cm4gYXR0cmlidXRlc1xufVxuXG4vKipcbiAqIENvbnZlcnRzIGEgZGF0ZS1saWtlIHZhbHVlIHRvIGFuIElTTyBzdHJpbmcsIG1hdGNoaW5nIHRoZSBjaGFuZ2UtZmVlZFxuICogc2VyaWFsaXplcidzIGNvbnZlbnRpb24gZm9yIHRoZSBzeW5jIGVudHJ5J3MgcHVibGljIHVwZGF0ZWQtYXQgbWV0YWRhdGEuXG4gKiBAcGFyYW0ge0RhdGUgfCBudWxsfSB2YWx1ZSAtIFBlcnNpc3RlZCB1cGRhdGVkLWF0IHZhbHVlLlxuICogQHJldHVybnMge3N0cmluZ30gSVNPIGRhdGUuXG4gKiBAdGhyb3dzIHtFcnJvcn0gV2hlbiB0aGUgcGVyc2lzdGVkIHJvdyBoYXMgbm8gdmFsaWQgdXBkYXRlZC1hdCB0aW1lc3RhbXAuXG4gKi9cbmZ1bmN0aW9uIGlzb0RhdGUodmFsdWUpIHtcbiAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBEYXRlKSB8fCBOdW1iZXIuaXNOYU4odmFsdWUuZ2V0VGltZSgpKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIlB1Ymxpc2hlZCBzeW5jIHJvdyBtdXN0IGhhdmUgYSB2YWxpZCB1cGRhdGVkQXQgdGltZXN0YW1wLlwiKVxuICB9XG5cbiAgcmV0dXJuIHZhbHVlLnRvSVNPU3RyaW5nKClcbn1cbiJdfQ==
|
|
608
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1wdWJsaXNoZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc3luYy9zeW5jLXB1Ymxpc2hlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxhQUFhLE1BQU0scUJBQXFCLENBQUE7QUFDL0MsT0FBTyxNQUFNLE1BQU0sY0FBYyxDQUFBO0FBQ2pDLE9BQU8sRUFBQywwQkFBMEIsRUFBQyxNQUFNLCtCQUErQixDQUFBO0FBQ3hFLE9BQU8sYUFBYSxNQUFNLDZCQUE2QixDQUFBO0FBQ3ZELE9BQU8sU0FBUyxNQUFNLHdCQUF3QixDQUFBO0FBQzlDLE9BQU8sbUJBQW1CLE1BQU0seUJBQXlCLENBQUE7QUFFekQsT0FBTyxFQUFDLDJCQUEyQixFQUFDLE1BQU0sNEJBQTRCLENBQUE7QUFDdEUsT0FBTyxFQUFDLHlCQUF5QixFQUFFLGFBQWEsRUFBQyxNQUFNLHlCQUF5QixDQUFBO0FBQ2hGLE9BQU8sRUFBQyxzQkFBc0IsRUFBQyxNQUFNLCtCQUErQixDQUFBO0FBQ3BFLE9BQU8sRUFBQyxzQkFBc0IsRUFBQyxNQUFNLHdCQUF3QixDQUFBO0FBRTdELHNGQUFzRjtBQUN0RixNQUFNLHdCQUF3QixHQUFHLEVBQUMsTUFBTSxFQUFFLGFBQWEsRUFBRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sRUFBRSxhQUFhLEVBQUMsQ0FBQTtBQUV4Rzs7Ozs7O29EQU1vRDtBQUNwRCxNQUFNLDRCQUE0QixHQUFHLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFBO0FBRXpELG9EQUFvRDtBQUNwRCxNQUFNLGdDQUFnQyxHQUFHLElBQUksT0FBTyxFQUFFLENBQUE7QUFFdEQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBNkJHO0FBQ0gsTUFBTSxDQUFDLE9BQU8sT0FBTyxhQUFhO0lBQ2hDOzs7Ozs7OztPQVFHO0lBQ0gsWUFBWSxPQUFPLEdBQUcsRUFBRTtRQUN0QixNQUFNLEVBQUMs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NERBQTREO0lBQzVELE1BQU0sVUFBVSxHQUFHLEVBQUMsR0FBRyxNQUFNLENBQUMsVUFBVSxFQUFFLEVBQUMsQ0FBQTtJQUUzQyxLQUFLLE1BQU0sQ0FBQyxhQUFhLEVBQUUsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1FBQ2hFLElBQUksS0FBSyxZQUFZLElBQUk7WUFBRSxVQUFVLENBQUMsYUFBYSxDQUFDLEdBQUcsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFBO0lBQzVFLENBQUM7SUFFRCxPQUFPLFVBQVUsQ0FBQTtBQUNuQixDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsU0FBUyxPQUFPLENBQUMsS0FBSztJQUNwQixJQUFJLENBQUMsQ0FBQyxLQUFLLFlBQVksSUFBSSxDQUFDLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDO1FBQzlELE1BQU0sSUFBSSxLQUFLLENBQUMsMkRBQTJELENBQUMsQ0FBQTtJQUM5RSxDQUFDO0lBRUQsT0FBTyxLQUFLLENBQUMsV0FBVyxFQUFFLENBQUE7QUFDNUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgQ29uZmlndXJhdGlvbiBmcm9tIFwiLi4vY29uZmlndXJhdGlvbi5qc1wiXG5pbXBvcnQgTG9nZ2VyIGZyb20gXCIuLi9sb2dnZXIuanNcIlxuaW1wb3J0IHtzY2FsYXJNb2RlbFByaW1hcnlLZXlWYWx1ZX0gZnJvbSBcIi4uL3V0aWxzL21vZGVsLXByaW1hcnkta2V5LmpzXCJcbmltcG9ydCByZXN0QXJnc0Vycm9yIGZyb20gXCIuLi91dGlscy9yZXN0LWFyZ3MtZXJyb3IuanNcIlxuaW1wb3J0IHNoYTI1NkhleCBmcm9tIFwiLi4vdXRpbHMvc2hhMjU2LWhleC5qc1wiXG5pbXBvcnQgc3RhYmxlSnNvblN0cmluZ2lmeSBmcm9tIFwiLi4vdXRpbHMvc3RhYmxlLWpzb24uanNcIlxuXG5pbXBvcnQge2RlY2xhcmVkU3luY1Njb3BlQXR0cmlidXRlc30gZnJvbSBcIi4vc3luYy1zY29wZS1hdHRyaWJ1dGVzLmpzXCJcbmltcG9ydCB7ZGVsaXZlckRlY2xhcmVkQnJvYWRjYXN0cywgdXBzZXJ0U3luY1Jvd30gZnJvbSBcIi4vc3luYy1jaGFuZ2UtZmFub3V0LmpzXCJcbmltcG9ydCB7aXNQdWJsaXNoaW5nU3VwcHJlc3NlZH0gZnJvbSBcIi4vc3luYy1wdWJsaXNoLXN1cHByZXNzaW9uLmpzXCJcbmltcG9ydCB7VkVMT0NJT1VTX1NZTkNfQ0hBTk5FTH0gZnJvbSBcIi4vc3luYy1jaGFubmVsLW5hbWUuanNcIlxuXG4vKiogQHR5cGUge3tjcmVhdGU6IFwiYWZ0ZXJDcmVhdGVcIiwgdXBkYXRlOiBcImFmdGVyVXBkYXRlXCIsIGRlc3Ryb3k6IFwiYWZ0ZXJEZXN0cm95XCJ9fSAqL1xuY29uc3QgUFVCTElTSEVEX0NBTExCQUNLX05BTUVTID0ge2NyZWF0ZTogXCJhZnRlckNyZWF0ZVwiLCBkZXN0cm95OiBcImFmdGVyRGVzdHJveVwiLCB1cGRhdGU6IFwiYWZ0ZXJVcGRhdGVcIn1cblxuLyoqXG4gKiBPcGVyYXRpb25zIHB1Ymxpc2hlZCBieSBkZWZhdWx0IGZvciBtb2RlbHMgZGVjbGFyaW5nIGBzdGF0aWMgc3luY2AgcHVibGlzaFxuICogd2l0aG91dCBhbiBgb3BlcmF0aW9uc2Aga2V5OiBzZXJ2ZXItc2lkZSBjcmVhdGVzIGFuZCB1cGRhdGVzIHB1Ymxpc2hcbiAqIGF1dG9tYXRpY2FsbHkuIERlc3Ryb3lzIGFyZSBub3QgcHVibGlzaGVkIGJ5IGRlZmF1bHQgYmVjYXVzZSBhIHNlcnZlclxuICogZGVzdHJveSBpcyBvZnRlbiBjbGVhbnVwIHJhdGhlciB0aGFuIGEgc3luY2VkIGRlbGV0ZTsgb3B0IGluIHdpdGggYW5cbiAqIG9wZXJhdGlvbnMgbGlzdC5cbiAqIEB0eXBlIHtBcnJheTxcImNyZWF0ZVwiIHwgXCJ1cGRhdGVcIiB8IFwiZGVzdHJveVwiPn0gKi9cbmNvbnN0IERFRkFVTFRfUFVCTElTSEVEX09QRVJBVElPTlMgPSBbXCJjcmVhdGVcIiwgXCJ1cGRhdGVcIl1cblxuLyoqIEB0eXBlIHtXZWFrTWFwPENvbmZpZ3VyYXRpb24sIFN5bmNQdWJsaXNoZXI+fSAqL1xuY29uc3Qgc3RhcnRlZFB1Ymxpc2hlcnNCeUNvbmZpZ3VyYXRpb24gPSBuZXcgV2Vha01hcCgpXG5cbi8qKlxuICogRGVjbGFyYXRpdmUgc2VydmVyLXNpZGUgc3luYyBwdWJsaXNoZXIg4oCUIHRoZSBzZXJ2ZXIgbWlycm9yIG9mIHRoZSBjbGllbnQnc1xuICogdHJhY2stYnktZGVmYXVsdCBtdXRhdGlvbiB0cmFja2luZy5cbiAqXG4gKiBTZXJ2ZXIgbW9kZWxzIGRlY2xhcmUgd2hhdCB0byBwdWJsaXNoIHRocm91Z2ggYHN0YXRpYyBzeW5jYCdzIGBwdWJsaXNoYFxuICoga2V5LCBhbmQgVmVsb2Npb3VzIHdyaXRlcyBldmVyeSBjb21taXR0ZWQgc2VydmVyLXNpZGUgY2hhbmdlIHRvIHRoZSBzeW5jXG4gKiBjaGFuZ2UgZmVlZCAobW9kZWwtYmFja2VkIFN5bmMtcm93IHVwc2VydCB3aXRoIHNlcnZlciByZS1zZXF1ZW5jaW5nKSBhbmRcbiAqIGJyb2FkY2FzdHMgdGhlIHN0YW5kYXJkIHN5bmMgZW52ZWxvcGUgKGB7ZWNob09yaWdpbiwgc3luY3M6IFsuLi5dfWApIG9uIHRoZVxuICogZnJhbWV3b3JrIHN5bmMgY2hhbm5lbCAoe0BsaW5rIFZFTE9DSU9VU19TWU5DX0NIQU5ORUx9KSBzY29wZWQgYnkgdGhlXG4gKiBjaGFuZ2UncyBkZXJpdmVkIHNjb3BlLXBhcnRpdGlvbiB2YWx1ZXMsIHNvIGRldmljZXMgcmVjZWl2ZSBzZXJ2ZXItb3JpZ2luXG4gKiBjaGFuZ2VzIHdpdGhvdXQgYXBwIGNvZGUgZGVjbGFyaW5nIGNoYW5uZWxzIG9yIGNhbGxpbmcgbWFudWFsXG4gKiB1cHNlcnQvYnJvYWRjYXN0IGhlbHBlcnM6XG4gKlxuICogICAgIHN0YXRpYyBzeW5jID0ge3B1Ymxpc2g6IHRydWV9IC8vIGRlZmF1bHQgcGF5bG9hZCAoYXR0cmlidXRlcykgKyBkZWZhdWx0IHNjb3BlIHBhcnRpdGlvblxuICogICAgIHN0YXRpYyBzeW5jID0ge3B1Ymxpc2g6IHtzZXJpYWxpemU6IChyZWNvcmQpID0+ICh7aWQ6IHJlY29yZC5pZCgpLCBwaW46IHJlY29yZC5waW4oKX0pfX1cbiAqXG4gKiBUaGUgc2NvcGUgcGFydGl0aW9uIGNvbWVzIGZyb20gdGhlIHN5bmMgbW9kZWwncyBgc3RhdGljXG4gKiBzeW5jU2NvcGVBdHRyaWJ1dGVzYCBkZWNsYXJhdGlvbiAoZm9yIGV4YW1wbGUgYFtcImV2ZW50SWRcIl1gIG9yXG4gKiBgW1wiYWNjb3VudElkXCJdYCDigJQgVmVsb2Npb3VzIGhhcyBubyBidWlsdC1pbiBwYXJ0aXRpb24gbmFtZSk6IGVhY2ggZGVjbGFyZWRcbiAqIHNjb3BlIGF0dHJpYnV0ZSByZWFkcyB0aGUgcmVjb3JkJ3MgYXR0cmlidXRlIG9mIHRoZSBzYW1lIG5hbWUgd2hlbiB0aGVcbiAqIG1vZGVsIGhhcyBvbmUsIGVsc2UgdGhlIHJlY29yZCdzIG93biBpZCAoc2NvcGUtcm9vdCBtb2RlbHMpLCBvdmVycmlkYWJsZVxuICogcGVyIG1vZGVsIHRocm91Z2ggYHB1Ymxpc2g6IHtzY29wZUF0dHJpYnV0ZXM6IHthY2NvdW50SWQ6IFwib3duZXJJZFwifX1gLlxuICogVGhlIHByZS1mcmFtZXdvcmstY2hhbm5lbCBgYnJvYWRjYXN0c2AgbGlzdCBhbmQgdGhlIGBldmVudElkYFxuICogc3RyaW5nL3Jlc29sdmVyLWZ1bmN0aW9uIGRlY2xhcmF0aW9uIGZvcm1zIGtlZXAgd29ya2luZyBidXQgYXJlIGRlcHJlY2F0ZWQuXG4gKlxuICogUmVwbGF5ZWQgZGV2aWNlIG11dGF0aW9ucyBuZXZlciBkb3VibGUtcHVibGlzaDogdGhlIGZyYW1ld29yaydzIHJvdXRlZFxuICogcmVwbGF5IGFwcGx5IG1hcmtzIGl0cyB3cml0dGVuIHJlY29yZHMgdGhyb3VnaCBgbWFya1NlcnZlckFwcGx5KHJlY29yZClgXG4gKiAoc2VlIHN5bmMtcHVibGlzaC1zdXBwcmVzc2lvbi5qcyksIGFuZCBhcHAgY29kZSBhcHBseWluZyBhbHJlYWR5LXN5bmNlZFxuICogZGF0YSBjYW4gdXNlIGBtYXJrU2VydmVyQXBwbHlgL2B3aXRob3V0UHVibGlzaGluZ2AgdGhlIHNhbWUgd2F5LlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTeW5jUHVibGlzaGVyIHtcbiAgLyoqXG4gICAqIEJ1aWxkcyB0aGUgc3luYyBwdWJsaXNoZXIgYnkgZGVyaXZpbmcgcHVibGlzaGVkIHJlc291cmNlcyBmcm9tIHRoZVxuICAgKiBjb25maWd1cmF0aW9uJ3MgcmVnaXN0ZXJlZCBtb2RlbHM6IGV2ZXJ5IG1vZGVsIGRlY2xhcmluZyBgc3RhdGljIHN5bmNgXG4gICAqIHdpdGggYSBgcHVibGlzaGAgZGVjbGFyYXRpb24gYmVjb21lcyBhIHB1Ymxpc2hlZCByZXNvdXJjZVxuICAgKiAoYHB1Ymxpc2g6IGZhbHNlYCBvcHRzIG91dCkuIFRoZSBzeW5jL2NoYW5nZSBtb2RlbCBpcyB0aGUgcmVnaXN0ZXJlZFxuICAgKiBcIlN5bmNcIiBtb2RlbCBhbmQgYnJvYWRjYXN0cyBkZWZhdWx0IHRvIHRoZSBjb25maWd1cmF0aW9uJ3MgY2hhbm5lbFxuICAgKiBicm9hZGNhc3QuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaGVyT3B0aW9uc30gW29wdGlvbnNdIC0gT3B0aW9uYWwgb3ZlcnJpZGVzLlxuICAgKi9cbiAgY29uc3RydWN0b3Iob3B0aW9ucyA9IHt9KSB7XG4gICAgY29uc3Qge2FjdG9yRm9yZWlnbktleUNvbHVtbiA9IFwiYXV0aGVudGljYXRpb25fdG9rZW5faWRcIiwgYnJvYWRjYXN0ZXIsIGNvbmZpZ3VyYXRpb24gPSBDb25maWd1cmF0aW9uLmN1cnJlbnQoKSwgb25FcnJvciwgc3luY01vZGVsLCAuLi5yZXN0T3B0aW9uc30gPSBvcHRpb25zXG5cbiAgICByZXN0QXJnc0Vycm9yKHJlc3RPcHRpb25zKVxuXG4gICAgY29uc3QgbW9kZWxDbGFzc2VzID0gY29uZmlndXJhdGlvbi5nZXRNb2RlbENsYXNzZXMoKVxuICAgIGNvbnN0IHB1Ymxpc2hpbmdNb2RlbENsYXNzZXMgPSBPYmplY3QudmFsdWVzKG1vZGVsQ2xhc3NlcykuZmlsdGVyKChtb2RlbENsYXNzKSA9PiBwdWJsaXNoRGVjbGFyYXRpb25Gb3IobW9kZWxDbGFzcykpXG5cbiAgICBpZiAocHVibGlzaGluZ01vZGVsQ2xhc3Nlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlN5bmNQdWJsaXNoZXIgZm91bmQgbm8gcmVnaXN0ZXJlZCBtb2RlbHMgZGVjbGFyaW5nIHN0YXRpYyBzeW5jIHB1Ymxpc2ggLSBkZWNsYXJlIGBzdGF0aWMgc3luYyA9IHtwdWJsaXNoOiB7c2VyaWFsaXplfX1gIG9uIHRoZSBtb2RlbHMgd2hvc2Ugc2VydmVyLXNpZGUgY2hhbmdlcyBzaG91bGQgcHVibGlzaCB0byB0aGUgc3luYyBmZWVkXCIpXG4gICAgfVxuXG4gICAgY29uc3QgcmVzb2x2ZWRTeW5jTW9kZWwgPSBzeW5jTW9kZWwgfHwgbW9kZWxDbGFzc2VzLlN5bmNcblxuICAgIGlmICghcmVzb2x2ZWRTeW5jTW9kZWwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlN5bmNQdWJsaXNoZXIgcmVxdWlyZXMgYSByZWdpc3RlcmVkIFxcXCJTeW5jXFxcIiBtb2RlbCBmb3IgcHVibGlzaGVkIHN5bmMgY2hhbmdlIHJvd3MgKG9yIHBhc3Mgb3B0aW9ucy5zeW5jTW9kZWwpXCIpXG4gICAgfVxuXG4gICAgY29uc3Qgc2NvcGVBdHRyaWJ1dGVzID0gZGVjbGFyZWRTeW5jU2NvcGVBdHRyaWJ1dGVzKHJlc29sdmVkU3luY01vZGVsKVxuICAgIC8qKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgaW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaGVyUmVzb3VyY2VDb25maWc+fSAqL1xuICAgIGNvbnN0IHJlc291cmNlcyA9IHt9XG5cbiAgICBmb3IgKGNvbnN0IG1vZGVsQ2xhc3Mgb2YgcHVibGlzaGluZ01vZGVsQ2xhc3Nlcykge1xuICAgICAgY29uc3QgcHVibGlzaCA9IHB1Ymxpc2hEZWNsYXJhdGlvbkZvcihtb2RlbENsYXNzKVxuICAgICAgY29uc3QgcmVzb3VyY2VDb25maWcgPSByZXNvdXJjZUNvbmZpZ0Zyb21QdWJsaXNoRGVjbGFyYXRpb24oe21vZGVsQ2xhc3MsIHB1Ymxpc2gsIHNjb3BlQXR0cmlidXRlcywgc3luY01vZGVsOiByZXNvbHZlZFN5bmNNb2RlbH0pXG5cbiAgICAgIHJlc291cmNlc1tyZXNvdXJjZUNvbmZpZy5yZXNvdXJjZVR5cGVdID0gcmVzb3VyY2VDb25maWdcbiAgICB9XG5cbiAgICAvKiogQHR5cGUge3thY3RvckZvcmVpZ25LZXlDb2x1bW46IHN0cmluZywgYnJvYWRjYXN0ZXI6IGltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hlck9wdGlvbnNbXCJicm9hZGNhc3RlclwiXSwgY29uZmlndXJhdGlvbjogQ29uZmlndXJhdGlvbiwgb25FcnJvcjogaW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaGVyT3B0aW9uc1tcIm9uRXJyb3JcIl0sIHJlc291cmNlczogUmVjb3JkPHN0cmluZywgaW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaGVyUmVzb3VyY2VDb25maWc+LCBzeW5jTW9kZWw6IFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+fX0gKi9cbiAgICB0aGlzLmNvbmZpZyA9IHthY3RvckZvcmVpZ25LZXlDb2x1bW4sIGJyb2FkY2FzdGVyLCBjb25maWd1cmF0aW9uLCBvbkVycm9yLCByZXNvdXJjZXMsIHN5bmNNb2RlbDogcmVzb2x2ZWRTeW5jTW9kZWx9XG4gICAgLyoqIEB0eXBlIHtBcnJheTx7Y2FsbGJhY2s6IChyZWNvcmQ6IFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+KSA9PiBQcm9taXNlPHZvaWQ+LCBjYWxsYmFja05hbWU6IFwiYWZ0ZXJDcmVhdGVcIiB8IFwiYWZ0ZXJVcGRhdGVcIiB8IFwiYWZ0ZXJEZXN0cm95XCIsIG1vZGVsQ2xhc3M6IFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+fT59ICovXG4gICAgdGhpcy5fcHVibGlzaGVkQ2FsbGJhY2tzID0gW11cbiAgICAvKiogQHR5cGUge0xvZ2dlciB8IG51bGx9ICovXG4gICAgdGhpcy5fbG9nZ2VyID0gbnVsbFxuICAgIHRoaXMuX3N0YXJ0ZWQgPSBmYWxzZVxuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyBhIHN5bmMgcHVibGlzaGVyIGRlcml2ZWQgZnJvbSB0aGUgZ2l2ZW4gY29uZmlndXJhdGlvbi4gQWxpYXMgZm9yXG4gICAqIGBuZXcgU3luY1B1Ymxpc2hlcih7Y29uZmlndXJhdGlvbiwgLi4ub3B0aW9uc30pYC5cbiAgICogQHBhcmFtIHtDb25maWd1cmF0aW9ufSBbY29uZmlndXJhdGlvbl0gLSBDb25maWd1cmF0aW9uIG93bmluZyB0aGUgcmVnaXN0ZXJlZCBtb2RlbHMuIERlZmF1bHRzIHRvIHRoZSBjdXJyZW50IGNvbmZpZ3VyYXRpb24uXG4gICAqIEBwYXJhbSB7T21pdDxpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoZXJPcHRpb25zLCBcImNvbmZpZ3VyYXRpb25cIj59IFtvcHRpb25zXSAtIE9wdGlvbmFsIG92ZXJyaWRlcy5cbiAgICogQHJldHVybnMge1N5bmNQdWJsaXNoZXJ9IFN5bmMgcHVibGlzaGVyIGRlcml2ZWQgZnJvbSB0aGUgY29uZmlndXJhdGlvbi5cbiAgICovXG4gIHN0YXRpYyBmcm9tQ29uZmlndXJhdGlvbihjb25maWd1cmF0aW9uID0gQ29uZmlndXJhdGlvbi5jdXJyZW50KCksIG9wdGlvbnMgPSB7fSkge1xuICAgIHJldHVybiBuZXcgU3luY1B1Ymxpc2hlcih7Li4ub3B0aW9ucywgY29uZmlndXJhdGlvbn0pXG4gIH1cblxuICAvKipcbiAgICogU3RhcnRzIChhbmQgbWVtb2l6ZXMgcGVyIGNvbmZpZ3VyYXRpb24pIHRoZSBzeW5jIHB1Ymxpc2hlciBmb3IgYSBzZXJ2ZXJcbiAgICogYm9vdDogbm8tb3Agd2hlbiBubyByZWdpc3RlcmVkIG1vZGVsIGRlY2xhcmVzIGEgcHVibGlzaCBjb25maWcsIGd1YXJkZWQgc29cbiAgICogcmVwZWF0ZWQgYm9vdHMgd2l0aCB0aGUgc2FtZSBjb25maWd1cmF0aW9uIHJlZ2lzdGVyIHRoZSBwdWJsaXNoIGNhbGxiYWNrc1xuICAgKiBvbmx5IG9uY2UuXG4gICAqIEBwYXJhbSB7Q29uZmlndXJhdGlvbn0gY29uZmlndXJhdGlvbiAtIENvbmZpZ3VyYXRpb24gb3duaW5nIHRoZSByZWdpc3RlcmVkIG1vZGVscy5cbiAgICogQHJldHVybnMge1Byb21pc2U8U3luY1B1Ymxpc2hlciB8IG51bGw+fSBTdGFydGVkIHB1Ymxpc2hlciwgb3IgbnVsbCB3aGVuIG5vIG1vZGVscyBkZWNsYXJlIHB1Ymxpc2guXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgc3RhcnRGcm9tQ29uZmlndXJhdGlvbihjb25maWd1cmF0aW9uKSB7XG4gICAgY29uc3Qgc3RhcnRlZFB1Ymxpc2hlciA9IHN0YXJ0ZWRQdWJsaXNoZXJzQnlDb25maWd1cmF0aW9uLmdldChjb25maWd1cmF0aW9uKVxuXG4gICAgaWYgKHN0YXJ0ZWRQdWJsaXNoZXIpIHJldHVybiBzdGFydGVkUHVibGlzaGVyXG5cbiAgICBpZiAoIU9iamVjdC52YWx1ZXMoY29uZmlndXJhdGlvbi5nZXRNb2RlbENsYXNzZXMoKSkuc29tZSgobW9kZWxDbGFzcykgPT4gcHVibGlzaERlY2xhcmF0aW9uRm9yKG1vZGVsQ2xhc3MpKSkgcmV0dXJuIG51bGxcblxuICAgIGNvbnN0IHB1Ymxpc2hlciA9IG5ldyBTeW5jUHVibGlzaGVyKHtjb25maWd1cmF0aW9ufSlcblxuICAgIHN0YXJ0ZWRQdWJsaXNoZXJzQnlDb25maWd1cmF0aW9uLnNldChjb25maWd1cmF0aW9uLCBwdWJsaXNoZXIpXG4gICAgYXdhaXQgcHVibGlzaGVyLnN0YXJ0KClcblxuICAgIHJldHVybiBwdWJsaXNoZXJcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgdGhlIHB1Ymxpc2ggY2FsbGJhY2tzIGZvciBldmVyeSBwdWJsaXNoZWQgcmVzb3VyY2U6IHNlcnZlci1zaWRlXG4gICAqIGNyZWF0ZXMgYW5kIHVwZGF0ZXMgKGRlc3Ryb3lzIHdoZW4gb3B0ZWQgaW4pIHVwc2VydCBhIHN5bmMgY2hhbmdlIHJvdyBhbmRcbiAgICogZmFuIG91dCB0aGUgZGVjbGFyZWQgYnJvYWRjYXN0cyBvbmNlIHRoZWlyIHRyYW5zYWN0aW9uIGNvbW1pdHMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgc3RhcnQoKSB7XG4gICAgaWYgKHRoaXMuX3N0YXJ0ZWQpIHJldHVyblxuXG4gICAgdGhpcy5fc3RhcnRlZCA9IHRydWVcblxuICAgIGZvciAoY29uc3QgcmVzb3VyY2VDb25maWcgb2YgT2JqZWN0LnZhbHVlcyh0aGlzLmNvbmZpZy5yZXNvdXJjZXMpKSB7XG4gICAgICBmb3IgKGNvbnN0IG9wZXJhdGlvbiBvZiByZXNvdXJjZUNvbmZpZy5vcGVyYXRpb25zKSB7XG4gICAgICAgIGNvbnN0IGNhbGxiYWNrTmFtZSA9IFBVQkxJU0hFRF9DQUxMQkFDS19OQU1FU1tvcGVyYXRpb25dXG4gICAgICAgIGNvbnN0IGNhbGxiYWNrID0gdGhpcy5wdWJsaXNoZWRNdXRhdGlvbkNhbGxiYWNrKHtvcGVyYXRpb24sIHJlc291cmNlQ29uZmlnfSlcblxuICAgICAgICByZXNvdXJjZUNvbmZpZy5tb2RlbENsYXNzW2NhbGxiYWNrTmFtZV0oY2FsbGJhY2spXG4gICAgICAgIHRoaXMuX3B1Ymxpc2hlZENhbGxiYWNrcy5wdXNoKHtjYWxsYmFjaywgY2FsbGJhY2tOYW1lLCBtb2RlbENsYXNzOiByZXNvdXJjZUNvbmZpZy5tb2RlbENsYXNzfSlcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVW5yZWdpc3RlcnMgYWxsIHB1Ymxpc2ggY2FsbGJhY2tzICh0ZXN0cywgc2h1dGRvd24pLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIHN0b3AoKSB7XG4gICAgZm9yIChjb25zdCB7Y2FsbGJhY2ssIGNhbGxiYWNrTmFtZSwgbW9kZWxDbGFzc30gb2YgdGhpcy5fcHVibGlzaGVkQ2FsbGJhY2tzKSB7XG4gICAgICBtb2RlbENsYXNzLnVucmVnaXN0ZXJMaWZlY3ljbGVDYWxsYmFjayhjYWxsYmFja05hbWUsIGNhbGxiYWNrKVxuICAgIH1cblxuICAgIHRoaXMuX3B1Ymxpc2hlZENhbGxiYWNrcyA9IFtdXG4gICAgdGhpcy5fc3RhcnRlZCA9IGZhbHNlXG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIHRoZSBsaWZlY3ljbGUgY2FsbGJhY2sgcHVibGlzaGluZyBvbmUgc2VydmVyLXNpZGUgbXV0YXRpb24uIFRoZVxuICAgKiBwdWJsaXNoZWQgcGF5bG9hZCAoZGVjbGFyYXRpb24gYHNlcmlhbGl6ZWApLCBldmVudCBzY29wZSwgYW5kIHN5bmMgdHlwZVxuICAgKiBhcmUgc25hcHNob3R0ZWQgYXQgbXV0YXRpb24tY2FsbGJhY2sgdGltZSwgc28gYWZ0ZXJTYXZlIGhvb2tzIGFzc2lnbmluZ1xuICAgKiB1bnNhdmVkIGF0dHJpYnV0ZXMgKG9yIGFueSBsYXRlciBkcmlmdCBvbiB0aGUgcmVjb3JkKSBjYW5ub3QgY2hhbmdlIHdoYXRcbiAgICogZ2V0cyBwdWJsaXNoZWQgdnMgd2hhdCB3YXMgY29tbWl0dGVkLiBQZXJzaXN0aW5nIGFuZCBicm9hZGNhc3RpbmcgYXJlXG4gICAqIGRlZmVycmVkIHRocm91Z2ggdGhlIG1vZGVsIGNvbm5lY3Rpb24ncyBhZnRlckNvbW1pdCBob29rIHNvIHRoZXkgb25seSBydW5cbiAgICogb25jZSB0aGUgbXV0YXRpb24ncyB0cmFuc2FjdGlvbiBoYXMgY29tbWl0dGVkIChpbW1lZGlhdGVseSB3aGVuIG5vXG4gICAqIHRyYW5zYWN0aW9uIGlzIG9wZW4pIC0gcm9sbGVkLWJhY2sgbXV0YXRpb25zIG5ldmVyIHB1Ymxpc2guIFBvc3QtY29tbWl0XG4gICAqIHB1Ymxpc2ggZmFpbHVyZXMgYXJlIHJlcG9ydGVkIHdpdGhvdXQgcmV0aHJvd2luZyBpbnRvIHRoZSBkcml2ZXInc1xuICAgKiBhZnRlckNvbW1pdCBjaGFpbiAoc2VlIHJlcG9ydEFmdGVyQ29tbWl0RXJyb3IpLlxuICAgKiBAcGFyYW0ge3tvcGVyYXRpb246IFwiY3JlYXRlXCIgfCBcInVwZGF0ZVwiIHwgXCJkZXN0cm95XCIsIHJlc291cmNlQ29uZmlnOiBpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoZXJSZXNvdXJjZUNvbmZpZ319IGFyZ3MgLSBPcGVyYXRpb24gYW5kIHJlc291cmNlIGNvbmZpZy5cbiAgICogQHJldHVybnMgeyhyZWNvcmQ6IFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+KSA9PiBQcm9taXNlPHZvaWQ+fSBMaWZlY3ljbGUgY2FsbGJhY2suXG4gICAqL1xuICBwdWJsaXNoZWRNdXRhdGlvbkNhbGxiYWNrKHtvcGVyYXRpb24sIHJlc291cmNlQ29uZmlnfSkge1xuICAgIHJldHVybiBhc3luYyAocmVjb3JkKSA9PiB7XG4gICAgICBpZiAoaXNQdWJsaXNoaW5nU3VwcHJlc3NlZChyZWNvcmQpKSByZXR1cm5cblxuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IHJlc291cmNlQ29uZmlnLnNlcmlhbGl6ZShyZWNvcmQpXG4gICAgICBjb25zdCByZXNvdXJjZUlkID0gU3RyaW5nKHNjYWxhck1vZGVsUHJpbWFyeUtleVZhbHVlKHJlY29yZC5pZCgpLCBgU3luYyBwdWJsaXNoaW5nIGZvciAke3Jlc291cmNlQ29uZmlnLnJlc291cmNlVHlwZX1gKSlcbiAgICAgIGNvbnN0IHN5bmNUeXBlID0gb3BlcmF0aW9uID09PSBcImRlc3Ryb3lcIiA/IFwiZGVsZXRlXCIgOiBcInVwZGF0ZVwiXG4gICAgICBjb25zdCBzY29wZVZhbHVlcyA9IGF3YWl0IHRoaXMucHVibGlzaGVkU2NvcGVWYWx1ZXMoe3JlY29yZCwgcmVzb3VyY2VDb25maWd9KVxuICAgICAgLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj59ICovXG4gICAgICBjb25zdCBhdHRyaWJ1dGVzID0ge1xuICAgICAgICBbdGhpcy5jb25maWcuYWN0b3JGb3JlaWduS2V5Q29sdW1uXTogbnVsbCxcbiAgICAgICAgY2xpZW50X3VwZGF0ZWRfYXQ6IG5ldyBEYXRlKCksXG4gICAgICAgIGRhdGE6IEpTT04uc3RyaW5naWZ5KGRhdGEpLFxuICAgICAgICByZXNvdXJjZV9pZDogcmVzb3VyY2VJZCxcbiAgICAgICAgcmVzb3VyY2VfdHlwZTogcmVzb3VyY2VDb25maWcucmVzb3VyY2VUeXBlLFxuICAgICAgICBzeW5jX3R5cGU6IHN5bmNUeXBlLFxuICAgICAgICAuLi5zY29wZVZhbHVlcy5jb2x1bW5zXG4gICAgICB9XG4gICAgICBjb25zdCBkYXRhYmFzZU9wZXJhdGlvbiA9IHJlY29yZC5kYXRhYmFzZU9wZXJhdGlvbigpXG4gICAgICBjb25zdCBvcGVyYXRpb25TY29wZSA9IGRhdGFiYXNlT3BlcmF0aW9uXG4gICAgICAgID8gZGF0YWJhc2VPcGVyYXRpb24uZm9yTW9kZWwodGhpcy5jb25maWcuc3luY01vZGVsKVxuICAgICAgICA6IHRoaXMuY29uZmlnLnN5bmNNb2RlbFxuXG4gICAgICBhd2FpdCByZWNvcmQuY29ubmVjdGlvbigpLmFmdGVyQ29tbWl0KGFzeW5jICgpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBzY29wZUNvbHVtbk5hbWVzID0gcmVzb3VyY2VDb25maWcuc2NvcGVQbGFuLm1hcCgoe2NvbHVtbk5hbWV9KSA9PiBjb2x1bW5OYW1lKVxuICAgICAgICAgIGNvbnN0IHN5bmNSb3cgPSBhd2FpdCB0aGlzLnVwc2VydFB1Ymxpc2hlZFN5bmNSb3coYXR0cmlidXRlcywgb3BlcmF0aW9uU2NvcGUsIHNjb3BlQ29sdW1uTmFtZXMpXG5cbiAgICAgICAgICBhd2FpdCB0aGlzLmJyb2FkY2FzdGVyKCkoe1xuICAgICAgICAgICAgYm9keToge1xuICAgICAgICAgICAgICBlY2hvT3JpZ2luOiBudWxsLFxuICAgICAgICAgICAgICBzeW5jczogW3RoaXMucHVibGlzaGVkU3luY0VudHJ5KHtkYXRhLCByZXNvdXJjZUNvbmZpZywgcmVzb3VyY2VJZCwgc3luY1Jvdywgc3luY1R5cGV9KV1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjaGFubmVsOiBWRUxPQ0lPVVNfU1lOQ19DSEFOTkVMLFxuICAgICAgICAgICAgcGFyYW1zOiB7Li4uc2NvcGVWYWx1ZXMucGFyYW1zLCByZXNvdXJjZVR5cGU6IHJlc291cmNlQ29uZmlnLnJlc291cmNlVHlwZX1cbiAgICAgICAgICB9KVxuXG4gICAgICAgICAgaWYgKHJlc291cmNlQ29uZmlnLmJyb2FkY2FzdHMpIHtcbiAgICAgICAgICAgIGF3YWl0IGRlbGl2ZXJEZWNsYXJlZEJyb2FkY2FzdHMoe1xuICAgICAgICAgICAgICBhcmdzOiB7ZGF0YSwgb3BlcmF0aW9uLCByZWNvcmQsIHJlc291cmNlSWQsIHJlc291cmNlVHlwZTogcmVzb3VyY2VDb25maWcucmVzb3VyY2VUeXBlLCBzeW5jUm93LCBzeW5jVHlwZX0sXG4gICAgICAgICAgICAgIGJyb2FkY2FzdGVyOiB0aGlzLmJyb2FkY2FzdGVyKCksXG4gICAgICAgICAgICAgIGJyb2FkY2FzdHM6IHJlc291cmNlQ29uZmlnLmJyb2FkY2FzdHNcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIGF3YWl0IHRoaXMucmVwb3J0QWZ0ZXJDb21taXRFcnJvcigvKiogQHR5cGUge0Vycm9yfSAqLyAoZXJyb3IpKVxuICAgICAgICB9XG4gICAgICB9KVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNvbHZlcyB0aGUgc2NvcGUtcGFydGl0aW9uIHZhbHVlcyBmb3Igb25lIHB1Ymxpc2hlZCBtdXRhdGlvbiBmcm9tIHRoZVxuICAgKiByZXNvdXJjZSdzIGRlcml2ZWQgc2NvcGUgcGxhbjogZWFjaCBlbnRyeSByZWFkcyBpdHMgcmVjb3JkIGF0dHJpYnV0ZSAob3JcbiAgICogdGhlIHJlY29yZCdzIG93biBpZCBmb3Igc2NvcGUtcm9vdCBtb2RlbHMsIG9yIHRoZSBkZXByZWNhdGVkIHJlc29sdmVyXG4gICAqIGZ1bmN0aW9uKS4gVGhlIHZhbHVlcyBhcmUgcGVyc2lzdGVkIG9udG8gdGhlIHN5bmMgcm93J3MgcGFydGl0aW9uIGNvbHVtbnNcbiAgICogYW5kIGJyb2FkY2FzdCBhcyB0aGUgZnJhbWV3b3JrIHN5bmMgY2hhbm5lbCdzIHNjb3BpbmcgcGFyYW1zLlxuICAgKiBAcGFyYW0ge3tyZWNvcmQ6IFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+LCByZXNvdXJjZUNvbmZpZzogaW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaGVyUmVzb3VyY2VDb25maWd9fSBhcmdzIC0gTXV0YXRlZCByZWNvcmQgYW5kIHJlc291cmNlIGNvbmZpZy5cbiAgICogQHJldHVybnMge1Byb21pc2U8e2NvbHVtbnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IG51bGw+LCBwYXJhbXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IG51bGw+fT59IFNjb3BlIHZhbHVlcyBrZXllZCBieSBzeW5jLXJvdyBjb2x1bW4gYW5kIGJ5IHNjb3BlIGF0dHJpYnV0ZS5cbiAgICovXG4gIGFzeW5jIHB1Ymxpc2hlZFNjb3BlVmFsdWVzKHtyZWNvcmQsIHJlc291cmNlQ29uZmlnfSkge1xuICAgIC8qKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgc3RyaW5nIHwgbnVsbD59ICovXG4gICAgY29uc3QgY29sdW1ucyA9IHt9XG4gICAgLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCBudWxsPn0gKi9cbiAgICBjb25zdCBwYXJhbXMgPSB7fVxuICAgIGNvbnN0IGNvbXB1dGVkU2NvcGVBdHRyaWJ1dGVzID0gcmVzb3VyY2VDb25maWcuc2NvcGVBdHRyaWJ1dGVzUmVzb2x2ZXJcbiAgICAgID8gYXdhaXQgdGhpcy5yZXNvbHZlQ29tcHV0ZWRTY29wZUF0dHJpYnV0ZXMoe3JlY29yZCwgcmVzb3VyY2VDb25maWd9KVxuICAgICAgOiBudWxsXG5cbiAgICBmb3IgKGNvbnN0IHNjb3BlUGxhbkVudHJ5IG9mIHJlc291cmNlQ29uZmlnLnNjb3BlUGxhbikge1xuICAgICAgLyoqIEB0eXBlIHtSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPn0gKi9cbiAgICAgIGxldCByYXdWYWx1ZVxuXG4gICAgICBpZiAoY29tcHV0ZWRTY29wZUF0dHJpYnV0ZXMpIHtcbiAgICAgICAgcmF3VmFsdWUgPSBjb21wdXRlZFNjb3BlQXR0cmlidXRlc1tzY29wZVBsYW5FbnRyeS5zY29wZUF0dHJpYnV0ZV1cbiAgICAgIH0gZWxzZSBpZiAoc2NvcGVQbGFuRW50cnkucmVzb2x2ZXIpIHtcbiAgICAgICAgcmF3VmFsdWUgPSBhd2FpdCBzY29wZVBsYW5FbnRyeS5yZXNvbHZlcihyZWNvcmQpXG4gICAgICB9IGVsc2UgaWYgKHNjb3BlUGxhbkVudHJ5LnJlY29yZEF0dHJpYnV0ZSkge1xuICAgICAgICByYXdWYWx1ZSA9IHJlY29yZC5yZWFkQXR0cmlidXRlKHNjb3BlUGxhbkVudHJ5LnJlY29yZEF0dHJpYnV0ZSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJhd1ZhbHVlID0gc2NhbGFyTW9kZWxQcmltYXJ5S2V5VmFsdWUocmVjb3JkLmlkKCksIGBTeW5jIHNjb3BlIHB1Ymxpc2hpbmcgZm9yICR7cmVzb3VyY2VDb25maWcucmVzb3VyY2VUeXBlfWApXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHZhbHVlID0gcmF3VmFsdWUgPT09IHVuZGVmaW5lZCB8fCByYXdWYWx1ZSA9PT0gbnVsbCA/IG51bGwgOiBTdHJpbmcocmF3VmFsdWUpXG5cbiAgICAgIGNvbHVtbnNbc2NvcGVQbGFuRW50cnkuY29sdW1uTmFtZV0gPSB2YWx1ZVxuICAgICAgcGFyYW1zW3Njb3BlUGxhbkVudHJ5LnNjb3BlQXR0cmlidXRlXSA9IHZhbHVlXG4gICAgfVxuXG4gICAgcmV0dXJuIHtjb2x1bW5zLCBwYXJhbXN9XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZXMgYW5kIHZhbGlkYXRlcyBvbmUgY29tcHV0ZWQgc2NvcGUtYXR0cmlidXRlcyBkZWNsYXJhdGlvbi4gVGhlXG4gICAqIHJlc29sdmVyIHJ1bnMgb25jZSBwZXIgcHVibGlzaGVkIG11dGF0aW9uIHdpdGggdGhlIGV4YWN0IGNvbm5lY3Rpb24gdGhhdFxuICAgKiBvd25zIHRoYXQgbXV0YXRpb247IGV2ZXJ5IGRlY2xhcmVkIHNjb3BlIHZhbHVlIGlzIHRoZW4gcmV1c2VkIGZvciByb3dcbiAgICogcGVyc2lzdGVuY2UgYW5kIGJyb2FkY2FzdCByb3V0aW5nIHNvIHRob3NlIHR3byBpZGVudGl0aWVzIGNhbm5vdCBkcmlmdC5cbiAgICogQHBhcmFtIHt7cmVjb3JkOiBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPiwgcmVzb3VyY2VDb25maWc6IGltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hlclJlc291cmNlQ29uZmlnfX0gYXJncyAtIFJlY29yZCBhbmQgcmVzb3VyY2UgY29uZmlndXJhdGlvbi5cbiAgICogQHJldHVybnMge1Byb21pc2U8UmVjb3JkPHN0cmluZywgc3RyaW5nIHwgbnVtYmVyIHwgbnVsbD4+fSBDb21wbGV0ZSBjb21wdXRlZCBzY29wZSB2YWx1ZXMuXG4gICAqL1xuICBhc3luYyByZXNvbHZlQ29tcHV0ZWRTY29wZUF0dHJpYnV0ZXMoe3JlY29yZCwgcmVzb3VyY2VDb25maWd9KSB7XG4gICAgY29uc3QgcmVzb2x2ZXIgPSByZXNvdXJjZUNvbmZpZy5zY29wZUF0dHJpYnV0ZXNSZXNvbHZlclxuXG4gICAgaWYgKCFyZXNvbHZlcikgdGhyb3cgbmV3IEVycm9yKGBObyBjb21wdXRlZCBzY29wZS1hdHRyaWJ1dGVzIHJlc29sdmVyIGNvbmZpZ3VyZWQgZm9yICR7cmVzb3VyY2VDb25maWcucmVzb3VyY2VUeXBlfWApXG5cbiAgICBjb25zdCByZXNvbHZlZCA9IGF3YWl0IHJlc29sdmVyKHtcbiAgICAgIGNvbmZpZ3VyYXRpb246IHRoaXMuY29uZmlnLmNvbmZpZ3VyYXRpb24sXG4gICAgICBjb25uZWN0aW9uOiByZWNvcmQuY29ubmVjdGlvbigpLFxuICAgICAgcmVjb3JkXG4gICAgfSlcblxuICAgIGlmICghaXNQbGFpbk9iamVjdChyZXNvbHZlZCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHtyZXNvdXJjZUNvbmZpZy5yZXNvdXJjZVR5cGV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggc2NvcGVBdHRyaWJ1dGVzIHJlc29sdmVyIG11c3QgcmVzb2x2ZSB0byBhIHBsYWluIG9iamVjdGApXG4gICAgfVxuXG4gICAgY29uc3QgZGVjbGFyZWRBdHRyaWJ1dGVzID0gcmVzb3VyY2VDb25maWcuc2NvcGVQbGFuLm1hcCgoe3Njb3BlQXR0cmlidXRlfSkgPT4gc2NvcGVBdHRyaWJ1dGUpXG5cbiAgICBmb3IgKGNvbnN0IHNjb3BlQXR0cmlidXRlIG9mIE9iamVjdC5rZXlzKHJlc29sdmVkKSkge1xuICAgICAgaWYgKCFkZWNsYXJlZEF0dHJpYnV0ZXMuaW5jbHVkZXMoc2NvcGVBdHRyaWJ1dGUpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtyZXNvdXJjZUNvbmZpZy5yZXNvdXJjZVR5cGV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggc2NvcGVBdHRyaWJ1dGVzIHJlc29sdmVyIHJldHVybmVkIHVua25vd24gc2NvcGUgYXR0cmlidXRlOiAke3Njb3BlQXR0cmlidXRlfSAodGhlIHN5bmMgbW9kZWwgZGVjbGFyZXM6ICR7ZGVjbGFyZWRBdHRyaWJ1dGVzLmpvaW4oXCIsIFwiKX0pYClcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHNjb3BlQXR0cmlidXRlIG9mIGRlY2xhcmVkQXR0cmlidXRlcykge1xuICAgICAgaWYgKCFPYmplY3QuaGFzT3duKHJlc29sdmVkLCBzY29wZUF0dHJpYnV0ZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke3Jlc291cmNlQ29uZmlnLnJlc291cmNlVHlwZX0gc3RhdGljIHN5bmMgcHVibGlzaCBzY29wZUF0dHJpYnV0ZXMgcmVzb2x2ZXIgbXVzdCByZXNvbHZlIHRoZSBkZWNsYXJlZCBzY29wZSBhdHRyaWJ1dGUgJHtzY29wZUF0dHJpYnV0ZX1gKVxuICAgICAgfVxuXG4gICAgICBjb25zdCB2YWx1ZSA9IHJlc29sdmVkW3Njb3BlQXR0cmlidXRlXVxuXG4gICAgICBpZiAodmFsdWUgIT09IG51bGwgJiYgdHlwZW9mIHZhbHVlICE9PSBcInN0cmluZ1wiICYmIHR5cGVvZiB2YWx1ZSAhPT0gXCJudW1iZXJcIikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7cmVzb3VyY2VDb25maWcucmVzb3VyY2VUeXBlfSBzdGF0aWMgc3luYyBwdWJsaXNoIHNjb3BlIGF0dHJpYnV0ZSAke3Njb3BlQXR0cmlidXRlfSBtdXN0IGJlIGEgc3RyaW5nLCBudW1iZXIsIG9yIG51bGxgKVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiAvKiogQHR5cGUge1JlY29yZDxzdHJpbmcsIHN0cmluZyB8IG51bWJlciB8IG51bGw+fSAqLyAocmVzb2x2ZWQpXG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIHRoZSBmcmFtZXdvcmsgc3luYyBjaGFubmVsIGVudHJ5IGZvciBvbmUgcHVibGlzaGVkIGNoYW5nZTogdGhlXG4gICAqIHNuYXBzaG90dGVkIHBheWxvYWQgcGx1cyB0aGUgcGVyc2lzdGVkIHN5bmMgcm93J3MgcHVibGljIGV4YWN0LXJvdyBtZXRhZGF0YVxuICAgKiAoaWQsIHNlcnZlciBzZXF1ZW5jZSwgdXBkYXRlZC1hdCwgYW5kIGRlY2xhcmVkIHNjb3BlLXBhcnRpdGlvbiBhdHRyaWJ1dGVzKS5cbiAgICogVXNlcyB0aGUgc3luYyBtb2RlbCdzIGdlbmVyYXRlZCB0eXBlZCBhY2Nlc3NvcnMgYW5kIGZvbGxvd3MgdGhlXG4gICAqIGNoYW5nZS1mZWVkIHNlcmlhbGl6ZXIncyBwdWJsaWMgZmllbGQgY29udmVudGlvbi5cbiAgICogQHBhcmFtIHt7ZGF0YTogUmVjb3JkPHN0cmluZywgUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4+LCByZXNvdXJjZUNvbmZpZzogaW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaGVyUmVzb3VyY2VDb25maWcsIHJlc291cmNlSWQ6IHN0cmluZywgc3luY1JvdzogUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4sIHN5bmNUeXBlOiBzdHJpbmd9fSBhcmdzIC0gUHVibGlzaCBhcmdzLlxuICAgKiBAcmV0dXJucyB7UmVjb3JkPHN0cmluZywgUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4+fSBCcm9hZGNhc3Qgc3luYyBlbnRyeS5cbiAgICovXG4gIHB1Ymxpc2hlZFN5bmNFbnRyeSh7ZGF0YSwgcmVzb3VyY2VDb25maWcsIHJlc291cmNlSWQsIHN5bmNSb3csIHN5bmNUeXBlfSkge1xuICAgIC8qKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4+fSAqL1xuICAgIGNvbnN0IGVudHJ5ID0ge1xuICAgICAgZGF0YSxcbiAgICAgIGlkOiBzeW5jUm93LmlkKCksXG4gICAgICByZXNvdXJjZUlkLFxuICAgICAgcmVzb3VyY2VUeXBlOiByZXNvdXJjZUNvbmZpZy5yZXNvdXJjZVR5cGUsXG4gICAgICBzZXJ2ZXJTZXF1ZW5jZTogc3luY1Jvdy5zZXJ2ZXJTZXF1ZW5jZSgpLFxuICAgICAgc3luY1R5cGUsXG4gICAgICB1cGRhdGVkQXQ6IGlzb0RhdGUoc3luY1Jvdy51cGRhdGVkQXQoKSlcbiAgICB9XG5cbiAgICBjb25zdCBzY29wZUF0dHJpYnV0ZXMgPSBkZWNsYXJlZFN5bmNTY29wZUF0dHJpYnV0ZXModGhpcy5jb25maWcuc3luY01vZGVsKVxuXG4gICAgZm9yIChjb25zdCBzY29wZUF0dHJpYnV0ZSBvZiBzY29wZUF0dHJpYnV0ZXMgfHwgW10pIHtcbiAgICAgIGNvbnN0IHNjb3BlQWNjZXNzb3IgPSBzeW5jUm93W3Njb3BlQXR0cmlidXRlXVxuXG4gICAgICBpZiAodHlwZW9mIHNjb3BlQWNjZXNzb3IgIT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFB1Ymxpc2hlZCBzeW5jIHJvdyBpcyBtaXNzaW5nIHRoZSBkZWNsYXJlZCBzY29wZSBhY2Nlc3NvciAke3Njb3BlQXR0cmlidXRlfSgpLmApXG4gICAgICB9XG5cbiAgICAgIGVudHJ5W3Njb3BlQXR0cmlidXRlXSA9IHNjb3BlQWNjZXNzb3IuY2FsbChzeW5jUm93KVxuICAgIH1cblxuICAgIHJldHVybiBlbnRyeVxuICB9XG5cbiAgLyoqXG4gICAqIFVwc2VydHMgdGhlIHB1Ymxpc2hlZCBzZXJ2ZXItb3JpZ2luIHN5bmMgcm93IGZvciBhIHJlc291cmNlIGlkZW50aXR5OlxuICAgKiBzZXJ2ZXItb3JpZ2luIHJvd3MgY2FycnkgYSBudWxsIGFjdG9yIGNvbHVtbiAobm8gZGV2aWNlIHRvIGVjaG8gdGhlXG4gICAqIGNoYW5nZSBiYWNrIHRvKSwgc28gcmVwZWF0ZWQgc2VydmVyIGNoYW5nZXMgdG8gb25lIGNvbXBsZXRlIHJlc291cmNlIGFuZFxuICAgKiBzY29wZSBpZGVudGl0eSByZXVzZSBhbmQgcmUtc2VxdWVuY2Ugb25lIGZlZWQgcm93LiBBIGRhdGFiYXNlIGFkdmlzb3J5XG4gICAqIGxvY2sgc2VyaWFsaXplcyByZWNvbmNpbGlhdGlvbiBwbHVzIHRoZSBzaGFyZWQgdXBzZXJ0IGJlY2F1c2UgdW5pcXVlXG4gICAqIGNvbnN0cmFpbnRzIGNvbnRhaW5pbmcgbnVsbGFibGUgYWN0b3Ivc2NvcGUgY29sdW1ucyBkbyBub3QgZW5mb3JjZSB0aGlzXG4gICAqIGlkZW50aXR5IHBvcnRhYmx5IGFjcm9zcyBzdXBwb3J0ZWQgZGF0YWJhc2VzLiBSZWNvbmNpbGlhdGlvbiByZXRhaW5zIHRoZVxuICAgKiByb3cgd2l0aCB0aGUgbmV3ZXN0IGZlZWQgc2VxdWVuY2UgKHRoZW4gbG93ZXN0IGlkIGZvciBhIGRldGVybWluaXN0aWMgdGllKVxuICAgKiBhbmQgcmVtb3ZlcyBvbGRlciBtYXRjaGluZyBzZXJ2ZXItb3JpZ2luIHJvd3MgYmVmb3JlIGFwcGx5aW5nIHRoZSBjdXJyZW50XG4gICAqIG11dGF0aW9uLlxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pn0gYXR0cmlidXRlcyAtIFNuYXBzaG90dGVkIHN5bmMgcm93IGF0dHJpYnV0ZXMuXG4gICAqIEBwYXJhbSB7UmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT59IHN5bmNNb2RlbCAtIE9wZXJhdGlvbi1ib3VuZCBvciBzdGF0aWMgU3luYyBtb2RlbCBpbnRlcmZhY2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nW119IHNjb3BlQ29sdW1uTmFtZXMgLSBQZXJzaXN0ZWQgc2NvcGUgY29sdW1ucyBwYXJ0aWNpcGF0aW5nIGluIHRoZSBjb21wbGV0ZSBpZGVudGl0eS5cbiAgICogQHJldHVybnMge1Byb21pc2U8UmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4+fSBVcHNlcnRlZCBzeW5jIHJvdy5cbiAgICovXG4gIGFzeW5jIHVwc2VydFB1Ymxpc2hlZFN5bmNSb3coYXR0cmlidXRlcywgc3luY01vZGVsID0gdGhpcy5jb25maWcuc3luY01vZGVsLCBzY29wZUNvbHVtbk5hbWVzID0gW10pIHtcbiAgICAvKiogQHR5cGUge1JlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pn0gKi9cbiAgICBjb25zdCBpZGVudGl0eSA9IHtcbiAgICAgIFt0aGlzLmNvbmZpZy5hY3RvckZvcmVpZ25LZXlDb2x1bW5dOiBudWxsLFxuICAgICAgcmVzb3VyY2VfaWQ6IGF0dHJpYnV0ZXMucmVzb3VyY2VfaWQsXG4gICAgICByZXNvdXJjZV90eXBlOiBhdHRyaWJ1dGVzLnJlc291cmNlX3R5cGVcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGNvbHVtbk5hbWUgb2Ygc2NvcGVDb2x1bW5OYW1lcykge1xuICAgICAgaWYgKCFPYmplY3QuaGFzT3duKGF0dHJpYnV0ZXMsIGNvbHVtbk5hbWUpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgUHVibGlzaGVkIHN5bmMgcm93IGlkZW50aXR5IGlzIG1pc3NpbmcgdGhlIHNjb3BlIGNvbHVtbiAke2NvbHVtbk5hbWV9YClcbiAgICAgIH1cblxuICAgICAgaWRlbnRpdHlbY29sdW1uTmFtZV0gPSBhdHRyaWJ1dGVzW2NvbHVtbk5hbWVdXG4gICAgfVxuXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuY29uZmlnLnN5bmNNb2RlbC53aXRoQWR2aXNvcnlMb2NrKHN5bmNQdWJsaXNoZXJJZGVudGl0eUxvY2tOYW1lKGlkZW50aXR5KSwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgbWF0Y2hpbmdTeW5jcyA9IGF3YWl0IHN5bmNNb2RlbFxuICAgICAgICAud2hlcmUoaWRlbnRpdHkpXG4gICAgICAgIC50b0FycmF5KClcblxuICAgICAgbWF0Y2hpbmdTeW5jcy5zb3J0KGNvbXBhcmVQdWJsaXNoZWRTeW5jUm93c0J5UmVjZW5jeSlcblxuICAgICAgY29uc3QgW2V4aXN0aW5nU3luYywgLi4uZHVwbGljYXRlU3luY3NdID0gbWF0Y2hpbmdTeW5jc1xuXG4gICAgICBmb3IgKGNvbnN0IGR1cGxpY2F0ZVN5bmMgb2YgZHVwbGljYXRlU3luY3MpIHtcbiAgICAgICAgYXdhaXQgZHVwbGljYXRlU3luYy5kZXN0cm95KClcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGF3YWl0IHVwc2VydFN5bmNSb3coe2F0dHJpYnV0ZXMsIGV4aXN0aW5nU3luYywgc3luY01vZGVsfSlcbiAgICB9LCB7ZGVkaWNhdGVkQ29ubmVjdGlvbjogdHJ1ZX0pXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgYnJvYWRjYXN0ZXIgZGVsaXZlcmluZyBkZWNsYXJlZCBicm9hZGNhc3RzOiB0aGUgaW5qZWN0ZWQgb25lLFxuICAgKiBvciB0aGUgY29uZmlndXJhdGlvbidzIGNoYW5uZWwgYnJvYWRjYXN0IGF3YWl0ZWQgdGhyb3VnaCB0aGUgcGVuZGluZ1xuICAgKiBicm9hZGNhc3QgcXVldWUuXG4gICAqIEByZXR1cm5zIHtOb25OdWxsYWJsZTxpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoZXJPcHRpb25zW1wiYnJvYWRjYXN0ZXJcIl0+fSBCcm9hZGNhc3QgZGVsaXZlcmVyLlxuICAgKi9cbiAgYnJvYWRjYXN0ZXIoKSB7XG4gICAgaWYgKHRoaXMuY29uZmlnLmJyb2FkY2FzdGVyKSByZXR1cm4gdGhpcy5jb25maWcuYnJvYWRjYXN0ZXJcblxuICAgIHJldHVybiBhc3luYyAoe2JvZHksIGNoYW5uZWwsIHBhcmFtc30pID0+IHtcbiAgICAgIHRoaXMuY29uZmlnLmNvbmZpZ3VyYXRpb24uYnJvYWRjYXN0VG9DaGFubmVsKGNoYW5uZWwsIHBhcmFtcywgYm9keSlcbiAgICAgIGF3YWl0IHRoaXMuY29uZmlnLmNvbmZpZ3VyYXRpb24uYXdhaXRQZW5kaW5nQnJvYWRjYXN0cygpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcG9ydHMgYSBwb3N0LWNvbW1pdCBwdWJsaXNoIGZhaWx1cmUuIFRoZSB0cmFuc2FjdGlvbiBoYXMgYWxyZWFkeVxuICAgKiBjb21taXR0ZWQgd2hlbiBhZnRlckNvbW1pdCBjYWxsYmFja3MgcnVuLCBzbyByZXRocm93aW5nIGhlcmUgd291bGQgcG9pc29uXG4gICAqIHRoZSBkcml2ZXIncyBhd2FpdGVkIGFmdGVyQ29tbWl0IGNoYWluIChicmVha2luZyB1bnJlbGF0ZWQgY2FsbGJhY2tzKSAtXG4gICAqIGluc3RlYWQgdGhlIGZhaWx1cmUgZ29lcyB0byB0aGUgY29uZmlndXJlZCBvbkVycm9yIGhvb2ssIG9yIGlzIGVtaXR0ZWQgb25cbiAgICogdGhlIGNvbmZpZ3VyYXRpb24ncyBmcmFtZXdvcmstZXJyb3IvYWxsLWVycm9yIGNoYW5uZWxzIChzbyBwcm9kdWN0aW9uIGJ1Z1xuICAgKiByZXBvcnRpbmcgdmlhIGBjb25maWd1cmF0aW9uLmdldEVycm9yRXZlbnRzKClgIHNlZXMgYSBicm9rZW4gcHVibGlzaFxuICAgKiBwYXRoKSBhbmQgbG9nZ2VkIGxvdWRseSB0aHJvdWdoIHRoZSBwdWJsaXNoZXIncyBsb2dnZXIgd2hlbiBub25lIGlzXG4gICAqIGNvbmZpZ3VyZWQuXG4gICAqIEBwYXJhbSB7RXJyb3J9IGVycm9yIC0gUG9zdC1jb21taXQgcHVibGlzaCBmYWlsdXJlLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGFzeW5jIHJlcG9ydEFmdGVyQ29tbWl0RXJyb3IoZXJyb3IpIHtcbiAgICBpZiAodGhpcy5jb25maWcub25FcnJvcikge1xuICAgICAgdGhpcy5jb25maWcub25FcnJvcihlcnJvcilcblxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgY29uc3QgZXJyb3JFdmVudHMgPSB0aGlzLmNvbmZpZy5jb25maWd1cmF0aW9uLmdldEVycm9yRXZlbnRzKClcbiAgICBjb25zdCBwYXlsb2FkID0ge2NvbnRleHQ6IHtzdGFnZTogXCJzeW5jLXB1Ymxpc2gtYWZ0ZXItY29tbWl0XCJ9LCBlcnJvcn1cblxuICAgIGVycm9yRXZlbnRzLmVtaXQoXCJmcmFtZXdvcmstZXJyb3JcIiwgcGF5bG9hZClcbiAgICBlcnJvckV2ZW50cy5lbWl0KFwiYWxsLWVycm9yXCIsIHsuLi5wYXlsb2FkLCBlcnJvclR5cGU6IFwiZnJhbWV3b3JrLWVycm9yXCJ9KVxuXG4gICAgYXdhaXQgdGhpcy5sb2dnZXIoKS5lcnJvcihcIlN5bmNQdWJsaXNoZXIgZmFpbGVkIHRvIHB1Ymxpc2ggYSBzZXJ2ZXItc2lkZSBzeW5jIGNoYW5nZSBhZnRlciBjb21taXRcIiwgZXJyb3IpXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgbGF6aWx5IGJ1aWx0IHB1Ymxpc2hlciBsb2dnZXIuXG4gICAqIEByZXR1cm5zIHtMb2dnZXJ9IFB1Ymxpc2hlciBsb2dnZXIuXG4gICAqL1xuICBsb2dnZXIoKSB7XG4gICAgdGhpcy5fbG9nZ2VyIHx8PSBuZXcgTG9nZ2VyKFwiU3luY1B1Ymxpc2hlclwiLCB7Y29uZmlndXJhdGlvbjogdGhpcy5jb25maWcuY29uZmlndXJhdGlvbn0pXG5cbiAgICByZXR1cm4gdGhpcy5fbG9nZ2VyXG4gIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgZGV0ZXJtaW5pc3RpYywgTXlTUUwtc2FmZSBhZHZpc29yeS1sb2NrIG5hbWUgZm9yIG9uZSBjb21wbGV0ZVxuICogc2VydmVyLW9yaWdpbiBwdWJsaXNoZXIgaWRlbnRpdHkuIFN0YWJsZSBKU09OIHByZXNlcnZlcyBudWxsIGFjdG9yL3Njb3BlXG4gKiBjb21wb25lbnRzIGRpc3RpbmN0bHkgZnJvbSBzdHJpbmdzLCBhbmQgdGhlIHRydW5jYXRlZCBTSEEtMjU2IGRpZ2VzdCBrZWVwc1xuICogdGhlIGZpbmFsIG5hbWUgYmVsb3cgTXlTUUwvTWFyaWFEQidzIDY0LWNoYXJhY3RlciBgR0VUX0xPQ0tgIGxpbWl0LlxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj59IGlkZW50aXR5IC0gQ29tcGxldGUgc3luYy1yb3cgaWRlbnRpdHkgaW4gY29sdW1uIGZvcm0uXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBBZHZpc29yeS1sb2NrIG5hbWUuXG4gKi9cbmZ1bmN0aW9uIHN5bmNQdWJsaXNoZXJJZGVudGl0eUxvY2tOYW1lKGlkZW50aXR5KSB7XG4gIGNvbnN0IGhhc2ggPSBzaGEyNTZIZXgoc3RhYmxlSnNvblN0cmluZ2lmeShpZGVudGl0eSkpLnNsaWNlKDAsIDMyKVxuXG4gIHJldHVybiBgdnNwOiR7aGFzaH1gXG59XG5cbi8qKlxuICogT3JkZXJzIG1hdGNoaW5nIHB1Ymxpc2hlZCByb3dzIGJ5IHRoZSBmZWVkJ3MgcHVibGljIHJlY2VuY3kgY29udHJhY3Qgc29cbiAqIGxlZ2FjeSBkdXBsaWNhdGVzIGhhdmUgb25lIGRldGVybWluaXN0aWMgc3Vydml2b3IuIFNlcnZlciBzZXF1ZW5jZXMgYXJlXG4gKiBwb3NpdGl2ZSBhbmQgbW9ub3RvbmljOyBhIGxlZ2FjeSBudWxsIHNlcXVlbmNlIGlzIG9sZGVyIHRoYW4gYW55IGFzc2lnbmVkXG4gKiBzZXF1ZW5jZSwgYW5kIHRoZSBpbW11dGFibGUgcm93IGlkIGJyZWFrcyBvdGhlcndpc2UtZXF1YWwgdGllcy5cbiAqIEBwYXJhbSB7UmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT59IGxlZnQgLSBGaXJzdCBtYXRjaGluZyBzeW5jIHJvdy5cbiAqIEBwYXJhbSB7UmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT59IHJpZ2h0IC0gU2Vjb25kIG1hdGNoaW5nIHN5bmMgcm93LlxuICogQHJldHVybnMge251bWJlcn0gU29ydCBjb21wYXJpc29uIHdpdGggdGhlIGNhbm9uaWNhbCBzdXJ2aXZvciBmaXJzdC5cbiAqL1xuZnVuY3Rpb24gY29tcGFyZVB1Ymxpc2hlZFN5bmNSb3dzQnlSZWNlbmN5KGxlZnQsIHJpZ2h0KSB7XG4gIGNvbnN0IGxlZnRTZXF1ZW5jZSA9IGxlZnQuc2VydmVyU2VxdWVuY2UoKVxuICBjb25zdCByaWdodFNlcXVlbmNlID0gcmlnaHQuc2VydmVyU2VxdWVuY2UoKVxuXG4gIGlmIChsZWZ0U2VxdWVuY2UgPT09IG51bGwgJiYgcmlnaHRTZXF1ZW5jZSAhPT0gbnVsbCkgcmV0dXJuIDFcbiAgaWYgKGxlZnRTZXF1ZW5jZSAhPT0gbnVsbCAmJiByaWdodFNlcXVlbmNlID09PSBudWxsKSByZXR1cm4gLTFcbiAgaWYgKGxlZnRTZXF1ZW5jZSAhPT0gcmlnaHRTZXF1ZW5jZSkgcmV0dXJuIHJpZ2h0U2VxdWVuY2UgLSBsZWZ0U2VxdWVuY2VcblxuICByZXR1cm4gbGVmdC5pZCgpLmxvY2FsZUNvbXBhcmUocmlnaHQuaWQoKSlcbn1cblxuLyoqXG4gKiBSZXNvbHZlcyBhIG1vZGVsIGNsYXNzJ3MgYWN0aXZlIHB1Ymxpc2ggZGVjbGFyYXRpb24gZnJvbSBgc3RhdGljIHN5bmNgLlxuICogT3B0ZWQtb3V0IChgcHVibGlzaDogZmFsc2VgKSBhbmQgdW5kZWNsYXJlZCBtb2RlbHMgcmVzb2x2ZSB0byBudWxsOyBldmVyeVxuICogb3RoZXIgZGVjbGFyZWQgdmFsdWUgZmxvd3MgaW50byBsb3VkIGRlY2xhcmF0aW9uIHZhbGlkYXRpb24uXG4gKiBAcGFyYW0ge1JldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+fSBtb2RlbENsYXNzIC0gUmVnaXN0ZXJlZCBtb2RlbCBjbGFzcy5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoRGVjbGFyYXRpb24gfCBudWxsfSBBY3RpdmUgcHVibGlzaCBkZWNsYXJhdGlvbiwgb3IgbnVsbC5cbiAqL1xuZnVuY3Rpb24gcHVibGlzaERlY2xhcmF0aW9uRm9yKG1vZGVsQ2xhc3MpIHtcbiAgY29uc3QgZGVjbGFyYXRpb24gPSBtb2RlbENsYXNzLnN5bmNcblxuICBpZiAoIWRlY2xhcmF0aW9uIHx8IHR5cGVvZiBkZWNsYXJhdGlvbiAhPT0gXCJvYmplY3RcIiB8fCBkZWNsYXJhdGlvbi5wdWJsaXNoID09PSB1bmRlZmluZWQgfHwgZGVjbGFyYXRpb24ucHVibGlzaCA9PT0gZmFsc2UpIHJldHVybiBudWxsXG5cbiAgcmV0dXJuIGRlY2xhcmF0aW9uLnB1Ymxpc2hcbn1cblxuLyoqXG4gKiBCdWlsZHMgb25lIHB1Ymxpc2hlZCByZXNvdXJjZSBjb25maWcgZnJvbSBhIG1vZGVsJ3MgYHN0YXRpYyBzeW5jYCBwdWJsaXNoXG4gKiBkZWNsYXJhdGlvbi4gYHB1Ymxpc2g6IHRydWVgIG9wdHMgaW4gd2l0aCBhbGwgZGVmYXVsdHMgKGF0dHJpYnV0ZSBwYXlsb2FkLFxuICogZGVyaXZlZCBzY29wZSBwYXJ0aXRpb24sIGNyZWF0ZWQvdXBkYXRlZCBvcGVyYXRpb25zKS5cbiAqIEBwYXJhbSB7e21vZGVsQ2xhc3M6IFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+LCBwdWJsaXNoOiBpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoRGVjbGFyYXRpb24gfCBudWxsLCBzY29wZUF0dHJpYnV0ZXM6IHN0cmluZ1tdIHwgbnVsbCwgc3luY01vZGVsOiBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPn19IGFyZ3MgLSBEZWNsYXJhdGlvbiBhcmdzIHBsdXMgdGhlIHN5bmMgbW9kZWwncyBkZWNsYXJlZCBzY29wZSBhdHRyaWJ1dGVzLlxuICogQHJldHVybnMge2ltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hlclJlc291cmNlQ29uZmlnfSBEZXJpdmVkIHJlc291cmNlIGNvbmZpZy5cbiAqL1xuZnVuY3Rpb24gcmVzb3VyY2VDb25maWdGcm9tUHVibGlzaERlY2xhcmF0aW9uKHttb2RlbENsYXNzLCBwdWJsaXNoLCBzY29wZUF0dHJpYnV0ZXM6IHN5bmNTY29wZUF0dHJpYnV0ZXMsIHN5bmNNb2RlbH0pIHtcbiAgY29uc3QgbW9kZWxOYW1lID0gbW9kZWxDbGFzcy5nZXRNb2RlbE5hbWUoKVxuICBjb25zdCBub3JtYWxpemVkUHVibGlzaCA9IHB1Ymxpc2ggPT09IHRydWUgPyB7fSA6IHB1Ymxpc2hcblxuICBpZiAoIW5vcm1hbGl6ZWRQdWJsaXNoIHx8IHR5cGVvZiBub3JtYWxpemVkUHVibGlzaCAhPT0gXCJvYmplY3RcIiB8fCBBcnJheS5pc0FycmF5KG5vcm1hbGl6ZWRQdWJsaXNoKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgJHttb2RlbE5hbWV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggbXVzdCBiZSB0cnVlLCBmYWxzZSBvciBhIHB1Ymxpc2ggZGVjbGFyYXRpb24gb2JqZWN0LCBnb3Q6ICR7U3RyaW5nKHB1Ymxpc2gpfWApXG4gIH1cblxuICBjb25zdCB7YnJvYWRjYXN0cywgZXZlbnRJZCwgb3BlcmF0aW9ucywgcmVzb3VyY2VUeXBlLCBzY29wZUF0dHJpYnV0ZXMsIHNlcmlhbGl6ZSwgLi4ucmVzdERlY2xhcmF0aW9ufSA9IG5vcm1hbGl6ZWRQdWJsaXNoXG4gIGNvbnN0IHVua25vd25LZXlzID0gT2JqZWN0LmtleXMocmVzdERlY2xhcmF0aW9uKVxuXG4gIGlmICh1bmtub3duS2V5cy5sZW5ndGggPiAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGAke21vZGVsTmFtZX0gc3RhdGljIHN5bmMgcHVibGlzaCByZWNlaXZlZCB1bmtub3duIGtleXM6ICR7dW5rbm93bktleXMuam9pbihcIiwgXCIpfSAoc3VwcG9ydGVkOiBicm9hZGNhc3RzLCBldmVudElkIChkZXByZWNhdGVkKSwgb3BlcmF0aW9ucywgcmVzb3VyY2VUeXBlLCBzY29wZUF0dHJpYnV0ZXMsIHNlcmlhbGl6ZSlgKVxuICB9XG4gIGlmIChzZXJpYWxpemUgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2Ygc2VyaWFsaXplICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bW9kZWxOYW1lfSBzdGF0aWMgc3luYyBwdWJsaXNoIHNlcmlhbGl6ZSBtdXN0IGJlIGEgZnVuY3Rpb24gYnVpbGRpbmcgdGhlIHB1Ymxpc2hlZCBwYXlsb2FkLCBnb3Q6ICR7U3RyaW5nKHNlcmlhbGl6ZSl9YClcbiAgfVxuICBpZiAob3BlcmF0aW9ucyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KG9wZXJhdGlvbnMpIHx8IG9wZXJhdGlvbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bW9kZWxOYW1lfSBzdGF0aWMgc3luYyBwdWJsaXNoIG9wZXJhdGlvbnMgbXVzdCBiZSBhIG5vbi1lbXB0eSBhcnJheSBvZiBjcmVhdGUvdXBkYXRlL2Rlc3Ryb3lgKVxuICAgIH1cblxuICAgIGZvciAoY29uc3Qgb3BlcmF0aW9uIG9mIG9wZXJhdGlvbnMpIHtcbiAgICAgIGlmICghKG9wZXJhdGlvbiBpbiBQVUJMSVNIRURfQ0FMTEJBQ0tfTkFNRVMpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHttb2RlbE5hbWV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggb3BlcmF0aW9ucyBtdXN0IGJlIGNyZWF0ZS91cGRhdGUvZGVzdHJveSwgZ290OiAke1N0cmluZyhvcGVyYXRpb24pfWApXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgY29uc3Qgc2NvcGVQbGFuID0gc2NvcGVQbGFuRm9yKHtldmVudElkLCBtb2RlbENsYXNzLCBtb2RlbE5hbWUsIHNjb3BlQXR0cmlidXRlcywgc3luY01vZGVsLCBzeW5jU2NvcGVBdHRyaWJ1dGVzfSlcblxuICByZXR1cm4ge1xuICAgIGJyb2FkY2FzdHMsXG4gICAgbW9kZWxDbGFzcyxcbiAgICBvcGVyYXRpb25zOiBvcGVyYXRpb25zID09PSB1bmRlZmluZWQgPyBERUZBVUxUX1BVQkxJU0hFRF9PUEVSQVRJT05TIDogb3BlcmF0aW9ucyxcbiAgICByZXNvdXJjZVR5cGU6IHJlc291cmNlVHlwZSA9PT0gdW5kZWZpbmVkID8gbW9kZWxOYW1lIDogcmVzb3VyY2VUeXBlLFxuICAgIHNjb3BlQXR0cmlidXRlc1Jlc29sdmVyOiB0eXBlb2Ygc2NvcGVBdHRyaWJ1dGVzID09PSBcImZ1bmN0aW9uXCIgPyBzY29wZUF0dHJpYnV0ZXMgOiB1bmRlZmluZWQsXG4gICAgc2NvcGVQbGFuLFxuICAgIHNlcmlhbGl6ZTogc2VyaWFsaXplID09PSB1bmRlZmluZWQgPyBkZWZhdWx0U2VyaWFsaXplZEF0dHJpYnV0ZXMgOiBzZXJpYWxpemVcbiAgfVxufVxuXG4vKipcbiAqIERlcml2ZXMgdGhlIHNjb3BlIHBsYW4gcGFydGl0aW9uaW5nIGEgcHVibGlzaGVkIG1vZGVsJ3MgY2hhbmdlczogb25lIGVudHJ5XG4gKiBwZXIgc2NvcGUgYXR0cmlidXRlIGRlY2xhcmVkIG9uIHRoZSBzeW5jIG1vZGVsIChgc3RhdGljXG4gKiBzeW5jU2NvcGVBdHRyaWJ1dGVzYCksIGVhY2ggcmVhZGluZyB0aGUgcmVjb3JkIGF0dHJpYnV0ZSBuYW1lZCBsaWtlIHRoZVxuICogc2NvcGUgYXR0cmlidXRlIChvdmVycmlkYWJsZSB0aHJvdWdoIHRoZSBkZWNsYXJhdGlvbidzIGBzY29wZUF0dHJpYnV0ZXNgXG4gKiBuYW1lIG1hcCksIG9yIHRoZSByZWNvcmQncyBvd24gaWQgd2hlbiB0aGUgbW9kZWwgaGFzIG5vIHN1Y2ggYXR0cmlidXRlXG4gKiAoc2NvcGUtcm9vdCBtb2RlbHMpLiBUaGUgZGVwcmVjYXRlZCBgZXZlbnRJZGAgZGVjbGFyYXRpb24gZm9ybXMgbWFwIHRvIGFcbiAqIGZpeGVkIGBldmVudElkYC9gZXZlbnRfaWRgIHBsYW4gZm9yIDEuMC41MDMgY29tcGF0aWJpbGl0eS5cbiAqIEBwYXJhbSB7e2V2ZW50SWQ6IGltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hEZWNsYXJhdGlvbkNvbmZpZ1tcImV2ZW50SWRcIl0sIG1vZGVsQ2xhc3M6IFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+LCBtb2RlbE5hbWU6IHN0cmluZywgc2NvcGVBdHRyaWJ1dGVzOiBpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoRGVjbGFyYXRpb25Db25maWdbXCJzY29wZUF0dHJpYnV0ZXNcIl0sIHN5bmNNb2RlbDogUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4sIHN5bmNTY29wZUF0dHJpYnV0ZXM6IHN0cmluZ1tdIHwgbnVsbH19IGFyZ3MgLSBEZWNsYXJhdGlvbiBhbmQgc3luYy1tb2RlbCBzY29wZSBhcmdzLlxuICogQHJldHVybnMge0FycmF5PGltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hlclNjb3BlUGxhbkVudHJ5Pn0gRGVyaXZlZCBzY29wZSBwbGFuLlxuICovXG5mdW5jdGlvbiBzY29wZVBsYW5Gb3Ioe2V2ZW50SWQsIG1vZGVsQ2xhc3MsIG1vZGVsTmFtZSwgc2NvcGVBdHRyaWJ1dGVzLCBzeW5jTW9kZWwsIHN5bmNTY29wZUF0dHJpYnV0ZXN9KSB7XG4gIGNvbnN0IGF0dHJpYnV0ZU5hbWVzID0gT2JqZWN0LnZhbHVlcyhtb2RlbENsYXNzLmdldENvbHVtbk5hbWVUb0F0dHJpYnV0ZU5hbWVNYXAoKSlcblxuICBpZiAoZXZlbnRJZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgaWYgKHNjb3BlQXR0cmlidXRlcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bW9kZWxOYW1lfSBzdGF0aWMgc3luYyBwdWJsaXNoIGNhbid0IGRlY2xhcmUgYm90aCBzY29wZUF0dHJpYnV0ZXMgYW5kIHRoZSBkZXByZWNhdGVkIGV2ZW50SWQgZm9ybWApXG4gICAgfVxuICAgIGlmICh0eXBlb2YgZXZlbnRJZCA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICByZXR1cm4gW3tjb2x1bW5OYW1lOiBcImV2ZW50X2lkXCIsIHJlY29yZEF0dHJpYnV0ZTogbnVsbCwgcmVzb2x2ZXI6IGV2ZW50SWQsIHNjb3BlQXR0cmlidXRlOiBcImV2ZW50SWRcIn1dXG4gICAgfVxuICAgIGlmICh0eXBlb2YgZXZlbnRJZCAhPT0gXCJzdHJpbmdcIikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGAke21vZGVsTmFtZX0gc3RhdGljIHN5bmMgcHVibGlzaCBldmVudElkIG11c3QgYmUgYW4gYXR0cmlidXRlLW5hbWUgc3RyaW5nIChvciBhIGRlcHJlY2F0ZWQgcmVzb2x2ZXIgZnVuY3Rpb24pLCBnb3Q6ICR7U3RyaW5nKGV2ZW50SWQpfWApXG4gICAgfVxuICAgIGlmICghYXR0cmlidXRlTmFtZXMuaW5jbHVkZXMoZXZlbnRJZCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHttb2RlbE5hbWV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggZXZlbnRJZCBhdHRyaWJ1dGUgZG9lc24ndCBleGlzdCBvbiB0aGUgbW9kZWw6ICR7ZXZlbnRJZH1gKVxuICAgIH1cblxuICAgIHJldHVybiBbe2NvbHVtbk5hbWU6IFwiZXZlbnRfaWRcIiwgcmVjb3JkQXR0cmlidXRlOiBldmVudElkLCByZXNvbHZlcjogdW5kZWZpbmVkLCBzY29wZUF0dHJpYnV0ZTogXCJldmVudElkXCJ9XVxuICB9XG5cbiAgaWYgKHNjb3BlQXR0cmlidXRlcyAhPT0gdW5kZWZpbmVkICYmICFzeW5jU2NvcGVBdHRyaWJ1dGVzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGAke21vZGVsTmFtZX0gc3RhdGljIHN5bmMgcHVibGlzaCBkZWNsYXJlcyBzY29wZUF0dHJpYnV0ZXMgYnV0IHRoZSBzeW5jIG1vZGVsIGRlY2xhcmVzIG5vIHN0YXRpYyBzeW5jU2NvcGVBdHRyaWJ1dGVzYClcbiAgfVxuXG4gIGlmICghc3luY1Njb3BlQXR0cmlidXRlcykgcmV0dXJuIFtdXG5cbiAgaWYgKHR5cGVvZiBzY29wZUF0dHJpYnV0ZXMgPT09IFwiZnVuY3Rpb25cIikge1xuICAgIHJldHVybiBzeW5jU2NvcGVBdHRyaWJ1dGVzLm1hcCgoc2NvcGVBdHRyaWJ1dGUpID0+ICh7XG4gICAgICBjb2x1bW5OYW1lOiBzeW5jU2NvcGVDb2x1bW5OYW1lKHtzY29wZUF0dHJpYnV0ZSwgc3luY01vZGVsfSksXG4gICAgICByZWNvcmRBdHRyaWJ1dGU6IG51bGwsXG4gICAgICByZXNvbHZlcjogdW5kZWZpbmVkLFxuICAgICAgc2NvcGVBdHRyaWJ1dGVcbiAgICB9KSlcbiAgfVxuXG4gIGlmIChzY29wZUF0dHJpYnV0ZXMgIT09IHVuZGVmaW5lZCAmJiAodHlwZW9mIHNjb3BlQXR0cmlidXRlcyAhPT0gXCJvYmplY3RcIiB8fCBBcnJheS5pc0FycmF5KHNjb3BlQXR0cmlidXRlcykpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGAke21vZGVsTmFtZX0gc3RhdGljIHN5bmMgcHVibGlzaCBzY29wZUF0dHJpYnV0ZXMgbXVzdCBiZSBhbiBvYmplY3QgbWFwcGluZyBzY29wZSBhdHRyaWJ1dGVzIHRvIHJlY29yZCBhdHRyaWJ1dGUgbmFtZXMsIGdvdDogJHtTdHJpbmcoc2NvcGVBdHRyaWJ1dGVzKX1gKVxuICB9XG5cbiAgZm9yIChjb25zdCBzY29wZUF0dHJpYnV0ZSBvZiBPYmplY3Qua2V5cyhzY29wZUF0dHJpYnV0ZXMgfHwge30pKSB7XG4gICAgaWYgKCFzeW5jU2NvcGVBdHRyaWJ1dGVzLmluY2x1ZGVzKHNjb3BlQXR0cmlidXRlKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGAke21vZGVsTmFtZX0gc3RhdGljIHN5bmMgcHVibGlzaCBzY29wZUF0dHJpYnV0ZXMgcmVjZWl2ZWQgdW5rbm93biBzY29wZSBhdHRyaWJ1dGU6ICR7c2NvcGVBdHRyaWJ1dGV9ICh0aGUgc3luYyBtb2RlbCBkZWNsYXJlczogJHtzeW5jU2NvcGVBdHRyaWJ1dGVzLmpvaW4oXCIsIFwiKX0pYClcbiAgICB9XG4gIH1cblxuICByZXR1cm4gc3luY1Njb3BlQXR0cmlidXRlcy5tYXAoKHNjb3BlQXR0cmlidXRlKSA9PiB7XG4gICAgY29uc3QgZGVjbGFyZWRSZWNvcmRBdHRyaWJ1dGUgPSBzY29wZUF0dHJpYnV0ZXM/LltzY29wZUF0dHJpYnV0ZV1cblxuICAgIGlmIChkZWNsYXJlZFJlY29yZEF0dHJpYnV0ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAodHlwZW9mIGRlY2xhcmVkUmVjb3JkQXR0cmlidXRlICE9PSBcInN0cmluZ1wiIHx8ICFhdHRyaWJ1dGVOYW1lcy5pbmNsdWRlcyhkZWNsYXJlZFJlY29yZEF0dHJpYnV0ZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke21vZGVsTmFtZX0gc3RhdGljIHN5bmMgcHVibGlzaCBzY29wZUF0dHJpYnV0ZXMuJHtzY29wZUF0dHJpYnV0ZX0gbXVzdCBuYW1lIGFuIGV4aXN0aW5nIHJlY29yZCBhdHRyaWJ1dGUsIGdvdDogJHtTdHJpbmcoZGVjbGFyZWRSZWNvcmRBdHRyaWJ1dGUpfWApXG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7Y29sdW1uTmFtZTogc3luY1Njb3BlQ29sdW1uTmFtZSh7c2NvcGVBdHRyaWJ1dGUsIHN5bmNNb2RlbH0pLCByZWNvcmRBdHRyaWJ1dGU6IGRlY2xhcmVkUmVjb3JkQXR0cmlidXRlLCByZXNvbHZlcjogdW5kZWZpbmVkLCBzY29wZUF0dHJpYnV0ZX1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgY29sdW1uTmFtZTogc3luY1Njb3BlQ29sdW1uTmFtZSh7c2NvcGVBdHRyaWJ1dGUsIHN5bmNNb2RlbH0pLFxuICAgICAgcmVjb3JkQXR0cmlidXRlOiBhdHRyaWJ1dGVOYW1lcy5pbmNsdWRlcyhzY29wZUF0dHJpYnV0ZSkgPyBzY29wZUF0dHJpYnV0ZSA6IG51bGwsXG4gICAgICByZXNvbHZlcjogdW5kZWZpbmVkLFxuICAgICAgc2NvcGVBdHRyaWJ1dGVcbiAgICB9XG4gIH0pXG59XG5cbi8qKlxuICogQ2hlY2tzIHRoYXQgYSBjb21wdXRlZCBkZWNsYXJhdGlvbiByZXR1cm5lZCBhbiBvcmRpbmFyeSBrZXkvdmFsdWUgb2JqZWN0LlxuICogQHBhcmFtIHt1bmtub3dufSB2YWx1ZSAtIFJlc29sdmVyIHJlc3VsdC5cbiAqIEByZXR1cm5zIHt2YWx1ZSBpcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPn0gV2hldGhlciB0aGUgdmFsdWUgaXMgYSBwbGFpbiBvYmplY3QuXG4gKi9cbmZ1bmN0aW9uIGlzUGxhaW5PYmplY3QodmFsdWUpIHtcbiAgaWYgKCF2YWx1ZSB8fCB0eXBlb2YgdmFsdWUgIT09IFwib2JqZWN0XCIgfHwgQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHJldHVybiBmYWxzZVxuXG4gIGNvbnN0IHByb3RvdHlwZSA9IE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSlcblxuICByZXR1cm4gcHJvdG90eXBlID09PSBPYmplY3QucHJvdG90eXBlIHx8IHByb3RvdHlwZSA9PT0gbnVsbFxufVxuXG4vKipcbiAqIFJlc29sdmVzIHRoZSBzeW5jLXJvdyBjb2x1bW4gcGVyc2lzdGluZyBhIGRlY2xhcmVkIHNjb3BlIGF0dHJpYnV0ZS5cbiAqIEBwYXJhbSB7e3Njb3BlQXR0cmlidXRlOiBzdHJpbmcsIHN5bmNNb2RlbDogUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT59fSBhcmdzIC0gU2NvcGUgYXR0cmlidXRlIGFuZCBzeW5jIG1vZGVsLlxuICogQHJldHVybnMge3N0cmluZ30gU3luYy1yb3cgY29sdW1uIG5hbWUuXG4gKi9cbmZ1bmN0aW9uIHN5bmNTY29wZUNvbHVtbk5hbWUoe3Njb3BlQXR0cmlidXRlLCBzeW5jTW9kZWx9KSB7XG4gIGNvbnN0IGNvbHVtbk5hbWUgPSBzeW5jTW9kZWwuZ2V0QXR0cmlidXRlTmFtZVRvQ29sdW1uTmFtZU1hcCgpW3Njb3BlQXR0cmlidXRlXVxuXG4gIGlmICghY29sdW1uTmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgJHtzeW5jTW9kZWwubmFtZX0gZGVjbGFyZXMgdGhlIHN5bmMgc2NvcGUgYXR0cmlidXRlICR7c2NvcGVBdHRyaWJ1dGV9IGJ1dCBoYXMgbm8gbWF0Y2hpbmcgY29sdW1uIGZvciBpdGApXG4gIH1cblxuICByZXR1cm4gY29sdW1uTmFtZVxufVxuXG4vKipcbiAqIERlZmF1bHQgcHVibGlzaCBzZXJpYWxpemVyOiB0aGUgcmVjb3JkJ3MgYXR0cmlidXRlcyB3aXRoIERhdGUgdmFsdWVzXG4gKiBzZXJpYWxpemVkIHRvIElTTyBzdHJpbmdzLlxuICogQHBhcmFtIHtSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPn0gcmVjb3JkIC0gTXV0YXRlZCBzZXJ2ZXIgbW9kZWwgcmVjb3JkLlxuICogQHJldHVybnMge1JlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pn0gU2VyaWFsaXplZCBhdHRyaWJ1dGVzIHBheWxvYWQuXG4gKi9cbmZ1bmN0aW9uIGRlZmF1bHRTZXJpYWxpemVkQXR0cmlidXRlcyhyZWNvcmQpIHtcbiAgLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj59ICovXG4gIGNvbnN0IGF0dHJpYnV0ZXMgPSB7Li4ucmVjb3JkLmF0dHJpYnV0ZXMoKX1cblxuICBmb3IgKGNvbnN0IFthdHRyaWJ1dGVOYW1lLCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMoYXR0cmlidXRlcykpIHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBEYXRlKSBhdHRyaWJ1dGVzW2F0dHJpYnV0ZU5hbWVdID0gdmFsdWUudG9JU09TdHJpbmcoKVxuICB9XG5cbiAgcmV0dXJuIGF0dHJpYnV0ZXNcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBhIGRhdGUtbGlrZSB2YWx1ZSB0byBhbiBJU08gc3RyaW5nLCBtYXRjaGluZyB0aGUgY2hhbmdlLWZlZWRcbiAqIHNlcmlhbGl6ZXIncyBjb252ZW50aW9uIGZvciB0aGUgc3luYyBlbnRyeSdzIHB1YmxpYyB1cGRhdGVkLWF0IG1ldGFkYXRhLlxuICogQHBhcmFtIHtEYXRlIHwgbnVsbH0gdmFsdWUgLSBQZXJzaXN0ZWQgdXBkYXRlZC1hdCB2YWx1ZS5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IElTTyBkYXRlLlxuICogQHRocm93cyB7RXJyb3J9IFdoZW4gdGhlIHBlcnNpc3RlZCByb3cgaGFzIG5vIHZhbGlkIHVwZGF0ZWQtYXQgdGltZXN0YW1wLlxuICovXG5mdW5jdGlvbiBpc29EYXRlKHZhbHVlKSB7XG4gIGlmICghKHZhbHVlIGluc3RhbmNlb2YgRGF0ZSkgfHwgTnVtYmVyLmlzTmFOKHZhbHVlLmdldFRpbWUoKSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJQdWJsaXNoZWQgc3luYyByb3cgbXVzdCBoYXZlIGEgdmFsaWQgdXBkYXRlZEF0IHRpbWVzdGFtcC5cIilcbiAgfVxuXG4gIHJldHVybiB2YWx1ZS50b0lTT1N0cmluZygpXG59XG4iXX0=
|
|
@@ -4,6 +4,8 @@ import Configuration from "../configuration.js"
|
|
|
4
4
|
import Logger from "../logger.js"
|
|
5
5
|
import {scalarModelPrimaryKeyValue} from "../utils/model-primary-key.js"
|
|
6
6
|
import restArgsError from "../utils/rest-args-error.js"
|
|
7
|
+
import sha256Hex from "../utils/sha256-hex.js"
|
|
8
|
+
import stableJsonStringify from "../utils/stable-json.js"
|
|
7
9
|
|
|
8
10
|
import {declaredSyncScopeAttributes} from "./sync-scope-attributes.js"
|
|
9
11
|
import {deliverDeclaredBroadcasts, upsertSyncRow} from "./sync-change-fanout.js"
|
|
@@ -211,7 +213,8 @@ export default class SyncPublisher {
|
|
|
211
213
|
|
|
212
214
|
await record.connection().afterCommit(async () => {
|
|
213
215
|
try {
|
|
214
|
-
const
|
|
216
|
+
const scopeColumnNames = resourceConfig.scopePlan.map(({columnName}) => columnName)
|
|
217
|
+
const syncRow = await this.upsertPublishedSyncRow(attributes, operationScope, scopeColumnNames)
|
|
215
218
|
|
|
216
219
|
await this.broadcaster()({
|
|
217
220
|
body: {
|
|
@@ -362,22 +365,50 @@ export default class SyncPublisher {
|
|
|
362
365
|
/**
|
|
363
366
|
* Upserts the published server-origin sync row for a resource identity:
|
|
364
367
|
* server-origin rows carry a null actor column (no device to echo the
|
|
365
|
-
* change back to), so repeated server changes to one resource
|
|
366
|
-
* re-sequence one feed row.
|
|
368
|
+
* change back to), so repeated server changes to one complete resource and
|
|
369
|
+
* scope identity reuse and re-sequence one feed row. A database advisory
|
|
370
|
+
* lock serializes reconciliation plus the shared upsert because unique
|
|
371
|
+
* constraints containing nullable actor/scope columns do not enforce this
|
|
372
|
+
* identity portably across supported databases. Reconciliation retains the
|
|
373
|
+
* row with the newest feed sequence (then lowest id for a deterministic tie)
|
|
374
|
+
* and removes older matching server-origin rows before applying the current
|
|
375
|
+
* mutation.
|
|
367
376
|
* @param {Record<string, ReturnType<typeof JSON.parse>>} attributes - Snapshotted sync row attributes.
|
|
368
377
|
* @param {ReturnType<typeof JSON.parse>} syncModel - Operation-bound or static Sync model interface.
|
|
378
|
+
* @param {string[]} scopeColumnNames - Persisted scope columns participating in the complete identity.
|
|
369
379
|
* @returns {Promise<ReturnType<typeof JSON.parse>>} Upserted sync row.
|
|
370
380
|
*/
|
|
371
|
-
async upsertPublishedSyncRow(attributes, syncModel = this.config.syncModel) {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
381
|
+
async upsertPublishedSyncRow(attributes, syncModel = this.config.syncModel, scopeColumnNames = []) {
|
|
382
|
+
/** @type {Record<string, ReturnType<typeof JSON.parse>>} */
|
|
383
|
+
const identity = {
|
|
384
|
+
[this.config.actorForeignKeyColumn]: null,
|
|
385
|
+
resource_id: attributes.resource_id,
|
|
386
|
+
resource_type: attributes.resource_type
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
for (const columnName of scopeColumnNames) {
|
|
390
|
+
if (!Object.hasOwn(attributes, columnName)) {
|
|
391
|
+
throw new Error(`Published sync row identity is missing the scope column ${columnName}`)
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
identity[columnName] = attributes[columnName]
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
return await this.config.syncModel.withAdvisoryLock(syncPublisherIdentityLockName(identity), async () => {
|
|
398
|
+
const matchingSyncs = await syncModel
|
|
399
|
+
.where(identity)
|
|
400
|
+
.toArray()
|
|
401
|
+
|
|
402
|
+
matchingSyncs.sort(comparePublishedSyncRowsByRecency)
|
|
403
|
+
|
|
404
|
+
const [existingSync, ...duplicateSyncs] = matchingSyncs
|
|
405
|
+
|
|
406
|
+
for (const duplicateSync of duplicateSyncs) {
|
|
407
|
+
await duplicateSync.destroy()
|
|
408
|
+
}
|
|
379
409
|
|
|
380
|
-
|
|
410
|
+
return await upsertSyncRow({attributes, existingSync, syncModel})
|
|
411
|
+
}, {dedicatedConnection: true})
|
|
381
412
|
}
|
|
382
413
|
|
|
383
414
|
/**
|
|
@@ -434,6 +465,40 @@ export default class SyncPublisher {
|
|
|
434
465
|
}
|
|
435
466
|
}
|
|
436
467
|
|
|
468
|
+
/**
|
|
469
|
+
* Returns a deterministic, MySQL-safe advisory-lock name for one complete
|
|
470
|
+
* server-origin publisher identity. Stable JSON preserves null actor/scope
|
|
471
|
+
* components distinctly from strings, and the truncated SHA-256 digest keeps
|
|
472
|
+
* the final name below MySQL/MariaDB's 64-character `GET_LOCK` limit.
|
|
473
|
+
* @param {Record<string, ReturnType<typeof JSON.parse>>} identity - Complete sync-row identity in column form.
|
|
474
|
+
* @returns {string} Advisory-lock name.
|
|
475
|
+
*/
|
|
476
|
+
function syncPublisherIdentityLockName(identity) {
|
|
477
|
+
const hash = sha256Hex(stableJsonStringify(identity)).slice(0, 32)
|
|
478
|
+
|
|
479
|
+
return `vsp:${hash}`
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Orders matching published rows by the feed's public recency contract so
|
|
484
|
+
* legacy duplicates have one deterministic survivor. Server sequences are
|
|
485
|
+
* positive and monotonic; a legacy null sequence is older than any assigned
|
|
486
|
+
* sequence, and the immutable row id breaks otherwise-equal ties.
|
|
487
|
+
* @param {ReturnType<typeof JSON.parse>} left - First matching sync row.
|
|
488
|
+
* @param {ReturnType<typeof JSON.parse>} right - Second matching sync row.
|
|
489
|
+
* @returns {number} Sort comparison with the canonical survivor first.
|
|
490
|
+
*/
|
|
491
|
+
function comparePublishedSyncRowsByRecency(left, right) {
|
|
492
|
+
const leftSequence = left.serverSequence()
|
|
493
|
+
const rightSequence = right.serverSequence()
|
|
494
|
+
|
|
495
|
+
if (leftSequence === null && rightSequence !== null) return 1
|
|
496
|
+
if (leftSequence !== null && rightSequence === null) return -1
|
|
497
|
+
if (leftSequence !== rightSequence) return rightSequence - leftSequence
|
|
498
|
+
|
|
499
|
+
return left.id().localeCompare(right.id())
|
|
500
|
+
}
|
|
501
|
+
|
|
437
502
|
/**
|
|
438
503
|
* Resolves a model class's active publish declaration from `static sync`.
|
|
439
504
|
* Opted-out (`publish: false`) and undeclared models resolve to null; every
|
package/package.json
CHANGED
|
@@ -4,6 +4,8 @@ import Configuration from "../configuration.js"
|
|
|
4
4
|
import Logger from "../logger.js"
|
|
5
5
|
import {scalarModelPrimaryKeyValue} from "../utils/model-primary-key.js"
|
|
6
6
|
import restArgsError from "../utils/rest-args-error.js"
|
|
7
|
+
import sha256Hex from "../utils/sha256-hex.js"
|
|
8
|
+
import stableJsonStringify from "../utils/stable-json.js"
|
|
7
9
|
|
|
8
10
|
import {declaredSyncScopeAttributes} from "./sync-scope-attributes.js"
|
|
9
11
|
import {deliverDeclaredBroadcasts, upsertSyncRow} from "./sync-change-fanout.js"
|
|
@@ -211,7 +213,8 @@ export default class SyncPublisher {
|
|
|
211
213
|
|
|
212
214
|
await record.connection().afterCommit(async () => {
|
|
213
215
|
try {
|
|
214
|
-
const
|
|
216
|
+
const scopeColumnNames = resourceConfig.scopePlan.map(({columnName}) => columnName)
|
|
217
|
+
const syncRow = await this.upsertPublishedSyncRow(attributes, operationScope, scopeColumnNames)
|
|
215
218
|
|
|
216
219
|
await this.broadcaster()({
|
|
217
220
|
body: {
|
|
@@ -362,22 +365,50 @@ export default class SyncPublisher {
|
|
|
362
365
|
/**
|
|
363
366
|
* Upserts the published server-origin sync row for a resource identity:
|
|
364
367
|
* server-origin rows carry a null actor column (no device to echo the
|
|
365
|
-
* change back to), so repeated server changes to one resource
|
|
366
|
-
* re-sequence one feed row.
|
|
368
|
+
* change back to), so repeated server changes to one complete resource and
|
|
369
|
+
* scope identity reuse and re-sequence one feed row. A database advisory
|
|
370
|
+
* lock serializes reconciliation plus the shared upsert because unique
|
|
371
|
+
* constraints containing nullable actor/scope columns do not enforce this
|
|
372
|
+
* identity portably across supported databases. Reconciliation retains the
|
|
373
|
+
* row with the newest feed sequence (then lowest id for a deterministic tie)
|
|
374
|
+
* and removes older matching server-origin rows before applying the current
|
|
375
|
+
* mutation.
|
|
367
376
|
* @param {Record<string, ReturnType<typeof JSON.parse>>} attributes - Snapshotted sync row attributes.
|
|
368
377
|
* @param {ReturnType<typeof JSON.parse>} syncModel - Operation-bound or static Sync model interface.
|
|
378
|
+
* @param {string[]} scopeColumnNames - Persisted scope columns participating in the complete identity.
|
|
369
379
|
* @returns {Promise<ReturnType<typeof JSON.parse>>} Upserted sync row.
|
|
370
380
|
*/
|
|
371
|
-
async upsertPublishedSyncRow(attributes, syncModel = this.config.syncModel) {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
381
|
+
async upsertPublishedSyncRow(attributes, syncModel = this.config.syncModel, scopeColumnNames = []) {
|
|
382
|
+
/** @type {Record<string, ReturnType<typeof JSON.parse>>} */
|
|
383
|
+
const identity = {
|
|
384
|
+
[this.config.actorForeignKeyColumn]: null,
|
|
385
|
+
resource_id: attributes.resource_id,
|
|
386
|
+
resource_type: attributes.resource_type
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
for (const columnName of scopeColumnNames) {
|
|
390
|
+
if (!Object.hasOwn(attributes, columnName)) {
|
|
391
|
+
throw new Error(`Published sync row identity is missing the scope column ${columnName}`)
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
identity[columnName] = attributes[columnName]
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
return await this.config.syncModel.withAdvisoryLock(syncPublisherIdentityLockName(identity), async () => {
|
|
398
|
+
const matchingSyncs = await syncModel
|
|
399
|
+
.where(identity)
|
|
400
|
+
.toArray()
|
|
401
|
+
|
|
402
|
+
matchingSyncs.sort(comparePublishedSyncRowsByRecency)
|
|
403
|
+
|
|
404
|
+
const [existingSync, ...duplicateSyncs] = matchingSyncs
|
|
405
|
+
|
|
406
|
+
for (const duplicateSync of duplicateSyncs) {
|
|
407
|
+
await duplicateSync.destroy()
|
|
408
|
+
}
|
|
379
409
|
|
|
380
|
-
|
|
410
|
+
return await upsertSyncRow({attributes, existingSync, syncModel})
|
|
411
|
+
}, {dedicatedConnection: true})
|
|
381
412
|
}
|
|
382
413
|
|
|
383
414
|
/**
|
|
@@ -434,6 +465,40 @@ export default class SyncPublisher {
|
|
|
434
465
|
}
|
|
435
466
|
}
|
|
436
467
|
|
|
468
|
+
/**
|
|
469
|
+
* Returns a deterministic, MySQL-safe advisory-lock name for one complete
|
|
470
|
+
* server-origin publisher identity. Stable JSON preserves null actor/scope
|
|
471
|
+
* components distinctly from strings, and the truncated SHA-256 digest keeps
|
|
472
|
+
* the final name below MySQL/MariaDB's 64-character `GET_LOCK` limit.
|
|
473
|
+
* @param {Record<string, ReturnType<typeof JSON.parse>>} identity - Complete sync-row identity in column form.
|
|
474
|
+
* @returns {string} Advisory-lock name.
|
|
475
|
+
*/
|
|
476
|
+
function syncPublisherIdentityLockName(identity) {
|
|
477
|
+
const hash = sha256Hex(stableJsonStringify(identity)).slice(0, 32)
|
|
478
|
+
|
|
479
|
+
return `vsp:${hash}`
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Orders matching published rows by the feed's public recency contract so
|
|
484
|
+
* legacy duplicates have one deterministic survivor. Server sequences are
|
|
485
|
+
* positive and monotonic; a legacy null sequence is older than any assigned
|
|
486
|
+
* sequence, and the immutable row id breaks otherwise-equal ties.
|
|
487
|
+
* @param {ReturnType<typeof JSON.parse>} left - First matching sync row.
|
|
488
|
+
* @param {ReturnType<typeof JSON.parse>} right - Second matching sync row.
|
|
489
|
+
* @returns {number} Sort comparison with the canonical survivor first.
|
|
490
|
+
*/
|
|
491
|
+
function comparePublishedSyncRowsByRecency(left, right) {
|
|
492
|
+
const leftSequence = left.serverSequence()
|
|
493
|
+
const rightSequence = right.serverSequence()
|
|
494
|
+
|
|
495
|
+
if (leftSequence === null && rightSequence !== null) return 1
|
|
496
|
+
if (leftSequence !== null && rightSequence === null) return -1
|
|
497
|
+
if (leftSequence !== rightSequence) return rightSequence - leftSequence
|
|
498
|
+
|
|
499
|
+
return left.id().localeCompare(right.id())
|
|
500
|
+
}
|
|
501
|
+
|
|
437
502
|
/**
|
|
438
503
|
* Resolves a model class's active publish declaration from `static sync`.
|
|
439
504
|
* Opted-out (`publish: false`) and undeclared models resolve to null; every
|