sonamu 0.9.19 → 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 +7 -7
- 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/entity-basic.md +31 -0
- package/src/skills/sonamu/puri.md +22 -0
- package/src/skills/sonamu/testing-devrunner.md +1 -1
- package/src/skills/sonamu/upsert.md +53 -6
- 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,9 +1,10 @@
|
|
|
1
|
-
import { __esmMin } from "../_virtual/
|
|
1
|
+
import { __esmMin } from "../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { getSonamuEnvironment, init_env } from "../env.js";
|
|
2
3
|
import { createKnexInstance, init_knex } from "../database/knex.js";
|
|
3
4
|
import { DB, init_db } from "../database/db.js";
|
|
4
5
|
import { SD, init_sd } from "../dict/sd.js";
|
|
5
6
|
import { ServiceUnavailableException, init_so_exceptions } from "../exceptions/so-exceptions.js";
|
|
6
|
-
import { init_controller, isTest } from "../utils/controller.js";
|
|
7
|
+
import { init_controller, isLocal, isTest } from "../utils/controller.js";
|
|
7
8
|
import { exists, init_fs_utils } from "../utils/fs-utils.js";
|
|
8
9
|
import { Sonamu, init_sonamu } from "../api/sonamu.js";
|
|
9
10
|
import { EntityManager, init_entity_manager } from "../entity/entity-manager.js";
|
|
@@ -13,10 +14,9 @@ import { generateAlterCode, generateCreateCode, init_code_generation } from "./c
|
|
|
13
14
|
import { getMigrationSetFromEntity, init_migration_set } from "./migration-set.js";
|
|
14
15
|
import { group, sum, unique } from "radashi";
|
|
15
16
|
import assert from "assert";
|
|
16
|
-
import { mkdir, readdir, unlink, writeFile } from "fs/promises";
|
|
17
17
|
import path from "path";
|
|
18
|
+
import { mkdir, readdir, unlink, writeFile } from "fs/promises";
|
|
18
19
|
import chalk from "chalk";
|
|
19
|
-
|
|
20
20
|
//#region src/migration/migrator.ts
|
|
21
21
|
var Migrator;
|
|
22
22
|
var init_migrator = __esmMin((() => {
|
|
@@ -25,6 +25,7 @@ var init_migrator = __esmMin((() => {
|
|
|
25
25
|
init_knex();
|
|
26
26
|
init_sd();
|
|
27
27
|
init_entity_manager();
|
|
28
|
+
init_env();
|
|
28
29
|
init_so_exceptions();
|
|
29
30
|
init_naite();
|
|
30
31
|
init_controller();
|
|
@@ -33,6 +34,17 @@ var init_migrator = __esmMin((() => {
|
|
|
33
34
|
init_migration_set();
|
|
34
35
|
init_postgresql_schema_reader();
|
|
35
36
|
Migrator = class {
|
|
37
|
+
isMissingMigrationTableError(error) {
|
|
38
|
+
if (typeof error !== "object" || error === null) return false;
|
|
39
|
+
const maybePostgresError = error;
|
|
40
|
+
return maybePostgresError.code === "42P01" && typeof maybePostgresError.message === "string" && maybePostgresError.message.includes("knex_migrations");
|
|
41
|
+
}
|
|
42
|
+
getMigrationTargetKeys() {
|
|
43
|
+
const connKeys = Object.keys(Sonamu.dbConfig).filter((key) => !key.endsWith("_readonly"));
|
|
44
|
+
if (isLocal()) return connKeys;
|
|
45
|
+
const environment = getSonamuEnvironment();
|
|
46
|
+
return connKeys.filter((key) => key === environment);
|
|
47
|
+
}
|
|
36
48
|
async runMigrationsSequentially(conns, action) {
|
|
37
49
|
const results = [];
|
|
38
50
|
for (const { connKey, knex } of conns) {
|
|
@@ -47,9 +59,7 @@ var init_migrator = __esmMin((() => {
|
|
|
47
59
|
}
|
|
48
60
|
async getMigrationCodes() {
|
|
49
61
|
const srcMigrationsDir = path.join(Sonamu.apiRootPath, "src", "migrations");
|
|
50
|
-
if (!await exists(srcMigrationsDir)) {
|
|
51
|
-
await mkdir(srcMigrationsDir, { recursive: true });
|
|
52
|
-
}
|
|
62
|
+
if (!await exists(srcMigrationsDir)) await mkdir(srcMigrationsDir, { recursive: true });
|
|
53
63
|
const codes = (await readdir(srcMigrationsDir)).filter((f) => f.endsWith(".ts")).map((f) => ({
|
|
54
64
|
name: f.replace(".ts", ""),
|
|
55
65
|
path: path.join(srcMigrationsDir, f)
|
|
@@ -69,7 +79,7 @@ var init_migrator = __esmMin((() => {
|
|
|
69
79
|
async getStatus() {
|
|
70
80
|
const codes = await this.getMigrationCodes();
|
|
71
81
|
Naite.t("migrator:getStatus:codes", codes);
|
|
72
|
-
const connKeys =
|
|
82
|
+
const connKeys = this.getMigrationTargetKeys();
|
|
73
83
|
let migrationStatusError;
|
|
74
84
|
const statuses = await Promise.all(connKeys.map(async (connKey) => {
|
|
75
85
|
const knexOptions = Sonamu.dbConfig[connKey];
|
|
@@ -79,6 +89,7 @@ var init_migrator = __esmMin((() => {
|
|
|
79
89
|
try {
|
|
80
90
|
return await tConn.migrate.status();
|
|
81
91
|
} catch (err) {
|
|
92
|
+
if (this.isMissingMigrationTableError(err)) return codes.length;
|
|
82
93
|
console.warn(chalk.yellow(`${connKey}의 마이그레이션 상태를 가져오는 데에 실패하였습니다. 데이터베이스가 올바르게 구성되지 않은 것 같습니다. 확인하시고 다시 시도해주세요.\n시도한 연결 설정:\n${JSON.stringify(knexOptions.connection, null, 2)}\n발생한 에러:\n${err}\n`));
|
|
83
94
|
migrationStatusError = err instanceof Error ? err.message : String(err);
|
|
84
95
|
return "error";
|
|
@@ -89,6 +100,7 @@ var init_migrator = __esmMin((() => {
|
|
|
89
100
|
const [, fdList] = await tConn.migrate.list();
|
|
90
101
|
return fdList.map((fd) => fd.file.replace(".ts", ""));
|
|
91
102
|
} catch (err) {
|
|
103
|
+
if (this.isMissingMigrationTableError(err)) return codes.map((code) => code.name);
|
|
92
104
|
migrationStatusError = err instanceof Error ? err.message : String(err);
|
|
93
105
|
return [];
|
|
94
106
|
}
|
|
@@ -97,6 +109,7 @@ var init_migrator = __esmMin((() => {
|
|
|
97
109
|
try {
|
|
98
110
|
return await tConn.migrate.currentVersion();
|
|
99
111
|
} catch (_err) {
|
|
112
|
+
if (this.isMissingMigrationTableError(_err)) return "none";
|
|
100
113
|
migrationStatusError = _err instanceof Error ? _err.message : String(_err);
|
|
101
114
|
return "error";
|
|
102
115
|
}
|
|
@@ -104,7 +117,7 @@ var init_migrator = __esmMin((() => {
|
|
|
104
117
|
Naite.t("migrator:getStatus:status", status);
|
|
105
118
|
const connection = knexOptions.connection;
|
|
106
119
|
return {
|
|
107
|
-
name: connKey
|
|
120
|
+
name: connKey,
|
|
108
121
|
connKey,
|
|
109
122
|
connString: `pg://${connection.user ?? ""}@${connection.host}:${connection.port}/${connection.database}`,
|
|
110
123
|
currentVersion,
|
|
@@ -118,7 +131,7 @@ var init_migrator = __esmMin((() => {
|
|
|
118
131
|
Naite.t("migrator:getStatus:conns", statuses);
|
|
119
132
|
const preparedCodes = await (async () => {
|
|
120
133
|
const status0conn = statuses.find((status) => status.status === 0);
|
|
121
|
-
if (status0conn ===
|
|
134
|
+
if (status0conn === void 0) {
|
|
122
135
|
console.warn(chalk.yellow(`While trying to prepare migration codes, we found that there is no database to compare migrations. We need at least one database where every migration is applied(status === 0). You might want to apply your existing migrations to one of the databases.`));
|
|
123
136
|
return [];
|
|
124
137
|
}
|
|
@@ -150,10 +163,13 @@ var init_migrator = __esmMin((() => {
|
|
|
150
163
|
async runAction(action, targets) {
|
|
151
164
|
Naite.t("migrator:runAction:action", action);
|
|
152
165
|
Naite.t("migrator:runAction:targets", targets);
|
|
166
|
+
const allowedTargets = new Set(this.getMigrationTargetKeys());
|
|
167
|
+
const disallowedTargets = targets.filter((target) => !allowedTargets.has(target));
|
|
168
|
+
if (disallowedTargets.length > 0) throw new Error(`Migration targets are not allowed in NODE_ENV=${getSonamuEnvironment()}: ${disallowedTargets.join(", ")}`);
|
|
153
169
|
const configs = unique(targets.map((target) => ({
|
|
154
170
|
connKey: target,
|
|
155
171
|
options: Sonamu.dbConfig[target]
|
|
156
|
-
})).filter((c) => c.options !==
|
|
172
|
+
})).filter((c) => c.options !== void 0), ({ options }) => `${options.connection.host}:${options.connection.port ?? 5432}/${options.connection.database}`);
|
|
157
173
|
const conns = await Promise.all(configs.map(async (config) => ({
|
|
158
174
|
connKey: config.connKey,
|
|
159
175
|
knex: createKnexInstance(config.options)
|
|
@@ -198,9 +214,7 @@ var init_migrator = __esmMin((() => {
|
|
|
198
214
|
async delCodes(codeNames) {
|
|
199
215
|
const { conns } = await this.getStatus();
|
|
200
216
|
const { canDelete, appliedCodes } = this.validateDeletable(conns, codeNames);
|
|
201
|
-
if (!canDelete) {
|
|
202
|
-
throw new Error(`You cannot delete a migration file if there is already applied. Applied codes: ${appliedCodes.join(", ")}`);
|
|
203
|
-
}
|
|
217
|
+
if (!canDelete) throw new Error(`You cannot delete a migration file if there is already applied. Applied codes: ${appliedCodes.join(", ")}`);
|
|
204
218
|
return sum(await Promise.all(codeNames.map(async (codeName) => {
|
|
205
219
|
const filePath = `${Sonamu.apiRootPath}/src/migrations/${codeName}.ts`;
|
|
206
220
|
if (await exists(filePath)) {
|
|
@@ -210,7 +224,7 @@ var init_migrator = __esmMin((() => {
|
|
|
210
224
|
return 0;
|
|
211
225
|
})));
|
|
212
226
|
}
|
|
213
|
-
genDateTag(index, baseDate = new Date()) {
|
|
227
|
+
genDateTag(index, baseDate = /* @__PURE__ */ new Date()) {
|
|
214
228
|
const date = new Date(baseDate.getTime() + index * 1e3);
|
|
215
229
|
const pad = (num, size = 2) => num.toString().padStart(size, "0");
|
|
216
230
|
return date.getFullYear().toString() + pad(date.getMonth() + 1) + pad(date.getDate()) + pad(date.getHours()) + pad(date.getMinutes()) + pad(date.getSeconds());
|
|
@@ -230,49 +244,41 @@ var init_migrator = __esmMin((() => {
|
|
|
230
244
|
return 0;
|
|
231
245
|
}
|
|
232
246
|
const migrationsDir = `${Sonamu.apiRootPath}/src/migrations`;
|
|
233
|
-
for (const [index, pcode] of preparedCodes.entries()) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
await writeFile(filePath, pcode.formatted);
|
|
238
|
-
!isTest() && console.log(chalk.green(`MIGRATION CREATED ${filePath}`));
|
|
239
|
-
}
|
|
247
|
+
for (const [index, pcode] of preparedCodes.entries()) if (pcode.formatted) {
|
|
248
|
+
const filePath = `${migrationsDir}/${this.genDateTag(index)}_${pcode.title}.ts`;
|
|
249
|
+
await writeFile(filePath, pcode.formatted);
|
|
250
|
+
!isTest() && console.log(chalk.green(`MIGRATION CREATED ${filePath}`));
|
|
240
251
|
}
|
|
241
252
|
return preparedCodes.length;
|
|
242
253
|
}
|
|
243
254
|
async compareMigrations(compareDB) {
|
|
244
|
-
const
|
|
245
|
-
const entitySetsWithJoinTable = entityIds.filter((entityId) => EntityManager.get(entityId).props.length > 0).map((entityId) => getMigrationSetFromEntity(EntityManager.get(entityId)));
|
|
255
|
+
const entitySetsWithJoinTable = EntityManager.getAllIds().filter((entityId) => EntityManager.get(entityId).props.length > 0).map((entityId) => getMigrationSetFromEntity(EntityManager.get(entityId)));
|
|
246
256
|
const joinTablesWithDup = entitySetsWithJoinTable.flatMap((entitySet) => entitySet.joinTables);
|
|
247
257
|
const joinTables = Object.values(group(joinTablesWithDup, (jt) => jt.table)).map((tables) => {
|
|
248
|
-
assert(tables !==
|
|
249
|
-
if (tables.length === 1)
|
|
250
|
-
return tables[0];
|
|
251
|
-
}
|
|
258
|
+
assert(tables !== void 0, "tables is undefined");
|
|
259
|
+
if (tables.length === 1) return tables[0];
|
|
252
260
|
return {
|
|
253
261
|
...tables[0],
|
|
254
262
|
indexes: unique(tables.flatMap((t) => t.indexes), (index) => [index.type, ...index.columns].join("-"))
|
|
255
263
|
};
|
|
256
264
|
});
|
|
257
265
|
const entitySets = [...entitySetsWithJoinTable, ...joinTables];
|
|
258
|
-
const codes =
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
return await
|
|
266
|
-
|
|
267
|
-
|
|
266
|
+
const codes = [];
|
|
267
|
+
const batchSize = 4;
|
|
268
|
+
for (let i = 0; i < entitySets.length; i += batchSize) {
|
|
269
|
+
const batchCodes = await Promise.all(entitySets.slice(i, i + batchSize).map(async (entitySet) => {
|
|
270
|
+
const dbSet = await PostgreSQLSchemaReader.getMigrationSetFromDB(compareDB, entitySet.table);
|
|
271
|
+
Naite.t(`migrator:compareMigrations:entitySet:${entitySet.table}`, entitySet);
|
|
272
|
+
Naite.t(`migrator:compareMigrations:dbSet:${entitySet.table}`, dbSet);
|
|
273
|
+
if (dbSet === null) return await generateCreateCode(entitySet);
|
|
274
|
+
else return await generateAlterCode(entitySet, dbSet, compareDB);
|
|
275
|
+
}));
|
|
276
|
+
codes.push(...batchCodes.flat());
|
|
277
|
+
}
|
|
268
278
|
codes.sort((codeA, codeB) => {
|
|
269
|
-
if (codeA.type === "foreign" && codeB.type === "normal")
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
return -1;
|
|
273
|
-
} else {
|
|
274
|
-
return 0;
|
|
275
|
-
}
|
|
279
|
+
if (codeA.type === "foreign" && codeB.type === "normal") return 1;
|
|
280
|
+
else if (codeA.type === "normal" && codeB.type === "foreign") return -1;
|
|
281
|
+
else return 0;
|
|
276
282
|
});
|
|
277
283
|
return codes;
|
|
278
284
|
}
|
|
@@ -284,15 +290,25 @@ var init_migrator = __esmMin((() => {
|
|
|
284
290
|
* @returns Shadow DB 테스트 결과
|
|
285
291
|
*/
|
|
286
292
|
async runShadowTest() {
|
|
287
|
-
const
|
|
288
|
-
const
|
|
293
|
+
const baseTestConn = Sonamu.dbConfig.test.connection;
|
|
294
|
+
const workerId = process.env.SONAMU_WORKER_DB === "true" ? process.env.VITEST_POOL_ID : null;
|
|
295
|
+
const templateDatabase = workerId !== null ? `${baseTestConn.database}_${workerId ?? "1"}` : baseTestConn.database;
|
|
296
|
+
const tdbConn = {
|
|
297
|
+
...baseTestConn,
|
|
298
|
+
database: templateDatabase
|
|
299
|
+
};
|
|
300
|
+
const shadowDatabase = `${templateDatabase}__migration_shadow`;
|
|
289
301
|
if (isTest()) {
|
|
290
302
|
await DB.clearTestTransaction();
|
|
291
|
-
|
|
292
|
-
await DB.destroy();
|
|
293
|
-
}
|
|
303
|
+
await DB.destroy();
|
|
294
304
|
}
|
|
295
|
-
const tdb = createKnexInstance(
|
|
305
|
+
const tdb = createKnexInstance({
|
|
306
|
+
...Sonamu.dbConfig.test,
|
|
307
|
+
connection: {
|
|
308
|
+
...baseTestConn,
|
|
309
|
+
database: "postgres"
|
|
310
|
+
}
|
|
311
|
+
});
|
|
296
312
|
try {
|
|
297
313
|
!isTest() && console.log(chalk.magenta(`${shadowDatabase} 삭제`));
|
|
298
314
|
await tdb.raw(`DROP DATABASE IF EXISTS ${shadowDatabase}`);
|
|
@@ -341,8 +357,8 @@ var init_migrator = __esmMin((() => {
|
|
|
341
357
|
}
|
|
342
358
|
};
|
|
343
359
|
}));
|
|
344
|
-
|
|
345
360
|
//#endregion
|
|
346
361
|
init_migrator();
|
|
347
362
|
export { Migrator, init_migrator };
|
|
348
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlncmF0b3IuanMiLCJuYW1lcyI6WyJyZXN1bHRzOiBNaWdyYXRpb25SZXN1bHQiLCJtaWdyYXRpb25TdGF0dXNFcnJvcjogc3RyaW5nIHwgdW5kZWZpbmVkIiwic3RhdHVzOiBudW1iZXIgfCBcImVycm9yXCIiLCJwZW5kaW5nOiBzdHJpbmdbXSIsImN1cnJlbnRWZXJzaW9uOiBzdHJpbmcgfCBcImVycm9yXCIiLCJwcmVwYXJlZENvZGVzOiBHZW5NaWdyYXRpb25Db2RlW10iLCJlbnRpdHlTZXRzOiBNaWdyYXRpb25TZXRbXSIsImNvZGVzOiBHZW5NaWdyYXRpb25Db2RlW10iXSwic291cmNlcyI6WyIuLi8uLi9zcmMvbWlncmF0aW9uL21pZ3JhdG9yLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhc3NlcnQgZnJvbSBcImFzc2VydFwiO1xuaW1wb3J0IHsgbWtkaXIsIHJlYWRkaXIsIHVubGluaywgd3JpdGVGaWxlIH0gZnJvbSBcImZzL3Byb21pc2VzXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuXG5pbXBvcnQgY2hhbGsgZnJvbSBcImNoYWxrXCI7XG5pbXBvcnQgeyB0eXBlIEtuZXggfSBmcm9tIFwia25leFwiO1xuaW1wb3J0IHsgZ3JvdXAsIHN1bSwgdW5pcXVlIH0gZnJvbSBcInJhZGFzaGlcIjtcblxuaW1wb3J0IHsgU29uYW11IH0gZnJvbSBcIi4uL2FwaS9zb25hbXVcIjtcbmltcG9ydCB7IERCIH0gZnJvbSBcIi4uL2RhdGFiYXNlL2RiXCI7XG5pbXBvcnQgeyB0eXBlIFNvbmFtdURCQ29uZmlnIH0gZnJvbSBcIi4uL2RhdGFiYXNlL2RiXCI7XG5pbXBvcnQgeyBjcmVhdGVLbmV4SW5zdGFuY2UgfSBmcm9tIFwiLi4vZGF0YWJhc2Uva25leFwiO1xuaW1wb3J0IHsgU0QgfSBmcm9tIFwiLi4vZGljdC9zZFwiO1xuaW1wb3J0IHsgRW50aXR5TWFuYWdlciB9IGZyb20gXCIuLi9lbnRpdHkvZW50aXR5LW1hbmFnZXJcIjtcbmltcG9ydCB7IFNlcnZpY2VVbmF2YWlsYWJsZUV4Y2VwdGlvbiB9IGZyb20gXCIuLi9leGNlcHRpb25zL3NvLWV4Y2VwdGlvbnNcIjtcbmltcG9ydCB7IE5haXRlIH0gZnJvbSBcIi4uL25haXRlL25haXRlXCI7XG5pbXBvcnQgeyB0eXBlIEdlbk1pZ3JhdGlvbkNvZGUsIHR5cGUgTWlncmF0aW9uU2V0IH0gZnJvbSBcIi4uL3R5cGVzL3R5cGVzXCI7XG5pbXBvcnQgeyBpc1Rlc3QgfSBmcm9tIFwiLi4vdXRpbHMvY29udHJvbGxlclwiO1xuaW1wb3J0IHsgZXhpc3RzIH0gZnJvbSBcIi4uL3V0aWxzL2ZzLXV0aWxzXCI7XG5pbXBvcnQgeyBnZW5lcmF0ZUFsdGVyQ29kZSwgZ2VuZXJhdGVDcmVhdGVDb2RlIH0gZnJvbSBcIi4vY29kZS1nZW5lcmF0aW9uXCI7XG5pbXBvcnQgeyBnZXRNaWdyYXRpb25TZXRGcm9tRW50aXR5IH0gZnJvbSBcIi4vbWlncmF0aW9uLXNldFwiO1xuaW1wb3J0IHsgUG9zdGdyZVNRTFNjaGVtYVJlYWRlciB9IGZyb20gXCIuL3Bvc3RncmVzcWwtc2NoZW1hLXJlYWRlclwiO1xuaW1wb3J0IHsgdHlwZSBDb25uU3RyaW5nLCB0eXBlIE1pZ3JhdGlvbkNvZGUsIHR5cGUgTWlncmF0aW9uU3RhdHVzIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuZXhwb3J0IHR5cGUgTWlncmF0aW9uUmVzdWx0ID0ge1xuICBjb25uS2V5OiBzdHJpbmc7XG4gIGJhdGNoTm86IG51bWJlcjtcbiAgYXBwbGllZDogc3RyaW5nW107XG59W107XG5cbmV4cG9ydCBjbGFzcyBNaWdyYXRvciB7XG4gIHByaXZhdGUgYXN5bmMgcnVuTWlncmF0aW9uc1NlcXVlbnRpYWxseShcbiAgICBjb25uczogeyBjb25uS2V5OiBrZXlvZiBTb25hbXVEQkNvbmZpZzsga25leDogS25leCB9W10sXG4gICAgYWN0aW9uOiBcImFwcGx5XCIgfCBcInJvbGxiYWNrXCIsXG4gICk6IFByb21pc2U8TWlncmF0aW9uUmVzdWx0PiB7XG4gICAgY29uc3QgcmVzdWx0czogTWlncmF0aW9uUmVzdWx0ID0gW107XG5cbiAgICBmb3IgKGNvbnN0IHsgY29ubktleSwga25leCB9IG9mIGNvbm5zKSB7XG4gICAgICBjb25zdCBbYmF0Y2hObywgYXBwbGllZF0gPVxuICAgICAgICBhY3Rpb24gPT09IFwiYXBwbHlcIiA/IGF3YWl0IGtuZXgubWlncmF0ZS5sYXRlc3QoKSA6IGF3YWl0IGtuZXgubWlncmF0ZS5yb2xsYmFjaygpO1xuXG4gICAgICByZXN1bHRzLnB1c2goe1xuICAgICAgICBjb25uS2V5LFxuICAgICAgICBiYXRjaE5vLFxuICAgICAgICBhcHBsaWVkLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGdldE1pZ3JhdGlvbkNvZGVzKCk6IFByb21pc2U8TWlncmF0aW9uQ29kZVtdPiB7XG4gICAgY29uc3Qgc3JjTWlncmF0aW9uc0RpciA9IHBhdGguam9pbihTb25hbXUuYXBpUm9vdFBhdGgsIFwic3JjXCIsIFwibWlncmF0aW9uc1wiKTsgLy8g7J206rG0IO2ZmOqyveyXkCDqtIDqs4Tsl4bsnbQg7ZWt7IOBIHNyY+yXkOyEnCDssL7slYTslbwg7ZW07JqULlxuXG4gICAgaWYgKCEoYXdhaXQgZXhpc3RzKHNyY01pZ3JhdGlvbnNEaXIpKSkge1xuICAgICAgYXdhaXQgbWtkaXIoc3JjTWlncmF0aW9uc0Rpciwge1xuICAgICAgICByZWN1cnNpdmU6IHRydWUsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBjb2RlcyA9IChhd2FpdCByZWFkZGlyKHNyY01pZ3JhdGlvbnNEaXIpKVxuICAgICAgLmZpbHRlcigoZikgPT4gZi5lbmRzV2l0aChcIi50c1wiKSlcbiAgICAgIC5tYXAoKGYpID0+ICh7XG4gICAgICAgIG5hbWU6IGYucmVwbGFjZShcIi50c1wiLCBcIlwiKSxcbiAgICAgICAgcGF0aDogcGF0aC5qb2luKHNyY01pZ3JhdGlvbnNEaXIsIGYpLFxuICAgICAgfSkpXG4gICAgICAudG9Tb3J0ZWQoKGEsIGIpID0+IChhLm5hbWUgPCBiLm5hbWUgPyAxIDogLTEpKTsgLy8g7J2066aEIOuCtOumvOywqOyInCDsoJXroKwo7LWc7Iug7IicKVxuXG4gICAgTmFpdGUudChcIm1pZ3JhdG9yOmdldE1pZ3JhdGlvbkNvZGVzOnJlc3VsdHNcIiwgY29kZXMpO1xuICAgIHJldHVybiBjb2RlcztcbiAgfVxuXG4gIC8qKlxuICAgKiDtg4Dqsp/rs4Qg66eI7J206re466CI7J207IWYIOyDge2DnOyZgCDsvZTrk5wg7IOd7ISxL+ykgOu5hCDsg4Htg5zrpbwg6rWs7ZW07Ji164uI64ukLlxuICAgKiDsi6TsoJzroZwgRELsl5Ag7KCR6re864+EIO2VmOqzoCDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcIO2MjOydvOuPhCDtmZXsnbjtlZjqs6AsXG4gICAqIO2VhOyalO2VmOuLpOuptCDsoIHsmqntlaAg7IiYIOyeiOuKlCDsvZTrk5zrpbwg7IOd7ISx6rmM7KeAIO2VtOyYteuLiOuLpC5cbiAgICpcbiAgICogQ0xJ7JmAIFNvbmFtdSBVSeyXkOyEnCDsgqzsmqnrkKnri4jri6QuXG4gICAqXG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBhc3luYyBnZXRTdGF0dXMoKTogUHJvbWlzZTxNaWdyYXRpb25TdGF0dXM+IHtcbiAgICBjb25zdCBjb2RlcyA9IGF3YWl0IHRoaXMuZ2V0TWlncmF0aW9uQ29kZXMoKTtcbiAgICBOYWl0ZS50KFwibWlncmF0b3I6Z2V0U3RhdHVzOmNvZGVzXCIsIGNvZGVzKTtcblxuICAgIGNvbnN0IGNvbm5LZXlzID0gT2JqZWN0LmtleXMoU29uYW11LmRiQ29uZmlnKS5maWx0ZXIoXG4gICAgICAoa2V5KSA9PiAha2V5LmVuZHNXaXRoKFwiX3NsYXZlXCIpLFxuICAgICkgYXMgKGtleW9mIHR5cGVvZiBTb25hbXUuZGJDb25maWcpW107XG5cbiAgICBsZXQgbWlncmF0aW9uU3RhdHVzRXJyb3I6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICAgIGNvbnN0IHN0YXR1c2VzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBjb25uS2V5cy5tYXAoYXN5bmMgKGNvbm5LZXkpID0+IHtcbiAgICAgICAgY29uc3Qga25leE9wdGlvbnMgPSBTb25hbXUuZGJDb25maWdbY29ubktleV07XG4gICAgICAgIGNvbnN0IHRDb25uID0gY3JlYXRlS25leEluc3RhbmNlKGtuZXhPcHRpb25zKTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHN0YXR1czogbnVtYmVyIHwgXCJlcnJvclwiID0gYXdhaXQgKGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIHJldHVybiBhd2FpdCB0Q29ubi5taWdyYXRlLnN0YXR1cygpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgICAgICBjaGFsay55ZWxsb3coXG4gICAgICAgICAgICAgICAgICBgJHtjb25uS2V5feydmCDrp4jsnbTqt7jroIjsnbTshZgg7IOB7YOc66W8IOqwgOyguOyYpOuKlCDrjbDsl5Ag7Iuk7Yyo7ZWY7JiA7Iq164uI64ukLiDrjbDsnbTthLDrsqDsnbTsiqTqsIAg7Jis67CU66W06rKMIOq1rOyEseuQmOyngCDslYrsnYAg6rKDIOqwmeyKteuLiOuLpC4g7ZmV7J247ZWY7Iuc6rOgIOuLpOyLnCDsi5zrj4TtlbTso7zshLjsmpQuXFxu7Iuc64+E7ZWcIOyXsOqysCDshKTsoJU6XFxuJHtKU09OLnN0cmluZ2lmeShrbmV4T3B0aW9ucy5jb25uZWN0aW9uLCBudWxsLCAyKX1cXG7rsJzsg53tlZwg7JeQ65+sOlxcbiR7ZXJyfVxcbmAsXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgbWlncmF0aW9uU3RhdHVzRXJyb3IgPSBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVycik7XG4gICAgICAgICAgICAgIHJldHVybiBcImVycm9yXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSkoKTtcbiAgICAgICAgICBjb25zdCBwZW5kaW5nOiBzdHJpbmdbXSA9IGF3YWl0IChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBjb25zdCBbLCBmZExpc3RdID0gYXdhaXQgdENvbm4ubWlncmF0ZS5saXN0KCk7XG4gICAgICAgICAgICAgIHJldHVybiBmZExpc3QubWFwKChmZDogeyBmaWxlOiBzdHJpbmcgfSkgPT4gZmQuZmlsZS5yZXBsYWNlKFwiLnRzXCIsIFwiXCIpKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICBtaWdyYXRpb25TdGF0dXNFcnJvciA9IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKTtcbiAgICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pKCk7XG4gICAgICAgICAgY29uc3QgY3VycmVudFZlcnNpb246IHN0cmluZyB8IFwiZXJyb3JcIiA9IGF3YWl0IChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICByZXR1cm4gYXdhaXQgdENvbm4ubWlncmF0ZS5jdXJyZW50VmVyc2lvbigpO1xuICAgICAgICAgICAgfSBjYXRjaCAoX2Vycikge1xuICAgICAgICAgICAgICBtaWdyYXRpb25TdGF0dXNFcnJvciA9IF9lcnIgaW5zdGFuY2VvZiBFcnJvciA/IF9lcnIubWVzc2FnZSA6IFN0cmluZyhfZXJyKTtcbiAgICAgICAgICAgICAgcmV0dXJuIFwiZXJyb3JcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KSgpO1xuICAgICAgICAgIE5haXRlLnQoXCJtaWdyYXRvcjpnZXRTdGF0dXM6c3RhdHVzXCIsIHN0YXR1cyk7XG5cbiAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0ga25leE9wdGlvbnMuY29ubmVjdGlvbiBhcyBLbmV4LlBnQ29ubmVjdGlvbkNvbmZpZztcblxuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBuYW1lOiBjb25uS2V5LnJlcGxhY2UoXCJfbWFzdGVyXCIsIFwiXCIpLFxuICAgICAgICAgICAgY29ubktleSxcbiAgICAgICAgICAgIGNvbm5TdHJpbmc6IGBwZzovLyR7Y29ubmVjdGlvbi51c2VyID8/IFwiXCJ9QCR7Y29ubmVjdGlvbi5ob3N0fToke1xuICAgICAgICAgICAgICBjb25uZWN0aW9uLnBvcnRcbiAgICAgICAgICAgIH0vJHtjb25uZWN0aW9uLmRhdGFiYXNlfWAgYXMgQ29ublN0cmluZyxcbiAgICAgICAgICAgIGN1cnJlbnRWZXJzaW9uLFxuICAgICAgICAgICAgc3RhdHVzOiBzdGF0dXMsXG4gICAgICAgICAgICBwZW5kaW5nLFxuICAgICAgICAgIH07XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgYXdhaXQgdENvbm4uZGVzdHJveSgpO1xuICAgICAgICB9XG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgTmFpdGUudChcIm1pZ3JhdG9yOmdldFN0YXR1czpjb25uc1wiLCBzdGF0dXNlcyk7XG5cbiAgICBjb25zdCBwcmVwYXJlZENvZGVzOiBHZW5NaWdyYXRpb25Db2RlW10gPSBhd2FpdCAoYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgc3RhdHVzMGNvbm4gPSBzdGF0dXNlcy5maW5kKChzdGF0dXMpID0+IHN0YXR1cy5zdGF0dXMgPT09IDApO1xuICAgICAgaWYgKHN0YXR1czBjb25uID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgIGNoYWxrLnllbGxvdyhcbiAgICAgICAgICAgIGBXaGlsZSB0cnlpbmcgdG8gcHJlcGFyZSBtaWdyYXRpb24gY29kZXMsIHdlIGZvdW5kIHRoYXQgdGhlcmUgaXMgbm8gZGF0YWJhc2UgdG8gY29tcGFyZSBtaWdyYXRpb25zLiBXZSBuZWVkIGF0IGxlYXN0IG9uZSBkYXRhYmFzZSB3aGVyZSBldmVyeSBtaWdyYXRpb24gaXMgYXBwbGllZChzdGF0dXMgPT09IDApLiBZb3UgbWlnaHQgd2FudCB0byBhcHBseSB5b3VyIGV4aXN0aW5nIG1pZ3JhdGlvbnMgdG8gb25lIG9mIHRoZSBkYXRhYmFzZXMuYCxcbiAgICAgICAgICApLFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNvbXBhcmVEQmNvbm4gPSBjcmVhdGVLbmV4SW5zdGFuY2UoU29uYW11LmRiQ29uZmlnW3N0YXR1czBjb25uLmNvbm5LZXldKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmNvbXBhcmVNaWdyYXRpb25zKGNvbXBhcmVEQmNvbm4pO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYXdhaXQgY29tcGFyZURCY29ubi5kZXN0cm95KCk7XG4gICAgICB9XG4gICAgfSkoKTtcblxuICAgIE5haXRlLnQoXCJtaWdyYXRvcjpnZXRTdGF0dXM6cHJlcGFyZWRDb2Rlc1wiLCBwcmVwYXJlZENvZGVzKTtcblxuICAgIHJldHVybiB7XG4gICAgICBjb25uczogc3RhdHVzZXMsXG4gICAgICBjb2RlcyxcbiAgICAgIHByZXBhcmVkQ29kZXMsXG4gICAgICBlcnJvcjogbWlncmF0aW9uU3RhdHVzRXJyb3IsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiDrp4jsnbTqt7jroIjsnbTshZjsnYQg7KCB7Jqp7ZWY6rGw64KYIOuhpOuwse2VqeuLiOuLpC5cbiAgICogU29uYW11IFVJ7JeQ7IScIOuniOydtOq3uOugiOydtOyFmCDsnpHsl4XsnYQg7IiY7ZaJ7ZWgIOuVjCDsgqzsmqnrkKnri4jri6QuXG4gICAqXG4gICAqIENMSeyZgCBTb25hbXUgVUnsl5DshJwg7IKs7Jqp65Cp64uI64ukLlxuICAgKlxuICAgKiBAcGFyYW0gYWN0aW9uIOyekeyXhSDsnKDtmJUgKGFwcGx5L3JvbGxiYWNrKVxuICAgKiBAcGFyYW0gdGFyZ2V0cyDsnpHsl4Ug64yA7IOBIERCIOyEpOyglSDtgqQgKGtleW9mIFNvbmFtdURCQ29uZmlnKVxuICAgKiBAcmV0dXJucyDsnpHsl4Ug6rKw6rO8XG4gICAqL1xuICBhc3luYyBydW5BY3Rpb24oXG4gICAgYWN0aW9uOiBcImFwcGx5XCIgfCBcInJvbGxiYWNrXCIsXG4gICAgdGFyZ2V0czogKGtleW9mIFNvbmFtdURCQ29uZmlnKVtdLFxuICApOiBQcm9taXNlPE1pZ3JhdGlvblJlc3VsdD4ge1xuICAgIE5haXRlLnQoXCJtaWdyYXRvcjpydW5BY3Rpb246YWN0aW9uXCIsIGFjdGlvbik7XG4gICAgTmFpdGUudChcIm1pZ3JhdG9yOnJ1bkFjdGlvbjp0YXJnZXRzXCIsIHRhcmdldHMpO1xuXG4gICAgLy8gZ2V0IHVuaXEga25leCBjb25maWdzXG4gICAgY29uc3QgY29uZmlncyA9IHVuaXF1ZShcbiAgICAgIHRhcmdldHNcbiAgICAgICAgLm1hcCgodGFyZ2V0KSA9PiAoe1xuICAgICAgICAgIGNvbm5LZXk6IHRhcmdldCxcbiAgICAgICAgICBvcHRpb25zOiBTb25hbXUuZGJDb25maWdbdGFyZ2V0XSxcbiAgICAgICAgfSkpXG4gICAgICAgIC5maWx0ZXIoKGMpID0+IGMub3B0aW9ucyAhPT0gdW5kZWZpbmVkKSxcbiAgICAgICh7IG9wdGlvbnMgfSkgPT5cbiAgICAgICAgYCR7KG9wdGlvbnMuY29ubmVjdGlvbiBhcyBLbmV4LlBnQ29ubmVjdGlvbkNvbmZpZykuaG9zdH06JHtcbiAgICAgICAgICAob3B0aW9ucy5jb25uZWN0aW9uIGFzIEtuZXguUGdDb25uZWN0aW9uQ29uZmlnKS5wb3J0ID8/IDU0MzJcbiAgICAgICAgfS8keyhvcHRpb25zLmNvbm5lY3Rpb24gYXMgS25leC5QZ0Nvbm5lY3Rpb25Db25maWcpLmRhdGFiYXNlfWAsXG4gICAgKTtcblxuICAgIC8vIGdldCBjb25uZWN0aW9uc1xuICAgIGNvbnN0IGNvbm5zID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBjb25maWdzLm1hcChhc3luYyAoY29uZmlnKSA9PiAoe1xuICAgICAgICBjb25uS2V5OiBjb25maWcuY29ubktleSxcbiAgICAgICAga25leDogY3JlYXRlS25leEluc3RhbmNlKGNvbmZpZy5vcHRpb25zKSxcbiAgICAgIH0pKSxcbiAgICApO1xuXG4gICAgdHJ5IHtcbiAgICAgIC8vIGFjdGlvblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgKGFzeW5jICgpID0+IHtcbiAgICAgICAgc3dpdGNoIChhY3Rpb24pIHtcbiAgICAgICAgICBjYXNlIFwiYXBwbHlcIjpcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJ1bk1pZ3JhdGlvbnNTZXF1ZW50aWFsbHkoY29ubnMsIFwiYXBwbHlcIik7XG4gICAgICAgICAgY2FzZSBcInJvbGxiYWNrXCI6XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ydW5NaWdyYXRpb25zU2VxdWVudGlhbGx5KGNvbm5zLCBcInJvbGxiYWNrXCIpO1xuICAgICAgICB9XG4gICAgICB9KSgpO1xuXG4gICAgICBOYWl0ZS50KFwibWlncmF0b3I6cnVuQWN0aW9uOnJlc3VsdFwiLCByZXN1bHQpO1xuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgY29ubnMubWFwKCh7IGtuZXggfSkgPT4ge1xuICAgICAgICAgIHJldHVybiBrbmV4LmRlc3Ryb3koKTtcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiDsgq3soJwg6rCA64ql7ZWcIOuniOydtOq3uOugiOydtOyFmCDsvZTrk5wg7YyM7J287J2EIOqygOymne2VqeuLiOuLpC5cbiAgICpcbiAgICogQHBhcmFtIGNvbm5zIOuniOydtOq3uOugiOydtOyFmCDsg4Htg5wg67Cw7Je0XG4gICAqIEBwYXJhbSBjb2RlTmFtZXMg7IKt7KCc7ZWgIOuniOydtOq3uOugiOydtOyFmCDsvZTrk5wg7YyM7J28IOydtOumhCDrsLDsl7RcbiAgICogQHJldHVybnMg7IKt7KCcIOqwgOuKpSDsl6zrtoAg67CPIOyggeyaqeuQnCDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcIO2MjOydvCDsnbTrpoRcbiAgICovXG4gIHZhbGlkYXRlRGVsZXRhYmxlKGNvbm5zOiBNaWdyYXRpb25TdGF0dXNbXCJjb25uc1wiXSwgY29kZU5hbWVzOiBzdHJpbmdbXSkge1xuICAgIGNvbnN0IGFwcGxpZWRDb2RlcyA9IGNvZGVOYW1lcy5maWx0ZXIoKGNvZGVOYW1lKSA9PlxuICAgICAgY29ubnMuc29tZSgoY29ubikgPT4gIWNvbm4ucGVuZGluZy5pbmNsdWRlcyhjb2RlTmFtZSkpLFxuICAgICk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgY2FuRGVsZXRlOiBhcHBsaWVkQ29kZXMubGVuZ3RoID09PSAwLFxuICAgICAgYXBwbGllZENvZGVzLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICog66eI7J206re466CI7J207IWYIOy9lOuTnCDtjIzsnbzsnYQg7IKt7KCc7ZWp64uI64ukLlxuICAgKlxuICAgKiBTb25hbXUgVUnsl5DshJwg7IKs7Jqp65Cp64uI64ukLlxuICAgKlxuICAgKiBAcGFyYW0gY29kZU5hbWVzIOyCreygnO2VoCDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcIO2MjOydvCDsnbTrpoQg67Cw7Je0XG4gICAqIEByZXR1cm5zIOyCreygnOuQnCDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcIO2MjOydvCDqsJzsiJhcbiAgICovXG4gIGFzeW5jIGRlbENvZGVzKGNvZGVOYW1lczogc3RyaW5nW10pOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IHsgY29ubnMgfSA9IGF3YWl0IHRoaXMuZ2V0U3RhdHVzKCk7XG4gICAgY29uc3QgeyBjYW5EZWxldGUsIGFwcGxpZWRDb2RlcyB9ID0gdGhpcy52YWxpZGF0ZURlbGV0YWJsZShjb25ucywgY29kZU5hbWVzKTtcbiAgICBpZiAoIWNhbkRlbGV0ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgWW91IGNhbm5vdCBkZWxldGUgYSBtaWdyYXRpb24gZmlsZSBpZiB0aGVyZSBpcyBhbHJlYWR5IGFwcGxpZWQuIEFwcGxpZWQgY29kZXM6ICR7YXBwbGllZENvZGVzLmpvaW4oXCIsIFwiKX1gLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc3VtKFxuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIGNvZGVOYW1lcy5tYXAoYXN5bmMgKGNvZGVOYW1lKSA9PiB7XG4gICAgICAgICAgY29uc3QgZmlsZVBhdGggPSBgJHtTb25hbXUuYXBpUm9vdFBhdGh9L3NyYy9taWdyYXRpb25zLyR7Y29kZU5hbWV9LnRzYDtcbiAgICAgICAgICBpZiAoYXdhaXQgZXhpc3RzKGZpbGVQYXRoKSkge1xuICAgICAgICAgICAgYXdhaXQgdW5saW5rKGZpbGVQYXRoKTtcbiAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfSksXG4gICAgICApLFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGdlbkRhdGVUYWcoaW5kZXg6IG51bWJlciwgYmFzZURhdGU6IERhdGUgPSBuZXcgRGF0ZSgpKTogc3RyaW5nIHtcbiAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoYmFzZURhdGUuZ2V0VGltZSgpICsgaW5kZXggKiAxMDAwKTtcbiAgICBjb25zdCBwYWQgPSAobnVtOiBudW1iZXIsIHNpemU6IG51bWJlciA9IDIpID0+IG51bS50b1N0cmluZygpLnBhZFN0YXJ0KHNpemUsIFwiMFwiKTtcbiAgICByZXR1cm4gKFxuICAgICAgZGF0ZS5nZXRGdWxsWWVhcigpLnRvU3RyaW5nKCkgK1xuICAgICAgcGFkKGRhdGUuZ2V0TW9udGgoKSArIDEpICtcbiAgICAgIHBhZChkYXRlLmdldERhdGUoKSkgK1xuICAgICAgcGFkKGRhdGUuZ2V0SG91cnMoKSkgK1xuICAgICAgcGFkKGRhdGUuZ2V0TWludXRlcygpKSArXG4gICAgICBwYWQoZGF0ZS5nZXRTZWNvbmRzKCkpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcIO2MjOydvOydhCDsg53shLHtlanri4jri6QuXG4gICAqXG4gICAqIFNvbmFtdSBVSeyXkOyEnCDsgqzsmqnrkKnri4jri6QuXG4gICAqXG4gICAqIEByZXR1cm5zIOyDneyEseuQnCDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcIO2MjOydvCDqsJzsiJhcbiAgICovXG4gIGFzeW5jIGdlbmVyYXRlUHJlcGFyZWRDb2RlcygpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IHsgcHJlcGFyZWRDb2RlcyB9ID0gYXdhaXQgdGhpcy5nZXRTdGF0dXMoKTtcbiAgICBOYWl0ZS50KFwibWlncmF0b3I6Z2VuZXJhdGVQcmVwYXJlZENvZGVzOnByZXBhcmVkQ29kZXNcIiwgcHJlcGFyZWRDb2Rlcyk7XG4gICAgaWYgKHByZXBhcmVkQ29kZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICBjb25zb2xlLmxvZyhjaGFsay5ncmVlbihcIlxcbu2YhOyerCDrqqjrkZAg7Iux7YGs65CcIOyDge2DnOyeheuLiOuLpC5cIikpO1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgLy8g7Iuk7KCcIOy9lOuTnCDsg53shLFcbiAgICBjb25zdCBtaWdyYXRpb25zRGlyID0gYCR7U29uYW11LmFwaVJvb3RQYXRofS9zcmMvbWlncmF0aW9uc2A7XG5cbiAgICBmb3IgKGNvbnN0IFtpbmRleCwgcGNvZGVdIG9mIHByZXBhcmVkQ29kZXMuZW50cmllcygpKSB7XG4gICAgICBpZiAocGNvZGUuZm9ybWF0dGVkKSB7XG4gICAgICAgIGNvbnN0IGRhdGVUYWcgPSB0aGlzLmdlbkRhdGVUYWcoaW5kZXgpO1xuICAgICAgICBjb25zdCBmaWxlUGF0aCA9IGAke21pZ3JhdGlvbnNEaXJ9LyR7ZGF0ZVRhZ31fJHtwY29kZS50aXRsZX0udHNgO1xuICAgICAgICBhd2FpdCB3cml0ZUZpbGUoZmlsZVBhdGgsIHBjb2RlLmZvcm1hdHRlZCk7XG4gICAgICAgICFpc1Rlc3QoKSAmJiBjb25zb2xlLmxvZyhjaGFsay5ncmVlbihgTUlHUkFUSU9OIENSRUFURUQgJHtmaWxlUGF0aH1gKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHByZXBhcmVkQ29kZXMubGVuZ3RoO1xuICB9XG5cbiAgYXN5bmMgY29tcGFyZU1pZ3JhdGlvbnMoY29tcGFyZURCOiBLbmV4KTogUHJvbWlzZTxHZW5NaWdyYXRpb25Db2RlW10+IHtcbiAgICAvLyBFbnRpdHkg7Iic7ZqM7ZWY7JesIOyLse2BrFxuICAgIGNvbnN0IGVudGl0eUlkcyA9IEVudGl0eU1hbmFnZXIuZ2V0QWxsSWRzKCk7XG5cbiAgICAvLyDsobDsnbjthYzsnbTruJQg7Y+s7ZWo7ZWY7JesIEVudGl0eeyXkOyEnCBNaWdyYXRpb25TZXQg7LaU7LacXG4gICAgY29uc3QgZW50aXR5U2V0c1dpdGhKb2luVGFibGUgPSBlbnRpdHlJZHNcbiAgICAgIC5maWx0ZXIoKGVudGl0eUlkKSA9PiBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCkucHJvcHMubGVuZ3RoID4gMClcbiAgICAgIC5tYXAoKGVudGl0eUlkKSA9PiBnZXRNaWdyYXRpb25TZXRGcm9tRW50aXR5KEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKSkpO1xuXG4gICAgLy8g7KGw7J247YWM7J2067iU66eMIOy2lOy2nFxuICAgIGNvbnN0IGpvaW5UYWJsZXNXaXRoRHVwID0gZW50aXR5U2V0c1dpdGhKb2luVGFibGUuZmxhdE1hcCgoZW50aXR5U2V0KSA9PiBlbnRpdHlTZXQuam9pblRhYmxlcyk7XG4gICAgLy8g7KSR67O1IOygnOqxsCAo7KSR67O17J24IOqyveyasCBpbmRleGVz66W8IOuzke2VqSlcbiAgICBjb25zdCBqb2luVGFibGVzID0gT2JqZWN0LnZhbHVlcyhncm91cChqb2luVGFibGVzV2l0aER1cCwgKGp0KSA9PiBqdC50YWJsZSkpLm1hcCgodGFibGVzKSA9PiB7XG4gICAgICBhc3NlcnQodGFibGVzICE9PSB1bmRlZmluZWQsIFwidGFibGVzIGlzIHVuZGVmaW5lZFwiKTtcbiAgICAgIGlmICh0YWJsZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIHJldHVybiB0YWJsZXNbMF07XG4gICAgICB9XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi50YWJsZXNbMF0sXG4gICAgICAgIGluZGV4ZXM6IHVuaXF1ZShcbiAgICAgICAgICB0YWJsZXMuZmxhdE1hcCgodCkgPT4gdC5pbmRleGVzKSxcbiAgICAgICAgICAoaW5kZXgpID0+IFtpbmRleC50eXBlLCAuLi5pbmRleC5jb2x1bW5zXS5qb2luKFwiLVwiKSxcbiAgICAgICAgKSxcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICAvLyDsobDsnbjthYzsnbTruJQg7Y+s7ZWo7ZWY7JesIE1pZ3JhdGlvblNldCDrsLDsl7RcbiAgICBjb25zdCBlbnRpdHlTZXRzOiBNaWdyYXRpb25TZXRbXSA9IFsuLi5lbnRpdHlTZXRzV2l0aEpvaW5UYWJsZSwgLi4uam9pblRhYmxlc107XG5cbiAgICBjb25zdCBjb2RlczogR2VuTWlncmF0aW9uQ29kZVtdID0gKFxuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIGVudGl0eVNldHMubWFwKGFzeW5jIChlbnRpdHlTZXQpID0+IHtcbiAgICAgICAgICBjb25zdCBkYlNldCA9IGF3YWl0IFBvc3RncmVTUUxTY2hlbWFSZWFkZXIuZ2V0TWlncmF0aW9uU2V0RnJvbURCKFxuICAgICAgICAgICAgY29tcGFyZURCLFxuICAgICAgICAgICAgZW50aXR5U2V0LnRhYmxlLFxuICAgICAgICAgICk7XG4gICAgICAgICAgTmFpdGUudChgbWlncmF0b3I6Y29tcGFyZU1pZ3JhdGlvbnM6ZW50aXR5U2V0OiR7ZW50aXR5U2V0LnRhYmxlfWAsIGVudGl0eVNldCk7XG4gICAgICAgICAgTmFpdGUudChgbWlncmF0b3I6Y29tcGFyZU1pZ3JhdGlvbnM6ZGJTZXQ6JHtlbnRpdHlTZXQudGFibGV9YCwgZGJTZXQpO1xuXG4gICAgICAgICAgaWYgKGRiU2V0ID09PSBudWxsKSB7XG4gICAgICAgICAgICAvLyDquLDsobQg7YWM7J2067iUIOyXhuydjCwg7IOI66GcIO2FjOydtOu4lCDsg53shLFcbiAgICAgICAgICAgIHJldHVybiBhd2FpdCBnZW5lcmF0ZUNyZWF0ZUNvZGUoZW50aXR5U2V0KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8g6riw7KG0IO2FjOydtOu4lCDsobTsnqztlZjripQg7LyA7J207IqkXG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgZ2VuZXJhdGVBbHRlckNvZGUoZW50aXR5U2V0LCBkYlNldCwgY29tcGFyZURCKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pLFxuICAgICAgKVxuICAgICkuZmxhdCgpO1xuXG4gICAgLy8gbm9ybWFsIO2DgOyeheydtCDslZ7snLzroZwsIGZvcmVpZ27snbQg65Kk66GcXG4gICAgY29kZXMuc29ydCgoY29kZUEsIGNvZGVCKSA9PiB7XG4gICAgICBpZiAoY29kZUEudHlwZSA9PT0gXCJmb3JlaWduXCIgJiYgY29kZUIudHlwZSA9PT0gXCJub3JtYWxcIikge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH0gZWxzZSBpZiAoY29kZUEudHlwZSA9PT0gXCJub3JtYWxcIiAmJiBjb2RlQi50eXBlID09PSBcImZvcmVpZ25cIikge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gMDtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiBjb2RlcztcbiAgfVxuXG4gIC8qKlxuICAgKiBTaGFkb3cgREIg7YWM7Iqk7Yq466W8IOynhO2Wie2VqeuLiOuLpC5cbiAgICpcbiAgICogU29uYW11IFVJ7JeQ7IScIOyCrOyaqeuQqeuLiOuLpC5cbiAgICpcbiAgICogQHJldHVybnMgU2hhZG93IERCIO2FjOyKpO2KuCDqsrDqs7xcbiAgICovXG4gIGFzeW5jIHJ1blNoYWRvd1Rlc3QoKTogUHJvbWlzZTxNaWdyYXRpb25SZXN1bHQ+IHtcbiAgICBjb25zdCB0ZGJDb25uID0gU29uYW11LmRiQ29uZmlnLnRlc3QuY29ubmVjdGlvbiBhcyBLbmV4LlBnQ29ubmVjdGlvbkNvbmZpZztcbiAgICBjb25zdCBzaGFkb3dEYXRhYmFzZSA9IGAke3RkYkNvbm4uZGF0YWJhc2V9X19taWdyYXRpb25fc2hhZG93YDtcblxuICAgIC8vIO2FjOyKpO2KuCDsg4Htmansl5DshJzripQg7Yq4656c7J6t7IWY7J2EIOy0iOq4sO2ZlO2VmOqzoCwg7IOIIOuNsOydtO2EsOuyoOydtOyKpCDsu6TrhKXshZjsnYQg6rCA7KC47JmA7JW8IO2VqFxuICAgIGlmIChpc1Rlc3QoKSkge1xuICAgICAgYXdhaXQgREIuY2xlYXJUZXN0VHJhbnNhY3Rpb24oKTtcbiAgICAgIC8vIOuzkeugrCDthYzsiqTtirgg66qo65Oc7JeQ7ISc64qUIHdvcmtlciBEQiDsl7DqsrAg7Jyg7KeAXG4gICAgICBpZiAocHJvY2Vzcy5lbnYuU09OQU1VX1dPUktFUl9EQiAhPT0gXCJ0cnVlXCIpIHtcbiAgICAgICAgYXdhaXQgREIuZGVzdHJveSgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIOq4sOyhtCBTaGFkb3cgREIg7IKt7KCcIO2bhCBTaGFkb3cgREIg7IOd7ISxXG4gICAgY29uc3QgdGRiID0gY3JlYXRlS25leEluc3RhbmNlKFNvbmFtdS5kYkNvbmZpZy50ZXN0KTtcbiAgICB0cnkge1xuICAgICAgIWlzVGVzdCgpICYmIGNvbnNvbGUubG9nKGNoYWxrLm1hZ2VudGEoYCR7c2hhZG93RGF0YWJhc2V9IOyCreygnGApKTtcbiAgICAgIGF3YWl0IHRkYi5yYXcoYERST1AgREFUQUJBU0UgSUYgRVhJU1RTICR7c2hhZG93RGF0YWJhc2V9YCk7XG4gICAgICBhd2FpdCB0ZGIucmF3KGBcbiAgICAgICAgU0VMRUNUIHBnX3Rlcm1pbmF0ZV9iYWNrZW5kKHBnX3N0YXRfYWN0aXZpdHkucGlkKVxuICAgICAgICBGUk9NIHBnX3N0YXRfYWN0aXZpdHlcbiAgICAgICAgV0hFUkUgZGF0bmFtZSA9ICcke3RkYkNvbm4uZGF0YWJhc2V9J1xuICAgICAgICAgIEFORCBwaWQgPD4gcGdfYmFja2VuZF9waWQoKTtcbiAgICAgIGApO1xuICAgICAgYXdhaXQgdGRiLnJhdyhgQ1JFQVRFIERBVEFCQVNFICR7c2hhZG93RGF0YWJhc2V9IFRFTVBMQVRFICR7dGRiQ29ubi5kYXRhYmFzZX1gKTtcblxuICAgICAgLy8gU2hhZG93IERC7JeQIOyXsOqysFxuICAgICAgY29uc3Qgc2RiID0gY3JlYXRlS25leEluc3RhbmNlKHtcbiAgICAgICAgLi4uU29uYW11LmRiQ29uZmlnLnRlc3QsXG4gICAgICAgIGNvbm5lY3Rpb246IHtcbiAgICAgICAgICAuLi50ZGJDb25uLFxuICAgICAgICAgIGRhdGFiYXNlOiBzaGFkb3dEYXRhYmFzZSxcbiAgICAgICAgICBwYXNzd29yZDogdGRiQ29ubi5wYXNzd29yZCxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICAvLyBzaGFkb3cgREIg7YWM7Iqk7Yq4IOynhO2WiVxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgW2JhdGNoTm8sIGFwcGxpZWRdID0gYXdhaXQgc2RiLm1pZ3JhdGUubGF0ZXN0KCk7XG4gICAgICAgICFpc1Rlc3QoKSAmJlxuICAgICAgICAgIGNvbnNvbGUubG9nKGNoYWxrLmdyZWVuKFwiU2hhZG93IERCIO2FjOyKpO2KuOyXkCDshLHqs7XtlojsirXri4jri6QhXCIpLCB7XG4gICAgICAgICAgICBiYXRjaE5vLFxuICAgICAgICAgICAgYXBwbGllZCxcbiAgICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGNvbm5LZXk6IFwic2hhZG93XCIsXG4gICAgICAgICAgICBiYXRjaE5vLFxuICAgICAgICAgICAgYXBwbGllZCxcbiAgICAgICAgICB9LFxuICAgICAgICBdO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICB0aHJvdyBuZXcgU2VydmljZVVuYXZhaWxhYmxlRXhjZXB0aW9uKFNEKFwic29uYW11LmVycm9yLnNoYWRvd0RiVGVzdEZhaWxlZFwiKSk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBhd2FpdCBzZGIuZGVzdHJveSgpO1xuICAgICAgfVxuICAgIH0gZmluYWxseSB7XG4gICAgICAvLyBTaGFkb3cgREIg7IKt7KCcXG4gICAgICAhaXNUZXN0KCkgJiYgY29uc29sZS5sb2coY2hhbGsubWFnZW50YShgJHtzaGFkb3dEYXRhYmFzZX0g7IKt7KCcYCkpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgdGRiLnJhdyhgRFJPUCBEQVRBQkFTRSBJRiBFWElTVFMgJHtzaGFkb3dEYXRhYmFzZX1gKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihcIlNoYWRvdyBEQiDsoJXrpqwg7Iuk7YyoOlwiLCBlKTsgLy8g7J206rKMIOyXhuycvOuptCDsobDsmqntnogg64iE7IiYXG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBhd2FpdCB0ZGIuZGVzdHJveSgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O2NBUXVDO1VBQ0g7WUFFa0I7VUFDdEI7c0JBQ3lCO3FCQUNpQjthQUNuQztrQkFFTTtnQkFDRjt1QkFDK0I7cUJBQ2Q7Z0NBQ1E7Q0FTdkQsV0FBYixNQUFzQjtFQUNwQixNQUFjLDBCQUNaLE9BQ0EsUUFDMEI7R0FDMUIsTUFBTUEsVUFBMkIsRUFBRTtBQUVuQyxRQUFLLE1BQU0sRUFBRSxTQUFTLFVBQVUsT0FBTztJQUNyQyxNQUFNLENBQUMsU0FBUyxXQUNkLFdBQVcsVUFBVSxNQUFNLEtBQUssUUFBUSxRQUFRLEdBQUcsTUFBTSxLQUFLLFFBQVEsVUFBVTtBQUVsRixZQUFRLEtB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
|
|
363
|
+
|
|
364
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlncmF0b3IuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vc3JjL21pZ3JhdGlvbi9taWdyYXRvci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgYXNzZXJ0IGZyb20gXCJhc3NlcnRcIjtcbmltcG9ydCB7IG1rZGlyLCByZWFkZGlyLCB1bmxpbmssIHdyaXRlRmlsZSB9IGZyb20gXCJmcy9wcm9taXNlc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcblxuaW1wb3J0IGNoYWxrIGZyb20gXCJjaGFsa1wiO1xuaW1wb3J0IHsgdHlwZSBLbmV4IH0gZnJvbSBcImtuZXhcIjtcbmltcG9ydCB7IGdyb3VwLCBzdW0sIHVuaXF1ZSB9IGZyb20gXCJyYWRhc2hpXCI7XG5cbmltcG9ydCB7IFNvbmFtdSB9IGZyb20gXCIuLi9hcGkvc29uYW11XCI7XG5pbXBvcnQgeyBEQiB9IGZyb20gXCIuLi9kYXRhYmFzZS9kYlwiO1xuaW1wb3J0IHsgdHlwZSBTb25hbXVEQkNvbmZpZyB9IGZyb20gXCIuLi9kYXRhYmFzZS9kYlwiO1xuaW1wb3J0IHsgY3JlYXRlS25leEluc3RhbmNlIH0gZnJvbSBcIi4uL2RhdGFiYXNlL2tuZXhcIjtcbmltcG9ydCB7IFNEIH0gZnJvbSBcIi4uL2RpY3Qvc2RcIjtcbmltcG9ydCB7IEVudGl0eU1hbmFnZXIgfSBmcm9tIFwiLi4vZW50aXR5L2VudGl0eS1tYW5hZ2VyXCI7XG5pbXBvcnQgeyBnZXRTb25hbXVFbnZpcm9ubWVudCB9IGZyb20gXCIuLi9lbnZcIjtcbmltcG9ydCB7IFNlcnZpY2VVbmF2YWlsYWJsZUV4Y2VwdGlvbiB9IGZyb20gXCIuLi9leGNlcHRpb25zL3NvLWV4Y2VwdGlvbnNcIjtcbmltcG9ydCB7IE5haXRlIH0gZnJvbSBcIi4uL25haXRlL25haXRlXCI7XG5pbXBvcnQgeyB0eXBlIEdlbk1pZ3JhdGlvbkNvZGUsIHR5cGUgTWlncmF0aW9uU2V0IH0gZnJvbSBcIi4uL3R5cGVzL3R5cGVzXCI7XG5pbXBvcnQgeyBpc0xvY2FsLCBpc1Rlc3QgfSBmcm9tIFwiLi4vdXRpbHMvY29udHJvbGxlclwiO1xuaW1wb3J0IHsgZXhpc3RzIH0gZnJvbSBcIi4uL3V0aWxzL2ZzLXV0aWxzXCI7XG5pbXBvcnQgeyBnZW5lcmF0ZUFsdGVyQ29kZSwgZ2VuZXJhdGVDcmVhdGVDb2RlIH0gZnJvbSBcIi4vY29kZS1nZW5lcmF0aW9uXCI7XG5pbXBvcnQgeyBnZXRNaWdyYXRpb25TZXRGcm9tRW50aXR5IH0gZnJvbSBcIi4vbWlncmF0aW9uLXNldFwiO1xuaW1wb3J0IHsgUG9zdGdyZVNRTFNjaGVtYVJlYWRlciB9IGZyb20gXCIuL3Bvc3RncmVzcWwtc2NoZW1hLXJlYWRlclwiO1xuaW1wb3J0IHsgdHlwZSBDb25uU3RyaW5nLCB0eXBlIE1pZ3JhdGlvbkNvZGUsIHR5cGUgTWlncmF0aW9uU3RhdHVzIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuZXhwb3J0IHR5cGUgTWlncmF0aW9uUmVzdWx0ID0ge1xuICBjb25uS2V5OiBzdHJpbmc7XG4gIGJhdGNoTm86IG51bWJlcjtcbiAgYXBwbGllZDogc3RyaW5nW107XG59W107XG5cbmV4cG9ydCBjbGFzcyBNaWdyYXRvciB7XG4gIHByaXZhdGUgaXNNaXNzaW5nTWlncmF0aW9uVGFibGVFcnJvcihlcnJvcjogdW5rbm93bik6IGJvb2xlYW4ge1xuICAgIGlmICh0eXBlb2YgZXJyb3IgIT09IFwib2JqZWN0XCIgfHwgZXJyb3IgPT09IG51bGwpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBtYXliZVBvc3RncmVzRXJyb3IgPSBlcnJvciBhcyB7IGNvZGU/OiB1bmtub3duOyBtZXNzYWdlPzogdW5rbm93biB9O1xuICAgIHJldHVybiAoXG4gICAgICBtYXliZVBvc3RncmVzRXJyb3IuY29kZSA9PT0gXCI0MlAwMVwiICYmXG4gICAgICB0eXBlb2YgbWF5YmVQb3N0Z3Jlc0Vycm9yLm1lc3NhZ2UgPT09IFwic3RyaW5nXCIgJiZcbiAgICAgIG1heWJlUG9zdGdyZXNFcnJvci5tZXNzYWdlLmluY2x1ZGVzKFwia25leF9taWdyYXRpb25zXCIpXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0TWlncmF0aW9uVGFyZ2V0S2V5cygpOiAoa2V5b2YgU29uYW11REJDb25maWcpW10ge1xuICAgIGNvbnN0IGNvbm5LZXlzID0gT2JqZWN0LmtleXMoU29uYW11LmRiQ29uZmlnKS5maWx0ZXIoXG4gICAgICAoa2V5KSA9PiAha2V5LmVuZHNXaXRoKFwiX3JlYWRvbmx5XCIpLFxuICAgICkgYXMgKGtleW9mIFNvbmFtdURCQ29uZmlnKVtdO1xuXG4gICAgaWYgKGlzTG9jYWwoKSkge1xuICAgICAgcmV0dXJuIGNvbm5LZXlzO1xuICAgIH1cblxuICAgIGNvbnN0IGVudmlyb25tZW50ID0gZ2V0U29uYW11RW52aXJvbm1lbnQoKTtcbiAgICByZXR1cm4gY29ubktleXMuZmlsdGVyKChrZXkpID0+IGtleSA9PT0gZW52aXJvbm1lbnQpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBydW5NaWdyYXRpb25zU2VxdWVudGlhbGx5KFxuICAgIGNvbm5zOiB7IGNvbm5LZXk6IGtleW9mIFNvbmFtdURCQ29uZmlnOyBrbmV4OiBLbmV4IH1bXSxcbiAgICBhY3Rpb246IFwiYXBwbHlcIiB8IFwicm9sbGJhY2tcIixcbiAgKTogUHJvbWlzZTxNaWdyYXRpb25SZXN1bHQ+IHtcbiAgICBjb25zdCByZXN1bHRzOiBNaWdyYXRpb25SZXN1bHQgPSBbXTtcblxuICAgIGZvciAoY29uc3QgeyBjb25uS2V5LCBrbmV4IH0gb2YgY29ubnMpIHtcbiAgICAgIGNvbnN0IFtiYXRjaE5vLCBhcHBsaWVkXSA9XG4gICAgICAgIGFjdGlvbiA9PT0gXCJhcHBseVwiID8gYXdhaXQga25leC5taWdyYXRlLmxhdGVzdCgpIDogYXdhaXQga25leC5taWdyYXRlLnJvbGxiYWNrKCk7XG5cbiAgICAgIHJlc3VsdHMucHVzaCh7XG4gICAgICAgIGNvbm5LZXksXG4gICAgICAgIGJhdGNoTm8sXG4gICAgICAgIGFwcGxpZWQsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZ2V0TWlncmF0aW9uQ29kZXMoKTogUHJvbWlzZTxNaWdyYXRpb25Db2RlW10+IHtcbiAgICBjb25zdCBzcmNNaWdyYXRpb25zRGlyID0gcGF0aC5qb2luKFNvbmFtdS5hcGlSb290UGF0aCwgXCJzcmNcIiwgXCJtaWdyYXRpb25zXCIpOyAvLyDsnbTqsbQg7ZmY6rK97JeQIOq0gOqzhOyXhuydtCDtla3sg4Egc3Jj7JeQ7IScIOywvuyVhOyVvCDtlbTsmpQuXG5cbiAgICBpZiAoIShhd2FpdCBleGlzdHMoc3JjTWlncmF0aW9uc0RpcikpKSB7XG4gICAgICBhd2FpdCBta2RpcihzcmNNaWdyYXRpb25zRGlyLCB7XG4gICAgICAgIHJlY3Vyc2l2ZTogdHJ1ZSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IGNvZGVzID0gKGF3YWl0IHJlYWRkaXIoc3JjTWlncmF0aW9uc0RpcikpXG4gICAgICAuZmlsdGVyKChmKSA9PiBmLmVuZHNXaXRoKFwiLnRzXCIpKVxuICAgICAgLm1hcCgoZikgPT4gKHtcbiAgICAgICAgbmFtZTogZi5yZXBsYWNlKFwiLnRzXCIsIFwiXCIpLFxuICAgICAgICBwYXRoOiBwYXRoLmpvaW4oc3JjTWlncmF0aW9uc0RpciwgZiksXG4gICAgICB9KSlcbiAgICAgIC50b1NvcnRlZCgoYSwgYikgPT4gKGEubmFtZSA8IGIubmFtZSA/IDEgOiAtMSkpOyAvLyDsnbTrpoQg64K066a87LCo7IicIOygleugrCjstZzsi6DsiJwpXG5cbiAgICBOYWl0ZS50KFwibWlncmF0b3I6Z2V0TWlncmF0aW9uQ29kZXM6cmVzdWx0c1wiLCBjb2Rlcyk7XG4gICAgcmV0dXJuIGNvZGVzO1xuICB9XG5cbiAgLyoqXG4gICAqIO2DgOqyn+uzhCDrp4jsnbTqt7jroIjsnbTshZgg7IOB7YOc7JmAIOy9lOuTnCDsg53shLEv7KSA67mEIOyDge2DnOulvCDqtaztlbTsmLXri4jri6QuXG4gICAqIOyLpOygnOuhnCBEQuyXkCDsoJHqt7zrj4Qg7ZWY6rOgIOuniOydtOq3uOugiOydtOyFmCDsvZTrk5wg7YyM7J2864+EIO2ZleyduO2VmOqzoCxcbiAgICog7ZWE7JqU7ZWY64uk66m0IOyggeyaqe2VoCDsiJgg7J6I64qUIOy9lOuTnOulvCDsg53shLHquYzsp4Ag7ZW07Ji164uI64ukLlxuICAgKlxuICAgKiBDTEnsmYAgU29uYW11IFVJ7JeQ7IScIOyCrOyaqeuQqeuLiOuLpC5cbiAgICpcbiAgICogQHJldHVybnNcbiAgICovXG4gIGFzeW5jIGdldFN0YXR1cygpOiBQcm9taXNlPE1pZ3JhdGlvblN0YXR1cz4ge1xuICAgIGNvbnN0IGNvZGVzID0gYXdhaXQgdGhpcy5nZXRNaWdyYXRpb25Db2RlcygpO1xuICAgIE5haXRlLnQoXCJtaWdyYXRvcjpnZXRTdGF0dXM6Y29kZXNcIiwgY29kZXMpO1xuXG4gICAgY29uc3QgY29ubktleXMgPSB0aGlzLmdldE1pZ3JhdGlvblRhcmdldEtleXMoKTtcblxuICAgIGxldCBtaWdyYXRpb25TdGF0dXNFcnJvcjogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gICAgY29uc3Qgc3RhdHVzZXMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIGNvbm5LZXlzLm1hcChhc3luYyAoY29ubktleSkgPT4ge1xuICAgICAgICBjb25zdCBrbmV4T3B0aW9ucyA9IFNvbmFtdS5kYkNvbmZpZ1tjb25uS2V5XTtcbiAgICAgICAgY29uc3QgdENvbm4gPSBjcmVhdGVLbmV4SW5zdGFuY2Uoa25leE9wdGlvbnMpO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3Qgc3RhdHVzOiBudW1iZXIgfCBcImVycm9yXCIgPSBhd2FpdCAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRDb25uLm1pZ3JhdGUuc3RhdHVzKCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgaWYgKHRoaXMuaXNNaXNzaW5nTWlncmF0aW9uVGFibGVFcnJvcihlcnIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgICAgICBjaGFsay55ZWxsb3coXG4gICAgICAgICAgICAgICAgICBgJHtjb25uS2V5feydmCDrp4jsnbTqt7jroIjsnbTshZgg7IOB7YOc66W8IOqwgOyguOyYpOuKlCDrjbDsl5Ag7Iuk7Yyo7ZWY7JiA7Iq164uI64ukLiDrjbDsnbTthLDrsqDsnbTsiqTqsIAg7Jis67CU66W06rKMIOq1rOyEseuQmOyngCDslYrsnYAg6rKDIOqwmeyKteuLiOuLpC4g7ZmV7J247ZWY7Iuc6rOgIOuLpOyLnCDsi5zrj4TtlbTso7zshLjsmpQuXFxu7Iuc64+E7ZWcIOyXsOqysCDshKTsoJU6XFxuJHtKU09OLnN0cmluZ2lmeShrbmV4T3B0aW9ucy5jb25uZWN0aW9uLCBudWxsLCAyKX1cXG7rsJzsg53tlZwg7JeQ65+sOlxcbiR7ZXJyfVxcbmAsXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgbWlncmF0aW9uU3RhdHVzRXJyb3IgPSBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVycik7XG4gICAgICAgICAgICAgIHJldHVybiBcImVycm9yXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSkoKTtcbiAgICAgICAgICBjb25zdCBwZW5kaW5nOiBzdHJpbmdbXSA9IGF3YWl0IChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBjb25zdCBbLCBmZExpc3RdID0gYXdhaXQgdENvbm4ubWlncmF0ZS5saXN0KCk7XG4gICAgICAgICAgICAgIHJldHVybiBmZExpc3QubWFwKChmZDogeyBmaWxlOiBzdHJpbmcgfSkgPT4gZmQuZmlsZS5yZXBsYWNlKFwiLnRzXCIsIFwiXCIpKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICBpZiAodGhpcy5pc01pc3NpbmdNaWdyYXRpb25UYWJsZUVycm9yKGVycikpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY29kZXMubWFwKChjb2RlKSA9PiBjb2RlLm5hbWUpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgbWlncmF0aW9uU3RhdHVzRXJyb3IgPSBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVycik7XG4gICAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KSgpO1xuICAgICAgICAgIGNvbnN0IGN1cnJlbnRWZXJzaW9uOiBzdHJpbmcgfCBcImVycm9yXCIgPSBhd2FpdCAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRDb25uLm1pZ3JhdGUuY3VycmVudFZlcnNpb24oKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKF9lcnIpIHtcbiAgICAgICAgICAgICAgaWYgKHRoaXMuaXNNaXNzaW5nTWlncmF0aW9uVGFibGVFcnJvcihfZXJyKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBcIm5vbmVcIjtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIG1pZ3JhdGlvblN0YXR1c0Vycm9yID0gX2VyciBpbnN0YW5jZW9mIEVycm9yID8gX2Vyci5tZXNzYWdlIDogU3RyaW5nKF9lcnIpO1xuICAgICAgICAgICAgICByZXR1cm4gXCJlcnJvclwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pKCk7XG4gICAgICAgICAgTmFpdGUudChcIm1pZ3JhdG9yOmdldFN0YXR1czpzdGF0dXNcIiwgc3RhdHVzKTtcblxuICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBrbmV4T3B0aW9ucy5jb25uZWN0aW9uIGFzIEtuZXguUGdDb25uZWN0aW9uQ29uZmlnO1xuXG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIG5hbWU6IGNvbm5LZXksXG4gICAgICAgICAgICBjb25uS2V5LFxuICAgICAgICAgICAgY29ublN0cmluZzogYHBnOi8vJHtjb25uZWN0aW9uLnVzZXIgPz8gXCJcIn1AJHtjb25uZWN0aW9uLmhvc3R9OiR7XG4gICAgICAgICAgICAgIGNvbm5lY3Rpb24ucG9ydFxuICAgICAgICAgICAgfS8ke2Nvbm5lY3Rpb24uZGF0YWJhc2V9YCBhcyBDb25uU3RyaW5nLFxuICAgICAgICAgICAgY3VycmVudFZlcnNpb24sXG4gICAgICAgICAgICBzdGF0dXM6IHN0YXR1cyxcbiAgICAgICAgICAgIHBlbmRpbmcsXG4gICAgICAgICAgfTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICBhd2FpdCB0Q29ubi5kZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICBOYWl0ZS50KFwibWlncmF0b3I6Z2V0U3RhdHVzOmNvbm5zXCIsIHN0YXR1c2VzKTtcblxuICAgIGNvbnN0IHByZXBhcmVkQ29kZXM6IEdlbk1pZ3JhdGlvbkNvZGVbXSA9IGF3YWl0IChhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzdGF0dXMwY29ubiA9IHN0YXR1c2VzLmZpbmQoKHN0YXR1cykgPT4gc3RhdHVzLnN0YXR1cyA9PT0gMCk7XG4gICAgICBpZiAoc3RhdHVzMGNvbm4gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgY2hhbGsueWVsbG93KFxuICAgICAgICAgICAgYFdoaWxlIHRyeWluZyB0byBwcmVwYXJlIG1pZ3JhdGlvbiBjb2Rlcywgd2UgZm91bmQgdGhhdCB0aGVyZSBpcyBubyBkYXRhYmFzZSB0byBjb21wYXJlIG1pZ3JhdGlvbnMuIFdlIG5lZWQgYXQgbGVhc3Qgb25lIGRhdGFiYXNlIHdoZXJlIGV2ZXJ5IG1pZ3JhdGlvbiBpcyBhcHBsaWVkKHN0YXR1cyA9PT0gMCkuIFlvdSBtaWdodCB3YW50IHRvIGFwcGx5IHlvdXIgZXhpc3RpbmcgbWlncmF0aW9ucyB0byBvbmUgb2YgdGhlIGRhdGFiYXNlcy5gLFxuICAgICAgICAgICksXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY29tcGFyZURCY29ubiA9IGNyZWF0ZUtuZXhJbnN0YW5jZShTb25hbXUuZGJDb25maWdbc3RhdHVzMGNvbm4uY29ubktleV0pO1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuY29tcGFyZU1pZ3JhdGlvbnMoY29tcGFyZURCY29ubik7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBhd2FpdCBjb21wYXJlREJjb25uLmRlc3Ryb3koKTtcbiAgICAgIH1cbiAgICB9KSgpO1xuXG4gICAgTmFpdGUudChcIm1pZ3JhdG9yOmdldFN0YXR1czpwcmVwYXJlZENvZGVzXCIsIHByZXBhcmVkQ29kZXMpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbm5zOiBzdGF0dXNlcyxcbiAgICAgIGNvZGVzLFxuICAgICAgcHJlcGFyZWRDb2RlcyxcbiAgICAgIGVycm9yOiBtaWdyYXRpb25TdGF0dXNFcnJvcixcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIOuniOydtOq3uOugiOydtOyFmOydhCDsoIHsmqntlZjqsbDrgpgg66Gk67Cx7ZWp64uI64ukLlxuICAgKiBTb25hbXUgVUnsl5DshJwg66eI7J206re466CI7J207IWYIOyekeyXheydhCDsiJjtlontlaAg65WMIOyCrOyaqeuQqeuLiOuLpC5cbiAgICpcbiAgICogQ0xJ7JmAIFNvbmFtdSBVSeyXkOyEnCDsgqzsmqnrkKnri4jri6QuXG4gICAqXG4gICAqIEBwYXJhbSBhY3Rpb24g7J6R7JeFIOycoO2YlSAoYXBwbHkvcm9sbGJhY2spXG4gICAqIEBwYXJhbSB0YXJnZXRzIOyekeyXhSDrjIDsg4EgREIg7ISk7KCVIO2CpCAoa2V5b2YgU29uYW11REJDb25maWcpXG4gICAqIEByZXR1cm5zIOyekeyXhSDqsrDqs7xcbiAgICovXG4gIGFzeW5jIHJ1bkFjdGlvbihcbiAgICBhY3Rpb246IFwiYXBwbHlcIiB8IFwicm9sbGJhY2tcIixcbiAgICB0YXJnZXRzOiAoa2V5b2YgU29uYW11REJDb25maWcpW10sXG4gICk6IFByb21pc2U8TWlncmF0aW9uUmVzdWx0PiB7XG4gICAgTmFpdGUudChcIm1pZ3JhdG9yOnJ1bkFjdGlvbjphY3Rpb25cIiwgYWN0aW9uKTtcbiAgICBOYWl0ZS50KFwibWlncmF0b3I6cnVuQWN0aW9uOnRhcmdldHNcIiwgdGFyZ2V0cyk7XG5cbiAgICBjb25zdCBhbGxvd2VkVGFyZ2V0cyA9IG5ldyBTZXQodGhpcy5nZXRNaWdyYXRpb25UYXJnZXRLZXlzKCkpO1xuICAgIGNvbnN0IGRpc2FsbG93ZWRUYXJnZXRzID0gdGFyZ2V0cy5maWx0ZXIoKHRhcmdldCkgPT4gIWFsbG93ZWRUYXJnZXRzLmhhcyh0YXJnZXQpKTtcbiAgICBpZiAoZGlzYWxsb3dlZFRhcmdldHMubGVuZ3RoID4gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgTWlncmF0aW9uIHRhcmdldHMgYXJlIG5vdCBhbGxvd2VkIGluIE5PREVfRU5WPSR7Z2V0U29uYW11RW52aXJvbm1lbnQoKX06ICR7ZGlzYWxsb3dlZFRhcmdldHMuam9pbihcIiwgXCIpfWAsXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIGdldCB1bmlxIGtuZXggY29uZmlnc1xuICAgIGNvbnN0IGNvbmZpZ3MgPSB1bmlxdWUoXG4gICAgICB0YXJnZXRzXG4gICAgICAgIC5tYXAoKHRhcmdldCkgPT4gKHtcbiAgICAgICAgICBjb25uS2V5OiB0YXJnZXQsXG4gICAgICAgICAgb3B0aW9uczogU29uYW11LmRiQ29uZmlnW3RhcmdldF0sXG4gICAgICAgIH0pKVxuICAgICAgICAuZmlsdGVyKChjKSA9PiBjLm9wdGlvbnMgIT09IHVuZGVmaW5lZCksXG4gICAgICAoeyBvcHRpb25zIH0pID0+XG4gICAgICAgIGAkeyhvcHRpb25zLmNvbm5lY3Rpb24gYXMgS25leC5QZ0Nvbm5lY3Rpb25Db25maWcpLmhvc3R9OiR7XG4gICAgICAgICAgKG9wdGlvbnMuY29ubmVjdGlvbiBhcyBLbmV4LlBnQ29ubmVjdGlvbkNvbmZpZykucG9ydCA/PyA1NDMyXG4gICAgICAgIH0vJHsob3B0aW9ucy5jb25uZWN0aW9uIGFzIEtuZXguUGdDb25uZWN0aW9uQ29uZmlnKS5kYXRhYmFzZX1gLFxuICAgICk7XG5cbiAgICAvLyBnZXQgY29ubmVjdGlvbnNcbiAgICBjb25zdCBjb25ucyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgY29uZmlncy5tYXAoYXN5bmMgKGNvbmZpZykgPT4gKHtcbiAgICAgICAgY29ubktleTogY29uZmlnLmNvbm5LZXksXG4gICAgICAgIGtuZXg6IGNyZWF0ZUtuZXhJbnN0YW5jZShjb25maWcub3B0aW9ucyksXG4gICAgICB9KSksXG4gICAgKTtcblxuICAgIHRyeSB7XG4gICAgICAvLyBhY3Rpb25cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IChhc3luYyAoKSA9PiB7XG4gICAgICAgIHN3aXRjaCAoYWN0aW9uKSB7XG4gICAgICAgICAgY2FzZSBcImFwcGx5XCI6XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ydW5NaWdyYXRpb25zU2VxdWVudGlhbGx5KGNvbm5zLCBcImFwcGx5XCIpO1xuICAgICAgICAgIGNhc2UgXCJyb2xsYmFja1wiOlxuICAgICAgICAgICAgcmV0dXJuIHRoaXMucnVuTWlncmF0aW9uc1NlcXVlbnRpYWxseShjb25ucywgXCJyb2xsYmFja1wiKTtcbiAgICAgICAgfVxuICAgICAgfSkoKTtcblxuICAgICAgTmFpdGUudChcIm1pZ3JhdG9yOnJ1bkFjdGlvbjpyZXN1bHRcIiwgcmVzdWx0KTtcblxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIGNvbm5zLm1hcCgoeyBrbmV4IH0pID0+IHtcbiAgICAgICAgICByZXR1cm4ga25leC5kZXN0cm95KCk7XG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICog7IKt7KCcIOqwgOuKpe2VnCDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcIO2MjOydvOydhCDqsoDspp3tlanri4jri6QuXG4gICAqXG4gICAqIEBwYXJhbSBjb25ucyDrp4jsnbTqt7jroIjsnbTshZgg7IOB7YOcIOuwsOyXtFxuICAgKiBAcGFyYW0gY29kZU5hbWVzIOyCreygnO2VoCDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcIO2MjOydvCDsnbTrpoQg67Cw7Je0XG4gICAqIEByZXR1cm5zIOyCreygnCDqsIDriqUg7Jes67aAIOuwjyDsoIHsmqnrkJwg66eI7J206re466CI7J207IWYIOy9lOuTnCDtjIzsnbwg7J2066aEXG4gICAqL1xuICB2YWxpZGF0ZURlbGV0YWJsZShjb25uczogTWlncmF0aW9uU3RhdHVzW1wiY29ubnNcIl0sIGNvZGVOYW1lczogc3RyaW5nW10pIHtcbiAgICBjb25zdCBhcHBsaWVkQ29kZXMgPSBjb2RlTmFtZXMuZmlsdGVyKChjb2RlTmFtZSkgPT5cbiAgICAgIGNvbm5zLnNvbWUoKGNvbm4pID0+ICFjb25uLnBlbmRpbmcuaW5jbHVkZXMoY29kZU5hbWUpKSxcbiAgICApO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNhbkRlbGV0ZTogYXBwbGllZENvZGVzLmxlbmd0aCA9PT0gMCxcbiAgICAgIGFwcGxpZWRDb2RlcyxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIOuniOydtOq3uOugiOydtOyFmCDsvZTrk5wg7YyM7J287J2EIOyCreygnO2VqeuLiOuLpC5cbiAgICpcbiAgICogU29uYW11IFVJ7JeQ7IScIOyCrOyaqeuQqeuLiOuLpC5cbiAgICpcbiAgICogQHBhcmFtIGNvZGVOYW1lcyDsgq3soJztlaAg66eI7J206re466CI7J207IWYIOy9lOuTnCDtjIzsnbwg7J2066aEIOuwsOyXtFxuICAgKiBAcmV0dXJucyDsgq3soJzrkJwg66eI7J206re466CI7J207IWYIOy9lOuTnCDtjIzsnbwg6rCc7IiYXG4gICAqL1xuICBhc3luYyBkZWxDb2Rlcyhjb2RlTmFtZXM6IHN0cmluZ1tdKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCB7IGNvbm5zIH0gPSBhd2FpdCB0aGlzLmdldFN0YXR1cygpO1xuICAgIGNvbnN0IHsgY2FuRGVsZXRlLCBhcHBsaWVkQ29kZXMgfSA9IHRoaXMudmFsaWRhdGVEZWxldGFibGUoY29ubnMsIGNvZGVOYW1lcyk7XG4gICAgaWYgKCFjYW5EZWxldGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFlvdSBjYW5ub3QgZGVsZXRlIGEgbWlncmF0aW9uIGZpbGUgaWYgdGhlcmUgaXMgYWxyZWFkeSBhcHBsaWVkLiBBcHBsaWVkIGNvZGVzOiAke2FwcGxpZWRDb2Rlcy5qb2luKFwiLCBcIil9YCxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHN1bShcbiAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBjb2RlTmFtZXMubWFwKGFzeW5jIChjb2RlTmFtZSkgPT4ge1xuICAgICAgICAgIGNvbnN0IGZpbGVQYXRoID0gYCR7U29uYW11LmFwaVJvb3RQYXRofS9zcmMvbWlncmF0aW9ucy8ke2NvZGVOYW1lfS50c2A7XG4gICAgICAgICAgaWYgKGF3YWl0IGV4aXN0cyhmaWxlUGF0aCkpIHtcbiAgICAgICAgICAgIGF3YWl0IHVubGluayhmaWxlUGF0aCk7XG4gICAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH0pLFxuICAgICAgKSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBnZW5EYXRlVGFnKGluZGV4OiBudW1iZXIsIGJhc2VEYXRlOiBEYXRlID0gbmV3IERhdGUoKSk6IHN0cmluZyB7XG4gICAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKGJhc2VEYXRlLmdldFRpbWUoKSArIGluZGV4ICogMTAwMCk7XG4gICAgY29uc3QgcGFkID0gKG51bTogbnVtYmVyLCBzaXplOiBudW1iZXIgPSAyKSA9PiBudW0udG9TdHJpbmcoKS5wYWRTdGFydChzaXplLCBcIjBcIik7XG4gICAgcmV0dXJuIChcbiAgICAgIGRhdGUuZ2V0RnVsbFllYXIoKS50b1N0cmluZygpICtcbiAgICAgIHBhZChkYXRlLmdldE1vbnRoKCkgKyAxKSArXG4gICAgICBwYWQoZGF0ZS5nZXREYXRlKCkpICtcbiAgICAgIHBhZChkYXRlLmdldEhvdXJzKCkpICtcbiAgICAgIHBhZChkYXRlLmdldE1pbnV0ZXMoKSkgK1xuICAgICAgcGFkKGRhdGUuZ2V0U2Vjb25kcygpKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICog66eI7J206re466CI7J207IWYIOy9lOuTnCDtjIzsnbzsnYQg7IOd7ISx7ZWp64uI64ukLlxuICAgKlxuICAgKiBTb25hbXUgVUnsl5DshJwg7IKs7Jqp65Cp64uI64ukLlxuICAgKlxuICAgKiBAcmV0dXJucyDsg53shLHrkJwg66eI7J206re466CI7J207IWYIOy9lOuTnCDtjIzsnbwg6rCc7IiYXG4gICAqL1xuICBhc3luYyBnZW5lcmF0ZVByZXBhcmVkQ29kZXMoKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCB7IHByZXBhcmVkQ29kZXMgfSA9IGF3YWl0IHRoaXMuZ2V0U3RhdHVzKCk7XG4gICAgTmFpdGUudChcIm1pZ3JhdG9yOmdlbmVyYXRlUHJlcGFyZWRDb2RlczpwcmVwYXJlZENvZGVzXCIsIHByZXBhcmVkQ29kZXMpO1xuICAgIGlmIChwcmVwYXJlZENvZGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgY29uc29sZS5sb2coY2hhbGsuZ3JlZW4oXCJcXG7tmITsnqwg66qo65GQIOyLse2BrOuQnCDsg4Htg5zsnoXri4jri6QuXCIpKTtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cblxuICAgIC8vIOyLpOygnCDsvZTrk5wg7IOd7ISxXG4gICAgY29uc3QgbWlncmF0aW9uc0RpciA9IGAke1NvbmFtdS5hcGlSb290UGF0aH0vc3JjL21pZ3JhdGlvbnNgO1xuXG4gICAgZm9yIChjb25zdCBbaW5kZXgsIHBjb2RlXSBvZiBwcmVwYXJlZENvZGVzLmVudHJpZXMoKSkge1xuICAgICAgaWYgKHBjb2RlLmZvcm1hdHRlZCkge1xuICAgICAgICBjb25zdCBkYXRlVGFnID0gdGhpcy5nZW5EYXRlVGFnKGluZGV4KTtcbiAgICAgICAgY29uc3QgZmlsZVBhdGggPSBgJHttaWdyYXRpb25zRGlyfS8ke2RhdGVUYWd9XyR7cGNvZGUudGl0bGV9LnRzYDtcbiAgICAgICAgYXdhaXQgd3JpdGVGaWxlKGZpbGVQYXRoLCBwY29kZS5mb3JtYXR0ZWQpO1xuICAgICAgICAhaXNUZXN0KCkgJiYgY29uc29sZS5sb2coY2hhbGsuZ3JlZW4oYE1JR1JBVElPTiBDUkVBVEVEICR7ZmlsZVBhdGh9YCkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBwcmVwYXJlZENvZGVzLmxlbmd0aDtcbiAgfVxuXG4gIGFzeW5jIGNvbXBhcmVNaWdyYXRpb25zKGNvbXBhcmVEQjogS25leCk6IFByb21pc2U8R2VuTWlncmF0aW9uQ29kZVtdPiB7XG4gICAgLy8gRW50aXR5IOyInO2ajO2VmOyXrCDsi7HtgaxcbiAgICBjb25zdCBlbnRpdHlJZHMgPSBFbnRpdHlNYW5hZ2VyLmdldEFsbElkcygpO1xuXG4gICAgLy8g7KGw7J247YWM7J2067iUIO2PrO2VqO2VmOyXrCBFbnRpdHnsl5DshJwgTWlncmF0aW9uU2V0IOy2lOy2nFxuICAgIGNvbnN0IGVudGl0eVNldHNXaXRoSm9pblRhYmxlID0gZW50aXR5SWRzXG4gICAgICAuZmlsdGVyKChlbnRpdHlJZCkgPT4gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpLnByb3BzLmxlbmd0aCA+IDApXG4gICAgICAubWFwKChlbnRpdHlJZCkgPT4gZ2V0TWlncmF0aW9uU2V0RnJvbUVudGl0eShFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCkpKTtcblxuICAgIC8vIOyhsOyduO2FjOydtOu4lOunjCDstpTstpxcbiAgICBjb25zdCBqb2luVGFibGVzV2l0aER1cCA9IGVudGl0eVNldHNXaXRoSm9pblRhYmxlLmZsYXRNYXAoKGVudGl0eVNldCkgPT4gZW50aXR5U2V0LmpvaW5UYWJsZXMpO1xuICAgIC8vIOykkeuztSDsoJzqsbAgKOykkeuzteyduCDqsr3smrAgaW5kZXhlc+ulvCDrs5HtlakpXG4gICAgY29uc3Qgam9pblRhYmxlcyA9IE9iamVjdC52YWx1ZXMoZ3JvdXAoam9pblRhYmxlc1dpdGhEdXAsIChqdCkgPT4ganQudGFibGUpKS5tYXAoKHRhYmxlcykgPT4ge1xuICAgICAgYXNzZXJ0KHRhYmxlcyAhPT0gdW5kZWZpbmVkLCBcInRhYmxlcyBpcyB1bmRlZmluZWRcIik7XG4gICAgICBpZiAodGFibGVzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICByZXR1cm4gdGFibGVzWzBdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4udGFibGVzWzBdLFxuICAgICAgICBpbmRleGVzOiB1bmlxdWUoXG4gICAgICAgICAgdGFibGVzLmZsYXRNYXAoKHQpID0+IHQuaW5kZXhlcyksXG4gICAgICAgICAgKGluZGV4KSA9PiBbaW5kZXgudHlwZSwgLi4uaW5kZXguY29sdW1uc10uam9pbihcIi1cIiksXG4gICAgICAgICksXG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgLy8g7KGw7J247YWM7J2067iUIO2PrO2VqO2VmOyXrCBNaWdyYXRpb25TZXQg67Cw7Je0XG4gICAgY29uc3QgZW50aXR5U2V0czogTWlncmF0aW9uU2V0W10gPSBbLi4uZW50aXR5U2V0c1dpdGhKb2luVGFibGUsIC4uLmpvaW5UYWJsZXNdO1xuXG4gICAgY29uc3QgY29kZXM6IEdlbk1pZ3JhdGlvbkNvZGVbXSA9IFtdO1xuICAgIGNvbnN0IGJhdGNoU2l6ZSA9IDQ7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGVudGl0eVNldHMubGVuZ3RoOyBpICs9IGJhdGNoU2l6ZSkge1xuICAgICAgY29uc3QgYmF0Y2hDb2RlcyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBlbnRpdHlTZXRzLnNsaWNlKGksIGkgKyBiYXRjaFNpemUpLm1hcChhc3luYyAoZW50aXR5U2V0KSA9PiB7XG4gICAgICAgICAgY29uc3QgZGJTZXQgPSBhd2FpdCBQb3N0Z3JlU1FMU2NoZW1hUmVhZGVyLmdldE1pZ3JhdGlvblNldEZyb21EQihcbiAgICAgICAgICAgIGNvbXBhcmVEQixcbiAgICAgICAgICAgIGVudGl0eVNldC50YWJsZSxcbiAgICAgICAgICApO1xuICAgICAgICAgIE5haXRlLnQoYG1pZ3JhdG9yOmNvbXBhcmVNaWdyYXRpb25zOmVudGl0eVNldDoke2VudGl0eVNldC50YWJsZX1gLCBlbnRpdHlTZXQpO1xuICAgICAgICAgIE5haXRlLnQoYG1pZ3JhdG9yOmNvbXBhcmVNaWdyYXRpb25zOmRiU2V0OiR7ZW50aXR5U2V0LnRhYmxlfWAsIGRiU2V0KTtcblxuICAgICAgICAgIGlmIChkYlNldCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgLy8g6riw7KG0IO2FjOydtOu4lCDsl4bsnYwsIOyDiOuhnCDthYzsnbTruJQg7IOd7ISxXG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgZ2VuZXJhdGVDcmVhdGVDb2RlKGVudGl0eVNldCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIOq4sOyhtCDthYzsnbTruJQg7KG07J6s7ZWY64qUIOy8gOydtOyKpFxuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IGdlbmVyYXRlQWx0ZXJDb2RlKGVudGl0eVNldCwgZGJTZXQsIGNvbXBhcmVEQik7XG4gICAgICAgICAgfVxuICAgICAgICB9KSxcbiAgICAgICk7XG5cbiAgICAgIGNvZGVzLnB1c2goLi4uYmF0Y2hDb2Rlcy5mbGF0KCkpO1xuICAgIH1cblxuICAgIC8vIG5vcm1hbCDtg4DsnoXsnbQg7JWe7Jy866GcLCBmb3JlaWdu7J20IOuSpOuhnFxuICAgIGNvZGVzLnNvcnQoKGNvZGVBLCBjb2RlQikgPT4ge1xuICAgICAgaWYgKGNvZGVBLnR5cGUgPT09IFwiZm9yZWlnblwiICYmIGNvZGVCLnR5cGUgPT09IFwibm9ybWFsXCIpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9IGVsc2UgaWYgKGNvZGVBLnR5cGUgPT09IFwibm9ybWFsXCIgJiYgY29kZUIudHlwZSA9PT0gXCJmb3JlaWduXCIpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4gY29kZXM7XG4gIH1cblxuICAvKipcbiAgICogU2hhZG93IERCIO2FjOyKpO2KuOulvCDsp4Ttlontlanri4jri6QuXG4gICAqXG4gICAqIFNvbmFtdSBVSeyXkOyEnCDsgqzsmqnrkKnri4jri6QuXG4gICAqXG4gICAqIEByZXR1cm5zIFNoYWRvdyBEQiDthYzsiqTtirgg6rKw6rO8XG4gICAqL1xuICBhc3luYyBydW5TaGFkb3dUZXN0KCk6IFByb21pc2U8TWlncmF0aW9uUmVzdWx0PiB7XG4gICAgY29uc3QgYmFzZVRlc3RDb25uID0gU29uYW11LmRiQ29uZmlnLnRlc3QuY29ubmVjdGlvbiBhcyBLbmV4LlBnQ29ubmVjdGlvbkNvbmZpZztcbiAgICBjb25zdCB3b3JrZXJJZCA9IHByb2Nlc3MuZW52LlNPTkFNVV9XT1JLRVJfREIgPT09IFwidHJ1ZVwiID8gcHJvY2Vzcy5lbnYuVklURVNUX1BPT0xfSUQgOiBudWxsO1xuICAgIGNvbnN0IHRlbXBsYXRlRGF0YWJhc2UgPVxuICAgICAgd29ya2VySWQgIT09IG51bGwgPyBgJHtiYXNlVGVzdENvbm4uZGF0YWJhc2V9XyR7d29ya2VySWQgPz8gXCIxXCJ9YCA6IGJhc2VUZXN0Q29ubi5kYXRhYmFzZTtcbiAgICBjb25zdCB0ZGJDb25uID0geyAuLi5iYXNlVGVzdENvbm4sIGRhdGFiYXNlOiB0ZW1wbGF0ZURhdGFiYXNlIH07XG4gICAgY29uc3Qgc2hhZG93RGF0YWJhc2UgPSBgJHt0ZW1wbGF0ZURhdGFiYXNlfV9fbWlncmF0aW9uX3NoYWRvd2A7XG5cbiAgICAvLyDthYzsiqTtirgg7IOB7Zmp7JeQ7ISc64qUIO2KuOuenOyereyFmOydhCDstIjquLDtmZTtlZjqs6AsIOyDiCDrjbDsnbTthLDrsqDsnbTsiqQg7Luk64Sl7IWY7J2EIOqwgOyguOyZgOyVvCDtlahcbiAgICBpZiAoaXNUZXN0KCkpIHtcbiAgICAgIGF3YWl0IERCLmNsZWFyVGVzdFRyYW5zYWN0aW9uKCk7XG4gICAgICBhd2FpdCBEQi5kZXN0cm95KCk7XG4gICAgfVxuXG4gICAgLy8g6riw7KG0IFNoYWRvdyBEQiDsgq3soJwg7ZuEIFNoYWRvdyBEQiDsg53shLFcbiAgICBjb25zdCB0ZGIgPSBjcmVhdGVLbmV4SW5zdGFuY2Uoe1xuICAgICAgLi4uU29uYW11LmRiQ29uZmlnLnRlc3QsXG4gICAgICBjb25uZWN0aW9uOiB7XG4gICAgICAgIC4uLmJhc2VUZXN0Q29ubixcbiAgICAgICAgZGF0YWJhc2U6IFwicG9zdGdyZXNcIixcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgdHJ5IHtcbiAgICAgICFpc1Rlc3QoKSAmJiBjb25zb2xlLmxvZyhjaGFsay5tYWdlbnRhKGAke3NoYWRvd0RhdGFiYXNlfSDsgq3soJxgKSk7XG4gICAgICBhd2FpdCB0ZGIucmF3KGBEUk9QIERBVEFCQVNFIElGIEVYSVNUUyAke3NoYWRvd0RhdGFiYXNlfWApO1xuICAgICAgYXdhaXQgdGRiLnJhdyhgXG4gICAgICAgIFNFTEVDVCBwZ190ZXJtaW5hdGVfYmFja2VuZChwZ19zdGF0X2FjdGl2aXR5LnBpZClcbiAgICAgICAgRlJPTSBwZ19zdGF0X2FjdGl2aXR5XG4gICAgICAgIFdIRVJFIGRhdG5hbWUgPSAnJHt0ZGJDb25uLmRhdGFiYXNlfSdcbiAgICAgICAgICBBTkQgcGlkIDw+IHBnX2JhY2tlbmRfcGlkKCk7XG4gICAgICBgKTtcbiAgICAgIGF3YWl0IHRkYi5yYXcoYENSRUFURSBEQVRBQkFTRSAke3NoYWRvd0RhdGFiYXNlfSBURU1QTEFURSAke3RkYkNvbm4uZGF0YWJhc2V9YCk7XG5cbiAgICAgIC8vIFNoYWRvdyBEQuyXkCDsl7DqsrBcbiAgICAgIGNvbnN0IHNkYiA9IGNyZWF0ZUtuZXhJbnN0YW5jZSh7XG4gICAgICAgIC4uLlNvbmFtdS5kYkNvbmZpZy50ZXN0LFxuICAgICAgICBjb25uZWN0aW9uOiB7XG4gICAgICAgICAgLi4udGRiQ29ubixcbiAgICAgICAgICBkYXRhYmFzZTogc2hhZG93RGF0YWJhc2UsXG4gICAgICAgICAgcGFzc3dvcmQ6IHRkYkNvbm4ucGFzc3dvcmQsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgLy8gc2hhZG93IERCIO2FjOyKpO2KuCDsp4TtlolcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IFtiYXRjaE5vLCBhcHBsaWVkXSA9IGF3YWl0IHNkYi5taWdyYXRlLmxhdGVzdCgpO1xuICAgICAgICAhaXNUZXN0KCkgJiZcbiAgICAgICAgICBjb25zb2xlLmxvZyhjaGFsay5ncmVlbihcIlNoYWRvdyBEQiDthYzsiqTtirjsl5Ag7ISx6rO17ZaI7Iq164uI64ukIVwiKSwge1xuICAgICAgICAgICAgYmF0Y2hObyxcbiAgICAgICAgICAgIGFwcGxpZWQsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBjb25uS2V5OiBcInNoYWRvd1wiLFxuICAgICAgICAgICAgYmF0Y2hObyxcbiAgICAgICAgICAgIGFwcGxpZWQsXG4gICAgICAgICAgfSxcbiAgICAgICAgXTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgICAgdGhyb3cgbmV3IFNlcnZpY2VVbmF2YWlsYWJsZUV4Y2VwdGlvbihTRChcInNvbmFtdS5lcnJvci5zaGFkb3dEYlRlc3RGYWlsZWRcIikpO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYXdhaXQgc2RiLmRlc3Ryb3koKTtcbiAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgLy8gU2hhZG93IERCIOyCreygnFxuICAgICAgIWlzVGVzdCgpICYmIGNvbnNvbGUubG9nKGNoYWxrLm1hZ2VudGEoYCR7c2hhZG93RGF0YWJhc2V9IOyCreygnGApKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHRkYi5yYXcoYERST1AgREFUQUJBU0UgSUYgRVhJU1RTICR7c2hhZG93RGF0YWJhc2V9YCk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJTaGFkb3cgREIg7KCV66asIOyLpO2MqDpcIiwgZSk7IC8vIOydtOqyjCDsl4bsnLzrqbQg7KGw7Jqp7Z6IIOuIhOyImFxuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYXdhaXQgdGRiLmRlc3Ryb3koKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzthQVFzQztTQUNIO1dBRWtCO1NBQ3RCO3FCQUN5QjtVQUNYO29CQUM0QjtZQUNuQztpQkFFZTtlQUNYO3NCQUMrQjtvQkFDZDsrQkFDUTtDQVN0RCxXQUFiLE1BQXNCO0VBQ3BCLDZCQUFxQyxPQUF5QjtHQUM1RCxJQUFJLE9BQU8sVUFBVSxZQUFZLFVBQVUsTUFDekMsT0FBTztHQUdULE1BQU0scUJBQXFCO0dBQzNCLE9BQ0UsbUJBQW1CLFNBQVMsV0FDNUIsT0FBTyxtQkFBbUIsWUFBWSxZQUN0QyxtQkFBbUIsUUFBUSxTQUFTLGlCQUFpQjtFQUV6RDtFQUVBLHlCQUEyRDtHQUN6RCxNQUFNLFdBQVcsT0FBTyxLQUFLLE9BQU8sUUFBUSxDQUFDLENBQUMsUUFDM0MsUUFBUSxDQUFDLElBQUksU0FBUyxXQUFXLENBQ3BDO0dBRUEsSUFBSSxRQUFRLEdBQ1YsT0FBTztHQUdULE1BQU0sY0FBYyxxQkFBcUI7R0FDekMsT0FBTyxTQUFTLFFBQVEsUUFBUSxRQUFRLFdBQVc7RUFDckQ7RUFFQSxNQUFjLDBCQUNaLE9BQ0EsUUFDMEI7R0FDMUIsTUFBTSxVQUEyQixDQUFDO0dBRWxDLEtBQUssTUFBTSxFQUFFLFNBQVMsVUFBVSxPQUFPO0lBQ3JDLE1BQU0sQ0FBQyxTQUFTLFdBQ2QsV0FBVyxVQUFVLE1BQU0sS0FBSyxRQUFRLE9BQU8sSUFBSSxNQUFNLEtBQUssUUFBUSxTQUFTO0lBRWpGLFFBQVEsS0FBSztLQUNYO0tBQ0E7S0FDQTtJQUNGLENBQUM7R0FDSDtHQUVBLE9BQU87RUFDVDtFQUVBLE1BQWMsb0JBQThDO0dBQzFELE1BQU0sbUJBQW1CLEtBQUssS0FBSyxPQUFPLGFBQWEsT0FBTyxZQUFZO0dBRTFFLElBQUksQ0FBRSxNQUFNLE9BQU8sZ0JBQWdCLEdBQ2pDLE1BQU0sTUFBTSxrQkFBa0IsRUFDNUIsV0FBVyxLQUNiLENBQUM7R0FHSCxNQUFNLFNBQVMsTUFBTSxRQUFRLGdCQUFnQixFQUFBLENBQzFDLFFBQVEsTUFBTSxFQUFFLFNBQVMsS0FBSyxDQUFDLENBQUMsQ0FDaEMsS0FBSyxPQUFPO0lBQ1gsTUFBTSxFQUFFLFFBQVEsT0FBTyxFQUFFO0lBQ3pCLE1BQU0sS0FBSyxLQUFLLGtCQUFrQixDQUFDO0dBQ3JDLEVBQUUsQ0FBQyxDQUNGLFVBQVUsR0FBRyxNQUFPLEVBQUUsT0FBTyxFQUFFLE9BQU8sSUFBSSxFQUFHO0dBRWhELE1BQU0sRUFBRSxzQ0FBc0MsS0FBSztHQUNuRCxPQUFPO0VBQ1Q7Ozs7Ozs7Ozs7RUFXQSxNQUFNLFlBQXNDO0dBQzFDLE1BQU0sUUFBUSxNQUFNLEtBQUssa0JBQWtCO0dBQzNDLE1BQU0sRUFBRSw0QkFBNEIsS0FBSztHQUV6QyxNQUFNLFdBQVcsS0FBSyx1QkFBdUI7R0FFN0MsSUFBSTtHQUVKLE1BQU0sV0FBVyxNQUFNLFFBQVEsSUFDN0IsU0FBUyxJQUFJLE9BQU8sWUFBWTtJQUM5QixNQUFNLGNBQWMsT0FBTyxTQUFTO0lBQ3BDLE1BQU0sUUFBUSxtQkFBbUIsV0FBVztJQUU1QyxJQUFJO0tBQ0YsTUFBTSxTQUEyQixPQUFPLFlBQVk7TUFDbEQsSUFBSTtPQUNGLE9BQU8sTUFBTSxNQUFNLFFBQVEsT0FBTztNQUNwQyxTQUFTLEtBQUs7T0FDWixJQUFJLEtBQUssNkJBQTZCLEdBQUcsR0FDdkMsT0FBTyxNQUFNO09BR2YsUUFBUSxLQUNOLE1BQU0sT0FDSixHQUFHLFFBQVEsMkZBQTJGLEtBQUssVUFBVSxZQUFZLFlBQVksTUFBTSxDQUFDLEVBQUUsYUFBYSxJQUFJLEdBQ3pLLENBQ0Y7T0FDQSx1QkFBdUIsZUFBZSxRQUFRLElBQUksVUFBVSxPQUFPLEdBQUc7T0FDdEUsT0FBTztNQUNUO0tBQ0YsRUFBQSxDQUFHO0tBQ0gsTUFBTSxVQUFvQixPQUFPLFlBQVk7TUFDM0MsSUFBSTtPQUNGLE1BQU0sR0FBRyxVQUFVLE1BQU0sTUFBTSxRQUFRLEtBQUs7T0FDNUMsT0FBTyxPQUFPLEtBQUssT0FBeUIsR0FBRyxLQUFLLFFBQVEsT0FBTyxFQUFFLENBQUM7TUFDeEUsU0FBUyxLQUFLO09BQ1osSUFBSSxLQUFLLDZCQUE2QixHQUFHLEdBQ3ZDLE9BQU8sTUFBTSxLQUFLLFNBQVMsS0FBSyxJQUFJO09BR3RDLHVCQUF1QixlQUFlLFFBQVEsSUFBSSxVQUFVLE9BQU8sR0FBRztPQUN0RSxPQUFPLENBQUM7TUFDVjtLQUNGLEVBQUEsQ0FBRztLQUNILE1BQU0saUJBQW1DLE9BQU8sWUFBWTtNQUMxRCxJQUFJO09BQ0YsT0FBTyxNQUFNLE1BQU0sUUFBUSxlQUFlO01BQzVDLFNBQVMsTUFBTTtPQUNiLElBQUksS0FBSyw2QkFBNkIsSUFBSSxHQUN4QyxPQUFPO09BR1QsdUJBQXVCLGdCQUFnQixRQUFRLEtBQUssVUFBVSxPQUFPLElBQUk7T0FDekUsT0FBTztNQUNUO0tBQ0YsRUFBQSxDQUFHO0tBQ0gsTUFBTSxFQUFFLDZCQUE2QixNQUFNO0tBRTNDLE1BQU0sYUFBYSxZQUFZO0tBRS9CLE9BQU87TUFDTCxNQUFNO01BQ047TUFDQSxZQUFZLFFBQVEsV0FBVyxRQUFRLEdBQUcsR0FBRyxXQUFXLEtBQUssR0FDM0QsV0FBVyxLQUNaLEdBQUcsV0FBVztNQUNmO01BQ1E7TUFDUjtLQUNGO0lBQ0YsVUFBVTtLQUNSLE1BQU0sTUFBTSxRQUFRO0lBQ3RCO0dBQ0YsQ0FBQyxDQUNIO0dBRUEsTUFBTSxFQUFFLDRCQUE0QixRQUFRO0dBRTVDLE1BQU0sZ0JBQW9DLE9BQU8sWUFBWTtJQUMzRCxNQUFNLGNBQWMsU0FBUyxNQUFNLFdBQVcsT0FBTyxXQUFXLENBQUM7SUFDakUsSUFBSSxnQkFBZ0IsUUFBVztLQUM3QixRQUFRLEtBQ04sTUFBTSxPQUNKLDRQQUNGLENBQ0Y7S0FDQSxPQUFPLENBQUM7SUFDVjtJQUVBLE1BQU0sZ0JBQWdCLG1CQUFtQixPQUFPLFNBQVMsWUFBWSxRQUFRO0lBQzdFLElBQUk7S0FDRixPQUFPLE1BQU0sS0FBSyxrQkFBa0IsYUFBYTtJQUNuRCxVQUFVO0tBQ1IsTUFBTSxjQUFjLFFBQVE7SUFDOUI7R0FDRixFQUFBLENBQUc7R0FFSCxNQUFNLEVBQUUsb0NBQW9DLGFBQWE7R0FFekQsT0FBTztJQUNMLE9BQU87SUFDUDtJQUNBO0lBQ0EsT0FBTztHQUNUO0VBQ0Y7Ozs7Ozs7Ozs7O0VBWUEsTUFBTSxVQUNKLFFBQ0EsU0FDMEI7R0FDMUIsTUFBTSxFQUFFLDZCQUE2QixNQUFNO0dBQzNDLE1BQU0sRUFBRSw4QkFBOEIsT0FBTztHQUU3QyxNQUFNLGlCQUFpQixJQUFJLElBQUksS0FBSyx1QkFBdUIsQ0FBQztHQUM1RCxNQUFNLG9CQUFvQixRQUFRLFFBQVEsV0FBVyxDQUFDLGVBQWUsSUFBSSxNQUFNLENBQUM7R0FDaEYsSUFBSSxrQkFBa0IsU0FBUyxHQUM3QixNQUFNLElBQUksTUFDUixpREFBaUQscUJBQXFCLEVBQUUsSUFBSSxrQkFBa0IsS0FBSyxJQUFJLEdBQ3pHO0dBSUYsTUFBTSxVQUFVLE9BQ2QsUUFDRyxLQUFLLFlBQVk7SUFDaEIsU0FBUztJQUNULFNBQVMsT0FBTyxTQUFTO0dBQzNCLEVBQUUsQ0FBQyxDQUNGLFFBQVEsTUFBTSxFQUFFLFlBQVksTUFBUyxJQUN2QyxFQUFFLGNBQ0QsR0FBSSxRQUFRLFdBQXVDLEtBQUssR0FDckQsUUFBUSxXQUF1QyxRQUFRLEtBQ3pELEdBQUksUUFBUSxXQUF1QyxVQUN4RDtHQUdBLE1BQU0sUUFBUSxNQUFNLFFBQVEsSUFDMUIsUUFBUSxJQUFJLE9BQU8sWUFBWTtJQUM3QixTQUFTLE9BQU87SUFDaEIsTUFBTSxtQkFBbUIsT0FBTyxPQUFPO0dBQ3pDLEVBQUUsQ0FDSjtHQUVBLElBQUk7SUFFRixNQUFNLFNBQVMsT0FBTyxZQUFZO0tBQ2hDLFFBQVEsUUFBUjtNQUNFLEtBQUssU0FDSCxPQUFPLEtBQUssMEJBQTBCLE9BQU8sT0FBTztNQUN0RCxLQUFLLFlBQ0gsT0FBTyxLQUFLLDBCQUEwQixPQUFPLFVBQVU7S0FDM0Q7SUFDRixFQUFBLENBQUc7SUFFSCxNQUFNLEVBQUUsNkJBQTZCLE1BQU07SUFFM0MsT0FBTztHQUNULFVBQVU7SUFDUixNQUFNLFFBQVEsSUFDWixNQUFNLEtBQUssRUFBRSxXQUFXO0tBQ3RCLE9BQU8sS0FBSyxRQUFRO0lBQ3RCLENBQUMsQ0FDSDtHQUNGO0VBQ0Y7Ozs7Ozs7O0VBU0Esa0JBQWtCLE9BQWlDLFdBQXFCO0dBQ3RFLE1BQU0sZUFBZSxVQUFVLFFBQVEsYUFDckMsTUFBTSxNQUFNLFNBQVMsQ0FBQyxLQUFLLFFBQVEsU0FBUyxRQUFRLENBQUMsQ0FDdkQ7R0FFQSxPQUFPO0lBQ0wsV0FBVyxhQUFhLFdBQVc7SUFDbkM7R0FDRjtFQUNGOzs7Ozs7Ozs7RUFVQSxNQUFNLFNBQVMsV0FBc0M7R0FDbkQsTUFBTSxFQUFFLFVBQVUsTUFBTSxLQUFLLFVBQVU7R0FDdkMsTUFBTSxFQUFFLFdBQVcsaUJBQWlCLEtBQUssa0JBQWtCLE9BQU8sU0FBUztHQUMzRSxJQUFJLENBQUMsV0FDSCxNQUFNLElBQUksTUFDUixrRkFBa0YsYUFBYSxLQUFLLElBQUksR0FDMUc7R0FHRixPQUFPLElBQ0wsTUFBTSxRQUFRLElBQ1osVUFBVSxJQUFJLE9BQU8sYUFBYTtJQUNoQyxNQUFNLFdBQVcsR0FBRyxPQUFPLFlBQVksa0JBQWtCLFNBQVM7SUFDbEUsSUFBSSxNQUFNLE9BQU8sUUFBUSxHQUFHO0tBQzFCLE1BQU0sT0FBTyxRQUFRO0tBQ3JCLE9BQU87SUFDVDtJQUNBLE9BQU87R0FDVCxDQUFDLENBQ0gsQ0FDRjtFQUNGO0VBRUEsV0FBbUIsT0FBZSwyQkFBaUIsSUFBSSxLQUFLLEdBQVc7R0FDckUsTUFBTSxPQUFPLElBQUksS0FBSyxTQUFTLFFBQVEsSUFBSSxRQUFRLEdBQUk7R0FDdkQsTUFBTSxPQUFPLEtBQWEsT0FBZSxNQUFNLElBQUksU0FBUyxDQUFDLENBQUMsU0FBUyxNQUFNLEdBQUc7R0FDaEYsT0FDRSxLQUFLLFlBQVksQ0FBQyxDQUFDLFNBQVMsSUFDNUIsSUFBSSxLQUFLLFNBQVMsSUFBSSxDQUFDLElBQ3ZCLElBQUksS0FBSyxRQUFRLENBQUMsSUFDbEIsSUFBSSxLQUFLLFNBQVMsQ0FBQyxJQUNuQixJQUFJLEtBQUssV0FBVyxDQUFDLElBQ3JCLElBQUksS0FBSyxXQUFXLENBQUM7RUFFekI7Ozs7Ozs7O0VBU0EsTUFBTSx3QkFBeUM7R0FDN0MsTUFBTSxFQUFFLGtCQUFrQixNQUFNLEtBQUssVUFBVTtHQUMvQyxNQUFNLEVBQUUsZ0RBQWdELGFBQWE7R0FDckUsSUFBSSxjQUFjLFdBQVcsR0FBRztJQUM5QixRQUFRLElBQUksTUFBTSxNQUFNLG9CQUFvQixDQUFDO0lBQzdDLE9BQU87R0FDVDtHQUdBLE1BQU0sZ0JBQWdCLEdBQUcsT0FBTyxZQUFZO0dBRTVDLEtBQUssTUFBTSxDQUFDLE9BQU8sVUFBVSxjQUFjLFFBQVEsR0FDakQsSUFBSSxNQUFNLFdBQVc7SUFFbkIsTUFBTSxXQUFXLEdBQUcsY0FBYyxHQURsQixLQUFLLFdBQVcsS0FDSyxFQUFRLEdBQUcsTUFBTSxNQUFNO0lBQzVELE1BQU0sVUFBVSxVQUFVLE1BQU0sU0FBUztJQUN6QyxDQUFDLE9BQU8sS0FBSyxRQUFRLElBQUksTUFBTSxNQUFNLHFCQUFxQixVQUFVLENBQUM7R0FDdkU7R0FHRixPQUFPLGNBQWM7RUFDdkI7RUFFQSxNQUFNLGtCQUFrQixXQUE4QztHQUtwRSxNQUFNLDBCQUhZLGNBQWMsVUFHQSxDQUFBLENBQzdCLFFBQVEsYUFBYSxjQUFjLElBQUksUUFBUSxDQUFDLENBQUMsTUFBTSxTQUFTLENBQUMsQ0FBQyxDQUNsRSxLQUFLLGFBQWEsMEJBQTBCLGNBQWMsSUFBSSxRQUFRLENBQUMsQ0FBQztHQUczRSxNQUFNLG9CQUFvQix3QkFBd0IsU0FBUyxjQUFjLFVBQVUsVUFBVTtHQUU3RixNQUFNLGFBQWEsT0FBTyxPQUFPLE1BQU0sb0JBQW9CLE9BQU8sR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssV0FBVztJQUMzRixPQUFPLFdBQVcsUUFBVyxxQkFBcUI7SUFDbEQsSUFBSSxPQUFPLFdBQVcsR0FDcEIsT0FBTyxPQUFPO0lBRWhCLE9BQU87S0FDTCxHQUFHLE9BQU87S0FDVixTQUFTLE9BQ1AsT0FBTyxTQUFTLE1BQU0sRUFBRSxPQUFPLElBQzlCLFVBQVUsQ0FBQyxNQUFNLE1BQU0sR0FBRyxNQUFNLE9BQU8sQ0FBQyxDQUFDLEtBQUssR0FBRyxDQUNwRDtJQUNGO0dBQ0YsQ0FBQztHQUdELE1BQU0sYUFBNkIsQ0FBQyxHQUFHLHlCQUF5QixHQUFHLFVBQVU7R0FFN0UsTUFBTSxRQUE0QixDQUFDO0dBQ25DLE1BQU0sWUFBWTtHQUVsQixLQUFLLElBQUksSUFBSSxHQUFHLElBQUksV0FBVyxRQUFRLEtBQUssV0FBVztJQUNyRCxNQUFNLGFBQWEsTUFBTSxRQUFRLElBQy9CLFdBQVcsTUFBTSxHQUFHLElBQUksU0FBUyxDQUFDLENBQUMsSUFBSSxPQUFPLGNBQWM7S0FDMUQsTUFBTSxRQUFRLE1BQU0sdUJBQXVCLHNCQUN6QyxXQUNBLFVBQVUsS0FDWjtLQUNBLE1BQU0sRUFBRSx3Q0FBd0MsVUFBVSxTQUFTLFNBQVM7S0FDNUUsTUFBTSxFQUFFLG9DQUFvQyxVQUFVLFNBQVMsS0FBSztLQUVwRSxJQUFJLFVBQVUsTUFFWixPQUFPLE1BQU0sbUJBQW1CLFNBQVM7VUFHekMsT0FBTyxNQUFNLGtCQUFrQixXQUFXLE9BQU8sU0FBUztJQUU5RCxDQUFDLENBQ0g7SUFFQSxNQUFNLEtBQUssR0FBRyxXQUFXLEtBQUssQ0FBQztHQUNqQztHQUdBLE1BQU0sTUFBTSxPQUFPLFVBQVU7SUFDM0IsSUFBSSxNQUFNLFNBQVMsYUFBYSxNQUFNLFNBQVMsVUFDN0MsT0FBTztTQUNGLElBQUksTUFBTSxTQUFTLFlBQVksTUFBTSxTQUFTLFdBQ25ELE9BQU87U0FFUCxPQUFPO0dBRVgsQ0FBQztHQUVELE9BQU87RUFDVDs7Ozs7Ozs7RUFTQSxNQUFNLGdCQUEwQztHQUM5QyxNQUFNLGVBQWUsT0FBTyxTQUFTLEtBQUs7R0FDMUMsTUFBTSxXQUFXLFFBQVEsSUFBSSxxQkFBcUIsU0FBUyxRQUFRLElBQUksaUJBQWlCO0dBQ3hGLE1BQU0sbUJBQ0osYUFBYSxPQUFPLEdBQUcsYUFBYSxTQUFTLEdBQUcsWUFBWSxRQUFRLGFBQWE7R0FDbkYsTUFBTSxVQUFVO0lBQUUsR0FBRztJQUFjLFVBQVU7R0FBaUI7R0FDOUQsTUFBTSxpQkFBaUIsR0FBRyxpQkFBaUI7R0FHM0MsSUFBSSxPQUFPLEdBQUc7SUFDWixNQUFNLEdBQUcscUJBQXFCO0lBQzlCLE1BQU0sR0FBRyxRQUFRO0dBQ25CO0dBR0EsTUFBTSxNQUFNLG1CQUFtQjtJQUM3QixHQUFHLE9BQU8sU0FBUztJQUNuQixZQUFZO0tBQ1YsR0FBRztLQUNILFVBQVU7SUFDWjtHQUNGLENBQUM7R0FDRCxJQUFJO0lBQ0YsQ0FBQyxPQUFPLEtBQUssUUFBUSxJQUFJLE1BQU0sUUFBUSxHQUFHLGVBQWUsSUFBSSxDQUFDO0lBQzlELE1BQU0sSUFBSSxJQUFJLDJCQUEyQixnQkFBZ0I7SUFDekQsTUFBTSxJQUFJLElBQUk7OzsyQkFHTyxRQUFRLFNBQVM7O09BRXJDO0lBQ0QsTUFBTSxJQUFJLElBQUksbUJBQW1CLGVBQWUsWUFBWSxRQUFRLFVBQVU7SUFHOUUsTUFBTSxNQUFNLG1CQUFtQjtLQUM3QixHQUFHLE9BQU8sU0FBUztLQUNuQixZQUFZO01BQ1YsR0FBRztNQUNILFVBQVU7TUFDVixVQUFVLFFBQVE7S0FDcEI7SUFDRixDQUFDO0lBR0QsSUFBSTtLQUNGLE1BQU0sQ0FBQyxTQUFTLFdBQVcsTUFBTSxJQUFJLFFBQVEsT0FBTztLQUNwRCxDQUFDLE9BQU8sS0FDTixRQUFRLElBQUksTUFBTSxNQUFNLHdCQUF3QixHQUFHO01BQ2pEO01BQ0E7S0FDRixDQUFDO0tBRUgsT0FBTyxDQUNMO01BQ0UsU0FBUztNQUNUO01BQ0E7S0FDRixDQUNGO0lBQ0YsU0FBUyxHQUFHO0tBQ1YsUUFBUSxNQUFNLENBQUM7S0FDZixNQUFNLElBQUksNEJBQTRCLEdBQUcsaUNBQWlDLENBQUM7SUFDN0UsVUFBVTtLQUNSLE1BQU0sSUFBSSxRQUFRO0lBQ3BCO0dBQ0YsVUFBVTtJQUVSLENBQUMsT0FBTyxLQUFLLFFBQVEsSUFBSSxNQUFNLFFBQVEsR0FBRyxlQUFlLElBQUksQ0FBQztJQUM5RCxJQUFJO0tBQ0YsTUFBTSxJQUFJLElBQUksMkJBQTJCLGdCQUFnQjtJQUMzRCxTQUFTLEdBQUc7S0FDVixRQUFRLE1BQU0sb0JBQW9CLENBQUM7SUFDckMsVUFBVTtLQUNSLE1BQU0sSUFBSSxRQUFRO0lBQ3BCO0dBQ0Y7RUFDRjtDQUNGIn0=
|