sonamu 0.9.20 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/_rolldown/runtime.js +36 -0
- package/dist/ai/agents/agent.js +5 -7
- package/dist/ai/agents/index.js +1 -2
- package/dist/ai/agents/types.js +1 -1
- package/dist/ai/index.js +1 -2
- package/dist/ai/providers/rtzr/api.js +2 -3
- package/dist/ai/providers/rtzr/error.js +14 -29
- package/dist/ai/providers/rtzr/index.js +1 -2
- package/dist/ai/providers/rtzr/model.js +13 -20
- package/dist/ai/providers/rtzr/options.js +2 -3
- package/dist/ai/providers/rtzr/provider.js +2 -3
- package/dist/ai/providers/rtzr/utils.js +12 -21
- package/dist/api/base-frame.js +4 -4
- package/dist/api/caster.js +21 -38
- package/dist/api/code-converters.js +41 -98
- package/dist/api/config.d.ts +1 -10
- package/dist/api/config.d.ts.map +1 -1
- package/dist/api/config.js +9 -8
- package/dist/api/context.js +2 -3
- package/dist/api/decorators.js +80 -116
- package/dist/api/index.js +2 -3
- package/dist/api/secret.js +6 -10
- package/dist/api/sonamu.d.ts.map +1 -1
- package/dist/api/sonamu.js +200 -387
- package/dist/api/validator.js +5 -8
- package/dist/api/websocket-helpers.js +21 -32
- package/dist/auth/audit-log/builders.js +2 -3
- package/dist/auth/audit-log/events.js +2 -2
- package/dist/auth/audit-log/plugin.js +30 -61
- package/dist/auth/audit-log-ingestor.js +19 -41
- package/dist/auth/auth-generator.js +16 -41
- package/dist/auth/better-auth-entities.js +3 -4
- package/dist/auth/index.js +2 -3
- package/dist/auth/knex-adapter.js +18 -45
- package/dist/auth/plugins/entity-definitions/admin.js +2 -2
- package/dist/auth/plugins/entity-definitions/anonymous.js +2 -2
- package/dist/auth/plugins/entity-definitions/api-key.js +2 -2
- package/dist/auth/plugins/entity-definitions/audit-log.js +2 -2
- package/dist/auth/plugins/entity-definitions/index.js +2 -3
- package/dist/auth/plugins/entity-definitions/jwt.js +2 -2
- package/dist/auth/plugins/entity-definitions/organization.js +2 -2
- package/dist/auth/plugins/entity-definitions/passkey.js +2 -2
- package/dist/auth/plugins/entity-definitions/phone-number.js +2 -2
- package/dist/auth/plugins/entity-definitions/sso.js +2 -2
- package/dist/auth/plugins/entity-definitions/two-factor.js +2 -2
- package/dist/auth/plugins/entity-definitions/types.js +1 -1
- package/dist/auth/plugins/entity-definitions/username.js +2 -2
- package/dist/auth/plugins/index.js +1 -2
- package/dist/auth/plugins/wrappers/admin.js +2 -3
- package/dist/auth/plugins/wrappers/anonymous.js +2 -3
- package/dist/auth/plugins/wrappers/api-key.js +2 -3
- package/dist/auth/plugins/wrappers/index.js +1 -2
- package/dist/auth/plugins/wrappers/jwt.js +2 -3
- package/dist/auth/plugins/wrappers/organization.js +2 -3
- package/dist/auth/plugins/wrappers/passkey.js +2 -3
- package/dist/auth/plugins/wrappers/phone-number.js +2 -3
- package/dist/auth/plugins/wrappers/sso.js +2 -3
- package/dist/auth/plugins/wrappers/two-factor.js +2 -3
- package/dist/auth/plugins/wrappers/username.js +2 -3
- package/dist/bin/build-config.js +2 -2
- package/dist/bin/cli.js +151 -258
- package/dist/bin/fixture.d.ts.map +1 -1
- package/dist/bin/fixture.js +55 -97
- package/dist/bin/hmr-hook-register.js +3 -3
- package/dist/bin/migrate-targets.d.ts +3 -0
- package/dist/bin/migrate-targets.d.ts.map +1 -0
- package/dist/bin/migrate-targets.js +11 -0
- package/dist/bin/test-command.js +25 -55
- package/dist/bin/ts-loader-register.js +5 -6
- package/dist/bin/ts-loader-registration.js +6 -13
- package/dist/cache/cache-manager.js +3 -4
- package/dist/cache/decorator.js +11 -21
- package/dist/cache/drivers.js +2 -3
- package/dist/cache/index.js +2 -3
- package/dist/cache/types.js +1 -1
- package/dist/cache-control/cache-control.js +21 -34
- package/dist/cache-control/types.js +1 -1
- package/dist/compress/compress.js +10 -10
- package/dist/compress/index.js +1 -2
- package/dist/compress/types.js +1 -1
- package/dist/cone/cone-generator.js +25 -63
- package/dist/database/_batch_update.js +26 -46
- package/dist/database/base-model.js +44 -97
- package/dist/database/base-model.types.js +1 -1
- package/dist/database/db.d.ts +8 -14
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +127 -72
- package/dist/database/knex.js +5 -8
- package/dist/database/puri-subset.types.js +1 -1
- package/dist/database/puri-wrapper.js +11 -15
- package/dist/database/puri.js +117 -234
- package/dist/database/puri.types.js +3 -4
- package/dist/database/transaction-context.js +4 -5
- package/dist/database/upsert-builder.js +109 -176
- package/dist/dict/en.d.ts +1 -0
- package/dist/dict/en.d.ts.map +1 -1
- package/dist/dict/en.js +4 -4
- package/dist/dict/index.js +2 -3
- package/dist/dict/ko.d.ts +1 -0
- package/dist/dict/ko.d.ts.map +1 -1
- package/dist/dict/ko.js +4 -4
- package/dist/dict/rc-keys.js +3 -4
- package/dist/dict/sd.js +8 -19
- package/dist/dict/sonamu-dictionary.js +141 -284
- package/dist/dict/types.js +1 -1
- package/dist/dict/utils.js +4 -5
- package/dist/entity/entity-manager.d.ts +2 -2
- package/dist/entity/entity-manager.js +34 -82
- package/dist/entity/entity-template-cone.js +33 -66
- package/dist/entity/entity.js +156 -310
- package/dist/env.d.ts +14 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +75 -0
- package/dist/exceptions/error-handler.js +2 -3
- package/dist/exceptions/so-exceptions.js +7 -5
- package/dist/filter/index.js +1 -2
- package/dist/filter/types.js +3 -4
- package/dist/filter/utils.js +21 -54
- package/dist/index.js +8 -7
- package/dist/logger/category.js +6 -12
- package/dist/logger/configure.js +23 -34
- package/dist/migration/code-generation.js +146 -314
- package/dist/migration/index-where-predicate.js +52 -144
- package/dist/migration/migration-set.js +19 -33
- package/dist/migration/migrator.d.ts +2 -0
- package/dist/migration/migrator.d.ts.map +1 -1
- package/dist/migration/migrator.js +69 -53
- package/dist/migration/postgresql-schema-reader.js +126 -225
- package/dist/migration/slack-confirm.d.ts +1 -0
- package/dist/migration/slack-confirm.d.ts.map +1 -1
- package/dist/migration/slack-confirm.js +28 -38
- package/dist/migration/types.js +1 -1
- package/dist/naite/messaging-types.js +1 -1
- package/dist/naite/naite-reporter.js +15 -32
- package/dist/naite/naite.js +43 -76
- package/dist/ssr/index.js +6 -9
- package/dist/ssr/registry.js +10 -18
- package/dist/ssr/renderer.js +10 -21
- package/dist/ssr/types.js +1 -1
- package/dist/storage/base-file.js +5 -10
- package/dist/storage/buffered-file.js +3 -4
- package/dist/storage/drivers.js +2 -3
- package/dist/storage/index.js +2 -3
- package/dist/storage/s3-driver.js +5 -9
- package/dist/storage/storage-manager.js +5 -5
- package/dist/storage/types.js +1 -1
- package/dist/storage/uploaded-file.js +4 -6
- package/dist/stream/index.js +1 -2
- package/dist/stream/sse.js +8 -13
- package/dist/stream/ws-audience-resolver.js +5 -5
- package/dist/stream/ws-audience.js +3 -4
- package/dist/stream/ws-cluster-bus.js +3 -4
- package/dist/stream/ws-core.js +1 -1
- package/dist/stream/ws-delivery.js +11 -25
- package/dist/stream/ws-local-connection-store.js +9 -18
- package/dist/stream/ws-presence-store.js +43 -97
- package/dist/stream/ws-registry.js +17 -22
- package/dist/stream/ws-telemetry-memory.js +38 -45
- package/dist/stream/ws-telemetry-trace.js +4 -6
- package/dist/stream/ws-telemetry.js +82 -135
- package/dist/stream/ws.js +47 -91
- package/dist/syncer/api-parser.js +81 -147
- package/dist/syncer/checksum.js +9 -20
- package/dist/syncer/code-generator.js +29 -47
- package/dist/syncer/entity-operations.js +17 -27
- package/dist/syncer/event-batcher.js +8 -15
- package/dist/syncer/file-patterns.js +3 -4
- package/dist/syncer/file-tracking.js +6 -10
- package/dist/syncer/index.js +1 -2
- package/dist/syncer/module-loader.js +10 -26
- package/dist/syncer/syncer-actions.js +19 -37
- package/dist/syncer/syncer.js +46 -98
- package/dist/syncer/watcher.js +12 -26
- package/dist/tasks/decorator.js +7 -11
- package/dist/tasks/step-wrapper.js +7 -8
- package/dist/tasks/workflow-manager.js +18 -25
- package/dist/template/entity-converter.js +40 -64
- package/dist/template/helpers.js +32 -63
- package/dist/template/implementations/entity.template.js +7 -11
- package/dist/template/implementations/entry-server.template.js +2 -3
- package/dist/template/implementations/generated.template.js +25 -51
- package/dist/template/implementations/generated_http.template.js +31 -58
- package/dist/template/implementations/generated_sso.template.js +45 -85
- package/dist/template/implementations/init_types.template.js +4 -7
- package/dist/template/implementations/model.template.js +5 -10
- package/dist/template/implementations/model_test.template.js +2 -3
- package/dist/template/implementations/queries.template.js +4 -7
- package/dist/template/implementations/sd.template.js +17 -35
- package/dist/template/implementations/services.template.js +18 -30
- package/dist/template/implementations/view_form.template.js +72 -125
- package/dist/template/implementations/view_id_all_select.template.js +2 -3
- package/dist/template/implementations/view_list.template.js +86 -143
- package/dist/template/implementations/view_search_input.template.js +2 -3
- package/dist/template/index.js +5 -8
- package/dist/template/template-manager.js +13 -26
- package/dist/template/template-types.js +2 -3
- package/dist/template/template.js +7 -11
- package/dist/template/zod-converter.js +173 -348
- package/dist/testing/_relation-graph.js +18 -37
- package/dist/testing/bootstrap.js +5 -8
- package/dist/testing/data-explorer.js +34 -78
- package/dist/testing/dev-test-routes.js +54 -60
- package/dist/testing/dev-vitest-manager.js +33 -84
- package/dist/testing/faker-mappings.js +3 -4
- package/dist/testing/fixture-generator.d.ts +2 -1
- package/dist/testing/fixture-generator.d.ts.map +1 -1
- package/dist/testing/fixture-generator.js +159 -321
- package/dist/testing/fixture-loader.js +2 -2
- package/dist/testing/fixture-manager.d.ts.map +1 -1
- package/dist/testing/fixture-manager.js +124 -227
- package/dist/testing/global-setup.d.ts.map +1 -1
- package/dist/testing/global-setup.js +29 -17
- package/dist/testing/index.js +1 -2
- package/dist/testing/naite-vitest-reporter.js +2 -3
- package/dist/testing/parallel-db-manager.js +5 -3
- package/dist/testing/vitest-helpers.d.ts.map +1 -1
- package/dist/testing/vitest-helpers.js +15 -12
- package/dist/types/types.d.ts +14 -14
- package/dist/types/types.js +27 -50
- package/dist/ui/ai-api.js +6 -11
- package/dist/ui/ai-client.js +86 -134
- package/dist/ui/api.js +99 -195
- package/dist/ui/cdd-service.js +78 -130
- package/dist/ui/cdd-types.js +1 -1
- package/dist/ui-web/assets/{index-Df8q-fhb.js → index-DFStGyd0.js} +49 -49
- package/dist/ui-web/assets/index-Dx4ap5i4.css +1 -0
- package/dist/ui-web/index.html +2 -2
- package/dist/utils/async-utils.js +13 -25
- package/dist/utils/class-name.js +3 -4
- package/dist/utils/console-util.js +11 -26
- package/dist/utils/controller.d.ts.map +1 -1
- package/dist/utils/controller.js +14 -12
- package/dist/utils/esm-utils.js +5 -8
- package/dist/utils/formatter.js +10 -22
- package/dist/utils/fs-utils.js +14 -25
- package/dist/utils/lodash-able.js +3 -4
- package/dist/utils/model.js +7 -14
- package/dist/utils/object-utils.js +41 -73
- package/dist/utils/path-utils.js +5 -9
- package/dist/utils/process-utils.js +4 -7
- package/dist/utils/sql-parser.js +6 -13
- package/dist/utils/type-utils.js +16 -26
- package/dist/utils/utils.js +18 -40
- package/dist/utils/zod-error.js +9 -16
- package/dist/vector/chunking.js +24 -37
- package/dist/vector/config.js +2 -2
- package/dist/vector/embedding.js +8 -19
- package/dist/vector/index.js +1 -2
- package/dist/vector/types.js +1 -1
- package/package.json +6 -6
- package/src/__tests__/env.test.ts +127 -0
- package/src/api/__tests__/config.test.ts +10 -1
- package/src/api/config.ts +4 -12
- package/src/api/sonamu.ts +14 -4
- package/src/bin/__tests__/migrate-targets.test.ts +28 -0
- package/src/bin/__tests__/test-command.test.ts +82 -1
- package/src/bin/cli.ts +9 -18
- package/src/bin/fixture.ts +5 -4
- package/src/bin/migrate-targets.ts +7 -0
- package/src/bin/test-command.ts +2 -2
- package/src/database/__tests__/db.test.ts +175 -0
- package/src/database/db.ts +193 -71
- package/src/dict/en.ts +2 -0
- package/src/dict/ko.ts +2 -0
- package/src/env.ts +123 -0
- package/src/migration/__tests__/migrator.test.ts +149 -0
- package/src/migration/migrator.ts +74 -17
- package/src/migration/slack-confirm.ts +21 -0
- package/src/skills/sonamu/database.md +1 -1
- package/src/skills/sonamu/testing-devrunner.md +1 -1
- package/src/stream/ws-telemetry-memory.ts +2 -2
- package/src/testing/fixture-generator.ts +2 -1
- package/src/testing/fixture-manager.ts +3 -4
- package/src/testing/global-setup.ts +42 -18
- package/src/testing/vitest-helpers.ts +14 -0
- package/src/utils/controller.ts +14 -7
- package/tsdown.api.config.ts +6 -0
- package/dist/_virtual/rolldown_runtime.js +0 -39
- package/dist/ui-web/assets/index-D4rYm-Xz.css +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { __esmMin } from "../_virtual/
|
|
1
|
+
import { __esmMin } from "../_virtual/_rolldown/runtime.js";
|
|
2
2
|
import { createKnexInstance, init_knex } from "../database/knex.js";
|
|
3
3
|
import { init_controller, isTest } from "../utils/controller.js";
|
|
4
4
|
import { Sonamu, init_sonamu } from "../api/sonamu.js";
|
|
@@ -10,11 +10,10 @@ import { RelationGraph, init__relation_graph } from "./_relation-graph.js";
|
|
|
10
10
|
import inflection from "inflection";
|
|
11
11
|
import { unique } from "radashi";
|
|
12
12
|
import assert from "assert";
|
|
13
|
+
import { readFileSync, writeFileSync } from "fs";
|
|
13
14
|
import chalk from "chalk";
|
|
14
15
|
import { execSync } from "child_process";
|
|
15
|
-
import { readFileSync, writeFileSync } from "fs";
|
|
16
16
|
import { inspect } from "util";
|
|
17
|
-
|
|
18
17
|
//#region src/testing/fixture-manager.ts
|
|
19
18
|
var FixtureManagerClass, FixtureManager;
|
|
20
19
|
var init_fixture_manager = __esmMin((() => {
|
|
@@ -32,9 +31,7 @@ var init_fixture_manager = __esmMin((() => {
|
|
|
32
31
|
this._tdb = tdb;
|
|
33
32
|
}
|
|
34
33
|
get tdb() {
|
|
35
|
-
if (this._tdb === null)
|
|
36
|
-
throw new Error("FixtureManager has not been initialized");
|
|
37
|
-
}
|
|
34
|
+
if (this._tdb === null) throw new Error("FixtureManager has not been initialized");
|
|
38
35
|
return this._tdb;
|
|
39
36
|
}
|
|
40
37
|
_fdb = null;
|
|
@@ -42,26 +39,20 @@ var init_fixture_manager = __esmMin((() => {
|
|
|
42
39
|
this._fdb = fdb;
|
|
43
40
|
}
|
|
44
41
|
get fdb() {
|
|
45
|
-
if (this._fdb === null)
|
|
46
|
-
throw new Error("FixtureManager has not been initialized");
|
|
47
|
-
}
|
|
42
|
+
if (this._fdb === null) throw new Error("FixtureManager has not been initialized");
|
|
48
43
|
return this._fdb;
|
|
49
44
|
}
|
|
50
45
|
cachedTableNames = null;
|
|
51
46
|
relationGraph = new RelationGraph();
|
|
52
47
|
builder = new UpsertBuilder();
|
|
53
|
-
fixtureRefMap = new Map();
|
|
54
|
-
skippedFixtures = new Map();
|
|
48
|
+
fixtureRefMap = /* @__PURE__ */ new Map();
|
|
49
|
+
skippedFixtures = /* @__PURE__ */ new Map();
|
|
55
50
|
init() {
|
|
56
|
-
if (this._tdb !== null)
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
if (Sonamu.dbConfig.test && Sonamu.dbConfig.production_master) {
|
|
51
|
+
if (this._tdb !== null) return;
|
|
52
|
+
if (Sonamu.dbConfig.test && Sonamu.dbConfig.production) {
|
|
60
53
|
const tConn = Sonamu.dbConfig.test.connection;
|
|
61
|
-
const pConn = Sonamu.dbConfig.
|
|
62
|
-
if (`${tConn.host ?? "localhost"}:${tConn.port ?? 5432}/${tConn.database}` === `${pConn.host ?? "localhost"}:${pConn.port ?? 5432}/${pConn.database}`)
|
|
63
|
-
throw new Error(`테스트DB와 프로덕션DB에 동일한 데이터베이스가 사용되었습니다.`);
|
|
64
|
-
}
|
|
54
|
+
const pConn = Sonamu.dbConfig.production.connection;
|
|
55
|
+
if (`${tConn.host ?? "localhost"}:${tConn.port ?? 5432}/${tConn.database}` === `${pConn.host ?? "localhost"}:${pConn.port ?? 5432}/${pConn.database}`) throw new Error(`테스트DB와 프로덕션DB에 동일한 데이터베이스가 사용되었습니다.`);
|
|
65
56
|
}
|
|
66
57
|
this.tdb = createKnexInstance(Sonamu.dbConfig.test);
|
|
67
58
|
this.fdb = createKnexInstance(Sonamu.dbConfig.fixture);
|
|
@@ -125,8 +116,7 @@ var init_fixture_manager = __esmMin((() => {
|
|
|
125
116
|
const tableName = entity.table || entity.id.toLowerCase();
|
|
126
117
|
const idProp = entity.props.find((p) => p.name === "id");
|
|
127
118
|
const idType = idProp?.type;
|
|
128
|
-
|
|
129
|
-
if (!usesSequence) {
|
|
119
|
+
if (!(idType === "integer" || idType === "bigInteger" || idProp?.cone?.fixtureStrategy === "sequence")) {
|
|
130
120
|
!isTest() && console.log(`Skipping sequence reset for ${tableName} (id type: ${idType || "unknown"})`);
|
|
131
121
|
continue;
|
|
132
122
|
}
|
|
@@ -142,57 +132,47 @@ var init_fixture_manager = __esmMin((() => {
|
|
|
142
132
|
await testDb.destroy();
|
|
143
133
|
}
|
|
144
134
|
}
|
|
145
|
-
visitedRecords = new Set();
|
|
135
|
+
visitedRecords = /* @__PURE__ */ new Set();
|
|
146
136
|
async importFixture(entityId, ids) {
|
|
147
137
|
this.visitedRecords.clear();
|
|
148
138
|
const queries = unique((await Promise.all(ids.map(async (id) => {
|
|
149
139
|
return await this.getImportQueries(entityId, "id", id);
|
|
150
140
|
}))).flat());
|
|
151
141
|
const wdb = BaseModel.getDB("w");
|
|
152
|
-
for (const query of queries)
|
|
153
|
-
await wdb.raw(query);
|
|
154
|
-
}
|
|
142
|
+
for (const query of queries) await wdb.raw(query);
|
|
155
143
|
}
|
|
156
144
|
async getImportQueries(entityId, field, id) {
|
|
157
145
|
const recordKey = `${entityId}#${field}#${id}`;
|
|
158
|
-
if (this.visitedRecords.has(recordKey))
|
|
159
|
-
return [];
|
|
160
|
-
}
|
|
146
|
+
if (this.visitedRecords.has(recordKey)) return [];
|
|
161
147
|
this.visitedRecords.add(recordKey);
|
|
162
148
|
const entity = EntityManager.get(entityId);
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
if (row === undefined) {
|
|
166
|
-
throw new Error(`${entityId}#${id} row를 찾을 수 없습니다.`);
|
|
167
|
-
}
|
|
149
|
+
const [row] = await BaseModel.getDB("w")(entity.table).where(field, id).limit(1);
|
|
150
|
+
if (row === void 0) throw new Error(`${entityId}#${id} row를 찾을 수 없습니다.`);
|
|
168
151
|
const fixtureDatabase = Sonamu.dbConfig.fixture.connection.database;
|
|
169
|
-
const realDatabase = Sonamu.dbConfig.
|
|
152
|
+
const realDatabase = Sonamu.dbConfig.production.connection.database;
|
|
170
153
|
const selfQuery = `INSERT IGNORE INTO \`${fixtureDatabase}\`.\`${entity.table}\` (SELECT * FROM \`${realDatabase}\`.\`${entity.table}\` WHERE \`id\` = ${id})`;
|
|
171
|
-
const args = Object.entries(entity.relations).filter(([, relation]) => isBelongsToOneRelationProp(relation) || isOneToOneRelationProp(relation) && relation.customJoinClause ===
|
|
172
|
-
let field
|
|
173
|
-
let id
|
|
154
|
+
const args = Object.entries(entity.relations).filter(([, relation]) => isBelongsToOneRelationProp(relation) || isOneToOneRelationProp(relation) && relation.customJoinClause === void 0).map(([, relation]) => {
|
|
155
|
+
let field;
|
|
156
|
+
let id;
|
|
174
157
|
if (isOneToOneRelationProp(relation) && !relation.hasJoinColumn) {
|
|
175
158
|
const relatedEntity = EntityManager.get(relation.with);
|
|
176
159
|
const relatedIdColumnName = relatedEntity.props.find((p) => isRelationProp(p) && p.with === entity.id)?.name;
|
|
177
|
-
if (!relatedIdColumnName) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
field$1 = `${relatedIdColumnName}_id`;
|
|
181
|
-
id$1 = row.id;
|
|
160
|
+
if (!relatedIdColumnName) throw new Error(`${relatedEntity.id}의 ${entity.id} 관계 프롭을 찾을 수 없습니다.`);
|
|
161
|
+
field = `${relatedIdColumnName}_id`;
|
|
162
|
+
id = row.id;
|
|
182
163
|
} else {
|
|
183
|
-
field
|
|
184
|
-
id
|
|
164
|
+
field = "id";
|
|
165
|
+
id = row[`${relation.name}_id`];
|
|
185
166
|
}
|
|
186
167
|
return {
|
|
187
168
|
entityId: relation.with,
|
|
188
|
-
field
|
|
189
|
-
id
|
|
169
|
+
field,
|
|
170
|
+
id
|
|
190
171
|
};
|
|
191
172
|
}).filter((arg) => arg.id !== null);
|
|
192
|
-
|
|
193
|
-
return this.getImportQueries(args
|
|
194
|
-
}));
|
|
195
|
-
return [...unique(relQueries.toReversed().flat()), selfQuery];
|
|
173
|
+
return [...unique((await Promise.all(args.map(async (args) => {
|
|
174
|
+
return this.getImportQueries(args.entityId, args.field, args.id);
|
|
175
|
+
}))).toReversed().flat()), selfQuery];
|
|
196
176
|
}
|
|
197
177
|
async destroy() {
|
|
198
178
|
if (this._tdb) {
|
|
@@ -213,41 +193,34 @@ var init_fixture_manager = __esmMin((() => {
|
|
|
213
193
|
const entity = EntityManager.get(entityId);
|
|
214
194
|
const column = entity.props.find((prop) => prop.name === field)?.type === "relation" ? `${field}_id` : field;
|
|
215
195
|
let query = sourceDB(entity.table);
|
|
216
|
-
if (searchType === "equals")
|
|
217
|
-
|
|
218
|
-
} else if (searchType === "like") {
|
|
219
|
-
query = query.where(column, "like", `%${value}%`);
|
|
220
|
-
}
|
|
196
|
+
if (searchType === "equals") query = query.where(column, value);
|
|
197
|
+
else if (searchType === "like") query = query.where(column, "like", `%${value}%`);
|
|
221
198
|
const rows = await query;
|
|
222
|
-
if (rows.length === 0)
|
|
223
|
-
throw new Error("No records found");
|
|
224
|
-
}
|
|
199
|
+
if (rows.length === 0) throw new Error("No records found");
|
|
225
200
|
const fixtures = [];
|
|
226
201
|
for (const row of rows) {
|
|
227
202
|
const initialRecordsLength = fixtures.length;
|
|
228
203
|
const newRecords = await this.createFixtureRecord(entity, row, { _db: sourceDB });
|
|
229
204
|
fixtures.push(...newRecords);
|
|
230
205
|
const currentFixtureRecord = fixtures.find((r) => r.fixtureId === `${entityId}#${row.id}`);
|
|
231
|
-
if (currentFixtureRecord)
|
|
232
|
-
currentFixtureRecord.fetchedRecords = fixtures.filter((r) => r.fixtureId !== currentFixtureRecord.fixtureId).slice(initialRecordsLength).map((r) => r.fixtureId);
|
|
233
|
-
}
|
|
206
|
+
if (currentFixtureRecord) currentFixtureRecord.fetchedRecords = fixtures.filter((r) => r.fixtureId !== currentFixtureRecord.fixtureId).slice(initialRecordsLength).map((r) => r.fixtureId);
|
|
234
207
|
}
|
|
235
208
|
for (const fixture of fixtures) {
|
|
236
|
-
const entity
|
|
209
|
+
const entity = EntityManager.get(fixture.entityId);
|
|
237
210
|
const customColumns = duplicateCheck?.columns?.[fixture.entityId];
|
|
238
211
|
if (customColumns && customColumns.length > 0) {
|
|
239
|
-
const customDuplicateRow = await this.checkDuplicateByColumns(targetDB, entity
|
|
212
|
+
const customDuplicateRow = await this.checkDuplicateByColumns(targetDB, entity, fixture, customColumns);
|
|
240
213
|
if (customDuplicateRow) {
|
|
241
|
-
const [record] = await this.createFixtureRecord(entity
|
|
214
|
+
const [record] = await this.createFixtureRecord(entity, customDuplicateRow, {
|
|
242
215
|
singleRecord: true,
|
|
243
216
|
_db: targetDB
|
|
244
217
|
});
|
|
245
218
|
fixture.target = record;
|
|
246
219
|
}
|
|
247
220
|
}
|
|
248
|
-
const uniqueRow = await this.checkUniqueViolation(targetDB, entity
|
|
221
|
+
const uniqueRow = await this.checkUniqueViolation(targetDB, entity, fixture);
|
|
249
222
|
if (uniqueRow) {
|
|
250
|
-
const [record] = await this.createFixtureRecord(entity
|
|
223
|
+
const [record] = await this.createFixtureRecord(entity, uniqueRow, {
|
|
251
224
|
singleRecord: true,
|
|
252
225
|
_db: targetDB
|
|
253
226
|
});
|
|
@@ -261,61 +234,52 @@ var init_fixture_manager = __esmMin((() => {
|
|
|
261
234
|
}
|
|
262
235
|
async createFixtureRecord(entity, row, options) {
|
|
263
236
|
const records = [];
|
|
264
|
-
const visitedEntities = new Set();
|
|
265
|
-
const create = async (entity
|
|
266
|
-
const fixtureId = `${entity
|
|
267
|
-
if (visitedEntities.has(fixtureId))
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
237
|
+
const visitedEntities = /* @__PURE__ */ new Set();
|
|
238
|
+
const create = async (entity, row) => {
|
|
239
|
+
const fixtureId = `${entity.id}#${row.id}`;
|
|
240
|
+
if (visitedEntities.has(fixtureId)) return;
|
|
270
241
|
visitedEntities.add(fixtureId);
|
|
271
242
|
const record = {
|
|
272
243
|
fixtureId,
|
|
273
|
-
entityId: entity
|
|
274
|
-
id: row
|
|
244
|
+
entityId: entity.id,
|
|
245
|
+
id: row.id,
|
|
275
246
|
columns: {},
|
|
276
247
|
fetchedRecords: [],
|
|
277
248
|
belongsRecords: []
|
|
278
249
|
};
|
|
279
|
-
for (const prop of entity
|
|
280
|
-
if (isVirtualProp(prop))
|
|
281
|
-
continue;
|
|
282
|
-
}
|
|
250
|
+
for (const prop of entity.props) {
|
|
251
|
+
if (isVirtualProp(prop)) continue;
|
|
283
252
|
record.columns[prop.name] = {
|
|
284
253
|
prop,
|
|
285
|
-
value: row
|
|
254
|
+
value: row[prop.name]
|
|
286
255
|
};
|
|
287
256
|
const db = options?._db ?? BaseModel.getDB("w");
|
|
288
257
|
if (isManyToManyRelationProp(prop)) {
|
|
289
258
|
const relatedEntity = EntityManager.get(prop.with);
|
|
290
259
|
const throughTable = prop.joinTable;
|
|
291
|
-
const fromColumn = `${inflection.singularize(entity
|
|
260
|
+
const fromColumn = `${inflection.singularize(entity.table)}_id`;
|
|
292
261
|
const toColumn = `${inflection.singularize(relatedEntity.table)}_id`;
|
|
293
|
-
const relatedIds = await db(throughTable).where(fromColumn, row
|
|
262
|
+
const relatedIds = await db(throughTable).where(fromColumn, row.id).pluck(toColumn);
|
|
294
263
|
record.columns[prop.name].value = relatedIds;
|
|
295
264
|
} else if (isHasManyRelationProp(prop)) {
|
|
296
|
-
const
|
|
297
|
-
const relatedIds = await db(relatedEntity.table).where(prop.joinColumn, row$1.id).pluck("id");
|
|
265
|
+
const relatedIds = await db(EntityManager.get(prop.with).table).where(prop.joinColumn, row.id).pluck("id");
|
|
298
266
|
record.columns[prop.name].value = relatedIds;
|
|
299
267
|
} else if (isOneToOneRelationProp(prop) && !prop.hasJoinColumn) {
|
|
300
268
|
const relatedEntity = EntityManager.get(prop.with);
|
|
301
|
-
const relatedProp = relatedEntity.props.find((p) => isRelationProp(p) && p.with === entity
|
|
269
|
+
const relatedProp = relatedEntity.props.find((p) => isRelationProp(p) && p.with === entity.id);
|
|
302
270
|
if (relatedProp && isRelationProp(relatedProp)) {
|
|
303
271
|
const fkColumn = `${relatedProp.name}_id`;
|
|
304
|
-
const relatedRow = await db(relatedEntity.table).where(fkColumn, row
|
|
272
|
+
const relatedRow = await db(relatedEntity.table).where(fkColumn, row.id).first();
|
|
305
273
|
record.columns[prop.name].value = relatedRow?.id;
|
|
306
274
|
}
|
|
307
275
|
} else if (isRelationProp(prop)) {
|
|
308
|
-
const relatedId = row
|
|
276
|
+
const relatedId = row[`${prop.name}_id`];
|
|
309
277
|
record.columns[prop.name].value = relatedId;
|
|
310
|
-
if (relatedId) {
|
|
311
|
-
record.belongsRecords.push(`${prop.with}#${relatedId}`);
|
|
312
|
-
}
|
|
278
|
+
if (relatedId) record.belongsRecords.push(`${prop.with}#${relatedId}`);
|
|
313
279
|
if (!options?.singleRecord && relatedId) {
|
|
314
280
|
const relatedEntity = EntityManager.get(prop.with);
|
|
315
281
|
const relatedRow = await db(relatedEntity.table).where("id", relatedId).first();
|
|
316
|
-
if (relatedRow)
|
|
317
|
-
await create(relatedEntity, relatedRow);
|
|
318
|
-
}
|
|
282
|
+
if (relatedRow) await create(relatedEntity, relatedRow);
|
|
319
283
|
}
|
|
320
284
|
}
|
|
321
285
|
}
|
|
@@ -337,9 +301,9 @@ var init_fixture_manager = __esmMin((() => {
|
|
|
337
301
|
async insertFixtures(dbName, _fixtures) {
|
|
338
302
|
const fixtures = unique(_fixtures, (f) => f.fixtureId);
|
|
339
303
|
this.builder = new UpsertBuilder();
|
|
340
|
-
this.fixtureRefMap = new Map();
|
|
341
|
-
this.skippedFixtures = new Map();
|
|
342
|
-
const
|
|
304
|
+
this.fixtureRefMap = /* @__PURE__ */ new Map();
|
|
305
|
+
this.skippedFixtures = /* @__PURE__ */ new Map();
|
|
306
|
+
const db = createKnexInstance(process.env.SONAMU_WORKER_DB === "true" && process.env.VITEST_POOL_ID ? (() => {
|
|
343
307
|
const workerId = parseInt(process.env.VITEST_POOL_ID ?? "1", 10);
|
|
344
308
|
const baseConfig = Sonamu.dbConfig[dbName];
|
|
345
309
|
const connection = baseConfig.connection;
|
|
@@ -354,8 +318,7 @@ var init_fixture_manager = __esmMin((() => {
|
|
|
354
318
|
max: 1
|
|
355
319
|
}
|
|
356
320
|
};
|
|
357
|
-
})() : Sonamu.dbConfig[dbName];
|
|
358
|
-
const db = createKnexInstance(dbConfig);
|
|
321
|
+
})() : Sonamu.dbConfig[dbName]);
|
|
359
322
|
const results = [];
|
|
360
323
|
try {
|
|
361
324
|
this.relationGraph.buildGraph(fixtures);
|
|
@@ -365,8 +328,7 @@ var init_fixture_manager = __esmMin((() => {
|
|
|
365
328
|
if (!fixture) continue;
|
|
366
329
|
const hasTarget = !!fixture.target;
|
|
367
330
|
const hasUnique = !!fixture.unique;
|
|
368
|
-
|
|
369
|
-
if (hasDuplicate && !fixture.override) {
|
|
331
|
+
if ((hasTarget || hasUnique) && !fixture.override) {
|
|
370
332
|
const existingId = fixture.unique?.id ?? fixture.target?.id;
|
|
371
333
|
assert(existingId);
|
|
372
334
|
this.skippedFixtures.set(fixtureId, {
|
|
@@ -376,14 +338,13 @@ var init_fixture_manager = __esmMin((() => {
|
|
|
376
338
|
!isTest() && console.log(chalk.yellow(`Skipped ${fixture.entityId}#${fixture.id} (existing: #${existingId}, override: false)`));
|
|
377
339
|
}
|
|
378
340
|
}
|
|
379
|
-
const fixturesByTable = new Map();
|
|
341
|
+
const fixturesByTable = /* @__PURE__ */ new Map();
|
|
380
342
|
const tableOrder = [];
|
|
381
343
|
for (const fixtureId of insertionOrder) {
|
|
382
344
|
if (this.skippedFixtures.has(fixtureId)) continue;
|
|
383
345
|
const fixture = fixtures.find((f) => f.fixtureId === fixtureId);
|
|
384
346
|
if (!fixture) continue;
|
|
385
|
-
const
|
|
386
|
-
const tableName = entity.table;
|
|
347
|
+
const tableName = EntityManager.get(fixture.entityId).table;
|
|
387
348
|
if (!fixturesByTable.has(tableName)) {
|
|
388
349
|
fixturesByTable.set(tableName, []);
|
|
389
350
|
tableOrder.push(tableName);
|
|
@@ -391,7 +352,7 @@ var init_fixture_manager = __esmMin((() => {
|
|
|
391
352
|
fixturesByTable.get(tableName)?.push(fixture);
|
|
392
353
|
}
|
|
393
354
|
await db.transaction(async (trx) => {
|
|
394
|
-
const insertedIdsByTable = new Map();
|
|
355
|
+
const insertedIdsByTable = /* @__PURE__ */ new Map();
|
|
395
356
|
for (const tableName of tableOrder) {
|
|
396
357
|
const tableFixtures = fixturesByTable.get(tableName) ?? [];
|
|
397
358
|
const levels = this.groupFixturesByLevel(tableFixtures);
|
|
@@ -400,46 +361,35 @@ var init_fixture_manager = __esmMin((() => {
|
|
|
400
361
|
this.registerFixture(fixture, insertedIdsByTable);
|
|
401
362
|
!isTest() && console.log(chalk.blue(`Registered ${fixture.entityId}#${fixture.id}${fixture.override ? ` (override)` : ""}`));
|
|
402
363
|
}
|
|
403
|
-
const
|
|
404
|
-
const uuids = table.rows.map((row) => row.uuid);
|
|
364
|
+
const uuids = this.builder.getTable(tableName).rows.map((row) => row.uuid);
|
|
405
365
|
!isTest() && console.log(chalk.blue(`Upserting ${tableName} with ${uuids.length} rows (level ${levels.indexOf(levelFixtures) + 1}/${levels.length})`));
|
|
406
366
|
const ids = await this.builder.upsert(trx, tableName);
|
|
407
367
|
if (uuids.length > 0 && uuids.length === ids.length) {
|
|
408
|
-
const existingMap = insertedIdsByTable.get(tableName) ?? new Map();
|
|
409
|
-
for (let i = 0; i < uuids.length; i++)
|
|
410
|
-
existingMap.set(uuids[i], ids[i]);
|
|
411
|
-
}
|
|
368
|
+
const existingMap = insertedIdsByTable.get(tableName) ?? /* @__PURE__ */ new Map();
|
|
369
|
+
for (let i = 0; i < uuids.length; i++) existingMap.set(uuids[i], ids[i]);
|
|
412
370
|
insertedIdsByTable.set(tableName, existingMap);
|
|
413
|
-
} else if (uuids.length !== ids.length) {
|
|
414
|
-
console.warn(chalk.yellow(`Warning: uuid count (${uuids.length}) != id count (${ids.length}) for ${tableName}`));
|
|
415
|
-
}
|
|
371
|
+
} else if (uuids.length !== ids.length) console.warn(chalk.yellow(`Warning: uuid count (${uuids.length}) != id count (${ids.length}) for ${tableName}`));
|
|
416
372
|
}
|
|
417
373
|
}
|
|
418
374
|
await this.processManyToManyRelations(trx, fixtures, insertedIdsByTable);
|
|
419
375
|
!isTest() && console.log(chalk.blue("Resetting sequences..."));
|
|
420
|
-
for (const tableName of tableOrder) {
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
!isTest() && console.log(chalk.gray(`Skipped sequence reset for ${tableName} (id type: ${idType || "unknown"})`));
|
|
429
|
-
continue;
|
|
430
|
-
}
|
|
376
|
+
for (const tableName of tableOrder) try {
|
|
377
|
+
const entity = EntityManager.getAllEntities().find((e) => e.table === tableName || e.id.toLowerCase() === tableName);
|
|
378
|
+
if (entity) {
|
|
379
|
+
const idProp = entity.props.find((p) => p.name === "id");
|
|
380
|
+
const idType = idProp?.type;
|
|
381
|
+
if (!(idType === "integer" || idType === "bigInteger" || idProp?.cone?.fixtureStrategy === "sequence")) {
|
|
382
|
+
!isTest() && console.log(chalk.gray(`Skipped sequence reset for ${tableName} (id type: ${idType || "unknown"})`));
|
|
383
|
+
continue;
|
|
431
384
|
}
|
|
432
|
-
const entity2 = EntityManager.getAllEntities().find((e) => e.table === tableName || e.id.toLowerCase() === tableName);
|
|
433
|
-
const idType2 = entity2?.props.find((p) => p.name === "id")?.type;
|
|
434
|
-
const maxIdResult = idType2 === "string" ? await trx.raw(`SELECT MAX(id::bigint) as max_id FROM "${tableName}"`).then((r) => r.rows[0]) : await trx(tableName).max("id as max_id").first();
|
|
435
|
-
const maxId = maxIdResult?.max_id;
|
|
436
|
-
if (maxId !== null && maxId !== undefined) {
|
|
437
|
-
await trx.raw(`SELECT setval(pg_get_serial_sequence(?, 'id'), ?)`, [tableName, maxId]);
|
|
438
|
-
!isTest() && console.log(chalk.green(`Reset sequence for ${tableName}: ${maxId}`));
|
|
439
|
-
}
|
|
440
|
-
} catch {
|
|
441
|
-
!isTest() && console.log(chalk.gray(`Skipped sequence reset for ${tableName}`));
|
|
442
385
|
}
|
|
386
|
+
const maxId = (EntityManager.getAllEntities().find((e) => e.table === tableName || e.id.toLowerCase() === tableName)?.props.find((p) => p.name === "id")?.type === "string" ? await trx.raw(`SELECT MAX(id::bigint) as max_id FROM "${tableName}"`).then((r) => r.rows[0]) : await trx(tableName).max("id as max_id").first())?.max_id;
|
|
387
|
+
if (maxId !== null && maxId !== void 0) {
|
|
388
|
+
await trx.raw(`SELECT setval(pg_get_serial_sequence(?, 'id'), ?)`, [tableName, maxId]);
|
|
389
|
+
!isTest() && console.log(chalk.green(`Reset sequence for ${tableName}: ${maxId}`));
|
|
390
|
+
}
|
|
391
|
+
} catch {
|
|
392
|
+
!isTest() && console.log(chalk.gray(`Skipped sequence reset for ${tableName}`));
|
|
443
393
|
}
|
|
444
394
|
for (const fixture of fixtures) {
|
|
445
395
|
const entity = EntityManager.get(fixture.entityId);
|
|
@@ -453,9 +403,8 @@ var init_fixture_manager = __esmMin((() => {
|
|
|
453
403
|
}
|
|
454
404
|
const ref = this.fixtureRefMap.get(fixture.fixtureId);
|
|
455
405
|
if (ref) {
|
|
456
|
-
const
|
|
457
|
-
|
|
458
|
-
if (insertedId !== undefined) {
|
|
406
|
+
const insertedId = insertedIdsByTable.get(entity.table)?.get(ref.uuid);
|
|
407
|
+
if (insertedId !== void 0) {
|
|
459
408
|
results.push({
|
|
460
409
|
entityId: fixture.entityId,
|
|
461
410
|
data: await trx(entity.table).where("id", insertedId).first()
|
|
@@ -481,52 +430,34 @@ var init_fixture_manager = __esmMin((() => {
|
|
|
481
430
|
const isOverrideMode = fixture.override && existingRecord;
|
|
482
431
|
for (const [propName, column] of Object.entries(fixture.columns)) {
|
|
483
432
|
const prop = column.prop;
|
|
484
|
-
if (isVirtualProp(prop))
|
|
485
|
-
|
|
486
|
-
}
|
|
487
|
-
if ("generated" in prop && prop.generated) {
|
|
488
|
-
continue;
|
|
489
|
-
}
|
|
433
|
+
if (isVirtualProp(prop)) continue;
|
|
434
|
+
if ("generated" in prop && prop.generated) continue;
|
|
490
435
|
if (propName === "id") {
|
|
491
436
|
const idProp = entity.props.find((p) => p.name === "id");
|
|
492
437
|
const usesSequence = !entity.parentId && (idProp?.type === "integer" || idProp?.type === "bigInteger" || idProp?.cone?.fixtureStrategy === "sequence");
|
|
493
|
-
if (isOverrideMode && existingRecord)
|
|
494
|
-
|
|
495
|
-
} else if (!usesSequence) {
|
|
496
|
-
row[propName] = column.value;
|
|
497
|
-
}
|
|
438
|
+
if (isOverrideMode && existingRecord) row[propName] = existingRecord.columns[propName]?.value;
|
|
439
|
+
else if (!usesSequence) row[propName] = column.value;
|
|
498
440
|
continue;
|
|
499
441
|
}
|
|
500
442
|
if (isRelationProp(prop)) {
|
|
501
443
|
if (isBelongsToOneRelationProp(prop) || isOneToOneRelationProp(prop) && prop.hasJoinColumn) {
|
|
502
444
|
const relatedId = column.value;
|
|
503
|
-
if (relatedId !== null && relatedId !==
|
|
445
|
+
if (relatedId !== null && relatedId !== void 0) {
|
|
504
446
|
const relatedFixtureId = `${prop.with}#${relatedId}`;
|
|
505
447
|
const skippedExistingId = this.skippedFixtures.get(relatedFixtureId)?.existingId;
|
|
506
|
-
if (skippedExistingId !==
|
|
507
|
-
|
|
508
|
-
} else {
|
|
448
|
+
if (skippedExistingId !== void 0) row[`${propName}_id`] = skippedExistingId;
|
|
449
|
+
else {
|
|
509
450
|
const relatedRef = this.fixtureRefMap.get(relatedFixtureId);
|
|
510
451
|
if (relatedRef) {
|
|
511
452
|
const relatedEntity = EntityManager.get(prop.with);
|
|
512
|
-
const
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
} else {
|
|
517
|
-
row[`${propName}_id`] = relatedRef;
|
|
518
|
-
}
|
|
519
|
-
} else {
|
|
520
|
-
row[`${propName}_id`] = relatedId;
|
|
521
|
-
}
|
|
453
|
+
const actualId = (insertedIdsByTable?.get(relatedEntity.table))?.get(relatedRef.uuid);
|
|
454
|
+
if (actualId !== void 0) row[`${propName}_id`] = actualId;
|
|
455
|
+
else row[`${propName}_id`] = relatedRef;
|
|
456
|
+
} else row[`${propName}_id`] = relatedId;
|
|
522
457
|
}
|
|
523
|
-
} else {
|
|
524
|
-
row[`${propName}_id`] = null;
|
|
525
|
-
}
|
|
458
|
+
} else row[`${propName}_id`] = null;
|
|
526
459
|
}
|
|
527
|
-
} else
|
|
528
|
-
row[propName] = this.convertColumnValue(prop, column.value);
|
|
529
|
-
}
|
|
460
|
+
} else row[propName] = this.convertColumnValue(prop, column.value);
|
|
530
461
|
}
|
|
531
462
|
!isTest() && console.log(chalk.blue(`Registering ${entity.table} - ${inspect(row, false, null, true)}`));
|
|
532
463
|
const ref = this.builder.register(entity.table, row);
|
|
@@ -537,15 +468,11 @@ var init_fixture_manager = __esmMin((() => {
|
|
|
537
468
|
* 컬럼 값 변환
|
|
538
469
|
*/
|
|
539
470
|
convertColumnValue(prop, value) {
|
|
540
|
-
if (value === null || value ===
|
|
541
|
-
return null;
|
|
542
|
-
}
|
|
471
|
+
if (value === null || value === void 0) return null;
|
|
543
472
|
switch (prop.type) {
|
|
544
473
|
case "json": return value;
|
|
545
474
|
case "date":
|
|
546
|
-
if (typeof value === "string" || typeof value === "number")
|
|
547
|
-
return new Date(value);
|
|
548
|
-
}
|
|
475
|
+
if (typeof value === "string" || typeof value === "number") return new Date(value);
|
|
549
476
|
return value;
|
|
550
477
|
default: return value;
|
|
551
478
|
}
|
|
@@ -555,9 +482,8 @@ var init_fixture_manager = __esmMin((() => {
|
|
|
555
482
|
const entity = EntityManager.get(fixture.entityId);
|
|
556
483
|
const sourceRef = this.fixtureRefMap.get(fixture.fixtureId);
|
|
557
484
|
if (!sourceRef) continue;
|
|
558
|
-
const
|
|
559
|
-
|
|
560
|
-
if (sourceId === undefined) continue;
|
|
485
|
+
const sourceId = insertedIdsByTable.get(entity.table)?.get(sourceRef.uuid);
|
|
486
|
+
if (sourceId === void 0) continue;
|
|
561
487
|
for (const [, column] of Object.entries(fixture.columns)) {
|
|
562
488
|
const prop = column.prop;
|
|
563
489
|
if (isManyToManyRelationProp(prop) && Array.isArray(column.value)) {
|
|
@@ -574,16 +500,13 @@ var init_fixture_manager = __esmMin((() => {
|
|
|
574
500
|
const relatedRef = this.fixtureRefMap.get(relatedFixtureId);
|
|
575
501
|
let targetId;
|
|
576
502
|
if (relatedRef) {
|
|
577
|
-
const
|
|
578
|
-
|
|
579
|
-
if (resolvedId === undefined) {
|
|
503
|
+
const resolvedId = insertedIdsByTable.get(relatedEntity.table)?.get(relatedRef.uuid);
|
|
504
|
+
if (resolvedId === void 0) {
|
|
580
505
|
console.warn(`Related fixture ${relatedFixtureId} not found in insertedIds, skipping`);
|
|
581
506
|
continue;
|
|
582
507
|
}
|
|
583
508
|
targetId = resolvedId;
|
|
584
|
-
} else
|
|
585
|
-
targetId = relatedId;
|
|
586
|
-
}
|
|
509
|
+
} else targetId = relatedId;
|
|
587
510
|
const [found] = await trx(joinTable).where({
|
|
588
511
|
[sourceColumn]: sourceId,
|
|
589
512
|
[targetColumn]: targetId
|
|
@@ -611,30 +534,23 @@ var init_fixture_manager = __esmMin((() => {
|
|
|
611
534
|
* 이를 방지하기 위해 FixtureManager가 레벨별로 나눠서 처리합니다.
|
|
612
535
|
*/
|
|
613
536
|
groupFixturesByLevel(fixtures) {
|
|
614
|
-
if (fixtures.length === 0)
|
|
615
|
-
return [];
|
|
616
|
-
}
|
|
537
|
+
if (fixtures.length === 0) return [];
|
|
617
538
|
const entity = EntityManager.get(fixtures[0].entityId);
|
|
618
539
|
const selfRefProps = entity.props.filter((p) => isRelationProp(p) && (isBelongsToOneRelationProp(p) || isOneToOneRelationProp(p) && p.hasJoinColumn) && p.with === entity.id);
|
|
619
|
-
if (selfRefProps.length === 0)
|
|
620
|
-
return [fixtures];
|
|
621
|
-
}
|
|
540
|
+
if (selfRefProps.length === 0) return [fixtures];
|
|
622
541
|
const levels = [];
|
|
623
542
|
const remaining = new Set(fixtures.map((f) => f.fixtureId));
|
|
624
|
-
const processed = new Set();
|
|
543
|
+
const processed = /* @__PURE__ */ new Set();
|
|
625
544
|
while (remaining.size > 0) {
|
|
626
545
|
const currentLevel = [];
|
|
627
546
|
for (const fixture of fixtures) {
|
|
628
547
|
if (!remaining.has(fixture.fixtureId)) continue;
|
|
629
|
-
|
|
548
|
+
if (selfRefProps.every((prop) => {
|
|
630
549
|
const refId = fixture.columns[prop.name]?.value;
|
|
631
|
-
if (refId === null || refId ===
|
|
550
|
+
if (refId === null || refId === void 0) return true;
|
|
632
551
|
const refFixtureId = `${prop.with}#${refId}`;
|
|
633
552
|
return processed.has(refFixtureId) || !remaining.has(refFixtureId);
|
|
634
|
-
});
|
|
635
|
-
if (canProcess) {
|
|
636
|
-
currentLevel.push(fixture);
|
|
637
|
-
}
|
|
553
|
+
})) currentLevel.push(fixture);
|
|
638
554
|
}
|
|
639
555
|
if (currentLevel.length === 0) {
|
|
640
556
|
const remainingIds = Array.from(remaining).join(", ");
|
|
@@ -649,51 +565,36 @@ var init_fixture_manager = __esmMin((() => {
|
|
|
649
565
|
return levels;
|
|
650
566
|
}
|
|
651
567
|
async checkUniqueViolation(db, entity, fixture) {
|
|
652
|
-
const
|
|
653
|
-
|
|
654
|
-
if (uniqueIndexes.length === 0) {
|
|
655
|
-
return null;
|
|
656
|
-
}
|
|
568
|
+
const uniqueIndexes = (entity.indexes?.filter((i) => i.type === "unique") ?? []).filter((index) => index.columns.every((column) => !column.name.startsWith(`${entity.table}__`)));
|
|
569
|
+
if (uniqueIndexes.length === 0) return null;
|
|
657
570
|
let uniqueQuery = db(entity.table);
|
|
658
571
|
let hasCondition = false;
|
|
659
572
|
for (const index of uniqueIndexes) {
|
|
660
|
-
|
|
573
|
+
if (index.columns.some((column) => {
|
|
661
574
|
const field = column.name.replace(/_id$/, "");
|
|
662
575
|
return fixture.columns[field]?.value === null;
|
|
663
|
-
});
|
|
664
|
-
if (containsNull) {
|
|
665
|
-
continue;
|
|
666
|
-
}
|
|
576
|
+
})) continue;
|
|
667
577
|
uniqueQuery = uniqueQuery.orWhere((qb) => {
|
|
668
578
|
for (const column of index.columns) {
|
|
669
579
|
const field = column.name.replace(/_id$/, "");
|
|
670
|
-
if (Array.isArray(fixture.columns[field]?.value))
|
|
671
|
-
|
|
672
|
-
} else {
|
|
673
|
-
qb.andWhere(column.name, fixture.columns[field]?.value);
|
|
674
|
-
}
|
|
580
|
+
if (Array.isArray(fixture.columns[field]?.value)) qb.whereIn(column.name, fixture.columns[field].value);
|
|
581
|
+
else qb.andWhere(column.name, fixture.columns[field]?.value);
|
|
675
582
|
}
|
|
676
583
|
});
|
|
677
584
|
hasCondition = true;
|
|
678
585
|
}
|
|
679
|
-
if (!hasCondition)
|
|
680
|
-
return null;
|
|
681
|
-
}
|
|
586
|
+
if (!hasCondition) return null;
|
|
682
587
|
const [uniqueFound] = await uniqueQuery;
|
|
683
588
|
return uniqueFound;
|
|
684
589
|
}
|
|
685
590
|
async checkDuplicateByColumns(db, entity, fixture, columns) {
|
|
686
|
-
if (columns.length === 0)
|
|
687
|
-
return null;
|
|
688
|
-
}
|
|
591
|
+
if (columns.length === 0) return null;
|
|
689
592
|
const whereClause = {};
|
|
690
593
|
for (const column of columns) {
|
|
691
594
|
const prop = entity.props.find((p) => p.name === column);
|
|
692
595
|
const dbColumn = prop && isRelationProp(prop) ? `${column}_id` : column;
|
|
693
596
|
const value = fixture.columns[column]?.value;
|
|
694
|
-
if (value === null || value ===
|
|
695
|
-
return null;
|
|
696
|
-
}
|
|
597
|
+
if (value === null || value === void 0) return null;
|
|
697
598
|
whereClause[dbColumn] = value;
|
|
698
599
|
}
|
|
699
600
|
const [found] = await db(entity.table).where(whereClause).limit(1);
|
|
@@ -704,18 +605,14 @@ var init_fixture_manager = __esmMin((() => {
|
|
|
704
605
|
const content = readFileSync(path).toString();
|
|
705
606
|
const fixtureLoaderStart = content.indexOf("const fixtureLoader = {");
|
|
706
607
|
const fixtureLoaderEnd = content.indexOf("};", fixtureLoaderStart);
|
|
707
|
-
if (fixtureLoaderStart !== -1 && fixtureLoaderEnd !== -1) {
|
|
708
|
-
|
|
709
|
-
writeFileSync(path, newContent);
|
|
710
|
-
} else {
|
|
711
|
-
throw new Error("Failed to find fixtureLoader in fixture.ts");
|
|
712
|
-
}
|
|
608
|
+
if (fixtureLoaderStart !== -1 && fixtureLoaderEnd !== -1) writeFileSync(path, `${content.slice(0, fixtureLoaderEnd)} ${code}\n${content.slice(fixtureLoaderEnd)}`);
|
|
609
|
+
else throw new Error("Failed to find fixtureLoader in fixture.ts");
|
|
713
610
|
}
|
|
714
611
|
};
|
|
715
612
|
FixtureManager = new FixtureManagerClass();
|
|
716
613
|
}));
|
|
717
|
-
|
|
718
614
|
//#endregion
|
|
719
615
|
init_fixture_manager();
|
|
720
616
|
export { FixtureManager, FixtureManagerClass, init_fixture_manager };
|
|
721
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZml4dHVyZS1tYW5hZ2VyLmpzIiwibmFtZXMiOlsiZmllbGQ6IHN0cmluZyIsImlkOiBudW1iZXIiLCJhcmdzIiwiZml4dHVyZXM6IEZpeHR1cmVSZWNvcmRbXSIsImVudGl0eSIsInJlY29yZHM6IEZpeHR1cmVSZWNvcmRbXSIsInJvdyIsInJlY29yZDogRml4dHVyZVJlY29yZCIsInJlc3VsdHM6IEZpeHR1cmVJbXBvcnRSZXN1bHRbXSIsInRhYmxlT3JkZXI6IHN0cmluZ1tdIiwicm93OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiIsInRhcmdldElkOiBudW1iZXIgfCBzdHJpbmciLCJsZXZlbHM6IEZpeHR1cmVSZWNvcmRbXVtdIiwiY3VycmVudExldmVsOiBGaXh0dXJlUmVjb3JkW10iLCJ3aGVyZUNsYXVzZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4iXSwic291cmNlcyI6WyIuLi8uLi9zcmMvdGVzdGluZy9maXh0dXJlLW1hbmFnZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGFzc2VydCBmcm9tIFwiYXNzZXJ0XCI7XG5pbXBvcnQgeyBleGVjU3luYyB9IGZyb20gXCJjaGlsZF9wcm9jZXNzXCI7XG5pbXBvcnQgeyByZWFkRmlsZVN5bmMsIHdyaXRlRmlsZVN5bmMgfSBmcm9tIFwiZnNcIjtcbmltcG9ydCB7IGluc3BlY3QgfSBmcm9tIFwidXRpbFwiO1xuXG5pbXBvcnQgY2hhbGsgZnJvbSBcImNoYWxrXCI7XG5pbXBvcnQgaW5mbGVjdGlvbiBmcm9tIFwiaW5mbGVjdGlvblwiO1xuaW1wb3J0IHsgdHlwZSBLbmV4IH0gZnJvbSBcImtuZXhcIjtcbmltcG9ydCB7IHVuaXF1ZSB9IGZyb20gXCJyYWRhc2hpXCI7XG5cbmltcG9ydCB7IFNvbmFtdSB9IGZyb20gXCIuLi9hcGkvc29uYW11XCI7XG5pbXBvcnQgeyBCYXNlTW9kZWwgfSBmcm9tIFwiLi4vZGF0YWJhc2UvYmFzZS1tb2RlbFwiO1xuaW1wb3J0IHsgdHlwZSBTb25hbXVEQkNvbmZpZyB9IGZyb20gXCIuLi9kYXRhYmFzZS9kYlwiO1xuaW1wb3J0IHsgY3JlYXRlS25leEluc3RhbmNlIH0gZnJvbSBcIi4uL2RhdGFiYXNlL2tuZXhcIjtcbmltcG9ydCB7IFVwc2VydEJ1aWxkZXIgfSBmcm9tIFwiLi4vZGF0YWJhc2UvdXBzZXJ0LWJ1aWxkZXJcIjtcbmltcG9ydCB7IHR5cGUgVUJSZWYgfSBmcm9tIFwiLi4vZGF0YWJhc2UvdXBzZXJ0LWJ1aWxkZXJcIjtcbmltcG9ydCB7IHR5cGUgRW50aXR5IH0gZnJvbSBcIi4uL2VudGl0eS9lbnRpdHlcIjtcbmltcG9ydCB7IEVudGl0eU1hbmFnZXIgfSBmcm9tIFwiLi4vZW50aXR5L2VudGl0eS1tYW5hZ2VyXCI7XG5pbXBvcnQge1xuICBpc0JlbG9uZ3NUb09uZVJlbGF0aW9uUHJvcCxcbiAgaXNIYXNNYW55UmVsYXRpb25Qcm9wLFxuICBpc01hbnlUb01hbnlSZWxhdGlvblByb3AsXG4gIGlzT25lVG9PbmVSZWxhdGlvblByb3AsXG4gIGlzUmVsYXRpb25Qcm9wLFxuICBpc1ZpcnR1YWxQcm9wLFxufSBmcm9tIFwiLi4vdHlwZXMvdHlwZXNcIjtcbmltcG9ydCB7XG4gIHR5cGUgQmVsb25nc1RvT25lUmVsYXRpb25Qcm9wLFxuICB0eXBlIERhdGFiYXNlU2NoZW1hRXh0ZW5kLFxuICB0eXBlIEVudGl0eVByb3AsXG4gIHR5cGUgRml4dHVyZUltcG9ydFJlc3VsdCxcbiAgdHlwZSBGaXh0dXJlUmVjb3JkLFxuICB0eXBlIEZpeHR1cmVTZWFyY2hPcHRpb25zLFxuICB0eXBlIE9uZVRvT25lUmVsYXRpb25Qcm9wLFxufSBmcm9tIFwiLi4vdHlwZXMvdHlwZXNcIjtcbmltcG9ydCB7IGlzVGVzdCB9IGZyb20gXCIuLi91dGlscy9jb250cm9sbGVyXCI7XG5pbXBvcnQgeyBSZWxhdGlvbkdyYXBoIH0gZnJvbSBcIi4vX3JlbGF0aW9uLWdyYXBoXCI7XG5cbi8qKiDsgqzsmqnsnpAg7KeA7KCVIOykkeuztSDtmZXsnbgg7Lus65+8IChlbnRpdHlJZOuzhOuhnCDsp4DsoJUpICovXG5leHBvcnQgaW50ZXJmYWNlIER1cGxpY2F0ZUNoZWNrT3B0aW9ucyB7XG4gIGNvbHVtbnM/OiB7XG4gICAgW2VudGl0eUlkOiBzdHJpbmddOiBzdHJpbmdbXTtcbiAgfTtcbn1cblxuZXhwb3J0IGNsYXNzIEZpeHR1cmVNYW5hZ2VyQ2xhc3Mge1xuICBwcml2YXRlIF90ZGI6IEtuZXggfCBudWxsID0gbnVsbDtcbiAgc2V0IHRkYih0ZGI6IEtuZXgpIHtcbiAgICB0aGlzLl90ZGIgPSB0ZGI7XG4gIH1cbiAgZ2V0IHRkYigpOiBLbmV4IHtcbiAgICBpZiAodGhpcy5fdGRiID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJGaXh0dXJlTWFuYWdlciBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWRcIik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl90ZGI7XG4gIH1cblxuICBwcml2YXRlIF9mZGI6IEtuZXggfCBudWxsID0gbnVsbDtcbiAgc2V0IGZkYihmZGI6IEtuZXgpIHtcbiAgICB0aGlzLl9mZGIgPSBmZGI7XG4gIH1cbiAgZ2V0IGZkYigpOiBLbmV4IHtcbiAgICBpZiAodGhpcy5fZmRiID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJGaXh0dXJlTWFuYWdlciBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWRcIik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9mZGI7XG4gIH1cbiAgY2FjaGVkVGFibGVOYW1lczogc3RyaW5nW10gfCBudWxsID0gbnVsbDtcblxuICBwcml2YXRlIHJlbGF0aW9uR3JhcGggPSBuZXcgUmVsYXRpb25HcmFwaCgpO1xuXG4gIC8vIFVwc2VydEJ1aWxkZXIg6riw67CYIGltcG9ydOulvCDsnITtlZwg7IOB7YOcXG4gIHByaXZhdGUgYnVpbGRlcjogVXBzZXJ0QnVpbGRlciA9IG5ldyBVcHNlcnRCdWlsZGVyKCk7XG4gIHByaXZhdGUgZml4dHVyZVJlZk1hcDogTWFwPHN0cmluZywgVUJSZWY+ID0gbmV3IE1hcCgpO1xuICBwcml2YXRlIHNraXBwZWRGaXh0dXJlczogTWFwPHN0cmluZywgeyBlbnRpdHlJZDogc3RyaW5nOyBleGlzdGluZ0lkOiBudW1iZXIgfCBzdHJpbmcgfT4gPVxuICAgIG5ldyBNYXAoKTtcblxuICBpbml0KCkge1xuICAgIGlmICh0aGlzLl90ZGIgIT09IG51bGwpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKFNvbmFtdS5kYkNvbmZpZy50ZXN0ICYmIFNvbmFtdS5kYkNvbmZpZy5wcm9kdWN0aW9uX21hc3Rlcikge1xuICAgICAgY29uc3QgdENvbm4gPSBTb25hbXUuZGJDb25maWcudGVzdC5jb25uZWN0aW9uIGFzIEtuZXguQ29ubmVjdGlvbkNvbmZpZyAmIHtcbiAgICAgICAgcG9ydD86IG51bWJlcjtcbiAgICAgIH07XG4gICAgICBjb25zdCBwQ29ubiA9IFNvbmFtdS5kYkNvbmZpZy5wcm9kdWN0aW9uX21hc3Rlci5jb25uZWN0aW9uIGFzIEtuZXguQ29ubmVjdGlvbkNvbmZpZyAmIHtcbiAgICAgICAgcG9ydD86IG51bWJlcjtcbiAgICAgIH07XG4gICAgICBpZiAoXG4gICAgICAgIGAke3RDb25uLmhvc3QgPz8gXCJsb2NhbGhvc3RcIn06JHt0Q29ubi5wb3J0ID8/IDU0MzJ9LyR7dENvbm4uZGF0YWJhc2V9YCA9PT1cbiAgICAgICAgYCR7cENvbm4uaG9zdCA/PyBcImxvY2FsaG9zdFwifToke3BDb25uLnBvcnQgPz8gNTQzMn0vJHtwQ29ubi5kYXRhYmFzZX1gXG4gICAgICApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGDthYzsiqTtirhEQuyZgCDtlITroZzrjZXshZhEQuyXkCDrj5nsnbztlZwg642w7J207YSw67Kg7J207Iqk6rCAIOyCrOyaqeuQmOyXiOyKteuLiOuLpC5gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLnRkYiA9IGNyZWF0ZUtuZXhJbnN0YW5jZShTb25hbXUuZGJDb25maWcudGVzdCk7XG4gICAgdGhpcy5mZGIgPSBjcmVhdGVLbmV4SW5zdGFuY2UoU29uYW11LmRiQ29uZmlnLmZpeHR1cmUpO1xuICB9XG5cbiAgLyoqXG4gICAg7JuQ6rKpIGZpeHR1cmUgRELrpbwg66Gc7LusIHRlc3QgRELroZwg67O17IKs7ZWp64uI64ukLlxuICAgIHBnX2R1bXDroZwg7JuQ6rKpIERC66W8IOuNpO2UhO2VmOqzoCwgcGdfcmVzdG9yZeuhnCDroZzsu6zsl5Ag67O17JuQ7ZWp64uI64ukLlxuICAqL1xuICBhc3luYyBzeW5jKCkge1xuICAgIGNvbnN0IGZpeHR1cmVDb25uID0gU29uYW11LmRiQ29uZmlnLmZpeHR1cmUuY29ubmVjdGlvbiBhcyBLbmV4LlBnQ29ubmVjdGlvbkNvbmZpZztcbiAgICBjb25zdCB0ZXN0Q29ubiA9IFNvbmFtdS5kYkNvbmZpZy50ZXN0LmNvbm5lY3Rpb24gYXMgS25leC5QZ0Nvbm5lY3Rpb25Db25maWc7XG5cbiAgICAvLyAxLiDroZzsu6wgdGVzdCBEQiDsl7DqsrAg7KKF66OMIOuwjyDsnqzsg53shLFcbiAgICBjb25zdCB0ZXN0UGdFbnYgPSB7IFBHUEFTU1dPUkQ6IHRlc3RDb25uLnBhc3N3b3JkIHx8IFwiXCIgfTtcbiAgICBleGVjU3luYyhcbiAgICAgIGBwc3FsIC1oICR7dGVzdENvbm4uaG9zdH0gLXAgJHt0ZXN0Q29ubi5wb3J0ID8/IDU0MzJ9IC1VICR7dGVzdENvbm4udXNlcn0gLWQgcG9zdGdyZXMgLWMgXCJcbiAgICAgICAgU0VMRUNUIHBnX3Rlcm1pbmF0ZV9iYWNrZW5kKHBnX3N0YXRfYWN0aXZpdHkucGlkKVxuICAgICAgICBGUk9NIHBnX3N0YXRfYWN0aXZpdHlcbiAgICAgICAgV0hFUkUgZGF0bmFtZSA9ICcke3Rlc3RDb25uLmRhdGFiYXNlfSdcbiAgICAgICAgICBBTkQgcGlkIDw+IHBnX2JhY2tlbmRfcGlkKCk7XG4gICAgICBcImAsXG4gICAgICB7IHN0ZGlvOiBcImluaGVyaXRcIiwgZW52OiB7IC4uLnByb2Nlc3MuZW52LCAuLi50ZXN0UGdFbnYgfSBhcyBOb2RlSlMuUHJvY2Vzc0VudiB9LFxuICAgICk7XG5cbiAgICBleGVjU3luYyhcbiAgICAgIGBwc3FsIC1oICR7dGVzdENvbm4uaG9zdH0gLXAgJHt0ZXN0Q29ubi5wb3J0ID8/IDU0MzJ9IC1VICR7dGVzdENvbm4udXNlcn0gLWQgcG9zdGdyZXMgLWMgXCJEUk9QIERBVEFCQVNFIElGIEVYSVNUUyBcXFxcXCIke3Rlc3RDb25uLmRhdGFiYXNlfVxcXFxcIlwiYCxcbiAgICAgIHsgc3RkaW86IFwiaW5oZXJpdFwiLCBlbnY6IHsgLi4ucHJvY2Vzcy5lbnYsIC4uLnRlc3RQZ0VudiB9IGFzIE5vZGVKUy5Qcm9jZXNzRW52IH0sXG4gICAgKTtcblxuICAgIGV4ZWNTeW5jKFxuICAgICAgYHBzcWwgLWggJHt0ZXN0Q29ubi5ob3N0fSAtcCAke3Rlc3RDb25uLnBvcnQgPz8gNTQzMn0gLVUgJHt0ZXN0Q29ubi51c2VyfSAtZCBwb3N0Z3JlcyAtYyBcIkNSRUFURSBEQVRBQkFTRSBcXFxcXCIke3Rlc3RDb25uLmRhdGFiYXNlfVxcXFxcIlwiYCxcbiAgICAgIHsgc3RkaW86IFwiaW5oZXJpdFwiLCBlbnY6IHsgLi4ucHJvY2Vzcy5lbnYsIC4uLnRlc3RQZ0VudiB9IGFzIE5vZGVKUy5Qcm9jZXNzRW52IH0sXG4gICAgKTtcblxuICAgIC8vIDIuIOybkOqyqSBmaXh0dXJlIERCIOKGkiDroZzsu6wgdGVzdCBEQuuhnCDrs7XsgqwgKHBnX2R1bXAgfCBwZ19yZXN0b3JlKVxuICAgIGNvbnN0IGZpeHR1cmVQZ0VudiA9IHsgUEdQQVNTV09SRDogZml4dHVyZUNvbm4ucGFzc3dvcmQgfHwgXCJcIiB9O1xuICAgIGNvbnN0IGR1bXBDbWQgPSBgcGdfZHVtcCAtaCAke2ZpeHR1cmVDb25uLmhvc3R9IC1wICR7Zml4dHVyZUNvbm4ucG9ydCA/PyA1NDMyfSAtVSAke2ZpeHR1cmVDb25uLnVzZXJ9IC1kICR7Zml4dHVyZUNvbm4uZGF0YWJhc2V9IC1GY2A7XG4gICAgY29uc3QgcmVzdG9yZUNtZCA9IGBwZ19yZXN0b3JlIC1oICR7dGVzdENvbm4uaG9zdH0gLXAgJHt0ZXN0Q29ubi5wb3J0ID8/IDU0MzJ9IC1VICR7dGVzdENvbm4udXNlcn0gLWQgJHt0ZXN0Q29ubi5kYXRhYmFzZX0gLS1uby1vd25lciAtLW5vLWFjbGA7XG5cbiAgICBleGVjU3luYyhgJHtkdW1wQ21kfSB8IFBHUEFTU1dPUkQ9XCIke3Rlc3RDb25uLnBhc3N3b3JkIHx8IFwiXCJ9XCIgJHtyZXN0b3JlQ21kfWAsIHtcbiAgICAgIHN0ZGlvOiBcImluaGVyaXRcIixcbiAgICAgIGVudjogeyAuLi5wcm9jZXNzLmVudiwgLi4uZml4dHVyZVBnRW52IH0gYXMgTm9kZUpTLlByb2Nlc3NFbnYsXG4gICAgICBzaGVsbDogXCIvYmluL2Jhc2hcIixcbiAgICB9KTtcblxuICAgIC8vIDMuIOyLnO2AgOyKpCDrpqzshYsgKOuNsOydtO2EsCDrs7Xsgqwg7ZuEIOyLnO2AgOyKpOulvCBNQVgoaWQp66GcIOygleugrClcbiAgICBhd2FpdCB0aGlzLnJlc2V0U2VxdWVuY2VzKFNvbmFtdS5kYkNvbmZpZy50ZXN0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiDrqqjrk6Ag7YWM7J2067iU7J2YIOyLnO2AgOyKpOulvCDtmITsnqwgTUFYKGlkKeuhnCDrpqzshYvtlanri4jri6QuXG4gICAqIGZpeHR1cmUgc3luYyDtm4Qg7Iuc7YCA7Iqk6rCAIOyLpOygnCDrjbDsnbTthLDsmYAg66ee7KeAIOyViuuKlCDrrLjsoJzrpbwg7ZW06rKw7ZWp64uI64ukLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyByZXNldFNlcXVlbmNlcyhkYkNvbmZpZzogU29uYW11REJDb25maWdbXCJ0ZXN0XCJdKSB7XG4gICAgY29uc3QgdGVzdERiID0gY3JlYXRlS25leEluc3RhbmNlKGRiQ29uZmlnKTtcbiAgICBjb25zdCBlbnRpdGllcyA9IEVudGl0eU1hbmFnZXIuZ2V0QWxsRW50aXRpZXMoKTtcblxuICAgIHRyeSB7XG4gICAgICBmb3IgKGNvbnN0IGVudGl0eSBvZiBlbnRpdGllcykge1xuICAgICAgICBjb25zdCB0YWJsZU5hbWUgPSBlbnRpdHkudGFibGUgfHwgZW50aXR5LmlkLnRvTG93ZXJDYXNlKCk7XG5cbiAgICAgICAgLy8gaWQg7ZWE65Oc7J2YIO2DgOyeheydhCDtmZXsnbjtlanri4jri6RcbiAgICAgICAgY29uc3QgaWRQcm9wID0gZW50aXR5LnByb3BzLmZpbmQoKHApID0+IHAubmFtZSA9PT0gXCJpZFwiKTtcbiAgICAgICAgY29uc3QgaWRUeXBlID0gaWRQcm9wPy50eXBlO1xuXG4gICAgICAgIC8vIGludGVnZXIvYmlnSW50ZWdlcuydtOqxsOuCmCwgc3RyaW5n7J207KeA66eMIGZpeHR1cmVTdHJhdGVneT1zZXF1ZW5jZeyduCDqsr3smrDsl5Drp4wg66as7IWL7ZWp64uI64ukXG4gICAgICAgIGNvbnN0IHVzZXNTZXF1ZW5jZSA9XG4gICAgICAgICAgaWRUeXBlID09PSBcImludGVnZXJcIiB8fFxuICAgICAgICAgIGlkVHlwZSA9PT0gXCJiaWdJbnRlZ2VyXCIgfHxcbiAgICAgICAgICBpZFByb3A/LmNvbmU/LmZpeHR1cmVTdHJhdGVneSA9PT0gXCJzZXF1ZW5jZVwiO1xuXG4gICAgICAgIGlmICghdXNlc1NlcXVlbmNlKSB7XG4gICAgICAgICAgIWlzVGVzdCgpICYmXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgICAgYFNraXBwaW5nIHNlcXVlbmNlIHJlc2V0IGZvciAke3RhYmxlTmFtZX0gKGlkIHR5cGU6ICR7aWRUeXBlIHx8IFwidW5rbm93blwifSlgLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFBvc3RncmVTUUwg7Iuc7YCA7Iqk66W8IO2YhOyerCDthYzsnbTruJTsnZggTUFYKGlkKeuhnCDrpqzshYvtlanri4jri6QuXG4gICAgICAgIC8vIHN0cmluZyDtg4DsnoXsnZgg6rK97JqwIOyIq+yekCDsupDsiqTtjIXsnbQg7ZWE7JqU7ZWp64uI64ukLlxuICAgICAgICBjb25zdCBtYXhFeHByID0gaWRUeXBlID09PSBcInN0cmluZ1wiID8gXCJNQVgoaWQ6OmJpZ2ludClcIiA6IFwiTUFYKGlkKVwiO1xuICAgICAgICBhd2FpdCB0ZXN0RGIucmF3KGBcbiAgICAgICAgICBTRUxFQ1Qgc2V0dmFsKFxuICAgICAgICAgICAgcGdfZ2V0X3NlcmlhbF9zZXF1ZW5jZSgncHVibGljLiR7dGFibGVOYW1lfScsICdpZCcpLFxuICAgICAgICAgICAgQ09BTEVTQ0UoKFNFTEVDVCAke21heEV4cHJ9IEZST00gJHt0YWJsZU5hbWV9KSwgMSlcbiAgICAgICAgICApXG4gICAgICAgIGApO1xuICAgICAgfVxuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCB0ZXN0RGIuZGVzdHJveSgpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgdmlzaXRlZFJlY29yZHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgYXN5bmMgaW1wb3J0Rml4dHVyZShlbnRpdHlJZDogc3RyaW5nLCBpZHM6IG51bWJlcltdKSB7XG4gICAgLy8g67Cp66y4IOq4sOuhnSDstIjquLDtmZQgKOyDiOuhnOyatCBpbXBvcnQg7J6R7JeFIOyLnOyekSlcbiAgICB0aGlzLnZpc2l0ZWRSZWNvcmRzLmNsZWFyKCk7XG5cbiAgICBjb25zdCBxdWVyaWVzID0gdW5pcXVlKFxuICAgICAgKFxuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgICBpZHMubWFwKGFzeW5jIChpZCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuZ2V0SW1wb3J0UXVlcmllcyhlbnRpdHlJZCwgXCJpZFwiLCBpZCk7XG4gICAgICAgICAgfSksXG4gICAgICAgIClcbiAgICAgICkuZmxhdCgpLFxuICAgICk7XG5cbiAgICBjb25zdCB3ZGIgPSBCYXNlTW9kZWwuZ2V0REIoXCJ3XCIpO1xuICAgIGZvciAoY29uc3QgcXVlcnkgb2YgcXVlcmllcykge1xuICAgICAgYXdhaXQgd2RiLnJhdyhxdWVyeSk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZ2V0SW1wb3J0UXVlcmllcyhlbnRpdHlJZDogc3RyaW5nLCBmaWVsZDogc3RyaW5nLCBpZDogbnVtYmVyKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIGNvbnN0IHJlY29yZEtleSA9IGAke2VudGl0eUlkfSMke2ZpZWxkfSMke2lkfWA7XG5cbiAgICAvLyDsiJztmZgg7LC47KGwIOuwqeyngDog7J2066+4IOuwqeusuO2VnCDroIjsvZTrk5zripQg7Iqk7YK1XG4gICAgaWYgKHRoaXMudmlzaXRlZFJlY29yZHMuaGFzKHJlY29yZEtleSkpIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgdGhpcy52aXNpdGVkUmVjb3Jkcy5hZGQocmVjb3JkS2V5KTtcblxuICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKTtcbiAgICBjb25zdCB3ZGIgPSBCYXNlTW9kZWwuZ2V0REIoXCJ3XCIpO1xuXG4gICAgLy8g7Jes6riw7IScIOyLpERC7J2YIHJvdyDqsIDsoLjsmLRcbiAgICBjb25zdCBbcm93XSA9IGF3YWl0IHdkYihlbnRpdHkudGFibGUpLndoZXJlKGZpZWxkLCBpZCkubGltaXQoMSk7XG4gICAgaWYgKHJvdyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7ZW50aXR5SWR9IyR7aWR9IHJvd+ulvCDssL7snYQg7IiYIOyXhuyKteuLiOuLpC5gKTtcbiAgICB9XG5cbiAgICAvLyDtlL3siqTss5BEQiwg7IukREJcbiAgICBjb25zdCBmaXh0dXJlRGF0YWJhc2UgPSAoU29uYW11LmRiQ29uZmlnLmZpeHR1cmUuY29ubmVjdGlvbiBhcyBLbmV4LkNvbm5lY3Rpb25Db25maWcpLmRhdGFiYXNlO1xuICAgIGNvbnN0IHJlYWxEYXRhYmFzZSA9IChTb25hbXUuZGJDb25maWcucHJvZHVjdGlvbl9tYXN0ZXIuY29ubmVjdGlvbiBhcyBLbmV4LkNvbm5lY3Rpb25Db25maWcpXG4gICAgICAuZGF0YWJhc2U7XG5cbiAgICBjb25zdCBzZWxmUXVlcnkgPSBgSU5TRVJUIElHTk9SRSBJTlRPIFxcYCR7Zml4dHVyZURhdGFiYXNlfVxcYC5cXGAke2VudGl0eS50YWJsZX1cXGAgKFNFTEVDVCAqIEZST00gXFxgJHtyZWFsRGF0YWJhc2V9XFxgLlxcYCR7ZW50aXR5LnRhYmxlfVxcYCBXSEVSRSBcXGBpZFxcYCA9ICR7aWR9KWA7XG5cbiAgICBjb25zdCBhcmdzID0gT2JqZWN0LmVudHJpZXMoZW50aXR5LnJlbGF0aW9ucylcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgIChbLCByZWxhdGlvbl0pID0+XG4gICAgICAgICAgaXNCZWxvbmdzVG9PbmVSZWxhdGlvblByb3AocmVsYXRpb24pIHx8XG4gICAgICAgICAgKGlzT25lVG9PbmVSZWxhdGlvblByb3AocmVsYXRpb24pICYmIHJlbGF0aW9uLmN1c3RvbUpvaW5DbGF1c2UgPT09IHVuZGVmaW5lZCksXG4gICAgICApXG4gICAgICAubWFwKChbLCByZWxhdGlvbl0pID0+IHtcbiAgICAgICAgLypcbiAgICAgICAgQmVsb25nc1RvT25l7J24IOqyveyasFxuICAgICAgICAgIENhdGVnb3J5IC8gJ2lkJyAvIHJvd1tjYXRlZ29yeV9pZF0g7Zi47LacXG4gICAgICAgIE9uZVRvT25l7JeQIGpvaW5Db2x1bW4gPT09IHRydWUg7J24IOqyveyasFxuICAgICAgICAgIFByb2ZpbGUgLyAnaWQnIC8gcm93W3Byb2ZpbGVfaWRdIO2YuOy2nFxuICAgICAgICBPbmVUb09uZeyXkCBqb2luQ29sdW1uID09PSBmYWxzZSDsnbgg6rK97JqwXG4gICAgICAgICAgUHJvZmlsZSAvICdwcm9maWxlX2lkJyAvIHJvd1snaWQnXSDtmLjstpxcbiAgICAgICAgKi9cbiAgICAgICAgbGV0IGZpZWxkOiBzdHJpbmc7XG4gICAgICAgIGxldCBpZDogbnVtYmVyO1xuICAgICAgICBpZiAoaXNPbmVUb09uZVJlbGF0aW9uUHJvcChyZWxhdGlvbikgJiYgIXJlbGF0aW9uLmhhc0pvaW5Db2x1bW4pIHtcbiAgICAgICAgICBjb25zdCByZWxhdGVkRW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQocmVsYXRpb24ud2l0aCk7XG4gICAgICAgICAgY29uc3QgcmVsYXRlZElkQ29sdW1uTmFtZSA9IHJlbGF0ZWRFbnRpdHkucHJvcHMuZmluZChcbiAgICAgICAgICAgIChwKSA9PiBpc1JlbGF0aW9uUHJvcChwKSAmJiBwLndpdGggPT09IGVudGl0eS5pZCxcbiAgICAgICAgICApPy5uYW1lO1xuICAgICAgICAgIGlmICghcmVsYXRlZElkQ29sdW1uTmFtZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke3JlbGF0ZWRFbnRpdHkuaWR97J2YICR7ZW50aXR5LmlkfSDqtIDqs4Qg7ZSE66Gt7J2EIOywvuydhCDsiJgg7JeG7Iq164uI64ukLmApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBmaWVsZCA9IGAke3JlbGF0ZWRJZENvbHVtbk5hbWV9X2lkYDtcbiAgICAgICAgICBpZCA9IHJvdy5pZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBmaWVsZCA9IFwiaWRcIjtcbiAgICAgICAgICBpZCA9IHJvd1tgJHtyZWxhdGlvbi5uYW1lfV9pZGBdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgZW50aXR5SWQ6IHJlbGF0aW9uLndpdGgsXG4gICAgICAgICAgZmllbGQsXG4gICAgICAgICAgaWQsXG4gICAgICAgIH07XG4gICAgICB9KVxuICAgICAgLmZpbHRlcigoYXJnKSA9PiBhcmcuaWQgIT09IG51bGwpO1xuXG4gICAgY29uc3QgcmVsUXVlcmllcyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgYXJncy5tYXAoYXN5bmMgKGFyZ3MpID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0SW1wb3J0UXVlcmllcyhhcmdzLmVudGl0eUlkLCBhcmdzLmZpZWxkLCBhcmdzLmlkKTtcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICByZXR1cm4gWy4uLnVuaXF1ZShyZWxRdWVyaWVzLnRvUmV2ZXJzZWQoKS5mbGF0KCkpLCBzZWxmUXVlcnldO1xuICB9XG5cbiAgYXN5bmMgZGVzdHJveSgpIHtcbiAgICBpZiAodGhpcy5fdGRiKSB7XG4gICAgICBhd2FpdCB0aGlzLl90ZGIuZGVzdHJveSgpO1xuICAgICAgdGhpcy5fdGRiID0gbnVsbDtcbiAgICB9XG4gICAgaWYgKHRoaXMuX2ZkYikge1xuICAgICAgYXdhaXQgdGhpcy5fZmRiLmRlc3Ryb3koKTtcbiAgICAgIHRoaXMuX2ZkYiA9IG51bGw7XG4gICAgfVxuICAgIGF3YWl0IEJhc2VNb2RlbC5kZXN0cm95KCk7XG4gIH1cblxuICBhc3luYyBnZXRGaXh0dXJlcyhcbiAgICBzb3VyY2VEQk5hbWU6IGtleW9mIFNvbmFtdURCQ29uZmlnLFxuICAgIHRhcmdldERCTmFtZToga2V5b2YgU29uYW11REJDb25maWcsXG4gICAgc2VhcmNoT3B0aW9uczogRml4dHVyZVNlYXJjaE9wdGlvbnMsXG4gICAgZHVwbGljYXRlQ2hlY2s/OiBEdXBsaWNhdGVDaGVja09wdGlvbnMsXG4gICkge1xuICAgIGNvbnN0IHNvdXJjZURCID0gY3JlYXRlS25leEluc3RhbmNlKFNvbmFtdS5kYkNvbmZpZ1tzb3VyY2VEQk5hbWVdKTtcbiAgICBjb25zdCB0YXJnZXREQiA9IGNyZWF0ZUtuZXhJbnN0YW5jZShTb25hbXUuZGJDb25maWdbdGFyZ2V0REJOYW1lXSk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgeyBlbnRpdHlJZCwgZmllbGQsIHZhbHVlLCBzZWFyY2hUeXBlIH0gPSBzZWFyY2hPcHRpb25zO1xuXG4gICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgICBjb25zdCBjb2x1bW4gPVxuICAgICAgICBlbnRpdHkucHJvcHMuZmluZCgocHJvcCkgPT4gcHJvcC5uYW1lID09PSBmaWVsZCk/LnR5cGUgPT09IFwicmVsYXRpb25cIlxuICAgICAgICAgID8gYCR7ZmllbGR9X2lkYFxuICAgICAgICAgIDogZmllbGQ7XG5cbiAgICAgIGxldCBxdWVyeSA9IHNvdXJjZURCKGVudGl0eS50YWJsZSk7XG4gICAgICBpZiAoc2VhcmNoVHlwZSA9PT0gXCJlcXVhbHNcIikge1xuICAgICAgICBxdWVyeSA9IHF1ZXJ5LndoZXJlKGNvbHVtbiwgdmFsdWUpO1xuICAgICAgfSBlbHNlIGlmIChzZWFyY2hUeXBlID09PSBcImxpa2VcIikge1xuICAgICAgICBxdWVyeSA9IHF1ZXJ5LndoZXJlKGNvbHVtbiwgXCJsaWtlXCIsIGAlJHt2YWx1ZX0lYCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJvd3MgPSBhd2FpdCBxdWVyeTtcbiAgICAgIGlmIChyb3dzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyByZWNvcmRzIGZvdW5kXCIpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBmaXh0dXJlczogRml4dHVyZVJlY29yZFtdID0gW107XG4gICAgICBmb3IgKGNvbnN0IHJvdyBvZiByb3dzKSB7XG4gICAgICAgIGNvbnN0IGluaXRpYWxSZWNvcmRzTGVuZ3RoID0gZml4dHVyZXMubGVuZ3RoO1xuICAgICAgICBjb25zdCBuZXdSZWNvcmRzID0gYXdhaXQgdGhpcy5jcmVhdGVGaXh0dXJlUmVjb3JkKGVudGl0eSwgcm93LCB7XG4gICAgICAgICAgX2RiOiBzb3VyY2VEQixcbiAgICAgICAgfSk7XG4gICAgICAgIGZpeHR1cmVzLnB1c2goLi4ubmV3UmVjb3Jkcyk7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRGaXh0dXJlUmVjb3JkID0gZml4dHVyZXMuZmluZCgocikgPT4gci5maXh0dXJlSWQgPT09IGAke2VudGl0eUlkfSMke3Jvdy5pZH1gKTtcblxuICAgICAgICBpZiAoY3VycmVudEZpeHR1cmVSZWNvcmQpIHtcbiAgICAgICAgICAvLyDtmITsnqwgZml4dHVyZeuhnOu2gO2EsCDsg53shLHrkJwgZmV0Y2hlZFJlY29yZHMg7ISk7KCVXG4gICAgICAgICAgY3VycmVudEZpeHR1cmVSZWNvcmQuZmV0Y2hlZFJlY29yZHMgPSBmaXh0dXJlc1xuICAgICAgICAgICAgLmZpbHRlcigocikgPT4gci5maXh0dXJlSWQgIT09IGN1cnJlbnRGaXh0dXJlUmVjb3JkLmZpeHR1cmVJZClcbiAgICAgICAgICAgIC5zbGljZShpbml0aWFsUmVjb3Jkc0xlbmd0aClcbiAgICAgICAgICAgIC5tYXAoKHIpID0+IHIuZml4dHVyZUlkKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IGZpeHR1cmUgb2YgZml4dHVyZXMpIHtcbiAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZml4dHVyZS5lbnRpdHlJZCk7XG5cbiAgICAgICAgLy8g7IKs7Jqp7J6QIOyngOyglSDsu6zrn7wg6riw7KSAIOykkeuztSDtmZXsnbgg4oaSIHRhcmdldFxuICAgICAgICBjb25zdCBjdXN0b21Db2x1bW5zID0gZHVwbGljYXRlQ2hlY2s/LmNvbHVtbnM/LltmaXh0dXJlLmVudGl0eUlkXTtcbiAgICAgICAgaWYgKGN1c3RvbUNvbHVtbnMgJiYgY3VzdG9tQ29sdW1ucy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgY29uc3QgY3VzdG9tRHVwbGljYXRlUm93ID0gYXdhaXQgdGhpcy5jaGVja0R1cGxpY2F0ZUJ5Q29sdW1ucyhcbiAgICAgICAgICAgIHRhcmdldERCLFxuICAgICAgICAgICAgZW50aXR5LFxuICAgICAgICAgICAgZml4dHVyZSxcbiAgICAgICAgICAgIGN1c3RvbUNvbHVtbnMsXG4gICAgICAgICAgKTtcbiAgICAgICAgICBpZiAoY3VzdG9tRHVwbGljYXRlUm93KSB7XG4gICAgICAgICAgICBjb25zdCBbcmVjb3JkXSA9IGF3YWl0IHRoaXMuY3JlYXRlRml4dHVyZVJlY29yZChlbnRpdHksIGN1c3RvbUR1cGxpY2F0ZVJvdywge1xuICAgICAgICAgICAgICBzaW5nbGVSZWNvcmQ6IHRydWUsXG4gICAgICAgICAgICAgIF9kYjogdGFyZ2V0REIsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGZpeHR1cmUudGFyZ2V0ID0gcmVjb3JkO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFVuaXF1ZSBpbmRleCDquLDspIAg7KSR67O1IO2ZleyduCDihpIgZml4dHVyZS51bmlxdWVcbiAgICAgICAgY29uc3QgdW5pcXVlUm93ID0gYXdhaXQgdGhpcy5jaGVja1VuaXF1ZVZpb2xhdGlvbih0YXJnZXREQiwgZW50aXR5LCBmaXh0dXJlKTtcbiAgICAgICAgaWYgKHVuaXF1ZVJvdykge1xuICAgICAgICAgIGNvbnN0IFtyZWNvcmRdID0gYXdhaXQgdGhpcy5jcmVhdGVGaXh0dXJlUmVjb3JkKGVudGl0eSwgdW5pcXVlUm93LCB7XG4gICAgICAgICAgICBzaW5nbGVSZWNvcmQ6IHRydWUsXG4gICAgICAgICAgICBfZGI6IHRhcmdldERCLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGZpeHR1cmUudW5pcXVlID0gcmVjb3JkO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB1bmlxdWUoZml4dHVyZXMsIChmKSA9PiBmLmZpeHR1cmVJZCk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChbdGFyZ2V0REIuZGVzdHJveSgpLCBzb3VyY2VEQi5kZXN0cm95KCldKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBjcmVhdGVGaXh0dXJlUmVjb3JkKFxuICAgIGVudGl0eTogRW50aXR5LFxuICAgIHJvdzoge1xuICAgICAgaWQ6IG51bWJlciB8IHN0cmluZztcbiAgICAgIFtrZXk6IHN0cmluZ106IHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4gfCBudWxsO1xuICAgIH0sXG4gICAgb3B0aW9ucz86IHtcbiAgICAgIHNpbmdsZVJlY29yZD86IGJvb2xlYW47XG4gICAgICBfZGI/OiBLbmV4O1xuICAgIH0sXG4gICk6IFByb21pc2U8Rml4dHVyZVJlY29yZFtdPiB7XG4gICAgY29uc3QgcmVjb3JkczogRml4dHVyZVJlY29yZFtdID0gW107XG4gICAgY29uc3QgdmlzaXRlZEVudGl0aWVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgICBjb25zdCBjcmVhdGUgPSBhc3luYyAoXG4gICAgICBlbnRpdHk6IEVudGl0eSxcbiAgICAgIHJvdzoge1xuICAgICAgICBpZDogbnVtYmVyIHwgc3RyaW5nO1xuICAgICAgICBba2V5OiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgbnVsbDtcbiAgICAgIH0sXG4gICAgKSA9PiB7XG4gICAgICBjb25zdCBmaXh0dXJlSWQgPSBgJHtlbnRpdHkuaWR9IyR7cm93LmlkfWA7XG4gICAgICBpZiAodmlzaXRlZEVudGl0aWVzLmhhcyhmaXh0dXJlSWQpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHZpc2l0ZWRFbnRpdGllcy5hZGQoZml4dHVyZUlkKTtcblxuICAgICAgY29uc3QgcmVjb3JkOiBGaXh0dXJlUmVjb3JkID0ge1xuICAgICAgICBmaXh0dXJlSWQsXG4gICAgICAgIGVudGl0eUlkOiBlbnRpdHkuaWQsXG4gICAgICAgIGlkOiByb3cuaWQsXG4gICAgICAgIGNvbHVtbnM6IHt9LFxuICAgICAgICBmZXRjaGVkUmVjb3JkczogW10sXG4gICAgICAgIGJlbG9uZ3NSZWNvcmRzOiBbXSxcbiAgICAgIH07XG5cbiAgICAgIGZvciAoY29uc3QgcHJvcCBvZiBlbnRpdHkucHJvcHMpIHtcbiAgICAgICAgaWYgKGlzVmlydHVhbFByb3AocHJvcCkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlY29yZC5jb2x1bW5zW3Byb3AubmFtZV0gPSB7XG4gICAgICAgICAgcHJvcDogcHJvcCxcbiAgICAgICAgICB2YWx1ZTogcm93W3Byb3AubmFtZV0sXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgZGIgPSBvcHRpb25zPy5fZGIgPz8gQmFzZU1vZGVsLmdldERCKFwid1wiKTtcbiAgICAgICAgaWYgKGlzTWFueVRvTWFueVJlbGF0aW9uUHJvcChwcm9wKSkge1xuICAgICAgICAgIGNvbnN0IHJlbGF0ZWRFbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChwcm9wLndpdGgpO1xuICAgICAgICAgIGNvbnN0IHRocm91Z2hUYWJsZSA9IHByb3Auam9pblRhYmxlO1xuICAgICAgICAgIGNvbnN0IGZyb21Db2x1bW4gPSBgJHtpbmZsZWN0aW9uLnNpbmd1bGFyaXplKGVudGl0eS50YWJsZSl9X2lkYDtcbiAgICAgICAgICBjb25zdCB0b0NvbHVtbiA9IGAke2luZmxlY3Rpb24uc2luZ3VsYXJpemUocmVsYXRlZEVudGl0eS50YWJsZSl9X2lkYDtcblxuICAgICAgICAgIGNvbnN0IHJlbGF0ZWRJZHMgPSBhd2FpdCBkYih0aHJvdWdoVGFibGUpLndoZXJlKGZyb21Db2x1bW4sIHJvdy5pZCkucGx1Y2sodG9Db2x1bW4pO1xuICAgICAgICAgIHJlY29yZC5jb2x1bW5zW3Byb3AubmFtZV0udmFsdWUgPSByZWxhdGVkSWRzO1xuICAgICAgICB9IGVsc2UgaWYgKGlzSGFzTWFueVJlbGF0aW9uUHJvcChwcm9wKSkge1xuICAgICAgICAgIGNvbnN0IHJlbGF0ZWRFbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChwcm9wLndpdGgpO1xuICAgICAgICAgIGNvbnN0IHJlbGF0ZWRJZHMgPSBhd2FpdCBkYihyZWxhdGVkRW50aXR5LnRhYmxlKVxuICAgICAgICAgICAgLndoZXJlKHByb3Auam9pbkNvbHVtbiwgcm93LmlkKVxuICAgICAgICAgICAgLnBsdWNrKFwiaWRcIik7XG4gICAgICAgICAgcmVjb3JkLmNvbHVtbnNbcHJvcC5uYW1lXS52YWx1ZSA9IHJlbGF0ZWRJZHM7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNPbmVUb09uZVJlbGF0aW9uUHJvcChwcm9wKSAmJiAhcHJvcC5oYXNKb2luQ29sdW1uKSB7XG4gICAgICAgICAgLy8g7Jet67Cp7ZalIE9uZVRvT25lOiBGS+ulvCDqsIDsp4Qg6rSA66CoIOyXlO2LsO2LsOulvCDssL7sirXri4jri6RcbiAgICAgICAgICAvLyDsmIjsi5w6IFVzZXIgT25lVG9PbmUgRW1wbG95ZWUgKEVtcGxveWVl6rCAIHVzZXJfaWQgRkvrpbwg6rCA7KeQKVxuICAgICAgICAgIGNvbnN0IHJlbGF0ZWRFbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChwcm9wLndpdGgpO1xuICAgICAgICAgIGNvbnN0IHJlbGF0ZWRQcm9wID0gcmVsYXRlZEVudGl0eS5wcm9wcy5maW5kKFxuICAgICAgICAgICAgKHApID0+IGlzUmVsYXRpb25Qcm9wKHApICYmIHAud2l0aCA9PT0gZW50aXR5LmlkLFxuICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKHJlbGF0ZWRQcm9wICYmIGlzUmVsYXRpb25Qcm9wKHJlbGF0ZWRQcm9wKSkge1xuICAgICAgICAgICAgLy8g6rSA66CoIOyXlO2LsO2LsOyXkOyEnCBGSyDsu6zrn7zsnLzroZwg7L+866as7ZWp64uI64ukIChpZOqwgCDslYTri5gpXG4gICAgICAgICAgICBjb25zdCBma0NvbHVtbiA9IGAke3JlbGF0ZWRQcm9wLm5hbWV9X2lkYDtcbiAgICAgICAgICAgIGNvbnN0IHJlbGF0ZWRSb3cgPSBhd2FpdCBkYihyZWxhdGVkRW50aXR5LnRhYmxlKS53aGVyZShma0NvbHVtbiwgcm93LmlkKS5maXJzdCgpO1xuICAgICAgICAgICAgcmVjb3JkLmNvbHVtbnNbcHJvcC5uYW1lXS52YWx1ZSA9IHJlbGF0ZWRSb3c/LmlkO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChpc1JlbGF0aW9uUHJvcChwcm9wKSkge1xuICAgICAgICAgIGNvbnN0IHJlbGF0ZWRJZCA9IHJvd1tgJHtwcm9wLm5hbWV9X2lkYF07XG4gICAgICAgICAgcmVjb3JkLmNvbHVtbnNbcHJvcC5uYW1lXS52YWx1ZSA9IHJlbGF0ZWRJZDtcbiAgICAgICAgICBpZiAocmVsYXRlZElkKSB7XG4gICAgICAgICAgICByZWNvcmQuYmVsb25nc1JlY29yZHMucHVzaChgJHtwcm9wLndpdGh9IyR7cmVsYXRlZElkfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW9wdGlvbnM/LnNpbmdsZVJlY29yZCAmJiByZWxhdGVkSWQpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlbGF0ZWRFbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChwcm9wLndpdGgpO1xuICAgICAgICAgICAgY29uc3QgcmVsYXRlZFJvdyA9IGF3YWl0IGRiKHJlbGF0ZWRFbnRpdHkudGFibGUpLndoZXJlKFwiaWRcIiwgcmVsYXRlZElkKS5maXJzdCgpO1xuICAgICAgICAgICAgaWYgKHJlbGF0ZWRSb3cpIHtcbiAgICAgICAgICAgICAgYXdhaXQgY3JlYXRlKHJlbGF0ZWRFbnRpdHksIHJlbGF0ZWRSb3cpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZWNvcmRzLnB1c2gocmVjb3JkKTtcbiAgICB9O1xuXG4gICAgYXdhaXQgY3JlYXRlKGVudGl0eSwgcm93KTtcblxuICAgIHJldHVybiByZWNvcmRzO1xuICB9XG5cbiAgLyoqXG4gICAqIDEuIFJlbGF0aW9uR3JhcGjroZwgZml4dHVyZSDri6jsnIQg7IK97J6FIOyInOyEnCDqs4TsgrAgKHNlbGYtcmVmZXJlbmNlIO2PrO2VqClcbiAgICogMi4g7YWM7J2067iU67OEIOugiOuyqOuzhOuhnCBVcHNlcnRCdWlsZGVy7JeQIOuTseuhnSDrsI8gdXBzZXJ0IOyLpO2WiVxuICAgKiAzLiDsiJzshJwg6riw67CYIHV1aWTihpJpZCDrp6TtlZEgKFVwc2VydEJ1aWxkZXLqsIAgdXVpZOulvCBEQuyXkCDsoIDsnqXtlZjsp4Ag7JWK7Jy866+A66GcKVxuICAgKlxuICAgKiBVcHNlcnRCdWlsZGVy64qUIHNlbGYtcmVmZXJlbmNl6rCAIOyeiOycvOuptCBidWlsZEluc2VydExldmVscygp66GcIOyerOygleugrO2VmOyXrFxuICAgKiDrk7HroZ0g7Iic7ISc7JmAIOuwmO2ZmCDsiJzshJzqsIAg64us65287KeIIOyImCDsnojsirXri4jri6QuIOydtOulvCDrsKnsp4DtlZjquLAg7JyE7ZW0XG4gICAqIEZpeHR1cmVNYW5hZ2Vy6rCAIOugiOuyqOuzhOuhnCDrgpjriKDshJwg7LKY66as7ZWY7JesIOqwgSB1cHNlcnQg7Zi47Lac7JeQ7ISc64qUXG4gICAqIHNlbGYtcmVmZXJlbmNl6rCAIOyXhuuPhOuhnSDtlanri4jri6QuXG4gICAqL1xuICBhc3luYyBpbnNlcnRGaXh0dXJlcyhcbiAgICBkYk5hbWU6IGtleW9mIFNvbmFtdURCQ29uZmlnLFxuICAgIF9maXh0dXJlczogRml4dHVyZVJlY29yZFtdLFxuICApOiBQcm9taXNlPEZpeHR1cmVJbXBvcnRSZXN1bHRbXT4ge1xuICAgIGNvbnN0IGZpeHR1cmVzID0gdW5pcXVlKF9maXh0dXJlcywgKGYpID0+IGYuZml4dHVyZUlkKTtcblxuICAgIC8vIOy0iOq4sO2ZlFxuICAgIHRoaXMuYnVpbGRlciA9IG5ldyBVcHNlcnRCdWlsZGVyKCk7XG4gICAgdGhpcy5maXh0dXJlUmVmTWFwID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuc2tpcHBlZEZpeHR1cmVzID0gbmV3IE1hcCgpO1xuXG4gICAgLy8g67OR66CsIO2FjOyKpO2KuCDrqqjrk5zsl5DshJzripQgd29ya2Vy67OEIERC7JeQIOyggOyepVxuICAgIGNvbnN0IGRiQ29uZmlnID1cbiAgICAgIHByb2Nlc3MuZW52LlNPTkFNVV9XT1JLRVJfREIgPT09IFwidHJ1ZVwiICYmIHByb2Nlc3MuZW52LlZJVEVTVF9QT09MX0lEXG4gICAgICAgID8gKCgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHdvcmtlcklkID0gcGFyc2VJbnQocHJvY2Vzcy5lbnYuVklURVNUX1BPT0xfSUQgPz8gXCIxXCIsIDEwKTtcbiAgICAgICAgICAgIGNvbnN0IGJhc2VDb25maWcgPSBTb25hbXUuZGJDb25maWdbZGJOYW1lXTtcbiAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBiYXNlQ29uZmlnLmNvbm5lY3Rpb24gYXMgeyBkYXRhYmFzZTogc3RyaW5nIH07XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAuLi5iYXNlQ29uZmlnLFxuICAgICAgICAgICAgICBjb25uZWN0aW9uOiB7IC4uLmNvbm5lY3Rpb24sIGRhdGFiYXNlOiBgJHtjb25uZWN0aW9uLmRhdGFiYXNlfV8ke3dvcmtlcklkfWAgfSxcbiAgICAgICAgICAgICAgcG9vbDogeyBtaW46IDEsIG1heDogMSB9LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9KSgpXG4gICAgICAgIDogU29uYW11LmRiQ29uZmlnW2RiTmFtZV07XG4gICAgY29uc3QgZGIgPSBjcmVhdGVLbmV4SW5zdGFuY2UoZGJDb25maWcpO1xuICAgIGNvbnN0IHJlc3VsdHM6IEZpeHR1cmVJbXBvcnRSZXN1bHRbXSA9IFtdO1xuXG4gICAgdHJ5IHtcbiAgICAgIC8vIDEuIFJlbGF0aW9uR3JhcGjroZwgZml4dHVyZSDri6jsnIQg7IK97J6FIOyInOyEnCDqs4TsgrBcbiAgICAgIHRoaXMucmVsYXRpb25HcmFwaC5idWlsZEdyYXBoKGZpeHR1cmVzKTtcbiAgICAgIGNvbnN0IGluc2VydGlvbk9yZGVyID0gdGhpcy5yZWxhdGlvbkdyYXBoLmdldEluc2VydGlvbk9yZGVyKCk7XG5cbiAgICAgIC8vIDIuIOyKpO2Cte2VoCBmaXh0dXJlIOuovOyggCDsspjrpqwgKG92ZXJyaWRlIOyytO2BrClcbiAgICAgIGZvciAoY29uc3QgZml4dHVyZUlkIG9mIGluc2VydGlvbk9yZGVyKSB7XG4gICAgICAgIGNvbnN0IGZpeHR1cmUgPSBmaXh0dXJlcy5maW5kKChmKSA9PiBmLmZpeHR1cmVJZCA9PT0gZml4dHVyZUlkKTtcbiAgICAgICAgaWYgKCFmaXh0dXJlKSBjb250aW51ZTtcblxuICAgICAgICBjb25zdCBoYXNUYXJnZXQgPSAhIWZpeHR1cmUudGFyZ2V0O1xuICAgICAgICBjb25zdCBoYXNVbmlxdWUgPSAhIWZpeHR1cmUudW5pcXVlO1xuICAgICAgICBjb25zdCBoYXNEdXBsaWNhdGUgPSBoYXNUYXJnZXQgfHwgaGFzVW5pcXVlO1xuXG4gICAgICAgIC8vIOykkeuzteydtCDsnojqs6Agb3ZlcnJpZGU9ZmFsc2Xsnbgg6rK97JqwOiDsiqTtgrVcbiAgICAgICAgaWYgKGhhc0R1cGxpY2F0ZSAmJiAhZml4dHVyZS5vdmVycmlkZSkge1xuICAgICAgICAgIC8vIOq4sOyhtCDroIjsvZTrk5wgSUQg7KCA7J6lICh1bmlxdWUg7Jqw7ISgLCDsl4bsnLzrqbQgdGFyZ2V0KVxuICAgICAgICAgIGNvbnN0IGV4aXN0aW5nSWQgPSBmaXh0dXJlLnVuaXF1ZT8uaWQgPz8gZml4dHVyZS50YXJnZXQ/LmlkO1xuICAgICAgICAgIGFzc2VydChleGlzdGluZ0lkKTtcbiAgICAgICAgICB0aGlzLnNraXBwZWRGaXh0dXJlcy5zZXQoZml4dHVyZUlkLCB7XG4gICAgICAgICAgICBlbnRpdHlJZDogZml4dHVyZS5lbnRpdHlJZCxcbiAgICAgICAgICAgIGV4aXN0aW5nSWQsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAhaXNUZXN0KCkgJiZcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgICBjaGFsay55ZWxsb3coXG4gICAgICAgICAgICAgICAgYFNraXBwZWQgJHtmaXh0dXJlLmVudGl0eUlkfSMke2ZpeHR1cmUuaWR9IChleGlzdGluZzogIyR7ZXhpc3RpbmdJZH0sIG92ZXJyaWRlOiBmYWxzZSlgLFxuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyAzLiDthYzsnbTruJTrs4QgZml4dHVyZSDqt7jro7ntmZQgKGluc2VydGlvbk9yZGVyIOyInOyEnCDquLDrsJgpXG4gICAgICBjb25zdCBmaXh0dXJlc0J5VGFibGUgPSBuZXcgTWFwPHN0cmluZywgRml4dHVyZVJlY29yZFtdPigpO1xuICAgICAgY29uc3QgdGFibGVPcmRlcjogc3RyaW5nW10gPSBbXTtcblxuICAgICAgZm9yIChjb25zdCBmaXh0dXJlSWQgb2YgaW5zZXJ0aW9uT3JkZXIpIHtcbiAgICAgICAgLy8g7Iqk7YK165CcIGZpeHR1cmUg7KCc7Jm4XG4gICAgICAgIGlmICh0aGlzLnNraXBwZWRGaXh0dXJlcy5oYXMoZml4dHVyZUlkKSkgY29udGludWU7XG5cbiAgICAgICAgY29uc3QgZml4dHVyZSA9IGZpeHR1cmVzLmZpbmQoKGYpID0+IGYuZml4dHVyZUlkID09PSBmaXh0dXJlSWQpO1xuICAgICAgICBpZiAoIWZpeHR1cmUpIGNvbnRpbnVlO1xuXG4gICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGZpeHR1cmUuZW50aXR5SWQpO1xuICAgICAgICBjb25zdCB0YWJsZU5hbWUgPSBlbnRpdHkudGFibGU7XG5cbiAgICAgICAgaWYgKCFmaXh0dXJlc0J5VGFibGUuaGFzKHRhYmxlTmFtZSkpIHtcbiAgICAgICAgICBmaXh0dXJlc0J5VGFibGUuc2V0KHRhYmxlTmFtZSwgW10pO1xuICAgICAgICAgIHRhYmxlT3JkZXIucHVzaCh0YWJsZU5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIGZpeHR1cmVzQnlUYWJsZS5nZXQodGFibGVOYW1lKT8ucHVzaChmaXh0dXJlKTtcbiAgICAgIH1cblxuICAgICAgYXdhaXQgZGIudHJhbnNhY3Rpb24oYXN5bmMgKHRyeCkgPT4ge1xuICAgICAgICBjb25zdCBpbnNlcnRlZElkc0J5VGFibGUgPSBuZXcgTWFwPHN0cmluZywgTWFwPHN0cmluZywgbnVtYmVyIHwgc3RyaW5nPj4oKTtcblxuICAgICAgICAvLyA0LiDthYzsnbTruJTrs4Qg66CI67Ko67OEIOyymOumrFxuICAgICAgICBmb3IgKGNvbnN0IHRhYmxlTmFtZSBvZiB0YWJsZU9yZGVyKSB7XG4gICAgICAgICAgY29uc3QgdGFibGVGaXh0dXJlcyA9IGZpeHR1cmVzQnlUYWJsZS5nZXQodGFibGVOYW1lKSA/PyBbXTtcbiAgICAgICAgICBjb25zdCBsZXZlbHMgPSB0aGlzLmdyb3VwRml4dHVyZXNCeUxldmVsKHRhYmxlRml4dHVyZXMpO1xuXG4gICAgICAgICAgZm9yIChjb25zdCBsZXZlbEZpeHR1cmVzIG9mIGxldmVscykge1xuICAgICAgICAgICAgLy8g7ZW064u5IOugiOuyqOydmCBmaXh0dXJl65OkIHJlZ2lzdGVyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGZpeHR1cmUgb2YgbGV2ZWxGaXh0dXJlcykge1xuICAgICAgICAgICAgICB0aGlzLnJlZ2lzdGVyRml4dHVyZShmaXh0dXJlLCBpbnNlcnRlZElkc0J5VGFibGUpO1xuICAgICAgICAgICAgICAhaXNUZXN0KCkgJiZcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgICAgICAgIGNoYWxrLmJsdWUoXG4gICAgICAgICAgICAgICAgICAgIGBSZWdpc3RlcmVkICR7Zml4dHVyZS5lbnRpdHlJZH0jJHtmaXh0dXJlLmlkfSR7Zml4dHVyZS5vdmVycmlkZSA/IGAgKG92ZXJyaWRlKWAgOiBcIlwifWAsXG4gICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHVwc2VydCDsi6Ttlokg7KCEIHV1aWQg66qp66GdIOyggOyepVxuICAgICAgICAgICAgY29uc3QgdGFibGUgPSB0aGlzLmJ1aWxkZXIuZ2V0VGFibGUodGFibGVOYW1lKTtcbiAgICAgICAgICAgIGNvbnN0IHV1aWRzID0gdGFibGUucm93cy5tYXAoKHJvdykgPT4gcm93LnV1aWQgYXMgc3RyaW5nKTtcblxuICAgICAgICAgICAgIWlzVGVzdCgpICYmXG4gICAgICAgICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgICAgIGNoYWxrLmJsdWUoXG4gICAgICAgICAgICAgICAgICBgVXBzZXJ0aW5nICR7dGFibGVOYW1lfSB3aXRoICR7dXVpZHMubGVuZ3RofSByb3dzIChsZXZlbCAke2xldmVscy5pbmRleE9mKGxldmVsRml4dHVyZXMpICsgMX0vJHtsZXZlbHMubGVuZ3RofSlgLFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zdCBpZHMgPSAoYXdhaXQgdGhpcy5idWlsZGVyLnVwc2VydChcbiAgICAgICAgICAgICAgdHJ4LFxuICAgICAgICAgICAgICB0YWJsZU5hbWUgYXMga2V5b2YgRGF0YWJhc2VTY2hlbWFFeHRlbmQsXG4gICAgICAgICAgICApKSBhcyAobnVtYmVyIHwgc3RyaW5nKVtdO1xuXG4gICAgICAgICAgICAvLyDsiJzshJwg6riw67CYIHV1aWQgLT4gaWQg66ek7ZWRXG4gICAgICAgICAgICAvLyBzZWxmLXJlZmVyZW5jZeqwgCDsl4bsnLzrr4DroZwg65Ox66GdIOyInOyEnCA9IOuwmO2ZmCDsiJzshJwg67O07J6lXG4gICAgICAgICAgICBpZiAodXVpZHMubGVuZ3RoID4gMCAmJiB1dWlkcy5sZW5ndGggPT09IGlkcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgY29uc3QgZXhpc3RpbmdNYXAgPVxuICAgICAgICAgICAgICAgIGluc2VydGVkSWRzQnlUYWJsZS5nZXQodGFibGVOYW1lKSA/PyBuZXcgTWFwPHN0cmluZywgbnVtYmVyIHwgc3RyaW5nPigpO1xuICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHV1aWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgZXhpc3RpbmdNYXAuc2V0KHV1aWRzW2ldLCBpZHNbaV0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGluc2VydGVkSWRzQnlUYWJsZS5zZXQodGFibGVOYW1lLCBleGlzdGluZ01hcCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHV1aWRzLmxlbmd0aCAhPT0gaWRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICAgICAgY2hhbGsueWVsbG93KFxuICAgICAgICAgICAgICAgICAgYFdhcm5pbmc6IHV1aWQgY291bnQgKCR7dXVpZHMubGVuZ3RofSkgIT0gaWQgY291bnQgKCR7aWRzLmxlbmd0aH0pIGZvciAke3RhYmxlTmFtZX1gLFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gNS4gTWFueVRvTWFueSDqtIDqs4Qg7LKY66asXG4gICAgICAgIGF3YWl0IHRoaXMucHJvY2Vzc01hbnlUb01hbnlSZWxhdGlvbnModHJ4LCBmaXh0dXJlcywgaW5zZXJ0ZWRJZHNCeVRhYmxlKTtcblxuICAgICAgICAvLyA2LiBQb3N0Z3JlU1FMIOyLnO2AgOyKpCDrpqzshYtcbiAgICAgICAgLy8gRml4dHVyZSDsgr3snoUg7ZuEIOqwgSDthYzsnbTruJTsnZggSUQg7Iuc7YCA7Iqk66W8IOy1nOuMgCBJRCDqsJLsnLzroZwg7JeF642w7J207Yq47ZWp64uI64ukLlxuICAgICAgICAvLyDsnbTroIfqsowg7ZWY7KeAIOyViuycvOuptCDri6TsnYwgSU5TRVJUIOyLnCBJROqwgCAyMDAw67KI64yA66GcIOyDneyEseuQoCDsiJgg7J6I7Iq164uI64ukLlxuICAgICAgICAhaXNUZXN0KCkgJiYgY29uc29sZS5sb2coY2hhbGsuYmx1ZShcIlJlc2V0dGluZyBzZXF1ZW5jZXMuLi5cIikpO1xuICAgICAgICBmb3IgKGNvbnN0IHRhYmxlTmFtZSBvZiB0YWJsZU9yZGVyKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIEVudGl0eeulvCDssL7slYTshJwgaWQg7YOA7J6FIO2ZleyduFxuICAgICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXRBbGxFbnRpdGllcygpLmZpbmQoXG4gICAgICAgICAgICAgIChlKSA9PiBlLnRhYmxlID09PSB0YWJsZU5hbWUgfHwgZS5pZC50b0xvd2VyQ2FzZSgpID09PSB0YWJsZU5hbWUsXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICBpZiAoZW50aXR5KSB7XG4gICAgICAgICAgICAgIGNvbnN0IGlkUHJvcCA9IGVudGl0eS5wcm9wcy5maW5kKChwKSA9PiBwLm5hbWUgPT09IFwiaWRcIik7XG4gICAgICAgICAgICAgIGNvbnN0IGlkVHlwZSA9IGlkUHJvcD8udHlwZTtcblxuICAgICAgICAgICAgICAvLyBpbnRlZ2VyL2JpZ0ludGVnZXLsnbTqsbDrgpgsIHN0cmluZ+ydtOyngOunjCBmaXh0dXJlU3RyYXRlZ3k9c2VxdWVuY2Xsnbgg6rK97Jqw7JeQ66eMIOumrOyFi+2VqeuLiOuLpFxuICAgICAgICAgICAgICBjb25zdCB1c2VzU2VxdWVuY2UgPVxuICAgICAgICAgICAgICAgIGlkVHlwZSA9PT0gXCJpbnRlZ2VyXCIgfHxcbiAgICAgICAgICAgICAgICBpZFR5cGUgPT09IFwiYmlnSW50ZWdlclwiIHx8XG4gICAgICAgICAgICAgICAgaWRQcm9wPy5jb25lPy5maXh0dXJlU3RyYXRlZ3kgPT09IFwic2VxdWVuY2VcIjtcblxuICAgICAgICAgICAgICBpZiAoIXVzZXNTZXF1ZW5jZSkge1xuICAgICAgICAgICAgICAgICFpc1Rlc3QoKSAmJlxuICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgICAgICAgICAgIGNoYWxrLmdyYXkoXG4gICAgICAgICAgICAgICAgICAgICAgYFNraXBwZWQgc2VxdWVuY2UgcmVzZXQgZm9yICR7dGFibGVOYW1lfSAoaWQgdHlwZTogJHtpZFR5cGUgfHwgXCJ1bmtub3duXCJ9KWAsXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIO2FjOydtOu4lOydmCDstZzrjIAgSUQg7KGw7ZqMIChzdHJpbmcg7YOA7J6F7J2AIOyIq+yekCDsupDsiqTtjIUg7ZWE7JqUKVxuICAgICAgICAgICAgY29uc3QgZW50aXR5MiA9IEVudGl0eU1hbmFnZXIuZ2V0QWxsRW50aXRpZXMoKS5maW5kKFxuICAgICAgICAgICAgICAoZSkgPT4gZS50YWJsZSA9PT0gdGFibGVOYW1lIHx8IGUuaWQudG9Mb3dlckNhc2UoKSA9PT0gdGFibGVOYW1lLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IGlkVHlwZTIgPSBlbnRpdHkyPy5wcm9wcy5maW5kKChwKSA9PiBwLm5hbWUgPT09IFwiaWRcIik/LnR5cGU7XG4gICAgICAgICAgICBjb25zdCBtYXhJZFJlc3VsdCA9XG4gICAgICAgICAgICAgIGlkVHlwZTIgPT09IFwic3RyaW5nXCJcbiAgICAgICAgICAgICAgICA/IGF3YWl0IHRyeFxuICAgICAgICAgICAgICAgICAgICAucmF3KGBTRUxFQ1QgTUFYKGlkOjpiaWdpbnQpIGFzIG1heF9pZCBGUk9NIFwiJHt0YWJsZU5hbWV9XCJgKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigocikgPT4gci5yb3dzWzBdKVxuICAgICAgICAgICAgICAgIDogYXdhaXQgdHJ4KHRhYmxlTmFtZSkubWF4KFwiaWQgYXMgbWF4X2lkXCIpLmZpcnN0KCk7XG4gICAgICAgICAgICBjb25zdCBtYXhJZCA9IG1heElkUmVzdWx0Py5tYXhfaWQ7XG5cbiAgICAgICAgICAgIGlmIChtYXhJZCAhPT0gbnVsbCAmJiBtYXhJZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgIC8vIOyLnO2AgOyKpOuqheydhCBwZ19nZXRfc2VyaWFsX3NlcXVlbmNl66GcIOyViOyghO2VmOqyjCDsobDtmoxcbiAgICAgICAgICAgICAgYXdhaXQgdHJ4LnJhdyhgU0VMRUNUIHNldHZhbChwZ19nZXRfc2VyaWFsX3NlcXVlbmNlKD8sICdpZCcpLCA/KWAsIFtcbiAgICAgICAgICAgICAgICB0YWJsZU5hbWUsXG4gICAgICAgICAgICAgICAgbWF4SWQsXG4gICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgICAhaXNUZXN0KCkgJiYgY29uc29sZS5sb2coY2hhbGsuZ3JlZW4oYFJlc2V0IHNlcXVlbmNlIGZvciAke3RhYmxlTmFtZX06ICR7bWF4SWR9YCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgLy8g7Iuc7YCA7Iqk6rCAIOyXhuuKlCDthYzsnbTruJQoam9pbiB0YWJsZSDrk7Ep7J2AIOustOyLnFxuICAgICAgICAgICAgIWlzVGVzdCgpICYmIGNvbnNvbGUubG9nKGNoYWxrLmdyYXkoYFNraXBwZWQgc2VxdWVuY2UgcmVzZXQgZm9yICR7dGFibGVOYW1lfWApKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyA3LiDqsrDqs7wg7IiY7KeRXG4gICAgICAgIGZvciAoY29uc3QgZml4dHVyZSBvZiBmaXh0dXJlcykge1xuICAgICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGZpeHR1cmUuZW50aXR5SWQpO1xuXG4gICAgICAgICAgLy8g7Iqk7YK165CcIGZpeHR1cmXripQg6riw7KG0IOugiOy9lOuTnCDsoJXrs7TroZwg6rKw6rO8IOy2lOqwgFxuICAgICAgICAgIGNvbnN0IHNraXBwZWQgPSB0aGlzLnNraXBwZWRGaXh0dXJlcy5nZXQoZml4dHVyZS5maXh0dXJlSWQpO1xuICAgICAgICAgIGlmIChza2lwcGVkKSB7XG4gICAgICAgICAgICByZXN1bHRzLnB1c2goe1xuICAgICAgICAgICAgICBlbnRpdHlJZDogZml4dHVyZS5lbnRpdHlJZCxcbiAgICAgICAgICAgICAgZGF0YTogYXdhaXQgdHJ4KGVudGl0eS50YWJsZSkud2hlcmUoXCJpZFwiLCBza2lwcGVkLmV4aXN0aW5nSWQpLmZpcnN0KCksXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHJlZiA9IHRoaXMuZml4dHVyZVJlZk1hcC5nZXQoZml4dHVyZS5maXh0dXJlSWQpO1xuICAgICAgICAgIGlmIChyZWYpIHtcbiAgICAgICAgICAgIGNvbnN0IHV1aWRUb0lkID0gaW5zZXJ0ZWRJZHNCeVRhYmxlLmdldChlbnRpdHkudGFibGUpO1xuICAgICAgICAgICAgY29uc3QgaW5zZXJ0ZWRJZCA9IHV1aWRUb0lkPy5nZXQocmVmLnV1aWQpO1xuXG4gICAgICAgICAgICBpZiAoaW5zZXJ0ZWRJZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgIHJlc3VsdHMucHVzaCh7XG4gICAgICAgICAgICAgICAgZW50aXR5SWQ6IGZpeHR1cmUuZW50aXR5SWQsXG4gICAgICAgICAgICAgICAgZGF0YTogYXdhaXQgdHJ4KGVudGl0eS50YWJsZSkud2hlcmUoXCJpZFwiLCBpbnNlcnRlZElkKS5maXJzdCgpLFxuICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAhaXNUZXN0KCkgJiZcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgICAgICAgIGNoYWxrLmdyZWVuKGBJbnNlcnRlZCBpbnRvICR7ZW50aXR5LnRhYmxlfTogIyR7Zml4dHVyZS5pZH0gLT4gIyR7aW5zZXJ0ZWRJZH1gKSxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGF3YWl0IGRiLmRlc3Ryb3koKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdW5pcXVlKHJlc3VsdHMsIChyKSA9PiBgJHtyLmVudGl0eUlkfSMke3IuZGF0YS5pZH1gKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaXh0dXJlUmVjb3Jk66W8IFVwc2VydEJ1aWxkZXLsl5Ag65Ox66GdXG4gICAqIEBwYXJhbSBpbnNlcnRlZElkc0J5VGFibGUg7J2066+4IHVwc2VydOuQnCDthYzsnbTruJTsnZggdXVpZOKGkmlkIOunpO2VkSAo66CI67Ko67OEIOyymOumrCDsi5wg7IKs7JqpKVxuICAgKi9cbiAgcHJpdmF0ZSByZWdpc3RlckZpeHR1cmUoXG4gICAgZml4dHVyZTogRml4dHVyZVJlY29yZCxcbiAgICBpbnNlcnRlZElkc0J5VGFibGU/OiBNYXA8c3RyaW5nLCBNYXA8c3RyaW5nLCBudW1iZXIgfCBzdHJpbmc+PixcbiAgKTogVUJSZWYge1xuICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGZpeHR1cmUuZW50aXR5SWQpO1xuICAgIGNvbnN0IHJvdzogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fTtcblxuICAgIC8vIE92ZXJyaWRlIOuqqOuTnCDtjJDri6g6IHRhcmdldCDrmJDripQgdW5pcXVl6rCAIOyeiOqzoCBvdmVycmlkZT10cnVl7J24IOqyveyasFxuICAgIGNvbnN0IGV4aXN0aW5nUmVjb3JkID0gZml4dHVyZS50YXJnZXQgPz8gZml4dHVyZS51bmlxdWU7XG4gICAgY29uc3QgaXNPdmVycmlkZU1vZGUgPSBmaXh0dXJlLm92ZXJyaWRlICYmIGV4aXN0aW5nUmVjb3JkO1xuXG4gICAgZm9yIChjb25zdCBbcHJvcE5hbWUsIGNvbHVtbl0gb2YgT2JqZWN0LmVudHJpZXMoZml4dHVyZS5jb2x1bW5zKSkge1xuICAgICAgY29uc3QgcHJvcCA9IGNvbHVtbi5wcm9wO1xuXG4gICAgICBpZiAoaXNWaXJ0dWFsUHJvcChwcm9wKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gR2VuZXJhdGVkIGNvbHVtbuydgCBJTlNFUlTsl5DshJwg7KCc7Jm4IChEQuqwgCDsnpDrj5kg7IOd7ISxKVxuICAgICAgaWYgKFwiZ2VuZXJhdGVkXCIgaW4gcHJvcCAmJiBwcm9wLmdlbmVyYXRlZCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gaWQg7LKY66asXG4gICAgICBpZiAocHJvcE5hbWUgPT09IFwiaWRcIikge1xuICAgICAgICBjb25zdCBpZFByb3AgPSBlbnRpdHkucHJvcHMuZmluZCgocCkgPT4gcC5uYW1lID09PSBcImlkXCIpO1xuICAgICAgICAvLyBwYXJlbnRJZCDsl5Tti7Dti7DsnZggaWTripQg67aA66qoIOyXlO2LsO2LsOydmCBGS+ydtOuvgOuhnCDsi5ztgIDsiqQg66+47IKs7JqpICjrqoXsi5zsoIHsnLzroZwg7Y+s7ZWoKVxuICAgICAgICBjb25zdCB1c2VzU2VxdWVuY2UgPVxuICAgICAgICAgICFlbnRpdHkucGFyZW50SWQgJiZcbiAgICAgICAgICAoaWRQcm9wPy50eXBlID09PSBcImludGVnZXJcIiB8fFxuICAgICAgICAgICAgaWRQcm9wPy50eXBlID09PSBcImJpZ0ludGVnZXJcIiB8fFxuICAgICAgICAgICAgaWRQcm9wPy5jb25lPy5maXh0dXJlU3RyYXRlZ3kgPT09IFwic2VxdWVuY2VcIik7XG5cbiAgICAgICAgaWYgKGlzT3ZlcnJpZGVNb2RlICYmIGV4aXN0aW5nUmVjb3JkKSB7XG4gICAgICAgICAgLy8gT3ZlcnJpZGU6IOq4sOyhtCDroIjsvZTrk5zsnZgg6rCSIOyCrOyaqSDihpIgVVBEQVRFXG4gICAgICAgICAgcm93W3Byb3BOYW1lXSA9IGV4aXN0aW5nUmVjb3JkLmNvbHVtbnNbcHJvcE5hbWVdPy52YWx1ZTtcbiAgICAgICAgfSBlbHNlIGlmICghdXNlc1NlcXVlbmNlKSB7XG4gICAgICAgICAgLy8gc3RyaW5nIFBLIOuYkOuKlCBwYXJlbnRJZCDsl5Tti7Dti7AgRks6IOyDneyEseuQnCBpZCDqsJLsnYQgSU5TRVJU7JeQIO2PrO2VqFxuICAgICAgICAgIHJvd1twcm9wTmFtZV0gPSBjb2x1bW4udmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgLy8gaW50ZWdlci9iaWdJbnRlZ2VyIFBLOiBEQiDsi5ztgIDsiqTsl5Ag66eh6rmAICjqsJIg7KCc7Jm4KVxuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzUmVsYXRpb25Qcm9wKHByb3ApKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBpc0JlbG9uZ3NUb09uZVJlbGF0aW9uUHJvcChwcm9wKSB8fFxuICAgICAgICAgIChpc09uZVRvT25lUmVsYXRpb25Qcm9wKHByb3ApICYmIHByb3AuaGFzSm9pbkNvbHVtbilcbiAgICAgICAgKSB7XG4gICAgICAgICAgY29uc3QgcmVsYXRlZElkID0gY29sdW1uLnZhbHVlIGFzIG51bWJlciB8IG51bGw7XG4gICAgICAgICAgaWYgKHJlbGF0ZWRJZCAhPT0gbnVsbCAmJiByZWxhdGVkSWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgY29uc3QgcmVsYXRlZEZpeHR1cmVJZCA9IGAke3Byb3Aud2l0aH0jJHtyZWxhdGVkSWR9YDtcblxuICAgICAgICAgICAgLy8g66i87KCAIHNraXDrkJwgZml4dHVyZeyduOyngCDtmZXsnbhcbiAgICAgICAgICAgIGNvbnN0IHNraXBwZWRFeGlzdGluZ0lkID0gdGhpcy5za2lwcGVkRml4dHVyZXMuZ2V0KHJlbGF0ZWRGaXh0dXJlSWQpPy5leGlzdGluZ0lkO1xuICAgICAgICAgICAgaWYgKHNraXBwZWRFeGlzdGluZ0lkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgLy8gc2tpcOuQnCBmaXh0dXJlIOKGkiB0YXJnZXQgRELsnZgg6riw7KG0IOugiOy9lOuTnCBpZCDsgqzsmqlcbiAgICAgICAgICAgICAgcm93W2Ake3Byb3BOYW1lfV9pZGBdID0gc2tpcHBlZEV4aXN0aW5nSWQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjb25zdCByZWxhdGVkUmVmID0gdGhpcy5maXh0dXJlUmVmTWFwLmdldChyZWxhdGVkRml4dHVyZUlkKTtcbiAgICAgICAgICAgICAgaWYgKHJlbGF0ZWRSZWYpIHtcbiAgICAgICAgICAgICAgICAvLyDsnbTrr7ggdXBzZXJ065CcIOqwmeydgCDthYzsnbTruJQgZml4dHVyZSDtmZXsnbhcbiAgICAgICAgICAgICAgICBjb25zdCByZWxhdGVkRW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQocHJvcC53aXRoKTtcbiAgICAgICAgICAgICAgICBjb25zdCByZWxhdGVkSW5zZXJ0ZWRJZHMgPSBpbnNlcnRlZElkc0J5VGFibGU/LmdldChyZWxhdGVkRW50aXR5LnRhYmxlKTtcbiAgICAgICAgICAgICAgICBjb25zdCBhY3R1YWxJZCA9IHJlbGF0ZWRJbnNlcnRlZElkcz8uZ2V0KHJlbGF0ZWRSZWYudXVpZCk7XG5cbiAgICAgICAgICAgICAgICBpZiAoYWN0dWFsSWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgLy8g7J2066+4IHVwc2VydOuQqCDihpIg7Iuk7KCcIElEIOyCrOyaqVxuICAgICAgICAgICAgICAgICAgcm93W2Ake3Byb3BOYW1lfV9pZGBdID0gYWN0dWFsSWQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIC8vIOyVhOyngSB1cHNlcnQg7JWI65CoIOKGkiBVQlJlZiDsgqzsmqlcbiAgICAgICAgICAgICAgICAgIHJvd1tgJHtwcm9wTmFtZX1faWRgXSA9IHJlbGF0ZWRSZWY7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIGZpeHR1cmVz7JeQIO2PrO2VqOuQmOyngCDslYrsnYAg66CI7L2U65OcIOKGkiBJRCDqt7jrjIDroZwg7IKs7JqpXG4gICAgICAgICAgICAgICAgcm93W2Ake3Byb3BOYW1lfV9pZGBdID0gcmVsYXRlZElkO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJvd1tgJHtwcm9wTmFtZX1faWRgXSA9IG51bGw7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIEhhc01hbnksIE1hbnlUb01hbnnripQg67OE64+EIOyymOumrFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8g7J2867CYIOy7rOufvFxuICAgICAgICByb3dbcHJvcE5hbWVdID0gdGhpcy5jb252ZXJ0Q29sdW1uVmFsdWUocHJvcCBhcyBFbnRpdHlQcm9wLCBjb2x1bW4udmFsdWUpO1xuICAgICAgfVxuICAgIH1cblxuICAgICFpc1Rlc3QoKSAmJlxuICAgICAgY29uc29sZS5sb2coY2hhbGsuYmx1ZShgUmVnaXN0ZXJpbmcgJHtlbnRpdHkudGFibGV9IC0gJHtpbnNwZWN0KHJvdywgZmFsc2UsIG51bGwsIHRydWUpfWApKTtcbiAgICBjb25zdCByZWYgPSB0aGlzLmJ1aWxkZXIucmVnaXN0ZXIoZW50aXR5LnRhYmxlLCByb3cpO1xuICAgIHRoaXMuZml4dHVyZVJlZk1hcC5zZXQoZml4dHVyZS5maXh0dXJlSWQsIHJlZik7XG5cbiAgICByZXR1cm4gcmVmO1xuICB9XG5cbiAgLyoqXG4gICAqIOy7rOufvCDqsJIg67OA7ZmYXG4gICAqL1xuICBwcml2YXRlIGNvbnZlcnRDb2x1bW5WYWx1ZShwcm9wOiBFbnRpdHlQcm9wLCB2YWx1ZTogdW5rbm93bik6IHVua25vd24ge1xuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBzd2l0Y2ggKHByb3AudHlwZSkge1xuICAgICAgY2FzZSBcImpzb25cIjpcbiAgICAgICAgLy8gVXBzZXJ0QnVpbGRlci5yZWdpc3RlcuyXkOyEnCBKU09OLnN0cmluZ2lmeSDsspjrpqztlZjrr4DroZwgb2JqZWN0IOq3uOuMgOuhnCDsoITri6xcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuXG4gICAgICBjYXNlIFwiZGF0ZVwiOlxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiIHx8IHR5cGVvZiB2YWx1ZSA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgIHJldHVybiBuZXcgRGF0ZSh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBwcm9jZXNzTWFueVRvTWFueVJlbGF0aW9ucyhcbiAgICB0cng6IEtuZXguVHJhbnNhY3Rpb24sXG4gICAgZml4dHVyZXM6IEZpeHR1cmVSZWNvcmRbXSxcbiAgICBpbnNlcnRlZElkc0J5VGFibGU6IE1hcDxzdHJpbmcsIE1hcDxzdHJpbmcsIG51bWJlciB8IHN0cmluZz4+LFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBmb3IgKGNvbnN0IGZpeHR1cmUgb2YgZml4dHVyZXMpIHtcbiAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGZpeHR1cmUuZW50aXR5SWQpO1xuICAgICAgY29uc3Qgc291cmNlUmVmID0gdGhpcy5maXh0dXJlUmVmTWFwLmdldChmaXh0dXJlLmZpeHR1cmVJZCk7XG5cbiAgICAgIGlmICghc291cmNlUmVmKSBjb250aW51ZTtcblxuICAgICAgY29uc3Qgc291cmNlVXVpZFRvSWQgPSBpbnNlcnRlZElkc0J5VGFibGUuZ2V0KGVudGl0eS50YWJsZSk7XG4gICAgICBjb25zdCBzb3VyY2VJZCA9IHNvdXJjZVV1aWRUb0lkPy5nZXQoc291cmNlUmVmLnV1aWQpO1xuXG4gICAgICBpZiAoc291cmNlSWQgPT09IHVuZGVmaW5lZCkgY29udGludWU7XG5cbiAgICAgIGZvciAoY29uc3QgWywgY29sdW1uXSBvZiBPYmplY3QuZW50cmllcyhmaXh0dXJlLmNvbHVtbnMpKSB7XG4gICAgICAgIGNvbnN0IHByb3AgPSBjb2x1bW4ucHJvcDtcblxuICAgICAgICBpZiAoaXNNYW55VG9NYW55UmVsYXRpb25Qcm9wKHByb3ApICYmIEFycmF5LmlzQXJyYXkoY29sdW1uLnZhbHVlKSkge1xuICAgICAgICAgIC8vIOyEoO2DneuQmOyngCDslYrsnYAgTWFueVRvTWFueSDqtIDqs4TripQg7KCA7J6l7ZWY7KeAIOyViuydjFxuICAgICAgICAgIGNvbnN0IHRhcmdldFRhYmxlID0gRW50aXR5TWFuYWdlci5nZXQocHJvcC53aXRoKTtcbiAgICAgICAgICBpZiAoIXRoaXMuYnVpbGRlci5oYXNUYWJsZSh0YXJnZXRUYWJsZS50YWJsZSkpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgY29uc3QgcmVsYXRlZElkcyA9IGNvbHVtbi52YWx1ZSBhcyBudW1iZXJbXTtcbiAgICAgICAgICBpZiAocmVsYXRlZElkcy5sZW5ndGggPT09IDApIGNvbnRpbnVlO1xuXG4gICAgICAgICAgY29uc3Qgam9pblRhYmxlID0gcHJvcC5qb2luVGFibGU7XG4gICAgICAgICAgY29uc3QgcmVsYXRlZEVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KHByb3Aud2l0aCk7XG5cbiAgICAgICAgICBjb25zdCBzb3VyY2VDb2x1bW4gPSBgJHtpbmZsZWN0aW9uLnNpbmd1bGFyaXplKGVudGl0eS50YWJsZSl9X2lkYDtcbiAgICAgICAgICBjb25zdCB0YXJnZXRDb2x1bW4gPSBgJHtpbmZsZWN0aW9uLnNpbmd1bGFyaXplKHJlbGF0ZWRFbnRpdHkudGFibGUpfV9pZGA7XG5cbiAgICAgICAgICBmb3IgKGNvbnN0IHJlbGF0ZWRJZCBvZiByZWxhdGVkSWRzKSB7XG4gICAgICAgICAgICBjb25zdCByZWxhdGVkRml4dHVyZUlkID0gYCR7cHJvcC53aXRofSMke3JlbGF0ZWRJZH1gO1xuICAgICAgICAgICAgY29uc3QgcmVsYXRlZFJlZiA9IHRoaXMuZml4dHVyZVJlZk1hcC5nZXQocmVsYXRlZEZpeHR1cmVJZCk7XG5cbiAgICAgICAgICAgIGxldCB0YXJnZXRJZDogbnVtYmVyIHwgc3RyaW5nO1xuXG4gICAgICAgICAgICBpZiAocmVsYXRlZFJlZikge1xuICAgICAgICAgICAgICBjb25zdCByZWxhdGVkVXVpZFRvSWQgPSBpbnNlcnRlZElkc0J5VGFibGUuZ2V0KHJlbGF0ZWRFbnRpdHkudGFibGUpO1xuICAgICAgICAgICAgICBjb25zdCByZXNvbHZlZElkID0gcmVsYXRlZFV1aWRUb0lkPy5nZXQocmVsYXRlZFJlZi51dWlkKTtcblxuICAgICAgICAgICAgICBpZiAocmVzb2x2ZWRJZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICAgICAgICAgYFJlbGF0ZWQgZml4dHVyZSAke3JlbGF0ZWRGaXh0dXJlSWR9IG5vdCBmb3VuZCBpbiBpbnNlcnRlZElkcywgc2tpcHBpbmdgLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgdGFyZ2V0SWQgPSByZXNvbHZlZElkO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGFyZ2V0SWQgPSByZWxhdGVkSWQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEpvaW5UYWJsZeyXkCDsgr3snoVcbiAgICAgICAgICAgIGNvbnN0IFtmb3VuZF0gPSBhd2FpdCB0cngoam9pblRhYmxlKVxuICAgICAgICAgICAgICAud2hlcmUoe1xuICAgICAgICAgICAgICAgIFtzb3VyY2VDb2x1bW5dOiBzb3VyY2VJZCxcbiAgICAgICAgICAgICAgICBbdGFyZ2V0Q29sdW1uXTogdGFyZ2V0SWQsXG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgIC5saW1pdCgxKTtcblxuICAgICAgICAgICAgaWYgKCFmb3VuZCkge1xuICAgICAgICAgICAgICBhd2FpdCB0cngoam9pblRhYmxlKS5pbnNlcnQoe1xuICAgICAgICAgICAgICAgIFtzb3VyY2VDb2x1bW5dOiBzb3VyY2VJZCxcbiAgICAgICAgICAgICAgICBbdGFyZ2V0Q29sdW1uXTogdGFyZ2V0SWQsXG4gICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICFpc1Rlc3QoKSAmJlxuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgICAgICAgY2hhbGsuZ3JlZW4oXG4gICAgICAgICAgICAgICAgICAgIGBJbnNlcnRlZCBpbnRvICR7am9pblRhYmxlfTogJHtlbnRpdHkudGFibGV9KCR7c291cmNlSWR9KSAtICR7cmVsYXRlZEVudGl0eS50YWJsZX0oJHt0YXJnZXRJZH0pYCxcbiAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICog6rCZ7J2AIO2FjOydtOu4lCDrgrQgZml4dHVyZeuTpOydhCBzZWxmLXJlZmVyZW5jZSDroIjrsqjrs4TroZwg67aE7ZWgXG4gICAqIC0gc2VsZi1yZWZlcmVuY2XqsIAg7JeG64qUIGZpeHR1cmXrk6Q6IExldmVsIDBcbiAgICogLSBMZXZlbCAw7J2EIOywuOyhsO2VmOuKlCBmaXh0dXJl65OkOiBMZXZlbCAxXG4gICAqIC0g67CY67O1XG4gICAqXG4gICAqIFVwc2VydEJ1aWxkZXLqsIAgc2VsZi1yZWZlcmVuY2XqsIAg7J6I7Jy866m0IGJ1aWxkSW5zZXJ0TGV2ZWxzKCnroZwg7J6s7KCV66Cs7ZWY7JesXG4gICAqIOuTseuhnSDsiJzshJzsmYAg67CY7ZmYIOyInOyEnOqwgCDri6zrnbzsp4gg7IiYIOyeiOyKteuLiOuLpC5cbiAgICog7J2066W8IOuwqeyngO2VmOq4sCDsnITtlbQgRml4dHVyZU1hbmFnZXLqsIAg66CI67Ko67OE66GcIOuCmOuIoOyEnCDsspjrpqztlanri4jri6QuXG4gICAqL1xuICBwcml2YXRlIGdyb3VwRml4dHVyZXNCeUxldmVsKGZpeHR1cmVzOiBGaXh0dXJlUmVjb3JkW10pOiBGaXh0dXJlUmVjb3JkW11bXSB7XG4gICAgaWYgKGZpeHR1cmVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGZpeHR1cmVzWzBdLmVudGl0eUlkKTtcblxuICAgIC8vIHNlbGYtcmVmZXJlbmNlIHJlbGF0aW9uIHByb3Ag7LC+6riwXG4gICAgY29uc3Qgc2VsZlJlZlByb3BzID0gZW50aXR5LnByb3BzLmZpbHRlcihcbiAgICAgIChwKTogcCBpcyBCZWxvbmdzVG9PbmVSZWxhdGlvblByb3AgfCBPbmVUb09uZVJlbGF0aW9uUHJvcCA9PlxuICAgICAgICBpc1JlbGF0aW9uUHJvcChwKSAmJlxuICAgICAgICAoaXNCZWxvbmdzVG9PbmVSZWxhdGlvblByb3AocCkgfHwgKGlzT25lVG9PbmVSZWxhdGlvblByb3AocCkgJiYgcC5oYXNKb2luQ29sdW1uKSkgJiZcbiAgICAgICAgcC53aXRoID09PSBlbnRpdHkuaWQsXG4gICAgKTtcblxuICAgIGlmIChzZWxmUmVmUHJvcHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAvLyBzZWxmLXJlZmVyZW5jZSDsl4bsnYwg4oaSIOuLqOydvCDroIjrsqhcbiAgICAgIHJldHVybiBbZml4dHVyZXNdO1xuICAgIH1cblxuICAgIC8vIOugiOuyqOuzhCDrtoTtlaAgKHRvcG9sb2dpY2FsIHNvcnQpXG4gICAgY29uc3QgbGV2ZWxzOiBGaXh0dXJlUmVjb3JkW11bXSA9IFtdO1xuICAgIGNvbnN0IHJlbWFpbmluZyA9IG5ldyBTZXQoZml4dHVyZXMubWFwKChmKSA9PiBmLmZpeHR1cmVJZCkpO1xuICAgIGNvbnN0IHByb2Nlc3NlZCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gICAgd2hpbGUgKHJlbWFpbmluZy5zaXplID4gMCkge1xuICAgICAgY29uc3QgY3VycmVudExldmVsOiBGaXh0dXJlUmVjb3JkW10gPSBbXTtcblxuICAgICAgZm9yIChjb25zdCBmaXh0dXJlIG9mIGZpeHR1cmVzKSB7XG4gICAgICAgIGlmICghcmVtYWluaW5nLmhhcyhmaXh0dXJlLmZpeHR1cmVJZCkpIGNvbnRpbnVlO1xuXG4gICAgICAgIC8vIHNlbGYtcmVmZXJlbmNl6rCAIOuqqOuRkCDsnbTrr7gg7LKY66as65CQ6rGw64KYIG51bGzsnbgg6rK97JqwXG4gICAgICAgIGNvbnN0IGNhblByb2Nlc3MgPSBzZWxmUmVmUHJvcHMuZXZlcnkoKHByb3ApID0+IHtcbiAgICAgICAgICBjb25zdCByZWZJZCA9IGZpeHR1cmUuY29sdW1uc1twcm9wLm5hbWVdPy52YWx1ZSBhcyBudW1iZXIgfCBudWxsO1xuICAgICAgICAgIGlmIChyZWZJZCA9PT0gbnVsbCB8fCByZWZJZCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICBjb25zdCByZWZGaXh0dXJlSWQgPSBgJHtwcm9wLndpdGh9IyR7cmVmSWR9YDtcbiAgICAgICAgICAvLyDsnbTrr7gg7LKY66as65CQ6rGw64KYLCDtmITsnqwgZml4dHVyZXPsl5Ag7Y+s7ZWo65CY7KeAIOyViuydgCDqsr3smrAgKOyZuOu2gCDssLjsobApXG4gICAgICAgICAgcmV0dXJuIHByb2Nlc3NlZC5oYXMocmVmRml4dHVyZUlkKSB8fCAhcmVtYWluaW5nLmhhcyhyZWZGaXh0dXJlSWQpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoY2FuUHJvY2Vzcykge1xuICAgICAgICAgIGN1cnJlbnRMZXZlbC5wdXNoKGZpeHR1cmUpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjdXJyZW50TGV2ZWwubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGNvbnN0IHJlbWFpbmluZ0lkcyA9IEFycmF5LmZyb20ocmVtYWluaW5nKS5qb2luKFwiLCBcIik7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgQ2lyY3VsYXIgc2VsZi1yZWZlcmVuY2UgZGV0ZWN0ZWQgaW4gJHtlbnRpdHkudGFibGV9LiBSZW1haW5pbmcgZml4dHVyZXM6ICR7cmVtYWluaW5nSWRzfWAsXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGZvciAoY29uc3QgZml4dHVyZSBvZiBjdXJyZW50TGV2ZWwpIHtcbiAgICAgICAgcmVtYWluaW5nLmRlbGV0ZShmaXh0dXJlLmZpeHR1cmVJZCk7XG4gICAgICAgIHByb2Nlc3NlZC5hZGQoZml4dHVyZS5maXh0dXJlSWQpO1xuICAgICAgfVxuXG4gICAgICBsZXZlbHMucHVzaChjdXJyZW50TGV2ZWwpO1xuICAgIH1cblxuICAgIHJldHVybiBsZXZlbHM7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNoZWNrVW5pcXVlVmlvbGF0aW9uKGRiOiBLbmV4LCBlbnRpdHk6IEVudGl0eSwgZml4dHVyZTogRml4dHVyZVJlY29yZCkge1xuICAgIGNvbnN0IF91bmlxdWVJbmRleGVzID0gZW50aXR5LmluZGV4ZXM/LmZpbHRlcigoaSkgPT4gaS50eXBlID09PSBcInVuaXF1ZVwiKSA/PyBbXTtcblxuICAgIGNvbnN0IHVuaXF1ZUluZGV4ZXMgPSBfdW5pcXVlSW5kZXhlcy5maWx0ZXIoKGluZGV4KSA9PlxuICAgICAgaW5kZXguY29sdW1ucy5ldmVyeSgoY29sdW1uKSA9PiAhY29sdW1uLm5hbWUuc3RhcnRzV2l0aChgJHtlbnRpdHkudGFibGV9X19gKSksXG4gICAgKTtcbiAgICBpZiAodW5pcXVlSW5kZXhlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGxldCB1bmlxdWVRdWVyeSA9IGRiKGVudGl0eS50YWJsZSk7XG4gICAgbGV0IGhhc0NvbmRpdGlvbiA9IGZhbHNlO1xuXG4gICAgZm9yIChjb25zdCBpbmRleCBvZiB1bmlxdWVJbmRleGVzKSB7XG4gICAgICAvLyDsu6zrn7wg7KSRIO2VmOuCmOudvOuPhCBudWxs7J2066m0IOycoOuLiO2BrCDsoJzslb3snYQg7JyE67CY7ZWY7KeAIOyViuq4sCDrlYzrrLjsl5Ag7ZW064u5IOyduOuNseyKpOuKlCDrrLTsi5xcbiAgICAgIGNvbnN0IGNvbnRhaW5zTnVsbCA9IGluZGV4LmNvbHVtbnMuc29tZSgoY29sdW1uKSA9PiB7XG4gICAgICAgIGNvbnN0IGZpZWxkID0gY29sdW1uLm5hbWUucmVwbGFjZSgvX2lkJC8sIFwiXCIpO1xuICAgICAgICByZXR1cm4gZml4dHVyZS5jb2x1bW5zW2ZpZWxkXT8udmFsdWUgPT09IG51bGw7XG4gICAgICB9KTtcbiAgICAgIGlmIChjb250YWluc051bGwpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIHVuaXF1ZVF1ZXJ5ID0gdW5pcXVlUXVlcnkub3JXaGVyZSgocWIpID0+IHtcbiAgICAgICAgZm9yIChjb25zdCBjb2x1bW4gb2YgaW5kZXguY29sdW1ucykge1xuICAgICAgICAgIGNvbnN0IGZpZWxkID0gY29sdW1uLm5hbWUucmVwbGFjZSgvX2lkJC8sIFwiXCIpO1xuXG4gICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZml4dHVyZS5jb2x1bW5zW2ZpZWxkXT8udmFsdWUpKSB7XG4gICAgICAgICAgICBxYi53aGVyZUluKGNvbHVtbi5uYW1lLCBmaXh0dXJlLmNvbHVtbnNbZmllbGRdLnZhbHVlKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcWIuYW5kV2hlcmUoY29sdW1uLm5hbWUsIGZpeHR1cmUuY29sdW1uc1tmaWVsZF0/LnZhbHVlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgaGFzQ29uZGl0aW9uID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAoIWhhc0NvbmRpdGlvbikge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgY29uc3QgW3VuaXF1ZUZvdW5kXSA9IGF3YWl0IHVuaXF1ZVF1ZXJ5O1xuICAgIHJldHVybiB1bmlxdWVGb3VuZDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgY2hlY2tEdXBsaWNhdGVCeUNvbHVtbnMoXG4gICAgZGI6IEtuZXgsXG4gICAgZW50aXR5OiBFbnRpdHksXG4gICAgZml4dHVyZTogRml4dHVyZVJlY29yZCxcbiAgICBjb2x1bW5zOiBzdHJpbmdbXSxcbiAgKSB7XG4gICAgaWYgKGNvbHVtbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCB3aGVyZUNsYXVzZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fTtcblxuICAgIGZvciAoY29uc3QgY29sdW1uIG9mIGNvbHVtbnMpIHtcbiAgICAgIC8vIHJlbGF0aW9uIO2VhOuTnOyduCDqsr3smrAgX2lkIOu2meydtOq4sFxuICAgICAgY29uc3QgcHJvcCA9IGVudGl0eS5wcm9wcy5maW5kKChwKSA9PiBwLm5hbWUgPT09IGNvbHVtbik7XG4gICAgICBjb25zdCBkYkNvbHVtbiA9IHByb3AgJiYgaXNSZWxhdGlvblByb3AocHJvcCkgPyBgJHtjb2x1bW59X2lkYCA6IGNvbHVtbjtcbiAgICAgIGNvbnN0IHZhbHVlID0gZml4dHVyZS5jb2x1bW5zW2NvbHVtbl0/LnZhbHVlO1xuXG4gICAgICAvLyBudWxsIOqwkuydtCDtj6ztlajrkJwg6rK97JqwIOykkeuztSDtmZXsnbgg7Iqk7YK1XG4gICAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cblxuICAgICAgd2hlcmVDbGF1c2VbZGJDb2x1bW5dID0gdmFsdWU7XG4gICAgfVxuXG4gICAgY29uc3QgW2ZvdW5kXSA9IGF3YWl0IGRiKGVudGl0eS50YWJsZSkud2hlcmUod2hlcmVDbGF1c2UpLmxpbWl0KDEpO1xuICAgIHJldHVybiBmb3VuZDtcbiAgfVxuXG4gIGFzeW5jIGFkZEZpeHR1cmVMb2FkZXIoY29kZTogc3RyaW5nKSB7XG4gICAgY29uc3QgcGF0aCA9IGAke1NvbmFtdS5hcGlSb290UGF0aH0vc3JjL3Rlc3RpbmcvZml4dHVyZS50c2A7XG4gICAgY29uc3QgY29udGVudCA9IHJlYWRGaWxlU3luYyhwYXRoKS50b1N0cmluZygpO1xuXG4gICAgY29uc3QgZml4dHVyZUxvYWRlclN0YXJ0ID0gY29udGVudC5pbmRleE9mKFwiY29uc3QgZml4dHVyZUxvYWRlciA9IHtcIik7XG4gICAgY29uc3QgZml4dHVyZUxvYWRlckVuZCA9IGNvbnRlbnQuaW5kZXhPZihcIn07XCIsIGZpeHR1cmVMb2FkZXJTdGFydCk7XG5cbiAgICBpZiAoZml4dHVyZUxvYWRlclN0YXJ0ICE9PSAtMSAmJiBmaXh0dXJlTG9hZGVyRW5kICE9PSAtMSkge1xuICAgICAgY29uc3QgbmV3Q29udGVudCA9IGAke2NvbnRlbnQuc2xpY2UoMCwgZml4dHVyZUxvYWRlckVuZCl9ICAke2NvZGV9XFxuJHtjb250ZW50LnNsaWNlKGZpeHR1cmVMb2FkZXJFbmQpfWA7XG5cbiAgICAgIHdyaXRlRmlsZVN5bmMocGF0aCwgbmV3Q29udGVudCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkZhaWxlZCB0byBmaW5kIGZpeHR1cmVMb2FkZXIgaW4gZml4dHVyZS50c1wiKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IEZpeHR1cmVNYW5hZ2VyID0gbmV3IEZpeHR1cmVNYW5hZ2VyQ2xhc3MoKTtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Y0FVdUM7a0JBQ1k7WUFFRztzQkFDSztzQkFHRjthQVFqQztrQkFVcUI7dUJBQ0s7Q0FTckMsc0JBQWIsTUFBaUM7RUFDL0IsQUFBUSxPQUFvQjtFQUM1QixJQUFJLElBQUksS0FBVztBQUNqQixRQUFLLE9BQU87O0VBRWQsSUFBSSxNQUFZO0FBQ2QsT0FBSSxLQUFLLFNBQVMsTUFBTTtBQUN0QixVQUFNLElBQUksTUFBTSwwQ0FBMEM7O0FBRTVELFVBQU8sS0FBSzs7RUFHZCxBQUFRLE9BQW9CO0VBQzVCLElBQUksSUFBSSxLQUFXO0FBQ2pCLFFBQUssT0FBTzs7RUFFZCxJQUFJLE1BQVk7QUFDZCxPQUFJLEtBQUssU0FBUyxNQUFNO0FBQ3RCLFVBQU0sSUFBSSxNQUFNLDBDQUEwQzs7QUFFNUQsVUFBTyxLQUFLOztFQUVkLG1CQUFvQztFQUVwQyxBQUFRLGdCQUFnQixJQUFJLGVBQWU7RUFHM0MsQUFBUSxVQUF5QixJQUFJLGVBQWU7RUFDcEQsQUFBUSxnQkFBb0MsSUFBSSxLQUFLO0VBQ3JELEFBQVEsa0JBQ04sSUFBSSxLQUFLO0VBRVgsT0FBTztBQUNMLE9BQUksS0FBSyxTQUFTLE1BQU07QUFDdEI7O0FBRUYsT0FBSSxPQUFPLFNBQVMsUUFBUSxPQUFPLFNBQVMsbUJBQW1CO0lBQzdELE1BQU0s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
|
|
617
|
+
|
|
618
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZml4dHVyZS1tYW5hZ2VyLmpzIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0aW5nL2ZpeHR1cmUtbWFuYWdlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgYXNzZXJ0IGZyb20gXCJhc3NlcnRcIjtcbmltcG9ydCB7IGV4ZWNTeW5jIH0gZnJvbSBcImNoaWxkX3Byb2Nlc3NcIjtcbmltcG9ydCB7IHJlYWRGaWxlU3luYywgd3JpdGVGaWxlU3luYyB9IGZyb20gXCJmc1wiO1xuaW1wb3J0IHsgaW5zcGVjdCB9IGZyb20gXCJ1dGlsXCI7XG5cbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIjtcbmltcG9ydCBpbmZsZWN0aW9uIGZyb20gXCJpbmZsZWN0aW9uXCI7XG5pbXBvcnQgeyB0eXBlIEtuZXggfSBmcm9tIFwia25leFwiO1xuaW1wb3J0IHsgdW5pcXVlIH0gZnJvbSBcInJhZGFzaGlcIjtcblxuaW1wb3J0IHsgU29uYW11IH0gZnJvbSBcIi4uL2FwaS9zb25hbXVcIjtcbmltcG9ydCB7IEJhc2VNb2RlbCB9IGZyb20gXCIuLi9kYXRhYmFzZS9iYXNlLW1vZGVsXCI7XG5pbXBvcnQgeyB0eXBlIFNvbmFtdURCQ29uZmlnIH0gZnJvbSBcIi4uL2RhdGFiYXNlL2RiXCI7XG5pbXBvcnQgeyBjcmVhdGVLbmV4SW5zdGFuY2UgfSBmcm9tIFwiLi4vZGF0YWJhc2Uva25leFwiO1xuaW1wb3J0IHsgVXBzZXJ0QnVpbGRlciB9IGZyb20gXCIuLi9kYXRhYmFzZS91cHNlcnQtYnVpbGRlclwiO1xuaW1wb3J0IHsgdHlwZSBVQlJlZiB9IGZyb20gXCIuLi9kYXRhYmFzZS91cHNlcnQtYnVpbGRlclwiO1xuaW1wb3J0IHsgdHlwZSBFbnRpdHkgfSBmcm9tIFwiLi4vZW50aXR5L2VudGl0eVwiO1xuaW1wb3J0IHsgRW50aXR5TWFuYWdlciB9IGZyb20gXCIuLi9lbnRpdHkvZW50aXR5LW1hbmFnZXJcIjtcbmltcG9ydCB7XG4gIGlzQmVsb25nc1RvT25lUmVsYXRpb25Qcm9wLFxuICBpc0hhc01hbnlSZWxhdGlvblByb3AsXG4gIGlzTWFueVRvTWFueVJlbGF0aW9uUHJvcCxcbiAgaXNPbmVUb09uZVJlbGF0aW9uUHJvcCxcbiAgaXNSZWxhdGlvblByb3AsXG4gIGlzVmlydHVhbFByb3AsXG59IGZyb20gXCIuLi90eXBlcy90eXBlc1wiO1xuaW1wb3J0IHtcbiAgdHlwZSBCZWxvbmdzVG9PbmVSZWxhdGlvblByb3AsXG4gIHR5cGUgRGF0YWJhc2VTY2hlbWFFeHRlbmQsXG4gIHR5cGUgRW50aXR5UHJvcCxcbiAgdHlwZSBGaXh0dXJlSW1wb3J0UmVzdWx0LFxuICB0eXBlIEZpeHR1cmVSZWNvcmQsXG4gIHR5cGUgRml4dHVyZVNlYXJjaE9wdGlvbnMsXG4gIHR5cGUgT25lVG9PbmVSZWxhdGlvblByb3AsXG59IGZyb20gXCIuLi90eXBlcy90eXBlc1wiO1xuaW1wb3J0IHsgaXNUZXN0IH0gZnJvbSBcIi4uL3V0aWxzL2NvbnRyb2xsZXJcIjtcbmltcG9ydCB7IFJlbGF0aW9uR3JhcGggfSBmcm9tIFwiLi9fcmVsYXRpb24tZ3JhcGhcIjtcblxuLyoqIOyCrOyaqeyekCDsp4DsoJUg7KSR67O1IO2ZleyduCDsu6zrn7wgKGVudGl0eUlk67OE66GcIOyngOyglSkgKi9cbmV4cG9ydCBpbnRlcmZhY2UgRHVwbGljYXRlQ2hlY2tPcHRpb25zIHtcbiAgY29sdW1ucz86IHtcbiAgICBbZW50aXR5SWQ6IHN0cmluZ106IHN0cmluZ1tdO1xuICB9O1xufVxuXG5leHBvcnQgY2xhc3MgRml4dHVyZU1hbmFnZXJDbGFzcyB7XG4gIHByaXZhdGUgX3RkYjogS25leCB8IG51bGwgPSBudWxsO1xuICBzZXQgdGRiKHRkYjogS25leCkge1xuICAgIHRoaXMuX3RkYiA9IHRkYjtcbiAgfVxuICBnZXQgdGRiKCk6IEtuZXgge1xuICAgIGlmICh0aGlzLl90ZGIgPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkZpeHR1cmVNYW5hZ2VyIGhhcyBub3QgYmVlbiBpbml0aWFsaXplZFwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3RkYjtcbiAgfVxuXG4gIHByaXZhdGUgX2ZkYjogS25leCB8IG51bGwgPSBudWxsO1xuICBzZXQgZmRiKGZkYjogS25leCkge1xuICAgIHRoaXMuX2ZkYiA9IGZkYjtcbiAgfVxuICBnZXQgZmRiKCk6IEtuZXgge1xuICAgIGlmICh0aGlzLl9mZGIgPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkZpeHR1cmVNYW5hZ2VyIGhhcyBub3QgYmVlbiBpbml0aWFsaXplZFwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2ZkYjtcbiAgfVxuICBjYWNoZWRUYWJsZU5hbWVzOiBzdHJpbmdbXSB8IG51bGwgPSBudWxsO1xuXG4gIHByaXZhdGUgcmVsYXRpb25HcmFwaCA9IG5ldyBSZWxhdGlvbkdyYXBoKCk7XG5cbiAgLy8gVXBzZXJ0QnVpbGRlciDquLDrsJggaW1wb3J066W8IOychO2VnCDsg4Htg5xcbiAgcHJpdmF0ZSBidWlsZGVyOiBVcHNlcnRCdWlsZGVyID0gbmV3IFVwc2VydEJ1aWxkZXIoKTtcbiAgcHJpdmF0ZSBmaXh0dXJlUmVmTWFwOiBNYXA8c3RyaW5nLCBVQlJlZj4gPSBuZXcgTWFwKCk7XG4gIHByaXZhdGUgc2tpcHBlZEZpeHR1cmVzOiBNYXA8c3RyaW5nLCB7IGVudGl0eUlkOiBzdHJpbmc7IGV4aXN0aW5nSWQ6IG51bWJlciB8IHN0cmluZyB9PiA9XG4gICAgbmV3IE1hcCgpO1xuXG4gIGluaXQoKSB7XG4gICAgaWYgKHRoaXMuX3RkYiAhPT0gbnVsbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoU29uYW11LmRiQ29uZmlnLnRlc3QgJiYgU29uYW11LmRiQ29uZmlnLnByb2R1Y3Rpb24pIHtcbiAgICAgIGNvbnN0IHRDb25uID0gU29uYW11LmRiQ29uZmlnLnRlc3QuY29ubmVjdGlvbiBhcyBLbmV4LkNvbm5lY3Rpb25Db25maWcgJiB7XG4gICAgICAgIHBvcnQ/OiBudW1iZXI7XG4gICAgICB9O1xuICAgICAgY29uc3QgcENvbm4gPSBTb25hbXUuZGJDb25maWcucHJvZHVjdGlvbi5jb25uZWN0aW9uIGFzIEtuZXguQ29ubmVjdGlvbkNvbmZpZyAmIHtcbiAgICAgICAgcG9ydD86IG51bWJlcjtcbiAgICAgIH07XG4gICAgICBpZiAoXG4gICAgICAgIGAke3RDb25uLmhvc3QgPz8gXCJsb2NhbGhvc3RcIn06JHt0Q29ubi5wb3J0ID8/IDU0MzJ9LyR7dENvbm4uZGF0YWJhc2V9YCA9PT1cbiAgICAgICAgYCR7cENvbm4uaG9zdCA/PyBcImxvY2FsaG9zdFwifToke3BDb25uLnBvcnQgPz8gNTQzMn0vJHtwQ29ubi5kYXRhYmFzZX1gXG4gICAgICApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGDthYzsiqTtirhEQuyZgCDtlITroZzrjZXshZhEQuyXkCDrj5nsnbztlZwg642w7J207YSw67Kg7J207Iqk6rCAIOyCrOyaqeuQmOyXiOyKteuLiOuLpC5gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLnRkYiA9IGNyZWF0ZUtuZXhJbnN0YW5jZShTb25hbXUuZGJDb25maWcudGVzdCk7XG4gICAgdGhpcy5mZGIgPSBjcmVhdGVLbmV4SW5zdGFuY2UoU29uYW11LmRiQ29uZmlnLmZpeHR1cmUpO1xuICB9XG5cbiAgLyoqXG4gICAg7JuQ6rKpIGZpeHR1cmUgRELrpbwg66Gc7LusIHRlc3QgRELroZwg67O17IKs7ZWp64uI64ukLlxuICAgIHBnX2R1bXDroZwg7JuQ6rKpIERC66W8IOuNpO2UhO2VmOqzoCwgcGdfcmVzdG9yZeuhnCDroZzsu6zsl5Ag67O17JuQ7ZWp64uI64ukLlxuICAqL1xuICBhc3luYyBzeW5jKCkge1xuICAgIGNvbnN0IGZpeHR1cmVDb25uID0gU29uYW11LmRiQ29uZmlnLmZpeHR1cmUuY29ubmVjdGlvbiBhcyBLbmV4LlBnQ29ubmVjdGlvbkNvbmZpZztcbiAgICBjb25zdCB0ZXN0Q29ubiA9IFNvbmFtdS5kYkNvbmZpZy50ZXN0LmNvbm5lY3Rpb24gYXMgS25leC5QZ0Nvbm5lY3Rpb25Db25maWc7XG5cbiAgICAvLyAxLiDroZzsu6wgdGVzdCBEQiDsl7DqsrAg7KKF66OMIOuwjyDsnqzsg53shLFcbiAgICBjb25zdCB0ZXN0UGdFbnYgPSB7IFBHUEFTU1dPUkQ6IHRlc3RDb25uLnBhc3N3b3JkIHx8IFwiXCIgfTtcbiAgICBleGVjU3luYyhcbiAgICAgIGBwc3FsIC1oICR7dGVzdENvbm4uaG9zdH0gLXAgJHt0ZXN0Q29ubi5wb3J0ID8/IDU0MzJ9IC1VICR7dGVzdENvbm4udXNlcn0gLWQgcG9zdGdyZXMgLWMgXCJcbiAgICAgICAgU0VMRUNUIHBnX3Rlcm1pbmF0ZV9iYWNrZW5kKHBnX3N0YXRfYWN0aXZpdHkucGlkKVxuICAgICAgICBGUk9NIHBnX3N0YXRfYWN0aXZpdHlcbiAgICAgICAgV0hFUkUgZGF0bmFtZSA9ICcke3Rlc3RDb25uLmRhdGFiYXNlfSdcbiAgICAgICAgICBBTkQgcGlkIDw+IHBnX2JhY2tlbmRfcGlkKCk7XG4gICAgICBcImAsXG4gICAgICB7IHN0ZGlvOiBcImluaGVyaXRcIiwgZW52OiB7IC4uLnByb2Nlc3MuZW52LCAuLi50ZXN0UGdFbnYgfSBhcyBOb2RlSlMuUHJvY2Vzc0VudiB9LFxuICAgICk7XG5cbiAgICBleGVjU3luYyhcbiAgICAgIGBwc3FsIC1oICR7dGVzdENvbm4uaG9zdH0gLXAgJHt0ZXN0Q29ubi5wb3J0ID8/IDU0MzJ9IC1VICR7dGVzdENvbm4udXNlcn0gLWQgcG9zdGdyZXMgLWMgXCJEUk9QIERBVEFCQVNFIElGIEVYSVNUUyBcXFxcXCIke3Rlc3RDb25uLmRhdGFiYXNlfVxcXFxcIlwiYCxcbiAgICAgIHsgc3RkaW86IFwiaW5oZXJpdFwiLCBlbnY6IHsgLi4ucHJvY2Vzcy5lbnYsIC4uLnRlc3RQZ0VudiB9IGFzIE5vZGVKUy5Qcm9jZXNzRW52IH0sXG4gICAgKTtcblxuICAgIGV4ZWNTeW5jKFxuICAgICAgYHBzcWwgLWggJHt0ZXN0Q29ubi5ob3N0fSAtcCAke3Rlc3RDb25uLnBvcnQgPz8gNTQzMn0gLVUgJHt0ZXN0Q29ubi51c2VyfSAtZCBwb3N0Z3JlcyAtYyBcIkNSRUFURSBEQVRBQkFTRSBcXFxcXCIke3Rlc3RDb25uLmRhdGFiYXNlfVxcXFxcIlwiYCxcbiAgICAgIHsgc3RkaW86IFwiaW5oZXJpdFwiLCBlbnY6IHsgLi4ucHJvY2Vzcy5lbnYsIC4uLnRlc3RQZ0VudiB9IGFzIE5vZGVKUy5Qcm9jZXNzRW52IH0sXG4gICAgKTtcblxuICAgIC8vIDIuIOybkOqyqSBmaXh0dXJlIERCIOKGkiDroZzsu6wgdGVzdCBEQuuhnCDrs7XsgqwgKHBnX2R1bXAgfCBwZ19yZXN0b3JlKVxuICAgIGNvbnN0IGZpeHR1cmVQZ0VudiA9IHsgUEdQQVNTV09SRDogZml4dHVyZUNvbm4ucGFzc3dvcmQgfHwgXCJcIiB9O1xuICAgIGNvbnN0IGR1bXBDbWQgPSBgcGdfZHVtcCAtaCAke2ZpeHR1cmVDb25uLmhvc3R9IC1wICR7Zml4dHVyZUNvbm4ucG9ydCA/PyA1NDMyfSAtVSAke2ZpeHR1cmVDb25uLnVzZXJ9IC1kICR7Zml4dHVyZUNvbm4uZGF0YWJhc2V9IC1GY2A7XG4gICAgY29uc3QgcmVzdG9yZUNtZCA9IGBwZ19yZXN0b3JlIC1oICR7dGVzdENvbm4uaG9zdH0gLXAgJHt0ZXN0Q29ubi5wb3J0ID8/IDU0MzJ9IC1VICR7dGVzdENvbm4udXNlcn0gLWQgJHt0ZXN0Q29ubi5kYXRhYmFzZX0gLS1uby1vd25lciAtLW5vLWFjbGA7XG5cbiAgICBleGVjU3luYyhgJHtkdW1wQ21kfSB8IFBHUEFTU1dPUkQ9XCIke3Rlc3RDb25uLnBhc3N3b3JkIHx8IFwiXCJ9XCIgJHtyZXN0b3JlQ21kfWAsIHtcbiAgICAgIHN0ZGlvOiBcImluaGVyaXRcIixcbiAgICAgIGVudjogeyAuLi5wcm9jZXNzLmVudiwgLi4uZml4dHVyZVBnRW52IH0gYXMgTm9kZUpTLlByb2Nlc3NFbnYsXG4gICAgICBzaGVsbDogXCIvYmluL2Jhc2hcIixcbiAgICB9KTtcblxuICAgIC8vIDMuIOyLnO2AgOyKpCDrpqzshYsgKOuNsOydtO2EsCDrs7Xsgqwg7ZuEIOyLnO2AgOyKpOulvCBNQVgoaWQp66GcIOygleugrClcbiAgICBhd2FpdCB0aGlzLnJlc2V0U2VxdWVuY2VzKFNvbmFtdS5kYkNvbmZpZy50ZXN0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiDrqqjrk6Ag7YWM7J2067iU7J2YIOyLnO2AgOyKpOulvCDtmITsnqwgTUFYKGlkKeuhnCDrpqzshYvtlanri4jri6QuXG4gICAqIGZpeHR1cmUgc3luYyDtm4Qg7Iuc7YCA7Iqk6rCAIOyLpOygnCDrjbDsnbTthLDsmYAg66ee7KeAIOyViuuKlCDrrLjsoJzrpbwg7ZW06rKw7ZWp64uI64ukLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyByZXNldFNlcXVlbmNlcyhkYkNvbmZpZzogU29uYW11REJDb25maWdbXCJ0ZXN0XCJdKSB7XG4gICAgY29uc3QgdGVzdERiID0gY3JlYXRlS25leEluc3RhbmNlKGRiQ29uZmlnKTtcbiAgICBjb25zdCBlbnRpdGllcyA9IEVudGl0eU1hbmFnZXIuZ2V0QWxsRW50aXRpZXMoKTtcblxuICAgIHRyeSB7XG4gICAgICBmb3IgKGNvbnN0IGVudGl0eSBvZiBlbnRpdGllcykge1xuICAgICAgICBjb25zdCB0YWJsZU5hbWUgPSBlbnRpdHkudGFibGUgfHwgZW50aXR5LmlkLnRvTG93ZXJDYXNlKCk7XG5cbiAgICAgICAgLy8gaWQg7ZWE65Oc7J2YIO2DgOyeheydhCDtmZXsnbjtlanri4jri6RcbiAgICAgICAgY29uc3QgaWRQcm9wID0gZW50aXR5LnByb3BzLmZpbmQoKHApID0+IHAubmFtZSA9PT0gXCJpZFwiKTtcbiAgICAgICAgY29uc3QgaWRUeXBlID0gaWRQcm9wPy50eXBlO1xuXG4gICAgICAgIC8vIGludGVnZXIvYmlnSW50ZWdlcuydtOqxsOuCmCwgc3RyaW5n7J207KeA66eMIGZpeHR1cmVTdHJhdGVneT1zZXF1ZW5jZeyduCDqsr3smrDsl5Drp4wg66as7IWL7ZWp64uI64ukXG4gICAgICAgIGNvbnN0IHVzZXNTZXF1ZW5jZSA9XG4gICAgICAgICAgaWRUeXBlID09PSBcImludGVnZXJcIiB8fFxuICAgICAgICAgIGlkVHlwZSA9PT0gXCJiaWdJbnRlZ2VyXCIgfHxcbiAgICAgICAgICBpZFByb3A/LmNvbmU/LmZpeHR1cmVTdHJhdGVneSA9PT0gXCJzZXF1ZW5jZVwiO1xuXG4gICAgICAgIGlmICghdXNlc1NlcXVlbmNlKSB7XG4gICAgICAgICAgIWlzVGVzdCgpICYmXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgICAgYFNraXBwaW5nIHNlcXVlbmNlIHJlc2V0IGZvciAke3RhYmxlTmFtZX0gKGlkIHR5cGU6ICR7aWRUeXBlIHx8IFwidW5rbm93blwifSlgLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFBvc3RncmVTUUwg7Iuc7YCA7Iqk66W8IO2YhOyerCDthYzsnbTruJTsnZggTUFYKGlkKeuhnCDrpqzshYvtlanri4jri6QuXG4gICAgICAgIC8vIHN0cmluZyDtg4DsnoXsnZgg6rK97JqwIOyIq+yekCDsupDsiqTtjIXsnbQg7ZWE7JqU7ZWp64uI64ukLlxuICAgICAgICBjb25zdCBtYXhFeHByID0gaWRUeXBlID09PSBcInN0cmluZ1wiID8gXCJNQVgoaWQ6OmJpZ2ludClcIiA6IFwiTUFYKGlkKVwiO1xuICAgICAgICBhd2FpdCB0ZXN0RGIucmF3KGBcbiAgICAgICAgICBTRUxFQ1Qgc2V0dmFsKFxuICAgICAgICAgICAgcGdfZ2V0X3NlcmlhbF9zZXF1ZW5jZSgncHVibGljLiR7dGFibGVOYW1lfScsICdpZCcpLFxuICAgICAgICAgICAgQ09BTEVTQ0UoKFNFTEVDVCAke21heEV4cHJ9IEZST00gJHt0YWJsZU5hbWV9KSwgMSlcbiAgICAgICAgICApXG4gICAgICAgIGApO1xuICAgICAgfVxuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCB0ZXN0RGIuZGVzdHJveSgpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgdmlzaXRlZFJlY29yZHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgYXN5bmMgaW1wb3J0Rml4dHVyZShlbnRpdHlJZDogc3RyaW5nLCBpZHM6IG51bWJlcltdKSB7XG4gICAgLy8g67Cp66y4IOq4sOuhnSDstIjquLDtmZQgKOyDiOuhnOyatCBpbXBvcnQg7J6R7JeFIOyLnOyekSlcbiAgICB0aGlzLnZpc2l0ZWRSZWNvcmRzLmNsZWFyKCk7XG5cbiAgICBjb25zdCBxdWVyaWVzID0gdW5pcXVlKFxuICAgICAgKFxuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgICBpZHMubWFwKGFzeW5jIChpZCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuZ2V0SW1wb3J0UXVlcmllcyhlbnRpdHlJZCwgXCJpZFwiLCBpZCk7XG4gICAgICAgICAgfSksXG4gICAgICAgIClcbiAgICAgICkuZmxhdCgpLFxuICAgICk7XG5cbiAgICBjb25zdCB3ZGIgPSBCYXNlTW9kZWwuZ2V0REIoXCJ3XCIpO1xuICAgIGZvciAoY29uc3QgcXVlcnkgb2YgcXVlcmllcykge1xuICAgICAgYXdhaXQgd2RiLnJhdyhxdWVyeSk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZ2V0SW1wb3J0UXVlcmllcyhlbnRpdHlJZDogc3RyaW5nLCBmaWVsZDogc3RyaW5nLCBpZDogbnVtYmVyKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIGNvbnN0IHJlY29yZEtleSA9IGAke2VudGl0eUlkfSMke2ZpZWxkfSMke2lkfWA7XG5cbiAgICAvLyDsiJztmZgg7LC47KGwIOuwqeyngDog7J2066+4IOuwqeusuO2VnCDroIjsvZTrk5zripQg7Iqk7YK1XG4gICAgaWYgKHRoaXMudmlzaXRlZFJlY29yZHMuaGFzKHJlY29yZEtleSkpIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgdGhpcy52aXNpdGVkUmVjb3Jkcy5hZGQocmVjb3JkS2V5KTtcblxuICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKTtcbiAgICBjb25zdCB3ZGIgPSBCYXNlTW9kZWwuZ2V0REIoXCJ3XCIpO1xuXG4gICAgLy8g7Jes6riw7IScIOyLpERC7J2YIHJvdyDqsIDsoLjsmLRcbiAgICBjb25zdCBbcm93XSA9IGF3YWl0IHdkYihlbnRpdHkudGFibGUpLndoZXJlKGZpZWxkLCBpZCkubGltaXQoMSk7XG4gICAgaWYgKHJvdyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7ZW50aXR5SWR9IyR7aWR9IHJvd+ulvCDssL7snYQg7IiYIOyXhuyKteuLiOuLpC5gKTtcbiAgICB9XG5cbiAgICAvLyDtlL3siqTss5BEQiwg7IukREJcbiAgICBjb25zdCBmaXh0dXJlRGF0YWJhc2UgPSAoU29uYW11LmRiQ29uZmlnLmZpeHR1cmUuY29ubmVjdGlvbiBhcyBLbmV4LkNvbm5lY3Rpb25Db25maWcpLmRhdGFiYXNlO1xuICAgIGNvbnN0IHJlYWxEYXRhYmFzZSA9IChTb25hbXUuZGJDb25maWcucHJvZHVjdGlvbi5jb25uZWN0aW9uIGFzIEtuZXguQ29ubmVjdGlvbkNvbmZpZykuZGF0YWJhc2U7XG5cbiAgICBjb25zdCBzZWxmUXVlcnkgPSBgSU5TRVJUIElHTk9SRSBJTlRPIFxcYCR7Zml4dHVyZURhdGFiYXNlfVxcYC5cXGAke2VudGl0eS50YWJsZX1cXGAgKFNFTEVDVCAqIEZST00gXFxgJHtyZWFsRGF0YWJhc2V9XFxgLlxcYCR7ZW50aXR5LnRhYmxlfVxcYCBXSEVSRSBcXGBpZFxcYCA9ICR7aWR9KWA7XG5cbiAgICBjb25zdCBhcmdzID0gT2JqZWN0LmVudHJpZXMoZW50aXR5LnJlbGF0aW9ucylcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgIChbLCByZWxhdGlvbl0pID0+XG4gICAgICAgICAgaXNCZWxvbmdzVG9PbmVSZWxhdGlvblByb3AocmVsYXRpb24pIHx8XG4gICAgICAgICAgKGlzT25lVG9PbmVSZWxhdGlvblByb3AocmVsYXRpb24pICYmIHJlbGF0aW9uLmN1c3RvbUpvaW5DbGF1c2UgPT09IHVuZGVmaW5lZCksXG4gICAgICApXG4gICAgICAubWFwKChbLCByZWxhdGlvbl0pID0+IHtcbiAgICAgICAgLypcbiAgICAgICAgQmVsb25nc1RvT25l7J24IOqyveyasFxuICAgICAgICAgIENhdGVnb3J5IC8gJ2lkJyAvIHJvd1tjYXRlZ29yeV9pZF0g7Zi47LacXG4gICAgICAgIE9uZVRvT25l7JeQIGpvaW5Db2x1bW4gPT09IHRydWUg7J24IOqyveyasFxuICAgICAgICAgIFByb2ZpbGUgLyAnaWQnIC8gcm93W3Byb2ZpbGVfaWRdIO2YuOy2nFxuICAgICAgICBPbmVUb09uZeyXkCBqb2luQ29sdW1uID09PSBmYWxzZSDsnbgg6rK97JqwXG4gICAgICAgICAgUHJvZmlsZSAvICdwcm9maWxlX2lkJyAvIHJvd1snaWQnXSDtmLjstpxcbiAgICAgICAgKi9cbiAgICAgICAgbGV0IGZpZWxkOiBzdHJpbmc7XG4gICAgICAgIGxldCBpZDogbnVtYmVyO1xuICAgICAgICBpZiAoaXNPbmVUb09uZVJlbGF0aW9uUHJvcChyZWxhdGlvbikgJiYgIXJlbGF0aW9uLmhhc0pvaW5Db2x1bW4pIHtcbiAgICAgICAgICBjb25zdCByZWxhdGVkRW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQocmVsYXRpb24ud2l0aCk7XG4gICAgICAgICAgY29uc3QgcmVsYXRlZElkQ29sdW1uTmFtZSA9IHJlbGF0ZWRFbnRpdHkucHJvcHMuZmluZChcbiAgICAgICAgICAgIChwKSA9PiBpc1JlbGF0aW9uUHJvcChwKSAmJiBwLndpdGggPT09IGVudGl0eS5pZCxcbiAgICAgICAgICApPy5uYW1lO1xuICAgICAgICAgIGlmICghcmVsYXRlZElkQ29sdW1uTmFtZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke3JlbGF0ZWRFbnRpdHkuaWR97J2YICR7ZW50aXR5LmlkfSDqtIDqs4Qg7ZSE66Gt7J2EIOywvuydhCDsiJgg7JeG7Iq164uI64ukLmApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBmaWVsZCA9IGAke3JlbGF0ZWRJZENvbHVtbk5hbWV9X2lkYDtcbiAgICAgICAgICBpZCA9IHJvdy5pZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBmaWVsZCA9IFwiaWRcIjtcbiAgICAgICAgICBpZCA9IHJvd1tgJHtyZWxhdGlvbi5uYW1lfV9pZGBdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgZW50aXR5SWQ6IHJlbGF0aW9uLndpdGgsXG4gICAgICAgICAgZmllbGQsXG4gICAgICAgICAgaWQsXG4gICAgICAgIH07XG4gICAgICB9KVxuICAgICAgLmZpbHRlcigoYXJnKSA9PiBhcmcuaWQgIT09IG51bGwpO1xuXG4gICAgY29uc3QgcmVsUXVlcmllcyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgYXJncy5tYXAoYXN5bmMgKGFyZ3MpID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0SW1wb3J0UXVlcmllcyhhcmdzLmVudGl0eUlkLCBhcmdzLmZpZWxkLCBhcmdzLmlkKTtcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICByZXR1cm4gWy4uLnVuaXF1ZShyZWxRdWVyaWVzLnRvUmV2ZXJzZWQoKS5mbGF0KCkpLCBzZWxmUXVlcnldO1xuICB9XG5cbiAgYXN5bmMgZGVzdHJveSgpIHtcbiAgICBpZiAodGhpcy5fdGRiKSB7XG4gICAgICBhd2FpdCB0aGlzLl90ZGIuZGVzdHJveSgpO1xuICAgICAgdGhpcy5fdGRiID0gbnVsbDtcbiAgICB9XG4gICAgaWYgKHRoaXMuX2ZkYikge1xuICAgICAgYXdhaXQgdGhpcy5fZmRiLmRlc3Ryb3koKTtcbiAgICAgIHRoaXMuX2ZkYiA9IG51bGw7XG4gICAgfVxuICAgIGF3YWl0IEJhc2VNb2RlbC5kZXN0cm95KCk7XG4gIH1cblxuICBhc3luYyBnZXRGaXh0dXJlcyhcbiAgICBzb3VyY2VEQk5hbWU6IGtleW9mIFNvbmFtdURCQ29uZmlnLFxuICAgIHRhcmdldERCTmFtZToga2V5b2YgU29uYW11REJDb25maWcsXG4gICAgc2VhcmNoT3B0aW9uczogRml4dHVyZVNlYXJjaE9wdGlvbnMsXG4gICAgZHVwbGljYXRlQ2hlY2s/OiBEdXBsaWNhdGVDaGVja09wdGlvbnMsXG4gICkge1xuICAgIGNvbnN0IHNvdXJjZURCID0gY3JlYXRlS25leEluc3RhbmNlKFNvbmFtdS5kYkNvbmZpZ1tzb3VyY2VEQk5hbWVdKTtcbiAgICBjb25zdCB0YXJnZXREQiA9IGNyZWF0ZUtuZXhJbnN0YW5jZShTb25hbXUuZGJDb25maWdbdGFyZ2V0REJOYW1lXSk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgeyBlbnRpdHlJZCwgZmllbGQsIHZhbHVlLCBzZWFyY2hUeXBlIH0gPSBzZWFyY2hPcHRpb25zO1xuXG4gICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgICBjb25zdCBjb2x1bW4gPVxuICAgICAgICBlbnRpdHkucHJvcHMuZmluZCgocHJvcCkgPT4gcHJvcC5uYW1lID09PSBmaWVsZCk/LnR5cGUgPT09IFwicmVsYXRpb25cIlxuICAgICAgICAgID8gYCR7ZmllbGR9X2lkYFxuICAgICAgICAgIDogZmllbGQ7XG5cbiAgICAgIGxldCBxdWVyeSA9IHNvdXJjZURCKGVudGl0eS50YWJsZSk7XG4gICAgICBpZiAoc2VhcmNoVHlwZSA9PT0gXCJlcXVhbHNcIikge1xuICAgICAgICBxdWVyeSA9IHF1ZXJ5LndoZXJlKGNvbHVtbiwgdmFsdWUpO1xuICAgICAgfSBlbHNlIGlmIChzZWFyY2hUeXBlID09PSBcImxpa2VcIikge1xuICAgICAgICBxdWVyeSA9IHF1ZXJ5LndoZXJlKGNvbHVtbiwgXCJsaWtlXCIsIGAlJHt2YWx1ZX0lYCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJvd3MgPSBhd2FpdCBxdWVyeTtcbiAgICAgIGlmIChyb3dzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyByZWNvcmRzIGZvdW5kXCIpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBmaXh0dXJlczogRml4dHVyZVJlY29yZFtdID0gW107XG4gICAgICBmb3IgKGNvbnN0IHJvdyBvZiByb3dzKSB7XG4gICAgICAgIGNvbnN0IGluaXRpYWxSZWNvcmRzTGVuZ3RoID0gZml4dHVyZXMubGVuZ3RoO1xuICAgICAgICBjb25zdCBuZXdSZWNvcmRzID0gYXdhaXQgdGhpcy5jcmVhdGVGaXh0dXJlUmVjb3JkKGVudGl0eSwgcm93LCB7XG4gICAgICAgICAgX2RiOiBzb3VyY2VEQixcbiAgICAgICAgfSk7XG4gICAgICAgIGZpeHR1cmVzLnB1c2goLi4ubmV3UmVjb3Jkcyk7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRGaXh0dXJlUmVjb3JkID0gZml4dHVyZXMuZmluZCgocikgPT4gci5maXh0dXJlSWQgPT09IGAke2VudGl0eUlkfSMke3Jvdy5pZH1gKTtcblxuICAgICAgICBpZiAoY3VycmVudEZpeHR1cmVSZWNvcmQpIHtcbiAgICAgICAgICAvLyDtmITsnqwgZml4dHVyZeuhnOu2gO2EsCDsg53shLHrkJwgZmV0Y2hlZFJlY29yZHMg7ISk7KCVXG4gICAgICAgICAgY3VycmVudEZpeHR1cmVSZWNvcmQuZmV0Y2hlZFJlY29yZHMgPSBmaXh0dXJlc1xuICAgICAgICAgICAgLmZpbHRlcigocikgPT4gci5maXh0dXJlSWQgIT09IGN1cnJlbnRGaXh0dXJlUmVjb3JkLmZpeHR1cmVJZClcbiAgICAgICAgICAgIC5zbGljZShpbml0aWFsUmVjb3Jkc0xlbmd0aClcbiAgICAgICAgICAgIC5tYXAoKHIpID0+IHIuZml4dHVyZUlkKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IGZpeHR1cmUgb2YgZml4dHVyZXMpIHtcbiAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZml4dHVyZS5lbnRpdHlJZCk7XG5cbiAgICAgICAgLy8g7IKs7Jqp7J6QIOyngOyglSDsu6zrn7wg6riw7KSAIOykkeuztSDtmZXsnbgg4oaSIHRhcmdldFxuICAgICAgICBjb25zdCBjdXN0b21Db2x1bW5zID0gZHVwbGljYXRlQ2hlY2s/LmNvbHVtbnM/LltmaXh0dXJlLmVudGl0eUlkXTtcbiAgICAgICAgaWYgKGN1c3RvbUNvbHVtbnMgJiYgY3VzdG9tQ29sdW1ucy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgY29uc3QgY3VzdG9tRHVwbGljYXRlUm93ID0gYXdhaXQgdGhpcy5jaGVja0R1cGxpY2F0ZUJ5Q29sdW1ucyhcbiAgICAgICAgICAgIHRhcmdldERCLFxuICAgICAgICAgICAgZW50aXR5LFxuICAgICAgICAgICAgZml4dHVyZSxcbiAgICAgICAgICAgIGN1c3RvbUNvbHVtbnMsXG4gICAgICAgICAgKTtcbiAgICAgICAgICBpZiAoY3VzdG9tRHVwbGljYXRlUm93KSB7XG4gICAgICAgICAgICBjb25zdCBbcmVjb3JkXSA9IGF3YWl0IHRoaXMuY3JlYXRlRml4dHVyZVJlY29yZChlbnRpdHksIGN1c3RvbUR1cGxpY2F0ZVJvdywge1xuICAgICAgICAgICAgICBzaW5nbGVSZWNvcmQ6IHRydWUsXG4gICAgICAgICAgICAgIF9kYjogdGFyZ2V0REIsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGZpeHR1cmUudGFyZ2V0ID0gcmVjb3JkO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFVuaXF1ZSBpbmRleCDquLDspIAg7KSR67O1IO2ZleyduCDihpIgZml4dHVyZS51bmlxdWVcbiAgICAgICAgY29uc3QgdW5pcXVlUm93ID0gYXdhaXQgdGhpcy5jaGVja1VuaXF1ZVZpb2xhdGlvbih0YXJnZXREQiwgZW50aXR5LCBmaXh0dXJlKTtcbiAgICAgICAgaWYgKHVuaXF1ZVJvdykge1xuICAgICAgICAgIGNvbnN0IFtyZWNvcmRdID0gYXdhaXQgdGhpcy5jcmVhdGVGaXh0dXJlUmVjb3JkKGVudGl0eSwgdW5pcXVlUm93LCB7XG4gICAgICAgICAgICBzaW5nbGVSZWNvcmQ6IHRydWUsXG4gICAgICAgICAgICBfZGI6IHRhcmdldERCLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGZpeHR1cmUudW5pcXVlID0gcmVjb3JkO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB1bmlxdWUoZml4dHVyZXMsIChmKSA9PiBmLmZpeHR1cmVJZCk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChbdGFyZ2V0REIuZGVzdHJveSgpLCBzb3VyY2VEQi5kZXN0cm95KCldKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBjcmVhdGVGaXh0dXJlUmVjb3JkKFxuICAgIGVudGl0eTogRW50aXR5LFxuICAgIHJvdzoge1xuICAgICAgaWQ6IG51bWJlciB8IHN0cmluZztcbiAgICAgIFtrZXk6IHN0cmluZ106IHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4gfCBudWxsO1xuICAgIH0sXG4gICAgb3B0aW9ucz86IHtcbiAgICAgIHNpbmdsZVJlY29yZD86IGJvb2xlYW47XG4gICAgICBfZGI/OiBLbmV4O1xuICAgIH0sXG4gICk6IFByb21pc2U8Rml4dHVyZVJlY29yZFtdPiB7XG4gICAgY29uc3QgcmVjb3JkczogRml4dHVyZVJlY29yZFtdID0gW107XG4gICAgY29uc3QgdmlzaXRlZEVudGl0aWVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgICBjb25zdCBjcmVhdGUgPSBhc3luYyAoXG4gICAgICBlbnRpdHk6IEVudGl0eSxcbiAgICAgIHJvdzoge1xuICAgICAgICBpZDogbnVtYmVyIHwgc3RyaW5nO1xuICAgICAgICBba2V5OiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgbnVsbDtcbiAgICAgIH0sXG4gICAgKSA9PiB7XG4gICAgICBjb25zdCBmaXh0dXJlSWQgPSBgJHtlbnRpdHkuaWR9IyR7cm93LmlkfWA7XG4gICAgICBpZiAodmlzaXRlZEVudGl0aWVzLmhhcyhmaXh0dXJlSWQpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHZpc2l0ZWRFbnRpdGllcy5hZGQoZml4dHVyZUlkKTtcblxuICAgICAgY29uc3QgcmVjb3JkOiBGaXh0dXJlUmVjb3JkID0ge1xuICAgICAgICBmaXh0dXJlSWQsXG4gICAgICAgIGVudGl0eUlkOiBlbnRpdHkuaWQsXG4gICAgICAgIGlkOiByb3cuaWQsXG4gICAgICAgIGNvbHVtbnM6IHt9LFxuICAgICAgICBmZXRjaGVkUmVjb3JkczogW10sXG4gICAgICAgIGJlbG9uZ3NSZWNvcmRzOiBbXSxcbiAgICAgIH07XG5cbiAgICAgIGZvciAoY29uc3QgcHJvcCBvZiBlbnRpdHkucHJvcHMpIHtcbiAgICAgICAgaWYgKGlzVmlydHVhbFByb3AocHJvcCkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlY29yZC5jb2x1bW5zW3Byb3AubmFtZV0gPSB7XG4gICAgICAgICAgcHJvcDogcHJvcCxcbiAgICAgICAgICB2YWx1ZTogcm93W3Byb3AubmFtZV0sXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgZGIgPSBvcHRpb25zPy5fZGIgPz8gQmFzZU1vZGVsLmdldERCKFwid1wiKTtcbiAgICAgICAgaWYgKGlzTWFueVRvTWFueVJlbGF0aW9uUHJvcChwcm9wKSkge1xuICAgICAgICAgIGNvbnN0IHJlbGF0ZWRFbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChwcm9wLndpdGgpO1xuICAgICAgICAgIGNvbnN0IHRocm91Z2hUYWJsZSA9IHByb3Auam9pblRhYmxlO1xuICAgICAgICAgIGNvbnN0IGZyb21Db2x1bW4gPSBgJHtpbmZsZWN0aW9uLnNpbmd1bGFyaXplKGVudGl0eS50YWJsZSl9X2lkYDtcbiAgICAgICAgICBjb25zdCB0b0NvbHVtbiA9IGAke2luZmxlY3Rpb24uc2luZ3VsYXJpemUocmVsYXRlZEVudGl0eS50YWJsZSl9X2lkYDtcblxuICAgICAgICAgIGNvbnN0IHJlbGF0ZWRJZHMgPSBhd2FpdCBkYih0aHJvdWdoVGFibGUpLndoZXJlKGZyb21Db2x1bW4sIHJvdy5pZCkucGx1Y2sodG9Db2x1bW4pO1xuICAgICAgICAgIHJlY29yZC5jb2x1bW5zW3Byb3AubmFtZV0udmFsdWUgPSByZWxhdGVkSWRzO1xuICAgICAgICB9IGVsc2UgaWYgKGlzSGFzTWFueVJlbGF0aW9uUHJvcChwcm9wKSkge1xuICAgICAgICAgIGNvbnN0IHJlbGF0ZWRFbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChwcm9wLndpdGgpO1xuICAgICAgICAgIGNvbnN0IHJlbGF0ZWRJZHMgPSBhd2FpdCBkYihyZWxhdGVkRW50aXR5LnRhYmxlKVxuICAgICAgICAgICAgLndoZXJlKHByb3Auam9pbkNvbHVtbiwgcm93LmlkKVxuICAgICAgICAgICAgLnBsdWNrKFwiaWRcIik7XG4gICAgICAgICAgcmVjb3JkLmNvbHVtbnNbcHJvcC5uYW1lXS52YWx1ZSA9IHJlbGF0ZWRJZHM7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNPbmVUb09uZVJlbGF0aW9uUHJvcChwcm9wKSAmJiAhcHJvcC5oYXNKb2luQ29sdW1uKSB7XG4gICAgICAgICAgLy8g7Jet67Cp7ZalIE9uZVRvT25lOiBGS+ulvCDqsIDsp4Qg6rSA66CoIOyXlO2LsO2LsOulvCDssL7sirXri4jri6RcbiAgICAgICAgICAvLyDsmIjsi5w6IFVzZXIgT25lVG9PbmUgRW1wbG95ZWUgKEVtcGxveWVl6rCAIHVzZXJfaWQgRkvrpbwg6rCA7KeQKVxuICAgICAgICAgIGNvbnN0IHJlbGF0ZWRFbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChwcm9wLndpdGgpO1xuICAgICAgICAgIGNvbnN0IHJlbGF0ZWRQcm9wID0gcmVsYXRlZEVudGl0eS5wcm9wcy5maW5kKFxuICAgICAgICAgICAgKHApID0+IGlzUmVsYXRpb25Qcm9wKHApICYmIHAud2l0aCA9PT0gZW50aXR5LmlkLFxuICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKHJlbGF0ZWRQcm9wICYmIGlzUmVsYXRpb25Qcm9wKHJlbGF0ZWRQcm9wKSkge1xuICAgICAgICAgICAgLy8g6rSA66CoIOyXlO2LsO2LsOyXkOyEnCBGSyDsu6zrn7zsnLzroZwg7L+866as7ZWp64uI64ukIChpZOqwgCDslYTri5gpXG4gICAgICAgICAgICBjb25zdCBma0NvbHVtbiA9IGAke3JlbGF0ZWRQcm9wLm5hbWV9X2lkYDtcbiAgICAgICAgICAgIGNvbnN0IHJlbGF0ZWRSb3cgPSBhd2FpdCBkYihyZWxhdGVkRW50aXR5LnRhYmxlKS53aGVyZShma0NvbHVtbiwgcm93LmlkKS5maXJzdCgpO1xuICAgICAgICAgICAgcmVjb3JkLmNvbHVtbnNbcHJvcC5uYW1lXS52YWx1ZSA9IHJlbGF0ZWRSb3c/LmlkO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChpc1JlbGF0aW9uUHJvcChwcm9wKSkge1xuICAgICAgICAgIGNvbnN0IHJlbGF0ZWRJZCA9IHJvd1tgJHtwcm9wLm5hbWV9X2lkYF07XG4gICAgICAgICAgcmVjb3JkLmNvbHVtbnNbcHJvcC5uYW1lXS52YWx1ZSA9IHJlbGF0ZWRJZDtcbiAgICAgICAgICBpZiAocmVsYXRlZElkKSB7XG4gICAgICAgICAgICByZWNvcmQuYmVsb25nc1JlY29yZHMucHVzaChgJHtwcm9wLndpdGh9IyR7cmVsYXRlZElkfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW9wdGlvbnM/LnNpbmdsZVJlY29yZCAmJiByZWxhdGVkSWQpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlbGF0ZWRFbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChwcm9wLndpdGgpO1xuICAgICAgICAgICAgY29uc3QgcmVsYXRlZFJvdyA9IGF3YWl0IGRiKHJlbGF0ZWRFbnRpdHkudGFibGUpLndoZXJlKFwiaWRcIiwgcmVsYXRlZElkKS5maXJzdCgpO1xuICAgICAgICAgICAgaWYgKHJlbGF0ZWRSb3cpIHtcbiAgICAgICAgICAgICAgYXdhaXQgY3JlYXRlKHJlbGF0ZWRFbnRpdHksIHJlbGF0ZWRSb3cpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZWNvcmRzLnB1c2gocmVjb3JkKTtcbiAgICB9O1xuXG4gICAgYXdhaXQgY3JlYXRlKGVudGl0eSwgcm93KTtcblxuICAgIHJldHVybiByZWNvcmRzO1xuICB9XG5cbiAgLyoqXG4gICAqIDEuIFJlbGF0aW9uR3JhcGjroZwgZml4dHVyZSDri6jsnIQg7IK97J6FIOyInOyEnCDqs4TsgrAgKHNlbGYtcmVmZXJlbmNlIO2PrO2VqClcbiAgICogMi4g7YWM7J2067iU67OEIOugiOuyqOuzhOuhnCBVcHNlcnRCdWlsZGVy7JeQIOuTseuhnSDrsI8gdXBzZXJ0IOyLpO2WiVxuICAgKiAzLiDsiJzshJwg6riw67CYIHV1aWTihpJpZCDrp6TtlZEgKFVwc2VydEJ1aWxkZXLqsIAgdXVpZOulvCBEQuyXkCDsoIDsnqXtlZjsp4Ag7JWK7Jy866+A66GcKVxuICAgKlxuICAgKiBVcHNlcnRCdWlsZGVy64qUIHNlbGYtcmVmZXJlbmNl6rCAIOyeiOycvOuptCBidWlsZEluc2VydExldmVscygp66GcIOyerOygleugrO2VmOyXrFxuICAgKiDrk7HroZ0g7Iic7ISc7JmAIOuwmO2ZmCDsiJzshJzqsIAg64us65287KeIIOyImCDsnojsirXri4jri6QuIOydtOulvCDrsKnsp4DtlZjquLAg7JyE7ZW0XG4gICAqIEZpeHR1cmVNYW5hZ2Vy6rCAIOugiOuyqOuzhOuhnCDrgpjriKDshJwg7LKY66as7ZWY7JesIOqwgSB1cHNlcnQg7Zi47Lac7JeQ7ISc64qUXG4gICAqIHNlbGYtcmVmZXJlbmNl6rCAIOyXhuuPhOuhnSDtlanri4jri6QuXG4gICAqL1xuICBhc3luYyBpbnNlcnRGaXh0dXJlcyhcbiAgICBkYk5hbWU6IGtleW9mIFNvbmFtdURCQ29uZmlnLFxuICAgIF9maXh0dXJlczogRml4dHVyZVJlY29yZFtdLFxuICApOiBQcm9taXNlPEZpeHR1cmVJbXBvcnRSZXN1bHRbXT4ge1xuICAgIGNvbnN0IGZpeHR1cmVzID0gdW5pcXVlKF9maXh0dXJlcywgKGYpID0+IGYuZml4dHVyZUlkKTtcblxuICAgIC8vIOy0iOq4sO2ZlFxuICAgIHRoaXMuYnVpbGRlciA9IG5ldyBVcHNlcnRCdWlsZGVyKCk7XG4gICAgdGhpcy5maXh0dXJlUmVmTWFwID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuc2tpcHBlZEZpeHR1cmVzID0gbmV3IE1hcCgpO1xuXG4gICAgLy8g67OR66CsIO2FjOyKpO2KuCDrqqjrk5zsl5DshJzripQgd29ya2Vy67OEIERC7JeQIOyggOyepVxuICAgIGNvbnN0IGRiQ29uZmlnID1cbiAgICAgIHByb2Nlc3MuZW52LlNPTkFNVV9XT1JLRVJfREIgPT09IFwidHJ1ZVwiICYmIHByb2Nlc3MuZW52LlZJVEVTVF9QT09MX0lEXG4gICAgICAgID8gKCgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHdvcmtlcklkID0gcGFyc2VJbnQocHJvY2Vzcy5lbnYuVklURVNUX1BPT0xfSUQgPz8gXCIxXCIsIDEwKTtcbiAgICAgICAgICAgIGNvbnN0IGJhc2VDb25maWcgPSBTb25hbXUuZGJDb25maWdbZGJOYW1lXTtcbiAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBiYXNlQ29uZmlnLmNvbm5lY3Rpb24gYXMgeyBkYXRhYmFzZTogc3RyaW5nIH07XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAuLi5iYXNlQ29uZmlnLFxuICAgICAgICAgICAgICBjb25uZWN0aW9uOiB7IC4uLmNvbm5lY3Rpb24sIGRhdGFiYXNlOiBgJHtjb25uZWN0aW9uLmRhdGFiYXNlfV8ke3dvcmtlcklkfWAgfSxcbiAgICAgICAgICAgICAgcG9vbDogeyBtaW46IDEsIG1heDogMSB9LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9KSgpXG4gICAgICAgIDogU29uYW11LmRiQ29uZmlnW2RiTmFtZV07XG4gICAgY29uc3QgZGIgPSBjcmVhdGVLbmV4SW5zdGFuY2UoZGJDb25maWcpO1xuICAgIGNvbnN0IHJlc3VsdHM6IEZpeHR1cmVJbXBvcnRSZXN1bHRbXSA9IFtdO1xuXG4gICAgdHJ5IHtcbiAgICAgIC8vIDEuIFJlbGF0aW9uR3JhcGjroZwgZml4dHVyZSDri6jsnIQg7IK97J6FIOyInOyEnCDqs4TsgrBcbiAgICAgIHRoaXMucmVsYXRpb25HcmFwaC5idWlsZEdyYXBoKGZpeHR1cmVzKTtcbiAgICAgIGNvbnN0IGluc2VydGlvbk9yZGVyID0gdGhpcy5yZWxhdGlvbkdyYXBoLmdldEluc2VydGlvbk9yZGVyKCk7XG5cbiAgICAgIC8vIDIuIOyKpO2Cte2VoCBmaXh0dXJlIOuovOyggCDsspjrpqwgKG92ZXJyaWRlIOyytO2BrClcbiAgICAgIGZvciAoY29uc3QgZml4dHVyZUlkIG9mIGluc2VydGlvbk9yZGVyKSB7XG4gICAgICAgIGNvbnN0IGZpeHR1cmUgPSBmaXh0dXJlcy5maW5kKChmKSA9PiBmLmZpeHR1cmVJZCA9PT0gZml4dHVyZUlkKTtcbiAgICAgICAgaWYgKCFmaXh0dXJlKSBjb250aW51ZTtcblxuICAgICAgICBjb25zdCBoYXNUYXJnZXQgPSAhIWZpeHR1cmUudGFyZ2V0O1xuICAgICAgICBjb25zdCBoYXNVbmlxdWUgPSAhIWZpeHR1cmUudW5pcXVlO1xuICAgICAgICBjb25zdCBoYXNEdXBsaWNhdGUgPSBoYXNUYXJnZXQgfHwgaGFzVW5pcXVlO1xuXG4gICAgICAgIC8vIOykkeuzteydtCDsnojqs6Agb3ZlcnJpZGU9ZmFsc2Xsnbgg6rK97JqwOiDsiqTtgrVcbiAgICAgICAgaWYgKGhhc0R1cGxpY2F0ZSAmJiAhZml4dHVyZS5vdmVycmlkZSkge1xuICAgICAgICAgIC8vIOq4sOyhtCDroIjsvZTrk5wgSUQg7KCA7J6lICh1bmlxdWUg7Jqw7ISgLCDsl4bsnLzrqbQgdGFyZ2V0KVxuICAgICAgICAgIGNvbnN0IGV4aXN0aW5nSWQgPSBmaXh0dXJlLnVuaXF1ZT8uaWQgPz8gZml4dHVyZS50YXJnZXQ/LmlkO1xuICAgICAgICAgIGFzc2VydChleGlzdGluZ0lkKTtcbiAgICAgICAgICB0aGlzLnNraXBwZWRGaXh0dXJlcy5zZXQoZml4dHVyZUlkLCB7XG4gICAgICAgICAgICBlbnRpdHlJZDogZml4dHVyZS5lbnRpdHlJZCxcbiAgICAgICAgICAgIGV4aXN0aW5nSWQsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAhaXNUZXN0KCkgJiZcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgICBjaGFsay55ZWxsb3coXG4gICAgICAgICAgICAgICAgYFNraXBwZWQgJHtmaXh0dXJlLmVudGl0eUlkfSMke2ZpeHR1cmUuaWR9IChleGlzdGluZzogIyR7ZXhpc3RpbmdJZH0sIG92ZXJyaWRlOiBmYWxzZSlgLFxuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyAzLiDthYzsnbTruJTrs4QgZml4dHVyZSDqt7jro7ntmZQgKGluc2VydGlvbk9yZGVyIOyInOyEnCDquLDrsJgpXG4gICAgICBjb25zdCBmaXh0dXJlc0J5VGFibGUgPSBuZXcgTWFwPHN0cmluZywgRml4dHVyZVJlY29yZFtdPigpO1xuICAgICAgY29uc3QgdGFibGVPcmRlcjogc3RyaW5nW10gPSBbXTtcblxuICAgICAgZm9yIChjb25zdCBmaXh0dXJlSWQgb2YgaW5zZXJ0aW9uT3JkZXIpIHtcbiAgICAgICAgLy8g7Iqk7YK165CcIGZpeHR1cmUg7KCc7Jm4XG4gICAgICAgIGlmICh0aGlzLnNraXBwZWRGaXh0dXJlcy5oYXMoZml4dHVyZUlkKSkgY29udGludWU7XG5cbiAgICAgICAgY29uc3QgZml4dHVyZSA9IGZpeHR1cmVzLmZpbmQoKGYpID0+IGYuZml4dHVyZUlkID09PSBmaXh0dXJlSWQpO1xuICAgICAgICBpZiAoIWZpeHR1cmUpIGNvbnRpbnVlO1xuXG4gICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGZpeHR1cmUuZW50aXR5SWQpO1xuICAgICAgICBjb25zdCB0YWJsZU5hbWUgPSBlbnRpdHkudGFibGU7XG5cbiAgICAgICAgaWYgKCFmaXh0dXJlc0J5VGFibGUuaGFzKHRhYmxlTmFtZSkpIHtcbiAgICAgICAgICBmaXh0dXJlc0J5VGFibGUuc2V0KHRhYmxlTmFtZSwgW10pO1xuICAgICAgICAgIHRhYmxlT3JkZXIucHVzaCh0YWJsZU5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIGZpeHR1cmVzQnlUYWJsZS5nZXQodGFibGVOYW1lKT8ucHVzaChmaXh0dXJlKTtcbiAgICAgIH1cblxuICAgICAgYXdhaXQgZGIudHJhbnNhY3Rpb24oYXN5bmMgKHRyeCkgPT4ge1xuICAgICAgICBjb25zdCBpbnNlcnRlZElkc0J5VGFibGUgPSBuZXcgTWFwPHN0cmluZywgTWFwPHN0cmluZywgbnVtYmVyIHwgc3RyaW5nPj4oKTtcblxuICAgICAgICAvLyA0LiDthYzsnbTruJTrs4Qg66CI67Ko67OEIOyymOumrFxuICAgICAgICBmb3IgKGNvbnN0IHRhYmxlTmFtZSBvZiB0YWJsZU9yZGVyKSB7XG4gICAgICAgICAgY29uc3QgdGFibGVGaXh0dXJlcyA9IGZpeHR1cmVzQnlUYWJsZS5nZXQodGFibGVOYW1lKSA/PyBbXTtcbiAgICAgICAgICBjb25zdCBsZXZlbHMgPSB0aGlzLmdyb3VwRml4dHVyZXNCeUxldmVsKHRhYmxlRml4dHVyZXMpO1xuXG4gICAgICAgICAgZm9yIChjb25zdCBsZXZlbEZpeHR1cmVzIG9mIGxldmVscykge1xuICAgICAgICAgICAgLy8g7ZW064u5IOugiOuyqOydmCBmaXh0dXJl65OkIHJlZ2lzdGVyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGZpeHR1cmUgb2YgbGV2ZWxGaXh0dXJlcykge1xuICAgICAgICAgICAgICB0aGlzLnJlZ2lzdGVyRml4dHVyZShmaXh0dXJlLCBpbnNlcnRlZElkc0J5VGFibGUpO1xuICAgICAgICAgICAgICAhaXNUZXN0KCkgJiZcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgICAgICAgIGNoYWxrLmJsdWUoXG4gICAgICAgICAgICAgICAgICAgIGBSZWdpc3RlcmVkICR7Zml4dHVyZS5lbnRpdHlJZH0jJHtmaXh0dXJlLmlkfSR7Zml4dHVyZS5vdmVycmlkZSA/IGAgKG92ZXJyaWRlKWAgOiBcIlwifWAsXG4gICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHVwc2VydCDsi6Ttlokg7KCEIHV1aWQg66qp66GdIOyggOyepVxuICAgICAgICAgICAgY29uc3QgdGFibGUgPSB0aGlzLmJ1aWxkZXIuZ2V0VGFibGUodGFibGVOYW1lKTtcbiAgICAgICAgICAgIGNvbnN0IHV1aWRzID0gdGFibGUucm93cy5tYXAoKHJvdykgPT4gcm93LnV1aWQgYXMgc3RyaW5nKTtcblxuICAgICAgICAgICAgIWlzVGVzdCgpICYmXG4gICAgICAgICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgICAgIGNoYWxrLmJsdWUoXG4gICAgICAgICAgICAgICAgICBgVXBzZXJ0aW5nICR7dGFibGVOYW1lfSB3aXRoICR7dXVpZHMubGVuZ3RofSByb3dzIChsZXZlbCAke2xldmVscy5pbmRleE9mKGxldmVsRml4dHVyZXMpICsgMX0vJHtsZXZlbHMubGVuZ3RofSlgLFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zdCBpZHMgPSAoYXdhaXQgdGhpcy5idWlsZGVyLnVwc2VydChcbiAgICAgICAgICAgICAgdHJ4LFxuICAgICAgICAgICAgICB0YWJsZU5hbWUgYXMga2V5b2YgRGF0YWJhc2VTY2hlbWFFeHRlbmQsXG4gICAgICAgICAgICApKSBhcyAobnVtYmVyIHwgc3RyaW5nKVtdO1xuXG4gICAgICAgICAgICAvLyDsiJzshJwg6riw67CYIHV1aWQgLT4gaWQg66ek7ZWRXG4gICAgICAgICAgICAvLyBzZWxmLXJlZmVyZW5jZeqwgCDsl4bsnLzrr4DroZwg65Ox66GdIOyInOyEnCA9IOuwmO2ZmCDsiJzshJwg67O07J6lXG4gICAgICAgICAgICBpZiAodXVpZHMubGVuZ3RoID4gMCAmJiB1dWlkcy5sZW5ndGggPT09IGlkcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgY29uc3QgZXhpc3RpbmdNYXAgPVxuICAgICAgICAgICAgICAgIGluc2VydGVkSWRzQnlUYWJsZS5nZXQodGFibGVOYW1lKSA/PyBuZXcgTWFwPHN0cmluZywgbnVtYmVyIHwgc3RyaW5nPigpO1xuICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHV1aWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgZXhpc3RpbmdNYXAuc2V0KHV1aWRzW2ldLCBpZHNbaV0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGluc2VydGVkSWRzQnlUYWJsZS5zZXQodGFibGVOYW1lLCBleGlzdGluZ01hcCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHV1aWRzLmxlbmd0aCAhPT0gaWRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICAgICAgY2hhbGsueWVsbG93KFxuICAgICAgICAgICAgICAgICAgYFdhcm5pbmc6IHV1aWQgY291bnQgKCR7dXVpZHMubGVuZ3RofSkgIT0gaWQgY291bnQgKCR7aWRzLmxlbmd0aH0pIGZvciAke3RhYmxlTmFtZX1gLFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gNS4gTWFueVRvTWFueSDqtIDqs4Qg7LKY66asXG4gICAgICAgIGF3YWl0IHRoaXMucHJvY2Vzc01hbnlUb01hbnlSZWxhdGlvbnModHJ4LCBmaXh0dXJlcywgaW5zZXJ0ZWRJZHNCeVRhYmxlKTtcblxuICAgICAgICAvLyA2LiBQb3N0Z3JlU1FMIOyLnO2AgOyKpCDrpqzshYtcbiAgICAgICAgLy8gRml4dHVyZSDsgr3snoUg7ZuEIOqwgSDthYzsnbTruJTsnZggSUQg7Iuc7YCA7Iqk66W8IOy1nOuMgCBJRCDqsJLsnLzroZwg7JeF642w7J207Yq47ZWp64uI64ukLlxuICAgICAgICAvLyDsnbTroIfqsowg7ZWY7KeAIOyViuycvOuptCDri6TsnYwgSU5TRVJUIOyLnCBJROqwgCAyMDAw67KI64yA66GcIOyDneyEseuQoCDsiJgg7J6I7Iq164uI64ukLlxuICAgICAgICAhaXNUZXN0KCkgJiYgY29uc29sZS5sb2coY2hhbGsuYmx1ZShcIlJlc2V0dGluZyBzZXF1ZW5jZXMuLi5cIikpO1xuICAgICAgICBmb3IgKGNvbnN0IHRhYmxlTmFtZSBvZiB0YWJsZU9yZGVyKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIEVudGl0eeulvCDssL7slYTshJwgaWQg7YOA7J6FIO2ZleyduFxuICAgICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXRBbGxFbnRpdGllcygpLmZpbmQoXG4gICAgICAgICAgICAgIChlKSA9PiBlLnRhYmxlID09PSB0YWJsZU5hbWUgfHwgZS5pZC50b0xvd2VyQ2FzZSgpID09PSB0YWJsZU5hbWUsXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICBpZiAoZW50aXR5KSB7XG4gICAgICAgICAgICAgIGNvbnN0IGlkUHJvcCA9IGVudGl0eS5wcm9wcy5maW5kKChwKSA9PiBwLm5hbWUgPT09IFwiaWRcIik7XG4gICAgICAgICAgICAgIGNvbnN0IGlkVHlwZSA9IGlkUHJvcD8udHlwZTtcblxuICAgICAgICAgICAgICAvLyBpbnRlZ2VyL2JpZ0ludGVnZXLsnbTqsbDrgpgsIHN0cmluZ+ydtOyngOunjCBmaXh0dXJlU3RyYXRlZ3k9c2VxdWVuY2Xsnbgg6rK97Jqw7JeQ66eMIOumrOyFi+2VqeuLiOuLpFxuICAgICAgICAgICAgICBjb25zdCB1c2VzU2VxdWVuY2UgPVxuICAgICAgICAgICAgICAgIGlkVHlwZSA9PT0gXCJpbnRlZ2VyXCIgfHxcbiAgICAgICAgICAgICAgICBpZFR5cGUgPT09IFwiYmlnSW50ZWdlclwiIHx8XG4gICAgICAgICAgICAgICAgaWRQcm9wPy5jb25lPy5maXh0dXJlU3RyYXRlZ3kgPT09IFwic2VxdWVuY2VcIjtcblxuICAgICAgICAgICAgICBpZiAoIXVzZXNTZXF1ZW5jZSkge1xuICAgICAgICAgICAgICAgICFpc1Rlc3QoKSAmJlxuICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgICAgICAgICAgIGNoYWxrLmdyYXkoXG4gICAgICAgICAgICAgICAgICAgICAgYFNraXBwZWQgc2VxdWVuY2UgcmVzZXQgZm9yICR7dGFibGVOYW1lfSAoaWQgdHlwZTogJHtpZFR5cGUgfHwgXCJ1bmtub3duXCJ9KWAsXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIO2FjOydtOu4lOydmCDstZzrjIAgSUQg7KGw7ZqMIChzdHJpbmcg7YOA7J6F7J2AIOyIq+yekCDsupDsiqTtjIUg7ZWE7JqUKVxuICAgICAgICAgICAgY29uc3QgZW50aXR5MiA9IEVudGl0eU1hbmFnZXIuZ2V0QWxsRW50aXRpZXMoKS5maW5kKFxuICAgICAgICAgICAgICAoZSkgPT4gZS50YWJsZSA9PT0gdGFibGVOYW1lIHx8IGUuaWQudG9Mb3dlckNhc2UoKSA9PT0gdGFibGVOYW1lLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IGlkVHlwZTIgPSBlbnRpdHkyPy5wcm9wcy5maW5kKChwKSA9PiBwLm5hbWUgPT09IFwiaWRcIik/LnR5cGU7XG4gICAgICAgICAgICBjb25zdCBtYXhJZFJlc3VsdCA9XG4gICAgICAgICAgICAgIGlkVHlwZTIgPT09IFwic3RyaW5nXCJcbiAgICAgICAgICAgICAgICA/IGF3YWl0IHRyeFxuICAgICAgICAgICAgICAgICAgICAucmF3KGBTRUxFQ1QgTUFYKGlkOjpiaWdpbnQpIGFzIG1heF9pZCBGUk9NIFwiJHt0YWJsZU5hbWV9XCJgKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigocikgPT4gci5yb3dzWzBdKVxuICAgICAgICAgICAgICAgIDogYXdhaXQgdHJ4KHRhYmxlTmFtZSkubWF4KFwiaWQgYXMgbWF4X2lkXCIpLmZpcnN0KCk7XG4gICAgICAgICAgICBjb25zdCBtYXhJZCA9IG1heElkUmVzdWx0Py5tYXhfaWQ7XG5cbiAgICAgICAgICAgIGlmIChtYXhJZCAhPT0gbnVsbCAmJiBtYXhJZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgIC8vIOyLnO2AgOyKpOuqheydhCBwZ19nZXRfc2VyaWFsX3NlcXVlbmNl66GcIOyViOyghO2VmOqyjCDsobDtmoxcbiAgICAgICAgICAgICAgYXdhaXQgdHJ4LnJhdyhgU0VMRUNUIHNldHZhbChwZ19nZXRfc2VyaWFsX3NlcXVlbmNlKD8sICdpZCcpLCA/KWAsIFtcbiAgICAgICAgICAgICAgICB0YWJsZU5hbWUsXG4gICAgICAgICAgICAgICAgbWF4SWQsXG4gICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgICAhaXNUZXN0KCkgJiYgY29uc29sZS5sb2coY2hhbGsuZ3JlZW4oYFJlc2V0IHNlcXVlbmNlIGZvciAke3RhYmxlTmFtZX06ICR7bWF4SWR9YCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgLy8g7Iuc7YCA7Iqk6rCAIOyXhuuKlCDthYzsnbTruJQoam9pbiB0YWJsZSDrk7Ep7J2AIOustOyLnFxuICAgICAgICAgICAgIWlzVGVzdCgpICYmIGNvbnNvbGUubG9nKGNoYWxrLmdyYXkoYFNraXBwZWQgc2VxdWVuY2UgcmVzZXQgZm9yICR7dGFibGVOYW1lfWApKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyA3LiDqsrDqs7wg7IiY7KeRXG4gICAgICAgIGZvciAoY29uc3QgZml4dHVyZSBvZiBmaXh0dXJlcykge1xuICAgICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGZpeHR1cmUuZW50aXR5SWQpO1xuXG4gICAgICAgICAgLy8g7Iqk7YK165CcIGZpeHR1cmXripQg6riw7KG0IOugiOy9lOuTnCDsoJXrs7TroZwg6rKw6rO8IOy2lOqwgFxuICAgICAgICAgIGNvbnN0IHNraXBwZWQgPSB0aGlzLnNraXBwZWRGaXh0dXJlcy5nZXQoZml4dHVyZS5maXh0dXJlSWQpO1xuICAgICAgICAgIGlmIChza2lwcGVkKSB7XG4gICAgICAgICAgICByZXN1bHRzLnB1c2goe1xuICAgICAgICAgICAgICBlbnRpdHlJZDogZml4dHVyZS5lbnRpdHlJZCxcbiAgICAgICAgICAgICAgZGF0YTogYXdhaXQgdHJ4KGVudGl0eS50YWJsZSkud2hlcmUoXCJpZFwiLCBza2lwcGVkLmV4aXN0aW5nSWQpLmZpcnN0KCksXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHJlZiA9IHRoaXMuZml4dHVyZVJlZk1hcC5nZXQoZml4dHVyZS5maXh0dXJlSWQpO1xuICAgICAgICAgIGlmIChyZWYpIHtcbiAgICAgICAgICAgIGNvbnN0IHV1aWRUb0lkID0gaW5zZXJ0ZWRJZHNCeVRhYmxlLmdldChlbnRpdHkudGFibGUpO1xuICAgICAgICAgICAgY29uc3QgaW5zZXJ0ZWRJZCA9IHV1aWRUb0lkPy5nZXQocmVmLnV1aWQpO1xuXG4gICAgICAgICAgICBpZiAoaW5zZXJ0ZWRJZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgIHJlc3VsdHMucHVzaCh7XG4gICAgICAgICAgICAgICAgZW50aXR5SWQ6IGZpeHR1cmUuZW50aXR5SWQsXG4gICAgICAgICAgICAgICAgZGF0YTogYXdhaXQgdHJ4KGVudGl0eS50YWJsZSkud2hlcmUoXCJpZFwiLCBpbnNlcnRlZElkKS5maXJzdCgpLFxuICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAhaXNUZXN0KCkgJiZcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgICAgICAgIGNoYWxrLmdyZWVuKGBJbnNlcnRlZCBpbnRvICR7ZW50aXR5LnRhYmxlfTogIyR7Zml4dHVyZS5pZH0gLT4gIyR7aW5zZXJ0ZWRJZH1gKSxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGF3YWl0IGRiLmRlc3Ryb3koKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdW5pcXVlKHJlc3VsdHMsIChyKSA9PiBgJHtyLmVudGl0eUlkfSMke3IuZGF0YS5pZH1gKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaXh0dXJlUmVjb3Jk66W8IFVwc2VydEJ1aWxkZXLsl5Ag65Ox66GdXG4gICAqIEBwYXJhbSBpbnNlcnRlZElkc0J5VGFibGUg7J2066+4IHVwc2VydOuQnCDthYzsnbTruJTsnZggdXVpZOKGkmlkIOunpO2VkSAo66CI67Ko67OEIOyymOumrCDsi5wg7IKs7JqpKVxuICAgKi9cbiAgcHJpdmF0ZSByZWdpc3RlckZpeHR1cmUoXG4gICAgZml4dHVyZTogRml4dHVyZVJlY29yZCxcbiAgICBpbnNlcnRlZElkc0J5VGFibGU/OiBNYXA8c3RyaW5nLCBNYXA8c3RyaW5nLCBudW1iZXIgfCBzdHJpbmc+PixcbiAgKTogVUJSZWYge1xuICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGZpeHR1cmUuZW50aXR5SWQpO1xuICAgIGNvbnN0IHJvdzogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fTtcblxuICAgIC8vIE92ZXJyaWRlIOuqqOuTnCDtjJDri6g6IHRhcmdldCDrmJDripQgdW5pcXVl6rCAIOyeiOqzoCBvdmVycmlkZT10cnVl7J24IOqyveyasFxuICAgIGNvbnN0IGV4aXN0aW5nUmVjb3JkID0gZml4dHVyZS50YXJnZXQgPz8gZml4dHVyZS51bmlxdWU7XG4gICAgY29uc3QgaXNPdmVycmlkZU1vZGUgPSBmaXh0dXJlLm92ZXJyaWRlICYmIGV4aXN0aW5nUmVjb3JkO1xuXG4gICAgZm9yIChjb25zdCBbcHJvcE5hbWUsIGNvbHVtbl0gb2YgT2JqZWN0LmVudHJpZXMoZml4dHVyZS5jb2x1bW5zKSkge1xuICAgICAgY29uc3QgcHJvcCA9IGNvbHVtbi5wcm9wO1xuXG4gICAgICBpZiAoaXNWaXJ0dWFsUHJvcChwcm9wKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gR2VuZXJhdGVkIGNvbHVtbuydgCBJTlNFUlTsl5DshJwg7KCc7Jm4IChEQuqwgCDsnpDrj5kg7IOd7ISxKVxuICAgICAgaWYgKFwiZ2VuZXJhdGVkXCIgaW4gcHJvcCAmJiBwcm9wLmdlbmVyYXRlZCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gaWQg7LKY66asXG4gICAgICBpZiAocHJvcE5hbWUgPT09IFwiaWRcIikge1xuICAgICAgICBjb25zdCBpZFByb3AgPSBlbnRpdHkucHJvcHMuZmluZCgocCkgPT4gcC5uYW1lID09PSBcImlkXCIpO1xuICAgICAgICAvLyBwYXJlbnRJZCDsl5Tti7Dti7DsnZggaWTripQg67aA66qoIOyXlO2LsO2LsOydmCBGS+ydtOuvgOuhnCDsi5ztgIDsiqQg66+47IKs7JqpICjrqoXsi5zsoIHsnLzroZwg7Y+s7ZWoKVxuICAgICAgICBjb25zdCB1c2VzU2VxdWVuY2UgPVxuICAgICAgICAgICFlbnRpdHkucGFyZW50SWQgJiZcbiAgICAgICAgICAoaWRQcm9wPy50eXBlID09PSBcImludGVnZXJcIiB8fFxuICAgICAgICAgICAgaWRQcm9wPy50eXBlID09PSBcImJpZ0ludGVnZXJcIiB8fFxuICAgICAgICAgICAgaWRQcm9wPy5jb25lPy5maXh0dXJlU3RyYXRlZ3kgPT09IFwic2VxdWVuY2VcIik7XG5cbiAgICAgICAgaWYgKGlzT3ZlcnJpZGVNb2RlICYmIGV4aXN0aW5nUmVjb3JkKSB7XG4gICAgICAgICAgLy8gT3ZlcnJpZGU6IOq4sOyhtCDroIjsvZTrk5zsnZgg6rCSIOyCrOyaqSDihpIgVVBEQVRFXG4gICAgICAgICAgcm93W3Byb3BOYW1lXSA9IGV4aXN0aW5nUmVjb3JkLmNvbHVtbnNbcHJvcE5hbWVdPy52YWx1ZTtcbiAgICAgICAgfSBlbHNlIGlmICghdXNlc1NlcXVlbmNlKSB7XG4gICAgICAgICAgLy8gc3RyaW5nIFBLIOuYkOuKlCBwYXJlbnRJZCDsl5Tti7Dti7AgRks6IOyDneyEseuQnCBpZCDqsJLsnYQgSU5TRVJU7JeQIO2PrO2VqFxuICAgICAgICAgIHJvd1twcm9wTmFtZV0gPSBjb2x1bW4udmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgLy8gaW50ZWdlci9iaWdJbnRlZ2VyIFBLOiBEQiDsi5ztgIDsiqTsl5Ag66eh6rmAICjqsJIg7KCc7Jm4KVxuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzUmVsYXRpb25Qcm9wKHByb3ApKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBpc0JlbG9uZ3NUb09uZVJlbGF0aW9uUHJvcChwcm9wKSB8fFxuICAgICAgICAgIChpc09uZVRvT25lUmVsYXRpb25Qcm9wKHByb3ApICYmIHByb3AuaGFzSm9pbkNvbHVtbilcbiAgICAgICAgKSB7XG4gICAgICAgICAgY29uc3QgcmVsYXRlZElkID0gY29sdW1uLnZhbHVlIGFzIG51bWJlciB8IG51bGw7XG4gICAgICAgICAgaWYgKHJlbGF0ZWRJZCAhPT0gbnVsbCAmJiByZWxhdGVkSWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgY29uc3QgcmVsYXRlZEZpeHR1cmVJZCA9IGAke3Byb3Aud2l0aH0jJHtyZWxhdGVkSWR9YDtcblxuICAgICAgICAgICAgLy8g66i87KCAIHNraXDrkJwgZml4dHVyZeyduOyngCDtmZXsnbhcbiAgICAgICAgICAgIGNvbnN0IHNraXBwZWRFeGlzdGluZ0lkID0gdGhpcy5za2lwcGVkRml4dHVyZXMuZ2V0KHJlbGF0ZWRGaXh0dXJlSWQpPy5leGlzdGluZ0lkO1xuICAgICAgICAgICAgaWYgKHNraXBwZWRFeGlzdGluZ0lkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgLy8gc2tpcOuQnCBmaXh0dXJlIOKGkiB0YXJnZXQgRELsnZgg6riw7KG0IOugiOy9lOuTnCBpZCDsgqzsmqlcbiAgICAgICAgICAgICAgcm93W2Ake3Byb3BOYW1lfV9pZGBdID0gc2tpcHBlZEV4aXN0aW5nSWQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjb25zdCByZWxhdGVkUmVmID0gdGhpcy5maXh0dXJlUmVmTWFwLmdldChyZWxhdGVkRml4dHVyZUlkKTtcbiAgICAgICAgICAgICAgaWYgKHJlbGF0ZWRSZWYpIHtcbiAgICAgICAgICAgICAgICAvLyDsnbTrr7ggdXBzZXJ065CcIOqwmeydgCDthYzsnbTruJQgZml4dHVyZSDtmZXsnbhcbiAgICAgICAgICAgICAgICBjb25zdCByZWxhdGVkRW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQocHJvcC53aXRoKTtcbiAgICAgICAgICAgICAgICBjb25zdCByZWxhdGVkSW5zZXJ0ZWRJZHMgPSBpbnNlcnRlZElkc0J5VGFibGU/LmdldChyZWxhdGVkRW50aXR5LnRhYmxlKTtcbiAgICAgICAgICAgICAgICBjb25zdCBhY3R1YWxJZCA9IHJlbGF0ZWRJbnNlcnRlZElkcz8uZ2V0KHJlbGF0ZWRSZWYudXVpZCk7XG5cbiAgICAgICAgICAgICAgICBpZiAoYWN0dWFsSWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgLy8g7J2066+4IHVwc2VydOuQqCDihpIg7Iuk7KCcIElEIOyCrOyaqVxuICAgICAgICAgICAgICAgICAgcm93W2Ake3Byb3BOYW1lfV9pZGBdID0gYWN0dWFsSWQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIC8vIOyVhOyngSB1cHNlcnQg7JWI65CoIOKGkiBVQlJlZiDsgqzsmqlcbiAgICAgICAgICAgICAgICAgIHJvd1tgJHtwcm9wTmFtZX1faWRgXSA9IHJlbGF0ZWRSZWY7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIGZpeHR1cmVz7JeQIO2PrO2VqOuQmOyngCDslYrsnYAg66CI7L2U65OcIOKGkiBJRCDqt7jrjIDroZwg7IKs7JqpXG4gICAgICAgICAgICAgICAgcm93W2Ake3Byb3BOYW1lfV9pZGBdID0gcmVsYXRlZElkO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJvd1tgJHtwcm9wTmFtZX1faWRgXSA9IG51bGw7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIEhhc01hbnksIE1hbnlUb01hbnnripQg67OE64+EIOyymOumrFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8g7J2867CYIOy7rOufvFxuICAgICAgICByb3dbcHJvcE5hbWVdID0gdGhpcy5jb252ZXJ0Q29sdW1uVmFsdWUocHJvcCBhcyBFbnRpdHlQcm9wLCBjb2x1bW4udmFsdWUpO1xuICAgICAgfVxuICAgIH1cblxuICAgICFpc1Rlc3QoKSAmJlxuICAgICAgY29uc29sZS5sb2coY2hhbGsuYmx1ZShgUmVnaXN0ZXJpbmcgJHtlbnRpdHkudGFibGV9IC0gJHtpbnNwZWN0KHJvdywgZmFsc2UsIG51bGwsIHRydWUpfWApKTtcbiAgICBjb25zdCByZWYgPSB0aGlzLmJ1aWxkZXIucmVnaXN0ZXIoZW50aXR5LnRhYmxlLCByb3cpO1xuICAgIHRoaXMuZml4dHVyZVJlZk1hcC5zZXQoZml4dHVyZS5maXh0dXJlSWQsIHJlZik7XG5cbiAgICByZXR1cm4gcmVmO1xuICB9XG5cbiAgLyoqXG4gICAqIOy7rOufvCDqsJIg67OA7ZmYXG4gICAqL1xuICBwcml2YXRlIGNvbnZlcnRDb2x1bW5WYWx1ZShwcm9wOiBFbnRpdHlQcm9wLCB2YWx1ZTogdW5rbm93bik6IHVua25vd24ge1xuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBzd2l0Y2ggKHByb3AudHlwZSkge1xuICAgICAgY2FzZSBcImpzb25cIjpcbiAgICAgICAgLy8gVXBzZXJ0QnVpbGRlci5yZWdpc3RlcuyXkOyEnCBKU09OLnN0cmluZ2lmeSDsspjrpqztlZjrr4DroZwgb2JqZWN0IOq3uOuMgOuhnCDsoITri6xcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuXG4gICAgICBjYXNlIFwiZGF0ZVwiOlxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiIHx8IHR5cGVvZiB2YWx1ZSA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgIHJldHVybiBuZXcgRGF0ZSh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBwcm9jZXNzTWFueVRvTWFueVJlbGF0aW9ucyhcbiAgICB0cng6IEtuZXguVHJhbnNhY3Rpb24sXG4gICAgZml4dHVyZXM6IEZpeHR1cmVSZWNvcmRbXSxcbiAgICBpbnNlcnRlZElkc0J5VGFibGU6IE1hcDxzdHJpbmcsIE1hcDxzdHJpbmcsIG51bWJlciB8IHN0cmluZz4+LFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBmb3IgKGNvbnN0IGZpeHR1cmUgb2YgZml4dHVyZXMpIHtcbiAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGZpeHR1cmUuZW50aXR5SWQpO1xuICAgICAgY29uc3Qgc291cmNlUmVmID0gdGhpcy5maXh0dXJlUmVmTWFwLmdldChmaXh0dXJlLmZpeHR1cmVJZCk7XG5cbiAgICAgIGlmICghc291cmNlUmVmKSBjb250aW51ZTtcblxuICAgICAgY29uc3Qgc291cmNlVXVpZFRvSWQgPSBpbnNlcnRlZElkc0J5VGFibGUuZ2V0KGVudGl0eS50YWJsZSk7XG4gICAgICBjb25zdCBzb3VyY2VJZCA9IHNvdXJjZVV1aWRUb0lkPy5nZXQoc291cmNlUmVmLnV1aWQpO1xuXG4gICAgICBpZiAoc291cmNlSWQgPT09IHVuZGVmaW5lZCkgY29udGludWU7XG5cbiAgICAgIGZvciAoY29uc3QgWywgY29sdW1uXSBvZiBPYmplY3QuZW50cmllcyhmaXh0dXJlLmNvbHVtbnMpKSB7XG4gICAgICAgIGNvbnN0IHByb3AgPSBjb2x1bW4ucHJvcDtcblxuICAgICAgICBpZiAoaXNNYW55VG9NYW55UmVsYXRpb25Qcm9wKHByb3ApICYmIEFycmF5LmlzQXJyYXkoY29sdW1uLnZhbHVlKSkge1xuICAgICAgICAgIC8vIOyEoO2DneuQmOyngCDslYrsnYAgTWFueVRvTWFueSDqtIDqs4TripQg7KCA7J6l7ZWY7KeAIOyViuydjFxuICAgICAgICAgIGNvbnN0IHRhcmdldFRhYmxlID0gRW50aXR5TWFuYWdlci5nZXQocHJvcC53aXRoKTtcbiAgICAgICAgICBpZiAoIXRoaXMuYnVpbGRlci5oYXNUYWJsZSh0YXJnZXRUYWJsZS50YWJsZSkpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgY29uc3QgcmVsYXRlZElkcyA9IGNvbHVtbi52YWx1ZSBhcyBudW1iZXJbXTtcbiAgICAgICAgICBpZiAocmVsYXRlZElkcy5sZW5ndGggPT09IDApIGNvbnRpbnVlO1xuXG4gICAgICAgICAgY29uc3Qgam9pblRhYmxlID0gcHJvcC5qb2luVGFibGU7XG4gICAgICAgICAgY29uc3QgcmVsYXRlZEVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KHByb3Aud2l0aCk7XG5cbiAgICAgICAgICBjb25zdCBzb3VyY2VDb2x1bW4gPSBgJHtpbmZsZWN0aW9uLnNpbmd1bGFyaXplKGVudGl0eS50YWJsZSl9X2lkYDtcbiAgICAgICAgICBjb25zdCB0YXJnZXRDb2x1bW4gPSBgJHtpbmZsZWN0aW9uLnNpbmd1bGFyaXplKHJlbGF0ZWRFbnRpdHkudGFibGUpfV9pZGA7XG5cbiAgICAgICAgICBmb3IgKGNvbnN0IHJlbGF0ZWRJZCBvZiByZWxhdGVkSWRzKSB7XG4gICAgICAgICAgICBjb25zdCByZWxhdGVkRml4dHVyZUlkID0gYCR7cHJvcC53aXRofSMke3JlbGF0ZWRJZH1gO1xuICAgICAgICAgICAgY29uc3QgcmVsYXRlZFJlZiA9IHRoaXMuZml4dHVyZVJlZk1hcC5nZXQocmVsYXRlZEZpeHR1cmVJZCk7XG5cbiAgICAgICAgICAgIGxldCB0YXJnZXRJZDogbnVtYmVyIHwgc3RyaW5nO1xuXG4gICAgICAgICAgICBpZiAocmVsYXRlZFJlZikge1xuICAgICAgICAgICAgICBjb25zdCByZWxhdGVkVXVpZFRvSWQgPSBpbnNlcnRlZElkc0J5VGFibGUuZ2V0KHJlbGF0ZWRFbnRpdHkudGFibGUpO1xuICAgICAgICAgICAgICBjb25zdCByZXNvbHZlZElkID0gcmVsYXRlZFV1aWRUb0lkPy5nZXQocmVsYXRlZFJlZi51dWlkKTtcblxuICAgICAgICAgICAgICBpZiAocmVzb2x2ZWRJZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICAgICAgICAgYFJlbGF0ZWQgZml4dHVyZSAke3JlbGF0ZWRGaXh0dXJlSWR9IG5vdCBmb3VuZCBpbiBpbnNlcnRlZElkcywgc2tpcHBpbmdgLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgdGFyZ2V0SWQgPSByZXNvbHZlZElkO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGFyZ2V0SWQgPSByZWxhdGVkSWQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEpvaW5UYWJsZeyXkCDsgr3snoVcbiAgICAgICAgICAgIGNvbnN0IFtmb3VuZF0gPSBhd2FpdCB0cngoam9pblRhYmxlKVxuICAgICAgICAgICAgICAud2hlcmUoe1xuICAgICAgICAgICAgICAgIFtzb3VyY2VDb2x1bW5dOiBzb3VyY2VJZCxcbiAgICAgICAgICAgICAgICBbdGFyZ2V0Q29sdW1uXTogdGFyZ2V0SWQsXG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgIC5saW1pdCgxKTtcblxuICAgICAgICAgICAgaWYgKCFmb3VuZCkge1xuICAgICAgICAgICAgICBhd2FpdCB0cngoam9pblRhYmxlKS5pbnNlcnQoe1xuICAgICAgICAgICAgICAgIFtzb3VyY2VDb2x1bW5dOiBzb3VyY2VJZCxcbiAgICAgICAgICAgICAgICBbdGFyZ2V0Q29sdW1uXTogdGFyZ2V0SWQsXG4gICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICFpc1Rlc3QoKSAmJlxuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgICAgICAgY2hhbGsuZ3JlZW4oXG4gICAgICAgICAgICAgICAgICAgIGBJbnNlcnRlZCBpbnRvICR7am9pblRhYmxlfTogJHtlbnRpdHkudGFibGV9KCR7c291cmNlSWR9KSAtICR7cmVsYXRlZEVudGl0eS50YWJsZX0oJHt0YXJnZXRJZH0pYCxcbiAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICog6rCZ7J2AIO2FjOydtOu4lCDrgrQgZml4dHVyZeuTpOydhCBzZWxmLXJlZmVyZW5jZSDroIjrsqjrs4TroZwg67aE7ZWgXG4gICAqIC0gc2VsZi1yZWZlcmVuY2XqsIAg7JeG64qUIGZpeHR1cmXrk6Q6IExldmVsIDBcbiAgICogLSBMZXZlbCAw7J2EIOywuOyhsO2VmOuKlCBmaXh0dXJl65OkOiBMZXZlbCAxXG4gICAqIC0g67CY67O1XG4gICAqXG4gICAqIFVwc2VydEJ1aWxkZXLqsIAgc2VsZi1yZWZlcmVuY2XqsIAg7J6I7Jy866m0IGJ1aWxkSW5zZXJ0TGV2ZWxzKCnroZwg7J6s7KCV66Cs7ZWY7JesXG4gICAqIOuTseuhnSDsiJzshJzsmYAg67CY7ZmYIOyInOyEnOqwgCDri6zrnbzsp4gg7IiYIOyeiOyKteuLiOuLpC5cbiAgICog7J2066W8IOuwqeyngO2VmOq4sCDsnITtlbQgRml4dHVyZU1hbmFnZXLqsIAg66CI67Ko67OE66GcIOuCmOuIoOyEnCDsspjrpqztlanri4jri6QuXG4gICAqL1xuICBwcml2YXRlIGdyb3VwRml4dHVyZXNCeUxldmVsKGZpeHR1cmVzOiBGaXh0dXJlUmVjb3JkW10pOiBGaXh0dXJlUmVjb3JkW11bXSB7XG4gICAgaWYgKGZpeHR1cmVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGZpeHR1cmVzWzBdLmVudGl0eUlkKTtcblxuICAgIC8vIHNlbGYtcmVmZXJlbmNlIHJlbGF0aW9uIHByb3Ag7LC+6riwXG4gICAgY29uc3Qgc2VsZlJlZlByb3BzID0gZW50aXR5LnByb3BzLmZpbHRlcihcbiAgICAgIChwKTogcCBpcyBCZWxvbmdzVG9PbmVSZWxhdGlvblByb3AgfCBPbmVUb09uZVJlbGF0aW9uUHJvcCA9PlxuICAgICAgICBpc1JlbGF0aW9uUHJvcChwKSAmJlxuICAgICAgICAoaXNCZWxvbmdzVG9PbmVSZWxhdGlvblByb3AocCkgfHwgKGlzT25lVG9PbmVSZWxhdGlvblByb3AocCkgJiYgcC5oYXNKb2luQ29sdW1uKSkgJiZcbiAgICAgICAgcC53aXRoID09PSBlbnRpdHkuaWQsXG4gICAgKTtcblxuICAgIGlmIChzZWxmUmVmUHJvcHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAvLyBzZWxmLXJlZmVyZW5jZSDsl4bsnYwg4oaSIOuLqOydvCDroIjrsqhcbiAgICAgIHJldHVybiBbZml4dHVyZXNdO1xuICAgIH1cblxuICAgIC8vIOugiOuyqOuzhCDrtoTtlaAgKHRvcG9sb2dpY2FsIHNvcnQpXG4gICAgY29uc3QgbGV2ZWxzOiBGaXh0dXJlUmVjb3JkW11bXSA9IFtdO1xuICAgIGNvbnN0IHJlbWFpbmluZyA9IG5ldyBTZXQoZml4dHVyZXMubWFwKChmKSA9PiBmLmZpeHR1cmVJZCkpO1xuICAgIGNvbnN0IHByb2Nlc3NlZCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gICAgd2hpbGUgKHJlbWFpbmluZy5zaXplID4gMCkge1xuICAgICAgY29uc3QgY3VycmVudExldmVsOiBGaXh0dXJlUmVjb3JkW10gPSBbXTtcblxuICAgICAgZm9yIChjb25zdCBmaXh0dXJlIG9mIGZpeHR1cmVzKSB7XG4gICAgICAgIGlmICghcmVtYWluaW5nLmhhcyhmaXh0dXJlLmZpeHR1cmVJZCkpIGNvbnRpbnVlO1xuXG4gICAgICAgIC8vIHNlbGYtcmVmZXJlbmNl6rCAIOuqqOuRkCDsnbTrr7gg7LKY66as65CQ6rGw64KYIG51bGzsnbgg6rK97JqwXG4gICAgICAgIGNvbnN0IGNhblByb2Nlc3MgPSBzZWxmUmVmUHJvcHMuZXZlcnkoKHByb3ApID0+IHtcbiAgICAgICAgICBjb25zdCByZWZJZCA9IGZpeHR1cmUuY29sdW1uc1twcm9wLm5hbWVdPy52YWx1ZSBhcyBudW1iZXIgfCBudWxsO1xuICAgICAgICAgIGlmIChyZWZJZCA9PT0gbnVsbCB8fCByZWZJZCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICBjb25zdCByZWZGaXh0dXJlSWQgPSBgJHtwcm9wLndpdGh9IyR7cmVmSWR9YDtcbiAgICAgICAgICAvLyDsnbTrr7gg7LKY66as65CQ6rGw64KYLCDtmITsnqwgZml4dHVyZXPsl5Ag7Y+s7ZWo65CY7KeAIOyViuydgCDqsr3smrAgKOyZuOu2gCDssLjsobApXG4gICAgICAgICAgcmV0dXJuIHByb2Nlc3NlZC5oYXMocmVmRml4dHVyZUlkKSB8fCAhcmVtYWluaW5nLmhhcyhyZWZGaXh0dXJlSWQpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoY2FuUHJvY2Vzcykge1xuICAgICAgICAgIGN1cnJlbnRMZXZlbC5wdXNoKGZpeHR1cmUpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjdXJyZW50TGV2ZWwubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGNvbnN0IHJlbWFpbmluZ0lkcyA9IEFycmF5LmZyb20ocmVtYWluaW5nKS5qb2luKFwiLCBcIik7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgQ2lyY3VsYXIgc2VsZi1yZWZlcmVuY2UgZGV0ZWN0ZWQgaW4gJHtlbnRpdHkudGFibGV9LiBSZW1haW5pbmcgZml4dHVyZXM6ICR7cmVtYWluaW5nSWRzfWAsXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGZvciAoY29uc3QgZml4dHVyZSBvZiBjdXJyZW50TGV2ZWwpIHtcbiAgICAgICAgcmVtYWluaW5nLmRlbGV0ZShmaXh0dXJlLmZpeHR1cmVJZCk7XG4gICAgICAgIHByb2Nlc3NlZC5hZGQoZml4dHVyZS5maXh0dXJlSWQpO1xuICAgICAgfVxuXG4gICAgICBsZXZlbHMucHVzaChjdXJyZW50TGV2ZWwpO1xuICAgIH1cblxuICAgIHJldHVybiBsZXZlbHM7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNoZWNrVW5pcXVlVmlvbGF0aW9uKGRiOiBLbmV4LCBlbnRpdHk6IEVudGl0eSwgZml4dHVyZTogRml4dHVyZVJlY29yZCkge1xuICAgIGNvbnN0IF91bmlxdWVJbmRleGVzID0gZW50aXR5LmluZGV4ZXM/LmZpbHRlcigoaSkgPT4gaS50eXBlID09PSBcInVuaXF1ZVwiKSA/PyBbXTtcblxuICAgIGNvbnN0IHVuaXF1ZUluZGV4ZXMgPSBfdW5pcXVlSW5kZXhlcy5maWx0ZXIoKGluZGV4KSA9PlxuICAgICAgaW5kZXguY29sdW1ucy5ldmVyeSgoY29sdW1uKSA9PiAhY29sdW1uLm5hbWUuc3RhcnRzV2l0aChgJHtlbnRpdHkudGFibGV9X19gKSksXG4gICAgKTtcbiAgICBpZiAodW5pcXVlSW5kZXhlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGxldCB1bmlxdWVRdWVyeSA9IGRiKGVudGl0eS50YWJsZSk7XG4gICAgbGV0IGhhc0NvbmRpdGlvbiA9IGZhbHNlO1xuXG4gICAgZm9yIChjb25zdCBpbmRleCBvZiB1bmlxdWVJbmRleGVzKSB7XG4gICAgICAvLyDsu6zrn7wg7KSRIO2VmOuCmOudvOuPhCBudWxs7J2066m0IOycoOuLiO2BrCDsoJzslb3snYQg7JyE67CY7ZWY7KeAIOyViuq4sCDrlYzrrLjsl5Ag7ZW064u5IOyduOuNseyKpOuKlCDrrLTsi5xcbiAgICAgIGNvbnN0IGNvbnRhaW5zTnVsbCA9IGluZGV4LmNvbHVtbnMuc29tZSgoY29sdW1uKSA9PiB7XG4gICAgICAgIGNvbnN0IGZpZWxkID0gY29sdW1uLm5hbWUucmVwbGFjZSgvX2lkJC8sIFwiXCIpO1xuICAgICAgICByZXR1cm4gZml4dHVyZS5jb2x1bW5zW2ZpZWxkXT8udmFsdWUgPT09IG51bGw7XG4gICAgICB9KTtcbiAgICAgIGlmIChjb250YWluc051bGwpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIHVuaXF1ZVF1ZXJ5ID0gdW5pcXVlUXVlcnkub3JXaGVyZSgocWIpID0+IHtcbiAgICAgICAgZm9yIChjb25zdCBjb2x1bW4gb2YgaW5kZXguY29sdW1ucykge1xuICAgICAgICAgIGNvbnN0IGZpZWxkID0gY29sdW1uLm5hbWUucmVwbGFjZSgvX2lkJC8sIFwiXCIpO1xuXG4gICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZml4dHVyZS5jb2x1bW5zW2ZpZWxkXT8udmFsdWUpKSB7XG4gICAgICAgICAgICBxYi53aGVyZUluKGNvbHVtbi5uYW1lLCBmaXh0dXJlLmNvbHVtbnNbZmllbGRdLnZhbHVlKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcWIuYW5kV2hlcmUoY29sdW1uLm5hbWUsIGZpeHR1cmUuY29sdW1uc1tmaWVsZF0/LnZhbHVlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgaGFzQ29uZGl0aW9uID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAoIWhhc0NvbmRpdGlvbikge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgY29uc3QgW3VuaXF1ZUZvdW5kXSA9IGF3YWl0IHVuaXF1ZVF1ZXJ5O1xuICAgIHJldHVybiB1bmlxdWVGb3VuZDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgY2hlY2tEdXBsaWNhdGVCeUNvbHVtbnMoXG4gICAgZGI6IEtuZXgsXG4gICAgZW50aXR5OiBFbnRpdHksXG4gICAgZml4dHVyZTogRml4dHVyZVJlY29yZCxcbiAgICBjb2x1bW5zOiBzdHJpbmdbXSxcbiAgKSB7XG4gICAgaWYgKGNvbHVtbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCB3aGVyZUNsYXVzZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fTtcblxuICAgIGZvciAoY29uc3QgY29sdW1uIG9mIGNvbHVtbnMpIHtcbiAgICAgIC8vIHJlbGF0aW9uIO2VhOuTnOyduCDqsr3smrAgX2lkIOu2meydtOq4sFxuICAgICAgY29uc3QgcHJvcCA9IGVudGl0eS5wcm9wcy5maW5kKChwKSA9PiBwLm5hbWUgPT09IGNvbHVtbik7XG4gICAgICBjb25zdCBkYkNvbHVtbiA9IHByb3AgJiYgaXNSZWxhdGlvblByb3AocHJvcCkgPyBgJHtjb2x1bW59X2lkYCA6IGNvbHVtbjtcbiAgICAgIGNvbnN0IHZhbHVlID0gZml4dHVyZS5jb2x1bW5zW2NvbHVtbl0/LnZhbHVlO1xuXG4gICAgICAvLyBudWxsIOqwkuydtCDtj6ztlajrkJwg6rK97JqwIOykkeuztSDtmZXsnbgg7Iqk7YK1XG4gICAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cblxuICAgICAgd2hlcmVDbGF1c2VbZGJDb2x1bW5dID0gdmFsdWU7XG4gICAgfVxuXG4gICAgY29uc3QgW2ZvdW5kXSA9IGF3YWl0IGRiKGVudGl0eS50YWJsZSkud2hlcmUod2hlcmVDbGF1c2UpLmxpbWl0KDEpO1xuICAgIHJldHVybiBmb3VuZDtcbiAgfVxuXG4gIGFzeW5jIGFkZEZpeHR1cmVMb2FkZXIoY29kZTogc3RyaW5nKSB7XG4gICAgY29uc3QgcGF0aCA9IGAke1NvbmFtdS5hcGlSb290UGF0aH0vc3JjL3Rlc3RpbmcvZml4dHVyZS50c2A7XG4gICAgY29uc3QgY29udGVudCA9IHJlYWRGaWxlU3luYyhwYXRoKS50b1N0cmluZygpO1xuXG4gICAgY29uc3QgZml4dHVyZUxvYWRlclN0YXJ0ID0gY29udGVudC5pbmRleE9mKFwiY29uc3QgZml4dHVyZUxvYWRlciA9IHtcIik7XG4gICAgY29uc3QgZml4dHVyZUxvYWRlckVuZCA9IGNvbnRlbnQuaW5kZXhPZihcIn07XCIsIGZpeHR1cmVMb2FkZXJTdGFydCk7XG5cbiAgICBpZiAoZml4dHVyZUxvYWRlclN0YXJ0ICE9PSAtMSAmJiBmaXh0dXJlTG9hZGVyRW5kICE9PSAtMSkge1xuICAgICAgY29uc3QgbmV3Q29udGVudCA9IGAke2NvbnRlbnQuc2xpY2UoMCwgZml4dHVyZUxvYWRlckVuZCl9ICAke2NvZGV9XFxuJHtjb250ZW50LnNsaWNlKGZpeHR1cmVMb2FkZXJFbmQpfWA7XG5cbiAgICAgIHdyaXRlRmlsZVN5bmMocGF0aCwgbmV3Q29udGVudCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkZhaWxlZCB0byBmaW5kIGZpeHR1cmVMb2FkZXIgaW4gZml4dHVyZS50c1wiKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IEZpeHR1cmVNYW5hZ2VyID0gbmV3IEZpeHR1cmVNYW5hZ2VyQ2xhc3MoKTtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7OzthQVVzQztpQkFDWTtXQUVHO3FCQUNLO3FCQUdGO1lBUWpDO2lC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
|