@decohere/create 0.0.1-dev.23 → 0.0.1-dev.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/commonjs/src/models/compose.model.js +56 -4
  2. package/commonjs/src/models/dev-container.model.js +29 -2
  3. package/commonjs/src/models/package-json.model.js +11 -6
  4. package/commonjs/src/runner.js +26 -2
  5. package/commonjs/src/webapi/create-api.js +66 -5
  6. package/commonjs/src/webapi/features/auth.feature.js +288 -7
  7. package/commonjs/src/webapi/features/auth0-cli.js +256 -9
  8. package/commonjs/src/webapi/features/database.feature.js +56 -24
  9. package/commonjs/src/webapi/features/postman.feature.js +337 -48
  10. package/commonjs/src/webapi/models/api-package-json.model.js +4 -1
  11. package/commonjs/src/webapi/models/auth-config.model.js +4 -1
  12. package/commonjs/src/webapi/models/controller-source-file.model.js +16 -8
  13. package/commonjs/src/webapi/models/main-source-file.model.js +28 -4
  14. package/es6/src/models/compose.model.js +57 -6
  15. package/es6/src/models/dev-container.model.js +30 -8
  16. package/es6/src/models/package-json.model.js +11 -6
  17. package/es6/src/runner.js +27 -3
  18. package/es6/src/webapi/create-api.js +66 -5
  19. package/es6/src/webapi/features/auth.feature.js +288 -7
  20. package/es6/src/webapi/features/auth0-cli.js +230 -9
  21. package/es6/src/webapi/features/database.feature.js +56 -24
  22. package/es6/src/webapi/features/postman.feature.js +324 -45
  23. package/es6/src/webapi/models/api-package-json.model.js +4 -1
  24. package/es6/src/webapi/models/auth-config.model.js +4 -1
  25. package/es6/src/webapi/models/controller-source-file.model.js +16 -8
  26. package/es6/src/webapi/models/main-source-file.model.js +28 -4
  27. package/package.json +2 -2
  28. package/types/src/models/compose.model.d.ts +27 -2
  29. package/types/src/models/dev-container.model.d.ts +12 -0
  30. package/types/src/models/package-json.model.d.ts +2 -0
  31. package/types/src/webapi/features/auth.feature.d.ts +3 -0
  32. package/types/src/webapi/features/auth0-cli.d.ts +50 -3
  33. package/types/src/webapi/features/postman.feature.d.ts +5 -0
  34. package/types/src/webapi/models/auth-config.model.d.ts +8 -0
  35. package/types/src/webapi/models/controller-source-file.model.d.ts +6 -3
  36. package/types/src/webapi/models/main-source-file.model.d.ts +12 -0
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "AuthFeature", {
10
10
  });
11
11
  const _prompt = require("../../domain/prompt.js");
12
12
  const _const = require("../../models/const.js");
13
+ const _createapi = require("../create-api.js");
13
14
  const _authconfigmodel = require("../models/auth-config.model.js");
14
15
  const _controllersourcefilemodel = require("../models/controller-source-file.model.js");
15
16
  const _auth0cli = /*#__PURE__*/ _interop_require_wildcard(require("./auth0-cli.js"));
@@ -54,7 +55,151 @@ function _interop_require_wildcard(obj, nodeInterop) {
54
55
  }
55
56
  return newObj;
56
57
  }
58
+ const ADMIN_ROLE = "admin";
59
+ const USER_ENTITY_TS = `import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
60
+ import type { Entity as IEntity } from "@decohere/codex";
61
+
62
+ @Entity()
63
+ export class UserEntity implements IEntity {
64
+ \t@PrimaryGeneratedColumn()
65
+ \tpublic id!: number;
66
+
67
+ \t@Column({ unique: true })
68
+ \tpublic sub!: string;
69
+
70
+ \t@Column({ type: "varchar", nullable: true })
71
+ \tpublic email!: string | null;
72
+
73
+ \t@Column()
74
+ \tpublic displayName!: string;
75
+
76
+ \t/** App-owned roles. The \`admin\` role grants CASL \`manage\`/\`all\` (wildcard). */
77
+ \t@Column({ type: "simple-json", default: "[]" })
78
+ \tpublic roles!: string[];
79
+ }
80
+ `;
81
+ const USER_REPOSITORY_TS = `import { injectable } from "@decohere/crucible/decorators";
82
+ import { injectUnitOfWork } from "@decohere/codex";
83
+ import { TypeOrmRepository, TypeOrmUnitOfWork } from "@decohere/codex-typeorm";
84
+ import { UserEntity } from "../entities/user.entity.js";
85
+
86
+ @injectable()
87
+ export class UserEntityRepository extends TypeOrmRepository<UserEntity> {
88
+ \tpublic constructor(@injectUnitOfWork() unitOfWork: TypeOrmUnitOfWork) {
89
+ \t\tsuper(unitOfWork, UserEntity);
90
+ \t}
91
+
92
+ \tpublic findBySub(sub: string): Promise<UserEntity | null> {
93
+ \t\treturn this.firstOrDefault({ where: { sub } });
94
+ \t}
95
+ }
96
+ `;
97
+ const USER_SERVICE_TS = `import { injectable } from "@decohere/crucible/decorators";
98
+ import type { Principal } from "@decohere/cortex";
99
+ import { UserEntity } from "../entities/user.entity.js";
100
+ import { UserEntityRepository } from "../repositories/user.repository.js";
101
+
102
+ function claimString(principal: Principal | undefined, key: string): string | undefined {
103
+ \tconst value = principal?.[key];
104
+ \treturn typeof value === "string" && value.length > 0 ? value : undefined;
105
+ }
106
+
107
+ @injectable()
108
+ export class UserService {
109
+ \tpublic constructor(private readonly users: UserEntityRepository) {}
110
+
111
+ \t/**
112
+ \t * Upsert a local profile keyed by JWT \`sub\`.
113
+ \t * Profile fields from the token fill gaps; seeded rows keep displayName/email/roles.
114
+ \t */
115
+ \tpublic async ensureFromPrincipal(principal: Principal | undefined): Promise<UserEntity> {
116
+ \t\tconst sub = principal?.sub;
117
+ \t\tif (!sub) {
118
+ \t\t\tthrow new Error("Authenticated request is missing principal.sub");
119
+ \t\t}
120
+
121
+ \t\tconst email =
122
+ \t\t\tclaimString(principal, "email") ?? claimString(principal, "preferred_username");
123
+ \t\tconst displayFromToken =
124
+ \t\t\tclaimString(principal, "name") ??
125
+ \t\t\tclaimString(principal, "nickname") ??
126
+ \t\t\temail;
127
+
128
+ \t\tconst existing = await this.users.findBySub(sub);
129
+ \t\tif (existing) {
130
+ \t\t\tlet dirty = false;
131
+ \t\t\tif (!existing.email && email) {
132
+ \t\t\t\texisting.email = email;
133
+ \t\t\t\tdirty = true;
134
+ \t\t\t}
135
+ \t\t\tif (existing.displayName === existing.sub && displayFromToken) {
136
+ \t\t\t\texisting.displayName = displayFromToken;
137
+ \t\t\t\tdirty = true;
138
+ \t\t\t}
139
+ \t\t\treturn dirty ? this.users.save(existing) : existing;
140
+ \t\t}
141
+
142
+ \t\tconst created = new UserEntity();
143
+ \t\tcreated.sub = sub;
144
+ \t\tcreated.email = email ?? null;
145
+ \t\tcreated.displayName = displayFromToken ?? sub;
146
+ \t\tcreated.roles = Array.isArray(principal.roles)
147
+ \t\t\t? principal.roles.filter((r): r is string => typeof r === "string")
148
+ \t\t\t: [];
149
+ \t\treturn this.users.save(created);
150
+ \t}
151
+ }
152
+ `;
153
+ const ABILITY_FACTORY_TS = `import { AbilityBuilder, createMongoAbility } from "@casl/ability";
154
+ import type { Principal } from "@decohere/cortex";
155
+
156
+ /** Root role — expands to CASL \`manage\`/\`all\` (covers every future ability). */
157
+ export const ADMIN_ROLE = "admin";
158
+
159
+ /**
160
+ * Roles are collections of abilities. Admin is a wildcard, not an enumerated list.
161
+ * Non-admin principals keep the default Auth0 scope → ability mapping.
162
+ */
163
+ export function createAbilityFactory(principal: Principal) {
164
+ \tconst { can, build } = new AbilityBuilder(createMongoAbility);
165
+ \tif (principal.roles?.includes(ADMIN_ROLE)) {
166
+ \t\tcan("manage", "all");
167
+ \t\treturn build();
168
+ \t}
169
+ \tfor (const scope of principal.scopes ?? []) {
170
+ \t\tconst [action, subject] = scope.split(":");
171
+ \t\tif (action && subject) can(action, subject);
172
+ \t}
173
+ \treturn build();
174
+ }
175
+
176
+ /**
177
+ * Map JWT payload → Principal. Bootstraps the seeded Auth0 admin \`sub\` with
178
+ * the admin role so authorization works before/without roles in the access token.
179
+ */
180
+ export function mapPrincipal(payload: Record<string, unknown>): Principal {
181
+ \tconst sub = typeof payload.sub === "string" ? payload.sub : "";
182
+ \tconst scopes = Array.isArray(payload.scopes)
183
+ \t\t? (payload.scopes as string[])
184
+ \t\t: typeof payload.scope === "string"
185
+ \t\t\t? payload.scope.split(" ")
186
+ \t\t\t: undefined;
187
+ \tconst fromToken = Array.isArray(payload.roles)
188
+ \t\t? (payload.roles as unknown[]).filter((r): r is string => typeof r === "string")
189
+ \t\t: [];
190
+ \tconst roles =
191
+ \t\tsub && sub === process.env.AUTH0_ADMIN_USER_SUB
192
+ \t\t\t? [...new Set([ADMIN_ROLE, ...fromToken])]
193
+ \t\t\t: fromToken.length > 0
194
+ \t\t\t\t? fromToken
195
+ \t\t\t\t: undefined;
196
+ \treturn { ...payload, sub, roles, scopes };
197
+ }
198
+ `;
57
199
  async function getOptions(workspace, cliOptions) {
200
+ if (cliOptions.authProvider === "auth0" && !cliOptions.issuerBaseUrl) {
201
+ return getAuth0Options(workspace, cliOptions);
202
+ }
58
203
  if (cliOptions.authProvider != null) return {};
59
204
  const choices = [
60
205
  {
@@ -69,9 +214,9 @@ async function getOptions(workspace, cliOptions) {
69
214
  if (provider !== "auth0") return {
70
215
  authProvider: "none"
71
216
  };
72
- return getAuth0Options(workspace);
217
+ return getAuth0Options(workspace, cliOptions);
73
218
  }
74
- async function getAuth0Options(workspace) {
219
+ async function getAuth0Options(workspace, cliOptions) {
75
220
  if (!_auth0cli.isInstalled()) {
76
221
  console.error("\n The Auth0 CLI is required for automated setup.\n" + " Install: brew install auth0/auth0-cli/auth0\n" + " Or visit: https://github.com/auth0/auth0-cli\n");
77
222
  process.exit(1);
@@ -128,24 +273,156 @@ async function getAuth0Options(workspace) {
128
273
  } else {
129
274
  audience = apiSelected.existing;
130
275
  console.log(` \u2713 Selected: ${audience}`);
276
+ try {
277
+ _auth0cli.updateApiScopes(audience);
278
+ console.log(` \u2713 API scopes ensured (${_auth0cli.HELLO_API_SCOPES.join(", ")})`);
279
+ } catch {
280
+ console.error(" ✗ Failed to update API scopes — add Hello scopes in the Auth0 dashboard.");
281
+ }
282
+ }
283
+ const withLocalUsers = cliOptions.databaseProvider === "postgres/typeorm";
284
+ let adminUsername;
285
+ let adminPassword;
286
+ if (withLocalUsers) {
287
+ adminUsername = cliOptions.adminUsername ?? await (0, _prompt.ask)("\n Admin username [admin]: ", "admin");
288
+ adminPassword = cliOptions.adminPassword;
289
+ if (adminPassword == null) {
290
+ adminPassword = await (0, _prompt.ask)(" Admin password (leave blank to generate): ");
291
+ if (!adminPassword) {
292
+ adminPassword = _auth0cli.generateAdminPassword();
293
+ console.log(` ✓ Generated admin password (written to .env): ${adminPassword}`);
294
+ }
295
+ }
131
296
  }
132
297
  return {
133
298
  authProvider: "auth0",
134
299
  issuerBaseUrl,
135
- audience
300
+ audience,
301
+ ...withLocalUsers ? {
302
+ adminUsername,
303
+ adminPassword
304
+ } : {}
136
305
  };
137
306
  }
307
+ function adminEmail(workspaceName, username) {
308
+ if (username.includes("@")) return username;
309
+ const slug = workspaceName.toLowerCase().replace(/[^a-z0-9-]/g, "-");
310
+ return `${username}@${slug}.example.com`;
311
+ }
312
+ function createAuth0AdminUser(workspace, options, authConfig) {
313
+ const username = options.adminUsername ?? "admin";
314
+ const password = options.adminPassword;
315
+ if (!password) return;
316
+ const email = adminEmail(workspace.name, username);
317
+ try {
318
+ const admin = _auth0cli.createAdminDatabaseUser({
319
+ email,
320
+ password,
321
+ username
322
+ });
323
+ authConfig.setAdminUser({
324
+ sub: admin.user_id,
325
+ email: admin.email,
326
+ password: admin.password,
327
+ username: admin.username
328
+ });
329
+ workspace.getModel(_const.WELL_KNOWN_FILES.ENV_FILE)?.addEntry("AUTH0_ADMIN_USER_SUB", admin.user_id).addEntry("AUTH0_ADMIN_USER_EMAIL", admin.email).addEntry("AUTH0_ADMIN_USER_PASSWORD", admin.password).addEntry("AUTH0_ADMIN_USERNAME", admin.username);
330
+ console.log(` ✓ Auth0 admin user ready: ${admin.email} (role: ${ADMIN_ROLE})`);
331
+ console.log(` Login with EMAIL (not username): ${admin.email}`);
332
+ console.log(` Password: see AUTH0_ADMIN_USER_PASSWORD in .env`);
333
+ } catch (err) {
334
+ console.error(` ✗ Failed to ensure Auth0 admin user (${email}): ${err instanceof Error ? err.message : err}`);
335
+ }
336
+ }
337
+ function scaffoldLocalUserProfile(workspace) {
338
+ workspace.getModel(_const.WELL_KNOWN_FILES.PACKAGE_JSON)?.addDependency("@casl/ability", "^6.8.1");
339
+ workspace.getModel(_const.WELL_KNOWN_FILES.API_PACKAGE_JSON)?.addDependency("@casl/ability", "^6.8.1");
340
+ const main = workspace.getModel(_const.WELL_KNOWN_FILES.MAIN_TS);
341
+ main?.addEntity({
342
+ className: "UserEntity",
343
+ importPath: "./entities/user.entity.js"
344
+ }).addRepository({
345
+ className: "UserEntityRepository",
346
+ importPath: "./repositories/user.repository.js"
347
+ }).addService({
348
+ className: "UserService",
349
+ importPath: "./services/user.service.js",
350
+ scope: "request"
351
+ }).addImport("createAbilityFactory", "./auth/ability.factory.js").addImport("mapPrincipal", "./auth/ability.factory.js").setTypeOrmSeed([
352
+ "const sub = process.env.AUTH0_ADMIN_USER_SUB;",
353
+ "if (!sub) return;",
354
+ "const repo = dataSource.getRepository(UserEntity);",
355
+ "const existing = await repo.findOne({ where: { sub } });",
356
+ "if (existing) return;",
357
+ "await repo.save(repo.create({",
358
+ " sub,",
359
+ " email: process.env.AUTH0_ADMIN_USER_EMAIL ?? null,",
360
+ ' displayName: process.env.AUTH0_ADMIN_USERNAME ?? "admin",',
361
+ ' roles: ["admin"],',
362
+ "}));"
363
+ ].join(" "));
364
+ workspace.getProject(_createapi.WEBAPI_PROJECT_DIR)?.addFile({
365
+ files: ()=>[
366
+ {
367
+ filePath: "src/entities/user.entity.ts",
368
+ content: USER_ENTITY_TS
369
+ },
370
+ {
371
+ filePath: "src/repositories/user.repository.ts",
372
+ content: USER_REPOSITORY_TS
373
+ },
374
+ {
375
+ filePath: "src/services/user.service.ts",
376
+ content: USER_SERVICE_TS
377
+ },
378
+ {
379
+ filePath: "src/auth/ability.factory.ts",
380
+ content: ABILITY_FACTORY_TS
381
+ }
382
+ ]
383
+ });
384
+ for (const controller of workspace.getModels(_controllersourcefilemodel.ControllerSourceFile)){
385
+ controller.addImport("UserService", "../services/user.service.js").addConstructorParam("private readonly users: UserService");
386
+ controller.getMethod("getOne").setAsync(true).setBody([
387
+ "const user = await this.users.ensureFromPrincipal(this.principalProvider.currentPrincipal);",
388
+ // biome-ignore lint/suspicious/noTemplateCurlyInString: template literal in generated code
389
+ "return { id, message: `Hello ${user.displayName}!`, username: user.displayName };"
390
+ ]);
391
+ }
392
+ }
138
393
  function scaffold(workspace, options) {
139
394
  if (options.authProvider !== "auth0") return;
140
395
  const resource = "Hello";
396
+ const withLocalUsers = options.databaseProvider === "postgres/typeorm";
141
397
  for (const controller of workspace.getModels(_controllersourcefilemodel.ControllerSourceFile)){
142
398
  controller.addDecorator(`@Authorize("read", "${resource}")`).addCortexImport("AllowAnonymous").addCortexImport("Authorize").addCortexImport("IPrincipalProviderToken").addCortexImport("IPrincipalProvider", true).addImport("inject", "@decohere/crucible/decorators").addConstructorParam(`@inject(IPrincipalProviderToken) private readonly principalProvider: IPrincipalProvider`);
143
399
  controller.getMethod("getAll").addDecorator("@AllowAnonymous()");
400
+ if (!withLocalUsers) {
401
+ controller.getMethod("getOne").setBody([
402
+ "const principal = this.principalProvider.currentPrincipal;",
403
+ "const username =",
404
+ '\t(typeof principal?.name === "string" && principal.name) ||',
405
+ '\t(typeof principal?.nickname === "string" && principal.nickname) ||',
406
+ '\t(typeof principal?.email === "string" && principal.email) ||',
407
+ '\t(typeof principal?.preferred_username === "string" && principal.preferred_username) ||',
408
+ "\tprincipal?.sub ||",
409
+ '\t"unknown";',
410
+ // biome-ignore lint/suspicious/noTemplateCurlyInString: template literal in generated code
411
+ "return { id, message: `Hello ${username}!`, username };"
412
+ ]);
413
+ }
144
414
  controller.getMethod("create").addDecorator(`@Authorize("create", "${resource}")`);
145
415
  controller.getMethod("update").addDecorator(`@Authorize("update", "${resource}")`);
146
416
  controller.getMethod("remove").addDecorator(`@Authorize("delete", "${resource}")`);
147
417
  }
148
- workspace.getModel(_const.WELL_KNOWN_FILES.MAIN_TS)?.addSideEffectImport("@decohere/cortex/auth").addBuilderCall(".withAuth()");
418
+ const main = workspace.getModel(_const.WELL_KNOWN_FILES.MAIN_TS);
419
+ main?.addSideEffectImport("@decohere/cortex/auth");
420
+ if (withLocalUsers) {
421
+ scaffoldLocalUserProfile(workspace);
422
+ main?.addBuilderCall(".withAuth(createAbilityFactory, { principalMapper: mapPrincipal })");
423
+ } else {
424
+ main?.addBuilderCall(".withAuth()");
425
+ }
149
426
  // biome-ignore lint/suspicious/noTemplateCurlyInString: intentional YAML env-var placeholders
150
427
  const issuerPlaceholder = "${AUTH0_ISSUER_BASE_URL}";
151
428
  // biome-ignore lint/suspicious/noTemplateCurlyInString: intentional YAML env-var placeholders
@@ -153,14 +430,18 @@ function scaffold(workspace, options) {
153
430
  const configSection = `auth:\n discoveryUrl: ${issuerPlaceholder}\n audience: ${audPlaceholder}\n`;
154
431
  workspace.getModel(_const.WELL_KNOWN_FILES.CONFIG_YAML)?.addSection(configSection);
155
432
  workspace.getModel(_const.WELL_KNOWN_FILES.ENV_FILE)?.addEntry("AUTH0_ISSUER_BASE_URL", options.issuerBaseUrl ?? "").addEntry("AUTH0_AUDIENCE", options.audience ?? "");
156
- workspace.addModel(new _authconfigmodel.AuthConfigModel({
433
+ const authConfig = new _authconfigmodel.AuthConfigModel({
157
434
  issuerBaseUrl: options.issuerBaseUrl ?? "",
158
435
  audience: options.audience ?? ""
159
- }));
436
+ });
437
+ workspace.addModel(authConfig);
438
+ if (withLocalUsers && options.adminPassword) {
439
+ createAuth0AdminUser(workspace, options, authConfig);
440
+ }
160
441
  }
161
442
  const AuthFeature = {
162
443
  getOptions,
163
444
  scaffold
164
445
  };
165
446
 
166
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvd2ViYXBpL2ZlYXR1cmVzL2F1dGguZmVhdHVyZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBhc2ssIHBpY2sgfSBmcm9tIFwiLi4vLi4vZG9tYWluL3Byb21wdC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBDb25maWdZYW1sIH0gZnJvbSBcIi4uLy4uL21vZGVscy9jb25maWcteWFtbC5tb2RlbC5qc1wiO1xuaW1wb3J0IHsgV0VMTF9LTk9XTl9GSUxFUyB9IGZyb20gXCIuLi8uLi9tb2RlbHMvY29uc3QuanNcIjtcbmltcG9ydCB0eXBlIHsgRW52RmlsZSB9IGZyb20gXCIuLi8uLi9tb2RlbHMvZW52LWZpbGUubW9kZWwuanNcIjtcbmltcG9ydCB0eXBlIHsgV29ya3NwYWNlU2NhZmZvbGQgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL3Byb2plY3QubW9kZWwuanNcIjtcbmltcG9ydCB0eXBlIHsgRmVhdHVyZSB9IGZyb20gXCIuLi8uLi9zZXJ2aWNlcy9zY2FmZm9sZC5zZXJ2aWNlLmpzXCI7XG5pbXBvcnQgeyBBdXRoQ29uZmlnTW9kZWwgfSBmcm9tIFwiLi4vbW9kZWxzL2F1dGgtY29uZmlnLm1vZGVsLmpzXCI7XG5pbXBvcnQgeyBDb250cm9sbGVyU291cmNlRmlsZSB9IGZyb20gXCIuLi9tb2RlbHMvY29udHJvbGxlci1zb3VyY2UtZmlsZS5tb2RlbC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBNYWluU291cmNlRmlsZSB9IGZyb20gXCIuLi9tb2RlbHMvbWFpbi1zb3VyY2UtZmlsZS5tb2RlbC5qc1wiO1xuaW1wb3J0ICogYXMgYXV0aDBDbGkgZnJvbSBcIi4vYXV0aDAtY2xpLmpzXCI7XG5cbmV4cG9ydCB0eXBlIEF1dGhPcHRpb25zID0ge1xuXHRhdXRoUHJvdmlkZXI/OiBcImF1dGgwXCIgfCBcIm5vbmVcIjtcblx0aXNzdWVyQmFzZVVybD86IHN0cmluZztcblx0YXVkaWVuY2U/OiBzdHJpbmc7XG59O1xuXG5hc3luYyBmdW5jdGlvbiBnZXRPcHRpb25zKFxuXHR3b3Jrc3BhY2U6IFdvcmtzcGFjZVNjYWZmb2xkLFxuXHRjbGlPcHRpb25zOiBQYXJ0aWFsPEF1dGhPcHRpb25zPixcbik6IFByb21pc2U8UGFydGlhbDxBdXRoT3B0aW9ucz4+IHtcblx0aWYgKGNsaU9wdGlvbnMuYXV0aFByb3ZpZGVyICE9IG51bGwpIHJldHVybiB7fTtcblxuXHRjb25zdCBjaG9pY2VzID0gW3sgbGFiZWw6IFwibm9uZVwiIGFzIGNvbnN0IH0sIHsgbGFiZWw6IFwiYXV0aDBcIiBhcyBjb25zdCB9XTtcblx0Y29uc3Qgc2VsZWN0ZWQgPSBhd2FpdCBwaWNrKFwiXFxuICBBdXRoIHByb3ZpZGVyOiBcIiwgY2hvaWNlcywgKGMpID0+IGMubGFiZWwpO1xuXHRjb25zdCBwcm92aWRlciA9IHNlbGVjdGVkPy5sYWJlbCA/PyBcIm5vbmVcIjtcblxuXHRpZiAocHJvdmlkZXIgIT09IFwiYXV0aDBcIikgcmV0dXJuIHsgYXV0aFByb3ZpZGVyOiBcIm5vbmVcIiB9O1xuXG5cdHJldHVybiBnZXRBdXRoME9wdGlvbnMod29ya3NwYWNlKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0QXV0aDBPcHRpb25zKHdvcmtzcGFjZTogV29ya3NwYWNlU2NhZmZvbGQpOiBQcm9taXNlPFBhcnRpYWw8QXV0aE9wdGlvbnM+PiB7XG5cdGlmICghYXV0aDBDbGkuaXNJbnN0YWxsZWQoKSkge1xuXHRcdGNvbnNvbGUuZXJyb3IoXG5cdFx0XHRcIlxcbiAgVGhlIEF1dGgwIENMSSBpcyByZXF1aXJlZCBmb3IgYXV0b21hdGVkIHNldHVwLlxcblwiICtcblx0XHRcdFx0XCIgIEluc3RhbGw6IGJyZXcgaW5zdGFsbCBhdXRoMC9hdXRoMC1jbGkvYXV0aDBcXG5cIiArXG5cdFx0XHRcdFwiICBPciB2aXNpdDogaHR0cHM6Ly9naXRodWIuY29tL2F1dGgwL2F1dGgwLWNsaVxcblwiLFxuXHRcdCk7XG5cdFx0cHJvY2Vzcy5leGl0KDEpO1xuXHR9XG5cblx0cHJvY2Vzcy5zdGRvdXQud3JpdGUoXCJcXG4gIENoZWNraW5nIEF1dGgwIGNyZWRlbnRpYWxzLi4uXCIpO1xuXHRsZXQgdGVuYW50cyA9IGF1dGgwQ2xpLmxpc3RUZW5hbnRzKCk7XG5cdGlmICh0ZW5hbnRzLmxlbmd0aCA9PT0gMCkge1xuXHRcdHByb2Nlc3Muc3Rkb3V0LndyaXRlKFwiIG5vdCBsb2dnZWQgaW4uXFxuXCIpO1xuXHRcdGNvbnNvbGUubG9nKFwiICBMb2dnaW5nIGluIHRvIEF1dGgwICh5b3VyIGJyb3dzZXIgd2lsbCBvcGVuKS4uLlwiKTtcblx0XHRpZiAoIWF1dGgwQ2xpLmxvZ2luKCkpIHtcblx0XHRcdGNvbnNvbGUuZXJyb3IoXCJcXG4gIEF1dGgwIGxvZ2luIGZhaWxlZC5cIik7XG5cdFx0XHRwcm9jZXNzLmV4aXQoMSk7XG5cdFx0fVxuXHRcdHRlbmFudHMgPSBhdXRoMENsaS5saXN0VGVuYW50cygpO1xuXHR9XG5cblx0dHJ5IHtcblx0XHRhdXRoMENsaS5saXN0QXBpcygpO1xuXHRcdHByb2Nlc3Muc3Rkb3V0LndyaXRlKFwiIG9rLlxcblwiKTtcblx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0aWYgKGVyciBpbnN0YW5jZW9mIGF1dGgwQ2xpLkF1dGgwQXV0aEVycm9yKSB7XG5cdFx0XHRwcm9jZXNzLnN0ZG91dC53cml0ZShcIiB0b2tlbiBleHBpcmVkLlxcblwiKTtcblx0XHRcdGNvbnNvbGUubG9nKFwiICBSZS1hdXRoZW50aWNhdGluZyAoeW91ciBicm93c2VyIHdpbGwgb3BlbikuLi5cIik7XG5cdFx0XHRpZiAoIWF1dGgwQ2xpLmxvZ2luKCkpIHtcblx0XHRcdFx0Y29uc29sZS5lcnJvcihcIlxcbiAgQXV0aDAgbG9naW4gZmFpbGVkLlwiKTtcblx0XHRcdFx0cHJvY2Vzcy5leGl0KDEpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdGNvbnN0IGFjdGl2ZSA9IHRlbmFudHMuZmluZCgodCkgPT4gdC5hY3RpdmUpID8/IHRlbmFudHNbMF07XG5cdGNvbnN0IGlzc3VlckJhc2VVcmwgPSBgaHR0cHM6Ly8ke2FjdGl2ZS5uYW1lfWA7XG5cdGNvbnNvbGUubG9nKGBcXG4gIOKckyBBdXRoMCB0ZW5hbnQ6ICR7aXNzdWVyQmFzZVVybH1gKTtcblxuXHRwcm9jZXNzLnN0ZG91dC53cml0ZShcIlxcbiAgRmV0Y2hpbmcgQXV0aDAgQVBJcy4uLlwiKTtcblx0Y29uc3QgdXNlckFwaXMgPSBhdXRoMENsaS5saXN0QXBpcygpLmZpbHRlcigoYSkgPT4gIWEubmFtZS5pbmNsdWRlcyhcIk1hbmFnZW1lbnQgQVBJXCIpKTtcblx0cHJvY2Vzcy5zdGRvdXQud3JpdGUoYCBmb3VuZCAke3VzZXJBcGlzLmxlbmd0aH0uXFxuYCk7XG5cblx0dHlwZSBBcGlDaG9pY2UgPSB7IGxhYmVsOiBzdHJpbmc7IGV4aXN0aW5nOiBzdHJpbmcgfCBudWxsIH07XG5cdGNvbnN0IHByb2plY3ROYW1lID0gd29ya3NwYWNlLm5hbWU7XG5cdGNvbnN0IGFwaUNob2ljZXM6IEFwaUNob2ljZVtdID0gW1xuXHRcdHsgbGFiZWw6IGA8bmV3PiBodHRwczovL2FwaS4ke3Byb2plY3ROYW1lfWAsIGV4aXN0aW5nOiBudWxsIH0sXG5cdFx0Li4udXNlckFwaXMubWFwKChhKSA9PiAoeyBsYWJlbDogYCR7YS5uYW1lfSDigJQgJHthLmlkZW50aWZpZXJ9YCwgZXhpc3Rpbmc6IGEuaWRlbnRpZmllciB9KSksXG5cdF07XG5cblx0Y29uc3QgYXBpU2VsZWN0ZWQgPSBhd2FpdCBwaWNrKFwiXFxuICBTZWxlY3QgQXV0aDAgQVBJOiBcIiwgYXBpQ2hvaWNlcywgKGMpID0+IGMubGFiZWwpO1xuXG5cdGxldCBhdWRpZW5jZTogc3RyaW5nO1xuXHRpZiAoIWFwaVNlbGVjdGVkIHx8IGFwaVNlbGVjdGVkLmV4aXN0aW5nID09PSBudWxsKSB7XG5cdFx0Y29uc3QgZGVmYXVsdElkID0gYGh0dHBzOi8vYXBpLiR7cHJvamVjdE5hbWV9YDtcblx0XHRhdWRpZW5jZSA9IGF3YWl0IGFzayhgICBBUEkgSWRlbnRpZmllciBbJHtkZWZhdWx0SWR9XTogYCwgZGVmYXVsdElkKTtcblx0XHRjb25zb2xlLmxvZyhcIlxcbiAgQ3JlYXRpbmcgQXV0aDAgQVBJLi4uXCIpO1xuXHRcdGF1ZGllbmNlID0gYXV0aDBDbGkuY3JlYXRlQXBpKGAke3Byb2plY3ROYW1lfSBBUElgLCBhdWRpZW5jZSkuaWRlbnRpZmllcjtcblx0XHRjb25zb2xlLmxvZyhgICBcXHUyNzEzIEFQSSBjcmVhdGVkOiAke2F1ZGllbmNlfWApO1xuXHR9IGVsc2Uge1xuXHRcdGF1ZGllbmNlID0gYXBpU2VsZWN0ZWQuZXhpc3Rpbmc7XG5cdFx0Y29uc29sZS5sb2coYCAgXFx1MjcxMyBTZWxlY3RlZDogJHthdWRpZW5jZX1gKTtcblx0fVxuXG5cdHJldHVybiB7IGF1dGhQcm92aWRlcjogXCJhdXRoMFwiLCBpc3N1ZXJCYXNlVXJsLCBhdWRpZW5jZSB9O1xufVxuXG5mdW5jdGlvbiBzY2FmZm9sZCh3b3Jrc3BhY2U6IFdvcmtzcGFjZVNjYWZmb2xkLCBvcHRpb25zOiBBdXRoT3B0aW9ucyk6IHZvaWQge1xuXHRpZiAob3B0aW9ucy5hdXRoUHJvdmlkZXIgIT09IFwiYXV0aDBcIikgcmV0dXJuO1xuXG5cdGNvbnN0IHJlc291cmNlID0gXCJIZWxsb1wiO1xuXG5cdGZvciAoY29uc3QgY29udHJvbGxlciBvZiB3b3Jrc3BhY2UuZ2V0TW9kZWxzKENvbnRyb2xsZXJTb3VyY2VGaWxlKSkge1xuXHRcdGNvbnRyb2xsZXJcblx0XHRcdC5hZGREZWNvcmF0b3IoYEBBdXRob3JpemUoXCJyZWFkXCIsIFwiJHtyZXNvdXJjZX1cIilgKVxuXHRcdFx0LmFkZENvcnRleEltcG9ydChcIkFsbG93QW5vbnltb3VzXCIpXG5cdFx0XHQuYWRkQ29ydGV4SW1wb3J0KFwiQXV0aG9yaXplXCIpXG5cdFx0XHQuYWRkQ29ydGV4SW1wb3J0KFwiSVByaW5jaXBhbFByb3ZpZGVyVG9rZW5cIilcblx0XHRcdC5hZGRDb3J0ZXhJbXBvcnQoXCJJUHJpbmNpcGFsUHJvdmlkZXJcIiwgdHJ1ZSlcblx0XHRcdC5hZGRJbXBvcnQoXCJpbmplY3RcIiwgXCJAZGVjb2hlcmUvY3J1Y2libGUvZGVjb3JhdG9yc1wiKVxuXHRcdFx0LmFkZENvbnN0cnVjdG9yUGFyYW0oXG5cdFx0XHRcdGBAaW5qZWN0KElQcmluY2lwYWxQcm92aWRlclRva2VuKSBwcml2YXRlIHJlYWRvbmx5IHByaW5jaXBhbFByb3ZpZGVyOiBJUHJpbmNpcGFsUHJvdmlkZXJgLFxuXHRcdFx0KTtcblx0XHRjb250cm9sbGVyLmdldE1ldGhvZChcImdldEFsbFwiKS5hZGREZWNvcmF0b3IoXCJAQWxsb3dBbm9ueW1vdXMoKVwiKTtcblx0XHRjb250cm9sbGVyLmdldE1ldGhvZChcImNyZWF0ZVwiKS5hZGREZWNvcmF0b3IoYEBBdXRob3JpemUoXCJjcmVhdGVcIiwgXCIke3Jlc291cmNlfVwiKWApO1xuXHRcdGNvbnRyb2xsZXIuZ2V0TWV0aG9kKFwidXBkYXRlXCIpLmFkZERlY29yYXRvcihgQEF1dGhvcml6ZShcInVwZGF0ZVwiLCBcIiR7cmVzb3VyY2V9XCIpYCk7XG5cdFx0Y29udHJvbGxlci5nZXRNZXRob2QoXCJyZW1vdmVcIikuYWRkRGVjb3JhdG9yKGBAQXV0aG9yaXplKFwiZGVsZXRlXCIsIFwiJHtyZXNvdXJjZX1cIilgKTtcblx0fVxuXG5cdHdvcmtzcGFjZVxuXHRcdC5nZXRNb2RlbDxNYWluU291cmNlRmlsZT4oV0VMTF9LTk9XTl9GSUxFUy5NQUlOX1RTKVxuXHRcdD8uYWRkU2lkZUVmZmVjdEltcG9ydChcIkBkZWNvaGVyZS9jb3J0ZXgvYXV0aFwiKVxuXHRcdC5hZGRCdWlsZGVyQ2FsbChcIi53aXRoQXV0aCgpXCIpO1xuXG5cdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9UZW1wbGF0ZUN1cmx5SW5TdHJpbmc6IGludGVudGlvbmFsIFlBTUwgZW52LXZhciBwbGFjZWhvbGRlcnNcblx0Y29uc3QgaXNzdWVyUGxhY2Vob2xkZXIgPSBcIiR7QVVUSDBfSVNTVUVSX0JBU0VfVVJMfVwiO1xuXHQvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vVGVtcGxhdGVDdXJseUluU3RyaW5nOiBpbnRlbnRpb25hbCBZQU1MIGVudi12YXIgcGxhY2Vob2xkZXJzXG5cdGNvbnN0IGF1ZFBsYWNlaG9sZGVyID0gXCIke0FVVEgwX0FVRElFTkNFfVwiO1xuXG5cdGNvbnN0IGNvbmZpZ1NlY3Rpb24gPSBgYXV0aDpcXG4gIGRpc2NvdmVyeVVybDogJHtpc3N1ZXJQbGFjZWhvbGRlcn1cXG4gIGF1ZGllbmNlOiAke2F1ZFBsYWNlaG9sZGVyfVxcbmA7XG5cblx0d29ya3NwYWNlLmdldE1vZGVsPENvbmZpZ1lhbWw+KFdFTExfS05PV05fRklMRVMuQ09ORklHX1lBTUwpPy5hZGRTZWN0aW9uKGNvbmZpZ1NlY3Rpb24pO1xuXG5cdHdvcmtzcGFjZVxuXHRcdC5nZXRNb2RlbDxFbnZGaWxlPihXRUxMX0tOT1dOX0ZJTEVTLkVOVl9GSUxFKVxuXHRcdD8uYWRkRW50cnkoXCJBVVRIMF9JU1NVRVJfQkFTRV9VUkxcIiwgb3B0aW9ucy5pc3N1ZXJCYXNlVXJsID8/IFwiXCIpXG5cdFx0LmFkZEVudHJ5KFwiQVVUSDBfQVVESUVOQ0VcIiwgb3B0aW9ucy5hdWRpZW5jZSA/PyBcIlwiKTtcblxuXHR3b3Jrc3BhY2UuYWRkTW9kZWwoXG5cdFx0bmV3IEF1dGhDb25maWdNb2RlbCh7XG5cdFx0XHRpc3N1ZXJCYXNlVXJsOiBvcHRpb25zLmlzc3VlckJhc2VVcmwgPz8gXCJcIixcblx0XHRcdGF1ZGllbmNlOiBvcHRpb25zLmF1ZGllbmNlID8/IFwiXCIsXG5cdFx0fSksXG5cdCk7XG59XG5cbmV4cG9ydCBjb25zdCBBdXRoRmVhdHVyZTogRmVhdHVyZTxBdXRoT3B0aW9ucz4gPSB7IGdldE9wdGlvbnMsIHNjYWZmb2xkIH07XG4iXSwibmFtZXMiOlsiQXV0aEZlYXR1cmUiLCJnZXRPcHRpb25zIiwid29ya3NwYWNlIiwiY2xpT3B0aW9ucyIsImF1dGhQcm92aWRlciIsImNob2ljZXMiLCJsYWJlbCIsInNlbGVjdGVkIiwicGljayIsImMiLCJwcm92aWRlciIsImdldEF1dGgwT3B0aW9ucyIsImF1dGgwQ2xpIiwiaXNJbnN0YWxsZWQiLCJjb25zb2xlIiwiZXJyb3IiLCJwcm9jZXNzIiwiZXhpdCIsInN0ZG91dCIsIndyaXRlIiwidGVuYW50cyIsImxpc3RUZW5hbnRzIiwibGVuZ3RoIiwibG9nIiwibG9naW4iLCJsaXN0QXBpcyIsImVyciIsIkF1dGgwQXV0aEVycm9yIiwiYWN0aXZlIiwiZmluZCIsInQiLCJpc3N1ZXJCYXNlVXJsIiwibmFtZSIsInVzZXJBcGlzIiwiZmlsdGVyIiwiYSIsImluY2x1ZGVzIiwicHJvamVjdE5hbWUiLCJhcGlDaG9pY2VzIiwiZXhpc3RpbmciLCJtYXAiLCJpZGVudGlmaWVyIiwiYXBpU2VsZWN0ZWQiLCJhdWRpZW5jZSIsImRlZmF1bHRJZCIsImFzayIsImNyZWF0ZUFwaSIsInNjYWZmb2xkIiwib3B0aW9ucyIsInJlc291cmNlIiwiY29udHJvbGxlciIsImdldE1vZGVscyIsIkNvbnRyb2xsZXJTb3VyY2VGaWxlIiwiYWRkRGVjb3JhdG9yIiwiYWRkQ29ydGV4SW1wb3J0IiwiYWRkSW1wb3J0IiwiYWRkQ29uc3RydWN0b3JQYXJhbSIsImdldE1ldGhvZCIsImdldE1vZGVsIiwiV0VMTF9LTk9XTl9GSUxFUyIsIk1BSU5fVFMiLCJhZGRTaWRlRWZmZWN0SW1wb3J0IiwiYWRkQnVpbGRlckNhbGwiLCJpc3N1ZXJQbGFjZWhvbGRlciIsImF1ZFBsYWNlaG9sZGVyIiwiY29uZmlnU2VjdGlvbiIsIkNPTkZJR19ZQU1MIiwiYWRkU2VjdGlvbiIsIkVOVl9GSUxFIiwiYWRkRW50cnkiLCJhZGRNb2RlbCIsIkF1dGhDb25maWdNb2RlbCJdLCJtYXBwaW5ncyI6Ijs7OzsrQkFxSmFBOzs7ZUFBQUE7Ozt3QkFySmE7dUJBRU87aUNBSUQ7MkNBQ0s7a0VBRVg7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQVExQixlQUFlQyxXQUNkQyxTQUE0QixFQUM1QkMsVUFBZ0M7SUFFaEMsSUFBSUEsV0FBV0MsWUFBWSxJQUFJLE1BQU0sT0FBTyxDQUFDO0lBRTdDLE1BQU1DLFVBQVU7UUFBQztZQUFFQyxPQUFPO1FBQWdCO1FBQUc7WUFBRUEsT0FBTztRQUFpQjtLQUFFO0lBQ3pFLE1BQU1DLFdBQVcsTUFBTUMsSUFBQUEsWUFBSSxFQUFDLHVCQUF1QkgsU0FBUyxDQUFDSSxJQUFNQSxFQUFFSCxLQUFLO0lBQzFFLE1BQU1JLFdBQVdILFVBQVVELFNBQVM7SUFFcEMsSUFBSUksYUFBYSxTQUFTLE9BQU87UUFBRU4sY0FBYztJQUFPO0lBRXhELE9BQU9PLGdCQUFnQlQ7QUFDeEI7QUFFQSxlQUFlUyxnQkFBZ0JULFNBQTRCO0lBQzFELElBQUksQ0FBQ1UsVUFBU0MsV0FBVyxJQUFJO1FBQzVCQyxRQUFRQyxLQUFLLENBQ1oseURBQ0Msb0RBQ0E7UUFFRkMsUUFBUUMsSUFBSSxDQUFDO0lBQ2Q7SUFFQUQsUUFBUUUsTUFBTSxDQUFDQyxLQUFLLENBQUM7SUFDckIsSUFBSUMsVUFBVVIsVUFBU1MsV0FBVztJQUNsQyxJQUFJRCxRQUFRRSxNQUFNLEtBQUssR0FBRztRQUN6Qk4sUUFBUUUsTUFBTSxDQUFDQyxLQUFLLENBQUM7UUFDckJMLFFBQVFTLEdBQUcsQ0FBQztRQUNaLElBQUksQ0FBQ1gsVUFBU1ksS0FBSyxJQUFJO1lBQ3RCVixRQUFRQyxLQUFLLENBQUM7WUFDZEMsUUFBUUMsSUFBSSxDQUFDO1FBQ2Q7UUFDQUcsVUFBVVIsVUFBU1MsV0FBVztJQUMvQjtJQUVBLElBQUk7UUFDSFQsVUFBU2EsUUFBUTtRQUNqQlQsUUFBUUUsTUFBTSxDQUFDQyxLQUFLLENBQUM7SUFDdEIsRUFBRSxPQUFPTyxLQUFLO1FBQ2IsSUFBSUEsZUFBZWQsVUFBU2UsY0FBYyxFQUFFO1lBQzNDWCxRQUFRRSxNQUFNLENBQUNDLEtBQUssQ0FBQztZQUNyQkwsUUFBUVMsR0FBRyxDQUFDO1lBQ1osSUFBSSxDQUFDWCxVQUFTWSxLQUFLLElBQUk7Z0JBQ3RCVixRQUFRQyxLQUFLLENBQUM7Z0JBQ2RDLFFBQVFDLElBQUksQ0FBQztZQUNkO1FBQ0Q7SUFDRDtJQUVBLE1BQU1XLFNBQVNSLFFBQVFTLElBQUksQ0FBQyxDQUFDQyxJQUFNQSxFQUFFRixNQUFNLEtBQUtSLE9BQU8sQ0FBQyxFQUFFO0lBQzFELE1BQU1XLGdCQUFnQixDQUFDLFFBQVEsRUFBRUgsT0FBT0ksSUFBSSxFQUFFO0lBQzlDbEIsUUFBUVMsR0FBRyxDQUFDLENBQUMsb0JBQW9CLEVBQUVRLGVBQWU7SUFFbERmLFFBQVFFLE1BQU0sQ0FBQ0MsS0FBSyxDQUFDO0lBQ3JCLE1BQU1jLFdBQVdyQixVQUFTYSxRQUFRLEdBQUdTLE1BQU0sQ0FBQyxDQUFDQyxJQUFNLENBQUNBLEVBQUVILElBQUksQ0FBQ0ksUUFBUSxDQUFDO0lBQ3BFcEIsUUFBUUUsTUFBTSxDQUFDQyxLQUFLLENBQUMsQ0FBQyxPQUFPLEVBQUVjLFNBQVNYLE1BQU0sQ0FBQyxHQUFHLENBQUM7SUFHbkQsTUFBTWUsY0FBY25DLFVBQVU4QixJQUFJO0lBQ2xDLE1BQU1NLGFBQTBCO1FBQy9CO1lBQUVoQyxPQUFPLENBQUMsa0JBQWtCLEVBQUUrQixhQUFhO1lBQUVFLFVBQVU7UUFBSztXQUN6RE4sU0FBU08sR0FBRyxDQUFDLENBQUNMLElBQU8sQ0FBQTtnQkFBRTdCLE9BQU8sR0FBRzZCLEVBQUVILElBQUksQ0FBQyxHQUFHLEVBQUVHLEVBQUVNLFVBQVUsRUFBRTtnQkFBRUYsVUFBVUosRUFBRU0sVUFBVTtZQUFDLENBQUE7S0FDdkY7SUFFRCxNQUFNQyxjQUFjLE1BQU1sQyxJQUFBQSxZQUFJLEVBQUMsMEJBQTBCOEIsWUFBWSxDQUFDN0IsSUFBTUEsRUFBRUgsS0FBSztJQUVuRixJQUFJcUM7SUFDSixJQUFJLENBQUNELGVBQWVBLFlBQVlILFFBQVEsS0FBSyxNQUFNO1FBQ2xELE1BQU1LLFlBQVksQ0FBQyxZQUFZLEVBQUVQLGFBQWE7UUFDOUNNLFdBQVcsTUFBTUUsSUFBQUEsV0FBRyxFQUFDLENBQUMsa0JBQWtCLEVBQUVELFVBQVUsR0FBRyxDQUFDLEVBQUVBO1FBQzFEOUIsUUFBUVMsR0FBRyxDQUFDO1FBQ1pvQixXQUFXL0IsVUFBU2tDLFNBQVMsQ0FBQyxHQUFHVCxZQUFZLElBQUksQ0FBQyxFQUFFTSxVQUFVRixVQUFVO1FBQ3hFM0IsUUFBUVMsR0FBRyxDQUFDLENBQUMsc0JBQXNCLEVBQUVvQixVQUFVO0lBQ2hELE9BQU87UUFDTkEsV0FBV0QsWUFBWUgsUUFBUTtRQUMvQnpCLFFBQVFTLEdBQUcsQ0FBQyxDQUFDLG1CQUFtQixFQUFFb0IsVUFBVTtJQUM3QztJQUVBLE9BQU87UUFBRXZDLGNBQWM7UUFBUzJCO1FBQWVZO0lBQVM7QUFDekQ7QUFFQSxTQUFTSSxTQUFTN0MsU0FBNEIsRUFBRThDLE9BQW9CO0lBQ25FLElBQUlBLFFBQVE1QyxZQUFZLEtBQUssU0FBUztJQUV0QyxNQUFNNkMsV0FBVztJQUVqQixLQUFLLE1BQU1DLGNBQWNoRCxVQUFVaUQsU0FBUyxDQUFDQywrQ0FBb0IsRUFBRztRQUNuRUYsV0FDRUcsWUFBWSxDQUFDLENBQUMsb0JBQW9CLEVBQUVKLFNBQVMsRUFBRSxDQUFDLEVBQ2hESyxlQUFlLENBQUMsa0JBQ2hCQSxlQUFlLENBQUMsYUFDaEJBLGVBQWUsQ0FBQywyQkFDaEJBLGVBQWUsQ0FBQyxzQkFBc0IsTUFDdENDLFNBQVMsQ0FBQyxVQUFVLGlDQUNwQkMsbUJBQW1CLENBQ25CLENBQUMsdUZBQXVGLENBQUM7UUFFM0ZOLFdBQVdPLFNBQVMsQ0FBQyxVQUFVSixZQUFZLENBQUM7UUFDNUNILFdBQVdPLFNBQVMsQ0FBQyxVQUFVSixZQUFZLENBQUMsQ0FBQyxzQkFBc0IsRUFBRUosU0FBUyxFQUFFLENBQUM7UUFDakZDLFdBQVdPLFNBQVMsQ0FBQyxVQUFVSixZQUFZLENBQUMsQ0FBQyxzQkFBc0IsRUFBRUosU0FBUyxFQUFFLENBQUM7UUFDakZDLFdBQVdPLFNBQVMsQ0FBQyxVQUFVSixZQUFZLENBQUMsQ0FBQyxzQkFBc0IsRUFBRUosU0FBUyxFQUFFLENBQUM7SUFDbEY7SUFFQS9DLFVBQ0V3RCxRQUFRLENBQWlCQyx1QkFBZ0IsQ0FBQ0MsT0FBTyxHQUNoREMsb0JBQW9CLHlCQUNyQkMsZUFBZTtJQUVqQiw4RkFBOEY7SUFDOUYsTUFBTUMsb0JBQW9CO0lBQzFCLDhGQUE4RjtJQUM5RixNQUFNQyxpQkFBaUI7SUFFdkIsTUFBTUMsZ0JBQWdCLENBQUMsdUJBQXVCLEVBQUVGLGtCQUFrQixjQUFjLEVBQUVDLGVBQWUsRUFBRSxDQUFDO0lBRXBHOUQsVUFBVXdELFFBQVEsQ0FBYUMsdUJBQWdCLENBQUNPLFdBQVcsR0FBR0MsV0FBV0Y7SUFFekUvRCxVQUNFd0QsUUFBUSxDQUFVQyx1QkFBZ0IsQ0FBQ1MsUUFBUSxHQUMxQ0MsU0FBUyx5QkFBeUJyQixRQUFRakIsYUFBYSxJQUFJLElBQzVEc0MsU0FBUyxrQkFBa0JyQixRQUFRTCxRQUFRLElBQUk7SUFFakR6QyxVQUFVb0UsUUFBUSxDQUNqQixJQUFJQyxnQ0FBZSxDQUFDO1FBQ25CeEMsZUFBZWlCLFFBQVFqQixhQUFhLElBQUk7UUFDeENZLFVBQVVLLFFBQVFMLFFBQVEsSUFBSTtJQUMvQjtBQUVGO0FBRU8sTUFBTTNDLGNBQW9DO0lBQUVDO0lBQVk4QztBQUFTIn0=
447
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvd2ViYXBpL2ZlYXR1cmVzL2F1dGguZmVhdHVyZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBhc2ssIHBpY2sgfSBmcm9tIFwiLi4vLi4vZG9tYWluL3Byb21wdC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBDb25maWdZYW1sIH0gZnJvbSBcIi4uLy4uL21vZGVscy9jb25maWcteWFtbC5tb2RlbC5qc1wiO1xuaW1wb3J0IHsgV0VMTF9LTk9XTl9GSUxFUyB9IGZyb20gXCIuLi8uLi9tb2RlbHMvY29uc3QuanNcIjtcbmltcG9ydCB0eXBlIHsgRW52RmlsZSB9IGZyb20gXCIuLi8uLi9tb2RlbHMvZW52LWZpbGUubW9kZWwuanNcIjtcbmltcG9ydCB0eXBlIHsgUGFja2FnZUpzb24gfSBmcm9tIFwiLi4vLi4vbW9kZWxzL3BhY2thZ2UtanNvbi5tb2RlbC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBXb3Jrc3BhY2VTY2FmZm9sZCB9IGZyb20gXCIuLi8uLi9tb2RlbHMvcHJvamVjdC5tb2RlbC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBGZWF0dXJlIH0gZnJvbSBcIi4uLy4uL3NlcnZpY2VzL3NjYWZmb2xkLnNlcnZpY2UuanNcIjtcbmltcG9ydCB7IFdFQkFQSV9QUk9KRUNUX0RJUiB9IGZyb20gXCIuLi9jcmVhdGUtYXBpLmpzXCI7XG5pbXBvcnQgdHlwZSB7IEFwaVBhY2thZ2VKc29uIH0gZnJvbSBcIi4uL21vZGVscy9hcGktcGFja2FnZS1qc29uLm1vZGVsLmpzXCI7XG5pbXBvcnQgeyBBdXRoQ29uZmlnTW9kZWwgfSBmcm9tIFwiLi4vbW9kZWxzL2F1dGgtY29uZmlnLm1vZGVsLmpzXCI7XG5pbXBvcnQgeyBDb250cm9sbGVyU291cmNlRmlsZSB9IGZyb20gXCIuLi9tb2RlbHMvY29udHJvbGxlci1zb3VyY2UtZmlsZS5tb2RlbC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBNYWluU291cmNlRmlsZSB9IGZyb20gXCIuLi9tb2RlbHMvbWFpbi1zb3VyY2UtZmlsZS5tb2RlbC5qc1wiO1xuaW1wb3J0ICogYXMgYXV0aDBDbGkgZnJvbSBcIi4vYXV0aDAtY2xpLmpzXCI7XG5cbmV4cG9ydCB0eXBlIEF1dGhPcHRpb25zID0ge1xuXHRhdXRoUHJvdmlkZXI/OiBcImF1dGgwXCIgfCBcIm5vbmVcIjtcblx0aXNzdWVyQmFzZVVybD86IHN0cmluZztcblx0YXVkaWVuY2U/OiBzdHJpbmc7XG5cdGRhdGFiYXNlUHJvdmlkZXI/OiBcIm5vbmVcIiB8IFwicG9zdGdyZXMvdHlwZW9ybVwiO1xuXHRhZG1pblVzZXJuYW1lPzogc3RyaW5nO1xuXHRhZG1pblBhc3N3b3JkPzogc3RyaW5nO1xufTtcblxuY29uc3QgQURNSU5fUk9MRSA9IFwiYWRtaW5cIjtcblxuY29uc3QgVVNFUl9FTlRJVFlfVFMgPSBgaW1wb3J0IHsgQ29sdW1uLCBFbnRpdHksIFByaW1hcnlHZW5lcmF0ZWRDb2x1bW4gfSBmcm9tIFwidHlwZW9ybVwiO1xuaW1wb3J0IHR5cGUgeyBFbnRpdHkgYXMgSUVudGl0eSB9IGZyb20gXCJAZGVjb2hlcmUvY29kZXhcIjtcblxuQEVudGl0eSgpXG5leHBvcnQgY2xhc3MgVXNlckVudGl0eSBpbXBsZW1lbnRzIElFbnRpdHkge1xuXFx0QFByaW1hcnlHZW5lcmF0ZWRDb2x1bW4oKVxuXFx0cHVibGljIGlkITogbnVtYmVyO1xuXG5cXHRAQ29sdW1uKHsgdW5pcXVlOiB0cnVlIH0pXG5cXHRwdWJsaWMgc3ViITogc3RyaW5nO1xuXG5cXHRAQ29sdW1uKHsgdHlwZTogXCJ2YXJjaGFyXCIsIG51bGxhYmxlOiB0cnVlIH0pXG5cXHRwdWJsaWMgZW1haWwhOiBzdHJpbmcgfCBudWxsO1xuXG5cXHRAQ29sdW1uKClcblxcdHB1YmxpYyBkaXNwbGF5TmFtZSE6IHN0cmluZztcblxuXFx0LyoqIEFwcC1vd25lZCByb2xlcy4gVGhlIFxcYGFkbWluXFxgIHJvbGUgZ3JhbnRzIENBU0wgXFxgbWFuYWdlXFxgL1xcYGFsbFxcYCAod2lsZGNhcmQpLiAqL1xuXFx0QENvbHVtbih7IHR5cGU6IFwic2ltcGxlLWpzb25cIiwgZGVmYXVsdDogXCJbXVwiIH0pXG5cXHRwdWJsaWMgcm9sZXMhOiBzdHJpbmdbXTtcbn1cbmA7XG5cbmNvbnN0IFVTRVJfUkVQT1NJVE9SWV9UUyA9IGBpbXBvcnQgeyBpbmplY3RhYmxlIH0gZnJvbSBcIkBkZWNvaGVyZS9jcnVjaWJsZS9kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBpbmplY3RVbml0T2ZXb3JrIH0gZnJvbSBcIkBkZWNvaGVyZS9jb2RleFwiO1xuaW1wb3J0IHsgVHlwZU9ybVJlcG9zaXRvcnksIFR5cGVPcm1Vbml0T2ZXb3JrIH0gZnJvbSBcIkBkZWNvaGVyZS9jb2RleC10eXBlb3JtXCI7XG5pbXBvcnQgeyBVc2VyRW50aXR5IH0gZnJvbSBcIi4uL2VudGl0aWVzL3VzZXIuZW50aXR5LmpzXCI7XG5cbkBpbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBVc2VyRW50aXR5UmVwb3NpdG9yeSBleHRlbmRzIFR5cGVPcm1SZXBvc2l0b3J5PFVzZXJFbnRpdHk+IHtcblxcdHB1YmxpYyBjb25zdHJ1Y3RvcihAaW5qZWN0VW5pdE9mV29yaygpIHVuaXRPZldvcms6IFR5cGVPcm1Vbml0T2ZXb3JrKSB7XG5cXHRcXHRzdXBlcih1bml0T2ZXb3JrLCBVc2VyRW50aXR5KTtcblxcdH1cblxuXFx0cHVibGljIGZpbmRCeVN1YihzdWI6IHN0cmluZyk6IFByb21pc2U8VXNlckVudGl0eSB8IG51bGw+IHtcblxcdFxcdHJldHVybiB0aGlzLmZpcnN0T3JEZWZhdWx0KHsgd2hlcmU6IHsgc3ViIH0gfSk7XG5cXHR9XG59XG5gO1xuXG5jb25zdCBVU0VSX1NFUlZJQ0VfVFMgPSBgaW1wb3J0IHsgaW5qZWN0YWJsZSB9IGZyb20gXCJAZGVjb2hlcmUvY3J1Y2libGUvZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHR5cGUgeyBQcmluY2lwYWwgfSBmcm9tIFwiQGRlY29oZXJlL2NvcnRleFwiO1xuaW1wb3J0IHsgVXNlckVudGl0eSB9IGZyb20gXCIuLi9lbnRpdGllcy91c2VyLmVudGl0eS5qc1wiO1xuaW1wb3J0IHsgVXNlckVudGl0eVJlcG9zaXRvcnkgfSBmcm9tIFwiLi4vcmVwb3NpdG9yaWVzL3VzZXIucmVwb3NpdG9yeS5qc1wiO1xuXG5mdW5jdGlvbiBjbGFpbVN0cmluZyhwcmluY2lwYWw6IFByaW5jaXBhbCB8IHVuZGVmaW5lZCwga2V5OiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuXFx0Y29uc3QgdmFsdWUgPSBwcmluY2lwYWw/LltrZXldO1xuXFx0cmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiAmJiB2YWx1ZS5sZW5ndGggPiAwID8gdmFsdWUgOiB1bmRlZmluZWQ7XG59XG5cbkBpbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBVc2VyU2VydmljZSB7XG5cXHRwdWJsaWMgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSB1c2VyczogVXNlckVudGl0eVJlcG9zaXRvcnkpIHt9XG5cblxcdC8qKlxuXFx0ICogVXBzZXJ0IGEgbG9jYWwgcHJvZmlsZSBrZXllZCBieSBKV1QgXFxgc3ViXFxgLlxuXFx0ICogUHJvZmlsZSBmaWVsZHMgZnJvbSB0aGUgdG9rZW4gZmlsbCBnYXBzOyBzZWVkZWQgcm93cyBrZWVwIGRpc3BsYXlOYW1lL2VtYWlsL3JvbGVzLlxuXFx0ICovXG5cXHRwdWJsaWMgYXN5bmMgZW5zdXJlRnJvbVByaW5jaXBhbChwcmluY2lwYWw6IFByaW5jaXBhbCB8IHVuZGVmaW5lZCk6IFByb21pc2U8VXNlckVudGl0eT4ge1xuXFx0XFx0Y29uc3Qgc3ViID0gcHJpbmNpcGFsPy5zdWI7XG5cXHRcXHRpZiAoIXN1Yikge1xuXFx0XFx0XFx0dGhyb3cgbmV3IEVycm9yKFwiQXV0aGVudGljYXRlZCByZXF1ZXN0IGlzIG1pc3NpbmcgcHJpbmNpcGFsLnN1YlwiKTtcblxcdFxcdH1cblxuXFx0XFx0Y29uc3QgZW1haWwgPVxuXFx0XFx0XFx0Y2xhaW1TdHJpbmcocHJpbmNpcGFsLCBcImVtYWlsXCIpID8/IGNsYWltU3RyaW5nKHByaW5jaXBhbCwgXCJwcmVmZXJyZWRfdXNlcm5hbWVcIik7XG5cXHRcXHRjb25zdCBkaXNwbGF5RnJvbVRva2VuID1cblxcdFxcdFxcdGNsYWltU3RyaW5nKHByaW5jaXBhbCwgXCJuYW1lXCIpID8/XG5cXHRcXHRcXHRjbGFpbVN0cmluZyhwcmluY2lwYWwsIFwibmlja25hbWVcIikgPz9cblxcdFxcdFxcdGVtYWlsO1xuXG5cXHRcXHRjb25zdCBleGlzdGluZyA9IGF3YWl0IHRoaXMudXNlcnMuZmluZEJ5U3ViKHN1Yik7XG5cXHRcXHRpZiAoZXhpc3RpbmcpIHtcblxcdFxcdFxcdGxldCBkaXJ0eSA9IGZhbHNlO1xuXFx0XFx0XFx0aWYgKCFleGlzdGluZy5lbWFpbCAmJiBlbWFpbCkge1xuXFx0XFx0XFx0XFx0ZXhpc3RpbmcuZW1haWwgPSBlbWFpbDtcblxcdFxcdFxcdFxcdGRpcnR5ID0gdHJ1ZTtcblxcdFxcdFxcdH1cblxcdFxcdFxcdGlmIChleGlzdGluZy5kaXNwbGF5TmFtZSA9PT0gZXhpc3Rpbmcuc3ViICYmIGRpc3BsYXlGcm9tVG9rZW4pIHtcblxcdFxcdFxcdFxcdGV4aXN0aW5nLmRpc3BsYXlOYW1lID0gZGlzcGxheUZyb21Ub2tlbjtcblxcdFxcdFxcdFxcdGRpcnR5ID0gdHJ1ZTtcblxcdFxcdFxcdH1cblxcdFxcdFxcdHJldHVybiBkaXJ0eSA/IHRoaXMudXNlcnMuc2F2ZShleGlzdGluZykgOiBleGlzdGluZztcblxcdFxcdH1cblxuXFx0XFx0Y29uc3QgY3JlYXRlZCA9IG5ldyBVc2VyRW50aXR5KCk7XG5cXHRcXHRjcmVhdGVkLnN1YiA9IHN1YjtcblxcdFxcdGNyZWF0ZWQuZW1haWwgPSBlbWFpbCA/PyBudWxsO1xuXFx0XFx0Y3JlYXRlZC5kaXNwbGF5TmFtZSA9IGRpc3BsYXlGcm9tVG9rZW4gPz8gc3ViO1xuXFx0XFx0Y3JlYXRlZC5yb2xlcyA9IEFycmF5LmlzQXJyYXkocHJpbmNpcGFsLnJvbGVzKVxuXFx0XFx0XFx0PyBwcmluY2lwYWwucm9sZXMuZmlsdGVyKChyKTogciBpcyBzdHJpbmcgPT4gdHlwZW9mIHIgPT09IFwic3RyaW5nXCIpXG5cXHRcXHRcXHQ6IFtdO1xuXFx0XFx0cmV0dXJuIHRoaXMudXNlcnMuc2F2ZShjcmVhdGVkKTtcblxcdH1cbn1cbmA7XG5cbmNvbnN0IEFCSUxJVFlfRkFDVE9SWV9UUyA9IGBpbXBvcnQgeyBBYmlsaXR5QnVpbGRlciwgY3JlYXRlTW9uZ29BYmlsaXR5IH0gZnJvbSBcIkBjYXNsL2FiaWxpdHlcIjtcbmltcG9ydCB0eXBlIHsgUHJpbmNpcGFsIH0gZnJvbSBcIkBkZWNvaGVyZS9jb3J0ZXhcIjtcblxuLyoqIFJvb3Qgcm9sZSDigJQgZXhwYW5kcyB0byBDQVNMIFxcYG1hbmFnZVxcYC9cXGBhbGxcXGAgKGNvdmVycyBldmVyeSBmdXR1cmUgYWJpbGl0eSkuICovXG5leHBvcnQgY29uc3QgQURNSU5fUk9MRSA9IFwiYWRtaW5cIjtcblxuLyoqXG4gKiBSb2xlcyBhcmUgY29sbGVjdGlvbnMgb2YgYWJpbGl0aWVzLiBBZG1pbiBpcyBhIHdpbGRjYXJkLCBub3QgYW4gZW51bWVyYXRlZCBsaXN0LlxuICogTm9uLWFkbWluIHByaW5jaXBhbHMga2VlcCB0aGUgZGVmYXVsdCBBdXRoMCBzY29wZSDihpIgYWJpbGl0eSBtYXBwaW5nLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQWJpbGl0eUZhY3RvcnkocHJpbmNpcGFsOiBQcmluY2lwYWwpIHtcblxcdGNvbnN0IHsgY2FuLCBidWlsZCB9ID0gbmV3IEFiaWxpdHlCdWlsZGVyKGNyZWF0ZU1vbmdvQWJpbGl0eSk7XG5cXHRpZiAocHJpbmNpcGFsLnJvbGVzPy5pbmNsdWRlcyhBRE1JTl9ST0xFKSkge1xuXFx0XFx0Y2FuKFwibWFuYWdlXCIsIFwiYWxsXCIpO1xuXFx0XFx0cmV0dXJuIGJ1aWxkKCk7XG5cXHR9XG5cXHRmb3IgKGNvbnN0IHNjb3BlIG9mIHByaW5jaXBhbC5zY29wZXMgPz8gW10pIHtcblxcdFxcdGNvbnN0IFthY3Rpb24sIHN1YmplY3RdID0gc2NvcGUuc3BsaXQoXCI6XCIpO1xuXFx0XFx0aWYgKGFjdGlvbiAmJiBzdWJqZWN0KSBjYW4oYWN0aW9uLCBzdWJqZWN0KTtcblxcdH1cblxcdHJldHVybiBidWlsZCgpO1xufVxuXG4vKipcbiAqIE1hcCBKV1QgcGF5bG9hZCDihpIgUHJpbmNpcGFsLiBCb290c3RyYXBzIHRoZSBzZWVkZWQgQXV0aDAgYWRtaW4gXFxgc3ViXFxgIHdpdGhcbiAqIHRoZSBhZG1pbiByb2xlIHNvIGF1dGhvcml6YXRpb24gd29ya3MgYmVmb3JlL3dpdGhvdXQgcm9sZXMgaW4gdGhlIGFjY2VzcyB0b2tlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1hcFByaW5jaXBhbChwYXlsb2FkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IFByaW5jaXBhbCB7XG5cXHRjb25zdCBzdWIgPSB0eXBlb2YgcGF5bG9hZC5zdWIgPT09IFwic3RyaW5nXCIgPyBwYXlsb2FkLnN1YiA6IFwiXCI7XG5cXHRjb25zdCBzY29wZXMgPSBBcnJheS5pc0FycmF5KHBheWxvYWQuc2NvcGVzKVxuXFx0XFx0PyAocGF5bG9hZC5zY29wZXMgYXMgc3RyaW5nW10pXG5cXHRcXHQ6IHR5cGVvZiBwYXlsb2FkLnNjb3BlID09PSBcInN0cmluZ1wiXG5cXHRcXHRcXHQ/IHBheWxvYWQuc2NvcGUuc3BsaXQoXCIgXCIpXG5cXHRcXHRcXHQ6IHVuZGVmaW5lZDtcblxcdGNvbnN0IGZyb21Ub2tlbiA9IEFycmF5LmlzQXJyYXkocGF5bG9hZC5yb2xlcylcblxcdFxcdD8gKHBheWxvYWQucm9sZXMgYXMgdW5rbm93bltdKS5maWx0ZXIoKHIpOiByIGlzIHN0cmluZyA9PiB0eXBlb2YgciA9PT0gXCJzdHJpbmdcIilcblxcdFxcdDogW107XG5cXHRjb25zdCByb2xlcyA9XG5cXHRcXHRzdWIgJiYgc3ViID09PSBwcm9jZXNzLmVudi5BVVRIMF9BRE1JTl9VU0VSX1NVQlxuXFx0XFx0XFx0PyBbLi4ubmV3IFNldChbQURNSU5fUk9MRSwgLi4uZnJvbVRva2VuXSldXG5cXHRcXHRcXHQ6IGZyb21Ub2tlbi5sZW5ndGggPiAwXG5cXHRcXHRcXHRcXHQ/IGZyb21Ub2tlblxuXFx0XFx0XFx0XFx0OiB1bmRlZmluZWQ7XG5cXHRyZXR1cm4geyAuLi5wYXlsb2FkLCBzdWIsIHJvbGVzLCBzY29wZXMgfTtcbn1cbmA7XG5cbmFzeW5jIGZ1bmN0aW9uIGdldE9wdGlvbnMoXG5cdHdvcmtzcGFjZTogV29ya3NwYWNlU2NhZmZvbGQsXG5cdGNsaU9wdGlvbnM6IFBhcnRpYWw8QXV0aE9wdGlvbnM+LFxuKTogUHJvbWlzZTxQYXJ0aWFsPEF1dGhPcHRpb25zPj4ge1xuXHRpZiAoY2xpT3B0aW9ucy5hdXRoUHJvdmlkZXIgPT09IFwiYXV0aDBcIiAmJiAhY2xpT3B0aW9ucy5pc3N1ZXJCYXNlVXJsKSB7XG5cdFx0cmV0dXJuIGdldEF1dGgwT3B0aW9ucyh3b3Jrc3BhY2UsIGNsaU9wdGlvbnMpO1xuXHR9XG5cdGlmIChjbGlPcHRpb25zLmF1dGhQcm92aWRlciAhPSBudWxsKSByZXR1cm4ge307XG5cblx0Y29uc3QgY2hvaWNlcyA9IFt7IGxhYmVsOiBcIm5vbmVcIiBhcyBjb25zdCB9LCB7IGxhYmVsOiBcImF1dGgwXCIgYXMgY29uc3QgfV07XG5cdGNvbnN0IHNlbGVjdGVkID0gYXdhaXQgcGljayhcIlxcbiAgQXV0aCBwcm92aWRlcjogXCIsIGNob2ljZXMsIChjKSA9PiBjLmxhYmVsKTtcblx0Y29uc3QgcHJvdmlkZXIgPSBzZWxlY3RlZD8ubGFiZWwgPz8gXCJub25lXCI7XG5cblx0aWYgKHByb3ZpZGVyICE9PSBcImF1dGgwXCIpIHJldHVybiB7IGF1dGhQcm92aWRlcjogXCJub25lXCIgfTtcblxuXHRyZXR1cm4gZ2V0QXV0aDBPcHRpb25zKHdvcmtzcGFjZSwgY2xpT3B0aW9ucyk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldEF1dGgwT3B0aW9ucyhcblx0d29ya3NwYWNlOiBXb3Jrc3BhY2VTY2FmZm9sZCxcblx0Y2xpT3B0aW9uczogUGFydGlhbDxBdXRoT3B0aW9ucz4sXG4pOiBQcm9taXNlPFBhcnRpYWw8QXV0aE9wdGlvbnM+PiB7XG5cdGlmICghYXV0aDBDbGkuaXNJbnN0YWxsZWQoKSkge1xuXHRcdGNvbnNvbGUuZXJyb3IoXG5cdFx0XHRcIlxcbiAgVGhlIEF1dGgwIENMSSBpcyByZXF1aXJlZCBmb3IgYXV0b21hdGVkIHNldHVwLlxcblwiICtcblx0XHRcdFx0XCIgIEluc3RhbGw6IGJyZXcgaW5zdGFsbCBhdXRoMC9hdXRoMC1jbGkvYXV0aDBcXG5cIiArXG5cdFx0XHRcdFwiICBPciB2aXNpdDogaHR0cHM6Ly9naXRodWIuY29tL2F1dGgwL2F1dGgwLWNsaVxcblwiLFxuXHRcdCk7XG5cdFx0cHJvY2Vzcy5leGl0KDEpO1xuXHR9XG5cblx0cHJvY2Vzcy5zdGRvdXQud3JpdGUoXCJcXG4gIENoZWNraW5nIEF1dGgwIGNyZWRlbnRpYWxzLi4uXCIpO1xuXHRsZXQgdGVuYW50cyA9IGF1dGgwQ2xpLmxpc3RUZW5hbnRzKCk7XG5cdGlmICh0ZW5hbnRzLmxlbmd0aCA9PT0gMCkge1xuXHRcdHByb2Nlc3Muc3Rkb3V0LndyaXRlKFwiIG5vdCBsb2dnZWQgaW4uXFxuXCIpO1xuXHRcdGNvbnNvbGUubG9nKFwiICBMb2dnaW5nIGluIHRvIEF1dGgwICh5b3VyIGJyb3dzZXIgd2lsbCBvcGVuKS4uLlwiKTtcblx0XHRpZiAoIWF1dGgwQ2xpLmxvZ2luKCkpIHtcblx0XHRcdGNvbnNvbGUuZXJyb3IoXCJcXG4gIEF1dGgwIGxvZ2luIGZhaWxlZC5cIik7XG5cdFx0XHRwcm9jZXNzLmV4aXQoMSk7XG5cdFx0fVxuXHRcdHRlbmFudHMgPSBhdXRoMENsaS5saXN0VGVuYW50cygpO1xuXHR9XG5cblx0dHJ5IHtcblx0XHRhdXRoMENsaS5saXN0QXBpcygpO1xuXHRcdHByb2Nlc3Muc3Rkb3V0LndyaXRlKFwiIG9rLlxcblwiKTtcblx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0aWYgKGVyciBpbnN0YW5jZW9mIGF1dGgwQ2xpLkF1dGgwQXV0aEVycm9yKSB7XG5cdFx0XHRwcm9jZXNzLnN0ZG91dC53cml0ZShcIiB0b2tlbiBleHBpcmVkLlxcblwiKTtcblx0XHRcdGNvbnNvbGUubG9nKFwiICBSZS1hdXRoZW50aWNhdGluZyAoeW91ciBicm93c2VyIHdpbGwgb3BlbikuLi5cIik7XG5cdFx0XHRpZiAoIWF1dGgwQ2xpLmxvZ2luKCkpIHtcblx0XHRcdFx0Y29uc29sZS5lcnJvcihcIlxcbiAgQXV0aDAgbG9naW4gZmFpbGVkLlwiKTtcblx0XHRcdFx0cHJvY2Vzcy5leGl0KDEpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdGNvbnN0IGFjdGl2ZSA9IHRlbmFudHMuZmluZCgodCkgPT4gdC5hY3RpdmUpID8/IHRlbmFudHNbMF07XG5cdGNvbnN0IGlzc3VlckJhc2VVcmwgPSBgaHR0cHM6Ly8ke2FjdGl2ZS5uYW1lfWA7XG5cdGNvbnNvbGUubG9nKGBcXG4gIOKckyBBdXRoMCB0ZW5hbnQ6ICR7aXNzdWVyQmFzZVVybH1gKTtcblxuXHRwcm9jZXNzLnN0ZG91dC53cml0ZShcIlxcbiAgRmV0Y2hpbmcgQXV0aDAgQVBJcy4uLlwiKTtcblx0Y29uc3QgdXNlckFwaXMgPSBhdXRoMENsaS5saXN0QXBpcygpLmZpbHRlcigoYSkgPT4gIWEubmFtZS5pbmNsdWRlcyhcIk1hbmFnZW1lbnQgQVBJXCIpKTtcblx0cHJvY2Vzcy5zdGRvdXQud3JpdGUoYCBmb3VuZCAke3VzZXJBcGlzLmxlbmd0aH0uXFxuYCk7XG5cblx0dHlwZSBBcGlDaG9pY2UgPSB7IGxhYmVsOiBzdHJpbmc7IGV4aXN0aW5nOiBzdHJpbmcgfCBudWxsIH07XG5cdGNvbnN0IHByb2plY3ROYW1lID0gd29ya3NwYWNlLm5hbWU7XG5cdGNvbnN0IGFwaUNob2ljZXM6IEFwaUNob2ljZVtdID0gW1xuXHRcdHsgbGFiZWw6IGA8bmV3PiBodHRwczovL2FwaS4ke3Byb2plY3ROYW1lfWAsIGV4aXN0aW5nOiBudWxsIH0sXG5cdFx0Li4udXNlckFwaXMubWFwKChhKSA9PiAoeyBsYWJlbDogYCR7YS5uYW1lfSDigJQgJHthLmlkZW50aWZpZXJ9YCwgZXhpc3Rpbmc6IGEuaWRlbnRpZmllciB9KSksXG5cdF07XG5cblx0Y29uc3QgYXBpU2VsZWN0ZWQgPSBhd2FpdCBwaWNrKFwiXFxuICBTZWxlY3QgQXV0aDAgQVBJOiBcIiwgYXBpQ2hvaWNlcywgKGMpID0+IGMubGFiZWwpO1xuXG5cdGxldCBhdWRpZW5jZTogc3RyaW5nO1xuXHRpZiAoIWFwaVNlbGVjdGVkIHx8IGFwaVNlbGVjdGVkLmV4aXN0aW5nID09PSBudWxsKSB7XG5cdFx0Y29uc3QgZGVmYXVsdElkID0gYGh0dHBzOi8vYXBpLiR7cHJvamVjdE5hbWV9YDtcblx0XHRhdWRpZW5jZSA9IGF3YWl0IGFzayhgICBBUEkgSWRlbnRpZmllciBbJHtkZWZhdWx0SWR9XTogYCwgZGVmYXVsdElkKTtcblx0XHRjb25zb2xlLmxvZyhcIlxcbiAgQ3JlYXRpbmcgQXV0aDAgQVBJLi4uXCIpO1xuXHRcdGF1ZGllbmNlID0gYXV0aDBDbGkuY3JlYXRlQXBpKGAke3Byb2plY3ROYW1lfSBBUElgLCBhdWRpZW5jZSkuaWRlbnRpZmllcjtcblx0XHRjb25zb2xlLmxvZyhgICBcXHUyNzEzIEFQSSBjcmVhdGVkOiAke2F1ZGllbmNlfWApO1xuXHR9IGVsc2Uge1xuXHRcdGF1ZGllbmNlID0gYXBpU2VsZWN0ZWQuZXhpc3Rpbmc7XG5cdFx0Y29uc29sZS5sb2coYCAgXFx1MjcxMyBTZWxlY3RlZDogJHthdWRpZW5jZX1gKTtcblx0XHR0cnkge1xuXHRcdFx0YXV0aDBDbGkudXBkYXRlQXBpU2NvcGVzKGF1ZGllbmNlKTtcblx0XHRcdGNvbnNvbGUubG9nKGAgIFxcdTI3MTMgQVBJIHNjb3BlcyBlbnN1cmVkICgke2F1dGgwQ2xpLkhFTExPX0FQSV9TQ09QRVMuam9pbihcIiwgXCIpfSlgKTtcblx0XHR9IGNhdGNoIHtcblx0XHRcdGNvbnNvbGUuZXJyb3IoXG5cdFx0XHRcdFwiICDinJcgRmFpbGVkIHRvIHVwZGF0ZSBBUEkgc2NvcGVzIOKAlCBhZGQgSGVsbG8gc2NvcGVzIGluIHRoZSBBdXRoMCBkYXNoYm9hcmQuXCIsXG5cdFx0XHQpO1xuXHRcdH1cblx0fVxuXG5cdGNvbnN0IHdpdGhMb2NhbFVzZXJzID0gY2xpT3B0aW9ucy5kYXRhYmFzZVByb3ZpZGVyID09PSBcInBvc3RncmVzL3R5cGVvcm1cIjtcblx0bGV0IGFkbWluVXNlcm5hbWU6IHN0cmluZyB8IHVuZGVmaW5lZDtcblx0bGV0IGFkbWluUGFzc3dvcmQ6IHN0cmluZyB8IHVuZGVmaW5lZDtcblx0aWYgKHdpdGhMb2NhbFVzZXJzKSB7XG5cdFx0YWRtaW5Vc2VybmFtZSA9XG5cdFx0XHRjbGlPcHRpb25zLmFkbWluVXNlcm5hbWUgPz8gKGF3YWl0IGFzayhcIlxcbiAgQWRtaW4gdXNlcm5hbWUgW2FkbWluXTogXCIsIFwiYWRtaW5cIikpO1xuXHRcdGFkbWluUGFzc3dvcmQgPSBjbGlPcHRpb25zLmFkbWluUGFzc3dvcmQ7XG5cdFx0aWYgKGFkbWluUGFzc3dvcmQgPT0gbnVsbCkge1xuXHRcdFx0YWRtaW5QYXNzd29yZCA9IGF3YWl0IGFzayhcIiAgQWRtaW4gcGFzc3dvcmQgKGxlYXZlIGJsYW5rIHRvIGdlbmVyYXRlKTogXCIpO1xuXHRcdFx0aWYgKCFhZG1pblBhc3N3b3JkKSB7XG5cdFx0XHRcdGFkbWluUGFzc3dvcmQgPSBhdXRoMENsaS5nZW5lcmF0ZUFkbWluUGFzc3dvcmQoKTtcblx0XHRcdFx0Y29uc29sZS5sb2coYCAg4pyTIEdlbmVyYXRlZCBhZG1pbiBwYXNzd29yZCAod3JpdHRlbiB0byAuZW52KTogJHthZG1pblBhc3N3b3JkfWApO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHJldHVybiB7XG5cdFx0YXV0aFByb3ZpZGVyOiBcImF1dGgwXCIsXG5cdFx0aXNzdWVyQmFzZVVybCxcblx0XHRhdWRpZW5jZSxcblx0XHQuLi4od2l0aExvY2FsVXNlcnMgPyB7IGFkbWluVXNlcm5hbWUsIGFkbWluUGFzc3dvcmQgfSA6IHt9KSxcblx0fTtcbn1cblxuZnVuY3Rpb24gYWRtaW5FbWFpbCh3b3Jrc3BhY2VOYW1lOiBzdHJpbmcsIHVzZXJuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuXHRpZiAodXNlcm5hbWUuaW5jbHVkZXMoXCJAXCIpKSByZXR1cm4gdXNlcm5hbWU7XG5cdGNvbnN0IHNsdWcgPSB3b3Jrc3BhY2VOYW1lLnRvTG93ZXJDYXNlKCkucmVwbGFjZSgvW15hLXowLTktXS9nLCBcIi1cIik7XG5cdHJldHVybiBgJHt1c2VybmFtZX1AJHtzbHVnfS5leGFtcGxlLmNvbWA7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUF1dGgwQWRtaW5Vc2VyKFxuXHR3b3Jrc3BhY2U6IFdvcmtzcGFjZVNjYWZmb2xkLFxuXHRvcHRpb25zOiBBdXRoT3B0aW9ucyxcblx0YXV0aENvbmZpZzogQXV0aENvbmZpZ01vZGVsLFxuKTogdm9pZCB7XG5cdGNvbnN0IHVzZXJuYW1lID0gb3B0aW9ucy5hZG1pblVzZXJuYW1lID8/IFwiYWRtaW5cIjtcblx0Y29uc3QgcGFzc3dvcmQgPSBvcHRpb25zLmFkbWluUGFzc3dvcmQ7XG5cdGlmICghcGFzc3dvcmQpIHJldHVybjtcblxuXHRjb25zdCBlbWFpbCA9IGFkbWluRW1haWwod29ya3NwYWNlLm5hbWUsIHVzZXJuYW1lKTtcblx0dHJ5IHtcblx0XHRjb25zdCBhZG1pbiA9IGF1dGgwQ2xpLmNyZWF0ZUFkbWluRGF0YWJhc2VVc2VyKHsgZW1haWwsIHBhc3N3b3JkLCB1c2VybmFtZSB9KTtcblx0XHRhdXRoQ29uZmlnLnNldEFkbWluVXNlcih7XG5cdFx0XHRzdWI6IGFkbWluLnVzZXJfaWQsXG5cdFx0XHRlbWFpbDogYWRtaW4uZW1haWwsXG5cdFx0XHRwYXNzd29yZDogYWRtaW4ucGFzc3dvcmQsXG5cdFx0XHR1c2VybmFtZTogYWRtaW4udXNlcm5hbWUsXG5cdFx0fSk7XG5cdFx0d29ya3NwYWNlXG5cdFx0XHQuZ2V0TW9kZWw8RW52RmlsZT4oV0VMTF9LTk9XTl9GSUxFUy5FTlZfRklMRSlcblx0XHRcdD8uYWRkRW50cnkoXCJBVVRIMF9BRE1JTl9VU0VSX1NVQlwiLCBhZG1pbi51c2VyX2lkKVxuXHRcdFx0LmFkZEVudHJ5KFwiQVVUSDBfQURNSU5fVVNFUl9FTUFJTFwiLCBhZG1pbi5lbWFpbClcblx0XHRcdC5hZGRFbnRyeShcIkFVVEgwX0FETUlOX1VTRVJfUEFTU1dPUkRcIiwgYWRtaW4ucGFzc3dvcmQpXG5cdFx0XHQuYWRkRW50cnkoXCJBVVRIMF9BRE1JTl9VU0VSTkFNRVwiLCBhZG1pbi51c2VybmFtZSk7XG5cdFx0Y29uc29sZS5sb2coYCAg4pyTIEF1dGgwIGFkbWluIHVzZXIgcmVhZHk6ICR7YWRtaW4uZW1haWx9IChyb2xlOiAke0FETUlOX1JPTEV9KWApO1xuXHRcdGNvbnNvbGUubG9nKGAgICAgTG9naW4gd2l0aCBFTUFJTCAobm90IHVzZXJuYW1lKTogJHthZG1pbi5lbWFpbH1gKTtcblx0XHRjb25zb2xlLmxvZyhgICAgIFBhc3N3b3JkOiBzZWUgQVVUSDBfQURNSU5fVVNFUl9QQVNTV09SRCBpbiAuZW52YCk7XG5cdH0gY2F0Y2ggKGVycikge1xuXHRcdGNvbnNvbGUuZXJyb3IoXG5cdFx0XHRgICDinJcgRmFpbGVkIHRvIGVuc3VyZSBBdXRoMCBhZG1pbiB1c2VyICgke2VtYWlsfSk6ICR7ZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IGVycn1gLFxuXHRcdCk7XG5cdH1cbn1cblxuZnVuY3Rpb24gc2NhZmZvbGRMb2NhbFVzZXJQcm9maWxlKHdvcmtzcGFjZTogV29ya3NwYWNlU2NhZmZvbGQpOiB2b2lkIHtcblx0d29ya3NwYWNlXG5cdFx0LmdldE1vZGVsPFBhY2thZ2VKc29uPihXRUxMX0tOT1dOX0ZJTEVTLlBBQ0tBR0VfSlNPTilcblx0XHQ/LmFkZERlcGVuZGVuY3koXCJAY2FzbC9hYmlsaXR5XCIsIFwiXjYuOC4xXCIpO1xuXHR3b3Jrc3BhY2Vcblx0XHQuZ2V0TW9kZWw8QXBpUGFja2FnZUpzb24+KFdFTExfS05PV05fRklMRVMuQVBJX1BBQ0tBR0VfSlNPTilcblx0XHQ/LmFkZERlcGVuZGVuY3koXCJAY2FzbC9hYmlsaXR5XCIsIFwiXjYuOC4xXCIpO1xuXG5cdGNvbnN0IG1haW4gPSB3b3Jrc3BhY2UuZ2V0TW9kZWw8TWFpblNvdXJjZUZpbGU+KFdFTExfS05PV05fRklMRVMuTUFJTl9UUyk7XG5cdG1haW5cblx0XHQ/LmFkZEVudGl0eSh7IGNsYXNzTmFtZTogXCJVc2VyRW50aXR5XCIsIGltcG9ydFBhdGg6IFwiLi9lbnRpdGllcy91c2VyLmVudGl0eS5qc1wiIH0pXG5cdFx0LmFkZFJlcG9zaXRvcnkoe1xuXHRcdFx0Y2xhc3NOYW1lOiBcIlVzZXJFbnRpdHlSZXBvc2l0b3J5XCIsXG5cdFx0XHRpbXBvcnRQYXRoOiBcIi4vcmVwb3NpdG9yaWVzL3VzZXIucmVwb3NpdG9yeS5qc1wiLFxuXHRcdH0pXG5cdFx0LmFkZFNlcnZpY2Uoe1xuXHRcdFx0Y2xhc3NOYW1lOiBcIlVzZXJTZXJ2aWNlXCIsXG5cdFx0XHRpbXBvcnRQYXRoOiBcIi4vc2VydmljZXMvdXNlci5zZXJ2aWNlLmpzXCIsXG5cdFx0XHRzY29wZTogXCJyZXF1ZXN0XCIsXG5cdFx0fSlcblx0XHQuYWRkSW1wb3J0KFwiY3JlYXRlQWJpbGl0eUZhY3RvcnlcIiwgXCIuL2F1dGgvYWJpbGl0eS5mYWN0b3J5LmpzXCIpXG5cdFx0LmFkZEltcG9ydChcIm1hcFByaW5jaXBhbFwiLCBcIi4vYXV0aC9hYmlsaXR5LmZhY3RvcnkuanNcIilcblx0XHQuc2V0VHlwZU9ybVNlZWQoXG5cdFx0XHRbXG5cdFx0XHRcdFwiY29uc3Qgc3ViID0gcHJvY2Vzcy5lbnYuQVVUSDBfQURNSU5fVVNFUl9TVUI7XCIsXG5cdFx0XHRcdFwiaWYgKCFzdWIpIHJldHVybjtcIixcblx0XHRcdFx0XCJjb25zdCByZXBvID0gZGF0YVNvdXJjZS5nZXRSZXBvc2l0b3J5KFVzZXJFbnRpdHkpO1wiLFxuXHRcdFx0XHRcImNvbnN0IGV4aXN0aW5nID0gYXdhaXQgcmVwby5maW5kT25lKHsgd2hlcmU6IHsgc3ViIH0gfSk7XCIsXG5cdFx0XHRcdFwiaWYgKGV4aXN0aW5nKSByZXR1cm47XCIsXG5cdFx0XHRcdFwiYXdhaXQgcmVwby5zYXZlKHJlcG8uY3JlYXRlKHtcIixcblx0XHRcdFx0XCIgIHN1YixcIixcblx0XHRcdFx0XCIgIGVtYWlsOiBwcm9jZXNzLmVudi5BVVRIMF9BRE1JTl9VU0VSX0VNQUlMID8/IG51bGwsXCIsXG5cdFx0XHRcdCcgIGRpc3BsYXlOYW1lOiBwcm9jZXNzLmVudi5BVVRIMF9BRE1JTl9VU0VSTkFNRSA/PyBcImFkbWluXCIsJyxcblx0XHRcdFx0JyAgcm9sZXM6IFtcImFkbWluXCJdLCcsXG5cdFx0XHRcdFwifSkpO1wiLFxuXHRcdFx0XS5qb2luKFwiIFwiKSxcblx0XHQpO1xuXG5cdHdvcmtzcGFjZS5nZXRQcm9qZWN0KFdFQkFQSV9QUk9KRUNUX0RJUik/LmFkZEZpbGUoe1xuXHRcdGZpbGVzOiAoKSA9PiBbXG5cdFx0XHR7IGZpbGVQYXRoOiBcInNyYy9lbnRpdGllcy91c2VyLmVudGl0eS50c1wiLCBjb250ZW50OiBVU0VSX0VOVElUWV9UUyB9LFxuXHRcdFx0eyBmaWxlUGF0aDogXCJzcmMvcmVwb3NpdG9yaWVzL3VzZXIucmVwb3NpdG9yeS50c1wiLCBjb250ZW50OiBVU0VSX1JFUE9TSVRPUllfVFMgfSxcblx0XHRcdHsgZmlsZVBhdGg6IFwic3JjL3NlcnZpY2VzL3VzZXIuc2VydmljZS50c1wiLCBjb250ZW50OiBVU0VSX1NFUlZJQ0VfVFMgfSxcblx0XHRcdHsgZmlsZVBhdGg6IFwic3JjL2F1dGgvYWJpbGl0eS5mYWN0b3J5LnRzXCIsIGNvbnRlbnQ6IEFCSUxJVFlfRkFDVE9SWV9UUyB9LFxuXHRcdF0sXG5cdH0pO1xuXG5cdGZvciAoY29uc3QgY29udHJvbGxlciBvZiB3b3Jrc3BhY2UuZ2V0TW9kZWxzKENvbnRyb2xsZXJTb3VyY2VGaWxlKSkge1xuXHRcdGNvbnRyb2xsZXJcblx0XHRcdC5hZGRJbXBvcnQoXCJVc2VyU2VydmljZVwiLCBcIi4uL3NlcnZpY2VzL3VzZXIuc2VydmljZS5qc1wiKVxuXHRcdFx0LmFkZENvbnN0cnVjdG9yUGFyYW0oXCJwcml2YXRlIHJlYWRvbmx5IHVzZXJzOiBVc2VyU2VydmljZVwiKTtcblx0XHRjb250cm9sbGVyLmdldE1ldGhvZChcImdldE9uZVwiKS5zZXRBc3luYyh0cnVlKS5zZXRCb2R5KFtcblx0XHRcdFwiY29uc3QgdXNlciA9IGF3YWl0IHRoaXMudXNlcnMuZW5zdXJlRnJvbVByaW5jaXBhbCh0aGlzLnByaW5jaXBhbFByb3ZpZGVyLmN1cnJlbnRQcmluY2lwYWwpO1wiLFxuXHRcdFx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub1RlbXBsYXRlQ3VybHlJblN0cmluZzogdGVtcGxhdGUgbGl0ZXJhbCBpbiBnZW5lcmF0ZWQgY29kZVxuXHRcdFx0XCJyZXR1cm4geyBpZCwgbWVzc2FnZTogYEhlbGxvICR7dXNlci5kaXNwbGF5TmFtZX0hYCwgdXNlcm5hbWU6IHVzZXIuZGlzcGxheU5hbWUgfTtcIixcblx0XHRdKTtcblx0fVxufVxuXG5mdW5jdGlvbiBzY2FmZm9sZCh3b3Jrc3BhY2U6IFdvcmtzcGFjZVNjYWZmb2xkLCBvcHRpb25zOiBBdXRoT3B0aW9ucyk6IHZvaWQge1xuXHRpZiAob3B0aW9ucy5hdXRoUHJvdmlkZXIgIT09IFwiYXV0aDBcIikgcmV0dXJuO1xuXG5cdGNvbnN0IHJlc291cmNlID0gXCJIZWxsb1wiO1xuXHRjb25zdCB3aXRoTG9jYWxVc2VycyA9IG9wdGlvbnMuZGF0YWJhc2VQcm92aWRlciA9PT0gXCJwb3N0Z3Jlcy90eXBlb3JtXCI7XG5cblx0Zm9yIChjb25zdCBjb250cm9sbGVyIG9mIHdvcmtzcGFjZS5nZXRNb2RlbHMoQ29udHJvbGxlclNvdXJjZUZpbGUpKSB7XG5cdFx0Y29udHJvbGxlclxuXHRcdFx0LmFkZERlY29yYXRvcihgQEF1dGhvcml6ZShcInJlYWRcIiwgXCIke3Jlc291cmNlfVwiKWApXG5cdFx0XHQuYWRkQ29ydGV4SW1wb3J0KFwiQWxsb3dBbm9ueW1vdXNcIilcblx0XHRcdC5hZGRDb3J0ZXhJbXBvcnQoXCJBdXRob3JpemVcIilcblx0XHRcdC5hZGRDb3J0ZXhJbXBvcnQoXCJJUHJpbmNpcGFsUHJvdmlkZXJUb2tlblwiKVxuXHRcdFx0LmFkZENvcnRleEltcG9ydChcIklQcmluY2lwYWxQcm92aWRlclwiLCB0cnVlKVxuXHRcdFx0LmFkZEltcG9ydChcImluamVjdFwiLCBcIkBkZWNvaGVyZS9jcnVjaWJsZS9kZWNvcmF0b3JzXCIpXG5cdFx0XHQuYWRkQ29uc3RydWN0b3JQYXJhbShcblx0XHRcdFx0YEBpbmplY3QoSVByaW5jaXBhbFByb3ZpZGVyVG9rZW4pIHByaXZhdGUgcmVhZG9ubHkgcHJpbmNpcGFsUHJvdmlkZXI6IElQcmluY2lwYWxQcm92aWRlcmAsXG5cdFx0XHQpO1xuXHRcdGNvbnRyb2xsZXIuZ2V0TWV0aG9kKFwiZ2V0QWxsXCIpLmFkZERlY29yYXRvcihcIkBBbGxvd0Fub255bW91cygpXCIpO1xuXHRcdGlmICghd2l0aExvY2FsVXNlcnMpIHtcblx0XHRcdGNvbnRyb2xsZXIuZ2V0TWV0aG9kKFwiZ2V0T25lXCIpLnNldEJvZHkoW1xuXHRcdFx0XHRcImNvbnN0IHByaW5jaXBhbCA9IHRoaXMucHJpbmNpcGFsUHJvdmlkZXIuY3VycmVudFByaW5jaXBhbDtcIixcblx0XHRcdFx0XCJjb25zdCB1c2VybmFtZSA9XCIsXG5cdFx0XHRcdCdcXHQodHlwZW9mIHByaW5jaXBhbD8ubmFtZSA9PT0gXCJzdHJpbmdcIiAmJiBwcmluY2lwYWwubmFtZSkgfHwnLFxuXHRcdFx0XHQnXFx0KHR5cGVvZiBwcmluY2lwYWw/Lm5pY2tuYW1lID09PSBcInN0cmluZ1wiICYmIHByaW5jaXBhbC5uaWNrbmFtZSkgfHwnLFxuXHRcdFx0XHQnXFx0KHR5cGVvZiBwcmluY2lwYWw/LmVtYWlsID09PSBcInN0cmluZ1wiICYmIHByaW5jaXBhbC5lbWFpbCkgfHwnLFxuXHRcdFx0XHQnXFx0KHR5cGVvZiBwcmluY2lwYWw/LnByZWZlcnJlZF91c2VybmFtZSA9PT0gXCJzdHJpbmdcIiAmJiBwcmluY2lwYWwucHJlZmVycmVkX3VzZXJuYW1lKSB8fCcsXG5cdFx0XHRcdFwiXFx0cHJpbmNpcGFsPy5zdWIgfHxcIixcblx0XHRcdFx0J1xcdFwidW5rbm93blwiOycsXG5cdFx0XHRcdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9UZW1wbGF0ZUN1cmx5SW5TdHJpbmc6IHRlbXBsYXRlIGxpdGVyYWwgaW4gZ2VuZXJhdGVkIGNvZGVcblx0XHRcdFx0XCJyZXR1cm4geyBpZCwgbWVzc2FnZTogYEhlbGxvICR7dXNlcm5hbWV9IWAsIHVzZXJuYW1lIH07XCIsXG5cdFx0XHRdKTtcblx0XHR9XG5cdFx0Y29udHJvbGxlci5nZXRNZXRob2QoXCJjcmVhdGVcIikuYWRkRGVjb3JhdG9yKGBAQXV0aG9yaXplKFwiY3JlYXRlXCIsIFwiJHtyZXNvdXJjZX1cIilgKTtcblx0XHRjb250cm9sbGVyLmdldE1ldGhvZChcInVwZGF0ZVwiKS5hZGREZWNvcmF0b3IoYEBBdXRob3JpemUoXCJ1cGRhdGVcIiwgXCIke3Jlc291cmNlfVwiKWApO1xuXHRcdGNvbnRyb2xsZXIuZ2V0TWV0aG9kKFwicmVtb3ZlXCIpLmFkZERlY29yYXRvcihgQEF1dGhvcml6ZShcImRlbGV0ZVwiLCBcIiR7cmVzb3VyY2V9XCIpYCk7XG5cdH1cblxuXHRjb25zdCBtYWluID0gd29ya3NwYWNlLmdldE1vZGVsPE1haW5Tb3VyY2VGaWxlPihXRUxMX0tOT1dOX0ZJTEVTLk1BSU5fVFMpO1xuXHRtYWluPy5hZGRTaWRlRWZmZWN0SW1wb3J0KFwiQGRlY29oZXJlL2NvcnRleC9hdXRoXCIpO1xuXG5cdGlmICh3aXRoTG9jYWxVc2Vycykge1xuXHRcdHNjYWZmb2xkTG9jYWxVc2VyUHJvZmlsZSh3b3Jrc3BhY2UpO1xuXHRcdG1haW4/LmFkZEJ1aWxkZXJDYWxsKFwiLndpdGhBdXRoKGNyZWF0ZUFiaWxpdHlGYWN0b3J5LCB7IHByaW5jaXBhbE1hcHBlcjogbWFwUHJpbmNpcGFsIH0pXCIpO1xuXHR9IGVsc2Uge1xuXHRcdG1haW4/LmFkZEJ1aWxkZXJDYWxsKFwiLndpdGhBdXRoKClcIik7XG5cdH1cblxuXHQvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vVGVtcGxhdGVDdXJseUluU3RyaW5nOiBpbnRlbnRpb25hbCBZQU1MIGVudi12YXIgcGxhY2Vob2xkZXJzXG5cdGNvbnN0IGlzc3VlclBsYWNlaG9sZGVyID0gXCIke0FVVEgwX0lTU1VFUl9CQVNFX1VSTH1cIjtcblx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub1RlbXBsYXRlQ3VybHlJblN0cmluZzogaW50ZW50aW9uYWwgWUFNTCBlbnYtdmFyIHBsYWNlaG9sZGVyc1xuXHRjb25zdCBhdWRQbGFjZWhvbGRlciA9IFwiJHtBVVRIMF9BVURJRU5DRX1cIjtcblxuXHRjb25zdCBjb25maWdTZWN0aW9uID0gYGF1dGg6XFxuICBkaXNjb3ZlcnlVcmw6ICR7aXNzdWVyUGxhY2Vob2xkZXJ9XFxuICBhdWRpZW5jZTogJHthdWRQbGFjZWhvbGRlcn1cXG5gO1xuXG5cdHdvcmtzcGFjZS5nZXRNb2RlbDxDb25maWdZYW1sPihXRUxMX0tOT1dOX0ZJTEVTLkNPTkZJR19ZQU1MKT8uYWRkU2VjdGlvbihjb25maWdTZWN0aW9uKTtcblxuXHR3b3Jrc3BhY2Vcblx0XHQuZ2V0TW9kZWw8RW52RmlsZT4oV0VMTF9LTk9XTl9GSUxFUy5FTlZfRklMRSlcblx0XHQ/LmFkZEVudHJ5KFwiQVVUSDBfSVNTVUVSX0JBU0VfVVJMXCIsIG9wdGlvbnMuaXNzdWVyQmFzZVVybCA/PyBcIlwiKVxuXHRcdC5hZGRFbnRyeShcIkFVVEgwX0FVRElFTkNFXCIsIG9wdGlvbnMuYXVkaWVuY2UgPz8gXCJcIik7XG5cblx0Y29uc3QgYXV0aENvbmZpZyA9IG5ldyBBdXRoQ29uZmlnTW9kZWwoe1xuXHRcdGlzc3VlckJhc2VVcmw6IG9wdGlvbnMuaXNzdWVyQmFzZVVybCA/PyBcIlwiLFxuXHRcdGF1ZGllbmNlOiBvcHRpb25zLmF1ZGllbmNlID8/IFwiXCIsXG5cdH0pO1xuXHR3b3Jrc3BhY2UuYWRkTW9kZWwoYXV0aENvbmZpZyk7XG5cblx0aWYgKHdpdGhMb2NhbFVzZXJzICYmIG9wdGlvbnMuYWRtaW5QYXNzd29yZCkge1xuXHRcdGNyZWF0ZUF1dGgwQWRtaW5Vc2VyKHdvcmtzcGFjZSwgb3B0aW9ucywgYXV0aENvbmZpZyk7XG5cdH1cbn1cblxuZXhwb3J0IGNvbnN0IEF1dGhGZWF0dXJlOiBGZWF0dXJlPEF1dGhPcHRpb25zPiA9IHsgZ2V0T3B0aW9ucywgc2NhZmZvbGQgfTtcbiJdLCJuYW1lcyI6WyJBdXRoRmVhdHVyZSIsIkFETUlOX1JPTEUiLCJVU0VSX0VOVElUWV9UUyIsIlVTRVJfUkVQT1NJVE9SWV9UUyIsIlVTRVJfU0VSVklDRV9UUyIsIkFCSUxJVFlfRkFDVE9SWV9UUyIsImdldE9wdGlvbnMiLCJ3b3Jrc3BhY2UiLCJjbGlPcHRpb25zIiwiYXV0aFByb3ZpZGVyIiwiaXNzdWVyQmFzZVVybCIsImdldEF1dGgwT3B0aW9ucyIsImNob2ljZXMiLCJsYWJlbCIsInNlbGVjdGVkIiwicGljayIsImMiLCJwcm92aWRlciIsImF1dGgwQ2xpIiwiaXNJbnN0YWxsZWQiLCJjb25zb2xlIiwiZXJyb3IiLCJwcm9jZXNzIiwiZXhpdCIsInN0ZG91dCIsIndyaXRlIiwidGVuYW50cyIsImxpc3RUZW5hbnRzIiwibGVuZ3RoIiwibG9nIiwibG9naW4iLCJsaXN0QXBpcyIsImVyciIsIkF1dGgwQXV0aEVycm9yIiwiYWN0aXZlIiwiZmluZCIsInQiLCJuYW1lIiwidXNlckFwaXMiLCJmaWx0ZXIiLCJhIiwiaW5jbHVkZXMiLCJwcm9qZWN0TmFtZSIsImFwaUNob2ljZXMiLCJleGlzdGluZyIsIm1hcCIsImlkZW50aWZpZXIiLCJhcGlTZWxlY3RlZCIsImF1ZGllbmNlIiwiZGVmYXVsdElkIiwiYXNrIiwiY3JlYXRlQXBpIiwidXBkYXRlQXBpU2NvcGVzIiwiSEVMTE9fQVBJX1NDT1BFUyIsImpvaW4iLCJ3aXRoTG9jYWxVc2VycyIsImRhdGFiYXNlUHJvdmlkZXIiLCJhZG1pblVzZXJuYW1lIiwiYWRtaW5QYXNzd29yZCIsImdlbmVyYXRlQWRtaW5QYXNzd29yZCIsImFkbWluRW1haWwiLCJ3b3Jrc3BhY2VOYW1lIiwidXNlcm5hbWUiLCJzbHVnIiwidG9Mb3dlckNhc2UiLCJyZXBsYWNlIiwiY3JlYXRlQXV0aDBBZG1pblVzZXIiLCJvcHRpb25zIiwiYXV0aENvbmZpZyIsInBhc3N3b3JkIiwiZW1haWwiLCJhZG1pbiIsImNyZWF0ZUFkbWluRGF0YWJhc2VVc2VyIiwic2V0QWRtaW5Vc2VyIiwic3ViIiwidXNlcl9pZCIsImdldE1vZGVsIiwiV0VMTF9LTk9XTl9GSUxFUyIsIkVOVl9GSUxFIiwiYWRkRW50cnkiLCJFcnJvciIsIm1lc3NhZ2UiLCJzY2FmZm9sZExvY2FsVXNlclByb2ZpbGUiLCJQQUNLQUdFX0pTT04iLCJhZGREZXBlbmRlbmN5IiwiQVBJX1BBQ0tBR0VfSlNPTiIsIm1haW4iLCJNQUlOX1RTIiwiYWRkRW50aXR5IiwiY2xhc3NOYW1lIiwiaW1wb3J0UGF0aCIsImFkZFJlcG9zaXRvcnkiLCJhZGRTZXJ2aWNlIiwic2NvcGUiLCJhZGRJbXBvcnQiLCJzZXRUeXBlT3JtU2VlZCIsImdldFByb2plY3QiLCJXRUJBUElfUFJPSkVDVF9ESVIiLCJhZGRGaWxlIiwiZmlsZXMiLCJmaWxlUGF0aCIsImNvbnRlbnQiLCJjb250cm9sbGVyIiwiZ2V0TW9kZWxzIiwiQ29udHJvbGxlclNvdXJjZUZpbGUiLCJhZGRDb25zdHJ1Y3RvclBhcmFtIiwiZ2V0TWV0aG9kIiwic2V0QXN5bmMiLCJzZXRCb2R5Iiwic2NhZmZvbGQiLCJyZXNvdXJjZSIsImFkZERlY29yYXRvciIsImFkZENvcnRleEltcG9ydCIsImFkZFNpZGVFZmZlY3RJbXBvcnQiLCJhZGRCdWlsZGVyQ2FsbCIsImlzc3VlclBsYWNlaG9sZGVyIiwiYXVkUGxhY2Vob2xkZXIiLCJjb25maWdTZWN0aW9uIiwiQ09ORklHX1lBTUwiLCJhZGRTZWN0aW9uIiwiQXV0aENvbmZpZ01vZGVsIiwiYWRkTW9kZWwiXSwibWFwcGluZ3MiOiI7Ozs7K0JBMGNhQTs7O2VBQUFBOzs7d0JBMWNhO3VCQUVPOzJCQUtFO2lDQUVIOzJDQUNLO2tFQUVYOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFXMUIsTUFBTUMsYUFBYTtBQUVuQixNQUFNQyxpQkFBaUIsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBcUJ4QixDQUFDO0FBRUQsTUFBTUMscUJBQXFCLENBQUM7Ozs7Ozs7Ozs7Ozs7OztBQWU1QixDQUFDO0FBRUQsTUFBTUMsa0JBQWtCLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUF1RHpCLENBQUM7QUFFRCxNQUFNQyxxQkFBcUIsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBNkM1QixDQUFDO0FBRUQsZUFBZUMsV0FDZEMsU0FBNEIsRUFDNUJDLFVBQWdDO0lBRWhDLElBQUlBLFdBQVdDLFlBQVksS0FBSyxXQUFXLENBQUNELFdBQVdFLGFBQWEsRUFBRTtRQUNyRSxPQUFPQyxnQkFBZ0JKLFdBQVdDO0lBQ25DO0lBQ0EsSUFBSUEsV0FBV0MsWUFBWSxJQUFJLE1BQU0sT0FBTyxDQUFDO0lBRTdDLE1BQU1HLFVBQVU7UUFBQztZQUFFQyxPQUFPO1FBQWdCO1FBQUc7WUFBRUEsT0FBTztRQUFpQjtLQUFFO0lBQ3pFLE1BQU1DLFdBQVcsTUFBTUMsSUFBQUEsWUFBSSxFQUFDLHVCQUF1QkgsU0FBUyxDQUFDSSxJQUFNQSxFQUFFSCxLQUFLO0lBQzFFLE1BQU1JLFdBQVdILFVBQVVELFNBQVM7SUFFcEMsSUFBSUksYUFBYSxTQUFTLE9BQU87UUFBRVIsY0FBYztJQUFPO0lBRXhELE9BQU9FLGdCQUFnQkosV0FBV0M7QUFDbkM7QUFFQSxlQUFlRyxnQkFDZEosU0FBNEIsRUFDNUJDLFVBQWdD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