velocious 1.0.663 → 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.
Files changed (50) hide show
  1. package/README.md +2 -2
  2. package/build/background-jobs/client.js +36 -6
  3. package/build/configuration-types.js +3 -3
  4. package/build/database/query/alter-table-base.js +11 -1
  5. package/build/src/background-jobs/client.d.ts.map +1 -1
  6. package/build/src/background-jobs/client.js +35 -6
  7. package/build/src/configuration-types.d.ts +8 -4
  8. package/build/src/configuration-types.d.ts.map +1 -1
  9. package/build/src/configuration-types.js +4 -4
  10. package/build/src/database/query/alter-table-base.d.ts.map +1 -1
  11. package/build/src/database/query/alter-table-base.js +12 -2
  12. package/build/src/sync/sync-api-client.d.ts +36 -10
  13. package/build/src/sync/sync-api-client.d.ts.map +1 -1
  14. package/build/src/sync/sync-api-client.js +58 -14
  15. package/build/src/sync/sync-client-types.d.ts +41 -2
  16. package/build/src/sync/sync-client-types.d.ts.map +1 -1
  17. package/build/src/sync/sync-client-types.js +20 -3
  18. package/build/src/sync/sync-client.d.ts +112 -3
  19. package/build/src/sync/sync-client.d.ts.map +1 -1
  20. package/build/src/sync/sync-client.js +306 -60
  21. package/build/src/sync/sync-publisher-types.d.ts +36 -3
  22. package/build/src/sync/sync-publisher-types.d.ts.map +1 -1
  23. package/build/src/sync/sync-publisher-types.js +16 -2
  24. package/build/src/sync/sync-publisher.d.ts +22 -3
  25. package/build/src/sync/sync-publisher.d.ts.map +1 -1
  26. package/build/src/sync/sync-publisher.js +134 -13
  27. package/build/src/sync/sync-realtime-bridge.d.ts +11 -5
  28. package/build/src/sync/sync-realtime-bridge.d.ts.map +1 -1
  29. package/build/src/sync/sync-realtime-bridge.js +37 -13
  30. package/build/src/sync/sync-scope-store.d.ts +32 -0
  31. package/build/src/sync/sync-scope-store.d.ts.map +1 -1
  32. package/build/src/sync/sync-scope-store.js +74 -4
  33. package/build/sync/sync-api-client.js +58 -13
  34. package/build/sync/sync-client-types.js +22 -2
  35. package/build/sync/sync-client.js +333 -63
  36. package/build/sync/sync-publisher-types.js +17 -1
  37. package/build/sync/sync-publisher.js +156 -15
  38. package/build/sync/sync-realtime-bridge.js +37 -12
  39. package/build/sync/sync-scope-store.js +79 -3
  40. package/package.json +1 -1
  41. package/src/background-jobs/client.js +36 -6
  42. package/src/configuration-types.js +3 -3
  43. package/src/database/query/alter-table-base.js +11 -1
  44. package/src/sync/sync-api-client.js +58 -13
  45. package/src/sync/sync-client-types.js +22 -2
  46. package/src/sync/sync-client.js +333 -63
  47. package/src/sync/sync-publisher-types.js +17 -1
  48. package/src/sync/sync-publisher.js +156 -15
  49. package/src/sync/sync-realtime-bridge.js +37 -12
  50. package/src/sync/sync-scope-store.js +79 -3
@@ -204,11 +204,12 @@ export default class SyncScopeStore {
204
204
  this._assertScopeRow(scopeRow);
205
205
  await this.ensureReady();
206
206
  if (this._usesMemoryStorage()) {
207
- return this._memoryScopes.get(scopeRow.scopeDigest)?.cursorPayload ?? null;
207
+ const currentScope = this._memoryScopes.get(scopeRow.scopeDigest);
208
+ return currentScope?.id === scopeRow.id ? currentScope.cursorPayload : null;
208
209
  }
209
210
  return await this._withDb(async (db) => {
210
211
  const row = await this._rowByScopeDigest(db, scopeRow.scopeDigest);
211
- return row ? row.cursorPayload : null;
212
+ return row?.id === scopeRow.id ? row.cursorPayload : null;
212
213
  });
213
214
  }
214
215
  /**
@@ -227,12 +228,14 @@ export default class SyncScopeStore {
227
228
  const memoryScope = this._memoryScopes.get(scopeRow.scopeDigest);
228
229
  if (!memoryScope)
229
230
  throw new Error(`No sync scope found for: ${scopeRow.scopeDigest}`);
231
+ if (memoryScope.id !== scopeRow.id || memoryScope.state !== "active")
232
+ return;
230
233
  memoryScope.cursorPayload = cursorPayload;
231
234
  return;
232
235
  }
233
236
  await this._withDb(async (db) => {
234
237
  await db.update({
235
- conditions: { scope_digest: scopeRow.scopeDigest },
238
+ conditions: { id: scopeRow.id, scope_digest: scopeRow.scopeDigest, state: "active" },
236
239
  data: { cursor_json: cursorPayload, updated_at: new Date() },
237
240
  tableName: TABLE_NAME
238
241
  });
@@ -256,6 +259,73 @@ export default class SyncScopeStore {
256
259
  await db.update({ conditions: { scope_digest: digest }, data: { state: "removed", updated_at: new Date() }, tableName: TABLE_NAME });
257
260
  });
258
261
  }
262
+ /**
263
+ * Atomically deactivates selected scopes, clears their cursors and rotates
264
+ * their row identities. A cursor save carrying a pre-reset row identity can
265
+ * therefore never repopulate the reset scope. The optional cleanup hook runs
266
+ * inside the same database transaction, allowing an app to purge the local
267
+ * rows owned by those scopes without a cursor/cache split.
268
+ * @param {import("./sync-client-types.js").SerializedSyncScope[]} scopes - Selected scopes to reset.
269
+ * @param {object} [options] - Reset options.
270
+ * @param {(args: {connection: import("../database/drivers/base.js").default | null, scopes: import("./sync-client-types.js").SerializedSyncScope[]}) => Promise<void> | void} [options.cleanup] - App-owned local-row cleanup hook.
271
+ * @returns {Promise<void>}
272
+ */
273
+ async reset(scopes, { cleanup } = {}) {
274
+ if (!Array.isArray(scopes) || scopes.length === 0)
275
+ throw new Error("SyncScopeStore.reset requires at least one serialized scope");
276
+ if (cleanup !== undefined && typeof cleanup !== "function")
277
+ throw new Error("SyncScopeStore.reset cleanup must be a function");
278
+ await this.ensureReady();
279
+ const uniqueScopes = [...new Map(scopes.map((scope) => [scopeDigestForScope(scope), scope])).values()];
280
+ if (this._usesMemoryStorage()) {
281
+ if (cleanup)
282
+ await cleanup({ connection: null, scopes: uniqueScopes });
283
+ for (const scope of uniqueScopes)
284
+ this._resetMemoryScope(scope);
285
+ return;
286
+ }
287
+ await this._withDb(async (db) => {
288
+ await db.transaction(async () => {
289
+ if (cleanup)
290
+ await cleanup({ connection: db, scopes: uniqueScopes });
291
+ for (const scope of uniqueScopes)
292
+ await this._resetDatabaseScope({ db, scope });
293
+ });
294
+ });
295
+ }
296
+ /**
297
+ * Resets one memory-backed scope while preserving repeated-reset idempotence.
298
+ * @param {import("./sync-client-types.js").SerializedSyncScope} scope - Scope to reset.
299
+ * @returns {void}
300
+ */
301
+ _resetMemoryScope(scope) {
302
+ const digest = scopeDigestForScope(scope);
303
+ const memoryScope = this._memoryScopes.get(digest);
304
+ if (!memoryScope || (memoryScope.state === "removed" && memoryScope.cursorPayload === null))
305
+ return;
306
+ this._memoryScopes.set(digest, {
307
+ ...memoryScope,
308
+ cursorPayload: null,
309
+ id: new UUID(4).format(),
310
+ state: "removed"
311
+ });
312
+ }
313
+ /**
314
+ * Resets one database-backed scope while preserving repeated-reset idempotence.
315
+ * @param {{db: import("../database/drivers/base.js").default, scope: import("./sync-client-types.js").SerializedSyncScope}} args - Database and scope.
316
+ * @returns {Promise<void>}
317
+ */
318
+ async _resetDatabaseScope({ db, scope }) {
319
+ const digest = scopeDigestForScope(scope);
320
+ const existingRow = await this._rowByScopeDigest(db, digest);
321
+ if (!existingRow || (existingRow.state === "removed" && existingRow.cursorPayload === null))
322
+ return;
323
+ await db.update({
324
+ conditions: { id: existingRow.id, scope_digest: digest },
325
+ data: { cursor_json: null, id: new UUID(4).format(), state: "removed", updated_at: new Date() },
326
+ tableName: TABLE_NAME
327
+ });
328
+ }
259
329
  /**
260
330
  * Whether the store runs without a configured database.
261
331
  * @returns {boolean} Whether memory storage is used.
@@ -349,4 +419,4 @@ export default class SyncScopeStore {
349
419
  }
350
420
  }
351
421
  }
352
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1zY29wZS1zdG9yZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zeW5jL3N5bmMtc2NvcGUtc3RvcmUuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sU0FBUyxNQUFNLGlDQUFpQyxDQUFBO0FBQ3ZELE9BQU8sSUFBSSxNQUFNLFdBQVcsQ0FBQTtBQUU1QixPQUFPLEVBQUMsUUFBUSxFQUFDLE1BQU0sa0JBQWtCLENBQUE7QUFDekMsT0FBTyxtQkFBbUIsTUFBTSxrQkFBa0IsQ0FBQTtBQUVsRDs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLFVBQVUsR0FBRyx1QkFBdUIsQ0FBQTtBQUMxQyxNQUFNLG1CQUFtQixHQUFHLHVCQUF1QixDQUFBO0FBRW5EOzs7OztHQUtHO0FBQ0gsU0FBUyxtQkFBbUIsQ0FBQyxLQUFLO0lBQ2hDLE9BQU8sSUFBSSxJQUFJLENBQUMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxHQUFHLG1CQUFtQixHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUE7QUFDbkYsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQU8sY0FBYztJQUNqQzs7Ozs7O09BTUc7SUFDSCxZQUFZLEVBQUMsYUFBYSxFQUFFLGtCQUFrQixHQUFHLFNBQVMsRUFBRSxZQUFZLEVBQUM7UUFDdkUsSUFBSSxZQUFZO1lBQUUsWUFBWSxDQUFDLG1CQUFtQixDQUFDLGFBQWEsQ0FBQyxDQUFBO1FBRWpFLElBQUksQ0FBQyxhQUFhLEdBQUcsYUFBYSxDQUFBO1FBQ2xDLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxrQkFBa0IsQ0FBQTtRQUM1QyxJQUFJLENBQUMsWUFBWSxHQUFHLFlBQVksQ0FBQTtRQUNoQyxJQUFJLENBQUMsYUFBYSxHQUFHLFlBQVk7WUFDL0IsQ0FBQyxDQUFDLFlBQVksQ0FBQyxnQkFBZ0IsQ0FBQyxrQkFBa0IsQ0FBQztZQUNuRCxDQUFDLENBQUMsaUJBQWlCLGtCQUFrQixFQUFFLENBQUE7UUFDekMsd0NBQXdDO1FBQ3hDLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQTtRQUM5QixJQUFJLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQTtRQUNyQixtQ0FBbUM7UUFDbkMsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUE7UUFDekIsMEhBQTBIO1FBQzFILElBQUksQ0FBQyx5QkFBeUIsR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFBO0lBQ2hELENBQUM7SUFFRDs7O09BR0c7SUFDSCxLQUFLLENBQUMsV0FBVztRQUNmLElBQUksSUFBSSxDQUFDLFFBQVE7WUFBRSxPQUFNO1FBRXpCLElBQUksSUFBSSxDQUFDLGtCQUFrQixFQUFFLEVBQUUsQ0FBQztZQUM5QixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQTtZQUNwQixPQUFNO1FBQ1IsQ0FBQztRQUVELE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxNQUFNLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFBO0lBQ3JFLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsS0FBSyxDQUFDLGtCQUFrQixDQUFDLEVBQUU7UUFDekIsSUFBSSxJQUFJLENBQUMsUUFBUTtZQUFFLE9BQU07UUFFekIsTUFBTSxxQkFBcUIsR0FBRyxFQUFFLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLHFCQUFxQixFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQTtRQUN4RixNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUE7UUFFL0QsSUFBSSxxQkFBcUIsSUFBSSxnQkFBZ0IsRUFBRSxVQUFVLEtBQUsscUJBQXFCLEVBQUUsQ0FBQztZQUNwRixNQUFNLGdCQUFnQixDQUFDLE9BQU8sQ0FBQTtZQUM5QixPQUFNO1FBQ1IsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQ3ZCLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUE7WUFFdkMsTUFBTSxZQUFZLENBQUE7WUFDbEIsSUFBSSxJQUFJLENBQUMsYUFBYSxLQUFLLFlBQVk7Z0JBQUUsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUE7WUFDbEUsSUFBSSxJQUFJLENBQUMsUUFBUTtnQkFBRSxPQUFNO1lBRXpCLE1BQU0sSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFBO1lBQ3hCLE9BQU07UUFDUixDQUFDO1FBRUQsSUFBSSxxQkFBcUIsRUFBRSxDQUFDO1lBQzFCLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsQ0FBQyxDQUFBO1lBQ3JELE1BQU0sdUJBQXVCLEdBQUcsaUJBQWlCLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFBO1lBRXZFLE1BQU0sbUJBQW1CLEdBQUcsaUJBQWlCLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtnQkFDbkUsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO29CQUNiLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFBO29CQUNwQixPQUFNO2dCQUNSLENBQUM7Z0JBRUQsTUFBTSxxQkFBcUIsQ0FBQTtZQUM3QixDQUFDLENBQUMsQ0FBQTtZQUVGLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUMsVUFBVSxFQUFFLHFCQUFxQixFQUFFLE9BQU8sRUFBRSx1QkFBdUIsRUFBQyxDQUFDLENBQUE7WUFDN0csSUFBSSxDQUFDLGFBQWEsR0FBRyxtQkFBbUIsQ0FBQTtZQUN4QyxNQUFNLHVCQUF1QixDQUFBO1lBQzdCLE9BQU07UUFDUixDQUFDO1FBRUQsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUN6RCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQTtRQUN0QixDQUFDLENBQUMsQ0FBQTtRQUVGLElBQUksQ0FBQztZQUNILE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQTtRQUMxQixDQUFDO2dCQUFTLENBQUM7WUFDVCxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVE7Z0JBQUUsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUE7UUFDL0MsQ0FBQztJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsS0FBSyxDQUFDLGlCQUFpQixDQUFDLEtBQUs7UUFDM0IsTUFBTSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUE7UUFFeEIsTUFBTSxNQUFNLEdBQUcsbUJBQW1CLENBQUMsS0FBSyxDQUFDLENBQUE7UUFFekMsSUFBSSxJQUFJLENBQUMsa0JBQWtCLEVBQUUsRUFBRSxDQUFDO1lBQzlCLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1lBRXBELElBQUksYUFBYSxFQUFFLENBQUM7Z0JBQ2xCLElBQUksYUFBYSxDQUFDLEtBQUssS0FBSyxRQUFRO29CQUFFLGFBQWEsQ0FBQyxLQUFLLEdBQUcsUUFBUSxDQUFBO2dCQUVwRSxPQUFPLGFBQWEsQ0FBQTtZQUN0QixDQUFDO1lBRUQsTUFBTSxRQUFRLEdBQUc7Z0JBQ2YsVUFBVSxFQUFFLEtBQUssQ0FBQyxVQUFVO2dCQUM1QixhQUFhLEVBQUUsSUFBSTtnQkFDbkIsRUFBRSxFQUFFLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRTtnQkFDeEIsWUFBWSxFQUFFLEtBQUssQ0FBQyxZQUFZLElBQUksSUFBSTtnQkFDeEMsV0FBVyxFQUFFLE1BQU07Z0JBQ25CLEtBQUssRUFBRSxRQUFRO2dCQUNmLGFBQWEsRUFBRSxJQUFJLENBQUMsYUFBYTthQUNsQyxDQUFBO1lBRUQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFBO1lBRXhDLE9BQU8sUUFBUSxDQUFBO1FBQ2pCLENBQUM7UUFFRCxPQUFPLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEVBQUU7WUFDckMsTUFBTSxXQUFXLEdBQUcsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFBO1lBRTVELElBQUksV0FBVyxFQUFFLENBQUM7Z0JBQ2hCLElBQUksV0FBVyxDQUFDLEtBQUssS0FBSyxRQUFRLEVBQUUsQ0FBQztvQkFDbkMsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUMsVUFBVSxFQUFFLEVBQUMsRUFBRSxFQUFFLFdBQVcsQ0FBQyxFQUFFLEVBQUMsRUFBRSxJQUFJLEVBQUUsRUFBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxJQUFJLElBQUksRUFBRSxFQUFDLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBQyxDQUFDLENBQUE7b0JBQzNILFdBQVcsQ0FBQyxLQUFLLEdBQUcsUUFBUSxDQUFBO2dCQUM5QixDQUFDO2dCQUVELE9BQU8sV0FBVyxDQUFBO1lBQ3BCLENBQUM7WUFFRCxNQUFNLEVBQUUsQ0FBQyxNQUFNLENBQUM7Z0JBQ2QsU0FBUyxFQUFFLFVBQVU7Z0JBQ3JCLElBQUksRUFBRTtvQkFDSixlQUFlLEVBQUUsbUJBQW1CLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQztvQkFDdEQsVUFBVSxFQUFFLElBQUksSUFBSSxFQUFFO29CQUN0QixXQUFXLEVBQUUsSUFBSTtvQkFDakIsRUFBRSxFQUFFLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRTtvQkFDeEIsaUZBQWlGO29CQUNqRixpRUFBaUU7b0JBQ2pFLGFBQWEsRUFBRSxLQUFLLENBQUMsWUFBWSxJQUFJLEVBQUU7b0JBQ3ZDLFlBQVksRUFBRSxNQUFNO29CQUNwQixLQUFLLEVBQUUsUUFBUTtvQkFDZixVQUFVLEVBQUUsSUFBSSxJQUFJLEVBQUU7aUJBQ3ZCO2FBQ0YsQ0FBQyxDQUFBO1lBRUYsTUFBTSxVQUFVLEdBQUcsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFBO1lBRTNELElBQUksQ0FBQyxVQUFVO2dCQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsOEJBQThCLENBQUMsQ0FBQTtZQUVoRSxPQUFPLFVBQVUsQ0FBQTtRQUNuQixDQUFDLENBQUMsQ0FBQTtJQUNKLENBQUM7SUFFRDs7O09BR0c7SUFDSCxLQUFLLENBQUMsWUFBWTtRQUNoQixNQUFNLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQTtRQUV4QixJQUFJLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxFQUFFLENBQUM7WUFDOUIsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLEtBQUssS0FBSyxRQUFRLENBQUMsQ0FBQTtRQUNyRixDQUFDO1FBRUQsT0FBTyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxFQUFFO1lBQ3JDLE1BQU0sSUFBSSxHQUFHLG1FQUFtRSxDQUFDLENBQUMsTUFBTSxFQUFFO2lCQUN2RixRQUFRLEVBQUU7aUJBQ1YsSUFBSSxDQUFDLFVBQVUsQ0FBQztpQkFDaEIsS0FBSyxDQUFDLEVBQUMsS0FBSyxFQUFFLFFBQVEsRUFBQyxDQUFDO2lCQUN4QixLQUFLLENBQUMsZ0JBQWdCLENBQUM7aUJBQ3ZCLE9BQU8sRUFBRSxDQUFDLENBQUE7WUFFYixPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFBO1FBQ3hELENBQUMsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxLQUFLLENBQUMsVUFBVSxDQUFDLFFBQVE7UUFDdkIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxRQUFRLENBQUMsQ0FBQTtRQUM5QixNQUFNLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQTtRQUV4QixJQUFJLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxFQUFFLENBQUM7WUFDOUIsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLEVBQUUsYUFBYSxJQUFJLElBQUksQ0FBQTtRQUM1RSxDQUFDO1FBRUQsT0FBTyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxFQUFFO1lBQ3JDLE1BQU0sR0FBRyxHQUFHLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDLEVBQUUsRUFBRSxRQUFRLENBQUMsV0FBVyxDQUFDLENBQUE7WUFFbEUsT0FBTyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQTtRQUN2QyxDQUFDLENBQUMsQ0FBQTtJQUNKLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILEtBQUssQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLE1BQU07UUFDL0IsSUFBSSxDQUFDLGVBQWUsQ0FBQyxRQUFRLENBQUMsQ0FBQTtRQUM5QixJQUFJLENBQUMsTUFBTTtZQUFFLE9BQU07UUFFbkIsTUFBTSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUE7UUFFeEIsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQTtRQUU1QyxJQUFJLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxFQUFFLENBQUM7WUFDOUIsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFBO1lBRWhFLElBQUksQ0FBQyxXQUFXO2dCQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsNEJBQTRCLFFBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFBO1lBRXJGLFdBQVcsQ0FBQyxhQUFhLEdBQUcsYUFBYSxDQUFBO1lBQ3pDLE9BQU07UUFDUixDQUFDO1FBRUQsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsRUFBRTtZQUM5QixNQUFNLEVBQUUsQ0FBQyxNQUFNLENBQUM7Z0JBQ2QsVUFBVSxFQUFFLEVBQUMsWUFBWSxFQUFFLFFBQVEsQ0FBQyxXQUFXLEVBQUM7Z0JBQ2hELElBQUksRUFBRSxFQUFDLFdBQVcsRUFBRSxhQUFhLEVBQUUsVUFBVSxFQUFFLElBQUksSUFBSSxFQUFFLEVBQUM7Z0JBQzFELFNBQVMsRUFBRSxVQUFVO2FBQ3RCLENBQUMsQ0FBQTtRQUNKLENBQUMsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxLQUFLLENBQUMsVUFBVSxDQUFDLEtBQUs7UUFDcEIsTUFBTSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUE7UUFFeEIsTUFBTSxNQUFNLEdBQUcsbUJBQW1CLENBQUMsS0FBSyxDQUFDLENBQUE7UUFFekMsSUFBSSxJQUFJLENBQUMsa0JBQWtCLEVBQUUsRUFBRSxDQUFDO1lBQzlCLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1lBRWxELElBQUksV0FBVztnQkFBRSxXQUFXLENBQUMsS0FBSyxHQUFHLFNBQVMsQ0FBQTtZQUU5QyxPQUFNO1FBQ1IsQ0FBQztRQUVELE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEVBQUU7WUFDOUIsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUMsVUFBVSxFQUFFLEVBQUMsWUFBWSxFQUFFLE1BQU0sRUFBQyxFQUFFLElBQUksRUFBRSxFQUFDLEtBQUssRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLElBQUksSUFBSSxFQUFFLEVBQUMsRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFDLENBQUMsQ0FBQTtRQUNoSSxDQUFDLENBQUMsQ0FBQTtJQUNKLENBQUM7SUFFRDs7O09BR0c7SUFDSCxrQkFBa0I7UUFDaEIsSUFBSSxDQUFDO1lBQ0gsT0FBTyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsd0JBQXdCLEVBQUUsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQTtRQUNoRixDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsT0FBTyxJQUFJLENBQUE7UUFDYixDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRO1FBQ3BCLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3RCLE9BQU8sTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDLGlCQUFpQixDQUFDLEVBQUMsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLGtCQUFrQixFQUFFLElBQUksRUFBRSx5QkFBeUIsRUFBQyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsRUFBRTtnQkFDbkosT0FBTyxNQUFNLFFBQVEsQ0FBQyxTQUFTLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQTtZQUMvQyxDQUFDLENBQUMsQ0FBQTtRQUNKLENBQUM7UUFFRCxPQUFPLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFDLG1CQUFtQixFQUFFLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsSUFBSSxFQUFFLGtCQUFrQixFQUFDLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxFQUFFO1lBQzFJLE1BQU0sRUFBRSxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQTtZQUV2QyxJQUFJLENBQUMsRUFBRTtnQkFBRSxNQUFNLElBQUksS0FBSyxDQUFDLG9EQUFvRCxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQyxDQUFBO1lBRXZHLE9BQU8sTUFBTSxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUE7UUFDM0IsQ0FBQyxDQUFDLENBQUE7SUFDSixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFO1FBQ3pCLElBQUksTUFBTSxFQUFFLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQztZQUFFLE9BQU8sS0FBSyxDQUFBO1FBRWxELE1BQU0sS0FBSyxHQUFHLElBQUksU0FBUyxDQUFDLFVBQVUsRUFBRSxFQUFDLFdBQVcsRUFBRSxJQUFJLEVBQUMsQ0FBQyxDQUFBO1FBRTVELEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLEVBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFDLENBQUMsQ0FBQTtRQUNuRCxLQUFLLENBQUMsTUFBTSxDQUFDLGNBQWMsRUFBRSxFQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBQyxDQUFDLENBQUE7UUFDeEQsS0FBSyxDQUFDLE1BQU0sQ0FBQyxlQUFlLEVBQUUsRUFBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUMsQ0FBQyxDQUFBO1FBQ3pELEtBQUssQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsRUFBQyxJQUFJLEVBQUUsS0FBSyxFQUFDLENBQUMsQ0FBQTtRQUM1QyxLQUFLLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxFQUFDLElBQUksRUFBRSxJQUFJLEVBQUMsQ0FBQyxDQUFBO1FBQ3ZDLEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLEVBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFDLENBQUMsQ0FBQTtRQUNqRCxLQUFLLENBQUMsUUFBUSxDQUFDLFlBQVksRUFBRSxFQUFDLElBQUksRUFBRSxLQUFLLEVBQUMsQ0FBQyxDQUFBO1FBQzNDLEtBQUssQ0FBQyxRQUFRLENBQUMsWUFBWSxFQUFFLEVBQUMsSUFBSSxFQUFFLEtBQUssRUFBQyxDQUFDLENBQUE7UUFFM0MsTUFBTSxFQUFFLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBRTNCLE9BQU8sSUFBSSxDQUFBO0lBQ2IsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsS0FBSyxDQUFDLGlCQUFpQixDQUFDLEVBQUUsRUFBRSxNQUFNO1FBQ2hDLE1BQU0sSUFBSSxHQUFHLG1FQUFtRSxDQUFDLENBQUMsTUFBTSxFQUFFO2FBQ3ZGLFFBQVEsRUFBRTthQUNWLElBQUksQ0FBQyxVQUFVLENBQUM7YUFDaEIsS0FBSyxDQUFDLEVBQUMsWUFBWSxFQUFFLE1BQU0sRUFBQyxDQUFDO2FBQzdCLEtBQUssQ0FBQyxDQUFDLENBQUM7YUFDUixPQUFPLEVBQUUsQ0FBQyxDQUFBO1FBRWIsT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFBO0lBQzFELENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsa0JBQWtCLENBQUMsR0FBRztRQUNwQixPQUFPO1lBQ0wsVUFBVSxFQUFFLDREQUE0RCxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUM7WUFDbEgsYUFBYSxFQUFFLEdBQUcsQ0FBQyxXQUFXLEtBQUssSUFBSSxJQUFJLEdBQUcsQ0FBQyxXQUFXLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDO1lBQ3pHLEVBQUUsRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUNsQixZQUFZLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUM7WUFDakYsV0FBVyxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDO1lBQ3JDLEtBQUssRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQztZQUN4QixhQUFhLEVBQUUsSUFBSSxDQUFDLGFBQWE7U0FDbEMsQ0FBQTtJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsZUFBZSxDQUFDLFFBQVE7UUFDdEIsSUFBSSxRQUFRLENBQUMsYUFBYSxLQUFLLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUNsRCxNQUFNLElBQUksS0FBSyxDQUFDLDREQUE0RCxDQUFDLENBQUE7UUFDL0UsQ0FBQztJQUNILENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgVGFibGVEYXRhIGZyb20gXCIuLi9kYXRhYmFzZS90YWJsZS1kYXRhL2luZGV4LmpzXCJcbmltcG9ydCBVVUlEIGZyb20gXCJwdXJlLXV1aWRcIlxuXG5pbXBvcnQge3Njb3BlS2V5fSBmcm9tIFwiLi9xdWVyeS1zY29wZS5qc1wiXG5pbXBvcnQgc3RhYmxlSnNvblN0cmluZ2lmeSBmcm9tIFwiLi9zdGFibGUtanNvbi5qc1wiXG5cbi8qKlxuICogQHR5cGVkZWYge29iamVjdH0gU3luY1Njb3BlUm93XG4gKiBAcHJvcGVydHkge1JlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pn0gY29uZGl0aW9ucyAtIFNjb3BlIGF0dHJpYnV0ZSBjb25kaXRpb25zLlxuICogQHByb3BlcnR5IHtzdHJpbmcgfCBudWxsfSBjdXJzb3JQYXlsb2FkIC0gUGVyc2lzdGVkIGN1cnNvciBKU09OIHBheWxvYWQuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gaWQgLSBTY29wZSByb3cgaWQuXG4gKiBAcHJvcGVydHkge3N0cmluZyB8IG51bGx9IHJlc291cmNlVHlwZSAtIFNjb3BlIHJlc291cmNlL21vZGVsIG5hbWUsIG9yIG51bGwgZm9yIHRoZSBhbGwtdHlwZXMgKHVzZXIpIHNjb3BlLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IHNjb3BlRGlnZXN0IC0gRml4ZWQtc2l6ZSBkZXRlcm1pbmlzdGljIGRpZ2VzdCBvZiB0aGUgY2Fub25pY2FsIHNjb3BlIGtleS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBzdGF0ZSAtIFNjb3BlIHN0YXRlIChcImFjdGl2ZVwiIG9yIFwicmVtb3ZlZFwiKS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBzdG9yZUlkZW50aXR5IC0gUGh5c2ljYWwgc3RvcmUgaWRlbnRpdHkgb3duaW5nIHRoaXMgcm93LlxuICovXG5jb25zdCBUQUJMRV9OQU1FID0gXCJ2ZWxvY2lvdXNfc3luY19zY29wZXNcIlxuY29uc3QgU0NPUEVfRElHRVNUX1BSRUZJWCA9IFwidmVsb2Npb3VzLXN5bmMtc2NvcGU6XCJcblxuLyoqXG4gKiBEaWdlc3RzIGEgc2VyaWFsaXplZCBzY29wZSBpbnRvIGEgZml4ZWQtc2l6ZSBkZXRlcm1pbmlzdGljIGtleSwgc28gc2NvcGVcbiAqIGlkZW50aXRpZXMgd2l0aCBsb25nIGNvbmRpdGlvbiB2YWx1ZXMgZml0IGFuIGluZGV4ZWQgc3RyaW5nIGNvbHVtbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zeW5jLWNsaWVudC10eXBlcy5qc1wiKS5TZXJpYWxpemVkU3luY1Njb3BlfSBzY29wZSAtIFNlcmlhbGl6ZWQgc3luYyBzY29wZS5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IERldGVybWluaXN0aWMgVVVJRHY1IGRpZ2VzdCBvZiB0aGUgY2Fub25pY2FsIHNjb3BlIGtleS5cbiAqL1xuZnVuY3Rpb24gc2NvcGVEaWdlc3RGb3JTY29wZShzY29wZSkge1xuICByZXR1cm4gbmV3IFVVSUQoNSwgXCJuczpVUkxcIiwgYCR7U0NPUEVfRElHRVNUX1BSRUZJWH0ke3Njb3BlS2V5KHNjb3BlKX1gKS5mb3JtYXQoKVxufVxuXG4vKipcbiAqIEZyYW1ld29yay1vd25lZCBsb2NhbCBwZXJzaXN0ZW5jZSBmb3IgZGVjbGFyZWQgc3luYyBzY29wZXMgYW5kIHRoZWlyIGN1cnNvcnMuXG4gKlxuICogQmFja2VkIGJ5IGFuIGF1dG8tY3JlYXRlZCBgdmVsb2Npb3VzX3N5bmNfc2NvcGVzYCB0YWJsZSBvbiB0aGUgY29uZmlndXJlZFxuICogZGF0YWJhc2UsIHdpdGggYSBwcm9jZXNzLWxvY2FsIG1lbW9yeSBmYWxsYmFjayB3aGVuIG5vIGRhdGFiYXNlIGlzXG4gKiBjb25maWd1cmVkIChtaXJyb3JpbmcgdGhlIHNlcnZlciBjaGFuZ2UtZmVlZCBzdG9yZSkuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFN5bmNTY29wZVN0b3JlIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBzeW5jIHNjb3BlIHN0b3JlLlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIE9wdGlvbnMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi5qc1wiKS5kZWZhdWx0fSBhcmdzLmNvbmZpZ3VyYXRpb24gLSBDb25maWd1cmF0aW9uIG93bmluZyB0aGUgZGF0YWJhc2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbYXJncy5kYXRhYmFzZUlkZW50aWZpZXJdIC0gRGF0YWJhc2UgaWRlbnRpZmllci5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi90ZW5hbnRzL3RlbmFudC1oYW5kbGUuanNcIikuZGVmYXVsdH0gW2FyZ3MudGVuYW50SGFuZGxlXSAtIEltbXV0YWJsZSB0ZW5hbnQgaGFuZGxlIG93bmluZyB0aGUgcGh5c2ljYWwgc3RvcmUuXG4gICAqL1xuICBjb25zdHJ1Y3Rvcih7Y29uZmlndXJhdGlvbiwgZGF0YWJhc2VJZGVudGlmaWVyID0gXCJkZWZhdWx0XCIsIHRlbmFudEhhbmRsZX0pIHtcbiAgICBpZiAodGVuYW50SGFuZGxlKSB0ZW5hbnRIYW5kbGUuYXNzZXJ0Q29uZmlndXJhdGlvbihjb25maWd1cmF0aW9uKVxuXG4gICAgdGhpcy5jb25maWd1cmF0aW9uID0gY29uZmlndXJhdGlvblxuICAgIHRoaXMuZGF0YWJhc2VJZGVudGlmaWVyID0gZGF0YWJhc2VJZGVudGlmaWVyXG4gICAgdGhpcy50ZW5hbnRIYW5kbGUgPSB0ZW5hbnRIYW5kbGVcbiAgICB0aGlzLnN0b3JlSWRlbnRpdHkgPSB0ZW5hbnRIYW5kbGVcbiAgICAgID8gdGVuYW50SGFuZGxlLmRhdGFiYXNlSWRlbnRpdHkoZGF0YWJhc2VJZGVudGlmaWVyKVxuICAgICAgOiBgY29uZmlndXJhdGlvbjoke2RhdGFiYXNlSWRlbnRpZmllcn1gXG4gICAgLyoqIEB0eXBlIHtNYXA8c3RyaW5nLCBTeW5jU2NvcGVSb3c+fSAqL1xuICAgIHRoaXMuX21lbW9yeVNjb3BlcyA9IG5ldyBNYXAoKVxuICAgIHRoaXMuX2lzUmVhZHkgPSBmYWxzZVxuICAgIC8qKiBAdHlwZSB7UHJvbWlzZTx2b2lkPiB8IG51bGx9ICovXG4gICAgdGhpcy5fcmVhZHlQcm9taXNlID0gbnVsbFxuICAgIC8qKiBAdHlwZSB7V2Vha01hcDxpbXBvcnQoXCIuLi9kYXRhYmFzZS9kcml2ZXJzL2Jhc2UuanNcIikuZGVmYXVsdCwge2NvbXBsZXRpb246IFByb21pc2U8dm9pZD4sIHByb21pc2U6IFByb21pc2U8dm9pZD59Pn0gKi9cbiAgICB0aGlzLl90cmFuc2FjdGlvblJlYWR5UHJvbWlzZXMgPSBuZXcgV2Vha01hcCgpXG4gIH1cblxuICAvKipcbiAgICogRW5zdXJlcyB0aGUgYmFja2luZyB0YWJsZSBleGlzdHMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBSZXNvbHZlcyB3aGVuIHJlYWR5LlxuICAgKi9cbiAgYXN5bmMgZW5zdXJlUmVhZHkoKSB7XG4gICAgaWYgKHRoaXMuX2lzUmVhZHkpIHJldHVyblxuXG4gICAgaWYgKHRoaXMuX3VzZXNNZW1vcnlTdG9yYWdlKCkpIHtcbiAgICAgIHRoaXMuX2lzUmVhZHkgPSB0cnVlXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLl93aXRoRGIoYXN5bmMgKGRiKSA9PiBhd2FpdCB0aGlzLl9lbnN1cmVSZWFkeVdpdGhEYihkYikpXG4gIH1cblxuICAvKipcbiAgICogQ29vcmRpbmF0ZXMgZHVyYWJsZSBhbmQgdHJhbnNhY3Rpb24tbG9jYWwgcmVhZGluZXNzIG9uIG9uZSBjb25uZWN0aW9uLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2RhdGFiYXNlL2RyaXZlcnMvYmFzZS5qc1wiKS5kZWZhdWx0fSBkYiAtIERhdGFiYXNlIGNvbm5lY3Rpb24uXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBSZXNvbHZlcyB3aGVuIHRoaXMgY2FsbGVyIGNhbiB1c2UgdGhlIHRhYmxlLlxuICAgKi9cbiAgYXN5bmMgX2Vuc3VyZVJlYWR5V2l0aERiKGRiKSB7XG4gICAgaWYgKHRoaXMuX2lzUmVhZHkpIHJldHVyblxuXG4gICAgY29uc3QgdHJhbnNhY3Rpb25Db21wbGV0aW9uID0gZGIuaW5zaWRlVHJhbnNhY3Rpb24oKSA/IGRiLnRyYW5zYWN0aW9uQ29tcGxldGlvbigpIDogbnVsbFxuICAgIGNvbnN0IHRyYW5zYWN0aW9uUmVhZHkgPSB0aGlzLl90cmFuc2FjdGlvblJlYWR5UHJvbWlzZXMuZ2V0KGRiKVxuXG4gICAgaWYgKHRyYW5zYWN0aW9uQ29tcGxldGlvbiAmJiB0cmFuc2FjdGlvblJlYWR5Py5jb21wbGV0aW9uID09PSB0cmFuc2FjdGlvbkNvbXBsZXRpb24pIHtcbiAgICAgIGF3YWl0IHRyYW5zYWN0aW9uUmVhZHkucHJvbWlzZVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX3JlYWR5UHJvbWlzZSkge1xuICAgICAgY29uc3QgcmVhZHlQcm9taXNlID0gdGhpcy5fcmVhZHlQcm9taXNlXG5cbiAgICAgIGF3YWl0IHJlYWR5UHJvbWlzZVxuICAgICAgaWYgKHRoaXMuX3JlYWR5UHJvbWlzZSA9PT0gcmVhZHlQcm9taXNlKSB0aGlzLl9yZWFkeVByb21pc2UgPSBudWxsXG4gICAgICBpZiAodGhpcy5faXNSZWFkeSkgcmV0dXJuXG5cbiAgICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVhZHkoKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgaWYgKHRyYW5zYWN0aW9uQ29tcGxldGlvbikge1xuICAgICAgY29uc3QgdGFibGVSZWFkeVByb21pc2UgPSB0aGlzLl9lbnN1cmVTY29wZXNUYWJsZShkYilcbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uUmVhZHlQcm9taXNlID0gdGFibGVSZWFkeVByb21pc2UudGhlbigoKSA9PiB1bmRlZmluZWQpXG5cbiAgICAgIGNvbnN0IGR1cmFibGVSZWFkeVByb21pc2UgPSB0YWJsZVJlYWR5UHJvbWlzZS50aGVuKGFzeW5jIChjcmVhdGVkKSA9PiB7XG4gICAgICAgIGlmICghY3JlYXRlZCkge1xuICAgICAgICAgIHRoaXMuX2lzUmVhZHkgPSB0cnVlXG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCB0cmFuc2FjdGlvbkNvbXBsZXRpb25cbiAgICAgIH0pXG5cbiAgICAgIHRoaXMuX3RyYW5zYWN0aW9uUmVhZHlQcm9taXNlcy5zZXQoZGIsIHtjb21wbGV0aW9uOiB0cmFuc2FjdGlvbkNvbXBsZXRpb24sIHByb21pc2U6IHRyYW5zYWN0aW9uUmVhZHlQcm9taXNlfSlcbiAgICAgIHRoaXMuX3JlYWR5UHJvbWlzZSA9IGR1cmFibGVSZWFkeVByb21pc2VcbiAgICAgIGF3YWl0IHRyYW5zYWN0aW9uUmVhZHlQcm9taXNlXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICB0aGlzLl9yZWFkeVByb21pc2UgPSB0aGlzLl9lbnN1cmVTY29wZXNUYWJsZShkYikudGhlbigoKSA9PiB7XG4gICAgICB0aGlzLl9pc1JlYWR5ID0gdHJ1ZVxuICAgIH0pXG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5fcmVhZHlQcm9taXNlXG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGlmICghdGhpcy5faXNSZWFkeSkgdGhpcy5fcmVhZHlQcm9taXNlID0gbnVsbFxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kcyBvciBjcmVhdGVzIHRoZSBzY29wZSByb3cgZm9yIGEgc2VyaWFsaXplZCBzY29wZSwgcmVhY3RpdmF0aW5nIHJlbW92ZWQgc2NvcGVzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vc3luYy1jbGllbnQtdHlwZXMuanNcIikuU2VyaWFsaXplZFN5bmNTY29wZX0gc2NvcGUgLSBTZXJpYWxpemVkIHN5bmMgc2NvcGUuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFN5bmNTY29wZVJvdz59IFBlcnNpc3RlZCBzY29wZSByb3cuXG4gICAqL1xuICBhc3luYyBmaW5kT3JDcmVhdGVTY29wZShzY29wZSkge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVhZHkoKVxuXG4gICAgY29uc3QgZGlnZXN0ID0gc2NvcGVEaWdlc3RGb3JTY29wZShzY29wZSlcblxuICAgIGlmICh0aGlzLl91c2VzTWVtb3J5U3RvcmFnZSgpKSB7XG4gICAgICBjb25zdCBleGlzdGluZ1Njb3BlID0gdGhpcy5fbWVtb3J5U2NvcGVzLmdldChkaWdlc3QpXG5cbiAgICAgIGlmIChleGlzdGluZ1Njb3BlKSB7XG4gICAgICAgIGlmIChleGlzdGluZ1Njb3BlLnN0YXRlICE9PSBcImFjdGl2ZVwiKSBleGlzdGluZ1Njb3BlLnN0YXRlID0gXCJhY3RpdmVcIlxuXG4gICAgICAgIHJldHVybiBleGlzdGluZ1Njb3BlXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG5ld1Njb3BlID0ge1xuICAgICAgICBjb25kaXRpb25zOiBzY29wZS5jb25kaXRpb25zLFxuICAgICAgICBjdXJzb3JQYXlsb2FkOiBudWxsLFxuICAgICAgICBpZDogbmV3IFVVSUQoNCkuZm9ybWF0KCksXG4gICAgICAgIHJlc291cmNlVHlwZTogc2NvcGUucmVzb3VyY2VUeXBlID8/IG51bGwsXG4gICAgICAgIHNjb3BlRGlnZXN0OiBkaWdlc3QsXG4gICAgICAgIHN0YXRlOiBcImFjdGl2ZVwiLFxuICAgICAgICBzdG9yZUlkZW50aXR5OiB0aGlzLnN0b3JlSWRlbnRpdHlcbiAgICAgIH1cblxuICAgICAgdGhpcy5fbWVtb3J5U2NvcGVzLnNldChkaWdlc3QsIG5ld1Njb3BlKVxuXG4gICAgICByZXR1cm4gbmV3U2NvcGVcbiAgICB9XG5cbiAgICByZXR1cm4gYXdhaXQgdGhpcy5fd2l0aERiKGFzeW5jIChkYikgPT4ge1xuICAgICAgY29uc3QgZXhpc3RpbmdSb3cgPSBhd2FpdCB0aGlzLl9yb3dCeVNjb3BlRGlnZXN0KGRiLCBkaWdlc3QpXG5cbiAgICAgIGlmIChleGlzdGluZ1Jvdykge1xuICAgICAgICBpZiAoZXhpc3RpbmdSb3cuc3RhdGUgIT09IFwiYWN0aXZlXCIpIHtcbiAgICAgICAgICBhd2FpdCBkYi51cGRhdGUoe2NvbmRpdGlvbnM6IHtpZDogZXhpc3RpbmdSb3cuaWR9LCBkYXRhOiB7c3RhdGU6IFwiYWN0aXZlXCIsIHVwZGF0ZWRfYXQ6IG5ldyBEYXRlKCl9LCB0YWJsZU5hbWU6IFRBQkxFX05BTUV9KVxuICAgICAgICAgIGV4aXN0aW5nUm93LnN0YXRlID0gXCJhY3RpdmVcIlxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGV4aXN0aW5nUm93XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IGRiLmluc2VydCh7XG4gICAgICAgIHRhYmxlTmFtZTogVEFCTEVfTkFNRSxcbiAgICAgICAgZGF0YToge1xuICAgICAgICAgIGNvbmRpdGlvbnNfanNvbjogc3RhYmxlSnNvblN0cmluZ2lmeShzY29wZS5jb25kaXRpb25zKSxcbiAgICAgICAgICBjcmVhdGVkX2F0OiBuZXcgRGF0ZSgpLFxuICAgICAgICAgIGN1cnNvcl9qc29uOiBudWxsLFxuICAgICAgICAgIGlkOiBuZXcgVVVJRCg0KS5mb3JtYXQoKSxcbiAgICAgICAgICAvLyBUaGUgYWxsLXR5cGVzICh1c2VyKSBzY29wZSBoYXMgbm8gcmVzb3VyY2UgdHlwZTsgdGhlIGNvbHVtbiBpcyBub24tbnVsbCwgc28gaXRcbiAgICAgICAgICAvLyBzdG9yZXMgYXMgYW4gZW1wdHkgc3RyaW5nIGFuZCBub3JtYWxpemVzIGJhY2sgdG8gbnVsbCBvbiByZWFkLlxuICAgICAgICAgIHJlc291cmNlX3R5cGU6IHNjb3BlLnJlc291cmNlVHlwZSA/PyBcIlwiLFxuICAgICAgICAgIHNjb3BlX2RpZ2VzdDogZGlnZXN0LFxuICAgICAgICAgIHN0YXRlOiBcImFjdGl2ZVwiLFxuICAgICAgICAgIHVwZGF0ZWRfYXQ6IG5ldyBEYXRlKClcbiAgICAgICAgfVxuICAgICAgfSlcblxuICAgICAgY29uc3QgY3JlYXRlZFJvdyA9IGF3YWl0IHRoaXMuX3Jvd0J5U2NvcGVEaWdlc3QoZGIsIGRpZ2VzdClcblxuICAgICAgaWYgKCFjcmVhdGVkUm93KSB0aHJvdyBuZXcgRXJyb3IoXCJGYWlsZWQgdG8gcGVyc2lzdCBzeW5jIHNjb3BlXCIpXG5cbiAgICAgIHJldHVybiBjcmVhdGVkUm93XG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFsbCBhY3RpdmUgc2NvcGUgcm93cy5cbiAgICogQHJldHVybnMge1Byb21pc2U8U3luY1Njb3BlUm93W10+fSBBY3RpdmUgc2NvcGUgcm93cy5cbiAgICovXG4gIGFzeW5jIGFjdGl2ZVNjb3BlcygpIHtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlYWR5KClcblxuICAgIGlmICh0aGlzLl91c2VzTWVtb3J5U3RvcmFnZSgpKSB7XG4gICAgICByZXR1cm4gWy4uLnRoaXMuX21lbW9yeVNjb3Blcy52YWx1ZXMoKV0uZmlsdGVyKChzY29wZSkgPT4gc2NvcGUuc3RhdGUgPT09IFwiYWN0aXZlXCIpXG4gICAgfVxuXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuX3dpdGhEYihhc3luYyAoZGIpID0+IHtcbiAgICAgIGNvbnN0IHJvd3MgPSAvKiogQHR5cGUge0FycmF5PFJlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pj59ICovIChhd2FpdCBkYlxuICAgICAgICAubmV3UXVlcnkoKVxuICAgICAgICAuZnJvbShUQUJMRV9OQU1FKVxuICAgICAgICAud2hlcmUoe3N0YXRlOiBcImFjdGl2ZVwifSlcbiAgICAgICAgLm9yZGVyKFwiY3JlYXRlZF9hdCBBU0NcIilcbiAgICAgICAgLnJlc3VsdHMoKSlcblxuICAgICAgcmV0dXJuIHJvd3MubWFwKChyb3cpID0+IHRoaXMuX25vcm1hbGl6ZVNjb3BlUm93KHJvdykpXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2FkcyB0aGUgcGVyc2lzdGVkIGN1cnNvciBwYXlsb2FkIGZvciBhIHNjb3BlIHJvdy5cbiAgICogQHBhcmFtIHtTeW5jU2NvcGVSb3d9IHNjb3BlUm93IC0gU2NvcGUgcm93LlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmcgfCBudWxsPn0gQ3Vyc29yIEpTT04gcGF5bG9hZC5cbiAgICovXG4gIGFzeW5jIGxvYWRDdXJzb3Ioc2NvcGVSb3cpIHtcbiAgICB0aGlzLl9hc3NlcnRTY29wZVJvdyhzY29wZVJvdylcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlYWR5KClcblxuICAgIGlmICh0aGlzLl91c2VzTWVtb3J5U3RvcmFnZSgpKSB7XG4gICAgICByZXR1cm4gdGhpcy5fbWVtb3J5U2NvcGVzLmdldChzY29wZVJvdy5zY29wZURpZ2VzdCk/LmN1cnNvclBheWxvYWQgPz8gbnVsbFxuICAgIH1cblxuICAgIHJldHVybiBhd2FpdCB0aGlzLl93aXRoRGIoYXN5bmMgKGRiKSA9PiB7XG4gICAgICBjb25zdCByb3cgPSBhd2FpdCB0aGlzLl9yb3dCeVNjb3BlRGlnZXN0KGRiLCBzY29wZVJvdy5zY29wZURpZ2VzdClcblxuICAgICAgcmV0dXJuIHJvdyA/IHJvdy5jdXJzb3JQYXlsb2FkIDogbnVsbFxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogUGVyc2lzdHMgdGhlIGFja25vd2xlZGdlZCBjdXJzb3IgZm9yIGEgc2NvcGUgcm93LlxuICAgKiBAcGFyYW0ge1N5bmNTY29wZVJvd30gc2NvcGVSb3cgLSBTY29wZSByb3cuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zeW5jLWFwaS1jbGllbnQtdHlwZXMuanNcIikuU3luY0N1cnNvcn0gY3Vyc29yIC0gQWNrbm93bGVkZ2VkIGN1cnNvci5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBhc3luYyBzYXZlQ3Vyc29yKHNjb3BlUm93LCBjdXJzb3IpIHtcbiAgICB0aGlzLl9hc3NlcnRTY29wZVJvdyhzY29wZVJvdylcbiAgICBpZiAoIWN1cnNvcikgcmV0dXJuXG5cbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlYWR5KClcblxuICAgIGNvbnN0IGN1cnNvclBheWxvYWQgPSBKU09OLnN0cmluZ2lmeShjdXJzb3IpXG5cbiAgICBpZiAodGhpcy5fdXNlc01lbW9yeVN0b3JhZ2UoKSkge1xuICAgICAgY29uc3QgbWVtb3J5U2NvcGUgPSB0aGlzLl9tZW1vcnlTY29wZXMuZ2V0KHNjb3BlUm93LnNjb3BlRGlnZXN0KVxuXG4gICAgICBpZiAoIW1lbW9yeVNjb3BlKSB0aHJvdyBuZXcgRXJyb3IoYE5vIHN5bmMgc2NvcGUgZm91bmQgZm9yOiAke3Njb3BlUm93LnNjb3BlRGlnZXN0fWApXG5cbiAgICAgIG1lbW9yeVNjb3BlLmN1cnNvclBheWxvYWQgPSBjdXJzb3JQYXlsb2FkXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLl93aXRoRGIoYXN5bmMgKGRiKSA9PiB7XG4gICAgICBhd2FpdCBkYi51cGRhdGUoe1xuICAgICAgICBjb25kaXRpb25zOiB7c2NvcGVfZGlnZXN0OiBzY29wZVJvdy5zY29wZURpZ2VzdH0sXG4gICAgICAgIGRhdGE6IHtjdXJzb3JfanNvbjogY3Vyc29yUGF5bG9hZCwgdXBkYXRlZF9hdDogbmV3IERhdGUoKX0sXG4gICAgICAgIHRhYmxlTmFtZTogVEFCTEVfTkFNRVxuICAgICAgfSlcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIERlYWN0aXZhdGVzIHRoZSBzY29wZSByb3cgZm9yIGEgc2VyaWFsaXplZCBzY29wZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL3N5bmMtY2xpZW50LXR5cGVzLmpzXCIpLlNlcmlhbGl6ZWRTeW5jU2NvcGV9IHNjb3BlIC0gU2VyaWFsaXplZCBzeW5jIHNjb3BlLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGFzeW5jIGRlYWN0aXZhdGUoc2NvcGUpIHtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlYWR5KClcblxuICAgIGNvbnN0IGRpZ2VzdCA9IHNjb3BlRGlnZXN0Rm9yU2NvcGUoc2NvcGUpXG5cbiAgICBpZiAodGhpcy5fdXNlc01lbW9yeVN0b3JhZ2UoKSkge1xuICAgICAgY29uc3QgbWVtb3J5U2NvcGUgPSB0aGlzLl9tZW1vcnlTY29wZXMuZ2V0KGRpZ2VzdClcblxuICAgICAgaWYgKG1lbW9yeVNjb3BlKSBtZW1vcnlTY29wZS5zdGF0ZSA9IFwicmVtb3ZlZFwiXG5cbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGF3YWl0IHRoaXMuX3dpdGhEYihhc3luYyAoZGIpID0+IHtcbiAgICAgIGF3YWl0IGRiLnVwZGF0ZSh7Y29uZGl0aW9uczoge3Njb3BlX2RpZ2VzdDogZGlnZXN0fSwgZGF0YToge3N0YXRlOiBcInJlbW92ZWRcIiwgdXBkYXRlZF9hdDogbmV3IERhdGUoKX0sIHRhYmxlTmFtZTogVEFCTEVfTkFNRX0pXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBzdG9yZSBydW5zIHdpdGhvdXQgYSBjb25maWd1cmVkIGRhdGFiYXNlLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciBtZW1vcnkgc3RvcmFnZSBpcyB1c2VkLlxuICAgKi9cbiAgX3VzZXNNZW1vcnlTdG9yYWdlKCkge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gIXRoaXMuY29uZmlndXJhdGlvbi5nZXREYXRhYmFzZUNvbmZpZ3VyYXRpb24oKVt0aGlzLmRhdGFiYXNlSWRlbnRpZmllcl1cbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgYSBjYWxsYmFjayB3aXRoIGEgZGF0YWJhc2UgY29ubmVjdGlvbi5cbiAgICogQHRlbXBsYXRlIFJlc3VsdFxuICAgKiBAcGFyYW0geyhkYjogaW1wb3J0KFwiLi4vZGF0YWJhc2UvZHJpdmVycy9iYXNlLmpzXCIpLmRlZmF1bHQpID0+IFByb21pc2U8UmVzdWx0Pn0gY2FsbGJhY2sgLSBEYXRhYmFzZSBjYWxsYmFjay5cbiAgICogQHJldHVybnMge1Byb21pc2U8UmVzdWx0Pn0gQ2FsbGJhY2sgcmVzdWx0LlxuICAgKi9cbiAgYXN5bmMgX3dpdGhEYihjYWxsYmFjaykge1xuICAgIGlmICh0aGlzLnRlbmFudEhhbmRsZSkge1xuICAgICAgcmV0dXJuIGF3YWl0IHRoaXMudGVuYW50SGFuZGxlLmRhdGFiYXNlT3BlcmF0aW9uKHtkYXRhYmFzZUlkZW50aWZpZXI6IHRoaXMuZGF0YWJhc2VJZGVudGlmaWVyLCBuYW1lOiBcIlRlbmFudCBzeW5jIHNjb3BlIHN0b3JlXCJ9LCBhc3luYyAob3BlcmF0aW9uKSA9PiB7XG4gICAgICAgIHJldHVybiBhd2FpdCBjYWxsYmFjayhvcGVyYXRpb24uY29ubmVjdGlvbigpKVxuICAgICAgfSlcbiAgICB9XG5cbiAgICByZXR1cm4gYXdhaXQgdGhpcy5jb25maWd1cmF0aW9uLmVuc3VyZUNvbm5lY3Rpb25zKHtkYXRhYmFzZUlkZW50aWZpZXJzOiBbdGhpcy5kYXRhYmFzZUlkZW50aWZpZXJdLCBuYW1lOiBcIlN5bmMgc2NvcGUgc3RvcmVcIn0sIGFzeW5jIChkYnMpID0+IHtcbiAgICAgIGNvbnN0IGRiID0gZGJzW3RoaXMuZGF0YWJhc2VJZGVudGlmaWVyXVxuXG4gICAgICBpZiAoIWRiKSB0aHJvdyBuZXcgRXJyb3IoYE5vIGRhdGFiYXNlIGNvbm5lY3Rpb24gYXZhaWxhYmxlIGZvciBpZGVudGlmaWVyOiAke3RoaXMuZGF0YWJhc2VJZGVudGlmaWVyfWApXG5cbiAgICAgIHJldHVybiBhd2FpdCBjYWxsYmFjayhkYilcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIEVuc3VyZXMgdGhlIHNjb3BlcyB0YWJsZSBleGlzdHMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZGF0YWJhc2UvZHJpdmVycy9iYXNlLmpzXCIpLmRlZmF1bHR9IGRiIC0gRGF0YWJhc2UgY29ubmVjdGlvbi5cbiAgICogQHJldHVybnMge1Byb21pc2U8Ym9vbGVhbj59IFdoZXRoZXIgdGhlIHRhYmxlIGhhZCB0byBiZSBjcmVhdGVkLlxuICAgKi9cbiAgYXN5bmMgX2Vuc3VyZVNjb3Blc1RhYmxlKGRiKSB7XG4gICAgaWYgKGF3YWl0IGRiLnRhYmxlRXhpc3RzKFRBQkxFX05BTUUpKSByZXR1cm4gZmFsc2VcblxuICAgIGNvbnN0IHRhYmxlID0gbmV3IFRhYmxlRGF0YShUQUJMRV9OQU1FLCB7aWZOb3RFeGlzdHM6IHRydWV9KVxuXG4gICAgdGFibGUuc3RyaW5nKFwiaWRcIiwge251bGw6IGZhbHNlLCBwcmltYXJ5S2V5OiB0cnVlfSlcbiAgICB0YWJsZS5zdHJpbmcoXCJzY29wZV9kaWdlc3RcIiwge2luZGV4OiB0cnVlLCBudWxsOiBmYWxzZX0pXG4gICAgdGFibGUuc3RyaW5nKFwicmVzb3VyY2VfdHlwZVwiLCB7aW5kZXg6IHRydWUsIG51bGw6IGZhbHNlfSlcbiAgICB0YWJsZS50ZXh0KFwiY29uZGl0aW9uc19qc29uXCIsIHtudWxsOiBmYWxzZX0pXG4gICAgdGFibGUudGV4dChcImN1cnNvcl9qc29uXCIsIHtudWxsOiB0cnVlfSlcbiAgICB0YWJsZS5zdHJpbmcoXCJzdGF0ZVwiLCB7aW5kZXg6IHRydWUsIG51bGw6IGZhbHNlfSlcbiAgICB0YWJsZS5kYXRldGltZShcImNyZWF0ZWRfYXRcIiwge251bGw6IGZhbHNlfSlcbiAgICB0YWJsZS5kYXRldGltZShcInVwZGF0ZWRfYXRcIiwge251bGw6IGZhbHNlfSlcblxuICAgIGF3YWl0IGRiLmNyZWF0ZVRhYmxlKHRhYmxlKVxuXG4gICAgcmV0dXJuIHRydWVcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNvbHZlcyBhIHNjb3BlIHJvdyBieSBpdHMgZGlnZXN0LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2RhdGFiYXNlL2RyaXZlcnMvYmFzZS5qc1wiKS5kZWZhdWx0fSBkYiAtIERhdGFiYXNlIGNvbm5lY3Rpb24uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBkaWdlc3QgLSBGaXhlZC1zaXplIHNjb3BlIGRpZ2VzdC5cbiAgICogQHJldHVybnMge1Byb21pc2U8U3luY1Njb3BlUm93IHwgbnVsbD59IFNjb3BlIHJvdyBvciBudWxsLlxuICAgKi9cbiAgYXN5bmMgX3Jvd0J5U2NvcGVEaWdlc3QoZGIsIGRpZ2VzdCkge1xuICAgIGNvbnN0IHJvd3MgPSAvKiogQHR5cGUge0FycmF5PFJlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pj59ICovIChhd2FpdCBkYlxuICAgICAgLm5ld1F1ZXJ5KClcbiAgICAgIC5mcm9tKFRBQkxFX05BTUUpXG4gICAgICAud2hlcmUoe3Njb3BlX2RpZ2VzdDogZGlnZXN0fSlcbiAgICAgIC5saW1pdCgxKVxuICAgICAgLnJlc3VsdHMoKSlcblxuICAgIHJldHVybiByb3dzWzBdID8gdGhpcy5fbm9ybWFsaXplU2NvcGVSb3cocm93c1swXSkgOiBudWxsXG4gIH1cblxuICAvKipcbiAgICogTm9ybWFsaXplcyBhIHJhdyBzY29wZSB0YWJsZSByb3cuXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4+fSByb3cgLSBSYXcgdGFibGUgcm93LlxuICAgKiBAcmV0dXJucyB7U3luY1Njb3BlUm93fSBOb3JtYWxpemVkIHNjb3BlIHJvdy5cbiAgICovXG4gIF9ub3JtYWxpemVTY29wZVJvdyhyb3cpIHtcbiAgICByZXR1cm4ge1xuICAgICAgY29uZGl0aW9uczogLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj59ICovIChKU09OLnBhcnNlKFN0cmluZyhyb3cuY29uZGl0aW9uc19qc29uKSkpLFxuICAgICAgY3Vyc29yUGF5bG9hZDogcm93LmN1cnNvcl9qc29uID09PSBudWxsIHx8IHJvdy5jdXJzb3JfanNvbiA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IFN0cmluZyhyb3cuY3Vyc29yX2pzb24pLFxuICAgICAgaWQ6IFN0cmluZyhyb3cuaWQpLFxuICAgICAgcmVzb3VyY2VUeXBlOiBTdHJpbmcocm93LnJlc291cmNlX3R5cGUpID09PSBcIlwiID8gbnVsbCA6IFN0cmluZyhyb3cucmVzb3VyY2VfdHlwZSksXG4gICAgICBzY29wZURpZ2VzdDogU3RyaW5nKHJvdy5zY29wZV9kaWdlc3QpLFxuICAgICAgc3RhdGU6IFN0cmluZyhyb3cuc3RhdGUpLFxuICAgICAgc3RvcmVJZGVudGl0eTogdGhpcy5zdG9yZUlkZW50aXR5XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlamVjdHMgcGFzc2luZyBhIHNjb3BlIHJvdyBjYXB0dXJlZCBmcm9tIGFub3RoZXIgcGh5c2ljYWwgc3RvcmUuXG4gICAqIEBwYXJhbSB7U3luY1Njb3BlUm93fSBzY29wZVJvdyAtIFNjb3BlIHJvdyB0byB2YWxpZGF0ZS5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICBfYXNzZXJ0U2NvcGVSb3coc2NvcGVSb3cpIHtcbiAgICBpZiAoc2NvcGVSb3cuc3RvcmVJZGVudGl0eSAhPT0gdGhpcy5zdG9yZUlkZW50aXR5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTeW5jIHNjb3BlIHJvdyBiZWxvbmdzIHRvIGFub3RoZXIgcGh5c2ljYWwgdGVuYW50IGRhdGFiYXNlXCIpXG4gICAgfVxuICB9XG59XG4iXX0=
422
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1zY29wZS1zdG9yZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zeW5jL3N5bmMtc2NvcGUtc3RvcmUuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sU0FBUyxNQUFNLGlDQUFpQyxDQUFBO0FBQ3ZELE9BQU8sSUFBSSxNQUFNLFdBQVcsQ0FBQTtBQUU1QixPQUFPLEVBQUMsUUFBUSxFQUFDLE1BQU0sa0JBQWtCLENBQUE7QUFDekMsT0FBTyxtQkFBbUIsTUFBTSxrQkFBa0IsQ0FBQTtBQUVsRDs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLFVBQVUsR0FBRyx1QkFBdUIsQ0FBQTtBQUMxQyxNQUFNLG1CQUFtQixHQUFHLHVCQUF1QixDQUFBO0FBRW5EOzs7OztHQUtHO0FBQ0gsU0FBUyxtQkFBbUIsQ0FBQyxLQUFLO0lBQ2hDLE9BQU8sSUFBSSxJQUFJLENBQUMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxHQUFHLG1CQUFtQixHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUE7QUFDbkYsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQU8sY0FBYztJQUNqQzs7Ozs7O09BTUc7SUFDSCxZQUFZLEVBQUMsYUFBYSxFQUFFLGtCQUFrQixHQUFHLFNBQVMsRUFBRSxZQUFZLEVBQUM7UUFDdkUsSUFBSSxZQUFZO1lBQUUsWUFBWSxDQUFDLG1CQUFtQixDQUFDLGFBQWEsQ0FBQyxDQUFBO1FBRWpFLElBQUksQ0FBQyxhQUFhLEdBQUcsYUFBYSxDQUFBO1FBQ2xDLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxrQkFBa0IsQ0FBQTtRQUM1QyxJQUFJLENBQUMsWUFBWSxHQUFHLFlBQVksQ0FBQTtRQUNoQyxJQUFJLENBQUMsYUFBYSxHQUFHLFlBQVk7WUFDL0IsQ0FBQyxDQUFDLFlBQVksQ0FBQyxnQkFBZ0IsQ0FBQyxrQkFBa0IsQ0FBQztZQUNuRCxDQUFDLENBQUMsaUJBQWlCLGtCQUFrQixFQUFFLENBQUE7UUFDekMsd0NBQXdDO1FBQ3hDLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQTtRQUM5QixJQUFJLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQTtRQUNyQixtQ0FBbUM7UUFDbkMsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUE7UUFDekIsMEhBQTBIO1FBQzFILElBQUksQ0FBQyx5QkFBeUIsR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFBO0lBQ2hELENBQUM7SUFFRDs7O09BR0c7SUFDSCxLQUFLLENBQUMsV0FBVztRQUNmLElBQUksSUFBSSxDQUFDLFFBQVE7WUFBRSxPQUFNO1FBRXpCLElBQUksSUFBSSxDQUFDLGtCQUFrQixFQUFFLEVBQUUsQ0FBQztZQUM5QixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQTtZQUNwQixPQUFNO1FBQ1IsQ0FBQztRQUVELE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxNQUFNLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFBO0lBQ3JFLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsS0FBSyxDQUFDLGtCQUFrQixDQUFDLEVBQUU7UUFDekIsSUFBSSxJQUFJLENBQUMsUUFBUTtZQUFFLE9BQU07UUFFekIsTUFBTSxxQkFBcUIsR0FBRyxFQUFFLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLHFCQUFxQixFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQTtRQUN4RixNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUE7UUFFL0QsSUFBSSxxQkFBcUIsSUFBSSxnQkFBZ0IsRUFBRSxVQUFVLEtBQUsscUJBQXFCLEVBQUUsQ0FBQztZQUNwRixNQUFNLGdCQUFnQixDQUFDLE9BQU8sQ0FBQTtZQUM5QixPQUFNO1FBQ1IsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQ3ZCLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUE7WUFFdkMsTUFBTSxZQUFZLENBQUE7WUFDbEIsSUFBSSxJQUFJLENBQUMsYUFBYSxLQUFLLFlBQVk7Z0JBQUUsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUE7WUFDbEUsSUFBSSxJQUFJLENBQUMsUUFBUTtnQkFBRSxPQUFNO1lBRXpCLE1BQU0sSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFBO1lBQ3hCLE9BQU07UUFDUixDQUFDO1FBRUQsSUFBSSxxQkFBcUIsRUFBRSxDQUFDO1lBQzFCLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsQ0FBQyxDQUFBO1lBQ3JELE1BQU0sdUJBQXVCLEdBQUcsaUJBQWlCLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFBO1lBRXZFLE1BQU0sbUJBQW1CLEdBQUcsaUJBQWlCLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtnQkFDbkUsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO29CQUNiLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFBO29CQUNwQixPQUFNO2dCQUNSLENBQUM7Z0JBRUQsTUFBTSxxQkFBcUIsQ0FBQTtZQUM3QixDQUFDLENBQUMsQ0FBQTtZQUVGLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUMsVUFBVSxFQUFFLHFCQUFxQixFQUFFLE9BQU8sRUFBRSx1QkFBdUIsRUFBQyxDQUFDLENBQUE7WUFDN0csSUFBSSxDQUFDLGFBQWEsR0FBRyxtQkFBbUIsQ0FBQTtZQUN4QyxNQUFNLHVCQUF1QixDQUFBO1lBQzdCLE9BQU07UUFDUixDQUFDO1FBRUQsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUN6RCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQTtRQUN0QixDQUFDLENBQUMsQ0FBQTtRQUVGLElBQUksQ0FBQztZQUNILE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQTtRQUMxQixDQUFDO2dCQUFTLENBQUM7WUFDVCxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVE7Z0JBQUUsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUE7UUFDL0MsQ0FBQztJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsS0FBSyxDQUFDLGlCQUFpQixDQUFDLEtBQUs7UUFDM0IsTUFBTSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUE7UUFFeEIsTUFBTSxNQUFNLEdBQUcsbUJBQW1CLENBQUMsS0FBSyxDQUFDLENBQUE7UUFFekMsSUFBSSxJQUFJLENBQUMsa0JBQWtCLEVBQUUsRUFBRSxDQUFDO1lBQzlCLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1lBRXBELElBQUksYUFBYSxFQUFFLENBQUM7Z0JBQ2xCLElBQUksYUFBYSxDQUFDLEtBQUssS0FBSyxRQUFRO29CQUFFLGFBQWEsQ0FBQyxLQUFLLEdBQUcsUUFBUSxDQUFBO2dCQUVwRSxPQUFPLGFBQWEsQ0FBQTtZQUN0QixDQUFDO1lBRUQsTUFBTSxRQUFRLEdBQUc7Z0JBQ2YsVUFBVSxFQUFFLEtBQUssQ0FBQyxVQUFVO2dCQUM1QixhQUFhLEVBQUUsSUFBSTtnQkFDbkIsRUFBRSxFQUFFLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRTtnQkFDeEIsWUFBWSxFQUFFLEtBQUssQ0FBQyxZQUFZLElBQUksSUFBSTtnQkFDeEMsV0FBVyxFQUFFLE1BQU07Z0JBQ25CLEtBQUssRUFBRSxRQUFRO2dCQUNmLGFBQWEsRUFBRSxJQUFJLENBQUMsYUFBYTthQUNsQyxDQUFBO1lBRUQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFBO1lBRXhDLE9BQU8sUUFBUSxDQUFBO1FBQ2pCLENBQUM7UUFFRCxPQUFPLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEVBQUU7WUFDckMsTUFBTSxXQUFXLEdBQUcsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFBO1lBRTVELElBQUksV0FBVyxFQUFFLENBQUM7Z0JBQ2hCLElBQUksV0FBVyxDQUFDLEtBQUssS0FBSyxRQUFRLEVBQUUsQ0FBQztvQkFDbkMsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUMsVUFBVSxFQUFFLEVBQUMsRUFBRSxFQUFFLFdBQVcsQ0FBQyxFQUFFLEVBQUMsRUFBRSxJQUFJLEVBQUUsRUFBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxJQUFJLElBQUksRUFBRSxFQUFDLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBQyxDQUFDLENBQUE7b0JBQzNILFdBQVcsQ0FBQyxLQUFLLEdBQUcsUUFBUSxDQUFBO2dCQUM5QixDQUFDO2dCQUVELE9BQU8sV0FBVyxDQUFBO1lBQ3BCLENBQUM7WUFFRCxNQUFNLEVBQUUsQ0FBQyxNQUFNLENBQUM7Z0JBQ2QsU0FBUyxFQUFFLFVBQVU7Z0JBQ3JCLElBQUksRUFBRTtvQkFDSixlQUFlLEVBQUUsbUJBQW1CLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQztvQkFDdEQsVUFBVSxFQUFFLElBQUksSUFBSSxFQUFFO29CQUN0QixXQUFXLEVBQUUsSUFBSTtvQkFDakIsRUFBRSxFQUFFLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRTtvQkFDeEIsaUZBQWlGO29CQUNqRixpRUFBaUU7b0JBQ2pFLGFBQWEsRUFBRSxLQUFLLENBQUMsWUFBWSxJQUFJLEVBQUU7b0JBQ3ZDLFlBQVksRUFBRSxNQUFNO29CQUNwQixLQUFLLEVBQUUsUUFBUTtvQkFDZixVQUFVLEVBQUUsSUFBSSxJQUFJLEVBQUU7aUJBQ3ZCO2FBQ0YsQ0FBQyxDQUFBO1lBRUYsTUFBTSxVQUFVLEdBQUcsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFBO1lBRTNELElBQUksQ0FBQyxVQUFVO2dCQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsOEJBQThCLENBQUMsQ0FBQTtZQUVoRSxPQUFPLFVBQVUsQ0FBQTtRQUNuQixDQUFDLENBQUMsQ0FBQTtJQUNKLENBQUM7SUFFRDs7O09BR0c7SUFDSCxLQUFLLENBQUMsWUFBWTtRQUNoQixNQUFNLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQTtRQUV4QixJQUFJLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxFQUFFLENBQUM7WUFDOUIsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLEtBQUssS0FBSyxRQUFRLENBQUMsQ0FBQTtRQUNyRixDQUFDO1FBRUQsT0FBTyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxFQUFFO1lBQ3JDLE1BQU0sSUFBSSxHQUFHLG1FQUFtRSxDQUFDLENBQUMsTUFBTSxFQUFFO2lCQUN2RixRQUFRLEVBQUU7aUJBQ1YsSUFBSSxDQUFDLFVBQVUsQ0FBQztpQkFDaEIsS0FBSyxDQUFDLEVBQUMsS0FBSyxFQUFFLFFBQVEsRUFBQyxDQUFDO2lCQUN4QixLQUFLLENBQUMsZ0JBQWdCLENBQUM7aUJBQ3ZCLE9BQU8sRUFBRSxDQUFDLENBQUE7WUFFYixPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFBO1FBQ3hELENBQUMsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxLQUFLLENBQUMsVUFBVSxDQUFDLFFBQVE7UUFDdkIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxRQUFRLENBQUMsQ0FBQTtRQUM5QixNQUFNLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQTtRQUV4QixJQUFJLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxFQUFFLENBQUM7WUFDOUIsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFBO1lBRWpFLE9BQU8sWUFBWSxFQUFFLEVBQUUsS0FBSyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUE7UUFDN0UsQ0FBQztRQUVELE9BQU8sTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsRUFBRTtZQUNyQyxNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLEVBQUUsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFBO1lBRWxFLE9BQU8sR0FBRyxFQUFFLEVBQUUsS0FBSyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUE7UUFDM0QsQ0FBQyxDQUFDLENBQUE7SUFDSixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxLQUFLLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRSxNQUFNO1FBQy9CLElBQUksQ0FBQyxlQUFlLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDOUIsSUFBSSxDQUFDLE1BQU07WUFBRSxPQUFNO1FBRW5CLE1BQU0sSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFBO1FBRXhCLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUE7UUFFNUMsSUFBSSxJQUFJLENBQUMsa0JBQWtCLEVBQUUsRUFBRSxDQUFDO1lBQzlCLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsQ0FBQTtZQUVoRSxJQUFJLENBQUMsV0FBVztnQkFBRSxNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixRQUFRLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQTtZQUNyRixJQUFJLFdBQVcsQ0FBQyxFQUFFLEtBQUssUUFBUSxDQUFDLEVBQUUsSUFBSSxXQUFXLENBQUMsS0FBSyxLQUFLLFFBQVE7Z0JBQUUsT0FBTTtZQUU1RSxXQUFXLENBQUMsYUFBYSxHQUFHLGFBQWEsQ0FBQTtZQUN6QyxPQUFNO1FBQ1IsQ0FBQztRQUVELE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEVBQUU7WUFDOUIsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDO2dCQUNkLFVBQVUsRUFBRSxFQUFDLEVBQUUsRUFBRSxRQUFRLENBQUMsRUFBRSxFQUFFLFlBQVksRUFBRSxRQUFRLENBQUMsV0FBVyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUM7Z0JBQ2xGLElBQUksRUFBRSxFQUFDLFdBQVcsRUFBRSxhQUFhLEVBQUUsVUFBVSxFQUFFLElBQUksSUFBSSxFQUFFLEVBQUM7Z0JBQzFELFNBQVMsRUFBRSxVQUFVO2FBQ3RCLENBQUMsQ0FBQTtRQUNKLENBQUMsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxLQUFLLENBQUMsVUFBVSxDQUFDLEtBQUs7UUFDcEIsTUFBTSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUE7UUFFeEIsTUFBTSxNQUFNLEdBQUcsbUJBQW1CLENBQUMsS0FBSyxDQUFDLENBQUE7UUFFekMsSUFBSSxJQUFJLENBQUMsa0JBQWtCLEVBQUUsRUFBRSxDQUFDO1lBQzlCLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1lBRWxELElBQUksV0FBVztnQkFBRSxXQUFXLENBQUMsS0FBSyxHQUFHLFNBQVMsQ0FBQTtZQUU5QyxPQUFNO1FBQ1IsQ0FBQztRQUVELE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEVBQUU7WUFDOUIsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUMsVUFBVSxFQUFFLEVBQUMsWUFBWSxFQUFFLE1BQU0sRUFBQyxFQUFFLElBQUksRUFBRSxFQUFDLEtBQUssRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLElBQUksSUFBSSxFQUFFLEVBQUMsRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFDLENBQUMsQ0FBQTtRQUNoSSxDQUFDLENBQUMsQ0FBQTtJQUNKLENBQUM7SUFFRDs7Ozs7Ozs7OztPQVVHO0lBQ0gsS0FBSyxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsRUFBQyxPQUFPLEVBQUMsR0FBRyxFQUFFO1FBQ2hDLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssQ0FBQztZQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsNkRBQTZELENBQUMsQ0FBQTtRQUNqSSxJQUFJLE9BQU8sS0FBSyxTQUFTLElBQUksT0FBTyxPQUFPLEtBQUssVUFBVTtZQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsaURBQWlELENBQUMsQ0FBQTtRQUU5SCxNQUFNLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQTtRQUV4QixNQUFNLFlBQVksR0FBRyxDQUFDLEdBQUcsSUFBSSxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQTtRQUV0RyxJQUFJLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxFQUFFLENBQUM7WUFDOUIsSUFBSSxPQUFPO2dCQUFFLE1BQU0sT0FBTyxDQUFDLEVBQUMsVUFBVSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFDLENBQUMsQ0FBQTtZQUVwRSxLQUFLLE1BQU0sS0FBSyxJQUFJLFlBQVk7Z0JBQUUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxDQUFBO1lBRS9ELE9BQU07UUFDUixDQUFDO1FBRUQsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsRUFBRTtZQUM5QixNQUFNLEVBQUUsQ0FBQyxXQUFXLENBQUMsS0FBSyxJQUFJLEVBQUU7Z0JBQzlCLElBQUksT0FBTztvQkFBRSxNQUFNLE9BQU8sQ0FBQyxFQUFDLFVBQVUsRUFBRSxFQUFFLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBQyxDQUFDLENBQUE7Z0JBRWxFLEtBQUssTUFBTSxLQUFLLElBQUksWUFBWTtvQkFBRSxNQUFNLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxFQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUMsQ0FBQyxDQUFBO1lBQy9FLENBQUMsQ0FBQyxDQUFBO1FBQ0osQ0FBQyxDQUFDLENBQUE7SUFDSixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILGlCQUFpQixDQUFDLEtBQUs7UUFDckIsTUFBTSxNQUFNLEdBQUcsbUJBQW1CLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDekMsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUE7UUFFbEQsSUFBSSxDQUFDLFdBQVcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEtBQUssU0FBUyxJQUFJLFdBQVcsQ0FBQyxhQUFhLEtBQUssSUFBSSxDQUFDO1lBQUUsT0FBTTtRQUVuRyxJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUU7WUFDN0IsR0FBRyxXQUFXO1lBQ2QsYUFBYSxFQUFFLElBQUk7WUFDbkIsRUFBRSxFQUFFLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRTtZQUN4QixLQUFLLEVBQUUsU0FBUztTQUNqQixDQUFDLENBQUE7SUFDSixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxFQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUM7UUFDbkMsTUFBTSxNQUFNLEdBQUcsbUJBQW1CLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDekMsTUFBTSxXQUFXLEdBQUcsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFBO1FBRTVELElBQUksQ0FBQyxXQUFXLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxLQUFLLFNBQVMsSUFBSSxXQUFXLENBQUMsYUFBYSxLQUFLLElBQUksQ0FBQztZQUFFLE9BQU07UUFFbkcsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDO1lBQ2QsVUFBVSxFQUFFLEVBQUMsRUFBRSxFQUFFLFdBQVcsQ0FBQyxFQUFFLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBQztZQUN0RCxJQUFJLEVBQUUsRUFBQyxXQUFXLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxJQUFJLElBQUksRUFBRSxFQUFDO1lBQzdGLFNBQVMsRUFBRSxVQUFVO1NBQ3RCLENBQUMsQ0FBQTtJQUNKLENBQUM7SUFFRDs7O09BR0c7SUFDSCxrQkFBa0I7UUFDaEIsSUFBSSxDQUFDO1lBQ0gsT0FBTyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsd0JBQXdCLEVBQUUsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQTtRQUNoRixDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsT0FBTyxJQUFJLENBQUE7UUFDYixDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRO1FBQ3BCLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3RCLE9BQU8sTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDLGlCQUFpQixDQUFDLEVBQUMsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLGtCQUFrQixFQUFFLElBQUksRUFBRSx5QkFBeUIsRUFBQyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsRUFBRTtnQkFDbkosT0FBTyxNQUFNLFFBQVEsQ0FBQyxTQUFTLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQTtZQUMvQyxDQUFDLENBQUMsQ0FBQTtRQUNKLENBQUM7UUFFRCxPQUFPLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFDLG1CQUFtQixFQUFFLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsSUFBSSxFQUFFLGtCQUFrQixFQUFDLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxFQUFFO1lBQzFJLE1BQU0sRUFBRSxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQTtZQUV2QyxJQUFJLENBQUMsRUFBRTtnQkFBRSxNQUFNLElBQUksS0FBSyxDQUFDLG9EQUFvRCxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQyxDQUFBO1lBRXZHLE9BQU8sTUFBTSxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUE7UUFDM0IsQ0FBQyxDQUFDLENBQUE7SUFDSixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFO1FBQ3pCLElBQUksTUFBTSxFQUFFLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQztZQUFFLE9BQU8sS0FBSyxDQUFBO1FBRWxELE1BQU0sS0FBSyxHQUFHLElBQUksU0FBUyxDQUFDLFVBQVUsRUFBRSxFQUFDLFdBQVcsRUFBRSxJQUFJLEVBQUMsQ0FBQyxDQUFBO1FBRTVELEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLEVBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFDLENBQUMsQ0FBQTtRQUNuRCxLQUFLLENBQUMsTUFBTSxDQUFDLGNBQWMsRUFBRSxFQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBQyxDQUFDLENBQUE7UUFDeEQsS0FBSyxDQUFDLE1BQU0sQ0FBQyxlQUFlLEVBQUUsRUFBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUMsQ0FBQyxDQUFBO1FBQ3pELEtBQUssQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsRUFBQyxJQUFJLEVBQUUsS0FBSyxFQUFDLENBQUMsQ0FBQTtRQUM1QyxLQUFLLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxFQUFDLElBQUksRUFBRSxJQUFJLEVBQUMsQ0FBQyxDQUFBO1FBQ3ZDLEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLEVBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFDLENBQUMsQ0FBQTtRQUNqRCxLQUFLLENBQUMsUUFBUSxDQUFDLFlBQVksRUFBRSxFQUFDLElBQUksRUFBRSxLQUFLLEVBQUMsQ0FBQyxDQUFBO1FBQzNDLEtBQUssQ0FBQyxRQUFRLENBQUMsWUFBWSxFQUFFLEVBQUMsSUFBSSxFQUFFLEtBQUssRUFBQyxDQUFDLENBQUE7UUFFM0MsTUFBTSxFQUFFLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBRTNCLE9BQU8sSUFBSSxDQUFBO0lBQ2IsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsS0FBSyxDQUFDLGlCQUFpQixDQUFDLEVBQUUsRUFBRSxNQUFNO1FBQ2hDLE1BQU0sSUFBSSxHQUFHLG1FQUFtRSxDQUFDLENBQUMsTUFBTSxFQUFFO2FBQ3ZGLFFBQVEsRUFBRTthQUNWLElBQUksQ0FBQyxVQUFVLENBQUM7YUFDaEIsS0FBSyxDQUFDLEVBQUMsWUFBWSxFQUFFLE1BQU0sRUFBQyxDQUFDO2FBQzdCLEtBQUssQ0FBQyxDQUFDLENBQUM7YUFDUixPQUFPLEVBQUUsQ0FBQyxDQUFBO1FBRWIsT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFBO0lBQzFELENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsa0JBQWtCLENBQUMsR0FBRztRQUNwQixPQUFPO1lBQ0wsVUFBVSxFQUFFLDREQUE0RCxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUM7WUFDbEgsYUFBYSxFQUFFLEdBQUcsQ0FBQyxXQUFXLEtBQUssSUFBSSxJQUFJLEdBQUcsQ0FBQyxXQUFXLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDO1lBQ3pHLEVBQUUsRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUNsQixZQUFZLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUM7WUFDakYsV0FBVyxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDO1lBQ3JDLEtBQUssRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQztZQUN4QixhQUFhLEVBQUUsSUFBSSxDQUFDLGFBQWE7U0FDbEMsQ0FBQTtJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsZUFBZSxDQUFDLFFBQVE7UUFDdEIsSUFBSSxRQUFRLENBQUMsYUFBYSxLQUFLLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUNsRCxNQUFNLElBQUksS0FBSyxDQUFDLDREQUE0RCxDQUFDLENBQUE7UUFDL0UsQ0FBQztJQUNILENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgVGFibGVEYXRhIGZyb20gXCIuLi9kYXRhYmFzZS90YWJsZS1kYXRhL2luZGV4LmpzXCJcbmltcG9ydCBVVUlEIGZyb20gXCJwdXJlLXV1aWRcIlxuXG5pbXBvcnQge3Njb3BlS2V5fSBmcm9tIFwiLi9xdWVyeS1zY29wZS5qc1wiXG5pbXBvcnQgc3RhYmxlSnNvblN0cmluZ2lmeSBmcm9tIFwiLi9zdGFibGUtanNvbi5qc1wiXG5cbi8qKlxuICogQHR5cGVkZWYge29iamVjdH0gU3luY1Njb3BlUm93XG4gKiBAcHJvcGVydHkge1JlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pn0gY29uZGl0aW9ucyAtIFNjb3BlIGF0dHJpYnV0ZSBjb25kaXRpb25zLlxuICogQHByb3BlcnR5IHtzdHJpbmcgfCBudWxsfSBjdXJzb3JQYXlsb2FkIC0gUGVyc2lzdGVkIGN1cnNvciBKU09OIHBheWxvYWQuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gaWQgLSBTY29wZSByb3cgaWQuXG4gKiBAcHJvcGVydHkge3N0cmluZyB8IG51bGx9IHJlc291cmNlVHlwZSAtIFNjb3BlIHJlc291cmNlL21vZGVsIG5hbWUsIG9yIG51bGwgZm9yIHRoZSBhbGwtdHlwZXMgKHVzZXIpIHNjb3BlLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IHNjb3BlRGlnZXN0IC0gRml4ZWQtc2l6ZSBkZXRlcm1pbmlzdGljIGRpZ2VzdCBvZiB0aGUgY2Fub25pY2FsIHNjb3BlIGtleS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBzdGF0ZSAtIFNjb3BlIHN0YXRlIChcImFjdGl2ZVwiIG9yIFwicmVtb3ZlZFwiKS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBzdG9yZUlkZW50aXR5IC0gUGh5c2ljYWwgc3RvcmUgaWRlbnRpdHkgb3duaW5nIHRoaXMgcm93LlxuICovXG5jb25zdCBUQUJMRV9OQU1FID0gXCJ2ZWxvY2lvdXNfc3luY19zY29wZXNcIlxuY29uc3QgU0NPUEVfRElHRVNUX1BSRUZJWCA9IFwidmVsb2Npb3VzLXN5bmMtc2NvcGU6XCJcblxuLyoqXG4gKiBEaWdlc3RzIGEgc2VyaWFsaXplZCBzY29wZSBpbnRvIGEgZml4ZWQtc2l6ZSBkZXRlcm1pbmlzdGljIGtleSwgc28gc2NvcGVcbiAqIGlkZW50aXRpZXMgd2l0aCBsb25nIGNvbmRpdGlvbiB2YWx1ZXMgZml0IGFuIGluZGV4ZWQgc3RyaW5nIGNvbHVtbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zeW5jLWNsaWVudC10eXBlcy5qc1wiKS5TZXJpYWxpemVkU3luY1Njb3BlfSBzY29wZSAtIFNlcmlhbGl6ZWQgc3luYyBzY29wZS5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IERldGVybWluaXN0aWMgVVVJRHY1IGRpZ2VzdCBvZiB0aGUgY2Fub25pY2FsIHNjb3BlIGtleS5cbiAqL1xuZnVuY3Rpb24gc2NvcGVEaWdlc3RGb3JTY29wZShzY29wZSkge1xuICByZXR1cm4gbmV3IFVVSUQoNSwgXCJuczpVUkxcIiwgYCR7U0NPUEVfRElHRVNUX1BSRUZJWH0ke3Njb3BlS2V5KHNjb3BlKX1gKS5mb3JtYXQoKVxufVxuXG4vKipcbiAqIEZyYW1ld29yay1vd25lZCBsb2NhbCBwZXJzaXN0ZW5jZSBmb3IgZGVjbGFyZWQgc3luYyBzY29wZXMgYW5kIHRoZWlyIGN1cnNvcnMuXG4gKlxuICogQmFja2VkIGJ5IGFuIGF1dG8tY3JlYXRlZCBgdmVsb2Npb3VzX3N5bmNfc2NvcGVzYCB0YWJsZSBvbiB0aGUgY29uZmlndXJlZFxuICogZGF0YWJhc2UsIHdpdGggYSBwcm9jZXNzLWxvY2FsIG1lbW9yeSBmYWxsYmFjayB3aGVuIG5vIGRhdGFiYXNlIGlzXG4gKiBjb25maWd1cmVkIChtaXJyb3JpbmcgdGhlIHNlcnZlciBjaGFuZ2UtZmVlZCBzdG9yZSkuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFN5bmNTY29wZVN0b3JlIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBzeW5jIHNjb3BlIHN0b3JlLlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIE9wdGlvbnMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi5qc1wiKS5kZWZhdWx0fSBhcmdzLmNvbmZpZ3VyYXRpb24gLSBDb25maWd1cmF0aW9uIG93bmluZyB0aGUgZGF0YWJhc2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbYXJncy5kYXRhYmFzZUlkZW50aWZpZXJdIC0gRGF0YWJhc2UgaWRlbnRpZmllci5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi90ZW5hbnRzL3RlbmFudC1oYW5kbGUuanNcIikuZGVmYXVsdH0gW2FyZ3MudGVuYW50SGFuZGxlXSAtIEltbXV0YWJsZSB0ZW5hbnQgaGFuZGxlIG93bmluZyB0aGUgcGh5c2ljYWwgc3RvcmUuXG4gICAqL1xuICBjb25zdHJ1Y3Rvcih7Y29uZmlndXJhdGlvbiwgZGF0YWJhc2VJZGVudGlmaWVyID0gXCJkZWZhdWx0XCIsIHRlbmFudEhhbmRsZX0pIHtcbiAgICBpZiAodGVuYW50SGFuZGxlKSB0ZW5hbnRIYW5kbGUuYXNzZXJ0Q29uZmlndXJhdGlvbihjb25maWd1cmF0aW9uKVxuXG4gICAgdGhpcy5jb25maWd1cmF0aW9uID0gY29uZmlndXJhdGlvblxuICAgIHRoaXMuZGF0YWJhc2VJZGVudGlmaWVyID0gZGF0YWJhc2VJZGVudGlmaWVyXG4gICAgdGhpcy50ZW5hbnRIYW5kbGUgPSB0ZW5hbnRIYW5kbGVcbiAgICB0aGlzLnN0b3JlSWRlbnRpdHkgPSB0ZW5hbnRIYW5kbGVcbiAgICAgID8gdGVuYW50SGFuZGxlLmRhdGFiYXNlSWRlbnRpdHkoZGF0YWJhc2VJZGVudGlmaWVyKVxuICAgICAgOiBgY29uZmlndXJhdGlvbjoke2RhdGFiYXNlSWRlbnRpZmllcn1gXG4gICAgLyoqIEB0eXBlIHtNYXA8c3RyaW5nLCBTeW5jU2NvcGVSb3c+fSAqL1xuICAgIHRoaXMuX21lbW9yeVNjb3BlcyA9IG5ldyBNYXAoKVxuICAgIHRoaXMuX2lzUmVhZHkgPSBmYWxzZVxuICAgIC8qKiBAdHlwZSB7UHJvbWlzZTx2b2lkPiB8IG51bGx9ICovXG4gICAgdGhpcy5fcmVhZHlQcm9taXNlID0gbnVsbFxuICAgIC8qKiBAdHlwZSB7V2Vha01hcDxpbXBvcnQoXCIuLi9kYXRhYmFzZS9kcml2ZXJzL2Jhc2UuanNcIikuZGVmYXVsdCwge2NvbXBsZXRpb246IFByb21pc2U8dm9pZD4sIHByb21pc2U6IFByb21pc2U8dm9pZD59Pn0gKi9cbiAgICB0aGlzLl90cmFuc2FjdGlvblJlYWR5UHJvbWlzZXMgPSBuZXcgV2Vha01hcCgpXG4gIH1cblxuICAvKipcbiAgICogRW5zdXJlcyB0aGUgYmFja2luZyB0YWJsZSBleGlzdHMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBSZXNvbHZlcyB3aGVuIHJlYWR5LlxuICAgKi9cbiAgYXN5bmMgZW5zdXJlUmVhZHkoKSB7XG4gICAgaWYgKHRoaXMuX2lzUmVhZHkpIHJldHVyblxuXG4gICAgaWYgKHRoaXMuX3VzZXNNZW1vcnlTdG9yYWdlKCkpIHtcbiAgICAgIHRoaXMuX2lzUmVhZHkgPSB0cnVlXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLl93aXRoRGIoYXN5bmMgKGRiKSA9PiBhd2FpdCB0aGlzLl9lbnN1cmVSZWFkeVdpdGhEYihkYikpXG4gIH1cblxuICAvKipcbiAgICogQ29vcmRpbmF0ZXMgZHVyYWJsZSBhbmQgdHJhbnNhY3Rpb24tbG9jYWwgcmVhZGluZXNzIG9uIG9uZSBjb25uZWN0aW9uLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2RhdGFiYXNlL2RyaXZlcnMvYmFzZS5qc1wiKS5kZWZhdWx0fSBkYiAtIERhdGFiYXNlIGNvbm5lY3Rpb24uXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBSZXNvbHZlcyB3aGVuIHRoaXMgY2FsbGVyIGNhbiB1c2UgdGhlIHRhYmxlLlxuICAgKi9cbiAgYXN5bmMgX2Vuc3VyZVJlYWR5V2l0aERiKGRiKSB7XG4gICAgaWYgKHRoaXMuX2lzUmVhZHkpIHJldHVyblxuXG4gICAgY29uc3QgdHJhbnNhY3Rpb25Db21wbGV0aW9uID0gZGIuaW5zaWRlVHJhbnNhY3Rpb24oKSA/IGRiLnRyYW5zYWN0aW9uQ29tcGxldGlvbigpIDogbnVsbFxuICAgIGNvbnN0IHRyYW5zYWN0aW9uUmVhZHkgPSB0aGlzLl90cmFuc2FjdGlvblJlYWR5UHJvbWlzZXMuZ2V0KGRiKVxuXG4gICAgaWYgKHRyYW5zYWN0aW9uQ29tcGxldGlvbiAmJiB0cmFuc2FjdGlvblJlYWR5Py5jb21wbGV0aW9uID09PSB0cmFuc2FjdGlvbkNvbXBsZXRpb24pIHtcbiAgICAgIGF3YWl0IHRyYW5zYWN0aW9uUmVhZHkucHJvbWlzZVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX3JlYWR5UHJvbWlzZSkge1xuICAgICAgY29uc3QgcmVhZHlQcm9taXNlID0gdGhpcy5fcmVhZHlQcm9taXNlXG5cbiAgICAgIGF3YWl0IHJlYWR5UHJvbWlzZVxuICAgICAgaWYgKHRoaXMuX3JlYWR5UHJvbWlzZSA9PT0gcmVhZHlQcm9taXNlKSB0aGlzLl9yZWFkeVByb21pc2UgPSBudWxsXG4gICAgICBpZiAodGhpcy5faXNSZWFkeSkgcmV0dXJuXG5cbiAgICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVhZHkoKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgaWYgKHRyYW5zYWN0aW9uQ29tcGxldGlvbikge1xuICAgICAgY29uc3QgdGFibGVSZWFkeVByb21pc2UgPSB0aGlzLl9lbnN1cmVTY29wZXNUYWJsZShkYilcbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uUmVhZHlQcm9taXNlID0gdGFibGVSZWFkeVByb21pc2UudGhlbigoKSA9PiB1bmRlZmluZWQpXG5cbiAgICAgIGNvbnN0IGR1cmFibGVSZWFkeVByb21pc2UgPSB0YWJsZVJlYWR5UHJvbWlzZS50aGVuKGFzeW5jIChjcmVhdGVkKSA9PiB7XG4gICAgICAgIGlmICghY3JlYXRlZCkge1xuICAgICAgICAgIHRoaXMuX2lzUmVhZHkgPSB0cnVlXG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCB0cmFuc2FjdGlvbkNvbXBsZXRpb25cbiAgICAgIH0pXG5cbiAgICAgIHRoaXMuX3RyYW5zYWN0aW9uUmVhZHlQcm9taXNlcy5zZXQoZGIsIHtjb21wbGV0aW9uOiB0cmFuc2FjdGlvbkNvbXBsZXRpb24sIHByb21pc2U6IHRyYW5zYWN0aW9uUmVhZHlQcm9taXNlfSlcbiAgICAgIHRoaXMuX3JlYWR5UHJvbWlzZSA9IGR1cmFibGVSZWFkeVByb21pc2VcbiAgICAgIGF3YWl0IHRyYW5zYWN0aW9uUmVhZHlQcm9taXNlXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICB0aGlzLl9yZWFkeVByb21pc2UgPSB0aGlzLl9lbnN1cmVTY29wZXNUYWJsZShkYikudGhlbigoKSA9PiB7XG4gICAgICB0aGlzLl9pc1JlYWR5ID0gdHJ1ZVxuICAgIH0pXG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5fcmVhZHlQcm9taXNlXG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGlmICghdGhpcy5faXNSZWFkeSkgdGhpcy5fcmVhZHlQcm9taXNlID0gbnVsbFxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kcyBvciBjcmVhdGVzIHRoZSBzY29wZSByb3cgZm9yIGEgc2VyaWFsaXplZCBzY29wZSwgcmVhY3RpdmF0aW5nIHJlbW92ZWQgc2NvcGVzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vc3luYy1jbGllbnQtdHlwZXMuanNcIikuU2VyaWFsaXplZFN5bmNTY29wZX0gc2NvcGUgLSBTZXJpYWxpemVkIHN5bmMgc2NvcGUuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFN5bmNTY29wZVJvdz59IFBlcnNpc3RlZCBzY29wZSByb3cuXG4gICAqL1xuICBhc3luYyBmaW5kT3JDcmVhdGVTY29wZShzY29wZSkge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVhZHkoKVxuXG4gICAgY29uc3QgZGlnZXN0ID0gc2NvcGVEaWdlc3RGb3JTY29wZShzY29wZSlcblxuICAgIGlmICh0aGlzLl91c2VzTWVtb3J5U3RvcmFnZSgpKSB7XG4gICAgICBjb25zdCBleGlzdGluZ1Njb3BlID0gdGhpcy5fbWVtb3J5U2NvcGVzLmdldChkaWdlc3QpXG5cbiAgICAgIGlmIChleGlzdGluZ1Njb3BlKSB7XG4gICAgICAgIGlmIChleGlzdGluZ1Njb3BlLnN0YXRlICE9PSBcImFjdGl2ZVwiKSBleGlzdGluZ1Njb3BlLnN0YXRlID0gXCJhY3RpdmVcIlxuXG4gICAgICAgIHJldHVybiBleGlzdGluZ1Njb3BlXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG5ld1Njb3BlID0ge1xuICAgICAgICBjb25kaXRpb25zOiBzY29wZS5jb25kaXRpb25zLFxuICAgICAgICBjdXJzb3JQYXlsb2FkOiBudWxsLFxuICAgICAgICBpZDogbmV3IFVVSUQoNCkuZm9ybWF0KCksXG4gICAgICAgIHJlc291cmNlVHlwZTogc2NvcGUucmVzb3VyY2VUeXBlID8/IG51bGwsXG4gICAgICAgIHNjb3BlRGlnZXN0OiBkaWdlc3QsXG4gICAgICAgIHN0YXRlOiBcImFjdGl2ZVwiLFxuICAgICAgICBzdG9yZUlkZW50aXR5OiB0aGlzLnN0b3JlSWRlbnRpdHlcbiAgICAgIH1cblxuICAgICAgdGhpcy5fbWVtb3J5U2NvcGVzLnNldChkaWdlc3QsIG5ld1Njb3BlKVxuXG4gICAgICByZXR1cm4gbmV3U2NvcGVcbiAgICB9XG5cbiAgICByZXR1cm4gYXdhaXQgdGhpcy5fd2l0aERiKGFzeW5jIChkYikgPT4ge1xuICAgICAgY29uc3QgZXhpc3RpbmdSb3cgPSBhd2FpdCB0aGlzLl9yb3dCeVNjb3BlRGlnZXN0KGRiLCBkaWdlc3QpXG5cbiAgICAgIGlmIChleGlzdGluZ1Jvdykge1xuICAgICAgICBpZiAoZXhpc3RpbmdSb3cuc3RhdGUgIT09IFwiYWN0aXZlXCIpIHtcbiAgICAgICAgICBhd2FpdCBkYi51cGRhdGUoe2NvbmRpdGlvbnM6IHtpZDogZXhpc3RpbmdSb3cuaWR9LCBkYXRhOiB7c3RhdGU6IFwiYWN0aXZlXCIsIHVwZGF0ZWRfYXQ6IG5ldyBEYXRlKCl9LCB0YWJsZU5hbWU6IFRBQkxFX05BTUV9KVxuICAgICAgICAgIGV4aXN0aW5nUm93LnN0YXRlID0gXCJhY3RpdmVcIlxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGV4aXN0aW5nUm93XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IGRiLmluc2VydCh7XG4gICAgICAgIHRhYmxlTmFtZTogVEFCTEVfTkFNRSxcbiAgICAgICAgZGF0YToge1xuICAgICAgICAgIGNvbmRpdGlvbnNfanNvbjogc3RhYmxlSnNvblN0cmluZ2lmeShzY29wZS5jb25kaXRpb25zKSxcbiAgICAgICAgICBjcmVhdGVkX2F0OiBuZXcgRGF0ZSgpLFxuICAgICAgICAgIGN1cnNvcl9qc29uOiBudWxsLFxuICAgICAgICAgIGlkOiBuZXcgVVVJRCg0KS5mb3JtYXQoKSxcbiAgICAgICAgICAvLyBUaGUgYWxsLXR5cGVzICh1c2VyKSBzY29wZSBoYXMgbm8gcmVzb3VyY2UgdHlwZTsgdGhlIGNvbHVtbiBpcyBub24tbnVsbCwgc28gaXRcbiAgICAgICAgICAvLyBzdG9yZXMgYXMgYW4gZW1wdHkgc3RyaW5nIGFuZCBub3JtYWxpemVzIGJhY2sgdG8gbnVsbCBvbiByZWFkLlxuICAgICAgICAgIHJlc291cmNlX3R5cGU6IHNjb3BlLnJlc291cmNlVHlwZSA/PyBcIlwiLFxuICAgICAgICAgIHNjb3BlX2RpZ2VzdDogZGlnZXN0LFxuICAgICAgICAgIHN0YXRlOiBcImFjdGl2ZVwiLFxuICAgICAgICAgIHVwZGF0ZWRfYXQ6IG5ldyBEYXRlKClcbiAgICAgICAgfVxuICAgICAgfSlcblxuICAgICAgY29uc3QgY3JlYXRlZFJvdyA9IGF3YWl0IHRoaXMuX3Jvd0J5U2NvcGVEaWdlc3QoZGIsIGRpZ2VzdClcblxuICAgICAgaWYgKCFjcmVhdGVkUm93KSB0aHJvdyBuZXcgRXJyb3IoXCJGYWlsZWQgdG8gcGVyc2lzdCBzeW5jIHNjb3BlXCIpXG5cbiAgICAgIHJldHVybiBjcmVhdGVkUm93XG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFsbCBhY3RpdmUgc2NvcGUgcm93cy5cbiAgICogQHJldHVybnMge1Byb21pc2U8U3luY1Njb3BlUm93W10+fSBBY3RpdmUgc2NvcGUgcm93cy5cbiAgICovXG4gIGFzeW5jIGFjdGl2ZVNjb3BlcygpIHtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlYWR5KClcblxuICAgIGlmICh0aGlzLl91c2VzTWVtb3J5U3RvcmFnZSgpKSB7XG4gICAgICByZXR1cm4gWy4uLnRoaXMuX21lbW9yeVNjb3Blcy52YWx1ZXMoKV0uZmlsdGVyKChzY29wZSkgPT4gc2NvcGUuc3RhdGUgPT09IFwiYWN0aXZlXCIpXG4gICAgfVxuXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuX3dpdGhEYihhc3luYyAoZGIpID0+IHtcbiAgICAgIGNvbnN0IHJvd3MgPSAvKiogQHR5cGUge0FycmF5PFJlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pj59ICovIChhd2FpdCBkYlxuICAgICAgICAubmV3UXVlcnkoKVxuICAgICAgICAuZnJvbShUQUJMRV9OQU1FKVxuICAgICAgICAud2hlcmUoe3N0YXRlOiBcImFjdGl2ZVwifSlcbiAgICAgICAgLm9yZGVyKFwiY3JlYXRlZF9hdCBBU0NcIilcbiAgICAgICAgLnJlc3VsdHMoKSlcblxuICAgICAgcmV0dXJuIHJvd3MubWFwKChyb3cpID0+IHRoaXMuX25vcm1hbGl6ZVNjb3BlUm93KHJvdykpXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2FkcyB0aGUgcGVyc2lzdGVkIGN1cnNvciBwYXlsb2FkIGZvciBhIHNjb3BlIHJvdy5cbiAgICogQHBhcmFtIHtTeW5jU2NvcGVSb3d9IHNjb3BlUm93IC0gU2NvcGUgcm93LlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmcgfCBudWxsPn0gQ3Vyc29yIEpTT04gcGF5bG9hZC5cbiAgICovXG4gIGFzeW5jIGxvYWRDdXJzb3Ioc2NvcGVSb3cpIHtcbiAgICB0aGlzLl9hc3NlcnRTY29wZVJvdyhzY29wZVJvdylcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlYWR5KClcblxuICAgIGlmICh0aGlzLl91c2VzTWVtb3J5U3RvcmFnZSgpKSB7XG4gICAgICBjb25zdCBjdXJyZW50U2NvcGUgPSB0aGlzLl9tZW1vcnlTY29wZXMuZ2V0KHNjb3BlUm93LnNjb3BlRGlnZXN0KVxuXG4gICAgICByZXR1cm4gY3VycmVudFNjb3BlPy5pZCA9PT0gc2NvcGVSb3cuaWQgPyBjdXJyZW50U2NvcGUuY3Vyc29yUGF5bG9hZCA6IG51bGxcbiAgICB9XG5cbiAgICByZXR1cm4gYXdhaXQgdGhpcy5fd2l0aERiKGFzeW5jIChkYikgPT4ge1xuICAgICAgY29uc3Qgcm93ID0gYXdhaXQgdGhpcy5fcm93QnlTY29wZURpZ2VzdChkYiwgc2NvcGVSb3cuc2NvcGVEaWdlc3QpXG5cbiAgICAgIHJldHVybiByb3c/LmlkID09PSBzY29wZVJvdy5pZCA/IHJvdy5jdXJzb3JQYXlsb2FkIDogbnVsbFxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogUGVyc2lzdHMgdGhlIGFja25vd2xlZGdlZCBjdXJzb3IgZm9yIGEgc2NvcGUgcm93LlxuICAgKiBAcGFyYW0ge1N5bmNTY29wZVJvd30gc2NvcGVSb3cgLSBTY29wZSByb3cuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zeW5jLWFwaS1jbGllbnQtdHlwZXMuanNcIikuU3luY0N1cnNvcn0gY3Vyc29yIC0gQWNrbm93bGVkZ2VkIGN1cnNvci5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBhc3luYyBzYXZlQ3Vyc29yKHNjb3BlUm93LCBjdXJzb3IpIHtcbiAgICB0aGlzLl9hc3NlcnRTY29wZVJvdyhzY29wZVJvdylcbiAgICBpZiAoIWN1cnNvcikgcmV0dXJuXG5cbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlYWR5KClcblxuICAgIGNvbnN0IGN1cnNvclBheWxvYWQgPSBKU09OLnN0cmluZ2lmeShjdXJzb3IpXG5cbiAgICBpZiAodGhpcy5fdXNlc01lbW9yeVN0b3JhZ2UoKSkge1xuICAgICAgY29uc3QgbWVtb3J5U2NvcGUgPSB0aGlzLl9tZW1vcnlTY29wZXMuZ2V0KHNjb3BlUm93LnNjb3BlRGlnZXN0KVxuXG4gICAgICBpZiAoIW1lbW9yeVNjb3BlKSB0aHJvdyBuZXcgRXJyb3IoYE5vIHN5bmMgc2NvcGUgZm91bmQgZm9yOiAke3Njb3BlUm93LnNjb3BlRGlnZXN0fWApXG4gICAgICBpZiAobWVtb3J5U2NvcGUuaWQgIT09IHNjb3BlUm93LmlkIHx8IG1lbW9yeVNjb3BlLnN0YXRlICE9PSBcImFjdGl2ZVwiKSByZXR1cm5cblxuICAgICAgbWVtb3J5U2NvcGUuY3Vyc29yUGF5bG9hZCA9IGN1cnNvclBheWxvYWRcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGF3YWl0IHRoaXMuX3dpdGhEYihhc3luYyAoZGIpID0+IHtcbiAgICAgIGF3YWl0IGRiLnVwZGF0ZSh7XG4gICAgICAgIGNvbmRpdGlvbnM6IHtpZDogc2NvcGVSb3cuaWQsIHNjb3BlX2RpZ2VzdDogc2NvcGVSb3cuc2NvcGVEaWdlc3QsIHN0YXRlOiBcImFjdGl2ZVwifSxcbiAgICAgICAgZGF0YToge2N1cnNvcl9qc29uOiBjdXJzb3JQYXlsb2FkLCB1cGRhdGVkX2F0OiBuZXcgRGF0ZSgpfSxcbiAgICAgICAgdGFibGVOYW1lOiBUQUJMRV9OQU1FXG4gICAgICB9KVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogRGVhY3RpdmF0ZXMgdGhlIHNjb3BlIHJvdyBmb3IgYSBzZXJpYWxpemVkIHNjb3BlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vc3luYy1jbGllbnQtdHlwZXMuanNcIikuU2VyaWFsaXplZFN5bmNTY29wZX0gc2NvcGUgLSBTZXJpYWxpemVkIHN5bmMgc2NvcGUuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgZGVhY3RpdmF0ZShzY29wZSkge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVhZHkoKVxuXG4gICAgY29uc3QgZGlnZXN0ID0gc2NvcGVEaWdlc3RGb3JTY29wZShzY29wZSlcblxuICAgIGlmICh0aGlzLl91c2VzTWVtb3J5U3RvcmFnZSgpKSB7XG4gICAgICBjb25zdCBtZW1vcnlTY29wZSA9IHRoaXMuX21lbW9yeVNjb3Blcy5nZXQoZGlnZXN0KVxuXG4gICAgICBpZiAobWVtb3J5U2NvcGUpIG1lbW9yeVNjb3BlLnN0YXRlID0gXCJyZW1vdmVkXCJcblxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy5fd2l0aERiKGFzeW5jIChkYikgPT4ge1xuICAgICAgYXdhaXQgZGIudXBkYXRlKHtjb25kaXRpb25zOiB7c2NvcGVfZGlnZXN0OiBkaWdlc3R9LCBkYXRhOiB7c3RhdGU6IFwicmVtb3ZlZFwiLCB1cGRhdGVkX2F0OiBuZXcgRGF0ZSgpfSwgdGFibGVOYW1lOiBUQUJMRV9OQU1FfSlcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIEF0b21pY2FsbHkgZGVhY3RpdmF0ZXMgc2VsZWN0ZWQgc2NvcGVzLCBjbGVhcnMgdGhlaXIgY3Vyc29ycyBhbmQgcm90YXRlc1xuICAgKiB0aGVpciByb3cgaWRlbnRpdGllcy4gQSBjdXJzb3Igc2F2ZSBjYXJyeWluZyBhIHByZS1yZXNldCByb3cgaWRlbnRpdHkgY2FuXG4gICAqIHRoZXJlZm9yZSBuZXZlciByZXBvcHVsYXRlIHRoZSByZXNldCBzY29wZS4gVGhlIG9wdGlvbmFsIGNsZWFudXAgaG9vayBydW5zXG4gICAqIGluc2lkZSB0aGUgc2FtZSBkYXRhYmFzZSB0cmFuc2FjdGlvbiwgYWxsb3dpbmcgYW4gYXBwIHRvIHB1cmdlIHRoZSBsb2NhbFxuICAgKiByb3dzIG93bmVkIGJ5IHRob3NlIHNjb3BlcyB3aXRob3V0IGEgY3Vyc29yL2NhY2hlIHNwbGl0LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vc3luYy1jbGllbnQtdHlwZXMuanNcIikuU2VyaWFsaXplZFN5bmNTY29wZVtdfSBzY29wZXMgLSBTZWxlY3RlZCBzY29wZXMgdG8gcmVzZXQuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBbb3B0aW9uc10gLSBSZXNldCBvcHRpb25zLlxuICAgKiBAcGFyYW0geyhhcmdzOiB7Y29ubmVjdGlvbjogaW1wb3J0KFwiLi4vZGF0YWJhc2UvZHJpdmVycy9iYXNlLmpzXCIpLmRlZmF1bHQgfCBudWxsLCBzY29wZXM6IGltcG9ydChcIi4vc3luYy1jbGllbnQtdHlwZXMuanNcIikuU2VyaWFsaXplZFN5bmNTY29wZVtdfSkgPT4gUHJvbWlzZTx2b2lkPiB8IHZvaWR9IFtvcHRpb25zLmNsZWFudXBdIC0gQXBwLW93bmVkIGxvY2FsLXJvdyBjbGVhbnVwIGhvb2suXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgcmVzZXQoc2NvcGVzLCB7Y2xlYW51cH0gPSB7fSkge1xuICAgIGlmICghQXJyYXkuaXNBcnJheShzY29wZXMpIHx8IHNjb3Blcy5sZW5ndGggPT09IDApIHRocm93IG5ldyBFcnJvcihcIlN5bmNTY29wZVN0b3JlLnJlc2V0IHJlcXVpcmVzIGF0IGxlYXN0IG9uZSBzZXJpYWxpemVkIHNjb3BlXCIpXG4gICAgaWYgKGNsZWFudXAgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgY2xlYW51cCAhPT0gXCJmdW5jdGlvblwiKSB0aHJvdyBuZXcgRXJyb3IoXCJTeW5jU2NvcGVTdG9yZS5yZXNldCBjbGVhbnVwIG11c3QgYmUgYSBmdW5jdGlvblwiKVxuXG4gICAgYXdhaXQgdGhpcy5lbnN1cmVSZWFkeSgpXG5cbiAgICBjb25zdCB1bmlxdWVTY29wZXMgPSBbLi4ubmV3IE1hcChzY29wZXMubWFwKChzY29wZSkgPT4gW3Njb3BlRGlnZXN0Rm9yU2NvcGUoc2NvcGUpLCBzY29wZV0pKS52YWx1ZXMoKV1cblxuICAgIGlmICh0aGlzLl91c2VzTWVtb3J5U3RvcmFnZSgpKSB7XG4gICAgICBpZiAoY2xlYW51cCkgYXdhaXQgY2xlYW51cCh7Y29ubmVjdGlvbjogbnVsbCwgc2NvcGVzOiB1bmlxdWVTY29wZXN9KVxuXG4gICAgICBmb3IgKGNvbnN0IHNjb3BlIG9mIHVuaXF1ZVNjb3BlcykgdGhpcy5fcmVzZXRNZW1vcnlTY29wZShzY29wZSlcblxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy5fd2l0aERiKGFzeW5jIChkYikgPT4ge1xuICAgICAgYXdhaXQgZGIudHJhbnNhY3Rpb24oYXN5bmMgKCkgPT4ge1xuICAgICAgICBpZiAoY2xlYW51cCkgYXdhaXQgY2xlYW51cCh7Y29ubmVjdGlvbjogZGIsIHNjb3BlczogdW5pcXVlU2NvcGVzfSlcblxuICAgICAgICBmb3IgKGNvbnN0IHNjb3BlIG9mIHVuaXF1ZVNjb3BlcykgYXdhaXQgdGhpcy5fcmVzZXREYXRhYmFzZVNjb3BlKHtkYiwgc2NvcGV9KVxuICAgICAgfSlcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0cyBvbmUgbWVtb3J5LWJhY2tlZCBzY29wZSB3aGlsZSBwcmVzZXJ2aW5nIHJlcGVhdGVkLXJlc2V0IGlkZW1wb3RlbmNlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vc3luYy1jbGllbnQtdHlwZXMuanNcIikuU2VyaWFsaXplZFN5bmNTY29wZX0gc2NvcGUgLSBTY29wZSB0byByZXNldC5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICBfcmVzZXRNZW1vcnlTY29wZShzY29wZSkge1xuICAgIGNvbnN0IGRpZ2VzdCA9IHNjb3BlRGlnZXN0Rm9yU2NvcGUoc2NvcGUpXG4gICAgY29uc3QgbWVtb3J5U2NvcGUgPSB0aGlzLl9tZW1vcnlTY29wZXMuZ2V0KGRpZ2VzdClcblxuICAgIGlmICghbWVtb3J5U2NvcGUgfHwgKG1lbW9yeVNjb3BlLnN0YXRlID09PSBcInJlbW92ZWRcIiAmJiBtZW1vcnlTY29wZS5jdXJzb3JQYXlsb2FkID09PSBudWxsKSkgcmV0dXJuXG5cbiAgICB0aGlzLl9tZW1vcnlTY29wZXMuc2V0KGRpZ2VzdCwge1xuICAgICAgLi4ubWVtb3J5U2NvcGUsXG4gICAgICBjdXJzb3JQYXlsb2FkOiBudWxsLFxuICAgICAgaWQ6IG5ldyBVVUlEKDQpLmZvcm1hdCgpLFxuICAgICAgc3RhdGU6IFwicmVtb3ZlZFwiXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNldHMgb25lIGRhdGFiYXNlLWJhY2tlZCBzY29wZSB3aGlsZSBwcmVzZXJ2aW5nIHJlcGVhdGVkLXJlc2V0IGlkZW1wb3RlbmNlLlxuICAgKiBAcGFyYW0ge3tkYjogaW1wb3J0KFwiLi4vZGF0YWJhc2UvZHJpdmVycy9iYXNlLmpzXCIpLmRlZmF1bHQsIHNjb3BlOiBpbXBvcnQoXCIuL3N5bmMtY2xpZW50LXR5cGVzLmpzXCIpLlNlcmlhbGl6ZWRTeW5jU2NvcGV9fSBhcmdzIC0gRGF0YWJhc2UgYW5kIHNjb3BlLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGFzeW5jIF9yZXNldERhdGFiYXNlU2NvcGUoe2RiLCBzY29wZX0pIHtcbiAgICBjb25zdCBkaWdlc3QgPSBzY29wZURpZ2VzdEZvclNjb3BlKHNjb3BlKVxuICAgIGNvbnN0IGV4aXN0aW5nUm93ID0gYXdhaXQgdGhpcy5fcm93QnlTY29wZURpZ2VzdChkYiwgZGlnZXN0KVxuXG4gICAgaWYgKCFleGlzdGluZ1JvdyB8fCAoZXhpc3RpbmdSb3cuc3RhdGUgPT09IFwicmVtb3ZlZFwiICYmIGV4aXN0aW5nUm93LmN1cnNvclBheWxvYWQgPT09IG51bGwpKSByZXR1cm5cblxuICAgIGF3YWl0IGRiLnVwZGF0ZSh7XG4gICAgICBjb25kaXRpb25zOiB7aWQ6IGV4aXN0aW5nUm93LmlkLCBzY29wZV9kaWdlc3Q6IGRpZ2VzdH0sXG4gICAgICBkYXRhOiB7Y3Vyc29yX2pzb246IG51bGwsIGlkOiBuZXcgVVVJRCg0KS5mb3JtYXQoKSwgc3RhdGU6IFwicmVtb3ZlZFwiLCB1cGRhdGVkX2F0OiBuZXcgRGF0ZSgpfSxcbiAgICAgIHRhYmxlTmFtZTogVEFCTEVfTkFNRVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogV2hldGhlciB0aGUgc3RvcmUgcnVucyB3aXRob3V0IGEgY29uZmlndXJlZCBkYXRhYmFzZS5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgbWVtb3J5IHN0b3JhZ2UgaXMgdXNlZC5cbiAgICovXG4gIF91c2VzTWVtb3J5U3RvcmFnZSgpIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuICF0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0RGF0YWJhc2VDb25maWd1cmF0aW9uKClbdGhpcy5kYXRhYmFzZUlkZW50aWZpZXJdXG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGEgY2FsbGJhY2sgd2l0aCBhIGRhdGFiYXNlIGNvbm5lY3Rpb24uXG4gICAqIEB0ZW1wbGF0ZSBSZXN1bHRcbiAgICogQHBhcmFtIHsoZGI6IGltcG9ydChcIi4uL2RhdGFiYXNlL2RyaXZlcnMvYmFzZS5qc1wiKS5kZWZhdWx0KSA9PiBQcm9taXNlPFJlc3VsdD59IGNhbGxiYWNrIC0gRGF0YWJhc2UgY2FsbGJhY2suXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFJlc3VsdD59IENhbGxiYWNrIHJlc3VsdC5cbiAgICovXG4gIGFzeW5jIF93aXRoRGIoY2FsbGJhY2spIHtcbiAgICBpZiAodGhpcy50ZW5hbnRIYW5kbGUpIHtcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLnRlbmFudEhhbmRsZS5kYXRhYmFzZU9wZXJhdGlvbih7ZGF0YWJhc2VJZGVudGlmaWVyOiB0aGlzLmRhdGFiYXNlSWRlbnRpZmllciwgbmFtZTogXCJUZW5hbnQgc3luYyBzY29wZSBzdG9yZVwifSwgYXN5bmMgKG9wZXJhdGlvbikgPT4ge1xuICAgICAgICByZXR1cm4gYXdhaXQgY2FsbGJhY2sob3BlcmF0aW9uLmNvbm5lY3Rpb24oKSlcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuY29uZmlndXJhdGlvbi5lbnN1cmVDb25uZWN0aW9ucyh7ZGF0YWJhc2VJZGVudGlmaWVyczogW3RoaXMuZGF0YWJhc2VJZGVudGlmaWVyXSwgbmFtZTogXCJTeW5jIHNjb3BlIHN0b3JlXCJ9LCBhc3luYyAoZGJzKSA9PiB7XG4gICAgICBjb25zdCBkYiA9IGRic1t0aGlzLmRhdGFiYXNlSWRlbnRpZmllcl1cblxuICAgICAgaWYgKCFkYikgdGhyb3cgbmV3IEVycm9yKGBObyBkYXRhYmFzZSBjb25uZWN0aW9uIGF2YWlsYWJsZSBmb3IgaWRlbnRpZmllcjogJHt0aGlzLmRhdGFiYXNlSWRlbnRpZmllcn1gKVxuXG4gICAgICByZXR1cm4gYXdhaXQgY2FsbGJhY2soZGIpXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBFbnN1cmVzIHRoZSBzY29wZXMgdGFibGUgZXhpc3RzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2RhdGFiYXNlL2RyaXZlcnMvYmFzZS5qc1wiKS5kZWZhdWx0fSBkYiAtIERhdGFiYXNlIGNvbm5lY3Rpb24uXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPGJvb2xlYW4+fSBXaGV0aGVyIHRoZSB0YWJsZSBoYWQgdG8gYmUgY3JlYXRlZC5cbiAgICovXG4gIGFzeW5jIF9lbnN1cmVTY29wZXNUYWJsZShkYikge1xuICAgIGlmIChhd2FpdCBkYi50YWJsZUV4aXN0cyhUQUJMRV9OQU1FKSkgcmV0dXJuIGZhbHNlXG5cbiAgICBjb25zdCB0YWJsZSA9IG5ldyBUYWJsZURhdGEoVEFCTEVfTkFNRSwge2lmTm90RXhpc3RzOiB0cnVlfSlcblxuICAgIHRhYmxlLnN0cmluZyhcImlkXCIsIHtudWxsOiBmYWxzZSwgcHJpbWFyeUtleTogdHJ1ZX0pXG4gICAgdGFibGUuc3RyaW5nKFwic2NvcGVfZGlnZXN0XCIsIHtpbmRleDogdHJ1ZSwgbnVsbDogZmFsc2V9KVxuICAgIHRhYmxlLnN0cmluZyhcInJlc291cmNlX3R5cGVcIiwge2luZGV4OiB0cnVlLCBudWxsOiBmYWxzZX0pXG4gICAgdGFibGUudGV4dChcImNvbmRpdGlvbnNfanNvblwiLCB7bnVsbDogZmFsc2V9KVxuICAgIHRhYmxlLnRleHQoXCJjdXJzb3JfanNvblwiLCB7bnVsbDogdHJ1ZX0pXG4gICAgdGFibGUuc3RyaW5nKFwic3RhdGVcIiwge2luZGV4OiB0cnVlLCBudWxsOiBmYWxzZX0pXG4gICAgdGFibGUuZGF0ZXRpbWUoXCJjcmVhdGVkX2F0XCIsIHtudWxsOiBmYWxzZX0pXG4gICAgdGFibGUuZGF0ZXRpbWUoXCJ1cGRhdGVkX2F0XCIsIHtudWxsOiBmYWxzZX0pXG5cbiAgICBhd2FpdCBkYi5jcmVhdGVUYWJsZSh0YWJsZSlcblxuICAgIHJldHVybiB0cnVlXG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZXMgYSBzY29wZSByb3cgYnkgaXRzIGRpZ2VzdC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9kYXRhYmFzZS9kcml2ZXJzL2Jhc2UuanNcIikuZGVmYXVsdH0gZGIgLSBEYXRhYmFzZSBjb25uZWN0aW9uLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gZGlnZXN0IC0gRml4ZWQtc2l6ZSBzY29wZSBkaWdlc3QuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFN5bmNTY29wZVJvdyB8IG51bGw+fSBTY29wZSByb3cgb3IgbnVsbC5cbiAgICovXG4gIGFzeW5jIF9yb3dCeVNjb3BlRGlnZXN0KGRiLCBkaWdlc3QpIHtcbiAgICBjb25zdCByb3dzID0gLyoqIEB0eXBlIHtBcnJheTxSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj4+fSAqLyAoYXdhaXQgZGJcbiAgICAgIC5uZXdRdWVyeSgpXG4gICAgICAuZnJvbShUQUJMRV9OQU1FKVxuICAgICAgLndoZXJlKHtzY29wZV9kaWdlc3Q6IGRpZ2VzdH0pXG4gICAgICAubGltaXQoMSlcbiAgICAgIC5yZXN1bHRzKCkpXG5cbiAgICByZXR1cm4gcm93c1swXSA/IHRoaXMuX25vcm1hbGl6ZVNjb3BlUm93KHJvd3NbMF0pIDogbnVsbFxuICB9XG5cbiAgLyoqXG4gICAqIE5vcm1hbGl6ZXMgYSByYXcgc2NvcGUgdGFibGUgcm93LlxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pn0gcm93IC0gUmF3IHRhYmxlIHJvdy5cbiAgICogQHJldHVybnMge1N5bmNTY29wZVJvd30gTm9ybWFsaXplZCBzY29wZSByb3cuXG4gICAqL1xuICBfbm9ybWFsaXplU2NvcGVSb3cocm93KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbmRpdGlvbnM6IC8qKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4+fSAqLyAoSlNPTi5wYXJzZShTdHJpbmcocm93LmNvbmRpdGlvbnNfanNvbikpKSxcbiAgICAgIGN1cnNvclBheWxvYWQ6IHJvdy5jdXJzb3JfanNvbiA9PT0gbnVsbCB8fCByb3cuY3Vyc29yX2pzb24gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBTdHJpbmcocm93LmN1cnNvcl9qc29uKSxcbiAgICAgIGlkOiBTdHJpbmcocm93LmlkKSxcbiAgICAgIHJlc291cmNlVHlwZTogU3RyaW5nKHJvdy5yZXNvdXJjZV90eXBlKSA9PT0gXCJcIiA/IG51bGwgOiBTdHJpbmcocm93LnJlc291cmNlX3R5cGUpLFxuICAgICAgc2NvcGVEaWdlc3Q6IFN0cmluZyhyb3cuc2NvcGVfZGlnZXN0KSxcbiAgICAgIHN0YXRlOiBTdHJpbmcocm93LnN0YXRlKSxcbiAgICAgIHN0b3JlSWRlbnRpdHk6IHRoaXMuc3RvcmVJZGVudGl0eVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZWplY3RzIHBhc3NpbmcgYSBzY29wZSByb3cgY2FwdHVyZWQgZnJvbSBhbm90aGVyIHBoeXNpY2FsIHN0b3JlLlxuICAgKiBAcGFyYW0ge1N5bmNTY29wZVJvd30gc2NvcGVSb3cgLSBTY29wZSByb3cgdG8gdmFsaWRhdGUuXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgX2Fzc2VydFNjb3BlUm93KHNjb3BlUm93KSB7XG4gICAgaWYgKHNjb3BlUm93LnN0b3JlSWRlbnRpdHkgIT09IHRoaXMuc3RvcmVJZGVudGl0eSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU3luYyBzY29wZSByb3cgYmVsb25ncyB0byBhbm90aGVyIHBoeXNpY2FsIHRlbmFudCBkYXRhYmFzZVwiKVxuICAgIH1cbiAgfVxufVxuIl19
@@ -71,16 +71,19 @@ export default class SyncApiClient {
71
71
  * @param {string} args.authenticationToken - Authentication token.
72
72
  * @param {number} [args.batchSize] - Batch size.
73
73
  * @param {import("./sync-client-types.js").SyncClientConflictTrackingConfig} args.conflictTracking - Tracking configuration.
74
- * @param {(payload: {authenticationToken: string, syncs: Array<Record<string, ReturnType<typeof JSON.parse>>>}) => Promise<SyncReplayResponse>} args.postReplay - Transport boundary.
74
+ * @param {(payload: {authenticationToken: string, syncs: Array<Record<string, ReturnType<typeof JSON.parse>>>}, options?: {signal?: AbortSignal}) => Promise<SyncReplayResponse>} args.postReplay - Transport boundary.
75
75
  * @param {(identity: string) => number} args.remoteGeneration - Current remote generation.
76
76
  * @param {string} args.resourceType - Resource whose log records should drain.
77
+ * @param {AbortSignal} [args.signal] - Lifecycle cancellation signal.
77
78
  * @returns {Promise<void>} Resolves when no ready intent remains.
78
79
  */
79
- static async replayConflictTrackedSyncs({authenticationToken, batchSize, conflictTracking, postReplay, remoteGeneration, resourceType}) {
80
+ static async replayConflictTrackedSyncs({authenticationToken, batchSize, conflictTracking, postReplay, remoteGeneration, resourceType, signal}) {
80
81
  const maxBatchSize = this.normalizedBatchSize(batchSize)
81
82
 
82
83
  while (true) {
84
+ throwIfSyncAborted(signal)
83
85
  const records = await conflictTracking.mutationLog.records()
86
+ throwIfSyncAborted(signal)
84
87
  const statuses = new Map(records.map((record) => [record.mutation.clientMutationId, record.status]))
85
88
  const pending = records.filter((record) => record.status === "pending" && record.mutation.model === resourceType)
86
89
  const ready = pending.filter((record) => record.dependencies.every((dependency) => statuses.get(dependency.clientMutationId) === "synced"))
@@ -92,13 +95,15 @@ export default class SyncApiClient {
92
95
  const response = await postReplay({
93
96
  authenticationToken,
94
97
  syncs: groups.map((group) => this.conflictReplayPayload(group))
95
- })
98
+ }, {signal})
96
99
 
100
+ throwIfSyncAborted(signal)
97
101
  this.ensureSuccessfulResponse(response)
98
102
 
99
103
  const responsesById = new Map((response.syncs || []).map((result) => [String(result.id), result]))
100
104
 
101
105
  for (const group of groups) {
106
+ throwIfSyncAborted(signal)
102
107
  const result = responsesById.get(group[0].mutation.clientMutationId)
103
108
 
104
109
  if (!result) throw new Error(`Sync response missing result for mutation ${group[0].mutation.clientMutationId}`)
@@ -108,6 +113,7 @@ export default class SyncApiClient {
108
113
 
109
114
  for (const record of group) {
110
115
  await applySyncReplayResultToLocalMutationLog({mutationLog: conflictTracking.mutationLog, record, result: /** @type {Record<string, ReturnType<typeof JSON.parse>>} */ (result)})
116
+ throwIfSyncAborted(signal)
111
117
  }
112
118
 
113
119
  if (["successful", "duplicate"].includes(result.syncState) && result.serverVersion !== undefined) {
@@ -115,6 +121,7 @@ export default class SyncApiClient {
115
121
 
116
122
  if (remoteGeneration(identity) === generations.get(group[0].mutation.clientMutationId)) {
117
123
  await this.rebaseConflictSuccessor({conflictTracking, predecessor: group[group.length - 1], serverVersion: result.serverVersion})
124
+ throwIfSyncAborted(signal)
118
125
  }
119
126
  }
120
127
  }
@@ -261,6 +268,7 @@ export default class SyncApiClient {
261
268
  * @param {(payload: SyncChangesRequest) => Promise<SyncChangesResponse>} args.postChanges - Posts one changes request.
262
269
  * @param {Record<string, SyncResourceConfig>} args.resources - Resource policies.
263
270
  * @param {(progress: import("./sync-api-client-types.js").SyncPullProgress) => void} [args.onProgress] - Progress callback.
271
+ * @param {AbortSignal} [args.signal] - Lifecycle cancellation signal.
264
272
  * @returns {Promise<SyncChangesResult>} Pull result.
265
273
  */
266
274
  static async pullChangesWithCursor(args) {
@@ -271,7 +279,8 @@ export default class SyncApiClient {
271
279
  saveCursor: async (cursor) => await this.saveSyncCursor({cursor, cursorKey: args.cursorKey, cursorModel: args.cursorModel}),
272
280
  postChanges: args.postChanges,
273
281
  applySync: this.resourceApplier(args.resources),
274
- onProgress: args.onProgress
282
+ onProgress: args.onProgress,
283
+ signal: args.signal
275
284
  })
276
285
  }
277
286
 
@@ -309,12 +318,14 @@ export default class SyncApiClient {
309
318
  * @param {number} [args.batchSize] - Max syncs per request. Defaults to 100.
310
319
  * @param {() => Promise<SyncCursor | string | null | undefined>} args.loadCursor - Loads the persisted local cursor.
311
320
  * @param {(cursor: SyncCursor) => Promise<void>} args.saveCursor - Persists the final acknowledged cursor.
312
- * @param {(payload: SyncChangesRequest) => Promise<SyncChangesResponse>} args.postChanges - Posts one changes request.
321
+ * @param {(payload: SyncChangesRequest, options?: {signal?: AbortSignal}) => Promise<SyncChangesResponse>} args.postChanges - Posts one changes request.
313
322
  * @param {(sync: SyncChangeEnvelope) => Promise<SyncChangeApplyResult>} args.applySync - Applies one normalized sync row locally.
314
323
  * @param {(progress: import("./sync-api-client-types.js").SyncPullProgress) => void} [args.onProgress] - Progress callback invoked per applied page (and once for an empty pull) with the applied counts and the stable server total.
324
+ * @param {AbortSignal} [args.signal] - Lifecycle cancellation signal.
315
325
  * @returns {Promise<SyncChangesResult>} Pull result.
316
326
  */
317
327
  static async pullChanges(args) {
328
+ throwIfSyncAborted(args.signal)
318
329
  let afterCursor = this.syncCursorFromPayload(await args.loadCursor())
319
330
  let upToCursor = null
320
331
  let pages = 0
@@ -326,7 +337,9 @@ export default class SyncApiClient {
326
337
  const batchSize = this.normalizedBatchSize(args.batchSize)
327
338
 
328
339
  while (true) {
340
+ throwIfSyncAborted(args.signal)
329
341
  const changesResponse = await this.changesPage({...args, afterCursor, batchSize, upToCursor})
342
+ throwIfSyncAborted(args.signal)
330
343
  const syncs = changesResponse.syncs
331
344
 
332
345
  if (!upToCursor) upToCursor = changesResponse.upToCursor
@@ -341,6 +354,7 @@ export default class SyncApiClient {
341
354
  if (syncs.length === 0) {
342
355
  // Report the terminal progress once for an entirely empty pull so consumers observe
343
356
  // total 0; a pull that already applied pages reported its final counts on its last page.
357
+ throwIfSyncAborted(args.signal)
344
358
  if (pages === 0 && args.onProgress) args.onProgress({pages, syncedCount, total})
345
359
 
346
360
  break
@@ -354,7 +368,9 @@ export default class SyncApiClient {
354
368
  // waiting for the rest of the pull.
355
369
  await recordChanges.batch(async () => {
356
370
  for (const sync of syncs) {
371
+ throwIfSyncAborted(args.signal)
357
372
  const applyResult = await args.applySync(sync)
373
+ throwIfSyncAborted(args.signal)
358
374
  const resourceType = applyResult.resourceType ?? sync.resourceType()
359
375
 
360
376
  changed ||= applyResult.changed === true
@@ -369,11 +385,14 @@ export default class SyncApiClient {
369
385
 
370
386
  afterCursor = changesResponse.nextCursor
371
387
 
388
+ throwIfSyncAborted(args.signal)
372
389
  if (args.onProgress) args.onProgress({pages, syncedCount, total})
373
390
  if (syncs.length < batchSize) break
374
391
  }
375
392
 
393
+ throwIfSyncAborted(args.signal)
376
394
  if (afterCursor) await args.saveCursor(afterCursor)
395
+ throwIfSyncAborted(args.signal)
377
396
 
378
397
  return {changed, pages, resourceChanged, resourceCounts, syncedCount, total}
379
398
  }
@@ -384,18 +403,21 @@ export default class SyncApiClient {
384
403
  * @param {SyncCursor} args.afterCursor - Last acknowledged cursor.
385
404
  * @param {string} args.authenticationToken - Auth token.
386
405
  * @param {number} args.batchSize - Page size.
387
- * @param {(payload: SyncChangesRequest) => Promise<SyncChangesResponse>} args.postChanges - Changes poster.
406
+ * @param {(payload: SyncChangesRequest, options?: {signal?: AbortSignal}) => Promise<SyncChangesResponse>} args.postChanges - Changes poster.
407
+ * @param {AbortSignal} [args.signal] - Lifecycle cancellation signal.
388
408
  * @param {SyncCursor} args.upToCursor - Snapshot upper-bound cursor.
389
409
  * @returns {Promise<{nextCursor: SyncCursor, syncs: SyncChangeEnvelope[], total: number | null, upToCursor: SyncCursor}>} Normalized changes page.
390
410
  */
391
- static async changesPage({afterCursor, authenticationToken, batchSize, postChanges, upToCursor}) {
411
+ static async changesPage({afterCursor, authenticationToken, batchSize, postChanges, signal, upToCursor}) {
412
+ throwIfSyncAborted(signal)
392
413
  const response = await postChanges({
393
414
  authenticationToken,
394
415
  limit: batchSize,
395
416
  ...this.cursorPayload("after", afterCursor),
396
417
  ...this.cursorPayload("upTo", upToCursor)
397
- })
418
+ }, {signal})
398
419
 
420
+ throwIfSyncAborted(signal)
399
421
  this.ensureSuccessfulChangesResponse(response)
400
422
 
401
423
  const syncs = /** @type {unknown[]} */ (response.syncs)
@@ -578,7 +600,8 @@ export default class SyncApiClient {
578
600
  * @param {string} args.authenticationToken - Auth token to send with replay requests.
579
601
  * @param {number} [args.batchSize] - Max syncs per request.
580
602
  * @param {ReturnType<typeof JSON.parse>} args.syncModel - Local Sync model class.
581
- * @param {(payload: {authenticationToken: string, syncs: Array<Record<string, ReturnType<typeof JSON.parse>>>}) => Promise<SyncReplayResponse>} args.postReplay - Replay poster.
603
+ * @param {(payload: {authenticationToken: string, syncs: Array<Record<string, ReturnType<typeof JSON.parse>>>}, options?: {signal?: AbortSignal}) => Promise<SyncReplayResponse>} args.postReplay - Replay poster.
604
+ * @param {AbortSignal} [args.signal] - Lifecycle cancellation signal.
582
605
  * @returns {Promise<void>}
583
606
  */
584
607
  static async replayLocalSyncs(args) {
@@ -602,6 +625,7 @@ export default class SyncApiClient {
602
625
  },
603
626
  pendingSyncs: async () => await args.syncModel.preload({resource: true}).where({state: "pending"}).order("created_at").toArray(),
604
627
  postReplay: args.postReplay,
628
+ signal: args.signal,
605
629
  syncId: (sync) => (/** @type {{id: () => string | number | null | undefined}} */ (sync)).id(),
606
630
  syncPayload: (sync) => {
607
631
  postedSnapshotsBySyncId.set(String((/** @type {{id: () => string | number | null | undefined}} */ (sync)).id()), this.localSyncReplaySnapshot(sync))
@@ -810,15 +834,19 @@ export default class SyncApiClient {
810
834
  * @param {() => Promise<Array<unknown>>} args.pendingSyncs - Loads pending local sync rows in replay order.
811
835
  * @param {(sync: unknown) => string | number | null | undefined} args.syncId - Returns the local sync id.
812
836
  * @param {(sync: unknown) => Record<string, ReturnType<typeof JSON.parse>>} args.syncPayload - Builds the API sync envelope.
813
- * @param {(payload: {authenticationToken: string, syncs: Array<Record<string, ReturnType<typeof JSON.parse>>>}) => Promise<SyncReplayResponse>} args.postReplay - Posts one replay request.
837
+ * @param {(payload: {authenticationToken: string, syncs: Array<Record<string, ReturnType<typeof JSON.parse>>>}, options?: {signal?: AbortSignal}) => Promise<SyncReplayResponse>} args.postReplay - Posts one replay request.
814
838
  * @param {(sync: unknown, response: SyncReplayItem) => Promise<void>} args.markSuccessful - Marks one sync as successful locally.
839
+ * @param {AbortSignal} [args.signal] - Lifecycle cancellation signal.
815
840
  * @returns {Promise<void>} Resolves after all batches are replayed.
816
841
  */
817
842
  static async replayPending(args) {
843
+ throwIfSyncAborted(args.signal)
818
844
  const pendingSyncs = await args.pendingSyncs()
845
+ throwIfSyncAborted(args.signal)
819
846
  const batchSize = this.normalizedBatchSize(args.batchSize)
820
847
 
821
848
  for (let offset = 0; offset < pendingSyncs.length; offset += batchSize) {
849
+ throwIfSyncAborted(args.signal)
822
850
  await this.replayBatch({...args, pendingSyncs: pendingSyncs.slice(offset, offset + batchSize)})
823
851
  }
824
852
  }
@@ -830,14 +858,16 @@ export default class SyncApiClient {
830
858
  * @param {Array<unknown>} args.pendingSyncs - Batch syncs.
831
859
  * @param {(sync: unknown) => string | number | null | undefined} args.syncId - Sync id getter.
832
860
  * @param {(sync: unknown) => Record<string, ReturnType<typeof JSON.parse>>} args.syncPayload - Payload builder.
833
- * @param {(payload: {authenticationToken: string, syncs: Array<Record<string, ReturnType<typeof JSON.parse>>>}) => Promise<SyncReplayResponse>} args.postReplay - Replay poster.
861
+ * @param {(payload: {authenticationToken: string, syncs: Array<Record<string, ReturnType<typeof JSON.parse>>>}, options?: {signal?: AbortSignal}) => Promise<SyncReplayResponse>} args.postReplay - Replay poster.
834
862
  * @param {(sync: unknown, response: SyncReplayItem) => Promise<void>} args.markSuccessful - Success hook.
863
+ * @param {AbortSignal} [args.signal] - Lifecycle cancellation signal.
835
864
  * @returns {Promise<void>} Resolves after the batch is acknowledged.
836
865
  */
837
866
  static async replayBatch(args) {
838
- const {authenticationToken, markSuccessful, pendingSyncs, postReplay, syncId, syncPayload} = args
867
+ const {authenticationToken, markSuccessful, pendingSyncs, postReplay, signal, syncId, syncPayload} = args
839
868
 
840
869
  if (pendingSyncs.length === 0) return
870
+ throwIfSyncAborted(signal)
841
871
 
842
872
  const syncsById = new Map()
843
873
 
@@ -850,11 +880,13 @@ export default class SyncApiClient {
850
880
  const response = await postReplay({
851
881
  authenticationToken,
852
882
  syncs: pendingSyncs.map((sync) => syncPayload(sync))
853
- })
883
+ }, {signal})
854
884
 
885
+ throwIfSyncAborted(signal)
855
886
  this.ensureSuccessfulResponse(response)
856
887
 
857
888
  for (const syncResponse of response.syncs || []) {
889
+ throwIfSyncAborted(signal)
858
890
  const sync = syncsById.get(String(syncResponse.id))
859
891
 
860
892
  if (!sync) continue
@@ -863,6 +895,7 @@ export default class SyncApiClient {
863
895
  }
864
896
 
865
897
  await markSuccessful(sync, syncResponse)
898
+ throwIfSyncAborted(signal)
866
899
  }
867
900
  }
868
901
 
@@ -887,3 +920,15 @@ export default class SyncApiClient {
887
920
  return Math.floor(batchSize)
888
921
  }
889
922
  }
923
+
924
+ /**
925
+ * Throws the exact abort reason at lifecycle boundaries so callers can
926
+ * distinguish an expected cooperative stop from transport or apply failures.
927
+ * @param {AbortSignal | undefined} signal - Lifecycle signal.
928
+ * @returns {void}
929
+ */
930
+ function throwIfSyncAborted(signal) {
931
+ if (!signal?.aborted) return
932
+
933
+ throw signal.reason instanceof Error ? signal.reason : new Error("Sync operation aborted")
934
+ }
@@ -97,6 +97,26 @@
97
97
  * @property {import("../tenants/tenant-handle.js").default} [tenantHandle] - Immutable tenant handle binding every local sync state transition.
98
98
  */
99
99
 
100
+ /**
101
+ * Local cleanup hook that runs transactionally with selected scope resets.
102
+ * @typedef {(args: {connection: import("../database/drivers/base.js").default | null, scopes: SerializedSyncScope[]}) => Promise<void> | void} SyncClientScopeCleanup
103
+ */
104
+
105
+ /**
106
+ * Options for stopping and resetting a sync client lifecycle.
107
+ * @typedef {object} SyncClientStopOptions
108
+ * @property {SyncClientScopeCleanup} [cleanup] - App-owned local-row purge run atomically with resetScopes.
109
+ * @property {SerializedSyncScope[]} [resetScopes] - Selected scope rows to deactivate and restart from a null cursor.
110
+ */
111
+
112
+ /**
113
+ * Options for atomically replacing the external identity read by sync.client.
114
+ * @typedef {SyncClientStopOptions & {
115
+ * replace: () => Promise<void> | void,
116
+ * subscribeUserScope?: boolean
117
+ * }} SyncClientReplaceIdentityOptions
118
+ */
119
+
100
120
  /**
101
121
  * Internal derived sync client configuration built by the SyncClient
102
122
  * constructor — not an app-facing API.
@@ -107,8 +127,8 @@
107
127
  * @property {() => boolean | Promise<boolean>} [isOnline] - Connectivity gate for pulls and replays. Defaults to always online.
108
128
  * @property {(args: {scope: SerializedSyncScope}) => string | null | Promise<string | null>} [legacyCursor] - Seeds a newly declared scope's cursor (e.g. from a pre-scope cursor store) so devices don't re-pull everything.
109
129
  * @property {(error: Error) => void} [onError] - Reports background replay/pull failures. Defaults to rethrowing.
110
- * @property {(payload: import("./sync-api-client-types.js").SyncChangesRequest & {scope: SerializedSyncScope}) => Promise<import("./sync-api-client-types.js").SyncChangesResponse>} postChanges - Posts one changes request.
111
- * @property {(payload: {authenticationToken: string, syncs: Array<Record<string, ReturnType<typeof JSON.parse>>>}) => Promise<import("./sync-api-client-types.js").SyncReplayResponse>} postReplay - Posts one replay request.
130
+ * @property {(payload: import("./sync-api-client-types.js").SyncChangesRequest & {scope: SerializedSyncScope}, options?: {signal?: AbortSignal}) => Promise<import("./sync-api-client-types.js").SyncChangesResponse>} postChanges - Posts one changes request.
131
+ * @property {(payload: {authenticationToken: string, syncs: Array<Record<string, ReturnType<typeof JSON.parse>>>}, options?: {signal?: AbortSignal}) => Promise<import("./sync-api-client-types.js").SyncReplayResponse>} postReplay - Posts one replay request.
112
132
  * @property {import("../configuration-types.js").VelociousSyncClientRealtimeConfiguration} [realtime] - Realtime push configuration consumed by `subscribeRealtime(...)`.
113
133
  * @property {import("../remote-request-context.js").RemoteRequestContext} requestContext - Immutable scalar context captured for this client.
114
134
  * @property {Record<string, SyncClientResourceConfig>} resources - Derived resource policies keyed by resource/model name.